diff --git a/bsp/gd32/README.md b/bsp/gd32/README.md index 8d7a969ed9..fb706c2723 100644 --- a/bsp/gd32/README.md +++ b/bsp/gd32/README.md @@ -5,6 +5,12 @@ GD32 系列 BSP 目前支持情况如下表所示: | **BSP 文件夹名称** | **开发板名称** | |:------------------------- |:-------------------------- | +| **F1 系列** | | +| [gd32105r-start](gd32105r-start) | 兆易创新 官方 GD32105r-START 开发板 | +| **F2 系列** | | +| [gd32205r-start](gd32205r-start) | 兆易创新 官方 GD32205r-START 开发板 | +| **F3 系列** | | +| [gd32305r-start](gd32305r-start) | 兆易创新 官方 GD32305r-START 开发板 | | **F4 系列** | | | [gd32407v-start](gd32407v-start) | 兆易创新 官方 GD32407V-START 开发板 | diff --git a/bsp/gd32/docs/GD32系列BSP制作教程.md b/bsp/gd32/docs/GD32系列BSP制作教程.md index 6a894cc54a..6f0a4427f7 100644 --- a/bsp/gd32/docs/GD32系列BSP制作教程.md +++ b/bsp/gd32/docs/GD32系列BSP制作教程.md @@ -1,37 +1,32 @@ # GD32 系列 BSP 制作教程 -## 1. BSP 框架介绍 +## 1. BSP 框架介绍 BSP 框架结构如下图所示: ![BSP 框架图](./figures/frame.png) -GD32的BSP架构主要分为三个部分:libraries、tools和具体的Boards,其中libraries包含了GD32的通用库,包括每个系列的HAL以及适配RT-Thread的drivers;tools是生成工程的Python脚本工具;另外就是Boards文件,当然这里的Boards有很多,我这里值列举了GD32407V-START。 - - - +GD32的BSP架构主要分为三个部分:libraries、tools和具体的Boards,其中libraries包含了GD32的通用库,包括每个系列的Firmware Library以及适配RT-Thread的drivers;tools是生成工程的Python脚本工具;另外就是Boards文件,当然这里的Boards有很多,我这里值列举了GD32407V-START。 ## 2. 知识准备 制作一个 BSP 的过程就是构建一个新系统的过程,因此想要制作出好用的 BSP,要对 RT-Thread 系统的构建过程有一定了解,需要的知识准备如下所示: - 掌握 GD32 系列 BSP 的使用方法 - + 了解 BSP 的使用方法,可以阅读 [BSP 说明文档](../README.md) 中使用教程表格内的文档。 - 了解 Scons 工程构建方法 - + RT-Thread 使用 Scons 作为系统的构建工具,因此了解 Scons 的常用命令对制作新 BSP 是基本要求。 - 了解设备驱动框架 - + 在 RT-Thread 系统中,应用程序通过设备驱动框架来操作硬件,因此了解设备驱动框架,对添加 BSP 驱动是很重要的。 - 了解 Kconfig 语法 - - RT-Thread 系统通过 menuconfig 的方式进行配置,而 menuconfig 中的选项是由 Kconfig 文件决定的,因此想要对 RT-Thread 系统进行配置,需要对 kconfig 语法有一定了解。 - + RT-Thread 系统通过 menuconfig 的方式进行配置,而 menuconfig 中的选项是由 Kconfig 文件决定的,因此想要对 RT-Thread 系统进行配置,需要对 kconfig 语法有一定了解。 ## 3. BSP移植 @@ -53,28 +48,18 @@ GD32的BSP架构主要分为三个部分:libraries、tools和具体的Boards ![Download](./figures/dowmload.png) - - 下载好后双击GigaDevice.GD32F4xx_DFP.2.1.0.pack运行即可: - - ![install paxk](./figures/install_pack.png) - - 点击[Next]即可安装完成。 ![finish](./figures/pack_finish.png) - - 安装成功后,重新打开Keil,则可以在File->Device Database中出现Gigadevice的下拉选项,点击可以查看到相应的型号。 ![Gigadevice](./figures/Gigadevice.png) - - ### 3.2 BSP工程制作 **1.构建基础工程** @@ -111,8 +96,6 @@ source "board/Kconfig" 该文件是获取所有路径下的Kconfig。 - - bsp/gd32/gd32407v-start/SConscript修改后的内容如下: ```python @@ -135,11 +118,10 @@ for d in list: Return('objs') ``` - 该文件是用于遍历当前目录的所有文件夹。 - bsp/gd32/gd32407v-start/SConstruct修改后的内容如下: + ```python import os import sys @@ -190,24 +172,24 @@ Export('SDK_LIB') # prepare building environment objs = PrepareBuilding(env, RTT_ROOT, has_libcpu=False) -gd32_library = 'GD32F4xx_HAL' +gd32_library = 'GD32F4xx_Firmware_Library' rtconfig.BSP_LIBRARY_TYPE = gd32_library # include libraries objs.extend(SConscript(os.path.join(libraries_path_prefix, gd32_library, 'SConscript'))) # include drivers -objs.extend(SConscript(os.path.join(libraries_path_prefix, 'HAL_Drivers', 'SConscript'))) +objs.extend(SConscript(os.path.join(libraries_path_prefix, 'Drivers', 'SConscript'))) # make a building DoBuilding(TARGET, objs) ``` + 该文件用于链接所有的依赖文件,并调用make进行编译。 - - **3.修改开发环境信息** bsp/gd32/gd32407v-start/cconfig.h修改后的内容如下: + ```c #ifndef CCONFIG_H__ #define CCONFIG_H__ @@ -228,10 +210,9 @@ bsp/gd32/gd32407v-start/cconfig.h修改后的内容如下: #endif ``` + 该文件是是编译BSP的环境信息,需根据实际修改。 - - **4.修改KEIL的模板工程** 双击:template.uvprojx即可修改模板工程。 @@ -240,32 +221,22 @@ bsp/gd32/gd32407v-start/cconfig.h修改后的内容如下: ![Chip](./figures/chip.png) - - 修改FLASH和RAM的配置: ![storage](./figures/storage.png) - - 修改可执行文件名字: ![rename](./figures/rename.png) - - 修改默认调试工具:CMSIS-DAP Debugger。 ![Debug](./figures/debug.png) - - 修改编程算法:GD32F4xx FMC。 ![FMC](./figures/FMC.png) - - **5.修改board文件夹** (1) 修改bsp/gd32/gd32407v-start/board/linker_scripts/link.icf @@ -314,10 +285,9 @@ place in RAM_region { readwrite, block CSTACK, block HEAP }; place in RAM1_region { section .sram }; ``` + 该文件是IAR编译的链接脚本,根据《GD32F407xx_Datasheet_Rev2.1》可知,GD32F407VKT6的flash大小为3072KB,SRAM大小为192KB,因此需要设置ROM和RAM的起始地址和堆栈大小等。 - - (2) 修改bsp/gd32/gd32407v-start/board/linker_scripts/link.ld 修改后的内容如下: @@ -358,74 +328,74 @@ SECTIONS KEEP(*(VSymTab)) __vsymtab_end = .; . = ALIGN(4); - + /* section information for initial. */ . = ALIGN(4); __rt_init_start = .; KEEP(*(SORT(.rti_fn*))) __rt_init_end = .; . = ALIGN(4); - + . = ALIGN(4); _etext = .; } > CODE = 0 - + /* .ARM.exidx is sorted, so has to go in its own output section. */ __exidx_start = .; .ARM.exidx : { *(.ARM.exidx* .gnu.linkonce.armexidx.*) - + /* This is used by the startup in order to initialize the .data secion */ _sidata = .; } > CODE __exidx_end = .; - + /* .data section which is used for initialized data */ - + .data : AT (_sidata) { . = ALIGN(4); /* This is used by the startup in order to initialize the .data secion */ _sdata = . ; - + *(.data) *(.data.*) *(.gnu.linkonce.d*) - + . = ALIGN(4); /* This is used by the startup in order to initialize the .data secion */ _edata = . ; } >DATA - + .stack : { . = . + _system_stack_size; . = ALIGN(4); _estack = .; } >DATA - + __bss_start = .; .bss : { . = ALIGN(4); /* This is used by the startup in order to initialize the .bss secion */ _sbss = .; - + *(.bss) *(.bss.*) *(COMMON) - + . = ALIGN(4); /* This is used by the startup in order to initialize the .bss secion */ _ebss = . ; - + *(.bss.init) } > DATA __bss_end = .; - + _end = .; - + /* Stabs debugging sections. */ .stab 0 : { *(.stab) } .stabstr 0 : { *(.stabstr) } @@ -461,6 +431,7 @@ SECTIONS .debug_varnames 0 : { *(.debug_varnames) } } ``` + 该文件是GCC编译的链接脚本,根据《GD32F407xx_Datasheet_Rev2.1》可知,GD32F407VKT6的flash大小为3072KB,SRAM大小为192KB,因此CODE和DATA 的LENGTH分别设置为3072KB和192KB,其他芯片类似,但其实地址都是一样的。 (3) 修改bsp/gd32/gd32407v-start/board/linker_scripts/link.sct @@ -482,13 +453,13 @@ LR_IROM1 0x08000000 0x00300000 { ; load region size_region } } ``` + 该文件是MDK的连接脚本,根据《GD32F407xx_Datasheet_Rev2.1》手册,因此需要将 LR_IROM1 和 ER_IROM1 的参数设置为 0x00300000;RAM 的大小为192k,因此需要将 RW_IRAM1 的参数设置为 0x00030000。 - - (4) 修改bsp/gd32/gd32407v-start/board/board.h文件 修改后内容如下: + ```c #ifndef __BOARD_H__ #define __BOARD_H__ @@ -528,13 +499,13 @@ extern int __bss_end; #endif ``` + 值得注意的是,不同的编译器规定的堆栈内存的起始地址 HEAP_BEGIN 和结束地址 HEAP_END。这里 HEAP_BEGIN 和 HEAP_END 的值需要和前面的链接脚本是一致的,需要结合实际去修改。 - - (5) 修改bsp/gd32/gd32407v-start/board/board.c文件 修改后的文件如下: + ```c #include #include @@ -611,22 +582,24 @@ void SystemClock_Config(void) #endif } ``` + 该文件重点关注的就是SystemClock_Config配置,SystemCoreClock的定义在system_gd32f4xx.c中定义的。 - - (6) 修改bsp/gd32/gd32407v-start/board/Kconfig文件 修改后内容如下: + ```config menu "Hardware Drivers Config" +config SOC_SERIES_GD32F4xx + default y config SOC_GD32407V bool - select SOC_SERIES_GD32F4 + select SOC_SERIES_GD32F4xx select RT_USING_COMPONENTS_INIT select RT_USING_USER_MAIN default y - + menu "Onboard Peripheral Drivers" endmenu @@ -637,7 +610,7 @@ menu "On-chip Peripheral Drivers" bool "Enable GPIO" select RT_USING_PIN default y - + menuconfig BSP_USING_UART bool "Enable UART" default y @@ -646,13 +619,13 @@ menu "On-chip Peripheral Drivers" config BSP_USING_UART1 bool "Enable UART1" default y - + config BSP_UART1_RX_USING_DMA bool "Enable UART1 RX DMA" depends on BSP_USING_UART1 && RT_SERIAL_USING_DMA default n endif - + menuconfig BSP_USING_SPI bool "Enable SPI BUS" default n @@ -661,19 +634,19 @@ menu "On-chip Peripheral Drivers" config BSP_USING_SPI1 bool "Enable SPI1 BUS" default n - + config BSP_SPI1_TX_USING_DMA bool "Enable SPI1 TX DMA" depends on BSP_USING_SPI1 default n - + config BSP_SPI1_RX_USING_DMA bool "Enable SPI1 RX DMA" depends on BSP_USING_SPI1 select BSP_SPI1_TX_USING_DMA default n endif - + menuconfig BSP_USING_I2C1 bool "Enable I2C1 BUS (software simulation)" default n @@ -690,7 +663,7 @@ menu "On-chip Peripheral Drivers" range 1 216 default 25 endif - source "../libraries/HAL_Drivers/Kconfig" + source "../libraries/gd32_drivers/Kconfig" endmenu @@ -700,13 +673,13 @@ endmenu endmenu ``` + 这个文件就是配置板子驱动的,这里可根据实际需求添加。 - - (7) 修改bsp/gd32/gd32407v-start/board/SConscript文件 修改后内容如下: + ```python import os import rtconfig @@ -726,23 +699,22 @@ path = [cwd] startup_path_prefix = SDK_LIB if rtconfig.CROSS_TOOL == 'gcc': - src += [startup_path_prefix + '/GD32F4xx_HAL/CMSIS/GD/GD32F4xx/Source/GCC/startup_gd32f4xx.S'] + src += [startup_path_prefix + '/GD32F4xx_Firmware_Library/CMSIS/GD/GD32F4xx/Source/GCC/startup_gd32f4xx.s'] elif rtconfig.CROSS_TOOL == 'keil': - src += [startup_path_prefix + '/GD32F4xx_HAL/CMSIS/GD/GD32F4xx/Source/ARM/startup_gd32f4xx.s'] + src += [startup_path_prefix + '/GD32F4xx_Firmware_Library/CMSIS/GD/GD32F4xx/Source/ARM/startup_gd32f4xx.s'] elif rtconfig.CROSS_TOOL == 'iar': - src += [startup_path_prefix + '/GD32F4xx_HAL/CMSIS/GD/GD32F4xx/Source/IAR/startup_gd32f4xx.s'] - -CPPDEFINES = ['GD32F407xx'] + src += [startup_path_prefix + '/GD32F4xx_Firmware_Library/CMSIS/GD/GD32F4xx/Source/IAR/startup_gd32f4xx.s'] + +CPPDEFINES = ['GD32F407'] group = DefineGroup('Drivers', src, depend = [''], CPPPATH = path, CPPDEFINES = CPPDEFINES) Return('group') ``` + 该文件主要添加board文件夹的.c文件和头文件路径。另外根据开发环境选择相应的汇编文件,和前面的libraries的SConscript语法是一样,文件的结构都是类似的,这里就没有注释了。 到这里,基本所有的依赖脚本都配置完成了,接下来将通过menuconfig配置工程。 - - **6.menuconfig配置** 关闭套接字抽象层。 @@ -758,18 +730,16 @@ Return('group') GD32407V-START板载没有以太网,因此这里主要是关闭网络相关的内容,当然GD32407V-START的资源丰富,不关这些其实也不影响,如果是其他MCU,根据实际需求自行修改吧。 - - **7.驱动修改** 一个基本的BSP中,串口是必不可少的,所以还需要编写串口驱动,这里使用的串口2作为调试串口。 板子上还有LED灯,主要要编写GPIO驱动即可。 + 关于串口和LED的驱动可以查看源码,这里就不贴出来了。 - - **8.应用开发** 笔者在applications的main.c中添加LED的应用代码, + ```c #include #include @@ -785,7 +755,7 @@ int main(void) /* set LED2 pin mode to output */ rt_pin_mode(LED2_PIN, PIN_MODE_OUTPUT); - + while (count++) { rt_pin_write(LED2_PIN, PIN_HIGH); @@ -793,14 +763,13 @@ int main(void) rt_pin_write(LED2_PIN, PIN_LOW); rt_thread_mdelay(500); } - + return RT_EOK; } ``` + 当然,这需要GPIO驱动的支持。 - - **9.使用ENV编译工程** 在env中执行:scons @@ -810,32 +779,23 @@ int main(void) ![scons_success](./figures/scons_success.png) - - **10.使用env生成MDK工程** 在env中执行:scons --target=mdk5 ![scons_mdk5](./figures/scons_mdk5.png) - - 生成MDK工程后,打开MDK工程进行编译 ![MDK Build](./figures/MDK_Build.png) - 成功编译打印信息如下: ![MDK Build success](./figures/MDK_Build_Success.png) - - ### 3.3 使用GD-Link 下载调试GD32 前面使用ENV和MDK成功编译可BSP,那么接下来就是下载调试环节,下载需要下载器,而GD32部分开发板自带GD-link,可以用开发板上自带的GD-link调试仿真代码,不带的可外接GD-link模块,还是很方便的。具体操作方法如下。 - - 1.第一次使用GD-link插入电脑后,会自动安装驱动。 在Options for Target -> Debug 中选择“CMSIS-DAP Debugger”,部分客户反馈找不到这一驱动器选项,那是因为MDK版本过低,只有Keil4.74以上的版本和Keil5才支持CMSIS-DAP Debugger选项。 @@ -854,8 +814,6 @@ int main(void) ![GD link debug](./figures/gdlink_debug.png) - - 当然啦,也可使用GD-Link下载程序。 ![GD link download](./figures/gdlink_download.png) @@ -870,8 +828,6 @@ int main(void) 同时LED会不断闪烁。 - - ### 3.4 RT-Thread studio开发 当然,该工程也可导出使用rt-thread studio开发。 @@ -888,8 +844,6 @@ int main(void) ![rt-thread_studio](./figures/rt-thread_studio.png) - - ## 4. 规范 本章节介绍 RT-Thread GD32 系列 BSP 制作与提交时应当遵守的规范 。开发人员在 BSP 制作完成后,可以根据本规范提出的检查点对制作的 BSP 进行检查,确保 BSP 在提交前有较高的质量 。 @@ -918,6 +872,7 @@ GD32 BSP 的制作规范主要分为 3 个方面:工程配置,ENV 配置和 - 系统空闲线程栈大小统一设置为 256(宏:IDLE_THREAD_STACK_SIZE) - 开启组件自动初始化(宏:RT_USING_COMPONENTS_INIT) - 需要开启 user main 选项(宏:RT_USING_USER_MAIN) +- 默认关闭 libc(宏:RT_USING_LIBC) - FinSH 默认只使用 MSH 模式(宏:FINSH_USING_MSH_ONLY) #### 4.1.3 IDE 配置 diff --git a/bsp/gd32/docs/figures/frame.png b/bsp/gd32/docs/figures/frame.png index 8125f76176..ef7fd7b8e4 100644 Binary files a/bsp/gd32/docs/figures/frame.png and b/bsp/gd32/docs/figures/frame.png differ diff --git a/bsp/gd32/docs/figures/scons_mdk5.png b/bsp/gd32/docs/figures/scons_mdk5.png index 556e677c51..e627581364 100644 Binary files a/bsp/gd32/docs/figures/scons_mdk5.png and b/bsp/gd32/docs/figures/scons_mdk5.png differ diff --git a/bsp/gd32/gd32105r-start/.config b/bsp/gd32/gd32105r-start/.config new file mode 100644 index 0000000000..9b63a4b9d0 --- /dev/null +++ b/bsp/gd32/gd32105r-start/.config @@ -0,0 +1,669 @@ +# +# Automatically generated file; DO NOT EDIT. +# RT-Thread Configuration +# + +# +# RT-Thread Kernel +# +CONFIG_RT_NAME_MAX=8 +# CONFIG_RT_USING_BIG_ENDIAN is not set +# CONFIG_RT_USING_ARCH_DATA_TYPE is not set +# CONFIG_RT_USING_SMP is not set +CONFIG_RT_ALIGN_SIZE=4 +# CONFIG_RT_THREAD_PRIORITY_8 is not set +CONFIG_RT_THREAD_PRIORITY_32=y +# CONFIG_RT_THREAD_PRIORITY_256 is not set +CONFIG_RT_THREAD_PRIORITY_MAX=32 +CONFIG_RT_TICK_PER_SECOND=100 +CONFIG_RT_USING_OVERFLOW_CHECK=y +CONFIG_RT_USING_HOOK=y +CONFIG_RT_USING_IDLE_HOOK=y +CONFIG_RT_IDLE_HOOK_LIST_SIZE=4 +CONFIG_IDLE_THREAD_STACK_SIZE=256 +# CONFIG_RT_USING_TIMER_SOFT is not set + +# +# kservice optimization +# +# CONFIG_RT_KSERVICE_USING_STDLIB is not set +# CONFIG_RT_KSERVICE_USING_TINY_SIZE is not set +# CONFIG_RT_USING_TINY_FFS is not set +# CONFIG_RT_PRINTF_LONGLONG is not set +CONFIG_RT_DEBUG=y +CONFIG_RT_DEBUG_COLOR=y +# CONFIG_RT_DEBUG_INIT_CONFIG is not set +# CONFIG_RT_DEBUG_THREAD_CONFIG is not set +# CONFIG_RT_DEBUG_SCHEDULER_CONFIG is not set +# CONFIG_RT_DEBUG_IPC_CONFIG is not set +# CONFIG_RT_DEBUG_TIMER_CONFIG is not set +# CONFIG_RT_DEBUG_IRQ_CONFIG is not set +# CONFIG_RT_DEBUG_MEM_CONFIG is not set +# CONFIG_RT_DEBUG_SLAB_CONFIG is not set +# CONFIG_RT_DEBUG_MEMHEAP_CONFIG is not set +# CONFIG_RT_DEBUG_MODULE_CONFIG is not set + +# +# Inter-Thread communication +# +CONFIG_RT_USING_SEMAPHORE=y +CONFIG_RT_USING_MUTEX=y +CONFIG_RT_USING_EVENT=y +CONFIG_RT_USING_MAILBOX=y +CONFIG_RT_USING_MESSAGEQUEUE=y +# CONFIG_RT_USING_SIGNALS is not set + +# +# Memory Management +# +CONFIG_RT_USING_MEMPOOL=y +CONFIG_RT_USING_SMALL_MEM=y +# CONFIG_RT_USING_SLAB is not set +# CONFIG_RT_USING_MEMHEAP is not set +CONFIG_RT_USING_SMALL_MEM_AS_HEAP=y +# CONFIG_RT_USING_MEMHEAP_AS_HEAP is not set +# CONFIG_RT_USING_SLAB_AS_HEAP is not set +# CONFIG_RT_USING_USERHEAP is not set +# CONFIG_RT_USING_NOHEAP is not set +# CONFIG_RT_USING_MEMTRACE is not set +# CONFIG_RT_USING_HEAP_ISR is not set +CONFIG_RT_USING_HEAP=y + +# +# Kernel Device Object +# +CONFIG_RT_USING_DEVICE=y +# CONFIG_RT_USING_DEVICE_OPS is not set +# CONFIG_RT_USING_INTERRUPT_INFO is not set +CONFIG_RT_USING_CONSOLE=y +CONFIG_RT_CONSOLEBUF_SIZE=128 +CONFIG_RT_CONSOLE_DEVICE_NAME="uart1" +CONFIG_RT_VER_NUM=0x40100 +# CONFIG_RT_USING_CPU_FFS is not set +# CONFIG_ARCH_CPU_STACK_GROWS_UPWARD is not set + +# +# RT-Thread Components +# +CONFIG_RT_USING_COMPONENTS_INIT=y +CONFIG_RT_USING_USER_MAIN=y +CONFIG_RT_MAIN_THREAD_STACK_SIZE=2048 +CONFIG_RT_MAIN_THREAD_PRIORITY=10 +# CONFIG_RT_USING_LEGACY is not set + +# +# C++ features +# +# CONFIG_RT_USING_CPLUSPLUS is not set + +# +# Command shell +# +CONFIG_RT_USING_FINSH=y +CONFIG_RT_USING_MSH=y +CONFIG_FINSH_USING_MSH=y +CONFIG_FINSH_THREAD_NAME="tshell" +CONFIG_FINSH_THREAD_PRIORITY=20 +CONFIG_FINSH_THREAD_STACK_SIZE=4096 +CONFIG_FINSH_USING_HISTORY=y +CONFIG_FINSH_HISTORY_LINES=5 +CONFIG_FINSH_USING_SYMTAB=y +CONFIG_FINSH_CMD_SIZE=80 +CONFIG_MSH_USING_BUILT_IN_COMMANDS=y +CONFIG_FINSH_USING_DESCRIPTION=y +# CONFIG_FINSH_ECHO_DISABLE_DEFAULT is not set +# CONFIG_FINSH_USING_AUTH is not set +CONFIG_FINSH_ARG_MAX=10 + +# +# Device virtual file system +# +# CONFIG_RT_USING_DFS is not set + +# +# Device Drivers +# +CONFIG_RT_USING_DEVICE_IPC=y +CONFIG_RT_USING_SYSTEM_WORKQUEUE=y +CONFIG_RT_SYSTEM_WORKQUEUE_STACKSIZE=2048 +CONFIG_RT_SYSTEM_WORKQUEUE_PRIORITY=23 +CONFIG_RT_USING_SERIAL=y +CONFIG_RT_USING_SERIAL_V1=y +# CONFIG_RT_USING_SERIAL_V2 is not set +CONFIG_RT_SERIAL_USING_DMA=y +CONFIG_RT_SERIAL_RB_BUFSZ=64 +# CONFIG_RT_USING_CAN is not set +# CONFIG_RT_USING_HWTIMER is not set +# CONFIG_RT_USING_CPUTIME is not set +CONFIG_RT_USING_I2C=y +# CONFIG_RT_I2C_DEBUG is not set +CONFIG_RT_USING_I2C_BITOPS=y +# CONFIG_RT_I2C_BITOPS_DEBUG is not set +# CONFIG_RT_USING_PHY is not set +CONFIG_RT_USING_PIN=y +CONFIG_RT_USING_ADC=y +# CONFIG_RT_USING_DAC is not set +# CONFIG_RT_USING_PWM is not set +# CONFIG_RT_USING_MTD_NOR is not set +# CONFIG_RT_USING_MTD_NAND is not set +# CONFIG_RT_USING_PM is not set +# CONFIG_RT_USING_RTC is not set +# CONFIG_RT_USING_SDIO is not set +# CONFIG_RT_USING_SPI is not set +# CONFIG_RT_USING_WDT is not set +# CONFIG_RT_USING_AUDIO is not set +# CONFIG_RT_USING_SENSOR is not set +# CONFIG_RT_USING_TOUCH is not set +# CONFIG_RT_USING_HWCRYPTO is not set +# CONFIG_RT_USING_PULSE_ENCODER is not set +# CONFIG_RT_USING_INPUT_CAPTURE is not set +# CONFIG_RT_USING_WIFI is not set + +# +# Using USB +# +# CONFIG_RT_USING_USB is not set +# CONFIG_RT_USING_USB_HOST is not set +# CONFIG_RT_USING_USB_DEVICE is not set + +# +# POSIX layer and C standard library +# +# CONFIG_RT_USING_LIBC is not set +CONFIG_RT_LIBC_USING_TIME=y +CONFIG_RT_LIBC_DEFAULT_TIMEZONE=8 + +# +# POSIX (Portable Operating System Interface) layer +# +# CONFIG_RT_USING_POSIX_FS is not set +# CONFIG_RT_USING_POSIX_DELAY is not set +# CONFIG_RT_USING_POSIX_CLOCK is not set +# CONFIG_RT_USING_POSIX_GETLINE is not set +# CONFIG_RT_USING_PTHREADS is not set + +# +# Interprocess Communication (IPC) +# +# CONFIG_RT_USING_POSIX_PIPE is not set +# CONFIG_RT_USING_POSIX_MESSAGE_QUEUE is not set +# CONFIG_RT_USING_POSIX_MESSAGE_SEMAPHORE is not set + +# +# Socket is in the 'Network' category +# + +# +# Network +# + +# +# Socket abstraction layer +# +# CONFIG_RT_USING_SAL is not set + +# +# Network interface device +# +# CONFIG_RT_USING_NETDEV is not set + +# +# light weight TCP/IP stack +# +# CONFIG_RT_USING_LWIP is not set + +# +# AT commands +# +# CONFIG_RT_USING_AT is not set + +# +# VBUS(Virtual Software BUS) +# +# CONFIG_RT_USING_VBUS is not set + +# +# Utilities +# +# CONFIG_RT_USING_RYM is not set +# CONFIG_RT_USING_ULOG is not set +# CONFIG_RT_USING_UTEST is not set +# CONFIG_RT_USING_VAR_EXPORT is not set +# CONFIG_RT_USING_RT_LINK is not set + +# +# RT-Thread Utestcases +# +# CONFIG_RT_USING_UTESTCASES is not set + +# +# RT-Thread online packages +# + +# +# IoT - internet of things +# +# CONFIG_PKG_USING_LORAWAN_DRIVER is not set +# CONFIG_PKG_USING_PAHOMQTT is not set +# CONFIG_PKG_USING_UMQTT is not set +# CONFIG_PKG_USING_WEBCLIENT is not set +# CONFIG_PKG_USING_WEBNET is not set +# CONFIG_PKG_USING_MONGOOSE is not set +# CONFIG_PKG_USING_MYMQTT is not set +# CONFIG_PKG_USING_KAWAII_MQTT is not set +# CONFIG_PKG_USING_BC28_MQTT is not set +# CONFIG_PKG_USING_WEBTERMINAL is not set +# CONFIG_PKG_USING_CJSON is not set +# CONFIG_PKG_USING_JSMN is not set +# CONFIG_PKG_USING_LIBMODBUS is not set +# CONFIG_PKG_USING_FREEMODBUS is not set +# CONFIG_PKG_USING_LJSON is not set +# CONFIG_PKG_USING_EZXML is not set +# CONFIG_PKG_USING_NANOPB is not set + +# +# Wi-Fi +# + +# +# Marvell WiFi +# +# CONFIG_PKG_USING_WLANMARVELL is not set + +# +# Wiced WiFi +# +# CONFIG_PKG_USING_WLAN_WICED is not set +# CONFIG_PKG_USING_RW007 is not set +# CONFIG_PKG_USING_COAP is not set +# CONFIG_PKG_USING_NOPOLL is not set +# CONFIG_PKG_USING_NETUTILS is not set +# CONFIG_PKG_USING_CMUX is not set +# CONFIG_PKG_USING_PPP_DEVICE is not set +# CONFIG_PKG_USING_AT_DEVICE is not set +# CONFIG_PKG_USING_ATSRV_SOCKET is not set +# CONFIG_PKG_USING_WIZNET is not set +# CONFIG_PKG_USING_ZB_COORDINATOR is not set + +# +# IoT Cloud +# +# CONFIG_PKG_USING_ONENET is not set +# CONFIG_PKG_USING_GAGENT_CLOUD is not set +# CONFIG_PKG_USING_ALI_IOTKIT is not set +# CONFIG_PKG_USING_AZURE is not set +# CONFIG_PKG_USING_TENCENT_IOT_EXPLORER is not set +# CONFIG_PKG_USING_JIOT-C-SDK is not set +# CONFIG_PKG_USING_UCLOUD_IOT_SDK is not set +# CONFIG_PKG_USING_JOYLINK is not set +# CONFIG_PKG_USING_NIMBLE is not set +# CONFIG_PKG_USING_OTA_DOWNLOADER is not set +# CONFIG_PKG_USING_IPMSG is not set +# CONFIG_PKG_USING_LSSDP is not set +# CONFIG_PKG_USING_AIRKISS_OPEN is not set +# CONFIG_PKG_USING_LIBRWS is not set +# CONFIG_PKG_USING_TCPSERVER is not set +# CONFIG_PKG_USING_PROTOBUF_C is not set +# CONFIG_PKG_USING_DLT645 is not set +# CONFIG_PKG_USING_QXWZ is not set +# CONFIG_PKG_USING_SMTP_CLIENT is not set +# CONFIG_PKG_USING_ABUP_FOTA is not set +# CONFIG_PKG_USING_LIBCURL2RTT is not set +# CONFIG_PKG_USING_CAPNP is not set +# CONFIG_PKG_USING_RT_CJSON_TOOLS is not set +# CONFIG_PKG_USING_AGILE_TELNET is not set +# CONFIG_PKG_USING_NMEALIB is not set +# CONFIG_PKG_USING_AGILE_JSMN is not set +# CONFIG_PKG_USING_PDULIB is not set +# CONFIG_PKG_USING_BTSTACK is not set +# CONFIG_PKG_USING_LORAWAN_ED_STACK is not set +# CONFIG_PKG_USING_WAYZ_IOTKIT is not set +# CONFIG_PKG_USING_MAVLINK is not set +# CONFIG_PKG_USING_RAPIDJSON is not set +# CONFIG_PKG_USING_BSAL is not set +# CONFIG_PKG_USING_AGILE_MODBUS is not set +# CONFIG_PKG_USING_AGILE_FTP is not set +# CONFIG_PKG_USING_EMBEDDEDPROTO is not set +# CONFIG_PKG_USING_RT_LINK_HW is not set +# CONFIG_PKG_USING_LORA_PKT_FWD is not set +# CONFIG_PKG_USING_LORA_GW_DRIVER_LIB is not set +# CONFIG_PKG_USING_LORA_PKT_SNIFFER is not set +# CONFIG_PKG_USING_HM is not set +# CONFIG_PKG_USING_SMALL_MODBUS is not set +# CONFIG_PKG_USING_NET_SERVER is not set + +# +# security packages +# +# CONFIG_PKG_USING_MBEDTLS is not set +# CONFIG_PKG_USING_LIBSODIUM is not set +# CONFIG_PKG_USING_TINYCRYPT is not set +# CONFIG_PKG_USING_TFM is not set +# CONFIG_PKG_USING_YD_CRYPTO is not set + +# +# language packages +# +# CONFIG_PKG_USING_LUA is not set +# CONFIG_PKG_USING_JERRYSCRIPT is not set +# CONFIG_PKG_USING_MICROPYTHON is not set +# CONFIG_PKG_USING_PIKASCRIPT is not set + +# +# multimedia packages +# + +# +# LVGL: powerful and easy-to-use embedded GUI library +# +# CONFIG_PKG_USING_LVGL is not set +# CONFIG_PKG_USING_LITTLEVGL2RTT is not set +# CONFIG_PKG_USING_LV_MUSIC_DEMO is not set + +# +# u8g2: a monochrome graphic library +# +# CONFIG_PKG_USING_U8G2_OFFICIAL is not set +# CONFIG_PKG_USING_U8G2 is not set +# CONFIG_PKG_USING_OPENMV is not set +# CONFIG_PKG_USING_MUPDF is not set +# CONFIG_PKG_USING_STEMWIN is not set +# CONFIG_PKG_USING_WAVPLAYER is not set +# CONFIG_PKG_USING_TJPGD is not set +# CONFIG_PKG_USING_PDFGEN is not set +# CONFIG_PKG_USING_HELIX is not set +# CONFIG_PKG_USING_AZUREGUIX is not set +# CONFIG_PKG_USING_TOUCHGFX2RTT is not set +# CONFIG_PKG_USING_NUEMWIN is not set +# CONFIG_PKG_USING_MP3PLAYER is not set +# CONFIG_PKG_USING_TINYJPEG is not set +# CONFIG_PKG_USING_UGUI is not set + +# +# PainterEngine: A cross-platform graphics application framework written in C language +# +# CONFIG_PKG_USING_PAINTERENGINE is not set +# CONFIG_PKG_USING_PAINTERENGINE_AUX is not set +# CONFIG_PKG_USING_MCURSES is not set +# CONFIG_PKG_USING_TERMBOX is not set +# CONFIG_PKG_USING_VT100 is not set + +# +# tools packages +# +# CONFIG_PKG_USING_CMBACKTRACE is not set +# CONFIG_PKG_USING_EASYFLASH is not set +# CONFIG_PKG_USING_EASYLOGGER is not set +# CONFIG_PKG_USING_SYSTEMVIEW is not set +# CONFIG_PKG_USING_SEGGER_RTT is not set +# CONFIG_PKG_USING_RDB is not set +# CONFIG_PKG_USING_QRCODE is not set +# CONFIG_PKG_USING_ULOG_EASYFLASH is not set +# CONFIG_PKG_USING_ULOG_FILE is not set +# CONFIG_PKG_USING_LOGMGR is not set +# CONFIG_PKG_USING_ADBD is not set +# CONFIG_PKG_USING_COREMARK is not set +# CONFIG_PKG_USING_DHRYSTONE is not set +# CONFIG_PKG_USING_MEMORYPERF is not set +# CONFIG_PKG_USING_NR_MICRO_SHELL is not set +# CONFIG_PKG_USING_CHINESE_FONT_LIBRARY is not set +# CONFIG_PKG_USING_LUNAR_CALENDAR is not set +# CONFIG_PKG_USING_BS8116A is not set +# CONFIG_PKG_USING_GPS_RMC is not set +# CONFIG_PKG_USING_URLENCODE is not set +# CONFIG_PKG_USING_UMCN is not set +# CONFIG_PKG_USING_LWRB2RTT is not set +# CONFIG_PKG_USING_CPU_USAGE is not set +# CONFIG_PKG_USING_GBK2UTF8 is not set +# CONFIG_PKG_USING_VCONSOLE is not set +# CONFIG_PKG_USING_KDB is not set +# CONFIG_PKG_USING_WAMR is not set +# CONFIG_PKG_USING_MICRO_XRCE_DDS_CLIENT is not set +# CONFIG_PKG_USING_LWLOG is not set +# CONFIG_PKG_USING_ANV_TRACE is not set +# CONFIG_PKG_USING_ANV_MEMLEAK is not set +# CONFIG_PKG_USING_ANV_TESTSUIT is not set +# CONFIG_PKG_USING_ANV_BENCH is not set +# CONFIG_PKG_USING_DEVMEM is not set +# CONFIG_PKG_USING_REGEX is not set +# CONFIG_PKG_USING_MEM_SANDBOX is not set +# CONFIG_PKG_USING_SOLAR_TERMS is not set +# CONFIG_PKG_USING_GAN_ZHI is not set +# CONFIG_PKG_USING_FDT is not set + +# +# system packages +# +# CONFIG_PKG_USING_LUATOS_SOC is not set + +# +# enhanced kernel services +# +# CONFIG_PKG_USING_RT_MEMCPY_CM is not set +# CONFIG_PKG_USING_RT_KPRINTF_THREADSAFE is not set +# CONFIG_PKG_USING_RT_VSNPRINTF_FULL is not set + +# +# acceleration: Assembly language or algorithmic acceleration packages +# +# CONFIG_PKG_USING_QFPLIB_M0_FULL is not set +# CONFIG_PKG_USING_QFPLIB_M0_TINY is not set +# CONFIG_PKG_USING_QFPLIB_M3 is not set + +# +# CMSIS: ARM Cortex-M Microcontroller Software Interface Standard +# +# CONFIG_PKG_USING_CMSIS_5 is not set +# CONFIG_PKG_USING_CMSIS_RTOS2 is not set + +# +# Micrium: Micrium software products porting for RT-Thread +# +# CONFIG_PKG_USING_UCOSIII_WRAPPER is not set +# CONFIG_PKG_USING_UCOSII_WRAPPER is not set +# CONFIG_PKG_USING_UC_CRC is not set +# CONFIG_PKG_USING_UC_CLK is not set +# CONFIG_PKG_USING_UC_COMMON is not set +# CONFIG_PKG_USING_UC_MODBUS is not set +# CONFIG_RT_USING_ARDUINO is not set +# CONFIG_PKG_USING_GUIENGINE is not set +# CONFIG_PKG_USING_CAIRO is not set +# CONFIG_PKG_USING_PIXMAN is not set +# CONFIG_PKG_USING_PARTITION is not set +# CONFIG_PKG_USING_FAL is not set +# CONFIG_PKG_USING_FLASHDB is not set +# CONFIG_PKG_USING_SQLITE is not set +# CONFIG_PKG_USING_RTI is not set +# CONFIG_PKG_USING_DFS_YAFFS is not set +# CONFIG_PKG_USING_LITTLEFS is not set +# CONFIG_PKG_USING_DFS_JFFS2 is not set +# CONFIG_PKG_USING_DFS_UFFS is not set +# CONFIG_PKG_USING_LWEXT4 is not set +# CONFIG_PKG_USING_THREAD_POOL is not set +# CONFIG_PKG_USING_ROBOTS is not set +# CONFIG_PKG_USING_EV is not set +# CONFIG_PKG_USING_SYSWATCH is not set +# CONFIG_PKG_USING_SYS_LOAD_MONITOR is not set +# CONFIG_PKG_USING_PLCCORE is not set +# CONFIG_PKG_USING_RAMDISK is not set +# CONFIG_PKG_USING_MININI is not set +# CONFIG_PKG_USING_QBOOT is not set +# CONFIG_PKG_USING_PPOOL is not set +# CONFIG_PKG_USING_OPENAMP is not set +# CONFIG_PKG_USING_LPM is not set +# CONFIG_PKG_USING_TLSF is not set +# CONFIG_PKG_USING_EVENT_RECORDER is not set +# CONFIG_PKG_USING_ARM_2D is not set +# CONFIG_PKG_USING_WCWIDTH is not set +# CONFIG_PKG_USING_MCUBOOT is not set +# CONFIG_PKG_USING_TINYUSB is not set +# CONFIG_PKG_USING_USB_STACK is not set + +# +# peripheral libraries and drivers +# +# CONFIG_PKG_USING_SENSORS_DRIVERS is not set +# CONFIG_PKG_USING_REALTEK_AMEBA is not set +# CONFIG_PKG_USING_SHT2X is not set +# CONFIG_PKG_USING_SHT3X is not set +# CONFIG_PKG_USING_AS7341 is not set +# CONFIG_PKG_USING_STM32_SDIO is not set +# CONFIG_PKG_USING_ICM20608 is not set +# CONFIG_PKG_USING_BUTTON is not set +# CONFIG_PKG_USING_PCF8574 is not set +# CONFIG_PKG_USING_SX12XX is not set +# CONFIG_PKG_USING_SIGNAL_LED is not set +# CONFIG_PKG_USING_LEDBLINK is not set +# CONFIG_PKG_USING_LITTLED is not set +# CONFIG_PKG_USING_LKDGUI is not set +# CONFIG_PKG_USING_NRF5X_SDK is not set +# CONFIG_PKG_USING_NRFX is not set +# CONFIG_PKG_USING_WM_LIBRARIES is not set +# CONFIG_PKG_USING_KENDRYTE_SDK is not set +# CONFIG_PKG_USING_INFRARED is not set +# CONFIG_PKG_USING_AGILE_BUTTON is not set +# CONFIG_PKG_USING_AGILE_LED is not set +# CONFIG_PKG_USING_AT24CXX is not set +# CONFIG_PKG_USING_MOTIONDRIVER2RTT is not set +# CONFIG_PKG_USING_AD7746 is not set +# CONFIG_PKG_USING_PCA9685 is not set +# CONFIG_PKG_USING_I2C_TOOLS is not set +# CONFIG_PKG_USING_NRF24L01 is not set +# CONFIG_PKG_USING_TOUCH_DRIVERS is not set +# CONFIG_PKG_USING_MAX17048 is not set +# CONFIG_PKG_USING_RPLIDAR is not set +# CONFIG_PKG_USING_AS608 is not set +# CONFIG_PKG_USING_RC522 is not set +# CONFIG_PKG_USING_WS2812B is not set +# CONFIG_PKG_USING_EMBARC_BSP is not set +# CONFIG_PKG_USING_EXTERN_RTC_DRIVERS is not set +# CONFIG_PKG_USING_MULTI_RTIMER is not set +# CONFIG_PKG_USING_MAX7219 is not set +# CONFIG_PKG_USING_BEEP is not set +# CONFIG_PKG_USING_EASYBLINK is not set +# CONFIG_PKG_USING_PMS_SERIES is not set +# CONFIG_PKG_USING_CAN_YMODEM is not set +# CONFIG_PKG_USING_LORA_RADIO_DRIVER is not set +# CONFIG_PKG_USING_QLED is not set +# CONFIG_PKG_USING_PAJ7620 is not set +# CONFIG_PKG_USING_AGILE_CONSOLE is not set +# CONFIG_PKG_USING_LD3320 is not set +# CONFIG_PKG_USING_WK2124 is not set +# CONFIG_PKG_USING_LY68L6400 is not set +# CONFIG_PKG_USING_DM9051 is not set +# CONFIG_PKG_USING_SSD1306 is not set +# CONFIG_PKG_USING_QKEY is not set +# CONFIG_PKG_USING_RS485 is not set +# CONFIG_PKG_USING_NES is not set +# CONFIG_PKG_USING_VIRTUAL_SENSOR is not set +# CONFIG_PKG_USING_VDEVICE is not set +# CONFIG_PKG_USING_SGM706 is not set +# CONFIG_PKG_USING_STM32WB55_SDK is not set +# CONFIG_PKG_USING_RDA58XX is not set +# CONFIG_PKG_USING_LIBNFC is not set +# CONFIG_PKG_USING_MFOC is not set +# CONFIG_PKG_USING_TMC51XX is not set +# CONFIG_PKG_USING_TCA9534 is not set +# CONFIG_PKG_USING_KOBUKI is not set +# CONFIG_PKG_USING_ROSSERIAL is not set +# CONFIG_PKG_USING_MICRO_ROS is not set +# CONFIG_PKG_USING_MCP23008 is not set +# CONFIG_PKG_USING_BLUETRUM_SDK is not set +# CONFIG_PKG_USING_MISAKA_AT24CXX is not set +# CONFIG_PKG_USING_MISAKA_RGB_BLING is not set +# CONFIG_PKG_USING_BL_MCU_SDK is not set +# CONFIG_PKG_USING_SOFT_SERIAL is not set +# CONFIG_PKG_USING_MB85RS16 is not set + +# +# AI packages +# +# CONFIG_PKG_USING_LIBANN is not set +# CONFIG_PKG_USING_NNOM is not set +# CONFIG_PKG_USING_ONNX_BACKEND is not set +# CONFIG_PKG_USING_ONNX_PARSER is not set +# CONFIG_PKG_USING_TENSORFLOWLITEMICRO is not set +# CONFIG_PKG_USING_ELAPACK is not set +# CONFIG_PKG_USING_ULAPACK is not set +# CONFIG_PKG_USING_QUEST is not set +# CONFIG_PKG_USING_NAXOS is not set + +# +# miscellaneous packages +# + +# +# samples: kernel and components samples +# +# CONFIG_PKG_USING_KERNEL_SAMPLES is not set +# CONFIG_PKG_USING_FILESYSTEM_SAMPLES is not set +# CONFIG_PKG_USING_NETWORK_SAMPLES is not set +# CONFIG_PKG_USING_PERIPHERAL_SAMPLES is not set + +# +# entertainment: terminal games and other interesting software packages +# +# CONFIG_PKG_USING_CMATRIX is not set +# CONFIG_PKG_USING_SL is not set +# CONFIG_PKG_USING_CAL is not set +# CONFIG_PKG_USING_ACLOCK is not set +# CONFIG_PKG_USING_THREES is not set +# CONFIG_PKG_USING_2048 is not set +# CONFIG_PKG_USING_SNAKE is not set +# CONFIG_PKG_USING_TETRIS is not set +# CONFIG_PKG_USING_DONUT is not set +# CONFIG_PKG_USING_COWSAY is not set +# CONFIG_PKG_USING_LIBCSV is not set +# CONFIG_PKG_USING_OPTPARSE is not set +# CONFIG_PKG_USING_FASTLZ is not set +# CONFIG_PKG_USING_MINILZO is not set +# CONFIG_PKG_USING_QUICKLZ is not set +# CONFIG_PKG_USING_LZMA is not set +# CONFIG_PKG_USING_MULTIBUTTON is not set +# CONFIG_PKG_USING_FLEXIBLE_BUTTON is not set +# CONFIG_PKG_USING_CANFESTIVAL is not set +# CONFIG_PKG_USING_ZLIB is not set +# CONFIG_PKG_USING_MINIZIP is not set +# CONFIG_PKG_USING_DSTR is not set +# CONFIG_PKG_USING_TINYFRAME is not set +# CONFIG_PKG_USING_KENDRYTE_DEMO is not set +# CONFIG_PKG_USING_DIGITALCTRL is not set +# CONFIG_PKG_USING_UPACKER is not set +# CONFIG_PKG_USING_UPARAM is not set +# CONFIG_PKG_USING_HELLO is not set +# CONFIG_PKG_USING_VI is not set +# CONFIG_PKG_USING_KI is not set +# CONFIG_PKG_USING_ARMv7M_DWT is not set +# CONFIG_PKG_USING_UKAL is not set +# CONFIG_PKG_USING_CRCLIB is not set +# CONFIG_PKG_USING_LWGPS is not set +# CONFIG_PKG_USING_STATE_MACHINE is not set +# CONFIG_PKG_USING_DESIGN_PATTERN is not set + +# +# Hardware Drivers Config +# +CONFIG_SOC_SERIES_GD32F10x=y +CONFIG_SOC_GD32105R=y + +# +# Onboard Peripheral Drivers +# + +# +# On-chip Peripheral Drivers +# +CONFIG_BSP_USING_GPIO=y +CONFIG_BSP_USING_UART=y +CONFIG_BSP_USING_UART1=y +# CONFIG_BSP_UART1_RX_USING_DMA is not set +# CONFIG_BSP_USING_ADC is not set +# CONFIG_BSP_USING_SPI is not set +# CONFIG_BSP_USING_I2C1 is not set +# CONFIG_BSP_USING_TIM is not set +# CONFIG_BSP_USING_WDT is not set +# CONFIG_BSP_USING_RTC is not set + +# +# Board extended module Drivers +# diff --git a/bsp/gd32/gd32105r-start/Kconfig b/bsp/gd32/gd32105r-start/Kconfig new file mode 100644 index 0000000000..8cbc7b71a8 --- /dev/null +++ b/bsp/gd32/gd32105r-start/Kconfig @@ -0,0 +1,21 @@ +mainmenu "RT-Thread Configuration" + +config BSP_DIR + string + option env="BSP_ROOT" + default "." + +config RTT_DIR + string + option env="RTT_ROOT" + default "../../.." + +config PKGS_DIR + string + option env="PKGS_ROOT" + default "packages" + +source "$RTT_DIR/Kconfig" +source "$PKGS_DIR/Kconfig" +source "../libraries/Kconfig" +source "board/Kconfig" diff --git a/bsp/gd32/gd32105r-start/README.md b/bsp/gd32/gd32105r-start/README.md new file mode 100644 index 0000000000..3ebd9ac205 --- /dev/null +++ b/bsp/gd32/gd32105r-start/README.md @@ -0,0 +1,98 @@ +# GD32105R-START开发板BSP说明 + +## 简介 + +GD3105R-START是-兆易创新推出的一款GD32F10X系列的评估板,最高主频高达108M,该开发板具有丰富的板载资源,可以充分发挥 GD32105R 的芯片性能。 + +开发板外观如下图所示: + +![board](figures/board.jpg) + +该开发板常用 **板载资源** 如下: + +- GD32105R,主频 108MHz,256KB FLASH ,96KB RAM + +- 常用外设 + + - LED :2个,LED1 (电源指示灯),LED2(PC6) + - 按键:2个,K1(复位引脚),K2(用户按键,PA0) + +- 常用接口:USB 接口 + +- 调试接口:GD-LINK + +## 外设支持 + +本 BSP 目前对外设的支持情况如下: + +| **片上外设** | **支持情况** | **备注** | +|:--------- |:--------:|:------------------------------------- | +| GPIO | 支持 | PA0, PA1... PK15 ---> PIN: 0, 1...144 | +| UART | 支持 | UART0 - UART7 | +| I2C | 支持 | I2C1 | +| SPI | 支持 | SPI0. SPI1, SPI2 | +| SPI FLASH | 支持 | | +| **扩展模块** | **支持情况** | **备注** | +| 暂无 | 暂不支持 | 暂不支持 | + +## 使用说明 + +使用说明分为如下两个章节: + +- 快速上手 + + 本章节是为刚接触 RT-Thread 的新手准备的使用说明,遵循简单的步骤即可将 RT-Thread 操作系统运行在该开发板上,看到实验效果 。 + +- 进阶使用 + + 本章节是为需要在 RT-Thread 操作系统上使用更多开发板资源的开发者准备的。通过使用 ENV 工具对 BSP 进行配置,可以开启更多板载资源,实现更多高级功能。 + +### 快速上手 + +本 BSP 为开发者提供 MDK5 工程,并且支持 GCC 开发环境,也可使用RT-Thread Studio开发。下面以 MDK5 开发环境为例,介绍如何将系统运行起来。 + +#### 硬件连接 + +使用数据线连接开发板到 PC,使用USB转TTL模块连接PA2(MCU TX)和PA3(MCU RX),打开电源开关。 + +#### 编译下载 + +双击 project.uvprojx 文件,打开 MDK5 工程,编译并下载程序到开发板。 + +> 工程默认配置使用 GD-Link 仿真器下载程序,在通过 GD-Link 连接开发板的基础上,点击下载按钮即可下载程序到开发板 + +#### 运行结果 + +下载程序成功之后,系统会自动运行,LED 闪烁。 + +连接开发板对应串口到 PC , 在终端工具里打开相应的串口(115200-8-1-N),复位设备后,可以看到 RT-Thread 的输出信息: + +```bash + \ | / +- RT - Thread Operating System + / | \ 4.0.4 build Dec 19 2021 10:00:27 + 2006 - 2021 Copyright by rt-thread team +msh > +``` + +### 进阶使用 + +此 BSP 默认只开启了 GPIO 和 串口1的功能,如果需使用高级功能,需要利用 ENV 工具对BSP 进行配置,步骤如下: + +1. 在 bsp 下打开 env 工具。 + +2. 输入`menuconfig`命令配置工程,配置好之后保存退出。 + +3. 输入`pkgs --update`命令更新软件包。 + +4. 输入`scons --target=mdk4/mdk5` 命令重新生成工程。 + +## 注意事项 + +暂无 + +## 联系人信息 + +维护人: + +- [BruceOu](https://github.com/Ouxiaolong/), 邮箱: \ No newline at end of file diff --git a/bsp/gd32/gd32105r-start/SConscript b/bsp/gd32/gd32105r-start/SConscript new file mode 100644 index 0000000000..20f7689c53 --- /dev/null +++ b/bsp/gd32/gd32105r-start/SConscript @@ -0,0 +1,15 @@ +# for module compiling +import os +Import('RTT_ROOT') +from building import * + +cwd = GetCurrentDir() +objs = [] +list = os.listdir(cwd) + +for d in list: + path = os.path.join(cwd, d) + if os.path.isfile(os.path.join(path, 'SConscript')): + objs = objs + SConscript(os.path.join(d, 'SConscript')) + +Return('objs') diff --git a/bsp/gd32/gd32105r-start/SConstruct b/bsp/gd32/gd32105r-start/SConstruct new file mode 100644 index 0000000000..49074397d0 --- /dev/null +++ b/bsp/gd32/gd32105r-start/SConstruct @@ -0,0 +1,60 @@ +import os +import sys +import rtconfig + +if os.getenv('RTT_ROOT'): + RTT_ROOT = os.getenv('RTT_ROOT') +else: + RTT_ROOT = os.path.normpath(os.getcwd() + '/../../..') + +sys.path = sys.path + [os.path.join(RTT_ROOT, 'tools')] +try: + from building import * +except: + print('Cannot found RT-Thread root directory, please check RTT_ROOT') + print(RTT_ROOT) + exit(-1) + +TARGET = 'rtthread.' + rtconfig.TARGET_EXT + +DefaultEnvironment(tools=[]) +env = Environment(tools = ['mingw'], + AS = rtconfig.AS, ASFLAGS = rtconfig.AFLAGS, + CC = rtconfig.CC, CCFLAGS = rtconfig.CFLAGS, + AR = rtconfig.AR, ARFLAGS = '-rc', + CXX = rtconfig.CXX, CXXFLAGS = rtconfig.CXXFLAGS, + LINK = rtconfig.LINK, LINKFLAGS = rtconfig.LFLAGS) +env.PrependENVPath('PATH', rtconfig.EXEC_PATH) + +if rtconfig.PLATFORM == 'iar': + env.Replace(CCCOM = ['$CC $CCFLAGS $CPPFLAGS $_CPPDEFFLAGS $_CPPINCFLAGS -o $TARGET $SOURCES']) + env.Replace(ARFLAGS = ['']) + env.Replace(LINKCOM = env["LINKCOM"] + ' --map rtthread.map') + +Export('RTT_ROOT') +Export('rtconfig') + +SDK_ROOT = os.path.abspath('./') + +if os.path.exists(SDK_ROOT + '/libraries'): + libraries_path_prefix = SDK_ROOT + '/libraries' +else: + libraries_path_prefix = os.path.dirname(SDK_ROOT) + '/libraries' + +SDK_LIB = libraries_path_prefix +Export('SDK_LIB') + +# prepare building environment +objs = PrepareBuilding(env, RTT_ROOT, has_libcpu=False) + +gd32_library = 'GD32F10x_Firmware_Library' +rtconfig.BSP_LIBRARY_TYPE = gd32_library + +# include libraries +objs.extend(SConscript(os.path.join(libraries_path_prefix, gd32_library, 'SConscript'))) + +# include drivers +objs.extend(SConscript(os.path.join(libraries_path_prefix, 'gd32_drivers', 'SConscript'))) + +# make a building +DoBuilding(TARGET, objs) diff --git a/bsp/gd32/gd32105r-start/applications/SConscript b/bsp/gd32/gd32105r-start/applications/SConscript new file mode 100644 index 0000000000..01eb940dfb --- /dev/null +++ b/bsp/gd32/gd32105r-start/applications/SConscript @@ -0,0 +1,11 @@ +Import('RTT_ROOT') +Import('rtconfig') +from building import * + +cwd = os.path.join(str(Dir('#')), 'applications') +src = Glob('*.c') +CPPPATH = [cwd, str(Dir('#'))] + +group = DefineGroup('Applications', src, depend = [''], CPPPATH = CPPPATH) + +Return('group') diff --git a/bsp/gd32/gd32105r-start/applications/main.c b/bsp/gd32/gd32105r-start/applications/main.c new file mode 100644 index 0000000000..32fd8231da --- /dev/null +++ b/bsp/gd32/gd32105r-start/applications/main.c @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2006-2022, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2021-08-20 BruceOu first implementation + */ + +#include +#include +#include +#include + +/* defined the LED2 pin: PC6 */ +#define LED2_PIN GET_PIN(C, 6) + +int main(void) +{ + int count = 1; + + //set LED2 pin mode to output + rt_pin_mode(LED2_PIN, PIN_MODE_OUTPUT); + + while (count++) + { + rt_pin_write(LED2_PIN, PIN_HIGH); + rt_thread_mdelay(500); + rt_pin_write(LED2_PIN, PIN_LOW); + rt_thread_mdelay(500); + } + + return RT_EOK; +} diff --git a/bsp/gd32/gd32105r-start/board/Kconfig b/bsp/gd32/gd32105r-start/board/Kconfig new file mode 100644 index 0000000000..deda10f857 --- /dev/null +++ b/bsp/gd32/gd32105r-start/board/Kconfig @@ -0,0 +1,126 @@ +menu "Hardware Drivers Config" + +config SOC_SERIES_GD32F10x + bool + default y + +config SOC_GD32105R + bool + select SOC_SERIES_GD32F10x + select RT_USING_COMPONENTS_INIT + select RT_USING_USER_MAIN + default y + +menu "Onboard Peripheral Drivers" + +endmenu + +menu "On-chip Peripheral Drivers" + + config BSP_USING_GPIO + bool "Enable GPIO" + select RT_USING_PIN + default y + + menuconfig BSP_USING_UART + bool "Enable UART" + default y + select RT_USING_SERIAL + if BSP_USING_UART + config BSP_USING_UART1 + bool "Enable UART1" + default y + + config BSP_UART1_RX_USING_DMA + bool "Enable UART1 RX DMA" + depends on BSP_USING_UART1 && RT_SERIAL_USING_DMA + default n + endif + + menuconfig BSP_USING_ADC + bool "Enable ADC" + default n + select RT_USING_ADC + if BSP_USING_ADC + config BSP_USING_ADC0 + bool "using adc0" + default n + config BSP_USING_ADC1 + bool "using adc1" + default n + endif + + menuconfig BSP_USING_SPI + bool "Enable SPI BUS" + default n + select RT_USING_SPI + if BSP_USING_SPI + config BSP_USING_SPI0 + bool "Enable SPI0 BUS" + default n + config BSP_USING_SPI1 + bool "Enable SPI1 BUS" + default n + config BSP_USING_SPI2 + bool "Enable SPI2 BUS" + default n + endif + + menuconfig BSP_USING_I2C1 + bool "Enable I2C1 BUS (software simulation)" + default n + select RT_USING_I2C + select RT_USING_I2C_BITOPS + select RT_USING_PIN + if BSP_USING_I2C1 + config BSP_I2C1_SCL_PIN + int "i2c1 scl pin number" + range 1 216 + default 24 + config BSP_I2C1_SDA_PIN + int "I2C1 sda pin number" + range 1 216 + default 25 + endif + + menuconfig BSP_USING_TIM + bool "Enable timer" + default n + select RT_USING_HWTIMER + if BSP_USING_TIM + config BSP_USING_TIM10 + bool "Enable TIM10" + default n + + config BSP_USING_TIM11 + bool "Enable TIM11" + default n + + config BSP_USING_TIM12 + bool "Enable TIM12" + default n + + config BSP_USING_TIM13 + bool "Enable TIM13" + default n + endif + + config BSP_USING_WDT + bool "Enable Watchdog Timer" + select RT_USING_WDT + default n + + config BSP_USING_RTC + bool "using internal rtc" + default n + select RT_USING_RTC + + source "../libraries/gd32_drivers/Kconfig" + +endmenu + +menu "Board extended module Drivers" + +endmenu + +endmenu diff --git a/bsp/gd32/gd32105r-start/board/SConscript b/bsp/gd32/gd32105r-start/board/SConscript new file mode 100644 index 0000000000..c1f4a6001b --- /dev/null +++ b/bsp/gd32/gd32105r-start/board/SConscript @@ -0,0 +1,28 @@ +import os +import rtconfig +from building import * + +Import('SDK_LIB') + +cwd = GetCurrentDir() + +# add general drivers +src = Split(''' +board.c +''') + +path = [cwd] + +startup_path_prefix = SDK_LIB + +if rtconfig.CROSS_TOOL == 'gcc': + src += [startup_path_prefix + '/GD32F10x_Firmware_Library/CMSIS/GD/GD32F10x/Source/GCC/startup_gd32f10x_cl.s'] +elif rtconfig.CROSS_TOOL == 'keil': + src += [startup_path_prefix + '/GD32F10x_Firmware_Library/CMSIS/GD/GD32F10x/Source/ARM/startup_gd32f10x_cl.s'] +elif rtconfig.CROSS_TOOL == 'iar': + src += [startup_path_prefix + '/GD32F10x_Firmware_Library/CMSIS/GD/GD32F10x/Source/IAR/startup_gd32f10x_cl.s'] + +CPPDEFINES = ['GD32F10X_CL'] +group = DefineGroup('Drivers', src, depend = [''], CPPPATH = path, CPPDEFINES = CPPDEFINES) + +Return('group') diff --git a/bsp/gd32/gd32105r-start/board/board.c b/bsp/gd32/gd32105r-start/board/board.c new file mode 100644 index 0000000000..4a7c61b8cf --- /dev/null +++ b/bsp/gd32/gd32105r-start/board/board.c @@ -0,0 +1,85 @@ +/* + * Copyright (c) 2006-2022, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2021-12-18 BruceOu first implementation + */ +#include +#include +#include +#include + +/** + * @brief This function is executed in case of error occurrence. + * @param None + * @retval None + */ +void Error_Handler(void) +{ + /* USER CODE BEGIN Error_Handler */ + /* User can add his own implementation to report the HAL error return state */ + while (1) + { + } + /* USER CODE END Error_Handler */ +} + +/** System Clock Configuration +*/ +void SystemClock_Config(void) +{ + SysTick_Config(SystemCoreClock / RT_TICK_PER_SECOND); + NVIC_SetPriority(SysTick_IRQn, 0); +} + +/** + * This is the timer interrupt service routine. + * + */ +void SysTick_Handler(void) +{ + /* enter interrupt */ + rt_interrupt_enter(); + + rt_tick_increase(); + + /* leave interrupt */ + rt_interrupt_leave(); +} + +/** + * This function will initial GD32 board. + */ +void rt_hw_board_init() +{ + /* NVIC Configuration */ +#define NVIC_VTOR_MASK 0x3FFFFF80 +#ifdef VECT_TAB_RAM + /* Set the Vector Table base location at 0x10000000 */ + SCB->VTOR = (0x10000000 & NVIC_VTOR_MASK); +#else /* VECT_TAB_FLASH */ + /* Set the Vector Table base location at 0x08000000 */ + SCB->VTOR = (0x08000000 & NVIC_VTOR_MASK); +#endif + + SystemClock_Config(); + +#ifdef RT_USING_COMPONENTS_INIT + rt_components_board_init(); +#endif + +#ifdef RT_USING_CONSOLE + rt_console_set_device(RT_CONSOLE_DEVICE_NAME); +#endif + +#ifdef BSP_USING_SDRAM + rt_system_heap_init((void *)EXT_SDRAM_BEGIN, (void *)EXT_SDRAM_END); +#else + rt_system_heap_init((void *)HEAP_BEGIN, (void *)HEAP_END); +#endif +} + +/*@}*/ diff --git a/bsp/gd32/gd32105r-start/board/board.h b/bsp/gd32/gd32105r-start/board/board.h new file mode 100644 index 0000000000..eb89837241 --- /dev/null +++ b/bsp/gd32/gd32105r-start/board/board.h @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2006-2022, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2021-12-18 BruceOu first implementation + */ +#ifndef __BOARD_H__ +#define __BOARD_H__ + +#include "gd32f10x.h" +#include "drv_usart.h" +#include "drv_gpio.h" +#include "gd32f10x_exti.h" + +#define EXT_SDRAM_BEGIN (0xC0000000U) /* the begining address of external SDRAM */ +#define EXT_SDRAM_END (EXT_SDRAM_BEGIN + (32U * 1024 * 1024)) /* the end address of external SDRAM */ + +// Internal SRAM memory size[Kbytes] <8-96> +// Default: 96 +#ifdef __ICCARM__ +// Use *.icf ram symbal, to avoid hardcode. +extern char __ICFEDIT_region_RAM_end__; +#define GD32_SRAM_END &__ICFEDIT_region_RAM_end__ +#else +#define GD32_SRAM_SIZE 96 +#define GD32_SRAM_END (0x20000000 + GD32_SRAM_SIZE * 1024) +#endif + +#ifdef __CC_ARM +extern int Image$$RW_IRAM1$$ZI$$Limit; +#define HEAP_BEGIN (&Image$$RW_IRAM1$$ZI$$Limit) +#elif __ICCARM__ +#pragma section="HEAP" +#define HEAP_BEGIN (__segment_end("HEAP")) +#else +extern int __bss_end; +#define HEAP_BEGIN (&__bss_end) +#endif + +#define HEAP_END GD32_SRAM_END + +#endif + diff --git a/bsp/gd32/gd32105r-start/board/gd32f10x_libopt.h b/bsp/gd32/gd32105r-start/board/gd32f10x_libopt.h new file mode 100644 index 0000000000..5292c8eca7 --- /dev/null +++ b/bsp/gd32/gd32105r-start/board/gd32f10x_libopt.h @@ -0,0 +1,64 @@ +/*! + \file gd32f10x_libopt.h + \brief library optional for gd32f10x + + \version 2014-12-26, V1.0.0, demo for GD32F10x + \version 2017-06-30, V2.0.0, demo for GD32F10x + \version 2021-04-30, V2.1.0, demo for GD32F10x +*/ + +/* + Copyright (c) 2021, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef GD32F10X_LIBOPT_H +#define GD32F10X_LIBOPT_H + +#include "gd32f10x_fmc.h" +#include "gd32f10x_pmu.h" +#include "gd32f10x_bkp.h" +#include "gd32f10x_rcu.h" +#include "gd32f10x_exti.h" +#include "gd32f10x_gpio.h" +#include "gd32f10x_crc.h" +#include "gd32f10x_dma.h" +#include "gd32f10x_dbg.h" +#include "gd32f10x_adc.h" +#include "gd32f10x_dac.h" +#include "gd32f10x_fwdgt.h" +#include "gd32f10x_wwdgt.h" +#include "gd32f10x_rtc.h" +#include "gd32f10x_timer.h" +#include "gd32f10x_usart.h" +#include "gd32f10x_i2c.h" +#include "gd32f10x_spi.h" +#include "gd32f10x_sdio.h" +#include "gd32f10x_exmc.h" +#include "gd32f10x_can.h" +#include "gd32f10x_enet.h" +#include "gd32f10x_misc.h" + +#endif /* GD32F10X_LIBOPT_H */ diff --git a/bsp/gd32/gd32105r-start/board/linker_scripts/link.icf b/bsp/gd32/gd32105r-start/board/linker_scripts/link.icf new file mode 100644 index 0000000000..283881a728 --- /dev/null +++ b/bsp/gd32/gd32105r-start/board/linker_scripts/link.icf @@ -0,0 +1,40 @@ +/*###ICF### Section handled by ICF editor, don't touch! ****/ +/*-Editor annotation file-*/ +/* IcfEditorFile="$TOOLKIT_DIR$\config\ide\IcfEditor\cortex_v1_0.xml" */ +/*-Specials-*/ +define symbol __ICFEDIT_intvec_start__ = 0x08000000; +/*-Memory Regions-*/ +define symbol __ICFEDIT_region_ROM_start__ = 0x08000000; +define symbol __ICFEDIT_region_ROM_end__ = 0x0803FFFF; +define symbol __ICFEDIT_region_RAM_start__ = 0x20000000; +define symbol __ICFEDIT_region_RAM_end__ = 0x20017FFF; +/*-Sizes-*/ +define symbol __ICFEDIT_size_cstack__ = 0x200; +define symbol __ICFEDIT_size_heap__ = 0x200; +/**** End of ICF editor section. ###ICF###*/ + +export symbol __ICFEDIT_region_RAM_end__; + +define symbol __region_RAM1_start__ = 0x10000000; +define symbol __region_RAM1_end__ = 0x1000FFFF; + +define memory mem with size = 4G; +define region ROM_region = mem:[from __ICFEDIT_region_ROM_start__ to __ICFEDIT_region_ROM_end__]; +define region RAM_region = mem:[from __ICFEDIT_region_RAM_start__ to __ICFEDIT_region_RAM_end__]; +define region RAM1_region = mem:[from __region_RAM1_start__ to __region_RAM1_end__]; + +define block CSTACK with alignment = 8, size = __ICFEDIT_size_cstack__ { }; +define block HEAP with alignment = 8, size = __ICFEDIT_size_heap__ { }; + +initialize by copy { readwrite }; +do not initialize { section .noinit }; + +keep { section FSymTab }; +keep { section VSymTab }; +keep { section .rti_fn* }; +place at address mem:__ICFEDIT_intvec_start__ { readonly section .intvec }; + +place in ROM_region { readonly }; +place in RAM_region { readwrite, + block CSTACK, block HEAP }; +place in RAM1_region { section .sram }; \ No newline at end of file diff --git a/bsp/gd32/gd32105r-start/board/linker_scripts/link.ld b/bsp/gd32/gd32105r-start/board/linker_scripts/link.ld new file mode 100644 index 0000000000..8ba4a0e9f2 --- /dev/null +++ b/bsp/gd32/gd32105r-start/board/linker_scripts/link.ld @@ -0,0 +1,142 @@ +/* + * linker script for GD32F30x with GNU ld + * BruceOu 2021-12-14 + */ + +/* Program Entry, set to mark it as "used" and avoid gc */ +MEMORY +{ + CODE (rx) : ORIGIN = 0x08000000, LENGTH = 256k /* 256KB flash */ + DATA (rw) : ORIGIN = 0x20000000, LENGTH = 96k /* 96KB sram */ +} +ENTRY(Reset_Handler) +_system_stack_size = 0x200; + +SECTIONS +{ + .text : + { + . = ALIGN(4); + _stext = .; + KEEP(*(.isr_vector)) /* Startup code */ + . = ALIGN(4); + *(.text) /* remaining code */ + *(.text.*) /* remaining code */ + *(.rodata) /* read-only data (constants) */ + *(.rodata*) + *(.glue_7) + *(.glue_7t) + *(.gnu.linkonce.t*) + + /* section information for finsh shell */ + . = ALIGN(4); + __fsymtab_start = .; + KEEP(*(FSymTab)) + __fsymtab_end = .; + . = ALIGN(4); + __vsymtab_start = .; + KEEP(*(VSymTab)) + __vsymtab_end = .; + . = ALIGN(4); + + /* section information for initial. */ + . = ALIGN(4); + __rt_init_start = .; + KEEP(*(SORT(.rti_fn*))) + __rt_init_end = .; + . = ALIGN(4); + + . = ALIGN(4); + _etext = .; + } > CODE = 0 + + /* .ARM.exidx is sorted, so has to go in its own output section. */ + __exidx_start = .; + .ARM.exidx : + { + *(.ARM.exidx* .gnu.linkonce.armexidx.*) + + /* This is used by the startup in order to initialize the .data secion */ + _sidata = .; + } > CODE + __exidx_end = .; + + /* .data section which is used for initialized data */ + + .data : AT (_sidata) + { + . = ALIGN(4); + /* This is used by the startup in order to initialize the .data secion */ + _sdata = . ; + + *(.data) + *(.data.*) + *(.gnu.linkonce.d*) + + . = ALIGN(4); + /* This is used by the startup in order to initialize the .data secion */ + _edata = . ; + } >DATA + + .stack : + { + . = . + _system_stack_size; + . = ALIGN(4); + _estack = .; + } >DATA + + __bss_start = .; + .bss : + { + . = ALIGN(4); + /* This is used by the startup in order to initialize the .bss secion */ + _sbss = .; + + *(.bss) + *(.bss.*) + *(COMMON) + + . = ALIGN(4); + /* This is used by the startup in order to initialize the .bss secion */ + _ebss = . ; + + *(.bss.init) + } > DATA + __bss_end = .; + + _end = .; + + /* Stabs debugging sections. */ + .stab 0 : { *(.stab) } + .stabstr 0 : { *(.stabstr) } + .stab.excl 0 : { *(.stab.excl) } + .stab.exclstr 0 : { *(.stab.exclstr) } + .stab.index 0 : { *(.stab.index) } + .stab.indexstr 0 : { *(.stab.indexstr) } + .comment 0 : { *(.comment) } + /* DWARF debug sections. + * Symbols in the DWARF debugging sections are relative to the beginning + * of the section so we begin them at 0. */ + /* DWARF 1 */ + .debug 0 : { *(.debug) } + .line 0 : { *(.line) } + /* GNU DWARF 1 extensions */ + .debug_srcinfo 0 : { *(.debug_srcinfo) } + .debug_sfnames 0 : { *(.debug_sfnames) } + /* DWARF 1.1 and DWARF 2 */ + .debug_aranges 0 : { *(.debug_aranges) } + .debug_pubnames 0 : { *(.debug_pubnames) } + /* DWARF 2 */ + .debug_info 0 : { *(.debug_info .gnu.linkonce.wi.*) } + .debug_abbrev 0 : { *(.debug_abbrev) } + .debug_line 0 : { *(.debug_line) } + .debug_frame 0 : { *(.debug_frame) } + .debug_str 0 : { *(.debug_str) } + .debug_loc 0 : { *(.debug_loc) } + .debug_macinfo 0 : { *(.debug_macinfo) } + /* SGI/MIPS DWARF 2 extensions */ + .debug_weaknames 0 : { *(.debug_weaknames) } + .debug_funcnames 0 : { *(.debug_funcnames) } + .debug_typenames 0 : { *(.debug_typenames) } + .debug_varnames 0 : { *(.debug_varnames) } +} diff --git a/bsp/gd32/gd32105r-start/board/linker_scripts/link.sct b/bsp/gd32/gd32105r-start/board/linker_scripts/link.sct new file mode 100644 index 0000000000..0529ba2b9c --- /dev/null +++ b/bsp/gd32/gd32105r-start/board/linker_scripts/link.sct @@ -0,0 +1,15 @@ +; ************************************************************* +; *** Scatter-Loading Description File generated by uVision *** +; ************************************************************* + +LR_IROM1 0x08000000 0x00040000 { ; load region size_region + ER_IROM1 0x08000000 0x00040000 { ; load address = execution address + *.o (RESET, +First) + *(InRoot$$Sections) + .ANY (+RO) + } + RW_IRAM1 0x20000000 0x00018000 { ; RW data + .ANY (+RW +ZI) + } +} + diff --git a/bsp/gd32/gd32105r-start/figures/board.jpg b/bsp/gd32/gd32105r-start/figures/board.jpg new file mode 100644 index 0000000000..f892317dcd Binary files /dev/null and b/bsp/gd32/gd32105r-start/figures/board.jpg differ diff --git a/bsp/gd32/gd32105r-start/project.uvoptx b/bsp/gd32/gd32105r-start/project.uvoptx new file mode 100644 index 0000000000..c41712a0e7 --- /dev/null +++ b/bsp/gd32/gd32105r-start/project.uvoptx @@ -0,0 +1,180 @@ + + + + 1.0 + +
### uVision Project, (C) Keil Software
+ + + *.c + *.s*; *.src; *.a* + *.obj; *.o + *.lib + *.txt; *.h; *.inc + *.plm + *.cpp + 0 + + + + 0 + 0 + + + + rt-thread + 0x4 + ARM-ADS + + 10800000 + + 1 + 1 + 0 + 1 + 0 + + + 1 + 65535 + 0 + 0 + 0 + + + 79 + 66 + 8 + .\build\ + + + 1 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 0 + 0 + 0 + 0 + + + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 0 + 0 + + + 0 + 0 + 1 + + 255 + + 0 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 0 + 1 + 1 + 1 + 1 + 0 + 0 + 1 + 0 + 0 + 3 + + + + + + + + + + + BIN\CMSIS_AGDI.dll + + + + 0 + UL2CM3 + UL2CM3(-S0 -C0 -P0 -FD20000000 -FC1000 -FN1 -FF0GD32F10x_CL -FS08000000 -FL040000 -FP0($$Device:GD32F105RC$Flash\GD32F10x_CL.FLM)) + + + + + 0 + + + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + + + + 0 + 0 + 0 + + + + + + + + + + + + + ::CMSIS + 0 + 0 + 0 + 1 + + +
diff --git a/bsp/gd32/gd32105r-start/project.uvproj b/bsp/gd32/gd32105r-start/project.uvproj new file mode 100644 index 0000000000..f7f70b89ee --- /dev/null +++ b/bsp/gd32/gd32105r-start/project.uvproj @@ -0,0 +1,737 @@ + + + 1.1 +
### uVision Project, (C) Keil Software
+ + + rt-thread_gd32f10x + 0x4 + ARM-ADS + 0 + + + GD32F105RC + GigaDevice + IRAM(0x20000000-0x200018000) IROM(0x08000000-0x08040000) CLOCK(10800000) CPUTYPE("Cortex-M3") + + "Startup\GD\GD32F10x\startup_gd32f10x.s" ("GD32F10x Startup Code") + UL2CM3(-O207 -S0 -C0 -FO7 -FD20000000 -FC800 -FN1 -FF0GD32F10x_3MB -FS08000000 -FL0100000) + 0 + gd32f10x0.h + + + + + + + + + + SFD\GD\GD32F10x\GD32F10x.SFR + 0 + 0 + + + + GD\GD32F10x\ + GD\GD32F10x\ + + 0 + 0 + 0 + 0 + 1 + + .\output\ + rtthread-gd32f10x + 1 + 0 + 1 + 1 + 1 + .\build\ + 1 + 0 + 0 + + 0 + 0 + + + 0 + 0 + 0 + 0 + + + 0 + 0 + + + 0 + 0 + 0 + 0 + + + 0 + 0 + + + 0 + 0 + 0 + 0 + + 0 + + + + 0 + 0 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 0 + 3 + + + 1 + + + SARMCM3.DLL + -REMAP + DCM.DLL + -pCM3 + SARMCM3.DLL + + TCM.DLL + -pCM3 + + + + 1 + 0 + 0 + 0 + 16 + + + 0 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 0 + 1 + + + 1 + 1 + 1 + 1 + 1 + 1 + 0 + 1 + 0 + 1 + + 0 + 3 + + + + + + + + + + + + + + BIN\CMSIS_AGDI.dll + + + + + 1 + 0 + 0 + 1 + 1 + 4096 + + 1 + BIN\UL2CM3.DLL + "" () + + + + + 0 + + + + 0 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 0 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 0 + 0 + "Cortex-M3" + + 0 + 0 + 0 + 1 + 1 + 0 + 0 + 2 + 1 + 0 + 8 + 1 + 0 + 0 + 0 + 3 + 3 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 0 + 1 + 0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x20000000 + 0x10000 + + + 1 + 0x8000000 + 0x100000 + + + 0 + 0x0 + 0x0 + + + 1 + 0x0 + 0x0 + + + 1 + 0x0 + 0x0 + + + 1 + 0x0 + 0x0 + + + 1 + 0x8000000 + 0x100000 + + + 1 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x20000000 + 0x10000 + + + 0 + 0x10000000 + 0x10000 + + + + + + 1 + 1 + 0 + 0 + 1 + 0 + 0 + 0 + 0 + 0 + 2 + 0 + 0 + 1 + 0 + 0 + 1 + 1 + 1 + 1 + 0 + 0 + 0 + + + GD32F105xx, USE_STDPERIPH_DRIVER, __RTTHREAD__, __CLK_TCK=RT_TICK_PER_SECOND + + applications;.;..\..\..\libcpu\arm\common;..\..\..\libcpu\arm\cortex-m4;..\..\..\components\drivers\include;..\..\..\components\drivers\include;..\..\..\components\drivers\include;board;..\libraries\gd32_drivers;..\..\..\components\finsh;.;..\..\..\include;..\..\..\components\libc\compilers\common;..\..\..\components\libc\compilers\common\nogcc;..\libraries\GD32F10x_Firmware_Library\CMSIS\GD\GD32F10x\Include;..\libraries\GD32F10x_Firmware_Library\CMSIS;..\libraries\GD32F10x_Firmware_Library\GD32F10x_standard_peripheral\Include;..\..\..\examples\utest\testcases\kernel + + + + 1 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + + + + + + + + + 1 + 0 + 0 + 0 + 1 + 0 + 0x08000000 + 0x20000000 + + + + + + + + + + + + + Applications + + + main.c + 1 + applications\main.c + + + + + CPU + + + backtrace.c + 1 + ..\..\..\libcpu\arm\common\backtrace.c + + + + + div0.c + 1 + ..\..\..\libcpu\arm\common\div0.c + + + + + showmem.c + 1 + ..\..\..\libcpu\arm\common\showmem.c + + + + + cpuport.c + 1 + ..\..\..\libcpu\arm\cortex-m4\cpuport.c + + + + + context_rvds.S + 2 + ..\..\..\libcpu\arm\cortex-m4\context_rvds.S + + + + + DeviceDrivers + + + pin.c + 1 + ..\..\..\components\drivers\misc\pin.c + + + + + serial.c + 1 + ..\..\..\components\drivers\serial\serial.c + + + + + workqueue.c + 1 + ..\..\..\components\drivers\src\workqueue.c + + + + + waitqueue.c + 1 + ..\..\..\components\drivers\src\waitqueue.c + + + + + ringbuffer.c + 1 + ..\..\..\components\drivers\src\ringbuffer.c + + + + + dataqueue.c + 1 + ..\..\..\components\drivers\src\dataqueue.c + + + + + ringblk_buf.c + 1 + ..\..\..\components\drivers\src\ringblk_buf.c + + + + + pipe.c + 1 + ..\..\..\components\drivers\src\pipe.c + + + + + completion.c + 1 + ..\..\..\components\drivers\src\completion.c + + + + + Drivers + + + startup_gd32f10x.s + 2 + ..\libraries\GD32F10x_Firmware_Library\CMSIS\GD\GD32F10x\Source\ARM\startup_gd32f10x.s + + + + + board.c + 1 + board\board.c + + + + + drv_gpio.c + 1 + ..\libraries\gd32_drivers\drv_gpio.c + + + + + drv_usart.c + 1 + ..\libraries\gd32_drivers\drv_usart.c + + + + + Finsh + + + shell.c + 1 + ..\..\..\components\finsh\shell.c + + + + + msh.c + 1 + ..\..\..\components\finsh\msh.c + + + + + cmd.c + 1 + ..\..\..\components\finsh\cmd.c + + + + + Kernel + + + thread.c + 1 + ..\..\..\src\thread.c + + + + + irq.c + 1 + ..\..\..\src\irq.c + + + + + scheduler.c + 1 + ..\..\..\src\scheduler.c + + + + + ipc.c + 1 + ..\..\..\src\ipc.c + + + + + clock.c + 1 + ..\..\..\src\clock.c + + + + + timer.c + 1 + ..\..\..\src\timer.c + + + + + mempool.c + 1 + ..\..\..\src\mempool.c + + + + + idle.c + 1 + ..\..\..\src\idle.c + + + + + device.c + 1 + ..\..\..\src\device.c + + + + + object.c + 1 + ..\..\..\src\object.c + + + + + kservice.c + 1 + ..\..\..\src\kservice.c + + + + + components.c + 1 + ..\..\..\src\components.c + + + + + mem.c + 1 + ..\..\..\src\mem.c + + + + + libc + + + time.c + 1 + ..\..\..\components\libc\compilers\common\time.c + + + + + Libraries + + + gd32f10x_exti.c + 1 + ..\libraries\GD32F10x_Firmware_Library\GD32F10x_standard_peripheral\Source\gd32f10x_exti.c + + + + + gd32f10x_gpio.c + 1 + ..\libraries\GD32F10x_Firmware_Library\GD32F10x_standard_peripheral\Source\gd32f10x_gpio.c + + + + + gd32f10x_rcu.c + 1 + ..\libraries\GD32F10x_Firmware_Library\GD32F10x_standard_peripheral\Source\gd32f10x_rcu.c + + + + + gd32f10x_misc.c + 1 + ..\libraries\GD32F10x_Firmware_Library\GD32F10x_standard_peripheral\Source\gd32f10x_misc.c + + + + + gd32f10x_usart.c + 1 + ..\libraries\GD32F10x_Firmware_Library\GD32F10x_standard_peripheral\Source\gd32f10x_usart.c + + + + + system_gd32f10x.c + 1 + ..\libraries\GD32F10x_Firmware_Library\CMSIS\GD\GD32F10x\Source\system_gd32f10x.c + + + + + + +
diff --git a/bsp/gd32/gd32105r-start/project.uvprojx b/bsp/gd32/gd32105r-start/project.uvprojx new file mode 100644 index 0000000000..14ba7f7137 --- /dev/null +++ b/bsp/gd32/gd32105r-start/project.uvprojx @@ -0,0 +1,769 @@ + + + 2.1 +
### uVision Project, (C) Keil Software
+ + + rt-thread + 0x4 + ARM-ADS + 5060750::V5.06 update 6 (build 750)::.\ARMCC + 0 + + + GD32F105RC + GigaDevice + GigaDevice.GD32F10x_DFP.2.0.1 + http://www.keil.com/pack/ + IRAM(0x20000000,0x00018000) IROM(0x08000000,0x00040000) CPUTYPE("Cortex-M3") CLOCK(10800000) ELITTLE + + + UL2CM3(-S0 -C0 -P0 -FD20000000 -FC1000 -FN1 -FF0GD32F10x_CL -FS08000000 -FL040000 -FP0($$Device:GD32F105RC$Flash\GD32F10x_CL.FLM)) + 0 + $$Device:GD32F105RC$Device\Include\gd32f10x.h + + + + + + + + + + $$Device:GD32F105RC$SVD\GD32F10x\GD32F10x_CL.svd + 0 + 0 + + + + + + + 0 + 0 + 0 + 0 + 1 + + .\build\ + rtthread + 1 + 0 + 0 + 1 + 0 + .\build\ + 1 + 0 + 0 + + 0 + 0 + + + 0 + 0 + 0 + 0 + + + 0 + 0 + + + 0 + 0 + 0 + 0 + + + 1 + 0 + fromelf --bin !L --output rtthread.bin + + 0 + 0 + 0 + 0 + + 0 + + + + 0 + 0 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 0 + 3 + + + 1 + + + SARMCM3.DLL + -REMAP + DCM.DLL + -pCM3 + SARMCM3.DLL + + TCM.DLL + -pCM3 + + + + 1 + 0 + 0 + 0 + 16 + + + + + 1 + 0 + 0 + 1 + 1 + 4096 + + 1 + BIN\UL2CM3.DLL + + + + + + 0 + + + + 0 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 0 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 0 + 0 + "Cortex-M3" + + 0 + 0 + 0 + 1 + 1 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 8 + 0 + 0 + 0 + 0 + 3 + 3 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 0 + 1 + 0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x20000000 + 0x18000 + + + 1 + 0x8000000 + 0x40000 + + + 0 + 0x0 + 0x0 + + + 1 + 0x0 + 0x0 + + + 1 + 0x0 + 0x0 + + + 1 + 0x0 + 0x0 + + + 1 + 0x8000000 + 0x40000 + + + 1 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x20000000 + 0x18000 + + + 0 + 0x0 + 0x0 + + + + + + 1 + 4 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 1 + 0 + 0 + 1 + 1 + 1 + 1 + 0 + 0 + 0 + + + GD32F10X_CL, USE_STDPERIPH_DRIVER, __RTTHREAD__, __CLK_TCK=RT_TICK_PER_SECOND + + applications;.;..\..\..\libcpu\arm\common;..\..\..\libcpu\arm\cortex-m3;..\..\..\components\drivers\include;..\..\..\components\drivers\include;..\..\..\components\drivers\include;..\..\..\components\drivers\include;board;..\libraries\gd32_drivers;..\..\..\components\finsh;.;..\..\..\include;..\..\..\components\libc\compilers\common;..\..\..\components\libc\compilers\common\nogcc;..\libraries\GD32F10x_Firmware_Library\CMSIS\GD\GD32F10x\Include;..\libraries\GD32F10x_Firmware_Library\CMSIS;..\libraries\GD32F10x_Firmware_Library\GD32F10x_standard_peripheral\Include;..\..\..\components\libc\posix\io\poll;..\..\..\components\libc\posix\ipc;..\..\..\examples\utest\testcases\kernel + + + + 1 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 4 + + + + + + + + + 1 + 0 + 0 + 0 + 1 + 0 + 0x08000000 + 0x20000000 + + .\gd32_rom.ld + + + + + + + + + + + Applications + + + main.c + 1 + applications\main.c + + + + + CPU + + + backtrace.c + 1 + ..\..\..\libcpu\arm\common\backtrace.c + + + + + showmem.c + 1 + ..\..\..\libcpu\arm\common\showmem.c + + + + + div0.c + 1 + ..\..\..\libcpu\arm\common\div0.c + + + + + cpuport.c + 1 + ..\..\..\libcpu\arm\cortex-m3\cpuport.c + + + + + context_rvds.S + 2 + ..\..\..\libcpu\arm\cortex-m3\context_rvds.S + + + + + DeviceDrivers + + + i2c_core.c + 1 + ..\..\..\components\drivers\i2c\i2c_core.c + + + + + i2c_dev.c + 1 + ..\..\..\components\drivers\i2c\i2c_dev.c + + + + + i2c-bit-ops.c + 1 + ..\..\..\components\drivers\i2c\i2c-bit-ops.c + + + + + adc.c + 1 + ..\..\..\components\drivers\misc\adc.c + + + + + pin.c + 1 + ..\..\..\components\drivers\misc\pin.c + + + + + serial.c + 1 + ..\..\..\components\drivers\serial\serial.c + + + + + dataqueue.c + 1 + ..\..\..\components\drivers\src\dataqueue.c + + + + + waitqueue.c + 1 + ..\..\..\components\drivers\src\waitqueue.c + + + + + completion.c + 1 + ..\..\..\components\drivers\src\completion.c + + + + + ringbuffer.c + 1 + ..\..\..\components\drivers\src\ringbuffer.c + + + + + workqueue.c + 1 + ..\..\..\components\drivers\src\workqueue.c + + + + + ringblk_buf.c + 1 + ..\..\..\components\drivers\src\ringblk_buf.c + + + + + pipe.c + 1 + ..\..\..\components\drivers\src\pipe.c + + + + + Drivers + + + startup_gd32f10x_cl.s + 2 + ..\libraries\GD32F10x_Firmware_Library\CMSIS\GD\GD32F10x\Source\ARM\startup_gd32f10x_cl.s + + + + + board.c + 1 + board\board.c + + + + + drv_gpio.c + 1 + ..\libraries\gd32_drivers\drv_gpio.c + + + + + drv_usart.c + 1 + ..\libraries\gd32_drivers\drv_usart.c + + + + + Finsh + + + shell.c + 1 + ..\..\..\components\finsh\shell.c + + + + + msh.c + 1 + ..\..\..\components\finsh\msh.c + + + + + cmd.c + 1 + ..\..\..\components\finsh\cmd.c + + + + + Kernel + + + mempool.c + 1 + ..\..\..\src\mempool.c + + + + + idle.c + 1 + ..\..\..\src\idle.c + + + + + device.c + 1 + ..\..\..\src\device.c + + + + + timer.c + 1 + ..\..\..\src\timer.c + + + + + ipc.c + 1 + ..\..\..\src\ipc.c + + + + + kservice.c + 1 + ..\..\..\src\kservice.c + + + + + clock.c + 1 + ..\..\..\src\clock.c + + + + + irq.c + 1 + ..\..\..\src\irq.c + + + + + thread.c + 1 + ..\..\..\src\thread.c + + + + + mem.c + 1 + ..\..\..\src\mem.c + + + + + object.c + 1 + ..\..\..\src\object.c + + + + + scheduler.c + 1 + ..\..\..\src\scheduler.c + + + + + components.c + 1 + ..\..\..\src\components.c + + + + + libc + + + time.c + 1 + ..\..\..\components\libc\compilers\common\time.c + + + + + Libraries + + + gd32f10x_exti.c + 1 + ..\libraries\GD32F10x_Firmware_Library\GD32F10x_standard_peripheral\Source\gd32f10x_exti.c + + + + + gd32f10x_gpio.c + 1 + ..\libraries\GD32F10x_Firmware_Library\GD32F10x_standard_peripheral\Source\gd32f10x_gpio.c + + + + + gd32f10x_misc.c + 1 + ..\libraries\GD32F10x_Firmware_Library\GD32F10x_standard_peripheral\Source\gd32f10x_misc.c + + + + + system_gd32f10x.c + 1 + ..\libraries\GD32F10x_Firmware_Library\CMSIS\GD\GD32F10x\Source\system_gd32f10x.c + + + + + gd32f10x_rcu.c + 1 + ..\libraries\GD32F10x_Firmware_Library\GD32F10x_standard_peripheral\Source\gd32f10x_rcu.c + + + + + gd32f10x_adc.c + 1 + ..\libraries\GD32F10x_Firmware_Library\GD32F10x_standard_peripheral\Source\gd32f10x_adc.c + + + + + gd32f10x_i2c.c + 1 + ..\libraries\GD32F10x_Firmware_Library\GD32F10x_standard_peripheral\Source\gd32f10x_i2c.c + + + + + gd32f10x_usart.c + 1 + ..\libraries\GD32F10x_Firmware_Library\GD32F10x_standard_peripheral\Source\gd32f10x_usart.c + + + + + + + + + + + + + + + + + + + + + + <Project Info> + + + + + + 0 + 1 + + + +
diff --git a/bsp/gd32/gd32105r-start/rtconfig.h b/bsp/gd32/gd32105r-start/rtconfig.h new file mode 100644 index 0000000000..7f89e63117 --- /dev/null +++ b/bsp/gd32/gd32105r-start/rtconfig.h @@ -0,0 +1,212 @@ +#ifndef RT_CONFIG_H__ +#define RT_CONFIG_H__ + +/* Automatically generated file; DO NOT EDIT. */ +/* RT-Thread Configuration */ + +/* RT-Thread Kernel */ + +#define RT_NAME_MAX 8 +#define RT_ALIGN_SIZE 4 +#define RT_THREAD_PRIORITY_32 +#define RT_THREAD_PRIORITY_MAX 32 +#define RT_TICK_PER_SECOND 100 +#define RT_USING_OVERFLOW_CHECK +#define RT_USING_HOOK +#define RT_USING_IDLE_HOOK +#define RT_IDLE_HOOK_LIST_SIZE 4 +#define IDLE_THREAD_STACK_SIZE 256 + +/* kservice optimization */ + +#define RT_DEBUG +#define RT_DEBUG_COLOR + +/* Inter-Thread communication */ + +#define RT_USING_SEMAPHORE +#define RT_USING_MUTEX +#define RT_USING_EVENT +#define RT_USING_MAILBOX +#define RT_USING_MESSAGEQUEUE + +/* Memory Management */ + +#define RT_USING_MEMPOOL +#define RT_USING_SMALL_MEM +#define RT_USING_SMALL_MEM_AS_HEAP +#define RT_USING_HEAP + +/* Kernel Device Object */ + +#define RT_USING_DEVICE +#define RT_USING_CONSOLE +#define RT_CONSOLEBUF_SIZE 128 +#define RT_CONSOLE_DEVICE_NAME "uart1" +#define RT_VER_NUM 0x40100 + +/* RT-Thread Components */ + +#define RT_USING_COMPONENTS_INIT +#define RT_USING_USER_MAIN +#define RT_MAIN_THREAD_STACK_SIZE 2048 +#define RT_MAIN_THREAD_PRIORITY 10 + +/* C++ features */ + + +/* Command shell */ + +#define RT_USING_FINSH +#define RT_USING_MSH +#define FINSH_USING_MSH +#define FINSH_THREAD_NAME "tshell" +#define FINSH_THREAD_PRIORITY 20 +#define FINSH_THREAD_STACK_SIZE 4096 +#define FINSH_USING_HISTORY +#define FINSH_HISTORY_LINES 5 +#define FINSH_USING_SYMTAB +#define FINSH_CMD_SIZE 80 +#define MSH_USING_BUILT_IN_COMMANDS +#define FINSH_USING_DESCRIPTION +#define FINSH_ARG_MAX 10 + +/* Device virtual file system */ + + +/* Device Drivers */ + +#define RT_USING_DEVICE_IPC +#define RT_USING_SYSTEM_WORKQUEUE +#define RT_SYSTEM_WORKQUEUE_STACKSIZE 2048 +#define RT_SYSTEM_WORKQUEUE_PRIORITY 23 +#define RT_USING_SERIAL +#define RT_USING_SERIAL_V1 +#define RT_SERIAL_USING_DMA +#define RT_SERIAL_RB_BUFSZ 64 +#define RT_USING_I2C +#define RT_USING_I2C_BITOPS +#define RT_USING_PIN +#define RT_USING_ADC + +/* Using USB */ + + +/* POSIX layer and C standard library */ + +#define RT_LIBC_USING_TIME +#define RT_LIBC_DEFAULT_TIMEZONE 8 + +/* POSIX (Portable Operating System Interface) layer */ + + +/* Interprocess Communication (IPC) */ + + +/* Socket is in the 'Network' category */ + +/* Network */ + +/* Socket abstraction layer */ + + +/* Network interface device */ + + +/* light weight TCP/IP stack */ + + +/* AT commands */ + + +/* VBUS(Virtual Software BUS) */ + + +/* Utilities */ + + +/* RT-Thread Utestcases */ + + +/* RT-Thread online packages */ + +/* IoT - internet of things */ + + +/* Wi-Fi */ + +/* Marvell WiFi */ + + +/* Wiced WiFi */ + + +/* IoT Cloud */ + + +/* security packages */ + + +/* language packages */ + + +/* multimedia packages */ + +/* LVGL: powerful and easy-to-use embedded GUI library */ + + +/* u8g2: a monochrome graphic library */ + + +/* PainterEngine: A cross-platform graphics application framework written in C language */ + + +/* tools packages */ + + +/* system packages */ + + +/* enhanced kernel services */ + + +/* acceleration: Assembly language or algorithmic acceleration packages */ + + +/* CMSIS: ARM Cortex-M Microcontroller Software Interface Standard */ + + +/* Micrium: Micrium software products porting for RT-Thread */ + + +/* peripheral libraries and drivers */ + + +/* AI packages */ + + +/* miscellaneous packages */ + +/* samples: kernel and components samples */ + + +/* entertainment: terminal games and other interesting software packages */ + + +/* Hardware Drivers Config */ + +#define SOC_SERIES_GD32F10x +#define SOC_GD32105R + +/* Onboard Peripheral Drivers */ + +/* On-chip Peripheral Drivers */ + +#define BSP_USING_GPIO +#define BSP_USING_UART +#define BSP_USING_UART1 + +/* Board extended module Drivers */ + + +#endif diff --git a/bsp/gd32/gd32105r-start/rtconfig.py b/bsp/gd32/gd32105r-start/rtconfig.py new file mode 100644 index 0000000000..1839e540bf --- /dev/null +++ b/bsp/gd32/gd32105r-start/rtconfig.py @@ -0,0 +1,150 @@ +import os + +# toolchains options +ARCH='arm' +CPU='cortex-m3' +CROSS_TOOL='keil' + +# bsp lib config +BSP_LIBRARY_TYPE = None + +if os.getenv('RTT_CC'): + CROSS_TOOL = os.getenv('RTT_CC') +if os.getenv('RTT_ROOT'): + RTT_ROOT = os.getenv('RTT_ROOT') + +# cross_tool provides the cross compiler +# EXEC_PATH is the compiler execute path, for example, CodeSourcery, Keil MDK, IAR +if CROSS_TOOL == 'gcc': + PLATFORM = 'gcc' + EXEC_PATH = r'C:\Users\XXYYZZ' +elif CROSS_TOOL == 'keil': + PLATFORM = 'armcc' + EXEC_PATH = r'C:/Keil_v5' +elif CROSS_TOOL == 'iar': + PLATFORM = 'iar' + EXEC_PATH = r'C:/Program Files (x86)/IAR Systems/Embedded Workbench 8.0' + +if os.getenv('RTT_EXEC_PATH'): + EXEC_PATH = os.getenv('RTT_EXEC_PATH') + +BUILD = 'debug' + +if PLATFORM == 'gcc': + # toolchains + PREFIX = 'arm-none-eabi-' + CC = PREFIX + 'gcc' + AS = PREFIX + 'gcc' + AR = PREFIX + 'ar' + CXX = PREFIX + 'g++' + LINK = PREFIX + 'gcc' + TARGET_EXT = 'elf' + SIZE = PREFIX + 'size' + OBJDUMP = PREFIX + 'objdump' + OBJCPY = PREFIX + 'objcopy' + + DEVICE = ' -mcpu=cortex-m3 -mthumb -ffunction-sections -fdata-sections' + CFLAGS = DEVICE + ' -Dgcc' + AFLAGS = ' -c' + DEVICE + ' -x assembler-with-cpp -Wa,-mimplicit-it=thumb ' + LFLAGS = DEVICE + ' -Wl,--gc-sections,-Map=rtthread.map,-cref,-u,Reset_Handler -T board/linker_scripts/link.ld' + + CPATH = '' + LPATH = '' + + if BUILD == 'debug': + CFLAGS += ' -O0 -gdwarf-2 -g' + AFLAGS += ' -gdwarf-2' + else: + CFLAGS += ' -O2' + + CXXFLAGS = CFLAGS + + POST_ACTION = OBJCPY + ' -O binary $TARGET rtthread.bin\n' + SIZE + ' $TARGET \n' + +elif PLATFORM == 'armcc': + # toolchains + CC = 'armcc' + CXX = 'armcc' + AS = 'armasm' + AR = 'armar' + LINK = 'armlink' + TARGET_EXT = 'axf' + + DEVICE = ' --cpu Cortex-M3.fp' + CFLAGS = '-c ' + DEVICE + ' --apcs=interwork --c99' + AFLAGS = DEVICE + ' --apcs=interwork ' + LFLAGS = DEVICE + ' --scatter "board\linker_scripts\link.sct" --info sizes --info totals --info unused --info veneers --list rtthread.map --strict' + CFLAGS += ' -I' + EXEC_PATH + '/ARM/ARMCC/include' + LFLAGS += ' --libpath=' + EXEC_PATH + '/ARM/ARMCC/lib' + + CFLAGS += ' -D__MICROLIB ' + AFLAGS += ' --pd "__MICROLIB SETA 1" ' + LFLAGS += ' --library_type=microlib ' + EXEC_PATH += '/ARM/ARMCC/bin/' + + if BUILD == 'debug': + CFLAGS += ' -g -O0' + AFLAGS += ' -g' + else: + CFLAGS += ' -O2' + + CXXFLAGS = CFLAGS + CFLAGS += ' -std=c99' + + POST_ACTION = 'fromelf --bin $TARGET --output rtthread.bin \nfromelf -z $TARGET' + +elif PLATFORM == 'iar': + # toolchains + CC = 'iccarm' + CXX = 'iccarm' + AS = 'iasmarm' + AR = 'iarchive' + LINK = 'ilinkarm' + TARGET_EXT = 'out' + + DEVICE = '-Dewarm' + + CFLAGS = DEVICE + CFLAGS += ' --diag_suppress Pa050' + CFLAGS += ' --no_cse' + CFLAGS += ' --no_unroll' + CFLAGS += ' --no_inline' + CFLAGS += ' --no_code_motion' + CFLAGS += ' --no_tbaa' + CFLAGS += ' --no_clustering' + CFLAGS += ' --no_scheduling' + CFLAGS += ' --endian=little' + CFLAGS += ' --cpu=Cortex-M3' + CFLAGS += ' -e' + CFLAGS += ' --fpu=None' + CFLAGS += ' --dlib_config "' + EXEC_PATH + '/arm/INC/c/DLib_Config_Normal.h"' + CFLAGS += ' --silent' + + AFLAGS = DEVICE + AFLAGS += ' -s+' + AFLAGS += ' -w+' + AFLAGS += ' -r' + AFLAGS += ' --cpu Cortex-M3' + AFLAGS += ' --fpu None' + AFLAGS += ' -S' + + if BUILD == 'debug': + CFLAGS += ' --debug' + CFLAGS += ' -On' + else: + CFLAGS += ' -Oh' + + LFLAGS = ' --config "board/linker_scripts/link.icf"' + LFLAGS += ' --entry __iar_program_start' + + CXXFLAGS = CFLAGS + + EXEC_PATH = EXEC_PATH + '/arm/bin/' + POST_ACTION = 'ielftool --bin $TARGET rtthread.bin' + +def dist_handle(BSP_ROOT, dist_dir): + import sys + cwd_path = os.getcwd() + sys.path.append(os.path.join(os.path.dirname(BSP_ROOT), 'tools')) + from sdk_dist import dist_do_building + dist_do_building(BSP_ROOT, dist_dir) diff --git a/bsp/gd32/gd32105r-start/template.uvoptx b/bsp/gd32/gd32105r-start/template.uvoptx new file mode 100644 index 0000000000..c41712a0e7 --- /dev/null +++ b/bsp/gd32/gd32105r-start/template.uvoptx @@ -0,0 +1,180 @@ + + + + 1.0 + +
### uVision Project, (C) Keil Software
+ + + *.c + *.s*; *.src; *.a* + *.obj; *.o + *.lib + *.txt; *.h; *.inc + *.plm + *.cpp + 0 + + + + 0 + 0 + + + + rt-thread + 0x4 + ARM-ADS + + 10800000 + + 1 + 1 + 0 + 1 + 0 + + + 1 + 65535 + 0 + 0 + 0 + + + 79 + 66 + 8 + .\build\ + + + 1 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 0 + 0 + 0 + 0 + + + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 0 + 0 + + + 0 + 0 + 1 + + 255 + + 0 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 0 + 1 + 1 + 1 + 1 + 0 + 0 + 1 + 0 + 0 + 3 + + + + + + + + + + + BIN\CMSIS_AGDI.dll + + + + 0 + UL2CM3 + UL2CM3(-S0 -C0 -P0 -FD20000000 -FC1000 -FN1 -FF0GD32F10x_CL -FS08000000 -FL040000 -FP0($$Device:GD32F105RC$Flash\GD32F10x_CL.FLM)) + + + + + 0 + + + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + + + + 0 + 0 + 0 + + + + + + + + + + + + + ::CMSIS + 0 + 0 + 0 + 1 + + +
diff --git a/bsp/gd32/gd32105r-start/template.uvproj b/bsp/gd32/gd32105r-start/template.uvproj new file mode 100644 index 0000000000..592ba32731 --- /dev/null +++ b/bsp/gd32/gd32105r-start/template.uvproj @@ -0,0 +1,628 @@ + + + + 1.1 + +
### uVision Project, (C) Keil Software
+ + + + rt-thread + 0x4 + ARM-ADS + 0 + + + GD32F105RC + GigaDevice + IRAM(0x20000000-0x20018000) IROM(0x08000000-0x08040000) CLOCK(10800000) CPUTYPE("Cortex-M3") + + "Startup\GD\GD32F10x\startup_gd32f10x.s" ("GD32F10x Startup Code") + UL2CM3(-O207 -S0 -C0 -FO7 -FD20000000 -FC800 -FN1 -FF0GD32F10x_3MB -FS08000000 -FL0100000) + 0 + gd32f10x0.h + + + + + + + + + + SFD\GD\GD32F10x\GD32F10x.SFR + 0 + 0 + + + + GD\GD32F10x\ + GD\GD32F10x\ + + 0 + 0 + 0 + 0 + 1 + + .\output\ + rtthread + 1 + 0 + 1 + 1 + 1 + .\build\ + 1 + 0 + 0 + + 0 + 0 + + + 0 + 0 + 0 + 0 + + + 0 + 0 + + + 0 + 0 + 0 + 0 + + + 0 + 0 + + + 0 + 0 + 0 + 0 + + 0 + + + + 0 + 0 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 0 + 3 + + + 1 + + + SARMCM3.DLL + -REMAP + DCM.DLL + -pCM3 + SARMCM3.DLL + + TCM.DLL + -pCM3 + + + + 1 + 0 + 0 + 0 + 16 + + + 0 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 0 + 1 + + + 1 + 1 + 1 + 1 + 1 + 1 + 0 + 1 + 0 + 1 + + 0 + 3 + + + + + + + + + + + + + + BIN\CMSIS_AGDI.dll + + + + + 1 + 0 + 0 + 1 + 1 + 4096 + + 1 + BIN\UL2CM3.DLL + "" () + + + + + 0 + + + + 0 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 0 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 0 + 0 + "Cortex-M3" + + 0 + 0 + 0 + 1 + 1 + 0 + 0 + 2 + 1 + 0 + 8 + 1 + 0 + 0 + 0 + 3 + 3 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 0 + 1 + 0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x20000000 + 0x10000 + + + 1 + 0x8000000 + 0x100000 + + + 0 + 0x0 + 0x0 + + + 1 + 0x0 + 0x0 + + + 1 + 0x0 + 0x0 + + + 1 + 0x0 + 0x0 + + + 1 + 0x8000000 + 0x100000 + + + 1 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x20000000 + 0x10000 + + + 0 + 0x10000000 + 0x10000 + + + + + + 1 + 1 + 0 + 0 + 1 + 0 + 0 + 0 + 0 + 0 + 2 + 0 + 0 + 1 + 0 + 0 + 1 + 1 + 1 + 1 + 0 + 0 + 0 + + + + + ..\..\..\Library\Firmware\GD32F10x_standard_peripheral\Include;..\..\..\Library\Firmware\CMSIS\GD\GD32F10x\Include;..\..\..\Library\Utilities;..\ + + + + 1 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + + + + + + + + + 1 + 0 + 0 + 0 + 1 + 0 + 0x08000000 + 0x20000000 + + + + + + + + + + + + + Application + + + main.c + 1 + ..\main.c + + + gd32f10x_it.c + 1 + ..\gd32f10x_it.c + + + + + CMSIS + + + system_gd32f10x.c + 1 + ..\..\..\Library\Firmware\CMSIS\GD\GD32F10x\Source\system_gd32f10x.c + + + + + GD32F10x_Peripherals + + + gd32f10x_adc.c + 1 + ..\..\..\Library\Firmware\GD32F10x_standard_peripheral\Source\gd32f10x_adc.c + + + gd32f10x_can.c + 1 + ..\..\..\Library\Firmware\GD32F10x_standard_peripheral\Source\gd32f10x_can.c + + + gd32f10x_crc.c + 1 + ..\..\..\Library\Firmware\GD32F10x_standard_peripheral\Source\gd32f10x_crc.c + + + gd32f10x_ctc.c + 1 + ..\..\..\Library\Firmware\GD32F10x_standard_peripheral\Source\gd32f10x_ctc.c + + + gd32f10x_dac.c + 1 + ..\..\..\Library\Firmware\GD32F10x_standard_peripheral\Source\gd32f10x_dac.c + + + gd32f10x_dbg.c + 1 + ..\..\..\Library\Firmware\GD32F10x_standard_peripheral\Source\gd32f10x_dbg.c + + + gd32f10x_dci.c + 1 + ..\..\..\Library\Firmware\GD32F10x_standard_peripheral\Source\gd32f10x_dci.c + + + gd32f10x_dma.c + 1 + ..\..\..\Library\Firmware\GD32F10x_standard_peripheral\Source\gd32f10x_dma.c + + + gd32f10x_enet.c + 1 + ..\..\..\Library\Firmware\GD32F10x_standard_peripheral\Source\gd32f10x_enet.c + + + gd32f10x_exmc.c + 1 + ..\..\..\Library\Firmware\GD32F10x_standard_peripheral\Source\gd32f10x_exmc.c + + + gd32f10x_exti.c + 1 + ..\..\..\Library\Firmware\GD32F10x_standard_peripheral\Source\gd32f10x_exti.c + + + gd32f10x_fmc.c + 1 + ..\..\..\Library\Firmware\GD32F10x_standard_peripheral\Source\gd32f10x_fmc.c + + + gd32f10x_fwdgt.c + 1 + ..\..\..\Library\Firmware\GD32F10x_standard_peripheral\Source\gd32f10x_fwdgt.c + + + gd32f10x_gpio.c + 1 + ..\..\..\Library\Firmware\GD32F10x_standard_peripheral\Source\gd32f10x_gpio.c + + + gd32f10x_i2c.c + 1 + ..\..\..\Library\Firmware\GD32F10x_standard_peripheral\Source\gd32f10x_i2c.c + + + gd32f10x_ipa.c + 1 + ..\..\..\Library\Firmware\GD32F10x_standard_peripheral\Source\gd32f10x_ipa.c + + + gd32f10x_iref.c + 1 + ..\..\..\Library\Firmware\GD32F10x_standard_peripheral\Source\gd32f10x_iref.c + + + gd32f10x_misc.c + 1 + ..\..\..\Library\Firmware\GD32F10x_standard_peripheral\Source\gd32f10x_misc.c + + + gd32f10x_pmu.c + 1 + ..\..\..\Library\Firmware\GD32F10x_standard_peripheral\Source\gd32f10x_pmu.c + + + gd32f10x_rcu.c + 1 + ..\..\..\Library\Firmware\GD32F10x_standard_peripheral\Source\gd32f10x_rcu.c + + + gd32f10x_rtc.c + 1 + ..\..\..\Library\Firmware\GD32F10x_standard_peripheral\Source\gd32f10x_rtc.c + + + gd32f10x_sdio.c + 1 + ..\..\..\Library\Firmware\GD32F10x_standard_peripheral\Source\gd32f10x_sdio.c + + + gd32f10x_spi.c + 1 + ..\..\..\Library\Firmware\GD32F10x_standard_peripheral\Source\gd32f10x_spi.c + + + gd32f10x_syscfg.c + 1 + ..\..\..\Library\Firmware\GD32F10x_standard_peripheral\Source\gd32f10x_syscfg.c + + + gd32f10x_timer.c + 1 + ..\..\..\Library\Firmware\GD32F10x_standard_peripheral\Source\gd32f10x_timer.c + + + gd32f10x_tli.c + 1 + ..\..\..\Library\Firmware\GD32F10x_standard_peripheral\Source\gd32f10x_tli.c + + + gd32f10x_trng.c + 1 + ..\..\..\Library\Firmware\GD32F10x_standard_peripheral\Source\gd32f10x_trng.c + + + gd32f10x_usart.c + 1 + ..\..\..\Library\Firmware\GD32F10x_standard_peripheral\Source\gd32f10x_usart.c + + + gd32f10x_wwdgt.c + 1 + ..\..\..\Library\Firmware\GD32F10x_standard_peripheral\Source\gd32f10x_wwdgt.c + + + + + GD32F10x_START + + + gd32f105r_start.c + 1 + ..\..\..\Library\Utilities\gd32f105r_start.c + + + + + Startup + + + startup_gd32f10x.s + 2 + ..\..\..\Library\Firmware\CMSIS\GD\GD32F10x\Source\ARM\startup_gd32f10x.s + + + + + Doc + + + readme.txt + 5 + ..\readme.txt + + + + + + + +
diff --git a/bsp/gd32/gd32105r-start/template.uvprojx b/bsp/gd32/gd32105r-start/template.uvprojx new file mode 100644 index 0000000000..fd731a72ca --- /dev/null +++ b/bsp/gd32/gd32105r-start/template.uvprojx @@ -0,0 +1,418 @@ + + + + 2.1 + +
### uVision Project, (C) Keil Software
+ + + + rt-thread + 0x4 + ARM-ADS + 5060750::V5.06 update 6 (build 750)::.\ARMCC + 0 + + + GD32F105RC + GigaDevice + GigaDevice.GD32F10x_DFP.2.0.1 + http://www.keil.com/pack/ + IRAM(0x20000000,0x00018000) IROM(0x08000000,0x00040000) CPUTYPE("Cortex-M3") CLOCK(10800000) ELITTLE + + + UL2CM3(-S0 -C0 -P0 -FD20000000 -FC1000 -FN1 -FF0GD32F10x_CL -FS08000000 -FL040000 -FP0($$Device:GD32F105RC$Flash\GD32F10x_CL.FLM)) + 0 + $$Device:GD32F105RC$Device\Include\gd32f10x.h + + + + + + + + + + $$Device:GD32F105RC$SVD\GD32F10x\GD32F10x_CL.svd + 0 + 0 + + + + + + + 0 + 0 + 0 + 0 + 1 + + .\build\ + rtthread + 1 + 0 + 0 + 1 + 0 + .\build\ + 1 + 0 + 0 + + 0 + 0 + + + 0 + 0 + 0 + 0 + + + 0 + 0 + + + 0 + 0 + 0 + 0 + + + 1 + 0 + fromelf --bin !L --output rtthread.bin + + 0 + 0 + 0 + 0 + + 0 + + + + 0 + 0 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 0 + 3 + + + 1 + + + SARMCM3.DLL + -REMAP + DCM.DLL + -pCM3 + SARMCM3.DLL + + TCM.DLL + -pCM3 + + + + 1 + 0 + 0 + 0 + 16 + + + + + 1 + 0 + 0 + 1 + 1 + 4096 + + 1 + BIN\UL2CM3.DLL + + + + + + 0 + + + + 0 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 0 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 0 + 0 + "Cortex-M3" + + 0 + 0 + 0 + 1 + 1 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 8 + 0 + 0 + 0 + 0 + 3 + 3 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 0 + 1 + 0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x20000000 + 0x18000 + + + 1 + 0x8000000 + 0x40000 + + + 0 + 0x0 + 0x0 + + + 1 + 0x0 + 0x0 + + + 1 + 0x0 + 0x0 + + + 1 + 0x0 + 0x0 + + + 1 + 0x8000000 + 0x40000 + + + 1 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x20000000 + 0x18000 + + + 0 + 0x0 + 0x0 + + + + + + 1 + 4 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 1 + 0 + 0 + 1 + 1 + 1 + 1 + 0 + 0 + 0 + + + + + + + + + 1 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 4 + + + + + + + + + 1 + 0 + 0 + 0 + 1 + 0 + 0x08000000 + 0x20000000 + + .\gd32_rom.ld + + + + + + + + + + + ::CMSIS + + + + + + + + + + + + + + + + + + + + + + <Project Info> + + + + + + 0 + 1 + + + + +
diff --git a/bsp/gd32/gd32205r-start/.config b/bsp/gd32/gd32205r-start/.config new file mode 100644 index 0000000000..4c0efca811 --- /dev/null +++ b/bsp/gd32/gd32205r-start/.config @@ -0,0 +1,636 @@ +# +# Automatically generated file; DO NOT EDIT. +# RT-Thread Configuration +# + +# +# RT-Thread Kernel +# +CONFIG_RT_NAME_MAX=8 +# CONFIG_RT_USING_BIG_ENDIAN is not set +# CONFIG_RT_USING_ARCH_DATA_TYPE is not set +# CONFIG_RT_USING_SMP is not set +CONFIG_RT_ALIGN_SIZE=4 +# CONFIG_RT_THREAD_PRIORITY_8 is not set +CONFIG_RT_THREAD_PRIORITY_32=y +# CONFIG_RT_THREAD_PRIORITY_256 is not set +CONFIG_RT_THREAD_PRIORITY_MAX=32 +CONFIG_RT_TICK_PER_SECOND=100 +CONFIG_RT_USING_OVERFLOW_CHECK=y +CONFIG_RT_USING_HOOK=y +CONFIG_RT_USING_IDLE_HOOK=y +CONFIG_RT_IDLE_HOOK_LIST_SIZE=4 +CONFIG_IDLE_THREAD_STACK_SIZE=256 +# CONFIG_RT_USING_TIMER_SOFT is not set + +# +# kservice optimization +# +# CONFIG_RT_KSERVICE_USING_STDLIB is not set +# CONFIG_RT_KSERVICE_USING_TINY_SIZE is not set +# CONFIG_RT_USING_ASM_MEMCPY is not set +CONFIG_RT_DEBUG=y +CONFIG_RT_DEBUG_COLOR=y +# CONFIG_RT_DEBUG_INIT_CONFIG is not set +# CONFIG_RT_DEBUG_THREAD_CONFIG is not set +# CONFIG_RT_DEBUG_SCHEDULER_CONFIG is not set +# CONFIG_RT_DEBUG_IPC_CONFIG is not set +# CONFIG_RT_DEBUG_TIMER_CONFIG is not set +# CONFIG_RT_DEBUG_IRQ_CONFIG is not set +# CONFIG_RT_DEBUG_MEM_CONFIG is not set +# CONFIG_RT_DEBUG_SLAB_CONFIG is not set +# CONFIG_RT_DEBUG_MEMHEAP_CONFIG is not set +# CONFIG_RT_DEBUG_MODULE_CONFIG is not set + +# +# Inter-Thread communication +# +CONFIG_RT_USING_SEMAPHORE=y +CONFIG_RT_USING_MUTEX=y +CONFIG_RT_USING_EVENT=y +CONFIG_RT_USING_MAILBOX=y +CONFIG_RT_USING_MESSAGEQUEUE=y +# CONFIG_RT_USING_SIGNALS is not set + +# +# Memory Management +# +CONFIG_RT_USING_MEMPOOL=y +# CONFIG_RT_USING_MEMHEAP is not set +# CONFIG_RT_USING_NOHEAP is not set +CONFIG_RT_USING_SMALL_MEM=y +# CONFIG_RT_USING_SLAB is not set +# CONFIG_RT_USING_USERHEAP is not set +# CONFIG_RT_USING_MEMTRACE is not set +CONFIG_RT_USING_HEAP=y + +# +# Kernel Device Object +# +CONFIG_RT_USING_DEVICE=y +# CONFIG_RT_USING_DEVICE_OPS is not set +# CONFIG_RT_USING_INTERRUPT_INFO is not set +CONFIG_RT_USING_CONSOLE=y +CONFIG_RT_CONSOLEBUF_SIZE=128 +CONFIG_RT_CONSOLE_DEVICE_NAME="uart1" +# CONFIG_RT_PRINTF_LONGLONG is not set +CONFIG_RT_VER_NUM=0x40004 +# CONFIG_RT_USING_CPU_FFS is not set +# CONFIG_ARCH_CPU_STACK_GROWS_UPWARD is not set + +# +# RT-Thread Components +# +CONFIG_RT_USING_COMPONENTS_INIT=y +CONFIG_RT_USING_USER_MAIN=y +CONFIG_RT_MAIN_THREAD_STACK_SIZE=2048 +CONFIG_RT_MAIN_THREAD_PRIORITY=10 + +# +# C++ features +# +# CONFIG_RT_USING_CPLUSPLUS is not set + +# +# Command shell +# +CONFIG_RT_USING_FINSH=y +CONFIG_RT_USING_MSH=y +CONFIG_FINSH_USING_MSH=y +CONFIG_FINSH_THREAD_NAME="tshell" +CONFIG_FINSH_THREAD_PRIORITY=20 +CONFIG_FINSH_THREAD_STACK_SIZE=4096 +CONFIG_FINSH_USING_HISTORY=y +CONFIG_FINSH_HISTORY_LINES=5 +CONFIG_FINSH_USING_SYMTAB=y +CONFIG_FINSH_CMD_SIZE=80 +CONFIG_MSH_USING_BUILT_IN_COMMANDS=y +CONFIG_FINSH_USING_DESCRIPTION=y +# CONFIG_FINSH_ECHO_DISABLE_DEFAULT is not set +# CONFIG_FINSH_USING_AUTH is not set +CONFIG_FINSH_ARG_MAX=10 + +# +# Device virtual file system +# +# CONFIG_RT_USING_DFS is not set + +# +# Device Drivers +# +CONFIG_RT_USING_DEVICE_IPC=y +CONFIG_RT_PIPE_BUFSZ=512 +CONFIG_RT_USING_SYSTEM_WORKQUEUE=y +CONFIG_RT_SYSTEM_WORKQUEUE_STACKSIZE=2048 +CONFIG_RT_SYSTEM_WORKQUEUE_PRIORITY=23 +CONFIG_RT_USING_SERIAL=y +CONFIG_RT_USING_SERIAL_V1=y +# CONFIG_RT_USING_SERIAL_V2 is not set +CONFIG_RT_SERIAL_USING_DMA=y +CONFIG_RT_SERIAL_RB_BUFSZ=64 +# CONFIG_RT_USING_CAN is not set +# CONFIG_RT_USING_HWTIMER is not set +# CONFIG_RT_USING_CPUTIME is not set +# CONFIG_RT_USING_I2C is not set +# CONFIG_RT_USING_PHY is not set +CONFIG_RT_USING_PIN=y +# CONFIG_RT_USING_ADC is not set +# CONFIG_RT_USING_DAC is not set +# CONFIG_RT_USING_PWM is not set +# CONFIG_RT_USING_MTD_NOR is not set +# CONFIG_RT_USING_MTD_NAND is not set +# CONFIG_RT_USING_PM is not set +# CONFIG_RT_USING_RTC is not set +# CONFIG_RT_USING_SDIO is not set +# CONFIG_RT_USING_SPI is not set +# CONFIG_RT_USING_WDT is not set +# CONFIG_RT_USING_AUDIO is not set +# CONFIG_RT_USING_SENSOR is not set +# CONFIG_RT_USING_TOUCH is not set +# CONFIG_RT_USING_HWCRYPTO is not set +# CONFIG_RT_USING_PULSE_ENCODER is not set +# CONFIG_RT_USING_INPUT_CAPTURE is not set +# CONFIG_RT_USING_WIFI is not set + +# +# Using USB +# +# CONFIG_RT_USING_USB is not set +# CONFIG_RT_USING_USB_HOST is not set +# CONFIG_RT_USING_USB_DEVICE is not set + +# +# POSIX layer and C standard library +# +# CONFIG_RT_USING_LIBC is not set +CONFIG_RT_LIBC_USING_TIME=y +CONFIG_RT_LIBC_DEFAULT_TIMEZONE=8 +# CONFIG_RT_USING_PTHREADS is not set + +# +# Network +# + +# +# Socket abstraction layer +# +# CONFIG_RT_USING_SAL is not set + +# +# Network interface device +# +# CONFIG_RT_USING_NETDEV is not set + +# +# light weight TCP/IP stack +# +# CONFIG_RT_USING_LWIP is not set + +# +# AT commands +# +# CONFIG_RT_USING_AT is not set + +# +# VBUS(Virtual Software BUS) +# +# CONFIG_RT_USING_VBUS is not set + +# +# Utilities +# +# CONFIG_RT_USING_RYM is not set +# CONFIG_RT_USING_ULOG is not set +# CONFIG_RT_USING_UTEST is not set +# CONFIG_RT_USING_VAR_EXPORT is not set +# CONFIG_RT_USING_RT_LINK is not set + +# +# RT-Thread Utestcases +# +# CONFIG_RT_USING_UTESTCASES is not set + +# +# RT-Thread online packages +# + +# +# IoT - internet of things +# +# CONFIG_PKG_USING_LORAWAN_DRIVER is not set +# CONFIG_PKG_USING_PAHOMQTT is not set +# CONFIG_PKG_USING_UMQTT is not set +# CONFIG_PKG_USING_WEBCLIENT is not set +# CONFIG_PKG_USING_WEBNET is not set +# CONFIG_PKG_USING_MONGOOSE is not set +# CONFIG_PKG_USING_MYMQTT is not set +# CONFIG_PKG_USING_KAWAII_MQTT is not set +# CONFIG_PKG_USING_BC28_MQTT is not set +# CONFIG_PKG_USING_WEBTERMINAL is not set +# CONFIG_PKG_USING_CJSON is not set +# CONFIG_PKG_USING_JSMN is not set +# CONFIG_PKG_USING_LIBMODBUS is not set +# CONFIG_PKG_USING_FREEMODBUS is not set +# CONFIG_PKG_USING_LJSON is not set +# CONFIG_PKG_USING_EZXML is not set +# CONFIG_PKG_USING_NANOPB is not set + +# +# Wi-Fi +# + +# +# Marvell WiFi +# +# CONFIG_PKG_USING_WLANMARVELL is not set + +# +# Wiced WiFi +# +# CONFIG_PKG_USING_WLAN_WICED is not set +# CONFIG_PKG_USING_RW007 is not set +# CONFIG_PKG_USING_COAP is not set +# CONFIG_PKG_USING_NOPOLL is not set +# CONFIG_PKG_USING_NETUTILS is not set +# CONFIG_PKG_USING_CMUX is not set +# CONFIG_PKG_USING_PPP_DEVICE is not set +# CONFIG_PKG_USING_AT_DEVICE is not set +# CONFIG_PKG_USING_ATSRV_SOCKET is not set +# CONFIG_PKG_USING_WIZNET is not set +# CONFIG_PKG_USING_ZB_COORDINATOR is not set + +# +# IoT Cloud +# +# CONFIG_PKG_USING_ONENET is not set +# CONFIG_PKG_USING_GAGENT_CLOUD is not set +# CONFIG_PKG_USING_ALI_IOTKIT is not set +# CONFIG_PKG_USING_AZURE is not set +# CONFIG_PKG_USING_TENCENT_IOT_EXPLORER is not set +# CONFIG_PKG_USING_JIOT-C-SDK is not set +# CONFIG_PKG_USING_UCLOUD_IOT_SDK is not set +# CONFIG_PKG_USING_JOYLINK is not set +# CONFIG_PKG_USING_NIMBLE is not set +# CONFIG_PKG_USING_OTA_DOWNLOADER is not set +# CONFIG_PKG_USING_IPMSG is not set +# CONFIG_PKG_USING_LSSDP is not set +# CONFIG_PKG_USING_AIRKISS_OPEN is not set +# CONFIG_PKG_USING_LIBRWS is not set +# CONFIG_PKG_USING_TCPSERVER is not set +# CONFIG_PKG_USING_PROTOBUF_C is not set +# CONFIG_PKG_USING_DLT645 is not set +# CONFIG_PKG_USING_QXWZ is not set +# CONFIG_PKG_USING_SMTP_CLIENT is not set +# CONFIG_PKG_USING_ABUP_FOTA is not set +# CONFIG_PKG_USING_LIBCURL2RTT is not set +# CONFIG_PKG_USING_CAPNP is not set +# CONFIG_PKG_USING_RT_CJSON_TOOLS is not set +# CONFIG_PKG_USING_AGILE_TELNET is not set +# CONFIG_PKG_USING_NMEALIB is not set +# CONFIG_PKG_USING_AGILE_JSMN is not set +# CONFIG_PKG_USING_PDULIB is not set +# CONFIG_PKG_USING_BTSTACK is not set +# CONFIG_PKG_USING_LORAWAN_ED_STACK is not set +# CONFIG_PKG_USING_WAYZ_IOTKIT is not set +# CONFIG_PKG_USING_MAVLINK is not set +# CONFIG_PKG_USING_RAPIDJSON is not set +# CONFIG_PKG_USING_BSAL is not set +# CONFIG_PKG_USING_AGILE_MODBUS is not set +# CONFIG_PKG_USING_AGILE_FTP is not set +# CONFIG_PKG_USING_EMBEDDEDPROTO is not set +# CONFIG_PKG_USING_RT_LINK_HW is not set +# CONFIG_PKG_USING_LORA_PKT_FWD is not set +# CONFIG_PKG_USING_LORA_GW_DRIVER_LIB is not set +# CONFIG_PKG_USING_LORA_PKT_SNIFFER is not set +# CONFIG_PKG_USING_HM is not set +# CONFIG_PKG_USING_SMALL_MODBUS is not set + +# +# security packages +# +# CONFIG_PKG_USING_MBEDTLS is not set +# CONFIG_PKG_USING_LIBSODIUM is not set +# CONFIG_PKG_USING_TINYCRYPT is not set +# CONFIG_PKG_USING_TFM is not set +# CONFIG_PKG_USING_YD_CRYPTO is not set + +# +# language packages +# +# CONFIG_PKG_USING_LUA is not set +# CONFIG_PKG_USING_JERRYSCRIPT is not set +# CONFIG_PKG_USING_MICROPYTHON is not set +# CONFIG_PKG_USING_PIKASCRIPT is not set + +# +# multimedia packages +# + +# +# LVGL: powerful and easy-to-use embedded GUI library +# +# CONFIG_PKG_USING_LVGL is not set +# CONFIG_PKG_USING_LITTLEVGL2RTT is not set +# CONFIG_PKG_USING_LV_MUSIC_DEMO is not set + +# +# u8g2: a monochrome graphic library +# +# CONFIG_PKG_USING_U8G2_OFFICIAL is not set +# CONFIG_PKG_USING_U8G2 is not set +# CONFIG_PKG_USING_OPENMV is not set +# CONFIG_PKG_USING_MUPDF is not set +# CONFIG_PKG_USING_STEMWIN is not set +# CONFIG_PKG_USING_WAVPLAYER is not set +# CONFIG_PKG_USING_TJPGD is not set +# CONFIG_PKG_USING_PDFGEN is not set +# CONFIG_PKG_USING_HELIX is not set +# CONFIG_PKG_USING_AZUREGUIX is not set +# CONFIG_PKG_USING_TOUCHGFX2RTT is not set +# CONFIG_PKG_USING_NUEMWIN is not set +# CONFIG_PKG_USING_MP3PLAYER is not set +# CONFIG_PKG_USING_TINYJPEG is not set +# CONFIG_PKG_USING_UGUI is not set + +# +# PainterEngine: A cross-platform graphics application framework written in C language +# +# CONFIG_PKG_USING_PAINTERENGINE is not set +# CONFIG_PKG_USING_PAINTERENGINE_AUX is not set + +# +# tools packages +# +# CONFIG_PKG_USING_CMBACKTRACE is not set +# CONFIG_PKG_USING_EASYFLASH is not set +# CONFIG_PKG_USING_EASYLOGGER is not set +# CONFIG_PKG_USING_SYSTEMVIEW is not set +# CONFIG_PKG_USING_SEGGER_RTT is not set +# CONFIG_PKG_USING_RDB is not set +# CONFIG_PKG_USING_QRCODE is not set +# CONFIG_PKG_USING_ULOG_EASYFLASH is not set +# CONFIG_PKG_USING_ULOG_FILE is not set +# CONFIG_PKG_USING_LOGMGR is not set +# CONFIG_PKG_USING_ADBD is not set +# CONFIG_PKG_USING_COREMARK is not set +# CONFIG_PKG_USING_DHRYSTONE is not set +# CONFIG_PKG_USING_MEMORYPERF is not set +# CONFIG_PKG_USING_NR_MICRO_SHELL is not set +# CONFIG_PKG_USING_CHINESE_FONT_LIBRARY is not set +# CONFIG_PKG_USING_LUNAR_CALENDAR is not set +# CONFIG_PKG_USING_BS8116A is not set +# CONFIG_PKG_USING_GPS_RMC is not set +# CONFIG_PKG_USING_URLENCODE is not set +# CONFIG_PKG_USING_UMCN is not set +# CONFIG_PKG_USING_LWRB2RTT is not set +# CONFIG_PKG_USING_CPU_USAGE is not set +# CONFIG_PKG_USING_GBK2UTF8 is not set +# CONFIG_PKG_USING_VCONSOLE is not set +# CONFIG_PKG_USING_KDB is not set +# CONFIG_PKG_USING_WAMR is not set +# CONFIG_PKG_USING_MICRO_XRCE_DDS_CLIENT is not set +# CONFIG_PKG_USING_LWLOG is not set +# CONFIG_PKG_USING_ANV_TRACE is not set +# CONFIG_PKG_USING_ANV_MEMLEAK is not set +# CONFIG_PKG_USING_ANV_TESTSUIT is not set +# CONFIG_PKG_USING_ANV_BENCH is not set +# CONFIG_PKG_USING_DEVMEM is not set +# CONFIG_PKG_USING_REGEX is not set +# CONFIG_PKG_USING_MEM_SANDBOX is not set +# CONFIG_PKG_USING_SOLAR_TERMS is not set +# CONFIG_PKG_USING_GAN_ZHI is not set +# CONFIG_PKG_USING_FDT is not set + +# +# system packages +# + +# +# enhanced kernel services +# +# CONFIG_PKG_USING_RT_MEMCPY_CM is not set +# CONFIG_PKG_USING_RT_KPRINTF_THREADSAFE is not set +# CONFIG_PKG_USING_RT_VSNPRINTF_FULL is not set + +# +# acceleration: Assembly language or algorithmic acceleration packages +# +# CONFIG_PKG_USING_QFPLIB_M0_FULL is not set +# CONFIG_PKG_USING_QFPLIB_M0_TINY is not set +# CONFIG_PKG_USING_QFPLIB_M3 is not set + +# +# CMSIS: ARM Cortex-M Microcontroller Software Interface Standard +# +# CONFIG_PKG_USING_CMSIS_5 is not set +# CONFIG_PKG_USING_CMSIS_RTOS2 is not set + +# +# Micrium: Micrium software products porting for RT-Thread +# +# CONFIG_PKG_USING_UCOSIII_WRAPPER is not set +# CONFIG_PKG_USING_UCOSII_WRAPPER is not set +# CONFIG_PKG_USING_UC_CRC is not set +# CONFIG_PKG_USING_UC_CLK is not set +# CONFIG_PKG_USING_UC_COMMON is not set +# CONFIG_PKG_USING_UC_MODBUS is not set +# CONFIG_RT_USING_ARDUINO is not set +# CONFIG_PKG_USING_GUIENGINE is not set +# CONFIG_PKG_USING_CAIRO is not set +# CONFIG_PKG_USING_PIXMAN is not set +# CONFIG_PKG_USING_PARTITION is not set +# CONFIG_PKG_USING_FAL is not set +# CONFIG_PKG_USING_FLASHDB is not set +# CONFIG_PKG_USING_SQLITE is not set +# CONFIG_PKG_USING_RTI is not set +# CONFIG_PKG_USING_DFS_YAFFS is not set +# CONFIG_PKG_USING_LITTLEFS is not set +# CONFIG_PKG_USING_DFS_JFFS2 is not set +# CONFIG_PKG_USING_DFS_UFFS is not set +# CONFIG_PKG_USING_LWEXT4 is not set +# CONFIG_PKG_USING_THREAD_POOL is not set +# CONFIG_PKG_USING_ROBOTS is not set +# CONFIG_PKG_USING_EV is not set +# CONFIG_PKG_USING_SYSWATCH is not set +# CONFIG_PKG_USING_SYS_LOAD_MONITOR is not set +# CONFIG_PKG_USING_PLCCORE is not set +# CONFIG_PKG_USING_RAMDISK is not set +# CONFIG_PKG_USING_MININI is not set +# CONFIG_PKG_USING_QBOOT is not set +# CONFIG_PKG_USING_PPOOL is not set +# CONFIG_PKG_USING_OPENAMP is not set +# CONFIG_PKG_USING_LPM is not set +# CONFIG_PKG_USING_TLSF is not set +# CONFIG_PKG_USING_EVENT_RECORDER is not set +# CONFIG_PKG_USING_ARM_2D is not set +# CONFIG_PKG_USING_WCWIDTH is not set +# CONFIG_PKG_USING_MCUBOOT is not set +# CONFIG_PKG_USING_TINYUSB is not set +# CONFIG_PKG_USING_USB_STACK is not set + +# +# peripheral libraries and drivers +# +# CONFIG_PKG_USING_SENSORS_DRIVERS is not set +# CONFIG_PKG_USING_REALTEK_AMEBA is not set +# CONFIG_PKG_USING_SHT2X is not set +# CONFIG_PKG_USING_SHT3X is not set +# CONFIG_PKG_USING_AS7341 is not set +# CONFIG_PKG_USING_STM32_SDIO is not set +# CONFIG_PKG_USING_ICM20608 is not set +# CONFIG_PKG_USING_BUTTON is not set +# CONFIG_PKG_USING_PCF8574 is not set +# CONFIG_PKG_USING_SX12XX is not set +# CONFIG_PKG_USING_SIGNAL_LED is not set +# CONFIG_PKG_USING_LEDBLINK is not set +# CONFIG_PKG_USING_LITTLED is not set +# CONFIG_PKG_USING_LKDGUI is not set +# CONFIG_PKG_USING_NRF5X_SDK is not set +# CONFIG_PKG_USING_NRFX is not set +# CONFIG_PKG_USING_WM_LIBRARIES is not set +# CONFIG_PKG_USING_KENDRYTE_SDK is not set +# CONFIG_PKG_USING_INFRARED is not set +# CONFIG_PKG_USING_AGILE_BUTTON is not set +# CONFIG_PKG_USING_AGILE_LED is not set +# CONFIG_PKG_USING_AT24CXX is not set +# CONFIG_PKG_USING_MOTIONDRIVER2RTT is not set +# CONFIG_PKG_USING_AD7746 is not set +# CONFIG_PKG_USING_PCA9685 is not set +# CONFIG_PKG_USING_I2C_TOOLS is not set +# CONFIG_PKG_USING_NRF24L01 is not set +# CONFIG_PKG_USING_TOUCH_DRIVERS is not set +# CONFIG_PKG_USING_MAX17048 is not set +# CONFIG_PKG_USING_RPLIDAR is not set +# CONFIG_PKG_USING_AS608 is not set +# CONFIG_PKG_USING_RC522 is not set +# CONFIG_PKG_USING_WS2812B is not set +# CONFIG_PKG_USING_EMBARC_BSP is not set +# CONFIG_PKG_USING_EXTERN_RTC_DRIVERS is not set +# CONFIG_PKG_USING_MULTI_RTIMER is not set +# CONFIG_PKG_USING_MAX7219 is not set +# CONFIG_PKG_USING_BEEP is not set +# CONFIG_PKG_USING_EASYBLINK is not set +# CONFIG_PKG_USING_PMS_SERIES is not set +# CONFIG_PKG_USING_CAN_YMODEM is not set +# CONFIG_PKG_USING_LORA_RADIO_DRIVER is not set +# CONFIG_PKG_USING_QLED is not set +# CONFIG_PKG_USING_PAJ7620 is not set +# CONFIG_PKG_USING_AGILE_CONSOLE is not set +# CONFIG_PKG_USING_LD3320 is not set +# CONFIG_PKG_USING_WK2124 is not set +# CONFIG_PKG_USING_LY68L6400 is not set +# CONFIG_PKG_USING_DM9051 is not set +# CONFIG_PKG_USING_SSD1306 is not set +# CONFIG_PKG_USING_QKEY is not set +# CONFIG_PKG_USING_RS485 is not set +# CONFIG_PKG_USING_NES is not set +# CONFIG_PKG_USING_VIRTUAL_SENSOR is not set +# CONFIG_PKG_USING_VDEVICE is not set +# CONFIG_PKG_USING_SGM706 is not set +# CONFIG_PKG_USING_STM32WB55_SDK is not set +# CONFIG_PKG_USING_RDA58XX is not set +# CONFIG_PKG_USING_LIBNFC is not set +# CONFIG_PKG_USING_MFOC is not set +# CONFIG_PKG_USING_TMC51XX is not set +# CONFIG_PKG_USING_TCA9534 is not set +# CONFIG_PKG_USING_KOBUKI is not set +# CONFIG_PKG_USING_ROSSERIAL is not set +# CONFIG_PKG_USING_MICRO_ROS is not set +# CONFIG_PKG_USING_MCP23008 is not set +# CONFIG_PKG_USING_BLUETRUM_SDK is not set +# CONFIG_PKG_USING_MISAKA_AT24CXX is not set +# CONFIG_PKG_USING_MISAKA_RGB_BLING is not set +# CONFIG_PKG_USING_BL_MCU_SDK is not set +# CONFIG_PKG_USING_SOFT_SERIAL is not set +# CONFIG_PKG_USING_MB85RS16 is not set + +# +# AI packages +# +# CONFIG_PKG_USING_LIBANN is not set +# CONFIG_PKG_USING_NNOM is not set +# CONFIG_PKG_USING_ONNX_BACKEND is not set +# CONFIG_PKG_USING_ONNX_PARSER is not set +# CONFIG_PKG_USING_TENSORFLOWLITEMICRO is not set +# CONFIG_PKG_USING_ELAPACK is not set +# CONFIG_PKG_USING_ULAPACK is not set +# CONFIG_PKG_USING_QUEST is not set +# CONFIG_PKG_USING_NAXOS is not set + +# +# miscellaneous packages +# + +# +# samples: kernel and components samples +# +# CONFIG_PKG_USING_KERNEL_SAMPLES is not set +# CONFIG_PKG_USING_FILESYSTEM_SAMPLES is not set +# CONFIG_PKG_USING_NETWORK_SAMPLES is not set +# CONFIG_PKG_USING_PERIPHERAL_SAMPLES is not set + +# +# entertainment: terminal games and other interesting software packages +# +# CONFIG_PKG_USING_CMATRIX is not set +# CONFIG_PKG_USING_SL is not set +# CONFIG_PKG_USING_CAL is not set +# CONFIG_PKG_USING_ACLOCK is not set +# CONFIG_PKG_USING_THREES is not set +# CONFIG_PKG_USING_2048 is not set +# CONFIG_PKG_USING_SNAKE is not set +# CONFIG_PKG_USING_TETRIS is not set +# CONFIG_PKG_USING_DONUT is not set +# CONFIG_PKG_USING_LIBCSV is not set +# CONFIG_PKG_USING_OPTPARSE is not set +# CONFIG_PKG_USING_FASTLZ is not set +# CONFIG_PKG_USING_MINILZO is not set +# CONFIG_PKG_USING_QUICKLZ is not set +# CONFIG_PKG_USING_LZMA is not set +# CONFIG_PKG_USING_MULTIBUTTON is not set +# CONFIG_PKG_USING_FLEXIBLE_BUTTON is not set +# CONFIG_PKG_USING_CANFESTIVAL is not set +# CONFIG_PKG_USING_ZLIB is not set +# CONFIG_PKG_USING_MINIZIP is not set +# CONFIG_PKG_USING_DSTR is not set +# CONFIG_PKG_USING_TINYFRAME is not set +# CONFIG_PKG_USING_KENDRYTE_DEMO is not set +# CONFIG_PKG_USING_DIGITALCTRL is not set +# CONFIG_PKG_USING_UPACKER is not set +# CONFIG_PKG_USING_UPARAM is not set +# CONFIG_PKG_USING_HELLO is not set +# CONFIG_PKG_USING_VI is not set +# CONFIG_PKG_USING_KI is not set +# CONFIG_PKG_USING_ARMv7M_DWT is not set +# CONFIG_PKG_USING_VT100 is not set +# CONFIG_PKG_USING_UKAL is not set +# CONFIG_PKG_USING_CRCLIB is not set +# CONFIG_PKG_USING_LWGPS is not set +# CONFIG_PKG_USING_STATE_MACHINE is not set +# CONFIG_PKG_USING_MCURSES is not set +# CONFIG_PKG_USING_COWSAY is not set +# CONFIG_PKG_USING_TERMBOX is not set + +# +# Hardware Drivers Config +# +CONFIG_SOC_SERIES_GD32F20x=y +CONFIG_SOC_GD32205R=y + +# +# Onboard Peripheral Drivers +# + +# +# On-chip Peripheral Drivers +# +CONFIG_BSP_USING_GPIO=y +CONFIG_BSP_USING_UART=y +CONFIG_BSP_USING_UART1=y +# CONFIG_BSP_UART1_RX_USING_DMA is not set +# CONFIG_BSP_USING_SPI is not set +# CONFIG_BSP_USING_I2C1 is not set + +# +# Board extended module Drivers +# diff --git a/bsp/gd32/gd32205r-start/Kconfig b/bsp/gd32/gd32205r-start/Kconfig new file mode 100644 index 0000000000..8cbc7b71a8 --- /dev/null +++ b/bsp/gd32/gd32205r-start/Kconfig @@ -0,0 +1,21 @@ +mainmenu "RT-Thread Configuration" + +config BSP_DIR + string + option env="BSP_ROOT" + default "." + +config RTT_DIR + string + option env="RTT_ROOT" + default "../../.." + +config PKGS_DIR + string + option env="PKGS_ROOT" + default "packages" + +source "$RTT_DIR/Kconfig" +source "$PKGS_DIR/Kconfig" +source "../libraries/Kconfig" +source "board/Kconfig" diff --git a/bsp/gd32/gd32205r-start/README.md b/bsp/gd32/gd32205r-start/README.md new file mode 100644 index 0000000000..8a6fe8f125 --- /dev/null +++ b/bsp/gd32/gd32205r-start/README.md @@ -0,0 +1,98 @@ +# GD32205R-START开发板BSP说明 + +## 简介 + +GD32205R-START是-兆易创新推出的一款GD32F20X系列的评估板,最高主频高达120M,该开发板具有丰富的板载资源,可以充分发挥 GD32205R的芯片性能。 + +开发板外观如下图所示: + +![board](figures/board.jpg) + +该开发板常用 **板载资源** 如下: + +- GD32205R,主频 120MHz,256KB FLASH ,128KB RAM + +- 常用外设 + + - LED :2个,LED1 (电源指示灯),LED2(PC6) + - 按键:2个,K1(复位引脚),K2(用户按键,PA0) + +- 常用接口:USB 接口 + +- 调试接口:GD-LINK + +## 外设支持 + +本 BSP 目前对外设的支持情况如下: + +| **片上外设** | **支持情况** | **备注** | +|:--------- |:--------:|:------------------------------------- | +| GPIO | 支持 | PA0, PA1... PK15 ---> PIN: 0, 1...144 | +| UART | 支持 | UART0 - UART7 | +| I2C | 支持 | I2C1 | +| SPI | 支持 | SPI0. SPI1, SPI2 | +| SPI FLASH | 支持 | | +| **扩展模块** | **支持情况** | **备注** | +| 暂无 | 暂不支持 | 暂不支持 | + +## 使用说明 + +使用说明分为如下两个章节: + +- 快速上手 + + 本章节是为刚接触 RT-Thread 的新手准备的使用说明,遵循简单的步骤即可将 RT-Thread 操作系统运行在该开发板上,看到实验效果 。 + +- 进阶使用 + + 本章节是为需要在 RT-Thread 操作系统上使用更多开发板资源的开发者准备的。通过使用 ENV 工具对 BSP 进行配置,可以开启更多板载资源,实现更多高级功能。 + +### 快速上手 + +本 BSP 为开发者提供 MDK5 工程,并且支持 GCC 开发环境,也可使用RT-Thread Studio开发。下面以 MDK5 开发环境为例,介绍如何将系统运行起来。 + +#### 硬件连接 + +使用数据线连接开发板到 PC,使用USB转TTL模块连接PA2(MCU TX)和PA3(MCU RX),打开电源开关。 + +#### 编译下载 + +双击 project.uvprojx 文件,打开 MDK5 工程,编译并下载程序到开发板。 + +> 工程默认配置使用 GD-Link 仿真器下载程序,在通过 GD-Link 连接开发板的基础上,点击下载按钮即可下载程序到开发板 + +#### 运行结果 + +下载程序成功之后,系统会自动运行,LED 闪烁。 + +连接开发板对应串口到 PC , 在终端工具里打开相应的串口(115200-8-1-N),复位设备后,可以看到 RT-Thread 的输出信息: + +```bash + \ | / +- RT - Thread Operating System + / | \ 4.0.4 build Dec 19 2021 09:29:49 + 2006 - 2021 Copyright by rt-thread team +msh > +``` + +### 进阶使用 + +此 BSP 默认只开启了 GPIO 和 串口1的功能,如果需使用高级功能,需要利用 ENV 工具对BSP 进行配置,步骤如下: + +1. 在 bsp 下打开 env 工具。 + +2. 输入`menuconfig`命令配置工程,配置好之后保存退出。 + +3. 输入`pkgs --update`命令更新软件包。 + +4. 输入`scons --target=mdk4/mdk5/iar` 命令重新生成工程。 + +## 注意事项 + +暂无 + +## 联系人信息 + +维护人: + +- [BruceOu](https://github.com/Ouxiaolong/), 邮箱: \ No newline at end of file diff --git a/bsp/gd32/gd32205r-start/SConscript b/bsp/gd32/gd32205r-start/SConscript new file mode 100644 index 0000000000..20f7689c53 --- /dev/null +++ b/bsp/gd32/gd32205r-start/SConscript @@ -0,0 +1,15 @@ +# for module compiling +import os +Import('RTT_ROOT') +from building import * + +cwd = GetCurrentDir() +objs = [] +list = os.listdir(cwd) + +for d in list: + path = os.path.join(cwd, d) + if os.path.isfile(os.path.join(path, 'SConscript')): + objs = objs + SConscript(os.path.join(d, 'SConscript')) + +Return('objs') diff --git a/bsp/gd32/gd32205r-start/SConstruct b/bsp/gd32/gd32205r-start/SConstruct new file mode 100644 index 0000000000..14ab8b82ea --- /dev/null +++ b/bsp/gd32/gd32205r-start/SConstruct @@ -0,0 +1,60 @@ +import os +import sys +import rtconfig + +if os.getenv('RTT_ROOT'): + RTT_ROOT = os.getenv('RTT_ROOT') +else: + RTT_ROOT = os.path.normpath(os.getcwd() + '/../../..') + +sys.path = sys.path + [os.path.join(RTT_ROOT, 'tools')] +try: + from building import * +except: + print('Cannot found RT-Thread root directory, please check RTT_ROOT') + print(RTT_ROOT) + exit(-1) + +TARGET = 'rtthread.' + rtconfig.TARGET_EXT + +DefaultEnvironment(tools=[]) +env = Environment(tools = ['mingw'], + AS = rtconfig.AS, ASFLAGS = rtconfig.AFLAGS, + CC = rtconfig.CC, CCFLAGS = rtconfig.CFLAGS, + AR = rtconfig.AR, ARFLAGS = '-rc', + CXX = rtconfig.CXX, CXXFLAGS = rtconfig.CXXFLAGS, + LINK = rtconfig.LINK, LINKFLAGS = rtconfig.LFLAGS) +env.PrependENVPath('PATH', rtconfig.EXEC_PATH) + +if rtconfig.PLATFORM == 'iar': + env.Replace(CCCOM = ['$CC $CCFLAGS $CPPFLAGS $_CPPDEFFLAGS $_CPPINCFLAGS -o $TARGET $SOURCES']) + env.Replace(ARFLAGS = ['']) + env.Replace(LINKCOM = env["LINKCOM"] + ' --map rtthread.map') + +Export('RTT_ROOT') +Export('rtconfig') + +SDK_ROOT = os.path.abspath('./') + +if os.path.exists(SDK_ROOT + '/libraries'): + libraries_path_prefix = SDK_ROOT + '/libraries' +else: + libraries_path_prefix = os.path.dirname(SDK_ROOT) + '/libraries' + +SDK_LIB = libraries_path_prefix +Export('SDK_LIB') + +# prepare building environment +objs = PrepareBuilding(env, RTT_ROOT, has_libcpu=False) + +gd32_library = 'GD32F20x_Firmware_Library' +rtconfig.BSP_LIBRARY_TYPE = gd32_library + +# include libraries +objs.extend(SConscript(os.path.join(libraries_path_prefix, gd32_library, 'SConscript'))) + +# include drivers +objs.extend(SConscript(os.path.join(libraries_path_prefix, 'gd32_drivers', 'SConscript'))) + +# make a building +DoBuilding(TARGET, objs) diff --git a/bsp/gd32/gd32205r-start/applications/SConscript b/bsp/gd32/gd32205r-start/applications/SConscript new file mode 100644 index 0000000000..01eb940dfb --- /dev/null +++ b/bsp/gd32/gd32205r-start/applications/SConscript @@ -0,0 +1,11 @@ +Import('RTT_ROOT') +Import('rtconfig') +from building import * + +cwd = os.path.join(str(Dir('#')), 'applications') +src = Glob('*.c') +CPPPATH = [cwd, str(Dir('#'))] + +group = DefineGroup('Applications', src, depend = [''], CPPPATH = CPPPATH) + +Return('group') diff --git a/bsp/gd32/gd32205r-start/applications/main.c b/bsp/gd32/gd32205r-start/applications/main.c new file mode 100644 index 0000000000..fc35bb08e1 --- /dev/null +++ b/bsp/gd32/gd32205r-start/applications/main.c @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2006-2022, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2021-08-20 BruceOu first implementation + */ + +#include +#include +#include +#include + +/* defined the LED2 pin: PC6 */ +#define LED2_PIN GET_PIN(C, 6) + +int main(void) +{ + int count = 1; + + /* set LED2 pin mode to output */ + rt_pin_mode(LED2_PIN, PIN_MODE_OUTPUT); + + while (count++) + { + rt_pin_write(LED2_PIN, PIN_HIGH); + rt_thread_mdelay(500); + rt_pin_write(LED2_PIN, PIN_LOW); + rt_thread_mdelay(500); + } + + return RT_EOK; +} diff --git a/bsp/gd32/gd32205r-start/board/Kconfig b/bsp/gd32/gd32205r-start/board/Kconfig new file mode 100644 index 0000000000..49e208681b --- /dev/null +++ b/bsp/gd32/gd32205r-start/board/Kconfig @@ -0,0 +1,85 @@ +menu "Hardware Drivers Config" + +config SOC_SERIES_GD32F20x + bool + default y + +config SOC_GD32205R + bool + select SOC_SERIES_GD32F20x + select RT_USING_COMPONENTS_INIT + select RT_USING_USER_MAIN + default y + +menu "Onboard Peripheral Drivers" + +endmenu + +menu "On-chip Peripheral Drivers" + + config BSP_USING_GPIO + bool "Enable GPIO" + select RT_USING_PIN + default y + + menuconfig BSP_USING_UART + bool "Enable UART" + default y + select RT_USING_SERIAL + if BSP_USING_UART + config BSP_USING_UART1 + bool "Enable UART1" + default y + + config BSP_UART1_RX_USING_DMA + bool "Enable UART1 RX DMA" + depends on BSP_USING_UART1 && RT_SERIAL_USING_DMA + default n + endif + + menuconfig BSP_USING_SPI + bool "Enable SPI BUS" + default n + select RT_USING_SPI + if BSP_USING_SPI + config BSP_USING_SPI1 + bool "Enable SPI1 BUS" + default n + + config BSP_SPI1_TX_USING_DMA + bool "Enable SPI1 TX DMA" + depends on BSP_USING_SPI1 + default n + + config BSP_SPI1_RX_USING_DMA + bool "Enable SPI1 RX DMA" + depends on BSP_USING_SPI1 + select BSP_SPI1_TX_USING_DMA + default n + endif + + menuconfig BSP_USING_I2C1 + bool "Enable I2C1 BUS (software simulation)" + default n + select RT_USING_I2C + select RT_USING_I2C_BITOPS + select RT_USING_PIN + if BSP_USING_I2C1 + config BSP_I2C1_SCL_PIN + int "i2c1 scl pin number" + range 1 216 + default 24 + config BSP_I2C1_SDA_PIN + int "I2C1 sda pin number" + range 1 216 + default 25 + endif + source "../libraries/gd32_drivers/Kconfig" + +endmenu + +menu "Board extended module Drivers" + +endmenu + +endmenu diff --git a/bsp/gd32/gd32205r-start/board/SConscript b/bsp/gd32/gd32205r-start/board/SConscript new file mode 100644 index 0000000000..d1c8023578 --- /dev/null +++ b/bsp/gd32/gd32205r-start/board/SConscript @@ -0,0 +1,28 @@ +import os +import rtconfig +from building import * + +Import('SDK_LIB') + +cwd = GetCurrentDir() + +# add general drivers +src = Split(''' +board.c +''') + +path = [cwd] + +startup_path_prefix = SDK_LIB + +if rtconfig.CROSS_TOOL == 'gcc': + src += [startup_path_prefix + '/GD32F20x_Firmware_Library/CMSIS/GD/GD32F20x/Source/GCC/startup_gd32f20x_cl.s'] +elif rtconfig.CROSS_TOOL == 'keil': + src += [startup_path_prefix + '/GD32F20x_Firmware_Library/CMSIS/GD/GD32F20x/Source/ARM/startup_gd32f20x_cl.s'] +elif rtconfig.CROSS_TOOL == 'iar': + src += [startup_path_prefix + '/GD32F20x_Firmware_Library/CMSIS/GD/GD32F20x/Source/IAR/startup_gd32f20x_cl.s'] + +CPPDEFINES = ['GD32F20X_CL'] +group = DefineGroup('Drivers', src, depend = [''], CPPPATH = path, CPPDEFINES = CPPDEFINES) + +Return('group') diff --git a/bsp/gd32/gd32205r-start/board/board.c b/bsp/gd32/gd32205r-start/board/board.c new file mode 100644 index 0000000000..8331a86841 --- /dev/null +++ b/bsp/gd32/gd32205r-start/board/board.c @@ -0,0 +1,85 @@ +/* + * Copyright (c) 2006-2022, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2021-08-20 BruceOu first implementation + */ +#include +#include +#include +#include + +/** + * @brief This function is executed in case of error occurrence. + * @param None + * @retval None + */ +void Error_Handler(void) +{ + /* USER CODE BEGIN Error_Handler */ + /* User can add his own implementation to report the HAL error return state */ + while (1) + { + } + /* USER CODE END Error_Handler */ +} + +/** System Clock Configuration +*/ +void SystemClock_Config(void) +{ + SysTick_Config(SystemCoreClock / RT_TICK_PER_SECOND); + NVIC_SetPriority(SysTick_IRQn, 0); +} + +/** + * This is the timer interrupt service routine. + * + */ +void SysTick_Handler(void) +{ + /* enter interrupt */ + rt_interrupt_enter(); + + rt_tick_increase(); + + /* leave interrupt */ + rt_interrupt_leave(); +} + +/** + * This function will initial GD32 board. + */ +void rt_hw_board_init() +{ + /* NVIC Configuration */ +#define NVIC_VTOR_MASK 0x3FFFFF80 +#ifdef VECT_TAB_RAM + /* Set the Vector Table base location at 0x10000000 */ + SCB->VTOR = (0x10000000 & NVIC_VTOR_MASK); +#else /* VECT_TAB_FLASH */ + /* Set the Vector Table base location at 0x08000000 */ + SCB->VTOR = (0x08000000 & NVIC_VTOR_MASK); +#endif + + SystemClock_Config(); + +#ifdef RT_USING_COMPONENTS_INIT + rt_components_board_init(); +#endif + +#ifdef RT_USING_CONSOLE + rt_console_set_device(RT_CONSOLE_DEVICE_NAME); +#endif + +#ifdef BSP_USING_SDRAM + rt_system_heap_init((void *)EXT_SDRAM_BEGIN, (void *)EXT_SDRAM_END); +#else + rt_system_heap_init((void *)HEAP_BEGIN, (void *)HEAP_END); +#endif +} + +/*@}*/ diff --git a/bsp/gd32/gd32205r-start/board/board.h b/bsp/gd32/gd32205r-start/board/board.h new file mode 100644 index 0000000000..9c42e83ac1 --- /dev/null +++ b/bsp/gd32/gd32205r-start/board/board.h @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2006-2022, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2021-12-18 BruceOu first implementation + */ +#ifndef __BOARD_H__ +#define __BOARD_H__ + +#include "gd32f20x.h" +#include "drv_usart.h" +#include "drv_gpio.h" + +#include "gd32f20x_exti.h" + +#define EXT_SDRAM_BEGIN (0xC0000000U) /* the begining address of external SDRAM */ +#define EXT_SDRAM_END (EXT_SDRAM_BEGIN + (32U * 1024 * 1024)) /* the end address of external SDRAM */ + +// Internal SRAM memory size[Kbytes] <8-128> +// Default: 128 +#ifdef __ICCARM__ +// Use *.icf ram symbal, to avoid hardcode. +extern char __ICFEDIT_region_RAM_end__; +#define GD32_SRAM_END &__ICFEDIT_region_RAM_end__ +#else +#define GD32_SRAM_SIZE 128 +#define GD32_SRAM_END (0x20000000 + GD32_SRAM_SIZE * 1024) +#endif + +#ifdef __CC_ARM +extern int Image$$RW_IRAM1$$ZI$$Limit; +#define HEAP_BEGIN (&Image$$RW_IRAM1$$ZI$$Limit) +#elif __ICCARM__ +#pragma section="HEAP" +#define HEAP_BEGIN (__segment_end("HEAP")) +#else +extern int __bss_end; +#define HEAP_BEGIN (&__bss_end) +#endif + +#define HEAP_END GD32_SRAM_END + +#endif + diff --git a/bsp/gd32/gd32205r-start/board/gd32f20x_libopt.h b/bsp/gd32/gd32205r-start/board/gd32f20x_libopt.h new file mode 100644 index 0000000000..bd38888220 --- /dev/null +++ b/bsp/gd32/gd32205r-start/board/gd32f20x_libopt.h @@ -0,0 +1,70 @@ +/*! + \file gd32f20x_libopt.h + \brief library optional for gd32f20x + + \version 2015-07-15, V1.0.0, demo for GD32F20x + \version 2017-06-05, V2.0.0, demo for GD32F20x + \version 2019-04-01, V2.1.0, demo for GD32F20x + \version 2020-09-30, V2.2.0, demo for GD32F20x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef GD32F20X_LIBOPT_H +#define GD32F20X_LIBOPT_H + +#include "gd32f20x_adc.h" +#include "gd32f20x_bkp.h" +#include "gd32f20x_can.h" +#include "gd32f20x_crc.h" +#include "gd32f20x_cau.h" +#include "gd32f20x_dac.h" +#include "gd32f20x_dci.h" +#include "gd32f20x_dma.h" +#include "gd32f20x_enet.h" +#include "gd32f20x_exmc.h" +#include "gd32f20x_exti.h" +#include "gd32f20x_fmc.h" +#include "gd32f20x_gpio.h" +#include "gd32f20x_hau.h" +#include "gd32f20x_i2c.h" +#include "gd32f20x_fwdgt.h" +#include "gd32f20x_dbg.h" +#include "gd32f20x_misc.h" +#include "gd32f20x_pmu.h" +#include "gd32f20x_rcu.h" +#include "gd32f20x_trng.h" +#include "gd32f20x_rtc.h" +#include "gd32f20x_sdio.h" +#include "gd32f20x_spi.h" +#include "gd32f20x_timer.h" +#include "gd32f20x_tli.h" +#include "gd32f20x_usart.h" +#include "gd32f20x_wwdgt.h" + +#endif /* GD32F20X_LIBOPT_H */ diff --git a/bsp/gd32/gd32205r-start/board/linker_scripts/link.icf b/bsp/gd32/gd32205r-start/board/linker_scripts/link.icf new file mode 100644 index 0000000000..ac4747c3cb --- /dev/null +++ b/bsp/gd32/gd32205r-start/board/linker_scripts/link.icf @@ -0,0 +1,40 @@ +/*###ICF### Section handled by ICF editor, don't touch! ****/ +/*-Editor annotation file-*/ +/* IcfEditorFile="$TOOLKIT_DIR$\config\ide\IcfEditor\cortex_v1_0.xml" */ +/*-Specials-*/ +define symbol __ICFEDIT_intvec_start__ = 0x08000000; +/*-Memory Regions-*/ +define symbol __ICFEDIT_region_ROM_start__ = 0x08000000; +define symbol __ICFEDIT_region_ROM_end__ = 0x0803FFFF; +define symbol __ICFEDIT_region_RAM_start__ = 0x20000000; +define symbol __ICFEDIT_region_RAM_end__ = 0x2001FFFF; +/*-Sizes-*/ +define symbol __ICFEDIT_size_cstack__ = 0x2000; +define symbol __ICFEDIT_size_heap__ = 0x2000; +/**** End of ICF editor section. ###ICF###*/ + +export symbol __ICFEDIT_region_RAM_end__; + +define symbol __region_RAM1_start__ = 0x10000000; +define symbol __region_RAM1_end__ = 0x1000FFFF; + +define memory mem with size = 4G; +define region ROM_region = mem:[from __ICFEDIT_region_ROM_start__ to __ICFEDIT_region_ROM_end__]; +define region RAM_region = mem:[from __ICFEDIT_region_RAM_start__ to __ICFEDIT_region_RAM_end__]; +define region RAM1_region = mem:[from __region_RAM1_start__ to __region_RAM1_end__]; + +define block CSTACK with alignment = 8, size = __ICFEDIT_size_cstack__ { }; +define block HEAP with alignment = 8, size = __ICFEDIT_size_heap__ { }; + +initialize by copy { readwrite }; +do not initialize { section .noinit }; + +keep { section FSymTab }; +keep { section VSymTab }; +keep { section .rti_fn* }; +place at address mem:__ICFEDIT_intvec_start__ { readonly section .intvec }; + +place in ROM_region { readonly }; +place in RAM_region { readwrite, + block CSTACK, block HEAP }; +place in RAM1_region { section .sram }; \ No newline at end of file diff --git a/bsp/gd32/gd32205r-start/board/linker_scripts/link.ld b/bsp/gd32/gd32205r-start/board/linker_scripts/link.ld new file mode 100644 index 0000000000..dbb8d1bf13 --- /dev/null +++ b/bsp/gd32/gd32205r-start/board/linker_scripts/link.ld @@ -0,0 +1,142 @@ +/* + * linker script for GD32F4xx with GNU ld + * bernard.xiong 2009-10-14 + */ + +/* Program Entry, set to mark it as "used" and avoid gc */ +MEMORY +{ + CODE (rx) : ORIGIN = 0x08000000, LENGTH = 256k /* 256KB flash */ + DATA (rw) : ORIGIN = 0x20000000, LENGTH = 128k /* 128KB sram */ +} +ENTRY(Reset_Handler) +_system_stack_size = 0x200; + +SECTIONS +{ + .text : + { + . = ALIGN(4); + _stext = .; + KEEP(*(.isr_vector)) /* Startup code */ + . = ALIGN(4); + *(.text) /* remaining code */ + *(.text.*) /* remaining code */ + *(.rodata) /* read-only data (constants) */ + *(.rodata*) + *(.glue_7) + *(.glue_7t) + *(.gnu.linkonce.t*) + + /* section information for finsh shell */ + . = ALIGN(4); + __fsymtab_start = .; + KEEP(*(FSymTab)) + __fsymtab_end = .; + . = ALIGN(4); + __vsymtab_start = .; + KEEP(*(VSymTab)) + __vsymtab_end = .; + . = ALIGN(4); + + /* section information for initial. */ + . = ALIGN(4); + __rt_init_start = .; + KEEP(*(SORT(.rti_fn*))) + __rt_init_end = .; + . = ALIGN(4); + + . = ALIGN(4); + _etext = .; + } > CODE = 0 + + /* .ARM.exidx is sorted, so has to go in its own output section. */ + __exidx_start = .; + .ARM.exidx : + { + *(.ARM.exidx* .gnu.linkonce.armexidx.*) + + /* This is used by the startup in order to initialize the .data secion */ + _sidata = .; + } > CODE + __exidx_end = .; + + /* .data section which is used for initialized data */ + + .data : AT (_sidata) + { + . = ALIGN(4); + /* This is used by the startup in order to initialize the .data secion */ + _sdata = . ; + + *(.data) + *(.data.*) + *(.gnu.linkonce.d*) + + . = ALIGN(4); + /* This is used by the startup in order to initialize the .data secion */ + _edata = . ; + } >DATA + + .stack : + { + . = . + _system_stack_size; + . = ALIGN(4); + _estack = .; + } >DATA + + __bss_start = .; + .bss : + { + . = ALIGN(4); + /* This is used by the startup in order to initialize the .bss secion */ + _sbss = .; + + *(.bss) + *(.bss.*) + *(COMMON) + + . = ALIGN(4); + /* This is used by the startup in order to initialize the .bss secion */ + _ebss = . ; + + *(.bss.init) + } > DATA + __bss_end = .; + + _end = .; + + /* Stabs debugging sections. */ + .stab 0 : { *(.stab) } + .stabstr 0 : { *(.stabstr) } + .stab.excl 0 : { *(.stab.excl) } + .stab.exclstr 0 : { *(.stab.exclstr) } + .stab.index 0 : { *(.stab.index) } + .stab.indexstr 0 : { *(.stab.indexstr) } + .comment 0 : { *(.comment) } + /* DWARF debug sections. + * Symbols in the DWARF debugging sections are relative to the beginning + * of the section so we begin them at 0. */ + /* DWARF 1 */ + .debug 0 : { *(.debug) } + .line 0 : { *(.line) } + /* GNU DWARF 1 extensions */ + .debug_srcinfo 0 : { *(.debug_srcinfo) } + .debug_sfnames 0 : { *(.debug_sfnames) } + /* DWARF 1.1 and DWARF 2 */ + .debug_aranges 0 : { *(.debug_aranges) } + .debug_pubnames 0 : { *(.debug_pubnames) } + /* DWARF 2 */ + .debug_info 0 : { *(.debug_info .gnu.linkonce.wi.*) } + .debug_abbrev 0 : { *(.debug_abbrev) } + .debug_line 0 : { *(.debug_line) } + .debug_frame 0 : { *(.debug_frame) } + .debug_str 0 : { *(.debug_str) } + .debug_loc 0 : { *(.debug_loc) } + .debug_macinfo 0 : { *(.debug_macinfo) } + /* SGI/MIPS DWARF 2 extensions */ + .debug_weaknames 0 : { *(.debug_weaknames) } + .debug_funcnames 0 : { *(.debug_funcnames) } + .debug_typenames 0 : { *(.debug_typenames) } + .debug_varnames 0 : { *(.debug_varnames) } +} diff --git a/bsp/gd32/gd32205r-start/board/linker_scripts/link.sct b/bsp/gd32/gd32205r-start/board/linker_scripts/link.sct new file mode 100644 index 0000000000..f314c4bd58 --- /dev/null +++ b/bsp/gd32/gd32205r-start/board/linker_scripts/link.sct @@ -0,0 +1,15 @@ +; ************************************************************* +; *** Scatter-Loading Description File generated by uVision *** +; ************************************************************* + +LR_IROM1 0x08000000 0x00040000 { ; load region size_region + ER_IROM1 0x08000000 0x00040000 { ; load address = execution address + *.o (RESET, +First) + *(InRoot$$Sections) + .ANY (+RO) + } + RW_IRAM1 0x20000000 0x00020000 { ; RW data + .ANY (+RW +ZI) + } +} + diff --git a/bsp/gd32/gd32205r-start/figures/board.jpg b/bsp/gd32/gd32205r-start/figures/board.jpg new file mode 100644 index 0000000000..cc15375497 Binary files /dev/null and b/bsp/gd32/gd32205r-start/figures/board.jpg differ diff --git a/bsp/gd32/gd32205r-start/project.uvoptx b/bsp/gd32/gd32205r-start/project.uvoptx new file mode 100644 index 0000000000..3511a69bb3 --- /dev/null +++ b/bsp/gd32/gd32205r-start/project.uvoptx @@ -0,0 +1,180 @@ + + + + 1.0 + +
### uVision Project, (C) Keil Software
+ + + *.c + *.s*; *.src; *.a* + *.obj; *.o + *.lib + *.txt; *.h; *.inc + *.plm + *.cpp + 0 + + + + 0 + 0 + + + + rt-thread + 0x4 + ARM-ADS + + 12000000 + + 1 + 1 + 0 + 1 + 0 + + + 1 + 65535 + 0 + 0 + 0 + + + 79 + 66 + 8 + .\build\ + + + 1 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 0 + 0 + 0 + 0 + + + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 0 + 0 + + + 0 + 0 + 1 + + 255 + + 0 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 0 + 1 + 1 + 1 + 1 + 0 + 0 + 1 + 0 + 0 + 3 + + + + + + + + + + + BIN\CMSIS_AGDI.dll + + + + 0 + UL2CM3 + UL2CM3(-S0 -C0 -P0 -FD20000000 -FC1000 -FN1 -FF0GD32F20x_CL -FS08000000 -FL040000 -FP0($$Device:GD32F205RC$Flash\GD32F20x_CL.FLM)) + + + + + 0 + + + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + + + + 0 + 0 + 0 + + + + + + + + + + + + + ::CMSIS + 0 + 0 + 0 + 1 + + +
diff --git a/bsp/gd32/gd32205r-start/project.uvproj b/bsp/gd32/gd32205r-start/project.uvproj new file mode 100644 index 0000000000..965219aac8 --- /dev/null +++ b/bsp/gd32/gd32205r-start/project.uvproj @@ -0,0 +1,737 @@ + + + 1.1 +
### uVision Project, (C) Keil Software
+ + + rt-thread + 0x4 + ARM-ADS + 0 + + + GD32F205RC + GigaDevice + IRAM(0x20000000-0x020000) IROM(0x08000000-0x040000) CLOCK(12000000) CPUTYPE("Cortex-M3") + + "Startup\GD\GD32F20x\startup_gd32f20x.s" ("GD32F20x Startup Code") + UL2CM3(-O207 -S0 -C0 -FO7 -FD20000000 -FC800 -FN1 -FF0GD32F20x_3MB -FS08000000 -FL0300000) + 0 + gd32f20x0.h + + + + + + + + + + SFD\GD\GD32F20x\GD32F20x.SFR + 0 + 0 + + + + GD\GD32F20x\ + GD\GD32F20x\ + + 0 + 0 + 0 + 0 + 1 + + .\output\ + rtthread + 1 + 0 + 1 + 1 + 1 + .\build\ + 1 + 0 + 0 + + 0 + 0 + + + 0 + 0 + 0 + 0 + + + 0 + 0 + + + 0 + 0 + 0 + 0 + + + 0 + 0 + + + 0 + 0 + 0 + 0 + + 0 + + + + 0 + 0 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 0 + 3 + + + 1 + + + SARMCM3.DLL + -REMAP + DCM.DLL + -pCM3 + SARMCM3.DLL + + TCM.DLL + -pCM3 + + + + 1 + 0 + 0 + 0 + 16 + + + 0 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 0 + 1 + + + 1 + 1 + 1 + 1 + 1 + 1 + 0 + 1 + 0 + 1 + + 0 + 3 + + + + + + + + + + + + + + BIN\CMSIS_AGDI.dll + + + + + 1 + 0 + 0 + 1 + 1 + 4096 + + 1 + BIN\UL2CM3.DLL + "" () + + + + + 0 + + + + 0 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 0 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 0 + 0 + "Cortex-M3" + + 0 + 0 + 0 + 1 + 1 + 0 + 0 + 2 + 1 + 0 + 8 + 1 + 0 + 0 + 0 + 3 + 3 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 0 + 1 + 0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x20000000 + 0x30000 + + + 1 + 0x8000000 + 0x300000 + + + 0 + 0x0 + 0x0 + + + 1 + 0x0 + 0x0 + + + 1 + 0x0 + 0x0 + + + 1 + 0x0 + 0x0 + + + 1 + 0x8000000 + 0x300000 + + + 1 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x20000000 + 0x30000 + + + 0 + 0x10000000 + 0x10000 + + + + + + 1 + 1 + 0 + 0 + 1 + 0 + 0 + 0 + 0 + 0 + 2 + 0 + 0 + 1 + 0 + 0 + 1 + 1 + 1 + 1 + 0 + 0 + 0 + + + __CLK_TCK=RT_TICK_PER_SECOND, USE_STDPERIPH_DRIVER, __RTTHREAD__, GD32F20X_CL + + applications;.;..\..\..\libcpu\arm\common;..\..\..\libcpu\arm\cortex-m3;..\..\..\components\drivers\include;..\..\..\components\drivers\include;..\..\..\components\drivers\include;board;..\libraries\gd32_drivers;..\..\..\components\finsh;.;..\..\..\include;..\..\..\components\libc\compilers\common;..\..\..\components\libc\compilers\common\nogcc;..\libraries\GD32F20x_Firmware_Library\CMSIS\GD\GD32F20x\Include;..\libraries\GD32F20x_Firmware_Library\CMSIS;..\libraries\GD32F20x_Firmware_Library\GD32F20x_standard_peripheral\Include;..\..\..\components\libc\posix\io\poll;..\..\..\components\libc\posix\ipc;..\..\..\examples\utest\testcases\kernel + + + + 1 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + + + + + + + + + 1 + 0 + 0 + 0 + 1 + 0 + 0x08000000 + 0x20000000 + + + + + + + + + + + + + Applications + + + main.c + 1 + applications\main.c + + + + + CPU + + + backtrace.c + 1 + ..\..\..\libcpu\arm\common\backtrace.c + + + + + div0.c + 1 + ..\..\..\libcpu\arm\common\div0.c + + + + + showmem.c + 1 + ..\..\..\libcpu\arm\common\showmem.c + + + + + cpuport.c + 1 + ..\..\..\libcpu\arm\cortex-m3\cpuport.c + + + + + context_rvds.S + 2 + ..\..\..\libcpu\arm\cortex-m3\context_rvds.S + + + + + DeviceDrivers + + + pin.c + 1 + ..\..\..\components\drivers\misc\pin.c + + + + + serial.c + 1 + ..\..\..\components\drivers\serial\serial.c + + + + + ringbuffer.c + 1 + ..\..\..\components\drivers\src\ringbuffer.c + + + + + pipe.c + 1 + ..\..\..\components\drivers\src\pipe.c + + + + + workqueue.c + 1 + ..\..\..\components\drivers\src\workqueue.c + + + + + waitqueue.c + 1 + ..\..\..\components\drivers\src\waitqueue.c + + + + + completion.c + 1 + ..\..\..\components\drivers\src\completion.c + + + + + ringblk_buf.c + 1 + ..\..\..\components\drivers\src\ringblk_buf.c + + + + + dataqueue.c + 1 + ..\..\..\components\drivers\src\dataqueue.c + + + + + Drivers + + + startup_gd32f20x_cl.s + 2 + ..\libraries\GD32F20x_Firmware_Library\CMSIS\GD\GD32F20x\Source\ARM\startup_gd32f20x_cl.s + + + + + board.c + 1 + board\board.c + + + + + drv_gpio.c + 1 + ..\libraries\gd32_drivers\drv_gpio.c + + + + + drv_usart.c + 1 + ..\libraries\gd32_drivers\drv_usart.c + + + + + Finsh + + + shell.c + 1 + ..\..\..\components\finsh\shell.c + + + + + msh.c + 1 + ..\..\..\components\finsh\msh.c + + + + + cmd.c + 1 + ..\..\..\components\finsh\cmd.c + + + + + Kernel + + + ipc.c + 1 + ..\..\..\src\ipc.c + + + + + thread.c + 1 + ..\..\..\src\thread.c + + + + + mem.c + 1 + ..\..\..\src\mem.c + + + + + device.c + 1 + ..\..\..\src\device.c + + + + + idle.c + 1 + ..\..\..\src\idle.c + + + + + object.c + 1 + ..\..\..\src\object.c + + + + + mempool.c + 1 + ..\..\..\src\mempool.c + + + + + clock.c + 1 + ..\..\..\src\clock.c + + + + + irq.c + 1 + ..\..\..\src\irq.c + + + + + timer.c + 1 + ..\..\..\src\timer.c + + + + + components.c + 1 + ..\..\..\src\components.c + + + + + kservice.c + 1 + ..\..\..\src\kservice.c + + + + + scheduler.c + 1 + ..\..\..\src\scheduler.c + + + + + libc + + + time.c + 1 + ..\..\..\components\libc\compilers\common\time.c + + + + + Libraries + + + system_gd32f20x.c + 1 + ..\libraries\GD32F20x_Firmware_Library\CMSIS\GD\GD32F20x\Source\system_gd32f20x.c + + + + + gd32f20x_exti.c + 1 + ..\libraries\GD32F20x_Firmware_Library\GD32F20x_standard_peripheral\Source\gd32f20x_exti.c + + + + + gd32f20x_gpio.c + 1 + ..\libraries\GD32F20x_Firmware_Library\GD32F20x_standard_peripheral\Source\gd32f20x_gpio.c + + + + + gd32f20x_misc.c + 1 + ..\libraries\GD32F20x_Firmware_Library\GD32F20x_standard_peripheral\Source\gd32f20x_misc.c + + + + + gd32f20x_rcu.c + 1 + ..\libraries\GD32F20x_Firmware_Library\GD32F20x_standard_peripheral\Source\gd32f20x_rcu.c + + + + + gd32f20x_usart.c + 1 + ..\libraries\GD32F20x_Firmware_Library\GD32F20x_standard_peripheral\Source\gd32f20x_usart.c + + + + + + +
diff --git a/bsp/gd32/gd32205r-start/project.uvprojx b/bsp/gd32/gd32205r-start/project.uvprojx new file mode 100644 index 0000000000..7799e20a62 --- /dev/null +++ b/bsp/gd32/gd32205r-start/project.uvprojx @@ -0,0 +1,726 @@ + + + 2.1 +
### uVision Project, (C) Keil Software
+ + + rt-thread + 0x4 + ARM-ADS + 0 + + + GD32F205RC + GigaDevice + GigaDevice.GD32F20x_DFP.2.2.0 + http://gd32mcu.com/data/documents/pack/ + IRAM(0x20000000,0x020000) IROM(0x08000000,0x040000) CPUTYPE("Cortex-M3") CLOCK(12000000) ELITTLE + + + UL2CM3(-S0 -C0 -P0 -FD20000000 -FC1000 -FN1 -FF0GD32F20x_CL -FS08000000 -FL040000 -FP0($$Device:GD32F205RC$Flash\GD32F20x_CL.FLM)) + 0 + $$Device:GD32F205RC$Device\Include\gd32f20x.h + + + + + + + + + + $$Device:GD32F205RC$SVD\GD32F20x_CL.svd + 0 + 0 + + + + + + + 0 + 0 + 0 + 0 + 1 + + .\build\ + rtthread + 1 + 0 + 0 + 1 + 0 + .\build\ + 1 + 0 + 0 + + 0 + 0 + + + 0 + 0 + 0 + 0 + + + 0 + 0 + + + 0 + 0 + 0 + 0 + + + 1 + 0 + fromelf --bin !L --output rtthread.bin + + 0 + 0 + 0 + 0 + + 0 + + + + 0 + 0 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 0 + 3 + + + 1 + + + SARMCM3.DLL + -REMAP + DCM.DLL + -pCM3 + SARMCM3.DLL + + TCM.DLL + -pCM3 + + + + 1 + 0 + 0 + 0 + 16 + + + + + 1 + 0 + 0 + 1 + 1 + 4096 + + 1 + BIN\UL2CM3.DLL + + + + + + 0 + + + + 0 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 0 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 0 + 0 + "Cortex-M3" + + 0 + 0 + 0 + 1 + 1 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 8 + 0 + 0 + 0 + 0 + 3 + 3 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 0 + 1 + 0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x20000000 + 0x20000 + + + 1 + 0x8000000 + 0x40000 + + + 0 + 0x0 + 0x0 + + + 1 + 0x0 + 0x0 + + + 1 + 0x0 + 0x0 + + + 1 + 0x0 + 0x0 + + + 1 + 0x8000000 + 0x40000 + + + 1 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x20000000 + 0x20000 + + + 0 + 0x0 + 0x0 + + + + + + 1 + 4 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 1 + 0 + 0 + 1 + 1 + 1 + 1 + 0 + 0 + 0 + + + __CLK_TCK=RT_TICK_PER_SECOND, USE_STDPERIPH_DRIVER, __RTTHREAD__, GD32F20X_CL + + applications;.;..\..\..\libcpu\arm\common;..\..\..\libcpu\arm\cortex-m3;..\..\..\components\drivers\include;..\..\..\components\drivers\include;..\..\..\components\drivers\include;board;..\libraries\gd32_drivers;..\..\..\components\finsh;.;..\..\..\include;..\..\..\components\libc\compilers\common;..\..\..\components\libc\compilers\common\nogcc;..\libraries\GD32F20x_Firmware_Library\CMSIS\GD\GD32F20x\Include;..\libraries\GD32F20x_Firmware_Library\CMSIS;..\libraries\GD32F20x_Firmware_Library\GD32F20x_standard_peripheral\Include;..\..\..\components\libc\posix\io\poll;..\..\..\components\libc\posix\ipc;..\..\..\examples\utest\testcases\kernel + + + + 1 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 4 + + + + + + + + + 1 + 0 + 0 + 0 + 1 + 0 + 0x08000000 + 0x20000000 + + .\gd32_rom.ld + + + + + + + + + + + Applications + + + main.c + 1 + applications\main.c + + + + + CPU + + + showmem.c + 1 + ..\..\..\libcpu\arm\common\showmem.c + + + + + div0.c + 1 + ..\..\..\libcpu\arm\common\div0.c + + + + + backtrace.c + 1 + ..\..\..\libcpu\arm\common\backtrace.c + + + + + cpuport.c + 1 + ..\..\..\libcpu\arm\cortex-m3\cpuport.c + + + + + context_rvds.S + 2 + ..\..\..\libcpu\arm\cortex-m3\context_rvds.S + + + + + DeviceDrivers + + + pin.c + 1 + ..\..\..\components\drivers\misc\pin.c + + + + + serial.c + 1 + ..\..\..\components\drivers\serial\serial.c + + + + + ringbuffer.c + 1 + ..\..\..\components\drivers\src\ringbuffer.c + + + + + waitqueue.c + 1 + ..\..\..\components\drivers\src\waitqueue.c + + + + + dataqueue.c + 1 + ..\..\..\components\drivers\src\dataqueue.c + + + + + pipe.c + 1 + ..\..\..\components\drivers\src\pipe.c + + + + + workqueue.c + 1 + ..\..\..\components\drivers\src\workqueue.c + + + + + ringblk_buf.c + 1 + ..\..\..\components\drivers\src\ringblk_buf.c + + + + + completion.c + 1 + ..\..\..\components\drivers\src\completion.c + + + + + Drivers + + + startup_gd32f20x_cl.s + 2 + ..\libraries\GD32F20x_Firmware_Library\CMSIS\GD\GD32F20x\Source\ARM\startup_gd32f20x_cl.s + + + + + board.c + 1 + board\board.c + + + + + drv_gpio.c + 1 + ..\libraries\gd32_drivers\drv_gpio.c + + + + + drv_usart.c + 1 + ..\libraries\gd32_drivers\drv_usart.c + + + + + Finsh + + + shell.c + 1 + ..\..\..\components\finsh\shell.c + + + + + msh.c + 1 + ..\..\..\components\finsh\msh.c + + + + + cmd.c + 1 + ..\..\..\components\finsh\cmd.c + + + + + Kernel + + + idle.c + 1 + ..\..\..\src\idle.c + + + + + ipc.c + 1 + ..\..\..\src\ipc.c + + + + + components.c + 1 + ..\..\..\src\components.c + + + + + object.c + 1 + ..\..\..\src\object.c + + + + + thread.c + 1 + ..\..\..\src\thread.c + + + + + mempool.c + 1 + ..\..\..\src\mempool.c + + + + + irq.c + 1 + ..\..\..\src\irq.c + + + + + mem.c + 1 + ..\..\..\src\mem.c + + + + + scheduler.c + 1 + ..\..\..\src\scheduler.c + + + + + kservice.c + 1 + ..\..\..\src\kservice.c + + + + + timer.c + 1 + ..\..\..\src\timer.c + + + + + device.c + 1 + ..\..\..\src\device.c + + + + + clock.c + 1 + ..\..\..\src\clock.c + + + + + libc + + + time.c + 1 + ..\..\..\components\libc\compilers\common\time.c + + + + + Libraries + + + system_gd32f20x.c + 1 + ..\libraries\GD32F20x_Firmware_Library\CMSIS\GD\GD32F20x\Source\system_gd32f20x.c + + + + + gd32f20x_exti.c + 1 + ..\libraries\GD32F20x_Firmware_Library\GD32F20x_standard_peripheral\Source\gd32f20x_exti.c + + + + + gd32f20x_gpio.c + 1 + ..\libraries\GD32F20x_Firmware_Library\GD32F20x_standard_peripheral\Source\gd32f20x_gpio.c + + + + + gd32f20x_misc.c + 1 + ..\libraries\GD32F20x_Firmware_Library\GD32F20x_standard_peripheral\Source\gd32f20x_misc.c + + + + + gd32f20x_rcu.c + 1 + ..\libraries\GD32F20x_Firmware_Library\GD32F20x_standard_peripheral\Source\gd32f20x_rcu.c + + + + + gd32f20x_usart.c + 1 + ..\libraries\GD32F20x_Firmware_Library\GD32F20x_standard_peripheral\Source\gd32f20x_usart.c + + + + + + + + + + + + + + + + + + + + + + <Project Info> + + + + + + 0 + 1 + + + +
diff --git a/bsp/gd32/gd32205r-start/rtconfig.h b/bsp/gd32/gd32205r-start/rtconfig.h new file mode 100644 index 0000000000..f685958fd3 --- /dev/null +++ b/bsp/gd32/gd32205r-start/rtconfig.h @@ -0,0 +1,200 @@ +#ifndef RT_CONFIG_H__ +#define RT_CONFIG_H__ + +/* Automatically generated file; DO NOT EDIT. */ +/* RT-Thread Configuration */ + +/* RT-Thread Kernel */ + +#define RT_NAME_MAX 8 +#define RT_ALIGN_SIZE 4 +#define RT_THREAD_PRIORITY_32 +#define RT_THREAD_PRIORITY_MAX 32 +#define RT_TICK_PER_SECOND 100 +#define RT_USING_OVERFLOW_CHECK +#define RT_USING_HOOK +#define RT_USING_IDLE_HOOK +#define RT_IDLE_HOOK_LIST_SIZE 4 +#define IDLE_THREAD_STACK_SIZE 256 + +/* kservice optimization */ + +#define RT_DEBUG +#define RT_DEBUG_COLOR + +/* Inter-Thread communication */ + +#define RT_USING_SEMAPHORE +#define RT_USING_MUTEX +#define RT_USING_EVENT +#define RT_USING_MAILBOX +#define RT_USING_MESSAGEQUEUE + +/* Memory Management */ + +#define RT_USING_MEMPOOL +#define RT_USING_SMALL_MEM +#define RT_USING_HEAP + +/* Kernel Device Object */ + +#define RT_USING_DEVICE +#define RT_USING_CONSOLE +#define RT_CONSOLEBUF_SIZE 128 +#define RT_CONSOLE_DEVICE_NAME "uart1" +#define RT_VER_NUM 0x40004 + +/* RT-Thread Components */ + +#define RT_USING_COMPONENTS_INIT +#define RT_USING_USER_MAIN +#define RT_MAIN_THREAD_STACK_SIZE 2048 +#define RT_MAIN_THREAD_PRIORITY 10 + +/* C++ features */ + + +/* Command shell */ + +#define RT_USING_FINSH +#define RT_USING_MSH +#define FINSH_USING_MSH +#define FINSH_THREAD_NAME "tshell" +#define FINSH_THREAD_PRIORITY 20 +#define FINSH_THREAD_STACK_SIZE 4096 +#define FINSH_USING_HISTORY +#define FINSH_HISTORY_LINES 5 +#define FINSH_USING_SYMTAB +#define FINSH_CMD_SIZE 80 +#define MSH_USING_BUILT_IN_COMMANDS +#define FINSH_USING_DESCRIPTION +#define FINSH_ARG_MAX 10 + +/* Device virtual file system */ + + +/* Device Drivers */ + +#define RT_USING_DEVICE_IPC +#define RT_PIPE_BUFSZ 512 +#define RT_USING_SYSTEM_WORKQUEUE +#define RT_SYSTEM_WORKQUEUE_STACKSIZE 2048 +#define RT_SYSTEM_WORKQUEUE_PRIORITY 23 +#define RT_USING_SERIAL +#define RT_USING_SERIAL_V1 +#define RT_SERIAL_USING_DMA +#define RT_SERIAL_RB_BUFSZ 64 +#define RT_USING_PIN + +/* Using USB */ + + +/* POSIX layer and C standard library */ + +#define RT_LIBC_USING_TIME +#define RT_LIBC_DEFAULT_TIMEZONE 8 + +/* Network */ + +/* Socket abstraction layer */ + + +/* Network interface device */ + + +/* light weight TCP/IP stack */ + + +/* AT commands */ + + +/* VBUS(Virtual Software BUS) */ + + +/* Utilities */ + + +/* RT-Thread Utestcases */ + + +/* RT-Thread online packages */ + +/* IoT - internet of things */ + + +/* Wi-Fi */ + +/* Marvell WiFi */ + + +/* Wiced WiFi */ + + +/* IoT Cloud */ + + +/* security packages */ + + +/* language packages */ + + +/* multimedia packages */ + +/* LVGL: powerful and easy-to-use embedded GUI library */ + + +/* u8g2: a monochrome graphic library */ + + +/* PainterEngine: A cross-platform graphics application framework written in C language */ + + +/* tools packages */ + + +/* system packages */ + +/* enhanced kernel services */ + + +/* acceleration: Assembly language or algorithmic acceleration packages */ + + +/* CMSIS: ARM Cortex-M Microcontroller Software Interface Standard */ + + +/* Micrium: Micrium software products porting for RT-Thread */ + + +/* peripheral libraries and drivers */ + + +/* AI packages */ + + +/* miscellaneous packages */ + +/* samples: kernel and components samples */ + + +/* entertainment: terminal games and other interesting software packages */ + + +/* Hardware Drivers Config */ + +#define SOC_SERIES_GD32F20x +#define SOC_GD32205R + +/* Onboard Peripheral Drivers */ + +/* On-chip Peripheral Drivers */ + +#define BSP_USING_GPIO +#define BSP_USING_UART +#define BSP_USING_UART1 + +/* Board extended module Drivers */ + + +#endif diff --git a/bsp/gd32/gd32205r-start/rtconfig.py b/bsp/gd32/gd32205r-start/rtconfig.py new file mode 100644 index 0000000000..4285e6b03c --- /dev/null +++ b/bsp/gd32/gd32205r-start/rtconfig.py @@ -0,0 +1,150 @@ +import os + +# toolchains options +ARCH='arm' +CPU='cortex-m3' +CROSS_TOOL='keil' + +# bsp lib config +BSP_LIBRARY_TYPE = None + +if os.getenv('RTT_CC'): + CROSS_TOOL = os.getenv('RTT_CC') +if os.getenv('RTT_ROOT'): + RTT_ROOT = os.getenv('RTT_ROOT') + +# cross_tool provides the cross compiler +# EXEC_PATH is the compiler execute path, for example, CodeSourcery, Keil MDK, IAR +if CROSS_TOOL == 'gcc': + PLATFORM = 'gcc' + EXEC_PATH = r'C:\Users\XXYYZZ' +elif CROSS_TOOL == 'keil': + PLATFORM = 'armcc' + EXEC_PATH = r'C:/Keil_v5' +elif CROSS_TOOL == 'iar': + PLATFORM = 'iar' + EXEC_PATH = r'C:/Program Files (x86)/IAR Systems/Embedded Workbench 8.0' + +if os.getenv('RTT_EXEC_PATH'): + EXEC_PATH = os.getenv('RTT_EXEC_PATH') + +BUILD = 'debug' + +if PLATFORM == 'gcc': + # toolchains + PREFIX = 'arm-none-eabi-' + CC = PREFIX + 'gcc' + AS = PREFIX + 'gcc' + AR = PREFIX + 'ar' + CXX = PREFIX + 'g++' + LINK = PREFIX + 'gcc' + TARGET_EXT = 'elf' + SIZE = PREFIX + 'size' + OBJDUMP = PREFIX + 'objdump' + OBJCPY = PREFIX + 'objcopy' + + DEVICE = ' -mcpu=cortex-m3 -mthumb -ffunction-sections -fdata-sections' + CFLAGS = DEVICE + ' -Dgcc' + AFLAGS = ' -c' + DEVICE + ' -x assembler-with-cpp -Wa,-mimplicit-it=thumb ' + LFLAGS = DEVICE + ' -Wl,--gc-sections,-Map=rtthread.map,-cref,-u,Reset_Handler -T board/linker_scripts/link.ld' + + CPATH = '' + LPATH = '' + + if BUILD == 'debug': + CFLAGS += ' -O0 -gdwarf-2 -g' + AFLAGS += ' -gdwarf-2' + else: + CFLAGS += ' -O2' + + CXXFLAGS = CFLAGS + + POST_ACTION = OBJCPY + ' -O binary $TARGET rtthread.bin\n' + SIZE + ' $TARGET \n' + +elif PLATFORM == 'armcc': + # toolchains + CC = 'armcc' + CXX = 'armcc' + AS = 'armasm' + AR = 'armar' + LINK = 'armlink' + TARGET_EXT = 'axf' + + DEVICE = ' --cpu Cortex-M3.fp ' + CFLAGS = '-c ' + DEVICE + ' --apcs=interwork --c99' + AFLAGS = DEVICE + ' --apcs=interwork ' + LFLAGS = DEVICE + ' --scatter "board\linker_scripts\link.sct" --info sizes --info totals --info unused --info veneers --list rtthread.map --strict' + CFLAGS += ' -I' + EXEC_PATH + '/ARM/ARMCC/include' + LFLAGS += ' --libpath=' + EXEC_PATH + '/ARM/ARMCC/lib' + + CFLAGS += ' -D__MICROLIB ' + AFLAGS += ' --pd "__MICROLIB SETA 1" ' + LFLAGS += ' --library_type=microlib ' + EXEC_PATH += '/ARM/ARMCC/bin/' + + if BUILD == 'debug': + CFLAGS += ' -g -O0' + AFLAGS += ' -g' + else: + CFLAGS += ' -O2' + + CXXFLAGS = CFLAGS + CFLAGS += ' -std=c99' + + POST_ACTION = 'fromelf --bin $TARGET --output rtthread.bin \nfromelf -z $TARGET' + +elif PLATFORM == 'iar': + # toolchains + CC = 'iccarm' + CXX = 'iccarm' + AS = 'iasmarm' + AR = 'iarchive' + LINK = 'ilinkarm' + TARGET_EXT = 'out' + + DEVICE = '-Dewarm' + + CFLAGS = DEVICE + CFLAGS += ' --diag_suppress Pa050' + CFLAGS += ' --no_cse' + CFLAGS += ' --no_unroll' + CFLAGS += ' --no_inline' + CFLAGS += ' --no_code_motion' + CFLAGS += ' --no_tbaa' + CFLAGS += ' --no_clustering' + CFLAGS += ' --no_scheduling' + CFLAGS += ' --endian=little' + CFLAGS += ' --cpu=Cortex-M3' + CFLAGS += ' -e' + CFLAGS += ' --fpu=None' + CFLAGS += ' --dlib_config "' + EXEC_PATH + '/arm/INC/c/DLib_Config_Normal.h"' + CFLAGS += ' --silent' + + AFLAGS = DEVICE + AFLAGS += ' -s+' + AFLAGS += ' -w+' + AFLAGS += ' -r' + AFLAGS += ' --cpu Cortex-M3' + AFLAGS += ' --fpu None' + AFLAGS += ' -S' + + if BUILD == 'debug': + CFLAGS += ' --debug' + CFLAGS += ' -On' + else: + CFLAGS += ' -Oh' + + LFLAGS = ' --config "board/linker_scripts/link.icf"' + LFLAGS += ' --entry __iar_program_start' + + CXXFLAGS = CFLAGS + + EXEC_PATH = EXEC_PATH + '/arm/bin/' + POST_ACTION = 'ielftool --bin $TARGET rtthread.bin' + +def dist_handle(BSP_ROOT, dist_dir): + import sys + cwd_path = os.getcwd() + sys.path.append(os.path.join(os.path.dirname(BSP_ROOT), 'tools')) + from sdk_dist import dist_do_building + dist_do_building(BSP_ROOT, dist_dir) diff --git a/bsp/gd32/gd32205r-start/template.uvoptx b/bsp/gd32/gd32205r-start/template.uvoptx new file mode 100644 index 0000000000..3511a69bb3 --- /dev/null +++ b/bsp/gd32/gd32205r-start/template.uvoptx @@ -0,0 +1,180 @@ + + + + 1.0 + +
### uVision Project, (C) Keil Software
+ + + *.c + *.s*; *.src; *.a* + *.obj; *.o + *.lib + *.txt; *.h; *.inc + *.plm + *.cpp + 0 + + + + 0 + 0 + + + + rt-thread + 0x4 + ARM-ADS + + 12000000 + + 1 + 1 + 0 + 1 + 0 + + + 1 + 65535 + 0 + 0 + 0 + + + 79 + 66 + 8 + .\build\ + + + 1 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 0 + 0 + 0 + 0 + + + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 0 + 0 + + + 0 + 0 + 1 + + 255 + + 0 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 0 + 1 + 1 + 1 + 1 + 0 + 0 + 1 + 0 + 0 + 3 + + + + + + + + + + + BIN\CMSIS_AGDI.dll + + + + 0 + UL2CM3 + UL2CM3(-S0 -C0 -P0 -FD20000000 -FC1000 -FN1 -FF0GD32F20x_CL -FS08000000 -FL040000 -FP0($$Device:GD32F205RC$Flash\GD32F20x_CL.FLM)) + + + + + 0 + + + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + + + + 0 + 0 + 0 + + + + + + + + + + + + + ::CMSIS + 0 + 0 + 0 + 1 + + +
diff --git a/bsp/gd32/gd32205r-start/template.uvproj b/bsp/gd32/gd32205r-start/template.uvproj new file mode 100644 index 0000000000..344c060ada --- /dev/null +++ b/bsp/gd32/gd32205r-start/template.uvproj @@ -0,0 +1,628 @@ + + + + 1.1 + +
### uVision Project, (C) Keil Software
+ + + + rt-thread + 0x4 + ARM-ADS + 0 + + + GD32F205RC + GigaDevice + IRAM(0x20000000-0x020000) IROM(0x08000000-0x040000) CLOCK(12000000) CPUTYPE("Cortex-M3") + + "Startup\GD\GD32F20x\startup_gd32f20x.s" ("GD32F20x Startup Code") + UL2CM3(-O207 -S0 -C0 -FO7 -FD20000000 -FC800 -FN1 -FF0GD32F20x_3MB -FS08000000 -FL0300000) + 0 + gd32f20x0.h + + + + + + + + + + SFD\GD\GD32F20x\GD32F20x.SFR + 0 + 0 + + + + GD\GD32F20x\ + GD\GD32F20x\ + + 0 + 0 + 0 + 0 + 1 + + .\output\ + rtthread + 1 + 0 + 1 + 1 + 1 + .\build\ + 1 + 0 + 0 + + 0 + 0 + + + 0 + 0 + 0 + 0 + + + 0 + 0 + + + 0 + 0 + 0 + 0 + + + 0 + 0 + + + 0 + 0 + 0 + 0 + + 0 + + + + 0 + 0 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 0 + 3 + + + 1 + + + SARMCM3.DLL + -REMAP + DCM.DLL + -pCM3 + SARMCM3.DLL + + TCM.DLL + -pCM3 + + + + 1 + 0 + 0 + 0 + 16 + + + 0 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 0 + 1 + + + 1 + 1 + 1 + 1 + 1 + 1 + 0 + 1 + 0 + 1 + + 0 + 3 + + + + + + + + + + + + + + BIN\CMSIS_AGDI.dll + + + + + 1 + 0 + 0 + 1 + 1 + 4096 + + 1 + BIN\UL2CM3.DLL + "" () + + + + + 0 + + + + 0 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 0 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 0 + 0 + "Cortex-M3" + + 0 + 0 + 0 + 1 + 1 + 0 + 0 + 2 + 1 + 0 + 8 + 1 + 0 + 0 + 0 + 3 + 3 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 0 + 1 + 0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x20000000 + 0x30000 + + + 1 + 0x8000000 + 0x300000 + + + 0 + 0x0 + 0x0 + + + 1 + 0x0 + 0x0 + + + 1 + 0x0 + 0x0 + + + 1 + 0x0 + 0x0 + + + 1 + 0x8000000 + 0x300000 + + + 1 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x20000000 + 0x30000 + + + 0 + 0x10000000 + 0x10000 + + + + + + 1 + 1 + 0 + 0 + 1 + 0 + 0 + 0 + 0 + 0 + 2 + 0 + 0 + 1 + 0 + 0 + 1 + 1 + 1 + 1 + 0 + 0 + 0 + + + + + ..\..\..\Library\Firmware\GD32F20x_standard_peripheral\Include;..\..\..\Library\Firmware\CMSIS\GD\GD32F20x\Include;..\..\..\Library\Utilities;..\ + + + + 1 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + + + + + + + + + 1 + 0 + 0 + 0 + 1 + 0 + 0x08000000 + 0x20000000 + + + + + + + + + + + + + Application + + + main.c + 1 + ..\main.c + + + gd32f20x_it.c + 1 + ..\gd32f20x_it.c + + + + + CMSIS + + + system_gd32f20x.c + 1 + ..\..\..\Library\Firmware\CMSIS\GD\GD32F20x\Source\system_gd32f20x.c + + + + + GD32F20x_Peripherals + + + gd32f20x_adc.c + 1 + ..\..\..\Library\Firmware\GD32F20x_standard_peripheral\Source\gd32f20x_adc.c + + + gd32f20x_can.c + 1 + ..\..\..\Library\Firmware\GD32F20x_standard_peripheral\Source\gd32f20x_can.c + + + gd32f20x_crc.c + 1 + ..\..\..\Library\Firmware\GD32F20x_standard_peripheral\Source\gd32f20x_crc.c + + + gd32f20x_ctc.c + 1 + ..\..\..\Library\Firmware\GD32F20x_standard_peripheral\Source\gd32f20x_ctc.c + + + gd32f20x_dac.c + 1 + ..\..\..\Library\Firmware\GD32F20x_standard_peripheral\Source\gd32f20x_dac.c + + + gd32f20x_dbg.c + 1 + ..\..\..\Library\Firmware\GD32F20x_standard_peripheral\Source\gd32f20x_dbg.c + + + gd32f20x_dci.c + 1 + ..\..\..\Library\Firmware\GD32F20x_standard_peripheral\Source\gd32f20x_dci.c + + + gd32f20x_dma.c + 1 + ..\..\..\Library\Firmware\GD32F20x_standard_peripheral\Source\gd32f20x_dma.c + + + gd32f20x_enet.c + 1 + ..\..\..\Library\Firmware\GD32F20x_standard_peripheral\Source\gd32f20x_enet.c + + + gd32f20x_exmc.c + 1 + ..\..\..\Library\Firmware\GD32F20x_standard_peripheral\Source\gd32f20x_exmc.c + + + gd32f20x_exti.c + 1 + ..\..\..\Library\Firmware\GD32F20x_standard_peripheral\Source\gd32f20x_exti.c + + + gd32f20x_fmc.c + 1 + ..\..\..\Library\Firmware\GD32F20x_standard_peripheral\Source\gd32f20x_fmc.c + + + gd32f20x_fwdgt.c + 1 + ..\..\..\Library\Firmware\GD32F20x_standard_peripheral\Source\gd32f20x_fwdgt.c + + + gd32f20x_gpio.c + 1 + ..\..\..\Library\Firmware\GD32F20x_standard_peripheral\Source\gd32f20x_gpio.c + + + gd32f20x_i2c.c + 1 + ..\..\..\Library\Firmware\GD32F20x_standard_peripheral\Source\gd32f20x_i2c.c + + + gd32f20x_ipa.c + 1 + ..\..\..\Library\Firmware\GD32F20x_standard_peripheral\Source\gd32f20x_ipa.c + + + gd32f20x_iref.c + 1 + ..\..\..\Library\Firmware\GD32F20x_standard_peripheral\Source\gd32f20x_iref.c + + + gd32f20x_misc.c + 1 + ..\..\..\Library\Firmware\GD32F20x_standard_peripheral\Source\gd32f20x_misc.c + + + gd32f20x_pmu.c + 1 + ..\..\..\Library\Firmware\GD32F20x_standard_peripheral\Source\gd32f20x_pmu.c + + + gd32f20x_rcu.c + 1 + ..\..\..\Library\Firmware\GD32F20x_standard_peripheral\Source\gd32f20x_rcu.c + + + gd32f20x_rtc.c + 1 + ..\..\..\Library\Firmware\GD32F20x_standard_peripheral\Source\gd32f20x_rtc.c + + + gd32f20x_sdio.c + 1 + ..\..\..\Library\Firmware\GD32F20x_standard_peripheral\Source\gd32f20x_sdio.c + + + gd32f20x_spi.c + 1 + ..\..\..\Library\Firmware\GD32F20x_standard_peripheral\Source\gd32f20x_spi.c + + + gd32f20x_syscfg.c + 1 + ..\..\..\Library\Firmware\GD32F20x_standard_peripheral\Source\gd32f20x_syscfg.c + + + gd32f20x_timer.c + 1 + ..\..\..\Library\Firmware\GD32F20x_standard_peripheral\Source\gd32f20x_timer.c + + + gd32f20x_tli.c + 1 + ..\..\..\Library\Firmware\GD32F20x_standard_peripheral\Source\gd32f20x_tli.c + + + gd32f20x_trng.c + 1 + ..\..\..\Library\Firmware\GD32F20x_standard_peripheral\Source\gd32f20x_trng.c + + + gd32f20x_usart.c + 1 + ..\..\..\Library\Firmware\GD32F20x_standard_peripheral\Source\gd32f20x_usart.c + + + gd32f20x_wwdgt.c + 1 + ..\..\..\Library\Firmware\GD32F20x_standard_peripheral\Source\gd32f20x_wwdgt.c + + + + + GD32F20x_START + + + gd32f205r_start.c + 1 + ..\..\..\Library\Utilities\gd32f205r_start.c + + + + + Startup + + + startup_gd32f20x.s + 2 + ..\..\..\Library\Firmware\CMSIS\GD\GD32F20x\Source\ARM\startup_gd32f20x.s + + + + + Doc + + + readme.txt + 5 + ..\readme.txt + + + + + + + +
diff --git a/bsp/gd32/gd32205r-start/template.uvprojx b/bsp/gd32/gd32205r-start/template.uvprojx new file mode 100644 index 0000000000..1ba7a286ef --- /dev/null +++ b/bsp/gd32/gd32205r-start/template.uvprojx @@ -0,0 +1,417 @@ + + + + 2.1 + +
### uVision Project, (C) Keil Software
+ + + + rt-thread + 0x4 + ARM-ADS + 0 + + + GD32F205RC + GigaDevice + GigaDevice.GD32F20x_DFP.2.2.0 + http://gd32mcu.com/data/documents/pack/ + IRAM(0x20000000,0x020000) IROM(0x08000000,0x040000) CPUTYPE("Cortex-M3") CLOCK(12000000) ELITTLE + + + UL2CM3(-S0 -C0 -P0 -FD20000000 -FC1000 -FN1 -FF0GD32F20x_CL -FS08000000 -FL040000 -FP0($$Device:GD32F205RC$Flash\GD32F20x_CL.FLM)) + 0 + $$Device:GD32F205RC$Device\Include\gd32f20x.h + + + + + + + + + + $$Device:GD32F205RC$SVD\GD32F20x_CL.svd + 0 + 0 + + + + + + + 0 + 0 + 0 + 0 + 1 + + .\build\ + rtthread + 1 + 0 + 0 + 1 + 0 + .\build\ + 1 + 0 + 0 + + 0 + 0 + + + 0 + 0 + 0 + 0 + + + 0 + 0 + + + 0 + 0 + 0 + 0 + + + 1 + 0 + fromelf --bin !L --output rtthread.bin + + 0 + 0 + 0 + 0 + + 0 + + + + 0 + 0 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 0 + 3 + + + 1 + + + SARMCM3.DLL + -REMAP + DCM.DLL + -pCM3 + SARMCM3.DLL + + TCM.DLL + -pCM3 + + + + 1 + 0 + 0 + 0 + 16 + + + + + 1 + 0 + 0 + 1 + 1 + 4096 + + 1 + BIN\UL2CM3.DLL + + + + + + 0 + + + + 0 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 0 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 0 + 0 + "Cortex-M3" + + 0 + 0 + 0 + 1 + 1 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 8 + 0 + 0 + 0 + 0 + 3 + 3 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 0 + 1 + 0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x20000000 + 0x20000 + + + 1 + 0x8000000 + 0x40000 + + + 0 + 0x0 + 0x0 + + + 1 + 0x0 + 0x0 + + + 1 + 0x0 + 0x0 + + + 1 + 0x0 + 0x0 + + + 1 + 0x8000000 + 0x40000 + + + 1 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x20000000 + 0x20000 + + + 0 + 0x0 + 0x0 + + + + + + 1 + 4 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 1 + 0 + 0 + 1 + 1 + 1 + 1 + 0 + 0 + 0 + + + + + + + + + 1 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 4 + + + + + + + + + 1 + 0 + 0 + 0 + 1 + 0 + 0x08000000 + 0x20000000 + + .\gd32_rom.ld + + + + + + + + + + + ::CMSIS + + + + + + + + + + + + + + + + + + + + + + <Project Info> + + + + + + 0 + 1 + + + + +
diff --git a/bsp/gd32/gd32305r-start/.config b/bsp/gd32/gd32305r-start/.config new file mode 100644 index 0000000000..c8f9feac51 --- /dev/null +++ b/bsp/gd32/gd32305r-start/.config @@ -0,0 +1,636 @@ +# +# Automatically generated file; DO NOT EDIT. +# RT-Thread Configuration +# + +# +# RT-Thread Kernel +# +CONFIG_RT_NAME_MAX=8 +# CONFIG_RT_USING_BIG_ENDIAN is not set +# CONFIG_RT_USING_ARCH_DATA_TYPE is not set +# CONFIG_RT_USING_SMP is not set +CONFIG_RT_ALIGN_SIZE=4 +# CONFIG_RT_THREAD_PRIORITY_8 is not set +CONFIG_RT_THREAD_PRIORITY_32=y +# CONFIG_RT_THREAD_PRIORITY_256 is not set +CONFIG_RT_THREAD_PRIORITY_MAX=32 +CONFIG_RT_TICK_PER_SECOND=100 +CONFIG_RT_USING_OVERFLOW_CHECK=y +CONFIG_RT_USING_HOOK=y +CONFIG_RT_USING_IDLE_HOOK=y +CONFIG_RT_IDLE_HOOK_LIST_SIZE=4 +CONFIG_IDLE_THREAD_STACK_SIZE=256 +# CONFIG_RT_USING_TIMER_SOFT is not set + +# +# kservice optimization +# +# CONFIG_RT_KSERVICE_USING_STDLIB is not set +# CONFIG_RT_KSERVICE_USING_TINY_SIZE is not set +# CONFIG_RT_USING_ASM_MEMCPY is not set +CONFIG_RT_DEBUG=y +CONFIG_RT_DEBUG_COLOR=y +# CONFIG_RT_DEBUG_INIT_CONFIG is not set +# CONFIG_RT_DEBUG_THREAD_CONFIG is not set +# CONFIG_RT_DEBUG_SCHEDULER_CONFIG is not set +# CONFIG_RT_DEBUG_IPC_CONFIG is not set +# CONFIG_RT_DEBUG_TIMER_CONFIG is not set +# CONFIG_RT_DEBUG_IRQ_CONFIG is not set +# CONFIG_RT_DEBUG_MEM_CONFIG is not set +# CONFIG_RT_DEBUG_SLAB_CONFIG is not set +# CONFIG_RT_DEBUG_MEMHEAP_CONFIG is not set +# CONFIG_RT_DEBUG_MODULE_CONFIG is not set + +# +# Inter-Thread communication +# +CONFIG_RT_USING_SEMAPHORE=y +CONFIG_RT_USING_MUTEX=y +CONFIG_RT_USING_EVENT=y +CONFIG_RT_USING_MAILBOX=y +CONFIG_RT_USING_MESSAGEQUEUE=y +# CONFIG_RT_USING_SIGNALS is not set + +# +# Memory Management +# +CONFIG_RT_USING_MEMPOOL=y +# CONFIG_RT_USING_MEMHEAP is not set +# CONFIG_RT_USING_NOHEAP is not set +CONFIG_RT_USING_SMALL_MEM=y +# CONFIG_RT_USING_SLAB is not set +# CONFIG_RT_USING_USERHEAP is not set +# CONFIG_RT_USING_MEMTRACE is not set +CONFIG_RT_USING_HEAP=y + +# +# Kernel Device Object +# +CONFIG_RT_USING_DEVICE=y +# CONFIG_RT_USING_DEVICE_OPS is not set +# CONFIG_RT_USING_INTERRUPT_INFO is not set +CONFIG_RT_USING_CONSOLE=y +CONFIG_RT_CONSOLEBUF_SIZE=128 +CONFIG_RT_CONSOLE_DEVICE_NAME="uart1" +# CONFIG_RT_PRINTF_LONGLONG is not set +CONFIG_RT_VER_NUM=0x40004 +# CONFIG_RT_USING_CPU_FFS is not set +# CONFIG_ARCH_CPU_STACK_GROWS_UPWARD is not set + +# +# RT-Thread Components +# +CONFIG_RT_USING_COMPONENTS_INIT=y +CONFIG_RT_USING_USER_MAIN=y +CONFIG_RT_MAIN_THREAD_STACK_SIZE=2048 +CONFIG_RT_MAIN_THREAD_PRIORITY=10 + +# +# C++ features +# +# CONFIG_RT_USING_CPLUSPLUS is not set + +# +# Command shell +# +CONFIG_RT_USING_FINSH=y +CONFIG_RT_USING_MSH=y +CONFIG_FINSH_USING_MSH=y +CONFIG_FINSH_THREAD_NAME="tshell" +CONFIG_FINSH_THREAD_PRIORITY=20 +CONFIG_FINSH_THREAD_STACK_SIZE=4096 +CONFIG_FINSH_USING_HISTORY=y +CONFIG_FINSH_HISTORY_LINES=5 +CONFIG_FINSH_USING_SYMTAB=y +CONFIG_FINSH_CMD_SIZE=80 +CONFIG_MSH_USING_BUILT_IN_COMMANDS=y +CONFIG_FINSH_USING_DESCRIPTION=y +# CONFIG_FINSH_ECHO_DISABLE_DEFAULT is not set +# CONFIG_FINSH_USING_AUTH is not set +CONFIG_FINSH_ARG_MAX=10 + +# +# Device virtual file system +# +# CONFIG_RT_USING_DFS is not set + +# +# Device Drivers +# +CONFIG_RT_USING_DEVICE_IPC=y +CONFIG_RT_PIPE_BUFSZ=512 +CONFIG_RT_USING_SYSTEM_WORKQUEUE=y +CONFIG_RT_SYSTEM_WORKQUEUE_STACKSIZE=2048 +CONFIG_RT_SYSTEM_WORKQUEUE_PRIORITY=23 +CONFIG_RT_USING_SERIAL=y +CONFIG_RT_USING_SERIAL_V1=y +# CONFIG_RT_USING_SERIAL_V2 is not set +CONFIG_RT_SERIAL_USING_DMA=y +CONFIG_RT_SERIAL_RB_BUFSZ=64 +# CONFIG_RT_USING_CAN is not set +# CONFIG_RT_USING_HWTIMER is not set +# CONFIG_RT_USING_CPUTIME is not set +# CONFIG_RT_USING_I2C is not set +# CONFIG_RT_USING_PHY is not set +CONFIG_RT_USING_PIN=y +# CONFIG_RT_USING_ADC is not set +# CONFIG_RT_USING_DAC is not set +# CONFIG_RT_USING_PWM is not set +# CONFIG_RT_USING_MTD_NOR is not set +# CONFIG_RT_USING_MTD_NAND is not set +# CONFIG_RT_USING_PM is not set +# CONFIG_RT_USING_RTC is not set +# CONFIG_RT_USING_SDIO is not set +# CONFIG_RT_USING_SPI is not set +# CONFIG_RT_USING_WDT is not set +# CONFIG_RT_USING_AUDIO is not set +# CONFIG_RT_USING_SENSOR is not set +# CONFIG_RT_USING_TOUCH is not set +# CONFIG_RT_USING_HWCRYPTO is not set +# CONFIG_RT_USING_PULSE_ENCODER is not set +# CONFIG_RT_USING_INPUT_CAPTURE is not set +# CONFIG_RT_USING_WIFI is not set + +# +# Using USB +# +# CONFIG_RT_USING_USB is not set +# CONFIG_RT_USING_USB_HOST is not set +# CONFIG_RT_USING_USB_DEVICE is not set + +# +# POSIX layer and C standard library +# +# CONFIG_RT_USING_LIBC is not set +CONFIG_RT_LIBC_USING_TIME=y +CONFIG_RT_LIBC_DEFAULT_TIMEZONE=8 +# CONFIG_RT_USING_PTHREADS is not set + +# +# Network +# + +# +# Socket abstraction layer +# +# CONFIG_RT_USING_SAL is not set + +# +# Network interface device +# +# CONFIG_RT_USING_NETDEV is not set + +# +# light weight TCP/IP stack +# +# CONFIG_RT_USING_LWIP is not set + +# +# AT commands +# +# CONFIG_RT_USING_AT is not set + +# +# VBUS(Virtual Software BUS) +# +# CONFIG_RT_USING_VBUS is not set + +# +# Utilities +# +# CONFIG_RT_USING_RYM is not set +# CONFIG_RT_USING_ULOG is not set +# CONFIG_RT_USING_UTEST is not set +# CONFIG_RT_USING_VAR_EXPORT is not set +# CONFIG_RT_USING_RT_LINK is not set + +# +# RT-Thread Utestcases +# +# CONFIG_RT_USING_UTESTCASES is not set + +# +# RT-Thread online packages +# + +# +# IoT - internet of things +# +# CONFIG_PKG_USING_LORAWAN_DRIVER is not set +# CONFIG_PKG_USING_PAHOMQTT is not set +# CONFIG_PKG_USING_UMQTT is not set +# CONFIG_PKG_USING_WEBCLIENT is not set +# CONFIG_PKG_USING_WEBNET is not set +# CONFIG_PKG_USING_MONGOOSE is not set +# CONFIG_PKG_USING_MYMQTT is not set +# CONFIG_PKG_USING_KAWAII_MQTT is not set +# CONFIG_PKG_USING_BC28_MQTT is not set +# CONFIG_PKG_USING_WEBTERMINAL is not set +# CONFIG_PKG_USING_CJSON is not set +# CONFIG_PKG_USING_JSMN is not set +# CONFIG_PKG_USING_LIBMODBUS is not set +# CONFIG_PKG_USING_FREEMODBUS is not set +# CONFIG_PKG_USING_LJSON is not set +# CONFIG_PKG_USING_EZXML is not set +# CONFIG_PKG_USING_NANOPB is not set + +# +# Wi-Fi +# + +# +# Marvell WiFi +# +# CONFIG_PKG_USING_WLANMARVELL is not set + +# +# Wiced WiFi +# +# CONFIG_PKG_USING_WLAN_WICED is not set +# CONFIG_PKG_USING_RW007 is not set +# CONFIG_PKG_USING_COAP is not set +# CONFIG_PKG_USING_NOPOLL is not set +# CONFIG_PKG_USING_NETUTILS is not set +# CONFIG_PKG_USING_CMUX is not set +# CONFIG_PKG_USING_PPP_DEVICE is not set +# CONFIG_PKG_USING_AT_DEVICE is not set +# CONFIG_PKG_USING_ATSRV_SOCKET is not set +# CONFIG_PKG_USING_WIZNET is not set +# CONFIG_PKG_USING_ZB_COORDINATOR is not set + +# +# IoT Cloud +# +# CONFIG_PKG_USING_ONENET is not set +# CONFIG_PKG_USING_GAGENT_CLOUD is not set +# CONFIG_PKG_USING_ALI_IOTKIT is not set +# CONFIG_PKG_USING_AZURE is not set +# CONFIG_PKG_USING_TENCENT_IOT_EXPLORER is not set +# CONFIG_PKG_USING_JIOT-C-SDK is not set +# CONFIG_PKG_USING_UCLOUD_IOT_SDK is not set +# CONFIG_PKG_USING_JOYLINK is not set +# CONFIG_PKG_USING_NIMBLE is not set +# CONFIG_PKG_USING_OTA_DOWNLOADER is not set +# CONFIG_PKG_USING_IPMSG is not set +# CONFIG_PKG_USING_LSSDP is not set +# CONFIG_PKG_USING_AIRKISS_OPEN is not set +# CONFIG_PKG_USING_LIBRWS is not set +# CONFIG_PKG_USING_TCPSERVER is not set +# CONFIG_PKG_USING_PROTOBUF_C is not set +# CONFIG_PKG_USING_DLT645 is not set +# CONFIG_PKG_USING_QXWZ is not set +# CONFIG_PKG_USING_SMTP_CLIENT is not set +# CONFIG_PKG_USING_ABUP_FOTA is not set +# CONFIG_PKG_USING_LIBCURL2RTT is not set +# CONFIG_PKG_USING_CAPNP is not set +# CONFIG_PKG_USING_RT_CJSON_TOOLS is not set +# CONFIG_PKG_USING_AGILE_TELNET is not set +# CONFIG_PKG_USING_NMEALIB is not set +# CONFIG_PKG_USING_AGILE_JSMN is not set +# CONFIG_PKG_USING_PDULIB is not set +# CONFIG_PKG_USING_BTSTACK is not set +# CONFIG_PKG_USING_LORAWAN_ED_STACK is not set +# CONFIG_PKG_USING_WAYZ_IOTKIT is not set +# CONFIG_PKG_USING_MAVLINK is not set +# CONFIG_PKG_USING_RAPIDJSON is not set +# CONFIG_PKG_USING_BSAL is not set +# CONFIG_PKG_USING_AGILE_MODBUS is not set +# CONFIG_PKG_USING_AGILE_FTP is not set +# CONFIG_PKG_USING_EMBEDDEDPROTO is not set +# CONFIG_PKG_USING_RT_LINK_HW is not set +# CONFIG_PKG_USING_LORA_PKT_FWD is not set +# CONFIG_PKG_USING_LORA_GW_DRIVER_LIB is not set +# CONFIG_PKG_USING_LORA_PKT_SNIFFER is not set +# CONFIG_PKG_USING_HM is not set +# CONFIG_PKG_USING_SMALL_MODBUS is not set + +# +# security packages +# +# CONFIG_PKG_USING_MBEDTLS is not set +# CONFIG_PKG_USING_LIBSODIUM is not set +# CONFIG_PKG_USING_TINYCRYPT is not set +# CONFIG_PKG_USING_TFM is not set +# CONFIG_PKG_USING_YD_CRYPTO is not set + +# +# language packages +# +# CONFIG_PKG_USING_LUA is not set +# CONFIG_PKG_USING_JERRYSCRIPT is not set +# CONFIG_PKG_USING_MICROPYTHON is not set +# CONFIG_PKG_USING_PIKASCRIPT is not set + +# +# multimedia packages +# + +# +# LVGL: powerful and easy-to-use embedded GUI library +# +# CONFIG_PKG_USING_LVGL is not set +# CONFIG_PKG_USING_LITTLEVGL2RTT is not set +# CONFIG_PKG_USING_LV_MUSIC_DEMO is not set + +# +# u8g2: a monochrome graphic library +# +# CONFIG_PKG_USING_U8G2_OFFICIAL is not set +# CONFIG_PKG_USING_U8G2 is not set +# CONFIG_PKG_USING_OPENMV is not set +# CONFIG_PKG_USING_MUPDF is not set +# CONFIG_PKG_USING_STEMWIN is not set +# CONFIG_PKG_USING_WAVPLAYER is not set +# CONFIG_PKG_USING_TJPGD is not set +# CONFIG_PKG_USING_PDFGEN is not set +# CONFIG_PKG_USING_HELIX is not set +# CONFIG_PKG_USING_AZUREGUIX is not set +# CONFIG_PKG_USING_TOUCHGFX2RTT is not set +# CONFIG_PKG_USING_NUEMWIN is not set +# CONFIG_PKG_USING_MP3PLAYER is not set +# CONFIG_PKG_USING_TINYJPEG is not set +# CONFIG_PKG_USING_UGUI is not set + +# +# PainterEngine: A cross-platform graphics application framework written in C language +# +# CONFIG_PKG_USING_PAINTERENGINE is not set +# CONFIG_PKG_USING_PAINTERENGINE_AUX is not set + +# +# tools packages +# +# CONFIG_PKG_USING_CMBACKTRACE is not set +# CONFIG_PKG_USING_EASYFLASH is not set +# CONFIG_PKG_USING_EASYLOGGER is not set +# CONFIG_PKG_USING_SYSTEMVIEW is not set +# CONFIG_PKG_USING_SEGGER_RTT is not set +# CONFIG_PKG_USING_RDB is not set +# CONFIG_PKG_USING_QRCODE is not set +# CONFIG_PKG_USING_ULOG_EASYFLASH is not set +# CONFIG_PKG_USING_ULOG_FILE is not set +# CONFIG_PKG_USING_LOGMGR is not set +# CONFIG_PKG_USING_ADBD is not set +# CONFIG_PKG_USING_COREMARK is not set +# CONFIG_PKG_USING_DHRYSTONE is not set +# CONFIG_PKG_USING_MEMORYPERF is not set +# CONFIG_PKG_USING_NR_MICRO_SHELL is not set +# CONFIG_PKG_USING_CHINESE_FONT_LIBRARY is not set +# CONFIG_PKG_USING_LUNAR_CALENDAR is not set +# CONFIG_PKG_USING_BS8116A is not set +# CONFIG_PKG_USING_GPS_RMC is not set +# CONFIG_PKG_USING_URLENCODE is not set +# CONFIG_PKG_USING_UMCN is not set +# CONFIG_PKG_USING_LWRB2RTT is not set +# CONFIG_PKG_USING_CPU_USAGE is not set +# CONFIG_PKG_USING_GBK2UTF8 is not set +# CONFIG_PKG_USING_VCONSOLE is not set +# CONFIG_PKG_USING_KDB is not set +# CONFIG_PKG_USING_WAMR is not set +# CONFIG_PKG_USING_MICRO_XRCE_DDS_CLIENT is not set +# CONFIG_PKG_USING_LWLOG is not set +# CONFIG_PKG_USING_ANV_TRACE is not set +# CONFIG_PKG_USING_ANV_MEMLEAK is not set +# CONFIG_PKG_USING_ANV_TESTSUIT is not set +# CONFIG_PKG_USING_ANV_BENCH is not set +# CONFIG_PKG_USING_DEVMEM is not set +# CONFIG_PKG_USING_REGEX is not set +# CONFIG_PKG_USING_MEM_SANDBOX is not set +# CONFIG_PKG_USING_SOLAR_TERMS is not set +# CONFIG_PKG_USING_GAN_ZHI is not set +# CONFIG_PKG_USING_FDT is not set + +# +# system packages +# + +# +# enhanced kernel services +# +# CONFIG_PKG_USING_RT_MEMCPY_CM is not set +# CONFIG_PKG_USING_RT_KPRINTF_THREADSAFE is not set +# CONFIG_PKG_USING_RT_VSNPRINTF_FULL is not set + +# +# acceleration: Assembly language or algorithmic acceleration packages +# +# CONFIG_PKG_USING_QFPLIB_M0_FULL is not set +# CONFIG_PKG_USING_QFPLIB_M0_TINY is not set +# CONFIG_PKG_USING_QFPLIB_M3 is not set + +# +# CMSIS: ARM Cortex-M Microcontroller Software Interface Standard +# +# CONFIG_PKG_USING_CMSIS_5 is not set +# CONFIG_PKG_USING_CMSIS_RTOS2 is not set + +# +# Micrium: Micrium software products porting for RT-Thread +# +# CONFIG_PKG_USING_UCOSIII_WRAPPER is not set +# CONFIG_PKG_USING_UCOSII_WRAPPER is not set +# CONFIG_PKG_USING_UC_CRC is not set +# CONFIG_PKG_USING_UC_CLK is not set +# CONFIG_PKG_USING_UC_COMMON is not set +# CONFIG_PKG_USING_UC_MODBUS is not set +# CONFIG_RT_USING_ARDUINO is not set +# CONFIG_PKG_USING_GUIENGINE is not set +# CONFIG_PKG_USING_CAIRO is not set +# CONFIG_PKG_USING_PIXMAN is not set +# CONFIG_PKG_USING_PARTITION is not set +# CONFIG_PKG_USING_FAL is not set +# CONFIG_PKG_USING_FLASHDB is not set +# CONFIG_PKG_USING_SQLITE is not set +# CONFIG_PKG_USING_RTI is not set +# CONFIG_PKG_USING_DFS_YAFFS is not set +# CONFIG_PKG_USING_LITTLEFS is not set +# CONFIG_PKG_USING_DFS_JFFS2 is not set +# CONFIG_PKG_USING_DFS_UFFS is not set +# CONFIG_PKG_USING_LWEXT4 is not set +# CONFIG_PKG_USING_THREAD_POOL is not set +# CONFIG_PKG_USING_ROBOTS is not set +# CONFIG_PKG_USING_EV is not set +# CONFIG_PKG_USING_SYSWATCH is not set +# CONFIG_PKG_USING_SYS_LOAD_MONITOR is not set +# CONFIG_PKG_USING_PLCCORE is not set +# CONFIG_PKG_USING_RAMDISK is not set +# CONFIG_PKG_USING_MININI is not set +# CONFIG_PKG_USING_QBOOT is not set +# CONFIG_PKG_USING_PPOOL is not set +# CONFIG_PKG_USING_OPENAMP is not set +# CONFIG_PKG_USING_LPM is not set +# CONFIG_PKG_USING_TLSF is not set +# CONFIG_PKG_USING_EVENT_RECORDER is not set +# CONFIG_PKG_USING_ARM_2D is not set +# CONFIG_PKG_USING_WCWIDTH is not set +# CONFIG_PKG_USING_MCUBOOT is not set +# CONFIG_PKG_USING_TINYUSB is not set +# CONFIG_PKG_USING_USB_STACK is not set + +# +# peripheral libraries and drivers +# +# CONFIG_PKG_USING_SENSORS_DRIVERS is not set +# CONFIG_PKG_USING_REALTEK_AMEBA is not set +# CONFIG_PKG_USING_SHT2X is not set +# CONFIG_PKG_USING_SHT3X is not set +# CONFIG_PKG_USING_AS7341 is not set +# CONFIG_PKG_USING_STM32_SDIO is not set +# CONFIG_PKG_USING_ICM20608 is not set +# CONFIG_PKG_USING_BUTTON is not set +# CONFIG_PKG_USING_PCF8574 is not set +# CONFIG_PKG_USING_SX12XX is not set +# CONFIG_PKG_USING_SIGNAL_LED is not set +# CONFIG_PKG_USING_LEDBLINK is not set +# CONFIG_PKG_USING_LITTLED is not set +# CONFIG_PKG_USING_LKDGUI is not set +# CONFIG_PKG_USING_NRF5X_SDK is not set +# CONFIG_PKG_USING_NRFX is not set +# CONFIG_PKG_USING_WM_LIBRARIES is not set +# CONFIG_PKG_USING_KENDRYTE_SDK is not set +# CONFIG_PKG_USING_INFRARED is not set +# CONFIG_PKG_USING_AGILE_BUTTON is not set +# CONFIG_PKG_USING_AGILE_LED is not set +# CONFIG_PKG_USING_AT24CXX is not set +# CONFIG_PKG_USING_MOTIONDRIVER2RTT is not set +# CONFIG_PKG_USING_AD7746 is not set +# CONFIG_PKG_USING_PCA9685 is not set +# CONFIG_PKG_USING_I2C_TOOLS is not set +# CONFIG_PKG_USING_NRF24L01 is not set +# CONFIG_PKG_USING_TOUCH_DRIVERS is not set +# CONFIG_PKG_USING_MAX17048 is not set +# CONFIG_PKG_USING_RPLIDAR is not set +# CONFIG_PKG_USING_AS608 is not set +# CONFIG_PKG_USING_RC522 is not set +# CONFIG_PKG_USING_WS2812B is not set +# CONFIG_PKG_USING_EMBARC_BSP is not set +# CONFIG_PKG_USING_EXTERN_RTC_DRIVERS is not set +# CONFIG_PKG_USING_MULTI_RTIMER is not set +# CONFIG_PKG_USING_MAX7219 is not set +# CONFIG_PKG_USING_BEEP is not set +# CONFIG_PKG_USING_EASYBLINK is not set +# CONFIG_PKG_USING_PMS_SERIES is not set +# CONFIG_PKG_USING_CAN_YMODEM is not set +# CONFIG_PKG_USING_LORA_RADIO_DRIVER is not set +# CONFIG_PKG_USING_QLED is not set +# CONFIG_PKG_USING_PAJ7620 is not set +# CONFIG_PKG_USING_AGILE_CONSOLE is not set +# CONFIG_PKG_USING_LD3320 is not set +# CONFIG_PKG_USING_WK2124 is not set +# CONFIG_PKG_USING_LY68L6400 is not set +# CONFIG_PKG_USING_DM9051 is not set +# CONFIG_PKG_USING_SSD1306 is not set +# CONFIG_PKG_USING_QKEY is not set +# CONFIG_PKG_USING_RS485 is not set +# CONFIG_PKG_USING_NES is not set +# CONFIG_PKG_USING_VIRTUAL_SENSOR is not set +# CONFIG_PKG_USING_VDEVICE is not set +# CONFIG_PKG_USING_SGM706 is not set +# CONFIG_PKG_USING_STM32WB55_SDK is not set +# CONFIG_PKG_USING_RDA58XX is not set +# CONFIG_PKG_USING_LIBNFC is not set +# CONFIG_PKG_USING_MFOC is not set +# CONFIG_PKG_USING_TMC51XX is not set +# CONFIG_PKG_USING_TCA9534 is not set +# CONFIG_PKG_USING_KOBUKI is not set +# CONFIG_PKG_USING_ROSSERIAL is not set +# CONFIG_PKG_USING_MICRO_ROS is not set +# CONFIG_PKG_USING_MCP23008 is not set +# CONFIG_PKG_USING_BLUETRUM_SDK is not set +# CONFIG_PKG_USING_MISAKA_AT24CXX is not set +# CONFIG_PKG_USING_MISAKA_RGB_BLING is not set +# CONFIG_PKG_USING_BL_MCU_SDK is not set +# CONFIG_PKG_USING_SOFT_SERIAL is not set +# CONFIG_PKG_USING_MB85RS16 is not set + +# +# AI packages +# +# CONFIG_PKG_USING_LIBANN is not set +# CONFIG_PKG_USING_NNOM is not set +# CONFIG_PKG_USING_ONNX_BACKEND is not set +# CONFIG_PKG_USING_ONNX_PARSER is not set +# CONFIG_PKG_USING_TENSORFLOWLITEMICRO is not set +# CONFIG_PKG_USING_ELAPACK is not set +# CONFIG_PKG_USING_ULAPACK is not set +# CONFIG_PKG_USING_QUEST is not set +# CONFIG_PKG_USING_NAXOS is not set + +# +# miscellaneous packages +# + +# +# samples: kernel and components samples +# +# CONFIG_PKG_USING_KERNEL_SAMPLES is not set +# CONFIG_PKG_USING_FILESYSTEM_SAMPLES is not set +# CONFIG_PKG_USING_NETWORK_SAMPLES is not set +# CONFIG_PKG_USING_PERIPHERAL_SAMPLES is not set + +# +# entertainment: terminal games and other interesting software packages +# +# CONFIG_PKG_USING_CMATRIX is not set +# CONFIG_PKG_USING_SL is not set +# CONFIG_PKG_USING_CAL is not set +# CONFIG_PKG_USING_ACLOCK is not set +# CONFIG_PKG_USING_THREES is not set +# CONFIG_PKG_USING_2048 is not set +# CONFIG_PKG_USING_SNAKE is not set +# CONFIG_PKG_USING_TETRIS is not set +# CONFIG_PKG_USING_DONUT is not set +# CONFIG_PKG_USING_LIBCSV is not set +# CONFIG_PKG_USING_OPTPARSE is not set +# CONFIG_PKG_USING_FASTLZ is not set +# CONFIG_PKG_USING_MINILZO is not set +# CONFIG_PKG_USING_QUICKLZ is not set +# CONFIG_PKG_USING_LZMA is not set +# CONFIG_PKG_USING_MULTIBUTTON is not set +# CONFIG_PKG_USING_FLEXIBLE_BUTTON is not set +# CONFIG_PKG_USING_CANFESTIVAL is not set +# CONFIG_PKG_USING_ZLIB is not set +# CONFIG_PKG_USING_MINIZIP is not set +# CONFIG_PKG_USING_DSTR is not set +# CONFIG_PKG_USING_TINYFRAME is not set +# CONFIG_PKG_USING_KENDRYTE_DEMO is not set +# CONFIG_PKG_USING_DIGITALCTRL is not set +# CONFIG_PKG_USING_UPACKER is not set +# CONFIG_PKG_USING_UPARAM is not set +# CONFIG_PKG_USING_HELLO is not set +# CONFIG_PKG_USING_VI is not set +# CONFIG_PKG_USING_KI is not set +# CONFIG_PKG_USING_ARMv7M_DWT is not set +# CONFIG_PKG_USING_VT100 is not set +# CONFIG_PKG_USING_UKAL is not set +# CONFIG_PKG_USING_CRCLIB is not set +# CONFIG_PKG_USING_LWGPS is not set +# CONFIG_PKG_USING_STATE_MACHINE is not set +# CONFIG_PKG_USING_MCURSES is not set +# CONFIG_PKG_USING_COWSAY is not set +# CONFIG_PKG_USING_TERMBOX is not set + +# +# Hardware Drivers Config +# +CONFIG_SOC_SERIES_GD32F30x=y +CONFIG_SOC_GD32305R=y + +# +# Onboard Peripheral Drivers +# + +# +# On-chip Peripheral Drivers +# +CONFIG_BSP_USING_GPIO=y +CONFIG_BSP_USING_UART=y +CONFIG_BSP_USING_UART1=y +# CONFIG_BSP_UART1_RX_USING_DMA is not set +# CONFIG_BSP_USING_SPI is not set +# CONFIG_BSP_USING_I2C1 is not set + +# +# Board extended module Drivers +# diff --git a/bsp/gd32/gd32305r-start/Kconfig b/bsp/gd32/gd32305r-start/Kconfig new file mode 100644 index 0000000000..8cbc7b71a8 --- /dev/null +++ b/bsp/gd32/gd32305r-start/Kconfig @@ -0,0 +1,21 @@ +mainmenu "RT-Thread Configuration" + +config BSP_DIR + string + option env="BSP_ROOT" + default "." + +config RTT_DIR + string + option env="RTT_ROOT" + default "../../.." + +config PKGS_DIR + string + option env="PKGS_ROOT" + default "packages" + +source "$RTT_DIR/Kconfig" +source "$PKGS_DIR/Kconfig" +source "../libraries/Kconfig" +source "board/Kconfig" diff --git a/bsp/gd32/gd32305r-start/README.md b/bsp/gd32/gd32305r-start/README.md new file mode 100644 index 0000000000..c081a1fe27 --- /dev/null +++ b/bsp/gd32/gd32305r-start/README.md @@ -0,0 +1,98 @@ +# GD32305R-START开发板BSP说明 + +## 简介 + +GD3305R-START是-兆易创新推出的一款GD32F30X系列的评估板,最高主频高达120M,该开发板具有丰富的板载资源,可以充分发挥 GD3230R 的芯片性能。 + +开发板外观如下图所示: + +![board](figures/board.jpg) + +该开发板常用 **板载资源** 如下: + +- GD32305R,主频 120MHz,256KB FLASH ,96KB RAM + +- 常用外设 + + - LED :2个,LED1 (电源指示灯),LED2(PC6) + - 按键:2个,K1(复位引脚),K2(用户按键,PA0) + +- 常用接口:USB 接口 + +- 调试接口:GD-LINK + +## 外设支持 + +本 BSP 目前对外设的支持情况如下: + +| **片上外设** | **支持情况** | **备注** | +|:--------- |:--------:|:------------------------------------- | +| GPIO | 支持 | PA0, PA1... PK15 ---> PIN: 0, 1...144 | +| UART | 支持 | UART0 - UART7 | +| I2C | 支持 | I2C1 | +| SPI | 支持 | SPI0. SPI1, SPI2 | +| SPI FLASH | 支持 | | +| **扩展模块** | **支持情况** | **备注** | +| 暂无 | 暂不支持 | 暂不支持 | + +## 使用说明 + +使用说明分为如下两个章节: + +- 快速上手 + + 本章节是为刚接触 RT-Thread 的新手准备的使用说明,遵循简单的步骤即可将 RT-Thread 操作系统运行在该开发板上,看到实验效果 。 + +- 进阶使用 + + 本章节是为需要在 RT-Thread 操作系统上使用更多开发板资源的开发者准备的。通过使用 ENV 工具对 BSP 进行配置,可以开启更多板载资源,实现更多高级功能。 + +### 快速上手 + +本 BSP 为开发者提供 MDK5 工程,并且支持 GCC 开发环境,也可使用RT-Thread Studio开发。下面以 MDK5 开发环境为例,介绍如何将系统运行起来。 + +#### 硬件连接 + +使用数据线连接开发板到 PC,使用USB转TTL模块连接PA2(MCU TX)和PA3(MCU RX),打开电源开关。 + +#### 编译下载 + +双击 project.uvprojx 文件,打开 MDK5 工程,编译并下载程序到开发板。 + +> 工程默认配置使用 GD-Link 仿真器下载程序,在通过 GD-Link 连接开发板的基础上,点击下载按钮即可下载程序到开发板 + +#### 运行结果 + +下载程序成功之后,系统会自动运行,LED 闪烁。 + +连接开发板对应串口到 PC , 在终端工具里打开相应的串口(115200-8-1-N),复位设备后,可以看到 RT-Thread 的输出信息: + +```bash + \ | / +- RT - Thread Operating System + / | \ 4.0.4 build Jan 9 2021 + 2006 - 2021 Copyright by rt-thread team +msh > +``` + +### 进阶使用 + +此 BSP 默认只开启了 GPIO 和 串口1的功能,如果需使用高级功能,需要利用 ENV 工具对BSP 进行配置,步骤如下: + +1. 在 bsp 下打开 env 工具。 + +2. 输入`menuconfig`命令配置工程,配置好之后保存退出。 + +3. 输入`pkgs --update`命令更新软件包。 + +4. 输入`scons --target=mdk4/mdk5` 命令重新生成工程。 + +## 注意事项 + +暂无 + +## 联系人信息 + +维护人: + +- [BruceOu](https://github.com/Ouxiaolong/), 邮箱: \ No newline at end of file diff --git a/bsp/gd32/gd32305r-start/SConscript b/bsp/gd32/gd32305r-start/SConscript new file mode 100644 index 0000000000..20f7689c53 --- /dev/null +++ b/bsp/gd32/gd32305r-start/SConscript @@ -0,0 +1,15 @@ +# for module compiling +import os +Import('RTT_ROOT') +from building import * + +cwd = GetCurrentDir() +objs = [] +list = os.listdir(cwd) + +for d in list: + path = os.path.join(cwd, d) + if os.path.isfile(os.path.join(path, 'SConscript')): + objs = objs + SConscript(os.path.join(d, 'SConscript')) + +Return('objs') diff --git a/bsp/gd32/gd32305r-start/SConstruct b/bsp/gd32/gd32305r-start/SConstruct new file mode 100644 index 0000000000..f32e96f624 --- /dev/null +++ b/bsp/gd32/gd32305r-start/SConstruct @@ -0,0 +1,60 @@ +import os +import sys +import rtconfig + +if os.getenv('RTT_ROOT'): + RTT_ROOT = os.getenv('RTT_ROOT') +else: + RTT_ROOT = os.path.normpath(os.getcwd() + '/../../..') + +sys.path = sys.path + [os.path.join(RTT_ROOT, 'tools')] +try: + from building import * +except: + print('Cannot found RT-Thread root directory, please check RTT_ROOT') + print(RTT_ROOT) + exit(-1) + +TARGET = 'rtthread.' + rtconfig.TARGET_EXT + +DefaultEnvironment(tools=[]) +env = Environment(tools = ['mingw'], + AS = rtconfig.AS, ASFLAGS = rtconfig.AFLAGS, + CC = rtconfig.CC, CCFLAGS = rtconfig.CFLAGS, + AR = rtconfig.AR, ARFLAGS = '-rc', + CXX = rtconfig.CXX, CXXFLAGS = rtconfig.CXXFLAGS, + LINK = rtconfig.LINK, LINKFLAGS = rtconfig.LFLAGS) +env.PrependENVPath('PATH', rtconfig.EXEC_PATH) + +if rtconfig.PLATFORM == 'iar': + env.Replace(CCCOM = ['$CC $CCFLAGS $CPPFLAGS $_CPPDEFFLAGS $_CPPINCFLAGS -o $TARGET $SOURCES']) + env.Replace(ARFLAGS = ['']) + env.Replace(LINKCOM = env["LINKCOM"] + ' --map rtthread.map') + +Export('RTT_ROOT') +Export('rtconfig') + +SDK_ROOT = os.path.abspath('./') + +if os.path.exists(SDK_ROOT + '/libraries'): + libraries_path_prefix = SDK_ROOT + '/libraries' +else: + libraries_path_prefix = os.path.dirname(SDK_ROOT) + '/libraries' + +SDK_LIB = libraries_path_prefix +Export('SDK_LIB') + +# prepare building environment +objs = PrepareBuilding(env, RTT_ROOT, has_libcpu=False) + +gd32_library = 'GD32F30x_Firmware_Library' +rtconfig.BSP_LIBRARY_TYPE = gd32_library + +# include libraries +objs.extend(SConscript(os.path.join(libraries_path_prefix, gd32_library, 'SConscript'))) + +# include drivers +objs.extend(SConscript(os.path.join(libraries_path_prefix, 'gd32_drivers', 'SConscript'))) + +# make a building +DoBuilding(TARGET, objs) diff --git a/bsp/gd32/gd32305r-start/applications/SConscript b/bsp/gd32/gd32305r-start/applications/SConscript new file mode 100644 index 0000000000..01eb940dfb --- /dev/null +++ b/bsp/gd32/gd32305r-start/applications/SConscript @@ -0,0 +1,11 @@ +Import('RTT_ROOT') +Import('rtconfig') +from building import * + +cwd = os.path.join(str(Dir('#')), 'applications') +src = Glob('*.c') +CPPPATH = [cwd, str(Dir('#'))] + +group = DefineGroup('Applications', src, depend = [''], CPPPATH = CPPPATH) + +Return('group') diff --git a/bsp/gd32/gd32305r-start/applications/main.c b/bsp/gd32/gd32305r-start/applications/main.c new file mode 100644 index 0000000000..fc35bb08e1 --- /dev/null +++ b/bsp/gd32/gd32305r-start/applications/main.c @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2006-2022, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2021-08-20 BruceOu first implementation + */ + +#include +#include +#include +#include + +/* defined the LED2 pin: PC6 */ +#define LED2_PIN GET_PIN(C, 6) + +int main(void) +{ + int count = 1; + + /* set LED2 pin mode to output */ + rt_pin_mode(LED2_PIN, PIN_MODE_OUTPUT); + + while (count++) + { + rt_pin_write(LED2_PIN, PIN_HIGH); + rt_thread_mdelay(500); + rt_pin_write(LED2_PIN, PIN_LOW); + rt_thread_mdelay(500); + } + + return RT_EOK; +} diff --git a/bsp/gd32/gd32305r-start/board/Kconfig b/bsp/gd32/gd32305r-start/board/Kconfig new file mode 100644 index 0000000000..5ef7ae972d --- /dev/null +++ b/bsp/gd32/gd32305r-start/board/Kconfig @@ -0,0 +1,85 @@ +menu "Hardware Drivers Config" + +config SOC_SERIES_GD32F30x + bool + default y + +config SOC_GD32305R + bool + select SOC_SERIES_GD32F30x + select RT_USING_COMPONENTS_INIT + select RT_USING_USER_MAIN + default y + +menu "Onboard Peripheral Drivers" + +endmenu + +menu "On-chip Peripheral Drivers" + + config BSP_USING_GPIO + bool "Enable GPIO" + select RT_USING_PIN + default y + + menuconfig BSP_USING_UART + bool "Enable UART" + default y + select RT_USING_SERIAL + if BSP_USING_UART + config BSP_USING_UART1 + bool "Enable UART1" + default y + + config BSP_UART1_RX_USING_DMA + bool "Enable UART1 RX DMA" + depends on BSP_USING_UART1 && RT_SERIAL_USING_DMA + default n + endif + + menuconfig BSP_USING_SPI + bool "Enable SPI BUS" + default n + select RT_USING_SPI + if BSP_USING_SPI + config BSP_USING_SPI1 + bool "Enable SPI1 BUS" + default n + + config BSP_SPI1_TX_USING_DMA + bool "Enable SPI1 TX DMA" + depends on BSP_USING_SPI1 + default n + + config BSP_SPI1_RX_USING_DMA + bool "Enable SPI1 RX DMA" + depends on BSP_USING_SPI1 + select BSP_SPI1_TX_USING_DMA + default n + endif + + menuconfig BSP_USING_I2C1 + bool "Enable I2C1 BUS (software simulation)" + default n + select RT_USING_I2C + select RT_USING_I2C_BITOPS + select RT_USING_PIN + if BSP_USING_I2C1 + config BSP_I2C1_SCL_PIN + int "i2c1 scl pin number" + range 1 216 + default 24 + config BSP_I2C1_SDA_PIN + int "I2C1 sda pin number" + range 1 216 + default 25 + endif + source "../libraries/gd32_drivers/Kconfig" + +endmenu + +menu "Board extended module Drivers" + +endmenu + +endmenu diff --git a/bsp/gd32/gd32305r-start/board/SConscript b/bsp/gd32/gd32305r-start/board/SConscript new file mode 100644 index 0000000000..ec6b7bf3c1 --- /dev/null +++ b/bsp/gd32/gd32305r-start/board/SConscript @@ -0,0 +1,28 @@ +import os +import rtconfig +from building import * + +Import('SDK_LIB') + +cwd = GetCurrentDir() + +# add general drivers +src = Split(''' +board.c +''') + +path = [cwd] + +startup_path_prefix = SDK_LIB + +if rtconfig.CROSS_TOOL == 'gcc': + src += [startup_path_prefix + '/GD32F30x_Firmware_Library/CMSIS/GD/GD32F30x/Source/GCC/startup_gd32f30x_cl.s'] +elif rtconfig.CROSS_TOOL == 'keil': + src += [startup_path_prefix + '/GD32F30x_Firmware_Library/CMSIS/GD/GD32F30x/Source/ARM/startup_gd32f30x_cl.s'] +elif rtconfig.CROSS_TOOL == 'iar': + src += [startup_path_prefix + '/GD32F30x_Firmware_Library/CMSIS/GD/GD32F30x/Source/IAR/startup_gd32f30x_cl.s'] + +CPPDEFINES = ['GD32F30X_CL'] +group = DefineGroup('Drivers', src, depend = [''], CPPPATH = path, CPPDEFINES = CPPDEFINES) + +Return('group') diff --git a/bsp/gd32/gd32305r-start/board/board.c b/bsp/gd32/gd32305r-start/board/board.c new file mode 100644 index 0000000000..4a7c61b8cf --- /dev/null +++ b/bsp/gd32/gd32305r-start/board/board.c @@ -0,0 +1,85 @@ +/* + * Copyright (c) 2006-2022, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2021-12-18 BruceOu first implementation + */ +#include +#include +#include +#include + +/** + * @brief This function is executed in case of error occurrence. + * @param None + * @retval None + */ +void Error_Handler(void) +{ + /* USER CODE BEGIN Error_Handler */ + /* User can add his own implementation to report the HAL error return state */ + while (1) + { + } + /* USER CODE END Error_Handler */ +} + +/** System Clock Configuration +*/ +void SystemClock_Config(void) +{ + SysTick_Config(SystemCoreClock / RT_TICK_PER_SECOND); + NVIC_SetPriority(SysTick_IRQn, 0); +} + +/** + * This is the timer interrupt service routine. + * + */ +void SysTick_Handler(void) +{ + /* enter interrupt */ + rt_interrupt_enter(); + + rt_tick_increase(); + + /* leave interrupt */ + rt_interrupt_leave(); +} + +/** + * This function will initial GD32 board. + */ +void rt_hw_board_init() +{ + /* NVIC Configuration */ +#define NVIC_VTOR_MASK 0x3FFFFF80 +#ifdef VECT_TAB_RAM + /* Set the Vector Table base location at 0x10000000 */ + SCB->VTOR = (0x10000000 & NVIC_VTOR_MASK); +#else /* VECT_TAB_FLASH */ + /* Set the Vector Table base location at 0x08000000 */ + SCB->VTOR = (0x08000000 & NVIC_VTOR_MASK); +#endif + + SystemClock_Config(); + +#ifdef RT_USING_COMPONENTS_INIT + rt_components_board_init(); +#endif + +#ifdef RT_USING_CONSOLE + rt_console_set_device(RT_CONSOLE_DEVICE_NAME); +#endif + +#ifdef BSP_USING_SDRAM + rt_system_heap_init((void *)EXT_SDRAM_BEGIN, (void *)EXT_SDRAM_END); +#else + rt_system_heap_init((void *)HEAP_BEGIN, (void *)HEAP_END); +#endif +} + +/*@}*/ diff --git a/bsp/gd32/gd32305r-start/board/board.h b/bsp/gd32/gd32305r-start/board/board.h new file mode 100644 index 0000000000..7bc2c83c60 --- /dev/null +++ b/bsp/gd32/gd32305r-start/board/board.h @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2006-2022, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2021-12-18 BruceOu first implementation + */ +#ifndef __BOARD_H__ +#define __BOARD_H__ + +#include "gd32f30x.h" +#include "drv_usart.h" +#include "drv_gpio.h" + +#include "gd32f30x_exti.h" + +#define EXT_SDRAM_BEGIN (0xC0000000U) /* the begining address of external SDRAM */ +#define EXT_SDRAM_END (EXT_SDRAM_BEGIN + (32U * 1024 * 1024)) /* the end address of external SDRAM */ + +// Internal SRAM memory size[Kbytes] <8-96> +// Default: 96 +#ifdef __ICCARM__ +// Use *.icf ram symbal, to avoid hardcode. +extern char __ICFEDIT_region_RAM_end__; +#define GD32_SRAM_END &__ICFEDIT_region_RAM_end__ +#else +#define GD32_SRAM_SIZE 96 +#define GD32_SRAM_END (0x20000000 + GD32_SRAM_SIZE * 1024) +#endif + +#ifdef __CC_ARM +extern int Image$$RW_IRAM1$$ZI$$Limit; +#define HEAP_BEGIN (&Image$$RW_IRAM1$$ZI$$Limit) +#elif __ICCARM__ +#pragma section="HEAP" +#define HEAP_BEGIN (__segment_end("HEAP")) +#else +extern int __bss_end; +#define HEAP_BEGIN (&__bss_end) +#endif + +#define HEAP_END GD32_SRAM_END + +#endif + diff --git a/bsp/gd32/gd32305r-start/board/gd32f30x_libopt.h b/bsp/gd32/gd32305r-start/board/gd32f30x_libopt.h new file mode 100644 index 0000000000..e026fd658a --- /dev/null +++ b/bsp/gd32/gd32305r-start/board/gd32f30x_libopt.h @@ -0,0 +1,65 @@ +/*! + \file gd32f30x_libopt.h + \brief library optional for gd32f30x + + \version 2021-03-23, V2.0.0, demo for GD32F30x +*/ + +/* + Copyright (c) 2021, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef GD32F30X_LIBOPT_H +#define GD32F30X_LIBOPT_H + +#include "gd32f30x_rcu.h" +#include "gd32f30x_adc.h" +#include "gd32f30x_can.h" +#include "gd32f30x_crc.h" +#include "gd32f30x_ctc.h" +#include "gd32f30x_dac.h" +#include "gd32f30x_dbg.h" +#include "gd32f30x_dma.h" +#include "gd32f30x_exti.h" +#include "gd32f30x_fmc.h" +#include "gd32f30x_fwdgt.h" +#include "gd32f30x_gpio.h" +#include "gd32f30x_i2c.h" +#include "gd32f30x_pmu.h" +#include "gd32f30x_bkp.h" +#include "gd32f30x_rtc.h" +#include "gd32f30x_sdio.h" +#include "gd32f30x_spi.h" +#include "gd32f30x_timer.h" +#include "gd32f30x_usart.h" +#include "gd32f30x_wwdgt.h" +#include "gd32f30x_misc.h" +#include "gd32f30x_exmc.h" +#ifdef GD32F30X_CL +#include "gd32f30x_enet.h" +#endif /* GD32F30X_CL */ + +#endif /* GD32F30X_LIBOPT_H */ diff --git a/bsp/gd32/gd32305r-start/board/linker_scripts/link.icf b/bsp/gd32/gd32305r-start/board/linker_scripts/link.icf new file mode 100644 index 0000000000..283881a728 --- /dev/null +++ b/bsp/gd32/gd32305r-start/board/linker_scripts/link.icf @@ -0,0 +1,40 @@ +/*###ICF### Section handled by ICF editor, don't touch! ****/ +/*-Editor annotation file-*/ +/* IcfEditorFile="$TOOLKIT_DIR$\config\ide\IcfEditor\cortex_v1_0.xml" */ +/*-Specials-*/ +define symbol __ICFEDIT_intvec_start__ = 0x08000000; +/*-Memory Regions-*/ +define symbol __ICFEDIT_region_ROM_start__ = 0x08000000; +define symbol __ICFEDIT_region_ROM_end__ = 0x0803FFFF; +define symbol __ICFEDIT_region_RAM_start__ = 0x20000000; +define symbol __ICFEDIT_region_RAM_end__ = 0x20017FFF; +/*-Sizes-*/ +define symbol __ICFEDIT_size_cstack__ = 0x200; +define symbol __ICFEDIT_size_heap__ = 0x200; +/**** End of ICF editor section. ###ICF###*/ + +export symbol __ICFEDIT_region_RAM_end__; + +define symbol __region_RAM1_start__ = 0x10000000; +define symbol __region_RAM1_end__ = 0x1000FFFF; + +define memory mem with size = 4G; +define region ROM_region = mem:[from __ICFEDIT_region_ROM_start__ to __ICFEDIT_region_ROM_end__]; +define region RAM_region = mem:[from __ICFEDIT_region_RAM_start__ to __ICFEDIT_region_RAM_end__]; +define region RAM1_region = mem:[from __region_RAM1_start__ to __region_RAM1_end__]; + +define block CSTACK with alignment = 8, size = __ICFEDIT_size_cstack__ { }; +define block HEAP with alignment = 8, size = __ICFEDIT_size_heap__ { }; + +initialize by copy { readwrite }; +do not initialize { section .noinit }; + +keep { section FSymTab }; +keep { section VSymTab }; +keep { section .rti_fn* }; +place at address mem:__ICFEDIT_intvec_start__ { readonly section .intvec }; + +place in ROM_region { readonly }; +place in RAM_region { readwrite, + block CSTACK, block HEAP }; +place in RAM1_region { section .sram }; \ No newline at end of file diff --git a/bsp/gd32/gd32305r-start/board/linker_scripts/link.ld b/bsp/gd32/gd32305r-start/board/linker_scripts/link.ld new file mode 100644 index 0000000000..8ba4a0e9f2 --- /dev/null +++ b/bsp/gd32/gd32305r-start/board/linker_scripts/link.ld @@ -0,0 +1,142 @@ +/* + * linker script for GD32F30x with GNU ld + * BruceOu 2021-12-14 + */ + +/* Program Entry, set to mark it as "used" and avoid gc */ +MEMORY +{ + CODE (rx) : ORIGIN = 0x08000000, LENGTH = 256k /* 256KB flash */ + DATA (rw) : ORIGIN = 0x20000000, LENGTH = 96k /* 96KB sram */ +} +ENTRY(Reset_Handler) +_system_stack_size = 0x200; + +SECTIONS +{ + .text : + { + . = ALIGN(4); + _stext = .; + KEEP(*(.isr_vector)) /* Startup code */ + . = ALIGN(4); + *(.text) /* remaining code */ + *(.text.*) /* remaining code */ + *(.rodata) /* read-only data (constants) */ + *(.rodata*) + *(.glue_7) + *(.glue_7t) + *(.gnu.linkonce.t*) + + /* section information for finsh shell */ + . = ALIGN(4); + __fsymtab_start = .; + KEEP(*(FSymTab)) + __fsymtab_end = .; + . = ALIGN(4); + __vsymtab_start = .; + KEEP(*(VSymTab)) + __vsymtab_end = .; + . = ALIGN(4); + + /* section information for initial. */ + . = ALIGN(4); + __rt_init_start = .; + KEEP(*(SORT(.rti_fn*))) + __rt_init_end = .; + . = ALIGN(4); + + . = ALIGN(4); + _etext = .; + } > CODE = 0 + + /* .ARM.exidx is sorted, so has to go in its own output section. */ + __exidx_start = .; + .ARM.exidx : + { + *(.ARM.exidx* .gnu.linkonce.armexidx.*) + + /* This is used by the startup in order to initialize the .data secion */ + _sidata = .; + } > CODE + __exidx_end = .; + + /* .data section which is used for initialized data */ + + .data : AT (_sidata) + { + . = ALIGN(4); + /* This is used by the startup in order to initialize the .data secion */ + _sdata = . ; + + *(.data) + *(.data.*) + *(.gnu.linkonce.d*) + + . = ALIGN(4); + /* This is used by the startup in order to initialize the .data secion */ + _edata = . ; + } >DATA + + .stack : + { + . = . + _system_stack_size; + . = ALIGN(4); + _estack = .; + } >DATA + + __bss_start = .; + .bss : + { + . = ALIGN(4); + /* This is used by the startup in order to initialize the .bss secion */ + _sbss = .; + + *(.bss) + *(.bss.*) + *(COMMON) + + . = ALIGN(4); + /* This is used by the startup in order to initialize the .bss secion */ + _ebss = . ; + + *(.bss.init) + } > DATA + __bss_end = .; + + _end = .; + + /* Stabs debugging sections. */ + .stab 0 : { *(.stab) } + .stabstr 0 : { *(.stabstr) } + .stab.excl 0 : { *(.stab.excl) } + .stab.exclstr 0 : { *(.stab.exclstr) } + .stab.index 0 : { *(.stab.index) } + .stab.indexstr 0 : { *(.stab.indexstr) } + .comment 0 : { *(.comment) } + /* DWARF debug sections. + * Symbols in the DWARF debugging sections are relative to the beginning + * of the section so we begin them at 0. */ + /* DWARF 1 */ + .debug 0 : { *(.debug) } + .line 0 : { *(.line) } + /* GNU DWARF 1 extensions */ + .debug_srcinfo 0 : { *(.debug_srcinfo) } + .debug_sfnames 0 : { *(.debug_sfnames) } + /* DWARF 1.1 and DWARF 2 */ + .debug_aranges 0 : { *(.debug_aranges) } + .debug_pubnames 0 : { *(.debug_pubnames) } + /* DWARF 2 */ + .debug_info 0 : { *(.debug_info .gnu.linkonce.wi.*) } + .debug_abbrev 0 : { *(.debug_abbrev) } + .debug_line 0 : { *(.debug_line) } + .debug_frame 0 : { *(.debug_frame) } + .debug_str 0 : { *(.debug_str) } + .debug_loc 0 : { *(.debug_loc) } + .debug_macinfo 0 : { *(.debug_macinfo) } + /* SGI/MIPS DWARF 2 extensions */ + .debug_weaknames 0 : { *(.debug_weaknames) } + .debug_funcnames 0 : { *(.debug_funcnames) } + .debug_typenames 0 : { *(.debug_typenames) } + .debug_varnames 0 : { *(.debug_varnames) } +} diff --git a/bsp/gd32/gd32305r-start/board/linker_scripts/link.sct b/bsp/gd32/gd32305r-start/board/linker_scripts/link.sct new file mode 100644 index 0000000000..0529ba2b9c --- /dev/null +++ b/bsp/gd32/gd32305r-start/board/linker_scripts/link.sct @@ -0,0 +1,15 @@ +; ************************************************************* +; *** Scatter-Loading Description File generated by uVision *** +; ************************************************************* + +LR_IROM1 0x08000000 0x00040000 { ; load region size_region + ER_IROM1 0x08000000 0x00040000 { ; load address = execution address + *.o (RESET, +First) + *(InRoot$$Sections) + .ANY (+RO) + } + RW_IRAM1 0x20000000 0x00018000 { ; RW data + .ANY (+RW +ZI) + } +} + diff --git a/bsp/gd32/gd32305r-start/figures/board.jpg b/bsp/gd32/gd32305r-start/figures/board.jpg new file mode 100644 index 0000000000..38d61dadae Binary files /dev/null and b/bsp/gd32/gd32305r-start/figures/board.jpg differ diff --git a/bsp/gd32/gd32305r-start/project.uvoptx b/bsp/gd32/gd32305r-start/project.uvoptx new file mode 100644 index 0000000000..18fdad5165 --- /dev/null +++ b/bsp/gd32/gd32305r-start/project.uvoptx @@ -0,0 +1,180 @@ + + + + 1.0 + +
### uVision Project, (C) Keil Software
+ + + *.c + *.s*; *.src; *.a* + *.obj; *.o + *.lib + *.txt; *.h; *.inc + *.plm + *.cpp + 0 + + + + 0 + 0 + + + + rt-thread + 0x4 + ARM-ADS + + 12000000 + + 1 + 1 + 0 + 1 + 0 + + + 1 + 65535 + 0 + 0 + 0 + + + 79 + 66 + 8 + .\build\ + + + 1 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 0 + 0 + 0 + 0 + + + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 0 + 0 + + + 0 + 0 + 1 + + 0 + + 0 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 0 + 1 + 1 + 1 + 1 + 0 + 0 + 1 + 0 + 0 + 3 + + + + + + + + + + + BIN\CMSIS_AGDI.dll + + + + 0 + UL2CM3 + UL2CM3(-S0 -C0 -P0 -FD20000000 -FC1000 -FN1 -FF0GD32F30x_CL -FS08000000 -FL040000 -FP0($$Device:GD32F305RC$Flash\GD32F30x_CL.FLM)) + + + + + 0 + + + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + + + + 0 + 0 + 0 + + + + + + + + + + + + + ::CMSIS + 0 + 0 + 0 + 1 + + +
diff --git a/bsp/gd32/gd32305r-start/project.uvproj b/bsp/gd32/gd32305r-start/project.uvproj new file mode 100644 index 0000000000..34b3cd3d78 --- /dev/null +++ b/bsp/gd32/gd32305r-start/project.uvproj @@ -0,0 +1,737 @@ + + + 1.1 +
### uVision Project, (C) Keil Software
+ + + rt-thread + 0x4 + ARM-ADS + 0 + + + GD32F305RC + GigaDevice + IRAM(0x20000000-0x20018000) IROM(0x08000000-0x08040000) CLOCK(12000000) CPUTYPE("Cortex-M4") FPU2 + + "Startup\GD\GD32F30x\startup_gd32f30x.s" ("GD32F30x Startup Code") + UL2CM3(-O207 -S0 -C0 -FO7 -FD20000000 -FC800 -FN1 -FF0GD32F30x_3MB -FS08000000 -FL0300000) + 0 + gd32f30x0.h + + + + + + + + + + SFD\GD\GD32F30x\GD32F30x.SFR + 0 + 0 + + + + GD\GD32F30x\ + GD\GD32F30x\ + + 0 + 0 + 0 + 0 + 1 + + .\output\ + rtthread + 1 + 0 + 1 + 1 + 1 + .\build\ + 1 + 0 + 0 + + 0 + 0 + + + 0 + 0 + 0 + 0 + + + 0 + 0 + + + 0 + 0 + 0 + 0 + + + 0 + 0 + + + 0 + 0 + 0 + 0 + + 0 + + + + 0 + 0 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 0 + 3 + + + 1 + + + SARMCM3.DLL + -REMAP + DCM.DLL + -pCM3 + SARMCM3.DLL + + TCM.DLL + -pCM3 + + + + 1 + 0 + 0 + 0 + 16 + + + 0 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 0 + 1 + + + 1 + 1 + 1 + 1 + 1 + 1 + 0 + 1 + 0 + 1 + + 0 + 3 + + + + + + + + + + + + + + BIN\CMSIS_AGDI.dll + + + + + 1 + 0 + 0 + 1 + 1 + 4096 + + 1 + BIN\UL2CM3.DLL + "" () + + + + + 0 + + + + 0 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 0 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 0 + 0 + "Cortex-M4" + + 0 + 0 + 0 + 1 + 1 + 0 + 0 + 2 + 1 + 0 + 8 + 1 + 0 + 0 + 0 + 3 + 3 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 0 + 1 + 0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x20000000 + 0x30000 + + + 1 + 0x8000000 + 0x300000 + + + 0 + 0x0 + 0x0 + + + 1 + 0x0 + 0x0 + + + 1 + 0x0 + 0x0 + + + 1 + 0x0 + 0x0 + + + 1 + 0x8000000 + 0x300000 + + + 1 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x20000000 + 0x30000 + + + 0 + 0x10000000 + 0x10000 + + + + + + 1 + 1 + 0 + 0 + 1 + 0 + 0 + 0 + 0 + 0 + 2 + 0 + 0 + 1 + 0 + 0 + 1 + 1 + 1 + 1 + 0 + 0 + 0 + + + GD32F30X_CL, USE_STDPERIPH_DRIVER, __RTTHREAD__, __CLK_TCK=RT_TICK_PER_SECOND + + applications;.;..\..\..\libcpu\arm\common;..\..\..\libcpu\arm\cortex-m4;..\..\..\components\drivers\include;..\..\..\components\drivers\include;..\..\..\components\drivers\include;board;..\libraries\gd32_drivers;..\..\..\components\finsh;.;..\..\..\include;..\..\..\components\libc\compilers\common;..\..\..\components\libc\compilers\common\nogcc;..\libraries\GD32F30x_Firmware_Library\CMSIS\GD\GD32F30x\Include;..\libraries\GD32F30x_Firmware_Library\CMSIS;..\libraries\GD32F30x_Firmware_Library\GD32F30x_standard_peripheral\Include;..\..\..\components\libc\posix\io\poll;..\..\..\components\libc\posix\ipc;..\..\..\examples\utest\testcases\kernel + + + + 1 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + + + + + + + + + 1 + 0 + 0 + 0 + 1 + 0 + 0x08000000 + 0x20000000 + + + + + + + + + + + + + Applications + + + main.c + 1 + applications\main.c + + + + + CPU + + + div0.c + 1 + ..\..\..\libcpu\arm\common\div0.c + + + + + backtrace.c + 1 + ..\..\..\libcpu\arm\common\backtrace.c + + + + + showmem.c + 1 + ..\..\..\libcpu\arm\common\showmem.c + + + + + context_rvds.S + 2 + ..\..\..\libcpu\arm\cortex-m4\context_rvds.S + + + + + cpuport.c + 1 + ..\..\..\libcpu\arm\cortex-m4\cpuport.c + + + + + DeviceDrivers + + + pin.c + 1 + ..\..\..\components\drivers\misc\pin.c + + + + + serial.c + 1 + ..\..\..\components\drivers\serial\serial.c + + + + + completion.c + 1 + ..\..\..\components\drivers\src\completion.c + + + + + ringblk_buf.c + 1 + ..\..\..\components\drivers\src\ringblk_buf.c + + + + + workqueue.c + 1 + ..\..\..\components\drivers\src\workqueue.c + + + + + dataqueue.c + 1 + ..\..\..\components\drivers\src\dataqueue.c + + + + + waitqueue.c + 1 + ..\..\..\components\drivers\src\waitqueue.c + + + + + pipe.c + 1 + ..\..\..\components\drivers\src\pipe.c + + + + + ringbuffer.c + 1 + ..\..\..\components\drivers\src\ringbuffer.c + + + + + Drivers + + + startup_gd32f30x_cl.s + 2 + ..\libraries\GD32F30x_Firmware_Library\CMSIS\GD\GD32F30x\Source\ARM\startup_gd32f30x_cl.s + + + + + board.c + 1 + board\board.c + + + + + drv_gpio.c + 1 + ..\libraries\gd32_drivers\drv_gpio.c + + + + + drv_usart.c + 1 + ..\libraries\gd32_drivers\drv_usart.c + + + + + Finsh + + + shell.c + 1 + ..\..\..\components\finsh\shell.c + + + + + msh.c + 1 + ..\..\..\components\finsh\msh.c + + + + + cmd.c + 1 + ..\..\..\components\finsh\cmd.c + + + + + Kernel + + + mempool.c + 1 + ..\..\..\src\mempool.c + + + + + timer.c + 1 + ..\..\..\src\timer.c + + + + + components.c + 1 + ..\..\..\src\components.c + + + + + object.c + 1 + ..\..\..\src\object.c + + + + + irq.c + 1 + ..\..\..\src\irq.c + + + + + ipc.c + 1 + ..\..\..\src\ipc.c + + + + + kservice.c + 1 + ..\..\..\src\kservice.c + + + + + scheduler.c + 1 + ..\..\..\src\scheduler.c + + + + + idle.c + 1 + ..\..\..\src\idle.c + + + + + device.c + 1 + ..\..\..\src\device.c + + + + + mem.c + 1 + ..\..\..\src\mem.c + + + + + thread.c + 1 + ..\..\..\src\thread.c + + + + + clock.c + 1 + ..\..\..\src\clock.c + + + + + libc + + + time.c + 1 + ..\..\..\components\libc\compilers\common\time.c + + + + + Libraries + + + system_gd32f30x.c + 1 + ..\libraries\GD32F30x_Firmware_Library\CMSIS\GD\GD32F30x\Source\system_gd32f30x.c + + + + + gd32f30x_rcu.c + 1 + ..\libraries\GD32F30x_Firmware_Library\GD32F30x_standard_peripheral\Source\gd32f30x_rcu.c + + + + + gd32f30x_usart.c + 1 + ..\libraries\GD32F30x_Firmware_Library\GD32F30x_standard_peripheral\Source\gd32f30x_usart.c + + + + + gd32f30x_exti.c + 1 + ..\libraries\GD32F30x_Firmware_Library\GD32F30x_standard_peripheral\Source\gd32f30x_exti.c + + + + + gd32f30x_gpio.c + 1 + ..\libraries\GD32F30x_Firmware_Library\GD32F30x_standard_peripheral\Source\gd32f30x_gpio.c + + + + + gd32f30x_misc.c + 1 + ..\libraries\GD32F30x_Firmware_Library\GD32F30x_standard_peripheral\Source\gd32f30x_misc.c + + + + + + +
diff --git a/bsp/gd32/gd32305r-start/project.uvprojx b/bsp/gd32/gd32305r-start/project.uvprojx new file mode 100644 index 0000000000..865d1a16b2 --- /dev/null +++ b/bsp/gd32/gd32305r-start/project.uvprojx @@ -0,0 +1,727 @@ + + + 2.1 +
### uVision Project, (C) Keil Software
+ + + rt-thread + 0x4 + ARM-ADS + 5060750::V5.06 update 6 (build 750)::.\ARMCC + 0 + + + GD32F305RC + GigaDevice + GigaDevice.GD32F30x_DFP.2.1.0 + http://gd32mcu.com/data/documents/pack/ + IRAM(0x20000000,0x018000) IROM(0x08000000,0x040000) CPUTYPE("Cortex-M4") FPU2 CLOCK(12000000) ELITTLE + + + UL2CM3(-S0 -C0 -P0 -FD20000000 -FC1000 -FN1 -FF0GD32F30x_CL -FS08000000 -FL040000 -FP0($$Device:GD32F305RC$Flash\GD32F30x_CL.FLM)) + 0 + $$Device:GD32F305RC$Device\Include\gd32f30x.h + + + + + + + + + + $$Device:GD32F305RC$SVD\GD32F30x_CL.svd + 0 + 0 + + + + + + + 0 + 0 + 0 + 0 + 1 + + .\build\ + rtthread + 1 + 0 + 0 + 1 + 0 + .\build\ + 1 + 0 + 0 + + 0 + 0 + + + 0 + 0 + 0 + 0 + + + 0 + 0 + + + 0 + 0 + 0 + 0 + + + 1 + 0 + fromelf --bin !L --output rtthread.bin + + 0 + 0 + 0 + 0 + + 0 + + + + 0 + 0 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 0 + 3 + + + 1 + + + SARMCM3.DLL + -REMAP -MPU + DCM.DLL + -pCM4 + SARMCM3.DLL + -MPU + TCM.DLL + -pCM4 + + + + 1 + 0 + 0 + 0 + 16 + + + + + 1 + 0 + 0 + 1 + 1 + 4096 + + 1 + BIN\UL2CM3.DLL + + + + + + 0 + + + + 0 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 0 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 0 + 0 + "Cortex-M4" + + 0 + 0 + 0 + 1 + 1 + 0 + 0 + 2 + 0 + 0 + 0 + 0 + 8 + 0 + 0 + 0 + 0 + 3 + 3 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 0 + 1 + 0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x20000000 + 0x18000 + + + 1 + 0x8000000 + 0x40000 + + + 0 + 0x0 + 0x0 + + + 1 + 0x0 + 0x0 + + + 1 + 0x0 + 0x0 + + + 1 + 0x0 + 0x0 + + + 1 + 0x8000000 + 0x40000 + + + 1 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x20000000 + 0x18000 + + + 0 + 0x0 + 0x0 + + + + + + 1 + 4 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 1 + 0 + 0 + 1 + 1 + 1 + 1 + 0 + 0 + 0 + + + GD32F30X_CL, USE_STDPERIPH_DRIVER, __RTTHREAD__, __CLK_TCK=RT_TICK_PER_SECOND + + applications;.;..\..\..\libcpu\arm\common;..\..\..\libcpu\arm\cortex-m4;..\..\..\components\drivers\include;..\..\..\components\drivers\include;..\..\..\components\drivers\include;board;..\libraries\gd32_drivers;..\..\..\components\finsh;.;..\..\..\include;..\..\..\components\libc\compilers\common;..\..\..\components\libc\compilers\common\nogcc;..\libraries\GD32F30x_Firmware_Library\CMSIS\GD\GD32F30x\Include;..\libraries\GD32F30x_Firmware_Library\CMSIS;..\libraries\GD32F30x_Firmware_Library\GD32F30x_standard_peripheral\Include;..\..\..\components\libc\posix\io\poll;..\..\..\components\libc\posix\ipc;..\..\..\examples\utest\testcases\kernel + + + + 1 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 4 + + + + + + + + + 1 + 0 + 0 + 0 + 1 + 0 + 0x08000000 + 0x20000000 + + .\gd32_rom.ld + + + + + + + + + + + Applications + + + main.c + 1 + applications\main.c + + + + + CPU + + + backtrace.c + 1 + ..\..\..\libcpu\arm\common\backtrace.c + + + + + showmem.c + 1 + ..\..\..\libcpu\arm\common\showmem.c + + + + + div0.c + 1 + ..\..\..\libcpu\arm\common\div0.c + + + + + cpuport.c + 1 + ..\..\..\libcpu\arm\cortex-m4\cpuport.c + + + + + context_rvds.S + 2 + ..\..\..\libcpu\arm\cortex-m4\context_rvds.S + + + + + DeviceDrivers + + + pin.c + 1 + ..\..\..\components\drivers\misc\pin.c + + + + + serial.c + 1 + ..\..\..\components\drivers\serial\serial.c + + + + + pipe.c + 1 + ..\..\..\components\drivers\src\pipe.c + + + + + dataqueue.c + 1 + ..\..\..\components\drivers\src\dataqueue.c + + + + + ringbuffer.c + 1 + ..\..\..\components\drivers\src\ringbuffer.c + + + + + completion.c + 1 + ..\..\..\components\drivers\src\completion.c + + + + + ringblk_buf.c + 1 + ..\..\..\components\drivers\src\ringblk_buf.c + + + + + workqueue.c + 1 + ..\..\..\components\drivers\src\workqueue.c + + + + + waitqueue.c + 1 + ..\..\..\components\drivers\src\waitqueue.c + + + + + Drivers + + + startup_gd32f30x_cl.s + 2 + ..\libraries\GD32F30x_Firmware_Library\CMSIS\GD\GD32F30x\Source\ARM\startup_gd32f30x_cl.s + + + + + board.c + 1 + board\board.c + + + + + drv_gpio.c + 1 + ..\libraries\gd32_drivers\drv_gpio.c + + + + + drv_usart.c + 1 + ..\libraries\gd32_drivers\drv_usart.c + + + + + Finsh + + + shell.c + 1 + ..\..\..\components\finsh\shell.c + + + + + msh.c + 1 + ..\..\..\components\finsh\msh.c + + + + + cmd.c + 1 + ..\..\..\components\finsh\cmd.c + + + + + Kernel + + + irq.c + 1 + ..\..\..\src\irq.c + + + + + object.c + 1 + ..\..\..\src\object.c + + + + + components.c + 1 + ..\..\..\src\components.c + + + + + idle.c + 1 + ..\..\..\src\idle.c + + + + + thread.c + 1 + ..\..\..\src\thread.c + + + + + clock.c + 1 + ..\..\..\src\clock.c + + + + + scheduler.c + 1 + ..\..\..\src\scheduler.c + + + + + mem.c + 1 + ..\..\..\src\mem.c + + + + + mempool.c + 1 + ..\..\..\src\mempool.c + + + + + device.c + 1 + ..\..\..\src\device.c + + + + + ipc.c + 1 + ..\..\..\src\ipc.c + + + + + timer.c + 1 + ..\..\..\src\timer.c + + + + + kservice.c + 1 + ..\..\..\src\kservice.c + + + + + libc + + + time.c + 1 + ..\..\..\components\libc\compilers\common\time.c + + + + + Libraries + + + system_gd32f30x.c + 1 + ..\libraries\GD32F30x_Firmware_Library\CMSIS\GD\GD32F30x\Source\system_gd32f30x.c + + + + + gd32f30x_rcu.c + 1 + ..\libraries\GD32F30x_Firmware_Library\GD32F30x_standard_peripheral\Source\gd32f30x_rcu.c + + + + + gd32f30x_usart.c + 1 + ..\libraries\GD32F30x_Firmware_Library\GD32F30x_standard_peripheral\Source\gd32f30x_usart.c + + + + + gd32f30x_exti.c + 1 + ..\libraries\GD32F30x_Firmware_Library\GD32F30x_standard_peripheral\Source\gd32f30x_exti.c + + + + + gd32f30x_gpio.c + 1 + ..\libraries\GD32F30x_Firmware_Library\GD32F30x_standard_peripheral\Source\gd32f30x_gpio.c + + + + + gd32f30x_misc.c + 1 + ..\libraries\GD32F30x_Firmware_Library\GD32F30x_standard_peripheral\Source\gd32f30x_misc.c + + + + + + + + + + + + + + + + + + + + + + <Project Info> + + + + + + 0 + 1 + + + +
diff --git a/bsp/gd32/gd32305r-start/rtconfig.h b/bsp/gd32/gd32305r-start/rtconfig.h new file mode 100644 index 0000000000..099327af24 --- /dev/null +++ b/bsp/gd32/gd32305r-start/rtconfig.h @@ -0,0 +1,200 @@ +#ifndef RT_CONFIG_H__ +#define RT_CONFIG_H__ + +/* Automatically generated file; DO NOT EDIT. */ +/* RT-Thread Configuration */ + +/* RT-Thread Kernel */ + +#define RT_NAME_MAX 8 +#define RT_ALIGN_SIZE 4 +#define RT_THREAD_PRIORITY_32 +#define RT_THREAD_PRIORITY_MAX 32 +#define RT_TICK_PER_SECOND 100 +#define RT_USING_OVERFLOW_CHECK +#define RT_USING_HOOK +#define RT_USING_IDLE_HOOK +#define RT_IDLE_HOOK_LIST_SIZE 4 +#define IDLE_THREAD_STACK_SIZE 256 + +/* kservice optimization */ + +#define RT_DEBUG +#define RT_DEBUG_COLOR + +/* Inter-Thread communication */ + +#define RT_USING_SEMAPHORE +#define RT_USING_MUTEX +#define RT_USING_EVENT +#define RT_USING_MAILBOX +#define RT_USING_MESSAGEQUEUE + +/* Memory Management */ + +#define RT_USING_MEMPOOL +#define RT_USING_SMALL_MEM +#define RT_USING_HEAP + +/* Kernel Device Object */ + +#define RT_USING_DEVICE +#define RT_USING_CONSOLE +#define RT_CONSOLEBUF_SIZE 128 +#define RT_CONSOLE_DEVICE_NAME "uart1" +#define RT_VER_NUM 0x40004 + +/* RT-Thread Components */ + +#define RT_USING_COMPONENTS_INIT +#define RT_USING_USER_MAIN +#define RT_MAIN_THREAD_STACK_SIZE 2048 +#define RT_MAIN_THREAD_PRIORITY 10 + +/* C++ features */ + + +/* Command shell */ + +#define RT_USING_FINSH +#define RT_USING_MSH +#define FINSH_USING_MSH +#define FINSH_THREAD_NAME "tshell" +#define FINSH_THREAD_PRIORITY 20 +#define FINSH_THREAD_STACK_SIZE 4096 +#define FINSH_USING_HISTORY +#define FINSH_HISTORY_LINES 5 +#define FINSH_USING_SYMTAB +#define FINSH_CMD_SIZE 80 +#define MSH_USING_BUILT_IN_COMMANDS +#define FINSH_USING_DESCRIPTION +#define FINSH_ARG_MAX 10 + +/* Device virtual file system */ + + +/* Device Drivers */ + +#define RT_USING_DEVICE_IPC +#define RT_PIPE_BUFSZ 512 +#define RT_USING_SYSTEM_WORKQUEUE +#define RT_SYSTEM_WORKQUEUE_STACKSIZE 2048 +#define RT_SYSTEM_WORKQUEUE_PRIORITY 23 +#define RT_USING_SERIAL +#define RT_USING_SERIAL_V1 +#define RT_SERIAL_USING_DMA +#define RT_SERIAL_RB_BUFSZ 64 +#define RT_USING_PIN + +/* Using USB */ + + +/* POSIX layer and C standard library */ + +#define RT_LIBC_USING_TIME +#define RT_LIBC_DEFAULT_TIMEZONE 8 + +/* Network */ + +/* Socket abstraction layer */ + + +/* Network interface device */ + + +/* light weight TCP/IP stack */ + + +/* AT commands */ + + +/* VBUS(Virtual Software BUS) */ + + +/* Utilities */ + + +/* RT-Thread Utestcases */ + + +/* RT-Thread online packages */ + +/* IoT - internet of things */ + + +/* Wi-Fi */ + +/* Marvell WiFi */ + + +/* Wiced WiFi */ + + +/* IoT Cloud */ + + +/* security packages */ + + +/* language packages */ + + +/* multimedia packages */ + +/* LVGL: powerful and easy-to-use embedded GUI library */ + + +/* u8g2: a monochrome graphic library */ + + +/* PainterEngine: A cross-platform graphics application framework written in C language */ + + +/* tools packages */ + + +/* system packages */ + +/* enhanced kernel services */ + + +/* acceleration: Assembly language or algorithmic acceleration packages */ + + +/* CMSIS: ARM Cortex-M Microcontroller Software Interface Standard */ + + +/* Micrium: Micrium software products porting for RT-Thread */ + + +/* peripheral libraries and drivers */ + + +/* AI packages */ + + +/* miscellaneous packages */ + +/* samples: kernel and components samples */ + + +/* entertainment: terminal games and other interesting software packages */ + + +/* Hardware Drivers Config */ + +#define SOC_SERIES_GD32F30x +#define SOC_GD32305R + +/* Onboard Peripheral Drivers */ + +/* On-chip Peripheral Drivers */ + +#define BSP_USING_GPIO +#define BSP_USING_UART +#define BSP_USING_UART1 + +/* Board extended module Drivers */ + + +#endif diff --git a/bsp/gd32/gd32305r-start/rtconfig.py b/bsp/gd32/gd32305r-start/rtconfig.py new file mode 100644 index 0000000000..a91905a233 --- /dev/null +++ b/bsp/gd32/gd32305r-start/rtconfig.py @@ -0,0 +1,150 @@ +import os + +# toolchains options +ARCH='arm' +CPU='cortex-m4' +CROSS_TOOL='keil' + +# bsp lib config +BSP_LIBRARY_TYPE = None + +if os.getenv('RTT_CC'): + CROSS_TOOL = os.getenv('RTT_CC') +if os.getenv('RTT_ROOT'): + RTT_ROOT = os.getenv('RTT_ROOT') + +# cross_tool provides the cross compiler +# EXEC_PATH is the compiler execute path, for example, CodeSourcery, Keil MDK, IAR +if CROSS_TOOL == 'gcc': + PLATFORM = 'gcc' + EXEC_PATH = r'C:\Users\XXYYZZ' +elif CROSS_TOOL == 'keil': + PLATFORM = 'armcc' + EXEC_PATH = r'C:/Keil_v5' +elif CROSS_TOOL == 'iar': + PLATFORM = 'iar' + EXEC_PATH = r'C:/Program Files (x86)/IAR Systems/Embedded Workbench 8.0' + +if os.getenv('RTT_EXEC_PATH'): + EXEC_PATH = os.getenv('RTT_EXEC_PATH') + +BUILD = 'debug' + +if PLATFORM == 'gcc': + # toolchains + PREFIX = 'arm-none-eabi-' + CC = PREFIX + 'gcc' + AS = PREFIX + 'gcc' + AR = PREFIX + 'ar' + CXX = PREFIX + 'g++' + LINK = PREFIX + 'gcc' + TARGET_EXT = 'elf' + SIZE = PREFIX + 'size' + OBJDUMP = PREFIX + 'objdump' + OBJCPY = PREFIX + 'objcopy' + + DEVICE = ' -mcpu=cortex-m4 -mthumb -mfpu=fpv4-sp-d16 -mfloat-abi=hard -ffunction-sections -fdata-sections' + CFLAGS = DEVICE + ' -Dgcc' + AFLAGS = ' -c' + DEVICE + ' -x assembler-with-cpp -Wa,-mimplicit-it=thumb ' + LFLAGS = DEVICE + ' -Wl,--gc-sections,-Map=rtthread.map,-cref,-u,Reset_Handler -T board/linker_scripts/link.ld' + + CPATH = '' + LPATH = '' + + if BUILD == 'debug': + CFLAGS += ' -O0 -gdwarf-2 -g' + AFLAGS += ' -gdwarf-2' + else: + CFLAGS += ' -O2' + + CXXFLAGS = CFLAGS + + POST_ACTION = OBJCPY + ' -O binary $TARGET rtthread.bin\n' + SIZE + ' $TARGET \n' + +elif PLATFORM == 'armcc': + # toolchains + CC = 'armcc' + CXX = 'armcc' + AS = 'armasm' + AR = 'armar' + LINK = 'armlink' + TARGET_EXT = 'axf' + + DEVICE = ' --cpu Cortex-M4.fp ' + CFLAGS = '-c ' + DEVICE + ' --apcs=interwork --c99' + AFLAGS = DEVICE + ' --apcs=interwork ' + LFLAGS = DEVICE + ' --scatter "board\linker_scripts\link.sct" --info sizes --info totals --info unused --info veneers --list rtthread.map --strict' + CFLAGS += ' -I' + EXEC_PATH + '/ARM/ARMCC/include' + LFLAGS += ' --libpath=' + EXEC_PATH + '/ARM/ARMCC/lib' + + CFLAGS += ' -D__MICROLIB ' + AFLAGS += ' --pd "__MICROLIB SETA 1" ' + LFLAGS += ' --library_type=microlib ' + EXEC_PATH += '/ARM/ARMCC/bin/' + + if BUILD == 'debug': + CFLAGS += ' -g -O0' + AFLAGS += ' -g' + else: + CFLAGS += ' -O2' + + CXXFLAGS = CFLAGS + CFLAGS += ' -std=c99' + + POST_ACTION = 'fromelf --bin $TARGET --output rtthread.bin \nfromelf -z $TARGET' + +elif PLATFORM == 'iar': + # toolchains + CC = 'iccarm' + CXX = 'iccarm' + AS = 'iasmarm' + AR = 'iarchive' + LINK = 'ilinkarm' + TARGET_EXT = 'out' + + DEVICE = '-Dewarm' + + CFLAGS = DEVICE + CFLAGS += ' --diag_suppress Pa050' + CFLAGS += ' --no_cse' + CFLAGS += ' --no_unroll' + CFLAGS += ' --no_inline' + CFLAGS += ' --no_code_motion' + CFLAGS += ' --no_tbaa' + CFLAGS += ' --no_clustering' + CFLAGS += ' --no_scheduling' + CFLAGS += ' --endian=little' + CFLAGS += ' --cpu=Cortex-M4' + CFLAGS += ' -e' + CFLAGS += ' --fpu=VFPv4_sp' + CFLAGS += ' --dlib_config "' + EXEC_PATH + '/arm/INC/c/DLib_Config_Normal.h"' + CFLAGS += ' --silent' + + AFLAGS = DEVICE + AFLAGS += ' -s+' + AFLAGS += ' -w+' + AFLAGS += ' -r' + AFLAGS += ' --cpu Cortex-M4' + AFLAGS += ' --fpu VFPv4_sp' + AFLAGS += ' -S' + + if BUILD == 'debug': + CFLAGS += ' --debug' + CFLAGS += ' -On' + else: + CFLAGS += ' -Oh' + + LFLAGS = ' --config "board/linker_scripts/link.icf"' + LFLAGS += ' --entry __iar_program_start' + + CXXFLAGS = CFLAGS + + EXEC_PATH = EXEC_PATH + '/arm/bin/' + POST_ACTION = 'ielftool --bin $TARGET rtthread.bin' + +def dist_handle(BSP_ROOT, dist_dir): + import sys + cwd_path = os.getcwd() + sys.path.append(os.path.join(os.path.dirname(BSP_ROOT), 'tools')) + from sdk_dist import dist_do_building + dist_do_building(BSP_ROOT, dist_dir) diff --git a/bsp/gd32/gd32305r-start/template.uvoptx b/bsp/gd32/gd32305r-start/template.uvoptx new file mode 100644 index 0000000000..18fdad5165 --- /dev/null +++ b/bsp/gd32/gd32305r-start/template.uvoptx @@ -0,0 +1,180 @@ + + + + 1.0 + +
### uVision Project, (C) Keil Software
+ + + *.c + *.s*; *.src; *.a* + *.obj; *.o + *.lib + *.txt; *.h; *.inc + *.plm + *.cpp + 0 + + + + 0 + 0 + + + + rt-thread + 0x4 + ARM-ADS + + 12000000 + + 1 + 1 + 0 + 1 + 0 + + + 1 + 65535 + 0 + 0 + 0 + + + 79 + 66 + 8 + .\build\ + + + 1 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 0 + 0 + 0 + 0 + + + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 0 + 0 + + + 0 + 0 + 1 + + 0 + + 0 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 0 + 1 + 1 + 1 + 1 + 0 + 0 + 1 + 0 + 0 + 3 + + + + + + + + + + + BIN\CMSIS_AGDI.dll + + + + 0 + UL2CM3 + UL2CM3(-S0 -C0 -P0 -FD20000000 -FC1000 -FN1 -FF0GD32F30x_CL -FS08000000 -FL040000 -FP0($$Device:GD32F305RC$Flash\GD32F30x_CL.FLM)) + + + + + 0 + + + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + + + + 0 + 0 + 0 + + + + + + + + + + + + + ::CMSIS + 0 + 0 + 0 + 1 + + +
diff --git a/bsp/gd32/gd32305r-start/template.uvproj b/bsp/gd32/gd32305r-start/template.uvproj new file mode 100644 index 0000000000..919038f7f4 --- /dev/null +++ b/bsp/gd32/gd32305r-start/template.uvproj @@ -0,0 +1,628 @@ + + + + 1.1 + +
### uVision Project, (C) Keil Software
+ + + + rt-thread + 0x4 + ARM-ADS + 0 + + + GD32F305RC + GigaDevice + IRAM(0x20000000-0x20018000) IROM(0x08000000-0x08040000) CLOCK(12000000) CPUTYPE("Cortex-M4") FPU2 + + "Startup\GD\GD32F30x\startup_gd32f30x.s" ("GD32F30x Startup Code") + UL2CM3(-O207 -S0 -C0 -FO7 -FD20000000 -FC800 -FN1 -FF0GD32F30x_3MB -FS08000000 -FL0300000) + 0 + gd32f30x.h + + + + + + + + + + SFD\GD\GD32F30x\GD32F30x.SFR + 0 + 0 + + + + GD\GD32F30x\ + GD\GD32F30x\ + + 0 + 0 + 0 + 0 + 1 + + .\output\ + rtthread + 1 + 0 + 1 + 1 + 1 + .\build\ + 1 + 0 + 0 + + 0 + 0 + + + 0 + 0 + 0 + 0 + + + 0 + 0 + + + 0 + 0 + 0 + 0 + + + 0 + 0 + + + 0 + 0 + 0 + 0 + + 0 + + + + 0 + 0 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 0 + 3 + + + 1 + + + SARMCM3.DLL + -REMAP + DCM.DLL + -pCM3 + SARMCM3.DLL + + TCM.DLL + -pCM3 + + + + 1 + 0 + 0 + 0 + 16 + + + 0 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 0 + 1 + + + 1 + 1 + 1 + 1 + 1 + 1 + 0 + 1 + 0 + 1 + + 0 + 3 + + + + + + + + + + + + + + BIN\CMSIS_AGDI.dll + + + + + 1 + 0 + 0 + 1 + 1 + 4096 + + 1 + BIN\UL2CM3.DLL + "" () + + + + + 0 + + + + 0 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 0 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 0 + 0 + "Cortex-M4" + + 0 + 0 + 0 + 1 + 1 + 0 + 0 + 2 + 1 + 0 + 8 + 1 + 0 + 0 + 0 + 3 + 3 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 0 + 1 + 0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x20000000 + 0x30000 + + + 1 + 0x8000000 + 0x300000 + + + 0 + 0x0 + 0x0 + + + 1 + 0x0 + 0x0 + + + 1 + 0x0 + 0x0 + + + 1 + 0x0 + 0x0 + + + 1 + 0x8000000 + 0x300000 + + + 1 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x20000000 + 0x30000 + + + 0 + 0x10000000 + 0x10000 + + + + + + 1 + 1 + 0 + 0 + 1 + 0 + 0 + 0 + 0 + 0 + 2 + 0 + 0 + 1 + 0 + 0 + 1 + 1 + 1 + 1 + 0 + 0 + 0 + + + + + ..\..\..\Library\Firmware\GD32F30x_standard_peripheral\Include;..\..\..\Library\Firmware\CMSIS\GD\GD32F30x\Include;..\..\..\Library\Utilities;..\ + + + + 1 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + + + + + + + + + 1 + 0 + 0 + 0 + 1 + 0 + 0x08000000 + 0x20000000 + + + + + + + + + + + + + Application + + + main.c + 1 + ..\main.c + + + gd32f30x_it.c + 1 + ..\gd32f30x_it.c + + + + + CMSIS + + + system_gd32f30x.c + 1 + ..\..\..\Library\Firmware\CMSIS\GD\GD32F30x\Source\system_gd32f30x.c + + + + + GD32F30x_Peripherals + + + gd32f30x_adc.c + 1 + ..\..\..\Library\Firmware\GD32F30x_standard_peripheral\Source\gd32f30x_adc.c + + + gd32f30x_can.c + 1 + ..\..\..\Library\Firmware\GD32F30x_standard_peripheral\Source\gd32f30x_can.c + + + gd32f30x_crc.c + 1 + ..\..\..\Library\Firmware\GD32F30x_standard_peripheral\Source\gd32f30x_crc.c + + + gd32f30x_ctc.c + 1 + ..\..\..\Library\Firmware\GD32F30x_standard_peripheral\Source\gd32f30x_ctc.c + + + gd32f30x_dac.c + 1 + ..\..\..\Library\Firmware\GD32F30x_standard_peripheral\Source\gd32f30x_dac.c + + + gd32f30x_dbg.c + 1 + ..\..\..\Library\Firmware\GD32F30x_standard_peripheral\Source\gd32f30x_dbg.c + + + gd32f30x_dci.c + 1 + ..\..\..\Library\Firmware\GD32F30x_standard_peripheral\Source\gd32f30x_dci.c + + + gd32f30x_dma.c + 1 + ..\..\..\Library\Firmware\GD32F30x_standard_peripheral\Source\gd32f30x_dma.c + + + gd32f30x_enet.c + 1 + ..\..\..\Library\Firmware\GD32F30x_standard_peripheral\Source\gd32f30x_enet.c + + + gd32f30x_exmc.c + 1 + ..\..\..\Library\Firmware\GD32F30x_standard_peripheral\Source\gd32f30x_exmc.c + + + gd32f30x_exti.c + 1 + ..\..\..\Library\Firmware\GD32F30x_standard_peripheral\Source\gd32f30x_exti.c + + + gd32f30x_fmc.c + 1 + ..\..\..\Library\Firmware\GD32F30x_standard_peripheral\Source\gd32f30x_fmc.c + + + gd32f30x_fwdgt.c + 1 + ..\..\..\Library\Firmware\GD32F30x_standard_peripheral\Source\gd32f30x_fwdgt.c + + + gd32f30x_gpio.c + 1 + ..\..\..\Library\Firmware\GD32F30x_standard_peripheral\Source\gd32f30x_gpio.c + + + gd32f30x_i2c.c + 1 + ..\..\..\Library\Firmware\GD32F30x_standard_peripheral\Source\gd32f30x_i2c.c + + + gd32f30x_ipa.c + 1 + ..\..\..\Library\Firmware\GD32F30x_standard_peripheral\Source\gd32f30x_ipa.c + + + gd32f30x_iref.c + 1 + ..\..\..\Library\Firmware\GD32F30x_standard_peripheral\Source\gd32f30x_iref.c + + + gd32f30x_misc.c + 1 + ..\..\..\Library\Firmware\GD32F30x_standard_peripheral\Source\gd32f30x_misc.c + + + gd32f30x_pmu.c + 1 + ..\..\..\Library\Firmware\GD32F30x_standard_peripheral\Source\gd32f30x_pmu.c + + + gd32f30x_rcu.c + 1 + ..\..\..\Library\Firmware\GD32F30x_standard_peripheral\Source\gd32f30x_rcu.c + + + gd32f30x_rtc.c + 1 + ..\..\..\Library\Firmware\GD32F30x_standard_peripheral\Source\gd32f30x_rtc.c + + + gd32f30x_sdio.c + 1 + ..\..\..\Library\Firmware\GD32F30x_standard_peripheral\Source\gd32f30x_sdio.c + + + gd32f30x_spi.c + 1 + ..\..\..\Library\Firmware\GD32F30x_standard_peripheral\Source\gd32f30x_spi.c + + + gd32f30x_syscfg.c + 1 + ..\..\..\Library\Firmware\GD32F30x_standard_peripheral\Source\gd32f30x_syscfg.c + + + gd32f30x_timer.c + 1 + ..\..\..\Library\Firmware\GD32F30x_standard_peripheral\Source\gd32f30x_timer.c + + + gd32f30x_tli.c + 1 + ..\..\..\Library\Firmware\GD32F30x_standard_peripheral\Source\gd32f30x_tli.c + + + gd32f30x_trng.c + 1 + ..\..\..\Library\Firmware\GD32F30x_standard_peripheral\Source\gd32f30x_trng.c + + + gd32f30x_usart.c + 1 + ..\..\..\Library\Firmware\GD32F30x_standard_peripheral\Source\gd32f30x_usart.c + + + gd32f30x_wwdgt.c + 1 + ..\..\..\Library\Firmware\GD32F30x_standard_peripheral\Source\gd32f30x_wwdgt.c + + + + + GD32F30x_START + + + gd32f305r_start.c + 1 + ..\..\..\Library\Utilities\gd32f305r_start.c + + + + + Startup + + + startup_gd32f30x.s + 2 + ..\..\..\Library\Firmware\CMSIS\GD\GD32F30x\Source\ARM\startup_gd32f30x.s + + + + + Doc + + + readme.txt + 5 + ..\readme.txt + + + + + + + +
diff --git a/bsp/gd32/gd32305r-start/template.uvprojx b/bsp/gd32/gd32305r-start/template.uvprojx new file mode 100644 index 0000000000..0c172a57a8 --- /dev/null +++ b/bsp/gd32/gd32305r-start/template.uvprojx @@ -0,0 +1,418 @@ + + + + 2.1 + +
### uVision Project, (C) Keil Software
+ + + + rt-thread + 0x4 + ARM-ADS + 5060750::V5.06 update 6 (build 750)::.\ARMCC + 0 + + + GD32F305RC + GigaDevice + GigaDevice.GD32F30x_DFP.2.1.0 + http://gd32mcu.com/data/documents/pack/ + IRAM(0x20000000,0x018000) IROM(0x08000000,0x040000) CPUTYPE("Cortex-M4") FPU2 CLOCK(12000000) ELITTLE + + + UL2CM3(-S0 -C0 -P0 -FD20000000 -FC1000 -FN1 -FF0GD32F30x_CL -FS08000000 -FL040000 -FP0($$Device:GD32F305RC$Flash\GD32F30x_CL.FLM)) + 0 + $$Device:GD32F305RC$Device\Include\gd32f30x.h + + + + + + + + + + $$Device:GD32F305RC$SVD\GD32F30x_CL.svd + 0 + 0 + + + + + + + 0 + 0 + 0 + 0 + 1 + + .\build\ + rtthread + 1 + 0 + 0 + 1 + 0 + .\build\ + 1 + 0 + 0 + + 0 + 0 + + + 0 + 0 + 0 + 0 + + + 0 + 0 + + + 0 + 0 + 0 + 0 + + + 1 + 0 + fromelf --bin !L --output rtthread.bin + + 0 + 0 + 0 + 0 + + 0 + + + + 0 + 0 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 0 + 3 + + + 1 + + + SARMCM3.DLL + -REMAP -MPU + DCM.DLL + -pCM4 + SARMCM3.DLL + -MPU + TCM.DLL + -pCM4 + + + + 1 + 0 + 0 + 0 + 16 + + + + + 1 + 0 + 0 + 1 + 1 + 4096 + + 1 + BIN\UL2CM3.DLL + + + + + + 0 + + + + 0 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 0 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 0 + 0 + "Cortex-M4" + + 0 + 0 + 0 + 1 + 1 + 0 + 0 + 2 + 0 + 0 + 0 + 0 + 8 + 0 + 0 + 0 + 0 + 3 + 3 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 0 + 1 + 0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x20000000 + 0x18000 + + + 1 + 0x8000000 + 0x40000 + + + 0 + 0x0 + 0x0 + + + 1 + 0x0 + 0x0 + + + 1 + 0x0 + 0x0 + + + 1 + 0x0 + 0x0 + + + 1 + 0x8000000 + 0x40000 + + + 1 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x20000000 + 0x18000 + + + 0 + 0x0 + 0x0 + + + + + + 1 + 4 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 1 + 0 + 0 + 1 + 1 + 1 + 1 + 0 + 0 + 0 + + + + + + + + + 1 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 4 + + + + + + + + + 1 + 0 + 0 + 0 + 1 + 0 + 0x08000000 + 0x20000000 + + .\gd32_rom.ld + + + + + + + + + + + ::CMSIS + + + + + + + + + + + + + + + + + + + + + + <Project Info> + + + + + + 0 + 1 + + + + +
diff --git a/bsp/gd32/gd32407v-start/.config b/bsp/gd32/gd32407v-start/.config index df22c29d4f..9b21611c11 100644 --- a/bsp/gd32/gd32407v-start/.config +++ b/bsp/gd32/gd32407v-start/.config @@ -1,9 +1,13 @@ -# Generated by Kconfiglib (https://github.com/ulfalizer/Kconfiglib) +# +# Automatically generated file; DO NOT EDIT. +# RT-Thread Configuration +# # # RT-Thread Kernel # CONFIG_RT_NAME_MAX=8 +# CONFIG_RT_USING_BIG_ENDIAN is not set # CONFIG_RT_USING_ARCH_DATA_TYPE is not set # CONFIG_RT_USING_SMP is not set CONFIG_RT_ALIGN_SIZE=4 @@ -26,8 +30,6 @@ CONFIG_IDLE_THREAD_STACK_SIZE=256 # CONFIG_RT_KSERVICE_USING_TINY_SIZE is not set # CONFIG_RT_USING_TINY_FFS is not set # CONFIG_RT_PRINTF_LONGLONG is not set -# end of kservice optimization - CONFIG_RT_DEBUG=y CONFIG_RT_DEBUG_COLOR=y # CONFIG_RT_DEBUG_INIT_CONFIG is not set @@ -50,7 +52,6 @@ CONFIG_RT_USING_EVENT=y CONFIG_RT_USING_MAILBOX=y CONFIG_RT_USING_MESSAGEQUEUE=y # CONFIG_RT_USING_SIGNALS is not set -# end of Inter-Thread communication # # Memory Management @@ -67,7 +68,6 @@ CONFIG_RT_USING_SMALL_MEM_AS_HEAP=y # CONFIG_RT_USING_MEMTRACE is not set # CONFIG_RT_USING_HEAP_ISR is not set CONFIG_RT_USING_HEAP=y -# end of Memory Management # # Kernel Device Object @@ -78,15 +78,9 @@ CONFIG_RT_USING_DEVICE=y CONFIG_RT_USING_CONSOLE=y CONFIG_RT_CONSOLEBUF_SIZE=128 CONFIG_RT_CONSOLE_DEVICE_NAME="uart1" -# end of Kernel Device Object - CONFIG_RT_VER_NUM=0x40100 -# end of RT-Thread Kernel - -CONFIG_ARCH_ARM=y -CONFIG_RT_USING_CPU_FFS=y -CONFIG_ARCH_ARM_CORTEX_M=y -CONFIG_ARCH_ARM_CORTEX_M4=y +# CONFIG_RT_USING_CPU_FFS is not set +# CONFIG_ARCH_CPU_STACK_GROWS_UPWARD is not set # # RT-Thread Components @@ -101,7 +95,6 @@ CONFIG_RT_MAIN_THREAD_PRIORITY=10 # C++ features # # CONFIG_RT_USING_CPLUSPLUS is not set -# end of C++ features # # Command shell @@ -121,13 +114,11 @@ CONFIG_FINSH_USING_DESCRIPTION=y # CONFIG_FINSH_ECHO_DISABLE_DEFAULT is not set # CONFIG_FINSH_USING_AUTH is not set CONFIG_FINSH_ARG_MAX=10 -# end of Command shell # # Device virtual file system # # CONFIG_RT_USING_DFS is not set -# end of Device virtual file system # # Device Drivers @@ -144,7 +135,10 @@ CONFIG_RT_SERIAL_RB_BUFSZ=64 # CONFIG_RT_USING_CAN is not set # CONFIG_RT_USING_HWTIMER is not set # CONFIG_RT_USING_CPUTIME is not set -# CONFIG_RT_USING_I2C is not set +CONFIG_RT_USING_I2C=y +# CONFIG_RT_I2C_DEBUG is not set +CONFIG_RT_USING_I2C_BITOPS=y +# CONFIG_RT_I2C_BITOPS_DEBUG is not set # CONFIG_RT_USING_PHY is not set CONFIG_RT_USING_PIN=y # CONFIG_RT_USING_ADC is not set @@ -168,10 +162,9 @@ CONFIG_RT_USING_PIN=y # # Using USB # +# CONFIG_RT_USING_USB is not set # CONFIG_RT_USING_USB_HOST is not set # CONFIG_RT_USING_USB_DEVICE is not set -# end of Using USB -# end of Device Drivers # # POSIX layer and C standard library @@ -199,9 +192,6 @@ CONFIG_RT_LIBC_DEFAULT_TIMEZONE=8 # # Socket is in the 'Network' category # -# end of Interprocess Communication (IPC) -# end of POSIX (Portable Operating System Interface) layer -# end of POSIX layer and C standard library # # Network @@ -211,32 +201,26 @@ CONFIG_RT_LIBC_DEFAULT_TIMEZONE=8 # Socket abstraction layer # # CONFIG_RT_USING_SAL is not set -# end of Socket abstraction layer # # Network interface device # # CONFIG_RT_USING_NETDEV is not set -# end of Network interface device # # light weight TCP/IP stack # # CONFIG_RT_USING_LWIP is not set -# end of light weight TCP/IP stack # # AT commands # # CONFIG_RT_USING_AT is not set -# end of AT commands -# end of Network # # VBUS(Virtual Software BUS) # # CONFIG_RT_USING_VBUS is not set -# end of VBUS(Virtual Software BUS) # # Utilities @@ -246,16 +230,11 @@ CONFIG_RT_LIBC_DEFAULT_TIMEZONE=8 # CONFIG_RT_USING_UTEST is not set # CONFIG_RT_USING_VAR_EXPORT is not set # CONFIG_RT_USING_RT_LINK is not set -# end of Utilities - -# CONFIG_RT_USING_LWP is not set -# end of RT-Thread Components # # RT-Thread Utestcases # # CONFIG_RT_USING_UTESTCASES is not set -# end of RT-Thread Utestcases # # RT-Thread online packages @@ -290,17 +269,12 @@ CONFIG_RT_LIBC_DEFAULT_TIMEZONE=8 # Marvell WiFi # # CONFIG_PKG_USING_WLANMARVELL is not set -# end of Marvell WiFi # # Wiced WiFi # # CONFIG_PKG_USING_WLAN_WICED is not set -# end of Wiced WiFi - # CONFIG_PKG_USING_RW007 is not set -# end of Wi-Fi - # CONFIG_PKG_USING_COAP is not set # CONFIG_PKG_USING_NOPOLL is not set # CONFIG_PKG_USING_NETUTILS is not set @@ -322,8 +296,6 @@ CONFIG_RT_LIBC_DEFAULT_TIMEZONE=8 # CONFIG_PKG_USING_JIOT-C-SDK is not set # CONFIG_PKG_USING_UCLOUD_IOT_SDK is not set # CONFIG_PKG_USING_JOYLINK is not set -# end of IoT Cloud - # CONFIG_PKG_USING_NIMBLE is not set # CONFIG_PKG_USING_OTA_DOWNLOADER is not set # CONFIG_PKG_USING_IPMSG is not set @@ -358,7 +330,7 @@ CONFIG_RT_LIBC_DEFAULT_TIMEZONE=8 # CONFIG_PKG_USING_LORA_PKT_SNIFFER is not set # CONFIG_PKG_USING_HM is not set # CONFIG_PKG_USING_SMALL_MODBUS is not set -# end of IoT - internet of things +# CONFIG_PKG_USING_NET_SERVER is not set # # security packages @@ -368,7 +340,6 @@ CONFIG_RT_LIBC_DEFAULT_TIMEZONE=8 # CONFIG_PKG_USING_TINYCRYPT is not set # CONFIG_PKG_USING_TFM is not set # CONFIG_PKG_USING_YD_CRYPTO is not set -# end of security packages # # language packages @@ -377,7 +348,6 @@ CONFIG_RT_LIBC_DEFAULT_TIMEZONE=8 # CONFIG_PKG_USING_JERRYSCRIPT is not set # CONFIG_PKG_USING_MICROPYTHON is not set # CONFIG_PKG_USING_PIKASCRIPT is not set -# end of language packages # # multimedia packages @@ -389,15 +359,12 @@ CONFIG_RT_LIBC_DEFAULT_TIMEZONE=8 # CONFIG_PKG_USING_LVGL is not set # CONFIG_PKG_USING_LITTLEVGL2RTT is not set # CONFIG_PKG_USING_LV_MUSIC_DEMO is not set -# end of LVGL: powerful and easy-to-use embedded GUI library # # u8g2: a monochrome graphic library # # CONFIG_PKG_USING_U8G2_OFFICIAL is not set # CONFIG_PKG_USING_U8G2 is not set -# end of u8g2: a monochrome graphic library - # CONFIG_PKG_USING_OPENMV is not set # CONFIG_PKG_USING_MUPDF is not set # CONFIG_PKG_USING_STEMWIN is not set @@ -417,8 +384,9 @@ CONFIG_RT_LIBC_DEFAULT_TIMEZONE=8 # # CONFIG_PKG_USING_PAINTERENGINE is not set # CONFIG_PKG_USING_PAINTERENGINE_AUX is not set -# end of PainterEngine: A cross-platform graphics application framework written in C language -# end of multimedia packages +# CONFIG_PKG_USING_MCURSES is not set +# CONFIG_PKG_USING_TERMBOX is not set +# CONFIG_PKG_USING_VT100 is not set # # tools packages @@ -462,7 +430,6 @@ CONFIG_RT_LIBC_DEFAULT_TIMEZONE=8 # CONFIG_PKG_USING_SOLAR_TERMS is not set # CONFIG_PKG_USING_GAN_ZHI is not set # CONFIG_PKG_USING_FDT is not set -# end of tools packages # # system packages @@ -474,7 +441,12 @@ CONFIG_RT_LIBC_DEFAULT_TIMEZONE=8 # CONFIG_PKG_USING_RT_MEMCPY_CM is not set # CONFIG_PKG_USING_RT_KPRINTF_THREADSAFE is not set # CONFIG_PKG_USING_RT_VSNPRINTF_FULL is not set -# end of enhanced kernel services + +# +# POSIX extension functions +# +# CONFIG_PKG_USING_POSIX_GETLINE is not set +# CONFIG_PKG_USING_POSIX_WCWIDTH is not set # # acceleration: Assembly language or algorithmic acceleration packages @@ -482,14 +454,12 @@ CONFIG_RT_LIBC_DEFAULT_TIMEZONE=8 # CONFIG_PKG_USING_QFPLIB_M0_FULL is not set # CONFIG_PKG_USING_QFPLIB_M0_TINY is not set # CONFIG_PKG_USING_QFPLIB_M3 is not set -# end of acceleration: Assembly language or algorithmic acceleration packages # # CMSIS: ARM Cortex-M Microcontroller Software Interface Standard # # CONFIG_PKG_USING_CMSIS_5 is not set # CONFIG_PKG_USING_CMSIS_RTOS2 is not set -# end of CMSIS: ARM Cortex-M Microcontroller Software Interface Standard # # Micrium: Micrium software products porting for RT-Thread @@ -500,11 +470,8 @@ CONFIG_RT_LIBC_DEFAULT_TIMEZONE=8 # CONFIG_PKG_USING_UC_CLK is not set # CONFIG_PKG_USING_UC_COMMON is not set # CONFIG_PKG_USING_UC_MODBUS is not set -# end of Micrium: Micrium software products porting for RT-Thread - # CONFIG_RT_USING_ARDUINO is not set # CONFIG_PKG_USING_GUIENGINE is not set -# CONFIG_PKG_USING_PERSIMMON is not set # CONFIG_PKG_USING_CAIRO is not set # CONFIG_PKG_USING_PIXMAN is not set # CONFIG_PKG_USING_PARTITION is not set @@ -532,11 +499,10 @@ CONFIG_RT_LIBC_DEFAULT_TIMEZONE=8 # CONFIG_PKG_USING_TLSF is not set # CONFIG_PKG_USING_EVENT_RECORDER is not set # CONFIG_PKG_USING_ARM_2D is not set -# CONFIG_PKG_USING_WCWIDTH is not set # CONFIG_PKG_USING_MCUBOOT is not set # CONFIG_PKG_USING_TINYUSB is not set # CONFIG_PKG_USING_USB_STACK is not set -# end of system packages +# CONFIG_PKG_USING_LUATOS_SOC is not set # # peripheral libraries and drivers @@ -613,7 +579,6 @@ CONFIG_RT_LIBC_DEFAULT_TIMEZONE=8 # CONFIG_PKG_USING_BL_MCU_SDK is not set # CONFIG_PKG_USING_SOFT_SERIAL is not set # CONFIG_PKG_USING_MB85RS16 is not set -# end of peripheral libraries and drivers # # AI packages @@ -627,7 +592,6 @@ CONFIG_RT_LIBC_DEFAULT_TIMEZONE=8 # CONFIG_PKG_USING_ULAPACK is not set # CONFIG_PKG_USING_QUEST is not set # CONFIG_PKG_USING_NAXOS is not set -# end of AI packages # # miscellaneous packages @@ -640,7 +604,6 @@ CONFIG_RT_LIBC_DEFAULT_TIMEZONE=8 # CONFIG_PKG_USING_FILESYSTEM_SAMPLES is not set # CONFIG_PKG_USING_NETWORK_SAMPLES is not set # CONFIG_PKG_USING_PERIPHERAL_SAMPLES is not set -# end of samples: kernel and components samples # # entertainment: terminal games and other interesting software packages @@ -654,8 +617,7 @@ CONFIG_RT_LIBC_DEFAULT_TIMEZONE=8 # CONFIG_PKG_USING_SNAKE is not set # CONFIG_PKG_USING_TETRIS is not set # CONFIG_PKG_USING_DONUT is not set -# end of entertainment: terminal games and other interesting software packages - +# CONFIG_PKG_USING_COWSAY is not set # CONFIG_PKG_USING_LIBCSV is not set # CONFIG_PKG_USING_OPTPARSE is not set # CONFIG_PKG_USING_FASTLZ is not set @@ -677,23 +639,16 @@ CONFIG_RT_LIBC_DEFAULT_TIMEZONE=8 # CONFIG_PKG_USING_VI is not set # CONFIG_PKG_USING_KI is not set # CONFIG_PKG_USING_ARMv7M_DWT is not set -# CONFIG_PKG_USING_VT100 is not set # CONFIG_PKG_USING_UKAL is not set # CONFIG_PKG_USING_CRCLIB is not set # CONFIG_PKG_USING_LWGPS is not set # CONFIG_PKG_USING_STATE_MACHINE is not set -# CONFIG_PKG_USING_MCURSES is not set -# CONFIG_PKG_USING_COWSAY is not set -# CONFIG_PKG_USING_TERMBOX is not set -# end of miscellaneous packages -# end of RT-Thread online packages - -CONFIG_SOC_FAMILY_GD32=y -CONFIG_SOC_SERIES_GD32F4=y +# CONFIG_PKG_USING_DESIGN_PATTERN is not set # # Hardware Drivers Config # +CONFIG_SOC_SERIES_GD32F4xx=y CONFIG_SOC_GD32407V=y # @@ -708,10 +663,10 @@ CONFIG_BSP_USING_UART=y CONFIG_BSP_USING_UART1=y # CONFIG_BSP_UART1_RX_USING_DMA is not set # CONFIG_BSP_USING_SPI is not set -# CONFIG_BSP_USING_I2C1 is not set -# end of On-chip Peripheral Drivers +CONFIG_BSP_USING_I2C1=y +CONFIG_BSP_I2C1_SCL_PIN=24 +CONFIG_BSP_I2C1_SDA_PIN=25 # # Board extended module Drivers # -# end of Hardware Drivers Config diff --git a/bsp/gd32/gd32407v-start/README.md b/bsp/gd32/gd32407v-start/README.md index 81cefde079..0d02eeaddc 100644 --- a/bsp/gd32/gd32407v-start/README.md +++ b/bsp/gd32/gd32407v-start/README.md @@ -4,7 +4,6 @@ GD32407V-START是-兆易创新推出的一款GD32F4XX系列的评估板,最高主频高达168M,该开发板具有丰富的板载资源,可以充分发挥 GD32407V 的芯片性能。 - 开发板外观如下图所示: ![board](figures/board.jpg) @@ -14,32 +13,43 @@ GD32407V-START是-兆易创新推出的一款GD32F4XX系列的评估板,最高 - GD32407V,主频 168MHz,3072KB FLASH ,192KB RAM - 常用外设 - - - LED :3个,LED1 (电源指示灯),LED2(PC6) + + - LED :2个,LED1 (电源指示灯),LED2(PC6) - 按键:2个,K1(复位引脚),K2(用户按键,PA0) - 常用接口:USB 接口 - 调试接口:GD-LINK - +## 外设支持 + +本 BSP 目前对外设的支持情况如下: + +| **片上外设** | **支持情况** | **备注** | +|:--------- |:--------:|:------------------------------------- | +| GPIO | 支持 | PA0, PA1... PK15 ---> PIN: 0, 1...144 | +| UART | 支持 | UART0 - UART7 | +| I2C | 支持 | I2C1 | +| SPI | 支持 | SPI0. SPI1, SPI2 | +| SPI FLASH | 支持 | | +| **扩展模块** | **支持情况** | **备注** | +| 暂无 | 暂不支持 | 暂不支持 | ## 使用说明 使用说明分为如下两个章节: - 快速上手 - + 本章节是为刚接触 RT-Thread 的新手准备的使用说明,遵循简单的步骤即可将 RT-Thread 操作系统运行在该开发板上,看到实验效果 。 - 进阶使用 - + 本章节是为需要在 RT-Thread 操作系统上使用更多开发板资源的开发者准备的。通过使用 ENV 工具对 BSP 进行配置,可以开启更多板载资源,实现更多高级功能。 - ### 快速上手 -本 BSP 为开发者提供 MDK5 工程,并且支持 GCC 开发环境。下面以 MDK5 开发环境为例,介绍如何将系统运行起来。 +本 BSP 为开发者提供 MDK5 工程,并且支持 GCC 开发环境,也可使用RT-Thread Studio开发。下面以 MDK5 开发环境为例,介绍如何将系统运行起来。 #### 硬件连接 @@ -75,7 +85,7 @@ msh > 3. 输入`pkgs --update`命令更新软件包。 -4. 输入`scons --target=mdk4/mdk5/iar` 命令重新生成工程。 +4. 输入`scons --target=mdk4/mdk5` 命令重新生成工程。 ## 注意事项 @@ -85,4 +95,4 @@ msh > 维护人: -- [BruceOu](https://github.com/Ouxiaolong/), 邮箱: \ No newline at end of file +- [BruceOu](https://github.com/Ouxiaolong/), 邮箱: \ No newline at end of file diff --git a/bsp/gd32/gd32407v-start/SConstruct b/bsp/gd32/gd32407v-start/SConstruct index 48b90b094c..71deeebad1 100644 --- a/bsp/gd32/gd32407v-start/SConstruct +++ b/bsp/gd32/gd32407v-start/SConstruct @@ -20,14 +20,14 @@ TARGET = 'rtthread.' + rtconfig.TARGET_EXT DefaultEnvironment(tools=[]) env = Environment(tools = ['mingw'], AS = rtconfig.AS, ASFLAGS = rtconfig.AFLAGS, - CC = rtconfig.CC, CFLAGS = rtconfig.CFLAGS, + CC = rtconfig.CC, CCFLAGS = rtconfig.CFLAGS, AR = rtconfig.AR, ARFLAGS = '-rc', CXX = rtconfig.CXX, CXXFLAGS = rtconfig.CXXFLAGS, LINK = rtconfig.LINK, LINKFLAGS = rtconfig.LFLAGS) env.PrependENVPath('PATH', rtconfig.EXEC_PATH) if rtconfig.PLATFORM == 'iar': - env.Replace(CCCOM = ['$CC $CFLAGS $CPPFLAGS $_CPPDEFFLAGS $_CPPINCFLAGS -o $TARGET $SOURCES']) + env.Replace(CCCOM = ['$CC $CCFLAGS $CPPFLAGS $_CPPDEFFLAGS $_CPPINCFLAGS -o $TARGET $SOURCES']) env.Replace(ARFLAGS = ['']) env.Replace(LINKCOM = env["LINKCOM"] + ' --map rtthread.map') @@ -47,14 +47,14 @@ Export('SDK_LIB') # prepare building environment objs = PrepareBuilding(env, RTT_ROOT, has_libcpu=False) -gd32_library = 'GD32F4xx_HAL' +gd32_library = 'GD32F4xx_Firmware_Library' rtconfig.BSP_LIBRARY_TYPE = gd32_library # include libraries objs.extend(SConscript(os.path.join(libraries_path_prefix, gd32_library, 'SConscript'))) # include drivers -objs.extend(SConscript(os.path.join(libraries_path_prefix, 'HAL_Drivers', 'SConscript'))) +objs.extend(SConscript(os.path.join(libraries_path_prefix, 'gd32_drivers', 'SConscript'))) # make a building DoBuilding(TARGET, objs) diff --git a/bsp/gd32/gd32407v-start/applications/main.c b/bsp/gd32/gd32407v-start/applications/main.c index 4a528128b4..fc35bb08e1 100644 --- a/bsp/gd32/gd32407v-start/applications/main.c +++ b/bsp/gd32/gd32407v-start/applications/main.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006-2021, RT-Thread Development Team + * Copyright (c) 2006-2022, RT-Thread Development Team * * SPDX-License-Identifier: Apache-2.0 * diff --git a/bsp/gd32/gd32407v-start/board/Kconfig b/bsp/gd32/gd32407v-start/board/Kconfig index 190489eaa9..29331248c6 100644 --- a/bsp/gd32/gd32407v-start/board/Kconfig +++ b/bsp/gd32/gd32407v-start/board/Kconfig @@ -1,8 +1,12 @@ menu "Hardware Drivers Config" +config SOC_SERIES_GD32F4xx + bool + default y + config SOC_GD32407V bool - select SOC_SERIES_GD32F4 + select SOC_SERIES_GD32F4xx select RT_USING_COMPONENTS_INIT select RT_USING_USER_MAIN default y @@ -70,7 +74,7 @@ menu "On-chip Peripheral Drivers" range 1 216 default 25 endif - source "../libraries/HAL_Drivers/Kconfig" + source "../libraries/gd32_drivers/Kconfig" endmenu diff --git a/bsp/gd32/gd32407v-start/board/SConscript b/bsp/gd32/gd32407v-start/board/SConscript index 95b376bd92..171600e2e1 100644 --- a/bsp/gd32/gd32407v-start/board/SConscript +++ b/bsp/gd32/gd32407v-start/board/SConscript @@ -16,13 +16,13 @@ path = [cwd] startup_path_prefix = SDK_LIB if rtconfig.CROSS_TOOL == 'gcc': - src += [startup_path_prefix + '/GD32F4xx_HAL/CMSIS/GD/GD32F4xx/Source/GCC/startup_gd32f4xx.S'] + src += [startup_path_prefix + '/GD32F4xx_Firmware_Library/CMSIS/GD/GD32F4xx/Source/GCC/startup_gd32f4xx.s'] elif rtconfig.CROSS_TOOL == 'keil': - src += [startup_path_prefix + '/GD32F4xx_HAL/CMSIS/GD/GD32F4xx/Source/ARM/startup_gd32f4xx.s'] + src += [startup_path_prefix + '/GD32F4xx_Firmware_Library/CMSIS/GD/GD32F4xx/Source/ARM/startup_gd32f4xx.s'] elif rtconfig.CROSS_TOOL == 'iar': - src += [startup_path_prefix + '/GD32F4xx_HAL/CMSIS/GD/GD32F4xx/Source/IAR/startup_gd32f4xx.s'] + src += [startup_path_prefix + '/GD32F4xx_Firmware_Library/CMSIS/GD/GD32F4xx/Source/IAR/startup_gd32f4xx.s'] -CPPDEFINES = ['GD32F407xx'] +CPPDEFINES = ['GD32F407'] group = DefineGroup('Drivers', src, depend = [''], CPPPATH = path, CPPDEFINES = CPPDEFINES) Return('group') diff --git a/bsp/gd32/gd32407v-start/board/board.c b/bsp/gd32/gd32407v-start/board/board.c index 0e9f89865a..8331a86841 100644 --- a/bsp/gd32/gd32407v-start/board/board.c +++ b/bsp/gd32/gd32407v-start/board/board.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006-2021, RT-Thread Development Team + * Copyright (c) 2006-2022, RT-Thread Development Team * * SPDX-License-Identifier: Apache-2.0 * diff --git a/bsp/gd32/gd32407v-start/board/board.h b/bsp/gd32/gd32407v-start/board/board.h index b13b5439f6..237a77cc5b 100644 --- a/bsp/gd32/gd32407v-start/board/board.h +++ b/bsp/gd32/gd32407v-start/board/board.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006-2021, RT-Thread Development Team + * Copyright (c) 2006-2022, RT-Thread Development Team * * SPDX-License-Identifier: Apache-2.0 * diff --git a/bsp/gd32/gd32407v-start/project.uvoptx b/bsp/gd32/gd32407v-start/project.uvoptx index 664bc65176..d7d2ffa02e 100644 --- a/bsp/gd32/gd32407v-start/project.uvoptx +++ b/bsp/gd32/gd32407v-start/project.uvoptx @@ -22,7 +22,7 @@ - rt-thread_gd32f4xx + rt-thread 0x4 ARM-ADS @@ -117,20 +117,10 @@ BIN\CMSIS_AGDI.dll - - 0 - CMSIS_AGDI - -X"CMSIS-DAP" -O206 -S0 -C0 -P00000000 -N00("ARM CoreSight SW-DP") -D00(2BA01477) -L00(0) -TO65554 -TC10000000 -TT10000000 -TP20 -TDS8007 -TDT0 -TDC1F -TIEFFFFFFFF -TIP8 -FO7 -FD20000000 -FC1000 -FN1 -FF0GD32F4xx_3MB.FLM -FS08000000 -FL0300000 -FP0($$Device:GD32F407VK$Flash\GD32F4xx_3MB.FLM) - - - 0 - JL2CM3 - -U59401765 -O78 -S2 -ZTIFSpeedSel5000 -A0 -C0 -JU1 -JI127.0.0.1 -JP0 -RST0 -N00("ARM CoreSight SW-DP") -D00(2BA01477) -L00(4) -TO18 -TC10000000 -TP21 -TDS8007 -TDT0 -TDC1F -TIEFFFFFFFF -TIP8 -TB1 -TFE0 -FO15 -FD20000000 -FC1000 -FN1 -FF0GD32F4xx_3MB.FLM -FS08000000 -FL0300000 -FP0($$Device:GD32F407VK$Flash\GD32F4xx_3MB.FLM) - 0 UL2CM3 - UL2CM3(-S0 -C0 -P0 -FD20000000 -FC1000 -FN1 -FF0GD32F4xx_3MB -FS08000000 -FL0300000 -FP0($$Device:GD32F407VK$Flash\GD32F4xx_3MB.FLM)) + UL2CM3(-S0 -C0 -P0 ) -FN1 -FC1000 -FD20000000 -FF0GD32F4xx_3MB -FL0300000 -FS08000000 -FP0($$Device:GD32F407VK$Flash\GD32F4xx_3MB.FLM) @@ -179,6 +169,646 @@ + + Applications + 0 + 0 + 0 + 0 + + 1 + 1 + 1 + 0 + 0 + 0 + applications\main.c + main.c + 0 + 0 + + + + + CPU + 0 + 0 + 0 + 0 + + 2 + 2 + 1 + 0 + 0 + 0 + ..\..\..\libcpu\arm\common\backtrace.c + backtrace.c + 0 + 0 + + + 2 + 3 + 1 + 0 + 0 + 0 + ..\..\..\libcpu\arm\common\showmem.c + showmem.c + 0 + 0 + + + 2 + 4 + 1 + 0 + 0 + 0 + ..\..\..\libcpu\arm\common\div0.c + div0.c + 0 + 0 + + + 2 + 5 + 1 + 0 + 0 + 0 + ..\..\..\libcpu\arm\cortex-m4\cpuport.c + cpuport.c + 0 + 0 + + + 2 + 6 + 2 + 0 + 0 + 0 + ..\..\..\libcpu\arm\cortex-m4\context_rvds.S + context_rvds.S + 0 + 0 + + + + + DeviceDrivers + 0 + 0 + 0 + 0 + + 3 + 7 + 1 + 0 + 0 + 0 + ..\..\..\components\drivers\i2c\i2c_core.c + i2c_core.c + 0 + 0 + + + 3 + 8 + 1 + 0 + 0 + 0 + ..\..\..\components\drivers\i2c\i2c_dev.c + i2c_dev.c + 0 + 0 + + + 3 + 9 + 1 + 0 + 0 + 0 + ..\..\..\components\drivers\i2c\i2c-bit-ops.c + i2c-bit-ops.c + 0 + 0 + + + 3 + 10 + 1 + 0 + 0 + 0 + ..\..\..\components\drivers\misc\pin.c + pin.c + 0 + 0 + + + 3 + 11 + 1 + 0 + 0 + 0 + ..\..\..\components\drivers\serial\serial.c + serial.c + 0 + 0 + + + 3 + 12 + 1 + 0 + 0 + 0 + ..\..\..\components\drivers\src\workqueue.c + workqueue.c + 0 + 0 + + + 3 + 13 + 1 + 0 + 0 + 0 + ..\..\..\components\drivers\src\completion.c + completion.c + 0 + 0 + + + 3 + 14 + 1 + 0 + 0 + 0 + ..\..\..\components\drivers\src\pipe.c + pipe.c + 0 + 0 + + + 3 + 15 + 1 + 0 + 0 + 0 + ..\..\..\components\drivers\src\dataqueue.c + dataqueue.c + 0 + 0 + + + 3 + 16 + 1 + 0 + 0 + 0 + ..\..\..\components\drivers\src\waitqueue.c + waitqueue.c + 0 + 0 + + + 3 + 17 + 1 + 0 + 0 + 0 + ..\..\..\components\drivers\src\ringbuffer.c + ringbuffer.c + 0 + 0 + + + 3 + 18 + 1 + 0 + 0 + 0 + ..\..\..\components\drivers\src\ringblk_buf.c + ringblk_buf.c + 0 + 0 + + + + + Drivers + 0 + 0 + 0 + 0 + + 4 + 19 + 2 + 0 + 0 + 0 + ..\libraries\GD32F4xx_Firmware_Library\CMSIS\GD\GD32F4xx\Source\ARM\startup_gd32f4xx.s + startup_gd32f4xx.s + 0 + 0 + + + 4 + 20 + 1 + 0 + 0 + 0 + board\board.c + board.c + 0 + 0 + + + 4 + 21 + 1 + 0 + 0 + 0 + ..\libraries\gd32_drivers\drv_gpio.c + drv_gpio.c + 0 + 0 + + + 4 + 22 + 1 + 0 + 0 + 0 + ..\libraries\gd32_drivers\drv_usart.c + drv_usart.c + 0 + 0 + + + 4 + 23 + 1 + 0 + 0 + 0 + ..\libraries\gd32_drivers\drv_soft_i2c.c + drv_soft_i2c.c + 0 + 0 + + + + + Finsh + 0 + 0 + 0 + 0 + + 5 + 24 + 1 + 0 + 0 + 0 + ..\..\..\components\finsh\shell.c + shell.c + 0 + 0 + + + 5 + 25 + 1 + 0 + 0 + 0 + ..\..\..\components\finsh\msh.c + msh.c + 0 + 0 + + + 5 + 26 + 1 + 0 + 0 + 0 + ..\..\..\components\finsh\cmd.c + cmd.c + 0 + 0 + + + + + Kernel + 0 + 0 + 0 + 0 + + 6 + 27 + 1 + 0 + 0 + 0 + ..\..\..\src\components.c + components.c + 0 + 0 + + + 6 + 28 + 1 + 0 + 0 + 0 + ..\..\..\src\thread.c + thread.c + 0 + 0 + + + 6 + 29 + 1 + 0 + 0 + 0 + ..\..\..\src\irq.c + irq.c + 0 + 0 + + + 6 + 30 + 1 + 0 + 0 + 0 + ..\..\..\src\device.c + device.c + 0 + 0 + + + 6 + 31 + 1 + 0 + 0 + 0 + ..\..\..\src\timer.c + timer.c + 0 + 0 + + + 6 + 32 + 1 + 0 + 0 + 0 + ..\..\..\src\mem.c + mem.c + 0 + 0 + + + 6 + 33 + 1 + 0 + 0 + 0 + ..\..\..\src\kservice.c + kservice.c + 0 + 0 + + + 6 + 34 + 1 + 0 + 0 + 0 + ..\..\..\src\object.c + object.c + 0 + 0 + + + 6 + 35 + 1 + 0 + 0 + 0 + ..\..\..\src\clock.c + clock.c + 0 + 0 + + + 6 + 36 + 1 + 0 + 0 + 0 + ..\..\..\src\idle.c + idle.c + 0 + 0 + + + 6 + 37 + 1 + 0 + 0 + 0 + ..\..\..\src\ipc.c + ipc.c + 0 + 0 + + + 6 + 38 + 1 + 0 + 0 + 0 + ..\..\..\src\mempool.c + mempool.c + 0 + 0 + + + 6 + 39 + 1 + 0 + 0 + 0 + ..\..\..\src\scheduler.c + scheduler.c + 0 + 0 + + + + + libc + 0 + 0 + 0 + 0 + + 7 + 40 + 1 + 0 + 0 + 0 + ..\..\..\components\libc\compilers\common\time.c + time.c + 0 + 0 + + + + + Libraries + 0 + 0 + 0 + 0 + + 8 + 41 + 1 + 0 + 0 + 0 + ..\libraries\GD32F4xx_Firmware_Library\GD32F4xx_standard_peripheral\Source\gd32f4xx_i2c.c + gd32f4xx_i2c.c + 0 + 0 + + + 8 + 42 + 1 + 0 + 0 + 0 + ..\libraries\GD32F4xx_Firmware_Library\GD32F4xx_standard_peripheral\Source\gd32f4xx_syscfg.c + gd32f4xx_syscfg.c + 0 + 0 + + + 8 + 43 + 1 + 0 + 0 + 0 + ..\libraries\GD32F4xx_Firmware_Library\GD32F4xx_standard_peripheral\Source\gd32f4xx_exti.c + gd32f4xx_exti.c + 0 + 0 + + + 8 + 44 + 1 + 0 + 0 + 0 + ..\libraries\GD32F4xx_Firmware_Library\GD32F4xx_standard_peripheral\Source\gd32f4xx_gpio.c + gd32f4xx_gpio.c + 0 + 0 + + + 8 + 45 + 1 + 0 + 0 + 0 + ..\libraries\GD32F4xx_Firmware_Library\GD32F4xx_standard_peripheral\Source\gd32f4xx_rcu.c + gd32f4xx_rcu.c + 0 + 0 + + + 8 + 46 + 1 + 0 + 0 + 0 + ..\libraries\GD32F4xx_Firmware_Library\GD32F4xx_standard_peripheral\Source\gd32f4xx_misc.c + gd32f4xx_misc.c + 0 + 0 + + + 8 + 47 + 1 + 0 + 0 + 0 + ..\libraries\GD32F4xx_Firmware_Library\GD32F4xx_standard_peripheral\Source\gd32f4xx_usart.c + gd32f4xx_usart.c + 0 + 0 + + + 8 + 48 + 1 + 0 + 0 + 0 + ..\libraries\GD32F4xx_Firmware_Library\CMSIS\GD\GD32F4xx\Source\system_gd32f4xx.c + system_gd32f4xx.c + 0 + 0 + + + ::CMSIS 0 diff --git a/bsp/gd32/gd32407v-start/project.uvproj b/bsp/gd32/gd32407v-start/project.uvproj index e61bd5e518..876d693c33 100644 --- a/bsp/gd32/gd32407v-start/project.uvproj +++ b/bsp/gd32/gd32407v-start/project.uvproj @@ -4,7 +4,7 @@
### uVision Project, (C) Keil Software
- rt-thread_gd32f4xx + rt-thread 0x4 ARM-ADS 0 @@ -12,12 +12,12 @@ GD32F407VK GigaDevice - IRAM(0x20000000-0x2002FFFF) IRAM2(0x10000000-0x1000FFFF) IROM(0x08000000-0x082FFFFF) CLOCK(16000000) CPUTYPE("Cortex-M4") FPU2 + IRAM(0x20000000,0x020000) IRAM2(0x10000000,0x010000) IROM(0x08000000,0x300000) CPUTYPE("Cortex-M4") FPU2 CLOCK(16800000) "Startup\GD\GD32F4xx\startup_gd32f4xx.s" ("GD32F4xx Startup Code") - UL2CM3(-O207 -S0 -C0 -FO7 -FD20000000 -FC800 -FN1 -FF0GD32F4xx_3MB -FS08000000 -FL0300000) + UL2CM3(-S0 -C0 -P0 -FD20000000 -FC1000 -FN1 -FF0GD32F4xx_3MB -FS08000000 -FL0300000 -FP0($$Device:GD32F407VK$Flash\GD32F4xx_3MB.FLM)) 0 - gd32f4xx0.h + gd32f4xx.h @@ -43,7 +43,7 @@ 1 .\output\ - rtthread-gd32f4xx + rtthread 1 0 1 @@ -370,9 +370,9 @@ 0 - GD32F407xx, USE_STDPERIPH_DRIVER, __RTTHREAD__, __CLK_TCK=RT_TICK_PER_SECOND + GD32F30X_CL, USE_STDPERIPH_DRIVER, __RTTHREAD__, __CLK_TCK=RT_TICK_PER_SECOND - applications;.;..\..\..\libcpu\arm\common;..\..\..\libcpu\arm\cortex-m4;..\..\..\components\drivers\include;..\..\..\components\drivers\include;..\..\..\components\drivers\include;board;..\libraries\HAL_Drivers;..\..\..\components\finsh;.;..\..\..\include;..\..\..\components\libc\compilers\common;..\..\..\components\libc\compilers\common\nogcc;..\libraries\GD32F4xx_HAL\CMSIS\GD\GD32F4xx\Include;..\libraries\GD32F4xx_HAL\CMSIS;..\libraries\GD32F4xx_HAL\GD32F4xx_standard_peripheral\Include;..\..\..\components\libc\posix\io\poll;..\..\..\components\libc\posix\ipc;..\..\..\examples\utest\testcases\kernel + applications;.;..\..\..\libcpu\arm\common;..\..\..\libcpu\arm\cortex-m4;..\..\..\components\drivers\include;..\..\..\components\drivers\include;..\..\..\components\drivers\include;board;..\libraries\gd32_drivers;..\..\..\components\finsh;.;..\..\..\include;..\..\..\components\libc\compilers\common;..\..\..\components\libc\compilers\common\nogcc;..\libraries\GD32F30x_Firmware_Library\CMSIS\GD\GD32F30x\Include;..\libraries\GD32F30x_Firmware_Library\CMSIS;..\libraries\GD32F30x_Firmware_Library\GD32F30x_standard_peripheral\Include;..\..\..\components\libc\posix\io\poll;..\..\..\components\libc\posix\ipc;..\..\..\examples\utest\testcases\kernel @@ -432,13 +432,6 @@ ..\..\..\libcpu\arm\common\backtrace.c - - - div0.c - 1 - ..\..\..\libcpu\arm\common\div0.c - - showmem.c @@ -448,9 +441,9 @@ - context_rvds.S - 2 - ..\..\..\libcpu\arm\cortex-m4\context_rvds.S + div0.c + 1 + ..\..\..\libcpu\arm\common\div0.c @@ -460,6 +453,13 @@ ..\..\..\libcpu\arm\cortex-m4\cpuport.c + + + context_rvds.S + 2 + ..\..\..\libcpu\arm\cortex-m4\context_rvds.S + +
DeviceDrivers @@ -479,16 +479,16 @@ - ringblk_buf.c + workqueue.c 1 - ..\..\..\components\drivers\src\ringblk_buf.c + ..\..\..\components\drivers\src\workqueue.c - ringbuffer.c + ringblk_buf.c 1 - ..\..\..\components\drivers\src\ringbuffer.c + ..\..\..\components\drivers\src\ringblk_buf.c @@ -500,16 +500,16 @@ - dataqueue.c + ringbuffer.c 1 - ..\..\..\components\drivers\src\dataqueue.c + ..\..\..\components\drivers\src\ringbuffer.c - pipe.c + dataqueue.c 1 - ..\..\..\components\drivers\src\pipe.c + ..\..\..\components\drivers\src\dataqueue.c @@ -521,9 +521,9 @@ - workqueue.c + pipe.c 1 - ..\..\..\components\drivers\src\workqueue.c + ..\..\..\components\drivers\src\pipe.c @@ -531,9 +531,9 @@ Drivers - startup_gd32f4xx.s + startup_gd32f30x_cl.s 2 - ..\libraries\GD32F4xx_HAL\CMSIS\GD\GD32F4xx\Source\ARM\startup_gd32f4xx.s + ..\libraries\GD32F30x_Firmware_Library\CMSIS\GD\GD32F30x\Source\ARM\startup_gd32f30x_cl.s @@ -547,14 +547,14 @@ drv_gpio.c 1 - ..\libraries\HAL_Drivers\drv_gpio.c + ..\libraries\gd32_drivers\drv_gpio.c drv_usart.c 1 - ..\libraries\HAL_Drivers\drv_usart.c + ..\libraries\gd32_drivers\drv_usart.c @@ -584,6 +584,27 @@ Kernel + + + device.c + 1 + ..\..\..\src\device.c + + + + + scheduler.c + 1 + ..\..\..\src\scheduler.c + + + + + idle.c + 1 + ..\..\..\src\idle.c + + components.c @@ -593,9 +614,16 @@ - irq.c + mempool.c 1 - ..\..\..\src\irq.c + ..\..\..\src\mempool.c + + + + + timer.c + 1 + ..\..\..\src\timer.c @@ -605,20 +633,6 @@ ..\..\..\src\thread.c - - - ipc.c - 1 - ..\..\..\src\ipc.c - - - - - device.c - 1 - ..\..\..\src\device.c - - object.c @@ -635,9 +649,16 @@ - timer.c + kservice.c 1 - ..\..\..\src\timer.c + ..\..\..\src\kservice.c + + + + + ipc.c + 1 + ..\..\..\src\ipc.c @@ -649,30 +670,9 @@ - scheduler.c + irq.c 1 - ..\..\..\src\scheduler.c - - - - - mempool.c - 1 - ..\..\..\src\mempool.c - - - - - kservice.c - 1 - ..\..\..\src\kservice.c - - - - - idle.c - 1 - ..\..\..\src\idle.c + ..\..\..\src\irq.c @@ -690,51 +690,44 @@ Libraries - gd32f4xx_syscfg.c + system_gd32f30x.c 1 - ..\libraries\GD32F4xx_HAL\GD32F4xx_standard_peripheral\Source\gd32f4xx_syscfg.c + ..\libraries\GD32F30x_Firmware_Library\CMSIS\GD\GD32F30x\Source\system_gd32f30x.c - gd32f4xx_exti.c + gd32f30x_rcu.c 1 - ..\libraries\GD32F4xx_HAL\GD32F4xx_standard_peripheral\Source\gd32f4xx_exti.c + ..\libraries\GD32F30x_Firmware_Library\GD32F30x_standard_peripheral\Source\gd32f30x_rcu.c - gd32f4xx_gpio.c + gd32f30x_usart.c 1 - ..\libraries\GD32F4xx_HAL\GD32F4xx_standard_peripheral\Source\gd32f4xx_gpio.c + ..\libraries\GD32F30x_Firmware_Library\GD32F30x_standard_peripheral\Source\gd32f30x_usart.c - gd32f4xx_rcu.c + gd32f30x_exti.c 1 - ..\libraries\GD32F4xx_HAL\GD32F4xx_standard_peripheral\Source\gd32f4xx_rcu.c + ..\libraries\GD32F30x_Firmware_Library\GD32F30x_standard_peripheral\Source\gd32f30x_exti.c - gd32f4xx_misc.c + gd32f30x_gpio.c 1 - ..\libraries\GD32F4xx_HAL\GD32F4xx_standard_peripheral\Source\gd32f4xx_misc.c + ..\libraries\GD32F30x_Firmware_Library\GD32F30x_standard_peripheral\Source\gd32f30x_gpio.c - gd32f4xx_usart.c + gd32f30x_misc.c 1 - ..\libraries\GD32F4xx_HAL\GD32F4xx_standard_peripheral\Source\gd32f4xx_usart.c - - - - - system_gd32f4xx.c - 1 - ..\libraries\GD32F4xx_HAL\CMSIS\GD\GD32F4xx\Source\system_gd32f4xx.c + ..\libraries\GD32F30x_Firmware_Library\GD32F30x_standard_peripheral\Source\gd32f30x_misc.c diff --git a/bsp/gd32/gd32407v-start/project.uvprojx b/bsp/gd32/gd32407v-start/project.uvprojx index a41ce298ba..74a561886d 100644 --- a/bsp/gd32/gd32407v-start/project.uvprojx +++ b/bsp/gd32/gd32407v-start/project.uvprojx @@ -1,12 +1,16 @@ + 2.1 +
### uVision Project, (C) Keil Software
+ - rt-thread_gd32f4xx + rt-thread 0x4 ARM-ADS + 5060750::V5.06 update 6 (build 750)::.\ARMCC 0 @@ -14,29 +18,29 @@ GigaDevice GigaDevice.GD32F4xx_DFP.2.1.0 http://gd32mcu.com/data/documents/pack/ - IRAM(0x20000000,0x030000) IRAM2(0x10000000,0x010000) IROM(0x08000000,0x0300000) CPUTYPE("Cortex-M4") FPU2 CLOCK(12000000) ELITTLE - - + IRAM(0x20000000,0x020000) IRAM2(0x10000000,0x010000) IROM(0x08000000,0x300000) CPUTYPE("Cortex-M4") FPU2 CLOCK(16800000) ELITTLE + + UL2CM3(-S0 -C0 -P0 -FD20000000 -FC1000 -FN1 -FF0GD32F4xx_3MB -FS08000000 -FL0300000 -FP0($$Device:GD32F407VK$Flash\GD32F4xx_3MB.FLM)) 0 - $$Device:GD32F407VK$Device\Include\gd32f4xx.h - - - - - - - - - + $$Device:GD32F407VK$Device\F4XX\Include\gd32f4xx.h + + + + + + + + + $$Device:GD32F407VK$SVD\GD32F4xx.svd 0 0 - - - - - + + + + + 0 0 @@ -45,7 +49,7 @@ 1 .\build\ - rtthread-gd32f4xx + rtthread 1 0 0 @@ -58,8 +62,8 @@ 0 0 - - + + 0 0 0 @@ -68,8 +72,8 @@ 0 0 - - + + 0 0 0 @@ -79,14 +83,14 @@ 1 0 fromelf --bin !L --output rtthread.bin - + 0 0 0 0 0 - + 0 @@ -100,8 +104,8 @@ 0 0 3 - - + + 1 @@ -134,11 +138,11 @@ 1 BIN\UL2CM3.DLL - - - - - + + + + + 0 @@ -171,7 +175,7 @@ 0 0 "Cortex-M4" - + 0 0 0 @@ -242,7 +246,7 @@ 0 0x20000000 - 0x30000 + 0x20000 1 @@ -297,7 +301,7 @@ 0 0x20000000 - 0x30000 + 0x20000 0 @@ -305,11 +309,11 @@ 0x10000 - + 1 - 4 + 3 0 0 0 @@ -332,10 +336,10 @@ 0 0 - - GD32F407xx, USE_STDPERIPH_DRIVER, __RTTHREAD__, __CLK_TCK=RT_TICK_PER_SECOND - - applications;.;..\..\..\libcpu\arm\common;..\..\..\libcpu\arm\cortex-m4;..\..\..\components\drivers\include;..\..\..\components\drivers\include;..\..\..\components\drivers\include;board;..\libraries\HAL_Drivers;..\..\..\components\finsh;.;..\..\..\include;..\..\..\components\libc\compilers\common;..\..\..\components\libc\compilers\common\nogcc;..\libraries\GD32F4xx_HAL\CMSIS\GD\GD32F4xx\Include;..\libraries\GD32F4xx_HAL\CMSIS;..\libraries\GD32F4xx_HAL\GD32F4xx_standard_peripheral\Include;..\..\..\components\libc\posix\io\poll;..\..\..\components\libc\posix\ipc;..\..\..\examples\utest\testcases\kernel + + GD32F407, USE_STDPERIPH_DRIVER, __RTTHREAD__, __CLK_TCK=RT_TICK_PER_SECOND + + applications;.;..\..\..\libcpu\arm\common;..\..\..\libcpu\arm\cortex-m4;..\..\..\components\drivers\include;..\..\..\components\drivers\include;..\..\..\components\drivers\include;..\..\..\components\drivers\include;board;..\libraries\gd32_drivers;..\..\..\components\finsh;.;..\..\..\include;..\..\..\components\libc\compilers\common;..\..\..\components\libc\compilers\common\nogcc;..\libraries\GD32F4xx_Firmware_Library\CMSIS\GD\GD32F4xx\Include;..\libraries\GD32F4xx_Firmware_Library\CMSIS;..\libraries\GD32F4xx_Firmware_Library\GD32F4xx_standard_peripheral\Include;..\..\..\components\libc\posix\io\poll;..\..\..\components\libc\posix\ipc;..\..\..\examples\utest\testcases\kernel @@ -350,10 +354,10 @@ 0 4 - - - - + + + + @@ -365,13 +369,13 @@ 0 0x08000000 0x20000000 - + .\gd32_rom.ld - - - - - + + + + + @@ -389,105 +393,96 @@ CPU + + backtrace.c + 1 + ..\..\..\libcpu\arm\common\backtrace.c + showmem.c 1 ..\..\..\libcpu\arm\common\showmem.c - - div0.c 1 ..\..\..\libcpu\arm\common\div0.c - - - - backtrace.c - 1 - ..\..\..\libcpu\arm\common\backtrace.c - - - - - context_rvds.S - 2 - ..\..\..\libcpu\arm\cortex-m4\context_rvds.S - - - cpuport.c 1 ..\..\..\libcpu\arm\cortex-m4\cpuport.c + + context_rvds.S + 2 + ..\..\..\libcpu\arm\cortex-m4\context_rvds.S + DeviceDrivers + + i2c_core.c + 1 + ..\..\..\components\drivers\i2c\i2c_core.c + + + i2c_dev.c + 1 + ..\..\..\components\drivers\i2c\i2c_dev.c + + + i2c-bit-ops.c + 1 + ..\..\..\components\drivers\i2c\i2c-bit-ops.c + pin.c 1 ..\..\..\components\drivers\misc\pin.c - - serial.c 1 ..\..\..\components\drivers\serial\serial.c - - workqueue.c 1 ..\..\..\components\drivers\src\workqueue.c - - - - ringblk_buf.c - 1 - ..\..\..\components\drivers\src\ringblk_buf.c - - - - - pipe.c - 1 - ..\..\..\components\drivers\src\pipe.c - - - - - ringbuffer.c - 1 - ..\..\..\components\drivers\src\ringbuffer.c - - - - - waitqueue.c - 1 - ..\..\..\components\drivers\src\waitqueue.c - - - completion.c 1 ..\..\..\components\drivers\src\completion.c - - + + pipe.c + 1 + ..\..\..\components\drivers\src\pipe.c + dataqueue.c 1 ..\..\..\components\drivers\src\dataqueue.c + + waitqueue.c + 1 + ..\..\..\components\drivers\src\waitqueue.c + + + ringbuffer.c + 1 + ..\..\..\components\drivers\src\ringbuffer.c + + + ringblk_buf.c + 1 + ..\..\..\components\drivers\src\ringblk_buf.c + @@ -496,28 +491,27 @@ startup_gd32f4xx.s 2 - ..\libraries\GD32F4xx_HAL\CMSIS\GD\GD32F4xx\Source\ARM\startup_gd32f4xx.s + ..\libraries\GD32F4xx_Firmware_Library\CMSIS\GD\GD32F4xx\Source\ARM\startup_gd32f4xx.s - - board.c 1 board\board.c - - drv_gpio.c 1 - ..\libraries\HAL_Drivers\drv_gpio.c + ..\libraries\gd32_drivers\drv_gpio.c - - drv_usart.c 1 - ..\libraries\HAL_Drivers\drv_usart.c + ..\libraries\gd32_drivers\drv_usart.c + + + drv_soft_i2c.c + 1 + ..\libraries\gd32_drivers\drv_soft_i2c.c @@ -529,15 +523,11 @@ 1 ..\..\..\components\finsh\shell.c - - msh.c 1 ..\..\..\components\finsh\msh.c - - cmd.c 1 @@ -549,94 +539,70 @@ Kernel - scheduler.c + components.c 1 - ..\..\..\src\scheduler.c + ..\..\..\src\components.c - - - - mem.c - 1 - ..\..\..\src\mem.c - - - thread.c 1 ..\..\..\src\thread.c - - - - clock.c - 1 - ..\..\..\src\clock.c - - - - - device.c - 1 - ..\..\..\src\device.c - - - - - mempool.c - 1 - ..\..\..\src\mempool.c - - - - - ipc.c - 1 - ..\..\..\src\ipc.c - - - - - timer.c - 1 - ..\..\..\src\timer.c - - - - - idle.c - 1 - ..\..\..\src\idle.c - - - - - kservice.c - 1 - ..\..\..\src\kservice.c - - - irq.c 1 ..\..\..\src\irq.c - - - components.c + device.c 1 - ..\..\..\src\components.c + ..\..\..\src\device.c + + + timer.c + 1 + ..\..\..\src\timer.c + + + mem.c + 1 + ..\..\..\src\mem.c + + + kservice.c + 1 + ..\..\..\src\kservice.c - - object.c 1 ..\..\..\src\object.c + + clock.c + 1 + ..\..\..\src\clock.c + + + idle.c + 1 + ..\..\..\src\idle.c + + + ipc.c + 1 + ..\..\..\src\ipc.c + + + mempool.c + 1 + ..\..\..\src\mempool.c + + + scheduler.c + 1 + ..\..\..\src\scheduler.c + @@ -652,82 +618,81 @@ Libraries + + gd32f4xx_i2c.c + 1 + ..\libraries\GD32F4xx_Firmware_Library\GD32F4xx_standard_peripheral\Source\gd32f4xx_i2c.c + gd32f4xx_syscfg.c 1 - ..\libraries\GD32F4xx_HAL\GD32F4xx_standard_peripheral\Source\gd32f4xx_syscfg.c + ..\libraries\GD32F4xx_Firmware_Library\GD32F4xx_standard_peripheral\Source\gd32f4xx_syscfg.c - - gd32f4xx_exti.c 1 - ..\libraries\GD32F4xx_HAL\GD32F4xx_standard_peripheral\Source\gd32f4xx_exti.c + ..\libraries\GD32F4xx_Firmware_Library\GD32F4xx_standard_peripheral\Source\gd32f4xx_exti.c - - gd32f4xx_gpio.c 1 - ..\libraries\GD32F4xx_HAL\GD32F4xx_standard_peripheral\Source\gd32f4xx_gpio.c + ..\libraries\GD32F4xx_Firmware_Library\GD32F4xx_standard_peripheral\Source\gd32f4xx_gpio.c - - gd32f4xx_rcu.c 1 - ..\libraries\GD32F4xx_HAL\GD32F4xx_standard_peripheral\Source\gd32f4xx_rcu.c + ..\libraries\GD32F4xx_Firmware_Library\GD32F4xx_standard_peripheral\Source\gd32f4xx_rcu.c - - gd32f4xx_misc.c 1 - ..\libraries\GD32F4xx_HAL\GD32F4xx_standard_peripheral\Source\gd32f4xx_misc.c + ..\libraries\GD32F4xx_Firmware_Library\GD32F4xx_standard_peripheral\Source\gd32f4xx_misc.c - - gd32f4xx_usart.c 1 - ..\libraries\GD32F4xx_HAL\GD32F4xx_standard_peripheral\Source\gd32f4xx_usart.c + ..\libraries\GD32F4xx_Firmware_Library\GD32F4xx_standard_peripheral\Source\gd32f4xx_usart.c - - system_gd32f4xx.c 1 - ..\libraries\GD32F4xx_HAL\CMSIS\GD\GD32F4xx\Source\system_gd32f4xx.c + ..\libraries\GD32F4xx_Firmware_Library\CMSIS\GD\GD32F4xx\Source\system_gd32f4xx.c + + ::CMSIS + + - + - - + + - + - + + <Project Info> - - - - - + + + + + 0 1 +
diff --git a/bsp/gd32/gd32407v-start/rtconfig.h b/bsp/gd32/gd32407v-start/rtconfig.h index dbaa1a76a2..529818a7ca 100644 --- a/bsp/gd32/gd32407v-start/rtconfig.h +++ b/bsp/gd32/gd32407v-start/rtconfig.h @@ -1,7 +1,8 @@ #ifndef RT_CONFIG_H__ #define RT_CONFIG_H__ -/* Generated by Kconfiglib (https://github.com/ulfalizer/Kconfiglib) */ +/* Automatically generated file; DO NOT EDIT. */ +/* RT-Thread Configuration */ /* RT-Thread Kernel */ @@ -18,7 +19,6 @@ /* kservice optimization */ -/* end of kservice optimization */ #define RT_DEBUG #define RT_DEBUG_COLOR @@ -29,7 +29,6 @@ #define RT_USING_EVENT #define RT_USING_MAILBOX #define RT_USING_MESSAGEQUEUE -/* end of Inter-Thread communication */ /* Memory Management */ @@ -37,7 +36,6 @@ #define RT_USING_SMALL_MEM #define RT_USING_SMALL_MEM_AS_HEAP #define RT_USING_HEAP -/* end of Memory Management */ /* Kernel Device Object */ @@ -45,13 +43,7 @@ #define RT_USING_CONSOLE #define RT_CONSOLEBUF_SIZE 128 #define RT_CONSOLE_DEVICE_NAME "uart1" -/* end of Kernel Device Object */ #define RT_VER_NUM 0x40100 -/* end of RT-Thread Kernel */ -#define ARCH_ARM -#define RT_USING_CPU_FFS -#define ARCH_ARM_CORTEX_M -#define ARCH_ARM_CORTEX_M4 /* RT-Thread Components */ @@ -62,7 +54,6 @@ /* C++ features */ -/* end of C++ features */ /* Command shell */ @@ -79,11 +70,9 @@ #define MSH_USING_BUILT_IN_COMMANDS #define FINSH_USING_DESCRIPTION #define FINSH_ARG_MAX 10 -/* end of Command shell */ /* Device virtual file system */ -/* end of Device virtual file system */ /* Device Drivers */ @@ -95,12 +84,12 @@ #define RT_USING_SERIAL_V1 #define RT_SERIAL_USING_DMA #define RT_SERIAL_RB_BUFSZ 64 +#define RT_USING_I2C +#define RT_USING_I2C_BITOPS #define RT_USING_PIN /* Using USB */ -/* end of Using USB */ -/* end of Device Drivers */ /* POSIX layer and C standard library */ @@ -115,41 +104,28 @@ /* Socket is in the 'Network' category */ -/* end of Interprocess Communication (IPC) */ -/* end of POSIX (Portable Operating System Interface) layer */ -/* end of POSIX layer and C standard library */ - /* Network */ /* Socket abstraction layer */ -/* end of Socket abstraction layer */ /* Network interface device */ -/* end of Network interface device */ /* light weight TCP/IP stack */ -/* end of light weight TCP/IP stack */ /* AT commands */ -/* end of AT commands */ -/* end of Network */ /* VBUS(Virtual Software BUS) */ -/* end of VBUS(Virtual Software BUS) */ /* Utilities */ -/* end of Utilities */ -/* end of RT-Thread Components */ /* RT-Thread Utestcases */ -/* end of RT-Thread Utestcases */ /* RT-Thread online packages */ @@ -160,88 +136,67 @@ /* Marvell WiFi */ -/* end of Marvell WiFi */ /* Wiced WiFi */ -/* end of Wiced WiFi */ -/* end of Wi-Fi */ /* IoT Cloud */ -/* end of IoT Cloud */ -/* end of IoT - internet of things */ /* security packages */ -/* end of security packages */ /* language packages */ -/* end of language packages */ /* multimedia packages */ /* LVGL: powerful and easy-to-use embedded GUI library */ -/* end of LVGL: powerful and easy-to-use embedded GUI library */ /* u8g2: a monochrome graphic library */ -/* end of u8g2: a monochrome graphic library */ /* PainterEngine: A cross-platform graphics application framework written in C language */ -/* end of PainterEngine: A cross-platform graphics application framework written in C language */ -/* end of multimedia packages */ /* tools packages */ -/* end of tools packages */ /* system packages */ /* enhanced kernel services */ -/* end of enhanced kernel services */ + +/* POSIX extension functions */ + /* acceleration: Assembly language or algorithmic acceleration packages */ -/* end of acceleration: Assembly language or algorithmic acceleration packages */ /* CMSIS: ARM Cortex-M Microcontroller Software Interface Standard */ -/* end of CMSIS: ARM Cortex-M Microcontroller Software Interface Standard */ /* Micrium: Micrium software products porting for RT-Thread */ -/* end of Micrium: Micrium software products porting for RT-Thread */ -/* end of system packages */ /* peripheral libraries and drivers */ -/* end of peripheral libraries and drivers */ /* AI packages */ -/* end of AI packages */ /* miscellaneous packages */ /* samples: kernel and components samples */ -/* end of samples: kernel and components samples */ /* entertainment: terminal games and other interesting software packages */ -/* end of entertainment: terminal games and other interesting software packages */ -/* end of miscellaneous packages */ -/* end of RT-Thread online packages */ -#define SOC_FAMILY_GD32 -#define SOC_SERIES_GD32F4 /* Hardware Drivers Config */ +#define SOC_SERIES_GD32F4xx #define SOC_GD32407V /* Onboard Peripheral Drivers */ @@ -251,10 +206,11 @@ #define BSP_USING_GPIO #define BSP_USING_UART #define BSP_USING_UART1 -/* end of On-chip Peripheral Drivers */ +#define BSP_USING_I2C1 +#define BSP_I2C1_SCL_PIN 24 +#define BSP_I2C1_SDA_PIN 25 /* Board extended module Drivers */ -/* end of Hardware Drivers Config */ #endif diff --git a/bsp/gd32/gd32407v-start/rtconfig.py b/bsp/gd32/gd32407v-start/rtconfig.py index 70651871c5..a91905a233 100644 --- a/bsp/gd32/gd32407v-start/rtconfig.py +++ b/bsp/gd32/gd32407v-start/rtconfig.py @@ -43,7 +43,7 @@ if PLATFORM == 'gcc': OBJDUMP = PREFIX + 'objdump' OBJCPY = PREFIX + 'objcopy' - DEVICE = ' -mcpu=cortex-m4 -mthumb -mfpu=fpv4-sp-d16 -mfloat-abi=hard -ffunction-sections -fdata-sections -DGD32F407' + DEVICE = ' -mcpu=cortex-m4 -mthumb -mfpu=fpv4-sp-d16 -mfloat-abi=hard -ffunction-sections -fdata-sections' CFLAGS = DEVICE + ' -Dgcc' AFLAGS = ' -c' + DEVICE + ' -x assembler-with-cpp -Wa,-mimplicit-it=thumb ' LFLAGS = DEVICE + ' -Wl,--gc-sections,-Map=rtthread.map,-cref,-u,Reset_Handler -T board/linker_scripts/link.ld' diff --git a/bsp/gd32/gd32407v-start/template.uvoptx b/bsp/gd32/gd32407v-start/template.uvoptx index 664bc65176..6f7965ced8 100644 --- a/bsp/gd32/gd32407v-start/template.uvoptx +++ b/bsp/gd32/gd32407v-start/template.uvoptx @@ -22,7 +22,7 @@ - rt-thread_gd32f4xx + rt-thread 0x4 ARM-ADS @@ -117,20 +117,10 @@ BIN\CMSIS_AGDI.dll - - 0 - CMSIS_AGDI - -X"CMSIS-DAP" -O206 -S0 -C0 -P00000000 -N00("ARM CoreSight SW-DP") -D00(2BA01477) -L00(0) -TO65554 -TC10000000 -TT10000000 -TP20 -TDS8007 -TDT0 -TDC1F -TIEFFFFFFFF -TIP8 -FO7 -FD20000000 -FC1000 -FN1 -FF0GD32F4xx_3MB.FLM -FS08000000 -FL0300000 -FP0($$Device:GD32F407VK$Flash\GD32F4xx_3MB.FLM) - - - 0 - JL2CM3 - -U59401765 -O78 -S2 -ZTIFSpeedSel5000 -A0 -C0 -JU1 -JI127.0.0.1 -JP0 -RST0 -N00("ARM CoreSight SW-DP") -D00(2BA01477) -L00(4) -TO18 -TC10000000 -TP21 -TDS8007 -TDT0 -TDC1F -TIEFFFFFFFF -TIP8 -TB1 -TFE0 -FO15 -FD20000000 -FC1000 -FN1 -FF0GD32F4xx_3MB.FLM -FS08000000 -FL0300000 -FP0($$Device:GD32F407VK$Flash\GD32F4xx_3MB.FLM) - 0 UL2CM3 - UL2CM3(-S0 -C0 -P0 -FD20000000 -FC1000 -FN1 -FF0GD32F4xx_3MB -FS08000000 -FL0300000 -FP0($$Device:GD32F407VK$Flash\GD32F4xx_3MB.FLM)) + UL2CM3(-S0 -C0 -P0 ) -FN1 -FC1000 -FD20000000 -FF0GD32F4xx_3MB -FL0300000 -FS08000000 -FP0($$Device:GD32F407VK$Flash\GD32F4xx_3MB.FLM) diff --git a/bsp/gd32/gd32407v-start/template.uvproj b/bsp/gd32/gd32407v-start/template.uvproj index 408784da46..69d95a4e29 100644 --- a/bsp/gd32/gd32407v-start/template.uvproj +++ b/bsp/gd32/gd32407v-start/template.uvproj @@ -7,7 +7,7 @@ - rt-thread_gd32f4xx + rt-thread 0x4 ARM-ADS 0 @@ -15,12 +15,12 @@ GD32F407VK GigaDevice - IRAM(0x20000000-0x2002FFFF) IRAM2(0x10000000-0x1000FFFF) IROM(0x08000000-0x082FFFFF) CLOCK(16000000) CPUTYPE("Cortex-M4") FPU2 + IRAM(0x20000000,0x020000) IRAM2(0x10000000,0x010000) IROM(0x08000000,0x300000) CPUTYPE("Cortex-M4") FPU2 CLOCK(16800000) "Startup\GD\GD32F4xx\startup_gd32f4xx.s" ("GD32F4xx Startup Code") - UL2CM3(-O207 -S0 -C0 -FO7 -FD20000000 -FC800 -FN1 -FF0GD32F4xx_3MB -FS08000000 -FL0300000) + UL2CM3(-S0 -C0 -P0 -FD20000000 -FC1000 -FN1 -FF0GD32F4xx_3MB -FS08000000 -FL0300000 -FP0($$Device:GD32F407VK$Flash\GD32F4xx_3MB.FLM)) 0 - gd32f4xx0.h + gd32f4xx.h @@ -46,7 +46,7 @@ 1 .\output\ - rtthread-gd32f4xx + rtthread 1 0 1 @@ -592,12 +592,12 @@ - GD32F4xx_EVAL + GD32F4xx_START - gd32f450z_eval.c + gd32f407r_start.c 1 - ..\..\..\Library\Utilities\gd32f450z_eval.c + ..\..\..\Library\Utilities\gd32f407r_start.c diff --git a/bsp/gd32/gd32407v-start/template.uvprojx b/bsp/gd32/gd32407v-start/template.uvprojx index e06b13d247..dd4e87c945 100644 --- a/bsp/gd32/gd32407v-start/template.uvprojx +++ b/bsp/gd32/gd32407v-start/template.uvprojx @@ -7,9 +7,10 @@ - rt-thread_gd32f4xx + rt-thread 0x4 ARM-ADS + 5060750::V5.06 update 6 (build 750)::.\ARMCC 0 @@ -17,12 +18,12 @@ GigaDevice GigaDevice.GD32F4xx_DFP.2.1.0 http://gd32mcu.com/data/documents/pack/ - IRAM(0x20000000,0x030000) IRAM2(0x10000000,0x010000) IROM(0x08000000,0x0300000) CPUTYPE("Cortex-M4") FPU2 CLOCK(12000000) ELITTLE + IRAM(0x20000000,0x020000) IRAM2(0x10000000,0x010000) IROM(0x08000000,0x300000) CPUTYPE("Cortex-M4") FPU2 CLOCK(16800000) ELITTLE UL2CM3(-S0 -C0 -P0 -FD20000000 -FC1000 -FN1 -FF0GD32F4xx_3MB -FS08000000 -FL0300000 -FP0($$Device:GD32F407VK$Flash\GD32F4xx_3MB.FLM)) 0 - $$Device:GD32F407VK$Device\Include\gd32f4xx.h + $$Device:GD32F407VK$Device\F4XX\Include\gd32f4xx.h @@ -48,7 +49,7 @@ 1 .\build\ - rtthread-gd32f4xx + rtthread 1 0 0 @@ -245,7 +246,7 @@ 0 0x20000000 - 0x30000 + 0x20000 1 @@ -300,7 +301,7 @@ 0 0x20000000 - 0x30000 + 0x20000 0 @@ -312,7 +313,7 @@ 1 - 4 + 3 0 0 0 @@ -389,10 +390,10 @@ - - + + - + diff --git a/bsp/gd32/libraries/GD32F10x_Firmware_Library/CMSIS/GD/GD32F10x/Include/gd32f10x.h b/bsp/gd32/libraries/GD32F10x_Firmware_Library/CMSIS/GD/GD32F10x/Include/gd32f10x.h new file mode 100644 index 0000000000..41bae599cf --- /dev/null +++ b/bsp/gd32/libraries/GD32F10x_Firmware_Library/CMSIS/GD/GD32F10x/Include/gd32f10x.h @@ -0,0 +1,380 @@ +/*! + \file gd32f10x.h + \brief general definitions for GD32F10x + + \version 2014-12-26, V1.0.0, firmware for GD32F10x + \version 2017-06-20, V2.0.0, firmware for GD32F10x + \version 2018-07-31, V2.1.0, firmware for GD32F10x + \version 2020-09-30, V2.2.0, firmware for GD32F10x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef GD32F10X_H +#define GD32F10X_H + +#ifdef cplusplus + extern "C" { +#endif + +/* define GD32F10x */ +#if !defined (GD32F10X_MD) && !defined (GD32F10X_HD) && !defined (GD32F10X_XD) && !defined (GD32F10X_CL) + /* #define GD32F10X_MD */ /*!< GD32F10X_MD: GD32 Medium density devices */ + /* #define GD32F10X_HD */ /*!< GD32F10X_HD: GD32 High density Value Line devices */ + /* #define GD32F10X_XD */ /*!< GD32F10X_XD: GD32 Extra density devices */ + /* #define GD32F10X_CL */ /*!< GD32F10X_CL: GD32 Connectivity line devices */ +#endif /* define GD32F10x */ + +#if !defined (GD32F10X_MD) && !defined (GD32F10X_HD) && !defined (GD32F10X_XD) && !defined (GD32F10X_CL) + #error "Please select the target GD32F10x device in gd32f10x.h file" +#endif /* undefine GD32F10x tip */ + +/* define value of high speed crystal oscillator (HXTAL) in Hz */ +#if !defined HXTAL_VALUE +#ifdef GD32F10X_CL +#define HXTAL_VALUE ((uint32_t)25000000) /*!< value of the external oscillator in Hz */ +#else +#define HXTAL_VALUE ((uint32_t)8000000) /* !< from 4M to 16M *!< value of the external oscillator in Hz*/ +#endif /* HXTAL_VALUE */ +#endif /* high speed crystal oscillator value */ + +/* define startup timeout value of high speed crystal oscillator (HXTAL) */ +#if !defined (HXTAL_STARTUP_TIMEOUT) +#define HXTAL_STARTUP_TIMEOUT ((uint16_t)0xFFFF) +#endif /* high speed crystal oscillator startup timeout */ + +/* define value of internal 8MHz RC oscillator (IRC8M) in Hz */ +#if !defined (IRC8M_VALUE) +#define IRC8M_VALUE ((uint32_t)8000000) +#endif /* internal 8MHz RC oscillator value */ + +/* define startup timeout value of internal 8MHz RC oscillator (IRC8M) */ +#if !defined (IRC8M_STARTUP_TIMEOUT) +#define IRC8M_STARTUP_TIMEOUT ((uint16_t)0x0500) +#endif /* internal 8MHz RC oscillator startup timeout */ + +/* define value of internal 40KHz RC oscillator(IRC40K) in Hz */ +#if !defined (IRC40K_VALUE) +#define IRC40K_VALUE ((uint32_t)40000) +#endif /* internal 40KHz RC oscillator value */ + +/* define value of low speed crystal oscillator (LXTAL)in Hz */ +#if !defined (LXTAL_VALUE) +#define LXTAL_VALUE ((uint32_t)32768) +#endif /* low speed crystal oscillator value */ + +/* GD32F10x firmware library version number V2.0 */ +#define __GD32F10x_STDPERIPH_VERSION_MAIN (0x01) /*!< [31:24] main version */ +#define __GD32F10x_STDPERIPH_VERSION_SUB1 (0x00) /*!< [23:16] sub1 version */ +#define __GD32F10x_STDPERIPH_VERSION_SUB2 (0x00) /*!< [15:8] sub2 version */ +#define __GD32F10x_STDPERIPH_VERSION_RC (0x00) /*!< [7:0] release candidate */ +#define __GD32F10x_STDPERIPH_VERSION ((__GD32F10x_STDPERIPH_VERSION_MAIN << 24)\ + |(__GD32F10x_STDPERIPH_VERSION_SUB1 << 16)\ + |(__GD32F10x_STDPERIPH_VERSION_SUB2 << 8)\ + |(__GD32F10x_STDPERIPH_VERSION_RC)) + +/* configuration of the Cortex-M3 processor and core peripherals */ +#define __MPU_PRESENT 0 /*!< GD32F10x do not provide MPU */ +#define __NVIC_PRIO_BITS 4 /*!< GD32F10x uses 4 bits for the priority levels */ +#define __Vendor_SysTickConfig 0 /*!< set to 1 if different sysTick config is used */ +/* define interrupt number */ +typedef enum IRQn +{ + /* Cortex-M3 processor exceptions numbers */ + NonMaskableInt_IRQn = -14, /*!< 2 non maskable interrupt */ + MemoryManagement_IRQn = -12, /*!< 4 Cortex-M3 memory management interrupt */ + BusFault_IRQn = -11, /*!< 5 Cortex-M3 bus fault interrupt */ + UsageFault_IRQn = -10, /*!< 6 Cortex-M3 usage fault interrupt */ + SVCall_IRQn = -5, /*!< 11 Cortex-M3 SV call interrupt */ + DebugMonitor_IRQn = -4, /*!< 12 Cortex-M3 debug monitor interrupt */ + PendSV_IRQn = -2, /*!< 14 Cortex-M3 pend SV interrupt */ + SysTick_IRQn = -1, /*!< 15 Cortex-M3 system tick interrupt */ + + /* interruput numbers */ + WWDGT_IRQn = 0, /*!< window watchDog timer interrupt */ + LVD_IRQn = 1, /*!< LVD through EXTI line detect interrupt */ + TAMPER_IRQn = 2, /*!< tamper through EXTI line detect */ + RTC_IRQn = 3, /*!< RTC through EXTI line interrupt */ + FMC_IRQn = 4, /*!< FMC interrupt */ + RCU_CTC_IRQn = 5, /*!< RCU and CTC interrupt */ + EXTI0_IRQn = 6, /*!< EXTI line 0 interrupts */ + EXTI1_IRQn = 7, /*!< EXTI line 1 interrupts */ + EXTI2_IRQn = 8, /*!< EXTI line 2 interrupts */ + EXTI3_IRQn = 9, /*!< EXTI line 3 interrupts */ + EXTI4_IRQn = 10, /*!< EXTI line 4 interrupts */ + DMA0_Channel0_IRQn = 11, /*!< DMA0 channel0 interrupt */ + DMA0_Channel1_IRQn = 12, /*!< DMA0 channel1 interrupt */ + DMA0_Channel2_IRQn = 13, /*!< DMA0 channel2 interrupt */ + DMA0_Channel3_IRQn = 14, /*!< DMA0 channel3 interrupt */ + DMA0_Channel4_IRQn = 15, /*!< DMA0 channel4 interrupt */ + DMA0_Channel5_IRQn = 16, /*!< DMA0 channel5 interrupt */ + DMA0_Channel6_IRQn = 17, /*!< DMA0 channel6 interrupt */ + ADC0_1_IRQn = 18, /*!< ADC0 and ADC1 interrupt */ + +#ifdef GD32F10X_MD + USBD_HP_CAN0_TX_IRQn = 19, /*!< CAN0 TX interrupts */ + USBD_LP_CAN0_RX0_IRQn = 20, /*!< CAN0 RX0 interrupts */ + CAN0_RX1_IRQn = 21, /*!< CAN0 RX1 interrupts */ + CAN0_EWMC_IRQn = 22, /*!< CAN0 EWMC interrupts */ + EXTI5_9_IRQn = 23, /*!< EXTI[9:5] interrupts */ + TIMER0_BRK_IRQn = 24, /*!< TIMER0 break interrupts */ + TIMER0_UP_IRQn = 25, /*!< TIMER0 update interrupts */ + TIMER0_TRG_CMT_IRQn = 26, /*!< TIMER0 trigger and commutation interrupts */ + TIMER0_Channel_IRQn = 27, /*!< TIMER0 channel capture compare interrupts */ + TIMER1_IRQn = 28, /*!< TIMER1 interrupt */ + TIMER2_IRQn = 29, /*!< TIMER2 interrupt */ + TIMER3_IRQn = 30, /*!< TIMER3 interrupts */ + I2C0_EV_IRQn = 31, /*!< I2C0 event interrupt */ + I2C0_ER_IRQn = 32, /*!< I2C0 error interrupt */ + I2C1_EV_IRQn = 33, /*!< I2C1 event interrupt */ + I2C1_ER_IRQn = 34, /*!< I2C1 error interrupt */ + SPI0_IRQn = 35, /*!< SPI0 interrupt */ + SPI1_IRQn = 36, /*!< SPI1 interrupt */ + USART0_IRQn = 37, /*!< USART0 interrupt */ + USART1_IRQn = 38, /*!< USART1 interrupt */ + USART2_IRQn = 39, /*!< USART2 interrupt */ + EXTI10_15_IRQn = 40, /*!< EXTI[15:10] interrupts */ + RTC_Alarm_IRQn = 41, /*!< RTC alarm interrupt */ + USBD_WKUP_IRQn = 42, /*!< USBD Wakeup interrupt */ + EXMC_IRQn = 48, /*!< EXMC global interrupt */ +#endif /* GD32F10X_MD */ + +#ifdef GD32F10X_HD + USBD_HP_CAN0_TX_IRQn = 19, /*!< CAN0 TX interrupts */ + USBD_LP_CAN0_RX0_IRQn = 20, /*!< CAN0 RX0 interrupts */ + CAN0_RX1_IRQn = 21, /*!< CAN0 RX1 interrupts */ + CAN0_EWMC_IRQn = 22, /*!< CAN0 EWMC interrupts */ + EXTI5_9_IRQn = 23, /*!< EXTI[9:5] interrupts */ + TIMER0_BRK_IRQn = 24, /*!< TIMER0 break interrupts */ + TIMER0_UP_IRQn = 25, /*!< TIMER0 update interrupts */ + TIMER0_TRG_CMT_IRQn = 26, /*!< TIMER0 trigger and commutation interrupts */ + TIMER0_Channel_IRQn = 27, /*!< TIMER0 channel capture compare interrupts */ + TIMER1_IRQn = 28, /*!< TIMER1 interrupt */ + TIMER2_IRQn = 29, /*!< TIMER2 interrupt */ + TIMER3_IRQn = 30, /*!< TIMER3 interrupts */ + I2C0_EV_IRQn = 31, /*!< I2C0 event interrupt */ + I2C0_ER_IRQn = 32, /*!< I2C0 error interrupt */ + I2C1_EV_IRQn = 33, /*!< I2C1 event interrupt */ + I2C1_ER_IRQn = 34, /*!< I2C1 error interrupt */ + SPI0_IRQn = 35, /*!< SPI0 interrupt */ + SPI1_IRQn = 36, /*!< SPI1 interrupt */ + USART0_IRQn = 37, /*!< USART0 interrupt */ + USART1_IRQn = 38, /*!< USART1 interrupt */ + USART2_IRQn = 39, /*!< USART2 interrupt */ + EXTI10_15_IRQn = 40, /*!< EXTI[15:10] interrupts */ + RTC_Alarm_IRQn = 41, /*!< RTC alarm interrupt */ + USBD_WKUP_IRQn = 42, /*!< USBD Wakeup interrupt */ + TIMER7_BRK_IRQn = 43, /*!< TIMER7 break interrupts */ + TIMER7_UP_IRQn = 44, /*!< TIMER7 update interrupts */ + TIMER7_TRG_CMT_IRQn = 45, /*!< TIMER7 trigger and commutation interrupts */ + TIMER7_Channel_IRQn = 46, /*!< TIMER7 channel capture compare interrupts */ + ADC2_IRQn = 47, /*!< ADC2 global interrupt */ + EXMC_IRQn = 48, /*!< EXMC global interrupt */ + SDIO_IRQn = 49, /*!< SDIO global interrupt */ + TIMER4_IRQn = 50, /*!< TIMER4 global interrupt */ + SPI2_IRQn = 51, /*!< SPI2 global interrupt */ + UART3_IRQn = 52, /*!< UART3 global interrupt */ + UART4_IRQn = 53, /*!< UART4 global interrupt */ + TIMER5_IRQn = 54, /*!< TIMER5 global interrupt */ + TIMER6_IRQn = 55, /*!< TIMER6 global interrupt */ + DMA1_Channel0_IRQn = 56, /*!< DMA1 channel0 global interrupt */ + DMA1_Channel1_IRQn = 57, /*!< DMA1 channel1 global interrupt */ + DMA1_Channel2_IRQn = 58, /*!< DMA1 channel2 global interrupt */ + DMA1_Channel3_Channel4_IRQn = 59, /*!< DMA1 channel3 and channel4 global Interrupt */ +#endif /* GD32F10X_HD */ + +#ifdef GD32F10X_XD + USBD_HP_CAN0_TX_IRQn = 19, /*!< CAN0 TX interrupts */ + USBD_LP_CAN0_RX0_IRQn = 20, /*!< CAN0 RX0 interrupts */ + CAN0_RX1_IRQn = 21, /*!< CAN0 RX1 interrupts */ + CAN0_EWMC_IRQn = 22, /*!< CAN0 EWMC interrupts */ + EXTI5_9_IRQn = 23, /*!< EXTI[9:5] interrupts */ + TIMER0_BRK_TIMER8_IRQn = 24, /*!< TIMER0 break and TIMER8 interrupts */ + TIMER0_UP_TIMER9_IRQn = 25, /*!< TIMER0 update and TIMER9 interrupts */ + TIMER0_TRG_CMT_TIMER10_IRQn = 26, /*!< TIMER0 trigger and commutation and TIMER10 interrupts */ + TIMER0_Channel_IRQn = 27, /*!< TIMER0 channel capture compare interrupts */ + TIMER1_IRQn = 28, /*!< TIMER1 interrupt */ + TIMER2_IRQn = 29, /*!< TIMER2 interrupt */ + TIMER3_IRQn = 30, /*!< TIMER3 interrupts */ + I2C0_EV_IRQn = 31, /*!< I2C0 event interrupt */ + I2C0_ER_IRQn = 32, /*!< I2C0 error interrupt */ + I2C1_EV_IRQn = 33, /*!< I2C1 event interrupt */ + I2C1_ER_IRQn = 34, /*!< I2C1 error interrupt */ + SPI0_IRQn = 35, /*!< SPI0 interrupt */ + SPI1_IRQn = 36, /*!< SPI1 interrupt */ + USART0_IRQn = 37, /*!< USART0 interrupt */ + USART1_IRQn = 38, /*!< USART1 interrupt */ + USART2_IRQn = 39, /*!< USART2 interrupt */ + EXTI10_15_IRQn = 40, /*!< EXTI[15:10] interrupts */ + RTC_Alarm_IRQn = 41, /*!< RTC alarm interrupt */ + USBD_WKUP_IRQn = 42, /*!< USBD wakeup interrupt */ + TIMER7_BRK_TIMER11_IRQn = 43, /*!< TIMER7 break and TIMER11 interrupts */ + TIMER7_UP_TIMER12_IRQn = 44, /*!< TIMER7 update and TIMER12 interrupts */ + TIMER7_TRG_CMT_TIMER13_IRQn = 45, /*!< TIMER7 trigger and commutation and TIMER13 interrupts */ + TIMER7_Channel_IRQn = 46, /*!< TIMER7 channel capture compare interrupts */ + ADC2_IRQn = 47, /*!< ADC2 global interrupt */ + EXMC_IRQn = 48, /*!< EXMC global interrupt */ + SDIO_IRQn = 49, /*!< SDIO global interrupt */ + TIMER4_IRQn = 50, /*!< TIMER4 global interrupt */ + SPI2_IRQn = 51, /*!< SPI2 global interrupt */ + UART3_IRQn = 52, /*!< UART3 global interrupt */ + UART4_IRQn = 53, /*!< UART4 global interrupt */ + TIMER5_IRQn = 54, /*!< TIMER5 global interrupt */ + TIMER6_IRQn = 55, /*!< TIMER6 global interrupt */ + DMA1_Channel0_IRQn = 56, /*!< DMA1 channel0 global interrupt */ + DMA1_Channel1_IRQn = 57, /*!< DMA1 channel1 global interrupt */ + DMA1_Channel2_IRQn = 58, /*!< DMA1 channel2 global interrupt */ + DMA1_Channel3_Channel4_IRQn = 59, /*!< DMA1 channel3 and channel4 global interrupt */ +#endif /* GD32F10X_XD */ + +#ifdef GD32F10X_CL + CAN0_TX_IRQn = 19, /*!< CAN0 TX interrupts */ + CAN0_RX0_IRQn = 20, /*!< CAN0 RX0 interrupts */ + CAN0_RX1_IRQn = 21, /*!< CAN0 RX1 interrupts */ + CAN0_EWMC_IRQn = 22, /*!< CAN0 EWMC interrupts */ + EXTI5_9_IRQn = 23, /*!< EXTI[9:5] interrupts */ + TIMER0_BRK_IRQn = 24, /*!< TIMER0 break interrupts */ + TIMER0_UP_IRQn = 25, /*!< TIMER0 update interrupts */ + TIMER0_TRG_CMT_IRQn = 26, /*!< TIMER0 trigger and commutation interrupts */ + TIMER0_Channel_IRQn = 27, /*!< TIMER0 channel capture compare interrupts */ + TIMER1_IRQn = 28, /*!< TIMER1 interrupt */ + TIMER2_IRQn = 29, /*!< TIMER2 interrupt */ + TIMER3_IRQn = 30, /*!< TIMER3 interrupts */ + I2C0_EV_IRQn = 31, /*!< I2C0 event interrupt */ + I2C0_ER_IRQn = 32, /*!< I2C0 error interrupt */ + I2C1_EV_IRQn = 33, /*!< I2C1 event interrupt */ + I2C1_ER_IRQn = 34, /*!< I2C1 error interrupt */ + SPI0_IRQn = 35, /*!< SPI0 interrupt */ + SPI1_IRQn = 36, /*!< SPI1 interrupt */ + USART0_IRQn = 37, /*!< USART0 interrupt */ + USART1_IRQn = 38, /*!< USART1 interrupt */ + USART2_IRQn = 39, /*!< USART2 interrupt */ + EXTI10_15_IRQn = 40, /*!< EXTI[15:10] interrupts */ + RTC_ALARM_IRQn = 41, /*!< RTC alarm interrupt */ + USBFS_WKUP_IRQn = 42, /*!< USBFS wakeup interrupt */ + TIMER7_BRK_IRQn = 43, /*!< TIMER7 break interrupts */ + TIMER7_UP_IRQn = 44, /*!< TIMER7 update interrupts */ + TIMER7_TRG_CMT_IRQn = 45, /*!< TIMER7 trigger and commutation interrupts */ + TIMER7_Channel_IRQn = 46, /*!< TIMER7 channel capture compare interrupts */ + EXMC_IRQn = 48, /*!< EXMC global interrupt */ + TIMER4_IRQn = 50, /*!< TIMER4 global interrupt */ + SPI2_IRQn = 51, /*!< SPI2 global interrupt */ + UART3_IRQn = 52, /*!< UART3 global interrupt */ + UART4_IRQn = 53, /*!< UART4 global interrupt */ + TIMER5_IRQn = 54, /*!< TIMER5 global interrupt */ + TIMER6_IRQn = 55, /*!< TIMER6 global interrupt */ + DMA1_Channel0_IRQn = 56, /*!< DMA1 channel0 global interrupt */ + DMA1_Channel1_IRQn = 57, /*!< DMA1 channel1 global interrupt */ + DMA1_Channel2_IRQn = 58, /*!< DMA1 channel2 global interrupt */ + DMA1_Channel3_IRQn = 59, /*!< DMA1 channel3 global interrupt */ + DMA1_Channel4_IRQn = 60, /*!< DMA1 channel3 global interrupt */ + ENET_IRQn = 61, /*!< ENET global interrupt */ + ENET_WKUP_IRQn = 62, /*!< ENET Wakeup interrupt */ + CAN1_TX_IRQn = 63, /*!< CAN1 TX interrupt */ + CAN1_RX0_IRQn = 64, /*!< CAN1 RX0 interrupt */ + CAN1_RX1_IRQn = 65, /*!< CAN1 RX1 interrupt */ + CAN1_EWMC_IRQn = 66, /*!< CAN1 EWMC interrupt */ + USBFS_IRQn = 67, /*!< USBFS global interrupt */ +#endif /* GD32F10X_CL */ + +} IRQn_Type; + +/* includes */ +#include "core_cm3.h" +#include "system_gd32f10x.h" +#include + +/* enum definitions */ +typedef enum {DISABLE = 0, ENABLE = !DISABLE} EventStatus, ControlStatus; +typedef enum {FALSE = 0, TRUE = !FALSE} bool; +typedef enum {RESET = 0, SET = !RESET} FlagStatus; +typedef enum {ERROR = 0, SUCCESS = !ERROR} ErrStatus; + +/* bit operations */ +#define REG32(addr) (*(volatile uint32_t *)(uint32_t)(addr)) +#define REG16(addr) (*(volatile uint16_t *)(uint32_t)(addr)) +#define REG8(addr) (*(volatile uint8_t *)(uint32_t)(addr)) +#define BIT(x) ((uint32_t)((uint32_t)0x01U<<(x))) +#define BITS(start, end) ((0xFFFFFFFFUL << (start)) & (0xFFFFFFFFUL >> (31U - (uint32_t)(end)))) +#define GET_BITS(regval, start, end) (((regval) & BITS((start),(end))) >> (start)) + +/* main flash and SRAM memory map */ +#define FLASH_BASE ((uint32_t)0x08000000U) /*!< main FLASH base address */ +#define SRAM_BASE ((uint32_t)0x20000000U) /*!< SRAM0 base address */ +#define OB_BASE ((uint32_t)0x1FFFF800U) /*!< OB base address */ +#define DBG_BASE ((uint32_t)0xE0042000U) /*!< DBG base address */ +#define EXMC_BASE ((uint32_t)0xA0000000U) /*!< EXMC register base address */ + +/* peripheral memory map */ +#define APB1_BUS_BASE ((uint32_t)0x40000000U) /*!< apb1 base address */ +#define APB2_BUS_BASE ((uint32_t)0x40010000U) /*!< apb2 base address */ +#define AHB1_BUS_BASE ((uint32_t)0x40018000U) /*!< ahb1 base address */ +#define AHB3_BUS_BASE ((uint32_t)0x60000000U) /*!< ahb3 base address */ + +/* advanced peripheral bus 1 memory map */ +#define TIMER_BASE (APB1_BUS_BASE + 0x00000000U) /*!< TIMER base address */ +#define RTC_BASE (APB1_BUS_BASE + 0x00002800U) /*!< RTC base address */ +#define WWDGT_BASE (APB1_BUS_BASE + 0x00002C00U) /*!< WWDGT base address */ +#define FWDGT_BASE (APB1_BUS_BASE + 0x00003000U) /*!< FWDGT base address */ +#define SPI_BASE (APB1_BUS_BASE + 0x00003800U) /*!< SPI base address */ +#define USART_BASE (APB1_BUS_BASE + 0x00004400U) /*!< USART base address */ +#define I2C_BASE (APB1_BUS_BASE + 0x00005400U) /*!< I2C base address */ +#define USBD_BASE (APB1_BUS_BASE + 0x00005C00U) /*!< USBD base address */ +#define USBD_RAM_BASE (APB1_BUS_BASE + 0x00006000U) /*!< USBD RAM base address */ +#define CAN_BASE (APB1_BUS_BASE + 0x00006400U) /*!< CAN base address */ +#define BKP_BASE (APB1_BUS_BASE + 0x00006C00U) /*!< BKP base address */ +#define PMU_BASE (APB1_BUS_BASE + 0x00007000U) /*!< PMU base address */ +#define DAC_BASE (APB1_BUS_BASE + 0x00007400U) /*!< DAC base address */ + +/* advanced peripheral bus 2 memory map */ +#define AFIO_BASE (APB2_BUS_BASE + 0x00000000U) /*!< AFIO base address */ +#define EXTI_BASE (APB2_BUS_BASE + 0x00000400U) /*!< EXTI base address */ +#define GPIO_BASE (APB2_BUS_BASE + 0x00000800U) /*!< GPIO base address */ +#define ADC_BASE (APB2_BUS_BASE + 0x00002400U) /*!< ADC base address */ + +/* advanced high performance bus 1 memory map */ +#define SDIO_BASE (AHB1_BUS_BASE + 0x00000000U) /*!< SDIO base address */ +#define DMA_BASE (AHB1_BUS_BASE + 0x00008000U) /*!< DMA base address */ +#define RCU_BASE (AHB1_BUS_BASE + 0x00009000U) /*!< RCU base address */ +#define FMC_BASE (AHB1_BUS_BASE + 0x0000A000U) /*!< FMC base address */ +#define CRC_BASE (AHB1_BUS_BASE + 0x0000B000U) /*!< CRC base address */ +#define ENET_BASE (AHB1_BUS_BASE + 0x00010000U) /*!< ENET base address */ +#define USBFS_BASE (AHB1_BUS_BASE + 0x0FFE8000U) /*!< USBFS base address */ + +/* define marco USE_STDPERIPH_DRIVER */ +#if !defined USE_STDPERIPH_DRIVER +#define USE_STDPERIPH_DRIVER +#endif +#ifdef USE_STDPERIPH_DRIVER +#include "gd32f10x_libopt.h" +#endif /* USE_STDPERIPH_DRIVER */ + +#ifdef cplusplus +} +#endif +#endif diff --git a/bsp/gd32/libraries/GD32F10x_Firmware_Library/CMSIS/GD/GD32F10x/Include/system_gd32f10x.h b/bsp/gd32/libraries/GD32F10x_Firmware_Library/CMSIS/GD/GD32F10x/Include/system_gd32f10x.h new file mode 100644 index 0000000000..6bd00fb99d --- /dev/null +++ b/bsp/gd32/libraries/GD32F10x_Firmware_Library/CMSIS/GD/GD32F10x/Include/system_gd32f10x.h @@ -0,0 +1,60 @@ +/*! + \file system_gd32f10x.h + \brief CMSIS Cortex-M3 Device Peripheral Access Layer Header File for + GD32F10x Device Series +*/ + +/* + Copyright (c) 2012 ARM LIMITED + + All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +/* This file refers the CMSIS standard, some adjustments are made according to GigaDevice chips */ + +#ifndef SYSTEM_GD32F10X_H +#define SYSTEM_GD32F10X_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include + +/* system clock frequency (core clock) */ +extern uint32_t SystemCoreClock; + +/* function declarations */ +/* initialize the system and update the SystemCoreClock variable */ +extern void SystemInit(void); +/* update the SystemCoreClock with current core clock retrieved from cpu registers */ +extern void SystemCoreClockUpdate(void); + +#ifdef __cplusplus +} +#endif + +#endif /* SYSTEM_GD32F10X_H */ diff --git a/bsp/gd32/libraries/GD32F10x_Firmware_Library/CMSIS/GD/GD32F10x/Source/ARM/startup_gd32f10x_cl.s b/bsp/gd32/libraries/GD32F10x_Firmware_Library/CMSIS/GD/GD32F10x/Source/ARM/startup_gd32f10x_cl.s new file mode 100644 index 0000000000..a3ffa4c752 --- /dev/null +++ b/bsp/gd32/libraries/GD32F10x_Firmware_Library/CMSIS/GD/GD32F10x/Source/ARM/startup_gd32f10x_cl.s @@ -0,0 +1,390 @@ +;/*! +; \file startup_gd32f10x_cl.s +; \brief start up file +; +; \version 2014-12-26, V1.0.0, firmware for GD32F10x +; \version 2017-06-20, V2.0.0, firmware for GD32F10x +; \version 2018-07-31, V2.1.0, firmware for GD32F10x +;*/ +; +;/* +; Copyright (c) 2018, GigaDevice Semiconductor Inc. +; +; All rights reserved. +; +; Redistribution and use in source and binary forms, with or without modification, +;are permitted provided that the following conditions are met: +; +; 1. Redistributions of source code must retain the above copyright notice, this +; list of conditions and the following disclaimer. +; 2. Redistributions in binary form must reproduce the above copyright notice, +; this list of conditions and the following disclaimer in the documentation +; and/or other materials provided with the distribution. +; 3. Neither the name of the copyright holder nor the names of its contributors +; may be used to endorse or promote products derived from this software without +; specific prior written permission. +; +; THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +;AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +;WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +;IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +;INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +;NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +;PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +;WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +;ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +;OF SUCH DAMAGE. +;*/ + +; Stack Configuration +; Stack Size (in Bytes) <0x0-0xFFFFFFFF:8> +; + +Stack_Size EQU 0x00002000 + + AREA STACK, NOINIT, READWRITE, ALIGN = 3 +Stack_Mem SPACE Stack_Size +__initial_sp + + +; Heap Configuration +; Heap Size (in Bytes) <0x0-0xFFFFFFFF:8> +; + +Heap_Size EQU 0x00002000 + + AREA HEAP, NOINIT, READWRITE, ALIGN = 3 +__heap_base +Heap_Mem SPACE Heap_Size +__heap_limit + + + PRESERVE8 + THUMB + +; /* reset Vector Mapped to at Address 0 */ + AREA RESET, DATA, READONLY + EXPORT __Vectors + EXPORT __Vectors_End + EXPORT __Vectors_Size + +__Vectors DCD __initial_sp ; Top of Stack + DCD Reset_Handler ; Reset Handler + DCD NMI_Handler ; NMI Handler + DCD HardFault_Handler ; Hard Fault Handler + DCD MemManage_Handler ; MPU Fault Handler + DCD BusFault_Handler ; Bus Fault Handler + DCD UsageFault_Handler ; Usage Fault Handler + DCD 0 ; Reserved + DCD 0 ; Reserved + DCD 0 ; Reserved + DCD 0 ; Reserved + DCD SVC_Handler ; SVCall Handler + DCD DebugMon_Handler ; Debug Monitor Handler + DCD 0 ; Reserved + DCD PendSV_Handler ; PendSV Handler + DCD SysTick_Handler ; SysTick Handler + +; /* external interrupts handler */ + DCD WWDGT_IRQHandler ; 16:Window Watchdog Timer + DCD LVD_IRQHandler ; 17:LVD through EXTI Line detect + DCD TAMPER_IRQHandler ; 18:Tamper Interrupt + DCD RTC_IRQHandler ; 19:RTC through EXTI Line + DCD FMC_IRQHandler ; 20:FMC + DCD RCU_IRQHandler ; 21:RCU + DCD EXTI0_IRQHandler ; 22:EXTI Line 0 + DCD EXTI1_IRQHandler ; 23:EXTI Line 1 + DCD EXTI2_IRQHandler ; 24:EXTI Line 2 + DCD EXTI3_IRQHandler ; 25:EXTI Line 3 + DCD EXTI4_IRQHandler ; 26:EXTI Line 4 + DCD DMA0_Channel0_IRQHandler ; 27:DMA0 Channel 0 + DCD DMA0_Channel1_IRQHandler ; 28:DMA0 Channel 1 + DCD DMA0_Channel2_IRQHandler ; 29:DMA0 Channel 2 + DCD DMA0_Channel3_IRQHandler ; 30:DMA0 Channel 3 + DCD DMA0_Channel4_IRQHandler ; 31:DMA0 Channel 4 + DCD DMA0_Channel5_IRQHandler ; 32:DMA0 Channel 5 + DCD DMA0_Channel6_IRQHandler ; 33:DMA0 Channel 6 + DCD ADC0_1_IRQHandler ; 34:ADC0 and ADC1 + DCD CAN0_TX_IRQHandler ; 35:CAN0 TX + DCD CAN0_RX0_IRQHandler ; 36:CAN0 RX0 + DCD CAN0_RX1_IRQHandler ; 37:CAN0 RX1 + DCD CAN0_EWMC_IRQHandler ; 38:CAN0 EWMC + DCD EXTI5_9_IRQHandler ; 39:EXTI Line 5 to EXTI Line 9 + DCD TIMER0_BRK_IRQHandler ; 40:TIMER0 Break + DCD TIMER0_UP_IRQHandler ; 41:TIMER0 Update + DCD TIMER0_TRG_CMT_IRQHandler ; 42:TIMER0 Trigger and Commutation + DCD TIMER0_Channel_IRQHandler ; 43:TIMER0 Channel Capture Compare + DCD TIMER1_IRQHandler ; 44:TIMER1 + DCD TIMER2_IRQHandler ; 45:TIMER2 + DCD TIMER3_IRQHandler ; 46:TIMER3 + DCD I2C0_EV_IRQHandler ; 47:I2C0 Event + DCD I2C0_ER_IRQHandler ; 48:I2C0 Error + DCD I2C1_EV_IRQHandler ; 49:I2C1 Event + DCD I2C1_ER_IRQHandler ; 50:I2C1 Error + DCD SPI0_IRQHandler ; 51:SPI0 + DCD SPI1_IRQHandler ; 52:SPI1 + DCD USART0_IRQHandler ; 53:USART0 + DCD USART1_IRQHandler ; 54:USART1 + DCD USART2_IRQHandler ; 55:USART2 + DCD EXTI10_15_IRQHandler ; 56:EXTI Line 10 to EXTI Line 15 + DCD RTC_Alarm_IRQHandler ; 57:RTC Alarm through EXTI Line + DCD USBFS_WKUP_IRQHandler ; 58:USBFS WakeUp from suspend through EXTI Line + DCD TIMER7_BRK_IRQHandler ; 59:TIMER7 Break Interrupt + DCD TIMER7_UP_IRQHandler ; 60:TIMER7 Update Interrupt + DCD TIMER7_TRG_CMT_IRQHandler ; 61:TIMER7 Trigger + DCD TIMER7_Channel_IRQHandler ; 62:TIMER7 Channel Capture Compare + DCD 0 ; Reserved + DCD EXMC_IRQHandler ; 64:EXMC + DCD 0 ; Reserved + DCD TIMER4_IRQHandler ; 66:TIMER4 + DCD SPI2_IRQHandler ; 67:SPI2 + DCD UART3_IRQHandler ; 68:UART3 + DCD UART4_IRQHandler ; 69:UART4 + DCD TIMER5_IRQHandler ; 70:TIMER5 + DCD TIMER6_IRQHandler ; 71:TIMER6 + DCD DMA1_Channel0_IRQHandler ; 72:DMA1 Channel0 + DCD DMA1_Channel1_IRQHandler ; 73:DMA1 Channel1 + DCD DMA1_Channel2_IRQHandler ; 74:DMA1 Channel2 + DCD DMA1_Channel3_IRQHandler ; 75:DMA1 Channel3 + DCD DMA1_Channel4_IRQHandler ; 76:DMA1 Channel4 + DCD ENET_IRQHandler ; 77:Ethernet + DCD ENET_WKUP_IRQHandler ; 78:Ethernet Wakeup through EXTI line + DCD CAN1_TX_IRQHandler ; 79:CAN1 TX + DCD CAN1_RX0_IRQHandler ; 80:CAN1 RX0 + DCD CAN1_RX1_IRQHandler ; 81:CAN1 RX1 + DCD CAN1_EWMC_IRQHandler ; 82:CAN1 EWMC + DCD USBFS_IRQHandler ; 83:USBFS + +__Vectors_End + +__Vectors_Size EQU __Vectors_End - __Vectors + + AREA |.text|, CODE, READONLY + +;/* reset Handler */ +Reset_Handler PROC + EXPORT Reset_Handler [WEAK] + IMPORT __main + IMPORT SystemInit + LDR R0, =SystemInit + BLX R0 + LDR R0, =__main + BX R0 + ENDP + +;/* dummy Exception Handlers */ +NMI_Handler PROC + EXPORT NMI_Handler [WEAK] + B . + ENDP + +HardFault_Handler PROC + EXPORT HardFault_Handler [WEAK] + B . + ENDP + +MemManage_Handler PROC + EXPORT MemManage_Handler [WEAK] + B . + ENDP + +BusFault_Handler PROC + EXPORT BusFault_Handler [WEAK] + B . + ENDP + +UsageFault_Handler PROC + EXPORT UsageFault_Handler [WEAK] + B . + ENDP + +SVC_Handler PROC + EXPORT SVC_Handler [WEAK] + B . + ENDP + +DebugMon_Handler PROC + EXPORT DebugMon_Handler [WEAK] + B . + ENDP + +PendSV_Handler PROC + EXPORT PendSV_Handler [WEAK] + B . + ENDP + +SysTick_Handler PROC + EXPORT SysTick_Handler [WEAK] + B . + ENDP + +Default_Handler PROC +; /* external interrupts handler */ + EXPORT WWDGT_IRQHandler [WEAK] + EXPORT LVD_IRQHandler [WEAK] + EXPORT TAMPER_IRQHandler [WEAK] + EXPORT RTC_IRQHandler [WEAK] + EXPORT FMC_IRQHandler [WEAK] + EXPORT RCU_IRQHandler [WEAK] + EXPORT EXTI0_IRQHandler [WEAK] + EXPORT EXTI1_IRQHandler [WEAK] + EXPORT EXTI2_IRQHandler [WEAK] + EXPORT EXTI3_IRQHandler [WEAK] + EXPORT EXTI4_IRQHandler [WEAK] + EXPORT DMA0_Channel0_IRQHandler [WEAK] + EXPORT DMA0_Channel1_IRQHandler [WEAK] + EXPORT DMA0_Channel2_IRQHandler [WEAK] + EXPORT DMA0_Channel3_IRQHandler [WEAK] + EXPORT DMA0_Channel4_IRQHandler [WEAK] + EXPORT DMA0_Channel5_IRQHandler [WEAK] + EXPORT DMA0_Channel6_IRQHandler [WEAK] + EXPORT ADC0_1_IRQHandler [WEAK] + EXPORT CAN0_TX_IRQHandler [WEAK] + EXPORT CAN0_RX0_IRQHandler [WEAK] + EXPORT CAN0_RX1_IRQHandler [WEAK] + EXPORT CAN0_EWMC_IRQHandler [WEAK] + EXPORT EXTI5_9_IRQHandler [WEAK] + EXPORT TIMER0_BRK_IRQHandler [WEAK] + EXPORT TIMER0_UP_IRQHandler [WEAK] + EXPORT TIMER0_TRG_CMT_IRQHandler [WEAK] + EXPORT TIMER0_Channel_IRQHandler [WEAK] + EXPORT TIMER1_IRQHandler [WEAK] + EXPORT TIMER2_IRQHandler [WEAK] + EXPORT TIMER3_IRQHandler [WEAK] + EXPORT I2C0_EV_IRQHandler [WEAK] + EXPORT I2C0_ER_IRQHandler [WEAK] + EXPORT I2C1_EV_IRQHandler [WEAK] + EXPORT I2C1_ER_IRQHandler [WEAK] + EXPORT SPI0_IRQHandler [WEAK] + EXPORT SPI1_IRQHandler [WEAK] + EXPORT USART0_IRQHandler [WEAK] + EXPORT USART1_IRQHandler [WEAK] + EXPORT USART2_IRQHandler [WEAK] + EXPORT EXTI10_15_IRQHandler [WEAK] + EXPORT RTC_Alarm_IRQHandler [WEAK] + EXPORT USBFS_WKUP_IRQHandler [WEAK] + EXPORT TIMER7_BRK_IRQHandler [WEAK] + EXPORT TIMER7_UP_IRQHandler [WEAK] + EXPORT TIMER7_TRG_CMT_IRQHandler [WEAK] + EXPORT TIMER7_Channel_IRQHandler [WEAK] + EXPORT EXMC_IRQHandler [WEAK] + EXPORT TIMER4_IRQHandler [WEAK] + EXPORT SPI2_IRQHandler [WEAK] + EXPORT UART3_IRQHandler [WEAK] + EXPORT UART4_IRQHandler [WEAK] + EXPORT TIMER5_IRQHandler [WEAK] + EXPORT TIMER6_IRQHandler [WEAK] + EXPORT DMA1_Channel0_IRQHandler [WEAK] + EXPORT DMA1_Channel1_IRQHandler [WEAK] + EXPORT DMA1_Channel2_IRQHandler [WEAK] + EXPORT DMA1_Channel3_IRQHandler [WEAK] + EXPORT DMA1_Channel4_IRQHandler [WEAK] + EXPORT ENET_IRQHandler [WEAK] + EXPORT ENET_WKUP_IRQHandler [WEAK] + EXPORT CAN1_TX_IRQHandler [WEAK] + EXPORT CAN1_RX0_IRQHandler [WEAK] + EXPORT CAN1_RX1_IRQHandler [WEAK] + EXPORT CAN1_EWMC_IRQHandler [WEAK] + EXPORT USBFS_IRQHandler [WEAK] + + +;/* external interrupts handler */ +WWDGT_IRQHandler +LVD_IRQHandler +TAMPER_IRQHandler +RTC_IRQHandler +FMC_IRQHandler +RCU_IRQHandler +EXTI0_IRQHandler +EXTI1_IRQHandler +EXTI2_IRQHandler +EXTI3_IRQHandler +EXTI4_IRQHandler +DMA0_Channel0_IRQHandler +DMA0_Channel1_IRQHandler +DMA0_Channel2_IRQHandler +DMA0_Channel3_IRQHandler +DMA0_Channel4_IRQHandler +DMA0_Channel5_IRQHandler +DMA0_Channel6_IRQHandler +ADC0_1_IRQHandler +CAN0_TX_IRQHandler +CAN0_RX0_IRQHandler +CAN0_RX1_IRQHandler +CAN0_EWMC_IRQHandler +EXTI5_9_IRQHandler +TIMER0_BRK_IRQHandler +TIMER0_UP_IRQHandler +TIMER0_TRG_CMT_IRQHandler +TIMER0_Channel_IRQHandler +TIMER1_IRQHandler +TIMER2_IRQHandler +TIMER3_IRQHandler +I2C0_EV_IRQHandler +I2C0_ER_IRQHandler +I2C1_EV_IRQHandler +I2C1_ER_IRQHandler +SPI0_IRQHandler +SPI1_IRQHandler +USART0_IRQHandler +USART1_IRQHandler +USART2_IRQHandler +EXTI10_15_IRQHandler +RTC_Alarm_IRQHandler +USBFS_WKUP_IRQHandler +TIMER7_BRK_IRQHandler +TIMER7_UP_IRQHandler +TIMER7_TRG_CMT_IRQHandler +TIMER7_Channel_IRQHandler +EXMC_IRQHandler +TIMER4_IRQHandler +SPI2_IRQHandler +UART3_IRQHandler +UART4_IRQHandler +TIMER5_IRQHandler +TIMER6_IRQHandler +DMA1_Channel0_IRQHandler +DMA1_Channel1_IRQHandler +DMA1_Channel2_IRQHandler +DMA1_Channel3_IRQHandler +DMA1_Channel4_IRQHandler +ENET_IRQHandler +ENET_WKUP_IRQHandler +CAN1_TX_IRQHandler +CAN1_RX0_IRQHandler +CAN1_RX1_IRQHandler +CAN1_EWMC_IRQHandler +USBFS_IRQHandler + + + B . + ENDP + + ALIGN + +; user Initial Stack & Heap + + IF :DEF:__MICROLIB + + EXPORT __initial_sp + EXPORT __heap_base + EXPORT __heap_limit + + ELSE + + IMPORT __use_two_region_memory + EXPORT __user_initial_stackheap + +__user_initial_stackheap PROC + LDR R0, = Heap_Mem + LDR R1, =(Stack_Mem + Stack_Size) + LDR R2, = (Heap_Mem + Heap_Size) + LDR R3, = Stack_Mem + BX LR + ENDP + + ALIGN + + ENDIF + + END diff --git a/bsp/gd32/libraries/GD32F10x_Firmware_Library/CMSIS/GD/GD32F10x/Source/ARM/startup_gd32f10x_hd.s b/bsp/gd32/libraries/GD32F10x_Firmware_Library/CMSIS/GD/GD32F10x/Source/ARM/startup_gd32f10x_hd.s new file mode 100644 index 0000000000..fe768cc3a9 --- /dev/null +++ b/bsp/gd32/libraries/GD32F10x_Firmware_Library/CMSIS/GD/GD32F10x/Source/ARM/startup_gd32f10x_hd.s @@ -0,0 +1,371 @@ +;/*! +; \file startup_gd32f10x_hd.s +; \brief start up file +; +; \version 2014-12-26, V1.0.0, firmware for GD32F10x +; \version 2017-06-20, V2.0.0, firmware for GD32F10x +; \version 2018-07-31, V2.1.0, firmware for GD32F10x +;*/ +; +;/* +; Copyright (c) 2018, GigaDevice Semiconductor Inc. +; +; All rights reserved. +; +; Redistribution and use in source and binary forms, with or without modification, +;are permitted provided that the following conditions are met: +; +; 1. Redistributions of source code must retain the above copyright notice, this +; list of conditions and the following disclaimer. +; 2. Redistributions in binary form must reproduce the above copyright notice, +; this list of conditions and the following disclaimer in the documentation +; and/or other materials provided with the distribution. +; 3. Neither the name of the copyright holder nor the names of its contributors +; may be used to endorse or promote products derived from this software without +; specific prior written permission. +; +; THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +;AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +;WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +;IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +;INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +;NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +;PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +;WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +;ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +;OF SUCH DAMAGE. +;*/ + +; Stack Configuration +; Stack Size (in Bytes) <0x0-0xFFFFFFFF:8> +; + +Stack_Size EQU 0x00002000 + + AREA STACK, NOINIT, READWRITE, ALIGN = 3 +Stack_Mem SPACE Stack_Size +__initial_sp + + +; Heap Configuration +; Heap Size (in Bytes) <0x0-0xFFFFFFFF:8> +; + +Heap_Size EQU 0x00002000 + + AREA HEAP, NOINIT, READWRITE, ALIGN = 3 +__heap_base +Heap_Mem SPACE Heap_Size +__heap_limit + + + PRESERVE8 + THUMB + +; /* reset Vector Mapped to at Address 0 */ + AREA RESET, DATA, READONLY + EXPORT __Vectors + EXPORT __Vectors_End + EXPORT __Vectors_Size + +__Vectors DCD __initial_sp ; Top of Stack + DCD Reset_Handler ; Reset Handler + DCD NMI_Handler ; NMI Handler + DCD HardFault_Handler ; Hard Fault Handler + DCD MemManage_Handler ; MPU Fault Handler + DCD BusFault_Handler ; Bus Fault Handler + DCD UsageFault_Handler ; Usage Fault Handler + DCD 0 ; Reserved + DCD 0 ; Reserved + DCD 0 ; Reserved + DCD 0 ; Reserved + DCD SVC_Handler ; SVCall Handler + DCD DebugMon_Handler ; Debug Monitor Handler + DCD 0 ; Reserved + DCD PendSV_Handler ; PendSV Handler + DCD SysTick_Handler ; SysTick Handler + +; /* external interrupts handler */ + DCD WWDGT_IRQHandler ; 16:Window Watchdog Timer + DCD LVD_IRQHandler ; 17:LVD through EXTI Line detect + DCD TAMPER_IRQHandler ; 18:Tamper Interrupt + DCD RTC_IRQHandler ; 19:RTC through EXTI Line + DCD FMC_IRQHandler ; 20:FMC + DCD RCU_IRQHandler ; 21:RCU + DCD EXTI0_IRQHandler ; 22:EXTI Line 0 + DCD EXTI1_IRQHandler ; 23:EXTI Line 1 + DCD EXTI2_IRQHandler ; 24:EXTI Line 2 + DCD EXTI3_IRQHandler ; 25:EXTI Line 3 + DCD EXTI4_IRQHandler ; 26:EXTI Line 4 + DCD DMA0_Channel0_IRQHandler ; 27:DMA0 Channel 0 + DCD DMA0_Channel1_IRQHandler ; 28:DMA0 Channel 1 + DCD DMA0_Channel2_IRQHandler ; 29:DMA0 Channel 2 + DCD DMA0_Channel3_IRQHandler ; 30:DMA0 Channel 3 + DCD DMA0_Channel4_IRQHandler ; 31:DMA0 Channel 4 + DCD DMA0_Channel5_IRQHandler ; 32:DMA0 Channel 5 + DCD DMA0_Channel6_IRQHandler ; 33:DMA0 Channel 6 + DCD ADC0_1_IRQHandler ; 34:ADC0 and ADC1 + DCD USBD_HP_CAN0_TX_IRQHandler ; 35:USBD and CAN0 TX + DCD USBD_LP_CAN0_RX0_IRQHandler ; 36:USBD and CAN0 RX0 + DCD CAN0_RX1_IRQHandler ; 37:CAN0 RX1 + DCD CAN0_EWMC_IRQHandler ; 38:CAN0 EWMC + DCD EXTI5_9_IRQHandler ; 39:EXTI Line 5 to EXTI Line 9 + DCD TIMER0_BRK_IRQHandler ; 40:TIMER0 Break + DCD TIMER0_UP_IRQHandler ; 41:TIMER0 Update + DCD TIMER0_TRG_CMT_IRQHandler ; 42:TIMER0 Trigger and Commutation + DCD TIMER0_Channel_IRQHandler ; 43:TIMER0 Channel Capture Compare + DCD TIMER1_IRQHandler ; 44:TIMER1 + DCD TIMER2_IRQHandler ; 45:TIMER2 + DCD TIMER3_IRQHandler ; 46:TIMER3 + DCD I2C0_EV_IRQHandler ; 47:I2C0 Event + DCD I2C0_ER_IRQHandler ; 48:I2C0 Error + DCD I2C1_EV_IRQHandler ; 49:I2C1 Event + DCD I2C1_ER_IRQHandler ; 50:I2C1 Error + DCD SPI0_IRQHandler ; 51:SPI0 + DCD SPI1_IRQHandler ; 52:SPI1 + DCD USART0_IRQHandler ; 53:USART0 + DCD USART1_IRQHandler ; 54:USART1 + DCD USART2_IRQHandler ; 55:USART2 + DCD EXTI10_15_IRQHandler ; 56:EXTI Line 10 to EXTI Line 15 + DCD RTC_Alarm_IRQHandler ; 57:RTC Alarm through EXTI Line + DCD USBD_WKUP_IRQHandler ; 58:USBD WakeUp from suspend through EXTI Line + DCD TIMER7_BRK_IRQHandler ; 59:TIMER7 Break Interrupt + DCD TIMER7_UP_IRQHandler ; 60:TIMER7 Update Interrupt + DCD TIMER7_TRG_CMT_IRQHandler ; 61:TIMER7 Trigger and Commutation Interrupt + DCD TIMER7_Channel_IRQHandler ; 62:TIMER7 Channel Capture Compare + DCD ADC2_IRQHandler ; 63:ADC2 + DCD EXMC_IRQHandler ; 64:EXMC + DCD SDIO_IRQHandler ; 65:SDIO + DCD TIMER4_IRQHandler ; 66:TIMER4 + DCD SPI2_IRQHandler ; 67:SPI2 + DCD UART3_IRQHandler ; 68:UART3 + DCD UART4_IRQHandler ; 69:UART4 + DCD TIMER5_IRQHandler ; 70:TIMER5 + DCD TIMER6_IRQHandler ; 71:TIMER6 + DCD DMA1_Channel0_IRQHandler ; 72:DMA1 Channel0 + DCD DMA1_Channel1_IRQHandler ; 73:DMA1 Channel1 + DCD DMA1_Channel2_IRQHandler ; 74:DMA1 Channel2 + DCD DMA1_Channel3_4_IRQHandler ; 75:DMA1 Channel3 and Channel4 + +__Vectors_End + +__Vectors_Size EQU __Vectors_End - __Vectors + + AREA |.text|, CODE, READONLY + +;/* reset Handler */ +Reset_Handler PROC + EXPORT Reset_Handler [WEAK] + IMPORT __main + IMPORT SystemInit + LDR R0, =SystemInit + BLX R0 + LDR R0, =__main + BX R0 + ENDP + +;/* dummy Exception Handlers */ +NMI_Handler PROC + EXPORT NMI_Handler [WEAK] + B . + ENDP + +HardFault_Handler PROC + EXPORT HardFault_Handler [WEAK] + B . + ENDP + +MemManage_Handler PROC + EXPORT MemManage_Handler [WEAK] + B . + ENDP + +BusFault_Handler PROC + EXPORT BusFault_Handler [WEAK] + B . + ENDP + +UsageFault_Handler PROC + EXPORT UsageFault_Handler [WEAK] + B . + ENDP + +SVC_Handler PROC + EXPORT SVC_Handler [WEAK] + B . + ENDP + +DebugMon_Handler PROC + EXPORT DebugMon_Handler [WEAK] + B . + ENDP + +PendSV_Handler PROC + EXPORT PendSV_Handler [WEAK] + B . + ENDP + +SysTick_Handler PROC + EXPORT SysTick_Handler [WEAK] + B . + ENDP + +Default_Handler PROC +; /* external interrupts handler */ + EXPORT WWDGT_IRQHandler [WEAK] + EXPORT LVD_IRQHandler [WEAK] + EXPORT TAMPER_IRQHandler [WEAK] + EXPORT RTC_IRQHandler [WEAK] + EXPORT FMC_IRQHandler [WEAK] + EXPORT RCU_IRQHandler [WEAK] + EXPORT EXTI0_IRQHandler [WEAK] + EXPORT EXTI1_IRQHandler [WEAK] + EXPORT EXTI2_IRQHandler [WEAK] + EXPORT EXTI3_IRQHandler [WEAK] + EXPORT EXTI4_IRQHandler [WEAK] + EXPORT DMA0_Channel0_IRQHandler [WEAK] + EXPORT DMA0_Channel1_IRQHandler [WEAK] + EXPORT DMA0_Channel2_IRQHandler [WEAK] + EXPORT DMA0_Channel3_IRQHandler [WEAK] + EXPORT DMA0_Channel4_IRQHandler [WEAK] + EXPORT DMA0_Channel5_IRQHandler [WEAK] + EXPORT DMA0_Channel6_IRQHandler [WEAK] + EXPORT ADC0_1_IRQHandler [WEAK] + EXPORT USBD_HP_CAN0_TX_IRQHandler [WEAK] + EXPORT USBD_LP_CAN0_RX0_IRQHandler [WEAK] + EXPORT CAN0_RX1_IRQHandler [WEAK] + EXPORT CAN0_EWMC_IRQHandler [WEAK] + EXPORT EXTI5_9_IRQHandler [WEAK] + EXPORT TIMER0_BRK_IRQHandler [WEAK] + EXPORT TIMER0_UP_IRQHandler [WEAK] + EXPORT TIMER0_TRG_CMT_IRQHandler [WEAK] + EXPORT TIMER0_Channel_IRQHandler [WEAK] + EXPORT TIMER1_IRQHandler [WEAK] + EXPORT TIMER2_IRQHandler [WEAK] + EXPORT TIMER3_IRQHandler [WEAK] + EXPORT I2C0_EV_IRQHandler [WEAK] + EXPORT I2C0_ER_IRQHandler [WEAK] + EXPORT I2C1_EV_IRQHandler [WEAK] + EXPORT I2C1_ER_IRQHandler [WEAK] + EXPORT SPI0_IRQHandler [WEAK] + EXPORT SPI1_IRQHandler [WEAK] + EXPORT USART0_IRQHandler [WEAK] + EXPORT USART1_IRQHandler [WEAK] + EXPORT USART2_IRQHandler [WEAK] + EXPORT EXTI10_15_IRQHandler [WEAK] + EXPORT RTC_Alarm_IRQHandler [WEAK] + EXPORT USBD_WKUP_IRQHandler [WEAK] + EXPORT TIMER7_BRK_IRQHandler [WEAK] + EXPORT TIMER7_UP_IRQHandler [WEAK] + EXPORT TIMER7_TRG_CMT_IRQHandler [WEAK] + EXPORT TIMER7_Channel_IRQHandler [WEAK] + EXPORT ADC2_IRQHandler [WEAK] + EXPORT EXMC_IRQHandler [WEAK] + EXPORT SDIO_IRQHandler [WEAK] + EXPORT TIMER4_IRQHandler [WEAK] + EXPORT SPI2_IRQHandler [WEAK] + EXPORT UART3_IRQHandler [WEAK] + EXPORT UART4_IRQHandler [WEAK] + EXPORT TIMER5_IRQHandler [WEAK] + EXPORT TIMER6_IRQHandler [WEAK] + EXPORT DMA1_Channel0_IRQHandler [WEAK] + EXPORT DMA1_Channel1_IRQHandler [WEAK] + EXPORT DMA1_Channel2_IRQHandler [WEAK] + EXPORT DMA1_Channel3_4_IRQHandler [WEAK] + + +;/* external interrupts handler */ +WWDGT_IRQHandler +LVD_IRQHandler +TAMPER_IRQHandler +RTC_IRQHandler +FMC_IRQHandler +RCU_IRQHandler +EXTI0_IRQHandler +EXTI1_IRQHandler +EXTI2_IRQHandler +EXTI3_IRQHandler +EXTI4_IRQHandler +DMA0_Channel0_IRQHandler +DMA0_Channel1_IRQHandler +DMA0_Channel2_IRQHandler +DMA0_Channel3_IRQHandler +DMA0_Channel4_IRQHandler +DMA0_Channel5_IRQHandler +DMA0_Channel6_IRQHandler +ADC0_1_IRQHandler +USBD_HP_CAN0_TX_IRQHandler +USBD_LP_CAN0_RX0_IRQHandler +CAN0_RX1_IRQHandler +CAN0_EWMC_IRQHandler +EXTI5_9_IRQHandler +TIMER0_BRK_IRQHandler +TIMER0_UP_IRQHandler +TIMER0_TRG_CMT_IRQHandler +TIMER0_Channel_IRQHandler +TIMER1_IRQHandler +TIMER2_IRQHandler +TIMER3_IRQHandler +I2C0_EV_IRQHandler +I2C0_ER_IRQHandler +I2C1_EV_IRQHandler +I2C1_ER_IRQHandler +SPI0_IRQHandler +SPI1_IRQHandler +USART0_IRQHandler +USART1_IRQHandler +USART2_IRQHandler +EXTI10_15_IRQHandler +RTC_Alarm_IRQHandler +USBD_WKUP_IRQHandler +TIMER7_BRK_IRQHandler +TIMER7_UP_IRQHandler +TIMER7_TRG_CMT_IRQHandler +TIMER7_Channel_IRQHandler +ADC2_IRQHandler +EXMC_IRQHandler +SDIO_IRQHandler +TIMER4_IRQHandler +SPI2_IRQHandler +UART3_IRQHandler +UART4_IRQHandler +TIMER5_IRQHandler +TIMER6_IRQHandler +DMA1_Channel0_IRQHandler +DMA1_Channel1_IRQHandler +DMA1_Channel2_IRQHandler +DMA1_Channel3_4_IRQHandler + + + + B . + ENDP + + ALIGN + +; user Initial Stack & Heap + + IF :DEF:__MICROLIB + + EXPORT __initial_sp + EXPORT __heap_base + EXPORT __heap_limit + + ELSE + + IMPORT __use_two_region_memory + EXPORT __user_initial_stackheap + +__user_initial_stackheap PROC + LDR R0, = Heap_Mem + LDR R1, =(Stack_Mem + Stack_Size) + LDR R2, = (Heap_Mem + Heap_Size) + LDR R3, = Stack_Mem + BX LR + ENDP + + ALIGN + + ENDIF + + END diff --git a/bsp/gd32/libraries/GD32F10x_Firmware_Library/CMSIS/GD/GD32F10x/Source/ARM/startup_gd32f10x_md.s b/bsp/gd32/libraries/GD32F10x_Firmware_Library/CMSIS/GD/GD32F10x/Source/ARM/startup_gd32f10x_md.s new file mode 100644 index 0000000000..c567fee5c1 --- /dev/null +++ b/bsp/gd32/libraries/GD32F10x_Firmware_Library/CMSIS/GD/GD32F10x/Source/ARM/startup_gd32f10x_md.s @@ -0,0 +1,328 @@ +;/*! +; \file startup_gd32f10x_md.s +; \brief start up file +; +; \version 2014-12-26, V1.0.0, firmware for GD32F10x +; \version 2017-06-20, V2.0.0, firmware for GD32F10x +; \version 2018-07-31, V2.1.0, firmware for GD32F10x +;*/ +; +;/* +; Copyright (c) 2018, GigaDevice Semiconductor Inc. +; +; All rights reserved. +; +; Redistribution and use in source and binary forms, with or without modification, +;are permitted provided that the following conditions are met: +; +; 1. Redistributions of source code must retain the above copyright notice, this +; list of conditions and the following disclaimer. +; 2. Redistributions in binary form must reproduce the above copyright notice, +; this list of conditions and the following disclaimer in the documentation +; and/or other materials provided with the distribution. +; 3. Neither the name of the copyright holder nor the names of its contributors +; may be used to endorse or promote products derived from this software without +; specific prior written permission. +; +; THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +;AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +;WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +;IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +;INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +;NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +;PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +;WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +;ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +;OF SUCH DAMAGE. +;*/ + +; Stack Configuration +; Stack Size (in Bytes) <0x0-0xFFFFFFFF:8> +; + +Stack_Size EQU 0x00002000 + + AREA STACK, NOINIT, READWRITE, ALIGN = 3 +Stack_Mem SPACE Stack_Size +__initial_sp + + +; Heap Configuration +; Heap Size (in Bytes) <0x0-0xFFFFFFFF:8> +; + +Heap_Size EQU 0x00002000 + + AREA HEAP, NOINIT, READWRITE, ALIGN = 3 +__heap_base +Heap_Mem SPACE Heap_Size +__heap_limit + + + PRESERVE8 + THUMB + +; /* reset Vector Mapped to at Address 0 */ + AREA RESET, DATA, READONLY + EXPORT __Vectors + EXPORT __Vectors_End + EXPORT __Vectors_Size + +__Vectors DCD __initial_sp ; Top of Stack + DCD Reset_Handler ; Reset Handler + DCD NMI_Handler ; NMI Handler + DCD HardFault_Handler ; Hard Fault Handler + DCD MemManage_Handler ; MPU Fault Handler + DCD BusFault_Handler ; Bus Fault Handler + DCD UsageFault_Handler ; Usage Fault Handler + DCD 0 ; Reserved + DCD 0 ; Reserved + DCD 0 ; Reserved + DCD 0 ; Reserved + DCD SVC_Handler ; SVCall Handler + DCD DebugMon_Handler ; Debug Monitor Handler + DCD 0 ; Reserved + DCD PendSV_Handler ; PendSV Handler + DCD SysTick_Handler ; SysTick Handler + +; /* external interrupts handler */ + DCD WWDGT_IRQHandler ; 16:Window Watchdog Timer + DCD LVD_IRQHandler ; 17:LVD through EXTI Line detect + DCD TAMPER_IRQHandler ; 18:Tamper Interrupt + DCD RTC_IRQHandler ; 19:RTC through EXTI Line + DCD FMC_IRQHandler ; 20:FMC + DCD RCU_IRQHandler ; 21:RCU + DCD EXTI0_IRQHandler ; 22:EXTI Line 0 + DCD EXTI1_IRQHandler ; 23:EXTI Line 1 + DCD EXTI2_IRQHandler ; 24:EXTI Line 2 + DCD EXTI3_IRQHandler ; 25:EXTI Line 3 + DCD EXTI4_IRQHandler ; 26:EXTI Line 4 + DCD DMA0_Channel0_IRQHandler ; 27:DMA0 Channel 0 + DCD DMA0_Channel1_IRQHandler ; 28:DMA0 Channel 1 + DCD DMA0_Channel2_IRQHandler ; 29:DMA0 Channel 2 + DCD DMA0_Channel3_IRQHandler ; 30:DMA0 Channel 3 + DCD DMA0_Channel4_IRQHandler ; 31:DMA0 Channel 4 + DCD DMA0_Channel5_IRQHandler ; 32:DMA0 Channel 5 + DCD DMA0_Channel6_IRQHandler ; 33:DMA0 Channel 6 + DCD ADC0_1_IRQHandler ; 34:ADC0 and ADC1 + DCD USBD_HP_CAN0_TX_IRQHandler ; 35:USBD and CAN0 TX + DCD USBD_LP_CAN0_RX0_IRQHandler ; 36:USBD and CAN0 RX0 + DCD CAN0_RX1_IRQHandler ; 37:CAN0 RX1 + DCD CAN0_EWMC_IRQHandler ; 38:CAN0 EWMC + DCD EXTI5_9_IRQHandler ; 39:EXTI Line 5 to EXTI Line 9 + DCD TIMER0_BRK_IRQHandler ; 40:TIMER0 Break + DCD TIMER0_UP_IRQHandler ; 41:TIMER0 Update + DCD TIMER0_TRG_CMT_IRQHandler ; 42:TIMER0 Trigger + DCD TIMER0_Channel_IRQHandler ; 43:TIMER0 Channel Capture Compare + DCD TIMER1_IRQHandler ; 44:TIMER1 + DCD TIMER2_IRQHandler ; 45:TIMER2 + DCD TIMER3_IRQHandler ; 46:TIMER3 + DCD I2C0_EV_IRQHandler ; 47:I2C0 Event + DCD I2C0_ER_IRQHandler ; 48:I2C0 Error + DCD I2C1_EV_IRQHandler ; 49:I2C1 Event + DCD I2C1_ER_IRQHandler ; 50:I2C1 Error + DCD SPI0_IRQHandler ; 51:SPI0 + DCD SPI1_IRQHandler ; 52:SPI1 + DCD USART0_IRQHandler ; 53:USART0 + DCD USART1_IRQHandler ; 54:USART1 + DCD USART2_IRQHandler ; 55:USART2 + DCD EXTI10_15_IRQHandler ; 56:EXTI Line 10 to EXTI Line 15 + DCD RTC_Alarm_IRQHandler ; 57:RTC Alarm through EXTI Line + DCD USBD_WKUP_IRQHandler ; 58:USBD WakeUp from suspend through EXTI Line + DCD 0 ; Reserved + DCD 0 ; Reserved + DCD 0 ; Reserved + DCD 0 ; Reserved + DCD 0 ; Reserved + DCD EXMC_IRQHandler ; 64:EXMC + +__Vectors_End + +__Vectors_Size EQU __Vectors_End - __Vectors + + AREA |.text|, CODE, READONLY + +;/* reset Handler */ +Reset_Handler PROC + EXPORT Reset_Handler [WEAK] + IMPORT __main + IMPORT SystemInit + LDR R0, =SystemInit + BLX R0 + LDR R0, =__main + BX R0 + ENDP + +;/* dummy Exception Handlers */ +NMI_Handler PROC + EXPORT NMI_Handler [WEAK] + B . + ENDP + +HardFault_Handler PROC + EXPORT HardFault_Handler [WEAK] + B . + ENDP + +MemManage_Handler PROC + EXPORT MemManage_Handler [WEAK] + B . + ENDP + +BusFault_Handler PROC + EXPORT BusFault_Handler [WEAK] + B . + ENDP + +UsageFault_Handler PROC + EXPORT UsageFault_Handler [WEAK] + B . + ENDP + +SVC_Handler PROC + EXPORT SVC_Handler [WEAK] + B . + ENDP + +DebugMon_Handler PROC + EXPORT DebugMon_Handler [WEAK] + B . + ENDP + +PendSV_Handler PROC + EXPORT PendSV_Handler [WEAK] + B . + ENDP + +SysTick_Handler PROC + EXPORT SysTick_Handler [WEAK] + B . + ENDP + +Default_Handler PROC +; /* external interrupts handler */ + EXPORT WWDGT_IRQHandler [WEAK] + EXPORT LVD_IRQHandler [WEAK] + EXPORT TAMPER_IRQHandler [WEAK] + EXPORT RTC_IRQHandler [WEAK] + EXPORT FMC_IRQHandler [WEAK] + EXPORT RCU_IRQHandler [WEAK] + EXPORT EXTI0_IRQHandler [WEAK] + EXPORT EXTI1_IRQHandler [WEAK] + EXPORT EXTI2_IRQHandler [WEAK] + EXPORT EXTI3_IRQHandler [WEAK] + EXPORT EXTI4_IRQHandler [WEAK] + EXPORT DMA0_Channel0_IRQHandler [WEAK] + EXPORT DMA0_Channel1_IRQHandler [WEAK] + EXPORT DMA0_Channel2_IRQHandler [WEAK] + EXPORT DMA0_Channel3_IRQHandler [WEAK] + EXPORT DMA0_Channel4_IRQHandler [WEAK] + EXPORT DMA0_Channel5_IRQHandler [WEAK] + EXPORT DMA0_Channel6_IRQHandler [WEAK] + EXPORT ADC0_1_IRQHandler [WEAK] + EXPORT USBD_HP_CAN0_TX_IRQHandler [WEAK] + EXPORT USBD_LP_CAN0_RX0_IRQHandler [WEAK] + EXPORT CAN0_RX1_IRQHandler [WEAK] + EXPORT CAN0_EWMC_IRQHandler [WEAK] + EXPORT EXTI5_9_IRQHandler [WEAK] + EXPORT TIMER0_BRK_IRQHandler [WEAK] + EXPORT TIMER0_UP_IRQHandler [WEAK] + EXPORT TIMER0_TRG_CMT_IRQHandler [WEAK] + EXPORT TIMER0_Channel_IRQHandler [WEAK] + EXPORT TIMER1_IRQHandler [WEAK] + EXPORT TIMER2_IRQHandler [WEAK] + EXPORT TIMER3_IRQHandler [WEAK] + EXPORT I2C0_EV_IRQHandler [WEAK] + EXPORT I2C0_ER_IRQHandler [WEAK] + EXPORT I2C1_EV_IRQHandler [WEAK] + EXPORT I2C1_ER_IRQHandler [WEAK] + EXPORT SPI0_IRQHandler [WEAK] + EXPORT SPI1_IRQHandler [WEAK] + EXPORT USART0_IRQHandler [WEAK] + EXPORT USART1_IRQHandler [WEAK] + EXPORT USART2_IRQHandler [WEAK] + EXPORT EXTI10_15_IRQHandler [WEAK] + EXPORT RTC_Alarm_IRQHandler [WEAK] + EXPORT USBD_WKUP_IRQHandler [WEAK] + EXPORT EXMC_IRQHandler [WEAK] + + +;/* external interrupts handler */ +WWDGT_IRQHandler +LVD_IRQHandler +TAMPER_IRQHandler +RTC_IRQHandler +FMC_IRQHandler +RCU_IRQHandler +EXTI0_IRQHandler +EXTI1_IRQHandler +EXTI2_IRQHandler +EXTI3_IRQHandler +EXTI4_IRQHandler +DMA0_Channel0_IRQHandler +DMA0_Channel1_IRQHandler +DMA0_Channel2_IRQHandler +DMA0_Channel3_IRQHandler +DMA0_Channel4_IRQHandler +DMA0_Channel5_IRQHandler +DMA0_Channel6_IRQHandler +ADC0_1_IRQHandler +USBD_HP_CAN0_TX_IRQHandler +USBD_LP_CAN0_RX0_IRQHandler +CAN0_RX1_IRQHandler +CAN0_EWMC_IRQHandler +EXTI5_9_IRQHandler +TIMER0_BRK_IRQHandler +TIMER0_UP_IRQHandler +TIMER0_TRG_CMT_IRQHandler +TIMER0_Channel_IRQHandler +TIMER1_IRQHandler +TIMER2_IRQHandler +TIMER3_IRQHandler +I2C0_EV_IRQHandler +I2C0_ER_IRQHandler +I2C1_EV_IRQHandler +I2C1_ER_IRQHandler +SPI0_IRQHandler +SPI1_IRQHandler +USART0_IRQHandler +USART1_IRQHandler +USART2_IRQHandler +EXTI10_15_IRQHandler +RTC_Alarm_IRQHandler +USBD_WKUP_IRQHandler +EXMC_IRQHandler + + + + B . + ENDP + + ALIGN + +; user Initial Stack & Heap + + IF :DEF:__MICROLIB + + EXPORT __initial_sp + EXPORT __heap_base + EXPORT __heap_limit + + ELSE + + IMPORT __use_two_region_memory + EXPORT __user_initial_stackheap + +__user_initial_stackheap PROC + LDR R0, = Heap_Mem + LDR R1, =(Stack_Mem + Stack_Size) + LDR R2, = (Heap_Mem + Heap_Size) + LDR R3, = Stack_Mem + BX LR + ENDP + + ALIGN + + ENDIF + + END diff --git a/bsp/gd32/libraries/GD32F10x_Firmware_Library/CMSIS/GD/GD32F10x/Source/ARM/startup_gd32f10x_xd.s b/bsp/gd32/libraries/GD32F10x_Firmware_Library/CMSIS/GD/GD32F10x/Source/ARM/startup_gd32f10x_xd.s new file mode 100644 index 0000000000..3db249b8e5 --- /dev/null +++ b/bsp/gd32/libraries/GD32F10x_Firmware_Library/CMSIS/GD/GD32F10x/Source/ARM/startup_gd32f10x_xd.s @@ -0,0 +1,371 @@ +;/*! +; \file startup_gd32f10x_xd.s +; \brief start up file +; +; \version 2014-12-26, V1.0.0, firmware for GD32F10x +; \version 2017-06-20, V2.0.0, firmware for GD32F10x +; \version 2018-07-31, V2.1.0, firmware for GD32F10x +;*/ +; +;/* +; Copyright (c) 2018, GigaDevice Semiconductor Inc. +; +; All rights reserved. +; +; Redistribution and use in source and binary forms, with or without modification, +;are permitted provided that the following conditions are met: +; +; 1. Redistributions of source code must retain the above copyright notice, this +; list of conditions and the following disclaimer. +; 2. Redistributions in binary form must reproduce the above copyright notice, +; this list of conditions and the following disclaimer in the documentation +; and/or other materials provided with the distribution. +; 3. Neither the name of the copyright holder nor the names of its contributors +; may be used to endorse or promote products derived from this software without +; specific prior written permission. +; +; THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +;AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +;WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +;IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +;INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +;NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +;PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +;WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +;ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +;OF SUCH DAMAGE. +;*/ + +; Stack Configuration +; Stack Size (in Bytes) <0x0-0xFFFFFFFF:8> +; + +Stack_Size EQU 0x00002000 + + AREA STACK, NOINIT, READWRITE, ALIGN = 3 +Stack_Mem SPACE Stack_Size +__initial_sp + + +; Heap Configuration +; Heap Size (in Bytes) <0x0-0xFFFFFFFF:8> +; + +Heap_Size EQU 0x00002000 + + AREA HEAP, NOINIT, READWRITE, ALIGN = 3 +__heap_base +Heap_Mem SPACE Heap_Size +__heap_limit + + + PRESERVE8 + THUMB + +; /* reset Vector Mapped to at Address 0 */ + AREA RESET, DATA, READONLY + EXPORT __Vectors + EXPORT __Vectors_End + EXPORT __Vectors_Size + +__Vectors DCD __initial_sp ; Top of Stack + DCD Reset_Handler ; Reset Handler + DCD NMI_Handler ; NMI Handler + DCD HardFault_Handler ; Hard Fault Handler + DCD MemManage_Handler ; MPU Fault Handler + DCD BusFault_Handler ; Bus Fault Handler + DCD UsageFault_Handler ; Usage Fault Handler + DCD 0 ; Reserved + DCD 0 ; Reserved + DCD 0 ; Reserved + DCD 0 ; Reserved + DCD SVC_Handler ; SVCall Handler + DCD DebugMon_Handler ; Debug Monitor Handler + DCD 0 ; Reserved + DCD PendSV_Handler ; PendSV Handler + DCD SysTick_Handler ; SysTick Handler + +; /* external interrupts handler */ + DCD WWDGT_IRQHandler ; 16:Window Watchdog Timer + DCD LVD_IRQHandler ; 17:LVD through EXTI Line detect + DCD TAMPER_IRQHandler ; 18:Tamper Interrupt + DCD RTC_IRQHandler ; 19:RTC through EXTI Line + DCD FMC_IRQHandler ; 20:FMC + DCD RCU_IRQHandler ; 21:RCU + DCD EXTI0_IRQHandler ; 22:EXTI Line 0 + DCD EXTI1_IRQHandler ; 23:EXTI Line 1 + DCD EXTI2_IRQHandler ; 24:EXTI Line 2 + DCD EXTI3_IRQHandler ; 25:EXTI Line 3 + DCD EXTI4_IRQHandler ; 26:EXTI Line 4 + DCD DMA0_Channel0_IRQHandler ; 27:DMA0 Channel 0 + DCD DMA0_Channel1_IRQHandler ; 28:DMA0 Channel 1 + DCD DMA0_Channel2_IRQHandler ; 29:DMA0 Channel 2 + DCD DMA0_Channel3_IRQHandler ; 30:DMA0 Channel 3 + DCD DMA0_Channel4_IRQHandler ; 31:DMA0 Channel 4 + DCD DMA0_Channel5_IRQHandler ; 32:DMA0 Channel 5 + DCD DMA0_Channel6_IRQHandler ; 33:DMA0 Channel 6 + DCD ADC0_1_IRQHandler ; 34:ADC0 and ADC1 + DCD USBD_HP_CAN0_TX_IRQHandler ; 35:USBD and CAN0 TX + DCD USBD_LP_CAN0_RX0_IRQHandler ; 36:USBD and CAN0 RX0 + DCD CAN0_RX1_IRQHandler ; 37:CAN0 RX1 + DCD CAN0_EWMC_IRQHandler ; 38:CAN0 EWMC + DCD EXTI5_9_IRQHandler ; 39:EXTI Line 5 to EXTI Line 9 + DCD TIMER0_BRK_TIMER8_IRQHandler ; 40:TIMER0 Break and TIMER8 global + DCD TIMER0_UP_TIMER9_IRQHandler ; 41:TIMER0 Update and TIMER9 global + DCD TIMER0_TRG_CMT_TIMER10_IRQHandler ; 42:TIMER0 Trigger and Commutation and TIMER10 global + DCD TIMER0_Channel_IRQHandler ; 43:TIMER0 Channel Capture Compare + DCD TIMER1_IRQHandler ; 44:TIMER1 + DCD TIMER2_IRQHandler ; 45:TIMER2 + DCD TIMER3_IRQHandler ; 46:TIMER3 + DCD I2C0_EV_IRQHandler ; 47:I2C0 Event + DCD I2C0_ER_IRQHandler ; 48:I2C0 Error + DCD I2C1_EV_IRQHandler ; 49:I2C1 Event + DCD I2C1_ER_IRQHandler ; 50:I2C1 Error + DCD SPI0_IRQHandler ; 51:SPI0 + DCD SPI1_IRQHandler ; 52:SPI1 + DCD USART0_IRQHandler ; 53:USART0 + DCD USART1_IRQHandler ; 54:USART1 + DCD USART2_IRQHandler ; 55:USART2 + DCD EXTI10_15_IRQHandler ; 56:EXTI Line 10 to EXTI Line 15 + DCD RTC_Alarm_IRQHandler ; 57:RTC Alarm through EXTI Line + DCD USBD_WKUP_IRQHandler ; 58:USBD WakeUp from suspend through EXTI Line + DCD TIMER7_BRK_TIMER11_IRQHandler ; 59:TIMER7 Break Interrupt and TIMER11 global + DCD TIMER7_UP_TIMER12_IRQHandler ; 60:TIMER7 Update Interrupt and TIMER12 global + DCD TIMER7_TRG_CMT_TIMER13_IRQHandler ; 61:TIMER7 Trigger and Commutation Interrupt and TIMER13 global + DCD TIMER7_Channel_IRQHandler ; 62:TIMER7 Channel Capture Compare + DCD ADC2_IRQHandler ; 63:ADC2 + DCD EXMC_IRQHandler ; 64:EXMC + DCD SDIO_IRQHandler ; 65:SDIO + DCD TIMER4_IRQHandler ; 66:TIMER4 + DCD SPI2_IRQHandler ; 67:SPI2 + DCD UART3_IRQHandler ; 68:UART3 + DCD UART4_IRQHandler ; 69:UART4 + DCD TIMER5_IRQHandler ; 70:TIMER5 + DCD TIMER6_IRQHandler ; 71:TIMER6 + DCD DMA1_Channel0_IRQHandler ; 72:DMA1 Channel0 + DCD DMA1_Channel1_IRQHandler ; 73:DMA1 Channel1 + DCD DMA1_Channel2_IRQHandler ; 74:DMA1 Channel2 + DCD DMA1_Channel3_4_IRQHandler ; 75:DMA1 Channel3 and Channel4 + +__Vectors_End + +__Vectors_Size EQU __Vectors_End - __Vectors + + AREA |.text|, CODE, READONLY + +;/* reset Handler */ +Reset_Handler PROC + EXPORT Reset_Handler [WEAK] + IMPORT __main + IMPORT SystemInit + LDR R0, =SystemInit + BLX R0 + LDR R0, =__main + BX R0 + ENDP + +;/* dummy Exception Handlers */ +NMI_Handler PROC + EXPORT NMI_Handler [WEAK] + B . + ENDP + +HardFault_Handler PROC + EXPORT HardFault_Handler [WEAK] + B . + ENDP + +MemManage_Handler PROC + EXPORT MemManage_Handler [WEAK] + B . + ENDP + +BusFault_Handler PROC + EXPORT BusFault_Handler [WEAK] + B . + ENDP + +UsageFault_Handler PROC + EXPORT UsageFault_Handler [WEAK] + B . + ENDP + +SVC_Handler PROC + EXPORT SVC_Handler [WEAK] + B . + ENDP + +DebugMon_Handler PROC + EXPORT DebugMon_Handler [WEAK] + B . + ENDP + +PendSV_Handler PROC + EXPORT PendSV_Handler [WEAK] + B . + ENDP + +SysTick_Handler PROC + EXPORT SysTick_Handler [WEAK] + B . + ENDP + +Default_Handler PROC +; /* external interrupts handler */ + EXPORT WWDGT_IRQHandler [WEAK] + EXPORT LVD_IRQHandler [WEAK] + EXPORT TAMPER_IRQHandler [WEAK] + EXPORT RTC_IRQHandler [WEAK] + EXPORT FMC_IRQHandler [WEAK] + EXPORT RCU_IRQHandler [WEAK] + EXPORT EXTI0_IRQHandler [WEAK] + EXPORT EXTI1_IRQHandler [WEAK] + EXPORT EXTI2_IRQHandler [WEAK] + EXPORT EXTI3_IRQHandler [WEAK] + EXPORT EXTI4_IRQHandler [WEAK] + EXPORT DMA0_Channel0_IRQHandler [WEAK] + EXPORT DMA0_Channel1_IRQHandler [WEAK] + EXPORT DMA0_Channel2_IRQHandler [WEAK] + EXPORT DMA0_Channel3_IRQHandler [WEAK] + EXPORT DMA0_Channel4_IRQHandler [WEAK] + EXPORT DMA0_Channel5_IRQHandler [WEAK] + EXPORT DMA0_Channel6_IRQHandler [WEAK] + EXPORT ADC0_1_IRQHandler [WEAK] + EXPORT USBD_HP_CAN0_TX_IRQHandler [WEAK] + EXPORT USBD_LP_CAN0_RX0_IRQHandler [WEAK] + EXPORT CAN0_RX1_IRQHandler [WEAK] + EXPORT CAN0_EWMC_IRQHandler [WEAK] + EXPORT EXTI5_9_IRQHandler [WEAK] + EXPORT TIMER0_BRK_TIMER8_IRQHandler [WEAK] + EXPORT TIMER0_UP_TIMER9_IRQHandler [WEAK] + EXPORT TIMER0_TRG_CMT_TIMER10_IRQHandler [WEAK] + EXPORT TIMER0_Channel_IRQHandler [WEAK] + EXPORT TIMER1_IRQHandler [WEAK] + EXPORT TIMER2_IRQHandler [WEAK] + EXPORT TIMER3_IRQHandler [WEAK] + EXPORT I2C0_EV_IRQHandler [WEAK] + EXPORT I2C0_ER_IRQHandler [WEAK] + EXPORT I2C1_EV_IRQHandler [WEAK] + EXPORT I2C1_ER_IRQHandler [WEAK] + EXPORT SPI0_IRQHandler [WEAK] + EXPORT SPI1_IRQHandler [WEAK] + EXPORT USART0_IRQHandler [WEAK] + EXPORT USART1_IRQHandler [WEAK] + EXPORT USART2_IRQHandler [WEAK] + EXPORT EXTI10_15_IRQHandler [WEAK] + EXPORT RTC_Alarm_IRQHandler [WEAK] + EXPORT USBD_WKUP_IRQHandler [WEAK] + EXPORT TIMER7_BRK_TIMER11_IRQHandler [WEAK] + EXPORT TIMER7_UP_TIMER12_IRQHandler [WEAK] + EXPORT TIMER7_TRG_CMT_TIMER13_IRQHandler [WEAK] + EXPORT TIMER7_Channel_IRQHandler [WEAK] + EXPORT ADC2_IRQHandler [WEAK] + EXPORT EXMC_IRQHandler [WEAK] + EXPORT SDIO_IRQHandler [WEAK] + EXPORT TIMER4_IRQHandler [WEAK] + EXPORT SPI2_IRQHandler [WEAK] + EXPORT UART3_IRQHandler [WEAK] + EXPORT UART4_IRQHandler [WEAK] + EXPORT TIMER5_IRQHandler [WEAK] + EXPORT TIMER6_IRQHandler [WEAK] + EXPORT DMA1_Channel0_IRQHandler [WEAK] + EXPORT DMA1_Channel1_IRQHandler [WEAK] + EXPORT DMA1_Channel2_IRQHandler [WEAK] + EXPORT DMA1_Channel3_4_IRQHandler [WEAK] + + +;/* external interrupts handler */ +WWDGT_IRQHandler +LVD_IRQHandler +TAMPER_IRQHandler +RTC_IRQHandler +FMC_IRQHandler +RCU_IRQHandler +EXTI0_IRQHandler +EXTI1_IRQHandler +EXTI2_IRQHandler +EXTI3_IRQHandler +EXTI4_IRQHandler +DMA0_Channel0_IRQHandler +DMA0_Channel1_IRQHandler +DMA0_Channel2_IRQHandler +DMA0_Channel3_IRQHandler +DMA0_Channel4_IRQHandler +DMA0_Channel5_IRQHandler +DMA0_Channel6_IRQHandler +ADC0_1_IRQHandler +USBD_HP_CAN0_TX_IRQHandler +USBD_LP_CAN0_RX0_IRQHandler +CAN0_RX1_IRQHandler +CAN0_EWMC_IRQHandler +EXTI5_9_IRQHandler +TIMER0_BRK_TIMER8_IRQHandler +TIMER0_UP_TIMER9_IRQHandler +TIMER0_TRG_CMT_TIMER10_IRQHandler +TIMER0_Channel_IRQHandler +TIMER1_IRQHandler +TIMER2_IRQHandler +TIMER3_IRQHandler +I2C0_EV_IRQHandler +I2C0_ER_IRQHandler +I2C1_EV_IRQHandler +I2C1_ER_IRQHandler +SPI0_IRQHandler +SPI1_IRQHandler +USART0_IRQHandler +USART1_IRQHandler +USART2_IRQHandler +EXTI10_15_IRQHandler +RTC_Alarm_IRQHandler +USBD_WKUP_IRQHandler +TIMER7_BRK_TIMER11_IRQHandler +TIMER7_UP_TIMER12_IRQHandler +TIMER7_TRG_CMT_TIMER13_IRQHandler +TIMER7_Channel_IRQHandler +ADC2_IRQHandler +EXMC_IRQHandler +SDIO_IRQHandler +TIMER4_IRQHandler +SPI2_IRQHandler +UART3_IRQHandler +UART4_IRQHandler +TIMER5_IRQHandler +TIMER6_IRQHandler +DMA1_Channel0_IRQHandler +DMA1_Channel1_IRQHandler +DMA1_Channel2_IRQHandler +DMA1_Channel3_4_IRQHandler + + + + B . + ENDP + + ALIGN + +; user Initial Stack & Heap + + IF :DEF:__MICROLIB + + EXPORT __initial_sp + EXPORT __heap_base + EXPORT __heap_limit + + ELSE + + IMPORT __use_two_region_memory + EXPORT __user_initial_stackheap + +__user_initial_stackheap PROC + LDR R0, = Heap_Mem + LDR R1, =(Stack_Mem + Stack_Size) + LDR R2, = (Heap_Mem + Heap_Size) + LDR R3, = Stack_Mem + BX LR + ENDP + + ALIGN + + ENDIF + + END diff --git a/bsp/gd32/libraries/GD32F10x_Firmware_Library/CMSIS/GD/GD32F10x/Source/GCC/startup_gd32f10x_cl.s b/bsp/gd32/libraries/GD32F10x_Firmware_Library/CMSIS/GD/GD32F10x/Source/GCC/startup_gd32f10x_cl.s new file mode 100644 index 0000000000..e79129e8a4 --- /dev/null +++ b/bsp/gd32/libraries/GD32F10x_Firmware_Library/CMSIS/GD/GD32F10x/Source/GCC/startup_gd32f10x_cl.s @@ -0,0 +1,273 @@ +;/* +; * Copyright (c) 2006-2021, RT-Thread Development Team +; * +; * SPDX-License-Identifier: Apache-2.0 +; * +; * Change Logs: +; * Date Author Notes +; * 2021-12-18 BruceOu first implementation +; */ + +.syntax unified +.cpu cortex-m3 +.fpu softvfp +.thumb + +.global g_pfnVectors +.global Default_Handler + + .section .isr_vector,"a",%progbits + .type g_pfnVectors, %object + +g_pfnVectors: + .word _estack // Top of Stack + .word Reset_Handler // Reset Handler + .word NMI_Handler // NMI Handler + .word HardFault_Handler // Hard Fault Handler + .word MemManage_Handler // MPU Fault Handler + .word BusFault_Handler // Bus Fault Handler + .word UsageFault_Handler // Usage Fault Handler + .word 0 // Reserved + .word 0 // Reserved + .word 0 // Reserved + .word 0 // Reserved + .word SVC_Handler // SVCall Handler + .word DebugMon_Handler // Debug Monitor Handler + .word 0 // Reserved + .word PendSV_Handler // PendSV Handler + .word SysTick_Handler // SysTick Handler + + // external interrupts handler + .word WWDGT_IRQHandler // 16:Window Watchdog Timer + .word LVD_IRQHandler // 17:LVD through EXTI Line detect + .word TAMPER_IRQHandler // 18:Tamper through EXTI Line detect + .word RTC_IRQHandler // 19:RTC through EXTI Line + .word FMC_IRQHandler // 20:FMC + .word RCU_CTC_IRQHandler // 21:RCU and CTC + .word EXTI0_IRQHandler // 22:EXTI Line 0 + .word EXTI1_IRQHandler // 23:EXTI Line 1 + .word EXTI2_IRQHandler // 24:EXTI Line 2 + .word EXTI3_IRQHandler // 25:EXTI Line 3 + .word EXTI4_IRQHandler // 26:EXTI Line 4 + .word DMA0_Channel0_IRQHandler // 27:DMA0 Channel0 + .word DMA0_Channel1_IRQHandler // 28:DMA0 Channel1 + .word DMA0_Channel2_IRQHandler // 29:DMA0 Channel2 + .word DMA0_Channel3_IRQHandler // 30:DMA0 Channel3 + .word DMA0_Channel4_IRQHandler // 31:DMA0 Channel4 + .word DMA0_Channel5_IRQHandler // 32:DMA0 Channel5 + .word DMA0_Channel6_IRQHandler // 33:DMA0 Channel6 + .word ADC0_1_IRQHandler // 34:ADC0 and ADC1 + .word USBD_HP_CAN0_TX_IRQHandler // 35:USBD HP and CAN0 TX + .word USBD_LP_CAN0_RX0_IRQHandler // 36:USBD LP and CAN0 RX0 + .word CAN0_RX1_IRQHandler // 37:CAN0 RX1 + .word CAN0_EWMC_IRQHandler // 38:CAN0 EWMC + .word EXTI5_9_IRQHandler // 39:EXTI5 to EXTI9 + .word TIMER0_BRK_IRQHandler // 40:TIMER0 Break + .word TIMER0_UP_IRQHandler // 41:TIMER0 Update + .word TIMER0_TRG_CMT_IRQHandler // 42:TIMER0 Trigger and Commutation + .word TIMER0_Channel_IRQHandler // 43:TIMER0 Channel Capture Compare + .word TIMER1_IRQHandler // 44:TIMER1 + .word TIMER2_IRQHandler // 45:TIMER2 + .word TIMER3_IRQHandler // 46:TIMER3 + .word I2C0_EV_IRQHandler // 47:I2C0 Event + .word I2C0_ER_IRQHandler // 48:I2C0 Error + .word I2C1_EV_IRQHandler // 49:I2C1 Event + .word I2C1_ER_IRQHandler // 50:I2C1 Error + .word SPI0_IRQHandler // 51:SPI0 + .word SPI1_IRQHandler // 52:SPI1 + .word USART0_IRQHandler // 53:USART0 + .word USART1_IRQHandler // 54:USART1 + .word USART2_IRQHandler // 55:USART2 + .word EXTI10_15_IRQHandler // 56:EXTI10 to EXTI15 + .word RTC_Alarm_IRQHandler // 57:RTC Alarm + .word USBD_WKUP_IRQHandler // 58:USBD Wakeup + .word TIMER7_BRK_IRQHandler // 59:TIMER7 Break + .word TIMER7_UP_IRQHandler // 60:TIMER7 Update + .word TIMER7_TRG_CMT_IRQHandler // 61:TIMER7 Trigger and Commutation + .word TIMER7_Channel_IRQHandler // 62:TIMER7 Channel Capture Compare + .word 0 // 63:Reserved + .word EXMC_IRQHandler // 64:EXMC + .word 0 // 65:Reserved + .word TIMER4_IRQHandler // 66:TIMER4 + .word SPI2_IRQHandler // 67:SPI2 + .word UART3_IRQHandler // 68:UART3 + .word UART4_IRQHandler // 69:UART4 + .word TIMER5_IRQHandler // 70:TIMER5 + .word TIMER6_IRQHandler // 71:TIMER6 + .word DMA1_Channel0_IRQHandler // 72:DMA1 Channel0 + .word DMA1_Channel1_IRQHandler // 73:DMA1 Channel1 + .word DMA1_Channel2_IRQHandler // 74:DMA1 Channel2 + .word DMA1_Channel3_IRQHandler // 75:DMA1 Channel3 + .word DMA1_Channel4_IRQHandler // 76:DMA1 Channel4 + .word ENET_IRQHandler // 77:Ethernet + .word ENET_WKUP_IRQHandler // 78:Ethernet Wakeup through EXTI Line + .word CAN1_TX_IRQHandler // 79:CAN1 TX + .word CAN1_RX0_IRQHandler // 80:CAN1 RX0 + .word CAN1_RX1_IRQHandler // 81:CAN1 RX1 + .word CAN1_EWMC_IRQHandler // 82:CAN1 EWMC + .word USBFS_IRQHandler // 83:USBFS + + .size g_pfnVectors, .-g_pfnVectors + + .section .text.Reset_Handler + .weak Reset_Handler + .type Reset_Handler, %function +Reset_Handler: + ldr r1, =_sidata + ldr r2, =_sdata + ldr r3, =_edata + + subs r3, r2 + ble fill_bss_start + +loop_copy_data: + subs r3, #4 + ldr r0, [r1,r3] + str r0, [r2,r3] + bgt loop_copy_data + +fill_bss_start: + ldr r1, =__bss_start + ldr r2, =__bss_end + movs r0, 0 + subs r2, r1 + ble startup_enter + +loop_fill_bss: + subs r2, #4 + str r0, [r1, r2] + bgt loop_fill_bss + +startup_enter: + bl SystemInit + bl entry + + /* Exception Handlers */ + .weak NMI_Handler + .type NMI_Handler, %function +NMI_Handler: + b . + .size NMI_Handler, . - NMI_Handler + + .weak MemManage_Handler + .type MemManage_Handler, %function +MemManage_Handler: + b . + .size MemManage_Handler, . - MemManage_Handler + + .weak BusFault_Handler + .type BusFault_Handler, %function +BusFault_Handler: + b . + .size BusFault_Handler, . - BusFault_Handler + + .weak UsageFault_Handler + .type UsageFault_Handler, %function +UsageFault_Handler: + b . + .size UsageFault_Handler, . - UsageFault_Handler + + .weak SVC_Handler + .type SVC_Handler, %function +SVC_Handler: + b . + .size SVC_Handler, . - SVC_Handler + + .weak DebugMon_Handler + .type DebugMon_Handler, %function +DebugMon_Handler: + b . + .size DebugMon_Handler, . - DebugMon_Handler + + .weak PendSV_Handler + .type PendSV_Handler, %function +PendSV_Handler: + b . + .size PendSV_Handler, . - PendSV_Handler + + .weak SysTick_Handler + .type SysTick_Handler, %function +SysTick_Handler: + b . + .size SysTick_Handler, . - SysTick_Handler + + /* IQR Handler */ + .section .text.Default_Handler,"ax",%progbits + .type Default_Handler, %function +Default_Handler: + b . + .size Default_Handler, . - Default_Handler + + .macro IRQ handler + .weak \handler + .set \handler, Default_Handler + .endm + + IRQ WWDGT_IRQHandler + IRQ LVD_IRQHandler + IRQ TAMPER_IRQHandler + IRQ RTC_IRQHandler + IRQ FMC_IRQHandler + IRQ RCU_CTC_IRQHandler + IRQ EXTI0_IRQHandler + IRQ EXTI1_IRQHandler + IRQ EXTI2_IRQHandler + IRQ EXTI3_IRQHandler + IRQ EXTI4_IRQHandler + IRQ DMA0_Channel0_IRQHandler + IRQ DMA0_Channel1_IRQHandler + IRQ DMA0_Channel2_IRQHandler + IRQ DMA0_Channel3_IRQHandler + IRQ DMA0_Channel4_IRQHandler + IRQ DMA0_Channel5_IRQHandler + IRQ DMA0_Channel6_IRQHandler + IRQ ADC0_1_IRQHandler + IRQ USBD_HP_CAN0_TX_IRQHandler + IRQ USBD_LP_CAN0_RX0_IRQHandler + IRQ CAN0_RX1_IRQHandler + IRQ CAN0_EWMC_IRQHandler + IRQ EXTI5_9_IRQHandler + IRQ TIMER0_BRK_IRQHandler + IRQ TIMER0_UP_IRQHandler + IRQ TIMER0_TRG_CMT_IRQHandler + IRQ TIMER0_Channel_IRQHandler + IRQ TIMER1_IRQHandler + IRQ TIMER2_IRQHandler + IRQ TIMER3_IRQHandler + IRQ I2C0_EV_IRQHandler + IRQ I2C0_ER_IRQHandler + IRQ I2C1_EV_IRQHandler + IRQ I2C1_ER_IRQHandler + IRQ SPI0_IRQHandler + IRQ SPI1_IRQHandler + IRQ USART0_IRQHandler + IRQ USART1_IRQHandler + IRQ USART2_IRQHandler + IRQ EXTI10_15_IRQHandler + IRQ RTC_Alarm_IRQHandler + IRQ USBD_WKUP_IRQHandler + IRQ TIMER7_BRK_IRQHandler + IRQ TIMER7_UP_IRQHandler + IRQ TIMER7_TRG_CMT_IRQHandler + IRQ TIMER7_Channel_IRQHandler + IRQ ADC2_IRQHandler + IRQ EXMC_IRQHandler + IRQ SDIO_IRQHandler + IRQ TIMER4_IRQHandler + IRQ SPI2_IRQHandler + IRQ UART3_IRQHandler + IRQ UART4_IRQHandler + IRQ TIMER5_IRQHandler + IRQ TIMER6_IRQHandler + IRQ DMA1_Channel0_IRQHandler + IRQ DMA1_Channel1_IRQHandler + IRQ DMA1_Channel2_IRQHandler + IRQ DMA1_Channel3_IRQHandler + IRQ DMA1_Channel4_IRQHandler + IRQ ENET_IRQHandler + IRQ ENET_WKUP_IRQHandler + IRQ CAN1_TX_IRQHandler + IRQ CAN1_RX0_IRQHandler + IRQ CAN1_RX1_IRQHandler + IRQ CAN1_EWMC_IRQHandler + IRQ USBFS_IRQHandler diff --git a/bsp/gd32/libraries/GD32F10x_Firmware_Library/CMSIS/GD/GD32F10x/Source/GCC/startup_gd32f10x_hd.s b/bsp/gd32/libraries/GD32F10x_Firmware_Library/CMSIS/GD/GD32F10x/Source/GCC/startup_gd32f10x_hd.s new file mode 100644 index 0000000000..023bfa9449 --- /dev/null +++ b/bsp/gd32/libraries/GD32F10x_Firmware_Library/CMSIS/GD/GD32F10x/Source/GCC/startup_gd32f10x_hd.s @@ -0,0 +1,257 @@ +;/* +; * Copyright (c) 2006-2021, RT-Thread Development Team +; * +; * SPDX-License-Identifier: Apache-2.0 +; * +; * Change Logs: +; * Date Author Notes +; * 2021-12-18 BruceOu first implementation +; */ + +.syntax unified +.cpu cortex-m3 +.fpu softvfp +.thumb + +.global g_pfnVectors +.global Default_Handler + + .section .isr_vector,"a",%progbits + .type g_pfnVectors, %object + +g_pfnVectors: + .word _estack // Top of Stack + .word Reset_Handler // Reset Handler + .word NMI_Handler // NMI Handler + .word HardFault_Handler // Hard Fault Handler + .word MemManage_Handler // MPU Fault Handler + .word BusFault_Handler // Bus Fault Handler + .word UsageFault_Handler // Usage Fault Handler + .word 0 // Reserved + .word 0 // Reserved + .word 0 // Reserved + .word 0 // Reserved + .word SVC_Handler // SVCall Handler + .word DebugMon_Handler // Debug Monitor Handler + .word 0 // Reserved + .word PendSV_Handler // PendSV Handler + .word SysTick_Handler // SysTick Handler + + // external interrupts handler + .word WWDGT_IRQHandler // 16:Window Watchdog Timer + .word LVD_IRQHandler // 17:LVD through EXTI Line detect + .word TAMPER_IRQHandler // 18:Tamper through EXTI Line detect + .word RTC_IRQHandler // 19:RTC through EXTI Line + .word FMC_IRQHandler // 20:FMC + .word RCU_CTC_IRQHandler // 21:RCU and CTC + .word EXTI0_IRQHandler // 22:EXTI Line 0 + .word EXTI1_IRQHandler // 23:EXTI Line 1 + .word EXTI2_IRQHandler // 24:EXTI Line 2 + .word EXTI3_IRQHandler // 25:EXTI Line 3 + .word EXTI4_IRQHandler // 26:EXTI Line 4 + .word DMA0_Channel0_IRQHandler // 27:DMA0 Channel0 + .word DMA0_Channel1_IRQHandler // 28:DMA0 Channel1 + .word DMA0_Channel2_IRQHandler // 29:DMA0 Channel2 + .word DMA0_Channel3_IRQHandler // 30:DMA0 Channel3 + .word DMA0_Channel4_IRQHandler // 31:DMA0 Channel4 + .word DMA0_Channel5_IRQHandler // 32:DMA0 Channel5 + .word DMA0_Channel6_IRQHandler // 33:DMA0 Channel6 + .word ADC0_1_IRQHandler // 34:ADC0 and ADC1 + .word USBD_HP_CAN0_TX_IRQHandler // 35:USBD HP and CAN0 TX + .word USBD_LP_CAN0_RX0_IRQHandler // 36:USBD LP and CAN0 RX0 + .word CAN0_RX1_IRQHandler // 37:CAN0 RX1 + .word CAN0_EWMC_IRQHandler // 38:CAN0 EWMC + .word EXTI5_9_IRQHandler // 39:EXTI5 to EXTI9 + .word TIMER0_BRK_IRQHandler // 40:TIMER0 Break + .word TIMER0_UP_IRQHandler // 41:TIMER0 Update + .word TIMER0_TRG_CMT_IRQHandler // 42:TIMER0 Trigger and Commutation + .word TIMER0_Channel_IRQHandler // 43:TIMER0 Channel Capture Compare + .word TIMER1_IRQHandler // 44:TIMER1 + .word TIMER2_IRQHandler // 45:TIMER2 + .word TIMER3_IRQHandler // 46:TIMER3 + .word I2C0_EV_IRQHandler // 47:I2C0 Event + .word I2C0_ER_IRQHandler // 48:I2C0 Error + .word I2C1_EV_IRQHandler // 49:I2C1 Event + .word I2C1_ER_IRQHandler // 50:I2C1 Error + .word SPI0_IRQHandler // 51:SPI0 + .word SPI1_IRQHandler // 52:SPI1 + .word USART0_IRQHandler // 53:USART0 + .word USART1_IRQHandler // 54:USART1 + .word USART2_IRQHandler // 55:USART2 + .word EXTI10_15_IRQHandler // 56:EXTI10 to EXTI15 + .word RTC_Alarm_IRQHandler // 57:RTC Alarm + .word USBD_WKUP_IRQHandler // 58:USBD Wakeup + .word TIMER7_BRK_IRQHandler // 59:TIMER7 Break + .word TIMER7_UP_IRQHandler // 60:TIMER7 Update + .word TIMER7_TRG_CMT_IRQHandler // 61:TIMER7 Trigger and Commutation + .word TIMER7_Channel_IRQHandler // 62:TIMER7 Channel Capture Compare + .word ADC2_IRQHandler // 63:ADC2 + .word EXMC_IRQHandler // 64:EXMC + .word SDIO_IRQHandler // 65:SDIO + .word TIMER4_IRQHandler // 66:TIMER4 + .word SPI2_IRQHandler // 67:SPI2 + .word UART3_IRQHandler // 68:UART3 + .word UART4_IRQHandler // 69:UART4 + .word TIMER5_IRQHandler // 70:TIMER5 + .word TIMER6_IRQHandler // 71:TIMER6 + .word DMA1_Channel0_IRQHandler // 72:DMA1 Channel0 + .word DMA1_Channel1_IRQHandler // 73:DMA1 Channel1 + .word DMA1_Channel2_IRQHandler // 74:DMA1 Channel2 + .word DMA1_Channel3_4_IRQHandler // 75:DMA1 Channel3 and Channel4 + + .size g_pfnVectors, .-g_pfnVectors + + .section .text.Reset_Handler + .weak Reset_Handler + .type Reset_Handler, %function +Reset_Handler: + ldr r1, =_sidata + ldr r2, =_sdata + ldr r3, =_edata + + subs r3, r2 + ble fill_bss_start + +loop_copy_data: + subs r3, #4 + ldr r0, [r1,r3] + str r0, [r2,r3] + bgt loop_copy_data + +fill_bss_start: + ldr r1, =__bss_start + ldr r2, =__bss_end + movs r0, 0 + subs r2, r1 + ble startup_enter + +loop_fill_bss: + subs r2, #4 + str r0, [r1, r2] + bgt loop_fill_bss + +startup_enter: + bl SystemInit + bl entry + + /* Exception Handlers */ + .weak NMI_Handler + .type NMI_Handler, %function +NMI_Handler: + b . + .size NMI_Handler, . - NMI_Handler + + .weak MemManage_Handler + .type MemManage_Handler, %function +MemManage_Handler: + b . + .size MemManage_Handler, . - MemManage_Handler + + .weak BusFault_Handler + .type BusFault_Handler, %function +BusFault_Handler: + b . + .size BusFault_Handler, . - BusFault_Handler + + .weak UsageFault_Handler + .type UsageFault_Handler, %function +UsageFault_Handler: + b . + .size UsageFault_Handler, . - UsageFault_Handler + + .weak SVC_Handler + .type SVC_Handler, %function +SVC_Handler: + b . + .size SVC_Handler, . - SVC_Handler + + .weak DebugMon_Handler + .type DebugMon_Handler, %function +DebugMon_Handler: + b . + .size DebugMon_Handler, . - DebugMon_Handler + + .weak PendSV_Handler + .type PendSV_Handler, %function +PendSV_Handler: + b . + .size PendSV_Handler, . - PendSV_Handler + + .weak SysTick_Handler + .type SysTick_Handler, %function +SysTick_Handler: + b . + .size SysTick_Handler, . - SysTick_Handler + + /* IQR Handler */ + .section .text.Default_Handler,"ax",%progbits + .type Default_Handler, %function +Default_Handler: + b . + .size Default_Handler, . - Default_Handler + + .macro IRQ handler + .weak \handler + .set \handler, Default_Handler + .endm + + IRQ WWDGT_IRQHandler + IRQ LVD_IRQHandler + IRQ TAMPER_IRQHandler + IRQ RTC_IRQHandler + IRQ FMC_IRQHandler + IRQ RCU_CTC_IRQHandler + IRQ EXTI0_IRQHandler + IRQ EXTI1_IRQHandler + IRQ EXTI2_IRQHandler + IRQ EXTI3_IRQHandler + IRQ EXTI4_IRQHandler + IRQ DMA0_Channel0_IRQHandler + IRQ DMA0_Channel1_IRQHandler + IRQ DMA0_Channel2_IRQHandler + IRQ DMA0_Channel3_IRQHandler + IRQ DMA0_Channel4_IRQHandler + IRQ DMA0_Channel5_IRQHandler + IRQ DMA0_Channel6_IRQHandler + IRQ ADC0_1_IRQHandler + IRQ USBD_HP_CAN0_TX_IRQHandler + IRQ USBD_LP_CAN0_RX0_IRQHandler + IRQ CAN0_RX1_IRQHandler + IRQ CAN0_EWMC_IRQHandler + IRQ EXTI5_9_IRQHandler + IRQ TIMER0_BRK_IRQHandler + IRQ TIMER0_UP_IRQHandler + IRQ TIMER0_TRG_CMT_IRQHandler + IRQ TIMER0_Channel_IRQHandler + IRQ TIMER1_IRQHandler + IRQ TIMER2_IRQHandler + IRQ TIMER3_IRQHandler + IRQ I2C0_EV_IRQHandler + IRQ I2C0_ER_IRQHandler + IRQ I2C1_EV_IRQHandler + IRQ I2C1_ER_IRQHandler + IRQ SPI0_IRQHandler + IRQ SPI1_IRQHandler + IRQ USART0_IRQHandler + IRQ USART1_IRQHandler + IRQ USART2_IRQHandler + IRQ EXTI10_15_IRQHandler + IRQ RTC_Alarm_IRQHandler + IRQ USBD_WKUP_IRQHandler + IRQ TIMER7_BRK_IRQHandler + IRQ TIMER7_UP_IRQHandler + IRQ TIMER7_TRG_CMT_IRQHandler + IRQ TIMER7_Channel_IRQHandler + IRQ ADC2_IRQHandler + IRQ EXMC_IRQHandler + IRQ SDIO_IRQHandler + IRQ TIMER4_IRQHandler + IRQ SPI2_IRQHandler + IRQ UART3_IRQHandler + IRQ UART4_IRQHandler + IRQ TIMER5_IRQHandler + IRQ TIMER6_IRQHandler + IRQ DMA1_Channel0_IRQHandler + IRQ DMA1_Channel1_IRQHandler + IRQ DMA1_Channel2_IRQHandler + IRQ DMA1_Channel3_4_IRQHandler diff --git a/bsp/gd32/libraries/GD32F10x_Firmware_Library/CMSIS/GD/GD32F10x/Source/GCC/startup_gd32f10x_md.s b/bsp/gd32/libraries/GD32F10x_Firmware_Library/CMSIS/GD/GD32F10x/Source/GCC/startup_gd32f10x_md.s new file mode 100644 index 0000000000..71c3711013 --- /dev/null +++ b/bsp/gd32/libraries/GD32F10x_Firmware_Library/CMSIS/GD/GD32F10x/Source/GCC/startup_gd32f10x_md.s @@ -0,0 +1,230 @@ +;/* +; * Copyright (c) 2006-2021, RT-Thread Development Team +; * +; * SPDX-License-Identifier: Apache-2.0 +; * +; * Change Logs: +; * Date Author Notes +; * 2021-12-18 BruceOu first implementation +; */ + +.syntax unified +.cpu cortex-m3 +.fpu softvfp +.thumb + +.global g_pfnVectors +.global Default_Handler + + .section .isr_vector,"a",%progbits + .type g_pfnVectors, %object + +g_pfnVectors: + .word _estack // Top of Stack + .word Reset_Handler // Reset Handler + .word NMI_Handler // NMI Handler + .word HardFault_Handler // Hard Fault Handler + .word MemManage_Handler // MPU Fault Handler + .word BusFault_Handler // Bus Fault Handler + .word UsageFault_Handler // Usage Fault Handler + .word 0 // Reserved + .word 0 // Reserved + .word 0 // Reserved + .word 0 // Reserved + .word SVC_Handler // SVCall Handler + .word DebugMon_Handler // Debug Monitor Handler + .word 0 // Reserved + .word PendSV_Handler // PendSV Handler + .word SysTick_Handler // SysTick Handler + + // external interrupts handler + .word WWDGT_IRQHandler // 16:Window Watchdog Timer + .word LVD_IRQHandler // 17:LVD through EXTI Line detect + .word TAMPER_IRQHandler // 18:Tamper through EXTI Line detect + .word RTC_IRQHandler // 19:RTC through EXTI Line + .word FMC_IRQHandler // 20:FMC + .word RCU_CTC_IRQHandler // 21:RCU and CTC + .word EXTI0_IRQHandler // 22:EXTI Line 0 + .word EXTI1_IRQHandler // 23:EXTI Line 1 + .word EXTI2_IRQHandler // 24:EXTI Line 2 + .word EXTI3_IRQHandler // 25:EXTI Line 3 + .word EXTI4_IRQHandler // 26:EXTI Line 4 + .word DMA0_Channel0_IRQHandler // 27:DMA0 Channel0 + .word DMA0_Channel1_IRQHandler // 28:DMA0 Channel1 + .word DMA0_Channel2_IRQHandler // 29:DMA0 Channel2 + .word DMA0_Channel3_IRQHandler // 30:DMA0 Channel3 + .word DMA0_Channel4_IRQHandler // 31:DMA0 Channel4 + .word DMA0_Channel5_IRQHandler // 32:DMA0 Channel5 + .word DMA0_Channel6_IRQHandler // 33:DMA0 Channel6 + .word ADC0_1_IRQHandler // 34:ADC0 and ADC1 + .word USBD_HP_CAN0_TX_IRQHandler // 35:USBD HP and CAN0 TX + .word USBD_LP_CAN0_RX0_IRQHandler // 36:USBD LP and CAN0 RX0 + .word CAN0_RX1_IRQHandler // 37:CAN0 RX1 + .word CAN0_EWMC_IRQHandler // 38:CAN0 EWMC + .word EXTI5_9_IRQHandler // 39:EXTI5 to EXTI9 + .word TIMER0_BRK_IRQHandler // 40:TIMER0 Break + .word TIMER0_UP_IRQHandler // 41:TIMER0 Update + .word TIMER0_TRG_CMT_IRQHandler // 42:TIMER0 Trigger and Commutation + .word TIMER0_Channel_IRQHandler // 43:TIMER0 Channel Capture Compare + .word TIMER1_IRQHandler // 44:TIMER1 + .word TIMER2_IRQHandler // 45:TIMER2 + .word TIMER3_IRQHandler // 46:TIMER3 + .word I2C0_EV_IRQHandler // 47:I2C0 Event + .word I2C0_ER_IRQHandler // 48:I2C0 Error + .word I2C1_EV_IRQHandler // 49:I2C1 Event + .word I2C1_ER_IRQHandler // 50:I2C1 Error + .word SPI0_IRQHandler // 51:SPI0 + .word SPI1_IRQHandler // 52:SPI1 + .word USART0_IRQHandler // 53:USART0 + .word USART1_IRQHandler // 54:USART1 + .word USART2_IRQHandler // 55:USART2 + .word EXTI10_15_IRQHandler // 56:EXTI Line 10 to EXTI Line 15 + .word RTC_Alarm_IRQHandler // 57:RTC Alarm through EXTI Line + .word USBD_WKUP_IRQHandler // 58:USBD WakeUp from suspend through EXTI Line + .word 0 // 59:Reserved + .word 0 // 60:Reserved + .word 0 // 61:Reserved + .word 0 // 62:Reserved + .word 0 // 63:Reserved + .word EXMC_IRQHandler // 64:EXMC + + .size g_pfnVectors, .-g_pfnVectors + + .section .text.Reset_Handler + .weak Reset_Handler + .type Reset_Handler, %function +Reset_Handler: + ldr r1, =_sidata + ldr r2, =_sdata + ldr r3, =_edata + + subs r3, r2 + ble fill_bss_start + +loop_copy_data: + subs r3, #4 + ldr r0, [r1,r3] + str r0, [r2,r3] + bgt loop_copy_data + +fill_bss_start: + ldr r1, =__bss_start + ldr r2, =__bss_end + movs r0, 0 + subs r2, r1 + ble startup_enter + +loop_fill_bss: + subs r2, #4 + str r0, [r1, r2] + bgt loop_fill_bss + +startup_enter: + bl SystemInit + bl entry + + /* Exception Handlers */ + .weak NMI_Handler + .type NMI_Handler, %function +NMI_Handler: + b . + .size NMI_Handler, . - NMI_Handler + + .weak MemManage_Handler + .type MemManage_Handler, %function +MemManage_Handler: + b . + .size MemManage_Handler, . - MemManage_Handler + + .weak BusFault_Handler + .type BusFault_Handler, %function +BusFault_Handler: + b . + .size BusFault_Handler, . - BusFault_Handler + + .weak UsageFault_Handler + .type UsageFault_Handler, %function +UsageFault_Handler: + b . + .size UsageFault_Handler, . - UsageFault_Handler + + .weak SVC_Handler + .type SVC_Handler, %function +SVC_Handler: + b . + .size SVC_Handler, . - SVC_Handler + + .weak DebugMon_Handler + .type DebugMon_Handler, %function +DebugMon_Handler: + b . + .size DebugMon_Handler, . - DebugMon_Handler + + .weak PendSV_Handler + .type PendSV_Handler, %function +PendSV_Handler: + b . + .size PendSV_Handler, . - PendSV_Handler + + .weak SysTick_Handler + .type SysTick_Handler, %function +SysTick_Handler: + b . + .size SysTick_Handler, . - SysTick_Handler + + /* IQR Handler */ + .section .text.Default_Handler,"ax",%progbits + .type Default_Handler, %function +Default_Handler: + b . + .size Default_Handler, . - Default_Handler + + .macro IRQ handler + .weak \handler + .set \handler, Default_Handler + .endm + + IRQ WWDGT_IRQHandler + IRQ LVD_IRQHandler + IRQ TAMPER_IRQHandler + IRQ RTC_IRQHandler + IRQ FMC_IRQHandler + IRQ RCU_CTC_IRQHandler + IRQ EXTI0_IRQHandler + IRQ EXTI1_IRQHandler + IRQ EXTI2_IRQHandler + IRQ EXTI3_IRQHandler + IRQ EXTI4_IRQHandler + IRQ DMA0_Channel0_IRQHandler + IRQ DMA0_Channel1_IRQHandler + IRQ DMA0_Channel2_IRQHandler + IRQ DMA0_Channel3_IRQHandler + IRQ DMA0_Channel4_IRQHandler + IRQ DMA0_Channel5_IRQHandler + IRQ DMA0_Channel6_IRQHandler + IRQ ADC0_1_IRQHandler + IRQ USBD_HP_CAN0_TX_IRQHandler + IRQ USBD_LP_CAN0_RX0_IRQHandler + IRQ CAN0_RX1_IRQHandler + IRQ CAN0_EWMC_IRQHandler + IRQ EXTI5_9_IRQHandler + IRQ TIMER0_BRK_IRQHandler + IRQ TIMER0_UP_IRQHandler + IRQ TIMER0_TRG_CMT_IRQHandler + IRQ TIMER0_Channel_IRQHandler + IRQ TIMER1_IRQHandler + IRQ TIMER2_IRQHandler + IRQ TIMER3_IRQHandler + IRQ I2C0_EV_IRQHandler + IRQ I2C0_ER_IRQHandler + IRQ I2C1_EV_IRQHandler + IRQ I2C1_ER_IRQHandler + IRQ SPI0_IRQHandler + IRQ SPI1_IRQHandler + IRQ USART0_IRQHandler + IRQ USART1_IRQHandler + IRQ USART2_IRQHandler + IRQ EXTI10_15_IRQHandler + IRQ RTC_Alarm_IRQHandler + IRQ USBD_WKUP_IRQHandler + IRQ EXMC_IRQHandler diff --git a/bsp/gd32/libraries/GD32F10x_Firmware_Library/CMSIS/GD/GD32F10x/Source/GCC/startup_gd32f10x_xd.s b/bsp/gd32/libraries/GD32F10x_Firmware_Library/CMSIS/GD/GD32F10x/Source/GCC/startup_gd32f10x_xd.s new file mode 100644 index 0000000000..023bfa9449 --- /dev/null +++ b/bsp/gd32/libraries/GD32F10x_Firmware_Library/CMSIS/GD/GD32F10x/Source/GCC/startup_gd32f10x_xd.s @@ -0,0 +1,257 @@ +;/* +; * Copyright (c) 2006-2021, RT-Thread Development Team +; * +; * SPDX-License-Identifier: Apache-2.0 +; * +; * Change Logs: +; * Date Author Notes +; * 2021-12-18 BruceOu first implementation +; */ + +.syntax unified +.cpu cortex-m3 +.fpu softvfp +.thumb + +.global g_pfnVectors +.global Default_Handler + + .section .isr_vector,"a",%progbits + .type g_pfnVectors, %object + +g_pfnVectors: + .word _estack // Top of Stack + .word Reset_Handler // Reset Handler + .word NMI_Handler // NMI Handler + .word HardFault_Handler // Hard Fault Handler + .word MemManage_Handler // MPU Fault Handler + .word BusFault_Handler // Bus Fault Handler + .word UsageFault_Handler // Usage Fault Handler + .word 0 // Reserved + .word 0 // Reserved + .word 0 // Reserved + .word 0 // Reserved + .word SVC_Handler // SVCall Handler + .word DebugMon_Handler // Debug Monitor Handler + .word 0 // Reserved + .word PendSV_Handler // PendSV Handler + .word SysTick_Handler // SysTick Handler + + // external interrupts handler + .word WWDGT_IRQHandler // 16:Window Watchdog Timer + .word LVD_IRQHandler // 17:LVD through EXTI Line detect + .word TAMPER_IRQHandler // 18:Tamper through EXTI Line detect + .word RTC_IRQHandler // 19:RTC through EXTI Line + .word FMC_IRQHandler // 20:FMC + .word RCU_CTC_IRQHandler // 21:RCU and CTC + .word EXTI0_IRQHandler // 22:EXTI Line 0 + .word EXTI1_IRQHandler // 23:EXTI Line 1 + .word EXTI2_IRQHandler // 24:EXTI Line 2 + .word EXTI3_IRQHandler // 25:EXTI Line 3 + .word EXTI4_IRQHandler // 26:EXTI Line 4 + .word DMA0_Channel0_IRQHandler // 27:DMA0 Channel0 + .word DMA0_Channel1_IRQHandler // 28:DMA0 Channel1 + .word DMA0_Channel2_IRQHandler // 29:DMA0 Channel2 + .word DMA0_Channel3_IRQHandler // 30:DMA0 Channel3 + .word DMA0_Channel4_IRQHandler // 31:DMA0 Channel4 + .word DMA0_Channel5_IRQHandler // 32:DMA0 Channel5 + .word DMA0_Channel6_IRQHandler // 33:DMA0 Channel6 + .word ADC0_1_IRQHandler // 34:ADC0 and ADC1 + .word USBD_HP_CAN0_TX_IRQHandler // 35:USBD HP and CAN0 TX + .word USBD_LP_CAN0_RX0_IRQHandler // 36:USBD LP and CAN0 RX0 + .word CAN0_RX1_IRQHandler // 37:CAN0 RX1 + .word CAN0_EWMC_IRQHandler // 38:CAN0 EWMC + .word EXTI5_9_IRQHandler // 39:EXTI5 to EXTI9 + .word TIMER0_BRK_IRQHandler // 40:TIMER0 Break + .word TIMER0_UP_IRQHandler // 41:TIMER0 Update + .word TIMER0_TRG_CMT_IRQHandler // 42:TIMER0 Trigger and Commutation + .word TIMER0_Channel_IRQHandler // 43:TIMER0 Channel Capture Compare + .word TIMER1_IRQHandler // 44:TIMER1 + .word TIMER2_IRQHandler // 45:TIMER2 + .word TIMER3_IRQHandler // 46:TIMER3 + .word I2C0_EV_IRQHandler // 47:I2C0 Event + .word I2C0_ER_IRQHandler // 48:I2C0 Error + .word I2C1_EV_IRQHandler // 49:I2C1 Event + .word I2C1_ER_IRQHandler // 50:I2C1 Error + .word SPI0_IRQHandler // 51:SPI0 + .word SPI1_IRQHandler // 52:SPI1 + .word USART0_IRQHandler // 53:USART0 + .word USART1_IRQHandler // 54:USART1 + .word USART2_IRQHandler // 55:USART2 + .word EXTI10_15_IRQHandler // 56:EXTI10 to EXTI15 + .word RTC_Alarm_IRQHandler // 57:RTC Alarm + .word USBD_WKUP_IRQHandler // 58:USBD Wakeup + .word TIMER7_BRK_IRQHandler // 59:TIMER7 Break + .word TIMER7_UP_IRQHandler // 60:TIMER7 Update + .word TIMER7_TRG_CMT_IRQHandler // 61:TIMER7 Trigger and Commutation + .word TIMER7_Channel_IRQHandler // 62:TIMER7 Channel Capture Compare + .word ADC2_IRQHandler // 63:ADC2 + .word EXMC_IRQHandler // 64:EXMC + .word SDIO_IRQHandler // 65:SDIO + .word TIMER4_IRQHandler // 66:TIMER4 + .word SPI2_IRQHandler // 67:SPI2 + .word UART3_IRQHandler // 68:UART3 + .word UART4_IRQHandler // 69:UART4 + .word TIMER5_IRQHandler // 70:TIMER5 + .word TIMER6_IRQHandler // 71:TIMER6 + .word DMA1_Channel0_IRQHandler // 72:DMA1 Channel0 + .word DMA1_Channel1_IRQHandler // 73:DMA1 Channel1 + .word DMA1_Channel2_IRQHandler // 74:DMA1 Channel2 + .word DMA1_Channel3_4_IRQHandler // 75:DMA1 Channel3 and Channel4 + + .size g_pfnVectors, .-g_pfnVectors + + .section .text.Reset_Handler + .weak Reset_Handler + .type Reset_Handler, %function +Reset_Handler: + ldr r1, =_sidata + ldr r2, =_sdata + ldr r3, =_edata + + subs r3, r2 + ble fill_bss_start + +loop_copy_data: + subs r3, #4 + ldr r0, [r1,r3] + str r0, [r2,r3] + bgt loop_copy_data + +fill_bss_start: + ldr r1, =__bss_start + ldr r2, =__bss_end + movs r0, 0 + subs r2, r1 + ble startup_enter + +loop_fill_bss: + subs r2, #4 + str r0, [r1, r2] + bgt loop_fill_bss + +startup_enter: + bl SystemInit + bl entry + + /* Exception Handlers */ + .weak NMI_Handler + .type NMI_Handler, %function +NMI_Handler: + b . + .size NMI_Handler, . - NMI_Handler + + .weak MemManage_Handler + .type MemManage_Handler, %function +MemManage_Handler: + b . + .size MemManage_Handler, . - MemManage_Handler + + .weak BusFault_Handler + .type BusFault_Handler, %function +BusFault_Handler: + b . + .size BusFault_Handler, . - BusFault_Handler + + .weak UsageFault_Handler + .type UsageFault_Handler, %function +UsageFault_Handler: + b . + .size UsageFault_Handler, . - UsageFault_Handler + + .weak SVC_Handler + .type SVC_Handler, %function +SVC_Handler: + b . + .size SVC_Handler, . - SVC_Handler + + .weak DebugMon_Handler + .type DebugMon_Handler, %function +DebugMon_Handler: + b . + .size DebugMon_Handler, . - DebugMon_Handler + + .weak PendSV_Handler + .type PendSV_Handler, %function +PendSV_Handler: + b . + .size PendSV_Handler, . - PendSV_Handler + + .weak SysTick_Handler + .type SysTick_Handler, %function +SysTick_Handler: + b . + .size SysTick_Handler, . - SysTick_Handler + + /* IQR Handler */ + .section .text.Default_Handler,"ax",%progbits + .type Default_Handler, %function +Default_Handler: + b . + .size Default_Handler, . - Default_Handler + + .macro IRQ handler + .weak \handler + .set \handler, Default_Handler + .endm + + IRQ WWDGT_IRQHandler + IRQ LVD_IRQHandler + IRQ TAMPER_IRQHandler + IRQ RTC_IRQHandler + IRQ FMC_IRQHandler + IRQ RCU_CTC_IRQHandler + IRQ EXTI0_IRQHandler + IRQ EXTI1_IRQHandler + IRQ EXTI2_IRQHandler + IRQ EXTI3_IRQHandler + IRQ EXTI4_IRQHandler + IRQ DMA0_Channel0_IRQHandler + IRQ DMA0_Channel1_IRQHandler + IRQ DMA0_Channel2_IRQHandler + IRQ DMA0_Channel3_IRQHandler + IRQ DMA0_Channel4_IRQHandler + IRQ DMA0_Channel5_IRQHandler + IRQ DMA0_Channel6_IRQHandler + IRQ ADC0_1_IRQHandler + IRQ USBD_HP_CAN0_TX_IRQHandler + IRQ USBD_LP_CAN0_RX0_IRQHandler + IRQ CAN0_RX1_IRQHandler + IRQ CAN0_EWMC_IRQHandler + IRQ EXTI5_9_IRQHandler + IRQ TIMER0_BRK_IRQHandler + IRQ TIMER0_UP_IRQHandler + IRQ TIMER0_TRG_CMT_IRQHandler + IRQ TIMER0_Channel_IRQHandler + IRQ TIMER1_IRQHandler + IRQ TIMER2_IRQHandler + IRQ TIMER3_IRQHandler + IRQ I2C0_EV_IRQHandler + IRQ I2C0_ER_IRQHandler + IRQ I2C1_EV_IRQHandler + IRQ I2C1_ER_IRQHandler + IRQ SPI0_IRQHandler + IRQ SPI1_IRQHandler + IRQ USART0_IRQHandler + IRQ USART1_IRQHandler + IRQ USART2_IRQHandler + IRQ EXTI10_15_IRQHandler + IRQ RTC_Alarm_IRQHandler + IRQ USBD_WKUP_IRQHandler + IRQ TIMER7_BRK_IRQHandler + IRQ TIMER7_UP_IRQHandler + IRQ TIMER7_TRG_CMT_IRQHandler + IRQ TIMER7_Channel_IRQHandler + IRQ ADC2_IRQHandler + IRQ EXMC_IRQHandler + IRQ SDIO_IRQHandler + IRQ TIMER4_IRQHandler + IRQ SPI2_IRQHandler + IRQ UART3_IRQHandler + IRQ UART4_IRQHandler + IRQ TIMER5_IRQHandler + IRQ TIMER6_IRQHandler + IRQ DMA1_Channel0_IRQHandler + IRQ DMA1_Channel1_IRQHandler + IRQ DMA1_Channel2_IRQHandler + IRQ DMA1_Channel3_4_IRQHandler diff --git a/bsp/gd32/libraries/GD32F10x_Firmware_Library/CMSIS/GD/GD32F10x/Source/IAR/startup_gd32f10x_cl.s b/bsp/gd32/libraries/GD32F10x_Firmware_Library/CMSIS/GD/GD32F10x/Source/IAR/startup_gd32f10x_cl.s new file mode 100644 index 0000000000..76480fb238 --- /dev/null +++ b/bsp/gd32/libraries/GD32F10x_Firmware_Library/CMSIS/GD/GD32F10x/Source/IAR/startup_gd32f10x_cl.s @@ -0,0 +1,528 @@ +;/*! +; \file startup_gd32f10x_cl.s +; \brief start up file +; +; \version 2014-12-26, V1.0.0, firmware for GD32F10x +; \version 2017-06-20, V2.0.0, firmware for GD32F10x +; \version 2018-07-31, V2.1.0, firmware for GD32F10x +; \version 2020-09-30, V2.2.0, firmware for GD32F10x +;*/ + +;/* + ;Copyright (c) 2020, GigaDevice Semiconductor Inc. + + ;Redistribution and use in source and binary forms, with or without modification, +;are permitted provided that the following conditions are met: + + ;1. Redistributions of source code must retain the above copyright notice, this + ;list of conditions and the following disclaimer. + ;2. Redistributions in binary form must reproduce the above copyright notice, + ;this list of conditions and the following disclaimer in the documentation + ;and/or other materials provided with the distribution. + ;3. Neither the name of the copyright holder nor the names of its contributors + ;may be used to endorse or promote products derived from this software without + ;specific prior written permission. + + ;THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +;AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +;WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +;IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +;INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +;NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +;PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +;WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +;ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +;OF SUCH DAMAGE. +;*/ + + MODULE ?cstartup + + ;; Forward declaration of sections. + SECTION CSTACK:DATA:NOROOT(3) + + SECTION .intvec:CODE:NOROOT(2) + + EXTERN __iar_program_start + EXTERN SystemInit + PUBLIC __vector_table + + DATA +__vector_table + DCD sfe(CSTACK) ; top of stack + DCD Reset_Handler ; Reset Handler + + DCD NMI_Handler ; NMI Handler + DCD HardFault_Handler ; Hard Fault Handler + DCD MemManage_Handler ; MPU Fault Handler + DCD BusFault_Handler ; Bus Fault Handler + DCD UsageFault_Handler ; Usage Fault Handler + DCD 0 ; Reserved + DCD 0 ; Reserved + DCD 0 ; Reserved + DCD 0 ; Reserved + DCD SVC_Handler ; SVCall Handler + DCD DebugMon_Handler ; Debug Monitor Handler + DCD 0 ; Reserved + DCD PendSV_Handler ; PendSV Handler + DCD SysTick_Handler ; SysTick Handler + + ; External Interrupts + DCD WWDGT_IRQHandler ; Vector Number 16,Window Watchdog Timer + DCD LVD_IRQHandler ; Vector Number 17,LVD through EXTI Line detect + DCD TAMPER_IRQHandler ; Vector Number 18,Tamper Interrupt + DCD RTC_IRQHandler ; Vector Number 19,RTC through EXTI Line + DCD FMC_IRQHandler ; Vector Number 20,FMC + DCD RCU_IRQHandler ; Vector Number 21,RCU + DCD EXTI0_IRQHandler ; Vector Number 22,EXTI Line 0 + DCD EXTI1_IRQHandler ; Vector Number 23,EXTI Line 1 + DCD EXTI2_IRQHandler ; Vector Number 24,EXTI Line 2 + DCD EXTI3_IRQHandler ; Vector Number 25,EXTI Line 3 + DCD EXTI4_IRQHandler ; Vector Number 26,EXTI Line 4 + DCD DMA0_Channel0_IRQHandler ; Vector Number 27,DMA0 Channel 0 + DCD DMA0_Channel1_IRQHandler ; Vector Number 28,DMA0 Channel 1 + DCD DMA0_Channel2_IRQHandler ; Vector Number 29,DMA0 Channel 2 + DCD DMA0_Channel3_IRQHandler ; Vector Number 30,DMA0 Channel 3 + DCD DMA0_Channel4_IRQHandler ; Vector Number 31,DMA0 Channel 4 + DCD DMA0_Channel5_IRQHandler ; Vector Number 32,DMA0 Channel 5 + DCD DMA0_Channel6_IRQHandler ; Vector Number 33,DMA0 Channel 6 + DCD ADC0_1_IRQHandler ; Vector Number 34,ADC0 and ADC1 + DCD CAN0_TX_IRQHandler ; Vector Number 35,CAN0 TX + DCD CAN0_RX0_IRQHandler ; Vector Number 36,CAN0 RX0 + DCD CAN0_RX1_IRQHandler ; Vector Number 37,CAN0 RX1 + DCD CAN0_EWMC_IRQHandler ; Vector Number 38,CAN0 EWMC + DCD EXTI5_9_IRQHandler ; Vector Number 39,EXTI Line 5 to EXTI Line 9 + DCD TIMER0_BRK_IRQHandler ; Vector Number 40,TIMER0 Break + DCD TIMER0_UP_IRQHandler ; Vector Number 41,TIMER0 Update + DCD TIMER0_TRG_CMT_IRQHandler ; Vector Number 42,TIMER0 Trigger and Commutation + DCD TIMER0_Channel_IRQHandler ; Vector Number 43,TIMER0 Channel Capture Compare + DCD TIMER1_IRQHandler ; Vector Number 44,TIMER1 + DCD TIMER2_IRQHandler ; Vector Number 45,TIMER2 + DCD TIMER3_IRQHandler ; Vector Number 46,TIMER3 + DCD I2C0_EV_IRQHandler ; Vector Number 47,I2C0 Event + DCD I2C0_ER_IRQHandler ; Vector Number 48,I2C0 Error + DCD I2C1_EV_IRQHandler ; Vector Number 49,I2C1 Event + DCD I2C1_ER_IRQHandler ; Vector Number 50,I2C1 Error + DCD SPI0_IRQHandler ; Vector Number 51,SPI0 + DCD SPI1_IRQHandler ; Vector Number 52,SPI1 + DCD USART0_IRQHandler ; Vector Number 53,USART0 + DCD USART1_IRQHandler ; Vector Number 54,USART1 + DCD USART2_IRQHandler ; Vector Number 55,USART2 + DCD EXTI10_15_IRQHandler ; Vector Number 56,EXTI Line 10 to EXTI Line 15 + DCD RTC_Alarm_IRQHandler ; Vector Number 57,RTC Alarm through EXTI Line + DCD USBFS_WKUP_IRQHandler ; Vector Number 58,USBFS WakeUp from suspend through EXTI Line + DCD TIMER7_BRK_IRQHandler ; Vector Number 59,TIMER7 Break Interrupt + DCD TIMER7_UP_IRQHandler ; Vector Number 60,TIMER7 Update Interrupt + DCD TIMER7_TRG_CMT_IRQHandler ; Vector Number 61,TIMER7 Trigger and Commutation Interrupt + DCD TIMER7_Channel_IRQHandler ; Vector Number 62,TIMER7 Channel Capture Compare + DCD 0 ; Reserved + DCD EXMC_IRQHandler ; Vector Number 64,EXMC + DCD 0 ; Reserved + DCD TIMER4_IRQHandler ; Vector Number 66,TIMER4 + DCD SPI2_IRQHandler ; Vector Number 67,SPI2 + DCD UART3_IRQHandler ; Vector Number 68,UART3 + DCD UART4_IRQHandler ; Vector Number 69,UART4 + DCD TIMER5_IRQHandler ; Vector Number 70,TIMER5 + DCD TIMER6_IRQHandler ; Vector Number 71,TIMER6 + DCD DMA1_Channel0_IRQHandler ; Vector Number 72,DMA1 Channel0 + DCD DMA1_Channel1_IRQHandler ; Vector Number 73,DMA1 Channel1 + DCD DMA1_Channel2_IRQHandler ; Vector Number 74,DMA1 Channel2 + DCD DMA1_Channel3_IRQHandler ; Vector Number 75,DMA1 Channel3 + DCD DMA1_Channel4_IRQHandler ; Vector Number 76,DMA1 Channel4 + DCD ENET_IRQHandler ; Vector Number 77,Ethernet + DCD ENET_WKUP_IRQHandler ; Vector Number 78,Ethernet Wakeup through EXTI line + DCD CAN1_TX_IRQHandler ; Vector Number 79,CAN1 TX + DCD CAN1_RX0_IRQHandler ; Vector Number 80,CAN1 RX0 + DCD CAN1_RX1_IRQHandler ; Vector Number 81,CAN1 RX1 + DCD CAN1_EWMC_IRQHandler ; Vector Number 82,CAN1 EWMC + DCD USBFS_IRQHandler ; Vector Number 83,USBFS +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; +;; Default interrupt handlers. +;; + THUMB + + PUBWEAK Reset_Handler + SECTION .text:CODE:NOROOT:REORDER(2) +Reset_Handler + LDR R0, = SystemInit + BLX R0 + LDR R0, =__iar_program_start + BX R0 + + PUBWEAK NMI_Handler + SECTION .text:CODE:NOROOT:REORDER(1) +NMI_Handler + B NMI_Handler + + PUBWEAK HardFault_Handler + SECTION .text:CODE:NOROOT:REORDER(1) +HardFault_Handler + B HardFault_Handler + + PUBWEAK MemManage_Handler + SECTION .text:CODE:NOROOT:REORDER(1) +MemManage_Handler + B MemManage_Handler + + PUBWEAK BusFault_Handler + SECTION .text:CODE:NOROOT:REORDER(1) +BusFault_Handler + B BusFault_Handler + + PUBWEAK UsageFault_Handler + SECTION .text:CODE:NOROOT:REORDER(1) +UsageFault_Handler + B UsageFault_Handler + + PUBWEAK SVC_Handler + SECTION .text:CODE:NOROOT:REORDER(1) +SVC_Handler + B SVC_Handler + + PUBWEAK DebugMon_Handler + SECTION .text:CODE:NOROOT:REORDER(1) +DebugMon_Handler + B DebugMon_Handler + + PUBWEAK PendSV_Handler + SECTION .text:CODE:NOROOT:REORDER(1) +PendSV_Handler + B PendSV_Handler + + PUBWEAK SysTick_Handler + SECTION .text:CODE:NOROOT:REORDER(1) +SysTick_Handler + B SysTick_Handler + + PUBWEAK WWDGT_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +WWDGT_IRQHandler + B WWDGT_IRQHandler + + PUBWEAK LVD_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +LVD_IRQHandler + B LVD_IRQHandler + + PUBWEAK TAMPER_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +TAMPER_IRQHandler + B TAMPER_IRQHandler + + PUBWEAK RTC_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +RTC_IRQHandler + B RTC_IRQHandler + + PUBWEAK FMC_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +FMC_IRQHandler + B FMC_IRQHandler + + PUBWEAK RCU_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +RCU_IRQHandler + B RCU_IRQHandler + + PUBWEAK EXTI0_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +EXTI0_IRQHandler + B EXTI0_IRQHandler + + PUBWEAK EXTI1_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +EXTI1_IRQHandler + B EXTI1_IRQHandler + + PUBWEAK EXTI2_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +EXTI2_IRQHandler + B EXTI2_IRQHandler + + PUBWEAK EXTI3_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +EXTI3_IRQHandler + B EXTI3_IRQHandler + + PUBWEAK EXTI4_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +EXTI4_IRQHandler + B EXTI4_IRQHandler + + PUBWEAK DMA0_Channel0_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +DMA0_Channel0_IRQHandler + B DMA0_Channel0_IRQHandler + + PUBWEAK DMA0_Channel1_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +DMA0_Channel1_IRQHandler + B DMA0_Channel1_IRQHandler + + PUBWEAK DMA0_Channel2_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +DMA0_Channel2_IRQHandler + B DMA0_Channel2_IRQHandler + + PUBWEAK DMA0_Channel3_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +DMA0_Channel3_IRQHandler + B DMA0_Channel3_IRQHandler + + PUBWEAK DMA0_Channel4_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +DMA0_Channel4_IRQHandler + B DMA0_Channel4_IRQHandler + + PUBWEAK DMA0_Channel5_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +DMA0_Channel5_IRQHandler + B DMA0_Channel5_IRQHandler + + PUBWEAK DMA0_Channel6_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +DMA0_Channel6_IRQHandler + B DMA0_Channel6_IRQHandler + + PUBWEAK ADC0_1_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +ADC0_1_IRQHandler + B ADC0_1_IRQHandler + + PUBWEAK CAN0_TX_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +CAN0_TX_IRQHandler + B CAN0_TX_IRQHandler + + PUBWEAK CAN0_RX0_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +CAN0_RX0_IRQHandler + B CAN0_RX0_IRQHandler + + PUBWEAK CAN0_RX1_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +CAN0_RX1_IRQHandler + B CAN0_RX1_IRQHandler + + PUBWEAK CAN0_EWMC_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +CAN0_EWMC_IRQHandler + B CAN0_EWMC_IRQHandler + + PUBWEAK EXTI5_9_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +EXTI5_9_IRQHandler + B EXTI5_9_IRQHandler + + PUBWEAK TIMER0_BRK_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +TIMER0_BRK_IRQHandler + B TIMER0_BRK_IRQHandler + + PUBWEAK TIMER0_UP_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +TIMER0_UP_IRQHandler + B TIMER0_UP_IRQHandler + + PUBWEAK TIMER0_TRG_CMT_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +TIMER0_TRG_CMT_IRQHandler + B TIMER0_TRG_CMT_IRQHandler + + PUBWEAK TIMER0_Channel_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +TIMER0_Channel_IRQHandler + B TIMER0_Channel_IRQHandler + + PUBWEAK TIMER1_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +TIMER1_IRQHandler + B TIMER1_IRQHandler + + PUBWEAK TIMER2_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +TIMER2_IRQHandler + B TIMER2_IRQHandler + + PUBWEAK TIMER3_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +TIMER3_IRQHandler + B TIMER3_IRQHandler + + PUBWEAK I2C0_EV_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +I2C0_EV_IRQHandler + B I2C0_EV_IRQHandler + + PUBWEAK I2C0_ER_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +I2C0_ER_IRQHandler + B I2C0_ER_IRQHandler + + PUBWEAK I2C1_EV_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +I2C1_EV_IRQHandler + B I2C1_EV_IRQHandler + + PUBWEAK I2C1_ER_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +I2C1_ER_IRQHandler + B I2C1_ER_IRQHandler + + PUBWEAK SPI0_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +SPI0_IRQHandler + B SPI0_IRQHandler + + PUBWEAK SPI1_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +SPI1_IRQHandler + B SPI1_IRQHandler + + PUBWEAK USART0_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +USART0_IRQHandler + B USART0_IRQHandler + + PUBWEAK USART1_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +USART1_IRQHandler + B USART1_IRQHandler + + PUBWEAK USART2_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +USART2_IRQHandler + B USART2_IRQHandler + + PUBWEAK EXTI10_15_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +EXTI10_15_IRQHandler + B EXTI10_15_IRQHandler + + PUBWEAK RTC_Alarm_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +RTC_Alarm_IRQHandler + B RTC_Alarm_IRQHandler + + PUBWEAK USBFS_WKUP_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +USBFS_WKUP_IRQHandler + B USBFS_WKUP_IRQHandler + + PUBWEAK TIMER7_BRK_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +TIMER7_BRK_IRQHandler + B TIMER7_BRK_IRQHandler + + PUBWEAK TIMER7_UP_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +TIMER7_UP_IRQHandler + B TIMER7_UP_IRQHandler + + PUBWEAK TIMER7_TRG_CMT_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +TIMER7_TRG_CMT_IRQHandler + B TIMER7_TRG_CMT_IRQHandler + + PUBWEAK TIMER7_Channel_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +TIMER7_Channel_IRQHandler + B TIMER7_Channel_IRQHandler + + PUBWEAK EXMC_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +EXMC_IRQHandler + B EXMC_IRQHandler + + PUBWEAK TIMER4_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +TIMER4_IRQHandler + B TIMER4_IRQHandler + + PUBWEAK SPI2_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +SPI2_IRQHandler + B SPI2_IRQHandler + + PUBWEAK UART3_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +UART3_IRQHandler + B UART3_IRQHandler + + PUBWEAK UART4_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +UART4_IRQHandler + B UART4_IRQHandler + + PUBWEAK TIMER5_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +TIMER5_IRQHandler + B TIMER5_IRQHandler + + PUBWEAK TIMER6_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +TIMER6_IRQHandler + B TIMER6_IRQHandler + + PUBWEAK DMA1_Channel0_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +DMA1_Channel0_IRQHandler + B DMA1_Channel0_IRQHandler + + PUBWEAK DMA1_Channel1_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +DMA1_Channel1_IRQHandler + B DMA1_Channel1_IRQHandler + + PUBWEAK DMA1_Channel2_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +DMA1_Channel2_IRQHandler + B DMA1_Channel2_IRQHandler + + PUBWEAK DMA1_Channel3_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +DMA1_Channel3_IRQHandler + B DMA1_Channel3_IRQHandler + + PUBWEAK DMA1_Channel4_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +DMA1_Channel4_IRQHandler + B DMA1_Channel4_IRQHandler + + PUBWEAK ENET_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +ENET_IRQHandler + B ENET_IRQHandler + + PUBWEAK ENET_WKUP_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +ENET_WKUP_IRQHandler + B ENET_WKUP_IRQHandler + + PUBWEAK CAN1_TX_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +CAN1_TX_IRQHandler + B CAN1_TX_IRQHandler + + PUBWEAK CAN1_RX0_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +CAN1_RX0_IRQHandler + B CAN1_RX0_IRQHandler + + PUBWEAK CAN1_RX1_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +CAN1_RX1_IRQHandler + B CAN1_RX1_IRQHandler + + PUBWEAK CAN1_EWMC_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +CAN1_EWMC_IRQHandler + B CAN1_EWMC_IRQHandler + + PUBWEAK USBFS_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +USBFS_IRQHandler + B USBFS_IRQHandler + + + END diff --git a/bsp/gd32/libraries/GD32F10x_Firmware_Library/CMSIS/GD/GD32F10x/Source/IAR/startup_gd32f10x_hd.s b/bsp/gd32/libraries/GD32F10x_Firmware_Library/CMSIS/GD/GD32F10x/Source/IAR/startup_gd32f10x_hd.s new file mode 100644 index 0000000000..7f5356f0cf --- /dev/null +++ b/bsp/gd32/libraries/GD32F10x_Firmware_Library/CMSIS/GD/GD32F10x/Source/IAR/startup_gd32f10x_hd.s @@ -0,0 +1,490 @@ +;/*! +; \file startup_gd32f10x_hd.s +; \brief start up file +; +; \version 2014-12-26, V1.0.0, firmware for GD32F10x +; \version 2017-06-20, V2.0.0, firmware for GD32F10x +; \version 2018-07-31, V2.1.0, firmware for GD32F10x +; \version 2020-09-30, V2.2.0, firmware for GD32F10x +;*/ + +;/* + ;Copyright (c) 2020, GigaDevice Semiconductor Inc. + + ;Redistribution and use in source and binary forms, with or without modification, +;are permitted provided that the following conditions are met: + + ;1. Redistributions of source code must retain the above copyright notice, this + ;list of conditions and the following disclaimer. + ;2. Redistributions in binary form must reproduce the above copyright notice, + ;this list of conditions and the following disclaimer in the documentation + ;and/or other materials provided with the distribution. + ;3. Neither the name of the copyright holder nor the names of its contributors + ;may be used to endorse or promote products derived from this software without + ;specific prior written permission. + + ;THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +;AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +;WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +;IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +;INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +;NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +;PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +;WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +;ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +;OF SUCH DAMAGE. +;*/ + + MODULE ?cstartup + + ;; Forward declaration of sections. + SECTION CSTACK:DATA:NOROOT(3) + + SECTION .intvec:CODE:NOROOT(2) + + EXTERN __iar_program_start + EXTERN SystemInit + PUBLIC __vector_table + + DATA +__vector_table + DCD sfe(CSTACK) ; top of stack + DCD Reset_Handler ; Reset Handler + + DCD NMI_Handler ; NMI Handler + DCD HardFault_Handler ; Hard Fault Handler + DCD MemManage_Handler ; MPU Fault Handler + DCD BusFault_Handler ; Bus Fault Handler + DCD UsageFault_Handler ; Usage Fault Handler + DCD 0 ; Reserved + DCD 0 ; Reserved + DCD 0 ; Reserved + DCD 0 ; Reserved + DCD SVC_Handler ; SVCall Handler + DCD DebugMon_Handler ; Debug Monitor Handler + DCD 0 ; Reserved + DCD PendSV_Handler ; PendSV Handler + DCD SysTick_Handler ; SysTick Handler + + ; External Interrupts + DCD WWDGT_IRQHandler ; Vector Number 16,Window Watchdog Timer + DCD LVD_IRQHandler ; Vector Number 17,LVD through EXTI Line detect + DCD TAMPER_IRQHandler ; Vector Number 18,Tamper Interrupt + DCD RTC_IRQHandler ; Vector Number 19,RTC through EXTI Line + DCD FMC_IRQHandler ; Vector Number 20,FMC + DCD RCU_IRQHandler ; Vector Number 21,RCU + DCD EXTI0_IRQHandler ; Vector Number 22,EXTI Line 0 + DCD EXTI1_IRQHandler ; Vector Number 23,EXTI Line 1 + DCD EXTI2_IRQHandler ; Vector Number 24,EXTI Line 2 + DCD EXTI3_IRQHandler ; Vector Number 25,EXTI Line 3 + DCD EXTI4_IRQHandler ; Vector Number 26,EXTI Line 4 + DCD DMA0_Channel0_IRQHandler ; Vector Number 27,DMA0 Channel 0 + DCD DMA0_Channel1_IRQHandler ; Vector Number 28,DMA0 Channel 1 + DCD DMA0_Channel2_IRQHandler ; Vector Number 29,DMA0 Channel 2 + DCD DMA0_Channel3_IRQHandler ; Vector Number 30,DMA0 Channel 3 + DCD DMA0_Channel4_IRQHandler ; Vector Number 31,DMA0 Channel 4 + DCD DMA0_Channel5_IRQHandler ; Vector Number 32,DMA0 Channel 5 + DCD DMA0_Channel6_IRQHandler ; Vector Number 33,DMA0 Channel 6 + DCD ADC0_1_IRQHandler ; Vector Number 34,ADC0 and ADC1 + DCD USBD_HP_CAN0_TX_IRQHandler ; Vector Number 35,USBD and CAN0 TX + DCD USBD_LP_CAN0_RX0_IRQHandler ; Vector Number 36,USBD and CAN0 RX0 + DCD CAN0_RX1_IRQHandler ; Vector Number 37,CAN0 RX1 + DCD CAN0_EWMC_IRQHandler ; Vector Number 38,CAN0 EWMC + DCD EXTI5_9_IRQHandler ; Vector Number 39,EXTI Line 5 to EXTI Line 9 + DCD TIMER0_BRK_IRQHandler ; Vector Number 40,TIMER0 Break + DCD TIMER0_UP_IRQHandler ; Vector Number 41,TIMER0 Update + DCD TIMER0_TRG_CMT_IRQHandler ; Vector Number 42,TIMER0 Trigger and Commutation + DCD TIMER0_Channel_IRQHandler ; Vector Number 43,TIMER0 Channel Capture Compare + DCD TIMER1_IRQHandler ; Vector Number 44,TIMER1 + DCD TIMER2_IRQHandler ; Vector Number 45,TIMER2 + DCD TIMER3_IRQHandler ; Vector Number 46,TIMER3 + DCD I2C0_EV_IRQHandler ; Vector Number 47,I2C0 Event + DCD I2C0_ER_IRQHandler ; Vector Number 48,I2C0 Error + DCD I2C1_EV_IRQHandler ; Vector Number 49,I2C1 Event + DCD I2C1_ER_IRQHandler ; Vector Number 50,I2C1 Error + DCD SPI0_IRQHandler ; Vector Number 51,SPI0 + DCD SPI1_IRQHandler ; Vector Number 52,SPI1 + DCD USART0_IRQHandler ; Vector Number 53,USART0 + DCD USART1_IRQHandler ; Vector Number 54,USART1 + DCD USART2_IRQHandler ; Vector Number 55,USART2 + DCD EXTI10_15_IRQHandler ; Vector Number 56,EXTI Line 10 to EXTI Line 15 + DCD RTC_Alarm_IRQHandler ; Vector Number 57,RTC Alarm through EXTI Line + DCD USBD_WKUP_IRQHandler ; Vector Number 58,USBD WakeUp from suspend through EXTI Line + DCD TIMER7_BRK_IRQHandler ; Vector Number 59,TIMER7 Break Interrupt + DCD TIMER7_UP_IRQHandler ; Vector Number 60,TIMER7 Update Interrupt + DCD TIMER7_TRG_CMT_IRQHandler ; Vector Number 61,TIMER7 Trigger and Commutation Interrupt + DCD TIMER7_Channel_IRQHandler ; Vector Number 62,TIMER7 Channel Capture Compare + DCD ADC2_IRQHandler ; Vector Number 63,ADC2 + DCD EXMC_IRQHandler ; Vector Number 64,EXMC + DCD SDIO_IRQHandler ; Vector Number 65,SDIO + DCD TIMER4_IRQHandler ; Vector Number 66,TIMER4 + DCD SPI2_IRQHandler ; Vector Number 67,SPI2 + DCD UART3_IRQHandler ; Vector Number 68,UART3 + DCD UART4_IRQHandler ; Vector Number 69,UART4 + DCD TIMER5_IRQHandler ; Vector Number 70,TIMER5 + DCD TIMER6_IRQHandler ; Vector Number 71,TIMER6 + DCD DMA1_Channel0_IRQHandler ; Vector Number 72,DMA1 Channel0 + DCD DMA1_Channel1_IRQHandler ; Vector Number 73,DMA1 Channel1 + DCD DMA1_Channel2_IRQHandler ; Vector Number 74,DMA1 Channel2 + DCD DMA1_Channel3_4_IRQHandler ; Vector Number 75,DMA1 Channel4 +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; +;; Default interrupt handlers. +;; + THUMB + + PUBWEAK Reset_Handler + SECTION .text:CODE:NOROOT:REORDER(2) +Reset_Handler + LDR R0, = SystemInit + BLX R0 + LDR R0, =__iar_program_start + BX R0 + + PUBWEAK NMI_Handler + SECTION .text:CODE:NOROOT:REORDER(1) +NMI_Handler + B NMI_Handler + + PUBWEAK HardFault_Handler + SECTION .text:CODE:NOROOT:REORDER(1) +HardFault_Handler + B HardFault_Handler + + PUBWEAK MemManage_Handler + SECTION .text:CODE:NOROOT:REORDER(1) +MemManage_Handler + B MemManage_Handler + + PUBWEAK BusFault_Handler + SECTION .text:CODE:NOROOT:REORDER(1) +BusFault_Handler + B BusFault_Handler + + PUBWEAK UsageFault_Handler + SECTION .text:CODE:NOROOT:REORDER(1) +UsageFault_Handler + B UsageFault_Handler + + PUBWEAK SVC_Handler + SECTION .text:CODE:NOROOT:REORDER(1) +SVC_Handler + B SVC_Handler + + PUBWEAK DebugMon_Handler + SECTION .text:CODE:NOROOT:REORDER(1) +DebugMon_Handler + B DebugMon_Handler + + PUBWEAK PendSV_Handler + SECTION .text:CODE:NOROOT:REORDER(1) +PendSV_Handler + B PendSV_Handler + + PUBWEAK SysTick_Handler + SECTION .text:CODE:NOROOT:REORDER(1) +SysTick_Handler + B SysTick_Handler + + PUBWEAK WWDGT_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +WWDGT_IRQHandler + B WWDGT_IRQHandler + + PUBWEAK LVD_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +LVD_IRQHandler + B LVD_IRQHandler + + PUBWEAK TAMPER_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +TAMPER_IRQHandler + B TAMPER_IRQHandler + + PUBWEAK RTC_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +RTC_IRQHandler + B RTC_IRQHandler + + PUBWEAK FMC_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +FMC_IRQHandler + B FMC_IRQHandler + + PUBWEAK RCU_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +RCU_IRQHandler + B RCU_IRQHandler + + PUBWEAK EXTI0_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +EXTI0_IRQHandler + B EXTI0_IRQHandler + + PUBWEAK EXTI1_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +EXTI1_IRQHandler + B EXTI1_IRQHandler + + PUBWEAK EXTI2_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +EXTI2_IRQHandler + B EXTI2_IRQHandler + + PUBWEAK EXTI3_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +EXTI3_IRQHandler + B EXTI3_IRQHandler + + PUBWEAK EXTI4_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +EXTI4_IRQHandler + B EXTI4_IRQHandler + + PUBWEAK DMA0_Channel0_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +DMA0_Channel0_IRQHandler + B DMA0_Channel0_IRQHandler + + + PUBWEAK DMA0_Channel1_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +DMA0_Channel1_IRQHandler + B DMA0_Channel1_IRQHandler + + PUBWEAK DMA0_Channel2_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +DMA0_Channel2_IRQHandler + B DMA0_Channel2_IRQHandler + + PUBWEAK DMA0_Channel3_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +DMA0_Channel3_IRQHandler + B DMA0_Channel3_IRQHandler + + PUBWEAK DMA0_Channel4_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +DMA0_Channel4_IRQHandler + B DMA0_Channel4_IRQHandler + + PUBWEAK DMA0_Channel5_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +DMA0_Channel5_IRQHandler + B DMA0_Channel5_IRQHandler + + PUBWEAK DMA0_Channel6_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +DMA0_Channel6_IRQHandler + B DMA0_Channel6_IRQHandler + + PUBWEAK ADC0_1_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +ADC0_1_IRQHandler + B ADC0_1_IRQHandler + + PUBWEAK USBD_HP_CAN0_TX_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +USBD_HP_CAN0_TX_IRQHandler + B USBD_HP_CAN0_TX_IRQHandler + + PUBWEAK USBD_LP_CAN0_RX0_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +USBD_LP_CAN0_RX0_IRQHandler + B USBD_LP_CAN0_RX0_IRQHandler + + PUBWEAK CAN0_RX1_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +CAN0_RX1_IRQHandler + B CAN0_RX1_IRQHandler + + PUBWEAK CAN0_EWMC_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +CAN0_EWMC_IRQHandler + B CAN0_EWMC_IRQHandler + + PUBWEAK EXTI5_9_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +EXTI5_9_IRQHandler + B EXTI5_9_IRQHandler + + PUBWEAK TIMER0_BRK_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +TIMER0_BRK_IRQHandler + B TIMER0_BRK_IRQHandler + + PUBWEAK TIMER0_UP_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +TIMER0_UP_IRQHandler + B TIMER0_UP_IRQHandler + + PUBWEAK TIMER0_TRG_CMT_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +TIMER0_TRG_CMT_IRQHandler + B TIMER0_TRG_CMT_IRQHandler + + PUBWEAK TIMER0_Channel_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +TIMER0_Channel_IRQHandler + B TIMER0_Channel_IRQHandler + + PUBWEAK TIMER1_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +TIMER1_IRQHandler + B TIMER1_IRQHandler + + PUBWEAK TIMER2_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +TIMER2_IRQHandler + B TIMER2_IRQHandler + + PUBWEAK TIMER3_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +TIMER3_IRQHandler + B TIMER3_IRQHandler + + PUBWEAK I2C0_EV_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +I2C0_EV_IRQHandler + B I2C0_EV_IRQHandler + + PUBWEAK I2C0_ER_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +I2C0_ER_IRQHandler + B I2C0_ER_IRQHandler + + PUBWEAK I2C1_EV_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +I2C1_EV_IRQHandler + B I2C1_EV_IRQHandler + + PUBWEAK I2C1_ER_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +I2C1_ER_IRQHandler + B I2C1_ER_IRQHandler + + PUBWEAK SPI0_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +SPI0_IRQHandler + B SPI0_IRQHandler + + PUBWEAK SPI1_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +SPI1_IRQHandler + B SPI1_IRQHandler + + PUBWEAK USART0_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +USART0_IRQHandler + B USART0_IRQHandler + + PUBWEAK USART1_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +USART1_IRQHandler + B USART1_IRQHandler + + PUBWEAK USART2_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +USART2_IRQHandler + B USART2_IRQHandler + + PUBWEAK EXTI10_15_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +EXTI10_15_IRQHandler + B EXTI10_15_IRQHandler + + PUBWEAK RTC_Alarm_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +RTC_Alarm_IRQHandler + B RTC_Alarm_IRQHandler + + PUBWEAK USBD_WKUP_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +USBD_WKUP_IRQHandler + B USBD_WKUP_IRQHandler + + PUBWEAK TIMER7_BRK_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +TIMER7_BRK_IRQHandler + B TIMER7_BRK_IRQHandler + + PUBWEAK TIMER7_UP_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +TIMER7_UP_IRQHandler + B TIMER7_UP_IRQHandler + + PUBWEAK TIMER7_TRG_CMT_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +TIMER7_TRG_CMT_IRQHandler + B TIMER7_TRG_CMT_IRQHandler + + PUBWEAK TIMER7_Channel_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +TIMER7_Channel_IRQHandler + B TIMER7_Channel_IRQHandler + + PUBWEAK ADC2_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +ADC2_IRQHandler + B ADC2_IRQHandler + + PUBWEAK EXMC_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +EXMC_IRQHandler + B EXMC_IRQHandler + + PUBWEAK SDIO_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +SDIO_IRQHandler + B SDIO_IRQHandler + + PUBWEAK TIMER4_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +TIMER4_IRQHandler + B TIMER4_IRQHandler + + PUBWEAK SPI2_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +SPI2_IRQHandler + B SPI2_IRQHandler + + PUBWEAK UART3_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +UART3_IRQHandler + B UART3_IRQHandler + + PUBWEAK UART4_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +UART4_IRQHandler + B UART4_IRQHandler + + PUBWEAK TIMER5_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +TIMER5_IRQHandler + B TIMER5_IRQHandler + + PUBWEAK TIMER6_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +TIMER6_IRQHandler + B TIMER6_IRQHandler + + PUBWEAK DMA1_Channel0_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +DMA1_Channel0_IRQHandler + B DMA1_Channel0_IRQHandler + + PUBWEAK DMA1_Channel1_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +DMA1_Channel1_IRQHandler + B DMA1_Channel1_IRQHandler + + PUBWEAK DMA1_Channel2_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +DMA1_Channel2_IRQHandler + B DMA1_Channel2_IRQHandler + + PUBWEAK DMA1_Channel3_4_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +DMA1_Channel3_4_IRQHandler + B DMA1_Channel3_4_IRQHandler + + END diff --git a/bsp/gd32/libraries/GD32F10x_Firmware_Library/CMSIS/GD/GD32F10x/Source/IAR/startup_gd32f10x_md.s b/bsp/gd32/libraries/GD32F10x_Firmware_Library/CMSIS/GD/GD32F10x/Source/IAR/startup_gd32f10x_md.s new file mode 100644 index 0000000000..6fefa84837 --- /dev/null +++ b/bsp/gd32/libraries/GD32F10x_Firmware_Library/CMSIS/GD/GD32F10x/Source/IAR/startup_gd32f10x_md.s @@ -0,0 +1,399 @@ +;/*! +; \file startup_gd32f10x_md.s +; \brief start up file +; +; \version 2014-12-26, V1.0.0, firmware for GD32F10x +; \version 2017-06-20, V2.0.0, firmware for GD32F10x +; \version 2018-07-31, V2.1.0, firmware for GD32F10x +; \version 2020-09-30, V2.2.0, firmware for GD32F10x +;*/ + +;/* + ;Copyright (c) 2020, GigaDevice Semiconductor Inc. + + ;Redistribution and use in source and binary forms, with or without modification, +;are permitted provided that the following conditions are met: + + ;1. Redistributions of source code must retain the above copyright notice, this + ;list of conditions and the following disclaimer. + ;2. Redistributions in binary form must reproduce the above copyright notice, + ;this list of conditions and the following disclaimer in the documentation + ;and/or other materials provided with the distribution. + ;3. Neither the name of the copyright holder nor the names of its contributors + ;may be used to endorse or promote products derived from this software without + ;specific prior written permission. + + ;THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +;AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +;WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +;IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +;INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +;NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +;PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +;WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +;ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +;OF SUCH DAMAGE. +;*/ + + MODULE ?cstartup + + ;; Forward declaration of sections. + SECTION CSTACK:DATA:NOROOT(3) + + SECTION .intvec:CODE:NOROOT(2) + + EXTERN __iar_program_start + EXTERN SystemInit + PUBLIC __vector_table + + DATA +__vector_table + DCD sfe(CSTACK) ; top of stack + DCD Reset_Handler ; Reset Handler + + DCD NMI_Handler ; NMI Handler + DCD HardFault_Handler ; Hard Fault Handler + DCD MemManage_Handler ; MPU Fault Handler + DCD BusFault_Handler ; Bus Fault Handler + DCD UsageFault_Handler ; Usage Fault Handler + DCD 0 ; Reserved + DCD 0 ; Reserved + DCD 0 ; Reserved + DCD 0 ; Reserved + DCD SVC_Handler ; SVCall Handler + DCD DebugMon_Handler ; Debug Monitor Handler + DCD 0 ; Reserved + DCD PendSV_Handler ; PendSV Handler + DCD SysTick_Handler ; SysTick Handler + + ; External Interrupts + DCD WWDGT_IRQHandler ; Vector Number 16,Window Watchdog Timer + DCD LVD_IRQHandler ; Vector Number 17,LVD through EXTI Line detect + DCD TAMPER_IRQHandler ; Vector Number 18,Tamper Interrupt + DCD RTC_IRQHandler ; Vector Number 19,RTC through EXTI Line + DCD FMC_IRQHandler ; Vector Number 20,FMC + DCD RCU_IRQHandler ; Vector Number 21,RCU + DCD EXTI0_IRQHandler ; Vector Number 22,EXTI Line 0 + DCD EXTI1_IRQHandler ; Vector Number 23,EXTI Line 1 + DCD EXTI2_IRQHandler ; Vector Number 24,EXTI Line 2 + DCD EXTI3_IRQHandler ; Vector Number 25,EXTI Line 3 + DCD EXTI4_IRQHandler ; Vector Number 26,EXTI Line 4 + DCD DMA0_Channel0_IRQHandler ; Vector Number 27,DMA0 Channel 0 + DCD DMA0_Channel1_IRQHandler ; Vector Number 28,DMA0 Channel 1 + DCD DMA0_Channel2_IRQHandler ; Vector Number 29,DMA0 Channel 2 + DCD DMA0_Channel3_IRQHandler ; Vector Number 30,DMA0 Channel 3 + DCD DMA0_Channel4_IRQHandler ; Vector Number 31,DMA0 Channel 4 + DCD DMA0_Channel5_IRQHandler ; Vector Number 32,DMA0 Channel 5 + DCD DMA0_Channel6_IRQHandler ; Vector Number 33,DMA0 Channel 6 + DCD ADC0_1_IRQHandler ; Vector Number 34,ADC0 and ADC1 + DCD USBD_HP_CAN0_TX_IRQHandler ; Vector Number 35,USBD and CAN0 TX + DCD USBD_LP_CAN0_RX0_IRQHandler ; Vector Number 36,USBD and CAN0 RX0 + DCD CAN0_RX1_IRQHandler ; Vector Number 37,CAN0 RX1 + DCD CAN0_EWMC_IRQHandler ; Vector Number 38,CAN0 EWMC + DCD EXTI5_9_IRQHandler ; Vector Number 39,EXTI Line 5 to EXTI Line 9 + DCD TIMER0_BRK_IRQHandler ; Vector Number 40,TIMER0 Break + DCD TIMER0_UP_IRQHandler ; Vector Number 41,TIMER0 Update + DCD TIMER0_TRG_CMT_IRQHandler ; Vector Number 42,TIMER0 Trigger and Commutation + DCD TIMER0_Channel_IRQHandler ; Vector Number 43,TIMER0 Channel Capture Compare + DCD TIMER1_IRQHandler ; Vector Number 44,TIMER1 + DCD TIMER2_IRQHandler ; Vector Number 45,TIMER2 + DCD TIMER3_IRQHandler ; Vector Number 46,TIMER3 + DCD I2C0_EV_IRQHandler ; Vector Number 47,I2C0 Event + DCD I2C0_ER_IRQHandler ; Vector Number 48,I2C0 Error + DCD I2C1_EV_IRQHandler ; Vector Number 49,I2C1 Event + DCD I2C1_ER_IRQHandler ; Vector Number 50,I2C1 Error + DCD SPI0_IRQHandler ; Vector Number 51,SPI0 + DCD SPI1_IRQHandler ; Vector Number 52,SPI1 + DCD USART0_IRQHandler ; Vector Number 53,USART0 + DCD USART1_IRQHandler ; Vector Number 54,USART1 + DCD USART2_IRQHandler ; Vector Number 55,USART2 + DCD EXTI10_15_IRQHandler ; Vector Number 56,EXTI Line 10 to EXTI Line 15 + DCD RTC_Alarm_IRQHandler ; Vector Number 57,RTC Alarm through EXTI Line + DCD USBD_WKUP_IRQHandler ; Vector Number 58,USBD WakeUp from suspend through EXTI Line + DCD 0 ; Reserved + DCD 0 ; Reserved + DCD 0 ; Reserved + DCD 0 ; Reserved + DCD 0 ; Reserved + DCD EXMC_IRQHandler ; Vector Number 64,EXMC +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; +;; Default interrupt handlers. +;; + THUMB + + PUBWEAK Reset_Handler + SECTION .text:CODE:NOROOT:REORDER(2) +Reset_Handler + LDR R0, = SystemInit + BLX R0 + LDR R0, =__iar_program_start + BX R0 + + PUBWEAK NMI_Handler + SECTION .text:CODE:NOROOT:REORDER(1) +NMI_Handler + B NMI_Handler + + PUBWEAK HardFault_Handler + SECTION .text:CODE:NOROOT:REORDER(1) +HardFault_Handler + B HardFault_Handler + + PUBWEAK MemManage_Handler + SECTION .text:CODE:NOROOT:REORDER(1) +MemManage_Handler + B MemManage_Handler + + PUBWEAK BusFault_Handler + SECTION .text:CODE:NOROOT:REORDER(1) +BusFault_Handler + B BusFault_Handler + + PUBWEAK UsageFault_Handler + SECTION .text:CODE:NOROOT:REORDER(1) +UsageFault_Handler + B UsageFault_Handler + + PUBWEAK SVC_Handler + SECTION .text:CODE:NOROOT:REORDER(1) +SVC_Handler + B SVC_Handler + + PUBWEAK DebugMon_Handler + SECTION .text:CODE:NOROOT:REORDER(1) +DebugMon_Handler + B DebugMon_Handler + + PUBWEAK PendSV_Handler + SECTION .text:CODE:NOROOT:REORDER(1) +PendSV_Handler + B PendSV_Handler + + PUBWEAK SysTick_Handler + SECTION .text:CODE:NOROOT:REORDER(1) +SysTick_Handler + B SysTick_Handler + + PUBWEAK WWDGT_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +WWDGT_IRQHandler + B WWDGT_IRQHandler + + PUBWEAK LVD_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +LVD_IRQHandler + B LVD_IRQHandler + + PUBWEAK TAMPER_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +TAMPER_IRQHandler + B TAMPER_IRQHandler + + PUBWEAK RTC_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +RTC_IRQHandler + B RTC_IRQHandler + + PUBWEAK FMC_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +FMC_IRQHandler + B FMC_IRQHandler + + PUBWEAK RCU_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +RCU_IRQHandler + B RCU_IRQHandler + + PUBWEAK EXTI0_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +EXTI0_IRQHandler + B EXTI0_IRQHandler + + PUBWEAK EXTI1_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +EXTI1_IRQHandler + B EXTI1_IRQHandler + + PUBWEAK EXTI2_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +EXTI2_IRQHandler + B EXTI2_IRQHandler + + PUBWEAK EXTI3_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +EXTI3_IRQHandler + B EXTI3_IRQHandler + + PUBWEAK EXTI4_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +EXTI4_IRQHandler + B EXTI4_IRQHandler + + PUBWEAK DMA0_Channel0_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +DMA0_Channel0_IRQHandler + B DMA0_Channel0_IRQHandler + + + PUBWEAK DMA0_Channel1_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +DMA0_Channel1_IRQHandler + B DMA0_Channel1_IRQHandler + + PUBWEAK DMA0_Channel2_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +DMA0_Channel2_IRQHandler + B DMA0_Channel2_IRQHandler + + PUBWEAK DMA0_Channel3_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +DMA0_Channel3_IRQHandler + B DMA0_Channel3_IRQHandler + + PUBWEAK DMA0_Channel4_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +DMA0_Channel4_IRQHandler + B DMA0_Channel4_IRQHandler + + PUBWEAK DMA0_Channel5_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +DMA0_Channel5_IRQHandler + B DMA0_Channel5_IRQHandler + + PUBWEAK DMA0_Channel6_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +DMA0_Channel6_IRQHandler + B DMA0_Channel6_IRQHandler + + PUBWEAK ADC0_1_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +ADC0_1_IRQHandler + B ADC0_1_IRQHandler + + PUBWEAK USBD_HP_CAN0_TX_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +USBD_HP_CAN0_TX_IRQHandler + B USBD_HP_CAN0_TX_IRQHandler + + PUBWEAK USBD_LP_CAN0_RX0_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +USBD_LP_CAN0_RX0_IRQHandler + B USBD_LP_CAN0_RX0_IRQHandler + + PUBWEAK CAN0_RX1_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +CAN0_RX1_IRQHandler + B CAN0_RX1_IRQHandler + + PUBWEAK CAN0_EWMC_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +CAN0_EWMC_IRQHandler + B CAN0_EWMC_IRQHandler + + PUBWEAK EXTI5_9_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +EXTI5_9_IRQHandler + B EXTI5_9_IRQHandler + + PUBWEAK TIMER0_BRK_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +TIMER0_BRK_IRQHandler + B TIMER0_BRK_IRQHandler + + PUBWEAK TIMER0_UP_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +TIMER0_UP_IRQHandler + B TIMER0_UP_IRQHandler + + PUBWEAK TIMER0_TRG_CMT_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +TIMER0_TRG_CMT_IRQHandler + B TIMER0_TRG_CMT_IRQHandler + + PUBWEAK TIMER0_Channel_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +TIMER0_Channel_IRQHandler + B TIMER0_Channel_IRQHandler + + PUBWEAK TIMER1_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +TIMER1_IRQHandler + B TIMER1_IRQHandler + + PUBWEAK TIMER2_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +TIMER2_IRQHandler + B TIMER2_IRQHandler + + PUBWEAK TIMER3_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +TIMER3_IRQHandler + B TIMER3_IRQHandler + + PUBWEAK I2C0_EV_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +I2C0_EV_IRQHandler + B I2C0_EV_IRQHandler + + PUBWEAK I2C0_ER_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +I2C0_ER_IRQHandler + B I2C0_ER_IRQHandler + + PUBWEAK I2C1_EV_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +I2C1_EV_IRQHandler + B I2C1_EV_IRQHandler + + PUBWEAK I2C1_ER_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +I2C1_ER_IRQHandler + B I2C1_ER_IRQHandler + + PUBWEAK SPI0_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +SPI0_IRQHandler + B SPI0_IRQHandler + + PUBWEAK SPI1_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +SPI1_IRQHandler + B SPI1_IRQHandler + + PUBWEAK USART0_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +USART0_IRQHandler + B USART0_IRQHandler + + PUBWEAK USART1_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +USART1_IRQHandler + B USART1_IRQHandler + + PUBWEAK USART2_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +USART2_IRQHandler + B USART2_IRQHandler + + PUBWEAK EXTI10_15_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +EXTI10_15_IRQHandler + B EXTI10_15_IRQHandler + + PUBWEAK RTC_Alarm_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +RTC_Alarm_IRQHandler + B RTC_Alarm_IRQHandler + + PUBWEAK USBD_WKUP_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +USBD_WKUP_IRQHandler + B USBD_WKUP_IRQHandler + + PUBWEAK EXMC_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +EXMC_IRQHandler + B EXMC_IRQHandler + + END diff --git a/bsp/gd32/libraries/GD32F10x_Firmware_Library/CMSIS/GD/GD32F10x/Source/IAR/startup_gd32f10x_xd.s b/bsp/gd32/libraries/GD32F10x_Firmware_Library/CMSIS/GD/GD32F10x/Source/IAR/startup_gd32f10x_xd.s new file mode 100644 index 0000000000..08659afcbf --- /dev/null +++ b/bsp/gd32/libraries/GD32F10x_Firmware_Library/CMSIS/GD/GD32F10x/Source/IAR/startup_gd32f10x_xd.s @@ -0,0 +1,490 @@ +;/*! +; \file startup_gd32f10x_xd.s +; \brief start up file +; +; \version 2014-12-26, V1.0.0, firmware for GD32F10x +; \version 2017-06-20, V2.0.0, firmware for GD32F10x +; \version 2018-07-31, V2.1.0, firmware for GD32F10x +; \version 2020-09-30, V2.2.0, firmware for GD32F10x +;*/ + +;/* + ;Copyright (c) 2020, GigaDevice Semiconductor Inc. + + ;Redistribution and use in source and binary forms, with or without modification, +;are permitted provided that the following conditions are met: + + ;1. Redistributions of source code must retain the above copyright notice, this + ;list of conditions and the following disclaimer. + ;2. Redistributions in binary form must reproduce the above copyright notice, + ;this list of conditions and the following disclaimer in the documentation + ;and/or other materials provided with the distribution. + ;3. Neither the name of the copyright holder nor the names of its contributors + ;may be used to endorse or promote products derived from this software without + ;specific prior written permission. + + ;THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +;AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +;WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +;IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +;INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +;NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +;PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +;WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +;ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +;OF SUCH DAMAGE. +;*/ + + MODULE ?cstartup + + ;; Forward declaration of sections. + SECTION CSTACK:DATA:NOROOT(3) + + SECTION .intvec:CODE:NOROOT(2) + + EXTERN __iar_program_start + EXTERN SystemInit + PUBLIC __vector_table + + DATA +__vector_table + DCD sfe(CSTACK) ; top of stack + DCD Reset_Handler ; Reset Handler + + DCD NMI_Handler ; NMI Handler + DCD HardFault_Handler ; Hard Fault Handler + DCD MemManage_Handler ; MPU Fault Handler + DCD BusFault_Handler ; Bus Fault Handler + DCD UsageFault_Handler ; Usage Fault Handler + DCD 0 ; Reserved + DCD 0 ; Reserved + DCD 0 ; Reserved + DCD 0 ; Reserved + DCD SVC_Handler ; SVCall Handler + DCD DebugMon_Handler ; Debug Monitor Handler + DCD 0 ; Reserved + DCD PendSV_Handler ; PendSV Handler + DCD SysTick_Handler ; SysTick Handler + + ; External Interrupts + DCD WWDGT_IRQHandler ; Vector Number 16,Window Watchdog Timer + DCD LVD_IRQHandler ; Vector Number 17,LVD through EXTI Line detect + DCD TAMPER_IRQHandler ; Vector Number 18,Tamper Interrupt + DCD RTC_IRQHandler ; Vector Number 19,RTC through EXTI Line + DCD FMC_IRQHandler ; Vector Number 20,FMC + DCD RCU_IRQHandler ; Vector Number 21,RCU + DCD EXTI0_IRQHandler ; Vector Number 22,EXTI Line 0 + DCD EXTI1_IRQHandler ; Vector Number 23,EXTI Line 1 + DCD EXTI2_IRQHandler ; Vector Number 24,EXTI Line 2 + DCD EXTI3_IRQHandler ; Vector Number 25,EXTI Line 3 + DCD EXTI4_IRQHandler ; Vector Number 26,EXTI Line 4 + DCD DMA0_Channel0_IRQHandler ; Vector Number 27,DMA0 Channel 0 + DCD DMA0_Channel1_IRQHandler ; Vector Number 28,DMA0 Channel 1 + DCD DMA0_Channel2_IRQHandler ; Vector Number 29,DMA0 Channel 2 + DCD DMA0_Channel3_IRQHandler ; Vector Number 30,DMA0 Channel 3 + DCD DMA0_Channel4_IRQHandler ; Vector Number 31,DMA0 Channel 4 + DCD DMA0_Channel5_IRQHandler ; Vector Number 32,DMA0 Channel 5 + DCD DMA0_Channel6_IRQHandler ; Vector Number 33,DMA0 Channel 6 + DCD ADC0_1_IRQHandler ; Vector Number 34,ADC0 and ADC1 + DCD USBD_HP_CAN0_TX_IRQHandler ; Vector Number 35,USBD and CAN0 TX + DCD USBD_LP_CAN0_RX0_IRQHandler ; Vector Number 36,USBD and CAN0 RX0 + DCD CAN0_RX1_IRQHandler ; Vector Number 37,CAN0 RX1 + DCD CAN0_EWMC_IRQHandler ; Vector Number 38,CAN0 EWMC + DCD EXTI5_9_IRQHandler ; Vector Number 39,EXTI Line 5 to EXTI Line 9 + DCD TIMER0_BRK_TIMER8_IRQHandler ; Vector Number 40,TIMER0 Break and TIMER8 global + DCD TIMER0_UP_TIMER9_IRQHandler ; Vector Number 41,TIMER0 Update and TIMER9 global + DCD TIMER0_TRG_CMT_TIMER10_IRQHandler ; Vector Number 42,TIMER0 Trigger and Commutation and TIMER10 global + DCD TIMER0_Channel_IRQHandler ; Vector Number 43,TIMER0 Channel Capture Compare + DCD TIMER1_IRQHandler ; Vector Number 44,TIMER1 + DCD TIMER2_IRQHandler ; Vector Number 45,TIMER2 + DCD TIMER3_IRQHandler ; Vector Number 46,TIMER3 + DCD I2C0_EV_IRQHandler ; Vector Number 47,I2C0 Event + DCD I2C0_ER_IRQHandler ; Vector Number 48,I2C0 Error + DCD I2C1_EV_IRQHandler ; Vector Number 49,I2C1 Event + DCD I2C1_ER_IRQHandler ; Vector Number 50,I2C1 Error + DCD SPI0_IRQHandler ; Vector Number 51,SPI0 + DCD SPI1_IRQHandler ; Vector Number 52,SPI1 + DCD USART0_IRQHandler ; Vector Number 53,USART0 + DCD USART1_IRQHandler ; Vector Number 54,USART1 + DCD USART2_IRQHandler ; Vector Number 55,USART2 + DCD EXTI10_15_IRQHandler ; Vector Number 56,EXTI Line 10 to EXTI Line 15 + DCD RTC_Alarm_IRQHandler ; Vector Number 57,RTC Alarm through EXTI Line + DCD USBD_WKUP_IRQHandler ; Vector Number 58,USBD WakeUp from suspend through EXTI Line + DCD TIMER7_BRK_TIMER11_IRQHandler ; Vector Number 59,TIMER7 Break Interrupt and TIMER11 global + DCD TIMER7_UP_TIMER12_IRQHandler ; Vector Number 60,TIMER7 Update Interrupt and TIMER12 global + DCD TIMER7_TRG_CMT_TIMER13_IRQHandler ; Vector Number 61,TIMER7 Trigger and Commutation Interrupt and TIMER13 global + DCD TIMER7_Channel_IRQHandler ; Vector Number 62,TIMER7 Channel Capture Compare + DCD ADC2_IRQHandler ; Vector Number 63,ADC2 + DCD EXMC_IRQHandler ; Vector Number 64,EXMC + DCD SDIO_IRQHandler ; Vector Number 65,SDIO + DCD TIMER4_IRQHandler ; Vector Number 66,TIMER4 + DCD SPI2_IRQHandler ; Vector Number 67,SPI2 + DCD UART3_IRQHandler ; Vector Number 68,UART3 + DCD UART4_IRQHandler ; Vector Number 69,UART4 + DCD TIMER5_IRQHandler ; Vector Number 70,TIMER5 + DCD TIMER6_IRQHandler ; Vector Number 71,TIMER6 + DCD DMA1_Channel0_IRQHandler ; Vector Number 72,DMA1 Channel0 + DCD DMA1_Channel1_IRQHandler ; Vector Number 73,DMA1 Channel1 + DCD DMA1_Channel2_IRQHandler ; Vector Number 74,DMA1 Channel2 + DCD DMA1_Channel3_4_IRQHandler ; Vector Number 75,DMA1 Channel4 +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; +;; Default interrupt handlers. +;; + THUMB + + PUBWEAK Reset_Handler + SECTION .text:CODE:NOROOT:REORDER(2) +Reset_Handler + LDR R0, = SystemInit + BLX R0 + LDR R0, =__iar_program_start + BX R0 + + PUBWEAK NMI_Handler + SECTION .text:CODE:NOROOT:REORDER(1) +NMI_Handler + B NMI_Handler + + PUBWEAK HardFault_Handler + SECTION .text:CODE:NOROOT:REORDER(1) +HardFault_Handler + B HardFault_Handler + + PUBWEAK MemManage_Handler + SECTION .text:CODE:NOROOT:REORDER(1) +MemManage_Handler + B MemManage_Handler + + PUBWEAK BusFault_Handler + SECTION .text:CODE:NOROOT:REORDER(1) +BusFault_Handler + B BusFault_Handler + + PUBWEAK UsageFault_Handler + SECTION .text:CODE:NOROOT:REORDER(1) +UsageFault_Handler + B UsageFault_Handler + + PUBWEAK SVC_Handler + SECTION .text:CODE:NOROOT:REORDER(1) +SVC_Handler + B SVC_Handler + + PUBWEAK DebugMon_Handler + SECTION .text:CODE:NOROOT:REORDER(1) +DebugMon_Handler + B DebugMon_Handler + + PUBWEAK PendSV_Handler + SECTION .text:CODE:NOROOT:REORDER(1) +PendSV_Handler + B PendSV_Handler + + PUBWEAK SysTick_Handler + SECTION .text:CODE:NOROOT:REORDER(1) +SysTick_Handler + B SysTick_Handler + + PUBWEAK WWDGT_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +WWDGT_IRQHandler + B WWDGT_IRQHandler + + PUBWEAK LVD_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +LVD_IRQHandler + B LVD_IRQHandler + + PUBWEAK TAMPER_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +TAMPER_IRQHandler + B TAMPER_IRQHandler + + PUBWEAK RTC_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +RTC_IRQHandler + B RTC_IRQHandler + + PUBWEAK FMC_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +FMC_IRQHandler + B FMC_IRQHandler + + PUBWEAK RCU_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +RCU_IRQHandler + B RCU_IRQHandler + + PUBWEAK EXTI0_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +EXTI0_IRQHandler + B EXTI0_IRQHandler + + PUBWEAK EXTI1_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +EXTI1_IRQHandler + B EXTI1_IRQHandler + + PUBWEAK EXTI2_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +EXTI2_IRQHandler + B EXTI2_IRQHandler + + PUBWEAK EXTI3_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +EXTI3_IRQHandler + B EXTI3_IRQHandler + + PUBWEAK EXTI4_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +EXTI4_IRQHandler + B EXTI4_IRQHandler + + PUBWEAK DMA0_Channel0_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +DMA0_Channel0_IRQHandler + B DMA0_Channel0_IRQHandler + + + PUBWEAK DMA0_Channel1_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +DMA0_Channel1_IRQHandler + B DMA0_Channel1_IRQHandler + + PUBWEAK DMA0_Channel2_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +DMA0_Channel2_IRQHandler + B DMA0_Channel2_IRQHandler + + PUBWEAK DMA0_Channel3_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +DMA0_Channel3_IRQHandler + B DMA0_Channel3_IRQHandler + + PUBWEAK DMA0_Channel4_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +DMA0_Channel4_IRQHandler + B DMA0_Channel4_IRQHandler + + PUBWEAK DMA0_Channel5_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +DMA0_Channel5_IRQHandler + B DMA0_Channel5_IRQHandler + + PUBWEAK DMA0_Channel6_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +DMA0_Channel6_IRQHandler + B DMA0_Channel6_IRQHandler + + PUBWEAK ADC0_1_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +ADC0_1_IRQHandler + B ADC0_1_IRQHandler + + PUBWEAK USBD_HP_CAN0_TX_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +USBD_HP_CAN0_TX_IRQHandler + B USBD_HP_CAN0_TX_IRQHandler + + PUBWEAK USBD_LP_CAN0_RX0_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +USBD_LP_CAN0_RX0_IRQHandler + B USBD_LP_CAN0_RX0_IRQHandler + + PUBWEAK CAN0_RX1_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +CAN0_RX1_IRQHandler + B CAN0_RX1_IRQHandler + + PUBWEAK CAN0_EWMC_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +CAN0_EWMC_IRQHandler + B CAN0_EWMC_IRQHandler + + PUBWEAK EXTI5_9_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +EXTI5_9_IRQHandler + B EXTI5_9_IRQHandler + + PUBWEAK TIMER0_BRK_TIMER8_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +TIMER0_BRK_TIMER8_IRQHandler + B TIMER0_BRK_TIMER8_IRQHandler + + PUBWEAK TIMER0_UP_TIMER9_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +TIMER0_UP_TIMER9_IRQHandler + B TIMER0_UP_TIMER9_IRQHandler + + PUBWEAK TIMER0_TRG_CMT_TIMER10_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +TIMER0_TRG_CMT_TIMER10_IRQHandler + B TIMER0_TRG_CMT_TIMER10_IRQHandler + + PUBWEAK TIMER0_Channel_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +TIMER0_Channel_IRQHandler + B TIMER0_Channel_IRQHandler + + PUBWEAK TIMER1_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +TIMER1_IRQHandler + B TIMER1_IRQHandler + + PUBWEAK TIMER2_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +TIMER2_IRQHandler + B TIMER2_IRQHandler + + PUBWEAK TIMER3_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +TIMER3_IRQHandler + B TIMER3_IRQHandler + + PUBWEAK I2C0_EV_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +I2C0_EV_IRQHandler + B I2C0_EV_IRQHandler + + PUBWEAK I2C0_ER_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +I2C0_ER_IRQHandler + B I2C0_ER_IRQHandler + + PUBWEAK I2C1_EV_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +I2C1_EV_IRQHandler + B I2C1_EV_IRQHandler + + PUBWEAK I2C1_ER_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +I2C1_ER_IRQHandler + B I2C1_ER_IRQHandler + + PUBWEAK SPI0_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +SPI0_IRQHandler + B SPI0_IRQHandler + + PUBWEAK SPI1_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +SPI1_IRQHandler + B SPI1_IRQHandler + + PUBWEAK USART0_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +USART0_IRQHandler + B USART0_IRQHandler + + PUBWEAK USART1_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +USART1_IRQHandler + B USART1_IRQHandler + + PUBWEAK USART2_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +USART2_IRQHandler + B USART2_IRQHandler + + PUBWEAK EXTI10_15_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +EXTI10_15_IRQHandler + B EXTI10_15_IRQHandler + + PUBWEAK RTC_Alarm_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +RTC_Alarm_IRQHandler + B RTC_Alarm_IRQHandler + + PUBWEAK USBD_WKUP_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +USBD_WKUP_IRQHandler + B USBD_WKUP_IRQHandler + + PUBWEAK TIMER7_BRK_TIMER11_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +TIMER7_BRK_TIMER11_IRQHandler + B TIMER7_BRK_TIMER11_IRQHandler + + PUBWEAK TIMER7_UP_TIMER12_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +TIMER7_UP_TIMER12_IRQHandler + B TIMER7_UP_TIMER12_IRQHandler + + PUBWEAK TIMER7_TRG_CMT_TIMER13_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +TIMER7_TRG_CMT_TIMER13_IRQHandler + B TIMER7_TRG_CMT_TIMER13_IRQHandler + + PUBWEAK TIMER7_Channel_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +TIMER7_Channel_IRQHandler + B TIMER7_Channel_IRQHandler + + PUBWEAK ADC2_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +ADC2_IRQHandler + B ADC2_IRQHandler + + PUBWEAK EXMC_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +EXMC_IRQHandler + B EXMC_IRQHandler + + PUBWEAK SDIO_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +SDIO_IRQHandler + B SDIO_IRQHandler + + PUBWEAK TIMER4_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +TIMER4_IRQHandler + B TIMER4_IRQHandler + + PUBWEAK SPI2_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +SPI2_IRQHandler + B SPI2_IRQHandler + + PUBWEAK UART3_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +UART3_IRQHandler + B UART3_IRQHandler + + PUBWEAK UART4_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +UART4_IRQHandler + B UART4_IRQHandler + + PUBWEAK TIMER5_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +TIMER5_IRQHandler + B TIMER5_IRQHandler + + PUBWEAK TIMER6_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +TIMER6_IRQHandler + B TIMER6_IRQHandler + + PUBWEAK DMA1_Channel0_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +DMA1_Channel0_IRQHandler + B DMA1_Channel0_IRQHandler + + PUBWEAK DMA1_Channel1_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +DMA1_Channel1_IRQHandler + B DMA1_Channel1_IRQHandler + + PUBWEAK DMA1_Channel2_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +DMA1_Channel2_IRQHandler + B DMA1_Channel2_IRQHandler + + PUBWEAK DMA1_Channel3_4_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +DMA1_Channel3_4_IRQHandler + B DMA1_Channel3_4_IRQHandler + + END diff --git a/bsp/gd32/libraries/GD32F10x_Firmware_Library/CMSIS/GD/GD32F10x/Source/system_gd32f10x.c b/bsp/gd32/libraries/GD32F10x_Firmware_Library/CMSIS/GD/GD32F10x/Source/system_gd32f10x.c new file mode 100644 index 0000000000..5327aeb423 --- /dev/null +++ b/bsp/gd32/libraries/GD32F10x_Firmware_Library/CMSIS/GD/GD32F10x/Source/system_gd32f10x.c @@ -0,0 +1,1041 @@ +/*! + \file system_gd32f10x.c + \brief CMSIS Cortex-M3 Device Peripheral Access Layer Source File for + GD32F10x Device Series +*/ + +/* + Copyright (c) 2012 ARM LIMITED + + All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +/* This file refers the CMSIS standard, some adjustments are made according to GigaDevice chips */ + +#include "gd32f10x.h" + +/* system frequency define */ +#define __IRC8M (IRC8M_VALUE) /* internal 8 MHz RC oscillator frequency */ +#define __HXTAL (HXTAL_VALUE) /* high speed crystal oscillator frequency */ +#define __SYS_OSC_CLK (__IRC8M) /* main oscillator frequency */ + +#define VECT_TAB_OFFSET (uint32_t)0x00 /* vector table base offset */ + +/* select a system clock by uncommenting the following line */ +/* use IRC8M */ +//#define __SYSTEM_CLOCK_48M_PLL_IRC8M (uint32_t)(48000000) +//#define __SYSTEM_CLOCK_72M_PLL_IRC8M (uint32_t)(72000000) +//#define __SYSTEM_CLOCK_108M_PLL_IRC8M (uint32_t)(108000000) + +/* use HXTAL (XD series CK_HXTAL = 8M, CL series CK_HXTAL = 25M) */ +//#define __SYSTEM_CLOCK_HXTAL (uint32_t)(__HXTAL) +//#define __SYSTEM_CLOCK_24M_PLL_HXTAL (uint32_t)(24000000) +//#define __SYSTEM_CLOCK_36M_PLL_HXTAL (uint32_t)(36000000) +//#define __SYSTEM_CLOCK_48M_PLL_HXTAL (uint32_t)(48000000) +//#define __SYSTEM_CLOCK_56M_PLL_HXTAL (uint32_t)(56000000) +//#define __SYSTEM_CLOCK_72M_PLL_HXTAL (uint32_t)(72000000) +//#define __SYSTEM_CLOCK_96M_PLL_HXTAL (uint32_t)(96000000) +#define __SYSTEM_CLOCK_108M_PLL_HXTAL (uint32_t)(108000000) + +#define SEL_IRC8M 0x00U +#define SEL_HXTAL 0x01U +#define SEL_PLL 0x02U + +/* set the system clock frequency and declare the system clock configuration function */ +#ifdef __SYSTEM_CLOCK_48M_PLL_IRC8M +uint32_t SystemCoreClock = __SYSTEM_CLOCK_48M_PLL_IRC8M; +static void system_clock_48m_irc8m(void); +#elif defined (__SYSTEM_CLOCK_72M_PLL_IRC8M) +uint32_t SystemCoreClock = __SYSTEM_CLOCK_72M_PLL_IRC8M; +static void system_clock_72m_irc8m(void); +#elif defined (__SYSTEM_CLOCK_108M_PLL_IRC8M) +uint32_t SystemCoreClock = __SYSTEM_CLOCK_108M_PLL_IRC8M; +static void system_clock_108m_irc8m(void); + +#elif defined (__SYSTEM_CLOCK_HXTAL) +uint32_t SystemCoreClock = __SYSTEM_CLOCK_HXTAL; +static void system_clock_hxtal(void); +#elif defined (__SYSTEM_CLOCK_24M_PLL_HXTAL) +uint32_t SystemCoreClock = __SYSTEM_CLOCK_24M_PLL_HXTAL; +static void system_clock_24m_hxtal(void); +#elif defined (__SYSTEM_CLOCK_36M_PLL_HXTAL) +uint32_t SystemCoreClock = __SYSTEM_CLOCK_36M_PLL_HXTAL; +static void system_clock_36m_hxtal(void); +#elif defined (__SYSTEM_CLOCK_48M_PLL_HXTAL) +uint32_t SystemCoreClock = __SYSTEM_CLOCK_48M_PLL_HXTAL; +static void system_clock_48m_hxtal(void); +#elif defined (__SYSTEM_CLOCK_56M_PLL_HXTAL) +uint32_t SystemCoreClock = __SYSTEM_CLOCK_56M_PLL_HXTAL; +static void system_clock_56m_hxtal(void); +#elif defined (__SYSTEM_CLOCK_72M_PLL_HXTAL) +uint32_t SystemCoreClock = __SYSTEM_CLOCK_72M_PLL_HXTAL; +static void system_clock_72m_hxtal(void); +#elif defined (__SYSTEM_CLOCK_96M_PLL_HXTAL) +uint32_t SystemCoreClock = __SYSTEM_CLOCK_96M_PLL_HXTAL; +static void system_clock_96m_hxtal(void); +#elif defined (__SYSTEM_CLOCK_108M_PLL_HXTAL) +uint32_t SystemCoreClock = __SYSTEM_CLOCK_108M_PLL_HXTAL; +static void system_clock_108m_hxtal(void); +#endif /* __SYSTEM_CLOCK_48M_PLL_IRC8M */ + +/* configure the system clock */ +static void system_clock_config(void); + +/*! + \brief configure the system clock + \param[in] none + \param[out] none + \retval none +*/ +static void system_clock_config(void) +{ +#ifdef __SYSTEM_CLOCK_HXTAL + system_clock_hxtal(); +#elif defined (__SYSTEM_CLOCK_24M_PLL_HXTAL) + system_clock_24m_hxtal(); +#elif defined (__SYSTEM_CLOCK_36M_PLL_HXTAL) + system_clock_36m_hxtal(); +#elif defined (__SYSTEM_CLOCK_48M_PLL_HXTAL) + system_clock_48m_hxtal(); +#elif defined (__SYSTEM_CLOCK_56M_PLL_HXTAL) + system_clock_56m_hxtal(); +#elif defined (__SYSTEM_CLOCK_72M_PLL_HXTAL) + system_clock_72m_hxtal(); +#elif defined (__SYSTEM_CLOCK_96M_PLL_HXTAL) + system_clock_96m_hxtal(); +#elif defined (__SYSTEM_CLOCK_108M_PLL_HXTAL) + system_clock_108m_hxtal(); + +#elif defined (__SYSTEM_CLOCK_48M_PLL_IRC8M) + system_clock_48m_irc8m(); +#elif defined (__SYSTEM_CLOCK_72M_PLL_IRC8M) + system_clock_72m_irc8m(); +#elif defined (__SYSTEM_CLOCK_108M_PLL_IRC8M) + system_clock_108m_irc8m(); +#endif /* __SYSTEM_CLOCK_HXTAL */ +} + +/*! + \brief setup the microcontroller system, initialize the system + \param[in] none + \param[out] none + \retval none +*/ +void SystemInit(void) +{ + /* reset the RCC clock configuration to the default reset state */ + /* enable IRC8M */ + RCU_CTL |= RCU_CTL_IRC8MEN; + + /* reset SCS, AHBPSC, APB1PSC, APB2PSC, ADCPSC, CKOUT0SEL bits */ + RCU_CFG0 &= ~(RCU_CFG0_SCS | RCU_CFG0_AHBPSC | RCU_CFG0_APB1PSC | RCU_CFG0_APB2PSC | + RCU_CFG0_ADCPSC | RCU_CFG0_ADCPSC_2 | RCU_CFG0_CKOUT0SEL); + + /* reset HXTALEN, CKMEN, PLLEN bits */ + RCU_CTL &= ~(RCU_CTL_HXTALEN | RCU_CTL_CKMEN | RCU_CTL_PLLEN); + + /* Reset HXTALBPS bit */ + RCU_CTL &= ~(RCU_CTL_HXTALBPS); + + /* reset PLLSEL, PREDV0_LSB, PLLMF, USBFSPSC bits */ + +#ifdef GD32F10X_CL + RCU_CFG0 &= ~(RCU_CFG0_PLLSEL | RCU_CFG0_PREDV0_LSB | RCU_CFG0_PLLMF | + RCU_CFG0_USBFSPSC | RCU_CFG0_PLLMF_4); + + RCU_CFG1 = 0x00000000U; +#else + RCU_CFG0 &= ~(RCU_CFG0_PLLSEL | RCU_CFG0_PREDV0 | RCU_CFG0_PLLMF | + RCU_CFG0_USBDPSC | RCU_CFG0_PLLMF_4); +#endif /* GD32F10X_CL */ + +#if (defined(GD32F10X_MD) || defined(GD32F10X_HD) || defined(GD32F10X_XD)) + /* reset HXTALEN, CKMEN and PLLEN bits */ + RCU_CTL &= ~(RCU_CTL_PLLEN | RCU_CTL_CKMEN | RCU_CTL_HXTALEN); + /* disable all interrupts */ + RCU_INT = 0x009F0000U; +#elif defined(GD32F10X_CL) + /* Reset HXTALEN, CKMEN, PLLEN, PLL1EN and PLL2EN bits */ + RCU_CTL &= ~(RCU_CTL_PLLEN | RCU_CTL_PLL1EN | RCU_CTL_PLL2EN | RCU_CTL_CKMEN | RCU_CTL_HXTALEN); + /* disable all interrupts */ + RCU_INT = 0x00FF0000U; +#endif + + /* Configure the System clock source, PLL Multiplier, AHB/APBx prescalers and Flash settings */ + system_clock_config(); + +#ifdef VECT_TAB_SRAM + nvic_vector_table_set(NVIC_VECTTAB_RAM, VECT_TAB_OFFSET); +#else + nvic_vector_table_set(NVIC_VECTTAB_FLASH, VECT_TAB_OFFSET); +#endif +} + +/*! + \brief update the SystemCoreClock with current core clock retrieved from cpu registers + \param[in] none + \param[out] none + \retval none +*/ +void SystemCoreClockUpdate(void) +{ + uint32_t scss; + uint32_t pllsel, predv0sel, pllmf, ck_src, idx, clk_exp; +#ifdef GD32F10X_CL + uint32_t predv0, predv1, pll1mf; +#endif /* GD32F10X_CL */ + /* exponent of AHB, APB1 and APB2 clock divider */ + const uint8_t ahb_exp[16] = {0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 6, 7, 8, 9}; + + scss = GET_BITS(RCU_CFG0, 2, 3); + + switch (scss) + { + /* IRC8M is selected as CK_SYS */ + case SEL_IRC8M: + SystemCoreClock = IRC8M_VALUE; + break; + + /* HXTAL is selected as CK_SYS */ + case SEL_HXTAL: + SystemCoreClock = HXTAL_VALUE; + break; + + /* PLL is selected as CK_SYS */ + case SEL_PLL: + /* PLL clock source selection, HXTAL or IRC8M/2 */ + pllsel = (RCU_CFG0 & RCU_CFG0_PLLSEL); + + if(RCU_PLLSRC_IRC8M_DIV2 == pllsel){ + /* PLL clock source is IRC8M/2 */ + ck_src = IRC8M_VALUE / 2U; + }else{ + /* PLL clock source is HXTAL */ + ck_src = HXTAL_VALUE; + +#if (defined(GD32F10X_MD) || defined(GD32F10X_HD) || defined(GD32F10X_XD)) + predv0sel = (RCU_CFG0 & RCU_CFG0_PREDV0); + + /* PREDV0 input source clock divided by 2 */ + if(RCU_CFG0_PREDV0 == predv0sel){ + ck_src = HXTAL_VALUE / 2U; + } +#elif defined(GD32F10X_CL) + predv0sel = (RCU_CFG1 & RCU_CFG1_PREDV0SEL); + + /* source clock use PLL1 */ + if(RCU_PREDV0SRC_CKPLL1 == predv0sel){ + predv1 = ((RCU_CFG1 & RCU_CFG1_PREDV1) >> 4) + 1U; + pll1mf = ((RCU_CFG1 & RCU_CFG1_PLL1MF) >> 8) + 2U; + if(17U == pll1mf){ + pll1mf = 20U; + } + ck_src = (ck_src / predv1) * pll1mf; + } + predv0 = (RCU_CFG1 & RCU_CFG1_PREDV0) + 1U; + ck_src /= predv0; +#endif /* GD32F10X_MD and GD32F10X_HD and GD32F10X_XD */ + } + + /* PLL multiplication factor */ + pllmf = GET_BITS(RCU_CFG0, 18, 21); + + if((RCU_CFG0 & RCU_CFG0_PLLMF_4)){ + pllmf |= 0x10U; + } + + if(pllmf >= 15U){ + pllmf += 1U; + }else{ + pllmf += 2U; + } + + SystemCoreClock = ck_src * pllmf; + +#ifdef GD32F10X_CL + if(15U == pllmf){ + /* PLL source clock multiply by 6.5 */ + SystemCoreClock = ck_src * 6U + ck_src / 2U; + } +#endif /* GD32F10X_CL */ + + break; + + /* IRC8M is selected as CK_SYS */ + default: + SystemCoreClock = IRC8M_VALUE; + break; + } + /* calculate AHB clock frequency */ + idx = GET_BITS(RCU_CFG0, 4, 7); + clk_exp = ahb_exp[idx]; + SystemCoreClock = SystemCoreClock >> clk_exp; +} + +#ifdef __SYSTEM_CLOCK_HXTAL +/*! + \brief configure the system clock to HXTAL + \param[in] none + \param[out] none + \retval none +*/ +static void system_clock_hxtal(void) +{ + uint32_t timeout = 0U; + uint32_t stab_flag = 0U; + + /* enable HXTAL */ + RCU_CTL |= RCU_CTL_HXTALEN; + + /* wait until HXTAL is stable or the startup time is longer than HXTAL_STARTUP_TIMEOUT */ + do{ + timeout++; + stab_flag = (RCU_CTL & RCU_CTL_HXTALSTB); + }while((0U == stab_flag) && (HXTAL_STARTUP_TIMEOUT != timeout)); + + /* if fail */ + if(0U == (RCU_CTL & RCU_CTL_HXTALSTB)){ + while(1){ + } + } + + /* AHB = SYSCLK */ + RCU_CFG0 |= RCU_AHB_CKSYS_DIV1; + /* APB2 = AHB/1 */ + RCU_CFG0 |= RCU_APB2_CKAHB_DIV1; + /* APB1 = AHB/2 */ + RCU_CFG0 |= RCU_APB1_CKAHB_DIV2; + + /* select HXTAL as system clock */ + RCU_CFG0 &= ~RCU_CFG0_SCS; + RCU_CFG0 |= RCU_CKSYSSRC_HXTAL; + + /* wait until HXTAL is selected as system clock */ + while(0 == (RCU_CFG0 & RCU_SCSS_HXTAL)){ + } +} + +#elif defined (__SYSTEM_CLOCK_24M_PLL_HXTAL) +/*! + \brief configure the system clock to 24M by PLL which selects HXTAL(MD/HD/XD:8M; CL:25M) as its clock source + \param[in] none + \param[out] none + \retval none +*/ +static void system_clock_24m_hxtal(void) +{ + uint32_t timeout = 0U; + uint32_t stab_flag = 0U; + + /* enable HXTAL */ + RCU_CTL |= RCU_CTL_HXTALEN; + + /* wait until HXTAL is stable or the startup time is longer than HXTAL_STARTUP_TIMEOUT */ + do{ + timeout++; + stab_flag = (RCU_CTL & RCU_CTL_HXTALSTB); + }while((0U == stab_flag) && (HXTAL_STARTUP_TIMEOUT != timeout)); + + /* if fail */ + if(0U == (RCU_CTL & RCU_CTL_HXTALSTB)){ + while(1){ + } + } + + /* HXTAL is stable */ + /* AHB = SYSCLK */ + RCU_CFG0 |= RCU_AHB_CKSYS_DIV1; + /* APB2 = AHB/1 */ + RCU_CFG0 |= RCU_APB2_CKAHB_DIV1; + /* APB1 = AHB/2 */ + RCU_CFG0 |= RCU_APB1_CKAHB_DIV2; + +#if (defined(GD32F10X_MD) || defined(GD32F10X_HD) || defined(GD32F10X_XD)) + /* select HXTAL/2 as clock source */ + RCU_CFG0 &= ~(RCU_CFG0_PLLSEL | RCU_CFG0_PREDV0); + RCU_CFG0 |= (RCU_PLLSRC_HXTAL | RCU_CFG0_PREDV0); + + /* CK_PLL = (CK_HXTAL/2) * 6 = 24 MHz */ + RCU_CFG0 &= ~(RCU_CFG0_PLLMF | RCU_CFG0_PLLMF_4); + RCU_CFG0 |= RCU_PLL_MUL6; + +#elif defined(GD32F10X_CL) + /* CK_PLL = (CK_PREDIV0) * 6 = 24 MHz */ + RCU_CFG0 &= ~(RCU_CFG0_PLLMF | RCU_CFG0_PLLMF_4); + RCU_CFG0 |= (RCU_PLLSRC_HXTAL | RCU_PLL_MUL6); + + /* CK_PREDIV0 = (CK_HXTAL)/5 *8 /10 = 4 MHz */ + RCU_CFG1 &= ~(RCU_CFG1_PREDV0SEL | RCU_CFG1_PLL1MF | RCU_CFG1_PREDV1 | RCU_CFG1_PREDV0); + RCU_CFG1 |= (RCU_PREDV0SRC_CKPLL1 | RCU_PLL1_MUL8 | RCU_PREDV1_DIV5 | RCU_PREDV0_DIV10); + + /* enable PLL1 */ + RCU_CTL |= RCU_CTL_PLL1EN; + /* wait till PLL1 is ready */ + while((RCU_CTL & RCU_CTL_PLL1STB) == 0){ + } +#endif /* GD32F10X_MD and GD32F10X_HD and GD32F10X_XD */ + + /* enable PLL */ + RCU_CTL |= RCU_CTL_PLLEN; + + /* wait until PLL is stable */ + while(0U == (RCU_CTL & RCU_CTL_PLLSTB)){ + } + + /* select PLL as system clock */ + RCU_CFG0 &= ~RCU_CFG0_SCS; + RCU_CFG0 |= RCU_CKSYSSRC_PLL; + + /* wait until PLL is selected as system clock */ + while(0U == (RCU_CFG0 & RCU_SCSS_PLL)){ + } +} + +#elif defined (__SYSTEM_CLOCK_36M_PLL_HXTAL) +/*! + \brief configure the system clock to 36M by PLL which selects HXTAL(MD/HD/XD:8M; CL:25M) as its clock source + \param[in] none + \param[out] none + \retval none +*/ +static void system_clock_36m_hxtal(void) +{ + uint32_t timeout = 0U; + uint32_t stab_flag = 0U; + + /* enable HXTAL */ + RCU_CTL |= RCU_CTL_HXTALEN; + + /* wait until HXTAL is stable or the startup time is longer than HXTAL_STARTUP_TIMEOUT */ + do{ + timeout++; + stab_flag = (RCU_CTL & RCU_CTL_HXTALSTB); + }while((0U == stab_flag) && (HXTAL_STARTUP_TIMEOUT != timeout)); + + /* if fail */ + if(0U == (RCU_CTL & RCU_CTL_HXTALSTB)){ + while(1){ + } + } + + /* HXTAL is stable */ + /* AHB = SYSCLK */ + RCU_CFG0 |= RCU_AHB_CKSYS_DIV1; + /* APB2 = AHB/1 */ + RCU_CFG0 |= RCU_APB2_CKAHB_DIV1; + /* APB1 = AHB/2 */ + RCU_CFG0 |= RCU_APB1_CKAHB_DIV2; + +#if (defined(GD32F10X_MD) || defined(GD32F10X_HD) || defined(GD32F10X_XD)) + /* select HXTAL/2 as clock source */ + RCU_CFG0 &= ~(RCU_CFG0_PLLSEL | RCU_CFG0_PREDV0); + RCU_CFG0 |= (RCU_PLLSRC_HXTAL | RCU_CFG0_PREDV0); + + /* CK_PLL = (CK_HXTAL/2) * 9 = 36 MHz */ + RCU_CFG0 &= ~(RCU_CFG0_PLLMF | RCU_CFG0_PLLMF_4); + RCU_CFG0 |= RCU_PLL_MUL9; + +#elif defined(GD32F10X_CL) + /* CK_PLL = (CK_PREDIV0) * 9 = 36 MHz */ + RCU_CFG0 &= ~(RCU_CFG0_PLLMF | RCU_CFG0_PLLMF_4); + RCU_CFG0 |= (RCU_PLLSRC_HXTAL | RCU_PLL_MUL9); + + /* CK_PREDIV0 = (CK_HXTAL)/5 *8 /10 = 4 MHz */ + RCU_CFG1 &= ~(RCU_CFG1_PREDV0SEL | RCU_CFG1_PLL1MF | RCU_CFG1_PREDV1 | RCU_CFG1_PREDV0); + RCU_CFG1 |= (RCU_PREDV0SRC_CKPLL1 | RCU_PLL1_MUL8 | RCU_PREDV1_DIV5 | RCU_PREDV0_DIV10); + + /* enable PLL1 */ + RCU_CTL |= RCU_CTL_PLL1EN; + /* wait till PLL1 is ready */ + while((RCU_CTL & RCU_CTL_PLL1STB) == 0){ + } +#endif /* GD32F10X_MD and GD32F10X_HD and GD32F10X_XD */ + + /* enable PLL */ + RCU_CTL |= RCU_CTL_PLLEN; + + /* wait until PLL is stable */ + while(0U == (RCU_CTL & RCU_CTL_PLLSTB)){ + } + + /* select PLL as system clock */ + RCU_CFG0 &= ~RCU_CFG0_SCS; + RCU_CFG0 |= RCU_CKSYSSRC_PLL; + + /* wait until PLL is selected as system clock */ + while(0U == (RCU_CFG0 & RCU_SCSS_PLL)){ + } +} + +#elif defined (__SYSTEM_CLOCK_48M_PLL_HXTAL) +/*! + \brief configure the system clock to 48M by PLL which selects HXTAL(MD/HD/XD:8M; CL:25M) as its clock source + \param[in] none + \param[out] none + \retval none +*/ +static void system_clock_48m_hxtal(void) +{ + uint32_t timeout = 0U; + uint32_t stab_flag = 0U; + + /* enable HXTAL */ + RCU_CTL |= RCU_CTL_HXTALEN; + + /* wait until HXTAL is stable or the startup time is longer than HXTAL_STARTUP_TIMEOUT */ + do{ + timeout++; + stab_flag = (RCU_CTL & RCU_CTL_HXTALSTB); + }while((0U == stab_flag) && (HXTAL_STARTUP_TIMEOUT != timeout)); + + /* if fail */ + if(0U == (RCU_CTL & RCU_CTL_HXTALSTB)){ + while(1){ + } + } + + /* HXTAL is stable */ + /* AHB = SYSCLK */ + RCU_CFG0 |= RCU_AHB_CKSYS_DIV1; + /* APB2 = AHB/1 */ + RCU_CFG0 |= RCU_APB2_CKAHB_DIV1; + /* APB1 = AHB/2 */ + RCU_CFG0 |= RCU_APB1_CKAHB_DIV2; + +#if (defined(GD32F10X_MD) || defined(GD32F10X_HD) || defined(GD32F10X_XD)) + /* select HXTAL/2 as clock source */ + RCU_CFG0 &= ~(RCU_CFG0_PLLSEL | RCU_CFG0_PREDV0); + RCU_CFG0 |= (RCU_PLLSRC_HXTAL | RCU_CFG0_PREDV0); + + /* CK_PLL = (CK_HXTAL/2) * 12 = 48 MHz */ + RCU_CFG0 &= ~(RCU_CFG0_PLLMF | RCU_CFG0_PLLMF_4); + RCU_CFG0 |= RCU_PLL_MUL12; + +#elif defined(GD32F10X_CL) + /* CK_PLL = (CK_PREDIV0) * 12 = 48 MHz */ + RCU_CFG0 &= ~(RCU_CFG0_PLLMF | RCU_CFG0_PLLMF_4); + RCU_CFG0 |= (RCU_PLLSRC_HXTAL | RCU_PLL_MUL12); + + /* CK_PREDIV0 = (CK_HXTAL)/5 *8 /10 = 4 MHz */ + RCU_CFG1 &= ~(RCU_CFG1_PREDV0SEL | RCU_CFG1_PLL1MF | RCU_CFG1_PREDV1 | RCU_CFG1_PREDV0); + RCU_CFG1 |= (RCU_PREDV0SRC_CKPLL1 | RCU_PLL1_MUL8 | RCU_PREDV1_DIV5 | RCU_PREDV0_DIV10); + + /* enable PLL1 */ + RCU_CTL |= RCU_CTL_PLL1EN; + /* wait till PLL1 is ready */ + while((RCU_CTL & RCU_CTL_PLL1STB) == 0){ + } +#endif /* GD32F10X_MD and GD32F10X_HD and GD32F10X_XD */ + + /* enable PLL */ + RCU_CTL |= RCU_CTL_PLLEN; + + /* wait until PLL is stable */ + while(0U == (RCU_CTL & RCU_CTL_PLLSTB)){ + } + + /* select PLL as system clock */ + RCU_CFG0 &= ~RCU_CFG0_SCS; + RCU_CFG0 |= RCU_CKSYSSRC_PLL; + + /* wait until PLL is selected as system clock */ + while(0U == (RCU_CFG0 & RCU_SCSS_PLL)){ + } +} + +#elif defined (__SYSTEM_CLOCK_56M_PLL_HXTAL) +/*! + \brief configure the system clock to 56M by PLL which selects HXTAL(MD/HD/XD:8M; CL:25M) as its clock source + \param[in] none + \param[out] none + \retval none +*/ +static void system_clock_56m_hxtal(void) +{ + uint32_t timeout = 0U; + uint32_t stab_flag = 0U; + + /* enable HXTAL */ + RCU_CTL |= RCU_CTL_HXTALEN; + + /* wait until HXTAL is stable or the startup time is longer than HXTAL_STARTUP_TIMEOUT */ + do{ + timeout++; + stab_flag = (RCU_CTL & RCU_CTL_HXTALSTB); + }while((0U == stab_flag) && (HXTAL_STARTUP_TIMEOUT != timeout)); + + /* if fail */ + if(0U == (RCU_CTL & RCU_CTL_HXTALSTB)){ + while(1){ + } + } + + /* HXTAL is stable */ + /* AHB = SYSCLK */ + RCU_CFG0 |= RCU_AHB_CKSYS_DIV1; + /* APB2 = AHB/1 */ + RCU_CFG0 |= RCU_APB2_CKAHB_DIV1; + /* APB1 = AHB/2 */ + RCU_CFG0 |= RCU_APB1_CKAHB_DIV2; + +#if (defined(GD32F10X_MD) || defined(GD32F10X_HD) || defined(GD32F10X_XD)) + /* select HXTAL/2 as clock source */ + RCU_CFG0 &= ~(RCU_CFG0_PLLSEL | RCU_CFG0_PREDV0); + RCU_CFG0 |= (RCU_PLLSRC_HXTAL | RCU_CFG0_PREDV0); + + /* CK_PLL = (CK_HXTAL/2) * 14 = 56 MHz */ + RCU_CFG0 &= ~(RCU_CFG0_PLLMF | RCU_CFG0_PLLMF_4); + RCU_CFG0 |= RCU_PLL_MUL14; + +#elif defined(GD32F10X_CL) + /* CK_PLL = (CK_PREDIV0) * 14 = 56 MHz */ + RCU_CFG0 &= ~(RCU_CFG0_PLLMF | RCU_CFG0_PLLMF_4); + RCU_CFG0 |= (RCU_PLLSRC_HXTAL | RCU_PLL_MUL14); + + /* CK_PREDIV0 = (CK_HXTAL)/5 *8 /10 = 4 MHz */ + RCU_CFG1 &= ~(RCU_CFG1_PREDV0SEL | RCU_CFG1_PLL1MF | RCU_CFG1_PREDV1 | RCU_CFG1_PREDV0); + RCU_CFG1 |= (RCU_PREDV0SRC_CKPLL1 | RCU_PLL1_MUL8 | RCU_PREDV1_DIV5 | RCU_PREDV0_DIV10); + + /* enable PLL1 */ + RCU_CTL |= RCU_CTL_PLL1EN; + /* wait till PLL1 is ready */ + while((RCU_CTL & RCU_CTL_PLL1STB) == 0){ + } +#endif /* GD32F10X_MD and GD32F10X_HD and GD32F10X_XD */ + + /* enable PLL */ + RCU_CTL |= RCU_CTL_PLLEN; + + /* wait until PLL is stable */ + while(0U == (RCU_CTL & RCU_CTL_PLLSTB)){ + } + + /* select PLL as system clock */ + RCU_CFG0 &= ~RCU_CFG0_SCS; + RCU_CFG0 |= RCU_CKSYSSRC_PLL; + + /* wait until PLL is selected as system clock */ + while(0U == (RCU_CFG0 & RCU_SCSS_PLL)){ + } +} + +#elif defined (__SYSTEM_CLOCK_72M_PLL_HXTAL) +/*! + \brief configure the system clock to 72M by PLL which selects HXTAL(MD/HD/XD:8M; CL:25M) as its clock source + \param[in] none + \param[out] none + \retval none +*/ +static void system_clock_72m_hxtal(void) +{ + uint32_t timeout = 0U; + uint32_t stab_flag = 0U; + + /* enable HXTAL */ + RCU_CTL |= RCU_CTL_HXTALEN; + + /* wait until HXTAL is stable or the startup time is longer than HXTAL_STARTUP_TIMEOUT */ + do{ + timeout++; + stab_flag = (RCU_CTL & RCU_CTL_HXTALSTB); + }while((0U == stab_flag) && (HXTAL_STARTUP_TIMEOUT != timeout)); + + /* if fail */ + if(0U == (RCU_CTL & RCU_CTL_HXTALSTB)){ + while(1){ + } + } + + /* HXTAL is stable */ + /* AHB = SYSCLK */ + RCU_CFG0 |= RCU_AHB_CKSYS_DIV1; + /* APB2 = AHB/1 */ + RCU_CFG0 |= RCU_APB2_CKAHB_DIV1; + /* APB1 = AHB/2 */ + RCU_CFG0 |= RCU_APB1_CKAHB_DIV2; + +#if (defined(GD32F10X_MD) || defined(GD32F10X_HD) || defined(GD32F10X_XD)) + /* select HXTAL/2 as clock source */ + RCU_CFG0 &= ~(RCU_CFG0_PLLSEL | RCU_CFG0_PREDV0); + RCU_CFG0 |= (RCU_PLLSRC_HXTAL | RCU_CFG0_PREDV0); + + /* CK_PLL = (CK_HXTAL/2) * 18 = 72 MHz */ + RCU_CFG0 &= ~(RCU_CFG0_PLLMF | RCU_CFG0_PLLMF_4); + RCU_CFG0 |= RCU_PLL_MUL18; + +#elif defined(GD32F10X_CL) + /* CK_PLL = (CK_PREDIV0) * 18 = 72 MHz */ + RCU_CFG0 &= ~(RCU_CFG0_PLLMF | RCU_CFG0_PLLMF_4); + RCU_CFG0 |= (RCU_PLLSRC_HXTAL | RCU_PLL_MUL18); + + /* CK_PREDIV0 = (CK_HXTAL)/5 *8 /10 = 4 MHz */ + RCU_CFG1 &= ~(RCU_CFG1_PREDV0SEL | RCU_CFG1_PLL1MF | RCU_CFG1_PREDV1 | RCU_CFG1_PREDV0); + RCU_CFG1 |= (RCU_PREDV0SRC_CKPLL1 | RCU_PLL1_MUL8 | RCU_PREDV1_DIV5 | RCU_PREDV0_DIV10); + + /* enable PLL1 */ + RCU_CTL |= RCU_CTL_PLL1EN; + /* wait till PLL1 is ready */ + while((RCU_CTL & RCU_CTL_PLL1STB) == 0){ + } +#endif /* GD32F10X_MD and GD32F10X_HD and GD32F10X_XD */ + + /* enable PLL */ + RCU_CTL |= RCU_CTL_PLLEN; + + /* wait until PLL is stable */ + while(0U == (RCU_CTL & RCU_CTL_PLLSTB)){ + } + + /* select PLL as system clock */ + RCU_CFG0 &= ~RCU_CFG0_SCS; + RCU_CFG0 |= RCU_CKSYSSRC_PLL; + + /* wait until PLL is selected as system clock */ + while(0U == (RCU_CFG0 & RCU_SCSS_PLL)){ + } +} + +#elif defined (__SYSTEM_CLOCK_96M_PLL_HXTAL) +/*! + \brief configure the system clock to 96M by PLL which selects HXTAL(MD/HD/XD:8M; CL:25M) as its clock source + \param[in] none + \param[out] none + \retval none +*/ +static void system_clock_96m_hxtal(void) +{ + uint32_t timeout = 0U; + uint32_t stab_flag = 0U; + + /* enable HXTAL */ + RCU_CTL |= RCU_CTL_HXTALEN; + + /* wait until HXTAL is stable or the startup time is longer than HXTAL_STARTUP_TIMEOUT */ + do{ + timeout++; + stab_flag = (RCU_CTL & RCU_CTL_HXTALSTB); + }while((0U == stab_flag) && (HXTAL_STARTUP_TIMEOUT != timeout)); + + /* if fail */ + if(0U == (RCU_CTL & RCU_CTL_HXTALSTB)){ + while(1){ + } + } + + /* HXTAL is stable */ + /* AHB = SYSCLK */ + RCU_CFG0 |= RCU_AHB_CKSYS_DIV1; + /* APB2 = AHB/1 */ + RCU_CFG0 |= RCU_APB2_CKAHB_DIV1; + /* APB1 = AHB/2 */ + RCU_CFG0 |= RCU_APB1_CKAHB_DIV2; + +#if (defined(GD32F10X_MD) || defined(GD32F10X_HD) || defined(GD32F10X_XD)) + /* select HXTAL/2 as clock source */ + RCU_CFG0 &= ~(RCU_CFG0_PLLSEL | RCU_CFG0_PREDV0); + RCU_CFG0 |= (RCU_PLLSRC_HXTAL | RCU_CFG0_PREDV0); + + /* CK_PLL = (CK_HXTAL/2) * 24 = 96 MHz */ + RCU_CFG0 &= ~(RCU_CFG0_PLLMF | RCU_CFG0_PLLMF_4); + RCU_CFG0 |= RCU_PLL_MUL24; + +#elif defined(GD32F10X_CL) + /* CK_PLL = (CK_PREDIV0) * 24 = 96 MHz */ + RCU_CFG0 &= ~(RCU_CFG0_PLLMF | RCU_CFG0_PLLMF_4); + RCU_CFG0 |= (RCU_PLLSRC_HXTAL | RCU_PLL_MUL24); + + /* CK_PREDIV0 = (CK_HXTAL)/5 *8 /10 = 4 MHz */ + RCU_CFG1 &= ~(RCU_CFG1_PREDV0SEL | RCU_CFG1_PLL1MF | RCU_CFG1_PREDV1 | RCU_CFG1_PREDV0); + RCU_CFG1 |= (RCU_PREDV0SRC_CKPLL1 | RCU_PLL1_MUL8 | RCU_PREDV1_DIV5 | RCU_PREDV0_DIV10); + + /* enable PLL1 */ + RCU_CTL |= RCU_CTL_PLL1EN; + /* wait till PLL1 is ready */ + while((RCU_CTL & RCU_CTL_PLL1STB) == 0){ + } +#endif /* GD32F10X_MD and GD32F10X_HD and GD32F10X_XD */ + + /* enable PLL */ + RCU_CTL |= RCU_CTL_PLLEN; + + /* wait until PLL is stable */ + while(0U == (RCU_CTL & RCU_CTL_PLLSTB)){ + } + + /* select PLL as system clock */ + RCU_CFG0 &= ~RCU_CFG0_SCS; + RCU_CFG0 |= RCU_CKSYSSRC_PLL; + + /* wait until PLL is selected as system clock */ + while(0U == (RCU_CFG0 & RCU_SCSS_PLL)){ + } +} + +#elif defined (__SYSTEM_CLOCK_108M_PLL_HXTAL) +/*! + \brief configure the system clock to 108M by PLL which selects HXTAL(MD/HD/XD:8M; CL:25M) as its clock source + \param[in] none + \param[out] none + \retval none +*/ +static void system_clock_108m_hxtal(void) +{ + uint32_t timeout = 0U; + uint32_t stab_flag = 0U; + + /* enable HXTAL */ + RCU_CTL |= RCU_CTL_HXTALEN; + + /* wait until HXTAL is stable or the startup time is longer than HXTAL_STARTUP_TIMEOUT */ + do{ + timeout++; + stab_flag = (RCU_CTL & RCU_CTL_HXTALSTB); + }while((0U == stab_flag) && (HXTAL_STARTUP_TIMEOUT != timeout)); + + /* if fail */ + if(0U == (RCU_CTL & RCU_CTL_HXTALSTB)){ + while(1){ + } + } + + /* HXTAL is stable */ + /* AHB = SYSCLK */ + RCU_CFG0 |= RCU_AHB_CKSYS_DIV1; + /* APB2 = AHB/1 */ + RCU_CFG0 |= RCU_APB2_CKAHB_DIV1; + /* APB1 = AHB/2 */ + RCU_CFG0 |= RCU_APB1_CKAHB_DIV2; + +#if (defined(GD32F10X_MD) || defined(GD32F10X_HD) || defined(GD32F10X_XD)) + /* select HXTAL/2 as clock source */ + RCU_CFG0 &= ~(RCU_CFG0_PLLSEL | RCU_CFG0_PREDV0); + RCU_CFG0 |= (RCU_PLLSRC_HXTAL | RCU_CFG0_PREDV0); + + /* CK_PLL = (CK_HXTAL/2) * 27 = 108 MHz */ + RCU_CFG0 &= ~(RCU_CFG0_PLLMF | RCU_CFG0_PLLMF_4); + RCU_CFG0 |= RCU_PLL_MUL27; + +#elif defined(GD32F10X_CL) + /* CK_PLL = (CK_PREDIV0) * 27 = 108 MHz */ + RCU_CFG0 &= ~(RCU_CFG0_PLLMF | RCU_CFG0_PLLMF_4); + RCU_CFG0 |= (RCU_PLLSRC_HXTAL | RCU_PLL_MUL27); + + /* CK_PREDIV0 = (CK_HXTAL)/5 *8 /10 = 4 MHz */ + RCU_CFG1 &= ~(RCU_CFG1_PREDV0SEL | RCU_CFG1_PLL1MF | RCU_CFG1_PREDV1 | RCU_CFG1_PREDV0); + RCU_CFG1 |= (RCU_PREDV0SRC_CKPLL1 | RCU_PLL1_MUL8 | RCU_PREDV1_DIV5 | RCU_PREDV0_DIV10); + + /* enable PLL1 */ + RCU_CTL |= RCU_CTL_PLL1EN; + /* wait till PLL1 is ready */ + while(0U == (RCU_CTL & RCU_CTL_PLL1STB)){ + } +#endif /* GD32F10X_MD and GD32F10X_HD and GD32F10X_XD */ + + /* enable PLL */ + RCU_CTL |= RCU_CTL_PLLEN; + + /* wait until PLL is stable */ + while(0U == (RCU_CTL & RCU_CTL_PLLSTB)){ + } + + /* select PLL as system clock */ + RCU_CFG0 &= ~RCU_CFG0_SCS; + RCU_CFG0 |= RCU_CKSYSSRC_PLL; + + /* wait until PLL is selected as system clock */ + while(0U == (RCU_CFG0 & RCU_SCSS_PLL)){ + } +} + +#elif defined (__SYSTEM_CLOCK_48M_PLL_IRC8M) +/*! + \brief configure the system clock to 48M by PLL which selects IRC8M as its clock source + \param[in] none + \param[out] none + \retval none +*/ +static void system_clock_48m_irc8m(void) +{ + uint32_t timeout = 0U; + uint32_t stab_flag = 0U; + + /* enable IRC8M */ + RCU_CTL |= RCU_CTL_IRC8MEN; + + /* wait until IRC8M is stable or the startup time is longer than IRC8M_STARTUP_TIMEOUT */ + do{ + timeout++; + stab_flag = (RCU_CTL & RCU_CTL_IRC8MSTB); + } + while((0U == stab_flag) && (IRC8M_STARTUP_TIMEOUT != timeout)); + + /* if fail */ + if(0U == (RCU_CTL & RCU_CTL_IRC8MSTB)){ + while(1){ + } + } + + /* IRC8M is stable */ + /* AHB = SYSCLK */ + RCU_CFG0 |= RCU_AHB_CKSYS_DIV1; + /* APB2 = AHB/1 */ + RCU_CFG0 |= RCU_APB2_CKAHB_DIV1; + /* APB1 = AHB/2 */ + RCU_CFG0 |= RCU_APB1_CKAHB_DIV2; + + /* CK_PLL = (CK_IRC8M/2) * 12 = 48 MHz */ + RCU_CFG0 &= ~(RCU_CFG0_PLLMF | RCU_CFG0_PLLMF_4); + RCU_CFG0 |= RCU_PLL_MUL12; + + /* enable PLL */ + RCU_CTL |= RCU_CTL_PLLEN; + + /* wait until PLL is stable */ + while(0U == (RCU_CTL & RCU_CTL_PLLSTB)){ + } + + /* select PLL as system clock */ + RCU_CFG0 &= ~RCU_CFG0_SCS; + RCU_CFG0 |= RCU_CKSYSSRC_PLL; + + /* wait until PLL is selected as system clock */ + while(0U == (RCU_CFG0 & RCU_SCSS_PLL)){ + } +} + +#elif defined (__SYSTEM_CLOCK_72M_PLL_IRC8M) +/*! + \brief configure the system clock to 72M by PLL which selects IRC8M as its clock source + \param[in] none + \param[out] none + \retval none +*/ +static void system_clock_72m_irc8m(void) +{ + uint32_t timeout = 0U; + uint32_t stab_flag = 0U; + + /* enable IRC8M */ + RCU_CTL |= RCU_CTL_IRC8MEN; + + /* wait until IRC8M is stable or the startup time is longer than IRC8M_STARTUP_TIMEOUT */ + do{ + timeout++; + stab_flag = (RCU_CTL & RCU_CTL_IRC8MSTB); + } + while((0U == stab_flag) && (IRC8M_STARTUP_TIMEOUT != timeout)); + + /* if fail */ + if(0U == (RCU_CTL & RCU_CTL_IRC8MSTB)){ + while(1){ + } + } + + /* IRC8M is stable */ + /* AHB = SYSCLK */ + RCU_CFG0 |= RCU_AHB_CKSYS_DIV1; + /* APB2 = AHB/1 */ + RCU_CFG0 |= RCU_APB2_CKAHB_DIV1; + /* APB1 = AHB/2 */ + RCU_CFG0 |= RCU_APB1_CKAHB_DIV2; + + /* CK_PLL = (CK_IRC8M/2) * 18 = 72 MHz */ + RCU_CFG0 &= ~(RCU_CFG0_PLLMF | RCU_CFG0_PLLMF_4); + RCU_CFG0 |= RCU_PLL_MUL18; + + /* enable PLL */ + RCU_CTL |= RCU_CTL_PLLEN; + + /* wait until PLL is stable */ + while(0U == (RCU_CTL & RCU_CTL_PLLSTB)){ + } + + /* select PLL as system clock */ + RCU_CFG0 &= ~RCU_CFG0_SCS; + RCU_CFG0 |= RCU_CKSYSSRC_PLL; + + /* wait until PLL is selected as system clock */ + while(0U == (RCU_CFG0 & RCU_SCSS_PLL)){ + } +} + +#elif defined (__SYSTEM_CLOCK_108M_PLL_IRC8M) +/*! + \brief configure the system clock to 108M by PLL which selects IRC8M as its clock source + \param[in] none + \param[out] none + \retval none +*/ +static void system_clock_108m_irc8m(void) +{ + uint32_t timeout = 0U; + uint32_t stab_flag = 0U; + + /* enable IRC8M */ + RCU_CTL |= RCU_CTL_IRC8MEN; + + /* wait until IRC8M is stable or the startup time is longer than IRC8M_STARTUP_TIMEOUT */ + do{ + timeout++; + stab_flag = (RCU_CTL & RCU_CTL_IRC8MSTB); + } + while((0U == stab_flag) && (IRC8M_STARTUP_TIMEOUT != timeout)); + + /* if fail */ + if(0U == (RCU_CTL & RCU_CTL_IRC8MSTB)){ + while(1){ + } + } + + /* IRC8M is stable */ + /* AHB = SYSCLK */ + RCU_CFG0 |= RCU_AHB_CKSYS_DIV1; + /* APB2 = AHB/1 */ + RCU_CFG0 |= RCU_APB2_CKAHB_DIV1; + /* APB1 = AHB/2 */ + RCU_CFG0 |= RCU_APB1_CKAHB_DIV2; + + /* CK_PLL = (CK_IRC8M/2) * 27 = 108 MHz */ + RCU_CFG0 &= ~(RCU_CFG0_PLLMF | RCU_CFG0_PLLMF_4); + RCU_CFG0 |= RCU_PLL_MUL27; + + /* enable PLL */ + RCU_CTL |= RCU_CTL_PLLEN; + + /* wait until PLL is stable */ + while(0U == (RCU_CTL & RCU_CTL_PLLSTB)){ + } + + /* select PLL as system clock */ + RCU_CFG0 &= ~RCU_CFG0_SCS; + RCU_CFG0 |= RCU_CKSYSSRC_PLL; + + /* wait until PLL is selected as system clock */ + while(0U == (RCU_CFG0 & RCU_SCSS_PLL)){ + } +} + +#endif diff --git a/bsp/gd32/libraries/GD32F10x_Firmware_Library/CMSIS/core_cm3.h b/bsp/gd32/libraries/GD32F10x_Firmware_Library/CMSIS/core_cm3.h new file mode 100644 index 0000000000..1b661b4421 --- /dev/null +++ b/bsp/gd32/libraries/GD32F10x_Firmware_Library/CMSIS/core_cm3.h @@ -0,0 +1,1638 @@ +/**************************************************************************//** + * @file core_cm3.h + * @brief CMSIS Cortex-M3 Core Peripheral Access Layer Header File + * @version V3.30 + * @date 17. February 2014 + * + * @note + * + ******************************************************************************/ +/* Copyright (c) 2009 - 2014 ARM LIMITED + + All rights reserved. + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + - Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + - Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + - Neither the name of ARM nor the names of its contributors may be used + to endorse or promote products derived from this software without + specific prior written permission. + * + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDERS AND CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + ---------------------------------------------------------------------------*/ + + +#if defined ( __ICCARM__ ) + #pragma system_include /* treat file as system include file for MISRA check */ +#endif + +#ifdef __cplusplus + extern "C" { +#endif + +#ifndef __CORE_CM3_H_GENERIC +#define __CORE_CM3_H_GENERIC + +/** \page CMSIS_MISRA_Exceptions MISRA-C:2004 Compliance Exceptions + CMSIS violates the following MISRA-C:2004 rules: + + \li Required Rule 8.5, object/function definition in header file.
+ Function definitions in header files are used to allow 'inlining'. + + \li Required Rule 18.4, declaration of union type or object of union type: '{...}'.
+ Unions are used for effective representation of core registers. + + \li Advisory Rule 19.7, Function-like macro defined.
+ Function-like macros are used to allow more efficient code. + */ + + +/******************************************************************************* + * CMSIS definitions + ******************************************************************************/ +/** \ingroup Cortex_M3 + @{ + */ + +/* CMSIS CM3 definitions */ +#define __CM3_CMSIS_VERSION_MAIN (0x03) /*!< [31:16] CMSIS HAL main version */ +#define __CM3_CMSIS_VERSION_SUB (0x20) /*!< [15:0] CMSIS HAL sub version */ +#define __CM3_CMSIS_VERSION ((__CM3_CMSIS_VERSION_MAIN << 16) | \ + __CM3_CMSIS_VERSION_SUB ) /*!< CMSIS HAL version number */ + +#define __CORTEX_M (0x03) /*!< Cortex-M Core */ + + +#if defined ( __CC_ARM ) + #define __ASM __asm /*!< asm keyword for ARM Compiler */ + #define __INLINE __inline /*!< inline keyword for ARM Compiler */ + #define __STATIC_INLINE static __inline + +#elif defined ( __GNUC__ ) + #define __ASM __asm /*!< asm keyword for GNU Compiler */ + #define __INLINE inline /*!< inline keyword for GNU Compiler */ + #define __STATIC_INLINE static inline + +#elif defined ( __ICCARM__ ) + #define __ASM __asm /*!< asm keyword for IAR Compiler */ + #define __INLINE inline /*!< inline keyword for IAR Compiler. Only available in High optimization mode! */ + #define __STATIC_INLINE static inline + +#elif defined ( __TMS470__ ) + #define __ASM __asm /*!< asm keyword for TI CCS Compiler */ + #define __STATIC_INLINE static inline + +#elif defined ( __TASKING__ ) + #define __ASM __asm /*!< asm keyword for TASKING Compiler */ + #define __INLINE inline /*!< inline keyword for TASKING Compiler */ + #define __STATIC_INLINE static inline + +#elif defined ( __CSMC__ ) /* Cosmic */ + #define __packed + #define __ASM _asm /*!< asm keyword for COSMIC Compiler */ + #define __INLINE inline /*use -pc99 on compile line !< inline keyword for COSMIC Compiler */ + #define __STATIC_INLINE static inline + +#endif + +/** __FPU_USED indicates whether an FPU is used or not. This core does not support an FPU at all +*/ +#define __FPU_USED 0 + +#if defined ( __CC_ARM ) + #if defined __TARGET_FPU_VFP + #warning "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" + #endif + +#elif defined ( __GNUC__ ) + #if defined (__VFP_FP__) && !defined(__SOFTFP__) + #warning "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" + #endif + +#elif defined ( __ICCARM__ ) + #if defined __ARMVFP__ + #warning "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" + #endif + +#elif defined ( __TMS470__ ) + #if defined __TI__VFP_SUPPORT____ + #warning "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" + #endif + +#elif defined ( __TASKING__ ) + #if defined __FPU_VFP__ + #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" + #endif + +#elif defined ( __CSMC__ ) /* Cosmic */ + #if ( __CSMC__ & 0x400) // FPU present for parser + #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" + #endif +#endif + +#include /* standard types definitions */ +#include /* Core Instruction Access */ +#include /* Core Function Access */ + +#endif /* __CORE_CM3_H_GENERIC */ + +#ifndef __CMSIS_GENERIC + +#ifndef __CORE_CM3_H_DEPENDANT +#define __CORE_CM3_H_DEPENDANT + +/* check device defines and use defaults */ +#if defined __CHECK_DEVICE_DEFINES + #ifndef __CM3_REV + #define __CM3_REV 0x0200 + #warning "__CM3_REV not defined in device header file; using default!" + #endif + + #ifndef __MPU_PRESENT + #define __MPU_PRESENT 0 + #warning "__MPU_PRESENT not defined in device header file; using default!" + #endif + + #ifndef __NVIC_PRIO_BITS + #define __NVIC_PRIO_BITS 4 + #warning "__NVIC_PRIO_BITS not defined in device header file; using default!" + #endif + + #ifndef __Vendor_SysTickConfig + #define __Vendor_SysTickConfig 0 + #warning "__Vendor_SysTickConfig not defined in device header file; using default!" + #endif +#endif + +/* IO definitions (access restrictions to peripheral registers) */ +/** + \defgroup CMSIS_glob_defs CMSIS Global Defines + + IO Type Qualifiers are used + \li to specify the access to peripheral variables. + \li for automatic generation of peripheral register debug information. +*/ +#ifdef __cplusplus + #define __I volatile /*!< Defines 'read only' permissions */ +#else + #define __I volatile const /*!< Defines 'read only' permissions */ +#endif +#define __O volatile /*!< Defines 'write only' permissions */ +#define __IO volatile /*!< Defines 'read / write' permissions */ + +/*@} end of group Cortex_M3 */ + + + +/******************************************************************************* + * Register Abstraction + Core Register contain: + - Core Register + - Core NVIC Register + - Core SCB Register + - Core SysTick Register + - Core Debug Register + - Core MPU Register + ******************************************************************************/ +/** \defgroup CMSIS_core_register Defines and Type Definitions + \brief Type definitions and defines for Cortex-M processor based devices. +*/ + +/** \ingroup CMSIS_core_register + \defgroup CMSIS_CORE Status and Control Registers + \brief Core Register type definitions. + @{ + */ + +/** \brief Union type to access the Application Program Status Register (APSR). + */ +typedef union +{ + struct + { +#if (__CORTEX_M != 0x04) + uint32_t _reserved0:27; /*!< bit: 0..26 Reserved */ +#else + uint32_t _reserved0:16; /*!< bit: 0..15 Reserved */ + uint32_t GE:4; /*!< bit: 16..19 Greater than or Equal flags */ + uint32_t _reserved1:7; /*!< bit: 20..26 Reserved */ +#endif + uint32_t Q:1; /*!< bit: 27 Saturation condition flag */ + uint32_t V:1; /*!< bit: 28 Overflow condition code flag */ + uint32_t C:1; /*!< bit: 29 Carry condition code flag */ + uint32_t Z:1; /*!< bit: 30 Zero condition code flag */ + uint32_t N:1; /*!< bit: 31 Negative condition code flag */ + } b; /*!< Structure used for bit access */ + uint32_t w; /*!< Type used for word access */ +} APSR_Type; + + +/** \brief Union type to access the Interrupt Program Status Register (IPSR). + */ +typedef union +{ + struct + { + uint32_t ISR:9; /*!< bit: 0.. 8 Exception number */ + uint32_t _reserved0:23; /*!< bit: 9..31 Reserved */ + } b; /*!< Structure used for bit access */ + uint32_t w; /*!< Type used for word access */ +} IPSR_Type; + + +/** \brief Union type to access the Special-Purpose Program Status Registers (xPSR). + */ +typedef union +{ + struct + { + uint32_t ISR:9; /*!< bit: 0.. 8 Exception number */ +#if (__CORTEX_M != 0x04) + uint32_t _reserved0:15; /*!< bit: 9..23 Reserved */ +#else + uint32_t _reserved0:7; /*!< bit: 9..15 Reserved */ + uint32_t GE:4; /*!< bit: 16..19 Greater than or Equal flags */ + uint32_t _reserved1:4; /*!< bit: 20..23 Reserved */ +#endif + uint32_t T:1; /*!< bit: 24 Thumb bit (read 0) */ + uint32_t IT:2; /*!< bit: 25..26 saved IT state (read 0) */ + uint32_t Q:1; /*!< bit: 27 Saturation condition flag */ + uint32_t V:1; /*!< bit: 28 Overflow condition code flag */ + uint32_t C:1; /*!< bit: 29 Carry condition code flag */ + uint32_t Z:1; /*!< bit: 30 Zero condition code flag */ + uint32_t N:1; /*!< bit: 31 Negative condition code flag */ + } b; /*!< Structure used for bit access */ + uint32_t w; /*!< Type used for word access */ +} xPSR_Type; + + +/** \brief Union type to access the Control Registers (CONTROL). + */ +typedef union +{ + struct + { + uint32_t nPRIV:1; /*!< bit: 0 Execution privilege in Thread mode */ + uint32_t SPSEL:1; /*!< bit: 1 Stack to be used */ + uint32_t FPCA:1; /*!< bit: 2 FP extension active flag */ + uint32_t _reserved0:29; /*!< bit: 3..31 Reserved */ + } b; /*!< Structure used for bit access */ + uint32_t w; /*!< Type used for word access */ +} CONTROL_Type; + +/*@} end of group CMSIS_CORE */ + + +/** \ingroup CMSIS_core_register + \defgroup CMSIS_NVIC Nested Vectored Interrupt Controller (NVIC) + \brief Type definitions for the NVIC Registers + @{ + */ + +/** \brief Structure type to access the Nested Vectored Interrupt Controller (NVIC). + */ +typedef struct +{ + __IO uint32_t ISER[8]; /*!< Offset: 0x000 (R/W) Interrupt Set Enable Register */ + uint32_t RESERVED0[24]; + __IO uint32_t ICER[8]; /*!< Offset: 0x080 (R/W) Interrupt Clear Enable Register */ + uint32_t RSERVED1[24]; + __IO uint32_t ISPR[8]; /*!< Offset: 0x100 (R/W) Interrupt Set Pending Register */ + uint32_t RESERVED2[24]; + __IO uint32_t ICPR[8]; /*!< Offset: 0x180 (R/W) Interrupt Clear Pending Register */ + uint32_t RESERVED3[24]; + __IO uint32_t IABR[8]; /*!< Offset: 0x200 (R/W) Interrupt Active bit Register */ + uint32_t RESERVED4[56]; + __IO uint8_t IP[240]; /*!< Offset: 0x300 (R/W) Interrupt Priority Register (8Bit wide) */ + uint32_t RESERVED5[644]; + __O uint32_t STIR; /*!< Offset: 0xE00 ( /W) Software Trigger Interrupt Register */ +} NVIC_Type; + +/* Software Triggered Interrupt Register Definitions */ +#define NVIC_STIR_INTID_Pos 0 /*!< STIR: INTLINESNUM Position */ +#define NVIC_STIR_INTID_Msk (0x1FFUL << NVIC_STIR_INTID_Pos) /*!< STIR: INTLINESNUM Mask */ + +/*@} end of group CMSIS_NVIC */ + + +/** \ingroup CMSIS_core_register + \defgroup CMSIS_SCB System Control Block (SCB) + \brief Type definitions for the System Control Block Registers + @{ + */ + +/** \brief Structure type to access the System Control Block (SCB). + */ +typedef struct +{ + __I uint32_t CPUID; /*!< Offset: 0x000 (R/ ) CPUID Base Register */ + __IO uint32_t ICSR; /*!< Offset: 0x004 (R/W) Interrupt Control and State Register */ + __IO uint32_t VTOR; /*!< Offset: 0x008 (R/W) Vector Table Offset Register */ + __IO uint32_t AIRCR; /*!< Offset: 0x00C (R/W) Application Interrupt and Reset Control Register */ + __IO uint32_t SCR; /*!< Offset: 0x010 (R/W) System Control Register */ + __IO uint32_t CCR; /*!< Offset: 0x014 (R/W) Configuration Control Register */ + __IO uint8_t SHP[12]; /*!< Offset: 0x018 (R/W) System Handlers Priority Registers (4-7, 8-11, 12-15) */ + __IO uint32_t SHCSR; /*!< Offset: 0x024 (R/W) System Handler Control and State Register */ + __IO uint32_t CFSR; /*!< Offset: 0x028 (R/W) Configurable Fault Status Register */ + __IO uint32_t HFSR; /*!< Offset: 0x02C (R/W) HardFault Status Register */ + __IO uint32_t DFSR; /*!< Offset: 0x030 (R/W) Debug Fault Status Register */ + __IO uint32_t MMFAR; /*!< Offset: 0x034 (R/W) MemManage Fault Address Register */ + __IO uint32_t BFAR; /*!< Offset: 0x038 (R/W) BusFault Address Register */ + __IO uint32_t AFSR; /*!< Offset: 0x03C (R/W) Auxiliary Fault Status Register */ + __I uint32_t PFR[2]; /*!< Offset: 0x040 (R/ ) Processor Feature Register */ + __I uint32_t DFR; /*!< Offset: 0x048 (R/ ) Debug Feature Register */ + __I uint32_t ADR; /*!< Offset: 0x04C (R/ ) Auxiliary Feature Register */ + __I uint32_t MMFR[4]; /*!< Offset: 0x050 (R/ ) Memory Model Feature Register */ + __I uint32_t ISAR[5]; /*!< Offset: 0x060 (R/ ) Instruction Set Attributes Register */ + uint32_t RESERVED0[5]; + __IO uint32_t CPACR; /*!< Offset: 0x088 (R/W) Coprocessor Access Control Register */ +} SCB_Type; + +/* SCB CPUID Register Definitions */ +#define SCB_CPUID_IMPLEMENTER_Pos 24 /*!< SCB CPUID: IMPLEMENTER Position */ +#define SCB_CPUID_IMPLEMENTER_Msk (0xFFUL << SCB_CPUID_IMPLEMENTER_Pos) /*!< SCB CPUID: IMPLEMENTER Mask */ + +#define SCB_CPUID_VARIANT_Pos 20 /*!< SCB CPUID: VARIANT Position */ +#define SCB_CPUID_VARIANT_Msk (0xFUL << SCB_CPUID_VARIANT_Pos) /*!< SCB CPUID: VARIANT Mask */ + +#define SCB_CPUID_ARCHITECTURE_Pos 16 /*!< SCB CPUID: ARCHITECTURE Position */ +#define SCB_CPUID_ARCHITECTURE_Msk (0xFUL << SCB_CPUID_ARCHITECTURE_Pos) /*!< SCB CPUID: ARCHITECTURE Mask */ + +#define SCB_CPUID_PARTNO_Pos 4 /*!< SCB CPUID: PARTNO Position */ +#define SCB_CPUID_PARTNO_Msk (0xFFFUL << SCB_CPUID_PARTNO_Pos) /*!< SCB CPUID: PARTNO Mask */ + +#define SCB_CPUID_REVISION_Pos 0 /*!< SCB CPUID: REVISION Position */ +#define SCB_CPUID_REVISION_Msk (0xFUL << SCB_CPUID_REVISION_Pos) /*!< SCB CPUID: REVISION Mask */ + +/* SCB Interrupt Control State Register Definitions */ +#define SCB_ICSR_NMIPENDSET_Pos 31 /*!< SCB ICSR: NMIPENDSET Position */ +#define SCB_ICSR_NMIPENDSET_Msk (1UL << SCB_ICSR_NMIPENDSET_Pos) /*!< SCB ICSR: NMIPENDSET Mask */ + +#define SCB_ICSR_PENDSVSET_Pos 28 /*!< SCB ICSR: PENDSVSET Position */ +#define SCB_ICSR_PENDSVSET_Msk (1UL << SCB_ICSR_PENDSVSET_Pos) /*!< SCB ICSR: PENDSVSET Mask */ + +#define SCB_ICSR_PENDSVCLR_Pos 27 /*!< SCB ICSR: PENDSVCLR Position */ +#define SCB_ICSR_PENDSVCLR_Msk (1UL << SCB_ICSR_PENDSVCLR_Pos) /*!< SCB ICSR: PENDSVCLR Mask */ + +#define SCB_ICSR_PENDSTSET_Pos 26 /*!< SCB ICSR: PENDSTSET Position */ +#define SCB_ICSR_PENDSTSET_Msk (1UL << SCB_ICSR_PENDSTSET_Pos) /*!< SCB ICSR: PENDSTSET Mask */ + +#define SCB_ICSR_PENDSTCLR_Pos 25 /*!< SCB ICSR: PENDSTCLR Position */ +#define SCB_ICSR_PENDSTCLR_Msk (1UL << SCB_ICSR_PENDSTCLR_Pos) /*!< SCB ICSR: PENDSTCLR Mask */ + +#define SCB_ICSR_ISRPREEMPT_Pos 23 /*!< SCB ICSR: ISRPREEMPT Position */ +#define SCB_ICSR_ISRPREEMPT_Msk (1UL << SCB_ICSR_ISRPREEMPT_Pos) /*!< SCB ICSR: ISRPREEMPT Mask */ + +#define SCB_ICSR_ISRPENDING_Pos 22 /*!< SCB ICSR: ISRPENDING Position */ +#define SCB_ICSR_ISRPENDING_Msk (1UL << SCB_ICSR_ISRPENDING_Pos) /*!< SCB ICSR: ISRPENDING Mask */ + +#define SCB_ICSR_VECTPENDING_Pos 12 /*!< SCB ICSR: VECTPENDING Position */ +#define SCB_ICSR_VECTPENDING_Msk (0x1FFUL << SCB_ICSR_VECTPENDING_Pos) /*!< SCB ICSR: VECTPENDING Mask */ + +#define SCB_ICSR_RETTOBASE_Pos 11 /*!< SCB ICSR: RETTOBASE Position */ +#define SCB_ICSR_RETTOBASE_Msk (1UL << SCB_ICSR_RETTOBASE_Pos) /*!< SCB ICSR: RETTOBASE Mask */ + +#define SCB_ICSR_VECTACTIVE_Pos 0 /*!< SCB ICSR: VECTACTIVE Position */ +#define SCB_ICSR_VECTACTIVE_Msk (0x1FFUL << SCB_ICSR_VECTACTIVE_Pos) /*!< SCB ICSR: VECTACTIVE Mask */ + +/* SCB Vector Table Offset Register Definitions */ +#if (__CM3_REV < 0x0201) /* core r2p1 */ +#define SCB_VTOR_TBLBASE_Pos 29 /*!< SCB VTOR: TBLBASE Position */ +#define SCB_VTOR_TBLBASE_Msk (1UL << SCB_VTOR_TBLBASE_Pos) /*!< SCB VTOR: TBLBASE Mask */ + +#define SCB_VTOR_TBLOFF_Pos 7 /*!< SCB VTOR: TBLOFF Position */ +#define SCB_VTOR_TBLOFF_Msk (0x3FFFFFUL << SCB_VTOR_TBLOFF_Pos) /*!< SCB VTOR: TBLOFF Mask */ +#else +#define SCB_VTOR_TBLOFF_Pos 7 /*!< SCB VTOR: TBLOFF Position */ +#define SCB_VTOR_TBLOFF_Msk (0x1FFFFFFUL << SCB_VTOR_TBLOFF_Pos) /*!< SCB VTOR: TBLOFF Mask */ +#endif + +/* SCB Application Interrupt and Reset Control Register Definitions */ +#define SCB_AIRCR_VECTKEY_Pos 16 /*!< SCB AIRCR: VECTKEY Position */ +#define SCB_AIRCR_VECTKEY_Msk (0xFFFFUL << SCB_AIRCR_VECTKEY_Pos) /*!< SCB AIRCR: VECTKEY Mask */ + +#define SCB_AIRCR_VECTKEYSTAT_Pos 16 /*!< SCB AIRCR: VECTKEYSTAT Position */ +#define SCB_AIRCR_VECTKEYSTAT_Msk (0xFFFFUL << SCB_AIRCR_VECTKEYSTAT_Pos) /*!< SCB AIRCR: VECTKEYSTAT Mask */ + +#define SCB_AIRCR_ENDIANESS_Pos 15 /*!< SCB AIRCR: ENDIANESS Position */ +#define SCB_AIRCR_ENDIANESS_Msk (1UL << SCB_AIRCR_ENDIANESS_Pos) /*!< SCB AIRCR: ENDIANESS Mask */ + +#define SCB_AIRCR_PRIGROUP_Pos 8 /*!< SCB AIRCR: PRIGROUP Position */ +#define SCB_AIRCR_PRIGROUP_Msk (7UL << SCB_AIRCR_PRIGROUP_Pos) /*!< SCB AIRCR: PRIGROUP Mask */ + +#define SCB_AIRCR_SYSRESETREQ_Pos 2 /*!< SCB AIRCR: SYSRESETREQ Position */ +#define SCB_AIRCR_SYSRESETREQ_Msk (1UL << SCB_AIRCR_SYSRESETREQ_Pos) /*!< SCB AIRCR: SYSRESETREQ Mask */ + +#define SCB_AIRCR_VECTCLRACTIVE_Pos 1 /*!< SCB AIRCR: VECTCLRACTIVE Position */ +#define SCB_AIRCR_VECTCLRACTIVE_Msk (1UL << SCB_AIRCR_VECTCLRACTIVE_Pos) /*!< SCB AIRCR: VECTCLRACTIVE Mask */ + +#define SCB_AIRCR_VECTRESET_Pos 0 /*!< SCB AIRCR: VECTRESET Position */ +#define SCB_AIRCR_VECTRESET_Msk (1UL << SCB_AIRCR_VECTRESET_Pos) /*!< SCB AIRCR: VECTRESET Mask */ + +/* SCB System Control Register Definitions */ +#define SCB_SCR_SEVONPEND_Pos 4 /*!< SCB SCR: SEVONPEND Position */ +#define SCB_SCR_SEVONPEND_Msk (1UL << SCB_SCR_SEVONPEND_Pos) /*!< SCB SCR: SEVONPEND Mask */ + +#define SCB_SCR_SLEEPDEEP_Pos 2 /*!< SCB SCR: SLEEPDEEP Position */ +#define SCB_SCR_SLEEPDEEP_Msk (1UL << SCB_SCR_SLEEPDEEP_Pos) /*!< SCB SCR: SLEEPDEEP Mask */ + +#define SCB_SCR_SLEEPONEXIT_Pos 1 /*!< SCB SCR: SLEEPONEXIT Position */ +#define SCB_SCR_SLEEPONEXIT_Msk (1UL << SCB_SCR_SLEEPONEXIT_Pos) /*!< SCB SCR: SLEEPONEXIT Mask */ + +/* SCB Configuration Control Register Definitions */ +#define SCB_CCR_STKALIGN_Pos 9 /*!< SCB CCR: STKALIGN Position */ +#define SCB_CCR_STKALIGN_Msk (1UL << SCB_CCR_STKALIGN_Pos) /*!< SCB CCR: STKALIGN Mask */ + +#define SCB_CCR_BFHFNMIGN_Pos 8 /*!< SCB CCR: BFHFNMIGN Position */ +#define SCB_CCR_BFHFNMIGN_Msk (1UL << SCB_CCR_BFHFNMIGN_Pos) /*!< SCB CCR: BFHFNMIGN Mask */ + +#define SCB_CCR_DIV_0_TRP_Pos 4 /*!< SCB CCR: DIV_0_TRP Position */ +#define SCB_CCR_DIV_0_TRP_Msk (1UL << SCB_CCR_DIV_0_TRP_Pos) /*!< SCB CCR: DIV_0_TRP Mask */ + +#define SCB_CCR_UNALIGN_TRP_Pos 3 /*!< SCB CCR: UNALIGN_TRP Position */ +#define SCB_CCR_UNALIGN_TRP_Msk (1UL << SCB_CCR_UNALIGN_TRP_Pos) /*!< SCB CCR: UNALIGN_TRP Mask */ + +#define SCB_CCR_USERSETMPEND_Pos 1 /*!< SCB CCR: USERSETMPEND Position */ +#define SCB_CCR_USERSETMPEND_Msk (1UL << SCB_CCR_USERSETMPEND_Pos) /*!< SCB CCR: USERSETMPEND Mask */ + +#define SCB_CCR_NONBASETHRDENA_Pos 0 /*!< SCB CCR: NONBASETHRDENA Position */ +#define SCB_CCR_NONBASETHRDENA_Msk (1UL << SCB_CCR_NONBASETHRDENA_Pos) /*!< SCB CCR: NONBASETHRDENA Mask */ + +/* SCB System Handler Control and State Register Definitions */ +#define SCB_SHCSR_USGFAULTENA_Pos 18 /*!< SCB SHCSR: USGFAULTENA Position */ +#define SCB_SHCSR_USGFAULTENA_Msk (1UL << SCB_SHCSR_USGFAULTENA_Pos) /*!< SCB SHCSR: USGFAULTENA Mask */ + +#define SCB_SHCSR_BUSFAULTENA_Pos 17 /*!< SCB SHCSR: BUSFAULTENA Position */ +#define SCB_SHCSR_BUSFAULTENA_Msk (1UL << SCB_SHCSR_BUSFAULTENA_Pos) /*!< SCB SHCSR: BUSFAULTENA Mask */ + +#define SCB_SHCSR_MEMFAULTENA_Pos 16 /*!< SCB SHCSR: MEMFAULTENA Position */ +#define SCB_SHCSR_MEMFAULTENA_Msk (1UL << SCB_SHCSR_MEMFAULTENA_Pos) /*!< SCB SHCSR: MEMFAULTENA Mask */ + +#define SCB_SHCSR_SVCALLPENDED_Pos 15 /*!< SCB SHCSR: SVCALLPENDED Position */ +#define SCB_SHCSR_SVCALLPENDED_Msk (1UL << SCB_SHCSR_SVCALLPENDED_Pos) /*!< SCB SHCSR: SVCALLPENDED Mask */ + +#define SCB_SHCSR_BUSFAULTPENDED_Pos 14 /*!< SCB SHCSR: BUSFAULTPENDED Position */ +#define SCB_SHCSR_BUSFAULTPENDED_Msk (1UL << SCB_SHCSR_BUSFAULTPENDED_Pos) /*!< SCB SHCSR: BUSFAULTPENDED Mask */ + +#define SCB_SHCSR_MEMFAULTPENDED_Pos 13 /*!< SCB SHCSR: MEMFAULTPENDED Position */ +#define SCB_SHCSR_MEMFAULTPENDED_Msk (1UL << SCB_SHCSR_MEMFAULTPENDED_Pos) /*!< SCB SHCSR: MEMFAULTPENDED Mask */ + +#define SCB_SHCSR_USGFAULTPENDED_Pos 12 /*!< SCB SHCSR: USGFAULTPENDED Position */ +#define SCB_SHCSR_USGFAULTPENDED_Msk (1UL << SCB_SHCSR_USGFAULTPENDED_Pos) /*!< SCB SHCSR: USGFAULTPENDED Mask */ + +#define SCB_SHCSR_SYSTICKACT_Pos 11 /*!< SCB SHCSR: SYSTICKACT Position */ +#define SCB_SHCSR_SYSTICKACT_Msk (1UL << SCB_SHCSR_SYSTICKACT_Pos) /*!< SCB SHCSR: SYSTICKACT Mask */ + +#define SCB_SHCSR_PENDSVACT_Pos 10 /*!< SCB SHCSR: PENDSVACT Position */ +#define SCB_SHCSR_PENDSVACT_Msk (1UL << SCB_SHCSR_PENDSVACT_Pos) /*!< SCB SHCSR: PENDSVACT Mask */ + +#define SCB_SHCSR_MONITORACT_Pos 8 /*!< SCB SHCSR: MONITORACT Position */ +#define SCB_SHCSR_MONITORACT_Msk (1UL << SCB_SHCSR_MONITORACT_Pos) /*!< SCB SHCSR: MONITORACT Mask */ + +#define SCB_SHCSR_SVCALLACT_Pos 7 /*!< SCB SHCSR: SVCALLACT Position */ +#define SCB_SHCSR_SVCALLACT_Msk (1UL << SCB_SHCSR_SVCALLACT_Pos) /*!< SCB SHCSR: SVCALLACT Mask */ + +#define SCB_SHCSR_USGFAULTACT_Pos 3 /*!< SCB SHCSR: USGFAULTACT Position */ +#define SCB_SHCSR_USGFAULTACT_Msk (1UL << SCB_SHCSR_USGFAULTACT_Pos) /*!< SCB SHCSR: USGFAULTACT Mask */ + +#define SCB_SHCSR_BUSFAULTACT_Pos 1 /*!< SCB SHCSR: BUSFAULTACT Position */ +#define SCB_SHCSR_BUSFAULTACT_Msk (1UL << SCB_SHCSR_BUSFAULTACT_Pos) /*!< SCB SHCSR: BUSFAULTACT Mask */ + +#define SCB_SHCSR_MEMFAULTACT_Pos 0 /*!< SCB SHCSR: MEMFAULTACT Position */ +#define SCB_SHCSR_MEMFAULTACT_Msk (1UL << SCB_SHCSR_MEMFAULTACT_Pos) /*!< SCB SHCSR: MEMFAULTACT Mask */ + +/* SCB Configurable Fault Status Registers Definitions */ +#define SCB_CFSR_USGFAULTSR_Pos 16 /*!< SCB CFSR: Usage Fault Status Register Position */ +#define SCB_CFSR_USGFAULTSR_Msk (0xFFFFUL << SCB_CFSR_USGFAULTSR_Pos) /*!< SCB CFSR: Usage Fault Status Register Mask */ + +#define SCB_CFSR_BUSFAULTSR_Pos 8 /*!< SCB CFSR: Bus Fault Status Register Position */ +#define SCB_CFSR_BUSFAULTSR_Msk (0xFFUL << SCB_CFSR_BUSFAULTSR_Pos) /*!< SCB CFSR: Bus Fault Status Register Mask */ + +#define SCB_CFSR_MEMFAULTSR_Pos 0 /*!< SCB CFSR: Memory Manage Fault Status Register Position */ +#define SCB_CFSR_MEMFAULTSR_Msk (0xFFUL << SCB_CFSR_MEMFAULTSR_Pos) /*!< SCB CFSR: Memory Manage Fault Status Register Mask */ + +/* SCB Hard Fault Status Registers Definitions */ +#define SCB_HFSR_DEBUGEVT_Pos 31 /*!< SCB HFSR: DEBUGEVT Position */ +#define SCB_HFSR_DEBUGEVT_Msk (1UL << SCB_HFSR_DEBUGEVT_Pos) /*!< SCB HFSR: DEBUGEVT Mask */ + +#define SCB_HFSR_FORCED_Pos 30 /*!< SCB HFSR: FORCED Position */ +#define SCB_HFSR_FORCED_Msk (1UL << SCB_HFSR_FORCED_Pos) /*!< SCB HFSR: FORCED Mask */ + +#define SCB_HFSR_VECTTBL_Pos 1 /*!< SCB HFSR: VECTTBL Position */ +#define SCB_HFSR_VECTTBL_Msk (1UL << SCB_HFSR_VECTTBL_Pos) /*!< SCB HFSR: VECTTBL Mask */ + +/* SCB Debug Fault Status Register Definitions */ +#define SCB_DFSR_EXTERNAL_Pos 4 /*!< SCB DFSR: EXTERNAL Position */ +#define SCB_DFSR_EXTERNAL_Msk (1UL << SCB_DFSR_EXTERNAL_Pos) /*!< SCB DFSR: EXTERNAL Mask */ + +#define SCB_DFSR_VCATCH_Pos 3 /*!< SCB DFSR: VCATCH Position */ +#define SCB_DFSR_VCATCH_Msk (1UL << SCB_DFSR_VCATCH_Pos) /*!< SCB DFSR: VCATCH Mask */ + +#define SCB_DFSR_DWTTRAP_Pos 2 /*!< SCB DFSR: DWTTRAP Position */ +#define SCB_DFSR_DWTTRAP_Msk (1UL << SCB_DFSR_DWTTRAP_Pos) /*!< SCB DFSR: DWTTRAP Mask */ + +#define SCB_DFSR_BKPT_Pos 1 /*!< SCB DFSR: BKPT Position */ +#define SCB_DFSR_BKPT_Msk (1UL << SCB_DFSR_BKPT_Pos) /*!< SCB DFSR: BKPT Mask */ + +#define SCB_DFSR_HALTED_Pos 0 /*!< SCB DFSR: HALTED Position */ +#define SCB_DFSR_HALTED_Msk (1UL << SCB_DFSR_HALTED_Pos) /*!< SCB DFSR: HALTED Mask */ + +/*@} end of group CMSIS_SCB */ + + +/** \ingroup CMSIS_core_register + \defgroup CMSIS_SCnSCB System Controls not in SCB (SCnSCB) + \brief Type definitions for the System Control and ID Register not in the SCB + @{ + */ + +/** \brief Structure type to access the System Control and ID Register not in the SCB. + */ +typedef struct +{ + uint32_t RESERVED0[1]; + __I uint32_t ICTR; /*!< Offset: 0x004 (R/ ) Interrupt Controller Type Register */ +#if ((defined __CM3_REV) && (__CM3_REV >= 0x200)) + __IO uint32_t ACTLR; /*!< Offset: 0x008 (R/W) Auxiliary Control Register */ +#else + uint32_t RESERVED1[1]; +#endif +} SCnSCB_Type; + +/* Interrupt Controller Type Register Definitions */ +#define SCnSCB_ICTR_INTLINESNUM_Pos 0 /*!< ICTR: INTLINESNUM Position */ +#define SCnSCB_ICTR_INTLINESNUM_Msk (0xFUL << SCnSCB_ICTR_INTLINESNUM_Pos) /*!< ICTR: INTLINESNUM Mask */ + +/* Auxiliary Control Register Definitions */ + +#define SCnSCB_ACTLR_DISFOLD_Pos 2 /*!< ACTLR: DISFOLD Position */ +#define SCnSCB_ACTLR_DISFOLD_Msk (1UL << SCnSCB_ACTLR_DISFOLD_Pos) /*!< ACTLR: DISFOLD Mask */ + +#define SCnSCB_ACTLR_DISDEFWBUF_Pos 1 /*!< ACTLR: DISDEFWBUF Position */ +#define SCnSCB_ACTLR_DISDEFWBUF_Msk (1UL << SCnSCB_ACTLR_DISDEFWBUF_Pos) /*!< ACTLR: DISDEFWBUF Mask */ + +#define SCnSCB_ACTLR_DISMCYCINT_Pos 0 /*!< ACTLR: DISMCYCINT Position */ +#define SCnSCB_ACTLR_DISMCYCINT_Msk (1UL << SCnSCB_ACTLR_DISMCYCINT_Pos) /*!< ACTLR: DISMCYCINT Mask */ + +/*@} end of group CMSIS_SCnotSCB */ + + +/** \ingroup CMSIS_core_register + \defgroup CMSIS_SysTick System Tick Timer (SysTick) + \brief Type definitions for the System Timer Registers. + @{ + */ + +/** \brief Structure type to access the System Timer (SysTick). + */ +typedef struct +{ + __IO uint32_t CTRL; /*!< Offset: 0x000 (R/W) SysTick Control and Status Register */ + __IO uint32_t LOAD; /*!< Offset: 0x004 (R/W) SysTick Reload Value Register */ + __IO uint32_t VAL; /*!< Offset: 0x008 (R/W) SysTick Current Value Register */ + __I uint32_t CALIB; /*!< Offset: 0x00C (R/ ) SysTick Calibration Register */ +} SysTick_Type; + +/* SysTick Control / Status Register Definitions */ +#define SysTick_CTRL_COUNTFLAG_Pos 16 /*!< SysTick CTRL: COUNTFLAG Position */ +#define SysTick_CTRL_COUNTFLAG_Msk (1UL << SysTick_CTRL_COUNTFLAG_Pos) /*!< SysTick CTRL: COUNTFLAG Mask */ + +#define SysTick_CTRL_CLKSOURCE_Pos 2 /*!< SysTick CTRL: CLKSOURCE Position */ +#define SysTick_CTRL_CLKSOURCE_Msk (1UL << SysTick_CTRL_CLKSOURCE_Pos) /*!< SysTick CTRL: CLKSOURCE Mask */ + +#define SysTick_CTRL_TICKINT_Pos 1 /*!< SysTick CTRL: TICKINT Position */ +#define SysTick_CTRL_TICKINT_Msk (1UL << SysTick_CTRL_TICKINT_Pos) /*!< SysTick CTRL: TICKINT Mask */ + +#define SysTick_CTRL_ENABLE_Pos 0 /*!< SysTick CTRL: ENABLE Position */ +#define SysTick_CTRL_ENABLE_Msk (1UL << SysTick_CTRL_ENABLE_Pos) /*!< SysTick CTRL: ENABLE Mask */ + +/* SysTick Reload Register Definitions */ +#define SysTick_LOAD_RELOAD_Pos 0 /*!< SysTick LOAD: RELOAD Position */ +#define SysTick_LOAD_RELOAD_Msk (0xFFFFFFUL << SysTick_LOAD_RELOAD_Pos) /*!< SysTick LOAD: RELOAD Mask */ + +/* SysTick Current Register Definitions */ +#define SysTick_VAL_CURRENT_Pos 0 /*!< SysTick VAL: CURRENT Position */ +#define SysTick_VAL_CURRENT_Msk (0xFFFFFFUL << SysTick_VAL_CURRENT_Pos) /*!< SysTick VAL: CURRENT Mask */ + +/* SysTick Calibration Register Definitions */ +#define SysTick_CALIB_NOREF_Pos 31 /*!< SysTick CALIB: NOREF Position */ +#define SysTick_CALIB_NOREF_Msk (1UL << SysTick_CALIB_NOREF_Pos) /*!< SysTick CALIB: NOREF Mask */ + +#define SysTick_CALIB_SKEW_Pos 30 /*!< SysTick CALIB: SKEW Position */ +#define SysTick_CALIB_SKEW_Msk (1UL << SysTick_CALIB_SKEW_Pos) /*!< SysTick CALIB: SKEW Mask */ + +#define SysTick_CALIB_TENMS_Pos 0 /*!< SysTick CALIB: TENMS Position */ +#define SysTick_CALIB_TENMS_Msk (0xFFFFFFUL << SysTick_VAL_CURRENT_Pos) /*!< SysTick CALIB: TENMS Mask */ + +/*@} end of group CMSIS_SysTick */ + + +/** \ingroup CMSIS_core_register + \defgroup CMSIS_ITM Instrumentation Trace Macrocell (ITM) + \brief Type definitions for the Instrumentation Trace Macrocell (ITM) + @{ + */ + +/** \brief Structure type to access the Instrumentation Trace Macrocell Register (ITM). + */ +typedef struct +{ + __O union + { + __O uint8_t u8; /*!< Offset: 0x000 ( /W) ITM Stimulus Port 8-bit */ + __O uint16_t u16; /*!< Offset: 0x000 ( /W) ITM Stimulus Port 16-bit */ + __O uint32_t u32; /*!< Offset: 0x000 ( /W) ITM Stimulus Port 32-bit */ + } PORT [32]; /*!< Offset: 0x000 ( /W) ITM Stimulus Port Registers */ + uint32_t RESERVED0[864]; + __IO uint32_t TER; /*!< Offset: 0xE00 (R/W) ITM Trace Enable Register */ + uint32_t RESERVED1[15]; + __IO uint32_t TPR; /*!< Offset: 0xE40 (R/W) ITM Trace Privilege Register */ + uint32_t RESERVED2[15]; + __IO uint32_t TCR; /*!< Offset: 0xE80 (R/W) ITM Trace Control Register */ + uint32_t RESERVED3[29]; + __O uint32_t IWR; /*!< Offset: 0xEF8 ( /W) ITM Integration Write Register */ + __I uint32_t IRR; /*!< Offset: 0xEFC (R/ ) ITM Integration Read Register */ + __IO uint32_t IMCR; /*!< Offset: 0xF00 (R/W) ITM Integration Mode Control Register */ + uint32_t RESERVED4[43]; + __O uint32_t LAR; /*!< Offset: 0xFB0 ( /W) ITM Lock Access Register */ + __I uint32_t LSR; /*!< Offset: 0xFB4 (R/ ) ITM Lock Status Register */ + uint32_t RESERVED5[6]; + __I uint32_t PID4; /*!< Offset: 0xFD0 (R/ ) ITM Peripheral Identification Register #4 */ + __I uint32_t PID5; /*!< Offset: 0xFD4 (R/ ) ITM Peripheral Identification Register #5 */ + __I uint32_t PID6; /*!< Offset: 0xFD8 (R/ ) ITM Peripheral Identification Register #6 */ + __I uint32_t PID7; /*!< Offset: 0xFDC (R/ ) ITM Peripheral Identification Register #7 */ + __I uint32_t PID0; /*!< Offset: 0xFE0 (R/ ) ITM Peripheral Identification Register #0 */ + __I uint32_t PID1; /*!< Offset: 0xFE4 (R/ ) ITM Peripheral Identification Register #1 */ + __I uint32_t PID2; /*!< Offset: 0xFE8 (R/ ) ITM Peripheral Identification Register #2 */ + __I uint32_t PID3; /*!< Offset: 0xFEC (R/ ) ITM Peripheral Identification Register #3 */ + __I uint32_t CID0; /*!< Offset: 0xFF0 (R/ ) ITM Component Identification Register #0 */ + __I uint32_t CID1; /*!< Offset: 0xFF4 (R/ ) ITM Component Identification Register #1 */ + __I uint32_t CID2; /*!< Offset: 0xFF8 (R/ ) ITM Component Identification Register #2 */ + __I uint32_t CID3; /*!< Offset: 0xFFC (R/ ) ITM Component Identification Register #3 */ +} ITM_Type; + +/* ITM Trace Privilege Register Definitions */ +#define ITM_TPR_PRIVMASK_Pos 0 /*!< ITM TPR: PRIVMASK Position */ +#define ITM_TPR_PRIVMASK_Msk (0xFUL << ITM_TPR_PRIVMASK_Pos) /*!< ITM TPR: PRIVMASK Mask */ + +/* ITM Trace Control Register Definitions */ +#define ITM_TCR_BUSY_Pos 23 /*!< ITM TCR: BUSY Position */ +#define ITM_TCR_BUSY_Msk (1UL << ITM_TCR_BUSY_Pos) /*!< ITM TCR: BUSY Mask */ + +#define ITM_TCR_TraceBusID_Pos 16 /*!< ITM TCR: ATBID Position */ +#define ITM_TCR_TraceBusID_Msk (0x7FUL << ITM_TCR_TraceBusID_Pos) /*!< ITM TCR: ATBID Mask */ + +#define ITM_TCR_GTSFREQ_Pos 10 /*!< ITM TCR: Global timestamp frequency Position */ +#define ITM_TCR_GTSFREQ_Msk (3UL << ITM_TCR_GTSFREQ_Pos) /*!< ITM TCR: Global timestamp frequency Mask */ + +#define ITM_TCR_TSPrescale_Pos 8 /*!< ITM TCR: TSPrescale Position */ +#define ITM_TCR_TSPrescale_Msk (3UL << ITM_TCR_TSPrescale_Pos) /*!< ITM TCR: TSPrescale Mask */ + +#define ITM_TCR_SWOENA_Pos 4 /*!< ITM TCR: SWOENA Position */ +#define ITM_TCR_SWOENA_Msk (1UL << ITM_TCR_SWOENA_Pos) /*!< ITM TCR: SWOENA Mask */ + +#define ITM_TCR_DWTENA_Pos 3 /*!< ITM TCR: DWTENA Position */ +#define ITM_TCR_DWTENA_Msk (1UL << ITM_TCR_DWTENA_Pos) /*!< ITM TCR: DWTENA Mask */ + +#define ITM_TCR_SYNCENA_Pos 2 /*!< ITM TCR: SYNCENA Position */ +#define ITM_TCR_SYNCENA_Msk (1UL << ITM_TCR_SYNCENA_Pos) /*!< ITM TCR: SYNCENA Mask */ + +#define ITM_TCR_TSENA_Pos 1 /*!< ITM TCR: TSENA Position */ +#define ITM_TCR_TSENA_Msk (1UL << ITM_TCR_TSENA_Pos) /*!< ITM TCR: TSENA Mask */ + +#define ITM_TCR_ITMENA_Pos 0 /*!< ITM TCR: ITM Enable bit Position */ +#define ITM_TCR_ITMENA_Msk (1UL << ITM_TCR_ITMENA_Pos) /*!< ITM TCR: ITM Enable bit Mask */ + +/* ITM Integration Write Register Definitions */ +#define ITM_IWR_ATVALIDM_Pos 0 /*!< ITM IWR: ATVALIDM Position */ +#define ITM_IWR_ATVALIDM_Msk (1UL << ITM_IWR_ATVALIDM_Pos) /*!< ITM IWR: ATVALIDM Mask */ + +/* ITM Integration Read Register Definitions */ +#define ITM_IRR_ATREADYM_Pos 0 /*!< ITM IRR: ATREADYM Position */ +#define ITM_IRR_ATREADYM_Msk (1UL << ITM_IRR_ATREADYM_Pos) /*!< ITM IRR: ATREADYM Mask */ + +/* ITM Integration Mode Control Register Definitions */ +#define ITM_IMCR_INTEGRATION_Pos 0 /*!< ITM IMCR: INTEGRATION Position */ +#define ITM_IMCR_INTEGRATION_Msk (1UL << ITM_IMCR_INTEGRATION_Pos) /*!< ITM IMCR: INTEGRATION Mask */ + +/* ITM Lock Status Register Definitions */ +#define ITM_LSR_ByteAcc_Pos 2 /*!< ITM LSR: ByteAcc Position */ +#define ITM_LSR_ByteAcc_Msk (1UL << ITM_LSR_ByteAcc_Pos) /*!< ITM LSR: ByteAcc Mask */ + +#define ITM_LSR_Access_Pos 1 /*!< ITM LSR: Access Position */ +#define ITM_LSR_Access_Msk (1UL << ITM_LSR_Access_Pos) /*!< ITM LSR: Access Mask */ + +#define ITM_LSR_Present_Pos 0 /*!< ITM LSR: Present Position */ +#define ITM_LSR_Present_Msk (1UL << ITM_LSR_Present_Pos) /*!< ITM LSR: Present Mask */ + +/*@}*/ /* end of group CMSIS_ITM */ + + +/** \ingroup CMSIS_core_register + \defgroup CMSIS_DWT Data Watchpoint and Trace (DWT) + \brief Type definitions for the Data Watchpoint and Trace (DWT) + @{ + */ + +/** \brief Structure type to access the Data Watchpoint and Trace Register (DWT). + */ +typedef struct +{ + __IO uint32_t CTRL; /*!< Offset: 0x000 (R/W) Control Register */ + __IO uint32_t CYCCNT; /*!< Offset: 0x004 (R/W) Cycle Count Register */ + __IO uint32_t CPICNT; /*!< Offset: 0x008 (R/W) CPI Count Register */ + __IO uint32_t EXCCNT; /*!< Offset: 0x00C (R/W) Exception Overhead Count Register */ + __IO uint32_t SLEEPCNT; /*!< Offset: 0x010 (R/W) Sleep Count Register */ + __IO uint32_t LSUCNT; /*!< Offset: 0x014 (R/W) LSU Count Register */ + __IO uint32_t FOLDCNT; /*!< Offset: 0x018 (R/W) Folded-instruction Count Register */ + __I uint32_t PCSR; /*!< Offset: 0x01C (R/ ) Program Counter Sample Register */ + __IO uint32_t COMP0; /*!< Offset: 0x020 (R/W) Comparator Register 0 */ + __IO uint32_t MASK0; /*!< Offset: 0x024 (R/W) Mask Register 0 */ + __IO uint32_t FUNCTION0; /*!< Offset: 0x028 (R/W) Function Register 0 */ + uint32_t RESERVED0[1]; + __IO uint32_t COMP1; /*!< Offset: 0x030 (R/W) Comparator Register 1 */ + __IO uint32_t MASK1; /*!< Offset: 0x034 (R/W) Mask Register 1 */ + __IO uint32_t FUNCTION1; /*!< Offset: 0x038 (R/W) Function Register 1 */ + uint32_t RESERVED1[1]; + __IO uint32_t COMP2; /*!< Offset: 0x040 (R/W) Comparator Register 2 */ + __IO uint32_t MASK2; /*!< Offset: 0x044 (R/W) Mask Register 2 */ + __IO uint32_t FUNCTION2; /*!< Offset: 0x048 (R/W) Function Register 2 */ + uint32_t RESERVED2[1]; + __IO uint32_t COMP3; /*!< Offset: 0x050 (R/W) Comparator Register 3 */ + __IO uint32_t MASK3; /*!< Offset: 0x054 (R/W) Mask Register 3 */ + __IO uint32_t FUNCTION3; /*!< Offset: 0x058 (R/W) Function Register 3 */ +} DWT_Type; + +/* DWT Control Register Definitions */ +#define DWT_CTRL_NUMCOMP_Pos 28 /*!< DWT CTRL: NUMCOMP Position */ +#define DWT_CTRL_NUMCOMP_Msk (0xFUL << DWT_CTRL_NUMCOMP_Pos) /*!< DWT CTRL: NUMCOMP Mask */ + +#define DWT_CTRL_NOTRCPKT_Pos 27 /*!< DWT CTRL: NOTRCPKT Position */ +#define DWT_CTRL_NOTRCPKT_Msk (0x1UL << DWT_CTRL_NOTRCPKT_Pos) /*!< DWT CTRL: NOTRCPKT Mask */ + +#define DWT_CTRL_NOEXTTRIG_Pos 26 /*!< DWT CTRL: NOEXTTRIG Position */ +#define DWT_CTRL_NOEXTTRIG_Msk (0x1UL << DWT_CTRL_NOEXTTRIG_Pos) /*!< DWT CTRL: NOEXTTRIG Mask */ + +#define DWT_CTRL_NOCYCCNT_Pos 25 /*!< DWT CTRL: NOCYCCNT Position */ +#define DWT_CTRL_NOCYCCNT_Msk (0x1UL << DWT_CTRL_NOCYCCNT_Pos) /*!< DWT CTRL: NOCYCCNT Mask */ + +#define DWT_CTRL_NOPRFCNT_Pos 24 /*!< DWT CTRL: NOPRFCNT Position */ +#define DWT_CTRL_NOPRFCNT_Msk (0x1UL << DWT_CTRL_NOPRFCNT_Pos) /*!< DWT CTRL: NOPRFCNT Mask */ + +#define DWT_CTRL_CYCEVTENA_Pos 22 /*!< DWT CTRL: CYCEVTENA Position */ +#define DWT_CTRL_CYCEVTENA_Msk (0x1UL << DWT_CTRL_CYCEVTENA_Pos) /*!< DWT CTRL: CYCEVTENA Mask */ + +#define DWT_CTRL_FOLDEVTENA_Pos 21 /*!< DWT CTRL: FOLDEVTENA Position */ +#define DWT_CTRL_FOLDEVTENA_Msk (0x1UL << DWT_CTRL_FOLDEVTENA_Pos) /*!< DWT CTRL: FOLDEVTENA Mask */ + +#define DWT_CTRL_LSUEVTENA_Pos 20 /*!< DWT CTRL: LSUEVTENA Position */ +#define DWT_CTRL_LSUEVTENA_Msk (0x1UL << DWT_CTRL_LSUEVTENA_Pos) /*!< DWT CTRL: LSUEVTENA Mask */ + +#define DWT_CTRL_SLEEPEVTENA_Pos 19 /*!< DWT CTRL: SLEEPEVTENA Position */ +#define DWT_CTRL_SLEEPEVTENA_Msk (0x1UL << DWT_CTRL_SLEEPEVTENA_Pos) /*!< DWT CTRL: SLEEPEVTENA Mask */ + +#define DWT_CTRL_EXCEVTENA_Pos 18 /*!< DWT CTRL: EXCEVTENA Position */ +#define DWT_CTRL_EXCEVTENA_Msk (0x1UL << DWT_CTRL_EXCEVTENA_Pos) /*!< DWT CTRL: EXCEVTENA Mask */ + +#define DWT_CTRL_CPIEVTENA_Pos 17 /*!< DWT CTRL: CPIEVTENA Position */ +#define DWT_CTRL_CPIEVTENA_Msk (0x1UL << DWT_CTRL_CPIEVTENA_Pos) /*!< DWT CTRL: CPIEVTENA Mask */ + +#define DWT_CTRL_EXCTRCENA_Pos 16 /*!< DWT CTRL: EXCTRCENA Position */ +#define DWT_CTRL_EXCTRCENA_Msk (0x1UL << DWT_CTRL_EXCTRCENA_Pos) /*!< DWT CTRL: EXCTRCENA Mask */ + +#define DWT_CTRL_PCSAMPLENA_Pos 12 /*!< DWT CTRL: PCSAMPLENA Position */ +#define DWT_CTRL_PCSAMPLENA_Msk (0x1UL << DWT_CTRL_PCSAMPLENA_Pos) /*!< DWT CTRL: PCSAMPLENA Mask */ + +#define DWT_CTRL_SYNCTAP_Pos 10 /*!< DWT CTRL: SYNCTAP Position */ +#define DWT_CTRL_SYNCTAP_Msk (0x3UL << DWT_CTRL_SYNCTAP_Pos) /*!< DWT CTRL: SYNCTAP Mask */ + +#define DWT_CTRL_CYCTAP_Pos 9 /*!< DWT CTRL: CYCTAP Position */ +#define DWT_CTRL_CYCTAP_Msk (0x1UL << DWT_CTRL_CYCTAP_Pos) /*!< DWT CTRL: CYCTAP Mask */ + +#define DWT_CTRL_POSTINIT_Pos 5 /*!< DWT CTRL: POSTINIT Position */ +#define DWT_CTRL_POSTINIT_Msk (0xFUL << DWT_CTRL_POSTINIT_Pos) /*!< DWT CTRL: POSTINIT Mask */ + +#define DWT_CTRL_POSTPRESET_Pos 1 /*!< DWT CTRL: POSTPRESET Position */ +#define DWT_CTRL_POSTPRESET_Msk (0xFUL << DWT_CTRL_POSTPRESET_Pos) /*!< DWT CTRL: POSTPRESET Mask */ + +#define DWT_CTRL_CYCCNTENA_Pos 0 /*!< DWT CTRL: CYCCNTENA Position */ +#define DWT_CTRL_CYCCNTENA_Msk (0x1UL << DWT_CTRL_CYCCNTENA_Pos) /*!< DWT CTRL: CYCCNTENA Mask */ + +/* DWT CPI Count Register Definitions */ +#define DWT_CPICNT_CPICNT_Pos 0 /*!< DWT CPICNT: CPICNT Position */ +#define DWT_CPICNT_CPICNT_Msk (0xFFUL << DWT_CPICNT_CPICNT_Pos) /*!< DWT CPICNT: CPICNT Mask */ + +/* DWT Exception Overhead Count Register Definitions */ +#define DWT_EXCCNT_EXCCNT_Pos 0 /*!< DWT EXCCNT: EXCCNT Position */ +#define DWT_EXCCNT_EXCCNT_Msk (0xFFUL << DWT_EXCCNT_EXCCNT_Pos) /*!< DWT EXCCNT: EXCCNT Mask */ + +/* DWT Sleep Count Register Definitions */ +#define DWT_SLEEPCNT_SLEEPCNT_Pos 0 /*!< DWT SLEEPCNT: SLEEPCNT Position */ +#define DWT_SLEEPCNT_SLEEPCNT_Msk (0xFFUL << DWT_SLEEPCNT_SLEEPCNT_Pos) /*!< DWT SLEEPCNT: SLEEPCNT Mask */ + +/* DWT LSU Count Register Definitions */ +#define DWT_LSUCNT_LSUCNT_Pos 0 /*!< DWT LSUCNT: LSUCNT Position */ +#define DWT_LSUCNT_LSUCNT_Msk (0xFFUL << DWT_LSUCNT_LSUCNT_Pos) /*!< DWT LSUCNT: LSUCNT Mask */ + +/* DWT Folded-instruction Count Register Definitions */ +#define DWT_FOLDCNT_FOLDCNT_Pos 0 /*!< DWT FOLDCNT: FOLDCNT Position */ +#define DWT_FOLDCNT_FOLDCNT_Msk (0xFFUL << DWT_FOLDCNT_FOLDCNT_Pos) /*!< DWT FOLDCNT: FOLDCNT Mask */ + +/* DWT Comparator Mask Register Definitions */ +#define DWT_MASK_MASK_Pos 0 /*!< DWT MASK: MASK Position */ +#define DWT_MASK_MASK_Msk (0x1FUL << DWT_MASK_MASK_Pos) /*!< DWT MASK: MASK Mask */ + +/* DWT Comparator Function Register Definitions */ +#define DWT_FUNCTION_MATCHED_Pos 24 /*!< DWT FUNCTION: MATCHED Position */ +#define DWT_FUNCTION_MATCHED_Msk (0x1UL << DWT_FUNCTION_MATCHED_Pos) /*!< DWT FUNCTION: MATCHED Mask */ + +#define DWT_FUNCTION_DATAVADDR1_Pos 16 /*!< DWT FUNCTION: DATAVADDR1 Position */ +#define DWT_FUNCTION_DATAVADDR1_Msk (0xFUL << DWT_FUNCTION_DATAVADDR1_Pos) /*!< DWT FUNCTION: DATAVADDR1 Mask */ + +#define DWT_FUNCTION_DATAVADDR0_Pos 12 /*!< DWT FUNCTION: DATAVADDR0 Position */ +#define DWT_FUNCTION_DATAVADDR0_Msk (0xFUL << DWT_FUNCTION_DATAVADDR0_Pos) /*!< DWT FUNCTION: DATAVADDR0 Mask */ + +#define DWT_FUNCTION_DATAVSIZE_Pos 10 /*!< DWT FUNCTION: DATAVSIZE Position */ +#define DWT_FUNCTION_DATAVSIZE_Msk (0x3UL << DWT_FUNCTION_DATAVSIZE_Pos) /*!< DWT FUNCTION: DATAVSIZE Mask */ + +#define DWT_FUNCTION_LNK1ENA_Pos 9 /*!< DWT FUNCTION: LNK1ENA Position */ +#define DWT_FUNCTION_LNK1ENA_Msk (0x1UL << DWT_FUNCTION_LNK1ENA_Pos) /*!< DWT FUNCTION: LNK1ENA Mask */ + +#define DWT_FUNCTION_DATAVMATCH_Pos 8 /*!< DWT FUNCTION: DATAVMATCH Position */ +#define DWT_FUNCTION_DATAVMATCH_Msk (0x1UL << DWT_FUNCTION_DATAVMATCH_Pos) /*!< DWT FUNCTION: DATAVMATCH Mask */ + +#define DWT_FUNCTION_CYCMATCH_Pos 7 /*!< DWT FUNCTION: CYCMATCH Position */ +#define DWT_FUNCTION_CYCMATCH_Msk (0x1UL << DWT_FUNCTION_CYCMATCH_Pos) /*!< DWT FUNCTION: CYCMATCH Mask */ + +#define DWT_FUNCTION_EMITRANGE_Pos 5 /*!< DWT FUNCTION: EMITRANGE Position */ +#define DWT_FUNCTION_EMITRANGE_Msk (0x1UL << DWT_FUNCTION_EMITRANGE_Pos) /*!< DWT FUNCTION: EMITRANGE Mask */ + +#define DWT_FUNCTION_FUNCTION_Pos 0 /*!< DWT FUNCTION: FUNCTION Position */ +#define DWT_FUNCTION_FUNCTION_Msk (0xFUL << DWT_FUNCTION_FUNCTION_Pos) /*!< DWT FUNCTION: FUNCTION Mask */ + +/*@}*/ /* end of group CMSIS_DWT */ + + +/** \ingroup CMSIS_core_register + \defgroup CMSIS_TPI Trace Port Interface (TPI) + \brief Type definitions for the Trace Port Interface (TPI) + @{ + */ + +/** \brief Structure type to access the Trace Port Interface Register (TPI). + */ +typedef struct +{ + __IO uint32_t SSPSR; /*!< Offset: 0x000 (R/ ) Supported Parallel Port Size Register */ + __IO uint32_t CSPSR; /*!< Offset: 0x004 (R/W) Current Parallel Port Size Register */ + uint32_t RESERVED0[2]; + __IO uint32_t ACPR; /*!< Offset: 0x010 (R/W) Asynchronous Clock Prescaler Register */ + uint32_t RESERVED1[55]; + __IO uint32_t SPPR; /*!< Offset: 0x0F0 (R/W) Selected Pin Protocol Register */ + uint32_t RESERVED2[131]; + __I uint32_t FFSR; /*!< Offset: 0x300 (R/ ) Formatter and Flush Status Register */ + __IO uint32_t FFCR; /*!< Offset: 0x304 (R/W) Formatter and Flush Control Register */ + __I uint32_t FSCR; /*!< Offset: 0x308 (R/ ) Formatter Synchronization Counter Register */ + uint32_t RESERVED3[759]; + __I uint32_t TRIGGER; /*!< Offset: 0xEE8 (R/ ) TRIGGER */ + __I uint32_t FIFO0; /*!< Offset: 0xEEC (R/ ) Integration ETM Data */ + __I uint32_t ITATBCTR2; /*!< Offset: 0xEF0 (R/ ) ITATBCTR2 */ + uint32_t RESERVED4[1]; + __I uint32_t ITATBCTR0; /*!< Offset: 0xEF8 (R/ ) ITATBCTR0 */ + __I uint32_t FIFO1; /*!< Offset: 0xEFC (R/ ) Integration ITM Data */ + __IO uint32_t ITCTRL; /*!< Offset: 0xF00 (R/W) Integration Mode Control */ + uint32_t RESERVED5[39]; + __IO uint32_t CLAIMSET; /*!< Offset: 0xFA0 (R/W) Claim tag set */ + __IO uint32_t CLAIMCLR; /*!< Offset: 0xFA4 (R/W) Claim tag clear */ + uint32_t RESERVED7[8]; + __I uint32_t DEVID; /*!< Offset: 0xFC8 (R/ ) TPIU_DEVID */ + __I uint32_t DEVTYPE; /*!< Offset: 0xFCC (R/ ) TPIU_DEVTYPE */ +} TPI_Type; + +/* TPI Asynchronous Clock Prescaler Register Definitions */ +#define TPI_ACPR_PRESCALER_Pos 0 /*!< TPI ACPR: PRESCALER Position */ +#define TPI_ACPR_PRESCALER_Msk (0x1FFFUL << TPI_ACPR_PRESCALER_Pos) /*!< TPI ACPR: PRESCALER Mask */ + +/* TPI Selected Pin Protocol Register Definitions */ +#define TPI_SPPR_TXMODE_Pos 0 /*!< TPI SPPR: TXMODE Position */ +#define TPI_SPPR_TXMODE_Msk (0x3UL << TPI_SPPR_TXMODE_Pos) /*!< TPI SPPR: TXMODE Mask */ + +/* TPI Formatter and Flush Status Register Definitions */ +#define TPI_FFSR_FtNonStop_Pos 3 /*!< TPI FFSR: FtNonStop Position */ +#define TPI_FFSR_FtNonStop_Msk (0x1UL << TPI_FFSR_FtNonStop_Pos) /*!< TPI FFSR: FtNonStop Mask */ + +#define TPI_FFSR_TCPresent_Pos 2 /*!< TPI FFSR: TCPresent Position */ +#define TPI_FFSR_TCPresent_Msk (0x1UL << TPI_FFSR_TCPresent_Pos) /*!< TPI FFSR: TCPresent Mask */ + +#define TPI_FFSR_FtStopped_Pos 1 /*!< TPI FFSR: FtStopped Position */ +#define TPI_FFSR_FtStopped_Msk (0x1UL << TPI_FFSR_FtStopped_Pos) /*!< TPI FFSR: FtStopped Mask */ + +#define TPI_FFSR_FlInProg_Pos 0 /*!< TPI FFSR: FlInProg Position */ +#define TPI_FFSR_FlInProg_Msk (0x1UL << TPI_FFSR_FlInProg_Pos) /*!< TPI FFSR: FlInProg Mask */ + +/* TPI Formatter and Flush Control Register Definitions */ +#define TPI_FFCR_TrigIn_Pos 8 /*!< TPI FFCR: TrigIn Position */ +#define TPI_FFCR_TrigIn_Msk (0x1UL << TPI_FFCR_TrigIn_Pos) /*!< TPI FFCR: TrigIn Mask */ + +#define TPI_FFCR_EnFCont_Pos 1 /*!< TPI FFCR: EnFCont Position */ +#define TPI_FFCR_EnFCont_Msk (0x1UL << TPI_FFCR_EnFCont_Pos) /*!< TPI FFCR: EnFCont Mask */ + +/* TPI TRIGGER Register Definitions */ +#define TPI_TRIGGER_TRIGGER_Pos 0 /*!< TPI TRIGGER: TRIGGER Position */ +#define TPI_TRIGGER_TRIGGER_Msk (0x1UL << TPI_TRIGGER_TRIGGER_Pos) /*!< TPI TRIGGER: TRIGGER Mask */ + +/* TPI Integration ETM Data Register Definitions (FIFO0) */ +#define TPI_FIFO0_ITM_ATVALID_Pos 29 /*!< TPI FIFO0: ITM_ATVALID Position */ +#define TPI_FIFO0_ITM_ATVALID_Msk (0x3UL << TPI_FIFO0_ITM_ATVALID_Pos) /*!< TPI FIFO0: ITM_ATVALID Mask */ + +#define TPI_FIFO0_ITM_bytecount_Pos 27 /*!< TPI FIFO0: ITM_bytecount Position */ +#define TPI_FIFO0_ITM_bytecount_Msk (0x3UL << TPI_FIFO0_ITM_bytecount_Pos) /*!< TPI FIFO0: ITM_bytecount Mask */ + +#define TPI_FIFO0_ETM_ATVALID_Pos 26 /*!< TPI FIFO0: ETM_ATVALID Position */ +#define TPI_FIFO0_ETM_ATVALID_Msk (0x3UL << TPI_FIFO0_ETM_ATVALID_Pos) /*!< TPI FIFO0: ETM_ATVALID Mask */ + +#define TPI_FIFO0_ETM_bytecount_Pos 24 /*!< TPI FIFO0: ETM_bytecount Position */ +#define TPI_FIFO0_ETM_bytecount_Msk (0x3UL << TPI_FIFO0_ETM_bytecount_Pos) /*!< TPI FIFO0: ETM_bytecount Mask */ + +#define TPI_FIFO0_ETM2_Pos 16 /*!< TPI FIFO0: ETM2 Position */ +#define TPI_FIFO0_ETM2_Msk (0xFFUL << TPI_FIFO0_ETM2_Pos) /*!< TPI FIFO0: ETM2 Mask */ + +#define TPI_FIFO0_ETM1_Pos 8 /*!< TPI FIFO0: ETM1 Position */ +#define TPI_FIFO0_ETM1_Msk (0xFFUL << TPI_FIFO0_ETM1_Pos) /*!< TPI FIFO0: ETM1 Mask */ + +#define TPI_FIFO0_ETM0_Pos 0 /*!< TPI FIFO0: ETM0 Position */ +#define TPI_FIFO0_ETM0_Msk (0xFFUL << TPI_FIFO0_ETM0_Pos) /*!< TPI FIFO0: ETM0 Mask */ + +/* TPI ITATBCTR2 Register Definitions */ +#define TPI_ITATBCTR2_ATREADY_Pos 0 /*!< TPI ITATBCTR2: ATREADY Position */ +#define TPI_ITATBCTR2_ATREADY_Msk (0x1UL << TPI_ITATBCTR2_ATREADY_Pos) /*!< TPI ITATBCTR2: ATREADY Mask */ + +/* TPI Integration ITM Data Register Definitions (FIFO1) */ +#define TPI_FIFO1_ITM_ATVALID_Pos 29 /*!< TPI FIFO1: ITM_ATVALID Position */ +#define TPI_FIFO1_ITM_ATVALID_Msk (0x3UL << TPI_FIFO1_ITM_ATVALID_Pos) /*!< TPI FIFO1: ITM_ATVALID Mask */ + +#define TPI_FIFO1_ITM_bytecount_Pos 27 /*!< TPI FIFO1: ITM_bytecount Position */ +#define TPI_FIFO1_ITM_bytecount_Msk (0x3UL << TPI_FIFO1_ITM_bytecount_Pos) /*!< TPI FIFO1: ITM_bytecount Mask */ + +#define TPI_FIFO1_ETM_ATVALID_Pos 26 /*!< TPI FIFO1: ETM_ATVALID Position */ +#define TPI_FIFO1_ETM_ATVALID_Msk (0x3UL << TPI_FIFO1_ETM_ATVALID_Pos) /*!< TPI FIFO1: ETM_ATVALID Mask */ + +#define TPI_FIFO1_ETM_bytecount_Pos 24 /*!< TPI FIFO1: ETM_bytecount Position */ +#define TPI_FIFO1_ETM_bytecount_Msk (0x3UL << TPI_FIFO1_ETM_bytecount_Pos) /*!< TPI FIFO1: ETM_bytecount Mask */ + +#define TPI_FIFO1_ITM2_Pos 16 /*!< TPI FIFO1: ITM2 Position */ +#define TPI_FIFO1_ITM2_Msk (0xFFUL << TPI_FIFO1_ITM2_Pos) /*!< TPI FIFO1: ITM2 Mask */ + +#define TPI_FIFO1_ITM1_Pos 8 /*!< TPI FIFO1: ITM1 Position */ +#define TPI_FIFO1_ITM1_Msk (0xFFUL << TPI_FIFO1_ITM1_Pos) /*!< TPI FIFO1: ITM1 Mask */ + +#define TPI_FIFO1_ITM0_Pos 0 /*!< TPI FIFO1: ITM0 Position */ +#define TPI_FIFO1_ITM0_Msk (0xFFUL << TPI_FIFO1_ITM0_Pos) /*!< TPI FIFO1: ITM0 Mask */ + +/* TPI ITATBCTR0 Register Definitions */ +#define TPI_ITATBCTR0_ATREADY_Pos 0 /*!< TPI ITATBCTR0: ATREADY Position */ +#define TPI_ITATBCTR0_ATREADY_Msk (0x1UL << TPI_ITATBCTR0_ATREADY_Pos) /*!< TPI ITATBCTR0: ATREADY Mask */ + +/* TPI Integration Mode Control Register Definitions */ +#define TPI_ITCTRL_Mode_Pos 0 /*!< TPI ITCTRL: Mode Position */ +#define TPI_ITCTRL_Mode_Msk (0x1UL << TPI_ITCTRL_Mode_Pos) /*!< TPI ITCTRL: Mode Mask */ + +/* TPI DEVID Register Definitions */ +#define TPI_DEVID_NRZVALID_Pos 11 /*!< TPI DEVID: NRZVALID Position */ +#define TPI_DEVID_NRZVALID_Msk (0x1UL << TPI_DEVID_NRZVALID_Pos) /*!< TPI DEVID: NRZVALID Mask */ + +#define TPI_DEVID_MANCVALID_Pos 10 /*!< TPI DEVID: MANCVALID Position */ +#define TPI_DEVID_MANCVALID_Msk (0x1UL << TPI_DEVID_MANCVALID_Pos) /*!< TPI DEVID: MANCVALID Mask */ + +#define TPI_DEVID_PTINVALID_Pos 9 /*!< TPI DEVID: PTINVALID Position */ +#define TPI_DEVID_PTINVALID_Msk (0x1UL << TPI_DEVID_PTINVALID_Pos) /*!< TPI DEVID: PTINVALID Mask */ + +#define TPI_DEVID_MinBufSz_Pos 6 /*!< TPI DEVID: MinBufSz Position */ +#define TPI_DEVID_MinBufSz_Msk (0x7UL << TPI_DEVID_MinBufSz_Pos) /*!< TPI DEVID: MinBufSz Mask */ + +#define TPI_DEVID_AsynClkIn_Pos 5 /*!< TPI DEVID: AsynClkIn Position */ +#define TPI_DEVID_AsynClkIn_Msk (0x1UL << TPI_DEVID_AsynClkIn_Pos) /*!< TPI DEVID: AsynClkIn Mask */ + +#define TPI_DEVID_NrTraceInput_Pos 0 /*!< TPI DEVID: NrTraceInput Position */ +#define TPI_DEVID_NrTraceInput_Msk (0x1FUL << TPI_DEVID_NrTraceInput_Pos) /*!< TPI DEVID: NrTraceInput Mask */ + +/* TPI DEVTYPE Register Definitions */ +#define TPI_DEVTYPE_SubType_Pos 0 /*!< TPI DEVTYPE: SubType Position */ +#define TPI_DEVTYPE_SubType_Msk (0xFUL << TPI_DEVTYPE_SubType_Pos) /*!< TPI DEVTYPE: SubType Mask */ + +#define TPI_DEVTYPE_MajorType_Pos 4 /*!< TPI DEVTYPE: MajorType Position */ +#define TPI_DEVTYPE_MajorType_Msk (0xFUL << TPI_DEVTYPE_MajorType_Pos) /*!< TPI DEVTYPE: MajorType Mask */ + +/*@}*/ /* end of group CMSIS_TPI */ + + +#if (__MPU_PRESENT == 1) +/** \ingroup CMSIS_core_register + \defgroup CMSIS_MPU Memory Protection Unit (MPU) + \brief Type definitions for the Memory Protection Unit (MPU) + @{ + */ + +/** \brief Structure type to access the Memory Protection Unit (MPU). + */ +typedef struct +{ + __I uint32_t TYPE; /*!< Offset: 0x000 (R/ ) MPU Type Register */ + __IO uint32_t CTRL; /*!< Offset: 0x004 (R/W) MPU Control Register */ + __IO uint32_t RNR; /*!< Offset: 0x008 (R/W) MPU Region RNRber Register */ + __IO uint32_t RBAR; /*!< Offset: 0x00C (R/W) MPU Region Base Address Register */ + __IO uint32_t RASR; /*!< Offset: 0x010 (R/W) MPU Region Attribute and Size Register */ + __IO uint32_t RBAR_A1; /*!< Offset: 0x014 (R/W) MPU Alias 1 Region Base Address Register */ + __IO uint32_t RASR_A1; /*!< Offset: 0x018 (R/W) MPU Alias 1 Region Attribute and Size Register */ + __IO uint32_t RBAR_A2; /*!< Offset: 0x01C (R/W) MPU Alias 2 Region Base Address Register */ + __IO uint32_t RASR_A2; /*!< Offset: 0x020 (R/W) MPU Alias 2 Region Attribute and Size Register */ + __IO uint32_t RBAR_A3; /*!< Offset: 0x024 (R/W) MPU Alias 3 Region Base Address Register */ + __IO uint32_t RASR_A3; /*!< Offset: 0x028 (R/W) MPU Alias 3 Region Attribute and Size Register */ +} MPU_Type; + +/* MPU Type Register */ +#define MPU_TYPE_IREGION_Pos 16 /*!< MPU TYPE: IREGION Position */ +#define MPU_TYPE_IREGION_Msk (0xFFUL << MPU_TYPE_IREGION_Pos) /*!< MPU TYPE: IREGION Mask */ + +#define MPU_TYPE_DREGION_Pos 8 /*!< MPU TYPE: DREGION Position */ +#define MPU_TYPE_DREGION_Msk (0xFFUL << MPU_TYPE_DREGION_Pos) /*!< MPU TYPE: DREGION Mask */ + +#define MPU_TYPE_SEPARATE_Pos 0 /*!< MPU TYPE: SEPARATE Position */ +#define MPU_TYPE_SEPARATE_Msk (1UL << MPU_TYPE_SEPARATE_Pos) /*!< MPU TYPE: SEPARATE Mask */ + +/* MPU Control Register */ +#define MPU_CTRL_PRIVDEFENA_Pos 2 /*!< MPU CTRL: PRIVDEFENA Position */ +#define MPU_CTRL_PRIVDEFENA_Msk (1UL << MPU_CTRL_PRIVDEFENA_Pos) /*!< MPU CTRL: PRIVDEFENA Mask */ + +#define MPU_CTRL_HFNMIENA_Pos 1 /*!< MPU CTRL: HFNMIENA Position */ +#define MPU_CTRL_HFNMIENA_Msk (1UL << MPU_CTRL_HFNMIENA_Pos) /*!< MPU CTRL: HFNMIENA Mask */ + +#define MPU_CTRL_ENABLE_Pos 0 /*!< MPU CTRL: ENABLE Position */ +#define MPU_CTRL_ENABLE_Msk (1UL << MPU_CTRL_ENABLE_Pos) /*!< MPU CTRL: ENABLE Mask */ + +/* MPU Region Number Register */ +#define MPU_RNR_REGION_Pos 0 /*!< MPU RNR: REGION Position */ +#define MPU_RNR_REGION_Msk (0xFFUL << MPU_RNR_REGION_Pos) /*!< MPU RNR: REGION Mask */ + +/* MPU Region Base Address Register */ +#define MPU_RBAR_ADDR_Pos 5 /*!< MPU RBAR: ADDR Position */ +#define MPU_RBAR_ADDR_Msk (0x7FFFFFFUL << MPU_RBAR_ADDR_Pos) /*!< MPU RBAR: ADDR Mask */ + +#define MPU_RBAR_VALID_Pos 4 /*!< MPU RBAR: VALID Position */ +#define MPU_RBAR_VALID_Msk (1UL << MPU_RBAR_VALID_Pos) /*!< MPU RBAR: VALID Mask */ + +#define MPU_RBAR_REGION_Pos 0 /*!< MPU RBAR: REGION Position */ +#define MPU_RBAR_REGION_Msk (0xFUL << MPU_RBAR_REGION_Pos) /*!< MPU RBAR: REGION Mask */ + +/* MPU Region Attribute and Size Register */ +#define MPU_RASR_ATTRS_Pos 16 /*!< MPU RASR: MPU Region Attribute field Position */ +#define MPU_RASR_ATTRS_Msk (0xFFFFUL << MPU_RASR_ATTRS_Pos) /*!< MPU RASR: MPU Region Attribute field Mask */ + +#define MPU_RASR_XN_Pos 28 /*!< MPU RASR: ATTRS.XN Position */ +#define MPU_RASR_XN_Msk (1UL << MPU_RASR_XN_Pos) /*!< MPU RASR: ATTRS.XN Mask */ + +#define MPU_RASR_AP_Pos 24 /*!< MPU RASR: ATTRS.AP Position */ +#define MPU_RASR_AP_Msk (0x7UL << MPU_RASR_AP_Pos) /*!< MPU RASR: ATTRS.AP Mask */ + +#define MPU_RASR_TEX_Pos 19 /*!< MPU RASR: ATTRS.TEX Position */ +#define MPU_RASR_TEX_Msk (0x7UL << MPU_RASR_TEX_Pos) /*!< MPU RASR: ATTRS.TEX Mask */ + +#define MPU_RASR_S_Pos 18 /*!< MPU RASR: ATTRS.S Position */ +#define MPU_RASR_S_Msk (1UL << MPU_RASR_S_Pos) /*!< MPU RASR: ATTRS.S Mask */ + +#define MPU_RASR_C_Pos 17 /*!< MPU RASR: ATTRS.C Position */ +#define MPU_RASR_C_Msk (1UL << MPU_RASR_C_Pos) /*!< MPU RASR: ATTRS.C Mask */ + +#define MPU_RASR_B_Pos 16 /*!< MPU RASR: ATTRS.B Position */ +#define MPU_RASR_B_Msk (1UL << MPU_RASR_B_Pos) /*!< MPU RASR: ATTRS.B Mask */ + +#define MPU_RASR_SRD_Pos 8 /*!< MPU RASR: Sub-Region Disable Position */ +#define MPU_RASR_SRD_Msk (0xFFUL << MPU_RASR_SRD_Pos) /*!< MPU RASR: Sub-Region Disable Mask */ + +#define MPU_RASR_SIZE_Pos 1 /*!< MPU RASR: Region Size Field Position */ +#define MPU_RASR_SIZE_Msk (0x1FUL << MPU_RASR_SIZE_Pos) /*!< MPU RASR: Region Size Field Mask */ + +#define MPU_RASR_ENABLE_Pos 0 /*!< MPU RASR: Region enable bit Position */ +#define MPU_RASR_ENABLE_Msk (1UL << MPU_RASR_ENABLE_Pos) /*!< MPU RASR: Region enable bit Disable Mask */ + +/*@} end of group CMSIS_MPU */ +#endif + + +/** \ingroup CMSIS_core_register + \defgroup CMSIS_CoreDebug Core Debug Registers (CoreDebug) + \brief Type definitions for the Core Debug Registers + @{ + */ + +/** \brief Structure type to access the Core Debug Register (CoreDebug). + */ +typedef struct +{ + __IO uint32_t DHCSR; /*!< Offset: 0x000 (R/W) Debug Halting Control and Status Register */ + __O uint32_t DCRSR; /*!< Offset: 0x004 ( /W) Debug Core Register Selector Register */ + __IO uint32_t DCRDR; /*!< Offset: 0x008 (R/W) Debug Core Register Data Register */ + __IO uint32_t DEMCR; /*!< Offset: 0x00C (R/W) Debug Exception and Monitor Control Register */ +} CoreDebug_Type; + +/* Debug Halting Control and Status Register */ +#define CoreDebug_DHCSR_DBGKEY_Pos 16 /*!< CoreDebug DHCSR: DBGKEY Position */ +#define CoreDebug_DHCSR_DBGKEY_Msk (0xFFFFUL << CoreDebug_DHCSR_DBGKEY_Pos) /*!< CoreDebug DHCSR: DBGKEY Mask */ + +#define CoreDebug_DHCSR_S_RESET_ST_Pos 25 /*!< CoreDebug DHCSR: S_RESET_ST Position */ +#define CoreDebug_DHCSR_S_RESET_ST_Msk (1UL << CoreDebug_DHCSR_S_RESET_ST_Pos) /*!< CoreDebug DHCSR: S_RESET_ST Mask */ + +#define CoreDebug_DHCSR_S_RETIRE_ST_Pos 24 /*!< CoreDebug DHCSR: S_RETIRE_ST Position */ +#define CoreDebug_DHCSR_S_RETIRE_ST_Msk (1UL << CoreDebug_DHCSR_S_RETIRE_ST_Pos) /*!< CoreDebug DHCSR: S_RETIRE_ST Mask */ + +#define CoreDebug_DHCSR_S_LOCKUP_Pos 19 /*!< CoreDebug DHCSR: S_LOCKUP Position */ +#define CoreDebug_DHCSR_S_LOCKUP_Msk (1UL << CoreDebug_DHCSR_S_LOCKUP_Pos) /*!< CoreDebug DHCSR: S_LOCKUP Mask */ + +#define CoreDebug_DHCSR_S_SLEEP_Pos 18 /*!< CoreDebug DHCSR: S_SLEEP Position */ +#define CoreDebug_DHCSR_S_SLEEP_Msk (1UL << CoreDebug_DHCSR_S_SLEEP_Pos) /*!< CoreDebug DHCSR: S_SLEEP Mask */ + +#define CoreDebug_DHCSR_S_HALT_Pos 17 /*!< CoreDebug DHCSR: S_HALT Position */ +#define CoreDebug_DHCSR_S_HALT_Msk (1UL << CoreDebug_DHCSR_S_HALT_Pos) /*!< CoreDebug DHCSR: S_HALT Mask */ + +#define CoreDebug_DHCSR_S_REGRDY_Pos 16 /*!< CoreDebug DHCSR: S_REGRDY Position */ +#define CoreDebug_DHCSR_S_REGRDY_Msk (1UL << CoreDebug_DHCSR_S_REGRDY_Pos) /*!< CoreDebug DHCSR: S_REGRDY Mask */ + +#define CoreDebug_DHCSR_C_SNAPSTALL_Pos 5 /*!< CoreDebug DHCSR: C_SNAPSTALL Position */ +#define CoreDebug_DHCSR_C_SNAPSTALL_Msk (1UL << CoreDebug_DHCSR_C_SNAPSTALL_Pos) /*!< CoreDebug DHCSR: C_SNAPSTALL Mask */ + +#define CoreDebug_DHCSR_C_MASKINTS_Pos 3 /*!< CoreDebug DHCSR: C_MASKINTS Position */ +#define CoreDebug_DHCSR_C_MASKINTS_Msk (1UL << CoreDebug_DHCSR_C_MASKINTS_Pos) /*!< CoreDebug DHCSR: C_MASKINTS Mask */ + +#define CoreDebug_DHCSR_C_STEP_Pos 2 /*!< CoreDebug DHCSR: C_STEP Position */ +#define CoreDebug_DHCSR_C_STEP_Msk (1UL << CoreDebug_DHCSR_C_STEP_Pos) /*!< CoreDebug DHCSR: C_STEP Mask */ + +#define CoreDebug_DHCSR_C_HALT_Pos 1 /*!< CoreDebug DHCSR: C_HALT Position */ +#define CoreDebug_DHCSR_C_HALT_Msk (1UL << CoreDebug_DHCSR_C_HALT_Pos) /*!< CoreDebug DHCSR: C_HALT Mask */ + +#define CoreDebug_DHCSR_C_DEBUGEN_Pos 0 /*!< CoreDebug DHCSR: C_DEBUGEN Position */ +#define CoreDebug_DHCSR_C_DEBUGEN_Msk (1UL << CoreDebug_DHCSR_C_DEBUGEN_Pos) /*!< CoreDebug DHCSR: C_DEBUGEN Mask */ + +/* Debug Core Register Selector Register */ +#define CoreDebug_DCRSR_REGWnR_Pos 16 /*!< CoreDebug DCRSR: REGWnR Position */ +#define CoreDebug_DCRSR_REGWnR_Msk (1UL << CoreDebug_DCRSR_REGWnR_Pos) /*!< CoreDebug DCRSR: REGWnR Mask */ + +#define CoreDebug_DCRSR_REGSEL_Pos 0 /*!< CoreDebug DCRSR: REGSEL Position */ +#define CoreDebug_DCRSR_REGSEL_Msk (0x1FUL << CoreDebug_DCRSR_REGSEL_Pos) /*!< CoreDebug DCRSR: REGSEL Mask */ + +/* Debug Exception and Monitor Control Register */ +#define CoreDebug_DEMCR_TRCENA_Pos 24 /*!< CoreDebug DEMCR: TRCENA Position */ +#define CoreDebug_DEMCR_TRCENA_Msk (1UL << CoreDebug_DEMCR_TRCENA_Pos) /*!< CoreDebug DEMCR: TRCENA Mask */ + +#define CoreDebug_DEMCR_MON_REQ_Pos 19 /*!< CoreDebug DEMCR: MON_REQ Position */ +#define CoreDebug_DEMCR_MON_REQ_Msk (1UL << CoreDebug_DEMCR_MON_REQ_Pos) /*!< CoreDebug DEMCR: MON_REQ Mask */ + +#define CoreDebug_DEMCR_MON_STEP_Pos 18 /*!< CoreDebug DEMCR: MON_STEP Position */ +#define CoreDebug_DEMCR_MON_STEP_Msk (1UL << CoreDebug_DEMCR_MON_STEP_Pos) /*!< CoreDebug DEMCR: MON_STEP Mask */ + +#define CoreDebug_DEMCR_MON_PEND_Pos 17 /*!< CoreDebug DEMCR: MON_PEND Position */ +#define CoreDebug_DEMCR_MON_PEND_Msk (1UL << CoreDebug_DEMCR_MON_PEND_Pos) /*!< CoreDebug DEMCR: MON_PEND Mask */ + +#define CoreDebug_DEMCR_MON_EN_Pos 16 /*!< CoreDebug DEMCR: MON_EN Position */ +#define CoreDebug_DEMCR_MON_EN_Msk (1UL << CoreDebug_DEMCR_MON_EN_Pos) /*!< CoreDebug DEMCR: MON_EN Mask */ + +#define CoreDebug_DEMCR_VC_HARDERR_Pos 10 /*!< CoreDebug DEMCR: VC_HARDERR Position */ +#define CoreDebug_DEMCR_VC_HARDERR_Msk (1UL << CoreDebug_DEMCR_VC_HARDERR_Pos) /*!< CoreDebug DEMCR: VC_HARDERR Mask */ + +#define CoreDebug_DEMCR_VC_INTERR_Pos 9 /*!< CoreDebug DEMCR: VC_INTERR Position */ +#define CoreDebug_DEMCR_VC_INTERR_Msk (1UL << CoreDebug_DEMCR_VC_INTERR_Pos) /*!< CoreDebug DEMCR: VC_INTERR Mask */ + +#define CoreDebug_DEMCR_VC_BUSERR_Pos 8 /*!< CoreDebug DEMCR: VC_BUSERR Position */ +#define CoreDebug_DEMCR_VC_BUSERR_Msk (1UL << CoreDebug_DEMCR_VC_BUSERR_Pos) /*!< CoreDebug DEMCR: VC_BUSERR Mask */ + +#define CoreDebug_DEMCR_VC_STATERR_Pos 7 /*!< CoreDebug DEMCR: VC_STATERR Position */ +#define CoreDebug_DEMCR_VC_STATERR_Msk (1UL << CoreDebug_DEMCR_VC_STATERR_Pos) /*!< CoreDebug DEMCR: VC_STATERR Mask */ + +#define CoreDebug_DEMCR_VC_CHKERR_Pos 6 /*!< CoreDebug DEMCR: VC_CHKERR Position */ +#define CoreDebug_DEMCR_VC_CHKERR_Msk (1UL << CoreDebug_DEMCR_VC_CHKERR_Pos) /*!< CoreDebug DEMCR: VC_CHKERR Mask */ + +#define CoreDebug_DEMCR_VC_NOCPERR_Pos 5 /*!< CoreDebug DEMCR: VC_NOCPERR Position */ +#define CoreDebug_DEMCR_VC_NOCPERR_Msk (1UL << CoreDebug_DEMCR_VC_NOCPERR_Pos) /*!< CoreDebug DEMCR: VC_NOCPERR Mask */ + +#define CoreDebug_DEMCR_VC_MMERR_Pos 4 /*!< CoreDebug DEMCR: VC_MMERR Position */ +#define CoreDebug_DEMCR_VC_MMERR_Msk (1UL << CoreDebug_DEMCR_VC_MMERR_Pos) /*!< CoreDebug DEMCR: VC_MMERR Mask */ + +#define CoreDebug_DEMCR_VC_CORERESET_Pos 0 /*!< CoreDebug DEMCR: VC_CORERESET Position */ +#define CoreDebug_DEMCR_VC_CORERESET_Msk (1UL << CoreDebug_DEMCR_VC_CORERESET_Pos) /*!< CoreDebug DEMCR: VC_CORERESET Mask */ + +/*@} end of group CMSIS_CoreDebug */ + + +/** \ingroup CMSIS_core_register + \defgroup CMSIS_core_base Core Definitions + \brief Definitions for base addresses, unions, and structures. + @{ + */ + +/* Memory mapping of Cortex-M3 Hardware */ +#define SCS_BASE (0xE000E000UL) /*!< System Control Space Base Address */ +#define ITM_BASE (0xE0000000UL) /*!< ITM Base Address */ +#define DWT_BASE (0xE0001000UL) /*!< DWT Base Address */ +#define TPI_BASE (0xE0040000UL) /*!< TPI Base Address */ +#define CoreDebug_BASE (0xE000EDF0UL) /*!< Core Debug Base Address */ +#define SysTick_BASE (SCS_BASE + 0x0010UL) /*!< SysTick Base Address */ +#define NVIC_BASE (SCS_BASE + 0x0100UL) /*!< NVIC Base Address */ +#define SCB_BASE (SCS_BASE + 0x0D00UL) /*!< System Control Block Base Address */ + +#define SCnSCB ((SCnSCB_Type *) SCS_BASE ) /*!< System control Register not in SCB */ +#define SCB ((SCB_Type *) SCB_BASE ) /*!< SCB configuration struct */ +#define SysTick ((SysTick_Type *) SysTick_BASE ) /*!< SysTick configuration struct */ +#define NVIC ((NVIC_Type *) NVIC_BASE ) /*!< NVIC configuration struct */ +#define ITM ((ITM_Type *) ITM_BASE ) /*!< ITM configuration struct */ +#define DWT ((DWT_Type *) DWT_BASE ) /*!< DWT configuration struct */ +#define TPI ((TPI_Type *) TPI_BASE ) /*!< TPI configuration struct */ +#define CoreDebug ((CoreDebug_Type *) CoreDebug_BASE) /*!< Core Debug configuration struct */ + +#if (__MPU_PRESENT == 1) + #define MPU_BASE (SCS_BASE + 0x0D90UL) /*!< Memory Protection Unit */ + #define MPU ((MPU_Type *) MPU_BASE ) /*!< Memory Protection Unit */ +#endif + +/*@} */ + + + +/******************************************************************************* + * Hardware Abstraction Layer + Core Function Interface contains: + - Core NVIC Functions + - Core SysTick Functions + - Core Debug Functions + - Core Register Access Functions + ******************************************************************************/ +/** \defgroup CMSIS_Core_FunctionInterface Functions and Instructions Reference +*/ + + + +/* ########################## NVIC functions #################################### */ +/** \ingroup CMSIS_Core_FunctionInterface + \defgroup CMSIS_Core_NVICFunctions NVIC Functions + \brief Functions that manage interrupts and exceptions via the NVIC. + @{ + */ + +/** \brief Set Priority Grouping + + The function sets the priority grouping field using the required unlock sequence. + The parameter PriorityGroup is assigned to the field SCB->AIRCR [10:8] PRIGROUP field. + Only values from 0..7 are used. + In case of a conflict between priority grouping and available + priority bits (__NVIC_PRIO_BITS), the smallest possible priority group is set. + + \param [in] PriorityGroup Priority grouping field. + */ +__STATIC_INLINE void NVIC_SetPriorityGrouping(uint32_t PriorityGroup) +{ + uint32_t reg_value; + uint32_t PriorityGroupTmp = (PriorityGroup & (uint32_t)0x07); /* only values 0..7 are used */ + + reg_value = SCB->AIRCR; /* read old register configuration */ + reg_value &= ~(SCB_AIRCR_VECTKEY_Msk | SCB_AIRCR_PRIGROUP_Msk); /* clear bits to change */ + reg_value = (reg_value | + ((uint32_t)0x5FA << SCB_AIRCR_VECTKEY_Pos) | + (PriorityGroupTmp << 8)); /* Insert write key and priorty group */ + SCB->AIRCR = reg_value; +} + + +/** \brief Get Priority Grouping + + The function reads the priority grouping field from the NVIC Interrupt Controller. + + \return Priority grouping field (SCB->AIRCR [10:8] PRIGROUP field). + */ +__STATIC_INLINE uint32_t NVIC_GetPriorityGrouping(void) +{ + return ((SCB->AIRCR & SCB_AIRCR_PRIGROUP_Msk) >> SCB_AIRCR_PRIGROUP_Pos); /* read priority grouping field */ +} + + +/** \brief Enable External Interrupt + + The function enables a device-specific interrupt in the NVIC interrupt controller. + + \param [in] IRQn External interrupt number. Value cannot be negative. + */ +__STATIC_INLINE void NVIC_EnableIRQ(IRQn_Type IRQn) +{ + NVIC->ISER[((uint32_t)(IRQn) >> 5)] = (1 << ((uint32_t)(IRQn) & 0x1F)); /* enable interrupt */ +} + + +/** \brief Disable External Interrupt + + The function disables a device-specific interrupt in the NVIC interrupt controller. + + \param [in] IRQn External interrupt number. Value cannot be negative. + */ +__STATIC_INLINE void NVIC_DisableIRQ(IRQn_Type IRQn) +{ + NVIC->ICER[((uint32_t)(IRQn) >> 5)] = (1 << ((uint32_t)(IRQn) & 0x1F)); /* disable interrupt */ +} + + +/** \brief Get Pending Interrupt + + The function reads the pending register in the NVIC and returns the pending bit + for the specified interrupt. + + \param [in] IRQn Interrupt number. + + \return 0 Interrupt status is not pending. + \return 1 Interrupt status is pending. + */ +__STATIC_INLINE uint32_t NVIC_GetPendingIRQ(IRQn_Type IRQn) +{ + return((uint32_t) ((NVIC->ISPR[(uint32_t)(IRQn) >> 5] & (1 << ((uint32_t)(IRQn) & 0x1F)))?1:0)); /* Return 1 if pending else 0 */ +} + + +/** \brief Set Pending Interrupt + + The function sets the pending bit of an external interrupt. + + \param [in] IRQn Interrupt number. Value cannot be negative. + */ +__STATIC_INLINE void NVIC_SetPendingIRQ(IRQn_Type IRQn) +{ + NVIC->ISPR[((uint32_t)(IRQn) >> 5)] = (1 << ((uint32_t)(IRQn) & 0x1F)); /* set interrupt pending */ +} + + +/** \brief Clear Pending Interrupt + + The function clears the pending bit of an external interrupt. + + \param [in] IRQn External interrupt number. Value cannot be negative. + */ +__STATIC_INLINE void NVIC_ClearPendingIRQ(IRQn_Type IRQn) +{ + NVIC->ICPR[((uint32_t)(IRQn) >> 5)] = (1 << ((uint32_t)(IRQn) & 0x1F)); /* Clear pending interrupt */ +} + + +/** \brief Get Active Interrupt + + The function reads the active register in NVIC and returns the active bit. + + \param [in] IRQn Interrupt number. + + \return 0 Interrupt status is not active. + \return 1 Interrupt status is active. + */ +__STATIC_INLINE uint32_t NVIC_GetActive(IRQn_Type IRQn) +{ + return((uint32_t)((NVIC->IABR[(uint32_t)(IRQn) >> 5] & (1 << ((uint32_t)(IRQn) & 0x1F)))?1:0)); /* Return 1 if active else 0 */ +} + + +/** \brief Set Interrupt Priority + + The function sets the priority of an interrupt. + + \note The priority cannot be set for every core interrupt. + + \param [in] IRQn Interrupt number. + \param [in] priority Priority to set. + */ +__STATIC_INLINE void NVIC_SetPriority(IRQn_Type IRQn, uint32_t priority) +{ + if(IRQn < 0) { + SCB->SHP[((uint32_t)(IRQn) & 0xF)-4] = ((priority << (8 - __NVIC_PRIO_BITS)) & 0xff); } /* set Priority for Cortex-M System Interrupts */ + else { + NVIC->IP[(uint32_t)(IRQn)] = ((priority << (8 - __NVIC_PRIO_BITS)) & 0xff); } /* set Priority for device specific Interrupts */ +} + + +/** \brief Get Interrupt Priority + + The function reads the priority of an interrupt. The interrupt + number can be positive to specify an external (device specific) + interrupt, or negative to specify an internal (core) interrupt. + + + \param [in] IRQn Interrupt number. + \return Interrupt Priority. Value is aligned automatically to the implemented + priority bits of the microcontroller. + */ +__STATIC_INLINE uint32_t NVIC_GetPriority(IRQn_Type IRQn) +{ + + if(IRQn < 0) { + return((uint32_t)(SCB->SHP[((uint32_t)(IRQn) & 0xF)-4] >> (8 - __NVIC_PRIO_BITS))); } /* get priority for Cortex-M system interrupts */ + else { + return((uint32_t)(NVIC->IP[(uint32_t)(IRQn)] >> (8 - __NVIC_PRIO_BITS))); } /* get priority for device specific interrupts */ +} + + +/** \brief Encode Priority + + The function encodes the priority for an interrupt with the given priority group, + preemptive priority value, and subpriority value. + In case of a conflict between priority grouping and available + priority bits (__NVIC_PRIO_BITS), the samllest possible priority group is set. + + \param [in] PriorityGroup Used priority group. + \param [in] PreemptPriority Preemptive priority value (starting from 0). + \param [in] SubPriority Subpriority value (starting from 0). + \return Encoded priority. Value can be used in the function \ref NVIC_SetPriority(). + */ +__STATIC_INLINE uint32_t NVIC_EncodePriority (uint32_t PriorityGroup, uint32_t PreemptPriority, uint32_t SubPriority) +{ + uint32_t PriorityGroupTmp = (PriorityGroup & 0x07); /* only values 0..7 are used */ + uint32_t PreemptPriorityBits; + uint32_t SubPriorityBits; + + PreemptPriorityBits = ((7 - PriorityGroupTmp) > __NVIC_PRIO_BITS) ? __NVIC_PRIO_BITS : 7 - PriorityGroupTmp; + SubPriorityBits = ((PriorityGroupTmp + __NVIC_PRIO_BITS) < 7) ? 0 : PriorityGroupTmp - 7 + __NVIC_PRIO_BITS; + + return ( + ((PreemptPriority & ((1 << (PreemptPriorityBits)) - 1)) << SubPriorityBits) | + ((SubPriority & ((1 << (SubPriorityBits )) - 1))) + ); +} + + +/** \brief Decode Priority + + The function decodes an interrupt priority value with a given priority group to + preemptive priority value and subpriority value. + In case of a conflict between priority grouping and available + priority bits (__NVIC_PRIO_BITS) the samllest possible priority group is set. + + \param [in] Priority Priority value, which can be retrieved with the function \ref NVIC_GetPriority(). + \param [in] PriorityGroup Used priority group. + \param [out] pPreemptPriority Preemptive priority value (starting from 0). + \param [out] pSubPriority Subpriority value (starting from 0). + */ +__STATIC_INLINE void NVIC_DecodePriority (uint32_t Priority, uint32_t PriorityGroup, uint32_t* pPreemptPriority, uint32_t* pSubPriority) +{ + uint32_t PriorityGroupTmp = (PriorityGroup & 0x07); /* only values 0..7 are used */ + uint32_t PreemptPriorityBits; + uint32_t SubPriorityBits; + + PreemptPriorityBits = ((7 - PriorityGroupTmp) > __NVIC_PRIO_BITS) ? __NVIC_PRIO_BITS : 7 - PriorityGroupTmp; + SubPriorityBits = ((PriorityGroupTmp + __NVIC_PRIO_BITS) < 7) ? 0 : PriorityGroupTmp - 7 + __NVIC_PRIO_BITS; + + *pPreemptPriority = (Priority >> SubPriorityBits) & ((1 << (PreemptPriorityBits)) - 1); + *pSubPriority = (Priority ) & ((1 << (SubPriorityBits )) - 1); +} + + +/** \brief System Reset + + The function initiates a system reset request to reset the MCU. + */ +__STATIC_INLINE void NVIC_SystemReset(void) +{ + __DSB(); /* Ensure all outstanding memory accesses included + buffered write are completed before reset */ + SCB->AIRCR = ((0x5FA << SCB_AIRCR_VECTKEY_Pos) | + (SCB->AIRCR & SCB_AIRCR_PRIGROUP_Msk) | + SCB_AIRCR_SYSRESETREQ_Msk); /* Keep priority group unchanged */ + __DSB(); /* Ensure completion of memory access */ + while(1); /* wait until reset */ +} + +/*@} end of CMSIS_Core_NVICFunctions */ + + + +/* ################################## SysTick function ############################################ */ +/** \ingroup CMSIS_Core_FunctionInterface + \defgroup CMSIS_Core_SysTickFunctions SysTick Functions + \brief Functions that configure the System. + @{ + */ + +#if (__Vendor_SysTickConfig == 0) + +/** \brief System Tick Configuration + + The function initializes the System Timer and its interrupt, and starts the System Tick Timer. + Counter is in free running mode to generate periodic interrupts. + + \param [in] ticks Number of ticks between two interrupts. + + \return 0 Function succeeded. + \return 1 Function failed. + + \note When the variable __Vendor_SysTickConfig is set to 1, then the + function SysTick_Config is not included. In this case, the file device.h + must contain a vendor-specific implementation of this function. + + */ +__STATIC_INLINE uint32_t SysTick_Config(uint32_t ticks) +{ + if ((ticks - 1) > SysTick_LOAD_RELOAD_Msk) return (1); /* Reload value impossible */ + + SysTick->LOAD = ticks - 1; /* set reload register */ + NVIC_SetPriority (SysTick_IRQn, (1<<__NVIC_PRIO_BITS) - 1); /* set Priority for Systick Interrupt */ + SysTick->VAL = 0; /* Load the SysTick Counter Value */ + SysTick->CTRL = SysTick_CTRL_CLKSOURCE_Msk | + SysTick_CTRL_TICKINT_Msk | + SysTick_CTRL_ENABLE_Msk; /* Enable SysTick IRQ and SysTick Timer */ + return (0); /* Function successful */ +} + +#endif + +/*@} end of CMSIS_Core_SysTickFunctions */ + + + +/* ##################################### Debug In/Output function ########################################### */ +/** \ingroup CMSIS_Core_FunctionInterface + \defgroup CMSIS_core_DebugFunctions ITM Functions + \brief Functions that access the ITM debug interface. + @{ + */ + +extern volatile int32_t ITM_RxBuffer; /*!< External variable to receive characters. */ +#define ITM_RXBUFFER_EMPTY 0x5AA55AA5 /*!< Value identifying \ref ITM_RxBuffer is ready for next character. */ + + +/** \brief ITM Send Character + + The function transmits a character via the ITM channel 0, and + \li Just returns when no debugger is connected that has booked the output. + \li Is blocking when a debugger is connected, but the previous character sent has not been transmitted. + + \param [in] ch Character to transmit. + + \returns Character to transmit. + */ +__STATIC_INLINE uint32_t ITM_SendChar (uint32_t ch) +{ + if ((ITM->TCR & ITM_TCR_ITMENA_Msk) && /* ITM enabled */ + (ITM->TER & (1UL << 0) ) ) /* ITM Port #0 enabled */ + { + while (ITM->PORT[0].u32 == 0); + ITM->PORT[0].u8 = (uint8_t) ch; + } + return (ch); +} + + +/** \brief ITM Receive Character + + The function inputs a character via the external variable \ref ITM_RxBuffer. + + \return Received character. + \return -1 No character pending. + */ +__STATIC_INLINE int32_t ITM_ReceiveChar (void) { + int32_t ch = -1; /* no character available */ + + if (ITM_RxBuffer != ITM_RXBUFFER_EMPTY) { + ch = ITM_RxBuffer; + ITM_RxBuffer = ITM_RXBUFFER_EMPTY; /* ready for next character */ + } + + return (ch); +} + + +/** \brief ITM Check Character + + The function checks whether a character is pending for reading in the variable \ref ITM_RxBuffer. + + \return 0 No character available. + \return 1 Character available. + */ +__STATIC_INLINE int32_t ITM_CheckChar (void) { + + if (ITM_RxBuffer == ITM_RXBUFFER_EMPTY) { + return (0); /* no character available */ + } else { + return (1); /* character available */ + } +} + +/*@} end of CMSIS_core_DebugFunctions */ + +#endif /* __CORE_CM3_H_DEPENDANT */ + +#endif /* __CMSIS_GENERIC */ + +#ifdef __cplusplus +} +#endif diff --git a/bsp/gd32/libraries/GD32F10x_Firmware_Library/CMSIS/core_cmFunc.h b/bsp/gd32/libraries/GD32F10x_Firmware_Library/CMSIS/core_cmFunc.h new file mode 100644 index 0000000000..2c2af69c18 --- /dev/null +++ b/bsp/gd32/libraries/GD32F10x_Firmware_Library/CMSIS/core_cmFunc.h @@ -0,0 +1,637 @@ +/**************************************************************************//** + * @file core_cmFunc.h + * @brief CMSIS Cortex-M Core Function Access Header File + * @version V3.30 + * @date 17. February 2014 + * + * @note + * + ******************************************************************************/ +/* Copyright (c) 2009 - 2014 ARM LIMITED + + All rights reserved. + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + - Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + - Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + - Neither the name of ARM nor the names of its contributors may be used + to endorse or promote products derived from this software without + specific prior written permission. + * + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDERS AND CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + ---------------------------------------------------------------------------*/ + + +#ifndef __CORE_CMFUNC_H +#define __CORE_CMFUNC_H + + +/* ########################### Core Function Access ########################### */ +/** \ingroup CMSIS_Core_FunctionInterface + \defgroup CMSIS_Core_RegAccFunctions CMSIS Core Register Access Functions + @{ + */ + +#if defined ( __CC_ARM ) /*------------------RealView Compiler -----------------*/ +/* ARM armcc specific functions */ + +#if (__ARMCC_VERSION < 400677) + #error "Please use ARM Compiler Toolchain V4.0.677 or later!" +#endif + +/* intrinsic void __enable_irq(); */ +/* intrinsic void __disable_irq(); */ + +/** \brief Get Control Register + + This function returns the content of the Control Register. + + \return Control Register value + */ +__STATIC_INLINE uint32_t __get_CONTROL(void) +{ + register uint32_t __regControl __ASM("control"); + return(__regControl); +} + + +/** \brief Set Control Register + + This function writes the given value to the Control Register. + + \param [in] control Control Register value to set + */ +__STATIC_INLINE void __set_CONTROL(uint32_t control) +{ + register uint32_t __regControl __ASM("control"); + __regControl = control; +} + + +/** \brief Get IPSR Register + + This function returns the content of the IPSR Register. + + \return IPSR Register value + */ +__STATIC_INLINE uint32_t __get_IPSR(void) +{ + register uint32_t __regIPSR __ASM("ipsr"); + return(__regIPSR); +} + + +/** \brief Get APSR Register + + This function returns the content of the APSR Register. + + \return APSR Register value + */ +__STATIC_INLINE uint32_t __get_APSR(void) +{ + register uint32_t __regAPSR __ASM("apsr"); + return(__regAPSR); +} + + +/** \brief Get xPSR Register + + This function returns the content of the xPSR Register. + + \return xPSR Register value + */ +__STATIC_INLINE uint32_t __get_xPSR(void) +{ + register uint32_t __regXPSR __ASM("xpsr"); + return(__regXPSR); +} + + +/** \brief Get Process Stack Pointer + + This function returns the current value of the Process Stack Pointer (PSP). + + \return PSP Register value + */ +__STATIC_INLINE uint32_t __get_PSP(void) +{ + register uint32_t __regProcessStackPointer __ASM("psp"); + return(__regProcessStackPointer); +} + + +/** \brief Set Process Stack Pointer + + This function assigns the given value to the Process Stack Pointer (PSP). + + \param [in] topOfProcStack Process Stack Pointer value to set + */ +__STATIC_INLINE void __set_PSP(uint32_t topOfProcStack) +{ + register uint32_t __regProcessStackPointer __ASM("psp"); + __regProcessStackPointer = topOfProcStack; +} + + +/** \brief Get Main Stack Pointer + + This function returns the current value of the Main Stack Pointer (MSP). + + \return MSP Register value + */ +__STATIC_INLINE uint32_t __get_MSP(void) +{ + register uint32_t __regMainStackPointer __ASM("msp"); + return(__regMainStackPointer); +} + + +/** \brief Set Main Stack Pointer + + This function assigns the given value to the Main Stack Pointer (MSP). + + \param [in] topOfMainStack Main Stack Pointer value to set + */ +__STATIC_INLINE void __set_MSP(uint32_t topOfMainStack) +{ + register uint32_t __regMainStackPointer __ASM("msp"); + __regMainStackPointer = topOfMainStack; +} + + +/** \brief Get Priority Mask + + This function returns the current state of the priority mask bit from the Priority Mask Register. + + \return Priority Mask value + */ +__STATIC_INLINE uint32_t __get_PRIMASK(void) +{ + register uint32_t __regPriMask __ASM("primask"); + return(__regPriMask); +} + + +/** \brief Set Priority Mask + + This function assigns the given value to the Priority Mask Register. + + \param [in] priMask Priority Mask + */ +__STATIC_INLINE void __set_PRIMASK(uint32_t priMask) +{ + register uint32_t __regPriMask __ASM("primask"); + __regPriMask = (priMask); +} + + +#if (__CORTEX_M >= 0x03) + +/** \brief Enable FIQ + + This function enables FIQ interrupts by clearing the F-bit in the CPSR. + Can only be executed in Privileged modes. + */ +#define __enable_fault_irq __enable_fiq + + +/** \brief Disable FIQ + + This function disables FIQ interrupts by setting the F-bit in the CPSR. + Can only be executed in Privileged modes. + */ +#define __disable_fault_irq __disable_fiq + + +/** \brief Get Base Priority + + This function returns the current value of the Base Priority register. + + \return Base Priority register value + */ +__STATIC_INLINE uint32_t __get_BASEPRI(void) +{ + register uint32_t __regBasePri __ASM("basepri"); + return(__regBasePri); +} + + +/** \brief Set Base Priority + + This function assigns the given value to the Base Priority register. + + \param [in] basePri Base Priority value to set + */ +__STATIC_INLINE void __set_BASEPRI(uint32_t basePri) +{ + register uint32_t __regBasePri __ASM("basepri"); + __regBasePri = (basePri & 0xff); +} + + +/** \brief Get Fault Mask + + This function returns the current value of the Fault Mask register. + + \return Fault Mask register value + */ +__STATIC_INLINE uint32_t __get_FAULTMASK(void) +{ + register uint32_t __regFaultMask __ASM("faultmask"); + return(__regFaultMask); +} + + +/** \brief Set Fault Mask + + This function assigns the given value to the Fault Mask register. + + \param [in] faultMask Fault Mask value to set + */ +__STATIC_INLINE void __set_FAULTMASK(uint32_t faultMask) +{ + register uint32_t __regFaultMask __ASM("faultmask"); + __regFaultMask = (faultMask & (uint32_t)1); +} + +#endif /* (__CORTEX_M >= 0x03) */ + + +#if (__CORTEX_M == 0x04) + +/** \brief Get FPSCR + + This function returns the current value of the Floating Point Status/Control register. + + \return Floating Point Status/Control register value + */ +__STATIC_INLINE uint32_t __get_FPSCR(void) +{ +#if (__FPU_PRESENT == 1) && (__FPU_USED == 1) + register uint32_t __regfpscr __ASM("fpscr"); + return(__regfpscr); +#else + return(0); +#endif +} + + +/** \brief Set FPSCR + + This function assigns the given value to the Floating Point Status/Control register. + + \param [in] fpscr Floating Point Status/Control value to set + */ +__STATIC_INLINE void __set_FPSCR(uint32_t fpscr) +{ +#if (__FPU_PRESENT == 1) && (__FPU_USED == 1) + register uint32_t __regfpscr __ASM("fpscr"); + __regfpscr = (fpscr); +#endif +} + +#endif /* (__CORTEX_M == 0x04) */ + + +#elif defined ( __GNUC__ ) /*------------------ GNU Compiler ---------------------*/ +/* GNU gcc specific functions */ + +/** \brief Enable IRQ Interrupts + + This function enables IRQ interrupts by clearing the I-bit in the CPSR. + Can only be executed in Privileged modes. + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE void __enable_irq(void) +{ + __ASM volatile ("cpsie i" : : : "memory"); +} + + +/** \brief Disable IRQ Interrupts + + This function disables IRQ interrupts by setting the I-bit in the CPSR. + Can only be executed in Privileged modes. + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE void __disable_irq(void) +{ + __ASM volatile ("cpsid i" : : : "memory"); +} + + +/** \brief Get Control Register + + This function returns the content of the Control Register. + + \return Control Register value + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __get_CONTROL(void) +{ + uint32_t result; + + __ASM volatile ("MRS %0, control" : "=r" (result) ); + return(result); +} + + +/** \brief Set Control Register + + This function writes the given value to the Control Register. + + \param [in] control Control Register value to set + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE void __set_CONTROL(uint32_t control) +{ + __ASM volatile ("MSR control, %0" : : "r" (control) : "memory"); +} + + +/** \brief Get IPSR Register + + This function returns the content of the IPSR Register. + + \return IPSR Register value + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __get_IPSR(void) +{ + uint32_t result; + + __ASM volatile ("MRS %0, ipsr" : "=r" (result) ); + return(result); +} + + +/** \brief Get APSR Register + + This function returns the content of the APSR Register. + + \return APSR Register value + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __get_APSR(void) +{ + uint32_t result; + + __ASM volatile ("MRS %0, apsr" : "=r" (result) ); + return(result); +} + + +/** \brief Get xPSR Register + + This function returns the content of the xPSR Register. + + \return xPSR Register value + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __get_xPSR(void) +{ + uint32_t result; + + __ASM volatile ("MRS %0, xpsr" : "=r" (result) ); + return(result); +} + + +/** \brief Get Process Stack Pointer + + This function returns the current value of the Process Stack Pointer (PSP). + + \return PSP Register value + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __get_PSP(void) +{ + register uint32_t result; + + __ASM volatile ("MRS %0, psp\n" : "=r" (result) ); + return(result); +} + + +/** \brief Set Process Stack Pointer + + This function assigns the given value to the Process Stack Pointer (PSP). + + \param [in] topOfProcStack Process Stack Pointer value to set + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE void __set_PSP(uint32_t topOfProcStack) +{ + __ASM volatile ("MSR psp, %0\n" : : "r" (topOfProcStack) : "sp"); +} + + +/** \brief Get Main Stack Pointer + + This function returns the current value of the Main Stack Pointer (MSP). + + \return MSP Register value + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __get_MSP(void) +{ + register uint32_t result; + + __ASM volatile ("MRS %0, msp\n" : "=r" (result) ); + return(result); +} + + +/** \brief Set Main Stack Pointer + + This function assigns the given value to the Main Stack Pointer (MSP). + + \param [in] topOfMainStack Main Stack Pointer value to set + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE void __set_MSP(uint32_t topOfMainStack) +{ + __ASM volatile ("MSR msp, %0\n" : : "r" (topOfMainStack) : "sp"); +} + + +/** \brief Get Priority Mask + + This function returns the current state of the priority mask bit from the Priority Mask Register. + + \return Priority Mask value + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __get_PRIMASK(void) +{ + uint32_t result; + + __ASM volatile ("MRS %0, primask" : "=r" (result) ); + return(result); +} + + +/** \brief Set Priority Mask + + This function assigns the given value to the Priority Mask Register. + + \param [in] priMask Priority Mask + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE void __set_PRIMASK(uint32_t priMask) +{ + __ASM volatile ("MSR primask, %0" : : "r" (priMask) : "memory"); +} + + +#if (__CORTEX_M >= 0x03) + +/** \brief Enable FIQ + + This function enables FIQ interrupts by clearing the F-bit in the CPSR. + Can only be executed in Privileged modes. + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE void __enable_fault_irq(void) +{ + __ASM volatile ("cpsie f" : : : "memory"); +} + + +/** \brief Disable FIQ + + This function disables FIQ interrupts by setting the F-bit in the CPSR. + Can only be executed in Privileged modes. + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE void __disable_fault_irq(void) +{ + __ASM volatile ("cpsid f" : : : "memory"); +} + + +/** \brief Get Base Priority + + This function returns the current value of the Base Priority register. + + \return Base Priority register value + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __get_BASEPRI(void) +{ + uint32_t result; + + __ASM volatile ("MRS %0, basepri_max" : "=r" (result) ); + return(result); +} + + +/** \brief Set Base Priority + + This function assigns the given value to the Base Priority register. + + \param [in] basePri Base Priority value to set + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE void __set_BASEPRI(uint32_t value) +{ + __ASM volatile ("MSR basepri, %0" : : "r" (value) : "memory"); +} + + +/** \brief Get Fault Mask + + This function returns the current value of the Fault Mask register. + + \return Fault Mask register value + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __get_FAULTMASK(void) +{ + uint32_t result; + + __ASM volatile ("MRS %0, faultmask" : "=r" (result) ); + return(result); +} + + +/** \brief Set Fault Mask + + This function assigns the given value to the Fault Mask register. + + \param [in] faultMask Fault Mask value to set + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE void __set_FAULTMASK(uint32_t faultMask) +{ + __ASM volatile ("MSR faultmask, %0" : : "r" (faultMask) : "memory"); +} + +#endif /* (__CORTEX_M >= 0x03) */ + + +#if (__CORTEX_M == 0x04) + +/** \brief Get FPSCR + + This function returns the current value of the Floating Point Status/Control register. + + \return Floating Point Status/Control register value + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __get_FPSCR(void) +{ +#if (__FPU_PRESENT == 1) && (__FPU_USED == 1) + uint32_t result; + + /* Empty asm statement works as a scheduling barrier */ + __ASM volatile (""); + __ASM volatile ("VMRS %0, fpscr" : "=r" (result) ); + __ASM volatile (""); + return(result); +#else + return(0); +#endif +} + + +/** \brief Set FPSCR + + This function assigns the given value to the Floating Point Status/Control register. + + \param [in] fpscr Floating Point Status/Control value to set + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE void __set_FPSCR(uint32_t fpscr) +{ +#if (__FPU_PRESENT == 1) && (__FPU_USED == 1) + /* Empty asm statement works as a scheduling barrier */ + __ASM volatile (""); + __ASM volatile ("VMSR fpscr, %0" : : "r" (fpscr) : "vfpcc"); + __ASM volatile (""); +#endif +} + +#endif /* (__CORTEX_M == 0x04) */ + + +#elif defined ( __ICCARM__ ) /*------------------ ICC Compiler -------------------*/ +/* IAR iccarm specific functions */ +#include + + +#elif defined ( __TMS470__ ) /*---------------- TI CCS Compiler ------------------*/ +/* TI CCS specific functions */ +#include + + +#elif defined ( __TASKING__ ) /*------------------ TASKING Compiler --------------*/ +/* TASKING carm specific functions */ +/* + * The CMSIS functions have been implemented as intrinsics in the compiler. + * Please use "carm -?i" to get an up to date list of all intrinsics, + * Including the CMSIS ones. + */ + + +#elif defined ( __CSMC__ ) /*------------------ COSMIC Compiler -------------------*/ +/* Cosmic specific functions */ +#include + +#endif + +/*@} end of CMSIS_Core_RegAccFunctions */ + +#endif /* __CORE_CMFUNC_H */ diff --git a/bsp/gd32/libraries/GD32F10x_Firmware_Library/CMSIS/core_cmInstr.h b/bsp/gd32/libraries/GD32F10x_Firmware_Library/CMSIS/core_cmInstr.h new file mode 100644 index 0000000000..49ded78b3d --- /dev/null +++ b/bsp/gd32/libraries/GD32F10x_Firmware_Library/CMSIS/core_cmInstr.h @@ -0,0 +1,687 @@ +/**************************************************************************//** + * @file core_cmInstr.h + * @brief CMSIS Cortex-M Core Instruction Access Header File + * @version V3.30 + * @date 17. February 2014 + * + * @note + * + ******************************************************************************/ +/* Copyright (c) 2009 - 2014 ARM LIMITED + + All rights reserved. + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + - Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + - Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + - Neither the name of ARM nor the names of its contributors may be used + to endorse or promote products derived from this software without + specific prior written permission. + * + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDERS AND CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + ---------------------------------------------------------------------------*/ + + +#ifndef __CORE_CMINSTR_H +#define __CORE_CMINSTR_H + + +/* ########################## Core Instruction Access ######################### */ +/** \defgroup CMSIS_Core_InstructionInterface CMSIS Core Instruction Interface + Access to dedicated instructions + @{ +*/ + +#if defined ( __CC_ARM ) /*------------------RealView Compiler -----------------*/ +/* ARM armcc specific functions */ + +#if (__ARMCC_VERSION < 400677) + #error "Please use ARM Compiler Toolchain V4.0.677 or later!" +#endif + + +/** \brief No Operation + + No Operation does nothing. This instruction can be used for code alignment purposes. + */ +#define __NOP __nop + + +/** \brief Wait For Interrupt + + Wait For Interrupt is a hint instruction that suspends execution + until one of a number of events occurs. + */ +#define __WFI __wfi + + +/** \brief Wait For Event + + Wait For Event is a hint instruction that permits the processor to enter + a low-power state until one of a number of events occurs. + */ +#define __WFE __wfe + + +/** \brief Send Event + + Send Event is a hint instruction. It causes an event to be signaled to the CPU. + */ +#define __SEV __sev + + +/** \brief Instruction Synchronization Barrier + + Instruction Synchronization Barrier flushes the pipeline in the processor, + so that all instructions following the ISB are fetched from cache or + memory, after the instruction has been completed. + */ +#define __ISB() __isb(0xF) + + +/** \brief Data Synchronization Barrier + + This function acts as a special kind of Data Memory Barrier. + It completes when all explicit memory accesses before this instruction complete. + */ +#define __DSB() __dsb(0xF) + + +/** \brief Data Memory Barrier + + This function ensures the apparent order of the explicit memory operations before + and after the instruction, without ensuring their completion. + */ +#define __DMB() __dmb(0xF) + + +/** \brief Reverse byte order (32 bit) + + This function reverses the byte order in integer value. + + \param [in] value Value to reverse + \return Reversed value + */ +#define __REV __rev + + +/** \brief Reverse byte order (16 bit) + + This function reverses the byte order in two unsigned short values. + + \param [in] value Value to reverse + \return Reversed value + */ +#ifndef __NO_EMBEDDED_ASM +__attribute__((section(".rev16_text"))) __STATIC_INLINE __ASM uint32_t __REV16(uint32_t value) +{ + rev16 r0, r0 + bx lr +} +#endif + +/** \brief Reverse byte order in signed short value + + This function reverses the byte order in a signed short value with sign extension to integer. + + \param [in] value Value to reverse + \return Reversed value + */ +#ifndef __NO_EMBEDDED_ASM +__attribute__((section(".revsh_text"))) __STATIC_INLINE __ASM int32_t __REVSH(int32_t value) +{ + revsh r0, r0 + bx lr +} +#endif + + +/** \brief Rotate Right in unsigned value (32 bit) + + This function Rotate Right (immediate) provides the value of the contents of a register rotated by a variable number of bits. + + \param [in] value Value to rotate + \param [in] value Number of Bits to rotate + \return Rotated value + */ +#define __ROR __ror + + +/** \brief Breakpoint + + This function causes the processor to enter Debug state. + Debug tools can use this to investigate system state when the instruction at a particular address is reached. + + \param [in] value is ignored by the processor. + If required, a debugger can use it to store additional information about the breakpoint. + */ +#define __BKPT(value) __breakpoint(value) + + +#if (__CORTEX_M >= 0x03) + +/** \brief Reverse bit order of value + + This function reverses the bit order of the given value. + + \param [in] value Value to reverse + \return Reversed value + */ +#define __RBIT __rbit + + +/** \brief LDR Exclusive (8 bit) + + This function performs a exclusive LDR command for 8 bit value. + + \param [in] ptr Pointer to data + \return value of type uint8_t at (*ptr) + */ +#define __LDREXB(ptr) ((uint8_t ) __ldrex(ptr)) + + +/** \brief LDR Exclusive (16 bit) + + This function performs a exclusive LDR command for 16 bit values. + + \param [in] ptr Pointer to data + \return value of type uint16_t at (*ptr) + */ +#define __LDREXH(ptr) ((uint16_t) __ldrex(ptr)) + + +/** \brief LDR Exclusive (32 bit) + + This function performs a exclusive LDR command for 32 bit values. + + \param [in] ptr Pointer to data + \return value of type uint32_t at (*ptr) + */ +#define __LDREXW(ptr) ((uint32_t ) __ldrex(ptr)) + + +/** \brief STR Exclusive (8 bit) + + This function performs a exclusive STR command for 8 bit values. + + \param [in] value Value to store + \param [in] ptr Pointer to location + \return 0 Function succeeded + \return 1 Function failed + */ +#define __STREXB(value, ptr) __strex(value, ptr) + + +/** \brief STR Exclusive (16 bit) + + This function performs a exclusive STR command for 16 bit values. + + \param [in] value Value to store + \param [in] ptr Pointer to location + \return 0 Function succeeded + \return 1 Function failed + */ +#define __STREXH(value, ptr) __strex(value, ptr) + + +/** \brief STR Exclusive (32 bit) + + This function performs a exclusive STR command for 32 bit values. + + \param [in] value Value to store + \param [in] ptr Pointer to location + \return 0 Function succeeded + \return 1 Function failed + */ +#define __STREXW(value, ptr) __strex(value, ptr) + + +/** \brief Remove the exclusive lock + + This function removes the exclusive lock which is created by LDREX. + + */ +#define __CLREX __clrex + + +/** \brief Signed Saturate + + This function saturates a signed value. + + \param [in] value Value to be saturated + \param [in] sat Bit position to saturate to (1..32) + \return Saturated value + */ +#define __SSAT __ssat + + +/** \brief Unsigned Saturate + + This function saturates an unsigned value. + + \param [in] value Value to be saturated + \param [in] sat Bit position to saturate to (0..31) + \return Saturated value + */ +#define __USAT __usat + + +/** \brief Count leading zeros + + This function counts the number of leading zeros of a data value. + + \param [in] value Value to count the leading zeros + \return number of leading zeros in value + */ +#define __CLZ __clz + +#endif /* (__CORTEX_M >= 0x03) */ + + +#elif defined ( __GNUC__ ) /*------------------ GNU Compiler ---------------------*/ +/* GNU gcc specific functions */ + +/* Define macros for porting to both thumb1 and thumb2. + * For thumb1, use low register (r0-r7), specified by constrant "l" + * Otherwise, use general registers, specified by constrant "r" */ +#if defined (__thumb__) && !defined (__thumb2__) +#define __CMSIS_GCC_OUT_REG(r) "=l" (r) +#define __CMSIS_GCC_USE_REG(r) "l" (r) +#else +#define __CMSIS_GCC_OUT_REG(r) "=r" (r) +#define __CMSIS_GCC_USE_REG(r) "r" (r) +#endif + +/** \brief No Operation + + No Operation does nothing. This instruction can be used for code alignment purposes. + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE void __NOP(void) +{ + __ASM volatile ("nop"); +} + + +/** \brief Wait For Interrupt + + Wait For Interrupt is a hint instruction that suspends execution + until one of a number of events occurs. + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE void __WFI(void) +{ + __ASM volatile ("wfi"); +} + + +/** \brief Wait For Event + + Wait For Event is a hint instruction that permits the processor to enter + a low-power state until one of a number of events occurs. + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE void __WFE(void) +{ + __ASM volatile ("wfe"); +} + + +/** \brief Send Event + + Send Event is a hint instruction. It causes an event to be signaled to the CPU. + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE void __SEV(void) +{ + __ASM volatile ("sev"); +} + + +/** \brief Instruction Synchronization Barrier + + Instruction Synchronization Barrier flushes the pipeline in the processor, + so that all instructions following the ISB are fetched from cache or + memory, after the instruction has been completed. + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE void __ISB(void) +{ + __ASM volatile ("isb"); +} + + +/** \brief Data Synchronization Barrier + + This function acts as a special kind of Data Memory Barrier. + It completes when all explicit memory accesses before this instruction complete. + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE void __DSB(void) +{ + __ASM volatile ("dsb"); +} + + +/** \brief Data Memory Barrier + + This function ensures the apparent order of the explicit memory operations before + and after the instruction, without ensuring their completion. + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE void __DMB(void) +{ + __ASM volatile ("dmb"); +} + + +/** \brief Reverse byte order (32 bit) + + This function reverses the byte order in integer value. + + \param [in] value Value to reverse + \return Reversed value + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __REV(uint32_t value) +{ +#if (__GNUC__ > 4) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 5) + return __builtin_bswap32(value); +#else + uint32_t result; + + __ASM volatile ("rev %0, %1" : __CMSIS_GCC_OUT_REG (result) : __CMSIS_GCC_USE_REG (value) ); + return(result); +#endif +} + + +/** \brief Reverse byte order (16 bit) + + This function reverses the byte order in two unsigned short values. + + \param [in] value Value to reverse + \return Reversed value + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __REV16(uint32_t value) +{ + uint32_t result; + + __ASM volatile ("rev16 %0, %1" : __CMSIS_GCC_OUT_REG (result) : __CMSIS_GCC_USE_REG (value) ); + return(result); +} + + +/** \brief Reverse byte order in signed short value + + This function reverses the byte order in a signed short value with sign extension to integer. + + \param [in] value Value to reverse + \return Reversed value + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE int32_t __REVSH(int32_t value) +{ +#if (__GNUC__ > 4) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 8) + return (short)__builtin_bswap16(value); +#else + uint32_t result; + + __ASM volatile ("revsh %0, %1" : __CMSIS_GCC_OUT_REG (result) : __CMSIS_GCC_USE_REG (value) ); + return(result); +#endif +} + + +/** \brief Rotate Right in unsigned value (32 bit) + + This function Rotate Right (immediate) provides the value of the contents of a register rotated by a variable number of bits. + + \param [in] value Value to rotate + \param [in] value Number of Bits to rotate + \return Rotated value + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __ROR(uint32_t op1, uint32_t op2) +{ + return (op1 >> op2) | (op1 << (32 - op2)); +} + + +/** \brief Breakpoint + + This function causes the processor to enter Debug state. + Debug tools can use this to investigate system state when the instruction at a particular address is reached. + + \param [in] value is ignored by the processor. + If required, a debugger can use it to store additional information about the breakpoint. + */ +#define __BKPT(value) __ASM volatile ("bkpt "#value) + + +#if (__CORTEX_M >= 0x03) + +/** \brief Reverse bit order of value + + This function reverses the bit order of the given value. + + \param [in] value Value to reverse + \return Reversed value + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __RBIT(uint32_t value) +{ + uint32_t result; + + __ASM volatile ("rbit %0, %1" : "=r" (result) : "r" (value) ); + return(result); +} + + +/** \brief LDR Exclusive (8 bit) + + This function performs a exclusive LDR command for 8 bit value. + + \param [in] ptr Pointer to data + \return value of type uint8_t at (*ptr) + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE uint8_t __LDREXB(volatile uint8_t *addr) +{ + uint32_t result; + +#if (__GNUC__ > 4) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 8) + __ASM volatile ("ldrexb %0, %1" : "=r" (result) : "Q" (*addr) ); +#else + /* Prior to GCC 4.8, "Q" will be expanded to [rx, #0] which is not + accepted by assembler. So has to use following less efficient pattern. + */ + __ASM volatile ("ldrexb %0, [%1]" : "=r" (result) : "r" (addr) : "memory" ); +#endif + return ((uint8_t) result); /* Add explicit type cast here */ +} + + +/** \brief LDR Exclusive (16 bit) + + This function performs a exclusive LDR command for 16 bit values. + + \param [in] ptr Pointer to data + \return value of type uint16_t at (*ptr) + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE uint16_t __LDREXH(volatile uint16_t *addr) +{ + uint32_t result; + +#if (__GNUC__ > 4) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 8) + __ASM volatile ("ldrexh %0, %1" : "=r" (result) : "Q" (*addr) ); +#else + /* Prior to GCC 4.8, "Q" will be expanded to [rx, #0] which is not + accepted by assembler. So has to use following less efficient pattern. + */ + __ASM volatile ("ldrexh %0, [%1]" : "=r" (result) : "r" (addr) : "memory" ); +#endif + return ((uint16_t) result); /* Add explicit type cast here */ +} + + +/** \brief LDR Exclusive (32 bit) + + This function performs a exclusive LDR command for 32 bit values. + + \param [in] ptr Pointer to data + \return value of type uint32_t at (*ptr) + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __LDREXW(volatile uint32_t *addr) +{ + uint32_t result; + + __ASM volatile ("ldrex %0, %1" : "=r" (result) : "Q" (*addr) ); + return(result); +} + + +/** \brief STR Exclusive (8 bit) + + This function performs a exclusive STR command for 8 bit values. + + \param [in] value Value to store + \param [in] ptr Pointer to location + \return 0 Function succeeded + \return 1 Function failed + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __STREXB(uint8_t value, volatile uint8_t *addr) +{ + uint32_t result; + + __ASM volatile ("strexb %0, %2, %1" : "=&r" (result), "=Q" (*addr) : "r" ((uint32_t)value) ); + return(result); +} + + +/** \brief STR Exclusive (16 bit) + + This function performs a exclusive STR command for 16 bit values. + + \param [in] value Value to store + \param [in] ptr Pointer to location + \return 0 Function succeeded + \return 1 Function failed + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __STREXH(uint16_t value, volatile uint16_t *addr) +{ + uint32_t result; + + __ASM volatile ("strexh %0, %2, %1" : "=&r" (result), "=Q" (*addr) : "r" ((uint32_t)value) ); + return(result); +} + + +/** \brief STR Exclusive (32 bit) + + This function performs a exclusive STR command for 32 bit values. + + \param [in] value Value to store + \param [in] ptr Pointer to location + \return 0 Function succeeded + \return 1 Function failed + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __STREXW(uint32_t value, volatile uint32_t *addr) +{ + uint32_t result; + + __ASM volatile ("strex %0, %2, %1" : "=&r" (result), "=Q" (*addr) : "r" (value) ); + return(result); +} + + +/** \brief Remove the exclusive lock + + This function removes the exclusive lock which is created by LDREX. + + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE void __CLREX(void) +{ + __ASM volatile ("clrex" ::: "memory"); +} + + +/** \brief Signed Saturate + + This function saturates a signed value. + + \param [in] value Value to be saturated + \param [in] sat Bit position to saturate to (1..32) + \return Saturated value + */ +#define __SSAT(ARG1,ARG2) \ +({ \ + uint32_t __RES, __ARG1 = (ARG1); \ + __ASM ("ssat %0, %1, %2" : "=r" (__RES) : "I" (ARG2), "r" (__ARG1) ); \ + __RES; \ + }) + + +/** \brief Unsigned Saturate + + This function saturates an unsigned value. + + \param [in] value Value to be saturated + \param [in] sat Bit position to saturate to (0..31) + \return Saturated value + */ +#define __USAT(ARG1,ARG2) \ +({ \ + uint32_t __RES, __ARG1 = (ARG1); \ + __ASM ("usat %0, %1, %2" : "=r" (__RES) : "I" (ARG2), "r" (__ARG1) ); \ + __RES; \ + }) + + +/** \brief Count leading zeros + + This function counts the number of leading zeros of a data value. + + \param [in] value Value to count the leading zeros + \return number of leading zeros in value + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE uint8_t __CLZ(uint32_t value) +{ + uint32_t result; + + __ASM volatile ("clz %0, %1" : "=r" (result) : "r" (value) ); + return ((uint8_t) result); /* Add explicit type cast here */ +} + +#endif /* (__CORTEX_M >= 0x03) */ + + +#elif defined ( __ICCARM__ ) /*------------------ ICC Compiler -------------------*/ +/* IAR iccarm specific functions */ +#include + + +#elif defined ( __TMS470__ ) /*---------------- TI CCS Compiler ------------------*/ +/* TI CCS specific functions */ +#include + + +#elif defined ( __TASKING__ ) /*------------------ TASKING Compiler --------------*/ +/* TASKING carm specific functions */ +/* + * The CMSIS functions have been implemented as intrinsics in the compiler. + * Please use "carm -?i" to get an up to date list of all intrinsics, + * Including the CMSIS ones. + */ + + +#elif defined ( __CSMC__ ) /*------------------ COSMIC Compiler -------------------*/ +/* Cosmic specific functions */ +#include + +#endif + +/*@}*/ /* end of group CMSIS_Core_InstructionInterface */ + +#endif /* __CORE_CMINSTR_H */ diff --git a/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_standard_peripheral/Include/gd32f10x_adc.h b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_standard_peripheral/Include/gd32f10x_adc.h new file mode 100644 index 0000000000..3a5d4c303a --- /dev/null +++ b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_standard_peripheral/Include/gd32f10x_adc.h @@ -0,0 +1,367 @@ +/*! + \file gd32f10x_adc.h + \brief definitions for the ADC + + \version 2014-12-26, V1.0.0, firmware for GD32F10x + \version 2017-06-20, V2.0.0, firmware for GD32F10x + \version 2018-07-31, V2.1.0, firmware for GD32F10x + \version 2020-09-30, V2.2.0, firmware for GD32F10x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef GD32F10x_ADC_H +#define GD32F10x_ADC_H + +#include "gd32f10x.h" + +/* ADC definitions */ +#define ADC0 ADC_BASE +#define ADC1 (ADC_BASE + 0x400U) +#define ADC2 (ADC_BASE + 0x1800U) + +/* registers definitions */ +#define ADC_STAT(adcx) REG32((adcx) + 0x00U) /*!< ADC status register */ +#define ADC_CTL0(adcx) REG32((adcx) + 0x04U) /*!< ADC control register 0 */ +#define ADC_CTL1(adcx) REG32((adcx) + 0x08U) /*!< ADC control register 1 */ +#define ADC_SAMPT0(adcx) REG32((adcx) + 0x0CU) /*!< ADC sampling time register 0 */ +#define ADC_SAMPT1(adcx) REG32((adcx) + 0x10U) /*!< ADC sampling time register 1 */ +#define ADC_IOFF0(adcx) REG32((adcx) + 0x14U) /*!< ADC inserted channel data offset register 0 */ +#define ADC_IOFF1(adcx) REG32((adcx) + 0x18U) /*!< ADC inserted channel data offset register 1 */ +#define ADC_IOFF2(adcx) REG32((adcx) + 0x1CU) /*!< ADC inserted channel data offset register 2 */ +#define ADC_IOFF3(adcx) REG32((adcx) + 0x20U) /*!< ADC inserted channel data offset register 3 */ +#define ADC_WDHT(adcx) REG32((adcx) + 0x24U) /*!< ADC watchdog high threshold register */ +#define ADC_WDLT(adcx) REG32((adcx) + 0x28U) /*!< ADC watchdog low threshold register */ +#define ADC_RSQ0(adcx) REG32((adcx) + 0x2CU) /*!< ADC regular sequence register 0 */ +#define ADC_RSQ1(adcx) REG32((adcx) + 0x30U) /*!< ADC regular sequence register 1 */ +#define ADC_RSQ2(adcx) REG32((adcx) + 0x34U) /*!< ADC regular sequence register 2 */ +#define ADC_ISQ(adcx) REG32((adcx) + 0x38U) /*!< ADC inserted sequence register */ +#define ADC_IDATA0(adcx) REG32((adcx) + 0x3CU) /*!< ADC inserted data register 0 */ +#define ADC_IDATA1(adcx) REG32((adcx) + 0x40U) /*!< ADC inserted data register 1 */ +#define ADC_IDATA2(adcx) REG32((adcx) + 0x44U) /*!< ADC inserted data register 2 */ +#define ADC_IDATA3(adcx) REG32((adcx) + 0x48U) /*!< ADC inserted data register 3 */ +#define ADC_RDATA(adcx) REG32((adcx) + 0x4CU) /*!< ADC regular data register */ + +/* bits definitions */ +/* ADC_STAT */ +#define ADC_STAT_WDE BIT(0) /*!< analog watchdog event flag */ +#define ADC_STAT_EOC BIT(1) /*!< end of conversion */ +#define ADC_STAT_EOIC BIT(2) /*!< inserted channel end of conversion */ +#define ADC_STAT_STIC BIT(3) /*!< inserted channel start flag */ +#define ADC_STAT_STRC BIT(4) /*!< regular channel start flag */ + +/* ADC_CTL0 */ +#define ADC_CTL0_WDCHSEL BITS(0,4) /*!< analog watchdog channel select bits */ +#define ADC_CTL0_EOCIE BIT(5) /*!< interrupt enable for EOC */ +#define ADC_CTL0_WDEIE BIT(6) /*!< analog watchdog interrupt enable */ +#define ADC_CTL0_EOICIE BIT(7) /*!< interrupt enable for inserted channels */ +#define ADC_CTL0_SM BIT(8) /*!< scan mode */ +#define ADC_CTL0_WDSC BIT(9) /*!< when in scan mode, analog watchdog is effective on a single channel */ +#define ADC_CTL0_ICA BIT(10) /*!< automatic inserted group conversion */ +#define ADC_CTL0_DISRC BIT(11) /*!< discontinuous mode on regular channels */ +#define ADC_CTL0_DISIC BIT(12) /*!< discontinuous mode on inserted channels */ +#define ADC_CTL0_DISNUM BITS(13,15) /*!< discontinuous mode channel count */ +#define ADC_CTL0_SYNCM BITS(16,19) /*!< sync mode selection */ +#define ADC_CTL0_IWDEN BIT(22) /*!< analog watchdog enable on inserted channels */ +#define ADC_CTL0_RWDEN BIT(23) /*!< analog watchdog enable on regular channels */ +#define ADC_CTL0_DRES BITS(24,25) /*!< ADC data resolution */ + +/* ADC_CTL1 */ +#define ADC_CTL1_ADCON BIT(0) /*!< ADC converter on */ +#define ADC_CTL1_CTN BIT(1) /*!< continuous conversion */ +#define ADC_CTL1_CLB BIT(2) /*!< ADC calibration */ +#define ADC_CTL1_RSTCLB BIT(3) /*!< reset calibration */ +#define ADC_CTL1_DMA BIT(8) /*!< direct memory access mode */ +#define ADC_CTL1_DAL BIT(11) /*!< data alignment */ +#define ADC_CTL1_ETSIC BITS(12,14) /*!< external trigger select for inserted channel */ +#define ADC_CTL1_ETEIC BIT(15) /*!< external trigger enable for inserted channel */ +#define ADC_CTL1_ETSRC BITS(17,19) /*!< external trigger select for regular channel */ +#define ADC_CTL1_ETERC BIT(20) /*!< external trigger conversion mode for inserted channels */ +#define ADC_CTL1_SWICST BIT(21) /*!< start on inserted channel */ +#define ADC_CTL1_SWRCST BIT(22) /*!< start on regular channel */ +#define ADC_CTL1_TSVREN BIT(23) /*!< channel 16 and 17 enable of ADC0 */ + +/* ADC_SAMPTx x=0..1 */ +#define ADC_SAMPTX_SPTN BITS(0,2) /*!< channel n sample time selection */ + +/* ADC_IOFFx x=0..3 */ +#define ADC_IOFFX_IOFF BITS(0,11) /*!< data offset for inserted channel x */ + +/* ADC_WDHT */ +#define ADC_WDHT_WDHT BITS(0,11) /*!< analog watchdog high threshold */ + +/* ADC_WDLT */ +#define ADC_WDLT_WDLT BITS(0,11) /*!< analog watchdog low threshold */ + +/* ADC_RSQx x=0..2 */ +#define ADC_RSQX_RSQN BITS(0,4) /*!< nth conversion in regular sequence */ +#define ADC_RSQ0_RL BITS(20,23) /*!< regular channel sequence length */ + +/* ADC_ISQ */ +#define ADC_ISQ_ISQN BITS(0,4) /*!< nth conversion in inserted sequence */ +#define ADC_ISQ_IL BITS(20,21) /*!< inserted sequence length */ + +/* ADC_IDATAx x=0..3*/ +#define ADC_IDATAX_IDATAN BITS(0,15) /*!< inserted data n */ + +/* ADC_RDATA */ +#define ADC_RDATA_RDATA BITS(0,15) /*!< regular data */ +#define ADC_RDATA_ADC1RDTR BITS(16,31) /*!< ADC1 regular channel data */ + +/* constants definitions */ +/* adc_stat register value */ +#define ADC_FLAG_WDE ADC_STAT_WDE /*!< analog watchdog event flag */ +#define ADC_FLAG_EOC ADC_STAT_EOC /*!< end of conversion */ +#define ADC_FLAG_EOIC ADC_STAT_EOIC /*!< inserted channel end of conversion */ +#define ADC_FLAG_STIC ADC_STAT_STIC /*!< inserted channel start flag */ +#define ADC_FLAG_STRC ADC_STAT_STRC /*!< regular channel start flag */ + +/* adc_ctl0 register value */ +#define CTL0_DISNUM(regval) (BITS(13,15) & ((uint32_t)(regval) << 13)) /*!< write value to ADC_CTL0_DISNUM bit field */ + +/* scan mode */ +#define ADC_SCAN_MODE ADC_CTL0_SM /*!< scan mode */ + +/* inserted channel group convert automatically */ +#define ADC_INSERTED_CHANNEL_AUTO ADC_CTL0_ICA /*!< inserted channel group convert automatically */ + +/* ADC sync mode */ +#define CTL0_SYNCM(regval) (BITS(16,19) & ((uint32_t)(regval) << 16)) /*!< write value to ADC_CTL0_SYNCM bit field */ +#define ADC_MODE_FREE CTL0_SYNCM(0) /*!< all the ADCs work independently */ +#define ADC_DAUL_REGULAL_PARALLEL_INSERTED_PARALLEL CTL0_SYNCM(1) /*!< ADC0 and ADC1 work in combined regular parallel + inserted parallel mode */ +#define ADC_DAUL_REGULAL_PARALLEL_INSERTED_ROTATION CTL0_SYNCM(2) /*!< ADC0 and ADC1 work in combined regular parallel + trigger rotation mode */ +#define ADC_DAUL_INSERTED_PARALLEL_REGULAL_FOLLOWUP_FAST CTL0_SYNCM(3) /*!< ADC0 and ADC1 work in combined inserted parallel + follow-up fast mode */ +#define ADC_DAUL_INSERTED_PARALLEL_REGULAL_FOLLOWUP_SLOW CTL0_SYNCM(4) /*!< ADC0 and ADC1 work in combined inserted parallel + follow-up slow mode */ +#define ADC_DAUL_INSERTED_PARALLEL CTL0_SYNCM(5) /*!< ADC0 and ADC1 work in inserted parallel mode only */ +#define ADC_DAUL_REGULAL_PARALLEL CTL0_SYNCM(6) /*!< ADC0 and ADC1 work in regular parallel mode only */ +#define ADC_DAUL_REGULAL_FOLLOWUP_FAST CTL0_SYNCM(7) /*!< ADC0 and ADC1 work in follow-up fast mode only */ +#define ADC_DAUL_REGULAL_FOLLOWUP_SLOW CTL0_SYNCM(8) /*!< ADC0 and ADC1 work in follow-up slow mode only */ +#define ADC_DAUL_INSERTED_TRIGGER_ROTATION CTL0_SYNCM(9) /*!< ADC0 and ADC1 work in trigger rotation mode only */ + +/* adc_ctl1 register value */ +#define ADC_DATAALIGN_RIGHT ((uint32_t)0x00000000U) /*!< LSB alignment */ +#define ADC_DATAALIGN_LEFT ADC_CTL1_DAL /*!< MSB alignment */ + +/* continuous mode */ +#define ADC_CONTINUOUS_MODE ADC_CTL1_CTN /*!< continuous mode */ + +/* external trigger select for regular channel */ +#define CTL1_ETSRC(regval) (BITS(17,19) & ((uint32_t)(regval) << 17)) /*!< write value to ADC_CTL1_ETSRC bit field */ +/* for ADC0 and ADC1 regular channel */ +#define ADC0_1_EXTTRIG_REGULAR_T0_CH0 CTL1_ETSRC(0) /*!< TIMER0 CH0 event select */ +#define ADC0_1_EXTTRIG_REGULAR_T0_CH1 CTL1_ETSRC(1) /*!< TIMER0 CH1 event select */ +#define ADC0_1_EXTTRIG_REGULAR_T0_CH2 CTL1_ETSRC(2) /*!< TIMER0 CH2 event select */ +#define ADC0_1_EXTTRIG_REGULAR_T1_CH1 CTL1_ETSRC(3) /*!< TIMER1 CH1 event select */ +#define ADC0_1_EXTTRIG_REGULAR_T2_TRGO CTL1_ETSRC(4) /*!< TIMER2 TRGO event select */ +#define ADC0_1_EXTTRIG_REGULAR_T3_CH3 CTL1_ETSRC(5) /*!< TIMER3 CH3 event select */ +#define ADC0_1_EXTTRIG_REGULAR_T7_TRGO CTL1_ETSRC(6) /*!< TIMER7 TRGO event select */ +#define ADC0_1_EXTTRIG_REGULAR_EXTI_11 CTL1_ETSRC(6) /*!< external interrupt line 11 */ +#define ADC0_1_2_EXTTRIG_REGULAR_NONE CTL1_ETSRC(7) /*!< software trigger */ +/* for ADC2 regular channel */ +#define ADC2_EXTTRIG_REGULAR_T2_CH0 CTL1_ETSRC(0) /*!< TIMER2 CH0 event select */ +#define ADC2_EXTTRIG_REGULAR_T1_CH2 CTL1_ETSRC(1) /*!< TIMER1 CH2 event select */ +#define ADC2_EXTTRIG_REGULAR_T0_CH2 CTL1_ETSRC(2) /*!< TIMER0 CH2 event select */ +#define ADC2_EXTTRIG_REGULAR_T7_CH0 CTL1_ETSRC(3) /*!< TIMER7 CH0 event select */ +#define ADC2_EXTTRIG_REGULAR_T7_TRGO CTL1_ETSRC(4) /*!< TIMER7 TRGO event select */ +#define ADC2_EXTTRIG_REGULAR_T4_CH0 CTL1_ETSRC(5) /*!< TIMER4 CH0 event select */ +#define ADC2_EXTTRIG_REGULAR_T4_CH2 CTL1_ETSRC(6) /*!< TIMER4 CH2 event select */ + +/* external trigger mode for inserted channel */ +#define CTL1_ETSIC(regval) (BITS(12,14) & ((uint32_t)(regval) << 12)) /*!< write value to ADC_CTL1_ETSIC bit field */ +/* for ADC0 and ADC1 inserted channel */ +#define ADC0_1_EXTTRIG_INSERTED_T0_TRGO CTL1_ETSIC(0) /*!< TIMER0 TRGO event select */ +#define ADC0_1_EXTTRIG_INSERTED_T0_CH3 CTL1_ETSIC(1) /*!< TIMER0 CH3 event select */ +#define ADC0_1_EXTTRIG_INSERTED_T1_TRGO CTL1_ETSIC(2) /*!< TIMER1 TRGO event select */ +#define ADC0_1_EXTTRIG_INSERTED_T1_CH0 CTL1_ETSIC(3) /*!< TIMER1 CH0 event select */ +#define ADC0_1_EXTTRIG_INSERTED_T2_CH3 CTL1_ETSIC(4) /*!< TIMER2 CH3 event select */ +#define ADC0_1_EXTTRIG_INSERTED_T3_TRGO CTL1_ETSIC(5) /*!< TIMER3 TRGO event select */ +#define ADC0_1_EXTTRIG_INSERTED_EXTI_15 CTL1_ETSIC(6) /*!< external interrupt line 15 */ +#define ADC0_1_EXTTRIG_INSERTED_T7_CH3 CTL1_ETSIC(6) /*!< TIMER7 CH3 event select */ +#define ADC0_1_2_EXTTRIG_INSERTED_NONE CTL1_ETSIC(7) /*!< software trigger */ +/* for ADC2 inserted channel */ +#define ADC2_EXTTRIG_INSERTED_T0_TRGO CTL1_ETSIC(0) /*!< TIMER0 TRGO event select */ +#define ADC2_EXTTRIG_INSERTED_T0_CH3 CTL1_ETSIC(1) /*!< TIMER0 CH3 event select */ +#define ADC2_EXTTRIG_INSERTED_T3_CH2 CTL1_ETSIC(2) /*!< TIMER3 CH2 event select */ +#define ADC2_EXTTRIG_INSERTED_T7_CH1 CTL1_ETSIC(3) /*!< TIMER7 CH1 event select */ +#define ADC2_EXTTRIG_INSERTED_T7_CH3 CTL1_ETSIC(4) /*!< TIMER7 CH3 event select */ +#define ADC2_EXTTRIG_INSERTED_T4_TRGO CTL1_ETSIC(5) /*!< TIMER4 TRGO event select */ +#define ADC2_EXTTRIG_INSERTED_T4_CH3 CTL1_ETSIC(6) /*!< TIMER4 CH3 event select */ + +/* adc_samptx register value */ +#define SAMPTX_SPT(regval) (BITS(0,2) & ((uint32_t)(regval) << 0)) /*!< write value to ADC_SAMPTX_SPT bit field */ +#define ADC_SAMPLETIME_1POINT5 SAMPTX_SPT(0) /*!< 1.5 sampling cycles */ +#define ADC_SAMPLETIME_7POINT5 SAMPTX_SPT(1) /*!< 7.5 sampling cycles */ +#define ADC_SAMPLETIME_13POINT5 SAMPTX_SPT(2) /*!< 13.5 sampling cycles */ +#define ADC_SAMPLETIME_28POINT5 SAMPTX_SPT(3) /*!< 28.5 sampling cycles */ +#define ADC_SAMPLETIME_41POINT5 SAMPTX_SPT(4) /*!< 41.5 sampling cycles */ +#define ADC_SAMPLETIME_55POINT5 SAMPTX_SPT(5) /*!< 55.5 sampling cycles */ +#define ADC_SAMPLETIME_71POINT5 SAMPTX_SPT(6) /*!< 71.5 sampling cycles */ +#define ADC_SAMPLETIME_239POINT5 SAMPTX_SPT(7) /*!< 239.5 sampling cycles */ + +/* adc_ioffx register value */ +#define IOFFX_IOFF(regval) (BITS(0,11) & ((uint32_t)(regval) << 0)) /*!< write value to ADC_IOFFX_IOFF bit field */ + +/* adc_wdht register value */ +#define WDHT_WDHT(regval) (BITS(0,11) & ((uint32_t)(regval) << 0)) /*!< write value to ADC_WDHT_WDHT bit field */ + +/* adc_wdlt register value */ +#define WDLT_WDLT(regval) (BITS(0,11) & ((uint32_t)(regval) << 0)) /*!< write value to ADC_WDLT_WDLT bit field */ + +/* adc_rsqx register value */ +#define RSQ0_RL(regval) (BITS(20,23) & ((uint32_t)(regval) << 20)) /*!< write value to ADC_RSQ0_RL bit field */ + +/* adc_isq register value */ +#define ISQ_IL(regval) (BITS(20,21) & ((uint32_t)(regval) << 20)) /*!< write value to ADC_ISQ_IL bit field */ + +/* ADC channel group definitions */ +#define ADC_REGULAR_CHANNEL ((uint8_t)0x01U) /*!< adc regular channel group */ +#define ADC_INSERTED_CHANNEL ((uint8_t)0x02U) /*!< adc inserted channel group */ +#define ADC_REGULAR_INSERTED_CHANNEL ((uint8_t)0x03U) /*!< both regular and inserted channel group */ + +#define ADC_CHANNEL_DISCON_DISABLE ((uint8_t)0x04U) /*!< disable discontinuous mode of regular & inserted channel */ + +/* ADC inserted channel definitions */ +#define ADC_INSERTED_CHANNEL_0 ((uint8_t)0x00U) /*!< adc inserted channel 0 */ +#define ADC_INSERTED_CHANNEL_1 ((uint8_t)0x01U) /*!< adc inserted channel 1 */ +#define ADC_INSERTED_CHANNEL_2 ((uint8_t)0x02U) /*!< adc inserted channel 2 */ +#define ADC_INSERTED_CHANNEL_3 ((uint8_t)0x03U) /*!< adc inserted channel 3 */ + +/* ADC channel definitions */ +#define ADC_CHANNEL_0 ((uint8_t)0x00U) /*!< ADC channel 0 */ +#define ADC_CHANNEL_1 ((uint8_t)0x01U) /*!< ADC channel 1 */ +#define ADC_CHANNEL_2 ((uint8_t)0x02U) /*!< ADC channel 2 */ +#define ADC_CHANNEL_3 ((uint8_t)0x03U) /*!< ADC channel 3 */ +#define ADC_CHANNEL_4 ((uint8_t)0x04U) /*!< ADC channel 4 */ +#define ADC_CHANNEL_5 ((uint8_t)0x05U) /*!< ADC channel 5 */ +#define ADC_CHANNEL_6 ((uint8_t)0x06U) /*!< ADC channel 6 */ +#define ADC_CHANNEL_7 ((uint8_t)0x07U) /*!< ADC channel 7 */ +#define ADC_CHANNEL_8 ((uint8_t)0x08U) /*!< ADC channel 8 */ +#define ADC_CHANNEL_9 ((uint8_t)0x09U) /*!< ADC channel 9 */ +#define ADC_CHANNEL_10 ((uint8_t)0x0AU) /*!< ADC channel 10 */ +#define ADC_CHANNEL_11 ((uint8_t)0x0BU) /*!< ADC channel 11 */ +#define ADC_CHANNEL_12 ((uint8_t)0x0CU) /*!< ADC channel 12 */ +#define ADC_CHANNEL_13 ((uint8_t)0x0DU) /*!< ADC channel 13 */ +#define ADC_CHANNEL_14 ((uint8_t)0x0EU) /*!< ADC channel 14 */ +#define ADC_CHANNEL_15 ((uint8_t)0x0FU) /*!< ADC channel 15 */ +#define ADC_CHANNEL_16 ((uint8_t)0x10U) /*!< ADC channel 16 */ +#define ADC_CHANNEL_17 ((uint8_t)0x11U) /*!< ADC channel 17 */ + +/* ADC interrupt */ +#define ADC_INT_WDE ADC_STAT_WDE /*!< analog watchdog event interrupt */ +#define ADC_INT_EOC ADC_STAT_EOC /*!< end of group conversion interrupt */ +#define ADC_INT_EOIC ADC_STAT_EOIC /*!< end of inserted group conversion interrupt */ + +/* ADC interrupt flag */ +#define ADC_INT_FLAG_WDE ADC_STAT_WDE /*!< analog watchdog event interrupt flag */ +#define ADC_INT_FLAG_EOC ADC_STAT_EOC /*!< end of group conversion interrupt flag */ +#define ADC_INT_FLAG_EOIC ADC_STAT_EOIC /*!< end of inserted group conversion interrupt flag */ + +/* function declarations */ +/* initialization config */ +/* reset ADC */ +void adc_deinit(uint32_t adc_periph); +/* configure the ADC sync mode */ +void adc_mode_config(uint32_t mode); +/* enable or disable ADC special function */ +void adc_special_function_config(uint32_t adc_periph, uint32_t function, ControlStatus newvalue); +/* configure ADC data alignment */ +void adc_data_alignment_config(uint32_t adc_periph, uint32_t data_alignment); +/* enable ADC interface */ +void adc_enable(uint32_t adc_periph); +/* disable ADC interface */ +void adc_disable(uint32_t adc_periph); +/* ADC calibration and reset calibration */ +void adc_calibration_enable(uint32_t adc_periph); +/* enable the temperature sensor and Vrefint channel */ +void adc_tempsensor_vrefint_enable(void); +/* disable the temperature sensor and Vrefint channel */ +void adc_tempsensor_vrefint_disable(void); + +/* DMA config */ +/* enable DMA request */ +void adc_dma_mode_enable(uint32_t adc_periph); +/* disable DMA request */ +void adc_dma_mode_disable(uint32_t adc_periph); + +/* regular group and inserted group config */ +/* configure ADC discontinuous mode */ +void adc_discontinuous_mode_config(uint32_t adc_periph, uint8_t adc_channel_group, uint8_t length); + +/* configure the length of regular channel group or inserted channel group */ +void adc_channel_length_config(uint32_t adc_periph, uint8_t adc_channel_group, uint32_t length); +/* configure ADC regular channel */ +void adc_regular_channel_config(uint32_t adc_periph, uint8_t rank, uint8_t adc_channel, uint32_t sample_time); +/* configure ADC inserted channel */ +void adc_inserted_channel_config(uint32_t adc_periph, uint8_t rank, uint8_t adc_channel, uint32_t sample_time); +/* configure ADC inserted channel offset */ +void adc_inserted_channel_offset_config(uint32_t adc_periph, uint8_t inserted_channel, uint16_t offset); + +/* configure ADC external trigger source */ +void adc_external_trigger_source_config(uint32_t adc_periph, uint8_t adc_channel_group, uint32_t external_trigger_source); +/* configure ADC external trigger */ +void adc_external_trigger_config(uint32_t adc_periph, uint8_t adc_channel_group, ControlStatus newvalue); +/* enable ADC software trigger */ +void adc_software_trigger_enable(uint32_t adc_periph, uint8_t adc_channel_group); + +/* get channel data */ +/* read ADC regular group data register */ +uint16_t adc_regular_data_read(uint32_t adc_periph); +/* read ADC inserted group data register */ +uint16_t adc_inserted_data_read(uint32_t adc_periph, uint8_t inserted_channel); +/* read the last ADC0 and ADC1 conversion result data in sync mode */ +uint32_t adc_sync_mode_convert_value_read(void); + +/* watchdog config */ +/* configure ADC analog watchdog single channel */ +void adc_watchdog_single_channel_enable(uint32_t adc_periph, uint8_t adc_channel); +/* configure ADC analog watchdog group channel */ +void adc_watchdog_group_channel_enable(uint32_t adc_periph, uint8_t adc_channel_group); +/* disable ADC analog watchdog */ +void adc_watchdog_disable(uint32_t adc_periph); +/* configure ADC analog watchdog threshold */ +void adc_watchdog_threshold_config(uint32_t adc_periph, uint16_t low_threshold, uint16_t high_threshold); + +/* interrupt & flag functions */ +/* get the ADC flag bits */ +FlagStatus adc_flag_get(uint32_t adc_periph, uint32_t adc_flag); +/* clear the ADC flag bits */ +void adc_flag_clear(uint32_t adc_periph, uint32_t adc_flag); +/* get the bit state of ADCx software start conversion */ +FlagStatus adc_regular_software_startconv_flag_get(uint32_t adc_periph); +/* get the bit state of ADCx software inserted channel start conversion */ +FlagStatus adc_inserted_software_startconv_flag_get(uint32_t adc_periph); +/* get the ADC interrupt bits */ +FlagStatus adc_interrupt_flag_get(uint32_t adc_periph, uint32_t adc_interrupt); +/* clear the ADC flag */ +void adc_interrupt_flag_clear(uint32_t adc_periph, uint32_t adc_interrupt); +/* enable ADC interrupt */ +void adc_interrupt_enable(uint32_t adc_periph, uint32_t adc_interrupt); +/* disable ADC interrupt */ +void adc_interrupt_disable(uint32_t adc_periph, uint32_t adc_interrupt); + +#endif /* GD32F10x_ADC_H */ diff --git a/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_standard_peripheral/Include/gd32f10x_bkp.h b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_standard_peripheral/Include/gd32f10x_bkp.h new file mode 100644 index 0000000000..2963c35e9e --- /dev/null +++ b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_standard_peripheral/Include/gd32f10x_bkp.h @@ -0,0 +1,229 @@ +/*! + \file gd32f10x_bkp.h + \brief definitions for the BKP + + \version 2014-12-26, V1.0.0, firmware for GD32F10x + \version 2017-06-20, V2.0.0, firmware for GD32F10x + \version 2018-07-31, V2.1.0, firmware for GD32F10x + \version 2020-09-30, V2.2.0, firmware for GD32F10x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef GD32F10X_BKP_H +#define GD32F10X_BKP_H + +#include "gd32f10x.h" + +/* BKP definitions */ +#define BKP BKP_BASE /*!< BKP base address */ + +/* registers definitions */ +#define BKP_DATA0 REG16((BKP) + 0x04U) /*!< BKP data register 0 */ +#define BKP_DATA1 REG16((BKP) + 0x08U) /*!< BKP data register 1 */ +#define BKP_DATA2 REG16((BKP) + 0x0CU) /*!< BKP data register 2 */ +#define BKP_DATA3 REG16((BKP) + 0x10U) /*!< BKP data register 3 */ +#define BKP_DATA4 REG16((BKP) + 0x14U) /*!< BKP data register 4 */ +#define BKP_DATA5 REG16((BKP) + 0x18U) /*!< BKP data register 5 */ +#define BKP_DATA6 REG16((BKP) + 0x1CU) /*!< BKP data register 6 */ +#define BKP_DATA7 REG16((BKP) + 0x20U) /*!< BKP data register 7 */ +#define BKP_DATA8 REG16((BKP) + 0x24U) /*!< BKP data register 8 */ +#define BKP_DATA9 REG16((BKP) + 0x28U) /*!< BKP data register 9 */ +#define BKP_DATA10 REG16((BKP) + 0x40U) /*!< BKP data register 10 */ +#define BKP_DATA11 REG16((BKP) + 0x44U) /*!< BKP data register 11 */ +#define BKP_DATA12 REG16((BKP) + 0x48U) /*!< BKP data register 12 */ +#define BKP_DATA13 REG16((BKP) + 0x4CU) /*!< BKP data register 13 */ +#define BKP_DATA14 REG16((BKP) + 0x50U) /*!< BKP data register 14 */ +#define BKP_DATA15 REG16((BKP) + 0x54U) /*!< BKP data register 15 */ +#define BKP_DATA16 REG16((BKP) + 0x58U) /*!< BKP data register 16 */ +#define BKP_DATA17 REG16((BKP) + 0x5CU) /*!< BKP data register 17 */ +#define BKP_DATA18 REG16((BKP) + 0x60U) /*!< BKP data register 18 */ +#define BKP_DATA19 REG16((BKP) + 0x64U) /*!< BKP data register 19 */ +#define BKP_DATA20 REG16((BKP) + 0x68U) /*!< BKP data register 20 */ +#define BKP_DATA21 REG16((BKP) + 0x6CU) /*!< BKP data register 21 */ +#define BKP_DATA22 REG16((BKP) + 0x70U) /*!< BKP data register 22 */ +#define BKP_DATA23 REG16((BKP) + 0x74U) /*!< BKP data register 23 */ +#define BKP_DATA24 REG16((BKP) + 0x78U) /*!< BKP data register 24 */ +#define BKP_DATA25 REG16((BKP) + 0x7CU) /*!< BKP data register 25 */ +#define BKP_DATA26 REG16((BKP) + 0x80U) /*!< BKP data register 26 */ +#define BKP_DATA27 REG16((BKP) + 0x84U) /*!< BKP data register 27 */ +#define BKP_DATA28 REG16((BKP) + 0x88U) /*!< BKP data register 28 */ +#define BKP_DATA29 REG16((BKP) + 0x8CU) /*!< BKP data register 29 */ +#define BKP_DATA30 REG16((BKP) + 0x90U) /*!< BKP data register 30 */ +#define BKP_DATA31 REG16((BKP) + 0x94U) /*!< BKP data register 31 */ +#define BKP_DATA32 REG16((BKP) + 0x98U) /*!< BKP data register 32 */ +#define BKP_DATA33 REG16((BKP) + 0x9CU) /*!< BKP data register 33 */ +#define BKP_DATA34 REG16((BKP) + 0xA0U) /*!< BKP data register 34 */ +#define BKP_DATA35 REG16((BKP) + 0xA4U) /*!< BKP data register 35 */ +#define BKP_DATA36 REG16((BKP) + 0xA8U) /*!< BKP data register 36 */ +#define BKP_DATA37 REG16((BKP) + 0xACU) /*!< BKP data register 37 */ +#define BKP_DATA38 REG16((BKP) + 0xB0U) /*!< BKP data register 38 */ +#define BKP_DATA39 REG16((BKP) + 0xB4U) /*!< BKP data register 39 */ +#define BKP_DATA40 REG16((BKP) + 0xB8U) /*!< BKP data register 40 */ +#define BKP_DATA41 REG16((BKP) + 0xBCU) /*!< BKP data register 41 */ +#define BKP_OCTL REG16((BKP) + 0x2CU) /*!< RTC signal output control register */ +#define BKP_TPCTL REG16((BKP) + 0x30U) /*!< tamper pin control register */ +#define BKP_TPCS REG16((BKP) + 0x34U) /*!< tamper control and status register */ + +/* bits definitions */ +/* BKP_DATA */ +#define BKP_DATA BITS(0,15) /*!< backup data */ + +/* BKP_OCTL */ +#define BKP_OCTL_RCCV BITS(0,6) /*!< RTC clock calibration value */ +#define BKP_OCTL_COEN BIT(7) /*!< RTC clock calibration output enable */ +#define BKP_OCTL_ASOEN BIT(8) /*!< RTC alarm or second signal output enable */ +#define BKP_OCTL_ROSEL BIT(9) /*!< RTC output selection */ + +/* BKP_TPCTL */ +#define BKP_TPCTL_TPEN BIT(0) /*!< tamper detection enable */ +#define BKP_TPCTL_TPAL BIT(1) /*!< tamper pin active level */ + +/* BKP_TPCS */ +#define BKP_TPCS_TER BIT(0) /*!< tamper event reset */ +#define BKP_TPCS_TIR BIT(1) /*!< tamper interrupt reset */ +#define BKP_TPCS_TPIE BIT(2) /*!< tamper interrupt enable */ +#define BKP_TPCS_TEF BIT(8) /*!< tamper event flag */ +#define BKP_TPCS_TIF BIT(9) /*!< tamper interrupt flag */ + +/* constants definitions */ +/* BKP data register number */ +typedef enum +{ + BKP_DATA_0 = 1, /*!< BKP data register 0 */ + BKP_DATA_1, /*!< BKP data register 1 */ + BKP_DATA_2, /*!< BKP data register 2 */ + BKP_DATA_3, /*!< BKP data register 3 */ + BKP_DATA_4, /*!< BKP data register 4 */ + BKP_DATA_5, /*!< BKP data register 5 */ + BKP_DATA_6, /*!< BKP data register 6 */ + BKP_DATA_7, /*!< BKP data register 7 */ + BKP_DATA_8, /*!< BKP data register 8 */ + BKP_DATA_9, /*!< BKP data register 9 */ + BKP_DATA_10, /*!< BKP data register 10 */ + BKP_DATA_11, /*!< BKP data register 11 */ + BKP_DATA_12, /*!< BKP data register 12 */ + BKP_DATA_13, /*!< BKP data register 13 */ + BKP_DATA_14, /*!< BKP data register 14 */ + BKP_DATA_15, /*!< BKP data register 15 */ + BKP_DATA_16, /*!< BKP data register 16 */ + BKP_DATA_17, /*!< BKP data register 17 */ + BKP_DATA_18, /*!< BKP data register 18 */ + BKP_DATA_19, /*!< BKP data register 19 */ + BKP_DATA_20, /*!< BKP data register 20 */ + BKP_DATA_21, /*!< BKP data register 21 */ + BKP_DATA_22, /*!< BKP data register 22 */ + BKP_DATA_23, /*!< BKP data register 23 */ + BKP_DATA_24, /*!< BKP data register 24 */ + BKP_DATA_25, /*!< BKP data register 25 */ + BKP_DATA_26, /*!< BKP data register 26 */ + BKP_DATA_27, /*!< BKP data register 27 */ + BKP_DATA_28, /*!< BKP data register 28 */ + BKP_DATA_29, /*!< BKP data register 29 */ + BKP_DATA_30, /*!< BKP data register 30 */ + BKP_DATA_31, /*!< BKP data register 31 */ + BKP_DATA_32, /*!< BKP data register 32 */ + BKP_DATA_33, /*!< BKP data register 33 */ + BKP_DATA_34, /*!< BKP data register 34 */ + BKP_DATA_35, /*!< BKP data register 35 */ + BKP_DATA_36, /*!< BKP data register 36 */ + BKP_DATA_37, /*!< BKP data register 37 */ + BKP_DATA_38, /*!< BKP data register 38 */ + BKP_DATA_39, /*!< BKP data register 39 */ + BKP_DATA_40, /*!< BKP data register 40 */ + BKP_DATA_41, /*!< BKP data register 41 */ +}bkp_data_register_enum; + +/* BKP register */ +#define BKP_DATA0_9(number) REG16((BKP) + 0x04U + (number) * 0x04U) +#define BKP_DATA10_41(number) REG16((BKP) + 0x40U + ((number)-10U) * 0x04U) + +/* get data of BKP data register */ +#define BKP_DATA_GET(regval) GET_BITS((uint32_t)(regval), 0, 15) + +/* RTC clock calibration value */ +#define OCTL_RCCV(regval) (BITS(0,6) & ((uint32_t)(regval) << 0)) + +/* RTC output selection */ +#define RTC_OUTPUT_ALARM_PULSE ((uint16_t)0x0000U) /*!< RTC alarm pulse is selected as the RTC output */ +#define RTC_OUTPUT_SECOND_PULSE ((uint16_t)0x0200U) /*!< RTC second pulse is selected as the RTC output */ + +/* tamper pin active level */ +#define TAMPER_PIN_ACTIVE_HIGH ((uint16_t)0x0000U) /*!< the tamper pin is active high */ +#define TAMPER_PIN_ACTIVE_LOW ((uint16_t)0x0002U) /*!< the tamper pin is active low */ + +/* tamper flag */ +#define BKP_FLAG_TAMPER BKP_TPCS_TEF /*!< tamper event flag */ + +/* tamper interrupt flag */ +#define BKP_INT_FLAG_TAMPER BKP_TPCS_TIF /*!< tamper interrupt flag */ +/* function declarations */ +/* reset BKP registers */ +void bkp_deinit(void); +/* write BKP data register */ +void bkp_data_write(bkp_data_register_enum register_number, uint16_t data); +/* read BKP data register */ +uint16_t bkp_data_read(bkp_data_register_enum register_number); + +/* RTC related functions */ +/* enable RTC clock calibration output */ +void bkp_rtc_calibration_output_enable(void); +/* disable RTC clock calibration output */ +void bkp_rtc_calibration_output_disable(void); +/* enable RTC alarm or second signal output */ +void bkp_rtc_signal_output_enable(void); +/* disable RTC alarm or second signal output */ +void bkp_rtc_signal_output_disable(void); +/* select RTC output */ +void bkp_rtc_output_select(uint16_t outputsel); +/* set RTC clock calibration value */ +void bkp_rtc_calibration_value_set(uint8_t value); + +/* tamper pin related functions */ +/* enable tamper pin detection */ +void bkp_tamper_detection_enable(void); +/* disable tamper pin detection */ +void bkp_tamper_detection_disable(void); +/* set tamper pin active level */ +void bkp_tamper_active_level_set(uint16_t level); + +/* interrupt & flag functions */ +/* enable tamper interrupt */ +void bkp_interrupt_enable(void); +/* disable tamper interrupt */ +void bkp_interrupt_disable(void); +/* get tamper flag state */ +FlagStatus bkp_flag_get(void); +/* clear tamper flag state */ +void bkp_flag_clear(void); +/* get tamper interrupt flag state */ +FlagStatus bkp_interrupt_flag_get(void); +/* clear tamper interrupt flag state */ +void bkp_interrupt_flag_clear(void); + +#endif /* GD32F10X_BKP_H */ diff --git a/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_standard_peripheral/Include/gd32f10x_can.h b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_standard_peripheral/Include/gd32f10x_can.h new file mode 100644 index 0000000000..29b14e7451 --- /dev/null +++ b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_standard_peripheral/Include/gd32f10x_can.h @@ -0,0 +1,754 @@ +/*! + \file gd32f10x_can.h + \brief definitions for the CAN + + \version 2014-12-26, V1.0.0, firmware for GD32F10x + \version 2017-06-20, V2.0.0, firmware for GD32F10x + \version 2018-07-31, V2.1.0, firmware for GD32F10x + \version 2019-11-27, V2.1.1, firmware for GD32F10x + \version 2020-09-30, V2.2.0, firmware for GD32F10x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef GD32F10x_CAN_H +#define GD32F10x_CAN_H + +#include "gd32f10x.h" + +/* CAN definitions */ +#define CAN0 CAN_BASE /*!< CAN0 base address */ +#define CAN1 (CAN0 + 0x00000400U) /*!< CAN1 base address */ + +/* registers definitions */ +#define CAN_CTL(canx) REG32((canx) + 0x00U) /*!< CAN control register */ +#define CAN_STAT(canx) REG32((canx) + 0x04U) /*!< CAN status register */ +#define CAN_TSTAT(canx) REG32((canx) + 0x08U) /*!< CAN transmit status register*/ +#define CAN_RFIFO0(canx) REG32((canx) + 0x0CU) /*!< CAN receive FIFO0 register */ +#define CAN_RFIFO1(canx) REG32((canx) + 0x10U) /*!< CAN receive FIFO1 register */ +#define CAN_INTEN(canx) REG32((canx) + 0x14U) /*!< CAN interrupt enable register */ +#define CAN_ERR(canx) REG32((canx) + 0x18U) /*!< CAN error register */ +#define CAN_BT(canx) REG32((canx) + 0x1CU) /*!< CAN bit timing register */ +#define CAN_TMI0(canx) REG32((canx) + 0x180U) /*!< CAN transmit mailbox0 identifier register */ +#define CAN_TMP0(canx) REG32((canx) + 0x184U) /*!< CAN transmit mailbox0 property register */ +#define CAN_TMDATA00(canx) REG32((canx) + 0x188U) /*!< CAN transmit mailbox0 data0 register */ +#define CAN_TMDATA10(canx) REG32((canx) + 0x18CU) /*!< CAN transmit mailbox0 data1 register */ +#define CAN_TMI1(canx) REG32((canx) + 0x190U) /*!< CAN transmit mailbox1 identifier register */ +#define CAN_TMP1(canx) REG32((canx) + 0x194U) /*!< CAN transmit mailbox1 property register */ +#define CAN_TMDATA01(canx) REG32((canx) + 0x198U) /*!< CAN transmit mailbox1 data0 register */ +#define CAN_TMDATA11(canx) REG32((canx) + 0x19CU) /*!< CAN transmit mailbox1 data1 register */ +#define CAN_TMI2(canx) REG32((canx) + 0x1A0U) /*!< CAN transmit mailbox2 identifier register */ +#define CAN_TMP2(canx) REG32((canx) + 0x1A4U) /*!< CAN transmit mailbox2 property register */ +#define CAN_TMDATA02(canx) REG32((canx) + 0x1A8U) /*!< CAN transmit mailbox2 data0 register */ +#define CAN_TMDATA12(canx) REG32((canx) + 0x1ACU) /*!< CAN transmit mailbox2 data1 register */ +#define CAN_RFIFOMI0(canx) REG32((canx) + 0x1B0U) /*!< CAN receive FIFO0 mailbox identifier register */ +#define CAN_RFIFOMP0(canx) REG32((canx) + 0x1B4U) /*!< CAN receive FIFO0 mailbox property register */ +#define CAN_RFIFOMDATA00(canx) REG32((canx) + 0x1B8U) /*!< CAN receive FIFO0 mailbox data0 register */ +#define CAN_RFIFOMDATA10(canx) REG32((canx) + 0x1BCU) /*!< CAN receive FIFO0 mailbox data1 register */ +#define CAN_RFIFOMI1(canx) REG32((canx) + 0x1C0U) /*!< CAN receive FIFO1 mailbox identifier register */ +#define CAN_RFIFOMP1(canx) REG32((canx) + 0x1C4U) /*!< CAN receive FIFO1 mailbox property register */ +#define CAN_RFIFOMDATA01(canx) REG32((canx) + 0x1C8U) /*!< CAN receive FIFO1 mailbox data0 register */ +#define CAN_RFIFOMDATA11(canx) REG32((canx) + 0x1CCU) /*!< CAN receive FIFO1 mailbox data1 register */ +#define CAN_FCTL(canx) REG32((canx) + 0x200U) /*!< CAN filter control register */ +#define CAN_FMCFG(canx) REG32((canx) + 0x204U) /*!< CAN filter mode register */ +#define CAN_FSCFG(canx) REG32((canx) + 0x20CU) /*!< CAN filter scale register */ +#define CAN_FAFIFO(canx) REG32((canx) + 0x214U) /*!< CAN filter associated FIFO register */ +#define CAN_FW(canx) REG32((canx) + 0x21CU) /*!< CAN filter working register */ +#define CAN_F0DATA0(canx) REG32((canx) + 0x240U) /*!< CAN filter 0 data 0 register */ +#define CAN_F1DATA0(canx) REG32((canx) + 0x248U) /*!< CAN filter 1 data 0 register */ +#define CAN_F2DATA0(canx) REG32((canx) + 0x250U) /*!< CAN filter 2 data 0 register */ +#define CAN_F3DATA0(canx) REG32((canx) + 0x258U) /*!< CAN filter 3 data 0 register */ +#define CAN_F4DATA0(canx) REG32((canx) + 0x260U) /*!< CAN filter 4 data 0 register */ +#define CAN_F5DATA0(canx) REG32((canx) + 0x268U) /*!< CAN filter 5 data 0 register */ +#define CAN_F6DATA0(canx) REG32((canx) + 0x270U) /*!< CAN filter 6 data 0 register */ +#define CAN_F7DATA0(canx) REG32((canx) + 0x278U) /*!< CAN filter 7 data 0 register */ +#define CAN_F8DATA0(canx) REG32((canx) + 0x280U) /*!< CAN filter 8 data 0 register */ +#define CAN_F9DATA0(canx) REG32((canx) + 0x288U) /*!< CAN filter 9 data 0 register */ +#define CAN_F10DATA0(canx) REG32((canx) + 0x290U) /*!< CAN filter 10 data 0 register */ +#define CAN_F11DATA0(canx) REG32((canx) + 0x298U) /*!< CAN filter 11 data 0 register */ +#define CAN_F12DATA0(canx) REG32((canx) + 0x2A0U) /*!< CAN filter 12 data 0 register */ +#define CAN_F13DATA0(canx) REG32((canx) + 0x2A8U) /*!< CAN filter 13 data 0 register */ +#define CAN_F14DATA0(canx) REG32((canx) + 0x2B0U) /*!< CAN filter 14 data 0 register */ +#define CAN_F15DATA0(canx) REG32((canx) + 0x2B8U) /*!< CAN filter 15 data 0 register */ +#define CAN_F16DATA0(canx) REG32((canx) + 0x2C0U) /*!< CAN filter 16 data 0 register */ +#define CAN_F17DATA0(canx) REG32((canx) + 0x2C8U) /*!< CAN filter 17 data 0 register */ +#define CAN_F18DATA0(canx) REG32((canx) + 0x2D0U) /*!< CAN filter 18 data 0 register */ +#define CAN_F19DATA0(canx) REG32((canx) + 0x2D8U) /*!< CAN filter 19 data 0 register */ +#define CAN_F20DATA0(canx) REG32((canx) + 0x2E0U) /*!< CAN filter 20 data 0 register */ +#define CAN_F21DATA0(canx) REG32((canx) + 0x2E8U) /*!< CAN filter 21 data 0 register */ +#define CAN_F22DATA0(canx) REG32((canx) + 0x2F0U) /*!< CAN filter 22 data 0 register */ +#define CAN_F23DATA0(canx) REG32((canx) + 0x3F8U) /*!< CAN filter 23 data 0 register */ +#define CAN_F24DATA0(canx) REG32((canx) + 0x300U) /*!< CAN filter 24 data 0 register */ +#define CAN_F25DATA0(canx) REG32((canx) + 0x308U) /*!< CAN filter 25 data 0 register */ +#define CAN_F26DATA0(canx) REG32((canx) + 0x310U) /*!< CAN filter 26 data 0 register */ +#define CAN_F27DATA0(canx) REG32((canx) + 0x318U) /*!< CAN filter 27 data 0 register */ +#define CAN_F0DATA1(canx) REG32((canx) + 0x244U) /*!< CAN filter 0 data 1 register */ +#define CAN_F1DATA1(canx) REG32((canx) + 0x24CU) /*!< CAN filter 1 data 1 register */ +#define CAN_F2DATA1(canx) REG32((canx) + 0x254U) /*!< CAN filter 2 data 1 register */ +#define CAN_F3DATA1(canx) REG32((canx) + 0x25CU) /*!< CAN filter 3 data 1 register */ +#define CAN_F4DATA1(canx) REG32((canx) + 0x264U) /*!< CAN filter 4 data 1 register */ +#define CAN_F5DATA1(canx) REG32((canx) + 0x26CU) /*!< CAN filter 5 data 1 register */ +#define CAN_F6DATA1(canx) REG32((canx) + 0x274U) /*!< CAN filter 6 data 1 register */ +#define CAN_F7DATA1(canx) REG32((canx) + 0x27CU) /*!< CAN filter 7 data 1 register */ +#define CAN_F8DATA1(canx) REG32((canx) + 0x284U) /*!< CAN filter 8 data 1 register */ +#define CAN_F9DATA1(canx) REG32((canx) + 0x28CU) /*!< CAN filter 9 data 1 register */ +#define CAN_F10DATA1(canx) REG32((canx) + 0x294U) /*!< CAN filter 10 data 1 register */ +#define CAN_F11DATA1(canx) REG32((canx) + 0x29CU) /*!< CAN filter 11 data 1 register */ +#define CAN_F12DATA1(canx) REG32((canx) + 0x2A4U) /*!< CAN filter 12 data 1 register */ +#define CAN_F13DATA1(canx) REG32((canx) + 0x2ACU) /*!< CAN filter 13 data 1 register */ +#define CAN_F14DATA1(canx) REG32((canx) + 0x2B4U) /*!< CAN filter 14 data 1 register */ +#define CAN_F15DATA1(canx) REG32((canx) + 0x2BCU) /*!< CAN filter 15 data 1 register */ +#define CAN_F16DATA1(canx) REG32((canx) + 0x2C4U) /*!< CAN filter 16 data 1 register */ +#define CAN_F17DATA1(canx) REG32((canx) + 0x24CU) /*!< CAN filter 17 data 1 register */ +#define CAN_F18DATA1(canx) REG32((canx) + 0x2D4U) /*!< CAN filter 18 data 1 register */ +#define CAN_F19DATA1(canx) REG32((canx) + 0x2DCU) /*!< CAN filter 19 data 1 register */ +#define CAN_F20DATA1(canx) REG32((canx) + 0x2E4U) /*!< CAN filter 20 data 1 register */ +#define CAN_F21DATA1(canx) REG32((canx) + 0x2ECU) /*!< CAN filter 21 data 1 register */ +#define CAN_F22DATA1(canx) REG32((canx) + 0x2F4U) /*!< CAN filter 22 data 1 register */ +#define CAN_F23DATA1(canx) REG32((canx) + 0x2FCU) /*!< CAN filter 23 data 1 register */ +#define CAN_F24DATA1(canx) REG32((canx) + 0x304U) /*!< CAN filter 24 data 1 register */ +#define CAN_F25DATA1(canx) REG32((canx) + 0x30CU) /*!< CAN filter 25 data 1 register */ +#define CAN_F26DATA1(canx) REG32((canx) + 0x314U) /*!< CAN filter 26 data 1 register */ +#define CAN_F27DATA1(canx) REG32((canx) + 0x31CU) /*!< CAN filter 27 data 1 register */ + +/* CAN transmit mailbox bank */ +#define CAN_TMI(canx, bank) REG32((canx) + 0x180U + ((bank) * 0x10U)) /*!< CAN transmit mailbox identifier register */ +#define CAN_TMP(canx, bank) REG32((canx) + 0x184U + ((bank) * 0x10U)) /*!< CAN transmit mailbox property register */ +#define CAN_TMDATA0(canx, bank) REG32((canx) + 0x188U + ((bank) * 0x10U)) /*!< CAN transmit mailbox data0 register */ +#define CAN_TMDATA1(canx, bank) REG32((canx) + 0x18CU + ((bank) * 0x10U)) /*!< CAN transmit mailbox data1 register */ + +/* CAN filter bank */ +#define CAN_FDATA0(canx, bank) REG32((canx) + 0x240U + ((bank) * 0x8U) + 0x0U) /*!< CAN filter data 0 register */ +#define CAN_FDATA1(canx, bank) REG32((canx) + 0x240U + ((bank) * 0x8U) + 0x4U) /*!< CAN filter data 1 register */ + +/* CAN receive fifo mailbox bank */ +#define CAN_RFIFOMI(canx, bank) REG32((canx) + 0x1B0U + ((bank) * 0x10U)) /*!< CAN receive FIFO mailbox identifier register */ +#define CAN_RFIFOMP(canx, bank) REG32((canx) + 0x1B4U + ((bank) * 0x10U)) /*!< CAN receive FIFO mailbox property register */ +#define CAN_RFIFOMDATA0(canx, bank) REG32((canx) + 0x1B8U + ((bank) * 0x10U)) /*!< CAN receive FIFO mailbox data0 register */ +#define CAN_RFIFOMDATA1(canx, bank) REG32((canx) + 0x1BCU + ((bank) * 0x10U)) /*!< CAN receive FIFO mailbox data1 register */ + +/* bits definitions */ +/* CAN_CTL */ +#define CAN_CTL_IWMOD BIT(0) /*!< initial working mode */ +#define CAN_CTL_SLPWMOD BIT(1) /*!< sleep working mode */ +#define CAN_CTL_TFO BIT(2) /*!< transmit FIFO order */ +#define CAN_CTL_RFOD BIT(3) /*!< receive FIFO overwrite disable */ +#define CAN_CTL_ARD BIT(4) /*!< automatic retransmission disable */ +#define CAN_CTL_AWU BIT(5) /*!< automatic wakeup */ +#define CAN_CTL_ABOR BIT(6) /*!< automatic bus-off recovery */ +#define CAN_CTL_TTC BIT(7) /*!< time triggered communication */ +#define CAN_CTL_SWRST BIT(15) /*!< CAN software reset */ +#define CAN_CTL_DFZ BIT(16) /*!< CAN debug freeze */ + +/* CAN_STAT */ +#define CAN_STAT_IWS BIT(0) /*!< initial working state */ +#define CAN_STAT_SLPWS BIT(1) /*!< sleep working state */ +#define CAN_STAT_ERRIF BIT(2) /*!< error interrupt flag*/ +#define CAN_STAT_WUIF BIT(3) /*!< status change interrupt flag of wakeup from sleep working mode */ +#define CAN_STAT_SLPIF BIT(4) /*!< status change interrupt flag of sleep working mode entering */ +#define CAN_STAT_TS BIT(8) /*!< transmitting state */ +#define CAN_STAT_RS BIT(9) /*!< receiving state */ +#define CAN_STAT_LASTRX BIT(10) /*!< last sample value of rx pin */ +#define CAN_STAT_RXL BIT(11) /*!< CAN rx signal */ + +/* CAN_TSTAT */ +#define CAN_TSTAT_MTF0 BIT(0) /*!< mailbox0 transmit finished */ +#define CAN_TSTAT_MTFNERR0 BIT(1) /*!< mailbox0 transmit finished and no error */ +#define CAN_TSTAT_MAL0 BIT(2) /*!< mailbox0 arbitration lost */ +#define CAN_TSTAT_MTE0 BIT(3) /*!< mailbox0 transmit error */ +#define CAN_TSTAT_MST0 BIT(7) /*!< mailbox0 stop transmitting */ +#define CAN_TSTAT_MTF1 BIT(8) /*!< mailbox1 transmit finished */ +#define CAN_TSTAT_MTFNERR1 BIT(9) /*!< mailbox1 transmit finished and no error */ +#define CAN_TSTAT_MAL1 BIT(10) /*!< mailbox1 arbitration lost */ +#define CAN_TSTAT_MTE1 BIT(11) /*!< mailbox1 transmit error */ +#define CAN_TSTAT_MST1 BIT(15) /*!< mailbox1 stop transmitting */ +#define CAN_TSTAT_MTF2 BIT(16) /*!< mailbox2 transmit finished */ +#define CAN_TSTAT_MTFNERR2 BIT(17) /*!< mailbox2 transmit finished and no error */ +#define CAN_TSTAT_MAL2 BIT(18) /*!< mailbox2 arbitration lost */ +#define CAN_TSTAT_MTE2 BIT(19) /*!< mailbox2 transmit error */ +#define CAN_TSTAT_MST2 BIT(23) /*!< mailbox2 stop transmitting */ +#define CAN_TSTAT_NUM BITS(24,25) /*!< mailbox number */ +#define CAN_TSTAT_TME0 BIT(26) /*!< transmit mailbox0 empty */ +#define CAN_TSTAT_TME1 BIT(27) /*!< transmit mailbox1 empty */ +#define CAN_TSTAT_TME2 BIT(28) /*!< transmit mailbox2 empty */ +#define CAN_TSTAT_TMLS0 BIT(29) /*!< last sending priority flag for mailbox0 */ +#define CAN_TSTAT_TMLS1 BIT(30) /*!< last sending priority flag for mailbox1 */ +#define CAN_TSTAT_TMLS2 BIT(31) /*!< last sending priority flag for mailbox2 */ + +/* CAN_RFIFO0 */ +#define CAN_RFIFO0_RFL0 BITS(0,1) /*!< receive FIFO0 length */ +#define CAN_RFIFO0_RFF0 BIT(3) /*!< receive FIFO0 full */ +#define CAN_RFIFO0_RFO0 BIT(4) /*!< receive FIFO0 overfull */ +#define CAN_RFIFO0_RFD0 BIT(5) /*!< receive FIFO0 dequeue */ + +/* CAN_RFIFO1 */ +#define CAN_RFIFO1_RFL1 BITS(0,1) /*!< receive FIFO1 length */ +#define CAN_RFIFO1_RFF1 BIT(3) /*!< receive FIFO1 full */ +#define CAN_RFIFO1_RFO1 BIT(4) /*!< receive FIFO1 overfull */ +#define CAN_RFIFO1_RFD1 BIT(5) /*!< receive FIFO1 dequeue */ + +/* CAN_INTEN */ +#define CAN_INTEN_TMEIE BIT(0) /*!< transmit mailbox empty interrupt enable */ +#define CAN_INTEN_RFNEIE0 BIT(1) /*!< receive FIFO0 not empty interrupt enable */ +#define CAN_INTEN_RFFIE0 BIT(2) /*!< receive FIFO0 full interrupt enable */ +#define CAN_INTEN_RFOIE0 BIT(3) /*!< receive FIFO0 overfull interrupt enable */ +#define CAN_INTEN_RFNEIE1 BIT(4) /*!< receive FIFO1 not empty interrupt enable */ +#define CAN_INTEN_RFFIE1 BIT(5) /*!< receive FIFO1 full interrupt enable */ +#define CAN_INTEN_RFOIE1 BIT(6) /*!< receive FIFO1 overfull interrupt enable */ +#define CAN_INTEN_WERRIE BIT(8) /*!< warning error interrupt enable */ +#define CAN_INTEN_PERRIE BIT(9) /*!< passive error interrupt enable */ +#define CAN_INTEN_BOIE BIT(10) /*!< bus-off interrupt enable */ +#define CAN_INTEN_ERRNIE BIT(11) /*!< error number interrupt enable */ +#define CAN_INTEN_ERRIE BIT(15) /*!< error interrupt enable */ +#define CAN_INTEN_WIE BIT(16) /*!< wakeup interrupt enable */ +#define CAN_INTEN_SLPWIE BIT(17) /*!< sleep working interrupt enable */ + +/* CAN_ERR */ +#define CAN_ERR_WERR BIT(0) /*!< warning error */ +#define CAN_ERR_PERR BIT(1) /*!< passive error */ +#define CAN_ERR_BOERR BIT(2) /*!< bus-off error */ +#define CAN_ERR_ERRN BITS(4,6) /*!< error number */ +#define CAN_ERR_TECNT BITS(16,23) /*!< transmit error count */ +#define CAN_ERR_RECNT BITS(24,31) /*!< receive error count */ + +/* CAN_BT */ +#define CAN_BT_BAUDPSC BITS(0,9) /*!< baudrate prescaler */ +#define CAN_BT_BS1 BITS(16,19) /*!< bit segment 1 */ +#define CAN_BT_BS2 BITS(20,22) /*!< bit segment 2 */ +#define CAN_BT_SJW BITS(24,25) /*!< resynchronization jump width */ +#define CAN_BT_LCMOD BIT(30) /*!< loopback communication mode */ +#define CAN_BT_SCMOD BIT(31) /*!< silent communication mode */ + +/* CAN_TMIx */ +#define CAN_TMI_TEN BIT(0) /*!< transmit enable */ +#define CAN_TMI_FT BIT(1) /*!< frame type */ +#define CAN_TMI_FF BIT(2) /*!< frame format */ +#define CAN_TMI_EFID BITS(3,31) /*!< the frame identifier */ +#define CAN_TMI_SFID BITS(21,31) /*!< the frame identifier */ + +/* CAN_TMPx */ +#define CAN_TMP_DLENC BITS(0,3) /*!< data length code */ +#define CAN_TMP_TSEN BIT(8) /*!< time stamp enable */ +#define CAN_TMP_TS BITS(16,31) /*!< time stamp */ + +/* CAN_TMDATA0x */ +#define CAN_TMDATA0_DB0 BITS(0,7) /*!< transmit data byte 0 */ +#define CAN_TMDATA0_DB1 BITS(8,15) /*!< transmit data byte 1 */ +#define CAN_TMDATA0_DB2 BITS(16,23) /*!< transmit data byte 2 */ +#define CAN_TMDATA0_DB3 BITS(24,31) /*!< transmit data byte 3 */ + +/* CAN_TMDATA1x */ +#define CAN_TMDATA1_DB4 BITS(0,7) /*!< transmit data byte 4 */ +#define CAN_TMDATA1_DB5 BITS(8,15) /*!< transmit data byte 5 */ +#define CAN_TMDATA1_DB6 BITS(16,23) /*!< transmit data byte 6 */ +#define CAN_TMDATA1_DB7 BITS(24,31) /*!< transmit data byte 7 */ + +/* CAN_RFIFOMIx */ +#define CAN_RFIFOMI_FT BIT(1) /*!< frame type */ +#define CAN_RFIFOMI_FF BIT(2) /*!< frame format */ +#define CAN_RFIFOMI_EFID BITS(3,31) /*!< the frame identifier */ +#define CAN_RFIFOMI_SFID BITS(21,31) /*!< the frame identifier */ + +/* CAN_RFIFOMPx */ +#define CAN_RFIFOMP_DLENC BITS(0,3) /*!< receive data length code */ +#define CAN_RFIFOMP_FI BITS(8,15) /*!< filter index */ +#define CAN_RFIFOMP_TS BITS(16,31) /*!< time stamp */ + +/* CAN_RFIFOMDATA0x */ +#define CAN_RFIFOMDATA0_DB0 BITS(0,7) /*!< receive data byte 0 */ +#define CAN_RFIFOMDATA0_DB1 BITS(8,15) /*!< receive data byte 1 */ +#define CAN_RFIFOMDATA0_DB2 BITS(16,23) /*!< receive data byte 2 */ +#define CAN_RFIFOMDATA0_DB3 BITS(24,31) /*!< receive data byte 3 */ + +/* CAN_RFIFOMDATA1x */ +#define CAN_RFIFOMDATA1_DB4 BITS(0,7) /*!< receive data byte 4 */ +#define CAN_RFIFOMDATA1_DB5 BITS(8,15) /*!< receive data byte 5 */ +#define CAN_RFIFOMDATA1_DB6 BITS(16,23) /*!< receive data byte 6 */ +#define CAN_RFIFOMDATA1_DB7 BITS(24,31) /*!< receive data byte 7 */ + +/* CAN_FCTL */ +#define CAN_FCTL_FLD BIT(0) /*!< filter lock disable */ +#define CAN_FCTL_HBC1F BITS(8,13) /*!< header bank of CAN1 filter */ + +/* CAN_FMCFG */ +#define CAN_FMCFG_FMOD(regval) BIT(regval) /*!< filter mode, list or mask*/ + +/* CAN_FSCFG */ +#define CAN_FSCFG_FS(regval) BIT(regval) /*!< filter scale, 32 bits or 16 bits*/ + +/* CAN_FAFIFO */ +#define CAN_FAFIFOR_FAF(regval) BIT(regval) /*!< filter associated with FIFO */ + +/* CAN_FW */ +#define CAN_FW_FW(regval) BIT(regval) /*!< filter working */ + +/* CAN_FxDATAy */ +#define CAN_FDATA_FD(regval) BIT(regval) /*!< filter data */ + +/* consts definitions */ +/* define the CAN bit position and its register index offset */ +#define CAN_REGIDX_BIT(regidx, bitpos) (((uint32_t)(regidx) << 6) | (uint32_t)(bitpos)) +#define CAN_REG_VAL(canx, offset) (REG32((canx) + ((uint32_t)(offset) >> 6))) +#define CAN_BIT_POS(val) ((uint32_t)(val) & 0x1FU) + +#define CAN_REGIDX_BITS(regidx, bitpos0, bitpos1) (((uint32_t)(regidx) << 12) | ((uint32_t)(bitpos0) << 6) | (uint32_t)(bitpos1)) +#define CAN_REG_VALS(canx, offset) (REG32((canx) + ((uint32_t)(offset) >> 12))) +#define CAN_BIT_POS0(val) (((uint32_t)(val) >> 6) & 0x1FU) +#define CAN_BIT_POS1(val) ((uint32_t)(val) & 0x1FU) + +/* register offset */ +#define STAT_REG_OFFSET ((uint8_t)0x04U) /*!< STAT register offset */ +#define TSTAT_REG_OFFSET ((uint8_t)0x08U) /*!< TSTAT register offset */ +#define RFIFO0_REG_OFFSET ((uint8_t)0x0CU) /*!< RFIFO0 register offset */ +#define RFIFO1_REG_OFFSET ((uint8_t)0x10U) /*!< RFIFO1 register offset */ +#define ERR_REG_OFFSET ((uint8_t)0x18U) /*!< ERR register offset */ + +/* CAN flags */ +typedef enum +{ + /* flags in STAT register */ + CAN_FLAG_RXL = CAN_REGIDX_BIT(STAT_REG_OFFSET, 11U), /*!< RX level */ + CAN_FLAG_LASTRX = CAN_REGIDX_BIT(STAT_REG_OFFSET, 10U), /*!< last sample value of RX pin */ + CAN_FLAG_RS = CAN_REGIDX_BIT(STAT_REG_OFFSET, 9U), /*!< receiving state */ + CAN_FLAG_TS = CAN_REGIDX_BIT(STAT_REG_OFFSET, 8U), /*!< transmitting state */ + CAN_FLAG_SLPIF = CAN_REGIDX_BIT(STAT_REG_OFFSET, 4U), /*!< status change flag of entering sleep working mode */ + CAN_FLAG_WUIF = CAN_REGIDX_BIT(STAT_REG_OFFSET, 3U), /*!< status change flag of wakeup from sleep working mode */ + CAN_FLAG_ERRIF = CAN_REGIDX_BIT(STAT_REG_OFFSET, 2U), /*!< error flag */ + CAN_FLAG_SLPWS = CAN_REGIDX_BIT(STAT_REG_OFFSET, 1U), /*!< sleep working state */ + CAN_FLAG_IWS = CAN_REGIDX_BIT(STAT_REG_OFFSET, 0U), /*!< initial working state */ + /* flags in TSTAT register */ + CAN_FLAG_TMLS2 = CAN_REGIDX_BIT(TSTAT_REG_OFFSET, 31U), /*!< transmit mailbox 2 last sending in Tx FIFO */ + CAN_FLAG_TMLS1 = CAN_REGIDX_BIT(TSTAT_REG_OFFSET, 30U), /*!< transmit mailbox 1 last sending in Tx FIFO */ + CAN_FLAG_TMLS0 = CAN_REGIDX_BIT(TSTAT_REG_OFFSET, 29U), /*!< transmit mailbox 0 last sending in Tx FIFO */ + CAN_FLAG_TME2 = CAN_REGIDX_BIT(TSTAT_REG_OFFSET, 28U), /*!< transmit mailbox 2 empty */ + CAN_FLAG_TME1 = CAN_REGIDX_BIT(TSTAT_REG_OFFSET, 27U), /*!< transmit mailbox 1 empty */ + CAN_FLAG_TME0 = CAN_REGIDX_BIT(TSTAT_REG_OFFSET, 26U), /*!< transmit mailbox 0 empty */ + CAN_FLAG_MTE2 = CAN_REGIDX_BIT(TSTAT_REG_OFFSET, 19U), /*!< mailbox 2 transmit error */ + CAN_FLAG_MTE1 = CAN_REGIDX_BIT(TSTAT_REG_OFFSET, 11U), /*!< mailbox 1 transmit error */ + CAN_FLAG_MTE0 = CAN_REGIDX_BIT(TSTAT_REG_OFFSET, 3U), /*!< mailbox 0 transmit error */ + CAN_FLAG_MAL2 = CAN_REGIDX_BIT(TSTAT_REG_OFFSET, 18U), /*!< mailbox 2 arbitration lost */ + CAN_FLAG_MAL1 = CAN_REGIDX_BIT(TSTAT_REG_OFFSET, 10U), /*!< mailbox 1 arbitration lost */ + CAN_FLAG_MAL0 = CAN_REGIDX_BIT(TSTAT_REG_OFFSET, 2U), /*!< mailbox 0 arbitration lost */ + CAN_FLAG_MTFNERR2 = CAN_REGIDX_BIT(TSTAT_REG_OFFSET, 17U), /*!< mailbox 2 transmit finished with no error */ + CAN_FLAG_MTFNERR1 = CAN_REGIDX_BIT(TSTAT_REG_OFFSET, 9U), /*!< mailbox 1 transmit finished with no error */ + CAN_FLAG_MTFNERR0 = CAN_REGIDX_BIT(TSTAT_REG_OFFSET, 1U), /*!< mailbox 0 transmit finished with no error */ + CAN_FLAG_MTF2 = CAN_REGIDX_BIT(TSTAT_REG_OFFSET, 16U), /*!< mailbox 2 transmit finished */ + CAN_FLAG_MTF1 = CAN_REGIDX_BIT(TSTAT_REG_OFFSET, 8U), /*!< mailbox 1 transmit finished */ + CAN_FLAG_MTF0 = CAN_REGIDX_BIT(TSTAT_REG_OFFSET, 0U), /*!< mailbox 0 transmit finished */ + /* flags in RFIFO0 register */ + CAN_FLAG_RFO0 = CAN_REGIDX_BIT(RFIFO0_REG_OFFSET, 4U), /*!< receive FIFO0 overfull */ + CAN_FLAG_RFF0 = CAN_REGIDX_BIT(RFIFO0_REG_OFFSET, 3U), /*!< receive FIFO0 full */ + /* flags in RFIFO1 register */ + CAN_FLAG_RFO1 = CAN_REGIDX_BIT(RFIFO1_REG_OFFSET, 4U), /*!< receive FIFO1 overfull */ + CAN_FLAG_RFF1 = CAN_REGIDX_BIT(RFIFO1_REG_OFFSET, 3U), /*!< receive FIFO1 full */ + /* flags in ERR register */ + CAN_FLAG_BOERR = CAN_REGIDX_BIT(ERR_REG_OFFSET, 2U), /*!< bus-off error */ + CAN_FLAG_PERR = CAN_REGIDX_BIT(ERR_REG_OFFSET, 1U), /*!< passive error */ + CAN_FLAG_WERR = CAN_REGIDX_BIT(ERR_REG_OFFSET, 0U), /*!< warning error */ +}can_flag_enum; + +/* CAN interrupt flags */ +typedef enum +{ + /* interrupt flags in STAT register */ + CAN_INT_FLAG_SLPIF = CAN_REGIDX_BITS(STAT_REG_OFFSET, 4U, 17U), /*!< status change interrupt flag of sleep working mode entering */ + CAN_INT_FLAG_WUIF = CAN_REGIDX_BITS(STAT_REG_OFFSET, 3U, 16), /*!< status change interrupt flag of wakeup from sleep working mode */ + CAN_INT_FLAG_ERRIF = CAN_REGIDX_BITS(STAT_REG_OFFSET, 2U, 15), /*!< error interrupt flag */ + /* interrupt flags in TSTAT register */ + CAN_INT_FLAG_MTF2 = CAN_REGIDX_BITS(TSTAT_REG_OFFSET, 16U, 0U), /*!< mailbox 2 transmit finished interrupt flag */ + CAN_INT_FLAG_MTF1 = CAN_REGIDX_BITS(TSTAT_REG_OFFSET, 8U, 0U), /*!< mailbox 1 transmit finished interrupt flag */ + CAN_INT_FLAG_MTF0 = CAN_REGIDX_BITS(TSTAT_REG_OFFSET, 0U, 0U), /*!< mailbox 0 transmit finished interrupt flag */ + /* interrupt flags in RFIFO0 register */ + CAN_INT_FLAG_RFO0 = CAN_REGIDX_BITS(RFIFO0_REG_OFFSET, 4U, 3U), /*!< receive FIFO0 overfull interrupt flag */ + CAN_INT_FLAG_RFF0 = CAN_REGIDX_BITS(RFIFO0_REG_OFFSET, 3U, 2U), /*!< receive FIFO0 full interrupt flag */ + CAN_INT_FLAG_RFL0 = CAN_REGIDX_BITS(RFIFO0_REG_OFFSET, 2U, 1U), /*!< receive FIFO0 not empty interrupt flag */ + /* interrupt flags in RFIFO0 register */ + CAN_INT_FLAG_RFO1 = CAN_REGIDX_BITS(RFIFO1_REG_OFFSET, 4U, 6U), /*!< receive FIFO1 overfull interrupt flag */ + CAN_INT_FLAG_RFF1 = CAN_REGIDX_BITS(RFIFO1_REG_OFFSET, 3U, 5U), /*!< receive FIFO1 full interrupt flag */ + CAN_INT_FLAG_RFL1 = CAN_REGIDX_BITS(RFIFO1_REG_OFFSET, 2U, 4U), /*!< receive FIFO1 not empty interrupt flag */ + /* interrupt flags in ERR register */ + CAN_INT_FLAG_ERRN = CAN_REGIDX_BITS(ERR_REG_OFFSET, 3U, 11U), /*!< error number interrupt flag */ + CAN_INT_FLAG_BOERR = CAN_REGIDX_BITS(ERR_REG_OFFSET, 2U, 10U), /*!< bus-off error interrupt flag */ + CAN_INT_FLAG_PERR = CAN_REGIDX_BITS(ERR_REG_OFFSET, 1U, 9U), /*!< passive error interrupt flag */ + CAN_INT_FLAG_WERR = CAN_REGIDX_BITS(ERR_REG_OFFSET, 0U, 8U), /*!< warning error interrupt flag */ +}can_interrupt_flag_enum; + +/* CAN initiliaze parameters struct */ +typedef struct +{ + uint8_t working_mode; /*!< CAN working mode */ + uint8_t resync_jump_width; /*!< CAN resynchronization jump width */ + uint8_t time_segment_1; /*!< time segment 1 */ + uint8_t time_segment_2; /*!< time segment 2 */ + ControlStatus time_triggered; /*!< time triggered communication mode */ + ControlStatus auto_bus_off_recovery; /*!< automatic bus-off recovery */ + ControlStatus auto_wake_up; /*!< automatic wake-up mode */ + ControlStatus no_auto_retrans; /*!< automatic retransmission mode disable */ + ControlStatus rec_fifo_overwrite; /*!< receive FIFO overwrite mode */ + ControlStatus trans_fifo_order; /*!< transmit FIFO order */ + uint16_t prescaler; /*!< baudrate prescaler */ +}can_parameter_struct; + +/* CAN transmit message struct */ +typedef struct +{ + uint32_t tx_sfid; /*!< standard format frame identifier */ + uint32_t tx_efid; /*!< extended format frame identifier */ + uint8_t tx_ff; /*!< format of frame, standard or extended format */ + uint8_t tx_ft; /*!< type of frame, data or remote */ + uint8_t tx_dlen; /*!< data length */ + uint8_t tx_data[8]; /*!< transmit data */ +}can_trasnmit_message_struct; + +/* CAN receive message struct */ +typedef struct +{ + uint32_t rx_sfid; /*!< standard format frame identifier */ + uint32_t rx_efid; /*!< extended format frame identifier */ + uint8_t rx_ff; /*!< format of frame, standard or extended format */ + uint8_t rx_ft; /*!< type of frame, data or remote */ + uint8_t rx_dlen; /*!< data length */ + uint8_t rx_data[8]; /*!< receive data */ + uint8_t rx_fi; /*!< filtering index */ +} can_receive_message_struct; + +/* CAN filter parameters struct */ +typedef struct +{ + uint16_t filter_list_high; /*!< filter list number high bits*/ + uint16_t filter_list_low; /*!< filter list number low bits */ + uint16_t filter_mask_high; /*!< filter mask number high bits */ + uint16_t filter_mask_low; /*!< filter mask number low bits */ + uint16_t filter_fifo_number; /*!< receive FIFO associated with the filter */ + uint16_t filter_number; /*!< filter number */ + uint16_t filter_mode; /*!< filter mode, list or mask */ + uint16_t filter_bits; /*!< filter scale */ + ControlStatus filter_enable; /*!< filter work or not */ +}can_filter_parameter_struct; + +/* CAN errors */ +typedef enum +{ + CAN_ERROR_NONE = 0, /*!< no error */ + CAN_ERROR_FILL, /*!< fill error */ + CAN_ERROR_FORMATE, /*!< format error */ + CAN_ERROR_ACK, /*!< ACK error */ + CAN_ERROR_BITRECESSIVE, /*!< bit recessive error */ + CAN_ERROR_BITDOMINANTER, /*!< bit dominant error */ + CAN_ERROR_CRC, /*!< CRC error */ + CAN_ERROR_SOFTWARECFG, /*!< software configure */ +}can_error_enum; + +/* transmit states */ +typedef enum +{ + CAN_TRANSMIT_FAILED = 0U, /*!< CAN transmitted failure */ + CAN_TRANSMIT_OK = 1U, /*!< CAN transmitted success */ + CAN_TRANSMIT_PENDING = 2U, /*!< CAN transmitted pending */ + CAN_TRANSMIT_NOMAILBOX = 4U, /*!< no empty mailbox to be used for CAN */ +}can_transmit_state_enum; + +typedef enum +{ + CAN_INIT_STRUCT = 0, /* CAN initiliaze parameters struct */ + CAN_FILTER_STRUCT, /* CAN filter parameters struct */ + CAN_TX_MESSAGE_STRUCT, /* CAN transmit message struct */ + CAN_RX_MESSAGE_STRUCT, /* CAN receive message struct */ +}can_struct_type_enum; + +/* CAN baudrate prescaler*/ +#define BT_BAUDPSC(regval) (BITS(0,9) & ((uint32_t)(regval) << 0)) + +/* CAN bit segment 1*/ +#define BT_BS1(regval) (BITS(16,19) & ((uint32_t)(regval) << 16)) + +/* CAN bit segment 2*/ +#define BT_BS2(regval) (BITS(20,22) & ((uint32_t)(regval) << 20)) + +/* CAN resynchronization jump width*/ +#define BT_SJW(regval) (BITS(24,25) & ((uint32_t)(regval) << 24)) + +/* CAN communication mode*/ +#define BT_MODE(regval) (BITS(30,31) & ((uint32_t)(regval) << 30)) + +/* CAN FDATA high 16 bits */ +#define FDATA_MASK_HIGH(regval) (BITS(16,31) & ((uint32_t)(regval) << 16)) + +/* CAN FDATA low 16 bits */ +#define FDATA_MASK_LOW(regval) (BITS(0,15) & ((uint32_t)(regval) << 0)) + +/* CAN1 filter start bank_number*/ +#define FCTL_HBC1F(regval) (BITS(8,13) & ((uint32_t)(regval) << 8)) + +/* CAN transmit mailbox extended identifier*/ +#define TMI_EFID(regval) (BITS(3,31) & ((uint32_t)(regval) << 3)) + +/* CAN transmit mailbox standard identifier*/ +#define TMI_SFID(regval) (BITS(21,31) & ((uint32_t)(regval) << 21)) + +/* transmit data byte 0 */ +#define TMDATA0_DB0(regval) (BITS(0,7) & ((uint32_t)(regval) << 0)) + +/* transmit data byte 1 */ +#define TMDATA0_DB1(regval) (BITS(8,15) & ((uint32_t)(regval) << 8)) + +/* transmit data byte 2 */ +#define TMDATA0_DB2(regval) (BITS(16,23) & ((uint32_t)(regval) << 16)) + +/* transmit data byte 3 */ +#define TMDATA0_DB3(regval) (BITS(24,31) & ((uint32_t)(regval) << 24)) + +/* transmit data byte 4 */ +#define TMDATA1_DB4(regval) (BITS(0,7) & ((uint32_t)(regval) << 0)) + +/* transmit data byte 5 */ +#define TMDATA1_DB5(regval) (BITS(8,15) & ((uint32_t)(regval) << 8)) + +/* transmit data byte 6 */ +#define TMDATA1_DB6(regval) (BITS(16,23) & ((uint32_t)(regval) << 16)) + +/* transmit data byte 7 */ +#define TMDATA1_DB7(regval) (BITS(24,31) & ((uint32_t)(regval) << 24)) + +/* receive mailbox extended identifier*/ +#define GET_RFIFOMI_EFID(regval) GET_BITS((uint32_t)(regval), 3U, 31U) + +/* receive mailbox standrad identifier*/ +#define GET_RFIFOMI_SFID(regval) GET_BITS((uint32_t)(regval), 21U, 31U) + +/* receive data length */ +#define GET_RFIFOMP_DLENC(regval) GET_BITS((uint32_t)(regval), 0U, 3U) + +/* the index of the filter by which the frame is passed */ +#define GET_RFIFOMP_FI(regval) GET_BITS((uint32_t)(regval), 8U, 15U) + +/* receive data byte 0 */ +#define GET_RFIFOMDATA0_DB0(regval) GET_BITS((uint32_t)(regval), 0U, 7U) + +/* receive data byte 1 */ +#define GET_RFIFOMDATA0_DB1(regval) GET_BITS((uint32_t)(regval), 8U, 15U) + +/* receive data byte 2 */ +#define GET_RFIFOMDATA0_DB2(regval) GET_BITS((uint32_t)(regval), 16U, 23U) + +/* receive data byte 3 */ +#define GET_RFIFOMDATA0_DB3(regval) GET_BITS((uint32_t)(regval), 24U, 31U) + +/* receive data byte 4 */ +#define GET_RFIFOMDATA1_DB4(regval) GET_BITS((uint32_t)(regval), 0U, 7U) + +/* receive data byte 5 */ +#define GET_RFIFOMDATA1_DB5(regval) GET_BITS((uint32_t)(regval), 8U, 15U) + +/* receive data byte 6 */ +#define GET_RFIFOMDATA1_DB6(regval) GET_BITS((uint32_t)(regval), 16U, 23U) + +/* receive data byte 7 */ +#define GET_RFIFOMDATA1_DB7(regval) GET_BITS((uint32_t)(regval), 24U, 31U) + +/* error number */ +#define GET_ERR_ERRN(regval) GET_BITS((uint32_t)(regval), 4U, 6U) + +/* transmit error count */ +#define GET_ERR_TECNT(regval) GET_BITS((uint32_t)(regval), 16U, 23U) + +/* receive error count */ +#define GET_ERR_RECNT(regval) GET_BITS((uint32_t)(regval), 24U, 31U) + +/* CAN errors */ +#define ERR_ERRN(regval) (BITS(4,6) & ((uint32_t)(regval) << 4)) +#define CAN_ERRN_0 ERR_ERRN(0U) /* no error */ +#define CAN_ERRN_1 ERR_ERRN(1U) /*!< fill error */ +#define CAN_ERRN_2 ERR_ERRN(2U) /*!< format error */ +#define CAN_ERRN_3 ERR_ERRN(3U) /*!< ACK error */ +#define CAN_ERRN_4 ERR_ERRN(4U) /*!< bit recessive error */ +#define CAN_ERRN_5 ERR_ERRN(5U) /*!< bit dominant error */ +#define CAN_ERRN_6 ERR_ERRN(6U) /*!< CRC error */ +#define CAN_ERRN_7 ERR_ERRN(7U) /*!< software error */ + +#define CAN_STATE_PENDING ((uint32_t)0x00000000U) /*!< CAN pending */ + +/* CAN communication mode */ +#define CAN_NORMAL_MODE ((uint8_t)0x00U) /*!< normal communication mode */ +#define CAN_LOOPBACK_MODE ((uint8_t)0x01U) /*!< loopback communication mode */ +#define CAN_SILENT_MODE ((uint8_t)0x02U) /*!< silent communication mode */ +#define CAN_SILENT_LOOPBACK_MODE ((uint8_t)0x03U) /*!< loopback and silent communication mode */ + +/* CAN resynchronisation jump width */ +#define CAN_BT_SJW_1TQ ((uint8_t)0x00U) /*!< 1 time quanta */ +#define CAN_BT_SJW_2TQ ((uint8_t)0x01U) /*!< 2 time quanta */ +#define CAN_BT_SJW_3TQ ((uint8_t)0x02U) /*!< 3 time quanta */ +#define CAN_BT_SJW_4TQ ((uint8_t)0x03U) /*!< 4 time quanta */ + +/* CAN time segment 1 */ +#define CAN_BT_BS1_1TQ ((uint8_t)0x00U) /*!< 1 time quanta */ +#define CAN_BT_BS1_2TQ ((uint8_t)0x01U) /*!< 2 time quanta */ +#define CAN_BT_BS1_3TQ ((uint8_t)0x02U) /*!< 3 time quanta */ +#define CAN_BT_BS1_4TQ ((uint8_t)0x03U) /*!< 4 time quanta */ +#define CAN_BT_BS1_5TQ ((uint8_t)0x04U) /*!< 5 time quanta */ +#define CAN_BT_BS1_6TQ ((uint8_t)0x05U) /*!< 6 time quanta */ +#define CAN_BT_BS1_7TQ ((uint8_t)0x06U) /*!< 7 time quanta */ +#define CAN_BT_BS1_8TQ ((uint8_t)0x07U) /*!< 8 time quanta */ +#define CAN_BT_BS1_9TQ ((uint8_t)0x08U) /*!< 9 time quanta */ +#define CAN_BT_BS1_10TQ ((uint8_t)0x09U) /*!< 10 time quanta */ +#define CAN_BT_BS1_11TQ ((uint8_t)0x0AU) /*!< 11 time quanta */ +#define CAN_BT_BS1_12TQ ((uint8_t)0x0BU) /*!< 12 time quanta */ +#define CAN_BT_BS1_13TQ ((uint8_t)0x0CU) /*!< 13 time quanta */ +#define CAN_BT_BS1_14TQ ((uint8_t)0x0DU) /*!< 14 time quanta */ +#define CAN_BT_BS1_15TQ ((uint8_t)0x0EU) /*!< 15 time quanta */ +#define CAN_BT_BS1_16TQ ((uint8_t)0x0FU) /*!< 16 time quanta */ + +/* CAN time segment 2 */ +#define CAN_BT_BS2_1TQ ((uint8_t)0x00U) /*!< 1 time quanta */ +#define CAN_BT_BS2_2TQ ((uint8_t)0x01U) /*!< 2 time quanta */ +#define CAN_BT_BS2_3TQ ((uint8_t)0x02U) /*!< 3 time quanta */ +#define CAN_BT_BS2_4TQ ((uint8_t)0x03U) /*!< 4 time quanta */ +#define CAN_BT_BS2_5TQ ((uint8_t)0x04U) /*!< 5 time quanta */ +#define CAN_BT_BS2_6TQ ((uint8_t)0x05U) /*!< 6 time quanta */ +#define CAN_BT_BS2_7TQ ((uint8_t)0x06U) /*!< 7 time quanta */ +#define CAN_BT_BS2_8TQ ((uint8_t)0x07U) /*!< 8 time quanta */ + +/* CAN mailbox number */ +#define CAN_MAILBOX0 ((uint8_t)0x00U) /*!< mailbox0 */ +#define CAN_MAILBOX1 ((uint8_t)0x01U) /*!< mailbox1 */ +#define CAN_MAILBOX2 ((uint8_t)0x02U) /*!< mailbox2 */ +#define CAN_NOMAILBOX ((uint8_t)0x03U) /*!< no mailbox empty */ + +/* CAN frame format */ +#define CAN_FF_STANDARD ((uint32_t)0x00000000U) /*!< standard frame */ +#define CAN_FF_EXTENDED ((uint32_t)0x00000004U) /*!< extended frame */ + +/* CAN receive fifo */ +#define CAN_FIFO0 ((uint8_t)0x00U) /*!< receive FIFO0 */ +#define CAN_FIFO1 ((uint8_t)0x01U) /*!< receive FIFO1 */ + +/* frame number of receive fifo */ +#define CAN_RFIF_RFL_MASK ((uint32_t)0x00000003U) /*!< mask for frame number in receive FIFOx */ + +#define CAN_SFID_MASK ((uint32_t)0x000007FFU) /*!< mask of standard identifier */ +#define CAN_EFID_MASK ((uint32_t)0x1FFFFFFFU) /*!< mask of extended identifier */ + +/* CAN working mode */ +#define CAN_MODE_INITIALIZE ((uint8_t)0x01U) /*!< CAN initialize mode */ +#define CAN_MODE_NORMAL ((uint8_t)0x02U) /*!< CAN normal mode */ +#define CAN_MODE_SLEEP ((uint8_t)0x04U) /*!< CAN sleep mode */ + +/* filter bits */ +#define CAN_FILTERBITS_16BIT ((uint8_t)0x00U) /*!< CAN filter 16 bits */ +#define CAN_FILTERBITS_32BIT ((uint8_t)0x01U) /*!< CAN filter 32 bits */ + +/* filter mode */ +#define CAN_FILTERMODE_MASK ((uint8_t)0x00U) /*!< mask mode */ +#define CAN_FILTERMODE_LIST ((uint8_t)0x01U) /*!< list mode */ + +/* filter 16 bits mask */ +#define CAN_FILTER_MASK_16BITS ((uint32_t)0x0000FFFFU) /*!< can filter 16 bits mask */ + +/* frame type */ +#define CAN_FT_DATA ((uint32_t)0x00000000U) /*!< data frame */ +#define CAN_FT_REMOTE ((uint32_t)0x00000002U) /*!< remote frame */ + +/* CAN timeout */ +#define CAN_TIMEOUT ((uint32_t)0x0000FFFFU) /*!< timeout value */ + +/* interrupt enable bits */ +#define CAN_INT_TME CAN_INTEN_TMEIE /*!< transmit mailbox empty interrupt enable */ +#define CAN_INT_RFNE0 CAN_INTEN_RFNEIE0 /*!< receive FIFO0 not empty interrupt enable */ +#define CAN_INT_RFF0 CAN_INTEN_RFFIE0 /*!< receive FIFO0 full interrupt enable */ +#define CAN_INT_RFO0 CAN_INTEN_RFOIE0 /*!< receive FIFO0 overfull interrupt enable */ +#define CAN_INT_RFNE1 CAN_INTEN_RFNEIE1 /*!< receive FIFO1 not empty interrupt enable */ +#define CAN_INT_RFF1 CAN_INTEN_RFFIE1 /*!< receive FIFO1 full interrupt enable */ +#define CAN_INT_RFO1 CAN_INTEN_RFOIE1 /*!< receive FIFO1 overfull interrupt enable */ +#define CAN_INT_WERR CAN_INTEN_WERRIE /*!< warning error interrupt enable */ +#define CAN_INT_PERR CAN_INTEN_PERRIE /*!< passive error interrupt enable */ +#define CAN_INT_BO CAN_INTEN_BOIE /*!< bus-off interrupt enable */ +#define CAN_INT_ERRN CAN_INTEN_ERRNIE /*!< error number interrupt enable */ +#define CAN_INT_ERR CAN_INTEN_ERRIE /*!< error interrupt enable */ +#define CAN_INT_WAKEUP CAN_INTEN_WIE /*!< wakeup interrupt enable */ +#define CAN_INT_SLPW CAN_INTEN_SLPWIE /*!< sleep working interrupt enable */ + +/* function declarations */ +/* deinitialize CAN */ +void can_deinit(uint32_t can_periph); +/* initialize CAN struct */ +void can_struct_para_init(can_struct_type_enum type, void* p_struct); +/* initialize CAN */ +ErrStatus can_init(uint32_t can_periph, can_parameter_struct* can_parameter_init); +/* CAN filter init */ +void can_filter_init(can_filter_parameter_struct* can_filter_parameter_init); +/* set can1 fliter start bank number */ +void can1_filter_start_bank(uint8_t start_bank); +/* enable functions */ +/* CAN debug freeze enable */ +void can_debug_freeze_enable(uint32_t can_periph); +/* CAN debug freeze disable */ +void can_debug_freeze_disable(uint32_t can_periph); +/* CAN time trigger mode enable */ +void can_time_trigger_mode_enable(uint32_t can_periph); +/* CAN time trigger mode disable */ +void can_time_trigger_mode_disable(uint32_t can_periph); + +/* transmit functions */ +/* transmit CAN message */ +uint8_t can_message_transmit(uint32_t can_periph, can_trasnmit_message_struct* transmit_message); +/* get CAN transmit state */ +can_transmit_state_enum can_transmit_states(uint32_t can_periph, uint8_t mailbox_number); +/* stop CAN transmission */ +void can_transmission_stop(uint32_t can_periph, uint8_t mailbox_number); +/* CAN receive message */ +void can_message_receive(uint32_t can_periph, uint8_t fifo_number, can_receive_message_struct* receive_message); +/* CAN release fifo */ +void can_fifo_release(uint32_t can_periph, uint8_t fifo_number); +/* CAN receive message length */ +uint8_t can_receive_message_length_get(uint32_t can_periph, uint8_t fifo_number); +/* CAN working mode */ +ErrStatus can_working_mode_set(uint32_t can_periph, uint8_t working_mode); +/* CAN wakeup from sleep mode */ +ErrStatus can_wakeup(uint32_t can_periph); + +/* CAN get error */ +can_error_enum can_error_get(uint32_t can_periph); +/* get CAN receive error number */ +uint8_t can_receive_error_number_get(uint32_t can_periph); +/* get CAN transmit error number */ +uint8_t can_transmit_error_number_get(uint32_t can_periph); + +/* CAN interrupt enable */ +void can_interrupt_enable(uint32_t can_periph, uint32_t interrupt); +/* CAN interrupt disable */ +void can_interrupt_disable(uint32_t can_periph, uint32_t interrupt); +/* CAN get flag state */ +FlagStatus can_flag_get(uint32_t can_periph, can_flag_enum flag); +/* CAN clear flag state */ +void can_flag_clear(uint32_t can_periph, can_flag_enum flag); +/* CAN get interrupt flag state */ +FlagStatus can_interrupt_flag_get(uint32_t can_periph, can_interrupt_flag_enum flag); +/* CAN clear interrupt flag state */ +void can_interrupt_flag_clear(uint32_t can_periph, can_interrupt_flag_enum flag); + +#endif /* GD32F10x_CAN_H */ diff --git a/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_standard_peripheral/Include/gd32f10x_crc.h b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_standard_peripheral/Include/gd32f10x_crc.h new file mode 100644 index 0000000000..107b527456 --- /dev/null +++ b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_standard_peripheral/Include/gd32f10x_crc.h @@ -0,0 +1,80 @@ +/*! + \file gd32f10x_crc.h + \brief definitions for the CRC + + \version 2014-12-26, V1.0.0, firmware for GD32F10x + \version 2017-06-20, V2.0.0, firmware for GD32F10x + \version 2018-07-31, V2.1.0, firmware for GD32F10x + \version 2020-09-30, V2.2.0, firmware for GD32F10x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef GD32F10X_CRC_H +#define GD32F10X_CRC_H + +#include "gd32f10x.h" + +/* CRC definitions */ +#define CRC CRC_BASE + +/* registers definitions */ +#define CRC_DATA REG32(CRC + 0x00U) /*!< CRC data register */ +#define CRC_FDATA REG32(CRC + 0x04U) /*!< CRC free data register */ +#define CRC_CTL REG32(CRC + 0x08U) /*!< CRC control register */ + +/* bits definitions */ +/* CRC_DATA */ +#define CRC_DATA_DATA BITS(0,31) /*!< CRC calculation result bits */ + +/* CRC_FDATA */ +#define CRC_FDATA_FDATA BITS(0,7) /*!< CRC free data bits */ + +/* CRC_CTL */ +#define CRC_CTL_RST BIT(0) /*!< CRC reset CRC_DATA register bit */ + +/* function declarations */ +/* deinit CRC calculation unit */ +void crc_deinit(void); + +/* reset data register to the value of initializaiton data register */ +void crc_data_register_reset(void); +/* read the value of the data register */ +uint32_t crc_data_register_read(void); + +/* read the value of the free data register */ +uint8_t crc_free_data_register_read(void); +/* write data to the free data register */ +void crc_free_data_register_write(uint8_t free_data); + +/* calculate the CRC value of a 32-bit data */ +uint32_t crc_single_data_calculate(uint32_t sdata); +/* calculate the CRC value of an array of 32-bit values */ +uint32_t crc_block_data_calculate(uint32_t array[], uint32_t size); + +#endif /* GD32F10X_CRC_H */ diff --git a/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_standard_peripheral/Include/gd32f10x_dac.h b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_standard_peripheral/Include/gd32f10x_dac.h new file mode 100644 index 0000000000..fc9a16d47c --- /dev/null +++ b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_standard_peripheral/Include/gd32f10x_dac.h @@ -0,0 +1,249 @@ +/*! + \file gd32f10x_dac.h + \brief definitions for the DAC + + \version 2014-12-26, V1.0.0, firmware for GD32F10x + \version 2017-06-20, V2.0.0, firmware for GD32F10x + \version 2018-07-31, V2.1.0, firmware for GD32F10x + \version 2020-09-30, V2.2.0, firmware for GD32F10x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef GD32F10X_DAC_H +#define GD32F10X_DAC_H + +#include "gd32f10x.h" + +/* DACx(x=0,1) definitions */ +#define DAC DAC_BASE +#define DAC0 0U +#define DAC1 1U + +/* registers definitions */ +#define DAC_CTL REG32(DAC + 0x00U) /*!< DAC control register */ +#define DAC_SWT REG32(DAC + 0x04U) /*!< DAC software trigger register */ +#define DAC0_R12DH REG32(DAC + 0x08U) /*!< DAC0 12-bit right-aligned data holding register */ +#define DAC0_L12DH REG32(DAC + 0x0CU) /*!< DAC0 12-bit left-aligned data holding register */ +#define DAC0_R8DH REG32(DAC + 0x10U) /*!< DAC0 8-bit right-aligned data holding register */ +#define DAC1_R12DH REG32(DAC + 0x14U) /*!< DAC1 12-bit right-aligned data holding register */ +#define DAC1_L12DH REG32(DAC + 0x18U) /*!< DAC1 12-bit left-aligned data holding register */ +#define DAC1_R8DH REG32(DAC + 0x1CU) /*!< DAC1 8-bit right-aligned data holding register */ +#define DACC_R12DH REG32(DAC + 0x20U) /*!< DAC concurrent mode 12-bit right-aligned data holding register */ +#define DACC_L12DH REG32(DAC + 0x24U) /*!< DAC concurrent mode 12-bit left-aligned data holding register */ +#define DACC_R8DH REG32(DAC + 0x28U) /*!< DAC concurrent mode 8-bit right-aligned data holding register */ +#define DAC0_DO REG32(DAC + 0x2CU) /*!< DAC0 data output register */ +#define DAC1_DO REG32(DAC + 0x30U) /*!< DAC1 data output register */ + +/* bits definitions */ +/* DAC_CTL */ +#define DAC_CTL_DEN0 BIT(0) /*!< DAC0 enable/disable bit */ +#define DAC_CTL_DBOFF0 BIT(1) /*!< DAC0 output buffer turn on/off bit */ +#define DAC_CTL_DTEN0 BIT(2) /*!< DAC0 trigger enable/disable bit */ +#define DAC_CTL_DTSEL0 BITS(3,5) /*!< DAC0 trigger source selection enable/disable bits */ +#define DAC_CTL_DWM0 BITS(6,7) /*!< DAC0 noise wave mode */ +#define DAC_CTL_DWBW0 BITS(8,11) /*!< DAC0 noise wave bit width */ +#define DAC_CTL_DDMAEN0 BIT(12) /*!< DAC0 DMA enable/disable bit */ +#define DAC_CTL_DEN1 BIT(16) /*!< DAC1 enable/disable bit */ +#define DAC_CTL_DBOFF1 BIT(17) /*!< DAC1 output buffer turn on/turn off bit */ +#define DAC_CTL_DTEN1 BIT(18) /*!< DAC1 trigger enable/disable bit */ +#define DAC_CTL_DTSEL1 BITS(19,21) /*!< DAC1 trigger source selection enable/disable bits */ +#define DAC_CTL_DWM1 BITS(22,23) /*!< DAC1 noise wave mode */ +#define DAC_CTL_DWBW1 BITS(24,27) /*!< DAC1 noise wave bit width */ +#define DAC_CTL_DDMAEN1 BIT(28) /*!< DAC1 DMA enable/disable bit */ + +/* DAC_SWT */ +#define DAC_SWT_SWTR0 BIT(0) /*!< DAC0 software trigger bit, cleared by hardware */ +#define DAC_SWT_SWTR1 BIT(1) /*!< DAC1 software trigger bit, cleared by hardware */ + +/* DAC0_R12DH */ +#define DAC0_R12DH_DAC0_DH BITS(0,11) /*!< DAC0 12-bit right-aligned data bits */ + +/* DAC0_L12DH */ +#define DAC0_L12DH_DAC0_DH BITS(4,15) /*!< DAC0 12-bit left-aligned data bits */ + +/* DAC0_R8DH */ +#define DAC0_R8DH_DAC0_DH BITS(0,7) /*!< DAC0 8-bit right-aligned data bits */ + +/* DAC1_R12DH */ +#define DAC1_R12DH_DAC1_DH BITS(0,11) /*!< DAC1 12-bit right-aligned data bits */ + +/* DAC1_L12DH */ +#define DAC1_L12DH_DAC1_DH BITS(4,15) /*!< DAC1 12-bit left-aligned data bits */ + +/* DAC1_R8DH */ +#define DAC1_R8DH_DAC1_DH BITS(0,7) /*!< DAC1 8-bit right-aligned data bits */ + +/* DACC_R12DH */ +#define DACC_R12DH_DAC0_DH BITS(0,11) /*!< DAC concurrent mode DAC0 12-bit right-aligned data bits */ +#define DACC_R12DH_DAC1_DH BITS(16,27) /*!< DAC concurrent mode DAC1 12-bit right-aligned data bits */ + +/* DACC_L12DH */ +#define DACC_L12DH_DAC0_DH BITS(4,15) /*!< DAC concurrent mode DAC0 12-bit left-aligned data bits */ +#define DACC_L12DH_DAC1_DH BITS(20,31) /*!< DAC concurrent mode DAC1 12-bit left-aligned data bits */ + +/* DACC_R8DH */ +#define DACC_R8DH_DAC0_DH BITS(0,7) /*!< DAC concurrent mode DAC0 8-bit right-aligned data bits */ +#define DACC_R8DH_DAC1_DH BITS(8,15) /*!< DAC concurrent mode DAC1 8-bit right-aligned data bits */ + +/* DAC0_DO */ +#define DAC0_DO_DAC0_DO BITS(0,11) /*!< DAC0 12-bit output data bits */ + +/* DAC1_DO */ +#define DAC1_DO_DAC1_DO BITS(0,11) /*!< DAC1 12-bit output data bits */ + +/* constants definitions */ +/* DAC trigger source */ +#define CTL_DTSEL(regval) (BITS(3,5) & ((uint32_t)(regval) << 3)) +#define DAC_TRIGGER_T5_TRGO CTL_DTSEL(0) /*!< TIMER5 TRGO */ +#if (defined(GD32F10X_MD) || defined(GD32F10X_HD) || defined(GD32F10X_XD)) +#define DAC_TRIGGER_T7_TRGO CTL_DTSEL(1) /*!< TIMER7 TRGO */ +#elif defined(GD32F10X_CL) +#define DAC_TRIGGER_T2_TRGO CTL_DTSEL(1) /*!< TIMER2 TRGO */ +#endif /* GD32F10X_MD and GD32F10X_HD and GD32F10X_XD */ +#define DAC_TRIGGER_T6_TRGO CTL_DTSEL(2) /*!< TIMER6 TRGO */ +#define DAC_TRIGGER_T4_TRGO CTL_DTSEL(3) /*!< TIMER4 TRGO */ +#define DAC_TRIGGER_T1_TRGO CTL_DTSEL(4) /*!< TIMER1 TRGO */ +#define DAC_TRIGGER_T3_TRGO CTL_DTSEL(5) /*!< TIMER3 TRGO */ +#define DAC_TRIGGER_EXTI_9 CTL_DTSEL(6) /*!< EXTI interrupt line9 event */ +#define DAC_TRIGGER_SOFTWARE CTL_DTSEL(7) /*!< software trigger */ + +/* DAC noise wave mode */ +#define CTL_DWM(regval) (BITS(6,7) & ((uint32_t)(regval) << 6)) +#define DAC_WAVE_DISABLE CTL_DWM(0) /*!< wave disable */ +#define DAC_WAVE_MODE_LFSR CTL_DWM(1) /*!< LFSR noise mode */ +#define DAC_WAVE_MODE_TRIANGLE CTL_DWM(2) /*!< triangle noise mode */ + +/* DAC noise wave bit width */ +#define DWBW(regval) (BITS(8,11) & ((uint32_t)(regval) << 8)) +#define DAC_WAVE_BIT_WIDTH_1 DWBW(0) /*!< bit width of the wave signal is 1 */ +#define DAC_WAVE_BIT_WIDTH_2 DWBW(1) /*!< bit width of the wave signal is 2 */ +#define DAC_WAVE_BIT_WIDTH_3 DWBW(2) /*!< bit width of the wave signal is 3 */ +#define DAC_WAVE_BIT_WIDTH_4 DWBW(3) /*!< bit width of the wave signal is 4 */ +#define DAC_WAVE_BIT_WIDTH_5 DWBW(4) /*!< bit width of the wave signal is 5 */ +#define DAC_WAVE_BIT_WIDTH_6 DWBW(5) /*!< bit width of the wave signal is 6 */ +#define DAC_WAVE_BIT_WIDTH_7 DWBW(6) /*!< bit width of the wave signal is 7 */ +#define DAC_WAVE_BIT_WIDTH_8 DWBW(7) /*!< bit width of the wave signal is 8 */ +#define DAC_WAVE_BIT_WIDTH_9 DWBW(8) /*!< bit width of the wave signal is 9 */ +#define DAC_WAVE_BIT_WIDTH_10 DWBW(9) /*!< bit width of the wave signal is 10 */ +#define DAC_WAVE_BIT_WIDTH_11 DWBW(10) /*!< bit width of the wave signal is 11 */ +#define DAC_WAVE_BIT_WIDTH_12 DWBW(11) /*!< bit width of the wave signal is 12 */ + +/* unmask LFSR bits in DAC LFSR noise mode */ +#define DAC_LFSR_BIT0 DAC_WAVE_BIT_WIDTH_1 /*!< unmask the LFSR bit0 */ +#define DAC_LFSR_BITS1_0 DAC_WAVE_BIT_WIDTH_2 /*!< unmask the LFSR bits[1:0] */ +#define DAC_LFSR_BITS2_0 DAC_WAVE_BIT_WIDTH_3 /*!< unmask the LFSR bits[2:0] */ +#define DAC_LFSR_BITS3_0 DAC_WAVE_BIT_WIDTH_4 /*!< unmask the LFSR bits[3:0] */ +#define DAC_LFSR_BITS4_0 DAC_WAVE_BIT_WIDTH_5 /*!< unmask the LFSR bits[4:0] */ +#define DAC_LFSR_BITS5_0 DAC_WAVE_BIT_WIDTH_6 /*!< unmask the LFSR bits[5:0] */ +#define DAC_LFSR_BITS6_0 DAC_WAVE_BIT_WIDTH_7 /*!< unmask the LFSR bits[6:0] */ +#define DAC_LFSR_BITS7_0 DAC_WAVE_BIT_WIDTH_8 /*!< unmask the LFSR bits[7:0] */ +#define DAC_LFSR_BITS8_0 DAC_WAVE_BIT_WIDTH_9 /*!< unmask the LFSR bits[8:0] */ +#define DAC_LFSR_BITS9_0 DAC_WAVE_BIT_WIDTH_10 /*!< unmask the LFSR bits[9:0] */ +#define DAC_LFSR_BITS10_0 DAC_WAVE_BIT_WIDTH_11 /*!< unmask the LFSR bits[10:0] */ +#define DAC_LFSR_BITS11_0 DAC_WAVE_BIT_WIDTH_12 /*!< unmask the LFSR bits[11:0] */ + +/* DAC data alignment */ +#define DATA_ALIGN(regval) (BITS(0,1) & ((uint32_t)(regval) << 0)) +#define DAC_ALIGN_12B_R DATA_ALIGN(0) /*!< data right 12b alignment */ +#define DAC_ALIGN_12B_L DATA_ALIGN(1) /*!< data left 12b alignment */ +#define DAC_ALIGN_8B_R DATA_ALIGN(2) /*!< data right 8b alignment */ +/* triangle amplitude in DAC triangle noise mode */ +#define DAC_TRIANGLE_AMPLITUDE_1 DAC_WAVE_BIT_WIDTH_1 /*!< triangle amplitude is 1 */ +#define DAC_TRIANGLE_AMPLITUDE_3 DAC_WAVE_BIT_WIDTH_2 /*!< triangle amplitude is 3 */ +#define DAC_TRIANGLE_AMPLITUDE_7 DAC_WAVE_BIT_WIDTH_3 /*!< triangle amplitude is 7 */ +#define DAC_TRIANGLE_AMPLITUDE_15 DAC_WAVE_BIT_WIDTH_4 /*!< triangle amplitude is 15 */ +#define DAC_TRIANGLE_AMPLITUDE_31 DAC_WAVE_BIT_WIDTH_5 /*!< triangle amplitude is 31 */ +#define DAC_TRIANGLE_AMPLITUDE_63 DAC_WAVE_BIT_WIDTH_6 /*!< triangle amplitude is 63 */ +#define DAC_TRIANGLE_AMPLITUDE_127 DAC_WAVE_BIT_WIDTH_7 /*!< triangle amplitude is 127 */ +#define DAC_TRIANGLE_AMPLITUDE_255 DAC_WAVE_BIT_WIDTH_8 /*!< triangle amplitude is 255 */ +#define DAC_TRIANGLE_AMPLITUDE_511 DAC_WAVE_BIT_WIDTH_9 /*!< triangle amplitude is 511 */ +#define DAC_TRIANGLE_AMPLITUDE_1023 DAC_WAVE_BIT_WIDTH_10 /*!< triangle amplitude is 1023 */ +#define DAC_TRIANGLE_AMPLITUDE_2047 DAC_WAVE_BIT_WIDTH_11 /*!< triangle amplitude is 2047 */ +#define DAC_TRIANGLE_AMPLITUDE_4095 DAC_WAVE_BIT_WIDTH_12 /*!< triangle amplitude is 4095 */ + +/* function declarations */ +/* initialization functions */ +/* deinitialize DAC */ +void dac_deinit(void); +/* enable DAC */ +void dac_enable(uint32_t dac_periph); +/* disable DAC */ +void dac_disable(uint32_t dac_periph); +/* enable DAC DMA */ +void dac_dma_enable(uint32_t dac_periph); +/* disable DAC DMA */ +void dac_dma_disable(uint32_t dac_periph); +/* enable DAC output buffer */ +void dac_output_buffer_enable(uint32_t dac_periph); +/* disable DAC output buffer */ +void dac_output_buffer_disable(uint32_t dac_periph); +/* get the last data output value */ +uint16_t dac_output_value_get(uint32_t dac_periph); +/* set DAC data holding register value */ +void dac_data_set(uint32_t dac_periph, uint32_t dac_align, uint16_t data); + +/* DAC trigger configuration */ +/* enable DAC trigger */ +void dac_trigger_enable(uint32_t dac_periph); +/* disable DAC trigger */ +void dac_trigger_disable(uint32_t dac_periph); +/* configure DAC trigger source */ +void dac_trigger_source_config(uint32_t dac_periph, uint32_t triggersource); +/* enable DAC software trigger */ +void dac_software_trigger_enable(uint32_t dac_periph); +/* disable DAC software trigger */ +void dac_software_trigger_disable(uint32_t dac_periph); + +/* DAC wave mode configuration */ +/* configure DAC wave mode */ +void dac_wave_mode_config(uint32_t dac_periph, uint32_t wave_mode); +/* configure DAC wave bit width */ +void dac_wave_bit_width_config(uint32_t dac_periph, uint32_t bit_width); +/* configure DAC LFSR noise mode */ +void dac_lfsr_noise_config(uint32_t dac_periph, uint32_t unmask_bits); +/* configure DAC triangle noise mode */ +void dac_triangle_noise_config(uint32_t dac_periph, uint32_t amplitude); + +/* DAC concurrent mode configuration */ +/* enable DAC concurrent mode */ +void dac_concurrent_enable(void); +/* disable DAC concurrent mode */ +void dac_concurrent_disable(void); +/* enable DAC concurrent software trigger */ +void dac_concurrent_software_trigger_enable(void); +/* disable DAC concurrent software trigger */ +void dac_concurrent_software_trigger_disable(void); +/* enable DAC concurrent buffer function */ +void dac_concurrent_output_buffer_enable(void); +/* disable DAC concurrent buffer function */ +void dac_concurrent_output_buffer_disable(void); +/* set DAC concurrent mode data holding register value */ +void dac_concurrent_data_set(uint32_t dac_align, uint16_t data0, uint16_t data1); + +#endif /* GD32F10X_DAC_H */ diff --git a/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_standard_peripheral/Include/gd32f10x_dbg.h b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_standard_peripheral/Include/gd32f10x_dbg.h new file mode 100644 index 0000000000..cf51f0ed06 --- /dev/null +++ b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_standard_peripheral/Include/gd32f10x_dbg.h @@ -0,0 +1,152 @@ +/*! + \file gd32f10x_dbg.h + \brief definitions for the DBG + + \version 2014-12-26, V1.0.0, firmware for GD32F10x + \version 2017-06-20, V2.0.0, firmware for GD32F10x + \version 2018-07-31, V2.1.0, firmware for GD32F10x + \version 2019-07-01, V2.1.1, firmware for GD32F10x + \version 2020-09-30, V2.2.0, firmware for GD32F10x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef GD32F10X_DBG_H +#define GD32F10X_DBG_H + +#include "gd32f10x.h" + +/* DBG definitions */ +#define DBG DBG_BASE + +/* registers definitions */ +#define DBG_ID REG32(DBG + 0x00U) /*!< DBG_ID code register */ +#define DBG_CTL REG32(DBG + 0x04U) /*!< DBG control register */ + +/* bits definitions */ +/* DBG_ID */ +#define DBG_ID_ID_CODE BITS(0,31) /*!< DBG ID code values */ + +/* DBG_CTL */ +#define DBG_CTL_SLP_HOLD BIT(0) /*!< keep debugger connection during sleep mode */ +#define DBG_CTL_DSLP_HOLD BIT(1) /*!< keep debugger connection during deepsleep mode */ +#define DBG_CTL_STB_HOLD BIT(2) /*!< keep debugger connection during standby mode */ +#define DBG_CTL_TRACE_IOEN BIT(5) /*!< enable trace pin assignment */ +#define DBG_CTL_TRACE_MODE BITS(6,7) /*!< trace pin mode selection */ +#define DBG_CTL_FWDGT_HOLD BIT(8) /*!< debug FWDGT kept when core is halted */ +#define DBG_CTL_WWDGT_HOLD BIT(9) /*!< debug WWDGT kept when core is halted */ +#define DBG_CTL_TIMER0_HOLD BIT(10) /*!< hold TIMER0 counter when core is halted */ +#define DBG_CTL_TIMER1_HOLD BIT(11) /*!< hold TIMER1 counter when core is halted */ +#define DBG_CTL_TIMER2_HOLD BIT(12) /*!< hold TIMER2 counter when core is halted */ +#define DBG_CTL_TIMER3_HOLD BIT(13) /*!< hold TIMER3 counter when core is halted */ +#define DBG_CTL_CAN0_HOLD BIT(14) /*!< debug CAN0 kept when core is halted */ +#define DBG_CTL_I2C0_HOLD BIT(15) /*!< hold I2C0 smbus when core is halted */ +#define DBG_CTL_I2C1_HOLD BIT(16) /*!< hold I2C1 smbus when core is halted */ +#define DBG_CTL_TIMER7_HOLD BIT(17) /*!< hold TIMER7 counter when core is halted */ +#define DBG_CTL_TIMER4_HOLD BIT(18) /*!< hold TIMER4 counter when core is halted */ +#define DBG_CTL_TIMER5_HOLD BIT(19) /*!< hold TIMER5 counter when core is halted */ +#define DBG_CTL_TIMER6_HOLD BIT(20) /*!< hold TIMER6 counter when core is halted */ +#ifdef GD32F10X_CL +#define DBG_CTL_CAN1_HOLD BIT(21) /*!< debug CAN1 kept when core is halted */ +#endif /* GD32F10X_CL */ +#ifdef GD32F10X_XD +#define DBG_CTL_TIMER11_HOLD BIT(25) /*!< hold TIMER11 counter when core is halted */ +#define DBG_CTL_TIMER12_HOLD BIT(26) /*!< hold TIMER12 counter when core is halted */ +#define DBG_CTL_TIMER13_HOLD BIT(27) /*!< hold TIMER13 counter when core is halted */ +#define DBG_CTL_TIMER8_HOLD BIT(28) /*!< hold TIMER8 counter when core is halted */ +#define DBG_CTL_TIMER9_HOLD BIT(29) /*!< hold TIMER9 counter when core is halted */ +#define DBG_CTL_TIMER10_HOLD BIT(30) /*!< hold TIMER10 counter when core is halted */ +#endif /* GD32F10X_XD */ + +/* constants definitions */ +/* debug hold when core is halted */ +typedef enum +{ + DBG_FWDGT_HOLD = BIT(8), /*!< debug FWDGT kept when core is halted */ + DBG_WWDGT_HOLD = BIT(9), /*!< debug WWDGT kept when core is halted */ + DBG_TIMER0_HOLD = BIT(10), /*!< hold TIMER0 counter when core is halted */ + DBG_TIMER1_HOLD = BIT(11), /*!< hold TIMER1 counter when core is halted */ + DBG_TIMER2_HOLD = BIT(12), /*!< hold TIMER2 counter when core is halted */ + DBG_TIMER3_HOLD = BIT(13), /*!< hold TIMER3 counter when core is halted */ + DBG_CAN0_HOLD = BIT(14), /*!< debug CAN0 kept when core is halted */ + DBG_I2C0_HOLD = BIT(15), /*!< hold I2C0 smbus when core is halted */ + DBG_I2C1_HOLD = BIT(16), /*!< hold I2C1 smbus when core is halted */ + DBG_TIMER7_HOLD = BIT(17), /*!< hold TIMER7 counter when core is halted */ + DBG_TIMER4_HOLD = BIT(18), /*!< hold TIMER4 counter when core is halted */ + DBG_TIMER5_HOLD = BIT(19), /*!< hold TIMER5 counter when core is halted */ + DBG_TIMER6_HOLD = BIT(20), /*!< hold TIMER6 counter when core is halted */ +#ifdef GD32F10X_CL + DBG_CAN1_HOLD = BIT(21), /*!< debug CAN1 kept when core is halted */ +#endif /* GD32F10X_CL */ +#if (defined(GD32F10X_XD) || defined(GD32F10X_CL)) + DBG_TIMER11_HOLD = BIT(25), /*!< hold TIMER11 counter when core is halted */ + DBG_TIMER12_HOLD = BIT(26), /*!< hold TIMER12 counter when core is halted */ + DBG_TIMER13_HOLD = BIT(27), /*!< hold TIMER13 counter when core is halted */ + DBG_TIMER8_HOLD = BIT(28), /*!< hold TIMER8 counter when core is halted */ + DBG_TIMER9_HOLD = BIT(29), /*!< hold TIMER9 counter when core is halted */ + DBG_TIMER10_HOLD = BIT(30), /*!< hold TIMER10 counter when core is halted */ +#endif /* GD32F10X_XD || GD32F10X_CL*/ +}dbg_periph_enum; + +/* DBG low power mode configurations */ +#define DBG_LOW_POWER_SLEEP DBG_CTL_SLP_HOLD /*!< keep debugger connection during sleep mode */ +#define DBG_LOW_POWER_DEEPSLEEP DBG_CTL_DSLP_HOLD /*!< keep debugger connection during deepsleep mode */ +#define DBG_LOW_POWER_STANDBY DBG_CTL_STB_HOLD /*!< keep debugger connection during standby mode */ + +/* DBG_CTL0_TRACE_MODE configurations */ +#define CTL_TRACE_MODE(regval) (BITS(6,7) & ((uint32_t)(regval) << 6U)) +#define TRACE_MODE_ASYNC CTL_TRACE_MODE(0) /*!< trace pin used for async mode */ +#define TRACE_MODE_SYNC_DATASIZE_1 CTL_TRACE_MODE(1) /*!< trace pin used for sync mode and data size is 1 */ +#define TRACE_MODE_SYNC_DATASIZE_2 CTL_TRACE_MODE(2) /*!< trace pin used for sync mode and data size is 2 */ +#define TRACE_MODE_SYNC_DATASIZE_4 CTL_TRACE_MODE(3) /*!< trace pin used for sync mode and data size is 4 */ + +/* function declarations */ +/* read DBG_ID code register */ +uint32_t dbg_id_get(void); + +/* low power behavior configuration */ +/* enable low power behavior when the MCU is in debug mode */ +void dbg_low_power_enable(uint32_t dbg_low_power); +/* disable low power behavior when the MCU is in debug mode */ +void dbg_low_power_disable(uint32_t dbg_low_power); + +/* peripheral behavior configuration */ +/* enable peripheral behavior when the MCU is in debug mode */ +void dbg_periph_enable(dbg_periph_enum dbg_periph); +/* disable peripheral behavior when the MCU is in debug mode */ +void dbg_periph_disable(dbg_periph_enum dbg_periph); + +/* trace pin assignment configuration */ +/* enable trace pin assignment */ +void dbg_trace_pin_enable(void); +/* disable trace pin assignment */ +void dbg_trace_pin_disable(void); +/* set trace pin mode */ +void dbg_trace_pin_mode_set(uint32_t trace_mode); + +#endif /* GD32F10X_DBG_H */ diff --git a/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_standard_peripheral/Include/gd32f10x_dma.h b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_standard_peripheral/Include/gd32f10x_dma.h new file mode 100644 index 0000000000..a183117fe8 --- /dev/null +++ b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_standard_peripheral/Include/gd32f10x_dma.h @@ -0,0 +1,289 @@ +/*! + \file gd32f10x_dma.h + \brief definitions for the DMA + + \version 2014-12-26, V1.0.0, firmware for GD32F10x + \version 2017-06-20, V2.0.0, firmware for GD32F10x + \version 2018-07-31, V2.1.0, firmware for GD32F10x + \version 2019-10-30, V2.1.1, firmware for GD32F10x + \version 2020-09-30, V2.2.0, firmware for GD32F10x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef GD32F10X_DMA_H +#define GD32F10X_DMA_H + +#include "gd32f10x.h" + +/* DMA definitions */ +#define DMA0 (DMA_BASE) /*!< DMA0 base address */ +#define DMA1 (DMA_BASE + 0x0400U) /*!< DMA1 base address */ + +/* registers definitions */ +#define DMA_INTF(dmax) REG32((dmax) + 0x00U) /*!< DMA interrupt flag register */ +#define DMA_INTC(dmax) REG32((dmax) + 0x04U) /*!< DMA interrupt flag clear register */ + +#define DMA_CH0CTL(dmax) REG32((dmax) + 0x08U) /*!< DMA channel 0 control register */ +#define DMA_CH0CNT(dmax) REG32((dmax) + 0x0CU) /*!< DMA channel 0 counter register */ +#define DMA_CH0PADDR(dmax) REG32((dmax) + 0x10U) /*!< DMA channel 0 peripheral base address register */ +#define DMA_CH0MADDR(dmax) REG32((dmax) + 0x14U) /*!< DMA channel 0 memory base address register */ + +#define DMA_CH1CTL(dmax) REG32((dmax) + 0x1CU) /*!< DMA channel 1 control register */ +#define DMA_CH1CNT(dmax) REG32((dmax) + 0x20U) /*!< DMA channel 1 counter register */ +#define DMA_CH1PADDR(dmax) REG32((dmax) + 0x24U) /*!< DMA channel 1 peripheral base address register */ +#define DMA_CH1MADDR(dmax) REG32((dmax) + 0x28U) /*!< DMA channel 1 memory base address register */ + +#define DMA_CH2CTL(dmax) REG32((dmax) + 0x30U) /*!< DMA channel 2 control register */ +#define DMA_CH2CNT(dmax) REG32((dmax) + 0x34U) /*!< DMA channel 2 counter register */ +#define DMA_CH2PADDR(dmax) REG32((dmax) + 0x38U) /*!< DMA channel 2 peripheral base address register */ +#define DMA_CH2MADDR(dmax) REG32((dmax) + 0x3CU) /*!< DMA channel 2 memory base address register */ + +#define DMA_CH3CTL(dmax) REG32((dmax) + 0x44U) /*!< DMA channel 3 control register */ +#define DMA_CH3CNT(dmax) REG32((dmax) + 0x48U) /*!< DMA channel 3 counter register */ +#define DMA_CH3PADDR(dmax) REG32((dmax) + 0x4CU) /*!< DMA channel 3 peripheral base address register */ +#define DMA_CH3MADDR(dmax) REG32((dmax) + 0x50U) /*!< DMA channel 3 memory base address register */ + +#define DMA_CH4CTL(dmax) REG32((dmax) + 0x58U) /*!< DMA channel 4 control register */ +#define DMA_CH4CNT(dmax) REG32((dmax) + 0x5CU) /*!< DMA channel 4 counter register */ +#define DMA_CH4PADDR(dmax) REG32((dmax) + 0x60U) /*!< DMA channel 4 peripheral base address register */ +#define DMA_CH4MADDR(dmax) REG32((dmax) + 0x64U) /*!< DMA channel 4 memory base address register */ + +#define DMA_CH5CTL(dmax) REG32((dmax) + 0x6CU) /*!< DMA channel 5 control register */ +#define DMA_CH5CNT(dmax) REG32((dmax) + 0x70U) /*!< DMA channel 5 counter register */ +#define DMA_CH5PADDR(dmax) REG32((dmax) + 0x74U) /*!< DMA channel 5 peripheral base address register */ +#define DMA_CH5MADDR(dmax) REG32((dmax) + 0x78U) /*!< DMA channel 5 memory base address register */ + +#define DMA_CH6CTL(dmax) REG32((dmax) + 0x80U) /*!< DMA channel 6 control register */ +#define DMA_CH6CNT(dmax) REG32((dmax) + 0x84U) /*!< DMA channel 6 counter register */ +#define DMA_CH6PADDR(dmax) REG32((dmax) + 0x88U) /*!< DMA channel 6 peripheral base address register */ +#define DMA_CH6MADDR(dmax) REG32((dmax) + 0x8CU) /*!< DMA channel 6 memory base address register */ + +/* bits definitions */ +/* DMA_INTF */ +#define DMA_INTF_GIF BIT(0) /*!< global interrupt flag of channel */ +#define DMA_INTF_FTFIF BIT(1) /*!< full transfer finish flag of channel */ +#define DMA_INTF_HTFIF BIT(2) /*!< half transfer finish flag of channel */ +#define DMA_INTF_ERRIF BIT(3) /*!< error flag of channel */ + +/* DMA_INTC */ +#define DMA_INTC_GIFC BIT(0) /*!< clear global interrupt flag of channel */ +#define DMA_INTC_FTFIFC BIT(1) /*!< clear transfer finish flag of channel */ +#define DMA_INTC_HTFIFC BIT(2) /*!< clear half transfer finish flag of channel */ +#define DMA_INTC_ERRIFC BIT(3) /*!< clear error flag of channel */ + +/* DMA_CHxCTL, x=0..6 */ +#define DMA_CHXCTL_CHEN BIT(0) /*!< channel enable */ +#define DMA_CHXCTL_FTFIE BIT(1) /*!< enable bit for channel full transfer finish interrupt */ +#define DMA_CHXCTL_HTFIE BIT(2) /*!< enable bit for channel half transfer finish interrupt */ +#define DMA_CHXCTL_ERRIE BIT(3) /*!< enable bit for channel error interrupt */ +#define DMA_CHXCTL_DIR BIT(4) /*!< transfer direction */ +#define DMA_CHXCTL_CMEN BIT(5) /*!< circular mode enable */ +#define DMA_CHXCTL_PNAGA BIT(6) /*!< next address generation algorithm of peripheral */ +#define DMA_CHXCTL_MNAGA BIT(7) /*!< next address generation algorithm of memory */ +#define DMA_CHXCTL_PWIDTH BITS(8,9) /*!< transfer data width of peripheral */ +#define DMA_CHXCTL_MWIDTH BITS(10,11) /*!< transfer data width of memory */ +#define DMA_CHXCTL_PRIO BITS(12,13) /*!< priority level */ +#define DMA_CHXCTL_M2M BIT(14) /*!< memory to memory mode */ + +/* DMA_CHxCNT, x=0..6 */ +#define DMA_CHXCNT_CNT BITS(0,15) /*!< transfer counter */ + +/* DMA_CHxPADDR, x=0..6 */ +#define DMA_CHXPADDR_PADDR BITS(0,31) /*!< peripheral base address */ + +/* DMA_CHxMADDR, x=0..6 */ +#define DMA_CHXMADDR_MADDR BITS(0,31) /*!< memory base address */ + +/* constants definitions */ +/* DMA channel select */ +typedef enum +{ + DMA_CH0 = 0, /*!< DMA channel 0 */ + DMA_CH1, /*!< DMA channel 1 */ + DMA_CH2, /*!< DMA channel 2 */ + DMA_CH3, /*!< DMA channel 3 */ + DMA_CH4, /*!< DMA channel 4 */ + DMA_CH5, /*!< DMA channel 5 */ + DMA_CH6 /*!< DMA channel 6 */ +} dma_channel_enum; + +/* DMA initialize struct */ +typedef struct +{ + uint32_t periph_addr; /*!< peripheral base address */ + uint32_t periph_width; /*!< transfer data size of peripheral */ + uint32_t memory_addr; /*!< memory base address */ + uint32_t memory_width; /*!< transfer data size of memory */ + uint32_t number; /*!< channel transfer number */ + uint32_t priority; /*!< channel priority level */ + uint8_t periph_inc; /*!< peripheral increasing mode */ + uint8_t memory_inc; /*!< memory increasing mode */ + uint8_t direction; /*!< channel data transfer direction */ + +} dma_parameter_struct; + +#define DMA_FLAG_ADD(flag, shift) ((flag) << ((shift) * 4U)) /*!< DMA channel flag shift */ + +/* DMA_register address */ +#define DMA_CHCTL(dma, channel) REG32(((dma) + 0x08U) + 0x14U * (uint32_t)(channel)) /*!< the address of DMA channel CHXCTL register */ +#define DMA_CHCNT(dma, channel) REG32(((dma) + 0x0CU) + 0x14U * (uint32_t)(channel)) /*!< the address of DMA channel CHXCNT register */ +#define DMA_CHPADDR(dma, channel) REG32(((dma) + 0x10U) + 0x14U * (uint32_t)(channel)) /*!< the address of DMA channel CHXPADDR register */ +#define DMA_CHMADDR(dma, channel) REG32(((dma) + 0x14U) + 0x14U * (uint32_t)(channel)) /*!< the address of DMA channel CHXMADDR register */ + +/* DMA reset value */ +#define DMA_CHCTL_RESET_VALUE ((uint32_t)0x00000000U) /*!< the reset value of DMA channel CHXCTL register */ +#define DMA_CHCNT_RESET_VALUE ((uint32_t)0x00000000U) /*!< the reset value of DMA channel CHXCNT register */ +#define DMA_CHPADDR_RESET_VALUE ((uint32_t)0x00000000U) /*!< the reset value of DMA channel CHXPADDR register */ +#define DMA_CHMADDR_RESET_VALUE ((uint32_t)0x00000000U) /*!< the reset value of DMA channel CHXMADDR register */ +#define DMA_CHINTF_RESET_VALUE (DMA_INTF_GIF | DMA_INTF_FTFIF | \ + DMA_INTF_HTFIF | DMA_INTF_ERRIF) /*!< clear DMA channel DMA_INTF register */ + +/* DMA_INTF register */ +/* interrupt flag bits */ +#define DMA_INT_FLAG_G DMA_INTF_GIF /*!< global interrupt flag of channel */ +#define DMA_INT_FLAG_FTF DMA_INTF_FTFIF /*!< full transfer finish interrupt flag of channel */ +#define DMA_INT_FLAG_HTF DMA_INTF_HTFIF /*!< half transfer finish interrupt flag of channel */ +#define DMA_INT_FLAG_ERR DMA_INTF_ERRIF /*!< error interrupt flag of channel */ + +/* flag bits */ +#define DMA_FLAG_G DMA_INTF_GIF /*!< global interrupt flag of channel */ +#define DMA_FLAG_FTF DMA_INTF_FTFIF /*!< full transfer finish flag of channel */ +#define DMA_FLAG_HTF DMA_INTF_HTFIF /*!< half transfer finish flag of channel */ +#define DMA_FLAG_ERR DMA_INTF_ERRIF /*!< error flag of channel */ + +/* DMA_CHxCTL register */ +/* interrupt enable bits */ +#define DMA_INT_FTF DMA_CHXCTL_FTFIE /*!< enable bit for channel full transfer finish interrupt */ +#define DMA_INT_HTF DMA_CHXCTL_HTFIE /*!< enable bit for channel half transfer finish interrupt */ +#define DMA_INT_ERR DMA_CHXCTL_ERRIE /*!< enable bit for channel error interrupt */ + +/* transfer direction */ +#define DMA_PERIPHERAL_TO_MEMORY ((uint8_t)0x00U) /*!< read from peripheral and write to memory */ +#define DMA_MEMORY_TO_PERIPHERAL ((uint8_t)0x01U) /*!< read from memory and write to peripheral */ +/* circular mode */ +#define DMA_CIRCULAR_MODE_DISABLE ((uint32_t)0x00000000U) /*!< circular mode disable */ +#define DMA_CIRCULAR_MODE_ENABLE ((uint32_t)0x00000001U) /*!< circular mode enable */ + +/* peripheral increasing mode */ +#define DMA_PERIPH_INCREASE_DISABLE ((uint8_t)0x00U) /*!< next address of peripheral is fixed address mode */ +#define DMA_PERIPH_INCREASE_ENABLE ((uint8_t)0x01U) /*!< next address of peripheral is increasing address mode */ + +/* memory increasing mode */ +#define DMA_MEMORY_INCREASE_DISABLE ((uint8_t)0x00U) /*!< next address of memory is fixed address mode */ +#define DMA_MEMORY_INCREASE_ENABLE ((uint8_t)0x01U) /*!< next address of memory is increasing address mode */ + +/* transfer data size of peripheral */ +#define CHCTL_PWIDTH(regval) (BITS(8,9) & ((regval) << 8)) /*!< transfer data size of peripheral */ +#define DMA_PERIPHERAL_WIDTH_8BIT CHCTL_PWIDTH(0U) /*!< transfer data size of peripheral is 8-bit */ +#define DMA_PERIPHERAL_WIDTH_16BIT CHCTL_PWIDTH(1U) /*!< transfer data size of peripheral is 16-bit */ +#define DMA_PERIPHERAL_WIDTH_32BIT CHCTL_PWIDTH(2U) /*!< transfer data size of peripheral is 32-bit */ + +/* transfer data size of memory */ +#define CHCTL_MWIDTH(regval) (BITS(10,11) & ((regval) << 10)) /*!< transfer data size of memory */ +#define DMA_MEMORY_WIDTH_8BIT CHCTL_MWIDTH(0U) /*!< transfer data size of memory is 8-bit */ +#define DMA_MEMORY_WIDTH_16BIT CHCTL_MWIDTH(1U) /*!< transfer data size of memory is 16-bit */ +#define DMA_MEMORY_WIDTH_32BIT CHCTL_MWIDTH(2U) /*!< transfer data size of memory is 32-bit */ + +/* channel priority level */ +#define CHCTL_PRIO(regval) (BITS(12,13) & ((regval) << 12)) /*!< DMA channel priority level */ +#define DMA_PRIORITY_LOW CHCTL_PRIO(0U) /*!< low priority */ +#define DMA_PRIORITY_MEDIUM CHCTL_PRIO(1U) /*!< medium priority */ +#define DMA_PRIORITY_HIGH CHCTL_PRIO(2U) /*!< high priority */ +#define DMA_PRIORITY_ULTRA_HIGH CHCTL_PRIO(3U) /*!< ultra high priority */ + +/* memory to memory mode */ +#define DMA_MEMORY_TO_MEMORY_DISABLE ((uint32_t)0x00000000U) /*!< disable memory to memory mode */ +#define DMA_MEMORY_TO_MEMORY_ENABLE ((uint32_t)0x00000001U) /*!< enable memory to memory mode */ + +/* DMA_CHxCNT register */ +/* transfer counter */ +#define DMA_CHANNEL_CNT_MASK DMA_CHXCNT_CNT /*!< transfer counter mask */ + +/* function declarations */ +/* DMA deinitialization and initialization functions */ +/* deinitialize DMA a channel registers */ +void dma_deinit(uint32_t dma_periph, dma_channel_enum channelx); +/* initialize the parameters of DMA struct with the default values */ +void dma_struct_para_init(dma_parameter_struct* init_struct); +/* initialize DMA channel */ +void dma_init(uint32_t dma_periph, dma_channel_enum channelx, dma_parameter_struct *init_struct); +/* enable DMA circulation mode */ +void dma_circulation_enable(uint32_t dma_periph, dma_channel_enum channelx); +/* disable DMA circulation mode */ +void dma_circulation_disable(uint32_t dma_periph, dma_channel_enum channelx); +/* enable memory to memory mode */ +void dma_memory_to_memory_enable(uint32_t dma_periph, dma_channel_enum channelx); +/* disable memory to memory mode */ +void dma_memory_to_memory_disable(uint32_t dma_periph, dma_channel_enum channelx); +/* enable DMA channel */ +void dma_channel_enable(uint32_t dma_periph, dma_channel_enum channelx); +/* disable DMA channel */ +void dma_channel_disable(uint32_t dma_periph, dma_channel_enum channelx); + +/* DMA configuration functions */ +/* set DMA peripheral base address */ +void dma_periph_address_config(uint32_t dma_periph, dma_channel_enum channelx, uint32_t address); +/* set DMA memory base address */ +void dma_memory_address_config(uint32_t dma_periph, dma_channel_enum channelx, uint32_t address); +/* set the number of remaining data to be transferred by the DMA */ +void dma_transfer_number_config(uint32_t dma_periph, dma_channel_enum channelx, uint32_t number); +/* get the number of remaining data to be transferred by the DMA */ +uint32_t dma_transfer_number_get(uint32_t dma_periph, dma_channel_enum channelx); +/* configure priority level of DMA channel */ +void dma_priority_config(uint32_t dma_periph, dma_channel_enum channelx, uint32_t priority); +/* configure transfer data size of memory */ +void dma_memory_width_config(uint32_t dma_periph, dma_channel_enum channelx, uint32_t mwidth); +/* configure transfer data size of peripheral */ +void dma_periph_width_config(uint32_t dma_periph, dma_channel_enum channelx, uint32_t pwidth); +/* enable next address increasement algorithm of memory */ +void dma_memory_increase_enable(uint32_t dma_periph, dma_channel_enum channelx); +/* disable next address increasement algorithm of memory */ +void dma_memory_increase_disable(uint32_t dma_periph, dma_channel_enum channelx); +/* enable next address increasement algorithm of peripheral */ +void dma_periph_increase_enable(uint32_t dma_periph, dma_channel_enum channelx); +/* disable next address increasement algorithm of peripheral */ +void dma_periph_increase_disable(uint32_t dma_periph, dma_channel_enum channelx); +/* configure the direction of data transfer on the channel */ +void dma_transfer_direction_config(uint32_t dma_periph, dma_channel_enum channelx, uint8_t direction); + +/* flag and interrupt functions */ +/* check DMA flag is set or not */ +FlagStatus dma_flag_get(uint32_t dma_periph, dma_channel_enum channelx, uint32_t flag); +/* clear the flag of a DMA channel */ +void dma_flag_clear(uint32_t dma_periph, dma_channel_enum channelx, uint32_t flag); +/* check DMA flag and interrupt enable bit is set or not */ +FlagStatus dma_interrupt_flag_get(uint32_t dma_periph, dma_channel_enum channelx, uint32_t flag); +/* clear the interrupt flag of a DMA channel */ +void dma_interrupt_flag_clear(uint32_t dma_periph, dma_channel_enum channelx, uint32_t flag); +/* enable DMA interrupt */ +void dma_interrupt_enable(uint32_t dma_periph, dma_channel_enum channelx, uint32_t source); +/* disable DMA interrupt */ +void dma_interrupt_disable(uint32_t dma_periph, dma_channel_enum channelx, uint32_t source); + +#endif /* GD32F10X_DMA_H */ diff --git a/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_standard_peripheral/Include/gd32f10x_enet.h b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_standard_peripheral/Include/gd32f10x_enet.h new file mode 100644 index 0000000000..3776adb59b --- /dev/null +++ b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_standard_peripheral/Include/gd32f10x_enet.h @@ -0,0 +1,1497 @@ +/*! + \file gd32f10x_enet.h + \brief definitions for the ENET + + \version 2014-12-26, V1.0.0, firmware for GD32F10x + \version 2017-06-20, V2.0.0, firmware for GD32F10x + \version 2018-07-31, V2.1.0, firmware for GD32F10x + \version 2020-09-30, V2.2.0, firmware for GD32F10x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef GD32F10x_ENET_H +#define GD32F10x_ENET_H + +#include "gd32f10x.h" +#include + +#define IF_USE_EXTERNPHY_LIB 0 +#if (1 == IF_USE_EXTERNPHY_LIB) +#include "phy.h" +#endif + +#ifndef ENET_RXBUF_NUM +#define ENET_RXBUF_NUM 5U /*!< ethernet Rx DMA descriptor number */ +#endif + +#ifndef ENET_TXBUF_NUM +#define ENET_TXBUF_NUM 5U /*!< ethernet Tx DMA descriptor number */ +#endif + +#ifndef ENET_RXBUF_SIZE +#define ENET_RXBUF_SIZE ENET_MAX_FRAME_SIZE /*!< ethernet receive buffer size */ +#endif + +#ifndef ENET_TXBUF_SIZE +#define ENET_TXBUF_SIZE ENET_MAX_FRAME_SIZE /*!< ethernet transmit buffer size */ +#endif + +/* #define USE_DELAY */ + +#ifndef _PHY_H_ +#define DP83848 0 +#define LAN8700 1 +#define PHY_TYPE DP83848 + +#define PHY_ADDRESS ((uint16_t)1U) /*!< phy address determined by the hardware */ + +/* PHY read write timeouts */ +#define PHY_READ_TO ((uint32_t)0x0004FFFFU) /*!< PHY read timeout */ +#define PHY_WRITE_TO ((uint32_t)0x0004FFFFU) /*!< PHY write timeout */ + +/* PHY delay */ +#define PHY_RESETDELAY ((uint32_t)0x008FFFFFU) /*!< PHY reset delay */ +#define PHY_CONFIGDELAY ((uint32_t)0x00FFFFFFU) /*!< PHY configure delay */ + +/* PHY register address */ +#define PHY_REG_BCR 0U /*!< tranceiver basic control register */ +#define PHY_REG_BSR 1U /*!< tranceiver basic status register */ + +/* PHY basic control register */ +#define PHY_RESET ((uint16_t)0x8000) /*!< PHY reset */ +#define PHY_LOOPBACK ((uint16_t)0x4000) /*!< enable phy loop-back mode */ +#define PHY_FULLDUPLEX_100M ((uint16_t)0x2100) /*!< configure speed to 100 Mbit/s and the full-duplex mode */ +#define PHY_HALFDUPLEX_100M ((uint16_t)0x2000) /*!< configure speed to 100 Mbit/s and the half-duplex mode */ +#define PHY_FULLDUPLEX_10M ((uint16_t)0x0100) /*!< configure speed to 10 Mbit/s and the full-duplex mode */ +#define PHY_HALFDUPLEX_10M ((uint16_t)0x0000) /*!< configure speed to 10 Mbit/s and the half-duplex mode */ +#define PHY_AUTONEGOTIATION ((uint16_t)0x1000) /*!< enable auto-negotiation function */ +#define PHY_RESTART_AUTONEGOTIATION ((uint16_t)0x0200) /*!< restart auto-negotiation function */ +#define PHY_POWERDOWN ((uint16_t)0x0800) /*!< enable the power down mode */ +#define PHY_ISOLATE ((uint16_t)0x0400) /*!< isolate PHY from MII */ + +/* PHY basic status register */ +#define PHY_AUTONEGO_COMPLETE ((uint16_t)0x0020) /*!< auto-negotioation process completed */ +#define PHY_LINKED_STATUS ((uint16_t)0x0004) /*!< valid link established */ +#define PHY_JABBER_DETECTION ((uint16_t)0x0002) /*!< jabber condition detected */ + +#if(PHY_TYPE == LAN8700) +#define PHY_SR 31U /*!< tranceiver status register */ +#define PHY_SPEED_STATUS ((uint16_t)0x0004) /*!< configured information of speed: 10Mbit/s */ +#define PHY_DUPLEX_STATUS ((uint16_t)0x0010) /*!< configured information of duplex: full-duplex */ +#elif(PHY_TYPE == DP83848) +#define PHY_SR 16U /*!< tranceiver status register */ +#define PHY_SPEED_STATUS ((uint16_t)0x0002) /*!< configured information of speed: 10Mbit/s */ +#define PHY_DUPLEX_STATUS ((uint16_t)0x0004) /*!< configured information of duplex: full-duplex */ +#endif /* PHY_TYPE */ + +#endif /* _PHY_H_ */ + + +/* ENET definitions */ +#define ENET ENET_BASE + +/* registers definitions */ +#define ENET_MAC_CFG REG32((ENET) + 0x00U) /*!< ethernet MAC configuration register */ +#define ENET_MAC_FRMF REG32((ENET) + 0x04U) /*!< ethernet MAC frame filter register */ +#define ENET_MAC_HLH REG32((ENET) + 0x08U) /*!< ethernet MAC hash list high register */ +#define ENET_MAC_HLL REG32((ENET) + 0x0CU) /*!< ethernet MAC hash list low register */ +#define ENET_MAC_PHY_CTL REG32((ENET) + 0x10U) /*!< ethernet MAC PHY control register */ +#define ENET_MAC_PHY_DATA REG32((ENET) + 0x14U) /*!< ethernet MAC MII data register */ +#define ENET_MAC_FCTL REG32((ENET) + 0x18U) /*!< ethernet MAC flow control register */ +#define ENET_MAC_FCTH REG32((ENET) + 0x1080U) /*!< ethernet MAC flow control threshold register */ +#define ENET_MAC_VLT REG32((ENET) + 0x1CU) /*!< ethernet MAC VLAN tag register */ +#define ENET_MAC_RWFF REG32((ENET) + 0x28U) /*!< ethernet MAC remote wakeup frame filter register */ +#define ENET_MAC_WUM REG32((ENET) + 0x2CU) /*!< ethernet MAC wakeup management register */ +#define ENET_MAC_INTF REG32((ENET) + 0x38U) /*!< ethernet MAC interrupt flag register */ +#define ENET_MAC_INTMSK REG32((ENET) + 0x3CU) /*!< ethernet MAC interrupt mask register */ +#define ENET_MAC_ADDR0H REG32((ENET) + 0x40U) /*!< ethernet MAC address 0 high register */ +#define ENET_MAC_ADDR0L REG32((ENET) + 0x44U) /*!< ethernet MAC address 0 low register */ +#define ENET_MAC_ADDR1H REG32((ENET) + 0x48U) /*!< ethernet MAC address 1 high register */ +#define ENET_MAC_ADDR1L REG32((ENET) + 0x4CU) /*!< ethernet MAC address 1 low register */ +#define ENET_MAC_ADDT2H REG32((ENET) + 0x50U) /*!< ethernet MAC address 2 high register */ +#define ENET_MAC_ADDR2L REG32((ENET) + 0x54U) /*!< ethernet MAC address 2 low register */ +#define ENET_MAC_ADDR3H REG32((ENET) + 0x58U) /*!< ethernet MAC address 3 high register */ +#define ENET_MAC_ADDR3L REG32((ENET) + 0x5CU) /*!< ethernet MAC address 3 low register */ + +#define ENET_MSC_CTL REG32((ENET) + 0x100U) /*!< ethernet MSC control register */ +#define ENET_MSC_RINTF REG32((ENET) + 0x104U) /*!< ethernet MSC receive interrupt flag register */ +#define ENET_MSC_TINTF REG32((ENET) + 0x108U) /*!< ethernet MSC transmit interrupt flag register */ +#define ENET_MSC_RINTMSK REG32((ENET) + 0x10CU) /*!< ethernet MSC receive interrupt mask register */ +#define ENET_MSC_TINTMSK REG32((ENET) + 0x110U) /*!< ethernet MSC transmit interrupt mask register */ +#define ENET_MSC_SCCNT REG32((ENET) + 0x14CU) /*!< ethernet MSC transmitted good frames after a single collision counter register */ +#define ENET_MSC_MSCCNT REG32((ENET) + 0x150U) /*!< ethernet MSC transmitted good frames after more than a single collision counter register */ +#define ENET_MSC_TGFCNT REG32((ENET) + 0x168U) /*!< ethernet MSC transmitted good frames counter register */ +#define ENET_MSC_RFCECNT REG32((ENET) + 0x194U) /*!< ethernet MSC received frames with CRC error counter register */ +#define ENET_MSC_RFAECNT REG32((ENET) + 0x198U) /*!< ethernet MSC received frames with alignment error counter register */ +#define ENET_MSC_RGUFCNT REG32((ENET) + 0x1C4U) /*!< ethernet MSC received good unicast frames counter register */ + +#define ENET_PTP_TSCTL REG32((ENET) + 0x700U) /*!< ethernet PTP time stamp control register */ +#define ENET_PTP_SSINC REG32((ENET) + 0x704U) /*!< ethernet PTP subsecond increment register */ +#define ENET_PTP_TSH REG32((ENET) + 0x708U) /*!< ethernet PTP time stamp high register */ +#define ENET_PTP_TSL REG32((ENET) + 0x70CU) /*!< ethernet PTP time stamp low register */ +#define ENET_PTP_TSUH REG32((ENET) + 0x710U) /*!< ethernet PTP time stamp update high register */ +#define ENET_PTP_TSUL REG32((ENET) + 0x714U) /*!< ethernet PTP time stamp update low register */ +#define ENET_PTP_TSADDEND REG32((ENET) + 0x718U) /*!< ethernet PTP time stamp addend register */ +#define ENET_PTP_ETH REG32((ENET) + 0x71CU) /*!< ethernet PTP expected time high register */ +#define ENET_PTP_ETL REG32((ENET) + 0x720U) /*!< ethernet PTP expected time low register */ + +#define ENET_DMA_BCTL REG32((ENET) + 0x1000U) /*!< ethernet DMA bus control register */ +#define ENET_DMA_TPEN REG32((ENET) + 0x1004U) /*!< ethernet DMA transmit poll enable register */ +#define ENET_DMA_RPEN REG32((ENET) + 0x1008U) /*!< ethernet DMA receive poll enable register */ +#define ENET_DMA_RDTADDR REG32((ENET) + 0x100CU) /*!< ethernet DMA receive descriptor table address register */ +#define ENET_DMA_TDTADDR REG32((ENET) + 0x1010U) /*!< ethernet DMA transmit descriptor table address register */ +#define ENET_DMA_STAT REG32((ENET) + 0x1014U) /*!< ethernet DMA status register */ +#define ENET_DMA_CTL REG32((ENET) + 0x1018U) /*!< ethernet DMA control register */ +#define ENET_DMA_INTEN REG32((ENET) + 0x101CU) /*!< ethernet DMA interrupt enable register */ +#define ENET_DMA_MFBOCNT REG32((ENET) + 0x1020U) /*!< ethernet DMA missed frame and buffer overflow counter register */ +#define ENET_DMA_CTDADDR REG32((ENET) + 0x1048U) /*!< ethernet DMA current transmit descriptor address register */ +#define ENET_DMA_CRDADDR REG32((ENET) + 0x104CU) /*!< ethernet DMA current receive descriptor address register */ +#define ENET_DMA_CTBADDR REG32((ENET) + 0x1050U) /*!< ethernet DMA current transmit buffer address register */ +#define ENET_DMA_CRBADDR REG32((ENET) + 0x1054U) /*!< ethernet DMA current receive buffer address register */ + +/* bits definitions */ +/* ENET_MAC_CFG */ +#define ENET_MAC_CFG_REN BIT(2) /*!< receiver enable */ +#define ENET_MAC_CFG_TEN BIT(3) /*!< transmitter enable */ +#define ENET_MAC_CFG_DFC BIT(4) /*!< defferal check */ +#define ENET_MAC_CFG_BOL BITS(5,6) /*!< back-off limit */ +#define ENET_MAC_CFG_APCD BIT(7) /*!< automatic pad/CRC drop */ +#define ENET_MAC_CFG_RTD BIT(9) /*!< retry disable */ +#define ENET_MAC_CFG_IPFCO BIT(10) /*!< IP frame checksum offload */ +#define ENET_MAC_CFG_DPM BIT(11) /*!< duplex mode */ +#define ENET_MAC_CFG_LBM BIT(12) /*!< loopback mode */ +#define ENET_MAC_CFG_ROD BIT(13) /*!< receive own disable */ +#define ENET_MAC_CFG_SPD BIT(14) /*!< fast eneternet speed */ +#define ENET_MAC_CFG_CSD BIT(16) /*!< carrier sense disable */ +#define ENET_MAC_CFG_IGBS BITS(17,19) /*!< inter-frame gap bit selection */ +#define ENET_MAC_CFG_JBD BIT(22) /*!< jabber disable */ +#define ENET_MAC_CFG_WDD BIT(23) /*!< watchdog disable */ + +/* ENET_MAC_FRMF */ +#define ENET_MAC_FRMF_PM BIT(0) /*!< promiscuous mode */ +#define ENET_MAC_FRMF_HUF BIT(1) /*!< hash unicast filter */ +#define ENET_MAC_FRMF_HMF BIT(2) /*!< hash multicast filter */ +#define ENET_MAC_FRMF_DAIFLT BIT(3) /*!< destination address inverse filtering enable */ +#define ENET_MAC_FRMF_MFD BIT(4) /*!< multicast filter disable */ +#define ENET_MAC_FRMF_BFRMD BIT(5) /*!< broadcast frame disable */ +#define ENET_MAC_FRMF_PCFRM BITS(6,7) /*!< pass control frames */ +#define ENET_MAC_FRMF_SAIFLT BIT(8) /*!< source address inverse filtering */ +#define ENET_MAC_FRMF_SAFLT BIT(9) /*!< source address filter */ +#define ENET_MAC_FRMF_HPFLT BIT(10) /*!< hash or perfect filter */ +#define ENET_MAC_FRMF_FAR BIT(31) /*!< frames all receive */ + +/* ENET_MAC_HLH */ +#define ENET_MAC_HLH_HLH BITS(0,31) /*!< hash list high */ + +/* ENET_MAC_HLL */ +#define ENET_MAC_HLL_HLL BITS(0,31) /*!< hash list low */ + +/* ENET_MAC_PHY_CTL */ +#define ENET_MAC_PHY_CTL_PB BIT(0) /*!< PHY busy */ +#define ENET_MAC_PHY_CTL_PW BIT(1) /*!< PHY write */ +#define ENET_MAC_PHY_CTL_CLR BITS(2,4) /*!< clock range */ +#define ENET_MAC_PHY_CTL_PR BITS(6,10) /*!< PHY register */ +#define ENET_MAC_PHY_CTL_PA BITS(11,15) /*!< PHY address */ + +/* ENET_MAC_PHY_DATA */ +#define ENET_MAC_PHY_DATA_PD BITS(0,15) /*!< PHY data */ + +/* ENET_MAC_FCTL */ +#define ENET_MAC_FCTL_FLCBBKPA BIT(0) /*!< flow control busy(in full duplex mode)/backpressure activate(in half duplex mode) */ +#define ENET_MAC_FCTL_TFCEN BIT(1) /*!< transmit flow control enable */ +#define ENET_MAC_FCTL_RFCEN BIT(2) /*!< receive flow control enable */ +#define ENET_MAC_FCTL_UPFDT BIT(3) /*!< unicast pause frame detect */ +#define ENET_MAC_FCTL_PLTS BITS(4,5) /*!< pause low threshold */ +#define ENET_MAC_FCTL_DZQP BIT(7) /*!< disable zero-quanta pause */ +#define ENET_MAC_FCTL_PTM BITS(16,31) /*!< pause time */ + +/* ENET_MAC_FCTH */ +#define ENET_MAC_FCTH_RFA BITS(0,2) /*!< threshold of active flow control */ +#define ENET_MAC_FCTH_RFD BITS(4,6) /*!< threshold of deactive flow control */ + +/* ENET_MAC_VLT */ +#define ENET_MAC_VLT_VLTI BITS(0,15) /*!< VLAN tag identifier(for receive frames) */ +#define ENET_MAC_VLT_VLTC BIT(16) /*!< 12-bit VLAN tag comparison */ + +/* ENET_MAC_RWFF */ +#define ENET_MAC_RWFF_DATA BITS(0,31) /*!< wakeup frame filter register data */ + +/* ENET_MAC_WUM */ +#define ENET_MAC_WUM_PWD BIT(0) /*!< power down */ +#define ENET_MAC_WUM_MPEN BIT(1) /*!< magic packet enable */ +#define ENET_MAC_WUM_WFEN BIT(2) /*!< wakeup frame enable */ +#define ENET_MAC_WUM_MPKR BIT(5) /*!< magic packet received */ +#define ENET_MAC_WUM_WUFR BIT(6) /*!< wakeup frame received */ +#define ENET_MAC_WUM_GU BIT(9) /*!< global unicast */ +#define ENET_MAC_WUM_WUFFRPR BIT(31) /*!< wakeup frame filter register pointer reset */ + +/* ENET_MAC_INTF */ +#define ENET_MAC_INTF_WUM BIT(3) /*!< WUM status */ +#define ENET_MAC_INTF_MSC BIT(4) /*!< MSC status */ +#define ENET_MAC_INTF_MSCR BIT(5) /*!< MSC receive status */ +#define ENET_MAC_INTF_MSCT BIT(6) /*!< MSC transmit status */ +#define ENET_MAC_INTF_TMST BIT(9) /*!< timestamp trigger status */ + +/* ENET_MAC_INTMSK */ +#define ENET_MAC_INTMSK_WUMIM BIT(3) /*!< WUM interrupt mask */ +#define ENET_MAC_INTMSK_TMSTIM BIT(9) /*!< timestamp trigger interrupt mask */ + +/* ENET_MAC_ADDR0H */ +#define ENET_MAC_ADDR0H_ADDR0H BITS(0,15) /*!< MAC address0 high */ +#define ENET_MAC_ADDR0H_MO BIT(31) /*!< always read 1 and must be kept */ + +/* ENET_MAC_ADDR0L */ +#define ENET_MAC_ADDR0L_ADDR0L BITS(0,31) /*!< MAC address0 low */ + +/* ENET_MAC_ADDR1H */ +#define ENET_MAC_ADDR1H_ADDR1H BITS(0,15) /*!< MAC address1 high */ +#define ENET_MAC_ADDR1H_MB BITS(24,29) /*!< mask byte */ +#define ENET_MAC_ADDR1H_SAF BIT(30) /*!< source address filter */ +#define ENET_MAC_ADDR1H_AFE BIT(31) /*!< address filter enable */ + +/* ENET_MAC_ADDR1L */ +#define ENET_MAC_ADDR1L_ADDR1L BITS(0,31) /*!< MAC address1 low */ + +/* ENET_MAC_ADDR2H */ +#define ENET_MAC_ADDR2H_ADDR2H BITS(0,15) /*!< MAC address2 high */ +#define ENET_MAC_ADDR2H_MB BITS(24,29) /*!< mask byte */ +#define ENET_MAC_ADDR2H_SAF BIT(30) /*!< source address filter */ +#define ENET_MAC_ADDR2H_AFE BIT(31) /*!< address filter enable */ + +/* ENET_MAC_ADDR2L */ +#define ENET_MAC_ADDR2L_ADDR2L BITS(0,31) /*!< MAC address2 low */ + +/* ENET_MAC_ADDR3H */ +#define ENET_MAC_ADDR3H_ADDR3H BITS(0,15) /*!< MAC address3 high */ +#define ENET_MAC_ADDR3H_MB BITS(24,29) /*!< mask byte */ +#define ENET_MAC_ADDR3H_SAF BIT(30) /*!< source address filter */ +#define ENET_MAC_ADDR3H_AFE BIT(31) /*!< address filter enable */ + +/* ENET_MAC_ADDR3L */ +#define ENET_MAC_ADDR3L_ADDR3L BITS(0,31) /*!< MAC address3 low */ + +/* ENET_MSC_CTL */ +#define ENET_MSC_CTL_CTR BIT(0) /*!< counter reset */ +#define ENET_MSC_CTL_CTSR BIT(1) /*!< counter stop rollover */ +#define ENET_MSC_CTL_RTOR BIT(2) /*!< reset on read */ +#define ENET_MSC_CTL_MCFZ BIT(3) /*!< MSC counter freeze */ + +/* ENET_MSC_RINTF */ +#define ENET_MSC_RINTF_RFCE BIT(5) /*!< received frames CRC error */ +#define ENET_MSC_RINTF_RFAE BIT(6) /*!< received frames alignment error */ +#define ENET_MSC_RINTF_RGUF BIT(17) /*!< receive good unicast frames */ + +/* ENET_MSC_TINTF */ +#define ENET_MSC_TINTF_TGFSC BIT(14) /*!< transmitted good frames single collision */ +#define ENET_MSC_TINTF_TGFMSC BIT(15) /*!< transmitted good frames more single collision */ +#define ENET_MSC_TINTF_TGF BIT(21) /*!< transmitted good frames */ + +/* ENET_MSC_RINTMSK */ +#define ENET_MSC_RINTMSK_RFCEIM BIT(5) /*!< received frame CRC error interrupt mask */ +#define ENET_MSC_RINTMSK_RFAEIM BIT(6) /*!< received frames alignment error interrupt mask */ +#define ENET_MSC_RINTMSK_RGUFIM BIT(17) /*!< received good unicast frames interrupt mask */ + +/* ENET_MSC_TINTMSK */ +#define ENET_MSC_TINTMSK_TGFSCIM BIT(14) /*!< transmitted good frames single collision interrupt mask */ +#define ENET_MSC_TINTMSK_TGFMSCIM BIT(15) /*!< transmitted good frames more single collision interrupt mask */ +#define ENET_MSC_TINTMSK_TGFIM BIT(21) /*!< transmitted good frames interrupt mask */ + +/* ENET_MSC_SCCNT */ +#define ENET_MSC_SCCNT_SCC BITS(0,31) /*!< transmitted good frames single collision counter */ + +/* ENET_MSC_MSCCNT */ +#define ENET_MSC_MSCCNT_MSCC BITS(0,31) /*!< transmitted good frames more one single collision counter */ + +/* ENET_MSC_TGFCNT */ +#define ENET_MSC_TGFCNT_TGF BITS(0,31) /*!< transmitted good frames counter */ + +/* ENET_MSC_RFCECNT */ +#define ENET_MSC_RFCECNT_RFCER BITS(0,31) /*!< received frames with CRC error counter */ + +/* ENET_MSC_RFAECNT */ +#define ENET_MSC_RFAECNT_RFAER BITS(0,31) /*!< received frames alignment error counter */ + +/* ENET_MSC_RGUFCNT */ +#define ENET_MSC_RGUFCNT_RGUF BITS(0,31) /*!< received good unicast frames counter */ + +/* ENET_PTP_TSCTL */ +#define ENET_PTP_TSCTL_TMSEN BIT(0) /*!< timestamp enable */ +#define ENET_PTP_TSCTL_TMSFCU BIT(1) /*!< timestamp fine or coarse update */ +#define ENET_PTP_TSCTL_TMSSTI BIT(2) /*!< timestamp system time initialize */ +#define ENET_PTP_TSCTL_TMSSTU BIT(3) /*!< timestamp system time update */ +#define ENET_PTP_TSCTL_TMSITEN BIT(4) /*!< timestamp interrupt trigger enable */ +#define ENET_PTP_TSCTL_TMSARU BIT(5) /*!< timestamp addend register update */ + +/* ENET_PTP_SSINC */ +#define ENET_PTP_SSINC_STMSSI BITS(0,7) /*!< system time subsecond increment */ + +/* ENET_PTP_TSH */ +#define ENET_PTP_TSH_STMS BITS(0,31) /*!< system time second */ + +/* ENET_PTP_TSL */ +#define ENET_PTP_TSL_STMSS BITS(0,30) /*!< system time subseconds */ +#define ENET_PTP_TSL_STS BIT(31) /*!< system time sign */ + +/* ENET_PTP_TSUH */ +#define ENET_PTP_TSUH_TMSUS BITS(0,31) /*!< timestamp update seconds */ + +/* ENET_PTP_TSUL */ +#define ENET_PTP_TSUL_TMSUSS BITS(0,30) /*!< timestamp update subseconds */ +#define ENET_PTP_TSUL_TMSUPNS BIT(31) /*!< timestamp update positive or negative sign */ + +/* ENET_PTP_TSADDEND */ +#define ENET_PTP_TSADDEND_TMSA BITS(0,31) /*!< timestamp addend */ + +/* ENET_PTP_ETH */ +#define ENET_PTP_ETH_ETSH BITS(0,31) /*!< expected time high */ + +/* ENET_PTP_ETL */ +#define ENET_PTP_ETL_ETSL BITS(0,31) /*!< expected time low */ + +/* ENET_DMA_BCTL */ +#define ENET_DMA_BCTL_SWR BIT(0) /*!< software reset */ +#define ENET_DMA_BCTL_DAB BIT(1) /*!< DMA arbitration */ +#define ENET_DMA_BCTL_DPSL BITS(2,6) /*!< descriptor skip length */ +#define ENET_DMA_BCTL_PGBL BITS(8,13) /*!< programmable burst length */ +#define ENET_DMA_BCTL_RTPR BITS(14,15) /*!< RxDMA and TxDMA transfer priority ratio */ +#define ENET_DMA_BCTL_FB BIT(16) /*!< fixed Burst */ +#define ENET_DMA_BCTL_RXDP BITS(17,22) /*!< RxDMA PGBL */ +#define ENET_DMA_BCTL_UIP BIT(23) /*!< use independent PGBL */ +#define ENET_DMA_BCTL_FPBL BIT(24) /*!< four times PGBL mode */ +#define ENET_DMA_BCTL_AA BIT(25) /*!< address-aligned */ + +/* ENET_DMA_TPEN */ +#define ENET_DMA_TPEN_TPE BITS(0,31) /*!< transmit poll enable */ + +/* ENET_DMA_RPEN */ +#define ENET_DMA_RPEN_RPE BITS(0,31) /*!< receive poll enable */ + +/* ENET_DMA_RDTADDR */ +#define ENET_DMA_RDTADDR_SRT BITS(0,31) /*!< start address of receive table */ + +/* ENET_DMA_TDTADDR */ +#define ENET_DMA_TDTADDR_STT BITS(0,31) /*!< start address of transmit table */ + +/* ENET_DMA_STAT */ +#define ENET_DMA_STAT_TS BIT(0) /*!< transmit status */ +#define ENET_DMA_STAT_TPS BIT(1) /*!< transmit process stopped status */ +#define ENET_DMA_STAT_TBU BIT(2) /*!< transmit buffer unavailable status */ +#define ENET_DMA_STAT_TJT BIT(3) /*!< transmit jabber timeout status */ +#define ENET_DMA_STAT_RO BIT(4) /*!< receive overflow status */ +#define ENET_DMA_STAT_TU BIT(5) /*!< transmit underflow status */ +#define ENET_DMA_STAT_RS BIT(6) /*!< receive status */ +#define ENET_DMA_STAT_RBU BIT(7) /*!< receive buffer unavailable status */ +#define ENET_DMA_STAT_RPS BIT(8) /*!< receive process stopped status */ +#define ENET_DMA_STAT_RWT BIT(9) /*!< receive watchdog timeout status */ +#define ENET_DMA_STAT_ET BIT(10) /*!< early transmit status */ +#define ENET_DMA_STAT_FBE BIT(13) /*!< fatal bus error status */ +#define ENET_DMA_STAT_ER BIT(14) /*!< early receive status */ +#define ENET_DMA_STAT_AI BIT(15) /*!< abnormal interrupt summary */ +#define ENET_DMA_STAT_NI BIT(16) /*!< normal interrupt summary */ +#define ENET_DMA_STAT_RP BITS(17,19) /*!< receive process state */ +#define ENET_DMA_STAT_TP BITS(20,22) /*!< transmit process state */ +#define ENET_DMA_STAT_EB BITS(23,25) /*!< error bits status */ +#define ENET_DMA_STAT_MSC BIT(27) /*!< MSC status */ +#define ENET_DMA_STAT_WUM BIT(28) /*!< WUM status */ +#define ENET_DMA_STAT_TST BIT(29) /*!< timestamp trigger status */ + +/* ENET_DMA_CTL */ +#define ENET_DMA_CTL_SRE BIT(1) /*!< start/stop receive enable */ +#define ENET_DMA_CTL_OSF BIT(2) /*!< operate on second frame */ +#define ENET_DMA_CTL_RTHC BITS(3,4) /*!< receive threshold control */ +#define ENET_DMA_CTL_FUF BIT(6) /*!< forward undersized good frames */ +#define ENET_DMA_CTL_FERF BIT(7) /*!< forward error frames */ +#define ENET_DMA_CTL_STE BIT(13) /*!< start/stop transmission enable */ +#define ENET_DMA_CTL_TTHC BITS(14,16) /*!< transmit threshold control */ +#define ENET_DMA_CTL_FTF BIT(20) /*!< flush transmit FIFO */ +#define ENET_DMA_CTL_TSFD BIT(21) /*!< transmit store-and-forward */ +#define ENET_DMA_CTL_DAFRF BIT(24) /*!< disable flushing of received frames */ +#define ENET_DMA_CTL_RSFD BIT(25) /*!< receive store-and-forward */ +#define ENET_DMA_CTL_DTCERFD BIT(26) /*!< dropping of TCP/IP checksum error frames disable */ + +/* ENET_DMA_INTEN */ +#define ENET_DMA_INTEN_TIE BIT(0) /*!< transmit interrupt enable */ +#define ENET_DMA_INTEN_TPSIE BIT(1) /*!< transmit process stopped interrupt enable */ +#define ENET_DMA_INTEN_TBUIE BIT(2) /*!< transmit buffer unavailable interrupt enable */ +#define ENET_DMA_INTEN_TJTIE BIT(3) /*!< transmit jabber timeout interrupt enable */ +#define ENET_DMA_INTEN_ROIE BIT(4) /*!< receive overflow interrupt enable */ +#define ENET_DMA_INTEN_TUIE BIT(5) /*!< transmit underflow interrupt enable */ +#define ENET_DMA_INTEN_RIE BIT(6) /*!< receive interrupt enable */ +#define ENET_DMA_INTEN_RBUIE BIT(7) /*!< receive buffer unavailable interrupt enable */ +#define ENET_DMA_INTEN_RPSIE BIT(8) /*!< receive process stopped interrupt enable */ +#define ENET_DMA_INTEN_RWTIE BIT(9) /*!< receive watchdog timeout interrupt enable */ +#define ENET_DMA_INTEN_ETIE BIT(10) /*!< early transmit interrupt enable */ +#define ENET_DMA_INTEN_FBEIE BIT(13) /*!< fatal bus error interrupt enable */ +#define ENET_DMA_INTEN_ERIE BIT(14) /*!< early receive interrupt enable */ +#define ENET_DMA_INTEN_AIE BIT(15) /*!< abnormal interrupt summary enable */ +#define ENET_DMA_INTEN_NIE BIT(16) /*!< normal interrupt summary enable */ + +/* ENET_DMA_MFBOCNT */ +#define ENET_DMA_MFBOCNT_MSFC BITS(0,15) /*!< missed frames by the controller */ +#define ENET_DMA_MFBOCNT_OBMFC BIT(16) /* Overflow bit for missed frame counter */ +#define ENET_DMA_MFBOCNT_MSFA BITS(17,27) /*!< missed frames by the application */ +#define ENET_DMA_MFBOCNT_OBFOC BIT(28) /*!< Overflow bit for FIFO overflow counter */ + +/* ENET_DMA_CTDADDR */ +#define ENET_DMA_CTDADDR_TDAP BITS(0,31) /*!< transmit descriptor address pointer */ + +/* ENET_DMA_CRDADDR */ +#define ENET_DMA_CRDADDR_RDAP BITS(0,31) /*!< receive descriptor address pointer */ + +/* ENET_DMA_CTBADDR */ +#define ENET_DMA_CTBADDR_TBAP BITS(0,31) /*!< transmit buffer address pointer */ + +/* ENET_DMA_CRBADDR */ +#define ENET_DMA_CRBADDR_RBAP BITS(0,31) /*!< receive buffer address pointer */ + +/* ENET DMA Tx descriptor TDES0 */ +#define ENET_TDES0_DB BIT(0) /*!< deferred */ +#define ENET_TDES0_UFE BIT(1) /*!< underflow error */ +#define ENET_TDES0_EXD BIT(2) /*!< excessive deferral */ +#define ENET_TDES0_COCNT BITS(3,6) /*!< collision count */ +#define ENET_TDES0_VFRM BIT(7) /*!< VLAN frame */ +#define ENET_TDES0_ECO BIT(8) /*!< excessive collision */ +#define ENET_TDES0_LCO BIT(9) /*!< late collision */ +#define ENET_TDES0_NCA BIT(10) /*!< no carrier */ +#define ENET_TDES0_LCA BIT(11) /*!< loss of carrier */ +#define ENET_TDES0_IPPE BIT(12) /*!< IP payload error */ +#define ENET_TDES0_FRMF BIT(13) /*!< frame flushed */ +#define ENET_TDES0_JT BIT(14) /*!< jabber timeout */ +#define ENET_TDES0_ES BIT(15) /*!< error summary */ +#define ENET_TDES0_IPHE BIT(16) /*!< IP header error */ +#define ENET_TDES0_TTMSS BIT(17) /*!< transmit timestamp status */ +#define ENET_TDES0_TCHM BIT(20) /*!< the second address chained mode */ +#define ENET_TDES0_TERM BIT(21) /*!< transmit end of ring mode*/ +#define ENET_TDES0_CM BITS(22,23) /*!< checksum mode */ +#define ENET_TDES0_TTSEN BIT(25) /*!< transmit timestamp function enable */ +#define ENET_TDES0_DPAD BIT(26) /*!< disable adding pad */ +#define ENET_TDES0_DCRC BIT(27) /*!< disable CRC */ +#define ENET_TDES0_FSG BIT(28) /*!< first segment */ +#define ENET_TDES0_LSG BIT(29) /*!< last segment */ +#define ENET_TDES0_INTC BIT(30) /*!< interrupt on completion */ +#define ENET_TDES0_DAV BIT(31) /*!< DAV bit */ + +/* ENET DMA Tx descriptor TDES1 */ +#define ENET_TDES1_TB1S BITS(0,12) /*!< transmit buffer 1 size */ +#define ENET_TDES1_TB2S BITS(16,28) /*!< transmit buffer 2 size */ + +/* ENET DMA Tx descriptor TDES2 */ +#define ENET_TDES2_TB1AP BITS(0,31) /*!< transmit buffer 1 address pointer/transmit frame timestamp low 32-bit value */ + +/* ENET DMA Tx descriptor TDES3 */ +#define ENET_TDES3_TB2AP BITS(0,31) /*!< transmit buffer 2 address pointer (or next descriptor address) / transmit frame timestamp high 32-bit value */ + +/* ENET DMA Rx descriptor RDES0 */ +#define ENET_RDES0_PCERR BIT(0) /*!< payload checksum error */ +#define ENET_RDES0_CERR BIT(1) /*!< CRC error */ +#define ENET_RDES0_DBERR BIT(2) /*!< dribble bit error */ +#define ENET_RDES0_RERR BIT(3) /*!< receive error */ +#define ENET_RDES0_RWDT BIT(4) /*!< receive watchdog timeout */ +#define ENET_RDES0_FRMT BIT(5) /*!< frame type */ +#define ENET_RDES0_LCO BIT(6) /*!< late collision */ +#define ENET_RDES0_IPHERR BIT(7) /*!< IP frame header error */ +#define ENET_RDES0_LDES BIT(8) /*!< last descriptor */ +#define ENET_RDES0_FDES BIT(9) /*!< first descriptor */ +#define ENET_RDES0_VTAG BIT(10) /*!< VLAN tag */ +#define ENET_RDES0_OERR BIT(11) /*!< overflow Error */ +#define ENET_RDES0_LERR BIT(12) /*!< length error */ +#define ENET_RDES0_SAFF BIT(13) /*!< SA filter fail */ +#define ENET_RDES0_DERR BIT(14) /*!< descriptor error */ +#define ENET_RDES0_ERRS BIT(15) /*!< error summary */ +#define ENET_RDES0_FRML BITS(16,29) /*!< frame length */ +#define ENET_RDES0_DAFF BIT(30) /*!< destination address filter fail */ +#define ENET_RDES0_DAV BIT(31) /*!< descriptor available */ + +/* ENET DMA Rx descriptor RDES1 */ +#define ENET_RDES1_RB1S BITS(0,12) /*!< receive buffer 1 size */ +#define ENET_RDES1_RCHM BIT(14) /*!< receive chained mode for second address */ +#define ENET_RDES1_RERM BIT(15) /*!< receive end of ring mode*/ +#define ENET_RDES1_RB2S BITS(16,28) /*!< receive buffer 2 size */ +#define ENET_RDES1_DINTC BIT(31) /*!< disable interrupt on completion */ + +/* ENET DMA Rx descriptor RDES2 */ +#define ENET_RDES2_RB1AP BITS(0,31) /*!< receive buffer 1 address pointer / receive frame timestamp low 32-bit */ + +/* ENET DMA Rx descriptor RDES3 */ +#define ENET_RDES3_RB2AP BITS(0,31) /*!< receive buffer 2 address pointer (next descriptor address)/receive frame timestamp high 32-bit value */ + +/* constants definitions */ +/* define bit position and its register index offset */ +#define ENET_REGIDX_BIT(regidx, bitpos) (((uint32_t)(regidx) << 6) | (uint32_t)(bitpos)) +#define ENET_REG_VAL(periph) (REG32(ENET + ((uint32_t)(periph)>>6))) +#define ENET_BIT_POS(val) ((uint32_t)(val) & 0x1FU) + +/* ENET clock range judgement */ +#define ENET_RANGE(hclk, n, m) (((hclk) >= (n))&&((hclk) < (m))) + +/* define MAC address configuration and reference address */ +#define ENET_SET_MACADDRH(p) (((uint32_t)(p)[5] << 8) | (uint32_t)(p)[4]) +#define ENET_SET_MACADDRL(p) (((uint32_t)(p)[3] << 24) | ((uint32_t)(p)[2] << 16) | ((uint32_t)(p)[1] << 8) | (uint32_t)(p)[0]) +#define ENET_ADDRH_BASE ((ENET) + 0x40U) +#define ENET_ADDRL_BASE ((ENET) + 0x44U) +#define ENET_GET_MACADDR(offset, n) ((uint8_t)((REG32((ENET_ADDRL_BASE + (offset)) - (((n) / 4U) * 4U)) >> (8U * ((n) % 4U))) & 0xFFU)) + +/* register offset */ +#define MAC_FCTL_REG_OFFSET 0x0018U /*!< MAC flow control register offset */ +#define MAC_WUM_REG_OFFSET 0x002CU /*!< MAC wakeup management register offset */ +#define MAC_INTF_REG_OFFSET 0x0038U /*!< MAC interrupt flag register offset */ +#define MAC_INTMSK_REG_OFFSET 0x003CU /*!< MAC interrupt mask register offset */ + +#define MSC_RINTF_REG_OFFSET 0x0104U /*!< MSC receive interrupt flag register offset */ +#define MSC_TINTF_REG_OFFSET 0x0108U /*!< MSC transmit interrupt flag register offset */ +#define MSC_RINTMSK_REG_OFFSET 0x010CU /*!< MSC receive interrupt mask register offset */ +#define MSC_TINTMSK_REG_OFFSET 0x0110U /*!< MSC transmit interrupt mask register offset */ +#define MSC_SCCNT_REG_OFFSET 0x014CU /*!< MSC transmitted good frames after a single collision counter register offset */ +#define MSC_MSCCNT_REG_OFFSET 0x0150U /*!< MSC transmitted good frames after more than a single collision counter register offset */ +#define MSC_TGFCNT_REG_OFFSET 0x0168U /*!< MSC transmitted good frames counter register offset */ +#define MSC_RFCECNT_REG_OFFSET 0x0194U /*!< MSC received frames with CRC error counter register offset */ +#define MSC_RFAECNT_REG_OFFSET 0x0198U /*!< MSC received frames with alignment error counter register offset */ +#define MSC_RGUFCNT_REG_OFFSET 0x01C4U /*!< MSC received good unicast frames counter register offset */ + +#define DMA_STAT_REG_OFFSET 0x1014U /*!< DMA status register offset */ +#define DMA_INTEN_REG_OFFSET 0x101CU /*!< DMA interrupt enable register offset */ +#define DMA_TDTADDR_REG_OFFSET 0x1010U /*!< DMA transmit descriptor table address register offset */ +#define DMA_CTDADDR_REG_OFFSET 0x1048U /*!< DMA current transmit descriptor address register */ +#define DMA_CTBADDR_REG_OFFSET 0x1050U /*!< DMA current transmit buffer address register */ +#define DMA_RDTADDR_REG_OFFSET 0x100CU /*!< DMA receive descriptor table address register */ +#define DMA_CRDADDR_REG_OFFSET 0x104CU /*!< DMA current receive descriptor address register */ +#define DMA_CRBADDR_REG_OFFSET 0x1054U /*!< DMA current receive buffer address register */ + +/* ENET status flag get */ +typedef enum +{ + /* ENET_MAC_WUM register */ + ENET_MAC_FLAG_MPKR = ENET_REGIDX_BIT(MAC_WUM_REG_OFFSET, 5U), /*!< magic packet received flag */ + ENET_MAC_FLAG_WUFR = ENET_REGIDX_BIT(MAC_WUM_REG_OFFSET, 6U), /*!< wakeup frame received flag */ + /* ENET_MAC_FCTL register */ + ENET_MAC_FLAG_FLOWCONTROL = ENET_REGIDX_BIT(MAC_FCTL_REG_OFFSET, 0U), /*!< flow control status flag */ + /* ENET_MAC_INTF register */ + ENET_MAC_FLAG_WUM = ENET_REGIDX_BIT(MAC_INTF_REG_OFFSET, 3U), /*!< WUM status flag */ + ENET_MAC_FLAG_MSC = ENET_REGIDX_BIT(MAC_INTF_REG_OFFSET, 4U), /*!< MSC status flag */ + ENET_MAC_FLAG_MSCR = ENET_REGIDX_BIT(MAC_INTF_REG_OFFSET, 5U), /*!< MSC receive status flag */ + ENET_MAC_FLAG_MSCT = ENET_REGIDX_BIT(MAC_INTF_REG_OFFSET, 6U), /*!< MSC transmit status flag */ + ENET_MAC_FLAG_TMST = ENET_REGIDX_BIT(MAC_INTF_REG_OFFSET, 9U), /*!< timestamp trigger status flag */ + /* ENET_MSC_RINTF register */ + ENET_MSC_FLAG_RFCE = ENET_REGIDX_BIT(MSC_RINTF_REG_OFFSET, 5U), /*!< received frames CRC error flag */ + ENET_MSC_FLAG_RFAE = ENET_REGIDX_BIT(MSC_RINTF_REG_OFFSET, 6U), /*!< received frames alignment error flag */ + ENET_MSC_FLAG_RGUF = ENET_REGIDX_BIT(MSC_RINTF_REG_OFFSET, 17U), /*!< received good unicast frames flag */ + /* ENET_MSC_TINTF register */ + ENET_MSC_FLAG_TGFSC = ENET_REGIDX_BIT(MSC_TINTF_REG_OFFSET, 14U), /*!< transmitted good frames single collision flag */ + ENET_MSC_FLAG_TGFMSC = ENET_REGIDX_BIT(MSC_TINTF_REG_OFFSET, 15U), /*!< transmitted good frames more single collision flag */ + ENET_MSC_FLAG_TGF = ENET_REGIDX_BIT(MSC_TINTF_REG_OFFSET, 21U), /*!< transmitted good frames flag */ + /* ENET_DMA_STAT register */ + ENET_DMA_FLAG_TS = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 0U), /*!< transmit status flag */ + ENET_DMA_FLAG_TPS = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 1U), /*!< transmit process stopped status flag */ + ENET_DMA_FLAG_TBU = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 2U), /*!< transmit buffer unavailable status flag */ + ENET_DMA_FLAG_TJT = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 3U), /*!< transmit jabber timeout status flag */ + ENET_DMA_FLAG_RO = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 4U), /*!< receive overflow status flag */ + ENET_DMA_FLAG_TU = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 5U), /*!< transmit underflow status flag */ + ENET_DMA_FLAG_RS = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 6U), /*!< receive status flag */ + ENET_DMA_FLAG_RBU = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 7U), /*!< receive buffer unavailable status flag */ + ENET_DMA_FLAG_RPS = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 8U), /*!< receive process stopped status flag */ + ENET_DMA_FLAG_RWT = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 9U), /*!< receive watchdog timeout status flag */ + ENET_DMA_FLAG_ET = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 10U), /*!< early transmit status flag */ + ENET_DMA_FLAG_FBE = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 13U), /*!< fatal bus error status flag */ + ENET_DMA_FLAG_ER = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 14U), /*!< early receive status flag */ + ENET_DMA_FLAG_AI = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 15U), /*!< abnormal interrupt summary flag */ + ENET_DMA_FLAG_NI = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 16U), /*!< normal interrupt summary flag */ + ENET_DMA_FLAG_EB_DMA_ERROR = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 23U), /*!< error during data transfer by RxDMA/TxDMA flag */ + ENET_DMA_FLAG_EB_TRANSFER_ERROR = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 24U), /*!< error during write/read transfer flag */ + ENET_DMA_FLAG_EB_ACCESS_ERROR = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 25U), /*!< error during data buffer/descriptor access flag */ + ENET_DMA_FLAG_MSC = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 27U), /*!< MSC status flag */ + ENET_DMA_FLAG_WUM = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 28U), /*!< WUM status flag */ + ENET_DMA_FLAG_TST = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 29U), /*!< timestamp trigger status flag */ +}enet_flag_enum; + +/* ENET stutus flag clear */ +typedef enum +{ + /* ENET_DMA_STAT register */ + ENET_DMA_FLAG_TS_CLR = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 0U), /*!< transmit status flag */ + ENET_DMA_FLAG_TPS_CLR = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 1U), /*!< transmit process stopped status flag */ + ENET_DMA_FLAG_TBU_CLR = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 2U), /*!< transmit buffer unavailable status flag */ + ENET_DMA_FLAG_TJT_CLR = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 3U), /*!< transmit jabber timeout status flag */ + ENET_DMA_FLAG_RO_CLR = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 4U), /*!< receive overflow status flag */ + ENET_DMA_FLAG_TU_CLR = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 5U), /*!< transmit underflow status flag */ + ENET_DMA_FLAG_RS_CLR = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 6U), /*!< receive status flag */ + ENET_DMA_FLAG_RBU_CLR = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 7U), /*!< receive buffer unavailable status flag */ + ENET_DMA_FLAG_RPS_CLR = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 8U), /*!< receive process stopped status flag */ + ENET_DMA_FLAG_RWT_CLR = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 9U), /*!< receive watchdog timeout status flag */ + ENET_DMA_FLAG_ET_CLR = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 10U), /*!< early transmit status flag */ + ENET_DMA_FLAG_FBE_CLR = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 13U), /*!< fatal bus error status flag */ + ENET_DMA_FLAG_ER_CLR = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 14U), /*!< early receive status flag */ + ENET_DMA_FLAG_AI_CLR = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 15U), /*!< abnormal interrupt summary flag */ + ENET_DMA_FLAG_NI_CLR = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 16U), /*!< normal interrupt summary flag */ +}enet_flag_clear_enum; + +/* ENET interrupt enable/disable */ +typedef enum +{ + /* ENET_MAC_INTMSK register */ + ENET_MAC_INT_WUMIM = ENET_REGIDX_BIT(MAC_INTMSK_REG_OFFSET, 3U), /*!< WUM interrupt mask */ + ENET_MAC_INT_TMSTIM = ENET_REGIDX_BIT(MAC_INTMSK_REG_OFFSET, 9U), /*!< timestamp trigger interrupt mask */ + /* ENET_MSC_RINTMSK register */ + ENET_MSC_INT_RFCEIM = ENET_REGIDX_BIT(MSC_RINTMSK_REG_OFFSET, 5U), /*!< received frame CRC error interrupt mask */ + ENET_MSC_INT_RFAEIM = ENET_REGIDX_BIT(MSC_RINTMSK_REG_OFFSET, 6U), /*!< received frames alignment error interrupt mask */ + ENET_MSC_INT_RGUFIM = ENET_REGIDX_BIT(MSC_RINTMSK_REG_OFFSET, 17U), /*!< received good unicast frames interrupt mask */ + /* ENET_MSC_TINTMSK register */ + ENET_MSC_INT_TGFSCIM = ENET_REGIDX_BIT(MSC_TINTMSK_REG_OFFSET, 14U), /*!< transmitted good frames single collision interrupt mask */ + ENET_MSC_INT_TGFMSCIM = ENET_REGIDX_BIT(MSC_TINTMSK_REG_OFFSET, 15U), /*!< transmitted good frames more single collision interrupt mask */ + ENET_MSC_INT_TGFIM = ENET_REGIDX_BIT(MSC_TINTMSK_REG_OFFSET, 21U), /*!< transmitted good frames interrupt mask */ + /* ENET_DMA_INTEN register */ + ENET_DMA_INT_TIE = ENET_REGIDX_BIT(DMA_INTEN_REG_OFFSET, 0U), /*!< transmit interrupt enable */ + ENET_DMA_INT_TPSIE = ENET_REGIDX_BIT(DMA_INTEN_REG_OFFSET, 1U), /*!< transmit process stopped interrupt enable */ + ENET_DMA_INT_TBUIE = ENET_REGIDX_BIT(DMA_INTEN_REG_OFFSET, 2U), /*!< transmit buffer unavailable interrupt enable */ + ENET_DMA_INT_TJTIE = ENET_REGIDX_BIT(DMA_INTEN_REG_OFFSET, 3U), /*!< transmit jabber timeout interrupt enable */ + ENET_DMA_INT_ROIE = ENET_REGIDX_BIT(DMA_INTEN_REG_OFFSET, 4U), /*!< receive overflow interrupt enable */ + ENET_DMA_INT_TUIE = ENET_REGIDX_BIT(DMA_INTEN_REG_OFFSET, 5U), /*!< transmit underflow interrupt enable */ + ENET_DMA_INT_RIE = ENET_REGIDX_BIT(DMA_INTEN_REG_OFFSET, 6U), /*!< receive interrupt enable */ + ENET_DMA_INT_RBUIE = ENET_REGIDX_BIT(DMA_INTEN_REG_OFFSET, 7U), /*!< receive buffer unavailable interrupt enable */ + ENET_DMA_INT_RPSIE = ENET_REGIDX_BIT(DMA_INTEN_REG_OFFSET, 8U), /*!< receive process stopped interrupt enable */ + ENET_DMA_INT_RWTIE = ENET_REGIDX_BIT(DMA_INTEN_REG_OFFSET, 9U), /*!< receive watchdog timeout interrupt enable */ + ENET_DMA_INT_ETIE = ENET_REGIDX_BIT(DMA_INTEN_REG_OFFSET, 10U), /*!< early transmit interrupt enable */ + ENET_DMA_INT_FBEIE = ENET_REGIDX_BIT(DMA_INTEN_REG_OFFSET, 13U), /*!< fatal bus error interrupt enable */ + ENET_DMA_INT_ERIE = ENET_REGIDX_BIT(DMA_INTEN_REG_OFFSET, 14U), /*!< early receive interrupt enable */ + ENET_DMA_INT_AIE = ENET_REGIDX_BIT(DMA_INTEN_REG_OFFSET, 15U), /*!< abnormal interrupt summary enable */ + ENET_DMA_INT_NIE = ENET_REGIDX_BIT(DMA_INTEN_REG_OFFSET, 16U), /*!< normal interrupt summary enable */ +}enet_int_enum; + +/* ENET interrupt flag get */ +typedef enum +{ + /* ENET_MAC_INTF register */ + ENET_MAC_INT_FLAG_WUM = ENET_REGIDX_BIT(MAC_INTF_REG_OFFSET, 3U), /*!< WUM status flag */ + ENET_MAC_INT_FLAG_MSC = ENET_REGIDX_BIT(MAC_INTF_REG_OFFSET, 4U), /*!< MSC status flag */ + ENET_MAC_INT_FLAG_MSCR = ENET_REGIDX_BIT(MAC_INTF_REG_OFFSET, 5U), /*!< MSC receive status flag */ + ENET_MAC_INT_FLAG_MSCT = ENET_REGIDX_BIT(MAC_INTF_REG_OFFSET, 6U), /*!< MSC transmit status flag */ + ENET_MAC_INT_FLAG_TMST = ENET_REGIDX_BIT(MAC_INTF_REG_OFFSET, 9U), /*!< timestamp trigger status flag */ + /* ENET_MSC_RINTF register */ + ENET_MSC_INT_FLAG_RFCE = ENET_REGIDX_BIT(MSC_RINTF_REG_OFFSET, 5U), /*!< received frames CRC error flag */ + ENET_MSC_INT_FLAG_RFAE = ENET_REGIDX_BIT(MSC_RINTF_REG_OFFSET, 6U), /*!< received frames alignment error flag */ + ENET_MSC_INT_FLAG_RGUF = ENET_REGIDX_BIT(MSC_RINTF_REG_OFFSET, 17U), /*!< received good unicast frames flag */ + /* ENET_MSC_TINTF register */ + ENET_MSC_INT_FLAG_TGFSC = ENET_REGIDX_BIT(MSC_TINTF_REG_OFFSET, 14U), /*!< transmitted good frames single collision flag */ + ENET_MSC_INT_FLAG_TGFMSC = ENET_REGIDX_BIT(MSC_TINTF_REG_OFFSET, 15U), /*!< transmitted good frames more single collision flag */ + ENET_MSC_INT_FLAG_TGF = ENET_REGIDX_BIT(MSC_TINTF_REG_OFFSET, 21U), /*!< transmitted good frames flag */ + /* ENET_DMA_STAT register */ + ENET_DMA_INT_FLAG_TS = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 0U), /*!< transmit status flag */ + ENET_DMA_INT_FLAG_TPS = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 1U), /*!< transmit process stopped status flag */ + ENET_DMA_INT_FLAG_TBU = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 2U), /*!< transmit buffer unavailable status flag */ + ENET_DMA_INT_FLAG_TJT = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 3U), /*!< transmit jabber timeout status flag */ + ENET_DMA_INT_FLAG_RO = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 4U), /*!< receive overflow status flag */ + ENET_DMA_INT_FLAG_TU = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 5U), /*!< transmit underflow status flag */ + ENET_DMA_INT_FLAG_RS = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 6U), /*!< receive status flag */ + ENET_DMA_INT_FLAG_RBU = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 7U), /*!< receive buffer unavailable status flag */ + ENET_DMA_INT_FLAG_RPS = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 8U), /*!< receive process stopped status flag */ + ENET_DMA_INT_FLAG_RWT = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 9U), /*!< receive watchdog timeout status flag */ + ENET_DMA_INT_FLAG_ET = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 10U), /*!< early transmit status flag */ + ENET_DMA_INT_FLAG_FBE = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 13U), /*!< fatal bus error status flag */ + ENET_DMA_INT_FLAG_ER = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 14U), /*!< early receive status flag */ + ENET_DMA_INT_FLAG_AI = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 15U), /*!< abnormal interrupt summary flag */ + ENET_DMA_INT_FLAG_NI = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 16U), /*!< normal interrupt summary flag */ + ENET_DMA_INT_FLAG_MSC = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 27U), /*!< MSC status flag */ + ENET_DMA_INT_FLAG_WUM = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 28U), /*!< WUM status flag */ + ENET_DMA_INT_FLAG_TST = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 29U), /*!< timestamp trigger status flag */ +}enet_int_flag_enum; + +/* ENET interrupt flag clear */ +typedef enum +{ + /* ENET_DMA_STAT register */ + ENET_DMA_INT_FLAG_TS_CLR = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 0U), /*!< transmit status flag */ + ENET_DMA_INT_FLAG_TPS_CLR = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 1U), /*!< transmit process stopped status flag */ + ENET_DMA_INT_FLAG_TBU_CLR = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 2U), /*!< transmit buffer unavailable status flag */ + ENET_DMA_INT_FLAG_TJT_CLR = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 3U), /*!< transmit jabber timeout status flag */ + ENET_DMA_INT_FLAG_RO_CLR = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 4U), /*!< receive overflow status flag */ + ENET_DMA_INT_FLAG_TU_CLR = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 5U), /*!< transmit underflow status flag */ + ENET_DMA_INT_FLAG_RS_CLR = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 6U), /*!< receive status flag */ + ENET_DMA_INT_FLAG_RBU_CLR = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 7U), /*!< receive buffer unavailable status flag */ + ENET_DMA_INT_FLAG_RPS_CLR = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 8U), /*!< receive process stopped status flag */ + ENET_DMA_INT_FLAG_RWT_CLR = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 9U), /*!< receive watchdog timeout status flag */ + ENET_DMA_INT_FLAG_ET_CLR = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 10U), /*!< early transmit status flag */ + ENET_DMA_INT_FLAG_FBE_CLR = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 13U), /*!< fatal bus error status flag */ + ENET_DMA_INT_FLAG_ER_CLR = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 14U), /*!< early receive status flag */ + ENET_DMA_INT_FLAG_AI_CLR = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 15U), /*!< abnormal interrupt summary flag */ + ENET_DMA_INT_FLAG_NI_CLR = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 16U), /*!< normal interrupt summary flag */ +}enet_int_flag_clear_enum; + +/* current RX/TX descriptor/buffer/descriptor table address get */ +typedef enum +{ + ENET_RX_DESC_TABLE = DMA_RDTADDR_REG_OFFSET, /*!< RX descriptor table */ + ENET_RX_CURRENT_DESC = DMA_CRDADDR_REG_OFFSET, /*!< current RX descriptor */ + ENET_RX_CURRENT_BUFFER = DMA_CRBADDR_REG_OFFSET, /*!< current RX buffer */ + ENET_TX_DESC_TABLE = DMA_TDTADDR_REG_OFFSET, /*!< TX descriptor table */ + ENET_TX_CURRENT_DESC = DMA_CTDADDR_REG_OFFSET, /*!< current TX descriptor */ + ENET_TX_CURRENT_BUFFER = DMA_CTBADDR_REG_OFFSET /*!< current TX buffer */ +}enet_desc_reg_enum; + +/* MAC statistics counter get */ +typedef enum +{ + ENET_MSC_TX_SCCNT = MSC_SCCNT_REG_OFFSET, /*!< MSC transmitted good frames after a single collision counter */ + ENET_MSC_TX_MSCCNT = MSC_MSCCNT_REG_OFFSET, /*!< MSC transmitted good frames after more than a single collision counter */ + ENET_MSC_TX_TGFCNT = MSC_TGFCNT_REG_OFFSET, /*!< MSC transmitted good frames counter */ + ENET_MSC_RX_RFCECNT = MSC_RFCECNT_REG_OFFSET, /*!< MSC received frames with CRC error counter */ + ENET_MSC_RX_RFAECNT = MSC_RFAECNT_REG_OFFSET, /*!< MSC received frames with alignment error counter */ + ENET_MSC_RX_RGUFCNT = MSC_RGUFCNT_REG_OFFSET /*!< MSC received good unicast frames counter */ +}enet_msc_counter_enum; + +/* function option, used for ENET initialization */ +typedef enum +{ + FORWARD_OPTION = BIT(0), /*!< configure the frame forward related parameters */ + DMABUS_OPTION = BIT(1), /*!< configure the DMA bus mode related parameters */ + DMA_MAXBURST_OPTION = BIT(2), /*!< configure the DMA max burst related parameters */ + DMA_ARBITRATION_OPTION = BIT(3), /*!< configure the DMA arbitration related parameters */ + STORE_OPTION = BIT(4), /*!< configure the store forward mode related parameters */ + DMA_OPTION = BIT(5), /*!< configure the DMA control related parameters */ + VLAN_OPTION = BIT(6), /*!< configure the VLAN tag related parameters */ + FLOWCTL_OPTION = BIT(7), /*!< configure the flow control related parameters */ + HASHH_OPTION = BIT(8), /*!< configure the hash list high 32-bit related parameters */ + HASHL_OPTION = BIT(9), /*!< configure the hash list low 32-bit related parameters */ + FILTER_OPTION = BIT(10), /*!< configure the frame filter control related parameters */ + HALFDUPLEX_OPTION = BIT(11), /*!< configure the halfduplex related parameters */ + TIMER_OPTION = BIT(12), /*!< configure the frame timer related parameters */ + INTERFRAMEGAP_OPTION = BIT(13), /*!< configure the inter frame gap related parameters */ +}enet_option_enum; + +/* phy mode and mac loopback configurations */ +typedef enum +{ + ENET_AUTO_NEGOTIATION = 0x01u, /*!< PHY auto negotiation */ + ENET_100M_FULLDUPLEX = (ENET_MAC_CFG_SPD | ENET_MAC_CFG_DPM), /*!< 100Mbit/s, full-duplex */ + ENET_100M_HALFDUPLEX = ENET_MAC_CFG_SPD , /*!< 100Mbit/s, half-duplex */ + ENET_10M_FULLDUPLEX = ENET_MAC_CFG_DPM, /*!< 10Mbit/s, full-duplex */ + ENET_10M_HALFDUPLEX = (uint32_t)0x00000000U, /*!< 10Mbit/s, half-duplex */ + ENET_LOOPBACKMODE = (ENET_MAC_CFG_LBM | ENET_MAC_CFG_DPM) /*!< MAC in loopback mode at the MII */ +}enet_mediamode_enum; + +/* IP frame checksum function */ +typedef enum +{ + ENET_NO_AUTOCHECKSUM = (uint32_t)0x00000000U, /*!< disable IP frame checksum function */ + ENET_AUTOCHECKSUM_DROP_FAILFRAMES = ENET_MAC_CFG_IPFCO, /*!< enable IP frame checksum function */ + ENET_AUTOCHECKSUM_ACCEPT_FAILFRAMES = (ENET_MAC_CFG_IPFCO|ENET_DMA_CTL_DTCERFD) /*!< enable IP frame checksum function, and the received frame + with only payload error but no other errors will not be dropped */ +}enet_chksumconf_enum; + +/* received frame filter function */ +typedef enum +{ + ENET_PROMISCUOUS_MODE = ENET_MAC_FRMF_PM, /*!< promiscuous mode enabled */ + ENET_RECEIVEALL = (int32_t)ENET_MAC_FRMF_FAR, /*!< all received frame are forwarded to application */ + ENET_BROADCAST_FRAMES_PASS = (uint32_t)0x00000000U, /*!< the address filters pass all received broadcast frames */ + ENET_BROADCAST_FRAMES_DROP = ENET_MAC_FRMF_BFRMD /*!< the address filters filter all incoming broadcast frames */ +}enet_frmrecept_enum; + +/* register group value get */ +typedef enum +{ + ALL_MAC_REG = 0, /*!< MAC register group */ + ALL_MSC_REG = 22, /*!< MSC register group */ + ALL_PTP_REG = 33, /*!< PTP register group */ + ALL_DMA_REG = 44, /*!< DMA register group */ +}enet_registers_type_enum; + +/* dma direction select */ +typedef enum +{ + ENET_DMA_TX = ENET_DMA_STAT_TP, /*!< DMA transmit direction */ + ENET_DMA_RX = ENET_DMA_STAT_RP /*!< DMA receive direction */ +}enet_dmadirection_enum; + +/* PHY operation direction select */ +typedef enum +{ + ENET_PHY_READ = (uint32_t)0x00000000, /*!< read PHY */ + ENET_PHY_WRITE = ENET_MAC_PHY_CTL_PW /*!< write PHY */ +}enet_phydirection_enum; + +/* register operation direction select */ +typedef enum +{ + ENET_REG_READ, /*!< read register */ + ENET_REG_WRITE /*!< write register */ +}enet_regdirection_enum; + +/* ENET MAC addresses */ +typedef enum +{ + ENET_MAC_ADDRESS0 = ((uint32_t)0x00000000), /*!< MAC address0 */ + ENET_MAC_ADDRESS1 = ((uint32_t)0x00000008), /*!< MAC address1 */ + ENET_MAC_ADDRESS2 = ((uint32_t)0x00000010), /*!< MAC address2 */ + ENET_MAC_ADDRESS3 = ((uint32_t)0x00000018) /*!< MAC address3 */ +}enet_macaddress_enum; + +/* descriptor information */ +typedef enum +{ + TXDESC_COLLISION_COUNT, /*!< the number of collisions occurred before the frame was transmitted */ + TXDESC_BUFFER_1_ADDR, /*!< transmit frame buffer 1 address */ + RXDESC_FRAME_LENGTH, /*!< the byte length of the received frame that was transferred to the buffer */ + RXDESC_BUFFER_1_SIZE, /*!< receive buffer 1 size */ + RXDESC_BUFFER_2_SIZE, /*!< receive buffer 2 size */ + RXDESC_BUFFER_1_ADDR /*!< receive frame buffer 1 address */ +}enet_descstate_enum; + +/* structure for initialization of the ENET */ +typedef struct +{ + uint32_t option_enable; /*!< select which function to configure */ + uint32_t forward_frame; /*!< frame forward related parameters */ + uint32_t dmabus_mode; /*!< DMA bus mode related parameters */ + uint32_t dma_maxburst; /*!< DMA max burst related parameters */ + uint32_t dma_arbitration; /*!< DMA Tx and Rx arbitration related parameters */ + uint32_t store_forward_mode; /*!< store forward mode related parameters */ + uint32_t dma_function; /*!< DMA control related parameters */ + uint32_t vlan_config; /*!< VLAN tag related parameters */ + uint32_t flow_control; /*!< flow control related parameters */ + uint32_t hashtable_high; /*!< hash list high 32-bit related parameters */ + uint32_t hashtable_low; /*!< hash list low 32-bit related parameters */ + uint32_t framesfilter_mode; /*!< frame filter control related parameters */ + uint32_t halfduplex_param; /*!< halfduplex related parameters */ + uint32_t timer_config; /*!< frame timer related parameters */ + uint32_t interframegap; /*!< inter frame gap related parameters */ +}enet_initpara_struct; + +/* structure for ENET DMA desciptors */ +typedef struct +{ + uint32_t status; /*!< status */ + uint32_t control_buffer_size; /*!< control and buffer1, buffer2 lengths */ + uint32_t buffer1_addr; /*!< buffer1 address pointer/timestamp low */ + uint32_t buffer2_next_desc_addr; /*!< buffer2 or next descriptor address pointer/timestamp high */ +} enet_descriptors_struct; + +/* structure of PTP system time */ +typedef struct +{ + uint32_t second; /*!< second of system time */ + uint32_t nanosecond; /*!< nanosecond of system time */ + uint32_t sign; /*!< sign of system time */ +}enet_ptp_systime_struct; + +/* mac_cfg register value */ +#define MAC_CFG_BOL(regval) (BITS(5,6) & ((uint32_t)(regval) << 5)) /*!< write value to ENET_MAC_CFG_BOL bit field */ +#define ENET_BACKOFFLIMIT_10 MAC_CFG_BOL(0) /*!< min (n, 10) */ +#define ENET_BACKOFFLIMIT_8 MAC_CFG_BOL(1) /*!< min (n, 8) */ +#define ENET_BACKOFFLIMIT_4 MAC_CFG_BOL(2) /*!< min (n, 4) */ +#define ENET_BACKOFFLIMIT_1 MAC_CFG_BOL(3) /*!< min (n, 1) */ + +#define MAC_CFG_IGBS(regval) (BITS(17,19) & ((uint32_t)(regval) << 17)) /*!< write value to ENET_MAC_CFG_IGBS bit field */ +#define ENET_INTERFRAMEGAP_96BIT MAC_CFG_IGBS(0) /*!< minimum 96 bit times */ +#define ENET_INTERFRAMEGAP_88BIT MAC_CFG_IGBS(1) /*!< minimum 88 bit times */ +#define ENET_INTERFRAMEGAP_80BIT MAC_CFG_IGBS(2) /*!< minimum 80 bit times */ +#define ENET_INTERFRAMEGAP_72BIT MAC_CFG_IGBS(3) /*!< minimum 72 bit times */ +#define ENET_INTERFRAMEGAP_64BIT MAC_CFG_IGBS(4) /*!< minimum 64 bit times */ +#define ENET_INTERFRAMEGAP_56BIT MAC_CFG_IGBS(5) /*!< minimum 56 bit times */ +#define ENET_INTERFRAMEGAP_48BIT MAC_CFG_IGBS(6) /*!< minimum 48 bit times */ +#define ENET_INTERFRAMEGAP_40BIT MAC_CFG_IGBS(7) /*!< minimum 40 bit times */ + +#define ENET_WATCHDOG_ENABLE ((uint32_t)0x00000000U) /*!< the MAC allows no more than 2048 bytes of the frame being received */ +#define ENET_WATCHDOG_DISABLE ENET_MAC_CFG_WDD /*!< the MAC disables the watchdog timer on the receiver, and can receive frames of up to 16384 bytes */ + +#define ENET_JABBER_ENABLE ((uint32_t)0x00000000U) /*!< the maximum transmission byte is 2048 */ +#define ENET_JABBER_DISABLE ENET_MAC_CFG_JBD /*!< the maximum transmission byte can be 16384 */ + +#define ENET_CARRIERSENSE_ENABLE ((uint32_t)0x00000000U) /*!< the MAC transmitter generates carrier sense error and aborts the transmission */ +#define ENET_CARRIERSENSE_DISABLE ENET_MAC_CFG_CSD /*!< the MAC transmitter ignores the MII CRS signal during frame transmission in half-duplex mode */ + +#define ENET_SPEEDMODE_10M ((uint32_t)0x00000000U) /*!< 10 Mbit/s */ +#define ENET_SPEEDMODE_100M ENET_MAC_CFG_SPD /*!< 100 Mbit/s */ + +#define ENET_RECEIVEOWN_ENABLE ((uint32_t)0x00000000U) /*!< the MAC receives all packets that are given by the PHY while transmitting */ +#define ENET_RECEIVEOWN_DISABLE ENET_MAC_CFG_ROD /*!< the MAC disables the reception of frames in half-duplex mode */ + +#define ENET_LOOPBACKMODE_ENABLE ENET_MAC_CFG_LBM /*!< the MAC operates in loopback mode at the MII */ +#define ENET_LOOPBACKMODE_DISABLE ((uint32_t)0x00000000U) /*!< the MAC operates in normal mode */ + +#define ENET_MODE_FULLDUPLEX ENET_MAC_CFG_DPM /*!< full-duplex mode enable */ +#define ENET_MODE_HALFDUPLEX ((uint32_t)0x00000000U) /*!< half-duplex mode enable */ + +#define ENET_CHECKSUMOFFLOAD_ENABLE ENET_MAC_CFG_IPFCO /*!< IP frame checksum offload function enabled for received IP frame */ +#define ENET_CHECKSUMOFFLOAD_DISABLE ((uint32_t)0x00000000U) /*!< the checksum offload function in the receiver is disabled */ + +#define ENET_RETRYTRANSMISSION_ENABLE ((uint32_t)0x00000000U) /*!< the MAC attempts retries up to 16 times based on the settings of BOL*/ +#define ENET_RETRYTRANSMISSION_DISABLE ENET_MAC_CFG_RTD /*!< the MAC attempts only 1 transmission */ + +#define ENET_AUTO_PADCRC_DROP_ENABLE ENET_MAC_CFG_APCD /*!< the MAC strips the Pad/FCS field on received frames */ +#define ENET_AUTO_PADCRC_DROP_DISABLE ((uint32_t)0x00000000U) /*!< the MAC forwards all received frames without modify it */ +#define ENET_AUTO_PADCRC_DROP ENET_MAC_CFG_APCD /*!< the function of the MAC strips the Pad/FCS field on received frames */ + +#define ENET_DEFERRALCHECK_ENABLE ENET_MAC_CFG_DFC /*!< the deferral check function is enabled in the MAC */ +#define ENET_DEFERRALCHECK_DISABLE ((uint32_t)0x00000000U) /*!< the deferral check function is disabled */ + +/* mac_frmf register value */ +#define MAC_FRMF_PCFRM(regval) (BITS(6,7) & ((uint32_t)(regval) << 6)) /*!< write value to ENET_MAC_FRMF_PCFRM bit field */ +#define ENET_PCFRM_PREVENT_ALL MAC_FRMF_PCFRM(0) /*!< MAC prevents all control frames from reaching the application */ +#define ENET_PCFRM_PREVENT_PAUSEFRAME MAC_FRMF_PCFRM(1) /*!< MAC only forwards all other control frames except pause control frame */ +#define ENET_PCFRM_FORWARD_ALL MAC_FRMF_PCFRM(2) /*!< MAC forwards all control frames to application even if they fail the address filter */ +#define ENET_PCFRM_FORWARD_FILTERED MAC_FRMF_PCFRM(3) /*!< MAC forwards control frames that only pass the address filter */ + +#define ENET_RX_FILTER_DISABLE ENET_MAC_FRMF_FAR /*!< all received frame are forwarded to application */ +#define ENET_RX_FILTER_ENABLE ((uint32_t)0x00000000U) /*!< only the frame passed the filter can be forwarded to application */ + +#define ENET_SRC_FILTER_NORMAL_ENABLE ENET_MAC_FRMF_SAFLT /*!< filter source address */ +#define ENET_SRC_FILTER_INVERSE_ENABLE (ENET_MAC_FRMF_SAFLT | ENET_MAC_FRMF_SAIFLT) /*!< inverse source address filtering result */ +#define ENET_SRC_FILTER_DISABLE ((uint32_t)0x00000000U) /*!< source address function in filter disable */ +#define ENET_SRC_FILTER ENET_MAC_FRMF_SAFLT /*!< filter source address function */ +#define ENET_SRC_FILTER_INVERSE ENET_MAC_FRMF_SAIFLT /*!< inverse source address filtering result function */ + +#define ENET_BROADCASTFRAMES_ENABLE ((uint32_t)0x00000000U) /*!< the address filters pass all received broadcast frames */ +#define ENET_BROADCASTFRAMES_DISABLE ENET_MAC_FRMF_BFRMD /*!< the address filters filter all incoming broadcast frames */ + +#define ENET_DEST_FILTER_INVERSE_ENABLE ENET_MAC_FRMF_DAIFLT /*!< inverse DA filtering result */ +#define ENET_DEST_FILTER_INVERSE_DISABLE ((uint32_t)0x00000000U) /*!< not inverse DA filtering result */ +#define ENET_DEST_FILTER_INVERSE ENET_MAC_FRMF_DAIFLT /*!< inverse DA filtering result function */ + +#define ENET_PROMISCUOUS_ENABLE ENET_MAC_FRMF_PM /*!< promiscuous mode enabled */ +#define ENET_PROMISCUOUS_DISABLE ((uint32_t)0x00000000U) /*!< promiscuous mode disabled */ + +#define ENET_MULTICAST_FILTER_HASH_OR_PERFECT (ENET_MAC_FRMF_HMF | ENET_MAC_FRMF_HPFLT) /*!< pass multicast frames that match either the perfect or the hash filtering */ +#define ENET_MULTICAST_FILTER_HASH ENET_MAC_FRMF_HMF /*!< pass multicast frames that match the hash filtering */ +#define ENET_MULTICAST_FILTER_PERFECT ((uint32_t)0x00000000U) /*!< pass multicast frames that match the perfect filtering */ +#define ENET_MULTICAST_FILTER_NONE ENET_MAC_FRMF_MFD /*!< all multicast frames are passed */ +#define ENET_MULTICAST_FILTER_PASS ENET_MAC_FRMF_MFD /*!< pass all multicast frames function */ +#define ENET_MULTICAST_FILTER_HASH_MODE ENET_MAC_FRMF_HMF /*!< HASH multicast filter function */ +#define ENET_FILTER_MODE_EITHER ENET_MAC_FRMF_HPFLT /*!< HASH or perfect filter function */ + +#define ENET_UNICAST_FILTER_EITHER (ENET_MAC_FRMF_HUF | ENET_MAC_FRMF_HPFLT) /*!< pass unicast frames that match either the perfect or the hash filtering */ +#define ENET_UNICAST_FILTER_HASH ENET_MAC_FRMF_HUF /*!< pass unicast frames that match the hash filtering */ +#define ENET_UNICAST_FILTER_PERFECT ((uint32_t)0x00000000U) /*!< pass unicast frames that match the perfect filtering */ +#define ENET_UNICAST_FILTER_HASH_MODE ENET_MAC_FRMF_HUF /*!< HASH unicast filter function */ + +/* mac_phy_ctl register value */ +#define MAC_PHY_CTL_CLR(regval) (BITS(2,4) & ((uint32_t)(regval) << 2)) /*!< write value to ENET_MAC_PHY_CTL_CLR bit field */ +#define ENET_MDC_HCLK_DIV42 MAC_PHY_CTL_CLR(0) /*!< HCLK:60-100 MHz; MDC clock= HCLK/42 */ +#define ENET_MDC_HCLK_DIV62 MAC_PHY_CTL_CLR(1) /*!< HCLK:100-120 MHz; MDC clock= HCLK/62 */ +#define ENET_MDC_HCLK_DIV16 MAC_PHY_CTL_CLR(2) /*!< HCLK:20-35 MHz; MDC clock= HCLK/16 */ +#define ENET_MDC_HCLK_DIV26 MAC_PHY_CTL_CLR(3) /*!< HCLK:35-60 MHz; MDC clock= HCLK/26 */ + +#define MAC_PHY_CTL_PR(regval) (BITS(6,10) & ((uint32_t)(regval) << 6)) /*!< write value to ENET_MAC_PHY_CTL_PR bit field */ + +#define MAC_PHY_CTL_PA(regval) (BITS(11,15) & ((uint32_t)(regval) << 11)) /*!< write value to ENET_MAC_PHY_CTL_PA bit field */ + +/* mac_phy_data register value */ +#define MAC_PHY_DATA_PD(regval) (BITS(0,15) & ((uint32_t)(regval) << 0)) /*!< write value to ENET_MAC_PHY_DATA_PD bit field */ + +/* mac_fctl register value */ +#define MAC_FCTL_PLTS(regval) (BITS(4,5) & ((uint32_t)(regval) << 4)) /*!< write value to ENET_MAC_FCTL_PLTS bit field */ +#define ENET_PAUSETIME_MINUS4 MAC_FCTL_PLTS(0) /*!< pause time minus 4 slot times */ +#define ENET_PAUSETIME_MINUS28 MAC_FCTL_PLTS(1) /*!< pause time minus 28 slot times */ +#define ENET_PAUSETIME_MINUS144 MAC_FCTL_PLTS(2) /*!< pause time minus 144 slot times */ +#define ENET_PAUSETIME_MINUS256 MAC_FCTL_PLTS(3) /*!< pause time minus 256 slot times */ + +#define ENET_ZERO_QUANTA_PAUSE_ENABLE ((uint32_t)0x00000000U) /*!< enable the automatic zero-quanta generation function */ +#define ENET_ZERO_QUANTA_PAUSE_DISABLE ENET_MAC_FCTL_DZQP /*!< disable the automatic zero-quanta generation function */ +#define ENET_ZERO_QUANTA_PAUSE ENET_MAC_FCTL_DZQP /*!< the automatic zero-quanta generation function */ + +#define ENET_MAC0_AND_UNIQUE_ADDRESS_PAUSEDETECT ENET_MAC_FCTL_UPFDT /*!< besides the unique multicast address, MAC also use the MAC0 address to detect pause frame */ +#define ENET_UNIQUE_PAUSEDETECT ((uint32_t)0x00000000U) /*!< only the unique multicast address for pause frame which is specified in IEEE802.3 can be detected */ + +#define ENET_RX_FLOWCONTROL_ENABLE ENET_MAC_FCTL_RFCEN /*!< enable decoding function for the received pause frame and process it */ +#define ENET_RX_FLOWCONTROL_DISABLE ((uint32_t)0x00000000U) /*!< decode function for pause frame is disabled */ +#define ENET_RX_FLOWCONTROL ENET_MAC_FCTL_RFCEN /*!< decoding function for the received pause frame and process it */ + +#define ENET_TX_FLOWCONTROL_ENABLE ENET_MAC_FCTL_TFCEN /*!< enable the flow control operation in the MAC */ +#define ENET_TX_FLOWCONTROL_DISABLE ((uint32_t)0x00000000U) /*!< disable the flow control operation in the MAC */ +#define ENET_TX_FLOWCONTROL ENET_MAC_FCTL_TFCEN /*!< the flow control operation in the MAC */ + +#define ENET_BACK_PRESSURE_ENABLE ENET_MAC_FCTL_FLCBBKPA /*!< enable the back pressure operation in the MAC */ +#define ENET_BACK_PRESSURE_DISABLE ((uint32_t)0x00000000U) /*!< disable the back pressure operation in the MAC */ +#define ENET_BACK_PRESSURE ENET_MAC_FCTL_FLCBBKPA /*!< the back pressure operation in the MAC */ + +#define MAC_FCTL_PTM(regval) (BITS(16,31) & ((uint32_t)(regval) << 16)) /*!< write value to ENET_MAC_FCTL_PTM bit field */ +/* mac_vlt register value */ +#define MAC_VLT_VLTI(regval) (BITS(0,15) & ((uint32_t)(regval) << 0)) /*!< write value to ENET_MAC_VLT_VLTI bit field */ + +#define ENET_VLANTAGCOMPARISON_12BIT ENET_MAC_VLT_VLTC /*!< only low 12 bits of the VLAN tag are used for comparison */ +#define ENET_VLANTAGCOMPARISON_16BIT ((uint32_t)0x00000000U) /*!< all 16 bits of the VLAN tag are used for comparison */ + +/* mac_wum register value */ +#define ENET_WUM_FLAG_WUFFRPR ENET_MAC_WUM_WUFFRPR /*!< wakeup frame filter register poniter reset */ +#define ENET_WUM_FLAG_WUFR ENET_MAC_WUM_WUFR /*!< wakeup frame received */ +#define ENET_WUM_FLAG_MPKR ENET_MAC_WUM_MPKR /*!< magic packet received */ +#define ENET_WUM_POWER_DOWN ENET_MAC_WUM_PWD /*!< power down mode */ +#define ENET_WUM_MAGIC_PACKET_FRAME ENET_MAC_WUM_MPEN /*!< enable a wakeup event due to magic packet reception */ +#define ENET_WUM_WAKE_UP_FRAME ENET_MAC_WUM_WFEN /*!< enable a wakeup event due to wakeup frame reception */ +#define ENET_WUM_GLOBAL_UNICAST ENET_MAC_WUM_GU /*!< any received unicast frame passed filter is considered to be a wakeup frame */ + +/* mac_addr0h register value */ +#define MAC_ADDR0H_ADDR0H(regval) (BITS(0,15) & ((uint32_t)(regval) << 0)) /*!< write value to ENET_MAC_ADDR0H_ADDR0H bit field */ + +/* mac_addrxh register value, x = 1,2,3 */ +#define MAC_ADDR123H_ADDR123H(regval) (BITS(0,15) & ((uint32_t)(regval) << 0)) /*!< write value to ENET_MAC_ADDRxH_ADDRxH(x=1,2,3) bit field */ + +#define ENET_ADDRESS_MASK_BYTE0 BIT(24) /*!< low register bits [7:0] */ +#define ENET_ADDRESS_MASK_BYTE1 BIT(25) /*!< low register bits [15:8] */ +#define ENET_ADDRESS_MASK_BYTE2 BIT(26) /*!< low register bits [23:16] */ +#define ENET_ADDRESS_MASK_BYTE3 BIT(27) /*!< low register bits [31:24] */ +#define ENET_ADDRESS_MASK_BYTE4 BIT(28) /*!< high register bits [7:0] */ +#define ENET_ADDRESS_MASK_BYTE5 BIT(29) /*!< high register bits [15:8] */ + +#define ENET_ADDRESS_FILTER_SA BIT(30) /*!< use MAC address[47:0] is to compare with the SA fields of the received frame */ +#define ENET_ADDRESS_FILTER_DA ((uint32_t)0x00000000) /*!< use MAC address[47:0] is to compare with the DA fields of the received frame */ + +/* mac_fcth register value */ +#define MAC_FCTH_RFA(regval) ((BITS(0,2) & ((uint32_t)(regval) << 0))<<8) /*!< write value to ENET_MAC_FCTH_RFA bit field */ +#define ENET_ACTIVE_THRESHOLD_256BYTES MAC_FCTH_RFA(0) /*!< threshold level is 256 bytes */ +#define ENET_ACTIVE_THRESHOLD_512BYTES MAC_FCTH_RFA(1) /*!< threshold level is 512 bytes */ +#define ENET_ACTIVE_THRESHOLD_768BYTES MAC_FCTH_RFA(2) /*!< threshold level is 768 bytes */ +#define ENET_ACTIVE_THRESHOLD_1024BYTES MAC_FCTH_RFA(3) /*!< threshold level is 1024 bytes */ +#define ENET_ACTIVE_THRESHOLD_1280BYTES MAC_FCTH_RFA(4) /*!< threshold level is 1280 bytes */ +#define ENET_ACTIVE_THRESHOLD_1536BYTES MAC_FCTH_RFA(5) /*!< threshold level is 1536 bytes */ +#define ENET_ACTIVE_THRESHOLD_1792BYTES MAC_FCTH_RFA(6) /*!< threshold level is 1792 bytes */ + +#define MAC_FCTH_RFD(regval) ((BITS(4,6) & ((uint32_t)(regval) << 4))<<8) /*!< write value to ENET_MAC_FCTH_RFD bit field */ +#define ENET_DEACTIVE_THRESHOLD_256BYTES MAC_FCTH_RFD(0) /*!< threshold level is 256 bytes */ +#define ENET_DEACTIVE_THRESHOLD_512BYTES MAC_FCTH_RFD(1) /*!< threshold level is 512 bytes */ +#define ENET_DEACTIVE_THRESHOLD_768BYTES MAC_FCTH_RFD(2) /*!< threshold level is 768 bytes */ +#define ENET_DEACTIVE_THRESHOLD_1024BYTES MAC_FCTH_RFD(3) /*!< threshold level is 1024 bytes */ +#define ENET_DEACTIVE_THRESHOLD_1280BYTES MAC_FCTH_RFD(4) /*!< threshold level is 1280 bytes */ +#define ENET_DEACTIVE_THRESHOLD_1536BYTES MAC_FCTH_RFD(5) /*!< threshold level is 1536 bytes */ +#define ENET_DEACTIVE_THRESHOLD_1792BYTES MAC_FCTH_RFD(6) /*!< threshold level is 1792 bytes */ + +/* msc_ctl register value */ +#define ENET_MSC_COUNTER_STOP_ROLLOVER ENET_MSC_CTL_CTSR /*!< counter stop rollover */ +#define ENET_MSC_RESET_ON_READ ENET_MSC_CTL_RTOR /*!< reset on read */ +#define ENET_MSC_COUNTERS_FREEZE ENET_MSC_CTL_MCFZ /*!< MSC counter freeze */ + +/* ptp_tsctl register value */ +#define ENET_RXTX_TIMESTAMP ENET_PTP_TSCTL_TMSEN /*!< enable timestamp function for transmit and receive frames */ +#define ENET_PTP_TIMESTAMP_INT ENET_PTP_TSCTL_TMSITEN /*!< timestamp interrupt trigger enable */ + +/* ptp_ssinc register value */ +#define PTP_SSINC_STMSSI(regval) (BITS(0,7) & ((uint32_t)(regval) << 0)) /*!< write value to ENET_PTP_SSINC_STMSSI bit field */ + +/* ptp_tsl register value */ +#define GET_PTP_TSL_STMSS(regval) GET_BITS((uint32_t)(regval),0,30) /*!< get value of ENET_PTP_TSL_STMSS bit field */ + +#define ENET_PTP_TIME_POSITIVE ((uint32_t)0x00000000) /*!< time value is positive */ +#define ENET_PTP_TIME_NEGATIVE ENET_PTP_TSL_STS /*!< time value is negative */ + +#define GET_PTP_TSL_STS(regval) (((regval) & BIT(31)) >> (31U)) /*!< get value of ENET_PTP_TSL_STS bit field */ + +/* ptp_tsul register value */ +#define PTP_TSUL_TMSUSS(regval) (BITS(0,30) & ((uint32_t)(regval) << 0)) /*!< write value to ENET_PTP_TSUL_TMSUSS bit field */ + +#define ENET_PTP_ADD_TO_TIME ((uint32_t)0x00000000) /*!< timestamp update value is added to system time */ +#define ENET_PTP_SUBSTRACT_FROM_TIME ENET_PTP_TSUL_TMSUPNS /*!< timestamp update value is subtracted from system time */ + +/* dma_bctl register value */ +#define DMA_BCTL_DPSL(regval) (BITS(2,6) & ((uint32_t)(regval) << 2)) /*!< write value to ENET_DMA_BCTL_DPSL bit field */ +#define GET_DMA_BCTL_DPSL(regval) GET_BITS((regval),2,6) /*!< get value of ENET_DMA_BCTL_DPSL bit field */ + +#define DMA_BCTL_PGBL(regval) (BITS(8,13) & ((uint32_t)(regval) << 8)) /*!< write value to ENET_DMA_BCTL_PGBL bit field */ +#define ENET_PGBL_1BEAT DMA_BCTL_PGBL(1) /*!< maximum number of beats is 1 */ +#define ENET_PGBL_2BEAT DMA_BCTL_PGBL(2) /*!< maximum number of beats is 2 */ +#define ENET_PGBL_4BEAT DMA_BCTL_PGBL(4) /*!< maximum number of beats is 4 */ +#define ENET_PGBL_8BEAT DMA_BCTL_PGBL(8) /*!< maximum number of beats is 8 */ +#define ENET_PGBL_16BEAT DMA_BCTL_PGBL(16) /*!< maximum number of beats is 16 */ +#define ENET_PGBL_32BEAT DMA_BCTL_PGBL(32) /*!< maximum number of beats is 32 */ +#define ENET_PGBL_4xPGBL_4BEAT (DMA_BCTL_PGBL(1)|ENET_DMA_BCTL_FPBL) /*!< maximum number of beats is 4 */ +#define ENET_PGBL_4xPGBL_8BEAT (DMA_BCTL_PGBL(2)|ENET_DMA_BCTL_FPBL) /*!< maximum number of beats is 8 */ +#define ENET_PGBL_4xPGBL_16BEAT (DMA_BCTL_PGBL(4)|ENET_DMA_BCTL_FPBL) /*!< maximum number of beats is 16 */ +#define ENET_PGBL_4xPGBL_32BEAT (DMA_BCTL_PGBL(8)|ENET_DMA_BCTL_FPBL) /*!< maximum number of beats is 32 */ +#define ENET_PGBL_4xPGBL_64BEAT (DMA_BCTL_PGBL(16)|ENET_DMA_BCTL_FPBL) /*!< maximum number of beats is 64 */ +#define ENET_PGBL_4xPGBL_128BEAT (DMA_BCTL_PGBL(32)|ENET_DMA_BCTL_FPBL) /*!< maximum number of beats is 128 */ + +#define DMA_BCTL_RTPR(regval) (BITS(14,15) & ((uint32_t)(regval) << 14)) /*!< write value to ENET_DMA_BCTL_RTPR bit field */ +#define ENET_ARBITRATION_RXTX_1_1 DMA_BCTL_RTPR(0) /*!< receive and transmit priority ratio is 1:1*/ +#define ENET_ARBITRATION_RXTX_2_1 DMA_BCTL_RTPR(1) /*!< receive and transmit priority ratio is 2:1*/ +#define ENET_ARBITRATION_RXTX_3_1 DMA_BCTL_RTPR(2) /*!< receive and transmit priority ratio is 3:1 */ +#define ENET_ARBITRATION_RXTX_4_1 DMA_BCTL_RTPR(3) /*!< receive and transmit priority ratio is 4:1 */ +#define ENET_ARBITRATION_RXPRIORTX ENET_DMA_BCTL_DAB /*!< RxDMA has higher priority than TxDMA */ + +#define ENET_FIXED_BURST_ENABLE ENET_DMA_BCTL_FB /*!< AHB can only use SINGLE/INCR4/INCR8/INCR16 during start of normal burst transfers */ +#define ENET_FIXED_BURST_DISABLE ((uint32_t)0x00000000) /*!< AHB can use SINGLE/INCR burst transfer operations */ + +#define DMA_BCTL_RXDP(regval) (BITS(17,22) & ((uint32_t)(regval) << 17)) /*!< write value to ENET_DMA_BCTL_RXDP bit field */ +#define ENET_RXDP_1BEAT DMA_BCTL_RXDP(1) /*!< maximum number of beats 1 */ +#define ENET_RXDP_2BEAT DMA_BCTL_RXDP(2) /*!< maximum number of beats 2 */ +#define ENET_RXDP_4BEAT DMA_BCTL_RXDP(4) /*!< maximum number of beats 4 */ +#define ENET_RXDP_8BEAT DMA_BCTL_RXDP(8) /*!< maximum number of beats 8 */ +#define ENET_RXDP_16BEAT DMA_BCTL_RXDP(16) /*!< maximum number of beats 16 */ +#define ENET_RXDP_32BEAT DMA_BCTL_RXDP(32) /*!< maximum number of beats 32 */ +#define ENET_RXDP_4xPGBL_4BEAT (DMA_BCTL_RXDP(1)|ENET_DMA_BCTL_FPBL) /*!< maximum number of beats 4 */ +#define ENET_RXDP_4xPGBL_8BEAT (DMA_BCTL_RXDP(2)|ENET_DMA_BCTL_FPBL) /*!< maximum number of beats 8 */ +#define ENET_RXDP_4xPGBL_16BEAT (DMA_BCTL_RXDP(4)|ENET_DMA_BCTL_FPBL) /*!< maximum number of beats 16 */ +#define ENET_RXDP_4xPGBL_32BEAT (DMA_BCTL_RXDP(8)|ENET_DMA_BCTL_FPBL) /*!< maximum number of beats 32 */ +#define ENET_RXDP_4xPGBL_64BEAT (DMA_BCTL_RXDP(16)|ENET_DMA_BCTL_FPBL) /*!< maximum number of beats 64 */ +#define ENET_RXDP_4xPGBL_128BEAT (DMA_BCTL_RXDP(32)|ENET_DMA_BCTL_FPBL) /*!< maximum number of beats 128 */ + +#define ENET_RXTX_DIFFERENT_PGBL ENET_DMA_BCTL_UIP /*!< RxDMA uses the RXDP[5:0], while TxDMA uses the PGBL[5:0] */ +#define ENET_RXTX_SAME_PGBL ((uint32_t)0x00000000) /*!< RxDMA/TxDMA uses PGBL[5:0] */ + +#define ENET_ADDRESS_ALIGN_ENABLE ENET_DMA_BCTL_AA /*!< enabled address-aligned */ +#define ENET_ADDRESS_ALIGN_DISABLE ((uint32_t)0x00000000) /*!< disable address-aligned */ + +/* dma_stat register value */ +#define GET_DMA_STAT_RP(regval) GET_BITS((uint32_t)(regval),17,19) /*!< get value of ENET_DMA_STAT_RP bit field */ +#define ENET_RX_STATE_STOPPED ((uint32_t)0x00000000) /*!< reset or stop rx command issued */ +#define ENET_RX_STATE_FETCHING BIT(17) /*!< fetching the Rx descriptor */ +#define ENET_RX_STATE_WAITING (BIT(17)|BIT(18)) /*!< waiting for receive packet */ +#define ENET_RX_STATE_SUSPENDED BIT(19) /*!< Rx descriptor unavailable */ +#define ENET_RX_STATE_CLOSING (BIT(17)|BIT(19)) /*!< closing receive descriptor */ +#define ENET_RX_STATE_QUEUING ENET_DMA_STAT_RP /*!< transferring the receive packet data from recevie buffer to host memory */ + +#define GET_DMA_STAT_TP(regval) GET_BITS((uint32_t)(regval),20,22) /*!< get value of ENET_DMA_STAT_TP bit field */ +#define ENET_TX_STATE_STOPPED ((uint32_t)0x00000000) /*!< reset or stop Tx Command issued */ +#define ENET_TX_STATE_FETCHING BIT(20) /*!< fetching the Tx descriptor */ +#define ENET_TX_STATE_WAITING BIT(21) /*!< waiting for status */ +#define ENET_TX_STATE_READING (BIT(20)|BIT(21)) /*!< reading the data from host memory buffer and queuing it to transmit buffer */ +#define ENET_TX_STATE_SUSPENDED (BIT(21)|BIT(22)) /*!< Tx descriptor unavailabe or transmit buffer underflow */ +#define ENET_TX_STATE_CLOSING ENET_DMA_STAT_TP /*!< closing Tx descriptor */ + +#define GET_DMA_STAT_EB(regval) GET_BITS((uint32_t)(regval),23,25) /*!< get value of ENET_DMA_STAT_EB bit field */ +#define ENET_ERROR_TXDATA_TRANSFER BIT(23) /*!< error during data transfer by TxDMA or RxDMA */ +#define ENET_ERROR_READ_TRANSFER BIT(24) /*!< error during write transfer or read transfer */ +#define ENET_ERROR_DESC_ACCESS BIT(25) /*!< error during descriptor or buffer access */ + +/* dma_ctl register value */ +#define DMA_CTL_RTHC(regval) (BITS(3,4) & ((uint32_t)(regval) << 3)) /*!< write value to ENET_DMA_CTL_RTHC bit field */ +#define ENET_RX_THRESHOLD_64BYTES DMA_CTL_RTHC(0) /*!< threshold level is 64 Bytes */ +#define ENET_RX_THRESHOLD_32BYTES DMA_CTL_RTHC(1) /*!< threshold level is 32 Bytes */ +#define ENET_RX_THRESHOLD_96BYTES DMA_CTL_RTHC(2) /*!< threshold level is 96 Bytes */ +#define ENET_RX_THRESHOLD_128BYTES DMA_CTL_RTHC(3) /*!< threshold level is 128 Bytes */ + +#define DMA_CTL_TTHC(regval) (BITS(14,16) & ((uint32_t)(regval) << 14)) /*!< write value to ENET_DMA_CTL_TTHC bit field */ +#define ENET_TX_THRESHOLD_64BYTES DMA_CTL_TTHC(0) /*!< threshold level is 64 Bytes */ +#define ENET_TX_THRESHOLD_128BYTES DMA_CTL_TTHC(1) /*!< threshold level is 128 Bytes */ +#define ENET_TX_THRESHOLD_192BYTES DMA_CTL_TTHC(2) /*!< threshold level is 192 Bytes */ +#define ENET_TX_THRESHOLD_256BYTES DMA_CTL_TTHC(3) /*!< threshold level is 256 Bytes */ +#define ENET_TX_THRESHOLD_40BYTES DMA_CTL_TTHC(4) /*!< threshold level is 40 Bytes */ +#define ENET_TX_THRESHOLD_32BYTES DMA_CTL_TTHC(5) /*!< threshold level is 32 Bytes */ +#define ENET_TX_THRESHOLD_24BYTES DMA_CTL_TTHC(6) /*!< threshold level is 24 Bytes */ +#define ENET_TX_THRESHOLD_16BYTES DMA_CTL_TTHC(7) /*!< threshold level is 16 Bytes */ + +#define ENET_TCPIP_CKSUMERROR_ACCEPT ENET_DMA_CTL_DTCERFD /*!< Rx frame with only payload error but no other errors will not be dropped */ +#define ENET_TCPIP_CKSUMERROR_DROP ((uint32_t)0x00000000) /*!< all error frames will be dropped when FERF = 0 */ + +#define ENET_RX_MODE_STOREFORWARD ENET_DMA_CTL_RSFD /*!< RxFIFO operates in store-and-forward mode */ +#define ENET_RX_MODE_CUTTHROUGH ((uint32_t)0x00000000) /*!< RxFIFO operates in cut-through mode */ + +#define ENET_FLUSH_RXFRAME_ENABLE ((uint32_t)0x00000000) /*!< RxDMA flushes all frames */ +#define ENET_FLUSH_RXFRAME_DISABLE ENET_DMA_CTL_DAFRF /*!< RxDMA does not flush any frames */ +#define ENET_NO_FLUSH_RXFRAME ENET_DMA_CTL_DAFRF /*!< RxDMA does not flush frames function */ + +#define ENET_TX_MODE_STOREFORWARD ENET_DMA_CTL_TSFD /*!< TxFIFO operates in store-and-forward mode */ +#define ENET_TX_MODE_CUTTHROUGH ((uint32_t)0x00000000) /*!< TxFIFO operates in cut-through mode */ + +#define ENET_FORWARD_ERRFRAMES_ENABLE ENET_DMA_CTL_FERF /*!< all frame received with error except runt error are forwarded to memory */ +#define ENET_FORWARD_ERRFRAMES_DISABLE ((uint32_t)0x00000000) /*!< RxFIFO drop error frame */ +#define ENET_FORWARD_ERRFRAMES (ENET_DMA_CTL_FERF<<2) /*!< the function that all frame received with error except runt error are forwarded to memory */ + +#define ENET_FORWARD_UNDERSZ_GOODFRAMES_ENABLE ENET_DMA_CTL_FUF /*!< forward undersized good frames */ +#define ENET_FORWARD_UNDERSZ_GOODFRAMES_DISABLE ((uint32_t)0x00000000) /*!< RxFIFO drops all frames whose length is less than 64 bytes */ +#define ENET_FORWARD_UNDERSZ_GOODFRAMES (ENET_DMA_CTL_FUF<<2) /*!< the function that forwarding undersized good frames */ + +#define ENET_SECONDFRAME_OPT_ENABLE ((uint32_t)0x00000000) /*!< TxDMA controller operate on second frame mode enable*/ +#define ENET_SECONDFRAME_OPT_DISABLE ((uint32_t)0x00000000) /*!< TxDMA controller operate on second frame mode disable */ +#define ENET_SECONDFRAME_OPT ENET_DMA_CTL_OSF /*!< TxDMA controller operate on second frame function */ + +/* dma_mfbocnt register value */ +#define GET_DMA_MFBOCNT_MSFC(regval) GET_BITS((regval),0,15) /*!< get value of ENET_DMA_MFBOCNT_MSFC bit field */ + +#define GET_DMA_MFBOCNT_MSFA(regval) GET_BITS((regval),17,27) /*!< get value of ENET_DMA_MFBOCNT_MSFA bit field */ + +/* dma tx descriptor tdes0 register value */ +#define TDES0_CONT(regval) (BITS(3,6) & ((uint32_t)(regval) << 3)) /*!< write value to ENET DMA TDES0 CONT bit field */ +#define GET_TDES0_COCNT(regval) GET_BITS((regval),3,6) /*!< get value of ENET DMA TDES0 CONT bit field */ + +#define TDES0_CM(regval) (BITS(22,23) & ((uint32_t)(regval) << 22)) /*!< write value to ENET DMA TDES0 CM bit field */ +#define ENET_CHECKSUM_DISABLE TDES0_CM(0) /*!< checksum insertion disabled */ +#define ENET_CHECKSUM_IPV4HEADER TDES0_CM(1) /*!< only IP header checksum calculation and insertion are enabled */ +#define ENET_CHECKSUM_TCPUDPICMP_SEGMENT TDES0_CM(2) /*!< TCP/UDP/ICMP checksum insertion calculated but pseudo-header */ +#define ENET_CHECKSUM_TCPUDPICMP_FULL TDES0_CM(3) /*!< TCP/UDP/ICMP checksum insertion fully calculated */ + +/* dma tx descriptor tdes1 register value */ +#define TDES1_TB1S(regval) (BITS(0,12) & ((uint32_t)(regval) << 0)) /*!< write value to ENET DMA TDES1 TB1S bit field */ + +#define TDES1_TB2S(regval) (BITS(16,28) & ((uint32_t)(regval) << 16)) /*!< write value to ENET DMA TDES1 TB2S bit field */ + +/* dma rx descriptor rdes0 register value */ +#define RDES0_FRML(regval) (BITS(16,29) & ((uint32_t)(regval) << 16)) /*!< write value to ENET DMA RDES0 FRML bit field */ +#define GET_RDES0_FRML(regval) GET_BITS((regval),16,29) /*!< get value of ENET DMA RDES0 FRML bit field */ + +/* dma rx descriptor rdes1 register value */ +#define ENET_RECEIVE_COMPLETE_INT_ENABLE ((uint32_t)0x00000000U) /*!< RS bit immediately set after Rx completed */ +#define ENET_RECEIVE_COMPLETE_INT_DISABLE ENET_RDES1_DINTC /*!< RS bit not immediately set after Rx completed */ + +#define GET_RDES1_RB1S(regval) GET_BITS((regval),0,12) /*!< get value of ENET DMA RDES1 RB1S bit field */ + +#define GET_RDES1_RB2S(regval) GET_BITS((regval),16,28) /*!< get value of ENET DMA RDES1 RB2S bit field */ + +/* dma rx descriptor rdes4 register value */ +#define RDES4_IPPLDT(regval) (BITS(0,2) & ((uint32_t)(regval) << 0)) /*!< write value to ENET DMA RDES4 IPPLDT bit field */ +#define GET_RDES4_IPPLDT(regval) GET_BITS((regval),0,2) /*!< get value of ENET DMA RDES4 IPPLDT bit field */ + +#define RDES4_PTPMT(regval) (BITS(8,11) & ((uint32_t)(regval) << 8)) /*!< write value to ENET DMA RDES4 PTPMT bit field */ +#define GET_RDES4_PTPMT(regval) GET_BITS((regval),8,11) /*!< get value of ENET DMA RDES4 PTPMT bit field */ + +/* ENET register mask value */ +#define MAC_CFG_MASK ((uint32_t)0xFD30810FU) /*!< ENET_MAC_CFG register mask */ +#define MAC_FCTL_MASK ((uint32_t)0x0000FF41U) /*!< ENET_MAC_FCTL register mask */ +#define DMA_CTL_MASK ((uint32_t)0xF8DE3F23U) /*!< ENET_DMA_CTL register mask */ +#define DMA_BCTL_MASK ((uint32_t)0xF800007DU) /*!< ENET_DMA_BCTL register mask */ + +#define ETH_DMATXDESC_SIZE 0x10U /*!< TxDMA descriptor size */ +#define ETH_DMARXDESC_SIZE 0x10U /*!< RxDMA descriptor size */ + +typedef enum{ + ENET_PTP_SYSTIME_INIT = ENET_PTP_TSCTL_TMSSTI, /*!< timestamp initialize */ + ENET_PTP_SYSTIME_UPDATE = ENET_PTP_TSCTL_TMSSTU, /*!< timestamp update */ + ENET_PTP_ADDEND_UPDATE = ENET_PTP_TSCTL_TMSARU, /*!< addend register update */ + ENET_PTP_FINEMODE = (int32_t)(ENET_PTP_TSCTL_TMSFCU| BIT(31)), /*!< the system timestamp uses the fine method for updating */ + ENET_PTP_COARSEMODE = ENET_PTP_TSCTL_TMSFCU, /*!< the system timestamp uses the coarse method for updating */ +}enet_ptp_function_enum; + + +/* ENET remote wake-up frame register length */ +#define ETH_WAKEUP_REGISTER_LENGTH 8U /*!< remote wake-up frame register length */ + +/* ENET frame size */ +#define ENET_MAX_FRAME_SIZE 1524U /*!< header + frame_extra + payload + CRC */ + +/* ENET delay timeout */ +#define ENET_DELAY_TO ((uint32_t)0x0004FFFFU) /*!< ENET delay timeout */ +#define ENET_RESET_TO ((uint32_t)0x000004FFU) /*!< ENET reset timeout */ + +/* function declarations */ +/* main function */ +/* deinitialize the ENET, and reset structure parameters for ENET initialization */ +void enet_deinit(void); +/* configure the parameters which are usually less cared for initialization */ +void enet_initpara_config(enet_option_enum option, uint32_t para); +/* initialize ENET peripheral with generally concerned parameters and the less cared parameters */ +ErrStatus enet_init(enet_mediamode_enum mediamode, enet_chksumconf_enum checksum, enet_frmrecept_enum recept); +/* reset all core internal registers located in CLK_TX and CLK_RX */ +ErrStatus enet_software_reset(void); +/* check receive frame valid and return frame size */ +uint32_t enet_rxframe_size_get(void); +/* initialize the dma tx/rx descriptors's parameters in chain mode */ +void enet_descriptors_chain_init(enet_dmadirection_enum direction); +/* initialize the dma tx/rx descriptors's parameters in ring mode */ +void enet_descriptors_ring_init(enet_dmadirection_enum direction); +/* handle current received frame data to application buffer */ +ErrStatus enet_frame_receive(uint8_t *buffer, uint32_t bufsize); +/* handle current received frame but without data copy to application buffer */ +#define ENET_NOCOPY_FRAME_RECEIVE() enet_frame_receive(NULL, 0U) +/* handle application buffer data to transmit it */ +ErrStatus enet_frame_transmit(uint8_t *buffer, uint32_t length); +/* handle current transmit frame but without data copy from application buffer */ +#define ENET_NOCOPY_FRAME_TRANSMIT(len) enet_frame_transmit(NULL, (len)) +/* configure the transmit IP frame checksum offload calculation and insertion */ +void enet_transmit_checksum_config(enet_descriptors_struct *desc, uint32_t checksum); +/* ENET Tx and Rx function enable (include MAC and DMA module) */ +void enet_enable(void); +/* ENET Tx and Rx function disable (include MAC and DMA module) */ +void enet_disable(void); +/* configure MAC address */ +void enet_mac_address_set(enet_macaddress_enum mac_addr, uint8_t paddr[]); +/* get MAC address */ +void enet_mac_address_get(enet_macaddress_enum mac_addr, uint8_t paddr[]); + +/* get the ENET MAC/MSC/PTP/DMA status flag */ +FlagStatus enet_flag_get(enet_flag_enum enet_flag); +/* clear the ENET DMA status flag */ +void enet_flag_clear(enet_flag_clear_enum enet_flag); +/* enable ENET MAC/MSC/DMA interrupt */ +void enet_interrupt_enable(enet_int_enum enet_int); +/* disable ENET MAC/MSC/DMA interrupt */ +void enet_interrupt_disable(enet_int_enum enet_int); +/* get ENET MAC/MSC/DMA interrupt flag */ +FlagStatus enet_interrupt_flag_get(enet_int_flag_enum int_flag); +/* clear ENET DMA interrupt flag */ +void enet_interrupt_flag_clear(enet_int_flag_clear_enum int_flag_clear); + +/* MAC function */ +/* ENET Tx function enable (include MAC and DMA module) */ +void enet_tx_enable(void); +/* ENET Tx function disable (include MAC and DMA module) */ +void enet_tx_disable(void); +/* ENET Rx function enable (include MAC and DMA module) */ +void enet_rx_enable(void); +/* ENET Rx function disable (include MAC and DMA module) */ +void enet_rx_disable(void); +/* put registers value into the application buffer */ +void enet_registers_get(enet_registers_type_enum type, uint32_t *preg, uint32_t num); +/* enable the MAC address filter */ +void enet_address_filter_enable(enet_macaddress_enum mac_addr); +/* disable the MAC address filter */ +void enet_address_filter_disable(enet_macaddress_enum mac_addr); +/* configure the MAC address filter */ +void enet_address_filter_config(enet_macaddress_enum mac_addr, uint32_t addr_mask, uint32_t filter_type); +/* PHY interface configuration (configure SMI clock and reset PHY chip) */ +ErrStatus enet_phy_config(void); +/* write to/read from a PHY register */ +ErrStatus enet_phy_write_read(enet_phydirection_enum direction, uint16_t phy_address, uint16_t phy_reg, uint16_t *pvalue); +/* enable the loopback function of phy chip */ +ErrStatus enet_phyloopback_enable(void); +/* disable the loopback function of phy chip */ +ErrStatus enet_phyloopback_disable(void); +/* enable ENET forward feature */ +void enet_forward_feature_enable(uint32_t feature); +/* disable ENET forward feature */ +void enet_forward_feature_disable(uint32_t feature); +/* enable ENET fliter feature */ +void enet_fliter_feature_enable(uint32_t feature); +/* disable ENET fliter feature */ +void enet_fliter_feature_disable(uint32_t feature); + +/* flow control function */ +/* generate the pause frame, ENET will send pause frame after enable transmit flow control */ +ErrStatus enet_pauseframe_generate(void); +/* configure the pause frame detect type */ +void enet_pauseframe_detect_config(uint32_t detect); +/* configure the pause frame parameters */ +void enet_pauseframe_config(uint32_t pausetime, uint32_t pause_threshold); +/* configure the threshold of the flow control(deactive and active threshold) */ +void enet_flowcontrol_threshold_config(uint32_t deactive, uint32_t active); +/* enable ENET flow control feature */ +void enet_flowcontrol_feature_enable(uint32_t feature); +/* disable ENET flow control feature */ +void enet_flowcontrol_feature_disable(uint32_t feature); + +/* DMA function */ +/* get the dma transmit/receive process state */ +uint32_t enet_dmaprocess_state_get(enet_dmadirection_enum direction); +/* poll the dma transmission/reception enable */ +void enet_dmaprocess_resume(enet_dmadirection_enum direction); +/* check and recover the Rx process */ +void enet_rxprocess_check_recovery(void); +/* flush the ENET transmit fifo, and wait until the flush operation completes */ +ErrStatus enet_txfifo_flush(void); +/* get the transmit/receive address of current descriptor, or current buffer, or descriptor table */ +uint32_t enet_current_desc_address_get(enet_desc_reg_enum addr_get); +/* get the Tx or Rx descriptor information */ +uint32_t enet_desc_information_get(enet_descriptors_struct *desc, enet_descstate_enum info_get); +/* get the number of missed frames during receiving */ +void enet_missed_frame_counter_get(uint32_t *rxfifo_drop, uint32_t *rxdma_drop); + +/* descriptor function */ +/* get the bit flag of ENET dma descriptor */ +FlagStatus enet_desc_flag_get(enet_descriptors_struct *desc, uint32_t desc_flag); +/* set the bit flag of ENET dma tx descriptor */ +void enet_desc_flag_set(enet_descriptors_struct *desc, uint32_t desc_flag); +/* clear the bit flag of ENET dma tx descriptor */ +void enet_desc_flag_clear(enet_descriptors_struct *desc, uint32_t desc_flag); +/* when receiving the completed, set RS bit in ENET_DMA_STAT register will set */ +void enet_desc_receive_complete_bit_enable(enet_descriptors_struct *desc); +/* when receiving the completed, set RS bit in ENET_DMA_STAT register will not set */ +void enet_desc_receive_complete_bit_disable(enet_descriptors_struct *desc); +/* drop current receive frame */ +void enet_rxframe_drop(void); +/* enable DMA feature */ +void enet_dma_feature_enable(uint32_t feature); +/* disable DMA feature */ +void enet_dma_feature_disable(uint32_t feature); + +/* initialize the dma Tx/Rx descriptors's parameters in normal chain mode with ptp function */ +void enet_ptp_normal_descriptors_chain_init(enet_dmadirection_enum direction, enet_descriptors_struct *desc_ptptab); +/* initialize the dma Tx/Rx descriptors's parameters in normal ring mode with ptp function */ +void enet_ptp_normal_descriptors_ring_init(enet_dmadirection_enum direction, enet_descriptors_struct *desc_ptptab); +/* receive a packet data with timestamp values to application buffer, when the DMA is in normal mode */ +ErrStatus enet_ptpframe_receive_normal_mode(uint8_t *buffer, uint32_t bufsize, uint32_t timestamp[]); +/* handle current received frame but without data copy to application buffer in PTP normal mode */ +#define ENET_NOCOPY_PTPFRAME_RECEIVE_NORMAL_MODE(ptr) enet_ptpframe_receive_normal_mode(NULL, 0U, (ptr)) +/* send data with timestamp values in application buffer as a transmit packet, when the DMA is in normal mode */ +ErrStatus enet_ptpframe_transmit_normal_mode(uint8_t *buffer, uint32_t length, uint32_t timestamp[]); +/* handle current transmit frame but without data copy from application buffer in PTP normal mode */ +#define ENET_NOCOPY_PTPFRAME_TRANSMIT_NORMAL_MODE(len, ptr) enet_ptpframe_transmit_normal_mode(NULL, (len), (ptr)) + +/* WUM function */ +/* wakeup frame filter register pointer reset */ +void enet_wum_filter_register_pointer_reset(void); +/* set the remote wakeup frame registers */ +void enet_wum_filter_config(uint32_t pdata[]); +/* enable wakeup management features */ +void enet_wum_feature_enable(uint32_t feature); +/* disable wakeup management features */ +void enet_wum_feature_disable(uint32_t feature); + +/* MSC function */ +/* reset the MAC statistics counters */ +void enet_msc_counters_reset(void); +/* enable the MAC statistics counter features */ +void enet_msc_feature_enable(uint32_t feature); +/* disable the MAC statistics counter features */ +void enet_msc_feature_disable(uint32_t feature); +/* get MAC statistics counter */ +uint32_t enet_msc_counters_get(enet_msc_counter_enum counter); + +/* PTP function */ +/* change subsecond to nanosecond */ +uint32_t enet_ptp_subsecond_2_nanosecond(uint32_t subsecond); +/* change nanosecond to subsecond */ +uint32_t enet_ptp_nanosecond_2_subsecond(uint32_t nanosecond); +/* enable the PTP features */ +void enet_ptp_feature_enable(uint32_t feature); +/* disable the PTP features */ +void enet_ptp_feature_disable(uint32_t feature); +/* configure the PTP timestamp function */ +ErrStatus enet_ptp_timestamp_function_config(enet_ptp_function_enum func); +/* configure the PTP system time subsecond increment value */ +void enet_ptp_subsecond_increment_config(uint32_t subsecond); +/* adjusting the PTP clock frequency only in fine update mode */ +void enet_ptp_timestamp_addend_config(uint32_t add); +/* initializing or adding/subtracting to second of the PTP system time */ +void enet_ptp_timestamp_update_config(uint32_t sign, uint32_t second, uint32_t subsecond); +/* configure the PTP expected target time */ +void enet_ptp_expected_time_config(uint32_t second, uint32_t nanosecond); +/* get the PTP current system time */ +void enet_ptp_system_time_get(enet_ptp_systime_struct *systime_struct); +/* configure and start PTP timestamp counter */ +void enet_ptp_start(int32_t updatemethod, uint32_t init_sec, uint32_t init_subsec, uint32_t carry_cfg, uint32_t accuracy_cfg); +/* adjust frequency in fine method by configure addend register */ +void enet_ptp_finecorrection_adjfreq(int32_t carry_cfg); +/* update system time in coarse method */ +void enet_ptp_coarsecorrection_systime_update(enet_ptp_systime_struct *systime_struct); +/* set system time in fine method */ +void enet_ptp_finecorrection_settime(enet_ptp_systime_struct * systime_struct); +/* get the ptp flag status */ +FlagStatus enet_ptp_flag_get(uint32_t flag); + +/* internal function */ +/* reset the ENET initpara struct, call it before using enet_initpara_config() */ +void enet_initpara_reset(void); +/* initialize ENET peripheral with generally concerned parameters, call it by enet_init() */ +static void enet_default_init(void); +#ifdef USE_DELAY +/* user can provide more timing precise _ENET_DELAY_ function */ +#define _ENET_DELAY_ delay_ms +#else +/* insert a delay time */ +static void enet_delay(uint32_t ncount); +/* default _ENET_DELAY_ function with less precise timing */ +#define _ENET_DELAY_ enet_delay +#endif + +#endif /* GD32F10X_ENET_H */ diff --git a/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_standard_peripheral/Include/gd32f10x_exmc.h b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_standard_peripheral/Include/gd32f10x_exmc.h new file mode 100644 index 0000000000..eb0a1e5687 --- /dev/null +++ b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_standard_peripheral/Include/gd32f10x_exmc.h @@ -0,0 +1,431 @@ +/*! + \file gd32f10x_exmc.h + \brief definitions for the EXMC + + \version 2014-12-26, V1.0.0, firmware for GD32F10x + \version 2017-06-20, V2.0.0, firmware for GD32F10x + \version 2018-07-31, V2.1.0, firmware for GD32F10x + \version 2020-09-30, V2.2.0, firmware for GD32F10x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef GD32F10X_EXMC_H +#define GD32F10X_EXMC_H + +#include "gd32f10x.h" + +/* EXMC definitions */ +#define EXMC (EXMC_BASE) /*!< EXMC register base address */ + +/* registers definitions */ +/* NOR/PSRAM */ +#define EXMC_SNCTL0 REG32(EXMC + 0x00U) /*!< EXMC SRAM/NOR flash control register 0 */ +#define EXMC_SNTCFG0 REG32(EXMC + 0x04U) /*!< EXMC SRAM/NOR flash timing configuration register 0 */ +#define EXMC_SNWTCFG0 REG32(EXMC + 0x104U) /*!< EXMC SRAM/NOR flash write timing configuration register 0 */ + +#define EXMC_SNCTL1 REG32(EXMC + 0x08U) /*!< EXMC SRAM/NOR flash control register 1 */ +#define EXMC_SNTCFG1 REG32(EXMC + 0x0CU) /*!< EXMC SRAM/NOR flash timing configuration register 1 */ +#define EXMC_SNWTCFG1 REG32(EXMC + 0x10CU) /*!< EXMC SRAM/NOR flash write timing configuration register 1 */ + +#define EXMC_SNCTL2 REG32(EXMC + 0x10U) /*!< EXMC SRAM/NOR flash control register 2 */ +#define EXMC_SNTCFG2 REG32(EXMC + 0x14U) /*!< EXMC SRAM/NOR flash timing configuration register 2 */ +#define EXMC_SNWTCFG2 REG32(EXMC + 0x114U) /*!< EXMC SRAM/NOR flash write timing configuration register 2 */ + +#define EXMC_SNCTL3 REG32(EXMC + 0x18U) /*!< EXMC SRAM/NOR flash control register 3 */ +#define EXMC_SNTCFG3 REG32(EXMC + 0x1CU) /*!< EXMC SRAM/NOR flash timing configuration register 3 */ +#define EXMC_SNWTCFG3 REG32(EXMC + 0x11CU) /*!< EXMC SRAM/NOR flash write timing configuration register 3 */ + +/* NAND/PC card */ +#define EXMC_NPCTL1 REG32(EXMC + 0x60U) /*!< EXMC NAND/PC card control register 1 */ +#define EXMC_NPINTEN1 REG32(EXMC + 0x64U) /*!< EXMC NAND/PC card interrupt enable register 1 */ +#define EXMC_NPCTCFG1 REG32(EXMC + 0x68U) /*!< EXMC NAND/PC card common space timing configuration register 1 */ +#define EXMC_NPATCFG1 REG32(EXMC + 0x6CU) /*!< EXMC NAND/PC card attribute space timing configuration register 1 */ +#define EXMC_NECC1 REG32(EXMC + 0x74U) /*!< EXMC NAND ECC register 1 */ + +#define EXMC_NPCTL2 REG32(EXMC + 0x80U) /*!< EXMC NAND/PC card control register 2 */ +#define EXMC_NPINTEN2 REG32(EXMC + 0x84U) /*!< EXMC NAND/PC card interrupt enable register 2 */ +#define EXMC_NPCTCFG2 REG32(EXMC + 0x88U) /*!< EXMC NAND/PC card common space timing configuration register 2 */ +#define EXMC_NPATCFG2 REG32(EXMC + 0x8CU) /*!< EXMC NAND/PC card attribute space timing configuration register 2 */ +#define EXMC_NECC2 REG32(EXMC + 0x94U) /*!< EXMC NAND ECC register 2 */ + +#define EXMC_NPCTL3 REG32(EXMC + 0xA0U) /*!< EXMC NAND/PC card control register 3 */ +#define EXMC_NPINTEN3 REG32(EXMC + 0xA4U) /*!< EXMC NAND/PC card interrupt enable register 3 */ +#define EXMC_NPCTCFG3 REG32(EXMC + 0xA8U) /*!< EXMC NAND/PC card common space timing configuration register 3 */ +#define EXMC_NPATCFG3 REG32(EXMC + 0xACU) /*!< EXMC NAND/PC card attribute space timing configuration register 3 */ +#define EXMC_PIOTCFG3 REG32(EXMC + 0xB0U) /*!< EXMC PC card I/O space timing configuration register */ + +/* bits definitions */ +/* NOR/PSRAM */ +/* EXMC_SNCTLx,x=0..3 */ +#define EXMC_SNCTL_NRBKEN BIT(0) /*!< NOR bank enable */ +#define EXMC_SNCTL_NRMUX BIT(1) /*!< NOR bank memory address/data multiplexing */ +#define EXMC_SNCTL_NRTP BITS(2,3) /*!< NOR bank memory type */ +#define EXMC_SNCTL_NRW BITS(4,5) /*!< NOR bank memory data bus width */ +#define EXMC_SNCTL_NREN BIT(6) /*!< NOR flash access enable */ +#define EXMC_SNCTL_SBRSTEN BIT(8) /*!< synchronous burst enable */ +#define EXMC_SNCTL_NRWTPOL BIT(9) /*!< NWAIT signal polarity */ +#define EXMC_SNCTL_WRAPEN BIT(10) /*!< wrapped burst mode enable */ +#define EXMC_SNCTL_NRWTCFG BIT(11) /*!< NWAIT signal configuration, only work in synchronous mode */ +#define EXMC_SNCTL_WREN BIT(12) /*!< write enable */ +#define EXMC_SNCTL_NRWTEN BIT(13) /*!< NWAIT signal enable */ +#define EXMC_SNCTL_EXMODEN BIT(14) /*!< extended mode enable */ +#define EXMC_SNCTL_ASYNCWAIT BIT(15) /*!< asynchronous wait */ +#define EXMC_SNCTL_SYNCWR BIT(19) /*!< synchronous write */ + +/* EXMC_SNTCFGx,x=0..3 */ +#define EXMC_SNTCFG_ASET BITS(0,3) /*!< address setup time */ +#define EXMC_SNTCFG_AHLD BITS(4,7) /*!< address hold time */ +#define EXMC_SNTCFG_DSET BITS(8,15) /*!< data setup time */ +#define EXMC_SNTCFG_BUSLAT BITS(16,19) /*!< bus latency */ +#define EXMC_SNTCFG_CKDIV BITS(20,23) /*!< synchronous clock divide ratio */ +#define EXMC_SNTCFG_DLAT BITS(24,27) /*!< data latency for NOR flash */ +#define EXMC_SNTCFG_ASYNCMOD BITS(28,29) /*!< asynchronous access mode */ + +/* EXMC_SNWTCFGx,x=0..3 */ +#define EXMC_SNWTCFG_WASET BITS(0,3) /*!< address setup time */ +#define EXMC_SNWTCFG_WAHLD BITS(4,7) /*!< address hold time */ +#define EXMC_SNWTCFG_WDSET BITS(8,15) /*!< data setup time */ +#define EXMC_SNWTCFG_CKDIV BITS(20,23) /*!< synchronous clock divide ratio */ +#define EXMC_SNWTCFG_DLAT BITS(24,27) /*!< data latency for NOR flash */ +#define EXMC_SNWTCFG_WASYNCMOD BITS(28,29) /*!< asynchronous access mode */ + +/* NAND/PC card */ +/* EXMC_NPCTLx,x=1..3 */ +#define EXMC_NPCTL_NDWTEN BIT(1) /*!< wait feature enable */ +#define EXMC_NPCTL_NDBKEN BIT(2) /*!< NAND bank enable */ +#define EXMC_NPCTL_NDTP BIT(3) /*!< NAND bank memory type */ +#define EXMC_NPCTL_NDW BITS(4,5) /*!< NAND bank memory data bus width */ +#define EXMC_NPCTL_ECCEN BIT(6) /*!< ECC enable */ +#define EXMC_NPCTL_CTR BITS(9,12) /*!< CLE to RE delay */ +#define EXMC_NPCTL_ATR BITS(13,16) /*!< ALE to RE delay */ +#define EXMC_NPCTL_ECCSZ BITS(17,19) /*!< ECC size */ + +/* EXMC_NPINTENx,x=1..3 */ +#define EXMC_NPINTEN_INTRS BIT(0) /*!< interrupt rising edge status */ +#define EXMC_NPINTEN_INTHS BIT(1) /*!< interrupt high-level status */ +#define EXMC_NPINTEN_INTFS BIT(2) /*!< interrupt falling edge status */ +#define EXMC_NPINTEN_INTREN BIT(3) /*!< interrupt rising edge detection enable */ +#define EXMC_NPINTEN_INTHEN BIT(4) /*!< interrupt high-level detection enable */ +#define EXMC_NPINTEN_INTFEN BIT(5) /*!< interrupt falling edge detection enable */ +#define EXMC_NPINTEN_FFEPT BIT(6) /*!< FIFO empty flag */ + +/* EXMC_NPCTCFGx,x=1..3 */ +#define EXMC_NPCTCFG_COMSET BITS(0,7) /*!< common memory setup time */ +#define EXMC_NPCTCFG_COMWAIT BITS(8,15) /*!< common memory wait time */ +#define EXMC_NPCTCFG_COMHLD BITS(16,23) /*!< common memory hold time */ +#define EXMC_NPCTCFG_COMHIZ BITS(24,31) /*!< common memory data bus HiZ time */ + +/* EXMC_NPATCFGx,x=1..3 */ +#define EXMC_NPATCFG_ATTSET BITS(0,7) /*!< attribute memory setup time */ +#define EXMC_NPATCFG_ATTWAIT BITS(8,15) /*!< attribute memory wait time */ +#define EXMC_NPATCFG_ATTHLD BITS(16,23) /*!< attribute memory hold time */ +#define EXMC_NPATCFG_ATTHIZ BITS(24,31) /*!< attribute memory data bus HiZ time */ + +/* EXMC_PIOTCFG3 */ +#define EXMC_PIOTCFG3_IOSET BITS(0,7) /*!< IO space setup time */ +#define EXMC_PIOTCFG3_IOWAIT BITS(8,15) /*!< IO space wait time */ +#define EXMC_PIOTCFG3_IOHLD BITS(16,23) /*!< IO space hold time */ +#define EXMC_PIOTCFG3_IOHIZ BITS(24,31) /*!< IO space data bus HiZ time */ + +/* EXMC_NECCx,x=1,2 */ +#define EXMC_NECC_ECC BITS(0,31) /*!< ECC result */ + +/* constants definitions */ +/* EXMC NOR/SRAM timing initialize struct */ +typedef struct +{ + uint32_t asyn_access_mode; /*!< asynchronous access mode */ + uint32_t syn_data_latency; /*!< configure the data latency */ + uint32_t syn_clk_division; /*!< configure the clock divide ratio */ + uint32_t bus_latency; /*!< configure the bus latency */ + uint32_t asyn_data_setuptime; /*!< configure the data setup time,asynchronous access mode valid */ + uint32_t asyn_address_holdtime; /*!< configure the address hold time,asynchronous access mode valid */ + uint32_t asyn_address_setuptime; /*!< configure the data setup time,asynchronous access mode valid */ +}exmc_norsram_timing_parameter_struct; + +/* EXMC NOR/SRAM initialize struct */ +typedef struct +{ + uint32_t norsram_region; /*!< select the region of EXMC NOR/SRAM bank */ + uint32_t write_mode; /*!< the write mode, synchronous mode or asynchronous mode */ + uint32_t extended_mode; /*!< enable or disable the extended mode */ + uint32_t asyn_wait; /*!< enable or disable the asynchronous wait function */ + uint32_t nwait_signal; /*!< enable or disable the NWAIT signal while in synchronous bust mode */ + uint32_t memory_write; /*!< enable or disable the write operation */ + uint32_t nwait_config; /*!< NWAIT signal configuration */ + uint32_t wrap_burst_mode; /*!< enable or disable the wrap burst mode */ + uint32_t nwait_polarity; /*!< specifies the polarity of NWAIT signal from memory */ + uint32_t burst_mode; /*!< enable or disable the burst mode */ + uint32_t databus_width; /*!< specifies the databus width of external memory */ + uint32_t memory_type; /*!< specifies the type of external memory */ + uint32_t address_data_mux; /*!< specifies whether the data bus and address bus are multiplexed */ + exmc_norsram_timing_parameter_struct* read_write_timing; /*!< timing parameters for read and write if the extended mode is not used or the timing + parameters for read if the extended mode is used */ + exmc_norsram_timing_parameter_struct* write_timing; /*!< timing parameters for write when the extended mode is used */ +}exmc_norsram_parameter_struct; + +/* EXMC NAND/PC card timing initialize struct */ +typedef struct +{ + uint32_t databus_hiztime; /*!< configure the dadtabus HiZ time for write operation */ + uint32_t holdtime; /*!< configure the address hold time(or the data hold time for write operation) */ + uint32_t waittime; /*!< configure the minimum wait time */ + uint32_t setuptime; /*!< configure the address setup time */ +}exmc_nand_pccard_timing_parameter_struct; + +/* EXMC NAND initialize struct */ +typedef struct +{ + uint32_t nand_bank; /*!< select the bank of NAND */ + uint32_t ecc_size; /*!< the page size for the ECC calculation */ + uint32_t atr_latency; /*!< configure the latency of ALE low to RB low */ + uint32_t ctr_latency; /*!< configure the latency of CLE low to RB low */ + uint32_t ecc_logic; /*!< enable or disable the ECC calculation logic */ + uint32_t databus_width; /*!< the NAND flash databus width */ + uint32_t wait_feature; /*!< enables or disables the wait feature */ + exmc_nand_pccard_timing_parameter_struct* common_space_timing; /*!< the timing parameters for NAND flash common space */ + exmc_nand_pccard_timing_parameter_struct* attribute_space_timing; /*!< the timing parameters for NAND flash attribute space */ +}exmc_nand_parameter_struct; + +/* EXMC PC card initialize struct */ +typedef struct +{ + uint32_t atr_latency; /*!< configure the latency of ALE low to RB low */ + uint32_t ctr_latency; /*!< configure the latency of CLE low to RB low */ + uint32_t wait_feature; /*!< enables or disables the Wait feature */ + exmc_nand_pccard_timing_parameter_struct* common_space_timing; /*!< the timing parameters for NAND flash common space */ + exmc_nand_pccard_timing_parameter_struct* attribute_space_timing; /*!< the timing parameters for NAND flash attribute space */ + exmc_nand_pccard_timing_parameter_struct* io_space_timing; /*!< the timing parameters for NAND flash IO space */ +}exmc_pccard_parameter_struct;; + +/* EXMC register address */ +#define EXMC_SNCTL(region) REG32(EXMC + 0x08U * (region)) /*!< EXMC SRAM/NOR flash control register */ +#define EXMC_SNTCFG(region) REG32(EXMC + 0x04U + 0x08U * (region)) /*!< EXMC SRAM/NOR flash timing configuration register */ +#define EXMC_SNWTCFG(region) REG32(EXMC + 0x104U + 0x08U * (region)) /*!< EXMC SRAM/NOR flash write timing configuration register */ + +#define EXMC_NPCTL(bank) REG32(EXMC + 0x40U + 0x20U * (bank)) /*!< EXMC NAND/PC card control register */ +#define EXMC_NPINTEN(bank) REG32(EXMC + 0x44U + 0x20U * (bank)) /*!< EXMC NAND/PC card interrupt enable register */ +#define EXMC_NPCTCFG(bank) REG32(EXMC + 0x48U + 0x20U * (bank)) /*!< EXMC NAND/PC card common space timing configuration register */ +#define EXMC_NPATCFG(bank) REG32(EXMC + 0x4CU + 0x20U * (bank)) /*!< EXMC NAND/PC card attribute space timing configuration register */ +#define EXMC_NECC(bank) REG32(EXMC + 0x54U + 0x20U * (bank)) /*!< EXMC NAND ECC register */ + +/* NOR bank memory data bus width */ +#define SNCTL_NRW(regval) (BITS(4,5) & ((uint32_t)(regval) << 4)) +#define EXMC_NOR_DATABUS_WIDTH_8B SNCTL_NRW(0) /*!< NOR data width 8 bits */ +#define EXMC_NOR_DATABUS_WIDTH_16B SNCTL_NRW(1) /*!< NOR data width 16 bits */ + +/* NOR bank memory type */ +#define SNCTL_NRTP(regval) (BITS(2,3) & ((uint32_t)(regval) << 2)) +#define EXMC_MEMORY_TYPE_SRAM SNCTL_NRTP(0) /*!< SRAM,ROM */ +#define EXMC_MEMORY_TYPE_PSRAM SNCTL_NRTP(1) /*!< PSRAM,CRAM */ +#define EXMC_MEMORY_TYPE_NOR SNCTL_NRTP(2) /*!< NOR flash */ + +/* asynchronous access mode */ +#define SNTCFG_ASYNCMOD(regval) (BITS(28,29) & ((uint32_t)(regval) << 28)) +#define EXMC_ACCESS_MODE_A SNTCFG_ASYNCMOD(0) /*!< mode A access */ +#define EXMC_ACCESS_MODE_B SNTCFG_ASYNCMOD(1) /*!< mode B access */ +#define EXMC_ACCESS_MODE_C SNTCFG_ASYNCMOD(2) /*!< mode C access */ +#define EXMC_ACCESS_MODE_D SNTCFG_ASYNCMOD(3) /*!< mode D access */ + +/* data latency for NOR flash */ +#define SNTCFG_DLAT(regval) (BITS(24,27) & ((uint32_t)(regval) << 24)) +#define EXMC_DATALAT_2_CLK SNTCFG_DLAT(0) /*!< data latency 2 EXMC_CLK */ +#define EXMC_DATALAT_3_CLK SNTCFG_DLAT(1) /*!< data latency 3 EXMC_CLK */ +#define EXMC_DATALAT_4_CLK SNTCFG_DLAT(2) /*!< data latency 4 EXMC_CLK */ +#define EXMC_DATALAT_5_CLK SNTCFG_DLAT(3) /*!< data latency 5 EXMC_CLK */ +#define EXMC_DATALAT_6_CLK SNTCFG_DLAT(4) /*!< data latency 6 EXMC_CLK */ +#define EXMC_DATALAT_7_CLK SNTCFG_DLAT(5) /*!< data latency 7 EXMC_CLK */ +#define EXMC_DATALAT_8_CLK SNTCFG_DLAT(6) /*!< data latency 8 EXMC_CLK */ +#define EXMC_DATALAT_9_CLK SNTCFG_DLAT(7) /*!< data latency 9 EXMC_CLK */ +#define EXMC_DATALAT_10_CLK SNTCFG_DLAT(8) /*!< data latency 10 EXMC_CLK */ +#define EXMC_DATALAT_11_CLK SNTCFG_DLAT(9) /*!< data latency 11 EXMC_CLK */ +#define EXMC_DATALAT_12_CLK SNTCFG_DLAT(10) /*!< data latency 12 EXMC_CLK */ +#define EXMC_DATALAT_13_CLK SNTCFG_DLAT(11) /*!< data latency 13 EXMC_CLK */ +#define EXMC_DATALAT_14_CLK SNTCFG_DLAT(12) /*!< data latency 14 EXMC_CLK */ +#define EXMC_DATALAT_15_CLK SNTCFG_DLAT(13) /*!< data latency 15 EXMC_CLK */ +#define EXMC_DATALAT_16_CLK SNTCFG_DLAT(14) /*!< data latency 16 EXMC_CLK */ +#define EXMC_DATALAT_17_CLK SNTCFG_DLAT(15) /*!< data latency 17 EXMC_CLK */ + +/* synchronous clock divide ratio */ +#define SNTCFG_CKDIV(regval) (BITS(20,23) & ((uint32_t)(regval) << 20)) +#define EXMC_SYN_CLOCK_RATIO_DISABLE SNTCFG_CKDIV(0) /*!< EXMC_CLK disable */ +#define EXMC_SYN_CLOCK_RATIO_2_CLK SNTCFG_CKDIV(1) /*!< EXMC_CLK = 2*HCLK */ +#define EXMC_SYN_CLOCK_RATIO_3_CLK SNTCFG_CKDIV(2) /*!< EXMC_CLK = 3*HCLK */ +#define EXMC_SYN_CLOCK_RATIO_4_CLK SNTCFG_CKDIV(3) /*!< EXMC_CLK = 4*HCLK */ +#define EXMC_SYN_CLOCK_RATIO_5_CLK SNTCFG_CKDIV(4) /*!< EXMC_CLK = 5*HCLK */ +#define EXMC_SYN_CLOCK_RATIO_6_CLK SNTCFG_CKDIV(5) /*!< EXMC_CLK = 6*HCLK */ +#define EXMC_SYN_CLOCK_RATIO_7_CLK SNTCFG_CKDIV(6) /*!< EXMC_CLK = 7*HCLK */ +#define EXMC_SYN_CLOCK_RATIO_8_CLK SNTCFG_CKDIV(7) /*!< EXMC_CLK = 8*HCLK */ +#define EXMC_SYN_CLOCK_RATIO_9_CLK SNTCFG_CKDIV(8) /*!< EXMC_CLK = 9*HCLK */ +#define EXMC_SYN_CLOCK_RATIO_10_CLK SNTCFG_CKDIV(9) /*!< EXMC_CLK = 10*HCLK */ +#define EXMC_SYN_CLOCK_RATIO_11_CLK SNTCFG_CKDIV(10) /*!< EXMC_CLK = 11*HCLK */ +#define EXMC_SYN_CLOCK_RATIO_12_CLK SNTCFG_CKDIV(11) /*!< EXMC_CLK = 12*HCLK */ +#define EXMC_SYN_CLOCK_RATIO_13_CLK SNTCFG_CKDIV(12) /*!< EXMC_CLK = 13*HCLK */ +#define EXMC_SYN_CLOCK_RATIO_14_CLK SNTCFG_CKDIV(13) /*!< EXMC_CLK = 14*HCLK */ +#define EXMC_SYN_CLOCK_RATIO_15_CLK SNTCFG_CKDIV(14) /*!< EXMC_CLK = 15*HCLK */ +#define EXMC_SYN_CLOCK_RATIO_16_CLK SNTCFG_CKDIV(15) /*!< EXMC_CLK = 16*HCLK */ + +/* ECC size */ +#define NPCTL_ECCSZ(regval) (BITS(17,19) & ((uint32_t)(regval) << 17)) +#define EXMC_ECC_SIZE_256BYTES NPCTL_ECCSZ(0) /* 256 bytes */ +#define EXMC_ECC_SIZE_512BYTES NPCTL_ECCSZ(1) /* 512 bytes */ +#define EXMC_ECC_SIZE_1024BYTES NPCTL_ECCSZ(2) /* 1024 bytes */ +#define EXMC_ECC_SIZE_2048BYTES NPCTL_ECCSZ(3) /* 2048 bytes */ +#define EXMC_ECC_SIZE_4096BYTES NPCTL_ECCSZ(4) /* 4096 bytes */ +#define EXMC_ECC_SIZE_8192BYTES NPCTL_ECCSZ(5) /* 8192 bytes */ + +/* ALE to RE delay */ +#define NPCTL_ATR(regval) (BITS(13,16) & ((uint32_t)(regval) << 13)) +#define EXMC_ALE_RE_DELAY_1_HCLK NPCTL_ATR(0) /* ALE to RE delay = 1*HCLK */ +#define EXMC_ALE_RE_DELAY_2_HCLK NPCTL_ATR(1) /* ALE to RE delay = 2*HCLK */ +#define EXMC_ALE_RE_DELAY_3_HCLK NPCTL_ATR(2) /* ALE to RE delay = 3*HCLK */ +#define EXMC_ALE_RE_DELAY_4_HCLK NPCTL_ATR(3) /* ALE to RE delay = 4*HCLK */ +#define EXMC_ALE_RE_DELAY_5_HCLK NPCTL_ATR(4) /* ALE to RE delay = 5*HCLK */ +#define EXMC_ALE_RE_DELAY_6_HCLK NPCTL_ATR(5) /* ALE to RE delay = 6*HCLK */ +#define EXMC_ALE_RE_DELAY_7_HCLK NPCTL_ATR(6) /* ALE to RE delay = 7*HCLK */ +#define EXMC_ALE_RE_DELAY_8_HCLK NPCTL_ATR(7) /* ALE to RE delay = 8*HCLK */ +#define EXMC_ALE_RE_DELAY_9_HCLK NPCTL_ATR(8) /* ALE to RE delay = 9*HCLK */ +#define EXMC_ALE_RE_DELAY_10_HCLK NPCTL_ATR(9) /* ALE to RE delay = 10*HCLK */ +#define EXMC_ALE_RE_DELAY_11_HCLK NPCTL_ATR(10) /* ALE to RE delay = 11*HCLK */ +#define EXMC_ALE_RE_DELAY_12_HCLK NPCTL_ATR(11) /* ALE to RE delay = 12*HCLK */ +#define EXMC_ALE_RE_DELAY_13_HCLK NPCTL_ATR(12) /* ALE to RE delay = 13*HCLK */ +#define EXMC_ALE_RE_DELAY_14_HCLK NPCTL_ATR(13) /* ALE to RE delay = 14*HCLK */ +#define EXMC_ALE_RE_DELAY_15_HCLK NPCTL_ATR(14) /* ALE to RE delay = 15*HCLK */ +#define EXMC_ALE_RE_DELAY_16_HCLK NPCTL_ATR(15) /* ALE to RE delay = 16*HCLK */ + +/* CLE to RE delay */ +#define NPCTL_CTR(regval) (BITS(9,12) & ((uint32_t)(regval) << 9)) +#define EXMC_CLE_RE_DELAY_1_HCLK NPCTL_CTR(0) /* CLE to RE delay = 1*HCLK */ +#define EXMC_CLE_RE_DELAY_2_HCLK NPCTL_CTR(1) /* CLE to RE delay = 2*HCLK */ +#define EXMC_CLE_RE_DELAY_3_HCLK NPCTL_CTR(2) /* CLE to RE delay = 3*HCLK */ +#define EXMC_CLE_RE_DELAY_4_HCLK NPCTL_CTR(3) /* CLE to RE delay = 4*HCLK */ +#define EXMC_CLE_RE_DELAY_5_HCLK NPCTL_CTR(4) /* CLE to RE delay = 5*HCLK */ +#define EXMC_CLE_RE_DELAY_6_HCLK NPCTL_CTR(5) /* CLE to RE delay = 6*HCLK */ +#define EXMC_CLE_RE_DELAY_7_HCLK NPCTL_CTR(6) /* CLE to RE delay = 7*HCLK */ +#define EXMC_CLE_RE_DELAY_8_HCLK NPCTL_CTR(7) /* CLE to RE delay = 8*HCLK */ +#define EXMC_CLE_RE_DELAY_9_HCLK NPCTL_CTR(8) /* CLE to RE delay = 9*HCLK */ +#define EXMC_CLE_RE_DELAY_10_HCLK NPCTL_CTR(9) /* CLE to RE delay = 10*HCLK */ +#define EXMC_CLE_RE_DELAY_11_HCLK NPCTL_CTR(10) /* CLE to RE delay = 11*HCLK */ +#define EXMC_CLE_RE_DELAY_12_HCLK NPCTL_CTR(11) /* CLE to RE delay = 12*HCLK */ +#define EXMC_CLE_RE_DELAY_13_HCLK NPCTL_CTR(12) /* CLE to RE delay = 13*HCLK */ +#define EXMC_CLE_RE_DELAY_14_HCLK NPCTL_CTR(13) /* CLE to RE delay = 14*HCLK */ +#define EXMC_CLE_RE_DELAY_15_HCLK NPCTL_CTR(14) /* CLE to RE delay = 15*HCLK */ +#define EXMC_CLE_RE_DELAY_16_HCLK NPCTL_CTR(15) /* CLE to RE delay = 16*HCLK */ + +/* NAND bank memory data bus width */ +#define NPCTL_NDW(regval) (BITS(4,5) & ((uint32_t)(regval) << 4)) +#define EXMC_NAND_DATABUS_WIDTH_8B NPCTL_NDW(0) /*!< NAND data width 8 bits */ +#define EXMC_NAND_DATABUS_WIDTH_16B NPCTL_NDW(1) /*!< NAND data width 16 bits */ + +/* EXMC NOR/SRAM bank region definition */ +#define EXMC_BANK0_NORSRAM_REGION0 ((uint32_t)0x00000000U) /*!< bank0 NOR/SRAM region0 */ +#define EXMC_BANK0_NORSRAM_REGION1 ((uint32_t)0x00000001U) /*!< bank0 NOR/SRAM region1 */ +#define EXMC_BANK0_NORSRAM_REGION2 ((uint32_t)0x00000002U) /*!< bank0 NOR/SRAM region2 */ +#define EXMC_BANK0_NORSRAM_REGION3 ((uint32_t)0x00000003U) /*!< bank0 NOR/SRAM region3 */ + +/* EXMC NOR/SRAM write mode */ +#define EXMC_ASYN_WRITE ((uint32_t)0x00000000U) /*!< asynchronous write mode */ +#define EXMC_SYN_WRITE ((uint32_t)0x00080000U) /*!< synchronous write mode */ + +/* EXMC NWAIT signal configuration */ +#define EXMC_NWAIT_CONFIG_BEFORE ((uint32_t)0x00000000U) /*!< NWAIT signal is active one data cycle before wait state */ +#define EXMC_NWAIT_CONFIG_DURING ((uint32_t)0x00000800U) /*!< NWAIT signal is active during wait state */ + +/* EXMC NWAIT signal polarity configuration */ +#define EXMC_NWAIT_POLARITY_LOW ((uint32_t)0x00000000U) /*!< low level is active of NWAIT */ +#define EXMC_NWAIT_POLARITY_HIGH ((uint32_t)0x00000200U) /*!< high level is active of NWAIT */ + +/* EXMC NAND/PC card bank definition */ +#define EXMC_BANK1_NAND ((uint32_t)0x00000001U) /*!< bank1 NAND flash */ +#define EXMC_BANK2_NAND ((uint32_t)0x00000002U) /*!< bank2 NAND flash */ +#define EXMC_BANK3_PCCARD ((uint32_t)0x00000003U) /*!< bank3 PC card */ + +/* EXMC flag bits */ +#define EXMC_NAND_PCCARD_FLAG_RISE EXMC_NPINTEN_INTRS /*!< interrupt rising edge status */ +#define EXMC_NAND_PCCARD_FLAG_LEVEL EXMC_NPINTEN_INTHS /*!< interrupt high-level status */ +#define EXMC_NAND_PCCARD_FLAG_FALL EXMC_NPINTEN_INTFS /*!< interrupt falling edge status */ +#define EXMC_NAND_PCCARD_FLAG_FIFOE EXMC_NPINTEN_FFEPT /*!< FIFO empty flag */ + +/* EXMC interrupt flag bits */ +#define EXMC_NAND_PCCARD_INT_RISE EXMC_NPINTEN_INTREN /*!< interrupt rising edge detection enable */ +#define EXMC_NAND_PCCARD_INT_LEVEL EXMC_NPINTEN_INTHEN /*!< interrupt high-level detection enable */ +#define EXMC_NAND_PCCARD_INT_FALL EXMC_NPINTEN_INTFEN /*!< interrupt falling edge detection enable */ + +/* function declarations */ +/* deinitialize EXMC NOR/SRAM region */ +void exmc_norsram_deinit(uint32_t norsram_region); +/* exmc_norsram_parameter_struct parameter initialize */ +void exmc_norsram_struct_para_init(exmc_norsram_parameter_struct* exmc_norsram_init_struct); +/* initialize EXMC NOR/SRAM region */ +void exmc_norsram_init(exmc_norsram_parameter_struct* exmc_norsram_init_struct); +/* EXMC NOR/SRAM bank enable */ +void exmc_norsram_enable(uint32_t norsram_region); +/* EXMC NOR/SRAM bank disable */ +void exmc_norsram_disable(uint32_t norsram_region); + +/* deinitialize EXMC NAND bank */ +void exmc_nand_deinit(uint32_t nand_bank); +/* initialize EXMC NAND bank */ +void exmc_nand_init(exmc_nand_parameter_struct* exmc_nand_init_struct); +/* exmc_nand_init_struct parameter initialize */ +void exmc_nand_struct_para_init(exmc_nand_parameter_struct* exmc_nand_init_struct); +/* EXMC NAND bank enable */ +void exmc_nand_enable(uint32_t nand_bank); +/* EXMC NAND bank disable */ +void exmc_nand_disable(uint32_t nand_bank); +/* enable or disable the EXMC NAND ECC function */ +void exmc_nand_ecc_config(uint32_t nand_bank, ControlStatus newvalue); +/* get the EXMC ECC value */ +uint32_t exmc_ecc_get(uint32_t nand_bank); + +/* deinitialize EXMC PC card bank */ +void exmc_pccard_deinit(void); +/* initialize EXMC PC card bank */ +void exmc_pccard_init(exmc_pccard_parameter_struct* exmc_pccard_init_struct); +/* exmc_pccard_parameter_struct parameter initialize */ +void exmc_pccard_struct_para_init(exmc_pccard_parameter_struct* exmc_pccard_init_struct); +/* EXMC PC card bank enable */ +void exmc_pccard_enable(void); +/* EXMC PC card bank disable */ +void exmc_pccard_disable(void); + +/* enable EXMC interrupt */ +void exmc_interrupt_enable(uint32_t bank, uint32_t interrupt_source); +/* disable EXMC interrupt */ +void exmc_interrupt_disable(uint32_t bank, uint32_t interrupt_source); +/* check EXMC flag is set or not */ +FlagStatus exmc_flag_get(uint32_t bank, uint32_t flag); +/* clear EXMC flag */ +void exmc_flag_clear(uint32_t bank, uint32_t flag); +/* check EXMC flag is set or not */ +FlagStatus exmc_interrupt_flag_get(uint32_t bank, uint32_t interrupt_source); +/* clear EXMC flag */ +void exmc_interrupt_flag_clear(uint32_t bank, uint32_t interrupt_source); + +#endif /* GD32F10X_EXMC_H */ diff --git a/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_standard_peripheral/Include/gd32f10x_exti.h b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_standard_peripheral/Include/gd32f10x_exti.h new file mode 100644 index 0000000000..d73a195a0b --- /dev/null +++ b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_standard_peripheral/Include/gd32f10x_exti.h @@ -0,0 +1,257 @@ +/*! + \file gd32f10x_exti.h + \brief definitions for the EXTI + + \version 2014-12-26, V1.0.0, firmware for GD32F10x + \version 2017-06-20, V2.0.0, firmware for GD32F10x + \version 2018-07-31, V2.1.0, firmware for GD32F10x + \version 2020-09-30, V2.2.0, firmware for GD32F10x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef GD32F10X_EXTI_H +#define GD32F10X_EXTI_H + +#include "gd32f10x.h" + +/* EXTI definitions */ +#define EXTI EXTI_BASE + +/* registers definitions */ +#define EXTI_INTEN REG32(EXTI + 0x00U) /*!< interrupt enable register */ +#define EXTI_EVEN REG32(EXTI + 0x04U) /*!< event enable register */ +#define EXTI_RTEN REG32(EXTI + 0x08U) /*!< rising edge trigger enable register */ +#define EXTI_FTEN REG32(EXTI + 0x0CU) /*!< falling trigger enable register */ +#define EXTI_SWIEV REG32(EXTI + 0x10U) /*!< software interrupt event register */ +#define EXTI_PD REG32(EXTI + 0x14U) /*!< pending register */ + +/* bits definitions */ +/* EXTI_INTEN */ +#define EXTI_INTEN_INTEN0 BIT(0) /*!< interrupt from line 0 */ +#define EXTI_INTEN_INTEN1 BIT(1) /*!< interrupt from line 1 */ +#define EXTI_INTEN_INTEN2 BIT(2) /*!< interrupt from line 2 */ +#define EXTI_INTEN_INTEN3 BIT(3) /*!< interrupt from line 3 */ +#define EXTI_INTEN_INTEN4 BIT(4) /*!< interrupt from line 4 */ +#define EXTI_INTEN_INTEN5 BIT(5) /*!< interrupt from line 5 */ +#define EXTI_INTEN_INTEN6 BIT(6) /*!< interrupt from line 6 */ +#define EXTI_INTEN_INTEN7 BIT(7) /*!< interrupt from line 7 */ +#define EXTI_INTEN_INTEN8 BIT(8) /*!< interrupt from line 8 */ +#define EXTI_INTEN_INTEN9 BIT(9) /*!< interrupt from line 9 */ +#define EXTI_INTEN_INTEN10 BIT(10) /*!< interrupt from line 10 */ +#define EXTI_INTEN_INTEN11 BIT(11) /*!< interrupt from line 11 */ +#define EXTI_INTEN_INTEN12 BIT(12) /*!< interrupt from line 12 */ +#define EXTI_INTEN_INTEN13 BIT(13) /*!< interrupt from line 13 */ +#define EXTI_INTEN_INTEN14 BIT(14) /*!< interrupt from line 14 */ +#define EXTI_INTEN_INTEN15 BIT(15) /*!< interrupt from line 15 */ +#define EXTI_INTEN_INTEN16 BIT(16) /*!< interrupt from line 16 */ +#define EXTI_INTEN_INTEN17 BIT(17) /*!< interrupt from line 17 */ +#define EXTI_INTEN_INTEN18 BIT(18) /*!< interrupt from line 18 */ +#define EXTI_INTEN_INTEN19 BIT(19) /*!< interrupt from line 19 */ + +/* EXTI_EVEN */ +#define EXTI_EVEN_EVEN0 BIT(0) /*!< event from line 0 */ +#define EXTI_EVEN_EVEN1 BIT(1) /*!< event from line 1 */ +#define EXTI_EVEN_EVEN2 BIT(2) /*!< event from line 2 */ +#define EXTI_EVEN_EVEN3 BIT(3) /*!< event from line 3 */ +#define EXTI_EVEN_EVEN4 BIT(4) /*!< event from line 4 */ +#define EXTI_EVEN_EVEN5 BIT(5) /*!< event from line 5 */ +#define EXTI_EVEN_EVEN6 BIT(6) /*!< event from line 6 */ +#define EXTI_EVEN_EVEN7 BIT(7) /*!< event from line 7 */ +#define EXTI_EVEN_EVEN8 BIT(8) /*!< event from line 8 */ +#define EXTI_EVEN_EVEN9 BIT(9) /*!< event from line 9 */ +#define EXTI_EVEN_EVEN10 BIT(10) /*!< event from line 10 */ +#define EXTI_EVEN_EVEN11 BIT(11) /*!< event from line 11 */ +#define EXTI_EVEN_EVEN12 BIT(12) /*!< event from line 12 */ +#define EXTI_EVEN_EVEN13 BIT(13) /*!< event from line 13 */ +#define EXTI_EVEN_EVEN14 BIT(14) /*!< event from line 14 */ +#define EXTI_EVEN_EVEN15 BIT(15) /*!< event from line 15 */ +#define EXTI_EVEN_EVEN16 BIT(16) /*!< event from line 16 */ +#define EXTI_EVEN_EVEN17 BIT(17) /*!< event from line 17 */ +#define EXTI_EVEN_EVEN18 BIT(18) /*!< event from line 18 */ +#define EXTI_EVEN_EVEN19 BIT(19) /*!< event from line 19 */ + +/* EXTI_RTEN */ +#define EXTI_RTEN_RTEN0 BIT(0) /*!< rising edge from line 0 */ +#define EXTI_RTEN_RTEN1 BIT(1) /*!< rising edge from line 1 */ +#define EXTI_RTEN_RTEN2 BIT(2) /*!< rising edge from line 2 */ +#define EXTI_RTEN_RTEN3 BIT(3) /*!< rising edge from line 3 */ +#define EXTI_RTEN_RTEN4 BIT(4) /*!< rising edge from line 4 */ +#define EXTI_RTEN_RTEN5 BIT(5) /*!< rising edge from line 5 */ +#define EXTI_RTEN_RTEN6 BIT(6) /*!< rising edge from line 6 */ +#define EXTI_RTEN_RTEN7 BIT(7) /*!< rising edge from line 7 */ +#define EXTI_RTEN_RTEN8 BIT(8) /*!< rising edge from line 8 */ +#define EXTI_RTEN_RTEN9 BIT(9) /*!< rising edge from line 9 */ +#define EXTI_RTEN_RTEN10 BIT(10) /*!< rising edge from line 10 */ +#define EXTI_RTEN_RTEN11 BIT(11) /*!< rising edge from line 11 */ +#define EXTI_RTEN_RTEN12 BIT(12) /*!< rising edge from line 12 */ +#define EXTI_RTEN_RTEN13 BIT(13) /*!< rising edge from line 13 */ +#define EXTI_RTEN_RTEN14 BIT(14) /*!< rising edge from line 14 */ +#define EXTI_RTEN_RTEN15 BIT(15) /*!< rising edge from line 15 */ +#define EXTI_RTEN_RTEN16 BIT(16) /*!< rising edge from line 16 */ +#define EXTI_RTEN_RTEN17 BIT(17) /*!< rising edge from line 17 */ +#define EXTI_RTEN_RTEN18 BIT(18) /*!< rising edge from line 18 */ +#define EXTI_RTEN_RTEN19 BIT(19) /*!< rising edge from line 19 */ + +/* EXTI_FTEN */ +#define EXTI_FTEN_FTEN0 BIT(0) /*!< falling edge from line 0 */ +#define EXTI_FTEN_FTEN1 BIT(1) /*!< falling edge from line 1 */ +#define EXTI_FTEN_FTEN2 BIT(2) /*!< falling edge from line 2 */ +#define EXTI_FTEN_FTEN3 BIT(3) /*!< falling edge from line 3 */ +#define EXTI_FTEN_FTEN4 BIT(4) /*!< falling edge from line 4 */ +#define EXTI_FTEN_FTEN5 BIT(5) /*!< falling edge from line 5 */ +#define EXTI_FTEN_FTEN6 BIT(6) /*!< falling edge from line 6 */ +#define EXTI_FTEN_FTEN7 BIT(7) /*!< falling edge from line 7 */ +#define EXTI_FTEN_FTEN8 BIT(8) /*!< falling edge from line 8 */ +#define EXTI_FTEN_FTEN9 BIT(9) /*!< falling edge from line 9 */ +#define EXTI_FTEN_FTEN10 BIT(10) /*!< falling edge from line 10 */ +#define EXTI_FTEN_FTEN11 BIT(11) /*!< falling edge from line 11 */ +#define EXTI_FTEN_FTEN12 BIT(12) /*!< falling edge from line 12 */ +#define EXTI_FTEN_FTEN13 BIT(13) /*!< falling edge from line 13 */ +#define EXTI_FTEN_FTEN14 BIT(14) /*!< falling edge from line 14 */ +#define EXTI_FTEN_FTEN15 BIT(15) /*!< falling edge from line 15 */ +#define EXTI_FTEN_FTEN16 BIT(16) /*!< falling edge from line 16 */ +#define EXTI_FTEN_FTEN17 BIT(17) /*!< falling edge from line 17 */ +#define EXTI_FTEN_FTEN18 BIT(18) /*!< falling edge from line 18 */ +#define EXTI_FTEN_FTEN19 BIT(19) /*!< falling edge from line 19 */ + +/* EXTI_SWIEV */ +#define EXTI_SWIEV_SWIEV0 BIT(0) /*!< software interrupt/event request from line 0 */ +#define EXTI_SWIEV_SWIEV1 BIT(1) /*!< software interrupt/event request from line 1 */ +#define EXTI_SWIEV_SWIEV2 BIT(2) /*!< software interrupt/event request from line 2 */ +#define EXTI_SWIEV_SWIEV3 BIT(3) /*!< software interrupt/event request from line 3 */ +#define EXTI_SWIEV_SWIEV4 BIT(4) /*!< software interrupt/event request from line 4 */ +#define EXTI_SWIEV_SWIEV5 BIT(5) /*!< software interrupt/event request from line 5 */ +#define EXTI_SWIEV_SWIEV6 BIT(6) /*!< software interrupt/event request from line 6 */ +#define EXTI_SWIEV_SWIEV7 BIT(7) /*!< software interrupt/event request from line 7 */ +#define EXTI_SWIEV_SWIEV8 BIT(8) /*!< software interrupt/event request from line 8 */ +#define EXTI_SWIEV_SWIEV9 BIT(9) /*!< software interrupt/event request from line 9 */ +#define EXTI_SWIEV_SWIEV10 BIT(10) /*!< software interrupt/event request from line 10 */ +#define EXTI_SWIEV_SWIEV11 BIT(11) /*!< software interrupt/event request from line 11 */ +#define EXTI_SWIEV_SWIEV12 BIT(12) /*!< software interrupt/event request from line 12 */ +#define EXTI_SWIEV_SWIEV13 BIT(13) /*!< software interrupt/event request from line 13 */ +#define EXTI_SWIEV_SWIEV14 BIT(14) /*!< software interrupt/event request from line 14 */ +#define EXTI_SWIEV_SWIEV15 BIT(15) /*!< software interrupt/event request from line 15 */ +#define EXTI_SWIEV_SWIEV16 BIT(16) /*!< software interrupt/event request from line 16 */ +#define EXTI_SWIEV_SWIEV17 BIT(17) /*!< software interrupt/event request from line 17 */ +#define EXTI_SWIEV_SWIEV18 BIT(18) /*!< software interrupt/event request from line 18 */ +#define EXTI_SWIEV_SWIEV19 BIT(19) /*!< software interrupt/event request from line 19 */ + +/* EXTI_PD */ +#define EXTI_PD_PD0 BIT(0) /*!< interrupt/event pending status from line 0 */ +#define EXTI_PD_PD1 BIT(1) /*!< interrupt/event pending status from line 1 */ +#define EXTI_PD_PD2 BIT(2) /*!< interrupt/event pending status from line 2 */ +#define EXTI_PD_PD3 BIT(3) /*!< interrupt/event pending status from line 3 */ +#define EXTI_PD_PD4 BIT(4) /*!< interrupt/event pending status from line 4 */ +#define EXTI_PD_PD5 BIT(5) /*!< interrupt/event pending status from line 5 */ +#define EXTI_PD_PD6 BIT(6) /*!< interrupt/event pending status from line 6 */ +#define EXTI_PD_PD7 BIT(7) /*!< interrupt/event pending status from line 7 */ +#define EXTI_PD_PD8 BIT(8) /*!< interrupt/event pending status from line 8 */ +#define EXTI_PD_PD9 BIT(9) /*!< interrupt/event pending status from line 9 */ +#define EXTI_PD_PD10 BIT(10) /*!< interrupt/event pending status from line 10 */ +#define EXTI_PD_PD11 BIT(11) /*!< interrupt/event pending status from line 11 */ +#define EXTI_PD_PD12 BIT(12) /*!< interrupt/event pending status from line 12 */ +#define EXTI_PD_PD13 BIT(13) /*!< interrupt/event pending status from line 13 */ +#define EXTI_PD_PD14 BIT(14) /*!< interrupt/event pending status from line 14 */ +#define EXTI_PD_PD15 BIT(15) /*!< interrupt/event pending status from line 15 */ +#define EXTI_PD_PD16 BIT(16) /*!< interrupt/event pending status from line 16 */ +#define EXTI_PD_PD17 BIT(17) /*!< interrupt/event pending status from line 17 */ +#define EXTI_PD_PD18 BIT(18) /*!< interrupt/event pending status from line 18 */ +#define EXTI_PD_PD19 BIT(19) /*!< interrupt/event pending status from line 19 */ + +/* constants definitions */ +/* EXTI line number */ +typedef enum +{ + EXTI_0 = BIT(0), /*!< EXTI line 0 */ + EXTI_1 = BIT(1), /*!< EXTI line 1 */ + EXTI_2 = BIT(2), /*!< EXTI line 2 */ + EXTI_3 = BIT(3), /*!< EXTI line 3 */ + EXTI_4 = BIT(4), /*!< EXTI line 4 */ + EXTI_5 = BIT(5), /*!< EXTI line 5 */ + EXTI_6 = BIT(6), /*!< EXTI line 6 */ + EXTI_7 = BIT(7), /*!< EXTI line 7 */ + EXTI_8 = BIT(8), /*!< EXTI line 8 */ + EXTI_9 = BIT(9), /*!< EXTI line 9 */ + EXTI_10 = BIT(10), /*!< EXTI line 10 */ + EXTI_11 = BIT(11), /*!< EXTI line 11 */ + EXTI_12 = BIT(12), /*!< EXTI line 12 */ + EXTI_13 = BIT(13), /*!< EXTI line 13 */ + EXTI_14 = BIT(14), /*!< EXTI line 14 */ + EXTI_15 = BIT(15), /*!< EXTI line 15 */ + EXTI_16 = BIT(16), /*!< EXTI line 16 */ + EXTI_17 = BIT(17), /*!< EXTI line 17 */ + EXTI_18 = BIT(18), /*!< EXTI line 18 */ + EXTI_19 = BIT(19), /*!< EXTI line 19 */ +}exti_line_enum; + +/* external interrupt and event */ +typedef enum +{ + EXTI_INTERRUPT = 0, /*!< EXTI interrupt mode */ + EXTI_EVENT /*!< EXTI event mode */ +}exti_mode_enum; + +/* interrupt trigger mode */ +typedef enum +{ + EXTI_TRIG_RISING = 0, /*!< EXTI rising edge trigger */ + EXTI_TRIG_FALLING, /*!< EXTI falling edge trigger */ + EXTI_TRIG_BOTH /*!< EXTI rising edge and falling edge trigger */ +}exti_trig_type_enum; + +/* function declarations */ +/* initialization, EXTI lines configuration functions */ +/* deinitialize the EXTI */ +void exti_deinit(void); +/* enable the configuration of EXTI initialize */ +void exti_init(exti_line_enum linex, exti_mode_enum mode, exti_trig_type_enum trig_type); +/* enable the interrupts from EXTI line x */ +void exti_interrupt_enable(exti_line_enum linex); +/* enable the events from EXTI line x */ +void exti_event_enable(exti_line_enum linex); +/* disable the interrupts from EXTI line x */ +void exti_interrupt_disable(exti_line_enum linex); +/* disable the events from EXTI line x */ +void exti_event_disable(exti_line_enum linex); + +/* interrupt & flag functions */ +/* get EXTI lines pending flag */ +FlagStatus exti_flag_get(exti_line_enum linex); +/* clear EXTI lines pending flag */ +void exti_flag_clear(exti_line_enum linex); +/* get EXTI lines flag when the interrupt flag is set */ +FlagStatus exti_interrupt_flag_get(exti_line_enum linex); +/* clear EXTI lines pending flag */ +void exti_interrupt_flag_clear(exti_line_enum linex); +/* enable the EXTI software interrupt event */ +void exti_software_interrupt_enable(exti_line_enum linex); +/* disable the EXTI software interrupt event */ +void exti_software_interrupt_disable(exti_line_enum linex); + +#endif /* GD32F10X_EXTI_H */ diff --git a/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_standard_peripheral/Include/gd32f10x_fmc.h b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_standard_peripheral/Include/gd32f10x_fmc.h new file mode 100644 index 0000000000..d5b834ee0d --- /dev/null +++ b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_standard_peripheral/Include/gd32f10x_fmc.h @@ -0,0 +1,369 @@ +/*! + \file gd32f10x_fmc.h + \brief definitions for the FMC + + \version 2014-12-26, V1.0.0, firmware for GD32F10x + \version 2017-06-20, V2.0.0, firmware for GD32F10x + \version 2018-07-31, V2.1.0, firmware for GD32F10x + \version 2020-09-30, V2.2.0, firmware for GD32F10x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef GD32F10X_FMC_H +#define GD32F10X_FMC_H + +#include "gd32f10x.h" + +/* FMC and option byte definition */ +#define FMC FMC_BASE /*!< FMC register base address */ +#define OB OB_BASE /*!< option bytes base address */ + +/* registers definitions */ +#define FMC_WS REG32((FMC) + 0x00U) /*!< FMC wait state register */ +#define FMC_KEY0 REG32((FMC) + 0x04U) /*!< FMC unlock key register 0 */ +#define FMC_OBKEY REG32((FMC) + 0x08U) /*!< FMC option bytes unlock key register */ +#define FMC_STAT0 REG32((FMC) + 0x0CU) /*!< FMC status register 0 */ +#define FMC_CTL0 REG32((FMC) + 0x10U) /*!< FMC control register 0 */ +#define FMC_ADDR0 REG32((FMC) + 0x14U) /*!< FMC address register 0 */ +#define FMC_OBSTAT REG32((FMC) + 0x1CU) /*!< FMC option bytes status register */ +#define FMC_WP REG32((FMC) + 0x20U) /*!< FMC erase/program protection register */ +#define FMC_KEY1 REG32((FMC) + 0x44U) /*!< FMC unlock key register 1 */ +#define FMC_STAT1 REG32((FMC) + 0x4CU) /*!< FMC status register 1 */ +#define FMC_CTL1 REG32((FMC) + 0x50U) /*!< FMC control register 1 */ +#define FMC_ADDR1 REG32((FMC) + 0x54U) /*!< FMC address register 1 */ +#define FMC_WSEN REG32((FMC) + 0xFCU) /*!< FMC wait state enable register */ +#define FMC_PID REG32((FMC) + 0x100U) /*!< FMC product ID register */ + +#define OB_SPC REG16((OB) + 0x00U) /*!< option byte security protection value */ +#define OB_USER REG16((OB) + 0x02U) /*!< option byte user value*/ +#define OB_WP0 REG16((OB) + 0x08U) /*!< option byte write protection 0 */ +#define OB_WP1 REG16((OB) + 0x0AU) /*!< option byte write protection 1 */ +#define OB_WP2 REG16((OB) + 0x0CU) /*!< option byte write protection 2 */ +#define OB_WP3 REG16((OB) + 0x0EU) /*!< option byte write protection 3 */ + +/* bits definitions */ +/* FMC_WS */ +#define FMC_WS_WSCNT BITS(0,2) /*!< wait state counter */ + +/* FMC_KEY0 */ +#define FMC_KEY0_KEY BITS(0,31) /*!< FMC_CTL0 unlock key bits */ + +/* FMC_OBKEY */ +#define FMC_OBKEY_OBKEY BITS(0,31) /*!< option bytes unlock key bits */ + +/* FMC_STAT0 */ +#define FMC_STAT0_BUSY BIT(0) /*!< flash busy flag bit */ +#define FMC_STAT0_PGERR BIT(2) /*!< flash program error flag bit */ +#define FMC_STAT0_WPERR BIT(4) /*!< erase/program protection error flag bit */ +#define FMC_STAT0_ENDF BIT(5) /*!< end of operation flag bit */ + +/* FMC_CTL0 */ +#define FMC_CTL0_PG BIT(0) /*!< main flash program for bank0 command bit */ +#define FMC_CTL0_PER BIT(1) /*!< main flash page erase for bank0 command bit */ +#define FMC_CTL0_MER BIT(2) /*!< main flash mass erase for bank0 command bit */ +#define FMC_CTL0_OBPG BIT(4) /*!< option bytes program command bit */ +#define FMC_CTL0_OBER BIT(5) /*!< option bytes erase command bit */ +#define FMC_CTL0_START BIT(6) /*!< send erase command to FMC bit */ +#define FMC_CTL0_LK BIT(7) /*!< FMC_CTL0 lock bit */ +#define FMC_CTL0_OBWEN BIT(9) /*!< option bytes erase/program enable bit */ +#define FMC_CTL0_ERRIE BIT(10) /*!< error interrupt enable bit */ +#define FMC_CTL0_ENDIE BIT(12) /*!< end of operation interrupt enable bit */ + +/* FMC_ADDR0 */ +#define FMC_ADDR0_ADDR BITS(0,31) /*!< flash erase/program command address bits */ + +/* FMC_OBSTAT */ +#define FMC_OBSTAT_OBERR BIT(0) /*!< option bytes read error bit. */ +#define FMC_OBSTAT_SPC BIT(1) /*!< option bytes security protection code */ +#define FMC_OBSTAT_USER BITS(2,9) /*!< store USER of option bytes block after system reset */ +#define FMC_OBSTAT_DATA BITS(10,25) /*!< store DATA of option bytes block after system reset. */ + +/* FMC_WP */ +#define FMC_WP_WP BITS(0,31) /*!< store WP of option bytes block after system reset */ + +/* FMC_KEY1 */ +#define FMC_KEY1_KEY BITS(0,31) /*!< FMC_CTL1 unlock key bits */ + +/* FMC_STAT1 */ +#define FMC_STAT1_BUSY BIT(0) /*!< flash busy flag bit */ +#define FMC_STAT1_PGERR BIT(2) /*!< flash program error flag bit */ +#define FMC_STAT1_WPERR BIT(4) /*!< erase/program protection error flag bit */ +#define FMC_STAT1_ENDF BIT(5) /*!< end of operation flag bit */ + +/* FMC_CTL1 */ +#define FMC_CTL1_PG BIT(0) /*!< main flash program for bank1 command bit */ +#define FMC_CTL1_PER BIT(1) /*!< main flash page erase for bank1 command bit */ +#define FMC_CTL1_MER BIT(2) /*!< main flash mass erase for bank1 command bit */ +#define FMC_CTL1_START BIT(6) /*!< send erase command to FMC bit */ +#define FMC_CTL1_LK BIT(7) /*!< FMC_CTL1 lock bit */ +#define FMC_CTL1_ERRIE BIT(10) /*!< error interrupt enable bit */ +#define FMC_CTL1_ENDIE BIT(12) /*!< end of operation interrupt enable bit */ + +/* FMC_ADDR1 */ +#define FMC_ADDR1_ADDR BITS(0,31) /*!< flash erase/program command address bits */ + +/* FMC_WSEN */ +#define FMC_WSEN_WSEN BIT(0) /*!< FMC wait state enable bit */ + +/* FMC_PID */ +#define FMC_PID_PID BITS(0,31) /*!< product ID bits */ + +/* constants definitions */ +/* define the FMC bit position and its register index offset */ +#define FMC_REGIDX_BIT(regidx, bitpos) (((uint32_t)(regidx) << 6) | (uint32_t)(bitpos)) +#define FMC_REG_VAL(offset) (REG32(FMC + ((uint32_t)(offset) >> 6))) +#define FMC_BIT_POS(val) ((uint32_t)(val) & 0x1FU) +#define FMC_REGIDX_BITS(regidx, bitpos0, bitpos1) (((uint32_t)(regidx) << 12) | ((uint32_t)(bitpos0) << 6) | (uint32_t)(bitpos1)) +#define FMC_REG_VALS(offset) (REG32(FMC + ((uint32_t)(offset) >> 12))) +#define FMC_BIT_POS0(val) (((uint32_t)(val) >> 6) & 0x1FU) +#define FMC_BIT_POS1(val) ((uint32_t)(val) & 0x1FU) +#define FMC_REG_OFFSET_GET(flag) ((uint32_t)(flag) >> 12) + +/* configuration register */ +#define FMC_STAT0_REG_OFFSET 0x0CU /*!< status register 0 offset */ +#define FMC_CTL0_REG_OFFSET 0x10U /*!< control register 0 offset */ +#define FMC_STAT1_REG_OFFSET 0x4CU /*!< status register 1 offset */ +#define FMC_CTL1_REG_OFFSET 0x50U /*!< control register 1 offset */ +#define FMC_OBSTAT_REG_OFFSET 0x1CU /*!< option byte status register offset */ + +/* fmc state */ +typedef enum +{ + FMC_READY, /*!< the operation has been completed */ + FMC_BUSY, /*!< the operation is in progress */ + FMC_PGERR, /*!< program error */ + FMC_WPERR, /*!< erase/program protection error */ + FMC_TOERR, /*!< timeout error */ +}fmc_state_enum; + +/* FMC interrupt enable */ +typedef enum +{ + FMC_INT_BANK0_END = FMC_REGIDX_BIT(FMC_CTL0_REG_OFFSET, 12U), /*!< enable FMC end of program interrupt */ + FMC_INT_BANK0_ERR = FMC_REGIDX_BIT(FMC_CTL0_REG_OFFSET, 10U), /*!< enable FMC error interrupt */ + FMC_INT_BANK1_END = FMC_REGIDX_BIT(FMC_CTL1_REG_OFFSET, 12U), /*!< enable FMC bank1 end of program interrupt */ + FMC_INT_BANK1_ERR = FMC_REGIDX_BIT(FMC_CTL1_REG_OFFSET, 10U), /*!< enable FMC bank1 error interrupt */ +}fmc_int_enum; + +/* FMC flags */ +typedef enum +{ + FMC_FLAG_BANK0_BUSY = FMC_REGIDX_BIT(FMC_STAT0_REG_OFFSET, 0U), /*!< FMC bank0 busy flag */ + FMC_FLAG_BANK0_PGERR = FMC_REGIDX_BIT(FMC_STAT0_REG_OFFSET, 2U), /*!< FMC bank0 operation error flag bit */ + FMC_FLAG_BANK0_WPERR = FMC_REGIDX_BIT(FMC_STAT0_REG_OFFSET, 4U), /*!< FMC bank0 erase/program protection error flag bit */ + FMC_FLAG_BANK0_END = FMC_REGIDX_BIT(FMC_STAT0_REG_OFFSET, 5U), /*!< FMC bank0 end of operation flag bit */ + FMC_FLAG_OBERR = FMC_REGIDX_BIT(FMC_OBSTAT_REG_OFFSET, 0U), /*!< FMC option bytes read error flag */ + FMC_FLAG_BANK1_BUSY = FMC_REGIDX_BIT(FMC_STAT1_REG_OFFSET, 0U), /*!< FMC bank1 busy flag */ + FMC_FLAG_BANK1_PGERR = FMC_REGIDX_BIT(FMC_STAT1_REG_OFFSET, 2U), /*!< FMC bank1 operation error flag bit */ + FMC_FLAG_BANK1_WPERR = FMC_REGIDX_BIT(FMC_STAT1_REG_OFFSET, 4U), /*!< FMC bank1 erase/program protection error flag bit */ + FMC_FLAG_BANK1_END = FMC_REGIDX_BIT(FMC_STAT1_REG_OFFSET, 5U), /*!< FMC bank1 end of operation flag bit */ +}fmc_flag_enum; + +/* FMC interrupt flags */ +typedef enum +{ + FMC_INT_FLAG_BANK0_PGERR = FMC_REGIDX_BITS(FMC_STAT0_REG_OFFSET, 2U, 10U), /*!< FMC bank0 operation error interrupt flag bit */ + FMC_INT_FLAG_BANK0_WPERR = FMC_REGIDX_BITS(FMC_STAT0_REG_OFFSET, 4U, 10U), /*!< FMC bank0 erase/program protection error interrupt flag bit */ + FMC_INT_FLAG_BANK0_END = FMC_REGIDX_BITS(FMC_STAT0_REG_OFFSET, 5U, 12U), /*!< FMC bank0 end of operation interrupt flag bit */ + FMC_INT_FLAG_BANK1_PGERR = FMC_REGIDX_BITS(FMC_STAT1_REG_OFFSET, 2U, 10U), /*!< FMC bank1 operation error interrupt flag bit */ + FMC_INT_FLAG_BANK1_WPERR = FMC_REGIDX_BITS(FMC_STAT1_REG_OFFSET, 4U, 10U), /*!< FMC bank1 erase/program protection error interrupt flag bit */ + FMC_INT_FLAG_BANK1_END = FMC_REGIDX_BITS(FMC_STAT1_REG_OFFSET, 5U, 12U), /*!< FMC bank1 end of operation interrupt flag bit */ +}fmc_interrupt_flag_enum; + +/* unlock key */ +#define UNLOCK_KEY0 ((uint32_t)0x45670123U) /*!< unlock key 0 */ +#define UNLOCK_KEY1 ((uint32_t)0xCDEF89ABU) /*!< unlock key 1 */ + +/* FMC wait state counter */ +#define WS_WSCNT(regval) (BITS(0,2) & ((uint32_t)(regval))) +#define WS_WSCNT_0 WS_WSCNT(0) /*!< FMC 0 wait */ +#define WS_WSCNT_1 WS_WSCNT(1) /*!< FMC 1 wait */ +#define WS_WSCNT_2 WS_WSCNT(2) /*!< FMC 2 wait */ + +/* option bytes software/hardware free watch dog timer */ +#define OB_FWDGT_SW ((uint8_t)0x01U) /*!< software free watchdog */ +#define OB_FWDGT_HW ((uint8_t)0x00U) /*!< hardware free watchdog */ + +/* option bytes reset or not entering deep sleep mode */ +#define OB_DEEPSLEEP_NRST ((uint8_t)0x02U) /*!< no reset when entering deepsleep mode */ +#define OB_DEEPSLEEP_RST ((uint8_t)0x00U) /*!< generate a reset instead of entering deepsleep mode */ + +/* option bytes reset or not entering standby mode */ +#define OB_STDBY_NRST ((uint8_t)0x04U) /*!< no reset when entering deepsleep mode */ +#define OB_STDBY_RST ((uint8_t)0x00U) /*!< generate a reset instead of entering standby mode */ + +/* option bytes boot bank value */ +#define OB_BOOT_B0 ((uint8_t)0x08U) /*!< boot from bank0 */ +#define OB_BOOT_B1 ((uint8_t)0x00U) /*!< boot from bank1 */ + +#define OB_USER_MASK ((uint8_t)0xF0U) /*!< MASK value */ + +/* read protect configure */ +#define FMC_NSPC ((uint8_t)0xA5U) /*!< no security protection */ +#define FMC_USPC ((uint8_t)0xBBU) /*!< under security protection */ + +/* OB_SPC */ +#define OB_SPC_SPC ((uint32_t)0x000000FFU) /*!< option byte security protection value */ +#define OB_SPC_SPC_N ((uint32_t)0x0000FF00U) /*!< option byte security protection complement value */ + +/* OB_USER */ +#define OB_USER_USER ((uint32_t)0x00FF0000U) /*!< user option value */ +#define OB_USER_USER_N ((uint32_t)0xFF000000U) /*!< user option complement value */ + +/* OB_WP0 */ +#define OB_WP0_WP0 ((uint32_t)0x000000FFU) /*!< FMC write protection option value */ + +/* OB_WP1 */ +#define OB_WP1_WP1 ((uint32_t)0x0000FF00U) /*!< FMC write protection option complement value */ + +/* OB_WP2 */ +#define OB_WP2_WP2 ((uint32_t)0x00FF0000U) /*!< FMC write protection option value */ + +/* OB_WP3 */ +#define OB_WP3_WP3 ((uint32_t)0xFF000000U) /*!< FMC write protection option complement value */ + +/* option bytes write protection */ +#define OB_WP_0 ((uint32_t)0x00000001U) /*!< erase/program protection of sector 0 */ +#define OB_WP_1 ((uint32_t)0x00000002U) /*!< erase/program protection of sector 1 */ +#define OB_WP_2 ((uint32_t)0x00000004U) /*!< erase/program protection of sector 2 */ +#define OB_WP_3 ((uint32_t)0x00000008U) /*!< erase/program protection of sector 3 */ +#define OB_WP_4 ((uint32_t)0x00000010U) /*!< erase/program protection of sector 4 */ +#define OB_WP_5 ((uint32_t)0x00000020U) /*!< erase/program protection of sector 5 */ +#define OB_WP_6 ((uint32_t)0x00000040U) /*!< erase/program protection of sector 6 */ +#define OB_WP_7 ((uint32_t)0x00000080U) /*!< erase/program protection of sector 7 */ +#define OB_WP_8 ((uint32_t)0x00000100U) /*!< erase/program protection of sector 8 */ +#define OB_WP_9 ((uint32_t)0x00000200U) /*!< erase/program protection of sector 9 */ +#define OB_WP_10 ((uint32_t)0x00000400U) /*!< erase/program protection of sector 10 */ +#define OB_WP_11 ((uint32_t)0x00000800U) /*!< erase/program protection of sector 11 */ +#define OB_WP_12 ((uint32_t)0x00001000U) /*!< erase/program protection of sector 12 */ +#define OB_WP_13 ((uint32_t)0x00002000U) /*!< erase/program protection of sector 13 */ +#define OB_WP_14 ((uint32_t)0x00004000U) /*!< erase/program protection of sector 14 */ +#define OB_WP_15 ((uint32_t)0x00008000U) /*!< erase/program protection of sector 15 */ +#define OB_WP_16 ((uint32_t)0x00010000U) /*!< erase/program protection of sector 16 */ +#define OB_WP_17 ((uint32_t)0x00020000U) /*!< erase/program protection of sector 17 */ +#define OB_WP_18 ((uint32_t)0x00040000U) /*!< erase/program protection of sector 18 */ +#define OB_WP_19 ((uint32_t)0x00080000U) /*!< erase/program protection of sector 19 */ +#define OB_WP_20 ((uint32_t)0x00100000U) /*!< erase/program protection of sector 20 */ +#define OB_WP_21 ((uint32_t)0x00200000U) /*!< erase/program protection of sector 21 */ +#define OB_WP_22 ((uint32_t)0x00400000U) /*!< erase/program protection of sector 22 */ +#define OB_WP_23 ((uint32_t)0x00800000U) /*!< erase/program protection of sector 23 */ +#define OB_WP_24 ((uint32_t)0x01000000U) /*!< erase/program protection of sector 24 */ +#define OB_WP_25 ((uint32_t)0x02000000U) /*!< erase/program protection of sector 25 */ +#define OB_WP_26 ((uint32_t)0x04000000U) /*!< erase/program protection of sector 26 */ +#define OB_WP_27 ((uint32_t)0x08000000U) /*!< erase/program protection of sector 27 */ +#define OB_WP_28 ((uint32_t)0x10000000U) /*!< erase/program protection of sector 28 */ +#define OB_WP_29 ((uint32_t)0x20000000U) /*!< erase/program protection of sector 29 */ +#define OB_WP_30 ((uint32_t)0x40000000U) /*!< erase/program protection of sector 30 */ +#define OB_WP_31 ((uint32_t)0x80000000U) /*!< erase/program protection of sector 31 */ +#define OB_WP_ALL ((uint32_t)0xFFFFFFFFU) /*!< erase/program protection of all sectors */ + +/* FMC timeout */ +#define FMC_TIMEOUT_COUNT ((uint32_t)0x000F0000U) /*!< FMC timeout count value */ + +/* FMC BANK address */ +#define FMC_BANK0_END_ADDRESS ((uint32_t)0x0807FFFFU) /*!< FMC bank0 end address */ +#define FMC_BANK0_SIZE ((uint32_t)0x00000200U) /*!< FMC bank0 size */ +#define FMC_SIZE (*(uint16_t *)0x1FFFF7E0U) /*!< FMC size */ + +/* function declarations */ +/* FMC main memory programming functions */ +/* set the FMC wait state counter */ +void fmc_wscnt_set(uint32_t wscnt); +/* unlock the main FMC operation */ +void fmc_unlock(void); +/* unlock the FMC bank0 operation */ +void fmc_bank0_unlock(void); +/* unlock the FMC bank1 operation */ +void fmc_bank1_unlock(void); +/* lock the main FMC operation */ +void fmc_lock(void); +/* lock the bank0 FMC operation */ +void fmc_bank0_lock(void); +/* lock the bank1 FMC operation */ +void fmc_bank1_lock(void); +/* FMC erase page */ +fmc_state_enum fmc_page_erase(uint32_t page_address); +/* FMC erase whole chip */ +fmc_state_enum fmc_mass_erase(void); +/* FMC erase whole bank0 */ +fmc_state_enum fmc_bank0_erase(void); +/* FMC erase whole bank1 */ +fmc_state_enum fmc_bank1_erase(void); +/* FMC program a word at the corresponding address */ +fmc_state_enum fmc_word_program(uint32_t address, uint32_t data); +/* FMC program a half word at the corresponding address */ +fmc_state_enum fmc_halfword_program(uint32_t address, uint16_t data); + +/* FMC option bytes programming functions */ +/* unlock the option byte operation */ +void ob_unlock(void); +/* lock the option byte operation */ +void ob_lock(void); +/* erase the option byte */ +fmc_state_enum ob_erase(void); +/* enable write protect */ +fmc_state_enum ob_write_protection_enable(uint32_t ob_wp); +/* configure the option byte security protection */ +fmc_state_enum ob_security_protection_config(uint8_t ob_spc); +/* write the FMC option byte */ +fmc_state_enum ob_user_write(uint8_t ob_fwdgt, uint8_t ob_deepsleep, uint8_t ob_stdby, uint8_t ob_boot); +/* program option bytes data */ +fmc_state_enum ob_data_program(uint32_t address, uint8_t data); +/* get the FMC option byte user */ +uint8_t ob_user_get(void); +/* get OB_DATA in register FMC_OBSTAT */ +uint16_t ob_data_get(void); +/* get the FMC option byte write protection */ +uint32_t ob_write_protection_get(void); +/* get option byte security protection code value */ +FlagStatus ob_spc_get(void); + +/* FMC interrupts and flags management functions */ +/* enable FMC interrupt */ +void fmc_interrupt_enable(uint32_t interrupt); +/* disable FMC interrupt */ +void fmc_interrupt_disable(uint32_t interrupt); +/* check flag is set or not */ +FlagStatus fmc_flag_get(uint32_t flag); +/* clear the FMC flag */ +void fmc_flag_clear(uint32_t flag); +/* get FMC interrupt flag state */ +FlagStatus fmc_interrupt_flag_get(fmc_interrupt_flag_enum flag); +/* clear FMC interrupt flag state */ +void fmc_interrupt_flag_clear(fmc_interrupt_flag_enum flag); +/* return the FMC bank0 state */ +fmc_state_enum fmc_bank0_state_get(void); +/* return the FMC bank1 state */ +fmc_state_enum fmc_bank1_state_get(void); +/* check FMC bank0 ready or not */ +fmc_state_enum fmc_bank0_ready_wait(uint32_t timeout); +/* check FMC bank1 ready or not */ +fmc_state_enum fmc_bank1_ready_wait(uint32_t timeout); + +#endif /* GD32F10X_FMC_H */ diff --git a/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_standard_peripheral/Include/gd32f10x_fwdgt.h b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_standard_peripheral/Include/gd32f10x_fwdgt.h new file mode 100644 index 0000000000..d17c3691ee --- /dev/null +++ b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_standard_peripheral/Include/gd32f10x_fwdgt.h @@ -0,0 +1,107 @@ +/*! + \file gd32f10x_fwdgt.h + \brief definitions for the FWDGT + + \version 2014-12-26, V1.0.0, firmware for GD32F10x + \version 2017-06-20, V2.0.0, firmware for GD32F10x + \version 2018-07-31, V2.1.0, firmware for GD32F10x + \version 2020-09-30, V2.2.0, firmware for GD32F10x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef GD32F10X_FWDGT_H +#define GD32F10X_FWDGT_H + +#include "gd32f10x.h" + +/* FWDGT definitions */ +#define FWDGT FWDGT_BASE /*!< FWDGT base address */ + +/* registers definitions */ +#define FWDGT_CTL REG32((FWDGT) + 0x00U) /*!< FWDGT control register */ +#define FWDGT_PSC REG32((FWDGT) + 0x04U) /*!< FWDGT prescaler register */ +#define FWDGT_RLD REG32((FWDGT) + 0x08U) /*!< FWDGT reload register */ +#define FWDGT_STAT REG32((FWDGT) + 0x0CU) /*!< FWDGT status register */ + +/* bits definitions */ +/* FWDGT_CTL */ +#define FWDGT_CTL_CMD BITS(0,15) /*!< FWDGT command value */ + +/* FWDGT_PSC */ +#define FWDGT_PSC_PSC BITS(0,2) /*!< FWDGT prescaler divider value */ + +/* FWDGT_RLD */ +#define FWDGT_RLD_RLD BITS(0,11) /*!< FWDGT counter reload value */ + +/* FWDGT_STAT */ +#define FWDGT_STAT_PUD BIT(0) /*!< FWDGT prescaler divider value update */ +#define FWDGT_STAT_RUD BIT(1) /*!< FWDGT counter reload value update */ + +/* constants definitions */ +/* psc register value */ +#define PSC_PSC(regval) (BITS(0,2) & ((uint32_t)(regval) << 0)) +#define FWDGT_PSC_DIV4 ((uint8_t)PSC_PSC(0)) /*!< FWDGT prescaler set to 4 */ +#define FWDGT_PSC_DIV8 ((uint8_t)PSC_PSC(1)) /*!< FWDGT prescaler set to 8 */ +#define FWDGT_PSC_DIV16 ((uint8_t)PSC_PSC(2)) /*!< FWDGT prescaler set to 16 */ +#define FWDGT_PSC_DIV32 ((uint8_t)PSC_PSC(3)) /*!< FWDGT prescaler set to 32 */ +#define FWDGT_PSC_DIV64 ((uint8_t)PSC_PSC(4)) /*!< FWDGT prescaler set to 64 */ +#define FWDGT_PSC_DIV128 ((uint8_t)PSC_PSC(5)) /*!< FWDGT prescaler set to 128 */ +#define FWDGT_PSC_DIV256 ((uint8_t)PSC_PSC(6)) /*!< FWDGT prescaler set to 256 */ + +/* control value */ +#define FWDGT_WRITEACCESS_ENABLE ((uint16_t)0x5555U) /*!< FWDGT_CTL bits write access enable value */ +#define FWDGT_WRITEACCESS_DISABLE ((uint16_t)0x0000U) /*!< FWDGT_CTL bits write access disable value */ +#define FWDGT_KEY_RELOAD ((uint16_t)0xAAAAU) /*!< FWDGT_CTL bits fwdgt counter reload value */ +#define FWDGT_KEY_ENABLE ((uint16_t)0xCCCCU) /*!< FWDGT_CTL bits fwdgt counter enable value */ + +/* FWDGT timeout value */ +#define FWDGT_PSC_TIMEOUT ((uint32_t)0x000FFFFFU) /*!< FWDGT_PSC register write operation state flag timeout */ +#define FWDGT_RLD_TIMEOUT ((uint32_t)0x000FFFFFU) /*!< FWDGT_RLD register write operation state flag timeout */ + +/* FWDGT flag definitions */ +#define FWDGT_FLAG_PUD FWDGT_STAT_PUD /*!< FWDGT prescaler divider value update flag */ +#define FWDGT_FLAG_RUD FWDGT_STAT_RUD /*!< FWDGT counter reload value update flag */ + +/* function declarations */ +/* enable write access to FWDGT_PSC and FWDGT_RLD */ +void fwdgt_write_enable(void); +/* disable write access to FWDGT_PSC and FWDGT_RLD */ +void fwdgt_write_disable(void); +/* start the free watchdog timer counter */ +void fwdgt_enable(void); + +/* reload the counter of FWDGT */ +void fwdgt_counter_reload(void); +/* configure counter reload value, and prescaler divider value */ +ErrStatus fwdgt_config(uint16_t reload_value, uint8_t prescaler_div); + +/* get flag state of FWDGT */ +FlagStatus fwdgt_flag_get(uint16_t flag); + +#endif /* GD32F10X_FWDGT_H */ diff --git a/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_standard_peripheral/Include/gd32f10x_gpio.h b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_standard_peripheral/Include/gd32f10x_gpio.h new file mode 100644 index 0000000000..eeafc41012 --- /dev/null +++ b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_standard_peripheral/Include/gd32f10x_gpio.h @@ -0,0 +1,498 @@ +/*! + \file gd32f10x_gpio.h + \brief definitions for the GPIO + + \version 2014-12-26, V1.0.0, firmware for GD32F10x + \version 2017-06-20, V2.0.0, firmware for GD32F10x + \version 2018-07-31, V2.1.0, firmware for GD32F10x + \version 2020-09-30, V2.2.0, firmware for GD32F10x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef GD32F10x_GPIO_H +#define GD32F10x_GPIO_H + +#include "gd32f10x.h" + +/* GPIOx(x=A,B,C,D,E,F,G) definitions */ +#define GPIOA (GPIO_BASE + 0x00000000U) +#define GPIOB (GPIO_BASE + 0x00000400U) +#define GPIOC (GPIO_BASE + 0x00000800U) +#define GPIOD (GPIO_BASE + 0x00000C00U) +#define GPIOE (GPIO_BASE + 0x00001000U) +#define GPIOF (GPIO_BASE + 0x00001400U) +#define GPIOG (GPIO_BASE + 0x00001800U) + +/* AFIO definitions */ +#define AFIO AFIO_BASE + +/* registers definitions */ + +/* GPIO registers definitions */ +#define GPIO_CTL0(gpiox) REG32((gpiox) + 0x00U) /*!< GPIO port control register 0 */ +#define GPIO_CTL1(gpiox) REG32((gpiox) + 0x04U) /*!< GPIO port control register 1 */ +#define GPIO_ISTAT(gpiox) REG32((gpiox) + 0x08U) /*!< GPIO port input status register */ +#define GPIO_OCTL(gpiox) REG32((gpiox) + 0x0CU) /*!< GPIO port output control register */ +#define GPIO_BOP(gpiox) REG32((gpiox) + 0x10U) /*!< GPIO port bit operation register */ +#define GPIO_BC(gpiox) REG32((gpiox) + 0x14U) /*!< GPIO bit clear register */ +#define GPIO_LOCK(gpiox) REG32((gpiox) + 0x18U) /*!< GPIO port configuration lock register */ + +/* AFIO registers definitions */ +#define AFIO_EC REG32(AFIO + 0x00U) /*!< AFIO event control register */ +#define AFIO_PCF0 REG32(AFIO + 0x04U) /*!< AFIO port configuration register 0 */ +#define AFIO_EXTISS0 REG32(AFIO + 0x08U) /*!< AFIO port EXTI sources selection register 0 */ +#define AFIO_EXTISS1 REG32(AFIO + 0x0CU) /*!< AFIO port EXTI sources selection register 1 */ +#define AFIO_EXTISS2 REG32(AFIO + 0x10U) /*!< AFIO port EXTI sources selection register 2 */ +#define AFIO_EXTISS3 REG32(AFIO + 0x14U) /*!< AFIO port EXTI sources selection register 3 */ +#define AFIO_PCF1 REG32(AFIO + 0x1CU) /*!< AFIO port configuration register 1 */ + +/* bits definitions */ +/* GPIO_CTL0 */ +#define GPIO_CTL0_MD0 BITS(0,1) /*!< port 0 mode bits */ +#define GPIO_CTL0_CTL0 BITS(2,3) /*!< pin 0 configuration bits */ +#define GPIO_CTL0_MD1 BITS(4,5) /*!< port 1 mode bits */ +#define GPIO_CTL0_CTL1 BITS(6,7) /*!< pin 1 configuration bits */ +#define GPIO_CTL0_MD2 BITS(8,9) /*!< port 2 mode bits */ +#define GPIO_CTL0_CTL2 BITS(10,11) /*!< pin 2 configuration bits */ +#define GPIO_CTL0_MD3 BITS(12,13) /*!< port 3 mode bits */ +#define GPIO_CTL0_CTL3 BITS(14,15) /*!< pin 3 configuration bits */ +#define GPIO_CTL0_MD4 BITS(16,17) /*!< port 4 mode bits */ +#define GPIO_CTL0_CTL4 BITS(18,19) /*!< pin 4 configuration bits */ +#define GPIO_CTL0_MD5 BITS(20,21) /*!< port 5 mode bits */ +#define GPIO_CTL0_CTL5 BITS(22,23) /*!< pin 5 configuration bits */ +#define GPIO_CTL0_MD6 BITS(24,25) /*!< port 6 mode bits */ +#define GPIO_CTL0_CTL6 BITS(26,27) /*!< pin 6 configuration bits */ +#define GPIO_CTL0_MD7 BITS(28,29) /*!< port 7 mode bits */ +#define GPIO_CTL0_CTL7 BITS(30,31) /*!< pin 7 configuration bits */ + +/* GPIO_CTL1 */ +#define GPIO_CTL1_MD8 BITS(0,1) /*!< port 8 mode bits */ +#define GPIO_CTL1_CTL8 BITS(2,3) /*!< pin 8 configuration bits */ +#define GPIO_CTL1_MD9 BITS(4,5) /*!< port 9 mode bits */ +#define GPIO_CTL1_CTL9 BITS(6,7) /*!< pin 9 configuration bits */ +#define GPIO_CTL1_MD10 BITS(8,9) /*!< port 10 mode bits */ +#define GPIO_CTL1_CTL10 BITS(10,11) /*!< pin 10 configuration bits */ +#define GPIO_CTL1_MD11 BITS(12,13) /*!< port 11 mode bits */ +#define GPIO_CTL1_CTL11 BITS(14,15) /*!< pin 11 configuration bits */ +#define GPIO_CTL1_MD12 BITS(16,17) /*!< port 12 mode bits */ +#define GPIO_CTL1_CTL12 BITS(18,19) /*!< pin 12 configuration bits */ +#define GPIO_CTL1_MD13 BITS(20,21) /*!< port 13 mode bits */ +#define GPIO_CTL1_CTL13 BITS(22,23) /*!< pin 13 configuration bits */ +#define GPIO_CTL1_MD14 BITS(24,25) /*!< port 14 mode bits */ +#define GPIO_CTL1_CTL14 BITS(26,27) /*!< pin 14 configuration bits */ +#define GPIO_CTL1_MD15 BITS(28,29) /*!< port 15 mode bits */ +#define GPIO_CTL1_CTL15 BITS(30,31) /*!< pin 15 configuration bits */ + +/* GPIO_ISTAT */ +#define GPIO_ISTAT_ISTAT0 BIT(0) /*!< pin 0 input status */ +#define GPIO_ISTAT_ISTAT1 BIT(1) /*!< pin 1 input status */ +#define GPIO_ISTAT_ISTAT2 BIT(2) /*!< pin 2 input status */ +#define GPIO_ISTAT_ISTAT3 BIT(3) /*!< pin 3 input status */ +#define GPIO_ISTAT_ISTAT4 BIT(4) /*!< pin 4 input status */ +#define GPIO_ISTAT_ISTAT5 BIT(5) /*!< pin 5 input status */ +#define GPIO_ISTAT_ISTAT6 BIT(6) /*!< pin 6 input status */ +#define GPIO_ISTAT_ISTAT7 BIT(7) /*!< pin 7 input status */ +#define GPIO_ISTAT_ISTAT8 BIT(8) /*!< pin 8 input status */ +#define GPIO_ISTAT_ISTAT9 BIT(9) /*!< pin 9 input status */ +#define GPIO_ISTAT_ISTAT10 BIT(10) /*!< pin 10 input status */ +#define GPIO_ISTAT_ISTAT11 BIT(11) /*!< pin 11 input status */ +#define GPIO_ISTAT_ISTAT12 BIT(12) /*!< pin 12 input status */ +#define GPIO_ISTAT_ISTAT13 BIT(13) /*!< pin 13 input status */ +#define GPIO_ISTAT_ISTAT14 BIT(14) /*!< pin 14 input status */ +#define GPIO_ISTAT_ISTAT15 BIT(15) /*!< pin 15 input status */ + +/* GPIO_OCTL */ +#define GPIO_OCTL_OCTL0 BIT(0) /*!< pin 0 output bit */ +#define GPIO_OCTL_OCTL1 BIT(1) /*!< pin 1 output bit */ +#define GPIO_OCTL_OCTL2 BIT(2) /*!< pin 2 output bit */ +#define GPIO_OCTL_OCTL3 BIT(3) /*!< pin 3 output bit */ +#define GPIO_OCTL_OCTL4 BIT(4) /*!< pin 4 output bit */ +#define GPIO_OCTL_OCTL5 BIT(5) /*!< pin 5 output bit */ +#define GPIO_OCTL_OCTL6 BIT(6) /*!< pin 6 output bit */ +#define GPIO_OCTL_OCTL7 BIT(7) /*!< pin 7 output bit */ +#define GPIO_OCTL_OCTL8 BIT(8) /*!< pin 8 output bit */ +#define GPIO_OCTL_OCTL9 BIT(9) /*!< pin 9 output bit */ +#define GPIO_OCTL_OCTL10 BIT(10) /*!< pin 10 output bit */ +#define GPIO_OCTL_OCTL11 BIT(11) /*!< pin 11 output bit */ +#define GPIO_OCTL_OCTL12 BIT(12) /*!< pin 12 output bit */ +#define GPIO_OCTL_OCTL13 BIT(13) /*!< pin 13 output bit */ +#define GPIO_OCTL_OCTL14 BIT(14) /*!< pin 14 output bit */ +#define GPIO_OCTL_OCTL15 BIT(15) /*!< pin 15 output bit */ + +/* GPIO_BOP */ +#define GPIO_BOP_BOP0 BIT(0) /*!< pin 0 set bit */ +#define GPIO_BOP_BOP1 BIT(1) /*!< pin 1 set bit */ +#define GPIO_BOP_BOP2 BIT(2) /*!< pin 2 set bit */ +#define GPIO_BOP_BOP3 BIT(3) /*!< pin 3 set bit */ +#define GPIO_BOP_BOP4 BIT(4) /*!< pin 4 set bit */ +#define GPIO_BOP_BOP5 BIT(5) /*!< pin 5 set bit */ +#define GPIO_BOP_BOP6 BIT(6) /*!< pin 6 set bit */ +#define GPIO_BOP_BOP7 BIT(7) /*!< pin 7 set bit */ +#define GPIO_BOP_BOP8 BIT(8) /*!< pin 8 set bit */ +#define GPIO_BOP_BOP9 BIT(9) /*!< pin 9 set bit */ +#define GPIO_BOP_BOP10 BIT(10) /*!< pin 10 set bit */ +#define GPIO_BOP_BOP11 BIT(11) /*!< pin 11 set bit */ +#define GPIO_BOP_BOP12 BIT(12) /*!< pin 12 set bit */ +#define GPIO_BOP_BOP13 BIT(13) /*!< pin 13 set bit */ +#define GPIO_BOP_BOP14 BIT(14) /*!< pin 14 set bit */ +#define GPIO_BOP_BOP15 BIT(15) /*!< pin 15 set bit */ +#define GPIO_BOP_CR0 BIT(16) /*!< pin 0 clear bit */ +#define GPIO_BOP_CR1 BIT(17) /*!< pin 1 clear bit */ +#define GPIO_BOP_CR2 BIT(18) /*!< pin 2 clear bit */ +#define GPIO_BOP_CR3 BIT(19) /*!< pin 3 clear bit */ +#define GPIO_BOP_CR4 BIT(20) /*!< pin 4 clear bit */ +#define GPIO_BOP_CR5 BIT(21) /*!< pin 5 clear bit */ +#define GPIO_BOP_CR6 BIT(22) /*!< pin 6 clear bit */ +#define GPIO_BOP_CR7 BIT(23) /*!< pin 7 clear bit */ +#define GPIO_BOP_CR8 BIT(24) /*!< pin 8 clear bit */ +#define GPIO_BOP_CR9 BIT(25) /*!< pin 9 clear bit */ +#define GPIO_BOP_CR10 BIT(26) /*!< pin 10 clear bit */ +#define GPIO_BOP_CR11 BIT(27) /*!< pin 11 clear bit */ +#define GPIO_BOP_CR12 BIT(28) /*!< pin 12 clear bit */ +#define GPIO_BOP_CR13 BIT(29) /*!< pin 13 clear bit */ +#define GPIO_BOP_CR14 BIT(30) /*!< pin 14 clear bit */ +#define GPIO_BOP_CR15 BIT(31) /*!< pin 15 clear bit */ + +/* GPIO_BC */ +#define GPIO_BC_CR0 BIT(0) /*!< pin 0 clear bit */ +#define GPIO_BC_CR1 BIT(1) /*!< pin 1 clear bit */ +#define GPIO_BC_CR2 BIT(2) /*!< pin 2 clear bit */ +#define GPIO_BC_CR3 BIT(3) /*!< pin 3 clear bit */ +#define GPIO_BC_CR4 BIT(4) /*!< pin 4 clear bit */ +#define GPIO_BC_CR5 BIT(5) /*!< pin 5 clear bit */ +#define GPIO_BC_CR6 BIT(6) /*!< pin 6 clear bit */ +#define GPIO_BC_CR7 BIT(7) /*!< pin 7 clear bit */ +#define GPIO_BC_CR8 BIT(8) /*!< pin 8 clear bit */ +#define GPIO_BC_CR9 BIT(9) /*!< pin 9 clear bit */ +#define GPIO_BC_CR10 BIT(10) /*!< pin 10 clear bit */ +#define GPIO_BC_CR11 BIT(11) /*!< pin 11 clear bit */ +#define GPIO_BC_CR12 BIT(12) /*!< pin 12 clear bit */ +#define GPIO_BC_CR13 BIT(13) /*!< pin 13 clear bit */ +#define GPIO_BC_CR14 BIT(14) /*!< pin 14 clear bit */ +#define GPIO_BC_CR15 BIT(15) /*!< pin 15 clear bit */ + +/* GPIO_LOCK */ +#define GPIO_LOCK_LK0 BIT(0) /*!< pin 0 lock bit */ +#define GPIO_LOCK_LK1 BIT(1) /*!< pin 1 lock bit */ +#define GPIO_LOCK_LK2 BIT(2) /*!< pin 2 lock bit */ +#define GPIO_LOCK_LK3 BIT(3) /*!< pin 3 lock bit */ +#define GPIO_LOCK_LK4 BIT(4) /*!< pin 4 lock bit */ +#define GPIO_LOCK_LK5 BIT(5) /*!< pin 5 lock bit */ +#define GPIO_LOCK_LK6 BIT(6) /*!< pin 6 lock bit */ +#define GPIO_LOCK_LK7 BIT(7) /*!< pin 7 lock bit */ +#define GPIO_LOCK_LK8 BIT(8) /*!< pin 8 lock bit */ +#define GPIO_LOCK_LK9 BIT(9) /*!< pin 9 lock bit */ +#define GPIO_LOCK_LK10 BIT(10) /*!< pin 10 lock bit */ +#define GPIO_LOCK_LK11 BIT(11) /*!< pin 11 lock bit */ +#define GPIO_LOCK_LK12 BIT(12) /*!< pin 12 lock bit */ +#define GPIO_LOCK_LK13 BIT(13) /*!< pin 13 lock bit */ +#define GPIO_LOCK_LK14 BIT(14) /*!< pin 14 lock bit */ +#define GPIO_LOCK_LK15 BIT(15) /*!< pin 15 lock bit */ +#define GPIO_LOCK_LKK BIT(16) /*!< pin sequence lock key */ + +/* AFIO_EC */ +#define AFIO_EC_PIN BITS(0,3) /*!< event output pin selection */ +#define AFIO_EC_PORT BITS(4,6) /*!< event output port selection */ +#define AFIO_EC_EOE BIT(7) /*!< event output enable */ + +/* AFIO_PCF0 */ +#ifdef GD32F10X_CL +/* memory map and bit definitions for GD32F10X_CL devices */ +#define AFIO_PCF0_SPI0_REMAP BIT(0) /*!< SPI0 remapping */ +#define AFIO_PCF0_I2C0_REMAP BIT(1) /*!< I2C0 remapping */ +#define AFIO_PCF0_USART0_REMAP BIT(2) /*!< USART0 remapping */ +#define AFIO_PCF0_USART1_REMAP BIT(3) /*!< USART1 remapping */ +#define AFIO_PCF0_USART2_REMAP BITS(4,5) /*!< USART2 remapping */ +#define AFIO_PCF0_TIMER0_REMAP BITS(6,7) /*!< TIMER0 remapping */ +#define AFIO_PCF0_TIMER1_REMAP BITS(8,9) /*!< TIMER1 remapping */ +#define AFIO_PCF0_TIMER2_REMAP BITS(10,11) /*!< TIMER2 remapping */ +#define AFIO_PCF0_TIMER3_REMAP BIT(12) /*!< TIMER3 remapping */ +#define AFIO_PCF0_CAN0_REMAP BITS(13,14) /*!< CAN0 remapping */ +#define AFIO_PCF0_PD01_REMAP BIT(15) /*!< port D0/port D1 mapping on OSC_IN/OSC_OUT */ +#define AFIO_PCF0_TIMER4CH3_IREMAP BIT(16) /*!< TIMER3 channel3 internal remapping */ +#define AFIO_PCF0_ENET_REMAP BIT(21) /*!< ethernet MAC I/O remapping */ +#define AFIO_PCF0_CAN1_REMAP BIT(22) /*!< CAN1 remapping */ +#define AFIO_PCF0_ENET_PHY_SEL BIT(23) /*!< ethernet MII or RMII PHY selection */ +#define AFIO_PCF0_SWJ_CFG BITS(24,26) /*!< serial wire JTAG configuration */ +#define AFIO_PCF0_SPI2_REMAP BIT(28) /*!< SPI2/I2S2 remapping */ +#define AFIO_PCF0_TIMER1ITI1_REMAP BIT(29) /*!< TIMER1 internal trigger 1 remapping */ +#define AFIO_PCF0_PTP_PPS_REMAP BIT(30) /*!< ethernet PTP PPS remapping */ + +#else +/* memory map and bit definitions for GD32F10X_MD, GD32F10X_HD devices and GD32F10X_XD devices */ +#define AFIO_PCF0_SPI0_REMAP BIT(0) /*!< SPI0 remapping */ +#define AFIO_PCF0_I2C0_REMAP BIT(1) /*!< I2C0 remapping */ +#define AFIO_PCF0_USART0_REMAP BIT(2) /*!< USART0 remapping */ +#define AFIO_PCF0_USART1_REMAP BIT(3) /*!< USART1 remapping */ +#define AFIO_PCF0_USART2_REMAP BITS(4,5) /*!< USART2 remapping */ +#define AFIO_PCF0_TIMER0_REMAP BITS(6,7) /*!< TIMER0 remapping */ +#define AFIO_PCF0_TIMER1_REMAP BITS(8,9) /*!< TIMER1 remapping */ +#define AFIO_PCF0_TIMER2_REMAP BITS(10,11) /*!< TIMER2 remapping */ +#define AFIO_PCF0_TIMER3_REMAP BIT(12) /*!< TIMER3 remapping */ +#define AFIO_PCF0_CAN_REMAP BITS(13,14) /*!< CAN remapping */ +#define AFIO_PCF0_PD01_REMAP BIT(15) /*!< port D0/port D1 mapping on OSC_IN/OSC_OUT */ +#define AFIO_PCF0_TIMER4CH3_REMAP BIT(16) /*!< TIMER4 channel3 internal remapping */ +#define AFIO_PCF0_ADC0_ETRGINS_REMAP BIT(17) /*!< ADC 0 external trigger inserted conversion remapping */ +#define AFIO_PCF0_ADC0_ETRGREG_REMAP BIT(18) /*!< ADC 0 external trigger regular conversion remapping */ +#define AFIO_PCF0_ADC1_ETRGINS_REMAP BIT(19) /*!< ADC 1 external trigger inserted conversion remapping */ +#define AFIO_PCF0_ADC1_ETRGREG_REMAP BIT(20) /*!< ADC 1 external trigger regular conversion remapping */ +#define AFIO_PCF0_SWJ_CFG BITS(24,26) /*!< serial wire JTAG configuration */ +#endif /* GD32F10X_CL */ + +/* AFIO_EXTISS0 */ +#define AFIO_EXTI0_SS BITS(0,3) /*!< EXTI 0 sources selection */ +#define AFIO_EXTI1_SS BITS(4,7) /*!< EXTI 1 sources selection */ +#define AFIO_EXTI2_SS BITS(8,11) /*!< EXTI 2 sources selection */ +#define AFIO_EXTI3_SS BITS(12,15) /*!< EXTI 3 sources selection */ + +/* AFIO_EXTISS1 */ +#define AFIO_EXTI4_SS BITS(0,3) /*!< EXTI 4 sources selection */ +#define AFIO_EXTI5_SS BITS(4,7) /*!< EXTI 5 sources selection */ +#define AFIO_EXTI6_SS BITS(8,11) /*!< EXTI 6 sources selection */ +#define AFIO_EXTI7_SS BITS(12,15) /*!< EXTI 7 sources selection */ + +/* AFIO_EXTISS2 */ +#define AFIO_EXTI8_SS BITS(0,3) /*!< EXTI 8 sources selection */ +#define AFIO_EXTI9_SS BITS(4,7) /*!< EXTI 9 sources selection */ +#define AFIO_EXTI10_SS BITS(8,11) /*!< EXTI 10 sources selection */ +#define AFIO_EXTI11_SS BITS(12,15) /*!< EXTI 11 sources selection */ + +/* AFIO_EXTISS3 */ +#define AFIO_EXTI12_SS BITS(0,3) /*!< EXTI 12 sources selection */ +#define AFIO_EXTI13_SS BITS(4,7) /*!< EXTI 13 sources selection */ +#define AFIO_EXTI14_SS BITS(8,11) /*!< EXTI 14 sources selection */ +#define AFIO_EXTI15_SS BITS(12,15) /*!< EXTI 15 sources selection */ + +/* AFIO_PCF1 */ +#define AFIO_PCF1_TIMER8_REMAP BIT(5) /*!< TIMER8 remapping */ +#define AFIO_PCF1_TIMER9_REMAP BIT(6) /*!< TIMER9 remapping */ +#define AFIO_PCF1_TIMER10_REMAP BIT(7) /*!< TIMER10 remapping */ +#define AFIO_PCF1_TIMER12_REMAP BIT(8) /*!< TIMER12 remapping */ +#define AFIO_PCF1_TIMER13_REMAP BIT(9) /*!< TIMER13 remapping */ +#define AFIO_PCF1_EXMC_NADV BIT(10) /*!< EXMC_NADV connect/disconnect */ + +/* constants definitions */ +typedef FlagStatus bit_status; + +/* GPIO mode values set */ +#define GPIO_MODE_SET(n, mode) ((uint32_t)((uint32_t)(mode) << (4U * (n)))) +#define GPIO_MODE_MASK(n) (0xFU << (4U * (n))) + +/* GPIO mode definitions */ +#define GPIO_MODE_AIN ((uint8_t)0x00U) /*!< analog input mode */ +#define GPIO_MODE_IN_FLOATING ((uint8_t)0x04U) /*!< floating input mode */ +#define GPIO_MODE_IPD ((uint8_t)0x28U) /*!< pull-down input mode */ +#define GPIO_MODE_IPU ((uint8_t)0x48U) /*!< pull-up input mode */ +#define GPIO_MODE_OUT_OD ((uint8_t)0x14U) /*!< GPIO output with open-drain */ +#define GPIO_MODE_OUT_PP ((uint8_t)0x10U) /*!< GPIO output with push-pull */ +#define GPIO_MODE_AF_OD ((uint8_t)0x1CU) /*!< AFIO output with open-drain */ +#define GPIO_MODE_AF_PP ((uint8_t)0x18U) /*!< AFIO output with push-pull */ + +/* GPIO output max speed value */ +#define GPIO_OSPEED_10MHZ ((uint8_t)0x01U) /*!< output max speed 10MHz */ +#define GPIO_OSPEED_2MHZ ((uint8_t)0x02U) /*!< output max speed 2MHz */ +#define GPIO_OSPEED_50MHZ ((uint8_t)0x03U) /*!< output max speed 50MHz */ + +/* GPIO event output port definitions */ +#define GPIO_EVENT_PORT_GPIOA ((uint8_t)0x00U) /*!< event output port A */ +#define GPIO_EVENT_PORT_GPIOB ((uint8_t)0x01U) /*!< event output port B */ +#define GPIO_EVENT_PORT_GPIOC ((uint8_t)0x02U) /*!< event output port C */ +#define GPIO_EVENT_PORT_GPIOD ((uint8_t)0x03U) /*!< event output port D */ +#define GPIO_EVENT_PORT_GPIOE ((uint8_t)0x04U) /*!< event output port E */ + +/* GPIO output port source definitions */ +#define GPIO_PORT_SOURCE_GPIOA ((uint8_t)0x00U) /*!< output port source A */ +#define GPIO_PORT_SOURCE_GPIOB ((uint8_t)0x01U) /*!< output port source B */ +#define GPIO_PORT_SOURCE_GPIOC ((uint8_t)0x02U) /*!< output port source C */ +#define GPIO_PORT_SOURCE_GPIOD ((uint8_t)0x03U) /*!< output port source D */ +#define GPIO_PORT_SOURCE_GPIOE ((uint8_t)0x04U) /*!< output port source E */ +#define GPIO_PORT_SOURCE_GPIOF ((uint8_t)0x05U) /*!< output port source F */ +#define GPIO_PORT_SOURCE_GPIOG ((uint8_t)0x06U) /*!< output port source G */ + +/* GPIO event output pin definitions */ +#define GPIO_EVENT_PIN_0 ((uint8_t)0x00U) /*!< GPIO event pin 0 */ +#define GPIO_EVENT_PIN_1 ((uint8_t)0x01U) /*!< GPIO event pin 1 */ +#define GPIO_EVENT_PIN_2 ((uint8_t)0x02U) /*!< GPIO event pin 2 */ +#define GPIO_EVENT_PIN_3 ((uint8_t)0x03U) /*!< GPIO event pin 3 */ +#define GPIO_EVENT_PIN_4 ((uint8_t)0x04U) /*!< GPIO event pin 4 */ +#define GPIO_EVENT_PIN_5 ((uint8_t)0x05U) /*!< GPIO event pin 5 */ +#define GPIO_EVENT_PIN_6 ((uint8_t)0x06U) /*!< GPIO event pin 6 */ +#define GPIO_EVENT_PIN_7 ((uint8_t)0x07U) /*!< GPIO event pin 7 */ +#define GPIO_EVENT_PIN_8 ((uint8_t)0x08U) /*!< GPIO event pin 8 */ +#define GPIO_EVENT_PIN_9 ((uint8_t)0x09U) /*!< GPIO event pin 9 */ +#define GPIO_EVENT_PIN_10 ((uint8_t)0x0AU) /*!< GPIO event pin 10 */ +#define GPIO_EVENT_PIN_11 ((uint8_t)0x0BU) /*!< GPIO event pin 11 */ +#define GPIO_EVENT_PIN_12 ((uint8_t)0x0CU) /*!< GPIO event pin 12 */ +#define GPIO_EVENT_PIN_13 ((uint8_t)0x0DU) /*!< GPIO event pin 13 */ +#define GPIO_EVENT_PIN_14 ((uint8_t)0x0EU) /*!< GPIO event pin 14 */ +#define GPIO_EVENT_PIN_15 ((uint8_t)0x0FU) /*!< GPIO event pin 15 */ + +/* GPIO output pin source definitions */ +#define GPIO_PIN_SOURCE_0 ((uint8_t)0x00U) /*!< GPIO pin source 0 */ +#define GPIO_PIN_SOURCE_1 ((uint8_t)0x01U) /*!< GPIO pin source 1 */ +#define GPIO_PIN_SOURCE_2 ((uint8_t)0x02U) /*!< GPIO pin source 2 */ +#define GPIO_PIN_SOURCE_3 ((uint8_t)0x03U) /*!< GPIO pin source 3 */ +#define GPIO_PIN_SOURCE_4 ((uint8_t)0x04U) /*!< GPIO pin source 4 */ +#define GPIO_PIN_SOURCE_5 ((uint8_t)0x05U) /*!< GPIO pin source 5 */ +#define GPIO_PIN_SOURCE_6 ((uint8_t)0x06U) /*!< GPIO pin source 6 */ +#define GPIO_PIN_SOURCE_7 ((uint8_t)0x07U) /*!< GPIO pin source 7 */ +#define GPIO_PIN_SOURCE_8 ((uint8_t)0x08U) /*!< GPIO pin source 8 */ +#define GPIO_PIN_SOURCE_9 ((uint8_t)0x09U) /*!< GPIO pin source 9 */ +#define GPIO_PIN_SOURCE_10 ((uint8_t)0x0AU) /*!< GPIO pin source 10 */ +#define GPIO_PIN_SOURCE_11 ((uint8_t)0x0BU) /*!< GPIO pin source 11 */ +#define GPIO_PIN_SOURCE_12 ((uint8_t)0x0CU) /*!< GPIO pin source 12 */ +#define GPIO_PIN_SOURCE_13 ((uint8_t)0x0DU) /*!< GPIO pin source 13 */ +#define GPIO_PIN_SOURCE_14 ((uint8_t)0x0EU) /*!< GPIO pin source 14 */ +#define GPIO_PIN_SOURCE_15 ((uint8_t)0x0FU) /*!< GPIO pin source 15 */ + +/* GPIO pin definitions */ +#define GPIO_PIN_0 BIT(0) /*!< GPIO pin 0 */ +#define GPIO_PIN_1 BIT(1) /*!< GPIO pin 1 */ +#define GPIO_PIN_2 BIT(2) /*!< GPIO pin 2 */ +#define GPIO_PIN_3 BIT(3) /*!< GPIO pin 3 */ +#define GPIO_PIN_4 BIT(4) /*!< GPIO pin 4 */ +#define GPIO_PIN_5 BIT(5) /*!< GPIO pin 5 */ +#define GPIO_PIN_6 BIT(6) /*!< GPIO pin 6 */ +#define GPIO_PIN_7 BIT(7) /*!< GPIO pin 7 */ +#define GPIO_PIN_8 BIT(8) /*!< GPIO pin 8 */ +#define GPIO_PIN_9 BIT(9) /*!< GPIO pin 9 */ +#define GPIO_PIN_10 BIT(10) /*!< GPIO pin 10 */ +#define GPIO_PIN_11 BIT(11) /*!< GPIO pin 11 */ +#define GPIO_PIN_12 BIT(12) /*!< GPIO pin 12 */ +#define GPIO_PIN_13 BIT(13) /*!< GPIO pin 13 */ +#define GPIO_PIN_14 BIT(14) /*!< GPIO pin 14 */ +#define GPIO_PIN_15 BIT(15) /*!< GPIO pin 15 */ +#define GPIO_PIN_ALL BITS(0,15) /*!< GPIO pin all */ + +/* GPIO remap definitions */ +#define GPIO_SPI0_REMAP ((uint32_t)0x00000001U) /*!< SPI0 remapping */ +#define GPIO_I2C0_REMAP ((uint32_t)0x00000002U) /*!< I2C0 remapping */ +#define GPIO_USART0_REMAP ((uint32_t)0x00000004U) /*!< USART0 remapping */ +#define GPIO_USART1_REMAP ((uint32_t)0x00000008U) /*!< USART1 remapping */ +#define GPIO_USART2_PARTIAL_REMAP ((uint32_t)0x00140010U) /*!< USART2 partial remapping */ +#define GPIO_USART2_FULL_REMAP ((uint32_t)0x00140030U) /*!< USART2 full remapping */ +#define GPIO_TIMER0_PARTIAL_REMAP ((uint32_t)0x00160040U) /*!< TIMER0 partial remapping */ +#define GPIO_TIMER0_FULL_REMAP ((uint32_t)0x001600C0U) /*!< TIMER0 full remapping */ +#define GPIO_TIMER1_PARTIAL_REMAP0 ((uint32_t)0x00180100U) /*!< TIMER1 partial remapping */ +#define GPIO_TIMER1_PARTIAL_REMAP1 ((uint32_t)0x00180200U) /*!< TIMER1 partial remapping */ +#define GPIO_TIMER1_FULL_REMAP ((uint32_t)0x00180300U) /*!< TIMER1 full remapping */ +#define GPIO_TIMER2_PARTIAL_REMAP ((uint32_t)0x001A0800U) /*!< TIMER2 partial remapping */ +#define GPIO_TIMER2_FULL_REMAP ((uint32_t)0x001A0C00U) /*!< TIMER2 full remapping */ +#define GPIO_TIMER3_REMAP ((uint32_t)0x00001000U) /*!< TIMER3 remapping */ +#define GPIO_PD01_REMAP ((uint32_t)0x00008000U) /*!< PD01 remapping */ +#if (defined(GD32F10X_MD) || defined(GD32F10X_HD) || defined(GD32F10X_XD)) +#define GPIO_CAN_PARTIAL_REMAP ((uint32_t)0x001D4000U) /*!< CAN partial remapping(only for GD32F10X_MD devices, GD32F10X_HD devices and GD32F10X_XD devices) */ +#define GPIO_CAN_FULL_REMAP ((uint32_t)0x001D6000U) /*!< CAN full remapping(only for GD32F10X_MD devices, GD32F10X_HD devices and GD32F10X_XD devices) */ +#endif /* GD32F10X_MD||GD32F10X_HD||GD32F10X_XD */ +#if (defined(GD32F10X_CL) || defined(GD32F10X_HD) || defined(GD32F10X_XD)) +#define GPIO_SPI2_REMAP ((uint32_t)0x00201100U) /*!< SPI2 remapping(only for GD32F10X_CL devices) */ +#endif /* GD32F10X_CL||GD32F10X_HD */ +#if (defined(GD32F10X_CL) || defined(GD32F10X_HD)) +#define GPIO_TIMER4CH3_IREMAP ((uint32_t)0x00200001U) /*!< TIMER4 channel3 internal remapping(only for GD32F10X_CL devices and GD32F10X_HD devices) */ +#endif /* GD32F10X_CL||GD32F10X_HD */ +#if (defined(GD32F10X_MD) || defined(GD32F10X_HD) || defined(GD32F10X_XD)) +#define GPIO_ADC0_ETRGINS_REMAP ((uint32_t)0x00200002U) /*!< ADC0 external trigger inserted conversion remapping(only for GD32F10X_MD devices, GD32F10X_HD devices and GD32F10X_XD devices) */ +#define GPIO_ADC0_ETRGREG_REMAP ((uint32_t)0x00200004U) /*!< ADC0 external trigger regular conversion remapping(only for GD32F10X_MD devices, GD32F10X_HD devices and GD32F10X_XD devices) */ +#define GPIO_ADC1_ETRGINS_REMAP ((uint32_t)0x00200008U) /*!< ADC1 external trigger inserted conversion remapping(only for GD32F10X_MD devices, GD32F10X_HD devices and GD32F10X_XD devices) */ +#define GPIO_ADC1_ETRGREG_REMAP ((uint32_t)0x00200010U) /*!< ADC1 external trigger regular conversion remapping(only for GD32F10X_MD devices, GD32F10X_HD devices and GD32F10X_XD devices) */ +#endif /* GD32F10X_MD||GD32F10X_HD||GD32F10X_XD */ +#define GPIO_SWJ_NONJTRST_REMAP ((uint32_t)0x00300100U) /*!< full SWJ(JTAG-DP + SW-DP),but without NJTRST */ +#define GPIO_SWJ_SWDPENABLE_REMAP ((uint32_t)0x00300200U) /*!< JTAG-DP disabled and SW-DP enabled */ +#define GPIO_SWJ_DISABLE_REMAP ((uint32_t)0x00300400U) /*!< JTAG-DP disabled and SW-DP disabled */ +#ifdef GD32F10X_CL +#define GPIO_CAN0_PARTIAL_REMAP ((uint32_t)0x001D4000U) /*!< CAN0 partial remapping(only for GD32F10X_CL devices) */ +#define GPIO_CAN0_FULL_REMAP ((uint32_t)0x001D6000U) /*!< CAN0 full remapping(only for GD32F10X_CL devices) */ +#define GPIO_ENET_REMAP ((uint32_t)0x00200020U) /*!< ENET remapping(only for GD32F10X_CL devices) */ +#define GPIO_CAN1_REMAP ((uint32_t)0x00200040U) /*!< CAN1 remapping(only for GD32F10X_CL devices) */ +#define GPIO_TIMER1ITI1_REMAP ((uint32_t)0x00202000U) /*!< TIMER1 internal trigger 1 remapping(only for GD32F10X_CL devices) */ +#define GPIO_PTP_PPS_REMAP ((uint32_t)0x00204000U) /*!< ethernet PTP PPS remapping(only for GD32F10X_CL devices) */ +#endif /* GD32F10X_CL */ +#ifdef GD32F10X_XD +#define GPIO_TIMER8_REMAP ((uint32_t)0x80000020U) /*!< TIMER8 remapping */ +#define GPIO_TIMER9_REMAP ((uint32_t)0x80000040U) /*!< TIMER9 remapping */ +#define GPIO_TIMER10_REMAP ((uint32_t)0x80000080U) /*!< TIMER10 remapping */ +#define GPIO_TIMER12_REMAP ((uint32_t)0x80000100U) /*!< TIMER12 remapping */ +#define GPIO_TIMER13_REMAP ((uint32_t)0x80000200U) /*!< TIMER13 remapping */ +#define GPIO_EXMC_NADV_REMAP ((uint32_t)0x80000400U) /*!< EXMC_NADV connect/disconnect */ +#endif /* GD32F10X_XD */ + +#ifdef GD32F10X_CL +/* ethernet MII or RMII PHY selection */ +#define GPIO_ENET_PHY_MII ((uint32_t)0x00000000U) /*!< configure ethernet MAC for connection with an MII PHY */ +#define GPIO_ENET_PHY_RMII AFIO_PCF0_ENET_PHY_SEL /*!< configure ethernet MAC for connection with an RMII PHY */ +#endif /* GD32F10X_CL */ + +/* function declarations */ +/* reset GPIO port */ +void gpio_deinit(uint32_t gpio_periph); +/* reset alternate function I/O(AFIO) */ +void gpio_afio_deinit(void); +/* GPIO parameter initialization */ +void gpio_init(uint32_t gpio_periph,uint32_t mode,uint32_t speed,uint32_t pin); + +/* set GPIO pin bit */ +void gpio_bit_set(uint32_t gpio_periph, uint32_t pin); +/* reset GPIO pin bit */ +void gpio_bit_reset(uint32_t gpio_periph, uint32_t pin); +/* write data to the specified GPIO pin */ +void gpio_bit_write(uint32_t gpio_periph, uint32_t pin, bit_status bit_value); +/* write data to the specified GPIO port */ +void gpio_port_write(uint32_t gpio_periph, uint16_t data); + +/* get GPIO pin input status */ +FlagStatus gpio_input_bit_get(uint32_t gpio_periph, uint32_t pin); +/* get GPIO port input status */ +uint16_t gpio_input_port_get(uint32_t gpio_periph); +/* get GPIO pin output status */ +FlagStatus gpio_output_bit_get(uint32_t gpio_periph, uint32_t pin); +/* get GPIO port output status */ +uint16_t gpio_output_port_get(uint32_t gpio_periph); + +/* configure GPIO pin remap */ +void gpio_pin_remap_config(uint32_t remap, ControlStatus newvalue); + +/* select GPIO pin exti sources */ +void gpio_exti_source_select(uint8_t output_port, uint8_t output_pin); +/* configure GPIO pin event output */ +void gpio_event_output_config(uint8_t output_port, uint8_t output_pin); +/* enable GPIO pin event output */ +void gpio_event_output_enable(void); +/* disable GPIO pin event output */ +void gpio_event_output_disable(void); + +/* lock GPIO pin bit */ +void gpio_pin_lock(uint32_t gpio_periph, uint32_t pin); + +#ifdef GD32F10X_CL +/* select ethernet MII or RMII PHY */ +void gpio_ethernet_phy_select(uint32_t gpio_enetsel); +#endif /* GD32F10X_CL */ + + +#endif /* GD32F10x_GPIO_H */ diff --git a/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_standard_peripheral/Include/gd32f10x_i2c.h b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_standard_peripheral/Include/gd32f10x_i2c.h new file mode 100644 index 0000000000..44781cdd6e --- /dev/null +++ b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_standard_peripheral/Include/gd32f10x_i2c.h @@ -0,0 +1,347 @@ +/*! + \file gd32f10x_i2c.h + \brief definitions for the I2C + + \version 2014-12-26, V1.0.0, firmware for GD32F10x + \version 2017-06-20, V2.0.0, firmware for GD32F10x + \version 2018-07-31, V2.1.0, firmware for GD32F10x + \version 2019-04-16, V2.1.1, firmware for GD32F10x + \version 2020-09-30, V2.2.0, firmware for GD32F10x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef GD32F10X_I2C_H +#define GD32F10X_I2C_H + +#include "gd32f10x.h" + +/* I2Cx(x=0,1) definitions */ +#define I2C0 I2C_BASE /*!< I2C0 base address */ +#define I2C1 (I2C_BASE + 0x00000400U) /*!< I2C1 base address */ + +/* registers definitions */ +#define I2C_CTL0(i2cx) REG32((i2cx) + 0x00U) /*!< I2C control register 0 */ +#define I2C_CTL1(i2cx) REG32((i2cx) + 0x04U) /*!< I2C control register 1 */ +#define I2C_SADDR0(i2cx) REG32((i2cx) + 0x08U) /*!< I2C slave address register 0*/ +#define I2C_SADDR1(i2cx) REG32((i2cx) + 0x0CU) /*!< I2C slave address register */ +#define I2C_DATA(i2cx) REG32((i2cx) + 0x10U) /*!< I2C transfer buffer register */ +#define I2C_STAT0(i2cx) REG32((i2cx) + 0x14U) /*!< I2C transfer status register 0 */ +#define I2C_STAT1(i2cx) REG32((i2cx) + 0x18U) /*!< I2C transfer status register */ +#define I2C_CKCFG(i2cx) REG32((i2cx) + 0x1CU) /*!< I2C clock configure register */ +#define I2C_RT(i2cx) REG32((i2cx) + 0x20U) /*!< I2C rise time register */ + +/* bits definitions */ +/* I2Cx_CTL0 */ +#define I2C_CTL0_I2CEN BIT(0) /*!< peripheral enable */ +#define I2C_CTL0_SMBEN BIT(1) /*!< SMBus mode */ +#define I2C_CTL0_SMBSEL BIT(3) /*!< SMBus type */ +#define I2C_CTL0_ARPEN BIT(4) /*!< ARP enable */ +#define I2C_CTL0_PECEN BIT(5) /*!< PEC enable */ +#define I2C_CTL0_GCEN BIT(6) /*!< general call enable */ +#define I2C_CTL0_SS BIT(7) /*!< clock stretching disable (slave mode) */ +#define I2C_CTL0_START BIT(8) /*!< start generation */ +#define I2C_CTL0_STOP BIT(9) /*!< stop generation */ +#define I2C_CTL0_ACKEN BIT(10) /*!< acknowledge enable */ +#define I2C_CTL0_POAP BIT(11) /*!< acknowledge/PEC position (for data reception) */ +#define I2C_CTL0_PECTRANS BIT(12) /*!< packet error checking */ +#define I2C_CTL0_SALT BIT(13) /*!< SMBus alert */ +#define I2C_CTL0_SRESET BIT(15) /*!< software reset */ + +/* I2Cx_CTL1 */ +#define I2C_CTL1_I2CCLK BITS(0,5) /*!< I2CCLK[5:0] bits (peripheral clock frequency) */ +#define I2C_CTL1_ERRIE BIT(8) /*!< error interrupt enable */ +#define I2C_CTL1_EVIE BIT(9) /*!< event interrupt enable */ +#define I2C_CTL1_BUFIE BIT(10) /*!< buffer interrupt enable */ +#define I2C_CTL1_DMAON BIT(11) /*!< DMA requests enable */ +#define I2C_CTL1_DMALST BIT(12) /*!< DMA last transfer */ + +/* I2Cx_SADDR0 */ +#define I2C_SADDR0_ADDRESS0 BIT(0) /*!< bit 0 of a 10-bit address */ +#define I2C_SADDR0_ADDRESS BITS(1,7) /*!< 7-bit address or bits 7:1 of a 10-bit address */ +#define I2C_SADDR0_ADDRESS_H BITS(8,9) /*!< highest two bits of a 10-bit address */ +#define I2C_SADDR0_ADDFORMAT BIT(15) /*!< address mode for the I2C slave */ + +/* I2Cx_SADDR1 */ +#define I2C_SADDR1_DUADEN BIT(0) /*!< aual-address mode switch */ +#define I2C_SADDR1_ADDRESS2 BITS(1,7) /*!< second I2C address for the slave in dual-address mode */ + +/* I2Cx_DATA */ +#define I2C_DATA_TRB BITS(0,7) /*!< 8-bit data register */ + +/* I2Cx_STAT0 */ +#define I2C_STAT0_SBSEND BIT(0) /*!< start bit (master mode) */ +#define I2C_STAT0_ADDSEND BIT(1) /*!< address sent (master mode)/matched (slave mode) */ +#define I2C_STAT0_BTC BIT(2) /*!< byte transfer finished */ +#define I2C_STAT0_ADD10SEND BIT(3) /*!< 10-bit header sent (master mode) */ +#define I2C_STAT0_STPDET BIT(4) /*!< stop detection (slave mode) */ +#define I2C_STAT0_RBNE BIT(6) /*!< data register not empty (receivers) */ +#define I2C_STAT0_TBE BIT(7) /*!< data register empty (transmitters) */ +#define I2C_STAT0_BERR BIT(8) /*!< bus error */ +#define I2C_STAT0_LOSTARB BIT(9) /*!< arbitration lost (master mode) */ +#define I2C_STAT0_AERR BIT(10) /*!< acknowledge failure */ +#define I2C_STAT0_OUERR BIT(11) /*!< overrun/underrun */ +#define I2C_STAT0_PECERR BIT(12) /*!< PEC error in reception */ +#define I2C_STAT0_SMBTO BIT(14) /*!< timeout signal in SMBus mode */ +#define I2C_STAT0_SMBALT BIT(15) /*!< SMBus alert status */ + +/* I2Cx_STAT1 */ +#define I2C_STAT1_MASTER BIT(0) /*!< master/slave */ +#define I2C_STAT1_I2CBSY BIT(1) /*!< bus busy */ +#define I2C_STAT1_TR BIT(2) /*!< transmitter/receiver */ +#define I2C_STAT1_RXGC BIT(4) /*!< general call address (slave mode) */ +#define I2C_STAT1_DEFSMB BIT(5) /*!< SMBus device default address (slave mode) */ +#define I2C_STAT1_HSTSMB BIT(6) /*!< SMBus host header (slave mode) */ +#define I2C_STAT1_DUMODF BIT(7) /*!< dual flag (slave mode) */ +#define I2C_STAT1_PECV BITS(8,15) /*!< packet error checking value */ + +/* I2Cx_CKCFG */ +#define I2C_CKCFG_CLKC BITS(0,11) /*!< clock control register in fast/standard mode (master mode) */ +#define I2C_CKCFG_DTCY BIT(14) /*!< fast mode duty cycle */ +#define I2C_CKCFG_FAST BIT(15) /*!< I2C speed selection in master mode */ + +/* I2Cx_RT */ +#define I2C_RT_RISETIME BITS(0,5) /*!< maximum rise time in fast/standard mode (Master mode) */ + +/* constants definitions */ +/* define the I2C bit position and its register index offset */ +#define I2C_REGIDX_BIT(regidx, bitpos) (((uint32_t)(regidx) << 6) | (uint32_t)(bitpos)) +#define I2C_REG_VAL(i2cx, offset) (REG32((i2cx) + (((uint32_t)(offset) & 0xFFFFU) >> 6))) +#define I2C_BIT_POS(val) ((uint32_t)(val) & 0x1FU) +#define I2C_REGIDX_BIT2(regidx, bitpos, regidx2, bitpos2) (((uint32_t)(regidx2) << 22) | (uint32_t)((bitpos2) << 16)\ + | (((uint32_t)(regidx) << 6) | (uint32_t)(bitpos))) +#define I2C_REG_VAL2(i2cx, offset) (REG32((i2cx) + ((uint32_t)(offset) >> 22))) +#define I2C_BIT_POS2(val) (((uint32_t)(val) & 0x1F0000U) >> 16) + +/* register offset */ +#define I2C_CTL1_REG_OFFSET 0x04U /*!< CTL1 register offset */ +#define I2C_STAT0_REG_OFFSET 0x14U /*!< STAT0 register offset */ +#define I2C_STAT1_REG_OFFSET 0x18U /*!< STAT1 register offset */ + +/* I2C flags */ +typedef enum +{ + /* flags in STAT0 register */ + I2C_FLAG_SBSEND = I2C_REGIDX_BIT(I2C_STAT0_REG_OFFSET, 0U), /*!< start condition sent out in master mode */ + I2C_FLAG_ADDSEND = I2C_REGIDX_BIT(I2C_STAT0_REG_OFFSET, 1U), /*!< address is sent in master mode or received and matches in slave mode */ + I2C_FLAG_BTC = I2C_REGIDX_BIT(I2C_STAT0_REG_OFFSET, 2U), /*!< byte transmission finishes */ + I2C_FLAG_ADD10SEND = I2C_REGIDX_BIT(I2C_STAT0_REG_OFFSET, 3U), /*!< header of 10-bit address is sent in master mode */ + I2C_FLAG_STPDET = I2C_REGIDX_BIT(I2C_STAT0_REG_OFFSET, 4U), /*!< stop condition detected in slave mode */ + I2C_FLAG_RBNE = I2C_REGIDX_BIT(I2C_STAT0_REG_OFFSET, 6U), /*!< I2C_DATA is not Empty during receiving */ + I2C_FLAG_TBE = I2C_REGIDX_BIT(I2C_STAT0_REG_OFFSET, 7U), /*!< I2C_DATA is empty during transmitting */ + I2C_FLAG_BERR = I2C_REGIDX_BIT(I2C_STAT0_REG_OFFSET, 8U), /*!< a bus error occurs indication a unexpected start or stop condition on I2C bus */ + I2C_FLAG_LOSTARB = I2C_REGIDX_BIT(I2C_STAT0_REG_OFFSET, 9U), /*!< arbitration lost in master mode */ + I2C_FLAG_AERR = I2C_REGIDX_BIT(I2C_STAT0_REG_OFFSET, 10U), /*!< acknowledge error */ + I2C_FLAG_OUERR = I2C_REGIDX_BIT(I2C_STAT0_REG_OFFSET, 11U), /*!< over-run or under-run situation occurs in slave mode */ + I2C_FLAG_PECERR = I2C_REGIDX_BIT(I2C_STAT0_REG_OFFSET, 12U), /*!< PEC error when receiving data */ + I2C_FLAG_SMBTO = I2C_REGIDX_BIT(I2C_STAT0_REG_OFFSET, 14U), /*!< timeout signal in SMBus mode */ + I2C_FLAG_SMBALT = I2C_REGIDX_BIT(I2C_STAT0_REG_OFFSET, 15U), /*!< SMBus alert status */ + /* flags in STAT1 register */ + I2C_FLAG_MASTER = I2C_REGIDX_BIT(I2C_STAT1_REG_OFFSET, 0U), /*!< a flag indicating whether I2C block is in master or slave mode */ + I2C_FLAG_I2CBSY = I2C_REGIDX_BIT(I2C_STAT1_REG_OFFSET, 1U), /*!< busy flag */ + I2C_FLAG_TRS = I2C_REGIDX_BIT(I2C_STAT1_REG_OFFSET, 2U), /*!< whether the I2C is a transmitter or a receiver */ + I2C_FLAG_RXGC = I2C_REGIDX_BIT(I2C_STAT1_REG_OFFSET, 4U), /*!< general call address (00h) received */ + I2C_FLAG_DEFSMB = I2C_REGIDX_BIT(I2C_STAT1_REG_OFFSET, 5U), /*!< default address of SMBus device */ + I2C_FLAG_HSTSMB = I2C_REGIDX_BIT(I2C_STAT1_REG_OFFSET, 6U), /*!< SMBus host header detected in slave mode */ + I2C_FLAG_DUMOD = I2C_REGIDX_BIT(I2C_STAT1_REG_OFFSET, 7U), /*!< dual flag in slave mode indicating which address is matched in dual-address mode */ +}i2c_flag_enum; + +/* I2C interrupt flags */ +typedef enum +{ + /* interrupt flags in CTL1 register */ + I2C_INT_FLAG_SBSEND = I2C_REGIDX_BIT2(I2C_CTL1_REG_OFFSET, 9U, I2C_STAT0_REG_OFFSET, 0U), /*!< start condition sent out in master mode interrupt flag */ + I2C_INT_FLAG_ADDSEND = I2C_REGIDX_BIT2(I2C_CTL1_REG_OFFSET, 9U, I2C_STAT0_REG_OFFSET, 1U), /*!< address is sent in master mode or received and matches in slave mode interrupt flag */ + I2C_INT_FLAG_BTC = I2C_REGIDX_BIT2(I2C_CTL1_REG_OFFSET, 9U, I2C_STAT0_REG_OFFSET, 2U), /*!< byte transmission finishes */ + I2C_INT_FLAG_ADD10SEND = I2C_REGIDX_BIT2(I2C_CTL1_REG_OFFSET, 9U, I2C_STAT0_REG_OFFSET, 3U), /*!< header of 10-bit address is sent in master mode interrupt flag */ + I2C_INT_FLAG_STPDET = I2C_REGIDX_BIT2(I2C_CTL1_REG_OFFSET, 9U, I2C_STAT0_REG_OFFSET, 4U), /*!< stop condition detected in slave mode interrupt flag */ + I2C_INT_FLAG_RBNE = I2C_REGIDX_BIT2(I2C_CTL1_REG_OFFSET, 9U, I2C_STAT0_REG_OFFSET, 6U), /*!< I2C_DATA is not Empty during receiving interrupt flag */ + I2C_INT_FLAG_TBE = I2C_REGIDX_BIT2(I2C_CTL1_REG_OFFSET, 9U, I2C_STAT0_REG_OFFSET, 7U), /*!< I2C_DATA is empty during transmitting interrupt flag */ + I2C_INT_FLAG_BERR = I2C_REGIDX_BIT2(I2C_CTL1_REG_OFFSET, 8U, I2C_STAT0_REG_OFFSET, 8U), /*!< a bus error occurs indication a unexpected start or stop condition on I2C bus interrupt flag */ + I2C_INT_FLAG_LOSTARB = I2C_REGIDX_BIT2(I2C_CTL1_REG_OFFSET, 8U, I2C_STAT0_REG_OFFSET, 9U), /*!< arbitration lost in master mode interrupt flag */ + I2C_INT_FLAG_AERR = I2C_REGIDX_BIT2(I2C_CTL1_REG_OFFSET, 8U, I2C_STAT0_REG_OFFSET, 10U), /*!< acknowledge error interrupt flag */ + I2C_INT_FLAG_OUERR = I2C_REGIDX_BIT2(I2C_CTL1_REG_OFFSET, 8U, I2C_STAT0_REG_OFFSET, 11U), /*!< over-run or under-run situation occurs in slave mode interrupt flag */ + I2C_INT_FLAG_PECERR = I2C_REGIDX_BIT2(I2C_CTL1_REG_OFFSET, 8U, I2C_STAT0_REG_OFFSET, 12U), /*!< PEC error when receiving data interrupt flag */ + I2C_INT_FLAG_SMBTO = I2C_REGIDX_BIT2(I2C_CTL1_REG_OFFSET, 8U, I2C_STAT0_REG_OFFSET, 14U), /*!< timeout signal in SMBus mode interrupt flag */ + I2C_INT_FLAG_SMBALT = I2C_REGIDX_BIT2(I2C_CTL1_REG_OFFSET, 8U, I2C_STAT0_REG_OFFSET, 15U), /*!< SMBus Alert status interrupt flag */ +}i2c_interrupt_flag_enum; + +/* I2C interrupt enable or disable */ +typedef enum +{ + /* interrupt in CTL1 register */ + I2C_INT_ERR = I2C_REGIDX_BIT(I2C_CTL1_REG_OFFSET, 8U), /*!< error interrupt enable */ + I2C_INT_EV = I2C_REGIDX_BIT(I2C_CTL1_REG_OFFSET, 9U), /*!< event interrupt enable */ + I2C_INT_BUF = I2C_REGIDX_BIT(I2C_CTL1_REG_OFFSET, 10U), /*!< buffer interrupt enable */ +}i2c_interrupt_enum; + +/* SMBus/I2C mode switch and SMBus type selection */ +#define I2C_I2CMODE_ENABLE ((uint32_t)0x00000000U) /*!< I2C mode */ +#define I2C_SMBUSMODE_ENABLE I2C_CTL0_SMBEN /*!< SMBus mode */ + +/* SMBus/I2C mode switch and SMBus type selection */ +#define I2C_SMBUS_DEVICE ((uint32_t)0x00000000U) /*!< SMBus mode device type */ +#define I2C_SMBUS_HOST I2C_CTL0_SMBSEL /*!< SMBus mode host type */ + +/* I2C transfer direction */ +#define I2C_RECEIVER ((uint32_t)0x00000001U) /*!< receiver */ +#define I2C_TRANSMITTER ((uint32_t)0xFFFFFFFEU) /*!< transmitter */ + +/* whether or not to send an ACK */ +#define I2C_ACK_DISABLE ((uint32_t)0x00000000U) /*!< ACK will be not sent */ +#define I2C_ACK_ENABLE ((uint32_t)0x00000001U) /*!< ACK will be sent */ + +/* I2C POAP position*/ +#define I2C_ACKPOS_NEXT ((uint32_t)0x00000000U) /*!< ACKEN bit decides whether or not to send ACK for the next byte */ +#define I2C_ACKPOS_CURRENT ((uint32_t)0x00000001U) /*!< ACKEN bit decides whether or not to send ACK or not for the current byte */ + +/* I2C dual-address mode switch */ +#define I2C_DUADEN_DISABLE ((uint32_t)0x00000000U) /*!< dual-address mode disabled */ +#define I2C_DUADEN_ENABLE ((uint32_t)0x00000001U) /*!< dual-address mode enabled */ + +/* whether or not to stretch SCL low */ +#define I2C_SCLSTRETCH_ENABLE ((uint32_t)0x00000000U) /*!< SCL stretching is enabled */ +#define I2C_SCLSTRETCH_DISABLE I2C_CTL0_SS /*!< SCL stretching is disabled */ + +/* whether or not to response to a general call */ +#define I2C_GCEN_ENABLE I2C_CTL0_GCEN /*!< slave will response to a general call */ +#define I2C_GCEN_DISABLE ((uint32_t)0x00000000U) /*!< slave will not response to a general call */ + +/* software reset I2C */ +#define I2C_SRESET_SET I2C_CTL0_SRESET /*!< I2C is under reset */ +#define I2C_SRESET_RESET ((uint32_t)0x00000000U) /*!< I2C is not under reset */ + +/* I2C DMA mode configure */ +/* DMA mode switch */ +#define I2C_DMA_ON I2C_CTL1_DMAON /*!< DMA mode enabled */ +#define I2C_DMA_OFF ((uint32_t)0x00000000U) /*!< DMA mode disabled */ + +/* flag indicating DMA last transfer */ +#define I2C_DMALST_ON I2C_CTL1_DMALST /*!< next DMA EOT is the last transfer */ +#define I2C_DMALST_OFF ((uint32_t)0x00000000U) /*!< next DMA EOT is not the last transfer */ + +/* I2C PEC configure */ +/* PEC enable */ +#define I2C_PEC_ENABLE I2C_CTL0_PECEN /*!< PEC calculation on */ +#define I2C_PEC_DISABLE ((uint32_t)0x00000000U) /*!< PEC calculation off */ + +/* PEC transfer */ +#define I2C_PECTRANS_ENABLE I2C_CTL0_PECTRANS /*!< transfer PEC */ +#define I2C_PECTRANS_DISABLE ((uint32_t)0x00000000U) /*!< not transfer PEC value */ + +/* I2C SMBus configure */ +/* issue or not alert through SMBA pin */ +#define I2C_SALTSEND_ENABLE I2C_CTL0_SALT /*!< issue alert through SMBA pin */ +#define I2C_SALTSEND_DISABLE ((uint32_t)0x00000000U) /*!< not issue alert through SMBA */ + +/* ARP protocol in SMBus switch */ +#define I2C_ARP_ENABLE I2C_CTL0_ARPEN /*!< ARP is enabled */ +#define I2C_ARP_DISABLE ((uint32_t)0x00000000U) /*!< ARP is disabled */ + +/* transmit I2C data */ +#define DATA_TRANS(regval) (BITS(0,7) & ((uint32_t)(regval) << 0)) + +/* receive I2C data */ +#define DATA_RECV(regval) GET_BITS((uint32_t)(regval), 0, 7) + +/* I2C duty cycle in fast mode */ +#define I2C_DTCY_2 ((uint32_t)0x00000000U) /*!< I2C fast mode Tlow/Thigh = 2 */ +#define I2C_DTCY_16_9 I2C_CKCFG_DTCY /*!< I2C fast mode Tlow/Thigh = 16/9 */ + +/* address mode for the I2C slave */ +#define I2C_ADDFORMAT_7BITS ((uint32_t)0x00000000U) /*!< address:7 bits */ +#define I2C_ADDFORMAT_10BITS I2C_SADDR0_ADDFORMAT /*!< address:10 bits */ + +/* function declarations */ +/* reset I2C */ +void i2c_deinit(uint32_t i2c_periph); +/* configure I2C clock */ +void i2c_clock_config(uint32_t i2c_periph, uint32_t clkspeed, uint32_t dutycyc); +/* configure I2C address */ +void i2c_mode_addr_config(uint32_t i2c_periph, uint32_t mode, uint32_t addformat, uint32_t addr); +/* SMBus type selection */ +void i2c_smbus_type_config(uint32_t i2c_periph, uint32_t type); +/* whether or not to send an ACK */ +void i2c_ack_config(uint32_t i2c_periph, uint32_t ack); +/* configure I2C POAP position */ +void i2c_ackpos_config(uint32_t i2c_periph, uint32_t pos); +/* master sends slave address */ +void i2c_master_addressing(uint32_t i2c_periph, uint32_t addr, uint32_t trandirection); +/* enable dual-address mode */ +void i2c_dualaddr_enable(uint32_t i2c_periph, uint32_t addr); +/* disable dual-address mode */ +void i2c_dualaddr_disable(uint32_t i2c_periph); +/* enable I2C */ +void i2c_enable(uint32_t i2c_periph); +/* disable I2C */ +void i2c_disable(uint32_t i2c_periph); + +/* generate a START condition on I2C bus */ +void i2c_start_on_bus(uint32_t i2c_periph); +/* generate a STOP condition on I2C bus */ +void i2c_stop_on_bus(uint32_t i2c_periph); +/* I2C transmit data function */ +void i2c_data_transmit(uint32_t i2c_periph, uint8_t data); +/* I2C receive data function */ +uint8_t i2c_data_receive(uint32_t i2c_periph); +/* enable I2C DMA mode */ +void i2c_dma_enable(uint32_t i2c_periph, uint32_t dmastate); +/* configure whether next DMA EOT is DMA last transfer or not */ +void i2c_dma_last_transfer_config(uint32_t i2c_periph, uint32_t dmalast); +/* whether to stretch SCL low when data is not ready in slave mode */ +void i2c_stretch_scl_low_config(uint32_t i2c_periph, uint32_t stretchpara); +/* whether or not to response to a general call */ +void i2c_slave_response_to_gcall_config(uint32_t i2c_periph, uint32_t gcallpara); +/* software reset I2C */ +void i2c_software_reset_config(uint32_t i2c_periph, uint32_t sreset); + +/* I2C PEC calculation on or off */ +void i2c_pec_enable(uint32_t i2c_periph, uint32_t pecstate); +/* I2C whether to transfer PEC value */ +void i2c_pec_transfer_enable(uint32_t i2c_periph, uint32_t pecpara); +/* packet error checking value */ +uint8_t i2c_pec_value_get(uint32_t i2c_periph); +/* I2C issue alert through SMBA pin */ +void i2c_smbus_issue_alert(uint32_t i2c_periph, uint32_t smbuspara); +/* I2C ARP protocol in SMBus switch */ +void i2c_smbus_arp_enable(uint32_t i2c_periph, uint32_t arpstate); + +/* check I2C flag is set or not */ +FlagStatus i2c_flag_get(uint32_t i2c_periph, i2c_flag_enum flag); +/* clear I2C flag */ +void i2c_flag_clear(uint32_t i2c_periph, i2c_flag_enum flag); +/* enable I2C interrupt */ +void i2c_interrupt_enable(uint32_t i2c_periph, i2c_interrupt_enum interrupt); +/* disable I2C interrupt */ +void i2c_interrupt_disable(uint32_t i2c_periph, i2c_interrupt_enum interrupt); +/* check I2C interrupt flag */ +FlagStatus i2c_interrupt_flag_get(uint32_t i2c_periph, i2c_interrupt_flag_enum int_flag); +/* clear I2C interrupt flag */ +void i2c_interrupt_flag_clear(uint32_t i2c_periph, i2c_interrupt_flag_enum int_flag); + +#endif /* GD32E10X_I2C_H */ diff --git a/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_standard_peripheral/Include/gd32f10x_misc.h b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_standard_peripheral/Include/gd32f10x_misc.h new file mode 100644 index 0000000000..38e3110998 --- /dev/null +++ b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_standard_peripheral/Include/gd32f10x_misc.h @@ -0,0 +1,94 @@ +/*! + \file gd32f10x_misc.h + \brief definitions for the MISC + + \version 2014-12-26, V1.0.0, firmware for GD32F10x + \version 2017-06-20, V2.0.0, firmware for GD32F10x + \version 2018-07-31, V2.1.0, firmware for GD32F10x + \version 2020-09-30, V2.2.0, firmware for GD32F10x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef GD32F10X_MISC_H +#define GD32F10X_MISC_H + +#include "gd32f10x.h" + +/* constants definitions */ +/* set the RAM and FLASH base address */ +#define NVIC_VECTTAB_RAM ((uint32_t)0x20000000) /*!< RAM base address */ +#define NVIC_VECTTAB_FLASH ((uint32_t)0x08000000) /*!< Flash base address */ + +/* set the NVIC vector table offset mask */ +#define NVIC_VECTTAB_OFFSET_MASK ((uint32_t)0x1FFFFF80) + +/* the register key mask, if you want to do the write operation, you should write 0x5FA to VECTKEY bits */ +#define NVIC_AIRCR_VECTKEY_MASK ((uint32_t)0x05FA0000) + +/* priority group - define the pre-emption priority and the subpriority */ +#define NVIC_PRIGROUP_PRE0_SUB4 ((uint32_t)0x700) /*!< 0 bits for pre-emption priority 4 bits for subpriority */ +#define NVIC_PRIGROUP_PRE1_SUB3 ((uint32_t)0x600) /*!< 1 bits for pre-emption priority 3 bits for subpriority */ +#define NVIC_PRIGROUP_PRE2_SUB2 ((uint32_t)0x500) /*!< 2 bits for pre-emption priority 2 bits for subpriority */ +#define NVIC_PRIGROUP_PRE3_SUB1 ((uint32_t)0x400) /*!< 3 bits for pre-emption priority 1 bits for subpriority */ +#define NVIC_PRIGROUP_PRE4_SUB0 ((uint32_t)0x300) /*!< 4 bits for pre-emption priority 0 bits for subpriority */ + +/* choose the method to enter or exit the lowpower mode */ +#define SCB_SCR_SLEEPONEXIT ((uint8_t)0x02) /*!< choose the the system whether enter low power mode by exiting from ISR */ +#define SCB_SCR_SLEEPDEEP ((uint8_t)0x04) /*!< choose the the system enter the DEEPSLEEP mode or SLEEP mode */ +#define SCB_SCR_SEVONPEND ((uint8_t)0x10) /*!< choose the interrupt source that can wake up the lowpower mode */ + +#define SCB_LPM_SLEEP_EXIT_ISR SCB_SCR_SLEEPONEXIT +#define SCB_LPM_DEEPSLEEP SCB_SCR_SLEEPDEEP +#define SCB_LPM_WAKE_BY_ALL_INT SCB_SCR_SEVONPEND + +/* choose the systick clock source */ +#define SYSTICK_CLKSOURCE_HCLK_DIV8 ((uint32_t)0xFFFFFFFBU) /*!< systick clock source is from HCLK/8 */ +#define SYSTICK_CLKSOURCE_HCLK ((uint32_t)0x00000004U) /*!< systick clock source is from HCLK */ + +/* function declarations */ +/* set the priority group */ +void nvic_priority_group_set(uint32_t nvic_prigroup); + +/* enable NVIC request */ +void nvic_irq_enable(uint8_t nvic_irq, uint8_t nvic_irq_pre_priority, uint8_t nvic_irq_sub_priority); +/* disable NVIC request */ +void nvic_irq_disable(uint8_t nvic_irq); + +/* set the NVIC vector table base address */ +void nvic_vector_table_set(uint32_t nvic_vict_tab, uint32_t offset); + +/* set the state of the low power mode */ +void system_lowpower_set(uint8_t lowpower_mode); +/* reset the state of the low power mode */ +void system_lowpower_reset(uint8_t lowpower_mode); + +/* set the systick clock source */ +void systick_clksource_set(uint32_t systick_clksource); + +#endif /* GD32F10X_MISC_H */ diff --git a/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_standard_peripheral/Include/gd32f10x_pmu.h b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_standard_peripheral/Include/gd32f10x_pmu.h new file mode 100644 index 0000000000..edd53a69c3 --- /dev/null +++ b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_standard_peripheral/Include/gd32f10x_pmu.h @@ -0,0 +1,128 @@ +/*! + \file gd32f10x_pmu.h + \brief definitions for the PMU + + \version 2014-12-26, V1.0.0, firmware for GD32F10x + \version 2017-06-20, V2.0.0, firmware for GD32F10x + \version 2018-07-31, V2.1.0, firmware for GD32F10x + \version 2020-09-30, V2.2.0, firmware for GD32F10x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef GD32F10X_PMU_H +#define GD32F10X_PMU_H + +#include "gd32f10x.h" + +/* PMU definitions */ +#define PMU PMU_BASE /*!< PMU base address */ + +/* registers definitions */ +#define PMU_CTL REG32((PMU) + 0x00U) /*!< PMU control register */ +#define PMU_CS REG32((PMU) + 0x04U) /*!< PMU control and status register */ + +/* bits definitions */ +/* PMU_CTL */ +#define PMU_CTL_LDOLP BIT(0) /*!< LDO low power mode */ +#define PMU_CTL_STBMOD BIT(1) /*!< standby mode */ +#define PMU_CTL_WURST BIT(2) /*!< wakeup flag reset */ +#define PMU_CTL_STBRST BIT(3) /*!< standby flag reset */ +#define PMU_CTL_LVDEN BIT(4) /*!< low voltage detector enable */ +#define PMU_CTL_LVDT BITS(5,7) /*!< low voltage detector threshold */ +#define PMU_CTL_BKPWEN BIT(8) /*!< backup domain write enable */ + +/* PMU_CS */ +#define PMU_CS_WUF BIT(0) /*!< wakeup flag */ +#define PMU_CS_STBF BIT(1) /*!< standby flag */ +#define PMU_CS_LVDF BIT(2) /*!< low voltage detector status flag */ +#define PMU_CS_WUPEN BIT(8) /*!< wakeup pin enable */ + +/* constants definitions */ +/* PMU low voltage detector threshold definitions */ +#define CTL_LVDT(regval) (BITS(5,7)&((uint32_t)(regval) << 5)) +#define PMU_LVDT_0 CTL_LVDT(0) /*!< voltage threshold is 2.2V */ +#define PMU_LVDT_1 CTL_LVDT(1) /*!< voltage threshold is 2.3V */ +#define PMU_LVDT_2 CTL_LVDT(2) /*!< voltage threshold is 2.4V */ +#define PMU_LVDT_3 CTL_LVDT(3) /*!< voltage threshold is 2.5V */ +#define PMU_LVDT_4 CTL_LVDT(4) /*!< voltage threshold is 2.6V */ +#define PMU_LVDT_5 CTL_LVDT(5) /*!< voltage threshold is 2.7V */ +#define PMU_LVDT_6 CTL_LVDT(6) /*!< voltage threshold is 2.8V */ +#define PMU_LVDT_7 CTL_LVDT(7) /*!< voltage threshold is 2.9V */ + +/* PMU flag definitions */ +#define PMU_FLAG_WAKEUP PMU_CS_WUF /*!< wakeup flag status */ +#define PMU_FLAG_STANDBY PMU_CS_STBF /*!< standby flag status */ +#define PMU_FLAG_LVD PMU_CS_LVDF /*!< lvd flag status */ + +/* PMU ldo definitions */ +#define PMU_LDO_NORMAL ((uint32_t)0x00000000U) /*!< LDO normal work when PMU enter deepsleep mode */ +#define PMU_LDO_LOWPOWER PMU_CTL_LDOLP /*!< LDO work at low power status when PMU enter deepsleep mode */ + +/* PMU flag reset definitions */ +#define PMU_FLAG_RESET_WAKEUP ((uint8_t)0x00U) /*!< wakeup flag reset */ +#define PMU_FLAG_RESET_STANDBY ((uint8_t)0x01U) /*!< standby flag reset */ + +/* PMU command constants definitions */ +#define WFI_CMD ((uint8_t)0x00U) /*!< use WFI command */ +#define WFE_CMD ((uint8_t)0x01U) /*!< use WFE command */ + +/* function declarations */ +/* reset PMU registers */ +void pmu_deinit(void); + +/* select low voltage detector threshold */ +void pmu_lvd_select(uint32_t lvdt_n); +/* disable PMU lvd */ +void pmu_lvd_disable(void); + +/* set PMU mode */ +/* PMU work at sleep mode */ +void pmu_to_sleepmode(uint8_t sleepmodecmd); +/* PMU work at deepsleep mode */ +void pmu_to_deepsleepmode(uint32_t ldo, uint8_t deepsleepmodecmd); +/* PMU work at standby mode */ +void pmu_to_standbymode(uint8_t standbymodecmd); +/* enable PMU wakeup pin */ +void pmu_wakeup_pin_enable(void); +/* disable PMU wakeup pin */ +void pmu_wakeup_pin_disable(void); + +/* backup related functions */ +/* enable write access to the registers in backup domain */ +void pmu_backup_write_enable(void); +/* disable write access to the registers in backup domain */ +void pmu_backup_write_disable(void); + +/* flag functions */ +/* get flag state */ +FlagStatus pmu_flag_get(uint32_t flag); +/* clear flag bit */ +void pmu_flag_clear(uint32_t flag_reset); + +#endif /* GD32F10X_PMU_H */ diff --git a/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_standard_peripheral/Include/gd32f10x_rcu.h b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_standard_peripheral/Include/gd32f10x_rcu.h new file mode 100644 index 0000000000..29444f3e80 --- /dev/null +++ b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_standard_peripheral/Include/gd32f10x_rcu.h @@ -0,0 +1,923 @@ +/*! + \file gd32f10x_rcu.h + \brief definitions for the RCU + + \version 2014-12-26, V1.0.0, firmware for GD32F10x + \version 2017-06-20, V2.0.0, firmware for GD32F10x + \version 2018-07-31, V2.1.0, firmware for GD32F10x + \version 2020-09-30, V2.2.0, firmware for GD32F10x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef GD32F10X_RCU_H +#define GD32F10X_RCU_H + +#include "gd32f10x.h" + +/* RCU definitions */ +#define RCU RCU_BASE + +/* registers definitions */ +#if (defined(GD32F10X_MD) || defined(GD32F10X_HD) || defined(GD32F10X_XD)) +#define RCU_CTL REG32(RCU + 0x00U) /*!< control register */ +#define RCU_CFG0 REG32(RCU + 0x04U) /*!< clock configuration register 0 */ +#define RCU_INT REG32(RCU + 0x08U) /*!< clock interrupt register */ +#define RCU_APB2RST REG32(RCU + 0x0CU) /*!< APB2 reset register */ +#define RCU_APB1RST REG32(RCU + 0x10U) /*!< APB1 reset register */ +#define RCU_AHBEN REG32(RCU + 0x14U) /*!< AHB enable register */ +#define RCU_APB2EN REG32(RCU + 0x18U) /*!< APB2 enable register */ +#define RCU_APB1EN REG32(RCU + 0x1CU) /*!< APB1 enable register */ +#define RCU_BDCTL REG32(RCU + 0x20U) /*!< backup domain control register */ +#define RCU_RSTSCK REG32(RCU + 0x24U) /*!< reset source / clock register */ +#define RCU_DSV REG32(RCU + 0x34U) /*!< deep-sleep mode voltage register */ +#elif defined(GD32F10X_CL) +#define RCU_CTL REG32(RCU + 0x00U) /*!< control register */ +#define RCU_CFG0 REG32(RCU + 0x04U) /*!< clock configuration register 0 */ +#define RCU_INT REG32(RCU + 0x08U) /*!< clock interrupt register */ +#define RCU_APB2RST REG32(RCU + 0x0CU) /*!< APB2 reset register */ +#define RCU_APB1RST REG32(RCU + 0x10U) /*!< APB1 reset register */ +#define RCU_AHBEN REG32(RCU + 0x14U) /*!< AHB1 enable register */ +#define RCU_APB2EN REG32(RCU + 0x18U) /*!< APB2 enable register */ +#define RCU_APB1EN REG32(RCU + 0x1CU) /*!< APB1 enable register */ +#define RCU_BDCTL REG32(RCU + 0x20U) /*!< backup domain control register */ +#define RCU_RSTSCK REG32(RCU + 0x24U) /*!< reset source / clock register */ +#define RCU_AHBRST REG32(RCU + 0x28U) /*!< AHB reset register */ +#define RCU_CFG1 REG32(RCU + 0x2CU) /*!< clock configuration register 1 */ +#define RCU_DSV REG32(RCU + 0x34U) /*!< deep-sleep mode voltage register */ +#endif /* GD32F10X_MD and GD32F10X_HD and GD32F10X_XD */ + +/* bits definitions */ +/* RCU_CTL */ +#if (defined(GD32F10X_MD) || defined(GD32F10X_HD) || defined(GD32F10X_XD)) +#define RCU_CTL_IRC8MEN BIT(0) /*!< internal high speed oscillator enable */ +#define RCU_CTL_IRC8MSTB BIT(1) /*!< IRC8M high speed internal oscillator stabilization flag */ +#define RCU_CTL_IRC8MADJ BITS(3,7) /*!< high speed internal oscillator clock trim adjust value */ +#define RCU_CTL_IRC8MCALIB BITS(8,15) /*!< high speed internal oscillator calibration value register */ +#define RCU_CTL_HXTALEN BIT(16) /*!< external high speed oscillator enable */ +#define RCU_CTL_HXTALSTB BIT(17) /*!< external crystal oscillator clock stabilization flag */ +#define RCU_CTL_HXTALBPS BIT(18) /*!< external crystal oscillator clock bypass mode enable */ +#define RCU_CTL_CKMEN BIT(19) /*!< HXTAL clock monitor enable */ +#define RCU_CTL_PLLEN BIT(24) /*!< PLL enable */ +#define RCU_CTL_PLLSTB BIT(25) /*!< PLL clock stabilization flag */ +#elif defined(GD32F10X_CL) +#define RCU_CTL_IRC8MEN BIT(0) /*!< internal high speed oscillator enable */ +#define RCU_CTL_IRC8MSTB BIT(1) /*!< IRC8M high speed internal oscillator stabilization flag */ +#define RCU_CTL_IRC8MADJ BITS(3,7) /*!< high speed internal oscillator clock trim adjust value */ +#define RCU_CTL_IRC8MCALIB BITS(8,15) /*!< high speed internal oscillator calibration value register */ +#define RCU_CTL_HXTALEN BIT(16) /*!< external high speed oscillator enable */ +#define RCU_CTL_HXTALSTB BIT(17) /*!< external crystal oscillator clock stabilization flag */ +#define RCU_CTL_HXTALBPS BIT(18) /*!< external crystal oscillator clock bypass mode enable */ +#define RCU_CTL_CKMEN BIT(19) /*!< HXTAL clock monitor enable */ +#define RCU_CTL_PLLEN BIT(24) /*!< PLL enable */ +#define RCU_CTL_PLLSTB BIT(25) /*!< PLL clock stabilization flag */ +#define RCU_CTL_PLL1EN BIT(26) /*!< PLL1 enable */ +#define RCU_CTL_PLL1STB BIT(27) /*!< PLL1 clock stabilization flag */ +#define RCU_CTL_PLL2EN BIT(28) /*!< PLL2 enable */ +#define RCU_CTL_PLL2STB BIT(29) /*!< PLL2 clock stabilization flag */ +#endif /* GD32F10X_MD and GD32F10X_HD and GD32F10X_XD */ + +/* RCU_CFG0 */ +#if (defined(GD32F10X_MD) || defined(GD32F10X_HD) || defined(GD32F10X_XD)) +#define RCU_CFG0_SCS BITS(0,1) /*!< system clock switch */ +#define RCU_CFG0_SCSS BITS(2,3) /*!< system clock switch status */ +#define RCU_CFG0_AHBPSC BITS(4,7) /*!< AHB prescaler selection */ +#define RCU_CFG0_APB1PSC BITS(8,10) /*!< APB1 prescaler selection */ +#define RCU_CFG0_APB2PSC BITS(11,13) /*!< APB2 prescaler selection */ +#define RCU_CFG0_ADCPSC BITS(14,15) /*!< ADC prescaler selection */ +#define RCU_CFG0_PLLSEL BIT(16) /*!< PLL clock source selection */ +#define RCU_CFG0_PREDV0 BIT(17) /*!< PREDV0 division factor */ +#define RCU_CFG0_PLLMF BITS(18,21) /*!< PLL clock multiplication factor */ +#define RCU_CFG0_USBDPSC BITS(22,23) /*!< USBD clock prescaler selection */ +#define RCU_CFG0_CKOUT0SEL BITS(24,26) /*!< CKOUT0 clock source selection */ +#define RCU_CFG0_PLLMF_4 BIT(27) /*!< bit 4 of PLLMF */ +#define RCU_CFG0_ADCPSC_2 BIT(28) /*!< bit 2 of ADCPSC */ +#elif defined(GD32F10X_CL) +#define RCU_CFG0_SCS BITS(0,1) /*!< system clock switch */ +#define RCU_CFG0_SCSS BITS(2,3) /*!< system clock switch status */ +#define RCU_CFG0_AHBPSC BITS(4,7) /*!< AHB prescaler selection */ +#define RCU_CFG0_APB1PSC BITS(8,10) /*!< APB1 prescaler selection */ +#define RCU_CFG0_APB2PSC BITS(11,13) /*!< APB2 prescaler selection */ +#define RCU_CFG0_ADCPSC BITS(14,15) /*!< ADC prescaler selection */ +#define RCU_CFG0_PLLSEL BIT(16) /*!< PLL clock source selection */ +#define RCU_CFG0_PREDV0_LSB BIT(17) /*!< the LSB of PREDV0 division factor */ +#define RCU_CFG0_PLLMF BITS(18,21) /*!< PLL clock multiplication factor */ +#define RCU_CFG0_USBFSPSC BITS(22,23) /*!< USBFS clock prescaler selection */ +#define RCU_CFG0_CKOUT0SEL BITS(24,27) /*!< CKOUT0 clock source selection */ +#define RCU_CFG0_ADCPSC_2 BIT(28) /*!< bit 2 of ADCPSC */ +#define RCU_CFG0_PLLMF_4 BIT(29) /*!< bit 4 of PLLMF */ +#endif /* GD32F10X_MD and GD32F10X_HD and GD32F10X_XD */ + +/* RCU_INT */ +#if (defined(GD32F10X_MD) || defined(GD32F10X_HD) || defined(GD32F10X_XD)) +#define RCU_INT_IRC40KSTBIF BIT(0) /*!< IRC40K stabilization interrupt flag */ +#define RCU_INT_LXTALSTBIF BIT(1) /*!< LXTAL stabilization interrupt flag */ +#define RCU_INT_IRC8MSTBIF BIT(2) /*!< IRC8M stabilization interrupt flag */ +#define RCU_INT_HXTALSTBIF BIT(3) /*!< HXTAL stabilization interrupt flag */ +#define RCU_INT_PLLSTBIF BIT(4) /*!< PLL stabilization interrupt flag */ +#define RCU_INT_CKMIF BIT(7) /*!< HXTAL clock stuck interrupt flag */ +#define RCU_INT_IRC40KSTBIE BIT(8) /*!< IRC40K stabilization interrupt enable */ +#define RCU_INT_LXTALSTBIE BIT(9) /*!< LXTAL stabilization interrupt enable */ +#define RCU_INT_IRC8MSTBIE BIT(10) /*!< IRC8M stabilization interrupt enable */ +#define RCU_INT_HXTALSTBIE BIT(11) /*!< HXTAL stabilization interrupt enable */ +#define RCU_INT_PLLSTBIE BIT(12) /*!< PLL stabilization interrupt enable */ +#define RCU_INT_IRC40KSTBIC BIT(16) /*!< IRC40K Stabilization interrupt clear */ +#define RCU_INT_LXTALSTBIC BIT(17) /*!< LXTAL Stabilization interrupt clear */ +#define RCU_INT_IRC8MSTBIC BIT(18) /*!< IRC8M Stabilization interrupt clear */ +#define RCU_INT_HXTALSTBIC BIT(19) /*!< HXTAL Stabilization interrupt clear */ +#define RCU_INT_PLLSTBIC BIT(20) /*!< PLL stabilization interrupt clear */ +#define RCU_INT_CKMIC BIT(23) /*!< HXTAL clock stuck interrupt clear */ +#elif defined(GD32F10X_CL) +#define RCU_INT_IRC40KSTBIF BIT(0) /*!< IRC40K stabilization interrupt flag */ +#define RCU_INT_LXTALSTBIF BIT(1) /*!< LXTAL stabilization interrupt flag */ +#define RCU_INT_IRC8MSTBIF BIT(2) /*!< IRC8M stabilization interrupt flag */ +#define RCU_INT_HXTALSTBIF BIT(3) /*!< HXTAL stabilization interrupt flag */ +#define RCU_INT_PLLSTBIF BIT(4) /*!< PLL stabilization interrupt flag */ +#define RCU_INT_PLL1STBIF BIT(5) /*!< PLL1 stabilization interrupt flag */ +#define RCU_INT_PLL2STBIF BIT(6) /*!< PLL2 stabilization interrupt flag */ +#define RCU_INT_CKMIF BIT(7) /*!< HXTAL clock stuck interrupt flag */ +#define RCU_INT_IRC40KSTBIE BIT(8) /*!< IRC40K stabilization interrupt enable */ +#define RCU_INT_LXTALSTBIE BIT(9) /*!< LXTAL stabilization interrupt enable */ +#define RCU_INT_IRC8MSTBIE BIT(10) /*!< IRC8M stabilization interrupt enable */ +#define RCU_INT_HXTALSTBIE BIT(11) /*!< HXTAL stabilization interrupt enable */ +#define RCU_INT_PLLSTBIE BIT(12) /*!< PLL stabilization interrupt enable */ +#define RCU_INT_PLL1STBIE BIT(13) /*!< PLL1 stabilization interrupt enable */ +#define RCU_INT_PLL2STBIE BIT(14) /*!< PLL2 stabilization interrupt enable */ +#define RCU_INT_IRC40KSTBIC BIT(16) /*!< IRC40K stabilization interrupt clear */ +#define RCU_INT_LXTALSTBIC BIT(17) /*!< LXTAL stabilization interrupt clear */ +#define RCU_INT_IRC8MSTBIC BIT(18) /*!< IRC8M stabilization interrupt clear */ +#define RCU_INT_HXTALSTBIC BIT(19) /*!< HXTAL stabilization interrupt clear */ +#define RCU_INT_PLLSTBIC BIT(20) /*!< PLL stabilization interrupt clear */ +#define RCU_INT_PLL1STBIC BIT(21) /*!< PLL1 stabilization interrupt clear */ +#define RCU_INT_PLL2STBIC BIT(22) /*!< PLL2 stabilization interrupt clear */ +#define RCU_INT_CKMIC BIT(23) /*!< HXTAL clock stuck interrupt clear */ +#endif /* GD32F10X_MD and GD32F10X_HD and GD32F10X_XD */ + +/* RCU_APB2RST */ +#define RCU_APB2RST_AFRST BIT(0) /*!< alternate function I/O reset */ +#define RCU_APB2RST_PARST BIT(2) /*!< GPIO port A reset */ +#define RCU_APB2RST_PBRST BIT(3) /*!< GPIO port B reset */ +#define RCU_APB2RST_PCRST BIT(4) /*!< GPIO port C reset */ +#define RCU_APB2RST_PDRST BIT(5) /*!< GPIO port D reset */ +#define RCU_APB2RST_PERST BIT(6) /*!< GPIO port E reset */ +#define RCU_APB2RST_PFRST BIT(7) /*!< GPIO port F reset */ +#define RCU_APB2RST_PGRST BIT(8) /*!< GPIO port G reset */ +#define RCU_APB2RST_ADC0RST BIT(9) /*!< ADC0 reset */ +#define RCU_APB2RST_ADC1RST BIT(10) /*!< ADC1 reset */ +#define RCU_APB2RST_TIMER0RST BIT(11) /*!< TIMER0 reset */ +#define RCU_APB2RST_SPI0RST BIT(12) /*!< SPI0 reset */ +#define RCU_APB2RST_TIMER7RST BIT(13) /*!< TIMER7 reset */ +#define RCU_APB2RST_USART0RST BIT(14) /*!< USART0 reset */ +#ifndef GD32F10X_CL +#define RCU_APB2RST_ADC2RST BIT(15) /*!< ADC2 reset */ +#endif /* GD32F10X_CL */ +#ifdef GD32F10X_XD +#define RCU_APB2RST_TIMER8RST BIT(19) /*!< TIMER8 reset */ +#define RCU_APB2RST_TIMER9RST BIT(20) /*!< TIMER9 reset */ +#define RCU_APB2RST_TIMER10RST BIT(21) /*!< TIMER10 reset */ +#endif /* GD32F10X_XD */ + +/* RCU_APB1RST */ +#define RCU_APB1RST_TIMER1RST BIT(0) /*!< TIMER1 reset */ +#define RCU_APB1RST_TIMER2RST BIT(1) /*!< TIMER2 reset */ +#define RCU_APB1RST_TIMER3RST BIT(2) /*!< TIMER3 reset */ +#define RCU_APB1RST_TIMER4RST BIT(3) /*!< TIMER4 reset */ +#define RCU_APB1RST_TIMER5RST BIT(4) /*!< TIMER5 reset */ +#define RCU_APB1RST_TIMER6RST BIT(5) /*!< TIMER6 reset */ +#ifdef GD32F10X_XD +#define RCU_APB1RST_TIMER11RST BIT(6) /*!< TIMER11 reset */ +#define RCU_APB1RST_TIMER12RST BIT(7) /*!< TIMER12 reset */ +#define RCU_APB1RST_TIMER13RST BIT(8) /*!< TIMER13 reset */ +#endif /* GD32F10X_XD */ +#define RCU_APB1RST_WWDGTRST BIT(11) /*!< WWDGT reset */ +#define RCU_APB1RST_SPI1RST BIT(14) /*!< SPI1 reset */ +#define RCU_APB1RST_SPI2RST BIT(15) /*!< SPI2 reset */ +#define RCU_APB1RST_USART1RST BIT(17) /*!< USART1 reset */ +#define RCU_APB1RST_USART2RST BIT(18) /*!< USART2 reset */ +#define RCU_APB1RST_UART3RST BIT(19) /*!< UART3 reset */ +#define RCU_APB1RST_UART4RST BIT(20) /*!< UART4 reset */ +#define RCU_APB1RST_I2C0RST BIT(21) /*!< I2C0 reset */ +#define RCU_APB1RST_I2C1RST BIT(22) /*!< I2C1 reset */ +#if (defined(GD32F10X_MD) || defined(GD32F10X_HD) || defined(GD32F10X_XD)) +#define RCU_APB1RST_USBDRST BIT(23) /*!< USBD reset */ +#endif /* GD32F10X_MD and GD32F10X_HD and GD32F10X_XD */ +#define RCU_APB1RST_CAN0RST BIT(25) /*!< CAN0 reset */ +#ifdef GD32F10X_CL +#define RCU_APB1RST_CAN1RST BIT(26) /*!< CAN1 reset */ +#endif /* GD32F10X_CL */ +#define RCU_APB1RST_BKPIRST BIT(27) /*!< backup interface reset */ +#define RCU_APB1RST_PMURST BIT(28) /*!< PMU reset */ +#define RCU_APB1RST_DACRST BIT(29) /*!< DAC reset */ + +/* RCU_AHBEN */ +#define RCU_AHBEN_DMA0EN BIT(0) /*!< DMA0 clock enable */ +#define RCU_AHBEN_DMA1EN BIT(1) /*!< DMA1 clock enable */ +#define RCU_AHBEN_SRAMSPEN BIT(2) /*!< SRAM clock enable when sleep mode */ +#define RCU_AHBEN_FMCSPEN BIT(4) /*!< FMC clock enable when sleep mode */ +#define RCU_AHBEN_CRCEN BIT(6) /*!< CRC clock enable */ +#define RCU_AHBEN_EXMCEN BIT(8) /*!< EXMC clock enable */ +#if (defined(GD32F10X_MD) || defined(GD32F10X_HD) || defined(GD32F10X_XD)) +#define RCU_AHBEN_SDIOEN BIT(10) /*!< SDIO clock enable */ +#elif defined(GD32F10X_CL) +#define RCU_AHBEN_USBFSEN BIT(12) /*!< USBFS clock enable */ +#define RCU_AHBEN_ENETEN BIT(14) /*!< ENET clock enable */ +#define RCU_AHBEN_ENETTXEN BIT(15) /*!< Ethernet TX clock enable */ +#define RCU_AHBEN_ENETRXEN BIT(16) /*!< Ethernet RX clock enable */ +#endif /* GD32F10X_MD and GD32F10X_HD and GD32F10X_XD */ + +/* RCU_APB2EN */ +#define RCU_APB2EN_AFEN BIT(0) /*!< alternate function IO clock enable */ +#define RCU_APB2EN_PAEN BIT(2) /*!< GPIO port A clock enable */ +#define RCU_APB2EN_PBEN BIT(3) /*!< GPIO port B clock enable */ +#define RCU_APB2EN_PCEN BIT(4) /*!< GPIO port C clock enable */ +#define RCU_APB2EN_PDEN BIT(5) /*!< GPIO port D clock enable */ +#define RCU_APB2EN_PEEN BIT(6) /*!< GPIO port E clock enable */ +#define RCU_APB2EN_PFEN BIT(7) /*!< GPIO port F clock enable */ +#define RCU_APB2EN_PGEN BIT(8) /*!< GPIO port G clock enable */ +#define RCU_APB2EN_ADC0EN BIT(9) /*!< ADC0 clock enable */ +#define RCU_APB2EN_ADC1EN BIT(10) /*!< ADC1 clock enable */ +#define RCU_APB2EN_TIMER0EN BIT(11) /*!< TIMER0 clock enable */ +#define RCU_APB2EN_SPI0EN BIT(12) /*!< SPI0 clock enable */ +#define RCU_APB2EN_TIMER7EN BIT(13) /*!< TIMER7 clock enable */ +#define RCU_APB2EN_USART0EN BIT(14) /*!< USART0 clock enable */ +#ifndef GD32F10X_CL +#define RCU_APB2EN_ADC2EN BIT(15) /*!< ADC2 clock enable */ +#endif /* GD32F10X_CL */ +#ifdef GD32F10X_XD +#define RCU_APB2EN_TIMER8EN BIT(19) /*!< TIMER8 clock enable */ +#define RCU_APB2EN_TIMER9EN BIT(20) /*!< TIMER9 clock enable */ +#define RCU_APB2EN_TIMER10EN BIT(21) /*!< TIMER10 clock enable */ +#endif /* GD32F10X_XD */ + +/* RCU_APB1EN */ +#define RCU_APB1EN_TIMER1EN BIT(0) /*!< TIMER1 clock enable */ +#define RCU_APB1EN_TIMER2EN BIT(1) /*!< TIMER2 clock enable */ +#define RCU_APB1EN_TIMER3EN BIT(2) /*!< TIMER3 clock enable */ +#define RCU_APB1EN_TIMER4EN BIT(3) /*!< TIMER4 clock enable */ +#define RCU_APB1EN_TIMER5EN BIT(4) /*!< TIMER5 clock enable */ +#define RCU_APB1EN_TIMER6EN BIT(5) /*!< TIMER6 clock enable */ +#ifdef GD32F10X_XD +#define RCU_APB1EN_TIMER11EN BIT(6) /*!< TIMER11 clock enable */ +#define RCU_APB1EN_TIMER12EN BIT(7) /*!< TIMER12 clock enable */ +#define RCU_APB1EN_TIMER13EN BIT(8) /*!< TIMER13 clock enable */ +#endif /* GD32F10X_XD */ +#define RCU_APB1EN_WWDGTEN BIT(11) /*!< WWDGT clock enable */ +#define RCU_APB1EN_SPI1EN BIT(14) /*!< SPI1 clock enable */ +#define RCU_APB1EN_SPI2EN BIT(15) /*!< SPI2 clock enable */ +#define RCU_APB1EN_USART1EN BIT(17) /*!< USART1 clock enable */ +#define RCU_APB1EN_USART2EN BIT(18) /*!< USART2 clock enable */ +#define RCU_APB1EN_UART3EN BIT(19) /*!< UART3 clock enable */ +#define RCU_APB1EN_UART4EN BIT(20) /*!< UART4 clock enable */ +#define RCU_APB1EN_I2C0EN BIT(21) /*!< I2C0 clock enable */ +#define RCU_APB1EN_I2C1EN BIT(22) /*!< I2C1 clock enable */ +#if (defined(GD32F10X_MD) || defined(GD32F10X_HD) || defined(GD32F10X_XD)) +#define RCU_APB1EN_USBDEN BIT(23) /*!< USBD clock enable */ +#endif /* GD32F10X_MD and GD32F10X_HD and GD32F10X_XD */ +#define RCU_APB1EN_CAN0EN BIT(25) /*!< CAN0 clock enable */ +#ifdef GD32F10X_CL +#define RCU_APB1EN_CAN1EN BIT(26) /*!< CAN1 clock enable */ +#endif /* GD32F10X_CL */ +#define RCU_APB1EN_BKPIEN BIT(27) /*!< backup interface clock enable */ +#define RCU_APB1EN_PMUEN BIT(28) /*!< PMU clock enable */ +#define RCU_APB1EN_DACEN BIT(29) /*!< DAC clock enable */ + +/* RCU_BDCTL */ +#define RCU_BDCTL_LXTALEN BIT(0) /*!< LXTAL enable */ +#define RCU_BDCTL_LXTALSTB BIT(1) /*!< low speed crystal oscillator stabilization flag */ +#define RCU_BDCTL_LXTALBPS BIT(2) /*!< LXTAL bypass mode enable */ +#define RCU_BDCTL_RTCSRC BITS(8,9) /*!< RTC clock entry selection */ +#define RCU_BDCTL_RTCEN BIT(15) /*!< RTC clock enable */ +#define RCU_BDCTL_BKPRST BIT(16) /*!< backup domain reset */ + +/* RCU_RSTSCK */ +#define RCU_RSTSCK_IRC40KEN BIT(0) /*!< IRC40K enable */ +#define RCU_RSTSCK_IRC40KSTB BIT(1) /*!< IRC40K stabilization flag */ +#define RCU_RSTSCK_RSTFC BIT(24) /*!< reset flag clear */ +#define RCU_RSTSCK_EPRSTF BIT(26) /*!< external pin reset flag */ +#define RCU_RSTSCK_PORRSTF BIT(27) /*!< power reset flag */ +#define RCU_RSTSCK_SWRSTF BIT(28) /*!< software reset flag */ +#define RCU_RSTSCK_FWDGTRSTF BIT(29) /*!< free watchdog timer reset flag */ +#define RCU_RSTSCK_WWDGTRSTF BIT(30) /*!< window watchdog timer reset flag */ +#define RCU_RSTSCK_LPRSTF BIT(31) /*!< low-power reset flag */ + +#ifdef GD32F10X_CL +/* RCU_AHBRST */ +#define RCU_AHBRST_USBFSRST BIT(12) /*!< USBFS reset */ +#define RCU_AHBRST_ENETRST BIT(14) /*!< ENET reset */ +#endif /* GD32F10X_CL */ + +#if defined(GD32F10X_CL) +/* RCU_CFG1 */ +#define RCU_CFG1_PREDV0 BITS(0,3) /*!< PREDV0 division factor */ +#define RCU_CFG1_PREDV1 BITS(4,7) /*!< PREDV1 division factor */ +#define RCU_CFG1_PLL1MF BITS(8,11) /*!< PLL1 clock multiplication factor */ +#define RCU_CFG1_PLL2MF BITS(12,15) /*!< PLL2 clock multiplication factor */ +#define RCU_CFG1_PREDV0SEL BIT(16) /*!< PREDV0 input clock source selection */ +#define RCU_CFG1_I2S1SEL BIT(17) /*!< I2S1 clock source selection */ +#define RCU_CFG1_I2S2SEL BIT(18) /*!< I2S2 clock source selection */ +#endif /* GD32F10X_CL */ + +/* RCU_DSV */ +#define RCU_DSV_DSLPVS BITS(0,2) /*!< deep-sleep mode voltage select */ + +/* constants definitions */ +/* define the peripheral clock enable bit position and its register index offset */ +#define RCU_REGIDX_BIT(regidx, bitpos) (((uint32_t)(regidx) << 6) | (uint32_t)(bitpos)) +#define RCU_REG_VAL(periph) (REG32(RCU + ((uint32_t)(periph) >> 6))) +#define RCU_BIT_POS(val) ((uint32_t)(val) & 0x1FU) + +/* register offset */ +/* peripherals enable */ +#define AHBEN_REG_OFFSET 0x14U /*!< AHB enable register offset */ +#define APB1EN_REG_OFFSET 0x1CU /*!< APB1 enable register offset */ +#define APB2EN_REG_OFFSET 0x18U /*!< APB2 enable register offset */ + +/* peripherals reset */ +#define AHBRST_REG_OFFSET 0x28U /*!< AHB reset register offset */ +#define APB1RST_REG_OFFSET 0x10U /*!< APB1 reset register offset */ +#define APB2RST_REG_OFFSET 0x0CU /*!< APB2 reset register offset */ +#define RSTSCK_REG_OFFSET 0x24U /*!< reset source/clock register offset */ + +/* clock control */ +#define CTL_REG_OFFSET 0x00U /*!< control register offset */ +#define BDCTL_REG_OFFSET 0x20U /*!< backup domain control register offset */ + +/* clock stabilization and stuck interrupt */ +#define INT_REG_OFFSET 0x08U /*!< clock interrupt register offset */ + +/* configuration register */ +#define CFG0_REG_OFFSET 0x04U /*!< clock configuration register 0 offset */ +#define CFG1_REG_OFFSET 0x2CU /*!< clock configuration register 1 offset */ + +/* peripheral clock enable */ +typedef enum +{ + /* AHB peripherals */ + RCU_DMA0 = RCU_REGIDX_BIT(AHBEN_REG_OFFSET, 0U), /*!< DMA0 clock */ + RCU_DMA1 = RCU_REGIDX_BIT(AHBEN_REG_OFFSET, 1U), /*!< DMA1 clock */ + RCU_CRC = RCU_REGIDX_BIT(AHBEN_REG_OFFSET, 6U), /*!< CRC clock */ + RCU_EXMC = RCU_REGIDX_BIT(AHBEN_REG_OFFSET, 8U), /*!< EXMC clock */ +#if (defined(GD32F10X_MD) || defined(GD32F10X_HD) || defined(GD32F10X_XD)) + RCU_SDIO = RCU_REGIDX_BIT(AHBEN_REG_OFFSET, 10U), /*!< SDIO clock */ +#elif defined(GD32F10X_CL) + RCU_USBFS = RCU_REGIDX_BIT(AHBEN_REG_OFFSET, 12U), /*!< USBFS clock */ + RCU_ENET = RCU_REGIDX_BIT(AHBEN_REG_OFFSET, 14U), /*!< ENET clock */ + RCU_ENETTX = RCU_REGIDX_BIT(AHBEN_REG_OFFSET, 15U), /*!< ENETTX clock */ + RCU_ENETRX = RCU_REGIDX_BIT(AHBEN_REG_OFFSET, 16U), /*!< ENETRX clock */ +#endif /* GD32F10X_MD and GD32F10X_HD and GD32F10X_XD */ + + /* APB1 peripherals */ + RCU_TIMER1 = RCU_REGIDX_BIT(APB1EN_REG_OFFSET, 0U), /*!< TIMER1 clock */ + RCU_TIMER2 = RCU_REGIDX_BIT(APB1EN_REG_OFFSET, 1U), /*!< TIMER2 clock */ + RCU_TIMER3 = RCU_REGIDX_BIT(APB1EN_REG_OFFSET, 2U), /*!< TIMER3 clock */ + RCU_TIMER4 = RCU_REGIDX_BIT(APB1EN_REG_OFFSET, 3U), /*!< TIMER4 clock */ + RCU_TIMER5 = RCU_REGIDX_BIT(APB1EN_REG_OFFSET, 4U), /*!< TIMER5 clock */ + RCU_TIMER6 = RCU_REGIDX_BIT(APB1EN_REG_OFFSET, 5U), /*!< TIMER6 clock */ +#if defined(GD32F10X_XD) + RCU_TIMER11 = RCU_REGIDX_BIT(APB1EN_REG_OFFSET, 6U), /*!< TIMER11 clock */ + RCU_TIMER12 = RCU_REGIDX_BIT(APB1EN_REG_OFFSET, 7U), /*!< TIMER12 clock */ + RCU_TIMER13 = RCU_REGIDX_BIT(APB1EN_REG_OFFSET, 8U), /*!< TIMER13 clock */ +#endif /* GD32F10X_XD */ + RCU_WWDGT = RCU_REGIDX_BIT(APB1EN_REG_OFFSET, 11U), /*!< WWDGT clock */ + RCU_SPI1 = RCU_REGIDX_BIT(APB1EN_REG_OFFSET, 14U), /*!< SPI1 clock */ + RCU_SPI2 = RCU_REGIDX_BIT(APB1EN_REG_OFFSET, 15U), /*!< SPI2 clock */ + RCU_USART1 = RCU_REGIDX_BIT(APB1EN_REG_OFFSET, 17U), /*!< USART1 clock */ + RCU_USART2 = RCU_REGIDX_BIT(APB1EN_REG_OFFSET, 18U), /*!< USART2 clock */ + RCU_UART3 = RCU_REGIDX_BIT(APB1EN_REG_OFFSET, 19U), /*!< UART3 clock */ + RCU_UART4 = RCU_REGIDX_BIT(APB1EN_REG_OFFSET, 20U), /*!< UART4 clock */ + RCU_I2C0 = RCU_REGIDX_BIT(APB1EN_REG_OFFSET, 21U), /*!< I2C0 clock */ + RCU_I2C1 = RCU_REGIDX_BIT(APB1EN_REG_OFFSET, 22U), /*!< I2C1 clock */ +#if (defined(GD32F10X_MD) || defined(GD32F10X_HD) || defined(GD32F10X_XD)) + RCU_USBD = RCU_REGIDX_BIT(APB1EN_REG_OFFSET, 23U), /*!< USBD clock */ +#endif /* GD32F10X_MD and GD32F10X_HD and GD32F10X_XD */ + RCU_CAN0 = RCU_REGIDX_BIT(APB1EN_REG_OFFSET, 25U), /*!< CAN0 clock */ +#ifdef GD32F10X_CL + RCU_CAN1 = RCU_REGIDX_BIT(APB1EN_REG_OFFSET, 26U), /*!< CAN1 clock */ +#endif /* GD32F10X_CL */ + RCU_BKPI = RCU_REGIDX_BIT(APB1EN_REG_OFFSET, 27U), /*!< BKPI clock */ + RCU_PMU = RCU_REGIDX_BIT(APB1EN_REG_OFFSET, 28U), /*!< PMU clock */ + RCU_DAC = RCU_REGIDX_BIT(APB1EN_REG_OFFSET, 29U), /*!< DAC clock */ + RCU_RTC = RCU_REGIDX_BIT(BDCTL_REG_OFFSET, 15U), /*!< RTC clock */ + + /* APB2 peripherals */ + RCU_AF = RCU_REGIDX_BIT(APB2EN_REG_OFFSET, 0U), /*!< alternate function clock */ + RCU_GPIOA = RCU_REGIDX_BIT(APB2EN_REG_OFFSET, 2U), /*!< GPIOA clock */ + RCU_GPIOB = RCU_REGIDX_BIT(APB2EN_REG_OFFSET, 3U), /*!< GPIOB clock */ + RCU_GPIOC = RCU_REGIDX_BIT(APB2EN_REG_OFFSET, 4U), /*!< GPIOC clock */ + RCU_GPIOD = RCU_REGIDX_BIT(APB2EN_REG_OFFSET, 5U), /*!< GPIOD clock */ + RCU_GPIOE = RCU_REGIDX_BIT(APB2EN_REG_OFFSET, 6U), /*!< GPIOE clock */ + RCU_GPIOF = RCU_REGIDX_BIT(APB2EN_REG_OFFSET, 7U), /*!< GPIOF clock */ + RCU_GPIOG = RCU_REGIDX_BIT(APB2EN_REG_OFFSET, 8U), /*!< GPIOG clock */ + RCU_ADC0 = RCU_REGIDX_BIT(APB2EN_REG_OFFSET, 9U), /*!< ADC0 clock */ + RCU_ADC1 = RCU_REGIDX_BIT(APB2EN_REG_OFFSET, 10U), /*!< ADC1 clock */ + RCU_TIMER0 = RCU_REGIDX_BIT(APB2EN_REG_OFFSET, 11U), /*!< TIMER0 clock */ + RCU_SPI0 = RCU_REGIDX_BIT(APB2EN_REG_OFFSET, 12U), /*!< SPI0 clock */ + RCU_TIMER7 = RCU_REGIDX_BIT(APB2EN_REG_OFFSET, 13U), /*!< TIMER7 clock */ + RCU_USART0 = RCU_REGIDX_BIT(APB2EN_REG_OFFSET, 14U), /*!< USART0 clock */ +#ifndef GD32F10X_CL + RCU_ADC2 = RCU_REGIDX_BIT(APB2EN_REG_OFFSET, 15U), /*!< ADC2 clock */ +#endif /* GD32F10X_CL */ +#ifdef GD32F10X_XD + RCU_TIMER8 = RCU_REGIDX_BIT(APB2EN_REG_OFFSET, 19U), /*!< TIMER8 clock */ + RCU_TIMER9 = RCU_REGIDX_BIT(APB2EN_REG_OFFSET, 20U), /*!< TIMER9 clock */ + RCU_TIMER10 = RCU_REGIDX_BIT(APB2EN_REG_OFFSET, 21U), /*!< TIMER10 clock */ +#endif /* GD32F10X_XD */ +}rcu_periph_enum; + +/* peripheral clock enable when sleep mode*/ +typedef enum +{ + /* AHB peripherals */ + RCU_SRAM_SLP = RCU_REGIDX_BIT(AHBEN_REG_OFFSET, 2U), /*!< SRAM clock */ + RCU_FMC_SLP = RCU_REGIDX_BIT(AHBEN_REG_OFFSET, 4U), /*!< FMC clock */ +}rcu_periph_sleep_enum; + +/* peripherals reset */ +typedef enum +{ + /* AHB peripherals */ +#ifdef GD32F10X_CL + RCU_USBFSRST = RCU_REGIDX_BIT(AHBRST_REG_OFFSET, 12U), /*!< USBFS clock reset */ + RCU_ENETRST = RCU_REGIDX_BIT(AHBRST_REG_OFFSET, 14U), /*!< ENET clock reset */ +#endif /* GD32F10X_CL */ + + /* APB1 peripherals */ + RCU_TIMER1RST = RCU_REGIDX_BIT(APB1RST_REG_OFFSET, 0U), /*!< TIMER1 clock reset */ + RCU_TIMER2RST = RCU_REGIDX_BIT(APB1RST_REG_OFFSET, 1U), /*!< TIMER2 clock reset */ + RCU_TIMER3RST = RCU_REGIDX_BIT(APB1RST_REG_OFFSET, 2U), /*!< TIMER3 clock reset */ + RCU_TIMER4RST = RCU_REGIDX_BIT(APB1RST_REG_OFFSET, 3U), /*!< TIMER4 clock reset */ + RCU_TIMER5RST = RCU_REGIDX_BIT(APB1RST_REG_OFFSET, 4U), /*!< TIMER5 clock reset */ + RCU_TIMER6RST = RCU_REGIDX_BIT(APB1RST_REG_OFFSET, 5U), /*!< TIMER6 clock reset */ +#ifdef GD32F10X_XD + RCU_TIMER11RST = RCU_REGIDX_BIT(APB1RST_REG_OFFSET, 6U), /*!< TIMER11 clock reset */ + RCU_TIMER12RST = RCU_REGIDX_BIT(APB1RST_REG_OFFSET, 7U), /*!< TIMER12 clock reset */ + RCU_TIMER13RST = RCU_REGIDX_BIT(APB1RST_REG_OFFSET, 8U), /*!< TIMER13 clock reset */ +#endif /* GD32F10X_XD */ + RCU_WWDGTRST = RCU_REGIDX_BIT(APB1RST_REG_OFFSET, 11U), /*!< WWDGT clock reset */ + RCU_SPI1RST = RCU_REGIDX_BIT(APB1RST_REG_OFFSET, 14U), /*!< SPI1 clock reset */ + RCU_SPI2RST = RCU_REGIDX_BIT(APB1RST_REG_OFFSET, 15U), /*!< SPI2 clock reset */ + RCU_USART1RST = RCU_REGIDX_BIT(APB1RST_REG_OFFSET, 17U), /*!< USART1 clock reset */ + RCU_USART2RST = RCU_REGIDX_BIT(APB1RST_REG_OFFSET, 18U), /*!< USART2 clock reset */ + RCU_UART3RST = RCU_REGIDX_BIT(APB1RST_REG_OFFSET, 19U), /*!< UART3 clock reset */ + RCU_UART4RST = RCU_REGIDX_BIT(APB1RST_REG_OFFSET, 20U), /*!< UART4 clock reset */ + RCU_I2C0RST = RCU_REGIDX_BIT(APB1RST_REG_OFFSET, 21U), /*!< I2C0 clock reset */ + RCU_I2C1RST = RCU_REGIDX_BIT(APB1RST_REG_OFFSET, 22U), /*!< I2C1 clock reset */ +#if (defined(GD32F10X_MD) || defined(GD32F10X_HD) || defined(GD32F10X_XD)) + RCU_USBDRST = RCU_REGIDX_BIT(APB1RST_REG_OFFSET, 23U), /*!< USBD clock reset */ +#endif /* GD32F10X_MD and GD32F10X_HD and GD32F10X_XD */ + RCU_CAN0RST = RCU_REGIDX_BIT(APB1RST_REG_OFFSET, 25U), /*!< CAN0 clock reset */ +#ifdef GD32F10X_CL + RCU_CAN1RST = RCU_REGIDX_BIT(APB1RST_REG_OFFSET, 26U), /*!< CAN1 clock reset */ +#endif /* GD32F10X_CL */ + RCU_BKPIRST = RCU_REGIDX_BIT(APB1RST_REG_OFFSET, 27U), /*!< BKPI clock reset */ + RCU_PMURST = RCU_REGIDX_BIT(APB1RST_REG_OFFSET, 28U), /*!< PMU clock reset */ + RCU_DACRST = RCU_REGIDX_BIT(APB1RST_REG_OFFSET, 29U), /*!< DAC clock reset */ + + /* APB2 peripherals */ + RCU_AFRST = RCU_REGIDX_BIT(APB2RST_REG_OFFSET, 0U), /*!< alternate function clock reset */ + RCU_GPIOARST = RCU_REGIDX_BIT(APB2RST_REG_OFFSET, 2U), /*!< GPIOA clock reset */ + RCU_GPIOBRST = RCU_REGIDX_BIT(APB2RST_REG_OFFSET, 3U), /*!< GPIOB clock reset */ + RCU_GPIOCRST = RCU_REGIDX_BIT(APB2RST_REG_OFFSET, 4U), /*!< GPIOC clock reset */ + RCU_GPIODRST = RCU_REGIDX_BIT(APB2RST_REG_OFFSET, 5U), /*!< GPIOD clock reset */ + RCU_GPIOERST = RCU_REGIDX_BIT(APB2RST_REG_OFFSET, 6U), /*!< GPIOE clock reset */ + RCU_GPIOFRST = RCU_REGIDX_BIT(APB2RST_REG_OFFSET, 7U), /*!< GPIOF clock reset */ + RCU_GPIOGRST = RCU_REGIDX_BIT(APB2RST_REG_OFFSET, 8U), /*!< GPIOG clock reset */ + RCU_ADC0RST = RCU_REGIDX_BIT(APB2RST_REG_OFFSET, 9U), /*!< ADC0 clock reset */ + RCU_ADC1RST = RCU_REGIDX_BIT(APB2RST_REG_OFFSET, 10U), /*!< ADC1 clock reset */ + RCU_TIMER0RST = RCU_REGIDX_BIT(APB2RST_REG_OFFSET, 11U), /*!< TIMER0 clock reset */ + RCU_SPI0RST = RCU_REGIDX_BIT(APB2RST_REG_OFFSET, 12U), /*!< SPI0 clock reset */ + RCU_TIMER7RST = RCU_REGIDX_BIT(APB2RST_REG_OFFSET, 13U), /*!< TIMER7 clock reset */ + RCU_USART0RST = RCU_REGIDX_BIT(APB2RST_REG_OFFSET, 14U), /*!< USART0 clock reset */ +#ifndef GD32F10X_CL + RCU_ADC2RST = RCU_REGIDX_BIT(APB2RST_REG_OFFSET, 15U), /*!< ADC2 clock reset */ +#endif /* GD32F10X_CL */ +#ifdef GD32F10X_XD + RCU_TIMER8RST = RCU_REGIDX_BIT(APB2RST_REG_OFFSET, 19U), /*!< TIMER8 clock reset */ + RCU_TIMER9RST = RCU_REGIDX_BIT(APB2RST_REG_OFFSET, 20U), /*!< TIMER9 clock reset */ + RCU_TIMER10RST = RCU_REGIDX_BIT(APB2RST_REG_OFFSET, 21U), /*!< TIMER10 clock reset */ +#endif /* GD32F10X_XD */ +}rcu_periph_reset_enum; + +/* clock stabilization and peripheral reset flags */ +typedef enum +{ + /* clock stabilization flags */ + RCU_FLAG_IRC8MSTB = RCU_REGIDX_BIT(CTL_REG_OFFSET, 1U), /*!< IRC8M stabilization flags */ + RCU_FLAG_HXTALSTB = RCU_REGIDX_BIT(CTL_REG_OFFSET, 17U), /*!< HXTAL stabilization flags */ + RCU_FLAG_PLLSTB = RCU_REGIDX_BIT(CTL_REG_OFFSET, 25U), /*!< PLL stabilization flags */ +#ifdef GD32F10X_CL + RCU_FLAG_PLL1STB = RCU_REGIDX_BIT(CTL_REG_OFFSET, 27U), /*!< PLL1 stabilization flags */ + RCU_FLAG_PLL2STB = RCU_REGIDX_BIT(CTL_REG_OFFSET, 29U), /*!< PLL2 stabilization flags */ +#endif /* GD32F10X_CL */ + RCU_FLAG_LXTALSTB = RCU_REGIDX_BIT(BDCTL_REG_OFFSET, 1U), /*!< LXTAL stabilization flags */ + RCU_FLAG_IRC40KSTB = RCU_REGIDX_BIT(RSTSCK_REG_OFFSET, 1U), /*!< IRC40K stabilization flags */ + /* reset source flags */ + RCU_FLAG_EPRST = RCU_REGIDX_BIT(RSTSCK_REG_OFFSET, 26U), /*!< external PIN reset flags */ + RCU_FLAG_PORRST = RCU_REGIDX_BIT(RSTSCK_REG_OFFSET, 27U), /*!< power reset flags */ + RCU_FLAG_SWRST = RCU_REGIDX_BIT(RSTSCK_REG_OFFSET, 28U), /*!< software reset flags */ + RCU_FLAG_FWDGTRST = RCU_REGIDX_BIT(RSTSCK_REG_OFFSET, 29U), /*!< FWDGT reset flags */ + RCU_FLAG_WWDGTRST = RCU_REGIDX_BIT(RSTSCK_REG_OFFSET, 30U), /*!< WWDGT reset flags */ + RCU_FLAG_LPRST = RCU_REGIDX_BIT(RSTSCK_REG_OFFSET, 31U), /*!< low-power reset flags */ +}rcu_flag_enum; + +/* clock stabilization and ckm interrupt flags */ +typedef enum +{ + RCU_INT_FLAG_IRC40KSTB = RCU_REGIDX_BIT(INT_REG_OFFSET, 0U), /*!< IRC40K stabilization interrupt flag */ + RCU_INT_FLAG_LXTALSTB = RCU_REGIDX_BIT(INT_REG_OFFSET, 1U), /*!< LXTAL stabilization interrupt flag */ + RCU_INT_FLAG_IRC8MSTB = RCU_REGIDX_BIT(INT_REG_OFFSET, 2U), /*!< IRC8M stabilization interrupt flag */ + RCU_INT_FLAG_HXTALSTB = RCU_REGIDX_BIT(INT_REG_OFFSET, 3U), /*!< HXTAL stabilization interrupt flag */ + RCU_INT_FLAG_PLLSTB = RCU_REGIDX_BIT(INT_REG_OFFSET, 4U), /*!< PLL stabilization interrupt flag */ +#ifdef GD32F10X_CL + RCU_INT_FLAG_PLL1STB = RCU_REGIDX_BIT(INT_REG_OFFSET, 5U), /*!< PLL1 stabilization interrupt flag */ + RCU_INT_FLAG_PLL2STB = RCU_REGIDX_BIT(INT_REG_OFFSET, 6U), /*!< PLL2 stabilization interrupt flag */ +#endif /* GD32F10X_CL */ + RCU_INT_FLAG_CKM = RCU_REGIDX_BIT(INT_REG_OFFSET, 7U), /*!< HXTAL clock stuck interrupt flag */ +}rcu_int_flag_enum; + +/* clock stabilization and stuck interrupt flags clear */ +typedef enum +{ + RCU_INT_FLAG_IRC40KSTB_CLR = RCU_REGIDX_BIT(INT_REG_OFFSET, 16U), /*!< IRC40K stabilization interrupt flags clear */ + RCU_INT_FLAG_LXTALSTB_CLR = RCU_REGIDX_BIT(INT_REG_OFFSET, 17U), /*!< LXTAL stabilization interrupt flags clear */ + RCU_INT_FLAG_IRC8MSTB_CLR = RCU_REGIDX_BIT(INT_REG_OFFSET, 18U), /*!< IRC8M stabilization interrupt flags clear */ + RCU_INT_FLAG_HXTALSTB_CLR = RCU_REGIDX_BIT(INT_REG_OFFSET, 19U), /*!< HXTAL stabilization interrupt flags clear */ + RCU_INT_FLAG_PLLSTB_CLR = RCU_REGIDX_BIT(INT_REG_OFFSET, 20U), /*!< PLL stabilization interrupt flags clear */ +#ifdef GD32F10X_CL + RCU_INT_FLAG_PLL1STB_CLR = RCU_REGIDX_BIT(INT_REG_OFFSET, 21U), /*!< PLL1 stabilization interrupt flags clear */ + RCU_INT_FLAG_PLL2STB_CLR = RCU_REGIDX_BIT(INT_REG_OFFSET, 22U), /*!< PLL2 stabilization interrupt flags clear */ +#endif /* GD32F10X_CL */ + RCU_INT_FLAG_CKM_CLR = RCU_REGIDX_BIT(INT_REG_OFFSET, 23U), /*!< CKM interrupt flags clear */ +}rcu_int_flag_clear_enum; + +/* clock stabilization interrupt enable or disable */ +typedef enum +{ + RCU_INT_IRC40KSTB = RCU_REGIDX_BIT(INT_REG_OFFSET, 8U), /*!< IRC40K stabilization interrupt */ + RCU_INT_LXTALSTB = RCU_REGIDX_BIT(INT_REG_OFFSET, 9U), /*!< LXTAL stabilization interrupt */ + RCU_INT_IRC8MSTB = RCU_REGIDX_BIT(INT_REG_OFFSET, 10U), /*!< IRC8M stabilization interrupt */ + RCU_INT_HXTALSTB = RCU_REGIDX_BIT(INT_REG_OFFSET, 11U), /*!< HXTAL stabilization interrupt */ + RCU_INT_PLLSTB = RCU_REGIDX_BIT(INT_REG_OFFSET, 12U), /*!< PLL stabilization interrupt */ +#ifdef GD32F10X_CL + RCU_INT_PLL1STB = RCU_REGIDX_BIT(INT_REG_OFFSET, 13U), /*!< PLL1 stabilization interrupt */ + RCU_INT_PLL2STB = RCU_REGIDX_BIT(INT_REG_OFFSET, 14U), /*!< PLL2 stabilization interrupt */ +#endif /* GD32F10X_CL */ +}rcu_int_enum; + +/* oscillator types */ +typedef enum +{ + RCU_HXTAL = RCU_REGIDX_BIT(CTL_REG_OFFSET, 16U), /*!< HXTAL */ + RCU_LXTAL = RCU_REGIDX_BIT(BDCTL_REG_OFFSET, 0U), /*!< LXTAL */ + RCU_IRC8M = RCU_REGIDX_BIT(CTL_REG_OFFSET, 0U), /*!< IRC8M */ + RCU_IRC40K = RCU_REGIDX_BIT(RSTSCK_REG_OFFSET, 0U), /*!< IRC40K */ + RCU_PLL_CK = RCU_REGIDX_BIT(CTL_REG_OFFSET, 24U), /*!< PLL */ +#ifdef GD32F10X_CL + RCU_PLL1_CK = RCU_REGIDX_BIT(CTL_REG_OFFSET, 26U), /*!< PLL1 */ + RCU_PLL2_CK = RCU_REGIDX_BIT(CTL_REG_OFFSET, 28U), /*!< PLL2 */ +#endif /* GD32F10X_CL */ +}rcu_osci_type_enum; + +/* rcu clock frequency */ +typedef enum +{ + CK_SYS = 0, /*!< system clock */ + CK_AHB, /*!< AHB clock */ + CK_APB1, /*!< APB1 clock */ + CK_APB2, /*!< APB2 clock */ +}rcu_clock_freq_enum; + +/* RCU_CFG0 register bit define */ +/* system clock source select */ +#define CFG0_SCS(regval) (BITS(0,1) & ((uint32_t)(regval) << 0)) +#define RCU_CKSYSSRC_IRC8M CFG0_SCS(0) /*!< system clock source select IRC8M */ +#define RCU_CKSYSSRC_HXTAL CFG0_SCS(1) /*!< system clock source select HXTAL */ +#define RCU_CKSYSSRC_PLL CFG0_SCS(2) /*!< system clock source select PLL */ + +/* system clock source select status */ +#define CFG0_SCSS(regval) (BITS(2,3) & ((uint32_t)(regval) << 2)) +#define RCU_SCSS_IRC8M CFG0_SCSS(0) /*!< system clock source select IRC8M */ +#define RCU_SCSS_HXTAL CFG0_SCSS(1) /*!< system clock source select HXTAL */ +#define RCU_SCSS_PLL CFG0_SCSS(2) /*!< system clock source select PLLP */ + +/* AHB prescaler selection */ +#define CFG0_AHBPSC(regval) (BITS(4,7) & ((uint32_t)(regval) << 4)) +#define RCU_AHB_CKSYS_DIV1 CFG0_AHBPSC(0) /*!< AHB prescaler select CK_SYS */ +#define RCU_AHB_CKSYS_DIV2 CFG0_AHBPSC(8) /*!< AHB prescaler select CK_SYS/2 */ +#define RCU_AHB_CKSYS_DIV4 CFG0_AHBPSC(9) /*!< AHB prescaler select CK_SYS/4 */ +#define RCU_AHB_CKSYS_DIV8 CFG0_AHBPSC(10) /*!< AHB prescaler select CK_SYS/8 */ +#define RCU_AHB_CKSYS_DIV16 CFG0_AHBPSC(11) /*!< AHB prescaler select CK_SYS/16 */ +#define RCU_AHB_CKSYS_DIV64 CFG0_AHBPSC(12) /*!< AHB prescaler select CK_SYS/64 */ +#define RCU_AHB_CKSYS_DIV128 CFG0_AHBPSC(13) /*!< AHB prescaler select CK_SYS/128 */ +#define RCU_AHB_CKSYS_DIV256 CFG0_AHBPSC(14) /*!< AHB prescaler select CK_SYS/256 */ +#define RCU_AHB_CKSYS_DIV512 CFG0_AHBPSC(15) /*!< AHB prescaler select CK_SYS/512 */ + +/* APB1 prescaler selection */ +#define CFG0_APB1PSC(regval) (BITS(8,10) & ((uint32_t)(regval) << 8)) +#define RCU_APB1_CKAHB_DIV1 CFG0_APB1PSC(0) /*!< APB1 prescaler select CK_AHB */ +#define RCU_APB1_CKAHB_DIV2 CFG0_APB1PSC(4) /*!< APB1 prescaler select CK_AHB/2 */ +#define RCU_APB1_CKAHB_DIV4 CFG0_APB1PSC(5) /*!< APB1 prescaler select CK_AHB/4 */ +#define RCU_APB1_CKAHB_DIV8 CFG0_APB1PSC(6) /*!< APB1 prescaler select CK_AHB/8 */ +#define RCU_APB1_CKAHB_DIV16 CFG0_APB1PSC(7) /*!< APB1 prescaler select CK_AHB/16 */ + +/* APB2 prescaler selection */ +#define CFG0_APB2PSC(regval) (BITS(11,13) & ((uint32_t)(regval) << 11)) +#define RCU_APB2_CKAHB_DIV1 CFG0_APB2PSC(0) /*!< APB2 prescaler select CK_AHB */ +#define RCU_APB2_CKAHB_DIV2 CFG0_APB2PSC(4) /*!< APB2 prescaler select CK_AHB/2 */ +#define RCU_APB2_CKAHB_DIV4 CFG0_APB2PSC(5) /*!< APB2 prescaler select CK_AHB/4 */ +#define RCU_APB2_CKAHB_DIV8 CFG0_APB2PSC(6) /*!< APB2 prescaler select CK_AHB/8 */ +#define RCU_APB2_CKAHB_DIV16 CFG0_APB2PSC(7) /*!< APB2 prescaler select CK_AHB/16 */ + +/* ADC prescaler select */ +#define RCU_CKADC_CKAPB2_DIV2 ((uint32_t)0x00000000U) /*!< ADC prescaler select CK_APB2/2 */ +#define RCU_CKADC_CKAPB2_DIV4 ((uint32_t)0x00000001U) /*!< ADC prescaler select CK_APB2/4 */ +#define RCU_CKADC_CKAPB2_DIV6 ((uint32_t)0x00000002U) /*!< ADC prescaler select CK_APB2/6 */ +#define RCU_CKADC_CKAPB2_DIV8 ((uint32_t)0x00000003U) /*!< ADC prescaler select CK_APB2/8 */ +#define RCU_CKADC_CKAPB2_DIV12 ((uint32_t)0x00000005U) /*!< ADC prescaler select CK_APB2/12 */ +#define RCU_CKADC_CKAPB2_DIV16 ((uint32_t)0x00000007U) /*!< ADC prescaler select CK_APB2/16 */ + +/* PLL clock source selection */ +#define RCU_PLLSRC_IRC8M_DIV2 ((uint32_t)0x00000000U) /*!< IRC8M/2 clock selected as source clock of PLL */ +#define RCU_PLLSRC_HXTAL RCU_CFG0_PLLSEL /*!< HXTAL clock selected as source clock of PLL */ + +/* PLL clock multiplication factor */ +#define PLLMF_4 RCU_CFG0_PLLMF_4 /* bit 4 of PLLMF */ + +#define CFG0_PLLMF(regval) (BITS(18,21) & ((uint32_t)(regval) << 18)) +#define RCU_PLL_MUL2 CFG0_PLLMF(0) /*!< PLL source clock multiply by 2 */ +#define RCU_PLL_MUL3 CFG0_PLLMF(1) /*!< PLL source clock multiply by 3 */ +#define RCU_PLL_MUL4 CFG0_PLLMF(2) /*!< PLL source clock multiply by 4 */ +#define RCU_PLL_MUL5 CFG0_PLLMF(3) /*!< PLL source clock multiply by 5 */ +#define RCU_PLL_MUL6 CFG0_PLLMF(4) /*!< PLL source clock multiply by 6 */ +#define RCU_PLL_MUL7 CFG0_PLLMF(5) /*!< PLL source clock multiply by 7 */ +#define RCU_PLL_MUL8 CFG0_PLLMF(6) /*!< PLL source clock multiply by 8 */ +#define RCU_PLL_MUL9 CFG0_PLLMF(7) /*!< PLL source clock multiply by 9 */ +#define RCU_PLL_MUL10 CFG0_PLLMF(8) /*!< PLL source clock multiply by 10 */ +#define RCU_PLL_MUL11 CFG0_PLLMF(9) /*!< PLL source clock multiply by 11 */ +#define RCU_PLL_MUL12 CFG0_PLLMF(10) /*!< PLL source clock multiply by 12 */ +#define RCU_PLL_MUL13 CFG0_PLLMF(11) /*!< PLL source clock multiply by 13 */ +#define RCU_PLL_MUL14 CFG0_PLLMF(12) /*!< PLL source clock multiply by 14 */ +#if (defined(GD32F10X_MD) || defined(GD32F10X_HD) || defined(GD32F10X_XD)) +#define RCU_PLL_MUL15 CFG0_PLLMF(13) /*!< PLL source clock multiply by 15 */ +#elif defined(GD32F10X_CL) +#define RCU_PLL_MUL6_5 CFG0_PLLMF(13) /*!< PLL source clock multiply by 6.5 */ +#endif /* GD32F10X_MD and GD32F10X_HD and GD32F10X_XD */ +#define RCU_PLL_MUL16 CFG0_PLLMF(14) /*!< PLL source clock multiply by 16 */ +#define RCU_PLL_MUL17 (PLLMF_4 | CFG0_PLLMF(0)) /*!< PLL source clock multiply by 17 */ +#define RCU_PLL_MUL18 (PLLMF_4 | CFG0_PLLMF(1)) /*!< PLL source clock multiply by 18 */ +#define RCU_PLL_MUL19 (PLLMF_4 | CFG0_PLLMF(2)) /*!< PLL source clock multiply by 19 */ +#define RCU_PLL_MUL20 (PLLMF_4 | CFG0_PLLMF(3)) /*!< PLL source clock multiply by 20 */ +#define RCU_PLL_MUL21 (PLLMF_4 | CFG0_PLLMF(4)) /*!< PLL source clock multiply by 21 */ +#define RCU_PLL_MUL22 (PLLMF_4 | CFG0_PLLMF(5)) /*!< PLL source clock multiply by 22 */ +#define RCU_PLL_MUL23 (PLLMF_4 | CFG0_PLLMF(6)) /*!< PLL source clock multiply by 23 */ +#define RCU_PLL_MUL24 (PLLMF_4 | CFG0_PLLMF(7)) /*!< PLL source clock multiply by 24 */ +#define RCU_PLL_MUL25 (PLLMF_4 | CFG0_PLLMF(8)) /*!< PLL source clock multiply by 25 */ +#define RCU_PLL_MUL26 (PLLMF_4 | CFG0_PLLMF(9)) /*!< PLL source clock multiply by 26 */ +#define RCU_PLL_MUL27 (PLLMF_4 | CFG0_PLLMF(10)) /*!< PLL source clock multiply by 27 */ +#define RCU_PLL_MUL28 (PLLMF_4 | CFG0_PLLMF(11)) /*!< PLL source clock multiply by 28 */ +#define RCU_PLL_MUL29 (PLLMF_4 | CFG0_PLLMF(12)) /*!< PLL source clock multiply by 29 */ +#define RCU_PLL_MUL30 (PLLMF_4 | CFG0_PLLMF(13)) /*!< PLL source clock multiply by 30 */ +#define RCU_PLL_MUL31 (PLLMF_4 | CFG0_PLLMF(14)) /*!< PLL source clock multiply by 31 */ +#define RCU_PLL_MUL32 (PLLMF_4 | CFG0_PLLMF(15)) /*!< PLL source clock multiply by 32 */ + +/* USBD/USBFS prescaler select */ +#define CFG0_USBPSC(regval) (BITS(22,23) & ((uint32_t)(regval) << 22)) +#define RCU_CKUSB_CKPLL_DIV1_5 CFG0_USBPSC(0) /*!< USBD/USBFS prescaler select CK_PLL/1.5 */ +#define RCU_CKUSB_CKPLL_DIV1 CFG0_USBPSC(1) /*!< USBD/USBFS prescaler select CK_PLL/1 */ +#define RCU_CKUSB_CKPLL_DIV2_5 CFG0_USBPSC(2) /*!< USBD/USBFS prescaler select CK_PLL/2.5 */ +#define RCU_CKUSB_CKPLL_DIV2 CFG0_USBPSC(3) /*!< USBD/USBFS prescaler select CK_PLL/2 */ + +/* CKOUT0 clock source selection */ +#define CFG0_CKOUT0SEL(regval) (BITS(24,27) & ((uint32_t)(regval) << 24)) +#define RCU_CKOUT0SRC_NONE CFG0_CKOUT0SEL(0) /*!< no clock selected */ +#define RCU_CKOUT0SRC_CKSYS CFG0_CKOUT0SEL(4) /*!< system clock selected */ +#define RCU_CKOUT0SRC_IRC8M CFG0_CKOUT0SEL(5) /*!< internal 8M RC oscillator clock selected */ +#define RCU_CKOUT0SRC_HXTAL CFG0_CKOUT0SEL(6) /*!< high speed crystal oscillator clock (HXTAL) selected */ +#define RCU_CKOUT0SRC_CKPLL_DIV2 CFG0_CKOUT0SEL(7) /*!< CK_PLL/2 clock selected */ +#ifdef GD32F10X_CL +#define RCU_CKOUT0SRC_CKPLL1 CFG0_CKOUT0SEL(8) /*!< CK_PLL1 clock selected */ +#define RCU_CKOUT0SRC_CKPLL2_DIV2 CFG0_CKOUT0SEL(9) /*!< CK_PLL2/2 clock selected */ +#define RCU_CKOUT0SRC_EXT1 CFG0_CKOUT0SEL(10) /*!< EXT1 selected, to provide the external clock for ENET */ +#define RCU_CKOUT0SRC_CKPLL2 CFG0_CKOUT0SEL(11) /*!< CK_PLL2 clock selected */ +#endif /* GD32F10X_CL */ + +/* RTC clock entry selection */ +#define BDCTL_RTCSRC(regval) (BITS(8,9) & ((uint32_t)(regval) << 8)) +#define RCU_RTCSRC_NONE BDCTL_RTCSRC(0) /*!< no clock selected */ +#define RCU_RTCSRC_LXTAL BDCTL_RTCSRC(1) /*!< RTC source clock select LXTAL */ +#define RCU_RTCSRC_IRC40K BDCTL_RTCSRC(2) /*!< RTC source clock select IRC40K */ +#define RCU_RTCSRC_HXTAL_DIV_128 BDCTL_RTCSRC(3) /*!< RTC source clock select HXTAL/128 */ + +/* PREDV0 division factor */ +#define CFG1_PREDV0(regval) (BITS(0,3) & ((uint32_t)(regval) << 0)) +#define RCU_PREDV0_DIV1 CFG1_PREDV0(0) /*!< PREDV0 input source clock not divided */ +#define RCU_PREDV0_DIV2 CFG1_PREDV0(1) /*!< PREDV0 input source clock divided by 2 */ +#define RCU_PREDV0_DIV3 CFG1_PREDV0(2) /*!< PREDV0 input source clock divided by 3 */ +#define RCU_PREDV0_DIV4 CFG1_PREDV0(3) /*!< PREDV0 input source clock divided by 4 */ +#define RCU_PREDV0_DIV5 CFG1_PREDV0(4) /*!< PREDV0 input source clock divided by 5 */ +#define RCU_PREDV0_DIV6 CFG1_PREDV0(5) /*!< PREDV0 input source clock divided by 6 */ +#define RCU_PREDV0_DIV7 CFG1_PREDV0(6) /*!< PREDV0 input source clock divided by 7 */ +#define RCU_PREDV0_DIV8 CFG1_PREDV0(7) /*!< PREDV0 input source clock divided by 8 */ +#define RCU_PREDV0_DIV9 CFG1_PREDV0(8) /*!< PREDV0 input source clock divided by 9 */ +#define RCU_PREDV0_DIV10 CFG1_PREDV0(9) /*!< PREDV0 input source clock divided by 10 */ +#define RCU_PREDV0_DIV11 CFG1_PREDV0(10) /*!< PREDV0 input source clock divided by 11 */ +#define RCU_PREDV0_DIV12 CFG1_PREDV0(11) /*!< PREDV0 input source clock divided by 12 */ +#define RCU_PREDV0_DIV13 CFG1_PREDV0(12) /*!< PREDV0 input source clock divided by 13 */ +#define RCU_PREDV0_DIV14 CFG1_PREDV0(13) /*!< PREDV0 input source clock divided by 14 */ +#define RCU_PREDV0_DIV15 CFG1_PREDV0(14) /*!< PREDV0 input source clock divided by 15 */ +#define RCU_PREDV0_DIV16 CFG1_PREDV0(15) /*!< PREDV0 input source clock divided by 16 */ + +/* PREDV1 division factor */ +#define CFG1_PREDV1(regval) (BITS(4,7) & ((uint32_t)(regval) << 4)) +#define RCU_PREDV1_DIV1 CFG1_PREDV1(0) /*!< PREDV1 input source clock not divided */ +#define RCU_PREDV1_DIV2 CFG1_PREDV1(1) /*!< PREDV1 input source clock divided by 2 */ +#define RCU_PREDV1_DIV3 CFG1_PREDV1(2) /*!< PREDV1 input source clock divided by 3 */ +#define RCU_PREDV1_DIV4 CFG1_PREDV1(3) /*!< PREDV1 input source clock divided by 4 */ +#define RCU_PREDV1_DIV5 CFG1_PREDV1(4) /*!< PREDV1 input source clock divided by 5 */ +#define RCU_PREDV1_DIV6 CFG1_PREDV1(5) /*!< PREDV1 input source clock divided by 6 */ +#define RCU_PREDV1_DIV7 CFG1_PREDV1(6) /*!< PREDV1 input source clock divided by 7 */ +#define RCU_PREDV1_DIV8 CFG1_PREDV1(7) /*!< PREDV1 input source clock divided by 8 */ +#define RCU_PREDV1_DIV9 CFG1_PREDV1(8) /*!< PREDV1 input source clock divided by 9 */ +#define RCU_PREDV1_DIV10 CFG1_PREDV1(9) /*!< PREDV1 input source clock divided by 10 */ +#define RCU_PREDV1_DIV11 CFG1_PREDV1(10) /*!< PREDV1 input source clock divided by 11 */ +#define RCU_PREDV1_DIV12 CFG1_PREDV1(11) /*!< PREDV1 input source clock divided by 12 */ +#define RCU_PREDV1_DIV13 CFG1_PREDV1(12) /*!< PREDV1 input source clock divided by 13 */ +#define RCU_PREDV1_DIV14 CFG1_PREDV1(13) /*!< PREDV1 input source clock divided by 14 */ +#define RCU_PREDV1_DIV15 CFG1_PREDV1(14) /*!< PREDV1 input source clock divided by 15 */ +#define RCU_PREDV1_DIV16 CFG1_PREDV1(15) /*!< PREDV1 input source clock divided by 16 */ + +/* PLL1 clock multiplication factor */ +#define CFG1_PLL1MF(regval) (BITS(8,11) & ((uint32_t)(regval) << 8)) +#define RCU_PLL1_MUL8 CFG1_PLL1MF(6) /*!< PLL1 source clock multiply by 8 */ +#define RCU_PLL1_MUL9 CFG1_PLL1MF(7) /*!< PLL1 source clock multiply by 9 */ +#define RCU_PLL1_MUL10 CFG1_PLL1MF(8) /*!< PLL1 source clock multiply by 10 */ +#define RCU_PLL1_MUL11 CFG1_PLL1MF(9) /*!< PLL1 source clock multiply by 11 */ +#define RCU_PLL1_MUL12 CFG1_PLL1MF(10) /*!< PLL1 source clock multiply by 12 */ +#define RCU_PLL1_MUL13 CFG1_PLL1MF(11) /*!< PLL1 source clock multiply by 13 */ +#define RCU_PLL1_MUL14 CFG1_PLL1MF(12) /*!< PLL1 source clock multiply by 14 */ +#define RCU_PLL1_MUL15 CFG1_PLL1MF(13) /*!< PLL1 source clock multiply by 15 */ +#define RCU_PLL1_MUL16 CFG1_PLL1MF(14) /*!< PLL1 source clock multiply by 16 */ +#define RCU_PLL1_MUL20 CFG1_PLL1MF(15) /*!< PLL1 source clock multiply by 20 */ + +/* PLL2 clock multiplication factor */ +#define CFG1_PLL2MF(regval) (BITS(12,15) & ((uint32_t)(regval) << 12)) +#define RCU_PLL2_MUL8 CFG1_PLL2MF(6) /*!< PLL2 source clock multiply by 8 */ +#define RCU_PLL2_MUL9 CFG1_PLL2MF(7) /*!< PLL2 source clock multiply by 9 */ +#define RCU_PLL2_MUL10 CFG1_PLL2MF(8) /*!< PLL2 source clock multiply by 10 */ +#define RCU_PLL2_MUL11 CFG1_PLL2MF(9) /*!< PLL2 source clock multiply by 11 */ +#define RCU_PLL2_MUL12 CFG1_PLL2MF(10) /*!< PLL2 source clock multiply by 12 */ +#define RCU_PLL2_MUL13 CFG1_PLL2MF(11) /*!< PLL2 source clock multiply by 13 */ +#define RCU_PLL2_MUL14 CFG1_PLL2MF(12) /*!< PLL2 source clock multiply by 14 */ +#define RCU_PLL2_MUL15 CFG1_PLL2MF(13) /*!< PLL2 source clock multiply by 15 */ +#define RCU_PLL2_MUL16 CFG1_PLL2MF(14) /*!< PLL2 source clock multiply by 16 */ +#define RCU_PLL2_MUL20 CFG1_PLL2MF(15) /*!< PLL2 source clock multiply by 20 */ + +#ifdef GD32F10X_CL +/* PREDV0 input clock source selection */ +#define RCU_PREDV0SRC_HXTAL ((uint32_t)0x00000000U) /*!< HXTAL selected as PREDV0 input source clock */ +#define RCU_PREDV0SRC_CKPLL1 RCU_CFG1_PREDV0SEL /*!< CK_PLL1 selected as PREDV0 input source clock */ + +/* I2S1 clock source selection */ +#define RCU_I2S1SRC_CKSYS ((uint32_t)0x00000000U) /*!< system clock selected as I2S1 source clock */ +#define RCU_I2S1SRC_CKPLL2_MUL2 RCU_CFG1_I2S1SEL /*!< (CK_PLL2 x 2) selected as I2S1 source clock */ + +/* I2S2 clock source selection */ +#define RCU_I2S2SRC_CKSYS ((uint32_t)0x00000000U) /*!< system clock selected as I2S2 source clock */ +#define RCU_I2S2SRC_CKPLL2_MUL2 RCU_CFG1_I2S2SEL /*!< (CK_PLL2 x 2) selected as I2S2 source clock */ +#endif /* GD32F10X_CL */ + +/* deep-sleep mode voltage */ +#define DSV_DSLPVS(regval) (BITS(0,2) & ((uint32_t)(regval) << 0)) +#define RCU_DEEPSLEEP_V_1_2 DSV_DSLPVS(0) /*!< core voltage is 1.2V in deep-sleep mode */ +#define RCU_DEEPSLEEP_V_1_1 DSV_DSLPVS(1) /*!< core voltage is 1.1V in deep-sleep mode */ +#define RCU_DEEPSLEEP_V_1_0 DSV_DSLPVS(2) /*!< core voltage is 1.0V in deep-sleep mode */ +#define RCU_DEEPSLEEP_V_0_9 DSV_DSLPVS(3) /*!< core voltage is 0.9V in deep-sleep mode */ + +/* function declarations */ +/* initialization, peripheral clock enable/disable functions */ +/* deinitialize the RCU */ +void rcu_deinit(void); +/* enable the peripherals clock */ +void rcu_periph_clock_enable(rcu_periph_enum periph); +/* disable the peripherals clock */ +void rcu_periph_clock_disable(rcu_periph_enum periph); +/* enable the peripherals clock when sleep mode */ +void rcu_periph_clock_sleep_enable(rcu_periph_sleep_enum periph); +/* disable the peripherals clock when sleep mode */ +void rcu_periph_clock_sleep_disable(rcu_periph_sleep_enum periph); +/* reset the peripherals */ +void rcu_periph_reset_enable(rcu_periph_reset_enum periph_reset); +/* disable reset the peripheral */ +void rcu_periph_reset_disable(rcu_periph_reset_enum periph_reset); +/* reset the BKP domain */ +void rcu_bkp_reset_enable(void); +/* disable the BKP domain reset */ +void rcu_bkp_reset_disable(void); + +/* clock configuration functions */ +/* configure the system clock source */ +void rcu_system_clock_source_config(uint32_t ck_sys); +/* get the system clock source */ +uint32_t rcu_system_clock_source_get(void); +/* configure the AHB prescaler selection */ +void rcu_ahb_clock_config(uint32_t ck_ahb); +/* configure the APB1 prescaler selection */ +void rcu_apb1_clock_config(uint32_t ck_apb1); +/* configure the APB2 prescaler selection */ +void rcu_apb2_clock_config(uint32_t ck_apb2); +/* configure the CK_OUT0 clock source and divider */ +void rcu_ckout0_config(uint32_t ckout0_src); +/* configure the PLL clock source selection and PLL multiply factor */ +void rcu_pll_config(uint32_t pll_src, uint32_t pll_mul); +#if (defined(GD32F10X_MD) || defined(GD32F10X_HD) || defined(GD32F10X_XD)) +/* configure the PREDV0 division factor and clock source */ +void rcu_predv0_config(uint32_t predv0_div); +#elif defined(GD32F10X_CL) +/* configure the PREDV0 division factor and clock source */ +void rcu_predv0_config(uint32_t predv0_source, uint32_t predv0_div); +/* configure the PREDV1 division factor */ +void rcu_predv1_config(uint32_t predv1_div); +/* configure the PLL1 clock */ +void rcu_pll1_config(uint32_t pll_mul); +/* configure the PLL2 clock */ +void rcu_pll2_config(uint32_t pll_mul); +#endif /* GD32F10X_MD and GD32F10X_HD and GD32F10X_XD */ + +/* peripheral clock configuration functions */ +/* configure the ADC division factor */ +void rcu_adc_clock_config(uint32_t adc_psc); +/* configure the USBD/USBFS prescaler factor */ +void rcu_usb_clock_config(uint32_t usb_psc); +/* configure the RTC clock source selection */ +void rcu_rtc_clock_config(uint32_t rtc_clock_source); +#ifdef GD32F10X_CL +/* configure the I2S1 clock source selection */ +void rcu_i2s1_clock_config(uint32_t i2s_clock_source); +/* configure the I2S2 clock source selection */ +void rcu_i2s2_clock_config(uint32_t i2s_clock_source); +#endif /* GD32F10X_CL */ + +/* interrupt & flag functions */ +/* get the clock stabilization and periphral reset flags */ +FlagStatus rcu_flag_get(rcu_flag_enum flag); +/* clear the reset flag */ +void rcu_all_reset_flag_clear(void); +/* get the clock stabilization interrupt and ckm flags */ +FlagStatus rcu_interrupt_flag_get(rcu_int_flag_enum int_flag); +/* clear the interrupt flags */ +void rcu_interrupt_flag_clear(rcu_int_flag_clear_enum int_flag_clear); +/* enable the stabilization interrupt */ +void rcu_interrupt_enable(rcu_int_enum stab_int); +/* disable the stabilization interrupt */ +void rcu_interrupt_disable(rcu_int_enum stab_int); + +/* oscillator configuration functions */ +/* wait for oscillator stabilization flags is SET or oscillator startup is timeout */ +ErrStatus rcu_osci_stab_wait(rcu_osci_type_enum osci); +/* turn on the oscillator */ +void rcu_osci_on(rcu_osci_type_enum osci); +/* turn off the oscillator */ +void rcu_osci_off(rcu_osci_type_enum osci); +/* enable the oscillator bypass mode, HXTALEN or LXTALEN must be reset before it */ +void rcu_osci_bypass_mode_enable(rcu_osci_type_enum osci); +/* disable the oscillator bypass mode, HXTALEN or LXTALEN must be reset before it */ +void rcu_osci_bypass_mode_disable(rcu_osci_type_enum osci); +/* enable the HXTAL clock monitor */ +void rcu_hxtal_clock_monitor_enable(void); +/* disable the HXTAL clock monitor */ +void rcu_hxtal_clock_monitor_disable(void); + +/* set the IRC8M adjust value */ +void rcu_irc8m_adjust_value_set(uint8_t irc8m_adjval); +/* set the deep sleep mode voltage */ +void rcu_deepsleep_voltage_set(uint32_t dsvol); + +/* get the system clock, bus and peripheral clock frequency */ +uint32_t rcu_clock_freq_get(rcu_clock_freq_enum clock); + +#endif /* GD32F10X_RCU_H */ diff --git a/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_standard_peripheral/Include/gd32f10x_rtc.h b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_standard_peripheral/Include/gd32f10x_rtc.h new file mode 100644 index 0000000000..7a7e8d65a1 --- /dev/null +++ b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_standard_peripheral/Include/gd32f10x_rtc.h @@ -0,0 +1,151 @@ +/*! + \file gd32f10x_rtc.h + \brief definitions for the RTC + + \version 2014-12-26, V1.0.0, firmware for GD32F10x + \version 2017-06-20, V2.0.0, firmware for GD32F10x + \version 2018-07-31, V2.1.0, firmware for GD32F10x + \version 2020-09-30, V2.2.0, firmware for GD32F10x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef GD32F10X_RTC_H +#define GD32F10X_RTC_H + +#include "gd32f10x.h" + +/* RTC definitions */ +#define RTC RTC_BASE + +/* registers definitions */ +#define RTC_INTEN REG32(RTC + 0x00U) /*!< interrupt enable register */ +#define RTC_CTL REG32(RTC + 0x04U) /*!< control register */ +#define RTC_PSCH REG32(RTC + 0x08U) /*!< prescaler high register */ +#define RTC_PSCL REG32(RTC + 0x0CU) /*!< prescaler low register */ +#define RTC_DIVH REG32(RTC + 0x10U) /*!< divider high register */ +#define RTC_DIVL REG32(RTC + 0x14U) /*!< divider low register */ +#define RTC_CNTH REG32(RTC + 0x18U) /*!< counter high register */ +#define RTC_CNTL REG32(RTC + 0x1CU) /*!< counter low register */ +#define RTC_ALRMH REG32(RTC + 0x20U) /*!< alarm high register */ +#define RTC_ALRML REG32(RTC + 0x24U) /*!< alarm low register */ + +/* bits definitions */ +/* RTC_INTEN */ +#define RTC_INTEN_SCIE BIT(0) /*!< second interrupt enable */ +#define RTC_INTEN_ALRMIE BIT(1) /*!< alarm interrupt enable */ +#define RTC_INTEN_OVIE BIT(2) /*!< overflow interrupt enable */ + +/* RTC_CTL */ +#define RTC_CTL_SCIF BIT(0) /*!< second interrupt flag */ +#define RTC_CTL_ALRMIF BIT(1) /*!< alarm interrupt flag */ +#define RTC_CTL_OVIF BIT(2) /*!< overflow interrupt flag */ +#define RTC_CTL_RSYNF BIT(3) /*!< registers synchronized flag */ +#define RTC_CTL_CMF BIT(4) /*!< configuration mode flag */ +#define RTC_CTL_LWOFF BIT(5) /*!< last write operation finished flag */ + +/* RTC_PSCH */ +#define RTC_PSCH_PSC BITS(0,3) /*!< prescaler high value */ + +/* RTC_PSCL */ +#define RTC_PSCL_PSC BITS(0,15) /*!< prescaler low value */ + +/* RTC_DIVH */ +#define RTC_DIVH_DIV BITS(0,3) /*!< divider high value */ + +/* RTC_DIVL */ +#define RTC_DIVL_DIV BITS(0,15) /*!< divider low value */ + +/* RTC_CNTH */ +#define RTC_CNTH_CNT BITS(0,15) /*!< counter high value */ + +/* RTC_CNTL */ +#define RTC_CNTL_CNT BITS(0,15) /*!< counter low value */ + +/* RTC_ALRMH */ +#define RTC_ALRMH_ALRM BITS(0,15) /*!< alarm high value */ + +/* RTC_ALRML */ +#define RTC_ALRML_ALRM BITS(0,15) /*!< alarm low value */ + +/* constants definitions */ +/* RTC interrupt enable or disable definitions */ +#define RTC_INT_SECOND RTC_INTEN_SCIE /*!< second interrupt enable */ +#define RTC_INT_ALARM RTC_INTEN_ALRMIE /*!< alarm interrupt enable */ +#define RTC_INT_OVERFLOW RTC_INTEN_OVIE /*!< overflow interrupt enable */ + +/* RTC interrupt flag definitions */ +#define RTC_INT_FLAG_SECOND RTC_CTL_SCIF /*!< second interrupt flag */ +#define RTC_INT_FLAG_ALARM RTC_CTL_ALRMIF /*!< alarm interrupt flag */ +#define RTC_INT_FLAG_OVERFLOW RTC_CTL_OVIF /*!< overflow interrupt flag */ + +/* RTC flag definitions */ +#define RTC_FLAG_SECOND RTC_CTL_SCIF /*!< second interrupt flag */ +#define RTC_FLAG_ALARM RTC_CTL_ALRMIF /*!< alarm interrupt flag */ +#define RTC_FLAG_OVERFLOW RTC_CTL_OVIF /*!< overflow interrupt flag */ +#define RTC_FLAG_RSYN RTC_CTL_RSYNF /*!< registers synchronized flag */ +#define RTC_FLAG_LWOF RTC_CTL_LWOFF /*!< last write operation finished flag */ + +/* function declarations */ +/* initialization functions */ +/* enter RTC configuration mode */ +void rtc_configuration_mode_enter(void); +/* exit RTC configuration mode */ +void rtc_configuration_mode_exit(void); +/* set RTC counter value */ +void rtc_counter_set(uint32_t cnt); +/* set RTC prescaler value */ +void rtc_prescaler_set(uint32_t psc); + +/* operation functions */ +/* wait RTC last write operation finished flag set */ +void rtc_lwoff_wait(void); +/* wait RTC registers synchronized flag set */ +void rtc_register_sync_wait(void); +/* set RTC alarm value */ +void rtc_alarm_config(uint32_t alarm); +/* get RTC counter value */ +uint32_t rtc_counter_get(void); +/* get RTC divider value */ +uint32_t rtc_divider_get(void); + +/* flag & interrupt functions */ +/* get RTC flag status */ +FlagStatus rtc_flag_get(uint32_t flag); +/* clear RTC flag status */ +void rtc_flag_clear(uint32_t flag); +/* get RTC interrupt flag status */ +FlagStatus rtc_interrupt_flag_get(uint32_t flag); +/* clear RTC interrupt flag status */ +void rtc_interrupt_flag_clear(uint32_t flag); +/* enable RTC interrupt */ +void rtc_interrupt_enable(uint32_t interrupt); +/* disable RTC interrupt */ +void rtc_interrupt_disable(uint32_t interrupt); + +#endif /* GD32F10X_RTC_H */ diff --git a/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_standard_peripheral/Include/gd32f10x_sdio.h b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_standard_peripheral/Include/gd32f10x_sdio.h new file mode 100644 index 0000000000..4cb178ad70 --- /dev/null +++ b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_standard_peripheral/Include/gd32f10x_sdio.h @@ -0,0 +1,429 @@ +/*! + \file gd32f10x_sdio.h + \brief definitions for the SDIO + + \version 2014-12-26, V1.0.0, firmware for GD32F10x + \version 2017-06-20, V2.0.0, firmware for GD32F10x + \version 2018-07-31, V2.1.0, firmware for GD32F10x + \version 2020-09-30, V2.2.0, firmware for GD32F10x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef GD32F10X_SDIO_H +#define GD32F10X_SDIO_H + +#include "gd32f10x.h" + +/* SDIO definitions */ +#define SDIO SDIO_BASE + +/* registers definitions */ +#define SDIO_PWRCTL REG32(SDIO + 0x00U) /*!< SDIO power control register */ +#define SDIO_CLKCTL REG32(SDIO + 0x04U) /*!< SDIO clock control register */ +#define SDIO_CMDAGMT REG32(SDIO + 0x08U) /*!< SDIO command argument register */ +#define SDIO_CMDCTL REG32(SDIO + 0x0CU) /*!< SDIO command control register */ +#define SDIO_RSPCMDIDX REG32(SDIO + 0x10U) /*!< SDIO command index response register */ +#define SDIO_RESP0 REG32(SDIO + 0x14U) /*!< SDIO response register 0 */ +#define SDIO_RESP1 REG32(SDIO + 0x18U) /*!< SDIO response register 1 */ +#define SDIO_RESP2 REG32(SDIO + 0x1CU) /*!< SDIO response register 2 */ +#define SDIO_RESP3 REG32(SDIO + 0x20U) /*!< SDIO response register 3 */ +#define SDIO_DATATO REG32(SDIO + 0x24U) /*!< SDIO data timeout register */ +#define SDIO_DATALEN REG32(SDIO + 0x28U) /*!< SDIO data length register */ +#define SDIO_DATACTL REG32(SDIO + 0x2CU) /*!< SDIO data control register */ +#define SDIO_DATACNT REG32(SDIO + 0x30U) /*!< SDIO data counter register */ +#define SDIO_STAT REG32(SDIO + 0x34U) /*!< SDIO status register */ +#define SDIO_INTC REG32(SDIO + 0x38U) /*!< SDIO interrupt clear register */ +#define SDIO_INTEN REG32(SDIO + 0x3CU) /*!< SDIO interrupt enable register */ +#define SDIO_FIFOCNT REG32(SDIO + 0x48U) /*!< SDIO FIFO counter register */ +#define SDIO_FIFO REG32(SDIO + 0x80U) /*!< SDIO FIFO data register */ + +/* bits definitions */ +/* SDIO_PWRCTL */ +#define SDIO_PWRCTL_PWRCTL BITS(0,1) /*!< SDIO power control bits */ + +/* SDIO_CLKCTL */ +#define SDIO_CLKCTL_DIV BITS(0,7) /*!< clock division */ +#define SDIO_CLKCTL_CLKEN BIT(8) /*!< SDIO_CLK clock output enable bit */ +#define SDIO_CLKCTL_CLKPWRSAV BIT(9) /*!< SDIO_CLK clock dynamic switch on/off for power saving */ +#define SDIO_CLKCTL_CLKBYP BIT(10) /*!< clock bypass enable bit */ +#define SDIO_CLKCTL_BUSMODE BITS(11,12) /*!< SDIO card bus mode control bit */ +#define SDIO_CLKCTL_CLKEDGE BIT(13) /*!< SDIO_CLK clock edge selection bit */ +#define SDIO_CLKCTL_HWCLKEN BIT(14) /*!< hardware clock control enable bit */ + +/* SDIO_CMDAGMT */ +#define SDIO_CMDAGMT_CMDAGMT BITS(0,31) /*!< SDIO card command argument */ + +/* SDIO_CMDCTL */ +#define SDIO_CMDCTL_CMDIDX BITS(0,5) /*!< command index */ +#define SDIO_CMDCTL_CMDRESP BITS(6,7) /*!< command response type bits */ +#define SDIO_CMDCTL_INTWAIT BIT(8) /*!< interrupt wait instead of timeout */ +#define SDIO_CMDCTL_WAITDEND BIT(9) /*!< wait for ends of data transfer */ +#define SDIO_CMDCTL_CSMEN BIT(10) /*!< command state machine(CSM) enable bit */ +#define SDIO_CMDCTL_SUSPEND BIT(11) /*!< SD I/O suspend command(SD I/O only) */ +#define SDIO_CMDCTL_ENCMDC BIT(12) /*!< CMD completion signal enabled (CE-ATA only) */ +#define SDIO_CMDCTL_NINTEN BIT(13) /*!< no CE-ATA interrupt (CE-ATA only) */ +#define SDIO_CMDCTL_ATAEN BIT(14) /*!< CE-ATA command enable(CE-ATA only) */ + +/* SDIO_DATATO */ +#define SDIO_DATATO_DATATO BITS(0,31) /*!< data timeout period */ + +/* SDIO_DATALEN */ +#define SDIO_DATALEN_DATALEN BITS(0,24) /*!< data transfer length */ + +/* SDIO_DATACTL */ +#define SDIO_DATACTL_DATAEN BIT(0) /*!< data transfer enabled bit */ +#define SDIO_DATACTL_DATADIR BIT(1) /*!< data transfer direction */ +#define SDIO_DATACTL_TRANSMOD BIT(2) /*!< data transfer mode */ +#define SDIO_DATACTL_DMAEN BIT(3) /*!< DMA enable bit */ +#define SDIO_DATACTL_BLKSZ BITS(4,7) /*!< data block size */ +#define SDIO_DATACTL_RWEN BIT(8) /*!< read wait mode enabled(SD I/O only) */ +#define SDIO_DATACTL_RWSTOP BIT(9) /*!< read wait stop(SD I/O only) */ +#define SDIO_DATACTL_RWTYPE BIT(10) /*!< read wait type(SD I/O only) */ +#define SDIO_DATACTL_IOEN BIT(11) /*!< SD I/O specific function enable(SD I/O only) */ + +/* SDIO_STAT */ +#define SDIO_STAT_CCRCERR BIT(0) /*!< command response received (CRC check failed) */ +#define SDIO_STAT_DTCRCERR BIT(1) /*!< data block sent/received (CRC check failed) */ +#define SDIO_STAT_CMDTMOUT BIT(2) /*!< command response timeout */ +#define SDIO_STAT_DTTMOUT BIT(3) /*!< data timeout */ +#define SDIO_STAT_TXURE BIT(4) /*!< transmit FIFO underrun error occurs */ +#define SDIO_STAT_RXORE BIT(5) /*!< received FIFO overrun error occurs */ +#define SDIO_STAT_CMDRECV BIT(6) /*!< command response received (CRC check passed) */ +#define SDIO_STAT_CMDSEND BIT(7) /*!< command sent (no response required) */ +#define SDIO_STAT_DTEND BIT(8) /*!< data end (data counter, SDIO_DATACNT, is zero) */ +#define SDIO_STAT_STBITE BIT(9) /*!< start bit error in the bus */ +#define SDIO_STAT_DTBLKEND BIT(10) /*!< data block sent/received (CRC check passed) */ +#define SDIO_STAT_CMDRUN BIT(11) /*!< command transmission in progress */ +#define SDIO_STAT_TXRUN BIT(12) /*!< data transmission in progress */ +#define SDIO_STAT_RXRUN BIT(13) /*!< data reception in progress */ +#define SDIO_STAT_TFH BIT(14) /*!< transmit FIFO is half empty: at least 8 words can be written into the FIFO */ +#define SDIO_STAT_RFH BIT(15) /*!< receive FIFO is half full: at least 8 words can be read in the FIFO */ +#define SDIO_STAT_TFF BIT(16) /*!< transmit FIFO is full */ +#define SDIO_STAT_RFF BIT(17) /*!< receive FIFO is full */ +#define SDIO_STAT_TFE BIT(18) /*!< transmit FIFO is empty */ +#define SDIO_STAT_RFE BIT(19) /*!< receive FIFO is empty */ +#define SDIO_STAT_TXDTVAL BIT(20) /*!< data is valid in transmit FIFO */ +#define SDIO_STAT_RXDTVAL BIT(21) /*!< data is valid in receive FIFO */ +#define SDIO_STAT_SDIOINT BIT(22) /*!< SD I/O interrupt received */ +#define SDIO_STAT_ATAEND BIT(23) /*!< CE-ATA command completion signal received (only for CMD61) */ + +/* SDIO_INTC */ +#define SDIO_INTC_CCRCERRC BIT(0) /*!< CCRCERR flag clear bit */ +#define SDIO_INTC_DTCRCERRC BIT(1) /*!< DTCRCERR flag clear bit */ +#define SDIO_INTC_CMDTMOUTC BIT(2) /*!< CMDTMOUT flag clear bit */ +#define SDIO_INTC_DTTMOUTC BIT(3) /*!< DTTMOUT flag clear bit */ +#define SDIO_INTC_TXUREC BIT(4) /*!< TXURE flag clear bit */ +#define SDIO_INTC_RXOREC BIT(5) /*!< RXORE flag clear bit */ +#define SDIO_INTC_CMDRECVC BIT(6) /*!< CMDRECV flag clear bit */ +#define SDIO_INTC_CMDSENDC BIT(7) /*!< CMDSEND flag clear bit */ +#define SDIO_INTC_DTENDC BIT(8) /*!< DTEND flag clear bit */ +#define SDIO_INTC_STBITEC BIT(9) /*!< STBITE flag clear bit */ +#define SDIO_INTC_DTBLKENDC BIT(10) /*!< DTBLKEND flag clear bit */ +#define SDIO_INTC_SDIOINTC BIT(22) /*!< SDIOINT flag clear bit */ +#define SDIO_INTC_ATAENDC BIT(23) /*!< ATAEND flag clear bit */ + +/* SDIO_INTEN */ +#define SDIO_INTEN_CCRCERRIE BIT(0) /*!< command response CRC fail interrupt enable */ +#define SDIO_INTEN_DTCRCERRIE BIT(1) /*!< data CRC fail interrupt enable */ +#define SDIO_INTEN_CMDTMOUTIE BIT(2) /*!< command response timeout interrupt enable */ +#define SDIO_INTEN_DTTMOUTIE BIT(3) /*!< data timeout interrupt enable */ +#define SDIO_INTEN_TXUREIE BIT(4) /*!< transmit FIFO underrun error interrupt enable */ +#define SDIO_INTEN_RXOREIE BIT(5) /*!< received FIFO overrun error interrupt enable */ +#define SDIO_INTEN_CMDRECVIE BIT(6) /*!< command response received interrupt enable */ +#define SDIO_INTEN_CMDSENDIE BIT(7) /*!< command sent interrupt enable */ +#define SDIO_INTEN_DTENDIE BIT(8) /*!< data end interrupt enable */ +#define SDIO_INTEN_STBITEIE BIT(9) /*!< start bit error interrupt enable */ +#define SDIO_INTEN_DTBLKENDIE BIT(10) /*!< data block end interrupt enable */ +#define SDIO_INTEN_CMDRUNIE BIT(11) /*!< command transmission interrupt enable */ +#define SDIO_INTEN_TXRUNIE BIT(12) /*!< data transmission interrupt enable */ +#define SDIO_INTEN_RXRUNIE BIT(13) /*!< data reception interrupt enable */ +#define SDIO_INTEN_TFHIE BIT(14) /*!< transmit FIFO half empty interrupt enable */ +#define SDIO_INTEN_RFHIE BIT(15) /*!< receive FIFO half full interrupt enable */ +#define SDIO_INTEN_TFFIE BIT(16) /*!< transmit FIFO full interrupt enable */ +#define SDIO_INTEN_RFFIE BIT(17) /*!< receive FIFO full interrupt enable */ +#define SDIO_INTEN_TFEIE BIT(18) /*!< transmit FIFO empty interrupt enable */ +#define SDIO_INTEN_RFEIE BIT(19) /*!< receive FIFO empty interrupt enable */ +#define SDIO_INTEN_TXDTVALIE BIT(20) /*!< data valid in transmit FIFO interrupt enable */ +#define SDIO_INTEN_RXDTVALIE BIT(21) /*!< data valid in receive FIFO interrupt enable */ +#define SDIO_INTEN_SDIOINTIE BIT(22) /*!< SD I/O interrupt received interrupt enable */ +#define SDIO_INTEN_ATAENDIE BIT(23) /*!< CE-ATA command completion signal received interrupt enable */ + +/* SDIO_FIFO */ +#define SDIO_FIFO_FIFODT BITS(0,31) /*!< receive FIFO data or transmit FIFO data */ + +/* constants definitions */ +/* SDIO flags */ +#define SDIO_FLAG_CCRCERR BIT(0) /*!< command response received (CRC check failed) flag */ +#define SDIO_FLAG_DTCRCERR BIT(1) /*!< data block sent/received (CRC check failed) flag */ +#define SDIO_FLAG_CMDTMOUT BIT(2) /*!< command response timeout flag */ +#define SDIO_FLAG_DTTMOUT BIT(3) /*!< data timeout flag */ +#define SDIO_FLAG_TXURE BIT(4) /*!< transmit FIFO underrun error occurs flag */ +#define SDIO_FLAG_RXORE BIT(5) /*!< received FIFO overrun error occurs flag */ +#define SDIO_FLAG_CMDRECV BIT(6) /*!< command response received (CRC check passed) flag */ +#define SDIO_FLAG_CMDSEND BIT(7) /*!< command sent (no response required) flag */ +#define SDIO_FLAG_DTEND BIT(8) /*!< data end (data counter, SDIO_DATACNT, is zero) flag */ +#define SDIO_FLAG_STBITE BIT(9) /*!< start bit error in the bus flag */ +#define SDIO_FLAG_DTBLKEND BIT(10) /*!< data block sent/received (CRC check passed) flag */ +#define SDIO_FLAG_CMDRUN BIT(11) /*!< command transmission in progress flag */ +#define SDIO_FLAG_TXRUN BIT(12) /*!< data transmission in progress flag */ +#define SDIO_FLAG_RXRUN BIT(13) /*!< data reception in progress flag */ +#define SDIO_FLAG_TFH BIT(14) /*!< transmit FIFO is half empty flag: at least 8 words can be written into the FIFO */ +#define SDIO_FLAG_RFH BIT(15) /*!< receive FIFO is half full flag: at least 8 words can be read in the FIFO */ +#define SDIO_FLAG_TFF BIT(16) /*!< transmit FIFO is full flag */ +#define SDIO_FLAG_RFF BIT(17) /*!< receive FIFO is full flag */ +#define SDIO_FLAG_TFE BIT(18) /*!< transmit FIFO is empty flag */ +#define SDIO_FLAG_RFE BIT(19) /*!< receive FIFO is empty flag */ +#define SDIO_FLAG_TXDTVAL BIT(20) /*!< data is valid in transmit FIFO flag */ +#define SDIO_FLAG_RXDTVAL BIT(21) /*!< data is valid in receive FIFO flag */ +#define SDIO_FLAG_SDIOINT BIT(22) /*!< SD I/O interrupt received flag */ +#define SDIO_FLAG_ATAEND BIT(23) /*!< CE-ATA command completion signal received (only for CMD61) flag */ + +/* SDIO interrupt enable or disable */ +#define SDIO_INT_CCRCERR BIT(0) /*!< SDIO CCRCERR interrupt */ +#define SDIO_INT_DTCRCERR BIT(1) /*!< SDIO DTCRCERR interrupt */ +#define SDIO_INT_CMDTMOUT BIT(2) /*!< SDIO CMDTMOUT interrupt */ +#define SDIO_INT_DTTMOUT BIT(3) /*!< SDIO DTTMOUT interrupt */ +#define SDIO_INT_TXURE BIT(4) /*!< SDIO TXURE interrupt */ +#define SDIO_INT_RXORE BIT(5) /*!< SDIO RXORE interrupt */ +#define SDIO_INT_CMDRECV BIT(6) /*!< SDIO CMDRECV interrupt */ +#define SDIO_INT_CMDSEND BIT(7) /*!< SDIO CMDSEND interrupt */ +#define SDIO_INT_DTEND BIT(8) /*!< SDIO DTEND interrupt */ +#define SDIO_INT_STBITE BIT(9) /*!< SDIO STBITE interrupt */ +#define SDIO_INT_DTBLKEND BIT(10) /*!< SDIO DTBLKEND interrupt */ +#define SDIO_INT_CMDRUN BIT(11) /*!< SDIO CMDRUN interrupt */ +#define SDIO_INT_TXRUN BIT(12) /*!< SDIO TXRUN interrupt */ +#define SDIO_INT_RXRUN BIT(13) /*!< SDIO RXRUN interrupt */ +#define SDIO_INT_TFH BIT(14) /*!< SDIO TFH interrupt */ +#define SDIO_INT_RFH BIT(15) /*!< SDIO RFH interrupt */ +#define SDIO_INT_TFF BIT(16) /*!< SDIO TFF interrupt */ +#define SDIO_INT_RFF BIT(17) /*!< SDIO RFF interrupt */ +#define SDIO_INT_TFE BIT(18) /*!< SDIO TFE interrupt */ +#define SDIO_INT_RFE BIT(19) /*!< SDIO RFE interrupt */ +#define SDIO_INT_TXDTVAL BIT(20) /*!< SDIO TXDTVAL interrupt */ +#define SDIO_INT_RXDTVAL BIT(21) /*!< SDIO RXDTVAL interrupt */ +#define SDIO_INT_SDIOINT BIT(22) /*!< SDIO SDIOINT interrupt */ +#define SDIO_INT_ATAEND BIT(23) /*!< SDIO ATAEND interrupt */ + +/* SDIO interrupt flags */ +#define SDIO_INT_FLAG_CCRCERR BIT(0) /*!< SDIO CCRCERR interrupt */ +#define SDIO_INT_FLAG_DTCRCERR BIT(1) /*!< SDIO DTCRCERR interrupt */ +#define SDIO_INT_FLAG_CMDTMOUT BIT(2) /*!< SDIO CMDTMOUT interrupt */ +#define SDIO_INT_FLAG_DTTMOUT BIT(3) /*!< SDIO DTTMOUT interrupt */ +#define SDIO_INT_FLAG_TXURE BIT(4) /*!< SDIO TXURE interrupt */ +#define SDIO_INT_FLAG_RXORE BIT(5) /*!< SDIO RXORE interrupt */ +#define SDIO_INT_FLAG_CMDRECV BIT(6) /*!< SDIO CMDRECV interrupt */ +#define SDIO_INT_FLAG_CMDSEND BIT(7) /*!< SDIO CMDSEND interrupt */ +#define SDIO_INT_FLAG_DTEND BIT(8) /*!< SDIO DTEND interrupt */ +#define SDIO_INT_FLAG_STBITE BIT(9) /*!< SDIO STBITE interrupt */ +#define SDIO_INT_FLAG_DTBLKEND BIT(10) /*!< SDIO DTBLKEND interrupt */ +#define SDIO_INT_FLAG_CMDRUN BIT(11) /*!< SDIO CMDRUN interrupt */ +#define SDIO_INT_FLAG_TXRUN BIT(12) /*!< SDIO TXRUN interrupt */ +#define SDIO_INT_FLAG_RXRUN BIT(13) /*!< SDIO RXRUN interrupt */ +#define SDIO_INT_FLAG_TFH BIT(14) /*!< SDIO TFH interrupt */ +#define SDIO_INT_FLAG_RFH BIT(15) /*!< SDIO RFH interrupt */ +#define SDIO_INT_FLAG_TFF BIT(16) /*!< SDIO TFF interrupt */ +#define SDIO_INT_FLAG_RFF BIT(17) /*!< SDIO RFF interrupt */ +#define SDIO_INT_FLAG_TFE BIT(18) /*!< SDIO TFE interrupt */ +#define SDIO_INT_FLAG_RFE BIT(19) /*!< SDIO RFE interrupt */ +#define SDIO_INT_FLAG_TXDTVAL BIT(20) /*!< SDIO TXDTVAL interrupt */ +#define SDIO_INT_FLAG_RXDTVAL BIT(21) /*!< SDIO RXDTVAL interrupt */ +#define SDIO_INT_FLAG_SDIOINT BIT(22) /*!< SDIO SDIOINT interrupt */ +#define SDIO_INT_FLAG_ATAEND BIT(23) /*!< SDIO ATAEND interrupt */ + +/* SDIO power control */ +#define PWRCTL_PWRCTL(regval) (BITS(0,1) & ((uint32_t)(regval) << 0)) +#define SDIO_POWER_OFF PWRCTL_PWRCTL(0) /*!< SDIO power off */ +#define SDIO_POWER_ON PWRCTL_PWRCTL(3) /*!< SDIO power on */ + +/* SDIO card bus mode control */ +#define CLKCTL_BUSMODE(regval) (BITS(11,12) & ((uint32_t)(regval) << 11)) +#define SDIO_BUSMODE_1BIT CLKCTL_BUSMODE(0) /*!< 1-bit SDIO card bus mode */ +#define SDIO_BUSMODE_4BIT CLKCTL_BUSMODE(1) /*!< 4-bit SDIO card bus mode */ +#define SDIO_BUSMODE_8BIT CLKCTL_BUSMODE(2) /*!< 8-bit SDIO card bus mode */ + +/* SDIO_CLK clock edge selection */ +#define SDIO_SDIOCLKEDGE_RISING ((uint32_t)0x00000000U)/*!< select the rising edge of the SDIOCLK to generate SDIO_CLK */ +#define SDIO_SDIOCLKEDGE_FALLING SDIO_CLKCTL_CLKEDGE /*!< select the falling edge of the SDIOCLK to generate SDIO_CLK */ + +/* clock bypass enable or disable */ +#define SDIO_CLOCKBYPASS_DISABLE ((uint32_t)0x00000000U)/*!< no bypass */ +#define SDIO_CLOCKBYPASS_ENABLE SDIO_CLKCTL_CLKBYP /*!< clock bypass */ + +/* SDIO_CLK clock dynamic switch on/off for power saving */ +#define SDIO_CLOCKPWRSAVE_DISABLE ((uint32_t)0x00000000U)/*!< SDIO_CLK clock is always on */ +#define SDIO_CLOCKPWRSAVE_ENABLE SDIO_CLKCTL_CLKPWRSAV /*!< SDIO_CLK closed when bus is idle */ + +/* SDIO command response type */ +#define CMDCTL_CMDRESP(regval) (BITS(6,7) & ((uint32_t)(regval) << 6)) +#define SDIO_RESPONSETYPE_NO CMDCTL_CMDRESP(0) /*!< no response */ +#define SDIO_RESPONSETYPE_SHORT CMDCTL_CMDRESP(1) /*!< short response */ +#define SDIO_RESPONSETYPE_LONG CMDCTL_CMDRESP(3) /*!< long response */ + +/* command state machine wait type */ +#define SDIO_WAITTYPE_NO ((uint32_t)0x00000000U)/*!< not wait interrupt */ +#define SDIO_WAITTYPE_INTERRUPT SDIO_CMDCTL_INTWAIT /*!< wait interrupt */ +#define SDIO_WAITTYPE_DATAEND SDIO_CMDCTL_WAITDEND /*!< wait the end of data transfer */ + +#define SDIO_RESPONSE0 ((uint32_t)0x00000000U)/*!< card response[31:0]/card response[127:96] */ +#define SDIO_RESPONSE1 ((uint32_t)0x00000001U)/*!< card response[95:64] */ +#define SDIO_RESPONSE2 ((uint32_t)0x00000002U)/*!< card response[63:32] */ +#define SDIO_RESPONSE3 ((uint32_t)0x00000003U)/*!< card response[31:1], plus bit 0 */ + +/* SDIO data block size */ +#define DATACTL_BLKSZ(regval) (BITS(4,7) & ((uint32_t)(regval) << 4)) +#define SDIO_DATABLOCKSIZE_1BYTE DATACTL_BLKSZ(0) /*!< block size = 1 byte */ +#define SDIO_DATABLOCKSIZE_2BYTES DATACTL_BLKSZ(1) /*!< block size = 2 bytes */ +#define SDIO_DATABLOCKSIZE_4BYTES DATACTL_BLKSZ(2) /*!< block size = 4 bytes */ +#define SDIO_DATABLOCKSIZE_8BYTES DATACTL_BLKSZ(3) /*!< block size = 8 bytes */ +#define SDIO_DATABLOCKSIZE_16BYTES DATACTL_BLKSZ(4) /*!< block size = 16 bytes */ +#define SDIO_DATABLOCKSIZE_32BYTES DATACTL_BLKSZ(5) /*!< block size = 32 bytes */ +#define SDIO_DATABLOCKSIZE_64BYTES DATACTL_BLKSZ(6) /*!< block size = 64 bytes */ +#define SDIO_DATABLOCKSIZE_128BYTES DATACTL_BLKSZ(7) /*!< block size = 128 bytes */ +#define SDIO_DATABLOCKSIZE_256BYTES DATACTL_BLKSZ(8) /*!< block size = 256 bytes */ +#define SDIO_DATABLOCKSIZE_512BYTES DATACTL_BLKSZ(9) /*!< block size = 512 bytes */ +#define SDIO_DATABLOCKSIZE_1024BYTES DATACTL_BLKSZ(10) /*!< block size = 1024 bytes */ +#define SDIO_DATABLOCKSIZE_2048BYTES DATACTL_BLKSZ(11) /*!< block size = 2048 bytes */ +#define SDIO_DATABLOCKSIZE_4096BYTES DATACTL_BLKSZ(12) /*!< block size = 4096 bytes */ +#define SDIO_DATABLOCKSIZE_8192BYTES DATACTL_BLKSZ(13) /*!< block size = 8192 bytes */ +#define SDIO_DATABLOCKSIZE_16384BYTES DATACTL_BLKSZ(14) /*!< block size = 16384 bytes */ + +/* SDIO data transfer mode */ +#define SDIO_TRANSMODE_BLOCK ((uint32_t)0x00000000U)/*!< block transfer */ +#define SDIO_TRANSMODE_STREAM SDIO_DATACTL_TRANSMOD /*!< stream transfer or SDIO multibyte transfer */ + +/* SDIO data transfer direction */ +#define SDIO_TRANSDIRECTION_TOCARD ((uint32_t)0x00000000U)/*!< write data to card */ +#define SDIO_TRANSDIRECTION_TOSDIO SDIO_DATACTL_DATADIR /*!< read data from card */ + +/* SDIO read wait type */ +#define SDIO_READWAITTYPE_DAT2 ((uint32_t)0x00000000U)/*!< read wait control using SDIO_DAT[2] */ +#define SDIO_READWAITTYPE_CLK SDIO_DATACTL_RWTYPE /*!< read wait control by stopping SDIO_CLK */ + +/* function declarations */ +/* deinitialize the SDIO */ +void sdio_deinit(void); +/* configure the SDIO clock */ +void sdio_clock_config(uint32_t clock_edge, uint32_t clock_bypass, uint32_t clock_powersave, uint16_t clock_division); +/* enable hardware clock control */ +void sdio_hardware_clock_enable(void); +/* disable hardware clock control */ +void sdio_hardware_clock_disable(void); +/* set different SDIO card bus mode */ +void sdio_bus_mode_set(uint32_t bus_mode); +/* set the SDIO power state */ +void sdio_power_state_set(uint32_t power_state); +/* get the SDIO power state */ +uint32_t sdio_power_state_get(void); +/* enable SDIO_CLK clock output */ +void sdio_clock_enable(void); +/* disable SDIO_CLK clock output */ +void sdio_clock_disable(void); + +/* configure the command index, argument, response type, wait type and CSM to send command */ +/* configure the command and response */ +void sdio_command_response_config(uint32_t cmd_index, uint32_t cmd_argument, uint32_t response_type); +/* set the command state machine wait type */ +void sdio_wait_type_set(uint32_t wait_type); +/* enable the CSM(command state machine) */ +void sdio_csm_enable(void); +/* disable the CSM(command state machine) */ +void sdio_csm_disable(void); +/* get the last response command index */ +uint8_t sdio_command_index_get(void); +/* get the response for the last received command */ +uint32_t sdio_response_get(uint32_t responsex); + +/* configure the data timeout, length, block size, transfer mode, direction and DSM for data transfer */ +/* configure the data timeout, data length and data block size */ +void sdio_data_config(uint32_t data_timeout, uint32_t data_length, uint32_t data_blocksize); +/* configure the data transfer mode and direction */ +void sdio_data_transfer_config(uint32_t transfer_mode, uint32_t transfer_direction); +/* enable the DSM(data state machine) for data transfer */ +void sdio_dsm_enable(void); +/* disable the DSM(data state machine) */ +void sdio_dsm_disable(void); +/* write data(one word) to the transmit FIFO */ +void sdio_data_write(uint32_t data); +/* read data(one word) from the receive FIFO */ +uint32_t sdio_data_read(void); +/* get the number of remaining data bytes to be transferred to card */ +uint32_t sdio_data_counter_get(void); +/* get the number of words remaining to be written or read from FIFO */ +uint32_t sdio_fifo_counter_get(void); +/* enable the DMA request for SDIO */ +void sdio_dma_enable(void); +/* disable the DMA request for SDIO */ +void sdio_dma_disable(void); + +/* get the flags state of SDIO */ +FlagStatus sdio_flag_get(uint32_t flag); +/* clear the pending flags of SDIO */ +void sdio_flag_clear(uint32_t flag); +/* enable the SDIO interrupt */ +void sdio_interrupt_enable(uint32_t int_flag); +/* disable the SDIO interrupt */ +void sdio_interrupt_disable(uint32_t int_flag); +/* get the interrupt flags state of SDIO */ +FlagStatus sdio_interrupt_flag_get(uint32_t int_flag); +/* clear the interrupt pending flags of SDIO */ +void sdio_interrupt_flag_clear(uint32_t int_flag); + +/* enable the read wait mode(SD I/O only) */ +void sdio_readwait_enable(void); +/* disable the read wait mode(SD I/O only) */ +void sdio_readwait_disable(void); +/* enable the function that stop the read wait process(SD I/O only) */ +void sdio_stop_readwait_enable(void); +/* disable the function that stop the read wait process(SD I/O only) */ +void sdio_stop_readwait_disable(void); +/* set the read wait type(SD I/O only) */ +void sdio_readwait_type_set(uint32_t readwait_type); +/* enable the SD I/O mode specific operation(SD I/O only) */ +void sdio_operation_enable(void); +/* disable the SD I/O mode specific operation(SD I/O only) */ +void sdio_operation_disable(void); +/* enable the SD I/O suspend operation(SD I/O only) */ +void sdio_suspend_enable(void); +/* disable the SD I/O suspend operation(SD I/O only) */ +void sdio_suspend_disable(void); + +/* enable the CE-ATA command(CE-ATA only) */ +void sdio_ceata_command_enable(void); +/* disable the CE-ATA command(CE-ATA only) */ +void sdio_ceata_command_disable(void); +/* enable the CE-ATA interrupt(CE-ATA only) */ +void sdio_ceata_interrupt_enable(void); +/* disable the CE-ATA interrupt(CE-ATA only) */ +void sdio_ceata_interrupt_disable(void); +/* enable the CE-ATA command completion signal(CE-ATA only) */ +void sdio_ceata_command_completion_enable(void); +/* disable the CE-ATA command completion signal(CE-ATA only) */ +void sdio_ceata_command_completion_disable(void); + +#endif /* GD32F10X_SDIO_H */ diff --git a/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_standard_peripheral/Include/gd32f10x_spi.h b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_standard_peripheral/Include/gd32f10x_spi.h new file mode 100644 index 0000000000..f3553253f2 --- /dev/null +++ b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_standard_peripheral/Include/gd32f10x_spi.h @@ -0,0 +1,327 @@ +/*! + \file gd32f10x_spi.h + \brief definitions for the SPI + + \version 2014-12-26, V1.0.0, firmware for GD32F10x + \version 2017-06-20, V2.0.0, firmware for GD32F10x + \version 2018-07-31, V2.1.0, firmware for GD32F10x + \version 2020-09-30, V2.2.0, firmware for GD32F10x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef GD32F10X_SPI_H +#define GD32F10X_SPI_H + +#include "gd32f10x.h" + +/* SPIx(x=0,1,2) definitions */ +#define SPI0 (SPI_BASE + 0x0000F800U) +#define SPI1 SPI_BASE +#define SPI2 (SPI_BASE + 0x00000400U) + +/* SPI registers definitions */ +#define SPI_CTL0(spix) REG32((spix) + 0x00U) /*!< SPI control register 0 */ +#define SPI_CTL1(spix) REG32((spix) + 0x04U) /*!< SPI control register 1*/ +#define SPI_STAT(spix) REG32((spix) + 0x08U) /*!< SPI status register */ +#define SPI_DATA(spix) REG32((spix) + 0x0CU) /*!< SPI data register */ +#define SPI_CRCPOLY(spix) REG32((spix) + 0x10U) /*!< SPI CRC polynomial register */ +#define SPI_RCRC(spix) REG32((spix) + 0x14U) /*!< SPI receive CRC register */ +#define SPI_TCRC(spix) REG32((spix) + 0x18U) /*!< SPI transmit CRC register */ +#define SPI_I2SCTL(spix) REG32((spix) + 0x1CU) /*!< SPI I2S control register */ +#define SPI_I2SPSC(spix) REG32((spix) + 0x20U) /*!< SPI I2S clock prescaler register */ + +/* bits definitions */ +/* SPI_CTL0 */ +#define SPI_CTL0_CKPH BIT(0) /*!< clock phase selection*/ +#define SPI_CTL0_CKPL BIT(1) /*!< clock polarity selection */ +#define SPI_CTL0_MSTMOD BIT(2) /*!< master mode enable */ +#define SPI_CTL0_PSC BITS(3,5) /*!< master clock prescaler selection */ +#define SPI_CTL0_SPIEN BIT(6) /*!< SPI enable*/ +#define SPI_CTL0_LF BIT(7) /*!< LSB first mode */ +#define SPI_CTL0_SWNSS BIT(8) /*!< NSS pin selection in NSS software mode */ +#define SPI_CTL0_SWNSSEN BIT(9) /*!< NSS software mode selection */ +#define SPI_CTL0_RO BIT(10) /*!< receive only */ +#define SPI_CTL0_FF16 BIT(11) /*!< data frame size */ +#define SPI_CTL0_CRCNT BIT(12) /*!< CRC next transfer */ +#define SPI_CTL0_CRCEN BIT(13) /*!< CRC calculation enable */ +#define SPI_CTL0_BDOEN BIT(14) /*!< bidirectional transmit output enable*/ +#define SPI_CTL0_BDEN BIT(15) /*!< bidirectional enable */ + +/* SPI_CTL1 */ +#define SPI_CTL1_DMAREN BIT(0) /*!< receive buffer dma enable */ +#define SPI_CTL1_DMATEN BIT(1) /*!< transmit buffer dma enable */ +#define SPI_CTL1_NSSDRV BIT(2) /*!< drive NSS output */ +#define SPI_CTL1_ERRIE BIT(5) /*!< errors interrupt enable */ +#define SPI_CTL1_RBNEIE BIT(6) /*!< receive buffer not empty interrupt enable */ +#define SPI_CTL1_TBEIE BIT(7) /*!< transmit buffer empty interrupt enable */ + +/* SPI_STAT */ +#define SPI_STAT_RBNE BIT(0) /*!< receive buffer not empty */ +#define SPI_STAT_TBE BIT(1) /*!< transmit buffer empty */ +#define SPI_STAT_I2SCH BIT(2) /*!< I2S channel side */ +#define SPI_STAT_TXURERR BIT(3) /*!< I2S transmission underrun error bit */ +#define SPI_STAT_CRCERR BIT(4) /*!< SPI CRC error bit */ +#define SPI_STAT_CONFERR BIT(5) /*!< SPI configuration error bit */ +#define SPI_STAT_RXORERR BIT(6) /*!< SPI reception overrun error bit */ +#define SPI_STAT_TRANS BIT(7) /*!< transmitting on-going bit */ + +/* SPI_DATA */ +#define SPI_DATA_DATA BITS(0,15) /*!< data transfer register */ + +/* SPI_CRCPOLY */ +#define SPI_CRCPOLY_CPR BITS(0,15) /*!< CRC polynomial value */ + +/* SPI_RCRC */ +#define SPI_RCRC_RCR BITS(0,15) /*!< RX CRC value */ + +/* SPI_TCRC */ +#define SPI_TCRC_TCR BITS(0,15) /*!< TX CRC value */ + +/* SPI_I2SCTL */ +#define SPI_I2SCTL_CHLEN BIT(0) /*!< channel length */ +#define SPI_I2SCTL_DTLEN BITS(1,2) /*!< data length */ +#define SPI_I2SCTL_CKPL BIT(3) /*!< idle state clock polarity */ +#define SPI_I2SCTL_I2SSTD BITS(4,5) /*!< I2S standard selection */ +#define SPI_I2SCTL_PCMSMOD BIT(7) /*!< PCM frame synchronization mode */ +#define SPI_I2SCTL_I2SOPMOD BITS(8,9) /*!< I2S operation mode */ +#define SPI_I2SCTL_I2SEN BIT(10) /*!< I2S enable */ +#define SPI_I2SCTL_I2SSEL BIT(11) /*!< I2S mode selection */ + +/* SPI_I2SPSC */ +#define SPI_I2SPSC_DIV BITS(0,7) /*!< dividing factor for the prescaler */ +#define SPI_I2SPSC_OF BIT(8) /*!< odd factor for the prescaler */ +#define SPI_I2SPSC_MCKOEN BIT(9) /*!< I2S MCK output enable */ + +/* constants definitions */ +/* SPI and I2S parameter struct definitions */ +typedef struct +{ + uint32_t device_mode; /*!< SPI master or slave */ + uint32_t trans_mode; /*!< SPI transtype */ + uint32_t frame_size; /*!< SPI frame size */ + uint32_t nss; /*!< SPI NSS control by handware or software */ + uint32_t endian; /*!< SPI big endian or little endian */ + uint32_t clock_polarity_phase; /*!< SPI clock phase and polarity */ + uint32_t prescale; /*!< SPI prescale factor */ +}spi_parameter_struct; + +/* SPI mode definitions */ +#define SPI_MASTER (SPI_CTL0_MSTMOD | SPI_CTL0_SWNSS) /*!< SPI as master */ +#define SPI_SLAVE ((uint32_t)0x00000000U) /*!< SPI as slave */ + +/* SPI bidirectional transfer direction */ +#define SPI_BIDIRECTIONAL_TRANSMIT SPI_CTL0_BDOEN /*!< SPI work in transmit-only mode */ +#define SPI_BIDIRECTIONAL_RECEIVE (~SPI_CTL0_BDOEN) /*!< SPI work in receive-only mode */ + +/* SPI transmit type */ +#define SPI_TRANSMODE_FULLDUPLEX ((uint32_t)0x00000000U) /*!< SPI receive and send data at fullduplex communication */ +#define SPI_TRANSMODE_RECEIVEONLY SPI_CTL0_RO /*!< SPI only receive data */ +#define SPI_TRANSMODE_BDRECEIVE SPI_CTL0_BDEN /*!< bidirectional receive data */ +#define SPI_TRANSMODE_BDTRANSMIT (SPI_CTL0_BDEN | SPI_CTL0_BDOEN) /*!< bidirectional transmit data*/ + +/* SPI frame size */ +#define SPI_FRAMESIZE_16BIT SPI_CTL0_FF16 /*!< SPI frame size is 16 bits */ +#define SPI_FRAMESIZE_8BIT ((uint32_t)0x00000000U) /*!< SPI frame size is 8 bits */ + +/* SPI NSS control mode */ +#define SPI_NSS_SOFT SPI_CTL0_SWNSSEN /*!< SPI NSS control by software */ +#define SPI_NSS_HARD ((uint32_t)0x00000000U) /*!< SPI NSS control by hardware */ + +/* SPI transmit way */ +#define SPI_ENDIAN_MSB ((uint32_t)0x00000000U) /*!< SPI transmit way is big endian: transmit MSB first */ +#define SPI_ENDIAN_LSB SPI_CTL0_LF /*!< SPI transmit way is little endian: transmit LSB first */ + +/* SPI clock phase and polarity */ +#define SPI_CK_PL_LOW_PH_1EDGE ((uint32_t)0x00000000U) /*!< SPI clock polarity is low level and phase is first edge */ +#define SPI_CK_PL_HIGH_PH_1EDGE SPI_CTL0_CKPL /*!< SPI clock polarity is high level and phase is first edge */ +#define SPI_CK_PL_LOW_PH_2EDGE SPI_CTL0_CKPH /*!< SPI clock polarity is low level and phase is second edge */ +#define SPI_CK_PL_HIGH_PH_2EDGE (SPI_CTL0_CKPL | SPI_CTL0_CKPH) /*!< SPI clock polarity is high level and phase is second edge */ + +/* SPI clock prescale factor */ +#define CTL0_PSC(regval) (BITS(3,5) & ((uint32_t)(regval) << 3)) +#define SPI_PSC_2 CTL0_PSC(0) /*!< SPI clock prescale factor is 2 */ +#define SPI_PSC_4 CTL0_PSC(1) /*!< SPI clock prescale factor is 4 */ +#define SPI_PSC_8 CTL0_PSC(2) /*!< SPI clock prescale factor is 8 */ +#define SPI_PSC_16 CTL0_PSC(3) /*!< SPI clock prescale factor is 16 */ +#define SPI_PSC_32 CTL0_PSC(4) /*!< SPI clock prescale factor is 32 */ +#define SPI_PSC_64 CTL0_PSC(5) /*!< SPI clock prescale factor is 64 */ +#define SPI_PSC_128 CTL0_PSC(6) /*!< SPI clock prescale factor is 128 */ +#define SPI_PSC_256 CTL0_PSC(7) /*!< SPI clock prescale factor is 256 */ + +/* I2S audio sample rate */ +#define I2S_AUDIOSAMPLE_8K ((uint32_t)8000U) /*!< I2S audio sample rate is 8KHz */ +#define I2S_AUDIOSAMPLE_11K ((uint32_t)11025U) /*!< I2S audio sample rate is 11KHz */ +#define I2S_AUDIOSAMPLE_16K ((uint32_t)16000U) /*!< I2S audio sample rate is 16KHz */ +#define I2S_AUDIOSAMPLE_22K ((uint32_t)22050U) /*!< I2S audio sample rate is 22KHz */ +#define I2S_AUDIOSAMPLE_32K ((uint32_t)32000U) /*!< I2S audio sample rate is 32KHz */ +#define I2S_AUDIOSAMPLE_44K ((uint32_t)44100U) /*!< I2S audio sample rate is 44KHz */ +#define I2S_AUDIOSAMPLE_48K ((uint32_t)48000U) /*!< I2S audio sample rate is 48KHz */ +#define I2S_AUDIOSAMPLE_96K ((uint32_t)96000U) /*!< I2S audio sample rate is 96KHz */ +#define I2S_AUDIOSAMPLE_192K ((uint32_t)192000U) /*!< I2S audio sample rate is 192KHz */ + +/* I2S frame format */ +#define I2SCTL_DTLEN(regval) (BITS(1,2) & ((uint32_t)(regval) << 1)) +#define I2S_FRAMEFORMAT_DT16B_CH16B I2SCTL_DTLEN(0) /*!< I2S data length is 16 bit and channel length is 16 bit */ +#define I2S_FRAMEFORMAT_DT16B_CH32B (I2SCTL_DTLEN(0) | SPI_I2SCTL_CHLEN) /*!< I2S data length is 16 bit and channel length is 32 bit */ +#define I2S_FRAMEFORMAT_DT24B_CH32B (I2SCTL_DTLEN(1) | SPI_I2SCTL_CHLEN) /*!< I2S data length is 24 bit and channel length is 32 bit */ +#define I2S_FRAMEFORMAT_DT32B_CH32B (I2SCTL_DTLEN(2) | SPI_I2SCTL_CHLEN) /*!< I2S data length is 32 bit and channel length is 32 bit */ + +/* I2S master clock output */ +#define I2S_MCKOUT_DISABLE ((uint32_t)0x00000000U) /*!< I2S master clock output disable */ +#define I2S_MCKOUT_ENABLE SPI_I2SPSC_MCKOEN /*!< I2S master clock output enable */ + +/* I2S operation mode */ +#define I2SCTL_I2SOPMOD(regval) (BITS(8,9) & ((uint32_t)(regval) << 8)) +#define I2S_MODE_SLAVETX I2SCTL_I2SOPMOD(0) /*!< I2S slave transmit mode */ +#define I2S_MODE_SLAVERX I2SCTL_I2SOPMOD(1) /*!< I2S slave receive mode */ +#define I2S_MODE_MASTERTX I2SCTL_I2SOPMOD(2) /*!< I2S master transmit mode */ +#define I2S_MODE_MASTERRX I2SCTL_I2SOPMOD(3) /*!< I2S master receive mode */ + +/* I2S standard */ +#define I2SCTL_I2SSTD(regval) (BITS(4,5) & ((uint32_t)(regval) << 4)) +#define I2S_STD_PHILLIPS I2SCTL_I2SSTD(0) /*!< I2S phillips standard */ +#define I2S_STD_MSB I2SCTL_I2SSTD(1) /*!< I2S MSB standard */ +#define I2S_STD_LSB I2SCTL_I2SSTD(2) /*!< I2S LSB standard */ +#define I2S_STD_PCMSHORT I2SCTL_I2SSTD(3) /*!< I2S PCM short standard */ +#define I2S_STD_PCMLONG (I2SCTL_I2SSTD(3) | SPI_I2SCTL_PCMSMOD) /*!< I2S PCM long standard */ + +/* I2S clock polarity */ +#define I2S_CKPL_LOW ((uint32_t)0x00000000U) /*!< I2S clock polarity low level */ +#define I2S_CKPL_HIGH SPI_I2SCTL_CKPL /*!< I2S clock polarity high level */ + +/* SPI DMA constants definitions */ +#define SPI_DMA_TRANSMIT ((uint8_t)0x00U) /*!< SPI transmit data use DMA */ +#define SPI_DMA_RECEIVE ((uint8_t)0x01U) /*!< SPI receive data use DMA */ + +/* SPI CRC constants definitions */ +#define SPI_CRC_TX ((uint8_t)0x00U) /*!< SPI transmit CRC value */ +#define SPI_CRC_RX ((uint8_t)0x01U) /*!< SPI receive CRC value */ + +/* SPI/I2S interrupt enable/disable constants definitions */ +#define SPI_I2S_INT_TBE ((uint8_t)0x00U) /*!< transmit buffer empty interrupt */ +#define SPI_I2S_INT_RBNE ((uint8_t)0x01U) /*!< receive buffer not empty interrupt */ +#define SPI_I2S_INT_ERR ((uint8_t)0x02U) /*!< error interrupt */ + +/* SPI/I2S interrupt flag constants definitions */ +#define SPI_I2S_INT_FLAG_TBE ((uint8_t)0x00U) /*!< transmit buffer empty interrupt flag */ +#define SPI_I2S_INT_FLAG_RBNE ((uint8_t)0x01U) /*!< receive buffer not empty interrupt flag */ +#define SPI_I2S_INT_FLAG_RXORERR ((uint8_t)0x02U) /*!< overrun interrupt flag */ +#define SPI_INT_FLAG_CONFERR ((uint8_t)0x03U) /*!< config error interrupt flag */ +#define SPI_INT_FLAG_CRCERR ((uint8_t)0x04U) /*!< CRC error interrupt flag */ +#define I2S_INT_FLAG_TXURERR ((uint8_t)0x05U) /*!< underrun error interrupt flag */ + +/* SPI/I2S flag definitions */ +#define SPI_FLAG_RBNE SPI_STAT_RBNE /*!< receive buffer not empty flag */ +#define SPI_FLAG_TBE SPI_STAT_TBE /*!< transmit buffer empty flag */ +#define SPI_FLAG_CRCERR SPI_STAT_CRCERR /*!< CRC error flag */ +#define SPI_FLAG_CONFERR SPI_STAT_CONFERR /*!< mode config error flag */ +#define SPI_FLAG_RXORERR SPI_STAT_RXORERR /*!< receive overrun error flag */ +#define SPI_FLAG_TRANS SPI_STAT_TRANS /*!< transmit on-going flag */ +#define I2S_FLAG_RBNE SPI_STAT_RBNE /*!< receive buffer not empty flag */ +#define I2S_FLAG_TBE SPI_STAT_TBE /*!< transmit buffer empty flag */ +#define I2S_FLAG_CH SPI_STAT_I2SCH /*!< channel side flag */ +#define I2S_FLAG_TXURERR SPI_STAT_TXURERR /*!< underrun error flag */ +#define I2S_FLAG_RXORERR SPI_STAT_RXORERR /*!< overrun error flag */ +#define I2S_FLAG_TRANS SPI_STAT_TRANS /*!< transmit on-going flag */ + +/* function declarations */ +/* SPI/I2S deinitialization and initialization functions */ +/* reset SPI and I2S */ +void spi_i2s_deinit(uint32_t spi_periph); +/* initialize the parameters of SPI struct with the default values */ +void spi_struct_para_init(spi_parameter_struct* spi_struct); +/* initialize SPI parameter */ +void spi_init(uint32_t spi_periph, spi_parameter_struct* spi_struct); +/* enable SPI */ +void spi_enable(uint32_t spi_periph); +/* disable SPI */ +void spi_disable(uint32_t spi_periph); + +/* initialize I2S parameter */ +void i2s_init(uint32_t spi_periph,uint32_t mode, uint32_t standard, uint32_t ckpl); +/* configure I2S prescaler */ +void i2s_psc_config(uint32_t spi_periph, uint32_t audiosample, uint32_t frameformat, uint32_t mckout); +/* enable I2S */ +void i2s_enable(uint32_t spi_periph); +/* disable I2S */ +void i2s_disable(uint32_t spi_periph); + +/* NSS functions */ +/* enable SPI NSS output */ +void spi_nss_output_enable(uint32_t spi_periph); +/* disable SPI NSS output */ +void spi_nss_output_disable(uint32_t spi_periph); +/* SPI NSS pin high level in software mode */ +void spi_nss_internal_high(uint32_t spi_periph); +/* SPI NSS pin low level in software mode */ +void spi_nss_internal_low(uint32_t spi_periph); + +/* DMA communication */ +/* enable SPI DMA */ +void spi_dma_enable(uint32_t spi_periph, uint8_t dma); +/* disable SPI DMA */ +void spi_dma_disable(uint32_t spi_periph, uint8_t dma); + +/* normal mode communication */ +/* configure SPI/I2S data frame format */ +void spi_i2s_data_frame_format_config(uint32_t spi_periph, uint16_t frame_format); +/* SPI transmit data */ +void spi_i2s_data_transmit(uint32_t spi_periph, uint16_t data); +/* SPI receive data */ +uint16_t spi_i2s_data_receive(uint32_t spi_periph); +/* configure SPI bidirectional transfer direction */ +void spi_bidirectional_transfer_config(uint32_t spi_periph, uint32_t transfer_direction); + +/* SPI CRC functions */ +/* set SPI CRC polynomial */ +void spi_crc_polynomial_set(uint32_t spi_periph, uint16_t crc_poly); +/* get SPI CRC polynomial */ +uint16_t spi_crc_polynomial_get(uint32_t spi_periph); +/* turn on SPI CRC function */ +void spi_crc_on(uint32_t spi_periph); +/* turn off SPI CRC function */ +void spi_crc_off(uint32_t spi_periph); +/* SPI next data is CRC value */ +void spi_crc_next(uint32_t spi_periph); +/* get SPI CRC send value or receive value */ +uint16_t spi_crc_get(uint32_t spi_periph, uint8_t crc); + +/* flag and interrupt functions */ +/* enable SPI and I2S interrupt */ +void spi_i2s_interrupt_enable(uint32_t spi_periph, uint8_t interrupt); +/* disable SPI and I2S interrupt */ +void spi_i2s_interrupt_disable(uint32_t spi_periph, uint8_t interrupt); +/* get SPI and I2S interrupt status */ +FlagStatus spi_i2s_interrupt_flag_get(uint32_t spi_periph, uint8_t interrupt); +/* get SPI and I2S flag status */ +FlagStatus spi_i2s_flag_get(uint32_t spi_periph, uint32_t flag); +/* clear SPI CRC error flag status */ +void spi_crc_error_clear(uint32_t spi_periph); + +#endif /* GD32F10X_SPI_H */ diff --git a/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_standard_peripheral/Include/gd32f10x_timer.h b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_standard_peripheral/Include/gd32f10x_timer.h new file mode 100644 index 0000000000..0b4ca98237 --- /dev/null +++ b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_standard_peripheral/Include/gd32f10x_timer.h @@ -0,0 +1,729 @@ +/*! + \file gd32f10x_timer.h + \brief definitions for the TIMER + + \version 2014-12-26, V1.0.0, firmware for GD32F10x + \version 2017-06-20, V2.0.0, firmware for GD32F10x + \version 2018-07-31, V2.1.0, firmware for GD32F10x + \version 2020-09-30, V2.2.0, firmware for GD32F10x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef GD32F10X_TIMER_H +#define GD32F10X_TIMER_H + +#include "gd32f10x.h" + +/* TIMERx(x=0..13) definitions */ +#define TIMER0 (TIMER_BASE + 0x00012C00U) +#define TIMER1 (TIMER_BASE + 0x00000000U) +#define TIMER2 (TIMER_BASE + 0x00000400U) +#define TIMER3 (TIMER_BASE + 0x00000800U) +#define TIMER4 (TIMER_BASE + 0x00000C00U) +#define TIMER5 (TIMER_BASE + 0x00001000U) +#define TIMER6 (TIMER_BASE + 0x00001400U) +#define TIMER7 (TIMER_BASE + 0x00013400U) +#define TIMER8 (TIMER_BASE + 0x00014C00U) +#define TIMER9 (TIMER_BASE + 0x00015000U) +#define TIMER10 (TIMER_BASE + 0x00015400U) +#define TIMER11 (TIMER_BASE + 0x00001800U) +#define TIMER12 (TIMER_BASE + 0x00001C00U) +#define TIMER13 (TIMER_BASE + 0x00002000U) + +/* registers definitions */ +#define TIMER_CTL0(timerx) REG32((timerx) + 0x00U) /*!< TIMER control register 0 */ +#define TIMER_CTL1(timerx) REG32((timerx) + 0x04U) /*!< TIMER control register 1 */ +#define TIMER_SMCFG(timerx) REG32((timerx) + 0x08U) /*!< TIMER slave mode configuration register */ +#define TIMER_DMAINTEN(timerx) REG32((timerx) + 0x0CU) /*!< TIMER DMA and interrupt enable register */ +#define TIMER_INTF(timerx) REG32((timerx) + 0x10U) /*!< TIMER interrupt flag register */ +#define TIMER_SWEVG(timerx) REG32((timerx) + 0x14U) /*!< TIMER software event generation register */ +#define TIMER_CHCTL0(timerx) REG32((timerx) + 0x18U) /*!< TIMER channel control register 0 */ +#define TIMER_CHCTL1(timerx) REG32((timerx) + 0x1CU) /*!< TIMER channel control register 1 */ +#define TIMER_CHCTL2(timerx) REG32((timerx) + 0x20U) /*!< TIMER channel control register 2 */ +#define TIMER_CNT(timerx) REG32((timerx) + 0x24U) /*!< TIMER counter register */ +#define TIMER_PSC(timerx) REG32((timerx) + 0x28U) /*!< TIMER prescaler register */ +#define TIMER_CAR(timerx) REG32((timerx) + 0x2CU) /*!< TIMER counter auto reload register */ +#define TIMER_CREP(timerx) REG32((timerx) + 0x30U) /*!< TIMER counter repetition register */ +#define TIMER_CH0CV(timerx) REG32((timerx) + 0x34U) /*!< TIMER channel 0 capture/compare value register */ +#define TIMER_CH1CV(timerx) REG32((timerx) + 0x38U) /*!< TIMER channel 1 capture/compare value register */ +#define TIMER_CH2CV(timerx) REG32((timerx) + 0x3CU) /*!< TIMER channel 2 capture/compare value register */ +#define TIMER_CH3CV(timerx) REG32((timerx) + 0x40U) /*!< TIMER channel 3 capture/compare value register */ +#define TIMER_CCHP(timerx) REG32((timerx) + 0x44U) /*!< TIMER channel complementary protection register */ +#define TIMER_DMACFG(timerx) REG32((timerx) + 0x48U) /*!< TIMER DMA configuration register */ +#define TIMER_DMATB(timerx) REG32((timerx) + 0x4CU) /*!< TIMER DMA transfer buffer register */ + +/* bits definitions */ +/* TIMER_CTL0 */ +#define TIMER_CTL0_CEN BIT(0) /*!< TIMER counter enable */ +#define TIMER_CTL0_UPDIS BIT(1) /*!< update disable */ +#define TIMER_CTL0_UPS BIT(2) /*!< update source */ +#define TIMER_CTL0_SPM BIT(3) /*!< single pulse mode */ +#define TIMER_CTL0_DIR BIT(4) /*!< timer counter direction */ +#define TIMER_CTL0_CAM BITS(5,6) /*!< center-aligned mode selection */ +#define TIMER_CTL0_ARSE BIT(7) /*!< auto-reload shadow enable */ +#define TIMER_CTL0_CKDIV BITS(8,9) /*!< clock division */ + +/* TIMER_CTL1 */ +#define TIMER_CTL1_CCSE BIT(0) /*!< commutation control shadow enable */ +#define TIMER_CTL1_CCUC BIT(2) /*!< commutation control shadow register update control */ +#define TIMER_CTL1_DMAS BIT(3) /*!< DMA request source selection */ +#define TIMER_CTL1_MMC BITS(4,6) /*!< master mode control */ +#define TIMER_CTL1_TI0S BIT(7) /*!< channel 0 trigger input selection(hall mode selection) */ +#define TIMER_CTL1_ISO0 BIT(8) /*!< idle state of channel 0 output */ +#define TIMER_CTL1_ISO0N BIT(9) /*!< idle state of channel 0 complementary output */ +#define TIMER_CTL1_ISO1 BIT(10) /*!< idle state of channel 1 output */ +#define TIMER_CTL1_ISO1N BIT(11) /*!< idle state of channel 1 complementary output */ +#define TIMER_CTL1_ISO2 BIT(12) /*!< idle state of channel 2 output */ +#define TIMER_CTL1_ISO2N BIT(13) /*!< idle state of channel 2 complementary output */ +#define TIMER_CTL1_ISO3 BIT(14) /*!< idle state of channel 3 output */ + +/* TIMER_SMCFG */ +#define TIMER_SMCFG_SMC BITS(0,2) /*!< slave mode control */ +#define TIMER_SMCFG_TRGS BITS(4,6) /*!< trigger selection */ +#define TIMER_SMCFG_MSM BIT(7) /*!< master-slave mode */ +#define TIMER_SMCFG_ETFC BITS(8,11) /*!< external trigger filter control */ +#define TIMER_SMCFG_ETPSC BITS(12,13) /*!< external trigger prescaler */ +#define TIMER_SMCFG_SMC1 BIT(14) /*!< part of SMC for enable external clock mode 1 */ +#define TIMER_SMCFG_ETP BIT(15) /*!< external trigger polarity */ + +/* TIMER_DMAINTEN */ +#define TIMER_DMAINTEN_UPIE BIT(0) /*!< update interrupt enable */ +#define TIMER_DMAINTEN_CH0IE BIT(1) /*!< channel 0 capture/compare interrupt enable */ +#define TIMER_DMAINTEN_CH1IE BIT(2) /*!< channel 1 capture/compare interrupt enable */ +#define TIMER_DMAINTEN_CH2IE BIT(3) /*!< channel 2 capture/compare interrupt enable */ +#define TIMER_DMAINTEN_CH3IE BIT(4) /*!< channel 3 capture/compare interrupt enable */ +#define TIMER_DMAINTEN_CMTIE BIT(5) /*!< commutation interrupt request enable */ +#define TIMER_DMAINTEN_TRGIE BIT(6) /*!< trigger interrupt enable */ +#define TIMER_DMAINTEN_BRKIE BIT(7) /*!< break interrupt enable */ +#define TIMER_DMAINTEN_UPDEN BIT(8) /*!< update DMA request enable */ +#define TIMER_DMAINTEN_CH0DEN BIT(9) /*!< channel 0 capture/compare DMA request enable */ +#define TIMER_DMAINTEN_CH1DEN BIT(10) /*!< channel 1 capture/compare DMA request enable */ +#define TIMER_DMAINTEN_CH2DEN BIT(11) /*!< channel 2 capture/compare DMA request enable */ +#define TIMER_DMAINTEN_CH3DEN BIT(12) /*!< channel 3 capture/compare DMA request enable */ +#define TIMER_DMAINTEN_CMTDEN BIT(13) /*!< commutation DMA request enable */ +#define TIMER_DMAINTEN_TRGDEN BIT(14) /*!< trigger DMA request enable */ + +/* TIMER_INTF */ +#define TIMER_INTF_UPIF BIT(0) /*!< update interrupt flag */ +#define TIMER_INTF_CH0IF BIT(1) /*!< channel 0 capture/compare interrupt flag */ +#define TIMER_INTF_CH1IF BIT(2) /*!< channel 1 capture/compare interrupt flag */ +#define TIMER_INTF_CH2IF BIT(3) /*!< channel 2 capture/compare interrupt flag */ +#define TIMER_INTF_CH3IF BIT(4) /*!< channel 3 capture/compare interrupt flag */ +#define TIMER_INTF_CMTIF BIT(5) /*!< channel commutation interrupt flag */ +#define TIMER_INTF_TRGIF BIT(6) /*!< trigger interrupt flag */ +#define TIMER_INTF_BRKIF BIT(7) /*!< break interrupt flag */ +#define TIMER_INTF_CH0OF BIT(9) /*!< channel 0 over capture flag */ +#define TIMER_INTF_CH1OF BIT(10) /*!< channel 1 over capture flag */ +#define TIMER_INTF_CH2OF BIT(11) /*!< channel 2 over capture flag */ +#define TIMER_INTF_CH3OF BIT(12) /*!< channel 3 over capture flag */ + +/* TIMER_SWEVG */ +#define TIMER_SWEVG_UPG BIT(0) /*!< update event generate */ +#define TIMER_SWEVG_CH0G BIT(1) /*!< channel 0 capture or compare event generation */ +#define TIMER_SWEVG_CH1G BIT(2) /*!< channel 1 capture or compare event generation */ +#define TIMER_SWEVG_CH2G BIT(3) /*!< channel 2 capture or compare event generation */ +#define TIMER_SWEVG_CH3G BIT(4) /*!< channel 3 capture or compare event generation */ +#define TIMER_SWEVG_CMTG BIT(5) /*!< channel commutation event generation */ +#define TIMER_SWEVG_TRGG BIT(6) /*!< trigger event generation */ +#define TIMER_SWEVG_BRKG BIT(7) /*!< break event generation */ + +/* TIMER_CHCTL0 */ +/* output compare mode */ +#define TIMER_CHCTL0_CH0MS BITS(0,1) /*!< channel 0 mode selection */ +#define TIMER_CHCTL0_CH0COMFEN BIT(2) /*!< channel 0 output compare fast enable */ +#define TIMER_CHCTL0_CH0COMSEN BIT(3) /*!< channel 0 output compare shadow enable */ +#define TIMER_CHCTL0_CH0COMCTL BITS(4,6) /*!< channel 0 output compare control */ +#define TIMER_CHCTL0_CH0COMCEN BIT(7) /*!< channel 0 output compare clear enable */ +#define TIMER_CHCTL0_CH1MS BITS(8,9) /*!< channel 1 mode selection */ +#define TIMER_CHCTL0_CH1COMFEN BIT(10) /*!< channel 1 output compare fast enable */ +#define TIMER_CHCTL0_CH1COMSEN BIT(11) /*!< channel 1 output compare shadow enable */ +#define TIMER_CHCTL0_CH1COMCTL BITS(12,14) /*!< channel 1 output compare control */ +#define TIMER_CHCTL0_CH1COMCEN BIT(15) /*!< channel 1 output compare clear enable */ +/* input capture mode */ +#define TIMER_CHCTL0_CH0CAPPSC BITS(2,3) /*!< channel 0 input capture prescaler */ +#define TIMER_CHCTL0_CH0CAPFLT BITS(4,7) /*!< channel 0 input capture filter control */ +#define TIMER_CHCTL0_CH1CAPPSC BITS(10,11) /*!< channel 1 input capture prescaler */ +#define TIMER_CHCTL0_CH1CAPFLT BITS(12,15) /*!< channel 1 input capture filter control */ + +/* TIMER_CHCTL1 */ +/* output compare mode */ +#define TIMER_CHCTL1_CH2MS BITS(0,1) /*!< channel 2 mode selection */ +#define TIMER_CHCTL1_CH2COMFEN BIT(2) /*!< channel 2 output compare fast enable */ +#define TIMER_CHCTL1_CH2COMSEN BIT(3) /*!< channel 2 output compare shadow enable */ +#define TIMER_CHCTL1_CH2COMCTL BITS(4,6) /*!< channel 2 output compare control */ +#define TIMER_CHCTL1_CH2COMCEN BIT(7) /*!< channel 2 output compare clear enable */ +#define TIMER_CHCTL1_CH3MS BITS(8,9) /*!< channel 3 mode selection */ +#define TIMER_CHCTL1_CH3COMFEN BIT(10) /*!< channel 3 output compare fast enable */ +#define TIMER_CHCTL1_CH3COMSEN BIT(11) /*!< channel 3 output compare shadow enable */ +#define TIMER_CHCTL1_CH3COMCTL BITS(12,14) /*!< channel 3 output compare control */ +#define TIMER_CHCTL1_CH3COMCEN BIT(15) /*!< channel 3 output compare clear enable */ +/* input capture mode */ +#define TIMER_CHCTL1_CH2CAPPSC BITS(2,3) /*!< channel 2 input capture prescaler */ +#define TIMER_CHCTL1_CH2CAPFLT BITS(4,7) /*!< channel 2 input capture filter control */ +#define TIMER_CHCTL1_CH3CAPPSC BITS(10,11) /*!< channel 3 input capture prescaler */ +#define TIMER_CHCTL1_CH3CAPFLT BITS(12,15) /*!< channel 3 input capture filter control */ + +/* TIMER_CHCTL2 */ +#define TIMER_CHCTL2_CH0EN BIT(0) /*!< channel 0 capture/compare function enable */ +#define TIMER_CHCTL2_CH0P BIT(1) /*!< channel 0 capture/compare function polarity */ +#define TIMER_CHCTL2_CH0NEN BIT(2) /*!< channel 0 complementary output enable */ +#define TIMER_CHCTL2_CH0NP BIT(3) /*!< channel 0 complementary output polarity */ +#define TIMER_CHCTL2_CH1EN BIT(4) /*!< channel 1 capture/compare function enable */ +#define TIMER_CHCTL2_CH1P BIT(5) /*!< channel 1 capture/compare function polarity */ +#define TIMER_CHCTL2_CH1NEN BIT(6) /*!< channel 1 complementary output enable */ +#define TIMER_CHCTL2_CH1NP BIT(7) /*!< channel 1 complementary output polarity */ +#define TIMER_CHCTL2_CH2EN BIT(8) /*!< channel 2 capture/compare function enable */ +#define TIMER_CHCTL2_CH2P BIT(9) /*!< channel 2 capture/compare function polarity */ +#define TIMER_CHCTL2_CH2NEN BIT(10) /*!< channel 2 complementary output enable */ +#define TIMER_CHCTL2_CH2NP BIT(11) /*!< channel 2 complementary output polarity */ +#define TIMER_CHCTL2_CH3EN BIT(12) /*!< channel 3 capture/compare function enable */ +#define TIMER_CHCTL2_CH3P BIT(13) /*!< channel 3 capture/compare function polarity */ + +/* TIMER_CNT */ +#define TIMER_CNT_CNT BITS(0,15) /*!< 16 bit timer counter */ + +/* TIMER_PSC */ +#define TIMER_PSC_PSC BITS(0,15) /*!< prescaler value of the counter clock */ + +/* TIMER_CAR */ +#define TIMER_CAR_CARL BITS(0,15) /*!< 16 bit counter auto reload value */ + +/* TIMER_CREP */ +#define TIMER_CREP_CREP BITS(0,7) /*!< counter repetition value */ + +/* TIMER_CH0CV */ +#define TIMER_CH0CV_CH0VAL BITS(0,15) /*!< 16 bit capture/compare value of channel 0 */ + +/* TIMER_CH1CV */ +#define TIMER_CH1CV_CH1VAL BITS(0,15) /*!< 16 bit capture/compare value of channel 1 */ + +/* TIMER_CH2CV */ +#define TIMER_CH2CV_CH2VAL BITS(0,15) /*!< 16 bit capture/compare value of channel 2 */ + +/* TIMER_CH3CV */ +#define TIMER_CH3CV_CH3VAL BITS(0,15) /*!< 16 bit capture/compare value of channel 3 */ + +/* TIMER_CCHP */ +#define TIMER_CCHP_DTCFG BITS(0,7) /*!< dead time configure */ +#define TIMER_CCHP_PROT BITS(8,9) /*!< complementary register protect control */ +#define TIMER_CCHP_IOS BIT(10) /*!< idle mode off-state configure */ +#define TIMER_CCHP_ROS BIT(11) /*!< run mode off-state configure */ +#define TIMER_CCHP_BRKEN BIT(12) /*!< break enable */ +#define TIMER_CCHP_BRKP BIT(13) /*!< break polarity */ +#define TIMER_CCHP_OAEN BIT(14) /*!< output automatic enable */ +#define TIMER_CCHP_POEN BIT(15) /*!< primary output enable */ + +/* TIMER_DMACFG */ +#define TIMER_DMACFG_DMATA BITS(0,4) /*!< DMA transfer access start address */ +#define TIMER_DMACFG_DMATC BITS(8,12) /*!< DMA transfer count */ + +/* TIMER_DMATB */ +#define TIMER_DMATB_DMATB BITS(0,15) /*!< DMA transfer buffer address */ + +/* constants definitions */ +/* TIMER init parameter struct definitions */ +typedef struct +{ + uint16_t prescaler; /*!< prescaler value */ + uint16_t alignedmode; /*!< aligned mode */ + uint16_t counterdirection; /*!< counter direction */ + uint32_t period; /*!< period value */ + uint16_t clockdivision; /*!< clock division value */ + uint8_t repetitioncounter; /*!< the counter repetition value */ +}timer_parameter_struct; + +/* break parameter struct definitions*/ +typedef struct +{ + uint16_t runoffstate; /*!< run mode off-state */ + uint16_t ideloffstate; /*!< idle mode off-state */ + uint16_t deadtime; /*!< dead time */ + uint16_t breakpolarity; /*!< break polarity */ + uint16_t outputautostate; /*!< output automatic enable */ + uint16_t protectmode; /*!< complementary register protect control */ + uint16_t breakstate; /*!< break enable */ +}timer_break_parameter_struct; + +/* channel output parameter struct definitions */ +typedef struct +{ + uint16_t outputstate; /*!< channel output state */ + uint16_t outputnstate; /*!< channel complementary output state */ + uint16_t ocpolarity; /*!< channel output polarity */ + uint16_t ocnpolarity; /*!< channel complementary output polarity */ + uint16_t ocidlestate; /*!< idle state of channel output */ + uint16_t ocnidlestate; /*!< idle state of channel complementary output */ +}timer_oc_parameter_struct; + +/* channel input parameter struct definitions */ +typedef struct +{ + uint16_t icpolarity; /*!< channel input polarity */ + uint16_t icselection; /*!< channel input mode selection */ + uint16_t icprescaler; /*!< channel input capture prescaler */ + uint16_t icfilter; /*!< channel input capture filter control */ +}timer_ic_parameter_struct; + +/* TIMER interrupt enable or disable */ +#define TIMER_INT_UP TIMER_DMAINTEN_UPIE /*!< update interrupt */ +#define TIMER_INT_CH0 TIMER_DMAINTEN_CH0IE /*!< channel 0 interrupt */ +#define TIMER_INT_CH1 TIMER_DMAINTEN_CH1IE /*!< channel 1 interrupt */ +#define TIMER_INT_CH2 TIMER_DMAINTEN_CH2IE /*!< channel 2 interrupt */ +#define TIMER_INT_CH3 TIMER_DMAINTEN_CH3IE /*!< channel 3 interrupt */ +#define TIMER_INT_CMT TIMER_DMAINTEN_CMTIE /*!< channel commutation interrupt flag */ +#define TIMER_INT_TRG TIMER_DMAINTEN_TRGIE /*!< trigger interrupt */ +#define TIMER_INT_BRK TIMER_DMAINTEN_BRKIE /*!< break interrupt */ + +/* TIMER interrupt flag */ +#define TIMER_INT_FLAG_UP TIMER_INT_UP /*!< update interrupt */ +#define TIMER_INT_FLAG_CH0 TIMER_INT_CH0 /*!< channel 0 interrupt */ +#define TIMER_INT_FLAG_CH1 TIMER_INT_CH1 /*!< channel 1 interrupt */ +#define TIMER_INT_FLAG_CH2 TIMER_INT_CH2 /*!< channel 2 interrupt */ +#define TIMER_INT_FLAG_CH3 TIMER_INT_CH3 /*!< channel 3 interrupt */ +#define TIMER_INT_FLAG_CMT TIMER_INT_CMT /*!< channel commutation interrupt flag */ +#define TIMER_INT_FLAG_TRG TIMER_INT_TRG /*!< trigger interrupt */ +#define TIMER_INT_FLAG_BRK TIMER_INT_BRK + +/* TIMER flag */ +#define TIMER_FLAG_UP TIMER_INTF_UPIF /*!< update flag */ +#define TIMER_FLAG_CH0 TIMER_INTF_CH0IF /*!< channel 0 flag */ +#define TIMER_FLAG_CH1 TIMER_INTF_CH1IF /*!< channel 1 flag */ +#define TIMER_FLAG_CH2 TIMER_INTF_CH2IF /*!< channel 2 flag */ +#define TIMER_FLAG_CH3 TIMER_INTF_CH3IF /*!< channel 3 flag */ +#define TIMER_FLAG_CMT TIMER_INTF_CMTIF /*!< channel commutation flag */ +#define TIMER_FLAG_TRG TIMER_INTF_TRGIF /*!< trigger flag */ +#define TIMER_FLAG_BRK TIMER_INTF_BRKIF /*!< break flag */ +#define TIMER_FLAG_CH0O TIMER_INTF_CH0OF /*!< channel 0 overcapture flag */ +#define TIMER_FLAG_CH1O TIMER_INTF_CH1OF /*!< channel 1 overcapture flag */ +#define TIMER_FLAG_CH2O TIMER_INTF_CH2OF /*!< channel 2 overcapture flag */ +#define TIMER_FLAG_CH3O TIMER_INTF_CH3OF /*!< channel 3 overcapture flag */ +/* TIMER DMA source enable */ +#define TIMER_DMA_UPD ((uint16_t)TIMER_DMAINTEN_UPDEN) /*!< update DMA enable */ +#define TIMER_DMA_CH0D ((uint16_t)TIMER_DMAINTEN_CH0DEN) /*!< channel 0 DMA enable */ +#define TIMER_DMA_CH1D ((uint16_t)TIMER_DMAINTEN_CH1DEN) /*!< channel 1 DMA enable */ +#define TIMER_DMA_CH2D ((uint16_t)TIMER_DMAINTEN_CH2DEN) /*!< channel 2 DMA enable */ +#define TIMER_DMA_CH3D ((uint16_t)TIMER_DMAINTEN_CH3DEN) /*!< channel 3 DMA enable */ +#define TIMER_DMA_CMTD ((uint16_t)TIMER_DMAINTEN_CMTDEN) /*!< commutation DMA request enable */ +#define TIMER_DMA_TRGD ((uint16_t)TIMER_DMAINTEN_TRGDEN) /*!< trigger DMA enable */ + +/* channel DMA request source selection */ +#define TIMER_DMAREQUEST_UPDATEEVENT TIMER_CTL1_DMAS /*!< DMA request of channel n is sent when update event occurs */ +#define TIMER_DMAREQUEST_CHANNELEVENT ((uint32_t)0x00000000U) /*!< DMA request of channel n is sent when channel n event occurs */ + +/* DMA access base address */ +#define DMACFG_DMATA(regval) (BITS(0, 4) & ((uint32_t)(regval) << 0U)) +#define TIMER_DMACFG_DMATA_CTL0 DMACFG_DMATA(0) /*!< DMA transfer address is TIMER_CTL0 */ +#define TIMER_DMACFG_DMATA_CTL1 DMACFG_DMATA(1) /*!< DMA transfer address is TIMER_CTL1 */ +#define TIMER_DMACFG_DMATA_SMCFG DMACFG_DMATA(2) /*!< DMA transfer address is TIMER_SMCFG */ +#define TIMER_DMACFG_DMATA_DMAINTEN DMACFG_DMATA(3) /*!< DMA transfer address is TIMER_DMAINTEN */ +#define TIMER_DMACFG_DMATA_INTF DMACFG_DMATA(4) /*!< DMA transfer address is TIMER_INTF */ +#define TIMER_DMACFG_DMATA_SWEVG DMACFG_DMATA(5) /*!< DMA transfer address is TIMER_SWEVG */ +#define TIMER_DMACFG_DMATA_CHCTL0 DMACFG_DMATA(6) /*!< DMA transfer address is TIMER_CHCTL0 */ +#define TIMER_DMACFG_DMATA_CHCTL1 DMACFG_DMATA(7) /*!< DMA transfer address is TIMER_CHCTL1 */ +#define TIMER_DMACFG_DMATA_CHCTL2 DMACFG_DMATA(8) /*!< DMA transfer address is TIMER_CHCTL2 */ +#define TIMER_DMACFG_DMATA_CNT DMACFG_DMATA(9) /*!< DMA transfer address is TIMER_CNT */ +#define TIMER_DMACFG_DMATA_PSC DMACFG_DMATA(10) /*!< DMA transfer address is TIMER_PSC */ +#define TIMER_DMACFG_DMATA_CAR DMACFG_DMATA(11) /*!< DMA transfer address is TIMER_CAR */ +#define TIMER_DMACFG_DMATA_CREP DMACFG_DMATA(12) /*!< DMA transfer address is TIMER_CREP */ +#define TIMER_DMACFG_DMATA_CH0CV DMACFG_DMATA(13) /*!< DMA transfer address is TIMER_CH0CV */ +#define TIMER_DMACFG_DMATA_CH1CV DMACFG_DMATA(14) /*!< DMA transfer address is TIMER_CH1CV */ +#define TIMER_DMACFG_DMATA_CH2CV DMACFG_DMATA(15) /*!< DMA transfer address is TIMER_CH2CV */ +#define TIMER_DMACFG_DMATA_CH3CV DMACFG_DMATA(16) /*!< DMA transfer address is TIMER_CH3CV */ +#define TIMER_DMACFG_DMATA_CCHP DMACFG_DMATA(17) /*!< DMA transfer address is TIMER_CCHP */ +#define TIMER_DMACFG_DMATA_DMACFG DMACFG_DMATA(18) /*!< DMA transfer address is TIMER_DMACFG */ + +/* DMA access burst length */ +#define DMACFG_DMATC(regval) (BITS(8, 12) & ((uint32_t)(regval) << 8U)) +#define TIMER_DMACFG_DMATC_1TRANSFER DMACFG_DMATC(0) /*!< DMA transfer 1 time */ +#define TIMER_DMACFG_DMATC_2TRANSFER DMACFG_DMATC(1) /*!< DMA transfer 2 times */ +#define TIMER_DMACFG_DMATC_3TRANSFER DMACFG_DMATC(2) /*!< DMA transfer 3 times */ +#define TIMER_DMACFG_DMATC_4TRANSFER DMACFG_DMATC(3) /*!< DMA transfer 4 times */ +#define TIMER_DMACFG_DMATC_5TRANSFER DMACFG_DMATC(4) /*!< DMA transfer 5 times */ +#define TIMER_DMACFG_DMATC_6TRANSFER DMACFG_DMATC(5) /*!< DMA transfer 6 times */ +#define TIMER_DMACFG_DMATC_7TRANSFER DMACFG_DMATC(6) /*!< DMA transfer 7 times */ +#define TIMER_DMACFG_DMATC_8TRANSFER DMACFG_DMATC(7) /*!< DMA transfer 8 times */ +#define TIMER_DMACFG_DMATC_9TRANSFER DMACFG_DMATC(8) /*!< DMA transfer 9 times */ +#define TIMER_DMACFG_DMATC_10TRANSFER DMACFG_DMATC(9) /*!< DMA transfer 10 times */ +#define TIMER_DMACFG_DMATC_11TRANSFER DMACFG_DMATC(10) /*!< DMA transfer 11 times */ +#define TIMER_DMACFG_DMATC_12TRANSFER DMACFG_DMATC(11) /*!< DMA transfer 12 times */ +#define TIMER_DMACFG_DMATC_13TRANSFER DMACFG_DMATC(12) /*!< DMA transfer 13 times */ +#define TIMER_DMACFG_DMATC_14TRANSFER DMACFG_DMATC(13) /*!< DMA transfer 14 times */ +#define TIMER_DMACFG_DMATC_15TRANSFER DMACFG_DMATC(14) /*!< DMA transfer 15 times */ +#define TIMER_DMACFG_DMATC_16TRANSFER DMACFG_DMATC(15) /*!< DMA transfer 16 times */ +#define TIMER_DMACFG_DMATC_17TRANSFER DMACFG_DMATC(16) /*!< DMA transfer 17 times */ +#define TIMER_DMACFG_DMATC_18TRANSFER DMACFG_DMATC(17) /*!< DMA transfer 18 times */ + +/* TIMER software event generation source */ +#define TIMER_EVENT_SRC_UPG ((uint16_t)0x0001U) /*!< update event generation */ +#define TIMER_EVENT_SRC_CH0G ((uint16_t)0x0002U) /*!< channel 0 capture or compare event generation */ +#define TIMER_EVENT_SRC_CH1G ((uint16_t)0x0004U) /*!< channel 1 capture or compare event generation */ +#define TIMER_EVENT_SRC_CH2G ((uint16_t)0x0008U) /*!< channel 2 capture or compare event generation */ +#define TIMER_EVENT_SRC_CH3G ((uint16_t)0x0010U) /*!< channel 3 capture or compare event generation */ +#define TIMER_EVENT_SRC_CMTG ((uint16_t)0x0020U) /*!< channel commutation event generation */ +#define TIMER_EVENT_SRC_TRGG ((uint16_t)0x0040U) /*!< trigger event generation */ +#define TIMER_EVENT_SRC_BRKG ((uint16_t)0x0080U) /*!< break event generation */ + +/* center-aligned mode selection */ +#define CTL0_CAM(regval) ((uint16_t)(BITS(5, 6) & ((uint32_t)(regval) << 5U))) +#define TIMER_COUNTER_EDGE CTL0_CAM(0) /*!< edge-aligned mode */ +#define TIMER_COUNTER_CENTER_DOWN CTL0_CAM(1) /*!< center-aligned and counting down assert mode */ +#define TIMER_COUNTER_CENTER_UP CTL0_CAM(2) /*!< center-aligned and counting up assert mode */ +#define TIMER_COUNTER_CENTER_BOTH CTL0_CAM(3) /*!< center-aligned and counting up/down assert mode */ + +/* TIMER prescaler reload mode */ +#define TIMER_PSC_RELOAD_NOW TIMER_SWEVG_UPG /*!< the prescaler is loaded right now */ +#define TIMER_PSC_RELOAD_UPDATE ((uint32_t)0x00000000U) /*!< the prescaler is loaded at the next update event */ + +/* count direction */ +#define TIMER_COUNTER_UP ((uint16_t)0x0000U) /*!< counter up direction */ +#define TIMER_COUNTER_DOWN ((uint16_t)TIMER_CTL0_DIR) /*!< counter down direction */ + +/* specify division ratio between TIMER clock and dead-time and sampling clock */ +#define CTL0_CKDIV(regval) ((uint16_t)(BITS(8, 9) & ((uint32_t)(regval) << 8U))) +#define TIMER_CKDIV_DIV1 CTL0_CKDIV(0) /*!< clock division value is 1,fDTS=fTIMER_CK */ +#define TIMER_CKDIV_DIV2 CTL0_CKDIV(1) /*!< clock division value is 2,fDTS= fTIMER_CK/2 */ +#define TIMER_CKDIV_DIV4 CTL0_CKDIV(2) /*!< clock division value is 4, fDTS= fTIMER_CK/4 */ + +/* single pulse mode */ +#define TIMER_SP_MODE_SINGLE TIMER_CTL0_SPM /*!< single pulse mode */ +#define TIMER_SP_MODE_REPETITIVE ((uint32_t)0x00000000U) /*!< repetitive pulse mode */ + +/* update source */ +#define TIMER_UPDATE_SRC_REGULAR TIMER_CTL0_UPS /*!< update generate only by counter overflow/underflow */ +#define TIMER_UPDATE_SRC_GLOBAL ((uint32_t)0x00000000U) /*!< update generate by setting of UPG bit or the counter overflow/underflow,or the slave mode controller trigger */ + +/* run mode off-state configure */ +#define TIMER_ROS_STATE_ENABLE ((uint16_t)TIMER_CCHP_ROS) /*!< when POEN bit is set, the channel output signals(CHx_O/CHx_ON) are enabled, with relationship to CHxEN/CHxNEN bits */ +#define TIMER_ROS_STATE_DISABLE ((uint16_t)0x0000U) /*!< when POEN bit is set, the channel output signals(CHx_O/CHx_ON) are disabled */ + +/* idle mode off-state configure */ +#define TIMER_IOS_STATE_ENABLE ((uint16_t)TIMER_CCHP_IOS) /*!< when POEN bit is reset, he channel output signals(CHx_O/CHx_ON) are enabled, with relationship to CHxEN/CHxNEN bits */ +#define TIMER_IOS_STATE_DISABLE ((uint16_t)0x0000U) /*!< when POEN bit is reset, the channel output signals(CHx_O/CHx_ON) are disabled */ + +/* break input polarity */ +#define TIMER_BREAK_POLARITY_LOW ((uint16_t)0x0000U) /*!< break input polarity is low */ +#define TIMER_BREAK_POLARITY_HIGH ((uint16_t)TIMER_CCHP_BRKP) /*!< break input polarity is high */ + +/* output automatic enable */ +#define TIMER_OUTAUTO_ENABLE ((uint16_t)TIMER_CCHP_OAEN) /*!< output automatic enable */ +#define TIMER_OUTAUTO_DISABLE ((uint16_t)0x0000U) /*!< output automatic disable */ + +/* complementary register protect control */ +#define CCHP_PROT(regval) ((uint16_t)(BITS(8, 9) & ((uint32_t)(regval) << 8U))) +#define TIMER_CCHP_PROT_OFF CCHP_PROT(0) /*!< protect disable */ +#define TIMER_CCHP_PROT_0 CCHP_PROT(1) /*!< PROT mode 0 */ +#define TIMER_CCHP_PROT_1 CCHP_PROT(2) /*!< PROT mode 1 */ +#define TIMER_CCHP_PROT_2 CCHP_PROT(3) /*!< PROT mode 2 */ + +/* break input enable */ +#define TIMER_BREAK_ENABLE ((uint16_t)TIMER_CCHP_BRKEN) /*!< break input enable */ +#define TIMER_BREAK_DISABLE ((uint16_t)0x0000U) /*!< break input disable */ + +/* TIMER channel n(n=0,1,2,3) */ +#define TIMER_CH_0 ((uint16_t)0x0000U) /*!< TIMER channel 0(TIMERx(x=0..4,7..13)) */ +#define TIMER_CH_1 ((uint16_t)0x0001U) /*!< TIMER channel 1(TIMERx(x=0..4,7,8,11)) */ +#define TIMER_CH_2 ((uint16_t)0x0002U) /*!< TIMER channel 2(TIMERx(x=0..4,7)) */ +#define TIMER_CH_3 ((uint16_t)0x0003U) /*!< TIMER channel 3(TIMERx(x=0..4,7)) */ + +/* channel enable state */ +#define TIMER_CCX_ENABLE ((uint16_t)0x0001U) /*!< channel enable */ +#define TIMER_CCX_DISABLE ((uint16_t)0x0000U) /*!< channel disable */ + +/* channel complementary output enable state */ +#define TIMER_CCXN_ENABLE ((uint16_t)0x0004U) /*!< channel complementary enable */ +#define TIMER_CCXN_DISABLE ((uint16_t)0x0000U) /*!< channel complementary disable */ + +/* channel output polarity */ +#define TIMER_OC_POLARITY_HIGH ((uint16_t)0x0000U) /*!< channel output polarity is high */ +#define TIMER_OC_POLARITY_LOW ((uint16_t)0x0002U) /*!< channel output polarity is low */ + +/* channel complementary output polarity */ +#define TIMER_OCN_POLARITY_HIGH ((uint16_t)0x0000U) /*!< channel complementary output polarity is high */ +#define TIMER_OCN_POLARITY_LOW ((uint16_t)0x0008U) /*!< channel complementary output polarity is low */ + +/* idle state of channel output */ +#define TIMER_OC_IDLE_STATE_HIGH ((uint16_t)0x0100) /*!< idle state of channel output is high */ +#define TIMER_OC_IDLE_STATE_LOW ((uint16_t)0x0000) /*!< idle state of channel output is low */ + +/* idle state of channel complementary output */ +#define TIMER_OCN_IDLE_STATE_HIGH ((uint16_t)0x0200U) /*!< idle state of channel complementary output is high */ +#define TIMER_OCN_IDLE_STATE_LOW ((uint16_t)0x0000U) /*!< idle state of channel complementary output is low */ + +/* channel output compare mode */ +#define TIMER_OC_MODE_TIMING ((uint16_t)0x0000U) /*!< frozen mode */ +#define TIMER_OC_MODE_ACTIVE ((uint16_t)0x0010U) /*!< set the channel output */ +#define TIMER_OC_MODE_INACTIVE ((uint16_t)0x0020U) /*!< clear the channel output */ +#define TIMER_OC_MODE_TOGGLE ((uint16_t)0x0030U) /*!< toggle on match */ +#define TIMER_OC_MODE_LOW ((uint16_t)0x0040U) /*!< force low mode */ +#define TIMER_OC_MODE_HIGH ((uint16_t)0x0050U) /*!< force high mode */ +#define TIMER_OC_MODE_PWM0 ((uint16_t)0x0060U) /*!< PWM0 mode */ +#define TIMER_OC_MODE_PWM1 ((uint16_t)0x0070U) /*!< PWM1 mode*/ + +/* channel output compare shadow enable */ +#define TIMER_OC_SHADOW_ENABLE ((uint16_t)0x0008U) /*!< channel output shadow state enable */ +#define TIMER_OC_SHADOW_DISABLE ((uint16_t)0x0000U) /*!< channel output shadow state disable */ + +/* channel output compare fast enable */ +#define TIMER_OC_FAST_ENABLE ((uint16_t)0x0004) /*!< channel output fast function enable */ +#define TIMER_OC_FAST_DISABLE ((uint16_t)0x0000) /*!< channel output fast function disable */ + +/* channel output compare clear enable */ +#define TIMER_OC_CLEAR_ENABLE ((uint16_t)0x0080U) /*!< channel output clear function enable */ +#define TIMER_OC_CLEAR_DISABLE ((uint16_t)0x0000U) /*!< channel output clear function disable */ + +/* channel control shadow register update control */ +#define TIMER_UPDATECTL_CCU ((uint32_t)0x00000000U) /*!< the shadow registers update by when CMTG bit is set */ +#define TIMER_UPDATECTL_CCUTRI TIMER_CTL1_CCUC /*!< the shadow registers update by when CMTG bit is set or an rising edge of TRGI occurs */ + +/* channel input capture polarity */ +#define TIMER_IC_POLARITY_RISING ((uint16_t)0x0000U) /*!< input capture rising edge */ +#define TIMER_IC_POLARITY_FALLING ((uint16_t)0x0002U) /*!< input capture falling edge */ +#define TIMER_IC_POLARITY_BOTH_EDGE ((uint16_t)0x000AU) /*!< input capture both edge */ + +/* timer input capture selection */ +#define TIMER_IC_SELECTION_DIRECTTI ((uint16_t)0x0001U) /*!< channel y is configured as input and icy is mapped on CIy */ +#define TIMER_IC_SELECTION_INDIRECTTI ((uint16_t)0x0002U) /*!< channel y is configured as input and icy is mapped on opposite input */ +#define TIMER_IC_SELECTION_ITS ((uint16_t)0x0003U) /*!< channel y is configured as input and icy is mapped on ITS */ + +/* channel input capture prescaler */ +#define TIMER_IC_PSC_DIV1 ((uint16_t)0x0000U) /*!< no prescaler */ +#define TIMER_IC_PSC_DIV2 ((uint16_t)0x0004U) /*!< divided by 2 */ +#define TIMER_IC_PSC_DIV4 ((uint16_t)0x0008U) /*!< divided by 4 */ +#define TIMER_IC_PSC_DIV8 ((uint16_t)0x000CU) /*!< divided by 8 */ + +/* trigger selection */ +#define SMCFG_TRGSEL(regval) (BITS(4, 6) & ((uint32_t)(regval) << 4U)) +#define TIMER_SMCFG_TRGSEL_ITI0 SMCFG_TRGSEL(0) /*!< internal trigger 0 */ +#define TIMER_SMCFG_TRGSEL_ITI1 SMCFG_TRGSEL(1) /*!< internal trigger 1 */ +#define TIMER_SMCFG_TRGSEL_ITI2 SMCFG_TRGSEL(2) /*!< internal trigger 2 */ +#define TIMER_SMCFG_TRGSEL_ITI3 SMCFG_TRGSEL(3) /*!< internal trigger 3 */ +#define TIMER_SMCFG_TRGSEL_CI0F_ED SMCFG_TRGSEL(4) /*!< TI0 Edge Detector */ +#define TIMER_SMCFG_TRGSEL_CI0FE0 SMCFG_TRGSEL(5) /*!< filtered TIMER input 0 */ +#define TIMER_SMCFG_TRGSEL_CI1FE1 SMCFG_TRGSEL(6) /*!< filtered TIMER input 1 */ +#define TIMER_SMCFG_TRGSEL_ETIFP SMCFG_TRGSEL(7) /*!< external trigger */ + +/* master mode control */ +#define CTL1_MMC(regval) (BITS(4, 6) & ((uint32_t)(regval) << 4U)) +#define TIMER_TRI_OUT_SRC_RESET CTL1_MMC(0) /*!< the UPG bit as trigger output */ +#define TIMER_TRI_OUT_SRC_ENABLE CTL1_MMC(1) /*!< the counter enable signal TIMER_CTL0_CEN as trigger output */ +#define TIMER_TRI_OUT_SRC_UPDATE CTL1_MMC(2) /*!< update event as trigger output */ +#define TIMER_TRI_OUT_SRC_CH0 CTL1_MMC(3) /*!< a capture or a compare match occurred in channel 0 as trigger output TRGO */ +#define TIMER_TRI_OUT_SRC_O0CPRE CTL1_MMC(4) /*!< O0CPRE as trigger output */ +#define TIMER_TRI_OUT_SRC_O1CPRE CTL1_MMC(5) /*!< O1CPRE as trigger output */ +#define TIMER_TRI_OUT_SRC_O2CPRE CTL1_MMC(6) /*!< O2CPRE as trigger output */ +#define TIMER_TRI_OUT_SRC_O3CPRE CTL1_MMC(7) /*!< O3CPRE as trigger output */ + +/* slave mode control */ +#define SMCFG_SMC(regval) (BITS(0, 2) & ((uint32_t)(regval) << 0U)) +#define TIMER_SLAVE_MODE_DISABLE SMCFG_SMC(0) /*!< slave mode disable */ +#define TIMER_ENCODER_MODE0 SMCFG_SMC(1) /*!< encoder mode 0 */ +#define TIMER_ENCODER_MODE1 SMCFG_SMC(2) /*!< encoder mode 1 */ +#define TIMER_ENCODER_MODE2 SMCFG_SMC(3) /*!< encoder mode 2 */ +#define TIMER_SLAVE_MODE_RESTART SMCFG_SMC(4) /*!< restart mode */ +#define TIMER_SLAVE_MODE_PAUSE SMCFG_SMC(5) /*!< pause mode */ +#define TIMER_SLAVE_MODE_EVENT SMCFG_SMC(6) /*!< event mode */ +#define TIMER_SLAVE_MODE_EXTERNAL0 SMCFG_SMC(7) /*!< external clock mode 0 */ + +/* master slave mode selection */ +#define TIMER_MASTER_SLAVE_MODE_ENABLE TIMER_SMCFG_MSM /*!< master slave mode enable */ +#define TIMER_MASTER_SLAVE_MODE_DISABLE ((uint32_t)0x00000000U) /*!< master slave mode disable */ + +/* external trigger prescaler */ +#define SMCFG_ETPSC(regval) (BITS(12, 13) & ((uint32_t)(regval) << 12U)) +#define TIMER_EXT_TRI_PSC_OFF SMCFG_ETPSC(0) /*!< no divided */ +#define TIMER_EXT_TRI_PSC_DIV2 SMCFG_ETPSC(1) /*!< divided by 2 */ +#define TIMER_EXT_TRI_PSC_DIV4 SMCFG_ETPSC(2) /*!< divided by 4 */ +#define TIMER_EXT_TRI_PSC_DIV8 SMCFG_ETPSC(3) /*!< divided by 8 */ + +/* external trigger polarity */ +#define TIMER_ETP_FALLING TIMER_SMCFG_ETP /*!< active low or falling edge active */ +#define TIMER_ETP_RISING ((uint32_t)0x00000000U) /*!< active high or rising edge active */ + +/* channel 0 trigger input selection */ +#define TIMER_HALLINTERFACE_ENABLE TIMER_CTL1_TI0S /*!< TIMER hall sensor mode enable */ +#define TIMER_HALLINTERFACE_DISABLE ((uint32_t)0x00000000U) /*!< TIMER hall sensor mode disable */ + +/* TIMERx(x=0..4,7..13) write CHxVAL register selection */ +#define TIMER_CHVSEL_ENABLE ((uint16_t)TIMER_CFG_OUTSEL) /*!< write CHxVAL register selection enable */ +#define TIMER_CHVSEL_DISABLE ((uint16_t)0x0000U) /*!< write CHxVAL register selection disable */ + +/* function declarations */ +/* TIMER timebase */ +/* deinit a TIMER */ +void timer_deinit(uint32_t timer_periph); +/* initialize TIMER init parameter struct */ +void timer_struct_para_init(timer_parameter_struct* initpara); +/* initialize TIMER counter */ +void timer_init(uint32_t timer_periph, timer_parameter_struct* initpara); +/* enable a TIMER */ +void timer_enable(uint32_t timer_periph); +/* disable a TIMER */ +void timer_disable(uint32_t timer_periph); +/* enable the auto reload shadow function */ +void timer_auto_reload_shadow_enable(uint32_t timer_periph); +/* disable the auto reload shadow function */ +void timer_auto_reload_shadow_disable(uint32_t timer_periph); +/* enable the update event */ +void timer_update_event_enable(uint32_t timer_periph); +/* disable the update event */ +void timer_update_event_disable(uint32_t timer_periph); +/* set TIMER counter alignment mode */ +void timer_counter_alignment(uint32_t timer_periph, uint16_t aligned); +/* set TIMER counter up direction */ +void timer_counter_up_direction(uint32_t timer_periph); +/* set TIMER counter down direction */ +void timer_counter_down_direction(uint32_t timer_periph); +/* configure TIMER prescaler */ +void timer_prescaler_config(uint32_t timer_periph, uint16_t prescaler, uint32_t pscreload); +/* configure TIMER repetition register value */ +void timer_repetition_value_config(uint32_t timer_periph, uint8_t repetition); +/* configure TIMER autoreload register value */ +void timer_autoreload_value_config(uint32_t timer_periph, uint32_t autoreload); +/* configure TIMER counter register value */ +void timer_counter_value_config(uint32_t timer_periph, uint32_t counter); +/* read TIMER counter value */ +uint32_t timer_counter_read(uint32_t timer_periph); +/* read TIMER prescaler value */ +uint16_t timer_prescaler_read(uint32_t timer_periph); +/* configure TIMER single pulse mode */ +void timer_single_pulse_mode_config(uint32_t timer_periph, uint32_t spmode); +/* configure TIMER update source */ +void timer_update_source_config(uint32_t timer_periph, uint32_t update); + +/* timer DMA and event */ +/* enable the TIMER DMA */ +void timer_dma_enable(uint32_t timer_periph, uint16_t dma); +/* disable the TIMER DMA */ +void timer_dma_disable(uint32_t timer_periph, uint16_t dma); +/* channel DMA request source selection */ +void timer_channel_dma_request_source_select(uint32_t timer_periph, uint32_t dma_request); +/* configure the TIMER DMA transfer */ +void timer_dma_transfer_config(uint32_t timer_periph, uint32_t dma_baseaddr, uint32_t dma_lenth); +/* software generate events */ +void timer_event_software_generate(uint32_t timer_periph, uint16_t event); + +/* TIMER channel complementary protection */ +/* initialize TIMER break parameter struct */ +void timer_break_struct_para_init(timer_break_parameter_struct* breakpara); +/* configure TIMER break function */ +void timer_break_config(uint32_t timer_periph, timer_break_parameter_struct* breakpara); +/* enable TIMER break function */ +void timer_break_enable(uint32_t timer_periph); +/* disable TIMER break function */ +void timer_break_disable(uint32_t timer_periph); +/* enable TIMER output automatic function */ +void timer_automatic_output_enable(uint32_t timer_periph); +/* disable TIMER output automatic function */ +void timer_automatic_output_disable(uint32_t timer_periph); +/* enable or disable TIMER primary output function */ +void timer_primary_output_config(uint32_t timer_periph, ControlStatus newvalue); +/* enable or disable channel capture/compare control shadow register */ +void timer_channel_control_shadow_config(uint32_t timer_periph, ControlStatus newvalue); +/* configure TIMER channel control shadow register update control */ +void timer_channel_control_shadow_update_config(uint32_t timer_periph, uint32_t ccuctl); + +/* TIMER channel output */ +/* initialize TIMER channel output parameter struct */ +void timer_channel_output_struct_para_init(timer_oc_parameter_struct* ocpara); +/* configure TIMER channel output function */ +void timer_channel_output_config(uint32_t timer_periph, uint16_t channel, timer_oc_parameter_struct* ocpara); +/* configure TIMER channel output compare mode */ +void timer_channel_output_mode_config(uint32_t timer_periph, uint16_t channel, uint16_t ocmode); +/* configure TIMER channel output pulse value */ +void timer_channel_output_pulse_value_config(uint32_t timer_periph, uint16_t channel, uint16_t pulse); +/* configure TIMER channel output shadow function */ +void timer_channel_output_shadow_config(uint32_t timer_periph, uint16_t channel, uint16_t ocshadow); +/* configure TIMER channel output fast function */ +void timer_channel_output_fast_config(uint32_t timer_periph, uint16_t channel, uint16_t ocfast); +/* configure TIMER channel output clear function */ +void timer_channel_output_clear_config(uint32_t timer_periph, uint16_t channel, uint16_t occlear); +/* configure TIMER channel output polarity */ +void timer_channel_output_polarity_config(uint32_t timer_periph, uint16_t channel, uint16_t ocpolarity); +/* configure TIMER channel complementary output polarity */ +void timer_channel_complementary_output_polarity_config(uint32_t timer_periph, uint16_t channel, uint16_t ocnpolarity); +/* configure TIMER channel enable state */ +void timer_channel_output_state_config(uint32_t timer_periph, uint16_t channel, uint32_t state); +/* configure TIMER channel complementary output enable state */ +void timer_channel_complementary_output_state_config(uint32_t timer_periph, uint16_t channel, uint16_t ocnstate); + +/* TIMER channel input */ +/* initialize TIMER channel input parameter struct */ +void timer_channel_input_struct_para_init(timer_ic_parameter_struct* icpara); +/* configure TIMER input capture parameter */ +void timer_input_capture_config(uint32_t timer_periph, uint16_t channel, timer_ic_parameter_struct* icpara); +/* configure TIMER channel input capture prescaler value */ +void timer_channel_input_capture_prescaler_config(uint32_t timer_periph, uint16_t channel, uint16_t prescaler); +/* read TIMER channel capture compare register value */ +uint32_t timer_channel_capture_value_register_read(uint32_t timer_periph, uint16_t channel); +/* configure TIMER input pwm capture function */ +void timer_input_pwm_capture_config(uint32_t timer_periph, uint16_t channel, timer_ic_parameter_struct* icpwm); +/* configure TIMER hall sensor mode */ +void timer_hall_mode_config(uint32_t timer_periph, uint32_t hallmode); + +/* TIMER master and slave */ +/* select TIMER input trigger source */ +void timer_input_trigger_source_select(uint32_t timer_periph, uint32_t intrigger); +/* select TIMER master mode output trigger source */ +void timer_master_output_trigger_source_select(uint32_t timer_periph, uint32_t outrigger); +/* select TIMER slave mode */ +void timer_slave_mode_select(uint32_t timer_periph, uint32_t slavemode); +/* configure TIMER master slave mode */ +void timer_master_slave_mode_config(uint32_t timer_periph, uint32_t masterslave); +/* configure TIMER external trigger input */ +void timer_external_trigger_config(uint32_t timer_periph, uint32_t extprescaler, uint32_t extpolarity, uint8_t extfilter); +/* configure TIMER quadrature decoder mode */ +void timer_quadrature_decoder_mode_config(uint32_t timer_periph, uint32_t decomode, uint16_t ic0polarity, uint16_t ic1polarity); +/* configure TIMER internal clock mode */ +void timer_internal_clock_config(uint32_t timer_periph); +/* configure TIMER the internal trigger as external clock input */ +void timer_internal_trigger_as_external_clock_config(uint32_t timer_periph, uint32_t intrigger); +/* configure TIMER the external trigger as external clock input */ +void timer_external_trigger_as_external_clock_config(uint32_t timer_periph, uint32_t extrigger, uint16_t extpolarity, uint8_t extfilter); +/* configure TIMER the external clock mode 0 */ +void timer_external_clock_mode0_config(uint32_t timer_periph, uint32_t extprescaler, uint32_t extpolarity, uint8_t extfilter); +/* configure TIMER the external clock mode 1 */ +void timer_external_clock_mode1_config(uint32_t timer_periph, uint32_t extprescaler, uint32_t extpolarity, uint8_t extfilter); +/* disable TIMER the external clock mode 1 */ +void timer_external_clock_mode1_disable(uint32_t timer_periph); + +/* TIMER interrupt and flag */ +/* enable the TIMER interrupt */ +void timer_interrupt_enable(uint32_t timer_periph, uint32_t interrupt); +/* disable the TIMER interrupt */ +void timer_interrupt_disable(uint32_t timer_periph, uint32_t interrupt); +/* get TIMER interrupt flag */ +FlagStatus timer_interrupt_flag_get(uint32_t timer_periph, uint32_t interrupt); +/* clear TIMER interrupt flag */ +void timer_interrupt_flag_clear(uint32_t timer_periph, uint32_t interrupt); +/* get TIMER flag */ +FlagStatus timer_flag_get(uint32_t timer_periph, uint32_t flag); +/* clear TIMER flag */ +void timer_flag_clear(uint32_t timer_periph, uint32_t flag); + +#endif /* GD32E10X_TIMER_H */ diff --git a/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_standard_peripheral/Include/gd32f10x_usart.h b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_standard_peripheral/Include/gd32f10x_usart.h new file mode 100644 index 0000000000..8a3ea37581 --- /dev/null +++ b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_standard_peripheral/Include/gd32f10x_usart.h @@ -0,0 +1,377 @@ +/*! + \file gd32f10x_usart.h + \brief definitions for the USART + + \version 2014-12-26, V1.0.0, firmware for GD32F10x + \version 2017-06-20, V2.0.1, firmware for GD32F10x + \version 2018-07-31, V2.1.0, firmware for GD32F10x + \version 2020-09-30, V2.2.0, firmware for GD32F10x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef GD32F10X_USART_H +#define GD32F10X_USART_H + +#include "gd32f10x.h" + +/* USARTx(x=0,1,2)/UARTx(x=3,4) definitions */ +#define USART1 USART_BASE /*!< USART1 base address */ +#define USART2 (USART_BASE+(0x00000400U)) /*!< USART2 base address */ +#define UART3 (USART_BASE+(0x00000800U)) /*!< UART3 base address */ +#define UART4 (USART_BASE+(0x00000C00U)) /*!< UART4 base address */ +#define USART0 (USART_BASE+(0x0000F400U)) /*!< USART0 base address */ + +/* registers definitions */ +#define USART_STAT(usartx) REG32((usartx) + (0x00000000U)) /*!< USART status register */ +#define USART_DATA(usartx) REG32((usartx) + (0x00000004U)) /*!< USART data register */ +#define USART_BAUD(usartx) REG32((usartx) + (0x00000008U)) /*!< USART baud rate register */ +#define USART_CTL0(usartx) REG32((usartx) + (0x0000000CU)) /*!< USART control register 0 */ +#define USART_CTL1(usartx) REG32((usartx) + (0x00000010U)) /*!< USART control register 1 */ +#define USART_CTL2(usartx) REG32((usartx) + (0x00000014U)) /*!< USART control register 2 */ +#define USART_GP(usartx) REG32((usartx) + (0x00000018U)) /*!< USART guard time and prescaler register */ + +/* bits definitions */ +/* USARTx_STAT */ +#define USART_STAT_PERR BIT(0) /*!< parity error flag */ +#define USART_STAT_FERR BIT(1) /*!< frame error flag */ +#define USART_STAT_NERR BIT(2) /*!< noise error flag */ +#define USART_STAT_ORERR BIT(3) /*!< overrun error */ +#define USART_STAT_IDLEF BIT(4) /*!< IDLE frame detected flag */ +#define USART_STAT_RBNE BIT(5) /*!< read data buffer not empty */ +#define USART_STAT_TC BIT(6) /*!< transmission complete */ +#define USART_STAT_TBE BIT(7) /*!< transmit data buffer empty */ +#define USART_STAT_LBDF BIT(8) /*!< LIN break detected flag */ +#define USART_STAT_CTSF BIT(9) /*!< CTS change flag */ + +/* USARTx_DATA */ +#define USART_DATA_DATA BITS(0,8) /*!< transmit or read data value */ + +/* USARTx_BAUD */ +#define USART_BAUD_FRADIV BITS(0,3) /*!< fraction part of baud-rate divider */ +#define USART_BAUD_INTDIV BITS(4,15) /*!< integer part of baud-rate divider */ + +/* USARTx_CTL0 */ +#define USART_CTL0_SBKCMD BIT(0) /*!< send break command */ +#define USART_CTL0_RWU BIT(1) /*!< receiver wakeup from mute mode */ +#define USART_CTL0_REN BIT(2) /*!< receiver enable */ +#define USART_CTL0_TEN BIT(3) /*!< transmitter enable */ +#define USART_CTL0_IDLEIE BIT(4) /*!< idle line detected interrupt enable */ +#define USART_CTL0_RBNEIE BIT(5) /*!< read data buffer not empty interrupt and overrun error interrupt enable */ +#define USART_CTL0_TCIE BIT(6) /*!< transmission complete interrupt enable */ +#define USART_CTL0_TBEIE BIT(7) /*!< transmitter buffer empty interrupt enable */ +#define USART_CTL0_PERRIE BIT(8) /*!< parity error interrupt enable */ +#define USART_CTL0_PM BIT(9) /*!< parity mode */ +#define USART_CTL0_PCEN BIT(10) /*!< parity check function enable */ +#define USART_CTL0_WM BIT(11) /*!< wakeup method in mute mode */ +#define USART_CTL0_WL BIT(12) /*!< word length */ +#define USART_CTL0_UEN BIT(13) /*!< USART enable */ + +/* USARTx_CTL1 */ +#define USART_CTL1_ADDR BITS(0,3) /*!< address of USART */ +#define USART_CTL1_LBLEN BIT(5) /*!< LIN break frame length */ +#define USART_CTL1_LBDIE BIT(6) /*!< LIN break detected interrupt eanble */ +#define USART_CTL1_CLEN BIT(8) /*!< CK length */ +#define USART_CTL1_CPH BIT(9) /*!< CK phase */ +#define USART_CTL1_CPL BIT(10) /*!< CK polarity */ +#define USART_CTL1_CKEN BIT(11) /*!< CK pin enable */ +#define USART_CTL1_STB BITS(12,13) /*!< STOP bits length */ +#define USART_CTL1_LMEN BIT(14) /*!< LIN mode enable */ + +/* USARTx_CTL2 */ +#define USART_CTL2_ERRIE BIT(0) /*!< error interrupt enable */ +#define USART_CTL2_IREN BIT(1) /*!< IrDA mode enable */ +#define USART_CTL2_IRLP BIT(2) /*!< IrDA low-power */ +#define USART_CTL2_HDEN BIT(3) /*!< half-duplex enable */ +#define USART_CTL2_NKEN BIT(4) /*!< NACK enable in smartcard mode */ +#define USART_CTL2_SCEN BIT(5) /*!< smartcard mode enable */ +#define USART_CTL2_DENR BIT(6) /*!< DMA request enable for reception */ +#define USART_CTL2_DENT BIT(7) /*!< DMA request enable for transmission */ +#define USART_CTL2_RTSEN BIT(8) /*!< RTS enable */ +#define USART_CTL2_CTSEN BIT(9) /*!< CTS enable */ +#define USART_CTL2_CTSIE BIT(10) /*!< CTS interrupt enable */ + +/* USARTx_GP */ +#define USART_GP_PSC BITS(0,7) /*!< prescaler value for dividing the system clock */ +#define USART_GP_GUAT BITS(8,15) /*!< guard time value in smartcard mode */ + +/* constants definitions */ +/* define the USART bit position and its register index offset */ +#define USART_REGIDX_BIT(regidx, bitpos) (((uint32_t)(regidx) << 6) | (uint32_t)(bitpos)) +#define USART_REG_VAL(usartx, offset) (REG32((usartx) + (((uint32_t)(offset) & (0x0000FFFFU)) >> 6))) +#define USART_BIT_POS(val) ((uint32_t)(val) & (0x0000001FU)) +#define USART_REGIDX_BIT2(regidx, bitpos, regidx2, bitpos2) (((uint32_t)(regidx2) << 22) | (uint32_t)((bitpos2) << 16)\ + | (((uint32_t)(regidx) << 6) | (uint32_t)(bitpos))) +#define USART_REG_VAL2(usartx, offset) (REG32((usartx) + ((uint32_t)(offset) >> 22))) +#define USART_BIT_POS2(val) (((uint32_t)(val) & (0x001F0000U)) >> 16) + +/* register offset */ +#define USART_STAT_REG_OFFSET (0x00000000U) /*!< STAT register offset */ +#define USART_CTL0_REG_OFFSET (0x0000000CU) /*!< CTL0 register offset */ +#define USART_CTL1_REG_OFFSET (0x00000010U) /*!< CTL1 register offset */ +#define USART_CTL2_REG_OFFSET (0x00000014U) /*!< CTL2 register offset */ + +/* USART flags */ +typedef enum +{ + /* flags in STAT register */ + USART_FLAG_CTSF = USART_REGIDX_BIT(USART_STAT_REG_OFFSET, 9U), /*!< CTS change flag */ + USART_FLAG_LBDF = USART_REGIDX_BIT(USART_STAT_REG_OFFSET, 8U), /*!< LIN break detected flag */ + USART_FLAG_TBE = USART_REGIDX_BIT(USART_STAT_REG_OFFSET, 7U), /*!< transmit data buffer empty */ + USART_FLAG_TC = USART_REGIDX_BIT(USART_STAT_REG_OFFSET, 6U), /*!< transmission complete */ + USART_FLAG_RBNE = USART_REGIDX_BIT(USART_STAT_REG_OFFSET, 5U), /*!< read data buffer not empty */ + USART_FLAG_IDLEF = USART_REGIDX_BIT(USART_STAT_REG_OFFSET, 4U), /*!< IDLE frame detected flag */ + USART_FLAG_ORERR = USART_REGIDX_BIT(USART_STAT_REG_OFFSET, 3U), /*!< overrun error */ + USART_FLAG_NERR = USART_REGIDX_BIT(USART_STAT_REG_OFFSET, 2U), /*!< noise error flag */ + USART_FLAG_FERR = USART_REGIDX_BIT(USART_STAT_REG_OFFSET, 1U), /*!< frame error flag */ + USART_FLAG_PERR = USART_REGIDX_BIT(USART_STAT_REG_OFFSET, 0U), /*!< parity error flag */ +}usart_flag_enum; + +/* USART interrupt flags */ +typedef enum +{ + /* interrupt flags in CTL0 register */ + USART_INT_FLAG_PERR = USART_REGIDX_BIT2(USART_CTL0_REG_OFFSET, 8U, USART_STAT_REG_OFFSET, 0U), /*!< parity error interrupt and flag */ + USART_INT_FLAG_TBE = USART_REGIDX_BIT2(USART_CTL0_REG_OFFSET, 7U, USART_STAT_REG_OFFSET, 7U), /*!< transmitter buffer empty interrupt and flag */ + USART_INT_FLAG_TC = USART_REGIDX_BIT2(USART_CTL0_REG_OFFSET, 6U, USART_STAT_REG_OFFSET, 6U), /*!< transmission complete interrupt and flag */ + USART_INT_FLAG_RBNE = USART_REGIDX_BIT2(USART_CTL0_REG_OFFSET, 5U, USART_STAT_REG_OFFSET, 5U), /*!< read data buffer not empty interrupt and flag */ + USART_INT_FLAG_RBNE_ORERR = USART_REGIDX_BIT2(USART_CTL0_REG_OFFSET, 5U, USART_STAT_REG_OFFSET, 3U), /*!< read data buffer not empty interrupt and overrun error flag */ + USART_INT_FLAG_IDLE = USART_REGIDX_BIT2(USART_CTL0_REG_OFFSET, 4U, USART_STAT_REG_OFFSET, 4U), /*!< IDLE line detected interrupt and flag */ + /* interrupt flags in CTL1 register */ + USART_INT_FLAG_LBD = USART_REGIDX_BIT2(USART_CTL1_REG_OFFSET, 6U, USART_STAT_REG_OFFSET, 8U), /*!< LIN break detected interrupt and flag */ + /* interrupt flags in CTL2 register */ + USART_INT_FLAG_CTS = USART_REGIDX_BIT2(USART_CTL2_REG_OFFSET, 10U, USART_STAT_REG_OFFSET, 9U), /*!< CTS interrupt and flag */ + USART_INT_FLAG_ERR_ORERR = USART_REGIDX_BIT2(USART_CTL2_REG_OFFSET, 0U, USART_STAT_REG_OFFSET, 3U), /*!< error interrupt and overrun error */ + USART_INT_FLAG_ERR_NERR = USART_REGIDX_BIT2(USART_CTL2_REG_OFFSET, 0U, USART_STAT_REG_OFFSET, 2U), /*!< error interrupt and noise error flag */ + USART_INT_FLAG_ERR_FERR = USART_REGIDX_BIT2(USART_CTL2_REG_OFFSET, 0U, USART_STAT_REG_OFFSET, 1U), /*!< error interrupt and frame error flag */ +}usart_interrupt_flag_enum; + +/* USART interrupt enable or disable */ +typedef enum +{ + /* interrupt in CTL0 register */ + USART_INT_PERR = USART_REGIDX_BIT(USART_CTL0_REG_OFFSET, 8U), /*!< parity error interrupt */ + USART_INT_TBE = USART_REGIDX_BIT(USART_CTL0_REG_OFFSET, 7U), /*!< transmitter buffer empty interrupt */ + USART_INT_TC = USART_REGIDX_BIT(USART_CTL0_REG_OFFSET, 6U), /*!< transmission complete interrupt */ + USART_INT_RBNE = USART_REGIDX_BIT(USART_CTL0_REG_OFFSET, 5U), /*!< read data buffer not empty interrupt and overrun error interrupt */ + USART_INT_IDLE = USART_REGIDX_BIT(USART_CTL0_REG_OFFSET, 4U), /*!< IDLE line detected interrupt */ + /* interrupt in CTL1 register */ + USART_INT_LBD = USART_REGIDX_BIT(USART_CTL1_REG_OFFSET, 6U), /*!< LIN break detected interrupt */ + /* interrupt in CTL2 register */ + USART_INT_CTS = USART_REGIDX_BIT(USART_CTL2_REG_OFFSET, 10U), /*!< CTS interrupt */ + USART_INT_ERR = USART_REGIDX_BIT(USART_CTL2_REG_OFFSET, 0U), /*!< error interrupt */ +}usart_interrupt_enum; + +/* USART receiver configure */ +#define CTL0_REN(regval) (BIT(2) & ((uint32_t)(regval) << 2)) +#define USART_RECEIVE_ENABLE CTL0_REN(1) /*!< enable receiver */ +#define USART_RECEIVE_DISABLE CTL0_REN(0) /*!< disable receiver */ + +/* USART transmitter configure */ +#define CTL0_TEN(regval) (BIT(3) & ((uint32_t)(regval) << 3)) +#define USART_TRANSMIT_ENABLE CTL0_TEN(1) /*!< enable transmitter */ +#define USART_TRANSMIT_DISABLE CTL0_TEN(0) /*!< disable transmitter */ + +/* USART parity bits definitions */ +#define CTL0_PM(regval) (BITS(9,10) & ((uint32_t)(regval) << 9)) +#define USART_PM_NONE CTL0_PM(0) /*!< no parity */ +#define USART_PM_EVEN CTL0_PM(2) /*!< even parity */ +#define USART_PM_ODD CTL0_PM(3) /*!< odd parity */ + +/* USART wakeup method in mute mode */ +#define CTL0_WM(regval) (BIT(11) & ((uint32_t)(regval) << 11)) +#define USART_WM_IDLE CTL0_WM(0) /*!< idle line */ +#define USART_WM_ADDR CTL0_WM(1) /*!< address match */ + +/* USART word length definitions */ +#define CTL0_WL(regval) (BIT(12) & ((uint32_t)(regval) << 12)) +#define USART_WL_8BIT CTL0_WL(0) /*!< 8 bits */ +#define USART_WL_9BIT CTL0_WL(1) /*!< 9 bits */ + +/* USART stop bits definitions */ +#define CTL1_STB(regval) (BITS(12,13) & ((uint32_t)(regval) << 12)) +#define USART_STB_1BIT CTL1_STB(0) /*!< 1 bit */ +#define USART_STB_0_5BIT CTL1_STB(1) /*!< 0.5 bit */ +#define USART_STB_2BIT CTL1_STB(2) /*!< 2 bits */ +#define USART_STB_1_5BIT CTL1_STB(3) /*!< 1.5 bits */ + +/* USART LIN break frame length */ +#define CTL1_LBLEN(regval) (BIT(5) & ((uint32_t)(regval) << 5)) +#define USART_LBLEN_10B CTL1_LBLEN(0) /*!< 10 bits */ +#define USART_LBLEN_11B CTL1_LBLEN(1) /*!< 11 bits */ + +/* USART CK length */ +#define CTL1_CLEN(regval) (BIT(8) & ((uint32_t)(regval) << 8)) +#define USART_CLEN_NONE CTL1_CLEN(0) /*!< there are 7 CK pulses for an 8 bit frame and 8 CK pulses for a 9 bit frame */ +#define USART_CLEN_EN CTL1_CLEN(1) /*!< there are 8 CK pulses for an 8 bit frame and 9 CK pulses for a 9 bit frame */ + +/* USART clock phase */ +#define CTL1_CPH(regval) (BIT(9) & ((uint32_t)(regval) << 9)) +#define USART_CPH_1CK CTL1_CPH(0) /*!< first clock transition is the first data capture edge */ +#define USART_CPH_2CK CTL1_CPH(1) /*!< second clock transition is the first data capture edge */ + +/* USART clock polarity */ +#define CTL1_CPL(regval) (BIT(10) & ((uint32_t)(regval) << 10)) +#define USART_CPL_LOW CTL1_CPL(0) /*!< steady low value on CK pin */ +#define USART_CPL_HIGH CTL1_CPL(1) /*!< steady high value on CK pin */ + +/* USART DMA request for receive configure */ +#define CLT2_DENR(regval) (BIT(6) & ((uint32_t)(regval) << 6)) +#define USART_DENR_ENABLE CLT2_DENR(1) /*!< DMA request enable for reception */ +#define USART_DENR_DISABLE CLT2_DENR(0) /*!< DMA request disable for reception */ + +/* USART DMA request for transmission configure */ +#define CLT2_DENT(regval) (BIT(7) & ((uint32_t)(regval) << 7)) +#define USART_DENT_ENABLE CLT2_DENT(1) /*!< DMA request enable for transmission */ +#define USART_DENT_DISABLE CLT2_DENT(0) /*!< DMA request disable for transmission */ + +/* USART RTS configure */ +#define CLT2_RTSEN(regval) (BIT(8) & ((uint32_t)(regval) << 8)) +#define USART_RTS_ENABLE CLT2_RTSEN(1) /*!< RTS enable */ +#define USART_RTS_DISABLE CLT2_RTSEN(0) /*!< RTS disable */ + +/* USART CTS configure */ +#define CLT2_CTSEN(regval) (BIT(9) & ((uint32_t)(regval) << 9)) +#define USART_CTS_ENABLE CLT2_CTSEN(1) /*!< CTS enable */ +#define USART_CTS_DISABLE CLT2_CTSEN(0) /*!< CTS disable */ + +/* USART IrDA low-power enable */ +#define CTL2_IRLP(regval) (BIT(2) & ((uint32_t)(regval) << 2)) +#define USART_IRLP_LOW CTL2_IRLP(1) /*!< low-power */ +#define USART_IRLP_NORMAL CTL2_IRLP(0) /*!< normal */ + +/* function declarations */ +/* initialization functions */ +/* reset USART */ +void usart_deinit(uint32_t usart_periph); +/* configure USART baud rate value */ +void usart_baudrate_set(uint32_t usart_periph, uint32_t baudval); +/* configure USART parity function */ +void usart_parity_config(uint32_t usart_periph, uint32_t paritycfg); +/* configure USART word length */ +void usart_word_length_set(uint32_t usart_periph, uint32_t wlen); +/* configure USART stop bit length */ +void usart_stop_bit_set(uint32_t usart_periph, uint32_t stblen); + +/* USART normal mode communication */ +/* enable USART */ +void usart_enable(uint32_t usart_periph); +/* disable USART */ +void usart_disable(uint32_t usart_periph); +/* configure USART transmitter */ +void usart_transmit_config(uint32_t usart_periph, uint32_t txconfig); +/* configure USART receiver */ +void usart_receive_config(uint32_t usart_periph, uint32_t rxconfig); +/* USART transmit data function */ +void usart_data_transmit(uint32_t usart_periph, uint16_t data); +/* USART receive data function */ +uint16_t usart_data_receive(uint32_t usart_periph); + +/* multi-processor communication */ +/* configure address of the USART */ +void usart_address_config(uint32_t usart_periph, uint8_t addr); +/* enable mute mode */ +void usart_mute_mode_enable(uint32_t usart_periph); +/* disable mute mode */ +void usart_mute_mode_disable(uint32_t usart_periph); +/* configure wakeup method in mute mode */ +void usart_mute_mode_wakeup_config(uint32_t usart_periph, uint32_t wmethod); + +/* LIN mode communication */ +/* LIN mode enable */ +void usart_lin_mode_enable(uint32_t usart_periph); +/* LIN mode disable */ +void usart_lin_mode_disable(uint32_t usart_periph); +/* LIN break detection length */ +void usart_lin_break_detection_length_config(uint32_t usart_periph, uint32_t lblen); +/* send break frame */ +void usart_send_break(uint32_t usart_periph); + +/* half-duplex communication */ +/* half-duplex enable */ +void usart_halfduplex_enable(uint32_t usart_periph); +/* half-duplex disable */ +void usart_halfduplex_disable(uint32_t usart_periph); + +/* synchronous communication */ +/* clock enable */ +void usart_synchronous_clock_enable(uint32_t usart_periph); +/* clock disable */ +void usart_synchronous_clock_disable(uint32_t usart_periph); +/* configure usart synchronous mode parameters */ +void usart_synchronous_clock_config(uint32_t usart_periph, uint32_t clen, uint32_t cph, uint32_t cpl); + +/* smartcard communication */ +/* guard time value configure in smartcard mode */ +void usart_guard_time_config(uint32_t usart_periph,uint32_t gaut); +/* smartcard mode enable */ +void usart_smartcard_mode_enable(uint32_t usart_periph); +/* smartcard mode disable */ +void usart_smartcard_mode_disable(uint32_t usart_periph); +/* NACK enable in smartcard mode */ +void usart_smartcard_mode_nack_enable(uint32_t usart_periph); +/* NACK disable in smartcard mode */ +void usart_smartcard_mode_nack_disable(uint32_t usart_periph); + +/* IrDA communication */ +/* enable IrDA mode */ +void usart_irda_mode_enable(uint32_t usart_periph); +/* disable IrDA mode */ +void usart_irda_mode_disable(uint32_t usart_periph); +/* configure the peripheral clock prescaler */ +void usart_prescaler_config(uint32_t usart_periph, uint8_t psc); +/* configure IrDA low-power */ +void usart_irda_lowpower_config(uint32_t usart_periph, uint32_t irlp); + +/* hardware flow communication */ +/* configure hardware flow control RTS */ +void usart_hardware_flow_rts_config(uint32_t usart_periph, uint32_t rtsconfig); +/* configure hardware flow control CTS */ +void usart_hardware_flow_cts_config(uint32_t usart_periph, uint32_t ctsconfig); + +/* configure USART DMA for reception */ +void usart_dma_receive_config(uint32_t usart_periph, uint32_t dmacmd); +/* configure USART DMA for transmission */ +void usart_dma_transmit_config(uint32_t usart_periph, uint32_t dmacmd); + +/* flag functions */ +/* get flag in STAT register */ +FlagStatus usart_flag_get(uint32_t usart_periph, usart_flag_enum flag); +/* clear flag in STAT register */ +void usart_flag_clear(uint32_t usart_periph, usart_flag_enum flag); + +/* interrupt functions */ +/* enable USART interrupt */ +void usart_interrupt_enable(uint32_t usart_periph, uint32_t int_flag); +/* disable USART interrupt */ +void usart_interrupt_disable(uint32_t usart_periph, uint32_t int_flag); +/* get USART interrupt and flag status */ +FlagStatus usart_interrupt_flag_get(uint32_t usart_periph, uint32_t int_flag); +/* clear interrupt flag in STAT register */ +void usart_interrupt_flag_clear(uint32_t usart_periph, uint32_t flag); +#endif /* GD32F10X_USART_H */ diff --git a/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_standard_peripheral/Include/gd32f10x_wwdgt.h b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_standard_peripheral/Include/gd32f10x_wwdgt.h new file mode 100644 index 0000000000..20a2c79c5f --- /dev/null +++ b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_standard_peripheral/Include/gd32f10x_wwdgt.h @@ -0,0 +1,89 @@ +/*! + \file gd32f10x_wwdgt.h + \brief definitions for the WWDGT + + \version 2014-12-26, V1.0.0, firmware for GD32F10x + \version 2017-06-20, V2.0.0, firmware for GD32F10x + \version 2018-07-31, V2.1.0, firmware for GD32F10x + \version 2020-09-30, V2.2.0, firmware for GD32F10x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef GD32F10X_WWDGT_H +#define GD32F10X_WWDGT_H + +#include "gd32f10x.h" + +/* WWDGT definitions */ +#define WWDGT WWDGT_BASE /*!< WWDGT base address */ + +/* registers definitions */ +#define WWDGT_CTL REG32((WWDGT) + 0x00U) /*!< WWDGT control register */ +#define WWDGT_CFG REG32((WWDGT) + 0x04U) /*!< WWDGT configuration register */ +#define WWDGT_STAT REG32((WWDGT) + 0x08U) /*!< WWDGT status register */ + +/* bits definitions */ +/* WWDGT_CTL */ +#define WWDGT_CTL_CNT BITS(0,6) /*!< WWDGT counter value */ +#define WWDGT_CTL_WDGTEN BIT(7) /*!< WWDGT counter enable */ + +/* WWDGT_CFG */ +#define WWDGT_CFG_WIN BITS(0,6) /*!< WWDGT counter window value */ +#define WWDGT_CFG_PSC BITS(7,8) /*!< WWDGT prescaler divider value */ +#define WWDGT_CFG_EWIE BIT(9) /*!< early wakeup interrupt enable */ + +/* WWDGT_STAT */ +#define WWDGT_STAT_EWIF BIT(0) /*!< early wakeup interrupt flag */ + +/* constants definitions */ +#define CFG_PSC(regval) (BITS(7,8) & ((uint32_t)(regval) << 7)) /*!< write value to WWDGT_CFG_PSC bit field */ +#define WWDGT_CFG_PSC_DIV1 CFG_PSC(0) /*!< the time base of WWDGT = (PCLK1/4096)/1 */ +#define WWDGT_CFG_PSC_DIV2 CFG_PSC(1) /*!< the time base of WWDGT = (PCLK1/4096)/2 */ +#define WWDGT_CFG_PSC_DIV4 CFG_PSC(2) /*!< the time base of WWDGT = (PCLK1/4096)/4 */ +#define WWDGT_CFG_PSC_DIV8 CFG_PSC(3) /*!< the time base of WWDGT = (PCLK1/4096)/8 */ + +/* function declarations */ +/* reset the window watchdog timer configuration */ +void wwdgt_deinit(void); +/* start the window watchdog timer counter */ +void wwdgt_enable(void); + +/* configure the window watchdog timer counter value */ +void wwdgt_counter_update(uint16_t counter_value); +/* configure counter value, window value, and prescaler divider value */ +void wwdgt_config(uint16_t counter, uint16_t window, uint32_t prescaler); + +/* enable early wakeup interrupt of WWDGT */ +void wwdgt_interrupt_enable(void); +/* check early wakeup interrupt state of WWDGT */ +FlagStatus wwdgt_flag_get(void); +/* clear early wakeup interrupt state of WWDGT */ +void wwdgt_flag_clear(void); + +#endif /* GD32F10X_WWDGT_H */ diff --git a/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_standard_peripheral/Source/gd32f10x_adc.c b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_standard_peripheral/Source/gd32f10x_adc.c new file mode 100644 index 0000000000..d1d7addc7e --- /dev/null +++ b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_standard_peripheral/Source/gd32f10x_adc.c @@ -0,0 +1,932 @@ +/*! + \file gd32f10x_adc.c + \brief ADC driver + + \version 2014-12-26, V1.0.0, firmware for GD32F10x + \version 2017-06-20, V2.0.0, firmware for GD32F10x + \version 2018-07-31, V2.1.0, firmware for GD32F10x + \version 2020-09-30, V2.2.0, firmware for GD32F10x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "gd32f10x_adc.h" + +/* discontinuous mode macro*/ +#define ADC_CHANNEL_LENGTH_SUBTRACT_ONE ((uint8_t)1U) + +/* ADC regular channel macro */ +#define ADC_REGULAR_CHANNEL_RANK_SIX ((uint8_t)6U) +#define ADC_REGULAR_CHANNEL_RANK_TWELVE ((uint8_t)12U) +#define ADC_REGULAR_CHANNEL_RANK_SIXTEEN ((uint8_t)16U) +#define ADC_REGULAR_CHANNEL_RANK_LENGTH ((uint8_t)5U) + +/* ADC sampling time macro */ +#define ADC_CHANNEL_SAMPLE_TEN ((uint8_t)10U) +#define ADC_CHANNEL_SAMPLE_EIGHTEEN ((uint8_t)18U) +#define ADC_CHANNEL_SAMPLE_LENGTH ((uint8_t)3U) + +/* ADC inserted channel macro */ +#define ADC_INSERTED_CHANNEL_RANK_LENGTH ((uint8_t)5U) +#define ADC_INSERTED_CHANNEL_SHIFT_LENGTH ((uint8_t)15U) + +/* ADC inserted channel offset macro */ +#define ADC_OFFSET_LENGTH ((uint8_t)3U) +#define ADC_OFFSET_SHIFT_LENGTH ((uint8_t)4U) + +/*! + \brief reset ADC + \param[in] adc_periph: ADCx, x=0,1,2 + \param[out] none + \retval none +*/ +void adc_deinit(uint32_t adc_periph) +{ + switch(adc_periph){ + case ADC0: + /* reset ADC0 */ + rcu_periph_reset_enable(RCU_ADC0RST); + rcu_periph_reset_disable(RCU_ADC0RST); + break; + case ADC1: + /* reset ADC1 */ + rcu_periph_reset_enable(RCU_ADC1RST); + rcu_periph_reset_disable(RCU_ADC1RST); + break; +#ifndef GD32F10X_CL + case ADC2: + rcu_periph_reset_enable(RCU_ADC2RST); + rcu_periph_reset_disable(RCU_ADC2RST); + break; +#endif /* GD32F10X_CL */ + default: + break; + } +} + +/*! + \brief configure the ADC sync mode + \param[in] mode: ADC mode + only one parameter can be selected which is shown as below: + \arg ADC_MODE_FREE: all the ADCs work independently + \arg ADC_DAUL_REGULAL_PARALLEL_INSERTED_PARALLEL: ADC0 and ADC1 work in combined regular parallel + inserted parallel mode + \arg ADC_DAUL_REGULAL_PARALLEL_INSERTED_ROTATION: ADC0 and ADC1 work in combined regular parallel + trigger rotation mode + \arg ADC_DAUL_INSERTED_PARALLEL_REGULAL_FOLLOWUP_FAST: ADC0 and ADC1 work in combined inserted parallel + follow-up fast mode + \arg ADC_DAUL_INSERTED_PARALLEL_REGULAL_FOLLOWUP_SLOW: ADC0 and ADC1 work in combined inserted parallel + follow-up slow mode + \arg ADC_DAUL_INSERTED_PARALLEL: ADC0 and ADC1 work in inserted parallel mode only + \arg ADC_DAUL_REGULAL_PARALLEL: ADC0 and ADC1 work in regular parallel mode only + \arg ADC_DAUL_REGULAL_FOLLOWUP_FAST: ADC0 and ADC1 work in follow-up fast mode only + \arg ADC_DAUL_REGULAL_FOLLOWUP_SLOW: ADC0 and ADC1 work in follow-up slow mode only + \arg ADC_DAUL_INSERTED_TRIGGER_ROTATION: ADC0 and ADC1 work in trigger rotation mode only + \param[out] none + \retval none +*/ +void adc_mode_config(uint32_t mode) +{ + ADC_CTL0(ADC0) &= ~(ADC_CTL0_SYNCM); + ADC_CTL0(ADC0) |= mode; +} + +/*! + \brief enable or disable ADC special function + \param[in] adc_periph: ADCx, x=0,1,2 + \param[in] function: the function to config + only one parameter can be selected which is shown as below: + \arg ADC_SCAN_MODE: scan mode select + \arg ADC_INSERTED_CHANNEL_AUTO: inserted channel group convert automatically + \arg ADC_CONTINUOUS_MODE: continuous mode select + \param[in] newvalue: ENABLE or DISABLE + \param[out] none + \retval none +*/ +void adc_special_function_config(uint32_t adc_periph, uint32_t function, ControlStatus newvalue) +{ + if(newvalue){ + if(0U != (function & ADC_SCAN_MODE)){ + /* enable scan mode */ + ADC_CTL0(adc_periph) |= ADC_SCAN_MODE; + } + if(0U != (function & ADC_INSERTED_CHANNEL_AUTO)){ + /* enable inserted channel group convert automatically */ + ADC_CTL0(adc_periph) |= ADC_INSERTED_CHANNEL_AUTO; + } + if(0U != (function & ADC_CONTINUOUS_MODE)){ + /* enable continuous mode */ + ADC_CTL1(adc_periph) |= ADC_CONTINUOUS_MODE; + } + }else{ + if(0U != (function & ADC_SCAN_MODE)){ + /* disable scan mode */ + ADC_CTL0(adc_periph) &= ~ADC_SCAN_MODE; + } + if(0U != (function & ADC_INSERTED_CHANNEL_AUTO)){ + /* disable inserted channel group convert automatically */ + ADC_CTL0(adc_periph) &= ~ADC_INSERTED_CHANNEL_AUTO; + } + if(0U != (function & ADC_CONTINUOUS_MODE)){ + /* disable continuous mode */ + ADC_CTL1(adc_periph) &= ~ADC_CONTINUOUS_MODE; + } + } +} + +/*! + \brief configure ADC data alignment + \param[in] adc_periph: ADCx, x=0,1,2 + \param[in] data_alignment: data alignment select + only one parameter can be selected which is shown as below: + \arg ADC_DATAALIGN_RIGHT: LSB alignment + \arg ADC_DATAALIGN_LEFT: MSB alignment + \param[out] none + \retval none +*/ +void adc_data_alignment_config(uint32_t adc_periph, uint32_t data_alignment) +{ + if(ADC_DATAALIGN_RIGHT != data_alignment){ + /* MSB alignment */ + ADC_CTL1(adc_periph) |= ADC_CTL1_DAL; + }else{ + /* LSB alignment */ + ADC_CTL1(adc_periph) &= ~((uint32_t)ADC_CTL1_DAL); + } +} + +/*! + \brief enable ADC interface + \param[in] adc_periph: ADCx, x=0,1,2 + \param[out] none + \retval none +*/ +void adc_enable(uint32_t adc_periph) +{ + if(RESET == (ADC_CTL1(adc_periph) & ADC_CTL1_ADCON)){ + /* enable ADC */ + ADC_CTL1(adc_periph) |= (uint32_t)ADC_CTL1_ADCON; + } +} + +/*! + \brief disable ADC interface + \param[in] adc_periph: ADCx, x=0,1,2 + \param[out] none + \retval none +*/ +void adc_disable(uint32_t adc_periph) +{ + /* disable ADC */ + ADC_CTL1(adc_periph) &= ~((uint32_t)ADC_CTL1_ADCON); +} + +/*! + \brief ADC calibration and reset calibration + \param[in] adc_periph: ADCx, x=0,1,2 + \param[out] none + \retval none +*/ +void adc_calibration_enable(uint32_t adc_periph) +{ + /* reset the selected ADC1 calibration registers */ + ADC_CTL1(adc_periph) |= (uint32_t) ADC_CTL1_RSTCLB; + /* check the RSTCLB bit state */ + while(RESET != (ADC_CTL1(adc_periph) & ADC_CTL1_RSTCLB)){ + } + /* enable ADC calibration process */ + ADC_CTL1(adc_periph) |= ADC_CTL1_CLB; + /* check the CLB bit state */ + while(RESET != (ADC_CTL1(adc_periph) & ADC_CTL1_CLB)){ + } +} + +/*! + \brief enable the temperature sensor and Vrefint channel + \param[in] none + \param[out] none + \retval none +*/ +void adc_tempsensor_vrefint_enable(void) +{ + /* enable the temperature sensor and Vrefint channel */ + ADC_CTL1(ADC0) |= ADC_CTL1_TSVREN; +} + +/*! + \brief disable the temperature sensor and Vrefint channel + \param[in] none + \param[out] none + \retval none +*/ +void adc_tempsensor_vrefint_disable(void) +{ + /* disable the temperature sensor and Vrefint channel */ + ADC_CTL1(ADC0) &= ~ADC_CTL1_TSVREN; +} + +/*! + \brief enable DMA request + \param[in] adc_periph: ADCx, x=0,1,2 + \param[out] none + \retval none +*/ +void adc_dma_mode_enable(uint32_t adc_periph) +{ + /* enable DMA request */ + ADC_CTL1(adc_periph) |= (uint32_t)(ADC_CTL1_DMA); +} + +/*! + \brief disable DMA request + \param[in] adc_periph: ADCx, x=0,1,2 + \param[out] none + \retval none +*/ +void adc_dma_mode_disable(uint32_t adc_periph) +{ + /* disable DMA request */ + ADC_CTL1(adc_periph) &= ~((uint32_t)ADC_CTL1_DMA); +} + +/*! + \brief configure ADC discontinuous mode + \param[in] adc_periph: ADCx, x=0,1,2 + \param[in] adc_channel_group: select the channel group + only one parameter can be selected which is shown as below: + \arg ADC_REGULAR_CHANNEL: regular channel group + \arg ADC_INSERTED_CHANNEL: inserted channel group + \arg ADC_CHANNEL_DISCON_DISABLE: disable discontinuous mode of regular & inserted channel + \param[in] length: number of conversions in discontinuous mode,the number can be 1..8 + for regular channel, the number has no effect for inserted channel + \param[out] none + \retval none +*/ +void adc_discontinuous_mode_config(uint32_t adc_periph, uint8_t adc_channel_group, uint8_t length) +{ + /* disable discontinuous mode of regular & inserted channel */ + ADC_CTL0(adc_periph) &= ~((uint32_t)(ADC_CTL0_DISRC | ADC_CTL0_DISIC)); + switch(adc_channel_group){ + case ADC_REGULAR_CHANNEL: + /* config the number of conversions in discontinuous mode */ + ADC_CTL0(adc_periph) &= ~((uint32_t)ADC_CTL0_DISNUM); + ADC_CTL0(adc_periph) |= CTL0_DISNUM(((uint32_t)length - ADC_CHANNEL_LENGTH_SUBTRACT_ONE)); + /* enable regular channel group discontinuous mode */ + ADC_CTL0(adc_periph) |= (uint32_t)ADC_CTL0_DISRC; + break; + case ADC_INSERTED_CHANNEL: + /* enable inserted channel group discontinuous mode */ + ADC_CTL0(adc_periph) |= (uint32_t)ADC_CTL0_DISIC; + break; + case ADC_CHANNEL_DISCON_DISABLE: + /* disable discontinuous mode of regular & inserted channel */ + default: + break; + } +} + +/*! + \brief configure the length of regular channel group or inserted channel group + \param[in] adc_periph: ADCx, x=0,1,2 + \param[in] adc_channel_group: select the channel group + only one parameter can be selected which is shown as below: + \arg ADC_REGULAR_CHANNEL: regular channel group + \arg ADC_INSERTED_CHANNEL: inserted channel group + \param[in] length: the length of the channel + regular channel 1-16 + inserted channel 1-4 + \param[out] none + \retval none +*/ +void adc_channel_length_config(uint32_t adc_periph, uint8_t adc_channel_group, uint32_t length) +{ + switch(adc_channel_group){ + case ADC_REGULAR_CHANNEL: + /* configure the length of regular channel group */ + ADC_RSQ0(adc_periph) &= ~((uint32_t)ADC_RSQ0_RL); + ADC_RSQ0(adc_periph) |= RSQ0_RL((uint32_t)(length-ADC_CHANNEL_LENGTH_SUBTRACT_ONE)); + break; + case ADC_INSERTED_CHANNEL: + /* configure the length of inserted channel group */ + ADC_ISQ(adc_periph) &= ~((uint32_t)ADC_ISQ_IL); + ADC_ISQ(adc_periph) |= ISQ_IL((uint32_t)(length-ADC_CHANNEL_LENGTH_SUBTRACT_ONE)); + break; + default: + break; + } +} + +/*! + \brief configure ADC regular channel + \param[in] adc_periph: ADCx, x=0,1,2 + \param[in] rank: the regular group sequence rank,this parameter must be between 0 to 15 + \param[in] adc_channel: the selected ADC channel + only one parameter can be selected which is shown as below: + \arg ADC_CHANNEL_x(x=0..17)(x=16 and x=17 are only for ADC0): ADC Channelx + \param[in] sample_time: the sample time value + only one parameter can be selected which is shown as below: + \arg ADC_SAMPLETIME_1POINT5: 1.5 cycles + \arg ADC_SAMPLETIME_7POINT5: 7.5 cycles + \arg ADC_SAMPLETIME_13POINT5: 13.5 cycles + \arg ADC_SAMPLETIME_28POINT5: 28.5 cycles + \arg ADC_SAMPLETIME_41POINT5: 41.5 cycles + \arg ADC_SAMPLETIME_55POINT5: 55.5 cycles + \arg ADC_SAMPLETIME_71POINT5: 71.5 cycles + \arg ADC_SAMPLETIME_239POINT5: 239.5 cycles + \param[out] none + \retval none +*/ +void adc_regular_channel_config(uint32_t adc_periph, uint8_t rank, uint8_t adc_channel, uint32_t sample_time) +{ + uint32_t rsq,sampt; + + /* ADC regular sequence config */ + if(rank < ADC_REGULAR_CHANNEL_RANK_SIX){ + /* the regular group sequence rank is smaller than six */ + rsq = ADC_RSQ2(adc_periph); + rsq &= ~((uint32_t)(ADC_RSQX_RSQN << (ADC_REGULAR_CHANNEL_RANK_LENGTH*rank))); + /* the channel number is written to these bits to select a channel as the nth conversion in the regular channel group */ + rsq |= ((uint32_t)adc_channel << (ADC_REGULAR_CHANNEL_RANK_LENGTH*rank)); + ADC_RSQ2(adc_periph) = rsq; + }else if(rank < ADC_REGULAR_CHANNEL_RANK_TWELVE){ + /* the regular group sequence rank is smaller than twelve */ + rsq = ADC_RSQ1(adc_periph); + rsq &= ~((uint32_t)(ADC_RSQX_RSQN << (ADC_REGULAR_CHANNEL_RANK_LENGTH*(rank-ADC_REGULAR_CHANNEL_RANK_SIX)))); + /* the channel number is written to these bits to select a channel as the nth conversion in the regular channel group */ + rsq |= ((uint32_t)adc_channel << (ADC_REGULAR_CHANNEL_RANK_LENGTH*(rank-ADC_REGULAR_CHANNEL_RANK_SIX))); + ADC_RSQ1(adc_periph) = rsq; + }else if(rank < ADC_REGULAR_CHANNEL_RANK_SIXTEEN){ + /* the regular group sequence rank is smaller than sixteen */ + rsq = ADC_RSQ0(adc_periph); + rsq &= ~((uint32_t)(ADC_RSQX_RSQN << (ADC_REGULAR_CHANNEL_RANK_LENGTH*(rank-ADC_REGULAR_CHANNEL_RANK_TWELVE)))); + /* the channel number is written to these bits to select a channel as the nth conversion in the regular channel group */ + rsq |= ((uint32_t)adc_channel << (ADC_REGULAR_CHANNEL_RANK_LENGTH*(rank-ADC_REGULAR_CHANNEL_RANK_TWELVE))); + ADC_RSQ0(adc_periph) = rsq; + }else{ + } + + /* ADC sampling time config */ + if(adc_channel < ADC_CHANNEL_SAMPLE_TEN){ + /* the regular group sequence rank is smaller than ten */ + sampt = ADC_SAMPT1(adc_periph); + sampt &= ~((uint32_t)(ADC_SAMPTX_SPTN << (ADC_CHANNEL_SAMPLE_LENGTH*adc_channel))); + /* channel sample time set*/ + sampt |= (uint32_t)(sample_time << (ADC_CHANNEL_SAMPLE_LENGTH*adc_channel)); + ADC_SAMPT1(adc_periph) = sampt; + }else if(adc_channel < ADC_CHANNEL_SAMPLE_EIGHTEEN){ + /* the regular group sequence rank is smaller than eighteen */ + sampt = ADC_SAMPT0(adc_periph); + sampt &= ~((uint32_t)(ADC_SAMPTX_SPTN << (ADC_CHANNEL_SAMPLE_LENGTH*(adc_channel-ADC_CHANNEL_SAMPLE_TEN)))); + /* channel sample time set*/ + sampt |= (uint32_t)(sample_time << (ADC_CHANNEL_SAMPLE_LENGTH*(adc_channel-ADC_CHANNEL_SAMPLE_TEN))); + ADC_SAMPT0(adc_periph) = sampt; + }else{ + } +} + +/*! + \brief configure ADC inserted channel + \param[in] adc_periph: ADCx, x=0,1,2 + \param[in] rank: the inserted group sequencer rank,this parameter must be between 0 to 3 + \param[in] adc_channel: the selected ADC channel + only one parameter can be selected which is shown as below: + \arg ADC_CHANNEL_x(x=0..17)(x=16 and x=17 are only for ADC0): ADC Channelx + \param[in] sample_time: The sample time value + only one parameter can be selected which is shown as below: + \arg ADC_SAMPLETIME_1POINT5: 1.5 cycles + \arg ADC_SAMPLETIME_7POINT5: 7.5 cycles + \arg ADC_SAMPLETIME_13POINT5: 13.5 cycles + \arg ADC_SAMPLETIME_28POINT5: 28.5 cycles + \arg ADC_SAMPLETIME_41POINT5: 41.5 cycles + \arg ADC_SAMPLETIME_55POINT5: 55.5 cycles + \arg ADC_SAMPLETIME_71POINT5: 71.5 cycles + \arg ADC_SAMPLETIME_239POINT5: 239.5 cycles + \param[out] none + \retval none +*/ +void adc_inserted_channel_config(uint32_t adc_periph, uint8_t rank, uint8_t adc_channel, uint32_t sample_time) +{ + uint8_t inserted_length; + uint32_t isq,sampt; + /* get inserted channel group length */ + inserted_length = (uint8_t)GET_BITS(ADC_ISQ(adc_periph) , 20U , 21U); + /* the channel number is written to these bits to select a channel as the nth conversion in the inserted channel group */ + isq = ADC_ISQ(adc_periph); + isq &= ~((uint32_t)(ADC_ISQ_ISQN << (ADC_INSERTED_CHANNEL_SHIFT_LENGTH-(inserted_length-rank)*ADC_INSERTED_CHANNEL_RANK_LENGTH))); + isq |= ((uint32_t)adc_channel << (ADC_INSERTED_CHANNEL_SHIFT_LENGTH-(inserted_length-rank)*ADC_INSERTED_CHANNEL_RANK_LENGTH)); + ADC_ISQ(adc_periph) = isq; + + /* ADC sampling time config */ + if(adc_channel < ADC_CHANNEL_SAMPLE_TEN){ + /* the inserted group sequence rank is smaller than ten */ + sampt = ADC_SAMPT1(adc_periph); + sampt &= ~((uint32_t)(ADC_SAMPTX_SPTN << (ADC_CHANNEL_SAMPLE_LENGTH*adc_channel))); + /* channel sample time set*/ + sampt |= (uint32_t) sample_time << (ADC_CHANNEL_SAMPLE_LENGTH*adc_channel); + ADC_SAMPT1(adc_periph) = sampt; + }else if(adc_channel < ADC_CHANNEL_SAMPLE_EIGHTEEN){ + /* the inserted group sequence rank is smaller than eighteen */ + sampt = ADC_SAMPT0(adc_periph); + sampt &= ~((uint32_t)(ADC_SAMPTX_SPTN << (ADC_CHANNEL_SAMPLE_LENGTH*(adc_channel-ADC_CHANNEL_SAMPLE_TEN)))); + /* channel sample time set*/ + sampt |= ((uint32_t)sample_time << (ADC_CHANNEL_SAMPLE_LENGTH*(adc_channel-ADC_CHANNEL_SAMPLE_TEN))); + ADC_SAMPT0(adc_periph) = sampt; + }else{ + } +} + +/*! + \brief configure ADC inserted channel offset + \param[in] adc_periph: ADCx, x=0,1,2 + \param[in] inserted_channel: insert channel select + only one parameter can be selected + \arg ADC_INSERTED_CHANNEL_0: inserted channel0 + \arg ADC_INSERTED_CHANNEL_1: inserted channel1 + \arg ADC_INSERTED_CHANNEL_2: inserted channel2 + \arg ADC_INSERTED_CHANNEL_3: inserted channel3 + \param[in] offset: the offset data + \param[out] none + \retval none +*/ +void adc_inserted_channel_offset_config(uint32_t adc_periph, uint8_t inserted_channel, uint16_t offset) +{ + uint8_t inserted_length; + uint32_t num = 0U; + + inserted_length = (uint8_t)GET_BITS(ADC_ISQ(adc_periph) , 20U , 21U); + num = ((uint32_t)ADC_OFFSET_LENGTH - ((uint32_t)inserted_length - (uint32_t)inserted_channel)); + + if(num <= ADC_OFFSET_LENGTH){ + /* calculate the offset of the register */ + num = num * ADC_OFFSET_SHIFT_LENGTH; + /* config the offset of the selected channels */ + REG32((adc_periph) + 0x14U + num) = IOFFX_IOFF((uint32_t)offset); + } +} + +/*! + \brief configure ADC external trigger source + \param[in] adc_periph: ADCx, x=0,1,2 + \param[in] adc_channel_group: select the channel group + only one parameter can be selected which is shown as below: + \arg ADC_REGULAR_CHANNEL: regular channel group + \arg ADC_INSERTED_CHANNEL: inserted channel group + \param[in] external_trigger_source: regular or inserted group trigger source + only one parameter can be selected + for regular channel: + \arg ADC0_1_EXTTRIG_REGULAR_T0_CH0: TIMER0 CH0 event select + \arg ADC0_1_EXTTRIG_REGULAR_T0_CH1: TIMER0 CH1 event select + \arg ADC0_1_EXTTRIG_REGULAR_T0_CH2: TIMER0 CH2 event select + \arg ADC0_1_EXTTRIG_REGULAR_T1_CH1: TIMER1 CH1 event select + \arg ADC0_1_EXTTRIG_REGULAR_T2_TRGO: TIMER2 TRGO event select + \arg ADC0_1_EXTTRIG_REGULAR_T3_CH3: TIMER3 CH3 event select + \arg ADC0_1_EXTTRIG_REGULAR_T7_TRGO: TIMER7 TRGO event select + \arg ADC0_1_EXTTRIG_REGULAR_EXTI_11: external interrupt line 11 + \arg ADC2_EXTTRIG_REGULAR_T2_CH0: TIMER2 CH0 event select + \arg ADC2_EXTTRIG_REGULAR_T1_CH2: TIMER1 CH2 event select + \arg ADC2_EXTTRIG_REGULAR_T0_CH2: TIMER0 CH2 event select + \arg ADC2_EXTTRIG_REGULAR_T7_CH0: TIMER7 CH0 event select + \arg ADC2_EXTTRIG_REGULAR_T7_TRGO: TIMER7 TRGO event select + \arg ADC2_EXTTRIG_REGULAR_T4_CH0: TIMER4 CH0 event select + \arg ADC2_EXTTRIG_REGULAR_T4_CH2: TIMER4 CH2 event select + \arg ADC0_1_2_EXTTRIG_REGULAR_NONE: software trigger + for inserted channel: + \arg ADC0_1_EXTTRIG_INSERTED_T0_TRGO: TIMER0 TRGO event select + \arg ADC0_1_EXTTRIG_INSERTED_T0_CH3: TIMER0 CH3 event select + \arg ADC0_1_EXTTRIG_INSERTED_T1_TRGO: TIMER1 TRGO event select + \arg ADC0_1_EXTTRIG_INSERTED_T1_CH0: TIMER1 CH0 event select + \arg ADC0_1_EXTTRIG_INSERTED_T2_CH3: TIMER2 CH3 event select + \arg ADC0_1_EXTTRIG_INSERTED_T3_TRGO: TIMER3 TRGO event select + \arg ADC0_1_EXTTRIG_INSERTED_EXTI_15: external interrupt line 15 + \arg ADC0_1_EXTTRIG_INSERTED_T7_CH3: TIMER7 CH3 event select + \arg ADC2_EXTTRIG_INSERTED_T0_TRGO: TIMER0 TRGO event select + \arg ADC2_EXTTRIG_INSERTED_T0_CH3: TIMER0 CH3 event select + \arg ADC2_EXTTRIG_INSERTED_T3_CH2: TIMER3 CH2 event select + \arg ADC2_EXTTRIG_INSERTED_T7_CH1: TIMER7 CH1 event select + \arg ADC2_EXTTRIG_INSERTED_T7_CH3: TIMER7 CH3 event select + \arg ADC2_EXTTRIG_INSERTED_T4_TRGO: TIMER4 TRGO event select + \arg ADC2_EXTTRIG_INSERTED_T4_CH3: TIMER4 CH3 event select + \arg ADC0_1_2_EXTTRIG_INSERTED_NONE: software trigger + \param[out] none + \retval none +*/ +void adc_external_trigger_source_config(uint32_t adc_periph, uint8_t adc_channel_group, uint32_t external_trigger_source) +{ + switch(adc_channel_group){ + case ADC_REGULAR_CHANNEL: + /* configure ADC regular group external trigger source */ + ADC_CTL1(adc_periph) &= ~((uint32_t)ADC_CTL1_ETSRC); + ADC_CTL1(adc_periph) |= (uint32_t)external_trigger_source; + break; + case ADC_INSERTED_CHANNEL: + /* configure ADC inserted group external trigger source */ + ADC_CTL1(adc_periph) &= ~((uint32_t)ADC_CTL1_ETSIC); + ADC_CTL1(adc_periph) |= (uint32_t)external_trigger_source; + break; + default: + break; + } +} + +/*! + \brief configure ADC external trigger + \param[in] adc_periph: ADCx, x=0,1,2 + \param[in] adc_channel_group: select the channel group + one or more parameters can be selected which are shown as below: + \arg ADC_REGULAR_CHANNEL: regular channel group + \arg ADC_INSERTED_CHANNEL: inserted channel group + \param[in] newvalue: ENABLE or DISABLE + \param[out] none + \retval none +*/ +void adc_external_trigger_config(uint32_t adc_periph, uint8_t adc_channel_group, ControlStatus newvalue) +{ + if(newvalue){ + if(0U != (adc_channel_group & ADC_REGULAR_CHANNEL)){ + /* enable ADC regular channel group external trigger */ + ADC_CTL1(adc_periph) |= ADC_CTL1_ETERC; + } + if(0U != (adc_channel_group & ADC_INSERTED_CHANNEL)){ + /* enable ADC inserted channel group external trigger */ + ADC_CTL1(adc_periph) |= ADC_CTL1_ETEIC; + } + }else{ + if(0U != (adc_channel_group & ADC_REGULAR_CHANNEL)){ + /* disable ADC regular channel group external trigger */ + ADC_CTL1(adc_periph) &= ~ADC_CTL1_ETERC; + } + if(0U != (adc_channel_group & ADC_INSERTED_CHANNEL)){ + /* disable ADC regular channel group external trigger */ + ADC_CTL1(adc_periph) &= ~ADC_CTL1_ETEIC; + } + } +} + +/*! + \brief enable ADC software trigger + \param[in] adc_periph: ADCx, x=0,1,2 + \param[in] adc_channel_group: select the channel group + one or more parameters can be selected which are shown as below: + \arg ADC_REGULAR_CHANNEL: regular channel group + \arg ADC_INSERTED_CHANNEL: inserted channel group + \param[out] none + \retval none +*/ +void adc_software_trigger_enable(uint32_t adc_periph, uint8_t adc_channel_group) +{ + if(0U != (adc_channel_group & ADC_REGULAR_CHANNEL)){ + /* enable ADC regular channel group software trigger */ + ADC_CTL1(adc_periph) |= ADC_CTL1_SWRCST; + } + if(0U != (adc_channel_group & ADC_INSERTED_CHANNEL)){ + /* enable ADC inserted channel group software trigger */ + ADC_CTL1(adc_periph) |= ADC_CTL1_SWICST; + } +} + +/*! + \brief read ADC regular group data register + \param[in] adc_periph: ADCx, x=0,1,2 + \param[in] none + \param[out] none + \retval the conversion value +*/ +uint16_t adc_regular_data_read(uint32_t adc_periph) +{ + return (uint16_t)(ADC_RDATA(adc_periph)); +} + +/*! + \brief read ADC inserted group data register + \param[in] adc_periph: ADCx, x=0,1,2 + \param[in] inserted_channel: insert channel select + only one parameter can be selected + \arg ADC_INSERTED_CHANNEL_0: inserted Channel0 + \arg ADC_INSERTED_CHANNEL_1: inserted channel1 + \arg ADC_INSERTED_CHANNEL_2: inserted Channel2 + \arg ADC_INSERTED_CHANNEL_3: inserted Channel3 + \param[out] none + \retval the conversion value +*/ +uint16_t adc_inserted_data_read(uint32_t adc_periph, uint8_t inserted_channel) +{ + uint32_t idata; + /* read the data of the selected channel */ + switch(inserted_channel){ + case ADC_INSERTED_CHANNEL_0: + /* read the data of channel 0 */ + idata = ADC_IDATA0(adc_periph); + break; + case ADC_INSERTED_CHANNEL_1: + /* read the data of channel 1 */ + idata = ADC_IDATA1(adc_periph); + break; + case ADC_INSERTED_CHANNEL_2: + /* read the data of channel 2 */ + idata = ADC_IDATA2(adc_periph); + break; + case ADC_INSERTED_CHANNEL_3: + /* read the data of channel 3 */ + idata = ADC_IDATA3(adc_periph); + break; + default: + idata = 0U; + break; + } + return (uint16_t)idata; +} + +/*! + \brief read the last ADC0 and ADC1 conversion result data in sync mode + \param[in] none + \param[out] none + \retval the conversion value +*/ +uint32_t adc_sync_mode_convert_value_read(void) +{ + /* return conversion value */ + return ADC_RDATA(ADC0); +} + + +/*! + \brief configure ADC analog watchdog single channel + \param[in] adc_periph: ADCx, x=0,1,2 + \param[in] adc_channel: the selected ADC channel + only one parameter can be selected which is shown as below: + \arg ADC_CHANNEL_x: ADC Channelx(x=0..17)(x=16 and x=17 are only for ADC0) + \param[out] none + \retval none +*/ +void adc_watchdog_single_channel_enable(uint32_t adc_periph, uint8_t adc_channel) +{ + ADC_CTL0(adc_periph) &= (uint32_t)~(ADC_CTL0_RWDEN | ADC_CTL0_IWDEN | ADC_CTL0_WDSC | ADC_CTL0_WDCHSEL); + /* analog watchdog channel select */ + ADC_CTL0(adc_periph) |= (uint32_t)adc_channel; + ADC_CTL0(adc_periph) |= (uint32_t)(ADC_CTL0_RWDEN | ADC_CTL0_IWDEN | ADC_CTL0_WDSC); +} + +/*! + \brief configure ADC analog watchdog group channel + \param[in] adc_periph: ADCx, x=0,1,2 + \param[in] adc_channel_group: the channel group use analog watchdog + only one parameter can be selected which is shown as below: + \arg ADC_REGULAR_CHANNEL: regular channel group + \arg ADC_INSERTED_CHANNEL: inserted channel group + \arg ADC_REGULAR_INSERTED_CHANNEL: both regular and inserted group + \param[out] none + \retval none +*/ +void adc_watchdog_group_channel_enable(uint32_t adc_periph, uint8_t adc_channel_group) +{ + ADC_CTL0(adc_periph) &= (uint32_t)~(ADC_CTL0_RWDEN | ADC_CTL0_IWDEN | ADC_CTL0_WDSC); + /* select the group */ + switch(adc_channel_group){ + case ADC_REGULAR_CHANNEL: + /* regular channel analog watchdog enable */ + ADC_CTL0(adc_periph) |= (uint32_t) ADC_CTL0_RWDEN; + break; + case ADC_INSERTED_CHANNEL: + /* inserted channel analog watchdog enable */ + ADC_CTL0(adc_periph) |= (uint32_t) ADC_CTL0_IWDEN; + break; + case ADC_REGULAR_INSERTED_CHANNEL: + /* regular and inserted channel analog watchdog enable */ + ADC_CTL0(adc_periph) |= (uint32_t)(ADC_CTL0_RWDEN | ADC_CTL0_IWDEN); + break; + default: + break; + } +} + +/*! + \brief disable ADC analog watchdog + \param[in] adc_periph: ADCx, x=0,1,2 + \param[out] none + \retval none +*/ +void adc_watchdog_disable(uint32_t adc_periph) +{ + ADC_CTL0(adc_periph) &= (uint32_t)~(ADC_CTL0_RWDEN | ADC_CTL0_IWDEN | ADC_CTL0_WDSC | ADC_CTL0_WDCHSEL); +} + +/*! + \brief configure ADC analog watchdog threshold + \param[in] adc_periph: ADCx, x=0,1,2 + \param[in] low_threshold: analog watchdog low threshold, 0..4095 + \param[in] high_threshold: analog watchdog high threshold, 0..4095 + \param[out] none + \retval none +*/ +void adc_watchdog_threshold_config(uint32_t adc_periph, uint16_t low_threshold, uint16_t high_threshold) +{ + ADC_WDLT(adc_periph) = (uint32_t)WDLT_WDLT(low_threshold); + ADC_WDHT(adc_periph) = (uint32_t)WDHT_WDHT(high_threshold); +} + +/*! + \brief get the ADC flag bits + \param[in] adc_periph: ADCx, x=0,1,2 + \param[in] adc_flag: the adc flag bits + only one parameter can be selected which is shown as below: + \arg ADC_FLAG_WDE: analog watchdog event flag + \arg ADC_FLAG_EOC: end of group conversion flag + \arg ADC_FLAG_EOIC: end of inserted group conversion flag + \arg ADC_FLAG_STIC: start flag of inserted channel group + \arg ADC_FLAG_STRC: start flag of regular channel group + \param[out] none + \retval FlagStatus: SET or RESET +*/ +FlagStatus adc_flag_get(uint32_t adc_periph, uint32_t adc_flag) +{ + FlagStatus reval = RESET; + if(ADC_STAT(adc_periph) & adc_flag){ + reval = SET; + } + return reval; +} + +/*! + \brief clear the ADC flag bits + \param[in] adc_periph: ADCx, x=0,1,2 + \param[in] adc_flag: the adc flag bits + one or more parameters can be selected which are shown as below: + \arg ADC_FLAG_WDE: analog watchdog event flag + \arg ADC_FLAG_EOC: end of group conversion flag + \arg ADC_FLAG_EOIC: end of inserted group conversion flag + \arg ADC_FLAG_STIC: start flag of inserted channel group + \arg ADC_FLAG_STRC: start flag of regular channel group + \param[out] none + \retval none +*/ +void adc_flag_clear(uint32_t adc_periph, uint32_t adc_flag) +{ + ADC_STAT(adc_periph) &= ~((uint32_t)adc_flag); +} + +/*! + \brief get the bit state of ADCx software start conversion + \param[in] adc_periph: ADCx, x=0,1,2 + \param[in] none + \param[out] none + \retval FlagStatus: SET or RESET +*/ +FlagStatus adc_regular_software_startconv_flag_get(uint32_t adc_periph) +{ + FlagStatus reval = RESET; + if((uint32_t)RESET != (ADC_CTL1(adc_periph) & ADC_CTL1_SWRCST)){ + reval = SET; + } + return reval; +} + +/*! + \brief get the bit state of ADCx software inserted channel start conversion + \param[in] adc_periph: ADCx, x=0,1,2 + \param[in] none + \param[out] none + \retval FlagStatus: SET or RESET +*/ +FlagStatus adc_inserted_software_startconv_flag_get(uint32_t adc_periph) +{ + FlagStatus reval = RESET; + if((uint32_t)RESET != (ADC_CTL1(adc_periph) & ADC_CTL1_SWICST)){ + reval = SET; + } + return reval; +} + +/*! + \brief get the ADC interrupt bits + \param[in] adc_periph: ADCx, x=0,1,2 + \param[in] adc_interrupt: the adc interrupt bits + only one parameter can be selected which is shown as below: + \arg ADC_INT_FLAG_WDE: analog watchdog interrupt + \arg ADC_INT_FLAG_EOC: end of group conversion interrupt + \arg ADC_INT_FLAG_EOIC: end of inserted group conversion interrupt + \param[out] none + \retval FlagStatus: SET or RESET +*/ +FlagStatus adc_interrupt_flag_get(uint32_t adc_periph, uint32_t adc_interrupt) +{ + FlagStatus interrupt_flag = RESET; + uint32_t state; + /* check the interrupt bits */ + switch(adc_interrupt){ + case ADC_INT_FLAG_WDE: + /* get the ADC analog watchdog interrupt bits */ + state = ADC_STAT(adc_periph) & ADC_STAT_WDE; + if((ADC_CTL0(adc_periph) & ADC_CTL0_WDEIE) && state){ + interrupt_flag = SET; + } + break; + case ADC_INT_FLAG_EOC: + /* get the ADC end of group conversion interrupt bits */ + state = ADC_STAT(adc_periph) & ADC_STAT_EOC; + if((ADC_CTL0(adc_periph) & ADC_CTL0_EOCIE) && state){ + interrupt_flag = SET; + } + break; + case ADC_INT_FLAG_EOIC: + /* get the ADC end of inserted group conversion interrupt bits */ + state = ADC_STAT(adc_periph) & ADC_STAT_EOIC; + if((ADC_CTL0(adc_periph) & ADC_CTL0_EOICIE) && state){ + interrupt_flag = SET; + } + break; + default: + break; + } + return interrupt_flag; +} + +/*! + \brief clear the ADC flag + \param[in] adc_periph: ADCx, x=0,1,2 + \param[in] adc_interrupt: the adc status flag + one or more parameters can be selected which are shown as below: + \arg ADC_INT_FLAG_WDE: analog watchdog interrupt + \arg ADC_INT_FLAG_EOC: end of group conversion interrupt + \arg ADC_INT_FLAG_EOIC: end of inserted group conversion interrupt + \param[out] none + \retval none +*/ +void adc_interrupt_flag_clear(uint32_t adc_periph, uint32_t adc_interrupt) +{ + ADC_STAT(adc_periph) &= ~((uint32_t)adc_interrupt); +} + +/*! + \brief enable ADC interrupt + \param[in] adc_periph: ADCx, x=0,1,2 + \param[in] adc_interrupt: the adc interrupt + one or more parameters can be selected which are shown as below: + \arg ADC_INT_WDE: analog watchdog interrupt flag + \arg ADC_INT_EOC: end of group conversion interrupt flag + \arg ADC_INT_EOIC: end of inserted group conversion interrupt flag + \param[out] none + \retval none +*/ +void adc_interrupt_enable(uint32_t adc_periph, uint32_t adc_interrupt) +{ + /* enable ADC analog watchdog interrupt */ + if(0U != (adc_interrupt & ADC_INT_WDE)){ + ADC_CTL0(adc_periph) |= (uint32_t) ADC_CTL0_WDEIE; + } + /* enable ADC end of group conversion interrupt */ + if(0U != (adc_interrupt & ADC_INT_EOC)){ + ADC_CTL0(adc_periph) |= (uint32_t) ADC_CTL0_EOCIE; + } + /* enable ADC end of inserted group conversion interrupt */ + if(0U != (adc_interrupt & ADC_INT_EOIC)){ + ADC_CTL0(adc_periph) |= (uint32_t) ADC_CTL0_EOICIE; + } +} + +/*! + \brief disable ADC interrupt + \param[in] adc_periph: ADCx, x=0,1,2 + \param[in] adc_interrupt: the adc interrupt flag + one or more parameters can be selected which are shown as below: + \arg ADC_INT_WDE: analog watchdog interrupt flag + \arg ADC_INT_EOC: end of group conversion interrupt flag + \arg ADC_INT_EOIC: end of inserted group conversion interrupt flag + \param[out] none + \retval none +*/ +void adc_interrupt_disable(uint32_t adc_periph, uint32_t adc_interrupt) +{ + /* disable ADC analog watchdog interrupt */ + if(0U != (adc_interrupt & ADC_INT_WDE)){ + ADC_CTL0(adc_periph) &= ~(uint32_t) ADC_CTL0_WDEIE; + } + /* disable ADC end of group conversion interrupt */ + if(0U != (adc_interrupt & ADC_INT_EOC)){ + ADC_CTL0(adc_periph) &= ~(uint32_t) ADC_CTL0_EOCIE; + } + /* disable ADC end of inserted group conversion interrupt */ + if(0U != (adc_interrupt & ADC_INT_EOIC)){ + ADC_CTL0(adc_periph) &= ~(uint32_t) ADC_CTL0_EOICIE; + } +} diff --git a/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_standard_peripheral/Source/gd32f10x_bkp.c b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_standard_peripheral/Source/gd32f10x_bkp.c new file mode 100644 index 0000000000..fa8c59db56 --- /dev/null +++ b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_standard_peripheral/Source/gd32f10x_bkp.c @@ -0,0 +1,295 @@ +/*! + \file gd32f10x_bkp.c + \brief BKP driver + + \version 2014-12-26, V1.0.0, firmware for GD32F10x + \version 2017-06-20, V2.0.0, firmware for GD32F10x + \version 2018-07-31, V2.1.0, firmware for GD32F10x + \version 2020-09-30, V2.2.0, firmware for GD32F10x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "gd32f10x_bkp.h" + +/* BKP register bits offset */ +#define BKP_TAMPER_BITS_OFFSET ((uint32_t)8U) + +/*! + \brief reset BKP registers + \param[in] none + \param[out] none + \retval none +*/ +void bkp_deinit(void) +{ + /* reset BKP domain register*/ + rcu_bkp_reset_enable(); + rcu_bkp_reset_disable(); +} + +/*! + \brief write BKP data register + \param[in] register_number: refer to bkp_data_register_enum + only one parameter can be selected which is shown as below: + \arg BKP_DATA_x(x = 0..41): bkp data register number x + \param[in] data: the data to be write in BKP data register + \param[out] none + \retval none +*/ +void bkp_data_write(bkp_data_register_enum register_number, uint16_t data) +{ + if((register_number >= BKP_DATA_10) && (register_number <= BKP_DATA_41)){ + BKP_DATA10_41(register_number - 1U) = data; + }else if((register_number >= BKP_DATA_0) && (register_number <= BKP_DATA_9)){ + BKP_DATA0_9(register_number - 1U) = data; + }else{ + /* illegal parameters */ + } +} + +/*! + \brief read BKP data register + \param[in] register_number: refer to bkp_data_register_enum + only one parameter can be selected which is shown as below: + \arg BKP_DATA_x(x = 0..41): bkp data register number x + \param[out] none + \retval data of BKP data register +*/ +uint16_t bkp_data_read(bkp_data_register_enum register_number) +{ + uint16_t data = 0U; + + /* get the data from the BKP data register */ + if((register_number >= BKP_DATA_10) && (register_number <= BKP_DATA_41)){ + data = BKP_DATA10_41(register_number - 1U); + }else if((register_number >= BKP_DATA_0) && (register_number <= BKP_DATA_9)){ + data = BKP_DATA0_9(register_number - 1U); + }else{ + /* illegal parameters */ + } + return data; +} + +/*! + \brief enable RTC clock calibration output + \param[in] none + \param[out] none + \retval none +*/ +void bkp_rtc_calibration_output_enable(void) +{ + BKP_OCTL |= (uint16_t)BKP_OCTL_COEN; +} + +/*! + \brief disable RTC clock calibration output + \param[in] none + \param[out] none + \retval none +*/ +void bkp_rtc_calibration_output_disable(void) +{ + BKP_OCTL &= (uint16_t)~BKP_OCTL_COEN; +} + +/*! + \brief enable RTC alarm or second signal output + \param[in] none + \param[out] none + \retval none +*/ +void bkp_rtc_signal_output_enable(void) +{ + BKP_OCTL |= (uint16_t)BKP_OCTL_ASOEN; +} + +/*! + \brief disable RTC alarm or second signal output + \param[in] none + \param[out] none + \retval none +*/ +void bkp_rtc_signal_output_disable(void) +{ + BKP_OCTL &= (uint16_t)~BKP_OCTL_ASOEN; +} + +/*! + \brief select RTC output + \param[in] outputsel: RTC output selection + only one parameter can be selected which is shown as below: + \arg RTC_OUTPUT_ALARM_PULSE: RTC alarm pulse is selected as the RTC output + \arg RTC_OUTPUT_SECOND_PULSE: RTC second pulse is selected as the RTC output + \param[out] none + \retval none +*/ +void bkp_rtc_output_select(uint16_t outputsel) +{ + uint16_t ctl = 0U; + + /* configure BKP_OCTL_ROSEL with outputsel */ + ctl = BKP_OCTL; + ctl &= (uint16_t)~BKP_OCTL_ROSEL; + ctl |= outputsel; + BKP_OCTL = ctl; +} + +/*! + \brief set RTC clock calibration value + \param[in] value: RTC clock calibration value + \arg 0x00 - 0x7F + \param[out] none + \retval none +*/ +void bkp_rtc_calibration_value_set(uint8_t value) +{ + uint16_t ctl; + + /* configure BKP_OCTL_RCCV with value */ + ctl = BKP_OCTL; + ctl &= (uint16_t)~BKP_OCTL_RCCV; + ctl |= (uint16_t)OCTL_RCCV(value); + BKP_OCTL = ctl; +} + +/*! + \brief enable tamper detection + \param[in] none + \param[out] none + \retval none +*/ +void bkp_tamper_detection_enable(void) +{ + BKP_TPCTL |= (uint16_t)BKP_TPCTL_TPEN; +} + +/*! + \brief disable tamper detection + \param[in] none + \param[out] none + \retval none +*/ +void bkp_tamper_detection_disable(void) +{ + BKP_TPCTL &= (uint16_t)~BKP_TPCTL_TPEN; +} + +/*! + \brief set tamper pin active level + \param[in] level: tamper active level + only one parameter can be selected which is shown as below: + \arg TAMPER_PIN_ACTIVE_HIGH: the tamper pin is active high + \arg TAMPER_PIN_ACTIVE_LOW: the tamper pin is active low + \param[out] none + \retval none +*/ +void bkp_tamper_active_level_set(uint16_t level) +{ + uint16_t ctl = 0U; + + /* configure BKP_TPCTL_TPAL with level */ + ctl = BKP_TPCTL; + ctl &= (uint16_t)~BKP_TPCTL_TPAL; + ctl |= level; + BKP_TPCTL = ctl; +} + +/*! + \brief enable tamper interrupt + \param[in] none + \param[out] none + \retval none +*/ +void bkp_interrupt_enable(void) +{ + BKP_TPCS |= (uint16_t)BKP_TPCS_TPIE; +} + +/*! + \brief disable tamper interrupt + \param[in] none + \param[out] none + \retval none +*/ +void bkp_interrupt_disable(void) +{ + BKP_TPCS &= (uint16_t)~BKP_TPCS_TPIE; +} + +/*! + \brief get tamper flag state + \param[in] none + \param[out] none + \retval FlagStatus: SET or RESET +*/ +FlagStatus bkp_flag_get(void) +{ + if(RESET != (BKP_TPCS & BKP_FLAG_TAMPER)){ + return SET; + }else{ + return RESET; + } +} + +/*! + \brief clear tamper flag state + \param[in] none + \param[out] none + \retval none +*/ +void bkp_flag_clear(void) +{ + BKP_TPCS |= (uint16_t)(BKP_FLAG_TAMPER >> BKP_TAMPER_BITS_OFFSET); +} + +/*! + \brief get tamper interrupt flag state + \param[in] none + \param[out] none + \retval FlagStatus: SET or RESET +*/ +FlagStatus bkp_interrupt_flag_get(void) +{ + if(RESET != (BKP_TPCS & BKP_INT_FLAG_TAMPER)){ + return SET; + }else{ + return RESET; + } +} + +/*! + \brief clear tamper interrupt flag state + \param[in] none + \param[out] none + \retval none +*/ +void bkp_interrupt_flag_clear(void) +{ + BKP_TPCS |= (uint16_t)(BKP_INT_FLAG_TAMPER >> BKP_TAMPER_BITS_OFFSET); +} diff --git a/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_standard_peripheral/Source/gd32f10x_can.c b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_standard_peripheral/Source/gd32f10x_can.c new file mode 100644 index 0000000000..411b50f15c --- /dev/null +++ b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_standard_peripheral/Source/gd32f10x_can.c @@ -0,0 +1,1053 @@ +/*! + \file gd32f10x_can.c + \brief CAN driver + + \version 2014-12-26, V1.0.0, firmware for GD32F10x + \version 2017-06-20, V2.0.0, firmware for GD32F10x + \version 2018-07-31, V2.1.0, firmware for GD32F10x + \version 2019-11-27, V2.1.1, firmware for GD32F10x + \version 2020-07-14, V2.1.2, firmware for GD32F10x + \version 2020-09-30, V2.2.0, firmware for GD32F10x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "gd32f10x_can.h" + +#define CAN_ERROR_HANDLE(s) do{}while(1) + +#define RFO1_CLEAR_VAL ((uint32_t)0x00000000U) /*!< RFO1 clear value */ +#define RFF1_CLEAR_VAL ((uint32_t)0x00000018U) /*!< RFF1 clear value */ + +/*! + \brief deinitialize CAN + \param[in] can_periph + \arg CANx(x=0,1),the CAN1 only for GD32F10x_CL + \param[out] none + \retval none +*/ +void can_deinit(uint32_t can_periph) +{ +#ifdef GD32F10x_CL + if(CAN0 == can_periph){ + rcu_periph_reset_enable(RCU_CAN0RST); + rcu_periph_reset_disable(RCU_CAN0RST); + }else{ + rcu_periph_reset_enable(RCU_CAN1RST); + rcu_periph_reset_disable(RCU_CAN1RST); + } +#else + if(CAN0 == can_periph){ + rcu_periph_reset_enable(RCU_CAN0RST); + rcu_periph_reset_disable(RCU_CAN0RST); + } +#endif +} + +/*! + \brief initialize CAN parameter struct with a default value + \param[in] type: the type of CAN parameter struct + only one parameter can be selected which is shown as below: + \arg CAN_INIT_STRUCT: the CAN initial struct + \arg CAN_FILTER_STRUCT: the CAN filter struct + \arg CAN_TX_MESSAGE_STRUCT: the CAN TX message struct + \arg CAN_RX_MESSAGE_STRUCT: the CAN RX message struct + \param[in] p_struct: the pointer of the specific struct + \param[out] none + \retval none +*/ +void can_struct_para_init(can_struct_type_enum type, void* p_struct) +{ + uint8_t i; + + /* get type of the struct */ + switch(type){ + /* used for can_init() */ + case CAN_INIT_STRUCT: + ((can_parameter_struct*)p_struct)->auto_bus_off_recovery = DISABLE; + ((can_parameter_struct*)p_struct)->no_auto_retrans = DISABLE; + ((can_parameter_struct*)p_struct)->auto_wake_up = DISABLE; + ((can_parameter_struct*)p_struct)->prescaler = 0x03FFU; + ((can_parameter_struct*)p_struct)->rec_fifo_overwrite = DISABLE; + ((can_parameter_struct*)p_struct)->resync_jump_width = CAN_BT_SJW_1TQ; + ((can_parameter_struct*)p_struct)->time_segment_1 = CAN_BT_BS1_3TQ; + ((can_parameter_struct*)p_struct)->time_segment_2 = CAN_BT_BS2_1TQ; + ((can_parameter_struct*)p_struct)->time_triggered = DISABLE; + ((can_parameter_struct*)p_struct)->trans_fifo_order = DISABLE; + ((can_parameter_struct*)p_struct)->working_mode = CAN_NORMAL_MODE; + + break; + /* used for can_filter_init() */ + case CAN_FILTER_STRUCT: + ((can_filter_parameter_struct*)p_struct)->filter_bits = CAN_FILTERBITS_32BIT; + ((can_filter_parameter_struct*)p_struct)->filter_enable = DISABLE; + ((can_filter_parameter_struct*)p_struct)->filter_fifo_number = CAN_FIFO0; + ((can_filter_parameter_struct*)p_struct)->filter_list_high = 0x0000U; + ((can_filter_parameter_struct*)p_struct)->filter_list_low = 0x0000U; + ((can_filter_parameter_struct*)p_struct)->filter_mask_high = 0x0000U; + ((can_filter_parameter_struct*)p_struct)->filter_mask_low = 0x0000U; + ((can_filter_parameter_struct*)p_struct)->filter_mode = CAN_FILTERMODE_MASK; + ((can_filter_parameter_struct*)p_struct)->filter_number = 0U; + + break; + /* used for can_message_transmit() */ + case CAN_TX_MESSAGE_STRUCT: + for(i = 0U; i < 8U; i++){ + ((can_trasnmit_message_struct*)p_struct)->tx_data[i] = 0U; + } + + ((can_trasnmit_message_struct*)p_struct)->tx_dlen = 0u; + ((can_trasnmit_message_struct*)p_struct)->tx_efid = 0U; + ((can_trasnmit_message_struct*)p_struct)->tx_ff = (uint8_t)CAN_FF_STANDARD; + ((can_trasnmit_message_struct*)p_struct)->tx_ft = (uint8_t)CAN_FT_DATA; + ((can_trasnmit_message_struct*)p_struct)->tx_sfid = 0U; + + break; + /* used for can_message_receive() */ + case CAN_RX_MESSAGE_STRUCT: + for(i = 0U; i < 8U; i++){ + ((can_receive_message_struct*)p_struct)->rx_data[i] = 0U; + } + + ((can_receive_message_struct*)p_struct)->rx_dlen = 0U; + ((can_receive_message_struct*)p_struct)->rx_efid = 0U; + ((can_receive_message_struct*)p_struct)->rx_ff = (uint8_t)CAN_FF_STANDARD; + ((can_receive_message_struct*)p_struct)->rx_fi = 0U; + ((can_receive_message_struct*)p_struct)->rx_ft = (uint8_t)CAN_FT_DATA; + ((can_receive_message_struct*)p_struct)->rx_sfid = 0U; + + break; + + default: + CAN_ERROR_HANDLE("parameter is invalid \r\n"); + } +} + +/*! + \brief initialize CAN + \param[in] can_periph + \arg CANx(x=0,1),the CAN1 only for GD32F10x_CL + \param[in] can_parameter_init: parameters for CAN initializtion + \arg working_mode: CAN_NORMAL_MODE, CAN_LOOPBACK_MODE, CAN_SILENT_MODE, CAN_SILENT_LOOPBACK_MODE + \arg resync_jump_width: CAN_BT_SJW_xTQ(x=1, 2, 3, 4) + \arg time_segment_1: CAN_BT_BS1_xTQ(1..16) + \arg time_segment_2: CAN_BT_BS2_xTQ(1..8) + \arg time_triggered: ENABLE or DISABLE + \arg auto_bus_off_recovery: ENABLE or DISABLE + \arg auto_wake_up: ENABLE or DISABLE + \arg no_auto_retrans: ENABLE or DISABLE + \arg rec_fifo_overwrite: ENABLE or DISABLE + \arg trans_fifo_order: ENABLE or DISABLE + \arg prescaler: 0x0001 - 0x0400 + \param[out] none + \retval ErrStatus: SUCCESS or ERROR +*/ +ErrStatus can_init(uint32_t can_periph, can_parameter_struct* can_parameter_init) +{ + uint32_t timeout = CAN_TIMEOUT; + ErrStatus flag = ERROR; + + /* disable sleep mode */ + CAN_CTL(can_periph) &= ~CAN_CTL_SLPWMOD; + /* enable initialize mode */ + CAN_CTL(can_periph) |= CAN_CTL_IWMOD; + /* wait ACK */ + while((CAN_STAT_IWS != (CAN_STAT(can_periph) & CAN_STAT_IWS)) && (0U != timeout)){ + timeout--; + } + /* check initialize working success */ + if(CAN_STAT_IWS != (CAN_STAT(can_periph) & CAN_STAT_IWS)){ + flag = ERROR; + }else{ + /* set the bit timing register */ + CAN_BT(can_periph) = (BT_MODE((uint32_t)can_parameter_init->working_mode) | \ + BT_SJW((uint32_t)can_parameter_init->resync_jump_width) | \ + BT_BS1((uint32_t)can_parameter_init->time_segment_1) | \ + BT_BS2((uint32_t)can_parameter_init->time_segment_2) | \ + BT_BAUDPSC(((uint32_t)(can_parameter_init->prescaler) - 1U))); + + /* time trigger communication mode */ + if(ENABLE == can_parameter_init->time_triggered){ + CAN_CTL(can_periph) |= CAN_CTL_TTC; + }else{ + CAN_CTL(can_periph) &= ~CAN_CTL_TTC; + } + /* automatic bus-off managment */ + if(ENABLE == can_parameter_init->auto_bus_off_recovery){ + CAN_CTL(can_periph) |= CAN_CTL_ABOR; + }else{ + CAN_CTL(can_periph) &= ~CAN_CTL_ABOR; + } + /* automatic wakeup mode */ + if(ENABLE == can_parameter_init->auto_wake_up){ + CAN_CTL(can_periph) |= CAN_CTL_AWU; + }else{ + CAN_CTL(can_periph) &= ~CAN_CTL_AWU; + } + /* automatic retransmission mode disable */ + if(ENABLE == can_parameter_init->no_auto_retrans){ + CAN_CTL(can_periph) |= CAN_CTL_ARD; + }else{ + CAN_CTL(can_periph) &= ~CAN_CTL_ARD; + } + /* receive fifo overwrite mode */ + if(ENABLE == can_parameter_init->rec_fifo_overwrite){ + CAN_CTL(can_periph) |= CAN_CTL_RFOD; + }else{ + CAN_CTL(can_periph) &= ~CAN_CTL_RFOD; + } + /* transmit fifo order */ + if(ENABLE == can_parameter_init->trans_fifo_order){ + CAN_CTL(can_periph) |= CAN_CTL_TFO; + }else{ + CAN_CTL(can_periph) &= ~CAN_CTL_TFO; + } + /* disable initialize mode */ + CAN_CTL(can_periph) &= ~CAN_CTL_IWMOD; + timeout = CAN_TIMEOUT; + /* wait the ACK */ + while((CAN_STAT_IWS == (CAN_STAT(can_periph) & CAN_STAT_IWS)) && (0U != timeout)){ + timeout--; + } + /* check exit initialize mode */ + if(0U != timeout){ + flag = SUCCESS; + } + } + return flag; +} + +/*! + \brief initialize CAN filter + \param[in] can_filter_parameter_init: struct for CAN filter initialization + \arg filter_list_high: 0x0000 - 0xFFFF + \arg filter_list_low: 0x0000 - 0xFFFF + \arg filter_mask_high: 0x0000 - 0xFFFF + \arg filter_mask_low: 0x0000 - 0xFFFF + \arg filter_fifo_number: CAN_FIFO0, CAN_FIFO1 + \arg filter_number: 0 - 27 + \arg filter_mode: CAN_FILTERMODE_MASK, CAN_FILTERMODE_LIST + \arg filter_bits: CAN_FILTERBITS_32BIT, CAN_FILTERBITS_16BIT + \arg filter_enable: ENABLE or DISABLE + \param[out] none + \retval none +*/ +void can_filter_init(can_filter_parameter_struct* can_filter_parameter_init) +{ + uint32_t val = 0U; + + val = ((uint32_t)1) << (can_filter_parameter_init->filter_number); + /* filter lock disable */ + CAN_FCTL(CAN0) |= CAN_FCTL_FLD; + /* disable filter */ + CAN_FW(CAN0) &= ~(uint32_t)val; + + /* filter 16 bits */ + if(CAN_FILTERBITS_16BIT == can_filter_parameter_init->filter_bits){ + /* set filter 16 bits */ + CAN_FSCFG(CAN0) &= ~(uint32_t)val; + /* first 16 bits list and first 16 bits mask or first 16 bits list and second 16 bits list */ + CAN_FDATA0(CAN0, can_filter_parameter_init->filter_number) = \ + FDATA_MASK_HIGH((can_filter_parameter_init->filter_mask_low) & CAN_FILTER_MASK_16BITS) | \ + FDATA_MASK_LOW((can_filter_parameter_init->filter_list_low) & CAN_FILTER_MASK_16BITS); + /* second 16 bits list and second 16 bits mask or third 16 bits list and fourth 16 bits list */ + CAN_FDATA1(CAN0, can_filter_parameter_init->filter_number) = \ + FDATA_MASK_HIGH((can_filter_parameter_init->filter_mask_high) & CAN_FILTER_MASK_16BITS) | \ + FDATA_MASK_LOW((can_filter_parameter_init->filter_list_high) & CAN_FILTER_MASK_16BITS); + } + /* filter 32 bits */ + if(CAN_FILTERBITS_32BIT == can_filter_parameter_init->filter_bits){ + /* set filter 32 bits */ + CAN_FSCFG(CAN0) |= (uint32_t)val; + /* 32 bits list or first 32 bits list */ + CAN_FDATA0(CAN0, can_filter_parameter_init->filter_number) = \ + FDATA_MASK_HIGH((can_filter_parameter_init->filter_list_high) & CAN_FILTER_MASK_16BITS) | + FDATA_MASK_LOW((can_filter_parameter_init->filter_list_low) & CAN_FILTER_MASK_16BITS); + /* 32 bits mask or second 32 bits list */ + CAN_FDATA1(CAN0, can_filter_parameter_init->filter_number) = \ + FDATA_MASK_HIGH((can_filter_parameter_init->filter_mask_high) & CAN_FILTER_MASK_16BITS) | + FDATA_MASK_LOW((can_filter_parameter_init->filter_mask_low) & CAN_FILTER_MASK_16BITS); + } + + /* filter mode */ + if(CAN_FILTERMODE_MASK == can_filter_parameter_init->filter_mode){ + /* mask mode */ + CAN_FMCFG(CAN0) &= ~(uint32_t)val; + }else{ + /* list mode */ + CAN_FMCFG(CAN0) |= (uint32_t)val; + } + + /* filter FIFO */ + if(CAN_FIFO0 == (can_filter_parameter_init->filter_fifo_number)){ + /* FIFO0 */ + CAN_FAFIFO(CAN0) &= ~(uint32_t)val; + }else{ + /* FIFO1 */ + CAN_FAFIFO(CAN0) |= (uint32_t)val; + } + + /* filter working */ + if(ENABLE == can_filter_parameter_init->filter_enable){ + + CAN_FW(CAN0) |= (uint32_t)val; + } + + /* filter lock enable */ + CAN_FCTL(CAN0) &= ~CAN_FCTL_FLD; +} + +/*! + \brief set CAN1 fliter start bank number + \param[in] start_bank: CAN1 start bank number + only one parameter can be selected which is shown as below: + \arg (1..27) + \param[out] none + \retval none +*/ +void can1_filter_start_bank(uint8_t start_bank) +{ + /* filter lock disable */ + CAN_FCTL(CAN0) |= CAN_FCTL_FLD; + /* set CAN1 filter start number */ + CAN_FCTL(CAN0) &= ~(uint32_t)CAN_FCTL_HBC1F; + CAN_FCTL(CAN0) |= FCTL_HBC1F(start_bank); + /* filter lock enaable */ + CAN_FCTL(CAN0) &= ~CAN_FCTL_FLD; +} + +/*! + \brief enable CAN debug freeze + \param[in] can_periph + \arg CANx(x=0,1),the CAN1 only for GD32F10x_CL + \param[out] none + \retval none +*/ +void can_debug_freeze_enable(uint32_t can_periph) +{ + /* set DFZ bit */ + CAN_CTL(can_periph) |= CAN_CTL_DFZ; +#ifdef GD32F10x_CL + if(CAN0 == can_periph){ + dbg_periph_enable(DBG_CAN0_HOLD); + }else{ + dbg_periph_enable(DBG_CAN1_HOLD); + } +#else + if(CAN0 == can_periph){ + dbg_periph_enable(DBG_CAN0_HOLD); + } +#endif +} + +/*! + \brief disable CAN debug freeze + \param[in] can_periph + \arg CANx(x=0,1),the CAN1 only for GD32F10x_CL + \param[out] none + \retval none +*/ +void can_debug_freeze_disable(uint32_t can_periph) +{ + /* set DFZ bit */ + CAN_CTL(can_periph) &= ~CAN_CTL_DFZ; +#ifdef GD32F10x_CL + if(CAN0 == can_periph){ + dbg_periph_disable(DBG_CAN0_HOLD); + }else{ + dbg_periph_disable(DBG_CAN1_HOLD); + } +#else + if(CAN0 == can_periph){ + dbg_periph_enable(DBG_CAN0_HOLD); + } +#endif +} + +/*! + \brief enable CAN time trigger mode + \param[in] can_periph + \arg CANx(x=0,1),the CAN1 only for GD32F10x_CL + \param[out] none + \retval none +*/ +void can_time_trigger_mode_enable(uint32_t can_periph) +{ + uint8_t mailbox_number; + + /* enable the tcc mode */ + CAN_CTL(can_periph) |= CAN_CTL_TTC; + /* enable time stamp */ + for(mailbox_number = 0U; mailbox_number < 3U; mailbox_number++){ + CAN_TMP(can_periph, mailbox_number) |= CAN_TMP_TSEN; + } +} + +/*! + \brief disable CAN time trigger mode + \param[in] can_periph + \arg CANx(x=0,1),the CAN1 only for GD32F10x_CL + \param[out] none + \retval none +*/ +void can_time_trigger_mode_disable(uint32_t can_periph) +{ + uint8_t mailbox_number; + + /* disable the TCC mode */ + CAN_CTL(can_periph) &= ~CAN_CTL_TTC; + /* reset TSEN bits */ + for(mailbox_number = 0U; mailbox_number < 3U; mailbox_number++){ + CAN_TMP(can_periph, mailbox_number) &= ~CAN_TMP_TSEN; + } +} + +/*! + \brief transmit CAN message + \param[in] can_periph + \arg CANx(x=0,1),the CAN1 only for GD32F10x_CL + \param[in] transmit_message: struct for CAN transmit message + \arg tx_sfid: 0x00000000 - 0x000007FF + \arg tx_efid: 0x00000000 - 0x1FFFFFFF + \arg tx_ff: CAN_FF_STANDARD, CAN_FF_EXTENDED + \arg tx_ft: CAN_FT_DATA, CAN_FT_REMOTE + \arg tx_dlen: 0 - 8 + \arg tx_data[]: 0x00 - 0xFF + \param[out] none + \retval mailbox_number +*/ +uint8_t can_message_transmit(uint32_t can_periph, can_trasnmit_message_struct* transmit_message) +{ + uint8_t mailbox_number = CAN_MAILBOX0; + + /* select one empty mailbox */ + if(CAN_TSTAT_TME0 == (CAN_TSTAT(can_periph)&CAN_TSTAT_TME0)){ + mailbox_number = CAN_MAILBOX0; + }else if(CAN_TSTAT_TME1 == (CAN_TSTAT(can_periph)&CAN_TSTAT_TME1)){ + mailbox_number = CAN_MAILBOX1; + }else if(CAN_TSTAT_TME2 == (CAN_TSTAT(can_periph)&CAN_TSTAT_TME2)){ + mailbox_number = CAN_MAILBOX2; + }else{ + mailbox_number = CAN_NOMAILBOX; + } + /* return no mailbox empty */ + if(CAN_NOMAILBOX == mailbox_number){ + return CAN_NOMAILBOX; + } + + CAN_TMI(can_periph, mailbox_number) &= CAN_TMI_TEN; + if(CAN_FF_STANDARD == transmit_message->tx_ff){ + /* set transmit mailbox standard identifier */ + CAN_TMI(can_periph, mailbox_number) |= (uint32_t)(TMI_SFID(transmit_message->tx_sfid) | \ + transmit_message->tx_ft); + }else{ + /* set transmit mailbox extended identifier */ + CAN_TMI(can_periph, mailbox_number) |= (uint32_t)(TMI_EFID(transmit_message->tx_efid) | \ + transmit_message->tx_ff | \ + transmit_message->tx_ft); + } + /* set the data length */ + CAN_TMP(can_periph, mailbox_number) &= ~CAN_TMP_DLENC; + CAN_TMP(can_periph, mailbox_number) |= transmit_message->tx_dlen; + /* set the data */ + CAN_TMDATA0(can_periph, mailbox_number) = TMDATA0_DB3(transmit_message->tx_data[3]) | \ + TMDATA0_DB2(transmit_message->tx_data[2]) | \ + TMDATA0_DB1(transmit_message->tx_data[1]) | \ + TMDATA0_DB0(transmit_message->tx_data[0]); + CAN_TMDATA1(can_periph, mailbox_number) = TMDATA1_DB7(transmit_message->tx_data[7]) | \ + TMDATA1_DB6(transmit_message->tx_data[6]) | \ + TMDATA1_DB5(transmit_message->tx_data[5]) | \ + TMDATA1_DB4(transmit_message->tx_data[4]); + /* enable transmission */ + CAN_TMI(can_periph, mailbox_number) |= CAN_TMI_TEN; + + return mailbox_number; +} + +/*! + \brief get CAN transmit state + \param[in] can_periph + \arg CANx(x=0,1),the CAN1 only for GD32F10x_CL + \param[in] mailbox_number + only one parameter can be selected which is shown as below: + \arg CAN_MAILBOX(x=0,1,2) + \param[out] none + \retval can_transmit_state_enum +*/ +can_transmit_state_enum can_transmit_states(uint32_t can_periph, uint8_t mailbox_number) +{ + can_transmit_state_enum state = CAN_TRANSMIT_FAILED; + uint32_t val = 0U; + + /* check selected mailbox state */ + switch(mailbox_number){ + /* mailbox0 */ + case CAN_MAILBOX0: + val = CAN_TSTAT(can_periph) & (CAN_TSTAT_MTF0 | CAN_TSTAT_MTFNERR0 | CAN_TSTAT_TME0); + break; + /* mailbox1 */ + case CAN_MAILBOX1: + val = CAN_TSTAT(can_periph) & (CAN_TSTAT_MTF1 | CAN_TSTAT_MTFNERR1 | CAN_TSTAT_TME1); + break; + /* mailbox2 */ + case CAN_MAILBOX2: + val = CAN_TSTAT(can_periph) & (CAN_TSTAT_MTF2 | CAN_TSTAT_MTFNERR2 | CAN_TSTAT_TME2); + break; + default: + val = CAN_TRANSMIT_FAILED; + break; + } + + switch(val){ + /* transmit pending */ + case (CAN_STATE_PENDING): + state = CAN_TRANSMIT_PENDING; + break; + /* mailbox0 transmit succeeded */ + case (CAN_TSTAT_MTF0 | CAN_TSTAT_MTFNERR0 | CAN_TSTAT_TME0): + state = CAN_TRANSMIT_OK; + break; + /* mailbox1 transmit succeeded */ + case (CAN_TSTAT_MTF1 | CAN_TSTAT_MTFNERR1 | CAN_TSTAT_TME1): + state = CAN_TRANSMIT_OK; + break; + /* mailbox2 transmit succeeded */ + case (CAN_TSTAT_MTF2 | CAN_TSTAT_MTFNERR2 | CAN_TSTAT_TME2): + state = CAN_TRANSMIT_OK; + break; + /* transmit failed */ + default: + state = CAN_TRANSMIT_FAILED; + break; + } + return state; +} + +/*! + \brief stop CAN transmission + \param[in] can_periph + \arg CANx(x=0,1),the CAN1 only for GD32F10x_CL + \param[in] mailbox_number + only one parameter can be selected which is shown as below: + \arg CAN_MAILBOXx(x=0,1,2) + \param[out] none + \retval none +*/ +void can_transmission_stop(uint32_t can_periph, uint8_t mailbox_number) +{ + if(CAN_MAILBOX0 == mailbox_number){ + CAN_TSTAT(can_periph) |= CAN_TSTAT_MST0; + while(CAN_TSTAT_MST0 == (CAN_TSTAT(can_periph) & CAN_TSTAT_MST0)){ + } + }else if(CAN_MAILBOX1 == mailbox_number){ + CAN_TSTAT(can_periph) |= CAN_TSTAT_MST1; + while(CAN_TSTAT_MST1 == (CAN_TSTAT(can_periph) & CAN_TSTAT_MST1)){ + } + }else if(CAN_MAILBOX2 == mailbox_number){ + CAN_TSTAT(can_periph) |= CAN_TSTAT_MST2; + while(CAN_TSTAT_MST2 == (CAN_TSTAT(can_periph) & CAN_TSTAT_MST2)){ + } + }else{ + /* illegal parameters */ + } +} + +/*! + \brief CAN receive message + \param[in] can_periph + \arg CANx(x=0,1),the CAN1 only for GD32F10x_CL + \param[in] fifo_number + \arg CAN_FIFOx(x=0,1) + \param[out] receive_message: struct for CAN receive message + \arg rx_sfid: 0x00000000 - 0x000007FF + \arg rx_efid: 0x00000000 - 0x1FFFFFFF + \arg rx_ff: CAN_FF_STANDARD, CAN_FF_EXTENDED + \arg rx_ft: CAN_FT_DATA, CAN_FT_REMOTE + \arg rx_dlen: 0 - 8 + \arg rx_data[]: 0x00 - 0xFF + \arg rx_fi: 0 - 27 + \retval none +*/ +void can_message_receive(uint32_t can_periph, uint8_t fifo_number, can_receive_message_struct* receive_message) +{ + /* get the frame format */ + receive_message->rx_ff = (uint8_t)(CAN_RFIFOMI_FF & CAN_RFIFOMI(can_periph, fifo_number)); + if(CAN_FF_STANDARD == receive_message->rx_ff){ + /* get standard identifier */ + receive_message->rx_sfid = (uint32_t)(GET_RFIFOMI_SFID(CAN_RFIFOMI(can_periph, fifo_number))); + }else{ + /* get extended identifier */ + receive_message->rx_efid = (uint32_t)(GET_RFIFOMI_EFID(CAN_RFIFOMI(can_periph, fifo_number))); + } + + /* get frame type */ + receive_message->rx_ft = (uint8_t)(CAN_RFIFOMI_FT & CAN_RFIFOMI(can_periph, fifo_number)); + /* filtering index */ + receive_message->rx_fi = (uint8_t)(GET_RFIFOMP_FI(CAN_RFIFOMP(can_periph, fifo_number))); + /* get recevie data length */ + receive_message->rx_dlen = (uint8_t)(GET_RFIFOMP_DLENC(CAN_RFIFOMP(can_periph, fifo_number))); + + /* receive data */ + receive_message -> rx_data[0] = (uint8_t)(GET_RFIFOMDATA0_DB0(CAN_RFIFOMDATA0(can_periph, fifo_number))); + receive_message -> rx_data[1] = (uint8_t)(GET_RFIFOMDATA0_DB1(CAN_RFIFOMDATA0(can_periph, fifo_number))); + receive_message -> rx_data[2] = (uint8_t)(GET_RFIFOMDATA0_DB2(CAN_RFIFOMDATA0(can_periph, fifo_number))); + receive_message -> rx_data[3] = (uint8_t)(GET_RFIFOMDATA0_DB3(CAN_RFIFOMDATA0(can_periph, fifo_number))); + receive_message -> rx_data[4] = (uint8_t)(GET_RFIFOMDATA1_DB4(CAN_RFIFOMDATA1(can_periph, fifo_number))); + receive_message -> rx_data[5] = (uint8_t)(GET_RFIFOMDATA1_DB5(CAN_RFIFOMDATA1(can_periph, fifo_number))); + receive_message -> rx_data[6] = (uint8_t)(GET_RFIFOMDATA1_DB6(CAN_RFIFOMDATA1(can_periph, fifo_number))); + receive_message -> rx_data[7] = (uint8_t)(GET_RFIFOMDATA1_DB7(CAN_RFIFOMDATA1(can_periph, fifo_number))); + + /* release FIFO */ + if(CAN_FIFO0 == fifo_number){ + CAN_RFIFO0(can_periph) |= CAN_RFIFO0_RFD0; + }else{ + CAN_RFIFO1(can_periph) |= CAN_RFIFO1_RFD1; + } +} + +/*! + \brief release FIFO0 + \param[in] can_periph + \arg CANx(x=0,1),the CAN1 only for GD32F10x_CL + \param[in] fifo_number + only one parameter can be selected which is shown as below: + \arg CAN_FIFOx(x=0,1) + \param[out] none + \retval none +*/ +void can_fifo_release(uint32_t can_periph, uint8_t fifo_number) +{ + if(CAN_FIFO0 == fifo_number){ + CAN_RFIFO0(can_periph) |= CAN_RFIFO0_RFD0; + }else if(CAN_FIFO1 == fifo_number){ + CAN_RFIFO1(can_periph) |= CAN_RFIFO1_RFD1; + }else{ + /* illegal parameters */ + CAN_ERROR_HANDLE("CAN FIFO NUM is invalid \r\n"); + } +} + +/*! + \brief CAN receive message length + \param[in] can_periph + \arg CANx(x=0,1),the CAN1 only for GD32F10x_CL + \param[in] fifo_number + only one parameter can be selected which is shown as below: + \arg CAN_FIFOx(x=0,1) + \param[out] none + \retval message length +*/ +uint8_t can_receive_message_length_get(uint32_t can_periph, uint8_t fifo_number) +{ + uint8_t val = 0U; + + if(CAN_FIFO0 == fifo_number){ + /* FIFO0 */ + val = (uint8_t)(CAN_RFIFO0(can_periph) & CAN_RFIF_RFL_MASK); + }else if(CAN_FIFO1 == fifo_number){ + /* FIFO1 */ + val = (uint8_t)(CAN_RFIFO1(can_periph) & CAN_RFIF_RFL_MASK); + }else{ + /* illegal parameters */ + } + return val; +} + +/*! + \brief set CAN working mode + \param[in] can_periph + \arg CANx(x=0,1),the CAN1 only for GD32F10x_CL + \param[in] can_working_mode + only one parameter can be selected which is shown as below: + \arg CAN_MODE_INITIALIZE + \arg CAN_MODE_NORMAL + \arg CAN_MODE_SLEEP + \param[out] none + \retval ErrStatus: SUCCESS or ERROR +*/ +ErrStatus can_working_mode_set(uint32_t can_periph, uint8_t working_mode) +{ + ErrStatus flag = ERROR; + /* timeout for IWS or also for SLPWS bits */ + uint32_t timeout = CAN_TIMEOUT; + + if(CAN_MODE_INITIALIZE == working_mode){ + /* disable sleep mode */ + CAN_CTL(can_periph) &= (~(uint32_t)CAN_CTL_SLPWMOD); + /* set initialize mode */ + CAN_CTL(can_periph) |= (uint8_t)CAN_CTL_IWMOD; + /* wait the acknowledge */ + while((CAN_STAT_IWS != (CAN_STAT(can_periph) & CAN_STAT_IWS)) && (0U != timeout)){ + timeout--; + } + if(CAN_STAT_IWS != (CAN_STAT(can_periph) & CAN_STAT_IWS)){ + flag = ERROR; + }else{ + flag = SUCCESS; + } + }else if(CAN_MODE_NORMAL == working_mode){ + /* enter normal mode */ + CAN_CTL(can_periph) &= ~(uint32_t)(CAN_CTL_SLPWMOD | CAN_CTL_IWMOD); + /* wait the acknowledge */ + while((0U != (CAN_STAT(can_periph) & (CAN_STAT_IWS | CAN_STAT_SLPWS))) && (0U != timeout)){ + timeout--; + } + if(0U != (CAN_STAT(can_periph) & (CAN_STAT_IWS | CAN_STAT_SLPWS))){ + flag = ERROR; + }else{ + flag = SUCCESS; + } + }else if(CAN_MODE_SLEEP == working_mode){ + /* disable initialize mode */ + CAN_CTL(can_periph) &= (~(uint32_t)CAN_CTL_IWMOD); + /* set sleep mode */ + CAN_CTL(can_periph) |= (uint8_t)CAN_CTL_SLPWMOD; + /* wait the acknowledge */ + while((CAN_STAT_SLPWS != (CAN_STAT(can_periph) & CAN_STAT_SLPWS)) && (0U != timeout)){ + timeout--; + } + if(CAN_STAT_SLPWS != (CAN_STAT(can_periph) & CAN_STAT_SLPWS)){ + flag = ERROR; + }else{ + flag = SUCCESS; + } + }else{ + flag = ERROR; + } + return flag; +} + +/*! + \brief wake up CAN + \param[in] can_periph + \arg CANx(x=0,1),the CAN1 only for GD32F10x_CL + \param[out] none + \retval ErrStatus: SUCCESS or ERROR +*/ +ErrStatus can_wakeup(uint32_t can_periph) +{ + ErrStatus flag = ERROR; + uint32_t timeout = CAN_TIMEOUT; + + /* wakeup */ + CAN_CTL(can_periph) &= ~CAN_CTL_SLPWMOD; + + while((0U != (CAN_STAT(can_periph) & CAN_STAT_SLPWS)) && (0x00U != timeout)){ + timeout--; + } + /* check state */ + if(0U != (CAN_STAT(can_periph) & CAN_STAT_SLPWS)){ + flag = ERROR; + }else{ + flag = SUCCESS; + } + return flag; +} + +/*! + \brief get CAN error type + \param[in] can_periph + \arg CANx(x=0,1),the CAN1 only for GD32F10x_CL + \param[out] none + \retval can_error_enum + \arg CAN_ERROR_NONE: no error + \arg CAN_ERROR_FILL: fill error + \arg CAN_ERROR_FORMATE: format error + \arg CAN_ERROR_ACK: ACK error + \arg CAN_ERROR_BITRECESSIVE: bit recessive + \arg CAN_ERROR_BITDOMINANTER: bit dominant error + \arg CAN_ERROR_CRC: CRC error + \arg CAN_ERROR_SOFTWARECFG: software configure +*/ +can_error_enum can_error_get(uint32_t can_periph) +{ + can_error_enum error; + error = CAN_ERROR_NONE; + + /* get error type */ + error = (can_error_enum)(GET_ERR_ERRN(CAN_ERR(can_periph))); + return error; +} + +/*! + \brief get CAN receive error number + \param[in] can_periph + \arg CANx(x=0,1),the CAN1 only for GD32F10x_CL + \param[out] none + \retval error number +*/ +uint8_t can_receive_error_number_get(uint32_t can_periph) +{ + uint8_t val; + + /* get error count */ + val = (uint8_t)(GET_ERR_RECNT(CAN_ERR(can_periph))); + return val; +} + +/*! + \brief get CAN transmit error number + \param[in] can_periph + \arg CANx(x=0,1),the CAN1 only for GD32F10x_CL + \param[out] none + \retval error number +*/ +uint8_t can_transmit_error_number_get(uint32_t can_periph) +{ + uint8_t val; + + val = (uint8_t)(GET_ERR_TECNT(CAN_ERR(can_periph))); + return val; +} + +/*! + \brief enable CAN interrupt + \param[in] can_periph + \arg CANx(x=0,1),the CAN1 only for GD32F10x_CL + \param[in] interrupt + one or more parameters can be selected which are shown as below: + \arg CAN_INT_TME: transmit mailbox empty interrupt enable + \arg CAN_INT_RFNE0: receive FIFO0 not empty interrupt enable + \arg CAN_INT_RFF0: receive FIFO0 full interrupt enable + \arg CAN_INT_RFO0: receive FIFO0 overfull interrupt enable + \arg CAN_INT_RFNE1: receive FIFO1 not empty interrupt enable + \arg CAN_INT_RFF1: receive FIFO1 full interrupt enable + \arg CAN_INT_RFO1: receive FIFO1 overfull interrupt enable + \arg CAN_INT_WERR: warning error interrupt enable + \arg CAN_INT_PERR: passive error interrupt enable + \arg CAN_INT_BO: bus-off interrupt enable + \arg CAN_INT_ERRN: error number interrupt enable + \arg CAN_INT_ERR: error interrupt enable + \arg CAN_INT_WU: wakeup interrupt enable + \arg CAN_INT_SLPW: sleep working interrupt enable + \param[out] none + \retval none +*/ +void can_interrupt_enable(uint32_t can_periph, uint32_t interrupt) +{ + CAN_INTEN(can_periph) |= interrupt; +} + +/*! + \brief disable CAN interrupt + \param[in] can_periph + \arg CANx(x=0,1),the CAN1 only for GD32F10x_CL + \param[in] interrupt + one or more parameters can be selected which are shown as below: + \arg CAN_INT_TME: transmit mailbox empty interrupt enable + \arg CAN_INT_RFNE0: receive FIFO0 not empty interrupt enable + \arg CAN_INT_RFF0: receive FIFO0 full interrupt enable + \arg CAN_INT_RFO0: receive FIFO0 overfull interrupt enable + \arg CAN_INT_RFNE1: receive FIFO1 not empty interrupt enable + \arg CAN_INT_RFF1: receive FIFO1 full interrupt enable + \arg CAN_INT_RFO1: receive FIFO1 overfull interrupt enable + \arg CAN_INT_WERR: warning error interrupt enable + \arg CAN_INT_PERR: passive error interrupt enable + \arg CAN_INT_BO: bus-off interrupt enable + \arg CAN_INT_ERRN: error number interrupt enable + \arg CAN_INT_ERR: error interrupt enable + \arg CAN_INT_WU: wakeup interrupt enable + \arg CAN_INT_SLPW: sleep working interrupt enable + \param[out] none + \retval none +*/ +void can_interrupt_disable(uint32_t can_periph, uint32_t interrupt) +{ + CAN_INTEN(can_periph) &= ~interrupt; +} + +/*! + \brief get CAN flag state + \param[in] can_periph + \arg CANx(x=0,1),the CAN1 only for GD32F10x_CL + \param[in] flag: CAN flags, refer to can_flag_enum + only one parameter can be selected which is shown as below: + \arg CAN_FLAG_RXL: RX level + \arg CAN_FLAG_LASTRX: last sample value of RX pin + \arg CAN_FLAG_RS: receiving state + \arg CAN_FLAG_TS: transmitting state + \arg CAN_FLAG_SLPIF: status change flag of entering sleep working mode + \arg CAN_FLAG_WUIF: status change flag of wakeup from sleep working mode + \arg CAN_FLAG_ERRIF: error flag + \arg CAN_FLAG_SLPWS: sleep working state + \arg CAN_FLAG_IWS: initial working state + \arg CAN_FLAG_TMLS2: transmit mailbox 2 last sending in Tx FIFO + \arg CAN_FLAG_TMLS1: transmit mailbox 1 last sending in Tx FIFO + \arg CAN_FLAG_TMLS0: transmit mailbox 0 last sending in Tx FIFO + \arg CAN_FLAG_TME2: transmit mailbox 2 empty + \arg CAN_FLAG_TME1: transmit mailbox 1 empty + \arg CAN_FLAG_TME0: transmit mailbox 0 empty + \arg CAN_FLAG_MTE2: mailbox 2 transmit error + \arg CAN_FLAG_MTE1: mailbox 1 transmit error + \arg CAN_FLAG_MTE0: mailbox 0 transmit error + \arg CAN_FLAG_MAL2: mailbox 2 arbitration lost + \arg CAN_FLAG_MAL1: mailbox 1 arbitration lost + \arg CAN_FLAG_MAL0: mailbox 0 arbitration lost + \arg CAN_FLAG_MTFNERR2: mailbox 2 transmit finished with no error + \arg CAN_FLAG_MTFNERR1: mailbox 1 transmit finished with no error + \arg CAN_FLAG_MTFNERR0: mailbox 0 transmit finished with no error + \arg CAN_FLAG_MTF2: mailbox 2 transmit finished + \arg CAN_FLAG_MTF1: mailbox 1 transmit finished + \arg CAN_FLAG_MTF0: mailbox 0 transmit finished + \arg CAN_FLAG_RFO0: receive FIFO0 overfull + \arg CAN_FLAG_RFF0: receive FIFO0 full + \arg CAN_FLAG_RFO1: receive FIFO1 overfull + \arg CAN_FLAG_RFF1: receive FIFO1 full + \arg CAN_FLAG_BOERR: bus-off error + \arg CAN_FLAG_PERR: passive error + \arg CAN_FLAG_WERR: warning error + \param[out] none + \retval FlagStatus: SET or RESET +*/ +FlagStatus can_flag_get(uint32_t can_periph, can_flag_enum flag) +{ + /* get flag and interrupt enable state */ + if(RESET != (CAN_REG_VAL(can_periph, flag) & BIT(CAN_BIT_POS(flag)))){ + return SET; + }else{ + return RESET; + } +} + +/*! + \brief clear CAN flag state + \param[in] can_periph + \arg CANx(x=0,1),the CAN1 only for GD32F10x_CL + \param[in] flag: CAN flags, refer to can_flag_enum + only one parameter can be selected which is shown as below: + \arg CAN_FLAG_SLPIF: status change flag of entering sleep working mode + \arg CAN_FLAG_WUIF: status change flag of wakeup from sleep working mode + \arg CAN_FLAG_ERRIF: error flag + \arg CAN_FLAG_MTE2: mailbox 2 transmit error + \arg CAN_FLAG_MTE1: mailbox 1 transmit error + \arg CAN_FLAG_MTE0: mailbox 0 transmit error + \arg CAN_FLAG_MAL2: mailbox 2 arbitration lost + \arg CAN_FLAG_MAL1: mailbox 1 arbitration lost + \arg CAN_FLAG_MAL0: mailbox 0 arbitration lost + \arg CAN_FLAG_MTFNERR2: mailbox 2 transmit finished with no error + \arg CAN_FLAG_MTFNERR1: mailbox 1 transmit finished with no error + \arg CAN_FLAG_MTFNERR0: mailbox 0 transmit finished with no error + \arg CAN_FLAG_MTF2: mailbox 2 transmit finished + \arg CAN_FLAG_MTF1: mailbox 1 transmit finished + \arg CAN_FLAG_MTF0: mailbox 0 transmit finished + \arg CAN_FLAG_RFO0: receive FIFO0 overfull + \arg CAN_FLAG_RFF0: receive FIFO0 full + \arg CAN_FLAG_RFO1: receive FIFO1 overfull + \arg CAN_FLAG_RFF1: receive FIFO1 full + \param[out] none + \retval none +*/ +void can_flag_clear(uint32_t can_periph, can_flag_enum flag) +{ + if (flag == CAN_FLAG_RFO1){ + CAN_REG_VAL(can_periph, flag) = RFO1_CLEAR_VAL; + } else if (flag == CAN_FLAG_RFF1){ + CAN_REG_VAL(can_periph, flag) = RFF1_CLEAR_VAL; + } else { + CAN_REG_VAL(can_periph, flag) = BIT(CAN_BIT_POS(flag)); + } +} + +/*! + \brief get CAN interrupt flag state + \param[in] can_periph + \arg CANx(x=0,1),the CAN1 only for GD32F10x_CL + \param[in] flag: CAN interrupt flags, refer to can_interrupt_flag_enum + only one parameter can be selected which is shown as below: + \arg CAN_INT_FLAG_SLPIF: status change interrupt flag of sleep working mode entering + \arg CAN_INT_FLAG_WUIF: status change interrupt flag of wakeup from sleep working mode + \arg CAN_INT_FLAG_ERRIF: error interrupt flag + \arg CAN_INT_FLAG_MTF2: mailbox 2 transmit finished interrupt flag + \arg CAN_INT_FLAG_MTF1: mailbox 1 transmit finished interrupt flag + \arg CAN_INT_FLAG_MTF0: mailbox 0 transmit finished interrupt flag + \arg CAN_INT_FLAG_RFO0: receive FIFO0 overfull interrupt flag + \arg CAN_INT_FLAG_RFF0: receive FIFO0 full interrupt flag + \arg CAN_INT_FLAG_RFL0: receive FIFO0 not empty interrupt flag + \arg CAN_INT_FLAG_RFO1: receive FIFO1 overfull interrupt flag + \arg CAN_INT_FLAG_RFF1: receive FIFO1 full interrupt flag + \arg CAN_INT_FLAG_RFL1: receive FIFO1 not empty interrupt flag + \arg CAN_INT_FLAG_ERRN: error number interrupt flag + \arg CAN_INT_FLAG_BOERR: bus-off error interrupt flag + \arg CAN_INT_FLAG_PERR: passive error interrupt flag + \arg CAN_INT_FLAG_WERR: warning error interrupt flag + \param[out] none + \retval FlagStatus: SET or RESET +*/ +FlagStatus can_interrupt_flag_get(uint32_t can_periph, can_interrupt_flag_enum flag) +{ + uint32_t ret1 = RESET; + uint32_t ret2 = RESET; + + /* get the staus of interrupt flag */ + if (flag == CAN_INT_FLAG_RFL0) { + ret1 = can_receive_message_length_get(can_periph, CAN_FIFO0); + } else if (flag == CAN_INT_FLAG_RFL1) { + ret1 = can_receive_message_length_get(can_periph, CAN_FIFO1); + } else if (flag == CAN_INT_FLAG_ERRN) { + ret1 = can_error_get(can_periph); + } else { + ret1 = CAN_REG_VALS(can_periph, flag) & BIT(CAN_BIT_POS0(flag)); + } + /* get the staus of interrupt enale bit */ + ret2 = CAN_INTEN(can_periph) & BIT(CAN_BIT_POS1(flag)); + if(ret1 && ret2){ + return SET; + }else{ + return RESET; + } +} + +/*! + \brief clear CAN interrupt flag state + \param[in] can_periph + \arg CANx(x=0,1),the CAN1 only for GD32F10x_CL + \param[in] flag: CAN interrupt flags, refer to can_interrupt_flag_enum + only one parameter can be selected which is shown as below: + \arg CAN_INT_FLAG_SLPIF: status change interrupt flag of sleep working mode entering + \arg CAN_INT_FLAG_WUIF: status change interrupt flag of wakeup from sleep working mode + \arg CAN_INT_FLAG_ERRIF: error interrupt flag + \arg CAN_INT_FLAG_MTF2: mailbox 2 transmit finished interrupt flag + \arg CAN_INT_FLAG_MTF1: mailbox 1 transmit finished interrupt flag + \arg CAN_INT_FLAG_MTF0: mailbox 0 transmit finished interrupt flag + \arg CAN_INT_FLAG_RFO0: receive FIFO0 overfull interrupt flag + \arg CAN_INT_FLAG_RFF0: receive FIFO0 full interrupt flag + \arg CAN_INT_FLAG_RFO1: receive FIFO1 overfull interrupt flag + \arg CAN_INT_FLAG_RFF1: receive FIFO1 full interrupt flag + \param[out] none + \retval none +*/ +void can_interrupt_flag_clear(uint32_t can_periph, can_interrupt_flag_enum flag) +{ + if (flag == CAN_INT_FLAG_RFO1){ + CAN_REG_VALS(can_periph, flag) = RFO1_CLEAR_VAL; + } else if (flag == CAN_INT_FLAG_RFF1){ + CAN_REG_VALS(can_periph, flag) = RFF1_CLEAR_VAL; + } else { + CAN_REG_VALS(can_periph, flag) = BIT(CAN_BIT_POS0(flag)); + } +} diff --git a/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_standard_peripheral/Source/gd32f10x_crc.c b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_standard_peripheral/Source/gd32f10x_crc.c new file mode 100644 index 0000000000..d2a3f12761 --- /dev/null +++ b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_standard_peripheral/Source/gd32f10x_crc.c @@ -0,0 +1,130 @@ +/*! + \file gd32f10x_crc.c + \brief CRC driver + + \version 2014-12-26, V1.0.0, firmware for GD32F10x + \version 2017-06-20, V2.0.0, firmware for GD32F10x + \version 2018-07-31, V2.1.0, firmware for GD32F10x + \version 2020-09-30, V2.2.0, firmware for GD32F10x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "gd32f10x_crc.h" + +#define CRC_DATA_RESET_VALUE ((uint32_t)0xFFFFFFFFU) +#define CRC_FDATA_RESET_VALUE ((uint32_t)0x00000000U) + +/*! + \brief deinit CRC calculation unit + \param[in] none + \param[out] none + \retval none +*/ +void crc_deinit(void) +{ + CRC_DATA = CRC_DATA_RESET_VALUE; + CRC_FDATA = CRC_FDATA_RESET_VALUE; + CRC_CTL = (uint32_t)CRC_CTL_RST; +} + +/*! + \brief reset data register to the value of initializaiton data register + \param[in] none + \param[out] none + \retval none +*/ +void crc_data_register_reset(void) +{ + CRC_CTL |= (uint32_t)CRC_CTL_RST; +} + +/*! + \brief read the value of the data register + \param[in] none + \param[out] none + \retval 32-bit value of the data register +*/ +uint32_t crc_data_register_read(void) +{ + uint32_t data; + data = CRC_DATA; + return (data); +} + +/*! + \brief read the value of the free data register + \param[in] none + \param[out] none + \retval 8-bit value of the free data register +*/ +uint8_t crc_free_data_register_read(void) +{ + uint8_t fdata; + fdata = (uint8_t)CRC_FDATA; + return (fdata); +} + +/*! + \brief write data to the free data register + \param[in] free_data: specify 8-bit data + \param[out] none + \retval none +*/ +void crc_free_data_register_write(uint8_t free_data) +{ + CRC_FDATA = (uint32_t)free_data; +} + +/*! + \brief calculate the CRC value of a 32-bit data + \param[in] sdata: specified 32-bit data + \param[out] none + \retval 32-bit value calculated by CRC +*/ +uint32_t crc_single_data_calculate(uint32_t sdata) +{ + CRC_DATA = sdata; + return (CRC_DATA); +} + +/*! + \brief calculate the CRC value of an array of 32-bit values + \param[in] array: pointer to an array of 32-bit values + \param[in] size: size of the array + \param[out] none + \retval 32-bit value calculated by CRC +*/ +uint32_t crc_block_data_calculate(uint32_t array[], uint32_t size) +{ + uint32_t index; + for(index = 0U; index < size; index++){ + CRC_DATA = array[index]; + } + return (CRC_DATA); +} diff --git a/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_standard_peripheral/Source/gd32f10x_dac.c b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_standard_peripheral/Source/gd32f10x_dac.c new file mode 100644 index 0000000000..482c8a0cb6 --- /dev/null +++ b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_standard_peripheral/Source/gd32f10x_dac.c @@ -0,0 +1,558 @@ +/*! + \file gd32f10x_dac.c + \brief DAC driver + + \version 2014-12-26, V1.0.0, firmware for GD32F10x + \version 2017-06-20, V2.0.0, firmware for GD32F10x + \version 2018-07-31, V2.1.0, firmware for GD32F10x + \version 2020-09-30, V2.2.0, firmware for GD32F10x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "gd32f10x_dac.h" + +/* DAC register bit offset */ +#define DAC1_REG_OFFSET ((uint32_t)16U) +#define DH_12BIT_OFFSET ((uint32_t)16U) +#define DH_8BIT_OFFSET ((uint32_t)8U) + +/*! + \brief deinitialize DAC + \param[in] none + \param[out] none + \retval none +*/ +void dac_deinit(void) +{ + rcu_periph_reset_enable(RCU_DACRST); + rcu_periph_reset_disable(RCU_DACRST); +} + +/*! + \brief enable DAC + \param[in] dac_periph + \arg DACx(x=0,1) + \param[out] none + \retval none +*/ +void dac_enable(uint32_t dac_periph) +{ + if(DAC0 == dac_periph){ + DAC_CTL |= DAC_CTL_DEN0; + }else{ + DAC_CTL |= DAC_CTL_DEN1; + } +} + +/*! + \brief disable DAC + \param[in] dac_periph + \arg DACx(x=0,1) + \param[out] none + \retval none +*/ +void dac_disable(uint32_t dac_periph) +{ + if(DAC0 == dac_periph){ + DAC_CTL &= ~DAC_CTL_DEN0; + }else{ + DAC_CTL &= ~DAC_CTL_DEN1; + } +} + +/*! + \brief enable DAC DMA function + \param[in] dac_periph + \arg DACx(x=0,1) + \param[out] none + \retval none +*/ +void dac_dma_enable(uint32_t dac_periph) +{ + if(DAC0 == dac_periph){ + DAC_CTL |= DAC_CTL_DDMAEN0; + }else{ + DAC_CTL |= DAC_CTL_DDMAEN1; + } +} + +/*! + \brief disable DAC DMA function + \param[in] dac_periph + \arg DACx(x=0,1) + \param[out] none + \retval none +*/ +void dac_dma_disable(uint32_t dac_periph) +{ + if(DAC0 == dac_periph){ + DAC_CTL &= ~DAC_CTL_DDMAEN0; + }else{ + DAC_CTL &= ~DAC_CTL_DDMAEN1; + } +} + +/*! + \brief enable DAC output buffer + \param[in] dac_periph + \arg DACx(x=0,1) + \param[out] none + \retval none +*/ +void dac_output_buffer_enable(uint32_t dac_periph) +{ + if(DAC0 == dac_periph){ + DAC_CTL &= ~DAC_CTL_DBOFF0; + }else{ + DAC_CTL &= ~DAC_CTL_DBOFF1; + } +} + +/*! + \brief disable DAC output buffer + \param[in] dac_periph + \arg DACx(x=0,1) + \param[out] none + \retval none +*/ +void dac_output_buffer_disable(uint32_t dac_periph) +{ + if(DAC0 == dac_periph){ + DAC_CTL |= DAC_CTL_DBOFF0; + }else{ + DAC_CTL |= DAC_CTL_DBOFF1; + } +} + +/*! + \brief get DAC output value + \param[in] dac_periph + \arg DACx(x=0,1) + \param[out] none + \retval DAC output data +*/ +uint16_t dac_output_value_get(uint32_t dac_periph) +{ + uint16_t data = 0U; + if(DAC0 == dac_periph){ + /* store the DAC0 output value */ + data = (uint16_t)DAC0_DO; + }else{ + /* store the DAC1 output value */ + data = (uint16_t)DAC1_DO; + } + return data; +} + +/*! + \brief set the DAC specified data holding register value + \param[in] dac_periph + \arg DACx(x=0,1) + \param[in] dac_align + only one parameter can be selected which is shown as below: + \arg DAC_ALIGN_8B_R: data right 8b alignment + \arg DAC_ALIGN_12B_R: data right 12b alignment + \arg DAC_ALIGN_12B_L: data left 12b alignment + \param[in] data: data to be loaded + \param[out] none + \retval none +*/ +void dac_data_set(uint32_t dac_periph, uint32_t dac_align, uint16_t data) +{ + if(DAC0 == dac_periph){ + switch(dac_align){ + /* data right 12b alignment */ + case DAC_ALIGN_12B_R: + DAC0_R12DH = data; + break; + /* data left 12b alignment */ + case DAC_ALIGN_12B_L: + DAC0_L12DH = data; + break; + /* data right 8b alignment */ + case DAC_ALIGN_8B_R: + DAC0_R8DH = data; + break; + default: + break; + } + }else{ + switch(dac_align){ + /* data right 12b alignment */ + case DAC_ALIGN_12B_R: + DAC1_R12DH = data; + break; + /* data left 12b alignment */ + case DAC_ALIGN_12B_L: + DAC1_L12DH = data; + break; + /* data right 8b alignment */ + case DAC_ALIGN_8B_R: + DAC1_R8DH = data; + break; + default: + break; + } + } +} + +/*! + \brief enable DAC trigger + \param[in] dac_periph + \arg DACx(x=0,1) + \param[out] none + \retval none +*/ +void dac_trigger_enable(uint32_t dac_periph) +{ + if(DAC0 == dac_periph){ + DAC_CTL |= DAC_CTL_DTEN0; + }else{ + DAC_CTL |= DAC_CTL_DTEN1; + } +} + +/*! + \brief disable DAC trigger + \param[in] dac_periph + \arg DACx(x=0,1) + \param[out] none + \retval none +*/ +void dac_trigger_disable(uint32_t dac_periph) +{ + if(DAC0 == dac_periph){ + DAC_CTL &= ~DAC_CTL_DTEN0; + }else{ + DAC_CTL &= ~DAC_CTL_DTEN1; + } +} + +/*! + \brief set DAC trigger source + \param[in] dac_periph + \arg DACx(x=0,1) + \param[in] triggersource: external triggers of DAC + only one parameter can be selected which is shown as below: + \arg DAC_TRIGGER_T1_TRGO: TIMER1 TRGO + \arg DAC_TRIGGER_T2_TRGO: TIMER2 TRGO (for GD32F10X_CL) + \arg DAC_TRIGGER_T3_TRGO: TIMER3 TRGO + \arg DAC_TRIGGER_T4_TRGO: TIMER4 TRGO + \arg DAC_TRIGGER_T5_TRGO: TIMER5 TRGO + \arg DAC_TRIGGER_T6_TRGO: TIMER6 TRGO + \arg DAC_TRIGGER_T7_TRGO: TIMER7 TRGO (for GD32F10X_MD and GD32F10X_HD and GD32F10X_XD) + \arg DAC_TRIGGER_EXTI_9: EXTI interrupt line9 event + \arg DAC_TRIGGER_SOFTWARE: software trigger + \param[out] none + \retval none +*/ +void dac_trigger_source_config(uint32_t dac_periph,uint32_t triggersource) +{ + if(DAC0 == dac_periph){ + /* configure DAC0 trigger source */ + DAC_CTL &= ~DAC_CTL_DTSEL0; + DAC_CTL |= triggersource; + }else{ + /* configure DAC1 trigger source */ + DAC_CTL &= ~DAC_CTL_DTSEL1; + DAC_CTL |= (triggersource << DAC1_REG_OFFSET); + } +} + +/*! + \brief enable DAC software trigger + \param[in] dac_periph + \arg DACx(x=0,1) + \retval none +*/ +void dac_software_trigger_enable(uint32_t dac_periph) +{ + if(DAC0 == dac_periph){ + DAC_SWT |= DAC_SWT_SWTR0; + }else{ + DAC_SWT |= DAC_SWT_SWTR1; + } +} + +/*! + \brief disable DAC software trigger + \param[in] dac_periph + \arg DACx(x=0,1) + \param[out] none + \retval none +*/ +void dac_software_trigger_disable(uint32_t dac_periph) +{ + if(DAC0 == dac_periph){ + DAC_SWT &= ~DAC_SWT_SWTR0; + }else{ + DAC_SWT &= ~DAC_SWT_SWTR1; + } +} + +/*! + \brief configure DAC wave mode + \param[in] dac_periph + \arg DACx(x=0,1) + \param[in] wave_mode + only one parameter can be selected which is shown as below: + \arg DAC_WAVE_DISABLE: wave disable + \arg DAC_WAVE_MODE_LFSR: LFSR noise mode + \arg DAC_WAVE_MODE_TRIANGLE: triangle noise mode + \param[out] none + \retval none +*/ +void dac_wave_mode_config(uint32_t dac_periph, uint32_t wave_mode) +{ + if(DAC0 == dac_periph){ + /* configure DAC0 wave mode */ + DAC_CTL &= ~DAC_CTL_DWM0; + DAC_CTL |= wave_mode; + }else{ + /* configure DAC1 wave mode */ + DAC_CTL &= ~DAC_CTL_DWM1; + DAC_CTL |= (wave_mode << DAC1_REG_OFFSET); + } +} + +/*! + \brief configure DAC wave bit width + \param[in] dac_periph + \arg DACx(x=0,1) + \param[in] bit_width + only one parameter can be selected which is shown as below: + \arg DAC_WAVE_BIT_WIDTH_1: bit width of the wave signal is 1 + \arg DAC_WAVE_BIT_WIDTH_2: bit width of the wave signal is 2 + \arg DAC_WAVE_BIT_WIDTH_3: bit width of the wave signal is 3 + \arg DAC_WAVE_BIT_WIDTH_4: bit width of the wave signal is 4 + \arg DAC_WAVE_BIT_WIDTH_5: bit width of the wave signal is 5 + \arg DAC_WAVE_BIT_WIDTH_6: bit width of the wave signal is 6 + \arg DAC_WAVE_BIT_WIDTH_7: bit width of the wave signal is 7 + \arg DAC_WAVE_BIT_WIDTH_8: bit width of the wave signal is 8 + \arg DAC_WAVE_BIT_WIDTH_9: bit width of the wave signal is 9 + \arg DAC_WAVE_BIT_WIDTH_10: bit width of the wave signal is 10 + \arg DAC_WAVE_BIT_WIDTH_11: bit width of the wave signal is 11 + \arg DAC_WAVE_BIT_WIDTH_12: bit width of the wave signal is 12 + \param[out] none + \retval none +*/ +void dac_wave_bit_width_config(uint32_t dac_periph, uint32_t bit_width) +{ + if(DAC0 == dac_periph){ + /* configure DAC0 wave bit width */ + DAC_CTL &= ~DAC_CTL_DWBW0; + DAC_CTL |= bit_width; + }else{ + /* configure DAC1 wave bit width */ + DAC_CTL &= ~DAC_CTL_DWBW1; + DAC_CTL |= (bit_width << DAC1_REG_OFFSET); + } +} + +/*! + \brief configure DAC LFSR noise mode + \param[in] dac_periph + \arg DACx(x=0,1) + \param[in] unmask_bits + only one parameter can be selected which is shown as below: + \arg DAC_LFSR_BIT0: unmask the LFSR bit0 + \arg DAC_LFSR_BITS1_0: unmask the LFSR bits[1:0] + \arg DAC_LFSR_BITS2_0: unmask the LFSR bits[2:0] + \arg DAC_LFSR_BITS3_0: unmask the LFSR bits[3:0] + \arg DAC_LFSR_BITS4_0: unmask the LFSR bits[4:0] + \arg DAC_LFSR_BITS5_0: unmask the LFSR bits[5:0] + \arg DAC_LFSR_BITS6_0: unmask the LFSR bits[6:0] + \arg DAC_LFSR_BITS7_0: unmask the LFSR bits[7:0] + \arg DAC_LFSR_BITS8_0: unmask the LFSR bits[8:0] + \arg DAC_LFSR_BITS9_0: unmask the LFSR bits[9:0] + \arg DAC_LFSR_BITS10_0: unmask the LFSR bits[10:0] + \arg DAC_LFSR_BITS11_0: unmask the LFSR bits[11:0] + \param[out] none + \retval none +*/ +void dac_lfsr_noise_config(uint32_t dac_periph, uint32_t unmask_bits) +{ + if(DAC0 == dac_periph){ + /* configure DAC0 LFSR noise mode */ + DAC_CTL &= ~DAC_CTL_DWBW0; + DAC_CTL |= unmask_bits; + }else{ + /* configure DAC1 LFSR noise mode */ + DAC_CTL &= ~DAC_CTL_DWBW1; + DAC_CTL |= (unmask_bits << DAC1_REG_OFFSET); + } +} + +/*! + \brief configure DAC triangle noise mode + \param[in] dac_periph + \arg DACx(x=0,1) + \param[in] amplitude + only one parameter can be selected which is shown as below: + \arg DAC_TRIANGLE_AMPLITUDE_1: triangle amplitude is 1 + \arg DAC_TRIANGLE_AMPLITUDE_3: triangle amplitude is 3 + \arg DAC_TRIANGLE_AMPLITUDE_7: triangle amplitude is 7 + \arg DAC_TRIANGLE_AMPLITUDE_15: triangle amplitude is 15 + \arg DAC_TRIANGLE_AMPLITUDE_31: triangle amplitude is 31 + \arg DAC_TRIANGLE_AMPLITUDE_63: triangle amplitude is 63 + \arg DAC_TRIANGLE_AMPLITUDE_127: triangle amplitude is 127 + \arg DAC_TRIANGLE_AMPLITUDE_255: triangle amplitude is 255 + \arg DAC_TRIANGLE_AMPLITUDE_511: triangle amplitude is 511 + \arg DAC_TRIANGLE_AMPLITUDE_1023: triangle amplitude is 1023 + \arg DAC_TRIANGLE_AMPLITUDE_2047: triangle amplitude is 2047 + \arg DAC_TRIANGLE_AMPLITUDE_4095: triangle amplitude is 4095 + \param[out] none + \retval none +*/ +void dac_triangle_noise_config(uint32_t dac_periph, uint32_t amplitude) +{ + if(DAC0 == dac_periph){ + /* configure DAC0 triangle noise mode */ + DAC_CTL &= ~DAC_CTL_DWBW0; + DAC_CTL |= amplitude; + }else{ + /* configure DAC1 triangle noise mode */ + DAC_CTL &= ~DAC_CTL_DWBW1; + DAC_CTL |= (amplitude << DAC1_REG_OFFSET); + } +} + +/*! + \brief enable DAC concurrent mode + \param[in] none + \param[out] none + \retval none +*/ +void dac_concurrent_enable(void) +{ + uint32_t ctl = 0U; + ctl = DAC_CTL_DEN0 | DAC_CTL_DEN1; + DAC_CTL |= (ctl); +} + +/*! + \brief disable DAC concurrent mode + \param[in] none + \param[out] none + \retval none +*/ +void dac_concurrent_disable(void) +{ + uint32_t ctl = 0U; + ctl = DAC_CTL_DEN0 | DAC_CTL_DEN1; + DAC_CTL &= (~ctl); +} + +/*! + \brief enable DAC concurrent software trigger function + \param[in] none + \param[out] none + \retval none +*/ +void dac_concurrent_software_trigger_enable(void) +{ + uint32_t swt = 0U; + swt = DAC_SWT_SWTR0 | DAC_SWT_SWTR1; + DAC_SWT |= (swt); +} + +/*! + \brief disable DAC concurrent software trigger function + \param[in] none + \param[out] none + \retval none +*/ +void dac_concurrent_software_trigger_disable(void) +{ + uint32_t swt = 0U; + swt = DAC_SWT_SWTR0 | DAC_SWT_SWTR1; + DAC_SWT &= (~swt); +} + +/*! + \brief enable DAC concurrent buffer function + \param[in] none + \param[out] none + \retval none +*/ +void dac_concurrent_output_buffer_enable(void) +{ + uint32_t ctl = 0U; + ctl = DAC_CTL_DBOFF0 | DAC_CTL_DBOFF1; + DAC_CTL &= (~ctl); +} + +/*! + \brief disable DAC concurrent buffer function + \param[in] none + \param[out] none + \retval none +*/ +void dac_concurrent_output_buffer_disable(void) +{ + uint32_t ctl = 0U; + ctl = DAC_CTL_DBOFF0 | DAC_CTL_DBOFF1; + DAC_CTL |= (ctl); +} + +/*! + \brief set DAC concurrent mode data holding register value + \param[in] dac_align + only one parameter can be selected which is shown as below: + \arg DAC_ALIGN_8B_R: data right 8b alignment + \arg DAC_ALIGN_12B_R: data right 12b alignment + \arg DAC_ALIGN_12B_L: data left 12b alignment + \param[in] data0: data to be loaded + \param[in] data1: data to be loaded + \param[out] none + \retval none +*/ +void dac_concurrent_data_set(uint32_t dac_align, uint16_t data0, uint16_t data1) +{ + uint32_t data = 0U; + switch(dac_align){ + /* data right 12b alignment */ + case DAC_ALIGN_12B_R: + data = ((uint32_t)data1 << DH_12BIT_OFFSET) | data0; + DACC_R12DH = data; + break; + /* data left 12b alignment */ + case DAC_ALIGN_12B_L: + data = ((uint32_t)data1 << DH_12BIT_OFFSET) | data0; + DACC_L12DH = data; + break; + /* data right 8b alignment */ + case DAC_ALIGN_8B_R: + data = ((uint32_t)data1 << DH_8BIT_OFFSET) | data0; + DACC_R8DH = data; + break; + default: + break; + } +} diff --git a/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_standard_peripheral/Source/gd32f10x_dbg.c b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_standard_peripheral/Source/gd32f10x_dbg.c new file mode 100644 index 0000000000..937e40c54d --- /dev/null +++ b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_standard_peripheral/Source/gd32f10x_dbg.c @@ -0,0 +1,152 @@ +/*! + \file gd32f10x_dbg.c + \brief DBG driver + + \version 2014-12-26, V1.0.0, firmware for GD32F10x + \version 2017-06-20, V2.0.0, firmware for GD32F10x + \version 2018-07-31, V2.1.0, firmware for GD32F10x + \version 2020-09-30, V2.2.0, firmware for GD32F10x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "gd32f10x_dbg.h" + +/*! + \brief read DBG_ID code register + \param[in] none + \param[out] none + \retval DBG_ID code +*/ +uint32_t dbg_id_get(void) +{ + return DBG_ID; +} + +/*! + \brief enable low power behavior when the mcu is in debug mode + \param[in] dbg_low_power: + one or more parameters can be selected which are shown as below: + \arg DBG_LOW_POWER_SLEEP: keep debugger connection during sleep mode + \arg DBG_LOW_POWER_DEEPSLEEP: keep debugger connection during deepsleep mode + \arg DBG_LOW_POWER_STANDBY: keep debugger connection during standby mode + \param[out] none + \retval none +*/ +void dbg_low_power_enable(uint32_t dbg_low_power) +{ + DBG_CTL |= dbg_low_power; +} + +/*! + \brief disable low power behavior when the mcu is in debug mode + \param[in] dbg_low_power: + one or more parameters can be selected which are shown as below: + \arg DBG_LOW_POWER_SLEEP: donot keep debugger connection during sleep mode + \arg DBG_LOW_POWER_DEEPSLEEP: donot keep debugger connection during deepsleep mode + \arg DBG_LOW_POWER_STANDBY: donot keep debugger connection during standby mode + \param[out] none + \retval none +*/ +void dbg_low_power_disable(uint32_t dbg_low_power) +{ + DBG_CTL &= ~dbg_low_power; +} + +/*! + \brief enable peripheral behavior when the mcu is in debug mode + \param[in] dbg_periph: refer to dbg_periph_enum + one or more parameters can be selected which are shown as below: + \arg DBG_FWDGT_HOLD : debug FWDGT kept when core is halted + \arg DBG_WWDGT_HOLD : debug WWDGT kept when core is halted + \arg DBG_CANx_HOLD (x=0,1,CAN1 is only available for CL series): hold CANx counter when core is halted + \arg DBG_I2Cx_HOLD (x=0,1): hold I2Cx smbus when core is halted + \arg DBG_TIMERx_HOLD (x=0,1,2,3,4,5,6,7,8,9,10,11,12,13,TIMER8..13 are not available for HD series): hold TIMERx counter when core is halted + \param[out] none + \retval none +*/ +void dbg_periph_enable(dbg_periph_enum dbg_periph) +{ + DBG_CTL |= (uint32_t)dbg_periph; +} + +/*! + \brief disable peripheral behavior when the mcu is in debug mode + \param[in] dbg_periph: refer to dbg_periph_enum + one or more parameters can be selected which are shown as below: + \arg DBG_FWDGT_HOLD : debug FWDGT kept when core is halted + \arg DBG_WWDGT_HOLD : debug WWDGT kept when core is halted + \arg DBG_CANx_HOLD (x=0,1,CAN1 is only available for CL series): hold CAN0 counter when core is halted + \arg DBG_I2Cx_HOLD (x=0,1): hold I2Cx smbus when core is halted + \arg DBG_TIMERx_HOLD (x=0,1,2,3,4,5,6,7,8,9,10,11,12,13,TIMER8..13 are only available for XD and CL series): hold TIMERx counter when core is halted + \param[out] none + \retval none +*/ +void dbg_periph_disable(dbg_periph_enum dbg_periph) +{ + DBG_CTL &= ~(uint32_t)dbg_periph; +} + +/*! + \brief enable trace pin assignment + \param[in] none + \param[out] none + \retval none +*/ +void dbg_trace_pin_enable(void) +{ + DBG_CTL |= DBG_CTL_TRACE_IOEN; +} + +/*! + \brief disable trace pin assignment + \param[in] none + \param[out] none + \retval none +*/ +void dbg_trace_pin_disable(void) +{ + DBG_CTL &= ~DBG_CTL_TRACE_IOEN; +} + +/*! + \brief trace pin mode selection + \param[in] trace_mode: + only one parameter can be selected which is shown as below: + \arg TRACE_MODE_ASYNC: trace pin used for async mode + \arg TRACE_MODE_SYNC_DATASIZE_1: trace pin used for sync mode and data size is 1 + \arg TRACE_MODE_SYNC_DATASIZE_2: trace pin used for sync mode and data size is 2 + \arg TRACE_MODE_SYNC_DATASIZE_4: trace pin used for sync mode and data size is 4 + \param[out] none + \retval none +*/ +void dbg_trace_pin_mode_set(uint32_t trace_mode) +{ + DBG_CTL &= ~DBG_CTL_TRACE_MODE; + DBG_CTL |= trace_mode; +} diff --git a/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_standard_peripheral/Source/gd32f10x_dma.c b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_standard_peripheral/Source/gd32f10x_dma.c new file mode 100644 index 0000000000..8908bd734f --- /dev/null +++ b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_standard_peripheral/Source/gd32f10x_dma.c @@ -0,0 +1,737 @@ +/*! + \file gd32f10x_dma.c + \brief DMA driver + + \version 2014-12-26, V1.0.0, firmware for GD32F10x + \version 2017-06-20, V2.0.0, firmware for GD32F10x + \version 2018-07-31, V2.1.0, firmware for GD32F10x + \version 2019-10-30, V2.1.1, firmware for GD32F10x + \version 2020-09-30, V2.2.0, firmware for GD32F10x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "gd32f10x_dma.h" + +#define DMA_WRONG_HANDLE while(1){} + + /* check whether peripheral matches channels or not */ +static ErrStatus dma_periph_and_channel_check(uint32_t dma_periph, dma_channel_enum channelx); + +/*! + \brief deinitialize DMA a channel registers + \param[in] dma_periph: DMAx(x=0,1) + \arg DMAx(x=0,1) + \param[in] channelx: specify which DMA channel is deinitialized + only one parameter can be selected which is shown as below: + \arg DMA0: DMA_CHx(x=0..6), DMA1: DMA_CHx(x=0..4) + \param[out] none + \retval none +*/ +void dma_deinit(uint32_t dma_periph, dma_channel_enum channelx) +{ + if(ERROR == dma_periph_and_channel_check(dma_periph, channelx)){ + DMA_WRONG_HANDLE + } + + /* disable DMA a channel */ + DMA_CHCTL(dma_periph, channelx) &= ~DMA_CHXCTL_CHEN; + /* reset DMA channel registers */ + DMA_CHCTL(dma_periph, channelx) = DMA_CHCTL_RESET_VALUE; + DMA_CHCNT(dma_periph, channelx) = DMA_CHCNT_RESET_VALUE; + DMA_CHPADDR(dma_periph, channelx) = DMA_CHPADDR_RESET_VALUE; + DMA_CHMADDR(dma_periph, channelx) = DMA_CHMADDR_RESET_VALUE; + DMA_INTC(dma_periph) |= DMA_FLAG_ADD(DMA_CHINTF_RESET_VALUE, channelx); +} + +/*! + \brief initialize the parameters of DMA struct with the default values + \param[in] init_struct: the initialization data needed to initialize DMA channel + \param[out] none + \retval none +*/ +void dma_struct_para_init(dma_parameter_struct* init_struct) +{ + /* set the DMA struct with the default values */ + init_struct->periph_addr = 0U; + init_struct->periph_width = 0U; + init_struct->periph_inc = DMA_PERIPH_INCREASE_DISABLE; + init_struct->memory_addr = 0U; + init_struct->memory_width = 0U; + init_struct->memory_inc = DMA_MEMORY_INCREASE_DISABLE; + init_struct->number = 0U; + init_struct->direction = DMA_PERIPHERAL_TO_MEMORY; + init_struct->priority = DMA_PRIORITY_LOW; +} + +/*! + \brief initialize DMA channel + \param[in] dma_periph: DMAx(x=0,1) + \arg DMAx(x=0,1) + \param[in] channelx: specify which DMA channel is initialized + only one parameter can be selected which is shown as below: + \arg DMA0: DMA_CHx(x=0..6), DMA1: DMA_CHx(x=0..4) + \param[in] init_struct: the data needed to initialize DMA channel + periph_addr: peripheral base address + periph_width: DMA_PERIPHERAL_WIDTH_8BIT, DMA_PERIPHERAL_WIDTH_16BIT, DMA_PERIPHERAL_WIDTH_32BIT + periph_inc: DMA_PERIPH_INCREASE_ENABLE, DMA_PERIPH_INCREASE_DISABLE + memory_addr: memory base address + memory_width: DMA_MEMORY_WIDTH_8BIT, DMA_MEMORY_WIDTH_16BIT, DMA_MEMORY_WIDTH_32BIT + memory_inc: DMA_MEMORY_INCREASE_ENABLE, DMA_MEMORY_INCREASE_DISABLE + direction: DMA_PERIPHERAL_TO_MEMORY, DMA_MEMORY_TO_PERIPHERAL + number: the number of remaining data to be transferred by the DMA + priority: DMA_PRIORITY_LOW, DMA_PRIORITY_MEDIUM, DMA_PRIORITY_HIGH, DMA_PRIORITY_ULTRA_HIGH + \param[out] none + \retval none +*/ +void dma_init(uint32_t dma_periph, dma_channel_enum channelx, dma_parameter_struct *init_struct) +{ + uint32_t ctl; + + if(ERROR == dma_periph_and_channel_check(dma_periph, channelx)){ + DMA_WRONG_HANDLE + } + + /* configure peripheral base address */ + DMA_CHPADDR(dma_periph, channelx) = init_struct->periph_addr; + + /* configure memory base address */ + DMA_CHMADDR(dma_periph, channelx) = init_struct->memory_addr; + + /* configure the number of remaining data to be transferred */ + DMA_CHCNT(dma_periph, channelx) = (init_struct->number & DMA_CHANNEL_CNT_MASK); + + /* configure peripheral transfer width,memory transfer width, */ + ctl = DMA_CHCTL(dma_periph, channelx); + ctl &= ~(DMA_CHXCTL_PWIDTH | DMA_CHXCTL_MWIDTH | DMA_CHXCTL_PRIO); + ctl |= (init_struct->periph_width | init_struct->memory_width | init_struct->priority); + DMA_CHCTL(dma_periph, channelx) = ctl; + + /* configure peripheral increasing mode */ + if(DMA_PERIPH_INCREASE_ENABLE == init_struct->periph_inc){ + DMA_CHCTL(dma_periph, channelx) |= DMA_CHXCTL_PNAGA; + }else{ + DMA_CHCTL(dma_periph, channelx) &= ~DMA_CHXCTL_PNAGA; + } + + /* configure memory increasing mode */ + if(DMA_MEMORY_INCREASE_ENABLE == init_struct->memory_inc){ + DMA_CHCTL(dma_periph, channelx) |= DMA_CHXCTL_MNAGA; + }else{ + DMA_CHCTL(dma_periph, channelx) &= ~DMA_CHXCTL_MNAGA; + } + + /* configure the direction of data transfer */ + if(DMA_PERIPHERAL_TO_MEMORY == init_struct->direction){ + DMA_CHCTL(dma_periph, channelx) &= ~DMA_CHXCTL_DIR; + }else{ + DMA_CHCTL(dma_periph, channelx) |= DMA_CHXCTL_DIR; + } +} + +/*! + \brief enable DMA circulation mode + \param[in] dma_periph: DMAx(x=0,1) + \arg DMAx(x=0,1) + \param[in] channelx: specify which DMA channel + only one parameter can be selected which is shown as below: + \arg DMA0: DMA_CHx(x=0..6), DMA1: DMA_CHx(x=0..4) + \param[out] none + \retval none +*/ +void dma_circulation_enable(uint32_t dma_periph, dma_channel_enum channelx) +{ + if(ERROR == dma_periph_and_channel_check(dma_periph, channelx)){ + DMA_WRONG_HANDLE + } + + DMA_CHCTL(dma_periph, channelx) |= DMA_CHXCTL_CMEN; +} + +/*! + \brief disable DMA circulation mode + \param[in] dma_periph: DMAx(x=0,1) + \arg DMAx(x=0,1) + \param[in] channelx: specify which DMA channel + only one parameter can be selected which is shown as below: + \arg DMA0: DMA_CHx(x=0..6), DMA1: DMA_CHx(x=0..4) + \param[out] none + \retval none +*/ +void dma_circulation_disable(uint32_t dma_periph, dma_channel_enum channelx) +{ + if(ERROR == dma_periph_and_channel_check(dma_periph, channelx)){ + DMA_WRONG_HANDLE + } + + DMA_CHCTL(dma_periph, channelx) &= ~DMA_CHXCTL_CMEN; +} + +/*! + \brief enable memory to memory mode + \param[in] dma_periph: DMAx(x=0,1) + \arg DMAx(x=0,1) + \param[in] channelx: specify which DMA channel + only one parameter can be selected which is shown as below: + \arg DMA0: DMA_CHx(x=0..6), DMA1: DMA_CHx(x=0..4) + \param[out] none + \retval none +*/ +void dma_memory_to_memory_enable(uint32_t dma_periph, dma_channel_enum channelx) +{ + if(ERROR == dma_periph_and_channel_check(dma_periph, channelx)){ + DMA_WRONG_HANDLE + } + + DMA_CHCTL(dma_periph, channelx) |= DMA_CHXCTL_M2M; +} + +/*! + \brief disable memory to memory mode + \param[in] dma_periph: DMAx(x=0,1) + \arg DMAx(x=0,1) + \param[in] channelx: specify which DMA channel + only one parameter can be selected which is shown as below: + \arg DMA0: DMA_CHx(x=0..6), DMA1: DMA_CHx(x=0..4) + \param[out] none + \retval none +*/ +void dma_memory_to_memory_disable(uint32_t dma_periph, dma_channel_enum channelx) +{ + if(ERROR == dma_periph_and_channel_check(dma_periph, channelx)){ + DMA_WRONG_HANDLE + } + + DMA_CHCTL(dma_periph, channelx) &= ~DMA_CHXCTL_M2M; +} + +/*! + \brief enable DMA channel + \param[in] dma_periph: DMAx(x=0,1) + \arg DMAx(x=0,1) + \param[in] channelx: specify which DMA channel + only one parameter can be selected which is shown as below: + \arg DMA0: DMA_CHx(x=0..6), DMA1: DMA_CHx(x=0..4) + \param[out] none + \retval none +*/ +void dma_channel_enable(uint32_t dma_periph, dma_channel_enum channelx) +{ + if(ERROR == dma_periph_and_channel_check(dma_periph, channelx)){ + DMA_WRONG_HANDLE + } + + DMA_CHCTL(dma_periph, channelx) |= DMA_CHXCTL_CHEN; +} + +/*! + \brief disable DMA channel + \param[in] dma_periph: DMAx(x=0,1) + \arg DMAx(x=0,1) + \param[in] channelx: specify which DMA channel + only one parameter can be selected which is shown as below: + \arg DMA0: DMA_CHx(x=0..6), DMA1: DMA_CHx(x=0..4) + \param[out] none + \retval none +*/ +void dma_channel_disable(uint32_t dma_periph, dma_channel_enum channelx) +{ + if(ERROR == dma_periph_and_channel_check(dma_periph, channelx)){ + DMA_WRONG_HANDLE + } + + DMA_CHCTL(dma_periph, channelx) &= ~DMA_CHXCTL_CHEN; +} + +/*! + \brief set DMA peripheral base address + \param[in] dma_periph: DMAx(x=0,1) + \arg DMAx(x=0,1) + \param[in] channelx: specify which DMA channel to set peripheral base address + only one parameter can be selected which is shown as below: + \arg DMA0: DMA_CHx(x=0..6), DMA1: DMA_CHx(x=0..4) + \param[in] address: peripheral base address + \param[out] none + \retval none +*/ +void dma_periph_address_config(uint32_t dma_periph, dma_channel_enum channelx, uint32_t address) +{ + if(ERROR == dma_periph_and_channel_check(dma_periph, channelx)){ + DMA_WRONG_HANDLE + } + + DMA_CHPADDR(dma_periph, channelx) = address; +} + +/*! + \brief set DMA memory base address + \param[in] dma_periph: DMAx(x=0,1) + \arg DMAx(x=0,1) + \param[in] channelx: specify which DMA channel to set memory base address + only one parameter can be selected which is shown as below: + \arg DMA0: DMA_CHx(x=0..6), DMA1: DMA_CHx(x=0..4) + \param[in] address: memory base address + \param[out] none + \retval none +*/ +void dma_memory_address_config(uint32_t dma_periph, dma_channel_enum channelx, uint32_t address) +{ + if(ERROR == dma_periph_and_channel_check(dma_periph, channelx)){ + DMA_WRONG_HANDLE + } + + DMA_CHMADDR(dma_periph, channelx) = address; +} + +/*! + \brief set the number of remaining data to be transferred by the DMA + \param[in] dma_periph: DMAx(x=0,1) + \arg DMAx(x=0,1) + \param[in] channelx: specify which DMA channel to set number + only one parameter can be selected which is shown as below: + \arg DMA0: DMA_CHx(x=0..6), DMA1: DMA_CHx(x=0..4) + \param[in] number: the number of remaining data to be transferred by the DMA + \arg 0x0000-0xFFFF + \param[out] none + \retval none +*/ +void dma_transfer_number_config(uint32_t dma_periph, dma_channel_enum channelx, uint32_t number) +{ + if(ERROR == dma_periph_and_channel_check(dma_periph, channelx)){ + DMA_WRONG_HANDLE + } + + DMA_CHCNT(dma_periph, channelx) = (number & DMA_CHANNEL_CNT_MASK); +} + +/*! + \brief get the number of remaining data to be transferred by the DMA + \param[in] dma_periph: DMAx(x=0,1) + \arg DMAx(x=0,1) + \param[in] channelx: specify which DMA channel to set number + only one parameter can be selected which is shown as below: + \arg DMA0: DMA_CHx(x=0..6), DMA1: DMA_CHx(x=0..4) + \param[out] none + \retval uint32_t: the number of remaining data to be transferred by the DMA +*/ +uint32_t dma_transfer_number_get(uint32_t dma_periph, dma_channel_enum channelx) +{ + if(ERROR == dma_periph_and_channel_check(dma_periph, channelx)){ + DMA_WRONG_HANDLE + } + + return (uint32_t)DMA_CHCNT(dma_periph, channelx); +} + +/*! + \brief configure priority level of DMA channel + \param[in] dma_periph: DMAx(x=0,1) + \arg DMAx(x=0,1) + \param[in] channelx: specify which DMA channel + only one parameter can be selected which is shown as below: + \arg DMA0: DMA_CHx(x=0..6), DMA1: DMA_CHx(x=0..4) + \param[in] priority: priority Level of this channel + only one parameter can be selected which is shown as below: + \arg DMA_PRIORITY_LOW: low priority + \arg DMA_PRIORITY_MEDIUM: medium priority + \arg DMA_PRIORITY_HIGH: high priority + \arg DMA_PRIORITY_ULTRA_HIGH: ultra high priority + \param[out] none + \retval none +*/ +void dma_priority_config(uint32_t dma_periph, dma_channel_enum channelx, uint32_t priority) +{ + uint32_t ctl; + + if(ERROR == dma_periph_and_channel_check(dma_periph, channelx)){ + DMA_WRONG_HANDLE + } + + /* acquire DMA_CHxCTL register */ + ctl = DMA_CHCTL(dma_periph, channelx); + /* assign regiser */ + ctl &= ~DMA_CHXCTL_PRIO; + ctl |= priority; + DMA_CHCTL(dma_periph, channelx) = ctl; +} + +/*! + \brief configure transfer data size of memory + \param[in] dma_periph: DMAx(x=0,1) + \arg DMAx(x=0,1) + \param[in] channelx: specify which DMA channel + only one parameter can be selected which is shown as below: + \arg DMA0: DMA_CHx(x=0..6), DMA1: DMA_CHx(x=0..4) + \param[in] mwidth: transfer data width of memory + only one parameter can be selected which is shown as below: + \arg DMA_MEMORY_WIDTH_8BIT: transfer data width of memory is 8-bit + \arg DMA_MEMORY_WIDTH_16BIT: transfer data width of memory is 16-bit + \arg DMA_MEMORY_WIDTH_32BIT: transfer data width of memory is 32-bit + \param[out] none + \retval none +*/ +void dma_memory_width_config(uint32_t dma_periph, dma_channel_enum channelx, uint32_t mwidth) +{ + uint32_t ctl; + + if(ERROR == dma_periph_and_channel_check(dma_periph, channelx)){ + DMA_WRONG_HANDLE + } + + /* acquire DMA_CHxCTL register */ + ctl = DMA_CHCTL(dma_periph, channelx); + /* assign regiser */ + ctl &= ~DMA_CHXCTL_MWIDTH; + ctl |= mwidth; + DMA_CHCTL(dma_periph, channelx) = ctl; +} + +/*! + \brief configure transfer data size of peripheral + \param[in] dma_periph: DMAx(x=0,1) + \arg DMAx(x=0,1) + \param[in] channelx: specify which DMA channel + only one parameter can be selected which is shown as below: + \arg DMA0: DMA_CHx(x=0..6), DMA1: DMA_CHx(x=0..4) + \param[in] pwidth: transfer data width of peripheral + only one parameter can be selected which is shown as below: + \arg DMA_PERIPHERAL_WIDTH_8BIT: transfer data width of peripheral is 8-bit + \arg DMA_PERIPHERAL_WIDTH_16BIT: transfer data width of peripheral is 16-bit + \arg DMA_PERIPHERAL_WIDTH_32BIT: transfer data width of peripheral is 32-bit + \param[out] none + \retval none +*/ +void dma_periph_width_config(uint32_t dma_periph, dma_channel_enum channelx, uint32_t pwidth) +{ + uint32_t ctl; + + if(ERROR == dma_periph_and_channel_check(dma_periph, channelx)){ + DMA_WRONG_HANDLE + } + + /* acquire DMA_CHxCTL register */ + ctl = DMA_CHCTL(dma_periph, channelx); + /* assign regiser */ + ctl &= ~DMA_CHXCTL_PWIDTH; + ctl |= pwidth; + DMA_CHCTL(dma_periph, channelx) = ctl; +} + +/*! + \brief enable next address increasement algorithm of memory + \param[in] dma_periph: DMAx(x=0,1) + \arg DMAx(x=0,1) + \param[in] channelx: specify which DMA channel + only one parameter can be selected which is shown as below: + \arg DMA0: DMA_CHx(x=0..6), DMA1: DMA_CHx(x=0..4) + \param[out] none + \retval none +*/ +void dma_memory_increase_enable(uint32_t dma_periph, dma_channel_enum channelx) +{ + if(ERROR == dma_periph_and_channel_check(dma_periph, channelx)){ + DMA_WRONG_HANDLE + } + + DMA_CHCTL(dma_periph, channelx) |= DMA_CHXCTL_MNAGA; +} + +/*! + \brief disable next address increasement algorithm of memory + \param[in] dma_periph: DMAx(x=0,1) + \arg DMAx(x=0,1) + \param[in] channelx: specify which DMA channel + only one parameter can be selected which is shown as below: + \arg DMA0: DMA_CHx(x=0..6), DMA1: DMA_CHx(x=0..4) + \param[out] none + \retval none +*/ +void dma_memory_increase_disable(uint32_t dma_periph, dma_channel_enum channelx) +{ + if(ERROR == dma_periph_and_channel_check(dma_periph, channelx)){ + DMA_WRONG_HANDLE + } + + DMA_CHCTL(dma_periph, channelx) &= ~DMA_CHXCTL_MNAGA; +} + +/*! + \brief enable next address increasement algorithm of peripheral + \param[in] dma_periph: DMAx(x=0,1) + \arg DMAx(x=0,1) + \param[in] channelx: specify which DMA channel + only one parameter can be selected which is shown as below: + \arg DMA0: DMA_CHx(x=0..6), DMA1: DMA_CHx(x=0..4) + \param[out] none + \retval none +*/ +void dma_periph_increase_enable(uint32_t dma_periph, dma_channel_enum channelx) +{ + if(ERROR == dma_periph_and_channel_check(dma_periph, channelx)){ + DMA_WRONG_HANDLE + } + + DMA_CHCTL(dma_periph, channelx) |= DMA_CHXCTL_PNAGA; +} + +/*! + \brief disable next address increasement algorithm of peripheral + \param[in] dma_periph: DMAx(x=0,1) + \arg DMAx(x=0,1) + \param[in] channelx: specify which DMA channel + only one parameter can be selected which is shown as below: + \arg DMA0: DMA_CHx(x=0..6), DMA1: DMA_CHx(x=0..4) + \param[out] none + \retval none +*/ +void dma_periph_increase_disable(uint32_t dma_periph, dma_channel_enum channelx) +{ + if(ERROR == dma_periph_and_channel_check(dma_periph, channelx)){ + DMA_WRONG_HANDLE + } + + DMA_CHCTL(dma_periph, channelx) &= ~DMA_CHXCTL_PNAGA; +} + +/*! + \brief configure the direction of data transfer on the channel + \param[in] dma_periph: DMAx(x=0,1) + \arg DMAx(x=0,1) + \param[in] channelx: specify which DMA channel + only one parameter can be selected which is shown as below: + \arg DMA0: DMA_CHx(x=0..6), DMA1: DMA_CHx(x=0..4) + \param[in] direction: specify the direction of data transfer + only one parameter can be selected which is shown as below: + \arg DMA_PERIPHERAL_TO_MEMORY: read from peripheral and write to memory + \arg DMA_MEMORY_TO_PERIPHERAL: read from memory and write to peripheral + \param[out] none + \retval none +*/ +void dma_transfer_direction_config(uint32_t dma_periph, dma_channel_enum channelx, uint8_t direction) +{ + if(ERROR == dma_periph_and_channel_check(dma_periph, channelx)){ + DMA_WRONG_HANDLE + } + + if(DMA_PERIPHERAL_TO_MEMORY == direction){ + DMA_CHCTL(dma_periph, channelx) &= ~DMA_CHXCTL_DIR; + } else { + DMA_CHCTL(dma_periph, channelx) |= DMA_CHXCTL_DIR; + } +} + +/*! + \brief check DMA flag is set or not + \param[in] dma_periph: DMAx(x=0,1) + \arg DMAx(x=0,1) + \param[in] channelx: specify which DMA channel to get flag + only one parameter can be selected which is shown as below: + \arg DMA0: DMA_CHx(x=0..6), DMA1: DMA_CHx(x=0..4) + \param[in] flag: specify get which flag + only one parameter can be selected which is shown as below: + \arg DMA_FLAG_G: global interrupt flag of channel + \arg DMA_FLAG_FTF: full transfer finish flag of channel + \arg DMA_FLAG_HTF: half transfer finish flag of channel + \arg DMA_FLAG_ERR: error flag of channel + \param[out] none + \retval FlagStatus: SET or RESET +*/ +FlagStatus dma_flag_get(uint32_t dma_periph, dma_channel_enum channelx, uint32_t flag) +{ + FlagStatus reval; + + /* check whether the flag is set or not */ + if(RESET != (DMA_INTF(dma_periph) & DMA_FLAG_ADD(flag, channelx))){ + reval = SET; + }else{ + reval = RESET; + } + + return reval; +} + +/*! + \brief clear the flag of a DMA channel + \param[in] dma_periph: DMAx(x=0,1) + \arg DMAx(x=0,1) + \param[in] channelx: specify which DMA channel to clear flag + only one parameter can be selected which is shown as below: + \arg DMA0: DMA_CHx(x=0..6), DMA1: DMA_CHx(x=0..4) + \param[in] flag: specify get which flag + only one parameter can be selected which is shown as below: + \arg DMA_FLAG_G: global interrupt flag of channel + \arg DMA_FLAG_FTF: full transfer finish flag of channel + \arg DMA_FLAG_HTF: half transfer finish flag of channel + \arg DMA_FLAG_ERR: error flag of channel + \param[out] none + \retval none +*/ +void dma_flag_clear(uint32_t dma_periph, dma_channel_enum channelx, uint32_t flag) +{ + DMA_INTC(dma_periph) |= DMA_FLAG_ADD(flag, channelx); +} + +/*! + \brief check DMA flag and interrupt enable bit is set or not + \param[in] dma_periph: DMAx(x=0,1) + \arg DMAx(x=0,1) + \param[in] channelx: specify which DMA channel to get flag + only one parameter can be selected which is shown as below: + \arg DMA0: DMA_CHx(x=0..6), DMA1: DMA_CHx(x=0..4) + \param[in] flag: specify get which flag + only one parameter can be selected which is shown as below: + \arg DMA_INT_FLAG_FTF: full transfer finish interrupt flag of channel + \arg DMA_INT_FLAG_HTF: half transfer finish interrupt flag of channel + \arg DMA_INT_FLAG_ERR: error interrupt flag of channel + \param[out] none + \retval FlagStatus: SET or RESET +*/ +FlagStatus dma_interrupt_flag_get(uint32_t dma_periph, dma_channel_enum channelx, uint32_t flag) +{ + uint32_t interrupt_enable = 0U, interrupt_flag = 0U; + + switch(flag){ + case DMA_INT_FLAG_FTF: + /* check whether the full transfer finish interrupt flag is set and enabled */ + interrupt_flag = DMA_INTF(dma_periph) & DMA_FLAG_ADD(flag, channelx); + interrupt_enable = DMA_CHCTL(dma_periph, channelx) & DMA_CHXCTL_FTFIE; + break; + case DMA_INT_FLAG_HTF: + /* check whether the half transfer finish interrupt flag is set and enabled */ + interrupt_flag = DMA_INTF(dma_periph) & DMA_FLAG_ADD(flag, channelx); + interrupt_enable = DMA_CHCTL(dma_periph, channelx) & DMA_CHXCTL_HTFIE; + break; + case DMA_INT_FLAG_ERR: + /* check whether the error interrupt flag is set and enabled */ + interrupt_flag = DMA_INTF(dma_periph) & DMA_FLAG_ADD(flag, channelx); + interrupt_enable = DMA_CHCTL(dma_periph, channelx) & DMA_CHXCTL_ERRIE; + break; + default: + DMA_WRONG_HANDLE + } + + /* when the interrupt flag is set and enabled, return SET */ + if(interrupt_flag && interrupt_enable){ + return SET; + }else{ + return RESET; + } +} + +/*! + \brief clear DMA a channel flag + \param[in] dma_periph: DMAx(x=0,1) + \arg DMAx(x=0,1) + \param[in] channelx: specify which DMA channel to clear flag + only one parameter can be selected which is shown as below: + \arg DMA0: DMA_CHx(x=0..6), DMA1: DMA_CHx(x=0..4) + \param[in] flag: specify get which flag + only one parameter can be selected which is shown as below: + \arg DMA_INT_FLAG_G: global interrupt flag of channel + \arg DMA_INT_FLAG_FTF: full transfer finish interrupt flag of channel + \arg DMA_INT_FLAG_HTF: half transfer finish interrupt flag of channel + \arg DMA_INT_FLAG_ERR: error interrupt flag of channel + \param[out] none + \retval none +*/ +void dma_interrupt_flag_clear(uint32_t dma_periph, dma_channel_enum channelx, uint32_t flag) +{ + DMA_INTC(dma_periph) |= DMA_FLAG_ADD(flag, channelx); +} + +/*! + \brief enable DMA interrupt + \param[in] dma_periph: DMAx(x=0,1) + \arg DMAx(x=0,1) + \param[in] channelx: specify which DMA channel + only one parameter can be selected which is shown as below: + \arg DMA0: DMA_CHx(x=0..6), DMA1: DMA_CHx(x=0..4) + \param[in] source: specify which interrupt to enbale + one or more parameters can be selected which are shown as below + \arg DMA_INT_FTF: channel full transfer finish interrupt + \arg DMA_INT_HTF: channel half transfer finish interrupt + \arg DMA_INT_ERR: channel error interrupt + \param[out] none + \retval none +*/ +void dma_interrupt_enable(uint32_t dma_periph, dma_channel_enum channelx, uint32_t source) +{ + if(ERROR == dma_periph_and_channel_check(dma_periph, channelx)){ + DMA_WRONG_HANDLE + } + + DMA_CHCTL(dma_periph, channelx) |= source; +} + +/*! + \brief disable DMA interrupt + \param[in] dma_periph: DMAx(x=0,1) + \arg DMAx(x=0,1) + \param[in] channelx: specify which DMA channel + only one parameter can be selected which is shown as below: + \arg DMA0: DMA_CHx(x=0..6), DMA1: DMA_CHx(x=0..4) + \param[in] source: specify which interrupt to disbale + one or more parameters can be selected which are shown as below + \arg DMA_INT_FTF: channel full transfer finish interrupt + \arg DMA_INT_HTF: channel half transfer finish interrupt + \arg DMA_INT_ERR: channel error interrupt + \param[out] none + \retval none +*/ +void dma_interrupt_disable(uint32_t dma_periph, dma_channel_enum channelx, uint32_t source) +{ + if(ERROR == dma_periph_and_channel_check(dma_periph, channelx)){ + DMA_WRONG_HANDLE + } + + DMA_CHCTL(dma_periph, channelx) &= ~source; +} + +/*! + \brief check whether peripheral and channels match + \param[in] dma_periph: DMAx(x=0,1) + \arg DMAx(x=0,1) + \param[in] channelx: specify which DMA channel + only one parameter can be selected which is shown as below: + \arg DMA_CHx(x=0..6) + \param[out] none + \retval ErrStatus: SUCCESS or ERROR +*/ +static ErrStatus dma_periph_and_channel_check(uint32_t dma_periph, dma_channel_enum channelx) +{ + ErrStatus val = SUCCESS; + + if(DMA1 == dma_periph){ + /* for DMA1, the channel is from DMA_CH0 to DMA_CH4 */ + if(channelx > DMA_CH4){ + val = ERROR; + } + } + + return val; +} diff --git a/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_standard_peripheral/Source/gd32f10x_enet.c b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_standard_peripheral/Source/gd32f10x_enet.c new file mode 100644 index 0000000000..13866c84f4 --- /dev/null +++ b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_standard_peripheral/Source/gd32f10x_enet.c @@ -0,0 +1,3079 @@ +/*! + \file gd32f10x_enet.c + \brief ENET driver + + \version 2014-12-26, V1.0.0, firmware for GD32F10x + \version 2017-06-20, V2.0.0, firmware for GD32F10x + \version 2018-07-31, V2.1.0, firmware for GD32F10x + \version 2020-09-30, V2.2.0, firmware for GD32F10x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "gd32f10x_enet.h" + +#ifdef GD32F10X_CL + +#if defined (__CC_ARM) /*!< ARM compiler */ +__align(4) +enet_descriptors_struct rxdesc_tab[ENET_RXBUF_NUM]; /*!< ENET RxDMA descriptor */ +__align(4) +enet_descriptors_struct txdesc_tab[ENET_TXBUF_NUM]; /*!< ENET TxDMA descriptor */ +__align(4) +uint8_t rx_buff[ENET_RXBUF_NUM][ENET_RXBUF_SIZE]; /*!< ENET receive buffer */ +__align(4) +uint8_t tx_buff[ENET_TXBUF_NUM][ENET_TXBUF_SIZE]; /*!< ENET transmit buffer */ + +#elif defined ( __ICCARM__ ) /*!< IAR compiler */ +#pragma data_alignment=4 +enet_descriptors_struct rxdesc_tab[ENET_RXBUF_NUM]; /*!< ENET RxDMA descriptor */ +#pragma data_alignment=4 +enet_descriptors_struct txdesc_tab[ENET_TXBUF_NUM]; /*!< ENET TxDMA descriptor */ +#pragma data_alignment=4 +uint8_t rx_buff[ENET_RXBUF_NUM][ENET_RXBUF_SIZE]; /*!< ENET receive buffer */ +#pragma data_alignment=4 +uint8_t tx_buff[ENET_TXBUF_NUM][ENET_TXBUF_SIZE]; /*!< ENET transmit buffer */ + +#elif defined (__GNUC__) /* GNU Compiler */ +enet_descriptors_struct rxdesc_tab[ENET_RXBUF_NUM] __attribute__ ((aligned (4))); /*!< ENET RxDMA descriptor */ +enet_descriptors_struct txdesc_tab[ENET_TXBUF_NUM] __attribute__ ((aligned (4))); /*!< ENET TxDMA descriptor */ +uint8_t rx_buff[ENET_RXBUF_NUM][ENET_RXBUF_SIZE] __attribute__ ((aligned (4))); /*!< ENET receive buffer */ +uint8_t tx_buff[ENET_TXBUF_NUM][ENET_TXBUF_SIZE] __attribute__ ((aligned (4))); /*!< ENET transmit buffer */ + +#endif /* __CC_ARM */ + +/* global transmit and receive descriptors pointers */ +enet_descriptors_struct *dma_current_txdesc; +enet_descriptors_struct *dma_current_rxdesc; + +/* structure pointer of ptp descriptor for normal mode */ +enet_descriptors_struct *dma_current_ptp_txdesc = NULL; +enet_descriptors_struct *dma_current_ptp_rxdesc = NULL; + +/* init structure parameters for ENET initialization */ +static enet_initpara_struct enet_initpara ={0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; + +static uint32_t enet_unknow_err = 0U; + +/* array of register offset for debug information get */ +static const uint16_t enet_reg_tab[] = { +0x0000, 0x0004, 0x0008, 0x000C, 0x0010, 0x0014, 0x0018, 0x1080, 0x001C, 0x0028, 0x002C, +0x0038, 0x003C, 0x0040, 0x0044, 0x0048, 0x004C, 0x0050, 0x0054, 0x0058, 0x005C, + +0x0100, 0x0104, 0x0108, 0x010C, 0x0110, 0x014C, 0x0150, 0x0168, 0x0194, 0x0198, 0x01C4, + +0x0700, 0x0704,0x0708, 0x070C, 0x0710, 0x0714, 0x0718, 0x071C, 0x0720, + +0x1000, 0x1004, 0x1008, 0x100C, 0x1010, 0x1014, 0x1018, 0x101C, 0x1020, 0x1048, 0x104C, +0x1050, 0x1054}; + + +/*! + \brief deinitialize the ENET, and reset structure parameters for ENET initialization + \param[in] none + \param[out] none + \retval none +*/ +void enet_deinit(void) +{ + rcu_periph_reset_enable(RCU_ENETRST); + rcu_periph_reset_disable(RCU_ENETRST); + enet_initpara_reset(); +} + +/*! + \brief configure the parameters which are usually less cared for initialization + note -- this function must be called before enet_init(), otherwise + configuration will be no effect + \param[in] option: different function option, which is related to several parameters, + only one parameter can be selected which is shown as below, refer to enet_option_enum + \arg FORWARD_OPTION: choose to configure the frame forward related parameters + \arg DMABUS_OPTION: choose to configure the DMA bus mode related parameters + \arg DMA_MAXBURST_OPTION: choose to configure the DMA max burst related parameters + \arg DMA_ARBITRATION_OPTION: choose to configure the DMA arbitration related parameters + \arg STORE_OPTION: choose to configure the store forward mode related parameters + \arg DMA_OPTION: choose to configure the DMA descriptor related parameters + \arg VLAN_OPTION: choose to configure vlan related parameters + \arg FLOWCTL_OPTION: choose to configure flow control related parameters + \arg HASHH_OPTION: choose to configure hash high + \arg HASHL_OPTION: choose to configure hash low + \arg FILTER_OPTION: choose to configure frame filter related parameters + \arg HALFDUPLEX_OPTION: choose to configure halfduplex mode related parameters + \arg TIMER_OPTION: choose to configure time counter related parameters + \arg INTERFRAMEGAP_OPTION: choose to configure the inter frame gap related parameters + \param[in] para: the related parameters according to the option + all the related parameters should be configured which are shown as below + FORWARD_OPTION related parameters: + - ENET_AUTO_PADCRC_DROP_ENABLE/ ENET_AUTO_PADCRC_DROP_DISABLE ; + - ENET_FORWARD_ERRFRAMES_ENABLE/ ENET_FORWARD_ERRFRAMES_DISABLE ; + - ENET_FORWARD_UNDERSZ_GOODFRAMES_ENABLE/ ENET_FORWARD_UNDERSZ_GOODFRAMES_DISABLE . + DMABUS_OPTION related parameters: + - ENET_ADDRESS_ALIGN_ENABLE/ ENET_ADDRESS_ALIGN_DISABLE ; + - ENET_FIXED_BURST_ENABLE/ ENET_FIXED_BURST_DISABLE ; + DMA_MAXBURST_OPTION related parameters: + - ENET_RXDP_1BEAT/ ENET_RXDP_2BEAT/ ENET_RXDP_4BEAT/ + ENET_RXDP_8BEAT/ ENET_RXDP_16BEAT/ ENET_RXDP_32BEAT/ + ENET_RXDP_4xPGBL_4BEAT/ ENET_RXDP_4xPGBL_8BEAT/ + ENET_RXDP_4xPGBL_16BEAT/ ENET_RXDP_4xPGBL_32BEAT/ + ENET_RXDP_4xPGBL_64BEAT/ ENET_RXDP_4xPGBL_128BEAT ; + - ENET_PGBL_1BEAT/ ENET_PGBL_2BEAT/ ENET_PGBL_4BEAT/ + ENET_PGBL_8BEAT/ ENET_PGBL_16BEAT/ ENET_PGBL_32BEAT/ + ENET_PGBL_4xPGBL_4BEAT/ ENET_PGBL_4xPGBL_8BEAT/ + ENET_PGBL_4xPGBL_16BEAT/ ENET_PGBL_4xPGBL_32BEAT/ + ENET_PGBL_4xPGBL_64BEAT/ ENET_PGBL_4xPGBL_128BEAT ; + - ENET_RXTX_DIFFERENT_PGBL/ ENET_RXTX_SAME_PGBL ; + DMA_ARBITRATION_OPTION related parameters: + - ENET_ARBITRATION_RXPRIORTX / ENET_ARBITRATION_RXTX_1_1 + / ENET_ARBITRATION_RXTX_2_1/ ENET_ARBITRATION_RXTX_3_1 + / ENET_ARBITRATION_RXTX_4_1. + STORE_OPTION related parameters: + - ENET_RX_MODE_STOREFORWARD/ ENET_RX_MODE_CUTTHROUGH ; + - ENET_TX_MODE_STOREFORWARD/ ENET_TX_MODE_CUTTHROUGH ; + - ENET_RX_THRESHOLD_64BYTES/ ENET_RX_THRESHOLD_32BYTES/ + ENET_RX_THRESHOLD_96BYTES/ ENET_RX_THRESHOLD_128BYTES ; + - ENET_TX_THRESHOLD_64BYTES/ ENET_TX_THRESHOLD_128BYTES/ + ENET_TX_THRESHOLD_192BYTES/ ENET_TX_THRESHOLD_256BYTES/ + ENET_TX_THRESHOLD_40BYTES/ ENET_TX_THRESHOLD_32BYTES/ + ENET_TX_THRESHOLD_24BYTES/ ENET_TX_THRESHOLD_16BYTES . + DMA_OPTION related parameters: + - ENET_FLUSH_RXFRAME_ENABLE/ ENET_FLUSH_RXFRAME_DISABLE ; + - ENET_SECONDFRAME_OPT_ENABLE/ ENET_SECONDFRAME_OPT_DISABLE . + VLAN_OPTION related parameters: + - ENET_VLANTAGCOMPARISON_12BIT/ ENET_VLANTAGCOMPARISON_16BIT ; + - MAC_VLT_VLTI(regval) . + FLOWCTL_OPTION related parameters: + - MAC_FCTL_PTM(regval) ; + - ENET_ZERO_QUANTA_PAUSE_ENABLE/ ENET_ZERO_QUANTA_PAUSE_DISABLE ; + - ENET_PAUSETIME_MINUS4/ ENET_PAUSETIME_MINUS28/ + ENET_PAUSETIME_MINUS144/ENET_PAUSETIME_MINUS256 ; + - ENET_MAC0_AND_UNIQUE_ADDRESS_PAUSEDETECT/ ENET_UNIQUE_PAUSEDETECT ; + - ENET_RX_FLOWCONTROL_ENABLE/ ENET_RX_FLOWCONTROL_DISABLE ; + - ENET_TX_FLOWCONTROL_ENABLE/ ENET_TX_FLOWCONTROL_DISABLE . + HASHH_OPTION related parameters: + - 0x0~0xFFFF FFFFU + HASHL_OPTION related parameters: + - 0x0~0xFFFF FFFFU + FILTER_OPTION related parameters: + - ENET_SRC_FILTER_NORMAL_ENABLE/ ENET_SRC_FILTER_INVERSE_ENABLE/ + ENET_SRC_FILTER_DISABLE ; + - ENET_DEST_FILTER_INVERSE_ENABLE/ ENET_DEST_FILTER_INVERSE_DISABLE ; + - ENET_MULTICAST_FILTER_HASH_OR_PERFECT/ ENET_MULTICAST_FILTER_HASH/ + ENET_MULTICAST_FILTER_PERFECT/ ENET_MULTICAST_FILTER_NONE ; + - ENET_UNICAST_FILTER_EITHER/ ENET_UNICAST_FILTER_HASH/ + ENET_UNICAST_FILTER_PERFECT ; + - ENET_PCFRM_PREVENT_ALL/ ENET_PCFRM_PREVENT_PAUSEFRAME/ + ENET_PCFRM_FORWARD_ALL/ ENET_PCFRM_FORWARD_FILTERED . + HALFDUPLEX_OPTION related parameters: + - ENET_CARRIERSENSE_ENABLE/ ENET_CARRIERSENSE_DISABLE ; + - ENET_RECEIVEOWN_ENABLE/ ENET_RECEIVEOWN_DISABLE ; + - ENET_RETRYTRANSMISSION_ENABLE/ ENET_RETRYTRANSMISSION_DISABLE ; + - ENET_BACKOFFLIMIT_10/ ENET_BACKOFFLIMIT_8/ + ENET_BACKOFFLIMIT_4/ ENET_BACKOFFLIMIT_1 ; + - ENET_DEFERRALCHECK_ENABLE/ ENET_DEFERRALCHECK_DISABLE . + TIMER_OPTION related parameters: + - ENET_WATCHDOG_ENABLE/ ENET_WATCHDOG_DISABLE ; + - ENET_JABBER_ENABLE/ ENET_JABBER_DISABLE ; + INTERFRAMEGAP_OPTION related parameters: + - ENET_INTERFRAMEGAP_96BIT/ ENET_INTERFRAMEGAP_88BIT/ + ENET_INTERFRAMEGAP_80BIT/ ENET_INTERFRAMEGAP_72BIT/ + ENET_INTERFRAMEGAP_64BIT/ ENET_INTERFRAMEGAP_56BIT/ + ENET_INTERFRAMEGAP_48BIT/ ENET_INTERFRAMEGAP_40BIT . + \param[out] none + \retval none +*/ +void enet_initpara_config(enet_option_enum option, uint32_t para) +{ + switch(option){ + case FORWARD_OPTION: + /* choose to configure forward_frame, and save the configuration parameters */ + enet_initpara.option_enable |= (uint32_t)FORWARD_OPTION; + enet_initpara.forward_frame = para; + break; + case DMABUS_OPTION: + /* choose to configure dmabus_mode, and save the configuration parameters */ + enet_initpara.option_enable |= (uint32_t)DMABUS_OPTION; + enet_initpara.dmabus_mode = para; + break; + case DMA_MAXBURST_OPTION: + /* choose to configure dma_maxburst, and save the configuration parameters */ + enet_initpara.option_enable |= (uint32_t)DMA_MAXBURST_OPTION; + enet_initpara.dma_maxburst = para; + break; + case DMA_ARBITRATION_OPTION: + /* choose to configure dma_arbitration, and save the configuration parameters */ + enet_initpara.option_enable |= (uint32_t)DMA_ARBITRATION_OPTION; + enet_initpara.dma_arbitration = para; + break; + case STORE_OPTION: + /* choose to configure store_forward_mode, and save the configuration parameters */ + enet_initpara.option_enable |= (uint32_t)STORE_OPTION; + enet_initpara.store_forward_mode = para; + break; + case DMA_OPTION: + /* choose to configure dma_function, and save the configuration parameters */ + enet_initpara.option_enable |= (uint32_t)DMA_OPTION; + enet_initpara.dma_function = para; + break; + case VLAN_OPTION: + /* choose to configure vlan_config, and save the configuration parameters */ + enet_initpara.option_enable |= (uint32_t)VLAN_OPTION; + enet_initpara.vlan_config = para; + break; + case FLOWCTL_OPTION: + /* choose to configure flow_control, and save the configuration parameters */ + enet_initpara.option_enable |= (uint32_t)FLOWCTL_OPTION; + enet_initpara.flow_control = para; + break; + case HASHH_OPTION: + /* choose to configure hashtable_high, and save the configuration parameters */ + enet_initpara.option_enable |= (uint32_t)HASHH_OPTION; + enet_initpara.hashtable_high = para; + break; + case HASHL_OPTION: + /* choose to configure hashtable_low, and save the configuration parameters */ + enet_initpara.option_enable |= (uint32_t)HASHL_OPTION; + enet_initpara.hashtable_low = para; + break; + case FILTER_OPTION: + /* choose to configure framesfilter_mode, and save the configuration parameters */ + enet_initpara.option_enable |= (uint32_t)FILTER_OPTION; + enet_initpara.framesfilter_mode = para; + break; + case HALFDUPLEX_OPTION: + /* choose to configure halfduplex_param, and save the configuration parameters */ + enet_initpara.option_enable |= (uint32_t)HALFDUPLEX_OPTION; + enet_initpara.halfduplex_param = para; + break; + case TIMER_OPTION: + /* choose to configure timer_config, and save the configuration parameters */ + enet_initpara.option_enable |= (uint32_t)TIMER_OPTION; + enet_initpara.timer_config = para; + break; + case INTERFRAMEGAP_OPTION: + /* choose to configure interframegap, and save the configuration parameters */ + enet_initpara.option_enable |= (uint32_t)INTERFRAMEGAP_OPTION; + enet_initpara.interframegap = para; + break; + default: + break; + } +} + +/*! + \brief initialize ENET peripheral with generally concerned parameters and the less cared + parameters + \param[in] mediamode: PHY mode and mac loopback configurations, only one parameter can be selected + which is shown as below, refer to enet_mediamode_enum + \arg ENET_AUTO_NEGOTIATION: PHY auto negotiation + \arg ENET_100M_FULLDUPLEX: 100Mbit/s, full-duplex + \arg ENET_100M_HALFDUPLEX: 100Mbit/s, half-duplex + \arg ENET_10M_FULLDUPLEX: 10Mbit/s, full-duplex + \arg ENET_10M_HALFDUPLEX: 10Mbit/s, half-duplex + \arg ENET_LOOPBACKMODE: MAC in loopback mode at the MII + \param[in] checksum: IP frame checksum offload function, only one parameter can be selected + which is shown as below, refer to enet_mediamode_enum + \arg ENET_NO_AUTOCHECKSUM: disable IP frame checksum function + \arg ENET_AUTOCHECKSUM_DROP_FAILFRAMES: enable IP frame checksum function + \arg ENET_AUTOCHECKSUM_ACCEPT_FAILFRAMES: enable IP frame checksum function, and the received frame + with only payload error but no other errors will not be dropped + \param[in] recept: frame filter function, only one parameter can be selected + which is shown as below, refer to enet_frmrecept_enum + \arg ENET_PROMISCUOUS_MODE: promiscuous mode enabled + \arg ENET_RECEIVEALL: all received frame are forwarded to application + \arg ENET_BROADCAST_FRAMES_PASS: the address filters pass all received broadcast frames + \arg ENET_BROADCAST_FRAMES_DROP: the address filters filter all incoming broadcast frames + \param[out] none + \retval ErrStatus: ERROR or SUCCESS +*/ +ErrStatus enet_init(enet_mediamode_enum mediamode, enet_chksumconf_enum checksum, enet_frmrecept_enum recept) +{ + uint32_t reg_value=0U, reg_temp = 0U, temp = 0U; + uint32_t media_temp = 0U; + uint32_t timeout = 0U; + uint16_t phy_value = 0U; + ErrStatus phy_state= ERROR, enet_state = ERROR; + + /* PHY interface configuration, configure SMI clock and reset PHY chip */ + if(ERROR == enet_phy_config()){ + _ENET_DELAY_(PHY_RESETDELAY); + if(ERROR == enet_phy_config()){ + return enet_state; + } + } + /* initialize ENET peripheral with generally concerned parameters */ + enet_default_init(); + + /* 1st, configure mediamode */ + media_temp = (uint32_t)mediamode; + /* if is PHY auto negotiation */ + if((uint32_t)ENET_AUTO_NEGOTIATION == media_temp){ + /* wait for PHY_LINKED_STATUS bit be set */ + do{ + enet_phy_write_read(ENET_PHY_READ, PHY_ADDRESS, PHY_REG_BSR, &phy_value); + phy_value &= PHY_LINKED_STATUS; + timeout++; + }while((RESET == phy_value) && (timeout < PHY_READ_TO)); + /* return ERROR due to timeout */ + if(PHY_READ_TO == timeout){ + return enet_state; + } + /* reset timeout counter */ + timeout = 0U; + + /* enable auto-negotiation */ + phy_value = PHY_AUTONEGOTIATION; + phy_state = enet_phy_write_read(ENET_PHY_WRITE, PHY_ADDRESS, PHY_REG_BCR, &phy_value); + if(!phy_state){ + /* return ERROR due to write timeout */ + return enet_state; + } + + /* wait for the PHY_AUTONEGO_COMPLETE bit be set */ + do{ + enet_phy_write_read(ENET_PHY_READ, PHY_ADDRESS, PHY_REG_BSR, &phy_value); + phy_value &= PHY_AUTONEGO_COMPLETE; + timeout++; + }while((RESET == phy_value) && (timeout < (uint32_t)PHY_READ_TO)); + /* return ERROR due to timeout */ + if(PHY_READ_TO == timeout){ + return enet_state; + } + /* reset timeout counter */ + timeout = 0U; + + /* read the result of the auto-negotiation */ + enet_phy_write_read(ENET_PHY_READ, PHY_ADDRESS, PHY_SR, &phy_value); + /* configure the duplex mode of MAC following the auto-negotiation result */ + if((uint16_t)RESET != (phy_value & PHY_DUPLEX_STATUS)){ + media_temp = ENET_MODE_FULLDUPLEX; + }else{ + media_temp = ENET_MODE_HALFDUPLEX; + } + /* configure the communication speed of MAC following the auto-negotiation result */ + if((uint16_t)RESET !=(phy_value & PHY_SPEED_STATUS)){ + media_temp |= ENET_SPEEDMODE_10M; + }else{ + media_temp |= ENET_SPEEDMODE_100M; + } + }else{ + phy_value = (uint16_t)((media_temp & ENET_MAC_CFG_DPM) >> 3); + phy_value |= (uint16_t)((media_temp & ENET_MAC_CFG_SPD) >> 1); + phy_state = enet_phy_write_read(ENET_PHY_WRITE, PHY_ADDRESS, PHY_REG_BCR, &phy_value); + if(!phy_state){ + /* return ERROR due to write timeout */ + return enet_state; + } + /* PHY configuration need some time */ + _ENET_DELAY_(PHY_CONFIGDELAY); + } + /* after configuring the PHY, use mediamode to configure registers */ + reg_value = ENET_MAC_CFG; + /* configure ENET_MAC_CFG register */ + reg_value &= (~(ENET_MAC_CFG_SPD |ENET_MAC_CFG_DPM |ENET_MAC_CFG_LBM)); + reg_value |= media_temp; + ENET_MAC_CFG = reg_value; + + + /* 2st, configure checksum */ + if(RESET != ((uint32_t)checksum & ENET_CHECKSUMOFFLOAD_ENABLE)){ + ENET_MAC_CFG |= ENET_CHECKSUMOFFLOAD_ENABLE; + + reg_value = ENET_DMA_CTL; + /* configure ENET_DMA_CTL register */ + reg_value &= ~ENET_DMA_CTL_DTCERFD; + reg_value |= ((uint32_t)checksum & ENET_DMA_CTL_DTCERFD); + ENET_DMA_CTL = reg_value; + } + + /* 3rd, configure recept */ + ENET_MAC_FRMF |= (uint32_t)recept; + + /* 4th, configure different function options */ + /* configure forward_frame related registers */ + if(RESET != (enet_initpara.option_enable & (uint32_t)FORWARD_OPTION)){ + reg_temp = enet_initpara.forward_frame; + + reg_value = ENET_MAC_CFG; + temp = reg_temp; + /* configure ENET_MAC_CFG register */ + reg_value &= (~ENET_MAC_CFG_APCD); + temp &= ENET_MAC_CFG_APCD; + reg_value |= temp; + ENET_MAC_CFG = reg_value; + + reg_value = ENET_DMA_CTL; + temp = reg_temp; + /* configure ENET_DMA_CTL register */ + reg_value &= (~(ENET_DMA_CTL_FERF |ENET_DMA_CTL_FUF)); + temp &= ((ENET_DMA_CTL_FERF | ENET_DMA_CTL_FUF)<<2); + reg_value |= (temp >> 2); + ENET_DMA_CTL = reg_value; + } + + /* configure dmabus_mode related registers */ + if(RESET != (enet_initpara.option_enable & (uint32_t)DMABUS_OPTION)){ + temp = enet_initpara.dmabus_mode; + + reg_value = ENET_DMA_BCTL; + /* configure ENET_DMA_BCTL register */ + reg_value &= ~(ENET_DMA_BCTL_AA | ENET_DMA_BCTL_FB \ + |ENET_DMA_BCTL_FPBL); + reg_value |= temp; + ENET_DMA_BCTL = reg_value; + } + + /* configure dma_maxburst related registers */ + if(RESET != (enet_initpara.option_enable & (uint32_t)DMA_MAXBURST_OPTION)){ + temp = enet_initpara.dma_maxburst; + + reg_value = ENET_DMA_BCTL; + /* configure ENET_DMA_BCTL register */ + reg_value &= ~(ENET_DMA_BCTL_RXDP| ENET_DMA_BCTL_PGBL | ENET_DMA_BCTL_UIP); + reg_value |= temp; + ENET_DMA_BCTL = reg_value; + } + + /* configure dma_arbitration related registers */ + if(RESET != (enet_initpara.option_enable & (uint32_t)DMA_ARBITRATION_OPTION)){ + temp = enet_initpara.dma_arbitration; + + reg_value = ENET_DMA_BCTL; + /* configure ENET_DMA_BCTL register */ + reg_value &= ~(ENET_DMA_BCTL_RTPR | ENET_DMA_BCTL_DAB); + reg_value |= temp; + ENET_DMA_BCTL = reg_value; + } + + /* configure store_forward_mode related registers */ + if(RESET != (enet_initpara.option_enable & (uint32_t)STORE_OPTION)){ + temp = enet_initpara.store_forward_mode; + + reg_value = ENET_DMA_CTL; + /* configure ENET_DMA_CTL register */ + reg_value &= ~(ENET_DMA_CTL_RSFD | ENET_DMA_CTL_TSFD| ENET_DMA_CTL_RTHC| ENET_DMA_CTL_TTHC); + reg_value |= temp; + ENET_DMA_CTL = reg_value; + } + + /* configure dma_function related registers */ + if(RESET != (enet_initpara.option_enable & (uint32_t)DMA_OPTION)){ + reg_temp = enet_initpara.dma_function; + + reg_value = ENET_DMA_CTL; + /* configure ENET_DMA_CTL register */ + reg_value &= (~(ENET_DMA_CTL_DAFRF |ENET_DMA_CTL_OSF)); + reg_value |= reg_temp; + ENET_DMA_CTL = reg_value; + } + + /* configure vlan_config related registers */ + if(RESET != (enet_initpara.option_enable & (uint32_t)VLAN_OPTION)){ + reg_temp = enet_initpara.vlan_config; + + reg_value = ENET_MAC_VLT; + /* configure ENET_MAC_VLT register */ + reg_value &= ~(ENET_MAC_VLT_VLTI | ENET_MAC_VLT_VLTC); + reg_value |= reg_temp; + ENET_MAC_VLT = reg_value; + } + + /* configure flow_control related registers */ + if(RESET != (enet_initpara.option_enable & (uint32_t)FLOWCTL_OPTION)){ + reg_temp = enet_initpara.flow_control; + + reg_value = ENET_MAC_FCTL; + temp = reg_temp; + /* configure ENET_MAC_FCTL register */ + reg_value &= ~(ENET_MAC_FCTL_PTM |ENET_MAC_FCTL_DZQP |ENET_MAC_FCTL_PLTS \ + | ENET_MAC_FCTL_UPFDT |ENET_MAC_FCTL_RFCEN |ENET_MAC_FCTL_TFCEN); + temp &= (ENET_MAC_FCTL_PTM |ENET_MAC_FCTL_DZQP |ENET_MAC_FCTL_PLTS \ + | ENET_MAC_FCTL_UPFDT |ENET_MAC_FCTL_RFCEN |ENET_MAC_FCTL_TFCEN); + reg_value |= temp; + ENET_MAC_FCTL = reg_value; + + reg_value = ENET_MAC_FCTH; + temp = reg_temp; + /* configure ENET_MAC_FCTH register */ + reg_value &= ~(ENET_MAC_FCTH_RFA |ENET_MAC_FCTH_RFD); + temp &= ((ENET_MAC_FCTH_RFA | ENET_MAC_FCTH_RFD )<<8); + reg_value |= (temp >> 8); + ENET_MAC_FCTH = reg_value; + } + + /* configure hashtable_high related registers */ + if(RESET != (enet_initpara.option_enable & (uint32_t)HASHH_OPTION)){ + ENET_MAC_HLH = enet_initpara.hashtable_high; + } + + /* configure hashtable_low related registers */ + if(RESET != (enet_initpara.option_enable & (uint32_t)HASHL_OPTION)){ + ENET_MAC_HLL = enet_initpara.hashtable_low; + } + + /* configure framesfilter_mode related registers */ + if(RESET != (enet_initpara.option_enable & (uint32_t)FILTER_OPTION)){ + reg_temp = enet_initpara.framesfilter_mode; + + reg_value = ENET_MAC_FRMF; + /* configure ENET_MAC_FRMF register */ + reg_value &= ~(ENET_MAC_FRMF_SAFLT | ENET_MAC_FRMF_SAIFLT | ENET_MAC_FRMF_DAIFLT \ + | ENET_MAC_FRMF_HMF | ENET_MAC_FRMF_HPFLT | ENET_MAC_FRMF_MFD \ + | ENET_MAC_FRMF_HUF | ENET_MAC_FRMF_PCFRM); + reg_value |= reg_temp; + ENET_MAC_FRMF = reg_value; + } + + /* configure halfduplex_param related registers */ + if(RESET != (enet_initpara.option_enable & (uint32_t)HALFDUPLEX_OPTION)){ + reg_temp = enet_initpara.halfduplex_param; + + reg_value = ENET_MAC_CFG; + /* configure ENET_MAC_CFG register */ + reg_value &= ~(ENET_MAC_CFG_CSD | ENET_MAC_CFG_ROD | ENET_MAC_CFG_RTD \ + | ENET_MAC_CFG_BOL | ENET_MAC_CFG_DFC); + reg_value |= reg_temp; + ENET_MAC_CFG = reg_value; + } + + /* configure timer_config related registers */ + if(RESET != (enet_initpara.option_enable & (uint32_t)TIMER_OPTION)){ + reg_temp = enet_initpara.timer_config; + + reg_value = ENET_MAC_CFG; + /* configure ENET_MAC_CFG register */ + reg_value &= ~(ENET_MAC_CFG_WDD | ENET_MAC_CFG_JBD); + reg_value |= reg_temp; + ENET_MAC_CFG = reg_value; + } + + /* configure interframegap related registers */ + if(RESET != (enet_initpara.option_enable & (uint32_t)INTERFRAMEGAP_OPTION)){ + reg_temp = enet_initpara.interframegap; + + reg_value = ENET_MAC_CFG; + /* configure ENET_MAC_CFG register */ + reg_value &= ~ENET_MAC_CFG_IGBS; + reg_value |= reg_temp; + ENET_MAC_CFG = reg_value; + } + + enet_state = SUCCESS; + return enet_state; +} + +/*! + \brief reset all core internal registers located in CLK_TX and CLK_RX + \param[in] none + \param[out] none + \retval ErrStatus: SUCCESS or ERROR +*/ +ErrStatus enet_software_reset(void) +{ + uint32_t timeout = 0U; + ErrStatus enet_state = ERROR; + uint32_t dma_flag; + + /* reset all core internal registers located in CLK_TX and CLK_RX */ + ENET_DMA_BCTL |= ENET_DMA_BCTL_SWR; + + /* wait for reset operation complete */ + do{ + dma_flag = (ENET_DMA_BCTL & ENET_DMA_BCTL_SWR); + timeout++; + }while((RESET != dma_flag) && (ENET_DELAY_TO != timeout)); + + /* reset operation complete */ + if(RESET == (ENET_DMA_BCTL & ENET_DMA_BCTL_SWR)){ + enet_state = SUCCESS; + } + + return enet_state; +} + +/*! + \brief check receive frame valid and return frame size + \param[in] none + \param[out] none + \retval size of received frame: 0x0 - 0x3FFF +*/ +uint32_t enet_rxframe_size_get(void) +{ + uint32_t size = 0U; + uint32_t status; + + /* get rdes0 information of current RxDMA descriptor */ + status = dma_current_rxdesc->status; + + /* if the desciptor is owned by DMA */ + if((uint32_t)RESET != (status & ENET_RDES0_DAV)){ + return 0U; + } + + /* if has any error, or the frame uses two or more descriptors */ + if((((uint32_t)RESET) != (status & ENET_RDES0_ERRS)) || + (((uint32_t)RESET) == (status & ENET_RDES0_LDES)) || + (((uint32_t)RESET) == (status & ENET_RDES0_FDES))){ + /* drop current receive frame */ + enet_rxframe_drop(); + + return 1U; + } + + /* if is an ethernet-type frame, and IP frame payload error occurred */ + if((((uint32_t)RESET) != (status & ENET_RDES0_FRMT)) && + (((uint32_t)RESET) != (status & ENET_RDES0_PCERR))){ + /* drop current receive frame */ + enet_rxframe_drop(); + + return 1U; + } + + /* if CPU owns current descriptor, no error occured, the frame uses only one descriptor */ + if((((uint32_t)RESET) == (status & ENET_RDES0_DAV)) && + (((uint32_t)RESET) == (status & ENET_RDES0_ERRS)) && + (((uint32_t)RESET) != (status & ENET_RDES0_LDES)) && + (((uint32_t)RESET) != (status & ENET_RDES0_FDES))){ + /* get the size of the received data including CRC */ + size = GET_RDES0_FRML(status); + /* substract the CRC size */ + size = size - 4U; + }else{ + enet_unknow_err++; + enet_rxframe_drop(); + + return 1U; + } + + /* return packet size */ + return size; +} + +/*! + \brief initialize the DMA Tx/Rx descriptors's parameters in chain mode + \param[in] direction: the descriptors which users want to init, refer to enet_dmadirection_enum, + only one parameter can be selected which is shown as below + \arg ENET_DMA_TX: DMA Tx descriptors + \arg ENET_DMA_RX: DMA Rx descriptors + \param[out] none + \retval none +*/ +void enet_descriptors_chain_init(enet_dmadirection_enum direction) +{ + uint32_t num = 0U, count = 0U, maxsize = 0U; + uint32_t desc_status = 0U, desc_bufsize = 0U; + enet_descriptors_struct *desc, *desc_tab; + uint8_t *buf; + + /* if want to initialize DMA Tx descriptors */ + if (ENET_DMA_TX == direction){ + /* save a copy of the DMA Tx descriptors */ + desc_tab = txdesc_tab; + buf = &tx_buff[0][0]; + count = ENET_TXBUF_NUM; + maxsize = ENET_TXBUF_SIZE; + + /* select chain mode */ + desc_status = ENET_TDES0_TCHM; + + /* configure DMA Tx descriptor table address register */ + ENET_DMA_TDTADDR = (uint32_t)desc_tab; + dma_current_txdesc = desc_tab; + }else{ + /* if want to initialize DMA Rx descriptors */ + /* save a copy of the DMA Rx descriptors */ + desc_tab = rxdesc_tab; + buf = &rx_buff[0][0]; + count = ENET_RXBUF_NUM; + maxsize = ENET_RXBUF_SIZE; + + /* enable receiving */ + desc_status = ENET_RDES0_DAV; + /* select receive chained mode and set buffer1 size */ + desc_bufsize = ENET_RDES1_RCHM | (uint32_t)ENET_RXBUF_SIZE; + + /* configure DMA Rx descriptor table address register */ + ENET_DMA_RDTADDR = (uint32_t)desc_tab; + dma_current_rxdesc = desc_tab; + } + dma_current_ptp_rxdesc = NULL; + dma_current_ptp_txdesc = NULL; + + /* configure each descriptor */ + for(num=0U; num < count; num++){ + /* get the pointer to the next descriptor of the descriptor table */ + desc = desc_tab + num; + + /* configure descriptors */ + desc->status = desc_status; + desc->control_buffer_size = desc_bufsize; + desc->buffer1_addr = (uint32_t)(&buf[num * maxsize]); + + /* if is not the last descriptor */ + if(num < (count - 1U)){ + /* configure the next descriptor address */ + desc->buffer2_next_desc_addr = (uint32_t)(desc_tab + num + 1U); + }else{ + /* when it is the last descriptor, the next descriptor address + equals to first descriptor address in descriptor table */ + desc->buffer2_next_desc_addr = (uint32_t) desc_tab; + } + } +} + +/*! + \brief initialize the DMA Tx/Rx descriptors's parameters in ring mode + \param[in] direction: the descriptors which users want to init, refer to enet_dmadirection_enum, + only one parameter can be selected which is shown as below + \arg ENET_DMA_TX: DMA Tx descriptors + \arg ENET_DMA_RX: DMA Rx descriptors + \param[out] none + \retval none +*/ +void enet_descriptors_ring_init(enet_dmadirection_enum direction) +{ + uint32_t num = 0U, count = 0U, maxsize = 0U; + uint32_t desc_status = 0U, desc_bufsize = 0U; + enet_descriptors_struct *desc; + enet_descriptors_struct *desc_tab; + uint8_t *buf; + + /* configure descriptor skip length */ + ENET_DMA_BCTL &= ~ENET_DMA_BCTL_DPSL; + ENET_DMA_BCTL |= DMA_BCTL_DPSL(0); + + /* if want to initialize DMA Tx descriptors */ + if (ENET_DMA_TX == direction){ + /* save a copy of the DMA Tx descriptors */ + desc_tab = txdesc_tab; + buf = &tx_buff[0][0]; + count = ENET_TXBUF_NUM; + maxsize = ENET_TXBUF_SIZE; + + /* configure DMA Tx descriptor table address register */ + ENET_DMA_TDTADDR = (uint32_t)desc_tab; + dma_current_txdesc = desc_tab; + }else{ + /* if want to initialize DMA Rx descriptors */ + /* save a copy of the DMA Rx descriptors */ + desc_tab = rxdesc_tab; + buf = &rx_buff[0][0]; + count = ENET_RXBUF_NUM; + maxsize = ENET_RXBUF_SIZE; + + /* enable receiving */ + desc_status = ENET_RDES0_DAV; + /* set buffer1 size */ + desc_bufsize = ENET_RXBUF_SIZE; + + /* configure DMA Rx descriptor table address register */ + ENET_DMA_RDTADDR = (uint32_t)desc_tab; + dma_current_rxdesc = desc_tab; + } + dma_current_ptp_rxdesc = NULL; + dma_current_ptp_txdesc = NULL; + + /* configure each descriptor */ + for(num=0U; num < count; num++){ + /* get the pointer to the next descriptor of the descriptor table */ + desc = desc_tab + num; + + /* configure descriptors */ + desc->status = desc_status; + desc->control_buffer_size = desc_bufsize; + desc->buffer1_addr = (uint32_t)(&buf[num * maxsize]); + + /* when it is the last descriptor */ + if(num == (count - 1U)){ + if (ENET_DMA_TX == direction){ + /* configure transmit end of ring mode */ + desc->status |= ENET_TDES0_TERM; + }else{ + /* configure receive end of ring mode */ + desc->control_buffer_size |= ENET_RDES1_RERM; + } + } + } +} + +/*! + \brief handle current received frame data to application buffer + \param[in] bufsize: the size of buffer which is the parameter in function + \param[out] buffer: pointer to the received frame data + note -- if the input is NULL, user should copy data in application by himself + \retval ErrStatus: SUCCESS or ERROR +*/ +ErrStatus enet_frame_receive(uint8_t *buffer, uint32_t bufsize) +{ + uint32_t offset = 0U, size = 0U; + + /* the descriptor is busy due to own by the DMA */ + if((uint32_t)RESET != (dma_current_rxdesc->status & ENET_RDES0_DAV)){ + return ERROR; + } + + + /* if buffer pointer is null, indicates that users has copied data in application */ + if(NULL != buffer){ + /* if no error occurs, and the frame uses only one descriptor */ + if((((uint32_t)RESET) == (dma_current_rxdesc->status & ENET_RDES0_ERRS)) && + (((uint32_t)RESET) != (dma_current_rxdesc->status & ENET_RDES0_LDES)) && + (((uint32_t)RESET) != (dma_current_rxdesc->status & ENET_RDES0_FDES))){ + /* get the frame length except CRC */ + size = GET_RDES0_FRML(dma_current_rxdesc->status); + size = size - 4U; + + /* to avoid situation that the frame size exceeds the buffer length */ + if(size > bufsize){ + return ERROR; + } + + /* copy data from Rx buffer to application buffer */ + for(offset = 0U; offsetbuffer1_addr) + offset)); + } + + }else{ + /* return ERROR */ + return ERROR; + } + } + /* enable reception, descriptor is owned by DMA */ + dma_current_rxdesc->status = ENET_RDES0_DAV; + + /* check Rx buffer unavailable flag status */ + if ((uint32_t)RESET != (ENET_DMA_STAT & ENET_DMA_STAT_RBU)){ + /* clear RBU flag */ + ENET_DMA_STAT = ENET_DMA_STAT_RBU; + /* resume DMA reception by writing to the RPEN register*/ + ENET_DMA_RPEN = 0U; + } + + /* update the current RxDMA descriptor pointer to the next decriptor in RxDMA decriptor table */ + /* chained mode */ + if((uint32_t)RESET != (dma_current_rxdesc->control_buffer_size & ENET_RDES1_RCHM)){ + dma_current_rxdesc = (enet_descriptors_struct*) (dma_current_rxdesc->buffer2_next_desc_addr); + }else{ + /* ring mode */ + if((uint32_t)RESET != (dma_current_rxdesc->control_buffer_size & ENET_RDES1_RERM)){ + /* if is the last descriptor in table, the next descriptor is the table header */ + dma_current_rxdesc = (enet_descriptors_struct*) (ENET_DMA_RDTADDR); + }else{ + /* the next descriptor is the current address, add the descriptor size, and descriptor skip length */ + dma_current_rxdesc = (enet_descriptors_struct*) (uint32_t)((uint32_t)dma_current_rxdesc + ETH_DMARXDESC_SIZE + (GET_DMA_BCTL_DPSL(ENET_DMA_BCTL))); + } + } + + return SUCCESS; +} + +/*! + \brief handle application buffer data to transmit it + \param[in] buffer: pointer to the frame data to be transmitted, + note -- if the input is NULL, user should handle the data in application by himself + \param[in] length: the length of frame data to be transmitted + \param[out] none + \retval ErrStatus: SUCCESS or ERROR +*/ +ErrStatus enet_frame_transmit(uint8_t *buffer, uint32_t length) +{ + uint32_t offset = 0U; + uint32_t dma_tbu_flag, dma_tu_flag; + + /* the descriptor is busy due to own by the DMA */ + if((uint32_t)RESET != (dma_current_txdesc->status & ENET_TDES0_DAV)){ + return ERROR; + } + + /* only frame length no more than ENET_MAX_FRAME_SIZE is allowed */ + if(length > ENET_MAX_FRAME_SIZE){ + return ERROR; + } + + /* if buffer pointer is null, indicates that users has handled data in application */ + if(NULL != buffer){ + /* copy frame data from application buffer to Tx buffer */ + for(offset = 0U; offset < length; offset++){ + (*(__IO uint8_t *) (uint32_t)((dma_current_txdesc->buffer1_addr) + offset)) = (*(buffer + offset)); + } + } + + /* set the frame length */ + dma_current_txdesc->control_buffer_size = length; + /* set the segment of frame, frame is transmitted in one descriptor */ + dma_current_txdesc->status |= ENET_TDES0_LSG | ENET_TDES0_FSG; + /* enable the DMA transmission */ + dma_current_txdesc->status |= ENET_TDES0_DAV; + + /* check Tx buffer unavailable flag status */ + dma_tbu_flag = (ENET_DMA_STAT & ENET_DMA_STAT_TBU); + dma_tu_flag = (ENET_DMA_STAT & ENET_DMA_STAT_TU); + + if ((RESET != dma_tbu_flag) || (RESET != dma_tu_flag)){ + /* clear TBU and TU flag */ + ENET_DMA_STAT = (dma_tbu_flag | dma_tu_flag); + /* resume DMA transmission by writing to the TPEN register*/ + ENET_DMA_TPEN = 0U; + } + + /* update the current TxDMA descriptor pointer to the next decriptor in TxDMA decriptor table*/ + /* chained mode */ + if((uint32_t)RESET != (dma_current_txdesc->status & ENET_TDES0_TCHM)){ + dma_current_txdesc = (enet_descriptors_struct*) (dma_current_txdesc->buffer2_next_desc_addr); + }else{ + /* ring mode */ + if((uint32_t)RESET != (dma_current_txdesc->status & ENET_TDES0_TERM)){ + /* if is the last descriptor in table, the next descriptor is the table header */ + dma_current_txdesc = (enet_descriptors_struct*) (ENET_DMA_TDTADDR); + }else{ + /* the next descriptor is the current address, add the descriptor size, and descriptor skip length */ + dma_current_txdesc = (enet_descriptors_struct*) (uint32_t)((uint32_t)dma_current_txdesc + ETH_DMATXDESC_SIZE + (GET_DMA_BCTL_DPSL(ENET_DMA_BCTL))); + } + } + + return SUCCESS; +} + +/*! + \brief configure the transmit IP frame checksum offload calculation and insertion + \param[in] desc: the descriptor pointer which users want to configure + \param[in] checksum: IP frame checksum configuration + only one parameter can be selected which is shown as below + \arg ENET_CHECKSUM_DISABLE: checksum insertion disabled + \arg ENET_CHECKSUM_IPV4HEADER: only IP header checksum calculation and insertion are enabled + \arg ENET_CHECKSUM_TCPUDPICMP_SEGMENT: TCP/UDP/ICMP checksum insertion calculated but pseudo-header + \arg ENET_CHECKSUM_TCPUDPICMP_FULL: TCP/UDP/ICMP checksum insertion fully calculated + \param[out] none + \retval none +*/ +void enet_transmit_checksum_config(enet_descriptors_struct *desc, uint32_t checksum) +{ + desc->status &= ~ENET_TDES0_CM; + desc->status |= checksum; +} + +/*! + \brief ENET Tx and Rx function enable (include MAC and DMA module) + \param[in] none + \param[out] none + \retval none +*/ +void enet_enable(void) +{ + enet_tx_enable(); + enet_rx_enable(); +} + +/*! + \brief ENET Tx and Rx function disable (include MAC and DMA module) + \param[in] none + \param[out] none + \retval none +*/ +void enet_disable(void) +{ + enet_tx_disable(); + enet_rx_disable(); +} + +/*! + \brief configure MAC address + \param[in] mac_addr: select which MAC address will be set, + only one parameter can be selected which is shown as below + \arg ENET_MAC_ADDRESS0: set MAC address 0 filter + \arg ENET_MAC_ADDRESS1: set MAC address 1 filter + \arg ENET_MAC_ADDRESS2: set MAC address 2 filter + \arg ENET_MAC_ADDRESS3: set MAC address 3 filter + \param[in] paddr: the buffer pointer which stores the MAC address + (little-ending store, such as MAC address is aa:bb:cc:dd:ee:22, the buffer is {22, ee, dd, cc, bb, aa}) + \param[out] none + \retval none +*/ +void enet_mac_address_set(enet_macaddress_enum mac_addr, uint8_t paddr[]) +{ + REG32(ENET_ADDRH_BASE + (uint32_t)mac_addr) = ENET_SET_MACADDRH(paddr); + REG32(ENET_ADDRL_BASE + (uint32_t)mac_addr) = ENET_SET_MACADDRL(paddr); +} + +/*! + \brief get MAC address + \param[in] mac_addr: select which MAC address will be get, + only one parameter can be selected which is shown as below + \arg ENET_MAC_ADDRESS0: get MAC address 0 filter + \arg ENET_MAC_ADDRESS1: get MAC address 1 filter + \arg ENET_MAC_ADDRESS2: get MAC address 2 filter + \arg ENET_MAC_ADDRESS3: get MAC address 3 filter + \param[out] paddr: the buffer pointer which is stored the MAC address + (little-ending store, such as mac address is aa:bb:cc:dd:ee:22, the buffer is {22, ee, dd, cc, bb, aa}) + \retval none +*/ +void enet_mac_address_get(enet_macaddress_enum mac_addr, uint8_t paddr[]) +{ + paddr[0] = ENET_GET_MACADDR(mac_addr, 0U); + paddr[1] = ENET_GET_MACADDR(mac_addr, 1U); + paddr[2] = ENET_GET_MACADDR(mac_addr, 2U); + paddr[3] = ENET_GET_MACADDR(mac_addr, 3U); + paddr[4] = ENET_GET_MACADDR(mac_addr, 4U); + paddr[5] = ENET_GET_MACADDR(mac_addr, 5U); +} + +/*! + \brief get the ENET MAC/MSC/PTP/DMA status flag + \param[in] enet_flag: ENET status flag, refer to enet_flag_enum, + only one parameter can be selected which is shown as below + \arg ENET_MAC_FLAG_MPKR: magic packet received flag + \arg ENET_MAC_FLAG_WUFR: wakeup frame received flag + \arg ENET_MAC_FLAG_FLOWCONTROL: flow control status flag + \arg ENET_MAC_FLAG_WUM: WUM status flag + \arg ENET_MAC_FLAG_MSC: MSC status flag + \arg ENET_MAC_FLAG_MSCR: MSC receive status flag + \arg ENET_MAC_FLAG_MSCT: MSC transmit status flag + \arg ENET_MAC_FLAG_TMST: time stamp trigger status flag + \arg ENET_PTP_FLAG_TSSCO: timestamp second counter overflow flag + \arg ENET_PTP_FLAG_TTM: target time match flag + \arg ENET_MSC_FLAG_RFCE: received frames CRC error flag + \arg ENET_MSC_FLAG_RFAE: received frames alignment error flag + \arg ENET_MSC_FLAG_RGUF: received good unicast frames flag + \arg ENET_MSC_FLAG_TGFSC: transmitted good frames single collision flag + \arg ENET_MSC_FLAG_TGFMSC: transmitted good frames more single collision flag + \arg ENET_MSC_FLAG_TGF: transmitted good frames flag + \arg ENET_DMA_FLAG_TS: transmit status flag + \arg ENET_DMA_FLAG_TPS: transmit process stopped status flag + \arg ENET_DMA_FLAG_TBU: transmit buffer unavailable status flag + \arg ENET_DMA_FLAG_TJT: transmit jabber timeout status flag + \arg ENET_DMA_FLAG_RO: receive overflow status flag + \arg ENET_DMA_FLAG_TU: transmit underflow status flag + \arg ENET_DMA_FLAG_RS: receive status flag + \arg ENET_DMA_FLAG_RBU: receive buffer unavailable status flag + \arg ENET_DMA_FLAG_RPS: receive process stopped status flag + \arg ENET_DMA_FLAG_RWT: receive watchdog timeout status flag + \arg ENET_DMA_FLAG_ET: early transmit status flag + \arg ENET_DMA_FLAG_FBE: fatal bus error status flag + \arg ENET_DMA_FLAG_ER: early receive status flag + \arg ENET_DMA_FLAG_AI: abnormal interrupt summary flag + \arg ENET_DMA_FLAG_NI: normal interrupt summary flag + \arg ENET_DMA_FLAG_EB_DMA_ERROR: DMA error flag + \arg ENET_DMA_FLAG_EB_TRANSFER_ERROR: transfer error flag + \arg ENET_DMA_FLAG_EB_ACCESS_ERROR: access error flag + \arg ENET_DMA_FLAG_MSC: MSC status flag + \arg ENET_DMA_FLAG_WUM: WUM status flag + \arg ENET_DMA_FLAG_TST: timestamp trigger status flag + \param[out] none + \retval FlagStatus: SET or RESET +*/ +FlagStatus enet_flag_get(enet_flag_enum enet_flag) +{ + if(RESET != (ENET_REG_VAL(enet_flag) & BIT(ENET_BIT_POS(enet_flag)))){ + return SET; + }else{ + return RESET; + } +} + +/*! + \brief clear the ENET DMA status flag + \param[in] enet_flag: ENET DMA flag clear, refer to enet_flag_clear_enum + only one parameter can be selected which is shown as below + \arg ENET_DMA_FLAG_TS_CLR: transmit status flag clear + \arg ENET_DMA_FLAG_TPS_CLR: transmit process stopped status flag clear + \arg ENET_DMA_FLAG_TBU_CLR: transmit buffer unavailable status flag clear + \arg ENET_DMA_FLAG_TJT_CLR: transmit jabber timeout status flag clear + \arg ENET_DMA_FLAG_RO_CLR: receive overflow status flag clear + \arg ENET_DMA_FLAG_TU_CLR: transmit underflow status flag clear + \arg ENET_DMA_FLAG_RS_CLR: receive status flag clear + \arg ENET_DMA_FLAG_RBU_CLR: receive buffer unavailable status flag clear + \arg ENET_DMA_FLAG_RPS_CLR: receive process stopped status flag clear + \arg ENET_DMA_FLAG_RWT_CLR: receive watchdog timeout status flag clear + \arg ENET_DMA_FLAG_ET_CLR: early transmit status flag clear + \arg ENET_DMA_FLAG_FBE_CLR: fatal bus error status flag clear + \arg ENET_DMA_FLAG_ER_CLR: early receive status flag clear + \arg ENET_DMA_FLAG_AI_CLR: abnormal interrupt summary flag clear + \arg ENET_DMA_FLAG_NI_CLR: normal interrupt summary flag clear + \param[out] none + \retval none +*/ +void enet_flag_clear(enet_flag_clear_enum enet_flag) +{ + /* write 1 to the corresponding bit in ENET_DMA_STAT, to clear it */ + ENET_REG_VAL(enet_flag) = BIT(ENET_BIT_POS(enet_flag)); +} + +/*! + \brief enable ENET MAC/MSC/DMA interrupt + \param[in] enet_int: ENET interrupt, + only one parameter can be selected which is shown as below + \arg ENET_MAC_INT_WUMIM: WUM interrupt mask + \arg ENET_MAC_INT_TMSTIM: timestamp trigger interrupt mask + \arg ENET_MSC_INT_RFCEIM: received frame CRC error interrupt mask + \arg ENET_MSC_INT_RFAEIM: received frames alignment error interrupt mask + \arg ENET_MSC_INT_RGUFIM: received good unicast frames interrupt mask + \arg ENET_MSC_INT_TGFSCIM: transmitted good frames single collision interrupt mask + \arg ENET_MSC_INT_TGFMSCIM: transmitted good frames more single collision interrupt mask + \arg ENET_MSC_INT_TGFIM: transmitted good frames interrupt mask + \arg ENET_DMA_INT_TIE: transmit interrupt enable + \arg ENET_DMA_INT_TPSIE: transmit process stopped interrupt enable + \arg ENET_DMA_INT_TBUIE: transmit buffer unavailable interrupt enable + \arg ENET_DMA_INT_TJTIE: transmit jabber timeout interrupt enable + \arg ENET_DMA_INT_ROIE: receive overflow interrupt enable + \arg ENET_DMA_INT_TUIE: transmit underflow interrupt enable + \arg ENET_DMA_INT_RIE: receive interrupt enable + \arg ENET_DMA_INT_RBUIE: receive buffer unavailable interrupt enable + \arg ENET_DMA_INT_RPSIE: receive process stopped interrupt enable + \arg ENET_DMA_INT_RWTIE: receive watchdog timeout interrupt enable + \arg ENET_DMA_INT_ETIE: early transmit interrupt enable + \arg ENET_DMA_INT_FBEIE: fatal bus error interrupt enable + \arg ENET_DMA_INT_ERIE: early receive interrupt enable + \arg ENET_DMA_INT_AIE: abnormal interrupt summary enable + \arg ENET_DMA_INT_NIE: normal interrupt summary enable + \param[out] none + \retval none +*/ +void enet_interrupt_enable(enet_int_enum enet_int) +{ + if(DMA_INTEN_REG_OFFSET == ((uint32_t)enet_int >> 6)){ + /* ENET_DMA_INTEN register interrupt */ + ENET_REG_VAL(enet_int) |= BIT(ENET_BIT_POS(enet_int)); + }else{ + /* other INTMSK register interrupt */ + ENET_REG_VAL(enet_int) &= ~BIT(ENET_BIT_POS(enet_int)); + } +} + +/*! + \brief disable ENET MAC/MSC/DMA interrupt + \param[in] enet_int: ENET interrupt, + only one parameter can be selected which is shown as below + \arg ENET_MAC_INT_WUMIM: WUM interrupt mask + \arg ENET_MAC_INT_TMSTIM: timestamp trigger interrupt mask + \arg ENET_MSC_INT_RFCEIM: received frame CRC error interrupt mask + \arg ENET_MSC_INT_RFAEIM: received frames alignment error interrupt mask + \arg ENET_MSC_INT_RGUFIM: received good unicast frames interrupt mask + \arg ENET_MSC_INT_TGFSCIM: transmitted good frames single collision interrupt mask + \arg ENET_MSC_INT_TGFMSCIM: transmitted good frames more single collision interrupt mask + \arg ENET_MSC_INT_TGFIM: transmitted good frames interrupt mask + \arg ENET_DMA_INT_TIE: transmit interrupt enable + \arg ENET_DMA_INT_TPSIE: transmit process stopped interrupt enable + \arg ENET_DMA_INT_TBUIE: transmit buffer unavailable interrupt enable + \arg ENET_DMA_INT_TJTIE: transmit jabber timeout interrupt enable + \arg ENET_DMA_INT_ROIE: receive overflow interrupt enable + \arg ENET_DMA_INT_TUIE: transmit underflow interrupt enable + \arg ENET_DMA_INT_RIE: receive interrupt enable + \arg ENET_DMA_INT_RBUIE: receive buffer unavailable interrupt enable + \arg ENET_DMA_INT_RPSIE: receive process stopped interrupt enable + \arg ENET_DMA_INT_RWTIE: receive watchdog timeout interrupt enable + \arg ENET_DMA_INT_ETIE: early transmit interrupt enable + \arg ENET_DMA_INT_FBEIE: fatal bus error interrupt enable + \arg ENET_DMA_INT_ERIE: early receive interrupt enable + \arg ENET_DMA_INT_AIE: abnormal interrupt summary enable + \arg ENET_DMA_INT_NIE: normal interrupt summary enable + \param[out] none + \retval none +*/ +void enet_interrupt_disable(enet_int_enum enet_int) +{ + if(DMA_INTEN_REG_OFFSET == ((uint32_t)enet_int >> 6)){ + /* ENET_DMA_INTEN register interrupt */ + ENET_REG_VAL(enet_int) &= ~BIT(ENET_BIT_POS(enet_int)); + }else{ + /* other INTMSK register interrupt */ + ENET_REG_VAL(enet_int) |= BIT(ENET_BIT_POS(enet_int)); + } +} + +/*! + \brief get ENET MAC/MSC/DMA interrupt flag + \param[in] int_flag: ENET interrupt flag, + only one parameter can be selected which is shown as below + \arg ENET_MAC_INT_FLAG_WUM: WUM status flag + \arg ENET_MAC_INT_FLAG_MSC: MSC status flag + \arg ENET_MAC_INT_FLAG_MSCR: MSC receive status flag + \arg ENET_MAC_INT_FLAG_MSCT: MSC transmit status flag + \arg ENET_MAC_INT_FLAG_TMST: time stamp trigger status flag + \arg ENET_MSC_INT_FLAG_RFCE: received frames CRC error flag + \arg ENET_MSC_INT_FLAG_RFAE: received frames alignment error flag + \arg ENET_MSC_INT_FLAG_RGUF: received good unicast frames flag + \arg ENET_MSC_INT_FLAG_TGFSC: transmitted good frames single collision flag + \arg ENET_MSC_INT_FLAG_TGFMSC: transmitted good frames more single collision flag + \arg ENET_MSC_INT_FLAG_TGF: transmitted good frames flag + \arg ENET_DMA_INT_FLAG_TS: transmit status flag + \arg ENET_DMA_INT_FLAG_TPS: transmit process stopped status flag + \arg ENET_DMA_INT_FLAG_TBU: transmit buffer unavailable status flag + \arg ENET_DMA_INT_FLAG_TJT: transmit jabber timeout status flag + \arg ENET_DMA_INT_FLAG_RO: receive overflow status flag + \arg ENET_DMA_INT_FLAG_TU: transmit underflow status flag + \arg ENET_DMA_INT_FLAG_RS: receive status flag + \arg ENET_DMA_INT_FLAG_RBU: receive buffer unavailable status flag + \arg ENET_DMA_INT_FLAG_RPS: receive process stopped status flag + \arg ENET_DMA_INT_FLAG_RWT: receive watchdog timeout status flag + \arg ENET_DMA_INT_FLAG_ET: early transmit status flag + \arg ENET_DMA_INT_FLAG_FBE: fatal bus error status flag + \arg ENET_DMA_INT_FLAG_ER: early receive status flag + \arg ENET_DMA_INT_FLAG_AI: abnormal interrupt summary flag + \arg ENET_DMA_INT_FLAG_NI: normal interrupt summary flag + \arg ENET_DMA_INT_FLAG_MSC: MSC status flag + \arg ENET_DMA_INT_FLAG_WUM: WUM status flag + \arg ENET_DMA_INT_FLAG_TST: timestamp trigger status flag + \param[out] none + \retval FlagStatus: SET or RESET +*/ +FlagStatus enet_interrupt_flag_get(enet_int_flag_enum int_flag) +{ + if(RESET != (ENET_REG_VAL(int_flag) & BIT(ENET_BIT_POS(int_flag)))){ + return SET; + }else{ + return RESET; + } +} + +/*! + \brief clear ENET DMA interrupt flag + \param[in] int_flag_clear: clear ENET interrupt flag, + only one parameter can be selected which is shown as below + \arg ENET_DMA_INT_FLAG_TS_CLR: transmit status flag + \arg ENET_DMA_INT_FLAG_TPS_CLR: transmit process stopped status flag + \arg ENET_DMA_INT_FLAG_TBU_CLR: transmit buffer unavailable status flag + \arg ENET_DMA_INT_FLAG_TJT_CLR: transmit jabber timeout status flag + \arg ENET_DMA_INT_FLAG_RO_CLR: receive overflow status flag + \arg ENET_DMA_INT_FLAG_TU_CLR: transmit underflow status flag + \arg ENET_DMA_INT_FLAG_RS_CLR: receive status flag + \arg ENET_DMA_INT_FLAG_RBU_CLR: receive buffer unavailable status flag + \arg ENET_DMA_INT_FLAG_RPS_CLR: receive process stopped status flag + \arg ENET_DMA_INT_FLAG_RWT_CLR: receive watchdog timeout status flag + \arg ENET_DMA_INT_FLAG_ET_CLR: early transmit status flag + \arg ENET_DMA_INT_FLAG_FBE_CLR: fatal bus error status flag + \arg ENET_DMA_INT_FLAG_ER_CLR: early receive status flag + \arg ENET_DMA_INT_FLAG_AI_CLR: abnormal interrupt summary flag + \arg ENET_DMA_INT_FLAG_NI_CLR: normal interrupt summary flag + \param[out] none + \retval none +*/ +void enet_interrupt_flag_clear(enet_int_flag_clear_enum int_flag_clear) +{ + /* write 1 to the corresponding bit in ENET_DMA_STAT, to clear it */ + ENET_REG_VAL(int_flag_clear) = BIT(ENET_BIT_POS(int_flag_clear)); +} + +/*! + \brief ENET Tx function enable (include MAC and DMA module) + \param[in] none + \param[out] none + \retval none +*/ +void enet_tx_enable(void) +{ + ENET_MAC_CFG |= ENET_MAC_CFG_TEN; + enet_txfifo_flush(); + ENET_DMA_CTL |= ENET_DMA_CTL_STE; +} + +/*! + \brief ENET Tx function disable (include MAC and DMA module) + \param[in] none + \param[out] none + \retval none +*/ +void enet_tx_disable(void) +{ + ENET_DMA_CTL &= ~ENET_DMA_CTL_STE; + enet_txfifo_flush(); + ENET_MAC_CFG &= ~ENET_MAC_CFG_TEN; +} + +/*! + \brief ENET Rx function enable (include MAC and DMA module) + \param[in] none + \param[out] none + \retval none +*/ +void enet_rx_enable(void) +{ + ENET_MAC_CFG |= ENET_MAC_CFG_REN; + ENET_DMA_CTL |= ENET_DMA_CTL_SRE; +} + +/*! + \brief ENET Rx function disable (include MAC and DMA module) + \param[in] none + \param[out] none + \retval none +*/ +void enet_rx_disable(void) +{ + ENET_DMA_CTL &= ~ENET_DMA_CTL_SRE; + ENET_MAC_CFG &= ~ENET_MAC_CFG_REN; +} + +/*! + \brief put registers value into the application buffer + \param[in] type: register type which will be get, refer to enet_registers_type_enum, + only one parameter can be selected which is shown as below + \arg ALL_MAC_REG: get the registers within the offset scope between ENET_MAC_CFG and ENET_MAC_FCTH + \arg ALL_MSC_REG: get the registers within the offset scope between ENET_MSC_CTL and ENET_MSC_RGUFCNT + \arg ALL_PTP_REG: get the registers within the offset scope between ENET_PTP_TSCTL and ENET_PTP_PPSCTL + \arg ALL_DMA_REG: get the registers within the offset scope between ENET_DMA_BCTL and ENET_DMA_CRBADDR + \param[in] num: the number of registers that the user want to get + \param[out] preg: the application buffer pointer for storing the register value + \retval none +*/ +void enet_registers_get(enet_registers_type_enum type, uint32_t *preg, uint32_t num) +{ + uint32_t offset = 0U, max = 0U, limit = 0U; + + offset = (uint32_t)type; + max = (uint32_t)type + num; + limit = sizeof(enet_reg_tab)/sizeof(uint16_t); + + /* prevent element in this array is out of range */ + if(max > limit){ + max = limit; + } + + for(; offset < max; offset++){ + /* get value of the corresponding register */ + *preg = REG32((ENET) + enet_reg_tab[offset]); + preg++; + } +} + +/*! + \brief enable the MAC address filter + \param[in] mac_addr: select which MAC address will be enable + \arg ENET_MAC_ADDRESS1: enable MAC address 1 filter + \arg ENET_MAC_ADDRESS2: enable MAC address 2 filter + \arg ENET_MAC_ADDRESS3: enable MAC address 3 filter + \param[out] none + \retval none +*/ +void enet_address_filter_enable(enet_macaddress_enum mac_addr) +{ + REG32(ENET_ADDRH_BASE + mac_addr) |= ENET_MAC_ADDR1H_AFE; +} + +/*! + \brief disable the MAC address filter + \param[in] mac_addr: select which MAC address will be disable, + only one parameter can be selected which is shown as below + \arg ENET_MAC_ADDRESS1: disable MAC address 1 filter + \arg ENET_MAC_ADDRESS2: disable MAC address 2 filter + \arg ENET_MAC_ADDRESS3: disable MAC address 3 filter + \param[out] none + \retval none +*/ +void enet_address_filter_disable(enet_macaddress_enum mac_addr) +{ + REG32(ENET_ADDRH_BASE + mac_addr) &= ~ENET_MAC_ADDR1H_AFE; +} + +/*! + \brief configure the MAC address filter + \param[in] mac_addr: select which MAC address will be configured, + only one parameter can be selected which is shown as below + \arg ENET_MAC_ADDRESS1: configure MAC address 1 filter + \arg ENET_MAC_ADDRESS2: configure MAC address 2 filter + \arg ENET_MAC_ADDRESS3: configure MAC address 3 filter + \param[in] addr_mask: select which MAC address bytes will be mask, + one or more parameters can be selected which are shown as below + \arg ENET_ADDRESS_MASK_BYTE0: mask ENET_MAC_ADDR1L[7:0] bits + \arg ENET_ADDRESS_MASK_BYTE1: mask ENET_MAC_ADDR1L[15:8] bits + \arg ENET_ADDRESS_MASK_BYTE2: mask ENET_MAC_ADDR1L[23:16] bits + \arg ENET_ADDRESS_MASK_BYTE3: mask ENET_MAC_ADDR1L [31:24] bits + \arg ENET_ADDRESS_MASK_BYTE4: mask ENET_MAC_ADDR1H [7:0] bits + \arg ENET_ADDRESS_MASK_BYTE5: mask ENET_MAC_ADDR1H [15:8] bits + \param[in] filter_type: select which MAC address filter type will be selected, + only one parameter can be selected which is shown as below + \arg ENET_ADDRESS_FILTER_SA: The MAC address is used to compared with the SA field of the received frame + \arg ENET_ADDRESS_FILTER_DA: The MAC address is used to compared with the DA field of the received frame + \param[out] none + \retval none +*/ +void enet_address_filter_config(enet_macaddress_enum mac_addr, uint32_t addr_mask, uint32_t filter_type) +{ + uint32_t reg; + + /* get the address filter register value which is to be configured */ + reg = REG32(ENET_ADDRH_BASE + mac_addr); + + /* clear and configure the address filter register */ + reg &= ~(ENET_MAC_ADDR1H_MB | ENET_MAC_ADDR1H_SAF); + reg |= (addr_mask | filter_type); + REG32(ENET_ADDRH_BASE + mac_addr) = reg; +} + +/*! + \brief PHY interface configuration (configure SMI clock and reset PHY chip) + \param[in] none + \param[out] none + \retval ErrStatus: SUCCESS or ERROR +*/ +ErrStatus enet_phy_config(void) +{ + uint32_t ahbclk; + uint32_t reg; + uint16_t phy_value; + ErrStatus enet_state = ERROR; + + /* clear the previous MDC clock */ + reg = ENET_MAC_PHY_CTL; + reg &= ~ENET_MAC_PHY_CTL_CLR; + + /* get the HCLK frequency */ + ahbclk = rcu_clock_freq_get(CK_AHB); + + /* configure MDC clock according to HCLK frequency range */ + if(ENET_RANGE(ahbclk, 20000000U, 35000000U)){ + reg |= ENET_MDC_HCLK_DIV16; + }else if(ENET_RANGE(ahbclk, 35000000U, 60000000U)){ + reg |= ENET_MDC_HCLK_DIV26; + }else if(ENET_RANGE(ahbclk, 60000000U, 90000000U)){ + reg |= ENET_MDC_HCLK_DIV42; + }else if((ENET_RANGE(ahbclk, 90000000U, 108000000U))||(108000000U == ahbclk)){ + reg |= ENET_MDC_HCLK_DIV62; + }else{ + return enet_state; + } + ENET_MAC_PHY_CTL = reg; + + /* reset PHY */ + phy_value = PHY_RESET; + if(ERROR == (enet_phy_write_read(ENET_PHY_WRITE, PHY_ADDRESS, PHY_REG_BCR, &phy_value))){ + return enet_state; + } + /* PHY reset need some time */ + _ENET_DELAY_(ENET_DELAY_TO); + + /* check whether PHY reset is complete */ + if(ERROR == (enet_phy_write_read(ENET_PHY_READ, PHY_ADDRESS, PHY_REG_BCR, &phy_value))){ + return enet_state; + } + + /* PHY reset complete */ + if(RESET == (phy_value & PHY_RESET)){ + enet_state = SUCCESS; + } + + return enet_state; +} + +/*! + \brief write to / read from a PHY register + \param[in] direction: only one parameter can be selected which is shown as below + \arg ENET_PHY_WRITE: write data to phy register + \arg ENET_PHY_READ: read data from phy register + \param[in] phy_address: 0x0 - 0x1F + \param[in] phy_reg: 0x0 - 0x1F + \param[in] pvalue: the value will be written to the PHY register in ENET_PHY_WRITE direction + \param[out] pvalue: the value will be read from the PHY register in ENET_PHY_READ direction + \retval ErrStatus: SUCCESS or ERROR +*/ +ErrStatus enet_phy_write_read(enet_phydirection_enum direction, uint16_t phy_address, uint16_t phy_reg, uint16_t *pvalue) +{ + uint32_t reg, phy_flag; + uint32_t timeout = 0U; + ErrStatus enet_state = ERROR; + + /* configure ENET_MAC_PHY_CTL with write/read operation */ + reg = ENET_MAC_PHY_CTL; + reg &= ~(ENET_MAC_PHY_CTL_PB | ENET_MAC_PHY_CTL_PW | ENET_MAC_PHY_CTL_PR | ENET_MAC_PHY_CTL_PA); + reg |= (direction | MAC_PHY_CTL_PR(phy_reg) | MAC_PHY_CTL_PA(phy_address) | ENET_MAC_PHY_CTL_PB); + + /* if do the write operation, write value to the register */ + if(ENET_PHY_WRITE == direction){ + ENET_MAC_PHY_DATA = *pvalue; + } + + /* do PHY write/read operation, and wait the operation complete */ + ENET_MAC_PHY_CTL = reg; + do{ + phy_flag = (ENET_MAC_PHY_CTL & ENET_MAC_PHY_CTL_PB); + timeout++; + } + while((RESET != phy_flag) && (ENET_DELAY_TO != timeout)); + + /* write/read operation complete */ + if(RESET == (ENET_MAC_PHY_CTL & ENET_MAC_PHY_CTL_PB)){ + enet_state = SUCCESS; + } + + /* if do the read operation, get value from the register */ + if(ENET_PHY_READ == direction){ + *pvalue = (uint16_t)ENET_MAC_PHY_DATA; + } + + return enet_state; +} + +/*! + \brief enable the loopback function of PHY chip + \param[in] none + \param[out] none + \retval ErrStatus: ERROR or SUCCESS +*/ +ErrStatus enet_phyloopback_enable(void) +{ + uint16_t temp_phy = 0U; + ErrStatus phy_state = ERROR; + + /* get the PHY configuration to update it */ + enet_phy_write_read(ENET_PHY_READ, PHY_ADDRESS, PHY_REG_BCR, &temp_phy); + + /* enable the PHY loopback mode */ + temp_phy |= PHY_LOOPBACK; + + /* update the PHY control register with the new configuration */ + phy_state = enet_phy_write_read(ENET_PHY_WRITE, PHY_ADDRESS, PHY_REG_BCR, &temp_phy); + + return phy_state; +} + +/*! + \brief disable the loopback function of PHY chip + \param[in] none + \param[out] none + \retval ErrStatus: ERROR or SUCCESS +*/ +ErrStatus enet_phyloopback_disable(void) +{ + uint16_t temp_phy = 0U; + ErrStatus phy_state = ERROR; + + /* get the PHY configuration to update it */ + enet_phy_write_read(ENET_PHY_READ, PHY_ADDRESS, PHY_REG_BCR, &temp_phy); + + /* disable the PHY loopback mode */ + temp_phy &= (uint16_t)~PHY_LOOPBACK; + + /* update the PHY control register with the new configuration */ + phy_state = enet_phy_write_read(ENET_PHY_WRITE, PHY_ADDRESS, PHY_REG_BCR, &temp_phy); + + return phy_state; +} + +/*! + \brief enable ENET forward feature + \param[in] feature: the feature of ENET forward mode, + one or more parameters can be selected which are shown as below + \arg ENET_AUTO_PADCRC_DROP: the function of the MAC strips the Pad/FCS field on received frames + \arg ENET_FORWARD_ERRFRAMES: the function that all frame received with error except runt error are forwarded to memory + \arg ENET_FORWARD_UNDERSZ_GOODFRAMES: the function that forwarding undersized good frames + \param[out] none + \retval none +*/ +void enet_forward_feature_enable(uint32_t feature) +{ + uint32_t mask; + + mask = (feature & (~(ENET_FORWARD_ERRFRAMES | ENET_FORWARD_UNDERSZ_GOODFRAMES))); + ENET_MAC_CFG |= mask; + + mask = (feature & (~(ENET_AUTO_PADCRC_DROP))); + ENET_DMA_CTL |= (mask >> 2); +} + +/*! + \brief disable ENET forward feature + \param[in] feature: the feature of ENET forward mode, + one or more parameters can be selected which are shown as below + \arg ENET_AUTO_PADCRC_DROP: the function of the MAC strips the Pad/FCS field on received frames + \arg ENET_FORWARD_ERRFRAMES: the function that all frame received with error except runt error are forwarded to memory + \arg ENET_FORWARD_UNDERSZ_GOODFRAMES: the function that forwarding undersized good frames + \param[out] none + \retval none +*/ +void enet_forward_feature_disable(uint32_t feature) +{ + uint32_t mask; + + mask = (feature & (~(ENET_FORWARD_ERRFRAMES | ENET_FORWARD_UNDERSZ_GOODFRAMES))); + ENET_MAC_CFG &= ~mask; + + mask = (feature & (~(ENET_AUTO_PADCRC_DROP))); + ENET_DMA_CTL &= ~(mask >> 2); +} + +/*! + \brief enable ENET fliter feature + \param[in] feature: the feature of ENET fliter mode, + one or more parameters can be selected which are shown as below + \arg ENET_SRC_FILTER: filter source address function + \arg ENET_SRC_FILTER_INVERSE: inverse source address filtering result function + \arg ENET_DEST_FILTER_INVERSE: inverse DA filtering result function + \arg ENET_MULTICAST_FILTER_PASS: pass all multicast frames function + \arg ENET_MULTICAST_FILTER_HASH_MODE: HASH multicast filter function + \arg ENET_UNICAST_FILTER_HASH_MODE: HASH unicast filter function + \arg ENET_FILTER_MODE_EITHER: HASH or perfect filter function + \param[out] none + \retval none +*/ +void enet_fliter_feature_enable(uint32_t feature) +{ + ENET_MAC_FRMF |= feature; +} + +/*! + \brief disable ENET fliter feature + \param[in] feature: the feature of ENET fliter mode, + one or more parameters can be selected which are shown as below + \arg ENET_SRC_FILTER: filter source address function + \arg ENET_SRC_FILTER_INVERSE: inverse source address filtering result function + \arg ENET_DEST_FILTER_INVERSE: inverse DA filtering result function + \arg ENET_MULTICAST_FILTER_PASS: pass all multicast frames function + \arg ENET_MULTICAST_FILTER_HASH_MODE: HASH multicast filter function + \arg ENET_UNICAST_FILTER_HASH_MODE: HASH unicast filter function + \arg ENET_FILTER_MODE_EITHER: HASH or perfect filter function + \param[out] none + \retval none +*/ +void enet_fliter_feature_disable(uint32_t feature) +{ + ENET_MAC_FRMF &= ~feature; +} + +/*! + \brief generate the pause frame, ENET will send pause frame after enable transmit flow control + this function only use in full-dulex mode + \param[in] none + \param[out] none + \retval ErrStatus: ERROR or SUCCESS +*/ +ErrStatus enet_pauseframe_generate(void) +{ + ErrStatus enet_state =ERROR; + uint32_t temp = 0U; + + /* in full-duplex mode, must make sure this bit is 0 before writing register */ + temp = ENET_MAC_FCTL & ENET_MAC_FCTL_FLCBBKPA; + if(RESET == temp){ + ENET_MAC_FCTL |= ENET_MAC_FCTL_FLCBBKPA; + enet_state = SUCCESS; + } + return enet_state; +} + +/*! + \brief configure the pause frame detect type + \param[in] detect: pause frame detect type, + only one parameter can be selected which is shown as below + \arg ENET_MAC0_AND_UNIQUE_ADDRESS_PAUSEDETECT: besides the unique multicast address, MAC can also + use the MAC0 address to detecting pause frame + \arg ENET_UNIQUE_PAUSEDETECT: only the unique multicast address for pause frame which is specified + in IEEE802.3 can be detected + \param[out] none + \retval none +*/ +void enet_pauseframe_detect_config(uint32_t detect) +{ + ENET_MAC_FCTL &= ~ENET_MAC_FCTL_UPFDT; + ENET_MAC_FCTL |= detect; +} + +/*! + \brief configure the pause frame parameters + \param[in] pausetime: pause time in transmit pause control frame + \param[in] pause_threshold: the threshold of the pause timer for retransmitting frames automatically, + this value must make sure to be less than configured pause time, only one parameter can be + selected which is shown as below + \arg ENET_PAUSETIME_MINUS4: pause time minus 4 slot times + \arg ENET_PAUSETIME_MINUS28: pause time minus 28 slot times + \arg ENET_PAUSETIME_MINUS144: pause time minus 144 slot times + \arg ENET_PAUSETIME_MINUS256: pause time minus 256 slot times + \param[out] none + \retval none +*/ +void enet_pauseframe_config(uint32_t pausetime, uint32_t pause_threshold) +{ + ENET_MAC_FCTL &= ~(ENET_MAC_FCTL_PTM | ENET_MAC_FCTL_PLTS); + ENET_MAC_FCTL |= (MAC_FCTL_PTM(pausetime) | pause_threshold); +} + +/*! + \brief configure the threshold of the flow control(deactive and active threshold) + \param[in] deactive: the threshold of the deactive flow control, this value + should always be less than active flow control value, only one + parameter can be selected which is shown as below + \arg ENET_DEACTIVE_THRESHOLD_256BYTES: threshold level is 256 bytes + \arg ENET_DEACTIVE_THRESHOLD_512BYTES: threshold level is 512 bytes + \arg ENET_DEACTIVE_THRESHOLD_768BYTES: threshold level is 768 bytes + \arg ENET_DEACTIVE_THRESHOLD_1024BYTES: threshold level is 1024 bytes + \arg ENET_DEACTIVE_THRESHOLD_1280BYTES: threshold level is 1280 bytes + \arg ENET_DEACTIVE_THRESHOLD_1536BYTES: threshold level is 1536 bytes + \arg ENET_DEACTIVE_THRESHOLD_1792BYTES: threshold level is 1792 bytes + \param[in] active: the threshold of the active flow control, only one parameter + can be selected which is shown as below + \arg ENET_ACTIVE_THRESHOLD_256BYTES: threshold level is 256 bytes + \arg ENET_ACTIVE_THRESHOLD_512BYTES: threshold level is 512 bytes + \arg ENET_ACTIVE_THRESHOLD_768BYTES: threshold level is 768 bytes + \arg ENET_ACTIVE_THRESHOLD_1024BYTES: threshold level is 1024 bytes + \arg ENET_ACTIVE_THRESHOLD_1280BYTES: threshold level is 1280 bytes + \arg ENET_ACTIVE_THRESHOLD_1536BYTES: threshold level is 1536 bytes + \arg ENET_ACTIVE_THRESHOLD_1792BYTES: threshold level is 1792 bytes + \param[out] none + \retval none +*/ +void enet_flowcontrol_threshold_config(uint32_t deactive, uint32_t active) +{ + ENET_MAC_FCTH = ((deactive | active) >> 8); +} + +/*! + \brief enable ENET flow control feature + \param[in] feature: the feature of ENET flow control mode + one or more parameters can be selected which are shown as below + \arg ENET_ZERO_QUANTA_PAUSE: the automatic zero-quanta generation function + \arg ENET_TX_FLOWCONTROL: the flow control operation in the MAC + \arg ENET_RX_FLOWCONTROL: decoding function for the received pause frame and process it + \arg ENET_BACK_PRESSURE: back pressure operation in the MAC(only use in half-dulex mode) + \param[out] none + \retval none +*/ +void enet_flowcontrol_feature_enable(uint32_t feature) +{ + if(RESET != (feature & ENET_ZERO_QUANTA_PAUSE)){ + ENET_MAC_FCTL &= ~ENET_ZERO_QUANTA_PAUSE; + } + feature &= ~ENET_ZERO_QUANTA_PAUSE; + ENET_MAC_FCTL |= feature; +} + +/*! + \brief disable ENET flow control feature + \param[in] feature: the feature of ENET flow control mode + one or more parameters can be selected which are shown as below + \arg ENET_ZERO_QUANTA_PAUSE: the automatic zero-quanta generation function + \arg ENET_TX_FLOWCONTROL: the flow control operation in the MAC + \arg ENET_RX_FLOWCONTROL: decoding function for the received pause frame and process it + \arg ENET_BACK_PRESSURE: back pressure operation in the MAC(only use in half-dulex mode) + \param[out] none + \retval none +*/ +void enet_flowcontrol_feature_disable(uint32_t feature) +{ + if(RESET != (feature & ENET_ZERO_QUANTA_PAUSE)){ + ENET_MAC_FCTL |= ENET_ZERO_QUANTA_PAUSE; + } + feature &= ~ENET_ZERO_QUANTA_PAUSE; + ENET_MAC_FCTL &= ~feature; +} + +/*! + \brief get the dma transmit/receive process state + \param[in] direction: choose the direction of dma process which users want to check, + refer to enet_dmadirection_enum, only one parameter can be selected which is shown as below + \arg ENET_DMA_TX: dma transmit process + \arg ENET_DMA_RX: dma receive process + \param[out] none + \retval state of dma process, the value range shows below: + ENET_RX_STATE_STOPPED, ENET_RX_STATE_FETCHING, ENET_RX_STATE_WAITING, + ENET_RX_STATE_SUSPENDED, ENET_RX_STATE_CLOSING, ENET_RX_STATE_QUEUING, + ENET_TX_STATE_STOPPED, ENET_TX_STATE_FETCHING, ENET_TX_STATE_WAITING, + ENET_TX_STATE_READING, ENET_TX_STATE_SUSPENDED, ENET_TX_STATE_CLOSING +*/ +uint32_t enet_dmaprocess_state_get(enet_dmadirection_enum direction) +{ + uint32_t reval; + reval = (uint32_t)(ENET_DMA_STAT & (uint32_t)direction); + return reval; +} + +/*! + \brief poll the DMA transmission/reception enable by writing any value to the + ENET_DMA_TPEN/ENET_DMA_RPEN register, this will make the DMA to resume transmission/reception + \param[in] direction: choose the direction of DMA process which users want to resume, + refer to enet_dmadirection_enum, only one parameter can be selected which is shown as below + \arg ENET_DMA_TX: DMA transmit process + \arg ENET_DMA_RX: DMA receive process + \param[out] none + \retval none +*/ +void enet_dmaprocess_resume(enet_dmadirection_enum direction) +{ + if(ENET_DMA_TX == direction){ + ENET_DMA_TPEN = 0U; + }else{ + ENET_DMA_RPEN = 0U; + } +} + +/*! + \brief check and recover the Rx process + \param[in] none + \param[out] none + \retval none +*/ +void enet_rxprocess_check_recovery(void) +{ + uint32_t status; + + /* get DAV information of current RxDMA descriptor */ + status = dma_current_rxdesc->status; + status &= ENET_RDES0_DAV; + + /* if current descriptor is owned by DMA, but the descriptor address mismatches with + receive descriptor address pointer updated by RxDMA controller */ + if((ENET_DMA_CRDADDR != ((uint32_t)dma_current_rxdesc)) && + (ENET_RDES0_DAV == status)){ + dma_current_rxdesc = (enet_descriptors_struct*)ENET_DMA_CRDADDR; + } +} + +/*! + \brief flush the ENET transmit FIFO, and wait until the flush operation completes + \param[in] none + \param[out] none + \retval ErrStatus: ERROR or SUCCESS +*/ +ErrStatus enet_txfifo_flush(void) +{ + uint32_t flush_state; + uint32_t timeout = 0U; + ErrStatus enet_state = ERROR; + + /* set the FTF bit for flushing transmit FIFO */ + ENET_DMA_CTL |= ENET_DMA_CTL_FTF; + /* wait until the flush operation completes */ + do{ + flush_state = ENET_DMA_CTL & ENET_DMA_CTL_FTF; + timeout++; + }while((RESET != flush_state) && (timeout < ENET_DELAY_TO)); + /* return ERROR due to timeout */ + if(RESET == flush_state){ + enet_state = SUCCESS; + } + + return enet_state; +} + +/*! + \brief get the transmit/receive address of current descriptor, or current buffer, or descriptor table + \param[in] addr_get: choose the address which users want to get, refer to enet_desc_reg_enum, + only one parameter can be selected which is shown as below + \arg ENET_RX_DESC_TABLE: the start address of the receive descriptor table + \arg ENET_RX_CURRENT_DESC: the start descriptor address of the current receive descriptor read by + the RxDMA controller + \arg ENET_RX_CURRENT_BUFFER: the current receive buffer address being read by the RxDMA controller + \arg ENET_TX_DESC_TABLE: the start address of the transmit descriptor table + \arg ENET_TX_CURRENT_DESC: the start descriptor address of the current transmit descriptor read by + the TxDMA controller + \arg ENET_TX_CURRENT_BUFFER: the current transmit buffer address being read by the TxDMA controller + \param[out] none + \retval address value +*/ +uint32_t enet_current_desc_address_get(enet_desc_reg_enum addr_get) +{ + uint32_t reval = 0U; + + reval = REG32((ENET) +(uint32_t)addr_get); + return reval; +} + +/*! + \brief get the Tx or Rx descriptor information + \param[in] desc: the descriptor pointer which users want to get information + \param[in] info_get: the descriptor information type which is selected, + only one parameter can be selected which is shown as below + \arg RXDESC_BUFFER_1_SIZE: receive buffer 1 size + \arg RXDESC_BUFFER_2_SIZE: receive buffer 2 size + \arg RXDESC_FRAME_LENGTH: the byte length of the received frame that was transferred to the buffer + \arg TXDESC_COLLISION_COUNT: the number of collisions occurred before the frame was transmitted + \arg RXDESC_BUFFER_1_ADDR: the buffer1 address of the Rx frame + \arg TXDESC_BUFFER_1_ADDR: the buffer1 address of the Tx frame + \param[out] none + \retval descriptor information, if value is 0xFFFFFFFFU, means the false input parameter +*/ +uint32_t enet_desc_information_get(enet_descriptors_struct *desc, enet_descstate_enum info_get) +{ + uint32_t reval = 0xFFFFFFFFU; + + switch(info_get){ + case RXDESC_BUFFER_1_SIZE: + reval = GET_RDES1_RB1S(desc->control_buffer_size); + break; + case RXDESC_BUFFER_2_SIZE: + reval = GET_RDES1_RB2S(desc->control_buffer_size); + break; + case RXDESC_FRAME_LENGTH: + reval = GET_RDES0_FRML(desc->status); + if(reval > 4U){ + reval = reval - 4U; + }else{ + reval = 0U; + } + break; + case RXDESC_BUFFER_1_ADDR: + reval = desc->buffer1_addr; + break; + case TXDESC_BUFFER_1_ADDR: + reval = desc->buffer1_addr; + break; + case TXDESC_COLLISION_COUNT: + reval = GET_TDES0_COCNT(desc->status); + break; + default: + break; + } + return reval; +} + +/*! + \brief get the number of missed frames during receiving + \param[in] none + \param[out] rxfifo_drop: pointer to the number of frames dropped by RxFIFO + \param[out] rxdma_drop: pointer to the number of frames missed by the RxDMA controller + \retval none +*/ +void enet_missed_frame_counter_get(uint32_t *rxfifo_drop, uint32_t *rxdma_drop) +{ + uint32_t temp_counter = 0U; + + temp_counter = ENET_DMA_MFBOCNT; + *rxfifo_drop = GET_DMA_MFBOCNT_MSFA(temp_counter); + *rxdma_drop = GET_DMA_MFBOCNT_MSFC(temp_counter); +} + +/*! + \brief get the bit flag of ENET DMA descriptor + \param[in] desc: the descriptor pointer which users want to get flag + \param[in] desc_flag: the bit flag of ENET DMA descriptor, + only one parameter can be selected which is shown as below + \arg ENET_TDES0_DB: deferred + \arg ENET_TDES0_UFE: underflow error + \arg ENET_TDES0_EXD: excessive deferral + \arg ENET_TDES0_VFRM: VLAN frame + \arg ENET_TDES0_ECO: excessive collision + \arg ENET_TDES0_LCO: late collision + \arg ENET_TDES0_NCA: no carrier + \arg ENET_TDES0_LCA: loss of carrier + \arg ENET_TDES0_IPPE: IP payload error + \arg ENET_TDES0_FRMF: frame flushed + \arg ENET_TDES0_JT: jabber timeout + \arg ENET_TDES0_ES: error summary + \arg ENET_TDES0_IPHE: IP header error + \arg ENET_TDES0_TTMSS: transmit timestamp status + \arg ENET_TDES0_TCHM: the second address chained mode + \arg ENET_TDES0_TERM: transmit end of ring mode + \arg ENET_TDES0_TTSEN: transmit timestamp function enable + \arg ENET_TDES0_DPAD: disable adding pad + \arg ENET_TDES0_DCRC: disable CRC + \arg ENET_TDES0_FSG: first segment + \arg ENET_TDES0_LSG: last segment + \arg ENET_TDES0_INTC: interrupt on completion + \arg ENET_TDES0_DAV: DAV bit + + \arg ENET_RDES0_PCERR: payload checksum error + \arg ENET_RDES0_CERR: CRC error + \arg ENET_RDES0_DBERR: dribble bit error + \arg ENET_RDES0_RERR: receive error + \arg ENET_RDES0_RWDT: receive watchdog timeout + \arg ENET_RDES0_FRMT: frame type + \arg ENET_RDES0_LCO: late collision + \arg ENET_RDES0_IPHERR: IP frame header error + \arg ENET_RDES0_LDES: last descriptor + \arg ENET_RDES0_FDES: first descriptor + \arg ENET_RDES0_VTAG: VLAN tag + \arg ENET_RDES0_OERR: overflow error + \arg ENET_RDES0_LERR: length error + \arg ENET_RDES0_SAFF: SA filter fail + \arg ENET_RDES0_DERR: descriptor error + \arg ENET_RDES0_ERRS: error summary + \arg ENET_RDES0_DAFF: destination address filter fail + \arg ENET_RDES0_DAV: descriptor available + \param[out] none + \retval FlagStatus: SET or RESET +*/ +FlagStatus enet_desc_flag_get(enet_descriptors_struct *desc, uint32_t desc_flag) +{ + FlagStatus enet_flag = RESET; + + if ((uint32_t)RESET != (desc->status & desc_flag)){ + enet_flag = SET; + } + + return enet_flag; +} + +/*! + \brief set the bit flag of ENET DMA descriptor + \param[in] desc: the descriptor pointer which users want to set flag + \param[in] desc_flag: the bit flag of ENET DMA descriptor, + only one parameter can be selected which is shown as below + \arg ENET_TDES0_VFRM: VLAN frame + \arg ENET_TDES0_FRMF: frame flushed + \arg ENET_TDES0_TCHM: the second address chained mode + \arg ENET_TDES0_TERM: transmit end of ring mode + \arg ENET_TDES0_TTSEN: transmit timestamp function enable + \arg ENET_TDES0_DPAD: disable adding pad + \arg ENET_TDES0_DCRC: disable CRC + \arg ENET_TDES0_FSG: first segment + \arg ENET_TDES0_LSG: last segment + \arg ENET_TDES0_INTC: interrupt on completion + \arg ENET_TDES0_DAV: DAV bit + \arg ENET_RDES0_DAV: descriptor available + \param[out] none + \retval none +*/ +void enet_desc_flag_set(enet_descriptors_struct *desc, uint32_t desc_flag) +{ + desc->status |= desc_flag; +} + +/*! + \brief clear the bit flag of ENET DMA descriptor + \param[in] desc: the descriptor pointer which users want to clear flag + \param[in] desc_flag: the bit flag of ENET DMA descriptor, + only one parameter can be selected which is shown as below + \arg ENET_TDES0_VFRM: VLAN frame + \arg ENET_TDES0_FRMF: frame flushed + \arg ENET_TDES0_TCHM: the second address chained mode + \arg ENET_TDES0_TERM: transmit end of ring mode + \arg ENET_TDES0_TTSEN: transmit timestamp function enable + \arg ENET_TDES0_DPAD: disable adding pad + \arg ENET_TDES0_DCRC: disable CRC + \arg ENET_TDES0_FSG: first segment + \arg ENET_TDES0_LSG: last segment + \arg ENET_TDES0_INTC: interrupt on completion + \arg ENET_TDES0_DAV: DAV bit + \arg ENET_RDES0_DAV: descriptor available + \param[out] none + \retval none +*/ +void enet_desc_flag_clear(enet_descriptors_struct *desc, uint32_t desc_flag) +{ + desc->status &= ~desc_flag; +} + +/*! + \brief when receiving completed, set RS bit in ENET_DMA_STAT register will set + \param[in] desc: the descriptor pointer which users want to configure + \param[out] none + \retval none +*/ +void enet_desc_receive_complete_bit_enable(enet_descriptors_struct *desc) +{ + desc->control_buffer_size &= ~ENET_RDES1_DINTC; +} + +/*! + \brief when receiving completed, set RS bit in ENET_DMA_STAT register will not set + \param[in] desc: the descriptor pointer which users want to configure + \param[out] none + \retval none +*/ +void enet_desc_receive_complete_bit_disable(enet_descriptors_struct *desc) +{ + desc->control_buffer_size |= ENET_RDES1_DINTC; +} + +/*! + \brief drop current receive frame + \param[in] none + \param[out] none + \retval none +*/ +void enet_rxframe_drop(void) +{ + /* enable reception, descriptor is owned by DMA */ + dma_current_rxdesc->status = ENET_RDES0_DAV; + + /* chained mode */ + if((uint32_t)RESET != (dma_current_rxdesc->control_buffer_size & ENET_RDES1_RCHM)){ + if(NULL != dma_current_ptp_rxdesc){ + dma_current_rxdesc = (enet_descriptors_struct*) (dma_current_ptp_rxdesc->buffer2_next_desc_addr); + /* if it is the last ptp descriptor */ + if(0U != dma_current_ptp_rxdesc->status){ + /* pointer back to the first ptp descriptor address in the desc_ptptab list address */ + dma_current_ptp_rxdesc = (enet_descriptors_struct*) (dma_current_ptp_rxdesc->status); + }else{ + /* ponter to the next ptp descriptor */ + dma_current_ptp_rxdesc++; + } + }else{ + dma_current_rxdesc = (enet_descriptors_struct*) (dma_current_rxdesc->buffer2_next_desc_addr); + } + + }else{ + /* ring mode */ + if((uint32_t)RESET != (dma_current_rxdesc->control_buffer_size & ENET_RDES1_RERM)){ + /* if is the last descriptor in table, the next descriptor is the table header */ + dma_current_rxdesc = (enet_descriptors_struct*) (ENET_DMA_RDTADDR); + if(NULL != dma_current_ptp_rxdesc){ + dma_current_ptp_rxdesc = (enet_descriptors_struct*) (dma_current_ptp_rxdesc->status); + } + }else{ + /* the next descriptor is the current address, add the descriptor size, and descriptor skip length */ + dma_current_rxdesc = (enet_descriptors_struct*) (uint32_t)((uint32_t)dma_current_rxdesc + ETH_DMARXDESC_SIZE + GET_DMA_BCTL_DPSL(ENET_DMA_BCTL)); + if(NULL != dma_current_ptp_rxdesc){ + dma_current_ptp_rxdesc++; + } + } + } +} + +/*! + \brief enable DMA feature + \param[in] feature: the feature of DMA mode, + one or more parameters can be selected which are shown as below + \arg ENET_NO_FLUSH_RXFRAME: RxDMA does not flushes frames function + \arg ENET_SECONDFRAME_OPT: TxDMA controller operate on second frame function + \param[out] none + \retval none +*/ +void enet_dma_feature_enable(uint32_t feature) +{ + ENET_DMA_CTL |= feature; +} + +/*! + \brief disable DMA feature + \param[in] feature: the feature of DMA mode, + one or more parameters can be selected which are shown as below + \arg ENET_NO_FLUSH_RXFRAME: RxDMA does not flushes frames function + \arg ENET_SECONDFRAME_OPT: TxDMA controller operate on second frame function + \param[out] none + \retval none +*/ +void enet_dma_feature_disable(uint32_t feature) +{ + ENET_DMA_CTL &= ~feature; +} + +/*! + \brief initialize the DMA Tx/Rx descriptors's parameters in normal chain mode with PTP function + \param[in] direction: the descriptors which users want to init, refer to enet_dmadirection_enum, + only one parameter can be selected which is shown as below + \arg ENET_DMA_TX: DMA Tx descriptors + \arg ENET_DMA_RX: DMA Rx descriptors + \param[in] desc_ptptab: pointer to the first descriptor address of PTP Rx descriptor table + \param[out] none + \retval none +*/ +void enet_ptp_normal_descriptors_chain_init(enet_dmadirection_enum direction, enet_descriptors_struct *desc_ptptab) +{ + uint32_t num = 0U, count = 0U, maxsize = 0U; + uint32_t desc_status = 0U, desc_bufsize = 0U; + enet_descriptors_struct *desc, *desc_tab; + uint8_t *buf; + + /* if want to initialize DMA Tx descriptors */ + if (ENET_DMA_TX == direction){ + /* save a copy of the DMA Tx descriptors */ + desc_tab = txdesc_tab; + buf = &tx_buff[0][0]; + count = ENET_TXBUF_NUM; + maxsize = ENET_TXBUF_SIZE; + + /* select chain mode, and enable transmit timestamp function */ + desc_status = ENET_TDES0_TCHM | ENET_TDES0_TTSEN; + + /* configure DMA Tx descriptor table address register */ + ENET_DMA_TDTADDR = (uint32_t)desc_tab; + dma_current_txdesc = desc_tab; + dma_current_ptp_txdesc = desc_ptptab; + }else{ + /* if want to initialize DMA Rx descriptors */ + /* save a copy of the DMA Rx descriptors */ + desc_tab = rxdesc_tab; + buf = &rx_buff[0][0]; + count = ENET_RXBUF_NUM; + maxsize = ENET_RXBUF_SIZE; + + /* enable receiving */ + desc_status = ENET_RDES0_DAV; + /* select receive chained mode and set buffer1 size */ + desc_bufsize = ENET_RDES1_RCHM | (uint32_t)ENET_RXBUF_SIZE; + + /* configure DMA Rx descriptor table address register */ + ENET_DMA_RDTADDR = (uint32_t)desc_tab; + dma_current_rxdesc = desc_tab; + dma_current_ptp_rxdesc = desc_ptptab; + } + + /* configure each descriptor */ + for(num = 0U; num < count; num++){ + /* get the pointer to the next descriptor of the descriptor table */ + desc = desc_tab + num; + + /* configure descriptors */ + desc->status = desc_status; + desc->control_buffer_size = desc_bufsize; + desc->buffer1_addr = (uint32_t)(&buf[num * maxsize]); + + /* if is not the last descriptor */ + if(num < (count - 1U)){ + /* configure the next descriptor address */ + desc->buffer2_next_desc_addr = (uint32_t)(desc_tab + num + 1U); + }else{ + /* when it is the last descriptor, the next descriptor address + equals to first descriptor address in descriptor table */ + desc->buffer2_next_desc_addr = (uint32_t)desc_tab; + } + /* set desc_ptptab equal to desc_tab */ + (&desc_ptptab[num])->buffer1_addr = desc->buffer1_addr; + (&desc_ptptab[num])->buffer2_next_desc_addr = desc->buffer2_next_desc_addr; + } + /* when it is the last ptp descriptor, preserve the first descriptor + address of desc_ptptab in ptp descriptor status */ + (&desc_ptptab[num-1U])->status = (uint32_t)desc_ptptab; +} + +/*! + \brief initialize the DMA Tx/Rx descriptors's parameters in normal ring mode with PTP function + \param[in] direction: the descriptors which users want to init, refer to enet_dmadirection_enum, + only one parameter can be selected which is shown as below + \arg ENET_DMA_TX: DMA Tx descriptors + \arg ENET_DMA_RX: DMA Rx descriptors + \param[in] desc_ptptab: pointer to the first descriptor address of PTP Rx descriptor table + \param[out] none + \retval none +*/ +void enet_ptp_normal_descriptors_ring_init(enet_dmadirection_enum direction, enet_descriptors_struct *desc_ptptab) +{ + uint32_t num = 0U, count = 0U, maxsize = 0U; + uint32_t desc_status = 0U, desc_bufsize = 0U; + enet_descriptors_struct *desc, *desc_tab; + uint8_t *buf; + + /* configure descriptor skip length */ + ENET_DMA_BCTL &= ~ENET_DMA_BCTL_DPSL; + ENET_DMA_BCTL |= DMA_BCTL_DPSL(0); + + /* if want to initialize DMA Tx descriptors */ + if (ENET_DMA_TX == direction){ + /* save a copy of the DMA Tx descriptors */ + desc_tab = txdesc_tab; + buf = &tx_buff[0][0]; + count = ENET_TXBUF_NUM; + maxsize = ENET_TXBUF_SIZE; + + /* select ring mode, and enable transmit timestamp function */ + desc_status = ENET_TDES0_TTSEN; + + /* configure DMA Tx descriptor table address register */ + ENET_DMA_TDTADDR = (uint32_t)desc_tab; + dma_current_txdesc = desc_tab; + dma_current_ptp_txdesc = desc_ptptab; + }else{ + /* if want to initialize DMA Rx descriptors */ + /* save a copy of the DMA Rx descriptors */ + desc_tab = rxdesc_tab; + buf = &rx_buff[0][0]; + count = ENET_RXBUF_NUM; + maxsize = ENET_RXBUF_SIZE; + + /* enable receiving */ + desc_status = ENET_RDES0_DAV; + /* select receive ring mode and set buffer1 size */ + desc_bufsize = (uint32_t)ENET_RXBUF_SIZE; + + /* configure DMA Rx descriptor table address register */ + ENET_DMA_RDTADDR = (uint32_t)desc_tab; + dma_current_rxdesc = desc_tab; + dma_current_ptp_rxdesc = desc_ptptab; + } + + /* configure each descriptor */ + for(num = 0U; num < count; num++){ + /* get the pointer to the next descriptor of the descriptor table */ + desc = desc_tab + num; + + /* configure descriptors */ + desc->status = desc_status; + desc->control_buffer_size = desc_bufsize; + desc->buffer1_addr = (uint32_t)(&buf[num * maxsize]); + + /* when it is the last descriptor */ + if(num == (count - 1U)){ + if (ENET_DMA_TX == direction){ + /* configure transmit end of ring mode */ + desc->status |= ENET_TDES0_TERM; + }else{ + /* configure receive end of ring mode */ + desc->control_buffer_size |= ENET_RDES1_RERM; + } + } + /* set desc_ptptab equal to desc_tab */ + (&desc_ptptab[num])->buffer1_addr = desc->buffer1_addr; + (&desc_ptptab[num])->buffer2_next_desc_addr = desc->buffer2_next_desc_addr; + } + /* when it is the last ptp descriptor, preserve the first descriptor + address of desc_ptptab in ptp descriptor status */ + (&desc_ptptab[num-1U])->status = (uint32_t)desc_ptptab; +} + +/*! + \brief receive a packet data with timestamp values to application buffer, when the DMA is in normal mode + \param[in] bufsize: the size of buffer which is the parameter in function + \param[out] timestamp: pointer to the table which stores the timestamp high and low + \param[out] buffer: pointer to the application buffer + note -- if the input is NULL, user should copy data in application by himself + \retval ErrStatus: SUCCESS or ERROR +*/ +ErrStatus enet_ptpframe_receive_normal_mode(uint8_t *buffer, uint32_t bufsize, uint32_t timestamp[]) +{ + uint32_t offset = 0U, size = 0U; + + /* the descriptor is busy due to own by the DMA */ + if((uint32_t)RESET != (dma_current_rxdesc->status & ENET_RDES0_DAV)){ + return ERROR; + } + + /* if buffer pointer is null, indicates that users has copied data in application */ + if(NULL != buffer){ + /* if no error occurs, and the frame uses only one descriptor */ + if(((uint32_t)RESET == (dma_current_rxdesc->status & ENET_RDES0_ERRS)) && + ((uint32_t)RESET != (dma_current_rxdesc->status & ENET_RDES0_LDES)) && + ((uint32_t)RESET != (dma_current_rxdesc->status & ENET_RDES0_FDES))){ + + /* get the frame length except CRC */ + size = GET_RDES0_FRML(dma_current_rxdesc->status) - 4U; + + /* to avoid situation that the frame size exceeds the buffer length */ + if(size > bufsize){ + return ERROR; + } + + /* copy data from Rx buffer to application buffer */ + for(offset = 0U; offset < size; offset++){ + (*(buffer + offset)) = (*(__IO uint8_t *)(uint32_t)((dma_current_ptp_rxdesc->buffer1_addr) + offset)); + } + + }else{ + return ERROR; + } + } + /* copy timestamp value from Rx descriptor to application array */ + timestamp[0] = dma_current_rxdesc->buffer1_addr; + timestamp[1] = dma_current_rxdesc->buffer2_next_desc_addr; + + dma_current_rxdesc->buffer1_addr = dma_current_ptp_rxdesc ->buffer1_addr ; + dma_current_rxdesc->buffer2_next_desc_addr = dma_current_ptp_rxdesc ->buffer2_next_desc_addr; + + /* enable reception, descriptor is owned by DMA */ + dma_current_rxdesc->status = ENET_RDES0_DAV; + + /* check Rx buffer unavailable flag status */ + if ((uint32_t)RESET != (ENET_DMA_STAT & ENET_DMA_STAT_RBU)){ + /* clear RBU flag */ + ENET_DMA_STAT = ENET_DMA_STAT_RBU; + /* resume DMA reception by writing to the RPEN register*/ + ENET_DMA_RPEN = 0U; + } + + + /* update the current RxDMA descriptor pointer to the next decriptor in RxDMA decriptor table */ + /* chained mode */ + if((uint32_t)RESET != (dma_current_rxdesc->control_buffer_size & ENET_RDES1_RCHM)){ + dma_current_rxdesc = (enet_descriptors_struct*) (dma_current_ptp_rxdesc->buffer2_next_desc_addr); + /* if it is the last ptp descriptor */ + if(0U != dma_current_ptp_rxdesc->status){ + /* pointer back to the first ptp descriptor address in the desc_ptptab list address */ + dma_current_ptp_rxdesc = (enet_descriptors_struct*) (dma_current_ptp_rxdesc->status); + }else{ + /* ponter to the next ptp descriptor */ + dma_current_ptp_rxdesc++; + } + }else{ + /* ring mode */ + if((uint32_t)RESET != (dma_current_rxdesc->control_buffer_size & ENET_RDES1_RERM)){ + /* if is the last descriptor in table, the next descriptor is the table header */ + dma_current_rxdesc = (enet_descriptors_struct*) (ENET_DMA_RDTADDR); + /* RDES2 and RDES3 will not be covered by buffer address, so do not need to preserve a new table, + use the same table with RxDMA descriptor */ + dma_current_ptp_rxdesc = (enet_descriptors_struct*) (dma_current_ptp_rxdesc->status); + }else{ + /* the next descriptor is the current address, add the descriptor size, and descriptor skip length */ + dma_current_rxdesc = (enet_descriptors_struct*) (uint32_t)((uint32_t)dma_current_rxdesc + ETH_DMARXDESC_SIZE + GET_DMA_BCTL_DPSL(ENET_DMA_BCTL)); + dma_current_ptp_rxdesc ++; + } + } + + return SUCCESS; +} + +/*! + \brief send data with timestamp values in application buffer as a transmit packet, when the DMA is in normal mode + \param[in] buffer: pointer on the application buffer + note -- if the input is NULL, user should copy data in application by himself + \param[in] length: the length of frame data to be transmitted + \param[out] timestamp: pointer to the table which stores the timestamp high and low + note -- if the input is NULL, timestamp is ignored + \retval ErrStatus: SUCCESS or ERROR +*/ +ErrStatus enet_ptpframe_transmit_normal_mode(uint8_t *buffer, uint32_t length, uint32_t timestamp[]) +{ + uint32_t offset = 0U, timeout = 0U; + uint32_t dma_tbu_flag, dma_tu_flag, tdes0_ttmss_flag; + + /* the descriptor is busy due to own by the DMA */ + if((uint32_t)RESET != (dma_current_txdesc->status & ENET_TDES0_DAV)){ + return ERROR; + } + + /* only frame length no more than ENET_MAX_FRAME_SIZE is allowed */ + if(length > ENET_MAX_FRAME_SIZE){ + return ERROR; + } + + /* if buffer pointer is null, indicates that users has handled data in application */ + if(NULL != buffer){ + /* copy frame data from application buffer to Tx buffer */ + for(offset = 0U; offset < length; offset++){ + (*(__IO uint8_t *) (uint32_t)((dma_current_ptp_txdesc->buffer1_addr) + offset)) = (*(buffer + offset)); + } + } + /* set the frame length */ + dma_current_txdesc->control_buffer_size = (length & (uint32_t)0x1FFF); + /* set the segment of frame, frame is transmitted in one descriptor */ + dma_current_txdesc->status |= ENET_TDES0_LSG | ENET_TDES0_FSG; + /* enable the DMA transmission */ + dma_current_txdesc->status |= ENET_TDES0_DAV; + + /* check Tx buffer unavailable flag status */ + dma_tbu_flag = (ENET_DMA_STAT & ENET_DMA_STAT_TBU); + dma_tu_flag = (ENET_DMA_STAT & ENET_DMA_STAT_TU); + + if((RESET != dma_tbu_flag) || (RESET != dma_tu_flag)){ + /* clear TBU and TU flag */ + ENET_DMA_STAT = (dma_tbu_flag | dma_tu_flag); + /* resume DMA transmission by writing to the TPEN register*/ + ENET_DMA_TPEN = 0U; + } + + /* if timestamp pointer is null, indicates that users don't care timestamp in application */ + if(NULL != timestamp){ + /* wait for ENET_TDES0_TTMSS flag to be set, a timestamp was captured */ + do{ + tdes0_ttmss_flag = (dma_current_txdesc->status & ENET_TDES0_TTMSS); + timeout++; + }while((RESET == tdes0_ttmss_flag) && (timeout < ENET_DELAY_TO)); + + /* return ERROR due to timeout */ + if(ENET_DELAY_TO == timeout){ + return ERROR; + } + + /* clear the ENET_TDES0_TTMSS flag */ + dma_current_txdesc->status &= ~ENET_TDES0_TTMSS; + /* get the timestamp value of the transmit frame */ + timestamp[0] = dma_current_txdesc->buffer1_addr; + timestamp[1] = dma_current_txdesc->buffer2_next_desc_addr; + } + dma_current_txdesc->buffer1_addr = dma_current_ptp_txdesc ->buffer1_addr ; + dma_current_txdesc->buffer2_next_desc_addr = dma_current_ptp_txdesc ->buffer2_next_desc_addr; + + /* update the current TxDMA descriptor pointer to the next decriptor in TxDMA decriptor table */ + /* chained mode */ + if((uint32_t)RESET != (dma_current_txdesc->status & ENET_TDES0_TCHM)){ + dma_current_txdesc = (enet_descriptors_struct*) (dma_current_ptp_txdesc->buffer2_next_desc_addr); + /* if it is the last ptp descriptor */ + if(0U != dma_current_ptp_txdesc->status){ + /* pointer back to the first ptp descriptor address in the desc_ptptab list address */ + dma_current_ptp_txdesc = (enet_descriptors_struct*) (dma_current_ptp_txdesc->status); + }else{ + /* ponter to the next ptp descriptor */ + dma_current_ptp_txdesc++; + } + }else{ + /* ring mode */ + if((uint32_t)RESET != (dma_current_txdesc->status & ENET_TDES0_TERM)){ + /* if is the last descriptor in table, the next descriptor is the table header */ + dma_current_txdesc = (enet_descriptors_struct*) (ENET_DMA_TDTADDR); + /* TDES2 and TDES3 will not be covered by buffer address, so do not need to preserve a new table, + use the same table with TxDMA descriptor */ + dma_current_ptp_txdesc = (enet_descriptors_struct*) (dma_current_ptp_txdesc->status); + }else{ + /* the next descriptor is the current address, add the descriptor size, and descriptor skip length */ + dma_current_txdesc = (enet_descriptors_struct*) (uint32_t)((uint32_t)dma_current_txdesc + ETH_DMATXDESC_SIZE + GET_DMA_BCTL_DPSL(ENET_DMA_BCTL)); + dma_current_ptp_txdesc ++; + } + } + return SUCCESS; +} + +/*! + \brief wakeup frame filter register pointer reset + \param[in] none + \param[out] none + \retval none +*/ +void enet_wum_filter_register_pointer_reset(void) +{ + ENET_MAC_WUM |= ENET_MAC_WUM_WUFFRPR; +} + +/*! + \brief set the remote wakeup frame registers + \param[in] pdata: pointer to buffer data which is written to remote wakeup frame registers (8 words total) + \param[out] none + \retval none +*/ +void enet_wum_filter_config(uint32_t pdata[]) +{ + uint32_t num = 0U; + + /* configure ENET_MAC_RWFF register */ + for(num = 0U; num < ETH_WAKEUP_REGISTER_LENGTH; num++){ + ENET_MAC_RWFF = pdata[num]; + } +} + +/*! + \brief enable wakeup management features + \param[in] feature: one or more parameters can be selected which are shown as below + \arg ENET_WUM_POWER_DOWN: power down mode + \arg ENET_WUM_MAGIC_PACKET_FRAME: enable a wakeup event due to magic packet reception + \arg ENET_WUM_WAKE_UP_FRAME: enable a wakeup event due to wakeup frame reception + \arg ENET_WUM_GLOBAL_UNICAST: any received unicast frame passed filter is considered to be a wakeup frame + \param[out] none + \retval none +*/ +void enet_wum_feature_enable(uint32_t feature) +{ + ENET_MAC_WUM |= feature; +} + +/*! + \brief disable wakeup management features + \param[in] feature: one or more parameters can be selected which are shown as below + \arg ENET_WUM_MAGIC_PACKET_FRAME: enable a wakeup event due to magic packet reception + \arg ENET_WUM_WAKE_UP_FRAME: enable a wakeup event due to wakeup frame reception + \arg ENET_WUM_GLOBAL_UNICAST: any received unicast frame passed filter is considered to be a wakeup frame + \param[out] none + \retval none +*/ +void enet_wum_feature_disable(uint32_t feature) +{ + ENET_MAC_WUM &= (~feature); +} + +/*! + \brief reset the MAC statistics counters + \param[in] none + \param[out] none + \retval none +*/ +void enet_msc_counters_reset(void) +{ + /* reset all counters */ + ENET_MSC_CTL |= ENET_MSC_CTL_CTR; +} + +/*! + \brief enable the MAC statistics counter features + \param[in] feature: one or more parameters can be selected which are shown as below + \arg ENET_MSC_COUNTER_STOP_ROLLOVER: counter stop rollover + \arg ENET_MSC_RESET_ON_READ: reset on read + \arg ENET_MSC_COUNTERS_FREEZE: MSC counter freeze + \param[out] none + \retval none +*/ +void enet_msc_feature_enable(uint32_t feature) +{ + ENET_MSC_CTL |= feature; +} + +/*! + \brief disable the MAC statistics counter features + \param[in] feature: one or more parameters can be selected which are shown as below + \arg ENET_MSC_COUNTER_STOP_ROLLOVER: counter stop rollover + \arg ENET_MSC_RESET_ON_READ: reset on read + \arg ENET_MSC_COUNTERS_FREEZE: MSC counter freeze + \param[out] none + \retval none +*/ +void enet_msc_feature_disable(uint32_t feature) +{ + ENET_MSC_CTL &= (~feature); +} + +/*! + \brief get MAC statistics counter + \param[in] counter: MSC counters which is selected, refer to enet_msc_counter_enum, + only one parameter can be selected which is shown as below + \arg ENET_MSC_TX_SCCNT: MSC transmitted good frames after a single collision counter + \arg ENET_MSC_TX_MSCCNT: MSC transmitted good frames after more than a single collision counter + \arg ENET_MSC_TX_TGFCNT: MSC transmitted good frames counter + \arg ENET_MSC_RX_RFCECNT: MSC received frames with CRC error counter + \arg ENET_MSC_RX_RFAECNT: MSC received frames with alignment error counter + \arg ENET_MSC_RX_RGUFCNT: MSC received good unicast frames counter + \param[out] none + \retval the MSC counter value +*/ +uint32_t enet_msc_counters_get(enet_msc_counter_enum counter) +{ + uint32_t reval; + + reval = REG32((ENET + (uint32_t)counter)); + + return reval; +} + +/*! + \brief change subsecond to nanosecond + \param[in] subsecond: subsecond value + \param[out] none + \retval the nanosecond value +*/ +uint32_t enet_ptp_subsecond_2_nanosecond(uint32_t subsecond) +{ + uint64_t val = subsecond * 1000000000Ull; + val >>= 31; + return (uint32_t)val; +} + +/*! + \brief change nanosecond to subsecond + \param[in] nanosecond: nanosecond value + \param[out] none + \retval the subsecond value +*/ +uint32_t enet_ptp_nanosecond_2_subsecond(uint32_t nanosecond) +{ + uint64_t val = nanosecond * 0x80000000Ull; + val /= 1000000000U; + return (uint32_t)val; +} + +/*! + \brief enable the PTP features + \param[in] feature: the feature of ENET PTP mode + one or more parameters can be selected which are shown as below + \arg ENET_RXTX_TIMESTAMP: timestamp function for transmit and receive frames + \arg ENET_PTP_TIMESTAMP_INT: timestamp interrupt trigger + \param[out] none + \retval none +*/ +void enet_ptp_feature_enable(uint32_t feature) +{ + ENET_PTP_TSCTL |= feature; +} + +/*! + \brief disable the PTP features + \param[in] feature: the feature of ENET PTP mode + one or more parameters can be selected which are shown as below + \arg ENET_RXTX_TIMESTAMP: timestamp function for transmit and receive frames + \arg ENET_PTP_TIMESTAMP_INT: timestamp interrupt trigger + \param[out] none + \retval none +*/ +void enet_ptp_feature_disable(uint32_t feature) +{ + ENET_PTP_TSCTL &= ~feature; +} + +/*! + \brief configure the PTP timestamp function + \param[in] func: only one parameter can be selected which is shown as below + \arg ENET_PTP_ADDEND_UPDATE: addend register update + \arg ENET_PTP_SYSTIME_UPDATE: timestamp update + \arg ENET_PTP_SYSTIME_INIT: timestamp initialize + \arg ENET_PTP_FINEMODE: the system timestamp uses the fine method for updating + \arg ENET_PTP_COARSEMODE: the system timestamp uses the coarse method for updating + \param[out] none + \retval ErrStatus: SUCCESS or ERROR +*/ + +ErrStatus enet_ptp_timestamp_function_config(enet_ptp_function_enum func) +{ + uint32_t temp_config = 0U, temp_state = 0U; + uint32_t timeout = 0U; + ErrStatus enet_state = SUCCESS; + + switch(func){ + case ENET_PTP_ADDEND_UPDATE: + /* this bit must be read as zero before application set it */ + do{ + temp_state = ENET_PTP_TSCTL & ENET_PTP_TSCTL_TMSARU; + timeout++; + }while((RESET != temp_state) && (timeout < ENET_DELAY_TO)); + /* return ERROR due to timeout */ + if(ENET_DELAY_TO == timeout){ + enet_state = ERROR; + }else{ + ENET_PTP_TSCTL |= ENET_PTP_TSCTL_TMSARU; + } + break; + case ENET_PTP_SYSTIME_UPDATE: + /* both the TMSSTU and TMSSTI bits must be read as zero before application set this bit */ + do{ + temp_state = ENET_PTP_TSCTL & (ENET_PTP_TSCTL_TMSSTU | ENET_PTP_TSCTL_TMSSTI); + timeout++; + }while((RESET != temp_state) && (timeout < ENET_DELAY_TO)); + /* return ERROR due to timeout */ + if(ENET_DELAY_TO == timeout){ + enet_state = ERROR; + }else{ + ENET_PTP_TSCTL |= ENET_PTP_TSCTL_TMSSTU; + } + break; + case ENET_PTP_SYSTIME_INIT: + /* this bit must be read as zero before application set it */ + do{ + temp_state = ENET_PTP_TSCTL & ENET_PTP_TSCTL_TMSSTI; + timeout++; + }while((RESET != temp_state) && (timeout < ENET_DELAY_TO)); + /* return ERROR due to timeout */ + if(ENET_DELAY_TO == timeout){ + enet_state = ERROR; + }else{ + ENET_PTP_TSCTL |= ENET_PTP_TSCTL_TMSSTI; + } + break; + default: + temp_config = (uint32_t)func & (~BIT(31)); + if(RESET != ((uint32_t)func & BIT(31))){ + ENET_PTP_TSCTL |= temp_config; + }else{ + ENET_PTP_TSCTL &= ~temp_config; + } + break; + } + + return enet_state; +} + +/*! + \brief configure system time subsecond increment value + \param[in] subsecond: the value will be added to the subsecond value of system time, + this value must be between 0 and 0xFF + \param[out] none + \retval none +*/ +void enet_ptp_subsecond_increment_config(uint32_t subsecond) +{ + ENET_PTP_SSINC = PTP_SSINC_STMSSI(subsecond); +} + +/*! + \brief adjusting the clock frequency only in fine update mode + \param[in] add: the value will be added to the accumulator register to achieve time synchronization + \param[out] none + \retval none +*/ +void enet_ptp_timestamp_addend_config(uint32_t add) +{ + ENET_PTP_TSADDEND = add; +} + +/*! + \brief initialize or add/subtract to second of the system time + \param[in] sign: timestamp update positive or negative sign, + only one parameter can be selected which is shown as below + \arg ENET_PTP_ADD_TO_TIME: timestamp update value is added to system time + \arg ENET_PTP_SUBSTRACT_FROM_TIME: timestamp update value is subtracted from system time + \param[in] second: initializing or adding/subtracting to second of the system time + \param[in] subsecond: the current subsecond of the system time + with 0.46 ns accuracy if required accuracy is 20 ns + \param[out] none + \retval none +*/ +void enet_ptp_timestamp_update_config(uint32_t sign, uint32_t second, uint32_t subsecond) +{ + ENET_PTP_TSUH = second; + ENET_PTP_TSUL = sign | PTP_TSUL_TMSUSS(subsecond); +} + +/*! + \brief configure the expected target time + \param[in] second: the expected target second time + \param[in] nanosecond: the expected target nanosecond time (signed) + \param[out] none + \retval none +*/ +void enet_ptp_expected_time_config(uint32_t second, uint32_t nanosecond) +{ + ENET_PTP_ETH = second; + ENET_PTP_ETL = nanosecond; +} + +/*! + \brief get the current system time + \param[in] none + \param[out] systime_struct: pointer to a enet_ptp_systime_struct structure which contains + parameters of PTP system time + members of the structure and the member values are shown as below: + second: 0x0 - 0xFFFF FFFF + nanosecond: 0x0 - 0x7FFF FFFF * 10^9 / 2^31 + sign: ENET_PTP_TIME_POSITIVE, ENET_PTP_TIME_NEGATIVE + \retval none +*/ +void enet_ptp_system_time_get(enet_ptp_systime_struct *systime_struct) +{ + uint32_t temp_sec = 0U, temp_subs = 0U; + + /* get the value of sysytem time registers */ + temp_sec = (uint32_t)ENET_PTP_TSH; + temp_subs = (uint32_t)ENET_PTP_TSL; + + /* get sysytem time and construct the enet_ptp_systime_struct structure */ + systime_struct->second = temp_sec; + systime_struct->nanosecond = GET_PTP_TSL_STMSS(temp_subs); + systime_struct->nanosecond = enet_ptp_subsecond_2_nanosecond(systime_struct->nanosecond); + systime_struct->sign = GET_PTP_TSL_STS(temp_subs); +} + +/*! + \brief configure and start PTP timestamp counter + \param[in] updatemethod: method for updating + \arg ENET_PTP_FINEMODE: fine correction method + \arg ENET_PTP_COARSEMODE: coarse correction method + \param[in] init_sec: second value for initializing system time + \param[in] init_subsec: subsecond value for initializing system time + \param[in] carry_cfg: the value to be added to the accumulator register (in fine method is used) + \param[in] accuracy_cfg: the value to be added to the subsecond value of system time + \param[out] none + \retval none +*/ +void enet_ptp_start(int32_t updatemethod, uint32_t init_sec, uint32_t init_subsec, uint32_t carry_cfg, uint32_t accuracy_cfg) +{ + /* mask the timestamp trigger interrupt */ + enet_interrupt_disable(ENET_MAC_INT_TMSTIM); + + /* enable timestamp */ + enet_ptp_feature_enable(ENET_RXTX_TIMESTAMP); + + /* configure system time subsecond increment based on the PTP clock frequency */ + enet_ptp_subsecond_increment_config(accuracy_cfg); + + if(ENET_PTP_FINEMODE == updatemethod){ + /* fine correction method: configure the timestamp addend, then update */ + enet_ptp_timestamp_addend_config(carry_cfg); + enet_ptp_timestamp_function_config(ENET_PTP_ADDEND_UPDATE); + /* wait until update is completed */ + while(SET == enet_ptp_flag_get((uint32_t)ENET_PTP_ADDEND_UPDATE)){ + } + } + + /* choose the fine correction method */ + enet_ptp_timestamp_function_config((enet_ptp_function_enum)updatemethod); + + /* initialize the system time */ + enet_ptp_timestamp_update_config(ENET_PTP_ADD_TO_TIME, init_sec, init_subsec); + enet_ptp_timestamp_function_config(ENET_PTP_SYSTIME_INIT); +} + +/*! + \brief adjust frequency in fine method by configure addend register + \param[in] carry_cfg: the value to be added to the accumulator register + \param[out] none + \retval none +*/ +void enet_ptp_finecorrection_adjfreq(int32_t carry_cfg) +{ + /* re-configure the timestamp addend, then update */ + enet_ptp_timestamp_addend_config((uint32_t)carry_cfg); + enet_ptp_timestamp_function_config(ENET_PTP_ADDEND_UPDATE); +} + +/*! + \brief update system time in coarse method + \param[in] systime_struct: pointer to a enet_ptp_systime_struct structure which contains + parameters of PTP system time + members of the structure and the member values are shown as below: + second: 0x0 - 0xFFFF FFFF + nanosecond: 0x0 - 0x7FFF FFFF * 10^9 / 2^31 + sign: ENET_PTP_TIME_POSITIVE, ENET_PTP_TIME_NEGATIVE + \param[out] none + \retval none +*/ +void enet_ptp_coarsecorrection_systime_update(enet_ptp_systime_struct *systime_struct) +{ + uint32_t subsecond_val; + uint32_t carry_cfg; + + subsecond_val = enet_ptp_nanosecond_2_subsecond(systime_struct->nanosecond); + + /* save the carry_cfg value */ + carry_cfg = ENET_PTP_TSADDEND_TMSA; + + /* update the system time */ + enet_ptp_timestamp_update_config(systime_struct->sign, systime_struct->second, subsecond_val); + enet_ptp_timestamp_function_config(ENET_PTP_SYSTIME_UPDATE); + + /* wait until the update is completed */ + while(SET == enet_ptp_flag_get((uint32_t)ENET_PTP_SYSTIME_UPDATE)){ + } + + /* write back the carry_cfg value, then update */ + enet_ptp_timestamp_addend_config(carry_cfg); + enet_ptp_timestamp_function_config(ENET_PTP_ADDEND_UPDATE); +} + +/*! + \brief set system time in fine method + \param[in] systime_struct: pointer to a enet_ptp_systime_struct structure which contains + parameters of PTP system time + members of the structure and the member values are shown as below: + second: 0x0 - 0xFFFF FFFF + nanosecond: 0x0 - 0x7FFF FFFF * 10^9 / 2^31 + sign: ENET_PTP_TIME_POSITIVE, ENET_PTP_TIME_NEGATIVE + \param[out] none + \retval none +*/ +void enet_ptp_finecorrection_settime(enet_ptp_systime_struct * systime_struct) +{ + uint32_t subsecond_val; + + subsecond_val = enet_ptp_nanosecond_2_subsecond(systime_struct->nanosecond); + + /* initialize the system time */ + enet_ptp_timestamp_update_config(systime_struct->sign, systime_struct->second, subsecond_val); + enet_ptp_timestamp_function_config(ENET_PTP_SYSTIME_INIT); + + /* wait until the system time initialzation finished */ + while(SET == enet_ptp_flag_get((uint32_t)ENET_PTP_SYSTIME_INIT)){ + } +} + +/*! + \brief get the ptp flag status + \param[in] flag: ptp flag status to be checked + \arg ENET_PTP_ADDEND_UPDATE: addend register update + \arg ENET_PTP_SYSTIME_UPDATE: timestamp update + \arg ENET_PTP_SYSTIME_INIT: timestamp initialize + \param[out] none + \retval FlagStatus: SET or RESET +*/ +FlagStatus enet_ptp_flag_get(uint32_t flag) +{ + FlagStatus bitstatus = RESET; + + if ((uint32_t)RESET != (ENET_PTP_TSCTL & flag)){ + bitstatus = SET; + } + + return bitstatus; +} + +/*! + \brief reset the ENET initpara struct, call it before using enet_initpara_config() + \param[in] none + \param[out] none + \retval none +*/ +void enet_initpara_reset(void) +{ + enet_initpara.option_enable = 0U; + enet_initpara.forward_frame = 0U; + enet_initpara.dmabus_mode = 0U; + enet_initpara.dma_maxburst = 0U; + enet_initpara.dma_arbitration = 0U; + enet_initpara.store_forward_mode = 0U; + enet_initpara.dma_function = 0U; + enet_initpara.vlan_config = 0U; + enet_initpara.flow_control = 0U; + enet_initpara.hashtable_high = 0U; + enet_initpara.hashtable_low = 0U; + enet_initpara.framesfilter_mode = 0U; + enet_initpara.halfduplex_param = 0U; + enet_initpara.timer_config = 0U; + enet_initpara.interframegap = 0U; +} + +/*! + \brief initialize ENET peripheral with generally concerned parameters, call it by enet_init() + \param[in] none + \param[out] none + \retval none +*/ +static void enet_default_init(void) +{ + uint32_t reg_value = 0U; + + /* MAC */ + /* configure ENET_MAC_CFG register */ + reg_value = ENET_MAC_CFG; + reg_value &= MAC_CFG_MASK; + reg_value |= ENET_WATCHDOG_ENABLE | ENET_JABBER_ENABLE | ENET_INTERFRAMEGAP_96BIT \ + | ENET_SPEEDMODE_10M |ENET_MODE_HALFDUPLEX | ENET_LOOPBACKMODE_DISABLE \ + | ENET_CARRIERSENSE_ENABLE | ENET_RECEIVEOWN_ENABLE \ + | ENET_RETRYTRANSMISSION_ENABLE | ENET_BACKOFFLIMIT_10 \ + | ENET_DEFERRALCHECK_DISABLE \ + | ENET_AUTO_PADCRC_DROP_DISABLE \ + | ENET_CHECKSUMOFFLOAD_DISABLE; + ENET_MAC_CFG = reg_value; + + /* configure ENET_MAC_FRMF register */ + ENET_MAC_FRMF = ENET_SRC_FILTER_DISABLE |ENET_DEST_FILTER_INVERSE_DISABLE \ + |ENET_MULTICAST_FILTER_PERFECT |ENET_UNICAST_FILTER_PERFECT \ + |ENET_PCFRM_PREVENT_ALL |ENET_BROADCASTFRAMES_ENABLE \ + |ENET_PROMISCUOUS_DISABLE |ENET_RX_FILTER_ENABLE; + + /* configure ENET_MAC_HLH, ENET_MAC_HLL register */ + ENET_MAC_HLH = 0x0U; + + ENET_MAC_HLL = 0x0U; + + /* configure ENET_MAC_FCTL, ENET_MAC_FCTH register */ + reg_value = ENET_MAC_FCTL; + reg_value &= MAC_FCTL_MASK; + reg_value |= MAC_FCTL_PTM(0) |ENET_ZERO_QUANTA_PAUSE_DISABLE \ + |ENET_PAUSETIME_MINUS4 |ENET_UNIQUE_PAUSEDETECT \ + |ENET_RX_FLOWCONTROL_DISABLE |ENET_TX_FLOWCONTROL_DISABLE; + ENET_MAC_FCTL = reg_value; + + ENET_MAC_FCTH = ENET_DEACTIVE_THRESHOLD_512BYTES |ENET_ACTIVE_THRESHOLD_1536BYTES; + + /* configure ENET_MAC_VLT register */ + ENET_MAC_VLT = ENET_VLANTAGCOMPARISON_16BIT |MAC_VLT_VLTI(0); + + /* DMA */ + /* configure ENET_DMA_CTL register */ + reg_value = ENET_DMA_CTL; + reg_value &= DMA_CTL_MASK; + reg_value |= ENET_TCPIP_CKSUMERROR_DROP |ENET_RX_MODE_STOREFORWARD \ + |ENET_FLUSH_RXFRAME_ENABLE |ENET_TX_MODE_STOREFORWARD \ + |ENET_TX_THRESHOLD_64BYTES |ENET_RX_THRESHOLD_64BYTES \ + |ENET_FORWARD_ERRFRAMES_DISABLE |ENET_FORWARD_UNDERSZ_GOODFRAMES_DISABLE \ + |ENET_SECONDFRAME_OPT_DISABLE; + ENET_DMA_CTL = reg_value; + + /* configure ENET_DMA_BCTL register */ + reg_value = ENET_DMA_BCTL; + reg_value &= DMA_BCTL_MASK; + reg_value = ENET_ADDRESS_ALIGN_ENABLE |ENET_ARBITRATION_RXTX_2_1 \ + |ENET_RXDP_32BEAT |ENET_PGBL_32BEAT |ENET_RXTX_DIFFERENT_PGBL \ + |ENET_FIXED_BURST_ENABLE; + ENET_DMA_BCTL = reg_value; +} + +#ifndef USE_DELAY +/*! + \brief insert a delay time + \param[in] ncount: specifies the delay time length + \param[out] none + \param[out] none +*/ +static void enet_delay(uint32_t ncount) +{ + __IO uint32_t delay_time = 0U; + + for(delay_time = ncount; delay_time != 0U; delay_time--){ + } +} +#endif /* USE_DELAY */ + +#endif /* GD32F10X_CL */ diff --git a/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_standard_peripheral/Source/gd32f10x_exmc.c b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_standard_peripheral/Source/gd32f10x_exmc.c new file mode 100644 index 0000000000..3a9416d8a8 --- /dev/null +++ b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_standard_peripheral/Source/gd32f10x_exmc.c @@ -0,0 +1,645 @@ +/*! + \file gd32f10x_exmc.c + \brief EXMC driver + + \version 2014-12-26, V1.0.0, firmware for GD32F10x + \version 2017-06-20, V2.0.0, firmware for GD32F10x + \version 2018-07-31, V2.1.0, firmware for GD32F10x + \version 2020-09-30, V2.2.0, firmware for GD32F10x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "gd32f10x_exmc.h" + +/* EXMC bank0 register reset value */ +#define BANK0_SNCTL0_REGION_RESET ((uint32_t)0x000030DBU) +#define BANK0_SNCTL1_2_3_REGION_RESET ((uint32_t)0x000030D2U) +#define BANK0_SNTCFG_RESET ((uint32_t)0x0FFFFFFFU) +#define BANK0_SNWTCFG_RESET ((uint32_t)0x0FFFFFFFU) + +/* EXMC bank1/2 register reset mask*/ +#define BANK1_2_NPCTL_RESET ((uint32_t)0x00000018U) +#define BANK1_2_NPINTEN_RESET ((uint32_t)0x00000040U) +#define BANK1_2_NPCTCFG_RESET ((uint32_t)0xFCFCFCFCU) +#define BANK1_2_NPATCFG_RESET ((uint32_t)0xFCFCFCFCU) + +/* EXMC bank3 register reset mask*/ +#define BANK3_NPCTL_RESET ((uint32_t)0x00000018U) +#define BANK3_NPINTEN_RESET ((uint32_t)0x00000040U) +#define BANK3_NPCTCFG_RESET ((uint32_t)0xFCFCFCFCU) +#define BANK3_NPATCFG_RESET ((uint32_t)0xFCFCFCFCU) +#define BANK3_PIOTCFG3_RESET ((uint32_t)0xFCFCFCFCU) + +/* EXMC register bit offset */ +#define SNCTL_NRMUX_OFFSET ((uint32_t)1U) +#define SNCTL_SBRSTEN_OFFSET ((uint32_t)8U) +#define SNCTL_WRAPEN_OFFSET ((uint32_t)10U) +#define SNCTL_WREN_OFFSET ((uint32_t)12U) +#define SNCTL_NRWTEN_OFFSET ((uint32_t)13U) +#define SNCTL_EXMODEN_OFFSET ((uint32_t)14U) +#define SNCTL_ASYNCWAIT_OFFSET ((uint32_t)15U) + +#define SNTCFG_AHLD_OFFSET ((uint32_t)4U) +#define SNTCFG_DSET_OFFSET ((uint32_t)8U) +#define SNTCFG_BUSLAT_OFFSET ((uint32_t)16U) + +#define SNWTCFG_WAHLD_OFFSET ((uint32_t)4U) +#define SNWTCFG_WDSET_OFFSET ((uint32_t)8U) +#define SNWTCFG_WBUSLAT_OFFSET ((uint32_t)16U) + +#define NPCTL_NDWTEN_OFFSET ((uint32_t)1U) +#define NPCTL_ECCEN_OFFSET ((uint32_t)6U) + +#define NPCTCFG_COMWAIT_OFFSET ((uint32_t)8U) +#define NPCTCFG_COMHLD_OFFSET ((uint32_t)16U) +#define NPCTCFG_COMHIZ_OFFSET ((uint32_t)24U) + +#define NPATCFG_ATTWAIT_OFFSET ((uint32_t)8U) +#define NPATCFG_ATTHLD_OFFSET ((uint32_t)16U) +#define NPATCFG_ATTHIZ_OFFSET ((uint32_t)24U) + +#define PIOTCFG_IOWAIT_OFFSET ((uint32_t)8U) +#define PIOTCFG_IOHLD_OFFSET ((uint32_t)16U) +#define PIOTCFG_IOHIZ_OFFSET ((uint32_t)24U) + +#define INTEN_INTS_OFFSET ((uint32_t)3U) + +/*! + \brief deinitialize EXMC NOR/SRAM region + \param[in] norsram_region: select the region of bank0 + \arg EXMC_BANK0_NORSRAM_REGIONx(x=0..3) + \param[out] none + \retval none +*/ +void exmc_norsram_deinit(uint32_t norsram_region) +{ + /* reset the registers */ + if(EXMC_BANK0_NORSRAM_REGION0 == norsram_region){ + EXMC_SNCTL(norsram_region) = BANK0_SNCTL0_REGION_RESET; + }else{ + EXMC_SNCTL(norsram_region) = BANK0_SNCTL1_2_3_REGION_RESET; + } + + EXMC_SNTCFG(norsram_region) = BANK0_SNTCFG_RESET; + EXMC_SNWTCFG(norsram_region) = BANK0_SNWTCFG_RESET; +} + +/*! + \brief initialize EXMC NOR/SRAM region + \param[in] exmc_norsram_parameter_struct: configure the EXMC NOR/SRAM parameter + norsram_region: EXMC_BANK0_NORSRAM_REGIONx,x=0..3 + write_mode: EXMC_ASYN_WRITE,EXMC_SYN_WRITE + extended_mode: ENABLE or DISABLE + asyn_wait: ENABLE or DISABLE + nwait_signal: ENABLE or DISABLE + memory_write: ENABLE or DISABLE + nwait_config: EXMC_NWAIT_CONFIG_BEFORE,EXMC_NWAIT_CONFIG_DURING + wrap_burst_mode: ENABLE or DISABLE + nwait_polarity: EXMC_NWAIT_POLARITY_LOW,EXMC_NWAIT_POLARITY_HIGH + burst_mode: ENABLE or DISABLE + databus_width: EXMC_NOR_DATABUS_WIDTH_8B,EXMC_NOR_DATABUS_WIDTH_16B + memory_type: EXMC_MEMORY_TYPE_SRAM,EXMC_MEMORY_TYPE_PSRAM,EXMC_MEMORY_TYPE_NOR + address_data_mux: ENABLE or DISABLE + read_write_timing: struct exmc_norsram_timing_parameter_struct set the time + write_timing: struct exmc_norsram_timing_parameter_struct set the time + \param[out] none + \retval none +*/ +void exmc_norsram_init(exmc_norsram_parameter_struct* exmc_norsram_init_struct) +{ + uint32_t snctl = 0x00000000U, sntcfg = 0x00000000U, snwtcfg = 0x00000000U; + + /* get the register value */ + snctl = EXMC_SNCTL(exmc_norsram_init_struct->norsram_region); + + /* clear relative bits */ + snctl &= ((uint32_t)~(EXMC_SNCTL_NREN | EXMC_SNCTL_NRTP | EXMC_SNCTL_NRW | EXMC_SNCTL_SBRSTEN | + EXMC_SNCTL_NRWTPOL | EXMC_SNCTL_WRAPEN | EXMC_SNCTL_NRWTCFG | EXMC_SNCTL_WREN | + EXMC_SNCTL_NRWTEN | EXMC_SNCTL_EXMODEN | EXMC_SNCTL_ASYNCWAIT | EXMC_SNCTL_SYNCWR | + EXMC_SNCTL_NRMUX )); + + snctl |= (uint32_t)(exmc_norsram_init_struct->address_data_mux << SNCTL_NRMUX_OFFSET) | + exmc_norsram_init_struct->memory_type | + exmc_norsram_init_struct->databus_width | + (exmc_norsram_init_struct->burst_mode << SNCTL_SBRSTEN_OFFSET) | + exmc_norsram_init_struct->nwait_polarity | + (exmc_norsram_init_struct->wrap_burst_mode << SNCTL_WRAPEN_OFFSET) | + exmc_norsram_init_struct->nwait_config | + (exmc_norsram_init_struct->memory_write << SNCTL_WREN_OFFSET) | + (exmc_norsram_init_struct->nwait_signal << SNCTL_NRWTEN_OFFSET) | + (exmc_norsram_init_struct->extended_mode << SNCTL_EXMODEN_OFFSET) | + (exmc_norsram_init_struct->asyn_wait << SNCTL_ASYNCWAIT_OFFSET) | + exmc_norsram_init_struct->write_mode; + + sntcfg = (uint32_t)((exmc_norsram_init_struct->read_write_timing->asyn_address_setuptime - 1U ) & EXMC_SNTCFG_ASET )| + (((exmc_norsram_init_struct->read_write_timing->asyn_address_holdtime - 1U ) << SNTCFG_AHLD_OFFSET ) & EXMC_SNTCFG_AHLD ) | + (((exmc_norsram_init_struct->read_write_timing->asyn_data_setuptime - 1U ) << SNTCFG_DSET_OFFSET ) & EXMC_SNTCFG_DSET ) | + (((exmc_norsram_init_struct->read_write_timing->bus_latency - 1U ) << SNTCFG_BUSLAT_OFFSET ) & EXMC_SNTCFG_BUSLAT )| + exmc_norsram_init_struct->read_write_timing->syn_clk_division | + exmc_norsram_init_struct->read_write_timing->syn_data_latency | + exmc_norsram_init_struct->read_write_timing->asyn_access_mode; + + /* nor flash access enable */ + if(EXMC_MEMORY_TYPE_NOR == exmc_norsram_init_struct->memory_type){ + snctl |= (uint32_t)EXMC_SNCTL_NREN; + } + + /* extended mode configure */ + if(ENABLE == exmc_norsram_init_struct->extended_mode){ + snwtcfg = (uint32_t)(((exmc_norsram_init_struct->write_timing->asyn_address_setuptime - 1U) & EXMC_SNWTCFG_WASET) | + (((exmc_norsram_init_struct->write_timing->asyn_address_holdtime - 1U) << SNTCFG_AHLD_OFFSET ) & EXMC_SNWTCFG_WAHLD)| + (((exmc_norsram_init_struct->write_timing->asyn_data_setuptime - 1U) << SNTCFG_DSET_OFFSET) & EXMC_SNWTCFG_WDSET) | + exmc_norsram_init_struct->write_timing->asyn_access_mode); + }else{ + snwtcfg = BANK0_SNWTCFG_RESET; + } + + /* configure the registers */ + EXMC_SNCTL(exmc_norsram_init_struct->norsram_region) = snctl; + EXMC_SNTCFG(exmc_norsram_init_struct->norsram_region) = sntcfg; + EXMC_SNWTCFG(exmc_norsram_init_struct->norsram_region) = snwtcfg; +} + +/*! + \brief initialize the struct exmc_norsram_parameter_struct + \param[in] none + \param[out] exmc_norsram_init_struct: the initialized struct exmc_norsram_parameter_struct pointer + \retval none +*/ +void exmc_norsram_struct_para_init(exmc_norsram_parameter_struct* exmc_norsram_init_struct) +{ + /* configure the structure with default value */ + exmc_norsram_init_struct->norsram_region = EXMC_BANK0_NORSRAM_REGION0; + exmc_norsram_init_struct->address_data_mux = ENABLE; + exmc_norsram_init_struct->memory_type = EXMC_MEMORY_TYPE_SRAM; + exmc_norsram_init_struct->databus_width = EXMC_NOR_DATABUS_WIDTH_8B; + exmc_norsram_init_struct->burst_mode = DISABLE; + exmc_norsram_init_struct->nwait_polarity = EXMC_NWAIT_POLARITY_LOW; + exmc_norsram_init_struct->wrap_burst_mode = DISABLE; + exmc_norsram_init_struct->nwait_config = EXMC_NWAIT_CONFIG_BEFORE; + exmc_norsram_init_struct->memory_write = ENABLE; + exmc_norsram_init_struct->nwait_signal = ENABLE; + exmc_norsram_init_struct->extended_mode = DISABLE; + exmc_norsram_init_struct->asyn_wait = DISABLE; + exmc_norsram_init_struct->write_mode = EXMC_ASYN_WRITE; + + /* read/write timing configure */ + exmc_norsram_init_struct->read_write_timing->asyn_address_setuptime = 0xFU; + exmc_norsram_init_struct->read_write_timing->asyn_address_holdtime = 0xFU; + exmc_norsram_init_struct->read_write_timing->asyn_data_setuptime = 0xFFU; + exmc_norsram_init_struct->read_write_timing->bus_latency = 0xFU; + exmc_norsram_init_struct->read_write_timing->syn_clk_division = EXMC_SYN_CLOCK_RATIO_16_CLK; + exmc_norsram_init_struct->read_write_timing->syn_data_latency = EXMC_DATALAT_17_CLK; + exmc_norsram_init_struct->read_write_timing->asyn_access_mode = EXMC_ACCESS_MODE_A; + + /* write timing configure, when extended mode is used */ + exmc_norsram_init_struct->write_timing->asyn_address_setuptime = 0xFU; + exmc_norsram_init_struct->write_timing->asyn_address_holdtime = 0xFU; + exmc_norsram_init_struct->write_timing->asyn_data_setuptime = 0xFFU; + exmc_norsram_init_struct->write_timing->bus_latency = 0xFU; + exmc_norsram_init_struct->write_timing->asyn_access_mode = EXMC_ACCESS_MODE_A; +} + +/*! + \brief enable EXMC NOR/PSRAM bank region + \param[in] norsram_region: specifie the region of NOR/PSRAM bank + \arg EXMC_BANK0_NORSRAM_REGIONx(x=0..3) + \param[out] none + \retval none +*/ +void exmc_norsram_enable(uint32_t norsram_region) +{ + EXMC_SNCTL(norsram_region) |= (uint32_t)EXMC_SNCTL_NRBKEN; +} + +/*! + \brief disable EXMC NOR/PSRAM bank region + \param[in] norsram_region: specifie the region of NOR/PSRAM Bank + \arg EXMC_BANK0_NORSRAM_REGIONx(x=0..3) + \param[out] none + \retval none +*/ +void exmc_norsram_disable(uint32_t norsram_region) +{ + EXMC_SNCTL(norsram_region) &= ~(uint32_t)EXMC_SNCTL_NRBKEN; +} + +/*! + \brief deinitialize EXMC NAND bank + \param[in] nand_bank: select the bank of NAND + \arg EXMC_BANKx_NAND(x=1..2) + \param[out] none + \retval none +*/ +void exmc_nand_deinit(uint32_t nand_bank) +{ + /* EXMC_BANK1_NAND or EXMC_BANK2_NAND */ + EXMC_NPCTL(nand_bank) = BANK1_2_NPCTL_RESET; + EXMC_NPINTEN(nand_bank) = BANK1_2_NPINTEN_RESET; + EXMC_NPCTCFG(nand_bank) = BANK1_2_NPCTCFG_RESET; + EXMC_NPATCFG(nand_bank) = BANK1_2_NPATCFG_RESET; +} + +/*! + \brief initialize EXMC NAND bank + \param[in] exmc_nand_parameter_struct: configure the EXMC NAND parameter + nand_bank: EXMC_BANK1_NAND,EXMC_BANK2_NAND + ecc_size: EXMC_ECC_SIZE_xBYTES,x=256,512,1024,2048,4096 + atr_latency: EXMC_ALE_RE_DELAY_x_HCLK,x=1..16 + ctr_latency: EXMC_CLE_RE_DELAY_x_HCLK,x=1..16 + ecc_logic: ENABLE or DISABLE + databus_width: EXMC_NAND_DATABUS_WIDTH_8B,EXMC_NAND_DATABUS_WIDTH_16B + wait_feature: ENABLE or DISABLE + common_space_timing: struct exmc_nand_pccard_timing_parameter_struct set the time + attribute_space_timing: struct exmc_nand_pccard_timing_parameter_struct set the time + \param[out] none + \retval none +*/ +void exmc_nand_init(exmc_nand_parameter_struct* exmc_nand_init_struct) +{ + uint32_t npctl = 0x00000000U, npctcfg = 0x00000000U, npatcfg = 0x00000000U; + + npctl = (uint32_t)(exmc_nand_init_struct->wait_feature << NPCTL_NDWTEN_OFFSET)| + EXMC_NPCTL_NDTP | + exmc_nand_init_struct->databus_width | + (exmc_nand_init_struct->ecc_logic << NPCTL_ECCEN_OFFSET)| + exmc_nand_init_struct->ecc_size | + exmc_nand_init_struct->ctr_latency | + exmc_nand_init_struct->atr_latency; + + npctcfg = (uint32_t)((exmc_nand_init_struct->common_space_timing->setuptime - 1U) & EXMC_NPCTCFG_COMSET ) | + (((exmc_nand_init_struct->common_space_timing->waittime - 1U) << NPCTCFG_COMWAIT_OFFSET) & EXMC_NPCTCFG_COMWAIT ) | + ((exmc_nand_init_struct->common_space_timing->holdtime << NPCTCFG_COMHLD_OFFSET) & EXMC_NPCTCFG_COMHLD ) | + (((exmc_nand_init_struct->common_space_timing->databus_hiztime - 1U) << NPCTCFG_COMHIZ_OFFSET) & EXMC_NPCTCFG_COMHIZ ); + + npatcfg = (uint32_t)((exmc_nand_init_struct->attribute_space_timing->setuptime - 1U) & EXMC_NPATCFG_ATTSET ) | + (((exmc_nand_init_struct->attribute_space_timing->waittime - 1U) << NPATCFG_ATTWAIT_OFFSET) & EXMC_NPATCFG_ATTWAIT ) | + ((exmc_nand_init_struct->attribute_space_timing->holdtime << NPATCFG_ATTHLD_OFFSET) & EXMC_NPATCFG_ATTHLD ) | + (((exmc_nand_init_struct->attribute_space_timing->databus_hiztime -1U) << NPATCFG_ATTHIZ_OFFSET) & EXMC_NPATCFG_ATTHIZ ); + + /* EXMC_BANK1_NAND or EXMC_BANK2_NAND initialize */ + EXMC_NPCTL(exmc_nand_init_struct->nand_bank) = npctl; + EXMC_NPCTCFG(exmc_nand_init_struct->nand_bank) = npctcfg; + EXMC_NPATCFG(exmc_nand_init_struct->nand_bank) = npatcfg; +} + +/*! + \brief initialize the struct exmc_nand_init_struct + \param[in] none + \param[out] the initialized struct exmc_nand_init_struct pointer + \retval none +*/ +void exmc_nand_struct_para_init(exmc_nand_parameter_struct* exmc_nand_init_struct) +{ + /* configure the structure with default value */ + exmc_nand_init_struct->nand_bank = EXMC_BANK1_NAND; + exmc_nand_init_struct->wait_feature = DISABLE; + exmc_nand_init_struct->databus_width = EXMC_NAND_DATABUS_WIDTH_8B; + exmc_nand_init_struct->ecc_logic = DISABLE; + exmc_nand_init_struct->ecc_size = EXMC_ECC_SIZE_256BYTES; + exmc_nand_init_struct->ctr_latency = 0x0U; + exmc_nand_init_struct->atr_latency = 0x0U; + exmc_nand_init_struct->common_space_timing->setuptime = 0xFCU; + exmc_nand_init_struct->common_space_timing->waittime = 0xFCU; + exmc_nand_init_struct->common_space_timing->holdtime = 0xFCU; + exmc_nand_init_struct->common_space_timing->databus_hiztime = 0xFCU; + exmc_nand_init_struct->attribute_space_timing->setuptime = 0xFCU; + exmc_nand_init_struct->attribute_space_timing->waittime = 0xFCU; + exmc_nand_init_struct->attribute_space_timing->holdtime = 0xFCU; + exmc_nand_init_struct->attribute_space_timing->databus_hiztime = 0xFCU; +} + +/*! + \brief enable NAND bank + \param[in] nand_bank: specifie the NAND bank + \arg EXMC_BANKx_NAND(x=1,2) + \param[out] none + \retval none +*/ +void exmc_nand_enable(uint32_t nand_bank) +{ + EXMC_NPCTL(nand_bank) |= EXMC_NPCTL_NDBKEN; +} + +/*! + \brief disable NAND bank + \param[in] nand_bank: specifie the NAND bank + \arg EXMC_BANKx_NAND(x=1,2) + \param[out] none + \retval none +*/ +void exmc_nand_disable(uint32_t nand_bank) +{ + EXMC_NPCTL(nand_bank) &= ~EXMC_NPCTL_NDBKEN; +} + +/*! + \brief enable or disable the EXMC NAND ECC function + \param[in] nand_bank: specifie the NAND bank + \arg EXMC_BANKx_NAND(x=1,2) + \param[in] newvalue: ENABLE or DISABLE + \param[out] none + \retval none +*/ +void exmc_nand_ecc_config(uint32_t nand_bank, ControlStatus newvalue) +{ + if (ENABLE == newvalue){ + /* enable the selected NAND bank ECC function */ + EXMC_NPCTL(nand_bank) |= EXMC_NPCTL_ECCEN; + }else{ + /* disable the selected NAND bank ECC function */ + EXMC_NPCTL(nand_bank) &= ~EXMC_NPCTL_ECCEN; + } +} + +/*! + \brief get the EXMC ECC value + \param[in] nand_bank: specifie the NAND bank + \arg EXMC_BANKx_NAND(x=1,2) + \param[out] none + \retval the error correction code(ECC) value +*/ +uint32_t exmc_ecc_get(uint32_t nand_bank) +{ + return (EXMC_NECC(nand_bank)); +} + +/*! + \brief deinitialize EXMC PC card bank + \param[in] none + \param[out] none + \retval none +*/ +void exmc_pccard_deinit(void) +{ + /* EXMC_BANK3_PCCARD */ + EXMC_NPCTL3 = BANK3_NPCTL_RESET; + EXMC_NPINTEN3 = BANK3_NPINTEN_RESET; + EXMC_NPCTCFG3 = BANK3_NPCTCFG_RESET; + EXMC_NPATCFG3 = BANK3_NPATCFG_RESET; + EXMC_PIOTCFG3 = BANK3_PIOTCFG3_RESET; +} + +/*! + \brief initialize EXMC PC card bank + \param[in] exmc_pccard_parameter_struct: configure the EXMC NAND parameter + atr_latency: EXMC_ALE_RE_DELAY_x_HCLK,x=1..16 + ctr_latency: EXMC_CLE_RE_DELAY_x_HCLK,x=1..16 + wait_feature: ENABLE or DISABLE + common_space_timing: struct exmc_nand_pccard_timing_parameter_struct set the time + attribute_space_timing: struct exmc_nand_pccard_timing_parameter_struct set the time + io_space_timing: exmc_nand_pccard_timing_parameter_struct set the time + \param[out] none + \retval none +*/ +void exmc_pccard_init(exmc_pccard_parameter_struct* exmc_pccard_init_struct) +{ + /* configure the EXMC bank3 PC card control register */ + EXMC_NPCTL3 = (uint32_t)(exmc_pccard_init_struct->wait_feature << NPCTL_NDWTEN_OFFSET) | + EXMC_NAND_DATABUS_WIDTH_16B | + exmc_pccard_init_struct->ctr_latency | + exmc_pccard_init_struct->atr_latency ; + + /* configure the EXMC bank3 PC card common space timing configuration register */ + EXMC_NPCTCFG3 = (uint32_t)((exmc_pccard_init_struct->common_space_timing->setuptime - 1U)& EXMC_NPCTCFG_COMSET ) | + (((exmc_pccard_init_struct->common_space_timing->waittime - 1U) << NPCTCFG_COMWAIT_OFFSET) & EXMC_NPCTCFG_COMWAIT ) | + ((exmc_pccard_init_struct->common_space_timing->holdtime << NPCTCFG_COMHLD_OFFSET) & EXMC_NPCTCFG_COMHLD ) | + (((exmc_pccard_init_struct->common_space_timing->databus_hiztime - 1U) << NPCTCFG_COMHIZ_OFFSET) & EXMC_NPCTCFG_COMHIZ ); + + /* configure the EXMC bank3 PC card attribute space timing configuration register */ + EXMC_NPATCFG3 = (uint32_t)((exmc_pccard_init_struct->attribute_space_timing->setuptime - 1U) & EXMC_NPATCFG_ATTSET ) | + (((exmc_pccard_init_struct->attribute_space_timing->waittime - 1U) << NPATCFG_ATTWAIT_OFFSET) & EXMC_NPATCFG_ATTWAIT ) | + ((exmc_pccard_init_struct->attribute_space_timing->holdtime << NPATCFG_ATTHLD_OFFSET) & EXMC_NPATCFG_ATTHLD )| + (((exmc_pccard_init_struct->attribute_space_timing->databus_hiztime -1U) << NPATCFG_ATTHIZ_OFFSET) & EXMC_NPATCFG_ATTHIZ ); + + /* configure the EXMC bank3 PC card io space timing configuration register */ + EXMC_PIOTCFG3 = (uint32_t)((exmc_pccard_init_struct->io_space_timing->setuptime - 1U) & EXMC_PIOTCFG3_IOSET ) | + (((exmc_pccard_init_struct->io_space_timing->waittime - 1U) << PIOTCFG_IOWAIT_OFFSET) & EXMC_PIOTCFG3_IOWAIT ) | + ((exmc_pccard_init_struct->io_space_timing->holdtime << PIOTCFG_IOHLD_OFFSET) & EXMC_PIOTCFG3_IOHLD )| + ((exmc_pccard_init_struct->io_space_timing->databus_hiztime << PIOTCFG_IOHIZ_OFFSET) & EXMC_PIOTCFG3_IOHIZ ); +} + +/*! + \brief initialize the struct exmc_pccard_parameter_struct + \param[in] none + \param[out] the initialized struct exmc_pccard_parameter_struct pointer + \retval none +*/ +void exmc_pccard_struct_para_init(exmc_pccard_parameter_struct* exmc_pccard_init_struct) +{ + /* configure the structure with default value */ + exmc_pccard_init_struct->wait_feature = DISABLE; + exmc_pccard_init_struct->ctr_latency = 0x0U; + exmc_pccard_init_struct->atr_latency = 0x0U; + exmc_pccard_init_struct->common_space_timing->setuptime = 0xFCU; + exmc_pccard_init_struct->common_space_timing->waittime = 0xFCU; + exmc_pccard_init_struct->common_space_timing->holdtime = 0xFCU; + exmc_pccard_init_struct->common_space_timing->databus_hiztime = 0xFCU; + exmc_pccard_init_struct->attribute_space_timing->setuptime = 0xFCU; + exmc_pccard_init_struct->attribute_space_timing->waittime = 0xFCU; + exmc_pccard_init_struct->attribute_space_timing->holdtime = 0xFCU; + exmc_pccard_init_struct->attribute_space_timing->databus_hiztime = 0xFCU; + exmc_pccard_init_struct->io_space_timing->setuptime = 0xFCU; + exmc_pccard_init_struct->io_space_timing->waittime = 0xFCU; + exmc_pccard_init_struct->io_space_timing->holdtime = 0xFCU; + exmc_pccard_init_struct->io_space_timing->databus_hiztime = 0xFCU; +} + +/*! + \brief enable PC Card Bank + \param[in] none + \param[out] none + \retval none +*/ +void exmc_pccard_enable(void) +{ + EXMC_NPCTL3 |= EXMC_NPCTL_NDBKEN; +} + +/*! + \brief disable PC Card Bank + \param[in] none + \param[out] none + \retval none +*/ +void exmc_pccard_disable(void) +{ + EXMC_NPCTL3 &= ~EXMC_NPCTL_NDBKEN; +} + +/*! + \brief enable EXMC interrupt + \param[in] bank: specifies the NAND bank, PC card bank + only one parameter can be selected which is shown as below: + \arg EXMC_BANK1_NAND: the NAND bank1 + \arg EXMC_BANK2_NAND: the NAND bank2 + \arg EXMC_BANK3_PCCARD: the PC card bank + \param[in] interrupt_source: specify get which interrupt flag + one or more parameters can be selected which is shown as below: + \arg EXMC_NAND_PCCARD_INT_RISE: interrupt source of rising edge + \arg EXMC_NAND_PCCARD_INT_LEVEL: interrupt source of high-level + \arg EXMC_NAND_PCCARD_INT_FALL: interrupt source of falling edge + \param[out] none + \retval none +*/ +void exmc_interrupt_enable(uint32_t bank, uint32_t interrupt_source) +{ + /* NAND bank1, bank2 or PC card bank3 */ + EXMC_NPINTEN(bank) |= interrupt_source; +} + +/*! + \brief disable EXMC interrupt + \param[in] bank: specifies the NAND bank, PC card bank + only one parameter can be selected which is shown as below: + \arg EXMC_BANK1_NAND: the NAND bank1 + \arg EXMC_BANK2_NAND: the NAND bank2 + \arg EXMC_BANK3_PCCARD: the PC card bank + \param[in] interrupt_source: specify get which interrupt flag + one or more parameters can be selected which is shown as below: + \arg EXMC_NAND_PCCARD_INT_RISE: interrupt source of rising edge + \arg EXMC_NAND_PCCARD_INT_LEVEL: interrupt source of high-level + \arg EXMC_NAND_PCCARD_INT_FALL: interrupt source of falling edge + \param[out] none + \retval none +*/ +void exmc_interrupt_disable(uint32_t bank, uint32_t interrupt_source) +{ + /* NAND bank1,bank2 or PC card bank3 */ + EXMC_NPINTEN(bank) &= ~interrupt_source; +} + +/*! + \brief check EXMC flag is set or not + \param[in] bank: specifies the NAND bank, PC card bank + only one parameter can be selected which is shown as below: + \arg EXMC_BANK1_NAND: the NAND bank1 + \arg EXMC_BANK2_NAND: the NAND bank2 + \arg EXMC_BANK3_PCCARD: the PC Card bank + \param[in] flag: specify get which flag + only one parameter can be selected which is shown as below: + \arg EXMC_NAND_PCCARD_FLAG_RISE: interrupt rising edge status + \arg EXMC_NAND_PCCARD_FLAG_LEVEL: interrupt high-level status + \arg EXMC_NAND_PCCARD_FLAG_FALL: interrupt falling edge status + \arg EXMC_NAND_PCCARD_FLAG_FIFOE: FIFO empty flag + \param[out] none + \retval FlagStatus: SET or RESET +*/ +FlagStatus exmc_flag_get(uint32_t bank, uint32_t flag) +{ + uint32_t status = 0x00000000U; + + /* NAND bank1,bank2 or PC card bank3 */ + status = EXMC_NPINTEN(bank); + + if ((status & flag) != (uint32_t)flag ){ + /* flag is reset */ + return RESET; + }else{ + /* flag is set */ + return SET; + } +} + +/*! + \brief clear EXMC flag + \param[in] bank: specifie the NAND bank, PCCARD bank + only one parameter can be selected which is shown as below: + \arg EXMC_BANK1_NAND: the NAND bank1 + \arg EXMC_BANK2_NAND: the NAND bank2 + \arg EXMC_BANK3_PCCARD: the PC card bank + \param[in] flag: specify get which flag + one or more parameters can be selected which is shown as below: + \arg EXMC_NAND_PCCARD_FLAG_RISE: interrupt rising edge status + \arg EXMC_NAND_PCCARD_FLAG_LEVEL: interrupt high-level status + \arg EXMC_NAND_PCCARD_FLAG_FALL: interrupt falling edge status + \arg EXMC_NAND_PCCARD_FLAG_FIFOE: FIFO empty flag + \param[out] none + \retval none +*/ +void exmc_flag_clear(uint32_t bank, uint32_t flag) +{ + /* NAND bank1,bank2 or PC card bank3 */ + EXMC_NPINTEN(bank) &= ~flag; +} + +/*! + \brief check EXMC interrupt flag is set or not + \param[in] bank: specifies the NAND bank, PC card bank + only one parameter can be selected which is shown as below: + \arg EXMC_BANK1_NAND: the NAND bank1 + \arg EXMC_BANK2_NAND: the NAND bank2 + \arg EXMC_BANK3_PCCARD: the PC card bank + \param[in] interrupt_source: specify get which interrupt flag + only one parameter can be selected which is shown as below: + \arg EXMC_NAND_PCCARD_INT_RISE: interrupt source of rising edge + \arg EXMC_NAND_PCCARD_INT_LEVEL: interrupt source of high-level + \arg EXMC_NAND_PCCARD_INT_FALL: interrupt source of falling edge + \param[out] none + \retval FlagStatus: SET or RESET +*/ +FlagStatus exmc_interrupt_flag_get(uint32_t bank, uint32_t interrupt_source) +{ + uint32_t status = 0x00000000U,interrupt_enable = 0x00000000U,interrupt_state = 0x00000000U; + + /* NAND bank1,bank2 or PC card bank3 */ + status = EXMC_NPINTEN(bank); + interrupt_state = (status & (interrupt_source >> INTEN_INTS_OFFSET)); + + interrupt_enable = (status & interrupt_source); + + if ((interrupt_enable) && (interrupt_state)){ + /* interrupt flag is set */ + return SET; + }else{ + /* interrupt flag is reset */ + return RESET; + } +} + +/*! + \brief clear EXMC interrupt flag + \param[in] bank: specifies the NAND bank, PC card bank + only one parameter can be selected which is shown as below: + \arg EXMC_BANK1_NAND: the NAND bank1 + \arg EXMC_BANK2_NAND: the NAND bank2 + \arg EXMC_BANK3_PCCARD: the PC card bank + \param[in] interrupt_source: specify get which interrupt flag + one or more parameters can be selected which is shown as below: + \arg EXMC_NAND_PCCARD_INT_RISE: interrupt source of rising edge + \arg EXMC_NAND_PCCARD_INT_LEVEL: interrupt source of high-level + \arg EXMC_NAND_PCCARD_INT_FALL: interrupt source of falling edge + \param[out] none + \retval none +*/ +void exmc_interrupt_flag_clear(uint32_t bank, uint32_t interrupt_source) +{ + /* NAND bank1, bank2 or PC card bank3 */ + EXMC_NPINTEN(bank) &= ~(interrupt_source >> INTEN_INTS_OFFSET); +} diff --git a/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_standard_peripheral/Source/gd32f10x_exti.c b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_standard_peripheral/Source/gd32f10x_exti.c new file mode 100644 index 0000000000..48c220e193 --- /dev/null +++ b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_standard_peripheral/Source/gd32f10x_exti.c @@ -0,0 +1,254 @@ +/*! + \file gd32f10x_exti.c + \brief EXTI driver + + \version 2014-12-26, V1.0.0, firmware for GD32F10x + \version 2017-06-20, V2.0.0, firmware for GD32F10x + \version 2018-07-31, V2.1.0, firmware for GD32F10x + \version 2020-09-30, V2.2.0, firmware for GD32F10x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ +#include "gd32f10x_exti.h" + +#define EXTI_REG_RESET_VALUE ((uint32_t)0x00000000U) + +/*! + \brief deinitialize the EXTI + \param[in] none + \param[out] none + \retval none +*/ +void exti_deinit(void) +{ + /* reset the value of all the EXTI registers */ + EXTI_INTEN = EXTI_REG_RESET_VALUE; + EXTI_EVEN = EXTI_REG_RESET_VALUE; + EXTI_RTEN = EXTI_REG_RESET_VALUE; + EXTI_FTEN = EXTI_REG_RESET_VALUE; + EXTI_SWIEV = EXTI_REG_RESET_VALUE; +} + +/*! + \brief initialize the EXTI + \param[in] linex: EXTI line number, refer to exti_line_enum + only one parameter can be selected which is shown as below: + \arg EXTI_x (x=0..19): EXTI line x + \param[in] mode: interrupt or event mode, refer to exti_mode_enum + only one parameter can be selected which is shown as below: + \arg EXTI_INTERRUPT: interrupt mode + \arg EXTI_EVENT: event mode + \param[in] trig_type: trigger type, refer to exti_trig_type_enum + only one parameter can be selected which is shown as below: + \arg EXTI_TRIG_RISING: rising edge trigger + \arg EXTI_TRIG_FALLING: falling edge trigger + \arg EXTI_TRIG_BOTH: rising edge and falling edge trigger + \param[out] none + \retval none +*/ +void exti_init(exti_line_enum linex, exti_mode_enum mode, exti_trig_type_enum trig_type) +{ + /* reset the EXTI line x */ + EXTI_INTEN &= ~(uint32_t)linex; + EXTI_EVEN &= ~(uint32_t)linex; + EXTI_RTEN &= ~(uint32_t)linex; + EXTI_FTEN &= ~(uint32_t)linex; + + /* set the EXTI mode and enable the interrupts or events from EXTI line x */ + switch(mode){ + case EXTI_INTERRUPT: + EXTI_INTEN |= (uint32_t)linex; + break; + case EXTI_EVENT: + EXTI_EVEN |= (uint32_t)linex; + break; + default: + break; + } + + /* set the EXTI trigger type */ + switch(trig_type){ + case EXTI_TRIG_RISING: + EXTI_RTEN |= (uint32_t)linex; + EXTI_FTEN &= ~(uint32_t)linex; + break; + case EXTI_TRIG_FALLING: + EXTI_RTEN &= ~(uint32_t)linex; + EXTI_FTEN |= (uint32_t)linex; + break; + case EXTI_TRIG_BOTH: + EXTI_RTEN |= (uint32_t)linex; + EXTI_FTEN |= (uint32_t)linex; + break; + default: + break; + } +} + +/*! + \brief enable the interrupts from EXTI line x + \param[in] linex: EXTI line number, refer to exti_line_enum + only one parameter can be selected which is shown as below: + \arg EXTI_x (x=0..19): EXTI line x + \param[out] none + \retval none +*/ +void exti_interrupt_enable(exti_line_enum linex) +{ + EXTI_INTEN |= (uint32_t)linex; +} + +/*! + \brief enable the events from EXTI line x + \param[in] linex: EXTI line number, refer to exti_line_enum + only one parameter can be selected which is shown as below: + \arg EXTI_x (x=0..19): EXTI line x + \param[out] none + \retval none +*/ +void exti_event_enable(exti_line_enum linex) +{ + EXTI_EVEN |= (uint32_t)linex; +} + +/*! + \brief disable the interrupt from EXTI line x + \param[in] linex: EXTI line number, refer to exti_line_enum + only one parameter can be selected which is shown as below: + \arg EXTI_x (x=0..19): EXTI line x + \param[out] none + \retval none +*/ +void exti_interrupt_disable(exti_line_enum linex) +{ + EXTI_INTEN &= ~(uint32_t)linex; +} + +/*! + \brief disable the events from EXTI line x + \param[in] linex: EXTI line number, refer to exti_line_enum + only one parameter can be selected which is shown as below: + \arg EXTI_x (x=0..19): EXTI line x + \param[out] none + \retval none +*/ +void exti_event_disable(exti_line_enum linex) +{ + EXTI_EVEN &= ~(uint32_t)linex; +} + +/*! + \brief get EXTI lines flag + \param[in] linex: EXTI line number, refer to exti_line_enum + only one parameter can be selected which is shown as below: + \arg EXTI_x (x=0..19): EXTI line x + \param[out] none + \retval FlagStatus: status of flag (RESET or SET) +*/ +FlagStatus exti_flag_get(exti_line_enum linex) +{ + if(RESET != (EXTI_PD & (uint32_t)linex)){ + return SET; + }else{ + return RESET; + } +} + +/*! + \brief clear EXTI lines pending flag + \param[in] linex: EXTI line number, refer to exti_line_enum + only one parameter can be selected which is shown as below: + \arg EXTI_x (x=0..19): EXTI line x + \param[out] none + \retval none +*/ +void exti_flag_clear(exti_line_enum linex) +{ + EXTI_PD = (uint32_t)linex; +} + +/*! + \brief get EXTI lines flag when the interrupt flag is set + \param[in] linex: EXTI line number, refer to exti_line_enum + only one parameter can be selected which is shown as below: + \arg EXTI_x (x=0..19): EXTI line x + \param[out] none + \retval FlagStatus: status of flag (RESET or SET) +*/ +FlagStatus exti_interrupt_flag_get(exti_line_enum linex) +{ + uint32_t flag_left, flag_right; + + flag_left = EXTI_PD & (uint32_t)linex; + flag_right = EXTI_INTEN & (uint32_t)linex; + + if((RESET != flag_left) && (RESET != flag_right)){ + return SET; + }else{ + return RESET; + } +} + +/*! + \brief clear EXTI lines pending flag + \param[in] linex: EXTI line number, refer to exti_line_enum + only one parameter can be selected which is shown as below: + \arg EXTI_x (x=0..19): EXTI line x + \param[out] none + \retval none +*/ +void exti_interrupt_flag_clear(exti_line_enum linex) +{ + EXTI_PD = (uint32_t)linex; +} + +/*! + \brief enable EXTI software interrupt event + \param[in] linex: EXTI line number, refer to exti_line_enum + only one parameter can be selected which is shown as below: + \arg EXTI_x (x=0..19): EXTI line x + \param[out] none + \retval none +*/ +void exti_software_interrupt_enable(exti_line_enum linex) +{ + EXTI_SWIEV |= (uint32_t)linex; +} + +/*! + \brief disable EXTI software interrupt event + \param[in] linex: EXTI line number, refer to exti_line_enum + only one parameter can be selected which is shown as below: + \arg EXTI_x (x=0..19): EXTI line x + \param[out] none + \retval none +*/ +void exti_software_interrupt_disable(exti_line_enum linex) +{ + EXTI_SWIEV &= ~(uint32_t)linex; +} diff --git a/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_standard_peripheral/Source/gd32f10x_fmc.c b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_standard_peripheral/Source/gd32f10x_fmc.c new file mode 100644 index 0000000000..629fb44fc4 --- /dev/null +++ b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_standard_peripheral/Source/gd32f10x_fmc.c @@ -0,0 +1,964 @@ +/*! + \file gd32f10x_fmc.c + \brief FMC driver + + \version 2014-12-26, V1.0.0, firmware for GD32F10x + \version 2017-06-20, V2.0.0, firmware for GD32F10x + \version 2018-07-31, V2.1.0, firmware for GD32F10x + \version 2020-09-30, V2.2.0, firmware for GD32F10x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "gd32f10x_fmc.h" + +/*! + \brief set the wait state counter value + \param[in] wscnt£ºwait state counter value + \arg WS_WSCNT_0: FMC 0 wait state + \arg WS_WSCNT_1: FMC 1 wait state + \arg WS_WSCNT_2: FMC 2 wait state + \param[out] none + \retval none +*/ +void fmc_wscnt_set(uint32_t wscnt) +{ + uint32_t reg; + + reg = FMC_WS; + /* set the wait state counter value */ + reg &= ~FMC_WS_WSCNT; + FMC_WS = (reg | wscnt); +} + +/*! + \brief unlock the main FMC operation + \param[in] none + \param[out] none + \retval none +*/ +void fmc_unlock(void) +{ + if((RESET != (FMC_CTL0 & FMC_CTL0_LK))){ + /* write the FMC unlock key */ + FMC_KEY0 = UNLOCK_KEY0; + FMC_KEY0 = UNLOCK_KEY1; + } + + if(FMC_BANK0_SIZE < FMC_SIZE){ + /* write the FMC unlock key */ + if(RESET != (FMC_CTL1 & FMC_CTL1_LK)){ + FMC_KEY1 = UNLOCK_KEY0; + FMC_KEY1 = UNLOCK_KEY1; + } + } +} + +/*! + \brief unlock the FMC bank0 operation + this function can be used for all GD32F10x devices. + for GD32F10x_MD and GD32F10x_HD, this function unlocks bank0. + for GD32F10x_XD and GD32F10x_CL with flash no more than 512KB, it is equivalent to fmc_unlock function. + \param[in] none + \param[out] none + \retval none +*/ +void fmc_bank0_unlock(void) +{ + if((RESET != (FMC_CTL0 & FMC_CTL0_LK))){ + /* write the FMC unlock key */ + FMC_KEY0 = UNLOCK_KEY0; + FMC_KEY0 = UNLOCK_KEY1; + } +} + +/*! + \brief unlock the FMC bank1 operation + this function can be used for GD32F10x_XD and GD32F10x_CL with flash more than 512KB. + \param[in] none + \param[out] none + \retval none +*/ +void fmc_bank1_unlock(void) +{ + if((RESET != (FMC_CTL1 & FMC_CTL1_LK))){ + /* write the FMC unlock key */ + FMC_KEY1 = UNLOCK_KEY0; + FMC_KEY1 = UNLOCK_KEY1; + } +} + +/*! + \brief lock the main FMC operation + \param[in] none + \param[out] none + \retval none +*/ +void fmc_lock(void) +{ + /* set the LK bit */ + FMC_CTL0 |= FMC_CTL0_LK; + + if(FMC_BANK0_SIZE < FMC_SIZE){ + /* set the LK bit */ + FMC_CTL1 |= FMC_CTL1_LK; + } +} + +/*! + \brief lock the FMC bank0 operation + this function can be used for all GD32F10X devices. + for GD32F10x_MD and GD32F10x_HD, this function unlocks bank0. + for GD32F10x_XD and GD32F10x_CL with flash no more than 512KB, it is equivalent to fmc_unlock function. + \param[in] none + \param[out] none + \retval none +*/ +void fmc_bank0_lock(void) +{ + /* set the LK bit*/ + FMC_CTL0 |= FMC_CTL0_LK; +} + +/*! + \brief lock the FMC bank1 operation + this function can be used for GD32F10x_XD and GD32F10x_CL with flash more than 512KB. + \param[in] none + \param[out] none + \retval none +*/ +void fmc_bank1_lock(void) +{ + /* set the LK bit*/ + FMC_CTL1 |= FMC_CTL1_LK; +} + +/*! + \brief erase page + \param[in] page_address: the page address to be erased. + \param[out] none + \retval state of FMC, refer to fmc_state_enum +*/ +fmc_state_enum fmc_page_erase(uint32_t page_address) +{ + fmc_state_enum fmc_state; + + if(FMC_BANK0_SIZE < FMC_SIZE){ + if(FMC_BANK0_END_ADDRESS > page_address){ + fmc_state = fmc_bank0_ready_wait(FMC_TIMEOUT_COUNT); + /* if the last operation is completed, start page erase */ + if(FMC_READY == fmc_state){ + FMC_CTL0 |= FMC_CTL0_PER; + FMC_ADDR0 = page_address; + FMC_CTL0 |= FMC_CTL0_START; + /* wait for the FMC ready */ + fmc_state = fmc_bank0_ready_wait(FMC_TIMEOUT_COUNT); + /* reset the PER bit */ + FMC_CTL0 &= ~FMC_CTL0_PER; + } + }else{ + /* wait for the FMC ready */ + fmc_state = fmc_bank1_ready_wait(FMC_TIMEOUT_COUNT); + /* if the last operation is completed, start page erase */ + if(FMC_READY == fmc_state){ + FMC_CTL1 |= FMC_CTL1_PER; + FMC_ADDR1 = page_address; + if(FMC_OBSTAT & FMC_OBSTAT_SPC){ + FMC_ADDR0 = page_address; + } + FMC_CTL1 |= FMC_CTL1_START; + /* wait for the FMC ready */ + fmc_state = fmc_bank1_ready_wait(FMC_TIMEOUT_COUNT); + /* reset the PER bit */ + FMC_CTL1 &= ~FMC_CTL1_PER; + } + } + }else{ + fmc_state = fmc_bank0_ready_wait(FMC_TIMEOUT_COUNT); + /* if the last operation is completed, start page erase */ + if(FMC_READY == fmc_state){ + FMC_CTL0 |= FMC_CTL0_PER; + FMC_ADDR0 = page_address; + FMC_CTL0 |= FMC_CTL0_START; + /* wait for the FMC ready */ + fmc_state = fmc_bank0_ready_wait(FMC_TIMEOUT_COUNT); + /* reset the PER bit */ + FMC_CTL0 &= ~FMC_CTL0_PER; + } + } + /* return the FMC state */ + return fmc_state; +} + +/*! + \brief erase whole chip + \param[in] none + \param[out] none + \retval state of FMC, refer to fmc_state_enum +*/ +fmc_state_enum fmc_mass_erase(void) +{ + fmc_state_enum fmc_state; + if(FMC_BANK0_SIZE < FMC_SIZE){ + /* wait for the FMC ready */ + fmc_state = fmc_bank0_ready_wait(FMC_TIMEOUT_COUNT); + if(FMC_READY == fmc_state){ + /* start whole chip erase */ + FMC_CTL0 |= FMC_CTL0_MER; + FMC_CTL0 |= FMC_CTL0_START; + /* wait for the FMC ready */ + fmc_state = fmc_bank0_ready_wait(FMC_TIMEOUT_COUNT); + /* reset the MER bit */ + FMC_CTL0 &= ~FMC_CTL0_MER; + } + fmc_state = fmc_bank1_ready_wait(FMC_TIMEOUT_COUNT); + if(FMC_READY == fmc_state){ + /* start whole chip erase */ + FMC_CTL1 |= FMC_CTL1_MER; + FMC_CTL1 |= FMC_CTL1_START; + /* wait for the FMC ready */ + fmc_state = fmc_bank1_ready_wait(FMC_TIMEOUT_COUNT); + /* reset the MER bit */ + FMC_CTL1 &= ~FMC_CTL1_MER; + } + }else{ + fmc_state = fmc_bank0_ready_wait(FMC_TIMEOUT_COUNT); + + if(FMC_READY == fmc_state){ + /* start whole chip erase */ + FMC_CTL0 |= FMC_CTL0_MER; + FMC_CTL0 |= FMC_CTL0_START; + /* wait for the FMC ready */ + fmc_state = fmc_bank0_ready_wait(FMC_TIMEOUT_COUNT); + /* reset the MER bit */ + FMC_CTL0 &= ~FMC_CTL0_MER; + } + } + /* return the FMC state */ + return fmc_state; +} + +/*! + \brief erase bank0 + \param[in] none + \param[out] none + \retval state of FMC, refer to fmc_state_enum +*/ +fmc_state_enum fmc_bank0_erase(void) +{ + fmc_state_enum fmc_state = FMC_READY; + /* wait for the FMC ready */ + fmc_state = fmc_bank0_ready_wait(FMC_TIMEOUT_COUNT); + + if(FMC_READY == fmc_state){ + /* start FMC bank0 erase */ + FMC_CTL0 |= FMC_CTL0_MER; + FMC_CTL0 |= FMC_CTL0_START; + /* wait for the FMC ready */ + fmc_state = fmc_bank0_ready_wait(FMC_TIMEOUT_COUNT); + /* reset the MER bit */ + FMC_CTL0 &= ~FMC_CTL0_MER; + } + /* return the fmc state */ + return fmc_state; +} + +/*! + \brief erase bank1 + \param[in] none + \param[out] none + \retval state of FMC, refer to fmc_state_enum +*/ +fmc_state_enum fmc_bank1_erase(void) +{ + fmc_state_enum fmc_state = FMC_READY; + /* wait for the FMC ready */ + fmc_state = fmc_bank1_ready_wait(FMC_TIMEOUT_COUNT); + + if(FMC_READY == fmc_state){ + /* start FMC bank1 erase */ + FMC_CTL1 |= FMC_CTL1_MER; + FMC_CTL1 |= FMC_CTL1_START; + /* wait for the FMC ready */ + fmc_state = fmc_bank1_ready_wait(FMC_TIMEOUT_COUNT); + /* reset the MER bit */ + FMC_CTL1 &= ~FMC_CTL1_MER; + } + /* return the fmc state */ + return fmc_state; +} + +/*! + \brief program a word at the corresponding address + \param[in] address: address to program + \param[in] data: word to program + \param[out] none + \retval state of FMC, refer to fmc_state_enum +*/ +fmc_state_enum fmc_word_program(uint32_t address, uint32_t data) +{ + fmc_state_enum fmc_state = FMC_READY; + if(FMC_BANK0_SIZE < FMC_SIZE){ + if(FMC_BANK0_END_ADDRESS > address){ + fmc_state = fmc_bank0_ready_wait(FMC_TIMEOUT_COUNT); + + if(FMC_READY == fmc_state){ + /* set the PG bit to start program */ + FMC_CTL0 |= FMC_CTL0_PG; + REG32(address) = data; + /* wait for the FMC ready */ + fmc_state = fmc_bank0_ready_wait(FMC_TIMEOUT_COUNT); + /* reset the PG bit */ + FMC_CTL0 &= ~FMC_CTL0_PG; + } + }else{ + fmc_state = fmc_bank1_ready_wait(FMC_TIMEOUT_COUNT); + + if(FMC_READY == fmc_state){ + /* set the PG bit to start program */ + FMC_CTL1 |= FMC_CTL1_PG; + REG32(address) = data; + /* wait for the FMC ready */ + fmc_state = fmc_bank1_ready_wait(FMC_TIMEOUT_COUNT); + /* reset the PG bit */ + FMC_CTL1 &= ~FMC_CTL1_PG; + } + } + }else{ + fmc_state = fmc_bank0_ready_wait(FMC_TIMEOUT_COUNT); + + if(FMC_READY == fmc_state){ + /* set the PG bit to start program */ + FMC_CTL0 |= FMC_CTL0_PG; + REG32(address) = data; + /* wait for the FMC ready */ + fmc_state = fmc_bank0_ready_wait(FMC_TIMEOUT_COUNT); + /* reset the PG bit */ + FMC_CTL0 &= ~FMC_CTL0_PG; + } + } + /* return the FMC state */ + return fmc_state; +} + +/*! + \brief program a half word at the corresponding address + \param[in] address: address to program + \param[in] data: halfword to program + \param[out] none + \retval state of FMC, refer to fmc_state_enum +*/ +fmc_state_enum fmc_halfword_program(uint32_t address, uint16_t data) +{ + fmc_state_enum fmc_state = FMC_READY; + if(FMC_BANK0_SIZE < FMC_SIZE){ + if(FMC_BANK0_END_ADDRESS > address){ + fmc_state = fmc_bank0_ready_wait(FMC_TIMEOUT_COUNT); + + if(FMC_READY == fmc_state){ + /* set the PG bit to start program */ + FMC_CTL0 |= FMC_CTL0_PG; + REG16(address) = data; + /* wait for the FMC ready */ + fmc_state = fmc_bank0_ready_wait(FMC_TIMEOUT_COUNT); + /* reset the PG bit */ + FMC_CTL0 &= ~FMC_CTL0_PG; + } + }else{ + fmc_state = fmc_bank1_ready_wait(FMC_TIMEOUT_COUNT); + + if(FMC_READY == fmc_state){ + /* set the PG bit to start program */ + FMC_CTL1 |= FMC_CTL1_PG; + REG16(address) = data; + /* wait for the FMC ready */ + fmc_state = fmc_bank1_ready_wait(FMC_TIMEOUT_COUNT); + /* reset the PG bit */ + FMC_CTL1 &= ~FMC_CTL1_PG; + } + } + }else{ + fmc_state = fmc_bank0_ready_wait(FMC_TIMEOUT_COUNT); + + if(FMC_READY == fmc_state){ + /* set the PG bit to start program */ + FMC_CTL0 |= FMC_CTL0_PG; + REG16(address) = data; + /* wait for the FMC ready */ + fmc_state = fmc_bank0_ready_wait(FMC_TIMEOUT_COUNT); + /* reset the PG bit */ + FMC_CTL0 &= ~FMC_CTL0_PG; + } + } + /* return the FMC state */ + return fmc_state; +} + +/*! + \brief unlock the option byte operation + \param[in] none + \param[out] none + \retval none +*/ +void ob_unlock(void) +{ + if(RESET == (FMC_CTL0 & FMC_CTL0_OBWEN)){ + /* write the FMC key */ + FMC_OBKEY = UNLOCK_KEY0; + FMC_OBKEY = UNLOCK_KEY1; + } + + /* wait until OBWEN bit is set by hardware */ + while(RESET == (FMC_CTL0 & FMC_CTL0_OBWEN)){ + } +} + +/*! + \brief lock the option byte operation + \param[in] none + \param[out] none + \retval none +*/ +void ob_lock(void) +{ + /* reset the OBWEN bit */ + FMC_CTL0 &= ~FMC_CTL0_OBWEN; +} + +/*! + \brief erase the FMC option byte + unlock the FMC_CTL0 and option byte before calling this function + \param[in] none + \param[out] none + \retval state of FMC, refer to fmc_state_enum +*/ +fmc_state_enum ob_erase(void) +{ + uint16_t temp_spc = FMC_NSPC; + + fmc_state_enum fmc_state = fmc_bank0_ready_wait(FMC_TIMEOUT_COUNT); + + /* check the option byte security protection value */ + if(RESET != ob_spc_get()){ + temp_spc = FMC_USPC; + } + + if(FMC_READY == fmc_state){ + + /* start erase the option byte */ + FMC_CTL0 |= FMC_CTL0_OBER; + FMC_CTL0 |= FMC_CTL0_START; + + /* wait for the FMC ready */ + fmc_state = fmc_bank0_ready_wait(FMC_TIMEOUT_COUNT); + + if(FMC_READY == fmc_state){ + /* reset the OBER bit */ + FMC_CTL0 &= ~FMC_CTL0_OBER; + /* set the OBPG bit */ + FMC_CTL0 |= FMC_CTL0_OBPG; + /* no security protection */ + OB_SPC = (uint16_t)temp_spc; + /* wait for the FMC ready */ + fmc_state = fmc_bank0_ready_wait(FMC_TIMEOUT_COUNT); + if(FMC_TOERR != fmc_state){ + /* reset the OBPG bit */ + FMC_CTL0 &= ~FMC_CTL0_OBPG; + } + }else{ + if(FMC_TOERR != fmc_state){ + /* reset the OBPG bit */ + FMC_CTL0 &= ~FMC_CTL0_OBPG; + } + } + } + /* return the FMC state */ + return fmc_state; +} + +/*! + \brief enable write protection + \param[in] ob_wp: specify sector to be write protected, set the bit to 1 if + you want to protect the corresponding pages. meanwhile, sector + macro could used to set specific sector write protected. + one or more parameters can be selected which are shown as below: + \arg OB_WPx(x = 0..31): write protect specify sector + \arg OB_WP_ALL: write protect all sector + \param[out] none + \retval state of FMC, refer to fmc_state_enum +*/ +fmc_state_enum ob_write_protection_enable(uint32_t ob_wp) +{ + uint16_t temp_wp0, temp_wp1, temp_wp2, temp_wp3; + + fmc_state_enum fmc_state = fmc_bank0_ready_wait(FMC_TIMEOUT_COUNT); + + ob_wp = (uint32_t)(~ob_wp); + temp_wp0 = (uint16_t)(ob_wp & OB_WP0_WP0); + temp_wp1 = (uint16_t)((ob_wp & OB_WP1_WP1) >> 8U); + temp_wp2 = (uint16_t)((ob_wp & OB_WP2_WP2) >> 16U); + temp_wp3 = (uint16_t)((ob_wp & OB_WP3_WP3) >> 24U); + + if(FMC_READY == fmc_state){ + + /* set the OBPG bit*/ + FMC_CTL0 |= FMC_CTL0_OBPG; + + if(0xFFU != temp_wp0){ + OB_WP0 = temp_wp0; + + /* wait for the FMC ready */ + fmc_state = fmc_bank0_ready_wait(FMC_TIMEOUT_COUNT); + } + if((FMC_READY == fmc_state) && (0xFFU != temp_wp1)){ + OB_WP1 = temp_wp1; + + /* wait for the FMC ready */ + fmc_state = fmc_bank0_ready_wait(FMC_TIMEOUT_COUNT); + } + if((FMC_READY == fmc_state) && (0xFFU != temp_wp2)){ + OB_WP2 = temp_wp2; + + /* wait for the FMC ready */ + fmc_state = fmc_bank0_ready_wait(FMC_TIMEOUT_COUNT); + } + if((FMC_READY == fmc_state) && (0xFFU != temp_wp3)){ + OB_WP3 = temp_wp3; + + /* wait for the FMC ready */ + fmc_state = fmc_bank0_ready_wait(FMC_TIMEOUT_COUNT); + } + if(FMC_TOERR != fmc_state){ + /* reset the OBPG bit */ + FMC_CTL0 &= ~FMC_CTL0_OBPG; + } + } + /* return the FMC state */ + return fmc_state; +} + +/*! + \brief configure security protection + \param[in] ob_spc: specify security protection + only one parameter can be selected which is shown as below: + \arg FMC_NSPC: no security protection + \arg FMC_USPC: under security protection + \param[out] none + \retval state of FMC, refer to fmc_state_enum +*/ +fmc_state_enum ob_security_protection_config(uint8_t ob_spc) +{ + fmc_state_enum fmc_state = fmc_bank0_ready_wait(FMC_TIMEOUT_COUNT); + + if(FMC_READY == fmc_state){ + FMC_CTL0 |= FMC_CTL0_OBER; + FMC_CTL0 |= FMC_CTL0_START; + + /* wait for the FMC ready */ + fmc_state = fmc_bank0_ready_wait(FMC_TIMEOUT_COUNT); + + if(FMC_READY == fmc_state){ + /* reset the OBER bit */ + FMC_CTL0 &= ~FMC_CTL0_OBER; + + /* start the option byte program */ + FMC_CTL0 |= FMC_CTL0_OBPG; + + OB_SPC = (uint16_t)ob_spc; + + /* wait for the FMC ready */ + fmc_state = fmc_bank0_ready_wait(FMC_TIMEOUT_COUNT); + + if(FMC_TOERR != fmc_state){ + /* reset the OBPG bit */ + FMC_CTL0 &= ~FMC_CTL0_OBPG; + } + }else{ + if(FMC_TOERR != fmc_state){ + /* reset the OBER bit */ + FMC_CTL0 &= ~FMC_CTL0_OBER; + } + } + } + /* return the FMC state */ + return fmc_state; +} + +/*! + \brief program the FMC user option byte + \param[in] ob_fwdgt: option byte watchdog value + \arg OB_FWDGT_SW: software free watchdog + \arg OB_FWDGT_HW: hardware free watchdog + \param[in] ob_deepsleep: option byte deepsleep reset value + \arg OB_DEEPSLEEP_NRST: no reset when entering deepsleep mode + \arg OB_DEEPSLEEP_RST: generate a reset instead of entering deepsleep mode + \param[in] ob_stdby:option byte standby reset value + \arg OB_STDBY_NRST: no reset when entering standby mode + \arg OB_STDBY_RST: generate a reset instead of entering standby mode + \param[in] ob_boot: specifies the option byte boot bank value + \arg OB_BOOT_B0: boot from bank0 + \arg OB_BOOT_B1: boot from bank1 or bank0 if bank1 is void + \param[out] none + \retval state of FMC, refer to fmc_state_enum +*/ +fmc_state_enum ob_user_write(uint8_t ob_fwdgt, uint8_t ob_deepsleep, uint8_t ob_stdby, uint8_t ob_boot) +{ + fmc_state_enum fmc_state = FMC_READY; + uint8_t temp; + + /* wait for the FMC ready */ + fmc_state = fmc_bank0_ready_wait(FMC_TIMEOUT_COUNT); + + if(FMC_READY == fmc_state){ + /* set the OBPG bit*/ + FMC_CTL0 |= FMC_CTL0_OBPG; + + temp = ((uint8_t)((uint8_t)((uint8_t)(ob_boot | ob_fwdgt) | ob_deepsleep) | ob_stdby) | OB_USER_MASK); + OB_USER = (uint16_t)temp; + + /* wait for the FMC ready */ + fmc_state = fmc_bank0_ready_wait(FMC_TIMEOUT_COUNT); + + if(FMC_TOERR != fmc_state){ + /* reset the OBPG bit */ + FMC_CTL0 &= ~FMC_CTL0_OBPG; + } + } + /* return the FMC state */ + return fmc_state; +} + +/*! + \brief program option bytes data + \param[in] address: the option bytes address to be programmed + \param[in] data: the byte to be programmed + \param[out] none + \retval state of FMC, refer to fmc_state_enum +*/ +fmc_state_enum ob_data_program(uint32_t address, uint8_t data) +{ + fmc_state_enum fmc_state = fmc_bank0_ready_wait(FMC_TIMEOUT_COUNT); + + if(FMC_READY == fmc_state){ + /* set the OBPG bit */ + FMC_CTL0 |= FMC_CTL0_OBPG; + REG16(address) = data; + + /* wait for the FMC ready */ + fmc_state = fmc_bank0_ready_wait(FMC_TIMEOUT_COUNT); + + if(FMC_TOERR != fmc_state){ + /* reset the OBPG bit */ + FMC_CTL0 &= ~FMC_CTL0_OBPG; + } + } + /* return the FMC state */ + return fmc_state; +} + +/*! + \brief get the FMC user option byte + \param[in] none + \param[out] none + \retval the FMC user option byte values +*/ +uint8_t ob_user_get(void) +{ + /* return the FMC user option byte value */ + return (uint8_t)(FMC_OBSTAT >> 2U); +} + +/*! + \brief get OB_DATA in register FMC_OBSTAT + \param[in] none + \param[out] none + \retval ob_data +*/ +uint16_t ob_data_get(void) +{ + return (uint16_t)(FMC_OBSTAT >> 10U); +} + +/*! + \brief get the FMC option byte write protection + \param[in] none + \param[out] none + \retval the FMC write protection option byte value +*/ +uint32_t ob_write_protection_get(void) +{ + /* return the FMC write protection option byte value */ + return FMC_WP; +} + +/*! + \brief get the FMC option byte security protection + \param[in] none + \param[out] none + \retval FlagStatus: SET or RESET +*/ +FlagStatus ob_spc_get(void) +{ + FlagStatus spc_state = RESET; + + if(RESET != (FMC_OBSTAT & FMC_OBSTAT_SPC)){ + spc_state = SET; + }else{ + spc_state = RESET; + } + return spc_state; +} + +/*! + \brief enable FMC interrupt + \param[in] interrupt: the FMC interrupt source + only one parameter can be selected which is shown as below: + \arg FMC_INT_BANK0_END: enable FMC end of program interrupt + \arg FMC_INT_BANK0_ERR: enable FMC error interrupt + \arg FMC_INT_BANK1_END: enable FMC bank1 end of program interrupt + \arg FMC_INT_BANK1_ERR: enable FMC bank1 error interrupt + \param[out] none + \retval none +*/ +void fmc_interrupt_enable(uint32_t interrupt) +{ + FMC_REG_VAL(interrupt) |= BIT(FMC_BIT_POS(interrupt)); +} + +/*! + \brief disable FMC interrupt + \param[in] interrupt: the FMC interrupt source + only one parameter can be selected which is shown as below: + \arg FMC_INT_BANK0_END: enable FMC end of program interrupt + \arg FMC_INT_BANK0_ERR: enable FMC error interrupt + \arg FMC_INT_BANK1_END: enable FMC bank1 end of program interrupt + \arg FMC_INT_BANK1_ERR: enable FMC bank1 error interrupt + \param[out] none + \retval none +*/ +void fmc_interrupt_disable(uint32_t interrupt) +{ + FMC_REG_VAL(interrupt) &= ~BIT(FMC_BIT_POS(interrupt)); +} + +/*! + \brief check flag is set or not + \param[in] flag: check FMC flag + only one parameter can be selected which is shown as below: + \arg FMC_FLAG_BANK0_BUSY: FMC bank0 busy flag bit + \arg FMC_FLAG_BANK0_PGERR: FMC bank0 operation error flag bit + \arg FMC_FLAG_BANK0_WPERR: FMC bank0 erase/program protection error flag bit + \arg FMC_FLAG_BANK0_END: FMC bank0 end of operation flag bit + \arg FMC_FLAG_OBERR: FMC option bytes read error flag bit + \arg FMC_FLAG_BANK1_BUSY: FMC bank1 busy flag bit + \arg FMC_FLAG_BANK1_PGERR: FMC bank1 operation error flag bit + \arg FMC_FLAG_BANK1_WPERR: FMC bank1 erase/program protection error flag bit + \arg FMC_FLAG_BANK1_END: FMC bank1 end of operation flag bit + \param[out] none + \retval FlagStatus: SET or RESET +*/ +FlagStatus fmc_flag_get(uint32_t flag) +{ + if(RESET != (FMC_REG_VAL(flag) & BIT(FMC_BIT_POS(flag)))){ + return SET; + }else{ + return RESET; + } +} + +/*! + \brief clear the FMC flag + \param[in] flag: clear FMC flag + only one parameter can be selected which is shown as below: + \arg FMC_FLAG_BANK0_PGERR: FMC bank0 operation error flag bit + \arg FMC_FLAG_BANK0_WPERR: FMC bank0 erase/program protection error flag bit + \arg FMC_FLAG_BANK0_END: FMC bank0 end of operation flag bit + \arg FMC_FLAG_BANK1_PGERR: FMC bank1 operation error flag bit + \arg FMC_FLAG_BANK1_WPERR: FMC bank1 erase/program protection error flag bit + \arg FMC_FLAG_BANK1_END: FMC bank1 end of operation flag bit + \param[out] none + \retval none +*/ +void fmc_flag_clear(uint32_t flag) +{ + FMC_REG_VAL(flag) |= BIT(FMC_BIT_POS(flag)); +} + +/*! + \brief get FMC interrupt flag state + \param[in] flag: FMC interrupt flags, refer to fmc_interrupt_flag_enum + only one parameter can be selected which is shown as below: + \arg FMC_INT_FLAG_BANK0_PGERR: FMC bank0 operation error interrupt flag bit + \arg FMC_INT_FLAG_BANK0_WPERR: FMC bank0 erase/program protection error interrupt flag bit + \arg FMC_INT_FLAG_BANK0_END: FMC bank0 end of operation interrupt flag bit + \arg FMC_INT_FLAG_BANK1_PGERR: FMC bank1 operation error interrupt flag bit + \arg FMC_INT_FLAG_BANK1_WPERR: FMC bank1 erase/program protection error interrupt flag bit + \arg FMC_INT_FLAG_BANK1_END: FMC bank1 end of operation interrupt flag bit + \param[out] none + \retval FlagStatus: SET or RESET +*/ +FlagStatus fmc_interrupt_flag_get(fmc_interrupt_flag_enum flag) +{ + uint32_t ret1 = RESET; + uint32_t ret2 = RESET; + + if(FMC_STAT0_REG_OFFSET == FMC_REG_OFFSET_GET(flag)){ + /* get the staus of interrupt flag */ + ret1 = (uint32_t)(FMC_REG_VALS(flag) & BIT(FMC_BIT_POS0(flag))); + /* get the staus of interrupt enale bit */ + ret2 = (uint32_t)(FMC_CTL0 & BIT(FMC_BIT_POS1(flag))); + }else{ + /* get the staus of interrupt flag */ + ret1 = (uint32_t)(FMC_REG_VALS(flag) & BIT(FMC_BIT_POS0(flag))); + /* get the staus of interrupt enale bit */ + ret2 = (uint32_t)(FMC_CTL1 & BIT(FMC_BIT_POS1(flag))); + } + + if(ret1 && ret2){ + return SET; + }else{ + return RESET; + } +} + +/*! + \brief clear FMC interrupt flag state + \param[in] flag: FMC interrupt flags, refer to can_interrupt_flag_enum + only one parameter can be selected which is shown as below: + \arg FMC_INT_FLAG_BANK0_PGERR: FMC bank0 operation error interrupt flag bit + \arg FMC_INT_FLAG_BANK0_WPERR: FMC bank0 erase/program protection error interrupt flag bit + \arg FMC_INT_FLAG_BANK0_END: FMC bank0 end of operation interrupt flag bit + \arg FMC_INT_FLAG_BANK1_PGERR: FMC bank1 operation error interrupt flag bit + \arg FMC_INT_FLAG_BANK1_WPERR: FMC bank1 erase/program protection error interrupt flag bit + \arg FMC_INT_FLAG_BANK1_END: FMC bank1 end of operation interrupt flag bit + \param[out] none + \retval none +*/ +void fmc_interrupt_flag_clear(fmc_interrupt_flag_enum flag) +{ + FMC_REG_VALS(flag) |= BIT(FMC_BIT_POS0(flag)); +} + +/*! + \brief get the FMC bank0 state + \param[in] none + \param[out] none + \retval state of FMC, refer to fmc_state_enum +*/ +fmc_state_enum fmc_bank0_state_get(void) +{ + fmc_state_enum fmc_state = FMC_READY; + + if((uint32_t)0x00U != (FMC_STAT0 & FMC_STAT0_BUSY)){ + fmc_state = FMC_BUSY; + }else{ + if((uint32_t)0x00U != (FMC_STAT0 & FMC_STAT0_WPERR)){ + fmc_state = FMC_WPERR; + }else{ + if((uint32_t)0x00U != (FMC_STAT0 & (FMC_STAT0_PGERR))){ + fmc_state = FMC_PGERR; + } + } + } + /* return the FMC state */ + return fmc_state; +} + +/*! + \brief get the FMC bank1 state + \param[in] none + \param[out] none + \retval state of FMC, refer to fmc_state_enum +*/ +fmc_state_enum fmc_bank1_state_get(void) +{ + fmc_state_enum fmc_state = FMC_READY; + + if((uint32_t)0x00U != (FMC_STAT1 & FMC_STAT1_BUSY)){ + fmc_state = FMC_BUSY; + }else{ + if((uint32_t)0x00U != (FMC_STAT1 & FMC_STAT1_WPERR)){ + fmc_state = FMC_WPERR; + }else{ + if((uint32_t)0x00U != (FMC_STAT1 & FMC_STAT1_PGERR)){ + fmc_state = FMC_PGERR; + } + } + } + + /* return the FMC state */ + return fmc_state; +} + +/*! + \brief check whether FMC bank0 is ready or not + \param[in] timeout: count of loop + \param[out] none + \retval state of FMC, refer to fmc_state_enum +*/ +fmc_state_enum fmc_bank0_ready_wait(uint32_t timeout) +{ + fmc_state_enum fmc_state = FMC_BUSY; + + /* wait for FMC ready */ + do{ + /* get FMC state */ + fmc_state = fmc_bank0_state_get(); + timeout--; + }while((FMC_BUSY == fmc_state) && (0x00U != timeout)); + + if(FMC_BUSY == fmc_state){ + fmc_state = FMC_TOERR; + } + /* return the FMC state */ + return fmc_state; +} + +/*! + \brief check whether FMC bank1 is ready or not + \param[in] timeout: count of loop + \param[out] none + \retval state of FMC, refer to fmc_state_enum +*/ +fmc_state_enum fmc_bank1_ready_wait(uint32_t timeout) +{ + fmc_state_enum fmc_state = FMC_BUSY; + + /* wait for FMC ready */ + do{ + /* get FMC state */ + fmc_state = fmc_bank1_state_get(); + timeout--; + }while((FMC_BUSY == fmc_state) && (0x00U != timeout)); + + if(FMC_BUSY == fmc_state){ + fmc_state = FMC_TOERR; + } + /* return the FMC state */ + return fmc_state; +} diff --git a/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_standard_peripheral/Source/gd32f10x_fwdgt.c b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_standard_peripheral/Source/gd32f10x_fwdgt.c new file mode 100644 index 0000000000..50ef448cc6 --- /dev/null +++ b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_standard_peripheral/Source/gd32f10x_fwdgt.c @@ -0,0 +1,154 @@ +/*! + \file gd32f10x_fwdgt.c + \brief FWDGT driver + + \version 2014-12-26, V1.0.0, firmware for GD32F10x + \version 2017-06-20, V2.0.0, firmware for GD32F10x + \version 2018-07-31, V2.1.0, firmware for GD32F10x + \version 2020-09-30, V2.2.0, firmware for GD32F10x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "gd32f10x_fwdgt.h" + +/* write value to FWDGT_CTL_CMD bit field */ +#define CTL_CMD(regval) (BITS(0,15) & ((uint32_t)(regval) << 0)) +/* write value to FWDGT_RLD_RLD bit field */ +#define RLD_RLD(regval) (BITS(0,11) & ((uint32_t)(regval) << 0)) + +/*! + \brief enable write access to FWDGT_PSC and FWDGT_RLD + \param[in] none + \param[out] none + \retval none +*/ +void fwdgt_write_enable(void) +{ + FWDGT_CTL = FWDGT_WRITEACCESS_ENABLE; +} + +/*! + \brief disable write access to FWDGT_PSC and FWDGT_RLD + \param[in] none + \param[out] none + \retval none +*/ +void fwdgt_write_disable(void) +{ + FWDGT_CTL = FWDGT_WRITEACCESS_DISABLE; +} + +/*! + \brief start the free watchdog timer counter + \param[in] none + \param[out] none + \retval none +*/ +void fwdgt_enable(void) +{ + FWDGT_CTL = FWDGT_KEY_ENABLE; +} + +/*! + \brief reload the counter of FWDGT + \param[in] none + \param[out] none + \retval none +*/ +void fwdgt_counter_reload(void) +{ + FWDGT_CTL = FWDGT_KEY_RELOAD; +} + +/*! + \brief configure counter reload value, and prescaler divider value + \param[in] reload_value: specify reload value(0x0000 - 0x0FFF) + \param[in] prescaler_div: FWDGT prescaler value + only one parameter can be selected which is shown as below: + \arg FWDGT_PSC_DIV4: FWDGT prescaler set to 4 + \arg FWDGT_PSC_DIV8: FWDGT prescaler set to 8 + \arg FWDGT_PSC_DIV16: FWDGT prescaler set to 16 + \arg FWDGT_PSC_DIV32: FWDGT prescaler set to 32 + \arg FWDGT_PSC_DIV64: FWDGT prescaler set to 64 + \arg FWDGT_PSC_DIV128: FWDGT prescaler set to 128 + \arg FWDGT_PSC_DIV256: FWDGT prescaler set to 256 + \param[out] none + \retval ErrStatus: ERROR or SUCCESS +*/ +ErrStatus fwdgt_config(uint16_t reload_value, uint8_t prescaler_div) +{ + uint32_t timeout = FWDGT_PSC_TIMEOUT; + uint32_t flag_status = RESET; + + /* enable write access to FWDGT_PSC,and FWDGT_RLD */ + FWDGT_CTL = FWDGT_WRITEACCESS_ENABLE; + /* wait until the PUD flag to be reset */ + do{ + flag_status = FWDGT_STAT & FWDGT_STAT_PUD; + }while((--timeout > 0U) && ((uint32_t)RESET != flag_status)); + + if((uint32_t)RESET != flag_status){ + return ERROR; + } + /* configure FWDGT */ + FWDGT_PSC = (uint32_t)prescaler_div; + + timeout = FWDGT_RLD_TIMEOUT; + /* wait until the RUD flag to be reset */ + do{ + flag_status = FWDGT_STAT & FWDGT_STAT_RUD; + }while((--timeout > 0U) && ((uint32_t)RESET != flag_status)); + + if((uint32_t)RESET != flag_status){ + return ERROR; + } + FWDGT_RLD = RLD_RLD(reload_value); + /* reload the counter */ + FWDGT_CTL = FWDGT_KEY_RELOAD; + + return SUCCESS; +} + +/*! + \brief get flag state of FWDGT + \param[in] flag: flag to get + only one parameter can be selected which is shown as below: + \arg FWDGT_FLAG_PUD: a write operation to FWDGT_PSC register is on going + \arg FWDGT_FLAG_RUD: a write operation to FWDGT_RLD register is on going + \param[out] none + \retval FlagStatus: SET or RESET +*/ +FlagStatus fwdgt_flag_get(uint16_t flag) +{ + if(FWDGT_STAT & flag){ + return SET; + } + + return RESET; +} diff --git a/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_standard_peripheral/Source/gd32f10x_gpio.c b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_standard_peripheral/Source/gd32f10x_gpio.c new file mode 100644 index 0000000000..1ffd9d788b --- /dev/null +++ b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_standard_peripheral/Source/gd32f10x_gpio.c @@ -0,0 +1,538 @@ +/*! + \file gd32f10x_gpio.c + \brief GPIO driver + + \version 2014-12-26, V1.0.0, firmware for GD32F10x + \version 2017-06-20, V2.0.0, firmware for GD32F10x + \version 2018-07-31, V2.1.0, firmware for GD32F10x + \version 2020-09-30, V2.2.0, firmware for GD32F10x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "gd32f10x_gpio.h" + +#define AFIO_EXTI_SOURCE_MASK ((uint8_t)0x03U) /*!< AFIO exti source selection mask*/ +#define AFIO_EXTI_SOURCE_FIELDS ((uint8_t)0x04U) /*!< select AFIO exti source registers */ +#define LSB_16BIT_MASK ((uint16_t)0xFFFFU) /*!< LSB 16-bit mask */ +#define PCF_POSITION_MASK ((uint32_t)0x000F0000U) /*!< AFIO_PCF register position mask */ +#define PCF_SWJCFG_MASK ((uint32_t)0xF0FFFFFFU) /*!< AFIO_PCF register SWJCFG mask */ +#define PCF_LOCATION1_MASK ((uint32_t)0x00200000U) /*!< AFIO_PCF register location1 mask */ +#define PCF_LOCATION2_MASK ((uint32_t)0x00100000U) /*!< AFIO_PCF register location2 mask */ +#define AFIO_PCF1_FIELDS ((uint32_t)0x80000000U) /*!< select AFIO_PCF1 register */ +#define GPIO_OUTPUT_PORT_OFFSET ((uint32_t)4U) /*!< GPIO event output port offset*/ + +/*! + \brief reset GPIO port + \param[in] gpio_periph: GPIOx(x = A,B,C,D,E,F,G) + \param[out] none + \retval none +*/ +void gpio_deinit(uint32_t gpio_periph) +{ + switch(gpio_periph){ + case GPIOA: + /* reset GPIOA */ + rcu_periph_reset_enable(RCU_GPIOARST); + rcu_periph_reset_disable(RCU_GPIOARST); + break; + case GPIOB: + /* reset GPIOB */ + rcu_periph_reset_enable(RCU_GPIOBRST); + rcu_periph_reset_disable(RCU_GPIOBRST); + break; + case GPIOC: + /* reset GPIOC */ + rcu_periph_reset_enable(RCU_GPIOCRST); + rcu_periph_reset_disable(RCU_GPIOCRST); + break; + case GPIOD: + /* reset GPIOD */ + rcu_periph_reset_enable(RCU_GPIODRST); + rcu_periph_reset_disable(RCU_GPIODRST); + break; + case GPIOE: + /* reset GPIOE */ + rcu_periph_reset_enable(RCU_GPIOERST); + rcu_periph_reset_disable(RCU_GPIOERST); + break; + case GPIOF: + /* reset GPIOF */ + rcu_periph_reset_enable(RCU_GPIOFRST); + rcu_periph_reset_disable(RCU_GPIOFRST); + break; + case GPIOG: + /* reset GPIOG */ + rcu_periph_reset_enable(RCU_GPIOGRST); + rcu_periph_reset_disable(RCU_GPIOGRST); + break; + default: + break; + } +} + +/*! + \brief reset alternate function I/O(AFIO) + \param[in] none + \param[out] none + \retval none +*/ +void gpio_afio_deinit(void) +{ + rcu_periph_reset_enable(RCU_AFRST); + rcu_periph_reset_disable(RCU_AFRST); +} + +/*! + \brief GPIO parameter initialization + \param[in] gpio_periph: GPIOx(x = A,B,C,D,E,F,G) + \param[in] mode: gpio pin mode + only one parameter can be selected which is shown as below: + \arg GPIO_MODE_AIN: analog input mode + \arg GPIO_MODE_IN_FLOATING: floating input mode + \arg GPIO_MODE_IPD: pull-down input mode + \arg GPIO_MODE_IPU: pull-up input mode + \arg GPIO_MODE_OUT_OD: GPIO output with open-drain + \arg GPIO_MODE_OUT_PP: GPIO output with push-pull + \arg GPIO_MODE_AF_OD: AFIO output with open-drain + \arg GPIO_MODE_AF_PP: AFIO output with push-pull + \param[in] speed: gpio output max speed value + only one parameter can be selected which is shown as below: + \arg GPIO_OSPEED_10MHZ: output max speed 10MHz + \arg GPIO_OSPEED_2MHZ: output max speed 2MHz + \arg GPIO_OSPEED_50MHZ: output max speed 50MHz + \param[in] pin: GPIO pin + one or more parameters can be selected which are shown as below: + \arg GPIO_PIN_x(x=0..15), GPIO_PIN_ALL + + \param[out] none + \retval none +*/ +void gpio_init(uint32_t gpio_periph, uint32_t mode, uint32_t speed, uint32_t pin) +{ + uint16_t i; + uint32_t temp_mode = 0U; + uint32_t reg = 0U; + + /* GPIO mode configuration */ + temp_mode = (uint32_t)(mode & ((uint32_t)0x0FU)); + + /* GPIO speed configuration */ + if(((uint32_t)0x00U) != ((uint32_t)mode & ((uint32_t)0x10U))){ + /* output mode max speed:10MHz,2MHz,50MHz */ + temp_mode |= (uint32_t)speed; + } + + /* configure the eight low port pins with GPIO_CTL0 */ + for(i = 0U;i < 8U;i++){ + if((1U << i) & pin){ + reg = GPIO_CTL0(gpio_periph); + + /* clear the specified pin mode bits */ + reg &= ~GPIO_MODE_MASK(i); + /* set the specified pin mode bits */ + reg |= GPIO_MODE_SET(i, temp_mode); + + /* set IPD or IPU */ + if(GPIO_MODE_IPD == mode){ + /* reset the corresponding OCTL bit */ + GPIO_BC(gpio_periph) = (uint32_t)((1U << i) & pin); + }else{ + /* set the corresponding OCTL bit */ + if(GPIO_MODE_IPU == mode){ + GPIO_BOP(gpio_periph) = (uint32_t)((1U << i) & pin); + } + } + /* set GPIO_CTL0 register */ + GPIO_CTL0(gpio_periph) = reg; + } + } + /* configure the eight high port pins with GPIO_CTL1 */ + for(i = 8U;i < 16U;i++){ + if((1U << i) & pin){ + reg = GPIO_CTL1(gpio_periph); + + /* clear the specified pin mode bits */ + reg &= ~GPIO_MODE_MASK(i - 8U); + /* set the specified pin mode bits */ + reg |= GPIO_MODE_SET(i - 8U, temp_mode); + + /* set IPD or IPU */ + if(GPIO_MODE_IPD == mode){ + /* reset the corresponding OCTL bit */ + GPIO_BC(gpio_periph) = (uint32_t)((1U << i) & pin); + }else{ + /* set the corresponding OCTL bit */ + if(GPIO_MODE_IPU == mode){ + GPIO_BOP(gpio_periph) = (uint32_t)((1U << i) & pin); + } + } + /* set GPIO_CTL1 register */ + GPIO_CTL1(gpio_periph) = reg; + } + } +} + +/*! + \brief set GPIO pin + \param[in] gpio_periph: GPIOx(x = A,B,C,D,E,F,G) + \param[in] pin: GPIO pin + one or more parameters can be selected which are shown as below: + \arg GPIO_PIN_x(x=0..15), GPIO_PIN_ALL + \param[out] none + \retval none +*/ +void gpio_bit_set(uint32_t gpio_periph, uint32_t pin) +{ + GPIO_BOP(gpio_periph) = (uint32_t)pin; +} + +/*! + \brief reset GPIO pin + \param[in] gpio_periph: GPIOx(x = A,B,C,D,E,F,G) + \param[in] pin: GPIO pin + one or more parameters can be selected which are shown as below: + \arg GPIO_PIN_x(x=0..15), GPIO_PIN_ALL + \param[out] none + \retval none +*/ +void gpio_bit_reset(uint32_t gpio_periph, uint32_t pin) +{ + GPIO_BC(gpio_periph) = (uint32_t)pin; +} + +/*! + \brief write data to the specified GPIO pin + \param[in] gpio_periph: GPIOx(x = A,B,C,D,E,F,G) + \param[in] pin: GPIO pin + one or more parameters can be selected which are shown as below: + \arg GPIO_PIN_x(x=0..15), GPIO_PIN_ALL + \param[in] bit_value: SET or RESET + \arg RESET: clear the port pin + \arg SET: set the port pin + \param[out] none + \retval none +*/ +void gpio_bit_write(uint32_t gpio_periph, uint32_t pin, bit_status bit_value) +{ + if(RESET != bit_value){ + GPIO_BOP(gpio_periph) = (uint32_t)pin; + }else{ + GPIO_BC(gpio_periph) = (uint32_t)pin; + } +} + +/*! + \brief write data to the specified GPIO port + \param[in] gpio_periph: GPIOx(x = A,B,C,D,E,F,G) + \param[in] data: specify the value to be written to the port output data register + \param[out] none + \retval none +*/ +void gpio_port_write(uint32_t gpio_periph,uint16_t data) +{ + GPIO_OCTL(gpio_periph) = (uint32_t)data; +} + +/*! + \brief get GPIO pin input status + \param[in] gpio_periph: GPIOx(x = A,B,C,D,E,F,G) + \param[in] pin: GPIO pin + one or more parameters can be selected which are shown as below: + \arg GPIO_PIN_x(x=0..15), GPIO_PIN_ALL + \param[out] none + \retval input status of gpio pin: SET or RESET +*/ +FlagStatus gpio_input_bit_get(uint32_t gpio_periph,uint32_t pin) +{ + if((uint32_t)RESET != (GPIO_ISTAT(gpio_periph)&(pin))){ + return SET; + }else{ + return RESET; + } +} + +/*! + \brief get GPIO port input status + \param[in] gpio_periph: GPIOx(x = A,B,C,D,E,F,G) + \param[out] none + \retval input status of gpio all pins +*/ +uint16_t gpio_input_port_get(uint32_t gpio_periph) +{ + return (uint16_t)(GPIO_ISTAT(gpio_periph)); +} + +/*! + \brief get GPIO pin output status + \param[in] gpio_periph: GPIOx(x = A,B,C,D,E,F,G) + \param[in] pin: GPIO pin + one or more parameters can be selected which are shown as below: + \arg GPIO_PIN_x(x=0..15), GPIO_PIN_ALL + \param[out] none + \retval output status of gpio pin: SET or RESET +*/ +FlagStatus gpio_output_bit_get(uint32_t gpio_periph, uint32_t pin) +{ + if((uint32_t)RESET !=(GPIO_OCTL(gpio_periph)&(pin))){ + return SET; + }else{ + return RESET; + } +} + +/*! + \brief get GPIO port output status + \param[in] gpio_periph: GPIOx(x = A,B,C,D,E,F,G) + \param[out] none + \retval output status of gpio all pins +*/ +uint16_t gpio_output_port_get(uint32_t gpio_periph) +{ + return ((uint16_t)GPIO_OCTL(gpio_periph)); +} + +/*! + \brief configure GPIO pin remap + \param[in] gpio_remap: select the pin to remap + \arg GPIO_SPI0_REMAP: SPI0 remapping + \arg GPIO_I2C0_REMAP: I2C0 remapping + \arg GPIO_USART0_REMAP: USART0 remapping + \arg GPIO_USART1_REMAP: USART1 remapping + \arg GPIO_USART2_PARTIAL_REMAP: USART2 partial remapping + \arg GPIO_USART2_FULL_REMAP: USART2 full remapping + \arg GPIO_TIMER0_PARTIAL_REMAP: TIMER0 partial remapping + \arg GPIO_TIMER0_FULL_REMAP: TIMER0 full remapping + \arg GPIO_TIMER1_PARTIAL_REMAP1: TIMER1 partial remapping + \arg GPIO_TIMER1_PARTIAL_REMAP2: TIMER1 partial remapping + \arg GPIO_TIMER1_FULL_REMAP: TIMER1 full remapping + \arg GPIO_TIMER2_PARTIAL_REMAP: TIMER2 partial remapping + \arg GPIO_TIMER2_FULL_REMAP: TIMER2 full remapping + \arg GPIO_TIMER3_REMAP: TIMER3 remapping + \arg GPIO_CAN_PARTIAL_REMAP: CAN partial remapping(only for GD32F10X_MD, GD32F10X_HD devices and GD32F10X_XD devices) + \arg GPIO_CAN_FULL_REMAP: CAN full remapping(only for GD32F10X_MD, GD32F10X_HD devices and GD32F10X_XD devices) + \arg GPIO_CAN0_PARTIAL_REMAP: CAN0 partial remapping(only for GD32F10X_CL devices) + \arg GPIO_CAN0_FULL_REMAP: CAN0 full remapping(only for GD32F10X_CL devices) + \arg GPIO_PD01_REMAP: PD01 remapping + \arg GPIO_TIMER4CH3_IREMAP: TIMER4 channel3 internal remapping(only for GD32F10X_CL devices and GD32F10X_HD devices) + \arg GPIO_ADC0_ETRGINS_REMAP: ADC0 external trigger inserted conversion remapping(only for GD32F10X_MD, GD32F10X_HD devices and GD32F10X_XD devices) + \arg GPIO_ADC0_ETRGREG_REMAP: ADC0 external trigger regular conversion remapping(only for GD32F10X_MD, GD32F10X_HD devices and GD32F10X_XD devices) + \arg GPIO_ADC1_ETRGINS_REMAP: ADC1 external trigger inserted conversion remapping(only for GD32F10X_MD, GD32F10X_HD devices and GD32F10X_XD devices) + \arg GPIO_ADC1_ETRGREG_REMAP: ADC1 external trigger regular conversion remapping(only for GD32F10X_MD, GD32F10X_HD devices and GD32F10X_XD devices) + \arg GPIO_ENET_REMAP: ENET remapping(only for GD32F10X_CL devices) + \arg GPIO_CAN1_REMAP: CAN1 remapping(only for GD32F10X_CL devices) + \arg GPIO_SWJ_NONJTRST_REMAP: full SWJ(JTAG-DP + SW-DP),but without NJTRST + \arg GPIO_SWJ_SWDPENABLE_REMAP: JTAG-DP disabled and SW-DP enabled + \arg GPIO_SWJ_DISABLE_REMAP: JTAG-DP disabled and SW-DP disabled + \arg GPIO_SPI2_REMAP: SPI2 remapping(only for GD32F10X_CL, GD32F10X_HD and GD32F10X_XD devices) + \arg GPIO_TIMER1ITI1_REMAP: TIMER1 internal trigger 1 remapping(only for GD32F10X_CL devices) + \arg GPIO_PTP_PPS_REMAP: ethernet PTP PPS remapping(only for GD32F10X_CL devices) + \arg GPIO_TIMER8_REMAP: TIMER8 remapping + \arg GPIO_TIMER9_REMAP: TIMER9 remapping + \arg GPIO_TIMER10_REMAP: TIMER10 remapping + \arg GPIO_TIMER12_REMAP: TIMER12 remapping + \arg GPIO_TIMER13_REMAP: TIMER13 remapping + \arg GPIO_EXMC_NADV_REMAP: EXMC_NADV connect/disconnect + \param[in] newvalue: ENABLE or DISABLE + \param[out] none + \retval none +*/ +void gpio_pin_remap_config(uint32_t remap, ControlStatus newvalue) +{ + uint32_t remap1 = 0U, remap2 = 0U, temp_reg = 0U, temp_mask = 0U; + + if(AFIO_PCF1_FIELDS == (remap & AFIO_PCF1_FIELDS)){ + /* get AFIO_PCF1 regiter value */ + temp_reg = AFIO_PCF1; + }else{ + /* get AFIO_PCF0 regiter value */ + temp_reg = AFIO_PCF0; + } + + temp_mask = (remap & PCF_POSITION_MASK) >> 0x10U; + remap1 = remap & LSB_16BIT_MASK; + + /* judge pin remap type */ + if((PCF_LOCATION1_MASK | PCF_LOCATION2_MASK) == (remap & (PCF_LOCATION1_MASK | PCF_LOCATION2_MASK))){ + temp_reg &= PCF_SWJCFG_MASK; + AFIO_PCF0 &= PCF_SWJCFG_MASK; + }else if(PCF_LOCATION2_MASK == (remap & PCF_LOCATION2_MASK)){ + remap2 = ((uint32_t)0x03U) << temp_mask; + temp_reg &= ~remap2; + temp_reg |= ~PCF_SWJCFG_MASK; + }else{ + temp_reg &= ~(remap1 << ((remap >> 0x15U)*0x10U)); + temp_reg |= ~PCF_SWJCFG_MASK; + } + + /* set pin remap value */ + if(DISABLE != newvalue){ + temp_reg |= (remap1 << ((remap >> 0x15U)*0x10U)); + } + + if(AFIO_PCF1_FIELDS == (remap & AFIO_PCF1_FIELDS)){ + /* set AFIO_PCF1 regiter value */ + AFIO_PCF1 = temp_reg; + }else{ + /* set AFIO_PCF0 regiter value */ + AFIO_PCF0 = temp_reg; + } +} + +/*! + \brief select GPIO pin exti sources + \param[in] gpio_outputport: gpio event output port + \arg GPIO_PORT_SOURCE_GPIOA: output port source A + \arg GPIO_PORT_SOURCE_GPIOB: output port source B + \arg GPIO_PORT_SOURCE_GPIOC: output port source C + \arg GPIO_PORT_SOURCE_GPIOD: output port source D + \arg GPIO_PORT_SOURCE_GPIOE: output port source E + \arg GPIO_PORT_SOURCE_GPIOF: output port source F + \arg GPIO_PORT_SOURCE_GPIOG: output port source G + \param[in] gpio_outputpin: GPIO_PIN_SOURCE_x(x=0..15) + \param[out] none + \retval none +*/ +void gpio_exti_source_select(uint8_t output_port, uint8_t output_pin) +{ + uint32_t source = 0U; + source = ((uint32_t)0x0FU) << (AFIO_EXTI_SOURCE_FIELDS * (output_pin & AFIO_EXTI_SOURCE_MASK)); + + /* select EXTI sources */ + if(GPIO_PIN_SOURCE_4 > output_pin){ + /* select EXTI0/EXTI1/EXTI2/EXTI3 */ + AFIO_EXTISS0 &= ~source; + AFIO_EXTISS0 |= (((uint32_t)output_port) << (AFIO_EXTI_SOURCE_FIELDS * (output_pin & AFIO_EXTI_SOURCE_MASK))); + }else if(GPIO_PIN_SOURCE_8 > output_pin){ + /* select EXTI4/EXTI5/EXTI6/EXTI7 */ + AFIO_EXTISS1 &= ~source; + AFIO_EXTISS1 |= (((uint32_t)output_port) << (AFIO_EXTI_SOURCE_FIELDS * (output_pin & AFIO_EXTI_SOURCE_MASK))); + }else if(GPIO_PIN_SOURCE_12 > output_pin){ + /* select EXTI8/EXTI9/EXTI10/EXTI11 */ + AFIO_EXTISS2 &= ~source; + AFIO_EXTISS2 |= (((uint32_t)output_port) << (AFIO_EXTI_SOURCE_FIELDS * (output_pin & AFIO_EXTI_SOURCE_MASK))); + }else{ + /* select EXTI12/EXTI13/EXTI14/EXTI15 */ + AFIO_EXTISS3 &= ~source; + AFIO_EXTISS3 |= (((uint32_t)output_port) << (AFIO_EXTI_SOURCE_FIELDS * (output_pin & AFIO_EXTI_SOURCE_MASK))); + } +} + +/*! + \brief configure GPIO pin event output + \param[in] output_port: gpio event output port + only one parameter can be selected which are shown as below: + \arg GPIO_EVENT_PORT_GPIOA: event output port A + \arg GPIO_EVENT_PORT_GPIOB: event output port B + \arg GPIO_EVENT_PORT_GPIOC: event output port C + \arg GPIO_EVENT_PORT_GPIOD: event output port D + \arg GPIO_EVENT_PORT_GPIOE: event output port E + \arg GPIO_EVENT_PORT_GPIOE: event output port F + \arg GPIO_EVENT_PORT_GPIOE: event output port G + \param[in] output_pin: + only one parameter can be selected which are shown as below: + \arg GPIO_EVENT_PIN_x(x=0..15) + \param[out] none + \retval none +*/ +void gpio_event_output_config(uint8_t output_port, uint8_t output_pin) +{ + uint32_t reg = 0U; + reg = AFIO_EC; + + /* clear AFIO_EC_PORT and AFIO_EC_PIN bits */ + reg &= (uint32_t)(~(AFIO_EC_PORT|AFIO_EC_PIN)); + + reg |= (uint32_t)((uint32_t)output_port << GPIO_OUTPUT_PORT_OFFSET); + reg |= (uint32_t)output_pin; + + AFIO_EC = reg; +} + +/*! + \brief enable GPIO pin event output + \param[in] none + \param[out] none + \retval none +*/ +void gpio_event_output_enable(void) +{ + AFIO_EC |= AFIO_EC_EOE; +} + +/*! + \brief disable GPIO pin event output + \param[in] none + \param[out] none + \retval none +*/ +void gpio_event_output_disable(void) +{ + AFIO_EC &= (uint32_t)(~AFIO_EC_EOE); +} + +/*! + \brief lock GPIO pin + \param[in] gpio_periph: GPIOx(x = A,B,C,D,E,F,G) + \param[in] pin: GPIO pin + one or more parameters can be selected which are shown as below: + \arg GPIO_PIN_x(x=0..15), GPIO_PIN_ALL + \param[out] none + \retval none +*/ +void gpio_pin_lock(uint32_t gpio_periph, uint32_t pin) +{ + uint32_t lock = 0x00010000U; + lock |= pin; + + /* lock key writing sequence: write 1 -> write 0 -> write 1 -> read 0 -> read 1 */ + GPIO_LOCK(gpio_periph) = (uint32_t)lock; + GPIO_LOCK(gpio_periph) = (uint32_t)pin; + GPIO_LOCK(gpio_periph) = (uint32_t)lock; + lock = GPIO_LOCK(gpio_periph); + lock = GPIO_LOCK(gpio_periph); +} + +#ifdef GD32F10X_CL +/*! + \brief select ethernet MII or RMII PHY + \param[in] gpio_enetsel: ethernet MII or RMII PHY selection + \arg GPIO_ENET_PHY_MII: configure ethernet MAC for connection with an MII PHY + \arg GPIO_ENET_PHY_RMII: configure ethernet MAC for connection with an RMII PHY + \param[out] none + \retval none +*/ +void gpio_ethernet_phy_select(uint32_t gpio_enetsel) +{ + /* clear AFIO_PCF0_ENET_PHY_SEL bit */ + AFIO_PCF0 &= (uint32_t)(~AFIO_PCF0_ENET_PHY_SEL); + + /* select MII or RMII PHY */ + AFIO_PCF0 |= (uint32_t)gpio_enetsel; +} +#endif diff --git a/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_standard_peripheral/Source/gd32f10x_i2c.c b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_standard_peripheral/Source/gd32f10x_i2c.c new file mode 100644 index 0000000000..d823d31d46 --- /dev/null +++ b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_standard_peripheral/Source/gd32f10x_i2c.c @@ -0,0 +1,714 @@ +/*! + \file gd32f10x_i2c.c + \brief I2C driver + + \version 2014-12-26, V1.0.0, firmware for GD32F10x + \version 2017-06-20, V2.0.0, firmware for GD32F10x + \version 2018-07-31, V2.1.0, firmware for GD32F10x + \version 2019-04-16, V2.1.1, firmware for GD32F10x + \version 2020-09-30, V2.2.0, firmware for GD32F10x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "gd32f10x_i2c.h" + +/* I2C register bit mask */ +#define I2CCLK_MAX ((uint32_t)0x00000036U) /*!< i2cclk maximum value */ +#define I2CCLK_MIN ((uint32_t)0x00000002U) /*!< i2cclk minimum value */ +#define I2C_FLAG_MASK ((uint32_t)0x0000FFFFU) /*!< i2c flag mask */ +#define I2C_ADDRESS_MASK ((uint32_t)0x000003FFU) /*!< i2c address mask */ +#define I2C_ADDRESS2_MASK ((uint32_t)0x000000FEU) /*!< the second i2c address mask */ + +/* I2C register bit offset */ +#define STAT1_PECV_OFFSET ((uint32_t)8U) /* bit offset of PECV in I2C_STAT1 */ + +/*! + \brief reset I2C + \param[in] i2c_periph: I2Cx(x=0,1) + \param[out] none + \retval none +*/ +void i2c_deinit(uint32_t i2c_periph) +{ + switch(i2c_periph){ + case I2C0: + /* reset I2C0 */ + rcu_periph_reset_enable(RCU_I2C0RST); + rcu_periph_reset_disable(RCU_I2C0RST); + break; + case I2C1: + /* reset I2C1 */ + rcu_periph_reset_enable(RCU_I2C1RST); + rcu_periph_reset_disable(RCU_I2C1RST); + break; + default: + break; + } +} + +/*! + \brief configure I2C clock + \param[in] i2c_periph: I2Cx(x=0,1) + \param[in] clkspeed: I2C clock speed, supports standard mode (up to 100 kHz), fast mode (up to 400 kHz) + \param[in] dutycyc: duty cycle in fast mode + only one parameter can be selected which is shown as below: + \arg I2C_DTCY_2: T_low/T_high=2 + \arg I2C_DTCY_16_9: T_low/T_high=16/9 + \param[out] none + \retval none +*/ +void i2c_clock_config(uint32_t i2c_periph, uint32_t clkspeed, uint32_t dutycyc) +{ + uint32_t pclk1, clkc, freq, risetime; + uint32_t temp; + + pclk1 = rcu_clock_freq_get(CK_APB1); + /* I2C peripheral clock frequency */ + freq = (uint32_t)(pclk1/1000000U); + if(freq >= I2CCLK_MAX){ + freq = I2CCLK_MAX; + } + temp = I2C_CTL1(i2c_periph); + temp &= ~I2C_CTL1_I2CCLK; + temp |= freq; + + I2C_CTL1(i2c_periph) = temp; + + if(100000U >= clkspeed){ + /* the maximum SCL rise time is 1000ns in standard mode */ + risetime = (uint32_t)((pclk1/1000000U)+1U); + if(risetime >= I2CCLK_MAX){ + I2C_RT(i2c_periph) = I2CCLK_MAX; + }else if(risetime <= I2CCLK_MIN){ + I2C_RT(i2c_periph) = I2CCLK_MIN; + }else{ + I2C_RT(i2c_periph) = risetime; + } + clkc = (uint32_t)(pclk1/(clkspeed*2U)); + if(clkc < 0x04U){ + /* the CLKC in standard mode minmum value is 4 */ + clkc = 0x04U; + } + I2C_CKCFG(i2c_periph) |= (I2C_CKCFG_CLKC & clkc); + + }else if(400000U >= clkspeed){ + /* the maximum SCL rise time is 300ns in fast mode */ + I2C_RT(i2c_periph) = (uint32_t)(((freq*(uint32_t)300U)/(uint32_t)1000U)+(uint32_t)1U); + if(I2C_DTCY_2 == dutycyc){ + /* I2C duty cycle is 2 */ + clkc = (uint32_t)(pclk1/(clkspeed*3U)); + I2C_CKCFG(i2c_periph) &= ~I2C_CKCFG_DTCY; + }else{ + /* I2C duty cycle is 16/9 */ + clkc = (uint32_t)(pclk1/(clkspeed*25U)); + I2C_CKCFG(i2c_periph) |= I2C_CKCFG_DTCY; + } + if(0U == (clkc & I2C_CKCFG_CLKC)){ + /* the CLKC in fast mode minmum value is 1 */ + clkc |= 0x0001U; + } + I2C_CKCFG(i2c_periph) |= I2C_CKCFG_FAST; + I2C_CKCFG(i2c_periph) |= clkc; + }else{ + } +} + +/*! + \brief configure I2C address + \param[in] i2c_periph: I2Cx(x=0,1) + \param[in] mode: + only one parameter can be selected which is shown as below: + \arg I2C_I2CMODE_ENABLE: I2C mode + \arg I2C_SMBUSMODE_ENABLE: SMBus mode + \param[in] addformat: 7bits or 10bits + only one parameter can be selected which is shown as below: + \arg I2C_ADDFORMAT_7BITS: 7bits + \arg I2C_ADDFORMAT_10BITS: 10bits + \param[in] addr: I2C address + \param[out] none + \retval none +*/ +void i2c_mode_addr_config(uint32_t i2c_periph, uint32_t mode, uint32_t addformat, uint32_t addr) +{ + /* SMBus/I2C mode selected */ + uint32_t ctl = 0U; + + ctl = I2C_CTL0(i2c_periph); + ctl &= ~(I2C_CTL0_SMBEN); + ctl |= mode; + I2C_CTL0(i2c_periph) = ctl; + /* configure address */ + addr = addr & I2C_ADDRESS_MASK; + I2C_SADDR0(i2c_periph) = (addformat | addr); +} + +/*! + \brief SMBus type selection + \param[in] i2c_periph: I2Cx(x=0,1) + \param[in] type: + only one parameter can be selected which is shown as below: + \arg I2C_SMBUS_DEVICE: device + \arg I2C_SMBUS_HOST: host + \param[out] none + \retval none +*/ +void i2c_smbus_type_config(uint32_t i2c_periph, uint32_t type) +{ + if(I2C_SMBUS_HOST == type){ + I2C_CTL0(i2c_periph) |= I2C_CTL0_SMBSEL; + }else{ + I2C_CTL0(i2c_periph) &= ~(I2C_CTL0_SMBSEL); + } +} + +/*! + \brief whether or not to send an ACK + \param[in] i2c_periph: I2Cx(x=0,1) + \param[in] ack: + only one parameter can be selected which is shown as below: + \arg I2C_ACK_ENABLE: ACK will be sent + \arg I2C_ACK_DISABLE: ACK will not be sent + \param[out] none + \retval none +*/ +void i2c_ack_config(uint32_t i2c_periph, uint32_t ack) +{ + if(I2C_ACK_ENABLE == ack){ + I2C_CTL0(i2c_periph) |= I2C_CTL0_ACKEN; + }else{ + I2C_CTL0(i2c_periph) &= ~(I2C_CTL0_ACKEN); + } +} + +/*! + \brief configure I2C POAP position + \param[in] i2c_periph: I2Cx(x=0,1) + \param[in] pos: + only one parameter can be selected which is shown as below: + \arg I2C_ACKPOS_CURRENT: whether to send ACK or not for the current + \arg I2C_ACKPOS_NEXT: whether to send ACK or not for the next byte + \param[out] none + \retval none +*/ +void i2c_ackpos_config(uint32_t i2c_periph, uint32_t pos) +{ + /* configure I2C POAP position */ + if(I2C_ACKPOS_NEXT == pos){ + I2C_CTL0(i2c_periph) |= I2C_CTL0_POAP; + }else{ + I2C_CTL0(i2c_periph) &= ~(I2C_CTL0_POAP); + } +} + +/*! + \brief master sends slave address + \param[in] i2c_periph: I2Cx(x=0,1) + \param[in] addr: slave address + \param[in] trandirection: transmitter or receiver + only one parameter can be selected which is shown as below: + \arg I2C_TRANSMITTER: transmitter + \arg I2C_RECEIVER: receiver + \param[out] none + \retval none +*/ +void i2c_master_addressing(uint32_t i2c_periph, uint32_t addr, uint32_t trandirection) +{ + /* master is a transmitter or a receiver */ + if(I2C_TRANSMITTER == trandirection){ + addr = addr & I2C_TRANSMITTER; + }else{ + addr = addr | I2C_RECEIVER; + } + /* send slave address */ + I2C_DATA(i2c_periph) = addr; +} + +/*! + \brief enable dual-address mode + \param[in] i2c_periph: I2Cx(x=0,1) + \param[in] addr: the second address in dual-address mode + \param[out] none + \retval none +*/ +void i2c_dualaddr_enable(uint32_t i2c_periph, uint32_t addr) +{ + /* configure address */ + addr = addr & I2C_ADDRESS2_MASK; + I2C_SADDR1(i2c_periph) = (I2C_SADDR1_DUADEN | addr); +} + +/*! + \brief disable dual-address mode + \param[in] i2c_periph: I2Cx(x=0,1) + \param[out] none + \retval none +*/ +void i2c_dualaddr_disable(uint32_t i2c_periph) +{ + I2C_SADDR1(i2c_periph) &= ~(I2C_SADDR1_DUADEN); +} + +/*! + \brief enable I2C + \param[in] i2c_periph: I2Cx(x=0,1) + \param[out] none + \retval none +*/ +void i2c_enable(uint32_t i2c_periph) +{ + I2C_CTL0(i2c_periph) |= I2C_CTL0_I2CEN; +} + +/*! + \brief disable I2C + \param[in] i2c_periph: I2Cx(x=0,1) + \param[out] none + \retval none +*/ +void i2c_disable(uint32_t i2c_periph) +{ + I2C_CTL0(i2c_periph) &= ~(I2C_CTL0_I2CEN); +} + +/*! + \brief generate a START condition on I2C bus + \param[in] i2c_periph: I2Cx(x=0,1) + \param[out] none + \retval none +*/ +void i2c_start_on_bus(uint32_t i2c_periph) +{ + I2C_CTL0(i2c_periph) |= I2C_CTL0_START; +} + +/*! + \brief generate a STOP condition on I2C bus + \param[in] i2c_periph: I2Cx(x=0,1) + \param[out] none + \retval none +*/ +void i2c_stop_on_bus(uint32_t i2c_periph) +{ + I2C_CTL0(i2c_periph) |= I2C_CTL0_STOP; +} + +/*! + \brief I2C transmit data function + \param[in] i2c_periph: I2Cx(x=0,1) + \param[in] data: data of transmission + \param[out] none + \retval none +*/ +void i2c_data_transmit(uint32_t i2c_periph, uint8_t data) +{ + I2C_DATA(i2c_periph) = DATA_TRANS(data); +} + +/*! + \brief I2C receive data function + \param[in] i2c_periph: I2Cx(x=0,1) + \param[out] none + \retval data of received +*/ +uint8_t i2c_data_receive(uint32_t i2c_periph) +{ + return (uint8_t)DATA_RECV(I2C_DATA(i2c_periph)); +} + +/*! + \brief enable I2C DMA mode + \param[in] i2c_periph: I2Cx(x=0,1) + \param[in] dmastate: + only one parameter can be selected which is shown as below: + \arg I2C_DMA_ON: DMA mode enable + \arg I2C_DMA_OFF: DMA mode disable + \param[out] none + \retval none +*/ +void i2c_dma_enable(uint32_t i2c_periph, uint32_t dmastate) +{ + /* configure I2C DMA function */ + uint32_t ctl = 0U; + + ctl = I2C_CTL1(i2c_periph); + ctl &= ~(I2C_CTL1_DMAON); + ctl |= dmastate; + I2C_CTL1(i2c_periph) = ctl; +} + +/*! + \brief configure whether next DMA EOT is DMA last transfer or not + \param[in] i2c_periph: I2Cx(x=0,1) + \param[in] dmalast: + only one parameter can be selected which is shown as below: + \arg I2C_DMALST_ON: next DMA EOT is the last transfer + \arg I2C_DMALST_OFF: next DMA EOT is not the last transfer + \param[out] none + \retval none +*/ +void i2c_dma_last_transfer_config(uint32_t i2c_periph, uint32_t dmalast) +{ + /* configure DMA last transfer */ + uint32_t ctl = 0U; + + ctl = I2C_CTL1(i2c_periph); + ctl &= ~(I2C_CTL1_DMALST); + ctl |= dmalast; + I2C_CTL1(i2c_periph) = ctl; +} + +/*! + \brief whether to stretch SCL low when data is not ready in slave mode + \param[in] i2c_periph: I2Cx(x=0,1) + \param[in] stretchpara: + only one parameter can be selected which is shown as below: + \arg I2C_SCLSTRETCH_ENABLE: SCL stretching is enabled + \arg I2C_SCLSTRETCH_DISABLE: SCL stretching is disabled + \param[out] none + \retval none +*/ +void i2c_stretch_scl_low_config(uint32_t i2c_periph, uint32_t stretchpara) +{ + /* configure I2C SCL strerching enable or disable */ + uint32_t ctl = 0U; + + ctl = I2C_CTL0(i2c_periph); + ctl &= ~(I2C_CTL0_SS); + ctl |= stretchpara; + I2C_CTL0(i2c_periph) = ctl; +} + +/*! + \brief whether or not to response to a general call + \param[in] i2c_periph: I2Cx(x=0,1) + \param[in] gcallpara: + only one parameter can be selected which is shown as below: + \arg I2C_GCEN_ENABLE: slave will response to a general call + \arg I2C_GCEN_DISABLE: slave will not response to a general call + \param[out] none + \retval none +*/ +void i2c_slave_response_to_gcall_config(uint32_t i2c_periph, uint32_t gcallpara) +{ + /* configure slave response to a general call enable or disable */ + uint32_t ctl = 0U; + + ctl = I2C_CTL0(i2c_periph); + ctl &= ~(I2C_CTL0_GCEN); + ctl |= gcallpara; + I2C_CTL0(i2c_periph) = ctl; +} + +/*! + \brief software reset I2C + \param[in] i2c_periph: I2Cx(x=0,1) + \param[in] sreset: + only one parameter can be selected which is shown as below: + \arg I2C_SRESET_SET: I2C is under reset + \arg I2C_SRESET_RESET: I2C is not under reset + \param[out] none + \retval none +*/ +void i2c_software_reset_config(uint32_t i2c_periph, uint32_t sreset) +{ + /* modify CTL0 and configure software reset I2C state */ + uint32_t ctl = 0U; + + ctl = I2C_CTL0(i2c_periph); + ctl &= ~(I2C_CTL0_SRESET); + ctl |= sreset; + I2C_CTL0(i2c_periph) = ctl; +} + +/*! + \brief I2C PEC calculation on or off + \param[in] i2c_periph: I2Cx(x=0,1) + \param[in] pecstate: + only one parameter can be selected which is shown as below: + \arg I2C_PEC_ENABLE: PEC calculation on + \arg I2C_PEC_DISABLE: PEC calculation off + \param[out] none + \retval none +*/ +void i2c_pec_enable(uint32_t i2c_periph, uint32_t pecstate) +{ + /* on/off PEC calculation */ + uint32_t ctl = 0U; + + ctl = I2C_CTL0(i2c_periph); + ctl &= ~(I2C_CTL0_PECEN); + ctl |= pecstate; + I2C_CTL0(i2c_periph) = ctl; +} + +/*! + \brief I2C whether to transfer PEC value + \param[in] i2c_periph: I2Cx(x=0,1) + \param[in] pecpara: + only one parameter can be selected which is shown as below: + \arg I2C_PECTRANS_ENABLE: transfer PEC + \arg I2C_PECTRANS_DISABLE: not transfer PEC + \param[out] none + \retval none +*/ +void i2c_pec_transfer_enable(uint32_t i2c_periph, uint32_t pecpara) +{ + /* whether to transfer PEC */ + uint32_t ctl = 0U; + + ctl = I2C_CTL0(i2c_periph); + ctl &= ~(I2C_CTL0_PECTRANS); + ctl |= pecpara; + I2C_CTL0(i2c_periph) = ctl; +} + +/*! + \brief get packet error checking value + \param[in] i2c_periph: I2Cx(x=0,1) + \param[out] none + \retval PEC value +*/ +uint8_t i2c_pec_value_get(uint32_t i2c_periph) +{ + return (uint8_t)((I2C_STAT1(i2c_periph) & I2C_STAT1_PECV)>>STAT1_PECV_OFFSET); +} + +/*! + \brief I2C issue alert through SMBA pin + \param[in] i2c_periph: I2Cx(x=0,1) + \param[in] smbuspara: + only one parameter can be selected which is shown as below: + \arg I2C_SALTSEND_ENABLE: issue alert through SMBA pin + \arg I2C_SALTSEND_DISABLE: not issue alert through SMBA pin + \param[out] none + \retval none +*/ +void i2c_smbus_issue_alert(uint32_t i2c_periph, uint32_t smbuspara) +{ + /* issue alert through SMBA pin configure*/ + uint32_t ctl = 0U; + + ctl = I2C_CTL0(i2c_periph); + ctl &= ~(I2C_CTL0_SALT); + ctl |= smbuspara; + I2C_CTL0(i2c_periph) = ctl; +} + +/*! + \brief enable or disable I2C ARP protocol in SMBus switch + \param[in] i2c_periph: I2Cx(x=0,1) + \param[in] arpstate: + only one parameter can be selected which is shown as below: + \arg I2C_ARP_ENABLE: enable ARP + \arg I2C_ARP_DISABLE: disable ARP + \param[out] none + \retval none +*/ +void i2c_smbus_arp_enable(uint32_t i2c_periph, uint32_t arpstate) +{ + /* enable or disable I2C ARP protocol*/ + uint32_t ctl = 0U; + + ctl = I2C_CTL0(i2c_periph); + ctl &= ~(I2C_CTL0_ARPEN); + ctl |= arpstate; + I2C_CTL0(i2c_periph) = ctl; +} + +/*! + \brief check I2C flag is set or not + \param[in] i2c_periph: I2Cx(x=0,1) + \param[in] flag: I2C flags, refer to i2c_flag_enum + only one parameter can be selected which is shown as below: + \arg I2C_FLAG_SBSEND: start condition send out + \arg I2C_FLAG_ADDSEND: address is sent in master mode or received and matches in slave mode + \arg I2C_FLAG_BTC: byte transmission finishes + \arg I2C_FLAG_ADD10SEND: header of 10-bit address is sent in master mode + \arg I2C_FLAG_STPDET: stop condition detected in slave mode + \arg I2C_FLAG_RBNE: I2C_DATA is not Empty during receiving + \arg I2C_FLAG_TBE: I2C_DATA is empty during transmitting + \arg I2C_FLAG_BERR: a bus error occurs indication a unexpected start or stop condition on I2C bus + \arg I2C_FLAG_LOSTARB: arbitration lost in master mode + \arg I2C_FLAG_AERR: acknowledge error + \arg I2C_FLAG_OUERR: overrun or underrun situation occurs in slave mode + \arg I2C_FLAG_PECERR: PEC error when receiving data + \arg I2C_FLAG_SMBTO: timeout signal in SMBus mode + \arg I2C_FLAG_SMBALT: SMBus alert status + \arg I2C_FLAG_MASTER: a flag indicating whether I2C block is in master or slave mode + \arg I2C_FLAG_I2CBSY: busy flag + \arg I2C_FLAG_TRS: whether the I2C is a transmitter or a receiver + \arg I2C_FLAG_RXGC: general call address (00h) received + \arg I2C_FLAG_DEFSMB: default address of SMBus device + \arg I2C_FLAG_HSTSMB: SMBus host header detected in slave mode + \arg I2C_FLAG_DUMOD: dual flag in slave mode indicating which address is matched in dual-address mode + \param[out] none + \retval FlagStatus: SET or RESET +*/ +FlagStatus i2c_flag_get(uint32_t i2c_periph, i2c_flag_enum flag) +{ + if(RESET != (I2C_REG_VAL(i2c_periph, flag) & BIT(I2C_BIT_POS(flag)))){ + return SET; + }else{ + return RESET; + } +} + +/*! + \brief clear I2C flag + \param[in] i2c_periph: I2Cx(x=0,1) + \param[in] flag: I2C flags, refer to i2c_flag_enum + only one parameter can be selected which is shown as below: + \arg I2C_FLAG_SMBALT: SMBus Alert status + \arg I2C_FLAG_SMBTO: timeout signal in SMBus mode + \arg I2C_FLAG_PECERR: PEC error when receiving data + \arg I2C_FLAG_OUERR: over-run or under-run situation occurs in slave mode + \arg I2C_FLAG_AERR: acknowledge error + \arg I2C_FLAG_LOSTARB: arbitration lost in master mode + \arg I2C_FLAG_BERR: a bus error + \arg I2C_FLAG_ADDSEND: cleared by reading I2C_STAT0 and reading I2C_STAT1 + \param[out] none + \retval none +*/ +void i2c_flag_clear(uint32_t i2c_periph, i2c_flag_enum flag) +{ + if(I2C_FLAG_ADDSEND == flag){ + /* read I2C_STAT0 and then read I2C_STAT1 to clear ADDSEND */ + I2C_STAT0(i2c_periph); + I2C_STAT1(i2c_periph); + }else{ + I2C_REG_VAL(i2c_periph, flag) &= ~BIT(I2C_BIT_POS(flag)); + } +} + +/*! + \brief enable I2C interrupt + \param[in] i2c_periph: I2Cx(x=0,1) + \param[in] interrupt: I2C interrupts, refer to i2c_interrupt_enum + only one parameter can be selected which is shown as below: + \arg I2C_INT_ERR: error interrupt enable + \arg I2C_INT_EV: event interrupt enable + \arg I2C_INT_BUF: buffer interrupt enable + \param[out] none + \retval none +*/ +void i2c_interrupt_enable(uint32_t i2c_periph, i2c_interrupt_enum interrupt) +{ + I2C_REG_VAL(i2c_periph, interrupt) |= BIT(I2C_BIT_POS(interrupt)); +} + +/*! + \brief disable I2C interrupt + \param[in] i2c_periph: I2Cx(x=0,1) + \param[in] interrupt: I2C interrupts, refer to i2c_flag_enum + only one parameter can be selected which is shown as below: + \arg I2C_INT_ERR: error interrupt enable + \arg I2C_INT_EV: event interrupt enable + \arg I2C_INT_BUF: buffer interrupt enable + \param[out] none + \retval none +*/ +void i2c_interrupt_disable(uint32_t i2c_periph, i2c_interrupt_enum interrupt) +{ + I2C_REG_VAL(i2c_periph, interrupt) &= ~BIT(I2C_BIT_POS(interrupt)); +} + +/*! + \brief check I2C interrupt flag + \param[in] i2c_periph: I2Cx(x=0,1) + \param[in] int_flag: I2C interrupt flags, refer to i2c_interrupt_flag_enum + only one parameter can be selected which is shown as below: + \arg I2C_INT_FLAG_SBSEND: start condition sent out in master mode interrupt flag + \arg I2C_INT_FLAG_ADDSEND: address is sent in master mode or received and matches in slave mode interrupt flag + \arg I2C_INT_FLAG_BTC: byte transmission finishes + \arg I2C_INT_FLAG_ADD10SEND: header of 10-bit address is sent in master mode interrupt flag + \arg I2C_INT_FLAG_STPDET: etop condition detected in slave mode interrupt flag + \arg I2C_INT_FLAG_RBNE: I2C_DATA is not Empty during receiving interrupt flag + \arg I2C_INT_FLAG_TBE: I2C_DATA is empty during transmitting interrupt flag + \arg I2C_INT_FLAG_BERR: a bus error occurs indication a unexpected start or stop condition on I2C bus interrupt flag + \arg I2C_INT_FLAG_LOSTARB: arbitration lost in master mode interrupt flag + \arg I2C_INT_FLAG_AERR: acknowledge error interrupt flag + \arg I2C_INT_FLAG_OUERR: over-run or under-run situation occurs in slave mode interrupt flag + \arg I2C_INT_FLAG_PECERR: PEC error when receiving data interrupt flag + \arg I2C_INT_FLAG_SMBTO: timeout signal in SMBus mode interrupt flag + \arg I2C_INT_FLAG_SMBALT: SMBus Alert status interrupt flag + \param[out] none + \retval FlagStatus: SET or RESET +*/ +FlagStatus i2c_interrupt_flag_get(uint32_t i2c_periph, i2c_interrupt_flag_enum int_flag) +{ + uint32_t intenable = 0U, flagstatus = 0U, bufie; + + /* check BUFIE */ + bufie = I2C_CTL1(i2c_periph)&I2C_CTL1_BUFIE; + + /* get the interrupt enable bit status */ + intenable = (I2C_REG_VAL(i2c_periph, int_flag) & BIT(I2C_BIT_POS(int_flag))); + /* get the corresponding flag bit status */ + flagstatus = (I2C_REG_VAL2(i2c_periph, int_flag) & BIT(I2C_BIT_POS2(int_flag))); + + if((I2C_INT_FLAG_RBNE == int_flag) || (I2C_INT_FLAG_TBE == int_flag)){ + if(intenable && bufie){ + intenable = 1U; + }else{ + intenable = 0U; + } + } + if((0U != flagstatus) && (0U != intenable)){ + return SET; + }else{ + return RESET; + } +} + +/*! + \brief clear I2C interrupt flag + \param[in] i2c_periph: I2Cx(x=0,1) + \param[in] int_flag: I2C interrupt flags, refer to i2c_interrupt_flag_enum + only one parameter can be selected which is shown as below: + \arg I2C_INT_FLAG_ADDSEND: address is sent in master mode or received and matches in slave mode interrupt flag + \arg I2C_INT_FLAG_BERR: a bus error occurs indication a unexpected start or stop condition on I2C bus interrupt flag + \arg I2C_INT_FLAG_LOSTARB: arbitration lost in master mode interrupt flag + \arg I2C_INT_FLAG_AERR: acknowledge error interrupt flag + \arg I2C_INT_FLAG_OUERR: over-run or under-run situation occurs in slave mode interrupt flag + \arg I2C_INT_FLAG_PECERR: PEC error when receiving data interrupt flag + \arg I2C_INT_FLAG_SMBTO: timeout signal in SMBus mode interrupt flag + \arg I2C_INT_FLAG_SMBALT: SMBus Alert status interrupt flag + \param[out] none + \retval none +*/ +void i2c_interrupt_flag_clear(uint32_t i2c_periph, i2c_interrupt_flag_enum int_flag) +{ + if(I2C_INT_FLAG_ADDSEND == int_flag){ + /* read I2C_STAT0 and then read I2C_STAT1 to clear ADDSEND */ + I2C_STAT0(i2c_periph); + I2C_STAT1(i2c_periph); + }else{ + I2C_REG_VAL2(i2c_periph, int_flag) &= ~BIT(I2C_BIT_POS2(int_flag)); + } +} diff --git a/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_standard_peripheral/Source/gd32f10x_misc.c b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_standard_peripheral/Source/gd32f10x_misc.c new file mode 100644 index 0000000000..74d740481d --- /dev/null +++ b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_standard_peripheral/Source/gd32f10x_misc.c @@ -0,0 +1,186 @@ +/*! + \file gd32f10x_misc.c + \brief MISC driver + + \version 2014-12-26, V1.0.0, firmware for GD32F10x + \version 2017-06-20, V2.0.0, firmware for GD32F10x + \version 2018-07-31, V2.1.0, firmware for GD32F10x + \version 2020-09-30, V2.2.0, firmware for GD32F10x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "gd32f10x_misc.h" + +/*! + \brief set the priority group + \param[in] nvic_prigroup: the NVIC priority group + \arg NVIC_PRIGROUP_PRE0_SUB4:0 bits for pre-emption priority 4 bits for subpriority + \arg NVIC_PRIGROUP_PRE1_SUB3:1 bits for pre-emption priority 3 bits for subpriority + \arg NVIC_PRIGROUP_PRE2_SUB2:2 bits for pre-emption priority 2 bits for subpriority + \arg NVIC_PRIGROUP_PRE3_SUB1:3 bits for pre-emption priority 1 bits for subpriority + \arg NVIC_PRIGROUP_PRE4_SUB0:4 bits for pre-emption priority 0 bits for subpriority + \param[out] none + \retval none +*/ +void nvic_priority_group_set(uint32_t nvic_prigroup) +{ + /* set the priority group value */ + SCB->AIRCR = NVIC_AIRCR_VECTKEY_MASK | nvic_prigroup; +} + +/*! + \brief enable NVIC request + \param[in] nvic_irq: the NVIC interrupt request, detailed in IRQn_Type + \param[in] nvic_irq_pre_priority: the pre-emption priority needed to set + \param[in] nvic_irq_sub_priority: the subpriority needed to set + \param[out] none + \retval none +*/ +void nvic_irq_enable(uint8_t nvic_irq, + uint8_t nvic_irq_pre_priority, + uint8_t nvic_irq_sub_priority) +{ + uint32_t temp_priority = 0x00U, temp_pre = 0x00U, temp_sub = 0x00U; + + /* use the priority group value to get the temp_pre and the temp_sub */ + switch ((SCB->AIRCR) & (uint32_t)0x700U) { + case NVIC_PRIGROUP_PRE0_SUB4: + temp_pre = 0U; + temp_sub = 0x4U; + break; + case NVIC_PRIGROUP_PRE1_SUB3: + temp_pre = 1U; + temp_sub = 0x3U; + break; + case NVIC_PRIGROUP_PRE2_SUB2: + temp_pre = 2U; + temp_sub = 0x2U; + break; + case NVIC_PRIGROUP_PRE3_SUB1: + temp_pre = 3U; + temp_sub = 0x1U; + break; + case NVIC_PRIGROUP_PRE4_SUB0: + temp_pre = 4U; + temp_sub = 0x0U; + break; + default: + nvic_priority_group_set(NVIC_PRIGROUP_PRE2_SUB2); + temp_pre = 2U; + temp_sub = 0x2U; + break; + } + + /* get the temp_priority to fill the NVIC->IP register */ + temp_priority = (uint32_t)nvic_irq_pre_priority << (0x4U - temp_pre); + temp_priority |= nvic_irq_sub_priority &(0x0FU >> (0x4U - temp_sub)); + temp_priority = temp_priority << 0x04U; + NVIC->IP[nvic_irq] = (uint8_t)temp_priority; + + /* enable the selected IRQ */ + NVIC->ISER[nvic_irq >> 0x05U] = (uint32_t)0x01U << (nvic_irq & (uint8_t)0x1FU); +} + +/*! + \brief disable NVIC request + \param[in] nvic_irq: the NVIC interrupt request, detailed in IRQn_Type + \param[out] none + \retval none +*/ +void nvic_irq_disable(uint8_t nvic_irq) +{ + /* disable the selected IRQ.*/ + NVIC->ICER[nvic_irq >> 0x05U] = (uint32_t)0x01U << (nvic_irq & (uint8_t)0x1FU); +} + +/*! + \brief set the NVIC vector table base address + \param[in] nvic_vict_tab: the RAM or FLASH base address + \arg NVIC_VECTTAB_RAM: RAM base address + \are NVIC_VECTTAB_FLASH: Flash base address + \param[in] offset: Vector Table offset + \param[out] none + \retval none +*/ +void nvic_vector_table_set(uint32_t nvic_vict_tab, uint32_t offset) +{ + SCB->VTOR = nvic_vict_tab | (offset & NVIC_VECTTAB_OFFSET_MASK); +} + +/*! + \brief set the state of the low power mode + \param[in] lowpower_mode: the low power mode state + \arg SCB_LPM_SLEEP_EXIT_ISR: if chose this para, the system always enter low power + mode by exiting from ISR + \arg SCB_LPM_DEEPSLEEP: if chose this para, the system will enter the DEEPSLEEP mode + \arg SCB_LPM_WAKE_BY_ALL_INT: if chose this para, the lowpower mode can be woke up + by all the enable and disable interrupts + \param[out] none + \retval none +*/ +void system_lowpower_set(uint8_t lowpower_mode) +{ + SCB->SCR |= (uint32_t)lowpower_mode; +} + +/*! + \brief reset the state of the low power mode + \param[in] lowpower_mode: the low power mode state + \arg SCB_LPM_SLEEP_EXIT_ISR: if chose this para, the system will exit low power + mode by exiting from ISR + \arg SCB_LPM_DEEPSLEEP: if chose this para, the system will enter the SLEEP mode + \arg SCB_LPM_WAKE_BY_ALL_INT: if chose this para, the lowpower mode only can be + woke up by the enable interrupts + \param[out] none + \retval none +*/ +void system_lowpower_reset(uint8_t lowpower_mode) +{ + SCB->SCR &= (~(uint32_t)lowpower_mode); +} + +/*! + \brief set the systick clock source + \param[in] systick_clksource: the systick clock source needed to choose + \arg SYSTICK_CLKSOURCE_HCLK: systick clock source is from HCLK + \arg SYSTICK_CLKSOURCE_HCLK_DIV8: systick clock source is from HCLK/8 + \param[out] none + \retval none +*/ + +void systick_clksource_set(uint32_t systick_clksource) +{ + if(SYSTICK_CLKSOURCE_HCLK == systick_clksource ){ + /* set the systick clock source from HCLK */ + SysTick->CTRL |= SYSTICK_CLKSOURCE_HCLK; + }else{ + /* set the systick clock source from HCLK/8 */ + SysTick->CTRL &= SYSTICK_CLKSOURCE_HCLK_DIV8; + } +} diff --git a/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_standard_peripheral/Source/gd32f10x_pmu.c b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_standard_peripheral/Source/gd32f10x_pmu.c new file mode 100644 index 0000000000..42d557f374 --- /dev/null +++ b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_standard_peripheral/Source/gd32f10x_pmu.c @@ -0,0 +1,282 @@ +/*! + \file gd32f10x_pmu.c + \brief PMU driver + + \version 2014-12-26, V1.0.0, firmware for GD32F10x + \version 2017-06-20, V2.0.0, firmware for GD32F10x + \version 2018-07-31, V2.1.0, firmware for GD32F10x + \version 2019-11-26, V2.1.1, firmware for GD32F10x + \version 2020-09-30, V2.2.0, firmware for GD32F10x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "gd32f10x_pmu.h" + +/*! + \brief reset PMU register + \param[in] none + \param[out] none + \retval none +*/ +void pmu_deinit(void) +{ + /* reset PMU */ + rcu_periph_reset_enable(RCU_PMURST); + rcu_periph_reset_disable(RCU_PMURST); +} + +/*! + \brief select low voltage detector threshold + \param[in] lvdt_n: + only one parameter can be selected which is shown as below: + \arg PMU_LVDT_0: voltage threshold is 2.2V + \arg PMU_LVDT_1: voltage threshold is 2.3V + \arg PMU_LVDT_2: voltage threshold is 2.4V + \arg PMU_LVDT_3: voltage threshold is 2.5V + \arg PMU_LVDT_4: voltage threshold is 2.6V + \arg PMU_LVDT_5: voltage threshold is 2.7V + \arg PMU_LVDT_6: voltage threshold is 2.8V + \arg PMU_LVDT_7: voltage threshold is 2.9V + \param[out] none + \retval none +*/ +void pmu_lvd_select(uint32_t lvdt_n) +{ + /* disable LVD */ + PMU_CTL &= ~PMU_CTL_LVDEN; + /* clear LVDT bits */ + PMU_CTL &= ~PMU_CTL_LVDT; + /* set LVDT bits according to lvdt_n */ + PMU_CTL |= lvdt_n; + /* enable LVD */ + PMU_CTL |= PMU_CTL_LVDEN; +} + +/*! + \brief disable PMU lvd + \param[in] none + \param[out] none + \retval none +*/ +void pmu_lvd_disable(void) +{ + /* disable LVD */ + PMU_CTL &= ~PMU_CTL_LVDEN; +} + +/*! + \brief PMU work at sleep mode + \param[in] sleepmodecmd: + only one parameter can be selected which is shown as below: + \arg WFI_CMD: use WFI command + \arg WFE_CMD: use WFE command + \param[out] none + \retval none +*/ +void pmu_to_sleepmode(uint8_t sleepmodecmd) +{ + /* clear sleepdeep bit of Cortex-M3 system control register */ + SCB->SCR &= ~((uint32_t)SCB_SCR_SLEEPDEEP_Msk); + + /* select WFI or WFE command to enter sleep mode */ + if(WFI_CMD == sleepmodecmd){ + __WFI(); + }else{ + __WFE(); + } +} + +/*! + \brief PMU work at deepsleep mode + \param[in] ldo: + only one parameter can be selected which is shown as below: + \arg PMU_LDO_NORMAL: LDO work at normal power mode when pmu enter deepsleep mode + \arg PMU_LDO_LOWPOWER: LDO work at low power mode when pmu enter deepsleep mode + \param[in] deepsleepmodecmd: + only one parameter can be selected which is shown as below: + \arg WFI_CMD: use WFI command + \arg WFE_CMD: use WFE command + \param[out] none + \retval none +*/ +void pmu_to_deepsleepmode(uint32_t ldo,uint8_t deepsleepmodecmd) +{ + static uint32_t reg_snap[ 4 ]; + /* clear stbmod and ldolp bits */ + PMU_CTL &= ~((uint32_t)(PMU_CTL_STBMOD | PMU_CTL_LDOLP)); + + /* set ldolp bit according to pmu_ldo */ + PMU_CTL |= ldo; + + /* set sleepdeep bit of Cortex-M3 system control register */ + SCB->SCR |= SCB_SCR_SLEEPDEEP_Msk; + + reg_snap[0] = REG32(0xE000E010U); + reg_snap[1] = REG32(0xE000E100U); + reg_snap[2] = REG32(0xE000E104U); + reg_snap[3] = REG32(0xE000E108U); + + REG32( 0xE000E010U ) &= 0x00010004U; + REG32( 0xE000E180U ) = 0XFF7FF83DU; + REG32( 0xE000E184U ) = 0XBFFFF8FFU; + REG32( 0xE000E188U ) = 0xFFFFFFFFU; + + /* select WFI or WFE command to enter deepsleep mode */ + if(WFI_CMD == deepsleepmodecmd){ + __WFI(); + }else{ + __SEV(); + __WFE(); + __WFE(); + } + + REG32(0xE000E010U) = reg_snap[0] ; + REG32(0xE000E100U) = reg_snap[1] ; + REG32(0xE000E104U) = reg_snap[2] ; + REG32(0xE000E108U) = reg_snap[3] ; + + /* reset sleepdeep bit of Cortex-M3 system control register */ + SCB->SCR &= ~((uint32_t)SCB_SCR_SLEEPDEEP_Msk); +} + +/*! + \brief pmu work at standby mode + \param[in] standbymodecmd: + only one parameter can be selected which is shown as below: + \arg WFI_CMD: use WFI command + \arg WFE_CMD: use WFE command + \param[out] none + \retval none +*/ +void pmu_to_standbymode(uint8_t standbymodecmd) +{ + /* set sleepdeep bit of Cortex-M3 system control register */ + SCB->SCR |= SCB_SCR_SLEEPDEEP_Msk; + + /* set stbmod bit */ + PMU_CTL |= PMU_CTL_STBMOD; + + /* reset wakeup flag */ + PMU_CTL |= PMU_CTL_WURST; + + /* select WFI or WFE command to enter standby mode */ + if(WFI_CMD == standbymodecmd){ + __WFI(); + }else{ + __WFE(); + } +} + +/*! + \brief enable wakeup pin + \param[in] none + \param[out] none + \retval none +*/ +void pmu_wakeup_pin_enable(void) +{ + PMU_CS |= PMU_CS_WUPEN; +} + +/*! + \brief disable wakeup pin + \param[in] none + \param[out] none + \retval none +*/ +void pmu_wakeup_pin_disable(void) +{ + PMU_CS &= ~PMU_CS_WUPEN; +} + +/*! + \brief enable write access to the registers in backup domain + \param[in] none + \param[out] none + \retval none +*/ +void pmu_backup_write_enable(void) +{ + PMU_CTL |= PMU_CTL_BKPWEN; +} + +/*! + \brief disable write access to the registers in backup domain + \param[in] none + \param[out] none + \retval none +*/ +void pmu_backup_write_disable(void) +{ + PMU_CTL &= ~PMU_CTL_BKPWEN; +} + +/*! + \brief get flag state + \param[in] flag: + only one parameter can be selected which is shown as below: + \arg PMU_FLAG_WAKEUP: wakeup flag + \arg PMU_FLAG_STANDBY: standby flag + \arg PMU_FLAG_LVD: lvd flag + \param[out] none + \retval FlagStatus SET or RESET +*/ +FlagStatus pmu_flag_get(uint32_t flag) +{ + if(PMU_CS & flag){ + return SET; + }else{ + return RESET; + } +} + +/*! + \brief clear flag bit + \param[in] flag_reset: + only one parameter can be selected which is shown as below: + \arg PMU_FLAG_RESET_WAKEUP: reset wakeup flag + \arg PMU_FLAG_RESET_STANDBY: reset standby flag + \param[out] none + \retval none +*/ +void pmu_flag_clear(uint32_t flag_reset) +{ + switch(flag_reset){ + case PMU_FLAG_RESET_WAKEUP: + /* reset wakeup flag */ + PMU_CTL |= PMU_CTL_WURST; + break; + case PMU_FLAG_RESET_STANDBY: + /* reset standby flag */ + PMU_CTL |= PMU_CTL_STBRST; + break; + default : + break; + } +} diff --git a/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_standard_peripheral/Source/gd32f10x_rcu.c b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_standard_peripheral/Source/gd32f10x_rcu.c new file mode 100644 index 0000000000..07010878dd --- /dev/null +++ b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_standard_peripheral/Source/gd32f10x_rcu.c @@ -0,0 +1,1193 @@ +/*! + \file gd32f10x_rcu.c + \brief RCU driver + + \version 2014-12-26, V1.0.0, firmware for GD32F10x + \version 2017-06-20, V2.0.0, firmware for GD32F10x + \version 2018-07-31, V2.1.0, firmware for GD32F10x + \version 2020-09-30, V2.2.0, firmware for GD32F10x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "gd32f10x_rcu.h" + +/* define clock source */ +#define SEL_IRC8M ((uint16_t)0U) +#define SEL_HXTAL ((uint16_t)1U) +#define SEL_PLL ((uint16_t)2U) + +/* define startup timeout count */ +#define OSC_STARTUP_TIMEOUT ((uint32_t)0xFFFFFU) +#define LXTAL_STARTUP_TIMEOUT ((uint32_t)0x3FFFFFFU) + +/*! + \brief deinitialize the RCU + \param[in] none + \param[out] none + \retval none +*/ +void rcu_deinit(void) +{ + /* enable IRC8M */ + RCU_CTL |= RCU_CTL_IRC8MEN; + rcu_osci_stab_wait(RCU_IRC8M); + + /* reset CTL register */ + RCU_CTL &= ~(RCU_CTL_HXTALEN | RCU_CTL_CKMEN | RCU_CTL_PLLEN); + RCU_CTL &= ~RCU_CTL_HXTALBPS; +#ifdef GD32F10X_CL + RCU_CTL &= ~(RCU_CTL_PLL1EN | RCU_CTL_PLL2EN); +#endif /* GD32F10X_CL */ + + /* reset CFG0 register */ +#if (defined(GD32F10X_MD) || defined(GD32F10X_HD) || defined(GD32F10X_XD)) + RCU_CFG0 &= ~(RCU_CFG0_SCS | RCU_CFG0_AHBPSC | RCU_CFG0_APB1PSC | RCU_CFG0_APB2PSC | + RCU_CFG0_ADCPSC | RCU_CFG0_PLLSEL | RCU_CFG0_PREDV0 | RCU_CFG0_PLLMF | + RCU_CFG0_USBDPSC | RCU_CFG0_CKOUT0SEL | RCU_CFG0_PLLMF_4 | RCU_CFG0_ADCPSC_2); +#elif defined(GD32F10X_CL) + RCU_CFG0 &= ~(RCU_CFG0_SCS | RCU_CFG0_AHBPSC | RCU_CFG0_APB1PSC | RCU_CFG0_APB2PSC | + RCU_CFG0_ADCPSC | RCU_CFG0_PLLSEL | RCU_CFG0_PREDV0_LSB | RCU_CFG0_PLLMF | + RCU_CFG0_USBFSPSC | RCU_CFG0_CKOUT0SEL | RCU_CFG0_ADCPSC_2 | RCU_CFG0_PLLMF_4); +#endif /* GD32F10X_MD and GD32F10X_HD and GD32F10X_XD */ + + /* reset INT and CFG1 register */ +#if (defined(GD32F10X_MD) || defined(GD32F10X_HD) || defined(GD32F10X_XD)) + RCU_INT = 0x009f0000U; +#elif defined(GD32F10X_CL) + RCU_INT = 0x00ff0000U; + RCU_CFG1 &= ~(RCU_CFG1_PREDV0 | RCU_CFG1_PREDV1 | RCU_CFG1_PLL1MF | RCU_CFG1_PLL2MF | + RCU_CFG1_PREDV0SEL | RCU_CFG1_I2S1SEL | RCU_CFG1_I2S2SEL); +#endif /* GD32F10X_MD and GD32F10X_HD and GD32F10X_XD */ +} + +/*! + \brief enable the peripherals clock + \param[in] periph: RCU peripherals, refer to rcu_periph_enum + only one parameter can be selected which is shown as below: + \arg RCU_GPIOx (x=A,B,C,D,E,F,G): GPIO ports clock + \arg RCU_AF : alternate function clock + \arg RCU_CRC: CRC clock + \arg RCU_DMAx (x=0,1): DMA clock + \arg RCU_ENET: ENET clock(CL series available) + \arg RCU_ENETTX: ENETTX clock(CL series available) + \arg RCU_ENETRX: ENETRX clock(CL series available) + \arg RCU_USBD: USBD clock(HD,XD series available) + \arg RCU_USBFS: USBFS clock(CL series available) + \arg RCU_EXMC: EXMC clock + \arg RCU_TIMERx (x=0,1,2,3,4,5,6,7,8,9,10,11,12,13,TIMER8..13 are only available for XD series): TIMER clock + \arg RCU_WWDGT: WWDGT clock + \arg RCU_SPIx (x=0,1,2): SPI clock + \arg RCU_USARTx (x=0,1,2): USART clock + \arg RCU_UARTx (x=3,4): UART clock + \arg RCU_I2Cx (x=0,1): I2C clock + \arg RCU_CANx (x=0,1,CAN1 is only available for CL series): CAN clock + \arg RCU_PMU: PMU clock + \arg RCU_DAC: DAC clock + \arg RCU_RTC: RTC clock + \arg RCU_ADCx (x=0,1,2,ADC2 is not available for CL series): ADC clock + \arg RCU_SDIO: SDIO clock(not available for CL series) + \arg RCU_BKPI: BKP interface clock + \param[out] none + \retval none +*/ +void rcu_periph_clock_enable(rcu_periph_enum periph) +{ + RCU_REG_VAL(periph) |= BIT(RCU_BIT_POS(periph)); +} + +/*! + \brief disable the peripherals clock + \param[in] periph: RCU peripherals, refer to rcu_periph_enum + only one parameter can be selected which is shown as below: + \arg RCU_GPIOx (x=A,B,C,D,E,F,G): GPIO ports clock + \arg RCU_AF: alternate function clock + \arg RCU_CRC: CRC clock + \arg RCU_DMAx (x=0,1): DMA clock + \arg RCU_ENET: ENET clock(CL series available) + \arg RCU_ENETTX: ENETTX clock(CL series available) + \arg RCU_ENETRX: ENETRX clock(CL series available) + \arg RCU_USBD: USBD clock(HD,XD series available) + \arg RCU_USBFS: USBFS clock(CL series available) + \arg RCU_EXMC: EXMC clock + \arg RCU_TIMERx (x=0,1,2,3,4,5,6,7,8,9,10,11,12,13,TIMER8..13 are only available for XD series): TIMER clock + \arg RCU_WWDGT: WWDGT clock + \arg RCU_SPIx (x=0,1,2): SPI clock + \arg RCU_USARTx (x=0,1,2): USART clock + \arg RCU_UARTx (x=3,4): UART clock + \arg RCU_I2Cx (x=0,1): I2C clock + \arg RCU_CANx (x=0,1,CAN1 is only available for CL series): CAN clock + \arg RCU_PMU: PMU clock + \arg RCU_DAC: DAC clock + \arg RCU_RTC: RTC clock + \arg RCU_ADCx (x=0,1,2,ADC2 is not available for CL series): ADC clock + \arg RCU_SDIO: SDIO clock(not available for CL series) + \arg RCU_BKPI: BKP interface clock + \param[out] none + \retval none +*/ +void rcu_periph_clock_disable(rcu_periph_enum periph) +{ + RCU_REG_VAL(periph) &= ~BIT(RCU_BIT_POS(periph)); +} + +/*! + \brief enable the peripherals clock when sleep mode + \param[in] periph: RCU peripherals, refer to rcu_periph_sleep_enum + only one parameter can be selected which is shown as below: + \arg RCU_FMC_SLP: FMC clock + \arg RCU_SRAM_SLP: SRAM clock + \param[out] none + \retval none +*/ +void rcu_periph_clock_sleep_enable(rcu_periph_sleep_enum periph) +{ + RCU_REG_VAL(periph) |= BIT(RCU_BIT_POS(periph)); +} + +/*! + \brief disable the peripherals clock when sleep mode + \param[in] periph: RCU peripherals, refer to rcu_periph_sleep_enum + only one parameter can be selected which is shown as below: + \arg RCU_FMC_SLP: FMC clock + \arg RCU_SRAM_SLP: SRAM clock + \param[out] none + \retval none +*/ +void rcu_periph_clock_sleep_disable(rcu_periph_sleep_enum periph) +{ + RCU_REG_VAL(periph) &= ~BIT(RCU_BIT_POS(periph)); +} + +/*! + \brief reset the peripherals + \param[in] periph_reset: RCU peripherals reset, refer to rcu_periph_reset_enum + only one parameter can be selected which is shown as below: + \arg RCU_GPIOxRST (x=A,B,C,D,E,F,G): reset GPIO ports + \arg RCU_AFRST : reset alternate function clock + \arg RCU_ENETRST: reset ENET(CL series available) + \arg RCU_USBDRST: reset USBD(HD,XD series available) + \arg RCU_USBFSRST: reset USBFS(CL series available) + \arg RCU_TIMERxRST (x=0,1,2,3,4,5,6,7,8,9,10,11,12,13,TIMER8..13 are only available for XD series): reset TIMER + \arg RCU_WWDGTRST: reset WWDGT + \arg RCU_SPIxRST (x=0,1,2): reset SPI + \arg RCU_USARTxRST (x=0,1,2): reset USART + \arg RCU_UARTxRST (x=3,4): reset UART + \arg RCU_I2CxRST (x=0,1): reset I2C + \arg RCU_CANxRST (x=0,1,CAN1 is only available for CL series): reset CAN + \arg RCU_PMURST: reset PMU + \arg RCU_DACRST: reset DAC + \arg RCU_ADCxRST (x=0,1,2, ADC2 is not available for CL series): reset ADC + \arg RCU_BKPIRST: reset BKPI + \param[out] none + \retval none +*/ +void rcu_periph_reset_enable(rcu_periph_reset_enum periph_reset) +{ + RCU_REG_VAL(periph_reset) |= BIT(RCU_BIT_POS(periph_reset)); +} + +/*! + \brief disable reset the peripheral + \param[in] periph_reset: RCU peripherals reset, refer to rcu_periph_reset_enum + only one parameter can be selected which is shown as below: + \arg RCU_GPIOxRST (x=A,B,C,D,E,F,G): reset GPIO ports + \arg RCU_AFRST : reset alternate function clock + \arg RCU_ENETRST: reset ENET(CL series available) + \arg RCU_USBDRST: reset USBD(HD,XD series available) + \arg RCU_USBFSRST: reset USBFS(CL series available) + \arg RCU_TIMERxRST (x=0,1,2,3,4,5,6,7,8,9,10,11,12,13,TIMER8..13 are only available for XD series): reset TIMER + \arg RCU_WWDGTRST: reset WWDGT + \arg RCU_SPIxRST (x=0,1,2): reset SPI + \arg RCU_USARTxRST (x=0,1,2): reset USART + \arg RCU_UARTxRST (x=3,4): reset UART + \arg RCU_I2CxRST (x=0,1): reset I2C + \arg RCU_CANxRST (x=0,1,CAN1 is only available for CL series): reset CAN + \arg RCU_PMURST: reset PMU + \arg RCU_DACRST: reset DAC + \arg RCU_ADCxRST (x=0,1,2, ADC2 is not available for CL series): reset ADC + \arg RCU_BKPIRST: reset BKPI + \param[out] none + \retval none +*/ +void rcu_periph_reset_disable(rcu_periph_reset_enum periph_reset) +{ + RCU_REG_VAL(periph_reset) &= ~BIT(RCU_BIT_POS(periph_reset)); +} + +/*! + \brief reset the BKP domain + \param[in] none + \param[out] none + \retval none +*/ +void rcu_bkp_reset_enable(void) +{ + RCU_BDCTL |= RCU_BDCTL_BKPRST; +} + +/*! + \brief disable the BKP domain reset + \param[in] none + \param[out] none + \retval none +*/ +void rcu_bkp_reset_disable(void) +{ + RCU_BDCTL &= ~RCU_BDCTL_BKPRST; +} + +/*! + \brief configure the system clock source + \param[in] ck_sys: system clock source select + only one parameter can be selected which is shown as below: + \arg RCU_CKSYSSRC_IRC8M: select CK_IRC8M as the CK_SYS source + \arg RCU_CKSYSSRC_HXTAL: select CK_HXTAL as the CK_SYS source + \arg RCU_CKSYSSRC_PLL: select CK_PLL as the CK_SYS source + \param[out] none + \retval none +*/ +void rcu_system_clock_source_config(uint32_t ck_sys) +{ + uint32_t reg; + + reg = RCU_CFG0; + /* reset the SCS bits and set according to ck_sys */ + reg &= ~RCU_CFG0_SCS; + RCU_CFG0 = (reg | ck_sys); +} + +/*! + \brief get the system clock source + \param[in] none + \param[out] none + \retval which clock is selected as CK_SYS source + \arg RCU_SCSS_IRC8M: CK_IRC8M is selected as the CK_SYS source + \arg RCU_SCSS_HXTAL: CK_HXTAL is selected as the CK_SYS source + \arg RCU_SCSS_PLL: CK_PLL is selected as the CK_SYS source +*/ +uint32_t rcu_system_clock_source_get(void) +{ + return (RCU_CFG0 & RCU_CFG0_SCSS); +} + +/*! + \brief configure the AHB clock prescaler selection + \param[in] ck_ahb: AHB clock prescaler selection + only one parameter can be selected which is shown as below: + \arg RCU_AHB_CKSYS_DIVx, x=1, 2, 4, 8, 16, 64, 128, 256, 512 + \param[out] none + \retval none +*/ +void rcu_ahb_clock_config(uint32_t ck_ahb) +{ + uint32_t reg; + + reg = RCU_CFG0; + + /* reset the AHBPSC bits and set according to ck_ahb */ + reg &= ~RCU_CFG0_AHBPSC; + RCU_CFG0 = (reg | ck_ahb); +} + +/*! + \brief configure the APB1 clock prescaler selection + \param[in] ck_apb1: APB1 clock prescaler selection + only one parameter can be selected which is shown as below: + \arg RCU_APB1_CKAHB_DIV1: select CK_AHB as CK_APB1 + \arg RCU_APB1_CKAHB_DIV2: select CK_AHB/2 as CK_APB1 + \arg RCU_APB1_CKAHB_DIV4: select CK_AHB/4 as CK_APB1 + \arg RCU_APB1_CKAHB_DIV8: select CK_AHB/8 as CK_APB1 + \arg RCU_APB1_CKAHB_DIV16: select CK_AHB/16 as CK_APB1 + \param[out] none + \retval none +*/ +void rcu_apb1_clock_config(uint32_t ck_apb1) +{ + uint32_t reg; + + reg = RCU_CFG0; + + /* reset the APB1PSC and set according to ck_apb1 */ + reg &= ~RCU_CFG0_APB1PSC; + RCU_CFG0 = (reg | ck_apb1); +} + +/*! + \brief configure the APB2 clock prescaler selection + \param[in] ck_apb2: APB2 clock prescaler selection + only one parameter can be selected which is shown as below: + \arg RCU_APB2_CKAHB_DIV1: select CK_AHB as CK_APB2 + \arg RCU_APB2_CKAHB_DIV2: select CK_AHB/2 as CK_APB2 + \arg RCU_APB2_CKAHB_DIV4: select CK_AHB/4 as CK_APB2 + \arg RCU_APB2_CKAHB_DIV8: select CK_AHB/8 as CK_APB2 + \arg RCU_APB2_CKAHB_DIV16: select CK_AHB/16 as CK_APB2 + \param[out] none + \retval none +*/ +void rcu_apb2_clock_config(uint32_t ck_apb2) +{ + uint32_t reg; + + reg = RCU_CFG0; + + /* reset the APB2PSC and set according to ck_apb2 */ + reg &= ~RCU_CFG0_APB2PSC; + RCU_CFG0 = (reg | ck_apb2); +} + +/*! + \brief configure the CK_OUT0 clock source + \param[in] ckout0_src: CK_OUT0 clock source selection + only one parameter can be selected which is shown as below: + \arg RCU_CKOUT0SRC_NONE: no clock selected + \arg RCU_CKOUT0SRC_CKSYS: system clock selected + \arg RCU_CKOUT0SRC_IRC8M: high speed 8M internal oscillator clock selected + \arg RCU_CKOUT0SRC_HXTAL: HXTAL selected + \arg RCU_CKOUT0SRC_CKPLL_DIV2: CK_PLL/2 selected + \arg RCU_CKOUT0SRC_CKPLL1: CK_PLL1 selected + \arg RCU_CKOUT0SRC_CKPLL2_DIV2: CK_PLL2/2 selected + \arg RCU_CKOUT0SRC_EXT1: EXT1 selected + \arg RCU_CKOUT0SRC_CKPLL2: PLL2 selected + \param[out] none + \retval none +*/ +void rcu_ckout0_config(uint32_t ckout0_src) +{ + uint32_t reg; + + reg = RCU_CFG0; + + /* reset the CKOUT0SRC, set according to ckout0_src */ + reg &= ~RCU_CFG0_CKOUT0SEL; + RCU_CFG0 = (reg | ckout0_src); +} + +/*! + \brief configure the main PLL clock + \param[in] pll_src: PLL clock source selection + only one parameter can be selected which is shown as below: + \arg RCU_PLLSRC_IRC8M_DIV2: IRC8M/2 clock selected as source clock of PLL + \arg RCU_PLLSRC_HXTAL: HXTAL selected as source clock of PLL + \param[in] pll_mul: PLL clock multiplication factor + only one parameter can be selected which is shown as below: + \arg RCU_PLL_MULx (XD series x = 2..32, CL series x = 2..14, 6.5, 16..32) + \param[out] none + \retval none +*/ +void rcu_pll_config(uint32_t pll_src, uint32_t pll_mul) +{ + uint32_t reg = 0U; + + reg = RCU_CFG0; + + /* PLL clock source and multiplication factor configuration */ + reg &= ~(RCU_CFG0_PLLSEL | RCU_CFG0_PLLMF | RCU_CFG0_PLLMF_4); + reg |= (pll_src | pll_mul); + + RCU_CFG0 = reg; +} + +#if (defined(GD32F10X_MD) || defined(GD32F10X_HD) || defined(GD32F10X_XD)) +/*! + \brief configure the PREDV0 division factor + \param[in] predv0_div: PREDV0 division factor + only one parameter can be selected which is shown as below: + \arg RCU_PREDV0_DIVx, x = 1,2 + \param[out] none + \retval none +*/ +void rcu_predv0_config(uint32_t predv0_div) +{ + uint32_t reg = 0U; + + reg = RCU_CFG0; + /* reset PREDV0 bit */ + reg &= ~RCU_CFG0_PREDV0; + if(RCU_PREDV0_DIV2 == predv0_div){ + /* set the PREDV0 bit */ + reg |= RCU_CFG0_PREDV0; + } + + RCU_CFG0 = reg; +} +#elif defined(GD32F10X_CL) +/*! + \brief configure the PREDV0 division factor and clock source + \param[in] predv0_source: PREDV0 input clock source selection + only one parameter can be selected which is shown as below: + \arg RCU_PREDV0SRC_HXTAL: HXTAL selected as PREDV0 input source clock + \arg RCU_PREDV0SRC_CKPLL1: CK_PLL1 selected as PREDV0 input source clock + \param[in] predv0_div: PREDV0 division factor + only one parameter can be selected which is shown as below: + \arg RCU_PREDV0_DIVx, x = 1..16 + \param[out] none + \retval none +*/ +void rcu_predv0_config(uint32_t predv0_source, uint32_t predv0_div) +{ + uint32_t reg = 0U; + + reg = RCU_CFG1; + /* reset PREDV0SEL and PREDV0 bits */ + reg &= ~(RCU_CFG1_PREDV0SEL | RCU_CFG1_PREDV0); + /* set the PREDV0SEL and PREDV0 division factor */ + reg |= (predv0_source | predv0_div); + + RCU_CFG1 = reg; +} + +/*! + \brief configure the PREDV1 division factor + \param[in] predv1_div: PREDV1 division factor + only one parameter can be selected which is shown as below: + \arg RCU_PREDV1_DIVx, x = 1..16 + \param[out] none + \retval none +*/ +void rcu_predv1_config(uint32_t predv1_div) +{ + uint32_t reg = 0U; + + reg = RCU_CFG1; + /* reset the PREDV1 bits */ + reg &= ~RCU_CFG1_PREDV1; + /* set the PREDV1 division factor */ + reg |= predv1_div; + + RCU_CFG1 = reg; +} + +/*! + \brief configure the PLL1 clock + \param[in] pll_mul: PLL clock multiplication factor + only one parameter can be selected which is shown as below: + \arg RCU_PLL1_MULx (x = 8..16, 20) + \param[out] none + \retval none +*/ +void rcu_pll1_config(uint32_t pll_mul) +{ + RCU_CFG1 &= ~RCU_CFG1_PLL1MF; + RCU_CFG1 |= pll_mul; +} + +/*! + \brief configure the PLL2 clock + \param[in] pll_mul: PLL clock multiplication factor + only one parameter can be selected which is shown as below: + \arg RCU_PLL2_MULx (x = 8..16, 20) + \param[out] none + \retval none +*/ +void rcu_pll2_config(uint32_t pll_mul) +{ + RCU_CFG1 &= ~RCU_CFG1_PLL2MF; + RCU_CFG1 |= pll_mul; +} +#endif /* GD32F10X_MD and GD32F10X_HD and GD32F10X_XD */ + +/*! + \brief configure the ADC prescaler factor + \param[in] adc_psc: ADC prescaler factor + only one parameter can be selected which is shown as below: + \arg RCU_CKADC_CKAPB2_DIV2: ADC prescaler select CK_APB2/2 + \arg RCU_CKADC_CKAPB2_DIV4: ADC prescaler select CK_APB2/4 + \arg RCU_CKADC_CKAPB2_DIV6: ADC prescaler select CK_APB2/6 + \arg RCU_CKADC_CKAPB2_DIV8: ADC prescaler select CK_APB2/8 + \arg RCU_CKADC_CKAPB2_DIV12: ADC prescaler select CK_APB2/12 + \arg RCU_CKADC_CKAPB2_DIV16: ADC prescaler select CK_APB2/16 + \param[out] none + \retval none +*/ +void rcu_adc_clock_config(uint32_t adc_psc) +{ + uint32_t reg0; + + /* reset the ADCPSC bits */ + reg0 = RCU_CFG0; + reg0 &= ~(RCU_CFG0_ADCPSC_2 | RCU_CFG0_ADCPSC); + + /* set the ADC prescaler factor */ + switch(adc_psc){ + case RCU_CKADC_CKAPB2_DIV2: + case RCU_CKADC_CKAPB2_DIV4: + case RCU_CKADC_CKAPB2_DIV6: + case RCU_CKADC_CKAPB2_DIV8: + reg0 |= (adc_psc << 14); + break; + + case RCU_CKADC_CKAPB2_DIV12: + case RCU_CKADC_CKAPB2_DIV16: + adc_psc &= ~BIT(2); + reg0 |= (adc_psc << 14 | RCU_CFG0_ADCPSC_2); + break; + + default: + break; + } + + /* set the register */ + RCU_CFG0 = reg0; +} + +/*! + \brief configure the USBD/USBFS prescaler factor + \param[in] usb_psc: USB prescaler factor + only one parameter can be selected which is shown as below: + \arg RCU_CKUSB_CKPLL_DIV1_5: USBD/USBFS prescaler select CK_PLL/1.5 + \arg RCU_CKUSB_CKPLL_DIV1: USBD/USBFS prescaler select CK_PLL/1 + \arg RCU_CKUSB_CKPLL_DIV2_5: USBD/USBFS prescaler select CK_PLL/2.5 + \arg RCU_CKUSB_CKPLL_DIV2: USBD/USBFS prescaler select CK_PLL/2 + \param[out] none + \retval none +*/ +void rcu_usb_clock_config(uint32_t usb_psc) +{ + uint32_t reg; + + reg = RCU_CFG0; + + /* configure the USBD/USBFS prescaler factor */ +#if (defined(GD32F10X_MD) || defined(GD32F10X_HD) || defined(GD32F10X_XD)) + reg &= ~RCU_CFG0_USBDPSC; +#elif defined(GD32F10X_CL) + reg &= ~RCU_CFG0_USBFSPSC; +#endif /* GD32F10X_MD and GD32F10X_HD and GD32F10X_XD */ + + RCU_CFG0 = (reg | usb_psc); +} + +/*! + \brief configure the RTC clock source selection + \param[in] rtc_clock_source: RTC clock source selection + only one parameter can be selected which is shown as below: + \arg RCU_RTCSRC_NONE: no clock selected + \arg RCU_RTCSRC_LXTAL: CK_LXTAL selected as RTC source clock + \arg RCU_RTCSRC_IRC40K: CK_IRC40K selected as RTC source clock + \arg RCU_RTCSRC_HXTAL_DIV_128: CK_HXTAL/128 selected as RTC source clock + \param[out] none + \retval none +*/ +void rcu_rtc_clock_config(uint32_t rtc_clock_source) +{ + uint32_t reg; + + reg = RCU_BDCTL; + /* reset the RTCSRC bits and set according to rtc_clock_source */ + reg &= ~RCU_BDCTL_RTCSRC; + RCU_BDCTL = (reg | rtc_clock_source); +} + +#ifdef GD32F10X_CL +/*! + \brief configure the I2S1 clock source selection + \param[in] i2s_clock_source: I2S1 clock source selection + only one parameter can be selected which is shown as below: + \arg RCU_I2S1SRC_CKSYS: System clock selected as I2S1 source clock + \arg RCU_I2S1SRC_CKPLL2_MUL2: CK_PLL2x2 selected as I2S1 source clock + \param[out] none + \retval none +*/ +void rcu_i2s1_clock_config(uint32_t i2s_clock_source) +{ + uint32_t reg; + + reg = RCU_CFG1; + /* reset the I2S1SEL bit and set according to i2s_clock_source */ + reg &= ~RCU_CFG1_I2S1SEL; + RCU_CFG1 = (reg | i2s_clock_source); +} + +/*! + \brief configure the I2S2 clock source selection + \param[in] i2s_clock_source: I2S2 clock source selection + only one parameter can be selected which is shown as below: + \arg RCU_I2S2SRC_CKSYS: system clock selected as I2S2 source clock + \arg RCU_I2S2SRC_CKPLL2_MUL2: CK_PLL2x2 selected as I2S2 source clock + \param[out] none + \retval none +*/ +void rcu_i2s2_clock_config(uint32_t i2s_clock_source) +{ + uint32_t reg; + + reg = RCU_CFG1; + /* reset the I2S2SEL bit and set according to i2s_clock_source */ + reg &= ~RCU_CFG1_I2S2SEL; + RCU_CFG1 = (reg | i2s_clock_source); +} +#endif /* GD32F10X_CL */ + +/*! + \brief get the clock stabilization and periphral reset flags + \param[in] flag: the clock stabilization and periphral reset flags, refer to rcu_flag_enum + only one parameter can be selected which is shown as below: + \arg RCU_FLAG_IRC8MSTB: IRC8M stabilization flag + \arg RCU_FLAG_HXTALSTB: HXTAL stabilization flag + \arg RCU_FLAG_PLLSTB: PLL stabilization flag + \arg RCU_FLAG_PLL1STB: PLL1 stabilization flag(CL series only) + \arg RCU_FLAG_PLL2STB: PLL2 stabilization flag(CL series only) + \arg RCU_FLAG_LXTALSTB: LXTAL stabilization flag + \arg RCU_FLAG_IRC40KSTB: IRC40K stabilization flag + \arg RCU_FLAG_EPRST: external PIN reset flag + \arg RCU_FLAG_PORRST: power reset flag + \arg RCU_FLAG_SWRST: software reset flag + \arg RCU_FLAG_FWDGTRST: free watchdog timer reset flag + \arg RCU_FLAG_WWDGTRST: window watchdog timer reset flag + \arg RCU_FLAG_LPRST: low-power reset flag + \param[out] none + \retval FlagStatus: SET or RESET +*/ +FlagStatus rcu_flag_get(rcu_flag_enum flag) +{ + /* get the rcu flag */ + if(RESET != (RCU_REG_VAL(flag) & BIT(RCU_BIT_POS(flag)))){ + return SET; + }else{ + return RESET; + } +} + +/*! + \brief clear all the reset flag + \param[in] none + \param[out] none + \retval none +*/ +void rcu_all_reset_flag_clear(void) +{ + RCU_RSTSCK |= RCU_RSTSCK_RSTFC; +} + +/*! + \brief get the clock stabilization interrupt and ckm flags + \param[in] int_flag: interrupt and ckm flags, refer to rcu_int_flag_enum + only one parameter can be selected which is shown as below: + \arg RCU_INT_FLAG_IRC40KSTB: IRC40K stabilization interrupt flag + \arg RCU_INT_FLAG_LXTALSTB: LXTAL stabilization interrupt flag + \arg RCU_INT_FLAG_IRC8MSTB: IRC8M stabilization interrupt flag + \arg RCU_INT_FLAG_HXTALSTB: HXTAL stabilization interrupt flag + \arg RCU_INT_FLAG_PLLSTB: PLL stabilization interrupt flag + \arg RCU_INT_FLAG_PLL1STB: PLL1 stabilization interrupt flag(CL series only) + \arg RCU_INT_FLAG_PLL2STB: PLL2 stabilization interrupt flag(CL series only) + \arg RCU_INT_FLAG_CKM: HXTAL clock stuck interrupt flag + \param[out] none + \retval FlagStatus: SET or RESET +*/ +FlagStatus rcu_interrupt_flag_get(rcu_int_flag_enum int_flag) +{ + /* get the rcu interrupt flag */ + if(RESET != (RCU_REG_VAL(int_flag) & BIT(RCU_BIT_POS(int_flag)))){ + return SET; + }else{ + return RESET; + } +} + +/*! + \brief clear the interrupt flags + \param[in] int_flag_clear: clock stabilization and stuck interrupt flags clear, refer to rcu_int_flag_clear_enum + only one parameter can be selected which is shown as below: + \arg RCU_INT_FLAG_IRC40KSTB_CLR: IRC40K stabilization interrupt flag clear + \arg RCU_INT_FLAG_LXTALSTB_CLR: LXTAL stabilization interrupt flag clear + \arg RCU_INT_FLAG_IRC8MSTB_CLR: IRC8M stabilization interrupt flag clear + \arg RCU_INT_FLAG_HXTALSTB_CLR: HXTAL stabilization interrupt flag clear + \arg RCU_INT_FLAG_PLLSTB_CLR: PLL stabilization interrupt flag clear + \arg RCU_INT_FLAG_PLL1STB_CLR: PLL1 stabilization interrupt flag clear(CL series only) + \arg RCU_INT_FLAG_PLL2STB_CLR: PLL2 stabilization interrupt flag clear(CL series only) + \arg RCU_INT_FLAG_CKM_CLR: clock stuck interrupt flag clear + \param[out] none + \retval none +*/ +void rcu_interrupt_flag_clear(rcu_int_flag_clear_enum int_flag_clear) +{ + RCU_REG_VAL(int_flag_clear) |= BIT(RCU_BIT_POS(int_flag_clear)); +} + +/*! + \brief enable the stabilization interrupt + \param[in] stab_int: clock stabilization interrupt, refer to rcu_int_enum + Only one parameter can be selected which is shown as below: + \arg RCU_INT_IRC40KSTB: IRC40K stabilization interrupt enable + \arg RCU_INT_LXTALSTB: LXTAL stabilization interrupt enable + \arg RCU_INT_IRC8MSTB: IRC8M stabilization interrupt enable + \arg RCU_INT_HXTALSTB: HXTAL stabilization interrupt enable + \arg RCU_INT_PLLSTB: PLL stabilization interrupt enable + \arg RCU_INT_PLL1STB: PLL1 stabilization interrupt enable(CL series only) + \arg RCU_INT_PLL2STB: PLL2 stabilization interrupt enable(CL series only) + \param[out] none + \retval none +*/ +void rcu_interrupt_enable(rcu_int_enum stab_int) +{ + RCU_REG_VAL(stab_int) |= BIT(RCU_BIT_POS(stab_int)); +} + +/*! + \brief disable the stabilization interrupt + \param[in] stab_int: clock stabilization interrupt, refer to rcu_int_enum + only one parameter can be selected which is shown as below: + \arg RCU_INT_IRC40KSTB: IRC40K stabilization interrupt enable + \arg RCU_INT_LXTALSTB: LXTAL stabilization interrupt enable + \arg RCU_INT_IRC8MSTB: IRC8M stabilization interrupt enable + \arg RCU_INT_HXTALSTB: HXTAL stabilization interrupt enable + \arg RCU_INT_PLLSTB: PLL stabilization interrupt enable + \arg RCU_INT_PLL1STB: PLL1 stabilization interrupt enable(CL series only) + \arg RCU_INT_PLL2STB: PLL2 stabilization interrupt enable(CL series only) + \param[out] none + \retval none +*/ +void rcu_interrupt_disable(rcu_int_enum stab_int) +{ + RCU_REG_VAL(stab_int) &= ~BIT(RCU_BIT_POS(stab_int)); +} + +/*! + \brief wait for oscillator stabilization flags is SET or oscillator startup is timeout + \param[in] osci: oscillator types, refer to rcu_osci_type_enum + only one parameter can be selected which is shown as below: + \arg RCU_HXTAL: high speed crystal oscillator(HXTAL) + \arg RCU_LXTAL: low speed crystal oscillator(LXTAL) + \arg RCU_IRC8M: internal 8M RC oscillators(IRC8M) + \arg RCU_IRC40K: internal 40K RC oscillator(IRC40K) + \arg RCU_PLL_CK: phase locked loop(PLL) + \arg RCU_PLL1_CK: phase locked loop 1(CL series only) + \arg RCU_PLL2_CK: phase locked loop 2(CL series only) + \param[out] none + \retval ErrStatus: SUCCESS or ERROR +*/ +ErrStatus rcu_osci_stab_wait(rcu_osci_type_enum osci) +{ + uint32_t stb_cnt = 0U; + ErrStatus reval = ERROR; + FlagStatus osci_stat = RESET; + + switch(osci){ + /* wait HXTAL stable */ + case RCU_HXTAL: + while((RESET == osci_stat) && (HXTAL_STARTUP_TIMEOUT != stb_cnt)){ + osci_stat = rcu_flag_get(RCU_FLAG_HXTALSTB); + stb_cnt++; + } + + /* check whether flag is set or not */ + if(RESET != rcu_flag_get(RCU_FLAG_HXTALSTB)){ + reval = SUCCESS; + } + break; + + /* wait LXTAL stable */ + case RCU_LXTAL: + while((RESET == osci_stat) && (LXTAL_STARTUP_TIMEOUT != stb_cnt)){ + osci_stat = rcu_flag_get(RCU_FLAG_LXTALSTB); + stb_cnt++; + } + + /* check whether flag is set or not */ + if(RESET != rcu_flag_get(RCU_FLAG_LXTALSTB)){ + reval = SUCCESS; + } + break; + + /* wait IRC8M stable */ + case RCU_IRC8M: + while((RESET == osci_stat) && (IRC8M_STARTUP_TIMEOUT != stb_cnt)){ + osci_stat = rcu_flag_get(RCU_FLAG_IRC8MSTB); + stb_cnt++; + } + + /* check whether flag is set or not */ + if(RESET != rcu_flag_get(RCU_FLAG_IRC8MSTB)){ + reval = SUCCESS; + } + break; + + /* wait IRC40K stable */ + case RCU_IRC40K: + while((RESET == osci_stat) && (OSC_STARTUP_TIMEOUT != stb_cnt)){ + osci_stat = rcu_flag_get(RCU_FLAG_IRC40KSTB); + stb_cnt++; + } + + /* check whether flag is set or not */ + if(RESET != rcu_flag_get(RCU_FLAG_IRC40KSTB)){ + reval = SUCCESS; + } + break; + + /* wait PLL stable */ + case RCU_PLL_CK: + while((RESET == osci_stat) && (OSC_STARTUP_TIMEOUT != stb_cnt)){ + osci_stat = rcu_flag_get(RCU_FLAG_PLLSTB); + stb_cnt++; + } + + /* check whether flag is set or not */ + if(RESET != rcu_flag_get(RCU_FLAG_PLLSTB)){ + reval = SUCCESS; + } + break; + +#ifdef GD32F10X_CL + /* wait PLL1 stable */ + case RCU_PLL1_CK: + while((RESET == osci_stat) && (OSC_STARTUP_TIMEOUT != stb_cnt)){ + osci_stat = rcu_flag_get(RCU_FLAG_PLL1STB); + stb_cnt++; + } + + /* check whether flag is set or not */ + if(RESET != rcu_flag_get(RCU_FLAG_PLL1STB)){ + reval = SUCCESS; + } + break; + /* wait PLL2 stable */ + case RCU_PLL2_CK: + while((RESET == osci_stat) && (OSC_STARTUP_TIMEOUT != stb_cnt)){ + osci_stat = rcu_flag_get(RCU_FLAG_PLL2STB); + stb_cnt++; + } + + /* check whether flag is set or not */ + if(RESET != rcu_flag_get(RCU_FLAG_PLL2STB)){ + reval = SUCCESS; + } + break; +#endif /* GD32F10X_CL */ + + default: + break; + } + + /* return value */ + return reval; +} + +/*! + \brief turn on the oscillator + \param[in] osci: oscillator types, refer to rcu_osci_type_enum + only one parameter can be selected which is shown as below: + \arg RCU_HXTAL: high speed crystal oscillator(HXTAL) + \arg RCU_LXTAL: low speed crystal oscillator(LXTAL) + \arg RCU_IRC8M: internal 8M RC oscillators(IRC8M) + \arg RCU_IRC40K: internal 40K RC oscillator(IRC40K) + \arg RCU_PLL_CK: phase locked loop(PLL) + \arg RCU_PLL1_CK: phase locked loop 1(CL series only) + \arg RCU_PLL2_CK: phase locked loop 2(CL series only) + \param[out] none + \retval none +*/ +void rcu_osci_on(rcu_osci_type_enum osci) +{ + RCU_REG_VAL(osci) |= BIT(RCU_BIT_POS(osci)); +} + +/*! + \brief turn off the oscillator + \param[in] osci: oscillator types, refer to rcu_osci_type_enum + only one parameter can be selected which is shown as below: + \arg RCU_HXTAL: high speed crystal oscillator(HXTAL) + \arg RCU_LXTAL: low speed crystal oscillator(LXTAL) + \arg RCU_IRC8M: internal 8M RC oscillators(IRC8M) + \arg RCU_IRC40K: internal 40K RC oscillator(IRC40K) + \arg RCU_PLL_CK: phase locked loop(PLL) + \arg RCU_PLL1_CK: phase locked loop 1(CL series only) + \arg RCU_PLL2_CK: phase locked loop 2(CL series only) + \param[out] none + \retval none +*/ +void rcu_osci_off(rcu_osci_type_enum osci) +{ + RCU_REG_VAL(osci) &= ~BIT(RCU_BIT_POS(osci)); +} + +/*! + \brief enable the oscillator bypass mode, HXTALEN or LXTALEN must be reset before it + \param[in] osci: oscillator types, refer to rcu_osci_type_enum + only one parameter can be selected which is shown as below: + \arg RCU_HXTAL: high speed crystal oscillator(HXTAL) + \arg RCU_LXTAL: low speed crystal oscillator(LXTAL) + \param[out] none + \retval none +*/ +void rcu_osci_bypass_mode_enable(rcu_osci_type_enum osci) +{ + uint32_t reg; + + switch(osci){ + /* enable HXTAL to bypass mode */ + case RCU_HXTAL: + reg = RCU_CTL; + RCU_CTL &= ~RCU_CTL_HXTALEN; + RCU_CTL = (reg | RCU_CTL_HXTALBPS); + break; + /* enable LXTAL to bypass mode */ + case RCU_LXTAL: + reg = RCU_BDCTL; + RCU_BDCTL &= ~RCU_BDCTL_LXTALEN; + RCU_BDCTL = (reg | RCU_BDCTL_LXTALBPS); + break; + case RCU_IRC8M: + case RCU_IRC40K: + case RCU_PLL_CK: +#ifdef GD32F10X_CL + case RCU_PLL1_CK: + case RCU_PLL2_CK: +#endif /* GD32F10X_CL */ + break; + default: + break; + } +} + +/*! + \brief disable the oscillator bypass mode, HXTALEN or LXTALEN must be reset before it + \param[in] osci: oscillator types, refer to rcu_osci_type_enum + only one parameter can be selected which is shown as below: + \arg RCU_HXTAL: high speed crystal oscillator(HXTAL) + \arg RCU_LXTAL: low speed crystal oscillator(LXTAL) + \param[out] none + \retval none +*/ +void rcu_osci_bypass_mode_disable(rcu_osci_type_enum osci) +{ + uint32_t reg; + + switch(osci){ + /* disable HXTAL to bypass mode */ + case RCU_HXTAL: + reg = RCU_CTL; + RCU_CTL &= ~RCU_CTL_HXTALEN; + RCU_CTL = (reg & ~RCU_CTL_HXTALBPS); + break; + /* disable LXTAL to bypass mode */ + case RCU_LXTAL: + reg = RCU_BDCTL; + RCU_BDCTL &= ~RCU_BDCTL_LXTALEN; + RCU_BDCTL = (reg & ~RCU_BDCTL_LXTALBPS); + break; + case RCU_IRC8M: + case RCU_IRC40K: + case RCU_PLL_CK: +#ifdef GD32F10X_CL + case RCU_PLL1_CK: + case RCU_PLL2_CK: +#endif /* GD32F10X_CL */ + break; + default: + break; + } +} + +/*! + \brief enable the HXTAL clock monitor + \param[in] none + \param[out] none + \retval none +*/ + +void rcu_hxtal_clock_monitor_enable(void) +{ + RCU_CTL |= RCU_CTL_CKMEN; +} + +/*! + \brief disable the HXTAL clock monitor + \param[in] none + \param[out] none + \retval none +*/ +void rcu_hxtal_clock_monitor_disable(void) +{ + RCU_CTL &= ~RCU_CTL_CKMEN; +} + +/*! + \brief set the IRC8M adjust value + \param[in] irc8m_adjval: IRC8M adjust value, must be between 0 and 0x1F + \param[out] none + \retval none +*/ +void rcu_irc8m_adjust_value_set(uint8_t irc8m_adjval) +{ + uint32_t reg; + + reg = RCU_CTL; + /* reset the IRC8MADJ bits and set according to irc8m_adjval */ + reg &= ~RCU_CTL_IRC8MADJ; + RCU_CTL = (reg | ((irc8m_adjval & 0x1FU) << 3)); +} + +/*! + \brief deep-sleep mode voltage select + \param[in] dsvol: deep sleep mode voltage + only one parameter can be selected which is shown as below: + \arg RCU_DEEPSLEEP_V_1_2: the core voltage is 1.2V + \arg RCU_DEEPSLEEP_V_1_1: the core voltage is 1.1V + \arg RCU_DEEPSLEEP_V_1_0: the core voltage is 1.0V + \arg RCU_DEEPSLEEP_V_0_9: the core voltage is 0.9V + \param[out] none + \retval none +*/ +void rcu_deepsleep_voltage_set(uint32_t dsvol) +{ + dsvol &= RCU_DSV_DSLPVS; + RCU_DSV = dsvol; +} + +/*! + \brief get the system clock, bus and peripheral clock frequency + \param[in] clock: the clock frequency which to get + only one parameter can be selected which is shown as below: + \arg CK_SYS: system clock frequency + \arg CK_AHB: AHB clock frequency + \arg CK_APB1: APB1 clock frequency + \arg CK_APB2: APB2 clock frequency + \param[out] none + \retval clock frequency of system, AHB, APB1, APB2 +*/ +uint32_t rcu_clock_freq_get(rcu_clock_freq_enum clock) +{ + uint32_t sws, ck_freq = 0U; + uint32_t cksys_freq, ahb_freq, apb1_freq, apb2_freq; + uint32_t pllsel, predv0sel, pllmf,ck_src, idx, clk_exp; +#ifdef GD32F10X_CL + uint32_t predv0, predv1, pll1mf; +#endif /* GD32F10X_CL */ + + /* exponent of AHB, APB1 and APB2 clock divider */ + uint8_t ahb_exp[16] = {0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 6, 7, 8, 9}; + uint8_t apb1_exp[8] = {0, 0, 0, 0, 1, 2, 3, 4}; + uint8_t apb2_exp[8] = {0, 0, 0, 0, 1, 2, 3, 4}; + + sws = GET_BITS(RCU_CFG0, 2, 3); + switch(sws){ + /* IRC8M is selected as CK_SYS */ + case SEL_IRC8M: + cksys_freq = IRC8M_VALUE; + break; + /* HXTAL is selected as CK_SYS */ + case SEL_HXTAL: + cksys_freq = HXTAL_VALUE; + break; + /* PLL is selected as CK_SYS */ + case SEL_PLL: + /* PLL clock source selection, HXTAL or IRC8M/2 */ + pllsel = (RCU_CFG0 & RCU_CFG0_PLLSEL); + + if(RCU_PLLSRC_HXTAL == pllsel) { + /* PLL clock source is HXTAL */ + ck_src = HXTAL_VALUE; + +#if (defined(GD32F10X_MD) || defined(GD32F10X_HD) || defined(GD32F10X_XD)) + predv0sel = (RCU_CFG0 & RCU_CFG0_PREDV0); + /* PREDV0 input source clock divided by 2 */ + if(RCU_CFG0_PREDV0 == predv0sel){ + ck_src = HXTAL_VALUE/2U; + } +#elif defined(GD32F10X_CL) + predv0sel = (RCU_CFG1 & RCU_CFG1_PREDV0SEL); + /* source clock use PLL1 */ + if(RCU_PREDV0SRC_CKPLL1 == predv0sel){ + predv1 = (uint32_t)((RCU_CFG1 & RCU_CFG1_PREDV1) >> 4) + 1U; + pll1mf = (uint32_t)((RCU_CFG1 & RCU_CFG1_PLL1MF) >> 8) + 2U; + if(17U == pll1mf){ + pll1mf = 20U; + } + ck_src = (ck_src / predv1) * pll1mf; + } + predv0 = (RCU_CFG1 & RCU_CFG1_PREDV0) + 1U; + ck_src /= predv0; +#endif /* GD32F10X_HD and GD32F10X_XD */ + }else{ + /* PLL clock source is IRC8M/2 */ + ck_src = IRC8M_VALUE/2U; + } + + /* PLL multiplication factor */ + pllmf = GET_BITS(RCU_CFG0, 18, 21); + if((RCU_CFG0 & RCU_CFG0_PLLMF_4)){ + pllmf |= 0x10U; + } + if(pllmf < 15U){ + pllmf += 2U; + }else{ + pllmf += 1U; + } + + cksys_freq = ck_src * pllmf; + + #ifdef GD32F10X_CL + if(15U == pllmf){ + /* PLL source clock multiply by 6.5 */ + cksys_freq = ck_src * 6U + ck_src / 2U; + } + #endif /* GD32F10X_CL */ + + break; + /* IRC8M is selected as CK_SYS */ + default: + cksys_freq = IRC8M_VALUE; + break; + } + + /* calculate AHB clock frequency */ + idx = GET_BITS(RCU_CFG0, 4, 7); + clk_exp = ahb_exp[idx]; + ahb_freq = cksys_freq >> clk_exp; + + /* calculate APB1 clock frequency */ + idx = GET_BITS(RCU_CFG0, 8, 10); + clk_exp = apb1_exp[idx]; + apb1_freq = ahb_freq >> clk_exp; + + /* calculate APB2 clock frequency */ + idx = GET_BITS(RCU_CFG0, 11, 13); + clk_exp = apb2_exp[idx]; + apb2_freq = ahb_freq >> clk_exp; + + /* return the clocks frequency */ + switch(clock){ + case CK_SYS: + ck_freq = cksys_freq; + break; + case CK_AHB: + ck_freq = ahb_freq; + break; + case CK_APB1: + ck_freq = apb1_freq; + break; + case CK_APB2: + ck_freq = apb2_freq; + break; + default: + break; + } + return ck_freq; +} diff --git a/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_standard_peripheral/Source/gd32f10x_rtc.c b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_standard_peripheral/Source/gd32f10x_rtc.c new file mode 100644 index 0000000000..86768e0989 --- /dev/null +++ b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_standard_peripheral/Source/gd32f10x_rtc.c @@ -0,0 +1,276 @@ +/*! + \file gd32f10x_rtc.c + \brief RTC driver + + \version 2014-12-26, V1.0.0, firmware for GD32F10x + \version 2017-06-20, V2.0.0, firmware for GD32F10x + \version 2018-07-31, V2.1.0, firmware for GD32F10x + \version 2020-09-30, V2.2.0, firmware for GD32F10x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "gd32f10x_rtc.h" + +/* RTC register high / low bits mask */ +#define RTC_HIGH_BITS_MASK ((uint32_t)0x000F0000U) /* RTC high bits mask */ +#define RTC_LOW_BITS_MASK ((uint32_t)0x0000FFFFU) /* RTC low bits mask */ + +/* RTC register high bits offset */ +#define RTC_HIGH_BITS_OFFSET ((uint32_t)16U) + +/*! + \brief enter RTC configuration mode + \param[in] none + \param[out] none + \retval none +*/ +void rtc_configuration_mode_enter(void) +{ + RTC_CTL |= RTC_CTL_CMF; +} + +/*! + \brief exit RTC configuration mode + \param[in] none + \param[out] none + \retval none +*/ +void rtc_configuration_mode_exit(void) +{ + RTC_CTL &= ~RTC_CTL_CMF; +} + +/*! + \brief set RTC counter value + \param[in] cnt: RTC counter value + \param[out] none + \retval none +*/ +void rtc_counter_set(uint32_t cnt) +{ + rtc_configuration_mode_enter(); + /* set the RTC counter high bits */ + RTC_CNTH = (cnt >> RTC_HIGH_BITS_OFFSET); + /* set the RTC counter low bits */ + RTC_CNTL = (cnt & RTC_LOW_BITS_MASK); + rtc_configuration_mode_exit(); +} + +/*! + \brief set RTC prescaler value + \param[in] psc: RTC prescaler value + \param[out] none + \retval none +*/ +void rtc_prescaler_set(uint32_t psc) +{ + rtc_configuration_mode_enter(); + /* set the RTC prescaler high bits */ + RTC_PSCH = ((psc & RTC_HIGH_BITS_MASK) >> RTC_HIGH_BITS_OFFSET); + /* set the RTC prescaler low bits */ + RTC_PSCL = (psc & RTC_LOW_BITS_MASK); + rtc_configuration_mode_exit(); +} + +/*! + \brief wait RTC last write operation finished flag set + \param[in] none + \param[out] none + \retval none +*/ +void rtc_lwoff_wait(void) +{ + /* loop until LWOFF flag is set */ + while(RESET == (RTC_CTL & RTC_CTL_LWOFF)){ + } +} + +/*! + \brief wait RTC registers synchronized flag set + \param[in] none + \param[out] none + \retval none +*/ +void rtc_register_sync_wait(void) +{ + /* clear RSYNF flag */ + RTC_CTL &= ~RTC_CTL_RSYNF; + /* loop until RSYNF flag is set */ + while(RESET == (RTC_CTL & RTC_CTL_RSYNF)){ + } +} + +/*! + \brief set RTC alarm value + \param[in] alarm: RTC alarm value + \param[out] none + \retval none +*/ +void rtc_alarm_config(uint32_t alarm) +{ + rtc_configuration_mode_enter(); + /* set the alarm high bits */ + RTC_ALRMH = (alarm >> RTC_HIGH_BITS_OFFSET); + /* set the alarm low bits */ + RTC_ALRML = (alarm & RTC_LOW_BITS_MASK); + rtc_configuration_mode_exit(); +} + +/*! + \brief get RTC counter value + \param[in] none + \param[out] none + \retval RTC counter value +*/ +uint32_t rtc_counter_get(void) +{ + uint32_t temp = 0x0U; + + temp = RTC_CNTL; + temp |= (RTC_CNTH << RTC_HIGH_BITS_OFFSET); + return temp; +} + +/*! + \brief get RTC divider value + \param[in] none + \param[out] none + \retval RTC divider value +*/ +uint32_t rtc_divider_get(void) +{ + uint32_t temp = 0x00U; + + temp = ((RTC_DIVH & RTC_DIVH_DIV) << RTC_HIGH_BITS_OFFSET); + temp |= RTC_DIVL; + return temp; +} + +/*! + \brief get RTC flag status + \param[in] flag: specify which flag status to get + only one parameter can be selected which is shown as below: + \arg RTC_FLAG_SECOND: second interrupt flag + \arg RTC_FLAG_ALARM: alarm interrupt flag + \arg RTC_FLAG_OVERFLOW: overflow interrupt flag + \arg RTC_FLAG_RSYN: registers synchronized flag + \arg RTC_FLAG_LWOF: last write operation finished flag + \param[out] none + \retval SET or RESET +*/ +FlagStatus rtc_flag_get(uint32_t flag) +{ + if(RESET != (RTC_CTL & flag)){ + return SET; + }else{ + return RESET; + } +} + +/*! + \brief clear RTC flag status + \param[in] flag: specify which flag status to clear + one or more parameters can be selected which are shown as below: + \arg RTC_FLAG_SECOND: second interrupt flag + \arg RTC_FLAG_ALARM: alarm interrupt flag + \arg RTC_FLAG_OVERFLOW: overflow interrupt flag + \arg RTC_FLAG_RSYN: registers synchronized flag + \param[out] none + \retval none +*/ +void rtc_flag_clear(uint32_t flag) +{ + /* clear RTC flag */ + RTC_CTL &= ~flag; +} + +/*! + \brief get RTC interrupt flag status + \param[in] flag: specify which flag status to get + only one parameter can be selected which is shown as below: + \arg RTC_INT_FLAG_SECOND: second interrupt flag + \arg RTC_INT_FLAG_ALARM: alarm interrupt flag + \arg RTC_INT_FLAG_OVERFLOW: overflow interrupt flag + \param[out] none + \retval SET or RESET +*/ +FlagStatus rtc_interrupt_flag_get(uint32_t flag) +{ + if(RESET != (RTC_CTL & flag)){ + return SET; + }else{ + return RESET; + } +} + +/*! + \brief clear RTC interrupt flag status + \param[in] flag: specify which flag status to clear + one or more parameters can be selected which are shown as below: + \arg RTC_INT_FLAG_SECOND: second interrupt flag + \arg RTC_INT_FLAG_ALARM: alarm interrupt flag + \arg RTC_INT_FLAG_OVERFLOW: overflow interrupt flag + \param[out] none + \retval none +*/ +void rtc_interrupt_flag_clear(uint32_t flag) +{ + /* clear RTC interrupt flag */ + RTC_CTL &= ~flag; +} + +/*! + \brief enable RTC interrupt + \param[in] interrupt: specify which interrupt to enbale + one or more parameters can be selected which are shown as below: + \arg RTC_INT_SECOND: second interrupt + \arg RTC_INT_ALARM: alarm interrupt + \arg RTC_INT_OVERFLOW: overflow interrupt + \param[out] none + \retval none +*/ +void rtc_interrupt_enable(uint32_t interrupt) +{ + RTC_INTEN |= interrupt; +} + +/*! + \brief disable RTC interrupt + \param[in] interrupt: specify which interrupt to disbale + one or more parameters can be selected which are shown as below: + \arg RTC_INT_SECOND: second interrupt + \arg RTC_INT_ALARM: alarm interrupt + \arg RTC_INT_OVERFLOW: overflow interrupt + \param[out] none + \retval none +*/ +void rtc_interrupt_disable(uint32_t interrupt) +{ + RTC_INTEN &= ~interrupt; +} diff --git a/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_standard_peripheral/Source/gd32f10x_sdio.c b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_standard_peripheral/Source/gd32f10x_sdio.c new file mode 100644 index 0000000000..7a8ed96f13 --- /dev/null +++ b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_standard_peripheral/Source/gd32f10x_sdio.c @@ -0,0 +1,813 @@ +/*! + \file gd32f10x_sdio.c + \brief SDIO driver + + \version 2014-12-26, V1.0.0, firmware for GD32F10x + \version 2017-06-20, V2.0.0, firmware for GD32F10x + \version 2018-07-31, V2.1.0, firmware for GD32F10x + \version 2020-09-30, V2.2.0, firmware for GD32F10x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "gd32f10x_sdio.h" + +#define DEFAULT_RESET_VALUE 0x00000000U + +/*! + \brief deinitialize the SDIO + \param[in] none + \param[out] none + \retval none +*/ +void sdio_deinit(void) +{ + SDIO_PWRCTL = DEFAULT_RESET_VALUE; + SDIO_CLKCTL = DEFAULT_RESET_VALUE; + SDIO_CMDAGMT = DEFAULT_RESET_VALUE; + SDIO_CMDCTL = DEFAULT_RESET_VALUE; + SDIO_DATATO = DEFAULT_RESET_VALUE; + SDIO_DATALEN = DEFAULT_RESET_VALUE; + SDIO_DATACTL = DEFAULT_RESET_VALUE; + SDIO_INTC = DEFAULT_RESET_VALUE; + SDIO_INTEN = DEFAULT_RESET_VALUE; +} + +/*! + \brief configure the SDIO clock + \param[in] clock_edge: SDIO_CLK clock edge + only one parameter can be selected which is shown as below: + \arg SDIO_SDIOCLKEDGE_RISING: select the rising edge of the SDIOCLK to generate SDIO_CLK + \arg SDIO_SDIOCLKEDGE_FALLING: select the falling edge of the SDIOCLK to generate SDIO_CLK + \param[in] clock_bypass: clock bypass + only one parameter can be selected which is shown as below: + \arg SDIO_CLOCKBYPASS_ENABLE: clock bypass + \arg SDIO_CLOCKBYPASS_DISABLE: no bypass + \param[in] clock_powersave: SDIO_CLK clock dynamic switch on/off for power saving + only one parameter can be selected which is shown as below: + \arg SDIO_CLOCKPWRSAVE_ENABLE: SDIO_CLK closed when bus is idle + \arg SDIO_CLOCKPWRSAVE_DISABLE: SDIO_CLK clock is always on + \param[in] clock_division: clock division, less than 256 + \param[out] none + \retval none +*/ +void sdio_clock_config(uint32_t clock_edge, uint32_t clock_bypass, uint32_t clock_powersave, uint16_t clock_division) +{ + uint32_t clock_config = 0U; + clock_config = SDIO_CLKCTL; + /* reset the CLKEDGE, CLKBYP, CLKPWRSAV, DIV */ + clock_config &= ~(SDIO_CLKCTL_CLKEDGE | SDIO_CLKCTL_CLKBYP | SDIO_CLKCTL_CLKPWRSAV | SDIO_CLKCTL_DIV); + + /* configure the SDIO_CLKCTL according to the parameters */ + clock_config |= (clock_edge | clock_bypass | clock_powersave | clock_division); + SDIO_CLKCTL = clock_config; +} + +/*! + \brief enable hardware clock control + \param[in] none + \param[out] none + \retval none +*/ +void sdio_hardware_clock_enable(void) +{ + SDIO_CLKCTL |= SDIO_CLKCTL_HWCLKEN; +} + +/*! + \brief disable hardware clock control + \param[in] none + \param[out] none + \retval none +*/ +void sdio_hardware_clock_disable(void) +{ + SDIO_CLKCTL &= ~SDIO_CLKCTL_HWCLKEN; +} + +/*! + \brief set different SDIO card bus mode + \param[in] bus_mode: SDIO card bus mode + only one parameter can be selected which is shown as below: + \arg SDIO_BUSMODE_1BIT: 1-bit SDIO card bus mode + \arg SDIO_BUSMODE_4BIT: 4-bit SDIO card bus mode + \arg SDIO_BUSMODE_8BIT: 8-bit SDIO card bus mode + \param[out] none + \retval none +*/ +void sdio_bus_mode_set(uint32_t bus_mode) +{ + /* reset the SDIO card bus mode bits and set according to bus_mode */ + SDIO_CLKCTL &= ~SDIO_CLKCTL_BUSMODE; + SDIO_CLKCTL |= bus_mode; +} + +/*! + \brief set the SDIO power state + \param[in] power_state: SDIO power state + only one parameter can be selected which is shown as below: + \arg SDIO_POWER_ON: SDIO power on + \arg SDIO_POWER_OFF: SDIO power off + \param[out] none + \retval none +*/ +void sdio_power_state_set(uint32_t power_state) +{ + SDIO_PWRCTL = power_state; +} + +/*! + \brief get the SDIO power state + \param[in] none + \param[out] none + \retval SDIO power state + only one parameter can be selected which is shown as below: + \arg SDIO_POWER_ON: SDIO power on + \arg SDIO_POWER_OFF: SDIO power off +*/ +uint32_t sdio_power_state_get(void) +{ + return SDIO_PWRCTL; +} + +/*! + \brief enable SDIO_CLK clock output + \param[in] none + \param[out] none + \retval none +*/ +void sdio_clock_enable(void) +{ + SDIO_CLKCTL |= SDIO_CLKCTL_CLKEN; +} + +/*! + \brief disable SDIO_CLK clock output + \param[in] none + \param[out] none + \retval none +*/ +void sdio_clock_disable(void) +{ + SDIO_CLKCTL &= ~SDIO_CLKCTL_CLKEN; +} + +/*! + \brief configure the command and response + \param[in] cmd_index: command index, refer to the related specifications + \param[in] cmd_argument: command argument, refer to the related specifications + \param[in] response_type: response type + only one parameter can be selected which is shown as below: + \arg SDIO_RESPONSETYPE_NO: no response + \arg SDIO_RESPONSETYPE_SHORT: short response + \arg SDIO_RESPONSETYPE_LONG: long response + \param[out] none + \retval none +*/ +void sdio_command_response_config(uint32_t cmd_index, uint32_t cmd_argument, uint32_t response_type) +{ + uint32_t cmd_config = 0U; + /* reset the command index, command argument and response type */ + SDIO_CMDAGMT &= ~SDIO_CMDAGMT_CMDAGMT; + SDIO_CMDAGMT = cmd_argument; + cmd_config = SDIO_CMDCTL; + cmd_config &= ~(SDIO_CMDCTL_CMDIDX | SDIO_CMDCTL_CMDRESP); + /* configure SDIO_CMDCTL and SDIO_CMDAGMT according to the parameters */ + cmd_config |= (cmd_index | response_type); + SDIO_CMDCTL = cmd_config; +} + +/*! + \brief set the command state machine wait type + \param[in] wait_type: wait type + only one parameter can be selected which is shown as below: + \arg SDIO_WAITTYPE_NO: not wait interrupt + \arg SDIO_WAITTYPE_INTERRUPT: wait interrupt + \arg SDIO_WAITTYPE_DATAEND: wait the end of data transfer + \param[out] none + \retval none +*/ +void sdio_wait_type_set(uint32_t wait_type) +{ + /* reset INTWAIT and WAITDEND */ + SDIO_CMDCTL &= ~(SDIO_CMDCTL_INTWAIT | SDIO_CMDCTL_WAITDEND); + /* set the wait type according to wait_type */ + SDIO_CMDCTL |= wait_type; +} + +/*! + \brief enable the CSM(command state machine) + \param[in] none + \param[out] none + \retval none +*/ +void sdio_csm_enable(void) +{ + SDIO_CMDCTL |= SDIO_CMDCTL_CSMEN; +} + +/*! + \brief disable the CSM(command state machine) + \param[in] none + \param[out] none + \retval none +*/ +void sdio_csm_disable(void) +{ + SDIO_CMDCTL &= ~SDIO_CMDCTL_CSMEN; +} + +/*! + \brief get the last response command index + \param[in] none + \param[out] none + \retval last response command index +*/ +uint8_t sdio_command_index_get(void) +{ + return (uint8_t)SDIO_RSPCMDIDX; +} + +/*! + \brief get the response for the last received command + \param[in] responsex: SDIO response + only one parameter can be selected which is shown as below: + \arg SDIO_RESPONSE0: card response[31:0]/card response[127:96] + \arg SDIO_RESPONSE1: card response[95:64] + \arg SDIO_RESPONSE2: card response[63:32] + \arg SDIO_RESPONSE3: card response[31:1], plus bit 0 + \param[out] none + \retval response for the last received command +*/ +uint32_t sdio_response_get(uint32_t responsex) +{ + uint32_t resp_content = 0U; + switch(responsex){ + case SDIO_RESPONSE0: + resp_content = SDIO_RESP0; + break; + case SDIO_RESPONSE1: + resp_content = SDIO_RESP1; + break; + case SDIO_RESPONSE2: + resp_content = SDIO_RESP2; + break; + case SDIO_RESPONSE3: + resp_content = SDIO_RESP3; + break; + default: + break; + } + return resp_content; +} + +/*! + \brief configure the data timeout, data length and data block size + \param[in] data_timeout: data timeout period in card bus clock periods + \param[in] data_length: number of data bytes to be transferred + \param[in] data_blocksize: size of data block for block transfer + only one parameter can be selected which is shown as below: + \arg SDIO_DATABLOCKSIZE_1BYTE: block size = 1 byte + \arg SDIO_DATABLOCKSIZE_2BYTES: block size = 2 bytes + \arg SDIO_DATABLOCKSIZE_4BYTES: block size = 4 bytes + \arg SDIO_DATABLOCKSIZE_8BYTES: block size = 8 bytes + \arg SDIO_DATABLOCKSIZE_16BYTES: block size = 16 bytes + \arg SDIO_DATABLOCKSIZE_32BYTES: block size = 32 bytes + \arg SDIO_DATABLOCKSIZE_64BYTES: block size = 64 bytes + \arg SDIO_DATABLOCKSIZE_128BYTES: block size = 128 bytes + \arg SDIO_DATABLOCKSIZE_256BYTES: block size = 256 bytes + \arg SDIO_DATABLOCKSIZE_512BYTES: block size = 512 bytes + \arg SDIO_DATABLOCKSIZE_1024BYTES: block size = 1024 bytes + \arg SDIO_DATABLOCKSIZE_2048BYTES: block size = 2048 bytes + \arg SDIO_DATABLOCKSIZE_4096BYTES: block size = 4096 bytes + \arg SDIO_DATABLOCKSIZE_8192BYTES: block size = 8192 bytes + \arg SDIO_DATABLOCKSIZE_16384BYTES: block size = 16384 bytes + \param[out] none + \retval none +*/ +void sdio_data_config(uint32_t data_timeout, uint32_t data_length, uint32_t data_blocksize) +{ + /* reset data timeout, data length and data block size */ + SDIO_DATATO &= ~SDIO_DATATO_DATATO; + SDIO_DATALEN &= ~SDIO_DATALEN_DATALEN; + SDIO_DATACTL &= ~SDIO_DATACTL_BLKSZ; + /* configure the related parameters of data */ + SDIO_DATATO = data_timeout; + SDIO_DATALEN = data_length; + SDIO_DATACTL |= data_blocksize; +} + +/*! + \brief configure the data transfer mode and direction + \param[in] transfer_mode: mode of data transfer + only one parameter can be selected which is shown as below: + \arg SDIO_TRANSMODE_BLOCK: block transfer + \arg SDIO_TRANSMODE_STREAM: stream transfer or SDIO multibyte transfer + \param[in] transfer_direction: data transfer direction, read or write + only one parameter can be selected which is shown as below: + \arg SDIO_TRANSDIRECTION_TOCARD: write data to card + \arg SDIO_TRANSDIRECTION_TOSDIO: read data from card + \param[out] none + \retval none +*/ +void sdio_data_transfer_config(uint32_t transfer_mode, uint32_t transfer_direction) +{ + uint32_t data_trans = 0U; + /* reset the data transfer mode, transfer direction and set according to the parameters */ + data_trans = SDIO_DATACTL; + data_trans &= ~(SDIO_DATACTL_TRANSMOD | SDIO_DATACTL_DATADIR); + data_trans |= (transfer_mode | transfer_direction); + SDIO_DATACTL = data_trans; +} + +/*! + \brief enable the DSM(data state machine) for data transfer + \param[in] none + \param[out] none + \retval none +*/ +void sdio_dsm_enable(void) +{ + SDIO_DATACTL |= SDIO_DATACTL_DATAEN; +} + +/*! + \brief disable the DSM(data state machine) + \param[in] none + \param[out] none + \retval none +*/ +void sdio_dsm_disable(void) +{ + SDIO_DATACTL &= ~SDIO_DATACTL_DATAEN; +} + +/*! + \brief write data(one word) to the transmit FIFO + \param[in] data: 32-bit data write to card + \param[out] none + \retval none +*/ +void sdio_data_write(uint32_t data) +{ + SDIO_FIFO = data; +} + +/*! + \brief read data(one word) from the receive FIFO + \param[in] none + \param[out] none + \retval received data +*/ +uint32_t sdio_data_read(void) +{ + return SDIO_FIFO; +} + +/*! + \brief get the number of remaining data bytes to be transferred to card + \param[in] none + \param[out] none + \retval number of remaining data bytes to be transferred +*/ +uint32_t sdio_data_counter_get(void) +{ + return SDIO_DATACNT; +} + +/*! + \brief get the number of words remaining to be written or read from FIFO + \param[in] none + \param[out] none + \retval remaining number of words +*/ +uint32_t sdio_fifo_counter_get(void) +{ + return SDIO_FIFOCNT; +} + +/*! + \brief enable the DMA request for SDIO + \param[in] none + \param[out] none + \retval none +*/ +void sdio_dma_enable(void) +{ + SDIO_DATACTL |= SDIO_DATACTL_DMAEN; +} + +/*! + \brief disable the DMA request for SDIO + \param[in] none + \param[out] none + \retval none +*/ +void sdio_dma_disable(void) +{ + SDIO_DATACTL &= ~SDIO_DATACTL_DMAEN; +} + +/*! + \brief get the flags state of SDIO + \param[in] flag: flags state of SDIO + only one parameter can be selected which is shown as below: + \arg SDIO_FLAG_CCRCERR: command response received (CRC check failed) flag + \arg SDIO_FLAG_DTCRCERR: data block sent/received (CRC check failed) flag + \arg SDIO_FLAG_CMDTMOUT: command response timeout flag + \arg SDIO_FLAG_DTTMOUT: data timeout flag + \arg SDIO_FLAG_TXURE: transmit FIFO underrun error occurs flag + \arg SDIO_FLAG_RXORE: received FIFO overrun error occurs flag + \arg SDIO_FLAG_CMDRECV: command response received (CRC check passed) flag + \arg SDIO_FLAG_CMDSEND: command sent (no response required) flag + \arg SDIO_FLAG_DTEND: data end (data counter, SDIO_DATACNT, is zero) flag + \arg SDIO_FLAG_STBITE: start bit error in the bus flag + \arg SDIO_FLAG_DTBLKEND: data block sent/received (CRC check passed) flag + \arg SDIO_FLAG_CMDRUN: command transmission in progress flag + \arg SDIO_FLAG_TXRUN: data transmission in progress flag + \arg SDIO_FLAG_RXRUN: data reception in progress flag + \arg SDIO_FLAG_TFH: transmit FIFO is half empty flag: at least 8 words can be written into the FIFO + \arg SDIO_FLAG_RFH: receive FIFO is half full flag: at least 8 words can be read in the FIFO + \arg SDIO_FLAG_TFF: transmit FIFO is full flag + \arg SDIO_FLAG_RFF: receive FIFO is full flag + \arg SDIO_FLAG_TFE: transmit FIFO is empty flag + \arg SDIO_FLAG_RFE: receive FIFO is empty flag + \arg SDIO_FLAG_TXDTVAL: data is valid in transmit FIFO flag + \arg SDIO_FLAG_RXDTVAL: data is valid in receive FIFO flag + \arg SDIO_FLAG_SDIOINT: SD I/O interrupt received flag + \arg SDIO_FLAG_ATAEND: CE-ATA command completion signal received (only for CMD61) flag + \param[out] none + \retval FlagStatus: SET or RESET +*/ +FlagStatus sdio_flag_get(uint32_t flag) +{ + FlagStatus temp_flag = RESET; + if(RESET != (SDIO_STAT & flag)){ + temp_flag = SET; + } + return temp_flag; +} + +/*! + \brief clear the pending flags of SDIO + \param[in] flag: flags state of SDIO + only one parameter can be selected which is shown as below: + \arg SDIO_FLAG_CCRCERR: command response received (CRC check failed) flag + \arg SDIO_FLAG_DTCRCERR: data block sent/received (CRC check failed) flag + \arg SDIO_FLAG_CMDTMOUT: command response timeout flag + \arg SDIO_FLAG_DTTMOUT: data timeout flag + \arg SDIO_FLAG_TXURE: transmit FIFO underrun error occurs flag + \arg SDIO_FLAG_RXORE: received FIFO overrun error occurs flag + \arg SDIO_FLAG_CMDRECV: command response received (CRC check passed) flag + \arg SDIO_FLAG_CMDSEND: command sent (no response required) flag + \arg SDIO_FLAG_DTEND: data end (data counter, SDIO_DATACNT, is zero) flag + \arg SDIO_FLAG_STBITE: start bit error in the bus flag + \arg SDIO_FLAG_DTBLKEND: data block sent/received (CRC check passed) flag + \arg SDIO_FLAG_SDIOINT: SD I/O interrupt received flag + \arg SDIO_FLAG_ATAEND: CE-ATA command completion signal received (only for CMD61) flag + \param[out] none + \retval none +*/ +void sdio_flag_clear(uint32_t flag) +{ + SDIO_INTC = flag; +} + +/*! + \brief enable the SDIO interrupt + \param[in] int_flag: interrupt flags state of SDIO + only one parameter can be selected which is shown as below: + \arg SDIO_INT_CCRCERR: SDIO CCRCERR interrupt + \arg SDIO_INT_DTCRCERR: SDIO DTCRCERR interrupt + \arg SDIO_INT_CMDTMOUT: SDIO CMDTMOUT interrupt + \arg SDIO_INT_DTTMOUT: SDIO DTTMOUT interrupt + \arg SDIO_INT_TXURE: SDIO TXURE interrupt + \arg SDIO_INT_RXORE: SDIO RXORE interrupt + \arg SDIO_INT_CMDRECV: SDIO CMDRECV interrupt + \arg SDIO_INT_CMDSEND: SDIO CMDSEND interrupt + \arg SDIO_INT_DTEND: SDIO DTEND interrupt + \arg SDIO_INT_STBITE: SDIO STBITE interrupt + \arg SDIO_INT_DTBLKEND: SDIO DTBLKEND interrupt + \arg SDIO_INT_CMDRUN: SDIO CMDRUN interrupt + \arg SDIO_INT_TXRUN: SDIO TXRUN interrupt + \arg SDIO_INT_RXRUN: SDIO RXRUN interrupt + \arg SDIO_INT_TFH: SDIO TFH interrupt + \arg SDIO_INT_RFH: SDIO RFH interrupt + \arg SDIO_INT_TFF: SDIO TFF interrupt + \arg SDIO_INT_RFF: SDIO RFF interrupt + \arg SDIO_INT_TFE: SDIO TFE interrupt + \arg SDIO_INT_RFE: SDIO RFE interrupt + \arg SDIO_INT_TXDTVAL: SDIO TXDTVAL interrupt + \arg SDIO_INT_RXDTVAL: SDIO RXDTVAL interrupt + \arg SDIO_INT_SDIOINT: SDIO SDIOINT interrupt + \arg SDIO_INT_ATAEND: SDIO ATAEND interrupt + \param[out] none + \retval none +*/ +void sdio_interrupt_enable(uint32_t int_flag) +{ + SDIO_INTEN |= int_flag; +} + +/*! + \brief disable the SDIO interrupt + \param[in] int_flag: interrupt flags state of SDIO + only one parameter can be selected which is shown as below: + \arg SDIO_INT_CCRCERR: SDIO CCRCERR interrupt + \arg SDIO_INT_DTCRCERR: SDIO DTCRCERR interrupt + \arg SDIO_INT_CMDTMOUT: SDIO CMDTMOUT interrupt + \arg SDIO_INT_DTTMOUT: SDIO DTTMOUT interrupt + \arg SDIO_INT_TXURE: SDIO TXURE interrupt + \arg SDIO_INT_RXORE: SDIO RXORE interrupt + \arg SDIO_INT_CMDRECV: SDIO CMDRECV interrupt + \arg SDIO_INT_CMDSEND: SDIO CMDSEND interrupt + \arg SDIO_INT_DTEND: SDIO DTEND interrupt + \arg SDIO_INT_STBITE: SDIO STBITE interrupt + \arg SDIO_INT_DTBLKEND: SDIO DTBLKEND interrupt + \arg SDIO_INT_CMDRUN: SDIO CMDRUN interrupt + \arg SDIO_INT_TXRUN: SDIO TXRUN interrupt + \arg SDIO_INT_RXRUN: SDIO RXRUN interrupt + \arg SDIO_INT_TFH: SDIO TFH interrupt + \arg SDIO_INT_RFH: SDIO RFH interrupt + \arg SDIO_INT_TFF: SDIO TFF interrupt + \arg SDIO_INT_RFF: SDIO RFF interrupt + \arg SDIO_INT_TFE: SDIO TFE interrupt + \arg SDIO_INT_RFE: SDIO RFE interrupt + \arg SDIO_INT_TXDTVAL: SDIO TXDTVAL interrupt + \arg SDIO_INT_RXDTVAL: SDIO RXDTVAL interrupt + \arg SDIO_INT_SDIOINT: SDIO SDIOINT interrupt + \arg SDIO_INT_ATAEND: SDIO ATAEND interrupt + \param[out] none + \retval none +*/ +void sdio_interrupt_disable(uint32_t int_flag) +{ + SDIO_INTEN &= ~int_flag; +} + +/*! + \brief get the interrupt flags state of SDIO + \param[in] int_flag: interrupt flags state of SDIO + only one parameter can be selected which is shown as below: + \arg SDIO_INT_FLAG_CCRCERR: SDIO CCRCERR interrupt + \arg SDIO_INT_FLAG_DTCRCERR: SDIO DTCRCERR interrupt + \arg SDIO_INT_FLAG_CMDTMOUT: SDIO CMDTMOUT interrupt + \arg SDIO_INT_FLAG_DTTMOUT: SDIO DTTMOUT interrupt + \arg SDIO_INT_FLAG_TXURE: SDIO TXURE interrupt + \arg SDIO_INT_FLAG_RXORE: SDIO RXORE interrupt + \arg SDIO_INT_FLAG_CMDRECV: SDIO CMDRECV interrupt + \arg SDIO_INT_FLAG_CMDSEND: SDIO CMDSEND interrupt + \arg SDIO_INT_FLAG_DTEND: SDIO DTEND interrupt + \arg SDIO_INT_FLAG_STBITE: SDIO STBITE interrupt + \arg SDIO_INT_FLAG_DTBLKEND: SDIO DTBLKEND interrupt + \arg SDIO_INT_FLAG_CMDRUN: SDIO CMDRUN interrupt + \arg SDIO_INT_FLAG_TXRUN: SDIO TXRUN interrupt + \arg SDIO_INT_FLAG_RXRUN: SDIO RXRUN interrupt + \arg SDIO_INT_FLAG_TFH: SDIO TFH interrupt + \arg SDIO_INT_FLAG_RFH: SDIO RFH interrupt + \arg SDIO_INT_FLAG_TFF: SDIO TFF interrupt + \arg SDIO_INT_FLAG_RFF: SDIO RFF interrupt + \arg SDIO_INT_FLAG_TFE: SDIO TFE interrupt + \arg SDIO_INT_FLAG_RFE: SDIO RFE interrupt + \arg SDIO_INT_FLAG_TXDTVAL: SDIO TXDTVAL interrupt + \arg SDIO_INT_FLAG_RXDTVAL: SDIO RXDTVAL interrupt + \arg SDIO_INT_FLAG_SDIOINT: SDIO SDIOINT interrupt + \arg SDIO_INT_FLAG_ATAEND: SDIO ATAEND interrupt + \param[out] none + \retval FlagStatus: SET or RESET +*/ +FlagStatus sdio_interrupt_flag_get(uint32_t int_flag) +{ + uint32_t state = 0U; + state = SDIO_STAT; + if(state & int_flag){ + state = SDIO_INTEN; + /* check whether the corresponding bit in SDIO_INTEN is set or not */ + if(state & int_flag){ + return SET; + } + } + return RESET; +} + +/*! + \brief clear the interrupt pending flags of SDIO + \param[in] int_flag: interrupt flags state of SDIO + only one parameter can be selected which is shown as below: + \arg SDIO_INT_FLAG_CCRCERR: command response received (CRC check failed) flag + \arg SDIO_INT_FLAG_DTCRCERR: data block sent/received (CRC check failed) flag + \arg SDIO_INT_FLAG_CMDTMOUT: command response timeout flag + \arg SDIO_INT_FLAG_DTTMOUT: data timeout flag + \arg SDIO_INT_FLAG_TXURE: transmit FIFO underrun error occurs flag + \arg SDIO_INT_FLAG_RXORE: received FIFO overrun error occurs flag + \arg SDIO_INT_FLAG_CMDRECV: command response received (CRC check passed) flag + \arg SDIO_INT_FLAG_CMDSEND: command sent (no response required) flag + \arg SDIO_INT_FLAG_DTEND: data end (data counter, SDIO_DATACNT, is zero) flag + \arg SDIO_INT_FLAG_STBITE: start bit error in the bus flag + \arg SDIO_INT_FLAG_DTBLKEND: data block sent/received (CRC check passed) flag + \arg SDIO_INT_FLAG_SDIOINT: SD I/O interrupt received flag + \arg SDIO_INT_FLAG_ATAEND: CE-ATA command completion signal received (only for CMD61) flag + \param[out] none + \retval none +*/ +void sdio_interrupt_flag_clear(uint32_t int_flag) +{ + SDIO_INTC = int_flag; +} + +/*! + \brief enable the read wait mode(SD I/O only) + \param[in] none + \param[out] none + \retval none +*/ +void sdio_readwait_enable(void) +{ + SDIO_DATACTL |= SDIO_DATACTL_RWEN; +} + +/*! + \brief disable the read wait mode(SD I/O only) + \param[in] none + \param[out] none + \retval none +*/ +void sdio_readwait_disable(void) +{ + SDIO_DATACTL &= ~SDIO_DATACTL_RWEN; +} + +/*! + \brief enable the function that stop the read wait process(SD I/O only) + \param[in] none + \param[out] none + \retval none +*/ +void sdio_stop_readwait_enable(void) +{ + SDIO_DATACTL |= SDIO_DATACTL_RWSTOP; +} + +/*! + \brief disable the function that stop the read wait process(SD I/O only) + \param[in] none + \param[out] none + \retval none +*/ +void sdio_stop_readwait_disable(void) +{ + SDIO_DATACTL &= ~SDIO_DATACTL_RWSTOP; +} + +/*! + \brief set the read wait type(SD I/O only) + \param[in] readwait_type: SD I/O read wait type + only one parameter can be selected which is shown as below: + \arg SDIO_READWAITTYPE_CLK: read wait control by stopping SDIO_CLK + \arg SDIO_READWAITTYPE_DAT2: read wait control using SDIO_DAT[2] + \param[out] none + \retval none +*/ +void sdio_readwait_type_set(uint32_t readwait_type) +{ + if(SDIO_READWAITTYPE_CLK == readwait_type){ + SDIO_DATACTL |= SDIO_DATACTL_RWTYPE; + }else{ + SDIO_DATACTL &= ~SDIO_DATACTL_RWTYPE; + } +} + +/*! + \brief enable the SD I/O mode specific operation(SD I/O only) + \param[in] none + \param[out] none + \retval none +*/ +void sdio_operation_enable(void) +{ + SDIO_DATACTL |= SDIO_DATACTL_IOEN; +} + +/*! + \brief disable the SD I/O mode specific operation(SD I/O only) + \param[in] none + \param[out] none + \retval none +*/ +void sdio_operation_disable(void) +{ + SDIO_DATACTL &= ~SDIO_DATACTL_IOEN; +} + +/*! + \brief enable the SD I/O suspend operation(SD I/O only) + \param[in] none + \param[out] none + \retval none +*/ +void sdio_suspend_enable(void) +{ + SDIO_CMDCTL |= SDIO_CMDCTL_SUSPEND; +} + +/*! + \brief disable the SD I/O suspend operation(SD I/O only) + \param[in] none + \param[out] none + \retval none +*/ +void sdio_suspend_disable(void) +{ + SDIO_CMDCTL &= ~SDIO_CMDCTL_SUSPEND; +} + +/*! + \brief enable the CE-ATA command(CE-ATA only) + \param[in] none + \param[out] none + \retval none +*/ +void sdio_ceata_command_enable(void) +{ + SDIO_CMDCTL |= SDIO_CMDCTL_ATAEN; +} + +/*! + \brief disable the CE-ATA command(CE-ATA only) + \param[in] none + \param[out] none + \retval none +*/ +void sdio_ceata_command_disable(void) +{ + SDIO_CMDCTL &= ~SDIO_CMDCTL_ATAEN; +} + +/*! + \brief enable the CE-ATA interrupt(CE-ATA only) + \param[in] none + \param[out] none + \retval none +*/ +void sdio_ceata_interrupt_enable(void) +{ + SDIO_CMDCTL &= ~SDIO_CMDCTL_NINTEN; +} + +/*! + \brief disable the CE-ATA interrupt(CE-ATA only) + \param[in] none + \param[out] none + \retval none +*/ +void sdio_ceata_interrupt_disable(void) +{ + SDIO_CMDCTL |= SDIO_CMDCTL_NINTEN; +} + +/*! + \brief enable the CE-ATA command completion signal(CE-ATA only) + \param[in] none + \param[out] none + \retval none +*/ +void sdio_ceata_command_completion_enable(void) +{ + SDIO_CMDCTL |= SDIO_CMDCTL_ENCMDC; +} + +/*! + \brief disable the CE-ATA command completion signal(CE-ATA only) + \param[in] none + \param[out] none + \retval none +*/ +void sdio_ceata_command_completion_disable(void) +{ + SDIO_CMDCTL &= ~SDIO_CMDCTL_ENCMDC; +} diff --git a/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_standard_peripheral/Source/gd32f10x_spi.c b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_standard_peripheral/Source/gd32f10x_spi.c new file mode 100644 index 0000000000..6cb4a22dec --- /dev/null +++ b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_standard_peripheral/Source/gd32f10x_spi.c @@ -0,0 +1,717 @@ +/*! + \file gd32f10x_spi.c + \brief SPI driver + + \version 2014-12-26, V1.0.0, firmware for GD32F10x + \version 2017-06-20, V2.0.0, firmware for GD32F10x + \version 2018-07-31, V2.1.0, firmware for GD32F10x + \version 2020-09-30, V2.2.0, firmware for GD32F10x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "gd32f10x_spi.h" + +/* SPI/I2S parameter initialization mask */ +#define SPI_INIT_MASK ((uint32_t)0x00003040U) /*!< SPI parameter initialization mask */ +#define I2S_INIT_MASK ((uint32_t)0x0000F047U) /*!< I2S parameter initialization mask */ + +/* I2S clock source selection, multiplication and division mask */ +#define I2S1_CLOCK_SEL ((uint32_t)0x00020000U) /* I2S1 clock source selection */ +#define I2S2_CLOCK_SEL ((uint32_t)0x00040000U) /* I2S2 clock source selection */ +#define I2S_CLOCK_MUL_MASK ((uint32_t)0x0000F000U) /* I2S clock multiplication mask */ +#define I2S_CLOCK_DIV_MASK ((uint32_t)0x000000F0U) /* I2S clock division mask */ + +/* default value and offset */ +#define SPI_I2SPSC_DEFAULT_VALUE ((uint32_t)0x00000002U) /* default value of SPI_I2SPSC register */ +#define RCU_CFG1_PREDV1_OFFSET 4U /* PREDV1 offset in RCU_CFG1 */ +#define RCU_CFG1_PLL2MF_OFFSET 12U /* PLL2MF offset in RCU_CFG1 */ + +/*! + \brief reset SPI and I2S + \param[in] spi_periph: SPIx(x=0,1,2) + \param[out] none + \retval none +*/ +void spi_i2s_deinit(uint32_t spi_periph) +{ + switch(spi_periph){ + case SPI0: + /* reset SPI0 */ + rcu_periph_reset_enable(RCU_SPI0RST); + rcu_periph_reset_disable(RCU_SPI0RST); + break; + case SPI1: + /* reset SPI1 and I2S1 */ + rcu_periph_reset_enable(RCU_SPI1RST); + rcu_periph_reset_disable(RCU_SPI1RST); + break; + case SPI2: + /* reset SPI2 and I2S2 */ + rcu_periph_reset_enable(RCU_SPI2RST); + rcu_periph_reset_disable(RCU_SPI2RST); + break; + default : + break; + } +} + +/*! + \brief initialize the parameters of SPI struct with the default values + \param[in] spi_struct: SPI parameter stuct + \param[out] none + \retval none +*/ +void spi_struct_para_init(spi_parameter_struct* spi_struct) +{ + /* set the SPI struct with the default values */ + spi_struct->device_mode = SPI_SLAVE; + spi_struct->trans_mode = SPI_TRANSMODE_FULLDUPLEX; + spi_struct->frame_size = SPI_FRAMESIZE_8BIT; + spi_struct->nss = SPI_NSS_HARD; + spi_struct->clock_polarity_phase = SPI_CK_PL_LOW_PH_1EDGE; + spi_struct->prescale = SPI_PSC_2; +} + +/*! + \brief initialize SPI parameter + \param[in] spi_periph: SPIx(x=0,1,2) + \param[in] spi_struct: SPI parameter initialization stuct members of the structure + and the member values are shown as below: + device_mode: SPI_MASTER, SPI_SLAVE + trans_mode: SPI_TRANSMODE_FULLDUPLEX, SPI_TRANSMODE_RECEIVEONLY, + SPI_TRANSMODE_BDRECEIVE, SPI_TRANSMODE_BDTRANSMIT + frame_size: SPI_FRAMESIZE_16BIT, SPI_FRAMESIZE_8BIT + nss: SPI_NSS_SOFT, SPI_NSS_HARD + endian: SPI_ENDIAN_MSB, SPI_ENDIAN_LSB + clock_polarity_phase: SPI_CK_PL_LOW_PH_1EDGE, SPI_CK_PL_HIGH_PH_1EDGE + SPI_CK_PL_LOW_PH_2EDGE, SPI_CK_PL_HIGH_PH_2EDGE + prescale: SPI_PSC_n (n=2,4,8,16,32,64,128,256) + \param[out] none + \retval none +*/ +void spi_init(uint32_t spi_periph, spi_parameter_struct* spi_struct) +{ + uint32_t reg = 0U; + reg = SPI_CTL0(spi_periph); + reg &= SPI_INIT_MASK; + + /* select SPI as master or slave */ + reg |= spi_struct->device_mode; + /* select SPI transfer mode */ + reg |= spi_struct->trans_mode; + /* select SPI frame size */ + reg |= spi_struct->frame_size; + /* select SPI NSS use hardware or software */ + reg |= spi_struct->nss; + /* select SPI LSB or MSB */ + reg |= spi_struct->endian; + /* select SPI polarity and phase */ + reg |= spi_struct->clock_polarity_phase; + /* select SPI prescale to adjust transmit speed */ + reg |= spi_struct->prescale; + + /* write to SPI_CTL0 register */ + SPI_CTL0(spi_periph) = (uint32_t)reg; + + SPI_I2SCTL(spi_periph) &= (uint32_t)(~SPI_I2SCTL_I2SSEL); +} + +/*! + \brief enable SPI + \param[in] spi_periph: SPIx(x=0,1,2) + \param[out] none + \retval none +*/ +void spi_enable(uint32_t spi_periph) +{ + SPI_CTL0(spi_periph) |= (uint32_t)SPI_CTL0_SPIEN; +} + +/*! + \brief disable SPI + \param[in] spi_periph: SPIx(x=0,1,2) + \param[out] none + \retval none +*/ +void spi_disable(uint32_t spi_periph) +{ + SPI_CTL0(spi_periph) &= (uint32_t)(~SPI_CTL0_SPIEN); +} + +/*! + \brief initialize I2S parameter + \param[in] spi_periph: SPIx(x=1,2) + \param[in] mode: I2S operation mode + only one parameter can be selected which is shown as below: + \arg I2S_MODE_SLAVETX: I2S slave transmit mode + \arg I2S_MODE_SLAVERX: I2S slave receive mode + \arg I2S_MODE_MASTERTX: I2S master transmit mode + \arg I2S_MODE_MASTERRX: I2S master receive mode + \param[in] standard: I2S standard + only one parameter can be selected which is shown as below: + \arg I2S_STD_PHILLIPS: I2S phillips standard + \arg I2S_STD_MSB: I2S MSB standard + \arg I2S_STD_LSB: I2S LSB standard + \arg I2S_STD_PCMSHORT: I2S PCM short standard + \arg I2S_STD_PCMLONG: I2S PCM long standard + \param[in] ckpl: I2S idle state clock polarity + only one parameter can be selected which is shown as below: + \arg I2S_CKPL_LOW: I2S clock polarity low level + \arg I2S_CKPL_HIGH: I2S clock polarity high level + \param[out] none + \retval none +*/ +void i2s_init(uint32_t spi_periph, uint32_t mode, uint32_t standard, uint32_t ckpl) +{ + uint32_t reg = 0U; + reg = SPI_I2SCTL(spi_periph); + reg &= I2S_INIT_MASK; + + /* enable I2S mode */ + reg |= (uint32_t)SPI_I2SCTL_I2SSEL; + /* select I2S mode */ + reg |= (uint32_t)mode; + /* select I2S standard */ + reg |= (uint32_t)standard; + /* select I2S polarity */ + reg |= (uint32_t)ckpl; + + /* write to SPI_I2SCTL register */ + SPI_I2SCTL(spi_periph) = (uint32_t)reg; +} + +/*! + \brief configure I2S prescaler + \param[in] spi_periph: SPIx(x=1,2) + \param[in] audiosample: I2S audio sample rate + only one parameter can be selected which is shown as below: + \arg I2S_AUDIOSAMPLE_8K: audio sample rate is 8KHz + \arg I2S_AUDIOSAMPLE_11K: audio sample rate is 11KHz + \arg I2S_AUDIOSAMPLE_16K: audio sample rate is 16KHz + \arg I2S_AUDIOSAMPLE_22K: audio sample rate is 22KHz + \arg I2S_AUDIOSAMPLE_32K: audio sample rate is 32KHz + \arg I2S_AUDIOSAMPLE_44K: audio sample rate is 44KHz + \arg I2S_AUDIOSAMPLE_48K: audio sample rate is 48KHz + \arg I2S_AUDIOSAMPLE_96K: audio sample rate is 96KHz + \arg I2S_AUDIOSAMPLE_192K: audio sample rate is 192KHz + \param[in] frameformat: I2S data length and channel length + only one parameter can be selected which is shown as below: + \arg I2S_FRAMEFORMAT_DT16B_CH16B: I2S data length is 16 bit and channel length is 16 bit + \arg I2S_FRAMEFORMAT_DT16B_CH32B: I2S data length is 16 bit and channel length is 32 bit + \arg I2S_FRAMEFORMAT_DT24B_CH32B: I2S data length is 24 bit and channel length is 32 bit + \arg I2S_FRAMEFORMAT_DT32B_CH32B: I2S data length is 32 bit and channel length is 32 bit + \param[in] mckout: I2S master clock output + only one parameter can be selected which is shown as below: + \arg I2S_MCKOUT_ENABLE: I2S master clock output enable + \arg I2S_MCKOUT_DISABLE: I2S master clock output disable + \param[out] none + \retval none +*/ +void i2s_psc_config(uint32_t spi_periph, uint32_t audiosample, uint32_t frameformat, uint32_t mckout) +{ + uint32_t i2sdiv = 2U, i2sof = 0U; + uint32_t clks = 0U; + uint32_t i2sclock = 0U; + + /* deinit SPI_I2SPSC register */ + SPI_I2SPSC(spi_periph) = SPI_I2SPSC_DEFAULT_VALUE; + +#ifdef GD32F10X_CL + /* get the I2S clock source */ + if(SPI1 == ((uint32_t)spi_periph)){ + /* I2S1 clock source selection */ + clks = I2S1_CLOCK_SEL; + }else{ + /* I2S2 clock source selection */ + clks = I2S2_CLOCK_SEL; + } + + if(0U != (RCU_CFG1 & clks)){ + /* get RCU PLL2 clock multiplication factor */ + clks = (uint32_t)((RCU_CFG1 & I2S_CLOCK_MUL_MASK) >> RCU_CFG1_PLL2MF_OFFSET); + + if((clks > 5U) && (clks < 15U)){ + /* multiplier is between 8 and 14 */ + clks += 2U; + }else{ + if(15U == clks){ + /* multiplier is 20 */ + clks = 20U; + } + } + + /* get the PREDV1 value */ + i2sclock = (uint32_t)(((RCU_CFG1 & I2S_CLOCK_DIV_MASK) >> RCU_CFG1_PREDV1_OFFSET) + 1U); + /* calculate I2S clock based on PLL2 and PREDV1 */ + i2sclock = (uint32_t)((HXTAL_VALUE / i2sclock) * clks * 2U); + }else{ + /* get system clock */ + i2sclock = rcu_clock_freq_get(CK_SYS); + } +#else + /* get system clock */ + i2sclock = rcu_clock_freq_get(CK_SYS); +#endif /* GD32F10X_CL */ + + /* config the prescaler depending on the mclk output state, the frame format and audio sample rate */ + if(I2S_MCKOUT_ENABLE == mckout){ + clks = (uint32_t)(((i2sclock / 256U) * 10U) / audiosample); + }else{ + if(I2S_FRAMEFORMAT_DT16B_CH16B == frameformat){ + clks = (uint32_t)(((i2sclock / 32U) *10U ) / audiosample); + }else{ + clks = (uint32_t)(((i2sclock / 64U) *10U ) / audiosample); + } + } + + /* remove the floating point */ + clks = (clks + 5U) / 10U; + i2sof = (clks & 0x00000001U); + i2sdiv = ((clks - i2sof) / 2U); + i2sof = (i2sof << 8U); + + /* set the default values */ + if((i2sdiv < 2U) || (i2sdiv > 255U)){ + i2sdiv = 2U; + i2sof = 0U; + } + + /* configure SPI_I2SPSC */ + SPI_I2SPSC(spi_periph) = (uint32_t)(i2sdiv | i2sof | mckout); + + /* clear SPI_I2SCTL_DTLEN and SPI_I2SCTL_CHLEN bits */ + SPI_I2SCTL(spi_periph) &= (uint32_t)(~(SPI_I2SCTL_DTLEN | SPI_I2SCTL_CHLEN)); + /* configure data frame format */ + SPI_I2SCTL(spi_periph) |= (uint32_t)frameformat; +} + +/*! + \brief enable I2S + \param[in] spi_periph: SPIx(x=1,2) + \param[out] none + \retval none +*/ +void i2s_enable(uint32_t spi_periph) +{ + SPI_I2SCTL(spi_periph) |= (uint32_t)SPI_I2SCTL_I2SEN; +} + +/*! + \brief disable I2S + \param[in] spi_periph: SPIx(x=1,2) + \param[out] none + \retval none +*/ +void i2s_disable(uint32_t spi_periph) +{ + SPI_I2SCTL(spi_periph) &= (uint32_t)(~SPI_I2SCTL_I2SEN); +} + +/*! + \brief enable SPI NSS output + \param[in] spi_periph: SPIx(x=0,1,2) + \param[out] none + \retval none +*/ +void spi_nss_output_enable(uint32_t spi_periph) +{ + SPI_CTL1(spi_periph) |= (uint32_t)SPI_CTL1_NSSDRV; +} + +/*! + \brief disable SPI NSS output + \param[in] spi_periph: SPIx(x=0,1,2) + \param[out] none + \retval none +*/ +void spi_nss_output_disable(uint32_t spi_periph) +{ + SPI_CTL1(spi_periph) &= (uint32_t)(~SPI_CTL1_NSSDRV); +} + +/*! + \brief SPI NSS pin high level in software mode + \param[in] spi_periph: SPIx(x=0,1,2) + \param[out] none + \retval none +*/ +void spi_nss_internal_high(uint32_t spi_periph) +{ + SPI_CTL0(spi_periph) |= (uint32_t)SPI_CTL0_SWNSS; +} + +/*! + \brief SPI NSS pin low level in software mode + \param[in] spi_periph: SPIx(x=0,1,2) + \param[out] none + \retval none +*/ +void spi_nss_internal_low(uint32_t spi_periph) +{ + SPI_CTL0(spi_periph) &= (uint32_t)(~SPI_CTL0_SWNSS); +} + +/*! + \brief enable SPI DMA send or receive + \param[in] spi_periph: SPIx(x=0,1,2) + \param[in] dma: SPI DMA mode + only one parameter can be selected which is shown as below: + \arg SPI_DMA_TRANSMIT: SPI transmit data using DMA + \arg SPI_DMA_RECEIVE: SPI receive data using DMA + \param[out] none + \retval none +*/ +void spi_dma_enable(uint32_t spi_periph, uint8_t dma) +{ + if(SPI_DMA_TRANSMIT == dma){ + SPI_CTL1(spi_periph) |= (uint32_t)SPI_CTL1_DMATEN; + }else{ + SPI_CTL1(spi_periph) |= (uint32_t)SPI_CTL1_DMAREN; + } +} + +/*! + \brief disable SPI DMA send or receive + \param[in] spi_periph: SPIx(x=0,1,2) + \param[in] dma: SPI DMA mode + only one parameter can be selected which is shown as below: + \arg SPI_DMA_TRANSMIT: SPI transmit data using DMA + \arg SPI_DMA_RECEIVE: SPI receive data using DMA + \param[out] none + \retval none +*/ +void spi_dma_disable(uint32_t spi_periph, uint8_t dma) +{ + if(SPI_DMA_TRANSMIT == dma){ + SPI_CTL1(spi_periph) &= (uint32_t)(~SPI_CTL1_DMATEN); + }else{ + SPI_CTL1(spi_periph) &= (uint32_t)(~SPI_CTL1_DMAREN); + } +} + +/*! + \brief configure SPI/I2S data frame format + \param[in] spi_periph: SPIx(x=0,1,2) + \param[in] frame_format: SPI frame size + only one parameter can be selected which is shown as below: + \arg SPI_FRAMESIZE_16BIT: SPI frame size is 16 bits + \arg SPI_FRAMESIZE_8BIT: SPI frame size is 8 bits + \param[out] none + \retval none +*/ +void spi_i2s_data_frame_format_config(uint32_t spi_periph, uint16_t frame_format) +{ + /* clear SPI_CTL0_FF16 bit */ + SPI_CTL0(spi_periph) &= (uint32_t)(~SPI_CTL0_FF16); + /* configure SPI_CTL0_FF16 bit */ + SPI_CTL0(spi_periph) |= (uint32_t)frame_format; +} + +/*! + \brief SPI transmit data + \param[in] spi_periph: SPIx(x=0,1,2) + \param[in] data: 16-bit data + \param[out] none + \retval none +*/ +void spi_i2s_data_transmit(uint32_t spi_periph, uint16_t data) +{ + SPI_DATA(spi_periph) = (uint32_t)data; +} + +/*! + \brief SPI receive data + \param[in] spi_periph: SPIx(x=0,1,2) + \param[out] none + \retval 16-bit data +*/ +uint16_t spi_i2s_data_receive(uint32_t spi_periph) +{ + return ((uint16_t)SPI_DATA(spi_periph)); +} + +/*! + \brief configure SPI bidirectional transfer direction + \param[in] spi_periph: SPIx(x=0,1,2) + \param[in] transfer_direction: SPI transfer direction + only one parameter can be selected which is shown as below: + \arg SPI_BIDIRECTIONAL_TRANSMIT: SPI work in transmit-only mode + \arg SPI_BIDIRECTIONAL_RECEIVE: SPI work in receive-only mode + \param[out] none + \retval none +*/ +void spi_bidirectional_transfer_config(uint32_t spi_periph, uint32_t transfer_direction) +{ + if(SPI_BIDIRECTIONAL_TRANSMIT == transfer_direction){ + /* set the transmit only mode */ + SPI_CTL0(spi_periph) |= (uint32_t)SPI_BIDIRECTIONAL_TRANSMIT; + }else{ + /* set the receive only mode */ + SPI_CTL0(spi_periph) &= SPI_BIDIRECTIONAL_RECEIVE; + } +} + +/*! + \brief set CRC polynomial + \param[in] spi_periph: SPIx(x=0,1,2) + \param[in] crc_poly: CRC polynomial value + \param[out] none + \retval none +*/ +void spi_crc_polynomial_set(uint32_t spi_periph, uint16_t crc_poly) +{ + /* enable SPI CRC */ + SPI_CTL0(spi_periph) |= (uint32_t)SPI_CTL0_CRCEN; + /* set SPI CRC polynomial */ + SPI_CRCPOLY(spi_periph) = (uint32_t)crc_poly; +} + +/*! + \brief get SPI CRC polynomial + \param[in] spi_periph: SPIx(x=0,1,2) + \param[out] none + \retval 16-bit CRC polynomial +*/ +uint16_t spi_crc_polynomial_get(uint32_t spi_periph) +{ + return ((uint16_t)SPI_CRCPOLY(spi_periph)); +} + +/*! + \brief turn on CRC function + \param[in] spi_periph: SPIx(x=0,1,2) + \param[out] none + \retval none +*/ +void spi_crc_on(uint32_t spi_periph) +{ + SPI_CTL0(spi_periph) |= (uint32_t)SPI_CTL0_CRCEN; +} + +/*! + \brief turn off CRC function + \param[in] spi_periph: SPIx(x=0,1,2) + \param[out] none + \retval none +*/ +void spi_crc_off(uint32_t spi_periph) +{ + SPI_CTL0(spi_periph) &= (uint32_t)(~SPI_CTL0_CRCEN); +} +/*! + \brief SPI next data is CRC value + \param[in] spi_periph: SPIx(x=0,1,2) + \param[out] none + \retval none +*/ +void spi_crc_next(uint32_t spi_periph) +{ + SPI_CTL0(spi_periph) |= (uint32_t)SPI_CTL0_CRCNT; +} + +/*! + \brief get SPI CRC send value or receive value + \param[in] spi_periph: SPIx(x=0,1,2) + \param[in] crc: SPI crc value + only one parameter can be selected which is shown as below: + \arg SPI_CRC_TX: get transmit crc value + \arg SPI_CRC_RX: get receive crc value + \param[out] none + \retval 16-bit CRC value +*/ +uint16_t spi_crc_get(uint32_t spi_periph, uint8_t crc) +{ + if(SPI_CRC_TX == crc){ + return ((uint16_t)(SPI_TCRC(spi_periph))); + }else{ + return ((uint16_t)(SPI_RCRC(spi_periph))); + } +} + +/*! + \brief enable SPI and I2S interrupt + \param[in] spi_periph: SPIx(x=0,1,2) + \param[in] interrupt: SPI/I2S interrupt + only one parameter can be selected which is shown as below: + \arg SPI_I2S_INT_TBE: transmit buffer empty interrupt + \arg SPI_I2S_INT_RBNE: receive buffer not empty interrupt + \arg SPI_I2S_INT_ERR: CRC error,configuration error,reception overrun error, + transmission underrun error and format error interrupt + \param[out] none + \retval none +*/ +void spi_i2s_interrupt_enable(uint32_t spi_periph, uint8_t interrupt) +{ + switch(interrupt){ + /* SPI/I2S transmit buffer empty interrupt */ + case SPI_I2S_INT_TBE: + SPI_CTL1(spi_periph) |= (uint32_t)SPI_CTL1_TBEIE; + break; + /* SPI/I2S receive buffer not empty interrupt */ + case SPI_I2S_INT_RBNE: + SPI_CTL1(spi_periph) |= (uint32_t)SPI_CTL1_RBNEIE; + break; + /* SPI/I2S error */ + case SPI_I2S_INT_ERR: + SPI_CTL1(spi_periph) |= (uint32_t)SPI_CTL1_ERRIE; + break; + default: + break; + } +} + +/*! + \brief disable SPI and I2S interrupt + \param[in] spi_periph: SPIx(x=0,1,2) + \param[in] interrupt: SPI/I2S interrupt + only one parameter can be selected which is shown as below: + \arg SPI_I2S_INT_TBE: transmit buffer empty interrupt + \arg SPI_I2S_INT_RBNE: receive buffer not empty interrupt + \arg SPI_I2S_INT_ERR: CRC error,configuration error,reception overrun error, + transmission underrun error and format error interrupt + \param[out] none + \retval none +*/ +void spi_i2s_interrupt_disable(uint32_t spi_periph, uint8_t interrupt) +{ + switch(interrupt){ + /* SPI/I2S transmit buffer empty interrupt */ + case SPI_I2S_INT_TBE: + SPI_CTL1(spi_periph) &= (uint32_t)(~SPI_CTL1_TBEIE); + break; + /* SPI/I2S receive buffer not empty interrupt */ + case SPI_I2S_INT_RBNE: + SPI_CTL1(spi_periph) &= (uint32_t)(~SPI_CTL1_RBNEIE); + break; + /* SPI/I2S error */ + case SPI_I2S_INT_ERR: + SPI_CTL1(spi_periph) &= (uint32_t)(~SPI_CTL1_ERRIE); + break; + default : + break; + } +} + +/*! + \brief get SPI and I2S interrupt flag status + \param[in] spi_periph: SPIx(x=0,1,2) + \param[in] interrupt: SPI/I2S interrupt flag status + only one parameter can be selected which is shown as below: + \arg SPI_I2S_INT_FLAG_TBE: transmit buffer empty interrupt flag + \arg SPI_I2S_INT_FLAG_RBNE: receive buffer not empty interrupt flag + \arg SPI_I2S_INT_FLAG_RXORERR: overrun interrupt flag + \arg SPI_INT_FLAG_CONFERR: config error interrupt flag + \arg SPI_INT_FLAG_CRCERR: CRC error interrupt flag + \arg I2S_INT_FLAG_TXURERR: underrun error interrupt flag + \param[out] none + \retval FlagStatus: SET or RESET +*/ +FlagStatus spi_i2s_interrupt_flag_get(uint32_t spi_periph, uint8_t interrupt) +{ + uint32_t reg1 = SPI_STAT(spi_periph); + uint32_t reg2 = SPI_CTL1(spi_periph); + + switch(interrupt){ + /* SPI/I2S transmit buffer empty interrupt */ + case SPI_I2S_INT_FLAG_TBE: + reg1 = reg1 & SPI_STAT_TBE; + reg2 = reg2 & SPI_CTL1_TBEIE; + break; + /* SPI/I2S receive buffer not empty interrupt */ + case SPI_I2S_INT_FLAG_RBNE: + reg1 = reg1 & SPI_STAT_RBNE; + reg2 = reg2 & SPI_CTL1_RBNEIE; + break; + /* SPI/I2S overrun interrupt */ + case SPI_I2S_INT_FLAG_RXORERR: + reg1 = reg1 & SPI_STAT_RXORERR; + reg2 = reg2 & SPI_CTL1_ERRIE; + break; + /* SPI config error interrupt */ + case SPI_INT_FLAG_CONFERR: + reg1 = reg1 & SPI_STAT_CONFERR; + reg2 = reg2 & SPI_CTL1_ERRIE; + break; + /* SPI CRC error interrupt */ + case SPI_INT_FLAG_CRCERR: + reg1 = reg1 & SPI_STAT_CRCERR; + reg2 = reg2 & SPI_CTL1_ERRIE; + break; + /* I2S underrun error interrupt */ + case I2S_INT_FLAG_TXURERR: + reg1 = reg1 & SPI_STAT_TXURERR; + reg2 = reg2 & SPI_CTL1_ERRIE; + break; + default : + break; + } + /*get SPI/I2S interrupt flag status */ + if((0U != reg1) && (0U != reg2)){ + return SET; + }else{ + return RESET; + } +} + +/*! + \brief get SPI and I2S flag status + \param[in] spi_periph: SPIx(x=0,1,2) + \param[in] flag: SPI/I2S flag status + one or more parameters can be selected which are shown as below: + \arg SPI_FLAG_TBE: transmit buffer empty flag + \arg SPI_FLAG_RBNE: receive buffer not empty flag + \arg SPI_FLAG_TRANS: transmit on-going flag + \arg SPI_FLAG_RXORERR: receive overrun error flag + \arg SPI_FLAG_CONFERR: mode config error flag + \arg SPI_FLAG_CRCERR: CRC error flag + \arg I2S_FLAG_RXORERR: overrun error flag + \arg I2S_FLAG_TXURERR: underrun error flag + \arg I2S_FLAG_CH: channel side flag + \param[out] none + \retval FlagStatus: SET or RESET +*/ +FlagStatus spi_i2s_flag_get(uint32_t spi_periph, uint32_t flag) +{ + if(RESET != (SPI_STAT(spi_periph) & flag)){ + return SET; + }else{ + return RESET; + } +} + +/*! + \brief clear SPI CRC error flag status + \param[in] spi_periph: SPIx(x=0,1,2) + \param[out] none + \retval none +*/ +void spi_crc_error_clear(uint32_t spi_periph) +{ + SPI_STAT(spi_periph) &= (uint32_t)(~SPI_FLAG_CRCERR); +} diff --git a/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_standard_peripheral/Source/gd32f10x_timer.c b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_standard_peripheral/Source/gd32f10x_timer.c new file mode 100644 index 0000000000..bff7bfe1e7 --- /dev/null +++ b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_standard_peripheral/Source/gd32f10x_timer.c @@ -0,0 +1,2003 @@ +/*! + \file gd32f10x_timer.c + \brief TIMER driver + + \version 2014-12-26, V1.0.0, firmware for GD32F10x + \version 2017-06-20, V2.0.0, firmware for GD32F10x + \version 2018-07-31, V2.1.0, firmware for GD32F10x + \version 2020-09-30, V2.2.0, firmware for GD32F10x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "gd32f10x_timer.h" + +/* TIMER init parameter mask */ +#define ALIGNEDMODE_MASK ((uint32_t)0x00000060U) /*!< TIMER init parameter aligne dmode mask */ +#define COUNTERDIRECTION_MASK ((uint32_t)0x00000010U) /*!< TIMER init parameter counter direction mask */ +#define CLOCKDIVISION_MASK ((uint32_t)0x00000300U) /*!< TIMER init parameter clock division value mask */ + +/*! + \brief deinit a TIMER + \param[in] timer_periph: TIMERx(x=0..13) + \param[out] none + \retval none +*/ +void timer_deinit(uint32_t timer_periph) +{ + switch(timer_periph){ + case TIMER0: + /* reset TIMER0 */ + rcu_periph_reset_enable(RCU_TIMER0RST); + rcu_periph_reset_disable(RCU_TIMER0RST); + break; + case TIMER1: + /* reset TIMER1 */ + rcu_periph_reset_enable(RCU_TIMER1RST); + rcu_periph_reset_disable(RCU_TIMER1RST); + break; + case TIMER2: + /* reset TIMER2 */ + rcu_periph_reset_enable(RCU_TIMER2RST); + rcu_periph_reset_disable(RCU_TIMER2RST); + break; + case TIMER3: + /* reset TIMER3 */ + rcu_periph_reset_enable(RCU_TIMER3RST); + rcu_periph_reset_disable(RCU_TIMER3RST); + break; + case TIMER4: + /* reset TIMER4 */ + rcu_periph_reset_enable(RCU_TIMER4RST); + rcu_periph_reset_disable(RCU_TIMER4RST); + break; + case TIMER5: + /* reset TIMER5 */ + rcu_periph_reset_enable(RCU_TIMER5RST); + rcu_periph_reset_disable(RCU_TIMER5RST); + break; + case TIMER6: + /* reset TIMER6 */ + rcu_periph_reset_enable(RCU_TIMER6RST); + rcu_periph_reset_disable(RCU_TIMER6RST); + break; + case TIMER7: + /* reset TIMER7 */ + rcu_periph_reset_enable(RCU_TIMER7RST); + rcu_periph_reset_disable(RCU_TIMER7RST); + break; +#ifdef GD32F10X_XD + case TIMER8: + /* reset TIMER8 */ + rcu_periph_reset_enable(RCU_TIMER8RST); + rcu_periph_reset_disable(RCU_TIMER8RST); + break; + case TIMER9: + /* reset TIMER9 */ + rcu_periph_reset_enable(RCU_TIMER9RST); + rcu_periph_reset_disable(RCU_TIMER9RST); + break; + case TIMER10: + /* reset TIMER10 */ + rcu_periph_reset_enable(RCU_TIMER10RST); + rcu_periph_reset_disable(RCU_TIMER10RST); + break; + case TIMER11: + /* reset TIMER11 */ + rcu_periph_reset_enable(RCU_TIMER11RST); + rcu_periph_reset_disable(RCU_TIMER11RST); + break; + case TIMER12: + /* reset TIMER12 */ + rcu_periph_reset_enable(RCU_TIMER12RST); + rcu_periph_reset_disable(RCU_TIMER12RST); + break; + case TIMER13: + /* reset TIMER13 */ + rcu_periph_reset_enable(RCU_TIMER13RST); + rcu_periph_reset_disable(RCU_TIMER13RST); + break; +#endif /* GD32F10X_XD */ + default: + break; + } +} + +/*! + \brief initialize TIMER init parameter struct with a default value + \param[in] initpara: init parameter struct + \param[out] none + \retval none +*/ +void timer_struct_para_init(timer_parameter_struct* initpara) +{ + /* initialize the init parameter struct member with the default value */ + initpara->prescaler = 0U; + initpara->alignedmode = TIMER_COUNTER_EDGE; + initpara->counterdirection = TIMER_COUNTER_UP; + initpara->period = 65535U; + initpara->clockdivision = TIMER_CKDIV_DIV1; + initpara->repetitioncounter = 0U; +} + +/*! + \brief initialize TIMER counter + \param[in] timer_periph: TIMERx(x=0..13) + \param[in] initpara: init parameter struct + prescaler: prescaler value of the counter clock,0~65535 + alignedmode: TIMER_COUNTER_EDGE,TIMER_COUNTER_CENTER_DOWN,TIMER_COUNTER_CENTER_UP, + TIMER_COUNTER_CENTER_BOTH + counterdirection: TIMER_COUNTER_UP,TIMER_COUNTER_DOWN + period: counter auto reload value,0~65535 + clockdivision: TIMER_CKDIV_DIV1,TIMER_CKDIV_DIV2,TIMER_CKDIV_DIV4 + repetitioncounter: counter repetition value,0~255 + \param[out] none + \retval none +*/ +void timer_init(uint32_t timer_periph, timer_parameter_struct* initpara) +{ + /* configure the counter prescaler value */ + TIMER_PSC(timer_periph) = (uint16_t)initpara->prescaler; + + /* configure the counter direction and aligned mode */ + if((TIMER0 == timer_periph) || (TIMER1 == timer_periph) || (TIMER2 == timer_periph) || (TIMER3 == timer_periph) || + (TIMER4 == timer_periph) || (TIMER7 == timer_periph) || (TIMER8 == timer_periph) || (TIMER9 == timer_periph) || + (TIMER10 == timer_periph) || (TIMER11 == timer_periph) || (TIMER12 == timer_periph) || (TIMER13 == timer_periph)){ + TIMER_CTL0(timer_periph) &= (~(uint32_t)(TIMER_CTL0_DIR | TIMER_CTL0_CAM)); + TIMER_CTL0(timer_periph) |= (uint32_t)(initpara->alignedmode & ALIGNEDMODE_MASK); + TIMER_CTL0(timer_periph) |= (uint32_t)(initpara->counterdirection & COUNTERDIRECTION_MASK); + } + + /* configure the autoreload value */ + TIMER_CAR(timer_periph) = (uint32_t)initpara->period; + + if((TIMER5 != timer_periph) && (TIMER6 != timer_periph)){ + /* reset the CKDIV bit */ + TIMER_CTL0(timer_periph) &= (~(uint32_t)TIMER_CTL0_CKDIV); + TIMER_CTL0(timer_periph) |= (uint32_t)(initpara->clockdivision & CLOCKDIVISION_MASK); + } + + if((TIMER0 == timer_periph) || (TIMER7 == timer_periph)){ + /* configure the repetition counter value */ + TIMER_CREP(timer_periph) = (uint32_t)initpara->repetitioncounter; + } + + /* generate an update event */ + TIMER_SWEVG(timer_periph) |= (uint32_t)TIMER_SWEVG_UPG; +} + +/*! + \brief enable a TIMER + \param[in] timer_periph: TIMERx(x=0..13) + \param[out] none + \retval none +*/ +void timer_enable(uint32_t timer_periph) +{ + TIMER_CTL0(timer_periph) |= (uint32_t)TIMER_CTL0_CEN; +} + +/*! + \brief disable a TIMER + \param[in] timer_periph: TIMERx(x=0..13) + \param[out] none + \retval none +*/ +void timer_disable(uint32_t timer_periph) +{ + TIMER_CTL0(timer_periph) &= ~(uint32_t)TIMER_CTL0_CEN; +} + +/*! + \brief enable the auto reload shadow function + \param[in] timer_periph: TIMERx(x=0..13) + \param[out] none + \retval none +*/ +void timer_auto_reload_shadow_enable(uint32_t timer_periph) +{ + TIMER_CTL0(timer_periph) |= (uint32_t)TIMER_CTL0_ARSE; +} + +/*! + \brief disable the auto reload shadow function + \param[in] timer_periph: TIMERx(x=0..13) + \param[out] none + \retval none +*/ +void timer_auto_reload_shadow_disable(uint32_t timer_periph) +{ + TIMER_CTL0(timer_periph) &= ~(uint32_t)TIMER_CTL0_ARSE; +} + +/*! + \brief enable the update event + \param[in] timer_periph: TIMERx(x=0..13) + \param[out] none + \retval none +*/ +void timer_update_event_enable(uint32_t timer_periph) +{ + TIMER_CTL0(timer_periph) &= ~(uint32_t)TIMER_CTL0_UPDIS; +} + +/*! + \brief disable the update event + \param[in] timer_periph: TIMERx(x=0..13) + \param[out] none + \retval none +*/ +void timer_update_event_disable(uint32_t timer_periph) +{ + TIMER_CTL0(timer_periph) |= (uint32_t) TIMER_CTL0_UPDIS; +} + +/*! + \brief set TIMER counter alignment mode + \param[in] timer_periph: TIMERx(x=0..4,7..13) + \param[in] aligned: + only one parameter can be selected which is shown as below: + \arg TIMER_COUNTER_EDGE: edge-aligned mode + \arg TIMER_COUNTER_CENTER_DOWN: center-aligned and counting down assert mode + \arg TIMER_COUNTER_CENTER_UP: center-aligned and counting up assert mode + \arg TIMER_COUNTER_CENTER_BOTH: center-aligned and counting up/down assert mode + \param[out] none + \retval none +*/ +void timer_counter_alignment(uint32_t timer_periph, uint16_t aligned) +{ + TIMER_CTL0(timer_periph) &= ~(uint32_t)TIMER_CTL0_CAM; + TIMER_CTL0(timer_periph) |= (uint32_t)aligned; +} + +/*! + \brief set TIMER counter up direction + \param[in] timer_periph: TIMERx(x=0..4,7..13) + \param[out] none + \retval none +*/ +void timer_counter_up_direction(uint32_t timer_periph) +{ + TIMER_CTL0(timer_periph) &= ~(uint32_t)TIMER_CTL0_DIR; +} + +/*! + \brief set TIMER counter down direction + \param[in] timer_periph: TIMERx(x=0..4,7..13) + \param[out] none + \retval none +*/ +void timer_counter_down_direction(uint32_t timer_periph) +{ + TIMER_CTL0(timer_periph) |= (uint32_t)TIMER_CTL0_DIR; +} + +/*! + \brief configure TIMER prescaler + \param[in] timer_periph: TIMERx(x=0..13) + \param[in] prescaler: prescaler value + \param[in] pscreload: prescaler reload mode + only one parameter can be selected which is shown as below: + \arg TIMER_PSC_RELOAD_NOW: the prescaler is loaded right now + \arg TIMER_PSC_RELOAD_UPDATE: the prescaler is loaded at the next update event + \param[out] none + \retval none +*/ +void timer_prescaler_config(uint32_t timer_periph, uint16_t prescaler, uint32_t pscreload) +{ + TIMER_PSC(timer_periph) = (uint32_t)prescaler; + + if(TIMER_PSC_RELOAD_NOW == pscreload){ + TIMER_SWEVG(timer_periph) |= (uint32_t)TIMER_SWEVG_UPG; + } +} + +/*! + \brief configure TIMER repetition register value + \param[in] timer_periph: TIMERx(x=0,7) + \param[in] repetition: the counter repetition value,0~255 + \param[out] none + \retval none +*/ +void timer_repetition_value_config(uint32_t timer_periph, uint8_t repetition) +{ + TIMER_CREP(timer_periph) = (uint32_t)repetition; +} + +/*! + \brief configure TIMER autoreload register value + \param[in] timer_periph: TIMERx(x=0..13) + \param[in] autoreload: the counter auto-reload value + \param[out] none + \retval none +*/ +void timer_autoreload_value_config(uint32_t timer_periph, uint32_t autoreload) +{ + TIMER_CAR(timer_periph) = (uint32_t)autoreload; +} + +/*! + \brief configure TIMER counter register value + \param[in] timer_periph: TIMERx(x=0..13) + \param[in] counter: the counter value + \param[out] none + \retval none +*/ +void timer_counter_value_config(uint32_t timer_periph, uint32_t counter) +{ + TIMER_CNT(timer_periph) = (uint32_t)counter; +} + +/*! + \brief read TIMER counter value + \param[in] timer_periph: TIMERx(x=0..13) + \param[out] none + \retval counter value +*/ +uint32_t timer_counter_read(uint32_t timer_periph) +{ + uint32_t count_value = 0U; + count_value = TIMER_CNT(timer_periph); + return (count_value); +} + +/*! + \brief read TIMER prescaler value + \param[in] timer_periph: TIMERx(x=0..13) + \param[out] none + \retval prescaler register value +*/ +uint16_t timer_prescaler_read(uint32_t timer_periph) +{ + uint16_t prescaler_value = 0U; + prescaler_value = (uint16_t)(TIMER_PSC(timer_periph)); + return (prescaler_value); +} + +/*! + \brief configure TIMER single pulse mode + \param[in] timer_periph: TIMERx(x=0..8,11) + \param[in] spmode: + only one parameter can be selected which is shown as below: + \arg TIMER_SP_MODE_SINGLE: single pulse mode + \arg TIMER_SP_MODE_REPETITIVE: repetitive pulse mode + \param[out] none + \retval none +*/ +void timer_single_pulse_mode_config(uint32_t timer_periph, uint32_t spmode) +{ + if(TIMER_SP_MODE_SINGLE == spmode){ + TIMER_CTL0(timer_periph) |= (uint32_t)TIMER_CTL0_SPM; + }else if(TIMER_SP_MODE_REPETITIVE == spmode){ + TIMER_CTL0(timer_periph) &= ~((uint32_t)TIMER_CTL0_SPM); + }else{ + /* illegal parameters */ + } +} + +/*! + \brief configure TIMER update source + \param[in] timer_periph: TIMERx(x=0..13) + \param[in] update: + only one parameter can be selected which is shown as below: + \arg TIMER_UPDATE_SRC_GLOBAL: update generate by setting of UPG bit or the counter overflow/underflow, + or the slave mode controller trigger + \arg TIMER_UPDATE_SRC_REGULAR: update generate only by counter overflow/underflow + \param[out] none + \retval none +*/ +void timer_update_source_config(uint32_t timer_periph, uint32_t update) +{ + if(TIMER_UPDATE_SRC_REGULAR == update){ + TIMER_CTL0(timer_periph) |= (uint32_t)TIMER_CTL0_UPS; + }else if(TIMER_UPDATE_SRC_GLOBAL == update){ + TIMER_CTL0(timer_periph) &= ~(uint32_t)TIMER_CTL0_UPS; + }else{ + /* illegal parameters */ + } +} + +/*! + \brief enable the TIMER DMA + \param[in] timer_periph: please refer to the following parameters + \param[in] dma: timer DMA source enable + only one parameter can be selected which is shown as below: + \arg TIMER_DMA_UPD: update DMA enable,TIMERx(x=0..7) + \arg TIMER_DMA_CH0D: channel 0 DMA enable,TIMERx(x=0..4,7) + \arg TIMER_DMA_CH1D: channel 1 DMA enable,TIMERx(x=0..4,7) + \arg TIMER_DMA_CH2D: channel 2 DMA enable,TIMERx(x=0..4,7) + \arg TIMER_DMA_CH3D: channel 3 DMA enable,TIMERx(x=0..4,7) + \arg TIMER_DMA_CMTD: commutation DMA request enable,TIMERx(x=0,7) + \arg TIMER_DMA_TRGD: trigger DMA enable,TIMERx(x=0..4,7) + \param[out] none + \retval none +*/ +void timer_dma_enable(uint32_t timer_periph, uint16_t dma) +{ + TIMER_DMAINTEN(timer_periph) |= (uint32_t) dma; +} + +/*! + \brief disable the TIMER DMA + \param[in] timer_periph: please refer to the following parameters + \param[in] dma: timer DMA source disable + only one parameter can be selected which is shown as below: + \arg TIMER_DMA_UPD: update DMA disable,TIMERx(x=0..7) + \arg TIMER_DMA_CH0D: channel 0 DMA disable,TIMERx(x=0..4,7) + \arg TIMER_DMA_CH1D: channel 1 DMA disable,TIMERx(x=0..4,7) + \arg TIMER_DMA_CH2D: channel 2 DMA disable,TIMERx(x=0..4,7) + \arg TIMER_DMA_CH3D: channel 3 DMA disable,TIMERx(x=0..4,7) + \arg TIMER_DMA_CMTD: commutation DMA request disable,TIMERx(x=0,7) + \arg TIMER_DMA_TRGD: trigger DMA disable,TIMERx(x=0..4,7) + \param[out] none + \retval none +*/ +void timer_dma_disable(uint32_t timer_periph, uint16_t dma) +{ + TIMER_DMAINTEN(timer_periph) &= (~(uint32_t)(dma)); +} + +/*! + \brief channel DMA request source selection + \param[in] timer_periph: TIMERx(x=0..4,7) + \param[in] dma_request: channel DMA request source selection + only one parameter can be selected which is shown as below: + \arg TIMER_DMAREQUEST_CHANNELEVENT: DMA request of channel y is sent when channel y event occurs + \arg TIMER_DMAREQUEST_UPDATEEVENT: DMA request of channel y is sent when update event occurs + \param[out] none + \retval none +*/ +void timer_channel_dma_request_source_select(uint32_t timer_periph, uint32_t dma_request) +{ + if(TIMER_DMAREQUEST_UPDATEEVENT == dma_request){ + TIMER_CTL1(timer_periph) |= (uint32_t)TIMER_CTL1_DMAS; + }else if(TIMER_DMAREQUEST_CHANNELEVENT == dma_request){ + TIMER_CTL1(timer_periph) &= ~(uint32_t)TIMER_CTL1_DMAS; + }else{ + /* illegal parameters */ + } +} + +/*! + \brief configure the TIMER DMA transfer + \param[in] timer_periph: please refer to the following parameters + \param[in] dma_baseaddr: + only one parameter can be selected which is shown as below: + \arg TIMER_DMACFG_DMATA_CTL0: DMA transfer address is TIMER_CTL0,TIMERx(x=0..4,7) + \arg TIMER_DMACFG_DMATA_CTL1: DMA transfer address is TIMER_CTL1,TIMERx(x=0..4,7) + \arg TIMER_DMACFG_DMATA_SMCFG: DMA transfer address is TIMER_SMCFG,TIMERx(x=0..4,7) + \arg TIMER_DMACFG_DMATA_DMAINTEN: DMA transfer address is TIMER_DMAINTEN,TIMERx(x=0..4,7) + \arg TIMER_DMACFG_DMATA_INTF: DMA transfer address is TIMER_INTF,TIMERx(x=0..4,7) + \arg TIMER_DMACFG_DMATA_SWEVG: DMA transfer address is TIMER_SWEVG,TIMERx(x=0..4,7) + \arg TIMER_DMACFG_DMATA_CHCTL0: DMA transfer address is TIMER_CHCTL0,TIMERx(x=0..4,7) + \arg TIMER_DMACFG_DMATA_CHCTL1: DMA transfer address is TIMER_CHCTL1,TIMERx(x=0..4,7) + \arg TIMER_DMACFG_DMATA_CHCTL2: DMA transfer address is TIMER_CHCTL2,TIMERx(x=0..4,7) + \arg TIMER_DMACFG_DMATA_CNT: DMA transfer address is TIMER_CNT,TIMERx(x=0..4,7) + \arg TIMER_DMACFG_DMATA_PSC: DMA transfer address is TIMER_PSC,TIMERx(x=0..4,7) + \arg TIMER_DMACFG_DMATA_CAR: DMA transfer address is TIMER_CAR,TIMERx(x=0..4,7) + \arg TIMER_DMACFG_DMATA_CREP: DMA transfer address is TIMER_CREP,TIMERx(x=0,7) + \arg TIMER_DMACFG_DMATA_CH0CV: DMA transfer address is TIMER_CH0CV,TIMERx(x=0..4,7) + \arg TIMER_DMACFG_DMATA_CH1CV: DMA transfer address is TIMER_CH1CV,TIMERx(x=0..4,7) + \arg TIMER_DMACFG_DMATA_CH2CV: DMA transfer address is TIMER_CH2CV,TIMERx(x=0..4,7) + \arg TIMER_DMACFG_DMATA_CH3CV: DMA transfer address is TIMER_CH3CV,TIMERx(x=0..4,7) + \arg TIMER_DMACFG_DMATA_CCHP: DMA transfer address is TIMER_CCHP,TIMERx(x=0,7) + \arg TIMER_DMACFG_DMATA_DMACFG: DMA transfer address is TIMER_DMACFG,TIMERx(x=0..4,7) + \param[in] dma_lenth: + only one parameter can be selected which is shown as below: + \arg TIMER_DMACFG_DMATC_xTRANSFER(x=1..18): DMA transfer x time + \param[out] none + \retval none +*/ +void timer_dma_transfer_config(uint32_t timer_periph, uint32_t dma_baseaddr, uint32_t dma_lenth) +{ + TIMER_DMACFG(timer_periph) &= (~(uint32_t)(TIMER_DMACFG_DMATA | TIMER_DMACFG_DMATC)); + TIMER_DMACFG(timer_periph) |= (uint32_t)(dma_baseaddr | dma_lenth); +} + +/*! + \brief software generate events + \param[in] timer_periph: please refer to the following parameters + \param[in] event: the timer software event generation sources + one or more parameters can be selected which are shown as below: + \arg TIMER_EVENT_SRC_UPG: update event generation, TIMERx(x=0..13) + \arg TIMER_EVENT_SRC_CH0G: channel 0 capture or compare event generation, TIMERx(x=0..4,7..13) + \arg TIMER_EVENT_SRC_CH1G: channel 1 capture or compare event generation, TIMERx(x=0..4,7,8,11) + \arg TIMER_EVENT_SRC_CH2G: channel 2 capture or compare event generation, TIMERx(x=0..4,7) + \arg TIMER_EVENT_SRC_CH3G: channel 3 capture or compare event generation, TIMERx(x=0..4,7) + \arg TIMER_EVENT_SRC_CMTG: channel commutation event generation, TIMERx(x=0,7) + \arg TIMER_EVENT_SRC_TRGG: trigger event generation, TIMERx(x=0..4,7,8,11) + \arg TIMER_EVENT_SRC_BRKG: break event generation, TIMERx(x=0,7) + \param[out] none + \retval none +*/ +void timer_event_software_generate(uint32_t timer_periph, uint16_t event) +{ + TIMER_SWEVG(timer_periph) |= (uint32_t)event; +} + +/*! + \brief initialize TIMER break parameter struct with a default value + \param[in] breakpara: TIMER break parameter struct + \param[out] none + \retval none +*/ +void timer_break_struct_para_init(timer_break_parameter_struct* breakpara) +{ + /* initialize the break parameter struct member with the default value */ + breakpara->runoffstate = TIMER_ROS_STATE_DISABLE; + breakpara->ideloffstate = TIMER_IOS_STATE_DISABLE; + breakpara->deadtime = 0U; + breakpara->breakpolarity = TIMER_BREAK_POLARITY_LOW; + breakpara->outputautostate = TIMER_OUTAUTO_DISABLE; + breakpara->protectmode = TIMER_CCHP_PROT_OFF; + breakpara->breakstate = TIMER_BREAK_DISABLE; +} + +/*! + \brief configure TIMER break function + \param[in] timer_periph: TIMERx(x=0,7) + \param[in] breakpara: TIMER break parameter struct + runoffstate: TIMER_ROS_STATE_ENABLE,TIMER_ROS_STATE_DISABLE + ideloffstate: TIMER_IOS_STATE_ENABLE,TIMER_IOS_STATE_DISABLE + deadtime: 0~255 + breakpolarity: TIMER_BREAK_POLARITY_LOW,TIMER_BREAK_POLARITY_HIGH + outputautostate: TIMER_OUTAUTO_ENABLE,TIMER_OUTAUTO_DISABLE + protectmode: TIMER_CCHP_PROT_OFF,TIMER_CCHP_PROT_0,TIMER_CCHP_PROT_1,TIMER_CCHP_PROT_2 + breakstate: TIMER_BREAK_ENABLE,TIMER_BREAK_DISABLE + \param[out] none + \retval none +*/ +void timer_break_config(uint32_t timer_periph, timer_break_parameter_struct* breakpara) +{ + TIMER_CCHP(timer_periph) = (uint32_t)(((uint32_t)(breakpara->runoffstate)) | + ((uint32_t)(breakpara->ideloffstate)) | + ((uint32_t)(breakpara->deadtime)) | + ((uint32_t)(breakpara->breakpolarity)) | + ((uint32_t)(breakpara->outputautostate)) | + ((uint32_t)(breakpara->protectmode)) | + ((uint32_t)(breakpara->breakstate))) ; +} + +/*! + \brief enable TIMER break function + \param[in] timer_periph: TIMERx(x=0,7) + \param[out] none + \retval none +*/ +void timer_break_enable(uint32_t timer_periph) +{ + TIMER_CCHP(timer_periph) |= (uint32_t)TIMER_CCHP_BRKEN; +} + +/*! + \brief disable TIMER break function + \param[in] timer_periph: TIMERx(x=0,7) + \param[out] none + \retval none +*/ +void timer_break_disable(uint32_t timer_periph) +{ + TIMER_CCHP(timer_periph) &= ~(uint32_t)TIMER_CCHP_BRKEN; +} + +/*! + \brief enable TIMER output automatic function + \param[in] timer_periph: TIMERx(x=0,7) + \param[out] none + \retval none +*/ +void timer_automatic_output_enable(uint32_t timer_periph) +{ + TIMER_CCHP(timer_periph) |= (uint32_t)TIMER_CCHP_OAEN; +} + +/*! + \brief disable TIMER output automatic function + \param[in] timer_periph: TIMERx(x=0,7) + \param[out] none + \retval none +*/ +void timer_automatic_output_disable(uint32_t timer_periph) +{ + TIMER_CCHP(timer_periph) &= ~(uint32_t)TIMER_CCHP_OAEN; +} + +/*! + \brief enable or disable TIMER primary output function + \param[in] timer_periph: TIMERx(x=0,7) + \param[in] newvalue: ENABLE or DISABLE + \param[out] none + \retval none +*/ +void timer_primary_output_config(uint32_t timer_periph, ControlStatus newvalue) +{ + if(ENABLE == newvalue){ + TIMER_CCHP(timer_periph) |= (uint32_t)TIMER_CCHP_POEN; + }else{ + TIMER_CCHP(timer_periph) &= (~(uint32_t)TIMER_CCHP_POEN); + } +} + +/*! + \brief enable or disable channel capture/compare control shadow register + \param[in] timer_periph: TIMERx(x=0,7) + \param[in] newvalue: ENABLE or DISABLE + \param[out] none + \retval none +*/ +void timer_channel_control_shadow_config(uint32_t timer_periph, ControlStatus newvalue) +{ + if(ENABLE == newvalue){ + TIMER_CTL1(timer_periph) |= (uint32_t)TIMER_CTL1_CCSE; + }else{ + TIMER_CTL1(timer_periph) &= (~(uint32_t)TIMER_CTL1_CCSE); + } +} + +/*! + \brief configure TIMER channel control shadow register update control + \param[in] timer_periph: TIMERx(x=0,7) + \param[in] ccuctl: channel control shadow register update control + only one parameter can be selected which is shown as below: + \arg TIMER_UPDATECTL_CCU: the shadow registers update by when CMTG bit is set + \arg TIMER_UPDATECTL_CCUTRI: the shadow registers update by when CMTG bit is set or an rising edge of TRGI occurs + \param[out] none + \retval none +*/ +void timer_channel_control_shadow_update_config(uint32_t timer_periph, uint32_t ccuctl) +{ + if(TIMER_UPDATECTL_CCU == ccuctl){ + TIMER_CTL1(timer_periph) &= (~(uint32_t)TIMER_CTL1_CCUC); + }else if(TIMER_UPDATECTL_CCUTRI == ccuctl){ + TIMER_CTL1(timer_periph) |= (uint32_t)TIMER_CTL1_CCUC; + }else{ + /* illegal parameters */ + } +} + +/*! + \brief initialize TIMER channel output parameter struct with a default value + \param[in] ocpara: TIMER channel n output parameter struct + \param[out] none + \retval none +*/ +void timer_channel_output_struct_para_init(timer_oc_parameter_struct* ocpara) +{ + /* initialize the channel output parameter struct member with the default value */ + ocpara->outputstate = TIMER_CCX_DISABLE; + ocpara->outputnstate = TIMER_CCXN_DISABLE; + ocpara->ocpolarity = TIMER_OC_POLARITY_HIGH; + ocpara->ocnpolarity = TIMER_OCN_POLARITY_HIGH; + ocpara->ocidlestate = TIMER_OC_IDLE_STATE_LOW; + ocpara->ocnidlestate = TIMER_OCN_IDLE_STATE_LOW; +} + +/*! + \brief configure TIMER channel output function + \param[in] timer_periph: please refer to the following parameters + \param[in] channel: + only one parameter can be selected which is shown as below: + \arg TIMER_CH_0: TIMER channel 0(TIMERx(x=0..4,7..13)) + \arg TIMER_CH_1: TIMER channel 1(TIMERx(x=0..4,7,8,11)) + \arg TIMER_CH_2: TIMER channel 2(TIMERx(x=0..4,7)) + \arg TIMER_CH_3: TIMER channel 3(TIMERx(x=0..4,7)) + \param[in] ocpara: TIMER channeln output parameter struct + outputstate: TIMER_CCX_ENABLE,TIMER_CCX_DISABLE + outputnstate: TIMER_CCXN_ENABLE,TIMER_CCXN_DISABLE + ocpolarity: TIMER_OC_POLARITY_HIGH,TIMER_OC_POLARITY_LOW + ocnpolarity: TIMER_OCN_POLARITY_HIGH,TIMER_OCN_POLARITY_LOW + ocidlestate: TIMER_OC_IDLE_STATE_LOW,TIMER_OC_IDLE_STATE_HIGH + ocnidlestate: TIMER_OCN_IDLE_STATE_LOW,TIMER_OCN_IDLE_STATE_HIGH + \param[out] none + \retval none +*/ +void timer_channel_output_config(uint32_t timer_periph, uint16_t channel, timer_oc_parameter_struct* ocpara) +{ + switch(channel){ + /* configure TIMER_CH_0 */ + case TIMER_CH_0: + /* reset the CH0EN bit */ + TIMER_CHCTL2(timer_periph) &= (~(uint32_t)TIMER_CHCTL2_CH0EN); + TIMER_CHCTL0(timer_periph) &= ~(uint32_t)TIMER_CHCTL0_CH0MS; + /* set the CH0EN bit */ + TIMER_CHCTL2(timer_periph) |= (uint32_t)ocpara->outputstate; + /* reset the CH0P bit */ + TIMER_CHCTL2(timer_periph) &= (~(uint32_t)TIMER_CHCTL2_CH0P); + /* set the CH0P bit */ + TIMER_CHCTL2(timer_periph) |= (uint32_t)ocpara->ocpolarity; + + if((TIMER0 == timer_periph) || (TIMER7 == timer_periph)){ + /* reset the CH0NEN bit */ + TIMER_CHCTL2(timer_periph) &= (~(uint32_t)TIMER_CHCTL2_CH0NEN); + /* set the CH0NEN bit */ + TIMER_CHCTL2(timer_periph) |= (uint32_t)ocpara->outputnstate; + /* reset the CH0NP bit */ + TIMER_CHCTL2(timer_periph) &= (~(uint32_t)TIMER_CHCTL2_CH0NP); + /* set the CH0NP bit */ + TIMER_CHCTL2(timer_periph) |= (uint32_t)ocpara->ocnpolarity; + /* reset the ISO0 bit */ + TIMER_CTL1(timer_periph) &= (~(uint32_t)TIMER_CTL1_ISO0); + /* set the ISO0 bit */ + TIMER_CTL1(timer_periph) |= (uint32_t)ocpara->ocidlestate; + /* reset the ISO0N bit */ + TIMER_CTL1(timer_periph) &= (~(uint32_t)TIMER_CTL1_ISO0N); + /* set the ISO0N bit */ + TIMER_CTL1(timer_periph) |= (uint32_t)ocpara->ocnidlestate; + } + break; + /* configure TIMER_CH_1 */ + case TIMER_CH_1: + /* reset the CH1EN bit */ + TIMER_CHCTL2(timer_periph) &= (~(uint32_t)TIMER_CHCTL2_CH1EN); + TIMER_CHCTL0(timer_periph) &= ~(uint32_t)TIMER_CHCTL0_CH1MS; + /* set the CH1EN bit */ + TIMER_CHCTL2(timer_periph) |= (uint32_t)((uint32_t)(ocpara->outputstate) << 4U); + /* reset the CH1P bit */ + TIMER_CHCTL2(timer_periph) &= (~(uint32_t)TIMER_CHCTL2_CH1P); + /* set the CH1P bit */ + TIMER_CHCTL2(timer_periph) |= (uint32_t)((uint32_t)(ocpara->ocpolarity)<< 4U); + + if((TIMER0 == timer_periph) || (TIMER7 == timer_periph)){ + /* reset the CH1NEN bit */ + TIMER_CHCTL2(timer_periph) &= (~(uint32_t)TIMER_CHCTL2_CH1NEN); + /* set the CH1NEN bit */ + TIMER_CHCTL2(timer_periph) |= (uint32_t)((uint32_t)(ocpara->outputnstate)<< 4U); + /* reset the CH1NP bit */ + TIMER_CHCTL2(timer_periph) &= (~(uint32_t)TIMER_CHCTL2_CH1NP); + /* set the CH1NP bit */ + TIMER_CHCTL2(timer_periph) |= (uint32_t)((uint32_t)(ocpara->ocnpolarity)<< 4U); + /* reset the ISO1 bit */ + TIMER_CTL1(timer_periph) &= (~(uint32_t)TIMER_CTL1_ISO1); + /* set the ISO1 bit */ + TIMER_CTL1(timer_periph) |= (uint32_t)((uint32_t)(ocpara->ocidlestate)<< 2U); + /* reset the ISO1N bit */ + TIMER_CTL1(timer_periph) &= (~(uint32_t)TIMER_CTL1_ISO1N); + /* set the ISO1N bit */ + TIMER_CTL1(timer_periph) |= (uint32_t)((uint32_t)(ocpara->ocnidlestate)<< 2U); + } + break; + /* configure TIMER_CH_2 */ + case TIMER_CH_2: + /* reset the CH2EN bit */ + TIMER_CHCTL2(timer_periph) &= (~(uint32_t)TIMER_CHCTL2_CH2EN); + TIMER_CHCTL1(timer_periph) &= ~(uint32_t)TIMER_CHCTL1_CH2MS; + /* set the CH2EN bit */ + TIMER_CHCTL2(timer_periph) |= (uint32_t)((uint32_t)(ocpara->outputstate) << 8U); + /* reset the CH2P bit */ + TIMER_CHCTL2(timer_periph) &= (~(uint32_t)TIMER_CHCTL2_CH2P); + /* set the CH2P bit */ + TIMER_CHCTL2(timer_periph) |= (uint32_t)((uint32_t)(ocpara->ocpolarity)<< 8U); + + if((TIMER0 == timer_periph) || (TIMER7 == timer_periph)){ + /* reset the CH2NEN bit */ + TIMER_CHCTL2(timer_periph) &= (~(uint32_t)TIMER_CHCTL2_CH2NEN); + /* set the CH2NEN bit */ + TIMER_CHCTL2(timer_periph) |= (uint32_t)((uint32_t)(ocpara->outputnstate)<< 8U); + /* reset the CH2NP bit */ + TIMER_CHCTL2(timer_periph) &= (~(uint32_t)TIMER_CHCTL2_CH2NP); + /* set the CH2NP bit */ + TIMER_CHCTL2(timer_periph) |= (uint32_t)((uint32_t)(ocpara->ocnpolarity)<< 8U); + /* reset the ISO2 bit */ + TIMER_CTL1(timer_periph) &= (~(uint32_t)TIMER_CTL1_ISO2); + /* set the ISO2 bit */ + TIMER_CTL1(timer_periph) |= (uint32_t)((uint32_t)(ocpara->ocidlestate)<< 4U); + /* reset the ISO2N bit */ + TIMER_CTL1(timer_periph) &= (~(uint32_t)TIMER_CTL1_ISO2N); + /* set the ISO2N bit */ + TIMER_CTL1(timer_periph) |= (uint32_t)((uint32_t)(ocpara->ocnidlestate)<< 4U); + } + break; + /* configure TIMER_CH_3 */ + case TIMER_CH_3: + /* reset the CH3EN bit */ + TIMER_CHCTL2(timer_periph) &=(~(uint32_t)TIMER_CHCTL2_CH3EN); + TIMER_CHCTL1(timer_periph) &= ~(uint32_t)TIMER_CHCTL1_CH3MS; + /* set the CH3EN bit */ + TIMER_CHCTL2(timer_periph) |= (uint32_t)((uint32_t)(ocpara->outputstate) << 12U); + /* reset the CH3P bit */ + TIMER_CHCTL2(timer_periph) &= (~(uint32_t)TIMER_CHCTL2_CH3P); + /* set the CH3P bit */ + TIMER_CHCTL2(timer_periph) |= (uint32_t)((uint32_t)(ocpara->ocpolarity)<< 12U); + + if((TIMER0 == timer_periph) || (TIMER7 == timer_periph)){ + /* reset the ISO3 bit */ + TIMER_CTL1(timer_periph) &= (~(uint32_t)TIMER_CTL1_ISO3); + /* set the ISO3 bit */ + TIMER_CTL1(timer_periph) |= (uint32_t)((uint32_t)(ocpara->ocidlestate)<< 6U); + } + break; + default: + break; + } +} + +/*! + \brief configure TIMER channel output compare mode + \param[in] timer_periph: please refer to the following parameters + \param[in] channel: + only one parameter can be selected which is shown as below: + \arg TIMER_CH_0: TIMER channel0(TIMERx(x=0..4,7..13)) + \arg TIMER_CH_1: TIMER channel1(TIMERx(x=0..4,7,8,11)) + \arg TIMER_CH_2: TIMER channel2(TIMERx(x=0..4,7)) + \arg TIMER_CH_3: TIMER channel3(TIMERx(x=0..4,7)) + \param[in] ocmode: channel output compare mode + only one parameter can be selected which is shown as below: + \arg TIMER_OC_MODE_TIMING: timing mode + \arg TIMER_OC_MODE_ACTIVE: active mode + \arg TIMER_OC_MODE_INACTIVE: inactive mode + \arg TIMER_OC_MODE_TOGGLE: toggle mode + \arg TIMER_OC_MODE_LOW: force low mode + \arg TIMER_OC_MODE_HIGH: force high mode + \arg TIMER_OC_MODE_PWM0: PWM0 mode + \arg TIMER_OC_MODE_PWM1: PWM1 mode + \param[out] none + \retval none +*/ +void timer_channel_output_mode_config(uint32_t timer_periph, uint16_t channel, uint16_t ocmode) +{ + switch(channel){ + /* configure TIMER_CH_0 */ + case TIMER_CH_0: + TIMER_CHCTL0(timer_periph) &= (~(uint32_t)TIMER_CHCTL0_CH0COMCTL); + TIMER_CHCTL0(timer_periph) |= (uint32_t)ocmode; + break; + /* configure TIMER_CH_1 */ + case TIMER_CH_1: + TIMER_CHCTL0(timer_periph) &= (~(uint32_t)TIMER_CHCTL0_CH1COMCTL); + TIMER_CHCTL0(timer_periph) |= (uint32_t)((uint32_t)(ocmode)<< 8U); + break; + /* configure TIMER_CH_2 */ + case TIMER_CH_2: + TIMER_CHCTL1(timer_periph) &= (~(uint32_t)TIMER_CHCTL1_CH2COMCTL); + TIMER_CHCTL1(timer_periph) |= (uint32_t)ocmode; + break; + /* configure TIMER_CH_3 */ + case TIMER_CH_3: + TIMER_CHCTL1(timer_periph) &= (~(uint32_t)TIMER_CHCTL1_CH3COMCTL); + TIMER_CHCTL1(timer_periph) |= (uint32_t)((uint32_t)(ocmode)<< 8U); + break; + default: + break; + } +} + +/*! + \brief configure TIMER channel output pulse value + \param[in] timer_periph: please refer to the following parameters + \param[in] channel: + only one parameter can be selected which is shown as below: + \arg TIMER_CH_0: TIMER channel0(TIMERx(x=0..4,7..13)) + \arg TIMER_CH_1: TIMER channel1(TIMERx(x=0..4,7,8,11)) + \arg TIMER_CH_2: TIMER channel2(TIMERx(x=0..4,7)) + \arg TIMER_CH_3: TIMER channel3(TIMERx(x=0..4,7)) + \param[in] pulse: channel output pulse value + \param[out] none + \retval none +*/ +void timer_channel_output_pulse_value_config(uint32_t timer_periph, uint16_t channel, uint16_t pulse) +{ + switch(channel){ + /* configure TIMER_CH_0 */ + case TIMER_CH_0: + TIMER_CH0CV(timer_periph) = (uint32_t)pulse; + break; + /* configure TIMER_CH_1 */ + case TIMER_CH_1: + TIMER_CH1CV(timer_periph) = (uint32_t)pulse; + break; + /* configure TIMER_CH_2 */ + case TIMER_CH_2: + TIMER_CH2CV(timer_periph) = (uint32_t)pulse; + break; + /* configure TIMER_CH_3 */ + case TIMER_CH_3: + TIMER_CH3CV(timer_periph) = (uint32_t)pulse; + break; + default: + break; + } +} + +/*! + \brief configure TIMER channel output shadow function + \param[in] timer_periph: please refer to the following parameters + \param[in] channel: + only one parameter can be selected which is shown as below: + \arg TIMER_CH_0: TIMER channel0(TIMERx(x=0..4,7..13)) + \arg TIMER_CH_1: TIMER channel1(TIMERx(x=0..4,7,8,11)) + \arg TIMER_CH_2: TIMER channel2(TIMERx(x=0..4,7)) + \arg TIMER_CH_3: TIMER channel3(TIMERx(x=0..4,7)) + \param[in] ocshadow: channel output shadow state + only one parameter can be selected which is shown as below: + \arg TIMER_OC_SHADOW_ENABLE: channel output shadow state enable + \arg TIMER_OC_SHADOW_DISABLE: channel output shadow state disable + \param[out] none + \retval none +*/ +void timer_channel_output_shadow_config(uint32_t timer_periph, uint16_t channel, uint16_t ocshadow) +{ + switch(channel){ + /* configure TIMER_CH_0 */ + case TIMER_CH_0: + TIMER_CHCTL0(timer_periph) &= (~(uint32_t)TIMER_CHCTL0_CH0COMSEN); + TIMER_CHCTL0(timer_periph) |= (uint32_t)ocshadow; + break; + /* configure TIMER_CH_1 */ + case TIMER_CH_1: + TIMER_CHCTL0(timer_periph) &= (~(uint32_t)TIMER_CHCTL0_CH1COMSEN); + TIMER_CHCTL0(timer_periph) |= (uint32_t)((uint32_t)(ocshadow) << 8U); + break; + /* configure TIMER_CH_2 */ + case TIMER_CH_2: + TIMER_CHCTL1(timer_periph) &= (~(uint32_t)TIMER_CHCTL1_CH2COMSEN); + TIMER_CHCTL1(timer_periph) |= (uint32_t)ocshadow; + break; + /* configure TIMER_CH_3 */ + case TIMER_CH_3: + TIMER_CHCTL1(timer_periph) &= (~(uint32_t)TIMER_CHCTL1_CH3COMSEN); + TIMER_CHCTL1(timer_periph) |= (uint32_t)((uint32_t)(ocshadow) << 8U); + break; + default: + break; + } +} + +/*! + \brief configure TIMER channel output fast function + \param[in] timer_periph: please refer to the following parameters + \param[in] channel: + only one parameter can be selected which is shown as below: + \arg TIMER_CH_0: TIMER channel0(TIMERx(x=0..4,7..13)) + \arg TIMER_CH_1: TIMER channel1(TIMERx(x=0..4,7,8,11)) + \arg TIMER_CH_2: TIMER channel2(TIMERx(x=0..4,7)) + \arg TIMER_CH_3: TIMER channel3(TIMERx(x=0..4,7)) + \param[in] ocfast: channel output fast function + only one parameter can be selected which is shown as below: + \arg TIMER_OC_FAST_ENABLE: channel output fast function enable + \arg TIMER_OC_FAST_DISABLE: channel output fast function disable + \param[out] none + \retval none +*/ +void timer_channel_output_fast_config(uint32_t timer_periph, uint16_t channel, uint16_t ocfast) +{ + switch(channel){ + /* configure TIMER_CH_0 */ + case TIMER_CH_0: + TIMER_CHCTL0(timer_periph) &= (~(uint32_t)TIMER_CHCTL0_CH0COMFEN); + TIMER_CHCTL0(timer_periph) |= (uint32_t)ocfast; + break; + /* configure TIMER_CH_1 */ + case TIMER_CH_1: + TIMER_CHCTL0(timer_periph) &= (~(uint32_t)TIMER_CHCTL0_CH1COMFEN); + TIMER_CHCTL0(timer_periph) |= (uint32_t)((uint32_t)ocfast << 8U); + break; + /* configure TIMER_CH_2 */ + case TIMER_CH_2: + TIMER_CHCTL1(timer_periph) &= (~(uint32_t)TIMER_CHCTL1_CH2COMFEN); + TIMER_CHCTL1(timer_periph) |= (uint32_t)ocfast; + break; + /* configure TIMER_CH_3 */ + case TIMER_CH_3: + TIMER_CHCTL1(timer_periph) &= (~(uint32_t)TIMER_CHCTL1_CH3COMFEN); + TIMER_CHCTL1(timer_periph) |= (uint32_t)((uint32_t)ocfast << 8U); + break; + default: + break; + } +} + +/*! + \brief configure TIMER channel output clear function + \param[in] timer_periph: TIMERx(x=0..4,7) + \param[in] channel: + only one parameter can be selected which is shown as below: + \arg TIMER_CH_0: TIMER channel0 + \arg TIMER_CH_1: TIMER channel1 + \arg TIMER_CH_2: TIMER channel2 + \arg TIMER_CH_3: TIMER channel3 + \param[in] occlear: channel output clear function + only one parameter can be selected which is shown as below: + \arg TIMER_OC_CLEAR_ENABLE: channel output clear function enable + \arg TIMER_OC_CLEAR_DISABLE: channel output clear function disable + \param[out] none + \retval none +*/ +void timer_channel_output_clear_config(uint32_t timer_periph, uint16_t channel, uint16_t occlear) +{ + switch(channel){ + /* configure TIMER_CH_0 */ + case TIMER_CH_0: + TIMER_CHCTL0(timer_periph) &= (~(uint32_t)TIMER_CHCTL0_CH0COMCEN); + TIMER_CHCTL0(timer_periph) |= (uint32_t)occlear; + break; + /* configure TIMER_CH_1 */ + case TIMER_CH_1: + TIMER_CHCTL0(timer_periph) &= (~(uint32_t)TIMER_CHCTL0_CH1COMCEN); + TIMER_CHCTL0(timer_periph) |= (uint32_t)((uint32_t)occlear << 8U); + break; + /* configure TIMER_CH_2 */ + case TIMER_CH_2: + TIMER_CHCTL1(timer_periph) &= (~(uint32_t)TIMER_CHCTL1_CH2COMCEN); + TIMER_CHCTL1(timer_periph) |= (uint32_t)occlear; + break; + /* configure TIMER_CH_3 */ + case TIMER_CH_3: + TIMER_CHCTL1(timer_periph) &= (~(uint32_t)TIMER_CHCTL1_CH3COMCEN); + TIMER_CHCTL1(timer_periph) |= (uint32_t)((uint32_t)occlear << 8U); + break; + default: + break; + } +} + +/*! + \brief configure TIMER channel output polarity + \param[in] timer_periph: please refer to the following parameters + \param[in] channel: + only one parameter can be selected which is shown as below: + \arg TIMER_CH_0: TIMER channel0(TIMERx(x=0..4,7..13)) + \arg TIMER_CH_1: TIMER channel1(TIMERx(x=0..4,7,8,11)) + \arg TIMER_CH_2: TIMER channel2(TIMERx(x=0..4,7)) + \arg TIMER_CH_3: TIMER channel3(TIMERx(x=0..4,7)) + \param[in] ocpolarity: channel output polarity + only one parameter can be selected which is shown as below: + \arg TIMER_OC_POLARITY_HIGH: channel output polarity is high + \arg TIMER_OC_POLARITY_LOW: channel output polarity is low + \param[out] none + \retval none +*/ +void timer_channel_output_polarity_config(uint32_t timer_periph, uint16_t channel, uint16_t ocpolarity) +{ + switch(channel){ + /* configure TIMER_CH_0 */ + case TIMER_CH_0: + TIMER_CHCTL2(timer_periph) &= (~(uint32_t)TIMER_CHCTL2_CH0P); + TIMER_CHCTL2(timer_periph) |= (uint32_t)ocpolarity; + break; + /* configure TIMER_CH_1 */ + case TIMER_CH_1: + TIMER_CHCTL2(timer_periph) &= (~(uint32_t)TIMER_CHCTL2_CH1P); + TIMER_CHCTL2(timer_periph) |= (uint32_t)((uint32_t)ocpolarity << 4U); + break; + /* configure TIMER_CH_2 */ + case TIMER_CH_2: + TIMER_CHCTL2(timer_periph) &= (~(uint32_t)TIMER_CHCTL2_CH2P); + TIMER_CHCTL2(timer_periph) |= (uint32_t)((uint32_t)ocpolarity << 8U); + break; + /* configure TIMER_CH_3 */ + case TIMER_CH_3: + TIMER_CHCTL2(timer_periph) &= (~(uint32_t)TIMER_CHCTL2_CH3P); + TIMER_CHCTL2(timer_periph) |= (uint32_t)((uint32_t)ocpolarity << 12U); + break; + default: + break; + } +} + +/*! + \brief configure TIMER channel complementary output polarity + \param[in] timer_periph: please refer to the following parameters + \param[in] channel: + only one parameter can be selected which is shown as below: + \arg TIMER_CH_0: TIMER channel0(TIMERx(x=0..4,7..13)) + \arg TIMER_CH_1: TIMER channel1(TIMERx(x=0..4,7,8,11)) + \arg TIMER_CH_2: TIMER channel2(TIMERx(x=0..4,7)) + \param[in] ocnpolarity: channel complementary output polarity + only one parameter can be selected which is shown as below: + \arg TIMER_OCN_POLARITY_HIGH: channel complementary output polarity is high + \arg TIMER_OCN_POLARITY_LOW: channel complementary output polarity is low + \param[out] none + \retval none +*/ +void timer_channel_complementary_output_polarity_config(uint32_t timer_periph, uint16_t channel, uint16_t ocnpolarity) +{ + switch(channel){ + /* configure TIMER_CH_0 */ + case TIMER_CH_0: + TIMER_CHCTL2(timer_periph) &= (~(uint32_t)TIMER_CHCTL2_CH0NP); + TIMER_CHCTL2(timer_periph) |= (uint32_t)ocnpolarity; + break; + /* configure TIMER_CH_1 */ + case TIMER_CH_1: + TIMER_CHCTL2(timer_periph) &= (~(uint32_t)TIMER_CHCTL2_CH1NP); + TIMER_CHCTL2(timer_periph) |= (uint32_t)((uint32_t)ocnpolarity << 4U); + break; + /* configure TIMER_CH_2 */ + case TIMER_CH_2: + TIMER_CHCTL2(timer_periph) &= (~(uint32_t)TIMER_CHCTL2_CH2NP); + TIMER_CHCTL2(timer_periph) |= (uint32_t)((uint32_t)ocnpolarity << 8U); + break; + default: + break; + } +} + +/*! + \brief configure TIMER channel enable state + \param[in] timer_periph: please refer to the following parameters + \param[in] channel: + only one parameter can be selected which is shown as below: + \arg TIMER_CH_0: TIMER channel0(TIMERx(x=0..4,7..13)) + \arg TIMER_CH_1: TIMER channel1(TIMERx(x=0..4,7,8,11)) + \arg TIMER_CH_2: TIMER channel2(TIMERx(x=0..4,7)) + \arg TIMER_CH_3: TIMER channel3(TIMERx(x=0..4,7)) + \param[in] state: TIMER channel enable state + only one parameter can be selected which is shown as below: + \arg TIMER_CCX_ENABLE: channel enable + \arg TIMER_CCX_DISABLE: channel disable + \param[out] none + \retval none +*/ +void timer_channel_output_state_config(uint32_t timer_periph, uint16_t channel, uint32_t state) +{ + switch(channel){ + /* configure TIMER_CH_0 */ + case TIMER_CH_0: + TIMER_CHCTL2(timer_periph) &= (~(uint32_t)TIMER_CHCTL2_CH0EN); + TIMER_CHCTL2(timer_periph) |= (uint32_t)state; + break; + /* configure TIMER_CH_1 */ + case TIMER_CH_1: + TIMER_CHCTL2(timer_periph) &= (~(uint32_t)TIMER_CHCTL2_CH1EN); + TIMER_CHCTL2(timer_periph) |= (uint32_t)((uint32_t)state << 4U); + break; + /* configure TIMER_CH_2 */ + case TIMER_CH_2: + TIMER_CHCTL2(timer_periph) &= (~(uint32_t)TIMER_CHCTL2_CH2EN); + TIMER_CHCTL2(timer_periph) |= (uint32_t)((uint32_t)state << 8U); + break; + /* configure TIMER_CH_3 */ + case TIMER_CH_3: + TIMER_CHCTL2(timer_periph) &= (~(uint32_t)TIMER_CHCTL2_CH3EN); + TIMER_CHCTL2(timer_periph) |= (uint32_t)((uint32_t)state << 12U); + break; + default: + break; + } +} + +/*! + \brief configure TIMER channel complementary output enable state + \param[in] timer_periph: TIMERx(x=0,7) + \param[in] channel: + only one parameter can be selected which is shown as below: + \arg TIMER_CH_0: TIMER channel0 + \arg TIMER_CH_1: TIMER channel1 + \arg TIMER_CH_2: TIMER channel2 + \param[in] ocnstate: TIMER channel complementary output enable state + only one parameter can be selected which is shown as below: + \arg TIMER_CCXN_ENABLE: channel complementary enable + \arg TIMER_CCXN_DISABLE: channel complementary disable + \param[out] none + \retval none +*/ +void timer_channel_complementary_output_state_config(uint32_t timer_periph, uint16_t channel, uint16_t ocnstate) +{ + switch(channel){ + /* configure TIMER_CH_0 */ + case TIMER_CH_0: + TIMER_CHCTL2(timer_periph) &= (~(uint32_t)TIMER_CHCTL2_CH0NEN); + TIMER_CHCTL2(timer_periph) |= (uint32_t)ocnstate; + break; + /* configure TIMER_CH_1 */ + case TIMER_CH_1: + TIMER_CHCTL2(timer_periph) &= (~(uint32_t)TIMER_CHCTL2_CH1NEN); + TIMER_CHCTL2(timer_periph) |= (uint32_t)((uint32_t)ocnstate << 4U); + break; + /* configure TIMER_CH_2 */ + case TIMER_CH_2: + TIMER_CHCTL2(timer_periph) &= (~(uint32_t)TIMER_CHCTL2_CH2NEN); + TIMER_CHCTL2(timer_periph) |= (uint32_t)((uint32_t)ocnstate << 8U); + break; + default: + break; + } +} + +/*! + \brief initialize TIMER channel input parameter struct with a default value + \param[in] icpara: TIMER channel intput parameter struct + \param[out] none + \retval none +*/ +void timer_channel_input_struct_para_init(timer_ic_parameter_struct* icpara) +{ + /* initialize the channel input parameter struct member with the default value */ + icpara->icpolarity = TIMER_IC_POLARITY_RISING; + icpara->icselection = TIMER_IC_SELECTION_DIRECTTI; + icpara->icprescaler = TIMER_IC_PSC_DIV1; + icpara->icfilter = 0U; +} + +/*! + \brief configure TIMER input capture parameter + \param[in] timer_periph: please refer to the following parameters + \param[in] channel: + only one parameter can be selected which is shown as below: + \arg TIMER_CH_0: TIMER channel 0(TIMERx(x=0..4,7..13)) + \arg TIMER_CH_1: TIMER channel 1(TIMERx(x=0..4,7,8,11)) + \arg TIMER_CH_2: TIMER channel 2(TIMERx(x=0..4,7)) + \arg TIMER_CH_3: TIMER channel 3(TIMERx(x=0..4,7)) + \param[in] icpara: TIMER channel intput parameter struct + icpolarity: TIMER_IC_POLARITY_RISING, TIMER_IC_POLARITY_FALLING, + TIMER_IC_POLARITY_BOTH_EDGE(only for TIMER1~TIMER8) + icselection: TIMER_IC_SELECTION_DIRECTTI, TIMER_IC_SELECTION_INDIRECTTI, + TIMER_IC_SELECTION_ITS + icprescaler: TIMER_IC_PSC_DIV1, TIMER_IC_PSC_DIV2, TIMER_IC_PSC_DIV4, + TIMER_IC_PSC_DIV8 + icfilter: 0~15 + \param[out] none + \retval none +*/ +void timer_input_capture_config(uint32_t timer_periph, uint16_t channel, timer_ic_parameter_struct* icpara) +{ + switch(channel){ + /* configure TIMER_CH_0 */ + case TIMER_CH_0: + /* reset the CH0EN bit */ + TIMER_CHCTL2(timer_periph) &= (~(uint32_t)TIMER_CHCTL2_CH0EN); + + /* reset the CH0P and CH0NP bits */ + TIMER_CHCTL2(timer_periph) &= (~(uint32_t)(TIMER_CHCTL2_CH0P | TIMER_CHCTL2_CH0NP)); + TIMER_CHCTL2(timer_periph) |= (uint32_t)(icpara->icpolarity); + /* reset the CH0MS bit */ + TIMER_CHCTL0(timer_periph) &= (~(uint32_t)TIMER_CHCTL0_CH0MS); + TIMER_CHCTL0(timer_periph) |= (uint32_t)(icpara->icselection); + /* reset the CH0CAPFLT bit */ + TIMER_CHCTL0(timer_periph) &= (~(uint32_t)TIMER_CHCTL0_CH0CAPFLT); + TIMER_CHCTL0(timer_periph) |= (uint32_t)((uint32_t)(icpara->icfilter) << 4U); + + /* set the CH0EN bit */ + TIMER_CHCTL2(timer_periph) |= (uint32_t)TIMER_CHCTL2_CH0EN; + break; + + /* configure TIMER_CH_1 */ + case TIMER_CH_1: + /* reset the CH1EN bit */ + TIMER_CHCTL2(timer_periph) &= (~(uint32_t)TIMER_CHCTL2_CH1EN); + + /* reset the CH1P and CH1NP bits */ + TIMER_CHCTL2(timer_periph) &= (~(uint32_t)(TIMER_CHCTL2_CH1P | TIMER_CHCTL2_CH1NP)); + TIMER_CHCTL2(timer_periph) |= (uint32_t)((uint32_t)(icpara->icpolarity) << 4U); + /* reset the CH1MS bit */ + TIMER_CHCTL0(timer_periph) &= (~(uint32_t)TIMER_CHCTL0_CH1MS); + TIMER_CHCTL0(timer_periph) |= (uint32_t)((uint32_t)(icpara->icselection) << 8U); + /* reset the CH1CAPFLT bit */ + TIMER_CHCTL0(timer_periph) &= (~(uint32_t)TIMER_CHCTL0_CH1CAPFLT); + TIMER_CHCTL0(timer_periph) |= (uint32_t)((uint32_t)(icpara->icfilter) << 12U); + + /* set the CH1EN bit */ + TIMER_CHCTL2(timer_periph) |= (uint32_t)TIMER_CHCTL2_CH1EN; + break; + /* configure TIMER_CH_2 */ + case TIMER_CH_2: + /* reset the CH2EN bit */ + TIMER_CHCTL2(timer_periph) &= (~(uint32_t)TIMER_CHCTL2_CH2EN); + + /* reset the CH2P and CH2NP bits */ + TIMER_CHCTL2(timer_periph) &= (~(uint32_t)(TIMER_CHCTL2_CH2P | TIMER_CHCTL2_CH2NP)); + TIMER_CHCTL2(timer_periph) |= (uint32_t)((uint32_t)(icpara->icpolarity) << 8U); + + /* reset the CH2MS bit */ + TIMER_CHCTL1(timer_periph) &= (~(uint32_t)TIMER_CHCTL1_CH2MS); + TIMER_CHCTL1(timer_periph) |= (uint32_t)((uint32_t)(icpara->icselection)); + + /* reset the CH2CAPFLT bit */ + TIMER_CHCTL1(timer_periph) &= (~(uint32_t)TIMER_CHCTL1_CH2CAPFLT); + TIMER_CHCTL1(timer_periph) |= (uint32_t)((uint32_t)(icpara->icfilter) << 4U); + + /* set the CH2EN bit */ + TIMER_CHCTL2(timer_periph) |= (uint32_t)TIMER_CHCTL2_CH2EN; + break; + /* configure TIMER_CH_3 */ + case TIMER_CH_3: + /* reset the CH3EN bit */ + TIMER_CHCTL2(timer_periph) &= (~(uint32_t)TIMER_CHCTL2_CH3EN); + + /* reset the CH3P bits */ + TIMER_CHCTL2(timer_periph) &= (~(uint32_t)(TIMER_CHCTL2_CH3P)); + TIMER_CHCTL2(timer_periph) |= (uint32_t)((uint32_t)(icpara->icpolarity) << 12U); + + /* reset the CH3MS bit */ + TIMER_CHCTL1(timer_periph) &= (~(uint32_t)TIMER_CHCTL1_CH3MS); + TIMER_CHCTL1(timer_periph) |= (uint32_t)((uint32_t)(icpara->icselection) << 8U); + + /* reset the CH3CAPFLT bit */ + TIMER_CHCTL1(timer_periph) &= (~(uint32_t)TIMER_CHCTL1_CH3CAPFLT); + TIMER_CHCTL1(timer_periph) |= (uint32_t)((uint32_t)(icpara->icfilter) << 12U); + + /* set the CH3EN bit */ + TIMER_CHCTL2(timer_periph) |= (uint32_t)TIMER_CHCTL2_CH3EN; + break; + default: + break; + } + /* configure TIMER channel input capture prescaler value */ + timer_channel_input_capture_prescaler_config(timer_periph,channel,(uint16_t)(icpara->icprescaler)); +} + +/*! + \brief configure TIMER channel input capture prescaler value + \param[in] timer_periph: please refer to the following parameters + \param[in] channel: + only one parameter can be selected which is shown as below: + \arg TIMER_CH_0: TIMER channel0(TIMERx(x=0..4,7..13)) + \arg TIMER_CH_1: TIMER channel1(TIMERx(x=0..4,7,8,11)) + \arg TIMER_CH_2: TIMER channel2(TIMERx(x=0..4,7)) + \arg TIMER_CH_3: TIMER channel3(TIMERx(x=0..4,7)) + \param[in] prescaler: channel input capture prescaler value + only one parameter can be selected which is shown as below: + \arg TIMER_IC_PSC_DIV1: no prescaler + \arg TIMER_IC_PSC_DIV2: divided by 2 + \arg TIMER_IC_PSC_DIV4: divided by 4 + \arg TIMER_IC_PSC_DIV8: divided by 8 + \param[out] none + \retval none +*/ +void timer_channel_input_capture_prescaler_config(uint32_t timer_periph, uint16_t channel, uint16_t prescaler) +{ + switch(channel){ + /* configure TIMER_CH_0 */ + case TIMER_CH_0: + TIMER_CHCTL0(timer_periph) &= (~(uint32_t)TIMER_CHCTL0_CH0CAPPSC); + TIMER_CHCTL0(timer_periph) |= (uint32_t)prescaler; + break; + /* configure TIMER_CH_1 */ + case TIMER_CH_1: + TIMER_CHCTL0(timer_periph) &= (~(uint32_t)TIMER_CHCTL0_CH1CAPPSC); + TIMER_CHCTL0(timer_periph) |= ((uint32_t)prescaler << 8U); + break; + /* configure TIMER_CH_2 */ + case TIMER_CH_2: + TIMER_CHCTL1(timer_periph) &= (~(uint32_t)TIMER_CHCTL1_CH2CAPPSC); + TIMER_CHCTL1(timer_periph) |= (uint32_t)prescaler; + break; + /* configure TIMER_CH_3 */ + case TIMER_CH_3: + TIMER_CHCTL1(timer_periph) &= (~(uint32_t)TIMER_CHCTL1_CH3CAPPSC); + TIMER_CHCTL1(timer_periph) |= ((uint32_t)prescaler << 8U); + break; + default: + break; + } +} + +/*! + \brief read TIMER channel capture compare register value + \param[in] timer_periph: please refer to the following parameters + \param[in] channel: + only one parameter can be selected which is shown as below: + \arg TIMER_CH_0: TIMER channel0(TIMERx(x=0..4,7..13)) + \arg TIMER_CH_1: TIMER channel1(TIMERx(x=0..4,7,8,11)) + \arg TIMER_CH_2: TIMER channel2(TIMERx(x=0..4,7)) + \arg TIMER_CH_3: TIMER channel3(TIMERx(x=0..4,7)) + \param[out] none + \retval channel capture compare register value +*/ +uint32_t timer_channel_capture_value_register_read(uint32_t timer_periph, uint16_t channel) +{ + uint32_t count_value = 0U; + + switch(channel){ + case TIMER_CH_0: + /* read TIMER channel 0 capture compare register value */ + count_value = TIMER_CH0CV(timer_periph); + break; + case TIMER_CH_1: + /* read TIMER channel 1 capture compare register value */ + count_value = TIMER_CH1CV(timer_periph); + break; + case TIMER_CH_2: + /* read TIMER channel 2 capture compare register value */ + count_value = TIMER_CH2CV(timer_periph); + break; + case TIMER_CH_3: + /* read TIMER channel 3 capture compare register value */ + count_value = TIMER_CH3CV(timer_periph); + break; + default: + break; + } + return (count_value); +} + +/*! + \brief configure TIMER input pwm capture function + \param[in] timer_periph: TIMERx(x=0..4,7,8,11) + \param[in] channel: + only one parameter can be selected which is shown as below: + \arg TIMER_CH_0: TIMER channel0 + \arg TIMER_CH_1: TIMER channel1 + \param[in] icpwm:TIMER channel intput pwm parameter struct + icpolarity: TIMER_IC_POLARITY_RISING,TIMER_IC_POLARITY_FALLING + icselection: TIMER_IC_SELECTION_DIRECTTI,TIMER_IC_SELECTION_INDIRECTTI + icprescaler: TIMER_IC_PSC_DIV1,TIMER_IC_PSC_DIV2,TIMER_IC_PSC_DIV4,TIMER_IC_PSC_DIV8 + icfilter: 0~15 + \param[out] none + \retval none +*/ +void timer_input_pwm_capture_config(uint32_t timer_periph, uint16_t channel, timer_ic_parameter_struct* icpwm) +{ + uint16_t icpolarity = 0x0U; + uint16_t icselection = 0x0U; + + /* Set channel input polarity */ + if(TIMER_IC_POLARITY_RISING == icpwm->icpolarity){ + icpolarity = TIMER_IC_POLARITY_FALLING; + }else{ + icpolarity = TIMER_IC_POLARITY_RISING; + } + /* Set channel input mode selection */ + if(TIMER_IC_SELECTION_DIRECTTI == icpwm->icselection){ + icselection = TIMER_IC_SELECTION_INDIRECTTI; + }else{ + icselection = TIMER_IC_SELECTION_DIRECTTI; + } + + if(TIMER_CH_0 == channel){ + /* reset the CH0EN bit */ + TIMER_CHCTL2(timer_periph) &= (~(uint32_t)TIMER_CHCTL2_CH0EN); + /* reset the CH0P and CH0NP bits */ + TIMER_CHCTL2(timer_periph) &= (~(uint32_t)(TIMER_CHCTL2_CH0P | TIMER_CHCTL2_CH0NP)); + /* set the CH0P and CH0NP bits */ + TIMER_CHCTL2(timer_periph) |= (uint32_t)(icpwm->icpolarity); + /* reset the CH0MS bit */ + TIMER_CHCTL0(timer_periph) &= (~(uint32_t)TIMER_CHCTL0_CH0MS); + /* set the CH0MS bit */ + TIMER_CHCTL0(timer_periph) |= (uint32_t)(icpwm->icselection); + /* reset the CH0CAPFLT bit */ + TIMER_CHCTL0(timer_periph) &= (~(uint32_t)TIMER_CHCTL0_CH0CAPFLT); + /* set the CH0CAPFLT bit */ + TIMER_CHCTL0(timer_periph) |= ((uint32_t)(icpwm->icfilter) << 4U); + /* set the CH0EN bit */ + TIMER_CHCTL2(timer_periph) |= (uint32_t)TIMER_CHCTL2_CH0EN; + /* configure TIMER channel input capture prescaler value */ + timer_channel_input_capture_prescaler_config(timer_periph,TIMER_CH_0,(uint16_t)(icpwm->icprescaler)); + + /* reset the CH1EN bit */ + TIMER_CHCTL2(timer_periph) &= (~(uint32_t)TIMER_CHCTL2_CH1EN); + /* reset the CH1P and CH1NP bits */ + TIMER_CHCTL2(timer_periph) &= (~(uint32_t)(TIMER_CHCTL2_CH1P|TIMER_CHCTL2_CH1NP)); + /* set the CH1P and CH1NP bits */ + TIMER_CHCTL2(timer_periph) |= (uint32_t)((uint32_t)icpolarity<< 4U); + /* reset the CH1MS bit */ + TIMER_CHCTL0(timer_periph) &= (~(uint32_t)TIMER_CHCTL0_CH1MS); + /* set the CH1MS bit */ + TIMER_CHCTL0(timer_periph) |= (uint32_t)((uint32_t)icselection<< 8U); + /* reset the CH1CAPFLT bit */ + TIMER_CHCTL0(timer_periph) &= (~(uint32_t)TIMER_CHCTL0_CH1CAPFLT); + /* set the CH1CAPFLT bit */ + TIMER_CHCTL0(timer_periph) |= (uint32_t)((uint32_t)(icpwm->icfilter)<< 12U); + /* set the CH1EN bit */ + TIMER_CHCTL2(timer_periph) |= (uint32_t)TIMER_CHCTL2_CH1EN; + /* configure TIMER channel input capture prescaler value */ + timer_channel_input_capture_prescaler_config(timer_periph,TIMER_CH_1,(uint16_t)(icpwm->icprescaler)); + }else{ + /* reset the CH1EN bit */ + TIMER_CHCTL2(timer_periph) &= (~(uint32_t)TIMER_CHCTL2_CH1EN); + /* reset the CH1P and CH1NP bits */ + TIMER_CHCTL2(timer_periph) &= (~(uint32_t)(TIMER_CHCTL2_CH1P|TIMER_CHCTL2_CH1NP)); + /* set the CH1P and CH1NP bits */ + TIMER_CHCTL2(timer_periph) |= (uint32_t)((uint32_t)(icpwm->icpolarity)<< 4U); + /* reset the CH1MS bit */ + TIMER_CHCTL0(timer_periph) &= (~(uint32_t)TIMER_CHCTL0_CH1MS); + /* set the CH1MS bit */ + TIMER_CHCTL0(timer_periph) |= (uint32_t)((uint32_t)(icpwm->icselection)<< 8U); + /* reset the CH1CAPFLT bit */ + TIMER_CHCTL0(timer_periph) &= (~(uint32_t)TIMER_CHCTL0_CH1CAPFLT); + /* set the CH1CAPFLT bit */ + TIMER_CHCTL0(timer_periph) |= (uint32_t)((uint32_t)(icpwm->icfilter)<< 12U); + /* set the CH1EN bit */ + TIMER_CHCTL2(timer_periph) |= (uint32_t)TIMER_CHCTL2_CH1EN; + /* configure TIMER channel input capture prescaler value */ + timer_channel_input_capture_prescaler_config(timer_periph,TIMER_CH_1,(uint16_t)(icpwm->icprescaler)); + + /* reset the CH0EN bit */ + TIMER_CHCTL2(timer_periph) &= (~(uint32_t)TIMER_CHCTL2_CH0EN); + /* reset the CH0P and CH0NP bits */ + TIMER_CHCTL2(timer_periph) &= (~(uint32_t)(TIMER_CHCTL2_CH0P|TIMER_CHCTL2_CH0NP)); + /* set the CH0P and CH0NP bits */ + TIMER_CHCTL2(timer_periph) |= (uint32_t)icpolarity; + /* reset the CH0MS bit */ + TIMER_CHCTL0(timer_periph) &= (~(uint32_t)TIMER_CHCTL0_CH0MS); + /* set the CH0MS bit */ + TIMER_CHCTL0(timer_periph) |= (uint32_t)icselection; + /* reset the CH0CAPFLT bit */ + TIMER_CHCTL0(timer_periph) &= (~(uint32_t)TIMER_CHCTL0_CH0CAPFLT); + /* set the CH0CAPFLT bit */ + TIMER_CHCTL0(timer_periph) |= ((uint32_t)(icpwm->icfilter) << 4U); + /* set the CH0EN bit */ + TIMER_CHCTL2(timer_periph) |= (uint32_t)TIMER_CHCTL2_CH0EN; + /* configure TIMER channel input capture prescaler value */ + timer_channel_input_capture_prescaler_config(timer_periph,TIMER_CH_0,(uint16_t)(icpwm->icprescaler)); + } +} + +/*! + \brief configure TIMER hall sensor mode + \param[in] timer_periph: TIMERx(x=0..4,7) + \param[in] hallmode: + only one parameter can be selected which is shown as below: + \arg TIMER_HALLINTERFACE_ENABLE: TIMER hall sensor mode enable + \arg TIMER_HALLINTERFACE_DISABLE: TIMER hall sensor mode disable + \param[out] none + \retval none +*/ +void timer_hall_mode_config(uint32_t timer_periph, uint32_t hallmode) +{ + if(TIMER_HALLINTERFACE_ENABLE == hallmode){ + TIMER_CTL1(timer_periph) |= (uint32_t)TIMER_CTL1_TI0S; + }else if(TIMER_HALLINTERFACE_DISABLE == hallmode){ + TIMER_CTL1(timer_periph) &= ~(uint32_t)TIMER_CTL1_TI0S; + }else{ + /* illegal parameters */ + } +} + +/*! + \brief select TIMER input trigger source + \param[in] timer_periph: please refer to the following parameters + \param[in] intrigger: + only one parameter can be selected which is shown as below: + \arg TIMER_SMCFG_TRGSEL_ITI0: internal trigger 0,TIMERx(x=0..4,7,8,11) + \arg TIMER_SMCFG_TRGSEL_ITI1: internal trigger 1,TIMERx(x=0..4,7,8,11) + \arg TIMER_SMCFG_TRGSEL_ITI2: internal trigger 2,TIMERx(x=0..4,7,8,11) + \arg TIMER_SMCFG_TRGSEL_ITI3: internal trigger 3,TIMERx(x=0..4,7,8,11) + \arg TIMER_SMCFG_TRGSEL_CI0F_ED: TI0 edge detector,TIMERx(x=0..4,7,8,11) + \arg TIMER_SMCFG_TRGSEL_CI0FE0: filtered TIMER input 0,TIMERx(x=0..4,7,8,11) + \arg TIMER_SMCFG_TRGSEL_CI1FE1: filtered TIMER input 1,TIMERx(x=0..4,7,8,11) + \arg TIMER_SMCFG_TRGSEL_ETIFP: external trigger,TIMERx(x=0..4,7) + \param[out] none + \retval none +*/ +void timer_input_trigger_source_select(uint32_t timer_periph, uint32_t intrigger) +{ + TIMER_SMCFG(timer_periph) &= (~(uint32_t)TIMER_SMCFG_TRGS); + TIMER_SMCFG(timer_periph) |= (uint32_t)intrigger; +} + +/*! + \brief select TIMER master mode output trigger source + \param[in] timer_periph: TIMERx(x=0..7) + \param[in] outrigger: + only one parameter can be selected which is shown as below: + \arg TIMER_TRI_OUT_SRC_RESET: the UPG bit as trigger output(TIMERx(x=0..7)) + \arg TIMER_TRI_OUT_SRC_ENABLE: the counter enable signal TIMER_CTL0_CEN as trigger output(TIMERx(x=0..7)) + \arg TIMER_TRI_OUT_SRC_UPDATE: update event as trigger output(TIMERx(x=0..7)) + \arg TIMER_TRI_OUT_SRC_CH0: a capture or a compare match occurred in channel 0 as trigger output TRGO(TIMERx(x=0..4,7)) + \arg TIMER_TRI_OUT_SRC_O0CPRE: O0CPRE as trigger output(TIMERx(x=0..4,7)) + \arg TIMER_TRI_OUT_SRC_O1CPRE: O1CPRE as trigger output(TIMERx(x=0..4,7)) + \arg TIMER_TRI_OUT_SRC_O2CPRE: O2CPRE as trigger output(TIMERx(x=0..4,7)) + \arg TIMER_TRI_OUT_SRC_O3CPRE: O3CPRE as trigger output(TIMERx(x=0..4,7)) + \param[out] none + \retval none +*/ +void timer_master_output_trigger_source_select(uint32_t timer_periph, uint32_t outrigger) +{ + TIMER_CTL1(timer_periph) &= (~(uint32_t)TIMER_CTL1_MMC); + TIMER_CTL1(timer_periph) |= (uint32_t)outrigger; +} + +/*! + \brief select TIMER slave mode + \param[in] timer_periph: TIMERx(x=0..4,7,8,11) + \param[in] slavemode: + only one parameter can be selected which is shown as below: + \arg TIMER_SLAVE_MODE_DISABLE: slave mode disable + \arg TIMER_ENCODER_MODE0: encoder mode 0 + \arg TIMER_ENCODER_MODE1: encoder mode 1 + \arg TIMER_ENCODER_MODE2: encoder mode 2 + \arg TIMER_SLAVE_MODE_RESTART: restart mode + \arg TIMER_SLAVE_MODE_PAUSE: pause mode + \arg TIMER_SLAVE_MODE_EVENT: event mode + \arg TIMER_SLAVE_MODE_EXTERNAL0: external clock mode 0. + \param[out] none + \retval none +*/ + +void timer_slave_mode_select(uint32_t timer_periph, uint32_t slavemode) +{ + TIMER_SMCFG(timer_periph) &= (~(uint32_t)TIMER_SMCFG_SMC); + + TIMER_SMCFG(timer_periph) |= (uint32_t)slavemode; +} + +/*! + \brief configure TIMER master slave mode + \param[in] timer_periph: TIMERx(x=0..4,7,8,11) + \param[in] masterslave: + only one parameter can be selected which is shown as below: + \arg TIMER_MASTER_SLAVE_MODE_ENABLE: master slave mode enable + \arg TIMER_MASTER_SLAVE_MODE_DISABLE: master slave mode disable + \param[out] none + \retval none +*/ +void timer_master_slave_mode_config(uint32_t timer_periph, uint32_t masterslave) +{ + if(TIMER_MASTER_SLAVE_MODE_ENABLE == masterslave){ + TIMER_SMCFG(timer_periph) |= (uint32_t)TIMER_SMCFG_MSM; + }else if(TIMER_MASTER_SLAVE_MODE_DISABLE == masterslave){ + TIMER_SMCFG(timer_periph) &= ~(uint32_t)TIMER_SMCFG_MSM; + }else{ + /* illegal parameters */ + } +} + +/*! + \brief configure TIMER external trigger input + \param[in] timer_periph: TIMERx(x=0..4,7) + \param[in] extprescaler: + only one parameter can be selected which is shown as below: + \arg TIMER_EXT_TRI_PSC_OFF: no divided + \arg TIMER_EXT_TRI_PSC_DIV2: divided by 2 + \arg TIMER_EXT_TRI_PSC_DIV4: divided by 4 + \arg TIMER_EXT_TRI_PSC_DIV8: divided by 8 + \param[in] expolarity: + only one parameter can be selected which is shown as below: + \arg TIMER_ETP_FALLING: active low or falling edge active + \arg TIMER_ETP_RISING: active high or rising edge active + \param[in] extfilter: a value between 0 and 15 + \param[out] none + \retval none +*/ +void timer_external_trigger_config(uint32_t timer_periph, uint32_t extprescaler, uint32_t extpolarity, uint8_t extfilter) +{ + TIMER_SMCFG(timer_periph) &= (~(uint32_t)(TIMER_SMCFG_ETP | TIMER_SMCFG_ETPSC | TIMER_SMCFG_ETFC)); + TIMER_SMCFG(timer_periph) |= (uint32_t)(extprescaler | extpolarity); + TIMER_SMCFG(timer_periph) |= (uint32_t)(extfilter << 8U); +} + +/*! + \brief configure TIMER quadrature decoder mode + \param[in] timer_periph: TIMERx(x=0..4,7,8,11) + \param[in] decomode: + only one parameter can be selected which is shown as below: + \arg TIMER_ENCODER_MODE0: counter counts on CI0FE0 edge depending on CI1FE1 level + \arg TIMER_ENCODER_MODE1: counter counts on CI1FE1 edge depending on CI0FE0 level + \arg TIMER_ENCODER_MODE2: counter counts on both CI0FE0 and CI1FE1 edges depending on the level of the other input + \param[in] ic0polarity: + only one parameter can be selected which is shown as below: + \arg TIMER_IC_POLARITY_RISING: capture rising edge + \arg TIMER_IC_POLARITY_FALLING: capture falling edge + \param[in] ic1polarity: + only one parameter can be selected which is shown as below: + \arg TIMER_IC_POLARITY_RISING: capture rising edge + \arg TIMER_IC_POLARITY_FALLING: capture falling edge + \param[out] none + \retval none +*/ +void timer_quadrature_decoder_mode_config(uint32_t timer_periph, uint32_t decomode, uint16_t ic0polarity, uint16_t ic1polarity) +{ + /* configure the quadrature decoder mode */ + TIMER_SMCFG(timer_periph) &= (~(uint32_t)TIMER_SMCFG_SMC); + TIMER_SMCFG(timer_periph) |= (uint32_t)decomode; + /* configure input capture selection */ + TIMER_CHCTL0(timer_periph) &= (uint32_t)(((~(uint32_t)TIMER_CHCTL0_CH0MS)) & ((~(uint32_t)TIMER_CHCTL0_CH1MS))); + TIMER_CHCTL0(timer_periph) |= (uint32_t)(TIMER_IC_SELECTION_DIRECTTI | ((uint32_t)TIMER_IC_SELECTION_DIRECTTI << 8U)); + /* configure channel input capture polarity */ + TIMER_CHCTL2(timer_periph) &= (~(uint32_t)(TIMER_CHCTL2_CH0P | TIMER_CHCTL2_CH0NP)); + TIMER_CHCTL2(timer_periph) &= (~(uint32_t)(TIMER_CHCTL2_CH1P | TIMER_CHCTL2_CH1NP)); + TIMER_CHCTL2(timer_periph) |= ((uint32_t)ic0polarity | ((uint32_t)ic1polarity << 4U)); +} + +/*! + \brief configure TIMER internal clock mode + \param[in] timer_periph: TIMERx(x=0..4,7,8,11) + \param[out] none + \retval none +*/ +void timer_internal_clock_config(uint32_t timer_periph) +{ + TIMER_SMCFG(timer_periph) &= ~(uint32_t)TIMER_SMCFG_SMC; +} + +/*! + \brief configure TIMER the internal trigger as external clock input + \param[in] timer_periph: TIMERx(x=0..4,7,8,11) + \param[in] intrigger: + only one parameter can be selected which is shown as below: + \arg TIMER_SMCFG_TRGSEL_ITI0: internal trigger 0 + \arg TIMER_SMCFG_TRGSEL_ITI1: internal trigger 1 + \arg TIMER_SMCFG_TRGSEL_ITI2: internal trigger 2 + \arg TIMER_SMCFG_TRGSEL_ITI3: internal trigger 3 + \param[out] none + \retval none +*/ +void timer_internal_trigger_as_external_clock_config(uint32_t timer_periph, uint32_t intrigger) +{ + timer_input_trigger_source_select(timer_periph,intrigger); + TIMER_SMCFG(timer_periph) &= ~(uint32_t)TIMER_SMCFG_SMC; + TIMER_SMCFG(timer_periph) |= (uint32_t)TIMER_SLAVE_MODE_EXTERNAL0; +} + +/*! + \brief configure TIMER the external trigger as external clock input + \param[in] timer_periph: TIMERx(x=0..4,7,8,11) + \param[in] extrigger: + only one parameter can be selected which is shown as below: + \arg TIMER_SMCFG_TRGSEL_CI0F_ED: TI0 edge detector + \arg TIMER_SMCFG_TRGSEL_CI0FE0: filtered TIMER input 0 + \arg TIMER_SMCFG_TRGSEL_CI1FE1: filtered TIMER input 1 + \param[in] expolarity: + only one parameter can be selected which is shown as below: + \arg TIMER_IC_POLARITY_RISING: active high or rising edge active + \arg TIMER_IC_POLARITY_FALLING: active low or falling edge active + \param[in] extfilter: a value between 0 and 15 + \param[out] none + \retval none +*/ +void timer_external_trigger_as_external_clock_config(uint32_t timer_periph, uint32_t extrigger, uint16_t extpolarity, uint8_t extfilter) +{ + if(TIMER_SMCFG_TRGSEL_CI1FE1 == extrigger){ + /* reset the CH1EN bit */ + TIMER_CHCTL2(timer_periph) &= (~(uint32_t)TIMER_CHCTL2_CH1EN); + /* reset the CH1NP bit */ + TIMER_CHCTL2(timer_periph) &= (~(uint32_t)(TIMER_CHCTL2_CH1P|TIMER_CHCTL2_CH1NP)); + /* set the CH1NP bit */ + TIMER_CHCTL2(timer_periph) |= (uint32_t)((uint32_t)extpolarity << 4U); + /* reset the CH1MS bit */ + TIMER_CHCTL0(timer_periph) &= (~(uint32_t)TIMER_CHCTL0_CH1MS); + /* set the CH1MS bit */ + TIMER_CHCTL0(timer_periph) |= (uint32_t)((uint32_t)TIMER_IC_SELECTION_DIRECTTI<< 8U); + /* reset the CH1CAPFLT bit */ + TIMER_CHCTL0(timer_periph) &= (~(uint32_t)TIMER_CHCTL0_CH1CAPFLT); + /* set the CH1CAPFLT bit */ + TIMER_CHCTL0(timer_periph) |= (uint32_t)(extfilter << 12U); + /* set the CH1EN bit */ + TIMER_CHCTL2(timer_periph) |= (uint32_t)TIMER_CHCTL2_CH1EN; + }else{ + /* reset the CH0EN bit */ + TIMER_CHCTL2(timer_periph) &= (~(uint32_t)TIMER_CHCTL2_CH0EN); + /* reset the CH0P and CH0NP bits */ + TIMER_CHCTL2(timer_periph) &= (~(uint32_t)(TIMER_CHCTL2_CH0P|TIMER_CHCTL2_CH0NP)); + /* set the CH0P and CH0NP bits */ + TIMER_CHCTL2(timer_periph) |= (uint32_t)extpolarity; + /* reset the CH0MS bit */ + TIMER_CHCTL0(timer_periph) &= (~(uint32_t)TIMER_CHCTL0_CH0MS); + /* set the CH0MS bit */ + TIMER_CHCTL0(timer_periph) |= (uint32_t)TIMER_IC_SELECTION_DIRECTTI; + /* reset the CH0CAPFLT bit */ + TIMER_CHCTL0(timer_periph) &= (~(uint32_t)TIMER_CHCTL0_CH0CAPFLT); + /* reset the CH0CAPFLT bit */ + TIMER_CHCTL0(timer_periph) |= (uint32_t)(extfilter << 4U); + /* set the CH0EN bit */ + TIMER_CHCTL2(timer_periph) |= (uint32_t)TIMER_CHCTL2_CH0EN; + } + /* select TIMER input trigger source */ + timer_input_trigger_source_select(timer_periph,extrigger); + /* reset the SMC bit */ + TIMER_SMCFG(timer_periph) &= (~(uint32_t)TIMER_SMCFG_SMC); + /* set the SMC bit */ + TIMER_SMCFG(timer_periph) |= (uint32_t)TIMER_SLAVE_MODE_EXTERNAL0; +} + +/*! + \brief configure TIMER the external clock mode0 + \param[in] timer_periph: TIMERx(x=0..4,7,8,11) + \param[in] extprescaler: + only one parameter can be selected which is shown as below: + \arg TIMER_EXT_TRI_PSC_OFF: no divided + \arg TIMER_EXT_TRI_PSC_DIV2: divided by 2 + \arg TIMER_EXT_TRI_PSC_DIV4: divided by 4 + \arg TIMER_EXT_TRI_PSC_DIV8: divided by 8 + \param[in] expolarity: + only one parameter can be selected which is shown as below: + \arg TIMER_ETP_FALLING: active low or falling edge active + \arg TIMER_ETP_RISING: active high or rising edge active + \param[in] extfilter: a value between 0 and 15 + \param[out] none + \retval none +*/ +void timer_external_clock_mode0_config(uint32_t timer_periph, uint32_t extprescaler, uint32_t extpolarity, uint8_t extfilter) +{ + /* configure TIMER external trigger input */ + timer_external_trigger_config(timer_periph, extprescaler, extpolarity, extfilter); + /* reset the SMC bit,TRGS bit */ + TIMER_SMCFG(timer_periph) &= (~(uint32_t)(TIMER_SMCFG_SMC | TIMER_SMCFG_TRGS)); + /* set the SMC bit,TRGS bit */ + TIMER_SMCFG(timer_periph) |= (uint32_t)(TIMER_SLAVE_MODE_EXTERNAL0 | TIMER_SMCFG_TRGSEL_ETIFP); +} + +/*! + \brief configure TIMER the external clock mode1 + \param[in] timer_periph: TIMERx(x=0..4,7) + \param[in] extprescaler: + only one parameter can be selected which is shown as below: + \arg TIMER_EXT_TRI_PSC_OFF: no divided + \arg TIMER_EXT_TRI_PSC_DIV2: divided by 2 + \arg TIMER_EXT_TRI_PSC_DIV4: divided by 4 + \arg TIMER_EXT_TRI_PSC_DIV8: divided by 8 + \param[in] extpolarity: + only one parameter can be selected which is shown as below: + \arg TIMER_ETP_FALLING: active low or falling edge active + \arg TIMER_ETP_RISING: active high or rising edge active + \param[in] extfilter: a value between 0 and 15 + \param[out] none + \retval none +*/ +void timer_external_clock_mode1_config(uint32_t timer_periph, uint32_t extprescaler, uint32_t extpolarity, uint8_t extfilter) +{ + /* configure TIMER external trigger input */ + timer_external_trigger_config(timer_periph, extprescaler, extpolarity, extfilter); + TIMER_SMCFG(timer_periph) |= (uint32_t)TIMER_SMCFG_SMC1; +} + +/*! + \brief disable TIMER the external clock mode1 + \param[in] timer_periph: TIMERx(x=0..4,7) + \param[out] none + \retval none +*/ +void timer_external_clock_mode1_disable(uint32_t timer_periph) +{ + TIMER_SMCFG(timer_periph) &= ~(uint32_t)TIMER_SMCFG_SMC1; +} + +/*! + \brief enable the TIMER interrupt + \param[in] timer_periph: please refer to the following parameters + \param[in] interrupt: timer interrupt enable source + only one parameter can be selected which is shown as below: + \arg TIMER_INT_UP: update interrupt enable, TIMERx(x=0..13) + \arg TIMER_INT_CH0: channel 0 interrupt enable, TIMERx(x=0..4,7..13) + \arg TIMER_INT_CH1: channel 1 interrupt enable, TIMERx(x=0..4,7,8,11) + \arg TIMER_INT_CH2: channel 2 interrupt enable, TIMERx(x=0..4,7) + \arg TIMER_INT_CH3: channel 3 interrupt enable , TIMERx(x=0..4,7) + \arg TIMER_INT_CMT: commutation interrupt enable, TIMERx(x=0,7) + \arg TIMER_INT_TRG: trigger interrupt enable, TIMERx(x=0..4,7,8,11) + \arg TIMER_INT_BRK: break interrupt enable, TIMERx(x=0,7) + \param[out] none + \retval none +*/ +void timer_interrupt_enable(uint32_t timer_periph, uint32_t interrupt) +{ + TIMER_DMAINTEN(timer_periph) |= (uint32_t) interrupt; +} + +/*! + \brief disable the TIMER interrupt + \param[in] timer_periph: please refer to the following parameters + \param[in] interrupt: timer interrupt source disable + only one parameter can be selected which is shown as below: + \arg TIMER_INT_UP: update interrupt disable, TIMERx(x=0..13) + \arg TIMER_INT_CH0: channel 0 interrupt disable, TIMERx(x=0..4,7..13) + \arg TIMER_INT_CH1: channel 1 interrupt disable, TIMERx(x=0..4,7,8,11) + \arg TIMER_INT_CH2: channel 2 interrupt disable, TIMERx(x=0..4,7) + \arg TIMER_INT_CH3: channel 3 interrupt disable , TIMERx(x=0..4,7) + \arg TIMER_INT_CMT: commutation interrupt disable, TIMERx(x=0,7) + \arg TIMER_INT_TRG: trigger interrupt disable, TIMERx(x=0..4,7,8,11) + \arg TIMER_INT_BRK: break interrupt disable, TIMERx(x=0,7) + \param[out] none + \retval none +*/ +void timer_interrupt_disable(uint32_t timer_periph, uint32_t interrupt) +{ + TIMER_DMAINTEN(timer_periph) &= (~(uint32_t)interrupt); +} + +/*! + \brief get timer interrupt flag + \param[in] timer_periph: please refer to the following parameters + \param[in] interrupt: the timer interrupt bits + only one parameter can be selected which is shown as below: + \arg TIMER_INT_FLAG_UP: update interrupt flag,TIMERx(x=0..13) + \arg TIMER_INT_FLAG_CH0: channel 0 interrupt flag,TIMERx(x=0..4,7..13) + \arg TIMER_INT_FLAG_CH1: channel 1 interrupt flag,TIMERx(x=0..4,7,8,11) + \arg TIMER_INT_FLAG_CH2: channel 2 interrupt flag,TIMERx(x=0..4,7) + \arg TIMER_INT_FLAG_CH3: channel 3 interrupt flag,TIMERx(x=0..4,7) + \arg TIMER_INT_FLAG_CMT: channel commutation interrupt flag,TIMERx(x=0,7) + \arg TIMER_INT_FLAG_TRG: trigger interrupt flag,TIMERx(x=0,7,8,11) + \arg TIMER_INT_FLAG_BRK: break interrupt flag,TIMERx(x=0,7) + \param[out] none + \retval FlagStatus: SET or RESET +*/ +FlagStatus timer_interrupt_flag_get(uint32_t timer_periph, uint32_t interrupt) +{ + uint32_t val; + val = (TIMER_DMAINTEN(timer_periph) & interrupt); + if((RESET != (TIMER_INTF(timer_periph) & interrupt) ) && (RESET != val)){ + return SET; + }else{ + return RESET; + } +} + +/*! + \brief clear TIMER interrupt flag + \param[in] timer_periph: please refer to the following parameters + \param[in] interrupt: the timer interrupt bits + only one parameter can be selected which is shown as below: + \arg TIMER_INT_FLAG_UP: update interrupt flag,TIMERx(x=0..13) + \arg TIMER_INT_FLAG_CH0: channel 0 interrupt flag,TIMERx(x=0..4,7..13) + \arg TIMER_INT_FLAG_CH1: channel 1 interrupt flag,TIMERx(x=0..4,7,8,11) + \arg TIMER_INT_FLAG_CH2: channel 2 interrupt flag,TIMERx(x=0..4,7) + \arg TIMER_INT_FLAG_CH3: channel 3 interrupt flag,TIMERx(x=0..4,7) + \arg TIMER_INT_FLAG_CMT: channel commutation interrupt flag,TIMERx(x=0,7) + \arg TIMER_INT_FLAG_TRG: trigger interrupt flag,TIMERx(x=0,7,8,11) + \arg TIMER_INT_FLAG_BRK: break interrupt flag,TIMERx(x=0,7) + \param[out] none + \retval none +*/ +void timer_interrupt_flag_clear(uint32_t timer_periph, uint32_t interrupt) +{ + TIMER_INTF(timer_periph) = (~(uint32_t)interrupt); +} + +/*! + \brief get TIMER flags + \param[in] timer_periph: please refer to the following parameters + \param[in] flag: the timer interrupt flags + only one parameter can be selected which is shown as below: + \arg TIMER_FLAG_UP: update flag,TIMERx(x=0..13) + \arg TIMER_FLAG_CH0: channel 0 flag,TIMERx(x=0..4,7..13) + \arg TIMER_FLAG_CH1: channel 1 flag,TIMERx(x=0..4,7,8,11) + \arg TIMER_FLAG_CH2: channel 2 flag,TIMERx(x=0..4,7) + \arg TIMER_FLAG_CH3: channel 3 flag,TIMERx(x=0..4,7) + \arg TIMER_FLAG_CMT: channel commutation flag,TIMERx(x=0,7) + \arg TIMER_FLAG_TRG: trigger flag,TIMERx(x=0,7,8,11) + \arg TIMER_FLAG_BRK: break flag,TIMERx(x=0,7) + \arg TIMER_FLAG_CH0O: channel 0 overcapture flag,TIMERx(x=0..4,7..11) + \arg TIMER_FLAG_CH1O: channel 1 overcapture flag,TIMERx(x=0..4,7,8,11) + \arg TIMER_FLAG_CH2O: channel 2 overcapture flag,TIMERx(x=0..4,7) + \arg TIMER_FLAG_CH3O: channel 3 overcapture flag,TIMERx(x=0..4,7) + \param[out] none + \retval FlagStatus: SET or RESET +*/ +FlagStatus timer_flag_get(uint32_t timer_periph, uint32_t flag) +{ + if(RESET != (TIMER_INTF(timer_periph) & flag)){ + return SET; + }else{ + return RESET; + } +} + +/*! + \brief clear TIMER flags + \param[in] timer_periph: please refer to the following parameters + \param[in] flag: the timer interrupt flags + only one parameter can be selected which is shown as below: + \arg TIMER_FLAG_UP: update flag,TIMERx(x=0..13) + \arg TIMER_FLAG_CH0: channel 0 flag,TIMERx(x=0..4,7..13) + \arg TIMER_FLAG_CH1: channel 1 flag,TIMERx(x=0..4,7,8,11) + \arg TIMER_FLAG_CH2: channel 2 flag,TIMERx(x=0..4,7) + \arg TIMER_FLAG_CH3: channel 3 flag,TIMERx(x=0..4,7) + \arg TIMER_FLAG_CMT: channel control update flag,TIMERx(x=0,7) + \arg TIMER_FLAG_TRG: trigger flag,TIMERx(x=0,7,8,11) + \arg TIMER_FLAG_BRK: break flag,TIMERx(x=0,7) + \arg TIMER_FLAG_CH0O: channel 0 overcapture flag,TIMERx(x=0..4,7..11) + \arg TIMER_FLAG_CH1O: channel 1 overcapture flag,TIMERx(x=0..4,7,8,11) + \arg TIMER_FLAG_CH2O: channel 2 overcapture flag,TIMERx(x=0..4,7) + \arg TIMER_FLAG_CH3O: channel 3 overcapture flag,TIMERx(x=0..4,7) + \param[out] none + \retval none +*/ +void timer_flag_clear(uint32_t timer_periph, uint32_t flag) +{ + TIMER_INTF(timer_periph) = (~(uint32_t)flag); +} diff --git a/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_standard_peripheral/Source/gd32f10x_usart.c b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_standard_peripheral/Source/gd32f10x_usart.c new file mode 100644 index 0000000000..c1f000a6f0 --- /dev/null +++ b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_standard_peripheral/Source/gd32f10x_usart.c @@ -0,0 +1,766 @@ +/*! + \file gd32f10x_usart.c + \brief USART driver + + \version 2014-12-26, V1.0.0, firmware for GD32F10x + \version 2017-06-20, V2.0.1, firmware for GD32F10x + \version 2018-07-31, V2.1.0, firmware for GD32F10x + \version 2020-09-30, V2.2.0, firmware for GD32F10x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "gd32f10x_usart.h" + +/*! + \brief reset USART/UART + \param[in] usart_periph: USARTx(x=0,1,2)/UARTx(x=3,4) + \param[out] none + \retval none +*/ +void usart_deinit(uint32_t usart_periph) +{ + switch(usart_periph){ + case USART0: + /* reset USART0 */ + rcu_periph_reset_enable(RCU_USART0RST); + rcu_periph_reset_disable(RCU_USART0RST); + break; + case USART1: + /* reset USART1 */ + rcu_periph_reset_enable(RCU_USART1RST); + rcu_periph_reset_disable(RCU_USART1RST); + break; + case USART2: + /* reset USART2 */ + rcu_periph_reset_enable(RCU_USART2RST); + rcu_periph_reset_disable(RCU_USART2RST); + break; + case UART3: + /* reset UART3 */ + rcu_periph_reset_enable(RCU_UART3RST); + rcu_periph_reset_disable(RCU_UART3RST); + break; + case UART4: + /* reset UART4 */ + rcu_periph_reset_enable(RCU_UART4RST); + rcu_periph_reset_disable(RCU_UART4RST); + break; + default: + break; + } +} + +/*! + \brief configure USART baud rate value + \param[in] usart_periph: USARTx(x=0,1,2)/UARTx(x=3,4) + \param[in] baudval: baud rate value + \param[out] none + \retval none +*/ +void usart_baudrate_set(uint32_t usart_periph, uint32_t baudval) +{ + uint32_t uclk=0U, intdiv=0U, fradiv=0U, udiv=0U; + switch(usart_periph){ + /* get clock frequency */ + case USART0: + /* get USART0 clock */ + uclk=rcu_clock_freq_get(CK_APB2); + break; + case USART1: + /* get USART1 clock */ + uclk=rcu_clock_freq_get(CK_APB1); + break; + case USART2: + /* get USART2 clock */ + uclk=rcu_clock_freq_get(CK_APB1); + break; + case UART3: + /* get UART3 clock */ + uclk=rcu_clock_freq_get(CK_APB1); + break; + case UART4: + /* get UART4 clock */ + uclk=rcu_clock_freq_get(CK_APB1); + break; + default: + break; + } + /* oversampling by 16, configure the value of USART_BAUD */ + udiv = (uclk+baudval/2U)/baudval; + intdiv = udiv & (0x0000fff0U); + fradiv = udiv & (0x0000000fU); + USART_BAUD(usart_periph) = ((USART_BAUD_FRADIV | USART_BAUD_INTDIV) & (intdiv | fradiv)); +} + +/*! + \brief configure USART parity + \param[in] usart_periph: USARTx(x=0,1,2)/UARTx(x=3,4) + \param[in] paritycfg: configure USART parity + only one parameter can be selected which is shown as below: + \arg USART_PM_NONE: no parity + \arg USART_PM_ODD: odd parity + \arg USART_PM_EVEN: even parity + \param[out] none + \retval none +*/ +void usart_parity_config(uint32_t usart_periph, uint32_t paritycfg) +{ + /* clear USART_CTL0 PM,PCEN bits */ + USART_CTL0(usart_periph) &= ~(USART_CTL0_PM | USART_CTL0_PCEN); + /* configure USART parity mode */ + USART_CTL0(usart_periph) |= paritycfg ; +} + +/*! + \brief configure USART word length + \param[in] usart_periph: USARTx(x=0,1,2)/UARTx(x=3,4) + \param[in] wlen: USART word length configure + only one parameter can be selected which is shown as below: + \arg USART_WL_8BIT: 8 bits + \arg USART_WL_9BIT: 9 bits + \param[out] none + \retval none +*/ +void usart_word_length_set(uint32_t usart_periph, uint32_t wlen) +{ + /* clear USART_CTL0 WL bit */ + USART_CTL0(usart_periph) &= ~USART_CTL0_WL; + /* configure USART word length */ + USART_CTL0(usart_periph) |= wlen; +} + +/*! + \brief configure USART stop bit length + \param[in] usart_periph: USARTx(x=0,1,2)/UARTx(x=3,4) + \param[in] stblen: USART stop bit configure + only one parameter can be selected which is shown as below: + \arg USART_STB_1BIT: 1 bit + \arg USART_STB_0_5BIT: 0.5 bit, not available for UARTx(x=3,4) + \arg USART_STB_2BIT: 2 bits + \arg USART_STB_1_5BIT: 1.5 bits, not available for UARTx(x=3,4) + \param[out] none + \retval none +*/ +void usart_stop_bit_set(uint32_t usart_periph, uint32_t stblen) +{ + /* clear USART_CTL1 STB bits */ + USART_CTL1(usart_periph) &= ~USART_CTL1_STB; + /* configure USART stop bits */ + USART_CTL1(usart_periph) |= stblen; +} +/*! + \brief enable USART + \param[in] usart_periph: USARTx(x=0,1,2)/UARTx(x=3,4) + \param[out] none + \retval none +*/ +void usart_enable(uint32_t usart_periph) +{ + USART_CTL0(usart_periph) |= USART_CTL0_UEN; +} + +/*! + \brief disable USART + \param[in] usart_periph: USARTx(x=0,1,2)/UARTx(x=3,4) + \param[out] none + \retval none +*/ +void usart_disable(uint32_t usart_periph) +{ + USART_CTL0(usart_periph) &= ~(USART_CTL0_UEN); +} + +/*! + \brief configure USART transmitter + \param[in] usart_periph: USARTx(x=0,1,2)/UARTx(x=3,4) + \param[in] txconfig: enable or disable USART transmitter + only one parameter can be selected which is shown as below: + \arg USART_TRANSMIT_ENABLE: enable USART transmission + \arg USART_TRANSMIT_DISABLE: disable USART transmission + \param[out] none + \retval none +*/ +void usart_transmit_config(uint32_t usart_periph, uint32_t txconfig) +{ + uint32_t ctl = 0U; + + ctl = USART_CTL0(usart_periph); + ctl &= ~USART_CTL0_TEN; + ctl |= txconfig; + /* configure transfer mode */ + USART_CTL0(usart_periph) = ctl; +} + +/*! + \brief configure USART receiver + \param[in] usart_periph: USARTx(x=0,1,2)/UARTx(x=3,4) + \param[in] rxconfig: enable or disable USART receiver + only one parameter can be selected which is shown as below: + \arg USART_RECEIVE_ENABLE: enable USART reception + \arg USART_RECEIVE_DISABLE: disable USART reception + \param[out] none + \retval none +*/ +void usart_receive_config(uint32_t usart_periph, uint32_t rxconfig) +{ + uint32_t ctl = 0U; + + ctl = USART_CTL0(usart_periph); + ctl &= ~USART_CTL0_REN; + ctl |= rxconfig; + /* configure receiver mode */ + USART_CTL0(usart_periph) = ctl; +} + +/*! + \brief USART transmit data function + \param[in] usart_periph: USARTx(x=0,1,2)/UARTx(x=3,4) + \param[in] data: data of transmission + \param[out] none + \retval none +*/ +void usart_data_transmit(uint32_t usart_periph, uint16_t data) +{ + USART_DATA(usart_periph) = USART_DATA_DATA & data; +} + +/*! + \brief USART receive data function + \param[in] usart_periph: USARTx(x=0,1,2)/UARTx(x=3,4) + \param[out] none + \retval data of received +*/ +uint16_t usart_data_receive(uint32_t usart_periph) +{ + return (uint16_t)(GET_BITS(USART_DATA(usart_periph), 0U, 8U)); +} + +/*! + \brief configure the address of the USART in wake up by address match mode + \param[in] usart_periph: USARTx(x=0,1,2)/UARTx(x=3,4) + \param[in] addr: address of USART/UART + \param[out] none + \retval none +*/ +void usart_address_config(uint32_t usart_periph, uint8_t addr) +{ + USART_CTL1(usart_periph) &= ~(USART_CTL1_ADDR); + USART_CTL1(usart_periph) |= (USART_CTL1_ADDR & addr); +} + +/*! + \brief receiver in mute mode + \param[in] usart_periph: USARTx(x=0,1,2)/UARTx(x=3,4) + \param[out] none + \retval none +*/ +void usart_mute_mode_enable(uint32_t usart_periph) +{ + USART_CTL0(usart_periph) |= USART_CTL0_RWU; +} + +/*! + \brief receiver in active mode + \param[in] usart_periph: USARTx(x=0,1,2)/UARTx(x=3,4) + \param[out] none + \retval none +*/ +void usart_mute_mode_disable(uint32_t usart_periph) +{ + USART_CTL0(usart_periph) &= ~(USART_CTL0_RWU); +} + +/*! + \brief configure wakeup method in mute mode + \param[in] usart_periph: USARTx(x=0,1,2)/UARTx(x=3,4) + \param[in] wmethod: two methods be used to enter or exit the mute mode + only one parameter can be selected which is shown as below: + \arg USART_WM_IDLE: idle line + \arg USART_WM_ADDR: address mask + \param[out] none + \retval none +*/ +void usart_mute_mode_wakeup_config(uint32_t usart_periph, uint32_t wmethod) +{ + USART_CTL0(usart_periph) &= ~(USART_CTL0_WM); + USART_CTL0(usart_periph) |= wmethod; +} + +/*! + \brief enable LIN mode + \param[in] usart_periph: USARTx(x=0,1,2)/UARTx(x=3,4) + \param[out] none + \retval none +*/ +void usart_lin_mode_enable(uint32_t usart_periph) +{ + USART_CTL1(usart_periph) |= USART_CTL1_LMEN; +} + +/*! + \brief disable LIN mode + \param[in] usart_periph: USARTx(x=0,1,2)/UARTx(x=3,4) + \param[out] none + \retval none +*/ +void usart_lin_mode_disable(uint32_t usart_periph) +{ + USART_CTL1(usart_periph) &= ~(USART_CTL1_LMEN); +} + +/*! + \brief configure lin break frame length + \param[in] usart_periph: USARTx(x=0,1,2)/UARTx(x=3,4) + \param[in] lblen: lin break frame length + only one parameter can be selected which is shown as below: + \arg USART_LBLEN_10B: 10 bits + \arg USART_LBLEN_11B: 11 bits + \param[out] none + \retval none +*/ +void usart_lin_break_detection_length_config(uint32_t usart_periph, uint32_t lblen) +{ + USART_CTL1(usart_periph) &= ~(USART_CTL1_LBLEN); + USART_CTL1(usart_periph) |= (USART_CTL1_LBLEN & lblen); +} + +/*! + \brief send break frame + \param[in] usart_periph: USARTx(x=0,1,2)/UARTx(x=3,4) + \param[out] none + \retval none +*/ +void usart_send_break(uint32_t usart_periph) +{ + USART_CTL0(usart_periph) |= USART_CTL0_SBKCMD; +} + +/*! + \brief enable half duplex mode + \param[in] usart_periph: USARTx(x=0,1,2)/UARTx(x=3,4) + \param[out] none + \retval none +*/ +void usart_halfduplex_enable(uint32_t usart_periph) +{ + USART_CTL2(usart_periph) |= USART_CTL2_HDEN; +} + +/*! + \brief disable half duplex mode + \param[in] usart_periph: USARTx(x=0,1,2)/UARTx(x=3,4) + \param[out] none + \retval none +*/ +void usart_halfduplex_disable(uint32_t usart_periph) +{ + USART_CTL2(usart_periph) &= ~(USART_CTL2_HDEN); +} + +/*! + \brief enable CK pin in synchronous mode + \param[in] usart_periph: USARTx(x=0,1,2) + \param[out] none + \retval none +*/ +void usart_synchronous_clock_enable(uint32_t usart_periph) +{ + USART_CTL1(usart_periph) |= USART_CTL1_CKEN; +} + +/*! + \brief disable CK pin in synchronous mode + \param[in] usart_periph: USARTx(x=0,1,2) + \param[out] none + \retval none +*/ +void usart_synchronous_clock_disable(uint32_t usart_periph) +{ + USART_CTL1(usart_periph) &= ~(USART_CTL1_CKEN); +} + +/*! + \brief configure USART synchronous mode parameters + \param[in] usart_periph: USARTx(x=0,1,2) + \param[in] clen: CK length + only one parameter can be selected which is shown as below: + \arg USART_CLEN_NONE: there are 7 CK pulses for an 8 bit frame and 8 CK pulses for a 9 bit frame + \arg USART_CLEN_EN: there are 8 CK pulses for an 8 bit frame and 9 CK pulses for a 9 bit frame + \param[in] cph: clock phase + only one parameter can be selected which is shown as below: + \arg USART_CPH_1CK: first clock transition is the first data capture edge + \arg USART_CPH_2CK: second clock transition is the first data capture edge + \param[in] cpl: clock polarity + only one parameter can be selected which is shown as below: + \arg USART_CPL_LOW: steady low value on CK pin + \arg USART_CPL_HIGH: steady high value on CK pin + \param[out] none + \retval none +*/ +void usart_synchronous_clock_config(uint32_t usart_periph, uint32_t clen, uint32_t cph, uint32_t cpl) +{ + uint32_t ctl = 0U; + + /* read USART_CTL1 register */ + ctl = USART_CTL1(usart_periph); + ctl &= ~(USART_CTL1_CLEN | USART_CTL1_CPH | USART_CTL1_CPL); + /* set CK length, CK phase, CK polarity */ + ctl |= (USART_CTL1_CLEN & clen) | (USART_CTL1_CPH & cph) | (USART_CTL1_CPL & cpl); + + USART_CTL1(usart_periph) = ctl; +} + +/*! + \brief configure guard time value in smartcard mode + \param[in] usart_periph: USARTx(x=0,1,2) + \param[in] gaut: guard time value + \param[out] none + \retval none +*/ +void usart_guard_time_config(uint32_t usart_periph,uint32_t gaut) +{ + USART_GP(usart_periph) &= ~(USART_GP_GUAT); + USART_GP(usart_periph) |= (USART_GP_GUAT & ((gaut)<<8)); +} + +/*! + \brief enable smartcard mode + \param[in] usart_periph: USARTx(x=0,1,2) + \param[out] none + \retval none +*/ +void usart_smartcard_mode_enable(uint32_t usart_periph) +{ + USART_CTL2(usart_periph) |= USART_CTL2_SCEN; +} + +/*! + \brief disable smartcard mode + \param[in] usart_periph: USARTx(x=0,1,2) + \param[out] none + \retval none +*/ +void usart_smartcard_mode_disable(uint32_t usart_periph) +{ + USART_CTL2(usart_periph) &= ~(USART_CTL2_SCEN); +} + +/*! + \brief enable NACK in smartcard mode + \param[in] usart_periph: USARTx(x=0,1,2) + \param[out] none + \retval none +*/ +void usart_smartcard_mode_nack_enable(uint32_t usart_periph) +{ + USART_CTL2(usart_periph) |= USART_CTL2_NKEN; +} + +/*! + \brief disable NACK in smartcard mode + \param[in] usart_periph: USARTx(x=0,1,2) + \param[out] none + \retval none +*/ +void usart_smartcard_mode_nack_disable(uint32_t usart_periph) +{ + USART_CTL2(usart_periph) &= ~(USART_CTL2_NKEN); +} + +/*! + \brief enable IrDA mode + \param[in] usart_periph: USARTx(x=0,1,2)/UARTx(x=3,4) + \param[out] none + \retval none +*/ +void usart_irda_mode_enable(uint32_t usart_periph) +{ + USART_CTL2(usart_periph) |= USART_CTL2_IREN; +} + +/*! + \brief disable IrDA mode + \param[in] usart_periph: USARTx(x=0,1,2)/UARTx(x=3,4) + \param[out] none + \retval none +*/ +void usart_irda_mode_disable(uint32_t usart_periph) +{ + USART_CTL2(usart_periph) &= ~(USART_CTL2_IREN); +} + +/*! + \brief configure the peripheral clock prescaler in USART IrDA low-power mode + \param[in] usart_periph: USARTx(x=0,1,2)/UARTx(x=3,4) + \param[in] psc: 0x00-0xFF + \param[out] none + \retval none +*/ +void usart_prescaler_config(uint32_t usart_periph, uint8_t psc) +{ + USART_GP(usart_periph) &= ~(USART_GP_PSC); + USART_GP(usart_periph) |= psc; +} + +/*! + \brief configure IrDA low-power + \param[in] usart_periph: USARTx(x=0,1,2)/UARTx(x=3,4) + \param[in] irlp: IrDA low-power or normal + only one parameter can be selected which is shown as below: + \arg USART_IRLP_LOW: low-power + \arg USART_IRLP_NORMAL: normal + \param[out] none + \retval none +*/ +void usart_irda_lowpower_config(uint32_t usart_periph, uint32_t irlp) +{ + USART_CTL2(usart_periph) &= ~(USART_CTL2_IRLP); + USART_CTL2(usart_periph) |= (USART_CTL2_IRLP & irlp); +} + +/*! + \brief configure hardware flow control RTS + \param[in] usart_periph: USARTx(x=0,1,2) + \param[in] rtsconfig: enable or disable RTS + only one parameter can be selected which is shown as below: + \arg USART_RTS_ENABLE: enable RTS + \arg USART_RTS_DISABLE: disable RTS + \param[out] none + \retval none +*/ +void usart_hardware_flow_rts_config(uint32_t usart_periph, uint32_t rtsconfig) +{ + uint32_t ctl = 0U; + + ctl = USART_CTL2(usart_periph); + ctl &= ~USART_CTL2_RTSEN; + ctl |= rtsconfig; + /* configure RTS */ + USART_CTL2(usart_periph) = ctl; +} + +/*! + \brief configure hardware flow control CTS + \param[in] usart_periph: USARTx(x=0,1,2) + \param[in] ctsconfig: enable or disable CTS + only one parameter can be selected which is shown as below: + \arg USART_CTS_ENABLE: enable CTS + \arg USART_CTS_DISABLE: disable CTS + \param[out] none + \retval none +*/ +void usart_hardware_flow_cts_config(uint32_t usart_periph, uint32_t ctsconfig) +{ + uint32_t ctl = 0U; + + ctl = USART_CTL2(usart_periph); + ctl &= ~USART_CTL2_CTSEN; + ctl |= ctsconfig; + /* configure CTS */ + USART_CTL2(usart_periph) = ctl; +} + +/*! + \brief configure USART DMA reception + \param[in] usart_periph: USARTx(x=0,1,2)/UARTx(x=3) + \param[in] dmacmd: enable or disable DMA for reception + only one parameter can be selected which is shown as below: + \arg USART_DENR_ENABLE: DMA enable for reception + \arg USART_DENR_DISABLE: DMA disable for reception + \param[out] none + \retval none +*/ +void usart_dma_receive_config(uint32_t usart_periph, uint32_t dmacmd) +{ + uint32_t ctl = 0U; + + ctl = USART_CTL2(usart_periph); + ctl &= ~USART_CTL2_DENR; + ctl |= dmacmd; + /* configure DMA reception */ + USART_CTL2(usart_periph) = ctl; +} + +/*! + \brief configure USART DMA transmission + \param[in] usart_periph: USARTx(x=0,1,2)/UARTx(x=3) + \param[in] dmacmd: enable or disable DMA for transmission + only one parameter can be selected which is shown as below: + \arg USART_DENT_ENABLE: DMA enable for transmission + \arg USART_DENT_DISABLE: DMA disable for transmission + \param[out] none + \retval none +*/ +void usart_dma_transmit_config(uint32_t usart_periph, uint32_t dmacmd) +{ + uint32_t ctl = 0U; + + ctl = USART_CTL2(usart_periph); + ctl &= ~USART_CTL2_DENT; + ctl |= dmacmd; + /* configure DMA transmission */ + USART_CTL2(usart_periph) = ctl; +} + +/*! + \brief get flag in STAT register + \param[in] usart_periph: USARTx(x=0,1,2)/UARTx(x=3,4) + \param[in] flag: USART flags, refer to usart_flag_enum + only one parameter can be selected which is shown as below: + \arg USART_FLAG_CTSF: CTS change flag + \arg USART_FLAG_LBDF: LIN break detected flag + \arg USART_FLAG_TBE: transmit data buffer empty + \arg USART_FLAG_TC: transmission complete + \arg USART_FLAG_RBNE: read data buffer not empty + \arg USART_FLAG_IDLEF: IDLE frame detected flag + \arg USART_FLAG_ORERR: overrun error + \arg USART_FLAG_NERR: noise error flag + \arg USART_FLAG_FERR: frame error flag + \arg USART_FLAG_PERR: parity error flag + \param[out] none + \retval FlagStatus: SET or RESET +*/ +FlagStatus usart_flag_get(uint32_t usart_periph, usart_flag_enum flag) +{ + if(RESET != (USART_REG_VAL(usart_periph, flag) & BIT(USART_BIT_POS(flag)))){ + return SET; + }else{ + return RESET; + } +} + +/*! + \brief clear flag in STAT register + \param[in] usart_periph: USARTx(x=0,1,2)/UARTx(x=3,4) + \param[in] flag: USART flags, refer to usart_flag_enum + only one parameter can be selected which is shown as below: + \arg USART_FLAG_CTSF: CTS change flag + \arg USART_FLAG_LBDF: LIN break detected flag + \arg USART_FLAG_TC: transmission complete + \arg USART_FLAG_RBNE: read data buffer not empty + \param[out] none + \retval none +*/ +void usart_flag_clear(uint32_t usart_periph, usart_flag_enum flag) +{ + USART_REG_VAL(usart_periph, flag) &= ~BIT(USART_BIT_POS(flag)); +} + +/*! + \brief enable USART interrupt + \param[in] usart_periph: USARTx(x=0,1,2)/UARTx(x=3,4) + \param[in] int_flag + only one parameter can be selected which is shown as below: + \arg USART_INT_PERR: parity error interrupt + \arg USART_INT_TBE: transmitter buffer empty interrupt + \arg USART_INT_TC: transmission complete interrupt + \arg USART_INT_RBNE: read data buffer not empty interrupt and overrun error interrupt + \arg USART_INT_IDLE: IDLE line detected interrupt + \arg USART_INT_LBD: LIN break detected interrupt + \arg USART_INT_ERR: error interrupt + \arg USART_INT_CTS: CTS interrupt + \param[out] none + \retval none +*/ +void usart_interrupt_enable(uint32_t usart_periph, uint32_t int_flag) +{ + USART_REG_VAL(usart_periph, int_flag) |= BIT(USART_BIT_POS(int_flag)); +} + +/*! + \brief disable USART interrupt + \param[in] usart_periph: USARTx(x=0,1,2)/UARTx(x=3,4) + \param[in] int_flag + only one parameter can be selected which is shown as below: + \arg USART_INT_PERR: parity error interrupt + \arg USART_INT_TBE: transmitter buffer empty interrupt + \arg USART_INT_TC: transmission complete interrupt + \arg USART_INT_RBNE: read data buffer not empty interrupt and overrun error interrupt + \arg USART_INT_IDLE: IDLE line detected interrupt + \arg USART_INT_LBD: LIN break detected interrupt + \arg USART_INT_ERR: error interrupt + \arg USART_INT_CTS: CTS interrupt + \param[out] none + \retval none +*/ +void usart_interrupt_disable(uint32_t usart_periph, uint32_t int_flag) +{ + USART_REG_VAL(usart_periph, int_flag) &= ~BIT(USART_BIT_POS(int_flag)); +} + +/*! + \brief get USART interrupt and flag status + \param[in] usart_periph: USARTx(x=0,1,2)/UARTx(x=3,4) + \param[in] int_flag + only one parameter can be selected which is shown as below: + \arg USART_INT_FLAG_PERR: parity error interrupt and flag + \arg USART_INT_FLAG_TBE: transmitter buffer empty interrupt and flag + \arg USART_INT_FLAG_TC: transmission complete interrupt and flag + \arg USART_INT_FLAG_RBNE: read data buffer not empty interrupt and flag + \arg USART_INT_FLAG_RBNE_ORERR: read data buffer not empty interrupt and overrun error flag + \arg USART_INT_FLAG_IDLE: IDLE line detected interrupt and flag + \arg USART_INT_FLAG_LBD: LIN break detected interrupt and flag + \arg USART_INT_FLAG_CTS: CTS interrupt and flag + \arg USART_INT_FLAG_ERR_ORERR: error interrupt and overrun error + \arg USART_INT_FLAG_ERR_NERR: error interrupt and noise error flag + \arg USART_INT_FLAG_ERR_FERR: error interrupt and frame error flag + \param[out] none + \retval FlagStatus: SET or RESET +*/ +FlagStatus usart_interrupt_flag_get(uint32_t usart_periph, uint32_t int_flag) +{ + uint32_t intenable = 0U, flagstatus = 0U; + /* get the interrupt enable bit status */ + intenable = (USART_REG_VAL(usart_periph, int_flag) & BIT(USART_BIT_POS(int_flag))); + /* get the corresponding flag bit status */ + flagstatus = (USART_REG_VAL2(usart_periph, int_flag) & BIT(USART_BIT_POS2(int_flag))); + + if(flagstatus && intenable){ + return SET; + }else{ + return RESET; + } +} + +/*! + \brief clear USART interrupt flag in STAT register + \param[in] usart_periph: USARTx(x=0,1,2)/UARTx(x=3,4) + \param[in] flag: USART interrupt flag + only one parameter can be selected which is shown as below: + \arg USART_INT_FLAG_CTS: CTS change flag + \arg USART_INT_FLAG_LBD: LIN break detected flag + \arg USART_INT_FLAG_TC: transmission complete + \arg USART_INT_FLAG_RBNE: read data buffer not empty + \param[out] none + \retval none +*/ +void usart_interrupt_flag_clear(uint32_t usart_periph, uint32_t flag) +{ + USART_REG_VAL2(usart_periph, flag) &= ~BIT(USART_BIT_POS2(flag)); +} diff --git a/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_standard_peripheral/Source/gd32f10x_wwdgt.c b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_standard_peripheral/Source/gd32f10x_wwdgt.c new file mode 100644 index 0000000000..ce9ffc57e7 --- /dev/null +++ b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_standard_peripheral/Source/gd32f10x_wwdgt.c @@ -0,0 +1,149 @@ +/*! + \file gd32f10x_wwdgt.c + \brief WWDGT driver + + \version 2014-12-26, V1.0.0, firmware for GD32F10x + \version 2017-06-20, V2.0.0, firmware for GD32F10x + \version 2018-07-31, V2.1.0, firmware for GD32F10x + \version 2020-09-30, V2.2.0, firmware for GD32F10x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "gd32f10x_wwdgt.h" + +/* write value to WWDGT_CTL_CNT bit field */ +#define CTL_CNT(regval) (BITS(0,6) & ((uint32_t)(regval) << 0)) +/* write value to WWDGT_CFG_WIN bit field */ +#define CFG_WIN(regval) (BITS(0,6) & ((uint32_t)(regval) << 0)) + +/*! + \brief reset the window watchdog timer configuration + \param[in] none + \param[out] none + \retval none +*/ +void wwdgt_deinit(void) +{ + rcu_periph_reset_enable(RCU_WWDGTRST); + rcu_periph_reset_disable(RCU_WWDGTRST); +} + +/*! + \brief start the window watchdog timer counter + \param[in] none + \param[out] none + \retval none +*/ +void wwdgt_enable(void) +{ + WWDGT_CTL |= WWDGT_CTL_WDGTEN; +} + +/*! + \brief configure the window watchdog timer counter value + \param[in] counter_value: 0x00 - 0x7F + \param[out] none + \retval none +*/ +void wwdgt_counter_update(uint16_t counter_value) +{ + uint32_t reg = 0U; + + reg = (WWDGT_CTL & (~WWDGT_CTL_CNT)); + reg |= CTL_CNT(counter_value); + + WWDGT_CTL = reg; +} + +/*! + \brief configure counter value, window value, and prescaler divider value + \param[in] counter: 0x00 - 0x7F + \param[in] window: 0x00 - 0x7F + \param[in] prescaler: wwdgt prescaler value + only one parameter can be selected which is shown as below: + \arg WWDGT_CFG_PSC_DIV1: the time base of window watchdog counter = (PCLK1/4096)/1 + \arg WWDGT_CFG_PSC_DIV2: the time base of window watchdog counter = (PCLK1/4096)/2 + \arg WWDGT_CFG_PSC_DIV4: the time base of window watchdog counter = (PCLK1/4096)/4 + \arg WWDGT_CFG_PSC_DIV8: the time base of window watchdog counter = (PCLK1/4096)/8 + \param[out] none + \retval none +*/ +void wwdgt_config(uint16_t counter, uint16_t window, uint32_t prescaler) +{ + uint32_t reg_cfg = 0U, reg_ctl = 0U; + + /* clear WIN and PSC bits, clear CNT bit */ + reg_cfg = (WWDGT_CFG &(~(WWDGT_CFG_WIN|WWDGT_CFG_PSC))); + reg_ctl = (WWDGT_CTL &(~WWDGT_CTL_CNT)); + + /* configure WIN and PSC bits, configure CNT bit */ + reg_cfg |= CFG_WIN(window); + reg_cfg |= prescaler; + reg_ctl |= CTL_CNT(counter); + + WWDGT_CTL = reg_ctl; + WWDGT_CFG = reg_cfg; +} + +/*! + \brief enable early wakeup interrupt of WWDGT + \param[in] none + \param[out] none + \retval none +*/ +void wwdgt_interrupt_enable(void) +{ + WWDGT_CFG |= WWDGT_CFG_EWIE; +} + +/*! + \brief check early wakeup interrupt state of WWDGT + \param[in] none + \param[out] none + \retval FlagStatus: SET or RESET +*/ +FlagStatus wwdgt_flag_get(void) +{ + if(WWDGT_STAT & WWDGT_STAT_EWIF){ + return SET; + } + + return RESET; +} + +/*! + \brief clear early wakeup interrupt state of WWDGT + \param[in] none + \param[out] none + \retval none +*/ +void wwdgt_flag_clear(void) +{ + WWDGT_STAT &= (~WWDGT_STAT_EWIF); +} diff --git a/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbd_library/class/device/audio/Include/audio_core.h b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbd_library/class/device/audio/Include/audio_core.h new file mode 100644 index 0000000000..d6c1e1d480 --- /dev/null +++ b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbd_library/class/device/audio/Include/audio_core.h @@ -0,0 +1,261 @@ +/*! + \file audio_core.h + \brief the header file of USB audio device class core functions + + \version 2020-07-17, V3.0.0, firmware for GD32F10x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef __AUDIO_CORE_H +#define __AUDIO_CORE_H + +#include "usbd_enum.h" + +#define FORMAT_24BIT(x) (uint8_t)(x);(uint8_t)((x) >> 8);(uint8_t)((x) >> 16) + +/* audio_freq * data_size (2 bytes) * num_channels (stereo: 2) */ +#define DEFAULT_OUT_BIT_RESOLUTION 16U +#define DEFAULT_OUT_CHANNEL_NBR 2U /* mono = 1, stereo = 2 */ +#define AUDIO_OUT_PACKET (uint32_t)(((USBD_AUDIO_FREQ_16K * \ + (DEFAULT_OUT_BIT_RESOLUTION / 8U) *\ + DEFAULT_OUT_CHANNEL_NBR) / 1000U)) + +/* number of sub-packets in the audio transfer buffer. you can modify this value but always make sure + that it is an even number and higher than 3 */ +#define OUT_PACKET_NUM 4U + +/* total size of the audio transfer buffer */ +#define OUT_BUF_MARGIN 4U +#define TOTAL_OUT_BUF_SIZE ((uint32_t)((AUDIO_OUT_PACKET + OUT_BUF_MARGIN) * OUT_PACKET_NUM)) + +#define AUDIO_CONFIG_DESC_SET_LEN 109U +#define AUDIO_INTERFACE_DESC_SIZE 9U + +#define USB_AUDIO_DESC_SIZ 0x09U +#define AUDIO_STANDARD_EP_DESC_SIZE 0x09U +#define AUDIO_STREAMING_EP_DESC_SIZE 0x07U + +/* audio interface class code */ +#define USB_CLASS_AUDIO 0x01U + +/* audio interface subclass codes */ +#define AUDIO_SUBCLASS_CONTROL 0x01U +#define AUDIO_SUBCLASS_AUDIOSTREAMING 0x02U +#define AUDIO_SUBCLASS_MIDISTREAMING 0x03U + +/* audio interface protocol codes */ +#define AUDIO_PROTOCOL_UNDEFINED 0x00U +#define AUDIO_STREAMING_GENERAL 0x01U +#define AUDIO_STREAMING_FORMAT_TYPE 0x02U + +/* audio class-specific descriptor types */ +#define AUDIO_DESCTYPE_UNDEFINED 0x20U +#define AUDIO_DESCTYPE_DEVICE 0x21U +#define AUDIO_DESCTYPE_CONFIGURATION 0x22U +#define AUDIO_DESCTYPE_STRING 0x23U +#define AUDIO_DESCTYPE_INTERFACE 0x24U +#define AUDIO_DESCTYPE_ENDPOINT 0x25U + +/* audio control interface descriptor subtypes */ +#define AUDIO_CONTROL_HEADER 0x01U +#define AUDIO_CONTROL_INPUT_TERMINAL 0x02U +#define AUDIO_CONTROL_OUTPUT_TERMINAL 0x03U +#define AUDIO_CONTROL_MIXER_UNIT 0x04U +#define AUDIO_CONTROL_SELECTOR_UNIT 0x05U +#define AUDIO_CONTROL_FEATURE_UNIT 0x06U +#define AUDIO_CONTROL_PROCESSING_UNIT 0x07U +#define AUDIO_CONTROL_EXTENSION_UNIT 0x08U + +#define AUDIO_INPUT_TERMINAL_DESC_SIZE 0x0CU +#define AUDIO_OUTPUT_TERMINAL_DESC_SIZE 0x09U +#define AUDIO_STREAMING_INTERFACE_DESC_SIZE 0x07U + +#define AUDIO_CONTROL_MUTE 0x0001U + +#define AUDIO_FORMAT_TYPE_I 0x01U +#define AUDIO_FORMAT_TYPE_III 0x03U + +#define USB_ENDPOINT_TYPE_ISOCHRONOUS 0x01U +#define AUDIO_ENDPOINT_GENERAL 0x01U + +#define AUDIO_REQ_GET_CUR 0x81U +#define AUDIO_REQ_SET_CUR 0x01U + +#define AUDIO_OUT_STREAMING_CTRL 0x02U + +#define PACKET_SIZE(freq) (((freq) * 2U) * 2U / 1000U) + +#define AUDIO_PACKET_SIZE(frq) (uint8_t)(PACKET_SIZE(frq) & 0xFFU), \ + (uint8_t)((PACKET_SIZE(frq) >> 8U) & 0xFFU) + +#define SAMPLE_FREQ(frq) (uint8_t)(frq), (uint8_t)((frq) >> 8U), \ + (uint8_t)((frq) >> 16U) + + +#pragma pack(1) + +typedef struct +{ + usb_desc_header header; /*!< descriptor header, including type and size */ + uint8_t bDescriptorSubtype; /*!< header descriptor subtype */ + uint16_t bcdADC; /*!< audio device class specification release number in binary-coded decimal */ + uint16_t wTotalLength; /*!< total number of bytes */ + uint8_t bInCollection; /*!< the number of the streaming interfaces */ + uint8_t baInterfaceNr; /*!< interface number of the streaming interfaces */ +} usb_desc_AC_itf; + +typedef struct +{ + usb_desc_header header; /*!< descriptor header, including type and size */ + uint8_t bDescriptorSubtype; /*!< AS_GENERAL descriptor subtype */ + uint8_t bTerminalLink; /*!< the terminal ID */ + uint8_t bDelay; /*!< delay introduced by the data path */ + uint16_t wFormatTag; /*!< the audio data format */ +} usb_desc_AS_itf; + +typedef struct +{ + usb_desc_header header; /*!< descriptor header, including type and size */ + uint8_t bDescriptorSubtype; /*!< INPUT_TERMINAL descriptor subtype. */ + uint8_t bTerminalID; /*!< constant uniquely identifying the terminal within the audio function */ + uint16_t wTerminalType; /*!< constant characterizing the type of terminal */ + uint8_t bAssocTerminal; /*!< ID of the output terminal */ + uint8_t bNrChannels; /*!< number of logical output channels */ + uint16_t wChannelConfig; /*!< describes the spatial location of the logical channels */ + uint8_t iChannelNames; /*!< index of a string descriptor */ + uint8_t iTerminal; /*!< index of a string descriptor */ +} usb_desc_input_terminal; + +typedef struct +{ + usb_desc_header header; /*!< descriptor header, including type and size */ + uint8_t bDescriptorSubtype; /*!< OUTPUT_TERMINAL descriptor subtype */ + uint8_t bTerminalID; /*!< constant uniquely identifying the terminal within the audio function */ + uint16_t wTerminalType; /*!< constant characterizing the type of terminal */ + uint8_t bAssocTerminal; /*!< constant, identifying the input terminal to which this output terminal is associated */ + uint8_t bSourceID; /*!< ID of the unit or terminal */ + uint8_t iTerminal; /*!< index of a string descriptor */ +} usb_desc_output_terminal; + +typedef struct +{ + usb_desc_header header; /*!< descriptor header, including type and size */ + uint8_t bDescriptorSubtype; /*!< FEATURE_UNIT descriptor subtype */ + uint8_t bUnitID; /*!< constant uniquely identifying the unit within the audio function */ + uint8_t bSourceID; /*!< ID of the unit or terminal */ + uint8_t bControlSize; /*!< size in bytes of an element of the bmaControls() array */ + uint8_t bmaControls0; /*!< a bit set to 1 indicates that the mentioned control is supported for master channel 0 */ + uint8_t bmaControls1; /*!< a bit set to 1 indicates that the mentioned control is supported for logical channel 1 */ + uint8_t iFeature; /*!< index of a string descriptor */ +} usb_desc_mono_feature_unit; + +typedef struct +{ + usb_desc_header header; /*!< descriptor header, including type and size */ + uint8_t bDescriptorSubtype; /*!< FEATURE_UNIT descriptor subtype */ + uint8_t bUnitID; /*!< constant uniquely identifying the unit within the audio function */ + uint8_t bSourceID; /*!< ID of the unit or terminal */ + uint8_t bControlSize; /*!< size in bytes of an element of the bmaControls() array */ + uint16_t bmaControls0; /*!< a bit set to 1 indicates that the mentioned control is supported for master channel 0 */ + uint16_t bmaControls1; /*!< a bit set to 1 indicates that the mentioned control is supported for logical channel 1 */ + uint16_t bmaControls2; /*!< a bit set to 1 indicates that the mentioned control is supported for logical channel 2 */ + uint8_t iFeature; /*!< index of a string descriptor */ +} usb_desc_stereo_feature_unit; + +typedef struct +{ + usb_desc_header header; /*!< descriptor header, including type and size */ + uint8_t bDescriptorSubtype; /*!< FORMAT_TYPE descriptor subtype */ + uint8_t bFormatType; /*!< constant identifying the format type */ + uint8_t bNrChannels; /*!< indicates the number of physical channels in the audio data stream */ + uint8_t bSubFrameSize; /*!< the number of bytes occupied by one audio sub frame */ + uint8_t bBitResolution; /*!< the number of effectively used bits from the available bits in an audio sub frame */ + uint8_t bSamFreqType; /*!< indicates how the sampling frequency can be programmed */ + uint8_t bSamFreq[3]; /*!< sampling frequency ns in Hz for this isochronous data endpoint */ +} usb_desc_format_type; + +typedef struct +{ + usb_desc_header header; /*!< descriptor header, including type and size */ + uint8_t bEndpointAddress; /*!< the address of the endpoint */ + uint8_t bmAttributes; /*!< transfer type and synchronization type */ + uint16_t wMaxPacketSize; /*!< maximum packet size this endpoint is capable of sending or receiving */ + uint8_t bInterval; /*!< left to the designer's discretion */ + uint8_t bRefresh; /*!< reset to 0 */ + uint8_t bSynchAddress; /*!< reset to 0 */ +} usb_desc_std_ep; + +typedef struct +{ + usb_desc_header header; /*!< descriptor header, including type and size */ + uint8_t bDescriptorSubtype; /*!< EP_GENERAL descriptor subtype */ + uint8_t bmAttributes; /*!< transfer type and synchronization type */ + uint8_t bLockDelayUnits; /*!< indicates the units used for the wLockDelay field */ + uint16_t wLockDelay; /*!< indicates the time it takes this endpoint to reliably lock its internal clock recovery circuitry */ +} usb_desc_AS_ep; + +#pragma pack() + +/* USB configuration descriptor structure */ +typedef struct +{ + usb_desc_config config; + usb_desc_itf std_itf; + usb_desc_AC_itf ac_itf; + usb_desc_input_terminal in_terminal; + usb_desc_mono_feature_unit feature_unit; + usb_desc_output_terminal out_terminal; + usb_desc_itf std_as_itf_zeroband; + usb_desc_itf std_as_itf_opera; + usb_desc_AS_itf as_itf; + usb_desc_format_type format_typeI; + usb_desc_std_ep std_endpoint; + usb_desc_AS_ep as_endpoint; +} usb_desc_config_set; + +typedef struct +{ + /* main buffer for audio data out transfers and its relative pointers */ + uint8_t isoc_out_buff[TOTAL_OUT_BUF_SIZE * 2U]; + uint8_t* isoc_out_wrptr; + uint8_t* isoc_out_rdptr; + + /* main buffer for audio control requests transfers and its relative variables */ + uint8_t audioctl[64]; + uint8_t audioctl_unit; + uint32_t audioctl_len; + + uint32_t play_flag; +} usbd_audio_handler; + +extern usb_desc audio_desc; +extern usb_class audio_class; + +#endif /* __AUDIO_CORE_H */ + diff --git a/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbd_library/class/device/audio/Include/audio_out_itf.h b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbd_library/class/device/audio/Include/audio_out_itf.h new file mode 100644 index 0000000000..6951044bd4 --- /dev/null +++ b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbd_library/class/device/audio/Include/audio_out_itf.h @@ -0,0 +1,76 @@ +/*! + \file audio_out_itf.h + \brief audio OUT (playback) interface header file + + \version 2020-07-17, V3.0.0, firmware for GD32F10x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef __AUDIO_OUT_ITF_H +#define __AUDIO_OUT_ITF_H + +#include "usbd_conf.h" + +/* audio commands enumeration */ +typedef enum +{ + AUDIO_CMD_PLAY = 1U, + AUDIO_CMD_PAUSE, + AUDIO_CMD_STOP, +}audio_cmd_enum; + +/* mute commands */ +#define AUDIO_MUTE 0x01U +#define AUDIO_UNMUTE 0x00U + +/* functions return value */ +#define AUDIO_OK 0x00U +#define AUDIO_FAIL 0xFFU + +/* audio machine states */ +#define AUDIO_STATE_INACTIVE 0x00U +#define AUDIO_STATE_ACTIVE 0x01U +#define AUDIO_STATE_PLAYING 0x02U +#define AUDIO_STATE_PAUSED 0x03U +#define AUDIO_STATE_STOPPED 0x04U +#define AUDIO_STATE_ERROR 0x05U + +typedef struct { + uint8_t (*audio_init) (uint32_t audio_freq, uint32_t volume, uint32_t options); + uint8_t (*audio_deinit) (uint32_t options); + uint8_t (*audio_cmd) (uint8_t* pbuf, uint32_t size, uint8_t cmd); + uint8_t (*audio_volume_ctl) (uint8_t vol); + uint8_t (*audio_mute_ctl) (uint8_t cmd); + uint8_t (*audio_periodic_tc) (uint8_t cmd); + uint8_t (*audio_state_get) (void); +} audio_fops_struct; + +extern audio_fops_struct audio_out_fops; + +#endif /* __AUDIO_OUT_ITF_H */ diff --git a/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbd_library/class/device/audio/Source/audio_core.c b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbd_library/class/device/audio/Source/audio_core.c new file mode 100644 index 0000000000..dd474b151f --- /dev/null +++ b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbd_library/class/device/audio/Source/audio_core.c @@ -0,0 +1,549 @@ +/*! + \file audio_core.c + \brief USB audio device class core functions + + \version 2020-07-17, V3.0.0, firmware for GD32F10x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "usbd_transc.h" +#include "audio_out_itf.h" +#include "audio_core.h" + +#include + +#define USBD_VID 0x28E9U +#define USBD_PID 0x9574U + +/* local function prototypes ('static') */ +static uint8_t usbd_audio_sof (usb_dev *udev); +static uint8_t audio_init (usb_dev *udev, uint8_t config_index); +static uint8_t audio_deinit (usb_dev *udev, uint8_t config_index); +static uint8_t audio_req_handler (usb_dev *udev, usb_req *req); +static uint8_t audio_ctlx_out (usb_dev *udev); +static void audio_data_out (usb_dev *udev, uint8_t ep_num); + +usb_class audio_class = { + .init = audio_init, + .deinit = audio_deinit, + .req_process = audio_req_handler, + .ctlx_out = audio_ctlx_out, + .data_out = audio_data_out +}; + +usbd_int_cb_struct usb_inthandler = +{ + usbd_audio_sof, +}; + +/* note:it should use the c99 standard when compiling the below codes */ +/* USB standard device descriptor */ +usb_desc_dev audio_dev_desc = +{ + .header = + { + .bLength = USB_DEV_DESC_LEN, + .bDescriptorType = USB_DESCTYPE_DEV + }, + .bcdUSB = 0x0200U, + .bDeviceClass = 0x00U, + .bDeviceSubClass = 0x00U, + .bDeviceProtocol = 0x00U, + .bMaxPacketSize0 = USBD_EP0_MAX_SIZE, + .idVendor = USBD_VID, + .idProduct = USBD_PID, + .bcdDevice = 0x0100U, + .iManufacturer = STR_IDX_MFC, + .iProduct = STR_IDX_PRODUCT, + .iSerialNumber = STR_IDX_SERIAL, + .bNumberConfigurations = USBD_CFG_MAX_NUM +}; + +/* USB device configuration descriptor */ +usb_desc_config_set audio_config_set = +{ + .config = + { + .header = + { + .bLength = sizeof(usb_desc_config), + .bDescriptorType = USB_DESCTYPE_CONFIG + }, + .wTotalLength = AUDIO_CONFIG_DESC_SET_LEN, + .bNumInterfaces = 0x02U, + .bConfigurationValue = 0x01U, + .iConfiguration = 0x00U, + .bmAttributes = 0xC0U, + .bMaxPower = 0x32U + }, + + .std_itf = + { + .header = + { + .bLength = sizeof(usb_desc_itf), + .bDescriptorType = USB_DESCTYPE_ITF + }, + .bInterfaceNumber = 0x00U, + .bAlternateSetting = 0x00U, + .bNumEndpoints = 0x00U, + .bInterfaceClass = USB_CLASS_AUDIO, + .bInterfaceSubClass = AUDIO_SUBCLASS_CONTROL, + .bInterfaceProtocol = AUDIO_PROTOCOL_UNDEFINED, + .iInterface = 0x00U + }, + + .ac_itf = + { + .header = + { + .bLength = sizeof(usb_desc_AC_itf), + .bDescriptorType = AUDIO_DESCTYPE_INTERFACE + }, + .bDescriptorSubtype = 0x01U, + .bcdADC = 0x0100U, + .wTotalLength = 0x0027U, + .bInCollection = 0x01U, + .baInterfaceNr = 0x01U + }, + + .in_terminal = + { + .header = + { + .bLength = sizeof(usb_desc_input_terminal), + .bDescriptorType = AUDIO_DESCTYPE_INTERFACE + }, + .bDescriptorSubtype = 0x02U, + .bTerminalID = 0x01U, + .wTerminalType = 0x0101U, + .bAssocTerminal = 0x00U, + .bNrChannels = 0x01U, + .wChannelConfig = 0x0000U, + .iChannelNames = 0x00U, + .iTerminal = 0x00U + }, + + .feature_unit = + { + .header = + { + .bLength = sizeof(usb_desc_mono_feature_unit), + .bDescriptorType = AUDIO_DESCTYPE_INTERFACE + }, + .bDescriptorSubtype = AUDIO_CONTROL_FEATURE_UNIT, + .bUnitID = AUDIO_OUT_STREAMING_CTRL, + .bSourceID = 0x01U, + .bControlSize = 0x01U, + .bmaControls0 = AUDIO_CONTROL_MUTE, + .bmaControls1 = 0x00U, + .iFeature = 0x00U + }, + + .out_terminal = + { + .header = + { + .bLength = sizeof(usb_desc_output_terminal), + .bDescriptorType = AUDIO_DESCTYPE_INTERFACE + }, + .bDescriptorSubtype = AUDIO_CONTROL_OUTPUT_TERMINAL, + .bTerminalID = 0x03U, + .wTerminalType = 0x0301U, + .bAssocTerminal = 0x00U, + .bSourceID = 0x02U, + .iTerminal = 0x00U + }, + + .std_as_itf_zeroband = + { + .header = + { + .bLength = sizeof(usb_desc_itf), + .bDescriptorType = USB_DESCTYPE_ITF + }, + .bInterfaceNumber = 0x01U, + .bAlternateSetting = 0x00U, + .bNumEndpoints = 0x00U, + .bInterfaceClass = USB_CLASS_AUDIO, + .bInterfaceSubClass = AUDIO_SUBCLASS_AUDIOSTREAMING, + .bInterfaceProtocol = AUDIO_PROTOCOL_UNDEFINED, + .iInterface = 0x00U + }, + + .std_as_itf_opera = + { + .header = + { + .bLength = sizeof(usb_desc_itf), + .bDescriptorType = USB_DESCTYPE_ITF + }, + .bInterfaceNumber = 0x01U, + .bAlternateSetting = 0x01U, + .bNumEndpoints = 0x01U, + .bInterfaceClass = USB_CLASS_AUDIO, + .bInterfaceSubClass = AUDIO_SUBCLASS_AUDIOSTREAMING, + .bInterfaceProtocol = AUDIO_PROTOCOL_UNDEFINED, + .iInterface = 0x00U + }, + + .as_itf = + { + .header = + { + .bLength = sizeof(usb_desc_AS_itf), + .bDescriptorType = AUDIO_DESCTYPE_INTERFACE + }, + .bDescriptorSubtype = AUDIO_STREAMING_GENERAL, + .bTerminalLink = 0x01U, + .bDelay = 0x01U, + .wFormatTag = 0x0001U, + }, + + .format_typeI = + { + .header = + { + .bLength = sizeof(usb_desc_format_type), + .bDescriptorType = AUDIO_DESCTYPE_INTERFACE + }, + .bDescriptorSubtype = AUDIO_STREAMING_FORMAT_TYPE, + .bFormatType = AUDIO_FORMAT_TYPE_III, + .bNrChannels = 0x02U, + .bSubFrameSize = 0x02U, + .bBitResolution = 0x10U, + .bSamFreqType = 0x01U, + .bSamFreq[0] = (uint8_t)USBD_AUDIO_FREQ_16K, + .bSamFreq[1] = USBD_AUDIO_FREQ_16K >> 8, + .bSamFreq[2] = USBD_AUDIO_FREQ_16K >> 16 + }, + + .std_endpoint = + { + .header = + { + .bLength = sizeof(usb_desc_std_ep), + .bDescriptorType = USB_DESCTYPE_EP + }, + .bEndpointAddress = AUDIO_OUT_EP, + .bmAttributes = USB_ENDPOINT_TYPE_ISOCHRONOUS, + .wMaxPacketSize = PACKET_SIZE(USBD_AUDIO_FREQ_16K), + .bInterval = 0x01U, + .bRefresh = 0x00U, + .bSynchAddress = 0x00U + }, + + .as_endpoint = + { + .header = + { + .bLength = sizeof(usb_desc_AS_ep), + .bDescriptorType = AUDIO_DESCTYPE_ENDPOINT + }, + .bDescriptorSubtype = AUDIO_ENDPOINT_GENERAL, + .bmAttributes = 0x00U, + .bLockDelayUnits = 0x00U, + .wLockDelay = 0x0000U, + } +}; + +/* USB language ID descriptor */ +static usb_desc_LANGID usbd_language_id_desc = +{ + .header = + { + .bLength = sizeof(usb_desc_LANGID), + .bDescriptorType = USB_DESCTYPE_STR + }, + + .wLANGID = ENG_LANGID +}; + +/* USB manufacture string */ +static usb_desc_str manufacturer_string = +{ + .header = + { + .bLength = USB_STRING_LEN(10U), + .bDescriptorType = USB_DESCTYPE_STR, + }, + .unicode_string = {'G', 'i', 'g', 'a', 'D', 'e', 'v', 'i', 'c', 'e'} +}; + +/* USB product string */ +static usb_desc_str product_string = +{ + .header = + { + .bLength = USB_STRING_LEN(14U), + .bDescriptorType = USB_DESCTYPE_STR, + }, + .unicode_string = {'G', 'D', '3', '2', '-', 'U', 'S', 'B', '_', 'A', 'u', 'd', 'i', 'o'} +}; + +/* USBD serial string */ +static usb_desc_str serial_string = +{ + .header = + { + .bLength = USB_STRING_LEN(12U), + .bDescriptorType = USB_DESCTYPE_STR, + } +}; + +/* USB string descriptor */ +static uint8_t* usbd_audio_strings[] = +{ + [STR_IDX_LANGID] = (uint8_t *)&usbd_language_id_desc, + [STR_IDX_MFC] = (uint8_t *)&manufacturer_string, + [STR_IDX_PRODUCT] = (uint8_t *)&product_string, + [STR_IDX_SERIAL] = (uint8_t *)&serial_string +}; + +usb_desc audio_desc = { + .dev_desc = (uint8_t *)&audio_dev_desc, + .config_desc = (uint8_t *)&audio_config_set, + .strings = usbd_audio_strings +}; + +/*! + \brief initialize the audio device + \param[in] udev: pointer to USB device instance + \param[in] config_index: configuration index + \param[out] none + \retval USB device operation status +*/ +static uint8_t audio_init (usb_dev *udev, uint8_t config_index) +{ + usb_desc_std_ep std_ep = audio_config_set.std_endpoint; + + static usbd_audio_handler audio_handler; + + memset((void *)&audio_handler, 0, sizeof(usbd_audio_handler)); + + usb_desc_ep ep = { + .header = std_ep.header, + .bEndpointAddress = std_ep.bEndpointAddress, + .bmAttributes = std_ep.bmAttributes, + .wMaxPacketSize = std_ep.wMaxPacketSize, + .bInterval = std_ep.bInterval + }; + + /* initialize RX endpoint */ + usbd_ep_init(udev, EP_BUF_DBL, AUDIO_BUF_ADDR, &ep); + + usbd_int_fops = &usb_inthandler; + + audio_handler.isoc_out_rdptr = audio_handler.isoc_out_buff; + audio_handler.isoc_out_wrptr = audio_handler.isoc_out_buff; + + /* initialize the audio output hardware layer */ + if (USBD_OK != audio_out_fops.audio_init(USBD_AUDIO_FREQ_16K, DEFAULT_VOLUME, 0U)) { + return USBD_FAIL; + } + + udev->ep_transc[AUDIO_OUT_EP][TRANSC_OUT] = audio_class.data_out; + + /* prepare out endpoint to receive audio data */ + usbd_ep_recev (udev, AUDIO_OUT_EP, (uint8_t*)audio_handler.isoc_out_buff, (uint16_t)AUDIO_OUT_PACKET); + + udev->class_data[USBD_AUDIO_INTERFACE] = (void *)&audio_handler; + + return USBD_OK; +} + +/*! + \brief de-initialize the audio device + \param[in] udev: pointer to USB device instance + \param[in] config_index: configuration index + \param[out] none + \retval USB device operation status +*/ +static uint8_t audio_deinit (usb_dev *udev, uint8_t config_index) +{ + /* deinitialize audio endpoints */ + usbd_ep_deinit(udev, AUDIO_OUT_EP); + + /* deinitialize the audio output hardware layer */ + if (USBD_OK != audio_out_fops.audio_deinit(0U)) { + return USBD_FAIL; + } + + return USBD_OK; +} + +/*! + \brief handle the audio class-specific requests + \param[in] udev: pointer to USB device instance + \param[in] req: device class-specific request + \param[out] none + \retval USB device operation status +*/ +static uint8_t audio_req_handler (usb_dev *udev, usb_req *req) +{ + uint8_t status = REQ_NOTSUPP; + + usbd_audio_handler *audio = (usbd_audio_handler *)udev->class_data[USBD_AUDIO_INTERFACE]; + + switch (req->bRequest) { + case AUDIO_REQ_GET_CUR: + usb_transc_config(&udev->transc_in[0], audio->audioctl, req->wLength, 0U); + + status = REQ_SUPP; + break; + + case AUDIO_REQ_SET_CUR: + if (req->wLength) { + usb_transc_config(&udev->transc_out[0], audio->audioctl, req->wLength, 0U); + + udev->class_core->req_cmd = AUDIO_REQ_SET_CUR; + + audio->audioctl_len = req->wLength; + audio->audioctl_unit = BYTE_HIGH(req->wIndex); + + status = REQ_SUPP; + } + break; + + default: + break; + } + + return status; +} + +/*! + \brief handles the audio out data stage + \param[in] udev: pointer to USB device instance + \param[in] ep_num: endpoint number + \param[out] none + \retval USB device operation status +*/ +static void audio_data_out (usb_dev *udev, uint8_t ep_num) +{ + usbd_audio_handler *audio = (usbd_audio_handler *)udev->class_data[USBD_AUDIO_INTERFACE]; + + if (AUDIO_OUT_EP == ep_num) { + /* increment the Buffer pointer or roll it back when all buffers are full */ + if (audio->isoc_out_wrptr >= (audio->isoc_out_buff + (AUDIO_OUT_PACKET * OUT_PACKET_NUM))) { + /* all buffers are full: roll back */ + audio->isoc_out_wrptr = audio->isoc_out_buff; + } else { + /* increment the buffer pointer */ + audio->isoc_out_wrptr += AUDIO_OUT_PACKET; + } + + /* prepare out endpoint to receive next audio packet */ + usbd_ep_recev (udev, AUDIO_OUT_EP, (uint8_t*)(audio->isoc_out_wrptr), (uint16_t)AUDIO_OUT_PACKET); + + /* trigger the start of streaming only when half buffer is full */ + if ((0U == audio->play_flag) && (audio->isoc_out_wrptr >= (audio->isoc_out_buff + ((AUDIO_OUT_PACKET * OUT_PACKET_NUM) / 2U)))) { + /* enable start of streaming */ + audio->play_flag = 1U; + } + } +} + +/*! + \brief handles audio control request data + \param[in] udev: pointer to USB device instance + \param[out] none + \retval USB device operation status +*/ +static uint8_t audio_ctlx_out (usb_dev *udev) +{ + usbd_audio_handler *audio = (usbd_audio_handler *)udev->class_data[USBD_AUDIO_INTERFACE]; + + /* check if an audio_control request has been issued */ + if (AUDIO_REQ_SET_CUR == udev->class_core->req_cmd) { + /* in this driver, to simplify code, only SET_CUR request is managed */ + + /* check for which addressed unit the audio_control request has been issued */ + if (AUDIO_OUT_STREAMING_CTRL == audio->audioctl_unit) { + /* in this driver, to simplify code, only one unit is manage */ + + /* call the audio interface mute function */ + audio_out_fops.audio_mute_ctl(audio->audioctl[0]); + + /* reset the audioctl_cmd variable to prevent re-entering this function */ + udev->class_core->req_cmd = 0U; + + audio->audioctl_len = 0U; + } + } + + return USBD_OK; +} + +/*! + \brief handles the SOF event (data buffer update and synchronization) + \param[in] udev: pointer to USB device instance + \param[out] none + \retval USB device operation status +*/ +static uint8_t usbd_audio_sof (usb_dev *udev) +{ + usbd_audio_handler *audio = (usbd_audio_handler *)udev->class_data[USBD_AUDIO_INTERFACE]; + + /* check if there are available data in stream buffer. + in this function, a single variable (play_flag) is used to avoid software delays. + the play operation must be executed as soon as possible after the SOF detection. */ + if (audio->play_flag) { + /* start playing received packet */ + audio_out_fops.audio_cmd((uint8_t*)(audio->isoc_out_rdptr), /* samples buffer pointer */ + AUDIO_OUT_PACKET, /* number of samples in Bytes */ + AUDIO_CMD_PLAY); /* command to be processed */ + + /* increment the Buffer pointer or roll it back when all buffers all full */ + if (audio->isoc_out_rdptr >= (audio->isoc_out_buff + (AUDIO_OUT_PACKET * OUT_PACKET_NUM))) { + /* roll back to the start of buffer */ + audio->isoc_out_rdptr = audio->isoc_out_buff; + } else { + /* increment to the next sub-buffer */ + audio->isoc_out_rdptr += AUDIO_OUT_PACKET; + } + + /* if all available buffers have been consumed, stop playing */ + if (audio->isoc_out_rdptr == audio->isoc_out_wrptr) { + /* pause the audio stream */ + audio_out_fops.audio_cmd((uint8_t*)(audio->isoc_out_buff), /* samples buffer pointer */ + AUDIO_OUT_PACKET, /* number of samples in Bytes */ + AUDIO_CMD_PAUSE); /* command to be processed */ + + /* stop entering play loop */ + audio->play_flag = 0U; + + /* reset buffer pointers */ + audio->isoc_out_rdptr = audio->isoc_out_buff; + audio->isoc_out_wrptr = audio->isoc_out_buff; + } + } + + return USBD_OK; +} diff --git a/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbd_library/class/device/audio/Source/audio_out_itf.c b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbd_library/class/device/audio/Source/audio_out_itf.c new file mode 100644 index 0000000000..90d7709694 --- /dev/null +++ b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbd_library/class/device/audio/Source/audio_out_itf.c @@ -0,0 +1,242 @@ +/*! + \file audio_out_itf.c + \brief audio OUT (playback) interface functions + + \version 2020-07-17, V3.0.0, firmware for GD32F10x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "audio_core.h" +#include "audio_out_itf.h" + +/* local function prototypes ('static') */ +static uint8_t init (uint32_t audio_freq, uint32_t volume, uint32_t options); +static uint8_t deinit (uint32_t options); +static uint8_t audio_cmd (uint8_t* pbuf, uint32_t size, uint8_t cmd); +static uint8_t volume_ctl (uint8_t vol); +static uint8_t mute_ctl (uint8_t cmd); +static uint8_t periodic_tc (uint8_t cmd); +static uint8_t get_state (void); + +audio_fops_struct audio_out_fops = +{ + init, + deinit, + audio_cmd, + volume_ctl, + mute_ctl, + periodic_tc, + get_state +}; + +static uint8_t audio_state = AUDIO_STATE_INACTIVE; + +/*! + \brief initialize and configures all required resources for audio play function + \param[in] audio_freq: statrt_up audio frequency + \param[in] volume: start_up volume to be set + \param[in] options: specific options passed to low layer function + \param[out] none + \retval AUDIO_OK if all operations succeed, otherwise, AUDIO_FAIL. +*/ +static uint8_t init (uint32_t audio_freq, uint32_t volume, uint32_t options) +{ + static uint32_t initialized = 0U; + + /* check if the low layer has already been initialized */ + if (0U == initialized) { + /* call low layer function */ + if (0U != eval_audio_init(OUTPUT_DEVICE_AUTO, volume, audio_freq)) { + audio_state = AUDIO_STATE_ERROR; + + return AUDIO_FAIL; + } + + /* set the initialization flag to prevent reinitializing the interface again */ + initialized = 1U; + } + + /* update the audio state machine */ + audio_state = AUDIO_STATE_ACTIVE; + + return AUDIO_OK; +} + +/*! + \brief free all resources used by low layer and stops audio-play function + \param[in] options: specific options passed to low layer function + \param[out] none + \retval AUDIO_OK if all operations succeed, otherwise, AUDIO_FAIL. +*/ +static uint8_t deinit (uint32_t options) +{ + /* update the audio state machine */ + audio_state = AUDIO_STATE_INACTIVE; + + return AUDIO_OK; +} + +/*! + \brief play, stop, pause or resume current file + \param[in] pbuf: address from which file should be played + \param[in] size: size of the current buffer/file + \param[in] cmd: command to be executed, can be: + \arg AUDIO_CMD_PLAY + \arg AUDIO_CMD_PAUSE + \arg AUDIO_CMD_RESUME + \arg AUDIO_CMD_STOP + \param[out] none + \retval AUDIO_OK if all operations succeed, otherwise, AUDIO_FAIL. +*/ +static uint8_t audio_cmd (uint8_t* pbuf, uint32_t size, uint8_t cmd) +{ + uint8_t status = AUDIO_OK; + + /* check the current state */ + if ((AUDIO_STATE_INACTIVE == audio_state) || (AUDIO_STATE_ERROR == audio_state)) { + audio_state = AUDIO_STATE_ERROR; + + return AUDIO_FAIL; + } + + switch (cmd) { + /* process the play command */ + case AUDIO_CMD_PLAY: + /* if current state is active or stopped */ + if ((AUDIO_STATE_ACTIVE == audio_state) || \ + (AUDIO_STATE_STOPPED == audio_state) || \ + (AUDIO_STATE_PLAYING == audio_state)) { + audio_mal_play((uint32_t)pbuf, (size / 2U)); + audio_state = AUDIO_STATE_PLAYING; + } else if (AUDIO_STATE_PAUSED == audio_state) { + if (eval_audio_pause_resume(AUDIO_RESUME, (uint32_t)pbuf, (size / 2U))) { + audio_state = AUDIO_STATE_ERROR; + + status = AUDIO_FAIL; + } else { + audio_state = AUDIO_STATE_PLAYING; + } + } else { + status = AUDIO_FAIL; + } + break; + + /* process the stop command */ + case AUDIO_CMD_STOP: + if (AUDIO_STATE_PLAYING != audio_state) { + /* unsupported command */ + status = AUDIO_FAIL; + } else if (eval_audio_stop(CODEC_PDWN_SW)) { + audio_state = AUDIO_STATE_ERROR; + + status = AUDIO_FAIL; + } else { + audio_state = AUDIO_STATE_STOPPED; + } + break; + + /* process the pause command */ + case AUDIO_CMD_PAUSE: + if (AUDIO_STATE_PLAYING != audio_state) { + /* unsupported command */ + status = AUDIO_FAIL; + } else if (eval_audio_pause_resume(AUDIO_PAUSE, (uint32_t)pbuf, (size / 2U))) { + audio_state = AUDIO_STATE_ERROR; + + status = AUDIO_FAIL; + } else { + audio_state = AUDIO_STATE_PAUSED; + } + break; + + /* unsupported command */ + default: + break; + } + + return status; +} + +/*! + \brief set the volume level + \param[in] vol: volume level to be set in % (from 0% to 100%) + \param[out] none + \retval AUDIO_OK if all operations succeed, otherwise, AUDIO_FAIL. +*/ +static uint8_t volume_ctl (uint8_t vol) +{ + /* call low layer volume setting function */ + if (eval_audio_volume_ctl(vol)) { + audio_state = AUDIO_STATE_ERROR; + + return AUDIO_FAIL; + } + + return AUDIO_OK; +} + +/*! + \brief mute or unmute the audio current output + \param[in] cmd: can be 0 to unmute, or 1 to mute + \param[out] none + \retval AUDIO_OK if all operations succeed, otherwise, AUDIO_FAIL. +*/ +static uint8_t mute_ctl (uint8_t cmd) +{ + /* call low layer mute setting function */ + if (eval_audio_mute((uint32_t)cmd)) { + audio_state = AUDIO_STATE_ERROR; + + return AUDIO_FAIL; + } + + return AUDIO_OK; +} + +/*! + \brief periodic transfer control + \param[in] cmd: command + \param[out] none + \retval AUDIO_OK if all operations succeed, otherwise, AUDIO_FAIL. +*/ +static uint8_t periodic_tc (uint8_t cmd) +{ + return AUDIO_OK; +} + +/*! + \brief return the current state of the audio machine + \param[in] none + \param[out] none + \retval AUDIO_OK if all operations succeed, otherwise, AUDIO_FAIL. +*/ +static uint8_t get_state (void) +{ + return audio_state; +} diff --git a/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbd_library/class/device/cdc/Include/cdc_acm_core.h b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbd_library/class/device/cdc/Include/cdc_acm_core.h new file mode 100644 index 0000000000..9f134ec7b4 --- /dev/null +++ b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbd_library/class/device/cdc/Include/cdc_acm_core.h @@ -0,0 +1,164 @@ +/*! + \file cdc_acm_core.h + \brief the header file of CDC ACM driver + + \version 2020-07-17, V3.0.0, firmware for GD32F10x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef __CDC_ACM_CORE_H +#define __CDC_ACM_CORE_H + +#include "usbd_enum.h" + +/* communications device class code */ +#define USB_CLASS_CDC 0x02U + +/* CDC subclass code */ +#define USB_CDC_SUBCLASS_DLCM 0x01U +#define USB_CDC_SUBCLASS_ACM 0x02U + +/* communications interface class control protocol codes */ +#define USB_CDC_PROTOCOL_NONE 0x00U +#define USB_CDC_PROTOCOL_AT 0x01U + +/* data interface class code */ +#define USB_CLASS_DATA 0x0AU + +#define USB_DESCTYPE_CDC_ACM 0x21U +#define USB_DESCTYPE_CS_INTERFACE 0x24U + +#define USB_CDC_ACM_CONFIG_DESC_SIZE 0x43U + +/* class-specific notification codes for PSTN subclasses */ +#define USB_CDC_NOTIFY_SERIAL_STATE 0x20U + +/* class-specific request codes */ +#define SEND_ENCAPSULATED_COMMAND 0x00U +#define GET_ENCAPSULATED_RESPONSE 0x01U +#define SET_COMM_FEATURE 0x02U +#define GET_COMM_FEATURE 0x03U +#define CLEAR_COMM_FEATURE 0x04U +#define SET_LINE_CODING 0x20U +#define GET_LINE_CODING 0x21U +#define SET_CONTROL_LINE_STATE 0x22U +#define SEND_BREAK 0x23U +#define NO_CMD 0xFFU + +#pragma pack(1) + +/* CDC ACM line coding structure */ +typedef struct { + uint32_t dwDTERate; /*!< data terminal rate */ + uint8_t bCharFormat; /*!< stop bits */ + uint8_t bParityType; /*!< parity */ + uint8_t bDataBits; /*!< data bits */ +} acm_line; + +/* notification structure */ +typedef struct { + uint8_t bmRequestType; /*!< type of request */ + uint8_t bNotification; /*!< communication interface class notifications */ + uint16_t wValue; /*!< value of notification */ + uint16_t wIndex; /*!< index of interface */ + uint16_t wLength; /*!< length of notification data */ +} acm_notification; + +/* header function structure */ +typedef struct { + usb_desc_header header; /*!< descriptor header, including type and size. */ + uint8_t bDescriptorSubtype; /*!< bDescriptorSubtype: header function descriptor */ + uint16_t bcdCDC; /*!< bcdCDC: low byte of spec release number (CDC1.10) */ +} usb_desc_header_func; + +/* call management function structure */ +typedef struct { + usb_desc_header header; /*!< descriptor header, including type and size. */ + uint8_t bDescriptorSubtype; /*!< bDescriptorSubtype: call management function descriptor */ + uint8_t bmCapabilities; /*!< bmCapabilities: D0 is reset, D1 is ignored */ + uint8_t bDataInterface; /*!< bDataInterface: 1 interface used for call management */ +} usb_desc_call_managment_func; + +/* ACM function structure */ +typedef struct { + usb_desc_header header; /*!< descriptor header, including type and size. */ + uint8_t bDescriptorSubtype; /*!< bDescriptorSubtype: abstract control management descriptor */ + uint8_t bmCapabilities; /*!< bmCapabilities: D1 */ +} usb_desc_acm_func; + +/* union function structure */ +typedef struct { + usb_desc_header header; /*!< descriptor header, including type and size. */ + uint8_t bDescriptorSubtype; /*!< bDescriptorSubtype: union function descriptor */ + uint8_t bMasterInterface; /*!< bMasterInterface: communication class interface */ + uint8_t bSlaveInterface0; /*!< bSlaveInterface0: data class interface */ +} usb_desc_union_func; + +#pragma pack() + +/* configuration descriptor structure */ +typedef struct { + usb_desc_config config; + usb_desc_itf cmd_itf; + usb_desc_header_func cdc_header; + usb_desc_call_managment_func cdc_call_managment; + usb_desc_acm_func cdc_acm; + usb_desc_union_func cdc_union; + usb_desc_ep cdc_cmd_endpoint; + usb_desc_itf cdc_data_interface; + usb_desc_ep cdc_out_endpoint; + usb_desc_ep cdc_in_endpoint; +} usb_cdc_desc_config_set; + +#define USB_CDC_RX_LEN 64U + +typedef struct { + uint8_t pre_packet_send; + uint8_t packet_sent; + uint8_t packet_receive; + + uint8_t data[USB_CDC_RX_LEN]; + + uint32_t receive_length; + + acm_line line_coding; +} usb_cdc_handler; + +extern usb_desc cdc_desc; +extern usb_class cdc_class; + +/* function declarations */ +/* receive CDC ACM data */ +void cdc_acm_data_receive(usb_dev *udev); +/* send CDC ACM data */ +void cdc_acm_data_send(usb_dev *udev); +/* check CDC ACM is ready for data transfer */ +uint8_t cdc_acm_check_ready(usb_dev *udev); + +#endif /* __CDC_ACM_CORE_H */ diff --git a/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbd_library/class/device/cdc/Source/cdc_acm_core.c b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbd_library/class/device/cdc/Source/cdc_acm_core.c new file mode 100644 index 0000000000..6ea6869a20 --- /dev/null +++ b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbd_library/class/device/cdc/Source/cdc_acm_core.c @@ -0,0 +1,509 @@ +/*! + \file cdc_acm_core.c + \brief CDC ACM driver + + \version 2020-07-17, V3.0.0, firmware for GD32F10x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "usbd_transc.h" +#include "cdc_acm_core.h" + +#define USBD_VID 0x28E9U +#define USBD_PID 0x018AU + +/* note:it should use the C99 standard when compiling the below codes */ +/* USB standard device descriptor */ +usb_desc_dev cdc_dev_desc = +{ + .header = + { + .bLength = USB_DEV_DESC_LEN, + .bDescriptorType = USB_DESCTYPE_DEV, + }, + .bcdUSB = 0x0200U, + .bDeviceClass = USB_CLASS_CDC, + .bDeviceSubClass = 0x00U, + .bDeviceProtocol = 0x00U, + .bMaxPacketSize0 = USBD_EP0_MAX_SIZE, + .idVendor = USBD_VID, + .idProduct = USBD_PID, + .bcdDevice = 0x0100U, + .iManufacturer = STR_IDX_MFC, + .iProduct = STR_IDX_PRODUCT, + .iSerialNumber = STR_IDX_SERIAL, + .bNumberConfigurations = USBD_CFG_MAX_NUM, +}; + +/* USB device configuration descriptor */ +usb_cdc_desc_config_set cdc_config_desc = +{ + .config = + { + .header = + { + .bLength = sizeof(usb_desc_config), + .bDescriptorType = USB_DESCTYPE_CONFIG, + }, + .wTotalLength = USB_CDC_ACM_CONFIG_DESC_SIZE, + .bNumInterfaces = 0x02U, + .bConfigurationValue = 0x01U, + .iConfiguration = 0x00U, + .bmAttributes = 0x80U, + .bMaxPower = 0x32U + }, + + .cmd_itf = + { + .header = + { + .bLength = sizeof(usb_desc_itf), + .bDescriptorType = USB_DESCTYPE_ITF + }, + .bInterfaceNumber = 0x00U, + .bAlternateSetting = 0x00U, + .bNumEndpoints = 0x01U, + .bInterfaceClass = USB_CLASS_CDC, + .bInterfaceSubClass = USB_CDC_SUBCLASS_ACM, + .bInterfaceProtocol = USB_CDC_PROTOCOL_AT, + .iInterface = 0x00U + }, + + .cdc_header = + { + .header = + { + .bLength = sizeof(usb_desc_header_func), + .bDescriptorType = USB_DESCTYPE_CS_INTERFACE + }, + .bDescriptorSubtype = 0x00U, + .bcdCDC = 0x0110U + }, + + .cdc_call_managment = + { + .header = + { + .bLength = sizeof(usb_desc_call_managment_func), + .bDescriptorType = USB_DESCTYPE_CS_INTERFACE + }, + .bDescriptorSubtype = 0x01U, + .bmCapabilities = 0x00U, + .bDataInterface = 0x01U + }, + + .cdc_acm = + { + .header = + { + .bLength = sizeof(usb_desc_acm_func), + .bDescriptorType = USB_DESCTYPE_CS_INTERFACE + }, + .bDescriptorSubtype = 0x02U, + .bmCapabilities = 0x02U, + }, + + .cdc_union = + { + .header = + { + .bLength = sizeof(usb_desc_union_func), + .bDescriptorType = USB_DESCTYPE_CS_INTERFACE + }, + .bDescriptorSubtype = 0x06U, + .bMasterInterface = 0x00U, + .bSlaveInterface0 = 0x01U, + }, + + .cdc_cmd_endpoint = + { + .header = + { + .bLength = sizeof(usb_desc_ep), + .bDescriptorType = USB_DESCTYPE_EP, + }, + .bEndpointAddress = CDC_CMD_EP, + .bmAttributes = USB_EP_ATTR_INT, + .wMaxPacketSize = CDC_ACM_CMD_PACKET_SIZE, + .bInterval = 0x0AU + }, + + .cdc_data_interface = + { + .header = + { + .bLength = sizeof(usb_desc_itf), + .bDescriptorType = USB_DESCTYPE_ITF, + }, + .bInterfaceNumber = 0x01U, + .bAlternateSetting = 0x00U, + .bNumEndpoints = 0x02U, + .bInterfaceClass = USB_CLASS_DATA, + .bInterfaceSubClass = 0x00U, + .bInterfaceProtocol = USB_CDC_PROTOCOL_NONE, + .iInterface = 0x00U + }, + + .cdc_out_endpoint = + { + .header = + { + .bLength = sizeof(usb_desc_ep), + .bDescriptorType = USB_DESCTYPE_EP, + }, + .bEndpointAddress = CDC_OUT_EP, + .bmAttributes = USB_EP_ATTR_BULK, + .wMaxPacketSize = CDC_ACM_DATA_PACKET_SIZE, + .bInterval = 0x00U + }, + + .cdc_in_endpoint = + { + .header = + { + .bLength = sizeof(usb_desc_ep), + .bDescriptorType = USB_DESCTYPE_EP + }, + .bEndpointAddress = CDC_IN_EP, + .bmAttributes = USB_EP_ATTR_BULK, + .wMaxPacketSize = CDC_ACM_DATA_PACKET_SIZE, + .bInterval = 0x00U + } +}; + +/* USB language ID descriptor */ +static usb_desc_LANGID usbd_language_id_desc = +{ + .header = + { + .bLength = sizeof(usb_desc_LANGID), + .bDescriptorType = USB_DESCTYPE_STR, + }, + .wLANGID = ENG_LANGID +}; + +/* USB manufacture string */ +static usb_desc_str manufacturer_string = +{ + .header = + { + .bLength = USB_STRING_LEN(10U), + .bDescriptorType = USB_DESCTYPE_STR, + }, + .unicode_string = {'G', 'i', 'g', 'a', 'D', 'e', 'v', 'i', 'c', 'e'} +}; + +/* USB product string */ +static usb_desc_str product_string = +{ + .header = + { + .bLength = USB_STRING_LEN(12U), + .bDescriptorType = USB_DESCTYPE_STR, + }, + .unicode_string = {'G', 'D', '3', '2', '-', 'C', 'D', 'C', '_', 'A', 'C', 'M'} +}; + +/* USBD serial string */ +static usb_desc_str serial_string = +{ + .header = + { + .bLength = USB_STRING_LEN(12U), + .bDescriptorType = USB_DESCTYPE_STR, + } +}; + +/* USB string descriptor set */ +uint8_t* usbd_cdc_strings[] = +{ + [STR_IDX_LANGID] = (uint8_t *)&usbd_language_id_desc, + [STR_IDX_MFC] = (uint8_t *)&manufacturer_string, + [STR_IDX_PRODUCT] = (uint8_t *)&product_string, + [STR_IDX_SERIAL] = (uint8_t *)&serial_string +}; + +usb_desc cdc_desc = { + .dev_desc = (uint8_t *)&cdc_dev_desc, + .config_desc = (uint8_t *)&cdc_config_desc, + .strings = usbd_cdc_strings +}; + +/* local function prototypes ('static') */ +static uint8_t cdc_acm_init (usb_dev *udev, uint8_t config_index); +static uint8_t cdc_acm_deinit (usb_dev *udev, uint8_t config_index); +static uint8_t cdc_acm_req_handler (usb_dev *udev, usb_req *req); +static uint8_t cdc_acm_ctlx_out (usb_dev *udev); +static void cdc_acm_data_in (usb_dev *udev, uint8_t ep_num); +static void cdc_acm_data_out (usb_dev *udev, uint8_t ep_num); + +usb_class cdc_class = { + .req_cmd = NO_CMD, + + .init = cdc_acm_init, + .deinit = cdc_acm_deinit, + .req_process = cdc_acm_req_handler, + .ctlx_out = cdc_acm_ctlx_out, + .data_in = cdc_acm_data_in, + .data_out = cdc_acm_data_out +}; + +/*! + \brief receive CDC ACM data + \param[in] udev: pointer to USB device instance + \param[out] none + \retval USB device operation status +*/ +void cdc_acm_data_receive(usb_dev *udev) +{ + usb_cdc_handler *cdc = (usb_cdc_handler *)udev->class_data[CDC_COM_INTERFACE]; + + cdc->packet_receive = 0U; + cdc->pre_packet_send = 0U; + + usbd_ep_recev(udev, CDC_OUT_EP, (uint8_t*)(cdc->data), USB_CDC_RX_LEN); +} + +/*! + \brief send CDC ACM data + \param[in] udev: pointer to USB device instance + \param[out] none + \retval USB device operation status +*/ +void cdc_acm_data_send (usb_dev *udev) +{ + usb_cdc_handler *cdc = (usb_cdc_handler *)udev->class_data[CDC_COM_INTERFACE]; + uint32_t data_len = cdc->receive_length; + + if ((0U != data_len) && (1U == cdc->packet_sent)) { + cdc->packet_sent = 0U; + usbd_ep_send(udev, CDC_IN_EP, (uint8_t*)(cdc->data), (uint16_t)data_len); + cdc->receive_length = 0U; + } +} + +/*! + \brief check CDC ACM is ready for data transfer + \param[in] udev: pointer to USB device instance + \param[out] none + \retval 0 if CDC is ready, 5 otherwise +*/ +uint8_t cdc_acm_check_ready(usb_dev *udev) +{ + if (udev->class_data[CDC_COM_INTERFACE] != NULL) { + usb_cdc_handler *cdc = (usb_cdc_handler *)udev->class_data[CDC_COM_INTERFACE]; + + if ((1U == cdc->packet_receive) && (1U == cdc->pre_packet_send)) { + return 0U; + } + } + + return 5U; +} + +/*! + \brief initialize the CDC ACM device + \param[in] udev: pointer to USB device instance + \param[in] config_index: configuration index + \param[out] none + \retval USB device operation status +*/ +static uint8_t cdc_acm_init (usb_dev *udev, uint8_t config_index) +{ + static usb_cdc_handler cdc_handler; + + /* initialize the data endpoints */ + usbd_ep_init(udev, EP_BUF_SNG, BULK_TX_ADDR, &(cdc_config_desc.cdc_in_endpoint)); + usbd_ep_init(udev, EP_BUF_SNG, BULK_RX_ADDR, &(cdc_config_desc.cdc_out_endpoint)); + + /* initialize the command endpoint */ + usbd_ep_init(udev, EP_BUF_SNG, INT_TX_ADDR, &(cdc_config_desc.cdc_cmd_endpoint)); + + udev->ep_transc[EP_ID(CDC_IN_EP)][TRANSC_IN] = cdc_class.data_in; + udev->ep_transc[CDC_OUT_EP][TRANSC_OUT] = cdc_class.data_out; + + /* initialize CDC handler structure */ + cdc_handler.packet_receive = 0U; + cdc_handler.packet_sent = 1U; + cdc_handler.pre_packet_send = 1U; + cdc_handler.receive_length = 0U; + + cdc_handler.line_coding = (acm_line){ + .dwDTERate = 115200U, + .bCharFormat = 0U, + .bParityType = 0U, + .bDataBits = 0x08U + }; + + udev->class_data[CDC_COM_INTERFACE] = (void *)&cdc_handler; + + return USBD_OK; +} + +/*! + \brief deinitialize the CDC ACM device + \param[in] udev: pointer to USB device instance + \param[in] config_index: configuration index + \param[out] none + \retval USB device operation status +*/ +static uint8_t cdc_acm_deinit (usb_dev *udev, uint8_t config_index) +{ + /* deinitialize the data endpoints */ + usbd_ep_deinit(udev, CDC_IN_EP); + usbd_ep_deinit(udev, CDC_OUT_EP); + + /* deinitialize the command endpoint */ + usbd_ep_deinit(udev, CDC_CMD_EP); + + return USBD_OK; +} + +/*! + \brief command data received on control endpoint + \param[in] udev: pointer to USB device instance + \param[out] none + \retval USB device operation status +*/ +static uint8_t cdc_acm_ctlx_out (usb_dev *udev) +{ + usb_cdc_handler *cdc = (usb_cdc_handler *)udev->class_data[CDC_COM_INTERFACE]; + + if (NO_CMD != udev->class_core->req_cmd) { + cdc->packet_receive = 1U; + cdc->pre_packet_send = 1U; + + udev->class_core->req_cmd = NO_CMD; + } + + return USBD_OK; +} + +/*! + \brief handle CDC ACM data in transaction + \param[in] udev: pointer to USB device instance + \param[in] ep_num: endpoint number + \param[out] none + \retval USB device operation status +*/ +static void cdc_acm_data_in (usb_dev *udev, uint8_t ep_num) +{ + usb_transc *transc = &udev->transc_in[ep_num]; + usb_cdc_handler *cdc = (usb_cdc_handler *)udev->class_data[CDC_COM_INTERFACE]; + + if (transc->xfer_count == transc->max_len) { + usbd_ep_send(udev, EP_ID(ep_num), NULL, 0U); + } else { + cdc->packet_sent = 1U; + cdc->pre_packet_send = 1U; + } +} + +/*! + \brief handle CDC ACM data out transaction + \param[in] udev: pointer to USB device instance + \param[in] ep_num: endpoint number + \param[out] none + \retval USB device operation status +*/ +static void cdc_acm_data_out (usb_dev *udev, uint8_t ep_num) +{ + usb_cdc_handler *cdc = (usb_cdc_handler *)udev->class_data[CDC_COM_INTERFACE]; + + cdc->packet_receive = 1U; + + cdc->receive_length = udev->transc_out[ep_num].xfer_count; +} + +/*! + \brief handle the CDC ACM class-specific requests + \param[in] udev: pointer to USB device instance + \param[in] req: device class-specific request + \param[out] none + \retval USB device operation status +*/ +static uint8_t cdc_acm_req_handler (usb_dev *udev, usb_req *req) +{ + uint8_t status = REQ_NOTSUPP, noti_buf[10] = {0U}; + usb_cdc_handler *cdc = (usb_cdc_handler *)udev->class_data[CDC_COM_INTERFACE]; + + acm_notification *notif = (void *)noti_buf; + + switch (req->bRequest) { + case SEND_ENCAPSULATED_COMMAND: + break; + + case GET_ENCAPSULATED_RESPONSE: + break; + + case SET_COMM_FEATURE: + break; + + case GET_COMM_FEATURE: + break; + + case CLEAR_COMM_FEATURE: + break; + + case SET_LINE_CODING: + /* set the value of the current command to be processed */ + udev->class_core->req_cmd = req->bRequest; + + usb_transc_config(&udev->transc_out[0U], (uint8_t *)&cdc->line_coding, req->wLength, 0U); + + status = REQ_SUPP; + break; + + case GET_LINE_CODING: + usb_transc_config(&udev->transc_in[0U], (uint8_t *)&cdc->line_coding, 7U, 0U); + + status = REQ_SUPP; + break; + + case SET_CONTROL_LINE_STATE: + notif->bmRequestType = 0xA1U; + notif->bNotification = USB_CDC_NOTIFY_SERIAL_STATE; + notif->wIndex = 0U; + notif->wValue = 0U; + notif->wLength = 2U; + noti_buf[8] = (uint8_t)req->wValue & 3U; + noti_buf[9] = 0U; + + status = REQ_SUPP; + break; + + case SEND_BREAK: + break; + + default: + break; + } + + return status; +} diff --git a/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbd_library/class/device/dfu/Include/dfu_core.h b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbd_library/class/device/dfu/Include/dfu_core.h new file mode 100644 index 0000000000..7eec7c345d --- /dev/null +++ b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbd_library/class/device/dfu/Include/dfu_core.h @@ -0,0 +1,179 @@ +/*! + \file dfu_core.h + \brief the header file of USB DFU device class core functions + + \version 2020-07-17, V3.0.0, firmware for GD32F10x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef __DFU_CORE_H +#define __DFU_CORE_H + +#include "usbd_enum.h" + +/* DFU class code */ +#define USB_DFU_CLASS 0xFEU + +/* DFU subclass code */ +#define USB_DFU_SUBCLASS_UPGRADE 0x01U + +/* DFU protocol code */ +#define USB_DFU_PROTOCL_RUNTIME 0x01U +#define USB_DFU_PROTOCL_DFU 0x02U + +/* manifestation state */ +#define MANIFEST_COMPLETE 0x00U +#define MANIFEST_IN_PROGRESS 0x01U + +/* DFU attributes code */ +#define USB_DFU_CAN_DOWNLOAD 0x01U +#define USB_DFU_CAN_UPLOAD 0x02U +#define USB_DFU_MANIFEST_TOLERANT 0x04U +#define USB_DFU_WILL_DETACH 0x08U + +/* special commands with download request */ +#define GET_COMMANDS 0x00U +#define SET_ADDRESS_POINTER 0x21U +#define ERASE 0x41U + +/* memory operation command */ +#define CMD_ERASE 0U +#define CMD_WRITE 1U + +#define _BYTE1(x) (uint8_t)((x) & 0xFFU) /*!< addressing cycle 1st byte */ +#define _BYTE2(x) (uint8_t)(((x) & 0xFF00U) >> 8U) /*!< addressing cycle 2nd byte */ +#define _BYTE3(x) (uint8_t)(((x) & 0xFF0000U) >> 16U) /*!< addressing cycle 3rd byte */ + +#define SET_POLLING_TIMEOUT(x) do { \ + dfu->bwPollTimeout0 = _BYTE1(x);\ + dfu->bwPollTimeout1 = _BYTE2(x);\ + dfu->bwPollTimeout2 = _BYTE3(x);\ + } while(0) + +#define FLASH_ERASE_TIMEOUT 60U +#define FLASH_WRITE_TIMEOUT 80U + +/* bit detach capable = bit 3 in bmAttributes field */ +#define DFU_DETACH_MASK (uint8_t)(0x10U) +#define USB_DFU_CONFIG_DESC_SIZE (18U + (9U * USBD_ITF_MAX_NUM)) +#define DFU_DESC_TYPE 0x21U + +/* DFU device state enumeration */ +typedef enum { + STATE_APP_IDLE = 0x00U, + 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 +} dfu_state; + +/* DFU device status enumeration */ +typedef enum { + STATUS_OK = 0x00U, + STATUS_ERR_TARGET, + STATUS_ERR_FILE, + STATUS_ERR_WRITE, + STATUS_ERR_ERASE, + STATUS_ERR_CHECK_ERASED, + STATUS_ERR_PROG, + STATUS_ERR_VERIFY, + STATUS_ERR_ADDRESS, + STATUS_ERR_NOTDONE, + STATUS_ERR_FIRMWARE, + STATUS_ERR_VENDOR, + STATUS_ERR_USBR, + STATUS_ERR_POR, + STATUS_ERR_UNKNOWN, + STATUS_ERR_STALLEDPKT +} dfu_status; + +/* DFU class-specific requests enumeration */ +typedef enum { + DFU_DETACH = 0U, + DFU_DNLOAD, + DFU_UPLOAD, + DFU_GETSTATUS, + DFU_CLRSTATUS, + DFU_GETSTATE, + DFU_ABORT, + DFU_REQ_MAX +} dfu_requests; + +#pragma pack(1) + +/* USB DFU function descriptor structure */ +typedef struct +{ + usb_desc_header header; /*!< descriptor header, including type and size */ + uint8_t bmAttributes; /*!< DFU attributes */ + uint16_t wDetachTimeOut; /*!< time, in milliseconds, that the device will wait after receipt of the DFU_DETACH request. If */ + uint16_t wTransferSize; /*!< maximum number of bytes that the device can accept per control-write transaction */ + uint16_t bcdDFUVersion; /*!< numeric expression identifying the version of the DFU specification release. */ +} usb_desc_dfu_func; + +#pragma pack() + +/* USB configuration descriptor structure */ +typedef struct +{ + usb_desc_config config; + usb_desc_itf dfu_itf; + usb_desc_dfu_func dfu_func; +} usb_dfu_desc_config_set; + +/* USB DFU handler structure */ +typedef struct +{ + uint8_t bStatus; + uint8_t bwPollTimeout0; + uint8_t bwPollTimeout1; + uint8_t bwPollTimeout2; + uint8_t bState; + uint8_t iString; + + uint8_t manifest_state; + uint16_t data_len; + uint16_t block_num; + uint32_t base_addr; + + uint8_t buf[TRANSFER_SIZE]; +} usbd_dfu_handler; + +typedef void (*app_func) (void); + +extern usb_desc dfu_desc; +extern usb_class dfu_class; + +#endif /* __DFU_CORE_H */ diff --git a/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbd_library/class/device/dfu/Source/dfu_core.c b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbd_library/class/device/dfu/Source/dfu_core.c new file mode 100644 index 0000000000..1ee3fe2c79 --- /dev/null +++ b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbd_library/class/device/dfu/Source/dfu_core.c @@ -0,0 +1,675 @@ +/*! + \file dfu_core.c + \brief USB DFU device class core functions + + \version 2020-07-17, V3.0.0, firmware for GD32F10x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "dfu_core.h" +#include "systick.h" +#include + +#define USBD_VID 0x28E9U +#define USBD_PID 0x0189U + +/* local function prototypes ('static') */ +static uint8_t dfu_init (usb_dev *udev, uint8_t config_index); +static uint8_t dfu_deinit (usb_dev *udev, uint8_t config_index); +static uint8_t dfu_req_handler (usb_dev *udev, usb_req *req); +static uint8_t dfu_ctlx_in (usb_dev *udev); + +/* DFU requests management functions */ +static void dfu_detach (usb_dev *udev, usb_req *req); +static void dfu_dnload (usb_dev *udev, usb_req *req); +static void dfu_upload (usb_dev *udev, usb_req *req); +static void dfu_getstatus (usb_dev *udev, usb_req *req); +static void dfu_clrstatus (usb_dev *udev, usb_req *req); +static void dfu_getstate (usb_dev *udev, usb_req *req); +static void dfu_abort (usb_dev *udev, usb_req *req); + +static void dfu_mode_leave (usb_dev *udev); +static uint8_t dfu_getstatus_complete (usb_dev *udev); + +static void (*dfu_request_process[])(usb_dev *udev, usb_req *req) = +{ + [DFU_DETACH] = dfu_detach, + [DFU_DNLOAD] = dfu_dnload, + [DFU_UPLOAD] = dfu_upload, + [DFU_GETSTATUS] = dfu_getstatus, + [DFU_CLRSTATUS] = dfu_clrstatus, + [DFU_GETSTATE] = dfu_getstate, + [DFU_ABORT] = dfu_abort +}; + +/* note:it should use the c99 standard when compiling the below codes */ +/* USB standard device descriptor */ +usb_desc_dev dfu_dev_desc = +{ + .header = + { + .bLength = USB_DEV_DESC_LEN, + .bDescriptorType = USB_DESCTYPE_DEV + }, + .bcdUSB = 0x0200U, + .bDeviceClass = 0x00U, + .bDeviceSubClass = 0x00U, + .bDeviceProtocol = 0x00U, + .bMaxPacketSize0 = USBD_EP0_MAX_SIZE, + .idVendor = USBD_VID, + .idProduct = USBD_PID, + .bcdDevice = 0x0100U, + .iManufacturer = STR_IDX_MFC, + .iProduct = STR_IDX_PRODUCT, + .iSerialNumber = STR_IDX_SERIAL, + .bNumberConfigurations = USBD_CFG_MAX_NUM +}; + +/* USB device configuration descriptor */ +usb_dfu_desc_config_set dfu_config_desc = +{ + .config = + { + .header = + { + .bLength = sizeof(usb_desc_config), + .bDescriptorType = USB_DESCTYPE_CONFIG + }, + .wTotalLength = USB_DFU_CONFIG_DESC_SIZE, + .bNumInterfaces = 0x01U, + .bConfigurationValue = 0x01U, + .iConfiguration = 0x00U, + .bmAttributes = 0x80U, + .bMaxPower = 0x32U + }, + + .dfu_itf = + { + .header = + { + .bLength = sizeof(usb_desc_itf), + .bDescriptorType = USB_DESCTYPE_ITF + }, + .bInterfaceNumber = 0x00U, + .bAlternateSetting = 0x00U, + .bNumEndpoints = 0x00U, + .bInterfaceClass = USB_DFU_CLASS, + .bInterfaceSubClass = USB_DFU_SUBCLASS_UPGRADE, + .bInterfaceProtocol = USB_DFU_PROTOCL_DFU, + .iInterface = 0x00U + }, + + .dfu_func = + { + .header = + { + .bLength = sizeof(usb_desc_dfu_func), + .bDescriptorType = DFU_DESC_TYPE + }, + .bmAttributes = USB_DFU_CAN_DOWNLOAD | USB_DFU_CAN_UPLOAD | USB_DFU_WILL_DETACH, + .wDetachTimeOut = 0x00FFU, + .wTransferSize = TRANSFER_SIZE, + .bcdDFUVersion = 0x011AU, + }, +}; + +/* USB language ID descriptor */ +static usb_desc_LANGID usbd_language_id_desc = +{ + .header = { + .bLength = sizeof(usb_desc_LANGID), + .bDescriptorType = USB_DESCTYPE_STR + }, + .wLANGID = ENG_LANGID +}; + +/* USB manufacture string */ +static usb_desc_str manufacturer_string = +{ + .header = + { + .bLength = USB_STRING_LEN(10U), + .bDescriptorType = USB_DESCTYPE_STR, + }, + .unicode_string = {'G', 'i', 'g', 'a', 'D', 'e', 'v', 'i', 'c', 'e'} +}; + +/* USB product string */ +static usb_desc_str product_string = +{ + .header = + { + .bLength = USB_STRING_LEN(12U), + .bDescriptorType = USB_DESCTYPE_STR, + }, + .unicode_string = {'G', 'D', '3', '2', '-', 'U', 'S', 'B', '_', 'D', 'F', 'U'} +}; + +/* USB serial string */ +static usb_desc_str serial_string = +{ + .header = + { + .bLength = USB_STRING_LEN(2U), + .bDescriptorType = USB_DESCTYPE_STR, + } +}; + +/* USB configure string */ +static usb_desc_str config_string = +{ + .header = + { + .bLength = USB_STRING_LEN(15U), + .bDescriptorType = USB_DESCTYPE_STR, + }, + .unicode_string = {'G', 'D', '3', '2', ' ', 'U', 'S', 'B', ' ', 'C', 'O', 'N', 'F', 'I', 'G'} +}; + +/* USB interface string */ +static usb_desc_str interface_string = +{ + .header = + { + .bLength = USB_STRING_LEN(15U), + .bDescriptorType = USB_DESCTYPE_STR, + }, + .unicode_string = {'@', 'I', 'n', 't', 'e', 'r', 'n', 'a', 'l', 'F', 'l', 'a', 's', 'h', ' ', '/', '0', 'x', '0', '8', '0', '0', + '0', '0', '0', '0', '/', '1', '6', '*', '0', '0', '1', 'K', 'a', ',', '4', '8', '*', '0', '0', '1', 'K', 'g'} +}; + +uint8_t* usbd_dfu_strings[] = +{ + [STR_IDX_LANGID] = (uint8_t *)&usbd_language_id_desc, + [STR_IDX_MFC] = (uint8_t *)&manufacturer_string, + [STR_IDX_PRODUCT] = (uint8_t *)&product_string, + [STR_IDX_SERIAL] = (uint8_t *)&serial_string, + [STR_IDX_CONFIG] = (uint8_t *)&config_string, + [STR_IDX_ITF] = (uint8_t *)&interface_string +}; + +usb_desc dfu_desc = { + .dev_desc = (uint8_t *)&dfu_dev_desc, + .config_desc = (uint8_t *)&dfu_config_desc, + .strings = usbd_dfu_strings +}; + +usb_class dfu_class = { + .init = dfu_init, + .deinit = dfu_deinit, + .req_process = dfu_req_handler, + .ctlx_in = dfu_ctlx_in +}; + +/*! + \brief initialize the USB DFU device + \param[in] udev: pointer to USB device instance + \param[in] config_index: configuration index + \param[out] none + \retval USB device operation status +*/ +static uint8_t dfu_init (usb_dev *udev, uint8_t config_index) +{ + static usbd_dfu_handler dfu_handler; + + /* unlock the internal flash */ + fmc_unlock(); + + systick_config(); + + memset((void *)&dfu_handler, 0, sizeof(usbd_dfu_handler)); + + dfu_handler.base_addr = APP_LOADED_ADDR; + dfu_handler.manifest_state = MANIFEST_COMPLETE; + dfu_handler.bState = STATE_DFU_IDLE; + dfu_handler.bStatus = STATUS_OK; + + udev->class_data[USBD_DFU_INTERFACE] = (void *)&dfu_handler; + + return USBD_OK; +} + +/*! + \brief deinitialize the USB DFU device + \param[in] udev: pointer to USB device instance + \param[in] config_index: configuration index + \param[out] none + \retval USB device operation status +*/ +static uint8_t dfu_deinit (usb_dev *udev, uint8_t config_index) +{ + usbd_dfu_handler *dfu = (usbd_dfu_handler *)udev->class_data[USBD_DFU_INTERFACE]; + + /* restore device default state */ + memset(udev->class_data[USBD_DFU_INTERFACE], 0, sizeof(usbd_dfu_handler)); + + dfu->bState = STATE_DFU_IDLE; + dfu->bStatus = STATUS_OK; + + /* lock the internal flash */ + fmc_lock(); + + return USBD_OK; +} + +/*! + \brief handle the USB DFU class-specific requests + \param[in] udev: pointer to USB device instance + \param[in] req: device class-specific request + \param[out] none + \retval USB device operation status +*/ +static uint8_t dfu_req_handler (usb_dev *udev, usb_req *req) +{ + if (req->bRequest < DFU_REQ_MAX) { + dfu_request_process[req->bRequest](udev, req); + } else { + return USBD_FAIL; + } + + return USBD_OK; +} + +/*! + \brief handle data stage + \param[in] udev: pointer to USB device instance + \param[out] none + \retval USB device operation status +*/ +static uint8_t dfu_ctlx_in (usb_dev *udev) +{ + dfu_getstatus_complete(udev); + + return USBD_OK; +} + +/*! + \brief handle data in stage in control endpoint 0 + \param[in] udev: pointer to USB device instance + \param[out] none + \retval USB device operation status + */ +static uint8_t dfu_getstatus_complete (usb_dev *udev) +{ + uint32_t addr; + + usbd_dfu_handler *dfu = (usbd_dfu_handler *)udev->class_data[USBD_DFU_INTERFACE]; + + if (STATE_DFU_DNBUSY == dfu->bState) { + /* decode the special command */ + if (0U == dfu->block_num) { + if (1U == dfu->data_len){ + if (GET_COMMANDS == dfu->buf[0]) { + /* no operation */ + } + } else if (5U == dfu->data_len) { + if (SET_ADDRESS_POINTER == dfu->buf[0]) { + /* set flash operation address */ + dfu->base_addr = *(uint32_t *)(dfu->buf + 1U); + } else if (ERASE == dfu->buf[0]) { + dfu->base_addr = *(uint32_t *)(dfu->buf + 1U); + + fmc_page_erase(dfu->base_addr); + } else { + /* no operation */ + } + } else { + /* no operation */ + } + } else if (dfu->block_num > 1U) { /* regular download command */ + /* preform the write operation */ + uint32_t idx = 0U; + + /* decode the required address */ + addr = (dfu->block_num - 2U) * TRANSFER_SIZE + dfu->base_addr; + + if (dfu->data_len & 0x03U) { /* not an aligned data */ + for (idx = dfu->data_len; idx < ((dfu->data_len & 0xFFFCU) + 4U); idx++) { + dfu->buf[idx] = 0xFFU; + } + } + + /* data received are word multiple */ + for (idx = 0U; idx < dfu->data_len; idx += 4U) { + fmc_word_program(addr, *(uint32_t *)(dfu->buf + idx)); + + addr += 4U; + } + + dfu->block_num = 0U; + } else { + /* no operation */ + } + + dfu->data_len = 0U; + + /* update the device state and poll timeout */ + dfu->bState = STATE_DFU_DNLOAD_SYNC; + + return USBD_OK; + } else if (STATE_DFU_MANIFEST == dfu->bState) { /* manifestation in progress */ + /* start leaving DFU mode */ + dfu_mode_leave(udev); + } else { + /* no operation */ + } + + return USBD_OK; +} + +/*! + \brief handle the DFU_DETACH request + \param[in] udev: pointer to USB device instance + \param[in] req: DFU class request + \param[out] none + \retval none. +*/ +static void dfu_detach(usb_dev *udev, usb_req *req) +{ + usbd_dfu_handler *dfu = (usbd_dfu_handler *)udev->class_data[USBD_DFU_INTERFACE]; + + switch (dfu->bState) { + case STATE_DFU_IDLE: + case STATE_DFU_DNLOAD_SYNC: + case STATE_DFU_DNLOAD_IDLE: + case STATE_DFU_MANIFEST_SYNC: + case STATE_DFU_UPLOAD_IDLE: + dfu->bStatus = STATUS_OK; + dfu->bState = STATE_DFU_IDLE; + dfu->iString = 0U; /* iString */ + + dfu->block_num = 0U; + dfu->data_len = 0U; + break; + + default: + break; + } + + /* check the detach capability in the DFU functional descriptor */ + if (dfu_config_desc.dfu_func.wDetachTimeOut & DFU_DETACH_MASK) { + usbd_disconnect(udev); + + usbd_connect(udev); + } else { + /* wait for the period of time specified in detach request */ + delay_1ms(4U); + } +} + +/*! + \brief handle the DFU_DNLOAD request + \param[in] udev: pointer to USB device instance + \param[in] req: DFU class request + \param[out] none + \retval none +*/ +static void dfu_dnload(usb_dev *udev, usb_req *req) +{ + usb_transc *transc = &udev->transc_out[0]; + + usbd_dfu_handler *dfu = (usbd_dfu_handler *)udev->class_data[USBD_DFU_INTERFACE]; + + switch (dfu->bState) { + case STATE_DFU_IDLE: + case STATE_DFU_DNLOAD_IDLE: + if (req->wLength > 0U) { + /* update the global length and block number */ + dfu->block_num = req->wValue; + dfu->data_len = req->wLength; + + dfu->bState = STATE_DFU_DNLOAD_SYNC; + + transc->xfer_len = dfu->data_len; + transc->xfer_buf = dfu->buf; + transc->xfer_count = 0U; + } else { + dfu->manifest_state = MANIFEST_IN_PROGRESS; + dfu->bState = STATE_DFU_MANIFEST_SYNC; + } + break; + + default: + break; + } +} + +/*! + \brief handles the DFU UPLOAD request. + \param[in] udev: pointer to USB device instance + \param[in] req: DFU class request + \param[out] none + \retval none +*/ +static void dfu_upload (usb_dev *udev, usb_req *req) +{ + uint8_t *phy_addr = NULL; + uint32_t addr = 0U; + + usbd_dfu_handler *dfu = (usbd_dfu_handler *)udev->class_data[USBD_DFU_INTERFACE]; + + if(req->wLength <= 0U) { + dfu->bState = STATE_DFU_IDLE; + + return; + } + + usb_transc *transc = &udev->transc_in[0]; + + switch (dfu->bState) { + case STATE_DFU_IDLE: + case STATE_DFU_UPLOAD_IDLE: + /* update the global length and block number */ + dfu->block_num = req->wValue; + dfu->data_len = req->wLength; + + /* DFU get command */ + if (0U == dfu->block_num) { + /* update the state machine */ + dfu->bState = (dfu->data_len > 3U) ? STATE_DFU_IDLE : STATE_DFU_UPLOAD_IDLE; + + /* store the values of all supported commands */ + dfu->buf[0] = GET_COMMANDS; + dfu->buf[1] = SET_ADDRESS_POINTER; + dfu->buf[2] = ERASE; + + /* send the status data over EP0 */ + transc->xfer_buf = &(dfu->buf[0]); + transc->xfer_len = 3U; + } else if (dfu->block_num > 1U) { + dfu->bState = STATE_DFU_UPLOAD_IDLE; + + /* change is accelerated */ + addr = (dfu->block_num - 2U) * TRANSFER_SIZE + dfu->base_addr; + + /* return the physical address where data are stored */ + phy_addr = (uint8_t *)(addr); + + /* send the status data over EP0 */ + transc->xfer_buf = phy_addr; + transc->xfer_len = dfu->data_len; + } else { + dfu->bState = STATUS_ERR_STALLEDPKT; + } + break; + + default: + dfu->data_len = 0U; + dfu->block_num = 0U; + break; + } +} + +/*! + \brief handle the DFU_GETSTATUS request + \param[in] udev: pointer to USB device instance + \param[in] req: DFU class request + \param[out] none + \retval none +*/ +static void dfu_getstatus (usb_dev *udev, usb_req *req) +{ + usb_transc *transc = &udev->transc_in[0]; + + usbd_dfu_handler *dfu = (usbd_dfu_handler *)udev->class_data[USBD_DFU_INTERFACE]; + + switch (dfu->bState) { + case STATE_DFU_DNLOAD_SYNC: + if (0U != dfu->data_len) { + dfu->bState = STATE_DFU_DNBUSY; + + if (0U == dfu->block_num) { + if (ERASE == dfu->buf[0]) { + SET_POLLING_TIMEOUT(FLASH_ERASE_TIMEOUT); + } else { + SET_POLLING_TIMEOUT(FLASH_WRITE_TIMEOUT); + } + } + } else { + dfu->bState = STATE_DFU_DNLOAD_IDLE; + } + break; + + case STATE_DFU_MANIFEST_SYNC: + if (MANIFEST_IN_PROGRESS == dfu->manifest_state) { + dfu->bState = STATE_DFU_MANIFEST; + dfu->bwPollTimeout0 = 1U; + } else if ((MANIFEST_COMPLETE == dfu->manifest_state) && \ + (dfu_config_desc.dfu_func.bmAttributes & 0x04U)){ + dfu->bState = STATE_DFU_IDLE; + dfu->bwPollTimeout0 = 0U; + } else { + /* no operation */ + } + break; + + default: + break; + } + + /* send the status data of DFU interface to host over EP0 */ + transc->xfer_buf = (uint8_t *)&(dfu->bStatus); + transc->xfer_len = 6U; +} + +/*! + \brief handle the DFU_CLRSTATUS request + \param[in] udev: pointer to USB device instance + \param[in] req: DFU class request + \param[out] none + \retval none +*/ +static void dfu_clrstatus (usb_dev *udev, usb_req *req) +{ + usbd_dfu_handler *dfu = (usbd_dfu_handler *)udev->class_data[USBD_DFU_INTERFACE]; + + if (STATE_DFU_ERROR == dfu->bState) { + dfu->bStatus = STATUS_OK; + dfu->bState = STATE_DFU_IDLE; + } else { + /* state error */ + dfu->bStatus = STATUS_ERR_UNKNOWN; + dfu->bState = STATE_DFU_ERROR; + } + + dfu->iString = 0U; /* iString: index = 0 */ +} + +/*! + \brief handle the DFU_GETSTATE request + \param[in] udev: pointer to USB device instance + \param[in] req: DFU class request + \param[out] none + \retval none +*/ +static void dfu_getstate (usb_dev *udev, usb_req *req) +{ + usb_transc *transc = &udev->transc_in[0]; + + usbd_dfu_handler *dfu = (usbd_dfu_handler *)udev->class_data[USBD_DFU_INTERFACE]; + + /* send the current state of the DFU interface to host */ + transc->xfer_buf = &(dfu->bState); + transc->xfer_len = 1U; +} + +/*! + \brief handle the DFU_ABORT request + \param[in] udev: pointer to USB device instance + \param[in] req: DFU class request + \param[out] none + \retval none +*/ +static void dfu_abort (usb_dev *udev, usb_req *req) +{ + usbd_dfu_handler *dfu = (usbd_dfu_handler *)udev->class_data[USBD_DFU_INTERFACE]; + + switch (dfu->bState){ + case STATE_DFU_IDLE: + case STATE_DFU_DNLOAD_SYNC: + case STATE_DFU_DNLOAD_IDLE: + case STATE_DFU_MANIFEST_SYNC: + case STATE_DFU_UPLOAD_IDLE: + dfu->bStatus = STATUS_OK; + dfu->bState = STATE_DFU_IDLE; + dfu->iString = 0U; /* iString: index = 0 */ + + dfu->block_num = 0U; + dfu->data_len = 0U; + break; + + default: + break; + } +} + +/*! + \brief leave DFU mode and reset device to jump to user loaded code + \param[in] udev: pointer to USB device instance + \param[out] none + \retval none +*/ +static void dfu_mode_leave (usb_dev *udev) +{ + usbd_dfu_handler *dfu = (usbd_dfu_handler *)udev->class_data[USBD_DFU_INTERFACE]; + + dfu->manifest_state = MANIFEST_COMPLETE; + + if (dfu_config_desc.dfu_func.bmAttributes & 0x04U) { + dfu->bState = STATE_DFU_MANIFEST_SYNC; + } else { + dfu->bState = STATE_DFU_MANIFEST_WAIT_RESET; + + /* lock the internal flash */ + fmc_lock(); + + /* generate system reset to allow jumping to the user code */ + NVIC_SystemReset(); + } +} diff --git a/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbd_library/class/device/hid/Include/custom_hid_core.h b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbd_library/class/device/hid/Include/custom_hid_core.h new file mode 100644 index 0000000000..052100c663 --- /dev/null +++ b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbd_library/class/device/hid/Include/custom_hid_core.h @@ -0,0 +1,67 @@ +/*! + \file custom_hid_core.h + \brief definitions for HID core + + \version 2020-07-17, V3.0.0, firmware for GD32F10x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef __CUSTOM_HID_CORE_H +#define __CUSTOM_HID_CORE_H + +#include "usbd_enum.h" +#include "usb_hid.h" + +#define DESC_LEN_REPORT 96U +#define DESC_LEN_CONFIG 41U + +#define MAX_PERIPH_NUM 4U + +typedef struct { + uint8_t data[2]; + + uint8_t reportID; + uint8_t idlestate; + uint8_t protocol; +} custom_hid_handler; + +typedef struct { + void (*periph_config[MAX_PERIPH_NUM])(void); +} hid_fop_handler; + +extern usb_desc custom_hid_desc; +extern usb_class custom_hid_class; + +/* function declarations */ +/* register HID interface operation functions */ +uint8_t custom_hid_itfop_register (usb_dev *udev, hid_fop_handler *hid_fop); +/* send custom HID report */ +uint8_t custom_hid_report_send (usb_dev *udev, uint8_t *report, uint16_t len); + +#endif /* __CUSTOM_HID_CORE_H */ diff --git a/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbd_library/class/device/hid/Include/standard_hid_core.h b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbd_library/class/device/hid/Include/standard_hid_core.h new file mode 100644 index 0000000000..c5fb914bf2 --- /dev/null +++ b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbd_library/class/device/hid/Include/standard_hid_core.h @@ -0,0 +1,66 @@ +/*! + \file standard_hid_core.h + \brief definitions for HID core + + \version 2020-07-17, V3.0.0, firmware for GD32F10x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef __STANDARD_HID_CORE_H +#define __STANDARD_HID_CORE_H + +#include "usbd_enum.h" +#include "usb_hid.h" + +#define USB_HID_CONFIG_DESC_LEN 0x22U +#define USB_HID_REPORT_DESC_LEN 0x2EU + +typedef struct { + uint32_t protocol; + uint32_t idle_state; + + uint8_t data[HID_IN_PACKET]; + __IO uint8_t prev_transfer_complete; +} standard_hid_handler; + +typedef struct { + void (*hid_itf_config) (void); + void (*hid_itf_data_process) (usb_dev *udev); +} hid_fop_handler; + +extern usb_desc hid_desc; +extern usb_class hid_class; + +/* function declarations */ +/* register HID interface operation functions */ +uint8_t hid_itfop_register (usb_dev *udev, hid_fop_handler *hid_fop); +/* send HID report */ +uint8_t hid_report_send (usb_dev *udev, uint8_t *report, uint16_t len); + +#endif /* __STANDARD_HID_CORE_H */ diff --git a/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbd_library/class/device/hid/Include/usb_hid.h b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbd_library/class/device/hid/Include/usb_hid.h new file mode 100644 index 0000000000..c4caf9477d --- /dev/null +++ b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbd_library/class/device/hid/Include/usb_hid.h @@ -0,0 +1,83 @@ +/*! + \file usb_hid.h + \brief definitions for the USB HID class + + \version 2020-07-17, V3.0.0, firmware for GD32F10x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef __USB_HID_H +#define __USB_HID_H + +#include "usb_ch9_std.h" + +#define USB_HID_CLASS 0x03U + +#define USB_DESCTYPE_HID 0x21U +#define USB_DESCTYPE_REPORT 0x22U + +/* HID subclass code */ +#define USB_HID_SUBCLASS_BOOT_ITF 0x01U + +/* HID protocol codes */ +#define USB_HID_PROTOCOL_KEYBOARD 0x01U +#define USB_HID_PROTOCOL_MOUSE 0x02U + +#define GET_REPORT 0x01U +#define GET_IDLE 0x02U +#define GET_PROTOCOL 0x03U +#define SET_REPORT 0x09U +#define SET_IDLE 0x0AU +#define SET_PROTOCOL 0x0BU + +#pragma pack(1) + +typedef struct +{ + usb_desc_header header; /*!< regular descriptor header containing the descriptor's type and length */ + + uint16_t bcdHID; /*!< BCD encoded version that the HID descriptor and device complies to */ + uint8_t bCountryCode; /*!< country code of the localized device, or zero if universal */ + uint8_t bNumDescriptors; /*!< total number of HID report descriptors for the interface */ + uint8_t bDescriptorType; /*!< type of HID report */ + uint16_t wDescriptorLength; /*!< length of the associated HID report descriptor, in bytes */ +} usb_desc_hid; + +#pragma pack() + +typedef struct +{ + usb_desc_config config; + usb_desc_itf hid_itf; + usb_desc_hid hid_vendor; + usb_desc_ep hid_epin; + usb_desc_ep hid_epout; +} usb_hid_desc_config_set; + +#endif /* __USB_HID_H */ diff --git a/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbd_library/class/device/hid/Source/custom_hid_core.c b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbd_library/class/device/hid/Source/custom_hid_core.c new file mode 100644 index 0000000000..e8e0a41eae --- /dev/null +++ b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbd_library/class/device/hid/Source/custom_hid_core.c @@ -0,0 +1,503 @@ +/*! + \file custom_hid_core.c + \brief custom HID class driver + + \version 2020-07-17, V3.0.0, firmware for GD32F10x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "usbd_transc.h" +#include "custom_hid_core.h" +#include + +#define USBD_VID 0x28E9U +#define USBD_PID 0x128AU + +/* Note:it should use the C99 standard when compiling the below codes */ +/* USB standard device descriptor */ +usb_desc_dev custom_hid_dev_desc = +{ + .header = + { + .bLength = USB_DEV_DESC_LEN, + .bDescriptorType = USB_DESCTYPE_DEV, + }, + .bcdUSB = 0x0200U, + .bDeviceClass = 0x00U, + .bDeviceSubClass = 0x00U, + .bDeviceProtocol = 0x00U, + .bMaxPacketSize0 = USBD_EP0_MAX_SIZE, + .idVendor = USBD_VID, + .idProduct = USBD_PID, + .bcdDevice = 0x0100U, + .iManufacturer = STR_IDX_MFC, + .iProduct = STR_IDX_PRODUCT, + .iSerialNumber = STR_IDX_SERIAL, + .bNumberConfigurations = USBD_CFG_MAX_NUM, +}; + +/* USB device configure descriptor */ +usb_hid_desc_config_set custom_hid_config_desc = +{ + .config = + { + .header = + { + .bLength = sizeof(usb_desc_config), + .bDescriptorType = USB_DESCTYPE_CONFIG + }, + .wTotalLength = DESC_LEN_CONFIG, + .bNumInterfaces = 0x01U, + .bConfigurationValue = 0x01U, + .iConfiguration = 0x00U, + .bmAttributes = 0x80U, + .bMaxPower = 0x32U + }, + + .hid_itf = + { + .header = + { + .bLength = sizeof(usb_desc_itf), + .bDescriptorType = USB_DESCTYPE_ITF + }, + .bInterfaceNumber = 0x00U, + .bAlternateSetting = 0x00U, + .bNumEndpoints = 0x02U, + .bInterfaceClass = USB_HID_CLASS, + .bInterfaceSubClass = 0x00U, + .bInterfaceProtocol = 0x00U, + .iInterface = 0x00U + }, + + .hid_vendor = + { + .header = + { + .bLength = sizeof(usb_desc_hid), + .bDescriptorType = USB_DESCTYPE_HID + }, + .bcdHID = 0x0111U, + .bCountryCode = 0x00U, + .bNumDescriptors = 0x01U, + .bDescriptorType = USB_DESCTYPE_REPORT, + .wDescriptorLength = DESC_LEN_REPORT, + }, + + .hid_epin = + { + .header = + { + .bLength = sizeof(usb_desc_ep), + .bDescriptorType = USB_DESCTYPE_EP + }, + .bEndpointAddress = CUSTOMHID_IN_EP, + .bmAttributes = USB_EP_ATTR_INT, + .wMaxPacketSize = CUSTOMHID_IN_PACKET, + .bInterval = 0x20U + }, + + .hid_epout = + { + .header = + { + .bLength = sizeof(usb_desc_ep), + .bDescriptorType = USB_DESCTYPE_EP + }, + .bEndpointAddress = CUSTOMHID_OUT_EP, + .bmAttributes = USB_EP_ATTR_INT, + .wMaxPacketSize = CUSTOMHID_OUT_PACKET, + .bInterval = 0x20U + } +}; + +/* USB language ID descriptor */ +static usb_desc_LANGID usbd_language_id_desc = +{ + .header = + { + .bLength = sizeof(usb_desc_LANGID), + .bDescriptorType = USB_DESCTYPE_STR + }, + .wLANGID = ENG_LANGID +}; + +/* USB manufacture string */ +static usb_desc_str manufacturer_string = +{ + .header = + { + .bLength = USB_STRING_LEN(10U), + .bDescriptorType = USB_DESCTYPE_STR, + }, + .unicode_string = {'G', 'i', 'g', 'a', 'D', 'e', 'v', 'i', 'c', 'e'} +}; + +/* USB product string */ +static usb_desc_str product_string = +{ + .header = + { + .bLength = USB_STRING_LEN(14U), + .bDescriptorType = USB_DESCTYPE_STR, + }, + .unicode_string = {'G', 'D', '3', '2', '-', 'C', 'u', 's', 't', 'o', 'm', 'H', 'I', 'D'} +}; + +/* USB serial string */ +static usb_desc_str serial_string = +{ + .header = + { + .bLength = USB_STRING_LEN(12U), + .bDescriptorType = USB_DESCTYPE_STR, + } +}; + +/* USB string descriptor set */ +static uint8_t* usbd_hid_strings[] = +{ + [STR_IDX_LANGID] = (uint8_t *)&usbd_language_id_desc, + [STR_IDX_MFC] = (uint8_t *)&manufacturer_string, + [STR_IDX_PRODUCT] = (uint8_t *)&product_string, + [STR_IDX_SERIAL] = (uint8_t *)&serial_string +}; + +usb_desc custom_hid_desc = { + .dev_desc = (uint8_t *)&custom_hid_dev_desc, + .config_desc = (uint8_t *)&custom_hid_config_desc, + .strings = usbd_hid_strings +}; + +/* local function prototypes ('static') */ +static uint8_t custom_hid_init (usb_dev *udev, uint8_t config_index); +static uint8_t custom_hid_deinit (usb_dev *udev, uint8_t config_index); +static uint8_t custom_hid_req_handler (usb_dev *udev, usb_req *req); +static void custom_hid_data_in (usb_dev *udev, uint8_t ep_num); +static void custom_hid_data_out (usb_dev *udev, uint8_t ep_num); + +usb_class custom_hid_class = { + .req_cmd = 0xFFU, + + .init = custom_hid_init, + .deinit = custom_hid_deinit, + .req_process = custom_hid_req_handler, + .data_in = custom_hid_data_in, + .data_out = custom_hid_data_out +}; + +const uint8_t customhid_report_descriptor[DESC_LEN_REPORT] = +{ + 0x06, 0x00, 0xFF, /* USAGE_PAGE (Vendor Defined: 0xFF00) */ + 0x09, 0x00, /* USAGE (Custom Device) */ + 0xa1, 0x01, /* COLLECTION (Application) */ + + /* led 1 */ + 0x85, 0x11, /* REPORT_ID (0x11) */ + 0x09, 0x01, /* USAGE (LED 1) */ + 0x15, 0x00, /* LOGICAL_MINIMUM (0) */ + 0x25, 0x01, /* LOGICAL_MAXIMUM (1) */ + 0x75, 0x08, /* REPORT_SIZE (8) */ + 0x95, 0x01, /* REPORT_COUNT (1) */ + 0x91, 0x82, /* OUTPUT (Data,Var,Abs,Vol) */ + + /* led 2 */ + 0x85, 0x12, /* REPORT_ID (0x12) */ + 0x09, 0x02, /* USAGE (LED 2) */ + 0x15, 0x00, /* LOGICAL_MINIMUM (0) */ + 0x25, 0x01, /* LOGICAL_MAXIMUM (1) */ + 0x75, 0x08, /* REPORT_SIZE (8) */ + 0x95, 0x01, /* REPORT_COUNT (1) */ + 0x91, 0x82, /* OUTPUT (Data,Var,Abs,Vol) */ + + /* led 3 */ + 0x85, 0x13, /* REPORT_ID (0x13) */ + 0x09, 0x03, /* USAGE (LED 3) */ + 0x15, 0x00, /* LOGICAL_MINIMUM (0) */ + 0x25, 0x01, /* LOGICAL_MAXIMUM (1) */ + 0x75, 0x08, /* REPORT_SIZE (8) */ + 0x95, 0x01, /* REPORT_COUNT (1) */ + 0x91, 0x82, /* OUTPUT (Data,Var,Abs,Vol) */ + + /* led 4 */ + 0x85, 0x14, /* REPORT_ID (0x14) */ + 0x09, 0x04, /* USAGE (LED 4) */ + 0x15, 0x00, /* LOGICAL_MINIMUM (0) */ + 0x25, 0x01, /* LOGICAL_MAXIMUM (1) */ + 0x75, 0x08, /* REPORT_SIZE (8) */ + 0x95, 0x01, /* REPORT_COUNT (1) */ + 0x91, 0x82, /* OUTPUT (Data,Var,Abs,Vol) */ + + /* wakeup key */ + 0x85, 0x15, /* REPORT_ID (0x15) */ + 0x09, 0x05, /* USAGE (Push Button) */ + 0x15, 0x00, /* LOGICAL_MINIMUM (0) */ + 0x25, 0x01, /* LOGICAL_MAXIMUM (1) */ + 0x75, 0x01, /* REPORT_SIZE (1) */ + 0x81, 0x02, /* INPUT (Data,Var,Abs,Vol) */ + + 0x75, 0x07, /* REPORT_SIZE (7) */ + 0x81, 0x03, /* INPUT (Cnst,Var,Abs,Vol) */ + + /* tamper key */ + 0x85, 0x16, /* REPORT_ID (0x16) */ + 0x09, 0x06, /* USAGE (Push Button) */ + 0x15, 0x00, /* LOGICAL_MINIMUM (0) */ + 0x25, 0x01, /* LOGICAL_MAXIMUM (1) */ + 0x75, 0x01, /* REPORT_SIZE (1) */ + 0x81, 0x02, /* INPUT (Data,Var,Abs,Vol) */ + + 0x75, 0x07, /* REPORT_SIZE (7) */ + 0x81, 0x03, /* INPUT (Cnst,Var,Abs,Vol) */ + + 0xc0 /* END_COLLECTION */ +}; + +/*! + \brief register HID interface operation functions + \param[in] udev: pointer to USB device instance + \param[in] hid_fop: HID operation functions structure + \param[out] none + \retval USB device operation status +*/ +uint8_t custom_hid_itfop_register (usb_dev *udev, hid_fop_handler *hid_fop) +{ + if (NULL != hid_fop) { + udev->user_data = hid_fop; + + return USBD_OK; + } + + return USBD_FAIL; +} + +/*! + \brief send custom HID report + \param[in] udev: pointer to USB device instance + \param[in] report: pointer to HID report + \param[in] len: data length + \param[out] none + \retval USB device operation status +*/ +uint8_t custom_hid_report_send (usb_dev *udev, uint8_t *report, uint16_t len) +{ + usbd_ep_send (udev, CUSTOMHID_IN_EP, report, len); + + return USBD_OK; +} + +/*! + \brief initialize the HID device + \param[in] udev: pointer to USB device instance + \param[in] config_index: configuration index + \param[out] none + \retval USB device operation status +*/ +static uint8_t custom_hid_init (usb_dev *udev, uint8_t config_index) +{ + static custom_hid_handler hid_handler; + + memset((void *)&hid_handler, 0, sizeof(custom_hid_handler)); + + /* initialize the data endpoints */ + usbd_ep_init(udev, EP_BUF_SNG, HID_TX_ADDR, &(custom_hid_config_desc.hid_epin)); + usbd_ep_init(udev, EP_BUF_SNG, HID_RX_ADDR, &(custom_hid_config_desc.hid_epout)); + + usbd_ep_recev (udev, CUSTOMHID_OUT_EP, hid_handler.data, 2U); + + udev->ep_transc[EP_ID(CUSTOMHID_IN_EP)][TRANSC_IN] = custom_hid_class.data_in; + udev->ep_transc[EP_ID(CUSTOMHID_OUT_EP)][TRANSC_OUT] = custom_hid_class.data_out; + + udev->class_data[CUSTOM_HID_INTERFACE] = (void *)&hid_handler; + + if (udev->user_data != NULL) { + for (uint8_t i = 0U; i < MAX_PERIPH_NUM; i++) { + if (((hid_fop_handler *)udev->user_data)->periph_config[i] != NULL) { + ((hid_fop_handler *)udev->user_data)->periph_config[i](); + } + } + } + + return USBD_OK; +} + +/*! + \brief de-initialize the HID device + \param[in] udev: pointer to USB device instance + \param[in] config_index: configuration index + \param[out] none + \retval USB device operation status +*/ +static uint8_t custom_hid_deinit (usb_dev *udev, uint8_t config_index) +{ + /* deinitialize HID endpoints */ + usbd_ep_deinit(udev, CUSTOMHID_IN_EP); + usbd_ep_deinit(udev, CUSTOMHID_OUT_EP); + + return USBD_OK; +} + +/*! + \brief handle the HID class-specific requests + \param[in] udev: pointer to USB device instance + \param[in] req: device class-specific request + \param[out] none + \retval USB device operation status +*/ +static uint8_t custom_hid_req_handler (usb_dev *udev, usb_req *req) +{ + uint8_t status = REQ_NOTSUPP; + + custom_hid_handler *hid = (custom_hid_handler *)udev->class_data[CUSTOM_HID_INTERFACE]; + + switch (req->bRequest) { + case USB_GET_DESCRIPTOR: + if (USB_DESCTYPE_REPORT == (req->wValue >> 8)) { + usb_transc_config(&udev->transc_in[0], + (uint8_t *)customhid_report_descriptor, + USB_MIN(DESC_LEN_REPORT, req->wLength), + 0U); + + status = REQ_SUPP; + } + break; + + case GET_REPORT: + if (2U == req->wLength) { + usb_transc_config(&udev->transc_in[0], hid->data, 2U, 0U); + + status = REQ_SUPP; + } + break; + + case GET_IDLE: + usb_transc_config(&udev->transc_in[0], (uint8_t *)&hid->idlestate, 1U, 0U); + + status = REQ_SUPP; + break; + + case GET_PROTOCOL: + usb_transc_config(&udev->transc_in[0], (uint8_t *)&hid->protocol, 1U, 0U); + + status = REQ_SUPP; + break; + + case SET_REPORT: + hid->reportID = (uint8_t)(req->wValue); + + usb_transc_config(&udev->transc_out[0], hid->data, req->wLength, 0U); + + status = REQ_SUPP; + break; + + case SET_IDLE: + hid->idlestate = (uint8_t)(req->wValue >> 8); + + status = REQ_SUPP; + break; + + case SET_PROTOCOL: + hid->protocol = (uint8_t)(req->wValue); + + status = REQ_SUPP; + break; + + default: + break; + } + + return status; +} + +/*! + \brief handle custom HID data in transaction + \param[in] udev: pointer to USB device instance + \param[in] ep_num: endpoint number + \param[out] none + \retval none +*/ +static void custom_hid_data_in (usb_dev *udev, uint8_t ep_num) +{ + return; +} + +/*! + \brief handle custom HID data out transaction + \param[in] udev: pointer to USB device instance + \param[in] ep_num: endpoint number + \param[out] none + \retval none +*/ +static void custom_hid_data_out (usb_dev *udev, uint8_t ep_num) +{ + custom_hid_handler *hid = (custom_hid_handler *)udev->class_data[CUSTOM_HID_INTERFACE]; + + if (CUSTOMHID_OUT_EP == ep_num){ + switch (hid->data[0]){ + case 0x11: + if (RESET != hid->data[1]) { + /* turn on led5 */ + gd_eval_led_on(LED5); + } else { + gd_eval_led_off(LED5); + } + break; + case 0x12: + if (RESET != hid->data[1]) { + gd_eval_led_on(LED2); + } else { + gd_eval_led_off(LED2); + } + break; + case 0x13: + if (RESET != hid->data[1]) { + gd_eval_led_on(LED3); + } else { + gd_eval_led_off(LED3); + } + break; + case 0x14: + if (RESET != hid->data[1]) { + gd_eval_led_on(LED4); + } else { + gd_eval_led_off(LED4); + } + break; + default: + /* turn off all leds */ + gd_eval_led_off(LED2); + gd_eval_led_off(LED3); + gd_eval_led_off(LED4); + gd_eval_led_off(LED5); + break; + } + + usbd_ep_recev(udev, CUSTOMHID_IN_EP, hid->data, 2U); + } +} diff --git a/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbd_library/class/device/hid/Source/standard_hid_core.c b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbd_library/class/device/hid/Source/standard_hid_core.c new file mode 100644 index 0000000000..78c878ac9d --- /dev/null +++ b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbd_library/class/device/hid/Source/standard_hid_core.c @@ -0,0 +1,427 @@ +/*! + \file standard_hid_core.c + \brief HID class driver + + \version 2020-07-17, V3.0.0, firmware for GD32F10x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "usbd_transc.h" +#include "standard_hid_core.h" +#include + +#define USBD_VID 0x28E9U +#define USBD_PID 0x0380U + +/* Note:it should use the C99 standard when compiling the below codes */ +/* USB standard device descriptor */ +usb_desc_dev hid_dev_desc = +{ + .header = + { + .bLength = USB_DEV_DESC_LEN, + .bDescriptorType = USB_DESCTYPE_DEV + }, +#ifdef LPM_ENABLED + .bcdUSB = 0x0201U, +#else + .bcdUSB = 0x0200U, +#endif /* LPM_ENABLED */ + .bDeviceClass = 0x00U, + .bDeviceSubClass = 0x00U, + .bDeviceProtocol = 0x00U, + .bMaxPacketSize0 = USBD_EP0_MAX_SIZE, + .idVendor = USBD_VID, + .idProduct = USBD_PID, + .bcdDevice = 0x0100U, + .iManufacturer = STR_IDX_MFC, + .iProduct = STR_IDX_PRODUCT, + .iSerialNumber = STR_IDX_SERIAL, + .bNumberConfigurations = USBD_CFG_MAX_NUM +}; + +#ifdef LPM_ENABLED + +/* BOS descriptor */ +uint8_t USBD_BOSDesc[USB_BOS_DESC_LEN] = +{ + 0x05, + USB_DESCTYPE_BOS, + 0x0C, + 0x00, + 0x01, /* 1 device capability descriptor */ + + /* device capability*/ + 0x07, + USB_DEVICE_CAPABITY, + 0x02, + 0x06, /* LPM capability bit set */ + 0x00, + 0x00, + 0x00 +}; + +#endif /* LPM_ENABLED */ + +usb_hid_desc_config_set hid_config_desc = +{ + .config = + { + .header = + { + .bLength = sizeof(usb_desc_config), + .bDescriptorType = USB_DESCTYPE_CONFIG + }, + .wTotalLength = USB_HID_CONFIG_DESC_LEN, + .bNumInterfaces = 0x01U, + .bConfigurationValue = 0x01U, + .iConfiguration = 0x00U, + .bmAttributes = 0xA0U, + .bMaxPower = 0x32U + }, + + .hid_itf = + { + .header = + { + .bLength = sizeof(usb_desc_itf), + .bDescriptorType = USB_DESCTYPE_ITF + }, + .bInterfaceNumber = 0x00U, + .bAlternateSetting = 0x00U, + .bNumEndpoints = 0x01U, + .bInterfaceClass = USB_HID_CLASS, + .bInterfaceSubClass = USB_HID_SUBCLASS_BOOT_ITF, + .bInterfaceProtocol = USB_HID_PROTOCOL_KEYBOARD, + .iInterface = 0x00U + }, + + .hid_vendor = + { + .header = + { + .bLength = sizeof(usb_desc_hid), + .bDescriptorType = USB_DESCTYPE_HID + }, + .bcdHID = 0x0111U, + .bCountryCode = 0x00U, + .bNumDescriptors = 0x01U, + .bDescriptorType = USB_DESCTYPE_REPORT, + .wDescriptorLength = USB_HID_REPORT_DESC_LEN, + }, + + .hid_epin = + { + .header = + { + .bLength = sizeof(usb_desc_ep), + .bDescriptorType = USB_DESCTYPE_EP + }, + .bEndpointAddress = HID_IN_EP, + .bmAttributes = USB_EP_ATTR_INT, + .wMaxPacketSize = HID_IN_PACKET, + .bInterval = 0x40U + } +}; + +/* USB language ID Descriptor */ +static usb_desc_LANGID usbd_language_id_desc = +{ + .header = + { + .bLength = sizeof(usb_desc_LANGID), + .bDescriptorType = USB_DESCTYPE_STR + }, + .wLANGID = ENG_LANGID +}; + +/* USB manufacture string */ +static usb_desc_str manufacturer_string = +{ + .header = + { + .bLength = USB_STRING_LEN(10U), + .bDescriptorType = USB_DESCTYPE_STR, + }, + .unicode_string = {'G', 'i', 'g', 'a', 'D', 'e', 'v', 'i', 'c', 'e'} +}; + +/* USB product string */ +static usb_desc_str product_string = +{ + .header = + { + .bLength = USB_STRING_LEN(17U), + .bDescriptorType = USB_DESCTYPE_STR, + }, + .unicode_string = {'G', 'D', '3', '2', '-', 'U', 'S', 'B', '_', 'K', 'e', 'y', 'b', 'o', 'a', 'r', 'd'} +}; + +/* USB serial string */ +static usb_desc_str serial_string = +{ + .header = + { + .bLength = USB_STRING_LEN(12U), + .bDescriptorType = USB_DESCTYPE_STR, + } +}; + +/* USB string descriptor set */ +static uint8_t* usbd_hid_strings[] = +{ + [STR_IDX_LANGID] = (uint8_t *)&usbd_language_id_desc, + [STR_IDX_MFC] = (uint8_t *)&manufacturer_string, + [STR_IDX_PRODUCT] = (uint8_t *)&product_string, + [STR_IDX_SERIAL] = (uint8_t *)&serial_string +}; + +usb_desc hid_desc = { +#ifdef LPM_ENABLED + .bos_desc = (uint8_t *)&USBD_BOSDesc, +#endif /* LPM_ENABLED */ + .dev_desc = (uint8_t *)&hid_dev_desc, + .config_desc = (uint8_t *)&hid_config_desc, + .strings = usbd_hid_strings +}; + +/* local function prototypes ('static') */ +static uint8_t hid_init (usb_dev *udev, uint8_t config_index); +static uint8_t hid_deinit (usb_dev *udev, uint8_t config_index); +static uint8_t hid_req_handler (usb_dev *udev, usb_req *req); +static void hid_data_in_handler (usb_dev *udev, uint8_t ep_num); + +usb_class hid_class = { + .init = hid_init, + .deinit = hid_deinit, + .req_process = hid_req_handler, + .data_in = hid_data_in_handler +}; + +const uint8_t hid_report_desc[USB_HID_REPORT_DESC_LEN] = +{ + 0x05, 0x01, /* USAGE_PAGE (Generic Desktop) */ + 0x09, 0x06, /* USAGE (Keyboard) */ + 0xa1, 0x01, /* COLLECTION (Application) */ + + 0x05, 0x07, /* USAGE_PAGE (Keyboard/Keypad) */ + 0x19, 0xe0, /* USAGE_MINIMUM (Keyboard LeftControl) */ + 0x29, 0xe7, /* USAGE_MAXIMUM (Keyboard Right GUI) */ + 0x15, 0x00, /* LOGICAL_MINIMUM (0) */ + 0x25, 0x01, /* LOGICAL_MAXIMUM (1) */ + 0x95, 0x08, /* REPORT_COUNT (8) */ + 0x75, 0x01, /* REPORT_SIZE (1) */ + 0x81, 0x02, /* INPUT (Data,Var,Abs) */ + + 0x95, 0x01, /* REPORT_COUNT (1) */ + 0x75, 0x08, /* REPORT_SIZE (8) */ + 0x81, 0x03, /* INPUT (Cnst,Var,Abs) */ + + 0x95, 0x06, /* REPORT_COUNT (6) */ + 0x75, 0x08, /* REPORT_SIZE (8) */ + 0x15, 0x00, /* LOGICAL_MINIMUM (0) */ + 0x26, 0xFF, 0x00, /* LOGICAL_MAXIMUM (255) */ + 0x05, 0x07, /* USAGE_PAGE (Keyboard/Keypad) */ + 0x19, 0x00, /* USAGE_MINIMUM (Reserved (no event indicated)) */ + 0x29, 0x65, /* USAGE_MAXIMUM (Keyboard Application) */ + 0x81, 0x00, /* INPUT (Data,Ary,Abs) */ + + 0xc0 /* END_COLLECTION */ +}; + +/*! + \brief register HID interface operation functions + \param[in] udev: pointer to USB device instance + \param[in] hid_fop: HID operation functions structure + \param[out] none + \retval USB device operation status +*/ +uint8_t hid_itfop_register (usb_dev *udev, hid_fop_handler *hid_fop) +{ + if (NULL != hid_fop) { + udev->user_data = (void *)hid_fop; + + return USBD_OK; + } + + return USBD_FAIL; +} + +/*! + \brief send HID report + \param[in] udev: pointer to USB device instance + \param[in] report: pointer to HID report + \param[in] len: data length + \param[out] none + \retval USB device operation status +*/ +uint8_t hid_report_send (usb_dev *udev, uint8_t *report, uint16_t len) +{ + standard_hid_handler *hid = (standard_hid_handler *)udev->class_data[USBD_HID_INTERFACE]; + + /* check if USB is configured */ + hid->prev_transfer_complete = 0U; + + usbd_ep_send(udev, HID_IN_EP, report, len); + + return USBD_OK; +} + +/*! + \brief initialize the HID device + \param[in] udev: pointer to USB device instance + \param[in] config_index: configuration index + \param[out] none + \retval USB device operation status +*/ +static uint8_t hid_init (usb_dev *udev, uint8_t config_index) +{ + static standard_hid_handler hid_handler; + + memset((void *)&hid_handler, 0, sizeof(standard_hid_handler)); + + /* initialize TX endpoint */ + usbd_ep_init(udev, EP_BUF_SNG, INT_TX_ADDR, &(hid_config_desc.hid_epin)); + + udev->ep_transc[EP_ID(HID_IN_EP)][TRANSC_IN] = hid_class.data_in; + + hid_handler.prev_transfer_complete = 1U; + + udev->class_data[USBD_HID_INTERFACE] = (void *)&hid_handler; + + if (NULL != udev->user_data) { + ((hid_fop_handler *)udev->user_data)->hid_itf_config(); + } + + return USBD_OK; +} + +/*! + \brief deinitialize the HID device + \param[in] udev: pointer to USB device instance + \param[in] config_index: configuration index + \param[out] none + \retval USB device operation status +*/ +static uint8_t hid_deinit (usb_dev *udev, uint8_t config_index) +{ + /* deinitialize HID endpoints */ + usbd_ep_deinit (udev, HID_IN_EP); + + return USBD_OK; +} + +/*! + \brief handle the HID class-specific requests + \param[in] udev: pointer to USB device instance + \param[in] req: device class-specific request + \param[out] none + \retval USB device operation status +*/ +static uint8_t hid_req_handler (usb_dev *udev, usb_req *req) +{ + uint8_t status = REQ_NOTSUPP; + + standard_hid_handler *hid = (standard_hid_handler *)udev->class_data[USBD_HID_INTERFACE]; + + switch (req->bRequest) { + case GET_REPORT: + /* no use for this driver */ + break; + + case GET_IDLE: + usb_transc_config(&udev->transc_in[0U], (uint8_t *)&hid->idle_state, 1U, 0U); + + status = REQ_SUPP; + break; + + case GET_PROTOCOL: + usb_transc_config(&udev->transc_in[0U], (uint8_t *)&hid->protocol, 1U, 0U); + + status = REQ_SUPP; + break; + + case SET_REPORT: + /* no use for this driver */ + break; + + case SET_IDLE: + hid->idle_state = (uint8_t)(req->wValue >> 8); + + status = REQ_SUPP; + break; + + case SET_PROTOCOL: + hid->protocol = (uint8_t)(req->wValue); + + status = REQ_SUPP; + break; + + case USB_GET_DESCRIPTOR: + if (USB_DESCTYPE_REPORT == (req->wValue >> 8)) { + usb_transc_config(&udev->transc_in[0U], + (uint8_t *)hid_report_desc, + USB_MIN(USB_HID_REPORT_DESC_LEN, req->wLength), + 0U); + + status = REQ_SUPP; + } else if (USB_DESCTYPE_HID == (req->wValue >> 8U)) { + usb_transc_config(&udev->transc_in[0U], + (uint8_t *)(&(hid_config_desc.hid_vendor)), + USB_MIN(9U, req->wLength), + 0U); + } + break; + + default: + break; + } + + return status; +} + +/*! + \brief handle data stage in DATA IN transaction + \param[in] udev: pointer to USB device instance + \param[in] ep_num: endpoint identifier + \param[out] none + \retval none +*/ +static void hid_data_in_handler (usb_dev *udev, uint8_t ep_num) +{ + standard_hid_handler *hid = (standard_hid_handler *)udev->class_data[USBD_HID_INTERFACE]; + + if (hid->data[2]) { + hid->data[2] = 0x00U; + + usbd_ep_send(udev, HID_IN_EP, hid->data, HID_IN_PACKET); + } else { + hid->prev_transfer_complete = 1U; + } +} diff --git a/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbd_library/class/device/iap/Include/usb_iap_core.h b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbd_library/class/device/iap/Include/usb_iap_core.h new file mode 100644 index 0000000000..e1b958ecb3 --- /dev/null +++ b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbd_library/class/device/iap/Include/usb_iap_core.h @@ -0,0 +1,82 @@ +/*! + \file usb_iap_core.h + \brief the header file of IAP driver + + \version 2020-07-17, V3.0.0, firmware for GD32F10x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef __USB_IAP_CORE_H +#define __USB_IAP_CORE_H + +#include "usbd_enum.h" +#include "usb_hid.h" + +#define USB_DESC_LEN_IAP_REPORT 35U +#define USB_DESC_LEN_IAP_CONFIG_SET 41U + +/* special commands with download request */ +#define IAP_OPTION_BYTE 0x01U +#define IAP_ERASE 0x02U +#define IAP_DNLOAD 0x03U +#define IAP_LEAVE 0x04U +#define IAP_GETBIN_ADDRESS 0x05U + +typedef void (*app_func) (void); + +typedef struct +{ + uint8_t report_buf[IAP_OUT_PACKET + 1U]; + uint8_t option_byte[IAP_IN_PACKET]; + + /* state machine variables */ + uint8_t dev_status[IAP_IN_PACKET]; + uint8_t bin_addr[IAP_IN_PACKET]; + + uint8_t reportID; + uint8_t flag; + + uint32_t protocol; + uint32_t idlestate; + + uint16_t transfer_times; + uint16_t page_count; + uint16_t lps; /* last packet size */ + uint32_t file_length; + uint32_t base_address; +} usbd_iap_handler; + +extern usb_desc iap_desc; +extern usb_class iap_class; + +/* function declarations */ +/* send IAP report */ +uint8_t iap_report_send(usb_dev *udev, uint8_t *report, uint16_t len); + +#endif /* __USB_IAP_CORE_H */ diff --git a/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbd_library/class/device/iap/Source/usb_iap_core.c b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbd_library/class/device/iap/Source/usb_iap_core.c new file mode 100644 index 0000000000..fe41b32434 --- /dev/null +++ b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbd_library/class/device/iap/Source/usb_iap_core.c @@ -0,0 +1,596 @@ +/*! + \file usb_iap_core.c + \brief IAP driver + + \version 2020-07-17, V3.0.0, firmware for GD32F10x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "usbd_transc.h" +#include "usb_iap_core.h" +#include + +#define USBD_VID 0x28E9U +#define USBD_PID 0x028BU + +/* Note:it should use the C99 standard when compiling the below codes */ +/* USB standard device descriptor */ +usb_desc_dev iap_dev_desc = +{ + .header = + { + .bLength = USB_DEV_DESC_LEN, + .bDescriptorType = USB_DESCTYPE_DEV + }, + .bcdUSB = 0x0200U, + .bDeviceClass = 0x00U, + .bDeviceSubClass = 0x00U, + .bDeviceProtocol = 0x00U, + .bMaxPacketSize0 = USBD_EP0_MAX_SIZE, + .idVendor = USBD_VID, + .idProduct = USBD_PID, + .bcdDevice = 0x0100U, + .iManufacturer = STR_IDX_MFC, + .iProduct = STR_IDX_PRODUCT, + .iSerialNumber = STR_IDX_SERIAL, + .bNumberConfigurations = USBD_CFG_MAX_NUM +}; + +/* USB device configure descriptor */ +usb_hid_desc_config_set iap_config_desc = +{ + .config = + { + .header = + { + .bLength = sizeof(usb_desc_config), + .bDescriptorType = USB_DESCTYPE_CONFIG + }, + .wTotalLength = USB_DESC_LEN_IAP_CONFIG_SET, + .bNumInterfaces = 0x01U, + .bConfigurationValue = 0x01U, + .iConfiguration = 0x00U, + .bmAttributes = 0x80U, + .bMaxPower = 0x32U + }, + + .hid_itf = + { + .header = + { + .bLength = sizeof(usb_desc_itf), + .bDescriptorType = USB_DESCTYPE_ITF + }, + .bInterfaceNumber = 0x00U, + .bAlternateSetting = 0x00U, + .bNumEndpoints = 0x02U, + .bInterfaceClass = USB_HID_CLASS, + .bInterfaceSubClass = 0x00U, + .bInterfaceProtocol = 0x01U, + .iInterface = 0x00U + }, + + .hid_vendor = + { + .header = + { + .bLength = sizeof(usb_desc_hid), + .bDescriptorType = USB_DESCTYPE_HID + }, + .bcdHID = 0x0111U, + .bCountryCode = 0x00U, + .bNumDescriptors = 0x01U, + .bDescriptorType = USB_DESCTYPE_REPORT, + .wDescriptorLength = USB_DESC_LEN_IAP_REPORT, + }, + + .hid_epin = + { + .header = + { + .bLength = sizeof(usb_desc_ep), + .bDescriptorType = USB_DESCTYPE_EP + }, + .bEndpointAddress = IAP_IN_EP, + .bmAttributes = USB_EP_ATTR_INT, + .wMaxPacketSize = IAP_IN_PACKET, + .bInterval = 0x01U + }, + + .hid_epout = + { + .header = + { + .bLength = sizeof(usb_desc_ep), + .bDescriptorType = USB_DESCTYPE_EP + }, + .bEndpointAddress = IAP_OUT_EP, + .bmAttributes = USB_EP_ATTR_INT, + .wMaxPacketSize = IAP_OUT_PACKET, + .bInterval = 0x01U + } +}; + +/* USB language ID Descriptor */ +usb_desc_LANGID usbd_language_id_desc = +{ + .header = + { + .bLength = sizeof(usb_desc_LANGID), + .bDescriptorType = USB_DESCTYPE_STR + }, + .wLANGID = ENG_LANGID +}; + +/* USB manufacture string */ +static usb_desc_str manufacturer_string = +{ + .header = + { + .bLength = USB_STRING_LEN(10U), + .bDescriptorType = USB_DESCTYPE_STR, + }, + .unicode_string = {'G', 'i', 'g', 'a', 'D', 'e', 'v', 'i', 'c', 'e'} +}; + +/* USB product string */ +static usb_desc_str product_string = +{ + .header = + { + .bLength = USB_STRING_LEN(12U), + .bDescriptorType = USB_DESCTYPE_STR, + }, + .unicode_string = {'G', 'D', '3', '2', '-', 'U', 'S', 'B', '_', 'I', 'A', 'P'} +}; + +/* USB serial string */ +static usb_desc_str serial_string = +{ + .header = + { + .bLength = USB_STRING_LEN(2U), + .bDescriptorType = USB_DESCTYPE_STR, + } +}; + +/* USB string descriptor set */ +uint8_t* usbd_iap_strings[] = +{ + [STR_IDX_LANGID] = (uint8_t *)&usbd_language_id_desc, + [STR_IDX_MFC] = (uint8_t *)&manufacturer_string, + [STR_IDX_PRODUCT] = (uint8_t *)&product_string, + [STR_IDX_SERIAL] = (uint8_t *)&serial_string +}; + +usb_desc iap_desc = { + .dev_desc = (uint8_t *)&iap_dev_desc, + .config_desc = (uint8_t *)&iap_config_desc, + .strings = usbd_iap_strings +}; + +/* local function prototypes ('static') */ +static uint8_t iap_init (usb_dev *udev, uint8_t config_index); +static uint8_t iap_deinit (usb_dev *udev, uint8_t config_index); +static uint8_t iap_req_handler (usb_dev *udev, usb_req *req); +static void iap_data_out (usb_dev *udev, uint8_t ep_num); + +usb_class iap_class = { + .init = iap_init, + .deinit = iap_deinit, + .req_process = iap_req_handler, + .data_out = iap_data_out +}; + +/* USB custom HID device report descriptor */ +const uint8_t iap_report_desc[USB_DESC_LEN_IAP_REPORT] = +{ + 0x05, 0x01, /* USAGE_PAGE (Generic Desktop) */ + 0x09, 0x00, /* USAGE (Custom Device) */ + 0xa1, 0x01, /* COLLECTION (Application) */ + + /* IAP command and data */ + 0x85, 0x01, /* REPORT_ID (0x01) */ + 0x09, 0x01, /* USAGE (IAP command) */ + 0x15, 0x00, /* LOGICAL_MINIMUM (0) */ + 0x25, 0xff, /* LOGICAL_MAXIMUM (255) */ + 0x75, 0x08, /* REPORT_SIZE (8) */ + 0x95, 0x3f, /* REPORT_COUNT (63) */ + 0x91, 0x82, /* OUTPUT (Data,Var,Abs,Vol) */ + + /* device status and option byte */ + 0x85, 0x02, /* REPORT_ID (0x02) */ + 0x09, 0x02, /* USAGE (Status and option byte) */ + 0x15, 0x00, /* LOGICAL_MINIMUM (0) */ + 0x25, 0xff, /* LOGICAL_MAXIMUM (255) */ + 0x75, 0x08, /* REPORT_SIZE (8) */ + 0x95, 0x10, /* REPORT_COUNT (16) */ + 0x81, 0x82, /* INPUT (Data,Var,Abs,Vol) */ + + 0xc0 /* END_COLLECTION */ +}; + +/* IAP requests management functions */ +static void iap_req_erase (usb_dev *udev); +static void iap_req_dnload (usb_dev *udev); +static void iap_req_optionbyte(usb_dev *udev); +static void iap_req_leave (usb_dev *udev); +static void iap_address_send (usb_dev *udev); +static void iap_data_write (uint8_t *data, uint32_t addr, uint32_t len); + +/*! + \brief initialize the HID device + \param[in] udev: pointer to USB device instance + \param[in] config_index: configuration index + \param[out] none + \retval USB device operation status +*/ +static uint8_t iap_init (usb_dev *udev, uint8_t config_index) +{ + static usbd_iap_handler iap_handler; + + /* initialize TX endpoint */ + usbd_ep_init(udev, EP_BUF_SNG, INT_TX_ADDR, &(iap_config_desc.hid_epin)); + + /* initialize RX endpoint */ + usbd_ep_init(udev, EP_BUF_SNG, INT_RX_ADDR, &(iap_config_desc.hid_epout)); + + /* unlock the internal flash */ + fmc_unlock(); + + memset((void *)&iap_handler, 0, sizeof(usbd_iap_handler)); + + /* prepare receive Data */ + usbd_ep_recev(udev, IAP_OUT_EP, iap_handler.report_buf, IAP_OUT_PACKET); + + udev->ep_transc[EP_ID(IAP_OUT_EP)][TRANSC_OUT] = iap_class.data_out; + + iap_handler.base_address = APP_LOADED_ADDR; + + udev->class_data[USBD_IAP_INTERFACE] = (void *)&iap_handler; + + return USBD_OK; +} + +/*! + \brief deinitialize the HID device + \param[in] udev: pointer to USB device instance + \param[in] config_index: configuration index + \param[out] none + \retval USB device operation status +*/ +static uint8_t iap_deinit (usb_dev *udev, uint8_t config_index) +{ + /* deinitialize HID endpoints */ + usbd_ep_deinit (udev, IAP_IN_EP); + usbd_ep_deinit (udev, IAP_OUT_EP); + + /* lock the internal flash */ + fmc_lock(); + + return USBD_OK; +} + +/*! + \brief handle the HID class-specific requests + \param[in] udev: pointer to USB device instance + \param[in] req: device class-specific request + \param[out] none + \retval USB device operation status +*/ +static uint8_t iap_req_handler (usb_dev *udev, usb_req *req) +{ + uint8_t status = REQ_NOTSUPP; + + usbd_iap_handler *iap = (usbd_iap_handler *)udev->class_data[USBD_IAP_INTERFACE]; + + switch (req->bRequest) { + case GET_REPORT: + /* no use for this driver */ + break; + + case GET_IDLE: + usb_transc_config(&udev->transc_in[0], (uint8_t *)&iap->idlestate, 1U, 0U); + + status = REQ_SUPP; + break; + + case GET_PROTOCOL: + usb_transc_config(&udev->transc_in[0], (uint8_t *)&iap->protocol, 1U, 0U); + + status = REQ_SUPP; + break; + + case SET_REPORT: + iap->reportID = (uint8_t)(req->wValue); + + usb_transc_config(&udev->transc_out[0], iap->report_buf, req->wLength, 0U); + + status = REQ_SUPP; + break; + + case SET_IDLE: + iap->idlestate = (uint8_t)(req->wValue >> 8); + + status = REQ_SUPP; + break; + + case SET_PROTOCOL: + iap->protocol = (uint8_t)(req->wValue); + + status = REQ_SUPP; + break; + + case USB_GET_DESCRIPTOR: + if (USB_DESCTYPE_REPORT == (req->wValue >> 8)) { + usb_transc_config(&udev->transc_in[0], + (uint8_t *)iap_report_desc, + USB_MIN(USB_DESC_LEN_IAP_REPORT, req->wLength), + 0U); + + return REQ_SUPP; + } + break; + + default: + break; + } + + return status; +} + +/*! + \brief handle data out stage + \param[in] udev: pointer to USB device instance + \param[in] ep_num: endpoint number + \param[out] none + \retval none +*/ +static void iap_data_out (usb_dev *udev ,uint8_t ep_num) +{ + usbd_iap_handler *iap = (usbd_iap_handler *)udev->class_data[USBD_IAP_INTERFACE]; + + if (0x01U == iap->report_buf[0]) { + switch(iap->report_buf[1]) { + case IAP_DNLOAD: + iap_req_dnload(udev); + break; + + case IAP_ERASE: + iap_req_erase(udev); + break; + + case IAP_OPTION_BYTE: + iap_req_optionbyte(udev); + break; + + case IAP_LEAVE: + iap_req_leave(udev); + break; + + case IAP_GETBIN_ADDRESS: + iap_address_send(udev); + break; + + default: + break; + } + } + + usbd_ep_recev(udev, IAP_OUT_EP, iap->report_buf, IAP_OUT_PACKET); +} + +/*! + \brief send IAP report + \param[in] udev: pointer to USB device instance + \param[in] report: pointer to HID report + \param[in] len: data length + \param[out] none + \retval USB device operation status +*/ +uint8_t iap_report_send (usb_dev *udev, uint8_t *report, uint16_t len) +{ + usbd_ep_send (udev, IAP_IN_EP, report, len); + + return USBD_OK; +} + +/*! + \brief handle the IAP_DNLOAD request + \param[in] udev: pointer to USB device instance + \param[out] none + \retval none +*/ +static void iap_req_dnload (usb_dev *udev) +{ + usbd_iap_handler *iap = (usbd_iap_handler *)udev->class_data[USBD_IAP_INTERFACE]; + + if (0U != iap->transfer_times) { + if (1U == iap->transfer_times) { + if (0U == iap->lps) { + iap_data_write(&iap->report_buf[2], iap->base_address, TRANSFER_SIZE); + } else { + iap_data_write(&iap->report_buf[2], iap->base_address, iap->file_length % TRANSFER_SIZE); + iap->lps = 0U; + } + + iap->dev_status[0] = 0x02U; + iap->dev_status[1] = 0x02U; + iap_report_send (udev, iap->dev_status, IAP_IN_PACKET); + } else { + iap_data_write(&iap->report_buf[2], iap->base_address, TRANSFER_SIZE); + + iap->base_address += TRANSFER_SIZE; + } + + iap->transfer_times--; + } +} + +/*! + \brief handle the IAP_ERASE request + \param[in] udev: pointer to USB device instance + \param[out] none + \retval none +*/ +static void iap_req_erase (usb_dev *udev) +{ + uint32_t i, addr = 0U; + + usbd_iap_handler *iap = (usbd_iap_handler *)udev->class_data[USBD_IAP_INTERFACE]; + + /* get base address to erase */ + iap->base_address = iap->report_buf[2]; + iap->base_address |= (uint32_t)iap->report_buf[3] << 8; + iap->base_address |= (uint32_t)iap->report_buf[4] << 16; + iap->base_address |= (uint32_t)iap->report_buf[5] << 24; + + iap->page_count = iap->report_buf[6]; + + /* get file length */ + iap->file_length = iap->report_buf[7]; + iap->file_length |= (uint32_t)iap->report_buf[8] << 8; + iap->file_length |= (uint32_t)iap->report_buf[9] << 16; + iap->file_length |= (uint32_t)iap->report_buf[10] << 24; + + /* compute last packet size and transfer times */ + iap->lps = iap->file_length % TRANSFER_SIZE; + if (0U == iap->lps) { + iap->transfer_times = (uint16_t)iap->file_length / TRANSFER_SIZE; + } else { + iap->transfer_times = (uint16_t)iap->file_length / TRANSFER_SIZE + 1U; + } + + /* check if the address is in protected area */ + if (IS_PROTECTED_AREA(iap->base_address)) { + return; + } + + addr = iap->base_address; + + for (i = 0U; i < iap->page_count; i ++) { + /* call the standard flash erase-page function */ + fmc_page_erase(addr); + + addr += PAGE_SIZE; + } + + iap->dev_status[0] = 0x02U; + iap->dev_status[1] = 0x01U; + + usbd_ep_send(udev, IAP_IN_EP, iap->dev_status, IAP_IN_PACKET); +} + +/*! + \brief handle the IAP_OPTION_BYTE request + \param[in] udev: pointer to USB device instance + \param[out] none + \retval none +*/ +static void iap_req_optionbyte (usb_dev *udev) +{ + uint8_t i = 0U; + uint32_t address = 0x1FFFF800U; + + usbd_iap_handler *iap = (usbd_iap_handler *)udev->class_data[USBD_IAP_INTERFACE]; + + iap->option_byte[0] = 0x02U; + + for (i = 1U; i < 17U; i++) { + iap->option_byte[i] = *(uint8_t *)address; + address++; + } + + iap_report_send(udev, iap->option_byte, IAP_IN_PACKET); +} + +/*! + \brief handle the IAP_LEAVE request + \param[in] udev: pointer to USB device instance + \param[out] none + \retval none +*/ +static void iap_req_leave (usb_dev *udev) +{ + /* lock the internal flash */ + fmc_lock(); + + /* generate system reset to allow jumping to the user code */ + NVIC_SystemReset(); +} + +/*! + \brief handle the IAP_SEND_ADDRESS request + \param[in] udev: pointer to USB device instance + \param[out] none + \retval none +*/ +static void iap_address_send(usb_dev *udev) +{ + usbd_iap_handler *iap = (usbd_iap_handler *)udev->class_data[USBD_IAP_INTERFACE]; + + iap->bin_addr[0] = 0x02U; + + iap->bin_addr[1] = (uint8_t)(APP_LOADED_ADDR); + iap->bin_addr[2] = (uint8_t)(APP_LOADED_ADDR >> 8); + iap->bin_addr[3] = (uint8_t)(APP_LOADED_ADDR >> 16); + iap->bin_addr[4] = (uint8_t)(APP_LOADED_ADDR >> 24); + + iap_report_send (udev, iap->bin_addr, IAP_IN_PACKET); +} + +/*! + \brief write data to sectors of memory + \param[in] data: data to be written + \param[in] addr: sector address/code + \param[in] len: length of data to be written (in bytes) + \param[out] none + \retval MAL_OK if all operations are OK, MAL_FAIL else +*/ +static void iap_data_write (uint8_t *data, uint32_t addr, uint32_t len) +{ + uint32_t index = 0U; + + /* check if the address is in protected area */ + if (IS_PROTECTED_AREA(addr)) { + return; + } + + if (len & 0x03U) {/* not an aligned data */ + for (index = len; index < ((len & 0xFFFCU) + 4U); index++) { + data[index] = 0xFFU; + } + } + + /* data received are word multiple */ + for (index = 0U; index < len; index += 4U) { + fmc_word_program(addr, *(uint32_t *)(data + index)); + addr += 4U; + } +} diff --git a/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbd_library/class/device/msc/Include/usbd_msc_bbb.h b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbd_library/class/device/msc/Include/usbd_msc_bbb.h new file mode 100644 index 0000000000..8abad3b021 --- /dev/null +++ b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbd_library/class/device/msc/Include/usbd_msc_bbb.h @@ -0,0 +1,129 @@ +/*! + \file usbd_msc_bbb.h + \brief the header file of the usbd_msc_bot.c file + + \version 2020-07-17, V3.0.0, firmware for GD32F10x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef __USBD_MSC_BBB_H +#define __USBD_MSC_BBB_H + +#include "usbd_core.h" +#include "usbd_msc_mem.h" +#include "usbd_msc_scsi.h" + +#define BBB_CBW_SIGNATURE 0x43425355U +#define BBB_CSW_SIGNATURE 0x53425355U +#define BBB_CBW_LENGTH 31U +#define BBB_CSW_LENGTH 13U + +typedef struct { + uint32_t dCBWSignature; + uint32_t dCBWTag; + uint32_t dCBWDataTransferLength; + uint8_t bmCBWFlags; + uint8_t bCBWLUN; + uint8_t bCBWCBLength; + uint8_t CBWCB[16]; +}msc_bbb_cbw; + +typedef struct { + uint32_t dCSWSignature; + uint32_t dCSWTag; + uint32_t dCSWDataResidue; + uint8_t bCSWStatus; +}msc_bbb_csw; + +/* CSW command status */ +enum msc_csw_status { + CSW_CMD_PASSED = 0, + CSW_CMD_FAILED, + CSW_PHASE_ERROR +}; + +/* MSC BBB state */ +enum msc_bbb_state { + BBB_IDLE = 0U, /*!< idle state */ + BBB_DATA_OUT, /*!< data OUT state */ + BBB_DATA_IN, /*!< data IN state */ + BBB_LAST_DATA_IN, /*!< last data IN state */ + BBB_SEND_DATA /*!< send immediate data state */ +}; + +/* MSC BBB status */ +enum msc_bbb_status { + BBB_STATUS_NORMAL = 0U, /*!< normal status */ + BBB_STATUS_RECOVERY, /*!< recovery status*/ + BBB_STATUS_ERROR /*!< error status */ +}; + +typedef struct +{ + uint8_t bbb_data[MSC_MEDIA_PACKET_SIZE]; + + uint8_t max_lun; + uint8_t bbb_state; + uint8_t bbb_status; + + uint32_t bbb_datalen; + + msc_bbb_cbw bbb_cbw; + msc_bbb_csw bbb_csw; + + uint8_t scsi_sense_head; + uint8_t scsi_sense_tail; + + uint32_t scsi_blk_size[MEM_LUN_NUM]; + uint32_t scsi_blk_nbr[MEM_LUN_NUM]; + + uint32_t scsi_blk_addr; + uint32_t scsi_blk_len; +// uint32_t scsi_disk_pop; + + msc_scsi_sense scsi_sense[SENSE_LIST_DEEPTH]; +} usbd_msc_handler; + +/* function declarations */ +/* initialize the bbb process */ +void msc_bbb_init (usb_dev *udev); +/* reset the BBB machine */ +void msc_bbb_reset (usb_dev *udev); +/* deinitialize the BBB machine */ +void msc_bbb_deinit (usb_dev *udev); +/* handle BBB data IN stage */ +void msc_bbb_data_in (usb_dev *udev, uint8_t ep_num); +/* handle BBB data OUT stage */ +void msc_bbb_data_out (usb_dev *udev, uint8_t ep_num); +/* send the CSW(command status wrapper) */ +void msc_bbb_csw_send (usb_dev *udev, uint8_t csw_status); +/* complete the clear feature request */ +void msc_bbb_clrfeature (usb_dev *udev, uint8_t ep_num); + +#endif /* __USBD_MSC_BBB_H */ diff --git a/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbd_library/class/device/msc/Include/usbd_msc_core.h b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbd_library/class/device/msc/Include/usbd_msc_core.h new file mode 100644 index 0000000000..c9ab389353 --- /dev/null +++ b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbd_library/class/device/msc/Include/usbd_msc_core.h @@ -0,0 +1,85 @@ +/*! + \file usbd_msc_core.h + \brief the header file of USB MSC device class core functions + + \version 2020-07-17, V3.0.0, firmware for GD32F10x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef __USBD_MSC_CORE_H +#define __USBD_MSC_CORE_H + +#include "usbd_core.h" + +/* mass storage device class code */ +#define USB_CLASS_MSC 0x08U + +/* mass storage subclass code */ +#define USB_MSC_SUBCLASS_RBC 0x01U +#define USB_MSC_SUBCLASS_ATAPI 0x02U +#define USB_MSC_SUBCLASS_UFI 0x04U +#define USB_MSC_SUBCLASS_SCSI 0x06U +#define USB_MSC_SUBCLASS_LOCKABLE 0x07U +#define USB_MSC_SUBCLASS_IEEE1667 0x08U + +/* mass storage interface class control protocol codes */ +#define USB_MSC_PROTOCOL_CBI 0x00U +#define USB_MSC_PROTOCOL_CBI_ALT 0x01U +#define USB_MSC_PROTOCOL_BBB 0x50U + +/* mass storage request codes */ +#define USB_MSC_REQ_CODES_ADSC 0x00U +#define USB_MSC_REQ_CODES_GET 0xFCU +#define USB_MSC_REQ_CODES_PUT 0xFDU +#define USB_MSC_REQ_CODES_GML 0xFEU +#define USB_MSC_REQ_CODES_BOMSR 0xFFU + +/* mass storage class-specific request codes */ +#define BBB_GET_MAX_LUN 0xFEU +#define BBB_RESET 0xFFU + +#define USB_MSC_CONFIG_DESC_SIZE 32U + +#define MSC_EPIN_SIZE MSC_DATA_PACKET_SIZE +#define MSC_EPOUT_SIZE MSC_DATA_PACKET_SIZE + +/* USB configuration descriptor structure */ +typedef struct +{ + usb_desc_config config; + + usb_desc_itf msc_itf; + usb_desc_ep msc_epin; + usb_desc_ep msc_epout; +} usb_desc_config_set; + +extern usb_desc msc_desc; +extern usb_class msc_class; + +#endif /* __USBD_MSC_CORE_H */ diff --git a/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbd_library/class/device/msc/Include/usbd_msc_data.h b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbd_library/class/device/msc/Include/usbd_msc_data.h new file mode 100644 index 0000000000..7f038ec568 --- /dev/null +++ b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbd_library/class/device/msc/Include/usbd_msc_data.h @@ -0,0 +1,49 @@ +/*! + \file usbd_msc_data.h + \brief the header file of the usbd_msc_data.c file + + \version 2020-07-17, V3.0.0, firmware for GD32F10x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef __USBD_MSC_DATA_H +#define __USBD_MSC_DATA_H + +#include "usbd_conf.h" + +#define MODE_SENSE6_LENGTH 8U +#define MODE_SENSE10_LENGTH 8U +#define INQUIRY_PAGE00_LENGTH 96U +#define FORMAT_CAPACITIES_LENGTH 20U + +extern const uint8_t msc_page00_inquiry_data[]; +extern const uint8_t msc_mode_sense6_data[]; +extern const uint8_t msc_mode_sense10_data[]; + +#endif /* __USBD_MSC_DATA_H */ diff --git a/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbd_library/class/device/msc/Include/usbd_msc_mem.h b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbd_library/class/device/msc/Include/usbd_msc_mem.h new file mode 100644 index 0000000000..a992e0182e --- /dev/null +++ b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbd_library/class/device/msc/Include/usbd_msc_mem.h @@ -0,0 +1,59 @@ +/*! + \file usbd_msc_mem.h + \brief header file for storage memory + + \version 2020-07-17, V3.0.0, firmware for GD32F10x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef __USBD_MSC_MEM_H +#define __USBD_MSC_MEM_H + +#include "usbd_conf.h" + +#define USBD_STD_INQUIRY_LENGTH 36U + +typedef struct +{ + int8_t (*mem_init) (uint8_t lun); + int8_t (*mem_ready) (uint8_t lun); + int8_t (*mem_protected) (uint8_t lun); + int8_t (*mem_read) (uint8_t lun, uint8_t *buf, uint32_t block_addr, uint16_t block_len); + int8_t (*mem_write) (uint8_t lun, uint8_t *buf, uint32_t block_addr, uint16_t block_len); + int8_t (*mem_maxlun) (void); + + uint8_t *mem_toc_data; + uint8_t *mem_inquiry_data[MEM_LUN_NUM]; + uint32_t mem_block_size[MEM_LUN_NUM]; + uint32_t mem_block_len[MEM_LUN_NUM]; +}usbd_mem_cb; + +extern usbd_mem_cb *usbd_mem_fops; + +#endif /* __USBD_MSC_MEM_H */ diff --git a/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbd_library/class/device/msc/Include/usbd_msc_scsi.h b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbd_library/class/device/msc/Include/usbd_msc_scsi.h new file mode 100644 index 0000000000..2e84231eba --- /dev/null +++ b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbd_library/class/device/msc/Include/usbd_msc_scsi.h @@ -0,0 +1,126 @@ +/*! + \file usbd_msc_scsi.h + \brief the header file of the usbd_msc_scsi.c file + + \version 2020-07-17, V3.0.0, firmware for GD32F10x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef __USBD_MSC_SCSI_H +#define __USBD_MSC_SCSI_H + +#include "usbd_msc_data.h" +#include "usbd_msc_bbb.h" + +#define SENSE_LIST_DEEPTH 4U + +/* SCSI commands */ +#define SCSI_FORMAT_UNIT 0x04U +#define SCSI_INQUIRY 0x12U +#define SCSI_MODE_SELECT6 0x15U +#define SCSI_MODE_SELECT10 0x55U +#define SCSI_MODE_SENSE6 0x1AU +#define SCSI_READ_TOC_DATA 0x43U +#define SCSI_MODE_SENSE10 0x5AU +#define SCSI_ALLOW_MEDIUM_REMOVAL 0x1EU +#define SCSI_READ6 0x08U +#define SCSI_READ10 0x28U +#define SCSI_READ12 0xA8U +#define SCSI_READ16 0x88U + +#define SCSI_READ_CAPACITY10 0x25U +#define SCSI_READ_CAPACITY16 0x9EU + +#define SCSI_REQUEST_SENSE 0x03U +#define SCSI_START_STOP_UNIT 0x1BU +#define SCSI_TEST_UNIT_READY 0x00U +#define SCSI_WRITE6 0x0AU +#define SCSI_WRITE10 0x2AU +#define SCSI_WRITE12 0xAAU +#define SCSI_WRITE16 0x8AU + +#define SCSI_VERIFY10 0x2FU +#define SCSI_VERIFY12 0xAFU +#define SCSI_VERIFY16 0x8FU + +#define SCSI_SEND_DIAGNOSTIC 0x1DU +#define SCSI_READ_FORMAT_CAPACITIES 0x23U + +#define INVALID_CDB 0x20U +#define INVALID_FIELED_IN_COMMAND 0x24U +#define PARAMETER_LIST_LENGTH_ERROR 0x1AU +#define INVALID_FIELD_IN_PARAMETER_LIST 0x26U +#define ADDRESS_OUT_OF_RANGE 0x21U +#define MEDIUM_NOT_PRESENT 0x3AU +#define MEDIUM_HAVE_CHANGED 0x28U +#define WRITE_PROTECTED 0x27U +#define UNRECOVERED_READ_ERROR 0x11U +#define WRITE_FAULT 0x03U + +#define READ_FORMAT_CAPACITY_DATA_LEN 0x0CU +#define READ_CAPACITY10_DATA_LEN 0x08U +#define MODE_SENSE10_DATA_LEN 0x08U +#define MODE_SENSE6_DATA_LEN 0x04U +#define READ_TOC_CMD_LEN 0x14U +#define REQUEST_SENSE_DATA_LEN 0x12U +#define STANDARD_INQUIRY_DATA_LEN 0x24U +#define BLKVFY 0x04U + +enum sense_state { + NO_SENSE = 0U, + RECOVERED_ERROR, + NOT_READY, + MEDIUM_ERROR, + HARDWARE_ERROR, + ILLEGAL_REQUEST, + UNIT_ATTENTION, + DATA_PROTECT, + BLANK_CHECK, + VENDOR_SPECIFIC, + COPY_ABORTED, + ABORTED_COMMAND, + RESERVED, + VOLUME_OVERFLOW, + MISCOMPARE +}; + +typedef struct { + uint8_t SenseKey; + uint32_t Information; + uint8_t ASC; + uint8_t ASCQ; +} msc_scsi_sense; + +/* function declarations */ +/* process SCSI commands */ +int8_t scsi_process_cmd (usb_dev *udev, uint8_t lun, uint8_t *cmd); +/* load the last error code in the error list */ +void scsi_sense_code (usb_dev *udev, uint8_t lun, uint8_t skey, uint8_t asc); + +#endif /* __USBD_MSC_SCSI_H */ diff --git a/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbd_library/class/device/msc/Source/usbd_msc_bbb.c b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbd_library/class/device/msc/Source/usbd_msc_bbb.c new file mode 100644 index 0000000000..16516d898a --- /dev/null +++ b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbd_library/class/device/msc/Source/usbd_msc_bbb.c @@ -0,0 +1,283 @@ +/*! + \file usbd_msc_bbb.c + \brief USB BBB(Bulk/Bulk/Bulk) protocol core functions + \note BBB means Bulk-only transport protocol for USB MSC + + \version 2020-07-17, V3.0.0, firmware for GD32F10x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "usbd_enum.h" +#include "usbd_msc_bbb.h" + +/* local function prototypes ('static') */ +static void msc_bbb_cbw_decode (usb_dev *udev); +static void msc_bbb_data_send (usb_dev *udev, uint8_t *pbuf, uint32_t Len); +static void msc_bbb_abort (usb_dev *udev); + +/*! + \brief initialize the bbb process + \param[in] udev: pointer to USB device instance + \param[out] none + \retval none +*/ +void msc_bbb_init (usb_dev *udev) +{ + uint8_t lun_num; + + usbd_msc_handler *msc = (usbd_msc_handler *)udev->class_data[USBD_MSC_INTERFACE]; + + msc->bbb_state = BBB_IDLE; + msc->bbb_status = BBB_STATUS_NORMAL; + + /* initializes the storage logic unit */ + for(lun_num = 0U; lun_num < MEM_LUN_NUM; lun_num++) { + usbd_mem_fops->mem_init(lun_num); + } + + /* prepare endpoint to receive the first BBB CBW */ + usbd_ep_recev (udev, MSC_OUT_EP, (uint8_t *)&msc->bbb_cbw, BBB_CBW_LENGTH); +} + +/*! + \brief reset the BBB machine + \param[in] udev: pointer to USB device instance + \param[out] none + \retval none +*/ +void msc_bbb_reset (usb_dev *udev) +{ + usbd_msc_handler *msc = (usbd_msc_handler *)udev->class_data[USBD_MSC_INTERFACE]; + + msc->bbb_state = BBB_IDLE; + msc->bbb_status = BBB_STATUS_RECOVERY; + + /* prepare endpoint to receive the first BBB command */ + usbd_ep_recev (udev, MSC_OUT_EP, (uint8_t *)&msc->bbb_cbw, BBB_CBW_LENGTH); +} + +/*! + \brief deinitialize the BBB machine + \param[in] udev: pointer to USB device instance + \param[out] none + \retval none +*/ +void msc_bbb_deinit (usb_dev *udev) +{ + usbd_msc_handler *msc = (usbd_msc_handler *)udev->class_data[USBD_MSC_INTERFACE]; + + msc->bbb_state = BBB_IDLE; +} + +/*! + \brief handle BBB data IN stage + \param[in] udev: pointer to USB device instance + \param[in] ep_num: endpoint number + \param[out] none + \retval none +*/ +void msc_bbb_data_in (usb_dev *udev, uint8_t ep_num) +{ + usbd_msc_handler *msc = (usbd_msc_handler *)udev->class_data[USBD_MSC_INTERFACE]; + + switch (msc->bbb_state) { + case BBB_DATA_IN: + if (scsi_process_cmd (udev, msc->bbb_cbw.bCBWLUN, &msc->bbb_cbw.CBWCB[0]) < 0) { + msc_bbb_csw_send (udev, CSW_CMD_FAILED); + } + break; + + case BBB_SEND_DATA: + case BBB_LAST_DATA_IN: + msc_bbb_csw_send (udev, CSW_CMD_PASSED); + break; + + default: + break; + } +} + +/*! + \brief handle BBB data OUT stage + \param[in] udev: pointer to USB device instance + \param[in] ep_num: endpoint number + \param[out] none + \retval none +*/ +void msc_bbb_data_out (usb_dev *udev, uint8_t ep_num) +{ + usbd_msc_handler *msc = (usbd_msc_handler *)udev->class_data[USBD_MSC_INTERFACE]; + + switch (msc->bbb_state) { + case BBB_IDLE: + msc_bbb_cbw_decode (udev); + break; + + case BBB_DATA_OUT: + if (scsi_process_cmd (udev, msc->bbb_cbw.bCBWLUN, &msc->bbb_cbw.CBWCB[0]) < 0) { + msc_bbb_csw_send (udev, CSW_CMD_FAILED); + } + break; + + default: + break; + } +} + +/*! + \brief send the CSW(command status wrapper) + \param[in] udev: pointer to USB device instance + \param[in] csw_status: CSW status + \param[out] none + \retval none +*/ +void msc_bbb_csw_send (usb_dev *udev, uint8_t csw_status) +{ + usbd_msc_handler *msc = (usbd_msc_handler *)udev->class_data[USBD_MSC_INTERFACE]; + + msc->bbb_csw.dCSWSignature = BBB_CSW_SIGNATURE; + msc->bbb_csw.bCSWStatus = csw_status; + msc->bbb_state = BBB_IDLE; + + usbd_ep_send (udev, MSC_IN_EP, (uint8_t *)&msc->bbb_csw, BBB_CSW_LENGTH); + + /* prepare endpoint to receive next command */ + usbd_ep_recev (udev, MSC_OUT_EP, (uint8_t *)&msc->bbb_cbw, BBB_CBW_LENGTH); +} + +/*! + \brief complete the clear feature request + \param[in] udev: pointer to USB device instance + \param[in] ep_num: endpoint number + \param[out] none + \retval none +*/ +void msc_bbb_clrfeature (usb_dev *udev, uint8_t ep_num) +{ + usbd_msc_handler *msc = (usbd_msc_handler *)udev->class_data[USBD_MSC_INTERFACE]; + + if (msc->bbb_status == BBB_STATUS_ERROR)/* bad CBW signature */ { + usbd_ep_stall(udev, MSC_IN_EP); + + msc->bbb_status = BBB_STATUS_NORMAL; + } else if(((ep_num & 0x80U) == 0x80U) && (msc->bbb_status != BBB_STATUS_RECOVERY)) { + msc_bbb_csw_send (udev, CSW_CMD_FAILED); + } else { + + } +} + +/*! + \brief decode the CBW command and set the BBB state machine accordingly + \param[in] udev: pointer to USB device instance + \param[out] none + \retval none +*/ +static void msc_bbb_cbw_decode (usb_dev *udev) +{ + usbd_msc_handler *msc = (usbd_msc_handler *)udev->class_data[USBD_MSC_INTERFACE]; + + uint16_t rx_len = udev->transc_out[MSC_OUT_EP].xfer_count; + + msc->bbb_csw.dCSWTag = msc->bbb_cbw.dCBWTag; + msc->bbb_csw.dCSWDataResidue = msc->bbb_cbw.dCBWDataTransferLength; + + if ((BBB_CBW_LENGTH != rx_len) || + (BBB_CBW_SIGNATURE != msc->bbb_cbw.dCBWSignature)|| + (msc->bbb_cbw.bCBWLUN > 1U) || + (msc->bbb_cbw.bCBWCBLength < 1U) || + (msc->bbb_cbw.bCBWCBLength > 16U)) { + /* illegal command handler */ + scsi_sense_code (udev, msc->bbb_cbw.bCBWLUN, ILLEGAL_REQUEST, INVALID_CDB); + + msc->bbb_status = BBB_STATUS_ERROR; + + msc_bbb_abort (udev); + } else { + if (scsi_process_cmd (udev, msc->bbb_cbw.bCBWLUN, &msc->bbb_cbw.CBWCB[0]) < 0) { + msc_bbb_abort (udev); + } else if ((BBB_DATA_IN != msc->bbb_state) && + (BBB_DATA_OUT != msc->bbb_state) && + (BBB_LAST_DATA_IN != msc->bbb_state)) { /* burst xfer handled internally */ + if (msc->bbb_datalen > 0U) { + msc_bbb_data_send (udev, msc->bbb_data, msc->bbb_datalen); + } else if (0U == msc->bbb_datalen) { + msc_bbb_csw_send (udev, CSW_CMD_PASSED); + } else { + + } + } else { + + } + } +} + +/*! + \brief send the requested data + \param[in] udev: pointer to USB device instance + \param[in] buf: pointer to data buffer + \param[in] len: data length + \param[out] none + \retval none +*/ +static void msc_bbb_data_send (usb_dev *udev, uint8_t *buf, uint32_t len) +{ + usbd_msc_handler *msc = (usbd_msc_handler *)udev->class_data[USBD_MSC_INTERFACE]; + + len = USB_MIN (msc->bbb_cbw.dCBWDataTransferLength, len); + + msc->bbb_csw.dCSWDataResidue -= len; + msc->bbb_csw.bCSWStatus = CSW_CMD_PASSED; + msc->bbb_state = BBB_SEND_DATA; + + usbd_ep_send (udev, MSC_IN_EP, buf, len); +} + +/*! + \brief abort the current transfer + \param[in] udev: pointer to USB device instance + \param[out] none + \retval none +*/ +static void msc_bbb_abort (usb_dev *udev) +{ + usbd_msc_handler *msc = (usbd_msc_handler *)udev->class_data[USBD_MSC_INTERFACE]; + + if ((0U == msc->bbb_cbw.bmCBWFlags) && + (0U != msc->bbb_cbw.dCBWDataTransferLength) && + (BBB_STATUS_NORMAL == msc->bbb_status)) { + usbd_ep_stall(udev, MSC_OUT_EP); + } + + usbd_ep_stall(udev, MSC_IN_EP); + + if (msc->bbb_status == BBB_STATUS_ERROR) { + usbd_ep_recev (udev, MSC_OUT_EP, (uint8_t *)&msc->bbb_cbw, BBB_CBW_LENGTH); + } +} diff --git a/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbd_library/class/device/msc/Source/usbd_msc_core.c b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbd_library/class/device/msc/Source/usbd_msc_core.c new file mode 100644 index 0000000000..9f946e5043 --- /dev/null +++ b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbd_library/class/device/msc/Source/usbd_msc_core.c @@ -0,0 +1,316 @@ +/*! + \file usbd_msc_core.c + \brief USB MSC device class core functions + + \version 2020-07-17, V3.0.0, firmware for GD32F10x + \version 2020-12-07, V3.0.1, firmware for GD32F10x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "usbd_enum.h" +#include "usbd_msc_bbb.h" +#include "usbd_msc_core.h" +#include "usbd_transc.h" +#include + +#define USBD_VID 0x28E9U +#define USBD_PID 0x128FU + +/* local function prototypes ('static') */ +static uint8_t msc_core_init (usb_dev *udev, uint8_t config_index); +static uint8_t msc_core_deinit (usb_dev *udev, uint8_t config_index); +static uint8_t msc_core_req (usb_dev *udev, usb_req *req); +static void msc_core_in (usb_dev *udev, uint8_t ep_num); +static void msc_core_out (usb_dev *udev, uint8_t ep_num); + +usb_class msc_class = +{ + .init = msc_core_init, + .deinit = msc_core_deinit, + + .req_process = msc_core_req, + + .data_in = msc_core_in, + .data_out = msc_core_out +}; + +/* note: it should use the C99 standard when compiling the below codes */ +/* USB standard device descriptor */ +const usb_desc_dev msc_dev_desc = +{ + .header = { + .bLength = USB_DEV_DESC_LEN, + .bDescriptorType = USB_DESCTYPE_DEV + }, + .bcdUSB = 0x0200U, + .bDeviceClass = 0x00U, + .bDeviceSubClass = 0x00U, + .bDeviceProtocol = 0x00U, + .bMaxPacketSize0 = USBD_EP0_MAX_SIZE, + .idVendor = USBD_VID, + .idProduct = USBD_PID, + .bcdDevice = 0x0100U, + .iManufacturer = STR_IDX_MFC, + .iProduct = STR_IDX_PRODUCT, + .iSerialNumber = STR_IDX_SERIAL, + .bNumberConfigurations = USBD_CFG_MAX_NUM +}; + +/* USB device configuration descriptor */ +const usb_desc_config_set msc_config_desc = +{ + .config = + { + .header = { + .bLength = sizeof(usb_desc_config), + .bDescriptorType = USB_DESCTYPE_CONFIG + }, + .wTotalLength = USB_MSC_CONFIG_DESC_SIZE, + .bNumInterfaces = 0x01U, + .bConfigurationValue = 0x01U, + .iConfiguration = 0x00U, + .bmAttributes = 0xC0U, + .bMaxPower = 0x32U + }, + + .msc_itf = + { + .header = { + .bLength = sizeof(usb_desc_itf), + .bDescriptorType = USB_DESCTYPE_ITF + }, + .bInterfaceNumber = 0x00U, + .bAlternateSetting = 0x00U, + .bNumEndpoints = 0x02U, + .bInterfaceClass = USB_CLASS_MSC, + .bInterfaceSubClass = USB_MSC_SUBCLASS_SCSI, + .bInterfaceProtocol = USB_MSC_PROTOCOL_BBB, + .iInterface = 0x00U + }, + + .msc_epin = + { + .header = { + .bLength = sizeof(usb_desc_ep), + .bDescriptorType = USB_DESCTYPE_EP + }, + .bEndpointAddress = MSC_IN_EP, + .bmAttributes = USB_EP_ATTR_BULK, + .wMaxPacketSize = MSC_EPIN_SIZE, + .bInterval = 0x00U + }, + + .msc_epout = + { + .header = { + .bLength = sizeof(usb_desc_ep), + .bDescriptorType = USB_DESCTYPE_EP + }, + .bEndpointAddress = MSC_OUT_EP, + .bmAttributes = USB_EP_ATTR_BULK, + .wMaxPacketSize = MSC_EPOUT_SIZE, + .bInterval = 0x00U + } +}; + +/* USB language ID descriptor */ +const usb_desc_LANGID usbd_language_id_desc = +{ + .header = + { + .bLength = sizeof(usb_desc_LANGID), + .bDescriptorType = USB_DESCTYPE_STR + }, + .wLANGID = ENG_LANGID +}; + +/* USB manufacture string */ +static const usb_desc_str manufacturer_string = +{ + .header = + { + .bLength = USB_STRING_LEN(10U), + .bDescriptorType = USB_DESCTYPE_STR, + }, + .unicode_string = {'G', 'i', 'g', 'a', 'D', 'e', 'v', 'i', 'c', 'e'} +}; + +/* USB product string */ +static const usb_desc_str product_string = +{ + .header = + { + .bLength = USB_STRING_LEN(12U), + .bDescriptorType = USB_DESCTYPE_STR, + }, + .unicode_string = {'G', 'D', '3', '2', '-', 'U', 'S', 'B', '_', 'M', 'S', 'C'} +}; + +/* USBD serial string */ +static usb_desc_str serial_string = +{ + .header = + { + .bLength = USB_STRING_LEN(12U), + .bDescriptorType = USB_DESCTYPE_STR, + } +}; + +/* USB string descriptor */ +uint8_t* usbd_msc_strings[] = +{ + [STR_IDX_LANGID] = (uint8_t *)&usbd_language_id_desc, + [STR_IDX_MFC] = (uint8_t *)&manufacturer_string, + [STR_IDX_PRODUCT] = (uint8_t *)&product_string, + [STR_IDX_SERIAL] = (uint8_t *)&serial_string +}; + +usb_desc msc_desc = { + .dev_desc = (uint8_t *)&msc_dev_desc, + .config_desc = (uint8_t *)&msc_config_desc, + .strings = usbd_msc_strings +}; + +static uint8_t usbd_msc_maxlun = 0U; + +/*! + \brief initialize the MSC device + \param[in] udev: pointer to USB device instance + \param[in] config_index: configuration index + \param[out] none + \retval USB device operation status +*/ +static uint8_t msc_core_init (usb_dev *udev, uint8_t config_index) +{ + static usbd_msc_handler msc_handler; + + memset((void *)&msc_handler, 0U, sizeof(usbd_msc_handler)); + + udev->class_data[USBD_MSC_INTERFACE] = (void *)&msc_handler; + + /* initialize Tx endpoint */ + usbd_ep_init(udev, EP_BUF_SNG, BULK_TX_ADDR, &(msc_config_desc.msc_epin)); + + /* initialize Rx endpoint */ + usbd_ep_init(udev, EP_BUF_SNG, BULK_RX_ADDR, &(msc_config_desc.msc_epout)); + + udev->ep_transc[EP_ID(MSC_IN_EP)][TRANSC_IN] = msc_class.data_in; + udev->ep_transc[MSC_OUT_EP][TRANSC_OUT] = msc_class.data_out; + + /* initialize the BBB layer */ + msc_bbb_init(udev); + + return USBD_OK; +} + +/*! + \brief deinitialize the MSC device + \param[in] udev: pointer to USB device instance + \param[in] config_index: configuration index + \param[out] none + \retval USB device operation status +*/ +static uint8_t msc_core_deinit (usb_dev *udev, uint8_t config_index) +{ + /* clear MSC endpoints */ + usbd_ep_deinit (udev, MSC_IN_EP); + usbd_ep_deinit (udev, MSC_OUT_EP); + + /* deinitialize the BBB layer */ + msc_bbb_deinit(udev); + + return USBD_OK; +} + +/*! + \brief handle the MSC class-specific and standard requests + \param[in] udev: pointer to USB device instance + \param[in] req: device class-specific request + \param[out] none + \retval USB device operation status +*/ +static uint8_t msc_core_req (usb_dev *udev, usb_req *req) +{ + switch (req->bRequest) { + case BBB_GET_MAX_LUN : + if((0U == req->wValue) && + (1U == req->wLength) && + (0x80U == (req->bmRequestType & 0x80U))) { + usbd_msc_maxlun = (uint8_t)usbd_mem_fops->mem_maxlun(); + + usb_transc_config(&udev->transc_in[0], &usbd_msc_maxlun, 1U, 0U); + } else { + return USBD_FAIL; + } + break; + + case BBB_RESET : + if((0U == req->wValue) && + (0U == req->wLength) && + (0x80U != (req->bmRequestType & 0x80U))) { + msc_bbb_reset(udev); + } else { + return USBD_FAIL; + } + break; + + case USB_CLEAR_FEATURE: + msc_bbb_clrfeature (udev, (uint8_t)req->wIndex); + break; + + default: + return USBD_FAIL; + } + + return USBD_OK; +} + +/*! + \brief handle data in stage + \param[in] udev: pointer to USB device instance + \param[in] ep_num: the endpoint number + \param[out] none + \retval none +*/ +static void msc_core_in (usb_dev *udev, uint8_t ep_num) +{ + msc_bbb_data_in(udev, ep_num); +} + +/*! + \brief handle data out stage + \param[in] udev: pointer to USB device instance + \param[in] ep_num: the endpoint number + \param[out] none + \retval none +*/ +static void msc_core_out (usb_dev *udev, uint8_t ep_num) +{ + msc_bbb_data_out (udev, ep_num); +} diff --git a/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbd_library/class/device/msc/Source/usbd_msc_data.c b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbd_library/class/device/msc/Source/usbd_msc_data.c new file mode 100644 index 0000000000..e7084cdbac --- /dev/null +++ b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbd_library/class/device/msc/Source/usbd_msc_data.c @@ -0,0 +1,73 @@ +/*! + \file usbd_msc_data.c + \brief USB MSC vital inquiry pages and sense data + + \version 2020-07-17, V3.0.0, firmware for GD32F10x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "usbd_msc_data.h" + +/* USB mass storage page 0 inquiry data */ +const uint8_t msc_page00_inquiry_data[] = +{ + 0x00U, + 0x00U, + 0x00U, + 0x00U, + (INQUIRY_PAGE00_LENGTH - 4U), + 0x80U, + 0x83U, +}; + +/* USB mass storage sense 6 data */ +const uint8_t msc_mode_sense6_data[] = +{ + 0x00U, + 0x00U, + 0x00U, + 0x00U, + 0x00U, + 0x00U, + 0x00U, + 0x00U +}; + +/* USB mass storage sense 10 data */ +const uint8_t msc_mode_sense10_data[] = +{ + 0x00U, + 0x06U, + 0x00U, + 0x00U, + 0x00U, + 0x00U, + 0x00U, + 0x00U +}; diff --git a/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbd_library/class/device/msc/Source/usbd_msc_scsi.c b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbd_library/class/device/msc/Source/usbd_msc_scsi.c new file mode 100644 index 0000000000..b6730b7382 --- /dev/null +++ b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbd_library/class/device/msc/Source/usbd_msc_scsi.c @@ -0,0 +1,728 @@ +/*! + \file usbd_msc_scsi.c + \brief USB SCSI layer functions + + \version 2020-07-17, V3.0.0, firmware for GD32F10x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "usbd_enum.h" +#include "usbd_msc_bbb.h" +#include "usbd_msc_scsi.h" +#include "usbd_msc_data.h" + +/* local function prototypes ('static') */ +static int8_t scsi_test_unit_ready (usb_dev *udev, uint8_t lun, uint8_t *params); +static int8_t scsi_mode_select6 (usb_dev *udev, uint8_t lun, uint8_t *params); +static int8_t scsi_mode_select10 (usb_dev *udev, uint8_t lun, uint8_t *params); +static int8_t scsi_inquiry (usb_dev *udev, uint8_t lun, uint8_t *params); +static int8_t scsi_read_format_capacity (usb_dev *udev, uint8_t lun, uint8_t *params); +static int8_t scsi_read_capacity10 (usb_dev *udev, uint8_t lun, uint8_t *params); +static int8_t scsi_request_sense (usb_dev *udev, uint8_t lun, uint8_t *params); +static int8_t scsi_mode_sense6 (usb_dev *udev, uint8_t lun, uint8_t *params); +static int8_t scsi_toc_cmd_read (usb_dev *udev, uint8_t lun, uint8_t *params); +static int8_t scsi_mode_sense10 (usb_dev *udev, uint8_t lun, uint8_t *params); +static int8_t scsi_write10 (usb_dev *udev, uint8_t lun, uint8_t *params); +static int8_t scsi_read10 (usb_dev *udev, uint8_t lun, uint8_t *params); +static int8_t scsi_verify10 (usb_dev *udev, uint8_t lun, uint8_t *params); + +static int8_t scsi_process_read (usb_dev *udev, uint8_t lun); +static int8_t scsi_process_write (usb_dev *udev, uint8_t lun); + +static inline int8_t scsi_check_address_range (usb_dev *udev, uint8_t lun, uint32_t blk_offset, uint16_t blk_nbr); +static inline int8_t scsi_format_cmd (usb_dev *udev, uint8_t lun); +static inline int8_t scsi_start_stop_unit (usb_dev *udev, uint8_t lun, uint8_t *params); +static inline int8_t scsi_allow_medium_removal (usb_dev *udev, uint8_t lun, uint8_t *params); + +/*! + \brief process SCSI commands + \param[in] udev: pointer to USB device instance + \param[in] lun: logical unit number + \param[in] params: command parameters + \param[out] none + \retval status +*/ +int8_t scsi_process_cmd(usb_dev *udev, uint8_t lun, uint8_t *params) +{ + switch (params[0]) { + case SCSI_TEST_UNIT_READY: + return scsi_test_unit_ready (udev, lun, params); + + case SCSI_REQUEST_SENSE: + return scsi_request_sense (udev, lun, params); + + case SCSI_INQUIRY: + return scsi_inquiry (udev, lun, params); + + case SCSI_START_STOP_UNIT: + return scsi_start_stop_unit (udev, lun, params); + + case SCSI_ALLOW_MEDIUM_REMOVAL: + return scsi_allow_medium_removal (udev, lun, params); + + case SCSI_MODE_SENSE6: + return scsi_mode_sense6 (udev, lun, params); + + case SCSI_MODE_SENSE10: + return scsi_mode_sense10 (udev, lun, params); + + case SCSI_READ_FORMAT_CAPACITIES: + return scsi_read_format_capacity (udev, lun, params); + + case SCSI_READ_CAPACITY10: + return scsi_read_capacity10 (udev, lun, params); + + case SCSI_READ10: + return scsi_read10 (udev, lun, params); + + case SCSI_WRITE10: + return scsi_write10 (udev, lun, params); + + case SCSI_VERIFY10: + return scsi_verify10 (udev, lun, params); + + case SCSI_FORMAT_UNIT: + return scsi_format_cmd (udev, lun); + + case SCSI_READ_TOC_DATA: + return scsi_toc_cmd_read (udev, lun, params); + + case SCSI_MODE_SELECT6: + return scsi_mode_select6 (udev, lun, params); + + case SCSI_MODE_SELECT10: + return scsi_mode_select10 (udev, lun, params); + + default: + scsi_sense_code (udev, lun, ILLEGAL_REQUEST, INVALID_CDB); + return -1; + } +} + +/*! + \brief load the last error code in the error list + \param[in] udev: pointer to USB device instance + \param[in] lun: logical unit number + \param[in] skey: sense key + \param[in] asc: additional sense key + \param[out] none + \retval none +*/ +void scsi_sense_code (usb_dev *udev, uint8_t lun, uint8_t skey, uint8_t asc) +{ + usbd_msc_handler *msc = (usbd_msc_handler *)udev->class_data[USBD_MSC_INTERFACE]; + + msc->scsi_sense[msc->scsi_sense_tail].SenseKey = skey; + msc->scsi_sense[msc->scsi_sense_tail].ASC = asc << 8U; + msc->scsi_sense_tail++; + + if (SENSE_LIST_DEEPTH == msc->scsi_sense_tail) { + msc->scsi_sense_tail = 0U; + } +} + +/*! + \brief process SCSI Test Unit Ready command + \param[in] udev: pointer to USB device instance + \param[in] lun: logical unit number + \param[in] params: command parameters + \param[out] none + \retval status +*/ +static int8_t scsi_test_unit_ready (usb_dev *udev, uint8_t lun, uint8_t *params) +{ + usbd_msc_handler *msc = (usbd_msc_handler *)udev->class_data[USBD_MSC_INTERFACE]; + + /* case 9 : Hi > D0 */ + if (0U != msc->bbb_cbw.dCBWDataTransferLength) { + scsi_sense_code (udev, msc->bbb_cbw.bCBWLUN, ILLEGAL_REQUEST, INVALID_CDB); + + return -1; + } + + if (0 != usbd_mem_fops->mem_ready(lun)) { + scsi_sense_code(udev, lun, NOT_READY, MEDIUM_NOT_PRESENT); + + return -1; + } + +// if (1U == msc->scsi_disk_pop) { +// usbd_disconnect (udev); +// } + + msc->bbb_datalen = 0U; + + return 0; +} + +/*! + \brief process Inquiry command + \param[in] udev: pointer to USB device instance + \param[in] lun: logical unit number + \param[in] params: command parameters + \param[out] none + \retval status +*/ +static int8_t scsi_mode_select6 (usb_dev *udev, uint8_t lun, uint8_t *params) +{ + usbd_msc_handler *msc = (usbd_msc_handler *)udev->class_data[USBD_MSC_INTERFACE]; + + msc->bbb_datalen = 0U; + + return 0; +} + +/*! + \brief process Inquiry command + \param[in] udev: pointer to USB device instance + \param[in] lun: logical unit number + \param[in] params: command parameters + \param[out] none + \retval status +*/ +static int8_t scsi_mode_select10 (usb_dev *udev, uint8_t lun, uint8_t *params) +{ + usbd_msc_handler *msc = (usbd_msc_handler *)udev->class_data[USBD_MSC_INTERFACE]; + + msc->bbb_datalen = 0U; + + return 0; +} + +/*! + \brief process Inquiry command + \param[in] udev: pointer to USB device instance + \param[in] lun: logical unit number + \param[in] params: command parameters + \param[out] none + \retval status +*/ +static int8_t scsi_inquiry (usb_dev *udev, uint8_t lun, uint8_t *params) +{ + uint8_t *page = NULL; + uint16_t len = 0U; + + usbd_msc_handler *msc = (usbd_msc_handler *)udev->class_data[USBD_MSC_INTERFACE]; + + if (params[1] & 0x01U) { + page = (uint8_t *)msc_page00_inquiry_data; + + len = INQUIRY_PAGE00_LENGTH; + } else { + page = (uint8_t *)usbd_mem_fops->mem_inquiry_data[lun]; + + len = (uint16_t)(page[4] + 5U); + + if (params[4] <= len) { + len = params[4]; + } + } + + msc->bbb_datalen = len; + + while (len) { + len--; + msc->bbb_data[len] = page[len]; + } + + return 0; +} + +/*! + \brief process Read Capacity 10 command + \param[in] udev: pointer to USB device instance + \param[in] lun: logical unit number + \param[in] params: command parameters + \param[out] none + \retval status +*/ +static int8_t scsi_read_capacity10 (usb_dev *udev, uint8_t lun, uint8_t *params) +{ + uint32_t blk_num = usbd_mem_fops->mem_block_len[lun] - 1U; + usbd_msc_handler *msc = (usbd_msc_handler *)udev->class_data[USBD_MSC_INTERFACE]; + + msc->scsi_blk_nbr[lun] = usbd_mem_fops->mem_block_len[lun]; + msc->scsi_blk_size[lun] = usbd_mem_fops->mem_block_size[lun]; + + msc->bbb_data[0] = (uint8_t)(blk_num >> 24U); + msc->bbb_data[1] = (uint8_t)(blk_num >> 16U); + msc->bbb_data[2] = (uint8_t)(blk_num >> 8U); + msc->bbb_data[3] = (uint8_t)(blk_num); + + msc->bbb_data[4] = (uint8_t)(msc->scsi_blk_size[lun] >> 24U); + msc->bbb_data[5] = (uint8_t)(msc->scsi_blk_size[lun] >> 16U); + msc->bbb_data[6] = (uint8_t)(msc->scsi_blk_size[lun] >> 8U); + msc->bbb_data[7] = (uint8_t)(msc->scsi_blk_size[lun]); + + msc->bbb_datalen = 8U; + + return 0; +} + +/*! + \brief process Read Format Capacity command + \param[in] udev: pointer to USB device instance + \param[in] lun: logical unit number + \param[in] params: command parameters + \param[out] none + \retval status +*/ +static int8_t scsi_read_format_capacity (usb_dev *udev, uint8_t lun, uint8_t *params) +{ + uint16_t i = 0U; + uint32_t blk_size = usbd_mem_fops->mem_block_size[lun]; + uint32_t blk_num = usbd_mem_fops->mem_block_len[lun]; + uint32_t blk_nbr = blk_num - 1U; + + usbd_msc_handler *msc = (usbd_msc_handler *)udev->class_data[USBD_MSC_INTERFACE]; + + for (i = 0U; i < 12U; i++) { + msc->bbb_data[i] = 0U; + } + + msc->bbb_data[3] = 0x08U; + msc->bbb_data[4] = (uint8_t)(blk_nbr >> 24U); + msc->bbb_data[5] = (uint8_t)(blk_nbr >> 16U); + msc->bbb_data[6] = (uint8_t)(blk_nbr >> 8U); + msc->bbb_data[7] = (uint8_t)(blk_nbr); + + msc->bbb_data[8] = 0x02U; + msc->bbb_data[9] = (uint8_t)(blk_size >> 16U); + msc->bbb_data[10] = (uint8_t)(blk_size >> 8U); + msc->bbb_data[11] = (uint8_t)(blk_size); + + msc->bbb_datalen = 12U; + + return 0; +} + +/*! + \brief process Mode Sense6 command + \param[in] udev: pointer to USB device instance + \param[in] lun: logical unit number + \param[in] params: command parameters + \param[out] none + \retval status +*/ +static int8_t scsi_mode_sense6 (usb_dev *udev, uint8_t lun, uint8_t *params) +{ + uint16_t len = 8U; + usbd_msc_handler *msc = (usbd_msc_handler *)udev->class_data[USBD_MSC_INTERFACE]; + + msc->bbb_datalen = len; + + while (len) { + len--; + msc->bbb_data[len] = msc_mode_sense6_data[len]; + } + + return 0; +} + +/*! + \brief process Mode Sense10 command + \param[in] udev: pointer to USB device instance + \param[in] lun: logical unit number + \param[in] params: command parameters + \param[out] none + \retval status +*/ +static int8_t scsi_mode_sense10 (usb_dev *udev, uint8_t lun, uint8_t *params) +{ + uint16_t len = 8U; + usbd_msc_handler *msc = (usbd_msc_handler *)udev->class_data[USBD_MSC_INTERFACE]; + + msc->bbb_datalen = len; + + while (len) { + len--; + msc->bbb_data[len] = msc_mode_sense10_data[len]; + } + + return 0; +} + +/*! + \brief process Request Sense command + \param[in] udev: pointer to USB device instance + \param[in] lun: logical unit number + \param[in] params: command parameters + \param[out] none + \retval status +*/ +static int8_t scsi_request_sense (usb_dev *udev, uint8_t lun, uint8_t *params) +{ + uint8_t i = 0U; + usbd_msc_handler *msc = (usbd_msc_handler *)udev->class_data[USBD_MSC_INTERFACE]; + + for (i = 0U; i < REQUEST_SENSE_DATA_LEN; i++) { + msc->bbb_data[i] = 0U; + } + + msc->bbb_data[0] = 0x70U; + msc->bbb_data[7] = REQUEST_SENSE_DATA_LEN - 6U; + + if ((msc->scsi_sense_head != msc->scsi_sense_tail)) { + msc->bbb_data[2] = msc->scsi_sense[msc->scsi_sense_head].SenseKey; + msc->bbb_data[12] = msc->scsi_sense[msc->scsi_sense_head].ASCQ; + msc->bbb_data[13] = msc->scsi_sense[msc->scsi_sense_head].ASC; + msc->scsi_sense_head++; + + if (msc->scsi_sense_head == SENSE_LIST_DEEPTH) { + msc->scsi_sense_head = 0U; + } + } + + msc->bbb_datalen = USB_MIN(REQUEST_SENSE_DATA_LEN, params[4]); + + return 0; +} + +/*! + \brief process Start Stop Unit command + \param[in] udev: pointer to USB device instance + \param[in] lun: logical unit number + \param[in] params: command parameters + \param[out] none + \retval status +*/ +static inline int8_t scsi_start_stop_unit (usb_dev *udev, uint8_t lun, uint8_t *params) +{ + usbd_msc_handler *msc = (usbd_msc_handler *)udev->class_data[USBD_MSC_INTERFACE]; + + msc->bbb_datalen = 0U; +// msc->scsi_disk_pop = 1U; + + return 0; +} + +/*! + \brief process Allow Medium Removal command + \param[in] udev: pointer to USB device instance + \param[in] lun: logical unit number + \param[in] params: command parameters + \param[out] none + \retval status +*/ +static inline int8_t scsi_allow_medium_removal (usb_dev *udev, uint8_t lun, uint8_t *params) +{ + usbd_msc_handler *msc = (usbd_msc_handler *)udev->class_data[USBD_MSC_INTERFACE]; + + msc->bbb_datalen = 0U; + + return 0; +} + +/*! + \brief process Read10 command + \param[in] udev: pointer to USB device instance + \param[in] lun: logical unit number + \param[in] params: command parameters + \param[out] none + \retval status +*/ +static int8_t scsi_read10 (usb_dev *udev, uint8_t lun, uint8_t *params) +{ + usbd_msc_handler *msc = (usbd_msc_handler *)udev->class_data[USBD_MSC_INTERFACE]; + + if (msc->bbb_state == BBB_IDLE) { + /* direction is from device to host */ + if (0x80U != (msc->bbb_cbw.bmCBWFlags & 0x80U)) { + scsi_sense_code (udev, msc->bbb_cbw.bCBWLUN, ILLEGAL_REQUEST, INVALID_CDB); + + return -1; + } + + if (0 != usbd_mem_fops->mem_ready(lun)) { + scsi_sense_code (udev, lun, NOT_READY, MEDIUM_NOT_PRESENT); + + return -1; + } + + msc->scsi_blk_addr = (params[2] << 24U) | (params[3] << 16U) | \ + (params[4] << 8U) | params[5]; + + msc->scsi_blk_len = (params[7] << 8U) | params[8]; + + if (scsi_check_address_range (udev, lun, msc->scsi_blk_addr, (uint16_t)msc->scsi_blk_len) < 0) { + return -1; /* error */ + } + + msc->bbb_state = BBB_DATA_IN; + + msc->scsi_blk_addr *= msc->scsi_blk_size[lun]; + msc->scsi_blk_len *= msc->scsi_blk_size[lun]; + + /* cases 4,5 : Hi <> Dn */ + if (msc->bbb_cbw.dCBWDataTransferLength != msc->scsi_blk_len) { + scsi_sense_code (udev, msc->bbb_cbw.bCBWLUN, ILLEGAL_REQUEST, INVALID_CDB); + + return -1; + } + } + + msc->bbb_datalen = MSC_MEDIA_PACKET_SIZE; + + return scsi_process_read (udev, lun); +} + +/*! + \brief process Write10 command + \param[in] udev: pointer to USB device instance + \param[in] lun: logical unit number + \param[in] params: command parameters + \param[out] none + \retval status +*/ +static int8_t scsi_write10 (usb_dev *udev, uint8_t lun, uint8_t *params) +{ + usbd_msc_handler *msc = (usbd_msc_handler *)udev->class_data[USBD_MSC_INTERFACE]; + + if (BBB_IDLE == msc->bbb_state) { + /* case 8 : Hi <> Do */ + if (0x80U == (msc->bbb_cbw.bmCBWFlags & 0x80U)) { + scsi_sense_code (udev, msc->bbb_cbw.bCBWLUN, ILLEGAL_REQUEST, INVALID_CDB); + + return -1; + } + + /* check whether media is ready */ + if (0 != usbd_mem_fops->mem_ready(lun)) { + scsi_sense_code (udev, lun, NOT_READY, MEDIUM_NOT_PRESENT); + + return -1; + } + + /* check if media is write-protected */ + if (0 != usbd_mem_fops->mem_protected(lun)) { + scsi_sense_code (udev, lun, NOT_READY, WRITE_PROTECTED); + + return -1; + } + + msc->scsi_blk_addr = (params[2] << 24U) | (params[3] << 16U) | \ + (params[4] << 8U) | params[5]; + + msc->scsi_blk_len = (params[7] << 8U) | params[8]; + + /* check if LBA address is in the right range */ + if (scsi_check_address_range (udev, lun, msc->scsi_blk_addr, (uint16_t)msc->scsi_blk_len) < 0) { + return -1; /* error */ + } + + msc->scsi_blk_addr *= msc->scsi_blk_size[lun]; + msc->scsi_blk_len *= msc->scsi_blk_size[lun]; + + /* cases 3,11,13 : Hn,Ho <> D0 */ + if (msc->bbb_cbw.dCBWDataTransferLength != msc->scsi_blk_len) { + scsi_sense_code (udev, msc->bbb_cbw.bCBWLUN, ILLEGAL_REQUEST, INVALID_CDB); + + return -1; + } + + /* prepare endpoint to receive first data packet */ + msc->bbb_state = BBB_DATA_OUT; + + usbd_ep_recev (udev, + MSC_OUT_EP, + msc->bbb_data, + USB_MIN (msc->scsi_blk_len, MSC_MEDIA_PACKET_SIZE)); + } else { /* write process ongoing */ + return scsi_process_write (udev, lun); + } + + return 0; +} + +/*! + \brief process Verify10 command + \param[in] udev: pointer to USB device instance + \param[in] lun: logical unit number + \param[in] params: command parameters + \param[out] none + \retval status +*/ +static int8_t scsi_verify10 (usb_dev *udev, uint8_t lun, uint8_t *params) +{ + usbd_msc_handler *msc = (usbd_msc_handler *)udev->class_data[USBD_MSC_INTERFACE]; + + if (0x02U == (params[1] & 0x02U)) { + scsi_sense_code (udev, lun, ILLEGAL_REQUEST, INVALID_FIELED_IN_COMMAND); + + return -1; /* error, verify mode not supported*/ + } + + if (scsi_check_address_range (udev, lun, msc->scsi_blk_addr, (uint16_t)msc->scsi_blk_len) < 0) { + return -1; /* error */ + } + + msc->bbb_datalen = 0U; + + return 0; +} + +/*! + \brief check address range + \param[in] udev: pointer to USB device instance + \param[in] lun: logical unit number + \param[in] blk_offset: block offset + \param[in] blk_nbr: number of block to be processed + \param[out] none + \retval status +*/ +static inline int8_t scsi_check_address_range (usb_dev *udev, uint8_t lun, uint32_t blk_offset, uint16_t blk_nbr) +{ + usbd_msc_handler *msc = (usbd_msc_handler *)udev->class_data[USBD_MSC_INTERFACE]; + + if ((blk_offset + blk_nbr) > msc->scsi_blk_nbr[lun]) { + scsi_sense_code (udev, lun, ILLEGAL_REQUEST, ADDRESS_OUT_OF_RANGE); + + return -1; + } + + return 0; +} + +/*! + \brief handle read process + \param[in] udev: pointer to USB device instance + \param[in] lun: logical unit number + \param[out] none + \retval status +*/ +static int8_t scsi_process_read (usb_dev *udev, uint8_t lun) +{ + usbd_msc_handler *msc = (usbd_msc_handler *)udev->class_data[USBD_MSC_INTERFACE]; + + uint32_t len = USB_MIN(msc->scsi_blk_len, MSC_MEDIA_PACKET_SIZE); + + if (usbd_mem_fops->mem_read(lun, + msc->bbb_data, + msc->scsi_blk_addr, + (uint16_t)(len / msc->scsi_blk_size[lun])) < 0) { + scsi_sense_code(udev, lun, HARDWARE_ERROR, UNRECOVERED_READ_ERROR); + + return -1; + } + + usbd_ep_send (udev, MSC_IN_EP, msc->bbb_data, len); + + msc->scsi_blk_addr += len; + msc->scsi_blk_len -= len; + + /* case 6 : Hi = Di */ + msc->bbb_csw.dCSWDataResidue -= len; + + if (0U == msc->scsi_blk_len) { + msc->bbb_state = BBB_LAST_DATA_IN; + } + + return 0; +} + +/*! + \brief handle write process + \param[in] udev: pointer to USB device instance + \param[in] lun: logical unit number + \param[out] none + \retval status +*/ +static int8_t scsi_process_write (usb_dev *udev, uint8_t lun) +{ + usbd_msc_handler *msc = (usbd_msc_handler *)udev->class_data[USBD_MSC_INTERFACE]; + + uint32_t len = USB_MIN(msc->scsi_blk_len, MSC_MEDIA_PACKET_SIZE); + + if (usbd_mem_fops->mem_write (lun, + msc->bbb_data, + msc->scsi_blk_addr, + (uint16_t)(len / msc->scsi_blk_size[lun])) < 0) { + scsi_sense_code(udev, lun, HARDWARE_ERROR, WRITE_FAULT); + + return -1; + } + + msc->scsi_blk_addr += len; + msc->scsi_blk_len -= len; + + /* case 12 : Ho = Do */ + msc->bbb_csw.dCSWDataResidue -= len; + + if (0U == msc->scsi_blk_len) { + msc_bbb_csw_send (udev, CSW_CMD_PASSED); + } else { + /* prepare endpoint to receive next packet */ + usbd_ep_recev (udev, + MSC_OUT_EP, + msc->bbb_data, + USB_MIN (msc->scsi_blk_len, MSC_MEDIA_PACKET_SIZE)); + } + + return 0; +} + +/*! + \brief process Format Unit command + \param[in] udev: pointer to USB device instance + \param[in] lun: logical unit number + \param[out] none + \retval status +*/ +static inline int8_t scsi_format_cmd (usb_dev *udev, uint8_t lun) +{ + return 0; +} + +/*! + \brief process Read_Toc command + \param[in] udev: pointer to USB device instance + \param[in] lun: logical unit number + \param[in] params: command parameters + \param[out] none + \retval status +*/ +static int8_t scsi_toc_cmd_read (usb_dev *udev, uint8_t lun, uint8_t *params) +{ + uint8_t* pPage; + uint16_t len; + + usbd_msc_handler *msc = (usbd_msc_handler *)udev->class_data[USBD_MSC_INTERFACE]; + + pPage = (uint8_t *)&usbd_mem_fops->mem_toc_data[lun * READ_TOC_CMD_LEN]; + len = (uint16_t)pPage[1] + 2U; + + msc->bbb_datalen = len; + + while (len) { + len--; + msc->bbb_data[len] = pPage[len]; + } + + return 0; +} diff --git a/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbd_library/class/device/printer/Include/printer_core.h b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbd_library/class/device/printer/Include/printer_core.h new file mode 100644 index 0000000000..02bca18e1b --- /dev/null +++ b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbd_library/class/device/printer/Include/printer_core.h @@ -0,0 +1,73 @@ +/*! + \file printer_core.h + \brief the header file of USB printer device class core functions + + \version 2020-07-17, V3.0.0, firmware for GD32F10x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef __PRINTER_CORE_H +#define __PRINTER_CORE_H + +#include "usbd_enum.h" + +/* USB printing device class code */ +#define USB_CLASS_PRINTER 0x07U + +/* printing device subclass code */ +#define USB_SUBCLASS_PRINTER 0x01U + +/* printing device protocol code */ +#define PROTOCOL_UNIDIRECTIONAL_ITF 0x01U +#define PROTOCOL_BI_DIRECTIONAL_ITF 0x02U +#define PROTOCOL_1284_4_ITF 0x03U +#define PROTOCOL_VENDOR 0xFFU + +#define DEVICE_ID_LEN 103U + +#define USB_PRINTER_CONFIG_DESC_LEN 32U + +/* printing device specific-class request */ +#define GET_DEVICE_ID 0x00U +#define GET_PORT_STATUS 0x01U +#define SOFT_RESET 0x02U + +/* USB configuration descriptor structure */ +typedef struct +{ + usb_desc_config config; + usb_desc_itf printer_itf; + usb_desc_ep printer_epin; + usb_desc_ep printer_epout; +} usb_printer_desc_config_set; + +extern usb_desc printer_desc; +extern usb_class printer_class; + +#endif /* __PRINTER_CORE_H */ diff --git a/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbd_library/class/device/printer/Source/printer_core.c b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbd_library/class/device/printer/Source/printer_core.c new file mode 100644 index 0000000000..3e91b6b3d5 --- /dev/null +++ b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbd_library/class/device/printer/Source/printer_core.c @@ -0,0 +1,310 @@ +/*! + \file printer_core.c + \brief USB printer device class core functions + + \version 2020-07-17, V3.0.0, firmware for GD32F10x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "usbd_transc.h" +#include "printer_core.h" + +#define USBD_VID 0x28E9U +#define USBD_PID 0x028DU + +/* printer port status: paper not empty/selected/no error */ +static uint8_t g_port_status = 0x18U; +uint8_t g_printer_data_buf[PRINTER_OUT_PACKET]; + +uint8_t Printer_DEVICE_ID[DEVICE_ID_LEN] = +{ + 0x00, 0x67, + 'M', 'A', 'N', 'U', 'F', 'A', 'C', 'T', 'U', 'R', 'E', 'R', ':', + 'G', 'I', 'G', 'A', ' ', 'D', 'E', 'V', 'I', 'C', 'E', '-', ';', + 'C', 'O', 'M', 'M', 'A', 'N', 'D', ' ', 'S', 'E', 'T', ':', + 'P', 'C', 'L', ',', 'M', 'P', 'L', ';', + 'M', 'O', 'D', 'E', 'L', ':', + 'L', 'a', 's', 'e', 'r', 'B', 'e', 'a', 'm', '?', ';', + 'C', 'O', 'M', 'M', 'E', 'N', 'T', ':', + 'G', 'o', 'o', 'd', ' ', '!', ';', + 'A', 'C', 'T', 'I', 'V', 'E', ' ', 'C', 'O', 'M', 'M', 'A', 'N', 'D', ' ', 'S', 'E', 'T', ':', + 'P', 'C', 'L', ';' +}; + +/* USB standard device descriptor */ +usb_desc_dev printer_dev_desc = +{ + .header = + { + .bLength = USB_DEV_DESC_LEN, + .bDescriptorType = USB_DESCTYPE_DEV, + }, + .bcdUSB = 0x0200U, + .bDeviceClass = 0x00U, + .bDeviceSubClass = 0x00U, + .bDeviceProtocol = 0x00U, + .bMaxPacketSize0 = USBD_EP0_MAX_SIZE, + .idVendor = USBD_VID, + .idProduct = USBD_PID, + .bcdDevice = 0x0100U, + .iManufacturer = STR_IDX_MFC, + .iProduct = STR_IDX_PRODUCT, + .iSerialNumber = STR_IDX_SERIAL, + .bNumberConfigurations = USBD_CFG_MAX_NUM, +}; + +/* USB device configuration descriptor */ +usb_printer_desc_config_set printer_config_desc = +{ + .config = + { + .header = + { + .bLength = sizeof(usb_desc_config), + .bDescriptorType = USB_DESCTYPE_CONFIG + }, + .wTotalLength = USB_PRINTER_CONFIG_DESC_LEN, + .bNumInterfaces = 0x01U, + .bConfigurationValue = 0x01U, + .iConfiguration = 0x00U, + .bmAttributes = 0xA0U, + .bMaxPower = 0x32U + }, + + .printer_itf = + { + .header = + { + .bLength = sizeof(usb_desc_itf), + .bDescriptorType = USB_DESCTYPE_ITF + }, + .bInterfaceNumber = 0x00U, + .bAlternateSetting = 0x00U, + .bNumEndpoints = 0x02U, + .bInterfaceClass = USB_CLASS_PRINTER, + .bInterfaceSubClass = USB_SUBCLASS_PRINTER, + .bInterfaceProtocol = PROTOCOL_BI_DIRECTIONAL_ITF, + .iInterface = 0x00U + }, + + .printer_epin = + { + .header = + { + .bLength = sizeof(usb_desc_ep), + .bDescriptorType = USB_DESCTYPE_EP + }, + .bEndpointAddress = PRINTER_IN_EP, + .bmAttributes = USB_EP_ATTR_BULK, + .wMaxPacketSize = PRINTER_IN_PACKET, + .bInterval = 0x00U + }, + + .printer_epout = + { + .header = + { + .bLength = sizeof(usb_desc_ep), + .bDescriptorType = USB_DESCTYPE_EP + }, + .bEndpointAddress = PRINTER_OUT_EP, + .bmAttributes = USB_EP_ATTR_BULK, + .wMaxPacketSize = PRINTER_OUT_PACKET, + .bInterval = 0x00U + }, +}; + +/* USB language ID Descriptor */ +static usb_desc_LANGID usbd_language_id_desc = +{ + .header = + { + .bLength = sizeof(usb_desc_LANGID), + .bDescriptorType = USB_DESCTYPE_STR, + }, + .wLANGID = ENG_LANGID +}; + +/* USB manufacture string */ +static usb_desc_str manufacturer_string = +{ + .header = + { + .bLength = USB_STRING_LEN(10U), + .bDescriptorType = USB_DESCTYPE_STR, + }, + .unicode_string = {'G', 'i', 'g', 'a', 'D', 'e', 'v', 'i', 'c', 'e'} +}; + +/* USB product string */ +static usb_desc_str product_string = +{ + .header = + { + .bLength = USB_STRING_LEN(16U), + .bDescriptorType = USB_DESCTYPE_STR, + }, + .unicode_string = {'G', 'D', '3', '2', '-', 'U', 'S', 'B', '_', 'P', 'r', 'i', 'n', 't', 'e', 'r'} +}; + +/* USB serial string */ +static usb_desc_str serial_string = +{ + .header = + { + .bLength = USB_STRING_LEN(12U), + .bDescriptorType = USB_DESCTYPE_STR, + } +}; + +/* USB string descriptor set */ +static uint8_t* usbd_msc_strings[] = +{ + [STR_IDX_LANGID] = (uint8_t *)&usbd_language_id_desc, + [STR_IDX_MFC] = (uint8_t *)&manufacturer_string, + [STR_IDX_PRODUCT] = (uint8_t *)&product_string, + [STR_IDX_SERIAL] = (uint8_t *)&serial_string +}; + +usb_desc printer_desc = { + .dev_desc = (uint8_t *)&printer_dev_desc, + .config_desc = (uint8_t *)&printer_config_desc, + .strings = usbd_msc_strings +}; + +/* local function prototypes ('static') */ +static uint8_t printer_init (usb_dev *udev, uint8_t config_index); +static uint8_t printer_deinit (usb_dev *udev, uint8_t config_index); +static uint8_t printer_req_handler (usb_dev *udev, usb_req *req); +static void printer_data_in (usb_dev *udev, uint8_t ep_num); +static void printer_data_out (usb_dev *udev, uint8_t ep_num); + +usb_class printer_class = { + .init = printer_init, + .deinit = printer_deinit, + .req_process = printer_req_handler, + .data_in = printer_data_in, + .data_out = printer_data_out +}; +/*! + \brief initialize the printer device + \param[in] udev: pointer to USB device instance + \param[in] config_index: configuration index + \param[out] none + \retval USB device operation status +*/ +static uint8_t printer_init (usb_dev *udev, uint8_t config_index) +{ + /* initialize the data TX/RX endpoint */ + usbd_ep_init(udev, EP_BUF_SNG, BULK_TX_ADDR, &(printer_config_desc.printer_epin)); + usbd_ep_init(udev, EP_BUF_SNG, BULK_RX_ADDR, &(printer_config_desc.printer_epout)); + + udev->ep_transc[EP_ID(PRINTER_IN_EP)][TRANSC_IN] = printer_class.data_in; + udev->ep_transc[PRINTER_OUT_EP][TRANSC_OUT] = printer_class.data_out; + + /* prepare to receive data */ + usbd_ep_recev(udev, PRINTER_OUT_EP, g_printer_data_buf, PRINTER_OUT_PACKET); + + return USBD_OK; +} + +/*! + \brief deinitialize the printer device + \param[in] udev: pointer to USB device instance + \param[in] config_index: configuration index + \param[out] none + \retval USB device operation status +*/ +static uint8_t printer_deinit (usb_dev *udev, uint8_t config_index) +{ + /* deinitialize the data TX/RX endpoint */ + usbd_ep_deinit(udev, PRINTER_IN_EP); + usbd_ep_deinit(udev, PRINTER_OUT_EP); + + return USBD_OK; +} + +/*! + \brief handle the printer class-specific requests + \param[in] udev: pointer to USB device instance + \param[in] req: device class-specific request + \param[out] none + \retval USB device operation status +*/ +static uint8_t printer_req_handler (usb_dev *udev, usb_req *req) +{ + uint8_t status = REQ_NOTSUPP; + + switch (req->bRequest) { + case GET_DEVICE_ID: + usb_transc_config(&udev->transc_in[0], Printer_DEVICE_ID, DEVICE_ID_LEN, 0U); + + status = REQ_SUPP; + break; + + case GET_PORT_STATUS: + usb_transc_config(&udev->transc_in[0], (uint8_t *)&g_port_status, 1U, 0U); + + status = REQ_SUPP; + break; + + case SOFT_RESET: + usbd_ep_recev(udev, PRINTER_OUT_EP, g_printer_data_buf, PRINTER_OUT_PACKET); + + status = REQ_SUPP; + break; + + default: + break; + } + + return status; +} + +/*! + \brief handle printer data + \param[in] udev: pointer to USB device instance + \param[in] ep_num: endpoint number + \param[out] none + \retval none +*/ +static void printer_data_in (usb_dev *udev, uint8_t ep_num) +{ +} + +/*! + \brief handle printer data + \param[in] udev: pointer to USB device instance + \param[in] ep_num: endpoint number + \param[out] none + \retval none +*/ +static void printer_data_out (usb_dev *udev, uint8_t ep_num) +{ +} diff --git a/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbd_library/device/Include/usb_ch9_std.h b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbd_library/device/Include/usb_ch9_std.h new file mode 100644 index 0000000000..d1f563a39d --- /dev/null +++ b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbd_library/device/Include/usb_ch9_std.h @@ -0,0 +1,211 @@ +/*! + \file usb_ch9_std.h + \brief USB 2.0 standard defines + + \version 2020-07-17, V3.0.0, firmware for GD32F10x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef __USB_CH9_STD_H +#define __USB_CH9_STD_H + +#include "usbd_conf.h" + +#define USB_DEV_QUALIFIER_DESC_LEN 0x0AU /*!< USB device qualifier descriptor length */ +#define USB_DEV_DESC_LEN 0x12U /*!< USB device descriptor length */ +#define USB_CFG_DESC_LEN 0x09U /*!< USB configuration descriptor length */ +#define USB_ITF_DESC_LEN 0x09U /*!< USB interface descriptor length */ +#define USB_EP_DESC_LEN 0x07U /*!< USB endpoint descriptor length */ +#define USB_BOS_DESC_LEN 0x0CU /*!< USB BOS descriptor length */ +#define USB_OTG_DESC_LEN 0x03U /*!< USB device OTG descriptor length */ +#define USB_SETUP_PACKET_LEN 0x08U /*!< USB SETUP packet length */ +#define USB_DEVICE_CAPABITY 0x10U /*!< USB device capabity */ + +/* bit 7 of bmRequestType: data phase transfer direction */ +#define USB_TRX_MASK 0x80U /*!< USB transfer direction mask */ +#define USB_TRX_OUT 0x00U /*!< USB transfer OUT direction */ +#define USB_TRX_IN 0x80U /*!< USB transfer IN direction */ + +/* bit 6..5 of bmRequestType: request type */ +#define USB_REQTYPE_STRD 0x00U /*!< USB standard request */ +#define USB_REQTYPE_CLASS 0x20U /*!< USB class request */ +#define USB_REQTYPE_VENDOR 0x40U /*!< USB vendor request */ +#define USB_REQTYPE_MASK 0x60U /*!< USB request mask */ + +#define USBD_BUS_POWERED 0x00U /*!< USB bus power supply */ +#define USBD_SELF_POWERED 0x01U /*!< USB self power supply */ + +#define USB_STATUS_REMOTE_WAKEUP 2U /*!< USB is in remote wakeup status */ +#define USB_STATUS_SELF_POWERED 1U /*!< USB is in self powered status */ + +/* bit 4..0 of bmRequestType: recipient type */ +enum _usb_recp_type { + USB_RECPTYPE_DEV = 0x0U, /*!< USB device request type */ + USB_RECPTYPE_ITF = 0x1U, /*!< USB interface request type */ + USB_RECPTYPE_EP = 0x2U, /*!< USB endpoint request type */ + USB_RECPTYPE_MASK = 0x3U /*!< USB request type mask */ +}; + +/* bRequest value */ +enum _usb_request { + USB_GET_STATUS = 0x0U, /*!< USB get status request */ + USB_CLEAR_FEATURE = 0x1U, /*!< USB clear feature request */ + USB_RESERVED2 = 0x2U, /*!< USB reserved2 */ + USB_SET_FEATURE = 0x3U, /*!< USB set feature request */ + USB_RESERVED4 = 0x4U, /*!< USB reserved4 */ + USB_SET_ADDRESS = 0x5U, /*!< USB set address request */ + USB_GET_DESCRIPTOR = 0x6U, /*!< USB get descriptor request */ + USB_SET_DESCRIPTOR = 0x7U, /*!< USB set descriptor request */ + USB_GET_CONFIGURATION = 0x8U, /*!< USB get configuration request */ + USB_SET_CONFIGURATION = 0x9U, /*!< USB set configuration request */ + USB_GET_INTERFACE = 0xAU, /*!< USB get interface request */ + USB_SET_INTERFACE = 0xBU, /*!< USB set interface request */ + USB_SYNCH_FRAME = 0xCU /*!< USB synchronized frame request */ +}; + +/* descriptor types of USB specifications */ +enum _usb_desctype { + USB_DESCTYPE_DEV = 0x1U, /*!< USB device descriptor type */ + USB_DESCTYPE_CONFIG = 0x2U, /*!< USB configuration descriptor type */ + USB_DESCTYPE_STR = 0x3U, /*!< USB string descriptor type */ + USB_DESCTYPE_ITF = 0x4U, /*!< USB interface descriptor type */ + USB_DESCTYPE_EP = 0x5U, /*!< USB endpoint descriptor type */ + USB_DESCTYPE_DEV_QUALIFIER = 0x6U, /*!< USB device qualifier descriptor type */ + USB_DESCTYPE_OTHER_SPD_CONFIG = 0x7U, /*!< USB other speed configuration descriptor type */ + USB_DESCTYPE_ITF_POWER = 0x8U, /*!< USB interface power descriptor type */ + USB_DESCTYPE_BOS = 0xFU /*!< USB BOS descriptor type */ +}; + +/* USB endpoint descriptor bmAttributes bit definitions */ +/* bits 1..0 : transfer type */ +enum _usbx_type { + USB_EP_ATTR_CTL = 0x0U, /*!< USB endpoint control attributes*/ + USB_EP_ATTR_ISO = 0x1U, /*!< USB endpoint isochronous attributes*/ + USB_EP_ATTR_BULK = 0x2U, /*!< USB endpoint bulk attributes*/ + USB_EP_ATTR_INT = 0x3U /*!< USB endpoint interrupt attributes*/ +}; + +/* bits 3..2 : Sync type (only if ISOCHRONOUS) */ +#define USB_EP_ATTR_NOSYNC 0x00U /*!< USB endpoint no SYNC attributes*/ +#define USB_EP_ATTR_ASYNC 0x04U /*!< USB endpoint ASYNC attributes*/ +#define USB_EP_ATTR_ADAPTIVE 0x08U /*!< USB endpoint adaptive attributes*/ +#define USB_EP_ATTR_SYNC 0x0CU /*!< USB endpoint SYNC attributes*/ +#define USB_EP_ATTR_SYNCTYPE 0x0CU /*!< USB endpoint SYNC type attributes*/ + +/* bits 5..4 : usage type (only if ISOCHRONOUS) */ +#define USB_EP_ATTR_DATA 0x00U /*!< USB endpoint data attributes*/ +#define USB_EP_ATTR_FEEDBACK 0x10U /*!< USB endpoint feedback attributes*/ +#define USB_EP_ATTR_IMPLICIT_FEEDBACK_DATA 0x20U /*!< USB endpoint implicit feedback attributes*/ +#define USB_EP_ATTR_USAGETYPE 0x30U /*!< USB endpoint usage type attributes*/ + +#pragma pack(1) + +/* USB standard device request structure */ +typedef struct _usb_req { + uint8_t bmRequestType; /*!< type of request */ + uint8_t bRequest; /*!< request of setup packet */ + uint16_t wValue; /*!< value of setup packet */ + uint16_t wIndex; /*!< index of setup packet */ + uint16_t wLength; /*!< length of setup packet */ +} usb_req; + +/* USB setup packet definition */ +typedef union _usb_setup { + uint8_t data[8]; /*!< USB setup data */ + + usb_req req; /*!< USB setup request */ +} usb_setup; + +/* USB descriptor definition */ +typedef struct _usb_desc_header { + uint8_t bLength; /*!< size of the descriptor */ + uint8_t bDescriptorType; /*!< type of the descriptor */ +} usb_desc_header; + +typedef struct _usb_desc_dev { + usb_desc_header header; /*!< descriptor header, including type and size */ + uint16_t bcdUSB; /*!< BCD of the supported USB specification */ + uint8_t bDeviceClass; /*!< USB device class */ + uint8_t bDeviceSubClass; /*!< USB device subclass */ + uint8_t bDeviceProtocol; /*!< USB device protocol */ + uint8_t bMaxPacketSize0; /*!< size of the control (address 0) endpoint's bank in bytes */ + uint16_t idVendor; /*!< vendor ID for the USB product */ + uint16_t idProduct; /*!< unique product ID for the USB product */ + uint16_t bcdDevice; /*!< product release (version) number */ + uint8_t iManufacturer; /*!< string index for the manufacturer's name */ + uint8_t iProduct; /*!< string index for the product name/details */ + uint8_t iSerialNumber; /*!< string index for the product's globally unique hexadecimal serial number */ + uint8_t bNumberConfigurations; /*!< total number of configurations supported by the device */ +} usb_desc_dev; + +typedef struct _usb_desc_config { + usb_desc_header header; /*!< descriptor header, including type and size */ + uint16_t wTotalLength; /*!< size of the configuration descriptor header, and all sub descriptors inside the configuration */ + uint8_t bNumInterfaces; /*!< total number of interfaces in the configuration */ + uint8_t bConfigurationValue; /*!< configuration index of the current configuration */ + uint8_t iConfiguration; /*!< index of a string descriptor describing the configuration */ + uint8_t bmAttributes; /*!< configuration attributes */ + uint8_t bMaxPower; /*!< maximum power consumption of the device while in the current configuration */ +} usb_desc_config; + +typedef struct _usb_desc_itf { + usb_desc_header header; /*!< descriptor header, including type and size */ + uint8_t bInterfaceNumber; /*!< index of the interface in the current configuration */ + uint8_t bAlternateSetting; /*!< alternate setting for the interface number */ + uint8_t bNumEndpoints; /*!< total number of endpoints in the interface */ + uint8_t bInterfaceClass; /*!< interface class ID */ + uint8_t bInterfaceSubClass; /*!< interface subclass ID */ + uint8_t bInterfaceProtocol; /*!< interface protocol ID */ + uint8_t iInterface; /*!< index of the string descriptor describing the interface */ +} usb_desc_itf; + +typedef struct _usb_desc_ep { + usb_desc_header header; /*!< descriptor header, including type and size */ + uint8_t bEndpointAddress; /*!< logical address of the endpoint */ + uint8_t bmAttributes; /*!< endpoint attribute */ + uint16_t wMaxPacketSize; /*!< size of the endpoint bank, in bytes */ + uint8_t bInterval; /*!< polling interval in milliseconds for the endpoint if it is an INTERRUPT or ISOCHRONOUS type */ +} usb_desc_ep; + +typedef struct _usb_desc_LANGID { + usb_desc_header header; /*!< descriptor header, including type and size. */ + uint16_t wLANGID; /*!< LANGID code */ +} usb_desc_LANGID; + +typedef struct _usb_desc_str { + usb_desc_header header; /*!< descriptor header, including type and size. */ + uint16_t unicode_string[64]; /*!< unicode string data */ +} usb_desc_str; + +#pragma pack() + +/* compute string descriptor length */ +#define USB_STRING_LEN(unicode_chars) (sizeof(usb_desc_header) + ((unicode_chars) << 1)) + +#endif /* __USB_CH9_STD_H */ diff --git a/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbd_library/device/Include/usbd_core.h b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbd_library/device/Include/usbd_core.h new file mode 100644 index 0000000000..44ba5c72ce --- /dev/null +++ b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbd_library/device/Include/usbd_core.h @@ -0,0 +1,333 @@ +/*! + \file usbd_core.h + \brief USB device driver core + + \version 2020-07-17, V3.0.0, firmware for GD32F10x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef __USBD_CORE_H +#define __USBD_CORE_H + +#include "usb_ch9_std.h" + +/* endpoints definitions */ +#define EP_IN(x) ((uint8_t)(0x80U | (x))) +#define EP_OUT(x) ((uint8_t)(x)) + +#define EP_DIR(x) ((uint8_t)((x) >> 7U)) +#define EP_ID(x) ((uint8_t)((x) & 0x7FU)) + +/* USB device endpoint0 max packet size */ +#define USBD_EP0_MAX_SIZE 64U + +#define USBD_TRANSC_COUNT 3U + +/* USB device operation status */ +enum usbd_status { + USBD_UNCONNECTED = 0U, /*!< USB device unconnected status */ + USBD_DEFAULT, /*!< USB device default status */ + USBD_ADDRESSED, /*!< USB device addressed status */ + USBD_CONFIGURED, /*!< USB device configured status */ + USBD_SUSPENDED, /*!< USB device suspended status */ + USBD_CONNECTED /*!< USB device connected status */ +}; + +/* USB device operation state */ +enum usbd_state { + USBD_OK = 0U, /*!< USB device OK state */ + USBD_BUSY, /*!< USB device busy state */ + USBD_FAIL /*!< USB device fail state */ +}; + +/* USB device type */ +enum usbd_transc { + TRANSC_SETUP = 0U, /*!< SETUP transaction */ + TRANSC_OUT, /*!< OUT transaction */ + TRANSC_IN, /*!< IN transaction */ + TRANSC_UNKNOWN /*!< unknown transaction */ +}; + +/* USB device endpoint buffer type */ +enum usbd_ep_kind { + EP_BUF_SNG = 0U, /*!< single buffer endpoint type value */ + EP_BUF_DBL /*!< double buffer endpoint type value */ +}; + +/* USB device transaction structure */ +typedef struct { + uint8_t max_len; /*!< packet max length */ + uint8_t ep_stall; /*!< endpoint STALL */ + + uint8_t *xfer_buf; /*!< transfer buffer */ + uint16_t xfer_len; /*!< transfer length */ + uint16_t xfer_count; /*!< transfer count */ +} usb_transc; + +/* USB device basic structure */ +typedef struct { + uint8_t max_ep_count; /*!< endpoint max count */ + uint8_t twin_buf; /*!< double buffer */ + uint16_t ram_size; /*!< ram size */ +} usb_basic; + +/* USB descriptor */ +typedef struct { + uint8_t *dev_desc; /*!< device descriptor */ + uint8_t *config_desc; /*!< configure descriptor */ + uint8_t *bos_desc; /*!< BOS descriptor */ + uint8_t **strings; /*!< strings descriptor */ +} usb_desc; + +/* USB power management */ +typedef struct { + uint8_t power_mode; /*!< power mode */ + uint8_t power_low; /*!< power low */ + uint8_t esof_count; /*!< ESOF count */ + uint8_t suspend_enabled; /*!< suspend enabled flag */ + uint8_t remote_wakeup; /*!< remote wakeup */ + uint8_t remote_wakeup_on; /*!< remote wakeup enable */ + uint8_t lpm_enable; /*!< LPM enable */ +} usb_pm; + +/* USB LPM management */ +typedef struct { + uint32_t besl; /*!< BESL */ + uint32_t L1_resume; /*!< L1 resume */ + uint32_t L1_remote_wakeup; /*!< L1 remote wakeup */ +} usb_lpm; + +/* USB control information */ +typedef struct { + usb_req req; /*!< USB request */ + uint8_t ctl_zlp; /*!< control zero length packet */ +} usb_control; + +typedef struct _usb_dev usb_dev; +typedef struct _usb_handler usb_handler; +typedef void (*usb_ep_transc) (usb_dev *usbd_dev, uint8_t ep_num); + +/* USB class structure */ +typedef struct { + uint8_t req_cmd; + uint8_t req_altset; + + uint8_t (*init) (usb_dev *udev, uint8_t config_index); + uint8_t (*deinit) (usb_dev *udev, uint8_t config_index); + + uint8_t (*req_process) (usb_dev *udev, usb_req *req); + + uint8_t (*ctlx_in) (usb_dev *udev); + uint8_t (*ctlx_out) (usb_dev *udev); + + void (*data_in) (usb_dev *udev, uint8_t ep_num); + void (*data_out) (usb_dev *udev, uint8_t ep_num); +} usb_class; + +/* USB core driver structure */ +struct _usb_dev { + /* basic parameters */ + uint8_t config; + uint8_t dev_addr; + + __IO uint8_t cur_status; + __IO uint8_t backup_status; + + usb_pm pm; +#ifdef LPM_ENABLED + usb_lpm lpm; +#endif /* LPM_ENABLED */ + usb_control control; + + usb_transc transc_out[EP_COUNT]; + usb_transc transc_in[EP_COUNT]; + + usb_ep_transc ep_transc[EP_COUNT][USBD_TRANSC_COUNT]; + + /* device class */ + usb_desc *desc; + usb_class *class_core; + usb_handler *drv_handler; + + void *class_data[USBD_ITF_MAX_NUM]; + void *user_data; + void *data; +}; + +typedef struct +{ + uint8_t (*SOF) (usb_dev *udev); /*!< SOF ISR callback */ +} usbd_int_cb_struct; + +/* USB handler structure */ +struct _usb_handler { + void (*init) (void); + void (*deinit) (void); + + void (*dp_pullup) (FlagStatus status); + void (*set_addr) (usb_dev *udev); + void (*suspend) (void); + void (*suspend_leave) (void); + void (*resume) (usb_dev *udev); + + void (*ep_reset) (usb_dev *udev); + void (*ep_setup) (usb_dev *udev, uint8_t buf_kind, uint32_t buf_addr, const usb_desc_ep *ep_desc); + void (*ep_disable) (usb_dev *udev, uint8_t ep_addr); + void (*ep_rx_enable) (usb_dev *udev, uint8_t ep_num); + void (*ep_write) (uint8_t *fifo, uint8_t ep_num, uint16_t bytes); + uint16_t (*ep_read) (uint8_t *fifo, uint8_t ep_num, uint8_t buf_kind); + void (*ep_stall_set) (usb_dev *udev, uint8_t ep_addr); + void (*ep_stall_clear) (usb_dev *udev, uint8_t ep_addr); + uint8_t (*ep_status_get) (usb_dev *udev, uint8_t ep_addr); +}; + +extern usbd_int_cb_struct *usbd_int_fops; + +/* static inline function definitions */ +/*! + \brief device connect + \param[in] udev: pointer to USB core instance + \param[out] none + \retval none +*/ +__STATIC_INLINE void usbd_connect (usb_dev *udev) +{ + udev->drv_handler->dp_pullup(SET); + + udev->cur_status = (uint8_t)USBD_CONNECTED; +} + + +/*! + \brief device disconnect + \param[in] udev: pointer to USB core instance + \param[out] none + \retval none +*/ +__STATIC_INLINE void usbd_disconnect (usb_dev *udev) +{ + udev->drv_handler->dp_pullup(RESET); + + udev->cur_status = (uint8_t)USBD_UNCONNECTED; +} + +/*! + \brief device core register configure when stop device + \param[in] udev: pointer to USB core instance + \param[out] none + \retval none +*/ +__STATIC_INLINE void usbd_core_deinit (usb_dev *udev) +{ + udev->drv_handler->deinit(); +} + +/*! + \brief initialize endpoint + \param[in] udev: pointer to USB core instance + \param[in] buf_kind: endpoint buffer kind + \param[in] buf_addr: buffer address + \param[in] ep_desc: pointer to endpoint descriptor + \param[out] none + \retval none +*/ +__STATIC_INLINE void usbd_ep_init (usb_dev *udev, uint8_t buf_kind, uint32_t buf_addr, const usb_desc_ep *ep_desc) +{ + udev->drv_handler->ep_setup(udev, buf_kind, buf_addr, ep_desc); +} + +/*! + \brief configure the endpoint when it is disabled + \param[in] udev: pointer to USB core instance + \param[in] ep_addr: endpoint address + in this parameter: + bit0..bit6: endpoint number (0..7) + bit7: endpoint direction which can be IN(1) or OUT(0) + \param[out] none + \retval none +*/ +__STATIC_INLINE void usbd_ep_deinit (usb_dev *udev, uint8_t ep_addr) +{ + udev->drv_handler->ep_disable(udev, ep_addr); +} + +/*! + \brief set an endpoint to STALL status + \param[in] udev: pointer to USB core instance + \param[in] ep_addr: endpoint address + in this parameter: + bit0..bit6: endpoint number (0..7) + bit7: endpoint direction which can be IN(1) or OUT(0) + \param[out] none + \retval none +*/ +__STATIC_INLINE void usbd_ep_stall (usb_dev *udev, uint8_t ep_addr) +{ + udev->drv_handler->ep_stall_set(udev, ep_addr); +} + +/*! + \brief clear endpoint stalled status + \param[in] udev: pointer to USB core instance + \param[in] ep_addr: endpoint address + in this parameter: + bit0..bit6: endpoint number (0..7) + bit7: endpoint direction which can be IN(1) or OUT(0) + \param[out] none + \retval none +*/ +__STATIC_INLINE void usbd_ep_clear_stall (usb_dev *udev, uint8_t ep_addr) +{ + udev->drv_handler->ep_stall_clear(udev, ep_addr); +} + +/*! + \brief get endpoint status + \param[in] udev: pointer to USB core instance + \param[in] ep_addr: endpoint address + in this parameter: + bit0..bit6: endpoint number (0..7) + bit7: endpoint direction which can be IN(1) or OUT(0) + \param[out] none + \retval none +*/ +__STATIC_INLINE uint8_t usbd_ep_status_get (usb_dev *udev, uint8_t ep_addr) +{ + return udev->drv_handler->ep_status_get(udev, ep_addr); +} + +/* function declarations */ +/* initialize USBD */ +void usbd_init(usb_dev *udev, usb_desc *desc, usb_class *usbc); +/* endpoint prepare to transmit data */ +void usbd_ep_send (usb_dev *udev, uint8_t ep_addr, uint8_t *pbuf, uint16_t buf_len); +/* endpoint prepare to receive data */ +void usbd_ep_recev (usb_dev *udev, uint8_t ep_addr, uint8_t *pbuf, uint16_t buf_len); + +#endif /* __USBD_CORE_H */ diff --git a/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbd_library/device/Include/usbd_enum.h b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbd_library/device/Include/usbd_enum.h new file mode 100644 index 0000000000..5f0f4e2745 --- /dev/null +++ b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbd_library/device/Include/usbd_enum.h @@ -0,0 +1,111 @@ +/*! + \file usbd_enum.h + \brief USB enumeration definitions + + \version 2020-07-17, V3.0.0, firmware for GD32F10x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef __USBD_ENUM_H +#define __USBD_ENUM_H + +#include "usbd_core.h" +#include "usb_ch9_std.h" + +#ifndef NULL + #define NULL 0U +#endif + +/* request state enumeration */ +typedef enum _usb_reqsta +{ + REQ_SUPP = 0x0U, /* supported request */ + REQ_NOTSUPP = 0x1U /* unsupported request */ +} usb_reqsta; + +/* string descriptor index enumeration */ +enum _str_index +{ + STR_IDX_LANGID = 0x0U, /* language ID string index */ + STR_IDX_MFC = 0x1U, /* manufacturer string index */ + STR_IDX_PRODUCT = 0x2U, /* product string index */ + STR_IDX_SERIAL = 0x3U, /* serial string index */ + STR_IDX_CONFIG = 0x4U, /* configuration string index */ + STR_IDX_ITF = 0x5U, /* interface string index */ + STR_IDX_MAX = 0x6U /* string index max value */ +}; + +/* PWR status enumeration */ +typedef enum +{ + USB_PWRSTA_SELF_POWERED = 0x1U, /* USB is in self powered status */ + USB_PWRSTA_REMOTE_WAKEUP = 0x2U, /* USB is in remote wakeup status */ +} usb_pwrsta; + +/* USB endpoint feature enumeration */ +typedef enum +{ + USB_FEATURE_EP_HALT = 0x0U, /* USB has endpoint halt feature */ + USB_FEATURE_REMOTE_WAKEUP = 0x1U, /* USB has endpoint remote wakeup feature */ + USB_FEATURE_TEST_MODE = 0x2U /* USB has endpoint test mode feature */ +} usb_feature; + +#define ENG_LANGID 0x0409U /* english language ID */ +#define CHN_LANGID 0x0804U /* chinese language ID */ + +/* device unique ID */ +#define DEVICE_ID1 (0x1FFFF7E8U) /* device ID1 */ +#define DEVICE_ID2 (0x1FFFF7ECU) /* device ID2 */ +#define DEVICE_ID3 (0x1FFFF7F0U) /* device ID3 */ + +#define DEVICE_ID (0x40022100U) /* device ID information */ + +//#define USB_SERIAL_STRING_SIZE 0x1AU + +/* USB device exported macros */ +#define BYTE_SWAP(addr) (((uint16_t)(*((uint8_t *)(addr)))) + \ + (uint16_t)(((uint16_t)(*(((uint8_t *)(addr)) + 1U))) << 8U)) +#define BYTE_LOW(x) ((uint8_t)((x) & 0x00FFU)) +#define BYTE_HIGH(x) ((uint8_t)(((x) & 0xFF00U) >> 8U)) + +#define USB_MIN(a, b) (((a) < (b)) ? (a) : (b)) + +#define CTL_EP(ep) (((ep) == 0x00U) || ((ep) == 0x80U)) + +/* function declarations */ +/* handle USB standard device request */ +usb_reqsta usbd_standard_request (usb_dev *udev, usb_req *req); +/* handle device class request */ +usb_reqsta usbd_class_request (usb_dev *udev, usb_req *req); +/* handle USB vendor request */ +usb_reqsta usbd_vendor_request (usb_dev *udev, usb_req *req); +/* get serial string */ +void serial_string_get (uint16_t *unicode_str); + +#endif /* __USBD_ENUM_H */ diff --git a/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbd_library/device/Include/usbd_pwr.h b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbd_library/device/Include/usbd_pwr.h new file mode 100644 index 0000000000..dcdb2183bc --- /dev/null +++ b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbd_library/device/Include/usbd_pwr.h @@ -0,0 +1,67 @@ +/*! + \file usbd_pwr.h + \brief USB device power management functions prototype + + \version 2020-07-17, V3.0.0, firmware for GD32F10x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef __USBD_PWR_H +#define __USBD_PWR_H + +#include "usbd_core.h" + +/* static inline function definitions */ +/*! + \brief first operation of USB wakeup is to wakeup MCU + \param[in] udev: pointer to USB core instance + \param[out] none + \retval none +*/ +__STATIC_INLINE void resume_mcu (usb_dev *udev) +{ + udev->drv_handler->suspend_leave(); +} + +/*! + \brief set USB device to suspend mode + \param[in] udev: pointer to USB core instance + \param[out] none + \retval none +*/ +__STATIC_INLINE void usbd_to_suspend (usb_dev *udev) +{ + udev->drv_handler->suspend(); +} + +/* function declarations */ +/* start to remote wakeup */ +void usbd_remote_wakeup_active (usb_dev *udev); + +#endif /* __USBD_PWR_H */ diff --git a/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbd_library/device/Include/usbd_transc.h b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbd_library/device/Include/usbd_transc.h new file mode 100644 index 0000000000..eb9a8138e1 --- /dev/null +++ b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbd_library/device/Include/usbd_transc.h @@ -0,0 +1,64 @@ +/*! + \file usbd_transc.h + \brief USBD transaction + + \version 2020-07-17, V3.0.0, firmware for GD32F10x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef __USB_TRANSC_H +#define __USB_TRANSC_H + +#include "usbd_core.h" + +/*! + \brief USB transaction configure + \param[in] transc: pointer to USB device transaction instance + \param[in] buf: transfer data buffer + \param[in] len: transfer data length + \param[in] count: transfer data counter + \param[out] none + \retval none +*/ +__STATIC_INLINE void usb_transc_config (usb_transc *transc, uint8_t *buf, uint16_t len, uint16_t count) +{ + transc->xfer_buf = buf; + transc->xfer_len = len; + transc->xfer_count = count; +} + +/* function declarations */ +/* process USB SETUP transaction */ +void _usb_setup_transc (usb_dev *udev, uint8_t ep_num); +/* process USB OUT transaction */ +void _usb_out0_transc (usb_dev *udev, uint8_t ep_num); +/* process USB IN transaction */ +void _usb_in0_transc (usb_dev *udev, uint8_t ep_num); + +#endif /* __USB_TRANSC_H */ diff --git a/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbd_library/device/Source/usbd_core.c b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbd_library/device/Source/usbd_core.c new file mode 100644 index 0000000000..6ad4188b2e --- /dev/null +++ b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbd_library/device/Source/usbd_core.c @@ -0,0 +1,127 @@ +/*! + \file usbd_core.c + \brief USB device driver + + \version 2020-07-17, V3.0.0, firmware for GD32F10x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "usbd_core.h" +#include "usbd_enum.h" +#include "usbd_transc.h" +#include "usbd_lld_core.h" + +usbd_int_cb_struct *usbd_int_fops = NULL; + +/*! + \brief configure USB device initialization + \param[in] udev: pointer to USB core instance + \param[in] desc: pointer to USB descriptor + \param[in] usbc: USB class + \param[out] none + \retval none +*/ +void usbd_init (usb_dev *udev, usb_desc *desc, usb_class *usbc) +{ + /* configure USBD core basic attributes */ + usbd_core.basic.max_ep_count = 8U; + usbd_core.basic.twin_buf = 1U; + usbd_core.basic.ram_size = 512U; + + usbd_core.dev = udev; + + udev->desc = desc; + udev->class_core = usbc; + udev->drv_handler = &usbd_drv_handler; + + udev->ep_transc[0][TRANSC_SETUP] = _usb_setup_transc; + udev->ep_transc[0][TRANSC_OUT] = _usb_out0_transc; + udev->ep_transc[0][TRANSC_IN] = _usb_in0_transc; + + /* configure power management */ + udev->pm.power_mode = (udev->desc->config_desc[7] & 0x40U) >> 5; + + /* enable USB suspend */ + udev->pm.suspend_enabled = 1U; + + /* USB low level initialization */ + udev->drv_handler->init(); + + /* create serial string */ + serial_string_get((uint16_t *)udev->desc->strings[STR_IDX_SERIAL]); +} + +/*! + \brief endpoint prepare to receive data + \param[in] udev: pointer to USB core instance + \param[in] ep_addr: endpoint address + in this parameter: + bit0..bit6: endpoint number (0..7) + bit7: endpoint direction which can be IN(1) or OUT(0) + \param[in] pbuf: user buffer address pointer + \param[in] buf_len: buffer length + \param[out] none + \retval none +*/ +void usbd_ep_recev (usb_dev *udev, uint8_t ep_addr, uint8_t *pbuf, uint16_t buf_len) +{ + /* configure the transaction level parameters */ + usb_transc *transc = &udev->transc_out[EP_ID(ep_addr)]; + + usb_transc_config(transc, pbuf, buf_len, 0U); + + /* enable endpoint to receive */ + udev->drv_handler->ep_rx_enable(udev, ep_addr); +} + +/*! + \brief endpoint prepare to transmit data + \param[in] udev: pointer to USB core instance + \param[in] ep_addr: endpoint address + in this parameter: + bit0..bit6: endpoint number (0..7) + bit7: endpoint direction which can be IN(1) or OUT(0) + \param[in] pbuf: transmit buffer address pointer + \param[in] buf_len: buffer length + \param[out] none + \retval none +*/ +void usbd_ep_send (usb_dev *udev, uint8_t ep_addr, uint8_t *pbuf, uint16_t buf_len) +{ + uint8_t ep_num = EP_ID(ep_addr); + + usb_transc *transc = &udev->transc_in[ep_num]; + + uint16_t len = USB_MIN(buf_len, transc->max_len); + + /* configure the transaction level parameters */ + udev->drv_handler->ep_write(pbuf, ep_num, len); + + usb_transc_config(transc, pbuf + len, buf_len - len, len); +} diff --git a/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbd_library/device/Source/usbd_enum.c b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbd_library/device/Source/usbd_enum.c new file mode 100644 index 0000000000..1af602b314 --- /dev/null +++ b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbd_library/device/Source/usbd_enum.c @@ -0,0 +1,747 @@ +/*! + \file usbd_enum.c + \brief USB enumeration function + + \version 2020-07-17, V3.0.0, firmware for GD32F10x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "usbd_enum.h" +#include "usbd_transc.h" + +/* USB enumeration handle functions */ +static usb_reqsta _usb_std_getstatus (usb_dev *udev, usb_req *req); +static usb_reqsta _usb_std_clearfeature (usb_dev *udev, usb_req *req); +static usb_reqsta _usb_std_setfeature (usb_dev *udev, usb_req *req); +static usb_reqsta _usb_std_setaddress (usb_dev *udev, usb_req *req); +static usb_reqsta _usb_std_getdescriptor (usb_dev *udev, usb_req *req); +static usb_reqsta _usb_std_setdescriptor (usb_dev *udev, usb_req *req); +static usb_reqsta _usb_std_getconfiguration (usb_dev *udev, usb_req *req); +static usb_reqsta _usb_std_setconfiguration (usb_dev *udev, usb_req *req); +static usb_reqsta _usb_std_reserved (usb_dev *udev, usb_req *req); +static usb_reqsta _usb_std_getinterface (usb_dev *udev, usb_req *req); +static usb_reqsta _usb_std_setinterface (usb_dev *udev, usb_req *req); +static usb_reqsta _usb_std_synchframe (usb_dev *udev, usb_req *req); + +static uint8_t* _usb_dev_desc_get (usb_dev *udev, uint8_t index, uint16_t *len); +static uint8_t* _usb_config_desc_get (usb_dev *udev, uint8_t index, uint16_t *len); +static uint8_t* _usb_str_desc_get (usb_dev *udev, uint8_t index, uint16_t *len); +static uint8_t* _usb_bos_desc_get (usb_dev *udev, uint8_t index, uint16_t *len); + +static void int_to_unicode (uint32_t value, uint8_t *pbuf, uint8_t len); + +/* standard device request handler */ +static usb_reqsta (*_std_dev_req[]) (usb_dev *udev, usb_req *req) = { + [USB_GET_STATUS] = _usb_std_getstatus, + [USB_CLEAR_FEATURE] = _usb_std_clearfeature, + [USB_RESERVED2] = _usb_std_reserved, + [USB_SET_FEATURE] = _usb_std_setfeature, + [USB_RESERVED4] = _usb_std_reserved, + [USB_SET_ADDRESS] = _usb_std_setaddress, + [USB_GET_DESCRIPTOR] = _usb_std_getdescriptor, + [USB_SET_DESCRIPTOR] = _usb_std_setdescriptor, + [USB_GET_CONFIGURATION] = _usb_std_getconfiguration, + [USB_SET_CONFIGURATION] = _usb_std_setconfiguration, + [USB_GET_INTERFACE] = _usb_std_getinterface, + [USB_SET_INTERFACE] = _usb_std_setinterface, + [USB_SYNCH_FRAME] = _usb_std_synchframe, +}; + +/* get standard descriptor handler */ +static uint8_t* (*std_desc_get[])(usb_dev *udev, uint8_t index, uint16_t *len) = { + [USB_DESCTYPE_DEV - 1U] = _usb_dev_desc_get, + [USB_DESCTYPE_CONFIG - 1U] = _usb_config_desc_get, + [USB_DESCTYPE_STR - 1U] = _usb_str_desc_get +}; + +/*! + \brief handle USB standard device request + \param[in] udev: pointer to USB device instance + \param[in] req: pointer to USB device request + \param[out] none + \retval USB device operation cur_status +*/ +usb_reqsta usbd_standard_request (usb_dev *udev, usb_req *req) +{ + /* call device request handle function */ + return (*_std_dev_req[req->bRequest]) (udev, req); +} + +/*! + \brief handle USB device class request + \param[in] udev: pointer to USB device instance + \param[in] req: pointer to USB device class request + \param[out] none + \retval USB device request status +*/ +usb_reqsta usbd_class_request (usb_dev *udev, usb_req *req) +{ + if ((uint8_t)USBD_CONFIGURED == udev->cur_status) { + if (BYTE_LOW(req->wIndex) < USBD_ITF_MAX_NUM) { + /* call device class handle function */ + return (usb_reqsta)udev->class_core->req_process(udev, req); + } + } + + return REQ_NOTSUPP; +} + +/*! + \brief handle USB vendor request + \param[in] udev: pointer to USB device instance + \param[in] req: pointer to USB vendor request + \param[out] none + \retval USB device request status +*/ +usb_reqsta usbd_vendor_request (usb_dev *udev, usb_req *req) +{ + (void)udev; + (void)req; + + /* added by user */ + + return REQ_NOTSUPP; +} + +/*! + \brief no operation, just for reserved + \param[in] udev: pointer to USB device instance + \param[in] req: pointer to USB device request + \param[out] none + \retval USB device request status +*/ +static usb_reqsta _usb_std_reserved (usb_dev *udev, usb_req *req) +{ + (void)udev; + (void)req; + + /* no operation */ + return REQ_NOTSUPP; +} + +/*! + \brief get the device descriptor + \param[in] udev: pointer to USB device instance + \param[in] index: no use + \param[out] len: data length pointer + \retval descriptor buffer pointer +*/ +static uint8_t* _usb_dev_desc_get (usb_dev *udev, uint8_t index, uint16_t *len) +{ + (void)index; + + *len = udev->desc->dev_desc[0]; + + return udev->desc->dev_desc; +} + +/*! + \brief get the configuration descriptor + \brief[in] udev: pointer to USB device instance + \brief[in] index: no use + \param[out] len: data length pointer + \retval descriptor buffer pointer +*/ +static uint8_t* _usb_config_desc_get (usb_dev *udev, uint8_t index, uint16_t *len) +{ + (void)index; + + *len = udev->desc->config_desc[2]; + + return udev->desc->config_desc; +} + +/*! + \brief get the BOS descriptor + \brief[in] udev: pointer to USB device instance + \brief[in] index: no use + \param[out] len: data length pointer + \retval descriptor buffer pointer +*/ +static uint8_t* _usb_bos_desc_get (usb_dev *udev, uint8_t index, uint16_t *len) +{ + if (NULL != udev->desc->bos_desc) { + (void)index; + + *len = (uint16_t)udev->desc->bos_desc[2] | (uint16_t)((uint16_t)udev->desc->bos_desc[3] << 8); + + return udev->desc->bos_desc; + } else { + *len = 0U; + + return NULL; + } +} + +/*! + \brief get string descriptor + \param[in] udev: pointer to USB device instance + \param[in] index: string descriptor index + \param[out] len: pointer to string length + \retval string descriptor +*/ +static uint8_t* _usb_str_desc_get (usb_dev *udev, uint8_t index, uint16_t *len) +{ + uint8_t* desc = udev->desc->strings[index]; + + *len = desc[0]; + + return desc; +} + +/*! + \brief handle Get_Status request + \param[in] udev: pointer to USB device instance + \param[in] req: pointer to USB device request + \param[out] none + \retval USB device request status +*/ +static usb_reqsta _usb_std_getstatus (usb_dev *udev, usb_req *req) +{ + uint8_t recp = BYTE_LOW(req->wIndex); + + usb_reqsta req_status = REQ_NOTSUPP; + + static uint8_t status[2] = {0U}; + + switch(req->bmRequestType & USB_RECPTYPE_MASK) { + /* handle device get status request */ + case USB_RECPTYPE_DEV: + switch (udev->cur_status) { + case USBD_ADDRESSED: + case USBD_CONFIGURED: + if (udev->pm.power_mode) { + status[0] = USB_STATUS_SELF_POWERED; + } else { + status[0] = 0U; + } + + if (udev->pm.remote_wakeup) { + status[0] |= USB_STATUS_REMOTE_WAKEUP; + } else { + status[0] = 0U; + } + + req_status = REQ_SUPP; + break; + + default: + break; + } + break; + + /* handle interface get status request */ + case USB_RECPTYPE_ITF: + if (((uint8_t)USBD_CONFIGURED == udev->cur_status) && (recp < USBD_ITF_MAX_NUM)) { + req_status = REQ_SUPP; + } + break; + + /* handle endpoint get status request */ + case USB_RECPTYPE_EP: + if ((uint8_t)USBD_CONFIGURED == udev->cur_status) { + if (0x80U == (recp & 0x80U)) { + status[0] = udev->transc_in[EP_ID(recp)].ep_stall; + } else { + status[0] = udev->transc_out[recp].ep_stall; + } + req_status = REQ_SUPP; + } + break; + + default: + break; + } + + if (REQ_SUPP == req_status) { + usb_transc_config(&udev->transc_in[0], status, 2U, 2U); + } + + return req_status; +} + +/*! + \brief handle USB Clear_Feature request + \param[in] udev: pointer to USB device instance + \param[in] req: USB device request + \param[out] none + \retval USB device request status +*/ +static usb_reqsta _usb_std_clearfeature (usb_dev *udev, usb_req *req) +{ + uint8_t ep = 0U; + + switch (req->bmRequestType & (uint8_t)USB_RECPTYPE_MASK) { + case USB_RECPTYPE_DEV: + switch (udev->cur_status) { + case USBD_ADDRESSED: + case USBD_CONFIGURED: + /* clear device remote wakeup feature */ + if ((uint16_t)USB_FEATURE_REMOTE_WAKEUP == req->wValue) { + udev->pm.remote_wakeup = 0U; + + return REQ_SUPP; + } + break; + + default: + break; + } + break; + + case USB_RECPTYPE_EP: + /* get endpoint address */ + ep = BYTE_LOW(req->wIndex); + + if ((uint8_t)USBD_CONFIGURED == udev->cur_status) { + /* clear endpoint halt feature */ + if (((uint16_t)USB_FEATURE_EP_HALT == req->wValue) && (!CTL_EP(ep))) { + usbd_ep_clear_stall(udev, ep); + + udev->class_core->req_process(udev, req); + + return REQ_SUPP; + } + } + break; + + case USB_RECPTYPE_ITF: + break; + + default: + break; + } + + return REQ_NOTSUPP; +} + +/*! + \brief handle USB Set_Feature request + \param[in] udev: pointer to USB device instance + \param[in] req: pointer to USB device request + \param[out] none + \retval USB device request status +*/ +static usb_reqsta _usb_std_setfeature (usb_dev *udev, usb_req *req) +{ + uint8_t ep = 0U; + + switch (req->bmRequestType & (uint8_t)USB_RECPTYPE_MASK) { + case USB_RECPTYPE_DEV: + switch (udev->cur_status) { + case USBD_ADDRESSED: + case USBD_CONFIGURED: + /* set device remote wakeup feature */ + if ((uint16_t)USB_FEATURE_REMOTE_WAKEUP == req->wValue) { + udev->pm.remote_wakeup = 1U; + + return REQ_SUPP; + } + break; + + default: + break; + } + break; + + case USB_RECPTYPE_EP: + /* get endpoint address */ + ep = BYTE_LOW(req->wIndex); + + if ((uint8_t)USBD_CONFIGURED == udev->cur_status) { + /* set endpoint halt feature */ + if (((uint8_t)USB_FEATURE_EP_HALT == req->wValue) && (!CTL_EP(ep))) { + usbd_ep_stall(udev, ep); + + return REQ_SUPP; + } + } + break; + + case USB_RECPTYPE_ITF: + break; + + default: + break; + } + + return REQ_NOTSUPP; +} + +/*! + \brief handle USB Set_Address request + \param[in] udev: pointer to USB device instance + \param[in] req: pointer to USB device request + \param[out] none + \retval USB device request status +*/ +static usb_reqsta _usb_std_setaddress (usb_dev *udev, usb_req *req) +{ + if ((0U == req->wIndex) && (0U == req->wLength)) { + udev->dev_addr = (uint8_t)(req->wValue) & 0x7FU; + + if (udev->cur_status != (uint8_t)USBD_CONFIGURED) { + if (udev->dev_addr) { + udev->cur_status = (uint8_t)USBD_ADDRESSED; + } else { + udev->cur_status = (uint8_t)USBD_DEFAULT; + } + + return REQ_SUPP; + } + } + + return REQ_NOTSUPP; +} + +/*! + \brief handle USB Get_Descriptor request + \param[in] udev: pointer to USB device instance + \param[in] req: pointer to USB device request + \param[out] none + \retval USB device request status +*/ +static usb_reqsta _usb_std_getdescriptor (usb_dev *udev, usb_req *req) +{ + uint8_t desc_type = 0U; + uint8_t desc_index = 0U; + + usb_reqsta status = REQ_NOTSUPP; + + usb_transc *transc = &udev->transc_in[0]; + + switch (req->bmRequestType & USB_RECPTYPE_MASK) { + case USB_RECPTYPE_DEV: + desc_type = BYTE_HIGH(req->wValue); + desc_index = BYTE_LOW(req->wValue); + + switch (desc_type) { + case USB_DESCTYPE_DEV: + transc->xfer_buf = std_desc_get[desc_type - 1U](udev, desc_index, &transc->xfer_len); + if (64U == req->wLength) { + transc->xfer_len = 8U; + } + break; + + case USB_DESCTYPE_CONFIG: + transc->xfer_buf = std_desc_get[desc_type - 1U](udev, desc_index, &transc->xfer_len); + break; + + case USB_DESCTYPE_STR: + if (desc_index < STR_IDX_MAX) { + transc->xfer_buf = std_desc_get[desc_type - 1U](udev, desc_index, &transc->xfer_len); + } + break; + + case USB_DESCTYPE_ITF: + case USB_DESCTYPE_EP: + case USB_DESCTYPE_DEV_QUALIFIER: + case USB_DESCTYPE_OTHER_SPD_CONFIG: + case USB_DESCTYPE_ITF_POWER: + break; + + case USB_DESCTYPE_BOS: + transc->xfer_buf = _usb_bos_desc_get(udev, desc_index, &transc->xfer_len); + break; + + default: + break; + } + break; + + case USB_RECPTYPE_ITF: + /* get device class special descriptor */ + status = (usb_reqsta)(udev->class_core->req_process(udev, req)); + break; + + case USB_RECPTYPE_EP: + break; + + default: + break; + } + + if ((transc->xfer_len) && (req->wLength)) { + transc->xfer_len = USB_MIN(transc->xfer_len, req->wLength); + + if ((transc->xfer_len < udev->control.req.wLength) && + (0U == transc->xfer_len % transc->max_len)) { + udev->control.ctl_zlp = 1U; + } + + status = REQ_SUPP; + } + + return status; +} + +/*! + \brief handle USB Set_Descriptor request + \param[in] udev: pointer to USB device instance + \param[in] req: pointer to USB device request + \param[out] none + \retval USB device request status +*/ +static usb_reqsta _usb_std_setdescriptor (usb_dev *udev, usb_req *req) +{ + (void)udev; + (void)req; + + /* no handle */ + return REQ_SUPP; +} + +/*! + \brief handle USB Get_Configuration request + \param[in] udev: pointer to USB device instance + \param[in] req: pointer to USB device request + \param[out] none + \retval USB device request status +*/ +static usb_reqsta _usb_std_getconfiguration (usb_dev *udev, usb_req *req) +{ + (void)req; + + usb_reqsta req_status = REQ_NOTSUPP; + + switch (udev->cur_status) { + case USBD_ADDRESSED: + if (0U == udev->config) { + req_status = REQ_SUPP; + } + break; + + case USBD_CONFIGURED: + if (udev->config) { + req_status = REQ_SUPP; + } + break; + + default: + break; + } + + if (REQ_SUPP == req_status) { + usb_transc_config(&udev->transc_in[0], &(udev->config), 1U, 1U); + } + + return req_status; +} + +/*! + \brief handle USB Set_Configuration request + \param[in] udev: pointer to USB device instance + \param[in] req: pointer to USB device request + \param[out] none + \retval USB device operation cur_status +*/ +static usb_reqsta _usb_std_setconfiguration (usb_dev *udev, usb_req *req) +{ + static uint8_t config; + usb_reqsta status = REQ_NOTSUPP; + + config = (uint8_t)(req->wValue); + + if (config <= USBD_CFG_MAX_NUM) { + switch (udev->cur_status) { + case USBD_ADDRESSED: + if (config){ + (void)udev->class_core->init(udev, config); + + udev->config = config; + udev->cur_status = (uint8_t)USBD_CONFIGURED; + } + status = REQ_SUPP; + break; + + case USBD_CONFIGURED: + if (0U == config) { + (void)udev->class_core->deinit(udev, config); + + udev->config = config; + udev->cur_status = (uint8_t)USBD_ADDRESSED; + } else if (config != udev->config) { + /* clear old configuration */ + (void)udev->class_core->deinit(udev, udev->config); + + /* set new configuration */ + udev->config = config; + + (void)udev->class_core->init(udev, config); + } else { + /* no operation */ + } + status = REQ_SUPP; + break; + + case USBD_DEFAULT: + break; + + default: + break; + } + } + + return status; +} + +/*! + \brief handle USB Get_Interface request + \param[in] udev: pointer to USB device instance + \param[in] req: pointer to USB device request + \param[out] none + \retval USB device request status +*/ +static usb_reqsta _usb_std_getinterface (usb_dev *udev, usb_req *req) +{ + switch (udev->cur_status) { + case USBD_DEFAULT: + break; + + case USBD_ADDRESSED: + break; + + case USBD_CONFIGURED: + if (BYTE_LOW(req->wIndex) < USBD_ITF_MAX_NUM) { + usb_transc_config(&udev->transc_in[0], &(udev->class_core->req_altset), 1U, 1U); + + return REQ_SUPP; + } + break; + + default: + break; + } + + return REQ_NOTSUPP; +} + +/*! + \brief handle USB Set_Interface request + \param[in] udev: pointer to USB device instance + \param[in] req: pointer to USB device request + \param[out] none + \retval USB device request status +*/ +static usb_reqsta _usb_std_setinterface (usb_dev *udev, usb_req *req) +{ + switch (udev->cur_status) { + case USBD_DEFAULT: + break; + + case USBD_ADDRESSED: + break; + + case USBD_CONFIGURED: + if (BYTE_LOW(req->wIndex) < USBD_ITF_MAX_NUM) { + udev->class_core->req_altset = (uint8_t)req->wValue; + + return REQ_SUPP; + } + break; + + default: + break; + } + + return REQ_NOTSUPP; +} + +/*! + \brief handle USB SynchFrame request + \param[in] udev: pointer to USB device instance + \param[in] req: pointer to USB device request + \param[out] none + \retval USB device request status +*/ +static usb_reqsta _usb_std_synchframe (usb_dev *udev, usb_req *req) +{ + (void)udev; + (void)req; + + /* no handle */ + return REQ_SUPP; +} + +/*! + \brief convert hex 32bits value into unicode char + \param[in] value: Hex 32bits value + \param[in] pbuf: buffer pointer to store unicode char + \param[in] len: value length + \param[out] none + \retval none +*/ +static void int_to_unicode (uint32_t value, uint8_t *pbuf, uint8_t len) +{ + uint8_t index = 0U; + + for (index = 0U; index < len; index++) { + if ((value >> 28U) < 0x0AU) { + pbuf[2U * index] = (uint8_t)((value >> 28) + '0'); + } else { + pbuf[2U * index] = (uint8_t)((value >> 28) + 'A' - 10U); + } + + value = value << 4U; + + pbuf[2U * index + 1U] = 0U; + } +} + +/*! + \brief convert hex 32bits value into unicode char + \param[in] unicode_str: pointer to unicode string + \param[out] none + \retval none +*/ +void serial_string_get (uint16_t *unicode_str) +{ + if (6U != (unicode_str[0] & 0x00FFU)) { + uint32_t DeviceSerial0, DeviceSerial1, DeviceSerial2; + + DeviceSerial0 = *(uint32_t*)DEVICE_ID1; + DeviceSerial1 = *(uint32_t*)DEVICE_ID2; + DeviceSerial2 = *(uint32_t*)DEVICE_ID3; + + DeviceSerial0 += DeviceSerial2; + + if (0U != DeviceSerial0) { + int_to_unicode(DeviceSerial0, (uint8_t*)&(unicode_str[1]), 8U); + int_to_unicode(DeviceSerial1, (uint8_t*)&(unicode_str[9]), 4U); + } + } else { + uint32_t device_serial = *(uint32_t*)DEVICE_ID; + + if (0U != device_serial) { + unicode_str[1] = (uint16_t)(device_serial & 0x0000FFFFU); + unicode_str[2] = (uint16_t)((device_serial & 0xFFFF0000U) >> 16U); + + } + } +} diff --git a/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbd_library/device/Source/usbd_pwr.c b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbd_library/device/Source/usbd_pwr.c new file mode 100644 index 0000000000..1713118c36 --- /dev/null +++ b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbd_library/device/Source/usbd_pwr.c @@ -0,0 +1,60 @@ +/*! + \file usbd_pwr.c + \brief USB device power management driver + + \version 2020-07-17, V3.0.0, firmware for GD32F10x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "usbd_pwr.h" + +/*! + \brief start to remote wakeup + \param[in] udev: pointer to USB core instance + \param[out] none + \retval none +*/ +void usbd_remote_wakeup_active(usb_dev *udev) +{ + resume_mcu(udev); + +#ifdef LPM_ENABLED + if(1U == udev->lpm.L1_remote_wakeup){ + udev->drv_handler->resume(udev); + + udev->lpm.L1_resume = 1U; + } +#endif /* LPM_ENABLED */ + + if(1U == udev->pm.remote_wakeup){ + udev->pm.remote_wakeup_on = 1U; + udev->pm.esof_count = 15U; + udev->drv_handler->resume(udev); + } +} diff --git a/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbd_library/device/Source/usbd_transc.c b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbd_library/device/Source/usbd_transc.c new file mode 100644 index 0000000000..87563a5cb8 --- /dev/null +++ b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbd_library/device/Source/usbd_transc.c @@ -0,0 +1,208 @@ +/*! + \file usbd_transc.c + \brief USBD transaction function + + \version 2020-07-17, V3.0.0, firmware for GD32F10x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "usbd_enum.h" +#include "usbd_transc.h" + +/* local function prototypes ('static') */ +static inline void usb_stall_transc (usb_dev *udev); +static inline void usb_ctl_status_in (usb_dev *udev); +static inline void usb_ctl_data_in (usb_dev *udev); +static inline void usb_ctl_out (usb_dev *udev); +static inline void usb_0len_packet_send (usb_dev *udev); + +/*! + \brief USB setup stage processing + \param[in] udev: pointer to USB device instance + \param[in] ep_num: endpoint identifier(0..7) + \param[out] none + \retval none +*/ +void _usb_setup_transc (usb_dev *udev, uint8_t ep_num) +{ + (void)ep_num; + + usb_reqsta reqstat = REQ_NOTSUPP; + + uint16_t count = udev->drv_handler->ep_read((uint8_t *)(&udev->control.req), 0U, (uint8_t)EP_BUF_SNG); + + if (count != USB_SETUP_PACKET_LEN) { + usb_stall_transc(udev); + + return; + } + + switch (udev->control.req.bmRequestType & USB_REQTYPE_MASK) { + /* standard device request */ + case USB_REQTYPE_STRD: + reqstat = usbd_standard_request(udev, &udev->control.req); + break; + + /* device class request */ + case USB_REQTYPE_CLASS: + reqstat = usbd_class_request(udev, &udev->control.req); + break; + + /* vendor defined request */ + case USB_REQTYPE_VENDOR: + reqstat = usbd_vendor_request(udev, &udev->control.req); + break; + + default: + break; + } + + if (REQ_SUPP == reqstat) { + if (0U == udev->control.req.wLength) { + /* USB control transfer status in stage */ + usb_ctl_status_in(udev); + } else { + if (udev->control.req.bmRequestType & 0x80U) { + usb_ctl_data_in(udev); + } else { + /* USB control transfer data out stage */ + usb_ctl_out(udev); + } + } + } else { + usb_stall_transc(udev); + } +} + +/*! + \brief data out stage processing + \param[in] udev: pointer to USB device instance + \param[in] ep_num: endpoint identifier(0..7) + \param[out] none + \retval none +*/ +void _usb_out0_transc (usb_dev *udev, uint8_t ep_num) +{ + if (((uint8_t)USBD_CONFIGURED == udev->cur_status) && (udev->class_core->ctlx_out != NULL)) { + /* device class handle */ + (void)udev->class_core->ctlx_out(udev); + } + + usb_transc_config(&udev->transc_out[ep_num], NULL, 0U, 0U); + + /* enter the control transaction status in stage */ + usb_ctl_status_in(udev); +} + +/*! + \brief data in stage processing + \param[in] udev: pointer to USB device instance + \param[in] ep_num: endpoint identifier(0..7) + \param[out] none + \retval none +*/ +void _usb_in0_transc (usb_dev *udev, uint8_t ep_num) +{ + (void)ep_num; + + if (udev->control.ctl_zlp) { + /* send 0 length packet */ + usb_0len_packet_send(udev); + + udev->control.ctl_zlp = 0U; + } + + if (((uint8_t)USBD_CONFIGURED == udev->cur_status) && (udev->class_core->ctlx_in != NULL)) { + (void)udev->class_core->ctlx_in(udev); + } + + /* USB control transfer status out stage */ + usb_ctl_out(udev); + + if (0U != udev->dev_addr) { + udev->drv_handler->set_addr(udev); + + udev->dev_addr = 0U; + } +} + +/*! + \brief USB stalled transaction + \param[in] udev: pointer to USB device instance + \param[out] none + \retval none +*/ +static inline void usb_stall_transc (usb_dev *udev) +{ + usbd_ep_stall(udev, 0x0U); +} + +/*! + \brief USB control transaction status in stage + \param[in] udev: pointer to USB device instance + \param[out] none + \retval none +*/ +static inline void usb_ctl_status_in (usb_dev *udev) +{ + udev->drv_handler->ep_write(udev->transc_in[0].xfer_buf, 0U, 0U); +} + +/*! + \brief USB control transaction data in stage + \param[in] udev: pointer to USB device instance + \param[out] none + \retval none +*/ +static inline void usb_ctl_data_in (usb_dev *udev) +{ + usbd_ep_send(udev, 0U, udev->transc_in[0].xfer_buf, udev->transc_in[0].xfer_len); +} + +/*! + \brief USB control transaction data out & status out stage + \param[in] udev: pointer to USB device instance + \param[out] none + \retval none +*/ +static inline void usb_ctl_out (usb_dev *udev) +{ + udev->drv_handler->ep_rx_enable(udev, 0U); +} + +/*! + \brief USB send 0 length data packet + \param[in] udev: pointer to USB device instance + \param[out] none + \retval none +*/ +static inline void usb_0len_packet_send (usb_dev *udev) +{ + udev->drv_handler->ep_write(udev->transc_in[0].xfer_buf, 0U, 0U); +} diff --git a/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbd_library/usbd/Include/usbd_lld_core.h b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbd_library/usbd/Include/usbd_lld_core.h new file mode 100644 index 0000000000..5963a97a03 --- /dev/null +++ b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbd_library/usbd/Include/usbd_lld_core.h @@ -0,0 +1,73 @@ +/*! + \file usbd_lld_core.h + \brief USB device low level driver core + + \version 2020-07-17, V3.0.0, firmware for GD32F10x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef __USBD_LLD_CORE_H +#define __USBD_LLD_CORE_H + +#include "usbd_lld_regs.h" +#include "usbd_core.h" + +/* double buffer endpoint direction enumeration */ +enum dbuf_ep_dir +{ + DBUF_EP_IN, /*!< double buffer in direction */ + DBUF_EP_OUT, /*!< double buffer out direction */ + DBUF_EP_ERR, /*!< double buffer error direction */ +}; + +/* USBD endpoint ram structure */ +typedef struct +{ + __IO uint32_t tx_addr; /*!< transmission address */ + __IO uint32_t tx_count; /*!< transmission count */ + __IO uint32_t rx_addr; /*!< reception address */ + __IO uint32_t rx_count; /*!< reception count */ +} usbd_ep_ram; + +extern struct _usb_handler usbd_drv_handler; + +/* USB core driver structure */ +typedef struct +{ + usb_basic basic; + usb_dev *dev; +} usb_core_drv; + +extern usb_core_drv usbd_core; + +/* function declarations */ +/* free buffer used from application by toggling the SW_BUF byte */ +void user_buffer_free (uint8_t ep_num, uint8_t dir); + +#endif /* __USBD_LLD_CORE_H */ diff --git a/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbd_library/usbd/Include/usbd_lld_int.h b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbd_library/usbd/Include/usbd_lld_int.h new file mode 100644 index 0000000000..85dbfc3ddd --- /dev/null +++ b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbd_library/usbd/Include/usbd_lld_int.h @@ -0,0 +1,48 @@ +/*! + \file usbd_lld_int.h + \brief USB device low level interrupt handler + + \version 2020-07-17, V3.0.0, firmware for GD32F10x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef __USBD_LLD_INT_H +#define __USBD_LLD_INT_H + +#include "usbd_core.h" +#include "usbd_enum.h" +#include "usbd_pwr.h" + +/* function declarations */ +/* USB device interrupt service routine */ +void usbd_isr (void); +/* handle USB high priority successful transfer event */ +void usbd_int_hpst (usb_dev *udev); + +#endif /* __USBD_LLD_INT_H */ diff --git a/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbd_library/usbd/Include/usbd_lld_regs.h b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbd_library/usbd/Include/usbd_lld_regs.h new file mode 100644 index 0000000000..8773c6a744 --- /dev/null +++ b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbd_library/usbd/Include/usbd_lld_regs.h @@ -0,0 +1,227 @@ +/*! + \file usbd_lld_regs.h + \brief USB device low level registers + + \version 2020-07-17, V3.0.0, firmware for GD32F10x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef __USBD_LLD_REGS_H +#define __USBD_LLD_REGS_H + +#include "usbd_conf.h" + +/* USB device registers base address */ +#define USBD USBD_BASE +#define USBD_RAM USBD_RAM_BASE + +/* registers definitions */ +/* common registers */ +#define USBD_CTL (REG32(USBD + 0x40U)) /*!< control register */ +#define USBD_INTF (REG32(USBD + 0x44U)) /*!< interrupt flag register */ +#define USBD_STAT (REG32(USBD + 0x48U)) /*!< status register */ +#define USBD_DADDR (REG32(USBD + 0x4CU)) /*!< device address register */ +#define USBD_BADDR (REG32(USBD + 0x50U)) /*!< buffer address register */ +#define USBD_LPMCS (REG32(USBD + 0x54U)) /*!< USBD LPM control and status register */ + +/* endpoint control and status register */ +#define USBD_EPxCS(ep_num) (REG32(USBD + (ep_num) * 4U)) /*!< endpoint x control and status register address */ + +/* bits definitions */ +/* USBD_CTL */ +#define CTL_STIE BIT(15) /*!< successful transfer interrupt enable mask */ +#define CTL_PMOUIE BIT(14) /*!< packet memory overrun/underrun interrupt enable mask */ +#define CTL_ERRIE BIT(13) /*!< error interrupt enable mask */ +#define CTL_WKUPIE BIT(12) /*!< wakeup interrupt enable mask */ +#define CTL_SPSIE BIT(11) /*!< suspend state interrupt enable mask */ +#define CTL_RSTIE BIT(10) /*!< reset interrupt enable mask */ +#define CTL_SOFIE BIT(9) /*!< start of frame interrupt enable mask */ +#define CTL_ESOFIE BIT(8) /*!< expected start of frame interrupt enable mask */ +#define CTL_L1REQIE BIT(7) /*!< LPM L1 state request interrupt enable */ +#define CTL_L1RSREQ BIT(5) /*!< LPM L1 resume request */ +#define CTL_RSREQ BIT(4) /*!< resume request */ +#define CTL_SETSPS BIT(3) /*!< set suspend state */ +#define CTL_LOWM BIT(2) /*!< low-power mode at suspend state */ +#define CTL_CLOSE BIT(1) /*!< goes to close state */ +#define CTL_SETRST BIT(0) /*!< set USB reset */ + +#ifdef LPM_ENABLED +#define USBD_INTEN BITS(7, 15) /*!< USBD interrupt enable bits */ +#else +#define USBD_INTEN BITS(8, 15) /*!< USBD interrupt enable bits */ +#endif +/* USBD_INTF */ +#define INTF_STIF BIT(15) /*!< successful transfer interrupt flag (read only bit) */ +#define INTF_PMOUIF BIT(14) /*!< packet memory overrun/underrun interrupt flag (clear-only bit) */ +#define INTF_ERRIF BIT(13) /*!< error interrupt flag (clear-only bit) */ +#define INTF_WKUPIF BIT(12) /*!< wakeup interrupt flag (clear-only bit) */ +#define INTF_SPSIF BIT(11) /*!< suspend state interrupt flag (clear-only bit) */ +#define INTF_RSTIF BIT(10) /*!< reset interrupt flag (clear-only bit) */ +#define INTF_SOFIF BIT(9) /*!< start of frame interrupt flag (clear-only bit) */ +#define INTF_ESOFIF BIT(8) /*!< expected start of frame interrupt flag(clear-only bit) */ +#define INTF_L1REQ BIT(7) /*!< LPM L1 transaction is successfully received and acknowledged */ +#define INTF_DIR BIT(4) /*!< direction of transaction (read-only bit) */ +#define INTF_EPNUM BITS(0, 3) /*!< endpoint number (read-only bit) */ + +/* USBD_STAT */ +#define STAT_RXDP BIT(15) /*!< data plus line status */ +#define STAT_RXDM BIT(14) /*!< data minus line status */ +#define STAT_LOCK BIT(13) /*!< locked the USB */ +#define STAT_SOFLN BITS(11, 12) /*!< SOF lost number */ +#define STAT_FCNT BITS(0, 10) /*!< frame number count */ + +/* USBD_DADDR */ +#define DADDR_USBEN BIT(7) /*!< USB module enable */ +#define DADDR_USBADDR BITS(0, 6) /*!< USB device address */ + +/* USBD_EPxCS */ +#define EPxCS_RX_ST BIT(15) /*!< endpoint reception successful transferred */ +#define EPxCS_RX_DTG BIT(14) /*!< endpoint reception data PID toggle */ +#define EPxCS_RX_STA BITS(12, 13) /*!< endpoint reception status bits */ +#define EPxCS_SETUP BIT(11) /*!< endpoint setup transaction completed */ +#define EPxCS_CTL BITS(9, 10) /*!< endpoint type control */ +#define EPxCS_KCTL BIT(8) /*!< endpoint kind control */ +#define EPxCS_TX_ST BIT(7) /*!< endpoint transmission successful transfer */ +#define EPxCS_TX_DTG BIT(6) /*!< endpoint transmission data toggle */ +#define EPxCS_TX_STA BITS(4, 5) /*!< endpoint transmission transfers status bits */ +#define EPxCS_AR BITS(0, 3) /*!< endpoint address */ + +/* USBD_LPMCS */ +#define LPMCS_BLSTAT BITS(4, 7) /*!< bLinkState value */ +#define LPMCS_REMWK BIT(3) /*!< bRemoteWake value */ +#define LPMCS_LPMACK BIT(1) /*!< LPM token acknowledge enable */ +#define LPMCS_LPMEN BIT(0) /*!< LPM support enable */ + +/* constants definitions */ +/* endpoint control and status register mask (no toggle fields) */ +#define EPCS_MASK (EPxCS_RX_ST | EPxCS_SETUP | \ + EPxCS_CTL | EPxCS_KCTL | EPxCS_TX_ST | EPxCS_AR) + +/* EPxCS_CTL[1:0] endpoint type control */ +#define ENDP_TYPE(regval) (EPxCS_CTL & ((regval) << 9U)) + +#define EP_BULK ENDP_TYPE(0U) /* bulk transfers */ +#define EP_CONTROL ENDP_TYPE(1U) /* control transfers */ +#define EP_ISO ENDP_TYPE(2U) /* isochronous transfers */ +#define EP_INTERRUPT ENDP_TYPE(3U) /* interrupt transfers */ +#define EP_CTL_MASK (~EPxCS_CTL & EPCS_MASK) + +/* endpoint kind control mask */ +#define EPKCTL_MASK (~EPxCS_KCTL & EPCS_MASK) + +/* EPxCS_TX_STA[1:0] status for TX transfer */ +#define ENDP_TXSTAT(regval) (EPxCS_TX_STA & ((regval) << 4U)) + +#define EPTX_DISABLED ENDP_TXSTAT(0U) /* transmission state is disabled */ +#define EPTX_STALL ENDP_TXSTAT(1U) /* transmission state is STALL */ +#define EPTX_NAK ENDP_TXSTAT(2U) /* transmission state is NAK */ +#define EPTX_VALID ENDP_TXSTAT(3U) /* transmission state is enabled */ +#define EPTX_DTGMASK (EPxCS_TX_STA | EPCS_MASK) + +/* EPxCS_RX_STA[1:0] status for RX transfer */ +#define ENDP_RXSTAT(regval) (EPxCS_RX_STA & ((regval) << 12U)) + +#define EPRX_DISABLED ENDP_RXSTAT(0U) /* reception state is disabled */ +#define EPRX_STALL ENDP_RXSTAT(1U) /* reception state is STALL */ +#define EPRX_NAK ENDP_RXSTAT(2U) /* reception state is NAK */ +#define EPRX_VALID ENDP_RXSTAT(3U) /* reception state is enabled */ +#define EPRX_DTGMASK (EPxCS_RX_STA | EPCS_MASK) + +/* endpoint receive/transmission counter register bit definitions */ +#define EPRCNT_BLKSIZ BIT(15) /* reception data block size */ +#define EPRCNT_BLKNUM BITS(10, 14) /* reception data block number */ +#define EPRCNT_CNT BITS(0, 9) /* reception data count */ + +#define EPTCNT_CNT BITS(0, 9) /* transmisson data count */ + +/* interrupt flag clear bits */ +#define CLR(x) (USBD_INTF = ~INTF_##x) + +/* endpoint receive/transmission counter register bit offset */ +#define BLKSIZE_OFFSET (0x01U) +#define BLKNUM_OFFSET (0x05U) +#define RXCNT_OFFSET (0x0AU) + +#define TXCNT_OFFSET (0x0AU) + +#define BLKSIZE32_MASK (0x1fU) +#define BLKSIZE2_MASK (0x01U) + +#define BLKSIZE32_OFFSETMASK (0x05U) +#define BLKSIZE2_OFFSETMASK (0x01U) + +/* USBD operation macros */ + +/* TX or RX transfer status setting (bits EPTX_STA[1:0]) */ + +#define USBD_EP_TX_STAT_SET(ep, stat) do {\ + USBD_EPxCS(ep) = (USBD_EPxCS(ep) & (uint16_t)EPTX_DTGMASK) ^ (stat); \ +} while(0) + +#define USBD_EP_RX_STAT_SET(ep, stat) do {\ + USBD_EPxCS(ep) = (USBD_EPxCS(ep) & (uint16_t)EPRX_DTGMASK) ^ (stat); \ +} while(0) + +/* clear bit EPxCS_RX_ST/EPxCS_TX_ST in the endpoint control and status register */ + +#define USBD_EP_TX_ST_CLEAR(ep) do {\ + USBD_EPxCS(ep) &= ~EPxCS_TX_ST & (uint16_t)EPCS_MASK; \ +} while(0) + +#define USBD_EP_RX_ST_CLEAR(ep) do {\ + USBD_EPxCS(ep) &= ~EPxCS_RX_ST & (uint16_t)EPCS_MASK; \ +} while(0) + +/* toggle EPxCS_RX_DTG or EPxCS_TX_DTG bit in the endpoint control and status register */ + +#define USBD_TX_DTG_TOGGLE(ep) do {\ + USBD_EPxCS(ep) = EPxCS_TX_DTG | (USBD_EPxCS(ep) & EPCS_MASK); \ +} while(0) + +#define USBD_RX_DTG_TOGGLE(ep) do {\ + USBD_EPxCS(ep) = EPxCS_RX_DTG | (USBD_EPxCS(ep) & EPCS_MASK); \ +} while(0) + +/* clear EPxCS_RX_DTG or EPxCS_TX_DTG bit in the endpoint control and status register */ + +#define USBD_TX_DTG_CLEAR(ep) do {\ + if ((USBD_EPxCS(ep_num) & EPxCS_TX_DTG) != 0U) {\ + USBD_TX_DTG_TOGGLE(ep);\ + } \ +} while(0) + +#define USBD_RX_DTG_CLEAR(ep) do {\ + if ((USBD_EPxCS(ep_num) & EPxCS_RX_DTG) != 0U) {\ + USBD_RX_DTG_TOGGLE(ep);\ + } \ +} while(0) + +#define USBD_EP_DBL_BUF_SET(ep) (USBD_EPxCS(ep) = (USBD_EPxCS(ep) | EPxCS_KCTL) & EPCS_MASK) + +#endif /* __USBD_LLD_REGS_H */ diff --git a/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbd_library/usbd/Source/usbd_lld_core.c b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbd_library/usbd/Source/usbd_lld_core.c new file mode 100644 index 0000000000..0eafa0f641 --- /dev/null +++ b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbd_library/usbd/Source/usbd_lld_core.c @@ -0,0 +1,630 @@ +/*! + \file usbd_lld_core.c + \brief USB device low level driver core + + \version 2020-07-17, V3.0.0, firmware for GD32F10x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "usbd_lld_core.h" +#include "usbd_enum.h" + +#define USB_EPTYPE_MASK 0x03U + +#if defined (__CC_ARM) /* ARM Compiler */ +static usbd_ep_ram btable_ep[EP_COUNT]__attribute__((at(USBD_RAM + 2 * (BTABLE_OFFSET & 0xFFF8)))); +#elif defined (__ICCARM__) /* IAR Compiler */ + __no_init usbd_ep_ram btable_ep[EP_COUNT] @(USBD_RAM + 2 * (BTABLE_OFFSET & 0xFFF8)); +#elif defined (__GNUC__) /* GNU GCC Compiler */ + usbd_ep_ram *btable_ep = (usbd_ep_ram *)(USBD_RAM + 2 * (BTABLE_OFFSET & 0xFFF8)); +#endif + +usb_core_drv usbd_core; + +static const uint32_t ep_type[] = { + [USB_EP_ATTR_CTL] = EP_CONTROL, + [USB_EP_ATTR_BULK] = EP_BULK, + [USB_EP_ATTR_INT] = EP_INTERRUPT, + [USB_EP_ATTR_ISO] = EP_ISO +}; + +/* local function prototypes ('static') */ +static void usbd_dp_pullup (FlagStatus status); +static void usbd_core_reset (void); +static void usbd_core_stop (void); +static void usbd_address_set (usb_dev *udev); +static void usbd_ep_reset (usb_dev *udev); +static void usbd_ep_setup (usb_dev *udev, uint8_t buf_kind, uint32_t buf_addr, const usb_desc_ep *ep_desc); +static void usbd_ep_rx_enable (usb_dev *udev, uint8_t ep_addr); +static void usbd_ep_disable (usb_dev *udev, uint8_t ep_addr); +static void usbd_ep_stall_set (usb_dev *udev, uint8_t ep_addr); +static void usbd_ep_stall_clear (usb_dev *udev, uint8_t ep_addr); +static void usbd_ep_data_write (uint8_t *user_fifo, uint8_t ep_num, uint16_t bytes); +static uint16_t usbd_ep_data_read (uint8_t *user_fifo, uint8_t ep_num, uint8_t buf_kind); +static void usbd_resume (usb_dev *udev); +static void usbd_suspend (void); +static void usbd_leave_suspend (void); +static uint8_t usbd_ep_status (usb_dev *udev, uint8_t ep_addr); + +struct _usb_handler usbd_drv_handler = { + .dp_pullup = usbd_dp_pullup, + .init = usbd_core_reset, + .deinit = usbd_core_stop, + .suspend = usbd_suspend, + .suspend_leave = usbd_leave_suspend, + .resume = usbd_resume, + .set_addr = usbd_address_set, + .ep_reset = usbd_ep_reset, + .ep_disable = usbd_ep_disable, + .ep_setup = usbd_ep_setup, + .ep_rx_enable = usbd_ep_rx_enable, + .ep_write = usbd_ep_data_write, + .ep_read = usbd_ep_data_read, + .ep_stall_set = usbd_ep_stall_set, + .ep_stall_clear = usbd_ep_stall_clear, + .ep_status_get = usbd_ep_status +}; + +/*! + \brief free buffer used from application by toggling the SW_BUF byte + \param[in] ep_num: endpoint identifier (0..7) + \param[in] dir: endpoint direction which can be OUT(0) or IN(1) + \param[out] none + \retval None +*/ +void user_buffer_free (uint8_t ep_num, uint8_t dir) +{ + if ((uint8_t)DBUF_EP_OUT == dir) { + USBD_TX_DTG_TOGGLE(ep_num); + } else if ((uint8_t)DBUF_EP_IN == dir) { + USBD_RX_DTG_TOGGLE(ep_num); + } else { + /* no operation */ + } +} + +/*! + \brief set the status of pull-up pin + \param[in] status: SET or RESET + \param[out] none + \retval none +*/ +static void usbd_dp_pullup (FlagStatus status) +{ + if (SET == status) { + gpio_bit_set(USB_PULLUP, USB_PULLUP_PIN); + } else { + gpio_bit_reset(USB_PULLUP, USB_PULLUP_PIN); + } +} + +/*! + \brief device core register initialization + \param[in] none + \param[out] none + \retval none +*/ +static void usbd_core_reset (void) +{ + /* reset the CLOSE bit */ + USBD_CTL = CTL_SETRST; + + /* may be need wait some time(tSTARTUP) ... */ + + /* clear SETRST bit in USBD_CTL register */ + USBD_CTL = 0U; + + /* clear all pending interrupts */ + USBD_INTF = 0U; + + /* set descriptors table offset in USB dedicated SRAM */ + USBD_BADDR = BTABLE_OFFSET & 0xFFF8U; + +#ifdef LPM_ENABLED + /* enable L1REQ interrupt */ + USBD_CTL = CTL_L1REQIE; + + USBD_LPMCS = LPMCS_LPMACK | LPMCS_LPMEN; +#endif /* LPM_ENABLED */ + + /* enable all interrupts mask bits */ + USBD_CTL |= CTL_STIE | CTL_WKUPIE | CTL_SPSIE | CTL_SOFIE | CTL_ESOFIE | CTL_RSTIE; +} + +/*! + \brief device core register configure when stop device + \param[in] none + \param[out] none + \retval none +*/ +static void usbd_core_stop (void) +{ + /* disable all interrupts and set USB reset */ + USBD_CTL = CTL_SETRST; + + /* clear all interrupt flags */ + USBD_INTF = 0U; + + /* close device */ + USBD_CTL = CTL_SETRST | CTL_CLOSE; +} + +/*! + \brief set device address + \param[in] udev: pointer to USB device instance + \param[out] none + \retval none +*/ +static void usbd_address_set (usb_dev *udev) +{ + USBD_DADDR = DADDR_USBEN | udev->dev_addr; +} + +/*! + \brief handle USB reset event + \param[in] udev: pointer to USB device instance + \param[out] none + \retval none +*/ +static void usbd_ep_reset (usb_dev *udev) +{ + uint8_t i = 0U; + + usb_transc *transc = &udev->transc_in[0]; + + btable_ep[0].tx_addr = EP0_TX_ADDR; + btable_ep[0].tx_count = 0U; + + transc->max_len = USBD_EP0_MAX_SIZE; + + transc = &udev->transc_out[0]; + + btable_ep[0].rx_addr = EP0_RX_ADDR; + + transc->max_len = USBD_EP0_MAX_SIZE; + + if (transc->max_len > 62U) { + btable_ep[0].rx_count = ((uint16_t)((uint16_t)transc->max_len << 5) - 1U) | 0x8000U; + } else { + btable_ep[0].rx_count = ((transc->max_len + 1U) & ~1U) << 9U; + } + + /* reset non-control endpoints */ + for (i = 1U; i < EP_COUNT; i++) { + USBD_EPxCS(i) = (USBD_EPxCS(i) & EPCS_MASK) | i; + } + + /* clear endpoint 0 register */ + USBD_EPxCS(0U)= (uint16_t)(USBD_EPxCS(0U)); + + USBD_EPxCS(0U) = EP_CONTROL | EPRX_VALID | EPTX_NAK; + + /* set device address as default address 0 */ + USBD_DADDR = DADDR_USBEN; + + udev->cur_status = (uint8_t)USBD_DEFAULT; +} + +/*! + \brief endpoint initialization + \param[in] udev: pointer to USB core instance + \param[in] buf_kind: endpoint buffer kind + \param[in] buf_addr: endpoint buffer address + \param[in] ep_desc: pointer to endpoint descriptor + \param[out] none + \retval none +*/ +static void usbd_ep_setup (usb_dev *udev, uint8_t buf_kind, uint32_t buf_addr, const usb_desc_ep *ep_desc) +{ + uint8_t ep_addr = ep_desc->bEndpointAddress; + uint8_t ep_num = EP_ID(ep_addr); + uint16_t max_len = ep_desc->wMaxPacketSize; + + usb_transc *transc = NULL; + + /* set the endpoint type */ + USBD_EPxCS(ep_num) = ep_type[ep_desc->bmAttributes & USB_EPTYPE_MASK] | ep_num; + + if (EP_DIR(ep_addr)) { + transc = &udev->transc_in[ep_num]; + + transc->max_len = (uint8_t)max_len; + + if ((uint8_t)EP_BUF_SNG == buf_kind) { + btable_ep[ep_num].tx_addr = buf_addr; + + /* configure the endpoint status as NAK status */ + USBD_EP_TX_STAT_SET(ep_num, EPTX_NAK); + } else if ((uint8_t)EP_BUF_DBL == buf_kind) { + USBD_EP_DBL_BUF_SET(ep_num); + + btable_ep[ep_num].tx_addr = buf_addr & 0xFFFFU; + btable_ep[ep_num].rx_addr = (buf_addr & 0xFFFF0000U) >> 16U; + + USBD_EP_TX_STAT_SET(ep_num, EPTX_VALID); + USBD_EP_RX_STAT_SET(ep_num, EPRX_DISABLED); + } else { + /* error operation */ + } + } else { + transc = &udev->transc_out[ep_num]; + + transc->max_len = (uint8_t)max_len; + + if ((uint8_t)EP_BUF_SNG == buf_kind) { + btable_ep[ep_num].rx_addr = buf_addr; + } else if ((uint8_t)EP_BUF_DBL == buf_kind) { + USBD_EP_DBL_BUF_SET(ep_num); + + USBD_TX_DTG_TOGGLE(ep_num); + + btable_ep[ep_num].tx_addr = buf_addr & 0xFFFFU; + btable_ep[ep_num].rx_addr = (buf_addr & 0xFFFF0000U) >> 16U; + + if (max_len > 62U) { + btable_ep[ep_num].tx_count = (((uint32_t)max_len << 5) - 1U) | 0x8000U; + } else { + btable_ep[ep_num].tx_count = ((max_len + 1U) & ~1U) << 9U; + } + } else { + /* error operation */ + } + + if (max_len > 62U) { + btable_ep[ep_num].rx_count = (((uint32_t)max_len << 5U) - 1U) | 0x8000U; + } else { + btable_ep[ep_num].rx_count = ((max_len + 1U) & ~1U) << 9U; + } + + if ((uint8_t)EP_BUF_SNG == buf_kind) { + /* configure the endpoint status as NAK status */ + USBD_EP_RX_STAT_SET(ep_num, EPRX_NAK); + } else if ((uint8_t)EP_BUF_DBL == buf_kind) { + USBD_EP_RX_STAT_SET(ep_num, EPRX_DISABLED); + USBD_EP_TX_STAT_SET(ep_num, EPTX_NAK); + } else { + /* error operation */ + } + } +} + +/*! + \brief configure the endpoint when it is disabled + \param[in] udev: pointer to USB core instance + \param[in] ep_addr: endpoint address + in this parameter: + bit0..bit6: endpoint number (0..7) + bit7: endpoint direction which can be IN(1) or OUT(0) + \param[out] none + \retval none +*/ +static void usbd_ep_disable (usb_dev *udev, uint8_t ep_addr) +{ + (void)udev; + + uint8_t ep_num = EP_ID(ep_addr); + + if (EP_DIR(ep_addr)) { + USBD_TX_DTG_CLEAR(ep_num); + + /* configure the endpoint status as DISABLED */ + USBD_EP_TX_STAT_SET(ep_num, EPTX_DISABLED); + } else { + USBD_RX_DTG_CLEAR(ep_num); + + /* configure the endpoint status as DISABLED */ + USBD_EP_RX_STAT_SET(ep_num, EPRX_DISABLED); + } +} + +/*! + \brief enable endpoint to receive + \param[in] udev: pointer to USB core instance + \param[in] ep_addr: endpoint address + in this parameter: + bit0..bit6: endpoint number (0..7) + bit7: endpoint direction which can be IN(1) or OUT(0) + \param[out] none + \retval none +*/ +static void usbd_ep_rx_enable (usb_dev *udev, uint8_t ep_addr) +{ + (void)udev; + + /* enable endpoint to receive */ + USBD_EP_RX_STAT_SET(EP_ID(ep_addr), EPRX_VALID); +} + +/*! + \brief set an endpoint to STALL status + \param[in] udev: pointer to USB core instance + \param[in] ep_addr: endpoint address + in this parameter: + bit0..bit6: endpoint number (0..7) + bit7: endpoint direction which can be IN(1) or OUT(0) + \param[out] none + \retval none +*/ +static void usbd_ep_stall_set (usb_dev *udev, uint8_t ep_addr) +{ + uint8_t ep_num = EP_ID(ep_addr); + + if (0U == ep_num) { + USBD_EP_TX_STAT_SET(0U, EPTX_STALL); + USBD_EP_RX_STAT_SET(0U, EPRX_STALL); + } else { + if (EP_DIR(ep_addr)) { + udev->transc_in[ep_num].ep_stall = 1U; + + USBD_EP_TX_STAT_SET(ep_num, EPTX_STALL); + } else { + udev->transc_out[ep_num].ep_stall = 1U; + + USBD_EP_RX_STAT_SET(ep_num, EPRX_STALL); + } + } +} + +/*! + \brief clear endpoint stalled status + \param[in] udev: pointer to USB core instance + \param[in] ep_addr: endpoint address + in this parameter: + bit0..bit6: endpoint number (0..7) + bit7: endpoint direction which can be IN(1) or OUT(0) + \param[out] none + \retval none +*/ +static void usbd_ep_stall_clear (usb_dev *udev, uint8_t ep_addr) +{ + uint8_t ep_num = EP_ID(ep_addr); + + if (EP_DIR(ep_addr)) { + /* clear endpoint data toggle bit */ + USBD_TX_DTG_CLEAR(ep_num); + + udev->transc_in[ep_num].ep_stall = 0U; + + /* clear endpoint stall status */ + USBD_EP_TX_STAT_SET(ep_num, EPTX_VALID); + } else { + /* clear endpoint data toggle bit */ + USBD_RX_DTG_CLEAR(ep_num); + + udev->transc_out[ep_num].ep_stall = 0U; + + /* clear endpoint stall status */ + USBD_EP_RX_STAT_SET(ep_num, EPRX_VALID); + } +} + +/*! + \brief get the endpoint status + \param[in] udev: pointer to USB core instance + \param[in] ep_addr: endpoint address + in this parameter: + bit0..bit6: endpoint number (0..7) + bit7: endpoint direction which can be IN(1) or OUT(0) + \param[out] none + \retval endpoint status +*/ +static uint8_t usbd_ep_status (usb_dev *udev, uint8_t ep_addr) +{ + (void)udev; + + uint32_t epcs = USBD_EPxCS(EP_ID(ep_addr)); + + if (EP_DIR(ep_addr)) { + return (uint8_t)(epcs & EPxCS_TX_STA); + } else { + return (uint8_t)(epcs & EPxCS_RX_STA); + } +} + +/*! + \brief write data from user FIFO to USB RAM + \param[in] user_fifo: pointer to user FIFO + \param[in] ep_num: endpoint number + \param[in] bytes: the bytes count of the write data + \param[out] none + \retval none +*/ +static void usbd_ep_data_write (uint8_t *user_fifo, uint8_t ep_num, uint16_t bytes) +{ + if (0U != bytes) { + uint32_t n; + uint32_t *write_addr = (uint32_t *)(btable_ep[ep_num].tx_addr * 2U + USBD_RAM); + + for (n = 0U; n < (bytes + 1U) / 2U; n++) { + *write_addr++ = *((uint16_t*)user_fifo); + user_fifo += 2U; + } + } + + btable_ep[ep_num].tx_count = bytes; + + USBD_EP_TX_STAT_SET(ep_num, EPTX_VALID); +} + +/*! + \brief read data from USBRAM to user FIFO + \param[in] user_fifo: pointer to user FIFO + \param[in] ep_num: endpoint number + \param[in] buf_kind: endpoint buffer kind + \param[out] none + \retval none +*/ +static uint16_t usbd_ep_data_read (uint8_t *user_fifo, uint8_t ep_num, uint8_t buf_kind) +{ + uint16_t n = 0U, bytes = 0U; + uint32_t *read_addr = NULL; + + if ((uint8_t)EP_BUF_SNG == buf_kind) { + bytes = (uint16_t)(btable_ep[ep_num].rx_count & EPRCNT_CNT); + + read_addr = (uint32_t *)(btable_ep[ep_num].rx_addr * 2U + USBD_RAM); + } else if ((uint8_t)EP_BUF_DBL == buf_kind) { + if (USBD_EPxCS(ep_num) & EPxCS_TX_DTG) { + bytes = (uint16_t)(btable_ep[ep_num].tx_count & EPRCNT_CNT); + + read_addr = (uint32_t *)(btable_ep[ep_num].tx_addr * 2U + USBD_RAM); + } else { + bytes = (uint16_t)(btable_ep[ep_num].rx_count & EPRCNT_CNT); + + read_addr = (uint32_t *)(btable_ep[ep_num].rx_addr * 2U + USBD_RAM); + } + } else { + return 0U; + } + + for (n = 0U; n < (bytes + 1U) / 2U; n++) { + *((uint16_t*)user_fifo) = (uint16_t)*read_addr++; + user_fifo += 2U; + } + + return bytes; +} + +#ifdef USBD_LOWPWR_MODE_ENABLE + +/*! + \brief restore system clocks and power while exiting from suspend mode + \param[in] none + \param[out] none + \retval none +*/ +static void lowpower_mode_exit (void) +{ + /* restore system clock */ + +#ifdef LPM_ENABLED + /* enable IRC8M */ + rcu_osci_on(RCU_IRC8M); + + /* wait till IRC8M is ready */ + while (RESET == rcu_flag_get(RCU_FLAG_IRC8MSTB)) { + } +#else + /* enable HXTAL */ + rcu_osci_on(RCU_HXTAL); + + /* wait till HXTAL is ready */ + while(RESET == rcu_flag_get(RCU_FLAG_HXTALSTB)) { + } +#endif + + /* enable PLL */ + rcu_osci_on(RCU_PLL_CK); + + /* wait till PLL is ready */ + while(RESET == rcu_flag_get(RCU_FLAG_PLLSTB)) { + } + + /* select PLL as system clock source */ + rcu_system_clock_source_config(RCU_CKSYSSRC_PLL); + + /* wait till PLL is used as system clock source */ + while(0x08U != rcu_system_clock_source_get()) { + } + + /* low power sleep on exit disabled */ + system_lowpower_reset(SCB_LPM_DEEPSLEEP); +} + +#endif /* USBD_LOWPWR_MODE_ENABLE */ + +/*! + \brief resume the USB device + \param[in] none + \param[out] none + \retval none +*/ +static void usbd_resume (usb_dev *udev) +{ +#ifdef LPM_ENABLED + if(1 == udev->lpm.L1_remote_wakeup){ + USBD_CTL |= CTL_L1RSREQ; + } +#endif /* LPM_ENABLED */ + + if(1U == usbd_core.dev->pm.remote_wakeup){ + /* make USB resume */ + USBD_CTL |= CTL_RSREQ; + } +} + +/*! + \brief set USB device to leave mode + \param[in] none + \param[out] none + \retval none +*/ +static void usbd_leave_suspend (void) +{ + /* clear low_power mode bit in USBD_CTL */ + USBD_CTL &= ~CTL_LOWM; + +#ifdef USBD_LOWPWR_MODE_ENABLE + + /* restore normal operations */ + lowpower_mode_exit(); + +#endif /* USBD_LOWPWR_MODE_ENABLE */ + + /* clear SETSPS bit */ + USBD_CTL &= ~CTL_SETSPS; +} + +/*! + \brief set USB device to enter suspend mode + \param[in] none + \param[out] none + \retval none +*/ +static void usbd_suspend (void) +{ + /* set USB module to suspend and low-power mode */ + USBD_CTL |= CTL_SETSPS | CTL_LOWM; + +#ifdef USBD_LOWPWR_MODE_ENABLE + + /* check wakeup flag is set */ + if (0U == (USBD_INTF & INTF_WKUPIF)) { + /* enter DEEP_SLEEP mode with LDO in low power mode */ + pmu_to_deepsleepmode(PMU_LDO_LOWPOWER, WFI_CMD); + } else { + /* clear wakeup interrupt flag */ + CLR(WKUPIF); + + /* clear set_suspend flag */ + USBD_CTL &= ~CTL_SETSPS; + } + +#endif /* USBD_LOWPWR_MODE_ENABLE */ +} diff --git a/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbd_library/usbd/Source/usbd_lld_int.c b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbd_library/usbd/Source/usbd_lld_int.c new file mode 100644 index 0000000000..c00e72638a --- /dev/null +++ b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbd_library/usbd/Source/usbd_lld_int.c @@ -0,0 +1,276 @@ + /*! + \file usbd_lld_int.c + \brief USB device low level interrupt routines + + \version 2020-07-17, V3.0.0, firmware for GD32F10x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "usbd_lld_int.h" +#include "usbd_lld_core.h" + +/* local function prototypes ('static') */ +static void usbd_int_suspend (usb_dev *udev); + +/*! + \brief handle USB high priority successful transfer event + \param[in] udev: pointer to USB device instance + \param[out] none + \retval none +*/ +void usbd_int_hpst (usb_dev *udev) +{ + __IO uint16_t int_status = 0U; + + /* wait till interrupts are not pending */ + while ((int_status = (uint16_t)USBD_INTF) & (uint16_t)INTF_STIF) { + /* get endpoint number */ + uint8_t ep_num = (uint8_t)(int_status & INTF_EPNUM); + + uint8_t transc_num = (uint8_t)TRANSC_UNKNOWN; + + if (int_status & INTF_DIR) { + if (USBD_EPxCS(ep_num) & EPxCS_RX_ST) { + uint16_t count = 0U; + + usb_transc *transc = &udev->transc_out[ep_num]; + + /* clear successful receive interrupt flag */ + USBD_EP_RX_ST_CLEAR(ep_num); + + count = udev->drv_handler->ep_read (transc->xfer_buf, ep_num, (uint8_t)EP_BUF_DBL); + + user_buffer_free(ep_num, (uint8_t)DBUF_EP_OUT); + + transc->xfer_buf += count; + transc->xfer_count += count; + transc->xfer_len -= count; + + if ((0U == transc->xfer_len) || (count < transc->max_len)) { + USBD_EP_RX_STAT_SET(ep_num, EPRX_NAK); + + transc_num = (uint8_t)TRANSC_OUT; + } + } + } else { + /* handle the in direction transaction */ + if (USBD_EPxCS(ep_num) & EPxCS_TX_ST) { + /* clear successful transmit interrupt flag */ + USBD_EP_TX_ST_CLEAR(ep_num); + + transc_num = (uint8_t)TRANSC_IN; + } + } + + if ((uint8_t)TRANSC_UNKNOWN != transc_num) { + udev->ep_transc[ep_num][transc_num](udev, ep_num); + } + } +} + +/*! + \brief USB interrupt events service routine + \param[in] none + \param[out] none + \retval none +*/ +void usbd_isr (void) +{ + __IO uint16_t int_status = (uint16_t)USBD_INTF; + __IO uint16_t int_flag = (uint16_t)(USBD_INTF & (USBD_CTL & USBD_INTEN)); + + usb_dev *udev = usbd_core.dev; + + if (INTF_STIF & int_flag) { + /* wait till interrupts are not pending */ + while ((int_status = (uint16_t)USBD_INTF) & (uint16_t)INTF_STIF) { + /* get endpoint number */ + uint8_t ep_num = (uint8_t)(int_status & INTF_EPNUM); + + if (int_status & INTF_DIR) { + /* handle the USB OUT direction transaction */ + if (USBD_EPxCS(ep_num) & EPxCS_RX_ST) { + /* clear successful receive interrupt flag */ + USBD_EP_RX_ST_CLEAR(ep_num); + + if (USBD_EPxCS(ep_num) & EPxCS_SETUP) { + + if (ep_num == 0U) { + udev->ep_transc[ep_num][TRANSC_SETUP](udev, ep_num); + } else { + return; + } + } else { + usb_transc *transc = &udev->transc_out[ep_num]; + + uint16_t count = udev->drv_handler->ep_read (transc->xfer_buf, ep_num, (uint8_t)EP_BUF_SNG); + + transc->xfer_buf += count; + transc->xfer_count += count; + + if ((transc->xfer_count >= transc->xfer_len) || (count < transc->max_len)) { + if (udev->ep_transc[ep_num][TRANSC_OUT]) { + udev->ep_transc[ep_num][TRANSC_OUT](udev, ep_num); + } + } else { + udev->drv_handler->ep_rx_enable(udev, ep_num); + } + } + } + } else { + /* handle the USB IN direction transaction */ + if (USBD_EPxCS(ep_num) & EPxCS_TX_ST) { + /* clear successful transmit interrupt flag */ + USBD_EP_TX_ST_CLEAR(ep_num); + + usb_transc *transc = &udev->transc_in[ep_num]; + + if (transc->xfer_len == 0U) { + if (udev->ep_transc[ep_num][TRANSC_IN]) { + udev->ep_transc[ep_num][TRANSC_IN](udev, ep_num); + } + } else { + usbd_ep_send(udev, ep_num, transc->xfer_buf, transc->xfer_len); + } + } + } + } + } + + if (INTF_WKUPIF & int_flag) { + /* clear wakeup interrupt flag in INTF */ + CLR(WKUPIF); + + /* restore the old cur_status */ + udev->cur_status = udev->backup_status; + +#ifdef LPM_ENABLED + if ((0U == udev->pm.remote_wakeup_on) && (0U == udev->lpm.L1_resume)) { + resume_mcu(udev); + } else if (1U == udev->pm.remote_wakeup_on) { + /* no operation */ + } else { + udev->lpm.L1_resume = 0U; + } + + /* clear L1 remote wakeup flag */ + udev->lpm.L1_remote_wakeup = 0U; +#else + if (0U == udev->pm.remote_wakeup_on) { + resume_mcu(udev); + } +#endif /* LPM_ENABLED */ + } + + if (INTF_SPSIF & int_flag) { + if(!(USBD_CTL & CTL_RSREQ)) { + usbd_int_suspend (udev); + + /* clear of suspend interrupt flag bit must be done after setting of CTLR_SETSPS */ + CLR(SPSIF); + } + } + + if (INTF_SOFIF & int_flag) { + /* clear SOF interrupt flag in INTF */ + CLR(SOFIF); + + /* if necessary, user can add code here */ + if (NULL != usbd_int_fops) { + (void)usbd_int_fops->SOF(udev); + } + } + + if (INTF_ESOFIF & int_flag) { + /* clear ESOF interrupt flag in INTF */ + CLR(ESOFIF); + + /* control resume time by ESOFs */ + if (udev->pm.esof_count > 0U) { + if (0U == --udev->pm.esof_count) { + if (udev->pm.remote_wakeup_on) { + USBD_CTL &= ~CTL_RSREQ; + + udev->pm.remote_wakeup_on = 0U; + } else { + USBD_CTL |= CTL_RSREQ; + + udev->pm.esof_count = 3U; + udev->pm.remote_wakeup_on = 1U; + } + } + } + } + + if (INTF_RSTIF & int_flag) { + /* clear reset interrupt flag in INTF */ + CLR(RSTIF); + + udev->drv_handler->ep_reset(udev); + } + +#ifdef LPM_ENABLED + if (INTF_L1REQ & int_flag) { + /* clear L1 ST bit in LPM INTF */ + USBD_INTF = CLR(L1REQ); + + /* read BESL field from subendpoint0 register which corresponds to HIRD parameter in LPM spec */ + udev->lpm.besl = (USBD_LPMCS & LPMCS_BLSTAT) >> 4; + + /* read BREMOTEWAKE bit from subendpoint0 register which corresponding to bRemoteWake bit in LPM request */ + udev->lpm.L1_remote_wakeup = (USBD_LPMCS & LPMCS_REMWK) >> 3; + + /* process USB device core layer suspend routine */ + usbd_int_suspend(udev); + } +#endif /* LPM_ENABLED */ +} + +/*! + \brief handle USB suspend event + \param[in] udev: pointer to USB device instance + \param[out] none + \retval none +*/ +static void usbd_int_suspend (usb_dev *udev) +{ + /* store the device current status */ + udev->backup_status = udev->cur_status; + + /* set device in suspended state */ + udev->cur_status = (uint8_t)USBD_SUSPENDED; + + /* usb enter in suspend mode and mcu system in low power mode */ + if (udev->pm.suspend_enabled) { + usbd_to_suspend(udev); + } else { + /* if not possible then resume after xx ms */ + udev->pm.esof_count = 3U; + } +} diff --git a/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/device/class/audio/Include/audio_core.h b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/device/class/audio/Include/audio_core.h new file mode 100644 index 0000000000..fabf9f3dc8 --- /dev/null +++ b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/device/class/audio/Include/audio_core.h @@ -0,0 +1,300 @@ +/*! + \file audio_core.h + \brief the header file of USB audio device class core functions + + \version 2020-07-17, V3.0.0, firmware for GD32F10x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef __AUDIO_CORE_H +#define __AUDIO_CORE_H + +#include "usbd_enum.h" + +#define FORMAT_24BIT(x) (uint8_t)(x);(uint8_t)(x >> 8U);(uint8_t)(x >> 16U) + +/* number of sub-packets in the audio transfer buffer. you can modify this value but always make sure + that it is an even number and higher than 3 */ +#define OUT_PACKET_NUM 4U + +/* total size of the audio transfer buffer */ +#define OUT_BUF_MARGIN 4U +#define TOTAL_OUT_BUF_SIZE ((uint32_t)((SPEAKER_OUT_PACKET + OUT_BUF_MARGIN) * OUT_PACKET_NUM)) + +#define AUDIO_CONFIG_DESC_SET_LEN (sizeof(usb_desc_config_set)) +#define AUDIO_INTERFACE_DESC_SIZE 9U + +#define USB_AUDIO_DESC_SIZ 0x09U +#define AUDIO_STANDARD_EP_DESC_SIZE 0x09U +#define AUDIO_STREAMING_EP_DESC_SIZE 0x07U + +/* audio interface class code */ +#define USB_CLASS_AUDIO 0x01U + +/* audio interface subclass codes */ +#define AUDIO_SUBCLASS_CONTROL 0x01U +#define AUDIO_SUBCLASS_AUDIOSTREAMING 0x02U +#define AUDIO_SUBCLASS_MIDISTREAMING 0x03U + +/* audio interface protocol codes */ +#define AUDIO_PROTOCOL_UNDEFINED 0x00U +#define AUDIO_STREAMING_GENERAL 0x01U +#define AUDIO_STREAMING_FORMAT_TYPE 0x02U + +/* audio class-specific descriptor types */ +#define AUDIO_DESCTYPE_UNDEFINED 0x20U +#define AUDIO_DESCTYPE_DEVICE 0x21U +#define AUDIO_DESCTYPE_CONFIGURATION 0x22U +#define AUDIO_DESCTYPE_STRING 0x23U +#define AUDIO_DESCTYPE_INTERFACE 0x24U +#define AUDIO_DESCTYPE_ENDPOINT 0x25U + +/* audio control interface descriptor subtypes */ +#define AUDIO_CONTROL_HEADER 0x01U +#define AUDIO_CONTROL_INPUT_TERMINAL 0x02U +#define AUDIO_CONTROL_OUTPUT_TERMINAL 0x03U +#define AUDIO_CONTROL_MIXER_UNIT 0x04U +#define AUDIO_CONTROL_SELECTOR_UNIT 0x05U +#define AUDIO_CONTROL_FEATURE_UNIT 0x06U +#define AUDIO_CONTROL_PROCESSING_UNIT 0x07U +#define AUDIO_CONTROL_EXTENSION_UNIT 0x08U + +#define AUDIO_INPUT_TERMINAL_DESC_SIZE 0x0CU +#define AUDIO_OUTPUT_TERMINAL_DESC_SIZE 0x09U +#define AUDIO_STREAMING_INTERFACE_DESC_SIZE 0x07U + +#define AUDIO_CONTROL_MUTE 0x01U +#define AUDIO_CONTROL_VOLUME 0x02U + +#define AUDIO_FORMAT_TYPE_I 0x01U +#define AUDIO_FORMAT_TYPE_III 0x03U + +#define USB_ENDPOINT_TYPE_ISOCHRONOUS 0x01U +#define AUDIO_ENDPOINT_GENERAL 0x01U + +#define AUDIO_REQ_UNDEFINED 0x00U +#define AUDIO_REQ_SET_CUR 0x01U +#define AUDIO_REQ_GET_CUR 0x81U +#define AUDIO_REQ_SET_MIN 0x02U +#define AUDIO_REQ_GET_MIN 0x82U +#define AUDIO_REQ_SET_MAX 0x03U +#define AUDIO_REQ_GET_MAX 0x83U +#define AUDIO_REQ_SET_RES 0x04U +#define AUDIO_REQ_GET_RES 0x84U +#define AUDIO_REQ_SET_MEM 0x05U +#define AUDIO_REQ_GET_MEM 0x85U +#define AUDIO_REQ_GET_STAT 0xFFU + +#define AUDIO_OUT_STREAMING_CTRL 0x05U +#define AUDIO_IN_STREAMING_CTRL 0x02U + +/* audio stream interface number */ +enum +{ +#ifdef USE_USB_AUDIO_MICPHONE + MIC_INTERFACE_COUNT, +#endif +#ifdef USE_USB_AUDIO_SPEAKER + SPEAK_INTERFACE_COUNT, +#endif + CONFIG_DESC_AS_ITF_COUNT, +}; + +#define AC_ITF_TOTAL_LEN (sizeof(usb_desc_AC_itf) + CONFIG_DESC_AS_ITF_COUNT*(sizeof(usb_desc_input_terminal) + \ + sizeof(usb_desc_mono_feature_unit) + sizeof(usb_desc_output_terminal))) + +#pragma pack(1) + +typedef struct +{ + usb_desc_header header; /*!< descriptor header, including type and size */ + uint8_t bDescriptorSubtype; /*!< header descriptor subtype */ + uint16_t bcdADC; /*!< audio device class specification release number in binary-coded decimal */ + uint16_t wTotalLength; /*!< total number of bytes */ + uint8_t bInCollection; /*!< the number of the streaming interfaces */ +#ifdef USE_USB_AUDIO_MICPHONE + uint8_t baInterfaceNr0; /*!< interface number of the streaming interfaces */ +#endif + +#ifdef USE_USB_AUDIO_SPEAKER + uint8_t baInterfaceNr1; /*!< interface number of the streaming interfaces */ +#endif +} usb_desc_AC_itf; + +typedef struct +{ + usb_desc_header header; /*!< descriptor header, including type and size */ + uint8_t bDescriptorSubtype; /*!< AS_GENERAL descriptor subtype */ + uint8_t bTerminalLink; /*!< the terminal ID */ + uint8_t bDelay; /*!< delay introduced by the data path */ + uint16_t wFormatTag; /*!< the audio data format */ +} usb_desc_AS_itf; + +typedef struct +{ + usb_desc_header header; /*!< descriptor header, including type and size */ + uint8_t bDescriptorSubtype; /*!< INPUT_TERMINAL descriptor subtype. */ + uint8_t bTerminalID; /*!< constant uniquely identifying the terminal within the audio function */ + uint16_t wTerminalType; /*!< constant characterizing the type of terminal */ + uint8_t bAssocTerminal; /*!< ID of the output terminal */ + uint8_t bNrChannels; /*!< number of logical output channels */ + uint16_t wChannelConfig; /*!< describes the spatial location of the logical channels */ + uint8_t iChannelNames; /*!< index of a string descriptor */ + uint8_t iTerminal; /*!< index of a string descriptor */ +} usb_desc_input_terminal; + +typedef struct +{ + usb_desc_header header; /*!< descriptor header, including type and size */ + uint8_t bDescriptorSubtype; /*!< OUTPUT_TERMINAL descriptor subtype */ + uint8_t bTerminalID; /*!< constant uniquely identifying the terminal within the audio function */ + uint16_t wTerminalType; /*!< constant characterizing the type of terminal */ + uint8_t bAssocTerminal; /*!< constant, identifying the input terminal to which this output terminal is associated */ + uint8_t bSourceID; /*!< ID of the unit or terminal */ + uint8_t iTerminal; /*!< index of a string descriptor */ +} usb_desc_output_terminal; + +typedef struct +{ + usb_desc_header header; /*!< descriptor header, including type and size */ + uint8_t bDescriptorSubtype; /*!< FEATURE_UNIT descriptor subtype */ + uint8_t bUnitID; /*!< constant uniquely identifying the unit within the audio function */ + uint8_t bSourceID; /*!< ID of the unit or terminal */ + uint8_t bControlSize; /*!< size in bytes of an element of the bmaControls() array */ + uint8_t bmaControls0; /*!< a bit set to 1 indicates that the mentioned control is supported for master channel 0 */ + uint8_t bmaControls1; /*!< a bit set to 1 indicates that the mentioned control is supported for logical channel 1 */ + uint8_t iFeature; /*!< index of a string descriptor */ +} usb_desc_mono_feature_unit; + +typedef struct +{ + usb_desc_header header; /*!< descriptor header, including type and size */ + uint8_t bDescriptorSubtype; /*!< FEATURE_UNIT descriptor subtype */ + uint8_t bUnitID; /*!< constant uniquely identifying the unit within the audio function */ + uint8_t bSourceID; /*!< ID of the unit or terminal */ + uint8_t bControlSize; /*!< size in bytes of an element of the bmaControls() array */ + uint16_t bmaControls0; /*!< a bit set to 1 indicates that the mentioned control is supported for master channel 0 */ + uint16_t bmaControls1; /*!< a bit set to 1 indicates that the mentioned control is supported for logical channel 1 */ + uint16_t bmaControls2; /*!< a bit set to 1 indicates that the mentioned control is supported for logical channel 2 */ + uint8_t iFeature; /*!< index of a string descriptor */ +} usb_desc_stereo_feature_unit; + +typedef struct +{ + usb_desc_header header; /*!< descriptor header, including type and size */ + uint8_t bDescriptorSubtype; /*!< FORMAT_TYPE descriptor subtype */ + uint8_t bFormatType; /*!< constant identifying the format type */ + uint8_t bNrChannels; /*!< indicates the number of physical channels in the audio data stream */ + uint8_t bSubFrameSize; /*!< the number of bytes occupied by one audio subframe */ + uint8_t bBitResolution; /*!< the number of effectively used bits from the available bits in an audio subframe */ + uint8_t bSamFreqType; /*!< indicates how the sampling frequency can be programmed */ + uint8_t bSamFreq[3]; /*!< sampling frequency ns in Hz for this isochronous data endpoint */ +} usb_desc_format_type; + +typedef struct +{ + usb_desc_header header; /*!< descriptor header, including type and size */ + uint8_t bEndpointAddress; /*!< the address of the endpoint */ + uint8_t bmAttributes; /*!< transfer type and synchronization type */ + uint16_t wMaxPacketSize; /*!< maximum packet size this endpoint is capable of sending or receiving */ + uint8_t bInterval; /*!< left to the designer's discretion */ + uint8_t bRefresh; /*!< reset to 0 */ + uint8_t bSynchAddress; /*!< reset to 0 */ +} usb_desc_std_ep; + +typedef struct +{ + usb_desc_header header; /*!< descriptor header, including type and size */ + uint8_t bDescriptorSubtype; /*!< EP_GENERAL descriptor subtype */ + uint8_t bmAttributes; /*!< transfer type and synchronization type */ + uint8_t bLockDelayUnits; /*!< indicates the units used for the wLockDelay field */ + uint16_t wLockDelay; /*!< indicates the time it takes this endpoint to reliably lock its internal clock recovery circuitry */ +} usb_desc_AS_ep; + +#pragma pack() + +/* USB configuration descriptor structure */ +typedef struct +{ + usb_desc_config config; + usb_desc_itf std_itf; + usb_desc_AC_itf ac_itf; + +#ifdef USE_USB_AUDIO_MICPHONE + usb_desc_input_terminal mic_in_terminal; + usb_desc_mono_feature_unit mic_feature_unit; + usb_desc_output_terminal mic_out_terminal; +#endif + +#ifdef USE_USB_AUDIO_SPEAKER + usb_desc_input_terminal speak_in_terminal; + usb_desc_mono_feature_unit speak_feature_unit; + usb_desc_output_terminal speak_out_terminal; +#endif + +#ifdef USE_USB_AUDIO_MICPHONE + usb_desc_itf mic_std_as_itf_zeroband; + usb_desc_itf mic_std_as_itf_opera; + usb_desc_AS_itf mic_as_itf; + usb_desc_format_type mic_format_typeI; + usb_desc_std_ep mic_std_endpoint; + usb_desc_AS_ep mic_as_endpoint; +#endif + +#ifdef USE_USB_AUDIO_SPEAKER + usb_desc_itf speak_std_as_itf_zeroband; + usb_desc_itf speak_std_as_itf_opera; + usb_desc_AS_itf speak_as_itf; + usb_desc_format_type speak_format_typeI; + usb_desc_std_ep speak_std_endpoint; + usb_desc_AS_ep speak_as_endpoint; +#endif +} usb_desc_config_set; + +typedef struct +{ + /* main buffer for audio data out transfers and its relative pointers */ + uint8_t isoc_out_buff[TOTAL_OUT_BUF_SIZE * 2U]; + uint8_t* isoc_out_wrptr; + uint8_t* isoc_out_rdptr; + + /* main buffer for audio control requests transfers and its relative variables */ + uint8_t audioctl[64]; + uint8_t audioctl_unit; + uint32_t audioctl_len; + +#ifdef USE_USB_AUDIO_SPEAKER + uint32_t play_flag; +#endif /* USE_USB_AUDIO_SPEAKER */ +} usbd_audio_handler; + +extern usb_desc audio_desc; +extern usb_class_core usbd_audio_cb; + +#endif /* __AUDIO_CORE_H */ diff --git a/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/device/class/audio/Include/audio_out_itf.h b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/device/class/audio/Include/audio_out_itf.h new file mode 100644 index 0000000000..46c8f8b2d9 --- /dev/null +++ b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/device/class/audio/Include/audio_out_itf.h @@ -0,0 +1,76 @@ +/*! + \file audio_out_itf.h + \brief audio OUT (playback) interface header file + + \version 2020-07-17, V3.0.0, firmware for GD32F10x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef __AUDIO_OUT_ITF_H +#define __AUDIO_OUT_ITF_H + +#include "usbd_conf.h" + +/* audio commands enumeration */ +typedef enum +{ + AUDIO_CMD_PLAY = 1U, + AUDIO_CMD_PAUSE, + AUDIO_CMD_STOP, +}audio_cmd_enum; + +/* mute commands */ +#define AUDIO_MUTE 0x01U +#define AUDIO_UNMUTE 0x00U + +/* functions return value */ +#define AUDIO_OK 0x00U +#define AUDIO_FAIL 0xFFU + +/* audio machine states */ +#define AUDIO_STATE_INACTIVE 0x00U +#define AUDIO_STATE_ACTIVE 0x01U +#define AUDIO_STATE_PLAYING 0x02U +#define AUDIO_STATE_PAUSED 0x03U +#define AUDIO_STATE_STOPPED 0x04U +#define AUDIO_STATE_ERROR 0x05U + +typedef struct { + uint8_t (*audio_init) (uint32_t audio_freq, uint32_t volume, uint32_t options); + uint8_t (*audio_deinit) (uint32_t options); + uint8_t (*audio_cmd) (uint8_t* pbuf, uint32_t size, uint8_t cmd); + uint8_t (*audio_volume_ctl) (uint8_t vol); + uint8_t (*audio_mute_ctl) (uint8_t cmd); + uint8_t (*audio_periodic_tc) (uint8_t cmd); + uint8_t (*audio_state_get) (void); +} audio_fops_struct; + +extern audio_fops_struct audio_out_fops; + +#endif /* __AUDIO_OUT_ITF_H */ diff --git a/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/device/class/audio/Source/audio_core.c b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/device/class/audio/Source/audio_core.c new file mode 100644 index 0000000000..e392bf3054 --- /dev/null +++ b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/device/class/audio/Source/audio_core.c @@ -0,0 +1,811 @@ +/*! + \file audio_core.c + \brief USB audio device class core functions + + \version 2020-07-17, V3.0.0, firmware for GD32F10x + \version 2020-12-07, V3.0.1, firmware for GD32F10x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "audio_out_itf.h" +#include "audio_core.h" + +#include + +#define USBD_VID 0x28E9U +#define USBD_PID 0x9574U + +#ifdef USE_USB_AUDIO_MICPHONE +extern volatile uint32_t count_data; +extern const char wavetestdata[]; +#define LENGTH_DATA (1747 * 32) +#endif + +/* local function prototypes ('static') */ +static uint8_t audio_init (usb_dev *udev, uint8_t config_index); +static uint8_t audio_deinit (usb_dev *udev, uint8_t config_index); +static uint8_t audio_req_handler (usb_dev *udev, usb_req *req); +static uint8_t audio_set_intf (usb_dev *udev, usb_req *req); +static uint8_t audio_ctlx_out (usb_dev *udev); +static uint8_t audio_data_in (usb_dev *udev, uint8_t ep_num); +static uint8_t audio_data_out (usb_dev *udev, uint8_t ep_num); +static uint8_t usbd_audio_sof (usb_dev *udev); + +usb_class_core usbd_audio_cb = { + .init = audio_init, + .deinit = audio_deinit, + .req_proc = audio_req_handler, + .set_intf = audio_set_intf, + .ctlx_out = audio_ctlx_out, + .data_in = audio_data_in, + .data_out = audio_data_out, + .SOF = usbd_audio_sof +}; + +#define VOL_MIN 0U /* volume Minimum Value */ +#define VOL_MAX 100U /* volume Maximum Value */ +#define VOL_RES 1U /* volume Resolution */ +#define VOL_0dB 70U /* 0dB is in the middle of VOL_MIN and VOL_MAX */ + +/* note:it should use the c99 standard when compiling the below codes */ +/* USB standard device descriptor */ +const usb_desc_dev audio_dev_desc = +{ + .header = + { + .bLength = USB_DEV_DESC_LEN, + .bDescriptorType = USB_DESCTYPE_DEV + }, + .bcdUSB = 0x0200U, + .bDeviceClass = 0x00U, + .bDeviceSubClass = 0x00U, + .bDeviceProtocol = 0x00U, + .bMaxPacketSize0 = USB_FS_EP0_MAX_LEN, + .idVendor = USBD_VID, + .idProduct = USBD_PID, + .bcdDevice = 0x0100U, + .iManufacturer = STR_IDX_MFC, + .iProduct = STR_IDX_PRODUCT, + .iSerialNumber = STR_IDX_SERIAL, + .bNumberConfigurations = USBD_CFG_MAX_NUM +}; + +/* USB device configuration descriptor */ +const usb_desc_config_set audio_config_set = +{ + .config = + { + .header = + { + .bLength = sizeof(usb_desc_config), + .bDescriptorType = USB_DESCTYPE_CONFIG + }, + .wTotalLength = AUDIO_CONFIG_DESC_SET_LEN, + .bNumInterfaces = 0x01U + CONFIG_DESC_AS_ITF_COUNT, + .bConfigurationValue = 0x01U, + .iConfiguration = 0x00U, + .bmAttributes = 0xC0U, + .bMaxPower = 0x32U + }, + + .std_itf = + { + .header = + { + .bLength = sizeof(usb_desc_itf), + .bDescriptorType = USB_DESCTYPE_ITF + }, + .bInterfaceNumber = 0x00U, + .bAlternateSetting = 0x00U, + .bNumEndpoints = 0x00U, + .bInterfaceClass = USB_CLASS_AUDIO, + .bInterfaceSubClass = AUDIO_SUBCLASS_CONTROL, + .bInterfaceProtocol = AUDIO_PROTOCOL_UNDEFINED, + .iInterface = 0x00U + }, + + .ac_itf = + { + .header = + { + .bLength = sizeof(usb_desc_AC_itf), + .bDescriptorType = AUDIO_DESCTYPE_INTERFACE + }, + .bDescriptorSubtype = 0x01U, + .bcdADC = 0x0100U, + .wTotalLength = AC_ITF_TOTAL_LEN, + .bInCollection = CONFIG_DESC_AS_ITF_COUNT, +#ifdef USE_USB_AUDIO_MICPHONE + .baInterfaceNr0 = 0x01U, +#endif +#ifdef USE_USB_AUDIO_SPEAKER + .baInterfaceNr1 = 0x02U +#endif + }, + +#ifdef USE_USB_AUDIO_MICPHONE + .mic_in_terminal = + { + .header = + { + .bLength = sizeof(usb_desc_input_terminal), + .bDescriptorType = AUDIO_DESCTYPE_INTERFACE + }, + .bDescriptorSubtype = 0x02U, + .bTerminalID = 0x01U, + .wTerminalType = 0x0201U, + .bAssocTerminal = 0x00U, + .bNrChannels = 0x02U, + .wChannelConfig = 0x0003U, + .iChannelNames = 0x00U, + .iTerminal = 0x00U + }, + + .mic_feature_unit = + { + .header = + { + .bLength = sizeof(usb_desc_mono_feature_unit), + .bDescriptorType = AUDIO_DESCTYPE_INTERFACE + }, + .bDescriptorSubtype = AUDIO_CONTROL_FEATURE_UNIT, + .bUnitID = AUDIO_IN_STREAMING_CTRL, + .bSourceID = 0x01U, + .bControlSize = 0x01U, + .bmaControls0 = AUDIO_CONTROL_MUTE, + .bmaControls1 = AUDIO_CONTROL_VOLUME, + .iFeature = 0x00U + }, + + .mic_out_terminal = + { + .header = + { + .bLength = sizeof(usb_desc_output_terminal), + .bDescriptorType = AUDIO_DESCTYPE_INTERFACE + }, + .bDescriptorSubtype = AUDIO_CONTROL_OUTPUT_TERMINAL, + .bTerminalID = 0x03U, + .wTerminalType = 0x0101U, + .bAssocTerminal = 0x00U, + .bSourceID = 0x02U, + .iTerminal = 0x00U + }, +#endif + +#ifdef USE_USB_AUDIO_SPEAKER + .speak_in_terminal = + { + .header = + { + .bLength = sizeof(usb_desc_input_terminal), + .bDescriptorType = AUDIO_DESCTYPE_INTERFACE + }, + .bDescriptorSubtype = AUDIO_CONTROL_INPUT_TERMINAL, + .bTerminalID = 0x04U, + .wTerminalType = 0x0101U, + .bAssocTerminal = 0x00U, + .bNrChannels = 0x02U, + .wChannelConfig = 0x0003U, + .iChannelNames = 0x00U, + .iTerminal = 0x00U + }, + + .speak_feature_unit = + { + .header = + { + .bLength = sizeof(usb_desc_mono_feature_unit), + .bDescriptorType = AUDIO_DESCTYPE_INTERFACE + }, + .bDescriptorSubtype = AUDIO_CONTROL_FEATURE_UNIT, + .bUnitID = AUDIO_OUT_STREAMING_CTRL, + .bSourceID = 0x04U, + .bControlSize = 0x01U, + .bmaControls0 = AUDIO_CONTROL_MUTE, + .bmaControls1 = AUDIO_CONTROL_VOLUME, + .iFeature = 0x00U + }, + + .speak_out_terminal = + { + .header = + { + .bLength = sizeof(usb_desc_output_terminal), + .bDescriptorType = AUDIO_DESCTYPE_INTERFACE + }, + .bDescriptorSubtype = AUDIO_CONTROL_OUTPUT_TERMINAL, + .bTerminalID = 0x06U, + .wTerminalType = 0x0301U, + .bAssocTerminal = 0x00U, + .bSourceID = 0x05U, + .iTerminal = 0x00U + }, +#endif + +#ifdef USE_USB_AUDIO_MICPHONE + .mic_std_as_itf_zeroband = + { + .header = + { + .bLength = sizeof(usb_desc_itf), + .bDescriptorType = USB_DESCTYPE_ITF + }, + .bInterfaceNumber = 0x01U, + .bAlternateSetting = 0x00U, + .bNumEndpoints = 0x00U, + .bInterfaceClass = USB_CLASS_AUDIO, + .bInterfaceSubClass = AUDIO_SUBCLASS_AUDIOSTREAMING, + .bInterfaceProtocol = AUDIO_PROTOCOL_UNDEFINED, + .iInterface = 0x00U + }, + + .mic_std_as_itf_opera = + { + .header = + { + .bLength = sizeof(usb_desc_itf), + .bDescriptorType = USB_DESCTYPE_ITF + }, + .bInterfaceNumber = 0x01U, + .bAlternateSetting = 0x01U, + .bNumEndpoints = 0x01U, + .bInterfaceClass = USB_CLASS_AUDIO, + .bInterfaceSubClass = AUDIO_SUBCLASS_AUDIOSTREAMING, + .bInterfaceProtocol = AUDIO_PROTOCOL_UNDEFINED, + .iInterface = 0x00U + }, + + .mic_as_itf = + { + .header = + { + .bLength = sizeof(usb_desc_AS_itf), + .bDescriptorType = AUDIO_DESCTYPE_INTERFACE + }, + .bDescriptorSubtype = AUDIO_STREAMING_GENERAL, + .bTerminalLink = 0x03U, + .bDelay = 0x01U, + .wFormatTag = 0x0001U, + }, + + .mic_format_typeI = + { + .header = + { + .bLength = sizeof(usb_desc_format_type), + .bDescriptorType = AUDIO_DESCTYPE_INTERFACE + }, + .bDescriptorSubtype = AUDIO_STREAMING_FORMAT_TYPE, + .bFormatType = AUDIO_FORMAT_TYPE_I, + .bNrChannels = MIC_IN_CHANNEL_NBR, + .bSubFrameSize = 0x02U, + .bBitResolution = MIC_IN_BIT_RESOLUTION, + .bSamFreqType = 0x01U, + .bSamFreq[0] = (uint8_t)USBD_MIC_FREQ, + .bSamFreq[1] = USBD_MIC_FREQ >> 8U, + .bSamFreq[2] = USBD_MIC_FREQ >> 16U + }, + + .mic_std_endpoint = + { + .header = + { + .bLength = sizeof(usb_desc_std_ep), + .bDescriptorType = USB_DESCTYPE_EP + }, + .bEndpointAddress = AUDIO_IN_EP, + .bmAttributes = USB_ENDPOINT_TYPE_ISOCHRONOUS, + .wMaxPacketSize = MIC_IN_PACKET, + .bInterval = 0x01U, + .bRefresh = 0x00U, + .bSynchAddress = 0x00U + }, + + .mic_as_endpoint = + { + .header = + { + .bLength = sizeof(usb_desc_AS_ep), + .bDescriptorType = AUDIO_DESCTYPE_ENDPOINT + }, + .bDescriptorSubtype = AUDIO_ENDPOINT_GENERAL, + .bmAttributes = 0x00U, + .bLockDelayUnits = 0x00U, + .wLockDelay = 0x0000U, + }, +#endif + +#ifdef USE_USB_AUDIO_SPEAKER + .speak_std_as_itf_zeroband = + { + .header = + { + .bLength = sizeof(usb_desc_itf), + .bDescriptorType = USB_DESCTYPE_ITF + }, + .bInterfaceNumber = 0x02U, + .bAlternateSetting = 0x00U, + .bNumEndpoints = 0x00U, + .bInterfaceClass = USB_CLASS_AUDIO, + .bInterfaceSubClass = AUDIO_SUBCLASS_AUDIOSTREAMING, + .bInterfaceProtocol = AUDIO_PROTOCOL_UNDEFINED, + .iInterface = 0x00U + }, + + .speak_std_as_itf_opera = + { + .header = + { + .bLength = sizeof(usb_desc_itf), + .bDescriptorType = USB_DESCTYPE_ITF + }, + .bInterfaceNumber = 0x02U, + .bAlternateSetting = 0x01U, + .bNumEndpoints = 0x01U, + .bInterfaceClass = USB_CLASS_AUDIO, + .bInterfaceSubClass = AUDIO_SUBCLASS_AUDIOSTREAMING, + .bInterfaceProtocol = AUDIO_PROTOCOL_UNDEFINED, + .iInterface = 0x00U + }, + + .speak_as_itf = + { + .header = + { + .bLength = sizeof(usb_desc_AS_itf), + .bDescriptorType = AUDIO_DESCTYPE_INTERFACE + }, + .bDescriptorSubtype = AUDIO_STREAMING_GENERAL, + .bTerminalLink = 0x04U, + .bDelay = 0x01U, + .wFormatTag = 0x0001U, + }, + + .speak_format_typeI = + { + .header = + { + .bLength = sizeof(usb_desc_format_type), + .bDescriptorType = AUDIO_DESCTYPE_INTERFACE + }, + .bDescriptorSubtype = AUDIO_STREAMING_FORMAT_TYPE, + .bFormatType = AUDIO_FORMAT_TYPE_I, + .bNrChannels = SPEAKER_OUT_CHANNEL_NBR, + .bSubFrameSize = 0x02U, + .bBitResolution = SPEAKER_OUT_BIT_RESOLUTION, + .bSamFreqType = 0x01U, + .bSamFreq[0] = (uint8_t)USBD_SPEAKER_FREQ, + .bSamFreq[1] = USBD_SPEAKER_FREQ >> 8U, + .bSamFreq[2] = USBD_SPEAKER_FREQ >> 16U + }, + + .speak_std_endpoint = + { + .header = + { + .bLength = sizeof(usb_desc_std_ep), + .bDescriptorType = USB_DESCTYPE_EP + }, + .bEndpointAddress = AUDIO_OUT_EP, + .bmAttributes = USB_ENDPOINT_TYPE_ISOCHRONOUS, + .wMaxPacketSize = SPEAKER_OUT_PACKET, + .bInterval = 0x01U, + .bRefresh = 0x00U, + .bSynchAddress = 0x00U + }, + + .speak_as_endpoint = + { + .header = + { + .bLength = sizeof(usb_desc_AS_ep), + .bDescriptorType = AUDIO_DESCTYPE_ENDPOINT + }, + .bDescriptorSubtype = AUDIO_ENDPOINT_GENERAL, + .bmAttributes = 0x00U, + .bLockDelayUnits = 0x00U, + .wLockDelay = 0x0000U, + } +#endif +}; + +/* USB language ID descriptor */ +static const usb_desc_LANGID usbd_language_id_desc = +{ + .header = + { + .bLength = sizeof(usb_desc_LANGID), + .bDescriptorType = USB_DESCTYPE_STR + }, + + .wLANGID = ENG_LANGID +}; + +/* USB manufacture string */ +static const usb_desc_str manufacturer_string = +{ + .header = + { + .bLength = USB_STRING_LEN(10), + .bDescriptorType = USB_DESCTYPE_STR, + }, + .unicode_string = {'G', 'i', 'g', 'a', 'D', 'e', 'v', 'i', 'c', 'e'} +}; + +/* USB product string */ +static const usb_desc_str product_string = +{ + .header = + { + .bLength = USB_STRING_LEN(14), + .bDescriptorType = USB_DESCTYPE_STR, + }, + .unicode_string = {'G', 'D', '3', '2', '-', 'U', 'S', 'B', '_', 'A', 'u', 'd', 'i', 'o'} +}; + +/* USBD serial string */ +static usb_desc_str serial_string = +{ + .header = + { + .bLength = USB_STRING_LEN(12), + .bDescriptorType = USB_DESCTYPE_STR, + } +}; + +/* USB string descriptor */ +void *const usbd_audio_strings[] = +{ + [STR_IDX_LANGID] = (uint8_t *)&usbd_language_id_desc, + [STR_IDX_MFC] = (uint8_t *)&manufacturer_string, + [STR_IDX_PRODUCT] = (uint8_t *)&product_string, + [STR_IDX_SERIAL] = (uint8_t *)&serial_string +}; + +usb_desc audio_desc = { + .dev_desc = (uint8_t *)&audio_dev_desc, + .config_desc = (uint8_t *)&audio_config_set, + .strings = usbd_audio_strings +}; + +/*! + \brief initialize the AUDIO device + \param[in] udev: pointer to USB device instance + \param[in] config_index: configuration index + \param[out] none + \retval USB device operation status +*/ +static uint8_t audio_init (usb_dev *udev, uint8_t config_index) +{ + static usbd_audio_handler audio_handler; + + memset((void *)&audio_handler, 0, sizeof(usbd_audio_handler)); + +#ifdef USE_USB_AUDIO_MICPHONE +{ + usb_desc_std_ep std_ep = audio_config_set.mic_std_endpoint; + + usb_desc_ep ep = { + .header = std_ep.header, + .bEndpointAddress = std_ep.bEndpointAddress, + .bmAttributes = std_ep.bmAttributes, + .wMaxPacketSize = std_ep.wMaxPacketSize, + .bInterval = std_ep.bInterval + }; + + /* initialize TX endpoint */ + usbd_ep_setup (udev, &ep); +} +#endif + +#ifdef USE_USB_AUDIO_SPEAKER +{ + audio_handler.isoc_out_rdptr = audio_handler.isoc_out_buff; + audio_handler.isoc_out_wrptr = audio_handler.isoc_out_buff; + + usb_desc_std_ep std_ep = audio_config_set.speak_std_endpoint; + + usb_desc_ep ep = { + .header = std_ep.header, + .bEndpointAddress = std_ep.bEndpointAddress, + .bmAttributes = std_ep.bmAttributes, + .wMaxPacketSize = std_ep.wMaxPacketSize, + .bInterval = std_ep.bInterval + }; + + /* initialize RX endpoint */ + usbd_ep_setup (udev, &ep); + + /* initialize the audio output hardware layer */ + if (USBD_OK != audio_out_fops.audio_init(USBD_AUDIO_FREQ_16K, DEFAULT_VOLUME, 0U)) { + return USBD_FAIL; + } + + /* prepare OUT endpoint to receive audio data */ + usbd_ep_recev (udev, AUDIO_OUT_EP, (uint8_t*)audio_handler.isoc_out_buff, SPEAKER_OUT_PACKET); +} +#endif + + udev->dev.class_data[USBD_AUDIO_INTERFACE] = (void *)&audio_handler; + + return USBD_OK; +} + +/*! + \brief deinitialize the AUDIO device + \param[in] udev: pointer to USB device instance + \param[in] config_index: configuration index + \param[out] none + \retval USB device operation status +*/ +static uint8_t audio_deinit (usb_dev *udev, uint8_t config_index) +{ +#ifdef USE_USB_AUDIO_MICPHONE + /* deinitialize AUDIO endpoints */ + usbd_ep_clear(udev, AUDIO_IN_EP); +#endif + +#ifdef USE_USB_AUDIO_SPEAKER + /* deinitialize AUDIO endpoints */ + usbd_ep_clear(udev, AUDIO_OUT_EP); + + /* deinitialize the audio output hardware layer */ + if (USBD_OK != audio_out_fops.audio_deinit(0U)) { + return USBD_FAIL; + } +#endif + + return USBD_OK; +} + +/*! + \brief handle the AUDIO class-specific requests + \param[in] udev: pointer to USB device instance + \param[in] req: device class-specific request + \param[out] none + \retval USB device operation status +*/ +static uint8_t audio_req_handler (usb_dev *udev, usb_req *req) +{ + uint8_t status = REQ_NOTSUPP; + + usbd_audio_handler *audio = (usbd_audio_handler *)udev->dev.class_data[USBD_AUDIO_INTERFACE]; + + usb_transc *transc_in = &udev->dev.transc_in[0]; + usb_transc *transc_out = &udev->dev.transc_out[0]; + + switch (req->bRequest) { + case AUDIO_REQ_GET_CUR: + transc_in->xfer_buf = audio->audioctl; + transc_in->remain_len = req->wLength; + + status = REQ_SUPP; + break; + + case AUDIO_REQ_SET_CUR: + if (req->wLength) { + transc_out->xfer_buf = audio->audioctl; + transc_out->remain_len = req->wLength; + + udev->dev.class_core->command = AUDIO_REQ_SET_CUR; + + audio->audioctl_len = req->wLength; + audio->audioctl_unit = BYTE_HIGH(req->wIndex); + + status = REQ_SUPP; + } + break; + + case AUDIO_REQ_GET_MIN: + *((uint16_t *)audio->audioctl) = VOL_MIN; + transc_in->xfer_buf = audio->audioctl; + transc_in->remain_len = req->wLength; + status = REQ_SUPP; + break; + + case AUDIO_REQ_GET_MAX: + *((uint16_t *)audio->audioctl) = VOL_MAX; + transc_in->xfer_buf = audio->audioctl; + transc_in->remain_len = req->wLength; + status = REQ_SUPP; + break; + + case AUDIO_REQ_GET_RES: + *((uint16_t *)audio->audioctl) = VOL_RES; + transc_in->xfer_buf = audio->audioctl; + transc_in->remain_len = req->wLength; + status = REQ_SUPP; + break; + + default: + break; + } + + return status; +} + +/*! + \brief handle the AUDIO set interface requests + \param[in] udev: pointer to USB device instance + \param[in] req: device class-specific request + \param[out] none + \retval USB device operation status +*/ +static uint8_t audio_set_intf(usb_dev *udev, usb_req *req) +{ + udev->dev.class_core->alter_set = req->wValue; + + return USBD_OK; +} + + +/*! + \brief handles the control transfer OUT callback + \param[in] udev: pointer to USB device instance + \param[out] none + \retval USB device operation status +*/ +static uint8_t audio_ctlx_out (usb_dev *udev) +{ +#ifdef USE_USB_AUDIO_SPEAKER + usbd_audio_handler *audio = (usbd_audio_handler *)udev->dev.class_data[USBD_AUDIO_INTERFACE]; + + /* handles audio control requests data */ + /* check if an audio_control request has been issued */ + if (AUDIO_REQ_SET_CUR == udev->dev.class_core->command) { + /* in this driver, to simplify code, only SET_CUR request is managed */ + + /* check for which addressed unit the audio_control request has been issued */ + if (AUDIO_OUT_STREAMING_CTRL == audio->audioctl_unit) { + /* in this driver, to simplify code, only one unit is manage */ + + /* call the audio interface mute function */ + audio_out_fops.audio_mute_ctl(audio->audioctl[0]); + + /* reset the audioctl_cmd variable to prevent re-entering this function */ + udev->dev.class_core->command = 0U; + + audio->audioctl_len = 0U; + } + } +#endif + + return USBD_OK; +} + +/*! + \brief handles the audio IN data stage + \param[in] udev: pointer to USB device instance + \param[in] ep_num: endpoint number + \param[out] none + \retval USB device operation status +*/ +static uint8_t audio_data_in (usb_dev *udev, uint8_t ep_num) +{ +#ifdef USE_USB_AUDIO_MICPHONE + if(count_data < LENGTH_DATA){ + /* Prepare next buffer to be sent: dummy data */ + usbd_ep_send(udev, AUDIO_IN_EP,(uint8_t*)&wavetestdata[count_data],MIC_IN_PACKET); + count_data += MIC_IN_PACKET; + } else { + usbd_ep_send(udev, AUDIO_IN_EP,(uint8_t*)wavetestdata,MIC_IN_PACKET); + count_data = MIC_IN_PACKET; + } +#endif + + return USBD_OK; +} + +/*! + \brief handles the audio OUT data stage + \param[in] udev: pointer to USB device instance + \param[in] ep_num: endpoint number + \param[out] none + \retval USB device operation status +*/ +static uint8_t audio_data_out (usb_dev *udev, uint8_t ep_num) +{ +#ifdef USE_USB_AUDIO_SPEAKER + usbd_audio_handler *audio = (usbd_audio_handler *)udev->dev.class_data[USBD_AUDIO_INTERFACE]; + + /* increment the Buffer pointer or roll it back when all buffers are full */ + if (audio->isoc_out_wrptr >= (audio->isoc_out_buff + (SPEAKER_OUT_PACKET * OUT_PACKET_NUM))) { + /* all buffers are full: roll back */ + audio->isoc_out_wrptr = audio->isoc_out_buff; + } else { + /* increment the buffer pointer */ + audio->isoc_out_wrptr += SPEAKER_OUT_PACKET; + } + + /* Toggle the frame index */ + udev->dev.transc_out[ep_num].frame_num = + (udev->dev.transc_out[ep_num].frame_num)? 0U:1U; + + /* prepare out endpoint to receive next audio packet */ + usbd_ep_recev (udev, AUDIO_OUT_EP, (uint8_t*)(audio->isoc_out_wrptr), SPEAKER_OUT_PACKET); + + /* trigger the start of streaming only when half buffer is full */ + if ((0U == audio->play_flag) && (audio->isoc_out_wrptr >= (audio->isoc_out_buff + ((SPEAKER_OUT_PACKET * OUT_PACKET_NUM) / 2U)))) { + /* enable start of streaming */ + audio->play_flag = 1U; + } +#endif + + return USBD_OK; +} + +/*! + \brief handles the SOF event (data buffer update and synchronization) + \param[in] udev: pointer to USB device instance + \param[out] none + \retval USB device operation status +*/ +static uint8_t usbd_audio_sof (usb_dev *udev) +{ +#ifdef USE_USB_AUDIO_SPEAKER + usbd_audio_handler *audio = (usbd_audio_handler *)udev->dev.class_data[USBD_AUDIO_INTERFACE]; + + /* check if there are available data in stream buffer. + in this function, a single variable (play_flag) is used to avoid software delays. + the play operation must be executed as soon as possible after the SOF detection. */ + if (audio->play_flag) { + /* start playing received packet */ + audio_out_fops.audio_cmd((uint8_t*)(audio->isoc_out_rdptr), /* samples buffer pointer */ + SPEAKER_OUT_PACKET, /* number of samples in Bytes */ + AUDIO_CMD_PLAY); /* command to be processed */ + + /* increment the Buffer pointer or roll it back when all buffers all full */ + if (audio->isoc_out_rdptr >= (audio->isoc_out_buff + (SPEAKER_OUT_PACKET * OUT_PACKET_NUM))) { + /* roll back to the start of buffer */ + audio->isoc_out_rdptr = audio->isoc_out_buff; + } else { + /* increment to the next sub-buffer */ + audio->isoc_out_rdptr += SPEAKER_OUT_PACKET; + } + + /* if all available buffers have been consumed, stop playing */ + if (audio->isoc_out_rdptr == audio->isoc_out_wrptr) { + /* Pause the audio stream */ + audio_out_fops.audio_cmd((uint8_t*)(audio->isoc_out_buff), /* samples buffer pointer */ + SPEAKER_OUT_PACKET, /* number of samples in Bytes */ + AUDIO_CMD_PAUSE); /* command to be processed */ + + /* stop entering play loop */ + audio->play_flag = 0U; + + /* reset buffer pointers */ + audio->isoc_out_rdptr = audio->isoc_out_buff; + audio->isoc_out_wrptr = audio->isoc_out_buff; + } + } +#endif + + return USBD_OK; +} diff --git a/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/device/class/audio/Source/audio_out_itf.c b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/device/class/audio/Source/audio_out_itf.c new file mode 100644 index 0000000000..fc3c3040e6 --- /dev/null +++ b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/device/class/audio/Source/audio_out_itf.c @@ -0,0 +1,228 @@ +/*! + \file audio_out_itf.c + \brief audio OUT (playback) interface functions + + \version 2020-07-17, V3.0.0, firmware for GD32F10x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "audio_core.h" +#include "audio_out_itf.h" + +static uint8_t init (uint32_t audiofreq, uint32_t volume, uint32_t options); +static uint8_t deinit (uint32_t options); +static uint8_t audio_cmd (uint8_t* pbuf, uint32_t size, uint8_t cmd); +static uint8_t volume_ctl (uint8_t vol); +static uint8_t mute_ctl (uint8_t cmd); +static uint8_t periodic_tc (uint8_t cmd); +static uint8_t get_state (void); + +audio_fops_struct audio_out_fops = +{ + init, + deinit, + audio_cmd, + volume_ctl, + mute_ctl, + periodic_tc, + get_state +}; + +static uint8_t audio_state = AUDIO_STATE_INACTIVE; + +/*! + \brief initialize and configures all required resources for audio play function + \param[in] audio_freq: statrt_up audio frequency + \param[in] volume: start_up volume to be set + \param[in] options: specific options passed to low layer function + \param[out] none + \retval AUDIO_OK if all operations succeed, AUDIO_FAIL else +*/ +static uint8_t init (uint32_t audio_freq, uint32_t volume, uint32_t options) +{ + static uint32_t initialized = 0U; + + /* check if the low layer has already been initialized */ + if (0U == initialized) { + /* call low layer function */ + if (0U != eval_audio_init(OUTPUT_DEVICE_AUTO, (uint8_t)volume, audio_freq)) { + audio_state = AUDIO_STATE_ERROR; + + return AUDIO_FAIL; + } + + /* set the initialization flag to prevent reinitializing the interface again */ + initialized = 1U; + } + + /* update the audio state machine */ + audio_state = AUDIO_STATE_ACTIVE; + + return AUDIO_OK; +} + +/*! + \brief free all resources used by low layer and stops audio-play function + \param[in] options: specific options passed to low layer function + \param[out] none + \retval AUDIO_OK if all operations succeed, AUDIO_FAIL else +*/ +static uint8_t deinit (uint32_t options) +{ + /* update the audio state machine */ + audio_state = AUDIO_STATE_INACTIVE; + + return AUDIO_OK; +} + +/*! + \brief play, stop, pause or resume current file + \param[in] pbuf: address from which file should be played + \param[in] size: size of the current buffer/file + \param[in] cmd: command to be executed, can be: + \arg AUDIO_CMD_PLAY + \arg AUDIO_CMD_PAUSE + \arg AUDIO_CMD_RESUME + \arg AUDIO_CMD_STOP + \param[out] none + \retval AUDIO_OK if all operations succeed, AUDIO_FAIL else +*/ +static uint8_t audio_cmd (uint8_t* pbuf, uint32_t size, uint8_t cmd) +{ + /* check the current state */ + if ((AUDIO_STATE_INACTIVE == audio_state) || (AUDIO_STATE_ERROR == audio_state)) { + audio_state = AUDIO_STATE_ERROR; + + return AUDIO_FAIL; + } + + switch (cmd) { + /* process the play command */ + case AUDIO_CMD_PLAY: + /* if current state is active or stopped */ + if ((AUDIO_STATE_ACTIVE == audio_state) || \ + (AUDIO_STATE_STOPPED == audio_state) || \ + (AUDIO_STATE_PLAYING == audio_state)) { + audio_mal_play((uint32_t)pbuf, size); + audio_state = AUDIO_STATE_PLAYING; + + return AUDIO_OK; + } else if (AUDIO_STATE_PAUSED == audio_state) { + if (eval_audio_pause_resume(AUDIO_RESUME, (uint32_t)pbuf, (size / 2U))) { + audio_state = AUDIO_STATE_ERROR; + + return AUDIO_FAIL; + } else { + audio_state = AUDIO_STATE_PLAYING; + + return AUDIO_OK; + } + } else { + return AUDIO_FAIL; + } + + /* process the stop command */ + case AUDIO_CMD_STOP: + if (AUDIO_STATE_PLAYING != audio_state) { + /* unsupported command */ + return AUDIO_FAIL; + } else if (eval_audio_stop(CODEC_PDWN_SW)) { + audio_state = AUDIO_STATE_ERROR; + + return AUDIO_FAIL; + } else { + audio_state = AUDIO_STATE_STOPPED; + + return AUDIO_OK; + } + + /* process the pause command */ + case AUDIO_CMD_PAUSE: + if (AUDIO_STATE_PLAYING != audio_state) { + /* unsupported command */ + return AUDIO_FAIL; + } else if (eval_audio_pause_resume(AUDIO_PAUSE, (uint32_t)pbuf, (size / 2U))) { + audio_state = AUDIO_STATE_ERROR; + + return AUDIO_FAIL; + } else { + audio_state = AUDIO_STATE_PAUSED; + + return AUDIO_OK; + } + + /* unsupported command */ + default: + return AUDIO_FAIL; + } +} + +/*! + \brief set the volume level + \param[in] vol: volume level to be set in % (from 0% to 100%) + \param[out] none + \retval AUDIO_OK if all operations succeed, AUDIO_FAIL else +*/ +static uint8_t volume_ctl (uint8_t vol) +{ + return AUDIO_OK; +} + +/*! + \brief mute or unmute the audio current output + \param[in] cmd: can be 0 to unmute, or 1 to mute + \param[out] none + \retval AUDIO_OK if all operations succeed, AUDIO_FAIL else +*/ +static uint8_t mute_ctl (uint8_t cmd) +{ + return AUDIO_OK; +} + +/*! + \brief periodic transfer control + \param[in] cmd: command + \param[out] none + \retval AUDIO_OK if all operations succeed, AUDIO_FAIL else +*/ +static uint8_t periodic_tc (uint8_t cmd) +{ + return AUDIO_OK; +} + +/*! + \brief return the current state of the audio machine + \param[in] none + \param[out] none + \retval AUDIO_OK if all operations succeed, AUDIO_FAIL else +*/ +static uint8_t get_state (void) +{ + return audio_state; +} diff --git a/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/device/class/cdc/Include/cdc_acm_core.h b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/device/class/cdc/Include/cdc_acm_core.h new file mode 100644 index 0000000000..df6d33e60e --- /dev/null +++ b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/device/class/cdc/Include/cdc_acm_core.h @@ -0,0 +1,66 @@ +/*! + \file cdc_acm_core.h + \brief the header file of cdc acm driver + + \version 2020-07-17, V3.0.0, firmware for GD32F10x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef __CDC_ACM_CORE_H +#define __CDC_ACM_CORE_H + +#include "usbd_enum.h" +#include "usb_cdc.h" + +#define USB_CDC_RX_LEN 64 + +typedef struct { + uint8_t packet_sent; + uint8_t packet_receive; + + uint8_t data[USB_CDC_RX_LEN]; + uint8_t cmd[USB_CDC_CMD_PACKET_SIZE]; + + uint32_t receive_length; + + acm_line line_coding; +} usb_cdc_handler; + +extern usb_desc cdc_desc; +extern usb_class_core cdc_class; + +/* function declarations */ +/* check CDC ACM is ready for data transfer */ +uint8_t cdc_acm_check_ready(usb_dev *udev); +/* send CDC ACM data */ +void cdc_acm_data_send(usb_dev *udev); +/* receive CDC ACM data */ +void cdc_acm_data_receive(usb_dev *udev); + +#endif /* __CDC_ACM_CORE_H */ diff --git a/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/device/class/cdc/Source/cdc_acm_core.c b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/device/class/cdc/Source/cdc_acm_core.c new file mode 100644 index 0000000000..9a110a8333 --- /dev/null +++ b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/device/class/cdc/Source/cdc_acm_core.c @@ -0,0 +1,524 @@ +/*! + \file cdc_acm_core.c + \brief CDC ACM driver + + \version 2020-07-17, V3.0.0, firmware for GD32F10x + \version 2020-12-07, V3.0.1, firmware for GD32F10x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "cdc_acm_core.h" + +#define USBD_VID 0x28E9U +#define USBD_PID 0x018AU + +/* note:it should use the C99 standard when compiling the below codes */ +/* USB standard device descriptor */ +const usb_desc_dev cdc_dev_desc = +{ + .header = + { + .bLength = USB_DEV_DESC_LEN, + .bDescriptorType = USB_DESCTYPE_DEV, + }, + .bcdUSB = 0x0200U, + .bDeviceClass = USB_CLASS_CDC, + .bDeviceSubClass = 0x00U, + .bDeviceProtocol = 0x00U, + .bMaxPacketSize0 = USB_FS_EP0_MAX_LEN, + .idVendor = USBD_VID, + .idProduct = USBD_PID, + .bcdDevice = 0x0100U, + .iManufacturer = STR_IDX_MFC, + .iProduct = STR_IDX_PRODUCT, + .iSerialNumber = STR_IDX_SERIAL, + .bNumberConfigurations = USBD_CFG_MAX_NUM, +}; + +/* USB device configuration descriptor */ +const usb_cdc_desc_config_set cdc_config_desc = +{ + .config = + { + .header = + { + .bLength = sizeof(usb_desc_config), + .bDescriptorType = USB_DESCTYPE_CONFIG, + }, + .wTotalLength = USB_CDC_ACM_CONFIG_DESC_SIZE, + .bNumInterfaces = 0x02U, + .bConfigurationValue = 0x01U, + .iConfiguration = 0x00U, + .bmAttributes = 0x80U, + .bMaxPower = 0x32U + }, + + .cmd_itf = + { + .header = + { + .bLength = sizeof(usb_desc_itf), + .bDescriptorType = USB_DESCTYPE_ITF + }, + .bInterfaceNumber = 0x00U, + .bAlternateSetting = 0x00U, + .bNumEndpoints = 0x01U, + .bInterfaceClass = USB_CLASS_CDC, + .bInterfaceSubClass = USB_CDC_SUBCLASS_ACM, + .bInterfaceProtocol = USB_CDC_PROTOCOL_AT, + .iInterface = 0x00U + }, + + .cdc_header = + { + .header = + { + .bLength = sizeof(usb_desc_header_func), + .bDescriptorType = USB_DESCTYPE_CS_INTERFACE + }, + .bDescriptorSubtype = 0x00U, + .bcdCDC = 0x0110U + }, + + .cdc_call_managment = + { + .header = + { + .bLength = sizeof(usb_desc_call_managment_func), + .bDescriptorType = USB_DESCTYPE_CS_INTERFACE + }, + .bDescriptorSubtype = 0x01U, + .bmCapabilities = 0x00U, + .bDataInterface = 0x01U + }, + + .cdc_acm = + { + .header = + { + .bLength = sizeof(usb_desc_acm_func), + .bDescriptorType = USB_DESCTYPE_CS_INTERFACE + }, + .bDescriptorSubtype = 0x02U, + .bmCapabilities = 0x02U, + }, + + .cdc_union = + { + .header = + { + .bLength = sizeof(usb_desc_union_func), + .bDescriptorType = USB_DESCTYPE_CS_INTERFACE + }, + .bDescriptorSubtype = 0x06U, + .bMasterInterface = 0x00U, + .bSlaveInterface0 = 0x01U, + }, + + .cdc_cmd_endpoint = + { + .header = + { + .bLength = sizeof(usb_desc_ep), + .bDescriptorType = USB_DESCTYPE_EP, + }, + .bEndpointAddress = CDC_CMD_EP, + .bmAttributes = USB_EP_ATTR_INT, + .wMaxPacketSize = USB_CDC_CMD_PACKET_SIZE, + .bInterval = 0x0AU + }, + + .cdc_data_interface = + { + .header = + { + .bLength = sizeof(usb_desc_itf), + .bDescriptorType = USB_DESCTYPE_ITF, + }, + .bInterfaceNumber = 0x01U, + .bAlternateSetting = 0x00U, + .bNumEndpoints = 0x02U, + .bInterfaceClass = USB_CLASS_DATA, + .bInterfaceSubClass = 0x00U, + .bInterfaceProtocol = USB_CDC_PROTOCOL_NONE, + .iInterface = 0x00U + }, + + .cdc_out_endpoint = + { + .header = + { + .bLength = sizeof(usb_desc_ep), + .bDescriptorType = USB_DESCTYPE_EP, + }, + .bEndpointAddress = CDC_DATA_OUT_EP, + .bmAttributes = USB_EP_ATTR_BULK, + .wMaxPacketSize = USB_CDC_DATA_PACKET_SIZE, + .bInterval = 0x00U + }, + + .cdc_in_endpoint = + { + .header = + { + .bLength = sizeof(usb_desc_ep), + .bDescriptorType = USB_DESCTYPE_EP + }, + .bEndpointAddress = CDC_DATA_IN_EP, + .bmAttributes = USB_EP_ATTR_BULK, + .wMaxPacketSize = USB_CDC_DATA_PACKET_SIZE, + .bInterval = 0x00U + } +}; + +/* USB language ID Descriptor */ +static const usb_desc_LANGID usbd_language_id_desc = +{ + .header = + { + .bLength = sizeof(usb_desc_LANGID), + .bDescriptorType = USB_DESCTYPE_STR, + }, + .wLANGID = ENG_LANGID +}; + +/* USB manufacture string */ +static const usb_desc_str manufacturer_string = +{ + .header = + { + .bLength = USB_STRING_LEN(10), + .bDescriptorType = USB_DESCTYPE_STR, + }, + .unicode_string = {'G', 'i', 'g', 'a', 'D', 'e', 'v', 'i', 'c', 'e'} +}; + +/* USB product string */ +static const usb_desc_str product_string = +{ + .header = + { + .bLength = USB_STRING_LEN(12), + .bDescriptorType = USB_DESCTYPE_STR, + }, + .unicode_string = {'G', 'D', '3', '2', '-', 'C', 'D', 'C', '_', 'A', 'C', 'M'} +}; + +/* USBD serial string */ +static usb_desc_str serial_string = +{ + .header = + { + .bLength = USB_STRING_LEN(12), + .bDescriptorType = USB_DESCTYPE_STR, + } +}; + +/* USB string descriptor set */ +void *const usbd_cdc_strings[] = +{ + [STR_IDX_LANGID] = (uint8_t *)&usbd_language_id_desc, + [STR_IDX_MFC] = (uint8_t *)&manufacturer_string, + [STR_IDX_PRODUCT] = (uint8_t *)&product_string, + [STR_IDX_SERIAL] = (uint8_t *)&serial_string +}; + +usb_desc cdc_desc = +{ + .dev_desc = (uint8_t *)&cdc_dev_desc, + .config_desc = (uint8_t *)&cdc_config_desc, + .strings = usbd_cdc_strings +}; + +/* local function prototypes ('static') */ +static uint8_t cdc_acm_init (usb_dev *udev, uint8_t config_index); +static uint8_t cdc_acm_deinit (usb_dev *udev, uint8_t config_index); +static uint8_t cdc_acm_req (usb_dev *udev, usb_req *req); +static uint8_t cdc_ctlx_out (usb_dev *udev); +static uint8_t cdc_acm_in (usb_dev *udev, uint8_t ep_num); +static uint8_t cdc_acm_out (usb_dev *udev, uint8_t ep_num); + +/* USB CDC device class callbacks structure */ +usb_class_core cdc_class = +{ + .command = NO_CMD, + .alter_set = 0U, + + .init = cdc_acm_init, + .deinit = cdc_acm_deinit, + .req_proc = cdc_acm_req, + .ctlx_out = cdc_ctlx_out, + .data_in = cdc_acm_in, + .data_out = cdc_acm_out +}; + +/*! + \brief check CDC ACM is ready for data transfer + \param[in] udev: pointer to USB device instance + \param[out] none + \retval 0 if CDC is ready, 5 else +*/ +uint8_t cdc_acm_check_ready(usb_dev *udev) +{ + if (udev->dev.class_data[CDC_COM_INTERFACE] != NULL) { + usb_cdc_handler *cdc = (usb_cdc_handler *)udev->dev.class_data[CDC_COM_INTERFACE]; + + if ((1U == cdc->packet_receive) && (1U == cdc->packet_sent)) { + return 0U; + } + } + + return 1U; +} + +/*! + \brief send CDC ACM data + \param[in] udev: pointer to USB device instance + \param[out] none + \retval USB device operation status +*/ +void cdc_acm_data_send (usb_dev *udev) +{ + usb_cdc_handler *cdc = (usb_cdc_handler *)udev->dev.class_data[CDC_COM_INTERFACE]; + + if (0U != cdc->receive_length) { + cdc->packet_sent = 0U; + + usbd_ep_send (udev, CDC_DATA_IN_EP, (uint8_t*)(cdc->data), cdc->receive_length); + + cdc->receive_length = 0U; + } +} + +/*! + \brief receive CDC ACM data + \param[in] udev: pointer to USB device instance + \param[out] none + \retval USB device operation status +*/ +void cdc_acm_data_receive (usb_dev *udev) +{ + usb_cdc_handler *cdc = (usb_cdc_handler *)udev->dev.class_data[CDC_COM_INTERFACE]; + + cdc->packet_receive = 0U; + cdc->packet_sent = 0U; + + usbd_ep_recev(udev, CDC_DATA_OUT_EP, (uint8_t*)(cdc->data), USB_CDC_DATA_PACKET_SIZE); +} + +/*! + \brief initialize the CDC ACM device + \param[in] udev: pointer to USB device instance + \param[in] config_index: configuration index + \param[out] none + \retval USB device operation status +*/ +static uint8_t cdc_acm_init (usb_dev *udev, uint8_t config_index) +{ + static usb_cdc_handler cdc_handler; + + /* initialize the data TX endpoint */ + usbd_ep_setup (udev, &(cdc_config_desc.cdc_in_endpoint)); + + /* initialize the data RX endpoint */ + usbd_ep_setup (udev, &(cdc_config_desc.cdc_out_endpoint)); + + /* initialize the command TX endpoint */ + usbd_ep_setup (udev, &(cdc_config_desc.cdc_cmd_endpoint)); + + /* initialize CDC handler structure */ + cdc_handler.packet_receive = 1U; + cdc_handler.packet_sent = 1U; + cdc_handler.receive_length = 0U; + + cdc_handler.line_coding = (acm_line){ + .dwDTERate = 115200, + .bCharFormat = 0, + .bParityType = 0, + .bDataBits = 0x08 + }; + + udev->dev.class_data[CDC_COM_INTERFACE] = (void *)&cdc_handler; + + return USBD_OK; +} + +/*! + \brief deinitialize the CDC ACM device + \param[in] udev: pointer to USB device instance + \param[in] config_index: configuration index + \param[out] none + \retval USB device operation status +*/ +static uint8_t cdc_acm_deinit (usb_dev *udev, uint8_t config_index) +{ + /* deinitialize the data TX/RX endpoint */ + usbd_ep_clear (udev, CDC_DATA_IN_EP); + usbd_ep_clear (udev, CDC_DATA_OUT_EP); + + /* deinitialize the command TX endpoint */ + usbd_ep_clear (udev, CDC_CMD_EP); + + return USBD_OK; +} + +/*! + \brief handle the CDC ACM class-specific requests + \param[in] udev: pointer to USB device instance + \param[in] req: device class-specific request + \param[out] none + \retval USB device operation status +*/ +static uint8_t cdc_acm_req (usb_dev *udev, usb_req *req) +{ + usb_cdc_handler *cdc = (usb_cdc_handler *)udev->dev.class_data[CDC_COM_INTERFACE]; + + usb_transc *transc = NULL; + + switch (req->bRequest) { + case SEND_ENCAPSULATED_COMMAND: + /* no operation for this driver */ + break; + + case GET_ENCAPSULATED_RESPONSE: + /* no operation for this driver */ + break; + + case SET_COMM_FEATURE: + /* no operation for this driver */ + break; + + case GET_COMM_FEATURE: + /* no operation for this driver */ + break; + + case CLEAR_COMM_FEATURE: + /* no operation for this driver */ + break; + + case SET_LINE_CODING: + transc = &udev->dev.transc_out[0]; + + /* set the value of the current command to be processed */ + udev->dev.class_core->alter_set = req->bRequest; + + /* enable EP0 prepare to receive command data packet */ + transc->remain_len = req->wLength; + transc->xfer_buf = cdc->cmd; + break; + + case GET_LINE_CODING: + transc = &udev->dev.transc_in[0]; + + cdc->cmd[0] = (uint8_t)(cdc->line_coding.dwDTERate); + cdc->cmd[1] = (uint8_t)(cdc->line_coding.dwDTERate >> 8); + cdc->cmd[2] = (uint8_t)(cdc->line_coding.dwDTERate >> 16); + cdc->cmd[3] = (uint8_t)(cdc->line_coding.dwDTERate >> 24); + cdc->cmd[4] = cdc->line_coding.bCharFormat; + cdc->cmd[5] = cdc->line_coding.bParityType; + cdc->cmd[6] = cdc->line_coding.bDataBits; + + transc->xfer_buf = cdc->cmd; + transc->remain_len = 7U; + break; + + case SET_CONTROL_LINE_STATE: + /* no operation for this driver */ + break; + + case SEND_BREAK: + /* no operation for this driver */ + break; + + default: + break; + } + + return USBD_OK; +} + +static uint8_t cdc_ctlx_out (usb_dev *udev) +{ + usb_cdc_handler *cdc = (usb_cdc_handler *)udev->dev.class_data[CDC_COM_INTERFACE]; + + if (udev->dev.class_core->alter_set != NO_CMD) { + /* process the command data */ + cdc->line_coding.dwDTERate = (uint32_t)((uint32_t)cdc->cmd[0] | + ((uint32_t)cdc->cmd[1] << 8U) | + ((uint32_t)cdc->cmd[2] << 16U) | + ((uint32_t)cdc->cmd[3] << 24U)); + + cdc->line_coding.bCharFormat = cdc->cmd[4]; + cdc->line_coding.bParityType = cdc->cmd[5]; + cdc->line_coding.bDataBits = cdc->cmd[6]; + + udev->dev.class_core->alter_set = NO_CMD; + } + + return USBD_OK; +} + +/*! + \brief handle CDC ACM data + \param[in] udev: pointer to USB device instance + \param[in] ep_num: endpoint identifier + \param[out] none + \retval USB device operation status +*/ +static uint8_t cdc_acm_in (usb_dev *udev, uint8_t ep_num) +{ + usb_transc *transc = &udev->dev.transc_in[EP_ID(ep_num)]; + + usb_cdc_handler *cdc = (usb_cdc_handler *)udev->dev.class_data[CDC_COM_INTERFACE]; + + if ((0U == transc->xfer_len % transc->max_len) && (0U != transc->xfer_len)) { + usbd_ep_send (udev, ep_num, NULL, 0U); + } else { + cdc->packet_sent = 1U; + } + + return USBD_OK; +} + +/*! + \brief handle CDC ACM data + \param[in] udev: pointer to USB device instance + \param[in] ep_num: endpoint identifier + \param[out] none + \retval USB device operation status +*/ +static uint8_t cdc_acm_out (usb_dev *udev, uint8_t ep_num) +{ + usb_cdc_handler *cdc = (usb_cdc_handler *)udev->dev.class_data[CDC_COM_INTERFACE]; + + cdc->packet_receive = 1U; + cdc->receive_length = ((usb_core_driver *)udev)->dev.transc_out[ep_num].xfer_count; + + return USBD_OK; +} diff --git a/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/device/class/dfu/Include/dfu_core.h b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/device/class/dfu/Include/dfu_core.h new file mode 100644 index 0000000000..20af740979 --- /dev/null +++ b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/device/class/dfu/Include/dfu_core.h @@ -0,0 +1,176 @@ +/*! + \file dfu_core.h + \brief the header file of USB DFU device class core functions + + \version 2020-07-17, V3.0.0, firmware for GD32F10x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef __DFU_CORE_H +#define __DFU_CORE_H + +#include "usbd_enum.h" + +/* DFU class code */ +#define USB_DFU_CLASS 0xFEU + +/* DFU subclass code */ +#define USB_DFU_SUBCLASS_UPGRADE 0x01U + +/* DFU protocol code */ +#define USB_DFU_PROTOCL_RUNTIME 0x01U +#define USB_DFU_PROTOCL_DFU 0x02U + +/* manifestation state */ +#define MANIFEST_COMPLETE 0x00U +#define MANIFEST_IN_PROGRESS 0x01U + +/* DFU attributes code */ +#define USB_DFU_CAN_DOWNLOAD 0x01U +#define USB_DFU_CAN_UPLOAD 0x02U +#define USB_DFU_MANIFEST_TOLERANT 0x04U +#define USB_DFU_WILL_DETACH 0x08U + +/* special commands with download request */ +#define GET_COMMANDS 0x00U +#define SET_ADDRESS_POINTER 0x21U +#define ERASE 0x41U + +/* memory operation command */ +#define CMD_ERASE 0U +#define CMD_WRITE 1U + +#define _BYTE1(x) (uint8_t)((x) & 0xFFU) /*!< addressing cycle 1st byte */ +#define _BYTE2(x) (uint8_t)(((x) & 0xFF00U) >> 8U) /*!< addressing cycle 2nd byte */ +#define _BYTE3(x) (uint8_t)(((x) & 0xFF0000U) >> 16U) /*!< addressing cycle 3rd byte */ + +#define FLASH_ERASE_TIMEOUT 60U +#define FLASH_WRITE_TIMEOUT 80U + +/* bit detach capable = bit 3 in bmAttributes field */ +#define DFU_DETACH_MASK (uint8_t)(0x10U) + +#define USB_SERIAL_STR_LEN 0x06U + +#define USB_DFU_CONFIG_DESC_SIZE 27U + +#define DFU_DESC_TYPE 0x21U + +/* DFU device state defines */ +typedef enum { + STATE_APP_IDLE = 0x00U, + 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 +} dfu_state; + +/* DFU device status defines */ +typedef enum { + STATUS_OK = 0x00U, + STATUS_ERR_TARGET, + STATUS_ERR_FILE, + STATUS_ERR_WRITE, + STATUS_ERR_ERASE, + STATUS_ERR_CHECK_ERASED, + STATUS_ERR_PROG, + STATUS_ERR_VERIFY, + STATUS_ERR_ADDRESS, + STATUS_ERR_NOTDONE, + STATUS_ERR_FIRMWARE, + STATUS_ERR_VENDOR, + STATUS_ERR_USBR, + STATUS_ERR_POR, + STATUS_ERR_UNKNOWN, + STATUS_ERR_STALLEDPKT +} dfu_status; + +/* DFU class-specific requests */ +typedef enum { + DFU_DETACH = 0U, + DFU_DNLOAD, + DFU_UPLOAD, + DFU_GETSTATUS, + DFU_CLRSTATUS, + DFU_GETSTATE, + DFU_ABORT, + DFU_REQ_MAX +} dfu_requests; + +#pragma pack(1) + +/* USB DFU function descriptor structure */ +typedef struct +{ + usb_desc_header header; /*!< descriptor header, including type and size */ + uint8_t bmAttributes; /*!< DFU attributes */ + uint16_t wDetachTimeOut; /*!< time, in milliseconds, that the device will wait after receipt of the DFU_DETACH request. If */ + uint16_t wTransferSize; /*!< maximum number of bytes that the device can accept per control-write transaction */ + uint16_t bcdDFUVersion; /*!< numeric expression identifying the version of the DFU Specification release. */ +} usb_desc_dfu_func; + +#pragma pack() + +/* USB configuration descriptor structure */ +typedef struct +{ + usb_desc_config config; + usb_desc_itf dfu_itf; + usb_desc_dfu_func dfu_func; +} usb_dfu_desc_config_set; + +typedef struct +{ + uint8_t bStatus; + uint8_t bwPollTimeout0; + uint8_t bwPollTimeout1; + uint8_t bwPollTimeout2; + uint8_t bState; + uint8_t iString; + + uint8_t manifest_state; + uint32_t data_len; + uint16_t block_num; + uint32_t base_addr; + + uint8_t buf[TRANSFER_SIZE]; +} usbd_dfu_handler; + +typedef void (*app_func) (void); + +extern usb_desc dfu_desc; +extern usb_class_core dfu_class; + +#endif /* DFU_CORE_H */ diff --git a/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/device/class/dfu/Include/dfu_mal.h b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/device/class/dfu/Include/dfu_mal.h new file mode 100644 index 0000000000..5393fca608 --- /dev/null +++ b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/device/class/dfu/Include/dfu_mal.h @@ -0,0 +1,84 @@ +/*! + \file dfu_mal.h + \brief USB DFU device media access layer header file + + \version 2020-07-17, V3.0.0, firmware for GD32F10x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef __DFU_MAL_H +#define __DFU_MAL_H + +#include "usbd_conf.h" + +typedef struct _dfu_mal_prop +{ + const uint8_t* pstr_desc; + + uint8_t (*mal_init) (void); + uint8_t (*mal_deinit) (void); + uint8_t (*mal_erase) (uint32_t addr); + uint8_t (*mal_write) (uint8_t *buf, uint32_t addr, uint32_t len); + uint8_t* (*mal_read) (uint8_t *buf, uint32_t addr, uint32_t len); + uint8_t (*mal_checkaddr) (uint32_t addr); + + const uint32_t erase_timeout; + const uint32_t write_timeout; +} dfu_mal_prop; + +typedef enum +{ + MAL_OK = 0, + MAL_FAIL +} MAL_Status; + +#define _1st_BYTE(x) (uint8_t)((x) & 0xFF) /*!< addressing cycle 1st byte */ +#define _2nd_BYTE(x) (uint8_t)(((x) & 0xFF00) >> 8) /*!< addressing cycle 2nd byte */ +#define _3rd_BYTE(x) (uint8_t)(((x) & 0xFF0000) >> 16) /*!< addressing cycle 3rd byte */ + +#define SET_POLLING_TIMEOUT(x) buffer[0] = _1st_BYTE(x);\ + buffer[1] = _2nd_BYTE(x);\ + buffer[2] = _3rd_BYTE(x); + +/* function declarations */ +/* initialize the memory media on the GD32 */ +uint8_t dfu_mal_init(void); +/* deinitialize the memory media on the GD32 */ +uint8_t dfu_mal_deinit(void); +/* erase a memory sector */ +uint8_t dfu_mal_erase(uint32_t addr); +/* write data to sectors of memory */ +uint8_t dfu_mal_write(uint8_t *buf, uint32_t addr, uint32_t len); +/* read data from sectors of memory */ +uint8_t* dfu_mal_read(uint8_t *buf, uint32_t addr, uint32_t len); +/* get the status of a given memory and store in buffer */ +uint8_t dfu_mal_getstatus(uint32_t addr, uint8_t cmd, uint8_t *buffer); + +#endif /* __DFU_MAL_H */ + diff --git a/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/device/class/dfu/Source/dfu_core.c b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/device/class/dfu/Source/dfu_core.c new file mode 100644 index 0000000000..2767d02845 --- /dev/null +++ b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/device/class/dfu/Source/dfu_core.c @@ -0,0 +1,653 @@ +/*! + \file dfu_core.c + \brief USB DFU device class core functions + + \version 2020-07-17, V3.0.0, firmware for GD32F10x + \version 2020-12-07, V3.0.1, firmware for GD32F10x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "dfu_core.h" +#include "drv_usb_hw.h" +#include "dfu_mal.h" +#include "flash_if.h" +#include + +#define USBD_VID 0x28E9U +#define USBD_PID 0x0189U + +/* local function prototypes ('static') */ +static uint8_t dfu_init(usb_dev *udev, uint8_t config_index); +static uint8_t dfu_deinit(usb_dev *udev, uint8_t config_index); +static uint8_t dfu_req_handler(usb_dev *udev, usb_req *req); +static uint8_t dfu_ctlx_in(usb_dev *udev); + +static void dfu_detach(usb_dev *udev, usb_req *req); +static void dfu_dnload(usb_dev *udev, usb_req *req); +static void dfu_upload(usb_dev *udev, usb_req *req); +static void dfu_getstatus(usb_dev *udev, usb_req *req); +static void dfu_clrstatus(usb_dev *udev, usb_req *req); +static void dfu_getstate(usb_dev *udev, usb_req *req); +static void dfu_abort(usb_dev *udev, usb_req *req); +static void dfu_mode_leave(usb_dev *udev); +static uint8_t dfu_getstatus_complete (usb_dev *udev); + +static void (*dfu_request_process[])(usb_dev *udev, usb_req *req) = +{ + [DFU_DETACH] = dfu_detach, + [DFU_DNLOAD] = dfu_dnload, + [DFU_UPLOAD] = dfu_upload, + [DFU_GETSTATUS] = dfu_getstatus, + [DFU_CLRSTATUS] = dfu_clrstatus, + [DFU_GETSTATE] = dfu_getstate, + [DFU_ABORT] = dfu_abort +}; + +/* note:it should use the c99 standard when compiling the below codes */ +/* USB standard device descriptor */ +const usb_desc_dev dfu_dev_desc = +{ + .header = + { + .bLength = USB_DEV_DESC_LEN, + .bDescriptorType = USB_DESCTYPE_DEV + }, + .bcdUSB = 0x0200U, + .bDeviceClass = 0x00U, + .bDeviceSubClass = 0x00U, + .bDeviceProtocol = 0x00U, + .bMaxPacketSize0 = USB_FS_EP0_MAX_LEN, + .idVendor = USBD_VID, + .idProduct = USBD_PID, + .bcdDevice = 0x0100U, + .iManufacturer = STR_IDX_MFC, + .iProduct = STR_IDX_PRODUCT, + .iSerialNumber = STR_IDX_SERIAL, + .bNumberConfigurations = USBD_CFG_MAX_NUM +}; + +/* USB device configuration descriptor */ +const usb_dfu_desc_config_set dfu_config_desc = +{ + .config = + { + .header = + { + .bLength = sizeof(usb_desc_config), + .bDescriptorType = USB_DESCTYPE_CONFIG + }, + .wTotalLength = USB_DFU_CONFIG_DESC_SIZE, + .bNumInterfaces = 0x01U, + .bConfigurationValue = 0x01U, + .iConfiguration = 0x00U, + .bmAttributes = 0x80U, + .bMaxPower = 0x32U + }, + + .dfu_itf = + { + .header = + { + .bLength = sizeof(usb_desc_itf), + .bDescriptorType = USB_DESCTYPE_ITF + }, + .bInterfaceNumber = 0x00U, + .bAlternateSetting = 0x00U, + .bNumEndpoints = 0x00U, + .bInterfaceClass = USB_DFU_CLASS, + .bInterfaceSubClass = USB_DFU_SUBCLASS_UPGRADE, + .bInterfaceProtocol = USB_DFU_PROTOCL_DFU, + .iInterface = 0x05U + }, + + .dfu_func = + { + .header = + { + .bLength = sizeof(usb_desc_dfu_func), + .bDescriptorType = DFU_DESC_TYPE + }, + .bmAttributes = USB_DFU_CAN_DOWNLOAD | USB_DFU_CAN_UPLOAD | USB_DFU_WILL_DETACH, + .wDetachTimeOut = 0x00FFU, + .wTransferSize = TRANSFER_SIZE, + .bcdDFUVersion = 0x011AU, + }, +}; + +/* USB language ID Descriptor */ +static const usb_desc_LANGID usbd_language_id_desc = +{ + .header = { + .bLength = sizeof(usb_desc_LANGID), + .bDescriptorType = USB_DESCTYPE_STR + }, + .wLANGID = ENG_LANGID +}; + +/* USB manufacture string */ +static const usb_desc_str manufacturer_string = +{ + .header = + { + .bLength = USB_STRING_LEN(10U), + .bDescriptorType = USB_DESCTYPE_STR, + }, + .unicode_string = {'G', 'i', 'g', 'a', 'D', 'e', 'v', 'i', 'c', 'e'} +}; + +/* USB product string */ +static const usb_desc_str product_string = +{ + .header = + { + .bLength = USB_STRING_LEN(12U), + .bDescriptorType = USB_DESCTYPE_STR, + }, + .unicode_string = {'G', 'D', '3', '2', '-', 'U', 'S', 'B', '_', 'D', 'F', 'U'} +}; + +/* USBD serial string */ +static usb_desc_str serial_string = +{ + .header = + { + .bLength = USB_STRING_LEN(2U), + .bDescriptorType = USB_DESCTYPE_STR, + } +}; + +/* USB configure string */ +static const usb_desc_str config_string = +{ + .header = + { + .bLength = USB_STRING_LEN(15U), + .bDescriptorType = USB_DESCTYPE_STR, + }, + .unicode_string = {'G', 'D', '3', '2', ' ', 'U', 'S', 'B', ' ', 'C', 'O', 'N', 'F', 'I', 'G'} +}; + +static const usb_desc_str interface_string = +{ + .header = + { + .bLength = USB_STRING_LEN(44U), + .bDescriptorType = USB_DESCTYPE_STR, + }, + .unicode_string = {'@', 'I', 'n', 't', 'e', 'r', 'n', 'a', 'l', 'F', 'l', 'a', 's', 'h', ' ', '/', '0', 'x', '0', '8', '0', '0', + '0', '0', '0', '0', '/', '1', '6', '*', '0', '0', '1', 'K', 'a', ',', '4', '8', '*', '0', '0', '1', 'K', 'g'} +}; + +void *const usbd_dfu_strings[] = +{ + [STR_IDX_LANGID] = (uint8_t *)&usbd_language_id_desc, + [STR_IDX_MFC] = (uint8_t *)&manufacturer_string, + [STR_IDX_PRODUCT] = (uint8_t *)&product_string, + [STR_IDX_SERIAL] = (uint8_t *)&serial_string, + [STR_IDX_CONFIG] = (uint8_t *)&config_string, + [STR_IDX_ITF] = (uint8_t *)&interface_string +}; + +usb_desc dfu_desc = { + .dev_desc = (uint8_t *)&dfu_dev_desc, + .config_desc = (uint8_t *)&dfu_config_desc, + .strings = usbd_dfu_strings +}; + +usb_class_core dfu_class = { + .init = dfu_init, + .deinit = dfu_deinit, + .req_proc = dfu_req_handler, + .ctlx_in = dfu_ctlx_in +}; + +/*! + \brief initialize the DFU device + \param[in] udev: pointer to USB device instance + \param[in] config_index: configuration index + \param[out] none + \retval USB device operation status +*/ +static uint8_t dfu_init (usb_dev *udev, uint8_t config_index) +{ + static usbd_dfu_handler dfu_handler; + + /* unlock the internal flash */ + dfu_mal_init(); + + memset((void *)&dfu_handler, 0, sizeof(usbd_dfu_handler)); + + dfu_handler.base_addr = APP_LOADED_ADDR; + dfu_handler.manifest_state = MANIFEST_COMPLETE; + dfu_handler.bState = STATE_DFU_IDLE; + dfu_handler.bStatus = STATUS_OK; + + udev->dev.class_data[USBD_DFU_INTERFACE] = (void *)&dfu_handler; + + return USBD_OK; +} + +/*! + \brief deinitialize the DFU device + \param[in] udev: pointer to USB device instance + \param[in] config_index: configuration index + \param[out] none + \retval USB device operation status +*/ +static uint8_t dfu_deinit (usb_dev *udev, uint8_t config_index) +{ + usbd_dfu_handler *dfu = (usbd_dfu_handler *)udev->dev.class_data[USBD_DFU_INTERFACE]; + + /* restore device default state */ + memset(udev->dev.class_data[USBD_DFU_INTERFACE], 0, sizeof(usbd_dfu_handler)); + + dfu->bState = STATE_DFU_IDLE; + dfu->bStatus = STATUS_OK; + + /* lock the internal flash */ + dfu_mal_deinit(); + + return USBD_OK; +} + +/*! + \brief handle the DFU class-specific requests + \param[in] udev: pointer to USB device instance + \param[in] req: device class-specific request + \param[out] none + \retval USB device operation status +*/ +static uint8_t dfu_req_handler (usb_dev *udev, usb_req *req) +{ + if (req->bRequest < DFU_REQ_MAX) { + dfu_request_process[req->bRequest](udev, req); + } else { + return USBD_FAIL; + } + + return USBD_OK; +} + +/*! + \brief handle data Stage + \param[in] udev: pointer to USB device instance + \param[in] ep_num: the endpoint number + \param[out] none + \retval USB device operation status +*/ +static uint8_t dfu_ctlx_in (usb_dev *udev) +{ + dfu_getstatus_complete(udev); + + return USBD_OK; +} + +/*! + \brief leave DFU mode and reset device to jump to user loaded code + \param[in] udev: pointer to USB device instance + \param[out] none + \retval none +*/ +static void dfu_mode_leave (usb_dev *udev) +{ + usbd_dfu_handler *dfu = (usbd_dfu_handler *)udev->dev.class_data[USBD_DFU_INTERFACE]; + + dfu->manifest_state = MANIFEST_COMPLETE; + + if (dfu_config_desc.dfu_func.bmAttributes & 0x04U) { + dfu->bState = STATE_DFU_MANIFEST_SYNC; + } else { + dfu->bState = STATE_DFU_MANIFEST_WAIT_RESET; + + /* lock the internal flash */ + dfu_mal_deinit(); + + /* generate system reset to allow jumping to the user code */ + NVIC_SystemReset(); + } +} + +/*! + \brief handle data IN stage in control endpoint 0 + \param[in] udev: pointer to USB device instance + \param[out] none + \retval USB device operation status + */ +static uint8_t dfu_getstatus_complete (usb_dev *udev) +{ + uint32_t addr; + + usbd_dfu_handler *dfu = (usbd_dfu_handler *)udev->dev.class_data[USBD_DFU_INTERFACE]; + + if (STATE_DFU_DNBUSY == dfu->bState) { + /* decode the special command */ + if (0U == dfu->block_num) { + if (1U == dfu->data_len){ + if (GET_COMMANDS == dfu->buf[0]) { + /* no operation */ + } + } else if (5U == dfu->data_len) { + if (SET_ADDRESS_POINTER == dfu->buf[0]) { + /* set flash operation address */ + dfu->base_addr = *(uint32_t *)(dfu->buf + 1U); + } else if (ERASE == dfu->buf[0]) { + dfu->base_addr = *(uint32_t *)(dfu->buf + 1U); + + dfu_mal_erase(dfu->base_addr); + } else { + /* no operation */ + } + } else { + /* no operation */ + } + } else if (dfu->block_num > 1U) { /* regular download command */ + /* decode the required address */ + addr = (dfu->block_num - 2U) * TRANSFER_SIZE + dfu->base_addr; + + dfu_mal_write (dfu->buf, addr, dfu->data_len); + + dfu->block_num = 0U; + } else { + /* no operation */ + } + + dfu->data_len = 0U; + + /* update the device state and poll timeout */ + dfu->bState = STATE_DFU_DNLOAD_SYNC; + + return USBD_OK; + } else if (dfu->bState == STATE_DFU_MANIFEST) { /* manifestation in progress */ + /* start leaving DFU mode */ + dfu_mode_leave(udev); + } else { + /* no operation */ + } + + return USBD_OK; +} + +/*! + \brief handle the DFU_DETACH request + \param[in] udev: pointer to USB device instance + \param[in] req: DFU class request + \param[out] none + \retval none. +*/ +static void dfu_detach(usb_dev *udev, usb_req *req) +{ + usbd_dfu_handler *dfu = (usbd_dfu_handler *)udev->dev.class_data[USBD_DFU_INTERFACE]; + + switch (dfu->bState) { + case STATE_DFU_IDLE: + case STATE_DFU_DNLOAD_SYNC: + case STATE_DFU_DNLOAD_IDLE: + case STATE_DFU_MANIFEST_SYNC: + case STATE_DFU_UPLOAD_IDLE: + dfu->bStatus = STATUS_OK; + dfu->bState = STATE_DFU_IDLE; + dfu->iString = 0U; /* iString */ + + dfu->block_num = 0U; + dfu->data_len = 0U; + break; + + default: + break; + } + + /* check the detach capability in the DFU functional descriptor */ + if (dfu_config_desc.dfu_func.wDetachTimeOut & DFU_DETACH_MASK) { + usbd_disconnect (udev); + + usbd_connect (udev); + } else { + /* wait for the period of time specified in detach request */ + usb_mdelay (4U); + } +} + +/*! + \brief handle the DFU_DNLOAD request + \param[in] udev: pointer to USB device instance + \param[in] req: DFU class request + \param[out] none + \retval none +*/ +static void dfu_dnload(usb_dev *udev, usb_req *req) +{ + usb_transc *transc = &udev->dev.transc_out[0]; + usbd_dfu_handler *dfu = (usbd_dfu_handler *)udev->dev.class_data[USBD_DFU_INTERFACE]; + + switch (dfu->bState) { + case STATE_DFU_IDLE: + case STATE_DFU_DNLOAD_IDLE: + if (req->wLength > 0U) { + /* update the global length and block number */ + dfu->block_num = req->wValue; + dfu->data_len = req->wLength; + + dfu->bState = STATE_DFU_DNLOAD_SYNC; + + transc->remain_len = dfu->data_len; + transc->xfer_buf = dfu->buf; + } else { + dfu->manifest_state = MANIFEST_IN_PROGRESS; + dfu->bState = STATE_DFU_MANIFEST_SYNC; + } + break; + + default: + break; + } +} + +/*! + \brief handles the DFU UPLOAD request. + \param[in] udev: pointer to USB device instance + \param[in] req: DFU class request + \param[out] none + \retval none +*/ +static void dfu_upload (usb_dev *udev, usb_req *req) +{ + uint8_t *phy_addr = NULL; + uint32_t addr = 0U; + usbd_dfu_handler *dfu = (usbd_dfu_handler *)udev->dev.class_data[USBD_DFU_INTERFACE]; + + usb_transc *transc = &udev->dev.transc_in[0]; + + if(req->wLength <= 0U) { + dfu->bState = STATE_DFU_IDLE; + return; + } + + switch (dfu->bState) { + case STATE_DFU_IDLE: + case STATE_DFU_UPLOAD_IDLE: + /* update the global length and block number */ + dfu->block_num = req->wValue; + dfu->data_len = req->wLength; + + /* DFU get command */ + if (0U == dfu->block_num) { + /* update the state machine */ + dfu->bState = (dfu->data_len > 3U) ? STATE_DFU_IDLE : STATE_DFU_UPLOAD_IDLE; + + /* store the values of all supported commands */ + dfu->buf[0] = GET_COMMANDS; + dfu->buf[1] = SET_ADDRESS_POINTER; + dfu->buf[2] = ERASE; + + /* send the status data over EP0 */ + transc->xfer_buf = &(dfu->buf[0]); + transc->remain_len = 3U; + } else if (dfu->block_num > 1U) { + dfu->bState = STATE_DFU_UPLOAD_IDLE; + + /* change is accelerated */ + addr = (dfu->block_num - 2U) * TRANSFER_SIZE + dfu->base_addr; + + /* return the physical address where data are stored */ + phy_addr = dfu_mal_read (dfu->buf, addr, dfu->data_len); + + /* send the status data over EP0 */ + transc->xfer_buf = phy_addr; + transc->remain_len = dfu->data_len; + } else { + dfu->bState = STATUS_ERR_STALLEDPKT; + } + break; + + default: + dfu->data_len = 0U; + dfu->block_num = 0U; + break; + } +} + +/*! + \brief handle the DFU_GETSTATUS request + \param[in] udev: pointer to USB device instance + \param[in] req: DFU class request + \param[out] none + \retval none +*/ +static void dfu_getstatus (usb_dev *udev, usb_req *req) +{ + usbd_dfu_handler *dfu = (usbd_dfu_handler *)udev->dev.class_data[USBD_DFU_INTERFACE]; + + usb_transc *transc = &udev->dev.transc_in[0]; + + switch (dfu->bState) { + case STATE_DFU_DNLOAD_SYNC: + if (0U != dfu->data_len) { + dfu->bState = STATE_DFU_DNBUSY; + + if (0U == dfu->block_num) { + if (ERASE == dfu->buf[0]) { + dfu_mal_getstatus (dfu->base_addr, CMD_ERASE, (uint8_t *)&dfu->bwPollTimeout0); + } else { + dfu_mal_getstatus (dfu->base_addr, CMD_WRITE, (uint8_t *)&dfu->bwPollTimeout0); + } + } + } else { + dfu->bState = STATE_DFU_DNLOAD_IDLE; + } + break; + + case STATE_DFU_MANIFEST_SYNC: + if (MANIFEST_IN_PROGRESS == dfu->manifest_state) { + dfu->bState = STATE_DFU_MANIFEST; + dfu->bwPollTimeout0 = 1U; + } else if ((MANIFEST_COMPLETE == dfu->manifest_state) && \ + (dfu_config_desc.dfu_func.bmAttributes & 0x04U)){ + dfu->bState = STATE_DFU_IDLE; + dfu->bwPollTimeout0 = 0U; + } else { + /* no operation */ + } + break; + + default: + break; + } + + /* send the status data of DFU interface to host over EP0 */ + transc->xfer_buf = (uint8_t *)&(dfu->bStatus); + transc->remain_len = 6U; +} + +/*! + \brief handle the DFU_CLRSTATUS request + \param udev: pointer to USB device instance + \param[out] none + \retval none +*/ +static void dfu_clrstatus (usb_dev *udev, usb_req *req) +{ + usbd_dfu_handler *dfu = (usbd_dfu_handler *)udev->dev.class_data[USBD_DFU_INTERFACE]; + + if (STATE_DFU_ERROR == dfu->bState) { + dfu->bStatus = STATUS_OK; + dfu->bState = STATE_DFU_IDLE; + } else { + /* state error */ + dfu->bStatus = STATUS_ERR_UNKNOWN; + dfu->bState = STATE_DFU_ERROR; + } + + dfu->iString = 0U; /* iString: index = 0 */ +} + +/*! + \brief handle the DFU_GETSTATE request + \param[in] udev: pointer to USB device instance + \param[out] none + \retval none +*/ +static void dfu_getstate (usb_dev *udev, usb_req *req) +{ + usbd_dfu_handler *dfu = (usbd_dfu_handler *)udev->dev.class_data[USBD_DFU_INTERFACE]; + + usb_transc *transc = &udev->dev.transc_in[0]; + + /* send the current state of the DFU interface to host */ + transc->xfer_buf = &(dfu->bState); + transc->remain_len = 1U; +} + +/*! + \brief handle the DFU_ABORT request + \param[in] udev: pointer to USB device instance + \param[out] none + \retval none +*/ +static void dfu_abort (usb_dev *udev, usb_req *req) +{ + usbd_dfu_handler *dfu = (usbd_dfu_handler *)udev->dev.class_data[USBD_DFU_INTERFACE]; + + switch (dfu->bState){ + case STATE_DFU_IDLE: + case STATE_DFU_DNLOAD_SYNC: + case STATE_DFU_DNLOAD_IDLE: + case STATE_DFU_MANIFEST_SYNC: + case STATE_DFU_UPLOAD_IDLE: + dfu->bStatus = STATUS_OK; + dfu->bState = STATE_DFU_IDLE; + dfu->iString = 0U; /* iString: index = 0 */ + + dfu->block_num = 0U; + dfu->data_len = 0U; + break; + + default: + break; + } +} diff --git a/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/device/class/dfu/Source/dfu_mal.c b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/device/class/dfu/Source/dfu_mal.c new file mode 100644 index 0000000000..4323b5b7b1 --- /dev/null +++ b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/device/class/dfu/Source/dfu_mal.c @@ -0,0 +1,233 @@ +/*! + \file dfu_mal.c + \brief USB DFU device media access layer functions + + \version 2020-07-17, V3.0.0, firmware for GD32F10x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "dfu_mal.h" +#include "flash_if.h" +#include "drv_usb_hw.h" +#include "usbd_transc.h" + +extern usb_core_driver usb_dfu_dev; + +extern struct { + uint8_t buf[TRANSFER_SIZE]; + uint16_t data_len; + uint16_t block_num; + uint32_t base_addr; +} prog; + +dfu_mal_prop* tMALTab[MAX_USED_MEMORY_MEDIA] = { + &DFU_Flash_cb +}; + +/* The list of memory interface string descriptor pointers. This list + can be updated whenever a memory has to be added or removed */ +const uint8_t* USBD_DFU_StringDesc[MAX_USED_MEMORY_MEDIA] = +{ + (const uint8_t *)FLASH_IF_STRING +}; + +static uint8_t dfu_mal_checkaddr (uint32_t addr); + +/*! + \brief initialize the memory media on the GD32 + \param[in] none + \param[out] none + \retval MAL_OK +*/ +uint8_t dfu_mal_init (void) +{ + uint32_t mem_index = 0U; + + /* initialize all supported memory medias */ + for (mem_index = 0U; mem_index < MAX_USED_MEMORY_MEDIA; mem_index++) { + /* check if the memory media exists */ + if (NULL != tMALTab[mem_index]->mal_init) { + tMALTab[mem_index]->mal_init(); + } + } + + return MAL_OK; +} + +/*! + \brief deinitialize the memory media on the GD32 + \param[in] none + \param[out] none + \retval MAL_OK +*/ +uint8_t dfu_mal_deinit (void) +{ + uint32_t mem_index = 0U; + + /* deinitialize all supported memory medias */ + for (mem_index = 0U; mem_index < MAX_USED_MEMORY_MEDIA; mem_index++) { + /* check if the memory media exists */ + if (NULL != tMALTab[mem_index]->mal_deinit) { + tMALTab[mem_index]->mal_deinit(); + } + } + + return MAL_OK; +} + +/*! + \brief erase a memory sector + \param[in] addr: memory sector address/code + \param[out] none + \retval MAL_OK +*/ +uint8_t dfu_mal_erase (uint32_t addr) +{ + uint32_t mem_index = dfu_mal_checkaddr(addr); + + /* check if the address is in protected area */ + if (IS_PROTECTED_AREA(addr)) { + return MAL_FAIL; + } + + if (mem_index < MAX_USED_MEMORY_MEDIA) { + /* check if the operation is supported */ + if (NULL != tMALTab[mem_index]->mal_erase) { + return tMALTab[mem_index]->mal_erase(addr); + } else { + return MAL_FAIL; + } + } else { + return MAL_FAIL; + } +} + +/*! + \brief write data to sectors of memory + \param[in] buf: the data buffer to be write + \param[in] addr: memory sector address/code + \param[in] len: data length + \param[out] none + \retval MAL_OK +*/ +uint8_t dfu_mal_write (uint8_t *buf, uint32_t addr, uint32_t len) +{ + uint32_t mem_index = dfu_mal_checkaddr(addr); + + /* check if the address is in protected area */ + if (IS_PROTECTED_AREA(addr)) { + return MAL_FAIL; + } + + if (mem_index < MAX_USED_MEMORY_MEDIA) { + /* check if the operation is supported */ + if (NULL != tMALTab[mem_index]->mal_write) { + return tMALTab[mem_index]->mal_write(buf, addr, len); + } else { + return MAL_FAIL; + } + } else { + return MAL_FAIL; + } +} + +/*! + \brief read data from sectors of memory + \param[in] buf: the data buffer to be write + \param[in] addr: memory sector address/code + \param[in] len: data length + \param[out] none + \retval pointer to buffer +*/ +uint8_t* dfu_mal_read (uint8_t *buf, uint32_t addr, uint32_t len) +{ + uint32_t mem_index = 0U; + + if (OB_RDPT != addr) { + mem_index = dfu_mal_checkaddr(addr); + } + + if (mem_index < MAX_USED_MEMORY_MEDIA) { + /* check if the operation is supported */ + if (NULL != tMALTab[mem_index]->mal_read) { + return tMALTab[mem_index]->mal_read(buf, addr, len); + } else { + return buf; + } + } else { + return buf; + } +} + +/*! + \brief get the status of a given memory and store in buffer + \param[in] addr: memory sector address/code + \param[in] cmd: 0 for erase and 1 for write + \param[in] buffer: pointer to the buffer where the status data will be stored + \param[out] none + \retval MAL_OK if all operations are OK, MAL_FAIL else +*/ +uint8_t dfu_mal_getstatus (uint32_t addr, uint8_t cmd, uint8_t *buffer) +{ + uint32_t mem_index = dfu_mal_checkaddr(addr); + + if (mem_index < MAX_USED_MEMORY_MEDIA) { + if (cmd & 0x01U) { + SET_POLLING_TIMEOUT(tMALTab[mem_index]->write_timeout); + } else { + SET_POLLING_TIMEOUT(tMALTab[mem_index]->erase_timeout); + } + + return MAL_OK; + } else { + return MAL_FAIL; + } +} + +/*! + \brief check the address is supported + \param[in] addr: memory sector address/code + \param[out] none + \retval index of the addressed memory +*/ +static uint8_t dfu_mal_checkaddr (uint32_t addr) +{ + uint8_t mem_index = 0U; + + /* check with all supported memories */ + for (mem_index = 0U; mem_index < MAX_USED_MEMORY_MEDIA; mem_index++) { + /* if the check address is supported, return the memory index */ + if (MAL_OK == tMALTab[mem_index]->mal_checkaddr(addr)) { + return mem_index; + } + } + + /* if there is no memory found, return MAX_USED_MEMORY_MEDIA */ + return (MAX_USED_MEMORY_MEDIA); +} diff --git a/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/device/class/hid/Include/custom_hid_core.h b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/device/class/hid/Include/custom_hid_core.h new file mode 100644 index 0000000000..a20ba15c48 --- /dev/null +++ b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/device/class/hid/Include/custom_hid_core.h @@ -0,0 +1,69 @@ +/*! + \file custom_hid_core.h + \brief definitions for HID core + + \version 2020-07-17, V3.0.0, firmware for GD32F10x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef __CUSTOM_HID_CORE_H +#define __CUSTOM_HID_CORE_H + +#include "usbd_enum.h" +#include "usb_hid.h" + +#define DESC_LEN_REPORT 96U +#define DESC_LEN_CONFIG 41U + +#define NO_CMD 0xFFU + +#define MAX_PERIPH_NUM 4U + +typedef struct { + uint8_t data[2]; + + uint8_t reportID; + uint8_t idlestate; + uint8_t protocol; +} custom_hid_handler; + +typedef struct { + void (*periph_config[MAX_PERIPH_NUM])(void); +} hid_fop_handler; + +extern usb_desc custom_hid_desc; +extern usb_class_core usbd_custom_hid_cb; + +/* function declarations */ +/* register HID interface operation functions */ +uint8_t custom_hid_itfop_register (usb_dev *udev, hid_fop_handler *hid_fop); +/* send custom HID report */ +uint8_t custom_hid_report_send (usb_dev *udev, uint8_t *report, uint32_t len); + +#endif /* __CUSTOM_HID_CORE_H */ diff --git a/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/device/class/hid/Include/standard_hid_core.h b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/device/class/hid/Include/standard_hid_core.h new file mode 100644 index 0000000000..313517dd85 --- /dev/null +++ b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/device/class/hid/Include/standard_hid_core.h @@ -0,0 +1,68 @@ +/*! + \file standard_hid_core.h + \brief definitions for HID core + + \version 2020-07-17, V3.0.0, firmware for GD32F10x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef __STANDARD_HID_CORE_H +#define __STANDARD_HID_CORE_H + +#include "usbd_enum.h" +#include "usb_hid.h" + +#define USB_HID_CONFIG_DESC_LEN 0x22U +#define USB_HID_REPORT_DESC_LEN 0x2EU + +#define NO_CMD 0xFFU + +typedef struct { + uint32_t protocol; + uint32_t idle_state; + + uint8_t data[HID_IN_PACKET]; + __IO uint8_t prev_transfer_complete; +} standard_hid_handler; + +typedef struct { + void (*hid_itf_config) (void); + void (*hid_itf_data_process) (usb_dev *udev); +} hid_fop_handler; + +extern usb_desc hid_desc; +extern usb_class_core usbd_hid_cb; + +/* function declarations */ +/* register HID interface operation functions */ +uint8_t hid_itfop_register (usb_dev *udev, hid_fop_handler *hid_fop); +/* send keyboard report */ +uint8_t hid_report_send (usb_dev *udev, uint8_t *report, uint32_t len); + +#endif /* __STANDARD_HID_CORE_H */ diff --git a/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/device/class/hid/Source/custom_hid_core.c b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/device/class/hid/Source/custom_hid_core.c new file mode 100644 index 0000000000..345637ee18 --- /dev/null +++ b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/device/class/hid/Source/custom_hid_core.c @@ -0,0 +1,489 @@ +/*! + \file custom_hid_core.c + \brief custom HID class driver + + \version 2020-07-17, V3.0.0, firmware for GD32F10x + \version 2020-12-07, V3.0.1, firmware for GD32F10x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "custom_hid_core.h" +#include "usbd_enum.h" + +#include + +#define USBD_VID 0x28E9U +#define USBD_PID 0x028AU + +/* Note:it should use the C99 standard when compiling the below codes */ +/* USB standard device descriptor */ +const usb_desc_dev custom_hid_dev_desc = +{ + .header = + { + .bLength = USB_DEV_DESC_LEN, + .bDescriptorType = USB_DESCTYPE_DEV, + }, + .bcdUSB = 0x0200U, + .bDeviceClass = 0x00U, + .bDeviceSubClass = 0x00U, + .bDeviceProtocol = 0x00U, + .bMaxPacketSize0 = USB_FS_EP0_MAX_LEN, + .idVendor = USBD_VID, + .idProduct = USBD_PID, + .bcdDevice = 0x0100U, + .iManufacturer = STR_IDX_MFC, + .iProduct = STR_IDX_PRODUCT, + .iSerialNumber = STR_IDX_SERIAL, + .bNumberConfigurations = USBD_CFG_MAX_NUM, +}; + +/* USB device configuration descriptor */ +const usb_hid_desc_config_set custom_hid_config_desc = +{ + .config = + { + .header = + { + .bLength = sizeof(usb_desc_config), + .bDescriptorType = USB_DESCTYPE_CONFIG + }, + .wTotalLength = DESC_LEN_CONFIG, + .bNumInterfaces = 0x01U, + .bConfigurationValue = 0x01U, + .iConfiguration = 0x00U, + .bmAttributes = 0x80U, + .bMaxPower = 0x32U + }, + + .hid_itf = + { + .header = + { + .bLength = sizeof(usb_desc_itf), + .bDescriptorType = USB_DESCTYPE_ITF + }, + .bInterfaceNumber = 0x00U, + .bAlternateSetting = 0x00U, + .bNumEndpoints = 0x02U, + .bInterfaceClass = USB_HID_CLASS, + .bInterfaceSubClass = 0x00U, + .bInterfaceProtocol = 0x00U, + .iInterface = 0x00U + }, + + .hid_vendor = + { + .header = + { + .bLength = sizeof(usb_desc_hid), + .bDescriptorType = USB_DESCTYPE_HID + }, + .bcdHID = 0x0111U, + .bCountryCode = 0x00U, + .bNumDescriptors = 0x01U, + .bDescriptorType = USB_DESCTYPE_REPORT, + .wDescriptorLength = DESC_LEN_REPORT, + }, + + .hid_epin = + { + .header = + { + .bLength = sizeof(usb_desc_ep), + .bDescriptorType = USB_DESCTYPE_EP + }, + .bEndpointAddress = CUSTOMHID_IN_EP, + .bmAttributes = USB_EP_ATTR_INT, + .wMaxPacketSize = CUSTOMHID_IN_PACKET, + .bInterval = 0x20U + }, + + .hid_epout = + { + .header = + { + .bLength = sizeof(usb_desc_ep), + .bDescriptorType = USB_DESCTYPE_EP + }, + .bEndpointAddress = CUSTOMHID_OUT_EP, + .bmAttributes = USB_EP_ATTR_INT, + .wMaxPacketSize = CUSTOMHID_OUT_PACKET, + .bInterval = 0x20U + } +}; + +/* USB language ID descriptor */ +static const usb_desc_LANGID usbd_language_id_desc = +{ + .header = + { + .bLength = sizeof(usb_desc_LANGID), + .bDescriptorType = USB_DESCTYPE_STR + }, + .wLANGID = ENG_LANGID +}; + +/* USB manufacture string */ +static const usb_desc_str manufacturer_string = +{ + .header = + { + .bLength = USB_STRING_LEN(10U), + .bDescriptorType = USB_DESCTYPE_STR, + }, + .unicode_string = {'G', 'i', 'g', 'a', 'D', 'e', 'v', 'i', 'c', 'e'} +}; + +/* USB product string */ +static const usb_desc_str product_string = +{ + .header = + { + .bLength = USB_STRING_LEN(14U), + .bDescriptorType = USB_DESCTYPE_STR, + }, + .unicode_string = {'G', 'D', '3', '2', '-', 'C', 'u', 's', 't', 'o', 'm', 'H', 'I', 'D'} +}; + +/* USBD serial string */ +static usb_desc_str serial_string = +{ + .header = + { + .bLength = USB_STRING_LEN(12U), + .bDescriptorType = USB_DESCTYPE_STR, + } +}; + +/* USB string descriptor set */ +void *const usbd_hid_strings[] = +{ + [STR_IDX_LANGID] = (uint8_t *)&usbd_language_id_desc, + [STR_IDX_MFC] = (uint8_t *)&manufacturer_string, + [STR_IDX_PRODUCT] = (uint8_t *)&product_string, + [STR_IDX_SERIAL] = (uint8_t *)&serial_string +}; + +usb_desc custom_hid_desc = { + .dev_desc = (uint8_t *)&custom_hid_dev_desc, + .config_desc = (uint8_t *)&custom_hid_config_desc, + .strings = usbd_hid_strings +}; + +const uint8_t customhid_report_descriptor[DESC_LEN_REPORT] = +{ + 0x06, 0x00, 0xFF, /* USAGE_PAGE (Vendor Defined: 0xFF00) */ + 0x09, 0x00, /* USAGE (Custom Device) */ + 0xa1, 0x01, /* COLLECTION (Application) */ + + /* led 1 */ + 0x85, 0x11, /* REPORT_ID (0x11) */ + 0x09, 0x01, /* USAGE (LED 1) */ + 0x15, 0x00, /* LOGICAL_MINIMUM (0) */ + 0x25, 0x01, /* LOGICAL_MAXIMUM (1) */ + 0x75, 0x08, /* REPORT_SIZE (8) */ + 0x95, 0x01, /* REPORT_COUNT (1) */ + 0x91, 0x82, /* OUTPUT (Data,Var,Abs,Vol) */ + + /* led 2 */ + 0x85, 0x12, /* REPORT_ID (0x12) */ + 0x09, 0x02, /* USAGE (LED 2) */ + 0x15, 0x00, /* LOGICAL_MINIMUM (0) */ + 0x25, 0x01, /* LOGICAL_MAXIMUM (1) */ + 0x75, 0x08, /* REPORT_SIZE (8) */ + 0x95, 0x01, /* REPORT_COUNT (1) */ + 0x91, 0x82, /* OUTPUT (Data,Var,Abs,Vol) */ + + /* led 3 */ + 0x85, 0x13, /* REPORT_ID (0x13) */ + 0x09, 0x03, /* USAGE (LED 3) */ + 0x15, 0x00, /* LOGICAL_MINIMUM (0) */ + 0x25, 0x01, /* LOGICAL_MAXIMUM (1) */ + 0x75, 0x08, /* REPORT_SIZE (8) */ + 0x95, 0x01, /* REPORT_COUNT (1) */ + 0x91, 0x82, /* OUTPUT (Data,Var,Abs,Vol) */ + + /* led 4 */ + 0x85, 0x14, /* REPORT_ID (0x14) */ + 0x09, 0x04, /* USAGE (LED 4) */ + 0x15, 0x00, /* LOGICAL_MINIMUM (0) */ + 0x25, 0x01, /* LOGICAL_MAXIMUM (1) */ + 0x75, 0x08, /* REPORT_SIZE (8) */ + 0x95, 0x01, /* REPORT_COUNT (1) */ + 0x91, 0x82, /* OUTPUT (Data,Var,Abs,Vol) */ + + /* wakeup key */ + 0x85, 0x15, /* REPORT_ID (0x15) */ + 0x09, 0x05, /* USAGE (Push Button) */ + 0x15, 0x00, /* LOGICAL_MINIMUM (0) */ + 0x25, 0x01, /* LOGICAL_MAXIMUM (1) */ + 0x75, 0x01, /* REPORT_SIZE (1) */ + 0x81, 0x02, /* INPUT (Data,Var,Abs,Vol) */ + + 0x75, 0x07, /* REPORT_SIZE (7) */ + 0x81, 0x03, /* INPUT (Cnst,Var,Abs,Vol) */ + + /* tamper key */ + 0x85, 0x16, /* REPORT_ID (0x16) */ + 0x09, 0x06, /* USAGE (Push Button) */ + 0x15, 0x00, /* LOGICAL_MINIMUM (0) */ + 0x25, 0x01, /* LOGICAL_MAXIMUM (1) */ + 0x75, 0x01, /* REPORT_SIZE (1) */ + 0x81, 0x02, /* INPUT (Data,Var,Abs,Vol) */ + + 0x75, 0x07, /* REPORT_SIZE (7) */ + 0x81, 0x03, /* INPUT (Cnst,Var,Abs,Vol) */ + + 0xc0 /* END_COLLECTION */ +}; + +/* local function prototypes ('static') */ +static uint8_t custom_hid_init (usb_dev *udev, uint8_t config_index); +static uint8_t custom_hid_deinit (usb_dev *udev, uint8_t config_index); +static uint8_t custom_hid_req_handler (usb_dev *udev, usb_req *req); + +static uint8_t custom_hid_data_in (usb_dev *udev, uint8_t ep_num); +static uint8_t custom_hid_data_out (usb_dev *udev, uint8_t ep_num); + +usb_class_core usbd_custom_hid_cb = +{ + .command = NO_CMD, + .alter_set = 0U, + + .init = custom_hid_init, + .deinit = custom_hid_deinit, + + .req_proc = custom_hid_req_handler, + + .data_in = custom_hid_data_in, + .data_out = custom_hid_data_out +}; + +/*! + \brief register HID interface operation functions + \param[in] udev: pointer to USB device instance + \param[in] hid_fop: HID operation functions structure + \param[out] none + \retval USB device operation status +*/ +uint8_t custom_hid_itfop_register (usb_dev *udev, hid_fop_handler *hid_fop) +{ + if (NULL != hid_fop) { + udev->dev.user_data = hid_fop; + + return USBD_OK; + } + + return USBD_FAIL; +} + +/*! + \brief send custom HID report + \param[in] udev: pointer to USB device instance + \param[in] report: pointer to HID report + \param[in] len: data length + \param[out] none + \retval USB device operation status +*/ +uint8_t custom_hid_report_send (usb_dev *udev, uint8_t *report, uint32_t len) +{ + usbd_ep_send (udev, CUSTOMHID_IN_EP, report, len); + + return USBD_OK; +} + +/*! + \brief initialize the HID device + \param[in] udev: pointer to USB device instance + \param[in] config_index: configuration index + \param[out] none + \retval USB device operation status +*/ +static uint8_t custom_hid_init (usb_dev *udev, uint8_t config_index) +{ + static custom_hid_handler hid_handler; + + memset((void *)&hid_handler, 0U, sizeof(custom_hid_handler)); + + /* initialize the data TX endpoint */ + usbd_ep_setup (udev, &(custom_hid_config_desc.hid_epin)); + + /* Initialize the data RX endpoint */ + usbd_ep_setup (udev, &(custom_hid_config_desc.hid_epout)); + + /* prepare receive data */ + usbd_ep_recev (udev, CUSTOMHID_OUT_EP, hid_handler.data, 2U); + + udev->dev.class_data[CUSTOM_HID_INTERFACE] = (void *)&hid_handler; + + if (udev->dev.user_data != NULL) { + for (uint8_t i = 0U; i < MAX_PERIPH_NUM; i++) { + if (((hid_fop_handler *)udev->dev.user_data)->periph_config[i] != NULL) { + ((hid_fop_handler *)udev->dev.user_data)->periph_config[i](); + } + } + } + + return USBD_OK; +} + +/*! + \brief deinitialize the HID device + \param[in] udev: pointer to USB device instance + \param[in] config_index: configuration index + \param[out] none + \retval USB device operation status +*/ +static uint8_t custom_hid_deinit (usb_dev *udev, uint8_t config_index) +{ + /* deinitialize HID endpoints */ + usbd_ep_clear(udev, CUSTOMHID_IN_EP); + usbd_ep_clear(udev, CUSTOMHID_OUT_EP); + + return USBD_OK; +} + +/*! + \brief handle the HID class-specific requests + \param[in] udev: pointer to USB device instance + \param[in] req: device class-specific request + \param[out] none + \retval USB device operation status +*/ +static uint8_t custom_hid_req_handler (usb_dev *udev, usb_req *req) +{ + usb_transc *transc = &udev->dev.transc_in[0]; + + custom_hid_handler *hid = (custom_hid_handler *)udev->dev.class_data[CUSTOM_HID_INTERFACE]; + + switch (req->bRequest) { + case GET_REPORT: + break; + + case GET_IDLE: + transc->xfer_buf = (uint8_t *)&hid->idlestate; + transc->remain_len = 1U; + break; + + case GET_PROTOCOL: + transc->xfer_buf = (uint8_t *)&hid->protocol; + transc->remain_len = 1U; + break; + + case SET_REPORT: + hid->reportID = (uint8_t)(req->wValue); + break; + + case SET_IDLE: + hid->idlestate = (uint8_t)(req->wValue >> 8U); + break; + + case SET_PROTOCOL: + hid->protocol = (uint8_t)(req->wValue); + break; + + case USB_GET_DESCRIPTOR: + if (USB_DESCTYPE_REPORT == (req->wValue >> 8U)) { + transc->remain_len = USB_MIN(DESC_LEN_REPORT, req->wLength); + transc->xfer_buf = (uint8_t *)customhid_report_descriptor; + } + break; + + default: + return USBD_FAIL; + } + + return USBD_OK; +} + +/*! + \brief handle custom HID data + \param[in] udev: pointer to USB device instance + \param[in] ep_num: endpoint identifier + \param[out] none + \retval USB device operation status +*/ +static uint8_t custom_hid_data_in (usb_dev *udev, uint8_t ep_num) +{ + return USBD_OK; +} + +/*! + \brief handle custom HID data + \param[in] udev: pointer to USB device instance + \param[in] ep_num: endpoint identifier + \param[out] none + \retval USB device operation status +*/ +static uint8_t custom_hid_data_out (usb_dev *udev, uint8_t ep_num) +{ + custom_hid_handler *hid = (custom_hid_handler *)udev->dev.class_data[CUSTOM_HID_INTERFACE]; + + switch (hid->data[0]){ + case 0x11U: + if (RESET != hid->data[1]) { + gd_eval_led_on(LED5); + } else { + gd_eval_led_off(LED5); + } + break; + + case 0x12U: + if (RESET != hid->data[1]) { + gd_eval_led_on(LED2); + } else { + gd_eval_led_off(LED2); + } + break; + + case 0x13U: + if (RESET != hid->data[1]) { + gd_eval_led_on(LED3); + } else { + gd_eval_led_off(LED3); + } + break; + + case 0x14U: + if (RESET != hid->data[1]) { + gd_eval_led_on(LED4); + } else { + gd_eval_led_off(LED4); + } + break; + + default: + break; + } + + usbd_ep_recev (udev, CUSTOMHID_IN_EP, hid->data, 2U); + + return USBD_OK; +} diff --git a/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/device/class/hid/Source/standard_hid_core.c b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/device/class/hid/Source/standard_hid_core.c new file mode 100644 index 0000000000..90353516c8 --- /dev/null +++ b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/device/class/hid/Source/standard_hid_core.c @@ -0,0 +1,390 @@ +/*! + \file standard_hid_core.c + \brief HID class driver + + \version 2020-07-17, V3.0.0, firmware for GD32F10x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "standard_hid_core.h" + +#include + +#define USBD_VID 0x28e9U +#define USBD_PID 0x0380U + +/* Note:it should use the C99 standard when compiling the below codes */ +/* USB standard device descriptor */ +const usb_desc_dev hid_dev_desc = +{ + .header = + { + .bLength = USB_DEV_DESC_LEN, + .bDescriptorType = USB_DESCTYPE_DEV + }, + .bcdUSB = 0x0200U, + .bDeviceClass = 0x00U, + .bDeviceSubClass = 0x00U, + .bDeviceProtocol = 0x00U, + .bMaxPacketSize0 = USB_FS_EP0_MAX_LEN, + .idVendor = USBD_VID, + .idProduct = USBD_PID, + .bcdDevice = 0x0100U, + .iManufacturer = STR_IDX_MFC, + .iProduct = STR_IDX_PRODUCT, + .iSerialNumber = STR_IDX_SERIAL, + .bNumberConfigurations = USBD_CFG_MAX_NUM +}; + +const usb_hid_desc_config_set hid_config_desc = +{ + .config = + { + .header = + { + .bLength = sizeof(usb_desc_config), + .bDescriptorType = USB_DESCTYPE_CONFIG + }, + .wTotalLength = USB_HID_CONFIG_DESC_LEN, + .bNumInterfaces = 0x01U, + .bConfigurationValue = 0x01U, + .iConfiguration = 0x00U, + .bmAttributes = 0xA0U, + .bMaxPower = 0x32U + }, + + .hid_itf = + { + .header = + { + .bLength = sizeof(usb_desc_itf), + .bDescriptorType = USB_DESCTYPE_ITF + }, + .bInterfaceNumber = 0x00U, + .bAlternateSetting = 0x00U, + .bNumEndpoints = 0x01U, + .bInterfaceClass = USB_HID_CLASS, + .bInterfaceSubClass = USB_HID_SUBCLASS_BOOT_ITF, + .bInterfaceProtocol = USB_HID_PROTOCOL_KEYBOARD, + .iInterface = 0x00U + }, + + .hid_vendor = + { + .header = + { + .bLength = sizeof(usb_desc_hid), + .bDescriptorType = USB_DESCTYPE_HID + }, + .bcdHID = 0x0111U, + .bCountryCode = 0x00U, + .bNumDescriptors = 0x01U, + .bDescriptorType = USB_DESCTYPE_REPORT, + .wDescriptorLength = USB_HID_REPORT_DESC_LEN, + }, + + .hid_epin = + { + .header = + { + .bLength = sizeof(usb_desc_ep), + .bDescriptorType = USB_DESCTYPE_EP + }, + .bEndpointAddress = HID_IN_EP, + .bmAttributes = USB_EP_ATTR_INT, + .wMaxPacketSize = HID_IN_PACKET, + .bInterval = 0x40U + } +}; + +/* USB language ID Descriptor */ +const usb_desc_LANGID usbd_language_id_desc = +{ + .header = + { + .bLength = sizeof(usb_desc_LANGID), + .bDescriptorType = USB_DESCTYPE_STR + }, + .wLANGID = ENG_LANGID +}; + +/* USB manufacture string */ +static const usb_desc_str manufacturer_string = +{ + .header = + { + .bLength = USB_STRING_LEN(10U), + .bDescriptorType = USB_DESCTYPE_STR, + }, + .unicode_string = {'G', 'i', 'g', 'a', 'D', 'e', 'v', 'i', 'c', 'e'} +}; + +/* USB product string */ +static const usb_desc_str product_string = +{ + .header = + { + .bLength = USB_STRING_LEN(17U), + .bDescriptorType = USB_DESCTYPE_STR, + }, + .unicode_string = {'G', 'D', '3', '2', '-','U', 'S', 'B', '_', 'K', 'e', 'y', 'b', 'o', 'a', 'r', 'd'} +}; + +/* USBD serial string */ +static usb_desc_str serial_string = +{ + .header = + { + .bLength = USB_STRING_LEN(12U), + .bDescriptorType = USB_DESCTYPE_STR, + } +}; + +void *const usbd_hid_strings[] = +{ + [STR_IDX_LANGID] = (uint8_t *)&usbd_language_id_desc, + [STR_IDX_MFC] = (uint8_t *)&manufacturer_string, + [STR_IDX_PRODUCT] = (uint8_t *)&product_string, + [STR_IDX_SERIAL] = (uint8_t *)&serial_string +}; + +usb_desc hid_desc = { + .dev_desc = (uint8_t *)&hid_dev_desc, + .config_desc = (uint8_t *)&hid_config_desc, + .strings = usbd_hid_strings +}; + +const uint8_t hid_report_desc[USB_HID_REPORT_DESC_LEN] = +{ + 0x05, 0x01, /* USAGE_PAGE (Generic Desktop) */ + 0x09, 0x06, /* USAGE (Keyboard) */ + 0xa1, 0x01, /* COLLECTION (Application) */ + + 0x05, 0x07, /* USAGE_PAGE (Keyboard/Keypad) */ + 0x19, 0xe0, /* USAGE_MINIMUM (Keyboard LeftControl) */ + 0x29, 0xe7, /* USAGE_MAXIMUM (Keyboard Right GUI) */ + 0x15, 0x00, /* LOGICAL_MINIMUM (0) */ + 0x25, 0x01, /* LOGICAL_MAXIMUM (1) */ + 0x95, 0x08, /* REPORT_COUNT (8) */ + 0x75, 0x01, /* REPORT_SIZE (1) */ + 0x81, 0x02, /* INPUT (Data,Var,Abs) */ + + 0x95, 0x01, /* REPORT_COUNT (1) */ + 0x75, 0x08, /* REPORT_SIZE (8) */ + 0x81, 0x03, /* INPUT (Cnst,Var,Abs) */ + + 0x95, 0x06, /* REPORT_COUNT (6) */ + 0x75, 0x08, /* REPORT_SIZE (8) */ + 0x15, 0x00, /* LOGICAL_MINIMUM (0) */ + 0x26, 0xFF, 0x00, /* LOGICAL_MAXIMUM (255) */ + 0x05, 0x07, /* USAGE_PAGE (Keyboard/Keypad) */ + 0x19, 0x00, /* USAGE_MINIMUM (Reserved (no event indicated)) */ + 0x29, 0x65, /* USAGE_MAXIMUM (Keyboard Application) */ + 0x81, 0x00, /* INPUT (Data,Ary,Abs) */ + + 0xc0 /* END_COLLECTION */ +}; + +/* local function prototypes ('static') */ +static uint8_t hid_init (usb_dev *udev, uint8_t config_index); +static uint8_t hid_deinit (usb_dev *udev, uint8_t config_index); +static uint8_t hid_req (usb_dev *udev, usb_req *req); +static uint8_t hid_data_in (usb_dev *udev, uint8_t ep_num); + +usb_class_core usbd_hid_cb = { + .command = NO_CMD, + .alter_set = 0U, + + .init = hid_init, + .deinit = hid_deinit, + .req_proc = hid_req, + .data_in = hid_data_in +}; + +/*! + \brief register HID interface operation functions + \param[in] udev: pointer to USB device instance + \param[in] hid_fop: HID operation function structure + \param[out] none + \retval USB device operation status +*/ +uint8_t hid_itfop_register (usb_dev *udev, hid_fop_handler *hid_fop) +{ + if (NULL != hid_fop) { + udev->dev.user_data = (void *)hid_fop; + + return USBD_OK; + } + + return USBD_FAIL; +} + +/*! + \brief send keyboard report + \param[in] udev: pointer to USB device instance + \param[in] report: pointer to HID report + \param[in] len: data length + \param[out] none + \retval USB device operation status +*/ +uint8_t hid_report_send (usb_dev *udev, uint8_t *report, uint32_t len) +{ + standard_hid_handler *hid = (standard_hid_handler *)udev->dev.class_data[USBD_HID_INTERFACE]; + + hid->prev_transfer_complete = 0U; + + usbd_ep_send(udev, HID_IN_EP, report, len); + + return USBD_OK; +} + +/*! + \brief initialize the HID device + \param[in] udev: pointer to USB device instance + \param[in] config_index: configuration index + \param[out] none + \retval USB device operation status +*/ +static uint8_t hid_init (usb_dev *udev, uint8_t config_index) +{ + static standard_hid_handler hid_handler; + + memset((void *)&hid_handler, 0U, sizeof(standard_hid_handler)); + + /* initialize the data TX endpoint */ + usbd_ep_setup (udev, &(hid_config_desc.hid_epin)); + + hid_handler.prev_transfer_complete = 1U; + + udev->dev.class_data[USBD_HID_INTERFACE] = (void *)&hid_handler; + + if (NULL != udev->dev.user_data) { + ((hid_fop_handler *)udev->dev.user_data)->hid_itf_config(); + } + + return USBD_OK; +} + +/*! + \brief deinitialize the HID device + \param[in] udev: pointer to USB device instance + \param[in] config_index: configuration index + \param[out] none + \retval USB device operation status +*/ +static uint8_t hid_deinit (usb_dev *udev, uint8_t config_index) +{ + /* deinitialize HID endpoints */ + usbd_ep_clear(udev, HID_IN_EP); + + return USBD_OK; +} + +/*! + \brief handle the HID class-specific requests + \param[in] udev: pointer to USB device instance + \param[in] req: device class-specific request + \param[out] none + \retval USB device operation status +*/ +static uint8_t hid_req (usb_dev *udev, usb_req *req) +{ + usb_transc *transc = &udev->dev.transc_in[0]; + + standard_hid_handler *hid = (standard_hid_handler *)udev->dev.class_data[USBD_HID_INTERFACE]; + + switch (req->bRequest) { + case GET_REPORT: + /* no use for this driver */ + break; + + case GET_IDLE: + transc->xfer_buf = (uint8_t *)&hid->idle_state; + + transc->remain_len = 1U; + break; + + case GET_PROTOCOL: + transc->xfer_buf = (uint8_t *)&hid->protocol; + + transc->remain_len = 1U; + break; + + case SET_REPORT: + /* no use for this driver */ + break; + + case SET_IDLE: + hid->idle_state = (uint8_t)(req->wValue >> 8U); + break; + + case SET_PROTOCOL: + hid->protocol = (uint8_t)(req->wValue); + break; + + case USB_GET_DESCRIPTOR: + if (USB_DESCTYPE_REPORT == (req->wValue >> 8U)) { + transc->remain_len = USB_MIN(USB_HID_REPORT_DESC_LEN, req->wLength); + transc->xfer_buf = (uint8_t *)hid_report_desc; + + return REQ_SUPP; + } else if (USB_DESCTYPE_HID == (req->wValue >> 8U)) { + transc->remain_len = USB_MIN(9U, req->wLength); + transc->xfer_buf = (uint8_t *)(&(hid_config_desc.hid_vendor)); + } + break; + + default: + break; + } + + return USBD_OK; +} + +/*! + \brief handle data stage + \param[in] udev: pointer to USB device instance + \param[in] ep_num: endpoint identifier + \param[out] none + \retval USB device operation status +*/ +static uint8_t hid_data_in (usb_dev *udev, uint8_t ep_num) +{ + standard_hid_handler *hid = (standard_hid_handler *)udev->dev.class_data[USBD_HID_INTERFACE]; + + if (0U != hid->data[2]) { + hid->data[2] = 0x00U; + + usbd_ep_send(udev, HID_IN_EP, hid->data, HID_IN_PACKET); + } else { + hid->prev_transfer_complete = 1U; + } + + return USBD_OK; +} diff --git a/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/device/class/iap/Include/usb_iap_core.h b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/device/class/iap/Include/usb_iap_core.h new file mode 100644 index 0000000000..1f091eacc2 --- /dev/null +++ b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/device/class/iap/Include/usb_iap_core.h @@ -0,0 +1,87 @@ +/*! + \file usb_iap_core.h + \brief the header file of IAP driver + + \version 2020-07-17, V3.0.0, firmware for GD32F10x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef __USB_IAP_CORE_H +#define __USB_IAP_CORE_H + +#include "usbd_enum.h" +#include "usb_hid.h" + +#define USB_SERIAL_STRING_SIZE 0x06U + +#ifdef USE_USB_FS + #define USB_DESC_LEN_IAP_REPORT 35U +#endif +#define USB_DESC_LEN_IAP_CONFIG_SET 41U + +/* special commands with download request */ +#define IAP_OPTION_BYTE1 0x01U +#define IAP_ERASE 0x02U +#define IAP_DNLOAD 0x03U +#define IAP_LEAVE 0x04U +#define IAP_GETBIN_ADDRESS 0x05U +#define IAP_OPTION_BYTE2 0x06U + +typedef struct +{ + uint8_t report_buf[IAP_OUT_PACKET + 1U]; + uint8_t option_byte[IAP_IN_PACKET]; + + /* state machine variables */ + uint8_t dev_status[IAP_IN_PACKET]; + uint8_t bin_addr[IAP_IN_PACKET]; + + uint8_t reportID; + uint8_t flag; + + uint32_t protocol; + uint32_t idlestate; + + uint16_t transfer_times; + uint16_t page_count; + uint16_t lps; /* last packet size */ + uint32_t file_length; + uint32_t base_address; +} usbd_iap_handler; + +typedef void (*app_func) (void); + +extern usb_desc iap_desc; +extern usb_class_core iap_class; + +/* function declarations */ +/* send IAP report */ +uint8_t iap_report_send (usb_dev *udev, uint8_t *report, uint32_t len); + +#endif /* __USB_IAP_CORE_H */ diff --git a/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/device/class/iap/Source/usb_iap_core.c b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/device/class/iap/Source/usb_iap_core.c new file mode 100644 index 0000000000..5e2adce144 --- /dev/null +++ b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/device/class/iap/Source/usb_iap_core.c @@ -0,0 +1,563 @@ +/*! + \file usb_iap_core.c + \brief IAP driver + + \version 2020-07-17, V3.0.0, firmware for GD32F10x + \version 2020-12-07, V3.0.1, firmware for GD32F10x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "usb_iap_core.h" +#include "flash_operation.h" + +#include + +#define USBD_VID 0x28E9U +#define USBD_PID 0x0228U + +/* Note:it should use the C99 standard when compiling the below codes */ +/* USB standard device descriptor */ +__ALIGN_BEGIN const usb_desc_dev iap_dev_desc __ALIGN_END = +{ + .header = + { + .bLength = USB_DEV_DESC_LEN, + .bDescriptorType = USB_DESCTYPE_DEV + }, + .bcdUSB = 0x0200U, + .bDeviceClass = 0x00U, + .bDeviceSubClass = 0x00U, + .bDeviceProtocol = 0x00U, + .bMaxPacketSize0 = USB_FS_EP0_MAX_LEN, + .idVendor = USBD_VID, + .idProduct = USBD_PID, + .bcdDevice = 0x0100U, + .iManufacturer = STR_IDX_MFC, + .iProduct = STR_IDX_PRODUCT, + .iSerialNumber = STR_IDX_SERIAL, + .bNumberConfigurations = USBD_CFG_MAX_NUM +}; + +__ALIGN_BEGIN const usb_hid_desc_config_set iap_config_desc __ALIGN_END = +{ + .config = + { + .header = + { + .bLength = sizeof(usb_desc_config), + .bDescriptorType = USB_DESCTYPE_CONFIG + }, + .wTotalLength = USB_DESC_LEN_IAP_CONFIG_SET, + .bNumInterfaces = 0x01U, + .bConfigurationValue = 0x01U, + .iConfiguration = 0x00U, + .bmAttributes = 0x80U, + .bMaxPower = 0x32U + }, + + .hid_itf = + { + .header = + { + .bLength = sizeof(usb_desc_itf), + .bDescriptorType = USB_DESCTYPE_ITF + }, + .bInterfaceNumber = 0x00U, + .bAlternateSetting = 0x00U, + .bNumEndpoints = 0x02U, + .bInterfaceClass = USB_HID_CLASS, + .bInterfaceSubClass = 0x00U, + .bInterfaceProtocol = 0x00U, + .iInterface = 0x00U + }, + + .hid_vendor = + { + .header = + { + .bLength = sizeof(usb_desc_hid), + .bDescriptorType = USB_DESCTYPE_HID + }, + .bcdHID = 0x0111U, + .bCountryCode = 0x00U, + .bNumDescriptors = 0x01U, + .bDescriptorType = USB_DESCTYPE_REPORT, + .wDescriptorLength = USB_DESC_LEN_IAP_REPORT, + }, + + .hid_epin = + { + .header = + { + .bLength = sizeof(usb_desc_ep), + .bDescriptorType = USB_DESCTYPE_EP + }, + .bEndpointAddress = IAP_IN_EP, + .bmAttributes = USB_EP_ATTR_INT, + .wMaxPacketSize = IAP_IN_PACKET, + .bInterval = 0x01U + }, + + .hid_epout = + { + .header = + { + .bLength = sizeof(usb_desc_ep), + .bDescriptorType = USB_DESCTYPE_EP + }, + .bEndpointAddress = IAP_OUT_EP, + .bmAttributes = USB_EP_ATTR_INT, + .wMaxPacketSize = IAP_OUT_PACKET, + .bInterval = 0x01U + } +}; + +/* USB language ID Descriptor */ +static __ALIGN_BEGIN const usb_desc_LANGID usbd_language_id_desc __ALIGN_END = +{ + .header = + { + .bLength = sizeof(usb_desc_LANGID), + .bDescriptorType = USB_DESCTYPE_STR + }, + .wLANGID = ENG_LANGID +}; + +/* USB manufacture string */ +static __ALIGN_BEGIN const usb_desc_str manufacturer_string __ALIGN_END = +{ + .header = + { + .bLength = USB_STRING_LEN(10U), + .bDescriptorType = USB_DESCTYPE_STR, + }, + .unicode_string = {'G', 'i', 'g', 'a', 'D', 'e', 'v', 'i', 'c', 'e'} +}; + +/* USB product string */ +static __ALIGN_BEGIN const usb_desc_str product_string __ALIGN_END = +{ + .header = + { + .bLength = USB_STRING_LEN(12U), + .bDescriptorType = USB_DESCTYPE_STR, + }, + .unicode_string = {'G', 'D', '3', '2', '-', 'U', 'S', 'B', '_', 'I', 'A', 'P'} +}; + +/* USBD serial string */ +static __ALIGN_BEGIN usb_desc_str serial_string __ALIGN_END = +{ + .header = + { + .bLength = USB_STRING_LEN(2U), + .bDescriptorType = USB_DESCTYPE_STR, + } +}; + +void *const usbd_iap_strings[] = +{ + [STR_IDX_LANGID] = (uint8_t *)&usbd_language_id_desc, + [STR_IDX_MFC] = (uint8_t *)&manufacturer_string, + [STR_IDX_PRODUCT] = (uint8_t *)&product_string, + [STR_IDX_SERIAL] = (uint8_t *)&serial_string +}; + +usb_desc iap_desc = { + .dev_desc = (uint8_t *)&iap_dev_desc, + .config_desc = (uint8_t *)&iap_config_desc, + .strings = usbd_iap_strings +}; + +/* local function prototypes ('static') */ +static uint8_t iap_init (usb_dev *udev, uint8_t config_index); +static uint8_t iap_deinit (usb_dev *udev, uint8_t config_index); +static uint8_t iap_req_handler (usb_dev *udev, usb_req *req); +static uint8_t iap_data_out (usb_dev *udev, uint8_t ep_num); + +/* IAP requests management functions */ +static void iap_req_erase (usb_dev *udev); +static void iap_req_dnload (usb_dev *udev); +static void iap_req_optionbyte(usb_dev *udev, uint8_t option_num); +static void iap_req_leave (usb_dev *udev); +static void iap_address_send (usb_dev *udev); + +usb_class_core iap_class = { + .init = iap_init, + .deinit = iap_deinit, + .req_proc = iap_req_handler, + .data_out = iap_data_out +}; + +/* USB custom HID device report descriptor */ +__ALIGN_BEGIN const uint8_t iap_report_desc[USB_DESC_LEN_IAP_REPORT] __ALIGN_END = +{ + 0x05, 0x01, /* USAGE_PAGE (Generic Desktop) */ + 0x09, 0x00, /* USAGE (Custom Device) */ + 0xa1, 0x01, /* COLLECTION (Application) */ + + /* IAP command and data */ + 0x85, 0x01, /* REPORT_ID (0x01) */ + 0x09, 0x01, /* USAGE (IAP command) */ + 0x15, 0x00, /* LOGICAL_MINIMUM (0) */ + 0x25, 0xff, /* LOGICAL_MAXIMUM (255) */ + 0x75, 0x08, /* REPORT_SIZE (8) */ + 0x95, REPORT_OUT_COUNT, + 0x91, 0x82, /* OUTPUT (Data,Var,Abs,Vol) */ + + /* device status and option byte */ + 0x85, 0x02, /* REPORT_ID (0x02) */ + 0x09, 0x02, /* USAGE (Status and option byte) */ + 0x15, 0x00, /* LOGICAL_MINIMUM (0) */ + 0x25, 0xff, /* LOGICAL_MAXIMUM (255) */ + 0x75, 0x08, /* REPORT_SIZE (8) */ + 0x95, REPORT_IN_COUNT, /* REPORT_COUNT (23) */ + 0x81, 0x82, /* INPUT (Data,Var,Abs,Vol) */ + + 0xc0 /* END_COLLECTION */ +}; + +/*! + \brief send IAP report + \param[in] udev: pointer to USB device instance + \param[in] report: pointer to HID report + \param[in] len: data length + \param[out] none + \retval USB device operation status +*/ +uint8_t iap_report_send (usb_dev *udev, uint8_t *report, uint32_t len) +{ + usbd_ep_send (udev, IAP_IN_EP, report, len); + + return USBD_OK; +} + +/*! + \brief initialize the IAP device + \param[in] udev: pointer to USB device instance + \param[in] config_index: configuration index + \param[out] none + \retval USB device operation status +*/ +static uint8_t iap_init (usb_dev *udev, uint8_t config_index) +{ + static __ALIGN_BEGIN usbd_iap_handler iap_handler __ALIGN_END; + + /* initialize TX endpoint */ + usbd_ep_setup(udev, &(iap_config_desc.hid_epin)); + + /* initialize RX endpoint */ + usbd_ep_setup(udev, &(iap_config_desc.hid_epout)); + + /* unlock the internal flash */ + fmc_unlock(); + + memset((void *)&iap_handler, 0U, sizeof(usbd_iap_handler)); + + /* prepare receive data */ + usbd_ep_recev(udev, IAP_OUT_EP, iap_handler.report_buf, IAP_OUT_PACKET); + + iap_handler.base_address = APP_LOADED_ADDR; + + udev->dev.class_data[USBD_IAP_INTERFACE] = (void *)&iap_handler; + + return USBD_OK; +} + +/*! + \brief deinitialize the IAP device + \param[in] udev: pointer to USB device instance + \param[in] config_index: configuration index + \param[out] none + \retval USB device operation status +*/ +static uint8_t iap_deinit (usb_dev *udev, uint8_t config_index) +{ + /* deinitialize IAP endpoints */ + usbd_ep_clear (udev, IAP_IN_EP); + usbd_ep_clear (udev, IAP_OUT_EP); + + /* lock the internal flash */ + fmc_lock(); + + return USBD_OK; +} + +/*! + \brief handle the IAP class-specific requests + \param[in] udev: pointer to USB device instance + \param[in] req: device class-specific request + \param[out] none + \retval USB device operation status +*/ +static uint8_t iap_req_handler (usb_dev *udev, usb_req *req) +{ + usb_transc *transc = &udev->dev.transc_in[0]; + + usbd_iap_handler *iap = (usbd_iap_handler *)udev->dev.class_data[USBD_IAP_INTERFACE]; + + switch (req->bRequest) { + case GET_REPORT: + /* no use for this driver */ + break; + + case GET_IDLE: + transc->xfer_buf = (uint8_t *)&iap->idlestate; + transc->remain_len = 1U; + break; + + case GET_PROTOCOL: + transc->xfer_buf = (uint8_t *)&iap->protocol; + transc->remain_len = 1U; + break; + + case SET_REPORT: + iap->reportID = (uint8_t)(req->wValue); + break; + + case SET_IDLE: + iap->idlestate = (uint8_t)(req->wValue >> 8U); + break; + + case SET_PROTOCOL: + iap->protocol = (uint8_t)(req->wValue); + break; + + case USB_GET_DESCRIPTOR: + if (USB_DESCTYPE_REPORT == (req->wValue >> 8U)) { + transc->remain_len = USB_MIN(USB_DESC_LEN_IAP_REPORT, req->wLength); + transc->xfer_buf = (uint8_t *)iap_report_desc; + } + break; + + default: + return USBD_FAIL; + } + + return USBD_OK; +} + +/*! + \brief handle data out stage + \param[in] udev: pointer to USB device instance + \param[in] ep_num: endpoint identifier + \param[out] none + \retval none +*/ +static uint8_t iap_data_out (usb_dev *udev ,uint8_t ep_num) +{ + usbd_iap_handler *iap = (usbd_iap_handler *)udev->dev.class_data[USBD_IAP_INTERFACE]; + + if (0x01U == iap->report_buf[0]) { + switch (iap->report_buf[1]) { + case IAP_DNLOAD: + iap_req_dnload(udev); + break; + + case IAP_ERASE: + iap_req_erase(udev); + break; + + case IAP_OPTION_BYTE1: + iap_req_optionbyte(udev, 0x01U); + break; + + case IAP_LEAVE: + iap_req_leave(udev); + break; + + case IAP_GETBIN_ADDRESS: + iap_address_send(udev); + break; + + case IAP_OPTION_BYTE2: + iap_req_optionbyte(udev, 0x02U); + break; + + default: + break; + } + } + + usbd_ep_recev(udev, IAP_OUT_EP, iap->report_buf, IAP_OUT_PACKET); + + return USBD_OK; +} + +/*! + \brief handle the IAP_DNLOAD request + \param[in] udev: pointer to USB device instance + \param[out] none + \retval none +*/ +static void iap_req_dnload(usb_dev *udev) +{ + usbd_iap_handler *iap = (usbd_iap_handler *)udev->dev.class_data[USBD_IAP_INTERFACE]; + + if (0U != iap->transfer_times) { + if (1U == iap->transfer_times) { + if (0U == iap->lps) { + iap_data_write(&iap->report_buf[2], iap->base_address, TRANSFER_SIZE); + } else { + iap_data_write(&iap->report_buf[2], iap->base_address, iap->file_length % TRANSFER_SIZE); + iap->lps = 0U; + } + + iap->dev_status[0] = 0x02U; + iap->dev_status[1] = 0x02U; + iap_report_send (udev, iap->dev_status, IAP_IN_PACKET); + } else { + iap_data_write(&iap->report_buf[2], iap->base_address, TRANSFER_SIZE); + + iap->base_address += TRANSFER_SIZE; + } + + iap->transfer_times--; + } +} + +/*! + \brief handle the IAP_ERASE request + \param[in] udev: pointer to USB device instance + \param[out] none + \retval none +*/ +static void iap_req_erase(usb_dev *udev) +{ + uint32_t addr = 0U; + + usbd_iap_handler *iap = (usbd_iap_handler *)udev->dev.class_data[USBD_IAP_INTERFACE]; + + /* get base address to erase */ + iap->base_address = iap->report_buf[2]; + iap->base_address |= iap->report_buf[3] << 8U; + iap->base_address |= iap->report_buf[4] << 16U; + iap->base_address |= iap->report_buf[5] << 24U; + + /* get file length */ + iap->file_length = iap->report_buf[7]; + iap->file_length |= iap->report_buf[8] << 8U; + iap->file_length |= iap->report_buf[9] << 16U; + iap->file_length |= iap->report_buf[10] << 24U; + + iap->lps = iap->file_length % TRANSFER_SIZE; + if (0U == iap->lps) { + iap->transfer_times = iap->file_length / TRANSFER_SIZE; + } else { + iap->transfer_times = iap->file_length / TRANSFER_SIZE + 1U; + } + + /* check if the address is in protected area */ + if (IS_PROTECTED_AREA(iap->base_address)) { + return; + } + + addr = iap->base_address; + + /* unlock the flash program erase controller */ + fmc_unlock(); + + flash_erase(addr, iap->file_length, iap->report_buf); + + fmc_lock(); + + iap->dev_status[0] = 0x02U; + iap->dev_status[1] = 0x01U; + + usbd_ep_send(udev, IAP_IN_EP, iap->dev_status, IAP_IN_PACKET); +} + +/*! + \brief handle the IAP_OPTION_BYTE request + \param[in] udev: pointer to USB device instance + \param[in] option_num: number of option byte + \param[out] none + \retval none +*/ +static void iap_req_optionbyte(usb_dev *udev, uint8_t option_num) +{ + uint8_t i = 0U; + uint32_t address = 0U; + + usbd_iap_handler *iap = (usbd_iap_handler *)udev->dev.class_data[USBD_IAP_INTERFACE]; + + iap->option_byte[0]= 0x02U; + + if (0x01U == option_num) { + address = OPT_BYTE_ADDR1; +#ifdef OPT_BYTE_ADDR2 + } else if (0x02U == option_num) { + address = OPT_BYTE_ADDR2; +#endif + } else { + return; + } + + for (i = 1U; i < 17U; i++) { + iap->option_byte[i] = *(uint8_t *)address; + address++; + } + + iap_report_send (udev, iap->option_byte, IAP_IN_PACKET); +} + +/*! + \brief handle the IAP_LEAVE request + \param[in] udev: pointer to USB device instance + \param[out] none + \retval none +*/ +static void iap_req_leave(usb_dev *udev) +{ + /* lock the internal flash */ + fmc_lock(); + + /* generate system reset to allow jumping to the user code */ + NVIC_SystemReset(); +} + +/*! + \brief handle the IAP_SEND_ADDRESS request + \param[in] udev: pointer to USB device instance + \param[out] none + \retval none +*/ +static void iap_address_send(usb_dev *udev) +{ + usbd_iap_handler *iap = (usbd_iap_handler *)udev->dev.class_data[USBD_IAP_INTERFACE]; + + iap->bin_addr[0] = 0x02U; + + iap->bin_addr[1] = (uint8_t)(APP_LOADED_ADDR); + iap->bin_addr[2] = (uint8_t)(APP_LOADED_ADDR >> 8U); + iap->bin_addr[3] = (uint8_t)(APP_LOADED_ADDR >> 16U); + iap->bin_addr[4] = (uint8_t)(APP_LOADED_ADDR >> 24U); + + iap_report_send (udev, iap->bin_addr, IAP_IN_PACKET); +} diff --git a/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/device/class/msc/Include/usbd_msc_bbb.h b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/device/class/msc/Include/usbd_msc_bbb.h new file mode 100644 index 0000000000..f97dcac2b8 --- /dev/null +++ b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/device/class/msc/Include/usbd_msc_bbb.h @@ -0,0 +1,101 @@ +/*! + \file usbd_msc_bbb.h + \brief the header file of the usbd_msc_bot.c file + + \version 2020-07-17, V3.0.0, firmware for GD32F10x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef __USBD_MSC_BBB_H +#define __USBD_MSC_BBB_H + +#include "usbd_core.h" +#include "msc_bbb.h" +#include "usbd_msc_mem.h" +#include "usbd_msc_scsi.h" + +/* MSC BBB state */ +enum msc_bbb_state { + BBB_IDLE = 0U, /*!< idle state */ + BBB_DATA_OUT, /*!< data OUT state */ + BBB_DATA_IN, /*!< data IN state */ + BBB_LAST_DATA_IN, /*!< last data IN state */ + BBB_SEND_DATA /*!< send immediate data state */ +}; + +/* MSC BBB status */ +enum msc_bbb_status { + BBB_STATUS_NORMAL = 0U, /*!< normal status */ + BBB_STATUS_RECOVERY, /*!< recovery status*/ + BBB_STATUS_ERROR /*!< error status */ +}; + +typedef struct +{ + uint8_t bbb_data[MSC_MEDIA_PACKET_SIZE]; + + uint8_t max_lun; + uint8_t bbb_state; + uint8_t bbb_status; + + uint32_t bbb_datalen; + + msc_bbb_cbw bbb_cbw; + msc_bbb_csw bbb_csw; + + uint8_t scsi_sense_head; + uint8_t scsi_sense_tail; + + uint32_t scsi_blk_size[MEM_LUN_NUM]; + uint32_t scsi_blk_nbr[MEM_LUN_NUM]; + + uint32_t scsi_blk_addr; + uint32_t scsi_blk_len; + uint32_t scsi_disk_pop; + + msc_scsi_sense scsi_sense[SENSE_LIST_DEEPTH]; +} usbd_msc_handler; + +/* function declarations */ +/* initialize the bbb process */ +void msc_bbb_init (usb_core_driver *udev); +/* reset the BBB machine */ +void msc_bbb_reset (usb_core_driver *udev); +/* deinitialize the BBB machine */ +void msc_bbb_deinit (usb_core_driver *udev); +/* handle BBB data IN stage */ +void msc_bbb_data_in (usb_core_driver *udev, uint8_t ep_num); +/* handle BBB data OUT stage */ +void msc_bbb_data_out (usb_core_driver *udev, uint8_t ep_num); +/* send the CSW(command status wrapper) */ +void msc_bbb_csw_send (usb_core_driver *udev, uint8_t csw_status); +/* complete the clear feature request */ +void msc_bbb_clrfeature (usb_core_driver *udev, uint8_t ep_num); + +#endif /* __USBD_MSC_BBB_H */ diff --git a/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/device/class/msc/Include/usbd_msc_core.h b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/device/class/msc/Include/usbd_msc_core.h new file mode 100644 index 0000000000..7c47554914 --- /dev/null +++ b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/device/class/msc/Include/usbd_msc_core.h @@ -0,0 +1,59 @@ +/*! + \file usbd_msc_core.h + \brief the header file of USB MSC device class core functions + + \version 2020-07-17, V3.0.0, firmware for GD32F10x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef __USBD_MSC_CORE_H +#define __USBD_MSC_CORE_H + +#include "usbd_core.h" +#include "usb_msc.h" + +#define USB_MSC_CONFIG_DESC_SIZE 32U + +#define MSC_EPIN_SIZE MSC_DATA_PACKET_SIZE +#define MSC_EPOUT_SIZE MSC_DATA_PACKET_SIZE + +/* USB configuration descriptor structure */ +typedef struct +{ + usb_desc_config config; + + usb_desc_itf msc_itf; + usb_desc_ep msc_epin; + usb_desc_ep msc_epout; +} usb_desc_config_set; + +extern usb_desc msc_desc; +extern usb_class_core msc_class; + +#endif /* __USBD_MSC_CORE_H */ diff --git a/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/device/class/msc/Include/usbd_msc_data.h b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/device/class/msc/Include/usbd_msc_data.h new file mode 100644 index 0000000000..7f038ec568 --- /dev/null +++ b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/device/class/msc/Include/usbd_msc_data.h @@ -0,0 +1,49 @@ +/*! + \file usbd_msc_data.h + \brief the header file of the usbd_msc_data.c file + + \version 2020-07-17, V3.0.0, firmware for GD32F10x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef __USBD_MSC_DATA_H +#define __USBD_MSC_DATA_H + +#include "usbd_conf.h" + +#define MODE_SENSE6_LENGTH 8U +#define MODE_SENSE10_LENGTH 8U +#define INQUIRY_PAGE00_LENGTH 96U +#define FORMAT_CAPACITIES_LENGTH 20U + +extern const uint8_t msc_page00_inquiry_data[]; +extern const uint8_t msc_mode_sense6_data[]; +extern const uint8_t msc_mode_sense10_data[]; + +#endif /* __USBD_MSC_DATA_H */ diff --git a/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/device/class/msc/Include/usbd_msc_mem.h b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/device/class/msc/Include/usbd_msc_mem.h new file mode 100644 index 0000000000..a992e0182e --- /dev/null +++ b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/device/class/msc/Include/usbd_msc_mem.h @@ -0,0 +1,59 @@ +/*! + \file usbd_msc_mem.h + \brief header file for storage memory + + \version 2020-07-17, V3.0.0, firmware for GD32F10x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef __USBD_MSC_MEM_H +#define __USBD_MSC_MEM_H + +#include "usbd_conf.h" + +#define USBD_STD_INQUIRY_LENGTH 36U + +typedef struct +{ + int8_t (*mem_init) (uint8_t lun); + int8_t (*mem_ready) (uint8_t lun); + int8_t (*mem_protected) (uint8_t lun); + int8_t (*mem_read) (uint8_t lun, uint8_t *buf, uint32_t block_addr, uint16_t block_len); + int8_t (*mem_write) (uint8_t lun, uint8_t *buf, uint32_t block_addr, uint16_t block_len); + int8_t (*mem_maxlun) (void); + + uint8_t *mem_toc_data; + uint8_t *mem_inquiry_data[MEM_LUN_NUM]; + uint32_t mem_block_size[MEM_LUN_NUM]; + uint32_t mem_block_len[MEM_LUN_NUM]; +}usbd_mem_cb; + +extern usbd_mem_cb *usbd_mem_fops; + +#endif /* __USBD_MSC_MEM_H */ diff --git a/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/device/class/msc/Include/usbd_msc_scsi.h b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/device/class/msc/Include/usbd_msc_scsi.h new file mode 100644 index 0000000000..1123541b77 --- /dev/null +++ b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/device/class/msc/Include/usbd_msc_scsi.h @@ -0,0 +1,50 @@ +/*! + \file usbd_msc_scsi.h + \brief the header file of the usbd_msc_scsi.c file + + \version 2020-07-17, V3.0.0, firmware for GD32F10x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef __USBD_MSC_SCSI_H +#define __USBD_MSC_SCSI_H + +#include "usbd_msc_data.h" +#include "usbd_msc_bbb.h" +#include "msc_scsi.h" + +#define SENSE_LIST_DEEPTH 4U + +/* function declarations */ +/* process SCSI commands */ +int8_t scsi_process_cmd (usb_core_driver *udev, uint8_t lun, uint8_t *cmd); +/* load the last error code in the error list */ +void scsi_sense_code (usb_core_driver *udev, uint8_t lun, uint8_t skey, uint8_t asc); + +#endif /* __USBD_MSC_SCSI_H */ diff --git a/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/device/class/msc/Source/usbd_msc_bbb.c b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/device/class/msc/Source/usbd_msc_bbb.c new file mode 100644 index 0000000000..773644a01d --- /dev/null +++ b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/device/class/msc/Source/usbd_msc_bbb.c @@ -0,0 +1,287 @@ +/*! + \file usbd_msc_bbb.c + \brief USB BBB(Bulk/Bulk/Bulk) protocol core functions + \note BBB means Bulk-only transport protocol for USB MSC + + \version 2020-07-17, V3.0.0, firmware for GD32F10x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "usbd_enum.h" +#include "usbd_msc_bbb.h" + +/* local function prototypes ('static') */ +static void msc_bbb_cbw_decode (usb_core_driver *udev); +static void msc_bbb_data_send (usb_core_driver *udev, uint8_t *pbuf, uint32_t Len); +static void msc_bbb_abort (usb_core_driver *udev); + +/*! + \brief initialize the bbb process + \param[in] udev: pointer to USB device instance + \param[out] none + \retval none +*/ +void msc_bbb_init (usb_core_driver *udev) +{ + uint8_t lun_num; + + usbd_msc_handler *msc = (usbd_msc_handler *)udev->dev.class_data[USBD_MSC_INTERFACE]; + + msc->bbb_state = BBB_IDLE; + msc->bbb_status = BBB_STATUS_NORMAL; + + /* initializes the storage logic unit */ + for(lun_num = 0U; lun_num < MEM_LUN_NUM; lun_num++) { + usbd_mem_fops->mem_init(lun_num); + } + + /* flush the RX FIFO */ + usbd_fifo_flush (udev, MSC_OUT_EP); + + /* flush the TX FIFO */ + usbd_fifo_flush (udev, MSC_IN_EP); + + /* prepare endpoint to receive the first BBB CBW */ + usbd_ep_recev (udev, MSC_OUT_EP, (uint8_t *)&msc->bbb_cbw, BBB_CBW_LENGTH); +} + +/*! + \brief reset the BBB machine + \param[in] udev: pointer to USB device instance + \param[out] none + \retval none +*/ +void msc_bbb_reset (usb_core_driver *udev) +{ + usbd_msc_handler *msc = (usbd_msc_handler *)udev->dev.class_data[USBD_MSC_INTERFACE]; + + msc->bbb_state = BBB_IDLE; + msc->bbb_status = BBB_STATUS_RECOVERY; + + /* prepare endpoint to receive the first BBB command */ + usbd_ep_recev (udev, MSC_OUT_EP, (uint8_t *)&msc->bbb_cbw, BBB_CBW_LENGTH); +} + +/*! + \brief deinitialize the BBB machine + \param[in] udev: pointer to USB device instance + \param[out] none + \retval none +*/ +void msc_bbb_deinit (usb_core_driver *udev) +{ + usbd_msc_handler *msc = (usbd_msc_handler *)udev->dev.class_data[USBD_MSC_INTERFACE]; + + msc->bbb_state = BBB_IDLE; +} + +/*! + \brief handle BBB data IN stage + \param[in] udev: pointer to USB device instance + \param[in] ep_num: endpoint number + \param[out] none + \retval none +*/ +void msc_bbb_data_in (usb_core_driver *udev, uint8_t ep_num) +{ + usbd_msc_handler *msc = (usbd_msc_handler *)udev->dev.class_data[USBD_MSC_INTERFACE]; + + switch (msc->bbb_state) { + case BBB_DATA_IN: + if (scsi_process_cmd (udev, msc->bbb_cbw.bCBWLUN, &msc->bbb_cbw.CBWCB[0]) < 0) { + msc_bbb_csw_send (udev, CSW_CMD_FAILED); + } + break; + + case BBB_SEND_DATA: + case BBB_LAST_DATA_IN: + msc_bbb_csw_send (udev, CSW_CMD_PASSED); + break; + + default: + break; + } +} + +/*! + \brief handle BBB data OUT stage + \param[in] udev: pointer to USB device instance + \param[in] ep_num: endpoint number + \param[out] none + \retval none +*/ +void msc_bbb_data_out (usb_core_driver *udev, uint8_t ep_num) +{ + usbd_msc_handler *msc = (usbd_msc_handler *)udev->dev.class_data[USBD_MSC_INTERFACE]; + + switch (msc->bbb_state) { + case BBB_IDLE: + msc_bbb_cbw_decode (udev); + break; + + case BBB_DATA_OUT: + if (scsi_process_cmd (udev, msc->bbb_cbw.bCBWLUN, &msc->bbb_cbw.CBWCB[0]) < 0) { + msc_bbb_csw_send (udev, CSW_CMD_FAILED); + } + break; + + default: + break; + } +} + +/*! + \brief send the CSW(command status wrapper) + \param[in] udev: pointer to USB device instance + \param[in] csw_status: CSW status + \param[out] none + \retval none +*/ +void msc_bbb_csw_send (usb_core_driver *udev, uint8_t csw_status) +{ + usbd_msc_handler *msc = (usbd_msc_handler *)udev->dev.class_data[USBD_MSC_INTERFACE]; + + msc->bbb_csw.dCSWSignature = BBB_CSW_SIGNATURE; + msc->bbb_csw.bCSWStatus = csw_status; + msc->bbb_state = BBB_IDLE; + + usbd_ep_send (udev, MSC_IN_EP, (uint8_t *)&msc->bbb_csw, BBB_CSW_LENGTH); + + /* prepare endpoint to receive next command */ + usbd_ep_recev (udev, MSC_OUT_EP, (uint8_t *)&msc->bbb_cbw, BBB_CBW_LENGTH); +} + +/*! + \brief complete the clear feature request + \param[in] udev: pointer to USB device instance + \param[in] ep_num: endpoint number + \param[out] none + \retval none +*/ +void msc_bbb_clrfeature (usb_core_driver *udev, uint8_t ep_num) +{ + usbd_msc_handler *msc = (usbd_msc_handler *)udev->dev.class_data[USBD_MSC_INTERFACE]; + + if (msc->bbb_status == BBB_STATUS_ERROR)/* bad CBW signature */ { + usbd_ep_stall(udev, MSC_IN_EP); + + msc->bbb_status = BBB_STATUS_NORMAL; + } else if(((ep_num & 0x80U) == 0x80U) && (msc->bbb_status != BBB_STATUS_RECOVERY)) { + msc_bbb_csw_send (udev, CSW_CMD_FAILED); + } else { + + } +} + +/*! + \brief decode the CBW command and set the BBB state machine accordingly + \param[in] udev: pointer to USB device instance + \param[out] none + \retval none +*/ +static void msc_bbb_cbw_decode (usb_core_driver *udev) +{ + usbd_msc_handler *msc = (usbd_msc_handler *)udev->dev.class_data[USBD_MSC_INTERFACE]; + + msc->bbb_csw.dCSWTag = msc->bbb_cbw.dCBWTag; + msc->bbb_csw.dCSWDataResidue = msc->bbb_cbw.dCBWDataTransferLength; + + if ((BBB_CBW_LENGTH != usbd_rxcount_get (udev, MSC_OUT_EP)) || + (BBB_CBW_SIGNATURE != msc->bbb_cbw.dCBWSignature)|| + (msc->bbb_cbw.bCBWLUN > 1U) || + (msc->bbb_cbw.bCBWCBLength < 1U) || + (msc->bbb_cbw.bCBWCBLength > 16U)) { + /* illegal command handler */ + scsi_sense_code (udev, msc->bbb_cbw.bCBWLUN, ILLEGAL_REQUEST, INVALID_CDB); + + msc->bbb_status = BBB_STATUS_ERROR; + + msc_bbb_abort (udev); + } else { + if (scsi_process_cmd (udev, msc->bbb_cbw.bCBWLUN, &msc->bbb_cbw.CBWCB[0]) < 0) { + msc_bbb_abort (udev); + } else if ((BBB_DATA_IN != msc->bbb_state) && + (BBB_DATA_OUT != msc->bbb_state) && + (BBB_LAST_DATA_IN != msc->bbb_state)) { /* burst xfer handled internally */ + if (msc->bbb_datalen > 0U) { + msc_bbb_data_send (udev, msc->bbb_data, msc->bbb_datalen); + } else if (0U == msc->bbb_datalen) { + msc_bbb_csw_send (udev, CSW_CMD_PASSED); + } else { + + } + } else { + + } + } +} + +/*! + \brief send the requested data + \param[in] udev: pointer to USB device instance + \param[in] buf: pointer to data buffer + \param[in] len: data length + \param[out] none + \retval none +*/ +static void msc_bbb_data_send (usb_core_driver *udev, uint8_t *buf, uint32_t len) +{ + usbd_msc_handler *msc = (usbd_msc_handler *)udev->dev.class_data[USBD_MSC_INTERFACE]; + + len = USB_MIN (msc->bbb_cbw.dCBWDataTransferLength, len); + + msc->bbb_csw.dCSWDataResidue -= len; + msc->bbb_csw.bCSWStatus = CSW_CMD_PASSED; + msc->bbb_state = BBB_SEND_DATA; + + usbd_ep_send (udev, MSC_IN_EP, buf, len); +} + +/*! + \brief abort the current transfer + \param[in] udev: pointer to USB device instance + \param[out] none + \retval none +*/ +static void msc_bbb_abort (usb_core_driver *udev) +{ + usbd_msc_handler *msc = (usbd_msc_handler *)udev->dev.class_data[USBD_MSC_INTERFACE]; + + if ((0U == msc->bbb_cbw.bmCBWFlags) && + (0U != msc->bbb_cbw.dCBWDataTransferLength) && + (BBB_STATUS_NORMAL == msc->bbb_status)) { + usbd_ep_stall(udev, MSC_OUT_EP); + } + + usbd_ep_stall(udev, MSC_IN_EP); + + if (msc->bbb_status == BBB_STATUS_ERROR) { + usbd_ep_recev (udev, MSC_OUT_EP, (uint8_t *)&msc->bbb_cbw, BBB_CBW_LENGTH); + } +} diff --git a/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/device/class/msc/Source/usbd_msc_core.c b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/device/class/msc/Source/usbd_msc_core.c new file mode 100644 index 0000000000..36cc11bc95 --- /dev/null +++ b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/device/class/msc/Source/usbd_msc_core.c @@ -0,0 +1,319 @@ +/*! + \file usbd_msc_core.c + \brief USB MSC device class core functions + + \version 2020-07-17, V3.0.0, firmware for GD32F10x + \version 2020-12-07, V3.0.1, firmware for GD32F10x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "usbd_enum.h" +#include "usbd_msc_bbb.h" +#include "usbd_msc_core.h" +#include + +#define USBD_VID 0x28E9U +#define USBD_PID 0x028FU + +/* local function prototypes ('static') */ +static uint8_t msc_core_init (usb_dev *udev, uint8_t config_index); +static uint8_t msc_core_deinit (usb_dev *udev, uint8_t config_index); +static uint8_t msc_core_req (usb_dev *udev, usb_req *req); +static uint8_t msc_core_in (usb_dev *udev, uint8_t ep_num); +static uint8_t msc_core_out (usb_dev *udev, uint8_t ep_num); + +usb_class_core msc_class = +{ + .init = msc_core_init, + .deinit = msc_core_deinit, + + .req_proc = msc_core_req, + + .data_in = msc_core_in, + .data_out = msc_core_out +}; + +/* note: it should use the C99 standard when compiling the below codes */ +/* USB standard device descriptor */ +__ALIGN_BEGIN const usb_desc_dev msc_dev_desc __ALIGN_END = +{ + .header = { + .bLength = USB_DEV_DESC_LEN, + .bDescriptorType = USB_DESCTYPE_DEV + }, + .bcdUSB = 0x0200U, + .bDeviceClass = 0x00U, + .bDeviceSubClass = 0x00U, + .bDeviceProtocol = 0x00U, + .bMaxPacketSize0 = USB_FS_EP0_MAX_LEN, + .idVendor = USBD_VID, + .idProduct = USBD_PID, + .bcdDevice = 0x0100U, + .iManufacturer = STR_IDX_MFC, + .iProduct = STR_IDX_PRODUCT, + .iSerialNumber = STR_IDX_SERIAL, + .bNumberConfigurations = USBD_CFG_MAX_NUM +}; + +/* USB device configuration descriptor */ +__ALIGN_BEGIN const usb_desc_config_set msc_config_desc __ALIGN_END = +{ + .config = + { + .header = { + .bLength = sizeof(usb_desc_config), + .bDescriptorType = USB_DESCTYPE_CONFIG + }, + .wTotalLength = USB_MSC_CONFIG_DESC_SIZE, + .bNumInterfaces = 0x01U, + .bConfigurationValue = 0x01U, + .iConfiguration = 0x00U, + .bmAttributes = 0xC0U, + .bMaxPower = 0x32U + }, + + .msc_itf = + { + .header = { + .bLength = sizeof(usb_desc_itf), + .bDescriptorType = USB_DESCTYPE_ITF + }, + .bInterfaceNumber = 0x00U, + .bAlternateSetting = 0x00U, + .bNumEndpoints = 0x02U, + .bInterfaceClass = USB_CLASS_MSC, + .bInterfaceSubClass = USB_MSC_SUBCLASS_SCSI, + .bInterfaceProtocol = USB_MSC_PROTOCOL_BBB, + .iInterface = 0x00U + }, + + .msc_epin = + { + .header = { + .bLength = sizeof(usb_desc_ep), + .bDescriptorType = USB_DESCTYPE_EP + }, + .bEndpointAddress = MSC_IN_EP, + .bmAttributes = USB_EP_ATTR_BULK, + .wMaxPacketSize = MSC_EPIN_SIZE, + .bInterval = 0x00U + }, + + .msc_epout = + { + .header = { + .bLength = sizeof(usb_desc_ep), + .bDescriptorType = USB_DESCTYPE_EP + }, + .bEndpointAddress = MSC_OUT_EP, + .bmAttributes = USB_EP_ATTR_BULK, + .wMaxPacketSize = MSC_EPOUT_SIZE, + .bInterval = 0x00U + } +}; + +/* USB language ID descriptor */ +__ALIGN_BEGIN const usb_desc_LANGID usbd_language_id_desc __ALIGN_END = +{ + .header = + { + .bLength = sizeof(usb_desc_LANGID), + .bDescriptorType = USB_DESCTYPE_STR + }, + .wLANGID = ENG_LANGID +}; + +/* USB manufacture string */ +static __ALIGN_BEGIN const usb_desc_str manufacturer_string __ALIGN_END = +{ + .header = + { + .bLength = USB_STRING_LEN(10U), + .bDescriptorType = USB_DESCTYPE_STR, + }, + .unicode_string = {'G', 'i', 'g', 'a', 'D', 'e', 'v', 'i', 'c', 'e'} +}; + +/* USB product string */ +static __ALIGN_BEGIN const usb_desc_str product_string __ALIGN_END = +{ + .header = + { + .bLength = USB_STRING_LEN(12U), + .bDescriptorType = USB_DESCTYPE_STR, + }, + .unicode_string = {'G', 'D', '3', '2', '-', 'U', 'S', 'B', '_', 'M', 'S', 'C'} +}; + +/* USBD serial string */ +static __ALIGN_BEGIN usb_desc_str serial_string __ALIGN_END = +{ + .header = + { + .bLength = USB_STRING_LEN(12U), + .bDescriptorType = USB_DESCTYPE_STR, + } +}; + +/* USB string descriptor */ +void *const usbd_msc_strings[] = +{ + [STR_IDX_LANGID] = (uint8_t *)&usbd_language_id_desc, + [STR_IDX_MFC] = (uint8_t *)&manufacturer_string, + [STR_IDX_PRODUCT] = (uint8_t *)&product_string, + [STR_IDX_SERIAL] = (uint8_t *)&serial_string +}; + +usb_desc msc_desc = { + .dev_desc = (uint8_t *)&msc_dev_desc, + .config_desc = (uint8_t *)&msc_config_desc, + .strings = usbd_msc_strings +}; + +static __ALIGN_BEGIN uint8_t usbd_msc_maxlun = 0U __ALIGN_END; + +/*! + \brief initialize the MSC device + \param[in] udev: pointer to USB device instance + \param[in] config_index: configuration index + \param[out] none + \retval USB device operation status +*/ +static uint8_t msc_core_init (usb_dev *udev, uint8_t config_index) +{ + static __ALIGN_BEGIN usbd_msc_handler msc_handler __ALIGN_END; + + memset((void *)&msc_handler, 0U, sizeof(usbd_msc_handler)); + + udev->dev.class_data[USBD_MSC_INTERFACE] = (void *)&msc_handler; + + /* configure MSC TX endpoint */ + usbd_ep_setup (udev, &(msc_config_desc.msc_epin)); + + /* configure MSC RX endpoint */ + usbd_ep_setup (udev, &(msc_config_desc.msc_epout)); + + /* initialize the BBB layer */ + msc_bbb_init(udev); + + return USBD_OK; +} + +/*! + \brief deinitialize the MSC device + \param[in] udev: pointer to USB device instance + \param[in] config_index: configuration index + \param[out] none + \retval USB device operation status +*/ +static uint8_t msc_core_deinit (usb_dev *udev, uint8_t config_index) +{ + /* clear MSC endpoints */ + usbd_ep_clear (udev, MSC_IN_EP); + usbd_ep_clear (udev, MSC_OUT_EP); + + /* deinitialize the BBB layer */ + msc_bbb_deinit(udev); + + return USBD_OK; +} + +/*! + \brief handle the MSC class-specific and standard requests + \param[in] udev: pointer to USB device instance + \param[in] req: device class-specific request + \param[out] none + \retval USB device operation status +*/ +static uint8_t msc_core_req (usb_dev *udev, usb_req *req) +{ + usb_transc *transc = &udev->dev.transc_in[0]; + + switch (req->bRequest) { + case BBB_GET_MAX_LUN : + if((0U == req->wValue) && + (1U == req->wLength) && + (0x80U == (req->bmRequestType & 0x80U))) { + usbd_msc_maxlun = (uint8_t)usbd_mem_fops->mem_maxlun(); + + transc->xfer_buf = &usbd_msc_maxlun; + transc->remain_len = 1U; + } else { + return USBD_FAIL; + } + break; + + case BBB_RESET : + if((0U == req->wValue) && + (0U == req->wLength) && + (0x80U != (req->bmRequestType & 0x80U))) { + msc_bbb_reset(udev); + } else { + return USBD_FAIL; + } + break; + + case USB_CLEAR_FEATURE: + msc_bbb_clrfeature (udev, (uint8_t)req->wIndex); + break; + + default: + return USBD_FAIL; + } + + return USBD_OK; +} + +/*! + \brief handle data in stage + \param[in] udev: pointer to USB device instance + \param[in] ep_num: the endpoint number + \param[out] none + \retval none +*/ +static uint8_t msc_core_in (usb_dev *udev, uint8_t ep_num) +{ + msc_bbb_data_in(udev, ep_num); + + return USBD_OK; +} + +/*! + \brief handle data out stage + \param[in] udev: pointer to USB device instance + \param[in] ep_num: the endpoint number + \param[out] none + \retval none +*/ +static uint8_t msc_core_out (usb_dev *udev, uint8_t ep_num) +{ + msc_bbb_data_out (udev, ep_num); + + return USBD_OK; +} diff --git a/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/device/class/msc/Source/usbd_msc_data.c b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/device/class/msc/Source/usbd_msc_data.c new file mode 100644 index 0000000000..e7084cdbac --- /dev/null +++ b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/device/class/msc/Source/usbd_msc_data.c @@ -0,0 +1,73 @@ +/*! + \file usbd_msc_data.c + \brief USB MSC vital inquiry pages and sense data + + \version 2020-07-17, V3.0.0, firmware for GD32F10x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "usbd_msc_data.h" + +/* USB mass storage page 0 inquiry data */ +const uint8_t msc_page00_inquiry_data[] = +{ + 0x00U, + 0x00U, + 0x00U, + 0x00U, + (INQUIRY_PAGE00_LENGTH - 4U), + 0x80U, + 0x83U, +}; + +/* USB mass storage sense 6 data */ +const uint8_t msc_mode_sense6_data[] = +{ + 0x00U, + 0x00U, + 0x00U, + 0x00U, + 0x00U, + 0x00U, + 0x00U, + 0x00U +}; + +/* USB mass storage sense 10 data */ +const uint8_t msc_mode_sense10_data[] = +{ + 0x00U, + 0x06U, + 0x00U, + 0x00U, + 0x00U, + 0x00U, + 0x00U, + 0x00U +}; diff --git a/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/device/class/msc/Source/usbd_msc_scsi.c b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/device/class/msc/Source/usbd_msc_scsi.c new file mode 100644 index 0000000000..3937fa6224 --- /dev/null +++ b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/device/class/msc/Source/usbd_msc_scsi.c @@ -0,0 +1,724 @@ +/*! + \file usbd_msc_scsi.c + \brief USB SCSI layer functions + + \version 2020-07-17, V3.0.0, firmware for GD32F10x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "usbd_enum.h" +#include "usbd_msc_bbb.h" +#include "usbd_msc_scsi.h" +#include "usbd_msc_data.h" + +/* local function prototypes ('static') */ +static int8_t scsi_test_unit_ready (usb_core_driver *udev, uint8_t lun, uint8_t *params); +static int8_t scsi_mode_select6 (usb_core_driver *udev, uint8_t lun, uint8_t *params); +static int8_t scsi_mode_select10 (usb_core_driver *udev, uint8_t lun, uint8_t *params); +static int8_t scsi_inquiry (usb_core_driver *udev, uint8_t lun, uint8_t *params); +static int8_t scsi_read_format_capacity (usb_core_driver *udev, uint8_t lun, uint8_t *params); +static int8_t scsi_read_capacity10 (usb_core_driver *udev, uint8_t lun, uint8_t *params); +static int8_t scsi_request_sense (usb_core_driver *udev, uint8_t lun, uint8_t *params); +static int8_t scsi_mode_sense6 (usb_core_driver *udev, uint8_t lun, uint8_t *params); +static int8_t scsi_toc_cmd_read (usb_core_driver *udev, uint8_t lun, uint8_t *params); +static int8_t scsi_mode_sense10 (usb_core_driver *udev, uint8_t lun, uint8_t *params); +static int8_t scsi_write10 (usb_core_driver *udev, uint8_t lun, uint8_t *params); +static int8_t scsi_read10 (usb_core_driver *udev, uint8_t lun, uint8_t *params); +static int8_t scsi_verify10 (usb_core_driver *udev, uint8_t lun, uint8_t *params); + +static int8_t scsi_process_read (usb_core_driver *udev, uint8_t lun); +static int8_t scsi_process_write (usb_core_driver *udev, uint8_t lun); + +static inline int8_t scsi_check_address_range (usb_core_driver *udev, uint8_t lun, uint32_t blk_offset, uint16_t blk_nbr); +static inline int8_t scsi_format_cmd (usb_core_driver *udev, uint8_t lun); +static inline int8_t scsi_start_stop_unit (usb_core_driver *udev, uint8_t lun, uint8_t *params); +static inline int8_t scsi_allow_medium_removal (usb_core_driver *udev, uint8_t lun, uint8_t *params); + +/*! + \brief process SCSI commands + \param[in] udev: pointer to USB device instance + \param[in] lun: logical unit number + \param[in] params: command parameters + \param[out] none + \retval status +*/ +int8_t scsi_process_cmd(usb_core_driver *udev, uint8_t lun, uint8_t *params) +{ + switch (params[0]) { + case SCSI_TEST_UNIT_READY: + return scsi_test_unit_ready (udev, lun, params); + + case SCSI_REQUEST_SENSE: + return scsi_request_sense (udev, lun, params); + + case SCSI_INQUIRY: + return scsi_inquiry (udev, lun, params); + + case SCSI_START_STOP_UNIT: + return scsi_start_stop_unit (udev, lun, params); + + case SCSI_ALLOW_MEDIUM_REMOVAL: + return scsi_allow_medium_removal (udev, lun, params); + + case SCSI_MODE_SENSE6: + return scsi_mode_sense6 (udev, lun, params); + + case SCSI_MODE_SENSE10: + return scsi_mode_sense10 (udev, lun, params); + + case SCSI_READ_FORMAT_CAPACITIES: + return scsi_read_format_capacity (udev, lun, params); + + case SCSI_READ_CAPACITY10: + return scsi_read_capacity10 (udev, lun, params); + + case SCSI_READ10: + return scsi_read10 (udev, lun, params); + + case SCSI_WRITE10: + return scsi_write10 (udev, lun, params); + + case SCSI_VERIFY10: + return scsi_verify10 (udev, lun, params); + + case SCSI_FORMAT_UNIT: + return scsi_format_cmd (udev, lun); + + case SCSI_READ_TOC_DATA: + return scsi_toc_cmd_read (udev, lun, params); + + case SCSI_MODE_SELECT6: + return scsi_mode_select6 (udev, lun, params); + + case SCSI_MODE_SELECT10: + return scsi_mode_select10 (udev, lun, params); + + default: + scsi_sense_code (udev, lun, ILLEGAL_REQUEST, INVALID_CDB); + return -1; + } +} + +/*! + \brief load the last error code in the error list + \param[in] udev: pointer to USB device instance + \param[in] lun: logical unit number + \param[in] skey: sense key + \param[in] asc: additional sense key + \param[out] none + \retval none +*/ +void scsi_sense_code (usb_core_driver *udev, uint8_t lun, uint8_t skey, uint8_t asc) +{ + usbd_msc_handler *msc = (usbd_msc_handler *)udev->dev.class_data[USBD_MSC_INTERFACE]; + + msc->scsi_sense[msc->scsi_sense_tail].SenseKey = skey; + msc->scsi_sense[msc->scsi_sense_tail].ASC = asc << 8U; + msc->scsi_sense_tail++; + + if (SENSE_LIST_DEEPTH == msc->scsi_sense_tail) { + msc->scsi_sense_tail = 0U; + } +} + +/*! + \brief process SCSI Test Unit Ready command + \param[in] udev: pointer to USB device instance + \param[in] lun: logical unit number + \param[in] params: command parameters + \param[out] none + \retval status +*/ +static int8_t scsi_test_unit_ready (usb_core_driver *udev, uint8_t lun, uint8_t *params) +{ + usbd_msc_handler *msc = (usbd_msc_handler *)udev->dev.class_data[USBD_MSC_INTERFACE]; + + /* case 9 : Hi > D0 */ + if (0U != msc->bbb_cbw.dCBWDataTransferLength) { + scsi_sense_code (udev, msc->bbb_cbw.bCBWLUN, ILLEGAL_REQUEST, INVALID_CDB); + + return -1; + } + + if (0 != usbd_mem_fops->mem_ready(lun)) { + scsi_sense_code(udev, lun, NOT_READY, MEDIUM_NOT_PRESENT); + + return -1; + } + + msc->bbb_datalen = 0U; + + return 0; +} + +/*! + \brief process Inquiry command + \param[in] udev: pointer to USB device instance + \param[in] lun: logical unit number + \param[in] params: command parameters + \param[out] none + \retval status +*/ +static int8_t scsi_mode_select6 (usb_core_driver *udev, uint8_t lun, uint8_t *params) +{ + usbd_msc_handler *msc = (usbd_msc_handler *)udev->dev.class_data[USBD_MSC_INTERFACE]; + + msc->bbb_datalen = 0U; + + return 0; +} + +/*! + \brief process Inquiry command + \param[in] udev: pointer to USB device instance + \param[in] lun: logical unit number + \param[in] params: command parameters + \param[out] none + \retval status +*/ +static int8_t scsi_mode_select10 (usb_core_driver *udev, uint8_t lun, uint8_t *params) +{ + usbd_msc_handler *msc = (usbd_msc_handler *)udev->dev.class_data[USBD_MSC_INTERFACE]; + + msc->bbb_datalen = 0U; + + return 0; +} + +/*! + \brief process Inquiry command + \param[in] udev: pointer to USB device instance + \param[in] lun: logical unit number + \param[in] params: command parameters + \param[out] none + \retval status +*/ +static int8_t scsi_inquiry (usb_core_driver *udev, uint8_t lun, uint8_t *params) +{ + uint8_t *page = NULL; + uint16_t len = 0U; + + usbd_msc_handler *msc = (usbd_msc_handler *)udev->dev.class_data[USBD_MSC_INTERFACE]; + + if (params[1] & 0x01U) { + page = (uint8_t *)msc_page00_inquiry_data; + + len = INQUIRY_PAGE00_LENGTH; + } else { + page = (uint8_t *)usbd_mem_fops->mem_inquiry_data[lun]; + + len = (uint16_t)(page[4] + 5U); + + if (params[4] <= len) { + len = params[4]; + } + } + + msc->bbb_datalen = len; + + while (len) { + len--; + msc->bbb_data[len] = page[len]; + } + + return 0; +} + +/*! + \brief process Read Capacity 10 command + \param[in] udev: pointer to USB device instance + \param[in] lun: logical unit number + \param[in] params: command parameters + \param[out] none + \retval status +*/ +static int8_t scsi_read_capacity10 (usb_core_driver *udev, uint8_t lun, uint8_t *params) +{ + uint32_t blk_num = usbd_mem_fops->mem_block_len[lun] - 1U; + usbd_msc_handler *msc = (usbd_msc_handler *)udev->dev.class_data[USBD_MSC_INTERFACE]; + + msc->scsi_blk_nbr[lun] = usbd_mem_fops->mem_block_len[lun]; + msc->scsi_blk_size[lun] = usbd_mem_fops->mem_block_size[lun]; + + msc->bbb_data[0] = (uint8_t)(blk_num >> 24U); + msc->bbb_data[1] = (uint8_t)(blk_num >> 16U); + msc->bbb_data[2] = (uint8_t)(blk_num >> 8U); + msc->bbb_data[3] = (uint8_t)(blk_num); + + msc->bbb_data[4] = (uint8_t)(msc->scsi_blk_size[lun] >> 24U); + msc->bbb_data[5] = (uint8_t)(msc->scsi_blk_size[lun] >> 16U); + msc->bbb_data[6] = (uint8_t)(msc->scsi_blk_size[lun] >> 8U); + msc->bbb_data[7] = (uint8_t)(msc->scsi_blk_size[lun]); + + msc->bbb_datalen = 8U; + + return 0; +} + +/*! + \brief process Read Format Capacity command + \param[in] udev: pointer to USB device instance + \param[in] lun: logical unit number + \param[in] params: command parameters + \param[out] none + \retval status +*/ +static int8_t scsi_read_format_capacity (usb_core_driver *udev, uint8_t lun, uint8_t *params) +{ + uint16_t i = 0U; + uint32_t blk_size = usbd_mem_fops->mem_block_size[lun]; + uint32_t blk_num = usbd_mem_fops->mem_block_len[lun]; + uint32_t blk_nbr = blk_num - 1U; + + usbd_msc_handler *msc = (usbd_msc_handler *)udev->dev.class_data[USBD_MSC_INTERFACE]; + + for (i = 0U; i < 12U; i++) { + msc->bbb_data[i] = 0U; + } + + msc->bbb_data[3] = 0x08U; + msc->bbb_data[4] = (uint8_t)(blk_nbr >> 24U); + msc->bbb_data[5] = (uint8_t)(blk_nbr >> 16U); + msc->bbb_data[6] = (uint8_t)(blk_nbr >> 8U); + msc->bbb_data[7] = (uint8_t)(blk_nbr); + + msc->bbb_data[8] = 0x02U; + msc->bbb_data[9] = (uint8_t)(blk_size >> 16U); + msc->bbb_data[10] = (uint8_t)(blk_size >> 8U); + msc->bbb_data[11] = (uint8_t)(blk_size); + + msc->bbb_datalen = 12U; + + return 0; +} + +/*! + \brief process Mode Sense6 command + \param[in] udev: pointer to USB device instance + \param[in] lun: logical unit number + \param[in] params: command parameters + \param[out] none + \retval status +*/ +static int8_t scsi_mode_sense6 (usb_core_driver *udev, uint8_t lun, uint8_t *params) +{ + uint16_t len = 8U; + usbd_msc_handler *msc = (usbd_msc_handler *)udev->dev.class_data[USBD_MSC_INTERFACE]; + + msc->bbb_datalen = len; + + while (len) { + len--; + msc->bbb_data[len] = msc_mode_sense6_data[len]; + } + + return 0; +} + +/*! + \brief process Mode Sense10 command + \param[in] udev: pointer to USB device instance + \param[in] lun: logical unit number + \param[in] params: command parameters + \param[out] none + \retval status +*/ +static int8_t scsi_mode_sense10 (usb_core_driver *udev, uint8_t lun, uint8_t *params) +{ + uint16_t len = 8U; + usbd_msc_handler *msc = (usbd_msc_handler *)udev->dev.class_data[USBD_MSC_INTERFACE]; + + msc->bbb_datalen = len; + + while (len) { + len--; + msc->bbb_data[len] = msc_mode_sense10_data[len]; + } + + return 0; +} + +/*! + \brief process Request Sense command + \param[in] udev: pointer to USB device instance + \param[in] lun: logical unit number + \param[in] params: command parameters + \param[out] none + \retval status +*/ +static int8_t scsi_request_sense (usb_core_driver *udev, uint8_t lun, uint8_t *params) +{ + uint8_t i = 0U; + usbd_msc_handler *msc = (usbd_msc_handler *)udev->dev.class_data[USBD_MSC_INTERFACE]; + + for (i = 0U; i < REQUEST_SENSE_DATA_LEN; i++) { + msc->bbb_data[i] = 0U; + } + + msc->bbb_data[0] = 0x70U; + msc->bbb_data[7] = REQUEST_SENSE_DATA_LEN - 6U; + + if ((msc->scsi_sense_head != msc->scsi_sense_tail)) { + msc->bbb_data[2] = msc->scsi_sense[msc->scsi_sense_head].SenseKey; + msc->bbb_data[12] = msc->scsi_sense[msc->scsi_sense_head].ASCQ; + msc->bbb_data[13] = msc->scsi_sense[msc->scsi_sense_head].ASC; + msc->scsi_sense_head++; + + if (msc->scsi_sense_head == SENSE_LIST_DEEPTH) { + msc->scsi_sense_head = 0U; + } + } + + msc->bbb_datalen = USB_MIN(REQUEST_SENSE_DATA_LEN, params[4]); + + return 0; +} + +/*! + \brief process Start Stop Unit command + \param[in] udev: pointer to USB device instance + \param[in] lun: logical unit number + \param[in] params: command parameters + \param[out] none + \retval status +*/ +static inline int8_t scsi_start_stop_unit (usb_core_driver *udev, uint8_t lun, uint8_t *params) +{ + usbd_msc_handler *msc = (usbd_msc_handler *)udev->dev.class_data[USBD_MSC_INTERFACE]; + + msc->bbb_datalen = 0U; + msc->scsi_disk_pop = 1U; + + return 0; +} + +/*! + \brief process Allow Medium Removal command + \param[in] udev: pointer to USB device instance + \param[in] lun: logical unit number + \param[in] params: command parameters + \param[out] none + \retval status +*/ +static inline int8_t scsi_allow_medium_removal (usb_core_driver *udev, uint8_t lun, uint8_t *params) +{ + usbd_msc_handler *msc = (usbd_msc_handler *)udev->dev.class_data[USBD_MSC_INTERFACE]; + + msc->bbb_datalen = 0U; + + return 0; +} + +/*! + \brief process Read10 command + \param[in] udev: pointer to USB device instance + \param[in] lun: logical unit number + \param[in] params: command parameters + \param[out] none + \retval status +*/ +static int8_t scsi_read10 (usb_core_driver *udev, uint8_t lun, uint8_t *params) +{ + usbd_msc_handler *msc = (usbd_msc_handler *)udev->dev.class_data[USBD_MSC_INTERFACE]; + + if (msc->bbb_state == BBB_IDLE) { + /* direction is from device to host */ + if (0x80U != (msc->bbb_cbw.bmCBWFlags & 0x80U)) { + scsi_sense_code (udev, msc->bbb_cbw.bCBWLUN, ILLEGAL_REQUEST, INVALID_CDB); + + return -1; + } + + if (0 != usbd_mem_fops->mem_ready(lun)) { + scsi_sense_code (udev, lun, NOT_READY, MEDIUM_NOT_PRESENT); + + return -1; + } + + msc->scsi_blk_addr = (params[2] << 24U) | (params[3] << 16U) | \ + (params[4] << 8U) | params[5]; + + msc->scsi_blk_len = (params[7] << 8U) | params[8]; + + if (scsi_check_address_range (udev, lun, msc->scsi_blk_addr, (uint16_t)msc->scsi_blk_len) < 0) { + return -1; /* error */ + } + + msc->bbb_state = BBB_DATA_IN; + + msc->scsi_blk_addr *= msc->scsi_blk_size[lun]; + msc->scsi_blk_len *= msc->scsi_blk_size[lun]; + + /* cases 4,5 : Hi <> Dn */ + if (msc->bbb_cbw.dCBWDataTransferLength != msc->scsi_blk_len) { + scsi_sense_code (udev, msc->bbb_cbw.bCBWLUN, ILLEGAL_REQUEST, INVALID_CDB); + + return -1; + } + } + + msc->bbb_datalen = MSC_MEDIA_PACKET_SIZE; + + return scsi_process_read (udev, lun); +} + +/*! + \brief process Write10 command + \param[in] udev: pointer to USB device instance + \param[in] lun: logical unit number + \param[in] params: command parameters + \param[out] none + \retval status +*/ +static int8_t scsi_write10 (usb_core_driver *udev, uint8_t lun, uint8_t *params) +{ + usbd_msc_handler *msc = (usbd_msc_handler *)udev->dev.class_data[USBD_MSC_INTERFACE]; + + if (BBB_IDLE == msc->bbb_state) { + /* case 8 : Hi <> Do */ + if (0x80U == (msc->bbb_cbw.bmCBWFlags & 0x80U)) { + scsi_sense_code (udev, msc->bbb_cbw.bCBWLUN, ILLEGAL_REQUEST, INVALID_CDB); + + return -1; + } + + /* check whether media is ready */ + if (0 != usbd_mem_fops->mem_ready(lun)) { + scsi_sense_code (udev, lun, NOT_READY, MEDIUM_NOT_PRESENT); + + return -1; + } + + /* check if media is write-protected */ + if (0 != usbd_mem_fops->mem_protected(lun)) { + scsi_sense_code (udev, lun, NOT_READY, WRITE_PROTECTED); + + return -1; + } + + msc->scsi_blk_addr = (params[2] << 24U) | (params[3] << 16U) | \ + (params[4] << 8U) | params[5]; + + msc->scsi_blk_len = (params[7] << 8U) | params[8]; + + /* check if LBA address is in the right range */ + if (scsi_check_address_range (udev, lun, msc->scsi_blk_addr, (uint16_t)msc->scsi_blk_len) < 0) { + return -1; /* error */ + } + + msc->scsi_blk_addr *= msc->scsi_blk_size[lun]; + msc->scsi_blk_len *= msc->scsi_blk_size[lun]; + + /* cases 3,11,13 : Hn,Ho <> D0 */ + if (msc->bbb_cbw.dCBWDataTransferLength != msc->scsi_blk_len) { + scsi_sense_code (udev, msc->bbb_cbw.bCBWLUN, ILLEGAL_REQUEST, INVALID_CDB); + + return -1; + } + + /* prepare endpoint to receive first data packet */ + msc->bbb_state = BBB_DATA_OUT; + + usbd_ep_recev (udev, + MSC_OUT_EP, + msc->bbb_data, + USB_MIN (msc->scsi_blk_len, MSC_MEDIA_PACKET_SIZE)); + } else { /* write process ongoing */ + return scsi_process_write (udev, lun); + } + + return 0; +} + +/*! + \brief process Verify10 command + \param[in] udev: pointer to USB device instance + \param[in] lun: logical unit number + \param[in] params: command parameters + \param[out] none + \retval status +*/ +static int8_t scsi_verify10 (usb_core_driver *udev, uint8_t lun, uint8_t *params) +{ + usbd_msc_handler *msc = (usbd_msc_handler *)udev->dev.class_data[USBD_MSC_INTERFACE]; + + if (0x02U == (params[1] & 0x02U)) { + scsi_sense_code (udev, lun, ILLEGAL_REQUEST, INVALID_FIELED_IN_COMMAND); + + return -1; /* error, verify mode not supported*/ + } + + if (scsi_check_address_range (udev, lun, msc->scsi_blk_addr, (uint16_t)msc->scsi_blk_len) < 0) { + return -1; /* error */ + } + + msc->bbb_datalen = 0U; + + return 0; +} + +/*! + \brief check address range + \param[in] udev: pointer to USB device instance + \param[in] lun: logical unit number + \param[in] blk_offset: block offset + \param[in] blk_nbr: number of block to be processed + \param[out] none + \retval status +*/ +static inline int8_t scsi_check_address_range (usb_core_driver *udev, uint8_t lun, uint32_t blk_offset, uint16_t blk_nbr) +{ + usbd_msc_handler *msc = (usbd_msc_handler *)udev->dev.class_data[USBD_MSC_INTERFACE]; + + if ((blk_offset + blk_nbr) > msc->scsi_blk_nbr[lun]) { + scsi_sense_code (udev, lun, ILLEGAL_REQUEST, ADDRESS_OUT_OF_RANGE); + + return -1; + } + + return 0; +} + +/*! + \brief handle read process + \param[in] udev: pointer to USB device instance + \param[in] lun: logical unit number + \param[out] none + \retval status +*/ +static int8_t scsi_process_read (usb_core_driver *udev, uint8_t lun) +{ + usbd_msc_handler *msc = (usbd_msc_handler *)udev->dev.class_data[USBD_MSC_INTERFACE]; + + uint32_t len = USB_MIN(msc->scsi_blk_len, MSC_MEDIA_PACKET_SIZE); + + if (usbd_mem_fops->mem_read(lun, + msc->bbb_data, + msc->scsi_blk_addr, + (uint16_t)(len / msc->scsi_blk_size[lun])) < 0) { + scsi_sense_code(udev, lun, HARDWARE_ERROR, UNRECOVERED_READ_ERROR); + + return -1; + } + + usbd_ep_send (udev, MSC_IN_EP, msc->bbb_data, len); + + msc->scsi_blk_addr += len; + msc->scsi_blk_len -= len; + + /* case 6 : Hi = Di */ + msc->bbb_csw.dCSWDataResidue -= len; + + if (0U == msc->scsi_blk_len) { + msc->bbb_state = BBB_LAST_DATA_IN; + } + + return 0; +} + +/*! + \brief handle write process + \param[in] udev: pointer to USB device instance + \param[in] lun: logical unit number + \param[out] none + \retval status +*/ +static int8_t scsi_process_write (usb_core_driver *udev, uint8_t lun) +{ + usbd_msc_handler *msc = (usbd_msc_handler *)udev->dev.class_data[USBD_MSC_INTERFACE]; + + uint32_t len = USB_MIN(msc->scsi_blk_len, MSC_MEDIA_PACKET_SIZE); + + if (usbd_mem_fops->mem_write (lun, + msc->bbb_data, + msc->scsi_blk_addr, + (uint16_t)(len / msc->scsi_blk_size[lun])) < 0) { + scsi_sense_code(udev, lun, HARDWARE_ERROR, WRITE_FAULT); + + return -1; + } + + msc->scsi_blk_addr += len; + msc->scsi_blk_len -= len; + + /* case 12 : Ho = Do */ + msc->bbb_csw.dCSWDataResidue -= len; + + if (0U == msc->scsi_blk_len) { + msc_bbb_csw_send (udev, CSW_CMD_PASSED); + } else { + /* prepare endpoint to receive next packet */ + usbd_ep_recev (udev, + MSC_OUT_EP, + msc->bbb_data, + USB_MIN (msc->scsi_blk_len, MSC_MEDIA_PACKET_SIZE)); + } + + return 0; +} + +/*! + \brief process Format Unit command + \param[in] udev: pointer to USB device instance + \param[in] lun: logical unit number + \param[out] none + \retval status +*/ +static inline int8_t scsi_format_cmd (usb_core_driver *udev, uint8_t lun) +{ + return 0; +} + +/*! + \brief process Read_Toc command + \param[in] udev: pointer to USB device instance + \param[in] lun: logical unit number + \param[in] params: command parameters + \param[out] none + \retval status +*/ +static int8_t scsi_toc_cmd_read (usb_core_driver *udev, uint8_t lun, uint8_t *params) +{ + uint8_t* pPage; + uint16_t len; + + usbd_msc_handler *msc = (usbd_msc_handler *)udev->dev.class_data[USBD_MSC_INTERFACE]; + + pPage = (uint8_t *)&usbd_mem_fops->mem_toc_data[lun * READ_TOC_CMD_LEN]; + len = (uint16_t)pPage[1] + 2U; + + msc->bbb_datalen = len; + + while (len) { + len--; + msc->bbb_data[len] = pPage[len]; + } + + return 0; +} diff --git a/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/device/class/printer/Include/printer_core.h b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/device/class/printer/Include/printer_core.h new file mode 100644 index 0000000000..4b1308df7e --- /dev/null +++ b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/device/class/printer/Include/printer_core.h @@ -0,0 +1,78 @@ +/*! + \file printer_core.h + \brief the header file of USB printer device class core functions + + \version 2020-07-17, V3.0.0, firmware for GD32F10x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef __PRINTER_CORE_H +#define __PRINTER_CORE_H + +#include "usbd_enum.h" +#include "usb_ch9_std.h" + +/* USB printing device class code */ +#define USB_CLASS_PRINTER 0x07U + +/* printing device subclass code */ +#define USB_SUBCLASS_PRINTER 0x01U + +/* printing device protocol code */ +#define PROTOCOL_UNIDIRECTIONAL_ITF 0x01U +#define PROTOCOL_BI_DIRECTIONAL_ITF 0x02U +#define PROTOCOL_1284_4_ITF 0x03U +#define PROTOCOL_VENDOR 0xFFU + +#define DEVICE_ID_LEN 103U + +#define USB_PRINTER_CONFIG_DESC_LEN 32U + +/* printing device specific-class request */ +#define GET_DEVICE_ID 0x00U +#define GET_PORT_STATUS 0x01U +#define SOFT_RESET 0x02U + +#pragma pack(1) + +/* USB configuration descriptor structure */ +typedef struct +{ + usb_desc_config config; + usb_desc_itf printer_itf; + usb_desc_ep printer_epin; + usb_desc_ep printer_epout; +} usb_printer_desc_config_set; + +#pragma pack() + +extern usb_desc printer_desc; +extern usb_class_core usbd_printer_cb; + +#endif /* __PRINTER_CORE_H */ diff --git a/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/device/class/printer/Source/printer_core.c b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/device/class/printer/Source/printer_core.c new file mode 100644 index 0000000000..bb09bcef01 --- /dev/null +++ b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/device/class/printer/Source/printer_core.c @@ -0,0 +1,309 @@ +/*! + \file printer_core.c + \brief USB printer device class core functions + + \version 2020-07-17, V3.0.0, firmware for GD32F10x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "printer_core.h" + +#define USBD_VID 0x28E9U +#define USBD_PID 0x028DU + +/* printer port status: paper not empty/selected/no error */ +static uint8_t g_port_status = 0x18U; + +uint8_t g_printer_data_buf[PRINTER_OUT_PACKET]; + +uint8_t PRINTER_DEVICE_ID[DEVICE_ID_LEN] = +{ + 0x00, 0x67, + 'M', 'A', 'N', 'U', 'F', 'A', 'C', 'T', 'U', 'R', 'E', 'R', ':', + 'G', 'I', 'G', 'A', ' ', 'D', 'E', 'V', 'I', 'C', 'E', '-', ';', + 'C', 'O', 'M', 'M', 'A', 'N', 'D', ' ', 'S', 'E', 'T', ':', + 'P', 'C', 'L', ',', 'M', 'P', 'L', ';', + 'M', 'O', 'D', 'E', 'L', ':', + 'L', 'a', 's', 'e', 'r', 'B', 'e', 'a', 'm', '?', ';', + 'C', 'O', 'M', 'M', 'E', 'N', 'T', ':', + 'G', 'o', 'o', 'd', ' ', '!', ';', + 'A', 'C', 'T', 'I', 'V', 'E', ' ', 'C', 'O', 'M', 'M', 'A', 'N', 'D', ' ', 'S', 'E', 'T', ':', + 'P', 'C', 'L', ';' +}; + +/* USB standard device descriptor */ +const usb_desc_dev printer_dev_desc = +{ + .header = + { + .bLength = USB_DEV_DESC_LEN, + .bDescriptorType = USB_DESCTYPE_DEV, + }, + .bcdUSB = 0x0200U, + .bDeviceClass = 0x00U, + .bDeviceSubClass = 0x00U, + .bDeviceProtocol = 0x00U, + .bMaxPacketSize0 = USB_FS_EP0_MAX_LEN, + .idVendor = USBD_VID, + .idProduct = USBD_PID, + .bcdDevice = 0x0100U, + .iManufacturer = STR_IDX_MFC, + .iProduct = STR_IDX_PRODUCT, + .iSerialNumber = STR_IDX_SERIAL, + .bNumberConfigurations = USBD_CFG_MAX_NUM, +}; +/* USB device configuration descriptor */ +const usb_printer_desc_config_set printer_config_desc = +{ + .config = + { + .header = + { + .bLength = sizeof(usb_desc_config), + .bDescriptorType = USB_DESCTYPE_CONFIG + }, + .wTotalLength = USB_PRINTER_CONFIG_DESC_LEN, + .bNumInterfaces = 0x01U, + .bConfigurationValue = 0x01U, + .iConfiguration = 0x00U, + .bmAttributes = 0xA0U, + .bMaxPower = 0x32U + }, + + .printer_itf = + { + .header = + { + .bLength = sizeof(usb_desc_itf), + .bDescriptorType = USB_DESCTYPE_ITF + }, + .bInterfaceNumber = 0x00U, + .bAlternateSetting = 0x00U, + .bNumEndpoints = 0x02U, + .bInterfaceClass = USB_CLASS_PRINTER, + .bInterfaceSubClass = USB_SUBCLASS_PRINTER, + .bInterfaceProtocol = PROTOCOL_BI_DIRECTIONAL_ITF, + .iInterface = 0x00U + }, + + .printer_epin = + { + .header = + { + .bLength = sizeof(usb_desc_ep), + .bDescriptorType = USB_DESCTYPE_EP + }, + .bEndpointAddress = PRINTER_IN_EP, + .bmAttributes = USB_EP_ATTR_BULK, + .wMaxPacketSize = PRINTER_IN_PACKET, + .bInterval = 0x00U + }, + + .printer_epout = + { + .header = + { + .bLength = sizeof(usb_desc_ep), + .bDescriptorType = USB_DESCTYPE_EP + }, + .bEndpointAddress = PRINTER_OUT_EP, + .bmAttributes = USB_EP_ATTR_BULK, + .wMaxPacketSize = PRINTER_OUT_PACKET, + .bInterval = 0x00U + }, +}; + +/* USB language ID Descriptor */ +static const usb_desc_LANGID usbd_language_id_desc = +{ + .header = + { + .bLength = sizeof(usb_desc_LANGID), + .bDescriptorType = USB_DESCTYPE_STR, + }, + .wLANGID = ENG_LANGID +}; + +/* USB manufacture string */ +static const usb_desc_str manufacturer_string = +{ + .header = + { + .bLength = USB_STRING_LEN(10U), + .bDescriptorType = USB_DESCTYPE_STR, + }, + .unicode_string = {'G', 'i', 'g', 'a', 'D', 'e', 'v', 'i', 'c', 'e'} +}; + +/* USB product string */ +static const usb_desc_str product_string = +{ + .header = + { + .bLength = USB_STRING_LEN(16U), + .bDescriptorType = USB_DESCTYPE_STR, + }, + .unicode_string = {'G', 'D', '3', '2', '-', 'U', 'S', 'B', '_', 'P', 'r', 'i', 'n', 't', 'e', 'r'} +}; + +/* USBD serial string */ +static usb_desc_str serial_string = +{ + .header = + { + .bLength = USB_STRING_LEN(12U), + .bDescriptorType = USB_DESCTYPE_STR, + } +}; + +/* USB string descriptor */ +static void *const usbd_msc_strings[] = +{ + [STR_IDX_LANGID] = (uint8_t *)&usbd_language_id_desc, + [STR_IDX_MFC] = (uint8_t *)&manufacturer_string, + [STR_IDX_PRODUCT] = (uint8_t *)&product_string, + [STR_IDX_SERIAL] = (uint8_t *)&serial_string +}; + +usb_desc printer_desc = { + .dev_desc = (uint8_t *)&printer_dev_desc, + .config_desc = (uint8_t *)&printer_config_desc, + .strings = usbd_msc_strings +}; + +/* local function prototypes ('static') */ +static uint8_t printer_init (usb_dev *udev, uint8_t config_index); +static uint8_t printer_deinit (usb_dev *udev, uint8_t config_index); +static uint8_t printer_req (usb_dev *udev, usb_req *req); +static uint8_t printer_in (usb_dev *udev, uint8_t ep_num); +static uint8_t printer_out (usb_dev *udev, uint8_t ep_num); + +usb_class_core usbd_printer_cb = { + .init = printer_init, + .deinit = printer_deinit, + + .req_proc = printer_req, + + .data_in = printer_in, + .data_out = printer_out +}; + +/*! + \brief initialize the printer device + \param[in] udev: pointer to USB device instance + \param[in] config_index: configuration index + \param[out] none + \retval USB device operation status +*/ +static uint8_t printer_init (usb_dev *udev, uint8_t config_index) +{ + /* initialize the data TX endpoint */ + usbd_ep_setup (udev, &(printer_config_desc.printer_epin)); + + /* initialize the data RX endpoint */ + usbd_ep_setup (udev, &(printer_config_desc.printer_epout)); + + /* prepare to receive data */ + usbd_ep_recev(udev, PRINTER_OUT_EP, g_printer_data_buf, PRINTER_OUT_PACKET); + + return USBD_OK; +} + +/*! + \brief deinitialize the printer device + \param[in] udev: pointer to USB device instance + \param[in] config_index: configuration index + \param[out] none + \retval USB device operation status +*/ +static uint8_t printer_deinit (usb_dev *udev, uint8_t config_index) +{ + /* deinitialize the data TX/RX endpoint */ + usbd_ep_clear (udev, PRINTER_IN_EP); + usbd_ep_clear (udev, PRINTER_OUT_EP); + + return USBD_OK; +} + +/*! + \brief handle the printer class-specific requests + \param[in] udev: pointer to USB device instance + \param[in] req: device class-specific request + \param[out] none + \retval USB device operation status +*/ +static uint8_t printer_req(usb_dev *udev, usb_req *req) +{ + usb_transc *transc = &udev->dev.transc_in[0]; + + switch (req->bRequest) { + case GET_DEVICE_ID: + transc->xfer_buf = (uint8_t *)PRINTER_DEVICE_ID; + transc->remain_len = DEVICE_ID_LEN; + break; + + case GET_PORT_STATUS: + transc->xfer_buf = (uint8_t *)&g_port_status; + transc->remain_len = 1U; + break; + + case SOFT_RESET: + usbd_ep_recev(udev, PRINTER_OUT_EP, g_printer_data_buf, PRINTER_OUT_PACKET); + break; + + default: + return USBD_FAIL; + } + + return USBD_OK; +} + +/*! + \brief handle printer data + \param[in] udev: pointer to USB device instance + \param[in] ep_num: endpoint number + \param[out] none + \retval USB device operation status +*/ +static uint8_t printer_in (usb_dev *udev, uint8_t ep_num) +{ + return USBD_OK; +} + +/*! + \brief handle printer data + \param[in] udev: pointer to USB device instance + \param[in] ep_num: endpoint number + \param[out] none + \retval USB device operation status +*/ +static uint8_t printer_out (usb_dev *udev, uint8_t ep_num) +{ + return USBD_OK; +} diff --git a/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/device/core/Include/usbd_core.h b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/device/core/Include/usbd_core.h new file mode 100644 index 0000000000..2325acfa6c --- /dev/null +++ b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/device/core/Include/usbd_core.h @@ -0,0 +1,103 @@ +/*! + \file usbd_core.h + \brief USB device mode core functions prototype + + \version 2020-07-17, V3.0.0, firmware for GD32F10x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef __USBD_CORE_H +#define __USBD_CORE_H + +#include "drv_usb_core.h" +#include "drv_usb_dev.h" + +typedef enum +{ + USBD_OK = 0U, /*!< status OK */ + USBD_BUSY, /*!< status busy */ + USBD_FAIL, /*!< status fail */ +} usbd_status; + +enum _usbd_status { + USBD_DEFAULT = 1U, /*!< default status */ + USBD_ADDRESSED = 2U, /*!< address send status */ + USBD_CONFIGURED = 3U, /*!< configured status */ + USBD_SUSPENDED = 4U /*!< suspended status */ +}; + +/* static inline function definitions */ + +/*! + \brief set USB device address + \param[in] udev: pointer to USB core instance + \param[in] addr: device address to set + \param[out] none + \retval none +*/ +__STATIC_INLINE void usbd_addr_set (usb_core_driver *udev, uint8_t addr) +{ + usb_devaddr_set(udev, addr); +} + +/*! + \brief get the received data length + \param[in] udev: pointer to USB device instance + \param[in] ep_num: endpoint number + \param[out] none + \retval USB device operation cur_status +*/ +__STATIC_INLINE uint16_t usbd_rxcount_get (usb_core_driver *udev, uint8_t ep_num) +{ + return (uint16_t)udev->dev.transc_out[ep_num].xfer_count; +} + +/* function declarations */ +/* initializes the USB device-mode stack and load the class driver */ +void usbd_init (usb_core_driver *udev, usb_core_enum core, usb_desc *desc, usb_class_core *class_core); +/* endpoint initialization */ +uint32_t usbd_ep_setup (usb_core_driver *udev, const usb_desc_ep *ep_desc); +/* configure the endpoint when it is disabled */ +uint32_t usbd_ep_clear (usb_core_driver *udev, uint8_t ep_addr); +/* endpoint prepare to receive data */ +uint32_t usbd_ep_recev (usb_core_driver *udev, uint8_t ep_addr, uint8_t *pbuf, uint32_t len); +/* endpoint prepare to transmit data */ +uint32_t usbd_ep_send (usb_core_driver *udev, uint8_t ep_addr, uint8_t *pbuf, uint32_t len); +/* set an endpoint to STALL status */ +uint32_t usbd_ep_stall (usb_core_driver *udev, uint8_t ep_addr); +/* clear endpoint STALLed status */ +uint32_t usbd_ep_stall_clear (usb_core_driver *udev, uint8_t ep_addr); +/* flush the endpoint FIFOs */ +uint32_t usbd_fifo_flush (usb_core_driver *udev, uint8_t ep_addr); +/* device connect */ +void usbd_connect (usb_core_driver *udev); +/* device disconnect */ +void usbd_disconnect (usb_core_driver *udev); + +#endif /* __USBD_CORE_H */ diff --git a/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/device/core/Include/usbd_enum.h b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/device/core/Include/usbd_enum.h new file mode 100644 index 0000000000..122f67c686 --- /dev/null +++ b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/device/core/Include/usbd_enum.h @@ -0,0 +1,105 @@ +/*! + \file usbd_enum.h + \brief USB enumeration definitions + + \version 2020-07-17, V3.0.0, firmware for GD32F10x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef __USBD_ENUM_H +#define __USBD_ENUM_H + +#include "usbd_core.h" +#include "usbd_conf.h" +#include + +#ifndef NULL + #define NULL 0U +#endif + +typedef enum _usb_reqsta { + REQ_SUPP = 0x0U, /* request support */ + REQ_NOTSUPP = 0x1U, /* request not support */ +} usb_reqsta; + +/* string descriptor index */ +enum _str_index +{ + STR_IDX_LANGID = 0x0U, /* language ID string index */ + STR_IDX_MFC = 0x1U, /* manufacturer string index */ + STR_IDX_PRODUCT = 0x2U, /* product string index */ + STR_IDX_SERIAL = 0x3U, /* serial string index */ + STR_IDX_CONFIG = 0x4U, /* configuration string index */ + STR_IDX_ITF = 0x5U, /* interface string index */ +#ifndef WINUSB_EXEMPT_DRIVER + STR_IDX_MAX = 0x6U, /* string maximum index */ +#else + STR_IDX_MAX = 0xEFU, /* string maximum index */ +#endif /* WINUSB_EXEMPT_DRIVER */ +}; + +typedef enum _usb_pwrsta { + USB_PWRSTA_SELF_POWERED = 0x1U, /* USB is in self powered status */ + USB_PWRSTA_REMOTE_WAKEUP = 0x2U, /* USB is in remote wakeup status */ +} usb_pwrsta; + +typedef enum _usb_feature +{ + USB_FEATURE_EP_HALT = 0x0U, /* USB has endpoint halt feature */ + USB_FEATURE_REMOTE_WAKEUP = 0x1U, /* USB has endpoint remote wakeup feature */ + USB_FEATURE_TEST_MODE = 0x2U, /* USB has endpoint test mode feature */ +} usb_feature; + +#define ENG_LANGID 0x0409U /* english language ID */ +#define CHN_LANGID 0x0804U /* chinese language ID */ + +/* USB device exported macros */ +#define CTL_EP(ep) (((ep) == 0x00U) || ((ep) == 0x80U)) + +#define DEVICE_ID1 (0x1FFFF7E8U) /* device ID1 */ +#define DEVICE_ID2 (0x1FFFF7ECU) /* device ID2 */ +#define DEVICE_ID3 (0x1FFFF7F0U) /* device ID3 */ + +#define DEVICE_ID (0x40022100U) + +/* function declarations */ +/* handle USB standard device request */ +usb_reqsta usbd_standard_request (usb_core_driver *udev, usb_req *req); +/* handle USB device class request */ +usb_reqsta usbd_class_request (usb_core_driver *udev, usb_req *req); +/* handle USB vendor request */ +usb_reqsta usbd_vendor_request (usb_core_driver *udev, usb_req *req); +/* handle USB enumeration error */ +void usbd_enum_error (usb_core_driver *udev, usb_req *req); +/* convert hex 32bits value into unicode char */ +void int_to_unicode (uint32_t value, uint8_t *pbuf, uint8_t len); +/* get serial string */ +void serial_string_get (uint16_t *unicode_str); + +#endif /* __USBD_ENUM_H */ diff --git a/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/device/core/Include/usbd_transc.h b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/device/core/Include/usbd_transc.h new file mode 100644 index 0000000000..e38db7804f --- /dev/null +++ b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/device/core/Include/usbd_transc.h @@ -0,0 +1,56 @@ +/*! + \file usbd_transc.h + \brief USB transaction core functions prototype + + \version 2020-07-17, V3.0.0, firmware for GD32F10x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef __USBD_TRANSC_H +#define __USBD_TRANSC_H + +#include "usbd_core.h" + +/* function declarations */ +/* USB send data in the control transaction */ +usbd_status usbd_ctl_send (usb_core_driver *udev); +/* USB receive data in control transaction */ +usbd_status usbd_ctl_recev (usb_core_driver *udev); +/* USB send control transaction status */ +usbd_status usbd_ctl_status_send (usb_core_driver *udev); +/* USB control receive status */ +usbd_status usbd_ctl_status_recev (usb_core_driver *udev); +/* USB setup stage processing */ +uint8_t usbd_setup_transc (usb_core_driver *udev); +/* data out stage processing */ +uint8_t usbd_out_transc (usb_core_driver *udev, uint8_t ep_num); +/* data in stage processing */ +uint8_t usbd_in_transc (usb_core_driver *udev, uint8_t ep_num); + +#endif /* __USBD_TRANSC_H */ diff --git a/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/device/core/Source/usbd_core.c b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/device/core/Source/usbd_core.c new file mode 100644 index 0000000000..0911091009 --- /dev/null +++ b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/device/core/Source/usbd_core.c @@ -0,0 +1,320 @@ +/*! + \file usbd_core.c + \brief USB device mode core functions + + \version 2020-07-17, V3.0.0, firmware for GD32F10x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "usbd_core.h" +#include "usbd_enum.h" +#include "drv_usb_hw.h" + +/* endpoint type */ +const uint32_t ep_type[] = { + [USB_EP_ATTR_CTL] = (uint32_t)USB_EPTYPE_CTRL, + [USB_EP_ATTR_BULK] = (uint32_t)USB_EPTYPE_BULK, + [USB_EP_ATTR_INT] = (uint32_t)USB_EPTYPE_INTR, + [USB_EP_ATTR_ISO] = (uint32_t)USB_EPTYPE_ISOC +}; + +/*! + \brief initializes the USB device-mode stack and load the class driver + \param[in] udev: pointer to USB core instance + \param[in] core: USB core type + \param[in] desc: pointer to USB descriptor + \param[in] class_core: class driver + \param[out] none + \retval none +*/ +void usbd_init (usb_core_driver *udev, usb_core_enum core, usb_desc *desc, usb_class_core *class_core) +{ + udev->dev.desc = desc; + + /* class callbacks */ + udev->dev.class_core = class_core; + + /* create serial string */ + serial_string_get(udev->dev.desc->strings[STR_IDX_SERIAL]); + + /* configure USB capabilities */ + (void)usb_basic_init (&udev->bp, &udev->regs, core); + + usb_globalint_disable(&udev->regs); + + /* initializes the USB core*/ + (void)usb_core_init (udev->bp, &udev->regs); + + /* set device disconnect */ + usbd_disconnect (udev); + +#ifndef USE_OTG_MODE + usb_curmode_set(&udev->regs, DEVICE_MODE); +#endif + + /* initializes device mode */ + (void)usb_devcore_init (udev); + + usb_globalint_enable(&udev->regs); + + /* set device connect */ + usbd_connect (udev); + + udev->dev.cur_status = (uint8_t)USBD_DEFAULT; +} + +/*! + \brief endpoint initialization + \param[in] udev: pointer to USB core instance + \param[in] ep_desc: pointer to endpoint descriptor + \param[out] none + \retval none +*/ +uint32_t usbd_ep_setup (usb_core_driver *udev, const usb_desc_ep *ep_desc) +{ + usb_transc *transc; + + uint8_t ep_addr = ep_desc->bEndpointAddress; + uint16_t max_len = ep_desc->wMaxPacketSize; + + /* set endpoint direction */ + if (EP_DIR(ep_addr)) { + transc = &udev->dev.transc_in[EP_ID(ep_addr)]; + + transc->ep_addr.dir = 1U; + } else { + transc = &udev->dev.transc_out[ep_addr]; + + transc->ep_addr.dir = 0U; + } + + transc->ep_addr.num = EP_ID(ep_addr); + transc->max_len = max_len; + transc->ep_type = (uint8_t)ep_type[ep_desc->bmAttributes & (uint8_t)USB_EPTYPE_MASK]; + + /* active USB endpoint function */ + (void)usb_transc_active (udev, transc); + + return 0U; +} + +/*! + \brief configure the endpoint when it is disabled + \param[in] udev: pointer to USB core instance + \param[in] ep_addr: endpoint address + in this parameter: + bit0..bit6: endpoint number (0..7) + bit7: endpoint direction which can be IN(1) or OUT(0) + \param[out] none + \retval none +*/ +uint32_t usbd_ep_clear (usb_core_driver *udev, uint8_t ep_addr) +{ + usb_transc *transc; + + if (EP_DIR(ep_addr)) { + transc = &udev->dev.transc_in[EP_ID(ep_addr)]; + } else { + transc = &udev->dev.transc_out[ep_addr]; + } + + /* deactivate USB endpoint function */ + (void)usb_transc_deactivate (udev, transc); + + return 0U; +} + +/*! + \brief endpoint prepare to receive data + \param[in] udev: pointer to USB core instance + \param[in] ep_addr: endpoint address + in this parameter: + bit0..bit6: endpoint number (0..7) + bit7: endpoint direction which can be IN(1) or OUT(0) + \param[in] pbuf: user buffer address pointer + \param[in] len: buffer length + \param[out] none + \retval none +*/ +uint32_t usbd_ep_recev (usb_core_driver *udev, uint8_t ep_addr, uint8_t *pbuf, uint32_t len) +{ + usb_transc *transc = &udev->dev.transc_out[EP_ID(ep_addr)]; + + /* setup the transfer */ + transc->xfer_buf = pbuf; + transc->xfer_len = len; + transc->xfer_count = 0U; + + if ((uint8_t)USB_USE_DMA == udev->bp.transfer_mode) { + transc->dma_addr = (uint32_t)pbuf; + } + + /* start the transfer */ + (void)usb_transc_outxfer (udev, transc); + + return 0U; +} + +/*! + \brief endpoint prepare to transmit data + \param[in] udev: pointer to USB core instance + \param[in] ep_addr: endpoint address + in this parameter: + bit0..bit6: endpoint number (0..7) + bit7: endpoint direction which can be IN(1) or OUT(0) + \param[in] pbuf: transmit buffer address pointer + \param[in] len: buffer length + \param[out] none + \retval none +*/ +uint32_t usbd_ep_send (usb_core_driver *udev, uint8_t ep_addr, uint8_t *pbuf, uint32_t len) +{ + usb_transc *transc = &udev->dev.transc_in[EP_ID(ep_addr)]; + + /* setup the transfer */ + transc->xfer_buf = pbuf; + transc->xfer_len = len; + transc->xfer_count = 0U; + + if ((uint8_t)USB_USE_DMA == udev->bp.transfer_mode) { + transc->dma_addr = (uint32_t)pbuf; + } + + /* start the transfer */ + (void)usb_transc_inxfer (udev, transc); + + return 0U; +} + +/*! + \brief set an endpoint to STALL status + \param[in] udev: pointer to USB core instance + \param[in] ep_addr: endpoint address + in this parameter: + bit0..bit6: endpoint number (0..7) + bit7: endpoint direction which can be IN(1) or OUT(0) + \param[out] none + \retval none +*/ +uint32_t usbd_ep_stall (usb_core_driver *udev, uint8_t ep_addr) +{ + usb_transc *transc = NULL; + + if (EP_DIR(ep_addr)) { + transc = &udev->dev.transc_in[EP_ID(ep_addr)]; + } else { + transc = &udev->dev.transc_out[ep_addr]; + } + + transc->ep_stall = 1U; + + (void)usb_transc_stall (udev, transc); + + return (0U); +} + +/*! + \brief clear endpoint STALLed status + \param[in] udev: pointer to USB core instance + \param[in] ep_addr: endpoint address + in this parameter: + bit0..bit6: endpoint number (0..7) + bit7: endpoint direction which can be IN(1) or OUT(0) + \param[out] none + \retval none +*/ +uint32_t usbd_ep_stall_clear (usb_core_driver *udev, uint8_t ep_addr) +{ + usb_transc *transc = NULL; + + if (EP_DIR(ep_addr)) { + transc = &udev->dev.transc_in[EP_ID(ep_addr)]; + } else { + transc = &udev->dev.transc_out[ep_addr]; + } + + transc->ep_stall = 0U; + + (void)usb_transc_clrstall (udev, transc); + + return (0U); +} + +/*! + \brief flush the endpoint FIFOs + \param[in] udev: pointer to USB core instance + \param[in] ep_addr: endpoint address + in this parameter: + bit0..bit6: endpoint number (0..7) + bit7: endpoint direction which can be IN(1) or OUT(0) + \param[out] none + \retval none +*/ +uint32_t usbd_fifo_flush (usb_core_driver *udev, uint8_t ep_addr) +{ + if (EP_DIR(ep_addr)) { + (void)usb_txfifo_flush (&udev->regs, EP_ID(ep_addr)); + } else { + (void)usb_rxfifo_flush (&udev->regs); + } + + return (0U); +} + +/*! + \brief device connect + \param[in] udev: pointer to USB device instance + \param[out] none + \retval none +*/ +void usbd_connect (usb_core_driver *udev) +{ +#ifndef USE_OTG_MODE + /* connect device */ + usb_dev_connect (udev); + + usb_mdelay(3U); +#endif /* USE_OTG_MODE */ +} + +/*! + \brief device disconnect + \param[in] udev: pointer to USB device instance + \param[out] none + \retval none +*/ +void usbd_disconnect (usb_core_driver *udev) +{ +#ifndef USE_OTG_MODE + /* disconnect device for 3ms */ + usb_dev_disconnect (udev); + + usb_mdelay(3U); +#endif /* USE_OTG_MODE */ +} diff --git a/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/device/core/Source/usbd_enum.c b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/device/core/Source/usbd_enum.c new file mode 100644 index 0000000000..e3166041f1 --- /dev/null +++ b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/device/core/Source/usbd_enum.c @@ -0,0 +1,764 @@ +/*! + \file usbd_enum.c + \brief USB enumeration function + + \version 2020-07-17, V3.0.0, firmware for GD32F10x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "usbd_enum.h" +#include "usb_ch9_std.h" + +#ifdef WINUSB_EXEMPT_DRIVER + +extern usbd_status usbd_OEM_req(usb_dev *udev, usb_req *req); + +#endif /* WINUSB_EXEMPT_DRIVER */ + +/* local function prototypes ('static') */ +static usb_reqsta _usb_std_reserved (usb_core_driver *udev, usb_req *req); +static uint8_t* _usb_dev_desc_get (usb_core_driver *udev, uint8_t index, uint16_t *len); +static uint8_t* _usb_config_desc_get (usb_core_driver *udev, uint8_t index, uint16_t *len); +static uint8_t* _usb_bos_desc_get (usb_core_driver *udev, uint8_t index, uint16_t *len); +static uint8_t* _usb_str_desc_get (usb_core_driver *udev, uint8_t index, uint16_t *len); +static usb_reqsta _usb_std_getstatus (usb_core_driver *udev, usb_req *req); +static usb_reqsta _usb_std_clearfeature (usb_core_driver *udev, usb_req *req); +static usb_reqsta _usb_std_setfeature (usb_core_driver *udev, usb_req *req); +static usb_reqsta _usb_std_setaddress (usb_core_driver *udev, usb_req *req); +static usb_reqsta _usb_std_getdescriptor (usb_core_driver *udev, usb_req *req); +static usb_reqsta _usb_std_setdescriptor (usb_core_driver *udev, usb_req *req); +static usb_reqsta _usb_std_getconfiguration (usb_core_driver *udev, usb_req *req); +static usb_reqsta _usb_std_setconfiguration (usb_core_driver *udev, usb_req *req); +static usb_reqsta _usb_std_getinterface (usb_core_driver *udev, usb_req *req); +static usb_reqsta _usb_std_setinterface (usb_core_driver *udev, usb_req *req); +static usb_reqsta _usb_std_synchframe (usb_core_driver *udev, usb_req *req); + +static usb_reqsta (*_std_dev_req[])(usb_core_driver *udev, usb_req *req) = +{ + [USB_GET_STATUS] = _usb_std_getstatus, + [USB_CLEAR_FEATURE] = _usb_std_clearfeature, + [USB_RESERVED2] = _usb_std_reserved, + [USB_SET_FEATURE] = _usb_std_setfeature, + [USB_RESERVED4] = _usb_std_reserved, + [USB_SET_ADDRESS] = _usb_std_setaddress, + [USB_GET_DESCRIPTOR] = _usb_std_getdescriptor, + [USB_SET_DESCRIPTOR] = _usb_std_setdescriptor, + [USB_GET_CONFIGURATION] = _usb_std_getconfiguration, + [USB_SET_CONFIGURATION] = _usb_std_setconfiguration, + [USB_GET_INTERFACE] = _usb_std_getinterface, + [USB_SET_INTERFACE] = _usb_std_setinterface, + [USB_SYNCH_FRAME] = _usb_std_synchframe, +}; + +/* get standard descriptor handler */ +static uint8_t* (*std_desc_get[])(usb_core_driver *udev, uint8_t index, uint16_t *len) = { + [(uint8_t)USB_DESCTYPE_DEV - 1U] = _usb_dev_desc_get, + [(uint8_t)USB_DESCTYPE_CONFIG - 1U] = _usb_config_desc_get, + [(uint8_t)USB_DESCTYPE_STR - 1U] = _usb_str_desc_get +}; + +/*! + \brief handle USB standard device request + \param[in] udev: pointer to USB device instance + \param[in] req: pointer to USB device request + \param[out] none + \retval USB device request status +*/ +usb_reqsta usbd_standard_request (usb_core_driver *udev, usb_req *req) +{ + return (*_std_dev_req[req->bRequest])(udev, req); +} + +/*! + \brief handle USB device class request + \param[in] udev: pointer to USB device instance + \param[in] req: pointer to USB device class request + \param[out] none + \retval USB device request status +*/ +usb_reqsta usbd_class_request (usb_core_driver *udev, usb_req *req) +{ + if ((uint8_t)USBD_CONFIGURED == udev->dev.cur_status) { + if (BYTE_LOW(req->wIndex) <= USBD_ITF_MAX_NUM) { + /* call device class handle function */ + return (usb_reqsta)udev->dev.class_core->req_proc(udev, req); + } + } + + return REQ_NOTSUPP; +} + +/*! + \brief handle USB vendor request + \param[in] udev: pointer to USB device instance + \param[in] req: pointer to USB vendor request + \param[out] none + \retval USB device request status +*/ +usb_reqsta usbd_vendor_request (usb_core_driver *udev, usb_req *req) +{ + (void)udev; + (void)req; + + /* added by user... */ +#ifdef WINUSB_EXEMPT_DRIVER + usbd_OEM_req(udev, req); +#endif + + return REQ_SUPP; +} + +/*! + \brief handle USB enumeration error + \param[in] udev: pointer to USB device instance + \param[in] req: pointer to USB device request + \param[out] none + \retval none +*/ +void usbd_enum_error (usb_core_driver *udev, usb_req *req) +{ + (void)req; + + (void)usbd_ep_stall (udev, 0x80U); + (void)usbd_ep_stall (udev, 0x00U); + + usb_ctlep_startout(udev); +} + +/*! + \brief convert hex 32bits value into unicode char + \param[in] value: hex 32bits value + \param[in] pbuf: buffer pointer to store unicode char + \param[in] len: value length + \param[out] none + \retval none +*/ +void int_to_unicode (uint32_t value, uint8_t *pbuf, uint8_t len) +{ + uint8_t index; + + for (index = 0U; index < len; index++) { + if ((value >> 28U) < 0x0AU) { + pbuf[2U * index] = (uint8_t)((value >> 28U) + '0'); + } else { + pbuf[2U * index] = (uint8_t)((value >> 28U) + 'A' - 10U); + } + + value = value << 4U; + + pbuf[2U * index + 1U] = 0U; + } +} + +/*! + \brief convert hex 32bits value into unicode char + \param[in] unicode_str: pointer to unicode string + \param[out] none + \retval none +*/ +void serial_string_get (uint16_t *unicode_str) +{ + if ((unicode_str[0] & 0x00FFU) != 6U) { + uint32_t DeviceSerial0, DeviceSerial1, DeviceSerial2; + + DeviceSerial0 = *(uint32_t*)DEVICE_ID1; + DeviceSerial1 = *(uint32_t*)DEVICE_ID2; + DeviceSerial2 = *(uint32_t*)DEVICE_ID3; + + DeviceSerial0 += DeviceSerial2; + + if (0U != DeviceSerial0) { + int_to_unicode(DeviceSerial0, (uint8_t*)&(unicode_str[1]), 8U); + int_to_unicode(DeviceSerial1, (uint8_t*)&(unicode_str[9]), 4U); + } + } else { + uint32_t device_serial = *(uint32_t*)DEVICE_ID; + + if(0U != device_serial) { + unicode_str[1] = (uint16_t)(device_serial & 0x0000FFFFU); + unicode_str[2] = (uint16_t)((device_serial & 0xFFFF0000U) >> 16U); + + } + } +} + +/*! + \brief no operation, just for reserved + \param[in] udev: pointer to USB device instance + \param[in] req: pointer to USB vendor request + \param[out] none + \retval USB device request status +*/ +static usb_reqsta _usb_std_reserved (usb_core_driver *udev, usb_req *req) +{ + (void)udev; + (void)req; + + /* no operation... */ + + return REQ_NOTSUPP; +} + +/*! + \brief get the device descriptor + \param[in] udev: pointer to USB device instance + \param[in] index: no use + \param[out] len: data length pointer + \retval descriptor buffer pointer +*/ +static uint8_t* _usb_dev_desc_get (usb_core_driver *udev, uint8_t index, uint16_t *len) +{ + (void)index; + + *len = udev->dev.desc->dev_desc[0]; + + return udev->dev.desc->dev_desc; +} + +/*! + \brief get the configuration descriptor + \brief[in] udev: pointer to USB device instance + \brief[in] index: no use + \param[out] len: data length pointer + \retval descriptor buffer pointer +*/ +static uint8_t* _usb_config_desc_get (usb_core_driver *udev, uint8_t index, uint16_t *len) +{ + (void)index; + + *len = udev->dev.desc->config_desc[2]; + + return udev->dev.desc->config_desc; +} + +/*! + \brief get the BOS descriptor + \brief[in] udev: pointer to USB device instance + \brief[in] index: no use + \param[out] len: data length pointer + \retval descriptor buffer pointer +*/ +static uint8_t* _usb_bos_desc_get (usb_core_driver *udev, uint8_t index, uint16_t *len) +{ + (void)index; + + *len = udev->dev.desc->bos_desc[2]; + + return udev->dev.desc->bos_desc; +} + +/*! + \brief get string descriptor + \param[in] udev: pointer to USB device instance + \param[in] index: string descriptor index + \param[out] len: pointer to string length + \retval descriptor buffer pointer +*/ +static uint8_t* _usb_str_desc_get (usb_core_driver *udev, uint8_t index, uint16_t *len) +{ + uint8_t *desc = udev->dev.desc->strings[index]; + + *len = desc[0]; + + return desc; +} + +/*! + \brief handle Get_Status request + \param[in] udev: pointer to USB device instance + \param[in] req: pointer to USB device request + \param[out] none + \retval USB device request status +*/ +static usb_reqsta _usb_std_getstatus (usb_core_driver *udev, usb_req *req) +{ + uint8_t recp = BYTE_LOW(req->wIndex); + usb_reqsta req_status = REQ_NOTSUPP; + usb_transc *transc = &udev->dev.transc_in[0]; + + static uint8_t status[2] = {0}; + + switch(req->bmRequestType & (uint8_t)USB_RECPTYPE_MASK) { + case USB_RECPTYPE_DEV: + if (((uint8_t)USBD_ADDRESSED == udev->dev.cur_status) || \ + ((uint8_t)USBD_CONFIGURED == udev->dev.cur_status)) { + + if (udev->dev.pm.power_mode) { + status[0] = USB_STATUS_SELF_POWERED; + } else { + status[0] = 0U; + } + + if (udev->dev.pm.dev_remote_wakeup) { + status[0] |= USB_STATUS_REMOTE_WAKEUP; + } else { + status[0] = 0U; + } + + req_status = REQ_SUPP; + } + break; + + case USB_RECPTYPE_ITF: + if (((uint8_t)USBD_CONFIGURED == udev->dev.cur_status) && (recp <= USBD_ITF_MAX_NUM)) { + req_status = REQ_SUPP; + } + break; + + case USB_RECPTYPE_EP: + if ((uint8_t)USBD_CONFIGURED == udev->dev.cur_status) { + if (0x80U == (recp & 0x80U)) { + status[0] = udev->dev.transc_in[EP_ID(recp)].ep_stall; + } else { + status[0] = udev->dev.transc_out[recp].ep_stall; + } + + req_status = REQ_SUPP; + } + break; + + default: + break; + } + + if (REQ_SUPP == req_status) { + transc->xfer_buf = status; + transc->remain_len = 2U; + } + + return req_status; +} + +/*! + \brief handle USB Clear_Feature request + \param[in] udev: pointer to USB device instance + \param[in] req: USB device request + \param[out] none + \retval USB device request status +*/ +static usb_reqsta _usb_std_clearfeature (usb_core_driver *udev, usb_req *req) +{ + uint8_t ep = 0U; + + switch(req->bmRequestType & (uint8_t)USB_RECPTYPE_MASK) { + case USB_RECPTYPE_DEV: + if (((uint8_t)USBD_ADDRESSED == udev->dev.cur_status) || \ + ((uint8_t)USBD_CONFIGURED == udev->dev.cur_status)) { + + /* clear device remote wakeup feature */ + if ((uint16_t)USB_FEATURE_REMOTE_WAKEUP == req->wValue) { + udev->dev.pm.dev_remote_wakeup = 0U; + + return REQ_SUPP; + } + } + break; + + case USB_RECPTYPE_ITF: + break; + + case USB_RECPTYPE_EP: + /* get endpoint address */ + ep = BYTE_LOW(req->wIndex); + + if ((uint8_t)USBD_CONFIGURED == udev->dev.cur_status) { + /* clear endpoint halt feature */ + if (((uint16_t)USB_FEATURE_EP_HALT == req->wValue) && (!CTL_EP(ep))) { + (void)usbd_ep_stall_clear (udev, ep); + + (void)udev->dev.class_core->req_proc (udev, req); + } + + return REQ_SUPP; + } + break; + + default: + break; + } + + return REQ_NOTSUPP; +} + +/*! + \brief handle USB Set_Feature request + \param[in] udev: pointer to USB device instance + \param[in] req: pointer to USB device request + \param[out] none + \retval USB device request status +*/ +static usb_reqsta _usb_std_setfeature (usb_core_driver *udev, usb_req *req) +{ + uint8_t ep = 0U; + + switch (req->bmRequestType & (uint8_t)USB_RECPTYPE_MASK) { + case USB_RECPTYPE_DEV: + if (((uint8_t)USBD_ADDRESSED == udev->dev.cur_status) || \ + ((uint8_t)USBD_CONFIGURED == udev->dev.cur_status)) { + /* set device remote wakeup feature */ + if ((uint16_t)USB_FEATURE_REMOTE_WAKEUP == req->wValue) { + udev->dev.pm.dev_remote_wakeup = 1U; + } + + return REQ_SUPP; + } + break; + + case USB_RECPTYPE_ITF: + break; + + case USB_RECPTYPE_EP: + /* get endpoint address */ + ep = BYTE_LOW(req->wIndex); + + if ((uint8_t)USBD_CONFIGURED == udev->dev.cur_status) { + /* set endpoint halt feature */ + if (((uint16_t)USB_FEATURE_EP_HALT == req->wValue) && (!CTL_EP(ep))) { + (void)usbd_ep_stall (udev, ep); + } + + return REQ_SUPP; + } + break; + + default: + break; + } + + return REQ_NOTSUPP; +} + +/*! + \brief handle USB Set_Address request + \param[in] udev: pointer to USB device instance + \param[in] req: pointer to USB device request + \param[out] none + \retval USB device request status +*/ +static usb_reqsta _usb_std_setaddress (usb_core_driver *udev, usb_req *req) +{ + if ((0U == req->wIndex) && (0U == req->wLength)) { + udev->dev.dev_addr = (uint8_t)(req->wValue) & 0x7FU; + + if (udev->dev.cur_status != (uint8_t)USBD_CONFIGURED) { + usbd_addr_set (udev, udev->dev.dev_addr); + + if (udev->dev.dev_addr) { + udev->dev.cur_status = (uint8_t)USBD_ADDRESSED; + } else { + udev->dev.cur_status = (uint8_t)USBD_DEFAULT; + } + + return REQ_SUPP; + } + } + + return REQ_NOTSUPP; +} + +/*! + \brief handle USB Get_Descriptor request + \param[in] udev: pointer to USB device instance + \param[in] req: pointer to USB device request + \param[out] none + \retval USB device request status +*/ +static usb_reqsta _usb_std_getdescriptor (usb_core_driver *udev, usb_req *req) +{ + uint8_t desc_type = 0U; + uint8_t desc_index = 0U; + + usb_reqsta status = REQ_NOTSUPP; + + usb_transc *transc = &udev->dev.transc_in[0]; + + /* get device standard descriptor */ + switch (req->bmRequestType & USB_RECPTYPE_MASK) { + case USB_RECPTYPE_DEV: + desc_type = BYTE_HIGH(req->wValue); + desc_index = BYTE_LOW(req->wValue); + + switch (desc_type) { + case USB_DESCTYPE_DEV: + transc->xfer_buf = std_desc_get[desc_type - 1U](udev, desc_index, (uint16_t *)&(transc->remain_len)); + + if (64U == req->wLength) { + transc->remain_len = 8U; + } + break; + + case USB_DESCTYPE_CONFIG: + transc->xfer_buf = std_desc_get[desc_type - 1U](udev, desc_index, (uint16_t *)&(transc->remain_len)); + break; + + case USB_DESCTYPE_STR: + if (desc_index < (uint8_t)STR_IDX_MAX) { + transc->xfer_buf = std_desc_get[desc_type - 1U](udev, desc_index, (uint16_t *)&(transc->remain_len)); + } + break; + + case USB_DESCTYPE_ITF: + case USB_DESCTYPE_EP: + case USB_DESCTYPE_DEV_QUALIFIER: + case USB_DESCTYPE_OTHER_SPD_CONFIG: + case USB_DESCTYPE_ITF_POWER: + break; + + case USB_DESCTYPE_BOS: + transc->xfer_buf = _usb_bos_desc_get(udev, desc_index, (uint16_t *)&(transc->remain_len)); + break; + + default: + break; + } + break; + + case USB_RECPTYPE_ITF: + /* get device class special descriptor */ + status = (usb_reqsta)(udev->dev.class_core->req_proc(udev, req)); + break; + + case USB_RECPTYPE_EP: + break; + + default: + break; + } + + if ((0U != transc->remain_len) && (0U != req->wLength)) { + if (transc->remain_len < req->wLength) { + if ((transc->remain_len >= transc->max_len) && (0U == (transc->remain_len % transc->max_len))) { + udev->dev.control.ctl_zlp = 1U; + } + } else { + transc->remain_len = req->wLength; + } + + status = REQ_SUPP; + } + + return status; +} + +/*! + \brief handle USB Set_Descriptor request + \param[in] udev: pointer to USB device instance + \param[in] req: pointer to USB device request + \param[out] none + \retval USB device request status +*/ +static usb_reqsta _usb_std_setdescriptor (usb_core_driver *udev, usb_req *req) +{ + (void)udev; + (void)req; + + /* no handle... */ + return REQ_SUPP; +} + +/*! + \brief handle USB Get_Configuration request + \param[in] udev: pointer to USB device instance + \param[in] req: pointer to USB device request + \param[out] none + \retval USB device request status +*/ +static usb_reqsta _usb_std_getconfiguration (usb_core_driver *udev, usb_req *req) +{ + (void)req; + + usb_reqsta req_status = REQ_NOTSUPP; + usb_transc *transc = &udev->dev.transc_in[0]; + + switch (udev->dev.cur_status) { + case USBD_ADDRESSED: + if (USB_DEFAULT_CONFIG == udev->dev.config) { + req_status = REQ_SUPP; + } + break; + + case USBD_CONFIGURED: + if (udev->dev.config != USB_DEFAULT_CONFIG) { + req_status = REQ_SUPP; + } + break; + + default: + break; + } + + if (REQ_SUPP == req_status) { + transc->xfer_buf = &(udev->dev.config); + transc->remain_len = 1U; + } + + return req_status; +} + +/*! + \brief handle USB Set_Configuration request + \param[in] udev: pointer to USB device instance + \param[in] req: pointer to USB device request + \param[out] none + \retval USB device request status +*/ +static usb_reqsta _usb_std_setconfiguration (usb_core_driver *udev, usb_req *req) +{ + static uint8_t config; + usb_reqsta status = REQ_NOTSUPP; + + config = (uint8_t)(req->wValue); + + if (config <= USBD_CFG_MAX_NUM) { + switch (udev->dev.cur_status) { + case USBD_ADDRESSED: + if (config){ + (void)udev->dev.class_core->init(udev, config); + + udev->dev.config = config; + udev->dev.cur_status = (uint8_t)USBD_CONFIGURED; + } + + status = REQ_SUPP; + break; + + case USBD_CONFIGURED: + if (USB_DEFAULT_CONFIG == config) { + (void)udev->dev.class_core->deinit(udev, config); + + udev->dev.config = config; + udev->dev.cur_status = (uint8_t)USBD_ADDRESSED; + } else if (config != udev->dev.config) { + /* clear old configuration */ + (void)udev->dev.class_core->deinit(udev, config); + + /* set new configuration */ + udev->dev.config = config; + + (void)udev->dev.class_core->init(udev, config); + } else { + /* no operation */ + } + + status = REQ_SUPP; + break; + + case USBD_DEFAULT: + break; + + default: + break; + } + } + + return status; +} + +/*! + \brief handle USB Get_Interface request + \param[in] udev: pointer to USB device instance + \param[in] req: pointer to USB device request + \param[out] none + \retval USB device request status +*/ +static usb_reqsta _usb_std_getinterface (usb_core_driver *udev, usb_req *req) +{ + switch (udev->dev.cur_status) { + case USBD_DEFAULT: + break; + + case USBD_ADDRESSED: + break; + + case USBD_CONFIGURED: + if (BYTE_LOW(req->wIndex) <= USBD_ITF_MAX_NUM) { + usb_transc *transc = &udev->dev.transc_in[0]; + + transc->xfer_buf = &(udev->dev.class_core->alter_set); + transc->remain_len = 1U; + + return REQ_SUPP; + } + break; + + default: + break; + } + + return REQ_NOTSUPP; +} + +/*! + \brief handle USB Set_Interface request + \param[in] udev: pointer to USB device instance + \param[in] req: pointer to USB device request + \param[out] none + \retval USB device request status +*/ +static usb_reqsta _usb_std_setinterface (usb_core_driver *udev, usb_req *req) +{ + switch (udev->dev.cur_status) { + case USBD_DEFAULT: + break; + + case USBD_ADDRESSED: + break; + + case USBD_CONFIGURED: + if (BYTE_LOW(req->wIndex) <= USBD_ITF_MAX_NUM) { + if (NULL != udev->dev.class_core->set_intf) { + (void)udev->dev.class_core->set_intf (udev, req); + } + + return REQ_SUPP; + } + break; + + default: + break; + } + + return REQ_NOTSUPP; +} + +/*! + \brief handle USB SynchFrame request + \param[in] udev: pointer to USB device instance + \param[in] req: pointer to USB device request + \param[out] none + \retval USB device request status +*/ +static usb_reqsta _usb_std_synchframe (usb_core_driver *udev, usb_req *req) +{ + (void)udev; + (void)req; + + /* no handle */ + return REQ_SUPP; +} diff --git a/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/device/core/Source/usbd_transc.c b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/device/core/Source/usbd_transc.c new file mode 100644 index 0000000000..cf50d93e4a --- /dev/null +++ b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/device/core/Source/usbd_transc.c @@ -0,0 +1,265 @@ +/*! + \file usbd_transc.c + \brief USB transaction core functions + + \version 2020-07-17, V3.0.0, firmware for GD32F10x + \version 2020-12-07, V3.0.1, firmware for GD32F10x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "usbd_enum.h" +#include "usbd_transc.h" + +/*! + \brief USB send data in the control transaction + \param[in] udev: pointer to USB device instance + \param[out] none + \retval USB device operation cur_status +*/ +usbd_status usbd_ctl_send (usb_core_driver *udev) +{ + usb_transc *transc = &udev->dev.transc_in[0]; + + (void)usbd_ep_send(udev, 0U, transc->xfer_buf, transc->remain_len); + + if (transc->remain_len > transc->max_len) { + udev->dev.control.ctl_state = (uint8_t)USB_CTL_DATA_IN; + } else { + udev->dev.control.ctl_state = (uint8_t)USB_CTL_LAST_DATA_IN; + } + + return USBD_OK; +} + +/*! + \brief USB receive data in control transaction + \param[in] udev: pointer to USB device instance + \param[out] none + \retval USB device operation cur_status +*/ +usbd_status usbd_ctl_recev (usb_core_driver *udev) +{ + usb_transc *transc = &udev->dev.transc_out[0]; + + (void)usbd_ep_recev (udev, 0U, transc->xfer_buf, transc->remain_len); + + if (transc->remain_len > transc->max_len) { + udev->dev.control.ctl_state = (uint8_t)USB_CTL_DATA_OUT; + } else { + udev->dev.control.ctl_state = (uint8_t)USB_CTL_LAST_DATA_OUT; + } + + return USBD_OK; +} + +/*! + \brief USB send control transaction status + \param[in] udev: pointer to USB device instance + \param[out] none + \retval USB device operation cur_status +*/ +usbd_status usbd_ctl_status_send (usb_core_driver *udev) +{ + udev->dev.control.ctl_state = (uint8_t)USB_CTL_STATUS_IN; + + (void)usbd_ep_send (udev, 0U, NULL, 0U); + + usb_ctlep_startout(udev); + + return USBD_OK; +} + +/*! + \brief USB control receive status + \param[in] udev: pointer to USB device instance + \param[out] none + \retval USB device operation cur_status +*/ +usbd_status usbd_ctl_status_recev (usb_core_driver *udev) +{ + udev->dev.control.ctl_state = (uint8_t)USB_CTL_STATUS_OUT; + + (void)usbd_ep_recev (udev, 0U, NULL, 0U); + + usb_ctlep_startout(udev); + + return USBD_OK; +} + +/*! + \brief USB setup stage processing + \param[in] udev: pointer to USB device instance + \param[out] none + \retval USB device operation cur_status +*/ +uint8_t usbd_setup_transc (usb_core_driver *udev) +{ + usb_reqsta reqstat = REQ_NOTSUPP; + + usb_req req = udev->dev.control.req; + + switch (req.bmRequestType & USB_REQTYPE_MASK) { + /* standard device request */ + case USB_REQTYPE_STRD: + reqstat = usbd_standard_request (udev, &req); + break; + + /* device class request */ + case USB_REQTYPE_CLASS: + reqstat = usbd_class_request (udev, &req); + break; + + /* vendor defined request */ + case USB_REQTYPE_VENDOR: + reqstat = usbd_vendor_request (udev, &req); + break; + + default: + break; + } + + if (REQ_SUPP == reqstat) { + if (0U == req.wLength) { + (void)usbd_ctl_status_send (udev); + } else { + if (req.bmRequestType & 0x80U) { + (void)usbd_ctl_send (udev); + } else { + (void)usbd_ctl_recev (udev); + } + } + } else { + usbd_enum_error (udev, &req); + } + + return (uint8_t)USBD_OK; +} + +/*! + \brief data out stage processing + \param[in] udev: pointer to USB device instance + \param[in] ep_num: endpoint identifier(0..7) + \param[out] none + \retval USB device operation cur_status +*/ +uint8_t usbd_out_transc (usb_core_driver *udev, uint8_t ep_num) +{ + if (0U == ep_num) { + usb_transc *transc = &udev->dev.transc_out[0]; + + switch (udev->dev.control.ctl_state) { + case USB_CTL_DATA_OUT: + /* update transfer length */ + transc->remain_len -= transc->max_len; + + if ((uint8_t)USB_USE_DMA == udev->bp.transfer_mode) { + transc->xfer_buf += transc->max_len; + } + + (void)usbd_ctl_recev (udev); + break; + + case USB_CTL_LAST_DATA_OUT: + if (udev->dev.cur_status == (uint8_t)USBD_CONFIGURED) { + if (udev->dev.class_core->ctlx_out != NULL) { + (void)udev->dev.class_core->ctlx_out (udev); + } + } + + transc->remain_len = 0U; + + (void)usbd_ctl_status_send (udev); + break; + + default: + break; + } + } else if ((udev->dev.class_core->data_out != NULL) && (udev->dev.cur_status == (uint8_t)USBD_CONFIGURED)) { + (void)udev->dev.class_core->data_out (udev, ep_num); + } else { + /* no operation */ + } + + return (uint8_t)USBD_OK; +} + +/*! + \brief data in stage processing + \param[in] udev: pointer to USB device instance + \param[in] ep_num: endpoint identifier(0..7) + \param[out] none + \retval USB device operation cur_status +*/ +uint8_t usbd_in_transc (usb_core_driver *udev, uint8_t ep_num) +{ + if (0U == ep_num) { + usb_transc *transc = &udev->dev.transc_in[0]; + + switch (udev->dev.control.ctl_state) { + case USB_CTL_DATA_IN: + /* update transfer length */ + transc->remain_len -= transc->max_len; + + if ((uint8_t)USB_USE_DMA == udev->bp.transfer_mode) { + transc->xfer_buf += transc->max_len; + } + + (void)usbd_ctl_send (udev); + break; + + case USB_CTL_LAST_DATA_IN: + /* last packet is MPS multiple, so send ZLP packet */ + if (udev->dev.control.ctl_zlp) { + (void)usbd_ep_send (udev, 0U, NULL, 0U); + + udev->dev.control.ctl_zlp = 0U; + } else { + if (udev->dev.cur_status == (uint8_t)USBD_CONFIGURED) { + if (udev->dev.class_core->ctlx_in != NULL) { + (void)udev->dev.class_core->ctlx_in (udev); + } + } + + transc->remain_len = 0U; + + (void)usbd_ctl_status_recev (udev); + } + break; + + default: + break; + } + } else { + if ((udev->dev.cur_status == (uint8_t)USBD_CONFIGURED) && (udev->dev.class_core->data_in != NULL)) { + (void)udev->dev.class_core->data_in (udev, ep_num); + } + } + + return (uint8_t)USBD_OK; +} diff --git a/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/driver/Include/drv_usb_core.h b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/driver/Include/drv_usb_core.h new file mode 100644 index 0000000000..10f2594a6d --- /dev/null +++ b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/driver/Include/drv_usb_core.h @@ -0,0 +1,163 @@ +/*! + \file drv_usb_core.h + \brief USB core low level driver header file + + \version 2020-07-17, V3.0.0, firmware for GD32F10x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef __DRV_USB_CORE_H +#define __DRV_USB_CORE_H + +#include "drv_usb_regs.h" +#include "usb_ch9_std.h" + +#define USB_FS_EP0_MAX_LEN 64U /*!< maximum packet size of endpoint 0 */ +#define HC_MAX_PACKET_COUNT 140U /*!< maximum packet count */ + +#define EP_ID(x) ((uint8_t)((x) & 0x7FU)) /*!< endpoint number */ +#define EP_DIR(x) ((uint8_t)((x) >> 7)) /*!< endpoint direction */ + +enum _usb_mode { + DEVICE_MODE = 0U, /*!< device mode */ + HOST_MODE, /*!< host mode */ + OTG_MODE /*!< OTG mode */ +}; + +enum _usb_eptype { + USB_EPTYPE_CTRL = 0U, /*!< control endpoint type */ + USB_EPTYPE_ISOC = 1U, /*!< isochronous endpoint type */ + USB_EPTYPE_BULK = 2U, /*!< bulk endpoint type */ + USB_EPTYPE_INTR = 3U, /*!< interrupt endpoint type */ + USB_EPTYPE_MASK = 3U /*!< endpoint type mask */ +}; + +typedef enum +{ + USB_OTG_OK = 0U, /*!< USB OTG status OK*/ + USB_OTG_FAIL /*!< USB OTG status fail*/ +} usb_otg_status; + +typedef enum +{ + USB_OK = 0U, /*!< USB status OK*/ + USB_FAIL /*!< USB status fail*/ +} usb_status; + +typedef enum +{ + USB_USE_FIFO, /*!< USB use FIFO transfer mode */ + USB_USE_DMA /*!< USB use DMA transfer mode */ +} usb_transfer_mode; + +typedef struct +{ + uint8_t core_enum; /*!< USB core type */ + uint8_t core_speed; /*!< USB core speed */ + uint8_t num_pipe; /*!< USB host channel numbers */ + uint8_t num_ep; /*!< USB device endpoint numbers */ + uint8_t transfer_mode; /*!< USB transfer mode */ + uint8_t phy_itf; /*!< USB core PHY interface */ + uint8_t sof_enable; /*!< USB SOF output */ + uint8_t low_power; /*!< USB low power */ + uint8_t lpm_enable; /*!< USB link power mode(LPM) */ + uint8_t vbus_sensing_enable; /*!< USB VBUS sensing feature */ + uint8_t use_dedicated_ep1; /*!< USB dedicated endpoint1 interrupt */ + uint8_t use_external_vbus; /*!< enable or disable the use of the external VBUS */ + uint32_t base_reg; /*!< base register address */ +} usb_core_basic; + +/* static inline function definitions */ + +/*! + \brief get the global interrupts + \param[in] usb_regs: pointer to USB core registers + \param[out] none + \retval interrupt status +*/ +__STATIC_INLINE uint32_t usb_coreintr_get(usb_core_regs *usb_regs) +{ + return usb_regs->gr->GINTEN & usb_regs->gr->GINTF; +} + +/*! + \brief set USB RX FIFO size + \param[in] usb_regs: pointer to USB core registers + \param[in] size: assigned FIFO size + \param[out] none + \retval none +*/ +__STATIC_INLINE void usb_set_rxfifo(usb_core_regs *usb_regs, uint16_t size) +{ + usb_regs->gr->GRFLEN = size; +} + +/*! + \brief enable the global interrupts + \param[in] usb_regs: pointer to USB core registers + \param[out] none + \retval none +*/ +__STATIC_INLINE void usb_globalint_enable(usb_core_regs *usb_regs) +{ + /* enable USB global interrupt */ + usb_regs->gr->GAHBCS |= GAHBCS_GINTEN; +} + +/*! + \brief disable the global interrupts + \param[in] usb_regs: pointer to USB core registers + \param[out] none + \retval none +*/ +__STATIC_INLINE void usb_globalint_disable(usb_core_regs *usb_regs) +{ + /* disable USB global interrupt */ + usb_regs->gr->GAHBCS &= ~GAHBCS_GINTEN; +} + +/* function declarations */ +/* configure core capabilities */ +usb_status usb_basic_init (usb_core_basic *usb_basic, usb_core_regs *usb_regs, usb_core_enum usb_core); +/* initializes the USB controller registers and prepares the core device mode or host mode operation */ +usb_status usb_core_init (usb_core_basic usb_basic, usb_core_regs *usb_regs); +/* write a packet into the TX FIFO associated with the endpoint */ +usb_status usb_txfifo_write (usb_core_regs *usb_regs, uint8_t *src_buf, uint8_t fifo_num, uint16_t byte_count); +/* read a packet from the RX FIFO associated with the endpoint */ +void *usb_rxfifo_read (usb_core_regs *usb_regs, uint8_t *dest_buf, uint16_t byte_count); +/* flush a TX FIFO or all TX FIFOs */ +usb_status usb_txfifo_flush (usb_core_regs *usb_regs, uint8_t fifo_num); +/* flush the entire RX FIFO */ +usb_status usb_rxfifo_flush (usb_core_regs *usb_regs); +/* set endpoint or channel TX FIFO size */ +void usb_set_txfifo(usb_core_regs *usb_regs, uint8_t fifo, uint16_t size); +/* set USB current mode */ +void usb_curmode_set(usb_core_regs *usb_regs, uint8_t mode); + +#endif /* __DRV_USB_CORE_H */ diff --git a/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/driver/Include/drv_usb_dev.h b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/driver/Include/drv_usb_dev.h new file mode 100644 index 0000000000..bbed1691bb --- /dev/null +++ b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/driver/Include/drv_usb_dev.h @@ -0,0 +1,300 @@ +/*! + \file drv_usb_dev.h + \brief USB device low level driver header file + + \version 2020-07-17, V3.0.0, firmware for GD32F10x + \version 2020-12-07, V3.0.1, firmware for GD32F10x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef __DRV_USB_DEV_H +#define __DRV_USB_DEV_H + +#include "usbd_conf.h" +#include "drv_usb_core.h" + +enum usb_ctl_status { + USB_CTL_IDLE = 0U, /*!< USB control transfer idle state */ + USB_CTL_DATA_IN, /*!< USB control transfer data in state */ + USB_CTL_LAST_DATA_IN, /*!< USB control transfer last data in state */ + USB_CTL_DATA_OUT, /*!< USB control transfer data out state */ + USB_CTL_LAST_DATA_OUT, /*!< USB control transfer last data out state */ + USB_CTL_STATUS_IN, /*!< USB control transfer status in state*/ + USB_CTL_STATUS_OUT /*!< USB control transfer status out state */ +}; + +#define EP_IN(x) ((uint8_t)(0x80U | (x))) /*!< device IN endpoint */ +#define EP_OUT(x) ((uint8_t)(x)) /*!< device OUT endpoint */ + +/* USB descriptor */ +typedef struct _usb_desc { + uint8_t *dev_desc; /*!< device descriptor */ + uint8_t *config_desc; /*!< configure descriptor */ + uint8_t *bos_desc; /*!< BOS descriptor */ + + void* const *strings; /*!< string descriptor */ +} usb_desc; + +/* USB power management */ +typedef struct _usb_pm { + uint8_t power_mode; /*!< power mode */ + uint8_t power_low; /*!< power low */ + uint8_t dev_remote_wakeup; /*!< remote wakeup */ + uint8_t remote_wakeup_on; /*!< remote wakeup on */ +} usb_pm; + +/* USB control information */ +typedef struct _usb_control { + usb_req req; /*!< USB standard device request */ + + uint8_t ctl_state; /*!< USB control transfer state */ + uint8_t ctl_zlp; /*!< zero length package */ +} usb_control; + +typedef struct +{ + struct { + uint8_t num: 4; /*!< the endpoint number.it can be from 0 to 6 */ + uint8_t pad: 3; /*!< padding between number and direction */ + uint8_t dir: 1; /*!< the endpoint direction */ + } ep_addr; + + uint8_t ep_type; /*!< USB endpoint type */ + uint8_t ep_stall; /*!< USB endpoint stall status */ + + uint8_t frame_num; /*!< number of frame */ + uint16_t max_len; /*!< Maximum packet length */ + + /* transaction level variables */ + uint8_t *xfer_buf; /*!< transmit buffer */ + uint32_t xfer_len; /*!< transmit buffer length */ + uint32_t xfer_count; /*!< transmit buffer count */ + + uint32_t remain_len; /*!< remain packet length */ + + uint32_t dma_addr; /*!< DMA address */ +} usb_transc; + +typedef struct _usb_core_driver usb_dev; + +typedef struct _usb_class_core +{ + uint8_t command; /*!< device class request command */ + uint8_t alter_set; /*!< alternative set */ + + uint8_t (*init) (usb_dev *udev, uint8_t config_index); /*!< initialize handler */ + uint8_t (*deinit) (usb_dev *udev, uint8_t config_index); /*!< deinitialize handler */ + + uint8_t (*req_proc) (usb_dev *udev, usb_req *req); /*!< device request handler */ + + uint8_t (*set_intf) (usb_dev *udev, usb_req *req); /*!< device set interface callback */ + + uint8_t (*ctlx_in) (usb_dev *udev); /*!< device contrl in callback */ + uint8_t (*ctlx_out) (usb_dev *udev); /*!< device contrl out callback */ + + uint8_t (*data_in) (usb_dev *udev, uint8_t ep_num); /*!< device data in handler */ + uint8_t (*data_out) (usb_dev *udev, uint8_t ep_num); /*!< device data out handler */ + + uint8_t (*SOF) (usb_dev *udev); /*!< Start of frame handler */ + + uint8_t (*incomplete_isoc_in) (usb_dev *udev); /*!< Incomplete synchronization IN transfer handler */ + uint8_t (*incomplete_isoc_out) (usb_dev *udev); /*!< Incomplete synchronization OUT transfer handler */ +} usb_class_core; + +typedef struct _usb_perp_dev +{ + uint8_t config; /*!< configuration */ + uint8_t dev_addr; /*!< device address */ + + __IO uint8_t cur_status; /*!< current status */ + __IO uint8_t backup_status; /*!< backup status */ + + usb_transc transc_in[USBFS_MAX_TX_FIFOS]; /*!< endpoint IN transaction */ + usb_transc transc_out[USBFS_MAX_TX_FIFOS]; /*!< endpoint OUT transaction */ + + usb_pm pm; /*!< power management */ + usb_control control; /*!< USB control information */ + usb_desc *desc; /*!< USB descriptors pointer */ + usb_class_core *class_core; /*!< class driver */ + void *class_data[USBD_ITF_MAX_NUM]; /*!< class data pointer */ + void *user_data; /*!< user data pointer */ + void *pdata; /*!< reserved data pointer */ +} usb_perp_dev; + +typedef struct _usb_core_driver +{ + usb_core_basic bp; /*!< USB basic parameters */ + usb_core_regs regs; /*!< USB registers */ + usb_perp_dev dev; /*!< USB peripheral device */ +} usb_core_driver; + +/* static inline function definitions */ + +/*! + \brief configure the USB device to be disconnected + \param[in] udev: pointer to USB device + \param[out] none + \retval operation status +*/ +__STATIC_INLINE void usb_dev_disconnect (usb_core_driver *udev) +{ + udev->regs.dr->DCTL |= DCTL_SD; +} + +/*! + \brief configure the USB device to be connected + \param[in] udev: pointer to USB device + \param[out] none + \retval operation status +*/ +__STATIC_INLINE void usb_dev_connect (usb_core_driver *udev) +{ + udev->regs.dr->DCTL &= ~DCTL_SD; +} + +/*! + \brief set the USB device address + \param[in] udev: pointer to USB device + \param[in] dev_addr: device address for setting + \param[out] none + \retval operation status +*/ +__STATIC_INLINE void usb_devaddr_set (usb_core_driver *udev, uint8_t dev_addr) +{ + udev->regs.dr->DCFG &= ~DCFG_DAR; + udev->regs.dr->DCFG |= (uint32_t)dev_addr << 4U; +} + +/*! + \brief read device all OUT endpoint interrupt register + \param[in] udev: pointer to USB device + \param[out] none + \retval interrupt status +*/ +__STATIC_INLINE uint32_t usb_oepintnum_read (usb_core_driver *udev) +{ + uint32_t value = udev->regs.dr->DAEPINT; + + value &= udev->regs.dr->DAEPINTEN; + + return (value & DAEPINT_OEPITB) >> 16U; +} + +/*! + \brief read device OUT endpoint interrupt flag register + \param[in] udev: pointer to USB device + \param[in] ep_num: endpoint number + \param[out] none + \retval interrupt status +*/ +__STATIC_INLINE uint32_t usb_oepintr_read (usb_core_driver *udev, uint8_t ep_num) +{ + uint32_t value = udev->regs.er_out[ep_num]->DOEPINTF; + + value &= udev->regs.dr->DOEPINTEN; + + return value; +} + +/*! + \brief read device all IN endpoint interrupt register + \param[in] udev: pointer to USB device + \param[out] none + \retval interrupt status +*/ +__STATIC_INLINE uint32_t usb_iepintnum_read (usb_core_driver *udev) +{ + uint32_t value = udev->regs.dr->DAEPINT; + + value &= udev->regs.dr->DAEPINTEN; + + return value & DAEPINT_IEPITB; +} + +/*! + \brief set remote wakeup signaling + \param[in] udev: pointer to USB device + \param[out] none + \retval none +*/ +__STATIC_INLINE void usb_rwkup_set (usb_core_driver *udev) +{ + if (udev->dev.pm.dev_remote_wakeup) { + /* enable remote wakeup signaling */ + udev->regs.dr->DCTL |= DCTL_RWKUP; + } +} + +/*! + \brief reset remote wakeup signaling + \param[in] udev: pointer to USB device + \param[out] none + \retval none +*/ +__STATIC_INLINE void usb_rwkup_reset (usb_core_driver *udev) +{ + if (udev->dev.pm.dev_remote_wakeup) { + /* disable remote wakeup signaling */ + udev->regs.dr->DCTL &= ~DCTL_RWKUP; + } +} + +/* function declarations */ +/* initialize USB core registers for device mode */ +usb_status usb_devcore_init (usb_core_driver *udev); +/* enable the USB device mode interrupts */ +usb_status usb_devint_enable (usb_core_driver *udev); +/* active the USB endpoint 0 transaction */ +usb_status usb_transc0_active (usb_core_driver *udev, usb_transc *transc); +/* active the USB transaction */ +usb_status usb_transc_active (usb_core_driver *udev, usb_transc *transc); +/* deactivate the USB transaction */ +usb_status usb_transc_deactivate (usb_core_driver *udev, usb_transc *transc); +/* configure USB transaction to start IN transfer */ +usb_status usb_transc_inxfer (usb_core_driver *udev, usb_transc *transc); +/* configure USB transaction to start OUT transfer */ +usb_status usb_transc_outxfer (usb_core_driver *udev, usb_transc *transc); +/* set the USB transaction STALL status */ +usb_status usb_transc_stall (usb_core_driver *udev, usb_transc *transc); +/* clear the USB transaction STALL status */ +usb_status usb_transc_clrstall (usb_core_driver *udev, usb_transc *transc); +/* read device IN endpoint interrupt flag register */ +uint32_t usb_iepintr_read (usb_core_driver *udev, uint8_t ep_num); +/* configures OUT endpoint 0 to receive SETUP packets */ +void usb_ctlep_startout (usb_core_driver *udev); +/* active remote wakeup signaling */ +void usb_rwkup_active (usb_core_driver *udev); +/* active USB core clock */ +void usb_clock_active (usb_core_driver *udev); +/* USB device suspend */ +void usb_dev_suspend (usb_core_driver *udev); +/* stop the device and clean up FIFOs */ +void usb_dev_stop (usb_core_driver *udev); + +#endif /* __DRV_USB_DEV_H */ diff --git a/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/driver/Include/drv_usb_host.h b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/driver/Include/drv_usb_host.h new file mode 100644 index 0000000000..d8a6d7da0d --- /dev/null +++ b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/driver/Include/drv_usb_host.h @@ -0,0 +1,193 @@ +/*! + \file drv_usb_host.h + \brief USB host mode low level driver header file + + \version 2020-07-17, V3.0.0, firmware for GD32F10x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef __DRV_USB_HOST_H +#define __DRV_USB_HOST_H + +#include "drv_usb_regs.h" +#include "usb_ch9_std.h" +#include "drv_usb_core.h" + +typedef enum _usb_pipe_status +{ + PIPE_IDLE = 0U, + PIPE_XF, + PIPE_HALTED, + PIPE_NAK, + PIPE_NYET, + PIPE_STALL, + PIPE_TRACERR, + PIPE_BBERR, + PIPE_REQOVR, + PIPE_DTGERR, +} usb_pipe_staus; + +typedef enum _usb_pipe_mode +{ + PIPE_PERIOD = 0U, + PIPE_NON_PERIOD = 1U +} usb_pipe_mode; + +typedef enum _usb_urb_state +{ + URB_IDLE = 0U, + URB_DONE, + URB_NOTREADY, + URB_ERROR, + URB_STALL, + URB_PING +} usb_urb_state; + +typedef struct _usb_pipe +{ + uint8_t in_used; + uint8_t dev_addr; + uint32_t dev_speed; + + struct { + uint8_t num; + uint8_t dir; + uint8_t type; + uint16_t mps; + } ep; + + uint8_t ping; + uint32_t DPID; + + uint8_t *xfer_buf; + uint32_t xfer_len; + uint32_t xfer_count; + + uint8_t data_toggle_in; + uint8_t data_toggle_out; + + __IO uint32_t err_count; + __IO usb_pipe_staus pp_status; + __IO usb_urb_state urb_state; +} usb_pipe; + + +typedef struct _usb_host_drv +{ + __IO uint32_t connect_status; + __IO uint32_t port_enabled; + __IO uint32_t backup_xfercount[USBFS_MAX_TX_FIFOS]; + + usb_pipe pipe[USBFS_MAX_TX_FIFOS]; + void *data; +} usb_host_drv; + +typedef struct _usb_core_driver +{ + usb_core_basic bp; + usb_core_regs regs; + usb_host_drv host; +} usb_core_driver; + +/*! + \brief get USB even frame + \param[in] udev: pointer to USB device + \param[out] none + \retval none +*/ +__STATIC_INLINE uint8_t usb_frame_even (usb_core_driver *udev) +{ + return (uint8_t)!(udev->regs.hr->HFINFR & 0x01U); +} + +/*! + \brief configure USB clock of PHY + \param[in] udev: pointer to USB device + \param[in] clock: PHY clock + \param[out] none + \retval none +*/ +__STATIC_INLINE void usb_phyclock_config (usb_core_driver *udev, uint8_t clock) +{ + udev->regs.hr->HCTL &= ~HCTL_CLKSEL; + udev->regs.hr->HCTL |= clock; +} + +/*! + \brief read USB port + \param[in] udev: pointer to USB device + \param[out] none + \retval port status +*/ +__STATIC_INLINE uint32_t usb_port_read (usb_core_driver *udev) +{ + return *udev->regs.HPCS & ~(HPCS_PE | HPCS_PCD | HPCS_PEDC); +} + +/*! + \brief get USB current speed + \param[in] udev: pointer to USB device + \param[out] none + \retval USB current speed +*/ +__STATIC_INLINE uint32_t usb_curspeed_get (usb_core_driver *udev) +{ + return *udev->regs.HPCS & HPCS_PS; +} + +/*! + \brief get USB current frame + \param[in] udev: pointer to USB device + \param[out] none + \retval USB current frame +*/ +__STATIC_INLINE uint32_t usb_curframe_get (usb_core_driver *udev) +{ + return (udev->regs.hr->HFINFR & 0xFFFFU); +} + +/* function declarations */ +/* initializes USB core for host mode */ +usb_status usb_host_init (usb_core_driver *udev); +/* control the VBUS to power */ +void usb_portvbus_switch (usb_core_driver *udev, uint8_t state); +/* reset host port */ +uint32_t usb_port_reset (usb_core_driver *udev); +/* initialize host pipe */ +usb_status usb_pipe_init (usb_core_driver *udev, uint8_t pipe_num); +/* prepare host pipe for transferring packets */ +usb_status usb_pipe_xfer (usb_core_driver *udev, uint8_t pipe_num); +/* halt host pipe */ +usb_status usb_pipe_halt (usb_core_driver *udev, uint8_t pipe_num); +/* configure host pipe to do ping operation */ +usb_status usb_pipe_ping (usb_core_driver *udev, uint8_t pipe_num); +/* stop the USB host and clean up FIFO */ +void usb_host_stop (usb_core_driver *udev); + +#endif /* __DRV_USB_HOST_H */ diff --git a/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/driver/Include/drv_usb_hw.h b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/driver/Include/drv_usb_hw.h new file mode 100644 index 0000000000..7af67edf3b --- /dev/null +++ b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/driver/Include/drv_usb_hw.h @@ -0,0 +1,69 @@ +/*! + \file drv_usb_hw.h + \brief USB hardware configuration header file + + \version 2020-07-17, V3.0.0, firmware for GD32F10x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef __DRV_USB_HW_H +#define __DRV_USB_HW_H + +#include "usb_conf.h" + +/* function declarations */ +/* configure USB clock */ +void usb_rcu_config (void); +/* configure USB interrupt */ +void usb_intr_config (void); +/* initializes delay unit using Timer2 */ +void usb_timer_init (void); +/* delay in micro seconds */ +void usb_udelay (const uint32_t usec); +/* delay in milliseconds */ +void usb_mdelay (const uint32_t msec); +/* configures system clock after wakeup from STOP mode */ +void system_clk_config_stop(void); + +/* configure the CTC peripheral */ +#ifdef USE_IRC48M + void ctc_config(void); +#endif /* USE_IRC48M */ + +#ifdef USE_HOST_MODE + void systick_config(void); + + /* configure USB VBus */ + void usb_vbus_config (void); + + /* drive USB VBus */ + void usb_vbus_drive (uint8_t State); +#endif /* USE_HOST_MODE */ + +#endif /* __DRV_USB_HW_H */ diff --git a/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/driver/Include/drv_usb_regs.h b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/driver/Include/drv_usb_regs.h new file mode 100644 index 0000000000..76729b9641 --- /dev/null +++ b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/driver/Include/drv_usb_regs.h @@ -0,0 +1,662 @@ +/*! + \file drv_usb_regs.h + \brief USB cell registers definition and handle macros + + \version 2020-07-17, V3.0.0, firmware for GD32F10x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef __DRV_USB_REGS_H +#define __DRV_USB_REGS_H + +#include "usb_conf.h" + +#define USBHS_REG_BASE 0x40040000L /*!< base address of USBHS registers */ +#define USBFS_REG_BASE 0x50000000L /*!< base address of USBFS registers */ + +#define USBFS_MAX_TX_FIFOS 15U /*!< FIFO number */ + +#define USBFS_MAX_PACKET_SIZE 64U /*!< USBFS max packet size */ +#define USBFS_MAX_CHANNEL_COUNT 8U /*!< USBFS host channel count */ +#define USBFS_MAX_EP_COUNT 4U /*!< USBFS device endpoint count */ +#define USBFS_MAX_FIFO_WORDLEN 320U /*!< USBFS max fifo size in words */ + +#define USBHS_MAX_PACKET_SIZE 512U /*!< USBHS max packet size */ +#define USBHS_MAX_CHANNEL_COUNT 12U /*!< USBHS host channel count */ +#define USBHS_MAX_EP_COUNT 6U /*!< USBHS device endpoint count */ +#define USBHS_MAX_FIFO_WORDLEN 1280U /*!< USBHS max fifo size in words */ + +#define USB_DATA_FIFO_OFFSET 0x1000U /*!< USB data fifo offset */ +#define USB_DATA_FIFO_SIZE 0x1000U /*!< USB data fifo size */ + +typedef enum +{ + USB_CORE_ENUM_HS = 0, /*!< USB core type is HS */ + USB_CORE_ENUM_FS = 1 /*!< USB core type is FS */ +} usb_core_enum; + +enum USB_SPEED { + USB_SPEED_UNKNOWN = 0, /*!< USB speed unknown */ + USB_SPEED_LOW, /*!< USB speed low */ + USB_SPEED_FULL, /*!< USB speed full */ + USB_SPEED_HIGH, /*!< USB speed high */ +}; + +enum usb_reg_offset { + USB_REG_OFFSET_CORE = 0x0000U, /*!< global OTG control and status register */ + USB_REG_OFFSET_DEV = 0x0800U, /*!< device mode control and status registers */ + USB_REG_OFFSET_EP = 0x0020U, + USB_REG_OFFSET_EP_IN = 0x0900U, /*!< device IN endpoint 0 control register */ + USB_REG_OFFSET_EP_OUT = 0x0B00U, /*!< device OUT endpoint 0 control register */ + USB_REG_OFFSET_HOST = 0x0400U, /*!< host control register */ + USB_REG_OFFSET_CH = 0x0020U, + USB_REG_OFFSET_PORT = 0x0440U, /*!< host port control and status register */ + USB_REG_OFFSET_CH_INOUT = 0x0500U, /*!< Host channel-x control registers */ + USB_REG_OFFSET_PWRCLKCTL = 0x0E00U, /*!< power and clock register */ +}; + +typedef struct +{ + __IO uint32_t GOTGCS; /*!< USB global OTG control and status register 000h */ + __IO uint32_t GOTGINTF; /*!< USB global OTG interrupt flag register 004h */ + __IO uint32_t GAHBCS; /*!< USB global AHB control and status register 008h */ + __IO uint32_t GUSBCS; /*!< USB global USB control and status register 00Ch */ + __IO uint32_t GRSTCTL; /*!< USB global reset control register 010h */ + __IO uint32_t GINTF; /*!< USB global interrupt flag register 014h */ + __IO uint32_t GINTEN; /*!< USB global interrupt enable register 018h */ + __IO uint32_t GRSTATR; /*!< USB receive status debug read register 01Ch */ + __IO uint32_t GRSTATP; /*!< USB receive status and pop register 020h */ + __IO uint32_t GRFLEN; /*!< USB global receive FIFO length register 024h */ + __IO uint32_t DIEP0TFLEN_HNPTFLEN; /*!< USB device IN endpoint 0/host non-periodic transmit FIFO length register 028h */ + __IO uint32_t HNPTFQSTAT; /*!< USB host non-periodic FIFO/queue status register 02Ch */ + uint32_t Reserved30[2]; /*!< Reserved 030h */ + __IO uint32_t GCCFG; /*!< USB global core configuration register 038h */ + __IO uint32_t CID; /*!< USB core ID register 03Ch */ + uint32_t Reserved40[48]; /*!< Reserved 040h-0FFh */ + __IO uint32_t HPTFLEN; /*!< USB host periodic transmit FIFO length register 100h */ + __IO uint32_t DIEPTFLEN[15]; /*!< USB device IN endpoint transmit FIFO length register 104h */ +} usb_gr; + + +typedef struct +{ + __IO uint32_t HCTL; /*!< USB host control register 400h */ + __IO uint32_t HFT; /*!< USB host frame interval register 404h */ + __IO uint32_t HFINFR; /*!< USB host frame information remaining register 408h */ + uint32_t Reserved40C; /*!< Reserved 40Ch */ + __IO uint32_t HPTFQSTAT; /*!< USB host periodic transmit FIFO/queue status register 410h */ + __IO uint32_t HACHINT; /*!< USB host all channels interrupt register 414h */ + __IO uint32_t HACHINTEN; /*!< USB host all channels interrupt enable register 418h */ +} usb_hr; + +typedef struct +{ + __IO uint32_t HCHCTL; /*!< USB host channel control register 500h */ + __IO uint32_t HCHSTCTL; /*!< Reserved 504h */ + __IO uint32_t HCHINTF; /*!< USB host channel interrupt flag register 508h */ + __IO uint32_t HCHINTEN; /*!< USB host channel interrupt enable register 50Ch */ + __IO uint32_t HCHLEN; /*!< USB host channel transfer length register 510h */ + __IO uint32_t HCHDMAADDR; /*!< USB host channel-x DMA address register 514h*/ + uint32_t Reserved[2]; +} usb_pr; + +typedef struct +{ + __IO uint32_t DCFG; /*!< USB device configuration register 800h */ + __IO uint32_t DCTL; /*!< USB device control register 804h */ + __IO uint32_t DSTAT; /*!< USB device status register 808h */ + uint32_t Reserved0C; /*!< Reserved 80Ch */ + __IO uint32_t DIEPINTEN; /*!< USB device IN endpoint common interrupt enable register 810h */ + __IO uint32_t DOEPINTEN; /*!< USB device OUT endpoint common interrupt enable register 814h */ + __IO uint32_t DAEPINT; /*!< USB device all endpoints interrupt register 818h */ + __IO uint32_t DAEPINTEN; /*!< USB device all endpoints interrupt enable register 81Ch */ + uint32_t Reserved20; /*!< Reserved 820h */ + uint32_t Reserved24; /*!< Reserved 824h */ + __IO uint32_t DVBUSDT; /*!< USB device VBUS discharge time register 828h */ + __IO uint32_t DVBUSPT; /*!< USB device VBUS pulsing time register 82Ch */ + __IO uint32_t DTHRCTL; /*!< device threshold control 830h */ + __IO uint32_t DIEPFEINTEN; /*!< USB Device IN endpoint FIFO empty interrupt enable register 834h */ + __IO uint32_t DEP1INT; /*!< USB device endpoint 1 interrupt register 838h */ + __IO uint32_t DEP1INTEN; /*!< USB device endpoint 1 interrupt enable register 83Ch */ + uint32_t Reserved40; /*!< Reserved 840h */ + __IO uint32_t DIEP1INTEN; /*!< USB device IN endpoint-1 interrupt enable register 844h */ + uint32_t Reserved48[15]; /*!< Reserved 848-880h */ + __IO uint32_t DOEP1INTEN; /*!< USB device OUT endpoint-1 interrupt enable register 884h */ +} usb_dr; + +typedef struct +{ + __IO uint32_t DIEPCTL; /*!< USB device IN endpoint control register 900h + (EpNum * 20h) + 00h */ + uint32_t Reserved04; /*!< Reserved 900h + (EpNum * 20h) + 04h */ + __IO uint32_t DIEPINTF; /*!< USB device IN endpoint interrupt flag register 900h + (EpNum * 20h) + 08h */ + uint32_t Reserved0C; /*!< Reserved 900h + (EpNum * 20h) + 0Ch */ + __IO uint32_t DIEPLEN; /*!< USB device IN endpoint transfer length register 900h + (EpNum * 20h) + 10h */ + __IO uint32_t DIEPDMAADDR; /*!< Device IN endpoint-x DMA address register 900h + (EpNum * 20h) + 14h */ + __IO uint32_t DIEPTFSTAT; /*!< USB device IN endpoint transmit FIFO status register 900h + (EpNum * 20h) + 18h */ +} usb_erin; + +typedef struct +{ + __IO uint32_t DOEPCTL; /*!< USB device IN endpoint control register B00h + (EpNum * 20h) + 00h */ + uint32_t Reserved04; /*!< Reserved B00h + (EpNum * 20h) + 04h */ + __IO uint32_t DOEPINTF; /*!< USB device IN endpoint interrupt flag register B00h + (EpNum * 20h) + 08h */ + uint32_t Reserved0C; /*!< Reserved B00h + (EpNum * 20h) + 0Ch */ + __IO uint32_t DOEPLEN; /*!< USB device IN endpoint transfer length register B00h + (EpNum * 20h) + 10h */ + __IO uint32_t DOEPDMAADDR; /*!< Device OUT endpoint-x DMA address register B00h + (EpNum * 20h) + 0Ch */ +} usb_erout; + +typedef struct _usb_regs +{ + usb_gr *gr; /*!< USBFS global registers */ + usb_dr *dr; /*!< Device control and status registers */ + usb_hr *hr; /*!< Host control and status registers */ + usb_erin *er_in[6]; /*!< USB device IN endpoint register */ + usb_erout *er_out[6]; /*!< USB device OUT endpoint register */ + usb_pr *pr[15]; /*!< USB Host channel-x control register */ + + __IO uint32_t *HPCS; /*!< USB host port control and status register */ + __IO uint32_t *DFIFO[USBFS_MAX_TX_FIFOS]; + __IO uint32_t *PWRCLKCTL; /*!< USB power and clock control register */ +} usb_core_regs; + +/* global OTG control and status register bits definitions */ +#define GOTGCS_BSV BIT(19) /*!< B-Session Valid */ +#define GOTGCS_ASV BIT(18) /*!< A-session valid */ +#define GOTGCS_DI BIT(17) /*!< debounce interval */ +#define GOTGCS_CIDPS BIT(16) /*!< id pin status */ +#define GOTGCS_DHNPEN BIT(11) /*!< device HNP enable */ +#define GOTGCS_HHNPEN BIT(10) /*!< host HNP enable */ +#define GOTGCS_HNPREQ BIT(9) /*!< HNP request */ +#define GOTGCS_HNPS BIT(8) /*!< HNP successes */ +#define GOTGCS_SRPREQ BIT(1) /*!< SRP request */ +#define GOTGCS_SRPS BIT(0) /*!< SRP successes */ + +/* global OTG interrupt flag register bits definitions */ +#define GOTGINTF_DF BIT(19) /*!< debounce finish */ +#define GOTGINTF_ADTO BIT(18) /*!< A-device timeout */ +#define GOTGINTF_HNPDET BIT(17) /*!< host negotiation request detected */ +#define GOTGINTF_HNPEND BIT(9) /*!< HNP end */ +#define GOTGINTF_SRPEND BIT(8) /*!< SRP end */ +#define GOTGINTF_SESEND BIT(2) /*!< session end */ + +/* global AHB control and status register bits definitions */ +#define GAHBCS_PTXFTH BIT(8) /*!< periodic Tx FIFO threshold */ +#define GAHBCS_TXFTH BIT(7) /*!< tx FIFO threshold */ +#define GAHBCS_DMAEN BIT(5) /*!< DMA function Enable */ +#define GAHBCS_BURST BITS(1, 4) /*!< the AHB burst type used by DMA */ +#define GAHBCS_GINTEN BIT(0) /*!< global interrupt enable */ + +/* global USB control and status register bits definitions */ +#define GUSBCS_FDM BIT(30) /*!< force device mode */ +#define GUSBCS_FHM BIT(29) /*!< force host mode */ +#define GUSBCS_ULPIEOI BIT(21) /*!< ULPI external over-current indicator */ +#define GUSBCS_ULPIEVD BIT(20) /*!< ULPI external VBUS driver */ +#define GUSBCS_UTT BITS(10, 13) /*!< USB turnaround time */ +#define GUSBCS_HNPCEN BIT(9) /*!< HNP capability enable */ +#define GUSBCS_SRPCEN BIT(8) /*!< SRP capability enable */ +#define GUSBCS_EMBPHY BIT(6) /*!< embedded PHY selected */ +#define GUSBCS_TOC BITS(0, 2) /*!< timeout calibration */ + +/* global reset control register bits definitions */ +#define GRSTCTL_DMAIDL BIT(31) /*!< DMA idle state */ +#define GRSTCTL_DMABSY BIT(30) /*!< DMA busy */ +#define GRSTCTL_TXFNUM BITS(6, 10) /*!< tx FIFO number */ +#define GRSTCTL_TXFF BIT(5) /*!< tx FIFO flush */ +#define GRSTCTL_RXFF BIT(4) /*!< rx FIFO flush */ +#define GRSTCTL_HFCRST BIT(2) /*!< host frame counter reset */ +#define GRSTCTL_HCSRST BIT(1) /*!< HCLK soft reset */ +#define GRSTCTL_CSRST BIT(0) /*!< core soft reset */ + +/* global interrupt flag register bits definitions */ +#define GINTF_WKUPIF BIT(31) /*!< wakeup interrupt flag */ +#define GINTF_SESIF BIT(30) /*!< session interrupt flag */ +#define GINTF_DISCIF BIT(29) /*!< disconnect interrupt flag */ +#define GINTF_IDPSC BIT(28) /*!< id pin status change */ +#define GINTF_PTXFEIF BIT(26) /*!< periodic tx FIFO empty interrupt flag */ +#define GINTF_HCIF BIT(25) /*!< host channels interrupt flag */ +#define GINTF_HPIF BIT(24) /*!< host port interrupt flag */ +#define GINTF_PXNCIF BIT(21) /*!< periodic transfer not complete interrupt flag */ +#define GINTF_ISOONCIF BIT(21) /*!< isochronous OUT transfer not complete interrupt flag */ +#define GINTF_ISOINCIF BIT(20) /*!< isochronous IN transfer not complete interrupt flag */ +#define GINTF_OEPIF BIT(19) /*!< OUT endpoint interrupt flag */ +#define GINTF_IEPIF BIT(18) /*!< IN endpoint interrupt flag */ +#define GINTF_EOPFIF BIT(15) /*!< end of periodic frame interrupt flag */ +#define GINTF_ISOOPDIF BIT(14) /*!< isochronous OUT packet dropped interrupt flag */ +#define GINTF_ENUMFIF BIT(13) /*!< enumeration finished */ +#define GINTF_RST BIT(12) /*!< USB reset */ +#define GINTF_SP BIT(11) /*!< USB suspend */ +#define GINTF_ESP BIT(10) /*!< early suspend */ +#define GINTF_GONAK BIT(7) /*!< global OUT NAK effective */ +#define GINTF_GNPINAK BIT(6) /*!< global IN non-periodic NAK effective */ +#define GINTF_NPTXFEIF BIT(5) /*!< non-periodic tx FIFO empty interrupt flag */ +#define GINTF_RXFNEIF BIT(4) /*!< rx FIFO non-empty interrupt flag */ +#define GINTF_SOF BIT(3) /*!< start of frame */ +#define GINTF_OTGIF BIT(2) /*!< OTG interrupt flag */ +#define GINTF_MFIF BIT(1) /*!< mode fault interrupt flag */ +#define GINTF_COPM BIT(0) /*!< current operation mode */ + +/* global interrupt enable register bits definitions */ +#define GINTEN_WKUPIE BIT(31) /*!< wakeup interrupt enable */ +#define GINTEN_SESIE BIT(30) /*!< session interrupt enable */ +#define GINTEN_DISCIE BIT(29) /*!< disconnect interrupt enable */ +#define GINTEN_IDPSCIE BIT(28) /*!< id pin status change interrupt enable */ +#define GINTEN_PTXFEIE BIT(26) /*!< periodic tx FIFO empty interrupt enable */ +#define GINTEN_HCIE BIT(25) /*!< host channels interrupt enable */ +#define GINTEN_HPIE BIT(24) /*!< host port interrupt enable */ +#define GINTEN_IPXIE BIT(21) /*!< periodic transfer not complete interrupt enable */ +#define GINTEN_ISOONCIE BIT(21) /*!< isochronous OUT transfer not complete interrupt enable */ +#define GINTEN_ISOINCIE BIT(20) /*!< isochronous IN transfer not complete interrupt enable */ +#define GINTEN_OEPIE BIT(19) /*!< OUT endpoints interrupt enable */ +#define GINTEN_IEPIE BIT(18) /*!< IN endpoints interrupt enable */ +#define GINTEN_EOPFIE BIT(15) /*!< end of periodic frame interrupt enable */ +#define GINTEN_ISOOPDIE BIT(14) /*!< isochronous OUT packet dropped interrupt enable */ +#define GINTEN_ENUMFIE BIT(13) /*!< enumeration finish enable */ +#define GINTEN_RSTIE BIT(12) /*!< USB reset interrupt enable */ +#define GINTEN_SPIE BIT(11) /*!< USB suspend interrupt enable */ +#define GINTEN_ESPIE BIT(10) /*!< early suspend interrupt enable */ +#define GINTEN_GONAKIE BIT(7) /*!< global OUT NAK effective interrupt enable */ +#define GINTEN_GNPINAKIE BIT(6) /*!< global non-periodic IN NAK effective interrupt enable */ +#define GINTEN_NPTXFEIE BIT(5) /*!< non-periodic Tx FIFO empty interrupt enable */ +#define GINTEN_RXFNEIE BIT(4) /*!< receive FIFO non-empty interrupt enable */ +#define GINTEN_SOFIE BIT(3) /*!< start of frame interrupt enable */ +#define GINTEN_OTGIE BIT(2) /*!< OTG interrupt enable */ +#define GINTEN_MFIE BIT(1) /*!< mode fault interrupt enable */ + +/* global receive status read and pop register bits definitions */ +#define GRSTATRP_RPCKST BITS(17, 20) /*!< received packet status */ +#define GRSTATRP_DPID BITS(15, 16) /*!< data PID */ +#define GRSTATRP_BCOUNT BITS(4, 14) /*!< byte count */ +#define GRSTATRP_CNUM BITS(0, 3) /*!< channel number */ +#define GRSTATRP_EPNUM BITS(0, 3) /*!< endpoint number */ + +/* global receive FIFO length register bits definitions */ +#define GRFLEN_RXFD BITS(0, 15) /*!< rx FIFO depth */ + +/* host non-periodic transmit FIFO length register bits definitions */ +#define HNPTFLEN_HNPTXFD BITS(16, 31) /*!< non-periodic Tx FIFO depth */ +#define HNPTFLEN_HNPTXRSAR BITS(0, 15) /*!< non-periodic Tx RAM start address */ + +/** + * @brief USB IN endpoint 0 transmit FIFO length register bits definitions + */ +#define DIEP0TFLEN_IEP0TXFD BITS(16, 31) /*!< IN Endpoint 0 Tx FIFO depth */ +#define DIEP0TFLEN_IEP0TXRSAR BITS(0, 15) /*!< IN Endpoint 0 TX RAM start address */ + +/* host non-periodic transmit FIFO/queue status register bits definitions */ +#define HNPTFQSTAT_NPTXRQTOP BITS(24, 30) /*!< top entry of the non-periodic Tx request queue */ +#define HNPTFQSTAT_NPTXRQS BITS(16, 23) /*!< non-periodic Tx request queue space */ +#define HNPTFQSTAT_NPTXFS BITS(0, 15) /*!< non-periodic Tx FIFO space */ +#define HNPTFQSTAT_CNUM BITS(27, 30) /*!< channel number*/ +#define HNPTFQSTAT_EPNUM BITS(27, 30) /*!< endpoint number */ +#define HNPTFQSTAT_TYPE BITS(25, 26) /*!< token type */ +#define HNPTFQSTAT_TMF BIT(24) /*!< terminate flag */ + +/* global core configuration register bits definitions */ +#define GCCFG_VBUSIG BIT(21) /*!< vbus ignored */ +#define GCCFG_SOFOEN BIT(20) /*!< SOF output enable */ +#define GCCFG_VBUSBCEN BIT(19) /*!< the VBUS B-device comparer enable */ +#define GCCFG_VBUSACEN BIT(18) /*!< the VBUS A-device comparer enable */ +#define GCCFG_PWRON BIT(16) /*!< power on */ + +/* core ID register bits definitions */ +#define CID_CID BITS(0, 31) /*!< core ID */ + +/* host periodic transmit FIFO length register bits definitions */ +#define HPTFLEN_HPTXFD BITS(16, 31) /*!< host periodic Tx FIFO depth */ +#define HPTFLEN_HPTXFSAR BITS(0, 15) /*!< host periodic Tx RAM start address */ + +/* device IN endpoint transmit FIFO length register bits definitions */ +#define DIEPTFLEN_IEPTXFD BITS(16, 31) /*!< IN endpoint Tx FIFO x depth */ +#define DIEPTFLEN_IEPTXRSAR BITS(0, 15) /*!< IN endpoint FIFOx Tx x RAM start address */ + +/* host control register bits definitions */ +#define HCTL_SPDFSLS BIT(2) /*!< speed limited to FS and LS */ +#define HCTL_CLKSEL BITS(0, 1) /*!< clock select for USB clock */ + +/* host frame interval register bits definitions */ +#define HFT_FRI BITS(0, 15) /*!< frame interval */ + +/* host frame information remaining register bits definitions */ +#define HFINFR_FRT BITS(16, 31) /*!< frame remaining time */ +#define HFINFR_FRNUM BITS(0, 15) /*!< frame number */ + +/* host periodic transmit FIFO/queue status register bits definitions */ +#define HPTFQSTAT_PTXREQT BITS(24, 31) /*!< top entry of the periodic Tx request queue */ +#define HPTFQSTAT_PTXREQS BITS(16, 23) /*!< periodic Tx request queue space */ +#define HPTFQSTAT_PTXFS BITS(0, 15) /*!< periodic Tx FIFO space */ +#define HPTFQSTAT_OEFRM BIT(31) /*!< odd/eveb frame */ +#define HPTFQSTAT_CNUM BITS(27, 30) /*!< channel number */ +#define HPTFQSTAT_EPNUM BITS(27, 30) /*!< endpoint number */ +#define HPTFQSTAT_TYPE BITS(25, 26) /*!< token type */ +#define HPTFQSTAT_TMF BIT(24) /*!< terminate flag */ + + +#define TFQSTAT_TXFS BITS(0, 15) +#define TFQSTAT_CNUM BITS(27, 30) + +/* host all channels interrupt register bits definitions */ +#define HACHINT_HACHINT BITS(0, 11) /*!< host all channel interrupts */ + +/* host all channels interrupt enable register bits definitions */ +#define HACHINTEN_CINTEN BITS(0, 11) /*!< channel interrupt enable */ + +/* host port control and status register bits definitions */ +#define HPCS_PS BITS(17, 18) /*!< port speed */ +#define HPCS_PP BIT(12) /*!< port power */ +#define HPCS_PLST BITS(10, 11) /*!< port line status */ +#define HPCS_PRST BIT(8) /*!< port reset */ +#define HPCS_PSP BIT(7) /*!< port suspend */ +#define HPCS_PREM BIT(6) /*!< port resume */ +#define HPCS_PEDC BIT(3) /*!< port enable/disable change */ +#define HPCS_PE BIT(2) /*!< port enable */ +#define HPCS_PCD BIT(1) /*!< port connect detected */ +#define HPCS_PCST BIT(0) /*!< port connect status */ + +/* host channel-x control register bits definitions */ +#define HCHCTL_CEN BIT(31) /*!< channel enable */ +#define HCHCTL_CDIS BIT(30) /*!< channel disable */ +#define HCHCTL_ODDFRM BIT(29) /*!< odd frame */ +#define HCHCTL_DAR BITS(22, 28) /*!< device address */ +#define HCHCTL_MPC BITS(20, 21) /*!< multiple packet count */ +#define HCHCTL_EPTYPE BITS(18, 19) /*!< endpoint type */ +#define HCHCTL_LSD BIT(17) /*!< low-speed device */ +#define HCHCTL_EPDIR BIT(15) /*!< endpoint direction */ +#define HCHCTL_EPNUM BITS(11, 14) /*!< endpoint number */ +#define HCHCTL_MPL BITS(0, 10) /*!< maximum packet length */ + +/* host channel-x split transaction register bits definitions */ +#define HCHSTCTL_SPLEN BIT(31) /*!< enable high-speed split transaction */ +#define HCHSTCTL_CSPLT BIT(16) /*!< complete-split enable */ +#define HCHSTCTL_ISOPCE BITS(14, 15) /*!< isochronous OUT payload continuation encoding */ +#define HCHSTCTL_HADDR BITS(7, 13) /*!< HUB address */ +#define HCHSTCTL_PADDR BITS(0, 6) /*!< port address */ + +/* host channel-x interrupt flag register bits definitions */ +#define HCHINTF_DTER BIT(10) /*!< data toggle error */ +#define HCHINTF_REQOVR BIT(9) /*!< request queue overrun */ +#define HCHINTF_BBER BIT(8) /*!< babble error */ +#define HCHINTF_USBER BIT(7) /*!< USB bus Error */ +#define HCHINTF_NYET BIT(6) /*!< NYET */ +#define HCHINTF_ACK BIT(5) /*!< ACK */ +#define HCHINTF_NAK BIT(4) /*!< NAK */ +#define HCHINTF_STALL BIT(3) /*!< STALL */ +#define HCHINTF_DMAER BIT(2) /*!< DMA error */ +#define HCHINTF_CH BIT(1) /*!< channel halted */ +#define HCHINTF_TF BIT(0) /*!< transfer finished */ + +/* host channel-x interrupt enable register bits definitions */ +#define HCHINTEN_DTERIE BIT(10) /*!< data toggle error interrupt enable */ +#define HCHINTEN_REQOVRIE BIT(9) /*!< request queue overrun interrupt enable */ +#define HCHINTEN_BBERIE BIT(8) /*!< babble error interrupt enable */ +#define HCHINTEN_USBERIE BIT(7) /*!< USB bus error interrupt enable */ +#define HCHINTEN_NYETIE BIT(6) /*!< NYET interrupt enable */ +#define HCHINTEN_ACKIE BIT(5) /*!< ACK interrupt enable */ +#define HCHINTEN_NAKIE BIT(4) /*!< NAK interrupt enable */ +#define HCHINTEN_STALLIE BIT(3) /*!< STALL interrupt enable */ +#define HCHINTEN_DMAERIE BIT(2) /*!< DMA error interrupt enable */ +#define HCHINTEN_CHIE BIT(1) /*!< channel halted interrupt enable */ +#define HCHINTEN_TFIE BIT(0) /*!< transfer finished interrupt enable */ + +/* host channel-x transfer length register bits definitions */ +#define HCHLEN_PING BIT(31) /*!< PING token request */ +#define HCHLEN_DPID BITS(29, 30) /*!< data PID */ +#define HCHLEN_PCNT BITS(19, 28) /*!< packet count */ +#define HCHLEN_TLEN BITS(0, 18) /*!< transfer length */ + +/* host channel-x DMA address register bits definitions */ +#define HCHDMAADDR_DMAADDR BITS(0, 31) /*!< DMA address */ + + +#define PORT_SPEED(x) (((uint32_t)(x) << 17) & HPCS_PS) /*!< Port speed */ + +#define PORT_SPEED_HIGH PORT_SPEED(0U) /*!< high speed */ +#define PORT_SPEED_FULL PORT_SPEED(1U) /*!< full speed */ +#define PORT_SPEED_LOW PORT_SPEED(2U) /*!< low speed */ + +#define PIPE_CTL_DAR(x) (((uint32_t)(x) << 22) & HCHCTL_DAR) /*!< device address */ +#define PIPE_CTL_EPTYPE(x) (((uint32_t)(x) << 18) & HCHCTL_EPTYPE) /*!< endpoint type */ +#define PIPE_CTL_EPNUM(x) (((uint32_t)(x) << 11) & HCHCTL_EPNUM) /*!< endpoint number */ +#define PIPE_CTL_EPDIR(x) (((uint32_t)(x) << 15) & HCHCTL_EPDIR) /*!< endpoint direction */ +#define PIPE_CTL_EPMPL(x) (((uint32_t)(x) << 0) & HCHCTL_MPL) /*!< maximum packet length */ +#define PIPE_CTL_LSD(x) (((uint32_t)(x) << 17) & HCHCTL_LSD) /*!< low-Speed device */ + +#define PIPE_XFER_PCNT(x) (((uint32_t)(x) << 19) & HCHLEN_PCNT) /*!< packet count */ +#define PIPE_XFER_DPID(x) (((uint32_t)(x) << 29) & HCHLEN_DPID) /*!< data PID */ + +#define PIPE_DPID_DATA0 PIPE_XFER_DPID(0) /*!< DATA0 */ +#define PIPE_DPID_DATA1 PIPE_XFER_DPID(2) /*!< DATA1 */ +#define PIPE_DPID_DATA2 PIPE_XFER_DPID(1) /*!< DATA2 */ +#define PIPE_DPID_SETUP PIPE_XFER_DPID(3) /*!< MDATA (non-control)/SETUP (control) */ + +extern const uint32_t PIPE_DPID[2]; + +/* device configuration registers bits definitions */ +#define DCFG_EOPFT BITS(11, 12) /*!< end of periodic frame time */ +#define DCFG_DAR BITS(4, 10) /*!< device address */ +#define DCFG_NZLSOH BIT(2) /*!< non-zero-length status OUT handshake */ +#define DCFG_DS BITS(0, 1) /*!< device speed */ + +/* device control registers bits definitions */ +#define DCTL_POIF BIT(11) /*!< power-on initialization finished */ +#define DCTL_CGONAK BIT(10) /*!< clear global OUT NAK */ +#define DCTL_SGONAK BIT(9) /*!< set global OUT NAK */ +#define DCTL_CGINAK BIT(8) /*!< clear global IN NAK */ +#define DCTL_SGINAK BIT(7) /*!< set global IN NAK */ +#define DCTL_GONS BIT(3) /*!< global OUT NAK status */ +#define DCTL_GINS BIT(2) /*!< global IN NAK status */ +#define DCTL_SD BIT(1) /*!< soft disconnect */ +#define DCTL_RWKUP BIT(0) /*!< remote wakeup */ + +/* device status registers bits definitions */ +#define DSTAT_FNRSOF BITS(8, 21) /*!< the frame number of the received SOF. */ +#define DSTAT_ES BITS(1, 2) /*!< enumerated speed */ +#define DSTAT_SPST BIT(0) /*!< suspend status */ + +/* device IN endpoint common interrupt enable registers bits definitions */ +#define DIEPINTEN_NAKEN BIT(13) /*!< NAK handshake sent by USBHS interrupt enable bit */ +#define DIEPINTEN_TXFEEN BIT(7) /*!< transmit FIFO empty interrupt enable bit */ +#define DIEPINTEN_IEPNEEN BIT(6) /*!< IN endpoint NAK effective interrupt enable bit */ +#define DIEPINTEN_EPTXFUDEN BIT(4) /*!< endpoint Tx FIFO underrun interrupt enable bit */ +#define DIEPINTEN_CITOEN BIT(3) /*!< control In Timeout interrupt enable bit */ +#define DIEPINTEN_EPDISEN BIT(1) /*!< endpoint disabled interrupt enable bit */ +#define DIEPINTEN_TFEN BIT(0) /*!< transfer finished interrupt enable bit */ + +/* device OUT endpoint common interrupt enable registers bits definitions */ +#define DOEPINTEN_NYETEN BIT(14) /*!< NYET handshake is sent interrupt enable bit */ +#define DOEPINTEN_BTBSTPEN BIT(6) /*!< back-to-back SETUP packets interrupt enable bit */ +#define DOEPINTEN_EPRXFOVREN BIT(4) /*!< endpoint Rx FIFO overrun interrupt enable bit */ +#define DOEPINTEN_STPFEN BIT(3) /*!< SETUP phase finished interrupt enable bit */ +#define DOEPINTEN_EPDISEN BIT(1) /*!< endpoint disabled interrupt enable bit */ +#define DOEPINTEN_TFEN BIT(0) /*!< transfer finished interrupt enable bit */ + +/* device all endpoints interrupt registers bits definitions */ +#define DAEPINT_OEPITB BITS(16, 21) /*!< device all OUT endpoint interrupt bits */ +#define DAEPINT_IEPITB BITS(0, 5) /*!< device all IN endpoint interrupt bits */ + +/* device all endpoints interrupt enable registers bits definitions */ +#define DAEPINTEN_OEPIE BITS(16, 21) /*!< OUT endpoint interrupt enable */ +#define DAEPINTEN_IEPIE BITS(0, 3) /*!< IN endpoint interrupt enable */ + +/* device Vbus discharge time registers bits definitions */ +#define DVBUSDT_DVBUSDT BITS(0, 15) /*!< device VBUS discharge time */ + +/* device Vbus pulsing time registers bits definitions */ +#define DVBUSPT_DVBUSPT BITS(0, 11) /*!< device VBUS pulsing time */ + +/* device IN endpoint FIFO empty interrupt enable register bits definitions */ +#define DIEPFEINTEN_IEPTXFEIE BITS(0, 5) /*!< IN endpoint Tx FIFO empty interrupt enable bits */ + +/* device endpoint 0 control register bits definitions */ +#define DEP0CTL_EPEN BIT(31) /*!< endpoint enable */ +#define DEP0CTL_EPD BIT(30) /*!< endpoint disable */ +#define DEP0CTL_SNAK BIT(27) /*!< set NAK */ +#define DEP0CTL_CNAK BIT(26) /*!< clear NAK */ +#define DIEP0CTL_TXFNUM BITS(22, 25) /*!< tx FIFO number */ +#define DEP0CTL_STALL BIT(21) /*!< STALL handshake */ +#define DOEP0CTL_SNOOP BIT(20) /*!< snoop mode */ +#define DEP0CTL_EPTYPE BITS(18, 19) /*!< endpoint type */ +#define DEP0CTL_NAKS BIT(17) /*!< NAK status */ +#define DEP0CTL_EPACT BIT(15) /*!< endpoint active */ +#define DEP0CTL_MPL BITS(0, 1) /*!< maximum packet length */ + +/* device endpoint x control register bits definitions */ +#define DEPCTL_EPEN BIT(31) /*!< endpoint enable */ +#define DEPCTL_EPD BIT(30) /*!< endpoint disable */ +#define DEPCTL_SODDFRM BIT(29) /*!< set odd frame */ +#define DEPCTL_SD1PID BIT(29) /*!< set DATA1 PID */ +#define DEPCTL_SEVNFRM BIT(28) /*!< set even frame */ +#define DEPCTL_SD0PID BIT(28) /*!< set DATA0 PID */ +#define DEPCTL_SNAK BIT(27) /*!< set NAK */ +#define DEPCTL_CNAK BIT(26) /*!< clear NAK */ +#define DIEPCTL_TXFNUM BITS(22, 25) /*!< tx FIFO number */ +#define DEPCTL_STALL BIT(21) /*!< STALL handshake */ +#define DOEPCTL_SNOOP BIT(20) /*!< snoop mode */ +#define DEPCTL_EPTYPE BITS(18, 19) /*!< endpoint type */ +#define DEPCTL_NAKS BIT(17) /*!< NAK status */ +#define DEPCTL_EOFRM BIT(16) /*!< even/odd frame */ +#define DEPCTL_DPID BIT(16) /*!< endpoint data PID */ +#define DEPCTL_EPACT BIT(15) /*!< endpoint active */ +#define DEPCTL_MPL BITS(0, 10) /*!< maximum packet length */ + +/* device IN endpoint-x interrupt flag register bits definitions */ +#define DIEPINTF_NAK BIT(13) /*!< NAK handshake sent by USBHS */ +#define DIEPINTF_TXFE BIT(7) /*!< transmit FIFO empty */ +#define DIEPINTF_IEPNE BIT(6) /*!< IN endpoint NAK effective */ +#define DIEPINTF_EPTXFUD BIT(4) /*!< endpoint Tx FIFO underrun */ +#define DIEPINTF_CITO BIT(3) /*!< control In Timeout interrupt */ +#define DIEPINTF_EPDIS BIT(1) /*!< endpoint disabled */ +#define DIEPINTF_TF BIT(0) /*!< transfer finished */ + +/* device OUT endpoint-x interrupt flag register bits definitions */ +#define DOEPINTF_NYET BIT(14) /*!< NYET handshake is sent */ +#define DOEPINTF_BTBSTP BIT(6) /*!< back-to-back SETUP packets */ +#define DOEPINTF_EPRXFOVR BIT(4) /*!< endpoint Rx FIFO overrun */ +#define DOEPINTF_STPF BIT(3) /*!< SETUP phase finished */ +#define DOEPINTF_EPDIS BIT(1) /*!< endpoint disabled */ +#define DOEPINTF_TF BIT(0) /*!< transfer finished */ + +/* device IN endpoint 0 transfer length register bits definitions */ +#define DIEP0LEN_PCNT BITS(19, 20) /*!< packet count */ +#define DIEP0LEN_TLEN BITS(0, 6) /*!< transfer length */ + +/* device OUT endpoint 0 transfer length register bits definitions */ +#define DOEP0LEN_STPCNT BITS(29, 30) /*!< SETUP packet count */ +#define DOEP0LEN_PCNT BIT(19) /*!< packet count */ +#define DOEP0LEN_TLEN BITS(0, 6) /*!< transfer length */ + +/* device OUT endpoint-x transfer length register bits definitions */ +#define DOEPLEN_RXDPID BITS(29, 30) /*!< received data PID */ +#define DOEPLEN_STPCNT BITS(29, 30) /*!< SETUP packet count */ +#define DIEPLEN_MCNT BITS(29, 30) /*!< multi count */ +#define DEPLEN_PCNT BITS(19, 28) /*!< packet count */ +#define DEPLEN_TLEN BITS(0, 18) /*!< transfer length */ + +/* device IN endpoint-x DMA address register bits definitions */ +#define DIEPDMAADDR_DMAADDR BITS(0, 31) /*!< DMA address */ + +/* device OUT endpoint-x DMA address register bits definitions */ +#define DOEPDMAADDR_DMAADDR BITS(0, 31) /*!< DMA address */ + +/* device IN endpoint-x transmit FIFO status register bits definitions */ +#define DIEPTFSTAT_IEPTFS BITS(0, 15) /*!< IN endpoint Tx FIFO space remaining */ + +/* USB power and clock registers bits definition */ +#define PWRCLKCTL_SHCLK BIT(1) /*!< stop HCLK */ +#define PWRCLKCTL_SUCLK BIT(0) /*!< stop the USB clock */ + +#define RSTAT_GOUT_NAK 1U /* global OUT NAK (triggers an interrupt) */ +#define RSTAT_DATA_UPDT 2U /* OUT data packet received */ +#define RSTAT_XFER_COMP 3U /* OUT transfer completed (triggers an interrupt) */ +#define RSTAT_SETUP_COMP 4U /* SETUP transaction completed (triggers an interrupt) */ +#define RSTAT_SETUP_UPDT 6U /* SETUP data packet received */ + +#define DSTAT_EM_HS_PHY_30MHZ_60MHZ 0U /* USB enumerate speed use high-speed PHY clock in 30MHz or 60MHz */ +#define DSTAT_EM_FS_PHY_30MHZ_60MHZ 1U /* USB enumerate speed use full-speed PHY clock in 30MHz or 60MHz */ +#define DSTAT_EM_LS_PHY_6MHZ 2U /* USB enumerate speed use low-speed PHY clock in 6MHz */ +#define DSTAT_EM_FS_PHY_48MHZ 3U /* USB enumerate speed use full-speed PHY clock in 48MHz */ + +#define DPID_DATA0 0U /* device endpoint data PID is DATA0 */ +#define DPID_DATA1 2U /* device endpoint data PID is DATA1 */ +#define DPID_DATA2 1U /* device endpoint data PID is DATA2 */ +#define DPID_MDATA 3U /* device endpoint data PID is MDATA */ + +#define GAHBCS_DMAINCR(regval) (GAHBCS_BURST & ((regval) << 1)) /*!< AHB burst type used by DMA*/ + +#define DMA_INCR0 GAHBCS_DMAINCR(0U) /*!< single burst type used by DMA*/ +#define DMA_INCR1 GAHBCS_DMAINCR(1U) /*!< 4-beat incrementing burst type used by DMA*/ +#define DMA_INCR4 GAHBCS_DMAINCR(3U) /*!< 8-beat incrementing burst type used by DMA*/ +#define DMA_INCR8 GAHBCS_DMAINCR(5U) /*!< 16-beat incrementing burst type used by DMA*/ +#define DMA_INCR16 GAHBCS_DMAINCR(7U) /*!< 32-beat incrementing burst type used by DMA*/ + +#define DCFG_PFRI(regval) (DCFG_EOPFT & ((regval) << 11)) /*!< end of periodic frame time configuration */ + +#define FRAME_INTERVAL_80 DCFG_PFRI(0U) /*!< 80% of the frame time */ +#define FRAME_INTERVAL_85 DCFG_PFRI(1U) /*!< 85% of the frame time */ +#define FRAME_INTERVAL_90 DCFG_PFRI(2U) /*!< 90% of the frame time */ +#define FRAME_INTERVAL_95 DCFG_PFRI(3U) /*!< 95% of the frame time */ + +#define DCFG_DEVSPEED(regval) (DCFG_DS & ((regval) << 0)) /*!< device speed configuration */ + +#define USB_SPEED_EXP_HIGH DCFG_DEVSPEED(0U) /*!< device external PHY high speed */ +#define USB_SPEED_EXP_FULL DCFG_DEVSPEED(1U) /*!< device external PHY full speed */ +#define USB_SPEED_INP_FULL DCFG_DEVSPEED(3U) /*!< device internal PHY full speed */ + +#define DEP0_MPL(regval) (DEP0CTL_MPL & ((regval) << 0)) /*!< maximum packet length configuration */ + +#define EP0MPL_64 DEP0_MPL(0U) /*!< maximum packet length 64 bytes */ +#define EP0MPL_32 DEP0_MPL(1U) /*!< maximum packet length 32 bytes */ +#define EP0MPL_16 DEP0_MPL(2U) /*!< maximum packet length 16 bytes */ +#define EP0MPL_8 DEP0_MPL(3U) /*!< maximum packet length 8 bytes */ + +#define DOEP0_TLEN(regval) (DOEP0LEN_TLEN & ((regval) << 0)) /*!< transfer length */ +#define DOEP0_PCNT(regval) (DOEP0LEN_PCNT & ((regval) << 19)) /*!< packet count */ +#define DOEP0_STPCNT(regval) (DOEP0LEN_STPCNT & ((regval) << 29)) /*!< SETUP packet count */ + +#define USB_ULPI_PHY 1U /*!< ULPI interface external PHY */ +#define USB_EMBEDDED_PHY 2U /*!< embedded PHY */ + +#define GRXSTS_PKTSTS_IN 2U +#define GRXSTS_PKTSTS_IN_XFER_COMP 3U +#define GRXSTS_PKTSTS_DATA_TOGGLE_ERR 5U +#define GRXSTS_PKTSTS_CH_HALTED 7U + +#define HCTL_30_60MHZ 0U /*!< USB clock 30-60MHZ */ +#define HCTL_48MHZ 1U /*!< USB clock 48MHZ */ +#define HCTL_6MHZ 2U /*!< USB clock 6MHZ */ + +#define EP0_OUT ((uint8_t)0x00) /*!< endpoint out 0 */ +#define EP0_IN ((uint8_t)0x80) /*!< endpoint in 0 */ +#define EP1_OUT ((uint8_t)0x01) /*!< endpoint out 1 */ +#define EP1_IN ((uint8_t)0x81) /*!< endpoint in 1 */ +#define EP2_OUT ((uint8_t)0x02) /*!< endpoint out 2 */ +#define EP2_IN ((uint8_t)0x82) /*!< endpoint in 2 */ +#define EP3_OUT ((uint8_t)0x03) /*!< endpoint out 3 */ +#define EP3_IN ((uint8_t)0x83) /*!< endpoint in 3 */ + +#endif /* __DRV_USB_REGS_H */ diff --git a/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/driver/Include/drv_usbd_int.h b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/driver/Include/drv_usbd_int.h new file mode 100644 index 0000000000..09cddd8d11 --- /dev/null +++ b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/driver/Include/drv_usbd_int.h @@ -0,0 +1,45 @@ +/*! + \file drv_usbd_int.h + \brief USB device mode interrupt header file + + \version 2020-07-17, V3.0.0, firmware for GD32F10x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef __DRV_USBD_INT_H +#define __DRV_USBD_INT_H + +#include "drv_usb_core.h" +#include "drv_usb_dev.h" + +/* function declarations */ +/* USB device-mode interrupts global service routine handler */ +void usbd_isr (usb_core_driver *udev); + +#endif /* __DRV_USBD_INT_H */ diff --git a/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/driver/Include/drv_usbh_int.h b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/driver/Include/drv_usbh_int.h new file mode 100644 index 0000000000..80ba44f3d6 --- /dev/null +++ b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/driver/Include/drv_usbh_int.h @@ -0,0 +1,56 @@ +/*! + \file drv_usbh_int.h.h + \brief USB host mode interrupt management header file + + \version 2020-07-17, V3.0.0, firmware for GD32F10x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef __DRV_USBH_INT_H +#define __DRV_USBH_INT_H + +#include "drv_usb_host.h" +#include "usbh_core.h" + +typedef struct _usbh_int_cb +{ + uint8_t (*connect) (usbh_host *uhost); + uint8_t (*disconnect) (usbh_host *uhost); + uint8_t (*port_enabled) (usbh_host *uhost); + uint8_t (*port_disabled) (usbh_host *uhost); + uint8_t (*SOF) (usbh_host *uhost); +} usbh_int_cb; + +extern usbh_int_cb *usbh_int_fop; + +/* function declarations */ +/* handle global host interrupt */ +uint32_t usbh_isr (usb_core_driver *udev); + +#endif /* __DRV_USBH_INT_H */ diff --git a/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/driver/Source/drv_usb_core.c b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/driver/Source/drv_usb_core.c new file mode 100644 index 0000000000..1619583933 --- /dev/null +++ b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/driver/Source/drv_usb_core.c @@ -0,0 +1,344 @@ +/*! + \file drv_usb_core.c + \brief USB core driver which can operate in host and device mode + + \version 2020-07-17, V3.0.0, firmware for GD32F10x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "drv_usb_core.h" +#include "drv_usb_hw.h" + +/* local function prototypes ('static') */ +static void usb_core_reset (usb_core_regs *usb_regs); + +/*! + \brief configure USB core basic + \param[in] usb_basic: pointer to USB capabilities + \param[in] usb_regs: USB core registers + \param[in] usb_core: USB core + \param[out] none + \retval operation status +*/ +usb_status usb_basic_init (usb_core_basic *usb_basic, + usb_core_regs *usb_regs, + usb_core_enum usb_core) +{ + /* configure USB default transfer mode as FIFO mode */ + usb_basic->transfer_mode = (uint8_t)USB_USE_FIFO; + + /* USB default speed is full-speed */ + usb_basic->core_speed = (uint8_t)USB_SPEED_FULL; + + usb_basic->core_enum = (uint8_t)usb_core; + + switch (usb_core) { + case USB_CORE_ENUM_FS: + usb_basic->base_reg = (uint32_t)USBFS_REG_BASE; + + /* set the host channel numbers */ + usb_basic->num_pipe = USBFS_MAX_CHANNEL_COUNT; + + /* set the device endpoint numbers */ + usb_basic->num_ep = USBFS_MAX_EP_COUNT; + + /* USBFS core use embedded physical layer */ + usb_basic->phy_itf = USB_EMBEDDED_PHY; + break; + + default: + return USB_FAIL; + } + + usb_basic->sof_enable = USB_SOF_OUTPUT; + usb_basic->low_power = USB_LOW_POWER; + + /* assign main registers address */ + *usb_regs = (usb_core_regs) { + .gr = (usb_gr*) (usb_basic->base_reg + USB_REG_OFFSET_CORE), + .hr = (usb_hr*) (usb_basic->base_reg + USB_REG_OFFSET_HOST), + .dr = (usb_dr*) (usb_basic->base_reg + USB_REG_OFFSET_DEV), + + .HPCS = (uint32_t*) (usb_basic->base_reg + USB_REG_OFFSET_PORT), + .PWRCLKCTL = (uint32_t*) (usb_basic->base_reg + USB_REG_OFFSET_PWRCLKCTL) + }; + + /* assign device endpoint registers address */ + for (uint8_t i = 0U; i < usb_basic->num_ep; i++) { + usb_regs->er_in[i] = (usb_erin *) \ + (usb_basic->base_reg + USB_REG_OFFSET_EP_IN + (i * USB_REG_OFFSET_EP)); + + usb_regs->er_out[i] = (usb_erout *)\ + (usb_basic->base_reg + USB_REG_OFFSET_EP_OUT + (i * USB_REG_OFFSET_EP)); + } + + /* assign host pipe registers address */ + for (uint8_t i = 0U; i < usb_basic->num_pipe; i++) { + usb_regs->pr[i] = (usb_pr *) \ + (usb_basic->base_reg + USB_REG_OFFSET_CH_INOUT + (i * USB_REG_OFFSET_CH)); + + usb_regs->DFIFO[i] = (uint32_t *) \ + (usb_basic->base_reg + USB_DATA_FIFO_OFFSET + (i * USB_DATA_FIFO_SIZE)); + } + + return USB_OK; +} + +/*! + \brief initializes the USB controller registers and + prepares the core device mode or host mode operation + \param[in] usb_basic: pointer to USB capabilities + \param[in] usb_regs: pointer to USB core registers + \param[out] none + \retval operation status +*/ +usb_status usb_core_init (usb_core_basic usb_basic, usb_core_regs *usb_regs) +{ + if (USB_ULPI_PHY == usb_basic.phy_itf) { + usb_regs->gr->GCCFG &= ~GCCFG_PWRON; + + if (usb_basic.sof_enable) { + usb_regs->gr->GCCFG |= GCCFG_SOFOEN; + } + + /* initialize the ULPI interface */ + usb_regs->gr->GUSBCS &= ~(GUSBCS_EMBPHY | GUSBCS_ULPIEOI); + +#ifdef USBHS_EXTERNAL_VBUS_ENABLED + /* use external VBUS driver */ + usb_regs->gr->GUSBCS |= GUSBCS_ULPIEVD; +#else + /* use internal VBUS driver */ + usb_regs->gr->GUSBCS &= ~GUSBCS_ULPIEVD; +#endif /* USBHS_EXTERNAL_VBUS_ENABLED */ + + /* soft reset the core */ + usb_core_reset (usb_regs); + } else { + usb_regs->gr->GUSBCS |= GUSBCS_EMBPHY; + + /* soft reset the core */ + usb_core_reset (usb_regs); + + /* active the transceiver and enable VBUS sensing */ + usb_regs->gr->GCCFG |= GCCFG_PWRON | GCCFG_VBUSACEN | GCCFG_VBUSBCEN; + +#ifndef VBUS_SENSING_ENABLED + usb_regs->gr->GCCFG |= GCCFG_VBUSIG; +#endif /* VBUS_SENSING_ENABLED */ + + /* enable SOF output */ + if (usb_basic.sof_enable) { + usb_regs->gr->GCCFG |= GCCFG_SOFOEN; + } + + usb_mdelay(20U); + } + + if ((uint8_t)USB_USE_DMA == usb_basic.transfer_mode) { + usb_regs->gr->GAHBCS &= ~GAHBCS_BURST; + usb_regs->gr->GAHBCS |= DMA_INCR8 | GAHBCS_DMAEN; + } + +#ifdef USE_OTG_MODE + + /* enable USB OTG features */ + usb_regs->gr->GUSBCS |= GUSBCS_HNPCEN | GUSBCS_SRPCEN; + + /* enable the USB wakeup and suspend interrupts */ + usb_regs->gr->GINTF = 0xBFFFFFFFU; + + usb_regs->gr->GINTEN = GINTEN_WKUPIE | GINTEN_SPIE | \ + GINTEN_OTGIE | GINTEN_SESIE | GINTEN_CIDPSCIE; + +#endif /* USE_OTG_MODE */ + + return USB_OK; +} + +/*! + \brief write a packet into the TX FIFO associated with the endpoint + \param[in] usb_regs: pointer to USB core registers + \param[in] src_buf: pointer to source buffer + \param[in] fifo_num: FIFO number which is in (0..3) + \param[in] byte_count: packet byte count + \param[out] none + \retval operation status +*/ +usb_status usb_txfifo_write (usb_core_regs *usb_regs, + uint8_t *src_buf, + uint8_t fifo_num, + uint16_t byte_count) +{ + uint32_t word_count = (byte_count + 3U) / 4U; + + __IO uint32_t *fifo = usb_regs->DFIFO[fifo_num]; + + while (word_count-- > 0U) { + *fifo = *((__packed uint32_t *)src_buf); + + src_buf += 4U; + } + + return USB_OK; +} + +/*! + \brief read a packet from the Rx FIFO associated with the endpoint + \param[in] usb_regs: pointer to USB core registers + \param[in] dest_buf: pointer to destination buffer + \param[in] byte_count: packet byte count + \param[out] none + \retval void type pointer +*/ +void *usb_rxfifo_read (usb_core_regs *usb_regs, uint8_t *dest_buf, uint16_t byte_count) +{ + uint32_t word_count = (byte_count + 3U) / 4U; + + __IO uint32_t *fifo = usb_regs->DFIFO[0]; + + while (word_count-- > 0U) { + *(__packed uint32_t *)dest_buf = *fifo; + + dest_buf += 4U; + } + + return ((void *)dest_buf); +} + +/*! + \brief flush a TX FIFO or all TX FIFOs + \param[in] usb_regs: pointer to USB core registers + \param[in] fifo_num: FIFO number which is in (0..3) + \param[out] none + \retval operation status +*/ +usb_status usb_txfifo_flush (usb_core_regs *usb_regs, uint8_t fifo_num) +{ + usb_regs->gr->GRSTCTL = ((uint32_t)fifo_num << 6U) | GRSTCTL_TXFF; + + /* wait for TX FIFO flush bit is set */ + while (usb_regs->gr->GRSTCTL & GRSTCTL_TXFF) { + /* no operation */ + } + + /* wait for 3 PHY clocks*/ + usb_udelay(3U); + + return USB_OK; +} + +/*! + \brief flush the entire Rx FIFO + \param[in] usb_regs: pointer to USB core registers + \param[out] none + \retval operation status +*/ +usb_status usb_rxfifo_flush (usb_core_regs *usb_regs) +{ + usb_regs->gr->GRSTCTL = GRSTCTL_RXFF; + + /* wait for RX FIFO flush bit is set */ + while (usb_regs->gr->GRSTCTL & GRSTCTL_RXFF) { + /* no operation */ + } + + /* wait for 3 PHY clocks */ + usb_udelay(3U); + + return USB_OK; +} + +/*! + \brief set endpoint or channel TX FIFO size + \param[in] usb_regs: pointer to USB core registers + \param[in] fifo: TX FIFO number + \param[in] size: assigned TX FIFO size + \param[out] none + \retval none +*/ +void usb_set_txfifo(usb_core_regs *usb_regs, uint8_t fifo, uint16_t size) +{ + uint32_t tx_offset; + + tx_offset = usb_regs->gr->GRFLEN; + + if (fifo == 0U) { + usb_regs->gr->DIEP0TFLEN_HNPTFLEN = ((uint32_t)size << 16) | tx_offset; + } else { + tx_offset += (usb_regs->gr->DIEP0TFLEN_HNPTFLEN) >> 16; + + for (uint8_t i = 0U; i < (fifo - 1U); i++) { + tx_offset += (usb_regs->gr->DIEPTFLEN[i] >> 16); + } + + /* multiply Tx_Size by 2 to get higher performance */ + usb_regs->gr->DIEPTFLEN[fifo - 1U] = ((uint32_t)size << 16) | tx_offset; + } +} + +/*! + \brief set USB current mode + \param[in] usb_regs: pointer to USB core registers + \param[out] none + \retval none +*/ +void usb_curmode_set(usb_core_regs *usb_regs, uint8_t mode) +{ + usb_regs->gr->GUSBCS &= ~(GUSBCS_FDM | GUSBCS_FHM); + + if (DEVICE_MODE == mode) { + usb_regs->gr->GUSBCS |= GUSBCS_FDM; + } else if (HOST_MODE == mode) { + usb_regs->gr->GUSBCS |= GUSBCS_FHM; + } else { + /* OTG mode and other mode can not be here! */ + } +} + +/*! + \brief configure USB core to soft reset + \param[in] usb_regs: pointer to USB core registers + \param[out] none + \retval none +*/ +static void usb_core_reset (usb_core_regs *usb_regs) +{ + /* enable core soft reset */ + usb_regs->gr->GRSTCTL |= GRSTCTL_CSRST; + + /* wait for the core to be soft reset */ + while (usb_regs->gr->GRSTCTL & GRSTCTL_CSRST) { + /* no operation */ + } + + /* wait for additional 3 PHY clocks */ + usb_udelay(3U); +} + diff --git a/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/driver/Source/drv_usb_dev.c b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/driver/Source/drv_usb_dev.c new file mode 100644 index 0000000000..6589ca0fa7 --- /dev/null +++ b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/driver/Source/drv_usb_dev.c @@ -0,0 +1,612 @@ +/*! + \file drv_usb_dev.c + \brief USB device mode low level driver + + \version 2020-07-17, V3.0.0, firmware for GD32F10x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "drv_usb_hw.h" +#include "drv_usb_core.h" +#include "drv_usb_dev.h" + +/* endpoint 0 max packet length */ +static const uint8_t EP0_MAXLEN[4] = { + [DSTAT_EM_HS_PHY_30MHZ_60MHZ] = EP0MPL_64, + [DSTAT_EM_FS_PHY_30MHZ_60MHZ] = EP0MPL_64, + [DSTAT_EM_FS_PHY_48MHZ] = EP0MPL_64, + [DSTAT_EM_LS_PHY_6MHZ] = EP0MPL_8 +}; + +#ifdef USB_FS_CORE + +/* USB endpoint Tx FIFO size */ +static uint16_t USBFS_TX_FIFO_SIZE[USBFS_MAX_EP_COUNT] = +{ + (uint16_t)TX0_FIFO_FS_SIZE, + (uint16_t)TX1_FIFO_FS_SIZE, + (uint16_t)TX2_FIFO_FS_SIZE, + (uint16_t)TX3_FIFO_FS_SIZE +}; + +#endif /* USBFS_CORE */ + +/*! + \brief initialize USB core registers for device mode + \param[in] udev: pointer to USB device + \param[out] none + \retval operation status +*/ +usb_status usb_devcore_init (usb_core_driver *udev) +{ + uint8_t i; + + /* restart the PHY clock (maybe don't need to...) */ + *udev->regs.PWRCLKCTL = 0U; + + /* configure periodic frame interval to default value */ + udev->regs.dr->DCFG &= ~DCFG_EOPFT; + udev->regs.dr->DCFG |= FRAME_INTERVAL_80; + + udev->regs.dr->DCFG &= ~DCFG_DS; + +#ifdef USB_FS_CORE + if (udev->bp.core_enum == (uint8_t)USB_CORE_ENUM_FS) { + /* set full-speed PHY */ + udev->regs.dr->DCFG |= USB_SPEED_INP_FULL; + + /* set Rx FIFO size */ + usb_set_rxfifo(&udev->regs, RX_FIFO_FS_SIZE); + + /* set endpoint 1 to 3's TX FIFO length and RAM address */ + for (i = 0U; i < USBFS_MAX_EP_COUNT; i++) { + usb_set_txfifo(&udev->regs, i, USBFS_TX_FIFO_SIZE[i]); + } + } +#endif /* USB_FS_CORE */ + + /* make sure all FIFOs are flushed */ + + /* flush all TX FIFOs */ + (void)usb_txfifo_flush (&udev->regs, 0x10U); + + /* flush entire RX FIFO */ + (void)usb_rxfifo_flush (&udev->regs); + + /* clear all pending device interrupts */ + udev->regs.dr->DIEPINTEN = 0U; + udev->regs.dr->DOEPINTEN = 0U; + udev->regs.dr->DAEPINT = 0xFFFFFFFFU; + udev->regs.dr->DAEPINTEN = 0U; + + /* configure all IN/OUT endpoints */ + for (i = 0U; i < udev->bp.num_ep; i++) { + if (udev->regs.er_in[i]->DIEPCTL & DEPCTL_EPEN) { + udev->regs.er_in[i]->DIEPCTL |= DEPCTL_EPD | DEPCTL_SNAK; + } else { + udev->regs.er_in[i]->DIEPCTL = 0U; + } + + /* set IN endpoint transfer length to 0 */ + udev->regs.er_in[i]->DIEPLEN = 0U; + + /* clear all pending IN endpoint interrupts */ + udev->regs.er_in[i]->DIEPINTF = 0xFFU; + + if (udev->regs.er_out[i]->DOEPCTL & DEPCTL_EPEN) { + udev->regs.er_out[i]->DOEPCTL |= DEPCTL_EPD | DEPCTL_SNAK; + } else { + udev->regs.er_out[i]->DOEPCTL = 0U; + } + + /* set OUT endpoint transfer length to 0 */ + udev->regs.er_out[i]->DOEPLEN = 0U; + + /* clear all pending OUT endpoint interrupts */ + udev->regs.er_out[i]->DOEPINTF = 0xFFU; + } + + udev->regs.dr->DIEPINTEN |= DIEPINTEN_EPTXFUDEN; + + (void)usb_devint_enable (udev); + + return USB_OK; +} + +/*! + \brief enable the USB device mode interrupts + \param[in] udev: pointer to USB device + \param[out] none + \retval operation status +*/ +usb_status usb_devint_enable (usb_core_driver *udev) +{ + /* clear any pending USB OTG interrupts */ + udev->regs.gr->GOTGINTF = 0xFFFFFFFFU; + + /* clear any pending interrupts */ + udev->regs.gr->GINTF = 0xBFFFFFFFU; + + /* enable the USB wakeup and suspend interrupts */ + udev->regs.gr->GINTEN = GINTEN_WKUPIE | GINTEN_SPIE; + + /* enable device_mode-related interrupts */ + if ((uint8_t)USB_USE_FIFO == udev->bp.transfer_mode) { + udev->regs.gr->GINTEN |= GINTEN_RXFNEIE; + } + + udev->regs.gr->GINTEN |= GINTEN_RSTIE | GINTEN_ENUMFIE | GINTEN_IEPIE |\ + GINTEN_OEPIE | GINTEN_SOFIE | GINTEN_ISOONCIE | GINTEN_ISOINCIE; + +#ifdef VBUS_SENSING_ENABLED + udev->regs.gr->GINTEN |= GINTEN_SESIE | GINTEN_OTGIE; +#endif /* VBUS_SENSING_ENABLED */ + + return USB_OK; +} + +/*! + \brief active the USB endpoint0 transaction + \param[in] udev: pointer to USB device + \param[in] transc: the USB endpoint0 transaction + \param[out] none + \retval operation status +*/ +usb_status usb_transc0_active (usb_core_driver *udev, usb_transc *transc) +{ + __IO uint32_t *reg_addr = NULL; + + /* get the endpoint number */ + uint8_t ep_num = transc->ep_addr.num; + + if (ep_num) { + /* not endpoint 0 */ + return USB_FAIL; + } + + if (transc->ep_addr.dir) { + reg_addr = &udev->regs.er_in[0]->DIEPCTL; + } else { + reg_addr = &udev->regs.er_out[0]->DOEPCTL; + } + + /* endpoint 0 is activated after USB clock is enabled */ + + *reg_addr &= ~(DEPCTL_MPL | DEPCTL_EPTYPE | DIEPCTL_TXFNUM); + + /* set endpoint 0 maximum packet length */ + *reg_addr |= EP0_MAXLEN[udev->regs.dr->DSTAT & DSTAT_ES]; + + /* activate endpoint */ + *reg_addr |= ((uint32_t)transc->ep_type << 18U) | ((uint32_t)ep_num << 22U) | DEPCTL_SD0PID | DEPCTL_EPACT; + + return USB_OK; +} + +/*! + \brief active the USB transaction + \param[in] udev: pointer to USB device + \param[in] transc: the USB transaction + \param[out] none + \retval status +*/ +usb_status usb_transc_active (usb_core_driver *udev, usb_transc *transc) +{ + __IO uint32_t *reg_addr = NULL; + __IO uint32_t epinten = 0U; + + /* get the endpoint number */ + uint8_t ep_num = transc->ep_addr.num; + + /* enable endpoint interrupt number */ + if (transc->ep_addr.dir) { + reg_addr = &udev->regs.er_in[ep_num]->DIEPCTL; + + epinten = 1U << ep_num; + } else { + reg_addr = &udev->regs.er_out[ep_num]->DOEPCTL; + + epinten = 1U << (16U + ep_num); + } + + /* if the endpoint is not active, need change the endpoint control register */ + if (!(*reg_addr & DEPCTL_EPACT)) { + *reg_addr &= ~(DEPCTL_MPL | DEPCTL_EPTYPE | DIEPCTL_TXFNUM); + + /* set endpoint maximum packet length */ + if (0U == ep_num) { + *reg_addr |= EP0_MAXLEN[udev->regs.dr->DSTAT & DSTAT_ES]; + } else { + *reg_addr |= transc->max_len; + } + + /* activate endpoint */ + *reg_addr |= ((uint32_t)transc->ep_type << 18U) | ((uint32_t)ep_num << 22U) | DEPCTL_SD0PID | DEPCTL_EPACT; + } + + + /* enable the interrupts for this endpoint */ + udev->regs.dr->DAEPINTEN |= epinten; + + return USB_OK; +} + +/*! + \brief deactivate the USB transaction + \param[in] udev: pointer to USB device + \param[in] transc: the USB transaction + \param[out] none + \retval status +*/ +usb_status usb_transc_deactivate(usb_core_driver *udev, usb_transc *transc) +{ + uint32_t epinten = 0U; + + uint8_t ep_num = transc->ep_addr.num; + + /* disable endpoint interrupt number */ + if (transc->ep_addr.dir) { + epinten = 1U << ep_num; + + udev->regs.er_in[ep_num]->DIEPCTL &= ~DEPCTL_EPACT; + } else { + epinten = 1U << (ep_num + 16U); + + udev->regs.er_out[ep_num]->DOEPCTL &= ~DEPCTL_EPACT; + } + + + /* disable the interrupts for this endpoint */ + udev->regs.dr->DAEPINTEN &= ~epinten; + + return USB_OK; +} + +/*! + \brief configure USB transaction to start IN transfer + \param[in] udev: pointer to USB device + \param[in] transc: the USB IN transaction + \param[out] none + \retval operation status +*/ +usb_status usb_transc_inxfer (usb_core_driver *udev, usb_transc *transc) +{ + usb_status status = USB_OK; + + uint8_t ep_num = transc->ep_addr.num; + + __IO uint32_t epctl = udev->regs.er_in[ep_num]->DIEPCTL; + __IO uint32_t eplen = udev->regs.er_in[ep_num]->DIEPLEN; + + eplen &= ~(DEPLEN_TLEN | DEPLEN_PCNT); + + /* zero length packet or endpoint 0 */ + if (0U == transc->xfer_len) { + /* set transfer packet count to 1 */ + eplen |= 1U << 19U; + } else { + /* set transfer packet count */ + if (0U == ep_num) { + transc->xfer_len = USB_MIN(transc->xfer_len, transc->max_len); + + eplen |= 1U << 19U; + } else { + eplen |= (((transc->xfer_len - 1U) + transc->max_len) / transc->max_len) << 19U; + } + + /* set endpoint transfer length */ + eplen |= transc->xfer_len; + + if (transc->ep_type == (uint8_t)USB_EPTYPE_ISOC) { + eplen |= DIEPLEN_MCNT & (1U << 29U); + } + } + + udev->regs.er_in[ep_num]->DIEPLEN = eplen; + + if (transc->ep_type == (uint8_t)USB_EPTYPE_ISOC) { + if (((udev->regs.dr->DSTAT & DSTAT_FNRSOF) >> 8U) & 0x01U) { + epctl |= DEPCTL_SEVNFRM; + } else { + epctl |= DEPCTL_SODDFRM; + } + } + + if ((uint8_t)USB_USE_DMA == udev->bp.transfer_mode) { + udev->regs.er_in[ep_num]->DIEPDMAADDR = transc->dma_addr; + } + + /* enable the endpoint and clear the NAK */ + epctl |= DEPCTL_CNAK | DEPCTL_EPEN; + + udev->regs.er_in[ep_num]->DIEPCTL = epctl; + + if ((uint8_t)USB_USE_FIFO == udev->bp.transfer_mode) { + udev->regs.er_in[ep_num]->DIEPCTL = epctl; + + if (transc->ep_type != (uint8_t)USB_EPTYPE_ISOC) { + /* enable the TX FIFO empty interrupt for this endpoint */ + if (transc->xfer_len > 0U) { + udev->regs.dr->DIEPFEINTEN |= 1U << ep_num; + } + } else { + (void)usb_txfifo_write (&udev->regs, transc->xfer_buf, ep_num, (uint16_t)transc->xfer_len); + } + } + + return status; +} + +/*! + \brief configure USB transaction to start OUT transfer + \param[in] udev: pointer to USB device + \param[in] transc: the USB OUT transaction + \param[out] none + \retval status +*/ +usb_status usb_transc_outxfer (usb_core_driver *udev, usb_transc *transc) +{ + usb_status status = USB_OK; + + uint8_t ep_num = transc->ep_addr.num; + + uint32_t epctl = udev->regs.er_out[ep_num]->DOEPCTL; + uint32_t eplen = udev->regs.er_out[ep_num]->DOEPLEN; + + eplen &= ~(DEPLEN_TLEN | DEPLEN_PCNT); + + /* zero length packet or endpoint 0 */ + if ((0U == transc->xfer_len) || (0U == ep_num)) { + /* set the transfer length to max packet size */ + eplen |= transc->max_len; + + /* set the transfer packet count to 1 */ + eplen |= 1U << 19U; + } else { + /* configure the transfer size and packet count as follows: + * pktcnt = N + * xfersize = N * maxpacket + */ + uint32_t packet_count = (transc->xfer_len + transc->max_len - 1U) / transc->max_len; + + eplen |= packet_count << 19U; + eplen |= packet_count * transc->max_len; + } + + udev->regs.er_out[ep_num]->DOEPLEN = eplen; + + if ((uint8_t)USB_USE_DMA == udev->bp.transfer_mode) { + udev->regs.er_out[ep_num]->DOEPDMAADDR = transc->dma_addr; + } + + if (transc->ep_type == (uint8_t)USB_EPTYPE_ISOC) { + if (transc->frame_num) { + epctl |= DEPCTL_SD1PID; + } else { + epctl |= DEPCTL_SD0PID; + } + } + + /* enable the endpoint and clear the NAK */ + epctl |= DEPCTL_EPEN | DEPCTL_CNAK; + + udev->regs.er_out[ep_num]->DOEPCTL = epctl; + + return status; +} + +/*! + \brief set the USB transaction STALL status + \param[in] udev: pointer to USB device + \param[in] transc: the USB transaction + \param[out] none + \retval status +*/ +usb_status usb_transc_stall (usb_core_driver *udev, usb_transc *transc) +{ + __IO uint32_t *reg_addr = NULL; + + uint8_t ep_num = transc->ep_addr.num; + + if (transc->ep_addr.dir) { + reg_addr = &(udev->regs.er_in[ep_num]->DIEPCTL); + + /* set the endpoint disable bit */ + if (*reg_addr & DEPCTL_EPEN) { + *reg_addr |= DEPCTL_EPD; + } + } else { + /* set the endpoint stall bit */ + reg_addr = &(udev->regs.er_out[ep_num]->DOEPCTL); + } + + /* set the endpoint stall bit */ + *reg_addr |= DEPCTL_STALL; + + return USB_OK; +} + +/*! + \brief clear the USB transaction STALL status + \param[in] udev: pointer to USB device + \param[in] transc: the USB transaction + \param[out] none + \retval operation status +*/ +usb_status usb_transc_clrstall(usb_core_driver *udev, usb_transc *transc) +{ + __IO uint32_t *reg_addr = NULL; + + uint8_t ep_num = transc->ep_addr.num; + + if (transc->ep_addr.dir) { + reg_addr = &(udev->regs.er_in[ep_num]->DIEPCTL); + } else { + reg_addr = &(udev->regs.er_out[ep_num]->DOEPCTL); + } + + /* clear the endpoint stall bits */ + *reg_addr &= ~DEPCTL_STALL; + + /* reset data PID of the periodic endpoints */ + if ((transc->ep_type == (uint8_t)USB_EPTYPE_INTR) || (transc->ep_type == (uint8_t)USB_EPTYPE_BULK)) { + *reg_addr |= DEPCTL_SD0PID; + } + + return USB_OK; +} + +/*! + \brief read device IN endpoint interrupt flag register + \param[in] udev: pointer to USB device + \param[in] ep_num: endpoint number + \param[out] none + \retval interrupt value +*/ +uint32_t usb_iepintr_read (usb_core_driver *udev, uint8_t ep_num) +{ + uint32_t value = 0U, fifoemptymask, commonintmask; + + commonintmask = udev->regs.dr->DIEPINTEN; + fifoemptymask = udev->regs.dr->DIEPFEINTEN; + + /* check FIFO empty interrupt enable bit */ + commonintmask |= ((fifoemptymask >> ep_num) & 0x1U) << 7; + + value = udev->regs.er_in[ep_num]->DIEPINTF & commonintmask; + + return value; +} + +/*! + \brief configures OUT endpoint 0 to receive SETUP packets + \param[in] udev: pointer to USB device + \param[out] none + \retval none +*/ +void usb_ctlep_startout (usb_core_driver *udev) +{ + /* set OUT endpoint 0 receive length to 24 bytes, 1 packet and 3 setup packets */ + udev->regs.er_out[0]->DOEPLEN = DOEP0_TLEN(8U * 3U) | DOEP0_PCNT(1U) | DOEP0_STPCNT(3U); + + if ((uint8_t)USB_USE_DMA == udev->bp.transfer_mode) { + udev->regs.er_out[0]->DOEPDMAADDR = (uint32_t)&udev->dev.control.req; + + /* endpoint enable */ + udev->regs.er_out[0]->DOEPCTL |= DEPCTL_EPACT | DEPCTL_EPEN; + } +} + +/*! + \brief active remote wakeup signaling + \param[in] udev: pointer to USB device + \param[out] none + \retval none +*/ +void usb_rwkup_active (usb_core_driver *udev) +{ + if (udev->dev.pm.dev_remote_wakeup) { + if (udev->regs.dr->DSTAT & DSTAT_SPST) { + if (udev->bp.low_power) { + /* ungate USB core clock */ + *udev->regs.PWRCLKCTL &= ~(PWRCLKCTL_SHCLK | PWRCLKCTL_SUCLK); + } + + /* active remote wakeup signaling */ + udev->regs.dr->DCTL |= DCTL_RWKUP; + + usb_mdelay(5U); + + udev->regs.dr->DCTL &= ~DCTL_RWKUP; + } + } +} + +/*! + \brief active USB core clock + \param[in] udev: pointer to USB device + \param[out] none + \retval none +*/ +void usb_clock_active (usb_core_driver *udev) +{ + if (udev->bp.low_power) { + if (udev->regs.dr->DSTAT & DSTAT_SPST) { + /* ungate USB Core clock */ + *udev->regs.PWRCLKCTL &= ~(PWRCLKCTL_SHCLK | PWRCLKCTL_SUCLK); + } + } +} + +/*! + \brief USB device suspend + \param[in] udev: pointer to USB device + \param[out] none + \retval none +*/ +void usb_dev_suspend (usb_core_driver *udev) +{ + __IO uint32_t devstat = udev->regs.dr->DSTAT; + + if ((udev->bp.low_power) && (devstat & DSTAT_SPST)) { + /* switch-off the USB clocks */ + *udev->regs.PWRCLKCTL |= PWRCLKCTL_SHCLK; + + /* enter DEEP_SLEEP mode with LDO in low power mode */ + pmu_to_deepsleepmode(PMU_LDO_LOWPOWER, WFI_CMD); + } +} + +/*! + \brief stop the device and clean up FIFOs + \param[in] udev: pointer to USB device + \param[out] none + \retval none +*/ +void usb_dev_stop (usb_core_driver *udev) +{ + uint32_t i; + + udev->dev.cur_status = 1U; + + /* clear all interrupt flag and enable bits */ + for (i = 0U; i < udev->bp.num_ep; i++) { + udev->regs.er_in[i]->DIEPINTF = 0xFFU; + udev->regs.er_out[i]->DOEPINTF = 0xFFU; + } + + udev->regs.dr->DIEPINTEN = 0U; + udev->regs.dr->DOEPINTEN = 0U; + udev->regs.dr->DAEPINTEN = 0U; + udev->regs.dr->DAEPINT = 0xFFFFFFFFU; + + /* flush the FIFO */ + (void)usb_rxfifo_flush (&udev->regs); + (void)usb_txfifo_flush (&udev->regs, 0x10U); +} diff --git a/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/driver/Source/drv_usb_host.c b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/driver/Source/drv_usb_host.c new file mode 100644 index 0000000000..feaa32e9d7 --- /dev/null +++ b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/driver/Source/drv_usb_host.c @@ -0,0 +1,452 @@ +/*! + \file drv_usb_host.c + \brief USB host mode low level driver + + \version 2020-07-17, V3.0.0, firmware for GD32F10x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "drv_usb_hw.h" +#include "drv_usb_core.h" +#include "drv_usb_host.h" + +const uint32_t PIPE_DPID[2] = { + PIPE_DPID_DATA0, + PIPE_DPID_DATA1 +}; + +/*! + \brief initializes USB core for host mode + \param[in] udev: pointer to selected USB host + \param[out] none + \retval operation status +*/ +usb_status usb_host_init (usb_core_driver *udev) +{ + uint32_t i = 0U, inten = 0U; + + uint32_t nptxfifolen = 0U; + uint32_t ptxfifolen = 0U; + + /* restart the PHY Clock */ + *udev->regs.PWRCLKCTL = 0U; + + /* support FS/LS only */ + udev->regs.hr->HCTL &= ~HCTL_SPDFSLS; + + /* configure data FIFOs size */ +#ifdef USB_FS_CORE + if (USB_CORE_ENUM_FS == udev->bp.core_enum) { + /* set Rx FIFO size */ + udev->regs.gr->GRFLEN = USB_RX_FIFO_FS_SIZE; + + /* set non-periodic TX FIFO size and address */ + nptxfifolen |= USB_RX_FIFO_FS_SIZE; + nptxfifolen |= USB_HTX_NPFIFO_FS_SIZE << 16U; + udev->regs.gr->DIEP0TFLEN_HNPTFLEN = nptxfifolen; + + /* set periodic TX FIFO size and address */ + ptxfifolen |= USB_RX_FIFO_FS_SIZE + USB_HTX_NPFIFO_FS_SIZE; + ptxfifolen |= USB_HTX_PFIFO_FS_SIZE << 16U; + udev->regs.gr->HPTFLEN = ptxfifolen; + } +#endif /* USB_FS_CORE */ + +#ifdef USE_OTG_MODE + + /* clear host set HNP enable in the usb_otg control register */ + udev->regs.gr->GOTGCS &= ~GOTGCS_HHNPEN; + +#endif /* USE_OTG_MODE */ + + /* make sure the FIFOs are flushed */ + + /* flush all TX FIFOs in device or host mode */ + usb_txfifo_flush (&udev->regs, 0x10U); + + /* flush the entire Rx FIFO */ + usb_rxfifo_flush (&udev->regs); + + /* disable all interrupts */ + udev->regs.gr->GINTEN = 0U; + + /* clear any pending USB OTG interrupts */ + udev->regs.gr->GOTGINTF = 0xFFFFFFFFU; + + /* enable the USB wakeup and suspend interrupts */ + udev->regs.gr->GINTF = 0xBFFFFFFFU; + + /* clear all pending host channel interrupts */ + for (i = 0U; i < udev->bp.num_pipe; i++) { + udev->regs.pr[i]->HCHINTF = 0xFFFFFFFFU; + udev->regs.pr[i]->HCHINTEN = 0U; + } + +#ifndef USE_OTG_MODE + usb_portvbus_switch (udev, 1U); +#endif /* USE_OTG_MODE */ + + udev->regs.gr->GINTEN = GINTEN_WKUPIE | GINTEN_SPIE; + + /* enable host_mode-related interrupts */ + if (USB_USE_FIFO == udev->bp.transfer_mode) { + inten = GINTEN_RXFNEIE; + } + + inten |= GINTEN_SESIE | GINTEN_HPIE | GINTEN_HCIE | GINTEN_ISOINCIE; + + udev->regs.gr->GINTEN |= inten; + + inten = GINTEN_DISCIE | GINTEN_SOFIE; + + udev->regs.gr->GINTEN &= ~inten; + + return USB_OK; +} + +/*! + \brief control the VBUS to power + \param[in] udev: pointer to selected usb host + \param[in] state: VBUS state + \param[out] none + \retval none +*/ +void usb_portvbus_switch (usb_core_driver *udev, uint8_t state) +{ + uint32_t port = 0U; + + /* enable or disable the external charge pump */ + usb_vbus_drive (state); + + /* turn on the host port power. */ + port = usb_port_read (udev); + + if (!(port & HPCS_PP) && (1U == state)) { + port |= HPCS_PP; + } + + if ((port & HPCS_PP) && (0U == state)) { + port &= ~HPCS_PP; + } + + *udev->regs.HPCS = port; + + usb_mdelay (200U); +} + +/*! + \brief reset host port + \param[in] udev: pointer to USB device + \param[out] none + \retval operation status +*/ +uint32_t usb_port_reset (usb_core_driver *udev) +{ + __IO uint32_t port = usb_port_read (udev); + + *udev->regs.HPCS = port | HPCS_PRST; + + usb_mdelay(20U); /* see note */ + + *udev->regs.HPCS = port & ~HPCS_PRST; + + usb_mdelay(20U); + + return 1U; +} + +/*! + \brief initialize host pipe + \param[in] udev: pointer to USB device + \param[in] pipe_num: host pipe number which is in (0..7) + \param[out] none + \retval operation status +*/ +usb_status usb_pipe_init (usb_core_driver *udev, uint8_t pipe_num) +{ + usb_status status = USB_OK; + + __IO uint32_t pp_ctl = 0U; + __IO uint32_t pp_inten = HCHINTEN_TFIE; + + usb_pipe *pp = &udev->host.pipe[pipe_num]; + + /* clear old interrupt conditions for this host channel */ + udev->regs.pr[pipe_num]->HCHINTF = 0xFFFFFFFFU; + + if (USB_USE_DMA == udev->bp.transfer_mode) { + pp_inten |= HCHINTEN_DMAERIE; + } + + if (pp->ep.dir) { + pp_inten |= HCHINTEN_BBERIE; + } + + /* enable channel interrupts required for this transfer */ + switch (pp->ep.type) { + case USB_EPTYPE_CTRL: + case USB_EPTYPE_BULK: + pp_inten |= HCHINTEN_STALLIE | HCHINTEN_USBERIE \ + | HCHINTEN_DTERIE | HCHINTEN_NAKIE; + + if (!pp->ep.dir) { + pp_inten |= HCHINTEN_NYETIE; + + if (pp->ping) { + pp_inten |= HCHINTEN_ACKIE; + } + } + break; + + case USB_EPTYPE_INTR: + pp_inten |= HCHINTEN_STALLIE | HCHINTEN_USBERIE | HCHINTEN_DTERIE \ + | HCHINTEN_NAKIE | HCHINTEN_REQOVRIE; + break; + + case USB_EPTYPE_ISOC: + pp_inten |= HCHINTEN_REQOVRIE | HCHINTEN_ACKIE; + + if (pp->ep.dir) { + pp_inten |= HCHINTEN_USBERIE; + } + break; + + default: + break; + } + + udev->regs.pr[pipe_num]->HCHINTEN = pp_inten; + + /* enable the top level host channel interrupt */ + udev->regs.hr->HACHINTEN |= 1U << pipe_num; + + /* make sure host channel interrupts are enabled */ + udev->regs.gr->GINTEN |= GINTEN_HCIE; + + /* program the host channel control register */ + pp_ctl |= PIPE_CTL_DAR(pp->dev_addr); + pp_ctl |= PIPE_CTL_EPNUM(pp->ep.num); + pp_ctl |= PIPE_CTL_EPDIR(pp->ep.dir); + pp_ctl |= PIPE_CTL_EPTYPE(pp->ep.type); + pp_ctl |= PIPE_CTL_LSD(pp->dev_speed == PORT_SPEED_LOW); + + pp_ctl |= pp->ep.mps; + pp_ctl |= ((uint32_t)(pp->ep.type == USB_EPTYPE_INTR) << 29U) & HCHCTL_ODDFRM; + + udev->regs.pr[pipe_num]->HCHCTL = pp_ctl; + + return status; +} + +/*! + \brief prepare host channel for transferring packets + \param[in] udev: pointer to USB device + \param[in] pipe_num: host pipe number which is in (0..7) + \param[out] none + \retval operation status +*/ +usb_status usb_pipe_xfer (usb_core_driver *udev, uint8_t pipe_num) +{ + usb_status status = USB_OK; + + uint16_t dword_len = 0U; + uint16_t packet_count = 0U; + + __IO uint32_t pp_ctl = 0U; + + usb_pipe *pp = &udev->host.pipe[pipe_num]; + + uint16_t max_packet_len = pp->ep.mps; + + /* compute the expected number of packets associated to the transfer */ + if (pp->xfer_len > 0U) { + packet_count = (uint16_t)((pp->xfer_len + max_packet_len - 1U) / max_packet_len); + + if (packet_count > HC_MAX_PACKET_COUNT) { + packet_count = HC_MAX_PACKET_COUNT; + pp->xfer_len = (uint16_t)(packet_count * max_packet_len); + } + } else { + packet_count = 1U; + } + + if (pp->ep.dir) { + pp->xfer_len = (uint16_t)(packet_count * max_packet_len); + } + + /* initialize the host channel transfer information */ + udev->regs.pr[pipe_num]->HCHLEN = pp->xfer_len | pp->DPID | PIPE_XFER_PCNT(packet_count); + + if (USB_USE_DMA == udev->bp.transfer_mode) { + udev->regs.pr[pipe_num]->HCHDMAADDR = (unsigned int)pp->xfer_buf; + } + + pp_ctl = udev->regs.pr[pipe_num]->HCHCTL; + + if (usb_frame_even(udev)) { + pp_ctl |= HCHCTL_ODDFRM; + } else { + pp_ctl &= ~HCHCTL_ODDFRM; + } + + /* set host channel enabled */ + pp_ctl |= HCHCTL_CEN; + pp_ctl &= ~HCHCTL_CDIS; + + udev->regs.pr[pipe_num]->HCHCTL = pp_ctl; + + if (USB_USE_FIFO == udev->bp.transfer_mode) { + if ((0U == pp->ep.dir) && (pp->xfer_len > 0U)) { + switch (pp->ep.type) { + /* non-periodic transfer */ + case USB_EPTYPE_CTRL: + case USB_EPTYPE_BULK: + dword_len = (uint16_t)((pp->xfer_len + 3U) / 4U); + + /* check if there is enough space in fifo space */ + if (dword_len > (udev->regs.gr->HNPTFQSTAT & HNPTFQSTAT_NPTXFS)) { + /* need to process data in nptxfempty interrupt */ + udev->regs.gr->GINTEN |= GINTEN_NPTXFEIE; + } + break; + + /* periodic transfer */ + case USB_EPTYPE_INTR: + case USB_EPTYPE_ISOC: + dword_len = (uint16_t)((pp->xfer_len + 3U) / 4U); + + /* check if there is enough space in fifo space */ + if (dword_len > (udev->regs.hr->HPTFQSTAT & HPTFQSTAT_PTXFS)) { + /* need to process data in ptxfempty interrupt */ + udev->regs.gr->GINTEN |= GINTEN_PTXFEIE; + } + break; + + default: + break; + } + + /* write packet into the TX fifo. */ + usb_txfifo_write (&udev->regs, pp->xfer_buf, pipe_num, (uint16_t)pp->xfer_len); + } + } + + return status; +} + +/*! + \brief halt pipe + \param[in] udev: pointer to USB device + \param[in] pipe_num: host pipe number which is in (0..7) + \param[out] none + \retval operation status +*/ +usb_status usb_pipe_halt (usb_core_driver *udev, uint8_t pipe_num) +{ + __IO uint32_t pp_ctl = udev->regs.pr[pipe_num]->HCHCTL; + + uint8_t ep_type = (uint8_t)((pp_ctl & HCHCTL_EPTYPE) >> 18U); + + pp_ctl |= HCHCTL_CEN | HCHCTL_CDIS; + + switch (ep_type) { + case USB_EPTYPE_CTRL: + case USB_EPTYPE_BULK: + if (0U == (udev->regs.gr->HNPTFQSTAT & HNPTFQSTAT_NPTXFS)) { + pp_ctl &= ~HCHCTL_CEN; + } + break; + + case USB_EPTYPE_INTR: + case USB_EPTYPE_ISOC: + if (0U == (udev->regs.hr->HPTFQSTAT & HPTFQSTAT_PTXFS)) { + pp_ctl &= ~HCHCTL_CEN; + } + break; + + default: + break; + } + + udev->regs.pr[pipe_num]->HCHCTL = pp_ctl; + + return USB_OK; +} + +/*! + \brief configure host pipe to do ping operation + \param[in] udev: pointer to USB device + \param[in] pipe_num: host pipe number which is in (0..7) + \param[out] none + \retval operation status +*/ +usb_status usb_pipe_ping (usb_core_driver *udev, uint8_t pipe_num) +{ + uint32_t pp_ctl = 0U; + + udev->regs.pr[pipe_num]->HCHLEN = HCHLEN_PING | (HCHLEN_PCNT & (1U << 19U)); + + pp_ctl = udev->regs.pr[pipe_num]->HCHCTL; + + pp_ctl |= HCHCTL_CEN; + pp_ctl &= ~HCHCTL_CDIS; + + udev->regs.pr[pipe_num]->HCHCTL = pp_ctl; + + return USB_OK; +} + +/*! + \brief stop the USB host and clean up FIFO + \param[in] udev: pointer to USB device + \param[out] none + \retval none +*/ +void usb_host_stop (usb_core_driver *udev) +{ + uint32_t i; + __IO uint32_t pp_ctl = 0U; + + udev->regs.hr->HACHINTEN = 0x0U; + udev->regs.hr->HACHINT = 0xFFFFFFFFU; + + /* flush out any leftover queued requests. */ + for (i = 0U; i < udev->bp.num_pipe; i++) { + pp_ctl = udev->regs.pr[i]->HCHCTL; + + pp_ctl &= ~(HCHCTL_CEN | HCHCTL_EPDIR); + pp_ctl |= HCHCTL_CDIS; + + udev->regs.pr[i]->HCHCTL = pp_ctl; + } + + /* flush the FIFO */ + usb_rxfifo_flush (&udev->regs); + usb_txfifo_flush (&udev->regs, 0x10U); +} diff --git a/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/driver/Source/drv_usbd_int.c b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/driver/Source/drv_usbd_int.c new file mode 100644 index 0000000000..570ff19744 --- /dev/null +++ b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/driver/Source/drv_usbd_int.c @@ -0,0 +1,497 @@ +/*! + \file drv_usbd_int.c + \brief USB device mode interrupt routines + + \version 2020-07-17, V3.0.0, firmware for GD32F10x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "usbd_conf.h" +#include "drv_usbd_int.h" +#include "usbd_transc.h" + +static uint32_t usbd_int_epout (usb_core_driver *udev); +static uint32_t usbd_int_epin (usb_core_driver *udev); +static uint32_t usbd_int_rxfifo (usb_core_driver *udev); +static uint32_t usbd_int_reset (usb_core_driver *udev); +static uint32_t usbd_int_enumfinish (usb_core_driver *udev); +static uint32_t usbd_int_suspend (usb_core_driver *udev); + +static uint32_t usbd_emptytxfifo_write (usb_core_driver *udev, uint32_t ep_num); + +static const uint8_t USB_SPEED[4] = { + [DSTAT_EM_HS_PHY_30MHZ_60MHZ] = (uint8_t)USB_SPEED_HIGH, + [DSTAT_EM_FS_PHY_30MHZ_60MHZ] = (uint8_t)USB_SPEED_FULL, + [DSTAT_EM_FS_PHY_48MHZ] = (uint8_t)USB_SPEED_FULL, + [DSTAT_EM_LS_PHY_6MHZ] = (uint8_t)USB_SPEED_LOW +}; + +/*! + \brief USB device-mode interrupts global service routine handler + \param[in] udev: pointer to USB device instance + \param[out] none + \retval none +*/ +void usbd_isr (usb_core_driver *udev) +{ + if (HOST_MODE != (udev->regs.gr->GINTF & GINTF_COPM)) { + uint32_t intr = udev->regs.gr->GINTF & udev->regs.gr->GINTEN; + + /* there are no interrupts, avoid spurious interrupt */ + if (!intr) { + return; + } + + /* OUT endpoints interrupts */ + if (intr & GINTF_OEPIF) { + (void)usbd_int_epout (udev); + } + + /* IN endpoints interrupts */ + if (intr & GINTF_IEPIF) { + (void)usbd_int_epin (udev); + } + + /* suspend interrupt */ + if (intr & GINTF_SP) { + (void)usbd_int_suspend (udev); + } + + /* wakeup interrupt */ + if (intr & GINTF_WKUPIF) { + /* inform upper layer by the resume event */ + udev->dev.cur_status = USBD_CONFIGURED; + + /* clear interrupt */ + udev->regs.gr->GINTF = GINTF_WKUPIF; + } + + /* start of frame interrupt */ + if (intr & GINTF_SOF) { + if (udev->dev.class_core->SOF) { + (void)udev->dev.class_core->SOF(udev); + } + + /* clear interrupt */ + udev->regs.gr->GINTF = GINTF_SOF; + } + + /* receive FIFO not empty interrupt */ + if (intr & GINTF_RXFNEIF) { + (void)usbd_int_rxfifo (udev); + } + + /* USB reset interrupt */ + if (intr & GINTF_RST) { + (void)usbd_int_reset (udev); + } + + /* enumeration has been done interrupt */ + if (intr & GINTF_ENUMFIF) { + (void)usbd_int_enumfinish (udev); + } + + /* incomplete synchronization IN transfer interrupt*/ + if (intr & GINTF_ISOINCIF) { + if (NULL != udev->dev.class_core->incomplete_isoc_in) { + (void)udev->dev.class_core->incomplete_isoc_in(udev); + } + + /* Clear interrupt */ + udev->regs.gr->GINTF = GINTF_ISOINCIF; + } + + /* incomplete synchronization OUT transfer interrupt*/ + if (intr & GINTF_ISOONCIF) { + if (NULL != udev->dev.class_core->incomplete_isoc_out) { + (void)udev->dev.class_core->incomplete_isoc_out(udev); + } + + /* clear interrupt */ + udev->regs.gr->GINTF = GINTF_ISOONCIF; + } + +#ifdef VBUS_SENSING_ENABLED + + /* session request interrupt */ + if (intr & GINTF_SESIF) { + udev->regs.gr->GINTF = GINTF_SESIF; + } + + /* OTG mode interrupt */ + if (intr & GINTF_OTGIF) { + if(udev->regs.gr->GOTGINTF & GOTGINTF_SESEND) { + + } + + /* clear OTG interrupt */ + udev->regs.gr->GINTF = GINTF_OTGIF; + } +#endif /* VBUS_SENSING_ENABLED */ + } +} + +/*! + \brief indicates that an OUT endpoint has a pending interrupt + \param[in] udev: pointer to USB device instance + \param[out] none + \retval operation status +*/ +static uint32_t usbd_int_epout (usb_core_driver *udev) +{ + uint32_t epintnum = 0U; + uint8_t ep_num = 0U; + + for (epintnum = usb_oepintnum_read (udev); epintnum; epintnum >>= 1, ep_num++) { + if (epintnum & 0x01U) { + __IO uint32_t oepintr = usb_oepintr_read (udev, ep_num); + + /* transfer complete interrupt */ + if (oepintr & DOEPINTF_TF) { + /* clear the bit in DOEPINTF for this interrupt */ + udev->regs.er_out[ep_num]->DOEPINTF = DOEPINTF_TF; + + if ((uint8_t)USB_USE_DMA == udev->bp.transfer_mode) { + __IO uint32_t eplen = udev->regs.er_out[ep_num]->DOEPLEN; + + udev->dev.transc_out[ep_num].xfer_count = udev->dev.transc_out[ep_num].max_len - \ + (eplen & DEPLEN_TLEN); + } + + /* inform upper layer: data ready */ + (void)usbd_out_transc (udev, ep_num); + + if ((uint8_t)USB_USE_DMA == udev->bp.transfer_mode) { + if ((0U == ep_num) && ((uint8_t)USB_CTL_STATUS_OUT == udev->dev.control.ctl_state)) { + usb_ctlep_startout (udev); + } + } + } + + /* setup phase finished interrupt (control endpoints) */ + if (oepintr & DOEPINTF_STPF) { + /* inform the upper layer that a setup packet is available */ + (void)usbd_setup_transc (udev); + + udev->regs.er_out[ep_num]->DOEPINTF = DOEPINTF_STPF; + } + } + } + + return 1U; +} + +/*! + \brief indicates that an IN endpoint has a pending interrupt + \param[in] udev: pointer to USB device instance + \param[out] none + \retval operation status +*/ +static uint32_t usbd_int_epin (usb_core_driver *udev) +{ + uint32_t epintnum = 0U; + uint8_t ep_num = 0U; + + for (epintnum = usb_iepintnum_read (udev); epintnum; epintnum >>= 1, ep_num++) { + if (epintnum & 0x1U) { + __IO uint32_t iepintr = usb_iepintr_read (udev, ep_num); + + if (iepintr & DIEPINTF_TF) { + udev->regs.er_in[ep_num]->DIEPINTF = DIEPINTF_TF; + + /* data transmission is completed */ + (void)usbd_in_transc (udev, ep_num); + + if ((uint8_t)USB_USE_DMA == udev->bp.transfer_mode) { + if ((0U == ep_num) && ((uint8_t)USB_CTL_STATUS_IN == udev->dev.control.ctl_state)) { + usb_ctlep_startout (udev); + } + } + } + + if (iepintr & DIEPINTF_TXFE) { + usbd_emptytxfifo_write (udev, (uint32_t)ep_num); + + udev->regs.er_in[ep_num]->DIEPINTF = DIEPINTF_TXFE; + } + } + } + + return 1U; +} + +/*! + \brief handle the RX status queue level interrupt + \param[in] udev: pointer to USB device instance + \param[out] none + \retval operation status +*/ +static uint32_t usbd_int_rxfifo (usb_core_driver *udev) +{ + usb_transc *transc = NULL; + + uint8_t data_PID = 0U; + uint32_t bcount = 0U; + + __IO uint32_t devrxstat = 0U; + + /* disable the Rx status queue non-empty interrupt */ + udev->regs.gr->GINTEN &= ~GINTEN_RXFNEIE; + + /* get the status from the top of the FIFO */ + devrxstat = udev->regs.gr->GRSTATP; + + uint8_t ep_num = (uint8_t)(devrxstat & GRSTATRP_EPNUM); + + transc = &udev->dev.transc_out[ep_num]; + + bcount = (devrxstat & GRSTATRP_BCOUNT) >> 4U; + data_PID = (uint8_t)((devrxstat & GRSTATRP_DPID) >> 15U); + + switch ((devrxstat & GRSTATRP_RPCKST) >> 17U) { + case RSTAT_GOUT_NAK: + break; + + case RSTAT_DATA_UPDT: + if (bcount > 0U) { + (void)usb_rxfifo_read (&udev->regs, transc->xfer_buf, (uint16_t)bcount); + + transc->xfer_buf += bcount; + transc->xfer_count += bcount; + } + break; + + case RSTAT_XFER_COMP: + /* trigger the OUT endpoint interrupt */ + break; + + case RSTAT_SETUP_COMP: + /* trigger the OUT endpoint interrupt */ + break; + + case RSTAT_SETUP_UPDT: +#ifdef GD32F10X_CL + #ifdef CDC_DATA_IN_EP + udev->regs.dr->DAEPINTEN |= (uint32_t)(1U << (EP_ID(CDC_DATA_IN_EP) + 16U)); + #endif /* CDC_DATA_IN_EP */ +#endif /* GD32F10X_CL */ + + if ((0U == transc->ep_addr.num) && (8U == bcount) && (DPID_DATA0 == data_PID)) { + /* copy the setup packet received in FIFO into the setup buffer in RAM */ + (void)usb_rxfifo_read (&udev->regs, (uint8_t *)&udev->dev.control.req, (uint16_t)bcount); + + transc->xfer_count += bcount; + } + break; + + default: + break; + } + + /* enable the Rx status queue level interrupt */ + udev->regs.gr->GINTEN |= GINTEN_RXFNEIE; + + return 1U; +} + +/*! + \brief handle USB reset interrupt + \param[in] udev: pointer to USB device instance + \param[out] none + \retval status +*/ +static uint32_t usbd_int_reset (usb_core_driver *udev) +{ + uint32_t i; + + /* clear the remote wakeup signaling */ + udev->regs.dr->DCTL &= ~DCTL_RWKUP; + + /* flush the TX FIFO */ + (void)usb_txfifo_flush (&udev->regs, 0U); + + for (i = 0U; i < udev->bp.num_ep; i++) { + udev->regs.er_in[i]->DIEPINTF = 0xFFU; + udev->regs.er_out[i]->DOEPINTF = 0xFFU; + } + + /* clear all pending device endpoint interrupts */ + udev->regs.dr->DAEPINT = 0xFFFFFFFFU; + + /* enable endpoint 0 interrupts */ + udev->regs.dr->DAEPINTEN = 1U | (1U << 16U); + + /* enable OUT endpoint interrupts */ + udev->regs.dr->DOEPINTEN = DOEPINTEN_STPFEN | DOEPINTEN_TFEN; + + /* enable IN endpoint interrupts */ + udev->regs.dr->DIEPINTEN = DIEPINTEN_TFEN; + + /* reset device address */ + udev->regs.dr->DCFG &= ~DCFG_DAR; + + /* configure endpoint 0 to receive SETUP packets */ + usb_ctlep_startout (udev); + + /* clear USB reset interrupt */ + udev->regs.gr->GINTF = GINTF_RST; + + udev->dev.transc_out[0] = (usb_transc) { + .ep_type = USB_EPTYPE_CTRL, + .max_len = USB_FS_EP0_MAX_LEN + }; + + (void)usb_transc_active (udev, &udev->dev.transc_out[0]); + + udev->dev.transc_in[0] = (usb_transc) { + .ep_addr = { + .dir = 1U + }, + + .ep_type = USB_EPTYPE_CTRL, + .max_len = USB_FS_EP0_MAX_LEN + }; + + (void)usb_transc_active (udev, &udev->dev.transc_in[0]); + + /* upon reset call user call back */ + udev->dev.cur_status = (uint8_t)USBD_DEFAULT; + + return 1U; +} + +/*! + \brief handle USB speed enumeration finish interrupt + \param[in] udev: pointer to USB device instance + \param[out] none + \retval status +*/ +static uint32_t usbd_int_enumfinish (usb_core_driver *udev) +{ + uint8_t enum_speed = (uint8_t)((udev->regs.dr->DSTAT & DSTAT_ES) >> 1U); + + udev->regs.dr->DCTL &= ~DCTL_CGINAK; + udev->regs.dr->DCTL |= DCTL_CGINAK; + + udev->regs.gr->GUSBCS &= ~GUSBCS_UTT; + + /* set USB turn-around time based on device speed and PHY interface */ + if (USB_SPEED[enum_speed] == (uint8_t)USB_SPEED_HIGH) { + udev->bp.core_speed = (uint8_t)USB_SPEED_HIGH; + + udev->regs.gr->GUSBCS |= 0x09U << 10U; + } else { + udev->bp.core_speed = (uint8_t)USB_SPEED_FULL; + + udev->regs.gr->GUSBCS |= 0x05U << 10U; + } + + /* clear interrupt */ + udev->regs.gr->GINTF = GINTF_ENUMFIF; + + return 1U; +} + +/*! + \brief USB suspend interrupt handler + \param[in] udev: pointer to USB device instance + \param[out] none + \retval operation status +*/ +static uint32_t usbd_int_suspend (usb_core_driver *udev) +{ + __IO uint8_t low_power = udev->bp.low_power; + __IO uint8_t suspend = (uint8_t)(udev->regs.dr->DSTAT & DSTAT_SPST); + __IO uint8_t is_configured = (udev->dev.cur_status == (uint8_t)USBD_CONFIGURED)? 1U : 0U; + + udev->dev.backup_status = udev->dev.cur_status; + udev->dev.cur_status = (uint8_t)USBD_SUSPENDED; + + if (low_power && suspend && is_configured) { + /* switch-off the OTG clocks */ + *udev->regs.PWRCLKCTL |= PWRCLKCTL_SUCLK | PWRCLKCTL_SHCLK; + + /* enter DEEP_SLEEP mode with LDO in low power mode */ + pmu_to_deepsleepmode(PMU_LDO_LOWPOWER, WFI_CMD); + } + + /* clear interrupt */ + udev->regs.gr->GINTF = GINTF_SP; + + return 1U; +} + +/*! + \brief check FIFO for the next packet to be loaded + \param[in] udev: pointer to USB device instance + \param[in] ep_num: endpoint identifier which is in (0..3) + \param[out] none + \retval status +*/ +static uint32_t usbd_emptytxfifo_write (usb_core_driver *udev, uint32_t ep_num) +{ + uint32_t len; + uint32_t word_count; + + usb_transc *transc = &udev->dev.transc_in[ep_num]; + + len = transc->xfer_len - transc->xfer_count; + + /* get the data length to write */ + if (len > transc->max_len) { + len = transc->max_len; + } + + word_count = (len + 3U) / 4U; + + while (((udev->regs.er_in[ep_num]->DIEPTFSTAT & DIEPTFSTAT_IEPTFS) >= word_count) && \ + (transc->xfer_count < transc->xfer_len)) { + len = transc->xfer_len - transc->xfer_count; + + if (len > transc->max_len) { + len = transc->max_len; + } + + /* write FIFO in word(4bytes) */ + word_count = (len + 3U) / 4U; + + /* write the FIFO */ + (void)usb_txfifo_write (&udev->regs, transc->xfer_buf, (uint8_t)ep_num, (uint16_t)len); + + transc->xfer_buf += len; + transc->xfer_count += len; + + if (transc->xfer_count == transc->xfer_len) { + /* disable the device endpoint FIFO empty interrupt */ + udev->regs.dr->DIEPFEINTEN &= ~(0x01U << ep_num); + } + } + + return 1U; +} diff --git a/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/driver/Source/drv_usbh_int.c b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/driver/Source/drv_usbh_int.c new file mode 100644 index 0000000000..2a1f442309 --- /dev/null +++ b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/driver/Source/drv_usbh_int.c @@ -0,0 +1,622 @@ +/*! + \file drv_usbh_int.c + \brief USB host mode interrupt handler file + + \version 2020-07-17, V3.0.0, firmware for GD32F10x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "drv_usb_core.h" +#include "drv_usb_host.h" +#include "drv_usbh_int.h" +#include "usbh_core.h" + +#if defined (__CC_ARM) /*!< ARM compiler */ + #pragma O0 +#elif defined (__GNUC__) /*!< GNU compiler */ + #pragma GCC optimize ("O0") +#elif defined (__TASKING__) /*!< TASKING compiler */ + #pragma optimize=0 +#endif /* __CC_ARM */ + +/* local function prototypes ('static') */ +static uint32_t usbh_int_port (usb_core_driver *udev); +static uint32_t usbh_int_pipe (usb_core_driver *udev); +static uint32_t usbh_int_pipe_in (usb_core_driver *udev, uint32_t pp_num); +static uint32_t usbh_int_pipe_out (usb_core_driver *udev, uint32_t pp_num); +static uint32_t usbh_int_rxfifonoempty (usb_core_driver *udev); +static uint32_t usbh_int_txfifoempty (usb_core_driver *udev, usb_pipe_mode pp_mode); + +/*! + \brief handle global host interrupt + \param[in] udev: pointer to USB core instance + \param[out] none + \retval operation status +*/ +uint32_t usbh_isr (usb_core_driver *udev) +{ + uint32_t retval = 0U; + + __IO uint32_t intr = 0U; + + /* check if host mode */ + if (HOST_MODE == (udev->regs.gr->GINTF & GINTF_COPM)) { + intr = usb_coreintr_get(&udev->regs); + + if (!intr) { + return 0U; + } + + if (intr & GINTF_SOF) { + usbh_int_fop->SOF(udev->host.data); + + /* clear interrupt */ + udev->regs.gr->GINTF = GINTF_SOF; + } + + if (intr & GINTF_RXFNEIF) { + retval |= usbh_int_rxfifonoempty (udev); + } + + if (intr & GINTF_NPTXFEIF) { + retval |= usbh_int_txfifoempty (udev, PIPE_NON_PERIOD); + } + + if (intr & GINTF_PTXFEIF) { + retval |= usbh_int_txfifoempty (udev, PIPE_PERIOD); + } + + if (intr & GINTF_HCIF) { + retval |= usbh_int_pipe (udev); + } + + if (intr & GINTF_HPIF) { + retval |= usbh_int_port (udev); + } + + if (intr & GINTF_DISCIF) { + usbh_int_fop->disconnect(udev->host.data); + + /* clear interrupt */ + udev->regs.gr->GINTF = GINTF_DISCIF; + } + + if (intr & GINTF_ISOONCIF) { + udev->regs.pr[0]->HCHCTL |= HCHCTL_CEN | HCHCTL_CDIS; + + /* clear interrupt */ + udev->regs.gr->GINTF = GINTF_ISOONCIF; + } + + if (intr & GINTF_SESIF) { + usb_portvbus_switch (udev, 1U); + + udev->regs.gr->GINTF = GINTF_SESIF; + } + + if (intr & GINTF_WKUPIF) { + /* clear interrupt */ + udev->regs.gr->GINTF = GINTF_WKUPIF; + } + } + + return retval; +} + +/*! + \brief handle USB pipe halt + \param[in] udev: pointer to USB core instance + \param[in] pp_num: pp_num: host channel number which is in (0..7) + \param[in] pp_int: pipe interrupt + \param[in] pp_status: pipe status + \param[out] none + \retval none +*/ +static inline void usb_pp_halt (usb_core_driver *udev, + uint8_t pp_num, + uint32_t pp_int, + usb_pipe_staus pp_status) +{ + udev->regs.pr[pp_num]->HCHINTEN |= HCHINTEN_CHIE; + + usb_pipe_halt(udev, pp_num); + + udev->regs.pr[pp_num]->HCHINTF = pp_int; + + udev->host.pipe[pp_num].pp_status = pp_status; +} + +/*! + \brief handle the host port interrupt + \param[in] udev: pointer to USB device instance + \param[out] none + \retval operation status +*/ +#if defined (__ICCARM__) /*!< IAR compiler */ + #pragma optimize = none +#endif /* __ICCARM */ +static uint32_t usbh_int_port (usb_core_driver *udev) +{ + uint32_t retval = 0U; + + /* note: when the USB PHY use USB HS PHY, the flag is needed */ + uint8_t port_reset = 0U; + + __IO uint32_t port_state = *udev->regs.HPCS; + + /* clear the interrupt bits in GINTSTS */ + port_state &= ~(HPCS_PE | HPCS_PCD | HPCS_PEDC); + + /* port connect detected */ + if (*udev->regs.HPCS & HPCS_PCD) { + port_state |= HPCS_PCD; + + usbh_int_fop->connect(udev->host.data); + + retval |= 1U; + } + + /* port enable changed */ + if (*udev->regs.HPCS & HPCS_PEDC) { + port_state |= HPCS_PEDC; + + if (*udev->regs.HPCS & HPCS_PE) { + uint32_t port_speed = usb_curspeed_get(udev); + uint32_t clock_type = udev->regs.hr->HCTL & HCTL_CLKSEL; + + udev->host.connect_status = 1U; + + if (PORT_SPEED_LOW == port_speed) { + udev->regs.hr->HFT = 6000U; + + if (HCTL_6MHZ != clock_type) { + if (USB_EMBEDDED_PHY == udev->bp.phy_itf) { + usb_phyclock_config (udev, HCTL_6MHZ); + } + + port_reset = 1U; + } + } else if (PORT_SPEED_FULL == port_speed) { + udev->regs.hr->HFT = 48000U; + + if (HCTL_48MHZ != clock_type) { + usb_phyclock_config (udev, HCTL_48MHZ); + } + + port_reset = 1U; + } else { + /* for high speed device and others */ + port_reset = 1U; + } + + usbh_int_fop->port_enabled(udev->host.data); + + udev->regs.gr->GINTEN |= GINTEN_DISCIE | GINTEN_SOFIE; + } else { + usbh_int_fop->port_disabled(udev->host.data); + } + } + + if (port_reset) { + usb_port_reset(udev); + } + + /* clear port interrupts */ + *udev->regs.HPCS = port_state; + + return retval; +} + +/*! + \brief handle all host channels interrupt + \param[in] udev: pointer to USB device instance + \param[out] none + \retval operation status +*/ +static uint32_t usbh_int_pipe (usb_core_driver *udev) +{ + uint32_t pp_num = 0U; + uint32_t retval = 0U; + + for (pp_num = 0U; pp_num < udev->bp.num_pipe; pp_num++) { + if ((udev->regs.hr->HACHINT & HACHINT_HACHINT) & (1UL << pp_num)) { + if (udev->regs.pr[pp_num]->HCHCTL & HCHCTL_EPDIR) { + retval |= usbh_int_pipe_in (udev, pp_num); + } else { + retval |= usbh_int_pipe_out (udev, pp_num); + } + } + } + + return retval; +} + +/*! + \brief handle the IN channel interrupt + \param[in] udev: pointer to USB device instance + \param[in] pp_num: host channel number which is in (0..7) + \param[out] none + \retval operation status +*/ +#if defined (__ICCARM__) /*!< IAR compiler */ + #pragma optimize = none +#endif /* __ICCARM */ +static uint32_t usbh_int_pipe_in (usb_core_driver *udev, uint32_t pp_num) +{ + usb_pr *pp_reg = udev->regs.pr[pp_num]; + + usb_pipe *pp = &udev->host.pipe[pp_num]; + + __IO uint32_t intr_pp = pp_reg->HCHINTF & pp_reg->HCHINTEN; + + uint8_t ep_type = (uint8_t)((pp_reg->HCHCTL & HCHCTL_EPTYPE) >> 18U); + + if (intr_pp & HCHINTF_ACK) { + pp_reg->HCHINTF = HCHINTF_ACK; + } else if (intr_pp & HCHINTF_STALL) { + usb_pp_halt (udev, (uint8_t)pp_num, HCHINTF_STALL, PIPE_STALL); + pp_reg->HCHINTF = HCHINTF_NAK; + + /* note: When there is a 'STALL', reset also NAK, + else, the udev->host.pp_status = HC_STALL + will be overwritten by 'NAK' in code below */ + intr_pp &= ~HCHINTF_NAK; + } else if (intr_pp & HCHINTF_DTER) { + usb_pp_halt (udev, (uint8_t)pp_num, HCHINTF_DTER, PIPE_DTGERR); + pp_reg->HCHINTF = HCHINTF_NAK; + } else { + /* no operation */ + } + + if (intr_pp & HCHINTF_REQOVR) { + usb_pp_halt (udev, (uint8_t)pp_num, HCHINTF_REQOVR, PIPE_REQOVR); + } else if (intr_pp & HCHINTF_TF) { + if ((uint8_t)USB_USE_DMA == udev->bp.transfer_mode) { + udev->host.backup_xfercount[pp_num] = pp->xfer_len - (pp_reg->HCHLEN & HCHLEN_TLEN); + } + + pp->pp_status = PIPE_XF; + pp->err_count = 0U; + + pp_reg->HCHINTF = HCHINTF_TF; + + switch (ep_type) { + case USB_EPTYPE_CTRL: + case USB_EPTYPE_BULK: + usb_pp_halt (udev, (uint8_t)pp_num, HCHINTF_NAK, PIPE_XF); + + pp->data_toggle_in ^= 1U; + break; + + case USB_EPTYPE_INTR: + case USB_EPTYPE_ISOC: + pp_reg->HCHCTL |= HCHCTL_ODDFRM; + pp->urb_state = URB_DONE; + break; + + default: + break; + } + } else if (intr_pp & HCHINTF_CH) { + pp_reg->HCHINTEN &= ~HCHINTEN_CHIE; + + switch (pp->pp_status) { + case PIPE_XF: + pp->urb_state = URB_DONE; + break; + + case PIPE_STALL: + pp->urb_state = URB_STALL; + break; + + case PIPE_TRACERR: + case PIPE_DTGERR: + pp->err_count = 0U; + pp->urb_state = URB_ERROR; + + pp->data_toggle_in ^= 1U; + break; + + case PIPE_IDLE: + case PIPE_HALTED: + case PIPE_NAK: + case PIPE_NYET: + case PIPE_BBERR: + case PIPE_REQOVR: + default: + if((uint8_t)USB_EPTYPE_INTR == ep_type) { + pp->data_toggle_in ^= 1U; + } + break; + } + + pp_reg->HCHINTF = HCHINTF_CH; + } else if (intr_pp & HCHINTF_USBER) { + pp->err_count++; + usb_pp_halt (udev, (uint8_t)pp_num, HCHINTF_USBER, PIPE_TRACERR); + } else if (intr_pp & HCHINTF_NAK) { + switch (ep_type) { + case USB_EPTYPE_CTRL: + case USB_EPTYPE_BULK: + /* re-activate the channel */ + pp_reg->HCHCTL = (pp_reg->HCHCTL | HCHCTL_CEN) & ~HCHCTL_CDIS; + break; + + case USB_EPTYPE_INTR: + pp_reg->HCHINTEN |= HCHINTEN_CHIE; + + (void)usb_pipe_halt(udev, (uint8_t)pp_num); + break; + + default: + break; + } + + pp->pp_status = PIPE_NAK; + + pp_reg->HCHINTF = HCHINTF_NAK; + } else { + /* no operation */ + } + + return 1U; +} + +/*! + \brief handle the OUT channel interrupt + \param[in] udev: pointer to USB device instance + \param[in] pp_num: host channel number which is in (0..7) + \param[out] none + \retval operation status +*/ +#if defined (__ICCARM__) /*!< IAR compiler */ + #pragma optimize = none +#endif /* __ICCARM */ +static uint32_t usbh_int_pipe_out (usb_core_driver *udev, uint32_t pp_num) +{ + usb_pr *pp_reg = udev->regs.pr[pp_num]; + + usb_pipe *pp = &udev->host.pipe[pp_num]; + + uint32_t intr_pp = pp_reg->HCHINTF & pp_reg->HCHINTEN; + + if (intr_pp & HCHINTF_ACK) { + if (URB_PING == pp->urb_state) { + pp->err_count = 0U; + usb_pp_halt (udev, (uint8_t)pp_num, HCHINTF_TF, PIPE_XF); + } + + pp_reg->HCHINTF = HCHINTF_ACK; + } else if (intr_pp & HCHINTF_STALL) { + usb_pp_halt (udev, (uint8_t)pp_num, HCHINTF_STALL, PIPE_STALL); + } else if (intr_pp & HCHINTF_DTER) { + usb_pp_halt (udev, (uint8_t)pp_num, HCHINTF_DTER, PIPE_DTGERR); + pp_reg->HCHINTF = HCHINTF_NAK; + } else if (intr_pp & HCHINTF_REQOVR) { + usb_pp_halt (udev, (uint8_t)pp_num, HCHINTF_REQOVR, PIPE_REQOVR); + } else if (intr_pp & HCHINTF_TF) { + pp->err_count = 0U; + usb_pp_halt (udev, (uint8_t)pp_num, HCHINTF_TF, PIPE_XF); + } else if (intr_pp & HCHINTF_NAK) { + pp->err_count = 0U; + usb_pp_halt (udev, (uint8_t)pp_num, HCHINTF_NAK, PIPE_NAK); + } else if (intr_pp & HCHINTF_USBER) { + pp->err_count++; + usb_pp_halt (udev, (uint8_t)pp_num, HCHINTF_USBER, PIPE_TRACERR); + } else if (intr_pp & HCHINTF_NYET) { + pp->err_count = 0U; + usb_pp_halt (udev, (uint8_t)pp_num, HCHINTF_NYET, PIPE_NYET); + } else if (intr_pp & HCHINTF_CH) { + udev->regs.pr[pp_num]->HCHINTEN &= ~HCHINTEN_CHIE; + + switch (pp->pp_status) { + case PIPE_XF: + pp->urb_state = URB_DONE; + + if ((uint8_t)USB_EPTYPE_BULK == ((pp_reg->HCHCTL & HCHCTL_EPTYPE) >> 18U)) { + pp->data_toggle_out ^= 1U; + } + break; + + case PIPE_NAK: + + if (URB_PING == pp->urb_state) { + (void)usb_pipe_ping (udev, (uint8_t)pp_num); + } else { + pp->urb_state = URB_NOTREADY; + } + break; + + case PIPE_NYET: + if (1U == udev->host.pipe[pp_num].ping) { + (void)usb_pipe_ping (udev, (uint8_t)pp_num); + pp->urb_state = URB_PING; + } + else { + pp->urb_state = URB_NOTREADY; + } + break; + + case PIPE_STALL: + pp->urb_state = URB_STALL; + break; + + case PIPE_TRACERR: + if (3U == pp->err_count) { + pp->urb_state = URB_ERROR; + pp->err_count = 0U; + } + break; + + case PIPE_IDLE: + case PIPE_HALTED: + case PIPE_BBERR: + case PIPE_REQOVR: + case PIPE_DTGERR: + default: + break; + } + + pp_reg->HCHINTF = HCHINTF_CH; + } else { + /* no operation */ + } + + return 1U; +} + +/*! + \brief handle the RX FIFO non-empty interrupt + \param[in] udev: pointer to USB device instance + \param[out] none + \retval operation status +*/ +#if defined (__ICCARM__) /*!< IAR compiler */ + #pragma optimize = none +#endif /* __ICCARM */ +static uint32_t usbh_int_rxfifonoempty (usb_core_driver *udev) +{ + uint32_t count = 0U; + + __IO uint8_t pp_num = 0U; + __IO uint32_t rx_stat = 0U; + + /* disable the RX status queue level interrupt */ + udev->regs.gr->GINTEN &= ~GINTEN_RXFNEIE; + + rx_stat = udev->regs.gr->GRSTATP; + pp_num = (uint8_t)(rx_stat & GRSTATRP_CNUM); + + switch ((rx_stat & GRSTATRP_RPCKST) >> 17U) { + case GRXSTS_PKTSTS_IN: + count = (rx_stat & GRSTATRP_BCOUNT) >> 4U; + + /* read the data into the host buffer. */ + if ((count > 0U) && (NULL != udev->host.pipe[pp_num].xfer_buf)) { + (void)usb_rxfifo_read (&udev->regs, udev->host.pipe[pp_num].xfer_buf, (uint16_t)count); + + /* manage multiple transfer packet */ + udev->host.pipe[pp_num].xfer_buf += count; + udev->host.pipe[pp_num].xfer_count += count; + + udev->host.backup_xfercount[pp_num] = udev->host.pipe[pp_num].xfer_count; + + if (udev->regs.pr[pp_num]->HCHLEN & HCHLEN_PCNT) { + /* re-activate the channel when more packets are expected */ + __IO uint32_t pp_ctl = udev->regs.pr[pp_num]->HCHCTL; + + pp_ctl |= HCHCTL_CEN; + pp_ctl &= ~HCHCTL_CDIS; + + udev->regs.pr[pp_num]->HCHCTL = pp_ctl; + } + } + break; + + case GRXSTS_PKTSTS_IN_XFER_COMP: + break; + + case GRXSTS_PKTSTS_DATA_TOGGLE_ERR: + count = (rx_stat & GRSTATRP_BCOUNT) >> 4U; + + while (count > 0U) { + rx_stat = udev->regs.gr->GRSTATP; + count--; + } + break; + + case GRXSTS_PKTSTS_CH_HALTED: + break; + + default: + break; + } + + /* enable the RX status queue level interrupt */ + udev->regs.gr->GINTEN |= GINTEN_RXFNEIE; + + return 1U; +} + +/*! + \brief handle the TX FIFO empty interrupt + \param[in] udev: pointer to USB device instance + \param[in] pp_mode: pipe mode + \param[out] none + \retval operation status +*/ +#if defined (__ICCARM__) /*!< IAR compiler */ + #pragma optimize = none +#endif /* __ICCARM */ +static uint32_t usbh_int_txfifoempty (usb_core_driver *udev, usb_pipe_mode pp_mode) +{ + uint8_t pp_num = 0U; + uint16_t word_count = 0U, len = 0U; + __IO uint32_t *txfiforeg = 0U, txfifostate = 0U; + + if (PIPE_NON_PERIOD == pp_mode) { + txfiforeg = &udev->regs.gr->HNPTFQSTAT; + } else if (PIPE_PERIOD == pp_mode) { + txfiforeg = &udev->regs.hr->HPTFQSTAT; + } else { + return 0U; + } + + txfifostate = *txfiforeg; + + pp_num = (uint8_t)((txfifostate & TFQSTAT_CNUM) >> 27U); + + word_count = (uint16_t)(udev->host.pipe[pp_num].xfer_len + 3U) / 4U; + + while (((txfifostate & TFQSTAT_TXFS) >= word_count) && (0U != udev->host.pipe[pp_num].xfer_len)) { + len = (uint16_t)(txfifostate & TFQSTAT_TXFS) * 4U; + + if (len > udev->host.pipe[pp_num].xfer_len) { + /* last packet */ + len = (uint16_t)udev->host.pipe[pp_num].xfer_len; + + if (PIPE_NON_PERIOD == pp_mode) { + udev->regs.gr->GINTEN &= ~GINTEN_NPTXFEIE; + } else { + udev->regs.gr->GINTEN &= ~GINTEN_PTXFEIE; + } + } + + word_count = (uint16_t)((udev->host.pipe[pp_num].xfer_len + 3U) / 4U); + usb_txfifo_write (&udev->regs, udev->host.pipe[pp_num].xfer_buf, pp_num, len); + + udev->host.pipe[pp_num].xfer_buf += len; + udev->host.pipe[pp_num].xfer_len -= len; + udev->host.pipe[pp_num].xfer_count += len; + + txfifostate = *txfiforeg; + } + + return 1U; +} diff --git a/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/host/class/hid/Include/usbh_hid_core.h b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/host/class/hid/Include/usbh_hid_core.h new file mode 100644 index 0000000000..8f9a6ca9fc --- /dev/null +++ b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/host/class/hid/Include/usbh_hid_core.h @@ -0,0 +1,212 @@ +/*! + \file usbh_hid_core.h + \brief header file for the usbh_hid_core.c + + \version 2020-07-17, V3.0.0, firmware for GD32F10x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef __USBH_HID_CORE_H +#define __USBH_HID_CORE_H + +#include "usb_hid.h" +#include "usbh_enum.h" +#include "usbh_transc.h" + +#define HID_MIN_POLL 10U +#define HID_REPORT_SIZE 16U +#define HID_MAX_USAGE 10U +#define HID_MAX_NBR_REPORT_FMT 10U +#define HID_QUEUE_SIZE 10U + +#define HID_ITEM_LONG 0xFEU + +#define HID_ITEM_TYPE_MAIN 0x00U +#define HID_ITEM_TYPE_GLOBAL 0x01U +#define HID_ITEM_TYPE_LOCAL 0x02U +#define HID_ITEM_TYPE_RESERVED 0x03U + +#define HID_MAIN_ITEM_TAG_INPUT 0x08U +#define HID_MAIN_ITEM_TAG_OUTPUT 0x09U +#define HID_MAIN_ITEM_TAG_COLLECTION 0x0AU +#define HID_MAIN_ITEM_TAG_FEATURE 0x0BU +#define HID_MAIN_ITEM_TAG_ENDCOLLECTION 0x0CU + +#define HID_GLOBAL_ITEM_TAG_USAGE_PAGE 0x00U +#define HID_GLOBAL_ITEM_TAG_LOG_MIN 0x01U +#define HID_GLOBAL_ITEM_TAG_LOG_MAX 0x02U +#define HID_GLOBAL_ITEM_TAG_PHY_MIN 0x03U +#define HID_GLOBAL_ITEM_TAG_PHY_MAX 0x04U +#define HID_GLOBAL_ITEM_TAG_UNIT_EXPONENT 0x05U +#define HID_GLOBAL_ITEM_TAG_UNIT 0x06U +#define HID_GLOBAL_ITEM_TAG_REPORT_SIZE 0x07U +#define HID_GLOBAL_ITEM_TAG_REPORT_ID 0x08U +#define HID_GLOBAL_ITEM_TAG_REPORT_COUNT 0x09U +#define HID_GLOBAL_ITEM_TAG_PUSH 0x0AU +#define HID_GLOBAL_ITEM_TAG_POP 0x0BU + +#define HID_LOCAL_ITEM_TAG_USAGE 0x00U +#define HID_LOCAL_ITEM_TAG_USAGE_MIN 0x01U +#define HID_LOCAL_ITEM_TAG_USAGE_MAX 0x02U +#define HID_LOCAL_ITEM_TAG_DESIGNATOR_INDEX 0x03U +#define HID_LOCAL_ITEM_TAG_DESIGNATOR_MIN 0x04U +#define HID_LOCAL_ITEM_TAG_DESIGNATOR_MAX 0x05U +#define HID_LOCAL_ITEM_TAG_STRING_INDEX 0x07U +#define HID_LOCAL_ITEM_TAG_STRING_MIN 0x08U +#define HID_LOCAL_ITEM_TAG_STRING_MAX 0x09U +#define HID_LOCAL_ITEM_TAG_DELIMITER 0x0AU + +#define USB_HID_DESC_SIZE 9U + +/* states for HID state machine */ +typedef enum { + HID_INIT = 0U, + HID_IDLE, + HID_SEND_DATA, + HID_BUSY, + HID_GET_DATA, + HID_SYNC, + HID_POLL, + HID_ERROR, +} hid_state; + +typedef enum { + HID_REQ_INIT = 0U, + HID_REQ_IDLE, + HID_REQ_GET_REPORT_DESC, + HID_REQ_GET_HID_DESC, + HID_REQ_SET_IDLE, + HID_REQ_SET_PROTOCOL, + HID_REQ_SET_REPORT, +} hid_ctlstate; + +typedef enum +{ + HID_MOUSE = 0x01U, + HID_KEYBOARD = 0x02U, + HID_UNKNOWN = 0xFFU, +} hid_type; + +typedef struct _hid_report_data +{ + uint8_t ReportID; + uint8_t ReportType; + uint16_t UsagePage; + uint32_t Usage[HID_MAX_USAGE]; + uint32_t NbrUsage; + uint32_t UsageMin; + uint32_t UsageMax; + int32_t LogMin; + int32_t LogMax; + int32_t PhyMin; + int32_t PhyMax; + int32_t UnitExp; + uint32_t Unit; + uint32_t ReportSize; + uint32_t ReportCnt; + uint32_t Flag; + uint32_t PhyUsage; + uint32_t AppUsage; + uint32_t LogUsage; +} hid_report_data; + +typedef struct _hid_report_ID +{ + uint8_t size; /*!< report size return by the device ID */ + uint8_t reportID; /*!< report ID */ + uint8_t type; /*!< report type (INPUT/OUTPUT/FEATURE) */ +} hid_report_ID; + +typedef struct _hid_collection +{ + uint32_t usage; + uint8_t type; + struct _hid_collection *next_ptr; +} hid_collection; + +typedef struct _hid_appcollection +{ + uint32_t usage; + uint8_t type; + uint8_t nbr_report_fmt; + hid_report_data report_data[HID_MAX_NBR_REPORT_FMT]; +} hid_appcollection; + +typedef struct +{ + uint8_t *buf; + uint16_t head; + uint16_t tail; + uint16_t size; + uint8_t lock; +} data_fifo; + +/* structure for HID process */ +typedef struct _hid_process +{ + uint8_t pipe_in; + uint8_t pipe_out; + uint8_t ep_addr; + uint8_t ep_in; + uint8_t ep_out; + __IO uint8_t data_ready; + uint8_t *pdata; + uint16_t len; + uint16_t poll; + + __IO uint32_t timer; + + data_fifo fifo; + usb_desc_hid hid_desc; + hid_report_data hid_report; + + hid_state state; + hid_ctlstate ctl_state; + usbh_status (*init)(usb_core_driver *udev, usbh_host *uhost); + void (*machine)(usb_core_driver *udev, usbh_host *uhost); +} usbh_hid_handler; + +extern usbh_class usbh_hid; + +/* function declarations */ +/* set HID report */ +usbh_status usbh_set_report (usb_core_driver *udev, + usbh_host *uhost, + uint8_t report_type, + uint8_t report_ID, + uint8_t report_len, + uint8_t *report_buf); +/* read data from FIFO */ +uint16_t usbh_hid_fifo_read (data_fifo *fifo, void *buf, uint16_t nbytes); +/* write data to FIFO */ +uint16_t usbh_hid_fifo_write (data_fifo *fifo, void *buf, uint16_t nbytes); +/* initialize FIFO */ +void usbh_hid_fifo_init (data_fifo *fifo, uint8_t *buf, uint16_t size); + +#endif /* __USBH_HID_CORE_H */ diff --git a/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/host/class/hid/Include/usbh_hid_keybd.h b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/host/class/hid/Include/usbh_hid_keybd.h new file mode 100644 index 0000000000..5825219e33 --- /dev/null +++ b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/host/class/hid/Include/usbh_hid_keybd.h @@ -0,0 +1,303 @@ +/*! + \file usbh_hid_keybd.h + \brief header file for usbh_hid_keybd.c + + \version 2020-07-17, V3.0.0, firmware for GD32F10x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef __USBH_HID_KEYBD_H +#define __USBH_HID_KEYBD_H + +#include "usb_conf.h" +#include "usbh_hid_core.h" + +//#define AZERTY_KEYBOARD +#define QWERTY_KEYBOARD + +#define KBD_LEFT_CTRL 0x01U +#define KBD_LEFT_SHIFT 0x02U +#define KBD_LEFT_ALT 0x04U +#define KBD_LEFT_GUI 0x08U +#define KBD_RIGHT_CTRL 0x10U +#define KBD_RIGHT_SHIFT 0x20U +#define KBD_RIGHT_ALT 0x40U +#define KBD_RIGHT_GUI 0x80U + +#define KEY_NONE 0x00U +#define KEY_ERRORROLLOVER 0x01U +#define KEY_POSTFAIL 0x02U +#define KEY_ERRORUNDEFINED 0x03U +#define KEY_A 0x04U +#define KEY_B 0x05U +#define KEY_C 0x06U +#define KEY_D 0x07U +#define KEY_E 0x08U +#define KEY_F 0x09U +#define KEY_G 0x0AU +#define KEY_H 0x0BU +#define KEY_I 0x0CU +#define KEY_J 0x0DU +#define KEY_K 0x0EU +#define KEY_L 0x0FU +#define KEY_M 0x10U +#define KEY_N 0x11U +#define KEY_O 0x12U +#define KEY_P 0x13U +#define KEY_Q 0x14U +#define KEY_R 0x15U +#define KEY_S 0x16U +#define KEY_T 0x17U +#define KEY_U 0x18U +#define KEY_V 0x19U +#define KEY_W 0x1AU +#define KEY_X 0x1BU +#define KEY_Y 0x1CU +#define KEY_Z 0x1DU +#define KEY_1_EXCLAMATION_MARK 0x1EU +#define KEY_2_AT 0x1FU +#define KEY_3_NUMBER_SIGN 0x20U +#define KEY_4_DOLLAR 0x21U +#define KEY_5_PERCENT 0x22U +#define KEY_6_CARET 0x23U +#define KEY_7_AMPERSAND 0x24U +#define KEY_8_ASTERISK 0x25U +#define KEY_9_OPARENTHESIS 0x26U +#define KEY_0_CPARENTHESIS 0x27U +#define KEY_ENTER 0x28U +#define KEY_ESCAPE 0x29U +#define KEY_BACKSPACE 0x2AU +#define KEY_TAB 0x2BU +#define KEY_SPACEBAR 0x2CU +#define KEY_MINUS_UNDERSCORE 0x2DU +#define KEY_EQUAL_PLUS 0x2EU +#define KEY_OBRACKET_AND_OBRACE 0x2FU +#define KEY_CBRACKET_AND_CBRACE 0x30U +#define KEY_BACKSLASH_VERTICAL_BAR 0x31U +#define KEY_NONUS_NUMBER_SIGN_TILDE 0x32U +#define KEY_SEMICOLON_COLON 0x33U +#define KEY_SINGLE_AND_DOUBLE_QUOTE 0x34U +#define KEY_GRAVE ACCENT AND TILDE 0x35U +#define KEY_COMMA_AND_LESS 0x36U +#define KEY_DOT_GREATER 0x37U +#define KEY_SLASH_QUESTION 0x38U +#define KEY_CAPS LOCK 0x39U +#define KEY_F1 0x3AU +#define KEY_F2 0x3BU +#define KEY_F3 0x3CU +#define KEY_F4 0x3DU +#define KEY_F5 0x3EU +#define KEY_F6 0x3FU +#define KEY_F7 0x40U +#define KEY_F8 0x41U +#define KEY_F9 0x42U +#define KEY_F10 0x43U +#define KEY_F11 0x44U +#define KEY_F12 0x45U +#define KEY_PRINTSCREEN 0x46U +#define KEY_SCROLL LOCK 0x47U +#define KEY_PAUSE 0x48U +#define KEY_INSERT 0x49U +#define KEY_HOME 0x4AU +#define KEY_PAGEUP 0x4BU +#define KEY_DELETE 0x4CU +#define KEY_END1 0x4DU +#define KEY_PAGEDOWN 0x4EU +#define KEY_RIGHTARROW 0x4FU +#define KEY_LEFTARROW 0x50U +#define KEY_DOWNARROW 0x51U +#define KEY_UPARROW 0x52U +#define KEY_KEYPAD_NUM_LOCK_AND_CLEAR 0x53U +#define KEY_KEYPAD_SLASH 0x54U +#define KEY_KEYPAD_ASTERIKS 0x55U +#define KEY_KEYPAD_MINUS 0x56U +#define KEY_KEYPAD_PLUS 0x57U +#define KEY_KEYPAD_ENTER 0x58U +#define KEY_KEYPAD_1_END 0x59U +#define KEY_KEYPAD_2_DOWN_ARROW 0x5AU +#define KEY_KEYPAD_3_PAGEDN 0x5BU +#define KEY_KEYPAD_4_LEFT_ARROW 0x5CU +#define KEY_KEYPAD_5 0x5DU +#define KEY_KEYPAD_6_RIGHT_ARROW 0x5EU +#define KEY_KEYPAD_7_HOME 0x5FU +#define KEY_KEYPAD_8_UP_ARROW 0x60U +#define KEY_KEYPAD_9_PAGEUP 0x61U +#define KEY_KEYPAD_0_INSERT 0x62U +#define KEY_KEYPAD_DECIMAL_SEPARATOR_DELETE 0x63U +#define KEY_NONUS_BACK_SLASH_VERTICAL_BAR 0x64U +#define KEY_APPLICATION 0x65U +#define KEY_POWER 0x66U +#define KEY_KEYPAD_EQUAL 0x67U +#define KEY_F13 0x68U +#define KEY_F14 0x69U +#define KEY_F15 0x6AU +#define KEY_F16 0x6BU +#define KEY_F17 0x6CU +#define KEY_F18 0x6DU +#define KEY_F19 0x6EU +#define KEY_F20 0x6FU +#define KEY_F21 0x70U +#define KEY_F22 0x71U +#define KEY_F23 0x72U +#define KEY_F24 0x73U +#define KEY_EXECUTE 0x74U +#define KEY_HELP 0x75U +#define KEY_MENU 0x76U +#define KEY_SELECT 0x77U +#define KEY_STOP 0x78U +#define KEY_AGAIN 0x79U +#define KEY_UNDO 0x7AU +#define KEY_CUT 0x7BU +#define KEY_COPY 0x7CU +#define KEY_PASTE 0x7DU +#define KEY_FIND 0x7EU +#define KEY_MUTE 0x7FU +#define KEY_VOLUME_UP 0x80U +#define KEY_VOLUME_DOWN 0x81U +#define KEY_LOCKING_CAPS_LOCK 0x82U +#define KEY_LOCKING_NUM_LOCK 0x83U +#define KEY_LOCKING_SCROLL_LOCK 0x84U +#define KEY_KEYPAD_COMMA 0x85U +#define KEY_KEYPAD_EQUAL_SIGN 0x86U +#define KEY_INTERNATIONAL1 0x87U +#define KEY_INTERNATIONAL2 0x88U +#define KEY_INTERNATIONAL3 0x89U +#define KEY_INTERNATIONAL4 0x8AU +#define KEY_INTERNATIONAL5 0x8BU +#define KEY_INTERNATIONAL6 0x8CU +#define KEY_INTERNATIONAL7 0x8DU +#define KEY_INTERNATIONAL8 0x8EU +#define KEY_INTERNATIONAL9 0x8FU +#define KEY_LANG1 0x90U +#define KEY_LANG2 0x91U +#define KEY_LANG3 0x92U +#define KEY_LANG4 0x93U +#define KEY_LANG5 0x94U +#define KEY_LANG6 0x95U +#define KEY_LANG7 0x96U +#define KEY_LANG8 0x97U +#define KEY_LANG9 0x98U +#define KEY_ALTERNATE_ERASE 0x99U +#define KEY_SYSREQ 0x9AU +#define KEY_CANCEL 0x9BU +#define KEY_CLEAR 0x9CU +#define KEY_PRIOR 0x9DU +#define KEY_RETURN 0x9EU +#define KEY_SEPARATOR 0x9FU +#define KEY_OUT 0xA0U +#define KEY_OPER 0xA1U +#define KEY_CLEAR_AGAIN 0xA2U +#define KEY_CRSEL 0xA3U +#define KEY_EXSEL 0xA4U +#define KEY_KEYPAD_00 0xB0U +#define KEY_KEYPAD_000 0xB1U +#define KEY_THOUSANDS_SEPARATOR 0xB2U +#define KEY_DECIMAL_SEPARATOR 0xB3U +#define KEY_CURRENCY_UNIT 0xB4U +#define KEY_CURRENCY_SUB_UNIT 0xB5U +#define KEY_KEYPAD_OPARENTHESIS 0xB6U +#define KEY_KEYPAD_CPARENTHESIS 0xB7U +#define KEY_KEYPAD_OBRACE 0xB8U +#define KEY_KEYPAD_CBRACE 0xB9U +#define KEY_KEYPAD_TAB 0xBAU +#define KEY_KEYPAD_BACKSPACE 0xBBU +#define KEY_KEYPAD_A 0xBCU +#define KEY_KEYPAD_B 0xBDU +#define KEY_KEYPAD_C 0xBEU +#define KEY_KEYPAD_D 0xBFU +#define KEY_KEYPAD_E 0xC0U +#define KEY_KEYPAD_F 0xC1U +#define KEY_KEYPAD_XOR 0xC2U +#define KEY_KEYPAD_CARET 0xC3U +#define KEY_KEYPAD_PERCENT 0xC4U +#define KEY_KEYPAD_LESS 0xC5U +#define KEY_KEYPAD_GREATER 0xC6U +#define KEY_KEYPAD_AMPERSAND 0xC7U +#define KEY_KEYPAD_LOGICAL_AND 0xC8U +#define KEY_KEYPAD_VERTICAL_BAR 0xC9U +#define KEY_KEYPAD_LOGIACL_OR 0xCAU +#define KEY_KEYPAD_COLON 0xCBU +#define KEY_KEYPAD_NUMBER_SIGN 0xCCU +#define KEY_KEYPAD_SPACE 0xCDU +#define KEY_KEYPAD_AT 0xCEU +#define KEY_KEYPAD_EXCLAMATION_MARK 0xCFU +#define KEY_KEYPAD_MEMORY_STORE 0xD0U +#define KEY_KEYPAD_MEMORY_RECALL 0xD1U +#define KEY_KEYPAD_MEMORY_CLEAR 0xD2U +#define KEY_KEYPAD_MEMORY_ADD 0xD3U +#define KEY_KEYPAD_MEMORY_SUBTRACT 0xD4U +#define KEY_KEYPAD_MEMORY_MULTIPLY 0xD5U +#define KEY_KEYPAD_MEMORY_DIVIDE 0xD6U +#define KEY_KEYPAD_PLUSMINUS 0xD7U +#define KEY_KEYPAD_CLEAR 0xD8U +#define KEY_KEYPAD_CLEAR_ENTRY 0xD9U +#define KEY_KEYPAD_BINARY 0xDAU +#define KEY_KEYPAD_OCTAL 0xDBU +#define KEY_KEYPAD_DECIMAL 0xDCU +#define KEY_KEYPAD_HEXADECIMAL 0xDDU +#define KEY_LEFTCONTROL 0xE0U +#define KEY_LEFTSHIFT 0xE1U +#define KEY_LEFTALT 0xE2U +#define KEY_LEFT_GUI 0xE3U +#define KEY_RIGHTCONTROL 0xE4U +#define KEY_RIGHTSHIFT 0xE5U +#define KEY_RIGHTALT 0xE6U +#define KEY_RIGHT_GUI 0xE7U + +#define KBR_MAX_NBR_PRESSED 6U + +typedef struct +{ + uint8_t state; + uint8_t lctrl; + uint8_t lshift; + uint8_t lalt; + uint8_t lgui; + uint8_t rctrl; + uint8_t rshift; + uint8_t ralt; + uint8_t rgui; + uint8_t keys[6]; +} hid_keybd_info; + +/* function declarations */ +/* initialize keyboard */ +void USR_KEYBRD_Init (void); +/* process keyboard data */ +void USR_KEYBRD_ProcessData (uint8_t pbuf); +/* initialize the keyboard function */ +usbh_status usbh_hid_keybd_init (usb_core_driver *udev, usbh_host *uhost); +/* get keyboard information */ +hid_keybd_info *usbh_hid_keybd_info_get (usb_core_driver *udev, usbh_host *uhost); +/* get the ascii code of hid */ +uint8_t usbh_hid_ascii_code_get (hid_keybd_info *info); +/* keyboard machine */ +void usbh_hid_keybrd_machine (usb_core_driver *udev, usbh_host *uhost); + +#endif /* __USBH_HID_KEYBD_H */ diff --git a/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/host/class/hid/Include/usbh_hid_mouse.h b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/host/class/hid/Include/usbh_hid_mouse.h new file mode 100644 index 0000000000..f835ea9391 --- /dev/null +++ b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/host/class/hid/Include/usbh_hid_mouse.h @@ -0,0 +1,59 @@ +/*! + \file usbh_hid_mouse.h + \brief header file for the usbh_hid_mouse.c + + \version 2020-07-17, V3.0.0, firmware for GD32F10x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef __USBH_HID_MOUSE_H +#define __USBH_HID_MOUSE_H + +#include "usbh_hid_core.h" + +typedef struct _hid_mouse_info +{ + uint8_t x; + uint8_t y; + uint8_t buttons[3]; +} hid_mouse_info; + +/* function declarations */ +/* initialize mouse */ +void USR_MOUSE_Init (void); +/* process mouse data */ +void USR_MOUSE_ProcessData (hid_mouse_info *data); +/* initialize mouse function */ +usbh_status usbh_hid_mouse_init (usb_core_driver *udev, usbh_host *uhost); +/* get mouse information */ +hid_mouse_info *usbh_hid_mouse_info_get (usb_core_driver *udev, usbh_host *uhost); +/* mouse machine */ +void usbh_hid_mouse_machine (usb_core_driver *udev, usbh_host *uhost); + +#endif /* __USBH_HID_MOUSE_H */ diff --git a/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/host/class/hid/Include/usbh_hid_parser.h b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/host/class/hid/Include/usbh_hid_parser.h new file mode 100644 index 0000000000..dcefd810e5 --- /dev/null +++ b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/host/class/hid/Include/usbh_hid_parser.h @@ -0,0 +1,62 @@ +/*! + \file usbh_hid_core.h + \brief header file for the usbh_hid_core.c + + \version 2020-07-17, V3.0.0, firmware for GD32F10x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + + +#ifndef __USBH_HID_PARSER_H +#define __USBH_HID_PARSER_H + +#include "usbh_hid_core.h" +#include "usbh_hid_usage.h" + +typedef struct +{ + uint8_t *data; + uint32_t size; + uint8_t shift; + uint8_t count; + uint8_t sign; + uint32_t logical_min; /*min value device can return*/ + uint32_t logical_max; /*max value device can return*/ + uint32_t physical_min; /*min vale read can report*/ + uint32_t physical_max; /*max value read can report*/ + uint32_t resolution; +} hid_report_item; + +/* function declarations */ +/* read a hid report item */ +uint32_t hid_item_read (hid_report_item *ri, uint8_t ndx); +/* write a hid report item */ +uint32_t hid_item_write (hid_report_item *ri, uint32_t value, uint8_t ndx); + +#endif /* __USBH_HID_PARSER_H */ diff --git a/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/host/class/hid/Include/usbh_hid_usage.h b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/host/class/hid/Include/usbh_hid_usage.h new file mode 100644 index 0000000000..6ad3e93557 --- /dev/null +++ b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/host/class/hid/Include/usbh_hid_usage.h @@ -0,0 +1,141 @@ +/*! + \file usbh_hid_core.h + \brief header file for the usbh_hid_core.c + + \version 2020-07-17, V3.0.0, firmware for GD32F10x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef __USDH_HID_USAGE_H +#define __USDH_HID_USAGE_H + +/* HID 1.11 usage pages */ +#define HID_USAGE_PAGE_UNDEFINED uint16_t (0x00) /* Undefined */ + +/* top level pages */ +#define HID_USAGE_PAGE_GEN_DES uint16_t (0x01) /* Generic Desktop Controls*/ +#define HID_USAGE_PAGE_SIM_CTR uint16_t (0x02) /* Simulation Controls */ +#define HID_USAGE_PAGE_VR_CTR uint16_t (0x03) /* VR Controls */ +#define HID_USAGE_PAGE_SPORT_CTR uint16_t (0x04) /* Sport Controls */ +#define HID_USAGE_PAGE_GAME_CTR uint16_t (0x05) /* Game Controls */ +#define HID_USAGE_PAGE_GEN_DEV uint16_t (0x06) /* Generic Device Controls */ +#define HID_USAGE_PAGE_KEYB uint16_t (0x07) /* Keyboard/Keypad */ +#define HID_USAGE_PAGE_LED uint16_t (0x08) /* LEDs */ +#define HID_USAGE_PAGE_BUTTON uint16_t (0x09) /* Button */ +#define HID_USAGE_PAGE_ORDINAL uint16_t (0x0A) /* Ordinal */ +#define HID_USAGE_PAGE_PHONE uint16_t (0x0B) /* Telephony */ +#define HID_USAGE_PAGE_CONSUMER uint16_t (0x0C) /* Consumer */ +#define HID_USAGE_PAGE_DIGITIZER uint16_t (0x0D) /* Digitizer*/ +#define HID_USAGE_PAGE_PID uint16_t (0x0F) /* PID Page (force feedback and related devices) */ +#define HID_USAGE_PAGE_UNICODE uint16_t (0x10) /* Unicode */ +#define HID_USAGE_PAGE_ALNUM_DISP uint16_t (0x14) /* Alphanumeric Display */ +/* end of top level pages */ + +#define HID_USAGE_PAGE_MEDICAL uint16_t (0x40) /* Medical Instruments */ + +/* 80-83 Monitor pages USB Device Class Definition for Monitor Devices */ +/* 84-87 Power pages USB Device Class Definition for Power Devices */ +#define HID_USAGE_PAGE_BARCODE uint16_t (0x8C) /* Bar Code Scanner page */ +#define HID_USAGE_PAGE_SCALE uint16_t (0x8D) /* Scale page */ +#define HID_USAGE_PAGE_MSR uint16_t (0x8E) /* Magnetic Stripe Reading (MSR) Devices */ +#define HID_USAGE_PAGE_POS uint16_t (0x8F) /* Reserved Point of Sale pages */ +#define HID_USAGE_PAGE_CAMERA_CTR uint16_t (0x90) /* Camera Control Page */ +#define HID_USAGE_PAGE_ARCADE uint16_t (0x91) /* Arcade Page */ + +/* usage definitions for the "generic desktop" page */ +#define HID_USAGE_UNDEFINED uint16_t (0x00) /* Undefined */ +#define HID_USAGE_POINTER uint16_t (0x01) /* Pointer (Physical Collection) */ +#define HID_USAGE_MOUSE uint16_t (0x02) /* Mouse (Application Collection) */ +#define HID_USAGE_JOYSTICK uint16_t (0x04) /* Joystick (Application Collection) */ +#define HID_USAGE_GAMEPAD uint16_t (0x05) /* Game Pad (Application Collection) */ +#define HID_USAGE_KBD uint16_t (0x06) /* Keyboard (Application Collection) */ +#define HID_USAGE_KEYPAD uint16_t (0x07) /* Keypad (Application Collection) */ +#define HID_USAGE_MAX_CTR uint16_t (0x08) /* Multi-axis Controller (Application Collection) */ +#define HID_USAGE_X uint16_t (0x30) /* X (Dynamic Value) */ +#define HID_USAGE_Y uint16_t (0x31) /* Y (Dynamic Value) */ +#define HID_USAGE_Z uint16_t (0x32) /* Z (Dynamic Value) */ +#define HID_USAGE_RX uint16_t (0x33) /* Rx (Dynamic Value) */ +#define HID_USAGE_RY uint16_t (0x34) /* Ry (Dynamic Value) */ +#define HID_USAGE_RZ uint16_t (0x35) /* Rz (Dynamic Value) */ +#define HID_USAGE_SLIDER uint16_t (0x36) /* Slider (Dynamic Value) */ +#define HID_USAGE_DIAL uint16_t (0x37) /* Dial (Dynamic Value) */ +#define HID_USAGE_WHEEL uint16_t (0x38) /* Wheel (Dynamic Value) */ +#define HID_USAGE_HATSW uint16_t (0x39) /* Hat switch (Dynamic Value) */ +#define HID_USAGE_COUNTEDBUF uint16_t (0x3A) /* Counted Buffer (Logical Collection) */ +#define HID_USAGE_BYTECOUNT uint16_t (0x3B) /* Byte Count (Dynamic Value) */ +#define HID_USAGE_MOTIONWAKE uint16_t (0x3C) /* Motion Wakeup (One Shot Control) */ +#define HID_USAGE_START uint16_t (0x3D) /* Start (On/Off Control) */ +#define HID_USAGE_SELECT uint16_t (0x3E) /* Select (On/Off Control) */ +#define HID_USAGE_VX uint16_t (0x40) /* Vx (Dynamic Value) */ +#define HID_USAGE_VY uint16_t (0x41) /* Vy (Dynamic Value) */ +#define HID_USAGE_VZ uint16_t (0x42) /* Vz (Dynamic Value) */ +#define HID_USAGE_VBRX uint16_t (0x43) /* Vbrx (Dynamic Value) */ +#define HID_USAGE_VBRY uint16_t (0x44) /* Vbry (Dynamic Value) */ +#define HID_USAGE_VBRZ uint16_t (0x45) /* Vbrz (Dynamic Value) */ +#define HID_USAGE_VNO uint16_t (0x46) /* Vno (Dynamic Value) */ +#define HID_USAGE_FEATNOTIF uint16_t (0x47) /* Feature Notification (Dynamic Value),(Dynamic Flag) */ +#define HID_USAGE_SYSCTL uint16_t (0x80) /* System Control (Application Collection) */ +#define HID_USAGE_PWDOWN uint16_t (0x81) /* System Power Down (One Shot Control) */ +#define HID_USAGE_SLEEP uint16_t (0x82) /* System Sleep (One Shot Control) */ +#define HID_USAGE_WAKEUP uint16_t (0x83) /* System Wake Up (One Shot Control) */ +#define HID_USAGE_CONTEXTM uint16_t (0x84) /* System Context Menu (One Shot Control) */ +#define HID_USAGE_MAINM uint16_t (0x85) /* System Main Menu (One Shot Control) */ +#define HID_USAGE_APPM uint16_t (0x86) /* System App Menu (One Shot Control) */ +#define HID_USAGE_MENUHELP uint16_t (0x87) /* System Menu Help (One Shot Control) */ +#define HID_USAGE_MENUEXIT uint16_t (0x88) /* System Menu Exit (One Shot Control) */ +#define HID_USAGE_MENUSELECT uint16_t (0x89) /* System Menu Select (One Shot Control) */ +#define HID_USAGE_SYSM_RIGHT uint16_t (0x8A) /* System Menu Right (Re-Trigger Control) */ +#define HID_USAGE_SYSM_LEFT uint16_t (0x8B) /* System Menu Left (Re-Trigger Control) */ +#define HID_USAGE_SYSM_UP uint16_t (0x8C) /* System Menu Up (Re-Trigger Control) */ +#define HID_USAGE_SYSM_DOWN uint16_t (0x8D) /* System Menu Down (Re-Trigger Control) */ +#define HID_USAGE_COLDRESET uint16_t (0x8E) /* System Cold Restart (One Shot Control) */ +#define HID_USAGE_WARMRESET uint16_t (0x8F) /* System Warm Restart (One Shot Control) */ +#define HID_USAGE_DUP uint16_t (0x90) /* D-pad Up (On/Off Control) */ +#define HID_USAGE_DDOWN uint16_t (0x91) /* D-pad Down (On/Off Control) */ +#define HID_USAGE_DRIGHT uint16_t (0x92) /* D-pad Right (On/Off Control) */ +#define HID_USAGE_DLEFT uint16_t (0x93) /* D-pad Left (On/Off Control) */ +#define HID_USAGE_SYS_DOCK uint16_t (0xA0) /* System Dock (One Shot Control) */ +#define HID_USAGE_SYS_UNDOCK uint16_t (0xA1) /* System Undock (One Shot Control) */ +#define HID_USAGE_SYS_SETUP uint16_t (0xA2) /* System Setup (One Shot Control) */ +#define HID_USAGE_SYS_BREAK uint16_t (0xA3) /* System Break (One Shot Control) */ +#define HID_USAGE_SYS_DBGBRK uint16_t (0xA4) /* System Debugger Break (One Shot Control) */ +#define HID_USAGE_APP_BRK uint16_t (0xA5) /* Application Break (One Shot Control) */ +#define HID_USAGE_APP_DBGBRK uint16_t (0xA6) /* Application Debugger Break (One Shot Control) */ +#define HID_USAGE_SYS_SPKMUTE uint16_t (0xA7) /* System Speaker Mute (One Shot Control) */ +#define HID_USAGE_SYS_HIBERN uint16_t (0xA8) /* System Hibernate (One Shot Control) */ +#define HID_USAGE_SYS_SIDPINV uint16_t (0xB0) /* System Display Invert (One Shot Control) */ +#define HID_USAGE_SYS_DISPINT uint16_t (0xB1) /* System Display Internal (One Shot Control) */ +#define HID_USAGE_SYS_DISPEXT uint16_t (0xB2) /* System Display External (One Shot Control) */ +#define HID_USAGE_SYS_DISPBOTH uint16_t (0xB3) /* System Display Both (One Shot Control) */ +#define HID_USAGE_SYS_DISPDUAL uint16_t (0xB4) /* System Display Dual (One Shot Control) */ +#define HID_USAGE_SYS_DISPTGLIE uint16_t (0xB5) /* System Display Toggle Int/Ext (One Shot Control) */ +#define HID_USAGE_SYS_DISP_SWAP uint16_t (0xB6) /* System Display Swap Primary/Secondary (One Shot Control) */ +#define HID_USAGE_SYS_DIPS_LCDA uint16_t (0xB7) /* System Display LCD Autoscale (One Shot Control) */ + +#endif /* __USDH_HID_USAGE_H */ diff --git a/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/host/class/hid/Source/usbh_hid_core.c b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/host/class/hid/Source/usbh_hid_core.c new file mode 100644 index 0000000000..35e97af107 --- /dev/null +++ b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/host/class/hid/Source/usbh_hid_core.c @@ -0,0 +1,676 @@ +/*! + \file usbh_hid_core.c + \brief USB host HID class driver + + \version 2020-07-17, V3.0.0, firmware for GD32F10x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "usbh_pipe.h" +#include "usbh_hid_core.h" +#include "usbh_hid_mouse.h" +#include "usbh_hid_keybd.h" + +#include +#include + +static void usbh_hiddesc_parse (usb_desc_hid *hid_desc, uint8_t *buf); +static void usbh_hid_itf_deinit (usbh_host *uhost); +static usbh_status usbh_hid_itf_init (usbh_host *uhost); +static usbh_status usbh_hid_class_req (usbh_host *uhost); +static usbh_status usbh_hid_handle (usbh_host *uhost); +static usbh_status usbh_hid_reportdesc_get (usbh_host *uhost, uint16_t len); +static usbh_status usbh_hid_sof(usbh_host *uhost); +static usbh_status usbh_hid_desc_get (usbh_host *uhost, uint16_t len); +static usbh_status usbh_set_idle (usbh_host *uhost, uint8_t duration, uint8_t report_ID); +static usbh_status usbh_set_protocol (usbh_host *uhost, uint8_t protocol); + +usbh_class usbh_hid = +{ + USB_HID_CLASS, + usbh_hid_itf_init, + usbh_hid_itf_deinit, + usbh_hid_class_req, + usbh_hid_handle, + usbh_hid_sof +}; + +/*! + \brief get report + \param[in] uhost: pointer to USB host + \param[in] report_type: duration for HID set idle request + \param[in] report_ID: targeted report ID for HID set idle request + \param[in] report_len: length of data report to be send + \param[in] report_buf: report buffer + \param[out] none + \retval operation status +*/ +usbh_status usbh_get_report (usbh_host *uhost, + uint8_t report_type, + uint8_t report_ID, + uint8_t report_len, + uint8_t *report_buf) +{ + usbh_status status = USBH_BUSY; + + if (CTL_IDLE == uhost->control.ctl_state) { + uhost->control.setup.req = (usb_req) { + .bmRequestType = USB_TRX_IN | USB_RECPTYPE_ITF | USB_REQTYPE_CLASS, + .bRequest = GET_REPORT, + .wValue = (report_type << 8U) | report_ID, + .wIndex = 0U, + .wLength = report_len + }; + + usbh_ctlstate_config (uhost, report_buf, report_len); + } + + status = usbh_ctl_handler (uhost); + + return status; +} + +/*! + \brief set report + \param[in] udev: pointer to USB core instance + \param[in] uhost: pointer to USB host + \param[in] report_type: duration for HID set idle request + \param[in] report_ID: targeted report ID for HID set idle request + \param[in] report_len: length of data report to be send + \param[in] report_buf: report buffer + \param[out] none + \retval operation status +*/ +usbh_status usbh_set_report (usb_core_driver *udev, + usbh_host *uhost, + uint8_t report_type, + uint8_t report_ID, + uint8_t report_len, + uint8_t *report_buf) +{ + usbh_status status = USBH_BUSY; + + if (CTL_IDLE == uhost->control.ctl_state) { + uhost->control.setup.req = (usb_req) { + .bmRequestType = USB_TRX_OUT | USB_RECPTYPE_ITF | USB_REQTYPE_CLASS, + .bRequest = SET_REPORT, + .wValue = (report_type << 8U) | report_ID, + .wIndex = 0U, + .wLength = report_len + }; + + usbh_ctlstate_config (uhost, report_buf, report_len); + } + + status = usbh_ctl_handler (uhost); + + return status; +} + +/*! + \brief deinitialize the host pipes used for the HID class + \param[in] uhost: pointer to USB host + \param[out] none + \retval operation status +*/ +void usbh_hid_itf_deinit (usbh_host *uhost) +{ + usbh_hid_handler *hid = (usbh_hid_handler *)uhost->active_class->class_data; + + if (0x00U != hid->pipe_in) { + usb_pipe_halt (uhost->data, hid->pipe_in); + + usbh_pipe_free (uhost->data, hid->pipe_in); + + hid->pipe_in = 0U; /* reset the pipe as free */ + } + + if (0x00U != hid->pipe_out) { + usb_pipe_halt (uhost->data, hid->pipe_out); + + usbh_pipe_free (uhost->data, hid->pipe_out); + + hid->pipe_out = 0U; /* reset the channel as free */ + } +} + +/*! + \brief return device type + \param[in] udev: pointer to USB core instance + \param[in] uhost: pointer to USB host + \param[out] none + \retval hid_type +*/ +hid_type usbh_hid_device_type_get(usb_core_driver *udev, usbh_host *uhost) +{ + hid_type type = HID_UNKNOWN; + uint8_t interface_protocol; + + if (HOST_CLASS_HANDLER == uhost->cur_state) { + interface_protocol = uhost->dev_prop.cfg_desc_set.itf_desc_set[uhost->dev_prop.cur_itf][0].itf_desc.bInterfaceProtocol; + + if (USB_HID_PROTOCOL_KEYBOARD == interface_protocol) { + type = HID_KEYBOARD; + } else { + if (USB_HID_PROTOCOL_MOUSE == interface_protocol) { + type = HID_MOUSE; + } + } + } + + return type; +} + +/*! + \brief return HID device poll time + \param[in] udev: pointer to USB core instance + \param[in] uhost: pointer to USB host + \param[out] none + \retval poll time (ms) +*/ +uint8_t usbh_hid_poll_interval_get (usb_core_driver *udev, usbh_host *uhost) +{ + usbh_hid_handler *hid = (usbh_hid_handler *)uhost->active_class->class_data; + + if ((HOST_CLASS_ENUM == uhost->cur_state) || + (HOST_USER_INPUT == uhost->cur_state) || + (HOST_CHECK_CLASS == uhost->cur_state) || + (HOST_CLASS_HANDLER == uhost->cur_state)) { + return (uint8_t)(hid->poll); + } else { + return 0U; + } +} + +/*! + \brief read from FIFO + \param[in] fifo: fifo address + \param[in] buf: read buffer + \param[in] nbytes: number of item to read + \param[out] none + \retval number of read items +*/ +uint16_t usbh_hid_fifo_read (data_fifo *fifo, void *buf, uint16_t nbytes) +{ + uint16_t i = 0U; + uint8_t *p = (uint8_t*) buf; + + if (0U == fifo->lock) { + fifo->lock = 1U; + + for (i = 0U; i < nbytes; i++) { + if (fifo->tail != fifo->head) { + *p++ = fifo->buf[fifo->tail]; + fifo->tail++; + + if (fifo->tail == fifo->size) { + fifo->tail = 0U; + } + } else { + fifo->lock = 0U; + + return i; + } + } + } + + fifo->lock = 0U; + + return nbytes; +} + +/*! + \brief write to FIFO + \param[in] fifo: fifo address + \param[in] buf: read buffer + \param[in] nbytes: number of item to read + \param[out] none + \retval number of write items +*/ +uint16_t usbh_hid_fifo_write (data_fifo *fifo, void *buf, uint16_t nbytes) +{ + uint16_t i = 0U; + uint8_t *p = (uint8_t*) buf; + + if (0U == fifo->lock) { + fifo->lock = 1U; + + for (i = 0U; i < nbytes; i++) { + if ((fifo->head + 1U == fifo->tail) || + ((fifo->head + 1U == fifo->size) && (0U == fifo->tail))) { + fifo->lock = 0U; + + return i; + } else { + fifo->buf[fifo->head] = *p++; + fifo->head++; + + if (fifo->head == fifo->size) { + fifo->head = 0U; + } + } + } + } + + fifo->lock = 0U; + + return nbytes; +} + +/*! + \brief initialize FIFO + \param[in] fifo: fifo address + \param[in] buf: read buffer + \param[in] size: size of FIFO + \param[out] none + \retval none +*/ +void usbh_hid_fifo_init (data_fifo *fifo, uint8_t *buf, uint16_t size) +{ + fifo->head = 0U; + fifo->tail = 0U; + fifo->lock = 0U; + fifo->size = size; + fifo->buf = buf; +} + +/*! + \brief initialize the hid class + \param[in] uhost: pointer to USB host + \param[out] none + \retval operation status +*/ +static usbh_status usbh_hid_itf_init (usbh_host *uhost) +{ + uint8_t num = 0U, ep_num = 0U, interface = 0U; + usbh_status status = USBH_BUSY; + + interface = usbh_interface_find(&uhost->dev_prop, USB_HID_CLASS, USB_HID_SUBCLASS_BOOT_ITF, 0xFFU); + + if (0xFFU == interface) { + uhost->usr_cb->dev_not_supported(); + + status = USBH_FAIL; + } else { + usbh_interface_select(&uhost->dev_prop, interface); + + static usbh_hid_handler hid_handler; + + memset((void*)&hid_handler, 0, sizeof(usbh_hid_handler)); + + hid_handler.state = HID_ERROR; + + uint8_t itf_protocol = uhost->dev_prop.cfg_desc_set.itf_desc_set[uhost->dev_prop.cur_itf][0].itf_desc.bInterfaceProtocol; + if (USB_HID_PROTOCOL_KEYBOARD == itf_protocol) { + hid_handler.init = usbh_hid_keybd_init; + hid_handler.machine = usbh_hid_keybrd_machine; + } else if (USB_HID_PROTOCOL_MOUSE == itf_protocol) { + hid_handler.init = usbh_hid_mouse_init; + hid_handler.machine = usbh_hid_mouse_machine; + } else { + status = USBH_FAIL; + } + + hid_handler.state = HID_INIT; + hid_handler.ctl_state = HID_REQ_INIT; + hid_handler.ep_addr = uhost->dev_prop.cfg_desc_set.itf_desc_set[uhost->dev_prop.cur_itf][0].ep_desc[0].bEndpointAddress; + hid_handler.len = uhost->dev_prop.cfg_desc_set.itf_desc_set[uhost->dev_prop.cur_itf][0].ep_desc[0].wMaxPacketSize; + hid_handler.poll = uhost->dev_prop.cfg_desc_set.itf_desc_set[uhost->dev_prop.cur_itf][0].ep_desc[0].bInterval; + + if (hid_handler.poll < HID_MIN_POLL) { + hid_handler.poll = HID_MIN_POLL; + } + + /* check fifo available number of endpoints */ + /* find the number of endpoints in the interface descriptor */ + /* choose the lower number in order not to overrun the buffer allocated */ + ep_num = USB_MIN(uhost->dev_prop.cfg_desc_set.itf_desc_set[uhost->dev_prop.cur_itf][0].itf_desc.bNumEndpoints, USBH_MAX_EP_NUM); + + /* decode endpoint IN and OUT address from interface descriptor */ + for (num = 0U; num < ep_num; num++) { + usb_desc_ep *ep_desc = &uhost->dev_prop.cfg_desc_set.itf_desc_set[uhost->dev_prop.cur_itf][0].ep_desc[num]; + + uint8_t ep_addr = ep_desc->bEndpointAddress; + + if (ep_addr & 0x80U) { + hid_handler.ep_in = ep_addr; + hid_handler.pipe_in = usbh_pipe_allocate (uhost->data, ep_addr); + + /* open channel for IN endpoint */ + usbh_pipe_create (uhost->data, + &uhost->dev_prop, + hid_handler.pipe_in, + USB_EPTYPE_INTR, + hid_handler.len); + + usbh_pipe_toggle_set(uhost->data, hid_handler.pipe_in, 0U); + } else { + hid_handler.ep_out = ep_addr; + hid_handler.pipe_out = usbh_pipe_allocate (uhost->data, ep_addr); + + /* open channel for OUT endpoint */ + usbh_pipe_create (uhost->data, + &uhost->dev_prop, + hid_handler.pipe_out, + USB_EPTYPE_INTR, + hid_handler.len); + + usbh_pipe_toggle_set(uhost->data, hid_handler.pipe_out, 0U); + } + } + + uhost->active_class->class_data = (void *)&hid_handler; + + status = USBH_OK; + } + + return status; +} + +/*! + \brief handle HID class requests for HID class + \param[in] uhost: pointer to USB host + \param[out] none + \retval operation status +*/ +static usbh_status usbh_hid_class_req (usbh_host *uhost) +{ + usbh_status status = USBH_BUSY; + usbh_status class_req_status = USBH_BUSY; + + usbh_hid_handler *hid = (usbh_hid_handler *)uhost->active_class->class_data; + + /* handle HID control state machine */ + switch (hid->ctl_state) { + case HID_REQ_INIT: + case HID_REQ_GET_HID_DESC: + /* get HID descriptor */ + if (USBH_OK == usbh_hid_desc_get (uhost, USB_HID_DESC_SIZE)) { + usbh_hiddesc_parse(&hid->hid_desc, uhost->dev_prop.data); + + hid->ctl_state = HID_REQ_GET_REPORT_DESC; + } + break; + + case HID_REQ_GET_REPORT_DESC: + /* get report descriptor */ + if (USBH_OK == usbh_hid_reportdesc_get(uhost, hid->hid_desc.wDescriptorLength)) { + hid->ctl_state = HID_REQ_SET_IDLE; + } + break; + + case HID_REQ_SET_IDLE: + class_req_status = usbh_set_idle (uhost, 0U, 0U); + + /* set idle */ + if (USBH_OK == class_req_status) { + hid->ctl_state = HID_REQ_SET_PROTOCOL; + } else { + if(USBH_NOT_SUPPORTED == class_req_status) { + hid->ctl_state = HID_REQ_SET_PROTOCOL; + } + } + break; + + case HID_REQ_SET_PROTOCOL: + /* set protocol */ + if (USBH_OK == usbh_set_protocol (uhost, 0U)) { + hid->ctl_state = HID_REQ_IDLE; + + /* all requests performed */ + status = USBH_OK; + } + break; + + case HID_REQ_IDLE: + default: + break; + } + + return status; +} + +/*! + \brief manage state machine for HID data transfers + \param[in] uhost: pointer to USB host + \param[out] none + \retval operation status +*/ +static usbh_status usbh_hid_handle (usbh_host *uhost) +{ + usbh_status status = USBH_OK; + usbh_hid_handler *hid = (usbh_hid_handler *)uhost->active_class->class_data; + + switch (hid->state) { + case HID_INIT: + hid->init(uhost->data, uhost); + hid->state = HID_IDLE; + break; + + case HID_IDLE: + hid->state = HID_SYNC; + status = USBH_OK; + break; + + case HID_SYNC: + /* sync with start of even frame */ + if (true == usb_frame_even(uhost->data)) { + hid->state = HID_GET_DATA; + } + break; + + case HID_GET_DATA: + usbh_data_recev (uhost->data, hid->pdata, hid->pipe_in, hid->len); + + hid->state = HID_POLL; + hid->timer = usb_curframe_get (uhost->data); + hid->data_ready = 0U; + break; + + case HID_POLL: + if (URB_DONE == usbh_urbstate_get (uhost->data, hid->pipe_in)) { + if (0U == hid->data_ready) { /* handle data once */ + usbh_hid_fifo_write(&hid->fifo, hid->pdata, hid->len); + hid->data_ready = 1U; + + hid->machine(uhost->data, uhost); + } + } else { + if (URB_STALL == usbh_urbstate_get (uhost->data, hid->pipe_in)) { /* IN endpoint stalled */ + /* issue clear feature on interrupt in endpoint */ + if (USBH_OK == (usbh_clrfeature (uhost, hid->ep_addr, hid->pipe_in))) { + /* change state to issue next in token */ + hid->state = HID_GET_DATA; + } + } + } + break; + + default: + break; + } + return status; +} + +/*! + \brief send get report descriptor command to the device + \param[in] uhost: pointer to USB host + \param[in] len: HID report descriptor length + \param[out] none + \retval operation status +*/ +static usbh_status usbh_hid_reportdesc_get (usbh_host *uhost, uint16_t len) +{ + usbh_status status = USBH_BUSY; + + if (CTL_IDLE == uhost->control.ctl_state) { + uhost->control.setup.req = (usb_req) { + .bmRequestType = USB_TRX_IN | USB_RECPTYPE_ITF | USB_REQTYPE_STRD, + .bRequest = USB_GET_DESCRIPTOR, + .wValue = USBH_DESC(USB_DESCTYPE_REPORT), + .wIndex = 0U, + .wLength = len + }; + + usbh_ctlstate_config (uhost, uhost->dev_prop.data, len); + } + + status = usbh_ctl_handler (uhost); + + return status; +} + +/*! + \brief managing the SOF process + \param[in] uhost: pointer to USB host + \param[out] none + \retval operation status +*/ +static usbh_status usbh_hid_sof(usbh_host *uhost) +{ + usbh_hid_handler *hid = (usbh_hid_handler *)uhost->active_class->class_data; + + if (HID_POLL == hid->state) { + uint32_t frame_count = usb_curframe_get (uhost->data); + + if ((frame_count > hid->timer) && ((frame_count - hid->timer) >= hid->poll)) { + hid->state = HID_GET_DATA; + } else if ((frame_count < hid->timer) && ((frame_count + 0x3FFFU - hid->timer) >= hid->poll)) { + hid->state = HID_GET_DATA; + } else { + /* no operation */ + } + } + + return USBH_OK; +} + +/*! + \brief send the command of get HID descriptor to the device + \param[in] uhost: pointer to USB host + \param[in] len: HID descriptor length + \param[out] none + \retval operation status +*/ +static usbh_status usbh_hid_desc_get (usbh_host *uhost, uint16_t len) +{ + usbh_status status = USBH_BUSY; + + if (CTL_IDLE == uhost->control.ctl_state) { + uhost->control.setup.req = (usb_req) { + .bmRequestType = USB_TRX_IN | USB_RECPTYPE_ITF | USB_REQTYPE_STRD, + .bRequest = USB_GET_DESCRIPTOR, + .wValue = USBH_DESC(USB_DESCTYPE_HID), + .wIndex = 0U, + .wLength = len + }; + + usbh_ctlstate_config (uhost, uhost->dev_prop.data, len); + } + + status = usbh_ctl_handler (uhost); + + return status; +} + +/*! + \brief set idle state + \param[in] uhost: pointer to USB host + \param[in] duration: duration for HID set idle request + \param[in] report_ID: targeted report ID for HID set idle request + \param[out] none + \retval operation status +*/ +static usbh_status usbh_set_idle (usbh_host *uhost, uint8_t duration, uint8_t report_ID) +{ + usbh_status status = USBH_BUSY; + + if (CTL_IDLE == uhost->control.ctl_state) { + uhost->control.setup.req = (usb_req) { + .bmRequestType = USB_TRX_OUT | USB_RECPTYPE_ITF | USB_REQTYPE_CLASS, + .bRequest = SET_IDLE, + .wValue = (duration << 8U) | report_ID, + .wIndex = 0U, + .wLength = 0U + }; + + usbh_ctlstate_config (uhost, NULL, 0U); + } + + status = usbh_ctl_handler (uhost); + + return status; +} + +/*! + \brief set protocol state + \param[in] uhost: pointer to USB host + \param[in] protocol: boot/report protocol + \param[out] none + \retval operation status +*/ +static usbh_status usbh_set_protocol (usbh_host *uhost, uint8_t protocol) +{ + usbh_status status = USBH_BUSY; + + if (CTL_IDLE == uhost->control.ctl_state) { + uhost->control.setup.req = (usb_req) { + .bmRequestType = USB_TRX_OUT | USB_RECPTYPE_ITF | USB_REQTYPE_CLASS, + .bRequest = SET_PROTOCOL, + .wValue = !protocol, + .wIndex = 0U, + .wLength = 0U + }; + + usbh_ctlstate_config (uhost, NULL, 0U); + } + + status = usbh_ctl_handler (uhost); + + return status; +} + +/*! + \brief parse the HID descriptor + \param[in] hid_desc: pointer to HID descriptor + \param[in] buf: pointer to buffer where the source descriptor is available + \param[out] none + \retval none +*/ +static void usbh_hiddesc_parse (usb_desc_hid *hid_desc, uint8_t *buf) +{ + hid_desc->header.bLength = *(uint8_t *)(buf + 0U); + hid_desc->header.bDescriptorType = *(uint8_t *)(buf + 1U); + hid_desc->bcdHID = BYTE_SWAP(buf + 2U); + hid_desc->bCountryCode = *(uint8_t *)(buf + 4U); + hid_desc->bNumDescriptors = *(uint8_t *)(buf + 5U); + hid_desc->bDescriptorType = *(uint8_t *)(buf + 6U); + hid_desc->wDescriptorLength = BYTE_SWAP(buf + 7U); +} + diff --git a/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/host/class/hid/Source/usbh_hid_keybd.c b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/host/class/hid/Source/usbh_hid_keybd.c new file mode 100644 index 0000000000..1905f0e040 --- /dev/null +++ b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/host/class/hid/Source/usbh_hid_keybd.c @@ -0,0 +1,399 @@ +/*! + \file usbh_hid_keybd.c + \brief USB host HID keyboard driver + + \version 2020-07-17, V3.0.0, firmware for GD32F10x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "usbh_hid_keybd.h" +#include "usbh_hid_parser.h" +#include + +hid_keybd_info keybd_info; + +uint32_t keybd_report_data[2]; + +static const hid_report_item imp_0_lctrl = +{ + (uint8_t*)(void *)keybd_report_data + 0, /* data */ + 1, /* size */ + 0, /* shift */ + 0, /* count (only for array items) */ + 0, /* signed */ + 0, /* min value read can return */ + 1, /* max value read can return */ + 0, /* min vale device can report */ + 1, /* max value device can report */ + 1 /* resolution */ +}; + +static const hid_report_item imp_0_lshift = +{ + (uint8_t*)(void *)keybd_report_data + 0, /* data */ + 1, /* size */ + 1, /* shift */ + 0, /* count (only for array items) */ + 0, /* signed */ + 0, /* min value read can return */ + 1, /* max value read can return */ + 0, /* min vale device can report */ + 1, /* max value device can report */ + 1 /* resolution */ +}; + +static const hid_report_item imp_0_lalt = +{ + (uint8_t*)(void *)keybd_report_data + 0, /* data */ + 1, /* size */ + 2, /* shift */ + 0, /* count (only for array items) */ + 0, /* signed */ + 0, /* min value read can return */ + 1, /* max value read can return */ + 0, /* min vale device can report */ + 1, /* max value device can report */ + 1 /* resolution */ +}; + +static const hid_report_item imp_0_lgui = +{ + (uint8_t*)(void *)keybd_report_data + 0, /* data */ + 1, /* size */ + 3, /* shift */ + 0, /* count (only for array items) */ + 0, /* signed */ + 0, /* min value read can return */ + 1, /* max value read can return */ + 0, /* min vale device can report */ + 1, /* max value device can report */ + 1 /* resolution */ +}; + +static const hid_report_item imp_0_rctrl = +{ + (uint8_t*)(void *)keybd_report_data + 0, /* data */ + 1, /* size */ + 4, /* shift */ + 0, /* count (only for array items) */ + 0, /* signed */ + 0, /* min value read can return */ + 1, /* max value read can return */ + 0, /* min vale device can report */ + 1, /* max value device can report */ + 1 /* resolution */ +}; + +static const hid_report_item imp_0_rshift = +{ + (uint8_t*)(void *)keybd_report_data + 0, /* data */ + 1, /* size */ + 5, /* shift */ + 0, /* count (only for array items) */ + 0, /* signed */ + 0, /* min value read can return */ + 1, /* max value read can return */ + 0, /* min vale device can report */ + 1, /* max value device can report */ + 1 /* resolution */ +}; + +static const hid_report_item imp_0_ralt = +{ + (uint8_t*)(void *)keybd_report_data + 0, /* data */ + 1, /* size */ + 6, /* shift */ + 0, /* count (only for array items) */ + 0, /* signed */ + 0, /* min value read can return */ + 1, /* max value read can return */ + 0, /* min vale device can report */ + 1, /* max value device can report */ + 1 /* resolution */ +}; + +static const hid_report_item imp_0_rgui = +{ + (uint8_t*)(void *)keybd_report_data + 0, /* data */ + 1, /* size */ + 7, /* shift */ + 0, /* count (only for array items) */ + 0, /* signed */ + 0, /* min value read can return */ + 1, /* max value read can return */ + 0, /* min vale device can report */ + 1, /* max value device can report */ + 1 /* resolution */ +}; + +static const hid_report_item imp_0_key_array = +{ + (uint8_t*)(void *)keybd_report_data + 2, /* data */ + 8, /* size */ + 0, /* shift */ + 6, /* count (only for array items) */ + 0, /* signed */ + 0, /* min value read can return */ + 101, /* max value read can return */ + 0, /* min vale device can report */ + 101, /* max value device can report */ + 1 /* resolution */ +}; + +/* local constants */ +static const uint8_t hid_keybrd_codes[] = +{ + 0, 0, 0, 0, 31, 50, 48, 33, + 19, 34, 35, 36, 24, 37, 38, 39, /* 0x00 - 0x0F */ + 52, 51, 25, 26, 17, 20, 32, 21, + 23, 49, 18, 47, 22, 46, 2, 3, /* 0x10 - 0x1F */ + 4, 5, 6, 7, 8, 9, 10, 11, + 43, 110, 15, 16, 61, 12, 13, 27, /* 0x20 - 0x2F */ + 28, 29, 42, 40, 41, 1, 53, 54, + 55, 30, 112, 113, 114, 115, 116, 117, /* 0x30 - 0x3F */ + 118, 119, 120, 121, 122, 123, 124, 125, + 126, 75, 80, 85, 76, 81, 86, 89, /* 0x40 - 0x4F */ + 79, 84, 83, 90, 95, 100, 105, 106, + 108, 93, 98, 103, 92, 97, 102, 91, /* 0x50 - 0x5F */ + 96, 101, 99, 104, 45, 129, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, /* 0x60 - 0x6F */ + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, /* 0x70 - 0x7F */ + 0, 0, 0, 0, 0, 107, 0, 56, + 0, 0, 0, 0, 0, 0, 0, 0, /* 0x80 - 0x8F */ + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, /* 0x90 - 0x9F */ + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, /* 0xA0 - 0xAF */ + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, /* 0xB0 - 0xBF */ + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, /* 0xC0 - 0xCF */ + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, /* 0xD0 - 0xDF */ + 58, 44, 60, 127, 64, 57, 62, 128 /* 0xE0 - 0xE7 */ +}; + +#ifdef QWERTY_KEYBOARD + +static const int8_t hid_keybrd_key[] = +{ + '\0', '`', '1', '2', '3', '4', '5', '6', + '7', '8', '9', '0', '-', '=', '\0', '\r', + '\t', 'q', 'w', 'e', 'r', 't', 'y', 'u', + 'i', 'o', 'p', '[', ']', '\\', + '\0', 'a', 's', 'd', 'f', 'g', 'h', 'j', + 'k', 'l', ';', '\'', '\0', '\n', + '\0', '\0', 'z', 'x', 'c', 'v', 'b', 'n', + 'm', ',', '.', '/', '\0', '\0', + '\0', '\0', '\0', ' ', '\0', '\0', '\0', '\0', + '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', + '\0', '\0', '\0', '\0', '\0', '\r', '\0', '\0', + '\0', '\0', '\0', '\0', '\0', '\0', + '\0', '\0', '7', '4', '1', + '\0', '/', '8', '5', '2', + '0', '*', '9', '6', '3', + '.', '-', '+', '\0', '\n', '\0', '\0', '\0', '\0', '\0', '\0', + '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', + '\0', '\0', '\0', '\0' +}; + +static const int8_t hid_keybrd_shiftkey[] = { + '\0', '~', '!', '@', '#', '$', '%', '^', '&', '*', '(', ')', + '_', '+', '\0', '\0', '\0', 'Q', 'W', 'E', 'R', 'T', 'Y', 'U', + 'I', 'O', 'P', '{', '}', '|', '\0', 'A', 'S', 'D', 'F', 'G', + 'H', 'J', 'K', 'L', ':', '"', '\0', '\n', '\0', '\0', 'Z', 'X', + 'C', 'V', 'B', 'N', 'M', '<', '>', '?', '\0', '\0', '\0', '\0', + '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', + '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', + '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', + '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', + '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', + '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0' +}; + +#else + +static const int8_t hid_keybrd_key[] = { + '\0', '`', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', + '-', '=', '\0', '\r', '\t', 'a', 'z', 'e', 'r', 't', 'y', 'u', + 'i', 'o', 'p', '[', ']', '\\', '\0', 'q', 's', 'd', 'f', 'g', + 'h', 'j', 'k', 'l', 'm', '\0', '\0', '\n', '\0', '\0', 'w', 'x', + 'c', 'v', 'b', 'n', ',', ';', ':', '!', '\0', '\0', '\0', '\0', + '\0', ' ', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', + '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\r', '\0', '\0', '\0', + '\0', '\0', '\0', '\0', '\0', '\0', '\0', '7', '4', '1', '\0', '/', + '8', '5', '2', '0', '*', '9', '6', '3', '.', '-', '+', '\0', + '\n', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', + '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0' +}; + +static const int8_t hid_keybrd_shiftkey[] = { + '\0', '~', '!', '@', '#', '$', '%', '^', '&', '*', '(', ')', '_', + '+', '\0', '\0', '\0', 'A', 'Z', 'E', 'R', 'T', 'Y', 'U', 'I', 'O', + 'P', '{', '}', '*', '\0', 'Q', 'S', 'D', 'F', 'G', 'H', 'J', 'K', + 'L', 'M', '%', '\0', '\n', '\0', '\0', 'W', 'X', 'C', 'V', 'B', 'N', + '?', '.', '/', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', + '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', + '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', + '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', + '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', + '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0' +}; + +#endif + +/* local function prototypes ('static') */ +static usbh_status usbh_hid_keybrd_decode (usb_core_driver *udev, usbh_host *uhost); + +/*! + \brief initialize the keyboard function + \param[in] udev: pointer to USB core instance + \param[in] uhost: pointer to USB host + \param[out] none + \retval operation status +*/ +usbh_status usbh_hid_keybd_init (usb_core_driver *udev, usbh_host *uhost) +{ + usbh_hid_handler *hid = (usbh_hid_handler *)uhost->active_class->class_data; + + keybd_info.lctrl = keybd_info.lshift = 0U; + keybd_info.lalt = keybd_info.lgui = 0U; + keybd_info.rctrl = keybd_info.rshift = 0U; + keybd_info.ralt = keybd_info.rgui = 0U; + + for (uint32_t x = 0U; x < (sizeof(keybd_report_data) / sizeof(uint32_t)); x++) { + keybd_report_data[x] = 0U; + } + + if (hid->len > (sizeof(keybd_report_data) / sizeof(uint32_t))) { + hid->len = (sizeof(keybd_report_data) / sizeof(uint32_t)); + } + + hid->pdata = (uint8_t*)(void *)keybd_report_data; + + usbh_hid_fifo_init (&hid->fifo, uhost->dev_prop.data, HID_QUEUE_SIZE * sizeof(keybd_report_data)); + + /* call user initialization*/ + USR_KEYBRD_Init(); + + return USBH_OK; +} + +/*! + \brief get keyboard information + \param[in] udev: pointer to USB core instance + \param[in] uhost: pointer to USB host handler + \param[out] none + \retval keyboard information +*/ +hid_keybd_info *usbh_hid_keybd_info_get (usb_core_driver *udev, usbh_host *uhost) +{ + if (USBH_OK == usbh_hid_keybrd_decode(udev, uhost)) { + return &keybd_info; + } else { + return NULL; + } +} + +/*! + \brief get ascii code + \param[in] info: keyboard information + \param[out] none + \retval output +*/ +uint8_t usbh_hid_ascii_code_get (hid_keybd_info *info) +{ + uint8_t output; + if ((1U == info->lshift) || (info->rshift)) { + output = hid_keybrd_shiftkey[hid_keybrd_codes[info->keys[0]]]; + } else { + output = hid_keybrd_key[hid_keybrd_codes[info->keys[0]]]; + } + + return output; +} + +/*! + \brief decode the pressed keys + \param[in] udev: pointer to USB core instance + \param[in] uhost: pointer to USB host + \param[out] none + \retval none +*/ +void usbh_hid_keybrd_machine (usb_core_driver *udev, usbh_host *uhost) +{ + hid_keybd_info *k_pinfo; + + k_pinfo = usbh_hid_keybd_info_get(udev, uhost); + + if (k_pinfo != NULL) { + char c = usbh_hid_ascii_code_get(k_pinfo); + + if (c != 0U) { + USR_KEYBRD_ProcessData(c); + } + } +} + +/*! + \brief decode keyboard information + \param[in] udev: pointer to USB core instance + \param[in] uhost: pointer to USB host + \param[out] none + \retval operation status +*/ +static usbh_status usbh_hid_keybrd_decode (usb_core_driver *udev, usbh_host *uhost) +{ + usbh_hid_handler *hid = (usbh_hid_handler *)uhost->active_class->class_data; + + if (hid->len == 0U) { + return USBH_FAIL; + } + + /* fill report */ + if (usbh_hid_fifo_read (&hid->fifo, &keybd_report_data, hid->len) == hid->len) { + keybd_info.lctrl = (uint8_t)hid_item_read((hid_report_item *)&imp_0_lctrl, 0U); + keybd_info.lshift = (uint8_t)hid_item_read((hid_report_item *)&imp_0_lshift, 0U); + keybd_info.lalt = (uint8_t)hid_item_read((hid_report_item *)&imp_0_lalt, 0U); + keybd_info.lgui = (uint8_t)hid_item_read((hid_report_item *)&imp_0_lgui, 0U); + keybd_info.rctrl = (uint8_t)hid_item_read((hid_report_item *)&imp_0_rctrl, 0U); + keybd_info.rshift = (uint8_t)hid_item_read((hid_report_item *)&imp_0_rshift, 0U); + keybd_info.ralt = (uint8_t)hid_item_read((hid_report_item *)&imp_0_ralt, 0U); + keybd_info.rgui = (uint8_t)hid_item_read((hid_report_item *)&imp_0_rgui, 0U); + + for (uint8_t x = 0U; x < sizeof(keybd_info.keys); x++) { + keybd_info.keys[x] = (uint8_t)hid_item_read((hid_report_item *)&imp_0_key_array, x); + } + + return USBH_OK; + } + + return USBH_FAIL; +} diff --git a/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/host/class/hid/Source/usbh_hid_mouse.c b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/host/class/hid/Source/usbh_hid_mouse.c new file mode 100644 index 0000000000..14ebeaa747 --- /dev/null +++ b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/host/class/hid/Source/usbh_hid_mouse.c @@ -0,0 +1,216 @@ +/*! + \file usbh_hid_mouse.c + \brief USB host HID mouse driver + + \version 2020-07-17, V3.0.0, firmware for GD32F10x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "usbh_hid_mouse.h" +#include "usbh_hid_parser.h" + +hid_mouse_info mouse_info; +uint32_t mouse_report_data[1]; + +/* structures defining how to access items in a hid mouse report */ +/* access button 1 state. */ +static const hid_report_item prop_b1 = +{ + (uint8_t *)(void *)mouse_report_data + 0, /* data */ + 1, /* size */ + 0, /* shift */ + 0, /* count (only for array items) */ + 0, /* signed? */ + 0, /* min value read can return */ + 1, /* max value read can return */ + 0, /* min value device can report */ + 1, /* max value device can report */ + 1 /* resolution */ +}; + +/* access button 2 state. */ +static const hid_report_item prop_b2 = +{ + (uint8_t *)(void *)mouse_report_data + 0, /* data */ + 1, /* size */ + 1, /* shift */ + 0, /* count (only for array items) */ + 0, /* signed? */ + 0, /* min value read can return */ + 1, /* max value read can return */ + 0, /* min value device can report */ + 1, /* max value device can report */ + 1 /* resolution */ +}; + +/* access button 3 state. */ +static const hid_report_item prop_b3 = +{ + (uint8_t *)(void *)mouse_report_data + 0, /* data */ + 1, /* size */ + 2, /* shift */ + 0, /* count (only for array items) */ + 0, /* signed? */ + 0, /* min value read can return */ + 1, /* max value read can return */ + 0, /* min vale device can report */ + 1, /* max value device can report */ + 1 /* resolution */ +}; + +/* access x coordinate change. */ +static const hid_report_item prop_x = +{ + (uint8_t *)(void *)mouse_report_data + 1, /* data */ + 8, /* size */ + 0, /* shift */ + 0, /* count (only for array items) */ + 1, /* signed? */ + 0, /* min value read can return */ + 0xFFFF,/* max value read can return */ + 0, /* min vale device can report */ + 0xFFFF,/* max value device can report */ + 1 /* resolution */ +}; + +/* access y coordinate change. */ +static const hid_report_item prop_y = +{ + (uint8_t *)(void *)mouse_report_data + 2, /* data */ + 8, /* size */ + 0, /* shift */ + 0, /* count (only for array items) */ + 1, /* signed? */ + 0, /* min value read can return */ + 0xFFFF,/* max value read can return */ + 0, /* min vale device can report */ + 0xFFFF,/* max value device can report */ + 1 /* resolution */ +}; + +/* local function prototypes ('static') */ +static usbh_status usbh_hid_mouse_decode(usb_core_driver *udev, usbh_host *uhost); + +/*! + \brief initialize the mouse function + \param[in] udev: pointer to USB core instance + \param[in] uhost: pointer to USB host + \param[out] none + \retval none +*/ +usbh_status usbh_hid_mouse_init (usb_core_driver *udev, usbh_host *uhost) +{ + usbh_hid_handler *hid = (usbh_hid_handler *)uhost->active_class->class_data; + + mouse_info.x = 0U; + mouse_info.y = 0U; + mouse_info.buttons[0] = 0U; + mouse_info.buttons[1] = 0U; + mouse_info.buttons[2] = 0U; + + mouse_report_data[0] = 0U; + + if(hid->len > sizeof(mouse_report_data)) { + hid->len = sizeof(mouse_report_data); + } + + hid->pdata = (uint8_t *)(void *)mouse_report_data; + + usbh_hid_fifo_init(&hid->fifo, uhost->dev_prop.data, HID_QUEUE_SIZE * sizeof(mouse_report_data)); + + USR_MOUSE_Init(); + + return USBH_OK; +} + +/*! + \brief get mouse information + \param[in] udev: pointer to USB core instance + \param[in] uhost: pointer to USB host + \param[out] none + \retval mouse information +*/ +hid_mouse_info *usbh_hid_mouse_info_get (usb_core_driver *udev, usbh_host *uhost) +{ + if(usbh_hid_mouse_decode(udev, uhost)== USBH_OK) { + return &mouse_info; + } else { + return NULL; + } +} + +/*! + \brief decode mouse data + \param[in] udev: pointer to USB core instance + \param[in] uhost: pointer to USB host + \param[out] none + \retval none +*/ +void usbh_hid_mouse_machine (usb_core_driver *udev, usbh_host *uhost) +{ + hid_mouse_info *m_pinfo = NULL; + + m_pinfo = usbh_hid_mouse_info_get(udev, uhost); + + if (NULL != m_pinfo) { + /* handle mouse data position */ + USR_MOUSE_ProcessData(&mouse_info); + } +} + +/*! + \brief decode mouse information + \param[in] udev: pointer to USB core instance + \param[in] uhost: pointer to USB host + \param[out] none + \retval operation status +*/ +static usbh_status usbh_hid_mouse_decode(usb_core_driver *udev, usbh_host *uhost) +{ + usbh_hid_handler *hid = (usbh_hid_handler *)uhost->active_class->class_data; + + if (0U == hid->len) { + return USBH_FAIL; + } + + /* fill report */ + if (usbh_hid_fifo_read(&hid->fifo, &mouse_report_data, hid->len) == hid->len) { + /* decode report */ + mouse_info.x = (uint8_t)hid_item_read((hid_report_item *)&prop_x, 0U); + mouse_info.y = (uint8_t)hid_item_read((hid_report_item *)&prop_y, 0U); + + mouse_info.buttons[0] = (uint8_t)hid_item_read((hid_report_item *)&prop_b1, 0U); + mouse_info.buttons[1] = (uint8_t)hid_item_read((hid_report_item *)&prop_b2, 0U); + mouse_info.buttons[2] = (uint8_t)hid_item_read((hid_report_item *)&prop_b3, 0U); + + return USBH_OK; + } + + return USBH_FAIL; +} diff --git a/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/host/class/hid/Source/usbh_hid_parser.c b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/host/class/hid/Source/usbh_hid_parser.c new file mode 100644 index 0000000000..420b703ed8 --- /dev/null +++ b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/host/class/hid/Source/usbh_hid_parser.c @@ -0,0 +1,148 @@ +/*! + \file usbh_hid_parser.c + \brief USB host HID parser driver + + \version 2020-07-17, V3.0.0, firmware for GD32F10x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "usbh_hid_parser.h" + +/*! + \brief read a hid report item + \param[in] ri: pointer to report item + \param[in] ndx: report index + \param[out] none + \retval operation status (0: fail otherwise: item value) +*/ +uint32_t hid_item_read (hid_report_item *ri, uint8_t ndx) +{ + uint32_t val = 0U; + uint32_t bofs = 0U; + uint8_t *data = ri->data; + uint8_t shift = ri->shift; + + /* get the logical value of the item */ + + /* if this is an array, wee may need to offset ri->data.*/ + if (ri->count > 0U) { + /* if app tries to read outside of the array. */ + if (ri->count <= ndx) { + return(0U); + } + + /* calculate bit offset */ + bofs = ndx * ri->size; + bofs += shift; + + /* calculate byte offset + shift pair from bit offset. */ + data += bofs / 8U; + shift = (uint8_t)(bofs % 8U); + } + + /* read data bytes in little endian order */ + for (uint32_t x = 0U; x < ((ri->size & 0x7U) ? (ri->size / 8U) + 1U : (ri->size / 8U)); x++) { + val=(uint32_t)((uint32_t)(*data) << (x * 8U)); + } + + val=(val >> shift) & ((1U << ri->size) - 1U); + + if ((val < ri->logical_min) || (val > ri->logical_max)) { + return(0U); + } + + /* convert logical value to physical value */ + /* see if the number is negative or not. */ + if ((ri->sign) && (val & (1U << (ri->size - 1U)))) { + /* yes, so sign extend value to 32 bits. */ + uint32_t vs = (uint32_t)((0xffffffffU & ~((1U << (ri->size)) - 1U)) | val); + + if (1U == ri->resolution) { + return((uint32_t)vs); + } + return((uint32_t)(vs * ri->resolution)); + } else { + if (1U == ri->resolution) { + return(val); + } + + return (val * ri->resolution); + } +} + +/*! + \brief write a hid report item + \param[in] ri: pointer to report item + \param[in] value: the value to be write + \param[in] ndx: report index + \param[out] none + \retval operation status (1: fail 0: OK) +*/ +uint32_t hid_item_write(hid_report_item *ri, uint32_t value, uint8_t ndx) +{ + uint32_t mask; + uint32_t bofs; + uint8_t *data = ri->data; + uint8_t shift = ri->shift; + + if ((value < ri->physical_min) || (value > ri->physical_max)) { + return(1U); + } + + /* if this is an array, wee may need to offset ri->data.*/ + if (ri->count > 0U) { + /* if app tries to read outside of the array. */ + if (ri->count >= ndx) { + return(0U); + } + + /* calculate bit offset */ + bofs = ndx * ri->size; + bofs += shift; + + /* calculate byte offset + shift pair from bit offset. */ + data += bofs / 8U; + shift = (uint8_t)(bofs % 8U); + } + + /* convert physical value to logical value. */ + if (1U != ri->resolution) { + value = value / ri->resolution; + } + + /* write logical value to report in little endian order. */ + mask = (1U << ri->size) - 1U; + value = (value & mask) << shift; + + for (uint32_t x = 0U; x < ((ri->size & 0x7U) ? (ri->size / 8U) + 1U : (ri->size / 8U)); x++) { + *(ri->data + x) = (uint8_t)((*(ri->data+x) & ~(mask>>(x* 8U))) | ((value >> (x * 8U)) & (mask >> (x * 8U)))); + } + + return 0U; +} diff --git a/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/host/class/msc/Include/usbh_msc_bbb.h b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/host/class/msc/Include/usbh_msc_bbb.h new file mode 100644 index 0000000000..9184a816ae --- /dev/null +++ b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/host/class/msc/Include/usbh_msc_bbb.h @@ -0,0 +1,150 @@ +/*! + \file usbh_msc_bbb.h + \brief header file for usbh_msc_bbb.c + + \version 2020-07-17, V3.0.0, firmware for GD32F10x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef __USBH_MSC_BBB_H +#define __USBH_MSC_BBB_H + +#include "usbh_enum.h" +#include "msc_bbb.h" + +typedef union { + msc_bbb_cbw field; + + uint8_t CBWArray[31]; +}usbh_cbw_pkt; + +typedef union { + msc_bbb_csw field; + + uint8_t CSWArray[13]; +}usbh_csw_pkt; + +enum usbh_msc_state { + USBH_MSC_BOT_INIT_STATE = 0U, + USBH_MSC_BOT_RESET, + USBH_MSC_GET_MAX_LUN, + USBH_MSC_TEST_UNIT_READY, + USBH_MSC_READ_CAPACITY10, + USBH_MSC_MODE_SENSE6, + USBH_MSC_REQUEST_SENSE, + USBH_MSC_BOT_USB_TRANSFERS, + USBH_MSC_DEFAULT_APPLI_STATE, + USBH_MSC_CTRL_ERROR_STATE, + USBH_MSC_UNRECOVERED_STATE +}; + +typedef enum +{ + BOT_OK = 0U, + BOT_FAIL, + BOT_PHASE_ERROR, + BOT_BUSY +} bot_status; + +typedef enum +{ + BOT_CMD_IDLE = 0U, + BOT_CMD_SEND, + BOT_CMD_WAIT, +} bot_cmd_state; + +/* csw status definitions */ +typedef enum +{ + BOT_CSW_CMD_PASSED = 0U, + BOT_CSW_CMD_FAILED, + BOT_CSW_PHASE_ERROR, +} bot_csw_status; + +typedef enum +{ + BOT_SEND_CBW = 1U, + BOT_SEND_CBW_WAIT, + BOT_DATA_IN, + BOT_DATA_IN_WAIT, + BOT_DATA_OUT, + BOT_DATA_OUT_WAIT, + BOT_RECEIVE_CSW, + BOT_RECEIVE_CSW_WAIT, + BOT_ERROR_IN, + BOT_ERROR_OUT, + BOT_UNRECOVERED_ERROR +} bot_state; + +typedef struct +{ + uint8_t *pbuf; + uint32_t data[16]; + bot_state state; + bot_state prev_state; + bot_cmd_state cmd_state; + usbh_cbw_pkt cbw; + usbh_csw_pkt csw; +} bot_handle; + +#define USBH_MSC_BOT_CBW_TAG 0x20304050U + +#define USBH_MSC_CSW_MAX_LENGTH 63U + +#define USBH_MSC_SEND_CSW_DISABLE 0U +#define USBH_MSC_SEND_CSW_ENABLE 1U + +#define USBH_MSC_DIR_IN 0U +#define USBH_MSC_DIR_OUT 1U +#define USBH_MSC_BOTH_DIR 2U + +#define USBH_MSC_PAGE_LENGTH 512U + +#define CBW_CB_LENGTH 16U +#define CBW_LENGTH 10U +#define CBW_LENGTH_TEST_UNIT_READY 0U + +#define MAX_BULK_STALL_COUNT_LIMIT 0x04U /*!< If STALL is seen on Bulk + Endpoint continously, this means + that device and Host has phase error + Hence a Reset is needed */ + +/* function declarations */ +/* initialize the mass storage parameters */ +void usbh_msc_bot_init (usbh_host *uhost); +/* manage the different states of BOT transfer and updates the status to upper layer */ +usbh_status usbh_msc_bot_process (usbh_host *uhost, uint8_t lun); +/* manages the different error handling for stall */ +usbh_status usbh_msc_bot_abort (usbh_host *uhost, uint8_t direction); +/* reset MSC bot request structure */ +usbh_status usbh_msc_bot_reset (usbh_host *uhost); +/* decode the CSW received by the device and updates the same to upper layer */ +bot_csw_status usbh_msc_csw_decode (usbh_host *uhost); + +#endif /* __USBH_MSC_BBB_H */ diff --git a/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/host/class/msc/Include/usbh_msc_core.h b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/host/class/msc/Include/usbh_msc_core.h new file mode 100644 index 0000000000..f6e41ff1d1 --- /dev/null +++ b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/host/class/msc/Include/usbh_msc_core.h @@ -0,0 +1,124 @@ +/*! + \file usbh_core.h + \brief header file for the usbh_core.c + + \version 2020-07-17, V3.0.0, firmware for GD32F10x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef __USBH_MSC_CORE_H +#define __USBH_MSC_CORE_H + +#include "usb_msc.h" +#include "usbh_msc_scsi.h" +#include "usbh_msc_bbb.h" + +#define MSC_MAX_SUPPORTED_LUN 2U + +typedef enum +{ + MSC_INIT = 0U, + MSC_IDLE, + MSC_TEST_UNIT_READY, + MSC_READ_CAPACITY10, + MSC_READ_INQUIRY, + MSC_REQUEST_SENSE, + MSC_READ, + MSC_WRITE, + MSC_UNRECOVERED_ERROR, + MSC_PERIODIC_CHECK, +} msc_state; + +typedef enum +{ + MSC_OK, + MSC_NOT_READY, + MSC_ERROR, +} msc_error; + +typedef enum +{ + MSC_REQ_IDLE = 0U, + MSC_REQ_RESET, + MSC_REQ_GET_MAX_LUN, + MSC_REQ_ERROR, +} msc_req_state; + +/* Structure for LUN */ +typedef struct +{ + msc_state state; + msc_error error; + msc_scsi_sense sense; + scsi_capacity capacity; + scsi_std_inquiry_data inquiry; + usbh_status prev_ready_state; + uint8_t state_changed; +} msc_lun; + +/* structure for MSC process */ +typedef struct _msc_process +{ + uint8_t pipe_in; + uint8_t pipe_out; + uint8_t ep_in; + uint8_t ep_out; + uint16_t ep_size_in; + uint16_t ep_size_out; + uint8_t cur_lun; + uint16_t rw_lun; + uint32_t max_lun; + msc_state state; + msc_error error; + msc_req_state req_state; + msc_req_state prev_req_state; + bot_handle bot; + msc_lun unit[MSC_MAX_SUPPORTED_LUN]; + uint32_t timer; +} usbh_msc_handler; + +extern usbh_class usbh_msc; + +/* function declarations */ +/* get msc logic unit information */ +usbh_status usbh_msc_lun_info_get (usbh_host *uhost, uint8_t lun, msc_lun *info); +/* msc read interface */ +usbh_status usbh_msc_read (usbh_host *uhost, + uint8_t lun, + uint32_t address, + uint8_t *pbuf, + uint32_t length); +/* msc write interface */ +usbh_status usbh_msc_write (usbh_host *uhost, + uint8_t lun, + uint32_t address, + uint8_t *pbuf, + uint32_t length); + +#endif /* __USBH_MSC_CORE_H */ diff --git a/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/host/class/msc/Include/usbh_msc_scsi.h b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/host/class/msc/Include/usbh_msc_scsi.h new file mode 100644 index 0000000000..c38d0d74a4 --- /dev/null +++ b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/host/class/msc/Include/usbh_msc_scsi.h @@ -0,0 +1,100 @@ +/*! + \file usbh_msc_scsi.h + \brief header file for usbh_msc_scsi.c + + \version 2020-07-17, V3.0.0, firmware for GD32F10x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef __USBH_MSC_SCSI_H +#define __USBH_MSC_SCSI_H + +#include "msc_scsi.h" +#include "usbh_enum.h" + +/* capacity data */ +typedef struct +{ + uint32_t block_nbr; + uint16_t block_size; +} scsi_capacity; + +/* inquiry data */ +typedef struct +{ + uint8_t peripheral_qualifier; + uint8_t device_type; + uint8_t removable_media; + uint8_t vendor_id[9]; + uint8_t product_id[17]; + uint8_t revision_id[5]; +} scsi_std_inquiry_data; + +typedef struct +{ + uint32_t msc_capacity; + uint32_t msc_sense_key; + uint16_t msc_page_len; + uint8_t msc_write_protect; +}usbh_msc_parameter; + +#define DESC_REQUEST_SENSE 0x00U +#define ALLOCATION_LENGTH_REQUEST_SENSE 63U +#define XFER_LEN_MODE_SENSE6 63U + +#define MASK_MODE_SENSE_WRITE_PROTECT 0x80U +#define MODE_SENSE_PAGE_CONTROL_FIELD 0x00U +#define MODE_SENSE_PAGE_CODE 0x3FU +#define DISK_WRITE_PROTECTED 0x01U + +/* function declarations */ +/* send 'Inquiry' command to the device */ +usbh_status usbh_msc_scsi_inquiry (usbh_host *uhost, uint8_t lun, scsi_std_inquiry_data *inquiry); +/* send 'Test unit ready' command to the device */ +usbh_status usbh_msc_test_unitready (usbh_host *uhost, uint8_t lun); +/* send the read capacity command to the device */ +usbh_status usbh_msc_read_capacity10 (usbh_host *uhost, uint8_t lun, scsi_capacity *capacity); +/* send the mode sense6 command to the device */ +usbh_status usbh_msc_mode_sense6 (usbh_host *uhost, uint8_t lun); +/* send the Request Sense command to the device */ +usbh_status usbh_msc_request_sense (usbh_host *uhost, uint8_t lun, msc_scsi_sense *sense_data); +/* send the write10 command to the device */ +usbh_status usbh_msc_write10 (usbh_host *uhost, + uint8_t lun, + uint8_t *data_buf, + uint32_t addr, + uint32_t byte_num); +/* send the read10 command to the device */ +usbh_status usbh_msc_read10 (usbh_host *uhost, + uint8_t lun, + uint8_t *data_buf, + uint32_t addr, + uint32_t byte_num); + +#endif /* __USBH_MSC_SCSI_H */ diff --git a/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/host/class/msc/Source/usbh_msc_bbb.c b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/host/class/msc/Source/usbh_msc_bbb.c new file mode 100644 index 0000000000..d8031fab08 --- /dev/null +++ b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/host/class/msc/Source/usbh_msc_bbb.c @@ -0,0 +1,362 @@ +/*! + \file usbh_msc_bbb.c + \brief USB MSC BBB protocol related functions + + \version 2020-07-17, V3.0.0, firmware for GD32F10x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "usbh_pipe.h" +#include "usbh_msc_core.h" +#include "usbh_msc_scsi.h" +#include "usbh_msc_bbb.h" +#include "usbh_transc.h" +#include "drv_usbh_int.h" + +/*! + \brief initialize the mass storage parameters + \param[in] uhost: pointer to USB host handler + \param[out] none + \retval none +*/ +void usbh_msc_bot_init (usbh_host *uhost) +{ + usbh_msc_handler *msc = (usbh_msc_handler *)uhost->active_class->class_data; + + msc->bot.cbw.field.dCBWSignature = BBB_CBW_SIGNATURE; + msc->bot.cbw.field.dCBWTag = USBH_MSC_BOT_CBW_TAG; + msc->bot.state = BOT_SEND_CBW; + msc->bot.cmd_state = BOT_CMD_SEND; +} + +/*! + \brief manage the different states of BOT transfer and updates the status to upper layer + \param[in] uhost: pointer to usb host handler + \param[in] lun: logic unit number + \param[out] none + \retval operation status +*/ +usbh_status usbh_msc_bot_process (usbh_host *uhost, uint8_t lun) +{ + bot_csw_status csw_status = BOT_CSW_CMD_FAILED; + usbh_status status = USBH_BUSY; + usbh_status error = USBH_BUSY; + usb_urb_state urb_status = URB_IDLE; + usbh_msc_handler *msc = (usbh_msc_handler *)uhost->active_class->class_data; + + switch (msc->bot.state) { + case BOT_SEND_CBW: + msc->bot.cbw.field.bCBWLUN = lun; + msc->bot.state = BOT_SEND_CBW_WAIT; + /* send CBW */ + usbh_data_send (uhost->data, + msc->bot.cbw.CBWArray, + msc->pipe_out, + BBB_CBW_LENGTH); + break; + + case BOT_SEND_CBW_WAIT: + urb_status = usbh_urbstate_get(uhost->data, msc->pipe_out); + + if (URB_DONE == urb_status) { + if (0U != msc->bot.cbw.field.dCBWDataTransferLength) { + if (USB_TRX_IN == (msc->bot.cbw.field.bmCBWFlags & USB_TRX_MASK)) { + msc->bot.state = BOT_DATA_IN; + } else { + msc->bot.state = BOT_DATA_OUT; + } + } else { + msc->bot.state = BOT_RECEIVE_CSW; + } + + } else if (URB_NOTREADY == urb_status) { + msc->bot.state = BOT_SEND_CBW; + } else { + if (URB_STALL == urb_status) { + msc->bot.state = BOT_ERROR_OUT; + } + } + break; + + case BOT_DATA_IN: + usbh_data_recev (uhost->data, + msc->bot.pbuf, + msc->pipe_in, + msc->ep_size_in); + + msc->bot.state = BOT_DATA_IN_WAIT; + break; + + case BOT_DATA_IN_WAIT: + urb_status = usbh_urbstate_get(uhost->data, msc->pipe_in); + + /* BOT DATA IN stage */ + if (URB_DONE == urb_status) { + if (msc->bot.cbw.field.dCBWDataTransferLength > msc->ep_size_in) { + msc->bot.pbuf += msc->ep_size_in; + msc->bot.cbw.field.dCBWDataTransferLength -= msc->ep_size_in; + } else { + msc->bot.cbw.field.dCBWDataTransferLength = 0U; + } + + if (msc->bot.cbw.field.dCBWDataTransferLength > 0U) { + usbh_data_recev (uhost->data, + msc->bot.pbuf, + msc->pipe_in, + msc->ep_size_in); + } else { + msc->bot.state = BOT_RECEIVE_CSW; + } + } else if(URB_STALL == urb_status) { + /* this is data stage stall condition */ + msc->bot.state = BOT_ERROR_IN; + } else { + /* no operation */ + } + break; + + case BOT_DATA_OUT: + usbh_data_send (uhost->data, + msc->bot.pbuf, + msc->pipe_out, + msc->ep_size_out); + + msc->bot.state = BOT_DATA_OUT_WAIT; + break; + + case BOT_DATA_OUT_WAIT: + /* BOT DATA OUT stage */ + urb_status = usbh_urbstate_get(uhost->data, msc->pipe_out); + if (URB_DONE == urb_status) { + if (msc->bot.cbw.field.dCBWDataTransferLength > msc->ep_size_out) { + msc->bot.pbuf += msc->ep_size_out; + msc->bot.cbw.field.dCBWDataTransferLength -= msc->ep_size_out; + } else { + msc->bot.cbw.field.dCBWDataTransferLength = 0; /* reset this value and keep in same state */ + } + + if (msc->bot.cbw.field.dCBWDataTransferLength > 0) { + usbh_data_send (uhost->data, + msc->bot.pbuf, + msc->pipe_out, + msc->ep_size_out); + } else { + msc->bot.state = BOT_RECEIVE_CSW; + } + } else if (URB_NOTREADY == urb_status) { + msc->bot.state = BOT_DATA_OUT; + } else if (URB_STALL == urb_status) { + msc->bot.state = BOT_ERROR_OUT; + } else { + /* no operation */ + } + break; + + case BOT_RECEIVE_CSW: + /* BOT CSW stage */ + usbh_data_recev (uhost->data, + msc->bot.csw.CSWArray, + msc->pipe_in, + BBB_CSW_LENGTH); + + msc->bot.state = BOT_RECEIVE_CSW_WAIT; + break; + + case BOT_RECEIVE_CSW_WAIT: + urb_status = usbh_urbstate_get(uhost->data, msc->pipe_in); + + /* decode CSW */ + if (URB_DONE == urb_status) { + msc->bot.state = BOT_SEND_CBW; + msc->bot.cmd_state = BOT_CMD_SEND; + + csw_status = usbh_msc_csw_decode(uhost); + if (BOT_CSW_CMD_PASSED == csw_status) { + status = USBH_OK; + } else { + status = USBH_FAIL; + } + } else if (URB_STALL == urb_status) { + msc->bot.state = BOT_ERROR_IN; + } else { + /* no operation */ + } + break; + + case BOT_ERROR_IN: + error = usbh_msc_bot_abort(uhost, USBH_MSC_DIR_IN); + + if (USBH_OK == error) { + msc->bot.state = BOT_RECEIVE_CSW; + } else if (USBH_UNRECOVERED_ERROR == status) { + /* this means that there is a stall error limit, do reset recovery */ + msc->bot.state = BOT_UNRECOVERED_ERROR; + } else { + /* no operation */ + } + break; + + case BOT_ERROR_OUT: + status = usbh_msc_bot_abort (uhost, USBH_MSC_DIR_OUT); + + if (USBH_OK == status) { + uint8_t toggle = usbh_pipe_toggle_get(uhost->data, msc->pipe_out); + usbh_pipe_toggle_set(uhost->data, msc->pipe_out, 1U - toggle); + usbh_pipe_toggle_set(uhost->data, msc->pipe_in, 0U); + msc->bot.state = BOT_ERROR_IN; + } else { + if (USBH_UNRECOVERED_ERROR == status) { + msc->bot.state = BOT_UNRECOVERED_ERROR; + } + } + break; + + case BOT_UNRECOVERED_ERROR: + status = usbh_msc_bot_reset(uhost); + if (USBH_OK == status) { + msc->bot.state = BOT_SEND_CBW; + } + break; + + default: + break; + } + + return status; +} + +/*! + \brief manages the different error handling for stall + \param[in] uhost: pointer to USB host handler + \param[in] direction: data IN or OUT + \param[out] none + \retval operation status +*/ +usbh_status usbh_msc_bot_abort (usbh_host *uhost, uint8_t direction) +{ + usbh_status status = USBH_BUSY; + usbh_msc_handler *msc = (usbh_msc_handler *)uhost->active_class->class_data; + + switch (direction) { + case USBH_MSC_DIR_IN : + /* send clrfeture command on bulk IN endpoint */ + status = usbh_clrfeature(uhost, + msc->ep_in, + msc->pipe_in); + break; + + case USBH_MSC_DIR_OUT : + /*send clrfeature command on bulk OUT endpoint */ + status = usbh_clrfeature(uhost, + msc->ep_out, + msc->pipe_out); + break; + + default: + break; + } + + return status; +} + +/*! + \brief reset MSC bot transfer + \param[in] uhost: pointer to USB host handler + \param[out] none + \retval operation status +*/ +usbh_status usbh_msc_bot_reset (usbh_host *uhost) +{ + usbh_status status = USBH_BUSY; + + if (CTL_IDLE == uhost->control.ctl_state) { + uhost->control.setup.req = (usb_req) { + .bmRequestType = USB_TRX_OUT | USB_REQTYPE_CLASS | USB_RECPTYPE_ITF, + .bRequest = BBB_RESET, + .wValue = 0U, + .wIndex = 0U, + .wLength = 0U + }; + + usbh_ctlstate_config (uhost, NULL, 0U); + } + + status = usbh_ctl_handler (uhost); + + return status; +} + +/*! + \brief decode the CSW received by the device and updates the same to upper layer + \param[in] uhost: pointer to USB host + \param[out] none + \retval on success USBH_MSC_OK, on failure USBH_MSC_FAIL + \notes + Refer to USB Mass-Storage Class: BOT (www.usb.org) + 6.3.1 Valid CSW Conditions : + The host shall consider the CSW valid when: + 1. dCSWSignature is equal to 53425355h + 2. the CSW is 13 (Dh) bytes in length, + 3. dCSWTag matches the dCBWTag from the corresponding CBW. +*/ +bot_csw_status usbh_msc_csw_decode (usbh_host *uhost) +{ + bot_csw_status status = BOT_CSW_CMD_FAILED; + usbh_msc_handler *msc = (usbh_msc_handler *)uhost->active_class->class_data; + + /* checking if the transfer length is different than 13 */ + if (BBB_CSW_LENGTH != usbh_xfercount_get (uhost->data, msc->pipe_in)) { + status = BOT_CSW_PHASE_ERROR; + } else { + /* CSW length is correct */ + + /* check validity of the CSW Signature and CSWStatus */ + if (BBB_CSW_SIGNATURE == msc->bot.csw.field.dCSWSignature) { + /* check condition 1. dCSWSignature is equal to 53425355h */ + if (msc->bot.csw.field.dCSWTag == msc->bot.cbw.field.dCBWTag) { + /* check condition 3. dCSWTag matches the dCBWTag from the corresponding CBW */ + if (0U == msc->bot.csw.field.bCSWStatus) { + status = BOT_CSW_CMD_PASSED; + } else if (1U == msc->bot.csw.field.bCSWStatus) { + status = BOT_CSW_CMD_FAILED; + } else if (2U == msc->bot.csw.field.bCSWStatus) { + status = BOT_CSW_PHASE_ERROR; + } else { + /* no operation */ + } + } + } else { + /* If the CSW signature is not valid, we shall return the phase error to + upper layers for reset recovery */ + status = BOT_CSW_PHASE_ERROR; + } + } + + return status; +} diff --git a/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/host/class/msc/Source/usbh_msc_core.c b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/host/class/msc/Source/usbh_msc_core.c new file mode 100644 index 0000000000..1285b97e2b --- /dev/null +++ b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/host/class/msc/Source/usbh_msc_core.c @@ -0,0 +1,561 @@ +/*! + \file usbh_core.c + \brief USB MSC(mass storage device) class driver + + \version 2020-07-17, V3.0.0, firmware for GD32F10x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "usbh_msc_core.h" +#include "usbh_msc_scsi.h" +#include "usbh_msc_bbb.h" +#include "usbh_pipe.h" +#include "usbh_transc.h" +#include +#include + +/* local function prototypes ('static') */ +static void usbh_msc_itf_deinit (usbh_host *uhost); +static usbh_status usbh_msc_itf_init (usbh_host *uhost); +static usbh_status usbh_msc_req (usbh_host *uhost); +static usbh_status usbh_msc_handle (usbh_host *uhost); +static usbh_status usbh_msc_maxlun_get (usbh_host *uhost, uint8_t *maxlun); +static usbh_status usbh_msc_rdwr_process(usbh_host *uhost, uint8_t lun); + +usbh_class usbh_msc = +{ + USB_CLASS_MSC, + usbh_msc_itf_init, + usbh_msc_itf_deinit, + usbh_msc_req, + usbh_msc_handle, +}; + +/*! + \brief interface initialization for MSC class + \param[in] uhost: pointer to USB host + \param[out] none + \retval operation status +*/ +static usbh_status usbh_msc_itf_init (usbh_host *uhost) +{ + usbh_status status = USBH_OK; + + uint8_t interface = usbh_interface_find(&uhost->dev_prop, MSC_CLASS, USB_MSC_SUBCLASS_SCSI, MSC_PROTOCOL); + + if (0xFFU == interface) { + uhost->usr_cb->dev_not_supported(); + + status = USBH_FAIL; + } else { + static usbh_msc_handler msc_handler; + + memset((void*)&msc_handler, 0, sizeof(usbh_msc_handler)); + + uhost->active_class->class_data = (void *)&msc_handler; + + usbh_interface_select(&uhost->dev_prop, interface); + + usb_desc_ep *ep_desc = &uhost->dev_prop.cfg_desc_set.itf_desc_set[interface][0].ep_desc[0]; + + if (ep_desc->bEndpointAddress & 0x80) { + msc_handler.ep_in = ep_desc->bEndpointAddress; + msc_handler.ep_size_in = ep_desc->wMaxPacketSize; + } else { + msc_handler.ep_out = ep_desc->bEndpointAddress; + msc_handler.ep_size_out = ep_desc->wMaxPacketSize; + } + + ep_desc = &uhost->dev_prop.cfg_desc_set.itf_desc_set[interface][0].ep_desc[1]; + + if (ep_desc->bEndpointAddress & 0x80) { + msc_handler.ep_in = ep_desc->bEndpointAddress; + msc_handler.ep_size_in = ep_desc->wMaxPacketSize; + } else { + msc_handler.ep_out = ep_desc->bEndpointAddress; + msc_handler.ep_size_out = ep_desc->wMaxPacketSize; + } + + msc_handler.state = MSC_INIT; + msc_handler.error = MSC_OK; + msc_handler.req_state = MSC_REQ_IDLE; + msc_handler.pipe_out = usbh_pipe_allocate(uhost->data, msc_handler.ep_out); + msc_handler.pipe_in = usbh_pipe_allocate(uhost->data, msc_handler.ep_in); + + usbh_msc_bot_init(uhost); + + /* open the new channels */ + usbh_pipe_create (uhost->data, + &uhost->dev_prop, + msc_handler.pipe_out, + USB_EPTYPE_BULK, + msc_handler.ep_size_out); + + usbh_pipe_create (uhost->data, + &uhost->dev_prop, + msc_handler.pipe_in, + USB_EPTYPE_BULK, + msc_handler.ep_size_in); + + usbh_pipe_toggle_set (uhost->data, msc_handler.pipe_out, 0U); + usbh_pipe_toggle_set (uhost->data, msc_handler.pipe_in, 0U); + } + + return status; +} + +/*! + \brief deinitialize interface by freeing host channels allocated to interface + \param[in] uhost: pointer to USB host + \param[out] none + \retval operation status +*/ +void usbh_msc_itf_deinit (usbh_host *uhost) +{ + usbh_msc_handler *msc = (usbh_msc_handler *)uhost->active_class->class_data; + + if (msc->pipe_out) { + usb_pipe_halt (uhost->data, msc->pipe_out); + usbh_pipe_free (uhost->data, msc->pipe_out); + + msc->pipe_out = 0U; + } + + if (msc->pipe_in) { + usb_pipe_halt (uhost->data, msc->pipe_in); + usbh_pipe_free (uhost->data, msc->pipe_in); + + msc->pipe_in = 0U; + } +} + +/*! + \brief initialize the MSC state machine + \param[in] uhost: pointer to USB host + \param[out] none + \retval operation status +*/ +static usbh_status usbh_msc_req (usbh_host *uhost) +{ + usbh_status status = USBH_BUSY; + usbh_msc_handler *msc = (usbh_msc_handler *)uhost->active_class->class_data; + + switch (msc->req_state) { + case MSC_REQ_IDLE: + case MSC_REQ_GET_MAX_LUN: + /* issue Get_MaxLun request */ + status = usbh_msc_maxlun_get (uhost, (uint8_t *)&msc->max_lun); + + if (USBH_OK == status) { + msc->max_lun = ((uint8_t)msc->max_lun > MSC_MAX_SUPPORTED_LUN) ? MSC_MAX_SUPPORTED_LUN : (uint8_t)msc->max_lun + 1U; + + for (uint8_t i = 0U; i < msc->max_lun; i++) { + msc->unit[i].prev_ready_state = USBH_FAIL; + msc->unit[i].state_changed = 0U; + } + } else { + if (USBH_NOT_SUPPORTED == status) { + msc->max_lun = 0U; + status = USBH_OK; + } + } + break; + + case MSC_REQ_ERROR: + /* issue clearfeature request */ + if (USBH_OK == usbh_clrfeature(uhost, 0x00U, uhost->control.pipe_out_num)) { + msc->req_state = msc->prev_req_state; + } + break; + + default: + break; + } + + return status; +} + +/*! + \brief MSC state machine handler + \param[in] uhost: pointer to USB host + \param[out] none + \retval operation status +*/ +static usbh_status usbh_msc_handle (usbh_host *uhost) +{ + usbh_status status = USBH_BUSY; + uint8_t scsi_status = USBH_BUSY; + uint8_t ready_status = USBH_BUSY; + usbh_msc_handler *msc = (usbh_msc_handler *)uhost->active_class->class_data; + + + switch (msc->state) { + case MSC_INIT: + if (msc->cur_lun < msc->max_lun) { + msc->unit[msc->cur_lun].error = MSC_NOT_READY; + + switch (msc->unit[msc->cur_lun].state) { + case MSC_INIT: + msc->unit[msc->cur_lun].state = MSC_READ_INQUIRY; + msc->timer = uhost->control.timer; + break; + + case MSC_READ_INQUIRY: + scsi_status = usbh_msc_scsi_inquiry(uhost, msc->cur_lun, &msc->unit[msc->cur_lun].inquiry); + + if (USBH_OK == scsi_status) { + msc->unit[msc->cur_lun].state = MSC_TEST_UNIT_READY; + } else if (scsi_status == USBH_FAIL) { + msc->unit[msc->cur_lun].state = MSC_REQUEST_SENSE; + } else { + if (scsi_status == USBH_UNRECOVERED_ERROR) { + msc->unit[msc->cur_lun].state = MSC_IDLE; + msc->unit[msc->cur_lun].error = MSC_ERROR; + } + } + break; + + case MSC_TEST_UNIT_READY: + /* issue SCSI command TestUnitReady */ + ready_status = usbh_msc_test_unitready(uhost, msc->cur_lun); + + if (USBH_OK == ready_status) { + if (USBH_OK != msc->unit[msc->cur_lun].prev_ready_state) { + msc->unit[msc->cur_lun].state_changed = 1U; + } else { + msc->unit[msc->cur_lun].state_changed = 0U; + } + + msc->unit[msc->cur_lun].state = MSC_READ_CAPACITY10; + msc->unit[msc->cur_lun].error = MSC_OK; + msc->unit[msc->cur_lun].prev_ready_state = USBH_OK; + } else if (USBH_FAIL == ready_status) { + if (USBH_FAIL != msc->unit[msc->cur_lun].prev_ready_state) { + msc->unit[msc->cur_lun].state_changed = 1U; + } else { + msc->unit[msc->cur_lun].state_changed = 0U; + } + + msc->unit[msc->cur_lun].state = MSC_REQUEST_SENSE; + msc->unit[msc->cur_lun].error = MSC_NOT_READY; + msc->unit[msc->cur_lun].prev_ready_state = USBH_FAIL; + } else { + if (USBH_UNRECOVERED_ERROR == ready_status) { + msc->unit[msc->cur_lun].state = MSC_IDLE; + msc->unit[msc->cur_lun].error = MSC_ERROR; + } + } + break; + + case MSC_READ_CAPACITY10: + /* issue READ_CAPACITY10 SCSI command */ + scsi_status = usbh_msc_read_capacity10(uhost, msc->cur_lun, &msc->unit[msc->cur_lun].capacity); + + if (USBH_OK == scsi_status) { + if (1U == msc->unit[msc->cur_lun].state_changed) { + } + msc->unit[msc->cur_lun].state = MSC_IDLE; + msc->unit[msc->cur_lun].error = MSC_OK; + msc->cur_lun ++; + } else if (USBH_FAIL == scsi_status) { + msc->unit[msc->cur_lun].state = MSC_REQUEST_SENSE; + } else { + if (USBH_UNRECOVERED_ERROR == scsi_status) { + msc->unit[msc->cur_lun].state = MSC_IDLE; + msc->unit[msc->cur_lun].error = MSC_ERROR; + } + } + break; + + case MSC_REQUEST_SENSE: + /* issue RequestSense SCSI command for receive error code */ + scsi_status = usbh_msc_request_sense (uhost, msc->cur_lun, &msc->unit[msc->cur_lun].sense); + if (USBH_OK == scsi_status) { + if ((msc->unit[msc->cur_lun].sense.SenseKey == UNIT_ATTENTION) || (msc->unit[msc->cur_lun].sense.SenseKey == NOT_READY)) { + if (((uhost->control.timer > msc->timer) && ((uhost->control.timer - msc->timer) < 10000U)) \ + || ((uhost->control.timer < msc->timer) && ((uhost->control.timer + 0x3FFFU - msc->timer) < 10000U))){ + msc->unit[msc->cur_lun].state = MSC_TEST_UNIT_READY; + break; + } + } + + msc->unit[msc->cur_lun].state = MSC_IDLE; + msc->cur_lun++; + } else if (USBH_FAIL == scsi_status) { + msc->unit[msc->cur_lun].state = MSC_UNRECOVERED_ERROR; + } else { + if (MSC_UNRECOVERED_ERROR == scsi_status) { + msc->unit[msc->cur_lun].state = MSC_IDLE; + msc->unit[msc->cur_lun].error = MSC_ERROR; + } + } + break; + + case MSC_UNRECOVERED_ERROR: + msc->cur_lun ++; + break; + + default: + break; + } + } else { + msc->cur_lun = 0U; + msc->state = MSC_IDLE; + } + break; + + case MSC_IDLE: + uhost->usr_cb->dev_user_app(); + status = USBH_OK; + break; + + default: + break; + } + + return status; +} + +/*! + \brief get max lun of the mass storage device + \param[in] uhost: pointer to USB host + \param[in] maxlun: pointer to max lun + \param[out] none + \retval operation status +*/ +static usbh_status usbh_msc_maxlun_get (usbh_host *uhost, uint8_t *maxlun) +{ + usbh_status status = USBH_BUSY; + + if (uhost->control.ctl_state == CTL_IDLE) { + uhost->control.setup.req = (usb_req) { + .bmRequestType = USB_TRX_IN | USB_REQTYPE_CLASS | USB_RECPTYPE_ITF, + .bRequest = BBB_GET_MAX_LUN, + .wValue = 0U, + .wIndex = 0U, + .wLength = 1U + }; + + usbh_ctlstate_config (uhost, maxlun, 1U); + } + + status = usbh_ctl_handler (uhost); + + return status; +} + +/*! + \brief get max lun of the mass storage device + \param[in] uhost: pointer to USB host + \param[in] lun: logic unit number + \param[out] none + \retval operation status +*/ +static usbh_status usbh_msc_rdwr_process(usbh_host *uhost, uint8_t lun) +{ + usbh_status error = USBH_BUSY; + usbh_status scsi_status = USBH_BUSY; + usbh_msc_handler *msc = (usbh_msc_handler *)uhost->active_class->class_data; + + /* switch MSC req state machine */ + switch (msc->unit[lun].state) { + case MSC_READ: + scsi_status = usbh_msc_read10(uhost, lun, NULL, 0U, 0U); + + if (USBH_OK == scsi_status) { + msc->unit[lun].state = MSC_IDLE; + error = USBH_OK; + } else if (USBH_FAIL == scsi_status) { + msc->unit[lun].state = MSC_REQUEST_SENSE; + } else { + if (USBH_UNRECOVERED_ERROR == scsi_status) { + msc->unit[lun].state = MSC_UNRECOVERED_ERROR; + error = USBH_FAIL; + } + } + break; + + case MSC_WRITE: + scsi_status = usbh_msc_write10(uhost, lun, NULL, 0U, 0U); + + if (USBH_OK == scsi_status) { + msc->unit[lun].state = MSC_IDLE; + error = USBH_OK; + } else if(USBH_FAIL == scsi_status) { + msc->unit[lun].state = MSC_REQUEST_SENSE; + } else { + if (USBH_UNRECOVERED_ERROR == scsi_status) { + msc->unit[lun].state = MSC_UNRECOVERED_ERROR; + error = USBH_FAIL; + } + } + break; + + case MSC_REQUEST_SENSE: + scsi_status = usbh_msc_request_sense (uhost, lun, &msc->unit[lun].sense); + + if (USBH_OK == scsi_status) { + msc->unit[lun].state = MSC_IDLE; + msc->unit[lun].error = MSC_ERROR; + + error = USBH_FAIL; + } + + if (USBH_FAIL == scsi_status) { + } else { + if (USBH_UNRECOVERED_ERROR == scsi_status) { + msc->unit[lun].state = MSC_UNRECOVERED_ERROR; + error = USBH_FAIL; + } + } + break; + + default: + break; + } + + return error; +} + +/*! + \brief get lun information + \param[in] uhost: pointer to USB host + \param[in] lun: logic unit number + \param[in] info: pointer to lun information + \param[out] none + \retval operation status +*/ +usbh_status usbh_msc_lun_info_get (usbh_host *uhost, uint8_t lun, msc_lun *info) +{ + usbh_msc_handler *msc = (usbh_msc_handler *)uhost->active_class->class_data; + + if (HOST_CLASS_HANDLER == uhost->cur_state) { + memcpy(info, &msc->unit[lun], sizeof(msc_lun)); + + return USBH_OK; + } else { + return USBH_FAIL; + } +} + +/*! + \brief handle MSC read operation + \param[in] uhost: pointer to USB host + \param[in] lun: logic unit number + \param[in] address: data address + \param[in] pbuf: pointer to data buffer + \param[in] length: buffer length + \param[out] none + \retval operation status +*/ +usbh_status usbh_msc_read (usbh_host *uhost, + uint8_t lun, + uint32_t address, + uint8_t *pbuf, + uint32_t length) +{ + uint32_t timeout = 0U; + usbh_msc_handler *msc = (usbh_msc_handler *)uhost->active_class->class_data; + usb_core_driver *udev = (usb_core_driver *)uhost->data; + + if ((0U == udev->host.connect_status) || + (HOST_CLASS_HANDLER != uhost->cur_state) || + (MSC_IDLE != msc->unit[lun].state)) { + return USBH_FAIL; + } + + msc->state = MSC_READ; + msc->unit[lun].state = MSC_READ; + msc->rw_lun = lun; + + usbh_msc_read10(uhost, lun, pbuf, address, length); + + timeout = uhost->control.timer; + + while (USBH_BUSY == usbh_msc_rdwr_process(uhost, lun)) { + if (((uhost->control.timer > timeout) && ((uhost->control.timer - timeout) > (1000U * length))) \ + || ((uhost->control.timer < timeout) && ((uhost->control.timer + 0x3FFFU - timeout) > (1000U * length))) \ + || (0U == udev->host.connect_status)){ + msc->state = MSC_IDLE; + return USBH_FAIL; + } + } + + msc->state = MSC_IDLE; + + return USBH_OK; +} + +/*! + \brief handle MSC write operation + \param[in] uhost: pointer to USB host + \param[in] lun: logic unit number + \param[in] address: data address + \param[in] pbuf: pointer to data buffer + \param[in] length: buffer length + \param[out] none + \retval operation status +*/ +usbh_status usbh_msc_write (usbh_host *uhost, + uint8_t lun, + uint32_t address, + uint8_t *pbuf, + uint32_t length) +{ + uint32_t timeout = 0U; + usb_core_driver *udev = (usb_core_driver *)uhost->data; + usbh_msc_handler *msc = (usbh_msc_handler *)uhost->active_class->class_data; + + if ((0U == udev->host.connect_status) || + (HOST_CLASS_HANDLER != uhost->cur_state) || + (MSC_IDLE != msc->unit[lun].state)) { + return USBH_FAIL; + } + + msc->state = MSC_WRITE; + msc->unit[lun].state = MSC_WRITE; + msc->rw_lun = lun; + + usbh_msc_write10(uhost, lun, pbuf, address, length); + + timeout = uhost->control.timer; + + while (USBH_BUSY == usbh_msc_rdwr_process(uhost, lun)) { + if (((uhost->control.timer > timeout) && ((uhost->control.timer - timeout) > (1000U * length))) \ + || ((uhost->control.timer < timeout) && ((uhost->control.timer + 0x3FFFU - timeout) > (1000U * length))) \ + || (0U == udev->host.connect_status)){ + msc->state = MSC_IDLE; + return USBH_FAIL; + } + } + + msc->state = MSC_IDLE; + + return USBH_OK; +} diff --git a/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/host/class/msc/Source/usbh_msc_fatfs.c b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/host/class/msc/Source/usbh_msc_fatfs.c new file mode 100644 index 0000000000..d54c5f7cc1 --- /dev/null +++ b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/host/class/msc/Source/usbh_msc_fatfs.c @@ -0,0 +1,233 @@ +/*! + \file usbh_msc_fatfs.c + \brief USB MSC host FATFS related functions + + \version 2020-07-17, V3.0.0, firmware for GD32F10x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "usb_conf.h" +#include "diskio.h" +#include "usbh_msc_core.h" + +static volatile DSTATUS state = STA_NOINIT; /* disk status */ + +extern usbh_host usb_host; + +/*! + \brief initialize the disk drive + \param[in] drv: physical drive number (0) + \param[out] none + \retval operation status +*/ +DSTATUS disk_initialize (BYTE drv) +{ + usb_core_driver *udev = (usb_core_driver *)usb_host.data; + + if (udev->host.connect_status) { + state &= ~STA_NOINIT; + } + + return state; +} + +/*! + \brief get disk status + \param[in] drv: physical drive number (0) + \param[out] none + \retval operation status +*/ +DSTATUS disk_status (BYTE drv) +{ + if (drv) { + return STA_NOINIT; /* supports only single drive */ + } + + return state; +} + +/*! + \brief read sectors + \param[in] drv: physical drive number (0) + \param[in] buff: pointer to the data buffer to store read data + \param[in] sector: start sector number (LBA) + \param[in] count: sector count (1..255) + \param[out] none + \retval operation status +*/ +DRESULT disk_read (BYTE drv, BYTE *buff, DWORD sector, UINT count) +{ + BYTE status = USBH_OK; + usb_core_driver *udev = (usb_core_driver *)usb_host.data; + + if (drv || (!count)) { + return RES_PARERR; + } + + if (state & STA_NOINIT) { + return RES_NOTRDY; + } + + if (udev->host.connect_status) { + do { + status = usbh_msc_read (&usb_host, drv, sector, buff, count); + + if (!udev->host.connect_status) { + return RES_ERROR; + } + } while(status == USBH_BUSY); + } + + if (status == USBH_OK) { + return RES_OK; + } + + return RES_ERROR; +} + +#if _READONLY == 0U + +/*! + \brief write sectors + \param[in] drv: physical drive number (0) + \param[in] buff: pointer to the data buffer to store read data + \param[in] sector: start sector number (LBA) + \param[in] count: sector count (1..255) + \param[out] none + \retval operation status +*/ +DRESULT disk_write (BYTE drv, const BYTE *buff, DWORD sector, UINT count) +{ + BYTE status = USBH_OK; + usb_core_driver *udev = (usb_core_driver *)usb_host.data; + + if ((!count) || drv) { + return RES_PARERR; + } + + if (state & STA_NOINIT) { + return RES_NOTRDY; + } + + if (state & STA_PROTECT) { + return RES_WRPRT; + } + + if (udev->host.connect_status) { + do { + status = usbh_msc_write (&usb_host, drv, sector, (BYTE*)buff, count); + + if (!udev->host.connect_status) { + return RES_ERROR; + } + } while(status == USBH_BUSY); + } + + if (status == USBH_OK) { + return RES_OK; + } + + return RES_ERROR; +} + +#endif /* _READONLY == 0 */ + +/*! + \brief I/O control function + \param[in] drv: physical drive number (0) + \param[in] ctrl: control code + \param[in] buff: pointer to the data buffer to store read data + \param[out] none + \retval operation status +*/ +DRESULT disk_ioctl (BYTE drv, BYTE ctrl, void *buff) +{ + DRESULT res = RES_OK; + msc_lun info; + + if (drv) { + return RES_PARERR; + } + + res = RES_ERROR; + + if (state & STA_NOINIT) { + return RES_NOTRDY; + } + + switch (ctrl) { + /* make sure that no pending write process */ + case CTRL_SYNC: + res = RES_OK; + break; + + /* get number of sectors on the disk (dword) */ + case GET_SECTOR_COUNT: + if (USBH_OK == usbh_msc_lun_info_get(&usb_host, drv, &info)) { + *(DWORD*)buff = (DWORD)info.capacity.block_nbr; + res = RES_OK; + } + break; + + /* get r/w sector size (word) */ + case GET_SECTOR_SIZE: + if (USBH_OK == usbh_msc_lun_info_get(&usb_host, drv, &info)) { + *(WORD*)buff = (DWORD)info.capacity.block_size; + res = RES_OK; + } + break; + + /* get erase block size in unit of sector (dword) */ + case GET_BLOCK_SIZE: + *(DWORD*)buff = 512; + break; + + default: + res = RES_PARERR; + break; + } + + return res; +} + +/*! + \brief get fat time + \param[in] none + \param[out] none + \retval time value +*/ +DWORD get_fattime(void) { + + return ((DWORD)(2019U - 1980U) << 25U) /* year 2019 */ + | ((DWORD)1U << 21U) /* month 1 */ + | ((DWORD)1U << 16U) /* day 1 */ + | ((DWORD)0U << 11U) /* hour 0 */ + | ((DWORD)0U << 5U) /* min 0 */ + | ((DWORD)0U >> 1U); /* sec 0 */ +} diff --git a/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/host/class/msc/Source/usbh_msc_scsi.c b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/host/class/msc/Source/usbh_msc_scsi.c new file mode 100644 index 0000000000..8120a9bdde --- /dev/null +++ b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/host/class/msc/Source/usbh_msc_scsi.c @@ -0,0 +1,400 @@ +/*! + \file usbh_msc_scsi.c + \brief USB MSC SCSI commands implemention + + \version 2020-07-17, V3.0.0, firmware for GD32F10x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "usbh_msc_core.h" +#include "usbh_msc_scsi.h" +#include "usbh_msc_bbb.h" + +#include + +/*! + \brief send 'Inquiry' command to the device + \param[in] uhost: pointer to USB host handler + \param[in] lun: logic unit number + \param[in] inquiry: pointer to the inquiry structure + \param[out] none + \retval operation status +*/ +usbh_status usbh_msc_scsi_inquiry (usbh_host *uhost, uint8_t lun, scsi_std_inquiry_data *inquiry) +{ + usbh_status error = USBH_FAIL; + usbh_msc_handler *msc = (usbh_msc_handler *)uhost->active_class->class_data; + + switch (msc->bot.cmd_state) { + case BOT_CMD_SEND: + /* prepare the cbw and relevant field*/ + msc->bot.cbw.field.dCBWDataTransferLength = STANDARD_INQUIRY_DATA_LEN; + msc->bot.cbw.field.bmCBWFlags = USB_TRX_IN; + msc->bot.cbw.field.bCBWCBLength = CBW_LENGTH; + + memset(msc->bot.cbw.field.CBWCB, 0U, CBW_LENGTH); + + msc->bot.cbw.field.CBWCB[0] = SCSI_INQUIRY; + msc->bot.cbw.field.CBWCB[1] = (lun << 5U); + msc->bot.cbw.field.CBWCB[4] = 0x24U; + + msc->bot.state = BOT_SEND_CBW; + msc->bot.cmd_state = BOT_CMD_WAIT; + msc->bot.pbuf = (uint8_t *)(void *)msc->bot.data; + error = USBH_BUSY; + break; + + case BOT_CMD_WAIT: + error = usbh_msc_bot_process(uhost, lun); + + if (USBH_OK == error) { + memset(inquiry, 0U, sizeof(scsi_std_inquiry_data)); + + /* assign inquiry data */ + inquiry->device_type = msc->bot.pbuf[0] & 0x1FU; + inquiry->peripheral_qualifier = msc->bot.pbuf[0] >> 5U; + + if (0x80U == ((uint32_t)msc->bot.pbuf[1] & 0x80U)) { + inquiry->removable_media = 1U; + } else { + inquiry->removable_media = 0U; + } + + memcpy (inquiry->vendor_id, &msc->bot.pbuf[8], 8U); + memcpy (inquiry->product_id, &msc->bot.pbuf[16], 16U); + memcpy (inquiry->revision_id, &msc->bot.pbuf[32], 4U); + } + break; + + default: + break; + } + + return error; +} + +/*! + \brief send 'Test unit ready' command to the device + \param[in] uhost: pointer to USB host handler + \param[in] lun: logic unit number + \param[out] none + \retval operation status +*/ +usbh_status usbh_msc_test_unitready (usbh_host *uhost, uint8_t lun) +{ + usbh_status status = USBH_FAIL; + usbh_msc_handler *msc = (usbh_msc_handler *)uhost->active_class->class_data; + + + switch (msc->bot.cmd_state) { + case BOT_CMD_SEND: + /* prepare the CBW and relevant field */ + msc->bot.cbw.field.dCBWDataTransferLength = CBW_LENGTH_TEST_UNIT_READY; + msc->bot.cbw.field.bmCBWFlags = USB_TRX_OUT; + msc->bot.cbw.field.bCBWCBLength = CBW_LENGTH; + + memset(msc->bot.cbw.field.CBWCB, 0U, CBW_CB_LENGTH); + + msc->bot.cbw.field.CBWCB[0] = SCSI_TEST_UNIT_READY; + msc->bot.state = BOT_SEND_CBW; + msc->bot.cmd_state = BOT_CMD_WAIT; + + status = USBH_BUSY; + break; + + case BOT_CMD_WAIT: + status = usbh_msc_bot_process(uhost, lun); + break; + + default: + break; + } + + return status; +} + +/*! + \brief send the read capacity command to the device + \param[in] uhost: pointer to USB host handler + \param[in] lun: logic unit number + \param[in] capacity: pointer to SCSI capacity + \param[out] none + \retval operation status +*/ +usbh_status usbh_msc_read_capacity10 (usbh_host *uhost, uint8_t lun, scsi_capacity *capacity) +{ + usbh_status status = USBH_FAIL; + usbh_msc_handler *msc = (usbh_msc_handler *)uhost->active_class->class_data; + + switch (msc->bot.cmd_state) { + case BOT_CMD_SEND: + /* prepare the CBW and relevant field */ + msc->bot.cbw.field.dCBWDataTransferLength = READ_CAPACITY10_DATA_LEN; + msc->bot.cbw.field.bmCBWFlags = USB_TRX_IN; + msc->bot.cbw.field.bCBWCBLength = CBW_LENGTH; + + memset(msc->bot.cbw.field.CBWCB, 0U, CBW_CB_LENGTH); + + msc->bot.cbw.field.CBWCB[0] = SCSI_READ_CAPACITY10; + msc->bot.state = BOT_SEND_CBW; + msc->bot.cmd_state = BOT_CMD_WAIT; + msc->bot.pbuf = (uint8_t *)(void *)msc->bot.data; + + status = USBH_BUSY; + break; + + case BOT_CMD_WAIT: + status = usbh_msc_bot_process(uhost, lun); + + if (USBH_OK == status) { + capacity->block_nbr = msc->bot.pbuf[3] | \ + ((uint32_t)msc->bot.pbuf[2] << 8U) | \ + ((uint32_t)msc->bot.pbuf[1] << 16U) | \ + ((uint32_t)msc->bot.pbuf[0] << 24U); + + capacity->block_size = (uint16_t)(msc->bot.pbuf[7] | ((uint32_t)msc->bot.pbuf[6] << 8U)); + } + break; + + default: + break; + } + + return status; +} + +/*! + \brief send the mode sense6 command to the device + \param[in] uhost: pointer to USB host handler + \param[in] lun: logic unit number + \param[out] none + \retval operation status +*/ +usbh_status usbh_msc_mode_sense6 (usbh_host *uhost, uint8_t lun) +{ + usbh_status status = USBH_FAIL; + usbh_msc_handler *msc = (usbh_msc_handler *)uhost->active_class->class_data; + + + switch (msc->bot.cmd_state) { + case BOT_CMD_SEND: + /* prepare the CBW and relevant field */ + msc->bot.cbw.field.dCBWDataTransferLength = XFER_LEN_MODE_SENSE6; + msc->bot.cbw.field.bmCBWFlags = USB_TRX_IN; + msc->bot.cbw.field.bCBWCBLength = CBW_LENGTH; + + memset(msc->bot.cbw.field.CBWCB, 0U, CBW_CB_LENGTH); + + msc->bot.cbw.field.CBWCB[0] = SCSI_MODE_SENSE6; + msc->bot.cbw.field.CBWCB[2] = MODE_SENSE_PAGE_CONTROL_FIELD | MODE_SENSE_PAGE_CODE; + msc->bot.cbw.field.CBWCB[4] = XFER_LEN_MODE_SENSE6; + msc->bot.state = BOT_SEND_CBW; + msc->bot.cmd_state = BOT_CMD_WAIT; + msc->bot.pbuf = (uint8_t *)(void *)msc->bot.data; + + status = USBH_BUSY; + break; + + case BOT_CMD_WAIT: + status = usbh_msc_bot_process(uhost, lun); + + if (USBH_OK == status) { + if (msc->bot.data[2] & MASK_MODE_SENSE_WRITE_PROTECT) { + + } else { + + } + } + break; + + default: + break; + } + + + return status; +} + +/*! + \brief send the Request Sense command to the device + \param[in] uhost: pointer to USB host handler + \param[in] lun: logic unit number + \param[in] sense_data: pointer to sense data + \param[out] none + \retval operation status +*/ +usbh_status usbh_msc_request_sense (usbh_host *uhost, uint8_t lun, msc_scsi_sense *sense_data) +{ + usbh_status status = USBH_FAIL; + usbh_msc_handler *msc = (usbh_msc_handler *)uhost->active_class->class_data; + + switch (msc->bot.cmd_state) { + case BOT_CMD_SEND: + /* prepare the cbw and relevant field */ + msc->bot.cbw.field.dCBWDataTransferLength = ALLOCATION_LENGTH_REQUEST_SENSE; + msc->bot.cbw.field.bmCBWFlags = USB_TRX_IN; + msc->bot.cbw.field.bCBWCBLength = CBW_LENGTH; + + memset(msc->bot.cbw.field.CBWCB, 0U, CBW_CB_LENGTH); + + msc->bot.cbw.field.CBWCB[0] = SCSI_REQUEST_SENSE; + msc->bot.cbw.field.CBWCB[1] = (lun << 5U); + msc->bot.cbw.field.CBWCB[4] = ALLOCATION_LENGTH_REQUEST_SENSE; + + msc->bot.state = BOT_SEND_CBW; + msc->bot.cmd_state = BOT_CMD_WAIT; + msc->bot.pbuf = (uint8_t *)(void *)msc->bot.data; + + status = USBH_BUSY; + break; + + case BOT_CMD_WAIT: + status = usbh_msc_bot_process(uhost, lun); + + if (status == USBH_OK) { + /* get sense data */ + sense_data->SenseKey = msc->bot.pbuf[2] & 0x0FU; + sense_data->ASC = msc->bot.pbuf[12]; + sense_data->ASCQ = msc->bot.pbuf[13]; + } + break; + + default: + break; + } + + return status; +} + +/*! + \brief send the write10 command to the device + \param[in] uhost: pointer to USB host handler + \param[in] lun: logic unit number + \param[in] data_buf: data buffer contains the data to write + \param[in] addr: address to which the data will be written + \param[in] sector_num: number of sector to be written + \param[out] none + \retval operation status +*/ +usbh_status usbh_msc_write10 (usbh_host *uhost, uint8_t lun, uint8_t *data_buf, uint32_t addr, uint32_t sector_num) +{ + usbh_status status = USBH_FAIL; + usbh_msc_handler *msc = (usbh_msc_handler *)uhost->active_class->class_data; + + switch (msc->bot.cmd_state) { + case BOT_CMD_SEND: + msc->bot.cbw.field.dCBWDataTransferLength = sector_num * msc->unit[lun].capacity.block_size; + msc->bot.cbw.field.bmCBWFlags = USB_TRX_OUT; + msc->bot.cbw.field.bCBWCBLength = CBW_LENGTH; + + memset(msc->bot.cbw.field.CBWCB, 0U, CBW_CB_LENGTH); + + msc->bot.cbw.field.CBWCB[0] = SCSI_WRITE10; + + /* logical block address */ + msc->bot.cbw.field.CBWCB[2] = (((uint8_t*)&addr)[3]); + msc->bot.cbw.field.CBWCB[3] = (((uint8_t*)&addr)[2]); + msc->bot.cbw.field.CBWCB[4] = (((uint8_t*)&addr)[1]); + msc->bot.cbw.field.CBWCB[5] = (((uint8_t*)&addr)[0]); + + /* transfer length */ + msc->bot.cbw.field.CBWCB[7] = (((uint8_t *)§or_num)[1]); + msc->bot.cbw.field.CBWCB[8] = (((uint8_t *)§or_num)[0]); + + msc->bot.state = BOT_SEND_CBW; + msc->bot.cmd_state = BOT_CMD_WAIT; + msc->bot.pbuf = data_buf; + + status = USBH_BUSY; + break; + + case BOT_CMD_WAIT: + status = usbh_msc_bot_process(uhost, lun); + break; + + default: + break; + } + + return status; +} + +/*! + \brief send the read10 command to the device + \param[in] uhost: pointer to USB host handler + \param[in] lun: logic unit number + \param[in] data_buf: data buffer contains the data to write + \param[in] addr: address to which the data will be read + \param[in] sector_num: number of sector to be read + \param[out] none + \retval operation status +*/ +usbh_status usbh_msc_read10 (usbh_host *uhost, uint8_t lun, uint8_t *data_buf, uint32_t addr, uint32_t sector_num) +{ + usbh_status status = USBH_FAIL; + usbh_msc_handler *msc = (usbh_msc_handler *)uhost->active_class->class_data; + + switch (msc->bot.cmd_state) { + case BOT_CMD_SEND: + /* prepare the CBW and relevant field */ + msc->bot.cbw.field.dCBWDataTransferLength = sector_num * msc->unit[lun].capacity.block_size; + msc->bot.cbw.field.bmCBWFlags = USB_TRX_IN; + msc->bot.cbw.field.bCBWCBLength = CBW_LENGTH; + + memset(msc->bot.cbw.field.CBWCB, 0U, CBW_CB_LENGTH); + + msc->bot.cbw.field.CBWCB[0] = SCSI_READ10; + + /* logical block address */ + msc->bot.cbw.field.CBWCB[2] = (((uint8_t*)&addr)[3]); + msc->bot.cbw.field.CBWCB[3] = (((uint8_t*)&addr)[2]); + msc->bot.cbw.field.CBWCB[4] = (((uint8_t*)&addr)[1]); + msc->bot.cbw.field.CBWCB[5] = (((uint8_t*)&addr)[0]); + + /* transfer length */ + msc->bot.cbw.field.CBWCB[7] = (((uint8_t *)§or_num)[1]); + msc->bot.cbw.field.CBWCB[8] = (((uint8_t *)§or_num)[0]); + + msc->bot.state = BOT_SEND_CBW; + msc->bot.cmd_state = BOT_CMD_WAIT; + msc->bot.pbuf = data_buf; + + status = USBH_BUSY; + break; + + case BOT_CMD_WAIT: + status = usbh_msc_bot_process(uhost, lun); + break; + + default: + break; + } + + return status; +} diff --git a/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/host/core/Include/usbh_core.h b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/host/core/Include/usbh_core.h new file mode 100644 index 0000000000..689fe0d29f --- /dev/null +++ b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/host/core/Include/usbh_core.h @@ -0,0 +1,274 @@ +/*! + \file usbh_core.h + \brief USB host core state machine header file + + \version 2020-07-17, V3.0.0, firmware for GD32F10x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef __USBH_CORE_H +#define __USBH_CORE_H + +#include "usbh_conf.h" +#include "drv_usb_host.h" + +#define MSC_CLASS 0x08U +#define HID_CLASS 0x03U +#define MSC_PROTOCOL 0x50U +#define CBI_PROTOCOL 0x01U + +#define USBH_MAX_ERROR_COUNT 3U + +#define USBH_DEV_ADDR_DEFAULT 0U +#define USBH_DEV_ADDR 1U + +typedef enum +{ + USBH_OK = 0U, + USBH_BUSY, + USBH_FAIL, + USBH_NOT_SUPPORTED, + USBH_UNRECOVERED_ERROR, + USBH_SPEED_UNKNOWN_ERROR, + USBH_APPLY_DEINIT +} usbh_status; + +/* USB host global operation state */ +typedef enum +{ + HOST_DEFAULT = 0U, + HOST_DETECT_DEV_SPEED, + HOST_DEV_ATTACHED, + HOST_DEV_DETACHED, + HOST_ENUM, + HOST_SET_WAKEUP_FEATURE, + HOST_CHECK_CLASS, + HOST_CLASS_ENUM, + HOST_CLASS_HANDLER, + HOST_USER_INPUT, + HOST_SUSPENDED, + HOST_WAKEUP, + HOST_ERROR +} usb_host_state; + +/* USB host enumeration state */ +typedef enum +{ + ENUM_DEFAULT = 0U, + ENUM_GET_DEV_DESC, + ENUM_SET_ADDR, + ENUM_GET_CFG_DESC, + ENUM_GET_CFG_DESC_SET, + ENUM_GET_STR_DESC, +#ifdef USB_MTP + ENUM_GET_MTP_STR, +#endif + ENUM_SET_CONFIGURATION, + ENUM_DEV_CONFIGURED +} usbh_enum_state; + +/* USB host control transfer state */ +typedef enum +{ + CTL_IDLE = 0U, + CTL_SETUP, + CTL_SETUP_WAIT, + CTL_DATA_IN, + CTL_DATA_IN_WAIT, + CTL_DATA_OUT, + CTL_DATA_OUT_WAIT, + CTL_STATUS_IN, + CTL_STATUS_IN_WAIT, + CTL_STATUS_OUT, + CTL_STATUS_OUT_WAIT, + CTL_ERROR, + CTL_FINISH +} usbh_ctl_state; + +/* user action state */ +typedef enum +{ + USBH_USER_NO_RESP = 0U, + USBH_USER_RESP_OK = 1U, +} usbh_user_status; + +typedef enum +{ + USBH_PORT_EVENT = 1U, + USBH_URB_EVENT, + USBH_CONTROL_EVENT, + USBH_CLASS_EVENT, + USBH_STATE_CHANGED_EVENT, +}usbh_os_event; + +/* control transfer information */ +typedef struct _usbh_control +{ + uint8_t pipe_in_num; + uint8_t pipe_out_num; + uint8_t max_len; + uint8_t error_count; + + uint8_t *buf; + uint16_t ctl_len; + uint16_t timer; + + usb_setup setup; + usbh_ctl_state ctl_state; +} usbh_control; + +/* USB interface descriptor set */ +typedef struct _usb_desc_itf_set +{ + usb_desc_itf itf_desc; + usb_desc_ep ep_desc[USBH_MAX_EP_NUM]; +} usb_desc_itf_set; + +/* USB configure descriptor set */ +typedef struct _usb_desc_cfg_set +{ + usb_desc_config cfg_desc; + usb_desc_itf_set itf_desc_set[USBH_MAX_INTERFACES_NUM][USBH_MAX_ALT_SETTING]; +} usb_desc_cfg_set; + +/* USB device property */ +typedef struct +{ + uint8_t data[USBH_DATA_BUF_MAX_LEN]; /* if DMA is used, the data array must be located in the first position */ + uint8_t cur_itf; + uint8_t addr; + + uint32_t speed; + + usb_desc_dev dev_desc; + usb_desc_cfg_set cfg_desc_set; + +#if (USBH_KEEP_CFG_DESCRIPTOR == 1U) + uint8_t cfgdesc_rawdata[USBH_CFGSET_MAX_LEN]; +#endif /* (USBH_KEEP_CFG_DESCRIPTOR == 1U) */ +} usb_dev_prop; + +struct _usbh_host; + +/* device class callbacks */ +typedef struct +{ + uint8_t class_code; /*!< USB class type */ + + usbh_status (*class_init) (struct _usbh_host *phost); + void (*class_deinit) (struct _usbh_host *phost); + usbh_status (*class_requests) (struct _usbh_host *phost); + usbh_status (*class_machine) (struct _usbh_host *phost); + usbh_status (*class_sof) (struct _usbh_host *uhost); + + void *class_data; +} usbh_class; + +/* user callbacks */ +typedef struct +{ + void (*dev_init) (void); + void (*dev_deinit) (void); + void (*dev_attach) (void); + void (*dev_reset) (void); + void (*dev_detach) (void); + void (*dev_over_currented) (void); + void (*dev_speed_detected) (uint32_t dev_speed); + void (*dev_devdesc_assigned) (void *dev_desc); + void (*dev_address_set) (void); + + void (*dev_cfgdesc_assigned) (usb_desc_config *cfg_desc, + usb_desc_itf *itf_desc, + usb_desc_ep *ep_desc); + + void (*dev_mfc_str) (void *mfc_str); + void (*dev_prod_str) (void *prod_str); + void (*dev_seral_str) (void *serial_str); + void (*dev_enumerated) (void); + usbh_user_status (*dev_user_input) (void); + int (*dev_user_app) (void); + void (*dev_not_supported) (void); + void (*dev_error) (void); +} usbh_user_cb; + +/* host information */ +typedef struct _usbh_host +{ + usb_host_state cur_state; /*!< host state machine value */ + usb_host_state backup_state; /*!< backup of previous state machine value */ + usbh_enum_state enum_state; /*!< enumeration state machine */ + usbh_control control; /*!< USB host control state machine */ + usb_dev_prop dev_prop; /*!< USB device property */ + + usbh_class *uclass[USBH_MAX_SUPPORTED_CLASS]; /*!< USB host supported class */ + usbh_class *active_class; /*!< USB active class */ + usbh_user_cb *usr_cb; /*!< USB user callback */ + + uint8_t class_num; /*!< USB class number */ + + void *data; /*!< used for... */ +} usbh_host; + +/*! + \brief get USB URB state + \param[in] udev: pointer to USB core instance + \param[in] pp_num: pipe number + \param[out] none + \retval none +*/ +static inline usb_urb_state usbh_urbstate_get (usb_core_driver *udev, uint8_t pp_num) +{ + return udev->host.pipe[pp_num].urb_state; +} + +/*! + \brief get USB transfer data count + \param[in] udev: pointer to USB core instance + \param[in] pp_num: pipe number + \param[out] none + \retval none +*/ +static inline uint32_t usbh_xfercount_get (usb_core_driver *udev, uint8_t pp_num) +{ + return udev->host.backup_xfercount[pp_num]; +} + +/* function declarations */ +/* USB host stack initializations */ +void usbh_init (usbh_host *uhost, usbh_user_cb *user_cb); +/* USB host register device class */ +usbh_status usbh_class_register (usbh_host *uhost, usbh_class *puclass); +/* deinitialize USB host */ +usbh_status usbh_deinit (usbh_host *uhost); +/* USB host core main state machine process */ +void usbh_core_task (usbh_host *uhost); +/* handle the error on USB host side */ +void usbh_error_handler (usbh_host *uhost, usbh_status err_type); + +#endif /* __USBH_CORE_H */ diff --git a/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/host/core/Include/usbh_enum.h b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/host/core/Include/usbh_enum.h new file mode 100644 index 0000000000..81ed701bc3 --- /dev/null +++ b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/host/core/Include/usbh_enum.h @@ -0,0 +1,71 @@ +/*! + \file usbh_enum.h + \brief USB host mode USB enumeration header file + + \version 2020-07-17, V3.0.0, firmware for GD32F10x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef __USBH_ENUM_H +#define __USBH_ENUM_H + +#include "usb_conf.h" +#include "usbh_core.h" + +/* function declarations */ +/* configure USB control status parameters */ +void usbh_ctlstate_config (usbh_host *uhost, uint8_t *buf, uint16_t len); +/* get device descriptor from the USB device */ +usbh_status usbh_devdesc_get (usbh_host *uhost, uint8_t len); +/* get configuration descriptor from the USB device */ +usbh_status usbh_cfgdesc_get (usbh_host *uhost, uint16_t len); +/* get string descriptor from the USB device */ +usbh_status usbh_strdesc_get (usbh_host *uhost,uint8_t str_index, uint8_t *buf, uint16_t len); +/* set the address to the connected device */ +usbh_status usbh_setaddress (usbh_host *uhost, uint8_t dev_addr); +/* set the configuration value to the connected device */ +usbh_status usbh_setcfg (usbh_host *uhost, uint16_t config); +/* set the interface value to the connected device */ +usbh_status usbh_setinterface (usbh_host *uhost, uint8_t itf_num, uint8_t alter_setting); +/* set or enable a specific device feature */ +usbh_status usbh_setdevfeature (usbh_host *uhost, uint8_t feature_selector, uint16_t windex); +/* clear or disable a specific device feature */ +usbh_status usbh_clrdevfeature (usbh_host *uhost, uint8_t feature_selector, uint16_t windex); +/* clear or disable a specific feature */ +usbh_status usbh_clrfeature (usbh_host *uhost, uint8_t ep_addr, uint8_t pp_num); +/* get the next descriptor header */ +usb_desc_header *usbh_nextdesc_get (uint8_t *pbuf, uint16_t *ptr); +/* select an interface */ +usbh_status usbh_interface_select (usb_dev_prop *udev, uint8_t interface); +/* find the interface index for a specific class */ +uint8_t usbh_interface_find (usb_dev_prop *udev, uint8_t main_class, uint8_t sub_class, uint8_t protocol); +/* find the interface index for a specific class interface and alternate setting number */ +uint8_t usbh_interfaceindex_find (usb_dev_prop *udev, uint8_t interface_number, uint8_t alt_settings); + +#endif /* __USBH_ENUM_H */ diff --git a/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/host/core/Include/usbh_pipe.h b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/host/core/Include/usbh_pipe.h new file mode 100644 index 0000000000..f18d6a5a44 --- /dev/null +++ b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/host/core/Include/usbh_pipe.h @@ -0,0 +1,100 @@ +/*! + \file usbh_pipe.h + \brief USB host mode pipe header file + + \version 2020-07-17, V3.0.0, firmware for GD32F10x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef __USBH_PIPE_H +#define __USBH_PIPE_H + +#include "usbh_core.h" + +#define HC_MAX 8U + +#define HC_OK 0x0000U +#define HC_USED 0x8000U +#define HC_ERROR 0xFFFFU +#define HC_USED_MASK 0x7FFFU + +/*! + \brief set toggle for a pipe + \param[in] udev: pointer to USB core instance + \param[in] pp_num: pipe number + \param[in] toggle: toggle (0/1) + \param[out] none + \retval operation status +*/ +__STATIC_INLINE void usbh_pipe_toggle_set (usb_core_driver *udev, uint8_t pp_num, uint8_t toggle) +{ + if (udev->host.pipe[pp_num].ep.dir) { + udev->host.pipe[pp_num].data_toggle_in = toggle; + } else { + udev->host.pipe[pp_num].data_toggle_out = toggle; + } +} + +/*! + \brief get toggle flag of pipe + \param[in] udev: pointer to USB core instance + \param[in] pp_num: pipe number + \param[out] none + \retval operation status +*/ +__STATIC_INLINE uint8_t usbh_pipe_toggle_get (usb_core_driver *udev, uint8_t pp_num) +{ + if (udev->host.pipe[pp_num].ep.dir) { + return udev->host.pipe[pp_num].data_toggle_in; + } else { + return udev->host.pipe[pp_num].data_toggle_out; + } +} + +/* function declarations */ +/* create a pipe */ +uint8_t usbh_pipe_create (usb_core_driver *udev, + usb_dev_prop *dev, + uint8_t pp_num, + uint8_t ep_type, + uint16_t ep_mpl); +/* modify a pipe */ +uint8_t usbh_pipe_update (usb_core_driver *udev, + uint8_t pp_num, + uint8_t dev_addr, + uint32_t dev_speed, + uint16_t ep_mpl); +/* allocate a new pipe */ +uint8_t usbh_pipe_allocate (usb_core_driver *udev, uint8_t ep_addr); +/* free a pipe */ +uint8_t usbh_pipe_free (usb_core_driver *udev, uint8_t pp_num); +/* delete all USB host pipe */ +uint8_t usbh_pipe_delete (usb_core_driver *udev); + +#endif /* __USBH_PIPE_H */ diff --git a/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/host/core/Include/usbh_transc.h b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/host/core/Include/usbh_transc.h new file mode 100644 index 0000000000..433d5087ee --- /dev/null +++ b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/host/core/Include/usbh_transc.h @@ -0,0 +1,51 @@ +/*! + \file usbh_transc.h + \brief USB host mode transactions header file + + \version 2020-07-17, V3.0.0, firmware for GD32F10x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef __USBH_TRANSC_H +#define __USBH_TRANSC_H + +#include "usb_conf.h" +#include "usbh_core.h" + +/* function declarations */ +/* send the setup packet to the USB device */ +usbh_status usbh_ctlsetup_send (usb_core_driver *udev, uint8_t *buf, uint8_t pp_num); +/* send a data packet to the USB device */ +usbh_status usbh_data_send (usb_core_driver *udev, uint8_t *buf, uint8_t pp_num, uint16_t len); +/* receive a data packet from the USB device */ +usbh_status usbh_data_recev (usb_core_driver *udev, uint8_t *buf, uint8_t pp_num, uint16_t len); +/* USB control transfer handler */ +usbh_status usbh_ctl_handler (usbh_host *uhost); + +#endif /* __USBH_TRANSC_H */ diff --git a/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/host/core/Source/usbh_core.c b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/host/core/Source/usbh_core.c new file mode 100644 index 0000000000..aee70bba18 --- /dev/null +++ b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/host/core/Source/usbh_core.c @@ -0,0 +1,650 @@ +/*! + \file usbh_core.c + \brief USB host core state machine driver + + \version 2020-07-17, V3.0.0, firmware for GD32F10x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "drv_usb_hw.h" +#include "usbh_pipe.h" +#include "usbh_enum.h" +#include "usbh_core.h" +#include "drv_usbh_int.h" +#include + +usb_core_driver usbh_core; + +/* local function prototypes ('static') */ +static uint8_t usbh_sof (usbh_host *uhost); +static uint8_t usbh_connect (usbh_host *uhost); +static uint8_t usbh_disconnect (usbh_host *uhost); +static uint8_t usbh_port_enabled (usbh_host *uhost); +static uint8_t usbh_port_disabled (usbh_host *uhost); +static usbh_status usbh_enum_task (usbh_host *uhost); + +#ifdef USB_FS_LOW_PWR_ENABLE +static void usb_hwp_suspend(usb_core_driver *udev); +static void usb_hwp_resume(usb_core_driver *udev); +#endif + +usbh_int_cb usbh_int_op = +{ + usbh_connect, + usbh_disconnect, + usbh_port_enabled, + usbh_port_disabled, + usbh_sof +}; + +usbh_int_cb *usbh_int_fop = &usbh_int_op; + +/*! + \brief USB host stack initializations + \param[in] uhost: pointer to USB host + \param[in] user_cb: pointer to user callback + \param[out] none + \retval none +*/ +void usbh_init (usbh_host *uhost, usbh_user_cb *user_cb) +{ + /* host deinitialization */ + usbh_deinit(uhost); + + uhost->usr_cb = user_cb; + + usbh_core.host.connect_status = 0U; + + for (uint8_t i = 0U; i < USBFS_MAX_TX_FIFOS; i++) { + usbh_core.host.pipe[i].err_count = 0U; + usbh_core.host.pipe[i].pp_status = PIPE_IDLE; + usbh_core.host.backup_xfercount[i] = 0U; + } + + usbh_core.host.pipe[0].ep.mps = 8U; + +#ifdef USE_USB_FS + usb_basic_init (&usbh_core.bp, &usbh_core.regs, USB_CORE_ENUM_FS); +#endif /* USE_USB_FS */ + +#ifndef DUAL_ROLE_MODE_ENABLED + usb_globalint_disable(&usbh_core.regs); + + usb_core_init (usbh_core.bp, &usbh_core.regs); + +#ifndef USE_OTG_MODE + usb_curmode_set (&usbh_core.regs, HOST_MODE); +#endif /* USE_OTG_MODE */ + + usb_host_init (&usbh_core); + + usb_globalint_enable(&usbh_core.regs); +#endif /* DUAL_ROLE_MODE_ENABLED */ + + /* link driver to the stack */ + usbh_core.host.data = (void *)uhost; + uhost->data = (void *)&usbh_core; + + /* upon initialize call usr call back */ + uhost->usr_cb->dev_init(); +} + +/*! + \brief USB host register device class + \param[in] uhost: pointer to USB host instance + \param[in] puclass: pointer to USB device class + \param[out] none + \retval operation status +*/ +usbh_status usbh_class_register (usbh_host *uhost, usbh_class *puclass) +{ + usbh_status status = USBH_OK; + + if (NULL != puclass) { + if (uhost->class_num < USBH_MAX_SUPPORTED_CLASS) { + uhost->uclass[uhost->class_num++] = puclass; + } else { + status = USBH_FAIL; + } + } else { + status = USBH_FAIL; + } + + return status; +} + +/*! + \brief deinitialize USB host + \param[in] uhost: pointer to USB host + \param[out] none + \retval operation status +*/ +usbh_status usbh_deinit(usbh_host *uhost) +{ + /* software initialize */ + uhost->cur_state = HOST_DEFAULT; + uhost->backup_state = HOST_DEFAULT; + uhost->enum_state = ENUM_DEFAULT; + + uhost->control.ctl_state = CTL_IDLE; + uhost->control.max_len = USB_FS_EP0_MAX_LEN; + + uhost->dev_prop.addr = USBH_DEV_ADDR_DEFAULT; + uhost->dev_prop.speed = PORT_SPEED_FULL; + uhost->dev_prop.cur_itf = 0xFFU; + + usbh_pipe_free(&usbh_core, uhost->control.pipe_in_num); + usbh_pipe_free(&usbh_core, uhost->control.pipe_out_num); + + return USBH_OK; +} + +/*! + \brief USB host core main state machine process + \param[in] uhost: pointer to USB host + \param[out] none + \retval none +*/ +void usbh_core_task (usbh_host *uhost) +{ + volatile usbh_status status = USBH_FAIL; + + /* check for host port events */ + if (((0U == usbh_core.host.connect_status) || (0U == usbh_core.host.port_enabled)) && (HOST_DEFAULT != uhost->cur_state)) { + if (uhost->cur_state != HOST_DEV_DETACHED) { + uhost->cur_state = HOST_DEV_DETACHED; + } + } + + switch (uhost->cur_state) { + case HOST_DEFAULT: + if (usbh_core.host.connect_status) { + uhost->cur_state = HOST_DETECT_DEV_SPEED; + + usb_mdelay (100U); + + usb_port_reset (&usbh_core); + + uhost->usr_cb->dev_reset(); + } + break; + + case HOST_DETECT_DEV_SPEED: + if (usbh_core.host.port_enabled) { + uhost->cur_state = HOST_DEV_ATTACHED; + + uhost->dev_prop.speed = usb_curspeed_get (&usbh_core); + + uhost->usr_cb->dev_speed_detected(uhost->dev_prop.speed); + + usb_mdelay (50U); + } + break; + + case HOST_DEV_ATTACHED: + uhost->usr_cb->dev_attach(); + uhost->control.pipe_out_num = usbh_pipe_allocate(&usbh_core, 0x00U); + uhost->control.pipe_in_num = usbh_pipe_allocate(&usbh_core, 0x80U); + + /* open IN control pipe */ + usbh_pipe_create (&usbh_core, + &uhost->dev_prop, + uhost->control.pipe_in_num, + USB_EPTYPE_CTRL, + (uint16_t)uhost->control.max_len); + + /* open OUT control pipe */ + usbh_pipe_create (&usbh_core, + &uhost->dev_prop, + uhost->control.pipe_out_num, + USB_EPTYPE_CTRL, + (uint16_t)uhost->control.max_len); + + uhost->cur_state = HOST_ENUM; + break; + + case HOST_ENUM: + /* check for enumeration status */ + if (USBH_OK == usbh_enum_task (uhost)) { + /* the function shall return USBH_OK when full enumeration is complete */ + + /* user callback for end of device basic enumeration */ + uhost->usr_cb->dev_enumerated(); + +#ifdef USB_FS_LOW_PWR_ENABLE + uhost->cur_state = HOST_SUSPENDED; +#else + uhost->cur_state = HOST_SET_WAKEUP_FEATURE; +#endif + } + break; + + case HOST_SET_WAKEUP_FEATURE: + if ((uhost->dev_prop.cfg_desc_set.cfg_desc.bmAttributes) & (1U << 5)) { + if (usbh_setdevfeature(uhost, FEATURE_SELECTOR_REMOTEWAKEUP, 0U) == USBH_OK) { + uhost->cur_state = HOST_CHECK_CLASS; + } + } else { + uhost->cur_state = HOST_CHECK_CLASS; + } + break; + + case HOST_CHECK_CLASS: + if (0U == uhost->class_num) { + uhost->cur_state = HOST_ERROR; + } else { + uhost->active_class = NULL; + + uint8_t itf_class = uhost->dev_prop.cfg_desc_set.itf_desc_set[0][0].itf_desc.bInterfaceClass; + + for (uint8_t index = 0U; index < uhost->class_num; index++) { + if ((uhost->uclass[index]->class_code == itf_class) || (0xFFU == itf_class)) { + uhost->active_class = uhost->uclass[index]; + } + } + + if (uhost->active_class != NULL) { + uhost->cur_state = HOST_USER_INPUT; + } else { + uhost->cur_state = HOST_ERROR; + } + } + break; + + case HOST_USER_INPUT: + /* the function should return user response true to move to class state */ + if (USBH_USER_RESP_OK == uhost->usr_cb->dev_user_input()) { + if ((USBH_OK == uhost->active_class->class_init(uhost))) { + uhost->cur_state = HOST_CLASS_ENUM; + } + } + break; + +#ifdef USB_FS_LOW_PWR_ENABLE + case HOST_SUSPENDED: + if (USBH_OK == usbh_setdevfeature(uhost, FEATURE_SELECTOR_DEV, 0U)) { + uhost->suspend_flag = 1; + usb_hwp_suspend(uhost->data); + uhost->usr_cb->dev_user_input(); + pmu_to_deepsleepmode(PMU_LDO_LOWPOWER, WFI_CMD); + uhost->cur_state = HOST_WAKEUP; + } + break; + + case HOST_WAKEUP: + if (USBH_OK == usbh_clrdevfeature(uhost, FEATURE_SELECTOR_DEV, 0U)) { + /* user callback for initialization */ + uhost->usr_cb->dev_init(); + + uhost->cur_state = HOST_CHECK_CLASS; + } + break; +#endif + + case HOST_CLASS_ENUM: + /* process class standard control requests state machine */ + status = uhost->active_class->class_requests(uhost); + + if (USBH_OK == status) { + uhost->cur_state = HOST_CLASS_HANDLER; + } else { + usbh_error_handler (uhost, status); + } + break; + + case HOST_CLASS_HANDLER: + /* process class state machine */ + status = uhost->active_class->class_machine(uhost); + + usbh_error_handler (uhost, status); + break; + + case HOST_ERROR: + /* initialize host for new enumeration */ + usbh_deinit (uhost); + uhost->usr_cb->dev_deinit(); + uhost->active_class->class_deinit(uhost); + break; + + case HOST_DEV_DETACHED: + /* manage user disconnect operations*/ + uhost->usr_cb->dev_detach(); + + /* re-initialize host for new enumeration */ + usbh_deinit(uhost); + uhost->usr_cb->dev_deinit(); + uhost->active_class->class_deinit(uhost); + usbh_pipe_delete(&usbh_core); + uhost->cur_state = HOST_DEFAULT; + break; + + default: + break; + } +} + +/*! + \brief handle the error on USB host side + \param[in] uhost: pointer to USB host + \param[in] err_type: type of error or busy/OK state + \param[out] none + \retval none +*/ +void usbh_error_handler (usbh_host *uhost, usbh_status err_type) +{ + /* error unrecovered or not supported device speed */ + if ((USBH_SPEED_UNKNOWN_ERROR == err_type) || (USBH_UNRECOVERED_ERROR == err_type)) { + uhost->usr_cb->dev_error(); + + uhost->cur_state = HOST_ERROR; + } else if (USBH_APPLY_DEINIT == err_type) { + uhost->cur_state = HOST_ERROR; + + /* user callback for initialization */ + uhost->usr_cb->dev_init(); + } else { + /* no operation */ + } +} + +/*! + \brief USB SOF callback function from the interrupt + \param[in] uhost: pointer to USB host + \param[out] none + \retval operation status +*/ +static uint8_t usbh_sof (usbh_host *uhost) +{ + /* this callback could be used to implement a scheduler process */ + uhost->control.timer = (uint16_t)usb_curframe_get(&usbh_core); + + if (uhost->active_class != NULL) { + if (uhost->active_class->class_sof != NULL) { + uhost->active_class->class_sof(uhost); + } + } + + return 0U; +} + +/*! + \brief USB connect callback function from the interrupt + \param[in] uhost: pointer to USB host + \param[out] none + \retval operation status +*/ +static uint8_t usbh_connect (usbh_host *uhost) +{ + usbh_core.host.connect_status = 1U; + + return 0U; +} + +/*! + \brief USB disconnect callback function from the interrupt + \param[in] uhost: pointer to USB host + \param[out] none + \retval operation status +*/ +static uint8_t usbh_disconnect (usbh_host *uhost) +{ + usbh_core.host.connect_status = 0U; + + return 0U; +} + +/*! + \brief USB port enable callback function from the interrupt + \param[in] uhost: pointer to USB host + \param[out] none + \retval operation status +*/ +static uint8_t usbh_port_enabled (usbh_host *uhost) +{ + usbh_core.host.port_enabled = 1U; + + return 0U; +} + +/*! + \brief USB port disabled callback function from the interrupt + \param[in] uhost: pointer to USB host + \param[out] none + \retval operation status +*/ +static uint8_t usbh_port_disabled (usbh_host *uhost) +{ + usbh_core.host.port_enabled = 0U; + + return 0U; +} + +/*! + \brief handle the USB enumeration task + \param[in] uhost: pointer to host + \param[out] none + \retval none +*/ +static usbh_status usbh_enum_task (usbh_host *uhost) +{ + uint8_t str_buf[64]; + + usbh_status status = USBH_BUSY; + + static uint8_t index_mfc_str = 0U, index_prod_str = 0U, index_serial_str = 0U; + + switch (uhost->enum_state) { + case ENUM_DEFAULT: + /* get device descriptor for only 1st 8 bytes : to get ep0 max packet size */ + if (USBH_OK == usbh_devdesc_get (uhost, 8U)) { + uhost->control.max_len = uhost->dev_prop.dev_desc.bMaxPacketSize0; + + /* modify control channels configuration for maximum packet size */ + usbh_pipe_update (&usbh_core, + uhost->control.pipe_out_num, + 0U, 0U, + (uint16_t)uhost->control.max_len); + + usbh_pipe_update (&usbh_core, + uhost->control.pipe_in_num, + 0U, 0U, + (uint16_t)uhost->control.max_len); + + uhost->enum_state = ENUM_GET_DEV_DESC; + } + break; + + case ENUM_GET_DEV_DESC: + /* get full device descriptor */ + if (USBH_OK == usbh_devdesc_get (uhost, USB_DEV_DESC_LEN)) { + uhost->usr_cb->dev_devdesc_assigned(&uhost->dev_prop.dev_desc); + + index_mfc_str = uhost->dev_prop.dev_desc.iManufacturer; + index_prod_str = uhost->dev_prop.dev_desc.iProduct; + index_serial_str = uhost->dev_prop.dev_desc.iSerialNumber; + + uhost->enum_state = ENUM_SET_ADDR; + } + break; + + case ENUM_SET_ADDR: + /* set address */ + if (USBH_OK == usbh_setaddress (uhost, USBH_DEV_ADDR)) { + usb_mdelay (2U); + + uhost->dev_prop.addr = USBH_DEV_ADDR; + + /* user callback for device address assigned */ + uhost->usr_cb->dev_address_set(); + + /* modify control channels to update device address */ + usbh_pipe_update (&usbh_core, + uhost->control.pipe_in_num, + uhost->dev_prop.addr, + 0U, 0U); + + usbh_pipe_update (&usbh_core, + uhost->control.pipe_out_num, + uhost->dev_prop.addr, + 0U, 0U); + + uhost->enum_state = ENUM_GET_CFG_DESC; + } + break; + + case ENUM_GET_CFG_DESC: + /* get standard configuration descriptor */ + if (USBH_OK == usbh_cfgdesc_get (uhost, USB_CFG_DESC_LEN)) { + uhost->enum_state = ENUM_GET_CFG_DESC_SET; + } + break; + + case ENUM_GET_CFG_DESC_SET: + /* get full configure descriptor (config, interface, endpoints) */ + if (USBH_OK == usbh_cfgdesc_get (uhost, uhost->dev_prop.cfg_desc_set.cfg_desc.wTotalLength)) { + /* user callback for configuration descriptors available */ + uhost->usr_cb->dev_cfgdesc_assigned (&uhost->dev_prop.cfg_desc_set.cfg_desc, + &uhost->dev_prop.cfg_desc_set.itf_desc_set[0][0].itf_desc, + &uhost->dev_prop.cfg_desc_set.itf_desc_set[0][0].ep_desc[0]); + + uhost->enum_state = ENUM_GET_STR_DESC; + } + break; + + case ENUM_GET_STR_DESC: + if (index_mfc_str) { + if (USBH_OK == usbh_strdesc_get (uhost, + uhost->dev_prop.dev_desc.iManufacturer, + str_buf, + 0xFFU)) { + /* user callback for manufacturing string */ + uhost->usr_cb->dev_mfc_str(str_buf); + + index_mfc_str = 0U; + } + } else { + if (index_prod_str) { + /* check that product string is available */ + if (USBH_OK == usbh_strdesc_get (uhost, + uhost->dev_prop.dev_desc.iProduct, + str_buf, + 0xFFU)) { + uhost->usr_cb->dev_prod_str(str_buf); + + index_prod_str = 0U; + } + } else { + if (index_serial_str) { + if (USBH_OK == usbh_strdesc_get (uhost, + uhost->dev_prop.dev_desc.iSerialNumber, + str_buf, + 0xFFU)) { + uhost->usr_cb->dev_seral_str(str_buf); + uhost->enum_state = ENUM_SET_CONFIGURATION; + index_serial_str = 0U; + } + } else { + uhost->enum_state = ENUM_SET_CONFIGURATION; + } + } + } + break; + + case ENUM_SET_CONFIGURATION: + if (USBH_OK == usbh_setcfg (uhost, (uint16_t)uhost->dev_prop.cfg_desc_set.cfg_desc.bConfigurationValue)) { + uhost->enum_state = ENUM_DEV_CONFIGURED; + } + break; + + case ENUM_DEV_CONFIGURED: + status = USBH_OK; + break; + + default: + break; + } + + return status; +} + + +#ifdef USB_FS_LOW_PWR_ENABLE + +/*! + \brief handles the USB resume from suspend mode + \param[in] udev: pointer to selected USB device + \param[out] none + \retval none +*/ +static void usb_hwp_resume(usb_core_driver *udev) +{ + __IO uint32_t hprt = 0U; + + /* switch-on the clocks */ + *udev->regs.PWRCLKCTL &= ~PWRCLKCTL_SUCLK; + + *udev->regs.PWRCLKCTL &= ~PWRCLKCTL_SHCLK; + + hprt = usb_port_read(udev); + + hprt &= ~HPCS_PSP; + hprt |= HPCS_PREM; + + *udev->regs.HPCS = hprt; + + usb_mdelay (20U); + + hprt &= ~HPCS_PREM; + + *udev->regs.HPCS = hprt; +} + +/*! + \brief handles the USB enter to suspend mode + \param[in] udev: pointer to selected USB device + \param[out] none + \retval none +*/ +static void usb_hwp_suspend(usb_core_driver *udev) +{ + __IO uint32_t hprt = 0U; + + hprt = usb_port_read(udev); + + hprt |= HPCS_PSP; + + *udev->regs.HPCS = hprt; + + /* switch-off the clocks */ + *udev->regs.PWRCLKCTL |= PWRCLKCTL_SUCLK; + + *udev->regs.PWRCLKCTL |= PWRCLKCTL_SHCLK; +} + +#endif /* USB_LOW_PWR_ENABLE */ diff --git a/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/host/core/Source/usbh_enum.c b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/host/core/Source/usbh_enum.c new file mode 100644 index 0000000000..14a42c3052 --- /dev/null +++ b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/host/core/Source/usbh_enum.c @@ -0,0 +1,693 @@ +/*! + \file usbh_enum.c + \brief USB host mode enumberation driver + + \version 2020-07-17, V3.0.0, firmware for GD32F10x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "usbh_pipe.h" +#include "usbh_transc.h" +#include "usbh_enum.h" + +/* local function prototypes ('static') */ +static void usbh_devdesc_parse (usb_desc_dev *dev_desc, uint8_t *buf, uint16_t len); +static void usbh_cfgdesc_parse (usb_desc_config *cfg_desc, uint8_t *buf); +static void usbh_cfgset_parse (usb_dev_prop *udev, uint8_t *buf); +static void usbh_itfdesc_parse (usb_desc_itf *itf_desc, uint8_t *buf); +static void usbh_epdesc_parse (usb_desc_ep *ep_desc, uint8_t *buf); +static void usbh_strdesc_parse (uint8_t *psrc, uint8_t *pdest, uint16_t len); + +/*! + \brief configure USB control status parameters + \param[in] uhost: pointer to USB host + \param[in] buf: control transfer data buffer pointer + \param[in] len: length of the data buffer + \param[out] none + \retval none +*/ +void usbh_ctlstate_config (usbh_host *uhost, uint8_t *buf, uint16_t len) +{ + /* prepare the transactions */ + uhost->control.buf = buf; + uhost->control.ctl_len = len; + + uhost->control.ctl_state = CTL_SETUP; +} + +/*! + \brief get device descriptor from the USB device + \param[in] uhost: pointer to USB host + \param[in] len: length of the descriptor + \param[out] none + \retval operation status +*/ +usbh_status usbh_devdesc_get (usbh_host *uhost, uint8_t len) +{ + usbh_status status = USBH_BUSY; + + usbh_control *usb_ctl = &uhost->control; + + if (CTL_IDLE == usb_ctl->ctl_state) { + usb_ctl->setup.req = (usb_req) { + .bmRequestType = USB_TRX_IN | USB_RECPTYPE_DEV | USB_REQTYPE_STRD, + .bRequest = USB_GET_DESCRIPTOR, + .wValue = USBH_DESC(USB_DESCTYPE_DEV), + .wIndex = 0U, + .wLength = len + }; + + usbh_ctlstate_config (uhost, uhost->dev_prop.data, (uint16_t)len); + } + + status = usbh_ctl_handler (uhost); + + if (USBH_OK == status) { + /* commands successfully sent and response received */ + usbh_devdesc_parse (&uhost->dev_prop.dev_desc, uhost->dev_prop.data, (uint16_t)len); + } + + return status; +} + +/*! + \brief get configuration descriptor from the USB device + \param[in] uhost: pointer to USB host + \param[in] len: length of the descriptor + \param[out] none + \retval operation status +*/ +usbh_status usbh_cfgdesc_get (usbh_host *uhost, uint16_t len) +{ + uint8_t *pdata = NULL; + + usbh_status status = USBH_BUSY; + + usbh_control *usb_ctl = &uhost->control; + +#if (USBH_KEEP_CFG_DESCRIPTOR == 1U) + pdata = uhost->dev_prop.cfgdesc_rawdata; +#else + pdata = uhost->dev_prop.data; +#endif + + if (CTL_IDLE == usb_ctl->ctl_state) { + usb_ctl->setup.req = (usb_req) { + .bmRequestType = USB_TRX_IN | USB_RECPTYPE_DEV | USB_REQTYPE_STRD, + .bRequest = USB_GET_DESCRIPTOR, + .wValue = USBH_DESC(USB_DESCTYPE_CONFIG), + .wIndex = 0U, + .wLength = len + }; + + usbh_ctlstate_config (uhost, pdata, len); + } + + status = usbh_ctl_handler (uhost); + + if (USBH_OK == status) { + if (len <= USB_CFG_DESC_LEN) { + usbh_cfgdesc_parse (&uhost->dev_prop.cfg_desc_set.cfg_desc, pdata); + } else { + usbh_cfgset_parse (&uhost->dev_prop, pdata); + } + } + + return status; +} + +/*! + \brief get string descriptor from the USB device + \param[in] uhost: pointer to USB host + \param[in] str_index: index for the string descriptor + \param[in] buf: buffer pointer to the string descriptor + \param[in] len: length of the descriptor + \param[out] none + \retval operation status +*/ +usbh_status usbh_strdesc_get (usbh_host *uhost, + uint8_t str_index, + uint8_t *buf, + uint16_t len) +{ + usbh_status status = USBH_BUSY; + + usbh_control *usb_ctl = &uhost->control; + + if (CTL_IDLE == usb_ctl->ctl_state) { + usb_ctl->setup.req = (usb_req) { + .bmRequestType = USB_TRX_IN | USB_RECPTYPE_DEV | USB_REQTYPE_STRD, + .bRequest = USB_GET_DESCRIPTOR, + .wValue = USBH_DESC(USB_DESCTYPE_STR) | str_index, + .wIndex = 0x0409U, + .wLength = len + }; + + usbh_ctlstate_config (uhost, uhost->dev_prop.data, len); + } + + status = usbh_ctl_handler (uhost); + + if (USBH_OK == status) { + /* commands successfully sent and response received */ + usbh_strdesc_parse (uhost->dev_prop.data, buf, len); + } + + return status; +} + +/*! + \brief set the address to the connected device + \param[in] uhost: pointer to USB host + \param[in] dev_addr: device address to assign + \param[out] none + \retval operation status +*/ +usbh_status usbh_setaddress (usbh_host *uhost, uint8_t dev_addr) +{ + usbh_status status = USBH_BUSY; + + usbh_control *usb_ctl = &uhost->control; + + if (CTL_IDLE == usb_ctl->ctl_state) { + usb_ctl->setup.req = (usb_req) { + .bmRequestType = USB_TRX_OUT | USB_RECPTYPE_DEV | USB_REQTYPE_STRD, + .bRequest = USB_SET_ADDRESS, + .wValue = (uint16_t)dev_addr, + .wIndex = 0U, + .wLength = 0U + }; + + usbh_ctlstate_config (uhost, NULL, 0U); + } + + status = usbh_ctl_handler (uhost); + + return status; +} + +/*! + \brief set the configuration value to the connected device + \param[in] uhost: pointer to USB host + \param[in] config_index: configuration value + \param[out] none + \retval operation status +*/ +usbh_status usbh_setcfg (usbh_host *uhost, uint16_t config_index) +{ + usbh_status status = USBH_BUSY; + + usbh_control *usb_ctl = &uhost->control; + + if (CTL_IDLE == usb_ctl->ctl_state) { + usb_ctl->setup.req = (usb_req) { + .bmRequestType = USB_TRX_OUT | USB_RECPTYPE_DEV | USB_REQTYPE_STRD, + .bRequest = USB_SET_CONFIGURATION, + .wValue = config_index, + .wIndex = 0U, + .wLength = 0U + }; + + usbh_ctlstate_config (uhost, NULL, 0U); + } + + status = usbh_ctl_handler (uhost); + + return status; +} + +/*! + \brief set the interface value to the connected device + \param[in] uhost: pointer to USB host + \param[in] itf_num: interface number + \param[in] set: alternated setting value + \param[out] none + \retval operation status +*/ +usbh_status usbh_setinterface (usbh_host *uhost, uint8_t itf_num, uint8_t set) +{ + usbh_status status = USBH_BUSY; + + usbh_control *usb_ctl = &uhost->control; + + if (CTL_IDLE == usb_ctl->ctl_state) { + usb_ctl->setup.req = (usb_req) { + .bmRequestType = USB_TRX_OUT | USB_RECPTYPE_ITF | USB_REQTYPE_STRD, + .bRequest = USB_SET_INTERFACE, + .wValue = set, + .wIndex = itf_num, + .wLength = 0U + }; + + usbh_ctlstate_config (uhost, NULL, 0U); + } + + status = usbh_ctl_handler (uhost); + + return status; +} + +/*! + \brief set the interface value to the connected device + \param[in] uhost: pointer to USB host + \param[in] feature_selector: feature selector + \param[in] windex: index value + \param[out] none + \retval operation status +*/ +usbh_status usbh_setdevfeature (usbh_host *uhost, uint8_t feature_selector, uint16_t windex) +{ + usbh_status status = USBH_BUSY; + + usbh_control *usb_ctl = &uhost->control; + + if (CTL_IDLE == usb_ctl->ctl_state) { + usb_ctl->setup.req = (usb_req) { + .bmRequestType = USB_TRX_OUT | USB_RECPTYPE_DEV | USB_REQTYPE_STRD, + .bRequest = USB_SET_FEATURE, + .wValue = feature_selector, + .wIndex = windex, + .wLength = 0U + }; + + usbh_ctlstate_config (uhost, NULL, 0U); + } + + status = usbh_ctl_handler (uhost); + + return status; +} + +/*! + \brief clear the interface value to the connected device + \param[in] uhost: pointer to USB host + \param[in] feature_selector: feature selector + \param[in] windex: index value + \param[out] none + \retval operation status +*/ +usbh_status usbh_clrdevfeature (usbh_host *uhost, uint8_t feature_selector, uint16_t windex) +{ + usbh_status status = USBH_BUSY; + + usbh_control *usb_ctl = &uhost->control; + + if (CTL_IDLE == usb_ctl->ctl_state) { + usb_ctl->setup.req = (usb_req) { + .bmRequestType = USB_TRX_OUT | USB_RECPTYPE_DEV | USB_REQTYPE_STRD, + .bRequest = USB_CLEAR_FEATURE, + .wValue = feature_selector, + .wIndex = windex, + .wLength = 0U + }; + + usbh_ctlstate_config (uhost, NULL, 0U); + } + + status = usbh_ctl_handler (uhost); + + return status; +} + +/*! + \brief clear or disable a specific feature + \param[in] uhost: pointer to USB host + \param[in] ep_addr: endpoint address + \param[in] pp_num: pipe number + \param[out] none + \retval operation status +*/ +usbh_status usbh_clrfeature (usbh_host *uhost, uint8_t ep_addr, uint8_t pp_num) +{ + usbh_status status = USBH_BUSY; + usbh_control *usb_ctl = &uhost->control; + usb_core_driver *udev = (usb_core_driver *)uhost->data; + + if (CTL_IDLE == usb_ctl->ctl_state) { + usb_ctl->setup.req = (usb_req) { + .bmRequestType = USB_TRX_OUT | USB_RECPTYPE_EP | USB_REQTYPE_STRD, + .bRequest = USB_CLEAR_FEATURE, + .wValue = FEATURE_SELECTOR_EP, + .wIndex = ep_addr, + .wLength = 0U + }; + + if (EP_ID(ep_addr) == udev->host.pipe[pp_num].ep.num) { + usbh_pipe_toggle_set(udev, pp_num, 0U); + } else { + return USBH_FAIL; + } + + usbh_ctlstate_config (uhost, NULL, 0U); + } + + status = usbh_ctl_handler (uhost); + + return status; +} + +/*! + \brief get the next descriptor header + \param[in] pbuf: pointer to buffer where the configuration descriptor set is available + \param[in] ptr: data pointer inside the configuration descriptor set + \param[out] none + \retval return descriptor header +*/ +usb_desc_header *usbh_nextdesc_get (uint8_t *pbuf, uint16_t *ptr) +{ + usb_desc_header *pnext; + + *ptr += ((usb_desc_header *)pbuf)->bLength; + + pnext = (usb_desc_header *)((uint8_t *)pbuf + ((usb_desc_header *)pbuf)->bLength); + + return (pnext); +} + +/*! + \brief get the next descriptor header + \param[in] udev: pointer to device property + \param[in] interface: interface number + \param[out] none + \retval operation status +*/ +usbh_status usbh_interface_select (usb_dev_prop *udev, uint8_t interface) +{ + usbh_status status = USBH_OK; + + if (interface < udev->cfg_desc_set.cfg_desc.bNumInterfaces) { + udev->cur_itf = interface; + } else { + status = USBH_FAIL; + } + + return status; +} + +/*! + \brief find the interface index for a specific class + \param[in] udev: pointer to device property + \param[in] main_class: class code + \param[in] sub_class: subclass code + \param[in] protocol: Protocol code + \param[out] none + \retval interface index in the configuration structure + \note interface index 0xFF means interface index not found +*/ +uint8_t usbh_interface_find (usb_dev_prop *udev, uint8_t main_class, uint8_t sub_class, uint8_t protocol) +{ + usb_desc_itf *pif; + + uint8_t if_ix = 0U; + + pif = (usb_desc_itf *)0; + + while (if_ix < udev->cfg_desc_set.cfg_desc.bNumInterfaces) { + pif = &udev->cfg_desc_set.itf_desc_set[if_ix][0].itf_desc; + + if (((pif->bInterfaceClass == main_class) || (main_class == 0xFFU))&& + ((pif->bInterfaceSubClass == sub_class) || (sub_class == 0xFFU))&& + ((pif->bInterfaceProtocol == protocol) || (protocol == 0xFFU))) { + return if_ix; + } + + if_ix++; + } + + return 0xFFU; +} + +/*! + \brief find the interface index for a specific class interface and alternate setting number + \param[in] udev: pointer to device property + \param[in] interface_number: interface number + \param[in] alt_settings: alternate setting number + \param[out] none + \retval interface index in the configuration structure + \note interface index 0xFF means interface index not found +*/ +uint8_t usbh_interfaceindex_find (usb_dev_prop *udev, uint8_t interface_number, uint8_t alt_settings) +{ + usb_desc_itf *pif; + + uint8_t if_ix = 0U; + + pif = (usb_desc_itf *)0; + + while (if_ix < USBH_MAX_INTERFACES_NUM) { + pif = &udev->cfg_desc_set.itf_desc_set[if_ix][alt_settings].itf_desc; + + if ((pif->bInterfaceNumber == interface_number) && (pif->bAlternateSetting == alt_settings)) { + return if_ix; + } + + if_ix++; + } + + return 0xFFU; +} + +/*! + \brief parse the device descriptor + \param[in] dev_desc: pointer to USB device descriptor buffer + \param[in] buf: pointer to the source descriptor buffer + \param[in] len: length of the descriptor + \param[out] none + \retval none +*/ +static void usbh_devdesc_parse (usb_desc_dev *dev_desc, uint8_t *buf, uint16_t len) +{ + *dev_desc = (usb_desc_dev) { + .header = { + .bLength = *(uint8_t *)(buf + 0U), + .bDescriptorType = *(uint8_t *)(buf + 1U) + }, + + .bcdUSB = BYTE_SWAP(buf + 2U), + .bDeviceClass = *(uint8_t *)(buf + 4U), + .bDeviceSubClass = *(uint8_t *)(buf + 5U), + .bDeviceProtocol = *(uint8_t *)(buf + 6U), + .bMaxPacketSize0 = *(uint8_t *)(buf + 7U) + }; + + if (len > 8U) { + /* for 1st time after device connection, host may issue only 8 bytes for device descriptor length */ + dev_desc->idVendor = BYTE_SWAP(buf + 8U); + dev_desc->idProduct = BYTE_SWAP(buf + 10U); + dev_desc->bcdDevice = BYTE_SWAP(buf + 12U); + dev_desc->iManufacturer = *(uint8_t *)(buf + 14U); + dev_desc->iProduct = *(uint8_t *)(buf + 15U); + dev_desc->iSerialNumber = *(uint8_t *)(buf + 16U); + dev_desc->bNumberConfigurations = *(uint8_t *)(buf + 17U); + } +} + +/*! + \brief parse the configuration descriptor + \param[in] cfg_desc: pointer to USB configuration descriptor buffer + \param[in] buf: pointer to the source descriptor buffer + \param[out] none + \retval none +*/ +static void usbh_cfgdesc_parse (usb_desc_config *cfg_desc, uint8_t *buf) +{ + /* parse configuration descriptor */ + *cfg_desc = (usb_desc_config) { + .header = { + .bLength = *(uint8_t *)(buf + 0U), + .bDescriptorType = *(uint8_t *)(buf + 1U), + }, + + .wTotalLength = BYTE_SWAP(buf + 2U), + .bNumInterfaces = *(uint8_t *)(buf + 4U), + .bConfigurationValue = *(uint8_t *)(buf + 5U), + .iConfiguration = *(uint8_t *)(buf + 6U), + .bmAttributes = *(uint8_t *)(buf + 7U), + .bMaxPower = *(uint8_t *)(buf + 8U) + }; +} + +/*! + \brief parse the configuration descriptor set + \param[in] udev: pointer to device property + \param[in] buf: pointer to the source descriptor buffer + \param[out] none + \retval none +*/ +static void usbh_cfgset_parse (usb_dev_prop *udev, uint8_t *buf) +{ + usb_desc_ep *ep = NULL; + usb_desc_itf_set *itf = NULL; + usb_desc_itf itf_value; + usb_desc_config *cfg = NULL; + + usb_desc_header *pdesc = (usb_desc_header *)buf; + + uint8_t itf_index = 0U, ep_index = 0U, alt_setting = 0U; + uint8_t pre_itf_index = 0U; + uint16_t ptr; + + /* parse configuration descriptor */ + usbh_cfgdesc_parse (&udev->cfg_desc_set.cfg_desc, buf); + cfg = &udev->cfg_desc_set.cfg_desc; + ptr = USB_CFG_DESC_LEN; + + if (cfg->bNumInterfaces > USBH_MAX_INTERFACES_NUM) { + return; + } + + while (ptr < cfg->wTotalLength) { + pdesc = usbh_nextdesc_get ((uint8_t *)pdesc, &ptr); + + if (pdesc->bDescriptorType == USB_DESCTYPE_ITF) { + itf_index = *(((uint8_t *)pdesc) + 2U); + + if (pre_itf_index != itf_index) { + alt_setting = 0U; + } + + itf = &udev->cfg_desc_set.itf_desc_set[itf_index][alt_setting]; + + alt_setting++; + + if ((*((uint8_t *)pdesc + 3U)) < 3U) { + usbh_itfdesc_parse (&itf_value, (uint8_t *)pdesc); + + /* parse endpoint descriptors relative to the current interface */ + if (itf_value.bNumEndpoints > USBH_MAX_EP_NUM) { + return; + } + + usbh_itfdesc_parse (&itf->itf_desc, (uint8_t *)&itf_value); + + /* store the previous interface index */ + pre_itf_index = itf_index; + + if (0U == itf_value.bNumEndpoints) { + continue; + } + + for (ep_index = 0U; ep_index < itf_value.bNumEndpoints; ) { + pdesc = usbh_nextdesc_get ((void*)pdesc, &ptr); + + if (pdesc->bDescriptorType == USB_DESCTYPE_EP) { + ep = &itf->ep_desc[ep_index]; + + usbh_epdesc_parse (ep, (uint8_t *)pdesc); + + ep_index++; + } + } + } + } + } +} + +/*! + \brief parse the interface descriptor + \param[in] itf_desc: pointer to USB interface descriptor buffer + \param[in] buf: pointer to the source descriptor buffer + \param[out] none + \retval none +*/ +static void usbh_itfdesc_parse (usb_desc_itf *itf_desc, uint8_t *buf) +{ + *itf_desc = (usb_desc_itf) { + .header = { + .bLength = *(uint8_t *)(buf + 0U), + .bDescriptorType = *(uint8_t *)(buf + 1U), + }, + + .bInterfaceNumber = *(uint8_t *)(buf + 2U), + .bAlternateSetting = *(uint8_t *)(buf + 3U), + .bNumEndpoints = *(uint8_t *)(buf + 4U), + .bInterfaceClass = *(uint8_t *)(buf + 5U), + .bInterfaceSubClass = *(uint8_t *)(buf + 6U), + .bInterfaceProtocol = *(uint8_t *)(buf + 7U), + .iInterface = *(uint8_t *)(buf + 8U) + }; +} + +/*! + \brief parse the endpoint descriptor + \param[in] ep_desc: pointer to USB endpoint descriptor buffer + \param[in] buf: pointer to the source descriptor buffer + \param[out] none + \retval none +*/ +static void usbh_epdesc_parse (usb_desc_ep *ep_desc, uint8_t *buf) +{ + *ep_desc = (usb_desc_ep) { + .header = { + .bLength = *(uint8_t *)(buf + 0U), + .bDescriptorType = *(uint8_t *)(buf + 1U) + }, + + .bEndpointAddress = *(uint8_t *)(buf + 2U), + .bmAttributes = *(uint8_t *)(buf + 3U), + .wMaxPacketSize = BYTE_SWAP(buf + 4U), + .bInterval = *(uint8_t *)(buf + 6U) + }; +} + +/*! + \brief parse the string descriptor + \param[in] psrc: source pointer containing the descriptor data + \param[in] pdest: destination address pointer + \param[in] len: length of the descriptor + \param[out] none + \retval none +*/ +static void usbh_strdesc_parse (uint8_t *psrc, uint8_t *pdest, uint16_t len) +{ + uint16_t str_len = 0U, index = 0U; + + /* the unicode string descriptor is not NULL-terminated. The string length is + * computed by substracting two from the value of the first byte of the descriptor. + */ + + /* check which is lower size, the size of string or the length of bytes read from the device */ + if (USB_DESCTYPE_STR == psrc[1]) { + /* make sure the descriptor is string type */ + + /* psrc[0] contains Size of Descriptor, subtract 2 to get the length of string */ + str_len = USB_MIN((uint16_t)psrc[0] - 2U, len); + + psrc += 2U; /* adjust the offset ignoring the string len and descriptor type */ + + for (index = 0U; index < str_len; index += 2U) { + /* copy only the string and ignore the unicode id, hence add the src */ + *pdest = psrc[index]; + + pdest++; + } + + *pdest = 0U; /* mark end of string */ + } +} diff --git a/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/host/core/Source/usbh_pipe.c b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/host/core/Source/usbh_pipe.c new file mode 100644 index 0000000000..2310216fe1 --- /dev/null +++ b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/host/core/Source/usbh_pipe.c @@ -0,0 +1,174 @@ +/*! + \file usbh_pipe.c + \brief USB host mode pipe operation driver + + \version 2020-07-17, V3.0.0, firmware for GD32F10x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "usbh_pipe.h" + +/* local function prototypes ('static') */ +static uint16_t usbh_freepipe_get (usb_core_driver *udev); + +/*! + \brief create a pipe + \param[in] udev: pointer to USB core instance + \param[in] dev: USB device + \param[in] pp_num: pipe number + \param[in] ep_type: endpoint type + \param[in] ep_mpl: endpoint max packet length + \param[out] none + \retval operation status +*/ +uint8_t usbh_pipe_create (usb_core_driver *udev, + usb_dev_prop *dev, + uint8_t pp_num, + uint8_t ep_type, + uint16_t ep_mpl) +{ + usb_pipe *pp = &udev->host.pipe[pp_num]; + + pp->dev_addr = dev->addr; + pp->dev_speed = dev->speed; + pp->ep.type = ep_type; + pp->ep.mps = ep_mpl; + pp->ping = (uint8_t)(dev->speed == PORT_SPEED_HIGH); + + usb_pipe_init (udev, pp_num); + + return HC_OK; +} + +/*! + \brief modify a pipe + \param[in] udev: pointer to USB core instance + \param[in] pp_num: pipe number + \param[in] dev_addr: device address + \param[in] dev_speed: device speed + \param[in] ep_mpl: endpoint max packet length + \param[out] none + \retval operation status +*/ +uint8_t usbh_pipe_update (usb_core_driver *udev, + uint8_t pp_num, + uint8_t dev_addr, + uint32_t dev_speed, + uint16_t ep_mpl) +{ + usb_pipe *pp = &udev->host.pipe[pp_num]; + + if ((pp->dev_addr != dev_addr) && (dev_addr)) { + pp->dev_addr = dev_addr; + } + + if ((pp->dev_speed != dev_speed) && (dev_speed)) { + pp->dev_speed = dev_speed; + } + + if ((pp->ep.mps != ep_mpl) && (ep_mpl)) { + pp->ep.mps = ep_mpl; + } + + usb_pipe_init (udev, pp_num); + + return HC_OK; +} + +/*! + \brief allocate a new pipe + \param[in] udev: pointer to USB core instance + \param[in] ep_addr: endpoint address + \param[out] none + \retval operation status +*/ +uint8_t usbh_pipe_allocate (usb_core_driver *udev, uint8_t ep_addr) +{ + uint16_t pp_num = usbh_freepipe_get (udev); + + if (HC_ERROR != pp_num) { + udev->host.pipe[pp_num].in_used = 1U; + udev->host.pipe[pp_num].ep.dir = EP_DIR(ep_addr); + udev->host.pipe[pp_num].ep.num = EP_ID(ep_addr); + } + + return (uint8_t)pp_num; +} + +/*! + \brief free a pipe + \param[in] udev: pointer to USB core instance + \param[in] pp_num: pipe number + \param[out] none + \retval operation status +*/ +uint8_t usbh_pipe_free (usb_core_driver *udev, uint8_t pp_num) +{ + if (pp_num < HC_MAX) { + udev->host.pipe[pp_num].in_used = 0U; + } + + return USBH_OK; +} + +/*! + \brief delete all USB host pipe + \param[in] udev: pointer to USB core instance + \param[out] none + \retval operation status +*/ +uint8_t usbh_pipe_delete (usb_core_driver *udev) +{ + uint8_t pp_num = 0U; + + for (pp_num = 2U; pp_num < HC_MAX; pp_num++) { + udev->host.pipe[pp_num] = (usb_pipe) {0}; + } + + return USBH_OK; +} + +/*! + \brief get a free pipe number for allocation + \param[in] udev: pointer to USB core instance + \param[out] none + \retval operation status +*/ +static uint16_t usbh_freepipe_get (usb_core_driver *udev) +{ + uint8_t pp_num = 0U; + + for (pp_num = 0U; pp_num < HC_MAX; pp_num++) { + if (0U == udev->host.pipe[pp_num].in_used) { + return (uint16_t)pp_num; + } + } + + return HC_ERROR; +} diff --git a/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/host/core/Source/usbh_transc.c b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/host/core/Source/usbh_transc.c new file mode 100644 index 0000000000..c5917b7476 --- /dev/null +++ b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/host/core/Source/usbh_transc.c @@ -0,0 +1,371 @@ +/*! + \file usbh_transc.c + \brief USB host mode transactions driver + + \version 2020-07-17, V3.0.0, firmware for GD32F10x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "drv_usb_hw.h" +#include "usbh_pipe.h" +#include "usbh_transc.h" + +/* local function prototypes ('static') */ +static usb_urb_state usbh_urb_wait (usbh_host *uhost, uint8_t pp_num, uint32_t wait_time); +static void usbh_setup_transc (usbh_host *uhost); +static void usbh_data_in_transc (usbh_host *uhost); +static void usbh_data_out_transc (usbh_host *uhost); +static void usbh_status_in_transc (usbh_host *uhost); +static void usbh_status_out_transc (usbh_host *uhost); +static uint32_t usbh_request_submit (usb_core_driver *udev, uint8_t pp_num); + +/*! + \brief send the setup packet to the USB device + \param[in] udev: pointer to USB core instance + \param[in] buf: data buffer which will be sent to USB device + \param[in] pp_num: pipe number + \param[out] none + \retval operation status +*/ +usbh_status usbh_ctlsetup_send (usb_core_driver *udev, uint8_t *buf, uint8_t pp_num) +{ + usb_pipe *pp = &udev->host.pipe[pp_num]; + + pp->DPID = PIPE_DPID_SETUP; + pp->xfer_buf = buf; + pp->xfer_len = USB_SETUP_PACKET_LEN; + + return (usbh_status)usbh_request_submit (udev, pp_num); +} + +/*! + \brief send a data packet to the USB device + \param[in] udev: pointer to USB core instance + \param[in] buf: data buffer which will be sent to USB device + \param[in] pp_num: pipe number + \param[in] len: length of the data to be sent + \param[out] none + \retval operation status +*/ +usbh_status usbh_data_send (usb_core_driver *udev, uint8_t *buf, uint8_t pp_num, uint16_t len) +{ + usb_pipe *pp = &udev->host.pipe[pp_num]; + + pp->xfer_buf = buf; + pp->xfer_len = len; + + switch (pp->ep.type) { + case USB_EPTYPE_CTRL: + if (0U == len) { + pp->data_toggle_out = 1U; + } + + pp->DPID = PIPE_DPID[pp->data_toggle_out]; + break; + + case USB_EPTYPE_INTR: + pp->DPID = PIPE_DPID[pp->data_toggle_out]; + + pp->data_toggle_out ^= 1U; + break; + + case USB_EPTYPE_BULK: + pp->DPID = PIPE_DPID[pp->data_toggle_out]; + break; + + case USB_EPTYPE_ISOC: + pp->DPID = PIPE_DPID[0]; + break; + + default: + break; + } + + usbh_request_submit (udev, pp_num); + + return USBH_OK; +} + +/*! + \brief receive a data packet from the USB device + \param[in] udev: pointer to USB core instance + \param[in] buf: data buffer which will be received from USB device + \param[in] pp_num: pipe number + \param[in] len: length of the data to be received + \param[out] none + \retval operation status +*/ +usbh_status usbh_data_recev (usb_core_driver *udev, uint8_t *buf, uint8_t pp_num, uint16_t len) +{ + usb_pipe *pp = &udev->host.pipe[pp_num]; + + pp->xfer_buf = buf; + pp->xfer_len = len; + + switch (pp->ep.type) { + case USB_EPTYPE_CTRL: + pp->DPID = PIPE_DPID[1]; + break; + + case USB_EPTYPE_INTR: + pp->DPID = PIPE_DPID[pp->data_toggle_in]; + + /* Toggle DATA PID */ + pp->data_toggle_in ^= 1U; + break; + + case USB_EPTYPE_BULK: + pp->DPID = PIPE_DPID[pp->data_toggle_in]; + break; + + case USB_EPTYPE_ISOC: + pp->DPID = PIPE_DPID[0]; + break; + + default: + break; + } + + usbh_request_submit (udev, pp_num); + + return USBH_OK; +} + +/*! + \brief USB control transfer handler + \param[in] uhost: pointer to USB host + \param[out] none + \retval operation status +*/ +usbh_status usbh_ctl_handler (usbh_host *uhost) +{ + usbh_status status = USBH_BUSY; + + switch (uhost->control.ctl_state) { + case CTL_SETUP: + usbh_setup_transc (uhost); + break; + + case CTL_DATA_IN: + usbh_data_in_transc (uhost); + break; + + case CTL_DATA_OUT: + usbh_data_out_transc (uhost); + break; + + case CTL_STATUS_IN: + usbh_status_in_transc (uhost); + break; + + case CTL_STATUS_OUT: + usbh_status_out_transc (uhost); + break; + + case CTL_FINISH: + uhost->control.ctl_state = CTL_IDLE; + + status = USBH_OK; + break; + + case CTL_ERROR: + if (++uhost->control.error_count <= USBH_MAX_ERROR_COUNT) { + /* do the transmission again, starting from SETUP packet */ + uhost->control.ctl_state = CTL_SETUP; + } else { + status = USBH_FAIL; + } + break; + + default: + break; + } + + return status; +} + +/*! + \brief wait for USB URB(USB request block) state + \param[in] uhost: pointer to USB host + \param[in] pp_num: pipe number + \param[in] wait_time: wait time + \param[out] none + \retval USB URB state +*/ +static usb_urb_state usbh_urb_wait (usbh_host *uhost, uint8_t pp_num, uint32_t wait_time) +{ + usb_urb_state urb_status = URB_IDLE; + + while (URB_DONE != (urb_status = usbh_urbstate_get(uhost->data, pp_num))) { + if (URB_NOTREADY == urb_status) { + break; + } else if (URB_STALL == urb_status) { + uhost->control.ctl_state = CTL_SETUP; + break; + } else if (URB_ERROR == urb_status) { + uhost->control.ctl_state = CTL_ERROR; + break; + } else if ((wait_time > 0U) && ((usb_curframe_get(uhost->data)- uhost->control.timer) > wait_time)) { + /* timeout for in transfer */ + uhost->control.ctl_state = CTL_ERROR; + break; + } else { + /* no operation, just wait */ + } + } + + return urb_status; +} + +/*! + \brief USB setup transaction + \param[in] uhost: pointer to USB host + \param[out] none + \retval none +*/ +static void usbh_setup_transc (usbh_host *uhost) +{ + /* send a SETUP packet */ + usbh_ctlsetup_send (uhost->data, + uhost->control.setup.data, + uhost->control.pipe_out_num); + + if (URB_DONE == usbh_urb_wait (uhost, uhost->control.pipe_out_num, 0U)) { + uint8_t dir = (uhost->control.setup.req.bmRequestType & USB_TRX_MASK); + + if (uhost->control.setup.req.wLength) { + if (USB_TRX_IN == dir) { + uhost->control.ctl_state = CTL_DATA_IN; + } else { + uhost->control.ctl_state = CTL_DATA_OUT; + } + } else { + if (USB_TRX_IN == dir) { + uhost->control.ctl_state = CTL_STATUS_OUT; + } else { + uhost->control.ctl_state = CTL_STATUS_IN; + } + } + + /* set the delay timer to enable timeout for data stage completion */ + uhost->control.timer = (uint16_t)usb_curframe_get(uhost->data); + } +} + +/*! + \brief USB data IN transaction + \param[in] uhost: pointer to USB host + \param[out] none + \retval none +*/ +static void usbh_data_in_transc (usbh_host *uhost) +{ + usbh_data_recev (uhost->data, + uhost->control.buf, + uhost->control.pipe_in_num, + uhost->control.ctl_len); + + if (URB_DONE == usbh_urb_wait (uhost, uhost->control.pipe_in_num, DATA_STAGE_TIMEOUT)) { + uhost->control.ctl_state = CTL_STATUS_OUT; + + uhost->control.timer = (uint16_t)usb_curframe_get(uhost->data); + } +} + +/*! + \brief USB data OUT transaction + \param[in] uhost: pointer to USB host + \param[out] none + \retval none +*/ +static void usbh_data_out_transc (usbh_host *uhost) +{ + usbh_pipe_toggle_set(uhost->data, uhost->control.pipe_out_num, 1U); + + usbh_data_send (uhost->data, + uhost->control.buf, + uhost->control.pipe_out_num, + uhost->control.ctl_len); + + if (URB_DONE == usbh_urb_wait (uhost, uhost->control.pipe_out_num, DATA_STAGE_TIMEOUT)) { + uhost->control.ctl_state = CTL_STATUS_IN; + + uhost->control.timer = (uint16_t)usb_curframe_get(uhost->data); + } +} + +/*! + \brief USB status IN transaction + \param[in] uhost: pointer to USB host + \param[out] none + \retval none +*/ +static void usbh_status_in_transc (usbh_host *uhost) +{ + uint8_t pp_num = uhost->control.pipe_in_num; + + usbh_data_recev (uhost->data, NULL, pp_num, 0U); + + if (URB_DONE == usbh_urb_wait (uhost, pp_num, NODATA_STAGE_TIMEOUT)) { + uhost->control.ctl_state = CTL_FINISH; + } +} + +/*! + \brief USB status OUT transaction + \param[in] uhost: pointer to USB host + \param[out] none + \retval none +*/ +static void usbh_status_out_transc (usbh_host *uhost) +{ + uint8_t pp_num = uhost->control.pipe_out_num; + + usbh_data_send (uhost->data, NULL, pp_num, 0U); + + if (URB_DONE == usbh_urb_wait (uhost, pp_num, NODATA_STAGE_TIMEOUT)) { + uhost->control.ctl_state = CTL_FINISH; + } +} + +/*! + \brief prepare a pipe and start a transfer + \param[in] udev: pointer to USB core instance + \param[in] pp_num: pipe number + \param[out] none + \retval operation status +*/ +static uint32_t usbh_request_submit (usb_core_driver *udev, uint8_t pp_num) +{ + udev->host.pipe[pp_num].urb_state = URB_IDLE; + udev->host.pipe[pp_num].xfer_count = 0U; + + return (uint32_t)usb_pipe_xfer (udev, pp_num); +} + diff --git a/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/ustd/class/cdc/usb_cdc.h b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/ustd/class/cdc/usb_cdc.h new file mode 100644 index 0000000000..c7f77e07dd --- /dev/null +++ b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/ustd/class/cdc/usb_cdc.h @@ -0,0 +1,180 @@ +/*! + \file usb_cdc.h + \brief the header file of communication device class standard + + \version 2020-07-17, V3.0.0, firmware for GD32F10x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef __USB_CDC_H +#define __USB_CDC_H + +#include "usb_ch9_std.h" + +/* communications device class code */ +#define USB_CLASS_CDC 0x02U + +/* communications interface class control protocol codes */ +#define USB_CDC_PROTOCOL_NONE 0x00U +#define USB_CDC_PROTOCOL_AT 0x01U +#define USB_CDC_PROTOCOL_VENDOR 0xFFU + +/* data interface class code */ +#define USB_CLASS_DATA 0x0AU + +#define USB_DESCTYPE_CDC_ACM 0x21U +#define USB_DESCTYPE_CS_INTERFACE 0x24U + +#define USB_CDC_ACM_CONFIG_DESC_SIZE 0x43U + +/* class-specific notification codes for pstn subclasses */ +#define USB_CDC_NOTIFY_SERIAL_STATE 0x20U + +/* class-specific request codes */ +#define SEND_ENCAPSULATED_COMMAND 0x00U +#define GET_ENCAPSULATED_RESPONSE 0x01U +#define SET_COMM_FEATURE 0x02U +#define GET_COMM_FEATURE 0x03U +#define CLEAR_COMM_FEATURE 0x04U + +#define SET_AUX_LINE_STATE 0x10U +#define SET_HOOK_STATE 0x11U +#define PULSE_SETUP 0x12U +#define SEND_PULSE 0x13U +#define SET_PULSE_TIME 0x14U +#define RING_AUX_JACK 0x15U + +#define SET_LINE_CODING 0x20U +#define GET_LINE_CODING 0x21U +#define SET_CONTROL_LINE_STATE 0x22U +#define SEND_BREAK 0x23U +#define NO_CMD 0xFFU + +#define SET_RINGER_PARMS 0x30U +#define GET_RINGER_PARMS 0x31U +#define SET_OPERATION_PARMS 0x32U +#define GET_OPERATION_PARMS 0x33U +#define SET_LINE_PARMS 0x34U +#define GET_LINE_PARMS 0x35U +#define DIAL_DIGITS 0x36U +#define SET_UNIT_PARAMETER 0x37U +#define GET_UNIT_PARAMETER 0x38U +#define CLEAR_UNIT_PARAMETER 0x39U +#define GET_PROFILE 0x3AU + +#define SET_ETHERNET_MULTICAST_FILTERS 0x40U +#define SET_ETHERNET_POWER_MANAGEMENT_PATTERN FILTER 0x41U +#define GET_ETHERNET_POWER_MANAGEMENT_PATTERN FILTER 0x42U +#define SET_ETHERNET_PACKET_FILTER 0x43U +#define GET_ETHERNET_STATISTIC 0x44U + +#define SET_ATM_DATA_FORMAT 0x50U +#define GET_ATM_DEVICE_STATISTICS 0x51U +#define SET_ATM_DEFAULT_VC 0x52U +#define GET_ATM_VC_STATISTICS 0x53U + +/* wValue for set control line state */ +#define CDC_ACTIVATE_CARRIER_SIGNAL_RTS 0x0002U +#define CDC_DEACTIVATE_CARRIER_SIGNAL_RTS 0x0000U +#define CDC_ACTIVATE_SIGNAL_DTR 0x0001U +#define CDC_DEACTIVATE_SIGNAL_DTR 0x0000U + +/* CDC subclass code */ +enum usb_cdc_subclass { + USB_CDC_SUBCLASS_RESERVED = 0U, /*!< reserved */ + USB_CDC_SUBCLASS_DLCM, /*!< direct line control mode */ + USB_CDC_SUBCLASS_ACM, /*!< abstract control mode */ + USB_CDC_SUBCLASS_TCM, /*!< telephone control mode */ + USB_CDC_SUBCLASS_MCM, /*!< multichannel control model */ + USB_CDC_SUBCLASS_CCM, /*!< CAPI control model */ + USB_CDC_SUBCLASS_ENCM, /*!< ethernet networking control model */ + USB_CDC_SUBCLASS_ANCM /*!< ATM networking control model */ +}; + +#pragma pack(1) + +/* cdc acm line coding structure */ +typedef struct { + uint32_t dwDTERate; /*!< data terminal rate */ + uint8_t bCharFormat; /*!< stop bits */ + uint8_t bParityType; /*!< parity */ + uint8_t bDataBits; /*!< data bits */ +} acm_line; + +/* notification structure */ +typedef struct { + uint8_t bmRequestType; /*!< type of request */ + uint8_t bNotification; /*!< communication interface class notifications */ + uint16_t wValue; /*!< value of notification */ + uint16_t wIndex; /*!< index of interface */ + uint16_t wLength; /*!< length of notification data */ +} acm_notification; + +typedef struct { + usb_desc_header header; /*!< descriptor header, including type and size. */ + uint8_t bDescriptorSubtype; /*!< bDescriptorSubtype: header function descriptor */ + uint16_t bcdCDC; /*!< bcdCDC: low byte of spec release number (CDC1.10) */ +} usb_desc_header_func; + +typedef struct { + usb_desc_header header; /*!< descriptor header, including type and size. */ + uint8_t bDescriptorSubtype; /*!< bDescriptorSubtype: call management function descriptor */ + uint8_t bmCapabilities; /*!< bmCapabilities: D0 is reset, D1 is ignored */ + uint8_t bDataInterface; /*!< bDataInterface: 1 interface used for call management */ +} usb_desc_call_managment_func; + +typedef struct { + usb_desc_header header; /*!< descriptor header, including type and size. */ + uint8_t bDescriptorSubtype; /*!< bDescriptorSubtype: abstract control management descriptor */ + uint8_t bmCapabilities; /*!< bmCapabilities: D1 */ +} usb_desc_acm_func; + +typedef struct { + usb_desc_header header; /*!< descriptor header, including type and size. */ + uint8_t bDescriptorSubtype; /*!< bDescriptorSubtype: union function descriptor */ + uint8_t bMasterInterface; /*!< bMasterInterface: communication class interface */ + uint8_t bSlaveInterface0; /*!< bSlaveInterface0: data class interface */ +} usb_desc_union_func; + +#pragma pack() + +typedef struct { + usb_desc_config config; + usb_desc_itf cmd_itf; + usb_desc_header_func cdc_header; + usb_desc_call_managment_func cdc_call_managment; + usb_desc_acm_func cdc_acm; + usb_desc_union_func cdc_union; + usb_desc_ep cdc_cmd_endpoint; + usb_desc_itf cdc_data_interface; + usb_desc_ep cdc_out_endpoint; + usb_desc_ep cdc_in_endpoint; +} usb_cdc_desc_config_set; + +#endif /* __USB_CDC_H */ diff --git a/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/ustd/class/hid/usb_hid.h b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/ustd/class/hid/usb_hid.h new file mode 100644 index 0000000000..bd00508b3e --- /dev/null +++ b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/ustd/class/hid/usb_hid.h @@ -0,0 +1,83 @@ +/*! + \file usb_hid.h + \brief definitions for the USB HID class + + \version 2020-07-17, V3.0.0, firmware for GD32F10x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef __USB_HID_H +#define __USB_HID_H + +#include "usb_ch9_std.h" + +#define USB_HID_CLASS 0x03U + +#define USB_DESCTYPE_HID 0x21U +#define USB_DESCTYPE_REPORT 0x22U + +/* HID subclass code */ +#define USB_HID_SUBCLASS_BOOT_ITF 0x01U + +/* HID protocol codes */ +#define USB_HID_PROTOCOL_KEYBOARD 0x01U +#define USB_HID_PROTOCOL_MOUSE 0x02U + +#define GET_REPORT 0x01U +#define GET_IDLE 0x02U +#define GET_PROTOCOL 0x03U +#define SET_REPORT 0x09U +#define SET_IDLE 0x0AU +#define SET_PROTOCOL 0x0BU + +#pragma pack(1) + +typedef struct +{ + usb_desc_header header; /*!< regular descriptor header containing the descriptor's type and length */ + + uint16_t bcdHID; /*!< BCD encoded version that the HID descriptor and device complies to */ + uint8_t bCountryCode; /*!< country code of the localized device, or zero if universal */ + uint8_t bNumDescriptors; /*!< total number of HID report descriptors for the interface */ + uint8_t bDescriptorType; /*!< type of HID report */ + uint16_t wDescriptorLength; /*!< length of the associated HID report descriptor, in bytes */ +} usb_desc_hid; + +#pragma pack() + +typedef struct +{ + usb_desc_config config; + usb_desc_itf hid_itf; + usb_desc_hid hid_vendor; + usb_desc_ep hid_epin; + usb_desc_ep hid_epout; +}usb_hid_desc_config_set; + +#endif /* __USB_HID_H */ diff --git a/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/ustd/class/msc/msc_bbb.h b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/ustd/class/msc/msc_bbb.h new file mode 100644 index 0000000000..32a259101b --- /dev/null +++ b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/ustd/class/msc/msc_bbb.h @@ -0,0 +1,69 @@ +/*! + \file msc_bbb.h + \brief definitions for the USB MSC BBB(bulk/bulk/bulk) protocol + + \version 2020-07-17, V3.0.0, firmware for GD32F10x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef __MSC_BBB_H +#define __MSC_BBB_H + +#include "usb_ch9_std.h" + +#define BBB_CBW_SIGNATURE 0x43425355U +#define BBB_CSW_SIGNATURE 0x53425355U +#define BBB_CBW_LENGTH 31U +#define BBB_CSW_LENGTH 13U + +typedef struct { + uint32_t dCBWSignature; + uint32_t dCBWTag; + uint32_t dCBWDataTransferLength; + uint8_t bmCBWFlags; + uint8_t bCBWLUN; + uint8_t bCBWCBLength; + uint8_t CBWCB[16]; +}msc_bbb_cbw; + +typedef struct { + uint32_t dCSWSignature; + uint32_t dCSWTag; + uint32_t dCSWDataResidue; + uint8_t bCSWStatus; +}msc_bbb_csw; + +/* CSW command status */ +enum msc_csw_status { + CSW_CMD_PASSED = 0, + CSW_CMD_FAILED, + CSW_PHASE_ERROR +}; + +#endif /* __MSC_BBB_H */ diff --git a/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/ustd/class/msc/msc_scsi.h b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/ustd/class/msc/msc_scsi.h new file mode 100644 index 0000000000..6a8aac60cf --- /dev/null +++ b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/ustd/class/msc/msc_scsi.h @@ -0,0 +1,117 @@ +/*! + \file msc_scsi.h + \brief definitions for the USB MSC SCSI commands + + \version 2020-07-17, V3.0.0, firmware for GD32F10x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef __MSC_SCSI_H +#define __MSC_SCSI_H + +#include "usb_ch9_std.h" + +/* SCSI commands */ +#define SCSI_FORMAT_UNIT 0x04U +#define SCSI_INQUIRY 0x12U +#define SCSI_MODE_SELECT6 0x15U +#define SCSI_MODE_SELECT10 0x55U +#define SCSI_MODE_SENSE6 0x1AU +#define SCSI_READ_TOC_DATA 0x43U +#define SCSI_MODE_SENSE10 0x5AU +#define SCSI_ALLOW_MEDIUM_REMOVAL 0x1EU +#define SCSI_READ6 0x08U +#define SCSI_READ10 0x28U +#define SCSI_READ12 0xA8U +#define SCSI_READ16 0x88U + +#define SCSI_READ_CAPACITY10 0x25U +#define SCSI_READ_CAPACITY16 0x9EU + +#define SCSI_REQUEST_SENSE 0x03U +#define SCSI_START_STOP_UNIT 0x1BU +#define SCSI_TEST_UNIT_READY 0x00U +#define SCSI_WRITE6 0x0AU +#define SCSI_WRITE10 0x2AU +#define SCSI_WRITE12 0xAAU +#define SCSI_WRITE16 0x8AU + +#define SCSI_VERIFY10 0x2FU +#define SCSI_VERIFY12 0xAFU +#define SCSI_VERIFY16 0x8FU + +#define SCSI_SEND_DIAGNOSTIC 0x1DU +#define SCSI_READ_FORMAT_CAPACITIES 0x23U + +#define INVALID_CDB 0x20U +#define INVALID_FIELED_IN_COMMAND 0x24U +#define PARAMETER_LIST_LENGTH_ERROR 0x1AU +#define INVALID_FIELD_IN_PARAMETER_LIST 0x26U +#define ADDRESS_OUT_OF_RANGE 0x21U +#define MEDIUM_NOT_PRESENT 0x3AU +#define MEDIUM_HAVE_CHANGED 0x28U +#define WRITE_PROTECTED 0x27U +#define UNRECOVERED_READ_ERROR 0x11U +#define WRITE_FAULT 0x03U + +#define READ_FORMAT_CAPACITY_DATA_LEN 0x0CU +#define READ_CAPACITY10_DATA_LEN 0x08U +#define MODE_SENSE10_DATA_LEN 0x08U +#define MODE_SENSE6_DATA_LEN 0x04U +#define READ_TOC_CMD_LEN 0x14U +#define REQUEST_SENSE_DATA_LEN 0x12U +#define STANDARD_INQUIRY_DATA_LEN 0x24U +#define BLKVFY 0x04U + +enum sense_state { + NO_SENSE = 0U, + RECOVERED_ERROR, + NOT_READY, + MEDIUM_ERROR, + HARDWARE_ERROR, + ILLEGAL_REQUEST, + UNIT_ATTENTION, + DATA_PROTECT, + BLANK_CHECK, + VENDOR_SPECIFIC, + COPY_ABORTED, + ABORTED_COMMAND, + RESERVED, + VOLUME_OVERFLOW, + MISCOMPARE +}; + +typedef struct { + uint8_t SenseKey; + uint32_t Information; + uint8_t ASC; + uint8_t ASCQ; +} msc_scsi_sense; + +#endif /* __MSC_SCSI_H */ diff --git a/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/ustd/class/msc/usb_msc.h b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/ustd/class/msc/usb_msc.h new file mode 100644 index 0000000000..4c6b971fbb --- /dev/null +++ b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/ustd/class/msc/usb_msc.h @@ -0,0 +1,68 @@ +/*! + \file usb_msc.h + \brief definitions for the USB MSC class + + \version 2020-07-17, V3.0.0, firmware for GD32F10x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef __USB_MSC_H +#define __USB_MSC_H + +#include "usb_ch9_std.h" + +/* mass storage device class code */ +#define USB_CLASS_MSC 0x08U + +/* mass storage subclass code */ +#define USB_MSC_SUBCLASS_RBC 0x01U +#define USB_MSC_SUBCLASS_ATAPI 0x02U +#define USB_MSC_SUBCLASS_UFI 0x04U +#define USB_MSC_SUBCLASS_SCSI 0x06U +#define USB_MSC_SUBCLASS_LOCKABLE 0x07U +#define USB_MSC_SUBCLASS_IEEE1667 0x08U + +/* mass storage interface class control protocol codes */ +#define USB_MSC_PROTOCOL_CBI 0x00U +#define USB_MSC_PROTOCOL_CBI_ALT 0x01U +#define USB_MSC_PROTOCOL_BBB 0x50U + +/* mass storage request codes */ +#define USB_MSC_REQ_CODES_ADSC 0x00U +#define USB_MSC_REQ_CODES_GET 0xFCU +#define USB_MSC_REQ_CODES_PUT 0xFDU +#define USB_MSC_REQ_CODES_GML 0xFEU +#define USB_MSC_REQ_CODES_BOMSR 0xFFU + +#define BBB_GET_MAX_LUN 0xFEU +#define BBB_RESET 0xFFU + +#define SCSI_CMD_LENGTH 16U + +#endif /* __USB_MSC_H */ diff --git a/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/ustd/common/usb_ch9_std.h b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/ustd/common/usb_ch9_std.h new file mode 100644 index 0000000000..4b366f2d6d --- /dev/null +++ b/bsp/gd32/libraries/GD32F10x_Firmware_Library/GD32F10x_usbfs_library/ustd/common/usb_ch9_std.h @@ -0,0 +1,248 @@ +/*! + \file usb_ch9_std.h + \brief USB 2.0 standard defines + + \version 2020-07-17, V3.0.0, firmware for GD32F10x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef __USB_CH9_STD_H +#define __USB_CH9_STD_H + +#include "usb_conf.h" + +#define USB_DEV_QUALIFIER_DESC_LEN 0x0AU /*!< USB device qualifier descriptor length */ +#define USB_DEV_DESC_LEN 0x12U /*!< USB device descriptor length */ +#define USB_CFG_DESC_LEN 0x09U /*!< USB configuration descriptor length */ +#define USB_ITF_DESC_LEN 0x09U /*!< USB interface descriptor length */ +#define USB_EP_DESC_LEN 0x07U /*!< USB endpoint descriptor length */ +#define USB_IAD_DESC_LEN 0x08U /*!< USB IAD descriptor length */ +#define USB_OTG_DESC_LEN 0x03U /*!< USB device OTG descriptor length */ + +#define USB_SETUP_PACKET_LEN 0x08U /*!< USB setup packet length */ + +/* bit 7 of bmRequestType: data phase transfer direction */ +#define USB_TRX_MASK 0x80U /*!< USB transfer direction mask */ +#define USB_TRX_OUT 0x00U /*!< USB transfer OUT direction */ +#define USB_TRX_IN 0x80U /*!< USB transfer IN direction */ + +/* bit 6..5 of bmRequestType: request type */ +#define USB_REQTYPE_STRD 0x00U /*!< USB standard request */ +#define USB_REQTYPE_CLASS 0x20U /*!< USB class request */ +#define USB_REQTYPE_VENDOR 0x40U /*!< USB vendor request */ +#define USB_REQTYPE_MASK 0x60U /*!< USB request mask */ + +#define USBD_BUS_POWERED 0x00U /*!< USB bus power supply */ +#define USBD_SELF_POWERED 0x01U /*!< USB self power supply */ + +#define USB_STATUS_REMOTE_WAKEUP 2U /*!< USB is in remote wakeup status */ +#define USB_STATUS_SELF_POWERED 1U /*!< USB is in self powered status */ + +/* bit 4..0 of bmRequestType: recipient type */ +enum _usb_recp_type { + USB_RECPTYPE_DEV = 0x0U, /*!< USB device request type */ + USB_RECPTYPE_ITF = 0x1U, /*!< USB interface request type */ + USB_RECPTYPE_EP = 0x2U, /*!< USB endpoint request type */ + USB_RECPTYPE_MASK = 0x3U /*!< USB request type mask */ +}; + +/* bRequest value */ +enum _usb_request { + USB_GET_STATUS = 0x0U, /*!< USB get status request */ + USB_CLEAR_FEATURE = 0x1U, /*!< USB clear feature request */ + USB_RESERVED2 = 0x2U, + USB_SET_FEATURE = 0x3U, /*!< USB set feature request */ + USB_RESERVED4 = 0x4U, + USB_SET_ADDRESS = 0x5U, /*!< USB set address request */ + USB_GET_DESCRIPTOR = 0x6U, /*!< USB get descriptor request */ + USB_SET_DESCRIPTOR = 0x7U, /*!< USB set descriptor request */ + USB_GET_CONFIGURATION = 0x8U, /*!< USB get configuration request */ + USB_SET_CONFIGURATION = 0x9U, /*!< USB set configuration request */ + USB_GET_INTERFACE = 0xAU, /*!< USB get interface request */ + USB_SET_INTERFACE = 0xBU, /*!< USB set interface request */ + USB_SYNCH_FRAME = 0xCU /*!< USB synchronize frame request */ +}; + +/* descriptor types of USB specifications */ +enum _usb_desctype { + USB_DESCTYPE_DEV = 0x1U, /*!< USB device descriptor type */ + USB_DESCTYPE_CONFIG = 0x2U, /*!< USB configuration descriptor type */ + USB_DESCTYPE_STR = 0x3U, /*!< USB string descriptor type */ + USB_DESCTYPE_ITF = 0x4U, /*!< USB interface descriptor type */ + USB_DESCTYPE_EP = 0x5U, /*!< USB endpoint descriptor type */ + USB_DESCTYPE_DEV_QUALIFIER = 0x6U, /*!< USB device qualifier descriptor type */ + USB_DESCTYPE_OTHER_SPD_CONFIG = 0x7U, /*!< USB other speed configuration descriptor type */ + USB_DESCTYPE_ITF_POWER = 0x8U, /*!< USB interface power descriptor type */ + USB_DESCTYPE_IAD = 0xBU, /*!< USB interface association descriptor type */ + USB_DESCTYPE_BOS = 0xFU /*!< USB BOS descriptor type */ +}; + +/* USB Endpoint Descriptor bmAttributes bit definitions */ +/* bits 1..0 : transfer type */ +enum _usbx_type { + USB_EP_ATTR_CTL = 0x0U, /*!< USB control transfer type */ + USB_EP_ATTR_ISO = 0x1U, /*!< USB Isochronous transfer type */ + USB_EP_ATTR_BULK = 0x2U, /*!< USB Bulk transfer type */ + USB_EP_ATTR_INT = 0x3U /*!< USB Interrupt transfer type */ +}; + +/* bits 3..2 : Sync type (only if ISOCHRONOUS) */ +#define USB_EP_ATTR_NOSYNC 0x00U /*!< No Synchronization */ +#define USB_EP_ATTR_ASYNC 0x04U /*!< Asynchronous */ +#define USB_EP_ATTR_ADAPTIVE 0x08U /*!< Adaptive */ +#define USB_EP_ATTR_SYNC 0x0CU /*!< Synchronous */ +#define USB_EP_ATTR_SYNCTYPE 0x0CU /*!< Synchronous type */ + +/* bits 5..4 : usage type (only if ISOCHRONOUS) */ +#define USB_EP_ATTR_DATA 0x00U /*!< Data endpoint */ +#define USB_EP_ATTR_FEEDBACK 0x10U /*!< Feedback endpoint */ +#define USB_EP_ATTR_IMPLICIT_FEEDBACK_DATA 0x20U /*!< Implicit feedback Data endpoint */ +#define USB_EP_ATTR_USAGETYPE 0x30U /*!< Usage type */ + +/* endpoint max packet size bits12..11 */ +#define USB_EP_MPS_ADD_0 (0x00 << 11) /*!< None(1 transaction per microframe */ +#define USB_EP_MPS_ADD_1 (0x01 << 11) /*!< 1 additional(2 transaction per microframe */ +#define USB_EP_MPS_ADD_2 (0x02 << 11) /*!< 2 additional(3 transaction per microframe */ + +#define FEATURE_SELECTOR_EP 0x00U /*!< USB endpoint feature selector */ +#define FEATURE_SELECTOR_DEV 0x01U /*!< USB device feature selector */ +#define FEATURE_SELECTOR_REMOTEWAKEUP 0x01U /*!< USB feature selector remote wakeup */ + +#define BYTE_SWAP(addr) (((uint16_t)(*((uint8_t *)(addr)))) + \ + (uint16_t)(((uint16_t)(*(((uint8_t *)(addr)) + 1U))) << 8U)) + +#define BYTE_LOW(x) ((uint8_t)((x) & 0x00FFU)) +#define BYTE_HIGH(x) ((uint8_t)(((x) & 0xFF00U) >> 8U)) + +#define USB_MIN(a, b) (((a) < (b)) ? (a) : (b)) + +#define USB_DEFAULT_CONFIG 0U + +/* USB classes */ +#define USB_CLASS_HID 0x03U /*!< USB HID class */ +#define USB_CLASS_MSC 0x08U /*!< USB MSC class */ + +/* use the following values when USB host need to get descriptor */ +#define USBH_DESC(x) (((x)<< 8U) & 0xFF00U) + +/* as per USB specs 9.2.6.4 :standard request with data request timeout: 5sec + standard request with no data stage timeout : 50ms */ +#define DATA_STAGE_TIMEOUT 5000U /*!< USB data stage timeout*/ +#define NODATA_STAGE_TIMEOUT 50U /*!< USB no data stage timeout*/ + +#pragma pack(1) + +/* USB standard device request structure */ +typedef struct _usb_req { + uint8_t bmRequestType; /*!< type of request */ + uint8_t bRequest; /*!< request of setup packet */ + uint16_t wValue; /*!< value of setup packet */ + uint16_t wIndex; /*!< index of setup packet */ + uint16_t wLength; /*!< length of setup packet */ +} usb_req; + +/* USB setup packet define */ +typedef union _usb_setup { + uint8_t data[8]; + + usb_req req; +} usb_setup; + +/* USB descriptor defines */ + +typedef struct _usb_desc_header { + uint8_t bLength; /*!< size of the descriptor */ + uint8_t bDescriptorType; /*!< type of the descriptor */ +} usb_desc_header; + +typedef struct _usb_desc_dev { + usb_desc_header header; /*!< descriptor header, including type and size */ + + uint16_t bcdUSB; /*!< BCD of the supported USB specification */ + uint8_t bDeviceClass; /*!< USB device class */ + uint8_t bDeviceSubClass; /*!< USB device subclass */ + uint8_t bDeviceProtocol; /*!< USB device protocol */ + uint8_t bMaxPacketSize0; /*!< size of the control (address 0) endpoint's bank in bytes */ + uint16_t idVendor; /*!< vendor ID for the USB product */ + uint16_t idProduct; /*!< unique product ID for the USB product */ + uint16_t bcdDevice; /*!< product release (version) number */ + uint8_t iManufacturer; /*!< string index for the manufacturer's name */ + uint8_t iProduct; /*!< string index for the product name/details */ + uint8_t iSerialNumber; /*!< string index for the product's globally unique hexadecimal serial number */ + uint8_t bNumberConfigurations; /*!< total number of configurations supported by the device */ +} usb_desc_dev; + +typedef struct _usb_desc_config { + usb_desc_header header; /*!< descriptor header, including type and size */ + + uint16_t wTotalLength; /*!< size of the configuration descriptor header,and all sub descriptors inside the configuration */ + uint8_t bNumInterfaces; /*!< total number of interfaces in the configuration */ + uint8_t bConfigurationValue; /*!< configuration index of the current configuration */ + uint8_t iConfiguration; /*!< index of a string descriptor describing the configuration */ + uint8_t bmAttributes; /*!< configuration attributes */ + uint8_t bMaxPower; /*!< maximum power consumption of the device while in the current configuration */ +} usb_desc_config; + +typedef struct _usb_desc_itf { + usb_desc_header header; /*!< descriptor header, including type and size */ + + uint8_t bInterfaceNumber; /*!< index of the interface in the current configuration */ + uint8_t bAlternateSetting; /*!< alternate setting for the interface number */ + uint8_t bNumEndpoints; /*!< total number of endpoints in the interface */ + uint8_t bInterfaceClass; /*!< interface class ID */ + uint8_t bInterfaceSubClass; /*!< interface subclass ID */ + uint8_t bInterfaceProtocol; /*!< interface protocol ID */ + uint8_t iInterface; /*!< index of the string descriptor describing the interface */ +} usb_desc_itf; + +typedef struct _usb_desc_ep { + usb_desc_header header; /*!< descriptor header, including type and size. */ + + uint8_t bEndpointAddress; /*!< logical address of the endpoint */ + uint8_t bmAttributes; /*!< endpoint attributes */ + uint16_t wMaxPacketSize; /*!< size of the endpoint bank, in bytes */ + uint8_t bInterval; /*!< polling interval in milliseconds for the endpoint if it is an INTERRUPT or ISOCHRONOUS type */ +} usb_desc_ep; + +typedef struct _usb_desc_LANGID { + usb_desc_header header; /*!< descriptor header, including type and size. */ + uint16_t wLANGID; /*!< LANGID code */ +} usb_desc_LANGID; + +typedef struct _usb_desc_str { + usb_desc_header header; /*!< descriptor header, including type and size. */ + uint16_t unicode_string[64]; /*!< unicode string data */ +} usb_desc_str; + +#pragma pack() + +/* compute string descriptor length */ +#define USB_STRING_LEN(unicode_chars) (sizeof(usb_desc_header) + ((unicode_chars) << 1U)) + +#endif /* __USB_CH9_STD_H */ diff --git a/bsp/gd32/libraries/GD32F10x_Firmware_Library/SConscript b/bsp/gd32/libraries/GD32F10x_Firmware_Library/SConscript new file mode 100644 index 0000000000..f5004445c0 --- /dev/null +++ b/bsp/gd32/libraries/GD32F10x_Firmware_Library/SConscript @@ -0,0 +1,60 @@ +import rtconfig +from building import * + +# get current directory +cwd = GetCurrentDir() + +# The set of source files associated with this SConscript file. + +src = Split(''' +CMSIS/GD/GD32F10x/Source/system_gd32f10x.c +GD32F10x_standard_peripheral/Source/gd32f10x_gpio.c +GD32F10x_standard_peripheral/Source/gd32f10x_rcu.c +GD32F10x_standard_peripheral/Source/gd32f10x_exti.c +GD32F10x_standard_peripheral/Source/gd32f10x_misc.c +''') + +if GetDepend(['RT_USING_SERIAL']): + src += ['GD32F10x_standard_peripheral/Source/gd32f10x_usart.c'] + +if GetDepend(['RT_USING_I2C']): + src += ['GD32F10x_standard_peripheral/Source/gd32f10x_i2c.c'] + +if GetDepend(['RT_USING_SPI']): + src += ['GD32F10x_standard_peripheral/Source/gd32f10x_spi.c'] + +if GetDepend(['RT_USING_CAN']): + src += ['GD32F10x_standard_peripheral/Source/gd32f10x_can.c'] + +if GetDepend(['BSP_USING_ETH']): + src += ['GD32F10x_standard_peripheral/Source/gd32f10x_enet.c'] + +if GetDepend(['RT_USING_ADC']): + src += ['GD32F10x_standard_peripheral/Source/gd32f10x_adc.c'] + +if GetDepend(['RT_USING_DAC']): + src += ['GD32F10x_standard_peripheral/Source/gd32f10x_dac.c'] + +if GetDepend(['RT_USING_HWTIMER']): + src += ['GD32F10x_standard_peripheral/Source/gd32f10x_timer.c'] + +if GetDepend(['RT_USING_RTC']): + src += ['GD32F10x_standard_peripheral/Source/gd32f10x_rtc.c'] + +if GetDepend(['RT_USING_WDT']): + src += ['GD32F10x_standard_peripheral/Source/gd32f10x_wwdgt.c'] + src += ['GD32F10x_standard_peripheral/Source/gd32f10x_fwdgt.c'] + +if GetDepend(['RT_USING_SDIO']): + src += ['GD32F10x_standard_peripheral/Source/gd32f10x_sdio.c'] + +path = [ + cwd + '/CMSIS/GD/GD32F10x/Include', + cwd + '/CMSIS', + cwd + '/GD32F10x_standard_peripheral/Include',] + +CPPDEFINES = ['USE_STDPERIPH_DRIVER'] + +group = DefineGroup('Libraries', src, depend = [''], CPPPATH = path, CPPDEFINES = CPPDEFINES) + +Return('group') diff --git a/bsp/gd32/libraries/GD32F20x_Firmware_Library/CMSIS/GD/GD32F20x/Include/gd32f20x.h b/bsp/gd32/libraries/GD32F20x_Firmware_Library/CMSIS/GD/GD32F20x/Include/gd32f20x.h new file mode 100644 index 0000000000..4929c455df --- /dev/null +++ b/bsp/gd32/libraries/GD32F20x_Firmware_Library/CMSIS/GD/GD32F20x/Include/gd32f20x.h @@ -0,0 +1,272 @@ +/*! + \file gd32f20x.h + \brief general definitions for GD32F20x + + \version 2015-07-15, V1.0.0, firmware for GD32F20x + \version 2017-06-05, V2.0.0, firmware for GD32F20x + \version 2018-10-31, V2.1.0, firmware for GD32F20x + \version 2020-09-30, V2.2.0, firmware for GD32F20x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef GD32F20X_H +#define GD32F20X_H + +#ifdef cplusplus + extern "C" { +#endif + +/* define GD32F20x */ +#if !defined (GD32F20X_CL) + #error "Please select first the target gd32f20x device used in your application (in gd32f20x.h file)" +#endif /* GD32F20X */ + +/* define value of high speed crystal oscillator (HXTAL) in Hz */ +#if !defined HXTAL_VALUE +#ifdef GD32F20X_CL +#define HXTAL_VALUE ((uint32_t)25000000) /*!< value of the external oscillator in Hz */ +#endif /* HXTAL_VALUE */ +#endif /* high speed crystal oscillator value */ + +/* define startup timeout value of high speed crystal oscillator (HXTAL) */ +#if !defined (HXTAL_STARTUP_TIMEOUT) +#define HXTAL_STARTUP_TIMEOUT ((uint16_t)0xFFFF) +#endif /* high speed crystal oscillator startup timeout */ + +/* define value of internal 8MHz RC oscillator (IRC8M) in Hz */ +#if !defined (IRC8M_VALUE) +#define IRC8M_VALUE ((uint32_t)8000000) +#endif /* internal 8MHz RC oscillator value */ + +/* define startup timeout value of internal 8MHz RC oscillator (IRC8M) */ +#if !defined (IRC8M_STARTUP_TIMEOUT) +#define IRC8M_STARTUP_TIMEOUT ((uint16_t)0x0500) +#endif /* internal 8MHz RC oscillator startup timeout */ + +/* define value of internal 40KHz RC oscillator(IRC40K) in Hz */ +#if !defined (IRC40K_VALUE) +#define IRC40K_VALUE ((uint32_t)40000) +#endif /* internal 40KHz RC oscillator value */ + +/* define value of low speed crystal oscillator (LXTAL)in Hz */ +#if !defined (LXTAL_VALUE) +#define LXTAL_VALUE ((uint32_t)32768) +#endif /* low speed crystal oscillator value */ + +/* GD32F20x firmware library version number V2.0 */ +#define __GD32F20x_STDPERIPH_VERSION_MAIN (0x01) /*!< [31:24] main version */ +#define __GD32F20x_STDPERIPH_VERSION_SUB1 (0x00) /*!< [23:16] sub1 version */ +#define __GD32F20x_STDPERIPH_VERSION_SUB2 (0x00) /*!< [15:8] sub2 version */ +#define __GD32F20x_STDPERIPH_VERSION_RC (0x00) /*!< [7:0] release candidate */ +#define __GD32F20x_STDPERIPH_VERSION ((__GD32F20x_STDPERIPH_VERSION_MAIN << 24)\ + |(__GD32F20x_STDPERIPH_VERSION_SUB1 << 16)\ + |(__GD32F20x_STDPERIPH_VERSION_SUB2 << 8)\ + |(__GD32F20x_STDPERIPH_VERSION_RC)) + +/* configuration of the Cortex-M3 processor and core peripherals */ +#define __MPU_PRESENT 0 /*!< GD32 devices does not provide an MPU */ +#define __NVIC_PRIO_BITS 4 /*!< GD32F20X uses 4 bits for the Priority levels */ +#define __VENDOR_SYSTICKCONFIG 0 /*!< set to 1 if different systick config is used */ + +/* define interrupt number */ +typedef enum IRQn +{ + /* Cortex-M3 processor exceptions numbers */ + NonMaskableInt_IRQn = -14, /*!< 2 non maskable interrupt */ + MemoryManagement_IRQn = -12, /*!< 4 Cortex-M3 memory management interrupt */ + BusFault_IRQn = -11, /*!< 5 Cortex-M3 bus fault interrupt */ + UsageFault_IRQn = -10, /*!< 6 Cortex-M3 usage fault interrupt */ + SVCall_IRQn = -5, /*!< 11 Cortex-M3 SV call interrupt */ + DebugMonitor_IRQn = -4, /*!< 12 Cortex-M3 debug monitor interrupt */ + PendSV_IRQn = -2, /*!< 14 Cortex-M3 pend SV interrupt */ + SysTick_IRQn = -1, /*!< 15 Cortex-M3 system tick interrupt */ + /* interruput numbers */ + WWDGT_IRQn = 0, /*!< WWDGT interrupt */ + LVD_IRQn = 1, /*!< LVD from EXTI line interrupt */ + TAMPER_IRQn = 2, /*!< tamper interrupt */ + RTC_IRQn = 3, /*!< RTC global interrupt */ + FMC_IRQn = 4, /*!< FMC global interrupt */ + RCU_IRQn = 5, /*!< RCU global interrupt */ + EXTI0_IRQn = 6, /*!< EXTI line0 interrupt */ + EXTI1_IRQn = 7, /*!< EXTI line1 interrupt */ + EXTI2_IRQn = 8, /*!< EXTI line2 interrupt */ + EXTI3_IRQn = 9, /*!< EXTI line3 interrupt */ + EXTI4_IRQn = 10, /*!< EXTI line4 interrupt */ + DMA0_Channel0_IRQn = 11, /*!< DMA0 channel 0 global interrupt */ + DMA0_Channel1_IRQn = 12, /*!< DMA0 channel 1 global interrupt */ + DMA0_Channel2_IRQn = 13, /*!< DMA0 channel 2 global interrupt */ + DMA0_Channel3_IRQn = 14, /*!< DMA0 channel 3 global interrupt */ + DMA0_Channel4_IRQn = 15, /*!< DMA0 channel 4 global interrupt */ + DMA0_Channel5_IRQn = 16, /*!< DMA0 channel 5 global interrupt */ + DMA0_Channel6_IRQn = 17, /*!< DMA0 channel 6 global interrupt */ + ADC0_1_IRQn = 18, /*!< ADC0 and ADC1 global interrupts */ + CAN0_TX_IRQn = 19, /*!< CAN0 TX interrupt */ + CAN0_RX0_IRQn = 20, /*!< CAN0 RX0 interrupt */ + CAN0_RX1_IRQn = 21, /*!< CAN0 RX1 interrupt */ + CAN0_EWMC_IRQn = 22, /*!< CAN0 EWMC interrupt */ + EXTI5_9_IRQn = 23, /*!< EXTI[9:5] interrupts */ + TIMER0_BRK_TIMER8_IRQn = 24, /*!< TIMER0 break interrupt and TIMER8 global interrupt */ + TIMER0_UP_TIMER9_IRQn = 25, /*!< TIMER0 update Interrupt and TIMER9 global interrupt */ + TIMER0_TRG_CMT_TIMER10_IRQn = 26, /*!< TIMER0 trigger and commutation interrupt and TIMER10 global interrupt */ + TIMER0_Channel_IRQn = 27, /*!< TIMER0 channel capture compare interrupt */ + TIMER1_IRQn = 28, /*!< TIMER1 global interrupt */ + TIMER2_IRQn = 29, /*!< TIMER2 global interrupt */ + TIMER3_IRQn = 30, /*!< TIMER3 global interrupt */ + I2C0_EV_IRQn = 31, /*!< I2C0 event interrupt */ + I2C0_ER_IRQn = 32, /*!< I2C0 error interrupt */ + I2C1_EV_IRQn = 33, /*!< I2C1 event interrupt */ + I2C1_ER_IRQn = 34, /*!< I2C1 error interrupt */ + SPI0_IRQn = 35, /*!< SPI0 global interrupt */ + SPI1_IRQn = 36, /*!< SPI1 global interrupt */ + USART0_IRQn = 37, /*!< USART0 global interrupt */ + USART1_IRQn = 38, /*!< USART1 global interrupt */ + USART2_IRQn = 39, /*!< USART2 global interrupt */ + EXTI10_15_IRQn = 40, /*!< EXTI[15:10] interrupts */ + RTC_Alarm_IRQn = 41, /*!< RTC alarm from EXTI line interrupt */ + USBFS_WKUP_IRQn = 42, /*!< USBFS wakeUp from EXTI line interrupt */ + TIMER7_BRK_TIMER11_IRQn = 43, /*!< TIMER7 break interrupt and TIMER11 global interrupt */ + TIMER7_UP_TIMER12_IRQn = 44, /*!< TIMER7 update interrupt and TIMER12 global interrupt */ + TIMER7_TRG_CMT_TIMER13_IRQn = 45, /*!< TIMER7 trigger and commutation interrupt and TIMER13 global interrupt */ + TIMER7_Channel_IRQn = 46, /*!< TIMER7 Channel Capture Compare Interrupt */ + ADC2_IRQn = 47, /*!< ADC2 global interrupt */ + EXMC_IRQn = 48, /*!< EXMC global interrupt */ + SDIO_IRQn = 49, /*!< SDIO global interrupt */ + TIMER4_IRQn = 50, /*!< TIMER4 global interrupt */ + SPI2_IRQn = 51, /*!< SPI2 global interrupt */ + UART3_IRQn = 52, /*!< UART3 global interrupt */ + UART4_IRQn = 53, /*!< UART4 global interrupt */ + TIMER5_IRQn = 54, /*!< TIMER5 global interrupt */ + TIMER6_IRQn = 55, /*!< TIMER6 global interrupt */ + DMA1_Channel0_IRQn = 56, /*!< DMA1 Channel 0 global interrupt */ + DMA1_Channel1_IRQn = 57, /*!< DMA1 Channel 1 global interrupt */ + DMA1_Channel2_IRQn = 58, /*!< DMA1 Channel 2 global interrupt */ + DMA1_Channel3_IRQn = 59, /*!< DMA1 Channel 3 global interrupt */ + DMA1_Channel4_IRQn = 60, /*!< DMA1 Channel 4 global interrupt */ + ENET_IRQn = 61, /*!< ENET global interrupt */ + ENET_WKUP_IRQn = 62, /*!< ENET wakeup through EXTI line interrupt */ + CAN1_TX_IRQn = 63, /*!< CAN1 TX interrupt */ + CAN1_RX0_IRQn = 64, /*!< CAN1 RX0 interrupt */ + CAN1_RX1_IRQn = 65, /*!< CAN1 RX1 interrupt */ + CAN1_EWMC_IRQn = 66, /*!< CAN1 EWMC interrupt */ + USBFS_IRQn = 67, /*!< USBFS global interrupt */ + DMA1_Channel5_IRQn = 69, /*!< DMA1 Channel 5 global interrupt */ + DMA1_Channel6_IRQn = 70, /*!< DMA1 Channel 6 global interrupt */ + USART5_IRQn = 71, /*!< USART5 global interrupt */ + I2C2_EV_IRQn = 72, /*!< I2C2 event interrupt */ + I2C2_ER_IRQn = 73, /*!< I2C2 error interrupt */ + DCI_IRQn = 78, /*!< DCI global interrupt */ + CAU_IRQn = 79, /*!< CAU global interrupt */ + HAU_TRNG_IRQn = 80, /*!< HAU or TRNG global interrupt */ + UART6_IRQn = 82, /*!< UART6 global interrupt */ + UART7_IRQn = 83, /*!< UART7 global interrupt */ + TLI_IRQn = 88, /*!< TLI global interrupt */ + TLI_ER_IRQn = 89 /*!< TLI global error interrupt */ +} IRQn_Type; + +/* includes */ +#include "core_cm3.h" +#include "system_gd32f20x.h" +#include + +/* enum definitions */ +typedef enum {DISABLE = 0, ENABLE = !DISABLE} EventStatus, ControlStatus; +typedef enum {FALSE = 0, TRUE = !FALSE} bool; +typedef enum {RESET = 0, SET = !RESET} FlagStatus; +typedef enum {ERROR = 0, SUCCESS = !ERROR} ErrStatus; + +/* bit operations */ +#define REG32(addr) (*(volatile uint32_t *)(uint32_t)(addr)) +#define REG16(addr) (*(volatile uint16_t *)(uint32_t)(addr)) +#define REG8(addr) (*(volatile uint8_t *)(uint32_t)(addr)) +#define BIT(x) ((uint32_t)((uint32_t)0x01U<<(x))) +#define BITS(start, end) ((0xFFFFFFFFUL << (start)) & (0xFFFFFFFFUL >> (31U - (uint32_t)(end)))) +#define GET_BITS(regval, start, end) (((regval) & BITS((start),(end))) >> (start)) + +/* main flash and SRAM memory map */ +#define FLASH_BASE ((uint32_t)0x08000000U) /*!< main FLASH base address */ +#define SRAM_BASE ((uint32_t)0x20000000U) /*!< SRAM base address */ +#define OB_BASE ((uint32_t)0x1FFFF800U) /*!< OB base address */ +#define SRAM_BB_BASE ((uint32_t)0x22000000) /*!< SRAM base address in the bit-band region */ +#define PERIPH_BB_BASE ((uint32_t)0x42000000) /*!< Peripheral base address in the bit-band region */ +#define DBG_BASE ((uint32_t)0xE0042000U) /*!< DBG base address */ +#define EXMC_BASE ((uint32_t)0xA0000000U) /*!< EXMC register base address */ + +/* peripheral memory map */ +#define APB1_BUS_BASE ((uint32_t)0x40000000U) /*!< apb1 base address */ +#define APB2_BUS_BASE ((uint32_t)0x40010000U) /*!< apb2 base address */ +#define AHB1_BUS_BASE ((uint32_t)0x40018000U) /*!< ahb1 base address */ +#define AHB2_BUS_BASE ((uint32_t)0x50000000U) /*!< ahb2 base address */ + +/* advanced peripheral bus 1 memory map */ +#define TIMER_BASE (APB1_BUS_BASE + 0x00000000U) /*!< TIMER base address */ +#define RTC_BASE (APB1_BUS_BASE + 0x00002800U) /*!< RTC base address */ +#define WWDGT_BASE (APB1_BUS_BASE + 0x00002C00U) /*!< WWDGT base address */ +#define FWDGT_BASE (APB1_BUS_BASE + 0x00003000U) /*!< FWDGT base address */ +#define SPI_BASE (APB1_BUS_BASE + 0x00003800U) /*!< SPI base address */ +#define USART_BASE (APB1_BUS_BASE + 0x00004400U) /*!< USART base address */ +#define I2C_BASE (APB1_BUS_BASE + 0x00005400U) /*!< I2C base address */ +#define CAN_BASE (APB1_BUS_BASE + 0x00006400U) /*!< CAN base address */ +#define BKP_BASE (APB1_BUS_BASE + 0x00006C00U) /*!< BKP base address */ +#define PMU_BASE (APB1_BUS_BASE + 0x00007000U) /*!< PMU base address */ +#define DAC_BASE (APB1_BUS_BASE + 0x00007400U) /*!< DAC base address */ + +/* advanced peripheral bus 2 memory map */ +#define AFIO_BASE (APB2_BUS_BASE + 0x00000000U) /*!< AFIO base address */ +#define EXTI_BASE (APB2_BUS_BASE + 0x00000400U) /*!< EXTI base address */ +#define GPIO_BASE (APB2_BUS_BASE + 0x00000800U) /*!< GPIO base address */ +#define ADC_BASE (APB2_BUS_BASE + 0x00002400U) /*!< ADC base address */ +#define TLI_BASE (APB2_BUS_BASE + 0x00006800U) /*!< TLI base address */ + +/* advanced high performance bus 1 memory map */ +#define SDIO_BASE (AHB1_BUS_BASE + 0x00000000U) /*!< SDIO base address */ +#define DMA_BASE (AHB1_BUS_BASE + 0x00008000U) /*!< DMA base address */ +#define RCU_BASE (AHB1_BUS_BASE + 0x00009000U) /*!< RCU base address */ +#define FMC_BASE (AHB1_BUS_BASE + 0x0000A000U) /*!< FMC base address */ +#define CRC_BASE (AHB1_BUS_BASE + 0x0000B000U) /*!< CRC base address */ +#define ENET_BASE (AHB1_BUS_BASE + 0x00010000U) /*!< ENET base address */ + +/* advanced high performance bus 2 memory map */ +#define USBFS_BASE (AHB2_BUS_BASE + 0x00000000U) /*!< USBFS base address */ +#define DCI_BASE (AHB2_BUS_BASE + 0x00050000U) /*!< DCI base address */ +#define CAU_BASE (AHB2_BUS_BASE + 0x00060000U) /*!< CAU base address */ +#define HAU_BASE (AHB2_BUS_BASE + 0x00060400U) /*!< HAU base address */ +#define TRNG_BASE (AHB2_BUS_BASE + 0x00060800U) /*!< TRNG base address */ + +/* define marco USE_STDPERIPH_DRIVER */ +#if !defined USE_STDPERIPH_DRIVER +#define USE_STDPERIPH_DRIVER +#endif +#ifdef USE_STDPERIPH_DRIVER +#include "gd32f20x_libopt.h" +#endif /* USE_STDPERIPH_DRIVER */ + +#ifdef cplusplus +} +#endif +#endif diff --git a/bsp/gd32/libraries/GD32F20x_Firmware_Library/CMSIS/GD/GD32F20x/Include/system_gd32f20x.h b/bsp/gd32/libraries/GD32F20x_Firmware_Library/CMSIS/GD/GD32F20x/Include/system_gd32f20x.h new file mode 100644 index 0000000000..6550880290 --- /dev/null +++ b/bsp/gd32/libraries/GD32F20x_Firmware_Library/CMSIS/GD/GD32F20x/Include/system_gd32f20x.h @@ -0,0 +1,58 @@ +/*! + \file system_gd32f20x.h + \brief CMSIS Cortex-M3 Device Peripheral Access Layer Header File for + GD32F20x Device Series +*/ + +/* Copyright (c) 2012 ARM LIMITED + + All rights reserved. + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + - Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + - Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + - Neither the name of ARM nor the names of its contributors may be used + to endorse or promote products derived from this software without + specific prior written permission. + * + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDERS AND CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + ---------------------------------------------------------------------------*/ + +/* This file refers the CMSIS standard, some adjustments are made according to GigaDevice chips */ + +#ifndef SYSTEM_GD32F20X_H +#define SYSTEM_GD32F20X_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include + +/* system clock frequency (core clock) */ +extern uint32_t SystemCoreClock; + +/* function declarations */ +/* initialize the system and update the SystemCoreClock variable */ +extern void SystemInit (void); +/* update the SystemCoreClock with current core clock retrieved from cpu registers */ +extern void SystemCoreClockUpdate (void); + +#ifdef __cplusplus +} +#endif + +#endif /* SYSTEM_GD32F20X_H */ diff --git a/bsp/gd32/libraries/GD32F20x_Firmware_Library/CMSIS/GD/GD32F20x/Source/ARM/startup_gd32f20x_cl.s b/bsp/gd32/libraries/GD32F20x_Firmware_Library/CMSIS/GD/GD32F20x/Source/ARM/startup_gd32f20x_cl.s new file mode 100644 index 0000000000..5b3128e8e2 --- /dev/null +++ b/bsp/gd32/libraries/GD32F20x_Firmware_Library/CMSIS/GD/GD32F20x/Source/ARM/startup_gd32f20x_cl.s @@ -0,0 +1,436 @@ +;/*! +; \file startup_gd32f20x_cl.s +; \brief start up file + +; \version 2015-07-15, V1.0.0, firmware for GD32F20x +; \version 2017-06-05, V2.0.0, firmware for GD32F20x +; \version 2018-10-31, V2.1.0, firmware for GD32F20x +; \version 2020-09-30, V2.2.0, firmware for GD32F20x +;*/ + +;/* +; Copyright (c) 2020, GigaDevice Semiconductor Inc. + +; Redistribution and use in source and binary forms, with or without modification, +;are permitted provided that the following conditions are met: + +; 1. Redistributions of source code must retain the above copyright notice, this +; list of conditions and the following disclaimer. +; 2. Redistributions in binary form must reproduce the above copyright notice, +; this list of conditions and the following disclaimer in the documentation +; and/or other materials provided with the distribution. +; 3. Neither the name of the copyright holder nor the names of its contributors +; may be used to endorse or promote products derived from this software without +; specific prior written permission. + +; THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +;AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +;WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +;IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +;INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +;NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +;PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +;WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +;ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +;OF SUCH DAMAGE. +;*/ + +; Stack Configuration +; Stack Size (in Bytes) <0x0-0xFFFFFFFF:8> +; + +Stack_Size EQU 0x00002000 + + AREA STACK, NOINIT, READWRITE, ALIGN = 3 +Stack_Mem SPACE Stack_Size +__initial_sp + + +; Heap Configuration +; Heap Size (in Bytes) <0x0-0xFFFFFFFF:8> +; + +Heap_Size EQU 0x00002000 + + AREA HEAP, NOINIT, READWRITE, ALIGN = 3 +__heap_base +Heap_Mem SPACE Heap_Size +__heap_limit + + + PRESERVE8 + THUMB + +; /* reset Vector Mapped to at Address 0 */ + AREA RESET, DATA, READONLY + EXPORT __Vectors + EXPORT __Vectors_End + EXPORT __Vectors_Size + +__Vectors DCD __initial_sp ; Top of Stack + DCD Reset_Handler ; Reset Handler + DCD NMI_Handler ; NMI Handler + DCD HardFault_Handler ; Hard Fault Handler + DCD MemManage_Handler ; MPU Fault Handler + DCD BusFault_Handler ; Bus Fault Handler + DCD UsageFault_Handler ; Usage Fault Handler + DCD 0 ; Reserved + DCD 0 ; Reserved + DCD 0 ; Reserved + DCD 0 ; Reserved + DCD SVC_Handler ; SVCall Handler + DCD DebugMon_Handler ; Debug Monitor Handler + DCD 0 ; Reserved + DCD PendSV_Handler ; PendSV Handler + DCD SysTick_Handler ; SysTick Handler + +; /* external interrupts handler */ + DCD WWDGT_IRQHandler ; 16:Window Watchdog Timer + DCD LVD_IRQHandler ; 17:LVD through EXTI Line detect + DCD TAMPER_IRQHandler ; 18:Tamper Interrupt + DCD RTC_IRQHandler ; 19:RTC through EXTI Line + DCD FMC_IRQHandler ; 20:FMC + DCD RCU_IRQHandler ; 21:RCU + DCD EXTI0_IRQHandler ; 22:EXTI Line 0 + DCD EXTI1_IRQHandler ; 23:EXTI Line 1 + DCD EXTI2_IRQHandler ; 24:EXTI Line 2 + DCD EXTI3_IRQHandler ; 25:EXTI Line 3 + DCD EXTI4_IRQHandler ; 26:EXTI Line 4 + DCD DMA0_Channel0_IRQHandler ; 27:DMA0 Channel 0 + DCD DMA0_Channel1_IRQHandler ; 28:DMA0 Channel 1 + DCD DMA0_Channel2_IRQHandler ; 29:DMA0 Channel 2 + DCD DMA0_Channel3_IRQHandler ; 30:DMA0 Channel 3 + DCD DMA0_Channel4_IRQHandler ; 31:DMA0 Channel 4 + DCD DMA0_Channel5_IRQHandler ; 32:DMA0 Channel 5 + DCD DMA0_Channel6_IRQHandler ; 33:DMA0 Channel 6 + DCD ADC0_1_IRQHandler ; 34:ADC0 and ADC1 + DCD CAN0_TX_IRQHandler ; 35:CAN0 TX + DCD CAN0_RX0_IRQHandler ; 36:CAN0 RX0 + DCD CAN0_RX1_IRQHandler ; 37:CAN0 RX1 + DCD CAN0_EWMC_IRQHandler ; 38:CAN0 EWMC + DCD EXTI5_9_IRQHandler ; 39:EXTI Line 5 to EXTI Line 9 + DCD TIMER0_BRK_TIMER8_IRQHandler ; 40:TIMER0 Break and TIMER8 global + DCD TIMER0_UP_TIMER9_IRQHandler ; 41:TIMER0 Update and TIMER9 global + DCD TIMER0_TRG_CMT_TIMER10_IRQHandler ; 42:TIMER0 Trigger and Commutation and TIMER10 global + DCD TIMER0_Channel_IRQHandler ; 43:TIMER0 Channel Capture Compare + DCD TIMER1_IRQHandler ; 44:TIMER1 + DCD TIMER2_IRQHandler ; 45:TIMER2 + DCD TIMER3_IRQHandler ; 46:TIMER3 + DCD I2C0_EV_IRQHandler ; 47:I2C0 Event + DCD I2C0_ER_IRQHandler ; 48:I2C0 Error + DCD I2C1_EV_IRQHandler ; 49:I2C1 Event + DCD I2C1_ER_IRQHandler ; 50:I2C1 Error + DCD SPI0_IRQHandler ; 51:SPI0 + DCD SPI1_IRQHandler ; 52:SPI1 + DCD USART0_IRQHandler ; 53:USART0 + DCD USART1_IRQHandler ; 54:USART1 + DCD USART2_IRQHandler ; 55:USART2 + DCD EXTI10_15_IRQHandler ; 56:EXTI Line 10 to EXTI Line 15 + DCD RTC_Alarm_IRQHandler ; 57:RTC Alarm through EXTI Line + DCD USBFS_WKUP_IRQHandler ; 58:USBFS WakeUp from suspend through EXTI Line + DCD TIMER7_BRK_TIMER11_IRQHandler ; 59:TIMER7 Break Interrupt and TIMER11 global + DCD TIMER7_UP_TIMER12_IRQHandler ; 60:TIMER7 Update Interrupt and TIMER12 global + DCD TIMER7_TRG_CMT_TIMER13_IRQHandler ; 61:TIMER7 Trigger and Commutation Interrupt and TIMER13 + DCD TIMER7_Channel_IRQHandler ; 62:TIMER7 Channel Capture Compare + DCD ADC2_IRQHandler ; 63:ADC2 + DCD EXMC_IRQHandler ; 64:EXMC + DCD SDIO_IRQHandler ; 65:SDIO + DCD TIMER4_IRQHandler ; 66:TIMER4 + DCD SPI2_IRQHandler ; 67:SPI2 + DCD UART3_IRQHandler ; 68:UART3 + DCD UART4_IRQHandler ; 69:UART4 + DCD TIMER5_IRQHandler ; 70:TIMER5 + DCD TIMER6_IRQHandler ; 71:TIMER6 + DCD DMA1_Channel0_IRQHandler ; 72:DMA1 Channel0 + DCD DMA1_Channel1_IRQHandler ; 73:DMA1 Channel1 + DCD DMA1_Channel2_IRQHandler ; 74:DMA1 Channel2 + DCD DMA1_Channel3_IRQHandler ; 75:DMA1 Channel3 + DCD DMA1_Channel4_IRQHandler ; 76:DMA1 Channel4 + DCD ENET_IRQHandler ; 77:Ethernet + DCD ENET_WKUP_IRQHandler ; 78:Ethernet Wakeup through EXTI line + DCD CAN1_TX_IRQHandler ; 79:CAN1 TX + DCD CAN1_RX0_IRQHandler ; 80:CAN1 RX0 + DCD CAN1_RX1_IRQHandler ; 81:CAN1 RX1 + DCD CAN1_EWMC_IRQHandler ; 82:CAN1 EWMC + DCD USBFS_IRQHandler ; 83:USBFS + DCD 0 ; 84:Reserved + DCD DMA1_Channel5_IRQHandler ; 85:DMA1 Channel5 + DCD DMA1_Channel6_IRQHandler ; 86:DMA1 Channel6 + DCD USART5_IRQHandler ; 87:USART5 + DCD I2C2_EV_IRQHandler ; 88:I2C2 Event + DCD I2C2_ER_IRQHandler ; 89:I2C2 Error + DCD 0 ; 90:Reserved + DCD 0 ; 91:Reserved + DCD 0 ; 92:Reserved + DCD 0 ; 93:Reserved + DCD DCI_IRQHandler ; 94:DCI + DCD CAU_IRQHandler ; 95:CAU + DCD HAU_TRNG_IRQHandler ; 96:HAU and TRNG + DCD 0 ; 97:Reserved + DCD UART6_IRQHandler ; 98:UART6 + DCD UART7_IRQHandler ; 99:UART7 + DCD 0 ; 100:Reserved + DCD 0 ; 101:Reserved + DCD 0 ; 102:Reserved + DCD 0 ; 103:Reserved + DCD TLI_IRQHandler ; 104:TLI + DCD TLI_ER_IRQHandler ; 105:TLI error +__Vectors_End + +__Vectors_Size EQU __Vectors_End - __Vectors + + AREA |.text|, CODE, READONLY + +;/* reset Handler */ +Reset_Handler PROC + EXPORT Reset_Handler [WEAK] + IMPORT __main + IMPORT SystemInit + LDR R0, =SystemInit + BLX R0 + LDR R0, =__main + BX R0 + ENDP + +;/* dummy Exception Handlers */ +NMI_Handler PROC + EXPORT NMI_Handler [WEAK] + B . + ENDP + +HardFault_Handler PROC + EXPORT HardFault_Handler [WEAK] + B . + ENDP + +MemManage_Handler PROC + EXPORT MemManage_Handler [WEAK] + B . + ENDP + +BusFault_Handler PROC + EXPORT BusFault_Handler [WEAK] + B . + ENDP + +UsageFault_Handler PROC + EXPORT UsageFault_Handler [WEAK] + B . + ENDP + +SVC_Handler PROC + EXPORT SVC_Handler [WEAK] + B . + ENDP + +DebugMon_Handler PROC + EXPORT DebugMon_Handler [WEAK] + B . + ENDP + +PendSV_Handler PROC + EXPORT PendSV_Handler [WEAK] + B . + ENDP + +SysTick_Handler PROC + EXPORT SysTick_Handler [WEAK] + B . + ENDP + +Default_Handler PROC +; /* external interrupts handler */ + EXPORT WWDGT_IRQHandler [WEAK] + EXPORT LVD_IRQHandler [WEAK] + EXPORT TAMPER_IRQHandler [WEAK] + EXPORT RTC_IRQHandler [WEAK] + EXPORT FMC_IRQHandler [WEAK] + EXPORT RCU_IRQHandler [WEAK] + EXPORT EXTI0_IRQHandler [WEAK] + EXPORT EXTI1_IRQHandler [WEAK] + EXPORT EXTI2_IRQHandler [WEAK] + EXPORT EXTI3_IRQHandler [WEAK] + EXPORT EXTI4_IRQHandler [WEAK] + EXPORT DMA0_Channel0_IRQHandler [WEAK] + EXPORT DMA0_Channel1_IRQHandler [WEAK] + EXPORT DMA0_Channel2_IRQHandler [WEAK] + EXPORT DMA0_Channel3_IRQHandler [WEAK] + EXPORT DMA0_Channel4_IRQHandler [WEAK] + EXPORT DMA0_Channel5_IRQHandler [WEAK] + EXPORT DMA0_Channel6_IRQHandler [WEAK] + EXPORT ADC0_1_IRQHandler [WEAK] + EXPORT CAN0_TX_IRQHandler [WEAK] + EXPORT CAN0_RX0_IRQHandler [WEAK] + EXPORT CAN0_RX1_IRQHandler [WEAK] + EXPORT CAN0_EWMC_IRQHandler [WEAK] + EXPORT EXTI5_9_IRQHandler [WEAK] + EXPORT TIMER0_BRK_TIMER8_IRQHandler [WEAK] + EXPORT TIMER0_UP_TIMER9_IRQHandler [WEAK] + EXPORT TIMER0_TRG_CMT_TIMER10_IRQHandler [WEAK] + EXPORT TIMER0_Channel_IRQHandler [WEAK] + EXPORT TIMER1_IRQHandler [WEAK] + EXPORT TIMER2_IRQHandler [WEAK] + EXPORT TIMER3_IRQHandler [WEAK] + EXPORT I2C0_EV_IRQHandler [WEAK] + EXPORT I2C0_ER_IRQHandler [WEAK] + EXPORT I2C1_EV_IRQHandler [WEAK] + EXPORT I2C1_ER_IRQHandler [WEAK] + EXPORT SPI0_IRQHandler [WEAK] + EXPORT SPI1_IRQHandler [WEAK] + EXPORT USART0_IRQHandler [WEAK] + EXPORT USART1_IRQHandler [WEAK] + EXPORT USART2_IRQHandler [WEAK] + EXPORT EXTI10_15_IRQHandler [WEAK] + EXPORT RTC_Alarm_IRQHandler [WEAK] + EXPORT USBFS_WKUP_IRQHandler [WEAK] + EXPORT TIMER7_BRK_TIMER11_IRQHandler [WEAK] + EXPORT TIMER7_UP_TIMER12_IRQHandler [WEAK] + EXPORT TIMER7_TRG_CMT_TIMER13_IRQHandler [WEAK] + EXPORT TIMER7_Channel_IRQHandler [WEAK] + EXPORT ADC2_IRQHandler [WEAK] + EXPORT EXMC_IRQHandler [WEAK] + EXPORT SDIO_IRQHandler [WEAK] + EXPORT TIMER4_IRQHandler [WEAK] + EXPORT SPI2_IRQHandler [WEAK] + EXPORT UART3_IRQHandler [WEAK] + EXPORT UART4_IRQHandler [WEAK] + EXPORT TIMER5_IRQHandler [WEAK] + EXPORT TIMER6_IRQHandler [WEAK] + EXPORT DMA1_Channel0_IRQHandler [WEAK] + EXPORT DMA1_Channel1_IRQHandler [WEAK] + EXPORT DMA1_Channel2_IRQHandler [WEAK] + EXPORT DMA1_Channel3_IRQHandler [WEAK] + EXPORT DMA1_Channel4_IRQHandler [WEAK] + EXPORT ENET_IRQHandler [WEAK] + EXPORT ENET_WKUP_IRQHandler [WEAK] + EXPORT CAN1_TX_IRQHandler [WEAK] + EXPORT CAN1_RX0_IRQHandler [WEAK] + EXPORT CAN1_RX1_IRQHandler [WEAK] + EXPORT CAN1_EWMC_IRQHandler [WEAK] + EXPORT USBFS_IRQHandler [WEAK] + EXPORT DMA1_Channel5_IRQHandler [WEAK] + EXPORT DMA1_Channel6_IRQHandler [WEAK] + EXPORT USART5_IRQHandler [WEAK] + EXPORT I2C2_EV_IRQHandler [WEAK] + EXPORT I2C2_ER_IRQHandler [WEAK] + EXPORT DCI_IRQHandler [WEAK] + EXPORT CAU_IRQHandler [WEAK] + EXPORT HAU_TRNG_IRQHandler [WEAK] + EXPORT UART6_IRQHandler [WEAK] + EXPORT UART7_IRQHandler [WEAK] + EXPORT TLI_IRQHandler [WEAK] + EXPORT TLI_ER_IRQHandler [WEAK] + +;/* external interrupts handler */ +WWDGT_IRQHandler +LVD_IRQHandler +TAMPER_IRQHandler +RTC_IRQHandler +FMC_IRQHandler +RCU_IRQHandler +EXTI0_IRQHandler +EXTI1_IRQHandler +EXTI2_IRQHandler +EXTI3_IRQHandler +EXTI4_IRQHandler +DMA0_Channel0_IRQHandler +DMA0_Channel1_IRQHandler +DMA0_Channel2_IRQHandler +DMA0_Channel3_IRQHandler +DMA0_Channel4_IRQHandler +DMA0_Channel5_IRQHandler +DMA0_Channel6_IRQHandler +ADC0_1_IRQHandler +CAN0_TX_IRQHandler +CAN0_RX0_IRQHandler +CAN0_RX1_IRQHandler +CAN0_EWMC_IRQHandler +EXTI5_9_IRQHandler +TIMER0_BRK_TIMER8_IRQHandler +TIMER0_UP_TIMER9_IRQHandler +TIMER0_TRG_CMT_TIMER10_IRQHandler +TIMER0_Channel_IRQHandler +TIMER1_IRQHandler +TIMER2_IRQHandler +TIMER3_IRQHandler +I2C0_EV_IRQHandler +I2C0_ER_IRQHandler +I2C1_EV_IRQHandler +I2C1_ER_IRQHandler +SPI0_IRQHandler +SPI1_IRQHandler +USART0_IRQHandler +USART1_IRQHandler +USART2_IRQHandler +EXTI10_15_IRQHandler +RTC_Alarm_IRQHandler +USBFS_WKUP_IRQHandler +TIMER7_BRK_TIMER11_IRQHandler +TIMER7_UP_TIMER12_IRQHandler +TIMER7_TRG_CMT_TIMER13_IRQHandler +TIMER7_Channel_IRQHandler +ADC2_IRQHandler +EXMC_IRQHandler +SDIO_IRQHandler +TIMER4_IRQHandler +SPI2_IRQHandler +UART3_IRQHandler +UART4_IRQHandler +TIMER5_IRQHandler +TIMER6_IRQHandler +DMA1_Channel0_IRQHandler +DMA1_Channel1_IRQHandler +DMA1_Channel2_IRQHandler +DMA1_Channel3_IRQHandler +DMA1_Channel4_IRQHandler +ENET_IRQHandler +ENET_WKUP_IRQHandler +CAN1_TX_IRQHandler +CAN1_RX0_IRQHandler +CAN1_RX1_IRQHandler +CAN1_EWMC_IRQHandler +USBFS_IRQHandler +DMA1_Channel5_IRQHandler +DMA1_Channel6_IRQHandler +USART5_IRQHandler +I2C2_EV_IRQHandler +I2C2_ER_IRQHandler +DCI_IRQHandler +CAU_IRQHandler +HAU_TRNG_IRQHandler +UART6_IRQHandler +UART7_IRQHandler +TLI_IRQHandler +TLI_ER_IRQHandler + + B . + ENDP + + ALIGN + +; user Initial Stack & Heap + + IF :DEF:__MICROLIB + + EXPORT __initial_sp + EXPORT __heap_base + EXPORT __heap_limit + + ELSE + + IMPORT __use_two_region_memory + EXPORT __user_initial_stackheap + +__user_initial_stackheap PROC + LDR R0, = Heap_Mem + LDR R1, =(Stack_Mem + Stack_Size) + LDR R2, = (Heap_Mem + Heap_Size) + LDR R3, = Stack_Mem + BX LR + ENDP + + ALIGN + + ENDIF + + END diff --git a/bsp/gd32/libraries/GD32F20x_Firmware_Library/CMSIS/GD/GD32F20x/Source/GCC/startup_gd32f20x_cl.s b/bsp/gd32/libraries/GD32F20x_Firmware_Library/CMSIS/GD/GD32F20x/Source/GCC/startup_gd32f20x_cl.s new file mode 100644 index 0000000000..c03d09f026 --- /dev/null +++ b/bsp/gd32/libraries/GD32F20x_Firmware_Library/CMSIS/GD/GD32F20x/Source/GCC/startup_gd32f20x_cl.s @@ -0,0 +1,307 @@ +;/* +; * Copyright (c) 2006-2021, RT-Thread Development Team +; * +; * SPDX-License-Identifier: Apache-2.0 +; * +; * Change Logs: +; * Date Author Notes +; * 2021-12-18 BruceOu first implementation +; */ + +.syntax unified +.cpu cortex-m3 +.fpu softvfp +.thumb + +.global g_pfnVectors +.global Default_Handler + + .section .isr_vector,"a",%progbits + .type g_pfnVectors, %object + +g_pfnVectors: + .word _estack // Top of Stack + .word Reset_Handler // Reset Handler + .word NMI_Handler // NMI Handler + .word HardFault_Handler // Hard Fault Handler + .word MemManage_Handler // MPU Fault Handler + .word BusFault_Handler // Bus Fault Handler + .word UsageFault_Handler // Usage Fault Handler + .word 0 // Reserved + .word 0 // Reserved + .word 0 // Reserved + .word 0 // Reserved + .word SVC_Handler // SVCall Handler + .word DebugMon_Handler // Debug Monitor Handler + .word 0 // Reserved + .word PendSV_Handler // PendSV Handler + .word SysTick_Handler // SysTick Handler + + // external interrupts handler + .word WWDGT_IRQHandler // 16:Window Watchdog Timer + .word LVD_IRQHandler // 17:LVD through EXTI Line detect + .word TAMPER_IRQHandler // 18:Tamper through EXTI Line detect + .word RTC_IRQHandler // 19:RTC through EXTI Line + .word FMC_IRQHandler // 20:FMC + .word RCU_CTC_IRQHandler // 21:RCU and CTC + .word EXTI0_IRQHandler // 22:EXTI Line 0 + .word EXTI1_IRQHandler // 23:EXTI Line 1 + .word EXTI2_IRQHandler // 24:EXTI Line 2 + .word EXTI3_IRQHandler // 25:EXTI Line 3 + .word EXTI4_IRQHandler // 26:EXTI Line 4 + .word DMA0_Channel0_IRQHandler // 27:DMA0 Channel0 + .word DMA0_Channel1_IRQHandler // 28:DMA0 Channel1 + .word DMA0_Channel2_IRQHandler // 29:DMA0 Channel2 + .word DMA0_Channel3_IRQHandler // 30:DMA0 Channel3 + .word DMA0_Channel4_IRQHandler // 31:DMA0 Channel4 + .word DMA0_Channel5_IRQHandler // 32:DMA0 Channel5 + .word DMA0_Channel6_IRQHandler // 33:DMA0 Channel6 + .word ADC0_1_IRQHandler // 34:ADC0 and ADC1 + .word CAN0_TX_IRQHandler // 35:CAN0 TX + .word CAN0_RX0_IRQHandler // 36:CAN0 RX0 + .word CAN0_RX1_IRQHandler // 37:CAN0 RX1 + .word CAN0_EWMC_IRQHandler // 38:CAN0 EWMC + .word EXTI5_9_IRQHandler // 39:EXTI Line 5 to EXTI Line 9 + .word TIMER0_BRK_TIMER8_IRQHandler // 40:TIMER0 Break and TIMER8 global + .word TIMER0_UP_TIMER9_IRQHandler // 41:TIMER0 Update and TIMER9 global + .word TIMER0_TRG_CMT_TIMER10_IRQHandler // 42:TIMER0 Trigger and Commutation and TIMER10 global + .word TIMER0_Channel_IRQHandler // 43:TIMER0 Channel Capture Compare + .word TIMER1_IRQHandler // 44:TIMER1 + .word TIMER2_IRQHandler // 45:TIMER2 + .word TIMER3_IRQHandler // 46:TIMER3 + .word I2C0_EV_IRQHandler // 47:I2C0 Event + .word I2C0_ER_IRQHandler // 48:I2C0 Error + .word I2C1_EV_IRQHandler // 49:I2C1 Event + .word I2C1_ER_IRQHandler // 50:I2C1 Error + .word SPI0_IRQHandler // 51:SPI0 + .word SPI1_IRQHandler // 52:SPI1 + .word USART0_IRQHandler // 53:USART0 + .word USART1_IRQHandler // 54:USART1 + .word USART2_IRQHandler // 55:USART2 + .word EXTI10_15_IRQHandler // 56:EXTI10 to EXTI15 + .word RTC_Alarm_IRQHandler // 57:RTC Alarm + .word USBFS_WKUP_IRQHandler // 58:USBFS WakeUp from suspend through EXTI Line + .word TIMER7_BRK_TIMER11_IRQHandler // 59:TIMER7 Break Interrupt and TIMER11 global + .word TIMER7_UP_TIMER12_IRQHandler // 60:TIMER7 Update Interrupt and TIMER12 global + .word TIMER7_TRG_CMT_TIMER13_IRQHandler // 61:TIMER7 Trigger and Commutation Interrupt and TIMER13 + .word TIMER7_Channel_IRQHandler // 62:TIMER7 Channel Capture Compare + .word ADC2_IRQHandler // 63:ADC2 + .word EXMC_IRQHandler // 64:EXMC + .word SDIO_IRQHandler // 65:SDIO + .word TIMER4_IRQHandler // 66:TIMER4 + .word SPI2_IRQHandler // 67:SPI2 + .word UART3_IRQHandler // 68:UART3 + .word UART4_IRQHandler // 69:UART4 + .word TIMER5_IRQHandler // 70:TIMER5 + .word TIMER6_IRQHandler // 71:TIMER6 + .word DMA1_Channel0_IRQHandler // 72:DMA1 Channel0 + .word DMA1_Channel1_IRQHandler // 73:DMA1 Channel1 + .word DMA1_Channel2_IRQHandler // 74:DMA1 Channel2 + .word DMA1_Channel3_IRQHandler // 75:DMA1 Channel3 + .word DMA1_Channel4_IRQHandler // 76:DMA1 Channel4 + .word ENET_IRQHandler // 77:Ethernet + .word ENET_WKUP_IRQHandler // 78:Ethernet Wakeup through EXTI Line + .word CAN1_TX_IRQHandler // 79:CAN1 TX + .word CAN1_RX0_IRQHandler // 80:CAN1 RX0 + .word CAN1_RX1_IRQHandler // 81:CAN1 RX1 + .word CAN1_EWMC_IRQHandler // 82:CAN1 EWMC + .word USBFS_IRQHandler // 83:USBFS + .word 0 // 84:Reserved + .word DMA1_Channel5_IRQHandler // 85:DMA1 Channel5 + .word DMA1_Channel6_IRQHandler // 86:DMA1 Channel6 + .word USART5_IRQHandler // 87:USART5 + .word I2C2_EV_IRQHandler // 88:I2C2 Event + .word I2C2_ER_IRQHandler // 89:I2C2 Error + .word 0 // 90:Reserved + .word 0 // 91:Reserved + .word 0 // 92:Reserved + .word 0 // 93:Reserved + .word DCI_IRQHandler // 94:DCI + .word CAU_IRQHandler // 95:CAU + .word HAU_TRNG_IRQHandler // 96:HAU and TRNG + .word 0 // 97:Reserved + .word UART6_IRQHandler // 98:UART6 + .word UART7_IRQHandler // 99:UART7 + .word 0 // 100:Reserved + .word 0 // 101:Reserved + .word 0 // 102:Reserved + .word 0 // 103:Reserved + .word TLI_IRQHandler // 104:TLI + .word TLI_ER_IRQHandler // 105:TLI error + + .size g_pfnVectors, .-g_pfnVectors + + .section .text.Reset_Handler + .weak Reset_Handler + .type Reset_Handler, %function +Reset_Handler: + ldr r1, =_sidata + ldr r2, =_sdata + ldr r3, =_edata + + subs r3, r2 + ble fill_bss_start + +loop_copy_data: + subs r3, #4 + ldr r0, [r1,r3] + str r0, [r2,r3] + bgt loop_copy_data + +fill_bss_start: + ldr r1, =__bss_start + ldr r2, =__bss_end + movs r0, 0 + subs r2, r1 + ble startup_enter + +loop_fill_bss: + subs r2, #4 + str r0, [r1, r2] + bgt loop_fill_bss + +startup_enter: + bl SystemInit + bl entry + + /* Exception Handlers */ + .weak NMI_Handler + .type NMI_Handler, %function +NMI_Handler: + b . + .size NMI_Handler, . - NMI_Handler + + .weak MemManage_Handler + .type MemManage_Handler, %function +MemManage_Handler: + b . + .size MemManage_Handler, . - MemManage_Handler + + .weak BusFault_Handler + .type BusFault_Handler, %function +BusFault_Handler: + b . + .size BusFault_Handler, . - BusFault_Handler + + .weak UsageFault_Handler + .type UsageFault_Handler, %function +UsageFault_Handler: + b . + .size UsageFault_Handler, . - UsageFault_Handler + + .weak SVC_Handler + .type SVC_Handler, %function +SVC_Handler: + b . + .size SVC_Handler, . - SVC_Handler + + .weak DebugMon_Handler + .type DebugMon_Handler, %function +DebugMon_Handler: + b . + .size DebugMon_Handler, . - DebugMon_Handler + + .weak PendSV_Handler + .type PendSV_Handler, %function +PendSV_Handler: + b . + .size PendSV_Handler, . - PendSV_Handler + + .weak SysTick_Handler + .type SysTick_Handler, %function +SysTick_Handler: + b . + .size SysTick_Handler, . - SysTick_Handler + + /* IQR Handler */ + .section .text.Default_Handler,"ax",%progbits + .type Default_Handler, %function +Default_Handler: + b . + .size Default_Handler, . - Default_Handler + + .macro IRQ handler + .weak \handler + .set \handler, Default_Handler + .endm + + IRQ WWDGT_IRQHandler + IRQ LVD_IRQHandler + IRQ TAMPER_IRQHandler + IRQ RTC_IRQHandler + IRQ FMC_IRQHandler + IRQ RCU_CTC_IRQHandler + IRQ EXTI0_IRQHandler + IRQ EXTI1_IRQHandler + IRQ EXTI2_IRQHandler + IRQ EXTI3_IRQHandler + IRQ EXTI4_IRQHandler + IRQ DMA0_Channel0_IRQHandler + IRQ DMA0_Channel1_IRQHandler + IRQ DMA0_Channel2_IRQHandler + IRQ DMA0_Channel3_IRQHandler + IRQ DMA0_Channel4_IRQHandler + IRQ DMA0_Channel5_IRQHandler + IRQ DMA0_Channel6_IRQHandler + IRQ ADC0_1_IRQHandler + IRQ CAN0_TX_IRQHandler + IRQ CAN0_RX0_IRQHandler + IRQ CAN0_RX1_IRQHandler + IRQ CAN0_EWMC_IRQHandler + IRQ EXTI5_9_IRQHandler + IRQ TIMER0_BRK_TIMER8_IRQHandler + IRQ TIMER0_UP_TIMER9_IRQHandler + IRQ TIMER0_TRG_CMT_TIMER10_IRQHandler + IRQ TIMER0_Channel_IRQHandler + IRQ TIMER1_IRQHandler + IRQ TIMER2_IRQHandler + IRQ TIMER3_IRQHandler + IRQ I2C0_EV_IRQHandler + IRQ I2C0_ER_IRQHandler + IRQ I2C1_EV_IRQHandler + IRQ I2C1_ER_IRQHandler + IRQ SPI0_IRQHandler + IRQ SPI1_IRQHandler + IRQ USART0_IRQHandler + IRQ USART1_IRQHandler + IRQ USART2_IRQHandler + IRQ EXTI10_15_IRQHandler + IRQ RTC_Alarm_IRQHandler + IRQ USBFS_WKUP_IRQHandler + IRQ TIMER7_BRK_TIMER11_IRQHandler + IRQ TIMER7_UP_TIMER12_IRQHandler + IRQ TIMER7_TRG_CMT_TIMER13_IRQHandler + IRQ TIMER7_Channel_IRQHandler + IRQ ADC2_IRQHandler + IRQ EXMC_IRQHandler + IRQ SDIO_IRQHandler + IRQ TIMER4_IRQHandler + IRQ SPI2_IRQHandler + IRQ UART3_IRQHandler + IRQ UART4_IRQHandler + IRQ TIMER5_IRQHandler + IRQ TIMER6_IRQHandler + IRQ DMA1_Channel0_IRQHandler + IRQ DMA1_Channel1_IRQHandler + IRQ DMA1_Channel2_IRQHandler + IRQ DMA1_Channel3_IRQHandler + IRQ DMA1_Channel4_IRQHandler + IRQ ENET_IRQHandler + IRQ ENET_WKUP_IRQHandler + IRQ CAN1_TX_IRQHandler + IRQ CAN1_RX0_IRQHandler + IRQ CAN1_RX1_IRQHandler + IRQ CAN1_EWMC_IRQHandler + IRQ USBFS_IRQHandler + IRQ DMA1_Channel5_IRQHandler + IRQ DMA1_Channel6_IRQHandler + IRQ USART5_IRQHandler + IRQ I2C2_EV_IRQHandler + IRQ I2C2_ER_IRQHandler + IRQ DCI_IRQHandler + IRQ CAU_IRQHandler + IRQ HAU_TRNG_IRQHandler + IRQ UART6_IRQHandler + IRQ UART7_IRQHandler + IRQ TLI_IRQHandler + IRQ TLI_ER_IRQHandler diff --git a/bsp/gd32/libraries/GD32F20x_Firmware_Library/CMSIS/GD/GD32F20x/Source/IAR/startup_gd32f20x_cl.s b/bsp/gd32/libraries/GD32F20x_Firmware_Library/CMSIS/GD/GD32F20x/Source/IAR/startup_gd32f20x_cl.s new file mode 100644 index 0000000000..9759157a4f --- /dev/null +++ b/bsp/gd32/libraries/GD32F20x_Firmware_Library/CMSIS/GD/GD32F20x/Source/IAR/startup_gd32f20x_cl.s @@ -0,0 +1,621 @@ +;/*! +; \file startup_gd32f20x_cl.s +; \brief start up file + +; \version 2015-07-15, V1.0.0, firmware for GD32F20x +; \version 2017-06-05, V2.0.0, firmware for GD32F20x +; \version 2018-10-31, V2.1.0, firmware for GD32F20x +; \version 2020-09-30, V2.2.0, firmware for GD32F20x +;*/ + +;/* +; Copyright (c) 2020, GigaDevice Semiconductor Inc. + +; Redistribution and use in source and binary forms, with or without modification, +;are permitted provided that the following conditions are met: + +; 1. Redistributions of source code must retain the above copyright notice, this +; list of conditions and the following disclaimer. +; 2. Redistributions in binary form must reproduce the above copyright notice, +; this list of conditions and the following disclaimer in the documentation +; and/or other materials provided with the distribution. +; 3. Neither the name of the copyright holder nor the names of its contributors +; may be used to endorse or promote products derived from this software without +; specific prior written permission. + +; THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +;AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +;WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +;IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +;INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +;NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +;PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +;WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +;ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +;OF SUCH DAMAGE. +;*/ + + MODULE ?cstartup + + ;; Forward declaration of sections. + SECTION CSTACK:DATA:NOROOT(3) + + SECTION .intvec:CODE:NOROOT(2) + + EXTERN __iar_program_start + EXTERN SystemInit + PUBLIC __vector_table + + DATA +__vector_table + DCD sfe(CSTACK) ; top of stack + DCD Reset_Handler ; Reset Handler + + DCD NMI_Handler ; NMI Handler + DCD HardFault_Handler ; Hard Fault Handler + DCD MemManage_Handler ; MPU Fault Handler + DCD BusFault_Handler ; Bus Fault Handler + DCD UsageFault_Handler ; Usage Fault Handler + DCD 0 ; Reserved + DCD 0 ; Reserved + DCD 0 ; Reserved + DCD 0 ; Reserved + DCD SVC_Handler ; SVCall Handler + DCD DebugMon_Handler ; Debug Monitor Handler + DCD 0 ; Reserved + DCD PendSV_Handler ; PendSV Handler + DCD SysTick_Handler ; SysTick Handler + + ; External Interrupts + DCD WWDGT_IRQHandler ; Vector Number 16,Window Watchdog Timer + DCD LVD_IRQHandler ; Vector Number 17,LVD through EXTI Line detect + DCD TAMPER_IRQHandler ; Vector Number 18,Tamper Interrupt + DCD RTC_IRQHandler ; Vector Number 19,RTC through EXTI Line + DCD FMC_IRQHandler ; Vector Number 20,FMC + DCD RCU_IRQHandler ; Vector Number 21,RCU + DCD EXTI0_IRQHandler ; Vector Number 22,EXTI Line 0 + DCD EXTI1_IRQHandler ; Vector Number 23,EXTI Line 1 + DCD EXTI2_IRQHandler ; Vector Number 24,EXTI Line 2 + DCD EXTI3_IRQHandler ; Vector Number 25,EXTI Line 3 + DCD EXTI4_IRQHandler ; Vector Number 26,EXTI Line 4 + DCD DMA0_Channel0_IRQHandler ; Vector Number 27,DMA0 Channel 0 + DCD DMA0_Channel1_IRQHandler ; Vector Number 28,DMA0 Channel 1 + DCD DMA0_Channel2_IRQHandler ; Vector Number 29,DMA0 Channel 2 + DCD DMA0_Channel3_IRQHandler ; Vector Number 30,DMA0 Channel 3 + DCD DMA0_Channel4_IRQHandler ; Vector Number 31,DMA0 Channel 4 + DCD DMA0_Channel5_IRQHandler ; Vector Number 32,DMA0 Channel 5 + DCD DMA0_Channel6_IRQHandler ; Vector Number 33,DMA0 Channel 6 + DCD ADC0_1_IRQHandler ; Vector Number 34,ADC0 and ADC1 + DCD CAN0_TX_IRQHandler ; Vector Number 35,CAN0 TX + DCD CAN0_RX0_IRQHandler ; Vector Number 36,CAN0 RX0 + DCD CAN0_RX1_IRQHandler ; Vector Number 37,CAN0 RX1 + DCD CAN0_EWMC_IRQHandler ; Vector Number 38,CAN0 EWMC + DCD EXTI5_9_IRQHandler ; Vector Number 39,EXTI Line 5 to EXTI Line 9 + DCD TIMER0_BRK_TIMER8_IRQHandler ; Vector Number 40,TIMER0 Break and TIMER8 global + DCD TIMER0_UP_TIMER9_IRQHandler ; Vector Number 41,TIMER0 Update and TIMER9 global + DCD TIMER0_TRG_CMT_TIMER10_IRQHandler ; Vector Number 42,TIMER0 Trigger and Commutation and TIMER10 global + DCD TIMER0_Channel_IRQHandler ; Vector Number 43,TIMER0 Channel Capture Compare + DCD TIMER1_IRQHandler ; Vector Number 44,TIMER1 + DCD TIMER2_IRQHandler ; Vector Number 45,TIMER2 + DCD TIMER3_IRQHandler ; Vector Number 46,TIMER3 + DCD I2C0_EV_IRQHandler ; Vector Number 47,I2C0 Event + DCD I2C0_ER_IRQHandler ; Vector Number 48,I2C0 Error + DCD I2C1_EV_IRQHandler ; Vector Number 49,I2C1 Event + DCD I2C1_ER_IRQHandler ; Vector Number 50,I2C1 Error + DCD SPI0_IRQHandler ; Vector Number 51,SPI0 + DCD SPI1_IRQHandler ; Vector Number 52,SPI1 + DCD USART0_IRQHandler ; Vector Number 53,USART0 + DCD USART1_IRQHandler ; Vector Number 54,USART1 + DCD USART2_IRQHandler ; Vector Number 55,USART2 + DCD EXTI10_15_IRQHandler ; Vector Number 56,EXTI Line 10 to EXTI Line 15 + DCD RTC_Alarm_IRQHandler ; Vector Number 57,RTC Alarm through EXTI Line + DCD USBFS_WKUP_IRQHandler ; Vector Number 58,USBFS WakeUp from suspend through EXTI Line + DCD TIMER7_BRK_TIMER11_IRQHandler ; Vector Number 59,TIMER7 Break Interrupt and TIMER11 global + DCD TIMER7_UP_TIMER12_IRQHandler ; Vector Number 60,TIMER7 Update Interrupt and TIMER12 global + DCD TIMER7_TRG_CMT_TIMER13_IRQHandler ; Vector Number 61,TIMER7 Trigger and Commutation Interrupt and TIMER13 + DCD TIMER7_Channel_IRQHandler ; Vector Number 62,TIMER7 Channel Capture Compare + DCD ADC2_IRQHandler ; Vector Number 63,ADC2 + DCD EXMC_IRQHandler ; Vector Number 64,EXMC + DCD SDIO_IRQHandler ; Vector Number 65,SDIO + DCD TIMER4_IRQHandler ; Vector Number 66,TIMER4 + DCD SPI2_IRQHandler ; Vector Number 67,SPI2 + DCD UART3_IRQHandler ; Vector Number 68,UART3 + DCD UART4_IRQHandler ; Vector Number 69,UART4 + DCD TIMER5_IRQHandler ; Vector Number 70,TIMER5 + DCD TIMER6_IRQHandler ; Vector Number 71,TIMER6 + DCD DMA1_Channel0_IRQHandler ; Vector Number 72,DMA1 Channel0 + DCD DMA1_Channel1_IRQHandler ; Vector Number 73,DMA1 Channel1 + DCD DMA1_Channel2_IRQHandler ; Vector Number 74,DMA1 Channel2 + DCD DMA1_Channel3_IRQHandler ; Vector Number 75,DMA1 Channel3 + DCD DMA1_Channel4_IRQHandler ; Vector Number 76,DMA1 Channel4 + DCD ENET_IRQHandler ; Vector Number 77,Ethernet + DCD ENET_WKUP_IRQHandler ; Vector Number 78,Ethernet Wakeup through EXTI line + DCD CAN1_TX_IRQHandler ; Vector Number 79,CAN1 TX + DCD CAN1_RX0_IRQHandler ; Vector Number 80,CAN1 RX0 + DCD CAN1_RX1_IRQHandler ; Vector Number 81,CAN1 RX1 + DCD CAN1_EWMC_IRQHandler ; Vector Number 82,CAN1 EWMC + DCD USBFS_IRQHandler ; Vector Number 83,USBFS + DCD 0 ; Vector Number 84,Reserved + DCD DMA1_Channel5_IRQHandler ; Vector Number 85,DMA1 Channel5 + DCD DMA1_Channel6_IRQHandler ; Vector Number 86,DMA1 Channel6 + DCD USART5_IRQHandler ; Vector Number 87,USART5 + DCD I2C2_EV_IRQHandler ; Vector Number 88,I2C2 Event + DCD I2C2_ER_IRQHandler ; Vector Number 89,I2C2 Error + DCD 0 ; Vector Number 90,Reserved + DCD 0 ; Vector Number 91,Reserved + DCD 0 ; Vector Number 92,Reserved + DCD 0 ; Vector Number 93,Reserved + DCD DCI_IRQHandler ; Vector Number 94,DCI + DCD CAU_IRQHandler ; Vector Number 95,CAU + DCD HAU_TRNG_IRQHandler ; Vector Number 96,HAU and TRNG + DCD 0 ; Vector Number 97,Reserved + DCD UART6_IRQHandler ; Vector Number 98,UART6 + DCD UART7_IRQHandler ; Vector Number 99,UART7 + DCD 0 ; Vector Number 100,Reserved + DCD 0 ; Vector Number 101,Reserved + DCD 0 ; Vector Number 102,Reserved + DCD 0 ; Vector Number 103,Reserved + DCD TLI_IRQHandler ; Vector Number 104,TLI + DCD TLI_ER_IRQHandler ; Vector Number 105,TLI error + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; +;; Default interrupt handlers. +;; + THUMB + + PUBWEAK Reset_Handler + SECTION .text:CODE:NOROOT:REORDER(2) +Reset_Handler + LDR R0, = SystemInit + BLX R0 + LDR R0, =__iar_program_start + BX R0 + + PUBWEAK NMI_Handler + SECTION .text:CODE:NOROOT:REORDER(1) +NMI_Handler + B NMI_Handler + + PUBWEAK HardFault_Handler + SECTION .text:CODE:NOROOT:REORDER(1) +HardFault_Handler + B HardFault_Handler + + PUBWEAK MemManage_Handler + SECTION .text:CODE:NOROOT:REORDER(1) +MemManage_Handler + B MemManage_Handler + + PUBWEAK BusFault_Handler + SECTION .text:CODE:NOROOT:REORDER(1) +BusFault_Handler + B BusFault_Handler + + PUBWEAK UsageFault_Handler + SECTION .text:CODE:NOROOT:REORDER(1) +UsageFault_Handler + B UsageFault_Handler + + PUBWEAK SVC_Handler + SECTION .text:CODE:NOROOT:REORDER(1) +SVC_Handler + B SVC_Handler + + PUBWEAK DebugMon_Handler + SECTION .text:CODE:NOROOT:REORDER(1) +DebugMon_Handler + B DebugMon_Handler + + PUBWEAK PendSV_Handler + SECTION .text:CODE:NOROOT:REORDER(1) +PendSV_Handler + B PendSV_Handler + + PUBWEAK SysTick_Handler + SECTION .text:CODE:NOROOT:REORDER(1) +SysTick_Handler + B SysTick_Handler + + PUBWEAK WWDGT_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +WWDGT_IRQHandler + B WWDGT_IRQHandler + + PUBWEAK LVD_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +LVD_IRQHandler + B LVD_IRQHandler + + PUBWEAK TAMPER_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +TAMPER_IRQHandler + B TAMPER_IRQHandler + + PUBWEAK RTC_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +RTC_IRQHandler + B RTC_IRQHandler + + PUBWEAK FMC_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +FMC_IRQHandler + B FMC_IRQHandler + + PUBWEAK RCU_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +RCU_IRQHandler + B RCU_IRQHandler + + PUBWEAK EXTI0_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +EXTI0_IRQHandler + B EXTI0_IRQHandler + + PUBWEAK EXTI1_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +EXTI1_IRQHandler + B EXTI1_IRQHandler + + PUBWEAK EXTI2_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +EXTI2_IRQHandler + B EXTI2_IRQHandler + + PUBWEAK EXTI3_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +EXTI3_IRQHandler + B EXTI3_IRQHandler + + PUBWEAK EXTI4_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +EXTI4_IRQHandler + B EXTI4_IRQHandler + + PUBWEAK DMA0_Channel0_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +DMA0_Channel0_IRQHandler + B DMA0_Channel0_IRQHandler + + + PUBWEAK DMA0_Channel1_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +DMA0_Channel1_IRQHandler + B DMA0_Channel1_IRQHandler + + PUBWEAK DMA0_Channel2_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +DMA0_Channel2_IRQHandler + B DMA0_Channel2_IRQHandler + + PUBWEAK DMA0_Channel3_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +DMA0_Channel3_IRQHandler + B DMA0_Channel3_IRQHandler + + PUBWEAK DMA0_Channel4_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +DMA0_Channel4_IRQHandler + B DMA0_Channel4_IRQHandler + + PUBWEAK DMA0_Channel5_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +DMA0_Channel5_IRQHandler + B DMA0_Channel5_IRQHandler + + PUBWEAK DMA0_Channel6_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +DMA0_Channel6_IRQHandler + B DMA0_Channel6_IRQHandler + + PUBWEAK ADC0_1_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +ADC0_1_IRQHandler + B ADC0_1_IRQHandler + + PUBWEAK CAN0_TX_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +CAN0_TX_IRQHandler + B CAN0_TX_IRQHandler + + PUBWEAK CAN0_RX0_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +CAN0_RX0_IRQHandler + B CAN0_RX0_IRQHandler + + PUBWEAK CAN0_RX1_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +CAN0_RX1_IRQHandler + B CAN0_RX1_IRQHandler + + PUBWEAK CAN0_EWMC_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +CAN0_EWMC_IRQHandler + B CAN0_EWMC_IRQHandler + + PUBWEAK EXTI5_9_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +EXTI5_9_IRQHandler + B EXTI5_9_IRQHandler + + PUBWEAK TIMER0_BRK_TIMER8_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +TIMER0_BRK_TIMER8_IRQHandler + B TIMER0_BRK_TIMER8_IRQHandler + + PUBWEAK TIMER0_UP_TIMER9_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +TIMER0_UP_TIMER9_IRQHandler + B TIMER0_UP_TIMER9_IRQHandler + + PUBWEAK TIMER0_TRG_CMT_TIMER10_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +TIMER0_TRG_CMT_TIMER10_IRQHandler + B TIMER0_TRG_CMT_TIMER10_IRQHandler + + PUBWEAK TIMER0_Channel_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +TIMER0_Channel_IRQHandler + B TIMER0_Channel_IRQHandler + + PUBWEAK TIMER1_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +TIMER1_IRQHandler + B TIMER1_IRQHandler + + PUBWEAK TIMER2_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +TIMER2_IRQHandler + B TIMER2_IRQHandler + + PUBWEAK TIMER3_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +TIMER3_IRQHandler + B TIMER3_IRQHandler + + PUBWEAK I2C0_EV_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +I2C0_EV_IRQHandler + B I2C0_EV_IRQHandler + + PUBWEAK I2C0_ER_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +I2C0_ER_IRQHandler + B I2C0_ER_IRQHandler + + PUBWEAK I2C1_EV_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +I2C1_EV_IRQHandler + B I2C1_EV_IRQHandler + + PUBWEAK I2C1_ER_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +I2C1_ER_IRQHandler + B I2C1_ER_IRQHandler + + PUBWEAK SPI0_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +SPI0_IRQHandler + B SPI0_IRQHandler + + PUBWEAK SPI1_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +SPI1_IRQHandler + B SPI1_IRQHandler + + PUBWEAK USART0_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +USART0_IRQHandler + B USART0_IRQHandler + + PUBWEAK USART1_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +USART1_IRQHandler + B USART1_IRQHandler + + PUBWEAK USART2_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +USART2_IRQHandler + B USART2_IRQHandler + + PUBWEAK EXTI10_15_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +EXTI10_15_IRQHandler + B EXTI10_15_IRQHandler + + PUBWEAK RTC_Alarm_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +RTC_Alarm_IRQHandler + B RTC_Alarm_IRQHandler + + PUBWEAK USBFS_WKUP_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +USBFS_WKUP_IRQHandler + B USBFS_WKUP_IRQHandler + + PUBWEAK TIMER7_BRK_TIMER11_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +TIMER7_BRK_TIMER11_IRQHandler + B TIMER7_BRK_TIMER11_IRQHandler + + PUBWEAK TIMER7_UP_TIMER12_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +TIMER7_UP_TIMER12_IRQHandler + B TIMER7_UP_TIMER12_IRQHandler + + PUBWEAK TIMER7_TRG_CMT_TIMER13_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +TIMER7_TRG_CMT_TIMER13_IRQHandler + B TIMER7_TRG_CMT_TIMER13_IRQHandler + + PUBWEAK TIMER7_Channel_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +TIMER7_Channel_IRQHandler + B TIMER7_Channel_IRQHandler + + PUBWEAK ADC2_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +ADC2_IRQHandler + B ADC2_IRQHandler + + PUBWEAK EXMC_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +EXMC_IRQHandler + B EXMC_IRQHandler + + PUBWEAK SDIO_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +SDIO_IRQHandler + B SDIO_IRQHandler + + PUBWEAK TIMER4_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +TIMER4_IRQHandler + B TIMER4_IRQHandler + + PUBWEAK SPI2_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +SPI2_IRQHandler + B SPI2_IRQHandler + + PUBWEAK UART3_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +UART3_IRQHandler + B UART3_IRQHandler + + PUBWEAK UART4_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +UART4_IRQHandler + B UART4_IRQHandler + + PUBWEAK TIMER5_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +TIMER5_IRQHandler + B TIMER5_IRQHandler + + PUBWEAK TIMER6_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +TIMER6_IRQHandler + B TIMER6_IRQHandler + + PUBWEAK DMA1_Channel0_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +DMA1_Channel0_IRQHandler + B DMA1_Channel0_IRQHandler + + PUBWEAK DMA1_Channel1_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +DMA1_Channel1_IRQHandler + B DMA1_Channel1_IRQHandler + + PUBWEAK DMA1_Channel2_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +DMA1_Channel2_IRQHandler + B DMA1_Channel2_IRQHandler + + PUBWEAK DMA1_Channel3_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +DMA1_Channel3_IRQHandler + B DMA1_Channel3_IRQHandler + + PUBWEAK DMA1_Channel4_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +DMA1_Channel4_IRQHandler + B DMA1_Channel4_IRQHandler + + PUBWEAK ENET_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +ENET_IRQHandler + B ENET_IRQHandler + + PUBWEAK ENET_WKUP_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +ENET_WKUP_IRQHandler + B ENET_WKUP_IRQHandler + + PUBWEAK CAN1_TX_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +CAN1_TX_IRQHandler + B CAN1_TX_IRQHandler + + PUBWEAK CAN1_RX0_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +CAN1_RX0_IRQHandler + B CAN1_RX0_IRQHandler + + PUBWEAK CAN1_RX1_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +CAN1_RX1_IRQHandler + B CAN1_RX1_IRQHandler + + PUBWEAK CAN1_EWMC_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +CAN1_EWMC_IRQHandler + B CAN1_EWMC_IRQHandler + + PUBWEAK USBFS_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +USBFS_IRQHandler + B USBFS_IRQHandler + + PUBWEAK DMA1_Channel5_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +DMA1_Channel5_IRQHandler + B DMA1_Channel5_IRQHandler + + PUBWEAK DMA1_Channel6_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +DMA1_Channel6_IRQHandler + B DMA1_Channel6_IRQHandler + + PUBWEAK USART5_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +USART5_IRQHandler + B USART5_IRQHandler + + PUBWEAK I2C2_EV_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +I2C2_EV_IRQHandler + B I2C2_EV_IRQHandler + + PUBWEAK I2C2_ER_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +I2C2_ER_IRQHandler + B I2C2_ER_IRQHandler + + PUBWEAK DCI_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +DCI_IRQHandler + B DCI_IRQHandler + + PUBWEAK CAU_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +CAU_IRQHandler + B CAU_IRQHandler + + PUBWEAK HAU_TRNG_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +HAU_TRNG_IRQHandler + B HAU_TRNG_IRQHandler + + PUBWEAK UART6_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +UART6_IRQHandler + B UART6_IRQHandler + + PUBWEAK UART7_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +UART7_IRQHandler + B UART7_IRQHandler + + PUBWEAK TLI_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +TLI_IRQHandler + B TLI_IRQHandler + + PUBWEAK TLI_ER_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +TLI_ER_IRQHandler + B TLI_ER_IRQHandler + + END diff --git a/bsp/gd32/libraries/GD32F20x_Firmware_Library/CMSIS/GD/GD32F20x/Source/system_gd32f20x.c b/bsp/gd32/libraries/GD32F20x_Firmware_Library/CMSIS/GD/GD32F20x/Source/system_gd32f20x.c new file mode 100644 index 0000000000..a3f76add9c --- /dev/null +++ b/bsp/gd32/libraries/GD32F20x_Firmware_Library/CMSIS/GD/GD32F20x/Source/system_gd32f20x.c @@ -0,0 +1,1113 @@ +/*! + \file system_gd32f20x.c + \brief CMSIS Cortex-M3 Device Peripheral Access Layer Source File for + GD32F20x Device Series +*/ + +/* Copyright (c) 2012 ARM LIMITED + + All rights reserved. + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + - Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + - Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + - Neither the name of ARM nor the names of its contributors may be used + to endorse or promote products derived from this software without + specific prior written permission. + * + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDERS AND CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + ---------------------------------------------------------------------------*/ + +/* This file refers the CMSIS standard, some adjustments are made according to GigaDevice chips */ + +#include "gd32f20x.h" + +/* system frequency define */ +#define __IRC8M (IRC8M_VALUE) /* internal 8 MHz RC oscillator frequency */ +#define __HXTAL (HXTAL_VALUE) /* high speed crystal oscillator frequency */ +#define __SYS_OSC_CLK (__IRC8M) /* main oscillator frequency */ + +/* select a system clock by uncommenting the following line */ +/* use IRC8M */ +//#define __SYSTEM_CLOCK_IRC8M (uint32_t)(__IRC8M) +//#define __SYSTEM_CLOCK_48M_PLL_IRC8M (uint32_t)(48000000) +//#define __SYSTEM_CLOCK_72M_PLL_IRC8M (uint32_t)(72000000) +//#define __SYSTEM_CLOCK_108M_PLL_IRC8M (uint32_t)(108000000) +//#define __SYSTEM_CLOCK_120M_PLL_IRC8M (uint32_t)(120000000) + +/* use HXTAL */ +//#define __SYSTEM_CLOCK_HXTAL (uint32_t)(__HXTAL) +//#define __SYSTEM_CLOCK_24M_PLL_HXTAL (uint32_t)(24000000) +//#define __SYSTEM_CLOCK_36M_PLL_HXTAL (uint32_t)(36000000) +//#define __SYSTEM_CLOCK_48M_PLL_HXTAL (uint32_t)(48000000) +//#define __SYSTEM_CLOCK_56M_PLL_HXTAL (uint32_t)(56000000) +//#define __SYSTEM_CLOCK_72M_PLL_HXTAL (uint32_t)(72000000) +//#define __SYSTEM_CLOCK_96M_PLL_HXTAL (uint32_t)(96000000) +//#define __SYSTEM_CLOCK_108M_PLL_HXTAL (uint32_t)(108000000) +#define __SYSTEM_CLOCK_120M_PLL_HXTAL (uint32_t)(120000000) + + +#define SEL_IRC8M 0x00U +#define SEL_HXTAL 0x01U +#define SEL_PLL 0x02U + +/* set the system clock frequency and declare the system clock configuration function */ +#ifdef __SYSTEM_CLOCK_IRC8M +uint32_t SystemCoreClock = __SYSTEM_CLOCK_IRC8M; +static void system_clock_8m_irc8m(void); +#elif defined (__SYSTEM_CLOCK_48M_PLL_IRC8M) +uint32_t SystemCoreClock = __SYSTEM_CLOCK_48M_PLL_IRC8M; +static void system_clock_48m_irc8m(void); +#elif defined (__SYSTEM_CLOCK_72M_PLL_IRC8M) +uint32_t SystemCoreClock = __SYSTEM_CLOCK_72M_PLL_IRC8M; +static void system_clock_72m_irc8m(void); +#elif defined (__SYSTEM_CLOCK_108M_PLL_IRC8M) +uint32_t SystemCoreClock = __SYSTEM_CLOCK_108M_PLL_IRC8M; +static void system_clock_108m_irc8m(void); +#elif defined (__SYSTEM_CLOCK_120M_PLL_IRC8M) +uint32_t SystemCoreClock = __SYSTEM_CLOCK_120M_PLL_IRC8M; +static void system_clock_120m_irc8m(void); + +#elif defined (__SYSTEM_CLOCK_HXTAL) +uint32_t SystemCoreClock = __SYSTEM_CLOCK_HXTAL; +static void system_clock_hxtal(void); +#elif defined (__SYSTEM_CLOCK_24M_PLL_HXTAL) +uint32_t SystemCoreClock = __SYSTEM_CLOCK_24M_PLL_HXTAL; +static void system_clock_24m_hxtal(void); +#elif defined (__SYSTEM_CLOCK_36M_PLL_HXTAL) +uint32_t SystemCoreClock = __SYSTEM_CLOCK_36M_PLL_HXTAL; +static void system_clock_36m_hxtal(void); +#elif defined (__SYSTEM_CLOCK_48M_PLL_HXTAL) +uint32_t SystemCoreClock = __SYSTEM_CLOCK_48M_PLL_HXTAL; +static void system_clock_48m_hxtal(void); +#elif defined (__SYSTEM_CLOCK_56M_PLL_HXTAL) +uint32_t SystemCoreClock = __SYSTEM_CLOCK_56M_PLL_HXTAL; +static void system_clock_56m_hxtal(void); +#elif defined (__SYSTEM_CLOCK_72M_PLL_HXTAL) +uint32_t SystemCoreClock = __SYSTEM_CLOCK_72M_PLL_HXTAL; +static void system_clock_72m_hxtal(void); +#elif defined (__SYSTEM_CLOCK_96M_PLL_HXTAL) +uint32_t SystemCoreClock = __SYSTEM_CLOCK_96M_PLL_HXTAL; +static void system_clock_96m_hxtal(void); +#elif defined (__SYSTEM_CLOCK_108M_PLL_HXTAL) +uint32_t SystemCoreClock = __SYSTEM_CLOCK_108M_PLL_HXTAL; +static void system_clock_108m_hxtal(void); +#elif defined (__SYSTEM_CLOCK_120M_PLL_HXTAL) +uint32_t SystemCoreClock = __SYSTEM_CLOCK_120M_PLL_HXTAL; +static void system_clock_120m_hxtal(void); +#endif /* __SYSTEM_CLOCK_IRC8M */ + +/* configure the system clock */ +static void system_clock_config(void); + +/*! + \brief setup the microcontroller system, initialize the system + \param[in] none + \param[out] none + \retval none +*/ +void SystemInit (void) +{ + /* reset the RCC clock configuration to the default reset state */ + /* enable IRC8M */ + RCU_CTL |= RCU_CTL_IRC8MEN; + + /* reset SCS, AHBPSC, APB1PSC, APB2PSC, ADCPSC, CKOUT0SEL bits */ + RCU_CFG0 &= ~(RCU_CFG0_SCS | RCU_CFG0_AHBPSC | RCU_CFG0_APB1PSC | RCU_CFG0_APB2PSC | + RCU_CFG0_ADCPSC | RCU_CFG0_ADCPSC_2 | RCU_CFG0_CKOUT0SEL); + + /* reset HXTALEN, CKMEN, PLLEN bits */ + RCU_CTL &= ~(RCU_CTL_HXTALEN | RCU_CTL_CKMEN | RCU_CTL_PLLEN ); + + /* Reset HXTALBPS bit */ + RCU_CTL &= ~(RCU_CTL_HXTALBPS); + + /* reset PLLSEL, PREDV0_LSB, PLLMF, USBFSPSC bits */ + RCU_CFG0 &= ~(RCU_CFG0_PLLSEL | RCU_CFG0_PREDV0_LSB | RCU_CFG0_PLLMF | + RCU_CFG0_USBFSPSC | RCU_CFG0_PLLMF_4); + + /* reset PLL1EN and PLL2EN bits */ + RCU_CTL &= ~(RCU_CTL_PLL1EN | RCU_CTL_PLL2EN); + + /* reset CFG1 register */ + RCU_CFG1 = 0x00000000U; + + /* reset INT register */ + RCU_INT = 0x00FF0000U; + + /* reset CFG2 register */ + RCU_CFG2 = 0x00000000U; + + /* reset PLLTCTL register */ + RCU_PLLTCTL &= (~RCU_PLLTCTL_PLLTEN); + + /* reset PLLTINT register */ + RCU_PLLTINT = 0x00400000U; + + /* Reset PLLTCFG register */ + RCU_PLLTCFG = 0x20003010U; + + /* Configure the System clock source, PLL Multiplier, AHB/APBx prescalers and Flash settings */ + system_clock_config(); +} +/*! + \brief configure the system clock + \param[in] none + \param[out] none + \retval none +*/ +static void system_clock_config(void) +{ +#ifdef __SYSTEM_CLOCK_IRC8M + system_clock_8m_irc8m(); +#elif defined (__SYSTEM_CLOCK_48M_PLL_IRC8M) + system_clock_48m_irc8m(); +#elif defined (__SYSTEM_CLOCK_72M_PLL_IRC8M) + system_clock_72m_irc8m(); +#elif defined (__SYSTEM_CLOCK_108M_PLL_IRC8M) + system_clock_108m_irc8m(); +#elif defined (__SYSTEM_CLOCK_120M_PLL_IRC8M) + system_clock_120m_irc8m(); + +#elif defined (__SYSTEM_CLOCK_HXTAL) + system_clock_hxtal(); +#elif defined (__SYSTEM_CLOCK_24M_PLL_HXTAL) + system_clock_24m_hxtal(); +#elif defined (__SYSTEM_CLOCK_36M_PLL_HXTAL) + system_clock_36m_hxtal(); +#elif defined (__SYSTEM_CLOCK_48M_PLL_HXTAL) + system_clock_48m_hxtal(); +#elif defined (__SYSTEM_CLOCK_56M_PLL_HXTAL) + system_clock_56m_hxtal(); +#elif defined (__SYSTEM_CLOCK_72M_PLL_HXTAL) + system_clock_72m_hxtal(); +#elif defined (__SYSTEM_CLOCK_96M_PLL_HXTAL) + system_clock_96m_hxtal(); +#elif defined (__SYSTEM_CLOCK_108M_PLL_HXTAL) + system_clock_108m_hxtal(); +#elif defined (__SYSTEM_CLOCK_120M_PLL_HXTAL) + system_clock_120m_hxtal(); +#endif /* __SYSTEM_CLOCK_IRC8M */ +} + +#ifdef __SYSTEM_CLOCK_IRC8M +/*! + \brief configure the system clock to 8M by IRC8M + \param[in] none + \param[out] none + \retval none +*/ +static void system_clock_8m_irc8m(void) +{ + uint32_t timeout = 0U; + uint32_t stab_flag = 0U; + + /* enable IRC8M */ + RCU_CTL |= RCU_CTL_IRC8MEN; + + /* wait until IRC8M is stable or the startup time is longer than IRC8M_STARTUP_TIMEOUT */ + do{ + timeout++; + stab_flag = (RCU_CTL & RCU_CTL_IRC8MSTB); + } + while((0U == stab_flag) && (IRC8M_STARTUP_TIMEOUT != timeout)); + + /* if fail */ + if(0U == (RCU_CTL & RCU_CTL_IRC8MSTB)){ + while(1){ + } + } + + /* AHB = SYSCLK */ + RCU_CFG0 |= RCU_AHB_CKSYS_DIV1; + /* APB2 = AHB/1 */ + RCU_CFG0 |= RCU_APB2_CKAHB_DIV1; + /* APB1 = AHB/2 */ + RCU_CFG0 |= RCU_APB1_CKAHB_DIV2; + + /* select IRC8M as system clock */ + RCU_CFG0 &= ~RCU_CFG0_SCS; + RCU_CFG0 |= RCU_CKSYSSRC_IRC8M; + + /* wait until IRC8M is selected as system clock */ + while(0U != (RCU_CFG0 & RCU_SCSS_IRC8M)){ + } +} + +#elif defined (__SYSTEM_CLOCK_48M_PLL_IRC8M) +/*! + \brief configure the system clock to 48M by PLL which selects IRC8M as its clock source + \param[in] none + \param[out] none + \retval none +*/ +static void system_clock_48m_irc8m(void) +{ + uint32_t timeout = 0U; + uint32_t stab_flag = 0U; + + /* enable IRC8M */ + RCU_CTL |= RCU_CTL_IRC8MEN; + + /* wait until IRC8M is stable or the startup time is longer than IRC8M_STARTUP_TIMEOUT */ + do{ + timeout++; + stab_flag = (RCU_CTL & RCU_CTL_IRC8MSTB); + } + while((0U == stab_flag) && (IRC8M_STARTUP_TIMEOUT != timeout)); + + /* if fail */ + if(0U == (RCU_CTL & RCU_CTL_IRC8MSTB)){ + while(1){ + } + } + + /* IRC8M is stable */ + /* AHB = SYSCLK */ + RCU_CFG0 |= RCU_AHB_CKSYS_DIV1; + /* APB2 = AHB/1 */ + RCU_CFG0 |= RCU_APB2_CKAHB_DIV1; + /* APB1 = AHB/2 */ + RCU_CFG0 |= RCU_APB1_CKAHB_DIV2; + + /* CK_PLL = (CK_IRC8M/2) * 12 = 48 MHz */ + RCU_CFG0 &= ~(RCU_CFG0_PLLMF | RCU_CFG0_PLLMF_4 | RCU_CFG0_PREDV0_LSB | RCU_CFG0_PLLSEL ); + RCU_CFG0 |= (RCU_PLLSRC_IRC8M_DIV2 | RCU_PLL_MUL12); + + /* enable PLL */ + RCU_CTL |= RCU_CTL_PLLEN; + + /* wait until PLL is stable */ + while(0U == (RCU_CTL & RCU_CTL_PLLSTB)){ + } + + /* select PLL as system clock */ + RCU_CFG0 &= ~RCU_CFG0_SCS; + RCU_CFG0 |= RCU_CKSYSSRC_PLL; + + /* wait until PLL is selected as system clock */ + while(0U == (RCU_CFG0 & RCU_SCSS_PLL)){ + } +} + +#elif defined (__SYSTEM_CLOCK_72M_PLL_IRC8M) +/*! + \brief configure the system clock to 72M by PLL which selects IRC8M as its clock source + \param[in] none + \param[out] none + \retval none +*/ +static void system_clock_72m_irc8m(void) +{ + uint32_t timeout = 0U; + uint32_t stab_flag = 0U; + + /* enable IRC8M */ + RCU_CTL |= RCU_CTL_IRC8MEN; + + /* wait until IRC8M is stable or the startup time is longer than IRC8M_STARTUP_TIMEOUT */ + do{ + timeout++; + stab_flag = (RCU_CTL & RCU_CTL_IRC8MSTB); + }while((0U == stab_flag) && (IRC8M_STARTUP_TIMEOUT != timeout)); + + /* if fail */ + if(0U == (RCU_CTL & RCU_CTL_IRC8MSTB)){ + while(1){ + } + } + + /* IRC8M is stable */ + /* AHB = SYSCLK */ + RCU_CFG0 |= RCU_AHB_CKSYS_DIV1; + /* APB2 = AHB/1 */ + RCU_CFG0 |= RCU_APB2_CKAHB_DIV1; + /* APB1 = AHB/2 */ + RCU_CFG0 |= RCU_APB1_CKAHB_DIV2; + + /* CK_PLL = (CK_IRC8M/2) * 18 = 72 MHz */ + RCU_CFG0 &= ~(RCU_CFG0_PLLMF | RCU_CFG0_PLLMF_4 | RCU_CFG0_PREDV0_LSB | RCU_CFG0_PLLSEL ); + RCU_CFG0 |= (RCU_PLLSRC_IRC8M_DIV2 | RCU_PLL_MUL18); + + /* enable PLL */ + RCU_CTL |= RCU_CTL_PLLEN; + + /* wait until PLL is stable */ + while(0U == (RCU_CTL & RCU_CTL_PLLSTB)){ + } + + /* select PLL as system clock */ + RCU_CFG0 &= ~RCU_CFG0_SCS; + RCU_CFG0 |= RCU_CKSYSSRC_PLL; + + /* wait until PLL is selected as system clock */ + while(0U == (RCU_CFG0 & RCU_SCSS_PLL)){ + } +} + +#elif defined (__SYSTEM_CLOCK_108M_PLL_IRC8M) +/*! + \brief configure the system clock to 108M by PLL which selects IRC8M as its clock source + \param[in] none + \param[out] none + \retval none +*/ +static void system_clock_108m_irc8m(void) +{ + uint32_t timeout = 0U; + uint32_t stab_flag = 0U; + + /* enable IRC8M */ + RCU_CTL |= RCU_CTL_IRC8MEN; + + /* wait until IRC8M is stable or the startup time is longer than IRC8M_STARTUP_TIMEOUT */ + do{ + timeout++; + stab_flag = (RCU_CTL & RCU_CTL_IRC8MSTB); + }while((0U == stab_flag) && (IRC8M_STARTUP_TIMEOUT != timeout)); + + /* if fail */ + if(0U == (RCU_CTL & RCU_CTL_IRC8MSTB)){ + while(1){ + } + } + + /* IRC8M is stable */ + /* AHB = SYSCLK */ + RCU_CFG0 |= RCU_AHB_CKSYS_DIV1; + /* APB2 = AHB/1 */ + RCU_CFG0 |= RCU_APB2_CKAHB_DIV1; + /* APB1 = AHB/2 */ + RCU_CFG0 |= RCU_APB1_CKAHB_DIV2; + + /* CK_PLL = (CK_IRC8M/2) * 27 = 108 MHz */ + RCU_CFG0 &= ~(RCU_CFG0_PLLMF | RCU_CFG0_PLLMF_4 | RCU_CFG0_PREDV0_LSB | RCU_CFG0_PLLSEL ); + RCU_CFG0 |= (RCU_PLLSRC_IRC8M_DIV2 | RCU_PLL_MUL27); + + /* enable PLL */ + RCU_CTL |= RCU_CTL_PLLEN; + + /* wait until PLL is stable */ + while(0U == (RCU_CTL & RCU_CTL_PLLSTB)){ + } + + /* select PLL as system clock */ + RCU_CFG0 &= ~RCU_CFG0_SCS; + RCU_CFG0 |= RCU_CKSYSSRC_PLL; + + /* wait until PLL is selected as system clock */ + while(0U == (RCU_CFG0 & RCU_SCSS_PLL)){ + } +} + +#elif defined (__SYSTEM_CLOCK_120M_PLL_IRC8M) +/*! + \brief configure the system clock to 120M by PLL which selects IRC8M as its clock source + \param[in] none + \param[out] none + \retval none +*/ +static void system_clock_120m_irc8m(void) +{ + uint32_t timeout = 0U; + uint32_t stab_flag = 0U; + + /* enable IRC8M */ + RCU_CTL |= RCU_CTL_IRC8MEN; + + /* wait until IRC8M is stable or the startup time is longer than IRC8M_STARTUP_TIMEOUT */ + do{ + timeout++; + stab_flag = (RCU_CTL & RCU_CTL_IRC8MSTB); + }while((0U == stab_flag) && (IRC8M_STARTUP_TIMEOUT != timeout)); + + /* if fail */ + if(0U == (RCU_CTL & RCU_CTL_IRC8MSTB)){ + while(1){ + } + } + + /* IRC8M is stable */ + /* AHB = SYSCLK */ + RCU_CFG0 |= RCU_AHB_CKSYS_DIV1; + /* APB2 = AHB/1 */ + RCU_CFG0 |= RCU_APB2_CKAHB_DIV1; + /* APB1 = AHB/2 */ + RCU_CFG0 |= RCU_APB1_CKAHB_DIV2; + + /* CK_PLL = (CK_IRC8M/2) * 30 = 120 MHz */ + RCU_CFG0 &= ~(RCU_CFG0_PLLMF | RCU_CFG0_PLLMF_4 | RCU_CFG0_PREDV0_LSB | RCU_CFG0_PLLSEL ); + RCU_CFG0 |= (RCU_PLLSRC_IRC8M_DIV2 | RCU_PLL_MUL30); + + /* enable PLL */ + RCU_CTL |= RCU_CTL_PLLEN; + + /* wait until PLL is stable */ + while(0U == (RCU_CTL & RCU_CTL_PLLSTB)){ + } + + /* select PLL as system clock */ + RCU_CFG0 &= ~RCU_CFG0_SCS; + RCU_CFG0 |= RCU_CKSYSSRC_PLL; + + /* wait until PLL is selected as system clock */ + while(0U == (RCU_CFG0 & RCU_SCSS_PLL)){ + } +} + +#elif defined (__SYSTEM_CLOCK_HXTAL) +/*! + \brief configure the system clock to HXTAL + \param[in] none + \param[out] none + \retval none +*/ +static void system_clock_hxtal(void) +{ + uint32_t timeout = 0U; + uint32_t stab_flag = 0U; + + /* enable HXTAL */ + RCU_CTL |= RCU_CTL_HXTALEN; + + /* wait until HXTAL is stable or the startup time is longer than HXTAL_STARTUP_TIMEOUT */ + do{ + timeout++; + stab_flag = (RCU_CTL & RCU_CTL_HXTALSTB); + }while((0U == stab_flag) && (HXTAL_STARTUP_TIMEOUT != timeout)); + + /* if fail */ + if(0U == (RCU_CTL & RCU_CTL_HXTALSTB)){ + while(1){ + } + } + + /* AHB = SYSCLK */ + RCU_CFG0 |= RCU_AHB_CKSYS_DIV1; + /* APB2 = AHB/1 */ + RCU_CFG0 |= RCU_APB2_CKAHB_DIV1; + /* APB1 = AHB/2 */ + RCU_CFG0 |= RCU_APB1_CKAHB_DIV2; + + /* select HXTAL as system clock */ + RCU_CFG0 &= ~RCU_CFG0_SCS; + RCU_CFG0 |= RCU_CKSYSSRC_HXTAL; + + /* wait until HXTAL is selected as system clock */ + while(0 == (RCU_CFG0 & RCU_SCSS_HXTAL)){ + } +} + +#elif defined (__SYSTEM_CLOCK_24M_PLL_HXTAL) +/*! + \brief configure the system clock to 24M by PLL which selects HXTAL(8M) as its clock source + \param[in] none + \param[out] none + \retval none +*/ +static void system_clock_24m_hxtal(void) +{ + uint32_t timeout = 0U; + uint32_t stab_flag = 0U; + + /* enable HXTAL */ + RCU_CTL |= RCU_CTL_HXTALEN; + + /* wait until HXTAL is stable or the startup time is longer than HXTAL_STARTUP_TIMEOUT */ + do{ + timeout++; + stab_flag = (RCU_CTL & RCU_CTL_HXTALSTB); + }while((0U == stab_flag) && (HXTAL_STARTUP_TIMEOUT != timeout)); + + /* if fail */ + if(0U == (RCU_CTL & RCU_CTL_HXTALSTB)){ + while(1){ + } + } + + /* HXTAL is stable */ + /* AHB = SYSCLK */ + RCU_CFG0 |= RCU_AHB_CKSYS_DIV1; + /* APB2 = AHB/1 */ + RCU_CFG0 |= RCU_APB2_CKAHB_DIV1; + /* APB1 = AHB/2 */ + RCU_CFG0 |= RCU_APB1_CKAHB_DIV2; + + /* CK_PLL = (CK_PREDIV0) * 6 = 24 MHz */ + RCU_CFG0 &= ~(RCU_CFG0_PLLMF | RCU_CFG0_PLLMF_4 | RCU_CFG0_PREDV0_LSB | RCU_CFG0_PLLSEL ); + RCU_CFG0 |= (RCU_PLLSRC_HXTAL | RCU_PLL_MUL6); + + /* CK_PREDIV0 = (CK_HXTAL)/5 *8 /10 = 4 MHz */ + RCU_CFG1 &= ~(RCU_CFG1_PREDV0SEL | RCU_CFG1_PLL1MF | RCU_CFG1_PREDV1 | RCU_CFG1_PREDV0); + RCU_CFG1 |= (RCU_PREDV0SRC_CKPLL1 | RCU_PLL1_MUL8 | RCU_PREDV1_DIV5 | RCU_PREDV0_DIV10); + + /* enable PLL1 */ + RCU_CTL |= RCU_CTL_PLL1EN; + /* wait till PLL1 is ready */ + while((RCU_CTL & RCU_CTL_PLL1STB) == 0){ + } + + /* enable PLL */ + RCU_CTL |= RCU_CTL_PLLEN; + + /* wait until PLL is stable */ + while(0U == (RCU_CTL & RCU_CTL_PLLSTB)){ + } + + /* select PLL as system clock */ + RCU_CFG0 &= ~RCU_CFG0_SCS; + RCU_CFG0 |= RCU_CKSYSSRC_PLL; + + /* wait until PLL is selected as system clock */ + while(0U == (RCU_CFG0 & RCU_SCSS_PLL)){ + } +} + + +#elif defined (__SYSTEM_CLOCK_36M_PLL_HXTAL) +/*! + \brief configure the system clock to 36M by PLL which selects HXTAL(8M) as its clock source + \param[in] none + \param[out] none + \retval none +*/ +static void system_clock_36m_hxtal(void) +{ + uint32_t timeout = 0U; + uint32_t stab_flag = 0U; + + /* enable HXTAL */ + RCU_CTL |= RCU_CTL_HXTALEN; + + /* wait until HXTAL is stable or the startup time is longer than HXTAL_STARTUP_TIMEOUT */ + do{ + timeout++; + stab_flag = (RCU_CTL & RCU_CTL_HXTALSTB); + }while((0U == stab_flag) && (HXTAL_STARTUP_TIMEOUT != timeout)); + + /* if fail */ + if(0U == (RCU_CTL & RCU_CTL_HXTALSTB)){ + while(1){ + } + } + + /* HXTAL is stable */ + /* AHB = SYSCLK */ + RCU_CFG0 |= RCU_AHB_CKSYS_DIV1; + /* APB2 = AHB/1 */ + RCU_CFG0 |= RCU_APB2_CKAHB_DIV1; + /* APB1 = AHB/2 */ + RCU_CFG0 |= RCU_APB1_CKAHB_DIV2; + + /* CK_PLL = (CK_PREDIV0) * 9 = 36 MHz */ + RCU_CFG0 &= ~(RCU_CFG0_PLLMF | RCU_CFG0_PLLMF_4 | RCU_CFG0_PREDV0_LSB | RCU_CFG0_PLLSEL ); + RCU_CFG0 |= (RCU_PLLSRC_HXTAL | RCU_PLL_MUL9); + + /* CK_PREDIV0 = (CK_HXTAL)/5 *8 /10 = 4 MHz */ + RCU_CFG1 &= ~(RCU_CFG1_PREDV0SEL | RCU_CFG1_PLL1MF | RCU_CFG1_PREDV1 | RCU_CFG1_PREDV0); + RCU_CFG1 |= (RCU_PREDV0SRC_CKPLL1 | RCU_PLL1_MUL8 | RCU_PREDV1_DIV5 | RCU_PREDV0_DIV10); + + /* enable PLL1 */ + RCU_CTL |= RCU_CTL_PLL1EN; + /* wait till PLL1 is ready */ + while((RCU_CTL & RCU_CTL_PLL1STB) == 0){ + } + + /* enable PLL */ + RCU_CTL |= RCU_CTL_PLLEN; + + /* wait until PLL is stable */ + while(0U == (RCU_CTL & RCU_CTL_PLLSTB)){ + } + + /* select PLL as system clock */ + RCU_CFG0 &= ~RCU_CFG0_SCS; + RCU_CFG0 |= RCU_CKSYSSRC_PLL; + + /* wait until PLL is selected as system clock */ + while(0U == (RCU_CFG0 & RCU_SCSS_PLL)){ + } +} + + +#elif defined (__SYSTEM_CLOCK_48M_PLL_HXTAL) +/*! + \brief configure the system clock to 48M by PLL which selects HXTAL(8M) as its clock source + \param[in] none + \param[out] none + \retval none +*/ +static void system_clock_48m_hxtal(void) +{ + uint32_t timeout = 0U; + uint32_t stab_flag = 0U; + + /* enable HXTAL */ + RCU_CTL |= RCU_CTL_HXTALEN; + + /* wait until HXTAL is stable or the startup time is longer than HXTAL_STARTUP_TIMEOUT */ + do{ + timeout++; + stab_flag = (RCU_CTL & RCU_CTL_HXTALSTB); + }while((0U == stab_flag) && (HXTAL_STARTUP_TIMEOUT != timeout)); + + /* if fail */ + if(0U == (RCU_CTL & RCU_CTL_HXTALSTB)){ + while(1){ + } + } + + /* HXTAL is stable */ + /* AHB = SYSCLK */ + RCU_CFG0 |= RCU_AHB_CKSYS_DIV1; + /* APB2 = AHB/1 */ + RCU_CFG0 |= RCU_APB2_CKAHB_DIV1; + /* APB1 = AHB/2 */ + RCU_CFG0 |= RCU_APB1_CKAHB_DIV2; + + /* CK_PLL = (CK_PREDIV0) * 6 = 48 MHz */ + RCU_CFG0 &= ~(RCU_CFG0_PLLMF | RCU_CFG0_PLLMF_4 | RCU_CFG0_PREDV0_LSB | RCU_CFG0_PLLSEL ); + RCU_CFG0 |= (RCU_PLLSRC_HXTAL | RCU_PLL_MUL6); + + /* CK_PREDIV0 = (CK_HXTAL) / 5 * 8 /5 = 8 MHz */ + RCU_CFG1 &= ~(RCU_CFG1_PREDV0SEL | RCU_CFG1_PLL1MF | RCU_CFG1_PREDV1 | RCU_CFG1_PREDV0); + RCU_CFG1 |= (RCU_PREDV0SRC_CKPLL1 | RCU_PLL1_MUL8 | RCU_PREDV1_DIV5 | RCU_PREDV0_DIV5); + + /* enable PLL1 */ + RCU_CTL |= RCU_CTL_PLL1EN; + /* wait till PLL1 is ready */ + while((RCU_CTL & RCU_CTL_PLL1STB) == 0){ + } + + /* enable PLL */ + RCU_CTL |= RCU_CTL_PLLEN; + + /* wait until PLL is stable */ + while(0U == (RCU_CTL & RCU_CTL_PLLSTB)){ + } + + /* select PLL as system clock */ + RCU_CFG0 &= ~RCU_CFG0_SCS; + RCU_CFG0 |= RCU_CKSYSSRC_PLL; + + /* wait until PLL is selected as system clock */ + while(0U == (RCU_CFG0 & RCU_SCSS_PLL)){ + } +} + +#elif defined (__SYSTEM_CLOCK_56M_PLL_HXTAL) +/*! + \brief configure the system clock to 56M by PLL which selects HXTAL(8M) as its clock source + \param[in] none + \param[out] none + \retval none +*/ +static void system_clock_56m_hxtal(void) +{ + uint32_t timeout = 0U; + uint32_t stab_flag = 0U; + + /* enable HXTAL */ + RCU_CTL |= RCU_CTL_HXTALEN; + + /* wait until HXTAL is stable or the startup time is longer than HXTAL_STARTUP_TIMEOUT */ + do{ + timeout++; + stab_flag = (RCU_CTL & RCU_CTL_HXTALSTB); + }while((0U == stab_flag) && (HXTAL_STARTUP_TIMEOUT != timeout)); + + /* if fail */ + if(0U == (RCU_CTL & RCU_CTL_HXTALSTB)){ + while(1){ + } + } + + /* HXTAL is stable */ + /* AHB = SYSCLK */ + RCU_CFG0 |= RCU_AHB_CKSYS_DIV1; + /* APB2 = AHB/1 */ + RCU_CFG0 |= RCU_APB2_CKAHB_DIV1; + /* APB1 = AHB/2 */ + RCU_CFG0 |= RCU_APB1_CKAHB_DIV2; + + /* CK_PLL = (CK_PREDIV0) * 7 = 56 MHz */ + RCU_CFG0 &= ~(RCU_CFG0_PLLMF | RCU_CFG0_PLLMF_4 | RCU_CFG0_PREDV0_LSB | RCU_CFG0_PLLSEL ); + RCU_CFG0 |= (RCU_PLLSRC_HXTAL | RCU_PLL_MUL7); + + /* CK_PREDIV0 = (CK_HXTAL) / 5 * 8 /5 = 8 MHz */ + RCU_CFG1 &= ~(RCU_CFG1_PREDV0SEL | RCU_CFG1_PLL1MF | RCU_CFG1_PREDV1 | RCU_CFG1_PREDV0); + RCU_CFG1 |= (RCU_PREDV0SRC_CKPLL1 | RCU_PLL1_MUL8 | RCU_PREDV1_DIV5 | RCU_PREDV0_DIV5); + + /* enable PLL1 */ + RCU_CTL |= RCU_CTL_PLL1EN; + /* wait till PLL1 is ready */ + while((RCU_CTL & RCU_CTL_PLL1STB) == 0){ + } + + /* enable PLL */ + RCU_CTL |= RCU_CTL_PLLEN; + + /* wait until PLL is stable */ + while(0U == (RCU_CTL & RCU_CTL_PLLSTB)){ + } + + /* select PLL as system clock */ + RCU_CFG0 &= ~RCU_CFG0_SCS; + RCU_CFG0 |= RCU_CKSYSSRC_PLL; + + /* wait until PLL is selected as system clock */ + while(0U == (RCU_CFG0 & RCU_SCSS_PLL)){ + } +} + +#elif defined (__SYSTEM_CLOCK_72M_PLL_HXTAL) +/*! + \brief configure the system clock to 72M by PLL which selects HXTAL(8M) as its clock source + \param[in] none + \param[out] none + \retval none +*/ +static void system_clock_72m_hxtal(void) +{ + uint32_t timeout = 0U; + uint32_t stab_flag = 0U; + + /* enable HXTAL */ + RCU_CTL |= RCU_CTL_HXTALEN; + + /* wait until HXTAL is stable or the startup time is longer than HXTAL_STARTUP_TIMEOUT */ + do{ + timeout++; + stab_flag = (RCU_CTL & RCU_CTL_HXTALSTB); + }while((0U == stab_flag) && (HXTAL_STARTUP_TIMEOUT != timeout)); + + /* if fail */ + if(0U == (RCU_CTL & RCU_CTL_HXTALSTB)){ + while(1){ + } + } + + /* HXTAL is stable */ + /* AHB = SYSCLK */ + RCU_CFG0 |= RCU_AHB_CKSYS_DIV1; + /* APB2 = AHB/1 */ + RCU_CFG0 |= RCU_APB2_CKAHB_DIV1; + /* APB1 = AHB/2 */ + RCU_CFG0 |= RCU_APB1_CKAHB_DIV2; + + /* CK_PLL = (CK_PREDIV0) * 9 = 72 MHz */ + RCU_CFG0 &= ~(RCU_CFG0_PLLMF | RCU_CFG0_PLLMF_4 | RCU_CFG0_PREDV0_LSB | RCU_CFG0_PLLSEL ); + RCU_CFG0 |= (RCU_PLLSRC_HXTAL | RCU_PLL_MUL9); + + /* CK_PREDIV0 = (CK_HXTAL) / 5 * 8 /5 = 8 MHz */ + RCU_CFG1 &= ~(RCU_CFG1_PREDV0SEL | RCU_CFG1_PLL1MF | RCU_CFG1_PREDV1 | RCU_CFG1_PREDV0); + RCU_CFG1 |= (RCU_PREDV0SRC_CKPLL1 | RCU_PLL1_MUL8 | RCU_PREDV1_DIV5 | RCU_PREDV0_DIV5); + + + /* enable PLL1 */ + RCU_CTL |= RCU_CTL_PLL1EN; + /* wait till PLL1 is ready */ + while((RCU_CTL & RCU_CTL_PLL1STB) == 0){ + } + + /* enable PLL */ + RCU_CTL |= RCU_CTL_PLLEN; + + /* wait until PLL is stable */ + while(0U == (RCU_CTL & RCU_CTL_PLLSTB)){ + } + + /* select PLL as system clock */ + RCU_CFG0 &= ~RCU_CFG0_SCS; + RCU_CFG0 |= RCU_CKSYSSRC_PLL; + + /* wait until PLL is selected as system clock */ + while(0U == (RCU_CFG0 & RCU_SCSS_PLL)){ + } +} + +#elif defined (__SYSTEM_CLOCK_96M_PLL_HXTAL) +/*! + \brief configure the system clock to 96M by PLL which selects HXTAL(8M) as its clock source + \param[in] none + \param[out] none + \retval none +*/ +static void system_clock_96m_hxtal(void) +{ + uint32_t timeout = 0U; + uint32_t stab_flag = 0U; + + /* enable HXTAL */ + RCU_CTL |= RCU_CTL_HXTALEN; + + /* wait until HXTAL is stable or the startup time is longer than HXTAL_STARTUP_TIMEOUT */ + do{ + timeout++; + stab_flag = (RCU_CTL & RCU_CTL_HXTALSTB); + }while((0U == stab_flag) && (HXTAL_STARTUP_TIMEOUT != timeout)); + + /* if fail */ + if(0U == (RCU_CTL & RCU_CTL_HXTALSTB)){ + while(1){ + } + } + + /* HXTAL is stable */ + /* AHB = SYSCLK */ + RCU_CFG0 |= RCU_AHB_CKSYS_DIV1; + /* APB2 = AHB/1 */ + RCU_CFG0 |= RCU_APB2_CKAHB_DIV1; + /* APB1 = AHB/2 */ + RCU_CFG0 |= RCU_APB1_CKAHB_DIV2; + + /* CK_PLL = (CK_PREDIV0) * 12 = 96 MHz */ + RCU_CFG0 &= ~(RCU_CFG0_PLLMF | RCU_CFG0_PLLMF_4 | RCU_CFG0_PREDV0_LSB | RCU_CFG0_PLLSEL ); + RCU_CFG0 |= (RCU_PLLSRC_HXTAL | RCU_PLL_MUL12); + + /* CK_PREDIV0 = (CK_HXTAL) / 5 * 8 /5 = 8 MHz */ + RCU_CFG1 &= ~(RCU_CFG1_PREDV0SEL | RCU_CFG1_PLL1MF | RCU_CFG1_PREDV1 | RCU_CFG1_PREDV0); + RCU_CFG1 |= (RCU_PREDV0SRC_CKPLL1 | RCU_PLL1_MUL8 | RCU_PREDV1_DIV5 | RCU_PREDV0_DIV5); + + /* enable PLL1 */ + RCU_CTL |= RCU_CTL_PLL1EN; + /* wait till PLL1 is ready */ + while((RCU_CTL & RCU_CTL_PLL1STB) == 0){ + } + + /* enable PLL */ + RCU_CTL |= RCU_CTL_PLLEN; + + /* wait until PLL is stable */ + while(0U == (RCU_CTL & RCU_CTL_PLLSTB)){ + } + + /* select PLL as system clock */ + RCU_CFG0 &= ~RCU_CFG0_SCS; + RCU_CFG0 |= RCU_CKSYSSRC_PLL; + + /* wait until PLL is selected as system clock */ + while(0U == (RCU_CFG0 & RCU_SCSS_PLL)){ + } +} + +#elif defined (__SYSTEM_CLOCK_108M_PLL_HXTAL) +/*! + \brief configure the system clock to 108M by PLL which selects HXTAL(8M) as its clock source + \param[in] none + \param[out] none + \retval none +*/ +static void system_clock_108m_hxtal(void) +{ + uint32_t timeout = 0U; + uint32_t stab_flag = 0U; + + /* enable HXTAL */ + RCU_CTL |= RCU_CTL_HXTALEN; + + /* wait until HXTAL is stable or the startup time is longer than HXTAL_STARTUP_TIMEOUT */ + do{ + timeout++; + stab_flag = (RCU_CTL & RCU_CTL_HXTALSTB); + }while((0U == stab_flag) && (HXTAL_STARTUP_TIMEOUT != timeout)); + + /* if fail */ + if(0U == (RCU_CTL & RCU_CTL_HXTALSTB)){ + while(1){ + } + } + + /* HXTAL is stable */ + /* AHB = SYSCLK */ + RCU_CFG0 |= RCU_AHB_CKSYS_DIV1; + /* APB2 = AHB/1 */ + RCU_CFG0 |= RCU_APB2_CKAHB_DIV1; + /* APB1 = AHB/2 */ + RCU_CFG0 |= RCU_APB1_CKAHB_DIV2; + + /* CK_PLL = (CK_PREDIV0) * 9 = 108 MHz */ + RCU_CFG0 &= ~(RCU_CFG0_PLLMF | RCU_CFG0_PLLMF_4 | RCU_CFG0_PREDV0_LSB | RCU_CFG0_PLLSEL ); + RCU_CFG0 |= (RCU_PLLSRC_HXTAL | RCU_PLL_MUL9); + + /* CK_PREDIV0 = (CK_HXTAL) / 5 * 12 /5 = 12 MHz */ + RCU_CFG1 &= ~(RCU_CFG1_PREDV0SEL | RCU_CFG1_PLL1MF | RCU_CFG1_PREDV1 | RCU_CFG1_PREDV0); + RCU_CFG1 |= (RCU_PREDV0SRC_CKPLL1 | RCU_PLL1_MUL12 | RCU_PREDV1_DIV5 | RCU_PREDV0_DIV5); + + /* enable PLL1 */ + RCU_CTL |= RCU_CTL_PLL1EN; + /* wait till PLL1 is ready */ + while((RCU_CTL & RCU_CTL_PLL1STB) == 0){ + } + + /* enable PLL */ + RCU_CTL |= RCU_CTL_PLLEN; + + /* wait until PLL is stable */ + while(0U == (RCU_CTL & RCU_CTL_PLLSTB)){ + } + + /* select PLL as system clock */ + RCU_CFG0 &= ~RCU_CFG0_SCS; + RCU_CFG0 |= RCU_CKSYSSRC_PLL; + + /* wait until PLL is selected as system clock */ + while(0U == (RCU_CFG0 & RCU_SCSS_PLL)){ + } +} + +#elif defined (__SYSTEM_CLOCK_120M_PLL_HXTAL) +/*! + \brief configure the system clock to 120M by PLL which selects HXTAL(8M) as its clock source + \param[in] none + \param[out] none + \retval none +*/ +static void system_clock_120m_hxtal(void) +{ + uint32_t timeout = 0U; + uint32_t stab_flag = 0U; + + /* enable HXTAL */ + RCU_CTL |= RCU_CTL_HXTALEN; + + /* wait until HXTAL is stable or the startup time is longer than HXTAL_STARTUP_TIMEOUT */ + do{ + timeout++; + stab_flag = (RCU_CTL & RCU_CTL_HXTALSTB); + }while((0U == stab_flag) && (HXTAL_STARTUP_TIMEOUT != timeout)); + + /* if fail */ + if(0U == (RCU_CTL & RCU_CTL_HXTALSTB)){ + while(1){ + } + } + + /* HXTAL is stable */ + /* AHB = SYSCLK */ + RCU_CFG0 |= RCU_AHB_CKSYS_DIV1; + /* APB2 = AHB/1 */ + RCU_CFG0 |= RCU_APB2_CKAHB_DIV1; + /* APB1 = AHB/2 */ + RCU_CFG0 |= RCU_APB1_CKAHB_DIV2; + + /* CK_PLL = (CK_PREDIV0) * 10 = 120 MHz */ + RCU_CFG0 &= ~(RCU_CFG0_PLLMF | RCU_CFG0_PLLMF_4 | RCU_CFG0_PREDV0_LSB | RCU_CFG0_PLLSEL ); + RCU_CFG0 |= (RCU_PLLSRC_HXTAL | RCU_PLL_MUL10); + + /* CK_PREDIV0 = (CK_HXTAL) / 5 * 12 /5 = 12 MHz */ + RCU_CFG1 &= ~(RCU_CFG1_PREDV0SEL | RCU_CFG1_PLL1MF | RCU_CFG1_PREDV1 | RCU_CFG1_PREDV0); + RCU_CFG1 |= (RCU_PREDV0SRC_CKPLL1 | RCU_PLL1_MUL12 | RCU_PREDV1_DIV5 | RCU_PREDV0_DIV5); + + /* enable PLL1 */ + RCU_CTL |= RCU_CTL_PLL1EN; + /* wait till PLL1 is ready */ + while((RCU_CTL & RCU_CTL_PLL1STB) == 0U){ + } + + /* enable PLL */ + RCU_CTL |= RCU_CTL_PLLEN; + + /* wait until PLL is stable */ + while(0U == (RCU_CTL & RCU_CTL_PLLSTB)){ + } + + /* select PLL as system clock */ + RCU_CFG0 &= ~RCU_CFG0_SCS; + RCU_CFG0 |= RCU_CKSYSSRC_PLL; + + /* wait until PLL is selected as system clock */ + while(0U == (RCU_CFG0 & RCU_SCSS_PLL)){ + } +} + +#endif /* __SYSTEM_CLOCK_IRC8M */ + +/*! + \brief update the SystemCoreClock with current core clock retrieved from cpu registers + \param[in] none + \param[out] none + \retval none +*/ +void SystemCoreClockUpdate (void) +{ + uint32_t sws; + uint32_t pllsel, predv0sel, pllmf,ck_src; + uint32_t predv0, predv1, pll1mf; + + sws = GET_BITS(RCU_CFG0, 2, 3); + switch(sws){ + /* IRC8M is selected as CK_SYS */ + case SEL_IRC8M: + SystemCoreClock = IRC8M_VALUE; + break; + /* HXTAL is selected as CK_SYS */ + case SEL_HXTAL: + SystemCoreClock = HXTAL_VALUE; + break; + /* PLL is selected as CK_SYS */ + case SEL_PLL: + /* PLL clock source selection, HXTAL or IRC8M/2 */ + pllsel = (RCU_CFG0 & RCU_CFG0_PLLSEL); + + if (RCU_PLLSRC_HXTAL == pllsel) { + /* PLL clock source is HXTAL */ + ck_src = HXTAL_VALUE; + + predv0sel = (RCU_CFG1 & RCU_CFG1_PREDV0SEL); + /* source clock use PLL1 */ + if(RCU_PREDV0SRC_CKPLL1 == predv0sel){ + predv1 = (uint32_t)((RCU_CFG1 & RCU_CFG1_PREDV1) >> 4) + 1U; + pll1mf = (uint32_t)((RCU_CFG1 & RCU_CFG1_PLL1MF) >> 8) + 2U; + if(17U == pll1mf){ + pll1mf = 20U; + } + ck_src = (ck_src/predv1)*pll1mf; + } + predv0 = (RCU_CFG1 & RCU_CFG1_PREDV0) + 1U; + ck_src /= predv0; + }else{ + /* PLL clock source is IRC8M/2 */ + ck_src = IRC8M_VALUE/2U; + } + + /* PLL multiplication factor */ + pllmf = GET_BITS(RCU_CFG0, 18, 21); + + if((RCU_CFG0 & RCU_CFG0_PLLMF_4)){ + pllmf |= 0x10U; + } + + if(13U == pllmf){ + /* PLL source clock multiply by 6.5 */ + SystemCoreClock = ck_src*6U + ck_src/2U; + }else{ + if(pllmf < 15U){ + pllmf += 2U; + }else{ + pllmf += 1U; + } + SystemCoreClock = ck_src*pllmf; + } + + break; + /* IRC8M is selected as CK_SYS */ + default: + SystemCoreClock = IRC8M_VALUE; + break; + } + +} diff --git a/bsp/gd32/libraries/GD32F20x_Firmware_Library/CMSIS/cmsis_armcc.h b/bsp/gd32/libraries/GD32F20x_Firmware_Library/CMSIS/cmsis_armcc.h new file mode 100644 index 0000000000..74c49c67de --- /dev/null +++ b/bsp/gd32/libraries/GD32F20x_Firmware_Library/CMSIS/cmsis_armcc.h @@ -0,0 +1,734 @@ +/**************************************************************************//** + * @file cmsis_armcc.h + * @brief CMSIS Cortex-M Core Function/Instruction Header File + * @version V4.30 + * @date 20. October 2015 + ******************************************************************************/ +/* Copyright (c) 2009 - 2015 ARM LIMITED + + All rights reserved. + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + - Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + - Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + - Neither the name of ARM nor the names of its contributors may be used + to endorse or promote products derived from this software without + specific prior written permission. + * + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDERS AND CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + ---------------------------------------------------------------------------*/ + + +#ifndef __CMSIS_ARMCC_H +#define __CMSIS_ARMCC_H + + +#if defined(__ARMCC_VERSION) && (__ARMCC_VERSION < 400677) + #error "Please use ARM Compiler Toolchain V4.0.677 or later!" +#endif + +/* ########################### Core Function Access ########################### */ +/** \ingroup CMSIS_Core_FunctionInterface + \defgroup CMSIS_Core_RegAccFunctions CMSIS Core Register Access Functions + @{ + */ + +/* intrinsic void __enable_irq(); */ +/* intrinsic void __disable_irq(); */ + +/** + \brief Get Control Register + \details Returns the content of the Control Register. + \return Control Register value + */ +__STATIC_INLINE uint32_t __get_CONTROL(void) +{ + register uint32_t __regControl __ASM("control"); + return(__regControl); +} + + +/** + \brief Set Control Register + \details Writes the given value to the Control Register. + \param [in] control Control Register value to set + */ +__STATIC_INLINE void __set_CONTROL(uint32_t control) +{ + register uint32_t __regControl __ASM("control"); + __regControl = control; +} + + +/** + \brief Get IPSR Register + \details Returns the content of the IPSR Register. + \return IPSR Register value + */ +__STATIC_INLINE uint32_t __get_IPSR(void) +{ + register uint32_t __regIPSR __ASM("ipsr"); + return(__regIPSR); +} + + +/** + \brief Get APSR Register + \details Returns the content of the APSR Register. + \return APSR Register value + */ +__STATIC_INLINE uint32_t __get_APSR(void) +{ + register uint32_t __regAPSR __ASM("apsr"); + return(__regAPSR); +} + + +/** + \brief Get xPSR Register + \details Returns the content of the xPSR Register. + \return xPSR Register value + */ +__STATIC_INLINE uint32_t __get_xPSR(void) +{ + register uint32_t __regXPSR __ASM("xpsr"); + return(__regXPSR); +} + + +/** + \brief Get Process Stack Pointer + \details Returns the current value of the Process Stack Pointer (PSP). + \return PSP Register value + */ +__STATIC_INLINE uint32_t __get_PSP(void) +{ + register uint32_t __regProcessStackPointer __ASM("psp"); + return(__regProcessStackPointer); +} + + +/** + \brief Set Process Stack Pointer + \details Assigns the given value to the Process Stack Pointer (PSP). + \param [in] topOfProcStack Process Stack Pointer value to set + */ +__STATIC_INLINE void __set_PSP(uint32_t topOfProcStack) +{ + register uint32_t __regProcessStackPointer __ASM("psp"); + __regProcessStackPointer = topOfProcStack; +} + + +/** + \brief Get Main Stack Pointer + \details Returns the current value of the Main Stack Pointer (MSP). + \return MSP Register value + */ +__STATIC_INLINE uint32_t __get_MSP(void) +{ + register uint32_t __regMainStackPointer __ASM("msp"); + return(__regMainStackPointer); +} + + +/** + \brief Set Main Stack Pointer + \details Assigns the given value to the Main Stack Pointer (MSP). + \param [in] topOfMainStack Main Stack Pointer value to set + */ +__STATIC_INLINE void __set_MSP(uint32_t topOfMainStack) +{ + register uint32_t __regMainStackPointer __ASM("msp"); + __regMainStackPointer = topOfMainStack; +} + + +/** + \brief Get Priority Mask + \details Returns the current state of the priority mask bit from the Priority Mask Register. + \return Priority Mask value + */ +__STATIC_INLINE uint32_t __get_PRIMASK(void) +{ + register uint32_t __regPriMask __ASM("primask"); + return(__regPriMask); +} + + +/** + \brief Set Priority Mask + \details Assigns the given value to the Priority Mask Register. + \param [in] priMask Priority Mask + */ +__STATIC_INLINE void __set_PRIMASK(uint32_t priMask) +{ + register uint32_t __regPriMask __ASM("primask"); + __regPriMask = (priMask); +} + + +#if (__CORTEX_M >= 0x03U) || (__CORTEX_SC >= 300U) + +/** + \brief Enable FIQ + \details Enables FIQ interrupts by clearing the F-bit in the CPSR. + Can only be executed in Privileged modes. + */ +#define __enable_fault_irq __enable_fiq + + +/** + \brief Disable FIQ + \details Disables FIQ interrupts by setting the F-bit in the CPSR. + Can only be executed in Privileged modes. + */ +#define __disable_fault_irq __disable_fiq + + +/** + \brief Get Base Priority + \details Returns the current value of the Base Priority register. + \return Base Priority register value + */ +__STATIC_INLINE uint32_t __get_BASEPRI(void) +{ + register uint32_t __regBasePri __ASM("basepri"); + return(__regBasePri); +} + + +/** + \brief Set Base Priority + \details Assigns the given value to the Base Priority register. + \param [in] basePri Base Priority value to set + */ +__STATIC_INLINE void __set_BASEPRI(uint32_t basePri) +{ + register uint32_t __regBasePri __ASM("basepri"); + __regBasePri = (basePri & 0xFFU); +} + + +/** + \brief Set Base Priority with condition + \details Assigns the given value to the Base Priority register only if BASEPRI masking is disabled, + or the new value increases the BASEPRI priority level. + \param [in] basePri Base Priority value to set + */ +__STATIC_INLINE void __set_BASEPRI_MAX(uint32_t basePri) +{ + register uint32_t __regBasePriMax __ASM("basepri_max"); + __regBasePriMax = (basePri & 0xFFU); +} + + +/** + \brief Get Fault Mask + \details Returns the current value of the Fault Mask register. + \return Fault Mask register value + */ +__STATIC_INLINE uint32_t __get_FAULTMASK(void) +{ + register uint32_t __regFaultMask __ASM("faultmask"); + return(__regFaultMask); +} + + +/** + \brief Set Fault Mask + \details Assigns the given value to the Fault Mask register. + \param [in] faultMask Fault Mask value to set + */ +__STATIC_INLINE void __set_FAULTMASK(uint32_t faultMask) +{ + register uint32_t __regFaultMask __ASM("faultmask"); + __regFaultMask = (faultMask & (uint32_t)1); +} + +#endif /* (__CORTEX_M >= 0x03U) || (__CORTEX_SC >= 300U) */ + + +#if (__CORTEX_M == 0x04U) || (__CORTEX_M == 0x07U) + +/** + \brief Get FPSCR + \details Returns the current value of the Floating Point Status/Control register. + \return Floating Point Status/Control register value + */ +__STATIC_INLINE uint32_t __get_FPSCR(void) +{ +#if (__FPU_PRESENT == 1U) && (__FPU_USED == 1U) + register uint32_t __regfpscr __ASM("fpscr"); + return(__regfpscr); +#else + return(0U); +#endif +} + + +/** + \brief Set FPSCR + \details Assigns the given value to the Floating Point Status/Control register. + \param [in] fpscr Floating Point Status/Control value to set + */ +__STATIC_INLINE void __set_FPSCR(uint32_t fpscr) +{ +#if (__FPU_PRESENT == 1U) && (__FPU_USED == 1U) + register uint32_t __regfpscr __ASM("fpscr"); + __regfpscr = (fpscr); +#endif +} + +#endif /* (__CORTEX_M == 0x04U) || (__CORTEX_M == 0x07U) */ + + + +/*@} end of CMSIS_Core_RegAccFunctions */ + + +/* ########################## Core Instruction Access ######################### */ +/** \defgroup CMSIS_Core_InstructionInterface CMSIS Core Instruction Interface + Access to dedicated instructions + @{ +*/ + +/** + \brief No Operation + \details No Operation does nothing. This instruction can be used for code alignment purposes. + */ +#define __NOP __nop + + +/** + \brief Wait For Interrupt + \details Wait For Interrupt is a hint instruction that suspends execution until one of a number of events occurs. + */ +#define __WFI __wfi + + +/** + \brief Wait For Event + \details Wait For Event is a hint instruction that permits the processor to enter + a low-power state until one of a number of events occurs. + */ +#define __WFE __wfe + + +/** + \brief Send Event + \details Send Event is a hint instruction. It causes an event to be signaled to the CPU. + */ +#define __SEV __sev + + +/** + \brief Instruction Synchronization Barrier + \details Instruction Synchronization Barrier flushes the pipeline in the processor, + so that all instructions following the ISB are fetched from cache or memory, + after the instruction has been completed. + */ +#define __ISB() do {\ + __schedule_barrier();\ + __isb(0xF);\ + __schedule_barrier();\ + } while (0U) + +/** + \brief Data Synchronization Barrier + \details Acts as a special kind of Data Memory Barrier. + It completes when all explicit memory accesses before this instruction complete. + */ +#define __DSB() do {\ + __schedule_barrier();\ + __dsb(0xF);\ + __schedule_barrier();\ + } while (0U) + +/** + \brief Data Memory Barrier + \details Ensures the apparent order of the explicit memory operations before + and after the instruction, without ensuring their completion. + */ +#define __DMB() do {\ + __schedule_barrier();\ + __dmb(0xF);\ + __schedule_barrier();\ + } while (0U) + +/** + \brief Reverse byte order (32 bit) + \details Reverses the byte order in integer value. + \param [in] value Value to reverse + \return Reversed value + */ +#define __REV __rev + + +/** + \brief Reverse byte order (16 bit) + \details Reverses the byte order in two unsigned short values. + \param [in] value Value to reverse + \return Reversed value + */ +#ifndef __NO_EMBEDDED_ASM +__attribute__((section(".rev16_text"))) __STATIC_INLINE __ASM uint32_t __REV16(uint32_t value) +{ + rev16 r0, r0 + bx lr +} +#endif + +/** + \brief Reverse byte order in signed short value + \details Reverses the byte order in a signed short value with sign extension to integer. + \param [in] value Value to reverse + \return Reversed value + */ +#ifndef __NO_EMBEDDED_ASM +__attribute__((section(".revsh_text"))) __STATIC_INLINE __ASM int32_t __REVSH(int32_t value) +{ + revsh r0, r0 + bx lr +} +#endif + + +/** + \brief Rotate Right in unsigned value (32 bit) + \details Rotate Right (immediate) provides the value of the contents of a register rotated by a variable number of bits. + \param [in] value Value to rotate + \param [in] value Number of Bits to rotate + \return Rotated value + */ +#define __ROR __ror + + +/** + \brief Breakpoint + \details Causes the processor to enter Debug state. + Debug tools can use this to investigate system state when the instruction at a particular address is reached. + \param [in] value is ignored by the processor. + If required, a debugger can use it to store additional information about the breakpoint. + */ +#define __BKPT(value) __breakpoint(value) + + +/** + \brief Reverse bit order of value + \details Reverses the bit order of the given value. + \param [in] value Value to reverse + \return Reversed value + */ +#if (__CORTEX_M >= 0x03U) || (__CORTEX_SC >= 300U) + #define __RBIT __rbit +#else +__attribute__((always_inline)) __STATIC_INLINE uint32_t __RBIT(uint32_t value) +{ + uint32_t result; + int32_t s = 4 /*sizeof(v)*/ * 8 - 1; /* extra shift needed at end */ + + result = value; /* r will be reversed bits of v; first get LSB of v */ + for (value >>= 1U; value; value >>= 1U) + { + result <<= 1U; + result |= value & 1U; + s--; + } + result <<= s; /* shift when v's highest bits are zero */ + return(result); +} +#endif + + +/** + \brief Count leading zeros + \details Counts the number of leading zeros of a data value. + \param [in] value Value to count the leading zeros + \return number of leading zeros in value + */ +#define __CLZ __clz + + +#if (__CORTEX_M >= 0x03U) || (__CORTEX_SC >= 300U) + +/** + \brief LDR Exclusive (8 bit) + \details Executes a exclusive LDR instruction for 8 bit value. + \param [in] ptr Pointer to data + \return value of type uint8_t at (*ptr) + */ +#if defined(__ARMCC_VERSION) && (__ARMCC_VERSION < 5060020) + #define __LDREXB(ptr) ((uint8_t ) __ldrex(ptr)) +#else + #define __LDREXB(ptr) _Pragma("push") _Pragma("diag_suppress 3731") ((uint8_t ) __ldrex(ptr)) _Pragma("pop") +#endif + + +/** + \brief LDR Exclusive (16 bit) + \details Executes a exclusive LDR instruction for 16 bit values. + \param [in] ptr Pointer to data + \return value of type uint16_t at (*ptr) + */ +#if defined(__ARMCC_VERSION) && (__ARMCC_VERSION < 5060020) + #define __LDREXH(ptr) ((uint16_t) __ldrex(ptr)) +#else + #define __LDREXH(ptr) _Pragma("push") _Pragma("diag_suppress 3731") ((uint16_t) __ldrex(ptr)) _Pragma("pop") +#endif + + +/** + \brief LDR Exclusive (32 bit) + \details Executes a exclusive LDR instruction for 32 bit values. + \param [in] ptr Pointer to data + \return value of type uint32_t at (*ptr) + */ +#if defined(__ARMCC_VERSION) && (__ARMCC_VERSION < 5060020) + #define __LDREXW(ptr) ((uint32_t ) __ldrex(ptr)) +#else + #define __LDREXW(ptr) _Pragma("push") _Pragma("diag_suppress 3731") ((uint32_t ) __ldrex(ptr)) _Pragma("pop") +#endif + + +/** + \brief STR Exclusive (8 bit) + \details Executes a exclusive STR instruction for 8 bit values. + \param [in] value Value to store + \param [in] ptr Pointer to location + \return 0 Function succeeded + \return 1 Function failed + */ +#if defined(__ARMCC_VERSION) && (__ARMCC_VERSION < 5060020) + #define __STREXB(value, ptr) __strex(value, ptr) +#else + #define __STREXB(value, ptr) _Pragma("push") _Pragma("diag_suppress 3731") __strex(value, ptr) _Pragma("pop") +#endif + + +/** + \brief STR Exclusive (16 bit) + \details Executes a exclusive STR instruction for 16 bit values. + \param [in] value Value to store + \param [in] ptr Pointer to location + \return 0 Function succeeded + \return 1 Function failed + */ +#if defined(__ARMCC_VERSION) && (__ARMCC_VERSION < 5060020) + #define __STREXH(value, ptr) __strex(value, ptr) +#else + #define __STREXH(value, ptr) _Pragma("push") _Pragma("diag_suppress 3731") __strex(value, ptr) _Pragma("pop") +#endif + + +/** + \brief STR Exclusive (32 bit) + \details Executes a exclusive STR instruction for 32 bit values. + \param [in] value Value to store + \param [in] ptr Pointer to location + \return 0 Function succeeded + \return 1 Function failed + */ +#if defined(__ARMCC_VERSION) && (__ARMCC_VERSION < 5060020) + #define __STREXW(value, ptr) __strex(value, ptr) +#else + #define __STREXW(value, ptr) _Pragma("push") _Pragma("diag_suppress 3731") __strex(value, ptr) _Pragma("pop") +#endif + + +/** + \brief Remove the exclusive lock + \details Removes the exclusive lock which is created by LDREX. + */ +#define __CLREX __clrex + + +/** + \brief Signed Saturate + \details Saturates a signed value. + \param [in] value Value to be saturated + \param [in] sat Bit position to saturate to (1..32) + \return Saturated value + */ +#define __SSAT __ssat + + +/** + \brief Unsigned Saturate + \details Saturates an unsigned value. + \param [in] value Value to be saturated + \param [in] sat Bit position to saturate to (0..31) + \return Saturated value + */ +#define __USAT __usat + + +/** + \brief Rotate Right with Extend (32 bit) + \details Moves each bit of a bitstring right by one bit. + The carry input is shifted in at the left end of the bitstring. + \param [in] value Value to rotate + \return Rotated value + */ +#ifndef __NO_EMBEDDED_ASM +__attribute__((section(".rrx_text"))) __STATIC_INLINE __ASM uint32_t __RRX(uint32_t value) +{ + rrx r0, r0 + bx lr +} +#endif + + +/** + \brief LDRT Unprivileged (8 bit) + \details Executes a Unprivileged LDRT instruction for 8 bit value. + \param [in] ptr Pointer to data + \return value of type uint8_t at (*ptr) + */ +#define __LDRBT(ptr) ((uint8_t ) __ldrt(ptr)) + + +/** + \brief LDRT Unprivileged (16 bit) + \details Executes a Unprivileged LDRT instruction for 16 bit values. + \param [in] ptr Pointer to data + \return value of type uint16_t at (*ptr) + */ +#define __LDRHT(ptr) ((uint16_t) __ldrt(ptr)) + + +/** + \brief LDRT Unprivileged (32 bit) + \details Executes a Unprivileged LDRT instruction for 32 bit values. + \param [in] ptr Pointer to data + \return value of type uint32_t at (*ptr) + */ +#define __LDRT(ptr) ((uint32_t ) __ldrt(ptr)) + + +/** + \brief STRT Unprivileged (8 bit) + \details Executes a Unprivileged STRT instruction for 8 bit values. + \param [in] value Value to store + \param [in] ptr Pointer to location + */ +#define __STRBT(value, ptr) __strt(value, ptr) + + +/** + \brief STRT Unprivileged (16 bit) + \details Executes a Unprivileged STRT instruction for 16 bit values. + \param [in] value Value to store + \param [in] ptr Pointer to location + */ +#define __STRHT(value, ptr) __strt(value, ptr) + + +/** + \brief STRT Unprivileged (32 bit) + \details Executes a Unprivileged STRT instruction for 32 bit values. + \param [in] value Value to store + \param [in] ptr Pointer to location + */ +#define __STRT(value, ptr) __strt(value, ptr) + +#endif /* (__CORTEX_M >= 0x03U) || (__CORTEX_SC >= 300U) */ + +/*@}*/ /* end of group CMSIS_Core_InstructionInterface */ + + +/* ################### Compiler specific Intrinsics ########################### */ +/** \defgroup CMSIS_SIMD_intrinsics CMSIS SIMD Intrinsics + Access to dedicated SIMD instructions + @{ +*/ + +#if (__CORTEX_M >= 0x04U) /* only for Cortex-M4 and above */ + +#define __SADD8 __sadd8 +#define __QADD8 __qadd8 +#define __SHADD8 __shadd8 +#define __UADD8 __uadd8 +#define __UQADD8 __uqadd8 +#define __UHADD8 __uhadd8 +#define __SSUB8 __ssub8 +#define __QSUB8 __qsub8 +#define __SHSUB8 __shsub8 +#define __USUB8 __usub8 +#define __UQSUB8 __uqsub8 +#define __UHSUB8 __uhsub8 +#define __SADD16 __sadd16 +#define __QADD16 __qadd16 +#define __SHADD16 __shadd16 +#define __UADD16 __uadd16 +#define __UQADD16 __uqadd16 +#define __UHADD16 __uhadd16 +#define __SSUB16 __ssub16 +#define __QSUB16 __qsub16 +#define __SHSUB16 __shsub16 +#define __USUB16 __usub16 +#define __UQSUB16 __uqsub16 +#define __UHSUB16 __uhsub16 +#define __SASX __sasx +#define __QASX __qasx +#define __SHASX __shasx +#define __UASX __uasx +#define __UQASX __uqasx +#define __UHASX __uhasx +#define __SSAX __ssax +#define __QSAX __qsax +#define __SHSAX __shsax +#define __USAX __usax +#define __UQSAX __uqsax +#define __UHSAX __uhsax +#define __USAD8 __usad8 +#define __USADA8 __usada8 +#define __SSAT16 __ssat16 +#define __USAT16 __usat16 +#define __UXTB16 __uxtb16 +#define __UXTAB16 __uxtab16 +#define __SXTB16 __sxtb16 +#define __SXTAB16 __sxtab16 +#define __SMUAD __smuad +#define __SMUADX __smuadx +#define __SMLAD __smlad +#define __SMLADX __smladx +#define __SMLALD __smlald +#define __SMLALDX __smlaldx +#define __SMUSD __smusd +#define __SMUSDX __smusdx +#define __SMLSD __smlsd +#define __SMLSDX __smlsdx +#define __SMLSLD __smlsld +#define __SMLSLDX __smlsldx +#define __SEL __sel +#define __QADD __qadd +#define __QSUB __qsub + +#define __PKHBT(ARG1,ARG2,ARG3) ( ((((uint32_t)(ARG1)) ) & 0x0000FFFFUL) | \ + ((((uint32_t)(ARG2)) << (ARG3)) & 0xFFFF0000UL) ) + +#define __PKHTB(ARG1,ARG2,ARG3) ( ((((uint32_t)(ARG1)) ) & 0xFFFF0000UL) | \ + ((((uint32_t)(ARG2)) >> (ARG3)) & 0x0000FFFFUL) ) + +#define __SMMLA(ARG1,ARG2,ARG3) ( (int32_t)((((int64_t)(ARG1) * (ARG2)) + \ + ((int64_t)(ARG3) << 32U) ) >> 32U)) + +#endif /* (__CORTEX_M >= 0x04) */ +/*@} end of group CMSIS_SIMD_intrinsics */ + + +#endif /* __CMSIS_ARMCC_H */ diff --git a/bsp/gd32/libraries/GD32F20x_Firmware_Library/CMSIS/core_cm3.h b/bsp/gd32/libraries/GD32F20x_Firmware_Library/CMSIS/core_cm3.h new file mode 100644 index 0000000000..1b661b4421 --- /dev/null +++ b/bsp/gd32/libraries/GD32F20x_Firmware_Library/CMSIS/core_cm3.h @@ -0,0 +1,1638 @@ +/**************************************************************************//** + * @file core_cm3.h + * @brief CMSIS Cortex-M3 Core Peripheral Access Layer Header File + * @version V3.30 + * @date 17. February 2014 + * + * @note + * + ******************************************************************************/ +/* Copyright (c) 2009 - 2014 ARM LIMITED + + All rights reserved. + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + - Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + - Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + - Neither the name of ARM nor the names of its contributors may be used + to endorse or promote products derived from this software without + specific prior written permission. + * + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDERS AND CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + ---------------------------------------------------------------------------*/ + + +#if defined ( __ICCARM__ ) + #pragma system_include /* treat file as system include file for MISRA check */ +#endif + +#ifdef __cplusplus + extern "C" { +#endif + +#ifndef __CORE_CM3_H_GENERIC +#define __CORE_CM3_H_GENERIC + +/** \page CMSIS_MISRA_Exceptions MISRA-C:2004 Compliance Exceptions + CMSIS violates the following MISRA-C:2004 rules: + + \li Required Rule 8.5, object/function definition in header file.
+ Function definitions in header files are used to allow 'inlining'. + + \li Required Rule 18.4, declaration of union type or object of union type: '{...}'.
+ Unions are used for effective representation of core registers. + + \li Advisory Rule 19.7, Function-like macro defined.
+ Function-like macros are used to allow more efficient code. + */ + + +/******************************************************************************* + * CMSIS definitions + ******************************************************************************/ +/** \ingroup Cortex_M3 + @{ + */ + +/* CMSIS CM3 definitions */ +#define __CM3_CMSIS_VERSION_MAIN (0x03) /*!< [31:16] CMSIS HAL main version */ +#define __CM3_CMSIS_VERSION_SUB (0x20) /*!< [15:0] CMSIS HAL sub version */ +#define __CM3_CMSIS_VERSION ((__CM3_CMSIS_VERSION_MAIN << 16) | \ + __CM3_CMSIS_VERSION_SUB ) /*!< CMSIS HAL version number */ + +#define __CORTEX_M (0x03) /*!< Cortex-M Core */ + + +#if defined ( __CC_ARM ) + #define __ASM __asm /*!< asm keyword for ARM Compiler */ + #define __INLINE __inline /*!< inline keyword for ARM Compiler */ + #define __STATIC_INLINE static __inline + +#elif defined ( __GNUC__ ) + #define __ASM __asm /*!< asm keyword for GNU Compiler */ + #define __INLINE inline /*!< inline keyword for GNU Compiler */ + #define __STATIC_INLINE static inline + +#elif defined ( __ICCARM__ ) + #define __ASM __asm /*!< asm keyword for IAR Compiler */ + #define __INLINE inline /*!< inline keyword for IAR Compiler. Only available in High optimization mode! */ + #define __STATIC_INLINE static inline + +#elif defined ( __TMS470__ ) + #define __ASM __asm /*!< asm keyword for TI CCS Compiler */ + #define __STATIC_INLINE static inline + +#elif defined ( __TASKING__ ) + #define __ASM __asm /*!< asm keyword for TASKING Compiler */ + #define __INLINE inline /*!< inline keyword for TASKING Compiler */ + #define __STATIC_INLINE static inline + +#elif defined ( __CSMC__ ) /* Cosmic */ + #define __packed + #define __ASM _asm /*!< asm keyword for COSMIC Compiler */ + #define __INLINE inline /*use -pc99 on compile line !< inline keyword for COSMIC Compiler */ + #define __STATIC_INLINE static inline + +#endif + +/** __FPU_USED indicates whether an FPU is used or not. This core does not support an FPU at all +*/ +#define __FPU_USED 0 + +#if defined ( __CC_ARM ) + #if defined __TARGET_FPU_VFP + #warning "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" + #endif + +#elif defined ( __GNUC__ ) + #if defined (__VFP_FP__) && !defined(__SOFTFP__) + #warning "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" + #endif + +#elif defined ( __ICCARM__ ) + #if defined __ARMVFP__ + #warning "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" + #endif + +#elif defined ( __TMS470__ ) + #if defined __TI__VFP_SUPPORT____ + #warning "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" + #endif + +#elif defined ( __TASKING__ ) + #if defined __FPU_VFP__ + #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" + #endif + +#elif defined ( __CSMC__ ) /* Cosmic */ + #if ( __CSMC__ & 0x400) // FPU present for parser + #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" + #endif +#endif + +#include /* standard types definitions */ +#include /* Core Instruction Access */ +#include /* Core Function Access */ + +#endif /* __CORE_CM3_H_GENERIC */ + +#ifndef __CMSIS_GENERIC + +#ifndef __CORE_CM3_H_DEPENDANT +#define __CORE_CM3_H_DEPENDANT + +/* check device defines and use defaults */ +#if defined __CHECK_DEVICE_DEFINES + #ifndef __CM3_REV + #define __CM3_REV 0x0200 + #warning "__CM3_REV not defined in device header file; using default!" + #endif + + #ifndef __MPU_PRESENT + #define __MPU_PRESENT 0 + #warning "__MPU_PRESENT not defined in device header file; using default!" + #endif + + #ifndef __NVIC_PRIO_BITS + #define __NVIC_PRIO_BITS 4 + #warning "__NVIC_PRIO_BITS not defined in device header file; using default!" + #endif + + #ifndef __Vendor_SysTickConfig + #define __Vendor_SysTickConfig 0 + #warning "__Vendor_SysTickConfig not defined in device header file; using default!" + #endif +#endif + +/* IO definitions (access restrictions to peripheral registers) */ +/** + \defgroup CMSIS_glob_defs CMSIS Global Defines + + IO Type Qualifiers are used + \li to specify the access to peripheral variables. + \li for automatic generation of peripheral register debug information. +*/ +#ifdef __cplusplus + #define __I volatile /*!< Defines 'read only' permissions */ +#else + #define __I volatile const /*!< Defines 'read only' permissions */ +#endif +#define __O volatile /*!< Defines 'write only' permissions */ +#define __IO volatile /*!< Defines 'read / write' permissions */ + +/*@} end of group Cortex_M3 */ + + + +/******************************************************************************* + * Register Abstraction + Core Register contain: + - Core Register + - Core NVIC Register + - Core SCB Register + - Core SysTick Register + - Core Debug Register + - Core MPU Register + ******************************************************************************/ +/** \defgroup CMSIS_core_register Defines and Type Definitions + \brief Type definitions and defines for Cortex-M processor based devices. +*/ + +/** \ingroup CMSIS_core_register + \defgroup CMSIS_CORE Status and Control Registers + \brief Core Register type definitions. + @{ + */ + +/** \brief Union type to access the Application Program Status Register (APSR). + */ +typedef union +{ + struct + { +#if (__CORTEX_M != 0x04) + uint32_t _reserved0:27; /*!< bit: 0..26 Reserved */ +#else + uint32_t _reserved0:16; /*!< bit: 0..15 Reserved */ + uint32_t GE:4; /*!< bit: 16..19 Greater than or Equal flags */ + uint32_t _reserved1:7; /*!< bit: 20..26 Reserved */ +#endif + uint32_t Q:1; /*!< bit: 27 Saturation condition flag */ + uint32_t V:1; /*!< bit: 28 Overflow condition code flag */ + uint32_t C:1; /*!< bit: 29 Carry condition code flag */ + uint32_t Z:1; /*!< bit: 30 Zero condition code flag */ + uint32_t N:1; /*!< bit: 31 Negative condition code flag */ + } b; /*!< Structure used for bit access */ + uint32_t w; /*!< Type used for word access */ +} APSR_Type; + + +/** \brief Union type to access the Interrupt Program Status Register (IPSR). + */ +typedef union +{ + struct + { + uint32_t ISR:9; /*!< bit: 0.. 8 Exception number */ + uint32_t _reserved0:23; /*!< bit: 9..31 Reserved */ + } b; /*!< Structure used for bit access */ + uint32_t w; /*!< Type used for word access */ +} IPSR_Type; + + +/** \brief Union type to access the Special-Purpose Program Status Registers (xPSR). + */ +typedef union +{ + struct + { + uint32_t ISR:9; /*!< bit: 0.. 8 Exception number */ +#if (__CORTEX_M != 0x04) + uint32_t _reserved0:15; /*!< bit: 9..23 Reserved */ +#else + uint32_t _reserved0:7; /*!< bit: 9..15 Reserved */ + uint32_t GE:4; /*!< bit: 16..19 Greater than or Equal flags */ + uint32_t _reserved1:4; /*!< bit: 20..23 Reserved */ +#endif + uint32_t T:1; /*!< bit: 24 Thumb bit (read 0) */ + uint32_t IT:2; /*!< bit: 25..26 saved IT state (read 0) */ + uint32_t Q:1; /*!< bit: 27 Saturation condition flag */ + uint32_t V:1; /*!< bit: 28 Overflow condition code flag */ + uint32_t C:1; /*!< bit: 29 Carry condition code flag */ + uint32_t Z:1; /*!< bit: 30 Zero condition code flag */ + uint32_t N:1; /*!< bit: 31 Negative condition code flag */ + } b; /*!< Structure used for bit access */ + uint32_t w; /*!< Type used for word access */ +} xPSR_Type; + + +/** \brief Union type to access the Control Registers (CONTROL). + */ +typedef union +{ + struct + { + uint32_t nPRIV:1; /*!< bit: 0 Execution privilege in Thread mode */ + uint32_t SPSEL:1; /*!< bit: 1 Stack to be used */ + uint32_t FPCA:1; /*!< bit: 2 FP extension active flag */ + uint32_t _reserved0:29; /*!< bit: 3..31 Reserved */ + } b; /*!< Structure used for bit access */ + uint32_t w; /*!< Type used for word access */ +} CONTROL_Type; + +/*@} end of group CMSIS_CORE */ + + +/** \ingroup CMSIS_core_register + \defgroup CMSIS_NVIC Nested Vectored Interrupt Controller (NVIC) + \brief Type definitions for the NVIC Registers + @{ + */ + +/** \brief Structure type to access the Nested Vectored Interrupt Controller (NVIC). + */ +typedef struct +{ + __IO uint32_t ISER[8]; /*!< Offset: 0x000 (R/W) Interrupt Set Enable Register */ + uint32_t RESERVED0[24]; + __IO uint32_t ICER[8]; /*!< Offset: 0x080 (R/W) Interrupt Clear Enable Register */ + uint32_t RSERVED1[24]; + __IO uint32_t ISPR[8]; /*!< Offset: 0x100 (R/W) Interrupt Set Pending Register */ + uint32_t RESERVED2[24]; + __IO uint32_t ICPR[8]; /*!< Offset: 0x180 (R/W) Interrupt Clear Pending Register */ + uint32_t RESERVED3[24]; + __IO uint32_t IABR[8]; /*!< Offset: 0x200 (R/W) Interrupt Active bit Register */ + uint32_t RESERVED4[56]; + __IO uint8_t IP[240]; /*!< Offset: 0x300 (R/W) Interrupt Priority Register (8Bit wide) */ + uint32_t RESERVED5[644]; + __O uint32_t STIR; /*!< Offset: 0xE00 ( /W) Software Trigger Interrupt Register */ +} NVIC_Type; + +/* Software Triggered Interrupt Register Definitions */ +#define NVIC_STIR_INTID_Pos 0 /*!< STIR: INTLINESNUM Position */ +#define NVIC_STIR_INTID_Msk (0x1FFUL << NVIC_STIR_INTID_Pos) /*!< STIR: INTLINESNUM Mask */ + +/*@} end of group CMSIS_NVIC */ + + +/** \ingroup CMSIS_core_register + \defgroup CMSIS_SCB System Control Block (SCB) + \brief Type definitions for the System Control Block Registers + @{ + */ + +/** \brief Structure type to access the System Control Block (SCB). + */ +typedef struct +{ + __I uint32_t CPUID; /*!< Offset: 0x000 (R/ ) CPUID Base Register */ + __IO uint32_t ICSR; /*!< Offset: 0x004 (R/W) Interrupt Control and State Register */ + __IO uint32_t VTOR; /*!< Offset: 0x008 (R/W) Vector Table Offset Register */ + __IO uint32_t AIRCR; /*!< Offset: 0x00C (R/W) Application Interrupt and Reset Control Register */ + __IO uint32_t SCR; /*!< Offset: 0x010 (R/W) System Control Register */ + __IO uint32_t CCR; /*!< Offset: 0x014 (R/W) Configuration Control Register */ + __IO uint8_t SHP[12]; /*!< Offset: 0x018 (R/W) System Handlers Priority Registers (4-7, 8-11, 12-15) */ + __IO uint32_t SHCSR; /*!< Offset: 0x024 (R/W) System Handler Control and State Register */ + __IO uint32_t CFSR; /*!< Offset: 0x028 (R/W) Configurable Fault Status Register */ + __IO uint32_t HFSR; /*!< Offset: 0x02C (R/W) HardFault Status Register */ + __IO uint32_t DFSR; /*!< Offset: 0x030 (R/W) Debug Fault Status Register */ + __IO uint32_t MMFAR; /*!< Offset: 0x034 (R/W) MemManage Fault Address Register */ + __IO uint32_t BFAR; /*!< Offset: 0x038 (R/W) BusFault Address Register */ + __IO uint32_t AFSR; /*!< Offset: 0x03C (R/W) Auxiliary Fault Status Register */ + __I uint32_t PFR[2]; /*!< Offset: 0x040 (R/ ) Processor Feature Register */ + __I uint32_t DFR; /*!< Offset: 0x048 (R/ ) Debug Feature Register */ + __I uint32_t ADR; /*!< Offset: 0x04C (R/ ) Auxiliary Feature Register */ + __I uint32_t MMFR[4]; /*!< Offset: 0x050 (R/ ) Memory Model Feature Register */ + __I uint32_t ISAR[5]; /*!< Offset: 0x060 (R/ ) Instruction Set Attributes Register */ + uint32_t RESERVED0[5]; + __IO uint32_t CPACR; /*!< Offset: 0x088 (R/W) Coprocessor Access Control Register */ +} SCB_Type; + +/* SCB CPUID Register Definitions */ +#define SCB_CPUID_IMPLEMENTER_Pos 24 /*!< SCB CPUID: IMPLEMENTER Position */ +#define SCB_CPUID_IMPLEMENTER_Msk (0xFFUL << SCB_CPUID_IMPLEMENTER_Pos) /*!< SCB CPUID: IMPLEMENTER Mask */ + +#define SCB_CPUID_VARIANT_Pos 20 /*!< SCB CPUID: VARIANT Position */ +#define SCB_CPUID_VARIANT_Msk (0xFUL << SCB_CPUID_VARIANT_Pos) /*!< SCB CPUID: VARIANT Mask */ + +#define SCB_CPUID_ARCHITECTURE_Pos 16 /*!< SCB CPUID: ARCHITECTURE Position */ +#define SCB_CPUID_ARCHITECTURE_Msk (0xFUL << SCB_CPUID_ARCHITECTURE_Pos) /*!< SCB CPUID: ARCHITECTURE Mask */ + +#define SCB_CPUID_PARTNO_Pos 4 /*!< SCB CPUID: PARTNO Position */ +#define SCB_CPUID_PARTNO_Msk (0xFFFUL << SCB_CPUID_PARTNO_Pos) /*!< SCB CPUID: PARTNO Mask */ + +#define SCB_CPUID_REVISION_Pos 0 /*!< SCB CPUID: REVISION Position */ +#define SCB_CPUID_REVISION_Msk (0xFUL << SCB_CPUID_REVISION_Pos) /*!< SCB CPUID: REVISION Mask */ + +/* SCB Interrupt Control State Register Definitions */ +#define SCB_ICSR_NMIPENDSET_Pos 31 /*!< SCB ICSR: NMIPENDSET Position */ +#define SCB_ICSR_NMIPENDSET_Msk (1UL << SCB_ICSR_NMIPENDSET_Pos) /*!< SCB ICSR: NMIPENDSET Mask */ + +#define SCB_ICSR_PENDSVSET_Pos 28 /*!< SCB ICSR: PENDSVSET Position */ +#define SCB_ICSR_PENDSVSET_Msk (1UL << SCB_ICSR_PENDSVSET_Pos) /*!< SCB ICSR: PENDSVSET Mask */ + +#define SCB_ICSR_PENDSVCLR_Pos 27 /*!< SCB ICSR: PENDSVCLR Position */ +#define SCB_ICSR_PENDSVCLR_Msk (1UL << SCB_ICSR_PENDSVCLR_Pos) /*!< SCB ICSR: PENDSVCLR Mask */ + +#define SCB_ICSR_PENDSTSET_Pos 26 /*!< SCB ICSR: PENDSTSET Position */ +#define SCB_ICSR_PENDSTSET_Msk (1UL << SCB_ICSR_PENDSTSET_Pos) /*!< SCB ICSR: PENDSTSET Mask */ + +#define SCB_ICSR_PENDSTCLR_Pos 25 /*!< SCB ICSR: PENDSTCLR Position */ +#define SCB_ICSR_PENDSTCLR_Msk (1UL << SCB_ICSR_PENDSTCLR_Pos) /*!< SCB ICSR: PENDSTCLR Mask */ + +#define SCB_ICSR_ISRPREEMPT_Pos 23 /*!< SCB ICSR: ISRPREEMPT Position */ +#define SCB_ICSR_ISRPREEMPT_Msk (1UL << SCB_ICSR_ISRPREEMPT_Pos) /*!< SCB ICSR: ISRPREEMPT Mask */ + +#define SCB_ICSR_ISRPENDING_Pos 22 /*!< SCB ICSR: ISRPENDING Position */ +#define SCB_ICSR_ISRPENDING_Msk (1UL << SCB_ICSR_ISRPENDING_Pos) /*!< SCB ICSR: ISRPENDING Mask */ + +#define SCB_ICSR_VECTPENDING_Pos 12 /*!< SCB ICSR: VECTPENDING Position */ +#define SCB_ICSR_VECTPENDING_Msk (0x1FFUL << SCB_ICSR_VECTPENDING_Pos) /*!< SCB ICSR: VECTPENDING Mask */ + +#define SCB_ICSR_RETTOBASE_Pos 11 /*!< SCB ICSR: RETTOBASE Position */ +#define SCB_ICSR_RETTOBASE_Msk (1UL << SCB_ICSR_RETTOBASE_Pos) /*!< SCB ICSR: RETTOBASE Mask */ + +#define SCB_ICSR_VECTACTIVE_Pos 0 /*!< SCB ICSR: VECTACTIVE Position */ +#define SCB_ICSR_VECTACTIVE_Msk (0x1FFUL << SCB_ICSR_VECTACTIVE_Pos) /*!< SCB ICSR: VECTACTIVE Mask */ + +/* SCB Vector Table Offset Register Definitions */ +#if (__CM3_REV < 0x0201) /* core r2p1 */ +#define SCB_VTOR_TBLBASE_Pos 29 /*!< SCB VTOR: TBLBASE Position */ +#define SCB_VTOR_TBLBASE_Msk (1UL << SCB_VTOR_TBLBASE_Pos) /*!< SCB VTOR: TBLBASE Mask */ + +#define SCB_VTOR_TBLOFF_Pos 7 /*!< SCB VTOR: TBLOFF Position */ +#define SCB_VTOR_TBLOFF_Msk (0x3FFFFFUL << SCB_VTOR_TBLOFF_Pos) /*!< SCB VTOR: TBLOFF Mask */ +#else +#define SCB_VTOR_TBLOFF_Pos 7 /*!< SCB VTOR: TBLOFF Position */ +#define SCB_VTOR_TBLOFF_Msk (0x1FFFFFFUL << SCB_VTOR_TBLOFF_Pos) /*!< SCB VTOR: TBLOFF Mask */ +#endif + +/* SCB Application Interrupt and Reset Control Register Definitions */ +#define SCB_AIRCR_VECTKEY_Pos 16 /*!< SCB AIRCR: VECTKEY Position */ +#define SCB_AIRCR_VECTKEY_Msk (0xFFFFUL << SCB_AIRCR_VECTKEY_Pos) /*!< SCB AIRCR: VECTKEY Mask */ + +#define SCB_AIRCR_VECTKEYSTAT_Pos 16 /*!< SCB AIRCR: VECTKEYSTAT Position */ +#define SCB_AIRCR_VECTKEYSTAT_Msk (0xFFFFUL << SCB_AIRCR_VECTKEYSTAT_Pos) /*!< SCB AIRCR: VECTKEYSTAT Mask */ + +#define SCB_AIRCR_ENDIANESS_Pos 15 /*!< SCB AIRCR: ENDIANESS Position */ +#define SCB_AIRCR_ENDIANESS_Msk (1UL << SCB_AIRCR_ENDIANESS_Pos) /*!< SCB AIRCR: ENDIANESS Mask */ + +#define SCB_AIRCR_PRIGROUP_Pos 8 /*!< SCB AIRCR: PRIGROUP Position */ +#define SCB_AIRCR_PRIGROUP_Msk (7UL << SCB_AIRCR_PRIGROUP_Pos) /*!< SCB AIRCR: PRIGROUP Mask */ + +#define SCB_AIRCR_SYSRESETREQ_Pos 2 /*!< SCB AIRCR: SYSRESETREQ Position */ +#define SCB_AIRCR_SYSRESETREQ_Msk (1UL << SCB_AIRCR_SYSRESETREQ_Pos) /*!< SCB AIRCR: SYSRESETREQ Mask */ + +#define SCB_AIRCR_VECTCLRACTIVE_Pos 1 /*!< SCB AIRCR: VECTCLRACTIVE Position */ +#define SCB_AIRCR_VECTCLRACTIVE_Msk (1UL << SCB_AIRCR_VECTCLRACTIVE_Pos) /*!< SCB AIRCR: VECTCLRACTIVE Mask */ + +#define SCB_AIRCR_VECTRESET_Pos 0 /*!< SCB AIRCR: VECTRESET Position */ +#define SCB_AIRCR_VECTRESET_Msk (1UL << SCB_AIRCR_VECTRESET_Pos) /*!< SCB AIRCR: VECTRESET Mask */ + +/* SCB System Control Register Definitions */ +#define SCB_SCR_SEVONPEND_Pos 4 /*!< SCB SCR: SEVONPEND Position */ +#define SCB_SCR_SEVONPEND_Msk (1UL << SCB_SCR_SEVONPEND_Pos) /*!< SCB SCR: SEVONPEND Mask */ + +#define SCB_SCR_SLEEPDEEP_Pos 2 /*!< SCB SCR: SLEEPDEEP Position */ +#define SCB_SCR_SLEEPDEEP_Msk (1UL << SCB_SCR_SLEEPDEEP_Pos) /*!< SCB SCR: SLEEPDEEP Mask */ + +#define SCB_SCR_SLEEPONEXIT_Pos 1 /*!< SCB SCR: SLEEPONEXIT Position */ +#define SCB_SCR_SLEEPONEXIT_Msk (1UL << SCB_SCR_SLEEPONEXIT_Pos) /*!< SCB SCR: SLEEPONEXIT Mask */ + +/* SCB Configuration Control Register Definitions */ +#define SCB_CCR_STKALIGN_Pos 9 /*!< SCB CCR: STKALIGN Position */ +#define SCB_CCR_STKALIGN_Msk (1UL << SCB_CCR_STKALIGN_Pos) /*!< SCB CCR: STKALIGN Mask */ + +#define SCB_CCR_BFHFNMIGN_Pos 8 /*!< SCB CCR: BFHFNMIGN Position */ +#define SCB_CCR_BFHFNMIGN_Msk (1UL << SCB_CCR_BFHFNMIGN_Pos) /*!< SCB CCR: BFHFNMIGN Mask */ + +#define SCB_CCR_DIV_0_TRP_Pos 4 /*!< SCB CCR: DIV_0_TRP Position */ +#define SCB_CCR_DIV_0_TRP_Msk (1UL << SCB_CCR_DIV_0_TRP_Pos) /*!< SCB CCR: DIV_0_TRP Mask */ + +#define SCB_CCR_UNALIGN_TRP_Pos 3 /*!< SCB CCR: UNALIGN_TRP Position */ +#define SCB_CCR_UNALIGN_TRP_Msk (1UL << SCB_CCR_UNALIGN_TRP_Pos) /*!< SCB CCR: UNALIGN_TRP Mask */ + +#define SCB_CCR_USERSETMPEND_Pos 1 /*!< SCB CCR: USERSETMPEND Position */ +#define SCB_CCR_USERSETMPEND_Msk (1UL << SCB_CCR_USERSETMPEND_Pos) /*!< SCB CCR: USERSETMPEND Mask */ + +#define SCB_CCR_NONBASETHRDENA_Pos 0 /*!< SCB CCR: NONBASETHRDENA Position */ +#define SCB_CCR_NONBASETHRDENA_Msk (1UL << SCB_CCR_NONBASETHRDENA_Pos) /*!< SCB CCR: NONBASETHRDENA Mask */ + +/* SCB System Handler Control and State Register Definitions */ +#define SCB_SHCSR_USGFAULTENA_Pos 18 /*!< SCB SHCSR: USGFAULTENA Position */ +#define SCB_SHCSR_USGFAULTENA_Msk (1UL << SCB_SHCSR_USGFAULTENA_Pos) /*!< SCB SHCSR: USGFAULTENA Mask */ + +#define SCB_SHCSR_BUSFAULTENA_Pos 17 /*!< SCB SHCSR: BUSFAULTENA Position */ +#define SCB_SHCSR_BUSFAULTENA_Msk (1UL << SCB_SHCSR_BUSFAULTENA_Pos) /*!< SCB SHCSR: BUSFAULTENA Mask */ + +#define SCB_SHCSR_MEMFAULTENA_Pos 16 /*!< SCB SHCSR: MEMFAULTENA Position */ +#define SCB_SHCSR_MEMFAULTENA_Msk (1UL << SCB_SHCSR_MEMFAULTENA_Pos) /*!< SCB SHCSR: MEMFAULTENA Mask */ + +#define SCB_SHCSR_SVCALLPENDED_Pos 15 /*!< SCB SHCSR: SVCALLPENDED Position */ +#define SCB_SHCSR_SVCALLPENDED_Msk (1UL << SCB_SHCSR_SVCALLPENDED_Pos) /*!< SCB SHCSR: SVCALLPENDED Mask */ + +#define SCB_SHCSR_BUSFAULTPENDED_Pos 14 /*!< SCB SHCSR: BUSFAULTPENDED Position */ +#define SCB_SHCSR_BUSFAULTPENDED_Msk (1UL << SCB_SHCSR_BUSFAULTPENDED_Pos) /*!< SCB SHCSR: BUSFAULTPENDED Mask */ + +#define SCB_SHCSR_MEMFAULTPENDED_Pos 13 /*!< SCB SHCSR: MEMFAULTPENDED Position */ +#define SCB_SHCSR_MEMFAULTPENDED_Msk (1UL << SCB_SHCSR_MEMFAULTPENDED_Pos) /*!< SCB SHCSR: MEMFAULTPENDED Mask */ + +#define SCB_SHCSR_USGFAULTPENDED_Pos 12 /*!< SCB SHCSR: USGFAULTPENDED Position */ +#define SCB_SHCSR_USGFAULTPENDED_Msk (1UL << SCB_SHCSR_USGFAULTPENDED_Pos) /*!< SCB SHCSR: USGFAULTPENDED Mask */ + +#define SCB_SHCSR_SYSTICKACT_Pos 11 /*!< SCB SHCSR: SYSTICKACT Position */ +#define SCB_SHCSR_SYSTICKACT_Msk (1UL << SCB_SHCSR_SYSTICKACT_Pos) /*!< SCB SHCSR: SYSTICKACT Mask */ + +#define SCB_SHCSR_PENDSVACT_Pos 10 /*!< SCB SHCSR: PENDSVACT Position */ +#define SCB_SHCSR_PENDSVACT_Msk (1UL << SCB_SHCSR_PENDSVACT_Pos) /*!< SCB SHCSR: PENDSVACT Mask */ + +#define SCB_SHCSR_MONITORACT_Pos 8 /*!< SCB SHCSR: MONITORACT Position */ +#define SCB_SHCSR_MONITORACT_Msk (1UL << SCB_SHCSR_MONITORACT_Pos) /*!< SCB SHCSR: MONITORACT Mask */ + +#define SCB_SHCSR_SVCALLACT_Pos 7 /*!< SCB SHCSR: SVCALLACT Position */ +#define SCB_SHCSR_SVCALLACT_Msk (1UL << SCB_SHCSR_SVCALLACT_Pos) /*!< SCB SHCSR: SVCALLACT Mask */ + +#define SCB_SHCSR_USGFAULTACT_Pos 3 /*!< SCB SHCSR: USGFAULTACT Position */ +#define SCB_SHCSR_USGFAULTACT_Msk (1UL << SCB_SHCSR_USGFAULTACT_Pos) /*!< SCB SHCSR: USGFAULTACT Mask */ + +#define SCB_SHCSR_BUSFAULTACT_Pos 1 /*!< SCB SHCSR: BUSFAULTACT Position */ +#define SCB_SHCSR_BUSFAULTACT_Msk (1UL << SCB_SHCSR_BUSFAULTACT_Pos) /*!< SCB SHCSR: BUSFAULTACT Mask */ + +#define SCB_SHCSR_MEMFAULTACT_Pos 0 /*!< SCB SHCSR: MEMFAULTACT Position */ +#define SCB_SHCSR_MEMFAULTACT_Msk (1UL << SCB_SHCSR_MEMFAULTACT_Pos) /*!< SCB SHCSR: MEMFAULTACT Mask */ + +/* SCB Configurable Fault Status Registers Definitions */ +#define SCB_CFSR_USGFAULTSR_Pos 16 /*!< SCB CFSR: Usage Fault Status Register Position */ +#define SCB_CFSR_USGFAULTSR_Msk (0xFFFFUL << SCB_CFSR_USGFAULTSR_Pos) /*!< SCB CFSR: Usage Fault Status Register Mask */ + +#define SCB_CFSR_BUSFAULTSR_Pos 8 /*!< SCB CFSR: Bus Fault Status Register Position */ +#define SCB_CFSR_BUSFAULTSR_Msk (0xFFUL << SCB_CFSR_BUSFAULTSR_Pos) /*!< SCB CFSR: Bus Fault Status Register Mask */ + +#define SCB_CFSR_MEMFAULTSR_Pos 0 /*!< SCB CFSR: Memory Manage Fault Status Register Position */ +#define SCB_CFSR_MEMFAULTSR_Msk (0xFFUL << SCB_CFSR_MEMFAULTSR_Pos) /*!< SCB CFSR: Memory Manage Fault Status Register Mask */ + +/* SCB Hard Fault Status Registers Definitions */ +#define SCB_HFSR_DEBUGEVT_Pos 31 /*!< SCB HFSR: DEBUGEVT Position */ +#define SCB_HFSR_DEBUGEVT_Msk (1UL << SCB_HFSR_DEBUGEVT_Pos) /*!< SCB HFSR: DEBUGEVT Mask */ + +#define SCB_HFSR_FORCED_Pos 30 /*!< SCB HFSR: FORCED Position */ +#define SCB_HFSR_FORCED_Msk (1UL << SCB_HFSR_FORCED_Pos) /*!< SCB HFSR: FORCED Mask */ + +#define SCB_HFSR_VECTTBL_Pos 1 /*!< SCB HFSR: VECTTBL Position */ +#define SCB_HFSR_VECTTBL_Msk (1UL << SCB_HFSR_VECTTBL_Pos) /*!< SCB HFSR: VECTTBL Mask */ + +/* SCB Debug Fault Status Register Definitions */ +#define SCB_DFSR_EXTERNAL_Pos 4 /*!< SCB DFSR: EXTERNAL Position */ +#define SCB_DFSR_EXTERNAL_Msk (1UL << SCB_DFSR_EXTERNAL_Pos) /*!< SCB DFSR: EXTERNAL Mask */ + +#define SCB_DFSR_VCATCH_Pos 3 /*!< SCB DFSR: VCATCH Position */ +#define SCB_DFSR_VCATCH_Msk (1UL << SCB_DFSR_VCATCH_Pos) /*!< SCB DFSR: VCATCH Mask */ + +#define SCB_DFSR_DWTTRAP_Pos 2 /*!< SCB DFSR: DWTTRAP Position */ +#define SCB_DFSR_DWTTRAP_Msk (1UL << SCB_DFSR_DWTTRAP_Pos) /*!< SCB DFSR: DWTTRAP Mask */ + +#define SCB_DFSR_BKPT_Pos 1 /*!< SCB DFSR: BKPT Position */ +#define SCB_DFSR_BKPT_Msk (1UL << SCB_DFSR_BKPT_Pos) /*!< SCB DFSR: BKPT Mask */ + +#define SCB_DFSR_HALTED_Pos 0 /*!< SCB DFSR: HALTED Position */ +#define SCB_DFSR_HALTED_Msk (1UL << SCB_DFSR_HALTED_Pos) /*!< SCB DFSR: HALTED Mask */ + +/*@} end of group CMSIS_SCB */ + + +/** \ingroup CMSIS_core_register + \defgroup CMSIS_SCnSCB System Controls not in SCB (SCnSCB) + \brief Type definitions for the System Control and ID Register not in the SCB + @{ + */ + +/** \brief Structure type to access the System Control and ID Register not in the SCB. + */ +typedef struct +{ + uint32_t RESERVED0[1]; + __I uint32_t ICTR; /*!< Offset: 0x004 (R/ ) Interrupt Controller Type Register */ +#if ((defined __CM3_REV) && (__CM3_REV >= 0x200)) + __IO uint32_t ACTLR; /*!< Offset: 0x008 (R/W) Auxiliary Control Register */ +#else + uint32_t RESERVED1[1]; +#endif +} SCnSCB_Type; + +/* Interrupt Controller Type Register Definitions */ +#define SCnSCB_ICTR_INTLINESNUM_Pos 0 /*!< ICTR: INTLINESNUM Position */ +#define SCnSCB_ICTR_INTLINESNUM_Msk (0xFUL << SCnSCB_ICTR_INTLINESNUM_Pos) /*!< ICTR: INTLINESNUM Mask */ + +/* Auxiliary Control Register Definitions */ + +#define SCnSCB_ACTLR_DISFOLD_Pos 2 /*!< ACTLR: DISFOLD Position */ +#define SCnSCB_ACTLR_DISFOLD_Msk (1UL << SCnSCB_ACTLR_DISFOLD_Pos) /*!< ACTLR: DISFOLD Mask */ + +#define SCnSCB_ACTLR_DISDEFWBUF_Pos 1 /*!< ACTLR: DISDEFWBUF Position */ +#define SCnSCB_ACTLR_DISDEFWBUF_Msk (1UL << SCnSCB_ACTLR_DISDEFWBUF_Pos) /*!< ACTLR: DISDEFWBUF Mask */ + +#define SCnSCB_ACTLR_DISMCYCINT_Pos 0 /*!< ACTLR: DISMCYCINT Position */ +#define SCnSCB_ACTLR_DISMCYCINT_Msk (1UL << SCnSCB_ACTLR_DISMCYCINT_Pos) /*!< ACTLR: DISMCYCINT Mask */ + +/*@} end of group CMSIS_SCnotSCB */ + + +/** \ingroup CMSIS_core_register + \defgroup CMSIS_SysTick System Tick Timer (SysTick) + \brief Type definitions for the System Timer Registers. + @{ + */ + +/** \brief Structure type to access the System Timer (SysTick). + */ +typedef struct +{ + __IO uint32_t CTRL; /*!< Offset: 0x000 (R/W) SysTick Control and Status Register */ + __IO uint32_t LOAD; /*!< Offset: 0x004 (R/W) SysTick Reload Value Register */ + __IO uint32_t VAL; /*!< Offset: 0x008 (R/W) SysTick Current Value Register */ + __I uint32_t CALIB; /*!< Offset: 0x00C (R/ ) SysTick Calibration Register */ +} SysTick_Type; + +/* SysTick Control / Status Register Definitions */ +#define SysTick_CTRL_COUNTFLAG_Pos 16 /*!< SysTick CTRL: COUNTFLAG Position */ +#define SysTick_CTRL_COUNTFLAG_Msk (1UL << SysTick_CTRL_COUNTFLAG_Pos) /*!< SysTick CTRL: COUNTFLAG Mask */ + +#define SysTick_CTRL_CLKSOURCE_Pos 2 /*!< SysTick CTRL: CLKSOURCE Position */ +#define SysTick_CTRL_CLKSOURCE_Msk (1UL << SysTick_CTRL_CLKSOURCE_Pos) /*!< SysTick CTRL: CLKSOURCE Mask */ + +#define SysTick_CTRL_TICKINT_Pos 1 /*!< SysTick CTRL: TICKINT Position */ +#define SysTick_CTRL_TICKINT_Msk (1UL << SysTick_CTRL_TICKINT_Pos) /*!< SysTick CTRL: TICKINT Mask */ + +#define SysTick_CTRL_ENABLE_Pos 0 /*!< SysTick CTRL: ENABLE Position */ +#define SysTick_CTRL_ENABLE_Msk (1UL << SysTick_CTRL_ENABLE_Pos) /*!< SysTick CTRL: ENABLE Mask */ + +/* SysTick Reload Register Definitions */ +#define SysTick_LOAD_RELOAD_Pos 0 /*!< SysTick LOAD: RELOAD Position */ +#define SysTick_LOAD_RELOAD_Msk (0xFFFFFFUL << SysTick_LOAD_RELOAD_Pos) /*!< SysTick LOAD: RELOAD Mask */ + +/* SysTick Current Register Definitions */ +#define SysTick_VAL_CURRENT_Pos 0 /*!< SysTick VAL: CURRENT Position */ +#define SysTick_VAL_CURRENT_Msk (0xFFFFFFUL << SysTick_VAL_CURRENT_Pos) /*!< SysTick VAL: CURRENT Mask */ + +/* SysTick Calibration Register Definitions */ +#define SysTick_CALIB_NOREF_Pos 31 /*!< SysTick CALIB: NOREF Position */ +#define SysTick_CALIB_NOREF_Msk (1UL << SysTick_CALIB_NOREF_Pos) /*!< SysTick CALIB: NOREF Mask */ + +#define SysTick_CALIB_SKEW_Pos 30 /*!< SysTick CALIB: SKEW Position */ +#define SysTick_CALIB_SKEW_Msk (1UL << SysTick_CALIB_SKEW_Pos) /*!< SysTick CALIB: SKEW Mask */ + +#define SysTick_CALIB_TENMS_Pos 0 /*!< SysTick CALIB: TENMS Position */ +#define SysTick_CALIB_TENMS_Msk (0xFFFFFFUL << SysTick_VAL_CURRENT_Pos) /*!< SysTick CALIB: TENMS Mask */ + +/*@} end of group CMSIS_SysTick */ + + +/** \ingroup CMSIS_core_register + \defgroup CMSIS_ITM Instrumentation Trace Macrocell (ITM) + \brief Type definitions for the Instrumentation Trace Macrocell (ITM) + @{ + */ + +/** \brief Structure type to access the Instrumentation Trace Macrocell Register (ITM). + */ +typedef struct +{ + __O union + { + __O uint8_t u8; /*!< Offset: 0x000 ( /W) ITM Stimulus Port 8-bit */ + __O uint16_t u16; /*!< Offset: 0x000 ( /W) ITM Stimulus Port 16-bit */ + __O uint32_t u32; /*!< Offset: 0x000 ( /W) ITM Stimulus Port 32-bit */ + } PORT [32]; /*!< Offset: 0x000 ( /W) ITM Stimulus Port Registers */ + uint32_t RESERVED0[864]; + __IO uint32_t TER; /*!< Offset: 0xE00 (R/W) ITM Trace Enable Register */ + uint32_t RESERVED1[15]; + __IO uint32_t TPR; /*!< Offset: 0xE40 (R/W) ITM Trace Privilege Register */ + uint32_t RESERVED2[15]; + __IO uint32_t TCR; /*!< Offset: 0xE80 (R/W) ITM Trace Control Register */ + uint32_t RESERVED3[29]; + __O uint32_t IWR; /*!< Offset: 0xEF8 ( /W) ITM Integration Write Register */ + __I uint32_t IRR; /*!< Offset: 0xEFC (R/ ) ITM Integration Read Register */ + __IO uint32_t IMCR; /*!< Offset: 0xF00 (R/W) ITM Integration Mode Control Register */ + uint32_t RESERVED4[43]; + __O uint32_t LAR; /*!< Offset: 0xFB0 ( /W) ITM Lock Access Register */ + __I uint32_t LSR; /*!< Offset: 0xFB4 (R/ ) ITM Lock Status Register */ + uint32_t RESERVED5[6]; + __I uint32_t PID4; /*!< Offset: 0xFD0 (R/ ) ITM Peripheral Identification Register #4 */ + __I uint32_t PID5; /*!< Offset: 0xFD4 (R/ ) ITM Peripheral Identification Register #5 */ + __I uint32_t PID6; /*!< Offset: 0xFD8 (R/ ) ITM Peripheral Identification Register #6 */ + __I uint32_t PID7; /*!< Offset: 0xFDC (R/ ) ITM Peripheral Identification Register #7 */ + __I uint32_t PID0; /*!< Offset: 0xFE0 (R/ ) ITM Peripheral Identification Register #0 */ + __I uint32_t PID1; /*!< Offset: 0xFE4 (R/ ) ITM Peripheral Identification Register #1 */ + __I uint32_t PID2; /*!< Offset: 0xFE8 (R/ ) ITM Peripheral Identification Register #2 */ + __I uint32_t PID3; /*!< Offset: 0xFEC (R/ ) ITM Peripheral Identification Register #3 */ + __I uint32_t CID0; /*!< Offset: 0xFF0 (R/ ) ITM Component Identification Register #0 */ + __I uint32_t CID1; /*!< Offset: 0xFF4 (R/ ) ITM Component Identification Register #1 */ + __I uint32_t CID2; /*!< Offset: 0xFF8 (R/ ) ITM Component Identification Register #2 */ + __I uint32_t CID3; /*!< Offset: 0xFFC (R/ ) ITM Component Identification Register #3 */ +} ITM_Type; + +/* ITM Trace Privilege Register Definitions */ +#define ITM_TPR_PRIVMASK_Pos 0 /*!< ITM TPR: PRIVMASK Position */ +#define ITM_TPR_PRIVMASK_Msk (0xFUL << ITM_TPR_PRIVMASK_Pos) /*!< ITM TPR: PRIVMASK Mask */ + +/* ITM Trace Control Register Definitions */ +#define ITM_TCR_BUSY_Pos 23 /*!< ITM TCR: BUSY Position */ +#define ITM_TCR_BUSY_Msk (1UL << ITM_TCR_BUSY_Pos) /*!< ITM TCR: BUSY Mask */ + +#define ITM_TCR_TraceBusID_Pos 16 /*!< ITM TCR: ATBID Position */ +#define ITM_TCR_TraceBusID_Msk (0x7FUL << ITM_TCR_TraceBusID_Pos) /*!< ITM TCR: ATBID Mask */ + +#define ITM_TCR_GTSFREQ_Pos 10 /*!< ITM TCR: Global timestamp frequency Position */ +#define ITM_TCR_GTSFREQ_Msk (3UL << ITM_TCR_GTSFREQ_Pos) /*!< ITM TCR: Global timestamp frequency Mask */ + +#define ITM_TCR_TSPrescale_Pos 8 /*!< ITM TCR: TSPrescale Position */ +#define ITM_TCR_TSPrescale_Msk (3UL << ITM_TCR_TSPrescale_Pos) /*!< ITM TCR: TSPrescale Mask */ + +#define ITM_TCR_SWOENA_Pos 4 /*!< ITM TCR: SWOENA Position */ +#define ITM_TCR_SWOENA_Msk (1UL << ITM_TCR_SWOENA_Pos) /*!< ITM TCR: SWOENA Mask */ + +#define ITM_TCR_DWTENA_Pos 3 /*!< ITM TCR: DWTENA Position */ +#define ITM_TCR_DWTENA_Msk (1UL << ITM_TCR_DWTENA_Pos) /*!< ITM TCR: DWTENA Mask */ + +#define ITM_TCR_SYNCENA_Pos 2 /*!< ITM TCR: SYNCENA Position */ +#define ITM_TCR_SYNCENA_Msk (1UL << ITM_TCR_SYNCENA_Pos) /*!< ITM TCR: SYNCENA Mask */ + +#define ITM_TCR_TSENA_Pos 1 /*!< ITM TCR: TSENA Position */ +#define ITM_TCR_TSENA_Msk (1UL << ITM_TCR_TSENA_Pos) /*!< ITM TCR: TSENA Mask */ + +#define ITM_TCR_ITMENA_Pos 0 /*!< ITM TCR: ITM Enable bit Position */ +#define ITM_TCR_ITMENA_Msk (1UL << ITM_TCR_ITMENA_Pos) /*!< ITM TCR: ITM Enable bit Mask */ + +/* ITM Integration Write Register Definitions */ +#define ITM_IWR_ATVALIDM_Pos 0 /*!< ITM IWR: ATVALIDM Position */ +#define ITM_IWR_ATVALIDM_Msk (1UL << ITM_IWR_ATVALIDM_Pos) /*!< ITM IWR: ATVALIDM Mask */ + +/* ITM Integration Read Register Definitions */ +#define ITM_IRR_ATREADYM_Pos 0 /*!< ITM IRR: ATREADYM Position */ +#define ITM_IRR_ATREADYM_Msk (1UL << ITM_IRR_ATREADYM_Pos) /*!< ITM IRR: ATREADYM Mask */ + +/* ITM Integration Mode Control Register Definitions */ +#define ITM_IMCR_INTEGRATION_Pos 0 /*!< ITM IMCR: INTEGRATION Position */ +#define ITM_IMCR_INTEGRATION_Msk (1UL << ITM_IMCR_INTEGRATION_Pos) /*!< ITM IMCR: INTEGRATION Mask */ + +/* ITM Lock Status Register Definitions */ +#define ITM_LSR_ByteAcc_Pos 2 /*!< ITM LSR: ByteAcc Position */ +#define ITM_LSR_ByteAcc_Msk (1UL << ITM_LSR_ByteAcc_Pos) /*!< ITM LSR: ByteAcc Mask */ + +#define ITM_LSR_Access_Pos 1 /*!< ITM LSR: Access Position */ +#define ITM_LSR_Access_Msk (1UL << ITM_LSR_Access_Pos) /*!< ITM LSR: Access Mask */ + +#define ITM_LSR_Present_Pos 0 /*!< ITM LSR: Present Position */ +#define ITM_LSR_Present_Msk (1UL << ITM_LSR_Present_Pos) /*!< ITM LSR: Present Mask */ + +/*@}*/ /* end of group CMSIS_ITM */ + + +/** \ingroup CMSIS_core_register + \defgroup CMSIS_DWT Data Watchpoint and Trace (DWT) + \brief Type definitions for the Data Watchpoint and Trace (DWT) + @{ + */ + +/** \brief Structure type to access the Data Watchpoint and Trace Register (DWT). + */ +typedef struct +{ + __IO uint32_t CTRL; /*!< Offset: 0x000 (R/W) Control Register */ + __IO uint32_t CYCCNT; /*!< Offset: 0x004 (R/W) Cycle Count Register */ + __IO uint32_t CPICNT; /*!< Offset: 0x008 (R/W) CPI Count Register */ + __IO uint32_t EXCCNT; /*!< Offset: 0x00C (R/W) Exception Overhead Count Register */ + __IO uint32_t SLEEPCNT; /*!< Offset: 0x010 (R/W) Sleep Count Register */ + __IO uint32_t LSUCNT; /*!< Offset: 0x014 (R/W) LSU Count Register */ + __IO uint32_t FOLDCNT; /*!< Offset: 0x018 (R/W) Folded-instruction Count Register */ + __I uint32_t PCSR; /*!< Offset: 0x01C (R/ ) Program Counter Sample Register */ + __IO uint32_t COMP0; /*!< Offset: 0x020 (R/W) Comparator Register 0 */ + __IO uint32_t MASK0; /*!< Offset: 0x024 (R/W) Mask Register 0 */ + __IO uint32_t FUNCTION0; /*!< Offset: 0x028 (R/W) Function Register 0 */ + uint32_t RESERVED0[1]; + __IO uint32_t COMP1; /*!< Offset: 0x030 (R/W) Comparator Register 1 */ + __IO uint32_t MASK1; /*!< Offset: 0x034 (R/W) Mask Register 1 */ + __IO uint32_t FUNCTION1; /*!< Offset: 0x038 (R/W) Function Register 1 */ + uint32_t RESERVED1[1]; + __IO uint32_t COMP2; /*!< Offset: 0x040 (R/W) Comparator Register 2 */ + __IO uint32_t MASK2; /*!< Offset: 0x044 (R/W) Mask Register 2 */ + __IO uint32_t FUNCTION2; /*!< Offset: 0x048 (R/W) Function Register 2 */ + uint32_t RESERVED2[1]; + __IO uint32_t COMP3; /*!< Offset: 0x050 (R/W) Comparator Register 3 */ + __IO uint32_t MASK3; /*!< Offset: 0x054 (R/W) Mask Register 3 */ + __IO uint32_t FUNCTION3; /*!< Offset: 0x058 (R/W) Function Register 3 */ +} DWT_Type; + +/* DWT Control Register Definitions */ +#define DWT_CTRL_NUMCOMP_Pos 28 /*!< DWT CTRL: NUMCOMP Position */ +#define DWT_CTRL_NUMCOMP_Msk (0xFUL << DWT_CTRL_NUMCOMP_Pos) /*!< DWT CTRL: NUMCOMP Mask */ + +#define DWT_CTRL_NOTRCPKT_Pos 27 /*!< DWT CTRL: NOTRCPKT Position */ +#define DWT_CTRL_NOTRCPKT_Msk (0x1UL << DWT_CTRL_NOTRCPKT_Pos) /*!< DWT CTRL: NOTRCPKT Mask */ + +#define DWT_CTRL_NOEXTTRIG_Pos 26 /*!< DWT CTRL: NOEXTTRIG Position */ +#define DWT_CTRL_NOEXTTRIG_Msk (0x1UL << DWT_CTRL_NOEXTTRIG_Pos) /*!< DWT CTRL: NOEXTTRIG Mask */ + +#define DWT_CTRL_NOCYCCNT_Pos 25 /*!< DWT CTRL: NOCYCCNT Position */ +#define DWT_CTRL_NOCYCCNT_Msk (0x1UL << DWT_CTRL_NOCYCCNT_Pos) /*!< DWT CTRL: NOCYCCNT Mask */ + +#define DWT_CTRL_NOPRFCNT_Pos 24 /*!< DWT CTRL: NOPRFCNT Position */ +#define DWT_CTRL_NOPRFCNT_Msk (0x1UL << DWT_CTRL_NOPRFCNT_Pos) /*!< DWT CTRL: NOPRFCNT Mask */ + +#define DWT_CTRL_CYCEVTENA_Pos 22 /*!< DWT CTRL: CYCEVTENA Position */ +#define DWT_CTRL_CYCEVTENA_Msk (0x1UL << DWT_CTRL_CYCEVTENA_Pos) /*!< DWT CTRL: CYCEVTENA Mask */ + +#define DWT_CTRL_FOLDEVTENA_Pos 21 /*!< DWT CTRL: FOLDEVTENA Position */ +#define DWT_CTRL_FOLDEVTENA_Msk (0x1UL << DWT_CTRL_FOLDEVTENA_Pos) /*!< DWT CTRL: FOLDEVTENA Mask */ + +#define DWT_CTRL_LSUEVTENA_Pos 20 /*!< DWT CTRL: LSUEVTENA Position */ +#define DWT_CTRL_LSUEVTENA_Msk (0x1UL << DWT_CTRL_LSUEVTENA_Pos) /*!< DWT CTRL: LSUEVTENA Mask */ + +#define DWT_CTRL_SLEEPEVTENA_Pos 19 /*!< DWT CTRL: SLEEPEVTENA Position */ +#define DWT_CTRL_SLEEPEVTENA_Msk (0x1UL << DWT_CTRL_SLEEPEVTENA_Pos) /*!< DWT CTRL: SLEEPEVTENA Mask */ + +#define DWT_CTRL_EXCEVTENA_Pos 18 /*!< DWT CTRL: EXCEVTENA Position */ +#define DWT_CTRL_EXCEVTENA_Msk (0x1UL << DWT_CTRL_EXCEVTENA_Pos) /*!< DWT CTRL: EXCEVTENA Mask */ + +#define DWT_CTRL_CPIEVTENA_Pos 17 /*!< DWT CTRL: CPIEVTENA Position */ +#define DWT_CTRL_CPIEVTENA_Msk (0x1UL << DWT_CTRL_CPIEVTENA_Pos) /*!< DWT CTRL: CPIEVTENA Mask */ + +#define DWT_CTRL_EXCTRCENA_Pos 16 /*!< DWT CTRL: EXCTRCENA Position */ +#define DWT_CTRL_EXCTRCENA_Msk (0x1UL << DWT_CTRL_EXCTRCENA_Pos) /*!< DWT CTRL: EXCTRCENA Mask */ + +#define DWT_CTRL_PCSAMPLENA_Pos 12 /*!< DWT CTRL: PCSAMPLENA Position */ +#define DWT_CTRL_PCSAMPLENA_Msk (0x1UL << DWT_CTRL_PCSAMPLENA_Pos) /*!< DWT CTRL: PCSAMPLENA Mask */ + +#define DWT_CTRL_SYNCTAP_Pos 10 /*!< DWT CTRL: SYNCTAP Position */ +#define DWT_CTRL_SYNCTAP_Msk (0x3UL << DWT_CTRL_SYNCTAP_Pos) /*!< DWT CTRL: SYNCTAP Mask */ + +#define DWT_CTRL_CYCTAP_Pos 9 /*!< DWT CTRL: CYCTAP Position */ +#define DWT_CTRL_CYCTAP_Msk (0x1UL << DWT_CTRL_CYCTAP_Pos) /*!< DWT CTRL: CYCTAP Mask */ + +#define DWT_CTRL_POSTINIT_Pos 5 /*!< DWT CTRL: POSTINIT Position */ +#define DWT_CTRL_POSTINIT_Msk (0xFUL << DWT_CTRL_POSTINIT_Pos) /*!< DWT CTRL: POSTINIT Mask */ + +#define DWT_CTRL_POSTPRESET_Pos 1 /*!< DWT CTRL: POSTPRESET Position */ +#define DWT_CTRL_POSTPRESET_Msk (0xFUL << DWT_CTRL_POSTPRESET_Pos) /*!< DWT CTRL: POSTPRESET Mask */ + +#define DWT_CTRL_CYCCNTENA_Pos 0 /*!< DWT CTRL: CYCCNTENA Position */ +#define DWT_CTRL_CYCCNTENA_Msk (0x1UL << DWT_CTRL_CYCCNTENA_Pos) /*!< DWT CTRL: CYCCNTENA Mask */ + +/* DWT CPI Count Register Definitions */ +#define DWT_CPICNT_CPICNT_Pos 0 /*!< DWT CPICNT: CPICNT Position */ +#define DWT_CPICNT_CPICNT_Msk (0xFFUL << DWT_CPICNT_CPICNT_Pos) /*!< DWT CPICNT: CPICNT Mask */ + +/* DWT Exception Overhead Count Register Definitions */ +#define DWT_EXCCNT_EXCCNT_Pos 0 /*!< DWT EXCCNT: EXCCNT Position */ +#define DWT_EXCCNT_EXCCNT_Msk (0xFFUL << DWT_EXCCNT_EXCCNT_Pos) /*!< DWT EXCCNT: EXCCNT Mask */ + +/* DWT Sleep Count Register Definitions */ +#define DWT_SLEEPCNT_SLEEPCNT_Pos 0 /*!< DWT SLEEPCNT: SLEEPCNT Position */ +#define DWT_SLEEPCNT_SLEEPCNT_Msk (0xFFUL << DWT_SLEEPCNT_SLEEPCNT_Pos) /*!< DWT SLEEPCNT: SLEEPCNT Mask */ + +/* DWT LSU Count Register Definitions */ +#define DWT_LSUCNT_LSUCNT_Pos 0 /*!< DWT LSUCNT: LSUCNT Position */ +#define DWT_LSUCNT_LSUCNT_Msk (0xFFUL << DWT_LSUCNT_LSUCNT_Pos) /*!< DWT LSUCNT: LSUCNT Mask */ + +/* DWT Folded-instruction Count Register Definitions */ +#define DWT_FOLDCNT_FOLDCNT_Pos 0 /*!< DWT FOLDCNT: FOLDCNT Position */ +#define DWT_FOLDCNT_FOLDCNT_Msk (0xFFUL << DWT_FOLDCNT_FOLDCNT_Pos) /*!< DWT FOLDCNT: FOLDCNT Mask */ + +/* DWT Comparator Mask Register Definitions */ +#define DWT_MASK_MASK_Pos 0 /*!< DWT MASK: MASK Position */ +#define DWT_MASK_MASK_Msk (0x1FUL << DWT_MASK_MASK_Pos) /*!< DWT MASK: MASK Mask */ + +/* DWT Comparator Function Register Definitions */ +#define DWT_FUNCTION_MATCHED_Pos 24 /*!< DWT FUNCTION: MATCHED Position */ +#define DWT_FUNCTION_MATCHED_Msk (0x1UL << DWT_FUNCTION_MATCHED_Pos) /*!< DWT FUNCTION: MATCHED Mask */ + +#define DWT_FUNCTION_DATAVADDR1_Pos 16 /*!< DWT FUNCTION: DATAVADDR1 Position */ +#define DWT_FUNCTION_DATAVADDR1_Msk (0xFUL << DWT_FUNCTION_DATAVADDR1_Pos) /*!< DWT FUNCTION: DATAVADDR1 Mask */ + +#define DWT_FUNCTION_DATAVADDR0_Pos 12 /*!< DWT FUNCTION: DATAVADDR0 Position */ +#define DWT_FUNCTION_DATAVADDR0_Msk (0xFUL << DWT_FUNCTION_DATAVADDR0_Pos) /*!< DWT FUNCTION: DATAVADDR0 Mask */ + +#define DWT_FUNCTION_DATAVSIZE_Pos 10 /*!< DWT FUNCTION: DATAVSIZE Position */ +#define DWT_FUNCTION_DATAVSIZE_Msk (0x3UL << DWT_FUNCTION_DATAVSIZE_Pos) /*!< DWT FUNCTION: DATAVSIZE Mask */ + +#define DWT_FUNCTION_LNK1ENA_Pos 9 /*!< DWT FUNCTION: LNK1ENA Position */ +#define DWT_FUNCTION_LNK1ENA_Msk (0x1UL << DWT_FUNCTION_LNK1ENA_Pos) /*!< DWT FUNCTION: LNK1ENA Mask */ + +#define DWT_FUNCTION_DATAVMATCH_Pos 8 /*!< DWT FUNCTION: DATAVMATCH Position */ +#define DWT_FUNCTION_DATAVMATCH_Msk (0x1UL << DWT_FUNCTION_DATAVMATCH_Pos) /*!< DWT FUNCTION: DATAVMATCH Mask */ + +#define DWT_FUNCTION_CYCMATCH_Pos 7 /*!< DWT FUNCTION: CYCMATCH Position */ +#define DWT_FUNCTION_CYCMATCH_Msk (0x1UL << DWT_FUNCTION_CYCMATCH_Pos) /*!< DWT FUNCTION: CYCMATCH Mask */ + +#define DWT_FUNCTION_EMITRANGE_Pos 5 /*!< DWT FUNCTION: EMITRANGE Position */ +#define DWT_FUNCTION_EMITRANGE_Msk (0x1UL << DWT_FUNCTION_EMITRANGE_Pos) /*!< DWT FUNCTION: EMITRANGE Mask */ + +#define DWT_FUNCTION_FUNCTION_Pos 0 /*!< DWT FUNCTION: FUNCTION Position */ +#define DWT_FUNCTION_FUNCTION_Msk (0xFUL << DWT_FUNCTION_FUNCTION_Pos) /*!< DWT FUNCTION: FUNCTION Mask */ + +/*@}*/ /* end of group CMSIS_DWT */ + + +/** \ingroup CMSIS_core_register + \defgroup CMSIS_TPI Trace Port Interface (TPI) + \brief Type definitions for the Trace Port Interface (TPI) + @{ + */ + +/** \brief Structure type to access the Trace Port Interface Register (TPI). + */ +typedef struct +{ + __IO uint32_t SSPSR; /*!< Offset: 0x000 (R/ ) Supported Parallel Port Size Register */ + __IO uint32_t CSPSR; /*!< Offset: 0x004 (R/W) Current Parallel Port Size Register */ + uint32_t RESERVED0[2]; + __IO uint32_t ACPR; /*!< Offset: 0x010 (R/W) Asynchronous Clock Prescaler Register */ + uint32_t RESERVED1[55]; + __IO uint32_t SPPR; /*!< Offset: 0x0F0 (R/W) Selected Pin Protocol Register */ + uint32_t RESERVED2[131]; + __I uint32_t FFSR; /*!< Offset: 0x300 (R/ ) Formatter and Flush Status Register */ + __IO uint32_t FFCR; /*!< Offset: 0x304 (R/W) Formatter and Flush Control Register */ + __I uint32_t FSCR; /*!< Offset: 0x308 (R/ ) Formatter Synchronization Counter Register */ + uint32_t RESERVED3[759]; + __I uint32_t TRIGGER; /*!< Offset: 0xEE8 (R/ ) TRIGGER */ + __I uint32_t FIFO0; /*!< Offset: 0xEEC (R/ ) Integration ETM Data */ + __I uint32_t ITATBCTR2; /*!< Offset: 0xEF0 (R/ ) ITATBCTR2 */ + uint32_t RESERVED4[1]; + __I uint32_t ITATBCTR0; /*!< Offset: 0xEF8 (R/ ) ITATBCTR0 */ + __I uint32_t FIFO1; /*!< Offset: 0xEFC (R/ ) Integration ITM Data */ + __IO uint32_t ITCTRL; /*!< Offset: 0xF00 (R/W) Integration Mode Control */ + uint32_t RESERVED5[39]; + __IO uint32_t CLAIMSET; /*!< Offset: 0xFA0 (R/W) Claim tag set */ + __IO uint32_t CLAIMCLR; /*!< Offset: 0xFA4 (R/W) Claim tag clear */ + uint32_t RESERVED7[8]; + __I uint32_t DEVID; /*!< Offset: 0xFC8 (R/ ) TPIU_DEVID */ + __I uint32_t DEVTYPE; /*!< Offset: 0xFCC (R/ ) TPIU_DEVTYPE */ +} TPI_Type; + +/* TPI Asynchronous Clock Prescaler Register Definitions */ +#define TPI_ACPR_PRESCALER_Pos 0 /*!< TPI ACPR: PRESCALER Position */ +#define TPI_ACPR_PRESCALER_Msk (0x1FFFUL << TPI_ACPR_PRESCALER_Pos) /*!< TPI ACPR: PRESCALER Mask */ + +/* TPI Selected Pin Protocol Register Definitions */ +#define TPI_SPPR_TXMODE_Pos 0 /*!< TPI SPPR: TXMODE Position */ +#define TPI_SPPR_TXMODE_Msk (0x3UL << TPI_SPPR_TXMODE_Pos) /*!< TPI SPPR: TXMODE Mask */ + +/* TPI Formatter and Flush Status Register Definitions */ +#define TPI_FFSR_FtNonStop_Pos 3 /*!< TPI FFSR: FtNonStop Position */ +#define TPI_FFSR_FtNonStop_Msk (0x1UL << TPI_FFSR_FtNonStop_Pos) /*!< TPI FFSR: FtNonStop Mask */ + +#define TPI_FFSR_TCPresent_Pos 2 /*!< TPI FFSR: TCPresent Position */ +#define TPI_FFSR_TCPresent_Msk (0x1UL << TPI_FFSR_TCPresent_Pos) /*!< TPI FFSR: TCPresent Mask */ + +#define TPI_FFSR_FtStopped_Pos 1 /*!< TPI FFSR: FtStopped Position */ +#define TPI_FFSR_FtStopped_Msk (0x1UL << TPI_FFSR_FtStopped_Pos) /*!< TPI FFSR: FtStopped Mask */ + +#define TPI_FFSR_FlInProg_Pos 0 /*!< TPI FFSR: FlInProg Position */ +#define TPI_FFSR_FlInProg_Msk (0x1UL << TPI_FFSR_FlInProg_Pos) /*!< TPI FFSR: FlInProg Mask */ + +/* TPI Formatter and Flush Control Register Definitions */ +#define TPI_FFCR_TrigIn_Pos 8 /*!< TPI FFCR: TrigIn Position */ +#define TPI_FFCR_TrigIn_Msk (0x1UL << TPI_FFCR_TrigIn_Pos) /*!< TPI FFCR: TrigIn Mask */ + +#define TPI_FFCR_EnFCont_Pos 1 /*!< TPI FFCR: EnFCont Position */ +#define TPI_FFCR_EnFCont_Msk (0x1UL << TPI_FFCR_EnFCont_Pos) /*!< TPI FFCR: EnFCont Mask */ + +/* TPI TRIGGER Register Definitions */ +#define TPI_TRIGGER_TRIGGER_Pos 0 /*!< TPI TRIGGER: TRIGGER Position */ +#define TPI_TRIGGER_TRIGGER_Msk (0x1UL << TPI_TRIGGER_TRIGGER_Pos) /*!< TPI TRIGGER: TRIGGER Mask */ + +/* TPI Integration ETM Data Register Definitions (FIFO0) */ +#define TPI_FIFO0_ITM_ATVALID_Pos 29 /*!< TPI FIFO0: ITM_ATVALID Position */ +#define TPI_FIFO0_ITM_ATVALID_Msk (0x3UL << TPI_FIFO0_ITM_ATVALID_Pos) /*!< TPI FIFO0: ITM_ATVALID Mask */ + +#define TPI_FIFO0_ITM_bytecount_Pos 27 /*!< TPI FIFO0: ITM_bytecount Position */ +#define TPI_FIFO0_ITM_bytecount_Msk (0x3UL << TPI_FIFO0_ITM_bytecount_Pos) /*!< TPI FIFO0: ITM_bytecount Mask */ + +#define TPI_FIFO0_ETM_ATVALID_Pos 26 /*!< TPI FIFO0: ETM_ATVALID Position */ +#define TPI_FIFO0_ETM_ATVALID_Msk (0x3UL << TPI_FIFO0_ETM_ATVALID_Pos) /*!< TPI FIFO0: ETM_ATVALID Mask */ + +#define TPI_FIFO0_ETM_bytecount_Pos 24 /*!< TPI FIFO0: ETM_bytecount Position */ +#define TPI_FIFO0_ETM_bytecount_Msk (0x3UL << TPI_FIFO0_ETM_bytecount_Pos) /*!< TPI FIFO0: ETM_bytecount Mask */ + +#define TPI_FIFO0_ETM2_Pos 16 /*!< TPI FIFO0: ETM2 Position */ +#define TPI_FIFO0_ETM2_Msk (0xFFUL << TPI_FIFO0_ETM2_Pos) /*!< TPI FIFO0: ETM2 Mask */ + +#define TPI_FIFO0_ETM1_Pos 8 /*!< TPI FIFO0: ETM1 Position */ +#define TPI_FIFO0_ETM1_Msk (0xFFUL << TPI_FIFO0_ETM1_Pos) /*!< TPI FIFO0: ETM1 Mask */ + +#define TPI_FIFO0_ETM0_Pos 0 /*!< TPI FIFO0: ETM0 Position */ +#define TPI_FIFO0_ETM0_Msk (0xFFUL << TPI_FIFO0_ETM0_Pos) /*!< TPI FIFO0: ETM0 Mask */ + +/* TPI ITATBCTR2 Register Definitions */ +#define TPI_ITATBCTR2_ATREADY_Pos 0 /*!< TPI ITATBCTR2: ATREADY Position */ +#define TPI_ITATBCTR2_ATREADY_Msk (0x1UL << TPI_ITATBCTR2_ATREADY_Pos) /*!< TPI ITATBCTR2: ATREADY Mask */ + +/* TPI Integration ITM Data Register Definitions (FIFO1) */ +#define TPI_FIFO1_ITM_ATVALID_Pos 29 /*!< TPI FIFO1: ITM_ATVALID Position */ +#define TPI_FIFO1_ITM_ATVALID_Msk (0x3UL << TPI_FIFO1_ITM_ATVALID_Pos) /*!< TPI FIFO1: ITM_ATVALID Mask */ + +#define TPI_FIFO1_ITM_bytecount_Pos 27 /*!< TPI FIFO1: ITM_bytecount Position */ +#define TPI_FIFO1_ITM_bytecount_Msk (0x3UL << TPI_FIFO1_ITM_bytecount_Pos) /*!< TPI FIFO1: ITM_bytecount Mask */ + +#define TPI_FIFO1_ETM_ATVALID_Pos 26 /*!< TPI FIFO1: ETM_ATVALID Position */ +#define TPI_FIFO1_ETM_ATVALID_Msk (0x3UL << TPI_FIFO1_ETM_ATVALID_Pos) /*!< TPI FIFO1: ETM_ATVALID Mask */ + +#define TPI_FIFO1_ETM_bytecount_Pos 24 /*!< TPI FIFO1: ETM_bytecount Position */ +#define TPI_FIFO1_ETM_bytecount_Msk (0x3UL << TPI_FIFO1_ETM_bytecount_Pos) /*!< TPI FIFO1: ETM_bytecount Mask */ + +#define TPI_FIFO1_ITM2_Pos 16 /*!< TPI FIFO1: ITM2 Position */ +#define TPI_FIFO1_ITM2_Msk (0xFFUL << TPI_FIFO1_ITM2_Pos) /*!< TPI FIFO1: ITM2 Mask */ + +#define TPI_FIFO1_ITM1_Pos 8 /*!< TPI FIFO1: ITM1 Position */ +#define TPI_FIFO1_ITM1_Msk (0xFFUL << TPI_FIFO1_ITM1_Pos) /*!< TPI FIFO1: ITM1 Mask */ + +#define TPI_FIFO1_ITM0_Pos 0 /*!< TPI FIFO1: ITM0 Position */ +#define TPI_FIFO1_ITM0_Msk (0xFFUL << TPI_FIFO1_ITM0_Pos) /*!< TPI FIFO1: ITM0 Mask */ + +/* TPI ITATBCTR0 Register Definitions */ +#define TPI_ITATBCTR0_ATREADY_Pos 0 /*!< TPI ITATBCTR0: ATREADY Position */ +#define TPI_ITATBCTR0_ATREADY_Msk (0x1UL << TPI_ITATBCTR0_ATREADY_Pos) /*!< TPI ITATBCTR0: ATREADY Mask */ + +/* TPI Integration Mode Control Register Definitions */ +#define TPI_ITCTRL_Mode_Pos 0 /*!< TPI ITCTRL: Mode Position */ +#define TPI_ITCTRL_Mode_Msk (0x1UL << TPI_ITCTRL_Mode_Pos) /*!< TPI ITCTRL: Mode Mask */ + +/* TPI DEVID Register Definitions */ +#define TPI_DEVID_NRZVALID_Pos 11 /*!< TPI DEVID: NRZVALID Position */ +#define TPI_DEVID_NRZVALID_Msk (0x1UL << TPI_DEVID_NRZVALID_Pos) /*!< TPI DEVID: NRZVALID Mask */ + +#define TPI_DEVID_MANCVALID_Pos 10 /*!< TPI DEVID: MANCVALID Position */ +#define TPI_DEVID_MANCVALID_Msk (0x1UL << TPI_DEVID_MANCVALID_Pos) /*!< TPI DEVID: MANCVALID Mask */ + +#define TPI_DEVID_PTINVALID_Pos 9 /*!< TPI DEVID: PTINVALID Position */ +#define TPI_DEVID_PTINVALID_Msk (0x1UL << TPI_DEVID_PTINVALID_Pos) /*!< TPI DEVID: PTINVALID Mask */ + +#define TPI_DEVID_MinBufSz_Pos 6 /*!< TPI DEVID: MinBufSz Position */ +#define TPI_DEVID_MinBufSz_Msk (0x7UL << TPI_DEVID_MinBufSz_Pos) /*!< TPI DEVID: MinBufSz Mask */ + +#define TPI_DEVID_AsynClkIn_Pos 5 /*!< TPI DEVID: AsynClkIn Position */ +#define TPI_DEVID_AsynClkIn_Msk (0x1UL << TPI_DEVID_AsynClkIn_Pos) /*!< TPI DEVID: AsynClkIn Mask */ + +#define TPI_DEVID_NrTraceInput_Pos 0 /*!< TPI DEVID: NrTraceInput Position */ +#define TPI_DEVID_NrTraceInput_Msk (0x1FUL << TPI_DEVID_NrTraceInput_Pos) /*!< TPI DEVID: NrTraceInput Mask */ + +/* TPI DEVTYPE Register Definitions */ +#define TPI_DEVTYPE_SubType_Pos 0 /*!< TPI DEVTYPE: SubType Position */ +#define TPI_DEVTYPE_SubType_Msk (0xFUL << TPI_DEVTYPE_SubType_Pos) /*!< TPI DEVTYPE: SubType Mask */ + +#define TPI_DEVTYPE_MajorType_Pos 4 /*!< TPI DEVTYPE: MajorType Position */ +#define TPI_DEVTYPE_MajorType_Msk (0xFUL << TPI_DEVTYPE_MajorType_Pos) /*!< TPI DEVTYPE: MajorType Mask */ + +/*@}*/ /* end of group CMSIS_TPI */ + + +#if (__MPU_PRESENT == 1) +/** \ingroup CMSIS_core_register + \defgroup CMSIS_MPU Memory Protection Unit (MPU) + \brief Type definitions for the Memory Protection Unit (MPU) + @{ + */ + +/** \brief Structure type to access the Memory Protection Unit (MPU). + */ +typedef struct +{ + __I uint32_t TYPE; /*!< Offset: 0x000 (R/ ) MPU Type Register */ + __IO uint32_t CTRL; /*!< Offset: 0x004 (R/W) MPU Control Register */ + __IO uint32_t RNR; /*!< Offset: 0x008 (R/W) MPU Region RNRber Register */ + __IO uint32_t RBAR; /*!< Offset: 0x00C (R/W) MPU Region Base Address Register */ + __IO uint32_t RASR; /*!< Offset: 0x010 (R/W) MPU Region Attribute and Size Register */ + __IO uint32_t RBAR_A1; /*!< Offset: 0x014 (R/W) MPU Alias 1 Region Base Address Register */ + __IO uint32_t RASR_A1; /*!< Offset: 0x018 (R/W) MPU Alias 1 Region Attribute and Size Register */ + __IO uint32_t RBAR_A2; /*!< Offset: 0x01C (R/W) MPU Alias 2 Region Base Address Register */ + __IO uint32_t RASR_A2; /*!< Offset: 0x020 (R/W) MPU Alias 2 Region Attribute and Size Register */ + __IO uint32_t RBAR_A3; /*!< Offset: 0x024 (R/W) MPU Alias 3 Region Base Address Register */ + __IO uint32_t RASR_A3; /*!< Offset: 0x028 (R/W) MPU Alias 3 Region Attribute and Size Register */ +} MPU_Type; + +/* MPU Type Register */ +#define MPU_TYPE_IREGION_Pos 16 /*!< MPU TYPE: IREGION Position */ +#define MPU_TYPE_IREGION_Msk (0xFFUL << MPU_TYPE_IREGION_Pos) /*!< MPU TYPE: IREGION Mask */ + +#define MPU_TYPE_DREGION_Pos 8 /*!< MPU TYPE: DREGION Position */ +#define MPU_TYPE_DREGION_Msk (0xFFUL << MPU_TYPE_DREGION_Pos) /*!< MPU TYPE: DREGION Mask */ + +#define MPU_TYPE_SEPARATE_Pos 0 /*!< MPU TYPE: SEPARATE Position */ +#define MPU_TYPE_SEPARATE_Msk (1UL << MPU_TYPE_SEPARATE_Pos) /*!< MPU TYPE: SEPARATE Mask */ + +/* MPU Control Register */ +#define MPU_CTRL_PRIVDEFENA_Pos 2 /*!< MPU CTRL: PRIVDEFENA Position */ +#define MPU_CTRL_PRIVDEFENA_Msk (1UL << MPU_CTRL_PRIVDEFENA_Pos) /*!< MPU CTRL: PRIVDEFENA Mask */ + +#define MPU_CTRL_HFNMIENA_Pos 1 /*!< MPU CTRL: HFNMIENA Position */ +#define MPU_CTRL_HFNMIENA_Msk (1UL << MPU_CTRL_HFNMIENA_Pos) /*!< MPU CTRL: HFNMIENA Mask */ + +#define MPU_CTRL_ENABLE_Pos 0 /*!< MPU CTRL: ENABLE Position */ +#define MPU_CTRL_ENABLE_Msk (1UL << MPU_CTRL_ENABLE_Pos) /*!< MPU CTRL: ENABLE Mask */ + +/* MPU Region Number Register */ +#define MPU_RNR_REGION_Pos 0 /*!< MPU RNR: REGION Position */ +#define MPU_RNR_REGION_Msk (0xFFUL << MPU_RNR_REGION_Pos) /*!< MPU RNR: REGION Mask */ + +/* MPU Region Base Address Register */ +#define MPU_RBAR_ADDR_Pos 5 /*!< MPU RBAR: ADDR Position */ +#define MPU_RBAR_ADDR_Msk (0x7FFFFFFUL << MPU_RBAR_ADDR_Pos) /*!< MPU RBAR: ADDR Mask */ + +#define MPU_RBAR_VALID_Pos 4 /*!< MPU RBAR: VALID Position */ +#define MPU_RBAR_VALID_Msk (1UL << MPU_RBAR_VALID_Pos) /*!< MPU RBAR: VALID Mask */ + +#define MPU_RBAR_REGION_Pos 0 /*!< MPU RBAR: REGION Position */ +#define MPU_RBAR_REGION_Msk (0xFUL << MPU_RBAR_REGION_Pos) /*!< MPU RBAR: REGION Mask */ + +/* MPU Region Attribute and Size Register */ +#define MPU_RASR_ATTRS_Pos 16 /*!< MPU RASR: MPU Region Attribute field Position */ +#define MPU_RASR_ATTRS_Msk (0xFFFFUL << MPU_RASR_ATTRS_Pos) /*!< MPU RASR: MPU Region Attribute field Mask */ + +#define MPU_RASR_XN_Pos 28 /*!< MPU RASR: ATTRS.XN Position */ +#define MPU_RASR_XN_Msk (1UL << MPU_RASR_XN_Pos) /*!< MPU RASR: ATTRS.XN Mask */ + +#define MPU_RASR_AP_Pos 24 /*!< MPU RASR: ATTRS.AP Position */ +#define MPU_RASR_AP_Msk (0x7UL << MPU_RASR_AP_Pos) /*!< MPU RASR: ATTRS.AP Mask */ + +#define MPU_RASR_TEX_Pos 19 /*!< MPU RASR: ATTRS.TEX Position */ +#define MPU_RASR_TEX_Msk (0x7UL << MPU_RASR_TEX_Pos) /*!< MPU RASR: ATTRS.TEX Mask */ + +#define MPU_RASR_S_Pos 18 /*!< MPU RASR: ATTRS.S Position */ +#define MPU_RASR_S_Msk (1UL << MPU_RASR_S_Pos) /*!< MPU RASR: ATTRS.S Mask */ + +#define MPU_RASR_C_Pos 17 /*!< MPU RASR: ATTRS.C Position */ +#define MPU_RASR_C_Msk (1UL << MPU_RASR_C_Pos) /*!< MPU RASR: ATTRS.C Mask */ + +#define MPU_RASR_B_Pos 16 /*!< MPU RASR: ATTRS.B Position */ +#define MPU_RASR_B_Msk (1UL << MPU_RASR_B_Pos) /*!< MPU RASR: ATTRS.B Mask */ + +#define MPU_RASR_SRD_Pos 8 /*!< MPU RASR: Sub-Region Disable Position */ +#define MPU_RASR_SRD_Msk (0xFFUL << MPU_RASR_SRD_Pos) /*!< MPU RASR: Sub-Region Disable Mask */ + +#define MPU_RASR_SIZE_Pos 1 /*!< MPU RASR: Region Size Field Position */ +#define MPU_RASR_SIZE_Msk (0x1FUL << MPU_RASR_SIZE_Pos) /*!< MPU RASR: Region Size Field Mask */ + +#define MPU_RASR_ENABLE_Pos 0 /*!< MPU RASR: Region enable bit Position */ +#define MPU_RASR_ENABLE_Msk (1UL << MPU_RASR_ENABLE_Pos) /*!< MPU RASR: Region enable bit Disable Mask */ + +/*@} end of group CMSIS_MPU */ +#endif + + +/** \ingroup CMSIS_core_register + \defgroup CMSIS_CoreDebug Core Debug Registers (CoreDebug) + \brief Type definitions for the Core Debug Registers + @{ + */ + +/** \brief Structure type to access the Core Debug Register (CoreDebug). + */ +typedef struct +{ + __IO uint32_t DHCSR; /*!< Offset: 0x000 (R/W) Debug Halting Control and Status Register */ + __O uint32_t DCRSR; /*!< Offset: 0x004 ( /W) Debug Core Register Selector Register */ + __IO uint32_t DCRDR; /*!< Offset: 0x008 (R/W) Debug Core Register Data Register */ + __IO uint32_t DEMCR; /*!< Offset: 0x00C (R/W) Debug Exception and Monitor Control Register */ +} CoreDebug_Type; + +/* Debug Halting Control and Status Register */ +#define CoreDebug_DHCSR_DBGKEY_Pos 16 /*!< CoreDebug DHCSR: DBGKEY Position */ +#define CoreDebug_DHCSR_DBGKEY_Msk (0xFFFFUL << CoreDebug_DHCSR_DBGKEY_Pos) /*!< CoreDebug DHCSR: DBGKEY Mask */ + +#define CoreDebug_DHCSR_S_RESET_ST_Pos 25 /*!< CoreDebug DHCSR: S_RESET_ST Position */ +#define CoreDebug_DHCSR_S_RESET_ST_Msk (1UL << CoreDebug_DHCSR_S_RESET_ST_Pos) /*!< CoreDebug DHCSR: S_RESET_ST Mask */ + +#define CoreDebug_DHCSR_S_RETIRE_ST_Pos 24 /*!< CoreDebug DHCSR: S_RETIRE_ST Position */ +#define CoreDebug_DHCSR_S_RETIRE_ST_Msk (1UL << CoreDebug_DHCSR_S_RETIRE_ST_Pos) /*!< CoreDebug DHCSR: S_RETIRE_ST Mask */ + +#define CoreDebug_DHCSR_S_LOCKUP_Pos 19 /*!< CoreDebug DHCSR: S_LOCKUP Position */ +#define CoreDebug_DHCSR_S_LOCKUP_Msk (1UL << CoreDebug_DHCSR_S_LOCKUP_Pos) /*!< CoreDebug DHCSR: S_LOCKUP Mask */ + +#define CoreDebug_DHCSR_S_SLEEP_Pos 18 /*!< CoreDebug DHCSR: S_SLEEP Position */ +#define CoreDebug_DHCSR_S_SLEEP_Msk (1UL << CoreDebug_DHCSR_S_SLEEP_Pos) /*!< CoreDebug DHCSR: S_SLEEP Mask */ + +#define CoreDebug_DHCSR_S_HALT_Pos 17 /*!< CoreDebug DHCSR: S_HALT Position */ +#define CoreDebug_DHCSR_S_HALT_Msk (1UL << CoreDebug_DHCSR_S_HALT_Pos) /*!< CoreDebug DHCSR: S_HALT Mask */ + +#define CoreDebug_DHCSR_S_REGRDY_Pos 16 /*!< CoreDebug DHCSR: S_REGRDY Position */ +#define CoreDebug_DHCSR_S_REGRDY_Msk (1UL << CoreDebug_DHCSR_S_REGRDY_Pos) /*!< CoreDebug DHCSR: S_REGRDY Mask */ + +#define CoreDebug_DHCSR_C_SNAPSTALL_Pos 5 /*!< CoreDebug DHCSR: C_SNAPSTALL Position */ +#define CoreDebug_DHCSR_C_SNAPSTALL_Msk (1UL << CoreDebug_DHCSR_C_SNAPSTALL_Pos) /*!< CoreDebug DHCSR: C_SNAPSTALL Mask */ + +#define CoreDebug_DHCSR_C_MASKINTS_Pos 3 /*!< CoreDebug DHCSR: C_MASKINTS Position */ +#define CoreDebug_DHCSR_C_MASKINTS_Msk (1UL << CoreDebug_DHCSR_C_MASKINTS_Pos) /*!< CoreDebug DHCSR: C_MASKINTS Mask */ + +#define CoreDebug_DHCSR_C_STEP_Pos 2 /*!< CoreDebug DHCSR: C_STEP Position */ +#define CoreDebug_DHCSR_C_STEP_Msk (1UL << CoreDebug_DHCSR_C_STEP_Pos) /*!< CoreDebug DHCSR: C_STEP Mask */ + +#define CoreDebug_DHCSR_C_HALT_Pos 1 /*!< CoreDebug DHCSR: C_HALT Position */ +#define CoreDebug_DHCSR_C_HALT_Msk (1UL << CoreDebug_DHCSR_C_HALT_Pos) /*!< CoreDebug DHCSR: C_HALT Mask */ + +#define CoreDebug_DHCSR_C_DEBUGEN_Pos 0 /*!< CoreDebug DHCSR: C_DEBUGEN Position */ +#define CoreDebug_DHCSR_C_DEBUGEN_Msk (1UL << CoreDebug_DHCSR_C_DEBUGEN_Pos) /*!< CoreDebug DHCSR: C_DEBUGEN Mask */ + +/* Debug Core Register Selector Register */ +#define CoreDebug_DCRSR_REGWnR_Pos 16 /*!< CoreDebug DCRSR: REGWnR Position */ +#define CoreDebug_DCRSR_REGWnR_Msk (1UL << CoreDebug_DCRSR_REGWnR_Pos) /*!< CoreDebug DCRSR: REGWnR Mask */ + +#define CoreDebug_DCRSR_REGSEL_Pos 0 /*!< CoreDebug DCRSR: REGSEL Position */ +#define CoreDebug_DCRSR_REGSEL_Msk (0x1FUL << CoreDebug_DCRSR_REGSEL_Pos) /*!< CoreDebug DCRSR: REGSEL Mask */ + +/* Debug Exception and Monitor Control Register */ +#define CoreDebug_DEMCR_TRCENA_Pos 24 /*!< CoreDebug DEMCR: TRCENA Position */ +#define CoreDebug_DEMCR_TRCENA_Msk (1UL << CoreDebug_DEMCR_TRCENA_Pos) /*!< CoreDebug DEMCR: TRCENA Mask */ + +#define CoreDebug_DEMCR_MON_REQ_Pos 19 /*!< CoreDebug DEMCR: MON_REQ Position */ +#define CoreDebug_DEMCR_MON_REQ_Msk (1UL << CoreDebug_DEMCR_MON_REQ_Pos) /*!< CoreDebug DEMCR: MON_REQ Mask */ + +#define CoreDebug_DEMCR_MON_STEP_Pos 18 /*!< CoreDebug DEMCR: MON_STEP Position */ +#define CoreDebug_DEMCR_MON_STEP_Msk (1UL << CoreDebug_DEMCR_MON_STEP_Pos) /*!< CoreDebug DEMCR: MON_STEP Mask */ + +#define CoreDebug_DEMCR_MON_PEND_Pos 17 /*!< CoreDebug DEMCR: MON_PEND Position */ +#define CoreDebug_DEMCR_MON_PEND_Msk (1UL << CoreDebug_DEMCR_MON_PEND_Pos) /*!< CoreDebug DEMCR: MON_PEND Mask */ + +#define CoreDebug_DEMCR_MON_EN_Pos 16 /*!< CoreDebug DEMCR: MON_EN Position */ +#define CoreDebug_DEMCR_MON_EN_Msk (1UL << CoreDebug_DEMCR_MON_EN_Pos) /*!< CoreDebug DEMCR: MON_EN Mask */ + +#define CoreDebug_DEMCR_VC_HARDERR_Pos 10 /*!< CoreDebug DEMCR: VC_HARDERR Position */ +#define CoreDebug_DEMCR_VC_HARDERR_Msk (1UL << CoreDebug_DEMCR_VC_HARDERR_Pos) /*!< CoreDebug DEMCR: VC_HARDERR Mask */ + +#define CoreDebug_DEMCR_VC_INTERR_Pos 9 /*!< CoreDebug DEMCR: VC_INTERR Position */ +#define CoreDebug_DEMCR_VC_INTERR_Msk (1UL << CoreDebug_DEMCR_VC_INTERR_Pos) /*!< CoreDebug DEMCR: VC_INTERR Mask */ + +#define CoreDebug_DEMCR_VC_BUSERR_Pos 8 /*!< CoreDebug DEMCR: VC_BUSERR Position */ +#define CoreDebug_DEMCR_VC_BUSERR_Msk (1UL << CoreDebug_DEMCR_VC_BUSERR_Pos) /*!< CoreDebug DEMCR: VC_BUSERR Mask */ + +#define CoreDebug_DEMCR_VC_STATERR_Pos 7 /*!< CoreDebug DEMCR: VC_STATERR Position */ +#define CoreDebug_DEMCR_VC_STATERR_Msk (1UL << CoreDebug_DEMCR_VC_STATERR_Pos) /*!< CoreDebug DEMCR: VC_STATERR Mask */ + +#define CoreDebug_DEMCR_VC_CHKERR_Pos 6 /*!< CoreDebug DEMCR: VC_CHKERR Position */ +#define CoreDebug_DEMCR_VC_CHKERR_Msk (1UL << CoreDebug_DEMCR_VC_CHKERR_Pos) /*!< CoreDebug DEMCR: VC_CHKERR Mask */ + +#define CoreDebug_DEMCR_VC_NOCPERR_Pos 5 /*!< CoreDebug DEMCR: VC_NOCPERR Position */ +#define CoreDebug_DEMCR_VC_NOCPERR_Msk (1UL << CoreDebug_DEMCR_VC_NOCPERR_Pos) /*!< CoreDebug DEMCR: VC_NOCPERR Mask */ + +#define CoreDebug_DEMCR_VC_MMERR_Pos 4 /*!< CoreDebug DEMCR: VC_MMERR Position */ +#define CoreDebug_DEMCR_VC_MMERR_Msk (1UL << CoreDebug_DEMCR_VC_MMERR_Pos) /*!< CoreDebug DEMCR: VC_MMERR Mask */ + +#define CoreDebug_DEMCR_VC_CORERESET_Pos 0 /*!< CoreDebug DEMCR: VC_CORERESET Position */ +#define CoreDebug_DEMCR_VC_CORERESET_Msk (1UL << CoreDebug_DEMCR_VC_CORERESET_Pos) /*!< CoreDebug DEMCR: VC_CORERESET Mask */ + +/*@} end of group CMSIS_CoreDebug */ + + +/** \ingroup CMSIS_core_register + \defgroup CMSIS_core_base Core Definitions + \brief Definitions for base addresses, unions, and structures. + @{ + */ + +/* Memory mapping of Cortex-M3 Hardware */ +#define SCS_BASE (0xE000E000UL) /*!< System Control Space Base Address */ +#define ITM_BASE (0xE0000000UL) /*!< ITM Base Address */ +#define DWT_BASE (0xE0001000UL) /*!< DWT Base Address */ +#define TPI_BASE (0xE0040000UL) /*!< TPI Base Address */ +#define CoreDebug_BASE (0xE000EDF0UL) /*!< Core Debug Base Address */ +#define SysTick_BASE (SCS_BASE + 0x0010UL) /*!< SysTick Base Address */ +#define NVIC_BASE (SCS_BASE + 0x0100UL) /*!< NVIC Base Address */ +#define SCB_BASE (SCS_BASE + 0x0D00UL) /*!< System Control Block Base Address */ + +#define SCnSCB ((SCnSCB_Type *) SCS_BASE ) /*!< System control Register not in SCB */ +#define SCB ((SCB_Type *) SCB_BASE ) /*!< SCB configuration struct */ +#define SysTick ((SysTick_Type *) SysTick_BASE ) /*!< SysTick configuration struct */ +#define NVIC ((NVIC_Type *) NVIC_BASE ) /*!< NVIC configuration struct */ +#define ITM ((ITM_Type *) ITM_BASE ) /*!< ITM configuration struct */ +#define DWT ((DWT_Type *) DWT_BASE ) /*!< DWT configuration struct */ +#define TPI ((TPI_Type *) TPI_BASE ) /*!< TPI configuration struct */ +#define CoreDebug ((CoreDebug_Type *) CoreDebug_BASE) /*!< Core Debug configuration struct */ + +#if (__MPU_PRESENT == 1) + #define MPU_BASE (SCS_BASE + 0x0D90UL) /*!< Memory Protection Unit */ + #define MPU ((MPU_Type *) MPU_BASE ) /*!< Memory Protection Unit */ +#endif + +/*@} */ + + + +/******************************************************************************* + * Hardware Abstraction Layer + Core Function Interface contains: + - Core NVIC Functions + - Core SysTick Functions + - Core Debug Functions + - Core Register Access Functions + ******************************************************************************/ +/** \defgroup CMSIS_Core_FunctionInterface Functions and Instructions Reference +*/ + + + +/* ########################## NVIC functions #################################### */ +/** \ingroup CMSIS_Core_FunctionInterface + \defgroup CMSIS_Core_NVICFunctions NVIC Functions + \brief Functions that manage interrupts and exceptions via the NVIC. + @{ + */ + +/** \brief Set Priority Grouping + + The function sets the priority grouping field using the required unlock sequence. + The parameter PriorityGroup is assigned to the field SCB->AIRCR [10:8] PRIGROUP field. + Only values from 0..7 are used. + In case of a conflict between priority grouping and available + priority bits (__NVIC_PRIO_BITS), the smallest possible priority group is set. + + \param [in] PriorityGroup Priority grouping field. + */ +__STATIC_INLINE void NVIC_SetPriorityGrouping(uint32_t PriorityGroup) +{ + uint32_t reg_value; + uint32_t PriorityGroupTmp = (PriorityGroup & (uint32_t)0x07); /* only values 0..7 are used */ + + reg_value = SCB->AIRCR; /* read old register configuration */ + reg_value &= ~(SCB_AIRCR_VECTKEY_Msk | SCB_AIRCR_PRIGROUP_Msk); /* clear bits to change */ + reg_value = (reg_value | + ((uint32_t)0x5FA << SCB_AIRCR_VECTKEY_Pos) | + (PriorityGroupTmp << 8)); /* Insert write key and priorty group */ + SCB->AIRCR = reg_value; +} + + +/** \brief Get Priority Grouping + + The function reads the priority grouping field from the NVIC Interrupt Controller. + + \return Priority grouping field (SCB->AIRCR [10:8] PRIGROUP field). + */ +__STATIC_INLINE uint32_t NVIC_GetPriorityGrouping(void) +{ + return ((SCB->AIRCR & SCB_AIRCR_PRIGROUP_Msk) >> SCB_AIRCR_PRIGROUP_Pos); /* read priority grouping field */ +} + + +/** \brief Enable External Interrupt + + The function enables a device-specific interrupt in the NVIC interrupt controller. + + \param [in] IRQn External interrupt number. Value cannot be negative. + */ +__STATIC_INLINE void NVIC_EnableIRQ(IRQn_Type IRQn) +{ + NVIC->ISER[((uint32_t)(IRQn) >> 5)] = (1 << ((uint32_t)(IRQn) & 0x1F)); /* enable interrupt */ +} + + +/** \brief Disable External Interrupt + + The function disables a device-specific interrupt in the NVIC interrupt controller. + + \param [in] IRQn External interrupt number. Value cannot be negative. + */ +__STATIC_INLINE void NVIC_DisableIRQ(IRQn_Type IRQn) +{ + NVIC->ICER[((uint32_t)(IRQn) >> 5)] = (1 << ((uint32_t)(IRQn) & 0x1F)); /* disable interrupt */ +} + + +/** \brief Get Pending Interrupt + + The function reads the pending register in the NVIC and returns the pending bit + for the specified interrupt. + + \param [in] IRQn Interrupt number. + + \return 0 Interrupt status is not pending. + \return 1 Interrupt status is pending. + */ +__STATIC_INLINE uint32_t NVIC_GetPendingIRQ(IRQn_Type IRQn) +{ + return((uint32_t) ((NVIC->ISPR[(uint32_t)(IRQn) >> 5] & (1 << ((uint32_t)(IRQn) & 0x1F)))?1:0)); /* Return 1 if pending else 0 */ +} + + +/** \brief Set Pending Interrupt + + The function sets the pending bit of an external interrupt. + + \param [in] IRQn Interrupt number. Value cannot be negative. + */ +__STATIC_INLINE void NVIC_SetPendingIRQ(IRQn_Type IRQn) +{ + NVIC->ISPR[((uint32_t)(IRQn) >> 5)] = (1 << ((uint32_t)(IRQn) & 0x1F)); /* set interrupt pending */ +} + + +/** \brief Clear Pending Interrupt + + The function clears the pending bit of an external interrupt. + + \param [in] IRQn External interrupt number. Value cannot be negative. + */ +__STATIC_INLINE void NVIC_ClearPendingIRQ(IRQn_Type IRQn) +{ + NVIC->ICPR[((uint32_t)(IRQn) >> 5)] = (1 << ((uint32_t)(IRQn) & 0x1F)); /* Clear pending interrupt */ +} + + +/** \brief Get Active Interrupt + + The function reads the active register in NVIC and returns the active bit. + + \param [in] IRQn Interrupt number. + + \return 0 Interrupt status is not active. + \return 1 Interrupt status is active. + */ +__STATIC_INLINE uint32_t NVIC_GetActive(IRQn_Type IRQn) +{ + return((uint32_t)((NVIC->IABR[(uint32_t)(IRQn) >> 5] & (1 << ((uint32_t)(IRQn) & 0x1F)))?1:0)); /* Return 1 if active else 0 */ +} + + +/** \brief Set Interrupt Priority + + The function sets the priority of an interrupt. + + \note The priority cannot be set for every core interrupt. + + \param [in] IRQn Interrupt number. + \param [in] priority Priority to set. + */ +__STATIC_INLINE void NVIC_SetPriority(IRQn_Type IRQn, uint32_t priority) +{ + if(IRQn < 0) { + SCB->SHP[((uint32_t)(IRQn) & 0xF)-4] = ((priority << (8 - __NVIC_PRIO_BITS)) & 0xff); } /* set Priority for Cortex-M System Interrupts */ + else { + NVIC->IP[(uint32_t)(IRQn)] = ((priority << (8 - __NVIC_PRIO_BITS)) & 0xff); } /* set Priority for device specific Interrupts */ +} + + +/** \brief Get Interrupt Priority + + The function reads the priority of an interrupt. The interrupt + number can be positive to specify an external (device specific) + interrupt, or negative to specify an internal (core) interrupt. + + + \param [in] IRQn Interrupt number. + \return Interrupt Priority. Value is aligned automatically to the implemented + priority bits of the microcontroller. + */ +__STATIC_INLINE uint32_t NVIC_GetPriority(IRQn_Type IRQn) +{ + + if(IRQn < 0) { + return((uint32_t)(SCB->SHP[((uint32_t)(IRQn) & 0xF)-4] >> (8 - __NVIC_PRIO_BITS))); } /* get priority for Cortex-M system interrupts */ + else { + return((uint32_t)(NVIC->IP[(uint32_t)(IRQn)] >> (8 - __NVIC_PRIO_BITS))); } /* get priority for device specific interrupts */ +} + + +/** \brief Encode Priority + + The function encodes the priority for an interrupt with the given priority group, + preemptive priority value, and subpriority value. + In case of a conflict between priority grouping and available + priority bits (__NVIC_PRIO_BITS), the samllest possible priority group is set. + + \param [in] PriorityGroup Used priority group. + \param [in] PreemptPriority Preemptive priority value (starting from 0). + \param [in] SubPriority Subpriority value (starting from 0). + \return Encoded priority. Value can be used in the function \ref NVIC_SetPriority(). + */ +__STATIC_INLINE uint32_t NVIC_EncodePriority (uint32_t PriorityGroup, uint32_t PreemptPriority, uint32_t SubPriority) +{ + uint32_t PriorityGroupTmp = (PriorityGroup & 0x07); /* only values 0..7 are used */ + uint32_t PreemptPriorityBits; + uint32_t SubPriorityBits; + + PreemptPriorityBits = ((7 - PriorityGroupTmp) > __NVIC_PRIO_BITS) ? __NVIC_PRIO_BITS : 7 - PriorityGroupTmp; + SubPriorityBits = ((PriorityGroupTmp + __NVIC_PRIO_BITS) < 7) ? 0 : PriorityGroupTmp - 7 + __NVIC_PRIO_BITS; + + return ( + ((PreemptPriority & ((1 << (PreemptPriorityBits)) - 1)) << SubPriorityBits) | + ((SubPriority & ((1 << (SubPriorityBits )) - 1))) + ); +} + + +/** \brief Decode Priority + + The function decodes an interrupt priority value with a given priority group to + preemptive priority value and subpriority value. + In case of a conflict between priority grouping and available + priority bits (__NVIC_PRIO_BITS) the samllest possible priority group is set. + + \param [in] Priority Priority value, which can be retrieved with the function \ref NVIC_GetPriority(). + \param [in] PriorityGroup Used priority group. + \param [out] pPreemptPriority Preemptive priority value (starting from 0). + \param [out] pSubPriority Subpriority value (starting from 0). + */ +__STATIC_INLINE void NVIC_DecodePriority (uint32_t Priority, uint32_t PriorityGroup, uint32_t* pPreemptPriority, uint32_t* pSubPriority) +{ + uint32_t PriorityGroupTmp = (PriorityGroup & 0x07); /* only values 0..7 are used */ + uint32_t PreemptPriorityBits; + uint32_t SubPriorityBits; + + PreemptPriorityBits = ((7 - PriorityGroupTmp) > __NVIC_PRIO_BITS) ? __NVIC_PRIO_BITS : 7 - PriorityGroupTmp; + SubPriorityBits = ((PriorityGroupTmp + __NVIC_PRIO_BITS) < 7) ? 0 : PriorityGroupTmp - 7 + __NVIC_PRIO_BITS; + + *pPreemptPriority = (Priority >> SubPriorityBits) & ((1 << (PreemptPriorityBits)) - 1); + *pSubPriority = (Priority ) & ((1 << (SubPriorityBits )) - 1); +} + + +/** \brief System Reset + + The function initiates a system reset request to reset the MCU. + */ +__STATIC_INLINE void NVIC_SystemReset(void) +{ + __DSB(); /* Ensure all outstanding memory accesses included + buffered write are completed before reset */ + SCB->AIRCR = ((0x5FA << SCB_AIRCR_VECTKEY_Pos) | + (SCB->AIRCR & SCB_AIRCR_PRIGROUP_Msk) | + SCB_AIRCR_SYSRESETREQ_Msk); /* Keep priority group unchanged */ + __DSB(); /* Ensure completion of memory access */ + while(1); /* wait until reset */ +} + +/*@} end of CMSIS_Core_NVICFunctions */ + + + +/* ################################## SysTick function ############################################ */ +/** \ingroup CMSIS_Core_FunctionInterface + \defgroup CMSIS_Core_SysTickFunctions SysTick Functions + \brief Functions that configure the System. + @{ + */ + +#if (__Vendor_SysTickConfig == 0) + +/** \brief System Tick Configuration + + The function initializes the System Timer and its interrupt, and starts the System Tick Timer. + Counter is in free running mode to generate periodic interrupts. + + \param [in] ticks Number of ticks between two interrupts. + + \return 0 Function succeeded. + \return 1 Function failed. + + \note When the variable __Vendor_SysTickConfig is set to 1, then the + function SysTick_Config is not included. In this case, the file device.h + must contain a vendor-specific implementation of this function. + + */ +__STATIC_INLINE uint32_t SysTick_Config(uint32_t ticks) +{ + if ((ticks - 1) > SysTick_LOAD_RELOAD_Msk) return (1); /* Reload value impossible */ + + SysTick->LOAD = ticks - 1; /* set reload register */ + NVIC_SetPriority (SysTick_IRQn, (1<<__NVIC_PRIO_BITS) - 1); /* set Priority for Systick Interrupt */ + SysTick->VAL = 0; /* Load the SysTick Counter Value */ + SysTick->CTRL = SysTick_CTRL_CLKSOURCE_Msk | + SysTick_CTRL_TICKINT_Msk | + SysTick_CTRL_ENABLE_Msk; /* Enable SysTick IRQ and SysTick Timer */ + return (0); /* Function successful */ +} + +#endif + +/*@} end of CMSIS_Core_SysTickFunctions */ + + + +/* ##################################### Debug In/Output function ########################################### */ +/** \ingroup CMSIS_Core_FunctionInterface + \defgroup CMSIS_core_DebugFunctions ITM Functions + \brief Functions that access the ITM debug interface. + @{ + */ + +extern volatile int32_t ITM_RxBuffer; /*!< External variable to receive characters. */ +#define ITM_RXBUFFER_EMPTY 0x5AA55AA5 /*!< Value identifying \ref ITM_RxBuffer is ready for next character. */ + + +/** \brief ITM Send Character + + The function transmits a character via the ITM channel 0, and + \li Just returns when no debugger is connected that has booked the output. + \li Is blocking when a debugger is connected, but the previous character sent has not been transmitted. + + \param [in] ch Character to transmit. + + \returns Character to transmit. + */ +__STATIC_INLINE uint32_t ITM_SendChar (uint32_t ch) +{ + if ((ITM->TCR & ITM_TCR_ITMENA_Msk) && /* ITM enabled */ + (ITM->TER & (1UL << 0) ) ) /* ITM Port #0 enabled */ + { + while (ITM->PORT[0].u32 == 0); + ITM->PORT[0].u8 = (uint8_t) ch; + } + return (ch); +} + + +/** \brief ITM Receive Character + + The function inputs a character via the external variable \ref ITM_RxBuffer. + + \return Received character. + \return -1 No character pending. + */ +__STATIC_INLINE int32_t ITM_ReceiveChar (void) { + int32_t ch = -1; /* no character available */ + + if (ITM_RxBuffer != ITM_RXBUFFER_EMPTY) { + ch = ITM_RxBuffer; + ITM_RxBuffer = ITM_RXBUFFER_EMPTY; /* ready for next character */ + } + + return (ch); +} + + +/** \brief ITM Check Character + + The function checks whether a character is pending for reading in the variable \ref ITM_RxBuffer. + + \return 0 No character available. + \return 1 Character available. + */ +__STATIC_INLINE int32_t ITM_CheckChar (void) { + + if (ITM_RxBuffer == ITM_RXBUFFER_EMPTY) { + return (0); /* no character available */ + } else { + return (1); /* character available */ + } +} + +/*@} end of CMSIS_core_DebugFunctions */ + +#endif /* __CORE_CM3_H_DEPENDANT */ + +#endif /* __CMSIS_GENERIC */ + +#ifdef __cplusplus +} +#endif diff --git a/bsp/gd32/libraries/GD32F20x_Firmware_Library/CMSIS/core_cmFunc.h b/bsp/gd32/libraries/GD32F20x_Firmware_Library/CMSIS/core_cmFunc.h new file mode 100644 index 0000000000..3c932e0d6e --- /dev/null +++ b/bsp/gd32/libraries/GD32F20x_Firmware_Library/CMSIS/core_cmFunc.h @@ -0,0 +1,616 @@ +/**************************************************************************//** + * @file core_cmFunc.h + * @brief CMSIS Cortex-M Core Function Access Header File + * @version V3.01 + * @date 06. March 2012 + * + * @note + * Copyright (C) 2009-2012 ARM Limited. All rights reserved. + * + * @par + * ARM Limited (ARM) is supplying this software for use with Cortex-M + * processor based microcontrollers. This file can be freely distributed + * within development tools that are supporting such ARM based processors. + * + * @par + * THIS SOFTWARE IS PROVIDED "AS IS". NO WARRANTIES, WHETHER EXPRESS, IMPLIED + * OR STATUTORY, INCLUDING, BUT NOT LIMITED TO, IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE APPLY TO THIS SOFTWARE. + * ARM SHALL NOT, IN ANY CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL, OR + * CONSEQUENTIAL DAMAGES, FOR ANY REASON WHATSOEVER. + * + ******************************************************************************/ + +#ifndef __CORE_CMFUNC_H +#define __CORE_CMFUNC_H + + +/* ########################### Core Function Access ########################### */ +/** \ingroup CMSIS_Core_FunctionInterface + \defgroup CMSIS_Core_RegAccFunctions CMSIS Core Register Access Functions + @{ + */ + +#if defined ( __CC_ARM ) /*------------------RealView Compiler -----------------*/ +/* ARM armcc specific functions */ + +#if (__ARMCC_VERSION < 400677) + #error "Please use ARM Compiler Toolchain V4.0.677 or later!" +#endif + +/* intrinsic void __enable_irq(); */ +/* intrinsic void __disable_irq(); */ + +/** \brief Get Control Register + + This function returns the content of the Control Register. + + \return Control Register value + */ +__STATIC_INLINE uint32_t __get_CONTROL(void) +{ + register uint32_t __regControl __ASM("control"); + return(__regControl); +} + + +/** \brief Set Control Register + + This function writes the given value to the Control Register. + + \param [in] control Control Register value to set + */ +__STATIC_INLINE void __set_CONTROL(uint32_t control) +{ + register uint32_t __regControl __ASM("control"); + __regControl = control; +} + + +/** \brief Get IPSR Register + + This function returns the content of the IPSR Register. + + \return IPSR Register value + */ +__STATIC_INLINE uint32_t __get_IPSR(void) +{ + register uint32_t __regIPSR __ASM("ipsr"); + return(__regIPSR); +} + + +/** \brief Get APSR Register + + This function returns the content of the APSR Register. + + \return APSR Register value + */ +__STATIC_INLINE uint32_t __get_APSR(void) +{ + register uint32_t __regAPSR __ASM("apsr"); + return(__regAPSR); +} + + +/** \brief Get xPSR Register + + This function returns the content of the xPSR Register. + + \return xPSR Register value + */ +__STATIC_INLINE uint32_t __get_xPSR(void) +{ + register uint32_t __regXPSR __ASM("xpsr"); + return(__regXPSR); +} + + +/** \brief Get Process Stack Pointer + + This function returns the current value of the Process Stack Pointer (PSP). + + \return PSP Register value + */ +__STATIC_INLINE uint32_t __get_PSP(void) +{ + register uint32_t __regProcessStackPointer __ASM("psp"); + return(__regProcessStackPointer); +} + + +/** \brief Set Process Stack Pointer + + This function assigns the given value to the Process Stack Pointer (PSP). + + \param [in] topOfProcStack Process Stack Pointer value to set + */ +__STATIC_INLINE void __set_PSP(uint32_t topOfProcStack) +{ + register uint32_t __regProcessStackPointer __ASM("psp"); + __regProcessStackPointer = topOfProcStack; +} + + +/** \brief Get Main Stack Pointer + + This function returns the current value of the Main Stack Pointer (MSP). + + \return MSP Register value + */ +__STATIC_INLINE uint32_t __get_MSP(void) +{ + register uint32_t __regMainStackPointer __ASM("msp"); + return(__regMainStackPointer); +} + + +/** \brief Set Main Stack Pointer + + This function assigns the given value to the Main Stack Pointer (MSP). + + \param [in] topOfMainStack Main Stack Pointer value to set + */ +__STATIC_INLINE void __set_MSP(uint32_t topOfMainStack) +{ + register uint32_t __regMainStackPointer __ASM("msp"); + __regMainStackPointer = topOfMainStack; +} + + +/** \brief Get Priority Mask + + This function returns the current state of the priority mask bit from the Priority Mask Register. + + \return Priority Mask value + */ +__STATIC_INLINE uint32_t __get_PRIMASK(void) +{ + register uint32_t __regPriMask __ASM("primask"); + return(__regPriMask); +} + + +/** \brief Set Priority Mask + + This function assigns the given value to the Priority Mask Register. + + \param [in] priMask Priority Mask + */ +__STATIC_INLINE void __set_PRIMASK(uint32_t priMask) +{ + register uint32_t __regPriMask __ASM("primask"); + __regPriMask = (priMask); +} + + +#if (__CORTEX_M >= 0x03) + +/** \brief Enable FIQ + + This function enables FIQ interrupts by clearing the F-bit in the CPSR. + Can only be executed in Privileged modes. + */ +#define __enable_fault_irq __enable_fiq + + +/** \brief Disable FIQ + + This function disables FIQ interrupts by setting the F-bit in the CPSR. + Can only be executed in Privileged modes. + */ +#define __disable_fault_irq __disable_fiq + + +/** \brief Get Base Priority + + This function returns the current value of the Base Priority register. + + \return Base Priority register value + */ +__STATIC_INLINE uint32_t __get_BASEPRI(void) +{ + register uint32_t __regBasePri __ASM("basepri"); + return(__regBasePri); +} + + +/** \brief Set Base Priority + + This function assigns the given value to the Base Priority register. + + \param [in] basePri Base Priority value to set + */ +__STATIC_INLINE void __set_BASEPRI(uint32_t basePri) +{ + register uint32_t __regBasePri __ASM("basepri"); + __regBasePri = (basePri & 0xff); +} + + +/** \brief Get Fault Mask + + This function returns the current value of the Fault Mask register. + + \return Fault Mask register value + */ +__STATIC_INLINE uint32_t __get_FAULTMASK(void) +{ + register uint32_t __regFaultMask __ASM("faultmask"); + return(__regFaultMask); +} + + +/** \brief Set Fault Mask + + This function assigns the given value to the Fault Mask register. + + \param [in] faultMask Fault Mask value to set + */ +__STATIC_INLINE void __set_FAULTMASK(uint32_t faultMask) +{ + register uint32_t __regFaultMask __ASM("faultmask"); + __regFaultMask = (faultMask & (uint32_t)1); +} + +#endif /* (__CORTEX_M >= 0x03) */ + + +#if (__CORTEX_M == 0x04) + +/** \brief Get FPSCR + + This function returns the current value of the Floating Point Status/Control register. + + \return Floating Point Status/Control register value + */ +__STATIC_INLINE uint32_t __get_FPSCR(void) +{ +#if (__FPU_PRESENT == 1) && (__FPU_USED == 1) + register uint32_t __regfpscr __ASM("fpscr"); + return(__regfpscr); +#else + return(0); +#endif +} + + +/** \brief Set FPSCR + + This function assigns the given value to the Floating Point Status/Control register. + + \param [in] fpscr Floating Point Status/Control value to set + */ +__STATIC_INLINE void __set_FPSCR(uint32_t fpscr) +{ +#if (__FPU_PRESENT == 1) && (__FPU_USED == 1) + register uint32_t __regfpscr __ASM("fpscr"); + __regfpscr = (fpscr); +#endif +} + +#endif /* (__CORTEX_M == 0x04) */ + + +#elif defined ( __ICCARM__ ) /*------------------ ICC Compiler -------------------*/ +/* IAR iccarm specific functions */ + +#include + + +#elif defined ( __TMS470__ ) /*---------------- TI CCS Compiler ------------------*/ +/* TI CCS specific functions */ + +#include + + +#elif defined ( __GNUC__ ) /*------------------ GNU Compiler ---------------------*/ +/* GNU gcc specific functions */ + +/** \brief Enable IRQ Interrupts + + This function enables IRQ interrupts by clearing the I-bit in the CPSR. + Can only be executed in Privileged modes. + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE void __enable_irq(void) +{ + __ASM volatile ("cpsie i"); +} + + +/** \brief Disable IRQ Interrupts + + This function disables IRQ interrupts by setting the I-bit in the CPSR. + Can only be executed in Privileged modes. + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE void __disable_irq(void) +{ + __ASM volatile ("cpsid i"); +} + + +/** \brief Get Control Register + + This function returns the content of the Control Register. + + \return Control Register value + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __get_CONTROL(void) +{ + uint32_t result; + + __ASM volatile ("MRS %0, control" : "=r" (result) ); + return(result); +} + + +/** \brief Set Control Register + + This function writes the given value to the Control Register. + + \param [in] control Control Register value to set + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE void __set_CONTROL(uint32_t control) +{ + __ASM volatile ("MSR control, %0" : : "r" (control) ); +} + + +/** \brief Get IPSR Register + + This function returns the content of the IPSR Register. + + \return IPSR Register value + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __get_IPSR(void) +{ + uint32_t result; + + __ASM volatile ("MRS %0, ipsr" : "=r" (result) ); + return(result); +} + + +/** \brief Get APSR Register + + This function returns the content of the APSR Register. + + \return APSR Register value + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __get_APSR(void) +{ + uint32_t result; + + __ASM volatile ("MRS %0, apsr" : "=r" (result) ); + return(result); +} + + +/** \brief Get xPSR Register + + This function returns the content of the xPSR Register. + + \return xPSR Register value + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __get_xPSR(void) +{ + uint32_t result; + + __ASM volatile ("MRS %0, xpsr" : "=r" (result) ); + return(result); +} + + +/** \brief Get Process Stack Pointer + + This function returns the current value of the Process Stack Pointer (PSP). + + \return PSP Register value + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __get_PSP(void) +{ + register uint32_t result; + + __ASM volatile ("MRS %0, psp\n" : "=r" (result) ); + return(result); +} + + +/** \brief Set Process Stack Pointer + + This function assigns the given value to the Process Stack Pointer (PSP). + + \param [in] topOfProcStack Process Stack Pointer value to set + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE void __set_PSP(uint32_t topOfProcStack) +{ + __ASM volatile ("MSR psp, %0\n" : : "r" (topOfProcStack) ); +} + + +/** \brief Get Main Stack Pointer + + This function returns the current value of the Main Stack Pointer (MSP). + + \return MSP Register value + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __get_MSP(void) +{ + register uint32_t result; + + __ASM volatile ("MRS %0, msp\n" : "=r" (result) ); + return(result); +} + + +/** \brief Set Main Stack Pointer + + This function assigns the given value to the Main Stack Pointer (MSP). + + \param [in] topOfMainStack Main Stack Pointer value to set + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE void __set_MSP(uint32_t topOfMainStack) +{ + __ASM volatile ("MSR msp, %0\n" : : "r" (topOfMainStack) ); +} + + +/** \brief Get Priority Mask + + This function returns the current state of the priority mask bit from the Priority Mask Register. + + \return Priority Mask value + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __get_PRIMASK(void) +{ + uint32_t result; + + __ASM volatile ("MRS %0, primask" : "=r" (result) ); + return(result); +} + + +/** \brief Set Priority Mask + + This function assigns the given value to the Priority Mask Register. + + \param [in] priMask Priority Mask + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE void __set_PRIMASK(uint32_t priMask) +{ + __ASM volatile ("MSR primask, %0" : : "r" (priMask) ); +} + + +#if (__CORTEX_M >= 0x03) + +/** \brief Enable FIQ + + This function enables FIQ interrupts by clearing the F-bit in the CPSR. + Can only be executed in Privileged modes. + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE void __enable_fault_irq(void) +{ + __ASM volatile ("cpsie f"); +} + + +/** \brief Disable FIQ + + This function disables FIQ interrupts by setting the F-bit in the CPSR. + Can only be executed in Privileged modes. + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE void __disable_fault_irq(void) +{ + __ASM volatile ("cpsid f"); +} + + +/** \brief Get Base Priority + + This function returns the current value of the Base Priority register. + + \return Base Priority register value + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __get_BASEPRI(void) +{ + uint32_t result; + + __ASM volatile ("MRS %0, basepri_max" : "=r" (result) ); + return(result); +} + + +/** \brief Set Base Priority + + This function assigns the given value to the Base Priority register. + + \param [in] basePri Base Priority value to set + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE void __set_BASEPRI(uint32_t value) +{ + __ASM volatile ("MSR basepri, %0" : : "r" (value) ); +} + + +/** \brief Get Fault Mask + + This function returns the current value of the Fault Mask register. + + \return Fault Mask register value + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __get_FAULTMASK(void) +{ + uint32_t result; + + __ASM volatile ("MRS %0, faultmask" : "=r" (result) ); + return(result); +} + + +/** \brief Set Fault Mask + + This function assigns the given value to the Fault Mask register. + + \param [in] faultMask Fault Mask value to set + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE void __set_FAULTMASK(uint32_t faultMask) +{ + __ASM volatile ("MSR faultmask, %0" : : "r" (faultMask) ); +} + +#endif /* (__CORTEX_M >= 0x03) */ + + +#if (__CORTEX_M == 0x04) + +/** \brief Get FPSCR + + This function returns the current value of the Floating Point Status/Control register. + + \return Floating Point Status/Control register value + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __get_FPSCR(void) +{ +#if (__FPU_PRESENT == 1) && (__FPU_USED == 1) + uint32_t result; + + __ASM volatile ("VMRS %0, fpscr" : "=r" (result) ); + return(result); +#else + return(0); +#endif +} + + +/** \brief Set FPSCR + + This function assigns the given value to the Floating Point Status/Control register. + + \param [in] fpscr Floating Point Status/Control value to set + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE void __set_FPSCR(uint32_t fpscr) +{ +#if (__FPU_PRESENT == 1) && (__FPU_USED == 1) + __ASM volatile ("VMSR fpscr, %0" : : "r" (fpscr) ); +#endif +} + +#endif /* (__CORTEX_M == 0x04) */ + + +#elif defined ( __TASKING__ ) /*------------------ TASKING Compiler --------------*/ +/* TASKING carm specific functions */ + +/* + * The CMSIS functions have been implemented as intrinsics in the compiler. + * Please use "carm -?i" to get an up to date list of all instrinsics, + * Including the CMSIS ones. + */ + +#endif + +/*@} end of CMSIS_Core_RegAccFunctions */ + + +#endif /* __CORE_CMFUNC_H */ diff --git a/bsp/gd32/libraries/GD32F20x_Firmware_Library/CMSIS/core_cmInstr.h b/bsp/gd32/libraries/GD32F20x_Firmware_Library/CMSIS/core_cmInstr.h new file mode 100644 index 0000000000..597e64df04 --- /dev/null +++ b/bsp/gd32/libraries/GD32F20x_Firmware_Library/CMSIS/core_cmInstr.h @@ -0,0 +1,618 @@ +/**************************************************************************//** + * @file core_cmInstr.h + * @brief CMSIS Cortex-M Core Instruction Access Header File + * @version V3.01 + * @date 06. March 2012 + * + * @note + * Copyright (C) 2009-2012 ARM Limited. All rights reserved. + * + * @par + * ARM Limited (ARM) is supplying this software for use with Cortex-M + * processor based microcontrollers. This file can be freely distributed + * within development tools that are supporting such ARM based processors. + * + * @par + * THIS SOFTWARE IS PROVIDED "AS IS". NO WARRANTIES, WHETHER EXPRESS, IMPLIED + * OR STATUTORY, INCLUDING, BUT NOT LIMITED TO, IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE APPLY TO THIS SOFTWARE. + * ARM SHALL NOT, IN ANY CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL, OR + * CONSEQUENTIAL DAMAGES, FOR ANY REASON WHATSOEVER. + * + ******************************************************************************/ + +#ifndef __CORE_CMINSTR_H +#define __CORE_CMINSTR_H + + +/* ########################## Core Instruction Access ######################### */ +/** \defgroup CMSIS_Core_InstructionInterface CMSIS Core Instruction Interface + Access to dedicated instructions + @{ +*/ + +#if defined ( __CC_ARM ) /*------------------RealView Compiler -----------------*/ +/* ARM armcc specific functions */ + +#if (__ARMCC_VERSION < 400677) + #error "Please use ARM Compiler Toolchain V4.0.677 or later!" +#endif + + +/** \brief No Operation + + No Operation does nothing. This instruction can be used for code alignment purposes. + */ +#define __NOP __nop + + +/** \brief Wait For Interrupt + + Wait For Interrupt is a hint instruction that suspends execution + until one of a number of events occurs. + */ +#define __WFI __wfi + + +/** \brief Wait For Event + + Wait For Event is a hint instruction that permits the processor to enter + a low-power state until one of a number of events occurs. + */ +#define __WFE __wfe + + +/** \brief Send Event + + Send Event is a hint instruction. It causes an event to be signaled to the CPU. + */ +#define __SEV __sev + + +/** \brief Instruction Synchronization Barrier + + Instruction Synchronization Barrier flushes the pipeline in the processor, + so that all instructions following the ISB are fetched from cache or + memory, after the instruction has been completed. + */ +#define __ISB() __isb(0xF) + + +/** \brief Data Synchronization Barrier + + This function acts as a special kind of Data Memory Barrier. + It completes when all explicit memory accesses before this instruction complete. + */ +#define __DSB() __dsb(0xF) + + +/** \brief Data Memory Barrier + + This function ensures the apparent order of the explicit memory operations before + and after the instruction, without ensuring their completion. + */ +#define __DMB() __dmb(0xF) + + +/** \brief Reverse byte order (32 bit) + + This function reverses the byte order in integer value. + + \param [in] value Value to reverse + \return Reversed value + */ +#define __REV __rev + + +/** \brief Reverse byte order (16 bit) + + This function reverses the byte order in two unsigned short values. + + \param [in] value Value to reverse + \return Reversed value + */ +__attribute__((section(".rev16_text"))) __STATIC_INLINE __ASM uint32_t __REV16(uint32_t value) +{ + rev16 r0, r0 + bx lr +} + + +/** \brief Reverse byte order in signed short value + + This function reverses the byte order in a signed short value with sign extension to integer. + + \param [in] value Value to reverse + \return Reversed value + */ +__attribute__((section(".revsh_text"))) __STATIC_INLINE __ASM int32_t __REVSH(int32_t value) +{ + revsh r0, r0 + bx lr +} + + +/** \brief Rotate Right in unsigned value (32 bit) + + This function Rotate Right (immediate) provides the value of the contents of a register rotated by a variable number of bits. + + \param [in] value Value to rotate + \param [in] value Number of Bits to rotate + \return Rotated value + */ +#define __ROR __ror + + +#if (__CORTEX_M >= 0x03) + +/** \brief Reverse bit order of value + + This function reverses the bit order of the given value. + + \param [in] value Value to reverse + \return Reversed value + */ +#define __RBIT __rbit + + +/** \brief LDR Exclusive (8 bit) + + This function performs a exclusive LDR command for 8 bit value. + + \param [in] ptr Pointer to data + \return value of type uint8_t at (*ptr) + */ +#define __LDREXB(ptr) ((uint8_t ) __ldrex(ptr)) + + +/** \brief LDR Exclusive (16 bit) + + This function performs a exclusive LDR command for 16 bit values. + + \param [in] ptr Pointer to data + \return value of type uint16_t at (*ptr) + */ +#define __LDREXH(ptr) ((uint16_t) __ldrex(ptr)) + + +/** \brief LDR Exclusive (32 bit) + + This function performs a exclusive LDR command for 32 bit values. + + \param [in] ptr Pointer to data + \return value of type uint32_t at (*ptr) + */ +#define __LDREXW(ptr) ((uint32_t ) __ldrex(ptr)) + + +/** \brief STR Exclusive (8 bit) + + This function performs a exclusive STR command for 8 bit values. + + \param [in] value Value to store + \param [in] ptr Pointer to location + \return 0 Function succeeded + \return 1 Function failed + */ +#define __STREXB(value, ptr) __strex(value, ptr) + + +/** \brief STR Exclusive (16 bit) + + This function performs a exclusive STR command for 16 bit values. + + \param [in] value Value to store + \param [in] ptr Pointer to location + \return 0 Function succeeded + \return 1 Function failed + */ +#define __STREXH(value, ptr) __strex(value, ptr) + + +/** \brief STR Exclusive (32 bit) + + This function performs a exclusive STR command for 32 bit values. + + \param [in] value Value to store + \param [in] ptr Pointer to location + \return 0 Function succeeded + \return 1 Function failed + */ +#define __STREXW(value, ptr) __strex(value, ptr) + + +/** \brief Remove the exclusive lock + + This function removes the exclusive lock which is created by LDREX. + + */ +#define __CLREX __clrex + + +/** \brief Signed Saturate + + This function saturates a signed value. + + \param [in] value Value to be saturated + \param [in] sat Bit position to saturate to (1..32) + \return Saturated value + */ +#define __SSAT __ssat + + +/** \brief Unsigned Saturate + + This function saturates an unsigned value. + + \param [in] value Value to be saturated + \param [in] sat Bit position to saturate to (0..31) + \return Saturated value + */ +#define __USAT __usat + + +/** \brief Count leading zeros + + This function counts the number of leading zeros of a data value. + + \param [in] value Value to count the leading zeros + \return number of leading zeros in value + */ +#define __CLZ __clz + +#endif /* (__CORTEX_M >= 0x03) */ + + + +#elif defined ( __ICCARM__ ) /*------------------ ICC Compiler -------------------*/ +/* IAR iccarm specific functions */ + +#include + + +#elif defined ( __TMS470__ ) /*---------------- TI CCS Compiler ------------------*/ +/* TI CCS specific functions */ + +#include + + +#elif defined ( __GNUC__ ) /*------------------ GNU Compiler ---------------------*/ +/* GNU gcc specific functions */ + +/** \brief No Operation + + No Operation does nothing. This instruction can be used for code alignment purposes. + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE void __NOP(void) +{ + __ASM volatile ("nop"); +} + + +/** \brief Wait For Interrupt + + Wait For Interrupt is a hint instruction that suspends execution + until one of a number of events occurs. + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE void __WFI(void) +{ + __ASM volatile ("wfi"); +} + + +/** \brief Wait For Event + + Wait For Event is a hint instruction that permits the processor to enter + a low-power state until one of a number of events occurs. + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE void __WFE(void) +{ + __ASM volatile ("wfe"); +} + + +/** \brief Send Event + + Send Event is a hint instruction. It causes an event to be signaled to the CPU. + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE void __SEV(void) +{ + __ASM volatile ("sev"); +} + + +/** \brief Instruction Synchronization Barrier + + Instruction Synchronization Barrier flushes the pipeline in the processor, + so that all instructions following the ISB are fetched from cache or + memory, after the instruction has been completed. + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE void __ISB(void) +{ + __ASM volatile ("isb"); +} + + +/** \brief Data Synchronization Barrier + + This function acts as a special kind of Data Memory Barrier. + It completes when all explicit memory accesses before this instruction complete. + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE void __DSB(void) +{ + __ASM volatile ("dsb"); +} + + +/** \brief Data Memory Barrier + + This function ensures the apparent order of the explicit memory operations before + and after the instruction, without ensuring their completion. + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE void __DMB(void) +{ + __ASM volatile ("dmb"); +} + + +/** \brief Reverse byte order (32 bit) + + This function reverses the byte order in integer value. + + \param [in] value Value to reverse + \return Reversed value + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __REV(uint32_t value) +{ + uint32_t result; + + __ASM volatile ("rev %0, %1" : "=r" (result) : "r" (value) ); + return(result); +} + + +/** \brief Reverse byte order (16 bit) + + This function reverses the byte order in two unsigned short values. + + \param [in] value Value to reverse + \return Reversed value + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __REV16(uint32_t value) +{ + uint32_t result; + + __ASM volatile ("rev16 %0, %1" : "=r" (result) : "r" (value) ); + return(result); +} + + +/** \brief Reverse byte order in signed short value + + This function reverses the byte order in a signed short value with sign extension to integer. + + \param [in] value Value to reverse + \return Reversed value + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE int32_t __REVSH(int32_t value) +{ + uint32_t result; + + __ASM volatile ("revsh %0, %1" : "=r" (result) : "r" (value) ); + return(result); +} + + +/** \brief Rotate Right in unsigned value (32 bit) + + This function Rotate Right (immediate) provides the value of the contents of a register rotated by a variable number of bits. + + \param [in] value Value to rotate + \param [in] value Number of Bits to rotate + \return Rotated value + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __ROR(uint32_t op1, uint32_t op2) +{ + + __ASM volatile ("ror %0, %0, %1" : "+r" (op1) : "r" (op2) ); + return(op1); +} + + +#if (__CORTEX_M >= 0x03) + +/** \brief Reverse bit order of value + + This function reverses the bit order of the given value. + + \param [in] value Value to reverse + \return Reversed value + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __RBIT(uint32_t value) +{ + uint32_t result; + + __ASM volatile ("rbit %0, %1" : "=r" (result) : "r" (value) ); + return(result); +} + + +/** \brief LDR Exclusive (8 bit) + + This function performs a exclusive LDR command for 8 bit value. + + \param [in] ptr Pointer to data + \return value of type uint8_t at (*ptr) + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE uint8_t __LDREXB(volatile uint8_t *addr) +{ + uint8_t result; + + __ASM volatile ("ldrexb %0, [%1]" : "=r" (result) : "r" (addr) ); + return(result); +} + + +/** \brief LDR Exclusive (16 bit) + + This function performs a exclusive LDR command for 16 bit values. + + \param [in] ptr Pointer to data + \return value of type uint16_t at (*ptr) + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE uint16_t __LDREXH(volatile uint16_t *addr) +{ + uint16_t result; + + __ASM volatile ("ldrexh %0, [%1]" : "=r" (result) : "r" (addr) ); + return(result); +} + + +/** \brief LDR Exclusive (32 bit) + + This function performs a exclusive LDR command for 32 bit values. + + \param [in] ptr Pointer to data + \return value of type uint32_t at (*ptr) + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __LDREXW(volatile uint32_t *addr) +{ + uint32_t result; + + __ASM volatile ("ldrex %0, [%1]" : "=r" (result) : "r" (addr) ); + return(result); +} + + +/** \brief STR Exclusive (8 bit) + + This function performs a exclusive STR command for 8 bit values. + + \param [in] value Value to store + \param [in] ptr Pointer to location + \return 0 Function succeeded + \return 1 Function failed + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __STREXB(uint8_t value, volatile uint8_t *addr) +{ + uint32_t result; + + __ASM volatile ("strexb %0, %2, [%1]" : "=&r" (result) : "r" (addr), "r" (value) ); + return(result); +} + + +/** \brief STR Exclusive (16 bit) + + This function performs a exclusive STR command for 16 bit values. + + \param [in] value Value to store + \param [in] ptr Pointer to location + \return 0 Function succeeded + \return 1 Function failed + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __STREXH(uint16_t value, volatile uint16_t *addr) +{ + uint32_t result; + + __ASM volatile ("strexh %0, %2, [%1]" : "=&r" (result) : "r" (addr), "r" (value) ); + return(result); +} + + +/** \brief STR Exclusive (32 bit) + + This function performs a exclusive STR command for 32 bit values. + + \param [in] value Value to store + \param [in] ptr Pointer to location + \return 0 Function succeeded + \return 1 Function failed + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __STREXW(uint32_t value, volatile uint32_t *addr) +{ + uint32_t result; + + __ASM volatile ("strex %0, %2, [%1]" : "=&r" (result) : "r" (addr), "r" (value) ); + return(result); +} + + +/** \brief Remove the exclusive lock + + This function removes the exclusive lock which is created by LDREX. + + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE void __CLREX(void) +{ + __ASM volatile ("clrex"); +} + + +/** \brief Signed Saturate + + This function saturates a signed value. + + \param [in] value Value to be saturated + \param [in] sat Bit position to saturate to (1..32) + \return Saturated value + */ +#define __SSAT(ARG1,ARG2) \ +({ \ + uint32_t __RES, __ARG1 = (ARG1); \ + __ASM ("ssat %0, %1, %2" : "=r" (__RES) : "I" (ARG2), "r" (__ARG1) ); \ + __RES; \ + }) + + +/** \brief Unsigned Saturate + + This function saturates an unsigned value. + + \param [in] value Value to be saturated + \param [in] sat Bit position to saturate to (0..31) + \return Saturated value + */ +#define __USAT(ARG1,ARG2) \ +({ \ + uint32_t __RES, __ARG1 = (ARG1); \ + __ASM ("usat %0, %1, %2" : "=r" (__RES) : "I" (ARG2), "r" (__ARG1) ); \ + __RES; \ + }) + + +/** \brief Count leading zeros + + This function counts the number of leading zeros of a data value. + + \param [in] value Value to count the leading zeros + \return number of leading zeros in value + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE uint8_t __CLZ(uint32_t value) +{ + uint8_t result; + + __ASM volatile ("clz %0, %1" : "=r" (result) : "r" (value) ); + return(result); +} + +#endif /* (__CORTEX_M >= 0x03) */ + + + + +#elif defined ( __TASKING__ ) /*------------------ TASKING Compiler --------------*/ +/* TASKING carm specific functions */ + +/* + * The CMSIS functions have been implemented as intrinsics in the compiler. + * Please use "carm -?i" to get an up to date list of all intrinsics, + * Including the CMSIS ones. + */ + +#endif + +/*@}*/ /* end of group CMSIS_Core_InstructionInterface */ + +#endif /* __CORE_CMINSTR_H */ diff --git a/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_standard_peripheral/Include/gd32f20x_adc.h b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_standard_peripheral/Include/gd32f20x_adc.h new file mode 100644 index 0000000000..78ebb5e49c --- /dev/null +++ b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_standard_peripheral/Include/gd32f20x_adc.h @@ -0,0 +1,411 @@ +/*! + \file gd32f20x_adc.h + \brief definitions for the ADC + + \version 2015-07-15, V1.0.0, firmware for GD32F20x + \version 2017-06-05, V2.0.0, firmware for GD32F20x + \version 2018-10-31, V2.1.0, firmware for GD32F20x + \version 2020-09-30, V2.2.0, firmware for GD32F20x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef GD32F20X_ADC_H +#define GD32F20X_ADC_H + +#include "gd32f20x.h" + +/* ADC definitions */ +#define ADC0 ADC_BASE +#define ADC1 (ADC_BASE + 0x400U) +#define ADC2 (ADC_BASE + 0x1800U) + +/* registers definitions */ +#define ADC_STAT(adcx) REG32((adcx) + 0x00U) /*!< ADC status register */ +#define ADC_CTL0(adcx) REG32((adcx) + 0x04U) /*!< ADC control register 0 */ +#define ADC_CTL1(adcx) REG32((adcx) + 0x08U) /*!< ADC control register 1 */ +#define ADC_SAMPT0(adcx) REG32((adcx) + 0x0CU) /*!< ADC sampling time register 0 */ +#define ADC_SAMPT1(adcx) REG32((adcx) + 0x10U) /*!< ADC sampling time register 1 */ +#define ADC_IOFF0(adcx) REG32((adcx) + 0x14U) /*!< ADC inserted channel data offset register 0 */ +#define ADC_IOFF1(adcx) REG32((adcx) + 0x18U) /*!< ADC inserted channel data offset register 1 */ +#define ADC_IOFF2(adcx) REG32((adcx) + 0x1CU) /*!< ADC inserted channel data offset register 2 */ +#define ADC_IOFF3(adcx) REG32((adcx) + 0x20U) /*!< ADC inserted channel data offset register 3 */ +#define ADC_WDHT(adcx) REG32((adcx) + 0x24U) /*!< ADC watchdog high threshold register */ +#define ADC_WDLT(adcx) REG32((adcx) + 0x28U) /*!< ADC watchdog low threshold register */ +#define ADC_RSQ0(adcx) REG32((adcx) + 0x2CU) /*!< ADC regular sequence register 0 */ +#define ADC_RSQ1(adcx) REG32((adcx) + 0x30U) /*!< ADC regular sequence register 1 */ +#define ADC_RSQ2(adcx) REG32((adcx) + 0x34U) /*!< ADC regular sequence register 2 */ +#define ADC_ISQ(adcx) REG32((adcx) + 0x38U) /*!< ADC inserted sequence register */ +#define ADC_IDATA0(adcx) REG32((adcx) + 0x3CU) /*!< ADC inserted data register 0 */ +#define ADC_IDATA1(adcx) REG32((adcx) + 0x40U) /*!< ADC inserted data register 1 */ +#define ADC_IDATA2(adcx) REG32((adcx) + 0x44U) /*!< ADC inserted data register 2 */ +#define ADC_IDATA3(adcx) REG32((adcx) + 0x48U) /*!< ADC inserted data register 3 */ +#define ADC_RDATA(adcx) REG32((adcx) + 0x4CU) /*!< ADC regular data register */ +#define ADC_OVSAMPCTL(adcx) REG32((adcx) + 0x80U) /*!< ADC oversampling control register */ + +/* bits definitions */ +/* ADC_STAT */ +#define ADC_STAT_WDE BIT(0) /*!< analog watchdog event flag */ +#define ADC_STAT_EOC BIT(1) /*!< end of conversion */ +#define ADC_STAT_EOIC BIT(2) /*!< inserted channel end of conversion */ +#define ADC_STAT_STIC BIT(3) /*!< inserted channel start flag */ +#define ADC_STAT_STRC BIT(4) /*!< regular channel start flag */ + +/* ADC_CTL0 */ +#define ADC_CTL0_WDCHSEL BITS(0,4) /*!< analog watchdog channel select bits */ +#define ADC_CTL0_EOCIE BIT(5) /*!< interrupt enable for EOC */ +#define ADC_CTL0_WDEIE BIT(6) /*!< analog watchdog interrupt enable */ +#define ADC_CTL0_EOICIE BIT(7) /*!< interrupt enable for inserted channels */ +#define ADC_CTL0_SM BIT(8) /*!< scan mode */ +#define ADC_CTL0_WDSC BIT(9) /*!< when in scan mode, analog watchdog is effective on a single channel */ +#define ADC_CTL0_ICA BIT(10) /*!< automatic inserted group conversion */ +#define ADC_CTL0_DISRC BIT(11) /*!< discontinuous mode on regular channels */ +#define ADC_CTL0_DISIC BIT(12) /*!< discontinuous mode on inserted channels */ +#define ADC_CTL0_DISNUM BITS(13,15) /*!< discontinuous mode channel count */ +#define ADC_CTL0_SYNCM BITS(16,19) /*!< sync mode selection */ +#define ADC_CTL0_IWDEN BIT(22) /*!< analog watchdog enable on inserted channels */ +#define ADC_CTL0_RWDEN BIT(23) /*!< analog watchdog enable on regular channels */ + +/* ADC_CTL1 */ +#define ADC_CTL1_ADCON BIT(0) /*!< ADC converter on */ +#define ADC_CTL1_CTN BIT(1) /*!< continuous conversion */ +#define ADC_CTL1_CLB BIT(2) /*!< ADC calibration */ +#define ADC_CTL1_RSTCLB BIT(3) /*!< reset calibration */ +#define ADC_CTL1_DMA BIT(8) /*!< direct memory access mode */ +#define ADC_CTL1_DAL BIT(11) /*!< data alignment */ +#define ADC_CTL1_ETSIC BITS(12,14) /*!< external trigger select for inserted channel */ +#define ADC_CTL1_ETEIC BIT(15) /*!< external trigger enable for inserted channel */ +#define ADC_CTL1_ETSRC BITS(17,19) /*!< external trigger select for regular channel */ +#define ADC_CTL1_ETERC BIT(20) /*!< external trigger enable for regular channel */ +#define ADC_CTL1_SWICST BIT(21) /*!< start on inserted channel */ +#define ADC_CTL1_SWRCST BIT(22) /*!< start on regular channel */ +#define ADC_CTL1_TSVREN BIT(23) /*!< channel 16 and 17 enable of ADC0 */ + +/* ADC_SAMPTx x=0,1 */ +#define ADC_SAMPTX_SPTN BITS(0,2) /*!< channel n sample time selection */ + +/* ADC_IOFFx x=0..3 */ +#define ADC_IOFFX_IOFF BITS(0,11) /*!< data offset for inserted channel x */ + +/* ADC_WDHT */ +#define ADC_WDHT_WDHT BITS(0,11) /*!< analog watchdog high threshold */ + +/* ADC_WDLT */ +#define ADC_WDLT_WDLT BITS(0,11) /*!< analog watchdog low threshold */ + +/* ADC_RSQx x=0..2 */ +#define ADC_RSQX_RSQN BITS(0,4) /*!< x conversion in regular sequence */ +#define ADC_RSQ0_RL BITS(20,23) /*!< regular channel sequence length */ + +/* ADC_ISQ */ +#define ADC_ISQ_ISQN BITS(0,4) /*!< n conversion in regular sequence */ +#define ADC_ISQ_IL BITS(20,21) /*!< inserted sequence length */ + +/* ADC_IDATAx x=0..3*/ +#define ADC_IDATAX_IDATAN BITS(0,15) /*!< inserted channel x conversion data */ + +/* ADC_RDATA */ +#define ADC_RDATA_RDATA BITS(0,15) /*!< regular channel data */ +#define ADC_RDATA_ADC1RDTR BITS(16,31) /*!< ADC1 regular channel data */ + +/* ADC_OVSAMPCTL */ +#define ADC_OVSAMPCTL_OVSEN BIT(0) /*!< oversampling enable */ +#define ADC_OVSAMPCTL_OVSR BITS(2,4) /*!< oversampling ratio */ +#define ADC_OVSAMPCTL_OVSS BITS(5,8) /*!< oversampling shift */ +#define ADC_OVSAMPCTL_TOVS BIT(9) /*!< triggered oversampling */ +#define ADC_OVSAMPCTL_DRES BITS(12,13) /*!< oversampling shift */ + +/* constants definitions */ +/* adc_stat register value */ +#define ADC_FLAG_WDE ADC_STAT_WDE /*!< analog watchdog event flag */ +#define ADC_FLAG_EOC ADC_STAT_EOC /*!< end of group conversion flag */ +#define ADC_FLAG_EOIC ADC_STAT_EOIC /*!< end of inserted channel group conversion flag */ +#define ADC_FLAG_STIC ADC_STAT_STIC /*!< inserted channel start flag */ +#define ADC_FLAG_STRC ADC_STAT_STRC /*!< regular channel start flag */ + +/* adc_ctl0 register value */ +#define CTL0_DISNUM(regval) (BITS(13,15) & ((uint32_t)(regval) << 13)) /*!< write value to ADC_CTL0_DISNUM bit field */ + +/* scan mode */ +#define ADC_SCAN_MODE ADC_CTL0_SM /*!< scan mode */ + +/* inserted channel group convert automatically */ +#define ADC_INSERTED_CHANNEL_AUTO ADC_CTL0_ICA /*!< inserted channel group convert automatically */ + +/* ADC sync mode */ +#define CTL0_SYNCM(regval) (BITS(16,19) & ((uint32_t)(regval) << 16)) /*!< write value to ADC_CTL0_SYNCM bit field */ +#define ADC_MODE_FREE CTL0_SYNCM(0) /*!< all the ADCs work independently */ +#define ADC_DAUL_REGULAL_PARALLEL_INSERTED_PARALLEL CTL0_SYNCM(1) /*!< ADC0 and ADC1 work in combined regular parallel + inserted parallel mode */ +#define ADC_DAUL_REGULAL_PARALLEL_INSERTED_ROTATION CTL0_SYNCM(2) /*!< ADC0 and ADC1 work in combined regular parallel + trigger rotation mode */ +#define ADC_DAUL_INSERTED_PARALLEL_REGULAL_FOLLOWUP_FAST CTL0_SYNCM(3) /*!< ADC0 and ADC1 work in combined inserted parallel + follow-up fast mode */ +#define ADC_DAUL_INSERTED_PARALLEL_REGULAL_FOLLOWUP_SLOW CTL0_SYNCM(4) /*!< ADC0 and ADC1 work in combined inserted parallel + follow-up slow mode */ +#define ADC_DAUL_INSERTED_PARALLEL CTL0_SYNCM(5) /*!< ADC0 and ADC1 work in inserted parallel mode only */ +#define ADC_DAUL_REGULAL_PARALLEL CTL0_SYNCM(6) /*!< ADC0 and ADC1 work in regular parallel mode only */ +#define ADC_DAUL_REGULAL_FOLLOWUP_FAST CTL0_SYNCM(7) /*!< ADC0 and ADC1 work in follow-up fast mode only */ +#define ADC_DAUL_REGULAL_FOLLOWUP_SLOW CTL0_SYNCM(8) /*!< ADC0 and ADC1 work in follow-up slow mode only */ +#define ADC_DAUL_INSERTED_TRIGGER_ROTATION CTL0_SYNCM(9) /*!< ADC0 and ADC1 work in trigger rotation mode only */ + +/* adc_ctl1 register value */ +#define ADC_DATAALIGN_RIGHT ((uint32_t)0x00000000U) /*!< LSB alignment */ +#define ADC_DATAALIGN_LEFT ADC_CTL1_DAL /*!< MSB alignment */ + +/* continuous mode */ +#define ADC_CONTINUOUS_MODE ADC_CTL1_CTN /*!< continuous mode */ + +/* external trigger select for regular channel */ +#define CTL1_ETSRC(regval) (BITS(17,19) & ((uint32_t)(regval) << 17)) /*!< write value to ADC_CTL1_ETSRC bit field */ +/* for ADC0 and ADC1 regular channel */ +#define ADC0_1_EXTTRIG_REGULAR_T0_CH0 CTL1_ETSRC(0) /*!< TIMER0 CH0 event select */ +#define ADC0_1_EXTTRIG_REGULAR_T0_CH1 CTL1_ETSRC(1) /*!< TIMER0 CH1 event select */ +#define ADC0_1_EXTTRIG_REGULAR_T0_CH2 CTL1_ETSRC(2) /*!< TIMER0 CH2 event select */ +#define ADC0_1_EXTTRIG_REGULAR_T1_CH1 CTL1_ETSRC(3) /*!< TIMER1 CH1 event select */ +#define ADC0_1_EXTTRIG_REGULAR_T2_TRGO CTL1_ETSRC(4) /*!< TIMER2 TRGO event select */ +#define ADC0_1_EXTTRIG_REGULAR_T3_CH3 CTL1_ETSRC(5) /*!< TIMER3 CH3 event select */ +#define ADC0_1_EXTTRIG_REGULAR_T7_TRGO CTL1_ETSRC(6) /*!< TIMER7 TRGO event select */ +#define ADC0_1_EXTTRIG_REGULAR_EXTI_11 CTL1_ETSRC(6) /*!< external interrupt line 11 */ +#define ADC0_1_2_EXTTRIG_REGULAR_NONE CTL1_ETSRC(7) /*!< software trigger */ +/* for ADC2 regular channel */ +#define ADC2_EXTTRIG_REGULAR_T2_CH0 CTL1_ETSRC(0) /*!< TIMER2 CH0 event select */ +#define ADC2_EXTTRIG_REGULAR_T1_CH2 CTL1_ETSRC(1) /*!< TIMER1 CH2 event select */ +#define ADC2_EXTTRIG_REGULAR_T0_CH2 CTL1_ETSRC(2) /*!< TIMER0 CH2 event select */ +#define ADC2_EXTTRIG_REGULAR_T7_CH0 CTL1_ETSRC(3) /*!< TIMER7 CH0 event select */ +#define ADC2_EXTTRIG_REGULAR_T7_TRGO CTL1_ETSRC(4) /*!< TIMER7 TRGO event select */ +#define ADC2_EXTTRIG_REGULAR_T4_CH0 CTL1_ETSRC(5) /*!< TIMER4 CH0 event select */ +#define ADC2_EXTTRIG_REGULAR_T4_CH2 CTL1_ETSRC(6) /*!< TIMER4 CH2 event select */ + +/* external trigger mode for inserted channel */ +#define CTL1_ETSIC(regval) (BITS(12,14) & ((uint32_t)(regval) << 12)) /*!< write value to ADC_CTL1_ETSIC bit field */ +/* for ADC0 and ADC1 inserted channel */ +#define ADC0_1_EXTTRIG_INSERTED_T0_TRGO CTL1_ETSIC(0) /*!< TIMER0 TRGO event select */ +#define ADC0_1_EXTTRIG_INSERTED_T0_CH3 CTL1_ETSIC(1) /*!< TIMER0 CH3 event select */ +#define ADC0_1_EXTTRIG_INSERTED_T1_TRGO CTL1_ETSIC(2) /*!< TIMER1 TRGO event select */ +#define ADC0_1_EXTTRIG_INSERTED_T1_CH0 CTL1_ETSIC(3) /*!< TIMER1 CH0 event select */ +#define ADC0_1_EXTTRIG_INSERTED_T2_CH3 CTL1_ETSIC(4) /*!< TIMER2 CH3 event select */ +#define ADC0_1_EXTTRIG_INSERTED_T3_TRGO CTL1_ETSIC(5) /*!< TIMER3 TRGO event select */ +#define ADC0_1_EXTTRIG_INSERTED_EXTI_15 CTL1_ETSIC(6) /*!< external interrupt line 15 */ +#define ADC0_1_EXTTRIG_INSERTED_T7_CH3 CTL1_ETSIC(6) /*!< TIMER7 CH3 event select */ +#define ADC0_1_2_EXTTRIG_INSERTED_NONE CTL1_ETSIC(7) /*!< software trigger */ +/* for ADC2 inserted channel */ +#define ADC2_EXTTRIG_INSERTED_T0_TRGO CTL1_ETSIC(0) /*!< TIMER0 TRGO event select */ +#define ADC2_EXTTRIG_INSERTED_T0_CH3 CTL1_ETSIC(1) /*!< TIMER0 CH3 event select */ +#define ADC2_EXTTRIG_INSERTED_T3_CH2 CTL1_ETSIC(2) /*!< TIMER3 CH2 event select */ +#define ADC2_EXTTRIG_INSERTED_T7_CH1 CTL1_ETSIC(3) /*!< TIMER7 CH1 event select */ +#define ADC2_EXTTRIG_INSERTED_T7_CH3 CTL1_ETSIC(4) /*!< TIMER7 CH3 event select */ +#define ADC2_EXTTRIG_INSERTED_T4_TRGO CTL1_ETSIC(5) /*!< TIMER4 TRGO event select */ +#define ADC2_EXTTRIG_INSERTED_T4_CH3 CTL1_ETSIC(6) /*!< TIMER4 CH3 event select */ + +/* adc_samptx register value */ +#define SAMPTX_SPT(regval) (BITS(0,2) & ((uint32_t)(regval) << 0)) /*!< write value to ADC_SAMPTX_SPT bit field */ +#define ADC_SAMPLETIME_1POINT5 SAMPTX_SPT(0) /*!< 1.5 sampling cycles */ +#define ADC_SAMPLETIME_7POINT5 SAMPTX_SPT(1) /*!< 7.5 sampling cycles */ +#define ADC_SAMPLETIME_13POINT5 SAMPTX_SPT(2) /*!< 13.5 sampling cycles */ +#define ADC_SAMPLETIME_28POINT5 SAMPTX_SPT(3) /*!< 28.5 sampling cycles */ +#define ADC_SAMPLETIME_41POINT5 SAMPTX_SPT(4) /*!< 41.5 sampling cycles */ +#define ADC_SAMPLETIME_55POINT5 SAMPTX_SPT(5) /*!< 55.5 sampling cycles */ +#define ADC_SAMPLETIME_71POINT5 SAMPTX_SPT(6) /*!< 71.5 sampling cycles */ +#define ADC_SAMPLETIME_239POINT5 SAMPTX_SPT(7) /*!< 239.5 sampling cycles */ + +/* adc_ioffx register value */ +#define IOFFX_IOFF(regval) (BITS(0,11) & ((uint32_t)(regval) << 0)) /*!< write value to ADC_IOFFX_IOFF bit field */ + +/* adc_wdht register value */ +#define WDHT_WDHT(regval) (BITS(0,11) & ((uint32_t)(regval) << 0)) /*!< write value to ADC_WDHT_WDHT bit field */ + +/* adc_wdlt register value */ +#define WDLT_WDLT(regval) (BITS(0,11) & ((uint32_t)(regval) << 0)) /*!< write value to ADC_WDLT_WDLT bit field */ + +/* adc_rsqx register value */ +#define RSQ0_RL(regval) (BITS(20,23) & ((uint32_t)(regval) << 20)) /*!< write value to ADC_RSQ0_RL bit field */ + +/* adc_isq register value */ +#define ISQ_IL(regval) (BITS(20,21) & ((uint32_t)(regval) << 20)) /*!< write value to ADC_ISQ_IL bit field */ + +/* adc_ovsampctl register value */ +#define OVSAMPCTL_DRES(regval) (BITS(12,13) & ((uint32_t)(regval) << 12)) /*!< write value to ADC_OVSAMPCTL_DRES bit field */ +#define ADC_RESOLUTION_12B OVSAMPCTL_DRES(0) /*!< 12-bit ADC resolution */ +#define ADC_RESOLUTION_10B OVSAMPCTL_DRES(1) /*!< 10-bit ADC resolution */ +#define ADC_RESOLUTION_8B OVSAMPCTL_DRES(2) /*!< 8-bit ADC resolution */ +#define ADC_RESOLUTION_6B OVSAMPCTL_DRES(3) /*!< 6-bit ADC resolution */ + +#define OVSAMPCTL_OVSS(regval) (BITS(5,8) & ((uint32_t)(regval) << 5)) /*!< write value to ADC_OVSAMPCTL_OVSS bit field */ +#define ADC_OVERSAMPLING_SHIFT_NONE OVSAMPCTL_OVSS(0) /*!< no oversampling shift */ +#define ADC_OVERSAMPLING_SHIFT_1B OVSAMPCTL_OVSS(1) /*!< 1-bit oversampling shift */ +#define ADC_OVERSAMPLING_SHIFT_2B OVSAMPCTL_OVSS(2) /*!< 2-bit oversampling shift */ +#define ADC_OVERSAMPLING_SHIFT_3B OVSAMPCTL_OVSS(3) /*!< 3-bit oversampling shift */ +#define ADC_OVERSAMPLING_SHIFT_4B OVSAMPCTL_OVSS(4) /*!< 4-bit oversampling shift */ +#define ADC_OVERSAMPLING_SHIFT_5B OVSAMPCTL_OVSS(5) /*!< 5-bit oversampling shift */ +#define ADC_OVERSAMPLING_SHIFT_6B OVSAMPCTL_OVSS(6) /*!< 6-bit oversampling shift */ +#define ADC_OVERSAMPLING_SHIFT_7B OVSAMPCTL_OVSS(7) /*!< 7-bit oversampling shift */ +#define ADC_OVERSAMPLING_SHIFT_8B OVSAMPCTL_OVSS(8) /*!< 8-bit oversampling shift */ + +#define OVSAMPCTL_OVSR(regval) (BITS(2,4) & ((uint32_t)(regval) << 2)) /*!< write value to ADC_OVSAMPCTL_OVSR bit field */ +#define ADC_OVERSAMPLING_RATIO_MUL2 OVSAMPCTL_OVSR(0) /*!< oversampling ratio multiple 2 */ +#define ADC_OVERSAMPLING_RATIO_MUL4 OVSAMPCTL_OVSR(1) /*!< oversampling ratio multiple 4 */ +#define ADC_OVERSAMPLING_RATIO_MUL8 OVSAMPCTL_OVSR(2) /*!< oversampling ratio multiple 8 */ +#define ADC_OVERSAMPLING_RATIO_MUL16 OVSAMPCTL_OVSR(3) /*!< oversampling ratio multiple 16 */ +#define ADC_OVERSAMPLING_RATIO_MUL32 OVSAMPCTL_OVSR(4) /*!< oversampling ratio multiple 32 */ +#define ADC_OVERSAMPLING_RATIO_MUL64 OVSAMPCTL_OVSR(5) /*!< oversampling ratio multiple 64 */ +#define ADC_OVERSAMPLING_RATIO_MUL128 OVSAMPCTL_OVSR(6) /*!< oversampling ratio multiple 128 */ +#define ADC_OVERSAMPLING_RATIO_MUL256 OVSAMPCTL_OVSR(7) /*!< oversampling ratio multiple 256 */ + +#define ADC_OVERSAMPLING_ALL_CONVERT 0U /*!< all oversampled conversions for a channel are done consecutively after a trigger */ +#define ADC_OVERSAMPLING_ONE_CONVERT 1U /*!< each oversampled conversion for a channel needs a trigger */ + +/* ADC channel group definitions */ +#define ADC_REGULAR_CHANNEL ((uint8_t)0x01U) /*!< ADC regular channel group */ +#define ADC_INSERTED_CHANNEL ((uint8_t)0x02U) /*!< ADC inserted channel group */ +#define ADC_REGULAR_INSERTED_CHANNEL ((uint8_t)0x03U) /*!< both regular and inserted channel group */ + +#define ADC_CHANNEL_DISCON_DISABLE ((uint8_t)0x04U) /*!< disable discontinuous mode of regular & inserted channel */ + +/* ADC inserted channel definitions */ +#define ADC_INSERTED_CHANNEL_0 ((uint8_t)0x00U) /*!< ADC inserted channel 0 */ +#define ADC_INSERTED_CHANNEL_1 ((uint8_t)0x01U) /*!< ADC inserted channel 1 */ +#define ADC_INSERTED_CHANNEL_2 ((uint8_t)0x02U) /*!< ADC inserted channel 2 */ +#define ADC_INSERTED_CHANNEL_3 ((uint8_t)0x03U) /*!< ADC inserted channel 3 */ + +/* ADC channel definitions */ +#define ADC_CHANNEL_0 ((uint8_t)0x00U) /*!< ADC channel 0 */ +#define ADC_CHANNEL_1 ((uint8_t)0x01U) /*!< ADC channel 1 */ +#define ADC_CHANNEL_2 ((uint8_t)0x02U) /*!< ADC channel 2 */ +#define ADC_CHANNEL_3 ((uint8_t)0x03U) /*!< ADC channel 3 */ +#define ADC_CHANNEL_4 ((uint8_t)0x04U) /*!< ADC channel 4 */ +#define ADC_CHANNEL_5 ((uint8_t)0x05U) /*!< ADC channel 5 */ +#define ADC_CHANNEL_6 ((uint8_t)0x06U) /*!< ADC channel 6 */ +#define ADC_CHANNEL_7 ((uint8_t)0x07U) /*!< ADC channel 7 */ +#define ADC_CHANNEL_8 ((uint8_t)0x08U) /*!< ADC channel 8 */ +#define ADC_CHANNEL_9 ((uint8_t)0x09U) /*!< ADC channel 9 */ +#define ADC_CHANNEL_10 ((uint8_t)0x0AU) /*!< ADC channel 10 */ +#define ADC_CHANNEL_11 ((uint8_t)0x0BU) /*!< ADC channel 11 */ +#define ADC_CHANNEL_12 ((uint8_t)0x0CU) /*!< ADC channel 12 */ +#define ADC_CHANNEL_13 ((uint8_t)0x0DU) /*!< ADC channel 13 */ +#define ADC_CHANNEL_14 ((uint8_t)0x0EU) /*!< ADC channel 14 */ +#define ADC_CHANNEL_15 ((uint8_t)0x0FU) /*!< ADC channel 15 */ +#define ADC_CHANNEL_16 ((uint8_t)0x10U) /*!< ADC channel 16 */ +#define ADC_CHANNEL_17 ((uint8_t)0x11U) /*!< ADC channel 17 */ + +/* ADC interrupt */ +#define ADC_INT_WDE ADC_STAT_WDE /*!< analog watchdog event interrupt */ +#define ADC_INT_EOC ADC_STAT_EOC /*!< end of group conversion interrupt */ +#define ADC_INT_EOIC ADC_STAT_EOIC /*!< end of inserted group conversion interrupt */ + +/* ADC interrupt flag */ +#define ADC_INT_FLAG_WDE ADC_STAT_WDE /*!< analog watchdog event interrupt flag */ +#define ADC_INT_FLAG_EOC ADC_STAT_EOC /*!< end of group conversion interrupt flag */ +#define ADC_INT_FLAG_EOIC ADC_STAT_EOIC /*!< end of inserted group conversion interrupt flag */ + +/* function declarations */ +/* initialization configure */ +/* reset ADC */ +void adc_deinit(uint32_t adc_periph); +/* configure the ADC sync mode */ +void adc_mode_config(uint32_t mode); +/* enable or disable ADC special function */ +void adc_special_function_config(uint32_t adc_periph, uint32_t function, ControlStatus new_value); +/* configure ADC data alignment */ +void adc_data_alignment_config(uint32_t adc_periph, uint32_t data_alignment); +/* enable ADC interface */ +void adc_enable(uint32_t adc_periph); +/* disable ADC interface */ +void adc_disable(uint32_t adc_periph); +/* ADC calibration and reset calibration */ +void adc_calibration_enable(uint32_t adc_periph); +/* enable the temperature sensor and Vrefint channel */ +void adc_tempsensor_vrefint_enable(void); +/* disable the temperature sensor and Vrefint channel */ +void adc_tempsensor_vrefint_disable(void); + +/* function configuration */ +/* DMA configure */ +/* enable DMA request */ +void adc_dma_mode_enable(uint32_t adc_periph); +/* disable DMA request */ +void adc_dma_mode_disable(uint32_t adc_periph); + +/* regular group and inserted group configure */ +/* configure ADC discontinuous mode */ +void adc_discontinuous_mode_config(uint32_t adc_periph, uint8_t adc_channel_group, uint8_t length); + +/* configure the length of regular channel group or inserted channel group */ +void adc_channel_length_config(uint32_t adc_periph, uint8_t adc_channel_group, uint32_t length); +/* configure ADC regular channel */ +void adc_regular_channel_config(uint32_t adc_periph, uint8_t rank, uint8_t adc_channel, uint32_t sample_time); +/* configure ADC inserted channel */ +void adc_inserted_channel_config(uint32_t adc_periph, uint8_t rank, uint8_t adc_channel, uint32_t sample_time); +/* configure ADC inserted channel offset */ +void adc_inserted_channel_offset_config(uint32_t adc_periph, uint8_t inserted_channel, uint16_t offset); + +/* configure ADC external trigger source */ +void adc_external_trigger_source_config(uint32_t adc_periph, uint8_t adc_channel_group, uint32_t external_trigger_source); +/* configure ADC external trigger */ +void adc_external_trigger_config(uint32_t adc_periph, uint8_t adc_channel_group, ControlStatus newvalue); +/* enable ADC software trigger */ +void adc_software_trigger_enable(uint32_t adc_periph, uint8_t adc_channel_group); + +/* get channel data */ +/* read ADC regular group data register */ +uint16_t adc_regular_data_read(uint32_t adc_periph); +/* read ADC inserted group data register */ +uint16_t adc_inserted_data_read(uint32_t adc_periph, uint8_t inserted_channel); +/* read the last ADC0 and ADC1 conversion result data in sync mode */ +uint32_t adc_sync_mode_convert_value_read(void); + +/* watchdog configure */ +/* configure ADC analog watchdog single channel */ +void adc_watchdog_single_channel_enable(uint32_t adc_periph, uint8_t adc_channel); +/* configure ADC analog watchdog group channel */ +void adc_watchdog_group_channel_enable(uint32_t adc_periph, uint8_t adc_channel_group); +/* disable ADC analog watchdog */ +void adc_watchdog_disable(uint32_t adc_periph); +/* configure ADC analog watchdog threshold */ +void adc_watchdog_threshold_config(uint32_t adc_periph, uint16_t low_threshold, uint16_t high_threshold); + +/* interrupt & flag functions */ +/* get the ADC flag bits */ +FlagStatus adc_flag_get(uint32_t adc_periph, uint32_t adc_flag); +/* clear the ADC flag bits */ +void adc_flag_clear(uint32_t adc_periph, uint32_t adc_flag); +/* get the ADC interrupt flag */ +FlagStatus adc_interrupt_flag_get(uint32_t adc_periph, uint32_t adc_interrupt); +/* clear the ADC interrupt flag */ +void adc_interrupt_flag_clear(uint32_t adc_periph, uint32_t adc_interrupt); +/* enable ADC interrupt */ +void adc_interrupt_enable(uint32_t adc_periph, uint32_t adc_interrupt); +/* disable ADC interrupt */ +void adc_interrupt_disable(uint32_t adc_periph, uint32_t adc_interrupt); + +/* configure ADC resolution */ +void adc_resolution_config(uint32_t adc_periph, uint32_t resolution); +/* configure ADC oversample mode */ +void adc_oversample_mode_config(uint32_t adc_periph, uint8_t mode, uint16_t shift, uint8_t ratio); +/* enable ADC oversample mode */ +void adc_oversample_mode_enable(uint32_t adc_periph); +/* disable ADC oversample mode */ +void adc_oversample_mode_disable(uint32_t adc_periph); + +#endif /* GD32F20X_ADC_H */ diff --git a/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_standard_peripheral/Include/gd32f20x_bkp.h b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_standard_peripheral/Include/gd32f20x_bkp.h new file mode 100644 index 0000000000..732c776880 --- /dev/null +++ b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_standard_peripheral/Include/gd32f20x_bkp.h @@ -0,0 +1,273 @@ +/*! + \file gd32f20x_bkp.h + \brief definitions for the BKP + + \version 2015-07-15, V1.0.0, firmware for GD32F20x + \version 2017-06-05, V2.0.0, firmware for GD32F20x + \version 2018-10-31, V2.1.0, firmware for GD32F20x + \version 2020-09-30, V2.2.0, firmware for GD32F20x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef GD32F20X_BKP_H +#define GD32F20X_BKP_H + +#include "gd32f20x.h" + +/* BKP definitions */ +#define BKP BKP_BASE /*!< BKP base address */ + +/* registers definitions */ +#define BKP_DATA0 REG16((BKP) + 0x04U) /*!< BKP data register 0 */ +#define BKP_DATA1 REG16((BKP) + 0x08U) /*!< BKP data register 1 */ +#define BKP_DATA2 REG16((BKP) + 0x0CU) /*!< BKP data register 2 */ +#define BKP_DATA3 REG16((BKP) + 0x10U) /*!< BKP data register 3 */ +#define BKP_DATA4 REG16((BKP) + 0x14U) /*!< BKP data register 4 */ +#define BKP_DATA5 REG16((BKP) + 0x18U) /*!< BKP data register 5 */ +#define BKP_DATA6 REG16((BKP) + 0x1CU) /*!< BKP data register 6 */ +#define BKP_DATA7 REG16((BKP) + 0x20U) /*!< BKP data register 7 */ +#define BKP_DATA8 REG16((BKP) + 0x24U) /*!< BKP data register 8 */ +#define BKP_DATA9 REG16((BKP) + 0x28U) /*!< BKP data register 9 */ +#define BKP_DATA10 REG16((BKP) + 0x40U) /*!< BKP data register 10 */ +#define BKP_DATA11 REG16((BKP) + 0x44U) /*!< BKP data register 11 */ +#define BKP_DATA12 REG16((BKP) + 0x48U) /*!< BKP data register 12 */ +#define BKP_DATA13 REG16((BKP) + 0x4CU) /*!< BKP data register 13 */ +#define BKP_DATA14 REG16((BKP) + 0x50U) /*!< BKP data register 14 */ +#define BKP_DATA15 REG16((BKP) + 0x54U) /*!< BKP data register 15 */ +#define BKP_DATA16 REG16((BKP) + 0x58U) /*!< BKP data register 16 */ +#define BKP_DATA17 REG16((BKP) + 0x5CU) /*!< BKP data register 17 */ +#define BKP_DATA18 REG16((BKP) + 0x60U) /*!< BKP data register 18 */ +#define BKP_DATA19 REG16((BKP) + 0x64U) /*!< BKP data register 19 */ +#define BKP_DATA20 REG16((BKP) + 0x68U) /*!< BKP data register 20 */ +#define BKP_DATA21 REG16((BKP) + 0x6CU) /*!< BKP data register 21 */ +#define BKP_DATA22 REG16((BKP) + 0x70U) /*!< BKP data register 22 */ +#define BKP_DATA23 REG16((BKP) + 0x74U) /*!< BKP data register 23 */ +#define BKP_DATA24 REG16((BKP) + 0x78U) /*!< BKP data register 24 */ +#define BKP_DATA25 REG16((BKP) + 0x7CU) /*!< BKP data register 25 */ +#define BKP_DATA26 REG16((BKP) + 0x80U) /*!< BKP data register 26 */ +#define BKP_DATA27 REG16((BKP) + 0x84U) /*!< BKP data register 27 */ +#define BKP_DATA28 REG16((BKP) + 0x88U) /*!< BKP data register 28 */ +#define BKP_DATA29 REG16((BKP) + 0x8CU) /*!< BKP data register 29 */ +#define BKP_DATA30 REG16((BKP) + 0x90U) /*!< BKP data register 30 */ +#define BKP_DATA31 REG16((BKP) + 0x94U) /*!< BKP data register 31 */ +#define BKP_DATA32 REG16((BKP) + 0x98U) /*!< BKP data register 32 */ +#define BKP_DATA33 REG16((BKP) + 0x9CU) /*!< BKP data register 33 */ +#define BKP_DATA34 REG16((BKP) + 0xA0U) /*!< BKP data register 34 */ +#define BKP_DATA35 REG16((BKP) + 0xA4U) /*!< BKP data register 35 */ +#define BKP_DATA36 REG16((BKP) + 0xA8U) /*!< BKP data register 36 */ +#define BKP_DATA37 REG16((BKP) + 0xACU) /*!< BKP data register 37 */ +#define BKP_DATA38 REG16((BKP) + 0xB0U) /*!< BKP data register 38 */ +#define BKP_DATA39 REG16((BKP) + 0xB4U) /*!< BKP data register 39 */ +#define BKP_DATA40 REG16((BKP) + 0xB8U) /*!< BKP data register 40 */ +#define BKP_DATA41 REG16((BKP) + 0xBCU) /*!< BKP data register 41 */ +#define BKP_OCTL REG16((BKP) + 0x2CU) /*!< RTC signal output control register */ +#define BKP_TPCTL0 REG16((BKP) + 0x30U) /*!< tamper pin control register 0 */ +#define BKP_TPCS REG16((BKP) + 0x34U) /*!< tamper control and status register */ +#define BKP_TPCTL1 REG16((BKP) + 0x38U) /*!< tamper pin control register 1 */ + +/* bits definitions */ +/* BKP_DATA */ +#define BKP_DATA BITS(0,15) /*!< backup data */ + +/* BKP_OCTL */ +#define BKP_OCTL_RCCV BITS(0,6) /*!< RTC clock calibration value */ +#define BKP_OCTL_COEN BIT(7) /*!< RTC clock calibration output enable */ +#define BKP_OCTL_ASOEN BIT(8) /*!< RTC alarm or second signal output enable */ +#define BKP_OCTL_ROSEL BIT(9) /*!< RTC output selection */ +#define BKP_OCTL_CCOSEL BIT(14) /*!< RTC clock output selection */ +#define BKP_OCTL_CALDIR BIT(15) /*!< RTC clock calibration direction */ + +/* BKP_TPCTL0 */ +#define BKP_TPCTL0_TPEN0 BIT(0) /*!< tamper0 detection enable */ +#define BKP_TPCTL0_TPAL0 BIT(1) /*!< tamper0 pin active level */ + +/* BKP_TPCS */ +#define BKP_TPCS_TER0 BIT(0) /*!< tamper0 event reset */ +#define BKP_TPCS_TIR0 BIT(1) /*!< tamper0 interrupt reset */ +#define BKP_TPCS_TPIE0 BIT(2) /*!< tamper0 interrupt enable */ +#define BKP_TPCS_TER1 BIT(5) /*!< tamper1 event reset */ +#define BKP_TPCS_TIR1 BIT(6) /*!< tamper1 interrupt reset */ +#define BKP_TPCS_TPIE1 BIT(7) /*!< tamper1 interrupt enable */ +#define BKP_TPCS_TEF0 BIT(8) /*!< tamper0 event flag */ +#define BKP_TPCS_TIF0 BIT(9) /*!< tamper0 interrupt flag */ +#define BKP_TPCS_TEF1 BIT(14) /*!< tamper1 event flag */ +#define BKP_TPCS_TIF1 BIT(15) /*!< tamper1 interrupt flag */ + +/* BKP_TPCTL1 */ +#define BKP_TPCTL1_TPEN1 BIT(8) /*!< tamper1 detection enable */ +#define BKP_TPCTL1_TPAL1 BIT(9) /*!< tamper1 pin active level */ +#define BKP_TPCTL1_TPM2 BIT(14) /*!< the second waveform detection enable */ +#define BKP_TPCTL1_TPM1 BIT(15) /*!< the first waveform detection enable */ + +/* constants definitions */ +/* tamperx definitions */ +typedef enum +{ + TAMPER_0 = 0, /*!< BKP tamper0 */ + TAMPER_1, /*!< BKP tamper1 */ +}bkp_tamper_enum; + +/* BKP data register number */ +typedef enum +{ + BKP_DATA_0 = 1, /*!< BKP data register 0 */ + BKP_DATA_1, /*!< BKP data register 1 */ + BKP_DATA_2, /*!< BKP data register 2 */ + BKP_DATA_3, /*!< BKP data register 3 */ + BKP_DATA_4, /*!< BKP data register 4 */ + BKP_DATA_5, /*!< BKP data register 5 */ + BKP_DATA_6, /*!< BKP data register 6 */ + BKP_DATA_7, /*!< BKP data register 7 */ + BKP_DATA_8, /*!< BKP data register 8 */ + BKP_DATA_9, /*!< BKP data register 9 */ + BKP_DATA_10, /*!< BKP data register 10 */ + BKP_DATA_11, /*!< BKP data register 11 */ + BKP_DATA_12, /*!< BKP data register 12 */ + BKP_DATA_13, /*!< BKP data register 13 */ + BKP_DATA_14, /*!< BKP data register 14 */ + BKP_DATA_15, /*!< BKP data register 15 */ + BKP_DATA_16, /*!< BKP data register 16 */ + BKP_DATA_17, /*!< BKP data register 17 */ + BKP_DATA_18, /*!< BKP data register 18 */ + BKP_DATA_19, /*!< BKP data register 19 */ + BKP_DATA_20, /*!< BKP data register 20 */ + BKP_DATA_21, /*!< BKP data register 21 */ + BKP_DATA_22, /*!< BKP data register 22 */ + BKP_DATA_23, /*!< BKP data register 23 */ + BKP_DATA_24, /*!< BKP data register 24 */ + BKP_DATA_25, /*!< BKP data register 25 */ + BKP_DATA_26, /*!< BKP data register 26 */ + BKP_DATA_27, /*!< BKP data register 27 */ + BKP_DATA_28, /*!< BKP data register 28 */ + BKP_DATA_29, /*!< BKP data register 29 */ + BKP_DATA_30, /*!< BKP data register 30 */ + BKP_DATA_31, /*!< BKP data register 31 */ + BKP_DATA_32, /*!< BKP data register 32 */ + BKP_DATA_33, /*!< BKP data register 33 */ + BKP_DATA_34, /*!< BKP data register 34 */ + BKP_DATA_35, /*!< BKP data register 35 */ + BKP_DATA_36, /*!< BKP data register 36 */ + BKP_DATA_37, /*!< BKP data register 37 */ + BKP_DATA_38, /*!< BKP data register 38 */ + BKP_DATA_39, /*!< BKP data register 39 */ + BKP_DATA_40, /*!< BKP data register 40 */ + BKP_DATA_41, /*!< BKP data register 41 */ +}bkp_data_register_enum; + +/* BKP register */ +#define BKP_DATA0_9(number) REG16((BKP) + 0x04U + (number) * 0x04U) +#define BKP_DATA10_41(number) REG16((BKP) + 0x40U + ((number)-10U) * 0x04U) + +/* get data of BKP data register */ +#define BKP_DATA_GET(regval) GET_BITS((uint32_t)(regval), 0, 15) + +/* RTC clock calibration value */ +#define OCTL_RCCV(regval) (BITS(0,6) & ((uint32_t)(regval) << 0)) + +/* RTC output selection */ +#define RTC_OUTPUT_ALARM_PULSE ((uint16_t)0x0000U) /*!< RTC alarm pulse is selected as the RTC output */ +#define RTC_OUTPUT_SECOND_PULSE ((uint16_t)0x0200U) /*!< RTC second pulse is selected as the RTC output */ + +/* RTC clock output selection */ +#define RTC_CLOCK_DIV64 ((uint16_t)0x0000U) /*!< RTC clock div 64 */ +#define RTC_CLOCK_DIV1 ((uint16_t)0x4000U) /*!< RTC clock div 1 */ + +/* RTC clock calibration direction */ +#define RTC_CLOCK_SLOWED_DOWN ((uint16_t)0x0000U) /*!< RTC clock slow down */ +#define RTC_CLOCK_SPEED_UP ((uint16_t)0x8000U) /*!< RTC clock speed up */ + +/* tamper pin active level */ +#define TAMPER_PIN_ACTIVE_HIGH ((uint16_t)0x0000U) /*!< the tamper pin is active high */ +#define TAMPER_PIN_ACTIVE_LOW ((uint16_t)0x0002U) /*!< the tamper pin is active low */ + +/* tamper flag */ +#define BKP_FLAG_TAMPER0 BKP_TPCS_TEF0 /*!< tamper0 event flag */ +#define BKP_FLAG_TAMPER1_WAVEDETECT BKP_TPCS_TEF1 /*!< tamper1/waveform detect event flag */ + +/* tamper interrupt flag */ +#define BKP_INT_FLAG_TAMPER0 BKP_TPCS_TIF0 /*!< tamper0 interrupt flag */ +#define BKP_INT_FLAG_TAMPER1_WAVEDETECT BKP_TPCS_TIF1 /*!< tamper1/waveform detect interrupt flag */ + +/* waveform detection mode */ +#define BKP_WAVEFORM_DETECT_1 BKP_TPCTL1_TPM1 /*!< the first waveform detection */ +#define BKP_WAVEFORM_DETECT_2 BKP_TPCTL1_TPM2 /*!< the second waveform detection */ + +/* function declarations */ +/* initialization functions */ +/* reset BKP registers */ +void bkp_deinit(void); +/* write BKP data register */ +void bkp_data_write(bkp_data_register_enum register_number, uint16_t data); +/* read BKP data register */ +uint16_t bkp_data_read(bkp_data_register_enum register_number); + +/* function configuration */ +/* RTC related functions */ +/* enable RTC clock calibration output */ +void bkp_rtc_calibration_output_enable(void); +/* disable RTC clock calibration output */ +void bkp_rtc_calibration_output_disable(void); +/* enable RTC alarm or second signal output */ +void bkp_rtc_signal_output_enable(void); +/* disable RTC alarm or second signal output */ +void bkp_rtc_signal_output_disable(void); +/* select RTC output */ +void bkp_rtc_output_select(uint16_t outputsel); +/* RTC clock output selection */ +void bkp_rtc_clock_output_select(uint16_t clocksel); +/* RTC clock calibration direction */ +void bkp_rtc_clock_calibration_direction(uint16_t direction); +/* set RTC clock calibration value */ +void bkp_rtc_calibration_value_set(uint8_t value); + +/* tamper pin related functions */ +/* enable tamper pin detection */ +void bkp_tamper_detection_enable(bkp_tamper_enum tamperx); +/* disable tamper pin detection */ +void bkp_tamper_detection_disable(bkp_tamper_enum tamperx); +/* set tamper pin active level */ +void bkp_tamper_active_level_set(bkp_tamper_enum tamperx, uint16_t level); + +/* interrupt & flag functions */ +/* enable tamper pin interrupt */ +void bkp_tamper_interrupt_enable(bkp_tamper_enum tamperx); +/* disable tamper pin interrupt */ +void bkp_tamper_interrupt_disable(bkp_tamper_enum tamperx); +/* waveform detect configure */ +void bkp_waveform_detect_enable(uint16_t waveform_detect_mode, ControlStatus newvalue); +/* get BKP flag state */ +FlagStatus bkp_flag_get(uint16_t flag); +/* clear BKP flag state */ +void bkp_flag_clear(uint16_t flag); +/* get BKP interrupt flag state */ +FlagStatus bkp_interrupt_flag_get(uint16_t flag); +/* clear BKP interrupt flag state */ +void bkp_interrupt_flag_clear(uint16_t flag); + +#endif /* GD32F20X_BKP_H */ diff --git a/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_standard_peripheral/Include/gd32f20x_can.h b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_standard_peripheral/Include/gd32f20x_can.h new file mode 100644 index 0000000000..bab172849a --- /dev/null +++ b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_standard_peripheral/Include/gd32f20x_can.h @@ -0,0 +1,758 @@ +/*! + \file gd32f20x_can.h + \brief definitions for the CAN + + \version 2015-07-15, V1.0.0, firmware for GD32F20x + \version 2017-06-05, V2.0.0, firmware for GD32F20x + \version 2018-10-31, V2.1.0, firmware for GD32F20x + \version 2020-09-30, V2.2.0, firmware for GD32F20x + \version 2019-11-27, V2.1.1, firmware for GD32F20x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef GD32F20X_CAN_H +#define GD32F20X_CAN_H + +#include "gd32f20x.h" + +/* CAN definitions */ +#define CAN0 CAN_BASE /*!< CAN0 base address */ +#define CAN1 (CAN0 + 0x00000400U) /*!< CAN1 base address */ + +/* registers definitions */ +#define CAN_CTL(canx) REG32((canx) + 0x00U) /*!< CAN control register */ +#define CAN_STAT(canx) REG32((canx) + 0x04U) /*!< CAN status register */ +#define CAN_TSTAT(canx) REG32((canx) + 0x08U) /*!< CAN transmit status register*/ +#define CAN_RFIFO0(canx) REG32((canx) + 0x0CU) /*!< CAN receive FIFO0 register */ +#define CAN_RFIFO1(canx) REG32((canx) + 0x10U) /*!< CAN receive FIFO1 register */ +#define CAN_INTEN(canx) REG32((canx) + 0x14U) /*!< CAN interrupt enable register */ +#define CAN_ERR(canx) REG32((canx) + 0x18U) /*!< CAN error register */ +#define CAN_BT(canx) REG32((canx) + 0x1CU) /*!< CAN bit timing register */ +#define CAN_TMI0(canx) REG32((canx) + 0x180U) /*!< CAN transmit mailbox0 identifier register */ +#define CAN_TMP0(canx) REG32((canx) + 0x184U) /*!< CAN transmit mailbox0 property register */ +#define CAN_TMDATA00(canx) REG32((canx) + 0x188U) /*!< CAN transmit mailbox0 data0 register */ +#define CAN_TMDATA10(canx) REG32((canx) + 0x18CU) /*!< CAN transmit mailbox0 data1 register */ +#define CAN_TMI1(canx) REG32((canx) + 0x190U) /*!< CAN transmit mailbox1 identifier register */ +#define CAN_TMP1(canx) REG32((canx) + 0x194U) /*!< CAN transmit mailbox1 property register */ +#define CAN_TMDATA01(canx) REG32((canx) + 0x198U) /*!< CAN transmit mailbox1 data0 register */ +#define CAN_TMDATA11(canx) REG32((canx) + 0x19CU) /*!< CAN transmit mailbox1 data1 register */ +#define CAN_TMI2(canx) REG32((canx) + 0x1A0U) /*!< CAN transmit mailbox2 identifier register */ +#define CAN_TMP2(canx) REG32((canx) + 0x1A4U) /*!< CAN transmit mailbox2 property register */ +#define CAN_TMDATA02(canx) REG32((canx) + 0x1A8U) /*!< CAN transmit mailbox2 data0 register */ +#define CAN_TMDATA12(canx) REG32((canx) + 0x1ACU) /*!< CAN transmit mailbox2 data1 register */ +#define CAN_RFIFOMI0(canx) REG32((canx) + 0x1B0U) /*!< CAN receive FIFO0 mailbox identifier register */ +#define CAN_RFIFOMP0(canx) REG32((canx) + 0x1B4U) /*!< CAN receive FIFO0 mailbox property register */ +#define CAN_RFIFOMDATA00(canx) REG32((canx) + 0x1B8U) /*!< CAN receive FIFO0 mailbox data0 register */ +#define CAN_RFIFOMDATA10(canx) REG32((canx) + 0x1BCU) /*!< CAN receive FIFO0 mailbox data1 register */ +#define CAN_RFIFOMI1(canx) REG32((canx) + 0x1C0U) /*!< CAN receive FIFO1 mailbox identifier register */ +#define CAN_RFIFOMP1(canx) REG32((canx) + 0x1C4U) /*!< CAN receive FIFO1 mailbox property register */ +#define CAN_RFIFOMDATA01(canx) REG32((canx) + 0x1C8U) /*!< CAN receive FIFO1 mailbox data0 register */ +#define CAN_RFIFOMDATA11(canx) REG32((canx) + 0x1CCU) /*!< CAN receive FIFO1 mailbox data1 register */ +#define CAN_FCTL(canx) REG32((canx) + 0x200U) /*!< CAN filter control register */ +#define CAN_FMCFG(canx) REG32((canx) + 0x204U) /*!< CAN filter mode register */ +#define CAN_FSCFG(canx) REG32((canx) + 0x20CU) /*!< CAN filter scale register */ +#define CAN_FAFIFO(canx) REG32((canx) + 0x214U) /*!< CAN filter associated FIFO register */ +#define CAN_FW(canx) REG32((canx) + 0x21CU) /*!< CAN filter working register */ +#define CAN_F0DATA0(canx) REG32((canx) + 0x240U) /*!< CAN filter 0 data 0 register */ +#define CAN_F1DATA0(canx) REG32((canx) + 0x248U) /*!< CAN filter 1 data 0 register */ +#define CAN_F2DATA0(canx) REG32((canx) + 0x250U) /*!< CAN filter 2 data 0 register */ +#define CAN_F3DATA0(canx) REG32((canx) + 0x258U) /*!< CAN filter 3 data 0 register */ +#define CAN_F4DATA0(canx) REG32((canx) + 0x260U) /*!< CAN filter 4 data 0 register */ +#define CAN_F5DATA0(canx) REG32((canx) + 0x268U) /*!< CAN filter 5 data 0 register */ +#define CAN_F6DATA0(canx) REG32((canx) + 0x270U) /*!< CAN filter 6 data 0 register */ +#define CAN_F7DATA0(canx) REG32((canx) + 0x278U) /*!< CAN filter 7 data 0 register */ +#define CAN_F8DATA0(canx) REG32((canx) + 0x280U) /*!< CAN filter 8 data 0 register */ +#define CAN_F9DATA0(canx) REG32((canx) + 0x288U) /*!< CAN filter 9 data 0 register */ +#define CAN_F10DATA0(canx) REG32((canx) + 0x290U) /*!< CAN filter 10 data 0 register */ +#define CAN_F11DATA0(canx) REG32((canx) + 0x298U) /*!< CAN filter 11 data 0 register */ +#define CAN_F12DATA0(canx) REG32((canx) + 0x2A0U) /*!< CAN filter 12 data 0 register */ +#define CAN_F13DATA0(canx) REG32((canx) + 0x2A8U) /*!< CAN filter 13 data 0 register */ +#define CAN_F14DATA0(canx) REG32((canx) + 0x2B0U) /*!< CAN filter 14 data 0 register */ +#define CAN_F15DATA0(canx) REG32((canx) + 0x2B8U) /*!< CAN filter 15 data 0 register */ +#define CAN_F16DATA0(canx) REG32((canx) + 0x2C0U) /*!< CAN filter 16 data 0 register */ +#define CAN_F17DATA0(canx) REG32((canx) + 0x2C8U) /*!< CAN filter 17 data 0 register */ +#define CAN_F18DATA0(canx) REG32((canx) + 0x2D0U) /*!< CAN filter 18 data 0 register */ +#define CAN_F19DATA0(canx) REG32((canx) + 0x2D8U) /*!< CAN filter 19 data 0 register */ +#define CAN_F20DATA0(canx) REG32((canx) + 0x2E0U) /*!< CAN filter 20 data 0 register */ +#define CAN_F21DATA0(canx) REG32((canx) + 0x2E8U) /*!< CAN filter 21 data 0 register */ +#define CAN_F22DATA0(canx) REG32((canx) + 0x2F0U) /*!< CAN filter 22 data 0 register */ +#define CAN_F23DATA0(canx) REG32((canx) + 0x3F8U) /*!< CAN filter 23 data 0 register */ +#define CAN_F24DATA0(canx) REG32((canx) + 0x300U) /*!< CAN filter 24 data 0 register */ +#define CAN_F25DATA0(canx) REG32((canx) + 0x308U) /*!< CAN filter 25 data 0 register */ +#define CAN_F26DATA0(canx) REG32((canx) + 0x310U) /*!< CAN filter 26 data 0 register */ +#define CAN_F27DATA0(canx) REG32((canx) + 0x318U) /*!< CAN filter 27 data 0 register */ +#define CAN_F0DATA1(canx) REG32((canx) + 0x244U) /*!< CAN filter 0 data 1 register */ +#define CAN_F1DATA1(canx) REG32((canx) + 0x24CU) /*!< CAN filter 1 data 1 register */ +#define CAN_F2DATA1(canx) REG32((canx) + 0x254U) /*!< CAN filter 2 data 1 register */ +#define CAN_F3DATA1(canx) REG32((canx) + 0x25CU) /*!< CAN filter 3 data 1 register */ +#define CAN_F4DATA1(canx) REG32((canx) + 0x264U) /*!< CAN filter 4 data 1 register */ +#define CAN_F5DATA1(canx) REG32((canx) + 0x26CU) /*!< CAN filter 5 data 1 register */ +#define CAN_F6DATA1(canx) REG32((canx) + 0x274U) /*!< CAN filter 6 data 1 register */ +#define CAN_F7DATA1(canx) REG32((canx) + 0x27CU) /*!< CAN filter 7 data 1 register */ +#define CAN_F8DATA1(canx) REG32((canx) + 0x284U) /*!< CAN filter 8 data 1 register */ +#define CAN_F9DATA1(canx) REG32((canx) + 0x28CU) /*!< CAN filter 9 data 1 register */ +#define CAN_F10DATA1(canx) REG32((canx) + 0x294U) /*!< CAN filter 10 data 1 register */ +#define CAN_F11DATA1(canx) REG32((canx) + 0x29CU) /*!< CAN filter 11 data 1 register */ +#define CAN_F12DATA1(canx) REG32((canx) + 0x2A4U) /*!< CAN filter 12 data 1 register */ +#define CAN_F13DATA1(canx) REG32((canx) + 0x2ACU) /*!< CAN filter 13 data 1 register */ +#define CAN_F14DATA1(canx) REG32((canx) + 0x2B4U) /*!< CAN filter 14 data 1 register */ +#define CAN_F15DATA1(canx) REG32((canx) + 0x2BCU) /*!< CAN filter 15 data 1 register */ +#define CAN_F16DATA1(canx) REG32((canx) + 0x2C4U) /*!< CAN filter 16 data 1 register */ +#define CAN_F17DATA1(canx) REG32((canx) + 0x24CU) /*!< CAN filter 17 data 1 register */ +#define CAN_F18DATA1(canx) REG32((canx) + 0x2D4U) /*!< CAN filter 18 data 1 register */ +#define CAN_F19DATA1(canx) REG32((canx) + 0x2DCU) /*!< CAN filter 19 data 1 register */ +#define CAN_F20DATA1(canx) REG32((canx) + 0x2E4U) /*!< CAN filter 20 data 1 register */ +#define CAN_F21DATA1(canx) REG32((canx) + 0x2ECU) /*!< CAN filter 21 data 1 register */ +#define CAN_F22DATA1(canx) REG32((canx) + 0x2F4U) /*!< CAN filter 22 data 1 register */ +#define CAN_F23DATA1(canx) REG32((canx) + 0x2FCU) /*!< CAN filter 23 data 1 register */ +#define CAN_F24DATA1(canx) REG32((canx) + 0x304U) /*!< CAN filter 24 data 1 register */ +#define CAN_F25DATA1(canx) REG32((canx) + 0x30CU) /*!< CAN filter 25 data 1 register */ +#define CAN_F26DATA1(canx) REG32((canx) + 0x314U) /*!< CAN filter 26 data 1 register */ +#define CAN_F27DATA1(canx) REG32((canx) + 0x31CU) /*!< CAN filter 27 data 1 register */ + +/* CAN transmit mailbox bank */ +#define CAN_TMI(canx, bank) REG32((canx) + 0x180U + ((bank) * 0x10U)) /*!< CAN transmit mailbox identifier register */ +#define CAN_TMP(canx, bank) REG32((canx) + 0x184U + ((bank) * 0x10U)) /*!< CAN transmit mailbox property register */ +#define CAN_TMDATA0(canx, bank) REG32((canx) + 0x188U + ((bank) * 0x10U)) /*!< CAN transmit mailbox data0 register */ +#define CAN_TMDATA1(canx, bank) REG32((canx) + 0x18CU + ((bank) * 0x10U)) /*!< CAN transmit mailbox data1 register */ + +/* CAN filter bank */ +#define CAN_FDATA0(canx, bank) REG32((canx) + 0x240U + ((bank) * 0x8U) + 0x0U) /*!< CAN filter data 0 register */ +#define CAN_FDATA1(canx, bank) REG32((canx) + 0x240U + ((bank) * 0x8U) + 0x4U) /*!< CAN filter data 1 register */ + +/* CAN receive fifo mailbox bank */ +#define CAN_RFIFOMI(canx, bank) REG32((canx) + 0x1B0U + ((bank) * 0x10U)) /*!< CAN receive FIFO mailbox identifier register */ +#define CAN_RFIFOMP(canx, bank) REG32((canx) + 0x1B4U + ((bank) * 0x10U)) /*!< CAN receive FIFO mailbox property register */ +#define CAN_RFIFOMDATA0(canx, bank) REG32((canx) + 0x1B8U + ((bank) * 0x10U)) /*!< CAN receive FIFO mailbox data0 register */ +#define CAN_RFIFOMDATA1(canx, bank) REG32((canx) + 0x1BCU + ((bank) * 0x10U)) /*!< CAN receive FIFO mailbox data1 register */ + +/* bits definitions */ +/* CAN_CTL */ +#define CAN_CTL_IWMOD BIT(0) /*!< initial working mode */ +#define CAN_CTL_SLPWMOD BIT(1) /*!< sleep working mode */ +#define CAN_CTL_TFO BIT(2) /*!< transmit FIFO order */ +#define CAN_CTL_RFOD BIT(3) /*!< receive FIFO overwrite disable */ +#define CAN_CTL_ARD BIT(4) /*!< automatic retransmission disable */ +#define CAN_CTL_AWU BIT(5) /*!< automatic wakeup */ +#define CAN_CTL_ABOR BIT(6) /*!< automatic bus-off recovery */ +#define CAN_CTL_TTC BIT(7) /*!< time triggered communication */ +#define CAN_CTL_SWRST BIT(15) /*!< CAN software reset */ +#define CAN_CTL_DFZ BIT(16) /*!< CAN debug freeze */ + +/* CAN_STAT */ +#define CAN_STAT_IWS BIT(0) /*!< initial working state */ +#define CAN_STAT_SLPWS BIT(1) /*!< sleep working state */ +#define CAN_STAT_ERRIF BIT(2) /*!< error interrupt flag*/ +#define CAN_STAT_WUIF BIT(3) /*!< status change interrupt flag of wakeup from sleep working mode */ +#define CAN_STAT_SLPIF BIT(4) /*!< status change interrupt flag of sleep working mode entering */ +#define CAN_STAT_TS BIT(8) /*!< transmitting state */ +#define CAN_STAT_RS BIT(9) /*!< receiving state */ +#define CAN_STAT_LASTRX BIT(10) /*!< last sample value of rx pin */ +#define CAN_STAT_RXL BIT(11) /*!< CAN rx signal */ + +/* CAN_TSTAT */ +#define CAN_TSTAT_MTF0 BIT(0) /*!< mailbox0 transmit finished */ +#define CAN_TSTAT_MTFNERR0 BIT(1) /*!< mailbox0 transmit finished and no error */ +#define CAN_TSTAT_MAL0 BIT(2) /*!< mailbox0 arbitration lost */ +#define CAN_TSTAT_MTE0 BIT(3) /*!< mailbox0 transmit error */ +#define CAN_TSTAT_MST0 BIT(7) /*!< mailbox0 stop transmitting */ +#define CAN_TSTAT_MTF1 BIT(8) /*!< mailbox1 transmit finished */ +#define CAN_TSTAT_MTFNERR1 BIT(9) /*!< mailbox1 transmit finished and no error */ +#define CAN_TSTAT_MAL1 BIT(10) /*!< mailbox1 arbitration lost */ +#define CAN_TSTAT_MTE1 BIT(11) /*!< mailbox1 transmit error */ +#define CAN_TSTAT_MST1 BIT(15) /*!< mailbox1 stop transmitting */ +#define CAN_TSTAT_MTF2 BIT(16) /*!< mailbox2 transmit finished */ +#define CAN_TSTAT_MTFNERR2 BIT(17) /*!< mailbox2 transmit finished and no error */ +#define CAN_TSTAT_MAL2 BIT(18) /*!< mailbox2 arbitration lost */ +#define CAN_TSTAT_MTE2 BIT(19) /*!< mailbox2 transmit error */ +#define CAN_TSTAT_MST2 BIT(23) /*!< mailbox2 stop transmitting */ +#define CAN_TSTAT_NUM BITS(24,25) /*!< mailbox number */ +#define CAN_TSTAT_TME0 BIT(26) /*!< transmit mailbox0 empty */ +#define CAN_TSTAT_TME1 BIT(27) /*!< transmit mailbox1 empty */ +#define CAN_TSTAT_TME2 BIT(28) /*!< transmit mailbox2 empty */ +#define CAN_TSTAT_TMLS0 BIT(29) /*!< last sending priority flag for mailbox0 */ +#define CAN_TSTAT_TMLS1 BIT(30) /*!< last sending priority flag for mailbox1 */ +#define CAN_TSTAT_TMLS2 BIT(31) /*!< last sending priority flag for mailbox2 */ + +/* CAN_RFIFO0 */ +#define CAN_RFIFO0_RFL0 BITS(0,1) /*!< receive FIFO0 length */ +#define CAN_RFIFO0_RFF0 BIT(3) /*!< receive FIFO0 full */ +#define CAN_RFIFO0_RFO0 BIT(4) /*!< receive FIFO0 overfull */ +#define CAN_RFIFO0_RFD0 BIT(5) /*!< receive FIFO0 dequeue */ + +/* CAN_RFIFO1 */ +#define CAN_RFIFO1_RFL1 BITS(0,1) /*!< receive FIFO1 length */ +#define CAN_RFIFO1_RFF1 BIT(3) /*!< receive FIFO1 full */ +#define CAN_RFIFO1_RFO1 BIT(4) /*!< receive FIFO1 overfull */ +#define CAN_RFIFO1_RFD1 BIT(5) /*!< receive FIFO1 dequeue */ + +/* CAN_INTEN */ +#define CAN_INTEN_TMEIE BIT(0) /*!< transmit mailbox empty interrupt enable */ +#define CAN_INTEN_RFNEIE0 BIT(1) /*!< receive FIFO0 not empty interrupt enable */ +#define CAN_INTEN_RFFIE0 BIT(2) /*!< receive FIFO0 full interrupt enable */ +#define CAN_INTEN_RFOIE0 BIT(3) /*!< receive FIFO0 overfull interrupt enable */ +#define CAN_INTEN_RFNEIE1 BIT(4) /*!< receive FIFO1 not empty interrupt enable */ +#define CAN_INTEN_RFFIE1 BIT(5) /*!< receive FIFO1 full interrupt enable */ +#define CAN_INTEN_RFOIE1 BIT(6) /*!< receive FIFO1 overfull interrupt enable */ +#define CAN_INTEN_WERRIE BIT(8) /*!< warning error interrupt enable */ +#define CAN_INTEN_PERRIE BIT(9) /*!< passive error interrupt enable */ +#define CAN_INTEN_BOIE BIT(10) /*!< bus-off interrupt enable */ +#define CAN_INTEN_ERRNIE BIT(11) /*!< error number interrupt enable */ +#define CAN_INTEN_ERRIE BIT(15) /*!< error interrupt enable */ +#define CAN_INTEN_WIE BIT(16) /*!< wakeup interrupt enable */ +#define CAN_INTEN_SLPWIE BIT(17) /*!< sleep working interrupt enable */ + +/* CAN_ERR */ +#define CAN_ERR_WERR BIT(0) /*!< warning error */ +#define CAN_ERR_PERR BIT(1) /*!< passive error */ +#define CAN_ERR_BOERR BIT(2) /*!< bus-off error */ +#define CAN_ERR_ERRN BITS(4,6) /*!< error number */ +#define CAN_ERR_TECNT BITS(16,23) /*!< transmit error count */ +#define CAN_ERR_RECNT BITS(24,31) /*!< receive error count */ + +/* CAN_BT */ +#define CAN_BT_BAUDPSC BITS(0,9) /*!< baudrate prescaler */ +#define CAN_BT_BS1 BITS(16,19) /*!< bit segment 1 */ +#define CAN_BT_BS2 BITS(20,22) /*!< bit segment 2 */ +#define CAN_BT_SJW BITS(24,25) /*!< resynchronization jump width */ +#define CAN_BT_LCMOD BIT(30) /*!< loopback communication mode */ +#define CAN_BT_SCMOD BIT(31) /*!< silent communication mode */ + +/* CAN_TMIx */ +#define CAN_TMI_TEN BIT(0) /*!< transmit enable */ +#define CAN_TMI_FT BIT(1) /*!< frame type */ +#define CAN_TMI_FF BIT(2) /*!< frame format */ +#define CAN_TMI_EFID BITS(3,31) /*!< the frame identifier */ +#define CAN_TMI_SFID BITS(21,31) /*!< the frame identifier */ + +/* CAN_TMPx */ +#define CAN_TMP_DLENC BITS(0,3) /*!< data length code */ +#define CAN_TMP_TSEN BIT(8) /*!< time stamp enable */ +#define CAN_TMP_TS BITS(16,31) /*!< time stamp */ + +/* CAN_TMDATA0x */ +#define CAN_TMDATA0_DB0 BITS(0,7) /*!< transmit data byte 0 */ +#define CAN_TMDATA0_DB1 BITS(8,15) /*!< transmit data byte 1 */ +#define CAN_TMDATA0_DB2 BITS(16,23) /*!< transmit data byte 2 */ +#define CAN_TMDATA0_DB3 BITS(24,31) /*!< transmit data byte 3 */ + +/* CAN_TMDATA1x */ +#define CAN_TMDATA1_DB4 BITS(0,7) /*!< transmit data byte 4 */ +#define CAN_TMDATA1_DB5 BITS(8,15) /*!< transmit data byte 5 */ +#define CAN_TMDATA1_DB6 BITS(16,23) /*!< transmit data byte 6 */ +#define CAN_TMDATA1_DB7 BITS(24,31) /*!< transmit data byte 7 */ + +/* CAN_RFIFOMIx */ +#define CAN_RFIFOMI_FT BIT(1) /*!< frame type */ +#define CAN_RFIFOMI_FF BIT(2) /*!< frame format */ +#define CAN_RFIFOMI_EFID BITS(3,31) /*!< the frame identifier */ +#define CAN_RFIFOMI_SFID BITS(21,31) /*!< the frame identifier */ + +/* CAN_RFIFOMPx */ +#define CAN_RFIFOMP_DLENC BITS(0,3) /*!< receive data length code */ +#define CAN_RFIFOMP_FI BITS(8,15) /*!< filter index */ +#define CAN_RFIFOMP_TS BITS(16,31) /*!< time stamp */ + +/* CAN_RFIFOMDATA0x */ +#define CAN_RFIFOMDATA0_DB0 BITS(0,7) /*!< receive data byte 0 */ +#define CAN_RFIFOMDATA0_DB1 BITS(8,15) /*!< receive data byte 1 */ +#define CAN_RFIFOMDATA0_DB2 BITS(16,23) /*!< receive data byte 2 */ +#define CAN_RFIFOMDATA0_DB3 BITS(24,31) /*!< receive data byte 3 */ + +/* CAN_RFIFOMDATA1x */ +#define CAN_RFIFOMDATA1_DB4 BITS(0,7) /*!< receive data byte 4 */ +#define CAN_RFIFOMDATA1_DB5 BITS(8,15) /*!< receive data byte 5 */ +#define CAN_RFIFOMDATA1_DB6 BITS(16,23) /*!< receive data byte 6 */ +#define CAN_RFIFOMDATA1_DB7 BITS(24,31) /*!< receive data byte 7 */ + +/* CAN_FCTL */ +#define CAN_FCTL_FLD BIT(0) /*!< filter lock disable */ +#define CAN_FCTL_HBC1F BITS(8,13) /*!< header bank of CAN1 filter */ + +/* CAN_FMCFG */ +#define CAN_FMCFG_FMOD(regval) BIT(regval) /*!< filter mode, list or mask*/ + +/* CAN_FSCFG */ +#define CAN_FSCFG_FS(regval) BIT(regval) /*!< filter scale, 32 bits or 16 bits*/ + +/* CAN_FAFIFO */ +#define CAN_FAFIFOR_FAF(regval) BIT(regval) /*!< filter associated with FIFO */ + +/* CAN_FW */ +#define CAN_FW_FW(regval) BIT(regval) /*!< filter working */ + +/* CAN_FxDATAy */ +#define CAN_FDATA_FD(regval) BIT(regval) /*!< filter data */ + +/* constants definitions */ +/* define the CAN bit position and its register index offset */ +#define CAN_REGIDX_BIT(regidx, bitpos) (((uint32_t)(regidx) << 6) | (uint32_t)(bitpos)) +#define CAN_REG_VAL(canx, offset) (REG32((canx) + ((uint32_t)(offset) >> 6))) +#define CAN_BIT_POS(val) ((uint32_t)(val) & 0x1FU) + +#define CAN_REGIDX_BITS(regidx, bitpos0, bitpos1) (((uint32_t)(regidx) << 12) | ((uint32_t)(bitpos0) << 6) | (uint32_t)(bitpos1)) +#define CAN_REG_VALS(canx, offset) (REG32((canx) + ((uint32_t)(offset) >> 12))) +#define CAN_BIT_POS0(val) (((uint32_t)(val) >> 6) & 0x1FU) +#define CAN_BIT_POS1(val) ((uint32_t)(val) & 0x1FU) + +/* register offset */ +#define STAT_REG_OFFSET ((uint8_t)0x04U) /*!< STAT register offset */ +#define TSTAT_REG_OFFSET ((uint8_t)0x08U) /*!< TSTAT register offset */ +#define RFIFO0_REG_OFFSET ((uint8_t)0x0CU) /*!< RFIFO0 register offset */ +#define RFIFO1_REG_OFFSET ((uint8_t)0x10U) /*!< RFIFO1 register offset */ +#define ERR_REG_OFFSET ((uint8_t)0x18U) /*!< ERR register offset */ + +/* CAN flags */ +typedef enum +{ + /* flags in STAT register */ + CAN_FLAG_RXL = CAN_REGIDX_BIT(STAT_REG_OFFSET, 11U), /*!< RX level */ + CAN_FLAG_LASTRX = CAN_REGIDX_BIT(STAT_REG_OFFSET, 10U), /*!< last sample value of RX pin */ + CAN_FLAG_RS = CAN_REGIDX_BIT(STAT_REG_OFFSET, 9U), /*!< receiving state */ + CAN_FLAG_TS = CAN_REGIDX_BIT(STAT_REG_OFFSET, 8U), /*!< transmitting state */ + CAN_FLAG_SLPIF = CAN_REGIDX_BIT(STAT_REG_OFFSET, 4U), /*!< status change flag of entering sleep working mode */ + CAN_FLAG_WUIF = CAN_REGIDX_BIT(STAT_REG_OFFSET, 3U), /*!< status change flag of wakeup from sleep working mode */ + CAN_FLAG_ERRIF = CAN_REGIDX_BIT(STAT_REG_OFFSET, 2U), /*!< error flag */ + CAN_FLAG_SLPWS = CAN_REGIDX_BIT(STAT_REG_OFFSET, 1U), /*!< sleep working state */ + CAN_FLAG_IWS = CAN_REGIDX_BIT(STAT_REG_OFFSET, 0U), /*!< initial working state */ + /* flags in TSTAT register */ + CAN_FLAG_TMLS2 = CAN_REGIDX_BIT(TSTAT_REG_OFFSET, 31U), /*!< transmit mailbox 2 last sending in Tx FIFO */ + CAN_FLAG_TMLS1 = CAN_REGIDX_BIT(TSTAT_REG_OFFSET, 30U), /*!< transmit mailbox 1 last sending in Tx FIFO */ + CAN_FLAG_TMLS0 = CAN_REGIDX_BIT(TSTAT_REG_OFFSET, 29U), /*!< transmit mailbox 0 last sending in Tx FIFO */ + CAN_FLAG_TME2 = CAN_REGIDX_BIT(TSTAT_REG_OFFSET, 28U), /*!< transmit mailbox 2 empty */ + CAN_FLAG_TME1 = CAN_REGIDX_BIT(TSTAT_REG_OFFSET, 27U), /*!< transmit mailbox 1 empty */ + CAN_FLAG_TME0 = CAN_REGIDX_BIT(TSTAT_REG_OFFSET, 26U), /*!< transmit mailbox 0 empty */ + CAN_FLAG_MTE2 = CAN_REGIDX_BIT(TSTAT_REG_OFFSET, 19U), /*!< mailbox 2 transmit error */ + CAN_FLAG_MTE1 = CAN_REGIDX_BIT(TSTAT_REG_OFFSET, 11U), /*!< mailbox 1 transmit error */ + CAN_FLAG_MTE0 = CAN_REGIDX_BIT(TSTAT_REG_OFFSET, 3U), /*!< mailbox 0 transmit error */ + CAN_FLAG_MAL2 = CAN_REGIDX_BIT(TSTAT_REG_OFFSET, 18U), /*!< mailbox 2 arbitration lost */ + CAN_FLAG_MAL1 = CAN_REGIDX_BIT(TSTAT_REG_OFFSET, 10U), /*!< mailbox 1 arbitration lost */ + CAN_FLAG_MAL0 = CAN_REGIDX_BIT(TSTAT_REG_OFFSET, 2U), /*!< mailbox 0 arbitration lost */ + CAN_FLAG_MTFNERR2 = CAN_REGIDX_BIT(TSTAT_REG_OFFSET, 17U), /*!< mailbox 2 transmit finished with no error */ + CAN_FLAG_MTFNERR1 = CAN_REGIDX_BIT(TSTAT_REG_OFFSET, 9U), /*!< mailbox 1 transmit finished with no error */ + CAN_FLAG_MTFNERR0 = CAN_REGIDX_BIT(TSTAT_REG_OFFSET, 1U), /*!< mailbox 0 transmit finished with no error */ + CAN_FLAG_MTF2 = CAN_REGIDX_BIT(TSTAT_REG_OFFSET, 16U), /*!< mailbox 2 transmit finished */ + CAN_FLAG_MTF1 = CAN_REGIDX_BIT(TSTAT_REG_OFFSET, 8U), /*!< mailbox 1 transmit finished */ + CAN_FLAG_MTF0 = CAN_REGIDX_BIT(TSTAT_REG_OFFSET, 0U), /*!< mailbox 0 transmit finished */ + /* flags in RFIFO0 register */ + CAN_FLAG_RFO0 = CAN_REGIDX_BIT(RFIFO0_REG_OFFSET, 4U), /*!< receive FIFO0 overfull */ + CAN_FLAG_RFF0 = CAN_REGIDX_BIT(RFIFO0_REG_OFFSET, 3U), /*!< receive FIFO0 full */ + /* flags in RFIFO1 register */ + CAN_FLAG_RFO1 = CAN_REGIDX_BIT(RFIFO1_REG_OFFSET, 4U), /*!< receive FIFO1 overfull */ + CAN_FLAG_RFF1 = CAN_REGIDX_BIT(RFIFO1_REG_OFFSET, 3U), /*!< receive FIFO1 full */ + /* flags in ERR register */ + CAN_FLAG_BOERR = CAN_REGIDX_BIT(ERR_REG_OFFSET, 2U), /*!< bus-off error */ + CAN_FLAG_PERR = CAN_REGIDX_BIT(ERR_REG_OFFSET, 1U), /*!< passive error */ + CAN_FLAG_WERR = CAN_REGIDX_BIT(ERR_REG_OFFSET, 0U), /*!< warning error */ +}can_flag_enum; + +/* CAN interrupt flags */ +typedef enum +{ + /* interrupt flags in STAT register */ + CAN_INT_FLAG_SLPIF = CAN_REGIDX_BITS(STAT_REG_OFFSET, 4U, 17U), /*!< status change interrupt flag of sleep working mode entering */ + CAN_INT_FLAG_WUIF = CAN_REGIDX_BITS(STAT_REG_OFFSET, 3U, 16), /*!< status change interrupt flag of wakeup from sleep working mode */ + CAN_INT_FLAG_ERRIF = CAN_REGIDX_BITS(STAT_REG_OFFSET, 2U, 15), /*!< error interrupt flag */ + /* interrupt flags in TSTAT register */ + CAN_INT_FLAG_MTF2 = CAN_REGIDX_BITS(TSTAT_REG_OFFSET, 16U, 0U), /*!< mailbox 2 transmit finished interrupt flag */ + CAN_INT_FLAG_MTF1 = CAN_REGIDX_BITS(TSTAT_REG_OFFSET, 8U, 0U), /*!< mailbox 1 transmit finished interrupt flag */ + CAN_INT_FLAG_MTF0 = CAN_REGIDX_BITS(TSTAT_REG_OFFSET, 0U, 0U), /*!< mailbox 0 transmit finished interrupt flag */ + /* interrupt flags in RFIFO0 register */ + CAN_INT_FLAG_RFO0 = CAN_REGIDX_BITS(RFIFO0_REG_OFFSET, 4U, 3U), /*!< receive FIFO0 overfull interrupt flag */ + CAN_INT_FLAG_RFF0 = CAN_REGIDX_BITS(RFIFO0_REG_OFFSET, 3U, 2U), /*!< receive FIFO0 full interrupt flag */ + CAN_INT_FLAG_RFL0 = CAN_REGIDX_BITS(RFIFO0_REG_OFFSET, 2U, 1U), /*!< receive FIFO0 not empty interrupt flag */ + /* interrupt flags in RFIFO0 register */ + CAN_INT_FLAG_RFO1 = CAN_REGIDX_BITS(RFIFO1_REG_OFFSET, 4U, 6U), /*!< receive FIFO1 overfull interrupt flag */ + CAN_INT_FLAG_RFF1 = CAN_REGIDX_BITS(RFIFO1_REG_OFFSET, 3U, 5U), /*!< receive FIFO1 full interrupt flag */ + CAN_INT_FLAG_RFL1 = CAN_REGIDX_BITS(RFIFO1_REG_OFFSET, 2U, 4U), /*!< receive FIFO1 not empty interrupt flag */ + /* interrupt flags in ERR register */ + CAN_INT_FLAG_ERRN = CAN_REGIDX_BITS(ERR_REG_OFFSET, 3U, 11U), /*!< error number interrupt flag */ + CAN_INT_FLAG_BOERR = CAN_REGIDX_BITS(ERR_REG_OFFSET, 2U, 10U), /*!< bus-off error interrupt flag */ + CAN_INT_FLAG_PERR = CAN_REGIDX_BITS(ERR_REG_OFFSET, 1U, 9U), /*!< passive error interrupt flag */ + CAN_INT_FLAG_WERR = CAN_REGIDX_BITS(ERR_REG_OFFSET, 0U, 8U), /*!< warning error interrupt flag */ +}can_interrupt_flag_enum; + +/* CAN initiliaze parameters structure */ +typedef struct +{ + uint8_t working_mode; /*!< CAN working mode */ + uint8_t resync_jump_width; /*!< CAN resynchronization jump width */ + uint8_t time_segment_1; /*!< time segment 1 */ + uint8_t time_segment_2; /*!< time segment 2 */ + ControlStatus time_triggered; /*!< time triggered communication mode */ + ControlStatus auto_bus_off_recovery; /*!< automatic bus-off recovery */ + ControlStatus auto_wake_up; /*!< automatic wake-up mode */ + ControlStatus no_auto_retrans; /*!< automatic retransmission mode disable */ + ControlStatus rec_fifo_overwrite; /*!< receive FIFO overwrite mode */ + ControlStatus trans_fifo_order; /*!< transmit FIFO order */ + uint16_t prescaler; /*!< baudrate prescaler */ +}can_parameter_struct; + +/* CAN transmit message structure */ +typedef struct +{ + uint32_t tx_sfid; /*!< standard format frame identifier */ + uint32_t tx_efid; /*!< extended format frame identifier */ + uint8_t tx_ff; /*!< format of frame, standard or extended format */ + uint8_t tx_ft; /*!< type of frame, data or remote */ + uint8_t tx_dlen; /*!< data length */ + uint8_t tx_data[8]; /*!< transmit data */ +}can_trasnmit_message_struct; + +/* CAN receive message structure */ +typedef struct +{ + uint32_t rx_sfid; /*!< standard format frame identifier */ + uint32_t rx_efid; /*!< extended format frame identifier */ + uint8_t rx_ff; /*!< format of frame, standard or extended format */ + uint8_t rx_ft; /*!< type of frame, data or remote */ + uint8_t rx_dlen; /*!< data length */ + uint8_t rx_data[8]; /*!< receive data */ + uint8_t rx_fi; /*!< filtering index */ +} can_receive_message_struct; + +/* CAN filter parameters structure */ +typedef struct +{ + uint16_t filter_list_high; /*!< filter list number high bits*/ + uint16_t filter_list_low; /*!< filter list number low bits */ + uint16_t filter_mask_high; /*!< filter mask number high bits */ + uint16_t filter_mask_low; /*!< filter mask number low bits */ + uint16_t filter_fifo_number; /*!< receive FIFO associated with the filter */ + uint16_t filter_number; /*!< filter number */ + uint16_t filter_mode; /*!< filter mode, list or mask */ + uint16_t filter_bits; /*!< filter scale */ + ControlStatus filter_enable; /*!< filter work or not */ +}can_filter_parameter_struct; + +/* CAN errors */ +typedef enum +{ + CAN_ERROR_NONE = 0, /*!< no error */ + CAN_ERROR_FILL, /*!< fill error */ + CAN_ERROR_FORMATE, /*!< format error */ + CAN_ERROR_ACK, /*!< ACK error */ + CAN_ERROR_BITRECESSIVE, /*!< bit recessive error */ + CAN_ERROR_BITDOMINANTER, /*!< bit dominant error */ + CAN_ERROR_CRC, /*!< CRC error */ + CAN_ERROR_SOFTWARECFG, /*!< software configure */ +}can_error_enum; + +/* transmit states */ +typedef enum +{ + CAN_TRANSMIT_FAILED = 0, /*!< CAN transmitted failure */ + CAN_TRANSMIT_OK = 1, /*!< CAN transmitted success */ + CAN_TRANSMIT_PENDING = 2, /*!< CAN transmitted pending */ + CAN_TRANSMIT_NOMAILBOX = 4, /*!< no empty mailbox to be used for CAN */ +}can_transmit_state_enum; + +typedef enum +{ + CAN_INIT_STRUCT = 0, /* CAN initiliaze parameters struct */ + CAN_FILTER_STRUCT, /* CAN filter parameters struct */ + CAN_TX_MESSAGE_STRUCT, /* CAN transmit message struct */ + CAN_RX_MESSAGE_STRUCT, /* CAN receive message struct */ +}can_struct_type_enum; + +/* CAN baudrate prescaler*/ +#define BT_BAUDPSC(regval) (BITS(0,9) & ((uint32_t)(regval) << 0)) + +/* CAN bit segment 1*/ +#define BT_BS1(regval) (BITS(16,19) & ((uint32_t)(regval) << 16)) + +/* CAN bit segment 2*/ +#define BT_BS2(regval) (BITS(20,22) & ((uint32_t)(regval) << 20)) + +/* CAN resynchronization jump width*/ +#define BT_SJW(regval) (BITS(24,25) & ((uint32_t)(regval) << 24)) + +/* CAN communication mode*/ +#define BT_MODE(regval) (BITS(30,31) & ((uint32_t)(regval) << 30)) + +/* CAN FDATA high 16 bits */ +#define FDATA_MASK_HIGH(regval) (BITS(16,31) & ((uint32_t)(regval) << 16)) + +/* CAN FDATA low 16 bits */ +#define FDATA_MASK_LOW(regval) (BITS(0,15) & ((uint32_t)(regval) << 0)) + +/* CAN1 filter start bank_number*/ +#define FCTL_HBC1F(regval) (BITS(8,13) & ((uint32_t)(regval) << 8)) + +/* CAN transmit mailbox extended identifier*/ +#define TMI_EFID(regval) (BITS(3,31) & ((uint32_t)(regval) << 3)) + +/* CAN transmit mailbox standard identifier*/ +#define TMI_SFID(regval) (BITS(21,31) & ((uint32_t)(regval) << 21)) + +/* transmit data byte 0 */ +#define TMDATA0_DB0(regval) (BITS(0,7) & ((uint32_t)(regval) << 0)) + +/* transmit data byte 1 */ +#define TMDATA0_DB1(regval) (BITS(8,15) & ((uint32_t)(regval) << 8)) + +/* transmit data byte 2 */ +#define TMDATA0_DB2(regval) (BITS(16,23) & ((uint32_t)(regval) << 16)) + +/* transmit data byte 3 */ +#define TMDATA0_DB3(regval) (BITS(24,31) & ((uint32_t)(regval) << 24)) + +/* transmit data byte 4 */ +#define TMDATA1_DB4(regval) (BITS(0,7) & ((uint32_t)(regval) << 0)) + +/* transmit data byte 5 */ +#define TMDATA1_DB5(regval) (BITS(8,15) & ((uint32_t)(regval) << 8)) + +/* transmit data byte 6 */ +#define TMDATA1_DB6(regval) (BITS(16,23) & ((uint32_t)(regval) << 16)) + +/* transmit data byte 7 */ +#define TMDATA1_DB7(regval) (BITS(24,31) & ((uint32_t)(regval) << 24)) + +/* receive mailbox extended identifier*/ +#define GET_RFIFOMI_EFID(regval) GET_BITS((uint32_t)(regval), 3, 31) + +/* receive mailbox standrad identifier*/ +#define GET_RFIFOMI_SFID(regval) GET_BITS((uint32_t)(regval), 21, 31) + +/* receive data length */ +#define GET_RFIFOMP_DLENC(regval) GET_BITS((uint32_t)(regval), 0, 3) + +/* the index of the filter by which the frame is passed */ +#define GET_RFIFOMP_FI(regval) GET_BITS((uint32_t)(regval), 8, 15) + +/* receive data byte 0 */ +#define GET_RFIFOMDATA0_DB0(regval) GET_BITS((uint32_t)(regval), 0, 7) + +/* receive data byte 1 */ +#define GET_RFIFOMDATA0_DB1(regval) GET_BITS((uint32_t)(regval), 8, 15) + +/* receive data byte 2 */ +#define GET_RFIFOMDATA0_DB2(regval) GET_BITS((uint32_t)(regval), 16, 23) + +/* receive data byte 3 */ +#define GET_RFIFOMDATA0_DB3(regval) GET_BITS((uint32_t)(regval), 24, 31) + +/* receive data byte 4 */ +#define GET_RFIFOMDATA1_DB4(regval) GET_BITS((uint32_t)(regval), 0, 7) + +/* receive data byte 5 */ +#define GET_RFIFOMDATA1_DB5(regval) GET_BITS((uint32_t)(regval), 8, 15) + +/* receive data byte 6 */ +#define GET_RFIFOMDATA1_DB6(regval) GET_BITS((uint32_t)(regval), 16, 23) + +/* receive data byte 7 */ +#define GET_RFIFOMDATA1_DB7(regval) GET_BITS((uint32_t)(regval), 24, 31) + +/* error number */ +#define GET_ERR_ERRN(regval) GET_BITS((uint32_t)(regval), 4, 6) + +/* transmit error count */ +#define GET_ERR_TECNT(regval) GET_BITS((uint32_t)(regval), 16, 23) + +/* receive error count */ +#define GET_ERR_RECNT(regval) GET_BITS((uint32_t)(regval), 24, 31) + +/* CAN errors */ +#define ERR_ERRN(regval) (BITS(4,6) & ((uint32_t)(regval) << 4)) +#define CAN_ERRN_0 ERR_ERRN(0) /*!< no error */ +#define CAN_ERRN_1 ERR_ERRN(1) /*!< fill error */ +#define CAN_ERRN_2 ERR_ERRN(2) /*!< format error */ +#define CAN_ERRN_3 ERR_ERRN(3) /*!< ACK error */ +#define CAN_ERRN_4 ERR_ERRN(4) /*!< bit recessive error */ +#define CAN_ERRN_5 ERR_ERRN(5) /*!< bit dominant error */ +#define CAN_ERRN_6 ERR_ERRN(6) /*!< CRC error */ +#define CAN_ERRN_7 ERR_ERRN(7) /*!< software error */ + +#define CAN_STATE_PENDING ((uint32_t)0x00000000U) /*!< CAN pending */ + +/* CAN communication mode */ +#define CAN_NORMAL_MODE ((uint8_t)0x00U) /*!< normal communication mode */ +#define CAN_LOOPBACK_MODE ((uint8_t)0x01U) /*!< loopback communication mode */ +#define CAN_SILENT_MODE ((uint8_t)0x02U) /*!< silent communication mode */ +#define CAN_SILENT_LOOPBACK_MODE ((uint8_t)0x03U) /*!< loopback and silent communication mode */ + +/* CAN resynchronisation jump width */ +#define CAN_BT_SJW_1TQ ((uint8_t)0x00U) /*!< 1 time quanta */ +#define CAN_BT_SJW_2TQ ((uint8_t)0x01U) /*!< 2 time quanta */ +#define CAN_BT_SJW_3TQ ((uint8_t)0x02U) /*!< 3 time quanta */ +#define CAN_BT_SJW_4TQ ((uint8_t)0x03U) /*!< 4 time quanta */ + +/* CAN time segment 1 */ +#define CAN_BT_BS1_1TQ ((uint8_t)0x00U) /*!< 1 time quanta */ +#define CAN_BT_BS1_2TQ ((uint8_t)0x01U) /*!< 2 time quanta */ +#define CAN_BT_BS1_3TQ ((uint8_t)0x02U) /*!< 3 time quanta */ +#define CAN_BT_BS1_4TQ ((uint8_t)0x03U) /*!< 4 time quanta */ +#define CAN_BT_BS1_5TQ ((uint8_t)0x04U) /*!< 5 time quanta */ +#define CAN_BT_BS1_6TQ ((uint8_t)0x05U) /*!< 6 time quanta */ +#define CAN_BT_BS1_7TQ ((uint8_t)0x06U) /*!< 7 time quanta */ +#define CAN_BT_BS1_8TQ ((uint8_t)0x07U) /*!< 8 time quanta */ +#define CAN_BT_BS1_9TQ ((uint8_t)0x08U) /*!< 9 time quanta */ +#define CAN_BT_BS1_10TQ ((uint8_t)0x09U) /*!< 10 time quanta */ +#define CAN_BT_BS1_11TQ ((uint8_t)0x0AU) /*!< 11 time quanta */ +#define CAN_BT_BS1_12TQ ((uint8_t)0x0BU) /*!< 12 time quanta */ +#define CAN_BT_BS1_13TQ ((uint8_t)0x0CU) /*!< 13 time quanta */ +#define CAN_BT_BS1_14TQ ((uint8_t)0x0DU) /*!< 14 time quanta */ +#define CAN_BT_BS1_15TQ ((uint8_t)0x0EU) /*!< 15 time quanta */ +#define CAN_BT_BS1_16TQ ((uint8_t)0x0FU) /*!< 16 time quanta */ + +/* CAN time segment 2 */ +#define CAN_BT_BS2_1TQ ((uint8_t)0x00U) /*!< 1 time quanta */ +#define CAN_BT_BS2_2TQ ((uint8_t)0x01U) /*!< 2 time quanta */ +#define CAN_BT_BS2_3TQ ((uint8_t)0x02U) /*!< 3 time quanta */ +#define CAN_BT_BS2_4TQ ((uint8_t)0x03U) /*!< 4 time quanta */ +#define CAN_BT_BS2_5TQ ((uint8_t)0x04U) /*!< 5 time quanta */ +#define CAN_BT_BS2_6TQ ((uint8_t)0x05U) /*!< 6 time quanta */ +#define CAN_BT_BS2_7TQ ((uint8_t)0x06U) /*!< 7 time quanta */ +#define CAN_BT_BS2_8TQ ((uint8_t)0x07U) /*!< 8 time quanta */ + +/* CAN mailbox number */ +#define CAN_MAILBOX0 ((uint8_t)0x00U) /*!< mailbox0 */ +#define CAN_MAILBOX1 ((uint8_t)0x01U) /*!< mailbox1 */ +#define CAN_MAILBOX2 ((uint8_t)0x02U) /*!< mailbox2 */ +#define CAN_NOMAILBOX ((uint8_t)0x03U) /*!< no mailbox empty */ + +/* CAN frame format */ +#define CAN_FF_STANDARD ((uint32_t)0x00000000U) /*!< standard frame */ +#define CAN_FF_EXTENDED ((uint32_t)0x00000004U) /*!< extended frame */ + +/* CAN receive fifo */ +#define CAN_FIFO0 ((uint8_t)0x00U) /*!< receive FIFO0 */ +#define CAN_FIFO1 ((uint8_t)0x01U) /*!< receive FIFO1 */ + +/* frame number of receive fifo */ +#define CAN_RFIF_RFL_MASK ((uint32_t)0x00000003U) /*!< mask for frame number in receive FIFOx */ + +#define CAN_SFID_MASK ((uint32_t)0x000007FFU) /*!< mask of standard identifier */ +#define CAN_EFID_MASK ((uint32_t)0x1FFFFFFFU) /*!< mask of extended identifier */ + +/* CAN working mode */ +#define CAN_MODE_INITIALIZE ((uint8_t)0x01U) /*!< CAN initialize mode */ +#define CAN_MODE_NORMAL ((uint8_t)0x02U) /*!< CAN normal mode */ +#define CAN_MODE_SLEEP ((uint8_t)0x04U) /*!< CAN sleep mode */ + +/* filter bits */ +#define CAN_FILTERBITS_16BIT ((uint8_t)0x00U) /*!< CAN filter 16 bits */ +#define CAN_FILTERBITS_32BIT ((uint8_t)0x01U) /*!< CAN filter 32 bits */ + +/* filter mode */ +#define CAN_FILTERMODE_MASK ((uint8_t)0x00U) /*!< mask mode */ +#define CAN_FILTERMODE_LIST ((uint8_t)0x01U) /*!< list mode */ + +/* filter 16 bits mask */ +#define CAN_FILTER_MASK_16BITS ((uint32_t)0x0000FFFFU) /*!< can filter 16 bits mask */ + +/* frame type */ +#define CAN_FT_DATA ((uint32_t)0x00000000U) /*!< data frame */ +#define CAN_FT_REMOTE ((uint32_t)0x00000002U) /*!< remote frame */ + +/* CAN timeout */ +#define CAN_TIMEOUT ((uint32_t)0x0000FFFFU) /*!< timeout value */ + +/* interrupt enable bits */ +#define CAN_INT_TME CAN_INTEN_TMEIE /*!< transmit mailbox empty interrupt enable */ +#define CAN_INT_RFNE0 CAN_INTEN_RFNEIE0 /*!< receive FIFO0 not empty interrupt enable */ +#define CAN_INT_RFF0 CAN_INTEN_RFFIE0 /*!< receive FIFO0 full interrupt enable */ +#define CAN_INT_RFO0 CAN_INTEN_RFOIE0 /*!< receive FIFO0 overfull interrupt enable */ +#define CAN_INT_RFNE1 CAN_INTEN_RFNEIE1 /*!< receive FIFO1 not empty interrupt enable */ +#define CAN_INT_RFF1 CAN_INTEN_RFFIE1 /*!< receive FIFO1 full interrupt enable */ +#define CAN_INT_RFO1 CAN_INTEN_RFOIE1 /*!< receive FIFO1 overfull interrupt enable */ +#define CAN_INT_WERR CAN_INTEN_WERRIE /*!< warning error interrupt enable */ +#define CAN_INT_PERR CAN_INTEN_PERRIE /*!< passive error interrupt enable */ +#define CAN_INT_BO CAN_INTEN_BOIE /*!< bus-off interrupt enable */ +#define CAN_INT_ERRN CAN_INTEN_ERRNIE /*!< error number interrupt enable */ +#define CAN_INT_ERR CAN_INTEN_ERRIE /*!< error interrupt enable */ +#define CAN_INT_WAKEUP CAN_INTEN_WIE /*!< wakeup interrupt enable */ +#define CAN_INT_SLPW CAN_INTEN_SLPWIE /*!< sleep working interrupt enable */ + +/* function declarations */ +/* initialization functions */ +/* deinitialize CAN */ +void can_deinit(uint32_t can_periph); +/* initialize CAN structure */ +void can_struct_para_init(can_struct_type_enum type, void* p_struct); +/* initialize CAN */ +ErrStatus can_init(uint32_t can_periph, can_parameter_struct* can_parameter_init); +/* CAN filter initialization */ +void can_filter_init(can_filter_parameter_struct* can_filter_parameter_init); + +/* function configuration */ +/* set can1 filter start bank number */ +void can1_filter_start_bank(uint8_t start_bank); +/* enable functions */ +/* CAN debug freeze enable */ +void can_debug_freeze_enable(uint32_t can_periph); +/* CAN debug freeze disable */ +void can_debug_freeze_disable(uint32_t can_periph); +/* CAN time trigger mode enable */ +void can_time_trigger_mode_enable(uint32_t can_periph); +/* CAN time trigger mode disable */ +void can_time_trigger_mode_disable(uint32_t can_periph); + +/* transmit functions */ +/* transmit CAN message */ +uint8_t can_message_transmit(uint32_t can_periph, can_trasnmit_message_struct* transmit_message); +/* get CAN transmit state */ +can_transmit_state_enum can_transmit_states(uint32_t can_periph, uint8_t mailbox_number); +/* stop CAN transmission */ +void can_transmission_stop(uint32_t can_periph, uint8_t mailbox_number); +/* CAN receive message */ +void can_message_receive(uint32_t can_periph, uint8_t fifo_number, can_receive_message_struct* receive_message); +/* CAN release fifo */ +void can_fifo_release(uint32_t can_periph, uint8_t fifo_number); +/* CAN receive message length */ +uint8_t can_receive_message_length_get(uint32_t can_periph, uint8_t fifo_number); +/* CAN working mode */ +ErrStatus can_working_mode_set(uint32_t can_periph, uint8_t working_mode); +/* CAN wakeup from sleep mode */ +ErrStatus can_wakeup(uint32_t can_periph); + +/* CAN get error */ +can_error_enum can_error_get(uint32_t can_periph); +/* get CAN receive error number */ +uint8_t can_receive_error_number_get(uint32_t can_periph); +/* get CAN transmit error number */ +uint8_t can_transmit_error_number_get(uint32_t can_periph); + +/* interrupt & flag functions */ +/* CAN interrupt enable */ +void can_interrupt_enable(uint32_t can_periph, uint32_t interrupt); +/* CAN interrupt disable */ +void can_interrupt_disable(uint32_t can_periph, uint32_t interrupt); +/* CAN get flag state */ +FlagStatus can_flag_get(uint32_t can_periph, can_flag_enum flag); +/* CAN clear flag state */ +void can_flag_clear(uint32_t can_periph, can_flag_enum flag); +/* CAN get interrupt flag state */ +FlagStatus can_interrupt_flag_get(uint32_t can_periph, can_interrupt_flag_enum flag); +/* CAN clear interrupt flag state */ +void can_interrupt_flag_clear(uint32_t can_periph, can_interrupt_flag_enum flag); + +#endif /* GD32F20X_CAN_H */ diff --git a/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_standard_peripheral/Include/gd32f20x_cau.h b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_standard_peripheral/Include/gd32f20x_cau.h new file mode 100644 index 0000000000..8cf28a7c4a --- /dev/null +++ b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_standard_peripheral/Include/gd32f20x_cau.h @@ -0,0 +1,258 @@ +/*! + \file gd32f20x_cau.h + \brief definitions for the CAU + + \version 2015-07-15, V1.0.0, firmware for GD32F20x + \version 2017-06-05, V2.0.0, firmware for GD32F20x + \version 2018-10-31, V2.1.0, firmware for GD32F20x + \version 2020-09-30, V2.2.0, firmware for GD32F20x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef GD32F20X_CAU_H +#define GD32F20X_CAU_H + +#include "gd32f20x.h" + +/* CAU definitions */ +#define CAU CAU_BASE + +/* registers definitions */ +#define CAU_CTL REG32(CAU + 0x00U) /*!< control register */ +#define CAU_STAT0 REG32(CAU + 0x04U) /*!< status register 0 */ +#define CAU_DI REG32(CAU + 0x08U) /*!< data input register */ +#define CAU_DO REG32(CAU + 0x0CU) /*!< data output register */ +#define CAU_DMAEN REG32(CAU + 0x10U) /*!< DMA enable register */ +#define CAU_INTEN REG32(CAU + 0x14U) /*!< interrupt enable register */ +#define CAU_STAT1 REG32(CAU + 0x18U) /*!< status register 1 */ +#define CAU_INTF REG32(CAU + 0x1CU) /*!< interrupt flag register */ +#define CAU_KEY0H REG32(CAU + 0x20U) /*!< key 0 high register */ +#define CAU_KEY0L REG32(CAU + 0x24U) /*!< key 0 low register */ +#define CAU_KEY1H REG32(CAU + 0x28U) /*!< key 1 high register */ +#define CAU_KEY1L REG32(CAU + 0x2CU) /*!< key 1 low register */ +#define CAU_KEY2H REG32(CAU + 0x30U) /*!< key 2 high register */ +#define CAU_KEY2L REG32(CAU + 0x34U) /*!< key 2 low register */ +#define CAU_KEY3H REG32(CAU + 0x38U) /*!< key 3 high register */ +#define CAU_KEY3L REG32(CAU + 0x3CU) /*!< key 3 low register */ +#define CAU_IV0H REG32(CAU + 0x40U) /*!< initial vector 0 high register */ +#define CAU_IV0L REG32(CAU + 0x44U) /*!< initial vector 0 low register */ +#define CAU_IV1H REG32(CAU + 0x48U) /*!< initial vector 1 high register */ +#define CAU_IV1L REG32(CAU + 0x4CU) /*!< initial vector 1 low register */ + +/* bits definitions */ +/* CAU_CTL */ +#define CAU_CTL_CAUDIR BIT(2) /*!< algorithm direction */ +#define CAU_CTL_ALGM BITS(3,5) /*!< algorithm mode selection */ +#define CAU_CTL_DATAM BITS(6,7) /*!< data swapping selection */ +#define CAU_CTL_KEYM BITS(8,9) /*!< key length selection when aes mode */ +#define CAU_CTL_FFLUSH BIT(14) /*!< FIFO flush */ +#define CAU_CTL_CAUEN BIT(15) /*!< cryptographic module enable */ + +/* CAU_STAT0 */ +#define CAU_STAT0_IEM BIT(0) /*!< IN FIFO empty flag */ +#define CAU_STAT0_INF BIT(1) /*!< IN FIFO not full flag */ +#define CAU_STAT0_ONE BIT(2) /*!< OUT FIFO not empty flag */ +#define CAU_STAT0_OFU BIT(3) /*!< OUT FIFO full flag */ +#define CAU_STAT0_BUSY BIT(4) /*!< busy flag */ + +/* CAU_DI */ +#define CAU_DI_DI BITS(0,31) /*!< data input */ + +/* CAU_DO */ +#define CAU_DO_DO BITS(0,31) /*!< data output */ + +/* CAU_DMAEN */ +#define CAU_DMAEN_DMAIEN BIT(0) /*!< IN FIFO DMA enable */ +#define CAU_DMAEN_DMAOEN BIT(1) /*!< OUT FIFO DMA enable */ + +/* CAU_INTEN */ +#define CAU_INTEN_IINTEN BIT(0) /*!< IN FIFO interrupt enable */ +#define CAU_INTEN_OINTEN BIT(1) /*!< OUT FIFO interrupt enable */ + +/* CAU_STAT1 */ +#define CAU_STAT1_ISTA BIT(0) /*!< flag set when there is less than 4 words in IN FIFO */ +#define CAU_STAT1_OSTA BIT(1) /*!< flag set when there is one or more word in OUT FIFO */ + +/* CAU_INTF */ +#define CAU_INTF_IINTF BIT(0) /*!< IN FIFO interrupt flag */ +#define CAU_INTF_OINTF BIT(1) /*!< OUT FIFO interrupt flag */ + +/* CAU_KEYxH x=0..3 */ +#define CAU_KEYXH_KEYXH BITS(0,31) /*!< the key for des, tdes, aes */ + +/* CAU_KEYxL x=0..3 */ +#define CAU_KEYXL_KEYXL BITS(0,31) /*!< the key for des, tdes, aes */ + +/* CAU_IVxH x=0..1 */ +#define CAU_IVXH_IVXH BITS(0,31) /*!< the initialization vector for des, tdes, aes */ + +/* CAU_IVxL x=0..1 */ +#define CAU_IVXL_IVXL BITS(0,31) /*!< the initialization vector for des, tdes, aes */ + +/* constants definitions */ +/* structure for keys initialization of the cau */ +typedef struct +{ + uint32_t key_0_high; /*!< key 0 high */ + uint32_t key_0_low; /*!< key 0 low */ + uint32_t key_1_high; /*!< key 1 high */ + uint32_t key_1_low; /*!< key 1 low */ + uint32_t key_2_high; /*!< key 2 high */ + uint32_t key_2_low; /*!< key 2 low */ + uint32_t key_3_high; /*!< key 3 high */ + uint32_t key_3_low; /*!< key 3 low */ +}cau_key_parameter_struct; + +/* structure for vectors initialization of the cau */ +typedef struct +{ + uint32_t iv_0_high; /*!< init vector 0 high */ + uint32_t iv_0_low; /*!< init vector 0 low */ + uint32_t iv_1_high; /*!< init vector 1 high */ + uint32_t iv_1_low; /*!< init vector 1 low */ +}cau_iv_parameter_struct; + +/* structure for vectors initialization of the cau */ +typedef struct +{ + uint8_t *input; /*!< pointer to the input buffer */ + uint32_t in_length; /*!< length of the input buffer, + must be a multiple of 8(DES and TDES) or 16(AES) */ + uint8_t *output; /*!< pointer to the returned buffer */ +}cau_text_struct; + +/* cau_ctl register value */ +#define CAU_ENCRYPT ((uint32_t)0x00000000) /*!< encrypt */ +#define CAU_DECRYPT CAU_CTL_CAUDIR /*!< decrypt */ + +#define CTL_ALGM(regval) (BITS(3,5) & ((uint32_t)(regval) << 3)) /*!< write value to CAU_CTL_ALGM bit field */ +#define CAU_MODE_TDES_ECB CTL_ALGM(0) /*!< TDES-ECB (3DES Electronic codebook) */ +#define CAU_MODE_TDES_CBC CTL_ALGM(1) /*!< TDES-CBC (3DES Cipher block chaining) */ +#define CAU_MODE_DES_ECB CTL_ALGM(2) /*!< DES-ECB (simple DES Electronic codebook) */ +#define CAU_MODE_DES_CBC CTL_ALGM(3) /*!< DES-CBC (simple DES Cipher block chaining) */ +#define CAU_MODE_AES_ECB CTL_ALGM(4) /*!< AES-ECB (AES Electronic codebook) */ +#define CAU_MODE_AES_CBC CTL_ALGM(5) /*!< AES-CBC (AES Cipher block chaining) */ +#define CAU_MODE_AES_CTR CTL_ALGM(6) /*!< AES-CTR (AES counter mode) */ +#define CAU_MODE_AES_KEY CTL_ALGM(7) /*!< AES decryption key preparation mode */ + +#define CTL_DATAM(regval) (BITS(6,7) & ((uint32_t)(regval) << 6)) /*!< write value to CAU_CTL_DATAM bit field */ +#define CAU_SWAPPING_32BIT CTL_DATAM(0) /*!< no swapping */ +#define CAU_SWAPPING_16BIT CTL_DATAM(1) /*!< half-word swapping */ +#define CAU_SWAPPING_8BIT CTL_DATAM(2) /*!< bytes swapping */ +#define CAU_SWAPPING_1BIT CTL_DATAM(3) /*!< bit swapping */ + +#define CTL_KEYM(regval) (BITS(8,9) & ((uint32_t)(regval) << 8)) /*!< write value to CAU_CTL_KEYM bit field */ +#define CAU_KEYSIZE_128BIT CTL_KEYM(0) /*!< 128 bit key length */ +#define CAU_KEYSIZE_192BIT CTL_KEYM(1) /*!< 192 bit key length */ +#define CAU_KEYSIZE_256BIT CTL_KEYM(2) /*!< 256 bit key length */ + +/* cau_stat0 register value */ +#define CAU_FLAG_INFIFO_EMPTY CAU_STAT0_IEM /*!< IN FIFO empty */ +#define CAU_FLAG_INFIFO_NO_FULL CAU_STAT0_INF /*!< IN FIFO is not full */ +#define CAU_FLAG_OUTFIFO_NO_EMPTY CAU_STAT0_ONE /*!< OUT FIFO not empty */ +#define CAU_FLAG_OUTFIFO_FULL CAU_STAT0_OFU /*!< OUT FIFO is full */ +#define CAU_FLAG_BUSY CAU_STAT0_BUSY /*!< the CAU core is busy */ + +/* cau_dmaen register value */ +#define CAU_DMA_INFIFO CAU_DMAEN_DMAIEN /*!< DMA input enable */ +#define CAU_DMA_OUTFIFO CAU_DMAEN_DMAOEN /*!< DMA output enable */ + +/* cau_inten register value */ +#define CAU_INT_INFIFO CAU_INTEN_IINTEN /*!< IN FIFO Interrupt */ +#define CAU_INT_OUTFIFO CAU_INTEN_OINTEN /*!< OUT FIFO Interrupt */ + +/* cau_stat1 register value */ +#define CAU_FLAG_INFIFO (CAU_STAT1_ISTA | ((uint32_t)0x00000020U)) /*!< IN FIFO flag status */ +#define CAU_FLAG_OUTFIFO (CAU_STAT1_OSTA | ((uint32_t)0x00000020U)) /*!< OUT FIFO flag status */ + +/* cau_intf register value */ +#define CAU_INT_FLAG_INFIFO CAU_INTF_IINTF /*!< IN FIFO interrupt status */ +#define CAU_INT_FLAG_OUTFIFO CAU_INTF_OINTF /*!< OUT FIFO interrupt status */ + +/* function declarations */ +/* initialization functions */ +/* reset the CAU peripheral */ +void cau_deinit(void); +/* enable the CAU peripheral */ +void cau_enable(void); +/* disable the CAU peripheral */ +void cau_disable(void); +/* enable the CAU DMA interface */ +void cau_dma_enable(uint32_t dma_req); +/* disable the CAU DMA interface */ +void cau_dma_disable(uint32_t dma_req); +/* initialize the CAU peripheral */ +void cau_init(uint32_t algo_dir, uint32_t algo_mode, uint32_t swapping); +/* configure key size if used AES algorithm */ +void cau_aes_keysize_config(uint32_t key_size); +/* initialize the key parameters */ +void cau_key_init(cau_key_parameter_struct* key_initpara); +/* initialize the structure cau_key_initpara */ +void cau_key_parameter_init(cau_key_parameter_struct* key_initpara); +/* initialize the vectors parameters */ +void cau_iv_init(cau_iv_parameter_struct* iv_initpara); +/* initialize the vectors parameters */ +void cau_iv_parameter_init(cau_iv_parameter_struct* iv_initpara); +/* flush the IN and OUT FIFOs */ +void cau_fifo_flush(void); +/* return whether CAU peripheral is enabled or disabled */ +ControlStatus cau_enable_state_get(void); +/* write data to the IN FIFO */ +void cau_data_write(uint32_t data); +/* return the last data entered into the output FIFO */ +uint32_t cau_data_read(void); + +/* function configuration */ +/* calculate digest in HASH mode */ +/* encrypt and decrypt using AES in ECB mode */ +ErrStatus cau_aes_ecb(uint32_t algo_dir, uint8_t *key, uint16_t keysize, cau_text_struct *text); +/* encrypt and decrypt using AES in CBC mode */ +ErrStatus cau_aes_cbc(uint32_t algo_dir, uint8_t *key, uint16_t keysize, uint8_t iv[16], cau_text_struct *text); +/* encrypt and decrypt using AES in CTR mode */ +ErrStatus cau_aes_ctr(uint32_t algo_dir, uint8_t *key, uint16_t keysize, uint8_t iv[16], cau_text_struct *text); +/* encrypt and decrypt using TDES in ECB mode */ +ErrStatus cau_tdes_ecb(uint32_t algo_dir, uint8_t key[24], cau_text_struct *text); +/* encrypt and decrypt using TDES in CBC mode */ +ErrStatus cau_tdes_cbc(uint32_t algo_dir, uint8_t key[24], uint8_t iv[8], cau_text_struct *text); +/* encrypt and decrypt using DES in ECB mode */ +ErrStatus cau_des_ecb(uint32_t algo_dir, uint8_t key[24], cau_text_struct *text); +/* encrypt and decrypt using DES in CBC mode */ +ErrStatus cau_des_cbc(uint32_t algo_dir, uint8_t key[24], uint8_t iv[8], cau_text_struct *text); + +/* interrupt & flag functions */ +/* get the CAU flag status */ +FlagStatus cau_flag_get(uint32_t flag); +/* enable the CAU interrupts */ +void cau_interrupt_enable(uint32_t interrupt); +/* disable the CAU interrupts */ +void cau_interrupt_disable(uint32_t interrupt); +/* get the interrupt flag */ +FlagStatus cau_interrupt_flag_get(uint32_t int_flag); + +#endif /* GD32F20X_CAU_H */ diff --git a/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_standard_peripheral/Include/gd32f20x_crc.h b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_standard_peripheral/Include/gd32f20x_crc.h new file mode 100644 index 0000000000..90556a8658 --- /dev/null +++ b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_standard_peripheral/Include/gd32f20x_crc.h @@ -0,0 +1,80 @@ +/*! + \file gd32f20x_crc.h + \brief definitions for the CRC + + \version 2015-07-15, V1.0.0, firmware for GD32F20x + \version 2017-06-05, V2.0.0, firmware for GD32F20x + \version 2018-10-31, V2.1.0, firmware for GD32F20x + \version 2020-09-30, V2.2.0, firmware for GD32F20x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef GD32F20X_CRC_H +#define GD32F20X_CRC_H + +#include "gd32f20x.h" + +/* CRC definitions */ +#define CRC CRC_BASE + +/* registers definitions */ +#define CRC_DATA REG32(CRC + 0x00U) /*!< CRC data register */ +#define CRC_FDATA REG32(CRC + 0x04U) /*!< CRC free data register */ +#define CRC_CTL REG32(CRC + 0x08U) /*!< CRC control register */ + +/* bits definitions */ +/* CRC_DATA */ +#define CRC_DATA_DATA BITS(0,31) /*!< CRC calculation result bits */ + +/* CRC_FDATA */ +#define CRC_FDATA_FDATA BITS(0,7) /*!< CRC free data bits */ + +/* CRC_CTL */ +#define CRC_CTL_RST BIT(0) /*!< CRC reset CRC_DATA register bit */ + +/* function declarations */ +/* initialization functions */ +/* deinit CRC calculation unit */ +void crc_deinit(void); +/* reset data register to the value of initialization data register */ +void crc_data_register_reset(void); +/* read the value of the data register */ +uint32_t crc_data_register_read(void); + +/* function configuration */ +/* read the value of the free data register */ +uint8_t crc_free_data_register_read(void); +/* write data to the free data register */ +void crc_free_data_register_write(uint8_t free_data); +/* calculate the CRC value of a 32-bit data */ +uint32_t crc_single_data_calculate(uint32_t sdata); +/* calculate the CRC value of an array of 32-bit values */ +uint32_t crc_block_data_calculate(uint32_t array[], uint32_t size); + +#endif /* GD32F20X_CRC_H */ diff --git a/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_standard_peripheral/Include/gd32f20x_dac.h b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_standard_peripheral/Include/gd32f20x_dac.h new file mode 100644 index 0000000000..b0d5100b0e --- /dev/null +++ b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_standard_peripheral/Include/gd32f20x_dac.h @@ -0,0 +1,247 @@ +/*! + \file gd32f20x_dac.h + \brief definitions for the DAC + + \version 2015-07-15, V1.0.0, firmware for GD32F20x + \version 2017-06-05, V2.0.0, firmware for GD32F20x + \version 2018-10-31, V2.1.0, firmware for GD32F20x + \version 2020-09-30, V2.2.0, firmware for GD32F20x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef GD32F20X_DAC_H +#define GD32F20X_DAC_H + +#include "gd32f20x.h" + +/* DACx(x=0,1) definitions */ +#define DAC DAC_BASE +#define DAC0 0U +#define DAC1 1U + +/* registers definitions */ +#define DAC_CTL REG32(DAC + 0x00U) /*!< DAC control register */ +#define DAC_SWT REG32(DAC + 0x04U) /*!< DAC software trigger register */ +#define DAC0_R12DH REG32(DAC + 0x08U) /*!< DAC0 12-bit right-aligned data holding register */ +#define DAC0_L12DH REG32(DAC + 0x0CU) /*!< DAC0 12-bit left-aligned data holding register */ +#define DAC0_R8DH REG32(DAC + 0x10U) /*!< DAC0 8-bit right-aligned data holding register */ +#define DAC1_R12DH REG32(DAC + 0x14U) /*!< DAC1 12-bit right-aligned data holding register */ +#define DAC1_L12DH REG32(DAC + 0x18U) /*!< DAC1 12-bit left-aligned data holding register */ +#define DAC1_R8DH REG32(DAC + 0x1CU) /*!< DAC1 8-bit right-aligned data holding register */ +#define DACC_R12DH REG32(DAC + 0x20U) /*!< DAC concurrent mode 12-bit right-aligned data holding register */ +#define DACC_L12DH REG32(DAC + 0x24U) /*!< DAC concurrent mode 12-bit left-aligned data holding register */ +#define DACC_R8DH REG32(DAC + 0x28U) /*!< DAC concurrent mode 8-bit right-aligned data holding register */ +#define DAC0_DO REG32(DAC + 0x2CU) /*!< DAC0 data output register */ +#define DAC1_DO REG32(DAC + 0x30U) /*!< DAC1 data output register */ + +/* bits definitions */ +/* DAC_CTL */ +#define DAC_CTL_DEN0 BIT(0) /*!< DAC0 enable/disable bit */ +#define DAC_CTL_DBOFF0 BIT(1) /*!< DAC0 output buffer turn on/off bit */ +#define DAC_CTL_DTEN0 BIT(2) /*!< DAC0 trigger enable/disable bit */ +#define DAC_CTL_DTSEL0 BITS(3,5) /*!< DAC0 trigger source selection enable/disable bits */ +#define DAC_CTL_DWM0 BITS(6,7) /*!< DAC0 noise wave mode */ +#define DAC_CTL_DWBW0 BITS(8,11) /*!< DAC0 noise wave bit width */ +#define DAC_CTL_DDMAEN0 BIT(12) /*!< DAC0 DMA enable/disable bit */ +#define DAC_CTL_DEN1 BIT(16) /*!< DAC1 enable/disable bit */ +#define DAC_CTL_DBOFF1 BIT(17) /*!< DAC1 output buffer turn on/turn off bit */ +#define DAC_CTL_DTEN1 BIT(18) /*!< DAC1 trigger enable/disable bit */ +#define DAC_CTL_DTSEL1 BITS(19,21) /*!< DAC1 trigger source selection enable/disable bits */ +#define DAC_CTL_DWM1 BITS(22,23) /*!< DAC1 noise wave mode */ +#define DAC_CTL_DWBW1 BITS(24,27) /*!< DAC1 noise wave bit width */ +#define DAC_CTL_DDMAEN1 BIT(28) /*!< DAC1 DMA enable/disable bit */ + +/* DAC_SWT */ +#define DAC_SWT_SWTR0 BIT(0) /*!< DAC0 software trigger bit, cleared by hardware */ +#define DAC_SWT_SWTR1 BIT(1) /*!< DAC1 software trigger bit, cleared by hardware */ + +/* DAC0_R12DH */ +#define DAC0_R12DH_DAC0_DH BITS(0,11) /*!< DAC0 12-bit right-aligned data bits */ + +/* DAC0_L12DH */ +#define DAC0_L12DH_DAC0_DH BITS(4,15) /*!< DAC0 12-bit left-aligned data bits */ + +/* DAC0_R8DH */ +#define DAC0_R8DH_DAC0_DH BITS(0,7) /*!< DAC0 8-bit right-aligned data bits */ + +/* DAC1_R12DH */ +#define DAC1_R12DH_DAC1_DH BITS(0,11) /*!< DAC1 12-bit right-aligned data bits */ + +/* DAC1_L12DH */ +#define DAC1_L12DH_DAC1_DH BITS(4,15) /*!< DAC1 12-bit left-aligned data bits */ + +/* DAC1_R8DH */ +#define DAC1_R8DH_DAC1_DH BITS(0,7) /*!< DAC1 8-bit right-aligned data bits */ + +/* DACC_R12DH */ +#define DACC_R12DH_DAC0_DH BITS(0,11) /*!< DAC concurrent mode DAC0 12-bit right-aligned data bits */ +#define DACC_R12DH_DAC1_DH BITS(16,27) /*!< DAC concurrent mode DAC1 12-bit right-aligned data bits */ + +/* DACC_L12DH */ +#define DACC_L12DH_DAC0_DH BITS(4,15) /*!< DAC concurrent mode DAC0 12-bit left-aligned data bits */ +#define DACC_L12DH_DAC1_DH BITS(20,31) /*!< DAC concurrent mode DAC1 12-bit left-aligned data bits */ + +/* DACC_R8DH */ +#define DACC_R8DH_DAC0_DH BITS(0,7) /*!< DAC concurrent mode DAC0 8-bit right-aligned data bits */ +#define DACC_R8DH_DAC1_DH BITS(8,15) /*!< DAC concurrent mode DAC1 8-bit right-aligned data bits */ + +/* DAC0_DO */ +#define DAC0_DO_DAC0_DO BITS(0,11) /*!< DAC0 12-bit output data bits */ + +/* DAC1_DO */ +#define DAC1_DO_DAC1_DO BITS(0,11) /*!< DAC1 12-bit output data bits */ + +/* constants definitions */ +/* DAC trigger source */ +#define CTL_DTSEL(regval) (BITS(3,5) & ((uint32_t)(regval) << 3)) +#define DAC_TRIGGER_T5_TRGO CTL_DTSEL(0) /*!< TIMER5 TRGO */ +#define DAC_TRIGGER_T2_TRGO CTL_DTSEL(1) /*!< TIMER2 TRGO */ +#define DAC_TRIGGER_T6_TRGO CTL_DTSEL(2) /*!< TIMER6 TRGO */ +#define DAC_TRIGGER_T4_TRGO CTL_DTSEL(3) /*!< TIMER4 TRGO */ +#define DAC_TRIGGER_T1_TRGO CTL_DTSEL(4) /*!< TIMER1 TRGO */ +#define DAC_TRIGGER_T3_TRGO CTL_DTSEL(5) /*!< TIMER3 TRGO */ +#define DAC_TRIGGER_EXTI_9 CTL_DTSEL(6) /*!< EXTI interrupt line9 event */ +#define DAC_TRIGGER_SOFTWARE CTL_DTSEL(7) /*!< software trigger */ + +/* DAC noise wave mode */ +#define CTL_DWM(regval) (BITS(6,7) & ((uint32_t)(regval) << 6)) +#define DAC_WAVE_DISABLE CTL_DWM(0) /*!< wave disable */ +#define DAC_WAVE_MODE_LFSR CTL_DWM(1) /*!< LFSR noise mode */ +#define DAC_WAVE_MODE_TRIANGLE CTL_DWM(2) /*!< triangle noise mode */ + +/* DAC noise wave bit width */ +#define DWBW(regval) (BITS(8,11) & ((uint32_t)(regval) << 8)) +#define DAC_WAVE_BIT_WIDTH_1 DWBW(0) /*!< bit width of the wave signal is 1 */ +#define DAC_WAVE_BIT_WIDTH_2 DWBW(1) /*!< bit width of the wave signal is 2 */ +#define DAC_WAVE_BIT_WIDTH_3 DWBW(2) /*!< bit width of the wave signal is 3 */ +#define DAC_WAVE_BIT_WIDTH_4 DWBW(3) /*!< bit width of the wave signal is 4 */ +#define DAC_WAVE_BIT_WIDTH_5 DWBW(4) /*!< bit width of the wave signal is 5 */ +#define DAC_WAVE_BIT_WIDTH_6 DWBW(5) /*!< bit width of the wave signal is 6 */ +#define DAC_WAVE_BIT_WIDTH_7 DWBW(6) /*!< bit width of the wave signal is 7 */ +#define DAC_WAVE_BIT_WIDTH_8 DWBW(7) /*!< bit width of the wave signal is 8 */ +#define DAC_WAVE_BIT_WIDTH_9 DWBW(8) /*!< bit width of the wave signal is 9 */ +#define DAC_WAVE_BIT_WIDTH_10 DWBW(9) /*!< bit width of the wave signal is 10 */ +#define DAC_WAVE_BIT_WIDTH_11 DWBW(10) /*!< bit width of the wave signal is 11 */ +#define DAC_WAVE_BIT_WIDTH_12 DWBW(11) /*!< bit width of the wave signal is 12 */ + +/* unmask LFSR bits in DAC LFSR noise mode */ +#define DAC_LFSR_BIT0 DAC_WAVE_BIT_WIDTH_1 /*!< unmask the LFSR bit0 */ +#define DAC_LFSR_BITS1_0 DAC_WAVE_BIT_WIDTH_2 /*!< unmask the LFSR bits[1:0] */ +#define DAC_LFSR_BITS2_0 DAC_WAVE_BIT_WIDTH_3 /*!< unmask the LFSR bits[2:0] */ +#define DAC_LFSR_BITS3_0 DAC_WAVE_BIT_WIDTH_4 /*!< unmask the LFSR bits[3:0] */ +#define DAC_LFSR_BITS4_0 DAC_WAVE_BIT_WIDTH_5 /*!< unmask the LFSR bits[4:0] */ +#define DAC_LFSR_BITS5_0 DAC_WAVE_BIT_WIDTH_6 /*!< unmask the LFSR bits[5:0] */ +#define DAC_LFSR_BITS6_0 DAC_WAVE_BIT_WIDTH_7 /*!< unmask the LFSR bits[6:0] */ +#define DAC_LFSR_BITS7_0 DAC_WAVE_BIT_WIDTH_8 /*!< unmask the LFSR bits[7:0] */ +#define DAC_LFSR_BITS8_0 DAC_WAVE_BIT_WIDTH_9 /*!< unmask the LFSR bits[8:0] */ +#define DAC_LFSR_BITS9_0 DAC_WAVE_BIT_WIDTH_10 /*!< unmask the LFSR bits[9:0] */ +#define DAC_LFSR_BITS10_0 DAC_WAVE_BIT_WIDTH_11 /*!< unmask the LFSR bits[10:0] */ +#define DAC_LFSR_BITS11_0 DAC_WAVE_BIT_WIDTH_12 /*!< unmask the LFSR bits[11:0] */ + +/* triangle amplitude in DAC triangle noise mode */ +#define DAC_TRIANGLE_AMPLITUDE_1 DAC_WAVE_BIT_WIDTH_1 /*!< triangle amplitude is 1 */ +#define DAC_TRIANGLE_AMPLITUDE_3 DAC_WAVE_BIT_WIDTH_2 /*!< triangle amplitude is 3 */ +#define DAC_TRIANGLE_AMPLITUDE_7 DAC_WAVE_BIT_WIDTH_3 /*!< triangle amplitude is 7 */ +#define DAC_TRIANGLE_AMPLITUDE_15 DAC_WAVE_BIT_WIDTH_4 /*!< triangle amplitude is 15 */ +#define DAC_TRIANGLE_AMPLITUDE_31 DAC_WAVE_BIT_WIDTH_5 /*!< triangle amplitude is 31 */ +#define DAC_TRIANGLE_AMPLITUDE_63 DAC_WAVE_BIT_WIDTH_6 /*!< triangle amplitude is 63 */ +#define DAC_TRIANGLE_AMPLITUDE_127 DAC_WAVE_BIT_WIDTH_7 /*!< triangle amplitude is 127 */ +#define DAC_TRIANGLE_AMPLITUDE_255 DAC_WAVE_BIT_WIDTH_8 /*!< triangle amplitude is 255 */ +#define DAC_TRIANGLE_AMPLITUDE_511 DAC_WAVE_BIT_WIDTH_9 /*!< triangle amplitude is 511 */ +#define DAC_TRIANGLE_AMPLITUDE_1023 DAC_WAVE_BIT_WIDTH_10 /*!< triangle amplitude is 1023 */ +#define DAC_TRIANGLE_AMPLITUDE_2047 DAC_WAVE_BIT_WIDTH_11 /*!< triangle amplitude is 2047 */ +#define DAC_TRIANGLE_AMPLITUDE_4095 DAC_WAVE_BIT_WIDTH_12 /*!< triangle amplitude is 4095 */ + +/* DAC data alignment */ +#define DATA_ALIGN(regval) (BITS(0,1) & ((uint32_t)(regval) << 0)) +#define DAC_ALIGN_12B_R DATA_ALIGN(0) /*!< data right 12b alignment */ +#define DAC_ALIGN_12B_L DATA_ALIGN(1) /*!< data left 12b alignment */ +#define DAC_ALIGN_8B_R DATA_ALIGN(2) /*!< data right 8b alignment */ + +/* function declarations */ +/* initialization functions */ +/* deinitialize DAC */ +void dac_deinit(void); +/* enable DAC */ +void dac_enable(uint32_t dac_periph); +/* disable DAC */ +void dac_disable(uint32_t dac_periph); +/* enable DAC DMA */ +void dac_dma_enable(uint32_t dac_periph); +/* disable DAC DMA */ +void dac_dma_disable(uint32_t dac_periph); +/* enable DAC output buffer */ +void dac_output_buffer_enable(uint32_t dac_periph); +/* disable DAC output buffer */ +void dac_output_buffer_disable(uint32_t dac_periph); +/* get the last data output value */ +uint16_t dac_output_value_get(uint32_t dac_periph); +/* set DAC data holding register value */ +void dac_data_set(uint32_t dac_periph, uint32_t dac_align, uint16_t data); + +/* function configuration */ +/* DAC trigger configuration */ +/* enable DAC trigger */ +void dac_trigger_enable(uint32_t dac_periph); +/* disable DAC trigger */ +void dac_trigger_disable(uint32_t dac_periph); +/* configure DAC trigger source */ +void dac_trigger_source_config(uint32_t dac_periph, uint32_t triggersource); +/* enable DAC software trigger */ +void dac_software_trigger_enable(uint32_t dac_periph); +/* disable DAC software trigger */ +void dac_software_trigger_disable(uint32_t dac_periph); + +/* DAC wave mode configuration */ +/* configure DAC wave mode */ +void dac_wave_mode_config(uint32_t dac_periph, uint32_t wave_mode); +/* configure DAC wave bit width */ +void dac_wave_bit_width_config(uint32_t dac_periph, uint32_t bit_width); +/* configure DAC LFSR noise mode */ +void dac_lfsr_noise_config(uint32_t dac_periph, uint32_t unmask_bits); +/* configure DAC triangle noise mode */ +void dac_triangle_noise_config(uint32_t dac_periph, uint32_t amplitude); + +/* DAC concurrent mode configuration */ +/* enable DAC concurrent mode */ +void dac_concurrent_enable(void); +/* disable DAC concurrent mode */ +void dac_concurrent_disable(void); +/* enable DAC concurrent software trigger */ +void dac_concurrent_software_trigger_enable(void); +/* disable DAC concurrent software trigger */ +void dac_concurrent_software_trigger_disable(void); +/* enable DAC concurrent buffer function */ +void dac_concurrent_output_buffer_enable(void); +/* disable DAC concurrent buffer function */ +void dac_concurrent_output_buffer_disable(void); +/* set DAC concurrent mode data holding register value */ +void dac_concurrent_data_set(uint32_t dac_align, uint16_t data0, uint16_t data1); + +#endif /* GD32F20X_DAC_H */ diff --git a/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_standard_peripheral/Include/gd32f20x_dbg.h b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_standard_peripheral/Include/gd32f20x_dbg.h new file mode 100644 index 0000000000..39c37464d1 --- /dev/null +++ b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_standard_peripheral/Include/gd32f20x_dbg.h @@ -0,0 +1,146 @@ +/*! + \file gd32f20x_dbg.h + \brief definitions for the DBG + + \version 2015-07-15, V1.0.0, firmware for GD32F20x + \version 2017-06-05, V2.0.0, firmware for GD32F20x + \version 2018-10-31, V2.1.0, firmware for GD32F20x + \version 2020-09-30, V2.2.0, firmware for GD32F20x + \version 2020-12-14, V2.2.1, firmware for GD32F20x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef GD32F20X_DBG_H +#define GD32F20X_DBG_H + +#include "gd32f20x.h" + +/* DBG definitions */ +#define DBG DBG_BASE + +/* registers definitions */ +#define DBG_ID REG32(DBG + 0x00U) /*!< DBG_ID code register */ +#define DBG_CTL REG32(DBG + 0x04U) /*!< DBG control register */ + +/* bits definitions */ +/* DBG_ID */ +#define DBG_ID_ID_CODE BITS(0,31) /*!< DBG ID code values */ + +/* DBG_CTL */ +#define DBG_CTL_SLP_HOLD BIT(0) /*!< keep debugger connection during sleep mode */ +#define DBG_CTL_DSLP_HOLD BIT(1) /*!< keep debugger connection during deepsleep mode */ +#define DBG_CTL_STB_HOLD BIT(2) /*!< keep debugger connection during standby mode */ +#define DBG_CTL_TRACE_IOEN BIT(5) /*!< enable trace pin assignment */ +#define DBG_CTL_TRACE_MODE BITS(6,7) /*!< trace pin mode selection */ +#define DBG_CTL_FWDGT_HOLD BIT(8) /*!< debug FWDGT kept when core is halted */ +#define DBG_CTL_WWDGT_HOLD BIT(9) /*!< debug WWDGT kept when core is halted */ +#define DBG_CTL_TIMER0_HOLD BIT(10) /*!< hold TIMER0 counter when core is halted */ +#define DBG_CTL_TIMER1_HOLD BIT(11) /*!< hold TIMER1 counter when core is halted */ +#define DBG_CTL_TIMER2_HOLD BIT(12) /*!< hold TIMER2 counter when core is halted */ +#define DBG_CTL_TIMER3_HOLD BIT(13) /*!< hold TIMER3 counter when core is halted */ +#define DBG_CTL_CAN0_HOLD BIT(14) /*!< debug CAN0 kept when core is halted */ +#define DBG_CTL_I2C0_HOLD BIT(15) /*!< hold I2C0 smbus when core is halted */ +#define DBG_CTL_I2C1_HOLD BIT(16) /*!< hold I2C1 smbus when core is halted */ +#define DBG_CTL_TIMER7_HOLD BIT(17) /*!< hold TIMER7 counter when core is halted */ +#define DBG_CTL_TIMER4_HOLD BIT(18) /*!< hold TIMER4 counter when core is halted */ +#define DBG_CTL_TIMER5_HOLD BIT(19) /*!< hold TIMER5 counter when core is halted */ +#define DBG_CTL_TIMER6_HOLD BIT(20) /*!< hold TIMER6 counter when core is halted */ +#define DBG_CTL_CAN1_HOLD BIT(21) /*!< debug CAN1 kept when core is halted */ +#define DBG_CTL_TIMER11_HOLD BIT(25) /*!< hold TIMER11 counter when core is halted */ +#define DBG_CTL_TIMER12_HOLD BIT(26) /*!< hold TIMER12 counter when core is halted */ +#define DBG_CTL_TIMER13_HOLD BIT(27) /*!< hold TIMER13 counter when core is halted */ +#define DBG_CTL_TIMER8_HOLD BIT(28) /*!< hold TIMER8 counter when core is halted */ +#define DBG_CTL_TIMER9_HOLD BIT(29) /*!< hold TIMER9 counter when core is halted */ +#define DBG_CTL_TIMER10_HOLD BIT(30) /*!< hold TIMER10 counter when core is halted */ + +/* constants definitions */ +/* debug hold when core is halted */ +typedef enum +{ + DBG_FWDGT_HOLD = BIT(8), /*!< debug FWDGT kept when core is halted */ + DBG_WWDGT_HOLD = BIT(9), /*!< debug WWDGT kept when core is halted */ + DBG_TIMER0_HOLD = BIT(10), /*!< hold TIMER0 counter when core is halted */ + DBG_TIMER1_HOLD = BIT(11), /*!< hold TIMER1 counter when core is halted */ + DBG_TIMER2_HOLD = BIT(12), /*!< hold TIMER2 counter when core is halted */ + DBG_TIMER3_HOLD = BIT(13), /*!< hold TIMER3 counter when core is halted */ + DBG_CAN0_HOLD = BIT(14), /*!< debug CAN0 kept when core is halted */ + DBG_I2C0_HOLD = BIT(15), /*!< hold I2C0 smbus when core is halted */ + DBG_I2C1_HOLD = BIT(16), /*!< hold I2C1 smbus when core is halted */ + DBG_TIMER7_HOLD = BIT(17), /*!< hold TIMER7 counter when core is halted */ + DBG_TIMER4_HOLD = BIT(18), /*!< hold TIMER4 counter when core is halted */ + DBG_TIMER5_HOLD = BIT(19), /*!< hold TIMER5 counter when core is halted */ + DBG_TIMER6_HOLD = BIT(20), /*!< hold TIMER6 counter when core is halted */ + DBG_CAN1_HOLD = BIT(21), /*!< debug CAN1 kept when core is halted */ + DBG_TIMER11_HOLD = BIT(25), /*!< hold TIMER11 counter when core is halted */ + DBG_TIMER12_HOLD = BIT(26), /*!< hold TIMER12 counter when core is halted */ + DBG_TIMER13_HOLD = BIT(27), /*!< hold TIMER13 counter when core is halted */ + DBG_TIMER8_HOLD = BIT(28), /*!< hold TIMER8 counter when core is halted */ + DBG_TIMER9_HOLD = BIT(29), /*!< hold TIMER9 counter when core is halted */ + DBG_TIMER10_HOLD = BIT(30), /*!< hold TIMER10 counter when core is halted */ +}dbg_periph_enum; + +/* DBG low power mode configurations */ +#define DBG_LOW_POWER_SLEEP DBG_CTL_SLP_HOLD /*!< keep debugger connection during sleep mode */ +#define DBG_LOW_POWER_DEEPSLEEP DBG_CTL_DSLP_HOLD /*!< keep debugger connection during deepsleep mode */ +#define DBG_LOW_POWER_STANDBY DBG_CTL_STB_HOLD /*!< keep debugger connection during standby mode */ + +/* DBG_CTL0_TRACE_MODE configurations */ +#define CTL_TRACE_MODE(regval) (BITS(6,7) & ((uint32_t)(regval) << 6U)) +#define TRACE_MODE_ASYNC CTL_TRACE_MODE(0) /*!< trace pin used for async mode */ +#define TRACE_MODE_SYNC_DATASIZE_1 CTL_TRACE_MODE(1) /*!< trace pin used for sync mode and data size is 1 */ +#define TRACE_MODE_SYNC_DATASIZE_2 CTL_TRACE_MODE(2) /*!< trace pin used for sync mode and data size is 2 */ +#define TRACE_MODE_SYNC_DATASIZE_4 CTL_TRACE_MODE(3) /*!< trace pin used for sync mode and data size is 4 */ + +/* function declarations */ +/* initialization functions */ +/* read DBG_ID code register */ +uint32_t dbg_id_get(void); + +/* function configuration */ +/* low power behavior configuration */ +/* enable low power behavior when the MCU is in debug mode */ +void dbg_low_power_enable(uint32_t dbg_low_power); +/* disable low power behavior when the MCU is in debug mode */ +void dbg_low_power_disable(uint32_t dbg_low_power); + +/* peripheral behavior configuration */ +/* enable peripheral behavior when the MCU is in debug mode */ +void dbg_periph_enable(dbg_periph_enum dbg_periph); +/* disable peripheral behavior when the MCU is in debug mode */ +void dbg_periph_disable(dbg_periph_enum dbg_periph); + +/* trace pin assignment configuration */ +/* enable trace pin assignment */ +void dbg_trace_pin_enable(void); +/* disable trace pin assignment */ +void dbg_trace_pin_disable(void); +/* set trace pin mode */ +void dbg_trace_pin_mode_set(uint32_t trace_mode); + +#endif /* GD32F20X_DBG_H */ diff --git a/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_standard_peripheral/Include/gd32f20x_dci.h b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_standard_peripheral/Include/gd32f20x_dci.h new file mode 100644 index 0000000000..868a64364d --- /dev/null +++ b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_standard_peripheral/Include/gd32f20x_dci.h @@ -0,0 +1,236 @@ +/*! + \file gd32f20x_dci.h + \brief definitions for the DCI + + \version 2015-07-15, V1.0.0, firmware for GD32F20x + \version 2017-06-05, V2.0.0, firmware for GD32F20x + \version 2018-10-31, V2.1.0, firmware for GD32F20x + \version 2020-09-30, V2.2.0, firmware for GD32F20x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef GD32F20X_DCI_H +#define GD32F20X_DCI_H + +#include "gd32f20x.h" + +/* DCI definitions */ +#define DCI DCI_BASE + +/* registers definitions */ +#define DCI_CTL REG32(DCI + 0x00U) /*!< DCI control register */ +#define DCI_STAT0 REG32(DCI + 0x04U) /*!< DCI status register 0 */ +#define DCI_STAT1 REG32(DCI + 0x08U) /*!< DCI status register 1 */ +#define DCI_INTEN REG32(DCI + 0x0CU) /*!< DCI interrupt enable register */ +#define DCI_INTF REG32(DCI + 0x10U) /*!< DCI interrupt flag register */ +#define DCI_INTC REG32(DCI + 0x14U) /*!< DCI interrupt clear register */ +#define DCI_SC REG32(DCI + 0x18U) /*!< DCI synchronization codes register */ +#define DCI_SCUMSK REG32(DCI + 0x1CU) /*!< DCI synchronization codes unmask register */ +#define DCI_CWSPOS REG32(DCI + 0x20U) /*!< DCI cropping window start position register */ +#define DCI_CWSZ REG32(DCI + 0x24U) /*!< DCI cropping window size register */ +#define DCI_DATA REG32(DCI + 0x28U) /*!< DCI data register */ + +/* bits definitions */ +/* DCI_CTL */ +#define DCI_CTL_CAP BIT(0) /*!< capture enable */ +#define DCI_CTL_SNAP BIT(1) /*!< snapshot mode */ +#define DCI_CTL_WDEN BIT(2) /*!< window enable */ +#define DCI_CTL_JM BIT(3) /*!< JPEG mode */ +#define DCI_CTL_ESM BIT(4) /*!< embedded synchronous mode */ +#define DCI_CTL_CKS BIT(5) /*!< clock polarity selection */ +#define DCI_CTL_HPS BIT(6) /*!< horizontal polarity selection */ +#define DCI_CTL_VPS BIT(7) /*!< vertical polarity selection */ +#define DCI_CTL_FR BITS(8,9) /*!< frame rate */ +#define DCI_CTL_DCIF BITS(10,11) /*!< digital camera interface format */ +#define DCI_CTL_DCIEN BIT(14) /*!< DCI enable */ + +/* DCI_STAT0 */ +#define DCI_STAT0_HS BIT(0) /*!< HS line status */ +#define DCI_STAT0_VS BIT(1) /*!< VS line status */ +#define DCI_STAT0_FV BIT(2) /*!< FIFO valid */ + +/* DCI_STAT1 */ +#define DCI_STAT1_EFF BIT(0) /*!< end of frame flag */ +#define DCI_STAT1_OVRF BIT(1) /*!< FIFO overrun flag */ +#define DCI_STAT1_ESEF BIT(2) /*!< embedded synchronous error flag */ +#define DCI_STAT1_VSF BIT(3) /*!< vsync flag */ +#define DCI_STAT1_ELF BIT(4) /*!< end of line flag */ + +/* DCI_INTEN */ +#define DCI_INTEN_EFIE BIT(0) /*!< end of frame interrupt enable */ +#define DCI_INTEN_OVRIE BIT(1) /*!< FIFO overrun interrupt enable */ +#define DCI_INTEN_ESEIE BIT(2) /*!< embedded synchronous error interrupt enable */ +#define DCI_INTEN_VSIE BIT(3) /*!< vsync interrupt enable */ +#define DCI_INTEN_ELIE BIT(4) /*!< end of line interrupt enable */ + +/* DCI_INTF */ +#define DCI_INTF_EFIF BIT(0) /*!< end of frame interrupt flag */ +#define DCI_INTF_OVRIF BIT(1) /*!< FIFO overrun interrupt flag */ +#define DCI_INTF_ESEIF BIT(2) /*!< embedded synchronous error interrupt flag */ +#define DCI_INTF_VSIF BIT(3) /*!< vsync interrupt flag */ +#define DCI_INTF_ELIF BIT(4) /*!< end of line interrupt flag */ + +/* DCI_INTC */ +#define DCI_INTC_EFFC BIT(0) /*!< clear end of frame flag */ +#define DCI_INTC_OVRFC BIT(1) /*!< clear FIFO overrun flag */ +#define DCI_INTC_ESEFC BIT(2) /*!< clear embedded synchronous error flag */ +#define DCI_INTC_VSFC BIT(3) /*!< vsync flag clear */ +#define DCI_INTC_ELFC BIT(4) /*!< end of line flag clear */ + +/* DCI_SC */ +#define DCI_SC_FS BITS(0,7) /*!< frame start code in embedded synchronous mode */ +#define DCI_SC_LS BITS(8,15) /*!< line start code in embedded synchronous mode */ +#define DCI_SC_LE BITS(16,23) /*!< line end code in embedded synchronous mode */ +#define DCI_SC_FE BITS(24,31) /*!< frame end code in embedded synchronous mode */ + +/* DCI_SCUNMSK */ +#define DCI_SCUMSK_FSM BITS(0,7) /*!< frame start code unmask bits in embedded synchronous mode */ +#define DCI_SCUMSK_LSM BITS(8,15) /*!< line start code unmask bits in embedded synchronous mode */ +#define DCI_SCUMSK_LEM BITS(16,23) /*!< line end code unmask bits in embedded synchronous mode */ +#define DCI_SCUMSK_FEM BITS(24,31) /*!< frame end code unmask bits in embedded synchronous mode */ + +/* DCI_CWSPOS */ +#define DCI_CWSPOS_WHSP BITS(0,13) /*!< window horizontal start position */ +#define DCI_CWSPOS_WVSP BITS(16,28) /*!< window vertical start position */ + +/* DCI_CWSZ */ +#define DCI_CWSZ_WHSZ BITS(0,13) /*!< window horizontal size */ +#define DCI_CWSZ_WVSZ BITS(16,29) /*!< window vertical size */ + +/* constants definitions */ +/* DCI parameter structure definitions */ +typedef struct +{ + uint32_t capture_mode; /*!< DCI capture mode: continuous or snapshot */ + uint32_t clock_polarity; /*!< clock polarity selection */ + uint32_t hsync_polarity; /*!< horizontal polarity selection */ + uint32_t vsync_polarity; /*!< vertical polarity selection */ + uint32_t frame_rate; /*!< frame capture rate */ + uint32_t interface_format; /*!< digital camera interface format */ +}dci_parameter_struct; + +#define DCI_CAPTURE_MODE_CONTINUOUS ((uint32_t)0x00000000U) /*!< continuous capture mode */ +#define DCI_CAPTURE_MODE_SNAPSHOT DCI_CTL_SNAP /*!< snapshot capture mode */ + +#define DCI_CK_POLARITY_FALLING ((uint32_t)0x00000000U) /*!< capture at falling edge */ +#define DCI_CK_POLARITY_RISING DCI_CTL_CKS /*!< capture at rising edge */ + +#define DCI_HSYNC_POLARITY_LOW ((uint32_t)0x00000000U) /*!< low level during blanking period */ +#define DCI_HSYNC_POLARITY_HIGH DCI_CTL_HPS /*!< high level during blanking period */ + +#define DCI_VSYNC_POLARITY_LOW ((uint32_t)0x00000000U) /*!< low level during blanking period */ +#define DCI_VSYNC_POLARITY_HIGH DCI_CTL_VPS /*!< high level during blanking period*/ + +#define CTL_FR(regval) (BITS(8,9)&((uint32_t)(regval) << 8U)) +#define DCI_FRAME_RATE_ALL CTL_FR(0) /*!< capture all frames */ +#define DCI_FRAME_RATE_1_2 CTL_FR(1) /*!< capture one in 2 frames */ +#define DCI_FRAME_RATE_1_4 CTL_FR(2) /*!< capture one in 4 frames */ + +#define CTL_DCIF(regval) (BITS(10,11)&((uint32_t)(regval) << 10U)) +#define DCI_INTERFACE_FORMAT_8BITS CTL_DCIF(0) /*!< 8-bit data on every pixel clock */ +#define DCI_INTERFACE_FORMAT_10BITS CTL_DCIF(1) /*!< 10-bit data on every pixel clock */ +#define DCI_INTERFACE_FORMAT_12BITS CTL_DCIF(2) /*!< 12-bit data on every pixel clock */ +#define DCI_INTERFACE_FORMAT_14BITS CTL_DCIF(3) /*!< 14-bit data on every pixel clock */ + +/* DCI interrupt constants definitions */ +#define DCI_INT_EF BIT(0) /*!< end of frame interrupt */ +#define DCI_INT_OVR BIT(1) /*!< FIFO overrun interrupt */ +#define DCI_INT_ESE BIT(2) /*!< embedded synchronous error interrupt */ +#define DCI_INT_VSYNC BIT(3) /*!< vsync interrupt */ +#define DCI_INT_EL BIT(4) /*!< end of line interrupt */ + +/* DCI interrupt flag definitions */ +#define DCI_INT_FLAG_EF BIT(0) /*!< end of frame interrupt flag */ +#define DCI_INT_FLAG_OVR BIT(1) /*!< FIFO overrun interrupt flag */ +#define DCI_INT_FLAG_ESE BIT(2) /*!< embedded synchronous error interrupt flag */ +#define DCI_INT_FLAG_VSYNC BIT(3) /*!< vsync interrupt flag */ +#define DCI_INT_FLAG_EL BIT(4) /*!< end of line interrupt flag */ + +/* DCI flag definitions */ +#define DCI_FLAG_HS DCI_STAT0_HS /*!< HS line status */ +#define DCI_FLAG_VS DCI_STAT0_VS /*!< VS line status */ +#define DCI_FLAG_FV DCI_STAT0_FV /*!< FIFO valid */ +#define DCI_FLAG_EF (DCI_STAT1_EFF | BIT(31)) /*!< end of frame flag */ +#define DCI_FLAG_OVR (DCI_STAT1_OVRF | BIT(31)) /*!< FIFO overrun flag */ +#define DCI_FLAG_ESE (DCI_STAT1_ESEF | BIT(31)) /*!< embedded synchronous error flag */ +#define DCI_FLAG_VSYNC (DCI_STAT1_VSF | BIT(31)) /*!< vsync flag */ +#define DCI_FLAG_EL (DCI_STAT1_ELF | BIT(31)) /*!< end of line flag */ + +/* function declarations */ +/* initialization functions */ +/* DCI deinit */ +void dci_deinit(void); +/* initialize DCI registers */ +void dci_init(dci_parameter_struct* dci_struct); + +/* enable DCI function */ +void dci_enable(void); +/* disable DCI function */ +void dci_disable(void); +/* enable DCI capture */ +void dci_capture_enable(void); +/* disable DCI capture */ +void dci_capture_disable(void); +/* enable DCI jpeg mode */ +void dci_jpeg_enable(void); +/* disable DCI jpeg mode */ +void dci_jpeg_disable(void); + +/* function configuration */ +/* enable cropping window function */ +void dci_crop_window_enable(void); +/* disable cropping window function */ +void dci_crop_window_disable(void); +/* configure DCI cropping window */ +void dci_crop_window_config(uint16_t start_x, uint16_t start_y, uint16_t size_width, uint16_t size_height); + +/* enable embedded synchronous mode */ +void dci_embedded_sync_enable(void); +/* disable embedded synchronous mode */ +void dci_embedded_sync_disable(void); +/* configure synchronous codes in embedded synchronous mode */ +void dci_sync_codes_config(uint8_t frame_start, uint8_t line_start, uint8_t line_end, uint8_t frame_end); +/* configure synchronous codes unmask in embedded synchronous mode */ +void dci_sync_codes_unmask_config(uint8_t frame_start, uint8_t line_start, uint8_t line_end, uint8_t frame_end); +/* read DCI data register */ +uint32_t dci_data_read(void); + +/* interrupt & flag functions */ +/* get specified flag */ +FlagStatus dci_flag_get(uint32_t flag); +/* enable specified DCI interrupt */ +void dci_interrupt_enable(uint32_t interrupt); +/* disable specified DCI interrupt */ +void dci_interrupt_disable(uint32_t interrupt); +/* get specified interrupt flag */ +FlagStatus dci_interrupt_flag_get(uint32_t int_flag); +/* clear specified interrupt flag */ +void dci_interrupt_flag_clear(uint32_t int_flag); + +#endif /* GD32F20X_DCI_H */ diff --git a/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_standard_peripheral/Include/gd32f20x_dma.h b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_standard_peripheral/Include/gd32f20x_dma.h new file mode 100644 index 0000000000..bc52e95db5 --- /dev/null +++ b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_standard_peripheral/Include/gd32f20x_dma.h @@ -0,0 +1,300 @@ +/*! + \file gd32f20x_dma.h + \brief definitions for the DMA + + \version 2015-07-15, V1.0.0, firmware for GD32F20x + \version 2017-06-05, V2.0.0, firmware for GD32F20x + \version 2018-10-31, V2.1.0, firmware for GD32F20x + \version 2020-09-30, V2.2.0, firmware for GD32F20x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef GD32F20X_DMA_H +#define GD32F20X_DMA_H + +#include "gd32f20x.h" + +/* DMA definitions */ +#define DMA0 (DMA_BASE) /*!< DMA0 base address */ +#define DMA1 (DMA_BASE + 0x0400U) /*!< DMA1 base address */ + +/* registers definitions */ +#define DMA_INTF(dmax) REG32((dmax) + 0x00U) /*!< DMA interrupt flag register */ +#define DMA_INTC(dmax) REG32((dmax) + 0x04U) /*!< DMA interrupt flag clear register */ + +#define DMA_CH0CTL(dmax) REG32((dmax) + 0x08U) /*!< DMA channel 0 control register */ +#define DMA_CH0CNT(dmax) REG32((dmax) + 0x0CU) /*!< DMA channel 0 counter register */ +#define DMA_CH0PADDR(dmax) REG32((dmax) + 0x10U) /*!< DMA channel 0 peripheral base address register */ +#define DMA_CH0MADDR(dmax) REG32((dmax) + 0x14U) /*!< DMA channel 0 memory base address register */ + +#define DMA_CH1CTL(dmax) REG32((dmax) + 0x1CU) /*!< DMA channel 1 control register */ +#define DMA_CH1CNT(dmax) REG32((dmax) + 0x20U) /*!< DMA channel 1 counter register */ +#define DMA_CH1PADDR(dmax) REG32((dmax) + 0x24U) /*!< DMA channel 1 peripheral base address register */ +#define DMA_CH1MADDR(dmax) REG32((dmax) + 0x28U) /*!< DMA channel 1 memory base address register */ + +#define DMA_CH2CTL(dmax) REG32((dmax) + 0x30U) /*!< DMA channel 2 control register */ +#define DMA_CH2CNT(dmax) REG32((dmax) + 0x34U) /*!< DMA channel 2 counter register */ +#define DMA_CH2PADDR(dmax) REG32((dmax) + 0x38U) /*!< DMA channel 2 peripheral base address register */ +#define DMA_CH2MADDR(dmax) REG32((dmax) + 0x3CU) /*!< DMA channel 2 memory base address register */ + +#define DMA_CH3CTL(dmax) REG32((dmax) + 0x44U) /*!< DMA channel 3 control register */ +#define DMA_CH3CNT(dmax) REG32((dmax) + 0x48U) /*!< DMA channel 3 counter register */ +#define DMA_CH3PADDR(dmax) REG32((dmax) + 0x4CU) /*!< DMA channel 3 peripheral base address register */ +#define DMA_CH3MADDR(dmax) REG32((dmax) + 0x50U) /*!< DMA channel 3 memory base address register */ + +#define DMA_CH4CTL(dmax) REG32((dmax) + 0x58U) /*!< DMA channel 4 control register */ +#define DMA_CH4CNT(dmax) REG32((dmax) + 0x5CU) /*!< DMA channel 4 counter register */ +#define DMA_CH4PADDR(dmax) REG32((dmax) + 0x60U) /*!< DMA channel 4 peripheral base address register */ +#define DMA_CH4MADDR(dmax) REG32((dmax) + 0x64U) /*!< DMA channel 4 memory base address register */ + +#define DMA_CH5CTL(dmax) REG32((dmax) + 0x6CU) /*!< DMA channel 5 control register */ +#define DMA_CH5CNT(dmax) REG32((dmax) + 0x70U) /*!< DMA channel 5 counter register */ +#define DMA_CH5PADDR(dmax) REG32((dmax) + 0x74U) /*!< DMA channel 5 peripheral base address register */ +#define DMA_CH5MADDR(dmax) REG32((dmax) + 0x78U) /*!< DMA channel 5 memory base address register */ + +#define DMA_CH6CTL(dmax) REG32((dmax) + 0x80U) /*!< DMA channel 6 control register */ +#define DMA_CH6CNT(dmax) REG32((dmax) + 0x84U) /*!< DMA channel 6 counter register */ +#define DMA_CH6PADDR(dmax) REG32((dmax) + 0x88U) /*!< DMA channel 6 peripheral base address register */ +#define DMA_CH6MADDR(dmax) REG32((dmax) + 0x8CU) /*!< DMA channel 6 memory base address register */ + +#define DMA_ACFG REG32((DMA1) + 0x300U) /*!< DMA additional configuration register */ + +/* bits definitions */ +/* DMA_INTF */ +#define DMA_INTF_GIF BIT(0) /*!< global interrupt flag of channel */ +#define DMA_INTF_FTFIF BIT(1) /*!< full transfer finish flag of channel */ +#define DMA_INTF_HTFIF BIT(2) /*!< half transfer finish flag of channel */ +#define DMA_INTF_ERRIF BIT(3) /*!< error flag of channel */ + +/* DMA_INTC */ +#define DMA_INTC_GIFC BIT(0) /*!< clear global interrupt flag of channel */ +#define DMA_INTC_FTFIFC BIT(1) /*!< clear transfer finish flag of channel */ +#define DMA_INTC_HTFIFC BIT(2) /*!< clear half transfer finish flag of channel */ +#define DMA_INTC_ERRIFC BIT(3) /*!< clear error flag of channel */ + +/* DMA_CHxCTL, x=0..6 */ +#define DMA_CHXCTL_CHEN BIT(0) /*!< channel enable */ +#define DMA_CHXCTL_FTFIE BIT(1) /*!< enable bit for channel full transfer finish interrupt */ +#define DMA_CHXCTL_HTFIE BIT(2) /*!< enable bit for channel half transfer finish interrupt */ +#define DMA_CHXCTL_ERRIE BIT(3) /*!< enable bit for channel error interrupt */ +#define DMA_CHXCTL_DIR BIT(4) /*!< transfer direction */ +#define DMA_CHXCTL_CMEN BIT(5) /*!< circular mode enable */ +#define DMA_CHXCTL_PNAGA BIT(6) /*!< next address generation algorithm of peripheral */ +#define DMA_CHXCTL_MNAGA BIT(7) /*!< next address generation algorithm of memory */ +#define DMA_CHXCTL_PWIDTH BITS(8,9) /*!< transfer data width of peripheral */ +#define DMA_CHXCTL_MWIDTH BITS(10,11) /*!< transfer data width of memory */ +#define DMA_CHXCTL_PRIO BITS(12,13) /*!< priority level */ +#define DMA_CHXCTL_M2M BIT(14) /*!< memory to memory mode */ + +/* DMA_CHxCNT, x=0..6 */ +#define DMA_CHXCNT_CNT BITS(0,15) /*!< transfer counter */ + +/* DMA_CHxPADDR, x=0..6 */ +#define DMA_CHXPADDR_PADDR BITS(0,31) /*!< peripheral base address */ + +/* DMA_CHxMADDR, x=0..6 */ +#define DMA_CHXMADDR_MADDR BITS(0,31) /*!< memory base address */ + +/* DMA_ACFG */ +#define DMA_ACFG_FD_CH5EN BIT(5) /*!< enable bit for DMA1 channel 5 Full_Data transfer mode */ + +/* constants definitions */ +/* DMA channel select */ +typedef enum +{ + DMA_CH0 = 0, /*!< DMA channel 0 */ + DMA_CH1, /*!< DMA channel 1 */ + DMA_CH2, /*!< DMA channel 2 */ + DMA_CH3, /*!< DMA channel 3 */ + DMA_CH4, /*!< DMA channel 4 */ + DMA_CH5, /*!< DMA channel 5 */ + DMA_CH6 /*!< DMA channel 6 */ +} dma_channel_enum; + +/* DMA initialize struct */ +typedef struct +{ + uint32_t periph_addr; /*!< peripheral base address */ + uint32_t periph_width; /*!< transfer data size of peripheral */ + uint32_t memory_addr; /*!< memory base address */ + uint32_t memory_width; /*!< transfer data size of memory */ + uint32_t number; /*!< channel transfer number */ + uint32_t priority; /*!< channel priority level */ + uint8_t periph_inc; /*!< peripheral increasing mode */ + uint8_t memory_inc; /*!< memory increasing mode */ + uint8_t direction; /*!< channel data transfer direction */ + +} dma_parameter_struct; + +#define DMA_FLAG_ADD(flag, shift) ((flag) << ((shift) * 4U)) /*!< DMA channel flag shift */ + +/* DMA_register address */ +#define DMA_CHCTL(dma, channel) REG32(((dma) + 0x08U) + 0x14U * (uint32_t)(channel)) /*!< the address of DMA channel CHXCTL register */ +#define DMA_CHCNT(dma, channel) REG32(((dma) + 0x0CU) + 0x14U * (uint32_t)(channel)) /*!< the address of DMA channel CHXCNT register */ +#define DMA_CHPADDR(dma, channel) REG32(((dma) + 0x10U) + 0x14U * (uint32_t)(channel)) /*!< the address of DMA channel CHXPADDR register */ +#define DMA_CHMADDR(dma, channel) REG32(((dma) + 0x14U) + 0x14U * (uint32_t)(channel)) /*!< the address of DMA channel CHXMADDR register */ + +/* DMA reset value */ +#define DMA_CHCTL_RESET_VALUE ((uint32_t)0x00000000U) /*!< the reset value of DMA channel CHXCTL register */ +#define DMA_CHCNT_RESET_VALUE ((uint32_t)0x00000000U) /*!< the reset value of DMA channel CHXCNT register */ +#define DMA_CHPADDR_RESET_VALUE ((uint32_t)0x00000000U) /*!< the reset value of DMA channel CHXPADDR register */ +#define DMA_CHMADDR_RESET_VALUE ((uint32_t)0x00000000U) /*!< the reset value of DMA channel CHXMADDR register */ +#define DMA_CHINTF_RESET_VALUE (DMA_INTF_GIF | DMA_INTF_FTFIF | \ + DMA_INTF_HTFIF | DMA_INTF_ERRIF) /*!< clear DMA channel DMA_INTF register */ +#define DMA_ACFG_RESET_VALUE ((uint32_t)0x00000000U) /*!< the reset value of DMA additional configuration register */ + +/* DMA_INTF register */ +/* interrupt flag bits */ +#define DMA_INT_FLAG_G DMA_INTF_GIF /*!< global interrupt flag of channel */ +#define DMA_INT_FLAG_FTF DMA_INTF_FTFIF /*!< full transfer finish interrupt flag of channel */ +#define DMA_INT_FLAG_HTF DMA_INTF_HTFIF /*!< half transfer finish interrupt flag of channel */ +#define DMA_INT_FLAG_ERR DMA_INTF_ERRIF /*!< error interrupt flag of channel */ + +/* flag bits */ +#define DMA_FLAG_G DMA_INTF_GIF /*!< global interrupt flag of channel */ +#define DMA_FLAG_FTF DMA_INTF_FTFIF /*!< full transfer finish flag of channel */ +#define DMA_FLAG_HTF DMA_INTF_HTFIF /*!< half transfer finish flag of channel */ +#define DMA_FLAG_ERR DMA_INTF_ERRIF /*!< error flag of channel */ + +/* DMA_CHxCTL register */ +/* interrupt enable bits */ +#define DMA_INT_FTF DMA_CHXCTL_FTFIE /*!< enable bit for channel full transfer finish interrupt */ +#define DMA_INT_HTF DMA_CHXCTL_HTFIE /*!< enable bit for channel half transfer finish interrupt */ +#define DMA_INT_ERR DMA_CHXCTL_ERRIE /*!< enable bit for channel error interrupt */ + +/* transfer direction */ +#define DMA_PERIPHERAL_TO_MEMORY ((uint8_t)0x00U) /*!< read from peripheral and write to memory */ +#define DMA_MEMORY_TO_PERIPHERAL ((uint8_t)0x01U) /*!< read from memory and write to peripheral */ + +/* circular mode */ +#define DMA_CIRCULAR_MODE_DISABLE ((uint32_t)0x00000000U) /*!< circular mode disable */ +#define DMA_CIRCULAR_MODE_ENABLE ((uint32_t)0x00000001U) /*!< circular mode enable */ + +/* peripheral increasing mode */ +#define DMA_PERIPH_INCREASE_DISABLE ((uint8_t)0x00U) /*!< next address of peripheral is fixed address mode */ +#define DMA_PERIPH_INCREASE_ENABLE ((uint8_t)0x01U) /*!< next address of peripheral is increasing address mode */ + +/* memory increasing mode */ +#define DMA_MEMORY_INCREASE_DISABLE ((uint8_t)0x00U) /*!< next address of memory is fixed address mode */ +#define DMA_MEMORY_INCREASE_ENABLE ((uint8_t)0x01U) /*!< next address of memory is increasing address mode */ + +/* transfer data size of peripheral */ +#define CHCTL_PWIDTH(regval) (BITS(8,9) & ((regval) << 8)) /*!< transfer data size of peripheral */ +#define DMA_PERIPHERAL_WIDTH_8BIT CHCTL_PWIDTH(0U) /*!< transfer data size of peripheral is 8-bit */ +#define DMA_PERIPHERAL_WIDTH_16BIT CHCTL_PWIDTH(1U) /*!< transfer data size of peripheral is 16-bit */ +#define DMA_PERIPHERAL_WIDTH_32BIT CHCTL_PWIDTH(2U) /*!< transfer data size of peripheral is 32-bit */ + +/* transfer data size of memory */ +#define CHCTL_MWIDTH(regval) (BITS(10,11) & ((regval) << 10)) /*!< transfer data size of memory */ +#define DMA_MEMORY_WIDTH_8BIT CHCTL_MWIDTH(0U) /*!< transfer data size of memory is 8-bit */ +#define DMA_MEMORY_WIDTH_16BIT CHCTL_MWIDTH(1U) /*!< transfer data size of memory is 16-bit */ +#define DMA_MEMORY_WIDTH_32BIT CHCTL_MWIDTH(2U) /*!< transfer data size of memory is 32-bit */ + +/* channel priority level */ +#define CHCTL_PRIO(regval) (BITS(12,13) & ((regval) << 12)) /*!< DMA channel priority level */ +#define DMA_PRIORITY_LOW CHCTL_PRIO(0U) /*!< low priority */ +#define DMA_PRIORITY_MEDIUM CHCTL_PRIO(1U) /*!< medium priority */ +#define DMA_PRIORITY_HIGH CHCTL_PRIO(2U) /*!< high priority */ +#define DMA_PRIORITY_ULTRA_HIGH CHCTL_PRIO(3U) /*!< ultra high priority */ + +/* memory to memory mode */ +#define DMA_MEMORY_TO_MEMORY_DISABLE ((uint32_t)0x00000000U) /*!< disable memory to memory mode */ +#define DMA_MEMORY_TO_MEMORY_ENABLE ((uint32_t)0x00000001U) /*!< enable memory to memory mode */ + +/* DMA_CHxCNT register */ +/* transfer counter */ +#define DMA_CHANNEL_CNT_MASK DMA_CHXCNT_CNT /*!< transfer counter mask */ + +/* function declarations */ +/* initialization functions */ +/* deinitialize DMA a channel registers */ +void dma_deinit(uint32_t dma_periph, dma_channel_enum channelx); +/* initialize the parameters of DMA structure with the default values */ +void dma_struct_para_init(dma_parameter_struct* init_struct); +/* initialize DMA channel */ +void dma_init(uint32_t dma_periph, dma_channel_enum channelx, dma_parameter_struct *init_struct); +/* enable DMA circulation mode */ +void dma_circulation_enable(uint32_t dma_periph, dma_channel_enum channelx); +/* disable DMA circulation mode */ +void dma_circulation_disable(uint32_t dma_periph, dma_channel_enum channelx); +/* enable memory to memory mode */ +void dma_memory_to_memory_enable(uint32_t dma_periph, dma_channel_enum channelx); +/* disable memory to memory mode */ +void dma_memory_to_memory_disable(uint32_t dma_periph, dma_channel_enum channelx); +/* enable DMA channel */ +void dma_channel_enable(uint32_t dma_periph, dma_channel_enum channelx); +/* disable DMA channel */ +void dma_channel_disable(uint32_t dma_periph, dma_channel_enum channelx); + +/* DMA configuration functions */ +/* set DMA peripheral base address */ +void dma_periph_address_config(uint32_t dma_periph, dma_channel_enum channelx, uint32_t address); +/* set DMA memory base address */ +void dma_memory_address_config(uint32_t dma_periph, dma_channel_enum channelx, uint32_t address); +/* set the number of remaining data to be transferred by the DMA */ +void dma_transfer_number_config(uint32_t dma_periph, dma_channel_enum channelx, uint32_t number); +/* get the number of remaining data to be transferred by the DMA */ +uint32_t dma_transfer_number_get(uint32_t dma_periph, dma_channel_enum channelx); +/* configure priority level of DMA channel */ +void dma_priority_config(uint32_t dma_periph, dma_channel_enum channelx, uint32_t priority); +/* configure transfer data size of memory */ +void dma_memory_width_config(uint32_t dma_periph, dma_channel_enum channelx, uint32_t mwidth); +/* configure transfer data size of peripheral */ +void dma_periph_width_config(uint32_t dma_periph, dma_channel_enum channelx, uint32_t pwidth); +/* enable next address increment algorithm of memory */ +void dma_memory_increase_enable(uint32_t dma_periph, dma_channel_enum channelx); +/* disable next address increment algorithm of memory */ +void dma_memory_increase_disable(uint32_t dma_periph, dma_channel_enum channelx); +/* enable next address increment algorithm of peripheral */ +void dma_periph_increase_enable(uint32_t dma_periph, dma_channel_enum channelx); +/* disable next address increment algorithm of peripheral */ +void dma_periph_increase_disable(uint32_t dma_periph, dma_channel_enum channelx); +/* configure the direction of data transfer on the channel */ +void dma_transfer_direction_config(uint32_t dma_periph, dma_channel_enum channelx, uint8_t direction); + +/* flag and interrupt functions */ +/* check DMA flag is set or not */ +FlagStatus dma_flag_get(uint32_t dma_periph, dma_channel_enum channelx, uint32_t flag); +/* clear the flag of a DMA channel */ +void dma_flag_clear(uint32_t dma_periph, dma_channel_enum channelx, uint32_t flag); +/* check DMA flag and interrupt enable bit is set or not */ +FlagStatus dma_interrupt_flag_get(uint32_t dma_periph, dma_channel_enum channelx, uint32_t flag); +/* clear the interrupt flag of a DMA channel */ +void dma_interrupt_flag_clear(uint32_t dma_periph, dma_channel_enum channelx, uint32_t flag); +/* enable DMA interrupt */ +void dma_interrupt_enable(uint32_t dma_periph, dma_channel_enum channelx, uint32_t source); +/* disable DMA interrupt */ +void dma_interrupt_disable(uint32_t dma_periph, dma_channel_enum channelx, uint32_t source); + +/* enable the DMA1 channel 5 Full_Data transfer mode */ +void dma_1_channel_5_fulldata_transfer_enable(void); +/* disable the DMA1 channel 5 Full_Data transfer mode */ +void dma_1_channel_5_fulldata_transfer_disable(void); + +#endif /* GD32F20X_DMA_H */ diff --git a/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_standard_peripheral/Include/gd32f20x_enet.h b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_standard_peripheral/Include/gd32f20x_enet.h new file mode 100644 index 0000000000..d18dd4761b --- /dev/null +++ b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_standard_peripheral/Include/gd32f20x_enet.h @@ -0,0 +1,1499 @@ +/*! + \file gd32f20x_enet.h + \brief definitions for the ENET + + \version 2015-07-15, V1.0.0, firmware for GD32F20x + \version 2017-06-05, V2.0.0, firmware for GD32F20x + \version 2018-10-31, V2.1.0, firmware for GD32F20x + \version 2020-09-30, V2.2.0, firmware for GD32F20x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef GD32F20X_ENET_H +#define GD32F20X_ENET_H + +#include "gd32f20x.h" +#include + +#define IF_USE_EXTERNPHY_LIB 0 +#if (1 == IF_USE_EXTERNPHY_LIB) +#include "phy.h" +#endif + +#ifndef ENET_RXBUF_NUM +#define ENET_RXBUF_NUM 5U /*!< ethernet Rx DMA descriptor number */ +#endif + +#ifndef ENET_TXBUF_NUM +#define ENET_TXBUF_NUM 5U /*!< ethernet Tx DMA descriptor number */ +#endif + +#ifndef ENET_RXBUF_SIZE +#define ENET_RXBUF_SIZE ENET_MAX_FRAME_SIZE /*!< ethernet receive buffer size */ +#endif + +#ifndef ENET_TXBUF_SIZE +#define ENET_TXBUF_SIZE ENET_MAX_FRAME_SIZE /*!< ethernet transmit buffer size */ +#endif + +/* #define USE_DELAY */ + +#ifndef _PHY_H_ +#define DP83848 0 +#define LAN8700 1 +#define PHY_TYPE DP83848 + +#define PHY_ADDRESS ((uint16_t)1U) /*!< phy address determined by the hardware */ + +/* PHY read write timeouts */ +#define PHY_READ_TO ((uint32_t)0x0004FFFFU) /*!< PHY read timeout */ +#define PHY_WRITE_TO ((uint32_t)0x0004FFFFU) /*!< PHY write timeout */ + +/* PHY delay */ +#define PHY_RESETDELAY ((uint32_t)0x008FFFFFU) /*!< PHY reset delay */ +#define PHY_CONFIGDELAY ((uint32_t)0x00FFFFFFU) /*!< PHY configure delay */ + +/* PHY register address */ +#define PHY_REG_BCR 0U /*!< tranceiver basic control register */ +#define PHY_REG_BSR 1U /*!< tranceiver basic status register */ + +/* PHY basic control register */ +#define PHY_RESET ((uint16_t)0x8000) /*!< PHY reset */ +#define PHY_LOOPBACK ((uint16_t)0x4000) /*!< enable phy loop-back mode */ +#define PHY_FULLDUPLEX_100M ((uint16_t)0x2100) /*!< configure speed to 100 Mbit/s and the full-duplex mode */ +#define PHY_HALFDUPLEX_100M ((uint16_t)0x2000) /*!< configure speed to 100 Mbit/s and the half-duplex mode */ +#define PHY_FULLDUPLEX_10M ((uint16_t)0x0100) /*!< configure speed to 10 Mbit/s and the full-duplex mode */ +#define PHY_HALFDUPLEX_10M ((uint16_t)0x0000) /*!< configure speed to 10 Mbit/s and the half-duplex mode */ +#define PHY_AUTONEGOTIATION ((uint16_t)0x1000) /*!< enable auto-negotiation function */ +#define PHY_RESTART_AUTONEGOTIATION ((uint16_t)0x0200) /*!< restart auto-negotiation function */ +#define PHY_POWERDOWN ((uint16_t)0x0800) /*!< enable the power down mode */ +#define PHY_ISOLATE ((uint16_t)0x0400) /*!< isolate PHY from MII */ + +/* PHY basic status register */ +#define PHY_AUTONEGO_COMPLETE ((uint16_t)0x0020) /*!< auto-negotioation process completed */ +#define PHY_LINKED_STATUS ((uint16_t)0x0004) /*!< valid link established */ +#define PHY_JABBER_DETECTION ((uint16_t)0x0002) /*!< jabber condition detected */ + +#if(PHY_TYPE == LAN8700) +#define PHY_SR 31U /*!< tranceiver status register */ +#define PHY_SPEED_STATUS ((uint16_t)0x0004) /*!< configured information of speed: 10Mbit/s */ +#define PHY_DUPLEX_STATUS ((uint16_t)0x0010) /*!< configured information of duplex: full-duplex */ +#elif(PHY_TYPE == DP83848) +#define PHY_SR 16U /*!< tranceiver status register */ +#define PHY_SPEED_STATUS ((uint16_t)0x0002) /*!< configured information of speed: 10Mbit/s */ +#define PHY_DUPLEX_STATUS ((uint16_t)0x0004) /*!< configured information of duplex: full-duplex */ +#endif /* PHY_TYPE */ + +#endif /* _PHY_H_ */ + + +/* ENET definitions */ +#define ENET ENET_BASE + +/* registers definitions */ +#define ENET_MAC_CFG REG32((ENET) + 0x00U) /*!< ethernet MAC configuration register */ +#define ENET_MAC_FRMF REG32((ENET) + 0x04U) /*!< ethernet MAC frame filter register */ +#define ENET_MAC_HLH REG32((ENET) + 0x08U) /*!< ethernet MAC hash list high register */ +#define ENET_MAC_HLL REG32((ENET) + 0x0CU) /*!< ethernet MAC hash list low register */ +#define ENET_MAC_PHY_CTL REG32((ENET) + 0x10U) /*!< ethernet MAC PHY control register */ +#define ENET_MAC_PHY_DATA REG32((ENET) + 0x14U) /*!< ethernet MAC MII data register */ +#define ENET_MAC_FCTL REG32((ENET) + 0x18U) /*!< ethernet MAC flow control register */ +#define ENET_MAC_FCTH REG32((ENET) + 0x1080U) /*!< ethernet MAC flow control threshold register */ +#define ENET_MAC_VLT REG32((ENET) + 0x1CU) /*!< ethernet MAC VLAN tag register */ +#define ENET_MAC_RWFF REG32((ENET) + 0x28U) /*!< ethernet MAC remote wakeup frame filter register */ +#define ENET_MAC_WUM REG32((ENET) + 0x2CU) /*!< ethernet MAC wakeup management register */ +#define ENET_MAC_INTF REG32((ENET) + 0x38U) /*!< ethernet MAC interrupt flag register */ +#define ENET_MAC_INTMSK REG32((ENET) + 0x3CU) /*!< ethernet MAC interrupt mask register */ +#define ENET_MAC_ADDR0H REG32((ENET) + 0x40U) /*!< ethernet MAC address 0 high register */ +#define ENET_MAC_ADDR0L REG32((ENET) + 0x44U) /*!< ethernet MAC address 0 low register */ +#define ENET_MAC_ADDR1H REG32((ENET) + 0x48U) /*!< ethernet MAC address 1 high register */ +#define ENET_MAC_ADDR1L REG32((ENET) + 0x4CU) /*!< ethernet MAC address 1 low register */ +#define ENET_MAC_ADDT2H REG32((ENET) + 0x50U) /*!< ethernet MAC address 2 high register */ +#define ENET_MAC_ADDR2L REG32((ENET) + 0x54U) /*!< ethernet MAC address 2 low register */ +#define ENET_MAC_ADDR3H REG32((ENET) + 0x58U) /*!< ethernet MAC address 3 high register */ +#define ENET_MAC_ADDR3L REG32((ENET) + 0x5CU) /*!< ethernet MAC address 3 low register */ + +#define ENET_MSC_CTL REG32((ENET) + 0x100U) /*!< ethernet MSC control register */ +#define ENET_MSC_RINTF REG32((ENET) + 0x104U) /*!< ethernet MSC receive interrupt flag register */ +#define ENET_MSC_TINTF REG32((ENET) + 0x108U) /*!< ethernet MSC transmit interrupt flag register */ +#define ENET_MSC_RINTMSK REG32((ENET) + 0x10CU) /*!< ethernet MSC receive interrupt mask register */ +#define ENET_MSC_TINTMSK REG32((ENET) + 0x110U) /*!< ethernet MSC transmit interrupt mask register */ +#define ENET_MSC_SCCNT REG32((ENET) + 0x14CU) /*!< ethernet MSC transmitted good frames after a single collision counter register */ +#define ENET_MSC_MSCCNT REG32((ENET) + 0x150U) /*!< ethernet MSC transmitted good frames after more than a single collision counter register */ +#define ENET_MSC_TGFCNT REG32((ENET) + 0x168U) /*!< ethernet MSC transmitted good frames counter register */ +#define ENET_MSC_RFCECNT REG32((ENET) + 0x194U) /*!< ethernet MSC received frames with CRC error counter register */ +#define ENET_MSC_RFAECNT REG32((ENET) + 0x198U) /*!< ethernet MSC received frames with alignment error counter register */ +#define ENET_MSC_RGUFCNT REG32((ENET) + 0x1C4U) /*!< ethernet MSC received good unicast frames counter register */ + +#define ENET_PTP_TSCTL REG32((ENET) + 0x700U) /*!< ethernet PTP time stamp control register */ +#define ENET_PTP_SSINC REG32((ENET) + 0x704U) /*!< ethernet PTP subsecond increment register */ +#define ENET_PTP_TSH REG32((ENET) + 0x708U) /*!< ethernet PTP time stamp high register */ +#define ENET_PTP_TSL REG32((ENET) + 0x70CU) /*!< ethernet PTP time stamp low register */ +#define ENET_PTP_TSUH REG32((ENET) + 0x710U) /*!< ethernet PTP time stamp update high register */ +#define ENET_PTP_TSUL REG32((ENET) + 0x714U) /*!< ethernet PTP time stamp update low register */ +#define ENET_PTP_TSADDEND REG32((ENET) + 0x718U) /*!< ethernet PTP time stamp addend register */ +#define ENET_PTP_ETH REG32((ENET) + 0x71CU) /*!< ethernet PTP expected time high register */ +#define ENET_PTP_ETL REG32((ENET) + 0x720U) /*!< ethernet PTP expected time low register */ + +#define ENET_DMA_BCTL REG32((ENET) + 0x1000U) /*!< ethernet DMA bus control register */ +#define ENET_DMA_TPEN REG32((ENET) + 0x1004U) /*!< ethernet DMA transmit poll enable register */ +#define ENET_DMA_RPEN REG32((ENET) + 0x1008U) /*!< ethernet DMA receive poll enable register */ +#define ENET_DMA_RDTADDR REG32((ENET) + 0x100CU) /*!< ethernet DMA receive descriptor table address register */ +#define ENET_DMA_TDTADDR REG32((ENET) + 0x1010U) /*!< ethernet DMA transmit descriptor table address register */ +#define ENET_DMA_STAT REG32((ENET) + 0x1014U) /*!< ethernet DMA status register */ +#define ENET_DMA_CTL REG32((ENET) + 0x1018U) /*!< ethernet DMA control register */ +#define ENET_DMA_INTEN REG32((ENET) + 0x101CU) /*!< ethernet DMA interrupt enable register */ +#define ENET_DMA_MFBOCNT REG32((ENET) + 0x1020U) /*!< ethernet DMA missed frame and buffer overflow counter register */ +#define ENET_DMA_CTDADDR REG32((ENET) + 0x1048U) /*!< ethernet DMA current transmit descriptor address register */ +#define ENET_DMA_CRDADDR REG32((ENET) + 0x104CU) /*!< ethernet DMA current receive descriptor address register */ +#define ENET_DMA_CTBADDR REG32((ENET) + 0x1050U) /*!< ethernet DMA current transmit buffer address register */ +#define ENET_DMA_CRBADDR REG32((ENET) + 0x1054U) /*!< ethernet DMA current receive buffer address register */ + +/* bits definitions */ +/* ENET_MAC_CFG */ +#define ENET_MAC_CFG_REN BIT(2) /*!< receiver enable */ +#define ENET_MAC_CFG_TEN BIT(3) /*!< transmitter enable */ +#define ENET_MAC_CFG_DFC BIT(4) /*!< defferal check */ +#define ENET_MAC_CFG_BOL BITS(5,6) /*!< back-off limit */ +#define ENET_MAC_CFG_APCD BIT(7) /*!< automatic pad/CRC drop */ +#define ENET_MAC_CFG_RTD BIT(9) /*!< retry disable */ +#define ENET_MAC_CFG_IPFCO BIT(10) /*!< IP frame checksum offload */ +#define ENET_MAC_CFG_DPM BIT(11) /*!< duplex mode */ +#define ENET_MAC_CFG_LBM BIT(12) /*!< loopback mode */ +#define ENET_MAC_CFG_ROD BIT(13) /*!< receive own disable */ +#define ENET_MAC_CFG_SPD BIT(14) /*!< fast eneternet speed */ +#define ENET_MAC_CFG_CSD BIT(16) /*!< carrier sense disable */ +#define ENET_MAC_CFG_IGBS BITS(17,19) /*!< inter-frame gap bit selection */ +#define ENET_MAC_CFG_JBD BIT(22) /*!< jabber disable */ +#define ENET_MAC_CFG_WDD BIT(23) /*!< watchdog disable */ + +/* ENET_MAC_FRMF */ +#define ENET_MAC_FRMF_PM BIT(0) /*!< promiscuous mode */ +#define ENET_MAC_FRMF_HUF BIT(1) /*!< hash unicast filter */ +#define ENET_MAC_FRMF_HMF BIT(2) /*!< hash multicast filter */ +#define ENET_MAC_FRMF_DAIFLT BIT(3) /*!< destination address inverse filtering enable */ +#define ENET_MAC_FRMF_MFD BIT(4) /*!< multicast filter disable */ +#define ENET_MAC_FRMF_BFRMD BIT(5) /*!< broadcast frame disable */ +#define ENET_MAC_FRMF_PCFRM BITS(6,7) /*!< pass control frames */ +#define ENET_MAC_FRMF_SAIFLT BIT(8) /*!< source address inverse filtering */ +#define ENET_MAC_FRMF_SAFLT BIT(9) /*!< source address filter */ +#define ENET_MAC_FRMF_HPFLT BIT(10) /*!< hash or perfect filter */ +#define ENET_MAC_FRMF_FAR BIT(31) /*!< frames all receive */ + +/* ENET_MAC_HLH */ +#define ENET_MAC_HLH_HLH BITS(0,31) /*!< hash list high */ + +/* ENET_MAC_HLL */ +#define ENET_MAC_HLL_HLL BITS(0,31) /*!< hash list low */ + +/* ENET_MAC_PHY_CTL */ +#define ENET_MAC_PHY_CTL_PB BIT(0) /*!< PHY busy */ +#define ENET_MAC_PHY_CTL_PW BIT(1) /*!< PHY write */ +#define ENET_MAC_PHY_CTL_CLR BITS(2,4) /*!< clock range */ +#define ENET_MAC_PHY_CTL_PR BITS(6,10) /*!< PHY register */ +#define ENET_MAC_PHY_CTL_PA BITS(11,15) /*!< PHY address */ + +/* ENET_MAC_PHY_DATA */ +#define ENET_MAC_PHY_DATA_PD BITS(0,15) /*!< PHY data */ + +/* ENET_MAC_FCTL */ +#define ENET_MAC_FCTL_FLCBBKPA BIT(0) /*!< flow control busy(in full duplex mode)/backpressure activate(in half duplex mode) */ +#define ENET_MAC_FCTL_TFCEN BIT(1) /*!< transmit flow control enable */ +#define ENET_MAC_FCTL_RFCEN BIT(2) /*!< receive flow control enable */ +#define ENET_MAC_FCTL_UPFDT BIT(3) /*!< unicast pause frame detect */ +#define ENET_MAC_FCTL_PLTS BITS(4,5) /*!< pause low threshold */ +#define ENET_MAC_FCTL_DZQP BIT(7) /*!< disable zero-quanta pause */ +#define ENET_MAC_FCTL_PTM BITS(16,31) /*!< pause time */ + +/* ENET_MAC_FCTH */ +#define ENET_MAC_FCTH_RFA BITS(0,2) /*!< threshold of active flow control */ +#define ENET_MAC_FCTH_RFD BITS(4,6) /*!< threshold of deactive flow control */ + +/* ENET_MAC_VLT */ +#define ENET_MAC_VLT_VLTI BITS(0,15) /*!< VLAN tag identifier(for receive frames) */ +#define ENET_MAC_VLT_VLTC BIT(16) /*!< 12-bit VLAN tag comparison */ + +/* ENET_MAC_RWFF */ +#define ENET_MAC_RWFF_DATA BITS(0,31) /*!< wakeup frame filter register data */ + +/* ENET_MAC_WUM */ +#define ENET_MAC_WUM_PWD BIT(0) /*!< power down */ +#define ENET_MAC_WUM_MPEN BIT(1) /*!< magic packet enable */ +#define ENET_MAC_WUM_WFEN BIT(2) /*!< wakeup frame enable */ +#define ENET_MAC_WUM_MPKR BIT(5) /*!< magic packet received */ +#define ENET_MAC_WUM_WUFR BIT(6) /*!< wakeup frame received */ +#define ENET_MAC_WUM_GU BIT(9) /*!< global unicast */ +#define ENET_MAC_WUM_WUFFRPR BIT(31) /*!< wakeup frame filter register pointer reset */ + +/* ENET_MAC_INTF */ +#define ENET_MAC_INTF_WUM BIT(3) /*!< WUM status */ +#define ENET_MAC_INTF_MSC BIT(4) /*!< MSC status */ +#define ENET_MAC_INTF_MSCR BIT(5) /*!< MSC receive status */ +#define ENET_MAC_INTF_MSCT BIT(6) /*!< MSC transmit status */ +#define ENET_MAC_INTF_TMST BIT(9) /*!< timestamp trigger status */ + +/* ENET_MAC_INTMSK */ +#define ENET_MAC_INTMSK_WUMIM BIT(3) /*!< WUM interrupt mask */ +#define ENET_MAC_INTMSK_TMSTIM BIT(9) /*!< timestamp trigger interrupt mask */ + +/* ENET_MAC_ADDR0H */ +#define ENET_MAC_ADDR0H_ADDR0H BITS(0,15) /*!< MAC address0 high */ +#define ENET_MAC_ADDR0H_MO BIT(31) /*!< always read 1 and must be kept */ + +/* ENET_MAC_ADDR0L */ +#define ENET_MAC_ADDR0L_ADDR0L BITS(0,31) /*!< MAC address0 low */ + +/* ENET_MAC_ADDR1H */ +#define ENET_MAC_ADDR1H_ADDR1H BITS(0,15) /*!< MAC address1 high */ +#define ENET_MAC_ADDR1H_MB BITS(24,29) /*!< mask byte */ +#define ENET_MAC_ADDR1H_SAF BIT(30) /*!< source address filter */ +#define ENET_MAC_ADDR1H_AFE BIT(31) /*!< address filter enable */ + +/* ENET_MAC_ADDR1L */ +#define ENET_MAC_ADDR1L_ADDR1L BITS(0,31) /*!< MAC address1 low */ + +/* ENET_MAC_ADDR2H */ +#define ENET_MAC_ADDR2H_ADDR2H BITS(0,15) /*!< MAC address2 high */ +#define ENET_MAC_ADDR2H_MB BITS(24,29) /*!< mask byte */ +#define ENET_MAC_ADDR2H_SAF BIT(30) /*!< source address filter */ +#define ENET_MAC_ADDR2H_AFE BIT(31) /*!< address filter enable */ + +/* ENET_MAC_ADDR2L */ +#define ENET_MAC_ADDR2L_ADDR2L BITS(0,31) /*!< MAC address2 low */ + +/* ENET_MAC_ADDR3H */ +#define ENET_MAC_ADDR3H_ADDR3H BITS(0,15) /*!< MAC address3 high */ +#define ENET_MAC_ADDR3H_MB BITS(24,29) /*!< mask byte */ +#define ENET_MAC_ADDR3H_SAF BIT(30) /*!< source address filter */ +#define ENET_MAC_ADDR3H_AFE BIT(31) /*!< address filter enable */ + +/* ENET_MAC_ADDR3L */ +#define ENET_MAC_ADDR3L_ADDR3L BITS(0,31) /*!< MAC address3 low */ + +/* ENET_MSC_CTL */ +#define ENET_MSC_CTL_CTR BIT(0) /*!< counter reset */ +#define ENET_MSC_CTL_CTSR BIT(1) /*!< counter stop rollover */ +#define ENET_MSC_CTL_RTOR BIT(2) /*!< reset on read */ +#define ENET_MSC_CTL_MCFZ BIT(3) /*!< MSC counter freeze */ + +/* ENET_MSC_RINTF */ +#define ENET_MSC_RINTF_RFCE BIT(5) /*!< received frames CRC error */ +#define ENET_MSC_RINTF_RFAE BIT(6) /*!< received frames alignment error */ +#define ENET_MSC_RINTF_RGUF BIT(17) /*!< receive good unicast frames */ + +/* ENET_MSC_TINTF */ +#define ENET_MSC_TINTF_TGFSC BIT(14) /*!< transmitted good frames single collision */ +#define ENET_MSC_TINTF_TGFMSC BIT(15) /*!< transmitted good frames more single collision */ +#define ENET_MSC_TINTF_TGF BIT(21) /*!< transmitted good frames */ + +/* ENET_MSC_RINTMSK */ +#define ENET_MSC_RINTMSK_RFCEIM BIT(5) /*!< received frame CRC error interrupt mask */ +#define ENET_MSC_RINTMSK_RFAEIM BIT(6) /*!< received frames alignment error interrupt mask */ +#define ENET_MSC_RINTMSK_RGUFIM BIT(17) /*!< received good unicast frames interrupt mask */ + +/* ENET_MSC_TINTMSK */ +#define ENET_MSC_TINTMSK_TGFSCIM BIT(14) /*!< transmitted good frames single collision interrupt mask */ +#define ENET_MSC_TINTMSK_TGFMSCIM BIT(15) /*!< transmitted good frames more single collision interrupt mask */ +#define ENET_MSC_TINTMSK_TGFIM BIT(21) /*!< transmitted good frames interrupt mask */ + +/* ENET_MSC_SCCNT */ +#define ENET_MSC_SCCNT_SCC BITS(0,31) /*!< transmitted good frames single collision counter */ + +/* ENET_MSC_MSCCNT */ +#define ENET_MSC_MSCCNT_MSCC BITS(0,31) /*!< transmitted good frames more one single collision counter */ + +/* ENET_MSC_TGFCNT */ +#define ENET_MSC_TGFCNT_TGF BITS(0,31) /*!< transmitted good frames counter */ + +/* ENET_MSC_RFCECNT */ +#define ENET_MSC_RFCECNT_RFCER BITS(0,31) /*!< received frames with CRC error counter */ + +/* ENET_MSC_RFAECNT */ +#define ENET_MSC_RFAECNT_RFAER BITS(0,31) /*!< received frames alignment error counter */ + +/* ENET_MSC_RGUFCNT */ +#define ENET_MSC_RGUFCNT_RGUF BITS(0,31) /*!< received good unicast frames counter */ + +/* ENET_PTP_TSCTL */ +#define ENET_PTP_TSCTL_TMSEN BIT(0) /*!< timestamp enable */ +#define ENET_PTP_TSCTL_TMSFCU BIT(1) /*!< timestamp fine or coarse update */ +#define ENET_PTP_TSCTL_TMSSTI BIT(2) /*!< timestamp system time initialize */ +#define ENET_PTP_TSCTL_TMSSTU BIT(3) /*!< timestamp system time update */ +#define ENET_PTP_TSCTL_TMSITEN BIT(4) /*!< timestamp interrupt trigger enable */ +#define ENET_PTP_TSCTL_TMSARU BIT(5) /*!< timestamp addend register update */ + +/* ENET_PTP_SSINC */ +#define ENET_PTP_SSINC_STMSSI BITS(0,7) /*!< system time subsecond increment */ + +/* ENET_PTP_TSH */ +#define ENET_PTP_TSH_STMS BITS(0,31) /*!< system time second */ + +/* ENET_PTP_TSL */ +#define ENET_PTP_TSL_STMSS BITS(0,30) /*!< system time subseconds */ +#define ENET_PTP_TSL_STS BIT(31) /*!< system time sign */ + +/* ENET_PTP_TSUH */ +#define ENET_PTP_TSUH_TMSUS BITS(0,31) /*!< timestamp update seconds */ + +/* ENET_PTP_TSUL */ +#define ENET_PTP_TSUL_TMSUSS BITS(0,30) /*!< timestamp update subseconds */ +#define ENET_PTP_TSUL_TMSUPNS BIT(31) /*!< timestamp update positive or negative sign */ + +/* ENET_PTP_TSADDEND */ +#define ENET_PTP_TSADDEND_TMSA BITS(0,31) /*!< timestamp addend */ + +/* ENET_PTP_ETH */ +#define ENET_PTP_ETH_ETSH BITS(0,31) /*!< expected time high */ + +/* ENET_PTP_ETL */ +#define ENET_PTP_ETL_ETSL BITS(0,31) /*!< expected time low */ + +/* ENET_DMA_BCTL */ +#define ENET_DMA_BCTL_SWR BIT(0) /*!< software reset */ +#define ENET_DMA_BCTL_DAB BIT(1) /*!< DMA arbitration */ +#define ENET_DMA_BCTL_DPSL BITS(2,6) /*!< descriptor skip length */ +#define ENET_DMA_BCTL_PGBL BITS(8,13) /*!< programmable burst length */ +#define ENET_DMA_BCTL_RTPR BITS(14,15) /*!< RxDMA and TxDMA transfer priority ratio */ +#define ENET_DMA_BCTL_FB BIT(16) /*!< fixed Burst */ +#define ENET_DMA_BCTL_RXDP BITS(17,22) /*!< RxDMA PGBL */ +#define ENET_DMA_BCTL_UIP BIT(23) /*!< use independent PGBL */ +#define ENET_DMA_BCTL_FPBL BIT(24) /*!< four times PGBL mode */ +#define ENET_DMA_BCTL_AA BIT(25) /*!< address-aligned */ + +/* ENET_DMA_TPEN */ +#define ENET_DMA_TPEN_TPE BITS(0,31) /*!< transmit poll enable */ + +/* ENET_DMA_RPEN */ +#define ENET_DMA_RPEN_RPE BITS(0,31) /*!< receive poll enable */ + +/* ENET_DMA_RDTADDR */ +#define ENET_DMA_RDTADDR_SRT BITS(0,31) /*!< start address of receive table */ + +/* ENET_DMA_TDTADDR */ +#define ENET_DMA_TDTADDR_STT BITS(0,31) /*!< start address of transmit table */ + +/* ENET_DMA_STAT */ +#define ENET_DMA_STAT_TS BIT(0) /*!< transmit status */ +#define ENET_DMA_STAT_TPS BIT(1) /*!< transmit process stopped status */ +#define ENET_DMA_STAT_TBU BIT(2) /*!< transmit buffer unavailable status */ +#define ENET_DMA_STAT_TJT BIT(3) /*!< transmit jabber timeout status */ +#define ENET_DMA_STAT_RO BIT(4) /*!< receive overflow status */ +#define ENET_DMA_STAT_TU BIT(5) /*!< transmit underflow status */ +#define ENET_DMA_STAT_RS BIT(6) /*!< receive status */ +#define ENET_DMA_STAT_RBU BIT(7) /*!< receive buffer unavailable status */ +#define ENET_DMA_STAT_RPS BIT(8) /*!< receive process stopped status */ +#define ENET_DMA_STAT_RWT BIT(9) /*!< receive watchdog timeout status */ +#define ENET_DMA_STAT_ET BIT(10) /*!< early transmit status */ +#define ENET_DMA_STAT_FBE BIT(13) /*!< fatal bus error status */ +#define ENET_DMA_STAT_ER BIT(14) /*!< early receive status */ +#define ENET_DMA_STAT_AI BIT(15) /*!< abnormal interrupt summary */ +#define ENET_DMA_STAT_NI BIT(16) /*!< normal interrupt summary */ +#define ENET_DMA_STAT_RP BITS(17,19) /*!< receive process state */ +#define ENET_DMA_STAT_TP BITS(20,22) /*!< transmit process state */ +#define ENET_DMA_STAT_EB BITS(23,25) /*!< error bits status */ +#define ENET_DMA_STAT_MSC BIT(27) /*!< MSC status */ +#define ENET_DMA_STAT_WUM BIT(28) /*!< WUM status */ +#define ENET_DMA_STAT_TST BIT(29) /*!< timestamp trigger status */ + +/* ENET_DMA_CTL */ +#define ENET_DMA_CTL_SRE BIT(1) /*!< start/stop receive enable */ +#define ENET_DMA_CTL_OSF BIT(2) /*!< operate on second frame */ +#define ENET_DMA_CTL_RTHC BITS(3,4) /*!< receive threshold control */ +#define ENET_DMA_CTL_FUF BIT(6) /*!< forward undersized good frames */ +#define ENET_DMA_CTL_FERF BIT(7) /*!< forward error frames */ +#define ENET_DMA_CTL_STE BIT(13) /*!< start/stop transmission enable */ +#define ENET_DMA_CTL_TTHC BITS(14,16) /*!< transmit threshold control */ +#define ENET_DMA_CTL_FTF BIT(20) /*!< flush transmit FIFO */ +#define ENET_DMA_CTL_TSFD BIT(21) /*!< transmit store-and-forward */ +#define ENET_DMA_CTL_DAFRF BIT(24) /*!< disable flushing of received frames */ +#define ENET_DMA_CTL_RSFD BIT(25) /*!< receive store-and-forward */ +#define ENET_DMA_CTL_DTCERFD BIT(26) /*!< dropping of TCP/IP checksum error frames disable */ + +/* ENET_DMA_INTEN */ +#define ENET_DMA_INTEN_TIE BIT(0) /*!< transmit interrupt enable */ +#define ENET_DMA_INTEN_TPSIE BIT(1) /*!< transmit process stopped interrupt enable */ +#define ENET_DMA_INTEN_TBUIE BIT(2) /*!< transmit buffer unavailable interrupt enable */ +#define ENET_DMA_INTEN_TJTIE BIT(3) /*!< transmit jabber timeout interrupt enable */ +#define ENET_DMA_INTEN_ROIE BIT(4) /*!< receive overflow interrupt enable */ +#define ENET_DMA_INTEN_TUIE BIT(5) /*!< transmit underflow interrupt enable */ +#define ENET_DMA_INTEN_RIE BIT(6) /*!< receive interrupt enable */ +#define ENET_DMA_INTEN_RBUIE BIT(7) /*!< receive buffer unavailable interrupt enable */ +#define ENET_DMA_INTEN_RPSIE BIT(8) /*!< receive process stopped interrupt enable */ +#define ENET_DMA_INTEN_RWTIE BIT(9) /*!< receive watchdog timeout interrupt enable */ +#define ENET_DMA_INTEN_ETIE BIT(10) /*!< early transmit interrupt enable */ +#define ENET_DMA_INTEN_FBEIE BIT(13) /*!< fatal bus error interrupt enable */ +#define ENET_DMA_INTEN_ERIE BIT(14) /*!< early receive interrupt enable */ +#define ENET_DMA_INTEN_AIE BIT(15) /*!< abnormal interrupt summary enable */ +#define ENET_DMA_INTEN_NIE BIT(16) /*!< normal interrupt summary enable */ + +/* ENET_DMA_MFBOCNT */ +#define ENET_DMA_MFBOCNT_MSFC BITS(0,15) /*!< missed frames by the controller */ +#define ENET_DMA_MFBOCNT_OBMFC BIT(16) /*!< overflow bit for missed frame counter */ +#define ENET_DMA_MFBOCNT_MSFA BITS(17,27) /*!< missed frames by the application */ +#define ENET_DMA_MFBOCNT_OBFOC BIT(28) /*!< overflow bit for FIFO overflow counter */ + +/* ENET_DMA_CTDADDR */ +#define ENET_DMA_CTDADDR_TDAP BITS(0,31) /*!< transmit descriptor address pointer */ + +/* ENET_DMA_CRDADDR */ +#define ENET_DMA_CRDADDR_RDAP BITS(0,31) /*!< receive descriptor address pointer */ + +/* ENET_DMA_CTBADDR */ +#define ENET_DMA_CTBADDR_TBAP BITS(0,31) /*!< transmit buffer address pointer */ + +/* ENET_DMA_CRBADDR */ +#define ENET_DMA_CRBADDR_RBAP BITS(0,31) /*!< receive buffer address pointer */ + +/* ENET DMA Tx descriptor TDES0 */ +#define ENET_TDES0_DB BIT(0) /*!< deferred */ +#define ENET_TDES0_UFE BIT(1) /*!< underflow error */ +#define ENET_TDES0_EXD BIT(2) /*!< excessive deferral */ +#define ENET_TDES0_COCNT BITS(3,6) /*!< collision count */ +#define ENET_TDES0_VFRM BIT(7) /*!< VLAN frame */ +#define ENET_TDES0_ECO BIT(8) /*!< excessive collision */ +#define ENET_TDES0_LCO BIT(9) /*!< late collision */ +#define ENET_TDES0_NCA BIT(10) /*!< no carrier */ +#define ENET_TDES0_LCA BIT(11) /*!< loss of carrier */ +#define ENET_TDES0_IPPE BIT(12) /*!< IP payload error */ +#define ENET_TDES0_FRMF BIT(13) /*!< frame flushed */ +#define ENET_TDES0_JT BIT(14) /*!< jabber timeout */ +#define ENET_TDES0_ES BIT(15) /*!< error summary */ +#define ENET_TDES0_IPHE BIT(16) /*!< IP header error */ +#define ENET_TDES0_TTMSS BIT(17) /*!< transmit timestamp status */ +#define ENET_TDES0_TCHM BIT(20) /*!< the second address chained mode */ +#define ENET_TDES0_TERM BIT(21) /*!< transmit end of ring mode*/ +#define ENET_TDES0_CM BITS(22,23) /*!< checksum mode */ +#define ENET_TDES0_TTSEN BIT(25) /*!< transmit timestamp function enable */ +#define ENET_TDES0_DPAD BIT(26) /*!< disable adding pad */ +#define ENET_TDES0_DCRC BIT(27) /*!< disable CRC */ +#define ENET_TDES0_FSG BIT(28) /*!< first segment */ +#define ENET_TDES0_LSG BIT(29) /*!< last segment */ +#define ENET_TDES0_INTC BIT(30) /*!< interrupt on completion */ +#define ENET_TDES0_DAV BIT(31) /*!< DAV bit */ + +/* ENET DMA Tx descriptor TDES1 */ +#define ENET_TDES1_TB1S BITS(0,12) /*!< transmit buffer 1 size */ +#define ENET_TDES1_TB2S BITS(16,28) /*!< transmit buffer 2 size */ + +/* ENET DMA Tx descriptor TDES2 */ +#define ENET_TDES2_TB1AP BITS(0,31) /*!< transmit buffer 1 address pointer/transmit frame timestamp low 32-bit value */ + +/* ENET DMA Tx descriptor TDES3 */ +#define ENET_TDES3_TB2AP BITS(0,31) /*!< transmit buffer 2 address pointer (or next descriptor address) / transmit frame timestamp high 32-bit value */ + +/* ENET DMA Rx descriptor RDES0 */ +#define ENET_RDES0_PCERR BIT(0) /*!< payload checksum error */ +#define ENET_RDES0_CERR BIT(1) /*!< CRC error */ +#define ENET_RDES0_DBERR BIT(2) /*!< dribble bit error */ +#define ENET_RDES0_RERR BIT(3) /*!< receive error */ +#define ENET_RDES0_RWDT BIT(4) /*!< receive watchdog timeout */ +#define ENET_RDES0_FRMT BIT(5) /*!< frame type */ +#define ENET_RDES0_LCO BIT(6) /*!< late collision */ +#define ENET_RDES0_IPHERR BIT(7) /*!< IP frame header error */ +#define ENET_RDES0_LDES BIT(8) /*!< last descriptor */ +#define ENET_RDES0_FDES BIT(9) /*!< first descriptor */ +#define ENET_RDES0_VTAG BIT(10) /*!< VLAN tag */ +#define ENET_RDES0_OERR BIT(11) /*!< overflow Error */ +#define ENET_RDES0_LERR BIT(12) /*!< length error */ +#define ENET_RDES0_SAFF BIT(13) /*!< SA filter fail */ +#define ENET_RDES0_DERR BIT(14) /*!< descriptor error */ +#define ENET_RDES0_ERRS BIT(15) /*!< error summary */ +#define ENET_RDES0_FRML BITS(16,29) /*!< frame length */ +#define ENET_RDES0_DAFF BIT(30) /*!< destination address filter fail */ +#define ENET_RDES0_DAV BIT(31) /*!< descriptor available */ + +/* ENET DMA Rx descriptor RDES1 */ +#define ENET_RDES1_RB1S BITS(0,12) /*!< receive buffer 1 size */ +#define ENET_RDES1_RCHM BIT(14) /*!< receive chained mode for second address */ +#define ENET_RDES1_RERM BIT(15) /*!< receive end of ring mode*/ +#define ENET_RDES1_RB2S BITS(16,28) /*!< receive buffer 2 size */ +#define ENET_RDES1_DINTC BIT(31) /*!< disable interrupt on completion */ + +/* ENET DMA Rx descriptor RDES2 */ +#define ENET_RDES2_RB1AP BITS(0,31) /*!< receive buffer 1 address pointer / receive frame timestamp low 32-bit */ + +/* ENET DMA Rx descriptor RDES3 */ +#define ENET_RDES3_RB2AP BITS(0,31) /*!< receive buffer 2 address pointer (next descriptor address)/receive frame timestamp high 32-bit value */ + +/* constants definitions */ +/* define bit position and its register index offset */ +#define ENET_REGIDX_BIT(regidx, bitpos) (((uint32_t)(regidx) << 6) | (uint32_t)(bitpos)) +#define ENET_REG_VAL(periph) (REG32(ENET + ((uint32_t)(periph)>>6))) +#define ENET_BIT_POS(val) ((uint32_t)(val) & 0x1FU) + +/* ENET clock range judgement */ +#define ENET_RANGE(hclk, n, m) (((hclk) >= (n))&&((hclk) < (m))) + +/* define MAC address configuration and reference address */ +#define ENET_SET_MACADDRH(p) (((uint32_t)(p)[5] << 8) | (uint32_t)(p)[4]) +#define ENET_SET_MACADDRL(p) (((uint32_t)(p)[3] << 24) | ((uint32_t)(p)[2] << 16) | ((uint32_t)(p)[1] << 8) | (uint32_t)(p)[0]) +#define ENET_ADDRH_BASE ((ENET) + 0x40U) +#define ENET_ADDRL_BASE ((ENET) + 0x44U) +#define ENET_GET_MACADDR(offset, n) ((uint8_t)((REG32((ENET_ADDRL_BASE + (offset)) - (((n) / 4U) * 4U)) >> (8U * ((n) % 4U))) & 0xFFU)) + +/* register offset */ +#define MAC_FCTL_REG_OFFSET 0x0018U /*!< MAC flow control register offset */ +#define MAC_WUM_REG_OFFSET 0x002CU /*!< MAC wakeup management register offset */ +#define MAC_INTF_REG_OFFSET 0x0038U /*!< MAC interrupt flag register offset */ +#define MAC_INTMSK_REG_OFFSET 0x003CU /*!< MAC interrupt mask register offset */ + +#define MSC_RINTF_REG_OFFSET 0x0104U /*!< MSC receive interrupt flag register offset */ +#define MSC_TINTF_REG_OFFSET 0x0108U /*!< MSC transmit interrupt flag register offset */ +#define MSC_RINTMSK_REG_OFFSET 0x010CU /*!< MSC receive interrupt mask register offset */ +#define MSC_TINTMSK_REG_OFFSET 0x0110U /*!< MSC transmit interrupt mask register offset */ +#define MSC_SCCNT_REG_OFFSET 0x014CU /*!< MSC transmitted good frames after a single collision counter register offset */ +#define MSC_MSCCNT_REG_OFFSET 0x0150U /*!< MSC transmitted good frames after more than a single collision counter register offset */ +#define MSC_TGFCNT_REG_OFFSET 0x0168U /*!< MSC transmitted good frames counter register offset */ +#define MSC_RFCECNT_REG_OFFSET 0x0194U /*!< MSC received frames with CRC error counter register offset */ +#define MSC_RFAECNT_REG_OFFSET 0x0198U /*!< MSC received frames with alignment error counter register offset */ +#define MSC_RGUFCNT_REG_OFFSET 0x01C4U /*!< MSC received good unicast frames counter register offset */ + +#define DMA_STAT_REG_OFFSET 0x1014U /*!< DMA status register offset */ +#define DMA_INTEN_REG_OFFSET 0x101CU /*!< DMA interrupt enable register offset */ +#define DMA_TDTADDR_REG_OFFSET 0x1010U /*!< DMA transmit descriptor table address register offset */ +#define DMA_CTDADDR_REG_OFFSET 0x1048U /*!< DMA current transmit descriptor address register */ +#define DMA_CTBADDR_REG_OFFSET 0x1050U /*!< DMA current transmit buffer address register */ +#define DMA_RDTADDR_REG_OFFSET 0x100CU /*!< DMA receive descriptor table address register */ +#define DMA_CRDADDR_REG_OFFSET 0x104CU /*!< DMA current receive descriptor address register */ +#define DMA_CRBADDR_REG_OFFSET 0x1054U /*!< DMA current receive buffer address register */ + +/* ENET status flag get */ +typedef enum +{ + /* ENET_MAC_WUM register */ + ENET_MAC_FLAG_MPKR = ENET_REGIDX_BIT(MAC_WUM_REG_OFFSET, 5U), /*!< magic packet received flag */ + ENET_MAC_FLAG_WUFR = ENET_REGIDX_BIT(MAC_WUM_REG_OFFSET, 6U), /*!< wakeup frame received flag */ + /* ENET_MAC_FCTL register */ + ENET_MAC_FLAG_FLOWCONTROL = ENET_REGIDX_BIT(MAC_FCTL_REG_OFFSET, 0U), /*!< flow control status flag */ + /* ENET_MAC_INTF register */ + ENET_MAC_FLAG_WUM = ENET_REGIDX_BIT(MAC_INTF_REG_OFFSET, 3U), /*!< WUM status flag */ + ENET_MAC_FLAG_MSC = ENET_REGIDX_BIT(MAC_INTF_REG_OFFSET, 4U), /*!< MSC status flag */ + ENET_MAC_FLAG_MSCR = ENET_REGIDX_BIT(MAC_INTF_REG_OFFSET, 5U), /*!< MSC receive status flag */ + ENET_MAC_FLAG_MSCT = ENET_REGIDX_BIT(MAC_INTF_REG_OFFSET, 6U), /*!< MSC transmit status flag */ + ENET_MAC_FLAG_TMST = ENET_REGIDX_BIT(MAC_INTF_REG_OFFSET, 9U), /*!< timestamp trigger status flag */ + /* ENET_MSC_RINTF register */ + ENET_MSC_FLAG_RFCE = ENET_REGIDX_BIT(MSC_RINTF_REG_OFFSET, 5U), /*!< received frames CRC error flag */ + ENET_MSC_FLAG_RFAE = ENET_REGIDX_BIT(MSC_RINTF_REG_OFFSET, 6U), /*!< received frames alignment error flag */ + ENET_MSC_FLAG_RGUF = ENET_REGIDX_BIT(MSC_RINTF_REG_OFFSET, 17U), /*!< received good unicast frames flag */ + /* ENET_MSC_TINTF register */ + ENET_MSC_FLAG_TGFSC = ENET_REGIDX_BIT(MSC_TINTF_REG_OFFSET, 14U), /*!< transmitted good frames single collision flag */ + ENET_MSC_FLAG_TGFMSC = ENET_REGIDX_BIT(MSC_TINTF_REG_OFFSET, 15U), /*!< transmitted good frames more single collision flag */ + ENET_MSC_FLAG_TGF = ENET_REGIDX_BIT(MSC_TINTF_REG_OFFSET, 21U), /*!< transmitted good frames flag */ + /* ENET_DMA_STAT register */ + ENET_DMA_FLAG_TS = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 0U), /*!< transmit status flag */ + ENET_DMA_FLAG_TPS = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 1U), /*!< transmit process stopped status flag */ + ENET_DMA_FLAG_TBU = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 2U), /*!< transmit buffer unavailable status flag */ + ENET_DMA_FLAG_TJT = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 3U), /*!< transmit jabber timeout status flag */ + ENET_DMA_FLAG_RO = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 4U), /*!< receive overflow status flag */ + ENET_DMA_FLAG_TU = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 5U), /*!< transmit underflow status flag */ + ENET_DMA_FLAG_RS = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 6U), /*!< receive status flag */ + ENET_DMA_FLAG_RBU = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 7U), /*!< receive buffer unavailable status flag */ + ENET_DMA_FLAG_RPS = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 8U), /*!< receive process stopped status flag */ + ENET_DMA_FLAG_RWT = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 9U), /*!< receive watchdog timeout status flag */ + ENET_DMA_FLAG_ET = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 10U), /*!< early transmit status flag */ + ENET_DMA_FLAG_FBE = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 13U), /*!< fatal bus error status flag */ + ENET_DMA_FLAG_ER = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 14U), /*!< early receive status flag */ + ENET_DMA_FLAG_AI = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 15U), /*!< abnormal interrupt summary flag */ + ENET_DMA_FLAG_NI = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 16U), /*!< normal interrupt summary flag */ + ENET_DMA_FLAG_EB_DMA_ERROR = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 23U), /*!< error during data transfer by RxDMA/TxDMA flag */ + ENET_DMA_FLAG_EB_TRANSFER_ERROR = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 24U), /*!< error during write/read transfer flag */ + ENET_DMA_FLAG_EB_ACCESS_ERROR = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 25U), /*!< error during data buffer/descriptor access flag */ + ENET_DMA_FLAG_MSC = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 27U), /*!< MSC status flag */ + ENET_DMA_FLAG_WUM = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 28U), /*!< WUM status flag */ + ENET_DMA_FLAG_TST = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 29U), /*!< timestamp trigger status flag */ +}enet_flag_enum; + +/* ENET status flag clear */ +typedef enum +{ + /* ENET_DMA_STAT register */ + ENET_DMA_FLAG_TS_CLR = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 0U), /*!< transmit status flag */ + ENET_DMA_FLAG_TPS_CLR = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 1U), /*!< transmit process stopped status flag */ + ENET_DMA_FLAG_TBU_CLR = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 2U), /*!< transmit buffer unavailable status flag */ + ENET_DMA_FLAG_TJT_CLR = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 3U), /*!< transmit jabber timeout status flag */ + ENET_DMA_FLAG_RO_CLR = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 4U), /*!< receive overflow status flag */ + ENET_DMA_FLAG_TU_CLR = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 5U), /*!< transmit underflow status flag */ + ENET_DMA_FLAG_RS_CLR = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 6U), /*!< receive status flag */ + ENET_DMA_FLAG_RBU_CLR = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 7U), /*!< receive buffer unavailable status flag */ + ENET_DMA_FLAG_RPS_CLR = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 8U), /*!< receive process stopped status flag */ + ENET_DMA_FLAG_RWT_CLR = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 9U), /*!< receive watchdog timeout status flag */ + ENET_DMA_FLAG_ET_CLR = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 10U), /*!< early transmit status flag */ + ENET_DMA_FLAG_FBE_CLR = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 13U), /*!< fatal bus error status flag */ + ENET_DMA_FLAG_ER_CLR = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 14U), /*!< early receive status flag */ + ENET_DMA_FLAG_AI_CLR = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 15U), /*!< abnormal interrupt summary flag */ + ENET_DMA_FLAG_NI_CLR = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 16U), /*!< normal interrupt summary flag */ +}enet_flag_clear_enum; + +/* ENET interrupt enable/disable */ +typedef enum +{ + /* ENET_MAC_INTMSK register */ + ENET_MAC_INT_WUMIM = ENET_REGIDX_BIT(MAC_INTMSK_REG_OFFSET, 3U), /*!< WUM interrupt mask */ + ENET_MAC_INT_TMSTIM = ENET_REGIDX_BIT(MAC_INTMSK_REG_OFFSET, 9U), /*!< timestamp trigger interrupt mask */ + /* ENET_MSC_RINTMSK register */ + ENET_MSC_INT_RFCEIM = ENET_REGIDX_BIT(MSC_RINTMSK_REG_OFFSET, 5U), /*!< received frame CRC error interrupt mask */ + ENET_MSC_INT_RFAEIM = ENET_REGIDX_BIT(MSC_RINTMSK_REG_OFFSET, 6U), /*!< received frames alignment error interrupt mask */ + ENET_MSC_INT_RGUFIM = ENET_REGIDX_BIT(MSC_RINTMSK_REG_OFFSET, 17U), /*!< received good unicast frames interrupt mask */ + /* ENET_MSC_TINTMSK register */ + ENET_MSC_INT_TGFSCIM = ENET_REGIDX_BIT(MSC_TINTMSK_REG_OFFSET, 14U), /*!< transmitted good frames single collision interrupt mask */ + ENET_MSC_INT_TGFMSCIM = ENET_REGIDX_BIT(MSC_TINTMSK_REG_OFFSET, 15U), /*!< transmitted good frames more single collision interrupt mask */ + ENET_MSC_INT_TGFIM = ENET_REGIDX_BIT(MSC_TINTMSK_REG_OFFSET, 21U), /*!< transmitted good frames interrupt mask */ + /* ENET_DMA_INTEN register */ + ENET_DMA_INT_TIE = ENET_REGIDX_BIT(DMA_INTEN_REG_OFFSET, 0U), /*!< transmit interrupt enable */ + ENET_DMA_INT_TPSIE = ENET_REGIDX_BIT(DMA_INTEN_REG_OFFSET, 1U), /*!< transmit process stopped interrupt enable */ + ENET_DMA_INT_TBUIE = ENET_REGIDX_BIT(DMA_INTEN_REG_OFFSET, 2U), /*!< transmit buffer unavailable interrupt enable */ + ENET_DMA_INT_TJTIE = ENET_REGIDX_BIT(DMA_INTEN_REG_OFFSET, 3U), /*!< transmit jabber timeout interrupt enable */ + ENET_DMA_INT_ROIE = ENET_REGIDX_BIT(DMA_INTEN_REG_OFFSET, 4U), /*!< receive overflow interrupt enable */ + ENET_DMA_INT_TUIE = ENET_REGIDX_BIT(DMA_INTEN_REG_OFFSET, 5U), /*!< transmit underflow interrupt enable */ + ENET_DMA_INT_RIE = ENET_REGIDX_BIT(DMA_INTEN_REG_OFFSET, 6U), /*!< receive interrupt enable */ + ENET_DMA_INT_RBUIE = ENET_REGIDX_BIT(DMA_INTEN_REG_OFFSET, 7U), /*!< receive buffer unavailable interrupt enable */ + ENET_DMA_INT_RPSIE = ENET_REGIDX_BIT(DMA_INTEN_REG_OFFSET, 8U), /*!< receive process stopped interrupt enable */ + ENET_DMA_INT_RWTIE = ENET_REGIDX_BIT(DMA_INTEN_REG_OFFSET, 9U), /*!< receive watchdog timeout interrupt enable */ + ENET_DMA_INT_ETIE = ENET_REGIDX_BIT(DMA_INTEN_REG_OFFSET, 10U), /*!< early transmit interrupt enable */ + ENET_DMA_INT_FBEIE = ENET_REGIDX_BIT(DMA_INTEN_REG_OFFSET, 13U), /*!< fatal bus error interrupt enable */ + ENET_DMA_INT_ERIE = ENET_REGIDX_BIT(DMA_INTEN_REG_OFFSET, 14U), /*!< early receive interrupt enable */ + ENET_DMA_INT_AIE = ENET_REGIDX_BIT(DMA_INTEN_REG_OFFSET, 15U), /*!< abnormal interrupt summary enable */ + ENET_DMA_INT_NIE = ENET_REGIDX_BIT(DMA_INTEN_REG_OFFSET, 16U), /*!< normal interrupt summary enable */ +}enet_int_enum; + +/* ENET interrupt flag get */ +typedef enum +{ + /* ENET_MAC_INTF register */ + ENET_MAC_INT_FLAG_WUM = ENET_REGIDX_BIT(MAC_INTF_REG_OFFSET, 3U), /*!< WUM status flag */ + ENET_MAC_INT_FLAG_MSC = ENET_REGIDX_BIT(MAC_INTF_REG_OFFSET, 4U), /*!< MSC status flag */ + ENET_MAC_INT_FLAG_MSCR = ENET_REGIDX_BIT(MAC_INTF_REG_OFFSET, 5U), /*!< MSC receive status flag */ + ENET_MAC_INT_FLAG_MSCT = ENET_REGIDX_BIT(MAC_INTF_REG_OFFSET, 6U), /*!< MSC transmit status flag */ + ENET_MAC_INT_FLAG_TMST = ENET_REGIDX_BIT(MAC_INTF_REG_OFFSET, 9U), /*!< timestamp trigger status flag */ + /* ENET_MSC_RINTF register */ + ENET_MSC_INT_FLAG_RFCE = ENET_REGIDX_BIT(MSC_RINTF_REG_OFFSET, 5U), /*!< received frames CRC error flag */ + ENET_MSC_INT_FLAG_RFAE = ENET_REGIDX_BIT(MSC_RINTF_REG_OFFSET, 6U), /*!< received frames alignment error flag */ + ENET_MSC_INT_FLAG_RGUF = ENET_REGIDX_BIT(MSC_RINTF_REG_OFFSET, 17U), /*!< received good unicast frames flag */ + /* ENET_MSC_TINTF register */ + ENET_MSC_INT_FLAG_TGFSC = ENET_REGIDX_BIT(MSC_TINTF_REG_OFFSET, 14U), /*!< transmitted good frames single collision flag */ + ENET_MSC_INT_FLAG_TGFMSC = ENET_REGIDX_BIT(MSC_TINTF_REG_OFFSET, 15U), /*!< transmitted good frames more single collision flag */ + ENET_MSC_INT_FLAG_TGF = ENET_REGIDX_BIT(MSC_TINTF_REG_OFFSET, 21U), /*!< transmitted good frames flag */ + /* ENET_DMA_STAT register */ + ENET_DMA_INT_FLAG_TS = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 0U), /*!< transmit status flag */ + ENET_DMA_INT_FLAG_TPS = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 1U), /*!< transmit process stopped status flag */ + ENET_DMA_INT_FLAG_TBU = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 2U), /*!< transmit buffer unavailable status flag */ + ENET_DMA_INT_FLAG_TJT = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 3U), /*!< transmit jabber timeout status flag */ + ENET_DMA_INT_FLAG_RO = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 4U), /*!< receive overflow status flag */ + ENET_DMA_INT_FLAG_TU = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 5U), /*!< transmit underflow status flag */ + ENET_DMA_INT_FLAG_RS = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 6U), /*!< receive status flag */ + ENET_DMA_INT_FLAG_RBU = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 7U), /*!< receive buffer unavailable status flag */ + ENET_DMA_INT_FLAG_RPS = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 8U), /*!< receive process stopped status flag */ + ENET_DMA_INT_FLAG_RWT = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 9U), /*!< receive watchdog timeout status flag */ + ENET_DMA_INT_FLAG_ET = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 10U), /*!< early transmit status flag */ + ENET_DMA_INT_FLAG_FBE = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 13U), /*!< fatal bus error status flag */ + ENET_DMA_INT_FLAG_ER = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 14U), /*!< early receive status flag */ + ENET_DMA_INT_FLAG_AI = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 15U), /*!< abnormal interrupt summary flag */ + ENET_DMA_INT_FLAG_NI = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 16U), /*!< normal interrupt summary flag */ + ENET_DMA_INT_FLAG_MSC = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 27U), /*!< MSC status flag */ + ENET_DMA_INT_FLAG_WUM = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 28U), /*!< WUM status flag */ + ENET_DMA_INT_FLAG_TST = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 29U), /*!< timestamp trigger status flag */ +}enet_int_flag_enum; + +/* ENET interrupt flag clear */ +typedef enum +{ + /* ENET_DMA_STAT register */ + ENET_DMA_INT_FLAG_TS_CLR = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 0U), /*!< transmit status flag */ + ENET_DMA_INT_FLAG_TPS_CLR = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 1U), /*!< transmit process stopped status flag */ + ENET_DMA_INT_FLAG_TBU_CLR = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 2U), /*!< transmit buffer unavailable status flag */ + ENET_DMA_INT_FLAG_TJT_CLR = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 3U), /*!< transmit jabber timeout status flag */ + ENET_DMA_INT_FLAG_RO_CLR = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 4U), /*!< receive overflow status flag */ + ENET_DMA_INT_FLAG_TU_CLR = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 5U), /*!< transmit underflow status flag */ + ENET_DMA_INT_FLAG_RS_CLR = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 6U), /*!< receive status flag */ + ENET_DMA_INT_FLAG_RBU_CLR = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 7U), /*!< receive buffer unavailable status flag */ + ENET_DMA_INT_FLAG_RPS_CLR = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 8U), /*!< receive process stopped status flag */ + ENET_DMA_INT_FLAG_RWT_CLR = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 9U), /*!< receive watchdog timeout status flag */ + ENET_DMA_INT_FLAG_ET_CLR = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 10U), /*!< early transmit status flag */ + ENET_DMA_INT_FLAG_FBE_CLR = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 13U), /*!< fatal bus error status flag */ + ENET_DMA_INT_FLAG_ER_CLR = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 14U), /*!< early receive status flag */ + ENET_DMA_INT_FLAG_AI_CLR = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 15U), /*!< abnormal interrupt summary flag */ + ENET_DMA_INT_FLAG_NI_CLR = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 16U), /*!< normal interrupt summary flag */ +}enet_int_flag_clear_enum; + +/* current RX/TX descriptor/buffer/descriptor table address get */ +typedef enum +{ + ENET_RX_DESC_TABLE = DMA_RDTADDR_REG_OFFSET, /*!< RX descriptor table */ + ENET_RX_CURRENT_DESC = DMA_CRDADDR_REG_OFFSET, /*!< current RX descriptor */ + ENET_RX_CURRENT_BUFFER = DMA_CRBADDR_REG_OFFSET, /*!< current RX buffer */ + ENET_TX_DESC_TABLE = DMA_TDTADDR_REG_OFFSET, /*!< TX descriptor table */ + ENET_TX_CURRENT_DESC = DMA_CTDADDR_REG_OFFSET, /*!< current TX descriptor */ + ENET_TX_CURRENT_BUFFER = DMA_CTBADDR_REG_OFFSET /*!< current TX buffer */ +}enet_desc_reg_enum; + +/* MAC statistics counter get */ +typedef enum +{ + ENET_MSC_TX_SCCNT = MSC_SCCNT_REG_OFFSET, /*!< MSC transmitted good frames after a single collision counter */ + ENET_MSC_TX_MSCCNT = MSC_MSCCNT_REG_OFFSET, /*!< MSC transmitted good frames after more than a single collision counter */ + ENET_MSC_TX_TGFCNT = MSC_TGFCNT_REG_OFFSET, /*!< MSC transmitted good frames counter */ + ENET_MSC_RX_RFCECNT = MSC_RFCECNT_REG_OFFSET, /*!< MSC received frames with CRC error counter */ + ENET_MSC_RX_RFAECNT = MSC_RFAECNT_REG_OFFSET, /*!< MSC received frames with alignment error counter */ + ENET_MSC_RX_RGUFCNT = MSC_RGUFCNT_REG_OFFSET /*!< MSC received good unicast frames counter */ +}enet_msc_counter_enum; + +/* function option, used for ENET initialization */ +typedef enum +{ + FORWARD_OPTION = BIT(0), /*!< configure the frame forward related parameters */ + DMABUS_OPTION = BIT(1), /*!< configure the DMA bus mode related parameters */ + DMA_MAXBURST_OPTION = BIT(2), /*!< configure the DMA max burst related parameters */ + DMA_ARBITRATION_OPTION = BIT(3), /*!< configure the DMA arbitration related parameters */ + STORE_OPTION = BIT(4), /*!< configure the store forward mode related parameters */ + DMA_OPTION = BIT(5), /*!< configure the DMA control related parameters */ + VLAN_OPTION = BIT(6), /*!< configure the VLAN tag related parameters */ + FLOWCTL_OPTION = BIT(7), /*!< configure the flow control related parameters */ + HASHH_OPTION = BIT(8), /*!< configure the hash list high 32-bit related parameters */ + HASHL_OPTION = BIT(9), /*!< configure the hash list low 32-bit related parameters */ + FILTER_OPTION = BIT(10), /*!< configure the frame filter control related parameters */ + HALFDUPLEX_OPTION = BIT(11), /*!< configure the halfduplex related parameters */ + TIMER_OPTION = BIT(12), /*!< configure the frame timer related parameters */ + INTERFRAMEGAP_OPTION = BIT(13), /*!< configure the inter frame gap related parameters */ +}enet_option_enum; + +/* phy mode and mac loopback configurations */ +typedef enum +{ + ENET_AUTO_NEGOTIATION = 0x01U, /*!< PHY auto negotiation */ + ENET_100M_FULLDUPLEX = (ENET_MAC_CFG_SPD | ENET_MAC_CFG_DPM), /*!< 100Mbit/s, full-duplex */ + ENET_100M_HALFDUPLEX = ENET_MAC_CFG_SPD , /*!< 100Mbit/s, half-duplex */ + ENET_10M_FULLDUPLEX = ENET_MAC_CFG_DPM, /*!< 10Mbit/s, full-duplex */ + ENET_10M_HALFDUPLEX = (uint32_t)0x00000000U, /*!< 10Mbit/s, half-duplex */ + ENET_LOOPBACKMODE = (ENET_MAC_CFG_LBM | ENET_MAC_CFG_DPM) /*!< MAC in loopback mode at the MII */ +}enet_mediamode_enum; + +/* IP frame checksum function */ +typedef enum +{ + ENET_NO_AUTOCHECKSUM = (uint32_t)0x00000000U, /*!< disable IP frame checksum function */ + ENET_AUTOCHECKSUM_DROP_FAILFRAMES = ENET_MAC_CFG_IPFCO, /*!< enable IP frame checksum function */ + ENET_AUTOCHECKSUM_ACCEPT_FAILFRAMES = (ENET_MAC_CFG_IPFCO|ENET_DMA_CTL_DTCERFD) /*!< enable IP frame checksum function, and the received frame + with only payload error but no other errors will not be dropped */ +}enet_chksumconf_enum; + +/* received frame filter function */ +typedef enum +{ + ENET_PROMISCUOUS_MODE = ENET_MAC_FRMF_PM, /*!< promiscuous mode enabled */ + ENET_RECEIVEALL = (int32_t)ENET_MAC_FRMF_FAR, /*!< all received frame are forwarded to application */ + ENET_BROADCAST_FRAMES_PASS = (uint32_t)0x00000000U, /*!< the address filters pass all received broadcast frames */ + ENET_BROADCAST_FRAMES_DROP = ENET_MAC_FRMF_BFRMD /*!< the address filters filter all incoming broadcast frames */ +}enet_frmrecept_enum; + +/* register group value get */ +typedef enum +{ + ALL_MAC_REG = 0, /*!< MAC register group */ + ALL_MSC_REG = 22, /*!< MSC register group */ + ALL_PTP_REG = 33, /*!< PTP register group */ + ALL_DMA_REG = 44, /*!< DMA register group */ +}enet_registers_type_enum; + +/* dma direction select */ +typedef enum +{ + ENET_DMA_TX = ENET_DMA_STAT_TP, /*!< DMA transmit direction */ + ENET_DMA_RX = ENET_DMA_STAT_RP /*!< DMA receive direction */ +}enet_dmadirection_enum; + +/* PHY operation direction select */ +typedef enum +{ + ENET_PHY_READ = (uint32_t)0x00000000, /*!< read PHY */ + ENET_PHY_WRITE = ENET_MAC_PHY_CTL_PW /*!< write PHY */ +}enet_phydirection_enum; + +/* register operation direction select */ +typedef enum +{ + ENET_REG_READ, /*!< read register */ + ENET_REG_WRITE /*!< write register */ +}enet_regdirection_enum; + +/* ENET MAC addresses */ +typedef enum +{ + ENET_MAC_ADDRESS0 = ((uint32_t)0x00000000), /*!< MAC address0 */ + ENET_MAC_ADDRESS1 = ((uint32_t)0x00000008), /*!< MAC address1 */ + ENET_MAC_ADDRESS2 = ((uint32_t)0x00000010), /*!< MAC address2 */ + ENET_MAC_ADDRESS3 = ((uint32_t)0x00000018) /*!< MAC address3 */ +}enet_macaddress_enum; + +/* descriptor information */ +typedef enum +{ + TXDESC_COLLISION_COUNT, /*!< the number of collisions occurred before the frame was transmitted */ + TXDESC_BUFFER_1_ADDR, /*!< transmit frame buffer 1 address */ + RXDESC_FRAME_LENGTH, /*!< the byte length of the received frame that was transferred to the buffer */ + RXDESC_BUFFER_1_SIZE, /*!< receive buffer 1 size */ + RXDESC_BUFFER_2_SIZE, /*!< receive buffer 2 size */ + RXDESC_BUFFER_1_ADDR /*!< receive frame buffer 1 address */ +}enet_descstate_enum; + +/* structure for initialization of the ENET */ +typedef struct +{ + uint32_t option_enable; /*!< select which function to configure */ + uint32_t forward_frame; /*!< frame forward related parameters */ + uint32_t dmabus_mode; /*!< DMA bus mode related parameters */ + uint32_t dma_maxburst; /*!< DMA max burst related parameters */ + uint32_t dma_arbitration; /*!< DMA Tx and Rx arbitration related parameters */ + uint32_t store_forward_mode; /*!< store forward mode related parameters */ + uint32_t dma_function; /*!< DMA control related parameters */ + uint32_t vlan_config; /*!< VLAN tag related parameters */ + uint32_t flow_control; /*!< flow control related parameters */ + uint32_t hashtable_high; /*!< hash list high 32-bit related parameters */ + uint32_t hashtable_low; /*!< hash list low 32-bit related parameters */ + uint32_t framesfilter_mode; /*!< frame filter control related parameters */ + uint32_t halfduplex_param; /*!< halfduplex related parameters */ + uint32_t timer_config; /*!< frame timer related parameters */ + uint32_t interframegap; /*!< inter frame gap related parameters */ +}enet_initpara_struct; + +/* structure for ENET DMA descriptors */ +typedef struct +{ + uint32_t status; /*!< status */ + uint32_t control_buffer_size; /*!< control and buffer1, buffer2 lengths */ + uint32_t buffer1_addr; /*!< buffer1 address pointer/timestamp low */ + uint32_t buffer2_next_desc_addr; /*!< buffer2 or next descriptor address pointer/timestamp high */ +} enet_descriptors_struct; + +/* structure of PTP system time */ +typedef struct +{ + uint32_t second; /*!< second of system time */ + uint32_t nanosecond; /*!< nanosecond of system time */ + uint32_t sign; /*!< sign of system time */ +}enet_ptp_systime_struct; + +/* mac_cfg register value */ +#define MAC_CFG_BOL(regval) (BITS(5,6) & ((uint32_t)(regval) << 5)) /*!< write value to ENET_MAC_CFG_BOL bit field */ +#define ENET_BACKOFFLIMIT_10 MAC_CFG_BOL(0) /*!< min (n, 10) */ +#define ENET_BACKOFFLIMIT_8 MAC_CFG_BOL(1) /*!< min (n, 8) */ +#define ENET_BACKOFFLIMIT_4 MAC_CFG_BOL(2) /*!< min (n, 4) */ +#define ENET_BACKOFFLIMIT_1 MAC_CFG_BOL(3) /*!< min (n, 1) */ + +#define MAC_CFG_IGBS(regval) (BITS(17,19) & ((uint32_t)(regval) << 17)) /*!< write value to ENET_MAC_CFG_IGBS bit field */ +#define ENET_INTERFRAMEGAP_96BIT MAC_CFG_IGBS(0) /*!< minimum 96 bit times */ +#define ENET_INTERFRAMEGAP_88BIT MAC_CFG_IGBS(1) /*!< minimum 88 bit times */ +#define ENET_INTERFRAMEGAP_80BIT MAC_CFG_IGBS(2) /*!< minimum 80 bit times */ +#define ENET_INTERFRAMEGAP_72BIT MAC_CFG_IGBS(3) /*!< minimum 72 bit times */ +#define ENET_INTERFRAMEGAP_64BIT MAC_CFG_IGBS(4) /*!< minimum 64 bit times */ +#define ENET_INTERFRAMEGAP_56BIT MAC_CFG_IGBS(5) /*!< minimum 56 bit times */ +#define ENET_INTERFRAMEGAP_48BIT MAC_CFG_IGBS(6) /*!< minimum 48 bit times */ +#define ENET_INTERFRAMEGAP_40BIT MAC_CFG_IGBS(7) /*!< minimum 40 bit times */ + +#define ENET_WATCHDOG_ENABLE ((uint32_t)0x00000000U) /*!< the MAC allows no more than 2048 bytes of the frame being received */ +#define ENET_WATCHDOG_DISABLE ENET_MAC_CFG_WDD /*!< the MAC disables the watchdog timer on the receiver, and can receive frames of up to 16384 bytes */ + +#define ENET_JABBER_ENABLE ((uint32_t)0x00000000U) /*!< the maximum transmission byte is 2048 */ +#define ENET_JABBER_DISABLE ENET_MAC_CFG_JBD /*!< the maximum transmission byte can be 16384 */ + +#define ENET_CARRIERSENSE_ENABLE ((uint32_t)0x00000000U) /*!< the MAC transmitter generates carrier sense error and aborts the transmission */ +#define ENET_CARRIERSENSE_DISABLE ENET_MAC_CFG_CSD /*!< the MAC transmitter ignores the MII CRS signal during frame transmission in half-duplex mode */ + +#define ENET_SPEEDMODE_10M ((uint32_t)0x00000000U) /*!< 10 Mbit/s */ +#define ENET_SPEEDMODE_100M ENET_MAC_CFG_SPD /*!< 100 Mbit/s */ + +#define ENET_RECEIVEOWN_ENABLE ((uint32_t)0x00000000U) /*!< the MAC receives all packets that are given by the PHY while transmitting */ +#define ENET_RECEIVEOWN_DISABLE ENET_MAC_CFG_ROD /*!< the MAC disables the reception of frames in half-duplex mode */ + +#define ENET_LOOPBACKMODE_ENABLE ENET_MAC_CFG_LBM /*!< the MAC operates in loopback mode at the MII */ +#define ENET_LOOPBACKMODE_DISABLE ((uint32_t)0x00000000U) /*!< the MAC operates in normal mode */ + +#define ENET_MODE_FULLDUPLEX ENET_MAC_CFG_DPM /*!< full-duplex mode enable */ +#define ENET_MODE_HALFDUPLEX ((uint32_t)0x00000000U) /*!< half-duplex mode enable */ + +#define ENET_CHECKSUMOFFLOAD_ENABLE ENET_MAC_CFG_IPFCO /*!< IP frame checksum offload function enabled for received IP frame */ +#define ENET_CHECKSUMOFFLOAD_DISABLE ((uint32_t)0x00000000U) /*!< the checksum offload function in the receiver is disabled */ + +#define ENET_RETRYTRANSMISSION_ENABLE ((uint32_t)0x00000000U) /*!< the MAC attempts retries up to 16 times based on the settings of BOL*/ +#define ENET_RETRYTRANSMISSION_DISABLE ENET_MAC_CFG_RTD /*!< the MAC attempts only 1 transmission */ + +#define ENET_AUTO_PADCRC_DROP_ENABLE ENET_MAC_CFG_APCD /*!< the MAC strips the Pad/FCS field on received frames */ +#define ENET_AUTO_PADCRC_DROP_DISABLE ((uint32_t)0x00000000U) /*!< the MAC forwards all received frames without modify it */ +#define ENET_AUTO_PADCRC_DROP ENET_MAC_CFG_APCD /*!< the function of the MAC strips the Pad/FCS field on received frames */ + +#define ENET_DEFERRALCHECK_ENABLE ENET_MAC_CFG_DFC /*!< the deferral check function is enabled in the MAC */ +#define ENET_DEFERRALCHECK_DISABLE ((uint32_t)0x00000000U) /*!< the deferral check function is disabled */ + +/* mac_frmf register value */ +#define MAC_FRMF_PCFRM(regval) (BITS(6,7) & ((uint32_t)(regval) << 6)) /*!< write value to ENET_MAC_FRMF_PCFRM bit field */ +#define ENET_PCFRM_PREVENT_ALL MAC_FRMF_PCFRM(0) /*!< MAC prevents all control frames from reaching the application */ +#define ENET_PCFRM_PREVENT_PAUSEFRAME MAC_FRMF_PCFRM(1) /*!< MAC only forwards all other control frames except pause control frame */ +#define ENET_PCFRM_FORWARD_ALL MAC_FRMF_PCFRM(2) /*!< MAC forwards all control frames to application even if they fail the address filter */ +#define ENET_PCFRM_FORWARD_FILTERED MAC_FRMF_PCFRM(3) /*!< MAC forwards control frames that only pass the address filter */ + +#define ENET_RX_FILTER_DISABLE ENET_MAC_FRMF_FAR /*!< all received frame are forwarded to application */ +#define ENET_RX_FILTER_ENABLE ((uint32_t)0x00000000U) /*!< only the frame passed the filter can be forwarded to application */ + +#define ENET_SRC_FILTER_NORMAL_ENABLE ENET_MAC_FRMF_SAFLT /*!< filter source address */ +#define ENET_SRC_FILTER_INVERSE_ENABLE (ENET_MAC_FRMF_SAFLT | ENET_MAC_FRMF_SAIFLT) /*!< inverse source address filtering result */ +#define ENET_SRC_FILTER_DISABLE ((uint32_t)0x00000000U) /*!< source address function in filter disable */ +#define ENET_SRC_FILTER ENET_MAC_FRMF_SAFLT /*!< filter source address function */ +#define ENET_SRC_FILTER_INVERSE ENET_MAC_FRMF_SAIFLT /*!< inverse source address filtering result function */ + +#define ENET_BROADCASTFRAMES_ENABLE ((uint32_t)0x00000000U) /*!< the address filters pass all received broadcast frames */ +#define ENET_BROADCASTFRAMES_DISABLE ENET_MAC_FRMF_BFRMD /*!< the address filters filter all incoming broadcast frames */ + +#define ENET_DEST_FILTER_INVERSE_ENABLE ENET_MAC_FRMF_DAIFLT /*!< inverse DA filtering result */ +#define ENET_DEST_FILTER_INVERSE_DISABLE ((uint32_t)0x00000000U) /*!< not inverse DA filtering result */ +#define ENET_DEST_FILTER_INVERSE ENET_MAC_FRMF_DAIFLT /*!< inverse DA filtering result function */ + +#define ENET_PROMISCUOUS_ENABLE ENET_MAC_FRMF_PM /*!< promiscuous mode enabled */ +#define ENET_PROMISCUOUS_DISABLE ((uint32_t)0x00000000U) /*!< promiscuous mode disabled */ + +#define ENET_MULTICAST_FILTER_HASH_OR_PERFECT (ENET_MAC_FRMF_HMF | ENET_MAC_FRMF_HPFLT) /*!< pass multicast frames that match either the perfect or the hash filtering */ +#define ENET_MULTICAST_FILTER_HASH ENET_MAC_FRMF_HMF /*!< pass multicast frames that match the hash filtering */ +#define ENET_MULTICAST_FILTER_PERFECT ((uint32_t)0x00000000U) /*!< pass multicast frames that match the perfect filtering */ +#define ENET_MULTICAST_FILTER_NONE ENET_MAC_FRMF_MFD /*!< all multicast frames are passed */ +#define ENET_MULTICAST_FILTER_PASS ENET_MAC_FRMF_MFD /*!< pass all multicast frames function */ +#define ENET_MULTICAST_FILTER_HASH_MODE ENET_MAC_FRMF_HMF /*!< HASH multicast filter function */ +#define ENET_FILTER_MODE_EITHER ENET_MAC_FRMF_HPFLT /*!< HASH or perfect filter function */ + +#define ENET_UNICAST_FILTER_EITHER (ENET_MAC_FRMF_HUF | ENET_MAC_FRMF_HPFLT) /*!< pass unicast frames that match either the perfect or the hash filtering */ +#define ENET_UNICAST_FILTER_HASH ENET_MAC_FRMF_HUF /*!< pass unicast frames that match the hash filtering */ +#define ENET_UNICAST_FILTER_PERFECT ((uint32_t)0x00000000U) /*!< pass unicast frames that match the perfect filtering */ +#define ENET_UNICAST_FILTER_HASH_MODE ENET_MAC_FRMF_HUF /*!< HASH unicast filter function */ + +/* mac_phy_ctl register value */ +#define MAC_PHY_CTL_CLR(regval) (BITS(2,4) & ((uint32_t)(regval) << 2)) /*!< write value to ENET_MAC_PHY_CTL_CLR bit field */ +#define ENET_MDC_HCLK_DIV42 MAC_PHY_CTL_CLR(0) /*!< HCLK:60-100 MHz; MDC clock= HCLK/42 */ +#define ENET_MDC_HCLK_DIV62 MAC_PHY_CTL_CLR(1) /*!< HCLK:100-120 MHz; MDC clock= HCLK/62 */ +#define ENET_MDC_HCLK_DIV16 MAC_PHY_CTL_CLR(2) /*!< HCLK:20-35 MHz; MDC clock= HCLK/16 */ +#define ENET_MDC_HCLK_DIV26 MAC_PHY_CTL_CLR(3) /*!< HCLK:35-60 MHz; MDC clock= HCLK/26 */ + +#define MAC_PHY_CTL_PR(regval) (BITS(6,10) & ((uint32_t)(regval) << 6)) /*!< write value to ENET_MAC_PHY_CTL_PR bit field */ + +#define MAC_PHY_CTL_PA(regval) (BITS(11,15) & ((uint32_t)(regval) << 11)) /*!< write value to ENET_MAC_PHY_CTL_PA bit field */ + +/* mac_phy_data register value */ +#define MAC_PHY_DATA_PD(regval) (BITS(0,15) & ((uint32_t)(regval) << 0)) /*!< write value to ENET_MAC_PHY_DATA_PD bit field */ + +/* mac_fctl register value */ +#define MAC_FCTL_PLTS(regval) (BITS(4,5) & ((uint32_t)(regval) << 4)) /*!< write value to ENET_MAC_FCTL_PLTS bit field */ +#define ENET_PAUSETIME_MINUS4 MAC_FCTL_PLTS(0) /*!< pause time minus 4 slot times */ +#define ENET_PAUSETIME_MINUS28 MAC_FCTL_PLTS(1) /*!< pause time minus 28 slot times */ +#define ENET_PAUSETIME_MINUS144 MAC_FCTL_PLTS(2) /*!< pause time minus 144 slot times */ +#define ENET_PAUSETIME_MINUS256 MAC_FCTL_PLTS(3) /*!< pause time minus 256 slot times */ + +#define ENET_ZERO_QUANTA_PAUSE_ENABLE ((uint32_t)0x00000000U) /*!< enable the automatic zero-quanta generation function */ +#define ENET_ZERO_QUANTA_PAUSE_DISABLE ENET_MAC_FCTL_DZQP /*!< disable the automatic zero-quanta generation function */ +#define ENET_ZERO_QUANTA_PAUSE ENET_MAC_FCTL_DZQP /*!< the automatic zero-quanta generation function */ + +#define ENET_MAC0_AND_UNIQUE_ADDRESS_PAUSEDETECT ENET_MAC_FCTL_UPFDT /*!< besides the unique multicast address, MAC also use the MAC0 address to detect pause frame */ +#define ENET_UNIQUE_PAUSEDETECT ((uint32_t)0x00000000U) /*!< only the unique multicast address for pause frame which is specified in IEEE802.3 can be detected */ + +#define ENET_RX_FLOWCONTROL_ENABLE ENET_MAC_FCTL_RFCEN /*!< enable decoding function for the received pause frame and process it */ +#define ENET_RX_FLOWCONTROL_DISABLE ((uint32_t)0x00000000U) /*!< decode function for pause frame is disabled */ +#define ENET_RX_FLOWCONTROL ENET_MAC_FCTL_RFCEN /*!< decoding function for the received pause frame and process it */ + +#define ENET_TX_FLOWCONTROL_ENABLE ENET_MAC_FCTL_TFCEN /*!< enable the flow control operation in the MAC */ +#define ENET_TX_FLOWCONTROL_DISABLE ((uint32_t)0x00000000U) /*!< disable the flow control operation in the MAC */ +#define ENET_TX_FLOWCONTROL ENET_MAC_FCTL_TFCEN /*!< the flow control operation in the MAC */ + +#define ENET_BACK_PRESSURE_ENABLE ENET_MAC_FCTL_FLCBBKPA /*!< enable the back pressure operation in the MAC */ +#define ENET_BACK_PRESSURE_DISABLE ((uint32_t)0x00000000U) /*!< disable the back pressure operation in the MAC */ +#define ENET_BACK_PRESSURE ENET_MAC_FCTL_FLCBBKPA /*!< the back pressure operation in the MAC */ + +#define MAC_FCTL_PTM(regval) (BITS(16,31) & ((uint32_t)(regval) << 16)) /*!< write value to ENET_MAC_FCTL_PTM bit field */ +/* mac_vlt register value */ +#define MAC_VLT_VLTI(regval) (BITS(0,15) & ((uint32_t)(regval) << 0)) /*!< write value to ENET_MAC_VLT_VLTI bit field */ + +#define ENET_VLANTAGCOMPARISON_12BIT ENET_MAC_VLT_VLTC /*!< only low 12 bits of the VLAN tag are used for comparison */ +#define ENET_VLANTAGCOMPARISON_16BIT ((uint32_t)0x00000000U) /*!< all 16 bits of the VLAN tag are used for comparison */ + +/* mac_wum register value */ +#define ENET_WUM_FLAG_WUFFRPR ENET_MAC_WUM_WUFFRPR /*!< wakeup frame filter register poniter reset */ +#define ENET_WUM_FLAG_WUFR ENET_MAC_WUM_WUFR /*!< wakeup frame received */ +#define ENET_WUM_FLAG_MPKR ENET_MAC_WUM_MPKR /*!< magic packet received */ +#define ENET_WUM_POWER_DOWN ENET_MAC_WUM_PWD /*!< power down mode */ +#define ENET_WUM_MAGIC_PACKET_FRAME ENET_MAC_WUM_MPEN /*!< enable a wakeup event due to magic packet reception */ +#define ENET_WUM_WAKE_UP_FRAME ENET_MAC_WUM_WFEN /*!< enable a wakeup event due to wakeup frame reception */ +#define ENET_WUM_GLOBAL_UNICAST ENET_MAC_WUM_GU /*!< any received unicast frame passed filter is considered to be a wakeup frame */ + +/* mac_addr0h register value */ +#define MAC_ADDR0H_ADDR0H(regval) (BITS(0,15) & ((uint32_t)(regval) << 0)) /*!< write value to ENET_MAC_ADDR0H_ADDR0H bit field */ + +/* mac_addrxh register value, x = 1,2,3 */ +#define MAC_ADDR123H_ADDR123H(regval) (BITS(0,15) & ((uint32_t)(regval) << 0)) /*!< write value to ENET_MAC_ADDRxH_ADDRxH(x=1,2,3) bit field */ + +#define ENET_ADDRESS_MASK_BYTE0 BIT(24) /*!< low register bits [7:0] */ +#define ENET_ADDRESS_MASK_BYTE1 BIT(25) /*!< low register bits [15:8] */ +#define ENET_ADDRESS_MASK_BYTE2 BIT(26) /*!< low register bits [23:16] */ +#define ENET_ADDRESS_MASK_BYTE3 BIT(27) /*!< low register bits [31:24] */ +#define ENET_ADDRESS_MASK_BYTE4 BIT(28) /*!< high register bits [7:0] */ +#define ENET_ADDRESS_MASK_BYTE5 BIT(29) /*!< high register bits [15:8] */ + +#define ENET_ADDRESS_FILTER_SA BIT(30) /*!< use MAC address[47:0] is to compare with the SA fields of the received frame */ +#define ENET_ADDRESS_FILTER_DA ((uint32_t)0x00000000) /*!< use MAC address[47:0] is to compare with the DA fields of the received frame */ + +/* mac_fcth register value */ +#define MAC_FCTH_RFA(regval) ((BITS(0,2) & ((uint32_t)(regval) << 0))<<8) /*!< write value to ENET_MAC_FCTH_RFA bit field */ +#define ENET_ACTIVE_THRESHOLD_256BYTES MAC_FCTH_RFA(0) /*!< threshold level is 256 bytes */ +#define ENET_ACTIVE_THRESHOLD_512BYTES MAC_FCTH_RFA(1) /*!< threshold level is 512 bytes */ +#define ENET_ACTIVE_THRESHOLD_768BYTES MAC_FCTH_RFA(2) /*!< threshold level is 768 bytes */ +#define ENET_ACTIVE_THRESHOLD_1024BYTES MAC_FCTH_RFA(3) /*!< threshold level is 1024 bytes */ +#define ENET_ACTIVE_THRESHOLD_1280BYTES MAC_FCTH_RFA(4) /*!< threshold level is 1280 bytes */ +#define ENET_ACTIVE_THRESHOLD_1536BYTES MAC_FCTH_RFA(5) /*!< threshold level is 1536 bytes */ +#define ENET_ACTIVE_THRESHOLD_1792BYTES MAC_FCTH_RFA(6) /*!< threshold level is 1792 bytes */ + +#define MAC_FCTH_RFD(regval) ((BITS(4,6) & ((uint32_t)(regval) << 4))<<8) /*!< write value to ENET_MAC_FCTH_RFD bit field */ +#define ENET_DEACTIVE_THRESHOLD_256BYTES MAC_FCTH_RFD(0) /*!< threshold level is 256 bytes */ +#define ENET_DEACTIVE_THRESHOLD_512BYTES MAC_FCTH_RFD(1) /*!< threshold level is 512 bytes */ +#define ENET_DEACTIVE_THRESHOLD_768BYTES MAC_FCTH_RFD(2) /*!< threshold level is 768 bytes */ +#define ENET_DEACTIVE_THRESHOLD_1024BYTES MAC_FCTH_RFD(3) /*!< threshold level is 1024 bytes */ +#define ENET_DEACTIVE_THRESHOLD_1280BYTES MAC_FCTH_RFD(4) /*!< threshold level is 1280 bytes */ +#define ENET_DEACTIVE_THRESHOLD_1536BYTES MAC_FCTH_RFD(5) /*!< threshold level is 1536 bytes */ +#define ENET_DEACTIVE_THRESHOLD_1792BYTES MAC_FCTH_RFD(6) /*!< threshold level is 1792 bytes */ + +/* msc_ctl register value */ +#define ENET_MSC_COUNTER_STOP_ROLLOVER ENET_MSC_CTL_CTSR /*!< counter stop rollover */ +#define ENET_MSC_RESET_ON_READ ENET_MSC_CTL_RTOR /*!< reset on read */ +#define ENET_MSC_COUNTERS_FREEZE ENET_MSC_CTL_MCFZ /*!< MSC counter freeze */ + +/* ptp_tsctl register value */ +#define ENET_RXTX_TIMESTAMP ENET_PTP_TSCTL_TMSEN /*!< enable timestamp function for transmit and receive frames */ +#define ENET_PTP_TIMESTAMP_INT ENET_PTP_TSCTL_TMSITEN /*!< timestamp interrupt trigger enable */ + +/* ptp_ssinc register value */ +#define PTP_SSINC_STMSSI(regval) (BITS(0,7) & ((uint32_t)(regval) << 0)) /*!< write value to ENET_PTP_SSINC_STMSSI bit field */ + +/* ptp_tsl register value */ +#define GET_PTP_TSL_STMSS(regval) GET_BITS((uint32_t)(regval),0,30) /*!< get value of ENET_PTP_TSL_STMSS bit field */ + +#define ENET_PTP_TIME_POSITIVE ((uint32_t)0x00000000) /*!< time value is positive */ +#define ENET_PTP_TIME_NEGATIVE ENET_PTP_TSL_STS /*!< time value is negative */ + +#define GET_PTP_TSL_STS(regval) (((regval) & BIT(31)) >> (31U)) /*!< get value of ENET_PTP_TSL_STS bit field */ + +/* ptp_tsul register value */ +#define PTP_TSUL_TMSUSS(regval) (BITS(0,30) & ((uint32_t)(regval) << 0)) /*!< write value to ENET_PTP_TSUL_TMSUSS bit field */ + +#define ENET_PTP_ADD_TO_TIME ((uint32_t)0x00000000) /*!< timestamp update value is added to system time */ +#define ENET_PTP_SUBSTRACT_FROM_TIME ENET_PTP_TSUL_TMSUPNS /*!< timestamp update value is subtracted from system time */ + +/* dma_bctl register value */ +#define DMA_BCTL_DPSL(regval) (BITS(2,6) & ((uint32_t)(regval) << 2)) /*!< write value to ENET_DMA_BCTL_DPSL bit field */ +#define GET_DMA_BCTL_DPSL(regval) GET_BITS((regval),2,6) /*!< get value of ENET_DMA_BCTL_DPSL bit field */ + +#define DMA_BCTL_PGBL(regval) (BITS(8,13) & ((uint32_t)(regval) << 8)) /*!< write value to ENET_DMA_BCTL_PGBL bit field */ +#define ENET_PGBL_1BEAT DMA_BCTL_PGBL(1) /*!< maximum number of beats is 1 */ +#define ENET_PGBL_2BEAT DMA_BCTL_PGBL(2) /*!< maximum number of beats is 2 */ +#define ENET_PGBL_4BEAT DMA_BCTL_PGBL(4) /*!< maximum number of beats is 4 */ +#define ENET_PGBL_8BEAT DMA_BCTL_PGBL(8) /*!< maximum number of beats is 8 */ +#define ENET_PGBL_16BEAT DMA_BCTL_PGBL(16) /*!< maximum number of beats is 16 */ +#define ENET_PGBL_32BEAT DMA_BCTL_PGBL(32) /*!< maximum number of beats is 32 */ +#define ENET_PGBL_4xPGBL_4BEAT (DMA_BCTL_PGBL(1)|ENET_DMA_BCTL_FPBL) /*!< maximum number of beats is 4 */ +#define ENET_PGBL_4xPGBL_8BEAT (DMA_BCTL_PGBL(2)|ENET_DMA_BCTL_FPBL) /*!< maximum number of beats is 8 */ +#define ENET_PGBL_4xPGBL_16BEAT (DMA_BCTL_PGBL(4)|ENET_DMA_BCTL_FPBL) /*!< maximum number of beats is 16 */ +#define ENET_PGBL_4xPGBL_32BEAT (DMA_BCTL_PGBL(8)|ENET_DMA_BCTL_FPBL) /*!< maximum number of beats is 32 */ +#define ENET_PGBL_4xPGBL_64BEAT (DMA_BCTL_PGBL(16)|ENET_DMA_BCTL_FPBL) /*!< maximum number of beats is 64 */ +#define ENET_PGBL_4xPGBL_128BEAT (DMA_BCTL_PGBL(32)|ENET_DMA_BCTL_FPBL) /*!< maximum number of beats is 128 */ + +#define DMA_BCTL_RTPR(regval) (BITS(14,15) & ((uint32_t)(regval) << 14)) /*!< write value to ENET_DMA_BCTL_RTPR bit field */ +#define ENET_ARBITRATION_RXTX_1_1 DMA_BCTL_RTPR(0) /*!< receive and transmit priority ratio is 1:1*/ +#define ENET_ARBITRATION_RXTX_2_1 DMA_BCTL_RTPR(1) /*!< receive and transmit priority ratio is 2:1*/ +#define ENET_ARBITRATION_RXTX_3_1 DMA_BCTL_RTPR(2) /*!< receive and transmit priority ratio is 3:1 */ +#define ENET_ARBITRATION_RXTX_4_1 DMA_BCTL_RTPR(3) /*!< receive and transmit priority ratio is 4:1 */ +#define ENET_ARBITRATION_RXPRIORTX ENET_DMA_BCTL_DAB /*!< RxDMA has higher priority than TxDMA */ + +#define ENET_FIXED_BURST_ENABLE ENET_DMA_BCTL_FB /*!< AHB can only use SINGLE/INCR4/INCR8/INCR16 during start of normal burst transfers */ +#define ENET_FIXED_BURST_DISABLE ((uint32_t)0x00000000) /*!< AHB can use SINGLE/INCR burst transfer operations */ + +#define DMA_BCTL_RXDP(regval) (BITS(17,22) & ((uint32_t)(regval) << 17)) /*!< write value to ENET_DMA_BCTL_RXDP bit field */ +#define ENET_RXDP_1BEAT DMA_BCTL_RXDP(1) /*!< maximum number of beats 1 */ +#define ENET_RXDP_2BEAT DMA_BCTL_RXDP(2) /*!< maximum number of beats 2 */ +#define ENET_RXDP_4BEAT DMA_BCTL_RXDP(4) /*!< maximum number of beats 4 */ +#define ENET_RXDP_8BEAT DMA_BCTL_RXDP(8) /*!< maximum number of beats 8 */ +#define ENET_RXDP_16BEAT DMA_BCTL_RXDP(16) /*!< maximum number of beats 16 */ +#define ENET_RXDP_32BEAT DMA_BCTL_RXDP(32) /*!< maximum number of beats 32 */ +#define ENET_RXDP_4xPGBL_4BEAT (DMA_BCTL_RXDP(1)|ENET_DMA_BCTL_FPBL) /*!< maximum number of beats 4 */ +#define ENET_RXDP_4xPGBL_8BEAT (DMA_BCTL_RXDP(2)|ENET_DMA_BCTL_FPBL) /*!< maximum number of beats 8 */ +#define ENET_RXDP_4xPGBL_16BEAT (DMA_BCTL_RXDP(4)|ENET_DMA_BCTL_FPBL) /*!< maximum number of beats 16 */ +#define ENET_RXDP_4xPGBL_32BEAT (DMA_BCTL_RXDP(8)|ENET_DMA_BCTL_FPBL) /*!< maximum number of beats 32 */ +#define ENET_RXDP_4xPGBL_64BEAT (DMA_BCTL_RXDP(16)|ENET_DMA_BCTL_FPBL) /*!< maximum number of beats 64 */ +#define ENET_RXDP_4xPGBL_128BEAT (DMA_BCTL_RXDP(32)|ENET_DMA_BCTL_FPBL) /*!< maximum number of beats 128 */ + +#define ENET_RXTX_DIFFERENT_PGBL ENET_DMA_BCTL_UIP /*!< RxDMA uses the RXDP[5:0], while TxDMA uses the PGBL[5:0] */ +#define ENET_RXTX_SAME_PGBL ((uint32_t)0x00000000) /*!< RxDMA/TxDMA uses PGBL[5:0] */ + +#define ENET_ADDRESS_ALIGN_ENABLE ENET_DMA_BCTL_AA /*!< enabled address-aligned */ +#define ENET_ADDRESS_ALIGN_DISABLE ((uint32_t)0x00000000) /*!< disable address-aligned */ + +/* dma_stat register value */ +#define GET_DMA_STAT_RP(regval) GET_BITS((uint32_t)(regval),17,19) /*!< get value of ENET_DMA_STAT_RP bit field */ +#define ENET_RX_STATE_STOPPED ((uint32_t)0x00000000) /*!< reset or stop rx command issued */ +#define ENET_RX_STATE_FETCHING BIT(17) /*!< fetching the Rx descriptor */ +#define ENET_RX_STATE_WAITING (BIT(17)|BIT(18)) /*!< waiting for receive packet */ +#define ENET_RX_STATE_SUSPENDED BIT(19) /*!< Rx descriptor unavailable */ +#define ENET_RX_STATE_CLOSING (BIT(17)|BIT(19)) /*!< closing receive descriptor */ +#define ENET_RX_STATE_QUEUING ENET_DMA_STAT_RP /*!< transferring the receive packet data from recevie buffer to host memory */ + +#define GET_DMA_STAT_TP(regval) GET_BITS((uint32_t)(regval),20,22) /*!< get value of ENET_DMA_STAT_TP bit field */ +#define ENET_TX_STATE_STOPPED ((uint32_t)0x00000000) /*!< reset or stop Tx Command issued */ +#define ENET_TX_STATE_FETCHING BIT(20) /*!< fetching the Tx descriptor */ +#define ENET_TX_STATE_WAITING BIT(21) /*!< waiting for status */ +#define ENET_TX_STATE_READING (BIT(20)|BIT(21)) /*!< reading the data from host memory buffer and queuing it to transmit buffer */ +#define ENET_TX_STATE_SUSPENDED (BIT(21)|BIT(22)) /*!< Tx descriptor unavailabe or transmit buffer underflow */ +#define ENET_TX_STATE_CLOSING ENET_DMA_STAT_TP /*!< closing Tx descriptor */ + +#define GET_DMA_STAT_EB(regval) GET_BITS((uint32_t)(regval),23,25) /*!< get value of ENET_DMA_STAT_EB bit field */ +#define ENET_ERROR_TXDATA_TRANSFER BIT(23) /*!< error during data transfer by TxDMA or RxDMA */ +#define ENET_ERROR_READ_TRANSFER BIT(24) /*!< error during write transfer or read transfer */ +#define ENET_ERROR_DESC_ACCESS BIT(25) /*!< error during descriptor or buffer access */ + +/* dma_ctl register value */ +#define DMA_CTL_RTHC(regval) (BITS(3,4) & ((uint32_t)(regval) << 3)) /*!< write value to ENET_DMA_CTL_RTHC bit field */ +#define ENET_RX_THRESHOLD_64BYTES DMA_CTL_RTHC(0) /*!< threshold level is 64 Bytes */ +#define ENET_RX_THRESHOLD_32BYTES DMA_CTL_RTHC(1) /*!< threshold level is 32 Bytes */ +#define ENET_RX_THRESHOLD_96BYTES DMA_CTL_RTHC(2) /*!< threshold level is 96 Bytes */ +#define ENET_RX_THRESHOLD_128BYTES DMA_CTL_RTHC(3) /*!< threshold level is 128 Bytes */ + +#define DMA_CTL_TTHC(regval) (BITS(14,16) & ((uint32_t)(regval) << 14)) /*!< write value to ENET_DMA_CTL_TTHC bit field */ +#define ENET_TX_THRESHOLD_64BYTES DMA_CTL_TTHC(0) /*!< threshold level is 64 Bytes */ +#define ENET_TX_THRESHOLD_128BYTES DMA_CTL_TTHC(1) /*!< threshold level is 128 Bytes */ +#define ENET_TX_THRESHOLD_192BYTES DMA_CTL_TTHC(2) /*!< threshold level is 192 Bytes */ +#define ENET_TX_THRESHOLD_256BYTES DMA_CTL_TTHC(3) /*!< threshold level is 256 Bytes */ +#define ENET_TX_THRESHOLD_40BYTES DMA_CTL_TTHC(4) /*!< threshold level is 40 Bytes */ +#define ENET_TX_THRESHOLD_32BYTES DMA_CTL_TTHC(5) /*!< threshold level is 32 Bytes */ +#define ENET_TX_THRESHOLD_24BYTES DMA_CTL_TTHC(6) /*!< threshold level is 24 Bytes */ +#define ENET_TX_THRESHOLD_16BYTES DMA_CTL_TTHC(7) /*!< threshold level is 16 Bytes */ + +#define ENET_TCPIP_CKSUMERROR_ACCEPT ENET_DMA_CTL_DTCERFD /*!< Rx frame with only payload error but no other errors will not be dropped */ +#define ENET_TCPIP_CKSUMERROR_DROP ((uint32_t)0x00000000) /*!< all error frames will be dropped when FERF = 0 */ + +#define ENET_RX_MODE_STOREFORWARD ENET_DMA_CTL_RSFD /*!< RxFIFO operates in store-and-forward mode */ +#define ENET_RX_MODE_CUTTHROUGH ((uint32_t)0x00000000) /*!< RxFIFO operates in cut-through mode */ + +#define ENET_FLUSH_RXFRAME_ENABLE ((uint32_t)0x00000000) /*!< RxDMA flushes all frames */ +#define ENET_FLUSH_RXFRAME_DISABLE ENET_DMA_CTL_DAFRF /*!< RxDMA does not flush any frames */ +#define ENET_NO_FLUSH_RXFRAME ENET_DMA_CTL_DAFRF /*!< RxDMA does not flush frames function */ + +#define ENET_TX_MODE_STOREFORWARD ENET_DMA_CTL_TSFD /*!< TxFIFO operates in store-and-forward mode */ +#define ENET_TX_MODE_CUTTHROUGH ((uint32_t)0x00000000) /*!< TxFIFO operates in cut-through mode */ + +#define ENET_FORWARD_ERRFRAMES_ENABLE (ENET_DMA_CTL_FERF<<2) /*!< all frame received with error except runt error are forwarded to memory */ +#define ENET_FORWARD_ERRFRAMES_DISABLE ((uint32_t)0x00000000) /*!< RxFIFO drop error frame */ +#define ENET_FORWARD_ERRFRAMES (ENET_DMA_CTL_FERF<<2) /*!< the function that all frame received with error except runt error are forwarded to memory */ + +#define ENET_FORWARD_UNDERSZ_GOODFRAMES_ENABLE (ENET_DMA_CTL_FUF<<2) /*!< forward undersized good frames */ +#define ENET_FORWARD_UNDERSZ_GOODFRAMES_DISABLE ((uint32_t)0x00000000) /*!< RxFIFO drops all frames whose length is less than 64 bytes */ +#define ENET_FORWARD_UNDERSZ_GOODFRAMES (ENET_DMA_CTL_FUF<<2) /*!< the function that forwarding undersized good frames */ + +#define ENET_SECONDFRAME_OPT_ENABLE ENET_DMA_CTL_OSF /*!< TxDMA controller operate on second frame mode enable*/ +#define ENET_SECONDFRAME_OPT_DISABLE ((uint32_t)0x00000000) /*!< TxDMA controller operate on second frame mode disable */ +#define ENET_SECONDFRAME_OPT ENET_DMA_CTL_OSF /*!< TxDMA controller operate on second frame function */ + +/* dma_mfbocnt register value */ +#define GET_DMA_MFBOCNT_MSFC(regval) GET_BITS((regval),0,15) /*!< get value of ENET_DMA_MFBOCNT_MSFC bit field */ + +#define GET_DMA_MFBOCNT_MSFA(regval) GET_BITS((regval),17,27) /*!< get value of ENET_DMA_MFBOCNT_MSFA bit field */ + +/* dma tx descriptor tdes0 register value */ +#define TDES0_CONT(regval) (BITS(3,6) & ((uint32_t)(regval) << 3)) /*!< write value to ENET DMA TDES0 CONT bit field */ +#define GET_TDES0_COCNT(regval) GET_BITS((regval),3,6) /*!< get value of ENET DMA TDES0 CONT bit field */ + +#define TDES0_CM(regval) (BITS(22,23) & ((uint32_t)(regval) << 22)) /*!< write value to ENET DMA TDES0 CM bit field */ +#define ENET_CHECKSUM_DISABLE TDES0_CM(0) /*!< checksum insertion disabled */ +#define ENET_CHECKSUM_IPV4HEADER TDES0_CM(1) /*!< only IP header checksum calculation and insertion are enabled */ +#define ENET_CHECKSUM_TCPUDPICMP_SEGMENT TDES0_CM(2) /*!< TCP/UDP/ICMP checksum insertion calculated but pseudo-header */ +#define ENET_CHECKSUM_TCPUDPICMP_FULL TDES0_CM(3) /*!< TCP/UDP/ICMP checksum insertion fully calculated */ + +/* dma tx descriptor tdes1 register value */ +#define TDES1_TB1S(regval) (BITS(0,12) & ((uint32_t)(regval) << 0)) /*!< write value to ENET DMA TDES1 TB1S bit field */ + +#define TDES1_TB2S(regval) (BITS(16,28) & ((uint32_t)(regval) << 16)) /*!< write value to ENET DMA TDES1 TB2S bit field */ + +/* dma rx descriptor rdes0 register value */ +#define RDES0_FRML(regval) (BITS(16,29) & ((uint32_t)(regval) << 16)) /*!< write value to ENET DMA RDES0 FRML bit field */ +#define GET_RDES0_FRML(regval) GET_BITS((regval),16,29) /*!< get value of ENET DMA RDES0 FRML bit field */ + +/* dma rx descriptor rdes1 register value */ +#define ENET_RECEIVE_COMPLETE_INT_ENABLE ((uint32_t)0x00000000U) /*!< RS bit immediately set after Rx completed */ +#define ENET_RECEIVE_COMPLETE_INT_DISABLE ENET_RDES1_DINTC /*!< RS bit not immediately set after Rx completed */ + +#define GET_RDES1_RB1S(regval) GET_BITS((regval),0,12) /*!< get value of ENET DMA RDES1 RB1S bit field */ + +#define GET_RDES1_RB2S(regval) GET_BITS((regval),16,28) /*!< get value of ENET DMA RDES1 RB2S bit field */ + +/* dma rx descriptor rdes4 register value */ +#define RDES4_IPPLDT(regval) (BITS(0,2) & ((uint32_t)(regval) << 0)) /*!< write value to ENET DMA RDES4 IPPLDT bit field */ +#define GET_RDES4_IPPLDT(regval) GET_BITS((regval),0,2) /*!< get value of ENET DMA RDES4 IPPLDT bit field */ + +#define RDES4_PTPMT(regval) (BITS(8,11) & ((uint32_t)(regval) << 8)) /*!< write value to ENET DMA RDES4 PTPMT bit field */ +#define GET_RDES4_PTPMT(regval) GET_BITS((regval),8,11) /*!< get value of ENET DMA RDES4 PTPMT bit field */ + +/* ENET register mask value */ +#define MAC_CFG_MASK ((uint32_t)0xFD30810FU) /*!< ENET_MAC_CFG register mask */ +#define MAC_FCTL_MASK ((uint32_t)0x0000FF41U) /*!< ENET_MAC_FCTL register mask */ +#define DMA_CTL_MASK ((uint32_t)0xF8DE3F23U) /*!< ENET_DMA_CTL register mask */ +#define DMA_BCTL_MASK ((uint32_t)0xF800007DU) /*!< ENET_DMA_BCTL register mask */ + +#define ETH_DMATXDESC_SIZE 0x10U /*!< TxDMA descriptor size */ +#define ETH_DMARXDESC_SIZE 0x10U /*!< RxDMA descriptor size */ + +typedef enum{ + ENET_PTP_SYSTIME_INIT = ENET_PTP_TSCTL_TMSSTI, /*!< timestamp initialize */ + ENET_PTP_SYSTIME_UPDATE = ENET_PTP_TSCTL_TMSSTU, /*!< timestamp update */ + ENET_PTP_ADDEND_UPDATE = ENET_PTP_TSCTL_TMSARU, /*!< addend register update */ + ENET_PTP_FINEMODE = (int32_t)(ENET_PTP_TSCTL_TMSFCU| BIT(31)), /*!< the system timestamp uses the fine method for updating */ + ENET_PTP_COARSEMODE = ENET_PTP_TSCTL_TMSFCU, /*!< the system timestamp uses the coarse method for updating */ +}enet_ptp_function_enum; + + +/* ENET remote wake-up frame register length */ +#define ETH_WAKEUP_REGISTER_LENGTH 8U /*!< remote wake-up frame register length */ + +/* ENET frame size */ +#define ENET_MAX_FRAME_SIZE 1524U /*!< header + frame_extra + payload + CRC */ + +/* ENET delay timeout */ +#define ENET_DELAY_TO ((uint32_t)0x0004FFFFU) /*!< ENET delay timeout */ +#define ENET_RESET_TO ((uint32_t)0x000004FFU) /*!< ENET reset timeout */ + +/* function declarations */ +/* main function */ +/* deinitialize the ENET, and reset structure parameters for ENET initialization */ +void enet_deinit(void); +/* configure the parameters which are usually less cared for initialization */ +void enet_initpara_config(enet_option_enum option, uint32_t para); +/* initialize ENET peripheral with generally concerned parameters and the less cared parameters */ +ErrStatus enet_init(enet_mediamode_enum mediamode, enet_chksumconf_enum checksum, enet_frmrecept_enum recept); +/* reset all core internal registers located in CLK_TX and CLK_RX */ +ErrStatus enet_software_reset(void); +/* check receive frame valid and return frame size */ +uint32_t enet_rxframe_size_get(void); +/* initialize the dma tx/rx descriptors's parameters in chain mode */ +void enet_descriptors_chain_init(enet_dmadirection_enum direction); +/* initialize the dma tx/rx descriptors's parameters in ring mode */ +void enet_descriptors_ring_init(enet_dmadirection_enum direction); +/* handle current received frame data to application buffer */ +ErrStatus enet_frame_receive(uint8_t *buffer, uint32_t bufsize); +/* handle current received frame but without data copy to application buffer */ +#define ENET_NOCOPY_FRAME_RECEIVE() enet_frame_receive(NULL, 0U) +/* handle application buffer data to transmit it */ +ErrStatus enet_frame_transmit(uint8_t *buffer, uint32_t length); +/* handle current transmit frame but without data copy from application buffer */ +#define ENET_NOCOPY_FRAME_TRANSMIT(len) enet_frame_transmit(NULL, (len)) +/* configure the transmit IP frame checksum offload calculation and insertion */ +void enet_transmit_checksum_config(enet_descriptors_struct *desc, uint32_t checksum); +/* ENET Tx and Rx function enable (include MAC and DMA module) */ +void enet_enable(void); +/* ENET Tx and Rx function disable (include MAC and DMA module) */ +void enet_disable(void); +/* configure MAC address */ +void enet_mac_address_set(enet_macaddress_enum mac_addr, uint8_t paddr[]); +/* get MAC address */ +void enet_mac_address_get(enet_macaddress_enum mac_addr, uint8_t paddr[]); + +/* get the ENET MAC/MSC/PTP/DMA status flag */ +FlagStatus enet_flag_get(enet_flag_enum enet_flag); +/* clear the ENET DMA status flag */ +void enet_flag_clear(enet_flag_clear_enum enet_flag); +/* enable ENET MAC/MSC/DMA interrupt */ +void enet_interrupt_enable(enet_int_enum enet_int); +/* disable ENET MAC/MSC/DMA interrupt */ +void enet_interrupt_disable(enet_int_enum enet_int); +/* get ENET MAC/MSC/DMA interrupt flag */ +FlagStatus enet_interrupt_flag_get(enet_int_flag_enum int_flag); +/* clear ENET DMA interrupt flag */ +void enet_interrupt_flag_clear(enet_int_flag_clear_enum int_flag_clear); + +/* MAC function */ +/* ENET Tx function enable (include MAC and DMA module) */ +void enet_tx_enable(void); +/* ENET Tx function disable (include MAC and DMA module) */ +void enet_tx_disable(void); +/* ENET Rx function enable (include MAC and DMA module) */ +void enet_rx_enable(void); +/* ENET Rx function disable (include MAC and DMA module) */ +void enet_rx_disable(void); +/* put registers value into the application buffer */ +void enet_registers_get(enet_registers_type_enum type, uint32_t *preg, uint32_t num); +/* get the enet debug status from the debug register */ +uint32_t enet_debug_status_get(uint32_t mac_debug); +/* enable the MAC address filter */ +void enet_address_filter_enable(enet_macaddress_enum mac_addr); +/* disable the MAC address filter */ +void enet_address_filter_disable(enet_macaddress_enum mac_addr); +/* configure the MAC address filter */ +void enet_address_filter_config(enet_macaddress_enum mac_addr, uint32_t addr_mask, uint32_t filter_type); +/* PHY interface configuration (configure SMI clock and reset PHY chip) */ +ErrStatus enet_phy_config(void); +/* write to/read from a PHY register */ +ErrStatus enet_phy_write_read(enet_phydirection_enum direction, uint16_t phy_address, uint16_t phy_reg, uint16_t *pvalue); +/* enable the loopback function of phy chip */ +ErrStatus enet_phyloopback_enable(void); +/* disable the loopback function of phy chip */ +ErrStatus enet_phyloopback_disable(void); +/* enable ENET forward feature */ +void enet_forward_feature_enable(uint32_t feature); +/* disable ENET forward feature */ +void enet_forward_feature_disable(uint32_t feature); +/* enable ENET fliter feature */ +void enet_fliter_feature_enable(uint32_t feature); +/* disable ENET fliter feature */ +void enet_fliter_feature_disable(uint32_t feature); + +/* flow control function */ +/* generate the pause frame, ENET will send pause frame after enable transmit flow control */ +ErrStatus enet_pauseframe_generate(void); +/* configure the pause frame detect type */ +void enet_pauseframe_detect_config(uint32_t detect); +/* configure the pause frame parameters */ +void enet_pauseframe_config(uint32_t pausetime, uint32_t pause_threshold); +/* configure the threshold of the flow control(deactive and active threshold) */ +void enet_flowcontrol_threshold_config(uint32_t deactive, uint32_t active); +/* enable ENET flow control feature */ +void enet_flowcontrol_feature_enable(uint32_t feature); +/* disable ENET flow control feature */ +void enet_flowcontrol_feature_disable(uint32_t feature); + +/* DMA function */ +/* get the dma transmit/receive process state */ +uint32_t enet_dmaprocess_state_get(enet_dmadirection_enum direction); +/* poll the dma transmission/reception enable */ +void enet_dmaprocess_resume(enet_dmadirection_enum direction); +/* check and recover the Rx process */ +void enet_rxprocess_check_recovery(void); +/* flush the ENET transmit fifo, and wait until the flush operation completes */ +ErrStatus enet_txfifo_flush(void); +/* get the transmit/receive address of current descriptor, or current buffer, or descriptor table */ +uint32_t enet_current_desc_address_get(enet_desc_reg_enum addr_get); +/* get the Tx or Rx descriptor information */ +uint32_t enet_desc_information_get(enet_descriptors_struct *desc, enet_descstate_enum info_get); +/* get the number of missed frames during receiving */ +void enet_missed_frame_counter_get(uint32_t *rxfifo_drop, uint32_t *rxdma_drop); + +/* descriptor function */ +/* get the bit flag of ENET dma descriptor */ +FlagStatus enet_desc_flag_get(enet_descriptors_struct *desc, uint32_t desc_flag); +/* set the bit flag of ENET dma tx descriptor */ +void enet_desc_flag_set(enet_descriptors_struct *desc, uint32_t desc_flag); +/* clear the bit flag of ENET dma tx descriptor */ +void enet_desc_flag_clear(enet_descriptors_struct *desc, uint32_t desc_flag); +/* when receiving the completed, set RS bit in ENET_DMA_STAT register will set */ +void enet_desc_receive_complete_bit_enable(enet_descriptors_struct *desc); +/* when receiving the completed, set RS bit in ENET_DMA_STAT register will not set */ +void enet_desc_receive_complete_bit_disable(enet_descriptors_struct *desc); +/* drop current receive frame */ +void enet_rxframe_drop(void); +/* enable DMA feature */ +void enet_dma_feature_enable(uint32_t feature); +/* disable DMA feature */ +void enet_dma_feature_disable(uint32_t feature); + +/* initialize the dma Tx/Rx descriptors's parameters in normal chain mode with ptp function */ +void enet_ptp_normal_descriptors_chain_init(enet_dmadirection_enum direction, enet_descriptors_struct *desc_ptptab); +/* initialize the dma Tx/Rx descriptors's parameters in normal ring mode with ptp function */ +void enet_ptp_normal_descriptors_ring_init(enet_dmadirection_enum direction, enet_descriptors_struct *desc_ptptab); +/* receive a packet data with timestamp values to application buffer, when the DMA is in normal mode */ +ErrStatus enet_ptpframe_receive_normal_mode(uint8_t *buffer, uint32_t bufsize, uint32_t timestamp[]); +/* handle current received frame but without data copy to application buffer in PTP normal mode */ +#define ENET_NOCOPY_PTPFRAME_RECEIVE_NORMAL_MODE(ptr) enet_ptpframe_receive_normal_mode(NULL, 0U, (ptr)) +/* send data with timestamp values in application buffer as a transmit packet, when the DMA is in normal mode */ +ErrStatus enet_ptpframe_transmit_normal_mode(uint8_t *buffer, uint32_t length, uint32_t timestamp[]); +/* handle current transmit frame but without data copy from application buffer in PTP normal mode */ +#define ENET_NOCOPY_PTPFRAME_TRANSMIT_NORMAL_MODE(len, ptr) enet_ptpframe_transmit_normal_mode(NULL, (len), (ptr)) + +/* WUM function */ +/* wakeup frame filter register pointer reset */ +void enet_wum_filter_register_pointer_reset(void); +/* set the remote wakeup frame registers */ +void enet_wum_filter_config(uint32_t pdata[]); +/* enable wakeup management features */ +void enet_wum_feature_enable(uint32_t feature); +/* disable wakeup management features */ +void enet_wum_feature_disable(uint32_t feature); + +/* MSC function */ +/* reset the MAC statistics counters */ +void enet_msc_counters_reset(void); +/* enable the MAC statistics counter features */ +void enet_msc_feature_enable(uint32_t feature); +/* disable the MAC statistics counter features */ +void enet_msc_feature_disable(uint32_t feature); +/* get MAC statistics counter */ +uint32_t enet_msc_counters_get(enet_msc_counter_enum counter); + +/* PTP function */ +/* change subsecond to nanosecond */ +uint32_t enet_ptp_subsecond_2_nanosecond(uint32_t subsecond); +/* change nanosecond to subsecond */ +uint32_t enet_ptp_nanosecond_2_subsecond(uint32_t nanosecond); +/* enable the PTP features */ +void enet_ptp_feature_enable(uint32_t feature); +/* disable the PTP features */ +void enet_ptp_feature_disable(uint32_t feature); +/* configure the PTP timestamp function */ +ErrStatus enet_ptp_timestamp_function_config(enet_ptp_function_enum func); +/* configure the PTP system time subsecond increment value */ +void enet_ptp_subsecond_increment_config(uint32_t subsecond); +/* adjusting the PTP clock frequency only in fine update mode */ +void enet_ptp_timestamp_addend_config(uint32_t add); +/* initializing or adding/subtracting to second of the PTP system time */ +void enet_ptp_timestamp_update_config(uint32_t sign, uint32_t second, uint32_t subsecond); +/* configure the PTP expected target time */ +void enet_ptp_expected_time_config(uint32_t second, uint32_t nanosecond); +/* get the PTP current system time */ +void enet_ptp_system_time_get(enet_ptp_systime_struct *systime_struct); +/* configure and start PTP timestamp counter */ +void enet_ptp_start(int32_t updatemethod, uint32_t init_sec, uint32_t init_subsec, uint32_t carry_cfg, uint32_t accuracy_cfg); +/* adjust frequency in fine method by configure addend register */ +void enet_ptp_finecorrection_adjfreq(int32_t carry_cfg); +/* update system time in coarse method */ +void enet_ptp_coarsecorrection_systime_update(enet_ptp_systime_struct *systime_struct); +/* set system time in fine method */ +void enet_ptp_finecorrection_settime(enet_ptp_systime_struct * systime_struct); +/* get the ptp flag status */ +FlagStatus enet_ptp_flag_get(uint32_t flag); + +/* internal function */ +/* reset the ENET initpara struct, call it before using enet_initpara_config() */ +void enet_initpara_reset(void); +/* initialize ENET peripheral with generally concerned parameters, call it by enet_init() */ +static void enet_default_init(void); +#ifdef USE_DELAY +/* user can provide more timing precise _ENET_DELAY_ function */ +#define _ENET_DELAY_ delay_ms +#else +/* insert a delay time */ +static void enet_delay(uint32_t ncount); +/* default _ENET_DELAY_ function with less precise timing */ +#define _ENET_DELAY_ enet_delay +#endif + +#endif /* GD32F20X_ENET_H */ diff --git a/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_standard_peripheral/Include/gd32f20x_exmc.h b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_standard_peripheral/Include/gd32f20x_exmc.h new file mode 100644 index 0000000000..ef2cc2f1f1 --- /dev/null +++ b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_standard_peripheral/Include/gd32f20x_exmc.h @@ -0,0 +1,920 @@ +/*! + \file gd32f20x_exmc.h + \brief definitions for the EXMC + + \version 2015-07-15, V1.0.0, firmware for GD32F20x + \version 2017-06-05, V2.0.0, firmware for GD32F20x + \version 2018-10-31, V2.1.0, firmware for GD32F20x + \version 2020-09-30, V2.2.0, firmware for GD32F20x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef GD32F20X_EXMC_H +#define GD32F20X_EXMC_H + +#include "gd32f20x.h" + +/* EXMC definitions */ +#define EXMC (EXMC_BASE) /*!< EXMC register base address */ +#define EXMC_NOR_PSRAM (EXMC_BASE - 0x40000000) /*!< EXMC NOR/PSRAM base address */ +#define EXMC_NAND (EXMC_BASE - 0x30000000) /*!< EXMC NAND base address */ +#define EXMC_PCCARD (EXMC_BASE - 0x10000000) /*!< EXMC PC card base address */ +#define EXMC_SDRAM (EXMC_BASE + 0x20000000) /*!< EXMC SDRAM base address */ + +/* registers definitions */ +/* NOR/PSRAM */ +#define EXMC_SNCTL0 REG32(EXMC + 0x00U) /*!< EXMC SRAM/NOR flash control register */ +#define EXMC_SNTCFG0 REG32(EXMC + 0x04U) /*!< EXMC SRAM/NOR flash timing configuration register */ +#define EXMC_SNWTCFG0 REG32(EXMC + 0x104U) /*!< EXMC SRAM/NOR flash write timing configuration register */ + +#define EXMC_SNCTL1 REG32(EXMC + 0x08U) /*!< EXMC SRAM/NOR flash control register */ +#define EXMC_SNTCFG1 REG32(EXMC + 0x0CU) /*!< EXMC SRAM/NOR flash timing configuration register */ +#define EXMC_SNWTCFG1 REG32(EXMC + 0x10CU) /*!< EXMC SRAM/NOR flash write timing configuration register */ + +#define EXMC_SNCTL2 REG32(EXMC + 0x10U) /*!< EXMC SRAM/NOR flash control register */ +#define EXMC_SNTCFG2 REG32(EXMC + 0x14U) /*!< EXMC SRAM/NOR flash timing configuration register */ +#define EXMC_SNWTCFG2 REG32(EXMC + 0x114U) /*!< EXMC SRAM/NOR flash write timing configuration register */ + +#define EXMC_SNCTL3 REG32(EXMC + 0x18U) /*!< EXMC SRAM/NOR flash control register */ +#define EXMC_SNTCFG3 REG32(EXMC + 0x1CU) /*!< EXMC SRAM/NOR flash timing configuration register */ +#define EXMC_SNWTCFG3 REG32(EXMC + 0x11CU) /*!< EXMC SRAM/NOR flash write timing configuration register */ + +/* NAND/PC card */ +#define EXMC_NPCTL1 REG32(EXMC + 0x60U) /*!< EXMC NAND/PC card control register */ +#define EXMC_NPINTEN1 REG32(EXMC + 0x64U) /*!< EXMC NAND/PC card interrupt enable register */ +#define EXMC_NPCTCFG1 REG32(EXMC + 0x68U) /*!< EXMC NAND/PC card common space timing configuration register */ +#define EXMC_NPATCFG1 REG32(EXMC + 0x6CU) /*!< EXMC NAND/PC card attribute space timing configuration register */ +#define EXMC_NECC1 REG32(EXMC + 0x74U) /*!< EXMC NAND ECC register */ + +#define EXMC_NPCTL2 REG32(EXMC + 0x80U) /*!< EXMC NAND/PC card control register */ +#define EXMC_NPINTEN2 REG32(EXMC + 0x84U) /*!< EXMC NAND/PC card interrupt enable register */ +#define EXMC_NPCTCFG2 REG32(EXMC + 0x88U) /*!< EXMC NAND/PC card common space timing configuration register */ +#define EXMC_NPATCFG2 REG32(EXMC + 0x8CU) /*!< EXMC NAND/PC card attribute space timing configuration register */ +#define EXMC_NECC2 REG32(EXMC + 0x94U) /*!< EXMC NAND ECC register */ + +#define EXMC_NPCTL3 REG32(EXMC + 0xA0U) /*!< EXMC NAND/PC card control register */ +#define EXMC_NPINTEN3 REG32(EXMC + 0xA4U) /*!< EXMC NAND/PC card interrupt enable register */ +#define EXMC_NPCTCFG3 REG32(EXMC + 0xA8U) /*!< EXMC NAND/PC card common space timing configuration register */ +#define EXMC_NPATCFG3 REG32(EXMC + 0xACU) /*!< EXMC NAND/PC card attribute space timing configuration register */ +#define EXMC_PIOTCFG3 REG32(EXMC + 0xB0U) /*!< EXMC PC card I/O space timing configuration register */ + +/* SDRAM */ +#define EXMC_SDCTL0 REG32(EXMC + 0x140U) /*!< EXMC SDRAM control register */ +#define EXMC_SDTCFG0 REG32(EXMC + 0x148U) /*!< EXMC SDRAM timing configuration register register */ + +#define EXMC_SDCTL1 REG32(EXMC + 0x144U) /*!< EXMC SDRAM control register */ +#define EXMC_SDTCFG1 REG32(EXMC + 0x14CU) /*!< EXMC SDRAM timing configuration register register */ + +#define EXMC_SDCMD REG32(EXMC + 0x150U) /*!< EXMC SDRAM command register */ +#define EXMC_SDARI REG32(EXMC + 0x154U) /*!< EXMC SDRAM auto-refresh interval register */ +#define EXMC_SDSTAT REG32(EXMC + 0x158U) /*!< EXMC SDRAM status register */ +#define EXMC_SDRSCTL REG32(EXMC + 0x180U) /*!< EXMC SDRAM read sample control register */ + +/* SQPI PSRAM */ +#define EXMC_SINIT REG32(EXMC + 0x310U) /*!< EXMC SPI initialization register */ +#define EXMC_SRCMD REG32(EXMC + 0x320U) /*!< EXMC SPI read command register */ +#define EXMC_SWCMD REG32(EXMC + 0x330U) /*!< EXMC SPI write command register */ +#define EXMC_SIDL REG32(EXMC + 0x340U) /*!< EXMC SPI ID low register */ +#define EXMC_SIDH REG32(EXMC + 0x350U) /*!< EXMC SPI ID high register */ + +/* bits definitions */ +/* NOR/PSRAM */ +/* EXMC_SNCTLx,x=0..3 */ +#define EXMC_SNCTL_NRBKEN BIT(0) /*!< NOR bank enable */ +#define EXMC_SNCTL_NRMUX BIT(1) /*!< NOR bank memory address/data multiplexing */ +#define EXMC_SNCTL_NRTP BITS(2,3) /*!< NOR bank memory type */ +#define EXMC_SNCTL_NRW BITS(4,5) /*!< NOR bank memory data bus width */ +#define EXMC_SNCTL_NREN BIT(6) /*!< NOR flash access enable */ +#define EXMC_SNCTL_SBRSTEN BIT(8) /*!< synchronous burst enable */ +#define EXMC_SNCTL_NRWTPOL BIT(9) /*!< NWAIT signal polarity */ +#define EXMC_SNCTL_WRAPEN BIT(10) /*!< wrapped burst mode enable */ +#define EXMC_SNCTL_NRWTCFG BIT(11) /*!< NWAIT signal configuration, only work in synchronous mode */ +#define EXMC_SNCTL_WREN BIT(12) /*!< write enable */ +#define EXMC_SNCTL_NRWTEN BIT(13) /*!< NWAIT signal enable */ +#define EXMC_SNCTL_EXMODEN BIT(14) /*!< extended mode enable */ +#define EXMC_SNCTL_ASYNCWAIT BIT(15) /*!< asynchronous wait */ +#define EXMC_SNCTL_SYNCWR BIT(19) /*!< synchronous write */ + +/* EXMC_SNTCFGx,x=0..3 */ +#define EXMC_SNTCFG_ASET BITS(0,3) /*!< address setup time */ +#define EXMC_SNTCFG_AHLD BITS(4,7) /*!< address hold time */ +#define EXMC_SNTCFG_DSET BITS(8,15) /*!< data setup time */ +#define EXMC_SNTCFG_BUSLAT BITS(16,19) /*!< bus latency */ +#define EXMC_SNTCFG_CKDIV BITS(20,23) /*!< synchronous clock divide ratio */ +#define EXMC_SNTCFG_DLAT BITS(24,27) /*!< data latency for NOR flash */ +#define EXMC_SNTCFG_ASYNCMOD BITS(28,29) /*!< asynchronous access mode */ + +/* EXMC_SNWTCFGx,x=0..3 */ +#define EXMC_SNWTCFG_WASET BITS(0,3) /*!< address setup time */ +#define EXMC_SNWTCFG_WAHLD BITS(4,7) /*!< address hold time */ +#define EXMC_SNWTCFG_WDSET BITS(8,15) /*!< data setup time */ +#define EXMC_SNWTCFG_CKDIV BITS(20,23) /*!< synchronous clock divide ratio */ +#define EXMC_SNWTCFG_DLAT BITS(24,27) /*!< data latency for NOR flash */ +#define EXMC_SNWTCFG_WASYNCMOD BITS(28,29) /*!< asynchronous access mode */ + +/* NAND/PC card */ +/* EXMC_NPCTLx,x=1..3 */ +#define EXMC_NPCTL_NDWTEN BIT(1) /*!< wait feature enable */ +#define EXMC_NPCTL_NDBKEN BIT(2) /*!< NAND bank enable */ +#define EXMC_NPCTL_NDTP BIT(3) /*!< NAND bank memory type */ +#define EXMC_NPCTL_NDW BITS(4,5) /*!< NAND bank memory data bus width */ +#define EXMC_NPCTL_ECCEN BIT(6) /*!< ECC enable */ +#define EXMC_NPCTL_CTR BITS(9,12) /*!< CLE to RE delay */ +#define EXMC_NPCTL_ATR BITS(13,16) /*!< ALE to RE delay */ +#define EXMC_NPCTL_ECCSZ BITS(17,19) /*!< ECC size */ + +/* EXMC_NPINTENx,x=1..3 */ +#define EXMC_NPINTEN_INTRS BIT(0) /*!< interrupt rising edge status */ +#define EXMC_NPINTEN_INTHS BIT(1) /*!< interrupt high-level status */ +#define EXMC_NPINTEN_INTFS BIT(2) /*!< interrupt falling edge status */ +#define EXMC_NPINTEN_INTREN BIT(3) /*!< interrupt rising edge detection enable */ +#define EXMC_NPINTEN_INTHEN BIT(4) /*!< interrupt high-level detection enable */ +#define EXMC_NPINTEN_INTFEN BIT(5) /*!< interrupt falling edge detection enable */ +#define EXMC_NPINTEN_FFEPT BIT(6) /*!< FIFO empty flag */ + +/* EXMC_NPCTCFGx,x=1..3 */ +#define EXMC_NPCTCFG_COMSET BITS(0,7) /*!< common memory setup time */ +#define EXMC_NPCTCFG_COMWAIT BITS(8,15) /*!< common memory wait time */ +#define EXMC_NPCTCFG_COMHLD BITS(16,23) /*!< common memory hold time */ +#define EXMC_NPCTCFG_COMHIZ BITS(24,31) /*!< common memory data bus HiZ time */ + +/* EXMC_NPATCFGx,x=1..3 */ +#define EXMC_NPATCFG_ATTSET BITS(0,7) /*!< attribute memory setup time */ +#define EXMC_NPATCFG_ATTWAIT BITS(8,15) /*!< attribute memory wait time */ +#define EXMC_NPATCFG_ATTHLD BITS(16,23) /*!< attribute memory hold time */ +#define EXMC_NPATCFG_ATTHIZ BITS(24,31) /*!< attribute memory data bus HiZ time */ + +/* EXMC_PIOTCFG3 */ +#define EXMC_PIOTCFG3_IOSET BITS(0,7) /*!< IO space setup time */ +#define EXMC_PIOTCFG3_IOWAIT BITS(8,15) /*!< IO space wait time */ +#define EXMC_PIOTCFG3_IOHLD BITS(16,23) /*!< IO space hold time */ +#define EXMC_PIOTCFG3_IOHIZ BITS(24,31) /*!< IO space data bus HiZ time */ + +/* EXMC_NECCx,x=1..2 */ +#define EXMC_NECC_ECC BITS(0,31) /*!< ECC result */ + +/* SDRAM */ +/* EXMC_SDCTLx,x=0..1 */ +#define EXMC_SDCTL_CAW BITS(0,1) /*!< column address bit width */ +#define EXMC_SDCTL_RAW BITS(2,3) /*!< row address bit width */ +#define EXMC_SDCTL_SDW BITS(4,5) /*!< SDRAM data bus width */ +#define EXMC_SDCTL_NBK BIT(6) /*!< number of banks */ +#define EXMC_SDCTL_CL BIT(7,8) /*!< CAS Latency */ +#define EXMC_SDCTL_WPEN BIT(9) /*!< write protection enable */ +#define EXMC_SDCTL_SDCLK BITS(10,11) /*!< SDRAM clock configuration */ +#define EXMC_SDCTL_BRSTRD BIT(12) /*!< burst read */ +#define EXMC_SDCTL_PIPED BITS(13,14) /*!< pipeline delay */ + +/* EXMC_SDTCFGx,x=0..1 */ +#define EXMC_SDTCFG_LMRD BITS(0,3) /*!< load mode register delay */ +#define EXMC_SDTCFG_XSRD BITS(4,7) /*!< exit self-refresh delay */ +#define EXMC_SDTCFG_RASD BITS(8,11) /*!< row address select delay */ +#define EXMC_SDTCFG_ARFD BITS(12,15) /*!< auto refresh delay */ +#define EXMC_SDTCFG_WRD BITS(16,19) /*!< write recovery delay */ +#define EXMC_SDTCFG_RPD BITS(20,23) /*!< row precharge delay */ +#define EXMC_SDTCFG_RCD BITS(24,27) /*!< row to column delay */ + +/* EXMC_SDCMD */ +#define EXMC_SDCMD_CMD BITS(0,2) /*!< command */ +#define EXMC_SDCMD_DS1 BIT(3) /*!< device select 1 */ +#define EXMC_SDCMD_DS0 BIT(4) /*!< device select 0 */ +#define EXMC_SDCMD_NARF BITS(5,8) /*!< number of successive auto-refresh */ +#define EXMC_SDCMD_MRC BITS(9,21) /*!< mode register content */ + +/* EXMC_SDARI */ +#define EXMC_SDARI_REC BIT(0) /*!< refresh error flag clear */ +#define EXMC_SDARI_ARINTV BITS(1,13) /*!< auto-refresh interval */ +#define EXMC_SDARI_REIE BIT(14) /*!< interrupt refresh error enable */ + +/* EXMC_SDSTAT */ +#define EXMC_SDSDAT_REIF BIT(0) /*!< refresh error interrupt flag */ +#define EXMC_SDSDAT_STA0 BITS(1,2) /*!< device 0 status */ +#define EXMC_SDSDAT_STA1 BITS(3,4) /*!< device 1 status */ +#define EXMC_SDSDAT_NRDY BIT(5) /*!< not ready status */ + +/* EXMC_SDRSCTL */ +#define EXMC_SDRSCTL_RSEN BIT(0) /*!< read sample enable */ +#define EXMC_SDRSCTL_SSCR BIT(1) /*!< select sample cycle of read data */ +#define EXMC_SDRSCTL_SDSC BITS(4,7) /*!< select the delayed sample clock of read data */ + +/* SQPI PSRAM */ +/* EXMC_SINIT */ +#define EXMC_SINIT_CMDBIT BITS(16,17) /*!< bit number of SPI PSRAM command phase */ +#define EXMC_SINIT_ARDBIT BITS(24,28) /*!< bit number of SPI PSRAM address phase */ +#define EXMC_SINIT_IDL BITS(29,30) /*!< SPI PSRAM ID length */ +#define EXMC_SINIT_POL BIT(31) /*!< read data sample polarity */ + +/* EXMC_SRCMD */ +#define EXMC_SRCMD_RCMD BITS(0,15) /*!< SPI read command for AHB read transfer */ +#define EXMC_SRCMD_RWAITCYCLE BITS(16,19) /*!< SPI read wait cycle number after address phase */ +#define EXMC_SRCMD_RMODE BITS(20,21) /*!< SPI PSRAM read command mode */ +#define EXMC_SRCMD_RDID BIT(31) /*!< send SPI read ID command */ + +/* EXMC_SWCMD */ +#define EXMC_SWCMD_WCMD BITS(0,15) /*!< SPI write command for AHB write transfer */ +#define EXMC_SWCMD_WWAITCYCLE BITS(16,19) /*!< SPI write wait cycle number after address phase */ +#define EXMC_SWCMD_WMODE BITS(20,21) /*!< SPI PSRAM write command mode */ +#define EXMC_SWCMD_SC BIT(31) /*!< send SPI special command */ + +/* EXMC_SIDL */ +#define EXMC_SIDL_SIDL BITS(0,31) /*!< ID low data saved for SPI read ID command */ + +/* EXMC_SIDH */ +#define EXMC_SIDL_SIDH BITS(0,31) /*!< ID high Data saved for SPI read ID command */ + +/* constants definitions */ +/* EXMC NOR/SRAM timing initialize structure */ +typedef struct +{ + uint32_t asyn_access_mode; /*!< asynchronous access mode */ + + uint32_t syn_data_latency; /*!< configure the data latency */ + /*!< the range is EXMC_DATALAT_2_CLK to EXMC_DATALAT_17_CLK */ + + uint32_t syn_clk_division; /*!< configure the clock divide ratio */ + /*!< the range is EXMC_SYN_CLOCK_RATIO_2_CLK to EXMC_SYN_CLOCK_RATIO_16_CLK */ + + uint32_t bus_latency; /*!< configure the bus latency */ + /*!< the range is 1 to 16 HCLK */ + + uint32_t asyn_data_setuptime; /*!< configure the data setup time,asynchronous access mode valid */ + /*!< the range is 2 to 256 HCLK */ + + uint32_t asyn_address_holdtime; /*!< configure the address hold time,asynchronous access mode valid */ + /*!< the range is 2 to 16 HCLK */ + + uint32_t asyn_address_setuptime; /*!< configure the data setup time,asynchronous access mode valid */ + /*!< the range is 1 to 16 HCLK */ +}exmc_norsram_timing_parameter_struct; + +/* EXMC NOR/SRAM initialize structure */ +typedef struct +{ + uint32_t norsram_region; /*!< select the region of EXMC NOR/SRAM bank */ + /*!< norsram_region: EXMC_BANK0_NORSRAM_REGIONx,x=0..3 */ + + uint32_t write_mode; /*!< the write mode, synchronous mode or asynchronous mode */ + /*!< write_mode: EXMC_ASYN_WRITE or EXMC_SYN_WRITE */ + + uint32_t extended_mode; /*!< enable or disable the extended mode */ + /*!< extended_mode: ENABLE or DISABLE */ + + uint32_t asyn_wait; /*!< enable or disable the asynchronous wait function */ + /*!< asyn_wait: ENABLE or DISABLE */ + + uint32_t nwait_signal; /*!< enable or disable the NWAIT signal while in synchronous bust mode */ + /*!< nwait_signal: ENABLE or DISABLE */ + + uint32_t memory_write; /*!< enable or disable the write operation */ + /*!< memory_write: ENABLE or DISABLE */ + + uint32_t nwait_config; /*!< NWAIT signal configuration */ + /*!< nwait_config: EXMC_NWAIT_CONFIG_BEFORE or EXMC_NWAIT_CONFIG_DURING */ + + uint32_t wrap_burst_mode; /*!< enable or disable the wrap burst mode */ + /*!< wrap_burst_mode: ENABLE or DISABLE */ + + uint32_t nwait_polarity; /*!< specifies the polarity of NWAIT signal from memory */ + /*!< nwait_polarity: EXMC_NWAIT_POLARITY_LOW or EXMC_NWAIT_POLARITY_HIGH */ + + uint32_t burst_mode; /*!< enable or disable the burst mode */ + /*!< burst_mode: ENABLE or DISABLE */ + + uint32_t databus_width; /*!< specifies the databus width of external memory */ + /*!< databus_width: EXMC_NOR_DATABUS_WIDTH_8B or EXMC_NOR_DATABUS_WIDTH_16B */ + + uint32_t memory_type; /*!< specifies the type of external memory */ + /*!< memory_type: EXMC_MEMORY_TYPE_SRAM / EXMC_MEMORY_TYPE_PSRAM / EXMC_MEMORY_TYPE_NOR */ + + uint32_t address_data_mux; /*!< specifies whether the data bus and address bus are multiplexed */ + /*!< address_data_mux: ENABLE or DISABLE */ + + exmc_norsram_timing_parameter_struct* read_write_timing; /*!< timing parameters for read and write if the extendedmode is not used or the timing + parameters for read if the extendedmode is used. */ + + exmc_norsram_timing_parameter_struct* write_timing; /*!< timing parameters for write when the extendedmode is used. */ +}exmc_norsram_parameter_struct; + +/* EXMC NAND/PC card timing initialize struct */ +typedef struct +{ + uint32_t databus_hiztime; /*!< configure the dadtabus HiZ time for write operation */ + /*!< the range is 1 to 256 HCLK */ + + uint32_t holdtime; /*!< configure the address hold time(or the data hold time for write operation) */ + /*!< the range is 1 to 255 HCLK */ + + uint32_t waittime; /*!< configure the minimum wait time */ + /*!< the range is 2 to 256 HCLK (+NWAIT active cycles) */ + + uint32_t setuptime; /*!< configure the address setup time */ + /*!< the range is 1 to 256 HCLK */ +}exmc_nand_pccard_timing_parameter_struct; + +/* EXMC NAND initialize structure */ +typedef struct +{ + uint32_t nand_bank; /*!< select the bank of NAND */ + /*!< nand_bank: EXMC_BANK1_NAND or EXMC_BANK2_NAND */ + + uint32_t ecc_size; /*!< the page size for the ECC calculation */ + /*!< ecc_size: EXMC_ECC_SIZE_xBYTES,x=256,512,1024,2048,4096 */ + + uint32_t atr_latency; /*!< configure the latency of ALE low to RB low */ + /*!< atr_latency: EXMC_ALE_RE_DELAY_x_HCLK,x=1..16 */ + + uint32_t ctr_latency; /*!< configure the latency of CLE low to RB low */ + /*!< ctr_latency: EXMC_CLE_RE_DELAY_x_HCLK,x=1..16 */ + + uint32_t ecc_logic; /*!< enable or disable the ECC calculation logic */ + /*!< ecc_logic: ENABLE or DISABLE */ + + uint32_t databus_width; /*!< the NAND flash databus width */ + /*!< databus_width: EXMC_NAND_DATABUS_WIDTH_8B or EXMC_NAND_DATABUS_WIDTH_16B */ + + uint32_t wait_feature; /*!< enables or disables the wait feature */ + /*!< wait_feature: ENABLE or DISABLE */ + + exmc_nand_pccard_timing_parameter_struct* common_space_timing; /*!< the timing parameters for NAND flash Common Space */ + + exmc_nand_pccard_timing_parameter_struct* attribute_space_timing; /*!< the timing parameters for NAND flash Attribute Space */ +}exmc_nand_parameter_struct; + +/* EXMC PC card initialize structure */ +typedef struct +{ + uint32_t atr_latency; /*!< configure the latency of ALE low to RB low */ + /*!< atr_latency: EXMC_ALE_RE_DELAY_x_HCLK,x=1..16 */ + + uint32_t ctr_latency; /*!< configure the latency of CLE low to RB low */ + /*!< ctr_latency: EXMC_CLE_RE_DELAY_x_HCLK,x=1..16 */ + + uint32_t wait_feature; /*!< enables or disables the Wait feature */ + /*!< wait_feature: ENABLE or DISABLE */ + + exmc_nand_pccard_timing_parameter_struct* common_space_timing; /*!< the timing parameters for NAND flash Common Space */ + + exmc_nand_pccard_timing_parameter_struct* attribute_space_timing; /*!< the timing parameters for NAND flash Attribute Space */ + + exmc_nand_pccard_timing_parameter_struct* io_space_timing; /*!< the timing parameters for NAND flash IO Space */ +}exmc_pccard_parameter_struct;; + +/* EXMC SDRAM timing initialize structure */ +typedef struct +{ + uint32_t row_to_column_delay; /*!< configure the row to column delay */ + /*!< the range is 1 to 16 cycles */ + + uint32_t row_precharge_delay; /*!< configure the row precharge delay */ + /*!< the range is 1 to 16 cycles */ + + uint32_t write_recovery_delay; /*!< configure the write recovery delay */ + /*!< the range is 1 to 16 cycles */ + + uint32_t auto_refresh_delay; /*!< configure the auto refresh delay */ + /*!< the range is 1 to 16 cycles */ + + uint32_t row_address_select_delay; /*!< configure the row address select delay */ + /*!< the range is 1 to 16 cycles */ + + uint32_t exit_selfrefresh_delay; /*!< configure the exit self-refresh delay */ + /*!< the range is 1 to 16 cycles */ + + uint32_t load_mode_register_delay; /*!< configure the load mode register delay */ + /*!< the range is 1 to 16 cycles */ +}exmc_sdram_timing_parameter_struct; + +/* EXMC SDRAM initialize structure */ +typedef struct +{ + uint32_t sdram_device; /*!< device of SDRAM */ + /*!< sdram_device: EXMC_SDRAM_DEVICE0 or EXMC_SDRAM_DEVICE1 */ + + uint32_t pipeline_read_delay; /*!< the delay for reading data after CAS latency in HCLK clock cycles */ + /*!< pipeline_read_delay: EXMC_PIPELINE_DELAY_x_HCLK, x=0..2 */ + + uint32_t brust_read_switch; /*!< enable or disable the burst read */ + /*!< brust_read_switch: ENABLE or DISABLE */ + + uint32_t sdclock_config; /*!< the SDCLK memory clock for both SDRAM banks */ + /*!< sdclock_config: EXMC_SDCLK_DISABLE,EXMC_SDCLK_PERIODS_2_HCLK,EXMC_SDCLK_PERIODS_3_HCLK */ + + uint32_t write_protection; /*!< enable or disable SDRAM bank write protection function */ + /*!< write_protection: ENABLE or DISABLE */ + + uint32_t cas_latency; /*!< configure the SDRAM CAS latency */ + /*!< cas_latency: EXMC_CAS_LATENCY_x_SDCLK, x=1..3 */ + + uint32_t internal_bank_number; /*!< the number internal banks */ + /*!< internal_bank_number: EXMC_SDRAM_2_INTER_BANK or EXMC_SDRAM_4_INTER_BANK */ + + uint32_t data_width; /*!< the databus width of SDRAM memory */ + /*!< data_width: EXMC_SDRAM_DATABUS_WIDTH_8B,EXMC_SDRAM_DATABUS_WIDTH_16B,EXMC_SDRAM_DATABUS_WIDTH_32B */ + + uint32_t row_address_width; /*!< the bit width of a row address */ + /*!< row_address_width: EXMC_SDRAM_ROW_ADDRESS_x, x=11..13 */ + + uint32_t column_address_width; /*!< the bit width of a column address */ + /*!< column_address_width: EXMC_SDRAM_COW_ADDRESS_x, x=8..11 */ + + exmc_sdram_timing_parameter_struct* timing; /*!< the timing parameters for write and read SDRAM */ +}exmc_sdram_parameter_struct; + +/* EXMC SDRAM command initialize structure */ +typedef struct +{ + uint32_t mode_register_content; /*!< the SDRAM mode register content */ + /*!< mode_register_content: */ + + uint32_t auto_refresh_number; /*!< the number of successive auto-refresh cycles will be send when CMD = 011 */ + /*!< auto_refresh_number: EXMC_SDRAM_AUTO_REFLESH_x_SDCLK, x=1..15 */ + + uint32_t bank_select; /*!< the bank which command will be sent to */ + /*!< bank_select: EXMC_SDRAM_DEVICE0_SELECT, EXMC_SDRAM_DEVICE1_SELECT, EXMC_SDRAM_DEVICE0_1_SELECT */ + + uint32_t command; /*!< the commands that will be sent to SDRAM */ + /*!< command: EXMC_SDRAM_NORMAL_OPERATION, EXMC_SDRAM_CLOCK_ENABLE, EXMC_SDRAM_PRECHARGE_ALL, + EXMC_SDRAM_AUTO_REFRESH, EXMC_SDRAM_LOAD_MODE_REGISTER, EXMC_SDRAM_SELF_REFRESH, + EXMC_SDRAM_POWERDOWN_ENTRY */ +}exmc_sdram_command_parameter_struct; + +/* EXMC SQPISRAM initialize structure */ +typedef struct{ + uint32_t sample_polarity; /*!< read data sample polarity */ + /*!< sample_polarity: EXMC_SDRAM_SAMPLE_RISING_EDGE,EXMC_SDRAM_SAMPLE_FALLING_EDGE */ + + uint32_t id_length; /*!< SPI PSRAM ID length */ + /*!< id_length: EXMC_SQPIPSRAM_ID_LENGTH_xB,x=8,16,32,64 */ + + uint32_t address_bits; /*!< bit number of SPI PSRAM address phase */ + /*!< address_bits: EXMC_SQPIPSRAM_ADDR_LENGTH_xB,x=1..26 */ + + uint32_t command_bits; /*!< bit number of SPI PSRAM command phase */ + /*!< command_bits: EXMC_SQPIPSRAM_COMMAND_LENGTH_xB,x=4,8,16 */ +}exmc_sqpipsram_parameter_struct; + +/* EXMC NOR/SRAM bank region definition */ +#define EXMC_BANK0_NORSRAM_REGION0 ((uint32_t)0x00000000U) /*!< bank0 NOR/SRAM region0 */ +#define EXMC_BANK0_NORSRAM_REGION1 ((uint32_t)0x00000001U) /*!< bank0 NOR/SRAM region1 */ +#define EXMC_BANK0_NORSRAM_REGION2 ((uint32_t)0x00000002U) /*!< bank0 NOR/SRAM region2 */ +#define EXMC_BANK0_NORSRAM_REGION3 ((uint32_t)0x00000003U) /*!< bank0 NOR/SRAM region3 */ + +/* EXMC NAND/PC card bank definition */ +#define EXMC_BANK1_NAND ((uint32_t)0x00000001U) /*!< bank1 NAND flash */ +#define EXMC_BANK2_NAND ((uint32_t)0x00000002U) /*!< bank2 NAND flash */ +#define EXMC_BANK3_PCCARD ((uint32_t)0x00000003U) /*!< bank3 PC card */ + +/* EXMC SDRAM bank definition */ +#define EXMC_SDRAM_DEVICE0 ((uint32_t)0x00000004U) /*!< SDRAM device0 */ +#define EXMC_SDRAM_DEVICE1 ((uint32_t)0x00000005U) /*!< SDRAM device1 */ + +/* EXMC_register address */ +#define EXMC_SNCTL(bank) REG32(EXMC + 0x08U*((uint32_t)(bank))) /*!< EXMC SRAM/NOR flash control register */ +#define EXMC_SNTCFG(bank) REG32(EXMC + 0x04U + 0x08U*(bank)) /*!< EXMC SRAM/NOR flash timing configuration register */ +#define EXMC_SNWTCFG(bank) REG32(EXMC + 0x104U + 0x08U*(bank)) /*!< EXMC SRAM/NOR flash write timing configuration register */ + +#define EXMC_NPCTL(bank) REG32(EXMC + 0x40U + 0x20U*(bank)) /*!< EXMC NAND/PC card control register */ +#define EXMC_NPINTEN(bank) REG32(EXMC + 0x44U + 0x20U*(bank)) /*!< EXMC NAND/PC card interrupt enable register */ +#define EXMC_NPCTCFG(bank) REG32(EXMC + 0x48U + 0x20U*(bank)) /*!< EXMC NAND/PC card common space timing configuration register */ +#define EXMC_NPATCFG(bank) REG32(EXMC + 0x4CU + 0x20U*(bank)) /*!< EXMC NAND/PC card attribute space timing configuration register */ +#define EXMC_NECC(bank) REG32(EXMC + 0x54U + 0x20U*(bank)) /*!< EXMC NAND ECC register */ + +#define EXMC_SDCTL(bank) REG32(EXMC + 0x140U + 0x4U*((bank) - 0x4U)) /*!< EXMC SDRAM control register */ +#define EXMC_SDTCFG(bank) REG32(EXMC + 0x148U + 0x4U*((bank) - 0x4U)) /*!< EXMC SDRAM timing configuration register */ + +/* NOR/PSRAM */ +/* NOR bank memory data bus width */ +#define SNCTL_NRW(regval) (BITS(4,5) & ((uint32_t)(regval) << 4)) +#define EXMC_NOR_DATABUS_WIDTH_8B SNCTL_NRW(0) /*!< NOR data width 8 bits */ +#define EXMC_NOR_DATABUS_WIDTH_16B SNCTL_NRW(1) /*!< NOR data width 16 bits */ + +/* NOR bank memory type */ +#define SNCTL_NRTP(regval) (BITS(2,3) & ((uint32_t)(regval) << 2)) +#define EXMC_MEMORY_TYPE_SRAM SNCTL_NRTP(0) /*!< SRAM,ROM */ +#define EXMC_MEMORY_TYPE_PSRAM SNCTL_NRTP(1) /*!< PSRAM,CRAM */ +#define EXMC_MEMORY_TYPE_NOR SNCTL_NRTP(2) /*!< NOR flash */ + +/* asynchronous access mode */ +#define SNTCFG_ASYNCMOD(regval) (BITS(28,29) & ((uint32_t)(regval) << 28)) +#define EXMC_ACCESS_MODE_A SNTCFG_ASYNCMOD(0) /*!< mode A access */ +#define EXMC_ACCESS_MODE_B SNTCFG_ASYNCMOD(1) /*!< mode B access */ +#define EXMC_ACCESS_MODE_C SNTCFG_ASYNCMOD(2) /*!< mode C access */ +#define EXMC_ACCESS_MODE_D SNTCFG_ASYNCMOD(3) /*!< mode D access */ + +/* data latency for NOR flash */ +#define SNTCFG_DLAT(regval) (BITS(24,27) & ((uint32_t)(regval) << 24)) +#define EXMC_DATALAT_2_CLK SNTCFG_DLAT(0) /*!< data latency 2 EXMC_CLK */ +#define EXMC_DATALAT_3_CLK SNTCFG_DLAT(1) /*!< data latency 3 EXMC_CLK */ +#define EXMC_DATALAT_4_CLK SNTCFG_DLAT(2) /*!< data latency 4 EXMC_CLK */ +#define EXMC_DATALAT_5_CLK SNTCFG_DLAT(3) /*!< data latency 5 EXMC_CLK */ +#define EXMC_DATALAT_6_CLK SNTCFG_DLAT(4) /*!< data latency 6 EXMC_CLK */ +#define EXMC_DATALAT_7_CLK SNTCFG_DLAT(5) /*!< data latency 7 EXMC_CLK */ +#define EXMC_DATALAT_8_CLK SNTCFG_DLAT(6) /*!< data latency 8 EXMC_CLK */ +#define EXMC_DATALAT_9_CLK SNTCFG_DLAT(7) /*!< data latency 9 EXMC_CLK */ +#define EXMC_DATALAT_10_CLK SNTCFG_DLAT(8) /*!< data latency 10 EXMC_CLK */ +#define EXMC_DATALAT_11_CLK SNTCFG_DLAT(9) /*!< data latency 11 EXMC_CLK */ +#define EXMC_DATALAT_12_CLK SNTCFG_DLAT(10) /*!< data latency 12 EXMC_CLK */ +#define EXMC_DATALAT_13_CLK SNTCFG_DLAT(11) /*!< data latency 13 EXMC_CLK */ +#define EXMC_DATALAT_14_CLK SNTCFG_DLAT(12) /*!< data latency 14 EXMC_CLK */ +#define EXMC_DATALAT_15_CLK SNTCFG_DLAT(13) /*!< data latency 15 EXMC_CLK */ +#define EXMC_DATALAT_16_CLK SNTCFG_DLAT(14) /*!< data latency 16 EXMC_CLK */ +#define EXMC_DATALAT_17_CLK SNTCFG_DLAT(15) /*!< data latency 17 EXMC_CLK */ + +/* synchronous clock divide ratio */ +#define SNTCFG_CKDIV(regval) (BITS(20,23) & ((uint32_t)(regval) << 20)) +#define EXMC_SYN_CLOCK_RATIO_2_CLK SNTCFG_CKDIV(1) /*!< EXMC_CLK = 2*HCLK */ +#define EXMC_SYN_CLOCK_RATIO_3_CLK SNTCFG_CKDIV(2) /*!< EXMC_CLK = 3*HCLK */ +#define EXMC_SYN_CLOCK_RATIO_4_CLK SNTCFG_CKDIV(3) /*!< EXMC_CLK = 4*HCLK */ +#define EXMC_SYN_CLOCK_RATIO_5_CLK SNTCFG_CKDIV(4) /*!< EXMC_CLK = 5*HCLK */ +#define EXMC_SYN_CLOCK_RATIO_6_CLK SNTCFG_CKDIV(5) /*!< EXMC_CLK = 6*HCLK */ +#define EXMC_SYN_CLOCK_RATIO_7_CLK SNTCFG_CKDIV(6) /*!< EXMC_CLK = 7*HCLK */ +#define EXMC_SYN_CLOCK_RATIO_8_CLK SNTCFG_CKDIV(7) /*!< EXMC_CLK = 8*HCLK */ +#define EXMC_SYN_CLOCK_RATIO_9_CLK SNTCFG_CKDIV(8) /*!< EXMC_CLK = 9*HCLK */ +#define EXMC_SYN_CLOCK_RATIO_10_CLK SNTCFG_CKDIV(9) /*!< EXMC_CLK = 10*HCLK */ +#define EXMC_SYN_CLOCK_RATIO_11_CLK SNTCFG_CKDIV(10) /*!< EXMC_CLK = 11*HCLK */ +#define EXMC_SYN_CLOCK_RATIO_12_CLK SNTCFG_CKDIV(11) /*!< EXMC_CLK = 12*HCLK */ +#define EXMC_SYN_CLOCK_RATIO_13_CLK SNTCFG_CKDIV(12) /*!< EXMC_CLK = 13*HCLK */ +#define EXMC_SYN_CLOCK_RATIO_14_CLK SNTCFG_CKDIV(13) /*!< EXMC_CLK = 14*HCLK */ +#define EXMC_SYN_CLOCK_RATIO_15_CLK SNTCFG_CKDIV(14) /*!< EXMC_CLK = 15*HCLK */ +#define EXMC_SYN_CLOCK_RATIO_16_CLK SNTCFG_CKDIV(15) /*!< EXMC_CLK = 16*HCLK */ +/* EXMC NOR/SRAM write mode */ +#define EXMC_ASYN_WRITE ((uint32_t)0x00000000U) /*!< asynchronous write mode */ +#define EXMC_SYN_WRITE EXMC_SNCTL_SYNCWR /*!< synchronous write mode */ + +/* EXMC NWAIT signal configuration */ +#define EXMC_NWAIT_CONFIG_BEFORE ((uint32_t)0x00000000U) /*!< NWAIT signal is active one data cycle before wait state */ +#define EXMC_NWAIT_CONFIG_DURING EXMC_SNCTL_NRWTCFG /*!< NWAIT signal is active during wait state */ + +/* EXMC NWAIT signal polarity configuration */ +#define EXMC_NWAIT_POLARITY_LOW ((uint32_t)0x00000000U) /*!< low level is active of NWAIT */ +#define EXMC_NWAIT_POLARITY_HIGH EXMC_SNCTL_NRWTPOL /*!< high level is active of NWAIT */ + +/* NAND/PC card */ +/* ECC size */ +#define NPCTL_ECCSZ(regval) (BITS(17,19) & ((uint32_t)(regval) << 17)) +#define EXMC_ECC_SIZE_256BYTES NPCTL_ECCSZ(0) /* 256 bytes */ +#define EXMC_ECC_SIZE_512BYTES NPCTL_ECCSZ(1) /* 512 bytes */ +#define EXMC_ECC_SIZE_1024BYTES NPCTL_ECCSZ(2) /* 1024 bytes */ +#define EXMC_ECC_SIZE_2048BYTES NPCTL_ECCSZ(3) /* 2048 bytes */ +#define EXMC_ECC_SIZE_4096BYTES NPCTL_ECCSZ(4) /* 4096 bytes */ +#define EXMC_ECC_SIZE_8192BYTES NPCTL_ECCSZ(5) /* 8192 bytes */ + +/* ALE to RE delay */ +#define NPCTL_ATR(regval) (BITS(13,16) & ((uint32_t)(regval) << 13)) +#define EXMC_ALE_RE_DELAY_1_HCLK NPCTL_ATR(0) /* ALE to RE delay = 1*HCLK */ +#define EXMC_ALE_RE_DELAY_2_HCLK NPCTL_ATR(1) /* ALE to RE delay = 2*HCLK */ +#define EXMC_ALE_RE_DELAY_3_HCLK NPCTL_ATR(2) /* ALE to RE delay = 3*HCLK */ +#define EXMC_ALE_RE_DELAY_4_HCLK NPCTL_ATR(3) /* ALE to RE delay = 4*HCLK */ +#define EXMC_ALE_RE_DELAY_5_HCLK NPCTL_ATR(4) /* ALE to RE delay = 5*HCLK */ +#define EXMC_ALE_RE_DELAY_6_HCLK NPCTL_ATR(5) /* ALE to RE delay = 6*HCLK */ +#define EXMC_ALE_RE_DELAY_7_HCLK NPCTL_ATR(6) /* ALE to RE delay = 7*HCLK */ +#define EXMC_ALE_RE_DELAY_8_HCLK NPCTL_ATR(7) /* ALE to RE delay = 8*HCLK */ +#define EXMC_ALE_RE_DELAY_9_HCLK NPCTL_ATR(8) /* ALE to RE delay = 9*HCLK */ +#define EXMC_ALE_RE_DELAY_10_HCLK NPCTL_ATR(9) /* ALE to RE delay = 10*HCLK */ +#define EXMC_ALE_RE_DELAY_11_HCLK NPCTL_ATR(10) /* ALE to RE delay = 11*HCLK */ +#define EXMC_ALE_RE_DELAY_12_HCLK NPCTL_ATR(11) /* ALE to RE delay = 12*HCLK */ +#define EXMC_ALE_RE_DELAY_13_HCLK NPCTL_ATR(12) /* ALE to RE delay = 13*HCLK */ +#define EXMC_ALE_RE_DELAY_14_HCLK NPCTL_ATR(13) /* ALE to RE delay = 14*HCLK */ +#define EXMC_ALE_RE_DELAY_15_HCLK NPCTL_ATR(14) /* ALE to RE delay = 15*HCLK */ +#define EXMC_ALE_RE_DELAY_16_HCLK NPCTL_ATR(15) /* ALE to RE delay = 16*HCLK */ + +/* CLE to RE delay */ +#define NPCTL_CTR(regval) (BITS(9,12) & ((uint32_t)(regval) << 9)) +#define EXMC_CLE_RE_DELAY_1_HCLK NPCTL_CTR(0) /* CLE to RE delay = 1*HCLK */ +#define EXMC_CLE_RE_DELAY_2_HCLK NPCTL_CTR(1) /* CLE to RE delay = 2*HCLK */ +#define EXMC_CLE_RE_DELAY_3_HCLK NPCTL_CTR(2) /* CLE to RE delay = 3*HCLK */ +#define EXMC_CLE_RE_DELAY_4_HCLK NPCTL_CTR(3) /* CLE to RE delay = 4*HCLK */ +#define EXMC_CLE_RE_DELAY_5_HCLK NPCTL_CTR(4) /* CLE to RE delay = 5*HCLK */ +#define EXMC_CLE_RE_DELAY_6_HCLK NPCTL_CTR(5) /* CLE to RE delay = 6*HCLK */ +#define EXMC_CLE_RE_DELAY_7_HCLK NPCTL_CTR(6) /* CLE to RE delay = 7*HCLK */ +#define EXMC_CLE_RE_DELAY_8_HCLK NPCTL_CTR(7) /* CLE to RE delay = 8*HCLK */ +#define EXMC_CLE_RE_DELAY_9_HCLK NPCTL_CTR(8) /* CLE to RE delay = 9*HCLK */ +#define EXMC_CLE_RE_DELAY_10_HCLK NPCTL_CTR(9) /* CLE to RE delay = 10*HCLK */ +#define EXMC_CLE_RE_DELAY_11_HCLK NPCTL_CTR(10) /* CLE to RE delay = 11*HCLK */ +#define EXMC_CLE_RE_DELAY_12_HCLK NPCTL_CTR(11) /* CLE to RE delay = 12*HCLK */ +#define EXMC_CLE_RE_DELAY_13_HCLK NPCTL_CTR(12) /* CLE to RE delay = 13*HCLK */ +#define EXMC_CLE_RE_DELAY_14_HCLK NPCTL_CTR(13) /* CLE to RE delay = 14*HCLK */ +#define EXMC_CLE_RE_DELAY_15_HCLK NPCTL_CTR(14) /* CLE to RE delay = 15*HCLK */ +#define EXMC_CLE_RE_DELAY_16_HCLK NPCTL_CTR(15) /* CLE to RE delay = 16*HCLK */ + +/* NAND bank memory data bus width */ +#define NPCTL_NDW(regval) (BITS(4,5) & ((uint32_t)(regval) << 4)) +#define EXMC_NAND_DATABUS_WIDTH_8B NPCTL_NDW(0) /*!< NAND data width 8 bits */ +#define EXMC_NAND_DATABUS_WIDTH_16B NPCTL_NDW(1) /*!< NAND data width 16 bits */ + +/* SDRAM */ +/* SDRAM pipeline delay */ +#define SDCTL_PIPED(regval) (BITS(13,14) & ((uint32_t)(regval) << 13)) +#define EXMC_PIPELINE_DELAY_0_HCLK SDCTL_PIPED(0) /*!< 0 HCLK clock cycle delay */ +#define EXMC_PIPELINE_DELAY_1_HCLK SDCTL_PIPED(1) /*!< 1 HCLK clock cycle delay */ +#define EXMC_PIPELINE_DELAY_2_HCLK SDCTL_PIPED(2) /*!< 2 HCLK clock cycle delay */ + +/* SDRAM clock configuration */ +#define SDCTL_SDCLK(regval) (BITS(10,11) & ((uint32_t)(regval) << 10)) +#define EXMC_SDCLK_DISABLE SDCTL_SDCLK(0) /*!< SDCLK memory clock disabled */ +#define EXMC_SDCLK_PERIODS_2_HCLK SDCTL_SDCLK(2) /*!< SDCLK memory period = 2*HCLK */ +#define EXMC_SDCLK_PERIODS_3_HCLK SDCTL_SDCLK(3) /*!< SDCLK memory period = 3*HCLK */ + +/* CAS latency */ +#define SDCTL_CL(regval) (BITS(7,8) & ((uint32_t)(regval) << 7)) +#define EXMC_CAS_LATENCY_1_SDCLK SDCTL_CL(1) /*!< CAS latency is 1 memory clock cycle */ +#define EXMC_CAS_LATENCY_2_SDCLK SDCTL_CL(2) /*!< CAS latency is 2 memory clock cycle */ +#define EXMC_CAS_LATENCY_3_SDCLK SDCTL_CL(3) /*!< CAS latency is 3 memory clock cycle */ + +/* SDRAM data bus width */ +#define SDCTL_SDW(regval) (BITS(4,5) & ((uint32_t)(regval) << 4)) +#define EXMC_SDRAM_DATABUS_WIDTH_8B SDCTL_SDW(0) /*!< SDRAM data width 8 bits */ +#define EXMC_SDRAM_DATABUS_WIDTH_16B SDCTL_SDW(1) /*!< SDRAM data width 16 bits */ +#define EXMC_SDRAM_DATABUS_WIDTH_32B SDCTL_SDW(2) /*!< SDRAM data width 32 bits */ + +/* SDRAM row address bit width */ +#define SDCTL_RAW(regval) (BITS(2,3) & ((uint32_t)(regval) << 2)) +#define EXMC_SDRAM_ROW_ADDRESS_11 SDCTL_RAW(0) /*!< row address bit width is 11 bits */ +#define EXMC_SDRAM_ROW_ADDRESS_12 SDCTL_RAW(1) /*!< row address bit width is 12 bits */ +#define EXMC_SDRAM_ROW_ADDRESS_13 SDCTL_RAW(2) /*!< row address bit width is 13 bits */ + +/* SDRAM column address bit width */ +#define SDCTL_CAW(regval) (BITS(0,1) & ((uint32_t)(regval) << 0)) +#define EXMC_SDRAM_COW_ADDRESS_8 SDCTL_CAW(0) /*!< column address bit width is 8 bits */ +#define EXMC_SDRAM_COW_ADDRESS_9 SDCTL_CAW(1) /*!< column address bit width is 9 bits */ +#define EXMC_SDRAM_COW_ADDRESS_10 SDCTL_CAW(2) /*!< column address bit width is 10 bits */ +#define EXMC_SDRAM_COW_ADDRESS_11 SDCTL_CAW(3) /*!< column address bit width is 11 bits */ + +/* SDRAM number of successive auto-refresh */ +#define SDCMD_NARF(regval) (BITS(5,8) & ((uint32_t)(regval) << 5)) +#define EXMC_SDRAM_AUTO_REFLESH_1_SDCLK SDCMD_NARF(0) /*!< 1 auto-refresh cycle */ +#define EXMC_SDRAM_AUTO_REFLESH_2_SDCLK SDCMD_NARF(1) /*!< 2 auto-refresh cycles */ +#define EXMC_SDRAM_AUTO_REFLESH_3_SDCLK SDCMD_NARF(2) /*!< 3 auto-refresh cycles */ +#define EXMC_SDRAM_AUTO_REFLESH_4_SDCLK SDCMD_NARF(3) /*!< 4 auto-refresh cycles */ +#define EXMC_SDRAM_AUTO_REFLESH_5_SDCLK SDCMD_NARF(4) /*!< 5 auto-refresh cycles */ +#define EXMC_SDRAM_AUTO_REFLESH_6_SDCLK SDCMD_NARF(5) /*!< 6 auto-refresh cycles */ +#define EXMC_SDRAM_AUTO_REFLESH_7_SDCLK SDCMD_NARF(6) /*!< 7 auto-refresh cycles */ +#define EXMC_SDRAM_AUTO_REFLESH_8_SDCLK SDCMD_NARF(7) /*!< 8 auto-refresh cycles */ +#define EXMC_SDRAM_AUTO_REFLESH_9_SDCLK SDCMD_NARF(8) /*!< 9 auto-refresh cycles */ +#define EXMC_SDRAM_AUTO_REFLESH_10_SDCLK SDCMD_NARF(9) /*!< 10 auto-refresh cycles */ +#define EXMC_SDRAM_AUTO_REFLESH_11_SDCLK SDCMD_NARF(10) /*!< 11 auto-refresh cycles */ +#define EXMC_SDRAM_AUTO_REFLESH_12_SDCLK SDCMD_NARF(11) /*!< 12 auto-refresh cycles */ +#define EXMC_SDRAM_AUTO_REFLESH_13_SDCLK SDCMD_NARF(12) /*!< 13 auto-refresh cycles */ +#define EXMC_SDRAM_AUTO_REFLESH_14_SDCLK SDCMD_NARF(13) /*!< 14 auto-refresh cycles */ +#define EXMC_SDRAM_AUTO_REFLESH_15_SDCLK SDCMD_NARF(14) /*!< 15 auto-refresh cycles */ + +/* SDRAM command select */ +#define SDCMD_CMD(regval) (BITS(0,2) & ((uint32_t)(regval) << 0)) +#define EXMC_SDRAM_NORMAL_OPERATION SDCMD_CMD(0) /*!< normal operation command */ +#define EXMC_SDRAM_CLOCK_ENABLE SDCMD_CMD(1) /*!< clock enable command */ +#define EXMC_SDRAM_PRECHARGE_ALL SDCMD_CMD(2) /*!< precharge all command */ +#define EXMC_SDRAM_AUTO_REFRESH SDCMD_CMD(3) /*!< auto-refresh command */ +#define EXMC_SDRAM_LOAD_MODE_REGISTER SDCMD_CMD(4) /*!< load mode register command */ +#define EXMC_SDRAM_SELF_REFRESH SDCMD_CMD(5) /*!< self-refresh command */ +#define EXMC_SDRAM_POWERDOWN_ENTRY SDCMD_CMD(6) /*!< power-down entry command */ + +/* SDRAM the delayed sample clock of read data */ +#define SDRSCTL_SDSC(regval) (BITS(4,7) & ((uint32_t)(regval) << 4)) +#define EXMC_SDRAM_0_DELAY_CELL SDRSCTL_SDSC(0) /*!< select the clock after 0 delay cell */ +#define EXMC_SDRAM_1_DELAY_CELL SDRSCTL_SDSC(1) /*!< select the clock after 1 delay cell */ +#define EXMC_SDRAM_2_DELAY_CELL SDRSCTL_SDSC(2) /*!< select the clock after 2 delay cell */ +#define EXMC_SDRAM_3_DELAY_CELL SDRSCTL_SDSC(3) /*!< select the clock after 3 delay cell */ +#define EXMC_SDRAM_4_DELAY_CELL SDRSCTL_SDSC(4) /*!< select the clock after 4 delay cell */ +#define EXMC_SDRAM_5_DELAY_CELL SDRSCTL_SDSC(5) /*!< select the clock after 5 delay cell */ +#define EXMC_SDRAM_6_DELAY_CELL SDRSCTL_SDSC(6) /*!< select the clock after 6 delay cell */ +#define EXMC_SDRAM_7_DELAY_CELL SDRSCTL_SDSC(7) /*!< select the clock after 7 delay cell */ +#define EXMC_SDRAM_8_DELAY_CELL SDRSCTL_SDSC(8) /*!< select the clock after 8 delay cell */ +#define EXMC_SDRAM_9_DELAY_CELL SDRSCTL_SDSC(9) /*!< select the clock after 9 delay cell */ +#define EXMC_SDRAM_10_DELAY_CELL SDRSCTL_SDSC(10) /*!< select the clock after 10 delay cell */ +#define EXMC_SDRAM_11_DELAY_CELL SDRSCTL_SDSC(11) /*!< select the clock after 11 delay cell */ +#define EXMC_SDRAM_12_DELAY_CELL SDRSCTL_SDSC(12) /*!< select the clock after 12 delay cell */ +#define EXMC_SDRAM_13_DELAY_CELL SDRSCTL_SDSC(13) /*!< select the clock after 13 delay cell */ +#define EXMC_SDRAM_14_DELAY_CELL SDRSCTL_SDSC(14) /*!< select the clock after 14 delay cell */ +#define EXMC_SDRAM_15_DELAY_CELL SDRSCTL_SDSC(15) /*!< select the clock after 15 delay cell */ + + /* EXMC SDRAM internal banks */ +#define EXMC_SDRAM_2_INTER_BANK ((uint32_t)0x00000000U) /*!< 2 internal banks */ +#define EXMC_SDRAM_4_INTER_BANK EXMC_SDCTL_NBK /*!< 4 internal banks */ + +/* SDRAM device0 select */ +#define EXMC_SDRAM_DEVICE0_SELECT EXMC_SDCMD_DS0 /*!< SDRAM Device0 is selected */ + +/* SDRAM device1 select */ +#define EXMC_SDRAM_DEVICE1_SELECT EXMC_SDCMD_DS1 /*!< SDRAM Device1 is selected */ + +/* SDRAM device0 and device1 select */ +#define EXMC_SDRAM_DEVICE0_1_SELECT (EXMC_SDCMD_DS0 | EXMC_SDCMD_DS1) /*!< SDRAM Device1 is selected */ + +/* SDRAM device status */ +#define EXMC_SDRAM_DEVICE_NORMAL ((uint32_t)0x00000000U) /*!< normal status */ +#define EXMC_SDRAM_DEVICE_SELF_REFRESH ((uint32_t)0x00000001U) /*!< self refresh status */ +#define EXMC_SDRAM_DEVICE_POWER_DOWN ((uint32_t)0x00000002U) /*!< power down status */ + +/* sample cycle of read data */ +#define EXMC_SDRAM_READSAMPLE_0_EXTRAHCLK ((uint32_t)0x00000000U) /*!< add 0 extra HCLK cycle to the read data sample clock besides the delay chain */ +#define EXMC_SDRAM_READSAMPLE_1_EXTRAHCLK EXMC_SDRSCTL_SSCR /*!< add 1 extra HCLK cycle to the read data sample clock besides the delay chain */ + +/* SQPI PSRAM */ +/* SPI PSRAM ID length */ +#define SINIT_IDL(regval) (BITS(29,30) & ((uint32_t)(regval) << 29)) +#define EXMC_SQPIPSRAM_ID_LENGTH_64B SINIT_IDL(0) /*!< SPI PSRAM ID length is 64 bits */ +#define EXMC_SQPIPSRAM_ID_LENGTH_32B SINIT_IDL(1) /*!< SPI PSRAM ID length is 32 bits */ +#define EXMC_SQPIPSRAM_ID_LENGTH_16B SINIT_IDL(2) /*!< SPI PSRAM ID length is 16 bits */ +#define EXMC_SQPIPSRAM_ID_LENGTH_8B SINIT_IDL(3) /*!< SPI PSRAM ID length is 8 bits */ + +/* SPI PSRAM bit number of address phase */ +#define SINIT_ADRBIT(regval) (BITS(24,28) & ((uint32_t)(regval) << 24)) +#define EXMC_SQPIPSRAM_ADDR_LENGTH_1B SINIT_ADRBIT(1) /*!< SPI PSRAM address is 1 bit */ +#define EXMC_SQPIPSRAM_ADDR_LENGTH_2B SINIT_ADRBIT(2) /*!< SPI PSRAM address is 2 bits */ +#define EXMC_SQPIPSRAM_ADDR_LENGTH_3B SINIT_ADRBIT(3) /*!< SPI PSRAM address is 3 bits */ +#define EXMC_SQPIPSRAM_ADDR_LENGTH_4B SINIT_ADRBIT(4) /*!< SPI PSRAM address is 4 bits */ +#define EXMC_SQPIPSRAM_ADDR_LENGTH_5B SINIT_ADRBIT(5) /*!< SPI PSRAM address is 5 bits */ +#define EXMC_SQPIPSRAM_ADDR_LENGTH_6B SINIT_ADRBIT(6) /*!< SPI PSRAM address is 6 bits */ +#define EXMC_SQPIPSRAM_ADDR_LENGTH_7B SINIT_ADRBIT(7) /*!< SPI PSRAM address is 7 bits */ +#define EXMC_SQPIPSRAM_ADDR_LENGTH_8B SINIT_ADRBIT(8) /*!< SPI PSRAM address is 8 bits */ +#define EXMC_SQPIPSRAM_ADDR_LENGTH_9B SINIT_ADRBIT(9) /*!< SPI PSRAM address is 9 bits */ +#define EXMC_SQPIPSRAM_ADDR_LENGTH_10B SINIT_ADRBIT(10) /*!< SPI PSRAM address is 10 bits */ +#define EXMC_SQPIPSRAM_ADDR_LENGTH_11B SINIT_ADRBIT(11) /*!< SPI PSRAM address is 11 bits */ +#define EXMC_SQPIPSRAM_ADDR_LENGTH_12B SINIT_ADRBIT(12) /*!< SPI PSRAM address is 12 bits */ +#define EXMC_SQPIPSRAM_ADDR_LENGTH_13B SINIT_ADRBIT(13) /*!< SPI PSRAM address is 13 bits */ +#define EXMC_SQPIPSRAM_ADDR_LENGTH_14B SINIT_ADRBIT(14) /*!< SPI PSRAM address is 14 bits */ +#define EXMC_SQPIPSRAM_ADDR_LENGTH_15B SINIT_ADRBIT(15) /*!< SPI PSRAM address is 15 bits */ +#define EXMC_SQPIPSRAM_ADDR_LENGTH_16B SINIT_ADRBIT(16) /*!< SPI PSRAM address is 16 bits */ +#define EXMC_SQPIPSRAM_ADDR_LENGTH_17B SINIT_ADRBIT(17) /*!< SPI PSRAM address is 17 bits */ +#define EXMC_SQPIPSRAM_ADDR_LENGTH_18B SINIT_ADRBIT(18) /*!< SPI PSRAM address is 18 bits */ +#define EXMC_SQPIPSRAM_ADDR_LENGTH_19B SINIT_ADRBIT(19) /*!< SPI PSRAM address is 19 bits */ +#define EXMC_SQPIPSRAM_ADDR_LENGTH_20B SINIT_ADRBIT(20) /*!< SPI PSRAM address is 20 bits */ +#define EXMC_SQPIPSRAM_ADDR_LENGTH_21B SINIT_ADRBIT(21) /*!< SPI PSRAM address is 21 bits */ +#define EXMC_SQPIPSRAM_ADDR_LENGTH_22B SINIT_ADRBIT(22) /*!< SPI PSRAM address is 22 bits */ +#define EXMC_SQPIPSRAM_ADDR_LENGTH_23B SINIT_ADRBIT(23) /*!< SPI PSRAM address is 23 bits */ +#define EXMC_SQPIPSRAM_ADDR_LENGTH_24B SINIT_ADRBIT(24) /*!< SPI PSRAM address is 24 bits */ +#define EXMC_SQPIPSRAM_ADDR_LENGTH_25B SINIT_ADRBIT(25) /*!< SPI PSRAM address is 25 bits */ +#define EXMC_SQPIPSRAM_ADDR_LENGTH_26B SINIT_ADRBIT(26) /*!< SPI PSRAM address is 26 bits */ + +/* SPI PSRAM bit number of command phase */ +#define SINIT_CMDBIT(regval) (BITS(16,17) & ((uint32_t)(regval) << 16)) +#define EXMC_SQPIPSRAM_COMMAND_LENGTH_4B SINIT_CMDBIT(0) /*!< SPI PSRAM command is 4 bits */ +#define EXMC_SQPIPSRAM_COMMAND_LENGTH_8B SINIT_CMDBIT(1) /*!< SPI PSRAM command is 8 bits */ +#define EXMC_SQPIPSRAM_COMMAND_LENGTH_16B SINIT_CMDBIT(2) /*!< SPI PSRAM command is 16 bits */ + +/* SPI PSRAM read command mode */ +#define SRCMD_RMODE(regval) (BITS(20,21) & ((uint32_t)(regval) << 20)) +#define EXMC_SQPIPSRAM_READ_MODE_DISABLE SRCMD_RMODE(0) /*!< not SPI mode */ +#define EXMC_SQPIPSRAM_READ_MODE_SPI SRCMD_RMODE(1) /*!< SPI mode */ +#define EXMC_SQPIPSRAM_READ_MODE_SQPI SRCMD_RMODE(2) /*!< SQPI mode */ +#define EXMC_SQPIPSRAM_READ_MODE_QPI SRCMD_RMODE(3) /*!< QPI mode */ + +/* SPI PSRAM write command mode */ +#define SRCMD_WMODE(regval) (BITS(20,21) & ((uint32_t)(regval) << 20)) +#define EXMC_SQPIPSRAM_WRITE_MODE_DISABLE SRCMD_WMODE(0) /*!< not SPI mode */ +#define EXMC_SQPIPSRAM_WRITE_MODE_SPI SRCMD_WMODE(1) /*!< SPI mode */ +#define EXMC_SQPIPSRAM_WRITE_MODE_SQPI SRCMD_WMODE(2) /*!< SQPI mode */ +#define EXMC_SQPIPSRAM_WRITE_MODE_QPI SRCMD_WMODE(3) /*!< QPI mode */ + +/* read data sample polarity */ +#define EXMC_SQPIPSRAM_SAMPLE_RISING_EDGE ((uint32_t)0x00000000U) /*!< sample data at rising edge */ +#define EXMC_SQPIPSRAM_SAMPLE_FALLING_EDGE EXMC_SINIT_POL /*!< sample data at falling edge */ + +/* SQPI SRAM command flag */ +#define EXMC_SEND_COMMAND_FLAG_RDID EXMC_SRCMD_RDID /*!< EXMC_SRCMD_RDID flag bit */ +#define EXMC_SEND_COMMAND_FLAG_SC EXMC_SWCMD_SC /*!< EXMC_SWCMD_SC flag bit */ + +/* EXMC flag bits */ +#define EXMC_NAND_PCCARD_FLAG_RISE EXMC_NPINTEN_INTRS /*!< interrupt rising edge status */ +#define EXMC_NAND_PCCARD_FLAG_LEVEL EXMC_NPINTEN_INTHS /*!< interrupt high-level status */ +#define EXMC_NAND_PCCARD_FLAG_FALL EXMC_NPINTEN_INTFS /*!< interrupt falling edge status */ +#define EXMC_NAND_PCCARD_FLAG_FIFOE EXMC_NPINTEN_FFEPT /*!< FIFO empty flag */ +#define EXMC_SDRAM_FLAG_REFRESH EXMC_SDSDAT_REIF /*!< refresh error interrupt flag */ +#define EXMC_SDRAM_FLAG_NREADY EXMC_SDSDAT_NRDY /*!< not ready status */ + +/* EXMC interrupt enable bits */ +#define EXMC_NAND_PCCARD_INT_RISE EXMC_NPINTEN_INTREN /*!< interrupt rising edge detection enable */ +#define EXMC_NAND_PCCARD_INT_LEVEL EXMC_NPINTEN_INTHEN /*!< interrupt high-level detection enable */ +#define EXMC_NAND_PCCARD_INT_FALL EXMC_NPINTEN_INTFEN /*!< interrupt falling edge detection enable */ +#define EXMC_SDRAM_INT_REFRESH EXMC_SDARI_REIE /*!< interrupt refresh error enable */ + +/* EXMC interrupt flag bits */ +#define EXMC_NAND_PCCARD_INT_FLAG_RISE EXMC_NPINTEN_INTREN /*!< interrupt rising edge detection enable */ +#define EXMC_NAND_PCCARD_INT_FLAG_LEVEL EXMC_NPINTEN_INTHEN /*!< interrupt high-level detection enable */ +#define EXMC_NAND_PCCARD_INT_FLAG_FALL EXMC_NPINTEN_INTFEN /*!< interrupt falling edge detection enable */ +#define EXMC_SDRAM_INT_FLAG_REFRESH EXMC_SDARI_REIE /*!< interrupt refresh error enable */ + +/* function declarations */ +/* function configuration */ +/* deinitialize EXMC NOR/SRAM region */ +void exmc_norsram_deinit(uint32_t exmc_norsram_region); +/* exmc_norsram_parameter_struct parameter initialize */ +void exmc_norsram_struct_para_init(exmc_norsram_parameter_struct* exmc_norsram_init_struct); +/* initialize EXMC NOR/SRAM region */ +void exmc_norsram_init(exmc_norsram_parameter_struct* exmc_norsram_init_struct); +/* EXMC NOR/SRAM bank enable */ +void exmc_norsram_enable(uint32_t exmc_norsram_region); +/* EXMC NOR/SRAM bank disable */ +void exmc_norsram_disable(uint32_t exmc_norsram_region); + +/* deinitialize EXMC NAND bank */ +void exmc_nand_deinit(uint32_t exmc_nand_bank); +/* exmc_nand_init_struct parameter initialize */ +void exmc_nand_struct_para_init(exmc_nand_parameter_struct* exmc_nand_init_struct); +/* initialize EXMC NAND bank */ +void exmc_nand_init(exmc_nand_parameter_struct* exmc_nand_init_struct); +/* EXMC NAND bank enable */ +void exmc_nand_enable(uint32_t exmc_nand_bank); +/* EXMC NAND bank disable */ +void exmc_nand_disable(uint32_t exmc_nand_bank); +/* enable or disable the EXMC NAND ECC function */ +void exmc_nand_ecc_config(uint32_t exmc_nand_bank, ControlStatus newvalue); +/* get the EXMC ECC value */ +uint32_t exmc_ecc_get(uint32_t exmc_nand_bank); + +/* deinitialize EXMC PC card bank */ +void exmc_pccard_deinit(void); +/* initialize EXMC PC card bank */ +void exmc_pccard_init(exmc_pccard_parameter_struct* exmc_pccard_init_struct); +/* exmc_pccard_parameter_struct parameter initialize */ +void exmc_pccard_struct_para_init(exmc_pccard_parameter_struct* exmc_pccard_init_struct); +/* EXMC PC card bank enable */ +void exmc_pccard_enable(void); +/* EXMC PC card bank disable */ +void exmc_pccard_disable(void); + +/* deinitialize EXMC SDRAM device */ +void exmc_sdram_deinit(uint32_t exmc_sdram_device); +/* initialize EXMC SDRAM device */ +void exmc_sdram_init(exmc_sdram_parameter_struct* exmc_sdram_init_struct); +/* exmc_sdram_parameter_struct parameter initialize */ +void exmc_sdram_parameter_init(exmc_sdram_parameter_struct* exmc_sdram_init_struct); +/* configure the SDRAM memory command */ +void exmc_sdram_command_config(exmc_sdram_command_parameter_struct* exmc_sdram_command_init_struct); +/* set auto-refresh interval */ +void exmc_sdram_refresh_count_set(uint32_t exmc_count); +/* set the number of successive auto-refresh command */ +void exmc_sdram_autorefresh_number_set(uint32_t exmc_number); +/* config the write protection function */ +void exmc_sdram_write_protection_config(uint32_t exmc_sdram_device, ControlStatus newvalue); +/* get the status of SDRAM device0 or device1 */ +uint32_t exmc_sdram_bankstatus_get(uint32_t exmc_sdram_device); +/* configure the delayed sample clock of read data */ +void exmc_sdram_readsample_config(uint32_t delay_cell, uint32_t extra_hclk); +/* enable read sample */ +void exmc_sdram_readsample_enable(void); +/* disable read sample */ +void exmc_sdram_readsample_disable(void); + +/* deinitialize EXMC SQPIPSRAM */ +void exmc_sqpipsram_deinit(void); +/* initialize EXMC SQPIPSRAM */ +void exmc_sqpipsram_init(exmc_sqpipsram_parameter_struct* exmc_sqpipsram_init_struct); +/* exmc_sqpipsram_parameter_struct parameter initialize */ +void exmc_sqpipsram_parameter_init(exmc_sqpipsram_parameter_struct* exmc_sqpipsram_init_struct); +/* set the read command */ +void exmc_sqpipsram_read_command_set(uint32_t read_command_mode, uint32_t read_wait_cycle, uint32_t read_command_code); +/* set the write command */ +void exmc_sqpipsram_write_command_set(uint32_t write_command_mode, uint32_t write_wait_cycle, uint32_t write_command_code); +/* send SPI read ID command */ +void exmc_sqpipsram_read_id_command_send(void); +/* send SPI special command which does not have address and data phase */ +void exmc_sqpipsram_write_cmd_send(void); +/* get the EXMC SPI ID low data */ +uint32_t exmc_sqpipsram_low_id_get(void); +/* get the EXMC SPI ID high data */ +uint32_t exmc_sqpipsram_high_id_get(void); +/* get the bit value of EXMC send write command bit or read ID command */ +FlagStatus exmc_sqpipsram_send_command_state_get(uint32_t send_command_flag); + +/* interrupt & flag functions */ +/* check EXMC flag is set or not */ +FlagStatus exmc_flag_get(uint32_t bank, uint32_t flag); +/* clear EXMC flag */ +void exmc_flag_clear(uint32_t bank, uint32_t flag); +/* check EXMC flag is set or not */ +FlagStatus exmc_interrupt_flag_get(uint32_t bank, uint32_t interrupt_source); +/* clear EXMC flag */ +void exmc_interrupt_flag_clear(uint32_t bank, uint32_t interrupt_source); +/* enable EXMC interrupt */ +void exmc_interrupt_enable(uint32_t bank, uint32_t interrupt_source); +/* disable EXMC interrupt */ +void exmc_interrupt_disable(uint32_t bank, uint32_t interrupt_source); + +#endif /* GD32F20X_EXMC_H */ diff --git a/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_standard_peripheral/Include/gd32f20x_exti.h b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_standard_peripheral/Include/gd32f20x_exti.h new file mode 100644 index 0000000000..54f1faa366 --- /dev/null +++ b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_standard_peripheral/Include/gd32f20x_exti.h @@ -0,0 +1,258 @@ +/*! + \file gd32f20x_exti.h + \brief definitions for the EXTI + + \version 2015-07-15, V1.0.0, firmware for GD32F20x + \version 2017-06-05, V2.0.0, firmware for GD32F20x + \version 2018-10-31, V2.1.0, firmware for GD32F20x + \version 2020-09-30, V2.2.0, firmware for GD32F20x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef GD32F20X_EXTI_H +#define GD32F20X_EXTI_H + +#include "gd32f20x.h" + +/* EXTI definitions */ +#define EXTI EXTI_BASE + +/* registers definitions */ +#define EXTI_INTEN REG32(EXTI + 0x00U) /*!< interrupt enable register */ +#define EXTI_EVEN REG32(EXTI + 0x04U) /*!< event enable register */ +#define EXTI_RTEN REG32(EXTI + 0x08U) /*!< rising edge trigger enable register */ +#define EXTI_FTEN REG32(EXTI + 0x0CU) /*!< falling trigger enable register */ +#define EXTI_SWIEV REG32(EXTI + 0x10U) /*!< software interrupt event register */ +#define EXTI_PD REG32(EXTI + 0x14U) /*!< pending register */ + +/* bits definitions */ +/* EXTI_INTEN */ +#define EXTI_INTEN_INTEN0 BIT(0) /*!< interrupt from line 0 */ +#define EXTI_INTEN_INTEN1 BIT(1) /*!< interrupt from line 1 */ +#define EXTI_INTEN_INTEN2 BIT(2) /*!< interrupt from line 2 */ +#define EXTI_INTEN_INTEN3 BIT(3) /*!< interrupt from line 3 */ +#define EXTI_INTEN_INTEN4 BIT(4) /*!< interrupt from line 4 */ +#define EXTI_INTEN_INTEN5 BIT(5) /*!< interrupt from line 5 */ +#define EXTI_INTEN_INTEN6 BIT(6) /*!< interrupt from line 6 */ +#define EXTI_INTEN_INTEN7 BIT(7) /*!< interrupt from line 7 */ +#define EXTI_INTEN_INTEN8 BIT(8) /*!< interrupt from line 8 */ +#define EXTI_INTEN_INTEN9 BIT(9) /*!< interrupt from line 9 */ +#define EXTI_INTEN_INTEN10 BIT(10) /*!< interrupt from line 10 */ +#define EXTI_INTEN_INTEN11 BIT(11) /*!< interrupt from line 11 */ +#define EXTI_INTEN_INTEN12 BIT(12) /*!< interrupt from line 12 */ +#define EXTI_INTEN_INTEN13 BIT(13) /*!< interrupt from line 13 */ +#define EXTI_INTEN_INTEN14 BIT(14) /*!< interrupt from line 14 */ +#define EXTI_INTEN_INTEN15 BIT(15) /*!< interrupt from line 15 */ +#define EXTI_INTEN_INTEN16 BIT(16) /*!< interrupt from line 16 */ +#define EXTI_INTEN_INTEN17 BIT(17) /*!< interrupt from line 17 */ +#define EXTI_INTEN_INTEN18 BIT(18) /*!< interrupt from line 18 */ +#define EXTI_INTEN_INTEN19 BIT(19) /*!< interrupt from line 19 */ + +/* EXTI_EVEN */ +#define EXTI_EVEN_EVEN0 BIT(0) /*!< event from line 0 */ +#define EXTI_EVEN_EVEN1 BIT(1) /*!< event from line 1 */ +#define EXTI_EVEN_EVEN2 BIT(2) /*!< event from line 2 */ +#define EXTI_EVEN_EVEN3 BIT(3) /*!< event from line 3 */ +#define EXTI_EVEN_EVEN4 BIT(4) /*!< event from line 4 */ +#define EXTI_EVEN_EVEN5 BIT(5) /*!< event from line 5 */ +#define EXTI_EVEN_EVEN6 BIT(6) /*!< event from line 6 */ +#define EXTI_EVEN_EVEN7 BIT(7) /*!< event from line 7 */ +#define EXTI_EVEN_EVEN8 BIT(8) /*!< event from line 8 */ +#define EXTI_EVEN_EVEN9 BIT(9) /*!< event from line 9 */ +#define EXTI_EVEN_EVEN10 BIT(10) /*!< event from line 10 */ +#define EXTI_EVEN_EVEN11 BIT(11) /*!< event from line 11 */ +#define EXTI_EVEN_EVEN12 BIT(12) /*!< event from line 12 */ +#define EXTI_EVEN_EVEN13 BIT(13) /*!< event from line 13 */ +#define EXTI_EVEN_EVEN14 BIT(14) /*!< event from line 14 */ +#define EXTI_EVEN_EVEN15 BIT(15) /*!< event from line 15 */ +#define EXTI_EVEN_EVEN16 BIT(16) /*!< event from line 16 */ +#define EXTI_EVEN_EVEN17 BIT(17) /*!< event from line 17 */ +#define EXTI_EVEN_EVEN18 BIT(18) /*!< event from line 18 */ +#define EXTI_EVEN_EVEN19 BIT(19) /*!< event from line 19 */ + +/* EXTI_RTEN */ +#define EXTI_RTEN_RTEN0 BIT(0) /*!< rising edge from line 0 */ +#define EXTI_RTEN_RTEN1 BIT(1) /*!< rising edge from line 1 */ +#define EXTI_RTEN_RTEN2 BIT(2) /*!< rising edge from line 2 */ +#define EXTI_RTEN_RTEN3 BIT(3) /*!< rising edge from line 3 */ +#define EXTI_RTEN_RTEN4 BIT(4) /*!< rising edge from line 4 */ +#define EXTI_RTEN_RTEN5 BIT(5) /*!< rising edge from line 5 */ +#define EXTI_RTEN_RTEN6 BIT(6) /*!< rising edge from line 6 */ +#define EXTI_RTEN_RTEN7 BIT(7) /*!< rising edge from line 7 */ +#define EXTI_RTEN_RTEN8 BIT(8) /*!< rising edge from line 8 */ +#define EXTI_RTEN_RTEN9 BIT(9) /*!< rising edge from line 9 */ +#define EXTI_RTEN_RTEN10 BIT(10) /*!< rising edge from line 10 */ +#define EXTI_RTEN_RTEN11 BIT(11) /*!< rising edge from line 11 */ +#define EXTI_RTEN_RTEN12 BIT(12) /*!< rising edge from line 12 */ +#define EXTI_RTEN_RTEN13 BIT(13) /*!< rising edge from line 13 */ +#define EXTI_RTEN_RTEN14 BIT(14) /*!< rising edge from line 14 */ +#define EXTI_RTEN_RTEN15 BIT(15) /*!< rising edge from line 15 */ +#define EXTI_RTEN_RTEN16 BIT(16) /*!< rising edge from line 16 */ +#define EXTI_RTEN_RTEN17 BIT(17) /*!< rising edge from line 17 */ +#define EXTI_RTEN_RTEN18 BIT(18) /*!< rising edge from line 18 */ +#define EXTI_RTEN_RTEN19 BIT(19) /*!< rising edge from line 19 */ + +/* EXTI_FTEN */ +#define EXTI_FTEN_FTEN0 BIT(0) /*!< falling edge from line 0 */ +#define EXTI_FTEN_FTEN1 BIT(1) /*!< falling edge from line 1 */ +#define EXTI_FTEN_FTEN2 BIT(2) /*!< falling edge from line 2 */ +#define EXTI_FTEN_FTEN3 BIT(3) /*!< falling edge from line 3 */ +#define EXTI_FTEN_FTEN4 BIT(4) /*!< falling edge from line 4 */ +#define EXTI_FTEN_FTEN5 BIT(5) /*!< falling edge from line 5 */ +#define EXTI_FTEN_FTEN6 BIT(6) /*!< falling edge from line 6 */ +#define EXTI_FTEN_FTEN7 BIT(7) /*!< falling edge from line 7 */ +#define EXTI_FTEN_FTEN8 BIT(8) /*!< falling edge from line 8 */ +#define EXTI_FTEN_FTEN9 BIT(9) /*!< falling edge from line 9 */ +#define EXTI_FTEN_FTEN10 BIT(10) /*!< falling edge from line 10 */ +#define EXTI_FTEN_FTEN11 BIT(11) /*!< falling edge from line 11 */ +#define EXTI_FTEN_FTEN12 BIT(12) /*!< falling edge from line 12 */ +#define EXTI_FTEN_FTEN13 BIT(13) /*!< falling edge from line 13 */ +#define EXTI_FTEN_FTEN14 BIT(14) /*!< falling edge from line 14 */ +#define EXTI_FTEN_FTEN15 BIT(15) /*!< falling edge from line 15 */ +#define EXTI_FTEN_FTEN16 BIT(16) /*!< falling edge from line 16 */ +#define EXTI_FTEN_FTEN17 BIT(17) /*!< falling edge from line 17 */ +#define EXTI_FTEN_FTEN18 BIT(18) /*!< falling edge from line 18 */ +#define EXTI_FTEN_FTEN19 BIT(19) /*!< falling edge from line 19 */ + +/* EXTI_SWIEV */ +#define EXTI_SWIEV_SWIEV0 BIT(0) /*!< software interrupt/event request from line 0 */ +#define EXTI_SWIEV_SWIEV1 BIT(1) /*!< software interrupt/event request from line 1 */ +#define EXTI_SWIEV_SWIEV2 BIT(2) /*!< software interrupt/event request from line 2 */ +#define EXTI_SWIEV_SWIEV3 BIT(3) /*!< software interrupt/event request from line 3 */ +#define EXTI_SWIEV_SWIEV4 BIT(4) /*!< software interrupt/event request from line 4 */ +#define EXTI_SWIEV_SWIEV5 BIT(5) /*!< software interrupt/event request from line 5 */ +#define EXTI_SWIEV_SWIEV6 BIT(6) /*!< software interrupt/event request from line 6 */ +#define EXTI_SWIEV_SWIEV7 BIT(7) /*!< software interrupt/event request from line 7 */ +#define EXTI_SWIEV_SWIEV8 BIT(8) /*!< software interrupt/event request from line 8 */ +#define EXTI_SWIEV_SWIEV9 BIT(9) /*!< software interrupt/event request from line 9 */ +#define EXTI_SWIEV_SWIEV10 BIT(10) /*!< software interrupt/event request from line 10 */ +#define EXTI_SWIEV_SWIEV11 BIT(11) /*!< software interrupt/event request from line 11 */ +#define EXTI_SWIEV_SWIEV12 BIT(12) /*!< software interrupt/event request from line 12 */ +#define EXTI_SWIEV_SWIEV13 BIT(13) /*!< software interrupt/event request from line 13 */ +#define EXTI_SWIEV_SWIEV14 BIT(14) /*!< software interrupt/event request from line 14 */ +#define EXTI_SWIEV_SWIEV15 BIT(15) /*!< software interrupt/event request from line 15 */ +#define EXTI_SWIEV_SWIEV16 BIT(16) /*!< software interrupt/event request from line 16 */ +#define EXTI_SWIEV_SWIEV17 BIT(17) /*!< software interrupt/event request from line 17 */ +#define EXTI_SWIEV_SWIEV18 BIT(18) /*!< software interrupt/event request from line 18 */ +#define EXTI_SWIEV_SWIEV19 BIT(19) /*!< software interrupt/event request from line 19 */ + +/* EXTI_PD */ +#define EXTI_PD_PD0 BIT(0) /*!< interrupt/event pending status from line 0 */ +#define EXTI_PD_PD1 BIT(1) /*!< interrupt/event pending status from line 1 */ +#define EXTI_PD_PD2 BIT(2) /*!< interrupt/event pending status from line 2 */ +#define EXTI_PD_PD3 BIT(3) /*!< interrupt/event pending status from line 3 */ +#define EXTI_PD_PD4 BIT(4) /*!< interrupt/event pending status from line 4 */ +#define EXTI_PD_PD5 BIT(5) /*!< interrupt/event pending status from line 5 */ +#define EXTI_PD_PD6 BIT(6) /*!< interrupt/event pending status from line 6 */ +#define EXTI_PD_PD7 BIT(7) /*!< interrupt/event pending status from line 7 */ +#define EXTI_PD_PD8 BIT(8) /*!< interrupt/event pending status from line 8 */ +#define EXTI_PD_PD9 BIT(9) /*!< interrupt/event pending status from line 9 */ +#define EXTI_PD_PD10 BIT(10) /*!< interrupt/event pending status from line 10 */ +#define EXTI_PD_PD11 BIT(11) /*!< interrupt/event pending status from line 11 */ +#define EXTI_PD_PD12 BIT(12) /*!< interrupt/event pending status from line 12 */ +#define EXTI_PD_PD13 BIT(13) /*!< interrupt/event pending status from line 13 */ +#define EXTI_PD_PD14 BIT(14) /*!< interrupt/event pending status from line 14 */ +#define EXTI_PD_PD15 BIT(15) /*!< interrupt/event pending status from line 15 */ +#define EXTI_PD_PD16 BIT(16) /*!< interrupt/event pending status from line 16 */ +#define EXTI_PD_PD17 BIT(17) /*!< interrupt/event pending status from line 17 */ +#define EXTI_PD_PD18 BIT(18) /*!< interrupt/event pending status from line 18 */ +#define EXTI_PD_PD19 BIT(19) /*!< interrupt/event pending status from line 19 */ + +/* constants definitions */ +/* EXTI line number */ +typedef enum +{ + EXTI_0 = BIT(0), /*!< EXTI line 0 */ + EXTI_1 = BIT(1), /*!< EXTI line 1 */ + EXTI_2 = BIT(2), /*!< EXTI line 2 */ + EXTI_3 = BIT(3), /*!< EXTI line 3 */ + EXTI_4 = BIT(4), /*!< EXTI line 4 */ + EXTI_5 = BIT(5), /*!< EXTI line 5 */ + EXTI_6 = BIT(6), /*!< EXTI line 6 */ + EXTI_7 = BIT(7), /*!< EXTI line 7 */ + EXTI_8 = BIT(8), /*!< EXTI line 8 */ + EXTI_9 = BIT(9), /*!< EXTI line 9 */ + EXTI_10 = BIT(10), /*!< EXTI line 10 */ + EXTI_11 = BIT(11), /*!< EXTI line 11 */ + EXTI_12 = BIT(12), /*!< EXTI line 12 */ + EXTI_13 = BIT(13), /*!< EXTI line 13 */ + EXTI_14 = BIT(14), /*!< EXTI line 14 */ + EXTI_15 = BIT(15), /*!< EXTI line 15 */ + EXTI_16 = BIT(16), /*!< EXTI line 16 */ + EXTI_17 = BIT(17), /*!< EXTI line 17 */ + EXTI_18 = BIT(18), /*!< EXTI line 18 */ + EXTI_19 = BIT(19), /*!< EXTI line 19 */ +}exti_line_enum; + +/* external interrupt and event */ +typedef enum +{ + EXTI_INTERRUPT = 0, /*!< EXTI interrupt mode */ + EXTI_EVENT /*!< EXTI event mode */ +}exti_mode_enum; + +/* interrupt trigger mode */ +typedef enum +{ + EXTI_TRIG_RISING = 0, /*!< EXTI rising edge trigger */ + EXTI_TRIG_FALLING, /*!< EXTI falling edge trigger */ + EXTI_TRIG_BOTH /*!< EXTI rising and falling edge trigger */ +}exti_trig_type_enum; + +/* function declarations */ +/* initialization, EXTI lines configuration functions */ +/* deinitialize the EXTI */ +void exti_deinit(void); +/* enable the configuration of EXTI initialize */ +void exti_init(exti_line_enum linex, exti_mode_enum mode, exti_trig_type_enum trig_type); +/* enable the interrupts from EXTI line x */ +void exti_interrupt_enable(exti_line_enum linex); +/* enable the events from EXTI line x */ +void exti_event_enable(exti_line_enum linex); +/* disable the interrupts from EXTI line x */ +void exti_interrupt_disable(exti_line_enum linex); +/* disable the events from EXTI line x */ +void exti_event_disable(exti_line_enum linex); + +/* interrupt & flag functions */ +/* get EXTI lines pending flag */ +FlagStatus exti_flag_get(exti_line_enum linex); +/* clear EXTI lines pending flag */ +void exti_flag_clear(exti_line_enum linex); +/* get EXTI lines flag when the interrupt flag is set */ +FlagStatus exti_interrupt_flag_get(exti_line_enum linex); +/* clear EXTI lines pending flag */ +void exti_interrupt_flag_clear(exti_line_enum linex); +/* enable the EXTI software interrupt event */ +void exti_software_interrupt_enable(exti_line_enum linex); +/* disable the EXTI software interrupt event */ +void exti_software_interrupt_disable(exti_line_enum linex); + +#endif /* GD32F20X_EXTI_H */ + diff --git a/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_standard_peripheral/Include/gd32f20x_fmc.h b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_standard_peripheral/Include/gd32f20x_fmc.h new file mode 100644 index 0000000000..0d2a2ea9e9 --- /dev/null +++ b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_standard_peripheral/Include/gd32f20x_fmc.h @@ -0,0 +1,369 @@ +/*! + \file gd32f20x_fmc.h + \brief definitions for the FMC + + \version 2015-07-15, V1.0.0, firmware for GD32F20x + \version 2017-06-05, V2.0.0, firmware for GD32F20x + \version 2018-10-31, V2.1.0, firmware for GD32F20x + \version 2020-09-30, V2.2.0, firmware for GD32F20x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef GD32F20X_FMC_H +#define GD32F20X_FMC_H + +#include "gd32f20x.h" + +/* FMC and option byte definition */ +#define FMC FMC_BASE /*!< FMC register base address */ +#define OB OB_BASE /*!< option bytes base address */ + +/* registers definitions */ +#define FMC_WS REG32((FMC) + 0x00U) /*!< FMC wait state register */ +#define FMC_KEY0 REG32((FMC) + 0x04U) /*!< FMC unlock key register 0 */ +#define FMC_OBKEY REG32((FMC) + 0x08U) /*!< FMC option bytes unlock key register */ +#define FMC_STAT0 REG32((FMC) + 0x0CU) /*!< FMC status register 0 */ +#define FMC_CTL0 REG32((FMC) + 0x10U) /*!< FMC control register 0 */ +#define FMC_ADDR0 REG32((FMC) + 0x14U) /*!< FMC address register 0 */ +#define FMC_OBSTAT REG32((FMC) + 0x1CU) /*!< FMC option bytes status register */ +#define FMC_WP REG32((FMC) + 0x20U) /*!< FMC erase/program protection register */ +#define FMC_KEY1 REG32((FMC) + 0x44U) /*!< FMC unlock key register 1 */ +#define FMC_STAT1 REG32((FMC) + 0x4CU) /*!< FMC status register 1 */ +#define FMC_CTL1 REG32((FMC) + 0x50U) /*!< FMC control register 1 */ +#define FMC_ADDR1 REG32((FMC) + 0x54U) /*!< FMC address register 1 */ +#define FMC_WSEN REG32((FMC) + 0xFCU) /*!< FMC wait state enable register */ +#define FMC_PID REG32((FMC) + 0x100U) /*!< FMC product ID register */ + +#define OB_SPC REG16((OB) + 0x00U) /*!< option byte security protection value */ +#define OB_USER REG16((OB) + 0x02U) /*!< option byte user value*/ +#define OB_WP0 REG16((OB) + 0x08U) /*!< option byte write protection 0 */ +#define OB_WP1 REG16((OB) + 0x0AU) /*!< option byte write protection 1 */ +#define OB_WP2 REG16((OB) + 0x0CU) /*!< option byte write protection 2 */ +#define OB_WP3 REG16((OB) + 0x0EU) /*!< option byte write protection 3 */ + +/* bits definitions */ +/* FMC_WS */ +#define FMC_WS_WSCNT BITS(0,2) /*!< wait state counter */ + +/* FMC_KEY0 */ +#define FMC_KEY0_KEY BITS(0,31) /*!< FMC_CTL0 unlock key bits */ + +/* FMC_OBKEY */ +#define FMC_OBKEY_OBKEY BITS(0,31) /*!< option bytes unlock key bits */ + +/* FMC_STAT0 */ +#define FMC_STAT0_BUSY BIT(0) /*!< flash busy flag bit */ +#define FMC_STAT0_PGERR BIT(2) /*!< flash program error flag bit */ +#define FMC_STAT0_WPERR BIT(4) /*!< erase/program protection error flag bit */ +#define FMC_STAT0_ENDF BIT(5) /*!< end of operation flag bit */ + +/* FMC_CTL0 */ +#define FMC_CTL0_PG BIT(0) /*!< main flash program for bank0 command bit */ +#define FMC_CTL0_PER BIT(1) /*!< main flash page erase for bank0 command bit */ +#define FMC_CTL0_MER BIT(2) /*!< main flash mass erase for bank0 command bit */ +#define FMC_CTL0_OBPG BIT(4) /*!< option bytes program command bit */ +#define FMC_CTL0_OBER BIT(5) /*!< option bytes erase command bit */ +#define FMC_CTL0_START BIT(6) /*!< send erase command to FMC bit */ +#define FMC_CTL0_LK BIT(7) /*!< FMC_CTL0 lock bit */ +#define FMC_CTL0_OBWEN BIT(9) /*!< option bytes erase/program enable bit */ +#define FMC_CTL0_ERRIE BIT(10) /*!< error interrupt enable bit */ +#define FMC_CTL0_ENDIE BIT(12) /*!< end of operation interrupt enable bit */ + +/* FMC_ADDR0 */ +#define FMC_ADDR0_ADDR BITS(0,31) /*!< Flash erase/program command address bits */ + +/* FMC_OBSTAT */ +#define FMC_OBSTAT_OBERR BIT(0) /*!< option bytes read error bit. */ +#define FMC_OBSTAT_SPC BIT(1) /*!< option bytes security protection code */ +#define FMC_OBSTAT_USER BITS(2,9) /*!< store USER of option bytes block after system reset */ +#define FMC_OBSTAT_DATA BITS(10,25) /*!< store DATA of option bytes block after system reset. */ + +/* FMC_WP */ +#define FMC_WP_WP BITS(0,31) /*!< store WP of option bytes block after system reset */ + +/* FMC_KEY1 */ +#define FMC_KEY1_KEY BITS(0,31) /*!< FMC_CTL1 unlock key bits */ + +/* FMC_STAT1 */ +#define FMC_STAT1_BUSY BIT(0) /*!< flash busy flag bit */ +#define FMC_STAT1_PGERR BIT(2) /*!< flash program error flag bit */ +#define FMC_STAT1_WPERR BIT(4) /*!< erase/program protection error flag bit */ +#define FMC_STAT1_ENDF BIT(5) /*!< end of operation flag bit */ + +/* FMC_CTL1 */ +#define FMC_CTL1_PG BIT(0) /*!< main flash program for bank1 command bit */ +#define FMC_CTL1_PER BIT(1) /*!< main flash page erase for bank1 command bit */ +#define FMC_CTL1_MER BIT(2) /*!< main flash mass erase for bank1 command bit */ +#define FMC_CTL1_START BIT(6) /*!< send erase command to FMC bit */ +#define FMC_CTL1_LK BIT(7) /*!< FMC_CTL1 lock bit */ +#define FMC_CTL1_ERRIE BIT(10) /*!< error interrupt enable bit */ +#define FMC_CTL1_ENDIE BIT(12) /*!< end of operation interrupt enable bit */ + +/* FMC_ADDR1 */ +#define FMC_ADDR1_ADDR BITS(0,31) /*!< Flash erase/program command address bits */ + +/* FMC_WSEN */ +#define FMC_WSEN_WSEN BIT(0) /*!< FMC wait state enable bit */ + +/* FMC_PID */ +#define FMC_PID_PID BITS(0,31) /*!< product ID bits */ + +/* constants definitions */ +/* define the FMC bit position and its register index offset */ +#define FMC_REGIDX_BIT(regidx, bitpos) (((uint32_t)(regidx) << 6) | (uint32_t)(bitpos)) +#define FMC_REG_VAL(offset) (REG32(FMC + ((uint32_t)(offset) >> 6))) +#define FMC_BIT_POS(val) ((uint32_t)(val) & 0x1FU) +#define FMC_REGIDX_BITS(regidx, bitpos0, bitpos1) (((uint32_t)(regidx) << 12) | ((uint32_t)(bitpos0) << 6) | (uint32_t)(bitpos1)) +#define FMC_REG_VALS(offset) (REG32(FMC + ((uint32_t)(offset) >> 12))) +#define FMC_BIT_POS0(val) (((uint32_t)(val) >> 6) & 0x1FU) +#define FMC_BIT_POS1(val) ((uint32_t)(val) & 0x1FU) +#define FMC_REG_OFFSET_GET(flag) ((uint32_t)(flag) >> 12) + +/* configuration register */ +#define FMC_STAT0_REG_OFFSET 0x0CU /*!< status register 0 offset */ +#define FMC_CTL0_REG_OFFSET 0x10U /*!< control register 0 offset */ +#define FMC_STAT1_REG_OFFSET 0x4CU /*!< status register 1 offset */ +#define FMC_CTL1_REG_OFFSET 0x50U /*!< control register 1 offset */ +#define FMC_OBSTAT_REG_OFFSET 0x1CU /*!< option byte status register offset */ + +/* fmc state */ +typedef enum +{ + FMC_READY, /*!< the operation has been completed */ + FMC_BUSY, /*!< the operation is in progress */ + FMC_PGERR, /*!< program error */ + FMC_WPERR, /*!< erase/program protection error */ + FMC_TOERR, /*!< timeout error */ +}fmc_state_enum; + +/* FMC interrupt enable */ +typedef enum +{ + FMC_INT_BANK0_END = FMC_REGIDX_BIT(FMC_CTL0_REG_OFFSET, 12U), /*!< enable FMC end of program interrupt */ + FMC_INT_BANK0_ERR = FMC_REGIDX_BIT(FMC_CTL0_REG_OFFSET, 10U), /*!< enable FMC error interrupt */ + FMC_INT_BANK1_END = FMC_REGIDX_BIT(FMC_CTL1_REG_OFFSET, 12U), /*!< enable FMC bank1 end of program interrupt */ + FMC_INT_BANK1_ERR = FMC_REGIDX_BIT(FMC_CTL1_REG_OFFSET, 10U), /*!< enable FMC bank1 error interrupt */ +}fmc_int_enum; + +/* FMC flags */ +typedef enum +{ + FMC_FLAG_BANK0_BUSY = FMC_REGIDX_BIT(FMC_STAT0_REG_OFFSET, 0U), /*!< FMC bank0 busy flag */ + FMC_FLAG_BANK0_PGERR = FMC_REGIDX_BIT(FMC_STAT0_REG_OFFSET, 2U), /*!< FMC bank0 operation error flag bit */ + FMC_FLAG_BANK0_WPERR = FMC_REGIDX_BIT(FMC_STAT0_REG_OFFSET, 4U), /*!< FMC bank0 erase/program protection error flag bit */ + FMC_FLAG_BANK0_END = FMC_REGIDX_BIT(FMC_STAT0_REG_OFFSET, 5U), /*!< FMC bank0 end of operation flag bit */ + FMC_FLAG_OBERR = FMC_REGIDX_BIT(FMC_OBSTAT_REG_OFFSET, 0U), /*!< FMC option bytes read error flag */ + FMC_FLAG_BANK1_BUSY = FMC_REGIDX_BIT(FMC_STAT1_REG_OFFSET, 0U), /*!< FMC bank1 busy flag */ + FMC_FLAG_BANK1_PGERR = FMC_REGIDX_BIT(FMC_STAT1_REG_OFFSET, 2U), /*!< FMC bank1 operation error flag bit */ + FMC_FLAG_BANK1_WPERR = FMC_REGIDX_BIT(FMC_STAT1_REG_OFFSET, 4U), /*!< FMC bank1 erase/program protection error flag bit */ + FMC_FLAG_BANK1_END = FMC_REGIDX_BIT(FMC_STAT1_REG_OFFSET, 5U), /*!< FMC bank1 end of operation flag bit */ +}fmc_flag_enum; + +/* FMC interrupt flags */ +typedef enum +{ + FMC_INT_FLAG_BANK0_PGERR = FMC_REGIDX_BITS(FMC_STAT0_REG_OFFSET, 2U, 10U), /*!< FMC bank0 operation error interrupt flag bit */ + FMC_INT_FLAG_BANK0_WPERR = FMC_REGIDX_BITS(FMC_STAT0_REG_OFFSET, 4U, 10U), /*!< FMC bank0 erase/program protection error interrupt flag bit */ + FMC_INT_FLAG_BANK0_END = FMC_REGIDX_BITS(FMC_STAT0_REG_OFFSET, 5U, 12U), /*!< FMC bank0 end of operation interrupt flag bit */ + FMC_INT_FLAG_BANK1_PGERR = FMC_REGIDX_BITS(FMC_STAT1_REG_OFFSET, 2U, 10U), /*!< FMC bank1 operation error interrupt flag bit */ + FMC_INT_FLAG_BANK1_WPERR = FMC_REGIDX_BITS(FMC_STAT1_REG_OFFSET, 4U, 10U), /*!< FMC bank1 erase/program protection error interrupt flag bit */ + FMC_INT_FLAG_BANK1_END = FMC_REGIDX_BITS(FMC_STAT1_REG_OFFSET, 5U, 12U), /*!< FMC bank1 end of operation interrupt flag bit */ +}fmc_interrupt_flag_enum; + +/* unlock key */ +#define UNLOCK_KEY0 ((uint32_t)0x45670123U) /*!< unlock key 0 */ +#define UNLOCK_KEY1 ((uint32_t)0xCDEF89ABU) /*!< unlock key 1 */ + +/* FMC wait state counter */ +#define WS_WSCNT(regval) (BITS(0,2) & ((uint32_t)(regval))) +#define WS_WSCNT_0 WS_WSCNT(0) /*!< FMC 0 wait */ +#define WS_WSCNT_1 WS_WSCNT(1) /*!< FMC 1 wait */ +#define WS_WSCNT_2 WS_WSCNT(2) /*!< FMC 2 wait */ + +/* option bytes software/hardware free watch dog timer */ +#define OB_FWDGT_SW ((uint8_t)0x01U) /*!< software free watchdog */ +#define OB_FWDGT_HW ((uint8_t)0x00U) /*!< hardware free watchdog */ + +/* option bytes reset or not entering deep sleep mode */ +#define OB_DEEPSLEEP_NRST ((uint8_t)0x02U) /*!< no reset when entering deepsleep mode */ +#define OB_DEEPSLEEP_RST ((uint8_t)0x00U) /*!< generate a reset instead of entering deepsleep mode */ + +/* option bytes reset or not entering standby mode */ +#define OB_STDBY_NRST ((uint8_t)0x04U) /*!< no reset when entering deepsleep mode */ +#define OB_STDBY_RST ((uint8_t)0x00U) /*!< generate a reset instead of entering standby mode */ + +/* option bytes boot bank value */ +#define OB_BOOT_B0 ((uint8_t)0x08U) /*!< boot from bank0 */ +#define OB_BOOT_B1 ((uint8_t)0x00U) /*!< boot from bank1 */ + +#define OB_USER_MASK ((uint8_t)0xF0U) /*!< MASK value */ + +/* read protect configure */ +#define FMC_NSPC ((uint8_t)0xA5U) /*!< no security protection */ +#define FMC_USPC ((uint8_t)0xBBU) /*!< under security protection */ + +/* OB_SPC */ +#define OB_SPC_SPC ((uint32_t)0x000000FFU) /*!< option byte security protection value */ +#define OB_SPC_SPC_N ((uint32_t)0x0000FF00U) /*!< option byte security protection complement value */ + +/* OB_USER */ +#define OB_USER_USER ((uint32_t)0x00FF0000U) /*!< user option value */ +#define OB_USER_USER_N ((uint32_t)0xFF000000U) /*!< user option complement value */ + +/* OB_WP0 */ +#define OB_WP0_WP0 ((uint32_t)0x000000FFU) /*!< FMC write protection option value */ + +/* OB_WP1 */ +#define OB_WP1_WP1 ((uint32_t)0x0000FF00U) /*!< FMC write protection option complement value */ + +/* OB_WP2 */ +#define OB_WP2_WP2 ((uint32_t)0x00FF0000U) /*!< FMC write protection option value */ + +/* OB_WP3 */ +#define OB_WP3_WP3 ((uint32_t)0xFF000000U) /*!< FMC write protection option complement value */ + +/* option bytes write protection */ +#define OB_WP_0 ((uint32_t)0x00000001U) /*!< erase/program protection of sector 0 */ +#define OB_WP_1 ((uint32_t)0x00000002U) /*!< erase/program protection of sector 1 */ +#define OB_WP_2 ((uint32_t)0x00000004U) /*!< erase/program protection of sector 2 */ +#define OB_WP_3 ((uint32_t)0x00000008U) /*!< erase/program protection of sector 3 */ +#define OB_WP_4 ((uint32_t)0x00000010U) /*!< erase/program protection of sector 4 */ +#define OB_WP_5 ((uint32_t)0x00000020U) /*!< erase/program protection of sector 5 */ +#define OB_WP_6 ((uint32_t)0x00000040U) /*!< erase/program protection of sector 6 */ +#define OB_WP_7 ((uint32_t)0x00000080U) /*!< erase/program protection of sector 7 */ +#define OB_WP_8 ((uint32_t)0x00000100U) /*!< erase/program protection of sector 8 */ +#define OB_WP_9 ((uint32_t)0x00000200U) /*!< erase/program protection of sector 9 */ +#define OB_WP_10 ((uint32_t)0x00000400U) /*!< erase/program protection of sector 10 */ +#define OB_WP_11 ((uint32_t)0x00000800U) /*!< erase/program protection of sector 11 */ +#define OB_WP_12 ((uint32_t)0x00001000U) /*!< erase/program protection of sector 12 */ +#define OB_WP_13 ((uint32_t)0x00002000U) /*!< erase/program protection of sector 13 */ +#define OB_WP_14 ((uint32_t)0x00004000U) /*!< erase/program protection of sector 14 */ +#define OB_WP_15 ((uint32_t)0x00008000U) /*!< erase/program protection of sector 15 */ +#define OB_WP_16 ((uint32_t)0x00010000U) /*!< erase/program protection of sector 16 */ +#define OB_WP_17 ((uint32_t)0x00020000U) /*!< erase/program protection of sector 17 */ +#define OB_WP_18 ((uint32_t)0x00040000U) /*!< erase/program protection of sector 18 */ +#define OB_WP_19 ((uint32_t)0x00080000U) /*!< erase/program protection of sector 19 */ +#define OB_WP_20 ((uint32_t)0x00100000U) /*!< erase/program protection of sector 20 */ +#define OB_WP_21 ((uint32_t)0x00200000U) /*!< erase/program protection of sector 21 */ +#define OB_WP_22 ((uint32_t)0x00400000U) /*!< erase/program protection of sector 22 */ +#define OB_WP_23 ((uint32_t)0x00800000U) /*!< erase/program protection of sector 23 */ +#define OB_WP_24 ((uint32_t)0x01000000U) /*!< erase/program protection of sector 24 */ +#define OB_WP_25 ((uint32_t)0x02000000U) /*!< erase/program protection of sector 25 */ +#define OB_WP_26 ((uint32_t)0x04000000U) /*!< erase/program protection of sector 26 */ +#define OB_WP_27 ((uint32_t)0x08000000U) /*!< erase/program protection of sector 27 */ +#define OB_WP_28 ((uint32_t)0x10000000U) /*!< erase/program protection of sector 28 */ +#define OB_WP_29 ((uint32_t)0x20000000U) /*!< erase/program protection of sector 29 */ +#define OB_WP_30 ((uint32_t)0x40000000U) /*!< erase/program protection of sector 30 */ +#define OB_WP_31 ((uint32_t)0x80000000U) /*!< erase/program protection of sector 31 */ +#define OB_WP_ALL ((uint32_t)0xFFFFFFFFU) /*!< erase/program protection of all sectors */ + +/* FMC timeout */ +#define FMC_TIMEOUT_COUNT ((uint32_t)0x000F0000U) /*!< FMC timeout count value */ + +/* FMC BANK address */ +#define FMC_BANK0_END_ADDRESS ((uint32_t)0x0807FFFFU) /*!< FMC bank0 end address */ +#define FMC_BANK0_SIZE ((uint32_t)0x00000200U) /*!< FMC bank0 size */ +#define FMC_SIZE (*(uint16_t *)0x1FFFF7E0U) /*!< FMC size */ + +/* function declarations */ +/* FMC main memory programming functions */ +/* set the FMC wait state counter */ +void fmc_wscnt_set(uint32_t wscnt); +/* unlock the main FMC operation */ +void fmc_unlock(void); +/* unlock the FMC bank0 operation */ +void fmc_bank0_unlock(void); +/* unlock the FMC bank1 operation */ +void fmc_bank1_unlock(void); +/* lock the main FMC operation */ +void fmc_lock(void); +/* lock the bank0 FMC operation */ +void fmc_bank0_lock(void); +/* lock the bank1 FMC operation */ +void fmc_bank1_lock(void); +/* FMC erase page */ +fmc_state_enum fmc_page_erase(uint32_t page_address); +/* FMC erase whole chip */ +fmc_state_enum fmc_mass_erase(void); +/* FMC erase whole bank0 */ +fmc_state_enum fmc_bank0_erase(void); +/* FMC erase whole bank1 */ +fmc_state_enum fmc_bank1_erase(void); +/* FMC program a word at the corresponding address */ +fmc_state_enum fmc_word_program(uint32_t address, uint32_t data); +/* FMC program a half word at the corresponding address */ +fmc_state_enum fmc_halfword_program(uint32_t address, uint16_t data); + +/* FMC option bytes programming functions */ +/* unlock the option byte operation */ +void ob_unlock(void); +/* lock the option byte operation */ +void ob_lock(void); +/* erase the option byte */ +fmc_state_enum ob_erase(void); +/* enable write protect */ +fmc_state_enum ob_write_protection_enable(uint32_t ob_wp); +/* configure the option byte security protection */ +fmc_state_enum ob_security_protection_config(uint8_t ob_spc); +/* write the FMC option byte */ +fmc_state_enum ob_user_write(uint8_t ob_fwdgt, uint8_t ob_deepsleep, uint8_t ob_stdby, uint8_t ob_boot); +/* program option bytes data */ +fmc_state_enum ob_data_program(uint32_t address, uint8_t data); +/* get the FMC option byte user */ +uint8_t ob_user_get(void); +/* get OB_DATA in register FMC_OBSTAT */ +uint16_t ob_data_get(void); +/* get the FMC option byte write protection */ +uint32_t ob_write_protection_get(void); +/* get option byte security protection code value */ +FlagStatus ob_spc_get(void); + +/* FMC interrupts and flags management functions */ +/* enable FMC interrupt */ +void fmc_interrupt_enable(uint32_t interrupt); +/* disable FMC interrupt */ +void fmc_interrupt_disable(uint32_t interrupt); +/* check flag is set or not */ +FlagStatus fmc_flag_get(uint32_t flag); +/* clear the FMC flag */ +void fmc_flag_clear(uint32_t flag); +/* get FMC interrupt flag state */ +FlagStatus fmc_interrupt_flag_get(fmc_interrupt_flag_enum flag); +/* clear FMC interrupt flag state */ +void fmc_interrupt_flag_clear(fmc_interrupt_flag_enum flag); +/* return the FMC bank0 state */ +fmc_state_enum fmc_bank0_state_get(void); +/* return the FMC bank1 state */ +fmc_state_enum fmc_bank1_state_get(void); +/* check FMC bank0 ready or not */ +fmc_state_enum fmc_bank0_ready_wait(uint32_t timeout); +/* check FMC bank1 ready or not */ +fmc_state_enum fmc_bank1_ready_wait(uint32_t timeout); + +#endif /* GD32F20X_FMC_H */ diff --git a/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_standard_peripheral/Include/gd32f20x_fwdgt.h b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_standard_peripheral/Include/gd32f20x_fwdgt.h new file mode 100644 index 0000000000..a7c041137b --- /dev/null +++ b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_standard_peripheral/Include/gd32f20x_fwdgt.h @@ -0,0 +1,109 @@ +/*! + \file gd32f20x_fwdgt.h + \brief definitions for the FWDGT + + \version 2015-07-15, V1.0.0, firmware for GD32F20x + \version 2017-06-05, V2.0.0, firmware for GD32F20x + \version 2018-10-31, V2.1.0, firmware for GD32F20x + \version 2020-09-30, V2.2.0, firmware for GD32F20x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef GD32F20X_FWDGT_H +#define GD32F20X_FWDGT_H + +#include "gd32f20x.h" + +/* FWDGT definitions */ +#define FWDGT FWDGT_BASE /*!< FWDGT base address */ + +/* registers definitions */ +#define FWDGT_CTL REG32((FWDGT) + 0x00U) /*!< FWDGT control register */ +#define FWDGT_PSC REG32((FWDGT) + 0x04U) /*!< FWDGT prescaler register */ +#define FWDGT_RLD REG32((FWDGT) + 0x08U) /*!< FWDGT reload register */ +#define FWDGT_STAT REG32((FWDGT) + 0x0CU) /*!< FWDGT status register */ + +/* bits definitions */ +/* FWDGT_CTL */ +#define FWDGT_CTL_CMD BITS(0,15) /*!< FWDGT command value */ + +/* FWDGT_PSC */ +#define FWDGT_PSC_PSC BITS(0,2) /*!< FWDGT prescaler divider value */ + +/* FWDGT_RLD */ +#define FWDGT_RLD_RLD BITS(0,11) /*!< FWDGT counter reload value */ + +/* FWDGT_STAT */ +#define FWDGT_STAT_PUD BIT(0) /*!< FWDGT prescaler divider value update */ +#define FWDGT_STAT_RUD BIT(1) /*!< FWDGT counter reload value update */ + +/* constants definitions */ +/* psc register value */ +#define PSC_PSC(regval) (BITS(0,2) & ((uint32_t)(regval) << 0)) +#define FWDGT_PSC_DIV4 ((uint8_t)PSC_PSC(0)) /*!< FWDGT prescaler set to 4 */ +#define FWDGT_PSC_DIV8 ((uint8_t)PSC_PSC(1)) /*!< FWDGT prescaler set to 8 */ +#define FWDGT_PSC_DIV16 ((uint8_t)PSC_PSC(2)) /*!< FWDGT prescaler set to 16 */ +#define FWDGT_PSC_DIV32 ((uint8_t)PSC_PSC(3)) /*!< FWDGT prescaler set to 32 */ +#define FWDGT_PSC_DIV64 ((uint8_t)PSC_PSC(4)) /*!< FWDGT prescaler set to 64 */ +#define FWDGT_PSC_DIV128 ((uint8_t)PSC_PSC(5)) /*!< FWDGT prescaler set to 128 */ +#define FWDGT_PSC_DIV256 ((uint8_t)PSC_PSC(6)) /*!< FWDGT prescaler set to 256 */ + +/* control value */ +#define FWDGT_WRITEACCESS_ENABLE ((uint16_t)0x5555U) /*!< FWDGT_CTL bits write access enable value */ +#define FWDGT_WRITEACCESS_DISABLE ((uint16_t)0x0000U) /*!< FWDGT_CTL bits write access disable value */ +#define FWDGT_KEY_RELOAD ((uint16_t)0xAAAAU) /*!< FWDGT_CTL bits fwdgt counter reload value */ +#define FWDGT_KEY_ENABLE ((uint16_t)0xCCCCU) /*!< FWDGT_CTL bits fwdgt counter enable value */ + +/* FWDGT timeout value */ +#define FWDGT_PSC_TIMEOUT ((uint32_t)0x000FFFFFU) /*!< FWDGT_PSC register write operation state flag timeout */ +#define FWDGT_RLD_TIMEOUT ((uint32_t)0x000FFFFFU) /*!< FWDGT_RLD register write operation state flag timeout */ + +/* FWDGT flag definitions */ +#define FWDGT_FLAG_PUD FWDGT_STAT_PUD /*!< FWDGT prescaler divider value update flag */ +#define FWDGT_FLAG_RUD FWDGT_STAT_RUD /*!< FWDGT counter reload value update flag */ + +/* function declarations */ +/* function configuration */ +/* enable write access to FWDGT_PSC and FWDGT_RLD */ +void fwdgt_write_enable(void); +/* disable write access to FWDGT_PSC and FWDGT_RLD */ +void fwdgt_write_disable(void); +/* start the free watchdog timer counter */ +void fwdgt_enable(void); + +/* reload the counter of FWDGT */ +void fwdgt_counter_reload(void); +/* configure counter reload value, and prescaler divider value */ +ErrStatus fwdgt_config(uint16_t reload_value, uint8_t prescaler_div); + +/* interrupt & flag functions */ +/* get flag state of FWDGT */ +FlagStatus fwdgt_flag_get(uint16_t flag); + +#endif /* GD32F20X_FWDGT_H */ diff --git a/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_standard_peripheral/Include/gd32f20x_gpio.h b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_standard_peripheral/Include/gd32f20x_gpio.h new file mode 100644 index 0000000000..fe29dad0ff --- /dev/null +++ b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_standard_peripheral/Include/gd32f20x_gpio.h @@ -0,0 +1,718 @@ +/*! + \file gd32f20x_gpio.h + \brief definitions for the GPIO + + \version 2015-07-15, V1.0.0, firmware for GD32F20x + \version 2017-06-05, V2.0.0, firmware for GD32F20x + \version 2018-10-31, V2.1.0, firmware for GD32F20x + \version 2020-09-30, V2.2.0, firmware for GD32F20x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef GD32F20X_GPIO_H +#define GD32F20X_GPIO_H + +#include "gd32f20x.h" + +/* GPIOx(x=A,B,C,D,E,F,G,H,I) definitions */ +#define GPIOA (GPIO_BASE + 0x00000000U) +#define GPIOB (GPIO_BASE + 0x00000400U) +#define GPIOC (GPIO_BASE + 0x00000800U) +#define GPIOD (GPIO_BASE + 0x00000C00U) +#define GPIOE (GPIO_BASE + 0x00001000U) +#define GPIOF (GPIO_BASE + 0x00001400U) +#define GPIOG (GPIO_BASE + 0x00001800U) +#define GPIOH (GPIO_BASE + 0x00006C00U) +#define GPIOI (GPIO_BASE + 0x00007000U) + +/* AFIO definitions */ +#define AFIO AFIO_BASE + +/* registers definitions */ +/* GPIO registers definitions */ +#define GPIO_CTL0(gpiox) REG32((gpiox) + 0x00U) /*!< GPIO port control register 0 */ +#define GPIO_CTL1(gpiox) REG32((gpiox) + 0x04U) /*!< GPIO port control register 1 */ +#define GPIO_ISTAT(gpiox) REG32((gpiox) + 0x08U) /*!< GPIO port input status register */ +#define GPIO_OCTL(gpiox) REG32((gpiox) + 0x0CU) /*!< GPIO port output control register */ +#define GPIO_BOP(gpiox) REG32((gpiox) + 0x10U) /*!< GPIO port bit operation register */ +#define GPIO_BC(gpiox) REG32((gpiox) + 0x14U) /*!< GPIO bit clear register */ +#define GPIO_LOCK(gpiox) REG32((gpiox) + 0x18U) /*!< GPIO port configuration lock register */ + +/* AFIO registers definitions */ +#define AFIO_EC REG32(AFIO + 0x00U) /*!< AFIO event control register */ +#define AFIO_PCF0 REG32(AFIO + 0x04U) /*!< AFIO port configuration register 0 */ +#define AFIO_EXTISS0 REG32(AFIO + 0x08U) /*!< AFIO port EXTI sources selection register 0 */ +#define AFIO_EXTISS1 REG32(AFIO + 0x0CU) /*!< AFIO port EXTI sources selection register 1 */ +#define AFIO_EXTISS2 REG32(AFIO + 0x10U) /*!< AFIO port EXTI sources selection register 2 */ +#define AFIO_EXTISS3 REG32(AFIO + 0x14U) /*!< AFIO port EXTI sources selection register 3 */ +#define AFIO_PCF1 REG32(AFIO + 0x1CU) /*!< AFIO port configuration register 1 */ +#define AFIO_PCF2 REG32(AFIO + 0x3CU) /*!< AFIO port configuration register 2 */ +#define AFIO_PCF3 REG32(AFIO + 0x40U) /*!< AFIO port configuration register 3 */ +#define AFIO_PCF4 REG32(AFIO + 0x44U) /*!< AFIO port configuration register 4 */ +#define AFIO_PCF5 REG32(AFIO + 0x48U) /*!< AFIO port configuration register 5 */ + +/* bits definitions */ +/* GPIO_CTL0 */ +#define GPIO_CTL0_MD0 BITS(0,1) /*!< port 0 mode bits */ +#define GPIO_CTL0_CTL0 BITS(2,3) /*!< pin 0 configuration bits */ +#define GPIO_CTL0_MD1 BITS(4,5) /*!< port 1 mode bits */ +#define GPIO_CTL0_CTL1 BITS(6,7) /*!< pin 1 configuration bits */ +#define GPIO_CTL0_MD2 BITS(8,9) /*!< port 2 mode bits */ +#define GPIO_CTL0_CTL2 BITS(10,11) /*!< pin 2 configuration bits */ +#define GPIO_CTL0_MD3 BITS(12,13) /*!< port 3 mode bits */ +#define GPIO_CTL0_CTL3 BITS(14,15) /*!< pin 3 configuration bits */ +#define GPIO_CTL0_MD4 BITS(16,17) /*!< port 4 mode bits */ +#define GPIO_CTL0_CTL4 BITS(18,19) /*!< pin 4 configuration bits */ +#define GPIO_CTL0_MD5 BITS(20,21) /*!< port 5 mode bits */ +#define GPIO_CTL0_CTL5 BITS(22,23) /*!< pin 5 configuration bits */ +#define GPIO_CTL0_MD6 BITS(24,25) /*!< port 6 mode bits */ +#define GPIO_CTL0_CTL6 BITS(26,27) /*!< pin 6 configuration bits */ +#define GPIO_CTL0_MD7 BITS(28,29) /*!< port 7 mode bits */ +#define GPIO_CTL0_CTL7 BITS(30,31) /*!< pin 7 configuration bits */ + +/* GPIO_CTL1 */ +#define GPIO_CTL1_MD8 BITS(0,1) /*!< port 8 mode bits */ +#define GPIO_CTL1_CTL8 BITS(2,3) /*!< pin 8 configuration bits */ +#define GPIO_CTL1_MD9 BITS(4,5) /*!< port 9 mode bits */ +#define GPIO_CTL1_CTL9 BITS(6,7) /*!< pin 9 configuration bits */ +#define GPIO_CTL1_MD10 BITS(8,9) /*!< port 10 mode bits */ +#define GPIO_CTL1_CTL10 BITS(10,11) /*!< pin 10 configuration bits */ +#define GPIO_CTL1_MD11 BITS(12,13) /*!< port 11 mode bits */ +#define GPIO_CTL1_CTL11 BITS(14,15) /*!< pin 11 configuration bits */ +#define GPIO_CTL1_MD12 BITS(16,17) /*!< port 12 mode bits */ +#define GPIO_CTL1_CTL12 BITS(18,19) /*!< pin 12 configuration bits */ +#define GPIO_CTL1_MD13 BITS(20,21) /*!< port 13 mode bits */ +#define GPIO_CTL1_CTL13 BITS(22,23) /*!< pin 13 configuration bits */ +#define GPIO_CTL1_MD14 BITS(24,25) /*!< port 14 mode bits */ +#define GPIO_CTL1_CTL14 BITS(26,27) /*!< pin 14 configuration bits */ +#define GPIO_CTL1_MD15 BITS(28,29) /*!< port 15 mode bits */ +#define GPIO_CTL1_CTL15 BITS(30,31) /*!< pin 15 configuration bits */ + +/* GPIO_ISTAT */ +#define GPIO_ISTAT_ISTAT0 BIT(0) /*!< pin 0 input status */ +#define GPIO_ISTAT_ISTAT1 BIT(1) /*!< pin 1 input status */ +#define GPIO_ISTAT_ISTAT2 BIT(2) /*!< pin 2 input status */ +#define GPIO_ISTAT_ISTAT3 BIT(3) /*!< pin 3 input status */ +#define GPIO_ISTAT_ISTAT4 BIT(4) /*!< pin 4 input status */ +#define GPIO_ISTAT_ISTAT5 BIT(5) /*!< pin 5 input status */ +#define GPIO_ISTAT_ISTAT6 BIT(6) /*!< pin 6 input status */ +#define GPIO_ISTAT_ISTAT7 BIT(7) /*!< pin 7 input status */ +#define GPIO_ISTAT_ISTAT8 BIT(8) /*!< pin 8 input status */ +#define GPIO_ISTAT_ISTAT9 BIT(9) /*!< pin 9 input status */ +#define GPIO_ISTAT_ISTAT10 BIT(10) /*!< pin 10 input status */ +#define GPIO_ISTAT_ISTAT11 BIT(11) /*!< pin 11 input status */ +#define GPIO_ISTAT_ISTAT12 BIT(12) /*!< pin 12 input status */ +#define GPIO_ISTAT_ISTAT13 BIT(13) /*!< pin 13 input status */ +#define GPIO_ISTAT_ISTAT14 BIT(14) /*!< pin 14 input status */ +#define GPIO_ISTAT_ISTAT15 BIT(15) /*!< pin 15 input status */ + +/* GPIO_OCTL */ +#define GPIO_OCTL_OCTL0 BIT(0) /*!< pin 0 output bit */ +#define GPIO_OCTL_OCTL1 BIT(1) /*!< pin 1 output bit */ +#define GPIO_OCTL_OCTL2 BIT(2) /*!< pin 2 output bit */ +#define GPIO_OCTL_OCTL3 BIT(3) /*!< pin 3 output bit */ +#define GPIO_OCTL_OCTL4 BIT(4) /*!< pin 4 output bit */ +#define GPIO_OCTL_OCTL5 BIT(5) /*!< pin 5 output bit */ +#define GPIO_OCTL_OCTL6 BIT(6) /*!< pin 6 output bit */ +#define GPIO_OCTL_OCTL7 BIT(7) /*!< pin 7 output bit */ +#define GPIO_OCTL_OCTL8 BIT(8) /*!< pin 8 output bit */ +#define GPIO_OCTL_OCTL9 BIT(9) /*!< pin 9 output bit */ +#define GPIO_OCTL_OCTL10 BIT(10) /*!< pin 10 output bit */ +#define GPIO_OCTL_OCTL11 BIT(11) /*!< pin 11 output bit */ +#define GPIO_OCTL_OCTL12 BIT(12) /*!< pin 12 output bit */ +#define GPIO_OCTL_OCTL13 BIT(13) /*!< pin 13 output bit */ +#define GPIO_OCTL_OCTL14 BIT(14) /*!< pin 14 output bit */ +#define GPIO_OCTL_OCTL15 BIT(15) /*!< pin 15 output bit */ + +/* GPIO_BOP */ +#define GPIO_BOP_BOP0 BIT(0) /*!< pin 0 set bit */ +#define GPIO_BOP_BOP1 BIT(1) /*!< pin 1 set bit */ +#define GPIO_BOP_BOP2 BIT(2) /*!< pin 2 set bit */ +#define GPIO_BOP_BOP3 BIT(3) /*!< pin 3 set bit */ +#define GPIO_BOP_BOP4 BIT(4) /*!< pin 4 set bit */ +#define GPIO_BOP_BOP5 BIT(5) /*!< pin 5 set bit */ +#define GPIO_BOP_BOP6 BIT(6) /*!< pin 6 set bit */ +#define GPIO_BOP_BOP7 BIT(7) /*!< pin 7 set bit */ +#define GPIO_BOP_BOP8 BIT(8) /*!< pin 8 set bit */ +#define GPIO_BOP_BOP9 BIT(9) /*!< pin 9 set bit */ +#define GPIO_BOP_BOP10 BIT(10) /*!< pin 10 set bit */ +#define GPIO_BOP_BOP11 BIT(11) /*!< pin 11 set bit */ +#define GPIO_BOP_BOP12 BIT(12) /*!< pin 12 set bit */ +#define GPIO_BOP_BOP13 BIT(13) /*!< pin 13 set bit */ +#define GPIO_BOP_BOP14 BIT(14) /*!< pin 14 set bit */ +#define GPIO_BOP_BOP15 BIT(15) /*!< pin 15 set bit */ +#define GPIO_BOP_CR0 BIT(16) /*!< pin 0 clear bit */ +#define GPIO_BOP_CR1 BIT(17) /*!< pin 1 clear bit */ +#define GPIO_BOP_CR2 BIT(18) /*!< pin 2 clear bit */ +#define GPIO_BOP_CR3 BIT(19) /*!< pin 3 clear bit */ +#define GPIO_BOP_CR4 BIT(20) /*!< pin 4 clear bit */ +#define GPIO_BOP_CR5 BIT(21) /*!< pin 5 clear bit */ +#define GPIO_BOP_CR6 BIT(22) /*!< pin 6 clear bit */ +#define GPIO_BOP_CR7 BIT(23) /*!< pin 7 clear bit */ +#define GPIO_BOP_CR8 BIT(24) /*!< pin 8 clear bit */ +#define GPIO_BOP_CR9 BIT(25) /*!< pin 9 clear bit */ +#define GPIO_BOP_CR10 BIT(26) /*!< pin 10 clear bit */ +#define GPIO_BOP_CR11 BIT(27) /*!< pin 11 clear bit */ +#define GPIO_BOP_CR12 BIT(28) /*!< pin 12 clear bit */ +#define GPIO_BOP_CR13 BIT(29) /*!< pin 13 clear bit */ +#define GPIO_BOP_CR14 BIT(30) /*!< pin 14 clear bit */ +#define GPIO_BOP_CR15 BIT(31) /*!< pin 15 clear bit */ + +/* GPIO_BC */ +#define GPIO_BC_CR0 BIT(0) /*!< pin 0 clear bit */ +#define GPIO_BC_CR1 BIT(1) /*!< pin 1 clear bit */ +#define GPIO_BC_CR2 BIT(2) /*!< pin 2 clear bit */ +#define GPIO_BC_CR3 BIT(3) /*!< pin 3 clear bit */ +#define GPIO_BC_CR4 BIT(4) /*!< pin 4 clear bit */ +#define GPIO_BC_CR5 BIT(5) /*!< pin 5 clear bit */ +#define GPIO_BC_CR6 BIT(6) /*!< pin 6 clear bit */ +#define GPIO_BC_CR7 BIT(7) /*!< pin 7 clear bit */ +#define GPIO_BC_CR8 BIT(8) /*!< pin 8 clear bit */ +#define GPIO_BC_CR9 BIT(9) /*!< pin 9 clear bit */ +#define GPIO_BC_CR10 BIT(10) /*!< pin 10 clear bit */ +#define GPIO_BC_CR11 BIT(11) /*!< pin 11 clear bit */ +#define GPIO_BC_CR12 BIT(12) /*!< pin 12 clear bit */ +#define GPIO_BC_CR13 BIT(13) /*!< pin 13 clear bit */ +#define GPIO_BC_CR14 BIT(14) /*!< pin 14 clear bit */ +#define GPIO_BC_CR15 BIT(15) /*!< pin 15 clear bit */ + +/* GPIO_LOCK */ +#define GPIO_LOCK_LK0 BIT(0) /*!< pin 0 lock bit */ +#define GPIO_LOCK_LK1 BIT(1) /*!< pin 1 lock bit */ +#define GPIO_LOCK_LK2 BIT(2) /*!< pin 2 lock bit */ +#define GPIO_LOCK_LK3 BIT(3) /*!< pin 3 lock bit */ +#define GPIO_LOCK_LK4 BIT(4) /*!< pin 4 lock bit */ +#define GPIO_LOCK_LK5 BIT(5) /*!< pin 5 lock bit */ +#define GPIO_LOCK_LK6 BIT(6) /*!< pin 6 lock bit */ +#define GPIO_LOCK_LK7 BIT(7) /*!< pin 7 lock bit */ +#define GPIO_LOCK_LK8 BIT(8) /*!< pin 8 lock bit */ +#define GPIO_LOCK_LK9 BIT(9) /*!< pin 9 lock bit */ +#define GPIO_LOCK_LK10 BIT(10) /*!< pin 10 lock bit */ +#define GPIO_LOCK_LK11 BIT(11) /*!< pin 11 lock bit */ +#define GPIO_LOCK_LK12 BIT(12) /*!< pin 12 lock bit */ +#define GPIO_LOCK_LK13 BIT(13) /*!< pin 13 lock bit */ +#define GPIO_LOCK_LK14 BIT(14) /*!< pin 14 lock bit */ +#define GPIO_LOCK_LK15 BIT(15) /*!< pin 15 lock bit */ +#define GPIO_LOCK_LKK BIT(16) /*!< pin sequence lock key */ + +/* AFIO_EC */ +#define AFIO_EC_PIN BITS(0,3) /*!< event output pin selection */ +#define AFIO_EC_PORT BITS(4,6) /*!< event output port selection */ +#define AFIO_EC_EOE BIT(7) /*!< event output enable */ + +/* AFIO_PCF0 */ +#define AFIO_PCF0_SPI0_REMAP BIT(0) /*!< SPI0 remapping */ +#define AFIO_PCF0_I2C0_REMAP BIT(1) /*!< I2C0 remapping */ +#define AFIO_PCF0_USART0_REMAP BIT(2) /*!< USART0 remapping */ +#define AFIO_PCF0_USART1_REMAP BIT(3) /*!< USART1 remapping */ +#define AFIO_PCF0_USART2_REMAP BITS(4,5) /*!< USART2 remapping */ +#define AFIO_PCF0_TIMER0_REMAP BITS(6,7) /*!< TIMER0 remapping */ +#define AFIO_PCF0_TIMER1_REMAP BITS(8,9) /*!< TIMER1 remapping */ +#define AFIO_PCF0_TIMER2_REMAP BITS(10,11) /*!< TIMER2 remapping */ +#define AFIO_PCF0_TIMER3_REMAP BIT(12) /*!< TIMER3 remapping */ +#define AFIO_PCF0_CAN0_REMAP BITS(13,14) /*!< CAN0 remapping */ +#define AFIO_PCF0_PD01_REMAP BIT(15) /*!< port D0/port D1 mapping on OSC_IN/OSC_OUT */ +#define AFIO_PCF0_TIMER4CH3_IREMAP BIT(16) /*!< TIMER4 channel3 internal remapping */ +#define AFIO_PCF0_ADC0_ETRGINS_REMAP BIT(17) /*!< ADC 0 external trigger inserted conversion remapping */ +#define AFIO_PCF0_ADC0_ETRGREG_REMAP BIT(18) /*!< ADC 0 external trigger regular conversion remapping */ +#define AFIO_PCF0_ADC1_ETRGINS_REMAP BIT(19) /*!< ADC 1 external trigger inserted conversion remapping */ +#define AFIO_PCF0_ADC1_ETRGREG_REMAP BIT(20) /*!< ADC 1 external trigger regular conversion remapping */ +#define AFIO_PCF0_ENET_REMAP BIT(21) /*!< ethernet MAC I/O remapping */ +#define AFIO_PCF0_CAN1_REMAP BIT(22) /*!< CAN1 remapping */ +#define AFIO_PCF0_ENET_PHY_SEL BIT(23) /*!< ethernet MII or RMII PHY selection */ +#define AFIO_PCF0_SWJ_CFG BITS(24,26) /*!< serial wire JTAG configuration */ +#define AFIO_PCF0_SPI2_REMAP BIT(28) /*!< SPI2/I2S2 remapping */ +#define AFIO_PCF0_TIMER1ITI1_REMAP BIT(29) /*!< TIMER1 internal trigger 1 remapping */ +#define AFIO_PCF0_PTP_PPS_REMAP BIT(30) /*!< ethernet PTP PPS remapping */ + +/* AFIO_EXTISS0 */ +#define AFIO_EXTI0_SS BITS(0,3) /*!< EXTI 0 sources selection */ +#define AFIO_EXTI1_SS BITS(4,7) /*!< EXTI 1 sources selection */ +#define AFIO_EXTI2_SS BITS(8,11) /*!< EXTI 2 sources selection */ +#define AFIO_EXTI3_SS BITS(12,15) /*!< EXTI 3 sources selection */ + +/* AFIO_EXTISS1 */ +#define AFIO_EXTI4_SS BITS(0,3) /*!< EXTI 4 sources selection */ +#define AFIO_EXTI5_SS BITS(4,7) /*!< EXTI 5 sources selection */ +#define AFIO_EXTI6_SS BITS(8,11) /*!< EXTI 6 sources selection */ +#define AFIO_EXTI7_SS BITS(12,15) /*!< EXTI 7 sources selection */ + +/* AFIO_EXTISS2 */ +#define AFIO_EXTI8_SS BITS(0,3) /*!< EXTI 8 sources selection */ +#define AFIO_EXTI9_SS BITS(4,7) /*!< EXTI 9 sources selection */ +#define AFIO_EXTI10_SS BITS(8,11) /*!< EXTI 10 sources selection */ +#define AFIO_EXTI11_SS BITS(12,15) /*!< EXTI 11 sources selection */ + +/* AFIO_EXTISS3 */ +#define AFIO_EXTI12_SS BITS(0,3) /*!< EXTI 12 sources selection */ +#define AFIO_EXTI13_SS BITS(4,7) /*!< EXTI 13 sources selection */ +#define AFIO_EXTI14_SS BITS(8,11) /*!< EXTI 14 sources selection */ +#define AFIO_EXTI15_SS BITS(12,15) /*!< EXTI 15 sources selection */ + +/* AFIO_PCF1 */ +#define AFIO_PCF1_TIMER8_REMAP BIT(5) /*!< TIMER8 remapping */ +#define AFIO_PCF1_TIMER9_REMAP BIT(6) /*!< TIMER9 remapping */ +#define AFIO_PCF1_TIMER10_REMAP BIT(7) /*!< TIMER10 remapping */ +#define AFIO_PCF1_TIMER12_REMAP BIT(8) /*!< TIMER12 remapping */ +#define AFIO_PCF1_TIMER13_REMAP BIT(9) /*!< TIMER13 remapping */ +#define AFIO_PCF1_EXMC_NADV BIT(10) /*!< EXMC_NADV connect/disconnect */ + +/* AFIO_PCF2 */ +#define AFIO_PCF2_DCI_VSYNC_REMAP BITS(0,1) /*!< DCI VSYNC remapping */ +#define AFIO_PCF2_DCI_D0_REMAP BITS(2,3) /*!< DCI D0 remapping */ +#define AFIO_PCF2_DCI_D1_REMAP BITS(4,5) /*!< DCI D1 remapping */ +#define AFIO_PCF2_DCI_D2_REMAP BITS(6,7) /*!< DCI D2 remapping */ +#define AFIO_PCF2_DCI_D3_REMAP BITS(8,9) /*!< DCI D3 remapping */ +#define AFIO_PCF2_DCI_D4_REMAP BITS(10,11) /*!< DCI D4 remapping */ +#define AFIO_PCF2_DCI_D5_REMAP BITS(12,13) /*!< DCI D5 remapping */ +#define AFIO_PCF2_DCI_D6_REMAP BITS(14,15) /*!< DCI D6 remapping */ +#define AFIO_PCF2_DCI_D7_REMAP BITS(16,17) /*!< DCI D7 remapping */ +#define AFIO_PCF2_DCI_D8_REMAP BITS(18,19) /*!< DCI D8 remapping */ +#define AFIO_PCF2_DCI_D9_REMAP BITS(20,21) /*!< DCI D9 remapping */ +#define AFIO_PCF2_DCI_D10_REMAP BITS(22,23) /*!< DCI D10 remapping */ +#define AFIO_PCF2_DCI_D11_REMAP BITS(24,25) /*!< DCI D11 remapping */ +#define AFIO_PCF2_DCI_D12_REMAP BIT(26) /*!< DCI D12 remapping */ +#define AFIO_PCF2_DCI_D13_REMAP BITS(27,28) /*!< DCI D13 remapping */ +#define AFIO_PCF2_DCI_HSYNC_REMAP BIT(29) /*!< DCI HSYNC remapping */ +#define AFIO_PCF2_PH01_REMAP BIT(31) /*!< PH0/PH1 remapping */ + +/* AFIO_PCF3 */ +#define AFIO_PCF3_TLI_B5_PA3_REMAP BIT(0) /*!< TLI B5 PA3 remapping */ +#define AFIO_PCF3_TLI_VSYNC_PA4_REMAP BIT(1) /*!< TLI VSYNC PA4 remapping */ +#define AFIO_PCF3_TLI_G2_PA6_REMAP BIT(2) /*!< TLI G2 PA6 remapping */ +#define AFIO_PCF3_TLI_R6_PA8_REMAP BIT(3) /*!< TLI R6 PA8 remapping */ +#define AFIO_PCF3_TLI_R4_PA11_REMAP BIT(4) /*!< TLI R4 PA11 remapping */ +#define AFIO_PCF3_TLI_R5_PA12_REMAP BIT(5) /*!< TLI R5 PA12 remapping */ +#define AFIO_PCF3_TLI_R3_PB0_REMAP BIT(6) /*!< TLI R3 PB0 remapping */ +#define AFIO_PCF3_TLI_R6_PB1_REMAP BIT(7) /*!< TLI R6 PB1 remapping */ +#define AFIO_PCF3_TLI_B6_PB8_REMAP BIT(8) /*!< TLI B6 PB8 remapping */ +#define AFIO_PCF3_TLI_B7_PB9_REMAP BIT(9) /*!< TLI B7 PB9 remapping */ +#define AFIO_PCF3_TLI_G4_PB10_REMAP BIT(10) /*!< TLI G4 PB10 remapping */ +#define AFIO_PCF3_TLI_G5_PB11_REMAP BIT(11) /*!< TLI G5 PB11 remapping */ +#define AFIO_PCF3_TLI_HSYNC_PC6_REMAP BIT(12) /*!< TLI HSYNC PC6 remapping */ +#define AFIO_PCF3_TLI_G6_PC7_REMAP BIT(13) /*!< TLI G6 PC7 remapping */ +#define AFIO_PCF3_TLI_R2_PC10_REMAP BIT(14) /*!< TLI R2 PC10 remapping */ +#define AFIO_PCF3_TLI_G7_PD3_REMAP BIT(15) /*!< TLI G7 PD3 remapping */ +#define AFIO_PCF3_TLI_B2_PD6_REMAP BIT(16) /*!< TLI B2 PD6 remapping */ +#define AFIO_PCF3_TLI_B3_PD10_REMAP BIT(17) /*!< TLI B3 PD10 remapping */ +#define AFIO_PCF3_TLI_B0_PE4_REMAP BIT(18) /*!< TLI B0 PE4 remapping */ +#define AFIO_PCF3_TLI_G0_PE5_REMAP BIT(19) /*!< TLI G0 PE5 remapping */ +#define AFIO_PCF3_TLI_G1_PE6_REMAP BIT(20) /*!< TLI G1 PE6 remapping */ +#define AFIO_PCF3_TLI_G3_PE11_REMAP BIT(21) /*!< TLI G3 PE11 remapping */ +#define AFIO_PCF3_TLI_B4_PE12_REMAP BIT(22) /*!< TLI B4 PE12 remapping */ +#define AFIO_PCF3_TLI_DE_PE13_REMAP BIT(23) /*!< TLI DE PE13 remapping */ +#define AFIO_PCF3_TLI_CLK_PE14_REMAP BIT(24) /*!< TLI CLK PE14 remapping */ +#define AFIO_PCF3_TLI_R7_PE15_REMAP BIT(25) /*!< TLI R7 PE15 remapping */ +#define AFIO_PCF3_TLI_DE_PF10_REMAP BIT(26) /*!< TLI DE PF10 remapping */ +#define AFIO_PCF3_TLI_R7_PG6_REMAP BIT(27) /*!< TLI R7 PG6 remapping */ +#define AFIO_PCF3_TLI_CLK_PG7_REMAP BIT(28) /*!< TLI CLK PG7 remapping */ +#define AFIO_PCF3_TLI_G3_PG10_REMAP BIT(29) /*!< TLI G3 PG10 remapping */ +#define AFIO_PCF3_TLI_B2_PG10_REMAP BIT(30) /*!< TLI B2 PG10 remapping */ +#define AFIO_PCF3_TLI_B3_PG11_REMAP BIT(31) /*!< TLI B3 PG11 remapping */ + +/* AFIO_PCF4 */ +#define AFIO_PCF4_TLI_B4_PG12_REMAP BIT(0) /*!< TLI B4 PG12 remapping */ +#define AFIO_PCF4_TLI_B1_PG12_REMAP BIT(1) /*!< TLI B1 PG12 remapping */ +#define AFIO_PCF4_TLI_R0_PH2_REMAP BIT(2) /*!< TLI R0 PH2 remapping */ +#define AFIO_PCF4_TLI_R1_PH3_REMAP BIT(3) /*!< TLI R1 PH3 remapping */ +#define AFIO_PCF4_TLI_R2_PH8_REMAP BIT(4) /*!< TLI R2 PH8 remapping */ +#define AFIO_PCF4_TLI_R3_PH9_REMAP BIT(5) /*!< TLI R3 PH9 remapping */ +#define AFIO_PCF4_TLI_R4_PH10_REMAP BIT(6) /*!< TLI R4 PH10 remapping */ +#define AFIO_PCF4_TLI_R5_PH11_REMAP BIT(7) /*!< TLI R5 PH11 remapping */ +#define AFIO_PCF4_TLI_R6_PH12_REMAP BIT(8) /*!< TLI R6 PH12 remapping */ +#define AFIO_PCF4_TLI_G2_PH13_REMAP BIT(9) /*!< TLI G2 PH13 remapping */ +#define AFIO_PCF4_TLI_G3_PH14_REMAP BIT(10) /*!< TLI G3 PH14 remapping */ +#define AFIO_PCF4_TLI_G4_PH15_REMAP BIT(11) /*!< TLI G4 PH15 remapping */ +#define AFIO_PCF4_TLI_G5_PI0_REMAP BIT(12) /*!< TLI G5 PI0 remapping */ +#define AFIO_PCF4_TLI_G6_PI1_REMAP BIT(13) /*!< TLI G6 PI1 remapping */ +#define AFIO_PCF4_TLI_G7_PI2_REMAP BIT(14) /*!< TLI G7 PI2 remapping */ +#define AFIO_PCF4_TLI_B4_PI4_REMAP BIT(15) /*!< TLI B4 PI4 remapping */ +#define AFIO_PCF4_TLI_B5_PI5_REMAP BIT(16) /*!< TLI B5 PI5 remapping */ +#define AFIO_PCF4_TLI_B6_PI6_REMAP BIT(17) /*!< TLI B6 PI6 remapping */ +#define AFIO_PCF4_TLI_B7_PI7_REMAP BIT(18) /*!< TLI B7 PI7 remapping */ +#define AFIO_PCF4_TLI_VSYNC_PI9_REMAP BIT(19) /*!< TLI VSYNC PI9 remapping */ +#define AFIO_PCF4_TLI_HSYNC_PI10_REMAP BIT(20) /*!< TLI HSYNC PI10 remapping */ +#define AFIO_PCF4_TLI_R0_PH4_REMAP BIT(21) /*!< TLI R0 PH4 remapping */ +#define AFIO_PCF4_TLI_R1_PI3_REMAP BIT(22) /*!< TLI R1 PI3 remapping */ +#define AFIO_PCF4_SPI1_SCK_REMAP BIT(23) /*!< SPI1 SCK remapping */ +#define AFIO_PCF4_SPI2_MOSI_REMAP BIT(24) /*!< SPI2 MOSI remapping */ + +/* AFIO_PCF5 */ +#define AFIO_PCF5_I2C2_REMAP0 BIT(0) /*!< I2C2 remapping 0 */ +#define AFIO_PCF5_I2C2_REMAP1 BIT(1) /*!< I2C2 remapping 1 */ +#define AFIO_PCF5_TIMER1_CH0_REMAP BIT(2) /*!< TIMER1 CH0 remapping */ +#define AFIO_PCF5_TIMER4_REMAP BIT(3) /*!< TIMER4 remapping */ +#define AFIO_PCF5_TIMER7_CHON_REMAP BITS(4,5) /*!< TIMER7 CHON remapping */ +#define AFIO_PCF5_TIMER7_CH_REMAP BIT(6) /*!< TIMER7 CH remapping */ +#define AFIO_PCF5_I2C1_REMAP BITS(7,8) /*!< I2C1 remapping */ +#define AFIO_PCF5_SPI1_NSCK_REMAP BITS(9,10) /*!< SPI1 NSCK remapping */ +#define AFIO_PCF5_SPI1_IO_REMAP BITS(11,12) /*!< SPI1 IO remapping */ +#define AFIO_PCF5_UART3_REMAP BIT(13) /*!< UART3 remapping */ +#define AFIO_PCF5_TIMER11_REMAP BIT(14) /*!< TIMER11 remapping */ +#define AFIO_PCF5_CAN0_ADD_REMAP BIT(15) /*!< CAN0 ADD remapping */ +#define AFIO_PCF5_ENET_TXD3_REMAP BIT(16) /*!< ENET TXD3 remapping */ +#define AFIO_PCF5_PPS_HI_REMAP BIT(17) /*!< ETH_PPS_OUT remapping */ +#define AFIO_PCF5_ENET_TXD01_REMAP BIT(18) /*!< ETH_TX_EN/ETH_TXD0/ETH_TXD1 remapping */ +#define AFIO_PCF5_ENET_CRSCOL_REMAP BIT(19) /*!< ETH_MII_CRS/ETH_MII_COL remapping */ +#define AFIO_PCF5_ENET_RX_HI_REMAP BIT(20) /*!< ETH_RXD2/ETH_RXD3/ETH_RX_ER remapping */ +#define AFIO_PCF5_UART6_REMAP BIT(21) /*!< UART6 remapping */ +#define AFIO_PCF5_USART5_CK_REMAP BIT(22) /*!< USART5 CK remapping */ +#define AFIO_PCF5_USART5_RTS_REMAP BIT(23) /*!< USART5 RTS remapping */ +#define AFIO_PCF5_USART5_CTS_REMAP BIT(24) /*!< USART5 CTS remapping */ +#define AFIO_PCF5_USART5_TX_REMAP BIT(25) /*!< USART5 TX remapping */ +#define AFIO_PCF5_USART5_RX_REMAP BIT(26) /*!< USART5 RX remapping */ +#define AFIO_PCF5_EXMC_SDNWE_REMAP BIT(27) /*!< EXMC SDNWE remapping */ +#define AFIO_PCF5_EXMC_SDCKE0_REMAP BIT(28) /*!< EXMC SDCKE0 remapping */ +#define AFIO_PCF5_EXMC_SDCKE1_REMAP BIT(29) /*!< EXMC SDCKE1 remapping */ +#define AFIO_PCF5_EXMC_SDNE0_REMAP BIT(30) /*!< EXMC SDNE0 remapping */ +#define AFIO_PCF5_EXMC_SDNE1_REMAP BIT(30) /*!< EXMC SDNE1 remapping */ + +/* constants definitions */ +typedef FlagStatus bit_status; + +/* GPIO mode values set */ +#define GPIO_MODE_SET(n, mode) ((uint32_t)((uint32_t)(mode) << (4U * (n)))) +#define GPIO_MODE_MASK(n) (0xFU << (4U * (n))) + +/* GPIO mode definitions */ +#define GPIO_MODE_AIN ((uint8_t)0x00U) /*!< analog input mode */ +#define GPIO_MODE_IN_FLOATING ((uint8_t)0x04U) /*!< floating input mode */ +#define GPIO_MODE_IPD ((uint8_t)0x28U) /*!< pull-down input mode */ +#define GPIO_MODE_IPU ((uint8_t)0x48U) /*!< pull-up input mode */ +#define GPIO_MODE_OUT_OD ((uint8_t)0x14U) /*!< GPIO output with open-drain */ +#define GPIO_MODE_OUT_PP ((uint8_t)0x10U) /*!< GPIO output with push-pull */ +#define GPIO_MODE_AF_OD ((uint8_t)0x1CU) /*!< AFIO output with open-drain */ +#define GPIO_MODE_AF_PP ((uint8_t)0x18U) /*!< AFIO output with push-pull */ + +/* GPIO output max speed value */ +#define GPIO_OSPEED_10MHZ ((uint8_t)0x01U) /*!< output max speed 10MHz */ +#define GPIO_OSPEED_2MHZ ((uint8_t)0x02U) /*!< output max speed 2MHz */ +#define GPIO_OSPEED_50MHZ ((uint8_t)0x03U) /*!< output max speed 50MHz */ + +/* GPIO event output port definitions */ +#define GPIO_EVENT_PORT_GPIOA ((uint8_t)0x00U) /*!< event output port A */ +#define GPIO_EVENT_PORT_GPIOB ((uint8_t)0x01U) /*!< event output port B */ +#define GPIO_EVENT_PORT_GPIOC ((uint8_t)0x02U) /*!< event output port C */ +#define GPIO_EVENT_PORT_GPIOD ((uint8_t)0x03U) /*!< event output port D */ +#define GPIO_EVENT_PORT_GPIOE ((uint8_t)0x04U) /*!< event output port E */ + +/* GPIO output port source definitions */ +#define GPIO_PORT_SOURCE_GPIOA ((uint8_t)0x00U) /*!< output port source A */ +#define GPIO_PORT_SOURCE_GPIOB ((uint8_t)0x01U) /*!< output port source B */ +#define GPIO_PORT_SOURCE_GPIOC ((uint8_t)0x02U) /*!< output port source C */ +#define GPIO_PORT_SOURCE_GPIOD ((uint8_t)0x03U) /*!< output port source D */ +#define GPIO_PORT_SOURCE_GPIOE ((uint8_t)0x04U) /*!< output port source E */ +#define GPIO_PORT_SOURCE_GPIOF ((uint8_t)0x05U) /*!< output port source F */ +#define GPIO_PORT_SOURCE_GPIOG ((uint8_t)0x06U) /*!< output port source G */ +#define GPIO_PORT_SOURCE_GPIOH ((uint8_t)0x07U) /*!< output port source H */ +#define GPIO_PORT_SOURCE_GPIOI ((uint8_t)0x08U) /*!< output port source I */ + +/* GPIO event output pin definitions */ +#define GPIO_EVENT_PIN_0 ((uint8_t)0x00U) /*!< GPIO event pin 0 */ +#define GPIO_EVENT_PIN_1 ((uint8_t)0x01U) /*!< GPIO event pin 1 */ +#define GPIO_EVENT_PIN_2 ((uint8_t)0x02U) /*!< GPIO event pin 2 */ +#define GPIO_EVENT_PIN_3 ((uint8_t)0x03U) /*!< GPIO event pin 3 */ +#define GPIO_EVENT_PIN_4 ((uint8_t)0x04U) /*!< GPIO event pin 4 */ +#define GPIO_EVENT_PIN_5 ((uint8_t)0x05U) /*!< GPIO event pin 5 */ +#define GPIO_EVENT_PIN_6 ((uint8_t)0x06U) /*!< GPIO event pin 6 */ +#define GPIO_EVENT_PIN_7 ((uint8_t)0x07U) /*!< GPIO event pin 7 */ +#define GPIO_EVENT_PIN_8 ((uint8_t)0x08U) /*!< GPIO event pin 8 */ +#define GPIO_EVENT_PIN_9 ((uint8_t)0x09U) /*!< GPIO event pin 9 */ +#define GPIO_EVENT_PIN_10 ((uint8_t)0x0AU) /*!< GPIO event pin 10 */ +#define GPIO_EVENT_PIN_11 ((uint8_t)0x0BU) /*!< GPIO event pin 11 */ +#define GPIO_EVENT_PIN_12 ((uint8_t)0x0CU) /*!< GPIO event pin 12 */ +#define GPIO_EVENT_PIN_13 ((uint8_t)0x0DU) /*!< GPIO event pin 13 */ +#define GPIO_EVENT_PIN_14 ((uint8_t)0x0EU) /*!< GPIO event pin 14 */ +#define GPIO_EVENT_PIN_15 ((uint8_t)0x0FU) /*!< GPIO event pin 15 */ + +/* GPIO output pin source definitions */ +#define GPIO_PIN_SOURCE_0 ((uint8_t)0x00U) /*!< GPIO pin source 0 */ +#define GPIO_PIN_SOURCE_1 ((uint8_t)0x01U) /*!< GPIO pin source 1 */ +#define GPIO_PIN_SOURCE_2 ((uint8_t)0x02U) /*!< GPIO pin source 2 */ +#define GPIO_PIN_SOURCE_3 ((uint8_t)0x03U) /*!< GPIO pin source 3 */ +#define GPIO_PIN_SOURCE_4 ((uint8_t)0x04U) /*!< GPIO pin source 4 */ +#define GPIO_PIN_SOURCE_5 ((uint8_t)0x05U) /*!< GPIO pin source 5 */ +#define GPIO_PIN_SOURCE_6 ((uint8_t)0x06U) /*!< GPIO pin source 6 */ +#define GPIO_PIN_SOURCE_7 ((uint8_t)0x07U) /*!< GPIO pin source 7 */ +#define GPIO_PIN_SOURCE_8 ((uint8_t)0x08U) /*!< GPIO pin source 8 */ +#define GPIO_PIN_SOURCE_9 ((uint8_t)0x09U) /*!< GPIO pin source 9 */ +#define GPIO_PIN_SOURCE_10 ((uint8_t)0x0AU) /*!< GPIO pin source 10 */ +#define GPIO_PIN_SOURCE_11 ((uint8_t)0x0BU) /*!< GPIO pin source 11 */ +#define GPIO_PIN_SOURCE_12 ((uint8_t)0x0CU) /*!< GPIO pin source 12 */ +#define GPIO_PIN_SOURCE_13 ((uint8_t)0x0DU) /*!< GPIO pin source 13 */ +#define GPIO_PIN_SOURCE_14 ((uint8_t)0x0EU) /*!< GPIO pin source 14 */ +#define GPIO_PIN_SOURCE_15 ((uint8_t)0x0FU) /*!< GPIO pin source 15 */ + +/* GPIO pin definitions */ +#define GPIO_PIN_0 BIT(0) /*!< GPIO pin 0 */ +#define GPIO_PIN_1 BIT(1) /*!< GPIO pin 1 */ +#define GPIO_PIN_2 BIT(2) /*!< GPIO pin 2 */ +#define GPIO_PIN_3 BIT(3) /*!< GPIO pin 3 */ +#define GPIO_PIN_4 BIT(4) /*!< GPIO pin 4 */ +#define GPIO_PIN_5 BIT(5) /*!< GPIO pin 5 */ +#define GPIO_PIN_6 BIT(6) /*!< GPIO pin 6 */ +#define GPIO_PIN_7 BIT(7) /*!< GPIO pin 7 */ +#define GPIO_PIN_8 BIT(8) /*!< GPIO pin 8 */ +#define GPIO_PIN_9 BIT(9) /*!< GPIO pin 9 */ +#define GPIO_PIN_10 BIT(10) /*!< GPIO pin 10 */ +#define GPIO_PIN_11 BIT(11) /*!< GPIO pin 11 */ +#define GPIO_PIN_12 BIT(12) /*!< GPIO pin 12 */ +#define GPIO_PIN_13 BIT(13) /*!< GPIO pin 13 */ +#define GPIO_PIN_14 BIT(14) /*!< GPIO pin 14 */ +#define GPIO_PIN_15 BIT(15) /*!< GPIO pin 15 */ +#define GPIO_PIN_ALL BITS(0,15) /*!< GPIO pin all */ + +/* GPIO remap definitions */ +/* AFIO_PCF0 and AFIO_PCF1 remap definitions */ +#define GPIO_SPI0_REMAP ((uint32_t)0x00000001U) /*!< SPI0 remapping */ +#define GPIO_I2C0_REMAP ((uint32_t)0x00000002U) /*!< I2C0 remapping */ +#define GPIO_USART0_REMAP ((uint32_t)0x00000004U) /*!< USART0 remapping */ +#define GPIO_USART1_REMAP ((uint32_t)0x00000008U) /*!< USART1 remapping */ +#define GPIO_USART2_PARTIAL_REMAP ((uint32_t)0x00140010U) /*!< USART2 partial remapping */ +#define GPIO_USART2_FULL_REMAP ((uint32_t)0x00140030U) /*!< USART2 full remapping */ +#define GPIO_TIMER0_PARTIAL_REMAP ((uint32_t)0x00160040U) /*!< TIMER0 partial remapping */ +#define GPIO_TIMER0_FULL_REMAP ((uint32_t)0x001600C0U) /*!< TIMER0 full remapping */ +#define GPIO_TIMER1_PARTIAL_REMAP0 ((uint32_t)0x00180100U) /*!< TIMER1 partial remapping */ +#define GPIO_TIMER1_PARTIAL_REMAP1 ((uint32_t)0x00180200U) /*!< TIMER1 partial remapping */ +#define GPIO_TIMER1_FULL_REMAP ((uint32_t)0x00180300U) /*!< TIMER1 full remapping */ +#define GPIO_TIMER2_PARTIAL_REMAP ((uint32_t)0x001A0800U) /*!< TIMER2 partial remapping */ +#define GPIO_TIMER2_FULL_REMAP ((uint32_t)0x001A0C00U) /*!< TIMER2 full remapping */ +#define GPIO_TIMER3_REMAP ((uint32_t)0x00001000U) /*!< TIMER3 remapping */ +#define GPIO_CAN0_PARTIAL_REMAP ((uint32_t)0x001D4000U) /*!< CAN0 partial remapping */ +#define GPIO_CAN0_FULL_REMAP ((uint32_t)0x001D6000U) /*!< CAN0 full remapping */ +#define GPIO_PD01_REMAP ((uint32_t)0x00008000U) /*!< PD01 remapping */ +#define GPIO_TIMER4CH3_IREMAP ((uint32_t)0x00200001U) /*!< TIMER4 channel3 internal remapping */ +#define GPIO_ADC0_ETRGINS_REMAP ((uint32_t)0x00200002U) /*!< ADC0 external trigger inserted conversion remapping */ +#define GPIO_ADC0_ETRGREG_REMAP ((uint32_t)0x00200004U) /*!< ADC0 external trigger regular conversion remapping */ +#define GPIO_ADC1_ETRGINS_REMAP ((uint32_t)0x00200008U) /*!< ADC1 external trigger inserted conversion remapping */ +#define GPIO_ADC1_ETRGREG_REMAP ((uint32_t)0x00200010U) /*!< ADC1 external trigger regular conversion remapping */ +#define GPIO_ENET_REMAP ((uint32_t)0x00200020U) /*!< ENET remapping */ +#define GPIO_CAN1_REMAP ((uint32_t)0x00200040U) /*!< CAN1 remapping */ +#define GPIO_SWJ_NONJTRST_REMAP ((uint32_t)0x00300100U) /*!< full SWJ(JTAG-DP + SW-DP),but without NJTRST */ +#define GPIO_SWJ_SWDPENABLE_REMAP ((uint32_t)0x00300200U) /*!< JTAG-DP disabled and SW-DP enabled */ +#define GPIO_SWJ_DISABLE_REMAP ((uint32_t)0x00300400U) /*!< JTAG-DP disabled and SW-DP disabled */ +#define GPIO_SPI2_REMAP ((uint32_t)0x00201100U) /*!< SPI2 remapping */ +#define GPIO_TIMER1ITI1_REMAP ((uint32_t)0x00202000U) /*!< TIMER1 internal trigger 1 remapping */ +#define GPIO_PTP_PPS_REMAP ((uint32_t)0x00204000U) /*!< ethernet PTP PPS remapping */ +#define GPIO_TIMER8_REMAP ((uint32_t)0x80000020U) /*!< TIMER8 remapping */ +#define GPIO_TIMER9_REMAP ((uint32_t)0x80000040U) /*!< TIMER9 remapping */ +#define GPIO_TIMER10_REMAP ((uint32_t)0x80000080U) /*!< TIMER10 remapping */ +#define GPIO_TIMER12_REMAP ((uint32_t)0x80000100U) /*!< TIMER12 remapping */ +#define GPIO_TIMER13_REMAP ((uint32_t)0x80000200U) /*!< TIMER13 remapping */ +#define GPIO_EXMC_NADV_REMAP ((uint32_t)0x80000400U) /*!< EXMC_NADV connect/disconnect */ + +/* AFIO_PCF2 remap definitions */ +#define GPIO_PCF2_DCI_VSYNC_PG9_REMAP ((uint32_t)0x00000001U) /*!< DCI VSYNC remapped to PG9 */ +#define GPIO_PCF2_DCI_VSYNC_PI5_REMAP ((uint32_t)0x00000003U) /*!< DCI VSYNC remapped to PI5 */ +#define GPIO_PCF2_DCI_D0_PC6_REMAP ((uint32_t)0x00000004U) /*!< DCI D0 remapped to PC6 */ +#define GPIO_PCF2_DCI_D0_PH9_REMAP ((uint32_t)0x0000000CU) /*!< DCI D0 remapped to PH9 */ +#define GPIO_PCF2_DCI_D1_PC7_REMAP ((uint32_t)0x00000010U) /*!< DCI D1 remapped to PC7 */ +#define GPIO_PCF2_DCI_D1_PH10_REMAP ((uint32_t)0x00000030U) /*!< DCI D1 remapped to PH10 */ +#define GPIO_PCF2_DCI_D2_PE0_REMAP ((uint32_t)0x00000040U) /*!< DCI D2 remapped to PE0 */ +#define GPIO_PCF2_DCI_D2_PG10_REMAP ((uint32_t)0x00000080U) /*!< DCI D2 remapped to PG10 */ +#define GPIO_PCF2_DCI_D2_PH11_REMAP ((uint32_t)0x000000C0U) /*!< DCI D2 remapped to PH11 */ +#define GPIO_PCF2_DCI_D3_PE1_REMAP ((uint32_t)0x00000100U) /*!< DCI D3 remapped to PE1 */ +#define GPIO_PCF2_DCI_D3_PG11_REMAP ((uint32_t)0x00000200U) /*!< DCI D3 remapped to PG11 */ +#define GPIO_PCF2_DCI_D3_PH12_REMAP ((uint32_t)0x00000300U) /*!< DCI D3 remapped to PH12 */ +#define GPIO_PCF2_DCI_D4_PE4_REMAP ((uint32_t)0x00000400U) /*!< DCI D4 remapped to PE4 */ +#define GPIO_PCF2_DCI_D4_PH14_REMAP ((uint32_t)0x00000C00U) /*!< DCI D4 remapped to PH14 */ +#define GPIO_PCF2_DCI_D5_PD3_REMAP ((uint32_t)0x00001000U) /*!< DCI D5 remapped to PD3 */ +#define GPIO_PCF2_DCI_D5_PI4_REMAP ((uint32_t)0x00003000U) /*!< DCI D5 remapped to PI4 */ +#define GPIO_PCF2_DCI_D6_PE5_REMAP ((uint32_t)0x00004000U) /*!< DCI D6 remapped to PE5 */ +#define GPIO_PCF2_DCI_D6_PI6_REMAP ((uint32_t)0x0000C000U) /*!< DCI D6 remapped to PI6 */ +#define GPIO_PCF2_DCI_D7_PE6_REMAP ((uint32_t)0x00010000U) /*!< DCI D7 remapped to PE6 */ +#define GPIO_PCF2_DCI_D7_PI7_REMAP ((uint32_t)0x00030000U) /*!< DCI D7 remapped to PI7 */ +#define GPIO_PCF2_DCI_D8_PH6_REMAP ((uint32_t)0x00040000U) /*!< DCI D8 remapped to PH6 */ +#define GPIO_PCF2_DCI_D8_PI1_REMAP ((uint32_t)0x000C0000U) /*!< DCI D8 remapped to PI1 */ +#define GPIO_PCF2_DCI_D9_PH7_REMAP ((uint32_t)0x00100000U) /*!< DCI D9 remapped to PH7 */ +#define GPIO_PCF2_DCI_D9_PI2_REMAP ((uint32_t)0x00300000U) /*!< DCI D9 remapped to PI2 */ +#define GPIO_PCF2_DCI_D10_PD6_REMAP ((uint32_t)0x00400000U) /*!< DCI D10 remapped to PD6 */ +#define GPIO_PCF2_DCI_D10_PI3_REMAP ((uint32_t)0x00C00000U) /*!< DCI D10 remapped to PI3 */ +#define GPIO_PCF2_DCI_D11_PF10_REMAP ((uint32_t)0x01000000U) /*!< DCI D11 remapped to PF10 */ +#define GPIO_PCF2_DCI_D11_PH15_REMAP ((uint32_t)0x03000000U) /*!< DCI D11 remapped to PH15 */ +#define GPIO_PCF2_DCI_D12_PG6_REMAP ((uint32_t)0x04000000U) /*!< DCI D12 remapped to PG6 */ +#define GPIO_PCF2_DCI_D13_PG15_REMAP ((uint32_t)0x08000000U) /*!< DCI D12 remapped to PG15 */ +#define GPIO_PCF2_DCI_D13_PI0_REMAP ((uint32_t)0x18000000U) /*!< DCI D13 remapped to PI0 */ +#define GPIO_PCF2_DCI_HSYNC_PH8_REMAP ((uint32_t)0x20000000U) /*!< DCI HSYNC to PH8 */ +#define GPIO_PCF2_PH01_REMAP ((uint32_t)0x80000000U) /*!< PH0/PH1 remapping */ + +/* AFIO_PCF3 remap definitions */ +#define GPIO_PCF3_TLI_B5_PA3_REMAP ((uint32_t)0x00000001U) /*!< TLI B5 remapped to PA3 */ +#define GPIO_PCF3_TLI_VSYNC_PA4_REMAP ((uint32_t)0x00000002U) /*!< TLI VSYNC remapped to PA4 */ +#define GPIO_PCF3_TLI_G2_PA6_REMAP ((uint32_t)0x00000004U) /*!< TLI G2 remapped to PA6 */ +#define GPIO_PCF3_TLI_R6_PA8_REMAP ((uint32_t)0x00000008U) /*!< TLI R6 remapped to PA8 */ +#define GPIO_PCF3_TLI_R4_PA11_REMAP ((uint32_t)0x00000010U) /*!< TLI R4 remapped to PA11 */ +#define GPIO_PCF3_TLI_R5_PA12_REMAP ((uint32_t)0x00000020U) /*!< TLI R5 remapped to PA12 */ +#define GPIO_PCF3_TLI_R3_PB0_REMAP ((uint32_t)0x00000040U) /*!< TLI R3 remapped to PB0 */ +#define GPIO_PCF3_TLI_R6_PB1_REMAP ((uint32_t)0x00000080U) /*!< TLI R6 remapped to PB1 */ +#define GPIO_PCF3_TLI_B6_PB8_REMAP ((uint32_t)0x00000100U) /*!< TLI B6 remapped to PB8 */ +#define GPIO_PCF3_TLI_B7_PB9_REMAP ((uint32_t)0x00000200U) /*!< TLI B7 remapped to PB9 */ +#define GPIO_PCF3_TLI_G4_PB10_REMAP ((uint32_t)0x00000400U) /*!< TLI G4 remapped to PB10 */ +#define GPIO_PCF3_TLI_G5_PB11_REMAP ((uint32_t)0x00000800U) /*!< TLI G5 remapped to PB11 */ +#define GPIO_PCF3_TLI_HSYNC_PC6_REMAP ((uint32_t)0x00001000U) /*!< TLI HSYNC remapped to PC6 */ +#define GPIO_PCF3_TLI_G6_PC7_REMAP ((uint32_t)0x00002000U) /*!< TLI G6 remapped to PC7 */ +#define GPIO_PCF3_TLI_R2_PC10_REMAP ((uint32_t)0x00004000U) /*!< TLI R2 remapped to PC10 */ +#define GPIO_PCF3_TLI_G7_PD3_REMAP ((uint32_t)0x00008000U) /*!< TLI G7 remapped to PD3 */ +#define GPIO_PCF3_TLI_B2_PD6_REMAP ((uint32_t)0x00010000U) /*!< TLI B2 remapped to PD6 */ +#define GPIO_PCF3_TLI_B3_PD10_REMAP ((uint32_t)0x00020000U) /*!< TLI B3 remapped to PD10 */ +#define GPIO_PCF3_TLI_B0_PE4_REMAP ((uint32_t)0x00040000U) /*!< TLI B0 remapped to PE4 */ +#define GPIO_PCF3_TLI_G0_PE5_REMAP ((uint32_t)0x00080000U) /*!< TLI G0 remapped to PE5 */ +#define GPIO_PCF3_TLI_G1_PE6_REMAP ((uint32_t)0x00100000U) /*!< TLI G1 remapped to PE6 */ +#define GPIO_PCF3_TLI_G3_PE11_REMAP ((uint32_t)0x00200000U) /*!< TLI G3 remapped to PE11 */ +#define GPIO_PCF3_TLI_B4_PE12_REMAP ((uint32_t)0x00400000U) /*!< TLI B4 remapped to PE12 */ +#define GPIO_PCF3_TLI_DE_PE13_REMAP ((uint32_t)0x00800000U) /*!< TLI DE remapped to PE13 */ +#define GPIO_PCF3_TLI_CLK_PE14_REMAP ((uint32_t)0x01000000U) /*!< TLI CLK remapped to PE14 */ +#define GPIO_PCF3_TLI_R7_PE15_REMAP ((uint32_t)0x02000000U) /*!< TLI R7 remapped to PE15 */ +#define GPIO_PCF3_TLI_DE_PF10_REMAP ((uint32_t)0x04000000U) /*!< TLI DE remapped to PF10 */ +#define GPIO_PCF3_TLI_R7_PG6_REMAP ((uint32_t)0x08000000U) /*!< TLI R7 remapped to PG6 */ +#define GPIO_PCF3_TLI_CLK_PG7_REMAP ((uint32_t)0x10000000U) /*!< TLI CLK remapped to PG7 */ +#define GPIO_PCF3_TLI_G3_PG10_REMAP ((uint32_t)0x20000000U) /*!< TLI G3 remapped to PG10 */ +#define GPIO_PCF3_TLI_B2_PG10_REMAP ((uint32_t)0x40000000U) /*!< TLI B2 remapped to PG10 */ +#define GPIO_PCF3_TLI_B3_PG11_REMAP ((uint32_t)0x80000000U) /*!< TLI B3 remapped to PG11 */ + +/* AFIO_PCF4 remap definitions */ +#define GPIO_PCF4_TLI_B4_PG12_REMAP ((uint32_t)0x00000001U) /*!< TLI B4 remapped to PG12 */ +#define GPIO_PCF4_TLI_B1_PG12_REMAP ((uint32_t)0x00000002U) /*!< TLI B1 remapped to PG12 */ +#define GPIO_PCF4_TLI_R0_PH2_REMAP2 ((uint32_t)0x00000004U) /*!< TLI R0 remapped to PH2 */ +#define GPIO_PCF4_TLI_R1_PH3_REMAP ((uint32_t)0x00000008U) /*!< TLI R1 remapped to PH3 */ +#define GPIO_PCF4_TLI_R2_PH8_REMAP ((uint32_t)0x00000010U) /*!< TLI R2 remapped to PH8 */ +#define GPIO_PCF4_TLI_R3_PH9_REMAP ((uint32_t)0x00000020U) /*!< TLI R3 remapped to PH9 */ +#define GPIO_PCF4_TLI_R4_PH10_REMAP ((uint32_t)0x00000040U) /*!< TLI R4 remapped to PH10 */ +#define GPIO_PCF4_TLI_R5_PH11_REMAP ((uint32_t)0x00000080U) /*!< TLI R5 remapped to PH11 */ +#define GPIO_PCF4_TLI_R6_PH12_REMAP ((uint32_t)0x00000100U) /*!< TLI R6 remapped to PH12 */ +#define GPIO_PCF4_TLI_G2_PH13_REMAP ((uint32_t)0x00000200U) /*!< TLI G2 remapped to PH13 */ +#define GPIO_PCF4_TLI_G3_PH14_REMAP ((uint32_t)0x00000400U) /*!< TLI G3 remapped to PH14 */ +#define GPIO_PCF4_TLI_G4_PH15_REMAP ((uint32_t)0x00000800U) /*!< TLI G4 remapped to PH15 */ +#define GPIO_PCF4_TLI_G5_PI0_REMAP ((uint32_t)0x00001000U) /*!< TLI G5 remapped to PI0 */ +#define GPIO_PCF4_TLI_G6_PI1_REMAP ((uint32_t)0x00002000U) /*!< TLI G6 remapped to PI1 */ +#define GPIO_PCF4_TLI_G7_PI2_REMAP ((uint32_t)0x00004000U) /*!< TLI G7 remapped to PI2 */ +#define GPIO_PCF4_TLI_B4_PI4_REMAP ((uint32_t)0x00008000U) /*!< TLI B4 remapped to PI4 */ +#define GPIO_PCF4_TLI_B5_PI5_REMAP ((uint32_t)0x00010000U) /*!< TLI B5 remapped to PI5 */ +#define GPIO_PCF4_TLI_B6_PI6_REMAP ((uint32_t)0x00020000U) /*!< TLI B6 remapped to PI6 */ +#define GPIO_PCF4_TLI_B7_PI7_REMAP ((uint32_t)0x00040000U) /*!< TLI B7 remapped to PI7 */ +#define GPIO_PCF4_TLI_VSYNC_PI9_REMAP ((uint32_t)0x00080000U) /*!< TLI VSYNC remapped to PI9 */ +#define GPIO_PCF4_TLI_HSYNC_PI10_REMAP ((uint32_t)0x00100000U) /*!< TLI HSYNC remapped to PI10 */ +#define GPIO_PCF4_TLI_R0_PH4_REMAP ((uint32_t)0x00200000U) /*!< TLI R0 remapped to PH4 */ +#define GPIO_PCF4_TLI_R1_PI3_REMAP ((uint32_t)0x00400000U) /*!< TLI R1 remapped to PI3 */ +#define GPIO_PCF4_SPI1_SCK_PD3_REMAP ((uint32_t)0x00800000U) /*!< SPI1 SCK remapped to PD3 */ +#define GPIO_PCF4_SPI2_MOSI_PD6_REMAP ((uint32_t)0x01000000U) /*!< SPI2 MOSI remapped to PD6 */ + +/* AFIO_PCF5 remap definitions */ +#define GPIO_PCF5_I2C2_REMAP0 ((uint32_t)0x00000001U) /*!< I2C2 remapping 0 */ +#define GPIO_PCF5_I2C2_REMAP1 ((uint32_t)0x00000002U) /*!< I2C2 remapping 1 */ +#define GPIO_PCF5_TIMER1_CH0_REMAP ((uint32_t)0x00000004U) /*!< TIMER1 CH0 remapped to PA5 */ +#define GPIO_PCF5_TIMER4_REMAP ((uint32_t)0x00000008U) /*!< TIMER4 CH0 remapping */ +#define GPIO_PCF5_TIMER7_CHON_REMAP0 ((uint32_t)0x00000020U) /*!< TIMER7 CHON remapping 0 */ +#define GPIO_PCF5_TIMER7_CHON_REMAP1 ((uint32_t)0x00000030U) /*!< TIMER7 CHON remapping 1 */ +#define GPIO_PCF5_TIMER7_CH_REMAP ((uint32_t)0x00000040U) /*!< TIMER7 CH remapping */ +#define GPIO_PCF5_I2C1_REMAP0 ((uint32_t)0x00000100U) /*!< I2C1 remapping 0 */ +#define GPIO_PCF5_I2C1_REMAP1 ((uint32_t)0x00000180U) /*!< I2C1 remapping 1 */ +#define GPIO_PCF5_SPI1_NSCK_REMAP0 ((uint32_t)0x00000400U) /*!< SPI1 NSS/SCK remapping 0 */ +#define GPIO_PCF5_SPI1_NSCK_REMAP1 ((uint32_t)0x00000600U) /*!< SPI1 NSS/SCK remapping 1 */ +#define GPIO_PCF5_SPI1_IO_REMAP0 ((uint32_t)0x00000800U) /*!< SPI1 MISO/MOSI remapping 0 */ +#define GPIO_PCF5_SPI1_IO_REMAP1 ((uint32_t)0x00001800U) /*!< SPI1 MISO/MOSI remapping 1 */ +#define GPIO_PCF5_UART3_REMAP ((uint32_t)0x00002000U) /*!< UART3 remapping */ +#define GPIO_PCF5_TIMER11_REMAP ((uint32_t)0x00004000U) /*!< TIMER11 remapping */ +#define GPIO_PCF5_CAN0_ADD_REMAP ((uint32_t)0x00008000U) /*!< CAN0 addition remapping */ +#define GPIO_PCF5_ENET_TXD3_REMAP ((uint32_t)0x00010000U) /*!< ETH_TXD3 remapped to PE2 */ +#define GPIO_PCF5_PPS_HI_REMAP ((uint32_t)0x00020000U) /*!< ETH_PPS_OUT remapped to PG8 */ +#define GPIO_PCF5_ENET_TXD01_REMAP ((uint32_t)0x00040000U) /*!< ETH_TX_EN/ETH_TXD0/ETH_TXD1 remapping */ +#define GPIO_PCF5_ENET_CRSCOL_REMAP ((uint32_t)0x00080000U) /*!< ETH_MII_CRS/ETH_MII_COL remapping */ +#define GPIO_PCF5_ENET_RX_HI_REMAP ((uint32_t)0x00100000U) /*!< ETH_RXD2/ETH_RXD3/ETH_RX_ER remapping */ +#define GPIO_PCF5_UART6_REMAP ((uint32_t)0x00200000U) /*!< UART6 remapping */ +#define GPIO_PCF5_USART5_CK_PG7_REMAP ((uint32_t)0x00400000U) /*!< USART5 CK remapped to PG7 */ +#define GPIO_PCF5_USART5_RTS_PG12_REMAP ((uint32_t)0x00800000U) /*!< USART5 RTS remapped to PG12 */ +#define GPIO_PCF5_USART5_CTS_PG13_REMAP ((uint32_t)0x01000000U) /*!< USART5 CTS remapped to PG13 */ +#define GPIO_PCF5_USART5_TX_PG14_REMAP ((uint32_t)0x02000000U) /*!< USART5 TX remapped to PG14 */ +#define GPIO_PCF5_USART5_RX_PG9_REMAP ((uint32_t)0x04000000U) /*!< USART5 RX remapped to PG9 */ +#define GPIO_PCF5_EXMC_SDNWE_PC0_REMAP ((uint32_t)0x08000000U) /*!< EXMC SDNWE remapped to PC0 */ +#define GPIO_PCF5_EXMC_SDCKE0_PC3_REMAP ((uint32_t)0x10000000U) /*!< EXMC SDCKE0 remapped to PC3 */ +#define GPIO_PCF5_EXMC_SDCKE1_PB5_REMAP ((uint32_t)0x20000000U) /*!< EXMC SDCKE1 remapped to PB5 */ +#define GPIO_PCF5_EXMC_SDNE0_PC2_REMAP ((uint32_t)0x40000000U) /*!< EXMC SDNE0 remapped to PC2 */ +#define GPIO_PCF5_EXMC_SDNE1_PB6_REMAP ((uint32_t)0x80000000U) /*!< EXMC SDNE1 remapped to PB6 */ + +/* AFIO port configuration register selection */ +#define GPIO_PCF2 ((uint8_t)0x02U) /*!< AFIO port configuration register 2 */ +#define GPIO_PCF3 ((uint8_t)0x03U) /*!< AFIO port configuration register 3 */ +#define GPIO_PCF4 ((uint8_t)0x04U) /*!< AFIO port configuration register 4 */ +#define GPIO_PCF5 ((uint8_t)0x05U) /*!< AFIO port configuration register 5*/ + +/* ethernet MII or RMII PHY selection */ +#define GPIO_ENET_PHY_MII ((uint32_t)0x00000000U) /*!< configure ethernet MAC for connection with an MII PHY */ +#define GPIO_ENET_PHY_RMII AFIO_PCF0_ENET_PHY_SEL /*!< configure ethernet MAC for connection with an RMII PHY */ + +/* function declarations */ +/* initialization functions */ +/* reset GPIO port */ +void gpio_deinit(uint32_t gpio_periph); +/* reset alternate function I/O(AFIO) */ +void gpio_afio_deinit(void); +/* GPIO parameter initialization */ +void gpio_init(uint32_t gpio_periph, uint32_t mode, uint32_t speed, uint32_t pin); + +/* function configuration */ +/* set GPIO pin bit */ +void gpio_bit_set(uint32_t gpio_periph, uint32_t pin); +/* reset GPIO pin bit */ +void gpio_bit_reset(uint32_t gpio_periph, uint32_t pin); +/* write data to the specified GPIO pin */ +void gpio_bit_write(uint32_t gpio_periph, uint32_t pin, bit_status bit_value); +/* write data to the specified GPIO port */ +void gpio_port_write(uint32_t gpio_periph, uint16_t data); + +/* get GPIO pin input status */ +FlagStatus gpio_input_bit_get(uint32_t gpio_periph, uint32_t pin); +/* get GPIO port input status */ +uint16_t gpio_input_port_get(uint32_t gpio_periph); +/* get GPIO pin output status */ +FlagStatus gpio_output_bit_get(uint32_t gpio_periph, uint32_t pin); +/* get GPIO port output status */ +uint16_t gpio_output_port_get(uint32_t gpio_periph); + +/* configure GPIO pin remap */ +void gpio_pin_remap_config(uint32_t gpio_remap, ControlStatus newvalue); +/* configure GPIO pin remap1 */ +void gpio_pin_remap1_config(uint8_t remap_reg, uint32_t remap, ControlStatus newvalue); + +/* select GPIO pin exti sources */ +void gpio_exti_source_select(uint8_t output_port, uint8_t output_pin); +/* configure GPIO pin event output */ +void gpio_event_output_config(uint8_t output_port, uint8_t output_pin); +/* enable GPIO pin event output */ +void gpio_event_output_enable(void); +/* disable GPIO pin event output */ +void gpio_event_output_disable(void); + +/* lock GPIO pin bit */ +void gpio_pin_lock(uint32_t gpio_periph, uint32_t pin); + +/* select ethernet MII or RMII PHY */ +void gpio_ethernet_phy_select(uint32_t enet_sel); + +#endif /* GD32F20X_GPIO_H */ diff --git a/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_standard_peripheral/Include/gd32f20x_hau.h b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_standard_peripheral/Include/gd32f20x_hau.h new file mode 100644 index 0000000000..069574a943 --- /dev/null +++ b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_standard_peripheral/Include/gd32f20x_hau.h @@ -0,0 +1,208 @@ +/*! + \file gd32f20x_hau.h + \brief definitions for the HAU + + \version 2015-07-15, V1.0.0, firmware for GD32F20x + \version 2017-06-05, V2.0.0, firmware for GD32F20x + \version 2018-10-31, V2.1.0, firmware for GD32F20x + \version 2020-09-30, V2.2.0, firmware for GD32F20x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef GD32F20X_HAU_H +#define GD32F20X_HAU_H + +#include "gd32f20x.h" + +/* HAU definitions */ +#define HAU HAU_BASE + +/* registers definitions */ +#define HAU_CTL REG32(HAU + 0x00U) /*!< control register */ +#define HAU_DI REG32(HAU + 0x04U) /*!< data input register */ +#define HAU_CFG REG32(HAU + 0x08U) /*!< configuration register */ +#define HAU_DO0 REG32(HAU + 0x0CU) /*!< data output register 0 */ +#define HAU_DO1 REG32(HAU + 0x10U) /*!< data output register 1 */ +#define HAU_DO2 REG32(HAU + 0x14U) /*!< data output register 2 */ +#define HAU_DO3 REG32(HAU + 0x18U) /*!< data output register 3 */ +#define HAU_DO4 REG32(HAU + 0x1CU) /*!< data output register 4 */ +#define HAU_DO5 REG32(HAU + 0x324U) /*!< data output register 5 */ +#define HAU_DO6 REG32(HAU + 0x328U) /*!< data output register 6 */ +#define HAU_DO7 REG32(HAU + 0x32CU) /*!< data output register 7 */ +#define HAU_INTEN REG32(HAU + 0x20U) /*!< interrupt enable register */ +#define HAU_STAT REG32(HAU + 0x24U) /*!< status and interrupt flag register */ + +/* bits definitions */ +/* HAU_CTL */ +#define HAU_CTL_START BIT(2) /*!< set to 1 to reset the HAU processor core, so that it is ready to start the digest calculation */ +#define HAU_CTL_DMAE BIT(3) /*!< DMA enable */ +#define HAU_CTL_DATAM BITS(4,5) /*!< data type mode */ +#define HAU_CTL_HMS BIT(6) /*!< HAU mode selection */ +#define HAU_CTL_ALGM_0 BIT(7) /*!< algorithm selection bit 0 */ +#define HAU_CTL_NWIF BITS(8,11) /*!< number of words in the input FIFO */ +#define HAU_CTL_DINE BIT(12) /*!< DI register not empty */ +#define HAU_CTL_MDS BIT(13) /*!< multiple DMA selection */ +#define HAU_CTL_KLM BIT(16) /*!< key length mode */ +#define HAU_CTL_ALGM_1 BIT(18) /*!< algorithm selection bit 1 */ + +/* HAU_DI */ +#define HAU_DI_DI BITS(0,31) /*!< message data input */ + +/* HAU_CFG */ +#define HAU_CFG_VBL BITS(0,4) /*!< valid bits length in the last word */ +#define HAU_CFG_CALEN BIT(8) /*!< digest calculation enable */ + +/* HAU_DOx x=0..7 */ +#define HAU_DOX_DOX BITS(0,31) /*!< message digest result of hash algorithm */ + +/* HAU_INTEN */ +#define HAU_INTEN_DIIE BIT(0) /*!< data input interrupt enable */ +#define HAU_INTEN_CCIE BIT(1) /*!< calculation completion interrupt enable */ + +/* HAU_STAT */ +#define HAU_STAT_DINT BIT(0) /*!< data input interrupt flag */ +#define HAU_STAT_CINT BIT(1) /*!< digest calculation completion interrupt flag */ +#define HAU_STAT_DMAS BIT(2) /*!< DMA status */ +#define HAU_STAT_BUSY BIT(3) /*!< busy bit */ + +/* constants definitions */ +/* structure for initialization of the hau */ +typedef struct +{ + uint32_t algo; /*!< algorithm selection */ + uint32_t mode; /*!< HAU mode selection */ + uint32_t datatype; /*!< data type mode */ + uint32_t keytype; /*!< key length mode */ +}hau_init_parameter_struct; + +/* structure for message digest result of the hau */ +typedef struct +{ + uint32_t out[8]; /* message digest result 0-7 */ +}hau_digest_parameter_struct; + +/* hau_ctl register value */ +#define HAU_ALGO_SHA1 ((uint32_t)0x00000000U) /*!< HAU function is SHA1 */ +#define HAU_ALGO_SHA224 HAU_CTL_ALGM_1 /*!< HAU function is SHA224 */ +#define HAU_ALGO_SHA256 (HAU_CTL_ALGM_1 | HAU_CTL_ALGM_0) /*!< HAU function is SHA256 */ +#define HAU_ALGO_MD5 HAU_CTL_ALGM_0 /*!< HAU function is MD5 */ + +#define HAU_MODE_HASH ((uint32_t)0x00000000U) /*!< HAU mode is HASH */ +#define HAU_MODE_HMAC HAU_CTL_HMS /*!< HAU mode is HMAC */ + +#define CTL_DATAM_1(regval) (BITS(4,5) & ((uint32_t)(regval) << 4)) /*!< write value to HAU_CTL_DATAM bit field */ +#define HAU_SWAPPING_32BIT CTL_DATAM_1(0) /*!< no swapping */ +#define HAU_SWAPPING_16BIT CTL_DATAM_1(1) /*!< half-word swapping */ +#define HAU_SWAPPING_8BIT CTL_DATAM_1(2) /*!< bytes swapping */ +#define HAU_SWAPPING_1BIT CTL_DATAM_1(3) /*!< bit swapping */ + +#define HAU_KEY_SHORTER_64 ((uint32_t)0x00000000U) /*!< HMAC key is <= 64 bytes */ +#define HAU_KEY_LONGGER_64 HAU_CTL_KLM /*!< HMAC key is > 64 bytes */ + +#define GET_CTL_NWIF(regval) GET_BITS((regval),8,11) /*!< get value of HAU_CTL_NWIF bit field */ + +#define SINGLE_DMA_AUTO_DIGEST ((uint32_t)0x00000000U) /*!< message padding and message digest calculation at the end of a DMA transfer */ +#define MULTIPLE_DMA_NO_DIGEST HAU_CTL_MDS /*!< multiple DMA transfers needed and CALEN bit is not automatically set at the end of a DMA transfer */ + +/* hau_cfg register value */ +#define CFG_VBL(regval) (BITS(0,4) & ((regval) << 0)) /*!< write value to HAU_CFG_VBL bit field */ + +/* hau_inten register value */ +#define HAU_INT_DATA_INPUT HAU_INTEN_DIIE /*!< a new block can be entered into the IN buffer */ +#define HAU_INT_CALCULATION_COMPLETE HAU_INTEN_CCIE /*!< calculation complete */ + +#define HAU_FLAG_DATA_INPUT HAU_STAT_DINT /*!< there is enough space (16 bytes) in the input FIFO */ +#define HAU_FLAG_CALCULATION_COMPLETE HAU_STAT_CINT /*!< digest calculation is completed */ +#define HAU_FLAG_DMA HAU_STAT_DMAS /*!< DMA is enabled (DMAE =1) or a transfer is processing */ +#define HAU_FLAG_BUSY HAU_STAT_BUSY /*!< data block is in process */ +#define HAU_FLAG_INFIFO_NO_EMPTY HAU_CTL_DINE /*!< the input FIFO is not empty */ + +#define HAU_INT_FLAG_DATA_INPUT HAU_STAT_DINT /*!< there is enough space (16 bytes) in the input FIFO */ +#define HAU_INT_FLAG_CALCULATION_COMPLETE HAU_STAT_CINT /*!< digest calculation is completed */ + +/* function declarations */ +/* initialization functions */ +/* reset the HAU peripheral */ +void hau_deinit(void); +/* initialize the HAU peripheral parameters */ +void hau_init(hau_init_parameter_struct* initpara); +/* initialize the structure hau_initpara */ +void hau_init_parameter_init(hau_init_parameter_struct* initpara); +/* reset the HAU processor core */ +void hau_reset(void); +/* configure the number of valid bits in last word of the message */ +void hau_last_word_validbits_num_config(uint32_t valid_num); +/* write data to the IN FIFO */ +void hau_data_write(uint32_t data); +/* return the number of words already written into the IN FIFO */ +uint32_t hau_infifo_words_num_get(void); +/* read the message digest result */ +void hau_digest_read(hau_digest_parameter_struct* digestpara); +/* enable digest calculation */ +void hau_digest_calculation_enable(void); +/* configure single or multiple DMA is used, and digest calculation at the end of a DMA transfer or not */ +void hau_multiple_single_dma_config(uint32_t multi_single); +/* enable the HAU DMA interface */ +void hau_dma_enable(void); +/* disable the HAU DMA interface */ +void hau_dma_disable(void); + +/* calculate digest in HASH mode */ +/* calculate digest using SHA1 in HASH mode */ +ErrStatus hau_hash_sha_1(uint8_t *input, uint32_t in_length, uint8_t output[20]); +/* calculate digest using SHA1 in HMAC mode */ +ErrStatus hau_hmac_sha_1(uint8_t *key, uint32_t keysize, uint8_t *input, uint32_t in_length, uint8_t output[20]); +/* calculate digest using SHA224 in HASH mode */ +ErrStatus hau_hash_sha_224(uint8_t *input, uint32_t in_length, uint8_t output[28]); +/* calculate digest using SHA224 in HMAC mode */ +ErrStatus hau_hmac_sha_224(uint8_t *key, uint32_t keysize, uint8_t *input, uint32_t in_length, uint8_t output[28]); +/* calculate digest using SHA256 in HASH mode */ +ErrStatus hau_hash_sha_256(uint8_t *input, uint32_t in_length, uint8_t output[32]); +/* calculate digest using SHA256 in HMAC mode */ +ErrStatus hau_hmac_sha_256(uint8_t *key, uint32_t keysize, uint8_t *input, uint32_t in_length, uint8_t output[32]); +/* calculate digest using MD5 in HASH mode */ +ErrStatus hau_hash_md5(uint8_t *input, uint32_t in_length, uint8_t output[16]); +/* calculate digest using MD5 in HMAC mode */ +ErrStatus hau_hmac_md5(uint8_t *key, uint32_t keysize, uint8_t *input, uint32_t in_length, uint8_t output[16]); + +/* interrupt & flag functions */ +/* get the HAU flag status */ +FlagStatus hau_flag_get(uint32_t flag); +/* clear the HAU flag status */ +void hau_flag_clear(uint32_t flag); +/* enable the HAU interrupts */ +void hau_interrupt_enable(uint32_t interrupt); +/* disable the HAU interrupts */ +void hau_interrupt_disable(uint32_t interrupt); +/* get the HAU interrupt flag status */ +FlagStatus hau_interrupt_flag_get(uint32_t int_flag); +/* clear the HAU interrupt flag status */ +void hau_interrupt_flag_clear(uint32_t int_flag); + +#endif /*GD32F20X_HAU_H */ diff --git a/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_standard_peripheral/Include/gd32f20x_i2c.h b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_standard_peripheral/Include/gd32f20x_i2c.h new file mode 100644 index 0000000000..f47b35af05 --- /dev/null +++ b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_standard_peripheral/Include/gd32f20x_i2c.h @@ -0,0 +1,352 @@ +/*! + \file gd32f20x_i2c.h + \brief definitions for the I2C + + \version 2015-07-15, V1.0.0, firmware for GD32F20x + \version 2017-06-05, V2.0.0, firmware for GD32F20x + \version 2018-10-31, V2.1.0, firmware for GD32F20x + \version 2020-09-30, V2.2.0, firmware for GD32F20x + \version 2019-04-16, V2.1.1, firmware for GD32F20x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef GD32F20X_I2C_H +#define GD32F20X_I2C_H + +#include "gd32f20x.h" + +/* I2Cx(x=0,1,2) definitions */ +#define I2C0 I2C_BASE /*!< I2C0 base address */ +#define I2C1 (I2C_BASE + 0x00000400U) /*!< I2C1 base address */ +#define I2C2 (I2C_BASE + 0x00006C00U) /*!< I2C2 base address */ + +/* registers definitions */ +#define I2C_CTL0(i2cx) REG32((i2cx) + 0x00U) /*!< I2C control register 0 */ +#define I2C_CTL1(i2cx) REG32((i2cx) + 0x04U) /*!< I2C control register 1 */ +#define I2C_SADDR0(i2cx) REG32((i2cx) + 0x08U) /*!< I2C slave address register 0*/ +#define I2C_SADDR1(i2cx) REG32((i2cx) + 0x0CU) /*!< I2C slave address register */ +#define I2C_DATA(i2cx) REG32((i2cx) + 0x10U) /*!< I2C transfer buffer register */ +#define I2C_STAT0(i2cx) REG32((i2cx) + 0x14U) /*!< I2C transfer status register 0 */ +#define I2C_STAT1(i2cx) REG32((i2cx) + 0x18U) /*!< I2C transfer status register */ +#define I2C_CKCFG(i2cx) REG32((i2cx) + 0x1CU) /*!< I2C clock configure register */ +#define I2C_RT(i2cx) REG32((i2cx) + 0x20U) /*!< I2C rise time register */ + +/* bits definitions */ +/* I2Cx_CTL0 */ +#define I2C_CTL0_I2CEN BIT(0) /*!< peripheral enable */ +#define I2C_CTL0_SMBEN BIT(1) /*!< SMBus mode */ +#define I2C_CTL0_SMBSEL BIT(3) /*!< SMBus type */ +#define I2C_CTL0_ARPEN BIT(4) /*!< ARP enable */ +#define I2C_CTL0_PECEN BIT(5) /*!< PEC enable */ +#define I2C_CTL0_GCEN BIT(6) /*!< general call enable */ +#define I2C_CTL0_DISSTRC BIT(7) /*!< clock stretching disable (slave mode) */ +#define I2C_CTL0_START BIT(8) /*!< start generation */ +#define I2C_CTL0_STOP BIT(9) /*!< stop generation */ +#define I2C_CTL0_ACKEN BIT(10) /*!< acknowledge enable */ +#define I2C_CTL0_POAP BIT(11) /*!< acknowledge/PEC position (for data reception) */ +#define I2C_CTL0_PECTRANS BIT(12) /*!< packet error checking */ +#define I2C_CTL0_SALT BIT(13) /*!< SMBus alert */ +#define I2C_CTL0_SRESET BIT(15) /*!< software reset */ + +/* I2Cx_CTL1 */ +#define I2C_CTL1_I2CCLK BITS(0,5) /*!< I2CCLK[5:0] bits (peripheral clock frequency) */ +#define I2C_CTL1_ERRIE BIT(8) /*!< error interrupt enable */ +#define I2C_CTL1_EVIE BIT(9) /*!< event interrupt enable */ +#define I2C_CTL1_BUFIE BIT(10) /*!< buffer interrupt enable */ +#define I2C_CTL1_DMAON BIT(11) /*!< DMA requests enable */ +#define I2C_CTL1_DMALST BIT(12) /*!< DMA last transfer */ + +/* I2Cx_SADDR0 */ +#define I2C_SADDR0_ADDRESS0 BIT(0) /*!< bit 0 of a 10-bit address */ +#define I2C_SADDR0_ADDRESS BITS(1,7) /*!< 7-bit address or bits 7:1 of a 10-bit address */ +#define I2C_SADDR0_ADDRESS_H BITS(8,9) /*!< highest two bits of a 10-bit address */ +#define I2C_SADDR0_ADDFORMAT BIT(15) /*!< address mode for the I2C slave */ + +/* I2Cx_SADDR1 */ +#define I2C_SADDR1_DUADEN BIT(0) /*!< aual-address mode switch */ +#define I2C_SADDR1_ADDRESS2 BITS(1,7) /*!< second I2C address for the slave in dual-address mode */ + +/* I2Cx_DATA */ +#define I2C_DATA_TRB BITS(0,7) /*!< 8-bit data register */ + +/* I2Cx_STAT0 */ +#define I2C_STAT0_SBSEND BIT(0) /*!< start bit (master mode) */ +#define I2C_STAT0_ADDSEND BIT(1) /*!< address sent (master mode)/matched (slave mode) */ +#define I2C_STAT0_BTC BIT(2) /*!< byte transfer finished */ +#define I2C_STAT0_ADD10SEND BIT(3) /*!< 10-bit header sent (master mode) */ +#define I2C_STAT0_STPDET BIT(4) /*!< stop detection (slave mode) */ +#define I2C_STAT0_RBNE BIT(6) /*!< data register not empty (receivers) */ +#define I2C_STAT0_TBE BIT(7) /*!< data register empty (transmitters) */ +#define I2C_STAT0_BERR BIT(8) /*!< bus error */ +#define I2C_STAT0_LOSTARB BIT(9) /*!< arbitration lost (master mode) */ +#define I2C_STAT0_AERR BIT(10) /*!< acknowledge failure */ +#define I2C_STAT0_OUERR BIT(11) /*!< overrun/underrun */ +#define I2C_STAT0_PECERR BIT(12) /*!< PEC error in reception */ +#define I2C_STAT0_SMBTO BIT(14) /*!< timeout signal in SMBus mode */ +#define I2C_STAT0_SMBALT BIT(15) /*!< SMBus alert status */ + +/* I2Cx_STAT1 */ +#define I2C_STAT1_MASTER BIT(0) /*!< master/slave */ +#define I2C_STAT1_I2CBSY BIT(1) /*!< bus busy */ +#define I2C_STAT1_TRS BIT(2) /*!< transmitter/receiver */ +#define I2C_STAT1_RXGC BIT(4) /*!< general call address (slave mode) */ +#define I2C_STAT1_DEFSMB BIT(5) /*!< SMBus device default address (slave mode) */ +#define I2C_STAT1_HSTSMB BIT(6) /*!< SMBus host header (slave mode) */ +#define I2C_STAT1_DUMODF BIT(7) /*!< dual flag (slave mode) */ +#define I2C_STAT1_ECV BITS(8,15) /*!< packet error checking register */ + +/* I2Cx_CKCFG */ +#define I2C_CKCFG_CLKC BITS(0,11) /*!< clock control register in fast/standard mode (master mode) */ +#define I2C_CKCFG_DTCY BIT(14) /*!< fast mode duty cycle */ +#define I2C_CKCFG_FAST BIT(15) /*!< I2C speed selection in master mode */ + +/* I2Cx_RT */ +#define I2C_RT_RISETIME BITS(0,5) /*!< maximum rise time in fast/standard mode (Master mode) */ + +/* constants definitions */ +/* define the I2C bit position and its register index offset */ +#define I2C_REGIDX_BIT(regidx, bitpos) (((uint32_t)(regidx) << 6) | (uint32_t)(bitpos)) +#define I2C_REG_VAL(i2cx, offset) (REG32((i2cx) + (((uint32_t)(offset) & 0xFFFFU) >> 6))) +#define I2C_BIT_POS(val) ((uint32_t)(val) & 0x1FU) +#define I2C_REGIDX_BIT2(regidx, bitpos, regidx2, bitpos2) (((uint32_t)(regidx2) << 22) | (uint32_t)((bitpos2) << 16)\ + | (((uint32_t)(regidx) << 6) | (uint32_t)(bitpos))) +#define I2C_REG_VAL2(i2cx, offset) (REG32((i2cx) + ((uint32_t)(offset) >> 22))) +#define I2C_BIT_POS2(val) (((uint32_t)(val) & 0x1F0000U) >> 16) + +/* register offset */ +#define I2C_CTL1_REG_OFFSET 0x04U /*!< CTL1 register offset */ +#define I2C_STAT0_REG_OFFSET 0x14U /*!< STAT0 register offset */ +#define I2C_STAT1_REG_OFFSET 0x18U /*!< STAT1 register offset */ +#define I2C_SAMCS_REG_OFFSET 0x80U /*!< SAMCS register offset */ + +/* I2C flags */ +typedef enum +{ + /* flags in STAT0 register */ + I2C_FLAG_SBSEND = I2C_REGIDX_BIT(I2C_STAT0_REG_OFFSET, 0U), /*!< start condition sent out in master mode */ + I2C_FLAG_ADDSEND = I2C_REGIDX_BIT(I2C_STAT0_REG_OFFSET, 1U), /*!< address is sent in master mode or received and matches in slave mode */ + I2C_FLAG_BTC = I2C_REGIDX_BIT(I2C_STAT0_REG_OFFSET, 2U), /*!< byte transmission finishes */ + I2C_FLAG_ADD10SEND = I2C_REGIDX_BIT(I2C_STAT0_REG_OFFSET, 3U), /*!< header of 10-bit address is sent in master mode */ + I2C_FLAG_STPDET = I2C_REGIDX_BIT(I2C_STAT0_REG_OFFSET, 4U), /*!< stop condition detected in slave mode */ + I2C_FLAG_RBNE = I2C_REGIDX_BIT(I2C_STAT0_REG_OFFSET, 6U), /*!< I2C_DATA is not Empty during receiving */ + I2C_FLAG_TBE = I2C_REGIDX_BIT(I2C_STAT0_REG_OFFSET, 7U), /*!< I2C_DATA is empty during transmitting */ + I2C_FLAG_BERR = I2C_REGIDX_BIT(I2C_STAT0_REG_OFFSET, 8U), /*!< a bus error occurs indication a unexpected start or stop condition on I2C bus */ + I2C_FLAG_LOSTARB = I2C_REGIDX_BIT(I2C_STAT0_REG_OFFSET, 9U), /*!< arbitration lost in master mode */ + I2C_FLAG_AERR = I2C_REGIDX_BIT(I2C_STAT0_REG_OFFSET, 10U), /*!< acknowledge error */ + I2C_FLAG_OUERR = I2C_REGIDX_BIT(I2C_STAT0_REG_OFFSET, 11U), /*!< over-run or under-run situation occurs in slave mode */ + I2C_FLAG_PECERR = I2C_REGIDX_BIT(I2C_STAT0_REG_OFFSET, 12U), /*!< PEC error when receiving data */ + I2C_FLAG_SMBTO = I2C_REGIDX_BIT(I2C_STAT0_REG_OFFSET, 14U), /*!< timeout signal in SMBus mode */ + I2C_FLAG_SMBALT = I2C_REGIDX_BIT(I2C_STAT0_REG_OFFSET, 15U), /*!< SMBus alert status */ + /* flags in STAT1 register */ + I2C_FLAG_MASTER = I2C_REGIDX_BIT(I2C_STAT1_REG_OFFSET, 0U), /*!< a flag indicating whether I2C block is in master or slave mode */ + I2C_FLAG_I2CBSY = I2C_REGIDX_BIT(I2C_STAT1_REG_OFFSET, 1U), /*!< busy flag */ + I2C_FLAG_TRS = I2C_REGIDX_BIT(I2C_STAT1_REG_OFFSET, 2U), /*!< whether the I2C is a transmitter or a receiver */ + I2C_FLAG_RXGC = I2C_REGIDX_BIT(I2C_STAT1_REG_OFFSET, 4U), /*!< general call address (00h) received */ + I2C_FLAG_DEFSMB = I2C_REGIDX_BIT(I2C_STAT1_REG_OFFSET, 5U), /*!< default address of SMBus device */ + I2C_FLAG_HSTSMB = I2C_REGIDX_BIT(I2C_STAT1_REG_OFFSET, 6U), /*!< SMBus host header detected in slave mode */ + I2C_FLAG_DUMOD = I2C_REGIDX_BIT(I2C_STAT1_REG_OFFSET, 7U) /*!< dual flag in slave mode indicating which address is matched in dual-address mode */ +}i2c_flag_enum; + +/* I2C interrupt flags */ +typedef enum +{ + /* interrupt flags in CTL1 register */ + I2C_INT_FLAG_SBSEND = I2C_REGIDX_BIT2(I2C_CTL1_REG_OFFSET, 9U, I2C_STAT0_REG_OFFSET, 0U), /*!< start condition sent out in master mode interrupt flag */ + I2C_INT_FLAG_ADDSEND = I2C_REGIDX_BIT2(I2C_CTL1_REG_OFFSET, 9U, I2C_STAT0_REG_OFFSET, 1U), /*!< address is sent in master mode or received and matches in slave mode interrupt flag */ + I2C_INT_FLAG_BTC = I2C_REGIDX_BIT2(I2C_CTL1_REG_OFFSET, 9U, I2C_STAT0_REG_OFFSET, 2U), /*!< byte transmission finishes */ + I2C_INT_FLAG_ADD10SEND = I2C_REGIDX_BIT2(I2C_CTL1_REG_OFFSET, 9U, I2C_STAT0_REG_OFFSET, 3U), /*!< header of 10-bit address is sent in master mode interrupt flag */ + I2C_INT_FLAG_STPDET = I2C_REGIDX_BIT2(I2C_CTL1_REG_OFFSET, 9U, I2C_STAT0_REG_OFFSET, 4U), /*!< stop condition detected in slave mode interrupt flag */ + I2C_INT_FLAG_RBNE = I2C_REGIDX_BIT2(I2C_CTL1_REG_OFFSET, 9U, I2C_STAT0_REG_OFFSET, 6U), /*!< I2C_DATA is not Empty during receiving interrupt flag */ + I2C_INT_FLAG_TBE = I2C_REGIDX_BIT2(I2C_CTL1_REG_OFFSET, 9U, I2C_STAT0_REG_OFFSET, 7U), /*!< I2C_DATA is empty during transmitting interrupt flag */ + I2C_INT_FLAG_BERR = I2C_REGIDX_BIT2(I2C_CTL1_REG_OFFSET, 8U, I2C_STAT0_REG_OFFSET, 8U), /*!< a bus error occurs indication a unexpected start or stop condition on I2C bus interrupt flag */ + I2C_INT_FLAG_LOSTARB = I2C_REGIDX_BIT2(I2C_CTL1_REG_OFFSET, 8U, I2C_STAT0_REG_OFFSET, 9U), /*!< arbitration lost in master mode interrupt flag */ + I2C_INT_FLAG_AERR = I2C_REGIDX_BIT2(I2C_CTL1_REG_OFFSET, 8U, I2C_STAT0_REG_OFFSET, 10U), /*!< acknowledge error interrupt flag */ + I2C_INT_FLAG_OUERR = I2C_REGIDX_BIT2(I2C_CTL1_REG_OFFSET, 8U, I2C_STAT0_REG_OFFSET, 11U), /*!< over-run or under-run situation occurs in slave mode interrupt flag */ + I2C_INT_FLAG_PECERR = I2C_REGIDX_BIT2(I2C_CTL1_REG_OFFSET, 8U, I2C_STAT0_REG_OFFSET, 12U), /*!< PEC error when receiving data interrupt flag */ + I2C_INT_FLAG_SMBTO = I2C_REGIDX_BIT2(I2C_CTL1_REG_OFFSET, 8U, I2C_STAT0_REG_OFFSET, 14U), /*!< timeout signal in SMBus mode interrupt flag */ + I2C_INT_FLAG_SMBALT = I2C_REGIDX_BIT2(I2C_CTL1_REG_OFFSET, 8U, I2C_STAT0_REG_OFFSET, 15U), /*!< SMBus Alert status interrupt flag */ +}i2c_interrupt_flag_enum; + +/* I2C interrupt enable or disable */ +typedef enum +{ + /* interrupt in CTL1 register */ + I2C_INT_ERR = I2C_REGIDX_BIT(I2C_CTL1_REG_OFFSET, 8U), /*!< error interrupt enable */ + I2C_INT_EV = I2C_REGIDX_BIT(I2C_CTL1_REG_OFFSET, 9U), /*!< event interrupt enable */ + I2C_INT_BUF = I2C_REGIDX_BIT(I2C_CTL1_REG_OFFSET, 10U), /*!< buffer interrupt enable */ +}i2c_interrupt_enum; + +/* SMBus/I2C mode switch and SMBus type selection */ +#define I2C_I2CMODE_ENABLE ((uint32_t)0x00000000U) /*!< I2C mode */ +#define I2C_SMBUSMODE_ENABLE I2C_CTL0_SMBEN /*!< SMBus mode */ + +/* SMBus/I2C mode switch and SMBus type selection */ +#define I2C_SMBUS_DEVICE ((uint32_t)0x00000000U) /*!< SMBus mode device type */ +#define I2C_SMBUS_HOST I2C_CTL0_SMBSEL /*!< SMBus mode host type */ + +/* I2C transfer direction */ +#define I2C_RECEIVER ((uint32_t)0x00000001U) /*!< receiver */ +#define I2C_TRANSMITTER ((uint32_t)0xFFFFFFFEU) /*!< transmitter */ + +/* whether or not to send an ACK */ +#define I2C_ACK_DISABLE ((uint32_t)0x00000000U) /*!< ACK will be not sent */ +#define I2C_ACK_ENABLE ((uint32_t)0x00000001U) /*!< ACK will be sent */ + +/* I2C POAP position*/ +#define I2C_ACKPOS_NEXT ((uint32_t)0x00000000U) /*!< ACKEN bit decides whether or not to send ACK for the next byte */ +#define I2C_ACKPOS_CURRENT ((uint32_t)0x00000001U) /*!< ACKEN bit decides whether or not to send ACK or not for the current byte */ + +/* I2C dual-address mode switch */ +#define I2C_DUADEN_DISABLE ((uint32_t)0x00000000U) /*!< dual-address mode disabled */ +#define I2C_DUADEN_ENABLE ((uint32_t)0x00000001U) /*!< dual-address mode enabled */ + +/* whether or not to stretch SCL low */ +#define I2C_SCLSTRETCH_DISABLE ((uint32_t)0x00000000U) /*!< SCL stretching is disabled */ +#define I2C_SCLSTRETCH_ENABLE I2C_CTL0_DISSTRC /*!< SCL stretching is enabled */ + +/* whether or not to response to a general call */ +#define I2C_GCEN_ENABLE I2C_CTL0_GCEN /*!< slave will response to a general call */ +#define I2C_GCEN_DISABLE ((uint32_t)0x00000000U) /*!< slave will not response to a general call */ + +/* software reset I2C */ +#define I2C_SRESET_SET I2C_CTL0_SRESET /*!< I2C is under reset */ +#define I2C_SRESET_RESET ((uint32_t)0x00000000U) /*!< I2C is not under reset */ + +/* I2C DMA mode configure */ +/* DMA mode switch */ +#define I2C_DMA_ON I2C_CTL1_DMAON /*!< DMA mode enabled */ +#define I2C_DMA_OFF ((uint32_t)0x00000000U) /*!< DMA mode disabled */ + +/* flag indicating DMA last transfer */ +#define I2C_DMALST_ON I2C_CTL1_DMALST /*!< next DMA EOT is the last transfer */ +#define I2C_DMALST_OFF ((uint32_t)0x00000000U) /*!< next DMA EOT is not the last transfer */ + +/* I2C PEC configure */ +/* PEC enable */ +#define I2C_PEC_ENABLE I2C_CTL0_PECEN /*!< PEC calculation on */ +#define I2C_PEC_DISABLE ((uint32_t)0x00000000U) /*!< PEC calculation off */ + +/* PEC transfer */ +#define I2C_PECTRANS_ENABLE I2C_CTL0_PECTRANS /*!< transfer PEC */ +#define I2C_PECTRANS_DISABLE ((uint32_t)0x00000000U) /*!< not transfer PEC value */ + +/* I2C SMBus configure */ +/* issue or not alert through SMBA pin */ +#define I2C_SALTSEND_ENABLE I2C_CTL0_SALT /*!< issue alert through SMBA pin */ +#define I2C_SALTSEND_DISABLE ((uint32_t)0x00000000U) /*!< not issue alert through SMBA */ + +/* ARP protocol in SMBus switch */ +#define I2C_ARP_ENABLE I2C_CTL0_ARPEN /*!< ARP is enabled */ +#define I2C_ARP_DISABLE ((uint32_t)0x00000000U) /*!< ARP is disabled */ + +/* transmit I2C data */ +#define DATA_TRANS(regval) (BITS(0,7) & ((uint32_t)(regval) << 0)) + +/* receive I2C data */ +#define DATA_RECV(regval) GET_BITS((uint32_t)(regval), 0, 7) + +/* I2C duty cycle in fast mode */ +#define I2C_DTCY_2 ((uint32_t)0x00000000U) /*!< I2C fast mode Tlow/Thigh = 2 */ +#define I2C_DTCY_16_9 I2C_CKCFG_DTCY /*!< I2C fast mode Tlow/Thigh = 16/9 */ + +/* address mode for the I2C slave */ +#define I2C_ADDFORMAT_7BITS ((uint32_t)0x00000000U) /*!< address:7 bits */ +#define I2C_ADDFORMAT_10BITS I2C_SADDR0_ADDFORMAT /*!< address:10 bits */ + +/* function declarations */ +/* initialization functions */ +/* reset I2C */ +void i2c_deinit(uint32_t i2c_periph); +/* configure I2C clock */ +void i2c_clock_config(uint32_t i2c_periph, uint32_t clkspeed, uint32_t dutycyc); +/* configure I2C address */ +void i2c_mode_addr_config(uint32_t i2c_periph, uint32_t mode, uint32_t addformat, uint32_t addr); +/* SMBus type selection */ +void i2c_smbus_type_config(uint32_t i2c_periph, uint32_t type); +/* whether or not to send an ACK */ +void i2c_ack_config(uint32_t i2c_periph, uint32_t ack); +/* configure I2C POAP position */ +void i2c_ackpos_config(uint32_t i2c_periph, uint32_t pos); +/* master sends slave address */ +void i2c_master_addressing(uint32_t i2c_periph, uint32_t addr, uint32_t trandirection); +/* enable dual-address mode */ +void i2c_dualaddr_enable(uint32_t i2c_periph, uint32_t addr); +/* disable dual-address mode */ +void i2c_dualaddr_disable(uint32_t i2c_periph); + +/* function configuration */ +/* enable I2C */ +void i2c_enable(uint32_t i2c_periph); +/* disable I2C */ +void i2c_disable(uint32_t i2c_periph); +/* generate a START condition on I2C bus */ +void i2c_start_on_bus(uint32_t i2c_periph); +/* generate a STOP condition on I2C bus */ +void i2c_stop_on_bus(uint32_t i2c_periph); +/* I2C transmit data function */ +void i2c_data_transmit(uint32_t i2c_periph, uint8_t data); +/* I2C receive data function */ +uint8_t i2c_data_receive(uint32_t i2c_periph); +/* enable I2C DMA mode */ +void i2c_dma_enable(uint32_t i2c_periph, uint32_t dmastate); +/* configure whether next DMA EOT is DMA last transfer or not */ +void i2c_dma_last_transfer_config(uint32_t i2c_periph, uint32_t dmalast); +/* whether to stretch SCL low when data is not ready in slave mode */ +void i2c_stretch_scl_low_config(uint32_t i2c_periph, uint32_t stretchpara); +/* whether or not to response to a general call */ +void i2c_slave_response_to_gcall_config(uint32_t i2c_periph, uint32_t gcallpara); +/* software reset I2C */ +void i2c_software_reset_config(uint32_t i2c_periph, uint32_t sreset); + +/* I2C PEC calculation on or off */ +void i2c_pec_enable(uint32_t i2c_periph, uint32_t pecstate); +/* I2C whether to transfer PEC value */ +void i2c_pec_transfer_enable(uint32_t i2c_periph, uint32_t pecpara); +/* packet error checking value */ +uint8_t i2c_pec_value_get(uint32_t i2c_periph); +/* I2C issue alert through SMBA pin */ +void i2c_smbus_issue_alert(uint32_t i2c_periph, uint32_t smbuspara); +/* I2C ARP protocol in SMBus switch */ +void i2c_smbus_arp_enable(uint32_t i2c_periph, uint32_t arpstate); + +/* interrupt & flag functions */ +/* check I2C flag is set or not */ +FlagStatus i2c_flag_get(uint32_t i2c_periph, i2c_flag_enum flag); +/* clear I2C flag */ +void i2c_flag_clear(uint32_t i2c_periph, i2c_flag_enum flag); +/* enable I2C interrupt */ +void i2c_interrupt_enable(uint32_t i2c_periph, i2c_interrupt_enum interrupt); +/* disable I2C interrupt */ +void i2c_interrupt_disable(uint32_t i2c_periph, i2c_interrupt_enum interrupt); +/* check I2C interrupt flag */ +FlagStatus i2c_interrupt_flag_get(uint32_t i2c_periph, i2c_interrupt_flag_enum int_flag); +/* clear I2C interrupt flag */ +void i2c_interrupt_flag_clear(uint32_t i2c_periph, i2c_interrupt_flag_enum int_flag); + +#endif /* GD32F20X_I2C_H */ diff --git a/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_standard_peripheral/Include/gd32f20x_misc.h b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_standard_peripheral/Include/gd32f20x_misc.h new file mode 100644 index 0000000000..98b68d5189 --- /dev/null +++ b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_standard_peripheral/Include/gd32f20x_misc.h @@ -0,0 +1,96 @@ +/*! + \file gd32f20x_misc.h + \brief definitions for the MISC + + \version 2015-07-15, V1.0.0, firmware for GD32F20x + \version 2017-06-05, V2.0.0, firmware for GD32F20x + \version 2018-10-31, V2.1.0, firmware for GD32F20x + \version 2020-09-30, V2.2.0, firmware for GD32F20x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef GD32F20X_MISC_H +#define GD32F20X_MISC_H + +#include "gd32f20x.h" + +/* constants definitions */ +/* set the RAM and FLASH base address */ +#define NVIC_VECTTAB_RAM ((uint32_t)0x20000000) /*!< RAM base address */ +#define NVIC_VECTTAB_FLASH ((uint32_t)0x08000000) /*!< Flash base address */ + +/* set the NVIC vector table offset mask */ +#define NVIC_VECTTAB_OFFSET_MASK ((uint32_t)0x1FFFFF80) /*!< NVIC vector table offset mask */ + +/* the register key mask, if you want to do the write operation, you should write 0x5FA to VECTKEY bits */ +#define NVIC_AIRCR_VECTKEY_MASK ((uint32_t)0x05FA0000) /*!< NVIC VECTKEY mask */ + +/* priority group - define the pre-emption priority and the subpriority */ +#define NVIC_PRIGROUP_PRE0_SUB4 ((uint32_t)0x700) /*!< 0 bits for pre-emption priority 4 bits for subpriority */ +#define NVIC_PRIGROUP_PRE1_SUB3 ((uint32_t)0x600) /*!< 1 bits for pre-emption priority 3 bits for subpriority */ +#define NVIC_PRIGROUP_PRE2_SUB2 ((uint32_t)0x500) /*!< 2 bits for pre-emption priority 2 bits for subpriority */ +#define NVIC_PRIGROUP_PRE3_SUB1 ((uint32_t)0x400) /*!< 3 bits for pre-emption priority 1 bits for subpriority */ +#define NVIC_PRIGROUP_PRE4_SUB0 ((uint32_t)0x300) /*!< 4 bits for pre-emption priority 0 bits for subpriority */ + +/* choose the method to enter or exit the lowpower mode */ +#define SCB_SCR_SLEEPONEXIT ((uint8_t)0x02) /*!< choose the the system whether enter low power mode by exiting from ISR */ +#define SCB_SCR_SLEEPDEEP ((uint8_t)0x04) /*!< choose the the system enter the DEEPSLEEP mode or SLEEP mode */ +#define SCB_SCR_SEVONPEND ((uint8_t)0x10) /*!< choose the interrupt source that can wake up the lowpower mode */ + +#define SCB_LPM_SLEEP_EXIT_ISR SCB_SCR_SLEEPONEXIT /*!< low power mode by exiting from ISR */ +#define SCB_LPM_DEEPSLEEP SCB_SCR_SLEEPDEEP /*!< DEEPSLEEP mode or SLEEP mode */ +#define SCB_LPM_WAKE_BY_ALL_INT SCB_SCR_SEVONPEND /*!< wakeup by all interrupt */ + +/* choose the systick clock source */ +#define SYSTICK_CLKSOURCE_HCLK_DIV8 ((uint32_t)0xFFFFFFFBU) /*!< systick clock source is from HCLK/8 */ +#define SYSTICK_CLKSOURCE_HCLK ((uint32_t)0x00000004U) /*!< systick clock source is from HCLK */ + +/* function declarations */ +/* function configuration */ +/* set the priority group */ +void nvic_priority_group_set(uint32_t nvic_prigroup); + +/* enable NVIC request */ +void nvic_irq_enable(uint8_t nvic_irq, uint8_t nvic_irq_pre_priority, uint8_t nvic_irq_sub_priority); +/* disable NVIC request */ +void nvic_irq_disable(uint8_t nvic_irq); + +/* set the NVIC vector table base address */ +void nvic_vector_table_set(uint32_t nvic_vict_tab, uint32_t offset); + +/* set the state of the low power mode */ +void system_lowpower_set(uint8_t lowpower_mode); +/* reset the state of the low power mode */ +void system_lowpower_reset(uint8_t lowpower_mode); + +/* set the systick clock source */ +void systick_clksource_set(uint32_t systick_clksource); + +#endif /* GD32F20X_MISC_H */ + diff --git a/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_standard_peripheral/Include/gd32f20x_pmu.h b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_standard_peripheral/Include/gd32f20x_pmu.h new file mode 100644 index 0000000000..9bb936a424 --- /dev/null +++ b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_standard_peripheral/Include/gd32f20x_pmu.h @@ -0,0 +1,129 @@ +/*! + \file gd32f20x_pmu.h + \brief definitions for the PMU + + \version 2015-07-15, V1.0.0, firmware for GD32F20x + \version 2017-06-05, V2.0.0, firmware for GD32F20x + \version 2018-10-31, V2.1.0, firmware for GD32F20x + \version 2020-09-30, V2.2.0, firmware for GD32F20x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef GD32F20X_PMU_H +#define GD32F20X_PMU_H + +#include "gd32f20x.h" + +/* PMU definitions */ +#define PMU PMU_BASE /*!< PMU base address */ + +/* registers definitions */ +#define PMU_CTL REG32((PMU) + 0x00U) /*!< PMU control register */ +#define PMU_CS REG32((PMU) + 0x04U) /*!< PMU control and status register */ + +/* bits definitions */ +/* PMU_CTL */ +#define PMU_CTL_LDOLP BIT(0) /*!< LDO low power mode */ +#define PMU_CTL_STBMOD BIT(1) /*!< standby mode */ +#define PMU_CTL_WURST BIT(2) /*!< wakeup flag reset */ +#define PMU_CTL_STBRST BIT(3) /*!< standby flag reset */ +#define PMU_CTL_LVDEN BIT(4) /*!< low voltage detector enable */ +#define PMU_CTL_LVDT BITS(5,7) /*!< low voltage detector threshold */ +#define PMU_CTL_BKPWEN BIT(8) /*!< backup domain write enable */ + +/* PMU_CS */ +#define PMU_CS_WUF BIT(0) /*!< wakeup flag */ +#define PMU_CS_STBF BIT(1) /*!< standby flag */ +#define PMU_CS_LVDF BIT(2) /*!< low voltage detector status flag */ +#define PMU_CS_WUPEN BIT(8) /*!< wakeup pin enable */ + +/* constants definitions */ +/* PMU low voltage detector threshold definitions */ +#define CTL_LVDT(regval) (BITS(5,7)&((uint32_t)(regval) << 5)) +#define PMU_LVDT_0 CTL_LVDT(0) /*!< voltage threshold is 2.2V */ +#define PMU_LVDT_1 CTL_LVDT(1) /*!< voltage threshold is 2.3V */ +#define PMU_LVDT_2 CTL_LVDT(2) /*!< voltage threshold is 2.4V */ +#define PMU_LVDT_3 CTL_LVDT(3) /*!< voltage threshold is 2.5V */ +#define PMU_LVDT_4 CTL_LVDT(4) /*!< voltage threshold is 2.6V */ +#define PMU_LVDT_5 CTL_LVDT(5) /*!< voltage threshold is 2.7V */ +#define PMU_LVDT_6 CTL_LVDT(6) /*!< voltage threshold is 2.8V */ +#define PMU_LVDT_7 CTL_LVDT(7) /*!< voltage threshold is 2.9V */ + +/* PMU flag definitions */ +#define PMU_FLAG_WAKEUP PMU_CS_WUF /*!< wakeup flag status */ +#define PMU_FLAG_STANDBY PMU_CS_STBF /*!< standby flag status */ +#define PMU_FLAG_LVD PMU_CS_LVDF /*!< lvd flag status */ + +/* PMU ldo definitions */ +#define PMU_LDO_NORMAL ((uint32_t)0x00000000U) /*!< LDO normal work when PMU enter deepsleep mode */ +#define PMU_LDO_LOWPOWER PMU_CTL_LDOLP /*!< LDO work at low power status when PMU enter deepsleep mode */ + +/* PMU flag reset definitions */ +#define PMU_FLAG_RESET_WAKEUP ((uint8_t)0x00U) /*!< wakeup flag reset */ +#define PMU_FLAG_RESET_STANDBY ((uint8_t)0x01U) /*!< standby flag reset */ + +/* PMU command constants definitions */ +#define WFI_CMD ((uint8_t)0x00U) /*!< use WFI command */ +#define WFE_CMD ((uint8_t)0x01U) /*!< use WFE command */ + +/* function declarations */ +/* initialization functions */ +/* reset PMU registers */ +void pmu_deinit(void); + +/* select low voltage detector threshold */ +void pmu_lvd_select(uint32_t lvdt_n); +/* disable PMU lvd */ +void pmu_lvd_disable(void); + +/* set PMU mode */ +/* PMU work at sleep mode */ +void pmu_to_sleepmode(uint8_t sleepmodecmd); +/* PMU work at deepsleep mode */ +void pmu_to_deepsleepmode(uint32_t ldo, uint8_t deepsleepmodecmd); +/* PMU work at standby mode */ +void pmu_to_standbymode(uint8_t standbymodecmd); +/* enable PMU wakeup pin */ +void pmu_wakeup_pin_enable(void); +/* disable PMU wakeup pin */ +void pmu_wakeup_pin_disable(void); + +/* backup related functions */ +/* enable write access to the registers in backup domain */ +void pmu_backup_write_enable(void); +/* disable write access to the registers in backup domain */ +void pmu_backup_write_disable(void); + +/* flag functions */ +/* get flag state */ +FlagStatus pmu_flag_get(uint32_t flag); +/* clear flag bit */ +void pmu_flag_clear(uint32_t flag_reset); + +#endif /* GD32F20X_PMU_H */ diff --git a/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_standard_peripheral/Include/gd32f20x_rcu.h b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_standard_peripheral/Include/gd32f20x_rcu.h new file mode 100644 index 0000000000..d95a78bcfe --- /dev/null +++ b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_standard_peripheral/Include/gd32f20x_rcu.h @@ -0,0 +1,1086 @@ +/*! + \file gd32f20x_rcu.h + \brief definitions for the RCU + + \version 2015-07-15, V1.0.0, firmware for GD32F20x + \version 2017-06-05, V2.0.0, firmware for GD32F20x + \version 2018-10-31, V2.1.0, firmware for GD32F20x + \version 2020-09-30, V2.2.0, firmware for GD32F20x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef GD32F20X_RCU_H +#define GD32F20X_RCU_H + +#include "gd32f20x.h" + +/* RCU definitions */ +#define RCU RCU_BASE + +/* registers definitions */ +#define RCU_CTL REG32(RCU + 0x00U) /*!< control register */ +#define RCU_CFG0 REG32(RCU + 0x04U) /*!< clock configuration register 0 */ +#define RCU_INT REG32(RCU + 0x08U) /*!< clock interrupt register */ +#define RCU_APB2RST REG32(RCU + 0x0CU) /*!< APB2 reset register */ +#define RCU_APB1RST REG32(RCU + 0x10U) /*!< APB1 reset register */ +#define RCU_AHB1EN REG32(RCU + 0x14U) /*!< AHB1 enable register */ +#define RCU_APB2EN REG32(RCU + 0x18U) /*!< APB2 enable register */ +#define RCU_APB1EN REG32(RCU + 0x1CU) /*!< APB1 enable register */ +#define RCU_BDCTL REG32(RCU + 0x20U) /*!< backup domain control register */ +#define RCU_RSTSCK REG32(RCU + 0x24U) /*!< reset source / clock register */ +#define RCU_AHB1RST REG32(RCU + 0x28U) /*!< AHB1 reset register */ +#define RCU_CFG1 REG32(RCU + 0x2CU) /*!< configuration register 1 */ +#define RCU_DSV REG32(RCU + 0x34U) /*!< deep-sleep mode voltage register */ +#define RCU_AHB2EN REG32(RCU + 0x60U) /*!< AHB2 enable register */ +#define RCU_ADDAPB2EN REG32(RCU + 0x64U) /*!< APB2 additional enable register */ +#define RCU_ADDAPB1EN REG32(RCU + 0x68U) /*!< APB1 additional enable register */ +#define RCU_AHB2RST REG32(RCU + 0x70U) /*!< AHB2 reset register */ +#define RCU_ADDAPB2RST REG32(RCU + 0x74U) /*!< APB2 additional reset register */ +#define RCU_ADDAPB1RST REG32(RCU + 0x78U) /*!< APB1 additional reset register */ +#define RCU_CFG2 REG32(RCU + 0x80U) /*!< configuration register 2 */ +#define RCU_PLLTCTL REG32(RCU + 0x90U) /*!< PLLT control register */ +#define RCU_PLLTINT REG32(RCU + 0x94U) /*!< PLLT interrupt register */ +#define RCU_PLLTCFG REG32(RCU + 0x98U) /*!< PLLT configuration register */ + +/* bits definitions */ +/* RCU_CTL */ +#define RCU_CTL_IRC8MEN BIT(0) /*!< internal high speed oscillator enable */ +#define RCU_CTL_IRC8MSTB BIT(1) /*!< IRC8M high speed internal oscillator stabilization flag */ +#define RCU_CTL_IRC8MADJ BITS(3,7) /*!< high speed internal oscillator clock trim adjust value */ +#define RCU_CTL_IRC8MCALIB BITS(8,15) /*!< high speed internal oscillator calibration value register */ +#define RCU_CTL_HXTALEN BIT(16) /*!< external high speed oscillator enable */ +#define RCU_CTL_HXTALSTB BIT(17) /*!< external crystal oscillator clock stabilization flag */ +#define RCU_CTL_HXTALBPS BIT(18) /*!< external crystal oscillator clock bypass mode enable */ +#define RCU_CTL_CKMEN BIT(19) /*!< HXTAL clock monitor enable */ +#define RCU_CTL_PLLEN BIT(24) /*!< PLL enable */ +#define RCU_CTL_PLLSTB BIT(25) /*!< PLL clock stabilization flag */ +#define RCU_CTL_PLL1EN BIT(26) /*!< PLL1 enable */ +#define RCU_CTL_PLL1STB BIT(27) /*!< PLL1 clock stabilization flag */ +#define RCU_CTL_PLL2EN BIT(28) /*!< PLL2 enable */ +#define RCU_CTL_PLL2STB BIT(29) /*!< PLL2 clock stabilization flag */ + +/* RCU_CFG0 */ +#define RCU_CFG0_SCS BITS(0,1) /*!< system clock switch */ +#define RCU_CFG0_SCSS BITS(2,3) /*!< system clock switch status */ +#define RCU_CFG0_AHBPSC BITS(4,7) /*!< AHB prescaler selection */ +#define RCU_CFG0_APB1PSC BITS(8,10) /*!< APB1 prescaler selection */ +#define RCU_CFG0_APB2PSC BITS(11,13) /*!< APB2 prescaler selection */ +#define RCU_CFG0_ADCPSC BITS(14,15) /*!< ADC prescaler selection */ +#define RCU_CFG0_PLLSEL BIT(16) /*!< PLL clock source selection */ +#define RCU_CFG0_PREDV0_LSB BIT(17) /*!< the LSB of PREDV0 division factor */ +#define RCU_CFG0_PLLMF BITS(18,21) /*!< PLL clock multiplication factor */ +#define RCU_CFG0_USBFSPSC BITS(22,23) /*!< USBFS clock prescaler selection */ +#define RCU_CFG0_CKOUT0SEL BITS(24,27) /*!< CKOUT0 clock source selection */ +#define RCU_CFG0_ADCPSC_2 BIT(28) /*!< bit 2 of ADCPSC */ +#define RCU_CFG0_PLLMF_4 BIT(29) /*!< bit 4 of PLLMF */ + +/* RCU_INT */ +#define RCU_INT_IRC40KSTBIF BIT(0) /*!< IRC40K stabilization interrupt flag */ +#define RCU_INT_LXTALSTBIF BIT(1) /*!< LXTAL stabilization interrupt flag */ +#define RCU_INT_IRC8MSTBIF BIT(2) /*!< IRC8M stabilization interrupt flag */ +#define RCU_INT_HXTALSTBIF BIT(3) /*!< HXTAL stabilization interrupt flag */ +#define RCU_INT_PLLSTBIF BIT(4) /*!< PLL stabilization interrupt flag */ +#define RCU_INT_PLL1STBIF BIT(5) /*!< PLL1 stabilization interrupt flag */ +#define RCU_INT_PLL2STBIF BIT(6) /*!< PLL2 stabilization interrupt flag */ +#define RCU_INT_CKMIF BIT(7) /*!< HXTAL clock stuck interrupt flag */ +#define RCU_INT_IRC40KSTBIE BIT(8) /*!< IRC40K stabilization interrupt enable */ +#define RCU_INT_LXTALSTBIE BIT(9) /*!< LXTAL stabilization interrupt enable */ +#define RCU_INT_IRC8MSTBIE BIT(10) /*!< IRC8M stabilization interrupt enable */ +#define RCU_INT_HXTALSTBIE BIT(11) /*!< HXTAL stabilization interrupt enable */ +#define RCU_INT_PLLSTBIE BIT(12) /*!< PLL stabilization interrupt enable */ +#define RCU_INT_PLL1STBIE BIT(13) /*!< PLL1 stabilization interrupt enable */ +#define RCU_INT_PLL2STBIE BIT(14) /*!< PLL2 stabilization interrupt enable */ +#define RCU_INT_IRC40KSTBIC BIT(16) /*!< IRC40K stabilization interrupt clear */ +#define RCU_INT_LXTALSTBIC BIT(17) /*!< LXTAL stabilization interrupt clear */ +#define RCU_INT_IRC8MSTBIC BIT(18) /*!< IRC8M stabilization interrupt clear */ +#define RCU_INT_HXTALSTBIC BIT(19) /*!< HXTAL stabilization interrupt clear */ +#define RCU_INT_PLLSTBIC BIT(20) /*!< PLL stabilization interrupt clear */ +#define RCU_INT_PLL1STBIC BIT(21) /*!< PLL1 stabilization interrupt clear */ +#define RCU_INT_PLL2STBIC BIT(22) /*!< PLL2 stabilization interrupt clear */ +#define RCU_INT_CKMIC BIT(23) /*!< HXTAL clock stuck interrupt clear */ + +/* RCU_APB2RST */ +#define RCU_APB2RST_AFRST BIT(0) /*!< alternate function I/O reset */ +#define RCU_APB2RST_PARST BIT(2) /*!< GPIO port A reset */ +#define RCU_APB2RST_PBRST BIT(3) /*!< GPIO port B reset */ +#define RCU_APB2RST_PCRST BIT(4) /*!< GPIO port C reset */ +#define RCU_APB2RST_PDRST BIT(5) /*!< GPIO port D reset */ +#define RCU_APB2RST_PERST BIT(6) /*!< GPIO port E reset */ +#define RCU_APB2RST_PFRST BIT(7) /*!< GPIO port F reset */ +#define RCU_APB2RST_PGRST BIT(8) /*!< GPIO port G reset */ +#define RCU_APB2RST_ADC0RST BIT(9) /*!< ADC0 reset */ +#define RCU_APB2RST_ADC1RST BIT(10) /*!< ADC1 reset */ +#define RCU_APB2RST_TIMER0RST BIT(11) /*!< TIMER0 reset */ +#define RCU_APB2RST_SPI0RST BIT(12) /*!< SPI0 reset */ +#define RCU_APB2RST_TIMER7RST BIT(13) /*!< TIMER7 reset */ +#define RCU_APB2RST_USART0RST BIT(14) /*!< USART0 reset */ +#define RCU_APB2RST_ADC2RST BIT(15) /*!< ADC2 reset */ +#define RCU_APB2RST_TIMER8RST BIT(19) /*!< TIMER8 reset */ +#define RCU_APB2RST_TIMER9RST BIT(20) /*!< TIMER9 reset */ +#define RCU_APB2RST_TIMER10RST BIT(21) /*!< TIMER10 reset */ + +/* RCU_APB1RST */ +#define RCU_APB1RST_TIMER1RST BIT(0) /*!< TIMER1 reset */ +#define RCU_APB1RST_TIMER2RST BIT(1) /*!< TIMER2 reset */ +#define RCU_APB1RST_TIMER3RST BIT(2) /*!< TIMER3 reset */ +#define RCU_APB1RST_TIMER4RST BIT(3) /*!< TIMER4 reset */ +#define RCU_APB1RST_TIMER5RST BIT(4) /*!< TIMER5 reset */ +#define RCU_APB1RST_TIMER6RST BIT(5) /*!< TIMER6 reset */ +#define RCU_APB1RST_TIMER11RST BIT(6) /*!< TIMER11 reset */ +#define RCU_APB1RST_TIMER12RST BIT(7) /*!< TIMER12 reset */ +#define RCU_APB1RST_TIMER13RST BIT(8) /*!< TIMER13 reset */ +#define RCU_APB1RST_WWDGTRST BIT(11) /*!< WWDGT reset */ +#define RCU_APB1RST_SPI1RST BIT(14) /*!< SPI1 reset */ +#define RCU_APB1RST_SPI2RST BIT(15) /*!< SPI2 reset */ +#define RCU_APB1RST_USART1RST BIT(17) /*!< USART1 reset */ +#define RCU_APB1RST_USART2RST BIT(18) /*!< USART2 reset */ +#define RCU_APB1RST_UART3RST BIT(19) /*!< UART3 reset */ +#define RCU_APB1RST_UART4RST BIT(20) /*!< UART4 reset */ +#define RCU_APB1RST_I2C0RST BIT(21) /*!< I2C0 reset */ +#define RCU_APB1RST_I2C1RST BIT(22) /*!< I2C1 reset */ +#define RCU_APB1RST_CAN0RST BIT(25) /*!< CAN0 reset */ +#define RCU_APB1RST_CAN1RST BIT(26) /*!< CAN1 reset */ +#define RCU_APB1RST_BKPIRST BIT(27) /*!< backup interface reset */ +#define RCU_APB1RST_PMURST BIT(28) /*!< PMU reset */ +#define RCU_APB1RST_DACRST BIT(29) /*!< DAC reset */ + +/* RCU_AHB1EN */ +#define RCU_AHB1EN_DMA0EN BIT(0) /*!< DMA0 clock enable */ +#define RCU_AHB1EN_DMA1EN BIT(1) /*!< DMA1 clock enable */ +#define RCU_AHB1EN_SRAMSPEN BIT(2) /*!< SRAM clock enable when sleep mode */ +#define RCU_AHB1EN_FMCSPEN BIT(4) /*!< FMC clock enable when sleep mode */ +#define RCU_AHB1EN_CRCEN BIT(6) /*!< CRC clock enable */ +#define RCU_AHB1EN_EXMCEN BIT(8) /*!< EXMC clock enable */ +#define RCU_AHB1EN_SDIOEN BIT(10) /*!< SDIO clock enable */ +#define RCU_AHB1EN_USBFSEN BIT(12) /*!< USBFS clock enable */ +#define RCU_AHB1EN_ENETEN BIT(14) /*!< ENET clock enable */ +#define RCU_AHB1EN_ENETTXEN BIT(15) /*!< Ethernet TX clock enable */ +#define RCU_AHB1EN_ENETRXEN BIT(16) /*!< Ethernet RX clock enable */ + +/* RCU_APB2EN */ +#define RCU_APB2EN_AFEN BIT(0) /*!< alternate function IO clock enable */ +#define RCU_APB2EN_PAEN BIT(2) /*!< GPIO port A clock enable */ +#define RCU_APB2EN_PBEN BIT(3) /*!< GPIO port B clock enable */ +#define RCU_APB2EN_PCEN BIT(4) /*!< GPIO port C clock enable */ +#define RCU_APB2EN_PDEN BIT(5) /*!< GPIO port D clock enable */ +#define RCU_APB2EN_PEEN BIT(6) /*!< GPIO port E clock enable */ +#define RCU_APB2EN_PFEN BIT(7) /*!< GPIO port F clock enable */ +#define RCU_APB2EN_PGEN BIT(8) /*!< GPIO port G clock enable */ +#define RCU_APB2EN_ADC0EN BIT(9) /*!< ADC0 clock enable */ +#define RCU_APB2EN_ADC1EN BIT(10) /*!< ADC1 clock enable */ +#define RCU_APB2EN_TIMER0EN BIT(11) /*!< TIMER0 clock enable */ +#define RCU_APB2EN_SPI0EN BIT(12) /*!< SPI0 clock enable */ +#define RCU_APB2EN_TIMER7EN BIT(13) /*!< TIMER7 clock enable */ +#define RCU_APB2EN_USART0EN BIT(14) /*!< USART0 clock enable */ +#define RCU_APB2EN_ADC2EN BIT(15) /*!< ADC2 clock enable */ +#define RCU_APB2EN_TIMER8EN BIT(19) /*!< TIMER8 clock enable */ +#define RCU_APB2EN_TIMER9EN BIT(20) /*!< TIMER9 clock enable */ +#define RCU_APB2EN_TIMER10EN BIT(21) /*!< TIMER10 clock enable */ + +/* RCU_APB1EN */ +#define RCU_APB1EN_TIMER1EN BIT(0) /*!< TIMER1 clock enable */ +#define RCU_APB1EN_TIMER2EN BIT(1) /*!< TIMER2 clock enable */ +#define RCU_APB1EN_TIMER3EN BIT(2) /*!< TIMER3 clock enable */ +#define RCU_APB1EN_TIMER4EN BIT(3) /*!< TIMER4 clock enable */ +#define RCU_APB1EN_TIMER5EN BIT(4) /*!< TIMER5 clock enable */ +#define RCU_APB1EN_TIMER6EN BIT(5) /*!< TIMER6 clock enable */ +#define RCU_APB1EN_TIMER11EN BIT(6) /*!< TIMER11 clock enable */ +#define RCU_APB1EN_TIMER12EN BIT(7) /*!< TIMER12 clock enable */ +#define RCU_APB1EN_TIMER13EN BIT(8) /*!< TIMER13 clock enable */ +#define RCU_APB1EN_WWDGTEN BIT(11) /*!< WWDGT clock enable */ +#define RCU_APB1EN_SPI1EN BIT(14) /*!< SPI1 clock enable */ +#define RCU_APB1EN_SPI2EN BIT(15) /*!< SPI2 clock enable */ +#define RCU_APB1EN_USART1EN BIT(17) /*!< USART1 clock enable */ +#define RCU_APB1EN_USART2EN BIT(18) /*!< USART2 clock enable */ +#define RCU_APB1EN_UART3EN BIT(19) /*!< UART3 clock enable */ +#define RCU_APB1EN_UART4EN BIT(20) /*!< UART4 clock enable */ +#define RCU_APB1EN_I2C0EN BIT(21) /*!< I2C0 clock enable */ +#define RCU_APB1EN_I2C1EN BIT(22) /*!< I2C1 clock enable */ +#define RCU_APB1EN_CAN0EN BIT(25) /*!< CAN0 clock enable */ +#define RCU_APB1EN_CAN1EN BIT(26) /*!< CAN1 clock enable */ +#define RCU_APB1EN_BKPIEN BIT(27) /*!< backup interface clock enable */ +#define RCU_APB1EN_PMUEN BIT(28) /*!< PMU clock enable */ +#define RCU_APB1EN_DACEN BIT(29) /*!< DAC clock enable */ + +/* RCU_BDCTL */ +#define RCU_BDCTL_LXTALEN BIT(0) /*!< LXTAL enable */ +#define RCU_BDCTL_LXTALSTB BIT(1) /*!< low speed crystal oscillator stabilization flag */ +#define RCU_BDCTL_LXTALBPS BIT(2) /*!< LXTAL bypass mode enable */ +#define RCU_BDCTL_LXTALDRI BITS(3,4) /*!< LXTAL drive capability */ +#define RCU_BDCTL_RTCSRC BITS(8,9) /*!< RTC clock entry selection */ +#define RCU_BDCTL_RTCEN BIT(15) /*!< RTC clock enable */ +#define RCU_BDCTL_BKPRST BIT(16) /*!< backup domain reset */ + +/* RCU_RSTSCK */ +#define RCU_RSTSCK_IRC40KEN BIT(0) /*!< IRC40K enable */ +#define RCU_RSTSCK_IRC40KSTB BIT(1) /*!< IRC40K stabilization flag */ +#define RCU_RSTSCK_RSTFC BIT(24) /*!< reset flag clear */ +#define RCU_RSTSCK_EPRSTF BIT(26) /*!< external pin reset flag */ +#define RCU_RSTSCK_PORRSTF BIT(27) /*!< power reset flag */ +#define RCU_RSTSCK_SWRSTF BIT(28) /*!< software reset flag */ +#define RCU_RSTSCK_FWDGTRSTF BIT(29) /*!< free watchdog timer reset flag */ +#define RCU_RSTSCK_WWDGTRSTF BIT(30) /*!< window watchdog timer reset flag */ +#define RCU_RSTSCK_LPRSTF BIT(31) /*!< low-power reset flag */ + +/* RCU_AHB1RST */ +#define RCU_AHB1RST_USBFSRST BIT(12) /*!< USBFS reset */ +#define RCU_AHB1RST_ENETRST BIT(14) /*!< ENET reset */ + +/* RCU_CFG1 */ +#define RCU_CFG1_PREDV0 BITS(0,3) /*!< PREDV0 division factor */ +#define RCU_CFG1_PREDV1 BITS(4,7) /*!< PREDV1 division factor */ +#define RCU_CFG1_PLL1MF BITS(8,11) /*!< PLL1 clock multiplication factor */ +#define RCU_CFG1_PLL2MF BITS(12,15) /*!< PLL2 clock multiplication factor */ +#define RCU_CFG1_PREDV0SEL BIT(16) /*!< PREDV0 input clock source selection */ +#define RCU_CFG1_I2S1SEL BIT(17) /*!< I2S1 clock source selection */ +#define RCU_CFG1_I2S2SEL BIT(18) /*!< I2S2 clock source selection */ + +/* RCU_DSV */ +#define RCU_DSV_DSLPVS BITS(0,2) /*!< deep-sleep mode voltage select */ + +/* RCU_AHB2EN */ +#define RCU_AHB2EN_DCIEN BIT(0) /*!< DCI clock enable */ +#define RCU_AHB2EN_CAUEN BIT(4) /*!< CAU clock enable */ +#define RCU_AHB2EN_HAUEN BIT(5) /*!< HAU clock enable */ +#define RCU_AHB2EN_TRNGEN BIT(6) /*!< TRNG clock enable */ + +/* RCU_ADDAPB2EN */ +#define RCU_ADDAPB2EN_USART5EN BIT(24) /*!< USART5 clock enable */ +#define RCU_ADDAPB2EN_TLIEN BIT(26) /*!< TLI clock enable */ +#define RCU_ADDAPB2EN_PHEN BIT(30) /*!< GPIO port H clock enable */ +#define RCU_ADDAPB2EN_PIEN BIT(31) /*!< GPIO port I clock enable */ + +/* RCU_ADDAPB1EN */ +#define RCU_ADDAPB1EN_I2C2EN BIT(23) /*!< I2C2 clock enable */ +#define RCU_ADDAPB1EN_UART6EN BIT(30) /*!< UART6 clock enable */ +#define RCU_ADDAPB1EN_UART7EN BIT(31) /*!< UART7 clock enable */ + +/* RCU_AHB2RST */ +#define RCU_AHB2RST_DCIRST BIT(0) /*!< DCI reset */ +#define RCU_AHB2RST_CAURST BIT(4) /*!< CAU reset */ +#define RCU_AHB2RST_HAURST BIT(5) /*!< HAU reset */ +#define RCU_AHB2RST_TRNGRST BIT(6) /*!< TRNG reset */ + +/* RCU_ADDAPB2RST */ +#define RCU_ADDAPB2RST_USART5RST BIT(24) /*!< USART5 reset */ +#define RCU_ADDAPB2RST_TLIRST BIT(26) /*!< TLI reset */ +#define RCU_ADDAPB2RST_PHRST BIT(30) /*!< GPIO port H reset */ +#define RCU_ADDAPB2RST_PIRST BIT(31) /*!< GPIO port I reset */ + +/* RCU_ADDAPB1RST */ +#define RCU_ADDAPB1RST_I2C2RST BIT(23) /*!< I2C2 reset */ +#define RCU_ADDAPB1RST_UART6RST BIT(30) /*!< UART6 reset */ +#define RCU_ADDAPB1RST_UART7RST BIT(31) /*!< UART7 reset */ + +/* RCU_CFG2 */ +#define RCU_CFG2_CKOUT0DIV BITS(0,5) /*!< CK_OUT0 divider */ +#define RCU_CFG2_CKOUT1DIV BITS(8,13) /*!< CK_OUT1 divider */ +#define RCU_CFG2_CKOUT1SEL BITS(16,19) /*!< CKOUT1 clock source selection */ + +/* RCU_PLLTCTL */ +#define RCU_PLLTCTL_PLLTEN BIT(28) /*!< PLLT enable */ +#define RCU_PLLTCTL_PLLTSTB BIT(29) /*!< PLLT clock stabilization flag */ + +/* RCU_PLLTINT */ +#define RCU_PLLTINT_PLLTSTBIF BIT(6) /*!< PLLT stabilization interrupt flag */ +#define RCU_PLLTINT_PLLTSTBIE BIT(14) /*!< PLLT stabilization interrupt enable */ +#define RCU_PLLTINT_PLLTSTBIC BIT(22) /*!< PLLT stabilization interrupt clear */ + +/* RCU_PLLTCFG */ +#define RCU_PLLTCFG_PLLTPSC BITS(0,5) /*!< PLLT prescaler selection */ +#define RCU_PLLTCFG_PLLTMF BITS(6,14) /*!< PLLT multiply factor for VCO */ +#define RCU_PLLTCFG_TLIPSC BITS(16,17) /*!< TLI prescaler selection */ +#define RCU_PLLTCFG_PLLTRPSC BITS(28,30) /*!< PLLTR prescaler selection */ +#define RCU_PLLTCFG_PLLTSEL BIT(31) /*!< PLLT clock source select */ + +/* constants definitions */ +/* define the peripheral clock enable bit position and its register index offset */ +#define RCU_REGIDX_BIT(regidx, bitpos) (((uint32_t)(regidx) << 6) | (uint32_t)(bitpos)) +#define RCU_REG_VAL(periph) (REG32(RCU + ((uint32_t)(periph) >> 6))) +#define RCU_BIT_POS(val) ((uint32_t)(val) & 0x1FU) + +/* register offset */ +/* peripherals enable */ +#define AHB1EN_REG_OFFSET 0x14U /*!< AHB1 enable register offset */ +#define APB2EN_REG_OFFSET 0x18U /*!< APB2 enable register offset */ +#define APB1EN_REG_OFFSET 0x1CU /*!< APB1 enable register offset */ +#define AHB2EN_REG_OFFSET 0x60U /*!< AHB2 enable register offset */ +#define ADD_APB2EN_REG_OFFSET 0x64U /*!< APB2 additional enable register offset */ +#define ADD_APB1EN_REG_OFFSET 0x68U /*!< APB1 additional enable register offset */ + +/* peripherals reset */ +#define APB2RST_REG_OFFSET 0x0CU /*!< APB2 reset register offset */ +#define APB1RST_REG_OFFSET 0x10U /*!< APB1 reset register offset */ +#define RSTSCK_REG_OFFSET 0x24U /*!< reset source / clock register offset */ +#define AHB1RST_REG_OFFSET 0x28U /*!< AHB1 reset register offset */ +#define AHB2RST_REG_OFFSET 0x70U /*!< AHB2 reset register offset */ +#define ADD_APB2RST_REG_OFFSET 0x74U /*!< APB2 additional reset register offset */ +#define ADD_APB1RST_REG_OFFSET 0x78U /*!< APB1 additional reset register offset */ + +/* clock control */ +#define CTL_REG_OFFSET 0x00U /*!< control register offset */ +#define BDCTL_REG_OFFSET 0x20U /*!< backup domain control register offset */ +#define PLLTCTL_REG_OFFSET 0x90U /*!< PLLT control register offset */ + +/* clock stabilization and stuck interrupt */ +#define INT_REG_OFFSET 0x08U /*!< interrupt register offset */ +#define PLLTINT_REG_OFFSET 0x94U /*!< PLLT interrupt register offset */ + +/* configuration register */ +#define CFG0_REG_OFFSET 0x04U /*!< configuration register 0 offset */ +#define CFG1_REG_OFFSET 0x2CU /*!< configuration register 1 offset */ +#define CFG2_REG_OFFSET 0x80U /*!< configuration register 2 offset */ +#define PLLTCFG_REG_OFFSET 0x98U /*!< PLLT configuration register offset */ + +/* peripheral clock enable */ +typedef enum +{ + /* AHB peripherals */ + RCU_DMA0 = RCU_REGIDX_BIT(AHB1EN_REG_OFFSET, 0U), /*!< DMA0 clock */ + RCU_DMA1 = RCU_REGIDX_BIT(AHB1EN_REG_OFFSET, 1U), /*!< DMA1 clock */ + RCU_CRC = RCU_REGIDX_BIT(AHB1EN_REG_OFFSET, 6U), /*!< CRC clock */ + RCU_EXMC = RCU_REGIDX_BIT(AHB1EN_REG_OFFSET, 8U), /*!< EXMC clock */ + RCU_SDIO = RCU_REGIDX_BIT(AHB1EN_REG_OFFSET, 10U), /*!< SDIO clock */ + RCU_USBFS = RCU_REGIDX_BIT(AHB1EN_REG_OFFSET, 12U), /*!< USBFS clock */ + RCU_ENET = RCU_REGIDX_BIT(AHB1EN_REG_OFFSET, 14U), /*!< ENET clock */ + RCU_ENETTX = RCU_REGIDX_BIT(AHB1EN_REG_OFFSET, 15U), /*!< ENETTX clock */ + RCU_ENETRX = RCU_REGIDX_BIT(AHB1EN_REG_OFFSET, 16U), /*!< ENETRX clock */ + + RCU_DCI = RCU_REGIDX_BIT(AHB2EN_REG_OFFSET, 0U), /*!< DCI clock */ + RCU_CAU = RCU_REGIDX_BIT(AHB2EN_REG_OFFSET, 4U), /*!< CAU clock */ + RCU_HAU = RCU_REGIDX_BIT(AHB2EN_REG_OFFSET, 5U), /*!< HAU clock */ + RCU_TRNG = RCU_REGIDX_BIT(AHB2EN_REG_OFFSET, 6U), /*!< TRNG clock */ + + /* APB1 peripherals */ + RCU_TIMER1 = RCU_REGIDX_BIT(APB1EN_REG_OFFSET, 0U), /*!< TIMER1 clock */ + RCU_TIMER2 = RCU_REGIDX_BIT(APB1EN_REG_OFFSET, 1U), /*!< TIMER2 clock */ + RCU_TIMER3 = RCU_REGIDX_BIT(APB1EN_REG_OFFSET, 2U), /*!< TIMER3 clock */ + RCU_TIMER4 = RCU_REGIDX_BIT(APB1EN_REG_OFFSET, 3U), /*!< TIMER4 clock */ + RCU_TIMER5 = RCU_REGIDX_BIT(APB1EN_REG_OFFSET, 4U), /*!< TIMER5 clock */ + RCU_TIMER6 = RCU_REGIDX_BIT(APB1EN_REG_OFFSET, 5U), /*!< TIMER6 clock */ + RCU_TIMER11 = RCU_REGIDX_BIT(APB1EN_REG_OFFSET, 6U), /*!< TIMER11 clock */ + RCU_TIMER12 = RCU_REGIDX_BIT(APB1EN_REG_OFFSET, 7U), /*!< TIMER12 clock */ + RCU_TIMER13 = RCU_REGIDX_BIT(APB1EN_REG_OFFSET, 8U), /*!< TIMER13 clock */ + RCU_WWDGT = RCU_REGIDX_BIT(APB1EN_REG_OFFSET, 11U), /*!< WWDGT clock */ + RCU_SPI1 = RCU_REGIDX_BIT(APB1EN_REG_OFFSET, 14U), /*!< SPI1 clock */ + RCU_SPI2 = RCU_REGIDX_BIT(APB1EN_REG_OFFSET, 15U), /*!< SPI2 clock */ + RCU_USART1 = RCU_REGIDX_BIT(APB1EN_REG_OFFSET, 17U), /*!< USART1 clock */ + RCU_USART2 = RCU_REGIDX_BIT(APB1EN_REG_OFFSET, 18U), /*!< USART2 clock */ + RCU_UART3 = RCU_REGIDX_BIT(APB1EN_REG_OFFSET, 19U), /*!< UART3 clock */ + RCU_UART4 = RCU_REGIDX_BIT(APB1EN_REG_OFFSET, 20U), /*!< UART4 clock */ + RCU_I2C0 = RCU_REGIDX_BIT(APB1EN_REG_OFFSET, 21U), /*!< I2C0 clock */ + RCU_I2C1 = RCU_REGIDX_BIT(APB1EN_REG_OFFSET, 22U), /*!< I2C1 clock */ + RCU_CAN0 = RCU_REGIDX_BIT(APB1EN_REG_OFFSET, 25U), /*!< CAN0 clock */ + RCU_CAN1 = RCU_REGIDX_BIT(APB1EN_REG_OFFSET, 26U), /*!< CAN1 clock */ + RCU_BKPI = RCU_REGIDX_BIT(APB1EN_REG_OFFSET, 27U), /*!< BKPI clock */ + RCU_PMU = RCU_REGIDX_BIT(APB1EN_REG_OFFSET, 28U), /*!< PMU clock */ + RCU_DAC = RCU_REGIDX_BIT(APB1EN_REG_OFFSET, 29U), /*!< DAC clock */ + + RCU_RTC = RCU_REGIDX_BIT(BDCTL_REG_OFFSET, 15U), /*!< RTC clock */ + + RCU_I2C2 = RCU_REGIDX_BIT(ADD_APB1EN_REG_OFFSET, 23U), /*!< I2C2 clock */ + RCU_UART6 = RCU_REGIDX_BIT(ADD_APB1EN_REG_OFFSET, 30U), /*!< UART6 clock */ + RCU_UART7 = RCU_REGIDX_BIT(ADD_APB1EN_REG_OFFSET, 31U), /*!< UART7 clock */ + + /* APB2 peripherals */ + RCU_AF = RCU_REGIDX_BIT(APB2EN_REG_OFFSET, 0U), /*!< alternate function clock */ + RCU_GPIOA = RCU_REGIDX_BIT(APB2EN_REG_OFFSET, 2U), /*!< GPIOA clock */ + RCU_GPIOB = RCU_REGIDX_BIT(APB2EN_REG_OFFSET, 3U), /*!< GPIOB clock */ + RCU_GPIOC = RCU_REGIDX_BIT(APB2EN_REG_OFFSET, 4U), /*!< GPIOC clock */ + RCU_GPIOD = RCU_REGIDX_BIT(APB2EN_REG_OFFSET, 5U), /*!< GPIOD clock */ + RCU_GPIOE = RCU_REGIDX_BIT(APB2EN_REG_OFFSET, 6U), /*!< GPIOE clock */ + RCU_GPIOF = RCU_REGIDX_BIT(APB2EN_REG_OFFSET, 7U), /*!< GPIOF clock */ + RCU_GPIOG = RCU_REGIDX_BIT(APB2EN_REG_OFFSET, 8U), /*!< GPIOG clock */ + RCU_ADC0 = RCU_REGIDX_BIT(APB2EN_REG_OFFSET, 9U), /*!< ADC0 clock */ + RCU_ADC1 = RCU_REGIDX_BIT(APB2EN_REG_OFFSET, 10U), /*!< ADC1 clock */ + RCU_TIMER0 = RCU_REGIDX_BIT(APB2EN_REG_OFFSET, 11U), /*!< TIMER0 clock */ + RCU_SPI0 = RCU_REGIDX_BIT(APB2EN_REG_OFFSET, 12U), /*!< SPI0 clock */ + RCU_TIMER7 = RCU_REGIDX_BIT(APB2EN_REG_OFFSET, 13U), /*!< TIMER7 clock */ + RCU_USART0 = RCU_REGIDX_BIT(APB2EN_REG_OFFSET, 14U), /*!< USART0 clock */ + RCU_ADC2 = RCU_REGIDX_BIT(APB2EN_REG_OFFSET, 15U), /*!< ADC2 clock */ + RCU_TIMER8 = RCU_REGIDX_BIT(APB2EN_REG_OFFSET, 19U), /*!< TIMER8 clock */ + RCU_TIMER9 = RCU_REGIDX_BIT(APB2EN_REG_OFFSET, 20U), /*!< TIMER9 clock */ + RCU_TIMER10 = RCU_REGIDX_BIT(APB2EN_REG_OFFSET, 21U), /*!< TIMER10 clock */ + + RCU_USART5 = RCU_REGIDX_BIT(ADD_APB2EN_REG_OFFSET, 24U), /*!< USART5 clock */ + RCU_TLI = RCU_REGIDX_BIT(ADD_APB2EN_REG_OFFSET, 26U), /*!< TLI clock */ + RCU_GPIOH = RCU_REGIDX_BIT(ADD_APB2EN_REG_OFFSET, 30U), /*!< GPIOH clock */ + RCU_GPIOI = RCU_REGIDX_BIT(ADD_APB2EN_REG_OFFSET, 31U), /*!< GPIOI clock */ + +}rcu_periph_enum; + +/* peripheral clock enable when sleep mode*/ +typedef enum +{ + /* AHB peripherals */ + RCU_SRAM_SLP = RCU_REGIDX_BIT(AHB1EN_REG_OFFSET, 2U), /*!< SRAM clock */ + RCU_FMC_SLP = RCU_REGIDX_BIT(AHB1EN_REG_OFFSET, 4U), /*!< FMC clock */ +}rcu_periph_sleep_enum; + +/* peripherals reset */ +typedef enum +{ + /* AHB peripherals */ + RCU_USBFSRST = RCU_REGIDX_BIT(AHB1RST_REG_OFFSET, 12U), /*!< USBFS clock reset */ + RCU_ENETRST = RCU_REGIDX_BIT(AHB1RST_REG_OFFSET, 14U), /*!< ENET clock reset */ + + RCU_DCIRST = RCU_REGIDX_BIT(AHB2RST_REG_OFFSET, 0U), /*!< DCI clock reset */ + RCU_CAURST = RCU_REGIDX_BIT(AHB2RST_REG_OFFSET, 4U), /*!< CAU clock reset */ + RCU_HAURST = RCU_REGIDX_BIT(AHB2RST_REG_OFFSET, 5U), /*!< HAU clock reset */ + RCU_TRNGRST = RCU_REGIDX_BIT(AHB2RST_REG_OFFSET, 6U), /*!< TRNG clock reset */ + + /* APB1 peripherals */ + RCU_TIMER1RST = RCU_REGIDX_BIT(APB1RST_REG_OFFSET, 0U), /*!< TIMER1 clock reset */ + RCU_TIMER2RST = RCU_REGIDX_BIT(APB1RST_REG_OFFSET, 1U), /*!< TIMER2 clock reset */ + RCU_TIMER3RST = RCU_REGIDX_BIT(APB1RST_REG_OFFSET, 2U), /*!< TIMER3 clock reset */ + RCU_TIMER4RST = RCU_REGIDX_BIT(APB1RST_REG_OFFSET, 3U), /*!< TIMER4 clock reset */ + RCU_TIMER5RST = RCU_REGIDX_BIT(APB1RST_REG_OFFSET, 4U), /*!< TIMER5 clock reset */ + RCU_TIMER6RST = RCU_REGIDX_BIT(APB1RST_REG_OFFSET, 5U), /*!< TIMER6 clock reset */ + RCU_TIMER11RST = RCU_REGIDX_BIT(APB1RST_REG_OFFSET, 6U), /*!< TIMER11 clock reset */ + RCU_TIMER12RST = RCU_REGIDX_BIT(APB1RST_REG_OFFSET, 7U), /*!< TIMER12 clock reset */ + RCU_TIMER13RST = RCU_REGIDX_BIT(APB1RST_REG_OFFSET, 8U), /*!< TIMER13 clock reset */ + RCU_WWDGTRST = RCU_REGIDX_BIT(APB1RST_REG_OFFSET, 11U), /*!< WWDGT clock reset */ + RCU_SPI1RST = RCU_REGIDX_BIT(APB1RST_REG_OFFSET, 14U), /*!< SPI1 clock reset */ + RCU_SPI2RST = RCU_REGIDX_BIT(APB1RST_REG_OFFSET, 15U), /*!< SPI2 clock reset */ + RCU_USART1RST = RCU_REGIDX_BIT(APB1RST_REG_OFFSET, 17U), /*!< USART1 clock reset */ + RCU_USART2RST = RCU_REGIDX_BIT(APB1RST_REG_OFFSET, 18U), /*!< USART2 clock reset */ + RCU_UART3RST = RCU_REGIDX_BIT(APB1RST_REG_OFFSET, 19U), /*!< UART3 clock reset */ + RCU_UART4RST = RCU_REGIDX_BIT(APB1RST_REG_OFFSET, 20U), /*!< UART4 clock reset */ + RCU_I2C0RST = RCU_REGIDX_BIT(APB1RST_REG_OFFSET, 21U), /*!< I2C0 clock reset */ + RCU_I2C1RST = RCU_REGIDX_BIT(APB1RST_REG_OFFSET, 22U), /*!< I2C1 clock reset */ + RCU_CAN0RST = RCU_REGIDX_BIT(APB1RST_REG_OFFSET, 25U), /*!< CAN0 clock reset */ + RCU_CAN1RST = RCU_REGIDX_BIT(APB1RST_REG_OFFSET, 26U), /*!< CAN1 clock reset */ + RCU_BKPIRST = RCU_REGIDX_BIT(APB1RST_REG_OFFSET, 27U), /*!< BKPI clock reset */ + RCU_PMURST = RCU_REGIDX_BIT(APB1RST_REG_OFFSET, 28U), /*!< PMU clock reset */ + RCU_DACRST = RCU_REGIDX_BIT(APB1RST_REG_OFFSET, 29U), /*!< DAC clock reset */ + + RCU_I2C2RST = RCU_REGIDX_BIT(ADD_APB1RST_REG_OFFSET, 23U), /*!< I2C2 clock reset */ + RCU_UART6RST = RCU_REGIDX_BIT(ADD_APB1RST_REG_OFFSET, 30U), /*!< UART6 clock reset */ + RCU_UART7RST = RCU_REGIDX_BIT(ADD_APB1RST_REG_OFFSET, 31U), /*!< UART7 clock reset */ + + /* APB2 peripherals */ + RCU_AFRST = RCU_REGIDX_BIT(APB2RST_REG_OFFSET, 0U), /*!< alternate function clock reset */ + RCU_GPIOARST = RCU_REGIDX_BIT(APB2RST_REG_OFFSET, 2U), /*!< GPIOA clock reset */ + RCU_GPIOBRST = RCU_REGIDX_BIT(APB2RST_REG_OFFSET, 3U), /*!< GPIOB clock reset */ + RCU_GPIOCRST = RCU_REGIDX_BIT(APB2RST_REG_OFFSET, 4U), /*!< GPIOC clock reset */ + RCU_GPIODRST = RCU_REGIDX_BIT(APB2RST_REG_OFFSET, 5U), /*!< GPIOD clock reset */ + RCU_GPIOERST = RCU_REGIDX_BIT(APB2RST_REG_OFFSET, 6U), /*!< GPIOE clock reset */ + RCU_GPIOFRST = RCU_REGIDX_BIT(APB2RST_REG_OFFSET, 7U), /*!< GPIOF clock reset */ + RCU_GPIOGRST = RCU_REGIDX_BIT(APB2RST_REG_OFFSET, 8U), /*!< GPIOG clock reset */ + RCU_ADC0RST = RCU_REGIDX_BIT(APB2RST_REG_OFFSET, 9U), /*!< ADC0 clock reset */ + RCU_ADC1RST = RCU_REGIDX_BIT(APB2RST_REG_OFFSET, 10U), /*!< ADC1 clock reset */ + RCU_TIMER0RST = RCU_REGIDX_BIT(APB2RST_REG_OFFSET, 11U), /*!< TIMER0 clock reset */ + RCU_SPI0RST = RCU_REGIDX_BIT(APB2RST_REG_OFFSET, 12U), /*!< SPI0 clock reset */ + RCU_TIMER7RST = RCU_REGIDX_BIT(APB2RST_REG_OFFSET, 13U), /*!< TIMER7 clock reset */ + RCU_USART0RST = RCU_REGIDX_BIT(APB2RST_REG_OFFSET, 14U), /*!< USART0 clock reset */ + RCU_ADC2RST = RCU_REGIDX_BIT(APB2RST_REG_OFFSET, 15U), /*!< ADC2 clock reset */ + RCU_TIMER8RST = RCU_REGIDX_BIT(APB2RST_REG_OFFSET, 19U), /*!< TIMER8 clock reset */ + RCU_TIMER9RST = RCU_REGIDX_BIT(APB2RST_REG_OFFSET, 20U), /*!< TIMER9 clock reset */ + RCU_TIMER10RST = RCU_REGIDX_BIT(APB2RST_REG_OFFSET, 21U), /*!< TIMER10 clock reset */ + + RCU_USART5RST = RCU_REGIDX_BIT(ADD_APB2RST_REG_OFFSET, 24U), /*!< USART5 clock reset */ + RCU_TLIRST = RCU_REGIDX_BIT(ADD_APB2RST_REG_OFFSET, 26U), /*!< TLI clock reset */ + RCU_GPIOHRST = RCU_REGIDX_BIT(ADD_APB2RST_REG_OFFSET, 30U), /*!< GPIOH clock reset */ + RCU_GPIOIRST = RCU_REGIDX_BIT(ADD_APB2RST_REG_OFFSET, 31U), /*!< GPIOI clock reset */ + +}rcu_periph_reset_enum; + +/* clock stabilization and peripheral reset flags */ +typedef enum +{ + /* clock stabilization flags */ + RCU_FLAG_IRC8MSTB = RCU_REGIDX_BIT(CTL_REG_OFFSET, 1U), /*!< IRC8M stabilization flags */ + RCU_FLAG_HXTALSTB = RCU_REGIDX_BIT(CTL_REG_OFFSET, 17U), /*!< HXTAL stabilization flags */ + RCU_FLAG_PLLSTB = RCU_REGIDX_BIT(CTL_REG_OFFSET, 25U), /*!< PLL stabilization flags */ + RCU_FLAG_PLL1STB = RCU_REGIDX_BIT(CTL_REG_OFFSET, 27U), /*!< PLL1 stabilization flags */ + RCU_FLAG_PLL2STB = RCU_REGIDX_BIT(CTL_REG_OFFSET, 29U), /*!< PLL2 stabilization flags */ + + RCU_FLAG_LXTALSTB = RCU_REGIDX_BIT(BDCTL_REG_OFFSET, 1U), /*!< LXTAL stabilization flags */ + + RCU_FLAG_IRC40KSTB = RCU_REGIDX_BIT(RSTSCK_REG_OFFSET, 1U), /*!< IRC40K stabilization flags */ + + RCU_FLAG_PLLTSTB = RCU_REGIDX_BIT(PLLTCTL_REG_OFFSET, 29U), /*!< PLLT stabilization flags */ + + /* reset source flags */ + RCU_FLAG_EPRST = RCU_REGIDX_BIT(RSTSCK_REG_OFFSET, 26U), /*!< external PIN reset flags */ + RCU_FLAG_PORRST = RCU_REGIDX_BIT(RSTSCK_REG_OFFSET, 27U), /*!< power reset flags */ + RCU_FLAG_SWRST = RCU_REGIDX_BIT(RSTSCK_REG_OFFSET, 28U), /*!< software reset flags */ + RCU_FLAG_FWDGTRST = RCU_REGIDX_BIT(RSTSCK_REG_OFFSET, 29U), /*!< FWDGT reset flags */ + RCU_FLAG_WWDGTRST = RCU_REGIDX_BIT(RSTSCK_REG_OFFSET, 30U), /*!< WWDGT reset flags */ + RCU_FLAG_LPRST = RCU_REGIDX_BIT(RSTSCK_REG_OFFSET, 31U), /*!< low-power reset flags */ +}rcu_flag_enum; + +/* clock stabilization and ckm interrupt flags */ +typedef enum +{ + RCU_INT_FLAG_IRC40KSTB = RCU_REGIDX_BIT(INT_REG_OFFSET, 0U), /*!< IRC40K stabilization interrupt flag */ + RCU_INT_FLAG_LXTALSTB = RCU_REGIDX_BIT(INT_REG_OFFSET, 1U), /*!< LXTAL stabilization interrupt flag */ + RCU_INT_FLAG_IRC8MSTB = RCU_REGIDX_BIT(INT_REG_OFFSET, 2U), /*!< IRC8M stabilization interrupt flag */ + RCU_INT_FLAG_HXTALSTB = RCU_REGIDX_BIT(INT_REG_OFFSET, 3U), /*!< HXTAL stabilization interrupt flag */ + RCU_INT_FLAG_PLLSTB = RCU_REGIDX_BIT(INT_REG_OFFSET, 4U), /*!< PLL stabilization interrupt flag */ + RCU_INT_FLAG_PLL1STB = RCU_REGIDX_BIT(INT_REG_OFFSET, 5U), /*!< PLL1 stabilization interrupt flag */ + RCU_INT_FLAG_PLL2STB = RCU_REGIDX_BIT(INT_REG_OFFSET, 6U), /*!< PLL2 stabilization interrupt flag */ + RCU_INT_FLAG_CKM = RCU_REGIDX_BIT(INT_REG_OFFSET, 7U), /*!< HXTAL clock stuck interrupt flag */ + RCU_INT_FLAG_PLLTSTB = RCU_REGIDX_BIT(PLLTINT_REG_OFFSET, 6U), /*!< PLLT stabilization interrupt flag */ +}rcu_int_flag_enum; + +/* clock stabilization and stuck interrupt flags clear */ +typedef enum +{ + RCU_INT_FLAG_IRC40KSTB_CLR = RCU_REGIDX_BIT(INT_REG_OFFSET, 16U), /*!< IRC40K stabilization interrupt flags clear */ + RCU_INT_FLAG_LXTALSTB_CLR = RCU_REGIDX_BIT(INT_REG_OFFSET, 17U), /*!< LXTAL stabilization interrupt flags clear */ + RCU_INT_FLAG_IRC8MSTB_CLR = RCU_REGIDX_BIT(INT_REG_OFFSET, 18U), /*!< IRC8M stabilization interrupt flags clear */ + RCU_INT_FLAG_HXTALSTB_CLR = RCU_REGIDX_BIT(INT_REG_OFFSET, 19U), /*!< HXTAL stabilization interrupt flags clear */ + RCU_INT_FLAG_PLLSTB_CLR = RCU_REGIDX_BIT(INT_REG_OFFSET, 20U), /*!< PLL stabilization interrupt flags clear */ + RCU_INT_FLAG_PLL1STB_CLR = RCU_REGIDX_BIT(INT_REG_OFFSET, 21U), /*!< PLL1 stabilization interrupt flags clear */ + RCU_INT_FLAG_PLL2STB_CLR = RCU_REGIDX_BIT(INT_REG_OFFSET, 22U), /*!< PLL2 stabilization interrupt flags clear */ + RCU_INT_FLAG_CKM_CLR = RCU_REGIDX_BIT(INT_REG_OFFSET, 23U), /*!< CKM interrupt flags clear */ + RCU_INT_FLAG_PLLTSTB_CLR = RCU_REGIDX_BIT(PLLTINT_REG_OFFSET, 22U), /*!< PLLT stabilization interrupt clear */ +}rcu_int_flag_clear_enum; + +/* clock stabilization interrupt enable or disable */ +typedef enum +{ + RCU_INT_IRC40KSTB = RCU_REGIDX_BIT(INT_REG_OFFSET, 8U), /*!< IRC40K stabilization interrupt */ + RCU_INT_LXTALSTB = RCU_REGIDX_BIT(INT_REG_OFFSET, 9U), /*!< LXTAL stabilization interrupt */ + RCU_INT_IRC8MSTB = RCU_REGIDX_BIT(INT_REG_OFFSET, 10U), /*!< IRC8M stabilization interrupt */ + RCU_INT_HXTALSTB = RCU_REGIDX_BIT(INT_REG_OFFSET, 11U), /*!< HXTAL stabilization interrupt */ + RCU_INT_PLLSTB = RCU_REGIDX_BIT(INT_REG_OFFSET, 12U), /*!< PLL stabilization interrupt */ + RCU_INT_PLL1STB = RCU_REGIDX_BIT(INT_REG_OFFSET, 13U), /*!< PLL1 stabilization interrupt */ + RCU_INT_PLL2STB = RCU_REGIDX_BIT(INT_REG_OFFSET, 14U), /*!< PLL2 stabilization interrupt */ + RCU_INT_PLLTSTB = RCU_REGIDX_BIT(PLLTINT_REG_OFFSET, 14U), /*!< PLLT stabilization interrupt */ +}rcu_int_enum; + +/* oscillator types */ +typedef enum +{ + RCU_IRC8M = RCU_REGIDX_BIT(CTL_REG_OFFSET, 0U), /*!< IRC8M */ + RCU_HXTAL = RCU_REGIDX_BIT(CTL_REG_OFFSET, 16U), /*!< HXTAL */ + RCU_PLL_CK = RCU_REGIDX_BIT(CTL_REG_OFFSET, 24U), /*!< PLL */ + RCU_PLL1_CK = RCU_REGIDX_BIT(CTL_REG_OFFSET, 26U), /*!< PLL1 */ + RCU_PLL2_CK = RCU_REGIDX_BIT(CTL_REG_OFFSET, 28U), /*!< PLL2 */ + + RCU_LXTAL = RCU_REGIDX_BIT(BDCTL_REG_OFFSET, 0U), /*!< LXTAL */ + + RCU_IRC40K = RCU_REGIDX_BIT(RSTSCK_REG_OFFSET, 0U), /*!< IRC40K */ + + RCU_PLLT_CK = RCU_REGIDX_BIT(PLLTCTL_REG_OFFSET, 28U), /*!< PLLT */ + +}rcu_osci_type_enum; + +/* rcu clock frequency */ +typedef enum +{ + CK_SYS = 0, /*!< system clock */ + CK_AHB, /*!< AHB clock */ + CK_APB1, /*!< APB1 clock */ + CK_APB2, /*!< APB2 clock */ +}rcu_clock_freq_enum; + +/* RCU_CFG0 register bit define */ +/* system clock source selection */ +#define CFG0_SCS(regval) (BITS(0,1) & ((uint32_t)(regval) << 0)) +#define RCU_CKSYSSRC_IRC8M CFG0_SCS(0) /*!< system clock source select IRC8M */ +#define RCU_CKSYSSRC_HXTAL CFG0_SCS(1) /*!< system clock source select HXTAL */ +#define RCU_CKSYSSRC_PLL CFG0_SCS(2) /*!< system clock source select PLL */ + +/* system clock source select status */ +#define CFG0_SCSS(regval) (BITS(2,3) & ((uint32_t)(regval) << 2)) +#define RCU_SCSS_IRC8M CFG0_SCSS(0) /*!< system clock source select IRC8M */ +#define RCU_SCSS_HXTAL CFG0_SCSS(1) /*!< system clock source select HXTAL */ +#define RCU_SCSS_PLL CFG0_SCSS(2) /*!< system clock source select PLLP */ + +/* AHB prescaler selection */ +#define CFG0_AHBPSC(regval) (BITS(4,7) & ((uint32_t)(regval) << 4)) +#define RCU_AHB_CKSYS_DIV1 CFG0_AHBPSC(0) /*!< AHB prescaler select CK_SYS */ +#define RCU_AHB_CKSYS_DIV2 CFG0_AHBPSC(8) /*!< AHB prescaler select CK_SYS/2 */ +#define RCU_AHB_CKSYS_DIV4 CFG0_AHBPSC(9) /*!< AHB prescaler select CK_SYS/4 */ +#define RCU_AHB_CKSYS_DIV8 CFG0_AHBPSC(10) /*!< AHB prescaler select CK_SYS/8 */ +#define RCU_AHB_CKSYS_DIV16 CFG0_AHBPSC(11) /*!< AHB prescaler select CK_SYS/16 */ +#define RCU_AHB_CKSYS_DIV64 CFG0_AHBPSC(12) /*!< AHB prescaler select CK_SYS/64 */ +#define RCU_AHB_CKSYS_DIV128 CFG0_AHBPSC(13) /*!< AHB prescaler select CK_SYS/128 */ +#define RCU_AHB_CKSYS_DIV256 CFG0_AHBPSC(14) /*!< AHB prescaler select CK_SYS/256 */ +#define RCU_AHB_CKSYS_DIV512 CFG0_AHBPSC(15) /*!< AHB prescaler select CK_SYS/512 */ + +/* APB1 prescaler selection */ +#define CFG0_APB1PSC(regval) (BITS(8,10) & ((uint32_t)(regval) << 8)) +#define RCU_APB1_CKAHB_DIV1 CFG0_APB1PSC(0) /*!< APB1 prescaler select CK_AHB */ +#define RCU_APB1_CKAHB_DIV2 CFG0_APB1PSC(4) /*!< APB1 prescaler select CK_AHB/2 */ +#define RCU_APB1_CKAHB_DIV4 CFG0_APB1PSC(5) /*!< APB1 prescaler select CK_AHB/4 */ +#define RCU_APB1_CKAHB_DIV8 CFG0_APB1PSC(6) /*!< APB1 prescaler select CK_AHB/8 */ +#define RCU_APB1_CKAHB_DIV16 CFG0_APB1PSC(7) /*!< APB1 prescaler select CK_AHB/16 */ + +/* APB2 prescaler selection */ +#define CFG0_APB2PSC(regval) (BITS(11,13) & ((uint32_t)(regval) << 11)) +#define RCU_APB2_CKAHB_DIV1 CFG0_APB2PSC(0) /*!< APB2 prescaler select CK_AHB */ +#define RCU_APB2_CKAHB_DIV2 CFG0_APB2PSC(4) /*!< APB2 prescaler select CK_AHB/2 */ +#define RCU_APB2_CKAHB_DIV4 CFG0_APB2PSC(5) /*!< APB2 prescaler select CK_AHB/4 */ +#define RCU_APB2_CKAHB_DIV8 CFG0_APB2PSC(6) /*!< APB2 prescaler select CK_AHB/8 */ +#define RCU_APB2_CKAHB_DIV16 CFG0_APB2PSC(7) /*!< APB2 prescaler select CK_AHB/16 */ + +/* ADC prescaler selection */ +#define RCU_CKADC_CKAPB2_DIV2 ((uint32_t)0x00000000U) /*!< ADC prescaler select CK_APB2/2 */ +#define RCU_CKADC_CKAPB2_DIV4 ((uint32_t)0x00000001U) /*!< ADC prescaler select CK_APB2/4 */ +#define RCU_CKADC_CKAPB2_DIV6 ((uint32_t)0x00000002U) /*!< ADC prescaler select CK_APB2/6 */ +#define RCU_CKADC_CKAPB2_DIV8 ((uint32_t)0x00000003U) /*!< ADC prescaler select CK_APB2/8 */ +#define RCU_CKADC_CKAPB2_DIV12 ((uint32_t)0x00000005U) /*!< ADC prescaler select CK_APB2/12 */ +#define RCU_CKADC_CKAPB2_DIV16 ((uint32_t)0x00000007U) /*!< ADC prescaler select CK_APB2/16 */ + +/* PLL clock source selection */ +#define RCU_PLLSRC_IRC8M_DIV2 ((uint32_t)0x00000000U) /*!< IRC8M/2 clock selected as source clock of PLL */ +#define RCU_PLLSRC_HXTAL RCU_CFG0_PLLSEL /*!< HXTAL selected as source clock of PLL */ + +/* PLL clock multiplication factor */ +#define PLLMF_4 RCU_CFG0_PLLMF_4 /* bit 4 of PLLMF */ + +#define CFG0_PLLMF(regval) (BITS(18,21) & ((uint32_t)(regval) << 18)) +#define RCU_PLL_MUL2 CFG0_PLLMF(0) /*!< PLL source clock multiply by 2 */ +#define RCU_PLL_MUL3 CFG0_PLLMF(1) /*!< PLL source clock multiply by 3 */ +#define RCU_PLL_MUL4 CFG0_PLLMF(2) /*!< PLL source clock multiply by 4 */ +#define RCU_PLL_MUL5 CFG0_PLLMF(3) /*!< PLL source clock multiply by 5 */ +#define RCU_PLL_MUL6 CFG0_PLLMF(4) /*!< PLL source clock multiply by 6 */ +#define RCU_PLL_MUL7 CFG0_PLLMF(5) /*!< PLL source clock multiply by 7 */ +#define RCU_PLL_MUL8 CFG0_PLLMF(6) /*!< PLL source clock multiply by 8 */ +#define RCU_PLL_MUL9 CFG0_PLLMF(7) /*!< PLL source clock multiply by 9 */ +#define RCU_PLL_MUL10 CFG0_PLLMF(8) /*!< PLL source clock multiply by 10 */ +#define RCU_PLL_MUL11 CFG0_PLLMF(9) /*!< PLL source clock multiply by 11 */ +#define RCU_PLL_MUL12 CFG0_PLLMF(10) /*!< PLL source clock multiply by 12 */ +#define RCU_PLL_MUL13 CFG0_PLLMF(11) /*!< PLL source clock multiply by 13 */ +#define RCU_PLL_MUL14 CFG0_PLLMF(12) /*!< PLL source clock multiply by 14 */ +#define RCU_PLL_MUL6_5 CFG0_PLLMF(13) /*!< PLL source clock multiply by 6.5 */ +#define RCU_PLL_MUL16 CFG0_PLLMF(14) /*!< PLL source clock multiply by 16 */ +#define RCU_PLL_MUL17 (PLLMF_4 | CFG0_PLLMF(0)) /*!< PLL source clock multiply by 17 */ +#define RCU_PLL_MUL18 (PLLMF_4 | CFG0_PLLMF(1)) /*!< PLL source clock multiply by 18 */ +#define RCU_PLL_MUL19 (PLLMF_4 | CFG0_PLLMF(2)) /*!< PLL source clock multiply by 19 */ +#define RCU_PLL_MUL20 (PLLMF_4 | CFG0_PLLMF(3)) /*!< PLL source clock multiply by 20 */ +#define RCU_PLL_MUL21 (PLLMF_4 | CFG0_PLLMF(4)) /*!< PLL source clock multiply by 21 */ +#define RCU_PLL_MUL22 (PLLMF_4 | CFG0_PLLMF(5)) /*!< PLL source clock multiply by 22 */ +#define RCU_PLL_MUL23 (PLLMF_4 | CFG0_PLLMF(6)) /*!< PLL source clock multiply by 23 */ +#define RCU_PLL_MUL24 (PLLMF_4 | CFG0_PLLMF(7)) /*!< PLL source clock multiply by 24 */ +#define RCU_PLL_MUL25 (PLLMF_4 | CFG0_PLLMF(8)) /*!< PLL source clock multiply by 25 */ +#define RCU_PLL_MUL26 (PLLMF_4 | CFG0_PLLMF(9)) /*!< PLL source clock multiply by 26 */ +#define RCU_PLL_MUL27 (PLLMF_4 | CFG0_PLLMF(10)) /*!< PLL source clock multiply by 27 */ +#define RCU_PLL_MUL28 (PLLMF_4 | CFG0_PLLMF(11)) /*!< PLL source clock multiply by 28 */ +#define RCU_PLL_MUL29 (PLLMF_4 | CFG0_PLLMF(12)) /*!< PLL source clock multiply by 29 */ +#define RCU_PLL_MUL30 (PLLMF_4 | CFG0_PLLMF(13)) /*!< PLL source clock multiply by 30 */ +#define RCU_PLL_MUL31 (PLLMF_4 | CFG0_PLLMF(14)) /*!< PLL source clock multiply by 31 */ +#define RCU_PLL_MUL32 (PLLMF_4 | CFG0_PLLMF(15)) /*!< PLL source clock multiply by 32 */ + +/* USBFS/TRNG prescaler selection */ +#define CFG0_USBFSPSC(regval) (BITS(22,23) & ((uint32_t)(regval) << 22)) +#define RCU_CKUSB_CKPLL_DIV1_5 CFG0_USBFSPSC(0) /*!< USBFS/TRNG prescaler select CK_PLL/1.5 */ +#define RCU_CKUSB_CKPLL_DIV1 CFG0_USBFSPSC(1) /*!< USBFS/TRNG prescaler select CK_PLL/1 */ +#define RCU_CKUSB_CKPLL_DIV2_5 CFG0_USBFSPSC(2) /*!< USBFS/TRNG prescaler select CK_PLL/2.5 */ +#define RCU_CKUSB_CKPLL_DIV2 CFG0_USBFSPSC(3) /*!< USBFS/TRNG prescaler select CK_PLL/2 */ + +/* CKOUT0 Clock source selection */ +#define CFG0_CKOUT0SEL(regval) (BITS(24,27) & ((uint32_t)(regval) << 24)) +#define RCU_CKOUT0SRC_NONE CFG0_CKOUT0SEL(0) /*!< no clock selected */ +#define RCU_CKOUT0SRC_CKSYS CFG0_CKOUT0SEL(4) /*!< system clock selected */ +#define RCU_CKOUT0SRC_IRC8M CFG0_CKOUT0SEL(5) /*!< internal 8M RC oscillator clock selected */ +#define RCU_CKOUT0SRC_HXTAL CFG0_CKOUT0SEL(6) /*!< high speed crystal oscillator clock (HXTAL) selected */ +#define RCU_CKOUT0SRC_CKPLL_DIV2 CFG0_CKOUT0SEL(7) /*!< CK_PLL/2 clock selected */ +#define RCU_CKOUT0SRC_CKPLL1 CFG0_CKOUT0SEL(8) /*!< CK_PLL1 clock selected */ +#define RCU_CKOUT0SRC_CKPLL2_DIV2 CFG0_CKOUT0SEL(9) /*!< CK_PLL2/2 clock selected */ +#define RCU_CKOUT0SRC_EXT1 CFG0_CKOUT0SEL(10) /*!< EXT1 selected, to provide the external clock for ENET */ +#define RCU_CKOUT0SRC_CKPLL2 CFG0_CKOUT0SEL(11) /*!< CK_PLL2 clock selected */ + +/* LXTAL drive capability */ +#define BDCTL_LXTALDRI(regval) (BITS(3,4) & ((uint32_t)(regval) << 3)) +#define RCU_LXTAL_LOWDRI BDCTL_LXTALDRI(0) /*!< lower driving capability */ +#define RCU_LXTAL_MED_LOWDRI BDCTL_LXTALDRI(1) /*!< medium low driving capability */ +#define RCU_LXTAL_MED_HIGHDRI BDCTL_LXTALDRI(2) /*!< medium high driving capability */ +#define RCU_LXTAL_HIGHDRI BDCTL_LXTALDRI(3) /*!< higher driving capability */ + +/* RTC clock entry selection */ +#define BDCTL_RTCSRC(regval) (BITS(8,9) & ((uint32_t)(regval) << 8)) +#define RCU_RTCSRC_NONE BDCTL_RTCSRC(0) /*!< no clock selected */ +#define RCU_RTCSRC_LXTAL BDCTL_RTCSRC(1) /*!< RTC source clock select LXTAL */ +#define RCU_RTCSRC_IRC40K BDCTL_RTCSRC(2) /*!< RTC source clock select IRC40K */ +#define RCU_RTCSRC_HXTAL_DIV128 BDCTL_RTCSRC(3) /*!< RTC source clock select HXTAL/128 */ + +/* PREDV0 division factor */ +#define CFG1_PREDV0(regval) (BITS(0,3) & ((uint32_t)(regval) << 0)) +#define RCU_PREDV0_DIV1 CFG1_PREDV0(0) /*!< PREDV0 input source clock divided by 1 */ +#define RCU_PREDV0_DIV2 CFG1_PREDV0(1) /*!< PREDV0 input source clock divided by 2 */ +#define RCU_PREDV0_DIV3 CFG1_PREDV0(2) /*!< PREDV0 input source clock divided by 3 */ +#define RCU_PREDV0_DIV4 CFG1_PREDV0(3) /*!< PREDV0 input source clock divided by 4 */ +#define RCU_PREDV0_DIV5 CFG1_PREDV0(4) /*!< PREDV0 input source clock divided by 5 */ +#define RCU_PREDV0_DIV6 CFG1_PREDV0(5) /*!< PREDV0 input source clock divided by 6 */ +#define RCU_PREDV0_DIV7 CFG1_PREDV0(6) /*!< PREDV0 input source clock divided by 7 */ +#define RCU_PREDV0_DIV8 CFG1_PREDV0(7) /*!< PREDV0 input source clock divided by 8 */ +#define RCU_PREDV0_DIV9 CFG1_PREDV0(8) /*!< PREDV0 input source clock divided by 9 */ +#define RCU_PREDV0_DIV10 CFG1_PREDV0(9) /*!< PREDV0 input source clock divided by 10 */ +#define RCU_PREDV0_DIV11 CFG1_PREDV0(10) /*!< PREDV0 input source clock divided by 11 */ +#define RCU_PREDV0_DIV12 CFG1_PREDV0(11) /*!< PREDV0 input source clock divided by 12 */ +#define RCU_PREDV0_DIV13 CFG1_PREDV0(12) /*!< PREDV0 input source clock divided by 13 */ +#define RCU_PREDV0_DIV14 CFG1_PREDV0(13) /*!< PREDV0 input source clock divided by 14 */ +#define RCU_PREDV0_DIV15 CFG1_PREDV0(14) /*!< PREDV0 input source clock divided by 15 */ +#define RCU_PREDV0_DIV16 CFG1_PREDV0(15) /*!< PREDV0 input source clock divided by 16 */ + +/* PREDV1 division factor */ +#define CFG1_PREDV1(regval) (BITS(4,7) & ((uint32_t)(regval) << 4)) +#define RCU_PREDV1_DIV1 CFG1_PREDV1(0) /*!< PREDV1 input source clock divided by 1 */ +#define RCU_PREDV1_DIV2 CFG1_PREDV1(1) /*!< PREDV1 input source clock divided by 2 */ +#define RCU_PREDV1_DIV3 CFG1_PREDV1(2) /*!< PREDV1 input source clock divided by 3 */ +#define RCU_PREDV1_DIV4 CFG1_PREDV1(3) /*!< PREDV1 input source clock divided by 4 */ +#define RCU_PREDV1_DIV5 CFG1_PREDV1(4) /*!< PREDV1 input source clock divided by 5 */ +#define RCU_PREDV1_DIV6 CFG1_PREDV1(5) /*!< PREDV1 input source clock divided by 6 */ +#define RCU_PREDV1_DIV7 CFG1_PREDV1(6) /*!< PREDV1 input source clock divided by 7 */ +#define RCU_PREDV1_DIV8 CFG1_PREDV1(7) /*!< PREDV1 input source clock divided by 8 */ +#define RCU_PREDV1_DIV9 CFG1_PREDV1(8) /*!< PREDV1 input source clock divided by 9 */ +#define RCU_PREDV1_DIV10 CFG1_PREDV1(9) /*!< PREDV1 input source clock divided by 10 */ +#define RCU_PREDV1_DIV11 CFG1_PREDV1(10) /*!< PREDV1 input source clock divided by 11 */ +#define RCU_PREDV1_DIV12 CFG1_PREDV1(11) /*!< PREDV1 input source clock divided by 12 */ +#define RCU_PREDV1_DIV13 CFG1_PREDV1(12) /*!< PREDV1 input source clock divided by 13 */ +#define RCU_PREDV1_DIV14 CFG1_PREDV1(13) /*!< PREDV1 input source clock divided by 14 */ +#define RCU_PREDV1_DIV15 CFG1_PREDV1(14) /*!< PREDV1 input source clock divided by 15 */ +#define RCU_PREDV1_DIV16 CFG1_PREDV1(15) /*!< PREDV1 input source clock divided by 16 */ + +/* PLL1 clock multiplication factor */ +#define CFG1_PLL1MF(regval) (BITS(8,11) & ((uint32_t)(regval) << 8)) +#define RCU_PLL1_MUL8 CFG1_PLL1MF(6) /*!< PLL1 source clock multiply by 8 */ +#define RCU_PLL1_MUL9 CFG1_PLL1MF(7) /*!< PLL1 source clock multiply by 9 */ +#define RCU_PLL1_MUL10 CFG1_PLL1MF(8) /*!< PLL1 source clock multiply by 10 */ +#define RCU_PLL1_MUL11 CFG1_PLL1MF(9) /*!< PLL1 source clock multiply by 11 */ +#define RCU_PLL1_MUL12 CFG1_PLL1MF(10) /*!< PLL1 source clock multiply by 12 */ +#define RCU_PLL1_MUL13 CFG1_PLL1MF(11) /*!< PLL1 source clock multiply by 13 */ +#define RCU_PLL1_MUL14 CFG1_PLL1MF(12) /*!< PLL1 source clock multiply by 14 */ +#define RCU_PLL1_MUL15 CFG1_PLL1MF(13) /*!< PLL1 source clock multiply by 15 */ +#define RCU_PLL1_MUL16 CFG1_PLL1MF(14) /*!< PLL1 source clock multiply by 16 */ +#define RCU_PLL1_MUL20 CFG1_PLL1MF(15) /*!< PLL1 source clock multiply by 20 */ + +/* PLL2 clock multiplication factor */ +#define CFG1_PLL2MF(regval) (BITS(12,15) & ((uint32_t)(regval) << 12)) +#define RCU_PLL2_MUL8 CFG1_PLL2MF(6) /*!< PLL2 source clock multiply by 8 */ +#define RCU_PLL2_MUL9 CFG1_PLL2MF(7) /*!< PLL2 source clock multiply by 9 */ +#define RCU_PLL2_MUL10 CFG1_PLL2MF(8) /*!< PLL2 source clock multiply by 10 */ +#define RCU_PLL2_MUL11 CFG1_PLL2MF(9) /*!< PLL2 source clock multiply by 11 */ +#define RCU_PLL2_MUL12 CFG1_PLL2MF(10) /*!< PLL2 source clock multiply by 12 */ +#define RCU_PLL2_MUL13 CFG1_PLL2MF(11) /*!< PLL2 source clock multiply by 13 */ +#define RCU_PLL2_MUL14 CFG1_PLL2MF(12) /*!< PLL2 source clock multiply by 14 */ +#define RCU_PLL2_MUL15 CFG1_PLL2MF(13) /*!< PLL2 source clock multiply by 15 */ +#define RCU_PLL2_MUL16 CFG1_PLL2MF(14) /*!< PLL2 source clock multiply by 16 */ +#define RCU_PLL2_MUL20 CFG1_PLL2MF(15) /*!< PLL2 source clock multiply by 20 */ + +/* PREDV0 input clock source selection */ +#define RCU_PREDV0SRC_HXTAL ((uint32_t)0x00000000U) /*!< HXTAL selected as PREDV0 input source clock */ +#define RCU_PREDV0SRC_CKPLL1 RCU_CFG1_PREDV0SEL /*!< CK_PLL1 selected as PREDV0 input source clock */ + +/* I2S1 clock source selection */ +#define RCU_I2S1SRC_CKSYS ((uint32_t)0x00000000U) /*!< system clock selected as I2S1 source clock */ +#define RCU_I2S1SRC_CKPLL2_MUL2 RCU_CFG1_I2S1SEL /*!< (CK_PLL2 x 2) selected as I2S1 source clock */ + +/* I2S2 clock source selection */ +#define RCU_I2S2SRC_CKSYS ((uint32_t)0x00000000U) /*!< system clock selected as I2S2 source clock */ +#define RCU_I2S2SRC_CKPLL2_MUL2 RCU_CFG1_I2S2SEL /*!< (CK_PLL2 x 2) selected as I2S2 source clock */ + +/* deep-sleep mode voltage */ +#define DSV_DSLPVS(regval) (BITS(0,2) & ((uint32_t)(regval) << 0)) +#define RCU_DEEPSLEEP_V_1_2 DSV_DSLPVS(0) /*!< core voltage is 1.2V in deep-sleep mode */ +#define RCU_DEEPSLEEP_V_1_1 DSV_DSLPVS(1) /*!< core voltage is 1.1V in deep-sleep mode */ +#define RCU_DEEPSLEEP_V_1_0 DSV_DSLPVS(2) /*!< core voltage is 1.0V in deep-sleep mode */ +#define RCU_DEEPSLEEP_V_0_9 DSV_DSLPVS(3) /*!< core voltage is 0.9V in deep-sleep mode */ + + +/* CKOUT0 division factor */ +#define CFG2_CKOUT0DIV(regval) (BITS(0,5) & ((uint32_t)(regval) << 0)) +#define RCU_CKOUT0_DIV1 CFG2_CKOUT0DIV(0) /*!< CK_OUT0 is divided by 1 */ +#define RCU_CKOUT0_DIV2 CFG2_CKOUT0DIV(1) /*!< CK_OUT0 is divided by 2 */ +#define RCU_CKOUT0_DIV3 CFG2_CKOUT0DIV(2) /*!< CK_OUT0 is divided by 3 */ +#define RCU_CKOUT0_DIV4 CFG2_CKOUT0DIV(3) /*!< CK_OUT0 is divided by 4 */ +#define RCU_CKOUT0_DIV5 CFG2_CKOUT0DIV(4) /*!< CK_OUT0 is divided by 5 */ +#define RCU_CKOUT0_DIV6 CFG2_CKOUT0DIV(5) /*!< CK_OUT0 is divided by 6 */ +#define RCU_CKOUT0_DIV7 CFG2_CKOUT0DIV(6) /*!< CK_OUT0 is divided by 7 */ +#define RCU_CKOUT0_DIV8 CFG2_CKOUT0DIV(7) /*!< CK_OUT0 is divided by 8 */ +#define RCU_CKOUT0_DIV9 CFG2_CKOUT0DIV(8) /*!< CK_OUT0 is divided by 9 */ +#define RCU_CKOUT0_DIV10 CFG2_CKOUT0DIV(9) /*!< CK_OUT0 is divided by 10 */ +#define RCU_CKOUT0_DIV11 CFG2_CKOUT0DIV(10) /*!< CK_OUT0 is divided by 11 */ +#define RCU_CKOUT0_DIV12 CFG2_CKOUT0DIV(11) /*!< CK_OUT0 is divided by 12 */ +#define RCU_CKOUT0_DIV13 CFG2_CKOUT0DIV(12) /*!< CK_OUT0 is divided by 13 */ +#define RCU_CKOUT0_DIV14 CFG2_CKOUT0DIV(13) /*!< CK_OUT0 is divided by 14 */ +#define RCU_CKOUT0_DIV15 CFG2_CKOUT0DIV(14) /*!< CK_OUT0 is divided by 15 */ +#define RCU_CKOUT0_DIV16 CFG2_CKOUT0DIV(15) /*!< CK_OUT0 is divided by 16 */ +#define RCU_CKOUT0_DIV17 CFG2_CKOUT0DIV(16) /*!< CK_OUT0 is divided by 17 */ +#define RCU_CKOUT0_DIV18 CFG2_CKOUT0DIV(17) /*!< CK_OUT0 is divided by 18 */ +#define RCU_CKOUT0_DIV19 CFG2_CKOUT0DIV(18) /*!< CK_OUT0 is divided by 19 */ +#define RCU_CKOUT0_DIV20 CFG2_CKOUT0DIV(19) /*!< CK_OUT0 is divided by 20 */ +#define RCU_CKOUT0_DIV21 CFG2_CKOUT0DIV(20) /*!< CK_OUT0 is divided by 21 */ +#define RCU_CKOUT0_DIV22 CFG2_CKOUT0DIV(21) /*!< CK_OUT0 is divided by 22 */ +#define RCU_CKOUT0_DIV23 CFG2_CKOUT0DIV(22) /*!< CK_OUT0 is divided by 23 */ +#define RCU_CKOUT0_DIV24 CFG2_CKOUT0DIV(23) /*!< CK_OUT0 is divided by 24 */ +#define RCU_CKOUT0_DIV25 CFG2_CKOUT0DIV(24) /*!< CK_OUT0 is divided by 25 */ +#define RCU_CKOUT0_DIV26 CFG2_CKOUT0DIV(25) /*!< CK_OUT0 is divided by 26 */ +#define RCU_CKOUT0_DIV27 CFG2_CKOUT0DIV(26) /*!< CK_OUT0 is divided by 27 */ +#define RCU_CKOUT0_DIV28 CFG2_CKOUT0DIV(27) /*!< CK_OUT0 is divided by 28 */ +#define RCU_CKOUT0_DIV29 CFG2_CKOUT0DIV(28) /*!< CK_OUT0 is divided by 29 */ +#define RCU_CKOUT0_DIV30 CFG2_CKOUT0DIV(29) /*!< CK_OUT0 is divided by 30 */ +#define RCU_CKOUT0_DIV31 CFG2_CKOUT0DIV(30) /*!< CK_OUT0 is divided by 31 */ +#define RCU_CKOUT0_DIV32 CFG2_CKOUT0DIV(31) /*!< CK_OUT0 is divided by 32 */ +#define RCU_CKOUT0_DIV33 CFG2_CKOUT0DIV(32) /*!< CK_OUT0 is divided by 33 */ +#define RCU_CKOUT0_DIV34 CFG2_CKOUT0DIV(33) /*!< CK_OUT0 is divided by 34 */ +#define RCU_CKOUT0_DIV35 CFG2_CKOUT0DIV(34) /*!< CK_OUT0 is divided by 35 */ +#define RCU_CKOUT0_DIV36 CFG2_CKOUT0DIV(35) /*!< CK_OUT0 is divided by 36 */ +#define RCU_CKOUT0_DIV37 CFG2_CKOUT0DIV(36) /*!< CK_OUT0 is divided by 37 */ +#define RCU_CKOUT0_DIV38 CFG2_CKOUT0DIV(37) /*!< CK_OUT0 is divided by 38 */ +#define RCU_CKOUT0_DIV39 CFG2_CKOUT0DIV(38) /*!< CK_OUT0 is divided by 39 */ +#define RCU_CKOUT0_DIV40 CFG2_CKOUT0DIV(39) /*!< CK_OUT0 is divided by 40 */ +#define RCU_CKOUT0_DIV41 CFG2_CKOUT0DIV(40) /*!< CK_OUT0 is divided by 41 */ +#define RCU_CKOUT0_DIV42 CFG2_CKOUT0DIV(41) /*!< CK_OUT0 is divided by 42 */ +#define RCU_CKOUT0_DIV43 CFG2_CKOUT0DIV(42) /*!< CK_OUT0 is divided by 43 */ +#define RCU_CKOUT0_DIV44 CFG2_CKOUT0DIV(43) /*!< CK_OUT0 is divided by 44 */ +#define RCU_CKOUT0_DIV45 CFG2_CKOUT0DIV(44) /*!< CK_OUT0 is divided by 45 */ +#define RCU_CKOUT0_DIV46 CFG2_CKOUT0DIV(45) /*!< CK_OUT0 is divided by 46 */ +#define RCU_CKOUT0_DIV47 CFG2_CKOUT0DIV(46) /*!< CK_OUT0 is divided by 47 */ +#define RCU_CKOUT0_DIV48 CFG2_CKOUT0DIV(47) /*!< CK_OUT0 is divided by 48 */ +#define RCU_CKOUT0_DIV49 CFG2_CKOUT0DIV(48) /*!< CK_OUT0 is divided by 49 */ +#define RCU_CKOUT0_DIV50 CFG2_CKOUT0DIV(49) /*!< CK_OUT0 is divided by 20 */ +#define RCU_CKOUT0_DIV51 CFG2_CKOUT0DIV(40) /*!< CK_OUT0 is divided by 51 */ +#define RCU_CKOUT0_DIV52 CFG2_CKOUT0DIV(51) /*!< CK_OUT0 is divided by 52 */ +#define RCU_CKOUT0_DIV53 CFG2_CKOUT0DIV(52) /*!< CK_OUT0 is divided by 53 */ +#define RCU_CKOUT0_DIV54 CFG2_CKOUT0DIV(53) /*!< CK_OUT0 is divided by 54 */ +#define RCU_CKOUT0_DIV55 CFG2_CKOUT0DIV(54) /*!< CK_OUT0 is divided by 55 */ +#define RCU_CKOUT0_DIV56 CFG2_CKOUT0DIV(55) /*!< CK_OUT0 is divided by 56 */ +#define RCU_CKOUT0_DIV57 CFG2_CKOUT0DIV(56) /*!< CK_OUT0 is divided by 57 */ +#define RCU_CKOUT0_DIV58 CFG2_CKOUT0DIV(57) /*!< CK_OUT0 is divided by 58 */ +#define RCU_CKOUT0_DIV59 CFG2_CKOUT0DIV(58) /*!< CK_OUT0 is divided by 59 */ +#define RCU_CKOUT0_DIV60 CFG2_CKOUT0DIV(59) /*!< CK_OUT0 is divided by 60 */ +#define RCU_CKOUT0_DIV61 CFG2_CKOUT0DIV(60) /*!< CK_OUT0 is divided by 61 */ +#define RCU_CKOUT0_DIV62 CFG2_CKOUT0DIV(61) /*!< CK_OUT0 is divided by 62 */ +#define RCU_CKOUT0_DIV63 CFG2_CKOUT0DIV(62) /*!< CK_OUT0 is divided by 63 */ +#define RCU_CKOUT0_DIV64 CFG2_CKOUT0DIV(63) /*!< CK_OUT0 is divided by 64 */ + +/* CKOUT1 division factor */ +#define CFG2_CKOUT1DIV(regval) (BITS(8,13) & ((uint32_t)(regval) << 8)) +#define RCU_CKOUT1_DIV1 CFG2_CKOUT1DIV(0) /*!< CK_OUT1 is divided by 1 */ +#define RCU_CKOUT1_DIV2 CFG2_CKOUT1DIV(1) /*!< CK_OUT1 is divided by 2 */ +#define RCU_CKOUT1_DIV3 CFG2_CKOUT1DIV(2) /*!< CK_OUT1 is divided by 3 */ +#define RCU_CKOUT1_DIV4 CFG2_CKOUT1DIV(3) /*!< CK_OUT1 is divided by 4 */ +#define RCU_CKOUT1_DIV5 CFG2_CKOUT1DIV(4) /*!< CK_OUT1 is divided by 5 */ +#define RCU_CKOUT1_DIV6 CFG2_CKOUT1DIV(5) /*!< CK_OUT1 is divided by 6 */ +#define RCU_CKOUT1_DIV7 CFG2_CKOUT1DIV(6) /*!< CK_OUT1 is divided by 7 */ +#define RCU_CKOUT1_DIV8 CFG2_CKOUT1DIV(7) /*!< CK_OUT1 is divided by 8 */ +#define RCU_CKOUT1_DIV9 CFG2_CKOUT1DIV(8) /*!< CK_OUT1 is divided by 9 */ +#define RCU_CKOUT1_DIV10 CFG2_CKOUT1DIV(9) /*!< CK_OUT1 is divided by 10 */ +#define RCU_CKOUT1_DIV11 CFG2_CKOUT1DIV(10) /*!< CK_OUT1 is divided by 11 */ +#define RCU_CKOUT1_DIV12 CFG2_CKOUT1DIV(11) /*!< CK_OUT1 is divided by 12 */ +#define RCU_CKOUT1_DIV13 CFG2_CKOUT1DIV(12) /*!< CK_OUT1 is divided by 13 */ +#define RCU_CKOUT1_DIV14 CFG2_CKOUT1DIV(13) /*!< CK_OUT1 is divided by 14 */ +#define RCU_CKOUT1_DIV15 CFG2_CKOUT1DIV(14) /*!< CK_OUT1 is divided by 15 */ +#define RCU_CKOUT1_DIV16 CFG2_CKOUT1DIV(15) /*!< CK_OUT1 is divided by 16 */ +#define RCU_CKOUT1_DIV17 CFG2_CKOUT1DIV(16) /*!< CK_OUT1 is divided by 17 */ +#define RCU_CKOUT1_DIV18 CFG2_CKOUT1DIV(17) /*!< CK_OUT1 is divided by 18 */ +#define RCU_CKOUT1_DIV19 CFG2_CKOUT1DIV(18) /*!< CK_OUT1 is divided by 19 */ +#define RCU_CKOUT1_DIV20 CFG2_CKOUT1DIV(19) /*!< CK_OUT1 is divided by 20 */ +#define RCU_CKOUT1_DIV21 CFG2_CKOUT1DIV(20) /*!< CK_OUT1 is divided by 21 */ +#define RCU_CKOUT1_DIV22 CFG2_CKOUT1DIV(21) /*!< CK_OUT1 is divided by 22 */ +#define RCU_CKOUT1_DIV23 CFG2_CKOUT1DIV(22) /*!< CK_OUT1 is divided by 23 */ +#define RCU_CKOUT1_DIV24 CFG2_CKOUT1DIV(23) /*!< CK_OUT1 is divided by 24 */ +#define RCU_CKOUT1_DIV25 CFG2_CKOUT1DIV(24) /*!< CK_OUT1 is divided by 25 */ +#define RCU_CKOUT1_DIV26 CFG2_CKOUT1DIV(25) /*!< CK_OUT1 is divided by 26 */ +#define RCU_CKOUT1_DIV27 CFG2_CKOUT1DIV(26) /*!< CK_OUT1 is divided by 27 */ +#define RCU_CKOUT1_DIV28 CFG2_CKOUT1DIV(27) /*!< CK_OUT1 is divided by 28 */ +#define RCU_CKOUT1_DIV29 CFG2_CKOUT1DIV(28) /*!< CK_OUT1 is divided by 29 */ +#define RCU_CKOUT1_DIV30 CFG2_CKOUT1DIV(29) /*!< CK_OUT1 is divided by 30 */ +#define RCU_CKOUT1_DIV31 CFG2_CKOUT1DIV(30) /*!< CK_OUT1 is divided by 31 */ +#define RCU_CKOUT1_DIV32 CFG2_CKOUT1DIV(31) /*!< CK_OUT1 is divided by 32 */ +#define RCU_CKOUT1_DIV33 CFG2_CKOUT1DIV(32) /*!< CK_OUT1 is divided by 33 */ +#define RCU_CKOUT1_DIV34 CFG2_CKOUT1DIV(33) /*!< CK_OUT1 is divided by 34 */ +#define RCU_CKOUT1_DIV35 CFG2_CKOUT1DIV(34) /*!< CK_OUT1 is divided by 35 */ +#define RCU_CKOUT1_DIV36 CFG2_CKOUT1DIV(35) /*!< CK_OUT1 is divided by 36 */ +#define RCU_CKOUT1_DIV37 CFG2_CKOUT1DIV(36) /*!< CK_OUT1 is divided by 37 */ +#define RCU_CKOUT1_DIV38 CFG2_CKOUT1DIV(37) /*!< CK_OUT1 is divided by 38 */ +#define RCU_CKOUT1_DIV39 CFG2_CKOUT1DIV(38) /*!< CK_OUT1 is divided by 39 */ +#define RCU_CKOUT1_DIV40 CFG2_CKOUT1DIV(39) /*!< CK_OUT1 is divided by 40 */ +#define RCU_CKOUT1_DIV41 CFG2_CKOUT1DIV(40) /*!< CK_OUT1 is divided by 41 */ +#define RCU_CKOUT1_DIV42 CFG2_CKOUT1DIV(41) /*!< CK_OUT1 is divided by 42 */ +#define RCU_CKOUT1_DIV43 CFG2_CKOUT1DIV(42) /*!< CK_OUT1 is divided by 43 */ +#define RCU_CKOUT1_DIV44 CFG2_CKOUT1DIV(43) /*!< CK_OUT1 is divided by 44 */ +#define RCU_CKOUT1_DIV45 CFG2_CKOUT1DIV(44) /*!< CK_OUT1 is divided by 45 */ +#define RCU_CKOUT1_DIV46 CFG2_CKOUT1DIV(45) /*!< CK_OUT1 is divided by 46 */ +#define RCU_CKOUT1_DIV47 CFG2_CKOUT1DIV(46) /*!< CK_OUT1 is divided by 47 */ +#define RCU_CKOUT1_DIV48 CFG2_CKOUT1DIV(47) /*!< CK_OUT1 is divided by 48 */ +#define RCU_CKOUT1_DIV49 CFG2_CKOUT1DIV(48) /*!< CK_OUT1 is divided by 49 */ +#define RCU_CKOUT1_DIV50 CFG2_CKOUT1DIV(49) /*!< CK_OUT1 is divided by 20 */ +#define RCU_CKOUT1_DIV51 CFG2_CKOUT1DIV(40) /*!< CK_OUT1 is divided by 51 */ +#define RCU_CKOUT1_DIV52 CFG2_CKOUT1DIV(51) /*!< CK_OUT1 is divided by 52 */ +#define RCU_CKOUT1_DIV53 CFG2_CKOUT1DIV(52) /*!< CK_OUT1 is divided by 53 */ +#define RCU_CKOUT1_DIV54 CFG2_CKOUT1DIV(53) /*!< CK_OUT1 is divided by 54 */ +#define RCU_CKOUT1_DIV55 CFG2_CKOUT1DIV(54) /*!< CK_OUT1 is divided by 55 */ +#define RCU_CKOUT1_DIV56 CFG2_CKOUT1DIV(55) /*!< CK_OUT1 is divided by 56 */ +#define RCU_CKOUT1_DIV57 CFG2_CKOUT1DIV(56) /*!< CK_OUT1 is divided by 57 */ +#define RCU_CKOUT1_DIV58 CFG2_CKOUT1DIV(57) /*!< CK_OUT1 is divided by 58 */ +#define RCU_CKOUT1_DIV59 CFG2_CKOUT1DIV(58) /*!< CK_OUT1 is divided by 59 */ +#define RCU_CKOUT1_DIV60 CFG2_CKOUT1DIV(59) /*!< CK_OUT1 is divided by 60 */ +#define RCU_CKOUT1_DIV61 CFG2_CKOUT1DIV(60) /*!< CK_OUT1 is divided by 61 */ +#define RCU_CKOUT1_DIV62 CFG2_CKOUT1DIV(61) /*!< CK_OUT1 is divided by 62 */ +#define RCU_CKOUT1_DIV63 CFG2_CKOUT1DIV(62) /*!< CK_OUT1 is divided by 63 */ +#define RCU_CKOUT1_DIV64 CFG2_CKOUT1DIV(63) /*!< CK_OUT1 is divided by 64 */ + +/* CKOUT1 Clock source selection */ +#define CFG2_CKOUT1SEL(regval) (BITS(16,19) & ((uint32_t)(regval) << 16)) +#define RCU_CKOUT1SRC_NONE CFG2_CKOUT1SEL(0) /*!< no clock selected */ +#define RCU_CKOUT1SRC_CKSYS CFG2_CKOUT1SEL(4) /*!< system clock selected */ +#define RCU_CKOUT1SRC_IRC8M CFG2_CKOUT1SEL(5) /*!< internal 8M RC oscillator clock selected */ +#define RCU_CKOUT1SRC_HXTAL CFG2_CKOUT1SEL(6) /*!< high speed crystal oscillator clock (HXTAL) selected */ +#define RCU_CKOUT1SRC_CKPLL_DIV2 CFG2_CKOUT1SEL(7) /*!< CK_PLL/2 clock selected */ +#define RCU_CKOUT1SRC_CKPLL1 CFG2_CKOUT1SEL(8) /*!< CK_PLL1 clock selected */ +#define RCU_CKOUT1SRC_CKPLL2_DIV2 CFG2_CKOUT1SEL(9) /*!< CK_PLL2/2 clock selected */ +#define RCU_CKOUT1SRC_EXT1 CFG2_CKOUT1SEL(10) /*!< EXT1 selected, to provide the external clock for ENET */ +#define RCU_CKOUT1SRC_CKPLL2 CFG2_CKOUT1SEL(11) /*!< CK_PLL2 clock selected */ + +/* PLLT division factor */ +#define PLLTCFG_PLLTPSC(regval) (BITS(0,5) & ((uint32_t)(regval) << 0)) + +/* PLLT clock multiplication factor for VCO */ +#define PLLTCFG_PLLTMF(regval) (BITS(6,14) & ((uint32_t)(regval) << 6)) + +/* TLI prescaler select */ +#define PLLTCFG_TLIPSC(regval) (BITS(16,17) & ((uint32_t)(regval) << 16)) +#define RCU_CKTLI_CKPLLTR_DIV2 PLLTCFG_TLIPSC(0) /*!< TLI prescaler select CK_PLLTR/2 */ +#define RCU_CKTLI_CKPLLTR_DIV4 PLLTCFG_TLIPSC(1) /*!< TLI prescaler select CK_PLLTR/4 */ +#define RCU_CKTLI_CKPLLTR_DIV8 PLLTCFG_TLIPSC(2) /*!< TLI prescaler select CK_PLLTR/8 */ +#define RCU_CKTLI_CKPLLTR_DIV16 PLLTCFG_TLIPSC(3) /*!< TLI prescaler select CK_PLLTR/16 */ + +/* PLLTR division factor */ +#define PLLTCFG_PLLTRPSC(regval) (BITS(28,30) & ((uint32_t)(regval) << 28)) + +/* PLLT clock source selection */ +#define RCU_PLLTSRC_IRC8M ((uint32_t)0x00000000U) /*!< IRC8M selected as source clock of PLLT */ +#define RCU_PLLTSRC_HXTAL RCU_PLLTCFG_PLLTSEL /*!< HXTAL selected as source clock of PLLT */ + +/* function declarations */ +/* initialization, peripheral clock enable/disable functions */ +/* deinitialize the RCU */ +void rcu_deinit(void); +/* enable the peripherals clock */ +void rcu_periph_clock_enable(rcu_periph_enum periph); +/* disable the peripherals clock */ +void rcu_periph_clock_disable(rcu_periph_enum periph); +/* enable the peripherals clock when sleep mode */ +void rcu_periph_clock_sleep_enable(rcu_periph_sleep_enum periph); +/* disable the peripherals clock when sleep mode */ +void rcu_periph_clock_sleep_disable(rcu_periph_sleep_enum periph); +/* reset the peripherals */ +void rcu_periph_reset_enable(rcu_periph_reset_enum periph_reset); +/* disable reset the peripheral */ +void rcu_periph_reset_disable(rcu_periph_reset_enum periph_reset); +/* reset the BKP domain */ +void rcu_bkp_reset_enable(void); +/* disable the BKP domain reset */ +void rcu_bkp_reset_disable(void); + +/* clock configuration functions */ +/* configure the system clock source */ +void rcu_system_clock_source_config(uint32_t ck_sys); +/* get the system clock source */ +uint32_t rcu_system_clock_source_get(void); +/* configure the AHB prescaler selection */ +void rcu_ahb_clock_config(uint32_t ck_ahb); +/* configure the APB1 prescaler selection */ +void rcu_apb1_clock_config(uint32_t ck_apb1); +/* configure the APB2 prescaler selection */ +void rcu_apb2_clock_config(uint32_t ck_apb2); + +/* configure the CK_OUT0 clock source and divider */ +void rcu_ckout0_config(uint32_t ckout0_src, uint32_t ckout0_div); +/* configure the CK_OUT1 clock source and divider */ +void rcu_ckout1_config(uint32_t ckout1_src, uint32_t ckout1_div); + +/* configure the PLL clock source selection and PLL multiply factor */ +void rcu_pll_config(uint32_t pll_src, uint32_t pll_mul); + +/* configure the PREDV0 division factor and clock source */ +void rcu_predv0_config(uint32_t predv0_source, uint32_t predv0_div); +/* configure the PREDV1 division factor */ +void rcu_predv1_config(uint32_t predv1_div); +/* configure the PLL1 clock */ +void rcu_pll1_config(uint32_t pll_mul); +/* configure the PLL2 clock */ +void rcu_pll2_config(uint32_t pll_mul); + +/* peripheral clock configuration functions */ +/* configure the ADC division factor */ +void rcu_adc_clock_config(uint32_t adc_psc); +/* configure the USBFS/TRNG prescaler factor */ +void rcu_usbfs_trng_clock_config(uint32_t usbfs_trng_psc); +/* configure the RTC clock source selection */ +void rcu_rtc_clock_config(uint32_t rtc_clock_source); +/* configure the I2S1 clock source selection */ +void rcu_i2s1_clock_config(uint32_t i2s_clock_source); +/* configure the I2S2 clock source selection */ +void rcu_i2s2_clock_config(uint32_t i2s_clock_source); + +/* configure the PLLT clock selection */ +void rcu_pllt_config(uint32_t pllt_src); +/* Configure the PLLT clock multiplication and division factors */ +ErrStatus rcu_pllt_vco_config(uint32_t pllt_psc, uint32_t pllt_mul, uint32_t ppltr_psc); +/* configure the TLI prescaler factor */ +void rcu_tli_clock_config(uint32_t tli_psc); + +/* get the clock stabilization and periphral reset flags */ +FlagStatus rcu_flag_get(rcu_flag_enum flag); +/* clear the reset flag */ +void rcu_all_reset_flag_clear(void); +/* get the clock stabilization interrupt and ckm flags */ +FlagStatus rcu_interrupt_flag_get(rcu_int_flag_enum int_flag); +/* clear the interrupt flags */ +void rcu_interrupt_flag_clear(rcu_int_flag_clear_enum int_flag_clear); +/* enable the stabilization interrupt */ +void rcu_interrupt_enable(rcu_int_enum stab_int); +/* disable the stabilization interrupt */ +void rcu_interrupt_disable(rcu_int_enum stab_int); + +/* configure the LXTAL drive capability */ +void rcu_lxtal_drive_capability_config(uint32_t lxtal_dricap); +/* wait for oscillator stabilization flags is SET or oscillator startup is timeout */ +ErrStatus rcu_osci_stab_wait(rcu_osci_type_enum osci); +/* turn on the oscillator */ +void rcu_osci_on(rcu_osci_type_enum osci); +/* turn off the oscillator */ +void rcu_osci_off(rcu_osci_type_enum osci); +/* enable the oscillator bypass mode, HXTALEN or LXTALEN must be reset before it */ +void rcu_osci_bypass_mode_enable(rcu_osci_type_enum osci); +/* disable the oscillator bypass mode, HXTALEN or LXTALEN must be reset before it */ +void rcu_osci_bypass_mode_disable(rcu_osci_type_enum osci); +/* enable the HXTAL clock monitor */ +void rcu_hxtal_clock_monitor_enable(void); +/* disable the HXTAL clock monitor */ +void rcu_hxtal_clock_monitor_disable(void); + +/* set the IRC8M adjust value */ +void rcu_irc8m_adjust_value_set(uint8_t irc8m_adjval); + +/* set the deep sleep mode voltage */ +void rcu_deepsleep_voltage_set(uint32_t dsvol); + +/* get the system clock, bus and peripheral clock frequency */ +uint32_t rcu_clock_freq_get(rcu_clock_freq_enum clock); + +#endif /* GD32F20X_RCU_H */ diff --git a/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_standard_peripheral/Include/gd32f20x_rtc.h b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_standard_peripheral/Include/gd32f20x_rtc.h new file mode 100644 index 0000000000..14e51f6abf --- /dev/null +++ b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_standard_peripheral/Include/gd32f20x_rtc.h @@ -0,0 +1,151 @@ +/*! + \file gd32f20x_rtc.h + \brief definitions for the RTC + + \version 2015-07-15, V1.0.0, firmware for GD32F20x + \version 2017-06-05, V2.0.0, firmware for GD32F20x + \version 2018-10-31, V2.1.0, firmware for GD32F20x + \version 2020-09-30, V2.2.0, firmware for GD32F20x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef GD32F20X_RTC_H +#define GD32F20X_RTC_H + +#include "gd32f20x.h" + +/* RTC definitions */ +#define RTC RTC_BASE + +/* registers definitions */ +#define RTC_INTEN REG32(RTC + 0x00U) /*!< interrupt enable register */ +#define RTC_CTL REG32(RTC + 0x04U) /*!< control register */ +#define RTC_PSCH REG32(RTC + 0x08U) /*!< prescaler high register */ +#define RTC_PSCL REG32(RTC + 0x0CU) /*!< prescaler low register */ +#define RTC_DIVH REG32(RTC + 0x10U) /*!< divider high register */ +#define RTC_DIVL REG32(RTC + 0x14U) /*!< divider low register */ +#define RTC_CNTH REG32(RTC + 0x18U) /*!< counter high register */ +#define RTC_CNTL REG32(RTC + 0x1CU) /*!< counter low register */ +#define RTC_ALRMH REG32(RTC + 0x20U) /*!< alarm high register */ +#define RTC_ALRML REG32(RTC + 0x24U) /*!< alarm low register */ + +/* bits definitions */ +/* RTC_INTEN */ +#define RTC_INTEN_SCIE BIT(0) /*!< second interrupt enable */ +#define RTC_INTEN_ALRMIE BIT(1) /*!< alarm interrupt enable */ +#define RTC_INTEN_OVIE BIT(2) /*!< overflow interrupt enable */ + +/* RTC_CTL */ +#define RTC_CTL_SCIF BIT(0) /*!< second interrupt flag */ +#define RTC_CTL_ALRMIF BIT(1) /*!< alarm interrupt flag */ +#define RTC_CTL_OVIF BIT(2) /*!< overflow interrupt flag */ +#define RTC_CTL_RSYNF BIT(3) /*!< registers synchronized flag */ +#define RTC_CTL_CMF BIT(4) /*!< configuration mode flag */ +#define RTC_CTL_LWOFF BIT(5) /*!< last write operation finished flag */ + +/* RTC_PSCH */ +#define RTC_PSCH_PSC BITS(0,3) /*!< prescaler high value */ + +/* RTC_PSCL */ +#define RTC_PSCL_PSC BITS(0,15) /*!< prescaler low value */ + +/* RTC_DIVH */ +#define RTC_DIVH_DIV BITS(0,3) /*!< divider high value */ + +/* RTC_DIVL */ +#define RTC_DIVL_DIV BITS(0,15) /*!< divider low value */ + +/* RTC_CNTH */ +#define RTC_CNTH_CNT BITS(0,15) /*!< counter high value */ + +/* RTC_CNTL */ +#define RTC_CNTL_CNT BITS(0,15) /*!< counter low value */ + +/* RTC_ALRMH */ +#define RTC_ALRMH_ALRM BITS(0,15) /*!< alarm high value */ + +/* RTC_ALRML */ +#define RTC_ALRML_ALRM BITS(0,15) /*!< alarm low value */ + +/* constants definitions */ +/* RTC interrupt enable or disable definitions */ +#define RTC_INT_SECOND RTC_INTEN_SCIE /*!< second interrupt enable */ +#define RTC_INT_ALARM RTC_INTEN_ALRMIE /*!< alarm interrupt enable */ +#define RTC_INT_OVERFLOW RTC_INTEN_OVIE /*!< overflow interrupt enable */ + +/* RTC interrupt flag definitions */ +#define RTC_INT_FLAG_SECOND RTC_CTL_SCIF /*!< second interrupt flag */ +#define RTC_INT_FLAG_ALARM RTC_CTL_ALRMIF /*!< alarm interrupt flag */ +#define RTC_INT_FLAG_OVERFLOW RTC_CTL_OVIF /*!< overflow interrupt flag */ + +/* RTC flag definitions */ +#define RTC_FLAG_SECOND RTC_CTL_SCIF /*!< second interrupt flag */ +#define RTC_FLAG_ALARM RTC_CTL_ALRMIF /*!< alarm interrupt flag */ +#define RTC_FLAG_OVERFLOW RTC_CTL_OVIF /*!< overflow interrupt flag */ +#define RTC_FLAG_RSYN RTC_CTL_RSYNF /*!< registers synchronized flag */ +#define RTC_FLAG_LWOF RTC_CTL_LWOFF /*!< last write operation finished flag */ + +/* function declarations */ +/* initialization functions */ +/* enter RTC configuration mode */ +void rtc_configuration_mode_enter(void); +/* exit RTC configuration mode */ +void rtc_configuration_mode_exit(void); +/* set RTC counter value */ +void rtc_counter_set(uint32_t cnt); +/* set RTC prescaler value */ +void rtc_prescaler_set(uint32_t psc); + +/* operation functions */ +/* wait RTC last write operation finished flag set */ +void rtc_lwoff_wait(void); +/* wait RTC registers synchronized flag set */ +void rtc_register_sync_wait(void); +/* set RTC alarm value */ +void rtc_alarm_config(uint32_t alarm); +/* get RTC counter value */ +uint32_t rtc_counter_get(void); +/* get RTC divider value */ +uint32_t rtc_divider_get(void); + +/* flag & interrupt functions */ +/* get RTC flag status */ +FlagStatus rtc_flag_get(uint32_t flag); +/* clear RTC flag status */ +void rtc_flag_clear(uint32_t flag); +/* get RTC interrupt flag status */ +FlagStatus rtc_interrupt_flag_get(uint32_t flag); +/* clear RTC interrupt flag status */ +void rtc_interrupt_flag_clear(uint32_t flag); +/* enable RTC interrupt */ +void rtc_interrupt_enable(uint32_t interrupt); +/* disable RTC interrupt */ +void rtc_interrupt_disable(uint32_t interrupt); + +#endif /* GD32F20X_RTC_H */ diff --git a/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_standard_peripheral/Include/gd32f20x_sdio.h b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_standard_peripheral/Include/gd32f20x_sdio.h new file mode 100644 index 0000000000..fd885a3ce8 --- /dev/null +++ b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_standard_peripheral/Include/gd32f20x_sdio.h @@ -0,0 +1,433 @@ +/*! + \file gd32f20x_sdio.h + \brief definitions for the SDIO + + \version 2015-07-15, V1.0.0, firmware for GD32F20x + \version 2017-06-05, V2.0.0, firmware for GD32F20x + \version 2018-10-31, V2.1.0, firmware for GD32F20x + \version 2020-09-30, V2.2.0, firmware for GD32F20x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef GD32F20X_SDIO_H +#define GD32F20X_SDIO_H + +#include "gd32f20x.h" + +/* SDIO definitions */ +#define SDIO SDIO_BASE + +/* registers definitions */ +#define SDIO_PWRCTL REG32(SDIO + 0x00U) /*!< SDIO power control register */ +#define SDIO_CLKCTL REG32(SDIO + 0x04U) /*!< SDIO clock control register */ +#define SDIO_CMDAGMT REG32(SDIO + 0x08U) /*!< SDIO command argument register */ +#define SDIO_CMDCTL REG32(SDIO + 0x0CU) /*!< SDIO command control register */ +#define SDIO_RSPCMDIDX REG32(SDIO + 0x10U) /*!< SDIO command index response register */ +#define SDIO_RESP0 REG32(SDIO + 0x14U) /*!< SDIO response register 0 */ +#define SDIO_RESP1 REG32(SDIO + 0x18U) /*!< SDIO response register 1 */ +#define SDIO_RESP2 REG32(SDIO + 0x1CU) /*!< SDIO response register 2 */ +#define SDIO_RESP3 REG32(SDIO + 0x20U) /*!< SDIO response register 3 */ +#define SDIO_DATATO REG32(SDIO + 0x24U) /*!< SDIO data timeout register */ +#define SDIO_DATALEN REG32(SDIO + 0x28U) /*!< SDIO data length register */ +#define SDIO_DATACTL REG32(SDIO + 0x2CU) /*!< SDIO data control register */ +#define SDIO_DATACNT REG32(SDIO + 0x30U) /*!< SDIO data counter register */ +#define SDIO_STAT REG32(SDIO + 0x34U) /*!< SDIO status register */ +#define SDIO_INTC REG32(SDIO + 0x38U) /*!< SDIO interrupt clear register */ +#define SDIO_INTEN REG32(SDIO + 0x3CU) /*!< SDIO interrupt enable register */ +#define SDIO_FIFOCNT REG32(SDIO + 0x48U) /*!< SDIO FIFO counter register */ +#define SDIO_FIFO REG32(SDIO + 0x80U) /*!< SDIO FIFO data register */ + +/* bits definitions */ +/* SDIO_PWRCTL */ +#define SDIO_PWRCTL_PWRCTL BITS(0,1) /*!< SDIO power control bits */ + +/* SDIO_CLKCTL */ +#define SDIO_CLKCTL_DIV BITS(0,7) /*!< clock division */ +#define SDIO_CLKCTL_CLKEN BIT(8) /*!< SDIO_CLK clock output enable bit */ +#define SDIO_CLKCTL_CLKPWRSAV BIT(9) /*!< SDIO_CLK clock dynamic switch on/off for power saving */ +#define SDIO_CLKCTL_CLKBYP BIT(10) /*!< clock bypass enable bit */ +#define SDIO_CLKCTL_BUSMODE BITS(11,12) /*!< SDIO card bus mode control bit */ +#define SDIO_CLKCTL_CLKEDGE BIT(13) /*!< SDIO_CLK clock edge selection bit */ +#define SDIO_CLKCTL_HWCLKEN BIT(14) /*!< hardware clock control enable bit */ +#define SDIO_CLKCTL_DIV8 BIT(31) /*!< MSB of clock division */ + +/* SDIO_CMDAGMT */ +#define SDIO_CMDAGMT_CMDAGMT BITS(0,31) /*!< SDIO card command argument */ + +/* SDIO_CMDCTL */ +#define SDIO_CMDCTL_CMDIDX BITS(0,5) /*!< command index */ +#define SDIO_CMDCTL_CMDRESP BITS(6,7) /*!< command response type bits */ +#define SDIO_CMDCTL_INTWAIT BIT(8) /*!< interrupt wait instead of timeout */ +#define SDIO_CMDCTL_WAITDEND BIT(9) /*!< wait for ends of data transfer */ +#define SDIO_CMDCTL_CSMEN BIT(10) /*!< command state machine(CSM) enable bit */ +#define SDIO_CMDCTL_SUSPEND BIT(11) /*!< SD I/O suspend command(SD I/O only) */ +#define SDIO_CMDCTL_ENCMDC BIT(12) /*!< CMD completion signal enabled (CE-ATA only) */ +#define SDIO_CMDCTL_NINTEN BIT(13) /*!< no CE-ATA interrupt (CE-ATA only) */ +#define SDIO_CMDCTL_ATAEN BIT(14) /*!< CE-ATA command enable(CE-ATA only) */ + +/* SDIO_DATATO */ +#define SDIO_DATATO_DATATO BITS(0,31) /*!< data timeout period */ + +/* SDIO_DATALEN */ +#define SDIO_DATALEN_DATALEN BITS(0,24) /*!< data transfer length */ + +/* SDIO_DATACTL */ +#define SDIO_DATACTL_DATAEN BIT(0) /*!< data transfer enabled bit */ +#define SDIO_DATACTL_DATADIR BIT(1) /*!< data transfer direction */ +#define SDIO_DATACTL_TRANSMOD BIT(2) /*!< data transfer mode */ +#define SDIO_DATACTL_DMAEN BIT(3) /*!< DMA enable bit */ +#define SDIO_DATACTL_BLKSZ BITS(4,7) /*!< data block size */ +#define SDIO_DATACTL_RWEN BIT(8) /*!< read wait mode enabled(SD I/O only) */ +#define SDIO_DATACTL_RWSTOP BIT(9) /*!< read wait stop(SD I/O only) */ +#define SDIO_DATACTL_RWTYPE BIT(10) /*!< read wait type(SD I/O only) */ +#define SDIO_DATACTL_IOEN BIT(11) /*!< SD I/O specific function enable(SD I/O only) */ + +/* SDIO_STAT */ +#define SDIO_STAT_CCRCERR BIT(0) /*!< command response received (CRC check failed) */ +#define SDIO_STAT_DTCRCERR BIT(1) /*!< data block sent/received (CRC check failed) */ +#define SDIO_STAT_CMDTMOUT BIT(2) /*!< command response timeout */ +#define SDIO_STAT_DTTMOUT BIT(3) /*!< data timeout */ +#define SDIO_STAT_TXURE BIT(4) /*!< transmit FIFO underrun error occurs */ +#define SDIO_STAT_RXORE BIT(5) /*!< received FIFO overrun error occurs */ +#define SDIO_STAT_CMDRECV BIT(6) /*!< command response received (CRC check passed) */ +#define SDIO_STAT_CMDSEND BIT(7) /*!< command sent (no response required) */ +#define SDIO_STAT_DTEND BIT(8) /*!< data end (data counter, SDIO_DATACNT, is zero) */ +#define SDIO_STAT_STBITE BIT(9) /*!< start bit error in the bus */ +#define SDIO_STAT_DTBLKEND BIT(10) /*!< data block sent/received (CRC check passed) */ +#define SDIO_STAT_CMDRUN BIT(11) /*!< command transmission in progress */ +#define SDIO_STAT_TXRUN BIT(12) /*!< data transmission in progress */ +#define SDIO_STAT_RXRUN BIT(13) /*!< data reception in progress */ +#define SDIO_STAT_TFH BIT(14) /*!< transmit FIFO is half empty: at least 8 words can be written into the FIFO */ +#define SDIO_STAT_RFH BIT(15) /*!< receive FIFO is half full: at least 8 words can be read in the FIFO */ +#define SDIO_STAT_TFF BIT(16) /*!< transmit FIFO is full */ +#define SDIO_STAT_RFF BIT(17) /*!< receive FIFO is full */ +#define SDIO_STAT_TFE BIT(18) /*!< transmit FIFO is empty */ +#define SDIO_STAT_RFE BIT(19) /*!< receive FIFO is empty */ +#define SDIO_STAT_TXDTVAL BIT(20) /*!< data is valid in transmit FIFO */ +#define SDIO_STAT_RXDTVAL BIT(21) /*!< data is valid in receive FIFO */ +#define SDIO_STAT_SDIOINT BIT(22) /*!< SD I/O interrupt received */ +#define SDIO_STAT_ATAEND BIT(23) /*!< CE-ATA command completion signal received (only for CMD61) */ + +/* SDIO_INTC */ +#define SDIO_INTC_CCRCERRC BIT(0) /*!< CCRCERR flag clear bit */ +#define SDIO_INTC_DTCRCERRC BIT(1) /*!< DTCRCERR flag clear bit */ +#define SDIO_INTC_CMDTMOUTC BIT(2) /*!< CMDTMOUT flag clear bit */ +#define SDIO_INTC_DTTMOUTC BIT(3) /*!< DTTMOUT flag clear bit */ +#define SDIO_INTC_TXUREC BIT(4) /*!< TXURE flag clear bit */ +#define SDIO_INTC_RXOREC BIT(5) /*!< RXORE flag clear bit */ +#define SDIO_INTC_CMDRECVC BIT(6) /*!< CMDRECV flag clear bit */ +#define SDIO_INTC_CMDSENDC BIT(7) /*!< CMDSEND flag clear bit */ +#define SDIO_INTC_DTENDC BIT(8) /*!< DTEND flag clear bit */ +#define SDIO_INTC_STBITEC BIT(9) /*!< STBITE flag clear bit */ +#define SDIO_INTC_DTBLKENDC BIT(10) /*!< DTBLKEND flag clear bit */ +#define SDIO_INTC_SDIOINTC BIT(22) /*!< SDIOINT flag clear bit */ +#define SDIO_INTC_ATAENDC BIT(23) /*!< ATAEND flag clear bit */ + +/* SDIO_INTEN */ +#define SDIO_INTEN_CCRCERRIE BIT(0) /*!< command response CRC fail interrupt enable */ +#define SDIO_INTEN_DTCRCERRIE BIT(1) /*!< data CRC fail interrupt enable */ +#define SDIO_INTEN_CMDTMOUTIE BIT(2) /*!< command response timeout interrupt enable */ +#define SDIO_INTEN_DTTMOUTIE BIT(3) /*!< data timeout interrupt enable */ +#define SDIO_INTEN_TXUREIE BIT(4) /*!< transmit FIFO underrun error interrupt enable */ +#define SDIO_INTEN_RXOREIE BIT(5) /*!< received FIFO overrun error interrupt enable */ +#define SDIO_INTEN_CMDRECVIE BIT(6) /*!< command response received interrupt enable */ +#define SDIO_INTEN_CMDSENDIE BIT(7) /*!< command sent interrupt enable */ +#define SDIO_INTEN_DTENDIE BIT(8) /*!< data end interrupt enable */ +#define SDIO_INTEN_STBITEIE BIT(9) /*!< start bit error interrupt enable */ +#define SDIO_INTEN_DTBLKENDIE BIT(10) /*!< data block end interrupt enable */ +#define SDIO_INTEN_CMDRUNIE BIT(11) /*!< command transmission interrupt enable */ +#define SDIO_INTEN_TXRUNIE BIT(12) /*!< data transmission interrupt enable */ +#define SDIO_INTEN_RXRUNIE BIT(13) /*!< data reception interrupt enable */ +#define SDIO_INTEN_TFHIE BIT(14) /*!< transmit FIFO half empty interrupt enable */ +#define SDIO_INTEN_RFHIE BIT(15) /*!< receive FIFO half full interrupt enable */ +#define SDIO_INTEN_TFFIE BIT(16) /*!< transmit FIFO full interrupt enable */ +#define SDIO_INTEN_RFFIE BIT(17) /*!< receive FIFO full interrupt enable */ +#define SDIO_INTEN_TFEIE BIT(18) /*!< transmit FIFO empty interrupt enable */ +#define SDIO_INTEN_RFEIE BIT(19) /*!< receive FIFO empty interrupt enable */ +#define SDIO_INTEN_TXDTVALIE BIT(20) /*!< data valid in transmit FIFO interrupt enable */ +#define SDIO_INTEN_RXDTVALIE BIT(21) /*!< data valid in receive FIFO interrupt enable */ +#define SDIO_INTEN_SDIOINTIE BIT(22) /*!< SD I/O interrupt received interrupt enable */ +#define SDIO_INTEN_ATAENDIE BIT(23) /*!< CE-ATA command completion signal received interrupt enable */ + +/* SDIO_FIFO */ +#define SDIO_FIFO_FIFODT BITS(0,31) /*!< receive FIFO data or transmit FIFO data */ + +/* constants definitions */ +/* SDIO flags */ +#define SDIO_FLAG_CCRCERR BIT(0) /*!< command response received (CRC check failed) flag */ +#define SDIO_FLAG_DTCRCERR BIT(1) /*!< data block sent/received (CRC check failed) flag */ +#define SDIO_FLAG_CMDTMOUT BIT(2) /*!< command response timeout flag */ +#define SDIO_FLAG_DTTMOUT BIT(3) /*!< data timeout flag */ +#define SDIO_FLAG_TXURE BIT(4) /*!< transmit FIFO underrun error occurs flag */ +#define SDIO_FLAG_RXORE BIT(5) /*!< received FIFO overrun error occurs flag */ +#define SDIO_FLAG_CMDRECV BIT(6) /*!< command response received (CRC check passed) flag */ +#define SDIO_FLAG_CMDSEND BIT(7) /*!< command sent (no response required) flag */ +#define SDIO_FLAG_DTEND BIT(8) /*!< data end (data counter, SDIO_DATACNT, is zero) flag */ +#define SDIO_FLAG_STBITE BIT(9) /*!< start bit error in the bus flag */ +#define SDIO_FLAG_DTBLKEND BIT(10) /*!< data block sent/received (CRC check passed) flag */ +#define SDIO_FLAG_CMDRUN BIT(11) /*!< command transmission in progress flag */ +#define SDIO_FLAG_TXRUN BIT(12) /*!< data transmission in progress flag */ +#define SDIO_FLAG_RXRUN BIT(13) /*!< data reception in progress flag */ +#define SDIO_FLAG_TFH BIT(14) /*!< transmit FIFO is half empty flag: at least 8 words can be written into the FIFO */ +#define SDIO_FLAG_RFH BIT(15) /*!< receive FIFO is half full flag: at least 8 words can be read in the FIFO */ +#define SDIO_FLAG_TFF BIT(16) /*!< transmit FIFO is full flag */ +#define SDIO_FLAG_RFF BIT(17) /*!< receive FIFO is full flag */ +#define SDIO_FLAG_TFE BIT(18) /*!< transmit FIFO is empty flag */ +#define SDIO_FLAG_RFE BIT(19) /*!< receive FIFO is empty flag */ +#define SDIO_FLAG_TXDTVAL BIT(20) /*!< data is valid in transmit FIFO flag */ +#define SDIO_FLAG_RXDTVAL BIT(21) /*!< data is valid in receive FIFO flag */ +#define SDIO_FLAG_SDIOINT BIT(22) /*!< SD I/O interrupt received flag */ +#define SDIO_FLAG_ATAEND BIT(23) /*!< CE-ATA command completion signal received (only for CMD61) flag */ + +/* SDIO interrupt enable or disable */ +#define SDIO_INT_CCRCERR BIT(0) /*!< SDIO CCRCERR interrupt */ +#define SDIO_INT_DTCRCERR BIT(1) /*!< SDIO DTCRCERR interrupt */ +#define SDIO_INT_CMDTMOUT BIT(2) /*!< SDIO CMDTMOUT interrupt */ +#define SDIO_INT_DTTMOUT BIT(3) /*!< SDIO DTTMOUT interrupt */ +#define SDIO_INT_TXURE BIT(4) /*!< SDIO TXURE interrupt */ +#define SDIO_INT_RXORE BIT(5) /*!< SDIO RXORE interrupt */ +#define SDIO_INT_CMDRECV BIT(6) /*!< SDIO CMDRECV interrupt */ +#define SDIO_INT_CMDSEND BIT(7) /*!< SDIO CMDSEND interrupt */ +#define SDIO_INT_DTEND BIT(8) /*!< SDIO DTEND interrupt */ +#define SDIO_INT_STBITE BIT(9) /*!< SDIO STBITE interrupt */ +#define SDIO_INT_DTBLKEND BIT(10) /*!< SDIO DTBLKEND interrupt */ +#define SDIO_INT_CMDRUN BIT(11) /*!< SDIO CMDRUN interrupt */ +#define SDIO_INT_TXRUN BIT(12) /*!< SDIO TXRUN interrupt */ +#define SDIO_INT_RXRUN BIT(13) /*!< SDIO RXRUN interrupt */ +#define SDIO_INT_TFH BIT(14) /*!< SDIO TFH interrupt */ +#define SDIO_INT_RFH BIT(15) /*!< SDIO RFH interrupt */ +#define SDIO_INT_TFF BIT(16) /*!< SDIO TFF interrupt */ +#define SDIO_INT_RFF BIT(17) /*!< SDIO RFF interrupt */ +#define SDIO_INT_TFE BIT(18) /*!< SDIO TFE interrupt */ +#define SDIO_INT_RFE BIT(19) /*!< SDIO RFE interrupt */ +#define SDIO_INT_TXDTVAL BIT(20) /*!< SDIO TXDTVAL interrupt */ +#define SDIO_INT_RXDTVAL BIT(21) /*!< SDIO RXDTVAL interrupt */ +#define SDIO_INT_SDIOINT BIT(22) /*!< SDIO SDIOINT interrupt */ +#define SDIO_INT_ATAEND BIT(23) /*!< SDIO ATAEND interrupt */ + +/* SDIO interrupt flags */ +#define SDIO_INT_FLAG_CCRCERR BIT(0) /*!< SDIO CCRCERR interrupt */ +#define SDIO_INT_FLAG_DTCRCERR BIT(1) /*!< SDIO DTCRCERR interrupt */ +#define SDIO_INT_FLAG_CMDTMOUT BIT(2) /*!< SDIO CMDTMOUT interrupt */ +#define SDIO_INT_FLAG_DTTMOUT BIT(3) /*!< SDIO DTTMOUT interrupt */ +#define SDIO_INT_FLAG_TXURE BIT(4) /*!< SDIO TXURE interrupt */ +#define SDIO_INT_FLAG_RXORE BIT(5) /*!< SDIO RXORE interrupt */ +#define SDIO_INT_FLAG_CMDRECV BIT(6) /*!< SDIO CMDRECV interrupt */ +#define SDIO_INT_FLAG_CMDSEND BIT(7) /*!< SDIO CMDSEND interrupt */ +#define SDIO_INT_FLAG_DTEND BIT(8) /*!< SDIO DTEND interrupt */ +#define SDIO_INT_FLAG_STBITE BIT(9) /*!< SDIO STBITE interrupt */ +#define SDIO_INT_FLAG_DTBLKEND BIT(10) /*!< SDIO DTBLKEND interrupt */ +#define SDIO_INT_FLAG_CMDRUN BIT(11) /*!< SDIO CMDRUN interrupt */ +#define SDIO_INT_FLAG_TXRUN BIT(12) /*!< SDIO TXRUN interrupt */ +#define SDIO_INT_FLAG_RXRUN BIT(13) /*!< SDIO RXRUN interrupt */ +#define SDIO_INT_FLAG_TFH BIT(14) /*!< SDIO TFH interrupt */ +#define SDIO_INT_FLAG_RFH BIT(15) /*!< SDIO RFH interrupt */ +#define SDIO_INT_FLAG_TFF BIT(16) /*!< SDIO TFF interrupt */ +#define SDIO_INT_FLAG_RFF BIT(17) /*!< SDIO RFF interrupt */ +#define SDIO_INT_FLAG_TFE BIT(18) /*!< SDIO TFE interrupt */ +#define SDIO_INT_FLAG_RFE BIT(19) /*!< SDIO RFE interrupt */ +#define SDIO_INT_FLAG_TXDTVAL BIT(20) /*!< SDIO TXDTVAL interrupt */ +#define SDIO_INT_FLAG_RXDTVAL BIT(21) /*!< SDIO RXDTVAL interrupt */ +#define SDIO_INT_FLAG_SDIOINT BIT(22) /*!< SDIO SDIOINT interrupt */ +#define SDIO_INT_FLAG_ATAEND BIT(23) /*!< SDIO ATAEND interrupt */ + +/* SDIO power control */ +#define PWRCTL_PWRCTL(regval) (BITS(0,1) & ((uint32_t)(regval) << 0)) +#define SDIO_POWER_OFF PWRCTL_PWRCTL(0) /*!< SDIO power off */ +#define SDIO_POWER_ON PWRCTL_PWRCTL(3) /*!< SDIO power on */ + +/* SDIO card bus mode control */ +#define CLKCTL_BUSMODE(regval) (BITS(11,12) & ((uint32_t)(regval) << 11)) +#define SDIO_BUSMODE_1BIT CLKCTL_BUSMODE(0) /*!< 1-bit SDIO card bus mode */ +#define SDIO_BUSMODE_4BIT CLKCTL_BUSMODE(1) /*!< 4-bit SDIO card bus mode */ +#define SDIO_BUSMODE_8BIT CLKCTL_BUSMODE(2) /*!< 8-bit SDIO card bus mode */ + +/* SDIO_CLK clock edge selection */ +#define SDIO_SDIOCLKEDGE_RISING ((uint32_t)0x00000000U)/*!< select the rising edge of the SDIOCLK to generate SDIO_CLK */ +#define SDIO_SDIOCLKEDGE_FALLING SDIO_CLKCTL_CLKEDGE /*!< select the falling edge of the SDIOCLK to generate SDIO_CLK */ + +/* clock bypass enable or disable */ +#define SDIO_CLOCKBYPASS_DISABLE ((uint32_t)0x00000000U)/*!< no bypass */ +#define SDIO_CLOCKBYPASS_ENABLE SDIO_CLKCTL_CLKBYP /*!< clock bypass */ + +/* SDIO_CLK clock dynamic switch on/off for power saving */ +#define SDIO_CLOCKPWRSAVE_DISABLE ((uint32_t)0x00000000U)/*!< SDIO_CLK clock is always on */ +#define SDIO_CLOCKPWRSAVE_ENABLE SDIO_CLKCTL_CLKPWRSAV /*!< SDIO_CLK closed when bus is idle */ + +/* SDIO command response type */ +#define CMDCTL_CMDRESP(regval) (BITS(6,7) & ((uint32_t)(regval) << 6)) +#define SDIO_RESPONSETYPE_NO CMDCTL_CMDRESP(0) /*!< no response */ +#define SDIO_RESPONSETYPE_SHORT CMDCTL_CMDRESP(1) /*!< short response */ +#define SDIO_RESPONSETYPE_LONG CMDCTL_CMDRESP(3) /*!< long response */ + +/* command state machine wait type */ +#define SDIO_WAITTYPE_NO ((uint32_t)0x00000000U)/*!< not wait interrupt */ +#define SDIO_WAITTYPE_INTERRUPT SDIO_CMDCTL_INTWAIT /*!< wait interrupt */ +#define SDIO_WAITTYPE_DATAEND SDIO_CMDCTL_WAITDEND /*!< wait the end of data transfer */ + +#define SDIO_RESPONSE0 ((uint32_t)0x00000000U)/*!< card response[31:0]/card response[127:96] */ +#define SDIO_RESPONSE1 ((uint32_t)0x00000001U)/*!< card response[95:64] */ +#define SDIO_RESPONSE2 ((uint32_t)0x00000002U)/*!< card response[63:32] */ +#define SDIO_RESPONSE3 ((uint32_t)0x00000003U)/*!< card response[31:1], plus bit 0 */ + +/* SDIO data block size */ +#define DATACTL_BLKSZ(regval) (BITS(4,7) & ((uint32_t)(regval) << 4)) +#define SDIO_DATABLOCKSIZE_1BYTE DATACTL_BLKSZ(0) /*!< block size = 1 byte */ +#define SDIO_DATABLOCKSIZE_2BYTES DATACTL_BLKSZ(1) /*!< block size = 2 bytes */ +#define SDIO_DATABLOCKSIZE_4BYTES DATACTL_BLKSZ(2) /*!< block size = 4 bytes */ +#define SDIO_DATABLOCKSIZE_8BYTES DATACTL_BLKSZ(3) /*!< block size = 8 bytes */ +#define SDIO_DATABLOCKSIZE_16BYTES DATACTL_BLKSZ(4) /*!< block size = 16 bytes */ +#define SDIO_DATABLOCKSIZE_32BYTES DATACTL_BLKSZ(5) /*!< block size = 32 bytes */ +#define SDIO_DATABLOCKSIZE_64BYTES DATACTL_BLKSZ(6) /*!< block size = 64 bytes */ +#define SDIO_DATABLOCKSIZE_128BYTES DATACTL_BLKSZ(7) /*!< block size = 128 bytes */ +#define SDIO_DATABLOCKSIZE_256BYTES DATACTL_BLKSZ(8) /*!< block size = 256 bytes */ +#define SDIO_DATABLOCKSIZE_512BYTES DATACTL_BLKSZ(9) /*!< block size = 512 bytes */ +#define SDIO_DATABLOCKSIZE_1024BYTES DATACTL_BLKSZ(10) /*!< block size = 1024 bytes */ +#define SDIO_DATABLOCKSIZE_2048BYTES DATACTL_BLKSZ(11) /*!< block size = 2048 bytes */ +#define SDIO_DATABLOCKSIZE_4096BYTES DATACTL_BLKSZ(12) /*!< block size = 4096 bytes */ +#define SDIO_DATABLOCKSIZE_8192BYTES DATACTL_BLKSZ(13) /*!< block size = 8192 bytes */ +#define SDIO_DATABLOCKSIZE_16384BYTES DATACTL_BLKSZ(14) /*!< block size = 16384 bytes */ + +/* SDIO data transfer mode */ +#define SDIO_TRANSMODE_BLOCK ((uint32_t)0x00000000U)/*!< block transfer */ +#define SDIO_TRANSMODE_STREAM SDIO_DATACTL_TRANSMOD /*!< stream transfer or SDIO multibyte transfer */ + +/* SDIO data transfer direction */ +#define SDIO_TRANSDIRECTION_TOCARD ((uint32_t)0x00000000U)/*!< write data to card */ +#define SDIO_TRANSDIRECTION_TOSDIO SDIO_DATACTL_DATADIR /*!< read data from card */ + +/* SDIO read wait type */ +#define SDIO_READWAITTYPE_DAT2 ((uint32_t)0x00000000U)/*!< read wait control using SDIO_DAT[2] */ +#define SDIO_READWAITTYPE_CLK SDIO_DATACTL_RWTYPE /*!< read wait control by stopping SDIO_CLK */ + +/* function declarations */ +/* initialization functions */ +/* deinitialize the SDIO */ +void sdio_deinit(void); +/* configure the SDIO clock */ +void sdio_clock_config(uint32_t clock_edge, uint32_t clock_bypass, uint32_t clock_powersave, uint16_t clock_division); +/* enable hardware clock control */ +void sdio_hardware_clock_enable(void); +/* disable hardware clock control */ +void sdio_hardware_clock_disable(void); +/* set different SDIO card bus mode */ +void sdio_bus_mode_set(uint32_t bus_mode); +/* set the SDIO power state */ +void sdio_power_state_set(uint32_t power_state); +/* get the SDIO power state */ +uint32_t sdio_power_state_get(void); +/* enable SDIO_CLK clock output */ +void sdio_clock_enable(void); +/* disable SDIO_CLK clock output */ +void sdio_clock_disable(void); + +/* function configuration */ +/* configure the command index, argument, response type, wait type and CSM to send command */ +/* configure the command and response */ +void sdio_command_response_config(uint32_t cmd_index, uint32_t cmd_argument, uint32_t response_type); +/* set the command state machine wait type */ +void sdio_wait_type_set(uint32_t wait_type); +/* enable the CSM(command state machine) */ +void sdio_csm_enable(void); +/* disable the CSM(command state machine) */ +void sdio_csm_disable(void); +/* get the last response command index */ +uint8_t sdio_command_index_get(void); +/* get the response for the last received command */ +uint32_t sdio_response_get(uint32_t responsex); + +/* configure the data timeout, length, block size, transfer mode, direction and DSM for data transfer */ +/* configure the data timeout, data length and data block size */ +void sdio_data_config(uint32_t data_timeout, uint32_t data_length, uint32_t data_blocksize); +/* configure the data transfer mode and direction */ +void sdio_data_transfer_config(uint32_t transfer_mode, uint32_t transfer_direction); +/* enable the DSM(data state machine) for data transfer */ +void sdio_dsm_enable(void); +/* disable the DSM(data state machine) */ +void sdio_dsm_disable(void); +/* write data(one word) to the transmit FIFO */ +void sdio_data_write(uint32_t data); +/* read data(one word) from the receive FIFO */ +uint32_t sdio_data_read(void); +/* get the number of remaining data bytes to be transferred to card */ +uint32_t sdio_data_counter_get(void); +/* get the number of words remaining to be written or read from FIFO */ +uint32_t sdio_fifo_counter_get(void); +/* enable the DMA request for SDIO */ +void sdio_dma_enable(void); +/* disable the DMA request for SDIO */ +void sdio_dma_disable(void); + +/* enable the read wait mode(SD I/O only) */ +void sdio_readwait_enable(void); +/* disable the read wait mode(SD I/O only) */ +void sdio_readwait_disable(void); +/* enable the function that stop the read wait process(SD I/O only) */ +void sdio_stop_readwait_enable(void); +/* disable the function that stop the read wait process(SD I/O only) */ +void sdio_stop_readwait_disable(void); +/* set the read wait type(SD I/O only) */ +void sdio_readwait_type_set(uint32_t readwait_type); +/* enable the SD I/O mode specific operation(SD I/O only) */ +void sdio_operation_enable(void); +/* disable the SD I/O mode specific operation(SD I/O only) */ +void sdio_operation_disable(void); +/* enable the SD I/O suspend operation(SD I/O only) */ +void sdio_suspend_enable(void); +/* disable the SD I/O suspend operation(SD I/O only) */ +void sdio_suspend_disable(void); + +/* enable the CE-ATA command(CE-ATA only) */ +void sdio_ceata_command_enable(void); +/* disable the CE-ATA command(CE-ATA only) */ +void sdio_ceata_command_disable(void); +/* enable the CE-ATA interrupt(CE-ATA only) */ +void sdio_ceata_interrupt_enable(void); +/* disable the CE-ATA interrupt(CE-ATA only) */ +void sdio_ceata_interrupt_disable(void); +/* enable the CE-ATA command completion signal(CE-ATA only) */ +void sdio_ceata_command_completion_enable(void); +/* disable the CE-ATA command completion signal(CE-ATA only) */ +void sdio_ceata_command_completion_disable(void); + +/* interrupt & flag functions */ +/* get the flags state of SDIO */ +FlagStatus sdio_flag_get(uint32_t flag); +/* clear the pending flags of SDIO */ +void sdio_flag_clear(uint32_t flag); +/* enable the SDIO interrupt */ +void sdio_interrupt_enable(uint32_t int_flag); +/* disable the SDIO interrupt */ +void sdio_interrupt_disable(uint32_t int_flag); +/* get the interrupt flags state of SDIO */ +FlagStatus sdio_interrupt_flag_get(uint32_t int_flag); +/* clear the interrupt pending flags of SDIO */ +void sdio_interrupt_flag_clear(uint32_t int_flag); + +#endif /* GD32F20X_SDIO_H */ diff --git a/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_standard_peripheral/Include/gd32f20x_spi.h b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_standard_peripheral/Include/gd32f20x_spi.h new file mode 100644 index 0000000000..f5e2d49280 --- /dev/null +++ b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_standard_peripheral/Include/gd32f20x_spi.h @@ -0,0 +1,346 @@ +/*! + \file gd32f20x_spi.h + \brief definitions for the SPI + + \version 2015-07-15, V1.0.0, firmware for GD32F20x + \version 2017-06-05, V2.0.0, firmware for GD32F20x + \version 2018-10-31, V2.1.0, firmware for GD32F20x + \version 2020-09-30, V2.2.0, firmware for GD32F20x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef GD32F20X_SPI_H +#define GD32F20X_SPI_H + +#include "gd32f20x.h" + +/* SPIx(x=0,1,2) definitions */ +#define SPI0 (SPI_BASE + 0x0000F800U) +#define SPI1 SPI_BASE +#define SPI2 (SPI_BASE + 0x00000400U) + +/* SPI registers definitions */ +#define SPI_CTL0(spix) REG32((spix) + 0x00U) /*!< SPI control register 0 */ +#define SPI_CTL1(spix) REG32((spix) + 0x04U) /*!< SPI control register 1*/ +#define SPI_STAT(spix) REG32((spix) + 0x08U) /*!< SPI status register */ +#define SPI_DATA(spix) REG32((spix) + 0x0CU) /*!< SPI data register */ +#define SPI_CRCPOLY(spix) REG32((spix) + 0x10U) /*!< SPI CRC polynomial register */ +#define SPI_RCRC(spix) REG32((spix) + 0x14U) /*!< SPI receive CRC register */ +#define SPI_TCRC(spix) REG32((spix) + 0x18U) /*!< SPI transmit CRC register */ +#define SPI_I2SCTL(spix) REG32((spix) + 0x1CU) /*!< SPI I2S control register */ +#define SPI_I2SPSC(spix) REG32((spix) + 0x20U) /*!< SPI I2S clock prescaler register */ +#define SPI_QCTL(spix) REG32((spix) + 0x80U) /*!< SPI quad mode control register(only SPI0) */ + +/* bits definitions */ +/* SPI_CTL0 */ +#define SPI_CTL0_CKPH BIT(0) /*!< clock phase selection*/ +#define SPI_CTL0_CKPL BIT(1) /*!< clock polarity selection */ +#define SPI_CTL0_MSTMOD BIT(2) /*!< master mode enable */ +#define SPI_CTL0_PSC BITS(3,5) /*!< master clock prescaler selection */ +#define SPI_CTL0_SPIEN BIT(6) /*!< SPI enable*/ +#define SPI_CTL0_LF BIT(7) /*!< LSB first mode */ +#define SPI_CTL0_SWNSS BIT(8) /*!< NSS pin selection in NSS software mode */ +#define SPI_CTL0_SWNSSEN BIT(9) /*!< NSS software mode selection */ +#define SPI_CTL0_RO BIT(10) /*!< receive only */ +#define SPI_CTL0_FF16 BIT(11) /*!< data frame size */ +#define SPI_CTL0_CRCNT BIT(12) /*!< CRC next transfer */ +#define SPI_CTL0_CRCEN BIT(13) /*!< CRC calculation enable */ +#define SPI_CTL0_BDOEN BIT(14) /*!< bidirectional transmit output enable*/ +#define SPI_CTL0_BDEN BIT(15) /*!< bidirectional enable */ + +/* SPI_CTL1 */ +#define SPI_CTL1_DMAREN BIT(0) /*!< receive buffer dma enable */ +#define SPI_CTL1_DMATEN BIT(1) /*!< transmit buffer dma enable */ +#define SPI_CTL1_NSSDRV BIT(2) /*!< drive NSS output */ +#define SPI_CTL1_ERRIE BIT(5) /*!< errors interrupt enable */ +#define SPI_CTL1_RBNEIE BIT(6) /*!< receive buffer not empty interrupt enable */ +#define SPI_CTL1_TBEIE BIT(7) /*!< transmit buffer empty interrupt enable */ + +/* SPI_STAT */ +#define SPI_STAT_RBNE BIT(0) /*!< receive buffer not empty */ +#define SPI_STAT_TBE BIT(1) /*!< transmit buffer empty */ +#define SPI_STAT_I2SCH BIT(2) /*!< I2S channel side */ +#define SPI_STAT_TXURERR BIT(3) /*!< I2S transmission underrun error bit */ +#define SPI_STAT_CRCERR BIT(4) /*!< SPI CRC error bit */ +#define SPI_STAT_CONFERR BIT(5) /*!< SPI configuration error bit */ +#define SPI_STAT_RXORERR BIT(6) /*!< SPI reception overrun error bit */ +#define SPI_STAT_TRANS BIT(7) /*!< transmitting on-going bit */ + +/* SPI_DATA */ +#define SPI_DATA_DATA BITS(0,15) /*!< data transfer register */ + +/* SPI_CRCPOLY */ +#define SPI_CRCPOLY_CPR BITS(0,15) /*!< CRC polynomial register */ + +/* SPI_RCRC */ +#define SPI_RCRC_RCR BITS(0,15) /*!< RX CRC register */ + +/* SPI_TCRC */ +#define SPI_TCRC_TCR BITS(0,15) /*!< RX CRC register */ + +/* SPI_I2SCTL */ +#define SPI_I2SCTL_CHLEN BIT(0) /*!< channel length */ +#define SPI_I2SCTL_DTLEN BITS(1,2) /*!< data length */ +#define SPI_I2SCTL_CKPL BIT(3) /*!< idle state clock polarity */ +#define SPI_I2SCTL_I2SSTD BITS(4,5) /*!< I2S standard selection */ +#define SPI_I2SCTL_PCMSMOD BIT(7) /*!< PCM frame synchronization mode */ +#define SPI_I2SCTL_I2SOPMOD BITS(8,9) /*!< I2S operation mode */ +#define SPI_I2SCTL_I2SEN BIT(10) /*!< I2S enable */ +#define SPI_I2SCTL_I2SSEL BIT(11) /*!< I2S mode selection */ + +/* SPI_I2SPSC */ +#define SPI_I2SPSC_DIV BITS(0,7) /*!< dividing factor for the prescaler */ +#define SPI_I2SPSC_OF BIT(8) /*!< odd factor for the prescaler */ +#define SPI_I2SPSC_MCKOEN BIT(9) /*!< I2S MCK output enable */ + +/* SPI_QCTL(only for SPI0) */ +#define SPI_QCTL_QMOD BIT(0) /*!< quad-SPI mode enable */ +#define SPI_QCTL_QRD BIT(1) /*!< quad-SPI mode read select */ +#define SPI_QCTL_IO23_DRV BIT(2) /*!< drive SPI_IO2 and SPI_IO3 enable */ + +/* constants definitions */ +/* SPI and I2S parameter struct definitions */ +typedef struct +{ + uint32_t device_mode; /*!< SPI master or slave */ + uint32_t trans_mode; /*!< SPI transfer type */ + uint32_t frame_size; /*!< SPI frame size */ + uint32_t nss; /*!< SPI NSS control by hardware or software */ + uint32_t endian; /*!< SPI big endian or little endian */ + uint32_t clock_polarity_phase; /*!< SPI clock phase and polarity */ + uint32_t prescale; /*!< SPI prescaler factor */ +}spi_parameter_struct; + +/* SPI mode definitions */ +#define SPI_MASTER (SPI_CTL0_MSTMOD | SPI_CTL0_SWNSS) /*!< SPI as master */ +#define SPI_SLAVE ((uint32_t)0x00000000U) /*!< SPI as slave */ + +/* SPI bidirectional transfer direction */ +#define SPI_BIDIRECTIONAL_TRANSMIT SPI_CTL0_BDOEN /*!< SPI work in transmit-only mode */ +#define SPI_BIDIRECTIONAL_RECEIVE ~SPI_CTL0_BDOEN /*!< SPI work in receive-only mode */ + +/* SPI transmit type */ +#define SPI_TRANSMODE_FULLDUPLEX ((uint32_t)0x00000000U) /*!< SPI receive and send data at fullduplex communication */ +#define SPI_TRANSMODE_RECEIVEONLY SPI_CTL0_RO /*!< SPI only receive data */ +#define SPI_TRANSMODE_BDRECEIVE SPI_CTL0_BDEN /*!< bidirectional receive data */ +#define SPI_TRANSMODE_BDTRANSMIT (SPI_CTL0_BDEN | SPI_CTL0_BDOEN) /*!< bidirectional transmit data*/ + +/* SPI frame size */ +#define SPI_FRAMESIZE_16BIT SPI_CTL0_FF16 /*!< SPI frame size is 16 bits */ +#define SPI_FRAMESIZE_8BIT ((uint32_t)0x00000000U) /*!< SPI frame size is 8 bits */ + +/* SPI NSS control mode */ +#define SPI_NSS_SOFT SPI_CTL0_SWNSSEN /*!< SPI NSS control by sofrware */ +#define SPI_NSS_HARD ((uint32_t)0x00000000U) /*!< SPI NSS control by hardware */ + +/* SPI transmit way */ +#define SPI_ENDIAN_MSB ((uint32_t)0x00000000U) /*!< SPI transmit way is big endian: transmit MSB first */ +#define SPI_ENDIAN_LSB SPI_CTL0_LF /*!< SPI transmit way is little endian: transmit LSB first */ + +/* SPI clock phase and polarity */ +#define SPI_CK_PL_LOW_PH_1EDGE ((uint32_t)0x00000000U) /*!< SPI clock polarity is low level and phase is first edge */ +#define SPI_CK_PL_HIGH_PH_1EDGE SPI_CTL0_CKPL /*!< SPI clock polarity is high level and phase is first edge */ +#define SPI_CK_PL_LOW_PH_2EDGE SPI_CTL0_CKPH /*!< SPI clock polarity is low level and phase is second edge */ +#define SPI_CK_PL_HIGH_PH_2EDGE (SPI_CTL0_CKPL | SPI_CTL0_CKPH) /*!< SPI clock polarity is high level and phase is second edge */ + +/* SPI clock prescale factor */ +#define CTL0_PSC(regval) (BITS(3,5) & ((uint32_t)(regval) << 3)) +#define SPI_PSC_2 CTL0_PSC(0) /*!< SPI clock prescale factor is 2 */ +#define SPI_PSC_4 CTL0_PSC(1) /*!< SPI clock prescale factor is 4 */ +#define SPI_PSC_8 CTL0_PSC(2) /*!< SPI clock prescale factor is 8 */ +#define SPI_PSC_16 CTL0_PSC(3) /*!< SPI clock prescale factor is 16 */ +#define SPI_PSC_32 CTL0_PSC(4) /*!< SPI clock prescale factor is 32 */ +#define SPI_PSC_64 CTL0_PSC(5) /*!< SPI clock prescale factor is 64 */ +#define SPI_PSC_128 CTL0_PSC(6) /*!< SPI clock prescale factor is 128 */ +#define SPI_PSC_256 CTL0_PSC(7) /*!< SPI clock prescale factor is 256 */ + +/* I2S audio sample rate */ +#define I2S_AUDIOSAMPLE_8K ((uint32_t)8000U) /*!< I2S audio sample rate is 8KHz */ +#define I2S_AUDIOSAMPLE_11K ((uint32_t)11025U) /*!< I2S audio sample rate is 11KHz */ +#define I2S_AUDIOSAMPLE_16K ((uint32_t)16000U) /*!< I2S audio sample rate is 16KHz */ +#define I2S_AUDIOSAMPLE_22K ((uint32_t)22050U) /*!< I2S audio sample rate is 22KHz */ +#define I2S_AUDIOSAMPLE_32K ((uint32_t)32000U) /*!< I2S audio sample rate is 32KHz */ +#define I2S_AUDIOSAMPLE_44K ((uint32_t)44100U) /*!< I2S audio sample rate is 44KHz */ +#define I2S_AUDIOSAMPLE_48K ((uint32_t)48000U) /*!< I2S audio sample rate is 48KHz */ +#define I2S_AUDIOSAMPLE_96K ((uint32_t)96000U) /*!< I2S audio sample rate is 96KHz */ +#define I2S_AUDIOSAMPLE_192K ((uint32_t)192000U) /*!< I2S audio sample rate is 192KHz */ + +/* I2S frame format */ +#define I2SCTL_DTLEN(regval) (BITS(1,2) & ((uint32_t)(regval) << 1)) +#define I2S_FRAMEFORMAT_DT16B_CH16B I2SCTL_DTLEN(0) /*!< I2S data length is 16 bit and channel length is 16 bit */ +#define I2S_FRAMEFORMAT_DT16B_CH32B (I2SCTL_DTLEN(0) | SPI_I2SCTL_CHLEN) /*!< I2S data length is 16 bit and channel length is 32 bit */ +#define I2S_FRAMEFORMAT_DT24B_CH32B (I2SCTL_DTLEN(1) | SPI_I2SCTL_CHLEN) /*!< I2S data length is 24 bit and channel length is 32 bit */ +#define I2S_FRAMEFORMAT_DT32B_CH32B (I2SCTL_DTLEN(2) | SPI_I2SCTL_CHLEN) /*!< I2S data length is 32 bit and channel length is 32 bit */ + +/* I2S master clock output */ +#define I2S_MCKOUT_DISABLE ((uint32_t)0x00000000U) /*!< I2S master clock output disable */ +#define I2S_MCKOUT_ENABLE SPI_I2SPSC_MCKOEN /*!< I2S master clock output enable */ + +/* I2S operation mode */ +#define I2SCTL_I2SOPMOD(regval) (BITS(8,9) & ((uint32_t)(regval) << 8)) +#define I2S_MODE_SLAVETX I2SCTL_I2SOPMOD(0) /*!< I2S slave transmit mode */ +#define I2S_MODE_SLAVERX I2SCTL_I2SOPMOD(1) /*!< I2S slave receive mode */ +#define I2S_MODE_MASTERTX I2SCTL_I2SOPMOD(2) /*!< I2S master transmit mode */ +#define I2S_MODE_MASTERRX I2SCTL_I2SOPMOD(3) /*!< I2S master receive mode */ + +/* I2S standard */ +#define I2SCTL_I2SSTD(regval) (BITS(4,5) & ((uint32_t)(regval) << 4)) +#define I2S_STD_PHILLIPS I2SCTL_I2SSTD(0) /*!< I2S phillips standard */ +#define I2S_STD_MSB I2SCTL_I2SSTD(1) /*!< I2S MSB standard */ +#define I2S_STD_LSB I2SCTL_I2SSTD(2) /*!< I2S LSB standard */ +#define I2S_STD_PCMSHORT I2SCTL_I2SSTD(3) /*!< I2S PCM short standard */ +#define I2S_STD_PCMLONG (I2SCTL_I2SSTD(3) | SPI_I2SCTL_PCMSMOD) /*!< I2S PCM long standard */ + +/* I2S clock polarity */ +#define I2S_CKPL_LOW ((uint32_t)0x00000000U) /*!< I2S clock polarity low level */ +#define I2S_CKPL_HIGH SPI_I2SCTL_CKPL /*!< I2S clock polarity high level */ + +/* SPI DMA constants definitions */ +#define SPI_DMA_TRANSMIT ((uint8_t)0x00U) /*!< SPI transmit data use DMA */ +#define SPI_DMA_RECEIVE ((uint8_t)0x01U) /*!< SPI receive data use DMA */ + +/* SPI CRC constants definitions */ +#define SPI_CRC_TX ((uint8_t)0x00U) /*!< SPI transmit CRC value */ +#define SPI_CRC_RX ((uint8_t)0x01U) /*!< SPI receive CRC value */ + +/* SPI/I2S interrupt enable/disable constants definitions */ +#define SPI_I2S_INT_TBE ((uint8_t)0x00U) /*!< transmit buffer empty interrupt */ +#define SPI_I2S_INT_RBNE ((uint8_t)0x01U) /*!< receive buffer not empty interrupt */ +#define SPI_I2S_INT_ERR ((uint8_t)0x02U) /*!< error interrupt */ + +/* SPI/I2S interrupt flag constants definitions */ +#define SPI_I2S_INT_FLAG_TBE ((uint8_t)0x00U) /*!< transmit buffer empty interrupt flag */ +#define SPI_I2S_INT_FLAG_RBNE ((uint8_t)0x01U) /*!< receive buffer not empty interrupt flag */ +#define SPI_I2S_INT_FLAG_RXORERR ((uint8_t)0x02U) /*!< overrun interrupt flag */ +#define SPI_INT_FLAG_CONFERR ((uint8_t)0x03U) /*!< config error interrupt flag */ +#define SPI_INT_FLAG_CRCERR ((uint8_t)0x04U) /*!< CRC error interrupt flag */ +#define I2S_INT_FLAG_TXURERR ((uint8_t)0x05U) /*!< underrun error interrupt flag */ + +/* SPI/I2S flag definitions */ +#define SPI_FLAG_RBNE SPI_STAT_RBNE /*!< receive buffer not empty flag */ +#define SPI_FLAG_TBE SPI_STAT_TBE /*!< transmit buffer empty flag */ +#define SPI_FLAG_CRCERR SPI_STAT_CRCERR /*!< CRC error flag */ +#define SPI_FLAG_CONFERR SPI_STAT_CONFERR /*!< mode config error flag */ +#define SPI_FLAG_RXORERR SPI_STAT_RXORERR /*!< receive overrun error flag */ +#define SPI_FLAG_TRANS SPI_STAT_TRANS /*!< transmit on-going flag */ +#define I2S_FLAG_RBNE SPI_STAT_RBNE /*!< receive buffer not empty flag */ +#define I2S_FLAG_TBE SPI_STAT_TBE /*!< transmit buffer empty flag */ +#define I2S_FLAG_CH SPI_STAT_I2SCH /*!< channel side flag */ +#define I2S_FLAG_TXURERR SPI_STAT_TXURERR /*!< underrun error flag */ +#define I2S_FLAG_RXORERR SPI_STAT_RXORERR /*!< overrun error flag */ +#define I2S_FLAG_TRANS SPI_STAT_TRANS /*!< transmit on-going flag */ + +/* function declarations */ +/* SPI/I2S deinitialization and initialization functions */ +/* reset SPI and I2S */ +void spi_i2s_deinit(uint32_t spi_periph); +/* initialize the parameters of SPI structure with the default values */ +void spi_struct_para_init(spi_parameter_struct* spi_struct); +/* initialize SPI parameter */ +void spi_init(uint32_t spi_periph, spi_parameter_struct* spi_struct); +/* enable SPI */ +void spi_enable(uint32_t spi_periph); +/* disable SPI */ +void spi_disable(uint32_t spi_periph); + +/* initialize I2S parameter */ +void i2s_init(uint32_t spi_periph, uint32_t mode, uint32_t standard, uint32_t ckpl); +/* configure I2S prescaler */ +void i2s_psc_config(uint32_t spi_periph, uint32_t audiosample, uint32_t frameformat, uint32_t mckout); +/* enable I2S */ +void i2s_enable(uint32_t spi_periph); +/* disable I2S */ +void i2s_disable(uint32_t spi_periph); + +/* NSS functions */ +/* enable SPI NSS output */ +void spi_nss_output_enable(uint32_t spi_periph); +/* disable SPI NSS output */ +void spi_nss_output_disable(uint32_t spi_periph); +/* SPI NSS pin high level in software mode */ +void spi_nss_internal_high(uint32_t spi_periph); +/* SPI NSS pin low level in software mode */ +void spi_nss_internal_low(uint32_t spi_periph); + +/* DMA communication */ +/* enable SPI DMA */ +void spi_dma_enable(uint32_t spi_periph, uint8_t dma); +/* disable SPI DMA */ +void spi_dma_disable(uint32_t spi_periph, uint8_t dma); + +/* normal mode communication */ +/* configure SPI/I2S data frame format */ +void spi_i2s_data_frame_format_config(uint32_t spi_periph, uint16_t frame_format); +/* SPI transmit data */ +void spi_i2s_data_transmit(uint32_t spi_periph, uint16_t data); +/* SPI receive data */ +uint16_t spi_i2s_data_receive(uint32_t spi_periph); +/* configure SPI bidirectional transfer direction */ +void spi_bidirectional_transfer_config(uint32_t spi_periph, uint32_t transfer_direction); + +/* SPI CRC functions */ +/* set SPI CRC polynomial */ +void spi_crc_polynomial_set(uint32_t spi_periph, uint16_t crc_poly); +/* get SPI CRC polynomial */ +uint16_t spi_crc_polynomial_get(uint32_t spi_periph); +/* turn on SPI CRC function */ +void spi_crc_on(uint32_t spi_periph); +/* turn off SPI CRC function */ +void spi_crc_off(uint32_t spi_periph); +/* SPI next data is CRC value */ +void spi_crc_next(uint32_t spi_periph); +/* get SPI CRC send value or receive value */ +uint16_t spi_crc_get(uint32_t spi_periph, uint8_t crc); + +/* flag and interrupt functions */ +/* enable SPI and I2S interrupt */ +void spi_i2s_interrupt_enable(uint32_t spi_periph, uint8_t interrupt); +/* disable SPI and I2S interrupt */ +void spi_i2s_interrupt_disable(uint32_t spi_periph, uint8_t interrupt); +/* get SPI and I2S interrupt status */ +FlagStatus spi_i2s_interrupt_flag_get(uint32_t spi_periph, uint8_t interrupt); +/* get SPI and I2S flag status */ +FlagStatus spi_i2s_flag_get(uint32_t spi_periph, uint32_t flag); +/* clear SPI CRC error flag status */ +void spi_crc_error_clear(uint32_t spi_periph); + +/* enable quad wire SPI */ +void qspi_enable(uint32_t spi_periph); +/* disable quad wire SPI */ +void qspi_disable(uint32_t spi_periph); +/* enable quad wire SPI write */ +void qspi_write_enable(uint32_t spi_periph); +/* enable quad wire SPI read */ +void qspi_read_enable(uint32_t spi_periph); +/* enable quad wire SPI_IO2 and SPI_IO3 pin output */ +void qspi_io23_output_enable(uint32_t spi_periph); +/* disable quad wire SPI_IO2 and SPI_IO3 pin output */ +void qspi_io23_output_disable(uint32_t spi_periph); + +#endif /* GD32F20X_SPI_H */ diff --git a/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_standard_peripheral/Include/gd32f20x_timer.h b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_standard_peripheral/Include/gd32f20x_timer.h new file mode 100644 index 0000000000..d0e0221a54 --- /dev/null +++ b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_standard_peripheral/Include/gd32f20x_timer.h @@ -0,0 +1,731 @@ +/*! + \file gd32f20x_timer.h + \brief definitions for the TIMER + + \version 2015-07-15, V1.0.0, firmware for GD32F20x + \version 2017-06-05, V2.0.0, firmware for GD32F20x + \version 2018-10-31, V2.1.0, firmware for GD32F20x + \version 2020-09-30, V2.2.0, firmware for GD32F20x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef GD32F20X_TIMER_H +#define GD32F20X_TIMER_H + +#include "gd32f20x.h" + +/* TIMERx(x=0..13) definitions */ +#define TIMER0 (TIMER_BASE + 0x00012C00U) +#define TIMER1 (TIMER_BASE + 0x00000000U) +#define TIMER2 (TIMER_BASE + 0x00000400U) +#define TIMER3 (TIMER_BASE + 0x00000800U) +#define TIMER4 (TIMER_BASE + 0x00000C00U) +#define TIMER5 (TIMER_BASE + 0x00001000U) +#define TIMER6 (TIMER_BASE + 0x00001400U) +#define TIMER7 (TIMER_BASE + 0x00013400U) +#define TIMER8 (TIMER_BASE + 0x00014C00U) +#define TIMER9 (TIMER_BASE + 0x00015000U) +#define TIMER10 (TIMER_BASE + 0x00015400U) +#define TIMER11 (TIMER_BASE + 0x00001800U) +#define TIMER12 (TIMER_BASE + 0x00001C00U) +#define TIMER13 (TIMER_BASE + 0x00002000U) + +/* registers definitions */ +#define TIMER_CTL0(timerx) REG32((timerx) + 0x00U) /*!< TIMER control register 0 */ +#define TIMER_CTL1(timerx) REG32((timerx) + 0x04U) /*!< TIMER control register 1 */ +#define TIMER_SMCFG(timerx) REG32((timerx) + 0x08U) /*!< TIMER slave mode configuration register */ +#define TIMER_DMAINTEN(timerx) REG32((timerx) + 0x0CU) /*!< TIMER DMA and interrupt enable register */ +#define TIMER_INTF(timerx) REG32((timerx) + 0x10U) /*!< TIMER interrupt flag register */ +#define TIMER_SWEVG(timerx) REG32((timerx) + 0x14U) /*!< TIMER software event generation register */ +#define TIMER_CHCTL0(timerx) REG32((timerx) + 0x18U) /*!< TIMER channel control register 0 */ +#define TIMER_CHCTL1(timerx) REG32((timerx) + 0x1CU) /*!< TIMER channel control register 1 */ +#define TIMER_CHCTL2(timerx) REG32((timerx) + 0x20U) /*!< TIMER channel control register 2 */ +#define TIMER_CNT(timerx) REG32((timerx) + 0x24U) /*!< TIMER counter register */ +#define TIMER_PSC(timerx) REG32((timerx) + 0x28U) /*!< TIMER prescaler register */ +#define TIMER_CAR(timerx) REG32((timerx) + 0x2CU) /*!< TIMER counter auto reload register */ +#define TIMER_CREP(timerx) REG32((timerx) + 0x30U) /*!< TIMER counter repetition register */ +#define TIMER_CH0CV(timerx) REG32((timerx) + 0x34U) /*!< TIMER channel 0 capture/compare value register */ +#define TIMER_CH1CV(timerx) REG32((timerx) + 0x38U) /*!< TIMER channel 1 capture/compare value register */ +#define TIMER_CH2CV(timerx) REG32((timerx) + 0x3CU) /*!< TIMER channel 2 capture/compare value register */ +#define TIMER_CH3CV(timerx) REG32((timerx) + 0x40U) /*!< TIMER channel 3 capture/compare value register */ +#define TIMER_CCHP(timerx) REG32((timerx) + 0x44U) /*!< TIMER channel complementary protection register */ +#define TIMER_DMACFG(timerx) REG32((timerx) + 0x48U) /*!< TIMER DMA configuration register */ +#define TIMER_DMATB(timerx) REG32((timerx) + 0x4CU) /*!< TIMER DMA transfer buffer register */ + +/* bits definitions */ +/* TIMER_CTL0 */ +#define TIMER_CTL0_CEN BIT(0) /*!< TIMER counter enable */ +#define TIMER_CTL0_UPDIS BIT(1) /*!< update disable */ +#define TIMER_CTL0_UPS BIT(2) /*!< update source */ +#define TIMER_CTL0_SPM BIT(3) /*!< single pulse mode */ +#define TIMER_CTL0_DIR BIT(4) /*!< timer counter direction */ +#define TIMER_CTL0_CAM BITS(5,6) /*!< center-aligned mode selection */ +#define TIMER_CTL0_ARSE BIT(7) /*!< auto-reload shadow enable */ +#define TIMER_CTL0_CKDIV BITS(8,9) /*!< clock division */ + +/* TIMER_CTL1 */ +#define TIMER_CTL1_CCSE BIT(0) /*!< commutation control shadow enable */ +#define TIMER_CTL1_CCUC BIT(2) /*!< commutation control shadow register update control */ +#define TIMER_CTL1_DMAS BIT(3) /*!< DMA request source selection */ +#define TIMER_CTL1_MMC BITS(4,6) /*!< master mode control */ +#define TIMER_CTL1_TI0S BIT(7) /*!< channel 0 trigger input selection(hall mode selection) */ +#define TIMER_CTL1_ISO0 BIT(8) /*!< idle state of channel 0 output */ +#define TIMER_CTL1_ISO0N BIT(9) /*!< idle state of channel 0 complementary output */ +#define TIMER_CTL1_ISO1 BIT(10) /*!< idle state of channel 1 output */ +#define TIMER_CTL1_ISO1N BIT(11) /*!< idle state of channel 1 complementary output */ +#define TIMER_CTL1_ISO2 BIT(12) /*!< idle state of channel 2 output */ +#define TIMER_CTL1_ISO2N BIT(13) /*!< idle state of channel 2 complementary output */ +#define TIMER_CTL1_ISO3 BIT(14) /*!< idle state of channel 3 output */ + +/* TIMER_SMCFG */ +#define TIMER_SMCFG_SMC BITS(0,2) /*!< slave mode control */ +#define TIMER_SMCFG_TRGS BITS(4,6) /*!< trigger selection */ +#define TIMER_SMCFG_MSM BIT(7) /*!< master-slave mode */ +#define TIMER_SMCFG_ETFC BITS(8,11) /*!< external trigger filter control */ +#define TIMER_SMCFG_ETPSC BITS(12,13) /*!< external trigger prescaler */ +#define TIMER_SMCFG_SMC1 BIT(14) /*!< part of SMC for enable external clock mode 1 */ +#define TIMER_SMCFG_ETP BIT(15) /*!< external trigger polarity */ + +/* TIMER_DMAINTEN */ +#define TIMER_DMAINTEN_UPIE BIT(0) /*!< update interrupt enable */ +#define TIMER_DMAINTEN_CH0IE BIT(1) /*!< channel 0 capture/compare interrupt enable */ +#define TIMER_DMAINTEN_CH1IE BIT(2) /*!< channel 1 capture/compare interrupt enable */ +#define TIMER_DMAINTEN_CH2IE BIT(3) /*!< channel 2 capture/compare interrupt enable */ +#define TIMER_DMAINTEN_CH3IE BIT(4) /*!< channel 3 capture/compare interrupt enable */ +#define TIMER_DMAINTEN_CMTIE BIT(5) /*!< commutation interrupt request enable */ +#define TIMER_DMAINTEN_TRGIE BIT(6) /*!< trigger interrupt enable */ +#define TIMER_DMAINTEN_BRKIE BIT(7) /*!< break interrupt enable */ +#define TIMER_DMAINTEN_UPDEN BIT(8) /*!< update DMA request enable */ +#define TIMER_DMAINTEN_CH0DEN BIT(9) /*!< channel 0 capture/compare DMA request enable */ +#define TIMER_DMAINTEN_CH1DEN BIT(10) /*!< channel 1 capture/compare DMA request enable */ +#define TIMER_DMAINTEN_CH2DEN BIT(11) /*!< channel 2 capture/compare DMA request enable */ +#define TIMER_DMAINTEN_CH3DEN BIT(12) /*!< channel 3 capture/compare DMA request enable */ +#define TIMER_DMAINTEN_CMTDEN BIT(13) /*!< commutation DMA request enable */ +#define TIMER_DMAINTEN_TRGDEN BIT(14) /*!< trigger DMA request enable */ + +/* TIMER_INTF */ +#define TIMER_INTF_UPIF BIT(0) /*!< update interrupt flag */ +#define TIMER_INTF_CH0IF BIT(1) /*!< channel 0 capture/compare interrupt flag */ +#define TIMER_INTF_CH1IF BIT(2) /*!< channel 1 capture/compare interrupt flag */ +#define TIMER_INTF_CH2IF BIT(3) /*!< channel 2 capture/compare interrupt flag */ +#define TIMER_INTF_CH3IF BIT(4) /*!< channel 3 capture/compare interrupt flag */ +#define TIMER_INTF_CMTIF BIT(5) /*!< channel commutation interrupt flag */ +#define TIMER_INTF_TRGIF BIT(6) /*!< trigger interrupt flag */ +#define TIMER_INTF_BRKIF BIT(7) /*!< break interrupt flag */ +#define TIMER_INTF_CH0OF BIT(9) /*!< channel 0 over capture flag */ +#define TIMER_INTF_CH1OF BIT(10) /*!< channel 1 over capture flag */ +#define TIMER_INTF_CH2OF BIT(11) /*!< channel 2 over capture flag */ +#define TIMER_INTF_CH3OF BIT(12) /*!< channel 3 over capture flag */ + +/* TIMER_SWEVG */ +#define TIMER_SWEVG_UPG BIT(0) /*!< update event generate */ +#define TIMER_SWEVG_CH0G BIT(1) /*!< channel 0 capture or compare event generation */ +#define TIMER_SWEVG_CH1G BIT(2) /*!< channel 1 capture or compare event generation */ +#define TIMER_SWEVG_CH2G BIT(3) /*!< channel 2 capture or compare event generation */ +#define TIMER_SWEVG_CH3G BIT(4) /*!< channel 3 capture or compare event generation */ +#define TIMER_SWEVG_CMTG BIT(5) /*!< channel commutation event generation */ +#define TIMER_SWEVG_TRGG BIT(6) /*!< trigger event generation */ +#define TIMER_SWEVG_BRKG BIT(7) /*!< break event generation */ + +/* TIMER_CHCTL0 */ +/* output compare mode */ +#define TIMER_CHCTL0_CH0MS BITS(0,1) /*!< channel 0 mode selection */ +#define TIMER_CHCTL0_CH0COMFEN BIT(2) /*!< channel 0 output compare fast enable */ +#define TIMER_CHCTL0_CH0COMSEN BIT(3) /*!< channel 0 output compare shadow enable */ +#define TIMER_CHCTL0_CH0COMCTL BITS(4,6) /*!< channel 0 output compare control */ +#define TIMER_CHCTL0_CH0COMCEN BIT(7) /*!< channel 0 output compare clear enable */ +#define TIMER_CHCTL0_CH1MS BITS(8,9) /*!< channel 1 mode selection */ +#define TIMER_CHCTL0_CH1COMFEN BIT(10) /*!< channel 1 output compare fast enable */ +#define TIMER_CHCTL0_CH1COMSEN BIT(11) /*!< channel 1 output compare shadow enable */ +#define TIMER_CHCTL0_CH1COMCTL BITS(12,14) /*!< channel 1 output compare control */ +#define TIMER_CHCTL0_CH1COMCEN BIT(15) /*!< channel 1 output compare clear enable */ +/* input capture mode */ +#define TIMER_CHCTL0_CH0CAPPSC BITS(2,3) /*!< channel 0 input capture prescaler */ +#define TIMER_CHCTL0_CH0CAPFLT BITS(4,7) /*!< channel 0 input capture filter control */ +#define TIMER_CHCTL0_CH1CAPPSC BITS(10,11) /*!< channel 1 input capture prescaler */ +#define TIMER_CHCTL0_CH1CAPFLT BITS(12,15) /*!< channel 1 input capture filter control */ + +/* TIMER_CHCTL1 */ +/* output compare mode */ +#define TIMER_CHCTL1_CH2MS BITS(0,1) /*!< channel 2 mode selection */ +#define TIMER_CHCTL1_CH2COMFEN BIT(2) /*!< channel 2 output compare fast enable */ +#define TIMER_CHCTL1_CH2COMSEN BIT(3) /*!< channel 2 output compare shadow enable */ +#define TIMER_CHCTL1_CH2COMCTL BITS(4,6) /*!< channel 2 output compare control */ +#define TIMER_CHCTL1_CH2COMCEN BIT(7) /*!< channel 2 output compare clear enable */ +#define TIMER_CHCTL1_CH3MS BITS(8,9) /*!< channel 3 mode selection */ +#define TIMER_CHCTL1_CH3COMFEN BIT(10) /*!< channel 3 output compare fast enable */ +#define TIMER_CHCTL1_CH3COMSEN BIT(11) /*!< channel 3 output compare shadow enable */ +#define TIMER_CHCTL1_CH3COMCTL BITS(12,14) /*!< channel 3 output compare control */ +#define TIMER_CHCTL1_CH3COMCEN BIT(15) /*!< channel 3 output compare clear enable */ +/* input capture mode */ +#define TIMER_CHCTL1_CH2CAPPSC BITS(2,3) /*!< channel 2 input capture prescaler */ +#define TIMER_CHCTL1_CH2CAPFLT BITS(4,7) /*!< channel 2 input capture filter control */ +#define TIMER_CHCTL1_CH3CAPPSC BITS(10,11) /*!< channel 3 input capture prescaler */ +#define TIMER_CHCTL1_CH3CAPFLT BITS(12,15) /*!< channel 3 input capture filter control */ + +/* TIMER_CHCTL2 */ +#define TIMER_CHCTL2_CH0EN BIT(0) /*!< channel 0 capture/compare function enable */ +#define TIMER_CHCTL2_CH0P BIT(1) /*!< channel 0 capture/compare function polarity */ +#define TIMER_CHCTL2_CH0NEN BIT(2) /*!< channel 0 complementary output enable */ +#define TIMER_CHCTL2_CH0NP BIT(3) /*!< channel 0 complementary output polarity */ +#define TIMER_CHCTL2_CH1EN BIT(4) /*!< channel 1 capture/compare function enable */ +#define TIMER_CHCTL2_CH1P BIT(5) /*!< channel 1 capture/compare function polarity */ +#define TIMER_CHCTL2_CH1NEN BIT(6) /*!< channel 1 complementary output enable */ +#define TIMER_CHCTL2_CH1NP BIT(7) /*!< channel 1 complementary output polarity */ +#define TIMER_CHCTL2_CH2EN BIT(8) /*!< channel 2 capture/compare function enable */ +#define TIMER_CHCTL2_CH2P BIT(9) /*!< channel 2 capture/compare function polarity */ +#define TIMER_CHCTL2_CH2NEN BIT(10) /*!< channel 2 complementary output enable */ +#define TIMER_CHCTL2_CH2NP BIT(11) /*!< channel 2 complementary output polarity */ +#define TIMER_CHCTL2_CH3EN BIT(12) /*!< channel 3 capture/compare function enable */ +#define TIMER_CHCTL2_CH3P BIT(13) /*!< channel 3 capture/compare function polarity */ + +/* TIMER_CNT */ +#define TIMER_CNT_CNT BITS(0,15) /*!< 16 bit timer counter */ + +/* TIMER_PSC */ +#define TIMER_PSC_PSC BITS(0,15) /*!< prescaler value of the counter clock */ + +/* TIMER_CAR */ +#define TIMER_CAR_CARL BITS(0,15) /*!< 16 bit counter auto reload value */ + +/* TIMER_CREP */ +#define TIMER_CREP_CREP BITS(0,7) /*!< counter repetition value */ + +/* TIMER_CH0CV */ +#define TIMER_CH0CV_CH0VAL BITS(0,15) /*!< 16 bit capture/compare value of channel 0 */ + +/* TIMER_CH1CV */ +#define TIMER_CH1CV_CH1VAL BITS(0,15) /*!< 16 bit capture/compare value of channel 1 */ + +/* TIMER_CH2CV */ +#define TIMER_CH2CV_CH2VAL BITS(0,15) /*!< 16 bit capture/compare value of channel 2 */ + +/* TIMER_CH3CV */ +#define TIMER_CH3CV_CH3VAL BITS(0,15) /*!< 16 bit capture/compare value of channel 3 */ + +/* TIMER_CCHP */ +#define TIMER_CCHP_DTCFG BITS(0,7) /*!< dead time configure */ +#define TIMER_CCHP_PROT BITS(8,9) /*!< complementary register protect control */ +#define TIMER_CCHP_IOS BIT(10) /*!< idle mode off-state configure */ +#define TIMER_CCHP_ROS BIT(11) /*!< run mode off-state configure */ +#define TIMER_CCHP_BRKEN BIT(12) /*!< break enable */ +#define TIMER_CCHP_BRKP BIT(13) /*!< break polarity */ +#define TIMER_CCHP_OAEN BIT(14) /*!< output automatic enable */ +#define TIMER_CCHP_POEN BIT(15) /*!< primary output enable */ + +/* TIMER_DMACFG */ +#define TIMER_DMACFG_DMATA BITS(0,4) /*!< DMA transfer access start address */ +#define TIMER_DMACFG_DMATC BITS(8,12) /*!< DMA transfer count */ + +/* TIMER_DMATB */ +#define TIMER_DMATB_DMATB BITS(0,15) /*!< DMA transfer buffer address */ + +/* constants definitions */ +/* TIMER init parameter structure definitions */ +typedef struct +{ + uint16_t prescaler; /*!< prescaler value */ + uint16_t alignedmode; /*!< aligned mode */ + uint16_t counterdirection; /*!< counter direction */ + uint32_t period; /*!< period value */ + uint16_t clockdivision; /*!< clock division value */ + uint8_t repetitioncounter; /*!< the counter repetition value */ +}timer_parameter_struct; + +/* break parameter structure definitions*/ +typedef struct +{ + uint16_t runoffstate; /*!< run mode off-state */ + uint16_t ideloffstate; /*!< idle mode off-state */ + uint16_t deadtime; /*!< dead time */ + uint16_t breakpolarity; /*!< break polarity */ + uint16_t outputautostate; /*!< output automatic enable */ + uint16_t protectmode; /*!< complementary register protect control */ + uint16_t breakstate; /*!< break enable */ +}timer_break_parameter_struct; + +/* channel output parameter structure definitions */ +typedef struct +{ + uint16_t outputstate; /*!< channel output state */ + uint16_t outputnstate; /*!< channel complementary output state */ + uint16_t ocpolarity; /*!< channel output polarity */ + uint16_t ocnpolarity; /*!< channel complementary output polarity */ + uint16_t ocidlestate; /*!< idle state of channel output */ + uint16_t ocnidlestate; /*!< idle state of channel complementary output */ +}timer_oc_parameter_struct; + +/* channel input parameter structure definitions */ +typedef struct +{ + uint16_t icpolarity; /*!< channel input polarity */ + uint16_t icselection; /*!< channel input mode selection */ + uint16_t icprescaler; /*!< channel input capture prescaler */ + uint16_t icfilter; /*!< channel input capture filter control */ +}timer_ic_parameter_struct; + +/* TIMER interrupt enable or disable */ +#define TIMER_INT_UP TIMER_DMAINTEN_UPIE /*!< update interrupt */ +#define TIMER_INT_CH0 TIMER_DMAINTEN_CH0IE /*!< channel 0 interrupt */ +#define TIMER_INT_CH1 TIMER_DMAINTEN_CH1IE /*!< channel 1 interrupt */ +#define TIMER_INT_CH2 TIMER_DMAINTEN_CH2IE /*!< channel 2 interrupt */ +#define TIMER_INT_CH3 TIMER_DMAINTEN_CH3IE /*!< channel 3 interrupt */ +#define TIMER_INT_CMT TIMER_DMAINTEN_CMTIE /*!< channel commutation interrupt flag */ +#define TIMER_INT_TRG TIMER_DMAINTEN_TRGIE /*!< trigger interrupt */ +#define TIMER_INT_BRK TIMER_DMAINTEN_BRKIE /*!< break interrupt */ + +/* TIMER interrupt flag */ +#define TIMER_INT_FLAG_UP TIMER_INT_UP /*!< update interrupt */ +#define TIMER_INT_FLAG_CH0 TIMER_INT_CH0 /*!< channel 0 interrupt */ +#define TIMER_INT_FLAG_CH1 TIMER_INT_CH1 /*!< channel 1 interrupt */ +#define TIMER_INT_FLAG_CH2 TIMER_INT_CH2 /*!< channel 2 interrupt */ +#define TIMER_INT_FLAG_CH3 TIMER_INT_CH3 /*!< channel 3 interrupt */ +#define TIMER_INT_FLAG_CMT TIMER_INT_CMT /*!< channel commutation interrupt flag */ +#define TIMER_INT_FLAG_TRG TIMER_INT_TRG /*!< trigger interrupt */ +#define TIMER_INT_FLAG_BRK TIMER_INT_BRK + +/* TIMER flag */ +#define TIMER_FLAG_UP TIMER_INTF_UPIF /*!< update flag */ +#define TIMER_FLAG_CH0 TIMER_INTF_CH0IF /*!< channel 0 flag */ +#define TIMER_FLAG_CH1 TIMER_INTF_CH1IF /*!< channel 1 flag */ +#define TIMER_FLAG_CH2 TIMER_INTF_CH2IF /*!< channel 2 flag */ +#define TIMER_FLAG_CH3 TIMER_INTF_CH3IF /*!< channel 3 flag */ +#define TIMER_FLAG_CMT TIMER_INTF_CMTIF /*!< channel commutation flag */ +#define TIMER_FLAG_TRG TIMER_INTF_TRGIF /*!< trigger flag */ +#define TIMER_FLAG_BRK TIMER_INTF_BRKIF /*!< break flag */ +#define TIMER_FLAG_CH0O TIMER_INTF_CH0OF /*!< channel 0 overcapture flag */ +#define TIMER_FLAG_CH1O TIMER_INTF_CH1OF /*!< channel 1 overcapture flag */ +#define TIMER_FLAG_CH2O TIMER_INTF_CH2OF /*!< channel 2 overcapture flag */ +#define TIMER_FLAG_CH3O TIMER_INTF_CH3OF /*!< channel 3 overcapture flag */ + +/* TIMER DMA source enable */ +#define TIMER_DMA_UPD ((uint16_t)TIMER_DMAINTEN_UPDEN) /*!< update DMA enable */ +#define TIMER_DMA_CH0D ((uint16_t)TIMER_DMAINTEN_CH0DEN) /*!< channel 0 DMA enable */ +#define TIMER_DMA_CH1D ((uint16_t)TIMER_DMAINTEN_CH1DEN) /*!< channel 1 DMA enable */ +#define TIMER_DMA_CH2D ((uint16_t)TIMER_DMAINTEN_CH2DEN) /*!< channel 2 DMA enable */ +#define TIMER_DMA_CH3D ((uint16_t)TIMER_DMAINTEN_CH3DEN) /*!< channel 3 DMA enable */ +#define TIMER_DMA_CMTD ((uint16_t)TIMER_DMAINTEN_CMTDEN) /*!< commutation DMA request enable */ +#define TIMER_DMA_TRGD ((uint16_t)TIMER_DMAINTEN_TRGDEN) /*!< trigger DMA enable */ + +/* channel DMA request source selection */ +#define TIMER_DMAREQUEST_UPDATEEVENT TIMER_CTL1_DMAS /*!< DMA request of channel n is sent when update event occurs */ +#define TIMER_DMAREQUEST_CHANNELEVENT ((uint32_t)0x00000000U) /*!< DMA request of channel n is sent when channel n event occurs */ + +/* DMA access base address */ +#define DMACFG_DMATA(regval) (BITS(0, 4) & ((uint32_t)(regval) << 0U)) +#define TIMER_DMACFG_DMATA_CTL0 DMACFG_DMATA(0) /*!< DMA transfer address is TIMER_CTL0 */ +#define TIMER_DMACFG_DMATA_CTL1 DMACFG_DMATA(1) /*!< DMA transfer address is TIMER_CTL1 */ +#define TIMER_DMACFG_DMATA_SMCFG DMACFG_DMATA(2) /*!< DMA transfer address is TIMER_SMCFG */ +#define TIMER_DMACFG_DMATA_DMAINTEN DMACFG_DMATA(3) /*!< DMA transfer address is TIMER_DMAINTEN */ +#define TIMER_DMACFG_DMATA_INTF DMACFG_DMATA(4) /*!< DMA transfer address is TIMER_INTF */ +#define TIMER_DMACFG_DMATA_SWEVG DMACFG_DMATA(5) /*!< DMA transfer address is TIMER_SWEVG */ +#define TIMER_DMACFG_DMATA_CHCTL0 DMACFG_DMATA(6) /*!< DMA transfer address is TIMER_CHCTL0 */ +#define TIMER_DMACFG_DMATA_CHCTL1 DMACFG_DMATA(7) /*!< DMA transfer address is TIMER_CHCTL1 */ +#define TIMER_DMACFG_DMATA_CHCTL2 DMACFG_DMATA(8) /*!< DMA transfer address is TIMER_CHCTL2 */ +#define TIMER_DMACFG_DMATA_CNT DMACFG_DMATA(9) /*!< DMA transfer address is TIMER_CNT */ +#define TIMER_DMACFG_DMATA_PSC DMACFG_DMATA(10) /*!< DMA transfer address is TIMER_PSC */ +#define TIMER_DMACFG_DMATA_CAR DMACFG_DMATA(11) /*!< DMA transfer address is TIMER_CAR */ +#define TIMER_DMACFG_DMATA_CREP DMACFG_DMATA(12) /*!< DMA transfer address is TIMER_CREP */ +#define TIMER_DMACFG_DMATA_CH0CV DMACFG_DMATA(13) /*!< DMA transfer address is TIMER_CH0CV */ +#define TIMER_DMACFG_DMATA_CH1CV DMACFG_DMATA(14) /*!< DMA transfer address is TIMER_CH1CV */ +#define TIMER_DMACFG_DMATA_CH2CV DMACFG_DMATA(15) /*!< DMA transfer address is TIMER_CH2CV */ +#define TIMER_DMACFG_DMATA_CH3CV DMACFG_DMATA(16) /*!< DMA transfer address is TIMER_CH3CV */ +#define TIMER_DMACFG_DMATA_CCHP DMACFG_DMATA(17) /*!< DMA transfer address is TIMER_CCHP */ +#define TIMER_DMACFG_DMATA_DMACFG DMACFG_DMATA(18) /*!< DMA transfer address is TIMER_DMACFG */ +#define TIMER_DMACFG_DMATA_DMATB DMACFG_DMATA(19) /*!< DMA transfer address is TIMER_DMATB */ + +/* DMA access burst length */ +#define DMACFG_DMATC(regval) (BITS(8, 12) & ((uint32_t)(regval) << 8U)) +#define TIMER_DMACFG_DMATC_1TRANSFER DMACFG_DMATC(0) /*!< DMA transfer 1 time */ +#define TIMER_DMACFG_DMATC_2TRANSFER DMACFG_DMATC(1) /*!< DMA transfer 2 times */ +#define TIMER_DMACFG_DMATC_3TRANSFER DMACFG_DMATC(2) /*!< DMA transfer 3 times */ +#define TIMER_DMACFG_DMATC_4TRANSFER DMACFG_DMATC(3) /*!< DMA transfer 4 times */ +#define TIMER_DMACFG_DMATC_5TRANSFER DMACFG_DMATC(4) /*!< DMA transfer 5 times */ +#define TIMER_DMACFG_DMATC_6TRANSFER DMACFG_DMATC(5) /*!< DMA transfer 6 times */ +#define TIMER_DMACFG_DMATC_7TRANSFER DMACFG_DMATC(6) /*!< DMA transfer 7 times */ +#define TIMER_DMACFG_DMATC_8TRANSFER DMACFG_DMATC(7) /*!< DMA transfer 8 times */ +#define TIMER_DMACFG_DMATC_9TRANSFER DMACFG_DMATC(8) /*!< DMA transfer 9 times */ +#define TIMER_DMACFG_DMATC_10TRANSFER DMACFG_DMATC(9) /*!< DMA transfer 10 times */ +#define TIMER_DMACFG_DMATC_11TRANSFER DMACFG_DMATC(10) /*!< DMA transfer 11 times */ +#define TIMER_DMACFG_DMATC_12TRANSFER DMACFG_DMATC(11) /*!< DMA transfer 12 times */ +#define TIMER_DMACFG_DMATC_13TRANSFER DMACFG_DMATC(12) /*!< DMA transfer 13 times */ +#define TIMER_DMACFG_DMATC_14TRANSFER DMACFG_DMATC(13) /*!< DMA transfer 14 times */ +#define TIMER_DMACFG_DMATC_15TRANSFER DMACFG_DMATC(14) /*!< DMA transfer 15 times */ +#define TIMER_DMACFG_DMATC_16TRANSFER DMACFG_DMATC(15) /*!< DMA transfer 16 times */ +#define TIMER_DMACFG_DMATC_17TRANSFER DMACFG_DMATC(16) /*!< DMA transfer 17 times */ +#define TIMER_DMACFG_DMATC_18TRANSFER DMACFG_DMATC(17) /*!< DMA transfer 18 times */ + +/* TIMER software event generation source */ +#define TIMER_EVENT_SRC_UPG ((uint16_t)0x0001U) /*!< update event generation */ +#define TIMER_EVENT_SRC_CH0G ((uint16_t)0x0002U) /*!< channel 0 capture or compare event generation */ +#define TIMER_EVENT_SRC_CH1G ((uint16_t)0x0004U) /*!< channel 1 capture or compare event generation */ +#define TIMER_EVENT_SRC_CH2G ((uint16_t)0x0008U) /*!< channel 2 capture or compare event generation */ +#define TIMER_EVENT_SRC_CH3G ((uint16_t)0x0010U) /*!< channel 3 capture or compare event generation */ +#define TIMER_EVENT_SRC_CMTG ((uint16_t)0x0020U) /*!< channel commutation event generation */ +#define TIMER_EVENT_SRC_TRGG ((uint16_t)0x0040U) /*!< trigger event generation */ +#define TIMER_EVENT_SRC_BRKG ((uint16_t)0x0080U) /*!< break event generation */ + +/* center-aligned mode selection */ +#define CTL0_CAM(regval) ((uint16_t)(BITS(5, 6) & ((uint32_t)(regval) << 5U))) +#define TIMER_COUNTER_EDGE CTL0_CAM(0) /*!< edge-aligned mode */ +#define TIMER_COUNTER_CENTER_DOWN CTL0_CAM(1) /*!< center-aligned and counting down assert mode */ +#define TIMER_COUNTER_CENTER_UP CTL0_CAM(2) /*!< center-aligned and counting up assert mode */ +#define TIMER_COUNTER_CENTER_BOTH CTL0_CAM(3) /*!< center-aligned and counting up/down assert mode */ + +/* TIMER prescaler reload mode */ +#define TIMER_PSC_RELOAD_NOW TIMER_SWEVG_UPG /*!< the prescaler is loaded right now */ +#define TIMER_PSC_RELOAD_UPDATE ((uint32_t)0x00000000U) /*!< the prescaler is loaded at the next update event */ + +/* count direction */ +#define TIMER_COUNTER_UP ((uint16_t)0x0000U) /*!< counter up direction */ +#define TIMER_COUNTER_DOWN ((uint16_t)TIMER_CTL0_DIR) /*!< counter down direction */ + +/* specify division ratio between TIMER clock and dead-time and sampling clock */ +#define CTL0_CKDIV(regval) ((uint16_t)(BITS(8, 9) & ((uint32_t)(regval) << 8U))) +#define TIMER_CKDIV_DIV1 CTL0_CKDIV(0) /*!< clock division value is 1,fDTS=fTIMER_CK */ +#define TIMER_CKDIV_DIV2 CTL0_CKDIV(1) /*!< clock division value is 2,fDTS= fTIMER_CK/2 */ +#define TIMER_CKDIV_DIV4 CTL0_CKDIV(2) /*!< clock division value is 4, fDTS= fTIMER_CK/4 */ + +/* single pulse mode */ +#define TIMER_SP_MODE_SINGLE TIMER_CTL0_SPM /*!< single pulse mode */ +#define TIMER_SP_MODE_REPETITIVE ((uint32_t)0x00000000U) /*!< repetitive pulse mode */ + +/* update source */ +#define TIMER_UPDATE_SRC_REGULAR TIMER_CTL0_UPS /*!< update generate only by counter overflow/underflow */ +#define TIMER_UPDATE_SRC_GLOBAL ((uint32_t)0x00000000U) /*!< update generate by setting of UPG bit or the counter overflow/underflow,or the slave mode controller trigger */ + +/* run mode off-state configure */ +#define TIMER_ROS_STATE_ENABLE ((uint16_t)TIMER_CCHP_ROS) /*!< when POEN bit is set, the channel output signals(CHx_O/CHx_ON) are enabled, with relationship to CHxEN/CHxNEN bits */ +#define TIMER_ROS_STATE_DISABLE ((uint16_t)0x0000U) /*!< when POEN bit is set, the channel output signals(CHx_O/CHx_ON) are disabled */ + +/* idle mode off-state configure */ +#define TIMER_IOS_STATE_ENABLE ((uint16_t)TIMER_CCHP_IOS) /*!< when POEN bit is reset, he channel output signals(CHx_O/CHx_ON) are enabled, with relationship to CHxEN/CHxNEN bits */ +#define TIMER_IOS_STATE_DISABLE ((uint16_t)0x0000U) /*!< when POEN bit is reset, the channel output signals(CHx_O/CHx_ON) are disabled */ + +/* break input polarity */ +#define TIMER_BREAK_POLARITY_LOW ((uint16_t)0x0000U) /*!< break input polarity is low */ +#define TIMER_BREAK_POLARITY_HIGH ((uint16_t)TIMER_CCHP_BRKP) /*!< break input polarity is high */ + +/* output automatic enable */ +#define TIMER_OUTAUTO_ENABLE ((uint16_t)TIMER_CCHP_OAEN) /*!< output automatic enable */ +#define TIMER_OUTAUTO_DISABLE ((uint16_t)0x0000U) /*!< output automatic disable */ + +/* complementary register protect control */ +#define CCHP_PROT(regval) ((uint16_t)(BITS(8, 9) & ((uint32_t)(regval) << 8U))) +#define TIMER_CCHP_PROT_OFF CCHP_PROT(0) /*!< protect disable */ +#define TIMER_CCHP_PROT_0 CCHP_PROT(1) /*!< PROT mode 0 */ +#define TIMER_CCHP_PROT_1 CCHP_PROT(2) /*!< PROT mode 1 */ +#define TIMER_CCHP_PROT_2 CCHP_PROT(3) /*!< PROT mode 2 */ + +/* break input enable */ +#define TIMER_BREAK_ENABLE ((uint16_t)TIMER_CCHP_BRKEN) /*!< break input enable */ +#define TIMER_BREAK_DISABLE ((uint16_t)0x0000U) /*!< break input disable */ + +/* TIMER channel n(n=0,1,2,3) */ +#define TIMER_CH_0 ((uint16_t)0x0000U) /*!< TIMER channel 0(TIMERx(x=0..4,7..13)) */ +#define TIMER_CH_1 ((uint16_t)0x0001U) /*!< TIMER channel 1(TIMERx(x=0..4,7,8,11)) */ +#define TIMER_CH_2 ((uint16_t)0x0002U) /*!< TIMER channel 2(TIMERx(x=0..4,7)) */ +#define TIMER_CH_3 ((uint16_t)0x0003U) /*!< TIMER channel 3(TIMERx(x=0..4,7)) */ + +/* channel enable state */ +#define TIMER_CCX_ENABLE ((uint16_t)0x0001U) /*!< channel enable */ +#define TIMER_CCX_DISABLE ((uint16_t)0x0000U) /*!< channel disable */ + +/* channel complementary output enable state */ +#define TIMER_CCXN_ENABLE ((uint16_t)0x0004U) /*!< channel complementary enable */ +#define TIMER_CCXN_DISABLE ((uint16_t)0x0000U) /*!< channel complementary disable */ + +/* channel output polarity */ +#define TIMER_OC_POLARITY_HIGH ((uint16_t)0x0000U) /*!< channel output polarity is high */ +#define TIMER_OC_POLARITY_LOW ((uint16_t)0x0002U) /*!< channel output polarity is low */ + +/* channel complementary output polarity */ +#define TIMER_OCN_POLARITY_HIGH ((uint16_t)0x0000U) /*!< channel complementary output polarity is high */ +#define TIMER_OCN_POLARITY_LOW ((uint16_t)0x0008U) /*!< channel complementary output polarity is low */ + +/* idle state of channel output */ +#define TIMER_OC_IDLE_STATE_HIGH ((uint16_t)0x0100) /*!< idle state of channel output is high */ +#define TIMER_OC_IDLE_STATE_LOW ((uint16_t)0x0000) /*!< idle state of channel output is low */ + +/* idle state of channel complementary output */ +#define TIMER_OCN_IDLE_STATE_HIGH ((uint16_t)0x0200U) /*!< idle state of channel complementary output is high */ +#define TIMER_OCN_IDLE_STATE_LOW ((uint16_t)0x0000U) /*!< idle state of channel complementary output is low */ + +/* channel output compare mode */ +#define TIMER_OC_MODE_TIMING ((uint16_t)0x0000U) /*!< frozen mode */ +#define TIMER_OC_MODE_ACTIVE ((uint16_t)0x0010U) /*!< set the channel output */ +#define TIMER_OC_MODE_INACTIVE ((uint16_t)0x0020U) /*!< clear the channel output */ +#define TIMER_OC_MODE_TOGGLE ((uint16_t)0x0030U) /*!< toggle on match */ +#define TIMER_OC_MODE_LOW ((uint16_t)0x0040U) /*!< force low mode */ +#define TIMER_OC_MODE_HIGH ((uint16_t)0x0050U) /*!< force high mode */ +#define TIMER_OC_MODE_PWM0 ((uint16_t)0x0060U) /*!< PWM0 mode */ +#define TIMER_OC_MODE_PWM1 ((uint16_t)0x0070U) /*!< PWM1 mode*/ + +/* channel output compare shadow enable */ +#define TIMER_OC_SHADOW_ENABLE ((uint16_t)0x0008U) /*!< channel output shadow state enable */ +#define TIMER_OC_SHADOW_DISABLE ((uint16_t)0x0000U) /*!< channel output shadow state disable */ + +/* channel output compare fast enable */ +#define TIMER_OC_FAST_ENABLE ((uint16_t)0x0004) /*!< channel output fast function enable */ +#define TIMER_OC_FAST_DISABLE ((uint16_t)0x0000) /*!< channel output fast function disable */ + +/* channel output compare clear enable */ +#define TIMER_OC_CLEAR_ENABLE ((uint16_t)0x0080U) /*!< channel output clear function enable */ +#define TIMER_OC_CLEAR_DISABLE ((uint16_t)0x0000U) /*!< channel output clear function disable */ + +/* channel control shadow register update control */ +#define TIMER_UPDATECTL_CCU ((uint32_t)0x00000000U) /*!< the shadow registers update by when CMTG bit is set */ +#define TIMER_UPDATECTL_CCUTRI TIMER_CTL1_CCUC /*!< the shadow registers update by when CMTG bit is set or an rising edge of TRGI occurs */ + +/* channel input capture polarity */ +#define TIMER_IC_POLARITY_RISING ((uint16_t)0x0000U) /*!< input capture rising edge */ +#define TIMER_IC_POLARITY_FALLING ((uint16_t)0x0002U) /*!< input capture falling edge */ +#define TIMER_IC_POLARITY_BOTH_EDGE ((uint16_t)0x000AU) /*!< input capture both edge */ + +/* timer input capture selection */ +#define TIMER_IC_SELECTION_DIRECTTI ((uint16_t)0x0001U) /*!< channel y is configured as input and icy is mapped on CIy */ +#define TIMER_IC_SELECTION_INDIRECTTI ((uint16_t)0x0002U) /*!< channel y is configured as input and icy is mapped on opposite input */ +#define TIMER_IC_SELECTION_ITS ((uint16_t)0x0003U) /*!< channel y is configured as input and icy is mapped on ITS */ + +/* channel input capture prescaler */ +#define TIMER_IC_PSC_DIV1 ((uint16_t)0x0000U) /*!< no prescaler */ +#define TIMER_IC_PSC_DIV2 ((uint16_t)0x0004U) /*!< divided by 2 */ +#define TIMER_IC_PSC_DIV4 ((uint16_t)0x0008U) /*!< divided by 4 */ +#define TIMER_IC_PSC_DIV8 ((uint16_t)0x000CU) /*!< divided by 8 */ + +/* trigger selection */ +#define SMCFG_TRGSEL(regval) (BITS(4, 6) & ((uint32_t)(regval) << 4U)) +#define TIMER_SMCFG_TRGSEL_ITI0 SMCFG_TRGSEL(0) /*!< internal trigger 0 */ +#define TIMER_SMCFG_TRGSEL_ITI1 SMCFG_TRGSEL(1) /*!< internal trigger 1 */ +#define TIMER_SMCFG_TRGSEL_ITI2 SMCFG_TRGSEL(2) /*!< internal trigger 2 */ +#define TIMER_SMCFG_TRGSEL_ITI3 SMCFG_TRGSEL(3) /*!< internal trigger 3 */ +#define TIMER_SMCFG_TRGSEL_CI0F_ED SMCFG_TRGSEL(4) /*!< TI0 Edge Detector */ +#define TIMER_SMCFG_TRGSEL_CI0FE0 SMCFG_TRGSEL(5) /*!< filtered TIMER input 0 */ +#define TIMER_SMCFG_TRGSEL_CI1FE1 SMCFG_TRGSEL(6) /*!< filtered TIMER input 1 */ +#define TIMER_SMCFG_TRGSEL_ETIFP SMCFG_TRGSEL(7) /*!< external trigger */ + +/* master mode control */ +#define CTL1_MMC(regval) (BITS(4, 6) & ((uint32_t)(regval) << 4U)) +#define TIMER_TRI_OUT_SRC_RESET CTL1_MMC(0) /*!< the UPG bit as trigger output */ +#define TIMER_TRI_OUT_SRC_ENABLE CTL1_MMC(1) /*!< the counter enable signal TIMER_CTL0_CEN as trigger output */ +#define TIMER_TRI_OUT_SRC_UPDATE CTL1_MMC(2) /*!< update event as trigger output */ +#define TIMER_TRI_OUT_SRC_CH0 CTL1_MMC(3) /*!< a capture or a compare match occurred in channel 0 as trigger output TRGO */ +#define TIMER_TRI_OUT_SRC_O0CPRE CTL1_MMC(4) /*!< O0CPRE as trigger output */ +#define TIMER_TRI_OUT_SRC_O1CPRE CTL1_MMC(5) /*!< O1CPRE as trigger output */ +#define TIMER_TRI_OUT_SRC_O2CPRE CTL1_MMC(6) /*!< O2CPRE as trigger output */ +#define TIMER_TRI_OUT_SRC_O3CPRE CTL1_MMC(7) /*!< O3CPRE as trigger output */ + +/* slave mode control */ +#define SMCFG_SMC(regval) (BITS(0, 2) & ((uint32_t)(regval) << 0U)) +#define TIMER_SLAVE_MODE_DISABLE SMCFG_SMC(0) /*!< slave mode disable */ +#define TIMER_ENCODER_MODE0 SMCFG_SMC(1) /*!< encoder mode 0 */ +#define TIMER_ENCODER_MODE1 SMCFG_SMC(2) /*!< encoder mode 1 */ +#define TIMER_ENCODER_MODE2 SMCFG_SMC(3) /*!< encoder mode 2 */ +#define TIMER_SLAVE_MODE_RESTART SMCFG_SMC(4) /*!< restart mode */ +#define TIMER_SLAVE_MODE_PAUSE SMCFG_SMC(5) /*!< pause mode */ +#define TIMER_SLAVE_MODE_EVENT SMCFG_SMC(6) /*!< event mode */ +#define TIMER_SLAVE_MODE_EXTERNAL0 SMCFG_SMC(7) /*!< external clock mode 0 */ + +/* master slave mode selection */ +#define TIMER_MASTER_SLAVE_MODE_ENABLE TIMER_SMCFG_MSM /*!< master slave mode enable */ +#define TIMER_MASTER_SLAVE_MODE_DISABLE ((uint32_t)0x00000000U) /*!< master slave mode disable */ + +/* external trigger prescaler */ +#define SMCFG_ETPSC(regval) (BITS(12, 13) & ((uint32_t)(regval) << 12U)) +#define TIMER_EXT_TRI_PSC_OFF SMCFG_ETPSC(0) /*!< no divided */ +#define TIMER_EXT_TRI_PSC_DIV2 SMCFG_ETPSC(1) /*!< divided by 2 */ +#define TIMER_EXT_TRI_PSC_DIV4 SMCFG_ETPSC(2) /*!< divided by 4 */ +#define TIMER_EXT_TRI_PSC_DIV8 SMCFG_ETPSC(3) /*!< divided by 8 */ + +/* external trigger polarity */ +#define TIMER_ETP_FALLING TIMER_SMCFG_ETP /*!< active low or falling edge active */ +#define TIMER_ETP_RISING ((uint32_t)0x00000000U) /*!< active high or rising edge active */ + +/* channel 0 trigger input selection */ +#define TIMER_HALLINTERFACE_ENABLE TIMER_CTL1_TI0S /*!< TIMER hall sensor mode enable */ +#define TIMER_HALLINTERFACE_DISABLE ((uint32_t)0x00000000U) /*!< TIMER hall sensor mode disable */ + +/* TIMERx(x=0..4,7..13) write CHxVAL register selection */ +#define TIMER_CHVSEL_ENABLE ((uint16_t)TIMER_CFG_OUTSEL) /*!< write CHxVAL register selection enable */ +#define TIMER_CHVSEL_DISABLE ((uint16_t)0x0000U) /*!< write CHxVAL register selection disable */ + +/* function declarations */ +/* TIMER timebase */ +/* deinit a TIMER */ +void timer_deinit(uint32_t timer_periph); +/* initialize TIMER init parameter structure */ +void timer_struct_para_init(timer_parameter_struct* initpara); +/* initialize TIMER counter */ +void timer_init(uint32_t timer_periph, timer_parameter_struct* initpara); +/* enable a TIMER */ +void timer_enable(uint32_t timer_periph); +/* disable a TIMER */ +void timer_disable(uint32_t timer_periph); +/* enable the auto reload shadow function */ +void timer_auto_reload_shadow_enable(uint32_t timer_periph); +/* disable the auto reload shadow function */ +void timer_auto_reload_shadow_disable(uint32_t timer_periph); +/* enable the update event */ +void timer_update_event_enable(uint32_t timer_periph); +/* disable the update event */ +void timer_update_event_disable(uint32_t timer_periph); +/* set TIMER counter alignment mode */ +void timer_counter_alignment(uint32_t timer_periph, uint16_t aligned); +/* set TIMER counter up direction */ +void timer_counter_up_direction(uint32_t timer_periph); +/* set TIMER counter down direction */ +void timer_counter_down_direction(uint32_t timer_periph); +/* configure TIMER prescaler */ +void timer_prescaler_config(uint32_t timer_periph, uint16_t prescaler, uint32_t pscreload); +/* configure TIMER repetition register value */ +void timer_repetition_value_config(uint32_t timer_periph, uint8_t repetition); +/* configure TIMER autoreload register value */ +void timer_autoreload_value_config(uint32_t timer_periph, uint32_t autoreload); +/* configure TIMER counter register value */ +void timer_counter_value_config(uint32_t timer_periph, uint32_t counter); +/* read TIMER counter value */ +uint32_t timer_counter_read(uint32_t timer_periph); +/* read TIMER prescaler value */ +uint16_t timer_prescaler_read(uint32_t timer_periph); +/* configure TIMER single pulse mode */ +void timer_single_pulse_mode_config(uint32_t timer_periph, uint32_t spmode); +/* configure TIMER update source */ +void timer_update_source_config(uint32_t timer_periph, uint32_t update); + +/* timer DMA and event */ +/* enable the TIMER DMA */ +void timer_dma_enable(uint32_t timer_periph, uint16_t dma); +/* disable the TIMER DMA */ +void timer_dma_disable(uint32_t timer_periph, uint16_t dma); +/* channel DMA request source selection */ +void timer_channel_dma_request_source_select(uint32_t timer_periph, uint32_t dma_request); +/* configure the TIMER DMA transfer */ +void timer_dma_transfer_config(uint32_t timer_periph, uint32_t dma_baseaddr, uint32_t dma_lenth); +/* software generate events */ +void timer_event_software_generate(uint32_t timer_periph, uint16_t event); + +/* TIMER channel complementary protection */ +/* initialize TIMER break parameter struct */ +void timer_break_struct_para_init(timer_break_parameter_struct* breakpara); +/* configure TIMER break function */ +void timer_break_config(uint32_t timer_periph, timer_break_parameter_struct* breakpara); +/* enable TIMER break function */ +void timer_break_enable(uint32_t timer_periph); +/* disable TIMER break function */ +void timer_break_disable(uint32_t timer_periph); +/* enable TIMER output automatic function */ +void timer_automatic_output_enable(uint32_t timer_periph); +/* disable TIMER output automatic function */ +void timer_automatic_output_disable(uint32_t timer_periph); +/* enable or disable TIMER primary output function */ +void timer_primary_output_config(uint32_t timer_periph, ControlStatus newvalue); +/* enable or disable channel capture/compare control shadow register */ +void timer_channel_control_shadow_config(uint32_t timer_periph, ControlStatus newvalue); +/* configure TIMER channel control shadow register update control */ +void timer_channel_control_shadow_update_config(uint32_t timer_periph, uint32_t ccuctl); + +/* TIMER channel output */ +/* initialize TIMER channel output parameter struct */ +void timer_channel_output_struct_para_init(timer_oc_parameter_struct* ocpara); +/* configure TIMER channel output function */ +void timer_channel_output_config(uint32_t timer_periph, uint16_t channel, timer_oc_parameter_struct* ocpara); +/* configure TIMER channel output compare mode */ +void timer_channel_output_mode_config(uint32_t timer_periph, uint16_t channel, uint16_t ocmode); +/* configure TIMER channel output pulse value */ +void timer_channel_output_pulse_value_config(uint32_t timer_periph, uint16_t channel, uint16_t pulse); +/* configure TIMER channel output shadow function */ +void timer_channel_output_shadow_config(uint32_t timer_periph, uint16_t channel, uint16_t ocshadow); +/* configure TIMER channel output fast function */ +void timer_channel_output_fast_config(uint32_t timer_periph, uint16_t channel, uint16_t ocfast); +/* configure TIMER channel output clear function */ +void timer_channel_output_clear_config(uint32_t timer_periph, uint16_t channel, uint16_t occlear); +/* configure TIMER channel output polarity */ +void timer_channel_output_polarity_config(uint32_t timer_periph, uint16_t channel, uint16_t ocpolarity); +/* configure TIMER channel complementary output polarity */ +void timer_channel_complementary_output_polarity_config(uint32_t timer_periph, uint16_t channel, uint16_t ocnpolarity); +/* configure TIMER channel enable state */ +void timer_channel_output_state_config(uint32_t timer_periph, uint16_t channel, uint32_t state); +/* configure TIMER channel complementary output enable state */ +void timer_channel_complementary_output_state_config(uint32_t timer_periph, uint16_t channel, uint16_t ocnstate); + +/* TIMER channel input */ +/* initialize TIMER channel input parameter structure */ +void timer_channel_input_struct_para_init(timer_ic_parameter_struct* icpara); +/* configure TIMER input capture parameter */ +void timer_input_capture_config(uint32_t timer_periph, uint16_t channel, timer_ic_parameter_struct* icpara); +/* configure TIMER channel input capture prescaler value */ +void timer_channel_input_capture_prescaler_config(uint32_t timer_periph, uint16_t channel, uint16_t prescaler); +/* read TIMER channel capture compare register value */ +uint32_t timer_channel_capture_value_register_read(uint32_t timer_periph, uint16_t channel); +/* configure TIMER input pwm capture function */ +void timer_input_pwm_capture_config(uint32_t timer_periph, uint16_t channel, timer_ic_parameter_struct* icpwm); +/* configure TIMER hall sensor mode */ +void timer_hall_mode_config(uint32_t timer_periph, uint32_t hallmode); + +/* TIMER master and slave */ +/* select TIMER input trigger source */ +void timer_input_trigger_source_select(uint32_t timer_periph, uint32_t intrigger); +/* select TIMER master mode output trigger source */ +void timer_master_output_trigger_source_select(uint32_t timer_periph, uint32_t outrigger); +/* select TIMER slave mode */ +void timer_slave_mode_select(uint32_t timer_periph, uint32_t slavemode); +/* configure TIMER master slave mode */ +void timer_master_slave_mode_config(uint32_t timer_periph, uint32_t masterslave); +/* configure TIMER external trigger input */ +void timer_external_trigger_config(uint32_t timer_periph, uint32_t extprescaler, uint32_t extpolarity, uint8_t extfilter); +/* configure TIMER quadrature decoder mode */ +void timer_quadrature_decoder_mode_config(uint32_t timer_periph, uint32_t decomode, uint16_t ic0polarity, uint16_t ic1polarity); +/* configure TIMER internal clock mode */ +void timer_internal_clock_config(uint32_t timer_periph); +/* configure TIMER the internal trigger as external clock input */ +void timer_internal_trigger_as_external_clock_config(uint32_t timer_periph, uint32_t intrigger); +/* configure TIMER the external trigger as external clock input */ +void timer_external_trigger_as_external_clock_config(uint32_t timer_periph, uint32_t extrigger, uint16_t extpolarity, uint8_t extfilter); +/* configure TIMER the external clock mode 0 */ +void timer_external_clock_mode0_config(uint32_t timer_periph, uint32_t extprescaler, uint32_t extpolarity, uint8_t extfilter); +/* configure TIMER the external clock mode 1 */ +void timer_external_clock_mode1_config(uint32_t timer_periph, uint32_t extprescaler, uint32_t extpolarity, uint8_t extfilter); +/* disable TIMER the external clock mode 1 */ +void timer_external_clock_mode1_disable(uint32_t timer_periph); + +/* TIMER interrupt and flag */ +/* enable the TIMER interrupt */ +void timer_interrupt_enable(uint32_t timer_periph, uint32_t interrupt); +/* disable the TIMER interrupt */ +void timer_interrupt_disable(uint32_t timer_periph, uint32_t interrupt); +/* get TIMER interrupt flag */ +FlagStatus timer_interrupt_flag_get(uint32_t timer_periph, uint32_t interrupt); +/* clear TIMER interrupt flag */ +void timer_interrupt_flag_clear(uint32_t timer_periph, uint32_t interrupt); +/* get TIMER flag */ +FlagStatus timer_flag_get(uint32_t timer_periph, uint32_t flag); +/* clear TIMER flag */ +void timer_flag_clear(uint32_t timer_periph, uint32_t flag); + +#endif /* GD32F20X_TIMER_H */ diff --git a/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_standard_peripheral/Include/gd32f20x_tli.h b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_standard_peripheral/Include/gd32f20x_tli.h new file mode 100644 index 0000000000..b6b9818a98 --- /dev/null +++ b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_standard_peripheral/Include/gd32f20x_tli.h @@ -0,0 +1,368 @@ +/*! + \file gd32f20x_tli.h + \brief definitions for the TLI + + \version 2015-07-15, V1.0.0, firmware for GD32F20x + \version 2017-06-05, V2.0.0, firmware for GD32F20x + \version 2018-10-31, V2.1.0, firmware for GD32F20x + \version 2020-09-30, V2.2.0, firmware for GD32F20x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef GD32F20X_TLI_H +#define GD32F20X_TLI_H + +#include "gd32f20x.h" + +/* TLI definitions */ +#define TLI TLI_BASE /*!< TLI base address */ +/* TLI layer definitions */ +#define LAYER0 TLI_BASE /*!< Layer0 base address */ +#define LAYER1 (TLI_BASE + 0x80) /*!< Layer1 base address */ + +/* registers definitions */ +#define TLI_SPSZ REG32(TLI + 0x08U) /*!< TLI synchronous pulse size register */ +#define TLI_BPSZ REG32(TLI + 0x0CU) /*!< TLI back-porch size register */ +#define TLI_ASZ REG32(TLI + 0x10U) /*!< TLI active size register */ +#define TLI_TSZ REG32(TLI + 0x14U) /*!< TLI total size register */ +#define TLI_CTL REG32(TLI + 0x18U) /*!< TLI control register */ +#define TLI_RL REG32(TLI + 0x24U) /*!< TLI reload layer register */ +#define TLI_BGC REG32(TLI + 0x2CU) /*!< TLI background color register */ +#define TLI_INTEN REG32(TLI + 0x34U) /*!< TLI interrupt enable register */ +#define TLI_INTF REG32(TLI + 0x38U) /*!< TLI interrupt flag register */ +#define TLI_INTC REG32(TLI + 0x3CU) /*!< TLI interrupt flag clear register */ +#define TLI_LM REG32(TLI + 0x40U) /*!< TLI line mark register */ +#define TLI_CPPOS REG32(TLI + 0x44U) /*!< TLI current pixel position register */ +#define TLI_STAT REG32(TLI + 0x48U) /*!< TLI status register */ +#define TLI_LxCTL(layerx) REG32((layerx) + 0x84U) /*!< TLI layer x control register */ +#define TLI_LxHPOS(layerx) REG32((layerx) + 0x88U) /*!< TLI layer x horizontal position parameters register */ +#define TLI_LxVPOS(layerx) REG32((layerx) + 0x8CU) /*!< TLI layer x vertical position parameters register */ +#define TLI_LxCKEY(layerx) REG32((layerx) + 0x90U) /*!< TLI layer x color key register */ +#define TLI_LxPPF(layerx) REG32((layerx) + 0x94U) /*!< TLI layer x packeted pixel format register */ +#define TLI_LxSA(layerx) REG32((layerx) + 0x98U) /*!< TLI layer x specified alpha register */ +#define TLI_LxDC(layerx) REG32((layerx) + 0x9CU) /*!< TLI layer x default color register */ +#define TLI_LxBLEND(layerx) REG32((layerx) + 0xA0U) /*!< TLI layer x blending register */ +#define TLI_LxFBADDR(layerx) REG32((layerx) + 0xACU) /*!< TLI layer x frame base address register */ +#define TLI_LxFLLEN(layerx) REG32((layerx) + 0xB0U) /*!< TLI layer x frame line length register */ +#define TLI_LxFTLN(layerx) REG32((layerx) + 0xB4U) /*!< TLI layer x frame total line number register */ +#define TLI_LxLUT(layerx) REG32((layerx) + 0xC4U) /*!< TLI layer x look up table register */ + +/* bits definitions */ +/* TLI_SPSZ */ +#define TLI_SPSZ_VPSZ BITS(0,11) /*!< size of the vertical synchronous pulse */ +#define TLI_SPSZ_HPSZ BITS(16,27) /*!< size of the horizontal synchronous pulse */ + +/* TLI_BPSZ */ +#define TLI_BPSZ_VBPSZ BITS(0,11) /*!< size of the vertical back porch plus synchronous pulse */ +#define TLI_BPSZ_HBPSZ BITS(16,27) /*!< size of the horizontal back porch plus synchronous pulse */ + +/* TLI_ASZ */ +#define TLI_ASZ_VASZ BITS(0,11) /*!< size of the vertical active area width plus back porch and synchronous pulse */ +#define TLI_ASZ_HASZ BITS(16,27) /*!< size of the horizontal active area width plus back porch and synchronous pulse */ + +/* TLI_TSZ */ +#define TLI_TSZ_VTSZ BITS(0,11) /*!< vertical total size of the display, including active area, back porch, synchronous pulse and front porch */ +#define TLI_TSZ_HTSZ BITS(16,27) /*!< horizontal total size of the display, including active area, back porch, synchronous pulse and front porch */ + +/* TLI_CTL */ +#define TLI_CTL_TLIEN BIT(0) /*!< TLI enable bit */ +#define TLI_CTL_BDB BITS(4,6) /*!< blue channel dither bits number */ +#define TLI_CTL_GDB BITS(8,10) /*!< green channel dither bits number */ +#define TLI_CTL_RDB BITS(12,14) /*!< red channel dither bits number */ +#define TLI_CTL_DFEN BIT(16) /*!< dither function enable */ +#define TLI_CTL_CLKPS BIT(28) /*!< pixel clock polarity selection */ +#define TLI_CTL_DEPS BIT(29) /*!< data enable polarity selection */ +#define TLI_CTL_VPPS BIT(30) /*!< vertical pulse polarity selection */ +#define TLI_CTL_HPPS BIT(31) /*!< horizontal pulse polarity selection */ + +/* TLI_RL */ +#define TLI_RL_RQR BIT(0) /*!< request reload */ +#define TLI_RL_FBR BIT(1) /*!< frame blank reload */ + +/* TLI_BGC */ +#define TLI_BGC_BVB BITS(0,7) /*!< background value blue */ +#define TLI_BGC_BVG BITS(8,15) /*!< background value green */ +#define TLI_BGC_BVR BITS(16,23) /*!< background value red */ + +/* TLI_INTEN */ +#define TLI_INTEN_LMIE BIT(0) /*!< line mark interrupt enable */ +#define TLI_INTEN_FEIE BIT(1) /*!< FIFO error interrupt enable */ +#define TLI_INTEN_TEIE BIT(2) /*!< transaction error interrupt enable */ +#define TLI_INTEN_LCRIE BIT(3) /*!< layer configuration reloaded interrupt enable */ + +/* TLI_INTF */ +#define TLI_INTF_LMF BIT(0) /*!< line mark flag */ +#define TLI_INTF_FEF BIT(1) /*!< FIFO error flag */ +#define TLI_INTF_TEF BIT(2) /*!< transaction error flag */ +#define TLI_INTF_LCRF BIT(3) /*!< layer configuration reloaded flag */ + +/* TLI_INTC */ +#define TLI_INTC_LMC BIT(0) /*!< line mark flag clear */ +#define TLI_INTC_FEC BIT(1) /*!< FIFO error flag clear */ +#define TLI_INTC_TEC BIT(2) /*!< transaction error flag clear */ +#define TLI_INTC_LCRC BIT(3) /*!< layer configuration reloaded flag clear */ + +/* TLI_LM */ +#define TLI_LM_LM BITS(0,10) /*!< line mark value */ + +/* TLI_CPPOS */ +#define TLI_CPPOS_VPOS BITS(0,15) /*!< vertical position */ +#define TLI_CPPOS_HPOS BITS(16,31) /*!< horizontal position */ + +/* TLI_STAT */ +#define TLI_STAT_VDE BIT(0) /*!< current VDE status */ +#define TLI_STAT_HDE BIT(1) /*!< current HDE status */ +#define TLI_STAT_VS BIT(2) /*!< current VS status of the TLI */ +#define TLI_STAT_HS BIT(3) /*!< current HS status of the TLI */ + +/* TLI_LxCTL */ +#define TLI_LxCTL_LEN BIT(0) /*!< layer enable */ +#define TLI_LxCTL_CKEYEN BIT(1) /*!< color keying enable */ +#define TLI_LxCTL_LUTEN BIT(4) /*!< LUT enable */ + +/* TLI_LxHPOS */ +#define TLI_LxHPOS_WLP BITS(0,11) /*!< window left position */ +#define TLI_LxHPOS_WRP BITS(16,27) /*!< window right position */ + +/* TLI_LxVPOS */ +#define TLI_LxVPOS_WTP BITS(0,11) /*!< window top position */ +#define TLI_LxVPOS_WBP BITS(16,27) /*!< window bottom position */ + +/* TLI_LxCKEY */ +#define TLI_LxCKEY_CKEYB BITS(0,7) /*!< color key blue */ +#define TLI_LxCKEY_CKEYG BITS(8,15) /*!< color key green */ +#define TLI_LxCKEY_CKEYR BITS(16,23) /*!< color key red */ + +/* TLI_LxPPF */ +#define TLI_LxPPF_PPF BITS(0,2) /*!< packeted pixel format */ + +/* TLI_LxSA */ +#define TLI_LxSA_SA BITS(0,7) /*!< specified alpha */ + +/* TLI_LxDC */ +#define TLI_LxDC_DCB BITS(0,7) /*!< the default color blue */ +#define TLI_LxDC_DCG BITS(8,15) /*!< the default color green */ +#define TLI_LxDC_DCR BITS(16,23) /*!< the default color red */ +#define TLI_LxDC_DCA BITS(24,31) /*!< the default color alpha */ + +/* TLI_LxBLEND */ +#define TLI_LxBLEND_ACF2 BITS(0,2) /*!< alpha calculation factor 2 of blending method */ +#define TLI_LxBLEND_ACF1 BITS(8,10) /*!< alpha calculation factor 1 of blending method */ + +/* TLI_LxFBADDR */ +#define TLI_LxFBADDR_FBADD BITS(0,31) /*!< frame buffer base address */ + +/* TLI_LxFLLEN */ +#define TLI_LxFLLEN_FLL BITS(0,13) /*!< frame line length */ +#define TLI_LxFLLEN_STDOFF BITS(16,29) /*!< frame buffer stride offset */ + +/* TLI_LxFTLN */ +#define TLI_LxFTLN_FTLN BITS(0,10) /*!< frame total line number */ + +/* TLI_LxLUT */ +#define TLI_LxLUT_TB BITS(0,7) /*!< blue channel of a LUT entry */ +#define TLI_LxLUT_TG BITS(8,15) /*!< green channel of a LUT entry */ +#define TLI_LxLUT_TR BITS(16,23) /*!< red channel of a LUT entry */ +#define TLI_LxLUT_TADD BITS(24,31) /*!< look up table write address */ + +/* constants definitions */ +/* TLI parameter structure definitions */ +typedef struct +{ + uint32_t synpsz_vpsz; /*!< size of the vertical synchronous pulse */ + uint32_t synpsz_hpsz; /*!< size of the horizontal synchronous pulse */ + uint32_t backpsz_vbpsz; /*!< size of the vertical back porch plus synchronous pulse */ + uint32_t backpsz_hbpsz; /*!< size of the horizontal back porch plus synchronous pulse */ + uint32_t activesz_vasz; /*!< size of the vertical active area width plus back porch and synchronous pulse */ + uint32_t activesz_hasz; /*!< size of the horizontal active area width plus back porch and synchronous pulse */ + uint32_t totalsz_vtsz; /*!< vertical total size of the display */ + uint32_t totalsz_htsz; /*!< horizontal total size of the display */ + uint32_t backcolor_red; /*!< background value red */ + uint32_t backcolor_green; /*!< background value green */ + uint32_t backcolor_blue; /*!< background value blue */ + uint32_t signalpolarity_hs; /*!< horizontal pulse polarity selection */ + uint32_t signalpolarity_vs; /*!< vertical pulse polarity selection */ + uint32_t signalpolarity_de; /*!< data enable polarity selection */ + uint32_t signalpolarity_pixelck; /*!< pixel clock polarity selection */ +}tli_parameter_struct; + +/* TLI layer parameter structure definitions */ +typedef struct +{ + uint32_t layer_window_rightpos; /*!< window right position */ + uint32_t layer_window_leftpos; /*!< window left position */ + uint32_t layer_window_bottompos; /*!< window bottom position */ + uint32_t layer_window_toppos; /*!< window top position */ + uint32_t layer_ppf; /*!< packeted pixel format */ + uint32_t layer_sa; /*!< specified alpha */ + uint32_t layer_default_alpha; /*!< the default color alpha */ + uint32_t layer_default_red; /*!< the default color red */ + uint32_t layer_default_green; /*!< the default color green */ + uint32_t layer_default_blue; /*!< the default color blue */ + uint32_t layer_acf1; /*!< alpha calculation factor 1 of blending method */ + uint32_t layer_acf2; /*!< alpha calculation factor 2 of blending method */ + uint32_t layer_frame_bufaddr; /*!< frame buffer base address */ + uint32_t layer_frame_buf_stride_offset; /*!< frame buffer stride offset */ + uint32_t layer_frame_line_length; /*!< frame line length */ + uint32_t layer_frame_total_line_number; /*!< frame total line number */ +}tli_layer_parameter_struct; + +/* TLI layer LUT parameter structure definitions */ +typedef struct +{ + uint32_t layer_table_addr; /*!< look up table write address */ + uint32_t layer_lut_channel_red; /*!< red channel of a LUT entry */ + uint32_t layer_lut_channel_green; /*!< green channel of a LUT entry */ + uint32_t layer_lut_channel_blue; /*!< blue channel of a LUT entry */ +}tli_layer_lut_parameter_struct; + +/* packeted pixel format */ +typedef enum +{ + LAYER_PPF_ARGB8888, /*!< layerx packeted pixel format ARGB8888 */ + LAYER_PPF_RGB888, /*!< layerx packeted pixel format RGB888 */ + LAYER_PPF_RGB565, /*!< layerx packeted pixel format RGB565 */ + LAYER_PPF_ARGB1555, /*!< layerx packeted pixel format ARGB1555 */ + LAYER_PPF_ARGB4444, /*!< layerx packeted pixel format ARGB4444 */ + LAYER_PPF_L8, /*!< layerx packeted pixel format L8 */ + LAYER_PPF_AL44, /*!< layerx packeted pixel format AL44 */ + LAYER_PPF_AL88 /*!< layerx packeted pixel format AL88 */ +} tli_layer_ppf_enum; + +/* TLI flags and states */ +#define TLI_FLAG_VDE TLI_STAT_VDE /*!< current VDE status */ +#define TLI_FLAG_HDE TLI_STAT_HDE /*!< current HDE status */ +#define TLI_FLAG_VS TLI_STAT_VS /*!< current VS status of the TLI */ +#define TLI_FLAG_HS TLI_STAT_HS /*!< current HS status of the TLI */ +#define TLI_FLAG_LM (BIT(0) | BIT(31)) /*!< line mark interrupt flag */ +#define TLI_FLAG_FE (BIT(1) | BIT(31)) /*!< FIFO error interrupt flag */ +#define TLI_FLAG_TE (BIT(2) | BIT(31)) /*!< transaction error interrupt flag */ +#define TLI_FLAG_LCR (BIT(3) | BIT(31)) /*!< layer configuration reloaded interrupt flag */ + +/* TLI interrupt enable or disable */ +#define TLI_INT_LM BIT(0) /*!< line mark interrupt */ +#define TLI_INT_FE BIT(1) /*!< FIFO error interrupt */ +#define TLI_INT_TE BIT(2) /*!< transaction error interrupt */ +#define TLI_INT_LCR BIT(3) /*!< layer configuration reloaded interrupt */ + +/* TLI interrupt flag */ +#define TLI_INT_FLAG_LM BIT(0) /*!< line mark interrupt flag */ +#define TLI_INT_FLAG_FE BIT(1) /*!< FIFO error interrupt flag */ +#define TLI_INT_FLAG_TE BIT(2) /*!< transaction error interrupt flag */ +#define TLI_INT_FLAG_LCR BIT(3) /*!< layer configuration reloaded interrupt flag */ + +/* layer reload configure */ +#define TLI_FRAME_BLANK_RELOAD_EN ((uint8_t)0x00U) /*!< the layer configuration will be reloaded at frame blank */ +#define TLI_REQUEST_RELOAD_EN ((uint8_t)0x01U) /*!< the layer configuration will be reloaded after this bit sets */ + +/* dither function */ +#define TLI_DITHER_DISABLE ((uint8_t)0x00U) /*!< dither function disable */ +#define TLI_DITHER_ENABLE ((uint8_t)0x01U) /*!< dither function enable */ + +/* horizontal pulse polarity selection */ +#define TLI_HSYN_ACTLIVE_LOW ((uint32_t)0x00000000U) /*!< horizontal synchronous pulse active low */ +#define TLI_HSYN_ACTLIVE_HIGHT TLI_CTL_HPPS /*!< horizontal synchronous pulse active high */ + +/* vertical pulse polarity selection */ +#define TLI_VSYN_ACTLIVE_LOW ((uint32_t)0x00000000U) /*!< vertical synchronous pulse active low */ +#define TLI_VSYN_ACTLIVE_HIGHT TLI_CTL_VPPS /*!< vertical synchronous pulse active high */ + +/* pixel clock polarity selection */ +#define TLI_PIXEL_CLOCK_TLI ((uint32_t)0x00000000U) /*!< pixel clock is TLI clock */ +#define TLI_PIXEL_CLOCK_INVERTEDTLI TLI_CTL_CLKPS /*!< pixel clock is inverted TLI clock */ + +/* data enable polarity selection */ +#define TLI_DE_ACTLIVE_LOW ((uint32_t)0x00000000U) /*!< data enable active low */ +#define TLI_DE_ACTLIVE_HIGHT TLI_CTL_DEPS /*!< data enable active high */ + +/* alpha calculation factor 1 of blending method */ +#define LxBLEND_ACF1(regval) (BITS(8,10) & ((regval)<<8)) +#define LAYER_ACF1_SA LxBLEND_ACF1(4) /*!< normalization specified alpha */ +#define LAYER_ACF1_PASA LxBLEND_ACF1(6) /*!< normalization pixel alpha * normalization specified alpha */ + +/* alpha calculation factor 2 of blending method */ +#define LxBLEND_ACF2(regval) (BITS(0,2) & ((regval))) +#define LAYER_ACF2_SA LxBLEND_ACF2(5) /*!< normalization specified alpha */ +#define LAYER_ACF2_PASA LxBLEND_ACF2(7) /*!< normalization pixel alpha * normalization specified alpha */ + +/* function declarations */ +/* initialization functions */ +/* deinitialize TLI */ +void tli_deinit(void); +/* initialize TLI */ +void tli_init(tli_parameter_struct *tli_struct); +/* configure TLI dither function */ +void tli_dither_config(uint8_t ditherstat); +/* enable TLI */ +void tli_enable(void); +/* disable TLI */ +void tli_disable(void); +/* configure TLI reload mode */ +void tli_reload_config(uint8_t reloadmode); + +/* set line mark value */ +void tli_line_mark_set(uint32_t linenum); +/* get current displayed position */ +uint32_t tli_current_pos_get(void); + +/* function configuration */ +/* TLI layer enable */ +void tli_layer_enable(uint32_t layerx); +/* TLI layer disable */ +void tli_layer_disable(uint32_t layerx); +/* TLI layer color keying enable */ +void tli_color_key_enable(uint32_t layerx); +/* TLI layer color keying disable */ +void tli_color_key_disable(uint32_t layerx); +/* TLI layer LUT enable */ +void tli_lut_enable(uint32_t layerx); +/* TLI layer LUT disable */ +void tli_lut_disable(uint32_t layerx); +/* TLI layer initialize */ +void tli_layer_init(uint32_t layerx,tli_layer_parameter_struct *layer_struct); +/* TLI layer initialize */ +void tli_layer_window_offset_modify(uint32_t layerx,uint32_t offset_x,uint32_t offset_y); +/* TLI layer LUT initialize */ +void tli_lut_init(uint32_t layerx,tli_layer_lut_parameter_struct *lut_struct); +/* TLI layer key initialize */ +void tli_ckey_init(uint32_t layerx,uint32_t redkey,uint32_t greenkey,uint32_t bluekey); + +/* interrupt & flag functions */ +/* get TLI flag or state */ +FlagStatus tli_flag_get(uint32_t flag); +/* enable TLI interrupt */ +void tli_interrupt_enable(uint32_t interrupt); +/* disable TLI interrupt */ +void tli_interrupt_disable(uint32_t interrupt); +/* get TLI interrupt flag */ +FlagStatus tli_interrupt_flag_get(uint32_t int_flag); +/* clear TLI interrupt flag */ +void tli_interrupt_flag_clear(uint32_t int_flag); + +#endif /* GD32F20X_TLI_H */ diff --git a/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_standard_peripheral/Include/gd32f20x_trng.h b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_standard_peripheral/Include/gd32f20x_trng.h new file mode 100644 index 0000000000..164b372869 --- /dev/null +++ b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_standard_peripheral/Include/gd32f20x_trng.h @@ -0,0 +1,105 @@ +/*! + \file gd32f20x_trng.h + \brief definitions for the TRNG + + \version 2015-07-15, V1.0.0, firmware for GD32F20x + \version 2017-06-05, V2.0.0, firmware for GD32F20x + \version 2018-10-31, V2.1.0, firmware for GD32F20x + \version 2020-09-30, V2.2.0, firmware for GD32F20x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef GD32F20X_TRNG_H +#define GD32F20X_TRNG_H + +#include "gd32f20x.h" + +/* TRNG definitions */ +#define TRNG TRNG_BASE + +/* registers definitions */ +#define TRNG_CTL REG32(TRNG + 0x00U) /*!< control register */ +#define TRNG_STAT REG32(TRNG + 0x04U) /*!< status register */ +#define TRNG_DATA REG32(TRNG + 0x08U) /*!< data register */ + +/* bits definitions */ +/* TRNG_CTL */ +#define TRNG_CTL_TRNGEN BIT(2) /*!< TRNG enable bit */ +#define TRNG_CTL_IE BIT(3) /*!< interrupt enable bit */ + +/* TRNG_STAT */ +#define TRNG_STAT_DRDY BIT(0) /*!< random data ready status bit */ +#define TRNG_STAT_CECS BIT(1) /*!< clock error current status */ +#define TRNG_STAT_SECS BIT(2) /*!< seed error current status */ +#define TRNG_STAT_CEIF BIT(5) /*!< clock error interrupt flag */ +#define TRNG_STAT_SEIF BIT(6) /*!< seed error interrupt flag */ + +/* TRNG_DATA */ +#define TRNG_DATA_TRNDATA BITS(0,31) /*!< 32-Bit Random data */ + +/* constants definitions */ +/* trng status flag */ +typedef enum +{ + TRNG_FLAG_DRDY = TRNG_STAT_DRDY, /*!< random Data ready status */ + TRNG_FLAG_CECS = TRNG_STAT_CECS, /*!< clock error current status */ + TRNG_FLAG_SECS = TRNG_STAT_SECS /*!< seed error current status */ +}trng_flag_enum; + +/* trng inerrupt flag */ +typedef enum +{ + TRNG_INT_FLAG_CE = TRNG_STAT_CEIF, /*!< clock error interrupt flag */ + TRNG_INT_FLAG_SE = TRNG_STAT_SEIF /*!< seed error interrupt flag */ +}trng_int_flag_enum; + +/* function declarations */ +/* initialization functions */ +/* deinitialize the TRNG */ +void trng_deinit(void); +/* enable the TRNG interface */ +void trng_enable(void); +/* disable the TRNG interface */ +void trng_disable(void); +/* get the true random data */ +uint32_t trng_get_true_random_data(void); + +/* interrupt & flag functions */ +/* get the trng status flags */ +FlagStatus trng_flag_get(trng_flag_enum flag); +/* the trng interrupt enable */ +void trng_interrupt_enable(void); +/* the trng interrupt disable */ +void trng_interrupt_disable(void); +/* get the trng interrupt flags */ +FlagStatus trng_interrupt_flag_get(trng_int_flag_enum int_flag); +/* clear the trng interrupt flags */ +void trng_interrupt_flag_clear(trng_int_flag_enum int_flag); + +#endif /* GD32F20X_TRNG_H */ diff --git a/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_standard_peripheral/Include/gd32f20x_usart.h b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_standard_peripheral/Include/gd32f20x_usart.h new file mode 100644 index 0000000000..a4c9b78846 --- /dev/null +++ b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_standard_peripheral/Include/gd32f20x_usart.h @@ -0,0 +1,449 @@ +/*! + \file gd32f20x_usart.h + \brief definitions for the USART + + \version 2015-07-15, V1.0.0, firmware for GD32F20x + \version 2017-06-05, V2.0.0, firmware for GD32F20x + \version 2018-10-31, V2.1.0, firmware for GD32F20x + \version 2020-09-30, V2.2.0, firmware for GD32F20x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef GD32F20X_USART_H +#define GD32F20X_USART_H + +#include "gd32f20x.h" + +/* USARTx(x=0,1,2,5)/UARTx(x=3,4,6,7) definitions */ +#define USART1 USART_BASE /*!< USART1 base address */ +#define USART2 (USART_BASE+0x00000400U) /*!< USART2 base address */ +#define UART3 (USART_BASE+0x00000800U) /*!< UART3 base address */ +#define UART4 (USART_BASE+0x00000C00U) /*!< UART4 base address */ +#define UART6 (USART_BASE+0x00003400U) /*!< UART6 base address */ +#define UART7 (USART_BASE+0x00003800U) /*!< UART7 base address */ +#define USART0 (USART_BASE+0x0000F400U) /*!< USART0 base address */ +#define USART5 (USART_BASE+0x00012C00U) /*!< USART5 base address */ + +/* registers definitions */ +#define USART_STAT0(usartx) REG32((usartx) + 0x00U) /*!< USART status register 0 */ +#define USART_DATA(usartx) REG32((usartx) + 0x04U) /*!< USART data register */ +#define USART_BAUD(usartx) REG32((usartx) + 0x08U) /*!< USART baud rate register */ +#define USART_CTL0(usartx) REG32((usartx) + 0x0CU) /*!< USART control register 0 */ +#define USART_CTL1(usartx) REG32((usartx) + 0x10U) /*!< USART control register 1 */ +#define USART_CTL2(usartx) REG32((usartx) + 0x14U) /*!< USART control register 2 */ +#define USART_GP(usartx) REG32((usartx) + 0x18U) /*!< USART guard time and prescaler register */ +#define USART_CTL3(usartx) REG32((usartx) + 0x80U) /*!< USART control register 3 */ +#define USART_RT(usartx) REG32((usartx) + 0x84U) /*!< USART receiver timeout register */ +#define USART_STAT1(usartx) REG32((usartx) + 0x88U) /*!< USART status register 1 */ + +/* bits definitions */ +/* USARTx_STAT0 */ +#define USART_STAT0_PERR BIT(0) /*!< parity error flag */ +#define USART_STAT0_FERR BIT(1) /*!< frame error flag */ +#define USART_STAT0_NERR BIT(2) /*!< noise error flag */ +#define USART_STAT0_ORERR BIT(3) /*!< overrun error */ +#define USART_STAT0_IDLEF BIT(4) /*!< IDLE frame detected flag */ +#define USART_STAT0_RBNE BIT(5) /*!< read data buffer not empty */ +#define USART_STAT0_TC BIT(6) /*!< transmission complete */ +#define USART_STAT0_TBE BIT(7) /*!< transmit data buffer empty */ +#define USART_STAT0_LBDF BIT(8) /*!< LIN break detected flag */ +#define USART_STAT0_CTSF BIT(9) /*!< CTS change flag */ + +/* USARTx_DATA */ +#define USART_DATA_DATA BITS(0,8) /*!< transmit or read data value */ + +/* USARTx_BAUD */ +#define USART_BAUD_FRADIV BITS(0,3) /*!< fraction part of baud-rate divider */ +#define USART_BAUD_INTDIV BITS(4,15) /*!< integer part of baud-rate divider */ + +/* USARTx_CTL0 */ +#define USART_CTL0_SBKCMD BIT(0) /*!< send break command */ +#define USART_CTL0_RWU BIT(1) /*!< receiver wakeup from mute mode */ +#define USART_CTL0_REN BIT(2) /*!< receiver enable */ +#define USART_CTL0_TEN BIT(3) /*!< transmitter enable */ +#define USART_CTL0_IDLEIE BIT(4) /*!< idle line detected interrupt enable */ +#define USART_CTL0_RBNEIE BIT(5) /*!< read data buffer not empty interrupt and overrun error interrupt enable */ +#define USART_CTL0_TCIE BIT(6) /*!< transmission complete interrupt enable */ +#define USART_CTL0_TBEIE BIT(7) /*!< transmitter buffer empty interrupt enable */ +#define USART_CTL0_PERRIE BIT(8) /*!< parity error interrupt enable */ +#define USART_CTL0_PM BIT(9) /*!< parity mode */ +#define USART_CTL0_PCEN BIT(10) /*!< parity check function enable */ +#define USART_CTL0_WM BIT(11) /*!< wakeup method in mute mode */ +#define USART_CTL0_WL BIT(12) /*!< word length */ +#define USART_CTL0_UEN BIT(13) /*!< USART enable */ + +/* USARTx_CTL1 */ +#define USART_CTL1_ADDR BITS(0,3) /*!< address of USART */ +#define USART_CTL1_LBLEN BIT(5) /*!< LIN break frame length */ +#define USART_CTL1_LBDIE BIT(6) /*!< LIN break detected interrupt eanble */ +#define USART_CTL1_CLEN BIT(8) /*!< CK length */ +#define USART_CTL1_CPH BIT(9) /*!< CK phase */ +#define USART_CTL1_CPL BIT(10) /*!< CK polarity */ +#define USART_CTL1_CKEN BIT(11) /*!< CK pin enable */ +#define USART_CTL1_STB BITS(12,13) /*!< STOP bits length */ +#define USART_CTL1_LMEN BIT(14) /*!< LIN mode enable */ + +/* USARTx_CTL2 */ +#define USART_CTL2_ERRIE BIT(0) /*!< error interrupt enable */ +#define USART_CTL2_IREN BIT(1) /*!< IrDA mode enable */ +#define USART_CTL2_IRLP BIT(2) /*!< IrDA low-power */ +#define USART_CTL2_HDEN BIT(3) /*!< half-duplex enable */ +#define USART_CTL2_NKEN BIT(4) /*!< NACK enable in smartcard mode */ +#define USART_CTL2_SCEN BIT(5) /*!< smartcard mode enable */ +#define USART_CTL2_DENR BIT(6) /*!< DMA request enable for reception */ +#define USART_CTL2_DENT BIT(7) /*!< DMA request enable for transmission */ +#define USART_CTL2_RTSEN BIT(8) /*!< RTS enable */ +#define USART_CTL2_CTSEN BIT(9) /*!< CTS enable */ +#define USART_CTL2_CTSIE BIT(10) /*!< CTS interrupt enable */ + +/* USARTx_GP */ +#define USART_GP_PSC BITS(0,7) /*!< prescaler value for dividing the system clock */ +#define USART_GP_GUAT BITS(8,15) /*!< guard time value in smartcard mode */ + +/* USARTx_CTL3 */ +#define USART_CTL3_RTEN BIT(0) /*!< receiver timeout enable */ +#define USART_CTL3_SCRTNUM BITS(1,3) /*!< smartcard auto-retry number */ +#define USART_CTL3_RTIE BIT(4) /*!< interrupt enable bit of receive timeout event */ +#define USART_CTL3_EBIE BIT(5) /*!< interrupt enable bit of end of block event */ +#define USART_CTL3_RINV BIT(8) /*!< RX pin level inversion */ +#define USART_CTL3_TINV BIT(9) /*!< TX pin level inversion */ +#define USART_CTL3_DINV BIT(10) /*!< data bit level inversion */ +#define USART_CTL3_MSBF BIT(11) /*!< most significant bit first */ + +/* USARTx_RT */ +#define USART_RT_RT BITS(0,23) /*!< receiver timeout threshold */ +#define USART_RT_BL BITS(24,31) /*!< block length */ + +/* USARTx_STAT1 */ +#define USART_STAT1_RTF BIT(11) /*!< receiver timeout flag */ +#define USART_STAT1_EBF BIT(12) /*!< end of block flag */ +#define USART_STAT1_BSY BIT(16) /*!< busy flag */ + +/* constants definitions */ +/* define the USART bit position and its register index offset */ +#define USART_REGIDX_BIT(regidx, bitpos) (((uint32_t)(regidx) << 6) | (uint32_t)(bitpos)) +#define USART_REG_VAL(usartx, offset) (REG32((usartx) + (((uint32_t)(offset) & 0xFFFFU) >> 6))) +#define USART_BIT_POS(val) ((uint32_t)(val) & 0x1FU) +#define USART_REGIDX_BIT2(regidx, bitpos, regidx2, bitpos2) (((uint32_t)(regidx2) << 22) | (uint32_t)((bitpos2) << 16)\ + | (((uint32_t)(regidx) << 6) | (uint32_t)(bitpos))) +#define USART_REG_VAL2(usartx, offset) (REG32((usartx) + ((uint32_t)(offset) >> 22))) +#define USART_BIT_POS2(val) (((uint32_t)(val) & 0x1F0000U) >> 16) + +/* register offset */ +#define USART_STAT0_REG_OFFSET 0x00U /*!< STAT0 register offset */ +#define USART_STAT1_REG_OFFSET 0x88U /*!< STAT1 register offset */ +#define USART_CTL0_REG_OFFSET 0x0CU /*!< CTL0 register offset */ +#define USART_CTL1_REG_OFFSET 0x10U /*!< CTL1 register offset */ +#define USART_CTL2_REG_OFFSET 0x14U /*!< CTL2 register offset */ +#define USART_CTL3_REG_OFFSET 0x80U /*!< CTL3 register offset */ + +/* USART flags */ +typedef enum +{ + /* flags in STAT0 register */ + USART_FLAG_CTS = USART_REGIDX_BIT(USART_STAT0_REG_OFFSET, 9U), /*!< CTS change flag */ + USART_FLAG_LBD = USART_REGIDX_BIT(USART_STAT0_REG_OFFSET, 8U), /*!< LIN break detected flag */ + USART_FLAG_TBE = USART_REGIDX_BIT(USART_STAT0_REG_OFFSET, 7U), /*!< transmit data buffer empty */ + USART_FLAG_TC = USART_REGIDX_BIT(USART_STAT0_REG_OFFSET, 6U), /*!< transmission complete */ + USART_FLAG_RBNE = USART_REGIDX_BIT(USART_STAT0_REG_OFFSET, 5U), /*!< read data buffer not empty */ + USART_FLAG_IDLE = USART_REGIDX_BIT(USART_STAT0_REG_OFFSET, 4U), /*!< IDLE frame detected flag */ + USART_FLAG_ORERR = USART_REGIDX_BIT(USART_STAT0_REG_OFFSET, 3U), /*!< overrun error */ + USART_FLAG_NERR = USART_REGIDX_BIT(USART_STAT0_REG_OFFSET, 2U), /*!< noise error flag */ + USART_FLAG_FERR = USART_REGIDX_BIT(USART_STAT0_REG_OFFSET, 1U), /*!< frame error flag */ + USART_FLAG_PERR = USART_REGIDX_BIT(USART_STAT0_REG_OFFSET, 0U), /*!< parity error flag */ + /* flags in STAT1 register */ + USART_FLAG_BSY = USART_REGIDX_BIT(USART_STAT1_REG_OFFSET, 16U), /*!< busy flag */ + USART_FLAG_EB = USART_REGIDX_BIT(USART_STAT1_REG_OFFSET, 12U), /*!< end of block flag */ + USART_FLAG_RT = USART_REGIDX_BIT(USART_STAT1_REG_OFFSET, 11U), /*!< receiver timeout flag */ +}usart_flag_enum; + +/* USART interrupt flags */ +typedef enum +{ + /* interrupt flags in CTL0 register */ + USART_INT_FLAG_PERR = USART_REGIDX_BIT2(USART_CTL0_REG_OFFSET, 8U, USART_STAT0_REG_OFFSET, 0U), /*!< parity error interrupt and flag */ + USART_INT_FLAG_TBE = USART_REGIDX_BIT2(USART_CTL0_REG_OFFSET, 7U, USART_STAT0_REG_OFFSET, 7U), /*!< transmitter buffer empty interrupt and flag */ + USART_INT_FLAG_TC = USART_REGIDX_BIT2(USART_CTL0_REG_OFFSET, 6U, USART_STAT0_REG_OFFSET, 6U), /*!< transmission complete interrupt and flag */ + USART_INT_FLAG_RBNE = USART_REGIDX_BIT2(USART_CTL0_REG_OFFSET, 5U, USART_STAT0_REG_OFFSET, 5U), /*!< read data buffer not empty interrupt and flag */ + USART_INT_FLAG_RBNE_ORERR = USART_REGIDX_BIT2(USART_CTL0_REG_OFFSET, 5U, USART_STAT0_REG_OFFSET, 3U), /*!< read data buffer not empty interrupt and overrun error flag */ + USART_INT_FLAG_IDLE = USART_REGIDX_BIT2(USART_CTL0_REG_OFFSET, 4U, USART_STAT0_REG_OFFSET, 4U), /*!< IDLE line detected interrupt and flag */ + /* interrupt flags in CTL1 register */ + USART_INT_FLAG_LBD = USART_REGIDX_BIT2(USART_CTL1_REG_OFFSET, 6U, USART_STAT0_REG_OFFSET, 8U), /*!< LIN break detected interrupt and flag */ + /* interrupt flags in CTL2 register */ + USART_INT_FLAG_CTS = USART_REGIDX_BIT2(USART_CTL2_REG_OFFSET, 10U, USART_STAT0_REG_OFFSET, 9U), /*!< CTS interrupt and flag */ + USART_INT_FLAG_ERR_ORERR = USART_REGIDX_BIT2(USART_CTL2_REG_OFFSET, 0U, USART_STAT0_REG_OFFSET, 3U), /*!< error interrupt and overrun error */ + USART_INT_FLAG_ERR_NERR = USART_REGIDX_BIT2(USART_CTL2_REG_OFFSET, 0U, USART_STAT0_REG_OFFSET, 2U), /*!< error interrupt and noise error flag */ + USART_INT_FLAG_ERR_FERR = USART_REGIDX_BIT2(USART_CTL2_REG_OFFSET, 0U, USART_STAT0_REG_OFFSET, 1U), /*!< error interrupt and frame error flag */ + /* interrupt flags in CTL3 register */ + USART_INT_FLAG_EB = USART_REGIDX_BIT2(USART_CTL3_REG_OFFSET, 5U, USART_STAT1_REG_OFFSET, 12U), /*!< interrupt enable bit of end of block event and flag */ + USART_INT_FLAG_RT = USART_REGIDX_BIT2(USART_CTL3_REG_OFFSET, 4U, USART_STAT1_REG_OFFSET, 11U), /*!< interrupt enable bit of receive timeout event and flag */ +}usart_interrupt_flag_enum; + +/* USART interrupt enable or disable */ +typedef enum +{ + /* interrupt in CTL0 register */ + USART_INT_PERR = USART_REGIDX_BIT(USART_CTL0_REG_OFFSET, 8U), /*!< parity error interrupt */ + USART_INT_TBE = USART_REGIDX_BIT(USART_CTL0_REG_OFFSET, 7U), /*!< transmitter buffer empty interrupt */ + USART_INT_TC = USART_REGIDX_BIT(USART_CTL0_REG_OFFSET, 6U), /*!< transmission complete interrupt */ + USART_INT_RBNE = USART_REGIDX_BIT(USART_CTL0_REG_OFFSET, 5U), /*!< read data buffer not empty interrupt and overrun error interrupt */ + USART_INT_IDLE = USART_REGIDX_BIT(USART_CTL0_REG_OFFSET, 4U), /*!< IDLE line detected interrupt */ + /* interrupt in CTL1 register */ + USART_INT_LBD = USART_REGIDX_BIT(USART_CTL1_REG_OFFSET, 6U), /*!< LIN break detected interrupt */ + /* interrupt in CTL2 register */ + USART_INT_CTS = USART_REGIDX_BIT(USART_CTL2_REG_OFFSET, 10U), /*!< CTS interrupt */ + USART_INT_ERR = USART_REGIDX_BIT(USART_CTL2_REG_OFFSET, 0U), /*!< error interrupt */ + /* interrupt in CTL3 register */ + USART_INT_EB = USART_REGIDX_BIT(USART_CTL3_REG_OFFSET, 5U), /*!< end of block interrupt */ + USART_INT_RT = USART_REGIDX_BIT(USART_CTL3_REG_OFFSET, 4U), /*!< receive timeout interrupt */ +}usart_interrupt_enum; + +/* USART invert configure */ +typedef enum +{ + /* data bit level inversion */ + USART_DINV_ENABLE, /*!< data bit level inversion */ + USART_DINV_DISABLE, /*!< data bit level not inversion */ + /* TX pin level inversion */ + USART_TXPIN_ENABLE, /*!< TX pin level inversion */ + USART_TXPIN_DISABLE, /*!< TX pin level not inversion */ + /* RX pin level inversion */ + USART_RXPIN_ENABLE, /*!< RX pin level inversion */ + USART_RXPIN_DISABLE, /*!< RX pin level not inversion */ +}usart_invert_enum; + +/* USART receiver configure */ +#define CTL0_REN(regval) (BIT(2) & ((uint32_t)(regval) << 2)) +#define USART_RECEIVE_ENABLE CTL0_REN(1) /*!< enable receiver */ +#define USART_RECEIVE_DISABLE CTL0_REN(0) /*!< disable receiver */ + +/* USART transmitter configure */ +#define CTL0_TEN(regval) (BIT(3) & ((uint32_t)(regval) << 3)) +#define USART_TRANSMIT_ENABLE CTL0_TEN(1) /*!< enable transmitter */ +#define USART_TRANSMIT_DISABLE CTL0_TEN(0) /*!< disable transmitter */ + +/* USART parity bits definitions */ +#define CTL0_PM(regval) (BITS(9,10) & ((uint32_t)(regval) << 9)) +#define USART_PM_NONE CTL0_PM(0) /*!< no parity */ +#define USART_PM_EVEN CTL0_PM(2) /*!< even parity */ +#define USART_PM_ODD CTL0_PM(3) /*!< odd parity */ + +/* USART wakeup method in mute mode */ +#define CTL0_WM(regval) (BIT(11) & ((uint32_t)(regval) << 11)) +#define USART_WM_IDLE CTL0_WM(0) /*!< idle line */ +#define USART_WM_ADDR CTL0_WM(1) /*!< address match */ + +/* USART word length definitions */ +#define CTL0_WL(regval) (BIT(12) & ((uint32_t)(regval) << 12)) +#define USART_WL_8BIT CTL0_WL(0) /*!< 8 bits */ +#define USART_WL_9BIT CTL0_WL(1) /*!< 9 bits */ + +/* USART stop bits definitions */ +#define CTL1_STB(regval) (BITS(12,13) & ((uint32_t)(regval) << 12)) +#define USART_STB_1BIT CTL1_STB(0) /*!< 1 bit */ +#define USART_STB_0_5BIT CTL1_STB(1) /*!< 0.5 bit */ +#define USART_STB_2BIT CTL1_STB(2) /*!< 2 bits */ +#define USART_STB_1_5BIT CTL1_STB(3) /*!< 1.5 bits */ + +/* USART LIN break frame length */ +#define CTL1_LBLEN(regval) (BIT(5) & ((uint32_t)(regval) << 5)) +#define USART_LBLEN_10B CTL1_LBLEN(0) /*!< 10 bits */ +#define USART_LBLEN_11B CTL1_LBLEN(1) /*!< 11 bits */ + +/* USART CK length */ +#define CTL1_CLEN(regval) (BIT(8) & ((uint32_t)(regval) << 8)) +#define USART_CLEN_NONE CTL1_CLEN(0) /*!< there are 7 CK pulses for an 8 bit frame and 8 CK pulses for a 9 bit frame */ +#define USART_CLEN_EN CTL1_CLEN(1) /*!< there are 8 CK pulses for an 8 bit frame and 9 CK pulses for a 9 bit frame */ + +/* USART clock phase */ +#define CTL1_CPH(regval) (BIT(9) & ((uint32_t)(regval) << 9)) +#define USART_CPH_1CK CTL1_CPH(0) /*!< first clock transition is the first data capture edge */ +#define USART_CPH_2CK CTL1_CPH(1) /*!< second clock transition is the first data capture edge */ + +/* USART clock polarity */ +#define CTL1_CPL(regval) (BIT(10) & ((uint32_t)(regval) << 10)) +#define USART_CPL_LOW CTL1_CPL(0) /*!< steady low value on CK pin */ +#define USART_CPL_HIGH CTL1_CPL(1) /*!< steady high value on CK pin */ + +/* USART DMA request for receive configure */ +#define CLT2_DENR(regval) (BIT(6) & ((uint32_t)(regval) << 6)) +#define USART_DENR_ENABLE CLT2_DENR(1) /*!< DMA request enable for reception */ +#define USART_DENR_DISABLE CLT2_DENR(0) /*!< DMA request disable for reception */ + +/* USART DMA request for transmission configure */ +#define CLT2_DENT(regval) (BIT(7) & ((uint32_t)(regval) << 7)) +#define USART_DENT_ENABLE CLT2_DENT(1) /*!< DMA request enable for transmission */ +#define USART_DENT_DISABLE CLT2_DENT(0) /*!< DMA request disable for transmission */ + +/* USART RTS configure */ +#define CLT2_RTSEN(regval) (BIT(8) & ((uint32_t)(regval) << 8)) +#define USART_RTS_ENABLE CLT2_RTSEN(1) /*!< RTS enable */ +#define USART_RTS_DISABLE CLT2_RTSEN(0) /*!< RTS disable */ + +/* USART CTS configure */ +#define CLT2_CTSEN(regval) (BIT(9) & ((uint32_t)(regval) << 9)) +#define USART_CTS_ENABLE CLT2_CTSEN(1) /*!< CTS enable */ +#define USART_CTS_DISABLE CLT2_CTSEN(0) /*!< CTS disable */ + +/* USART IrDA low-power enable */ +#define CTL2_IRLP(regval) (BIT(2) & ((uint32_t)(regval) << 2)) +#define USART_IRLP_LOW CTL2_IRLP(1) /*!< low-power */ +#define USART_IRLP_NORMAL CTL2_IRLP(0) /*!< normal */ + +/* USART data is transmitted/received with the LSB/MSB first */ +#define CTL3_MSBF(regval) (BIT(11) & ((uint32_t)(regval) << 11)) +#define USART_MSBF_LSB CTL3_MSBF(0) /*!< LSB first */ +#define USART_MSBF_MSB CTL3_MSBF(1) /*!< MSB first */ + + + +/* function declarations */ +/* initialization functions */ +/* reset USART */ +void usart_deinit(uint32_t usart_periph); +/* configure USART baud rate value */ +void usart_baudrate_set(uint32_t usart_periph, uint32_t baudval); +/* configure USART parity function */ +void usart_parity_config(uint32_t usart_periph, uint32_t paritycfg); +/* configure USART word length */ +void usart_word_length_set(uint32_t usart_periph, uint32_t wlen); +/* configure USART stop bit length */ +void usart_stop_bit_set(uint32_t usart_periph, uint32_t stblen); + +/* function configuration */ +/* USART normal mode communication */ +/* enable USART */ +void usart_enable(uint32_t usart_periph); +/* disable USART */ +void usart_disable(uint32_t usart_periph); +/* configure USART transmitter */ +void usart_transmit_config(uint32_t usart_periph, uint32_t txconfig); +/* configure USART receiver */ +void usart_receive_config(uint32_t usart_periph, uint32_t rxconfig); +/* data is transmitted/received with the LSB/MSB first */ +void usart_data_first_config(uint32_t usart_periph, uint32_t msbf); +/* configure USART inverted */ +void usart_invert_config(uint32_t usart_periph, usart_invert_enum invertpara); +/* enable receiver timeout */ +void usart_receiver_timeout_enable(uint32_t usart_periph); +/* disable receiver timeout */ +void usart_receiver_timeout_disable(uint32_t usart_periph); +/* configure receiver timeout threshold */ +void usart_receiver_timeout_threshold_config(uint32_t usart_periph, uint32_t rtimeout); +/* USART transmit data function */ +void usart_data_transmit(uint32_t usart_periph, uint16_t data); +/* USART receive data function */ +uint16_t usart_data_receive(uint32_t usart_periph); + +/* multi-processor communication */ +/* configure address of the USART */ +void usart_address_config(uint32_t usart_periph, uint8_t addr); +/* enable mute mode */ +void usart_mute_mode_enable(uint32_t usart_periph); +/* disable mute mode */ +void usart_mute_mode_disable(uint32_t usart_periph); +/* configure wakeup method in mute mode */ +void usart_mute_mode_wakeup_config(uint32_t usart_periph, uint32_t wmethod); + +/* LIN mode communication */ +/* LIN mode enable */ +void usart_lin_mode_enable(uint32_t usart_periph); +/* LIN mode disable */ +void usart_lin_mode_disable(uint32_t usart_periph); +/* LIN break detection length */ +void usart_lin_break_detection_length_config(uint32_t usart_periph, uint32_t lblen); +/* send break frame */ +void usart_send_break(uint32_t usart_periph); + +/* half-duplex communication */ +/* half-duplex enable */ +void usart_halfduplex_enable(uint32_t usart_periph); +/* half-duplex disable */ +void usart_halfduplex_disable(uint32_t usart_periph); + +/* synchronous communication */ +/* clock enable */ +void usart_synchronous_clock_enable(uint32_t usart_periph); +/* clock disable */ +void usart_synchronous_clock_disable(uint32_t usart_periph); +/* configure usart synchronous mode parameters */ +void usart_synchronous_clock_config(uint32_t usart_periph, uint32_t clen, uint32_t cph, uint32_t cpl); + +/* smartcard communication */ +/* guard time value configure in smartcard mode */ +void usart_guard_time_config(uint32_t usart_periph,uint32_t guat); +/* smartcard mode enable */ +void usart_smartcard_mode_enable(uint32_t usart_periph); +/* smartcard mode disable */ +void usart_smartcard_mode_disable(uint32_t usart_periph); +/* NACK enable in smartcard mode */ +void usart_smartcard_mode_nack_enable(uint32_t usart_periph); +/* NACK disable in smartcard mode */ +void usart_smartcard_mode_nack_disable(uint32_t usart_periph); +/* smartcard auto-retry number configure */ +void usart_smartcard_autoretry_config(uint32_t usart_periph, uint32_t scrtnum); +/* block length configure */ +void usart_block_length_config(uint32_t usart_periph, uint32_t bl); + +/* IrDA communication */ +/* enable IrDA mode */ +void usart_irda_mode_enable(uint32_t usart_periph); +/* disable IrDA mode */ +void usart_irda_mode_disable(uint32_t usart_periph); +/* configure the peripheral clock prescaler */ +void usart_prescaler_config(uint32_t usart_periph, uint8_t psc); +/* configure IrDA low-power */ +void usart_irda_lowpower_config(uint32_t usart_periph, uint32_t irlp); + +/* hardware flow communication */ +/* configure hardware flow control RTS */ +void usart_hardware_flow_rts_config(uint32_t usart_periph, uint32_t rtsconfig); +/* configure hardware flow control CTS */ +void usart_hardware_flow_cts_config(uint32_t usart_periph, uint32_t ctsconfig); + +/* configure USART DMA for reception */ +void usart_dma_receive_config(uint32_t usart_periph, uint32_t dmacmd); +/* configure USART DMA for transmission */ +void usart_dma_transmit_config(uint32_t usart_periph, uint32_t dmacmd); + +/* interrupt & flag functions */ +/* get flag in STAT0/STAT1 register */ +FlagStatus usart_flag_get(uint32_t usart_periph, usart_flag_enum flag); +/* clear flag in STAT0/STAT1 register */ +void usart_flag_clear(uint32_t usart_periph, usart_flag_enum flag); +/* enable USART interrupt */ +void usart_interrupt_enable(uint32_t usart_periph, uint32_t int_flag); +/* disable USART interrupt */ +void usart_interrupt_disable(uint32_t usart_periph, uint32_t int_flag); +/* get USART interrupt and flag status */ +FlagStatus usart_interrupt_flag_get(uint32_t usart_periph, uint32_t int_flag); +/* clear interrupt flag in STAT0/STAT1 register */ +void usart_interrupt_flag_clear(uint32_t usart_periph, uint32_t flag); + +#endif /* GD32F20X_USART_H */ diff --git a/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_standard_peripheral/Include/gd32f20x_wwdgt.h b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_standard_peripheral/Include/gd32f20x_wwdgt.h new file mode 100644 index 0000000000..1b11009455 --- /dev/null +++ b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_standard_peripheral/Include/gd32f20x_wwdgt.h @@ -0,0 +1,91 @@ +/*! + \file gd32f20x_wwdgt.h + \brief definitions for the WWDGT + + \version 2015-07-15, V1.0.0, firmware for GD32F20x + \version 2017-06-05, V2.0.0, firmware for GD32F20x + \version 2018-10-31, V2.1.0, firmware for GD32F20x + \version 2020-09-30, V2.2.0, firmware for GD32F20x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef GD32F20X_WWDGT_H +#define GD32F20X_WWDGT_H + +#include "gd32f20x.h" + +/* WWDGT definitions */ +#define WWDGT WWDGT_BASE /*!< WWDGT base address */ + +/* registers definitions */ +#define WWDGT_CTL REG32((WWDGT) + 0x00U) /*!< WWDGT control register */ +#define WWDGT_CFG REG32((WWDGT) + 0x04U) /*!< WWDGT configuration register */ +#define WWDGT_STAT REG32((WWDGT) + 0x08U) /*!< WWDGT status register */ + +/* bits definitions */ +/* WWDGT_CTL */ +#define WWDGT_CTL_CNT BITS(0,6) /*!< WWDGT counter value */ +#define WWDGT_CTL_WDGTEN BIT(7) /*!< WWDGT counter enable */ + +/* WWDGT_CFG */ +#define WWDGT_CFG_WIN BITS(0,6) /*!< WWDGT counter window value */ +#define WWDGT_CFG_PSC BITS(7,8) /*!< WWDGT prescaler divider value */ +#define WWDGT_CFG_EWIE BIT(9) /*!< early wakeup interrupt enable */ + +/* WWDGT_STAT */ +#define WWDGT_STAT_EWIF BIT(0) /*!< early wakeup interrupt flag */ + +/* constants definitions */ +#define CFG_PSC(regval) (BITS(7,8) & ((uint32_t)(regval) << 7)) /*!< write value to WWDGT_CFG_PSC bit field */ +#define WWDGT_CFG_PSC_DIV1 CFG_PSC(0) /*!< the time base of WWDGT = (PCLK1/4096)/1 */ +#define WWDGT_CFG_PSC_DIV2 CFG_PSC(1) /*!< the time base of WWDGT = (PCLK1/4096)/2 */ +#define WWDGT_CFG_PSC_DIV4 CFG_PSC(2) /*!< the time base of WWDGT = (PCLK1/4096)/4 */ +#define WWDGT_CFG_PSC_DIV8 CFG_PSC(3) /*!< the time base of WWDGT = (PCLK1/4096)/8 */ + +/* function declarations */ +/* initialization functions */ +/* reset the window watchdog timer configuration */ +void wwdgt_deinit(void); +/* start the window watchdog timer counter */ +void wwdgt_enable(void); + +/* configure the window watchdog timer counter value */ +void wwdgt_counter_update(uint16_t counter_value); +/* configure counter value, window value, and prescaler divider value */ +void wwdgt_config(uint16_t counter, uint16_t window, uint32_t prescaler); + +/* interrupt & flag functions */ +/* enable early wakeup interrupt of WWDGT */ +void wwdgt_interrupt_enable(void); +/* check early wakeup interrupt state of WWDGT */ +FlagStatus wwdgt_flag_get(void); +/* clear early wakeup interrupt state of WWDGT */ +void wwdgt_flag_clear(void); + +#endif /* GD32F20X_WWDGT_H */ diff --git a/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_standard_peripheral/Source/gd32f20x_adc.c b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_standard_peripheral/Source/gd32f20x_adc.c new file mode 100644 index 0000000000..567165855e --- /dev/null +++ b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_standard_peripheral/Source/gd32f20x_adc.c @@ -0,0 +1,1019 @@ +/*! + \file gd32f20x_adc.c + \brief ADC driver + + \version 2015-07-15, V1.0.0, firmware for GD32F20x + \version 2017-06-05, V2.0.0, firmware for GD32F20x + \version 2018-10-31, V2.1.0, firmware for GD32F20x + \version 2020-09-30, V2.2.0, firmware for GD32F20x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "gd32f20x_adc.h" + +/* discontinuous mode macro*/ +#define ADC_CHANNEL_LENGTH_SUBTRACT_ONE ((uint8_t)1U) + +/* ADC regular channel macro */ +#define ADC_REGULAR_CHANNEL_RANK_SIX ((uint8_t)6U) +#define ADC_REGULAR_CHANNEL_RANK_TWELVE ((uint8_t)12U) +#define ADC_REGULAR_CHANNEL_RANK_SIXTEEN ((uint8_t)16U) +#define ADC_REGULAR_CHANNEL_RANK_LENGTH ((uint8_t)5U) + +/* ADC sampling time macro */ +#define ADC_CHANNEL_SAMPLE_TEN ((uint8_t)10U) +#define ADC_CHANNEL_SAMPLE_EIGHTEEN ((uint8_t)18U) +#define ADC_CHANNEL_SAMPLE_LENGTH ((uint8_t)3U) + +/* ADC inserted channel macro */ +#define ADC_INSERTED_CHANNEL_RANK_LENGTH ((uint8_t)5U) +#define ADC_INSERTED_CHANNEL_SHIFT_LENGTH ((uint8_t)15U) + +/* ADC inserted channel offset macro */ +#define ADC_OFFSET_LENGTH ((uint8_t)3U) +#define ADC_OFFSET_SHIFT_LENGTH ((uint8_t)4U) + +/*! + \brief reset ADC + \param[in] adc_periph: ADCx, x=0,1,2 + \param[out] none + \retval none +*/ +void adc_deinit(uint32_t adc_periph) +{ + switch(adc_periph){ + case ADC0: + /* reset ADC0 */ + rcu_periph_reset_enable(RCU_ADC0RST); + rcu_periph_reset_disable(RCU_ADC0RST); + break; + case ADC1: + /* reset ADC1 */ + rcu_periph_reset_enable(RCU_ADC1RST); + rcu_periph_reset_disable(RCU_ADC1RST); + break; + case ADC2: + /* reset ADC2 */ + rcu_periph_reset_enable(RCU_ADC2RST); + rcu_periph_reset_disable(RCU_ADC2RST); + break; + default: + break; + } +} + +/*! + \brief configure the ADC sync mode(only for ADC0) + \param[in] mode: ADC mode + only one parameter can be selected which is shown as below: + \arg ADC_MODE_FREE: all the ADCs work independently + \arg ADC_DAUL_REGULAL_PARALLEL_INSERTED_PARALLEL: ADC0 and ADC1 work in combined regular parallel + inserted parallel mode + \arg ADC_DAUL_REGULAL_PARALLEL_INSERTED_ROTATION: ADC0 and ADC1 work in combined regular parallel + trigger rotation mode + \arg ADC_DAUL_INSERTED_PARALLEL_REGULAL_FOLLOWUP_FAST: ADC0 and ADC1 work in combined inserted parallel + follow-up fast mode + \arg ADC_DAUL_INSERTED_PARALLEL_REGULAL_FOLLOWUP_SLOW: ADC0 and ADC1 work in combined inserted parallel + follow-up slow mode + \arg ADC_DAUL_INSERTED_PARALLEL: ADC0 and ADC1 work in inserted parallel mode only + \arg ADC_DAUL_REGULAL_PARALLEL: ADC0 and ADC1 work in regular parallel mode only + \arg ADC_DAUL_REGULAL_FOLLOWUP_FAST: ADC0 and ADC1 work in follow-up fast mode only + \arg ADC_DAUL_REGULAL_FOLLOWUP_SLOW: ADC0 and ADC1 work in follow-up slow mode only + \arg ADC_DAUL_INSERTED_TRIGGER_ROTATION: ADC0 and ADC1 work in trigger rotation mode only + \param[out] none + \retval none +*/ +void adc_mode_config(uint32_t mode) +{ + ADC_CTL0(ADC0) &= ~(ADC_CTL0_SYNCM); + ADC_CTL0(ADC0) |= mode; +} + +/*! + \brief enable or disable ADC special function + \param[in] adc_periph: ADCx, x=0,1,2 + \param[in] function: the function to configure + one or more parameters can be selected below + \arg ADC_SCAN_MODE: scan mode select + \arg ADC_INSERTED_CHANNEL_AUTO: inserted channel group convert automatically + \arg ADC_CONTINUOUS_MODE: continuous mode select + \param[in] new_value: ENABLE or DISABLE + \param[out] none + \retval none +*/ +void adc_special_function_config(uint32_t adc_periph, uint32_t function, ControlStatus new_value) +{ + if(new_value){ + if(0U != (function & ADC_SCAN_MODE)){ + /* enable ADC scan mode */ + ADC_CTL0(adc_periph) |= ADC_SCAN_MODE; + } + + if(0U != (function & ADC_INSERTED_CHANNEL_AUTO)){ + /* enable ADC inserted channel group convert automatically */ + ADC_CTL0(adc_periph) |= ADC_INSERTED_CHANNEL_AUTO; + } + + if(0U != (function & ADC_CONTINUOUS_MODE)){ + /* enable ADC continuous mode */ + ADC_CTL1(adc_periph) |= ADC_CONTINUOUS_MODE; + } + }else{ + if(0U != (function & ADC_SCAN_MODE)){ + /* disable scan mode */ + ADC_CTL0(adc_periph) &= ~ADC_SCAN_MODE; + } + + if(0U != (function & ADC_INSERTED_CHANNEL_AUTO)){ + /* disable ADC inserted channel group convert automatically */ + ADC_CTL0(adc_periph) &= ~ADC_INSERTED_CHANNEL_AUTO; + } + + if(0U != (function & ADC_CONTINUOUS_MODE)){ + /* disable ADC continuous mode */ + ADC_CTL1(adc_periph) &= ~ADC_CONTINUOUS_MODE; + } + } +} + +/*! + \brief configure ADC data alignment + \param[in] adc_periph: ADCx, x=0,1,2 + \param[in] data_alignment: data alignment select + only one parameter can be selected which is shown as below: + \arg ADC_DATAALIGN_RIGHT: LSB alignment + \arg ADC_DATAALIGN_LEFT: MSB alignment + \param[out] none + \retval none +*/ +void adc_data_alignment_config(uint32_t adc_periph, uint32_t data_alignment) +{ + if(ADC_DATAALIGN_RIGHT != data_alignment){ + /* MSB alignment */ + ADC_CTL1(adc_periph) |= ADC_CTL1_DAL; + }else{ + /* LSB alignment */ + ADC_CTL1(adc_periph) &= ~((uint32_t)ADC_CTL1_DAL); + } +} + +/*! + \brief enable ADC interface + \param[in] adc_periph: ADCx, x=0,1,2 + \param[out] none + \retval none +*/ +void adc_enable(uint32_t adc_periph) +{ + if(RESET == (ADC_CTL1(adc_periph) & ADC_CTL1_ADCON)){ + /* enable ADC */ + ADC_CTL1(adc_periph) |= (uint32_t)ADC_CTL1_ADCON; + } +} + +/*! + \brief disable ADC interface + \param[in] adc_periph: ADCx, x=0,1,2 + \param[out] none + \retval none +*/ +void adc_disable(uint32_t adc_periph) +{ + /* disable ADC */ + ADC_CTL1(adc_periph) &= ~((uint32_t)ADC_CTL1_ADCON); +} + +/*! + \brief ADC calibration and reset calibration + \param[in] adc_periph: ADCx, x=0,1,2 + \param[out] none + \retval none +*/ +void adc_calibration_enable(uint32_t adc_periph) +{ + /* reset the selected ADC calibration registers */ + ADC_CTL1(adc_periph) |= (uint32_t) ADC_CTL1_RSTCLB; + /* check the RSTCLB bit state */ + while(RESET != (ADC_CTL1(adc_periph) & ADC_CTL1_RSTCLB)){ + } + /* enable ADC calibration process */ + ADC_CTL1(adc_periph) |= ADC_CTL1_CLB; + /* check the CLB bit state */ + while(RESET != (ADC_CTL1(adc_periph) & ADC_CTL1_CLB)){ + } +} + +/*! + \brief enable the temperature sensor and Vrefint channel + \param[in] none + \param[out] none + \retval none +*/ +void adc_tempsensor_vrefint_enable(void) +{ + /* enable the temperature sensor and Vrefint channel */ + ADC_CTL1(ADC0) |= ADC_CTL1_TSVREN; +} + +/*! + \brief disable the temperature sensor and Vrefint channel + \param[in] none + \param[out] none + \retval none +*/ +void adc_tempsensor_vrefint_disable(void) +{ + /* disable the temperature sensor and Vrefint channel */ + ADC_CTL1(ADC0) &= ~ADC_CTL1_TSVREN; +} + +/*! + \brief enable DMA request + \param[in] adc_periph: ADCx, x=0,1,2 + only one among these parameters can be selected + \param[out] none + \retval none +*/ +void adc_dma_mode_enable(uint32_t adc_periph) +{ + /* enable DMA request */ + ADC_CTL1(adc_periph) |= (uint32_t)(ADC_CTL1_DMA); +} + +/*! + \brief disable DMA request + \param[in] adc_periph: ADCx, x=0,1,2 + \param[out] none + \retval none +*/ +void adc_dma_mode_disable(uint32_t adc_periph) +{ + /* disable DMA request */ + ADC_CTL1(adc_periph) &= ~((uint32_t)ADC_CTL1_DMA); +} + +/*! + \brief configure ADC discontinuous mode + \param[in] adc_periph: ADCx, x=0,1,2 + \param[in] adc_channel_group: select the channel group + only one parameter can be selected which is shown as below: + \arg ADC_REGULAR_CHANNEL: regular channel group + \arg ADC_INSERTED_CHANNEL: inserted channel group + \arg ADC_CHANNEL_DISCON_DISABLE: disable discontinuous mode of regular and inserted channel + \param[in] length: number of conversions in discontinuous mode,the number can be 1..8 + for regular channel, the number has no effect for inserted channel + \param[out] none + \retval none +*/ +void adc_discontinuous_mode_config(uint32_t adc_periph, uint8_t adc_channel_group, uint8_t length) +{ + /* disable discontinuous mode of regular & inserted channel */ + ADC_CTL0(adc_periph) &= ~((uint32_t)(ADC_CTL0_DISRC | ADC_CTL0_DISIC)); + switch(adc_channel_group){ + case ADC_REGULAR_CHANNEL: + /* configure the number of conversions in discontinuous mode */ + ADC_CTL0(adc_periph) &= ~((uint32_t)ADC_CTL0_DISNUM); + ADC_CTL0(adc_periph) |= CTL0_DISNUM(((uint32_t)length - ADC_CHANNEL_LENGTH_SUBTRACT_ONE)); + /* enable regular channel group discontinuous mode */ + ADC_CTL0(adc_periph) |= (uint32_t)ADC_CTL0_DISRC; + break; + case ADC_INSERTED_CHANNEL: + /* enable inserted channel group discontinuous mode */ + ADC_CTL0(adc_periph) |= (uint32_t)ADC_CTL0_DISIC; + break; + case ADC_CHANNEL_DISCON_DISABLE: + /* disable discontinuous mode of regular & inserted channel */ + default: + break; + } +} + +/*! + \brief configure the length of regular channel group or inserted channel group + \param[in] adc_periph: ADCx, x=0,1,2 + \param[in] adc_channel_group: select the channel group + only one parameter can be selected which is shown as below: + \arg ADC_REGULAR_CHANNEL: regular channel group + \arg ADC_INSERTED_CHANNEL: inserted channel group + \param[in] length: the length of the channel + regular channel 1-16 + inserted channel 1-4 + \param[out] none + \retval none +*/ +void adc_channel_length_config(uint32_t adc_periph, uint8_t adc_channel_group, uint32_t length) +{ + switch(adc_channel_group){ + case ADC_REGULAR_CHANNEL: + /* configure the length of regular channel group */ + ADC_RSQ0(adc_periph) &= ~((uint32_t)ADC_RSQ0_RL); + ADC_RSQ0(adc_periph) |= RSQ0_RL((uint32_t)(length - ADC_CHANNEL_LENGTH_SUBTRACT_ONE)); + break; + case ADC_INSERTED_CHANNEL: + /* configure the length of inserted channel group */ + ADC_ISQ(adc_periph) &= ~((uint32_t)ADC_ISQ_IL); + ADC_ISQ(adc_periph) |= ISQ_IL((uint32_t)(length - ADC_CHANNEL_LENGTH_SUBTRACT_ONE)); + break; + default: + break; + } +} + +/*! + \brief configure ADC regular channel + \param[in] adc_periph: ADCx, x=0,1,2 + only one among these parameters can be selected + \param[in] rank: the regular group sequence rank,this parameter must be between 0 to 15 + \param[in] adc_channel: the selected ADC channel + only one parameter can be selected which is shown as below: + \arg ADC_CHANNEL_x(x=0..17)(x=16 and x=17 are only for ADC0): ADC Channelx + \param[in] sample_time: the sample time value + only one parameter can be selected which is shown as below: + \arg ADC_SAMPLETIME_1POINT5: 1.5 cycles + \arg ADC_SAMPLETIME_7POINT5: 7.5 cycles + \arg ADC_SAMPLETIME_13POINT5: 13.5 cycles + \arg ADC_SAMPLETIME_28POINT5: 28.5 cycles + \arg ADC_SAMPLETIME_41POINT5: 41.5 cycles + \arg ADC_SAMPLETIME_55POINT5: 55.5 cycles + \arg ADC_SAMPLETIME_71POINT5: 71.5 cycles + \arg ADC_SAMPLETIME_239POINT5: 239.5 cycles + \param[out] none + \retval none +*/ +void adc_regular_channel_config(uint32_t adc_periph, uint8_t rank, uint8_t adc_channel, uint32_t sample_time) +{ + uint32_t rsq,sampt; + + /* configure ADC regular sequence */ + if(rank < ADC_REGULAR_CHANNEL_RANK_SIX){ + /* the regular group sequence rank is smaller than six */ + rsq = ADC_RSQ2(adc_periph); + rsq &= ~((uint32_t)(ADC_RSQX_RSQN << (ADC_REGULAR_CHANNEL_RANK_LENGTH * rank))); + /* the channel number is written to these bits to select a channel as the nth conversion in the regular channel group */ + rsq |= ((uint32_t)adc_channel << (ADC_REGULAR_CHANNEL_RANK_LENGTH * rank)); + ADC_RSQ2(adc_periph) = rsq; + }else if(rank < ADC_REGULAR_CHANNEL_RANK_TWELVE){ + /* the regular group sequence rank is smaller than twelve */ + rsq = ADC_RSQ1(adc_periph); + rsq &= ~((uint32_t)(ADC_RSQX_RSQN << (ADC_REGULAR_CHANNEL_RANK_LENGTH * (rank - ADC_REGULAR_CHANNEL_RANK_SIX)))); + /* the channel number is written to these bits to select a channel as the nth conversion in the regular channel group */ + rsq |= ((uint32_t)adc_channel << (ADC_REGULAR_CHANNEL_RANK_LENGTH * (rank - ADC_REGULAR_CHANNEL_RANK_SIX))); + ADC_RSQ1(adc_periph) = rsq; + }else if(rank < ADC_REGULAR_CHANNEL_RANK_SIXTEEN){ + /* the regular group sequence rank is smaller than sixteen */ + rsq = ADC_RSQ0(adc_periph); + rsq &= ~((uint32_t)(ADC_RSQX_RSQN << (ADC_REGULAR_CHANNEL_RANK_LENGTH * (rank - ADC_REGULAR_CHANNEL_RANK_TWELVE)))); + /* the channel number is written to these bits to select a channel as the nth conversion in the regular channel group */ + rsq |= ((uint32_t)adc_channel << (ADC_REGULAR_CHANNEL_RANK_LENGTH * (rank - ADC_REGULAR_CHANNEL_RANK_TWELVE))); + ADC_RSQ0(adc_periph) = rsq; + }else{ + /* illegal parameters */ + } + + /* configure ADC sampling time */ + if(adc_channel < ADC_CHANNEL_SAMPLE_TEN){ + /* the regular group sequence rank is smaller than ten */ + sampt = ADC_SAMPT1(adc_periph); + sampt &= ~((uint32_t)(ADC_SAMPTX_SPTN << (ADC_CHANNEL_SAMPLE_LENGTH * adc_channel))); + /* channel sample time set*/ + sampt |= (uint32_t)(sample_time << (ADC_CHANNEL_SAMPLE_LENGTH * adc_channel)); + ADC_SAMPT1(adc_periph) = sampt; + }else if(adc_channel < ADC_CHANNEL_SAMPLE_EIGHTEEN){ + /* the regular group sequence rank is smaller than eighteen */ + sampt = ADC_SAMPT0(adc_periph); + sampt &= ~((uint32_t)(ADC_SAMPTX_SPTN << (ADC_CHANNEL_SAMPLE_LENGTH * (adc_channel - ADC_CHANNEL_SAMPLE_TEN)))); + /* channel sample time set*/ + sampt |= (uint32_t)(sample_time << (ADC_CHANNEL_SAMPLE_LENGTH * (adc_channel - ADC_CHANNEL_SAMPLE_TEN))); + ADC_SAMPT0(adc_periph) = sampt; + }else{ + /* illegal parameters */ + } +} + +/*! + \brief configure ADC inserted channel + \param[in] adc_periph: ADCx,x=0,1,2 + only one among these parameters can be selected + \param[in] rank: the inserted group sequencer rank,this parameter must be between 0 to 3 + \param[in] adc_channel: the selected ADC channel + only one parameter can be selected which is shown as below: + \arg ADC_CHANNEL_x(x=0..17)(x=16 and x=17 are only for ADC0): ADC Channelx + \param[in] sample_time: The sample time value + only one parameter can be selected which is shown as below: + \arg ADC_SAMPLETIME_1POINT5: 1.5 cycles + \arg ADC_SAMPLETIME_7POINT5: 7.5 cycles + \arg ADC_SAMPLETIME_13POINT5: 13.5 cycles + \arg ADC_SAMPLETIME_28POINT5: 28.5 cycles + \arg ADC_SAMPLETIME_41POINT5: 41.5 cycles + \arg ADC_SAMPLETIME_55POINT5: 55.5 cycles + \arg ADC_SAMPLETIME_71POINT5: 71.5 cycles + \arg ADC_SAMPLETIME_239POINT5: 239.5 cycles + \param[out] none + \retval none +*/ +void adc_inserted_channel_config(uint32_t adc_periph, uint8_t rank, uint8_t adc_channel, uint32_t sample_time) +{ + uint8_t inserted_length; + uint32_t isq,sampt; + /* get inserted channel group length */ + inserted_length = (uint8_t)GET_BITS(ADC_ISQ(adc_periph), 20U, 21U); + /* the channel number is written to these bits to select a channel as the nth conversion in the inserted channel group */ + isq = ADC_ISQ(adc_periph); + isq &= ~((uint32_t)(ADC_ISQ_ISQN << (ADC_INSERTED_CHANNEL_SHIFT_LENGTH - (inserted_length - rank) * ADC_INSERTED_CHANNEL_RANK_LENGTH))); + isq |= ((uint32_t)adc_channel << (ADC_INSERTED_CHANNEL_SHIFT_LENGTH - (inserted_length - rank) * ADC_INSERTED_CHANNEL_RANK_LENGTH)); + ADC_ISQ(adc_periph) = isq; + + /* ADC sampling time config */ + if(adc_channel < ADC_CHANNEL_SAMPLE_TEN){ + /* the inserted group sequence rank is smaller than ten */ + sampt = ADC_SAMPT1(adc_periph); + sampt &= ~((uint32_t)(ADC_SAMPTX_SPTN << (ADC_CHANNEL_SAMPLE_LENGTH * adc_channel))); + /* channel sample time set*/ + sampt |= (uint32_t) sample_time << (ADC_CHANNEL_SAMPLE_LENGTH * adc_channel); + ADC_SAMPT1(adc_periph) = sampt; + }else if(adc_channel < ADC_CHANNEL_SAMPLE_EIGHTEEN){ + /* the inserted group sequence rank is smaller than eighteen */ + sampt = ADC_SAMPT0(adc_periph); + sampt &= ~((uint32_t)(ADC_SAMPTX_SPTN << (ADC_CHANNEL_SAMPLE_LENGTH * (adc_channel - ADC_CHANNEL_SAMPLE_TEN)))); + /* channel sample time set*/ + sampt |= ((uint32_t)sample_time << (ADC_CHANNEL_SAMPLE_LENGTH * (adc_channel - ADC_CHANNEL_SAMPLE_TEN))); + ADC_SAMPT0(adc_periph) = sampt; + }else{ + /* illegal parameters */ + } +} + +/*! + \brief configure ADC inserted channel offset + \param[in] adc_periph: ADCx,x=0,1,2 + only one among these parameters can be selected + \param[in] inserted_channel: insert channel select + only one parameter can be selected + \arg ADC_INSERTED_CHANNEL_0: ADC inserted channel0 + \arg ADC_INSERTED_CHANNEL_1: ADC inserted channel1 + \arg ADC_INSERTED_CHANNEL_2: ADC inserted channel2 + \arg ADC_INSERTED_CHANNEL_3: ADC inserted channel3 + \param[in] offset: the offset data + \param[out] none + \retval none +*/ +void adc_inserted_channel_offset_config(uint32_t adc_periph, uint8_t inserted_channel, uint16_t offset) +{ + uint8_t inserted_length; + uint32_t num = 0U; + + inserted_length = (uint8_t)GET_BITS(ADC_ISQ(adc_periph), 20U, 21U); + num = ((uint32_t)ADC_OFFSET_LENGTH - ((uint32_t)inserted_length - (uint32_t)inserted_channel)); + + if(num <= ADC_OFFSET_LENGTH){ + /* calculate the offset of the register */ + num = num * ADC_OFFSET_SHIFT_LENGTH; + /* configure the offset of the selected channels */ + REG32((adc_periph) + 0x14U + num) = IOFFX_IOFF((uint32_t)offset); + } +} + +/*! + \brief configure ADC external trigger source + \param[in] adc_periph: ADCx, x=0,1,2 + only one among these parameters can be selected + \param[in] adc_channel_group: select the channel group + only one parameter can be selected which is shown as below: + \arg ADC_REGULAR_CHANNEL: regular channel group + \arg ADC_INSERTED_CHANNEL: inserted channel group + \param[in] external_trigger_source: regular or inserted group trigger source + only one parameter can be selected + for regular channel: + \arg ADC0_1_EXTTRIG_REGULAR_T0_CH0: TIMER0 CH0 event select + \arg ADC0_1_EXTTRIG_REGULAR_T0_CH1: TIMER0 CH1 event select + \arg ADC0_1_EXTTRIG_REGULAR_T0_CH2: TIMER0 CH2 event select + \arg ADC0_1_EXTTRIG_REGULAR_T1_CH1: TIMER1 CH1 event select + \arg ADC0_1_EXTTRIG_REGULAR_T2_TRGO: TIMER2 TRGO event select + \arg ADC0_1_EXTTRIG_REGULAR_T3_CH3: TIMER3 CH3 event select + \arg ADC0_1_EXTTRIG_REGULAR_T7_TRGO: TIMER7 TRGO event select + \arg ADC0_1_EXTTRIG_REGULAR_EXTI_11 : external interrupt line 11 + \arg ADC2_EXTTRIG_REGULAR_T2_CH0: TIMER2 CH0 event select + \arg ADC2_EXTTRIG_REGULAR_T1_CH2: TIMER1 CH2 event select + \arg ADC2_EXTTRIG_REGULAR_T0_CH2: TIMER0 CH2 event select + \arg ADC2_EXTTRIG_REGULAR_T7_CH0: TIMER7 CH0 event select + \arg ADC2_EXTTRIG_REGULAR_T7_TRGO: TIMER7 TRGO event select + \arg ADC2_EXTTRIG_REGULAR_T4_CH0: TIMER4 CH0 event select + \arg ADC2_EXTTRIG_REGULAR_T4_CH2: TIMER4 CH2 event select + \arg ADC0_1_2_EXTTRIG_REGULAR_NONE: software trigger + for inserted channel: + \arg ADC0_1_EXTTRIG_INSERTED_T0_TRGO: TIMER0 TRGO event select + \arg ADC0_1_EXTTRIG_INSERTED_T0_CH3: TIMER0 CH3 event select + \arg ADC0_1_EXTTRIG_INSERTED_T1_TRGO: TIMER1 TRGO event select + \arg ADC0_1_EXTTRIG_INSERTED_T1_CH0: TIMER1 CH0 event select + \arg ADC0_1_EXTTRIG_INSERTED_T2_CH3: TIMER2 CH3 event select + \arg ADC0_1_EXTTRIG_INSERTED_T3_TRGO: TIMER3 TRGO event select + \arg ADC0_1_EXTTRIG_INSERTED_EXTI_15: external interrupt line 15 + \arg ADC0_1_EXTTRIG_INSERTED_T7_CH3: TIMER7 CH3 event select + \arg ADC2_EXTTRIG_INSERTED_T0_TRGO: TIMER0 TRGO event select + \arg ADC2_EXTTRIG_INSERTED_T0_CH3: TIMER0 CH3 event select + \arg ADC2_EXTTRIG_INSERTED_T3_CH2: TIMER3 CH2 event select + \arg ADC2_EXTTRIG_INSERTED_T7_CH1: TIMER7 CH1 event select + \arg ADC2_EXTTRIG_INSERTED_T7_CH3: TIMER7 CH3 event select + \arg ADC2_EXTTRIG_INSERTED_T4_TRGO: TIMER4 TRGO event select + \arg ADC2_EXTTRIG_INSERTED_T4_CH3: TIMER4 CH3 event select + \arg ADC0_1_2_EXTTRIG_INSERTED_NONE: software trigger + \param[out] none + \retval none +*/ +void adc_external_trigger_source_config(uint32_t adc_periph, uint8_t adc_channel_group, uint32_t external_trigger_source) +{ + switch(adc_channel_group){ + case ADC_REGULAR_CHANNEL: + /* configure ADC regular group external trigger source */ + ADC_CTL1(adc_periph) &= ~((uint32_t)ADC_CTL1_ETSRC); + ADC_CTL1(adc_periph) |= (uint32_t)external_trigger_source; + break; + case ADC_INSERTED_CHANNEL: + /* configure ADC inserted group external trigger source */ + ADC_CTL1(adc_periph) &= ~((uint32_t)ADC_CTL1_ETSIC); + ADC_CTL1(adc_periph) |= (uint32_t)external_trigger_source; + break; + default: + break; + } +} + +/*! + \brief configure ADC external trigger + \param[in] adc_periph: ADCx, x=0,1,2 + only one among these parameters can be selected + \param[in] adc_channel_group: select the channel group + one or more parameters can be selected which are shown as below: + \arg ADC_REGULAR_CHANNEL: regular channel group + \arg ADC_INSERTED_CHANNEL: inserted channel group + \param[in] newvalue: ENABLE or DISABLE + \param[out] none + \retval none +*/ +void adc_external_trigger_config(uint32_t adc_periph, uint8_t adc_channel_group, ControlStatus newvalue) +{ + if(newvalue){ + if(0U != (adc_channel_group & ADC_REGULAR_CHANNEL)){ + /* external trigger enable for regular channel */ + ADC_CTL1(adc_periph) |= ADC_CTL1_ETERC; + } + + if(0U != (adc_channel_group & ADC_INSERTED_CHANNEL)){ + /* external trigger enable for inserted channel */ + ADC_CTL1(adc_periph) |= ADC_CTL1_ETEIC; + } + }else{ + if(0U != (adc_channel_group & ADC_REGULAR_CHANNEL)){ + /* external trigger disable for regular channel */ + ADC_CTL1(adc_periph) &= ~ADC_CTL1_ETERC; + } + + if(0U != (adc_channel_group & ADC_INSERTED_CHANNEL)){ + /* external trigger disable for inserted channel */ + ADC_CTL1(adc_periph) &= ~ADC_CTL1_ETEIC; + } + } +} + +/*! + \brief enable ADC software trigger + \param[in] adc_periph: ADCx, x=0,1,2 + only one among these parameters can be selected + \param[in] adc_channel_group: select the channel group + one or more parameters can be selected which are shown as below: + \arg ADC_REGULAR_CHANNEL: regular channel group + \arg ADC_INSERTED_CHANNEL: inserted channel group + \param[out] none + \retval none +*/ +void adc_software_trigger_enable(uint32_t adc_periph, uint8_t adc_channel_group) +{ + if(0U != (adc_channel_group & ADC_REGULAR_CHANNEL)){ + /* enable regular group channel software trigger */ + ADC_CTL1(adc_periph) |= ADC_CTL1_SWRCST; + } + + if(0U != (adc_channel_group & ADC_INSERTED_CHANNEL)){ + /* enable inserted channel group software trigger */ + ADC_CTL1(adc_periph) |= ADC_CTL1_SWICST; + } +} + +/*! + \brief read ADC regular group data register + \param[in] adc_periph: ADCx, x=0,1,2 + only one among these parameters can be selected + \param[in] none + \param[out] none + \retval the conversion value +*/ +uint16_t adc_regular_data_read(uint32_t adc_periph) +{ + return (uint16_t)(ADC_RDATA(adc_periph)); +} + +/*! + \brief read ADC inserted group data register + \param[in] adc_periph: ADCx, x=0,1,2 + only one among these parameters can be selected + \param[in] inserted_channel: inserted channel select + only one parameter can be selected + \arg ADC_INSERTED_CHANNEL_0: ADC inserted channel0 + \arg ADC_INSERTED_CHANNEL_1: ADC inserted channel1 + \arg ADC_INSERTED_CHANNEL_2: ADC inserted channel2 + \arg ADC_INSERTED_CHANNEL_3: ADC inserted channel3 + \param[out] none + \retval the conversion value +*/ +uint16_t adc_inserted_data_read(uint32_t adc_periph, uint8_t inserted_channel) +{ + uint32_t idata; + /* read the data of the selected channel */ + switch(inserted_channel){ + case ADC_INSERTED_CHANNEL_0: + /* read the data of channel 0 */ + idata = ADC_IDATA0(adc_periph); + break; + case ADC_INSERTED_CHANNEL_1: + /* read the data of channel 1 */ + idata = ADC_IDATA1(adc_periph); + break; + case ADC_INSERTED_CHANNEL_2: + /* read the data of channel 2 */ + idata = ADC_IDATA2(adc_periph); + break; + case ADC_INSERTED_CHANNEL_3: + /* read the data of channel 3 */ + idata = ADC_IDATA3(adc_periph); + break; + default: + idata = 0U; + break; + } + return (uint16_t)idata; +} + +/*! + \brief read the last ADC0 and ADC1 conversion result data in sync mode + \param[in] none + \param[out] none + \retval the conversion value +*/ +uint32_t adc_sync_mode_convert_value_read(void) +{ + /* return conversion value */ + return ADC_RDATA(ADC0); +} + +/*! + \brief configure ADC analog watchdog single channel + \param[in] adc_periph: ADCx, x=0,1,2 + only one among these parameters can be selected + \param[in] adc_channel: the selected ADC channel + only one parameter can be selected which is shown as below: + \arg ADC_CHANNEL_x: ADC Channelx(x=0..17)(x=16 and x=17 are only for ADC0) + \param[out] none + \retval none +*/ +void adc_watchdog_single_channel_enable(uint32_t adc_periph, uint8_t adc_channel) +{ + ADC_CTL0(adc_periph) &= (uint32_t)~(ADC_CTL0_RWDEN | ADC_CTL0_IWDEN | ADC_CTL0_WDSC | ADC_CTL0_WDCHSEL); + /* analog watchdog channel select */ + ADC_CTL0(adc_periph) |= (uint32_t)adc_channel; + ADC_CTL0(adc_periph) |= (uint32_t)(ADC_CTL0_RWDEN | ADC_CTL0_IWDEN | ADC_CTL0_WDSC); +} + +/*! + \brief configure ADC analog watchdog group channel + \param[in] adc_periph: ADCx, x=0,1,2 + only one among these parameters can be selected + \param[in] adc_channel_group: the channel group use analog watchdog + only one parameter can be selected which is shown as below: + \arg ADC_REGULAR_CHANNEL: regular channel group + \arg ADC_INSERTED_CHANNEL: inserted channel group + \arg ADC_REGULAR_INSERTED_CHANNEL: both regular and inserted group + \param[out] none + \retval none +*/ +void adc_watchdog_group_channel_enable(uint32_t adc_periph, uint8_t adc_channel_group) +{ + ADC_CTL0(adc_periph) &= (uint32_t)~(ADC_CTL0_RWDEN | ADC_CTL0_IWDEN | ADC_CTL0_WDSC); + /* select the group */ + switch(adc_channel_group){ + case ADC_REGULAR_CHANNEL: + /* regular channel analog watchdog enable */ + ADC_CTL0(adc_periph) |= (uint32_t) ADC_CTL0_RWDEN; + break; + case ADC_INSERTED_CHANNEL: + /* inserted channel analog watchdog enable */ + ADC_CTL0(adc_periph) |= (uint32_t) ADC_CTL0_IWDEN; + break; + case ADC_REGULAR_INSERTED_CHANNEL: + /* regular and inserted channel analog watchdog enable */ + ADC_CTL0(adc_periph) |= (uint32_t)(ADC_CTL0_RWDEN | ADC_CTL0_IWDEN); + break; + default: + break; + } +} + +/*! + \brief disable ADC analog watchdog + \param[in] adc_periph: ADCx,x=0,1,2 + only one among these parameters can be selected + \param[out] none + \retval none +*/ +void adc_watchdog_disable(uint32_t adc_periph) +{ + ADC_CTL0(adc_periph) &= (uint32_t)~(ADC_CTL0_RWDEN | ADC_CTL0_IWDEN | ADC_CTL0_WDSC | ADC_CTL0_WDCHSEL); +} + +/*! + \brief configure ADC analog watchdog threshold + \param[in] adc_periph: ADCx,x=0,1,2 + only one among these parameters can be selected + \param[in] low_threshold: analog watchdog low threshold,0..4095 + \param[in] high_threshold: analog watchdog high threshold,0..4095 + \param[out] none + \retval none +*/ +void adc_watchdog_threshold_config(uint32_t adc_periph, uint16_t low_threshold, uint16_t high_threshold) +{ + ADC_WDLT(adc_periph) = (uint32_t)WDLT_WDLT(low_threshold); + ADC_WDHT(adc_periph) = (uint32_t)WDHT_WDHT(high_threshold); +} + +/*! + \brief get the ADC flag bits + \param[in] adc_periph: ADCx, x=0,1,2 + only one among these parameters can be selected + \param[in] adc_flag: the adc flag bits + only one parameter can be selected which is shown as below: + \arg ADC_FLAG_WDE: analog watchdog event flag + \arg ADC_FLAG_EOC: end of group conversion flag + \arg ADC_FLAG_EOIC: end of inserted group conversion flag + \arg ADC_FLAG_STIC: start flag of inserted channel group + \arg ADC_FLAG_STRC: start flag of regular channel group + \param[out] none + \retval FlagStatus: SET or RESET +*/ +FlagStatus adc_flag_get(uint32_t adc_periph, uint32_t adc_flag) +{ + FlagStatus reval = RESET; + if(ADC_STAT(adc_periph) & adc_flag){ + reval = SET; + } + return reval; +} + +/*! + \brief clear the ADC flag bits + \param[in] adc_periph: ADCx, x=0,1,2 + only one among these parameters can be selected + \param[in] adc_flag: the adc flag bits + one or more parameters can be selected which are shown as below: + \arg ADC_FLAG_WDE: analog watchdog event flag + \arg ADC_FLAG_EOC: end of group conversion flag + \arg ADC_FLAG_EOIC: end of inserted group conversion flag + \arg ADC_FLAG_STIC: start flag of inserted channel group + \arg ADC_FLAG_STRC: start flag of regular channel group + \param[out] none + \retval none +*/ +void adc_flag_clear(uint32_t adc_periph, uint32_t adc_flag) +{ + ADC_STAT(adc_periph) &= ~((uint32_t)adc_flag); +} + +/*! + \brief get the ADC interrupt flag + \param[in] adc_periph: ADCx,x=0,1,2 + only one among these parameters can be selected + \param[in] adc_interrupt: the adc interrupt bits + only one parameter can be selected which is shown as below: + \arg ADC_INT_FLAG_WDE: analog watchdog interrupt + \arg ADC_INT_FLAG_EOC: end of group conversion interrupt + \arg ADC_INT_FLAG_EOIC: end of inserted group conversion interrupt + \param[out] none + \retval FlagStatus: SET or RESET +*/ +FlagStatus adc_interrupt_flag_get(uint32_t adc_periph, uint32_t adc_interrupt) +{ + FlagStatus interrupt_flag = RESET; + uint32_t state; + /* check the interrupt bits */ + switch(adc_interrupt){ + case ADC_INT_FLAG_WDE: + /* get the ADC analog watchdog interrupt bits */ + state = ADC_STAT(adc_periph) & ADC_STAT_WDE; + if((ADC_CTL0(adc_periph) & ADC_CTL0_WDEIE) && state){ + interrupt_flag = SET; + } + break; + case ADC_INT_FLAG_EOC: + /* get the ADC end of group conversion interrupt bits */ + state = ADC_STAT(adc_periph) & ADC_STAT_EOC; + if((ADC_CTL0(adc_periph) & ADC_CTL0_EOCIE) && state){ + interrupt_flag = SET; + } + break; + case ADC_INT_FLAG_EOIC: + /* get the ADC end of inserted group conversion interrupt bits */ + state = ADC_STAT(adc_periph) & ADC_STAT_EOIC; + if((ADC_CTL0(adc_periph) & ADC_CTL0_EOICIE) && state){ + interrupt_flag = SET; + } + break; + default: + break; + } + + return interrupt_flag; +} + +/*! + \brief clear the ADC interrupt flag + \param[in] adc_periph: ADCx, x=0,1,2 + only one among these parameters can be selected + \param[in] adc_interrupt: the adc status flag + one or more parameters can be selected which are shown as below: + \arg ADC_INT_FLAG_WDE: analog watchdog interrupt + \arg ADC_INT_FLAG_EOC: end of group conversion interrupt + \arg ADC_INT_FLAG_EOIC: end of inserted group conversion interrupt + \param[out] none + \retval none +*/ +void adc_interrupt_flag_clear(uint32_t adc_periph, uint32_t adc_interrupt) +{ + ADC_STAT(adc_periph) &= ~((uint32_t)adc_interrupt); +} + +/*! + \brief enable ADC interrupt + \param[in] adc_periph: ADCx, x=0,1,2 + only one among these parameters can be selected + \param[in] adc_interrupt: the adc interrupt + one or more parameters can be selected which are shown as below: + \arg ADC_INT_WDE: analog watchdog interrupt flag + \arg ADC_INT_EOC: end of group conversion interrupt flag + \arg ADC_INT_EOIC: end of inserted group conversion interrupt flag + \param[out] none + \retval none +*/ +void adc_interrupt_enable(uint32_t adc_periph, uint32_t adc_interrupt) +{ + /* enable ADC analog watchdog interrupt */ + if(0U != (adc_interrupt & ADC_INT_WDE)){ + ADC_CTL0(adc_periph) |= (uint32_t) ADC_CTL0_WDEIE; + } + /* enable ADC end of group conversion interrupt */ + if(0U != (adc_interrupt & ADC_INT_EOC)){ + ADC_CTL0(adc_periph) |= (uint32_t) ADC_CTL0_EOCIE; + } + /* enable ADC end of inserted group conversion interrupt */ + if(0U != (adc_interrupt & ADC_INT_EOIC)){ + ADC_CTL0(adc_periph) |= (uint32_t) ADC_CTL0_EOICIE; + } +} + +/*! + \brief disable ADC interrupt + \param[in] adc_periph: ADCx,x=0,1,2 + only one among these parameters can be selected + \param[in] adc_interrupt: the adc interrupt flag + one or more parameters can be selected which are shown as below: + \arg ADC_INT_WDE: analog watchdog interrupt flag + \arg ADC_INT_EOC: end of group conversion interrupt flag + \arg ADC_INT_EOIC: end of inserted group conversion interrupt flag + \param[out] none + \retval none +*/ +void adc_interrupt_disable(uint32_t adc_periph, uint32_t adc_interrupt) +{ + /* disable ADC analog watchdog interrupt */ + if(0U != (adc_interrupt & ADC_INT_WDE)){ + ADC_CTL0(adc_periph) &= ~(uint32_t) ADC_CTL0_WDEIE; + } + /* disable ADC end of group conversion interrupt */ + if(0U != (adc_interrupt & ADC_INT_EOC)){ + ADC_CTL0(adc_periph) &= ~(uint32_t) ADC_CTL0_EOCIE; + } + /* disable ADC end of inserted group conversion interrupt */ + if(0U != (adc_interrupt & ADC_INT_EOIC)){ + ADC_CTL0(adc_periph) &= ~(uint32_t) ADC_CTL0_EOICIE; + } +} + + + +/*! + \brief configure ADC resolution + \param[in] adc_periph: ADCx,x=0,1,2 + only one among these parameters can be selected + \param[in] resolution: ADC resolution + only one among these parameters can be selected + \arg ADC_RESOLUTION_12B: 12-bit ADC resolution + \arg ADC_RESOLUTION_10B: 10-bit ADC resolution + \arg ADC_RESOLUTION_8B: 8-bit ADC resolution + \arg ADC_RESOLUTION_6B: 6-bit ADC resolution + \param[out] none + \retval none +*/ +void adc_resolution_config(uint32_t adc_periph, uint32_t resolution) +{ + ADC_OVSAMPCTL(adc_periph) &= ~((uint32_t)ADC_OVSAMPCTL_DRES); + ADC_OVSAMPCTL(adc_periph) |= (uint32_t)resolution; +} + +/*! + \brief configure ADC oversample mode + \param[in] adc_periph: ADCx, x=0,1,2 + only one among these parameters can be selected + \param[in] mode: ADC oversampling mode + only oneparameter can be selected + \arg ADC_OVERSAMPLING_ALL_CONVERT: all oversampled conversions for a channel are done consecutively after a trigger + \arg ADC_OVERSAMPLING_ONE_CONVERT: each oversampled conversion for a channel needs a trigger + \param[in] shift: ADC oversampling shift + only oneparameter can be selected + \arg ADC_OVERSAMPLING_SHIFT_NONE: no oversampling shift + \arg ADC_OVERSAMPLING_SHIFT_1B: 1-bit oversampling shift + \arg ADC_OVERSAMPLING_SHIFT_2B: 2-bit oversampling shift + \arg ADC_OVERSAMPLING_SHIFT_3B: 3-bit oversampling shift + \arg ADC_OVERSAMPLING_SHIFT_4B: 3-bit oversampling shift + \arg ADC_OVERSAMPLING_SHIFT_5B: 5-bit oversampling shift + \arg ADC_OVERSAMPLING_SHIFT_6B: 6-bit oversampling shift + \arg ADC_OVERSAMPLING_SHIFT_7B: 7-bit oversampling shift + \arg ADC_OVERSAMPLING_SHIFT_8B: 8-bit oversampling shift + \param[in] ratio: ADC oversampling ratio + only oneparameter can be selected + \arg ADC_OVERSAMPLING_RATIO_MUL2: oversampling ratio multiple 2 + \arg ADC_OVERSAMPLING_RATIO_MUL4: oversampling ratio multiple 4 + \arg ADC_OVERSAMPLING_RATIO_MUL8: oversampling ratio multiple 8 + \arg ADC_OVERSAMPLING_RATIO_MUL16: oversampling ratio multiple 16 + \arg ADC_OVERSAMPLING_RATIO_MUL32: oversampling ratio multiple 32 + \arg ADC_OVERSAMPLING_RATIO_MUL64: oversampling ratio multiple 64 + \arg ADC_OVERSAMPLING_RATIO_MUL128: oversampling ratio multiple 128 + \arg ADC_OVERSAMPLING_RATIO_MUL256: oversampling ratio multiple 256 + \param[out] none + \retval none +*/ +void adc_oversample_mode_config(uint32_t adc_periph, uint8_t mode, uint16_t shift, uint8_t ratio) +{ + /* configure ADC oversampling mode */ + if(ADC_OVERSAMPLING_ONE_CONVERT == mode){ + ADC_OVSAMPCTL(adc_periph) |= (uint32_t)ADC_OVSAMPCTL_TOVS; + }else{ + ADC_OVSAMPCTL(adc_periph) &= ~((uint32_t)ADC_OVSAMPCTL_TOVS); + } + + /* configure the shift and ratio */ + ADC_OVSAMPCTL(adc_periph) &= ~((uint32_t)(ADC_OVSAMPCTL_OVSR | ADC_OVSAMPCTL_OVSS)); + ADC_OVSAMPCTL(adc_periph) |= ((uint32_t)shift | (uint32_t)ratio); +} + +/*! + \brief enable ADC oversample mode + \param[in] adc_periph: ADCx,x=0,1,2 + only one among these parameters can be selected + \param[out] none + \retval none +*/ +void adc_oversample_mode_enable(uint32_t adc_periph) +{ + ADC_OVSAMPCTL(adc_periph) |= ADC_OVSAMPCTL_OVSEN; +} + +/*! + \brief disable ADC oversample mode + \param[in] adc_periph: ADCx,x=0,1,2 + only one among these parameters can be selected + \param[out] none + \retval none +*/ +void adc_oversample_mode_disable(uint32_t adc_periph) +{ + ADC_OVSAMPCTL(adc_periph) &= ~((uint32_t)ADC_OVSAMPCTL_OVSEN); +} diff --git a/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_standard_peripheral/Source/gd32f20x_bkp.c b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_standard_peripheral/Source/gd32f20x_bkp.c new file mode 100644 index 0000000000..26a5ab7892 --- /dev/null +++ b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_standard_peripheral/Source/gd32f20x_bkp.c @@ -0,0 +1,421 @@ +/*! + \file gd32f20x_bkp.c + \brief BKP driver + + \version 2015-07-15, V1.0.0, firmware for GD32F20x + \version 2017-06-05, V2.0.0, firmware for GD32F20x + \version 2018-10-31, V2.1.0, firmware for GD32F20x + \version 2020-09-30, V2.2.0, firmware for GD32F20x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "gd32f20x_bkp.h" + +#define TAMPER0_FLAG_SHIFT ((uint8_t)8U) +#define TAMPER1_FLAG_SHIFT ((uint8_t)9U) + +/*! + \brief reset BKP registers + \param[in] none + \param[out] none + \retval none +*/ +void bkp_deinit(void) +{ + /* reset BKP domain register*/ + rcu_bkp_reset_enable(); + rcu_bkp_reset_disable(); +} + +/*! + \brief write BKP data register + \param[in] register_number: refer to bkp_data_register_enum + only one parameter can be selected which is shown as below: + \arg BKP_DATA_x(x = 0..41): bkp data register number x + \param[in] data: the data to be write in BKP data register + \param[out] none + \retval none +*/ +void bkp_data_write(bkp_data_register_enum register_number, uint16_t data) +{ + if((register_number >= BKP_DATA_10) && (register_number <= BKP_DATA_41)){ + BKP_DATA10_41(register_number - 1U) = data; + }else if((register_number >= BKP_DATA_0) && (register_number <= BKP_DATA_9)){ + BKP_DATA0_9(register_number - 1U) = data; + }else{ + /* illegal parameters */ + } +} + +/*! + \brief read BKP data register + \param[in] register_number: refer to bkp_data_register_enum + only one parameter can be selected which is shown as below: + \arg BKP_DATA_x(x = 0..41): bkp data register number x + \param[out] none + \retval data of BKP data register +*/ +uint16_t bkp_data_read(bkp_data_register_enum register_number) +{ + uint16_t data = 0U; + + /* get the data from the BKP data register */ + if((register_number >= BKP_DATA_10) && (register_number <= BKP_DATA_41)){ + data = BKP_DATA10_41(register_number - 1U); + }else if((register_number >= BKP_DATA_0) && (register_number <= BKP_DATA_9)){ + data = BKP_DATA0_9(register_number - 1U); + }else{ + /* illegal parameters */ + } + return data; +} + +/*! + \brief enable RTC clock calibration output + \param[in] none + \param[out] none + \retval none +*/ +void bkp_rtc_calibration_output_enable(void) +{ + BKP_OCTL |= (uint16_t)BKP_OCTL_COEN; +} + +/*! + \brief disable RTC clock calibration output + \param[in] none + \param[out] none + \retval none +*/ +void bkp_rtc_calibration_output_disable(void) +{ + BKP_OCTL &= (uint16_t)~BKP_OCTL_COEN; +} + +/*! + \brief enable RTC alarm or second signal output + \param[in] none + \param[out] none + \retval none +*/ +void bkp_rtc_signal_output_enable(void) +{ + BKP_OCTL |= (uint16_t)BKP_OCTL_ASOEN; +} + +/*! + \brief disable RTC alarm or second signal output + \param[in] none + \param[out] none + \retval none +*/ +void bkp_rtc_signal_output_disable(void) +{ + BKP_OCTL &= (uint16_t)~BKP_OCTL_ASOEN; +} + +/*! + \brief select RTC output + \param[in] outputsel: RTC output selection + only one parameter can be selected which is shown as below: + \arg RTC_OUTPUT_ALARM_PULSE: RTC alarm pulse is selected as the RTC output + \arg RTC_OUTPUT_SECOND_PULSE: RTC second pulse is selected as the RTC output + \param[out] none + \retval none +*/ +void bkp_rtc_output_select(uint16_t outputsel) +{ + uint16_t ctl = 0U; + + ctl = BKP_OCTL; + ctl &= (uint16_t)~BKP_OCTL_ROSEL; + ctl |= outputsel; + BKP_OCTL = ctl; +} + +/*! + \brief select RTC clock output + \param[in] clocksel: RTC clock output selection + \arg RTC_CLOCK_DIV64: RTC clock div 64 + \arg RTC_CLOCK_DIV1: RTC clock + \param[out] none + \retval none +*/ +void bkp_rtc_clock_output_select(uint16_t clocksel) +{ + uint16_t ctl = 0U; + + ctl = BKP_OCTL; + ctl &= (uint16_t)~BKP_OCTL_CCOSEL; + ctl |= clocksel; + BKP_OCTL = ctl; +} + +/*! + \brief RTC clock calibration direction + \param[in] direction: RTC clock calibration direction + \arg RTC_CLOCK_SLOWED_DOWN: RTC clock slow down + \arg RTC_CLOCK_SPEED_UP: RTC clock speed up + \param[out] none + \retval none +*/ +void bkp_rtc_clock_calibration_direction(uint16_t direction) +{ + uint16_t ctl = 0U; + + ctl = BKP_OCTL; + ctl &= (uint16_t)~BKP_OCTL_CALDIR; + ctl |= direction; + BKP_OCTL = ctl; +} + +/*! + \brief set RTC clock calibration value + \param[in] value: RTC clock calibration value + \arg 0x00 - 0x7F + \param[out] none + \retval none +*/ +void bkp_rtc_calibration_value_set(uint8_t value) +{ + uint16_t ctl; + + /* configure BKP_OCTL_RCCV with value */ + ctl = BKP_OCTL; + ctl &= (uint16_t)OCTL_RCCV(0); + ctl |= (uint16_t)OCTL_RCCV(value); + BKP_OCTL = ctl; +} + +/*! + \brief enable tamper detection + \param[in] tamperx + \arg TAMPER_0: BKP tamper0 + \arg TAMPER_1: BKP tamper1 + \param[out] none + \retval none +*/ +void bkp_tamper_detection_enable(bkp_tamper_enum tamperx) +{ + if(TAMPER_0 == tamperx){ + BKP_TPCTL0 |= (uint16_t)BKP_TPCTL0_TPEN0; + }else{ + BKP_TPCTL1 |= (uint16_t)BKP_TPCTL1_TPEN1; + } +} + +/*! + \brief disable tamper detection + \param[in] tamperx + \arg TAMPER_0: BKP tamper0 + \arg TAMPER_1: BKP tamper1 + \param[out] none + \retval none +*/ +void bkp_tamper_detection_disable(bkp_tamper_enum tamperx) +{ + if(TAMPER_0 == tamperx){ + BKP_TPCTL0 &= (uint16_t)~BKP_TPCTL0_TPEN0; + }else{ + BKP_TPCTL1 &= (uint16_t)~BKP_TPCTL1_TPEN1; + } +} + +/*! + \brief set tamper pin active level + \param[in] tamperx + \arg TAMPER_0: BKP tamper0 + \arg TAMPER_1: BKP tamper1 + \param[in] level: tamper active level + \arg TAMPER_PIN_ACTIVE_HIGH: the tamper pin is active high + \arg TAMPER_PIN_ACTIVE_LOW: the tamper pin is active low + \param[out] none + \retval none +*/ +void bkp_tamper_active_level_set(bkp_tamper_enum tamperx, uint16_t level) +{ + uint16_t ctl = 0U; + + if(TAMPER_0 == tamperx){ + ctl = BKP_TPCTL0; + ctl &= (uint16_t)~BKP_TPCTL0_TPAL0; + ctl |= level; + BKP_TPCTL0 = ctl; + }else{ + ctl = BKP_TPCTL1; + ctl &= (uint16_t)~BKP_TPCTL1_TPAL1; + ctl |= level; + BKP_TPCTL1 = ctl; + } +} + +/*! + \brief enable tamper interrupt + \param[in] tamperx + \arg TAMPER_0: BKP tamper0 + \arg TAMPER_1: BKP tamper1 + \param[out] none + \retval none +*/ +void bkp_tamper_interrupt_enable(bkp_tamper_enum tamperx) +{ + if(TAMPER_0 == tamperx){ + BKP_TPCS |= (uint16_t)BKP_TPCS_TPIE0; + }else{ + BKP_TPCS |= (uint16_t)BKP_TPCS_TPIE1; + } +} + +/*! + \brief disable tamper interrupt + \param[in] tamperx + \arg TAMPER_0: BKP tamper0 + \arg TAMPER_1: BKP tamper1 + \param[out] none + \retval none +*/ +void bkp_tamper_interrupt_disable(bkp_tamper_enum tamperx) +{ + if(TAMPER_0 == tamperx){ + BKP_TPCS &= (uint16_t)~BKP_TPCS_TPIE0; + }else{ + BKP_TPCS &= (uint16_t)~BKP_TPCS_TPIE1; + } +} + +/*! + \brief waveform detect configure + \param[in] waveform_detect_mode + \arg BKP_WAVEFORM_DETECT_1: the first waveform detection + \arg BKP_WAVEFORM_DETECT_2: the second waveform detection + \param[in] newvalue: ENABLE or DISABLE + \param[out] none + \retval FlagStatus: SET or RESET +*/ +void bkp_waveform_detect_enable(uint16_t waveform_detect_mode, ControlStatus newvalue) +{ + uint16_t tpctl0 = 0U, tpctl1 = 0U, octl = 0U; + + tpctl0 = BKP_TPCTL0; + tpctl1 = BKP_TPCTL1; + + /* disable tamper0 and tamper1 */ + tpctl0 &= (uint16_t)~BKP_TPCTL0_TPEN0; + tpctl1 &= (uint16_t)~BKP_TPCTL1_TPEN1; + + octl = BKP_OCTL; + + /* RTC clock output divided 64 */ + octl &= (uint16_t)~BKP_OCTL_CCOSEL; + + /* set the value to the register */ + BKP_TPCTL0 = tpctl0; + BKP_TPCTL1 = tpctl1; + BKP_OCTL = octl; + + if(DISABLE != newvalue){ + /* enable the waveform detection function */ + BKP_TPCTL1 |= waveform_detect_mode; + }else{ + /* disable the waveform detection function */ + BKP_TPCTL1 &= (uint16_t)(~waveform_detect_mode); + } +} + +/*! + \brief get bkp flag state + \param[in] flag + \arg BKP_FLAG_TAMPER0: tamper0 event flag + \arg BKP_FLAG_TAMPER1_WAVEDETECT: tamper1/wavedetect event flag + \param[out] none + \retval FlagStatus: SET or RESET +*/ +FlagStatus bkp_flag_get(uint16_t flag) +{ + if(RESET != (BKP_TPCS & flag)){ + return SET; + }else{ + return RESET; + } +} + +/*! + \brief clear bkp flag state + \param[in] flag + \arg BKP_FLAG_TAMPER0: tamper0 event flag + \arg BKP_FLAG_TAMPER1_WAVEDETECT: tamper1/wavedetect event flag + \param[out] none + \retval none +*/ +void bkp_flag_clear(uint16_t flag) +{ + if(BKP_FLAG_TAMPER0 == flag){ + BKP_TPCS |= (uint16_t)(flag >> TAMPER0_FLAG_SHIFT); + }else if(BKP_FLAG_TAMPER1_WAVEDETECT == flag){ + BKP_TPCS |= (uint16_t)(flag >> TAMPER1_FLAG_SHIFT); + }else{ + /* illegal parameters */ + } +} + +/*! + \brief get bkp interrupt flag state + \param[in] flag + \arg BKP_INT_FLAG_TAMPER0: tamper0 interrupt flag + \arg BKP_INT_FLAG_TAMPER1_WAVEDETECT: tamper1/waveform detect interrupt flag + \param[out] none + \retval FlagStatus: SET or RESET +*/ +FlagStatus bkp_interrupt_flag_get(uint16_t flag) +{ + if(RESET != (BKP_TPCS & flag)){ + return SET; + }else{ + return RESET; + } +} + +/*! + \brief clear bkp interrupt flag state + \param[in] flag + \arg BKP_INT_FLAG_TAMPER0: tamper0 interrupt flag + \arg BKP_INT_FLAG_TAMPER1_WAVEDETECT: tamper1/waveform detect interrupt flag + \param[out] none + \retval none +*/ +void bkp_interrupt_flag_clear(uint16_t flag) +{ + if(BKP_INT_FLAG_TAMPER0 == flag){ + BKP_TPCS |= (uint16_t)(flag >> TAMPER0_FLAG_SHIFT); + }else if(BKP_INT_FLAG_TAMPER1_WAVEDETECT == flag){ + BKP_TPCS |= (uint16_t)(flag >> TAMPER1_FLAG_SHIFT); + }else{ + /* illegal parameters */ + } +} diff --git a/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_standard_peripheral/Source/gd32f20x_can.c b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_standard_peripheral/Source/gd32f20x_can.c new file mode 100644 index 0000000000..c9d321a6e5 --- /dev/null +++ b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_standard_peripheral/Source/gd32f20x_can.c @@ -0,0 +1,1035 @@ +/*! + \file gd32f20x_can.c + \brief CAN driver + + \version 2015-07-15, V1.0.0, firmware for GD32F20x + \version 2017-06-05, V2.0.0, firmware for GD32F20x + \version 2018-10-31, V2.1.0, firmware for GD32F20x + \version 2019-11-27, V2.1.1, firmware for GD32F20x + \version 2020-07-14, V2.1.2, firmware for GD32F20x + \version 2020-09-30, V2.2.0, firmware for GD32F20x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "gd32f20x_can.h" + +#define CAN_ERROR_HANDLE(s) do{}while(1) + +#define RFO1_CLEAR_VAL ((uint32_t)0x00000000U) /*!< RFO1 clear value */ +#define RFF1_CLEAR_VAL ((uint32_t)0x00000018U) /*!< RFF1 clear value */ + +/*! + \brief deinitialize CAN + \param[in] can_periph + \arg CANx(x=0,1) + \param[out] none + \retval none +*/ +void can_deinit(uint32_t can_periph) +{ + if(CAN0 == can_periph){ + rcu_periph_reset_enable(RCU_CAN0RST); + rcu_periph_reset_disable(RCU_CAN0RST); + }else{ + rcu_periph_reset_enable(RCU_CAN1RST); + rcu_periph_reset_disable(RCU_CAN1RST); + } +} + +/*! + \brief initialize CAN parameter struct with a default value + \param[in] type: the type of CAN parameter struct + only one parameter can be selected which is shown as below: + \arg CAN_INIT_STRUCT: the CAN initial struct + \arg CAN_FILTER_STRUCT: the CAN filter struct + \arg CAN_TX_MESSAGE_STRUCT: the CAN TX message struct + \arg CAN_RX_MESSAGE_STRUCT: the CAN RX message struct + \param[in] p_struct: the pointer of the specific struct + \param[out] none + \retval none +*/ +void can_struct_para_init(can_struct_type_enum type, void* p_struct) +{ + uint8_t i; + + /* get type of the struct */ + switch(type){ + /* used for can_init() */ + case CAN_INIT_STRUCT: + ((can_parameter_struct*)p_struct)->auto_bus_off_recovery = DISABLE; + ((can_parameter_struct*)p_struct)->no_auto_retrans = DISABLE; + ((can_parameter_struct*)p_struct)->auto_wake_up = DISABLE; + ((can_parameter_struct*)p_struct)->prescaler = 0x03FFU; + ((can_parameter_struct*)p_struct)->rec_fifo_overwrite = DISABLE; + ((can_parameter_struct*)p_struct)->resync_jump_width = CAN_BT_SJW_1TQ; + ((can_parameter_struct*)p_struct)->time_segment_1 = CAN_BT_BS1_3TQ; + ((can_parameter_struct*)p_struct)->time_segment_2 = CAN_BT_BS2_1TQ; + ((can_parameter_struct*)p_struct)->time_triggered = DISABLE; + ((can_parameter_struct*)p_struct)->trans_fifo_order = DISABLE; + ((can_parameter_struct*)p_struct)->working_mode = CAN_NORMAL_MODE; + + break; + /* used for can_filter_init() */ + case CAN_FILTER_STRUCT: + ((can_filter_parameter_struct*)p_struct)->filter_bits = CAN_FILTERBITS_32BIT; + ((can_filter_parameter_struct*)p_struct)->filter_enable = DISABLE; + ((can_filter_parameter_struct*)p_struct)->filter_fifo_number = CAN_FIFO0; + ((can_filter_parameter_struct*)p_struct)->filter_list_high = 0x0000U; + ((can_filter_parameter_struct*)p_struct)->filter_list_low = 0x0000U; + ((can_filter_parameter_struct*)p_struct)->filter_mask_high = 0x0000U; + ((can_filter_parameter_struct*)p_struct)->filter_mask_low = 0x0000U; + ((can_filter_parameter_struct*)p_struct)->filter_mode = CAN_FILTERMODE_MASK; + ((can_filter_parameter_struct*)p_struct)->filter_number = 0U; + + break; + /* used for can_message_transmit() */ + case CAN_TX_MESSAGE_STRUCT: + for(i = 0U; i < 8U; i++){ + ((can_trasnmit_message_struct*)p_struct)->tx_data[i] = 0U; + } + + ((can_trasnmit_message_struct*)p_struct)->tx_dlen = 0u; + ((can_trasnmit_message_struct*)p_struct)->tx_efid = 0U; + ((can_trasnmit_message_struct*)p_struct)->tx_ff = (uint8_t)CAN_FF_STANDARD; + ((can_trasnmit_message_struct*)p_struct)->tx_ft = (uint8_t)CAN_FT_DATA; + ((can_trasnmit_message_struct*)p_struct)->tx_sfid = 0U; + + break; + /* used for can_message_receive() */ + case CAN_RX_MESSAGE_STRUCT: + for(i = 0U; i < 8U; i++){ + ((can_receive_message_struct*)p_struct)->rx_data[i] = 0U; + } + + ((can_receive_message_struct*)p_struct)->rx_dlen = 0U; + ((can_receive_message_struct*)p_struct)->rx_efid = 0U; + ((can_receive_message_struct*)p_struct)->rx_ff = (uint8_t)CAN_FF_STANDARD; + ((can_receive_message_struct*)p_struct)->rx_fi = 0U; + ((can_receive_message_struct*)p_struct)->rx_ft = (uint8_t)CAN_FT_DATA; + ((can_receive_message_struct*)p_struct)->rx_sfid = 0U; + + break; + + default: + CAN_ERROR_HANDLE("parameter is invalid \r\n"); + } +} + +/*! + \brief initialize CAN + \param[in] can_periph + \arg CANx(x=0,1) + \param[in] can_parameter_init: parameters for CAN initializtion + \arg working_mode: CAN_NORMAL_MODE, CAN_LOOPBACK_MODE, CAN_SILENT_MODE, CAN_SILENT_LOOPBACK_MODE + \arg resync_jump_width: CAN_BT_SJW_xTQ(x=1, 2, 3, 4) + \arg time_segment_1: CAN_BT_BS1_xTQ(1..16) + \arg time_segment_2: CAN_BT_BS2_xTQ(1..8) + \arg time_triggered: ENABLE or DISABLE + \arg auto_bus_off_recovery: ENABLE or DISABLE + \arg auto_wake_up: ENABLE or DISABLE + \arg no_auto_retrans: ENABLE or DISABLE + \arg rec_fifo_overwrite: ENABLE or DISABLE + \arg trans_fifo_order: ENABLE or DISABLE + \arg prescaler: 0x0001 - 0x0400 + \param[out] none + \retval ErrStatus: SUCCESS or ERROR +*/ +ErrStatus can_init(uint32_t can_periph, can_parameter_struct* can_parameter_init) +{ + uint32_t timeout = CAN_TIMEOUT; + ErrStatus flag = ERROR; + + /* disable sleep mode */ + CAN_CTL(can_periph) &= ~CAN_CTL_SLPWMOD; + /* enable initialize mode */ + CAN_CTL(can_periph) |= CAN_CTL_IWMOD; + /* wait ACK */ + while((CAN_STAT_IWS != (CAN_STAT(can_periph) & CAN_STAT_IWS)) && (0U != timeout)){ + timeout--; + } + /* check initialize working success */ + if(CAN_STAT_IWS != (CAN_STAT(can_periph) & CAN_STAT_IWS)){ + flag = ERROR; + }else{ + /* set the bit timing register */ + CAN_BT(can_periph) = (BT_MODE((uint32_t)can_parameter_init->working_mode) | \ + BT_SJW((uint32_t)can_parameter_init->resync_jump_width) | \ + BT_BS1((uint32_t)can_parameter_init->time_segment_1) | \ + BT_BS2((uint32_t)can_parameter_init->time_segment_2) | \ + BT_BAUDPSC(((uint32_t)(can_parameter_init->prescaler) - 1U))); + /* time trigger communication mode */ + if(ENABLE == can_parameter_init->time_triggered){ + CAN_CTL(can_periph) |= CAN_CTL_TTC; + }else{ + CAN_CTL(can_periph) &= ~CAN_CTL_TTC; + } + /* automatic bus-off managment */ + if(ENABLE == can_parameter_init->auto_bus_off_recovery){ + CAN_CTL(can_periph) |= CAN_CTL_ABOR; + }else{ + CAN_CTL(can_periph) &= ~CAN_CTL_ABOR; + } + /* automatic wakeup mode */ + if(ENABLE == can_parameter_init->auto_wake_up){ + CAN_CTL(can_periph) |= CAN_CTL_AWU; + }else{ + CAN_CTL(can_periph) &= ~CAN_CTL_AWU; + } + /* automatic retransmission mode disable*/ + if(ENABLE == can_parameter_init->no_auto_retrans){ + CAN_CTL(can_periph) |= CAN_CTL_ARD; + }else{ + CAN_CTL(can_periph) &= ~CAN_CTL_ARD; + } + /* receive fifo overwrite mode */ + if(ENABLE == can_parameter_init->rec_fifo_overwrite){ + CAN_CTL(can_periph) |= CAN_CTL_RFOD; + }else{ + CAN_CTL(can_periph) &= ~CAN_CTL_RFOD; + } + /* transmit fifo order */ + if(ENABLE == can_parameter_init->trans_fifo_order){ + CAN_CTL(can_periph) |= CAN_CTL_TFO; + }else{ + CAN_CTL(can_periph) &= ~CAN_CTL_TFO; + } + /* disable initialize mode */ + CAN_CTL(can_periph) &= ~CAN_CTL_IWMOD; + timeout = CAN_TIMEOUT; + /* wait the ACK */ + while((CAN_STAT_IWS == (CAN_STAT(can_periph) & CAN_STAT_IWS)) && (0U != timeout)){ + timeout--; + } + /* check exit initialize mode */ + if(0U != timeout){ + flag = SUCCESS; + } + } + return flag; +} + +/*! + \brief initialize CAN filter + \param[in] can_filter_parameter_init: struct for CAN filter initialization + \arg filter_list_high: 0x0000 - 0xFFFF + \arg filter_list_low: 0x0000 - 0xFFFF + \arg filter_mask_high: 0x0000 - 0xFFFF + \arg filter_mask_low: 0x0000 - 0xFFFF + \arg filter_fifo_number: CAN_FIFO0, CAN_FIFO1 + \arg filter_number: 0 - 27 + \arg filter_mode: CAN_FILTERMODE_MASK, CAN_FILTERMODE_LIST + \arg filter_bits: CAN_FILTERBITS_32BIT, CAN_FILTERBITS_16BIT + \arg filter_enable: ENABLE or DISABLE + \param[out] none + \retval none +*/ +void can_filter_init(can_filter_parameter_struct* can_filter_parameter_init) +{ + uint32_t val = 0U; + + val = ((uint32_t)1) << (can_filter_parameter_init->filter_number); + /* filter lock disable */ + CAN_FCTL(CAN0) |= CAN_FCTL_FLD; + /* disable filter */ + CAN_FW(CAN0) &= ~(uint32_t)val; + + /* filter 16 bits */ + if(CAN_FILTERBITS_16BIT == can_filter_parameter_init->filter_bits){ + /* set filter 16 bits */ + CAN_FSCFG(CAN0) &= ~(uint32_t)val; + /* first 16 bits list and first 16 bits mask or first 16 bits list and second 16 bits list */ + CAN_FDATA0(CAN0, can_filter_parameter_init->filter_number) = \ + FDATA_MASK_HIGH((can_filter_parameter_init->filter_mask_low) & CAN_FILTER_MASK_16BITS) | \ + FDATA_MASK_LOW((can_filter_parameter_init->filter_list_low) & CAN_FILTER_MASK_16BITS); + /* second 16 bits list and second 16 bits mask or third 16 bits list and fourth 16 bits list */ + CAN_FDATA1(CAN0, can_filter_parameter_init->filter_number) = \ + FDATA_MASK_HIGH((can_filter_parameter_init->filter_mask_high) & CAN_FILTER_MASK_16BITS) | \ + FDATA_MASK_LOW((can_filter_parameter_init->filter_list_high) & CAN_FILTER_MASK_16BITS); + } + /* filter 32 bits */ + if(CAN_FILTERBITS_32BIT == can_filter_parameter_init->filter_bits){ + /* set filter 32 bits */ + CAN_FSCFG(CAN0) |= (uint32_t)val; + /* 32 bits list or first 32 bits list */ + CAN_FDATA0(CAN0, can_filter_parameter_init->filter_number) = \ + FDATA_MASK_HIGH((can_filter_parameter_init->filter_list_high) & CAN_FILTER_MASK_16BITS) | + FDATA_MASK_LOW((can_filter_parameter_init->filter_list_low) & CAN_FILTER_MASK_16BITS); + /* 32 bits mask or second 32 bits list */ + CAN_FDATA1(CAN0, can_filter_parameter_init->filter_number) = \ + FDATA_MASK_HIGH((can_filter_parameter_init->filter_mask_high) & CAN_FILTER_MASK_16BITS) | + FDATA_MASK_LOW((can_filter_parameter_init->filter_mask_low) & CAN_FILTER_MASK_16BITS); + } + + /* filter mode */ + if(CAN_FILTERMODE_MASK == can_filter_parameter_init->filter_mode){ + /* mask mode */ + CAN_FMCFG(CAN0) &= ~(uint32_t)val; + }else{ + /* list mode */ + CAN_FMCFG(CAN0) |= (uint32_t)val; + } + + /* filter FIFO */ + if(CAN_FIFO0 == (can_filter_parameter_init->filter_fifo_number)){ + /* FIFO0 */ + CAN_FAFIFO(CAN0) &= ~(uint32_t)val; + }else{ + /* FIFO1 */ + CAN_FAFIFO(CAN0) |= (uint32_t)val; + } + + /* filter working */ + if(ENABLE == can_filter_parameter_init->filter_enable){ + + CAN_FW(CAN0) |= (uint32_t)val; + } + + /* filter lock enable */ + CAN_FCTL(CAN0) &= ~CAN_FCTL_FLD; +} + +/*! + \brief set CAN1 fliter start bank number + \param[in] start_bank: CAN1 start bank number + only one parameter can be selected which is shown as below: + \arg (1..27) + \param[out] none + \retval none +*/ +void can1_filter_start_bank(uint8_t start_bank) +{ + /* filter lock disable */ + CAN_FCTL(CAN0) |= CAN_FCTL_FLD; + /* set CAN1 filter start number */ + CAN_FCTL(CAN0) &= ~(uint32_t)CAN_FCTL_HBC1F; + CAN_FCTL(CAN0) |= FCTL_HBC1F(start_bank); + /* filter lock enaable */ + CAN_FCTL(CAN0) &= ~CAN_FCTL_FLD; +} + +/*! + \brief enable CAN debug freeze + \param[in] can_periph + \arg CANx(x=0,1) + \param[out] none + \retval none +*/ +void can_debug_freeze_enable(uint32_t can_periph) +{ + /* set DFZ bit */ + CAN_CTL(can_periph) |= CAN_CTL_DFZ; + + if(CAN0 == can_periph){ + dbg_periph_enable(DBG_CAN0_HOLD); + }else{ + dbg_periph_enable(DBG_CAN1_HOLD); + } +} + +/*! + \brief disable CAN debug freeze + \param[in] can_periph + \arg CANx(x=0,1) + \param[out] none + \retval none +*/ +void can_debug_freeze_disable(uint32_t can_periph) +{ + /* set DFZ bit */ + CAN_CTL(can_periph) &= ~CAN_CTL_DFZ; + + if(CAN0 == can_periph){ + dbg_periph_disable(DBG_CAN0_HOLD); + }else{ + dbg_periph_disable(DBG_CAN1_HOLD); + } +} + +/*! + \brief enable CAN time trigger mode + \param[in] can_periph + \arg CANx(x=0,1) + \param[out] none + \retval none +*/ +void can_time_trigger_mode_enable(uint32_t can_periph) +{ + uint8_t mailbox_number; + + /* enable the tcc mode */ + CAN_CTL(can_periph) |= CAN_CTL_TTC; + /* enable time stamp */ + for(mailbox_number=0U; mailbox_number<3U; mailbox_number++){ + CAN_TMP(can_periph, mailbox_number) |= CAN_TMP_TSEN; + } +} + +/*! + \brief disable CAN time trigger mode + \param[in] can_periph + \arg CANx(x=0,1) + \param[out] none + \retval none +*/ +void can_time_trigger_mode_disable(uint32_t can_periph) +{ + uint8_t mailbox_number; + + /* disable the TCC mode */ + CAN_CTL(can_periph) &= ~CAN_CTL_TTC; + /* reset TSEN bits */ + for(mailbox_number=0U; mailbox_number<3U; mailbox_number++){ + CAN_TMP(can_periph, mailbox_number) &= ~CAN_TMP_TSEN; + } +} + +/*! + \brief transmit CAN message + \param[in] can_periph + \arg CANx(x=0,1) + \param[in] transmit_message: struct for CAN transmit message + \arg tx_sfid: 0x00000000 - 0x000007FF + \arg tx_efid: 0x00000000 - 0x1FFFFFFF + \arg tx_ff: CAN_FF_STANDARD, CAN_FF_EXTENDED + \arg tx_ft: CAN_FT_DATA, CAN_FT_REMOTE + \arg tx_dlen: 0 - 8 + \arg tx_data[]: 0x00 - 0xFF + \param[out] none + \retval mailbox_number +*/ +uint8_t can_message_transmit(uint32_t can_periph, can_trasnmit_message_struct* transmit_message) +{ + uint8_t mailbox_number = CAN_MAILBOX0; + + /* select one empty mailbox */ + if(CAN_TSTAT_TME0 == (CAN_TSTAT(can_periph)&CAN_TSTAT_TME0)){ + mailbox_number = CAN_MAILBOX0; + }else if(CAN_TSTAT_TME1 == (CAN_TSTAT(can_periph)&CAN_TSTAT_TME1)){ + mailbox_number = CAN_MAILBOX1; + }else if(CAN_TSTAT_TME2 == (CAN_TSTAT(can_periph)&CAN_TSTAT_TME2)){ + mailbox_number = CAN_MAILBOX2; + }else{ + mailbox_number = CAN_NOMAILBOX; + } + /* return no mailbox empty */ + if(CAN_NOMAILBOX == mailbox_number){ + return CAN_NOMAILBOX; + } + + CAN_TMI(can_periph, mailbox_number) &= CAN_TMI_TEN; + if(CAN_FF_STANDARD == transmit_message->tx_ff){ + /* set transmit mailbox standard identifier */ + CAN_TMI(can_periph, mailbox_number) |= (uint32_t)(TMI_SFID(transmit_message->tx_sfid) | \ + transmit_message->tx_ft); + }else{ + /* set transmit mailbox extended identifier */ + CAN_TMI(can_periph, mailbox_number) |= (uint32_t)(TMI_EFID(transmit_message->tx_efid) | \ + transmit_message->tx_ff | \ + transmit_message->tx_ft); + } + /* set the data length */ + CAN_TMP(can_periph, mailbox_number) &= ((uint32_t)~CAN_TMP_DLENC); + CAN_TMP(can_periph, mailbox_number) |= transmit_message->tx_dlen; + /* set the data */ + CAN_TMDATA0(can_periph, mailbox_number) = TMDATA0_DB3(transmit_message->tx_data[3]) | \ + TMDATA0_DB2(transmit_message->tx_data[2]) | \ + TMDATA0_DB1(transmit_message->tx_data[1]) | \ + TMDATA0_DB0(transmit_message->tx_data[0]); + CAN_TMDATA1(can_periph, mailbox_number) = TMDATA1_DB7(transmit_message->tx_data[7]) | \ + TMDATA1_DB6(transmit_message->tx_data[6]) | \ + TMDATA1_DB5(transmit_message->tx_data[5]) | \ + TMDATA1_DB4(transmit_message->tx_data[4]); + /* enable transmission */ + CAN_TMI(can_periph, mailbox_number) |= CAN_TMI_TEN; + + return mailbox_number; +} + +/*! + \brief get CAN transmit state + \param[in] can_periph + \arg CANx(x=0,1) + \param[in] mailbox_number + only one parameter can be selected which is shown as below: + \arg CAN_MAILBOX(x=0,1,2) + \param[out] none + \retval can_transmit_state_enum +*/ +can_transmit_state_enum can_transmit_states(uint32_t can_periph, uint8_t mailbox_number) +{ + can_transmit_state_enum state = CAN_TRANSMIT_FAILED; + uint32_t val = 0U; + + /* check selected mailbox state */ + switch(mailbox_number){ + /* mailbox0 */ + case CAN_MAILBOX0: + val = CAN_TSTAT(can_periph) & (CAN_TSTAT_MTF0 | CAN_TSTAT_MTFNERR0 | CAN_TSTAT_TME0); + break; + /* mailbox1 */ + case CAN_MAILBOX1: + val = CAN_TSTAT(can_periph) & (CAN_TSTAT_MTF1 | CAN_TSTAT_MTFNERR1 | CAN_TSTAT_TME1); + break; + /* mailbox2 */ + case CAN_MAILBOX2: + val = CAN_TSTAT(can_periph) & (CAN_TSTAT_MTF2 | CAN_TSTAT_MTFNERR2 | CAN_TSTAT_TME2); + break; + default: + val = CAN_TRANSMIT_FAILED; + break; + } + + switch(val){ + /* transmit pending */ + case (CAN_STATE_PENDING): + state = CAN_TRANSMIT_PENDING; + break; + /* mailbox0 transmit succeeded */ + case (CAN_TSTAT_MTF0 | CAN_TSTAT_MTFNERR0 | CAN_TSTAT_TME0): + state = CAN_TRANSMIT_OK; + break; + /* mailbox1 transmit succeeded */ + case (CAN_TSTAT_MTF1 | CAN_TSTAT_MTFNERR1 | CAN_TSTAT_TME1): + state = CAN_TRANSMIT_OK; + break; + /* mailbox2 transmit succeeded */ + case (CAN_TSTAT_MTF2 | CAN_TSTAT_MTFNERR2 | CAN_TSTAT_TME2): + state = CAN_TRANSMIT_OK; + break; + /* transmit failed */ + default: + state = CAN_TRANSMIT_FAILED; + break; + } + return state; +} + +/*! + \brief stop CAN transmission + \param[in] can_periph + \arg CANx(x=0,1) + \param[in] mailbox_number + only one parameter can be selected which is shown as below: + \arg CAN_MAILBOXx(x=0,1,2) + \param[out] none + \retval none +*/ +void can_transmission_stop(uint32_t can_periph, uint8_t mailbox_number) +{ + if(CAN_MAILBOX0 == mailbox_number){ + CAN_TSTAT(can_periph) |= CAN_TSTAT_MST0; + while(CAN_TSTAT_MST0 == (CAN_TSTAT(can_periph) & CAN_TSTAT_MST0)){ + } + }else if(CAN_MAILBOX1 == mailbox_number){ + CAN_TSTAT(can_periph) |= CAN_TSTAT_MST1; + while(CAN_TSTAT_MST1 == (CAN_TSTAT(can_periph) & CAN_TSTAT_MST1)){ + } + }else if(CAN_MAILBOX2 == mailbox_number){ + CAN_TSTAT(can_periph) |= CAN_TSTAT_MST2; + while(CAN_TSTAT_MST2 == (CAN_TSTAT(can_periph) & CAN_TSTAT_MST2)){ + } + }else{ + /* illegal parameters */ + } +} + +/*! + \brief CAN receive message + \param[in] can_periph + \arg CANx(x=0,1) + \param[in] fifo_number + \arg CAN_FIFOx(x=0,1) + \param[out] receive_message: struct for CAN receive message + \arg rx_sfid: 0x00000000 - 0x000007FF + \arg rx_efid: 0x00000000 - 0x1FFFFFFF + \arg rx_ff: CAN_FF_STANDARD, CAN_FF_EXTENDED + \arg rx_ft: CAN_FT_DATA, CAN_FT_REMOTE + \arg rx_dlen: 0 - 8 + \arg rx_data[]: 0x00 - 0xFF + \arg rx_fi: 0 - 27 + \retval none +*/ +void can_message_receive(uint32_t can_periph, uint8_t fifo_number, can_receive_message_struct* receive_message) +{ + /* get the frame format */ + receive_message->rx_ff = (uint8_t)(CAN_RFIFOMI_FF & CAN_RFIFOMI(can_periph, fifo_number)); + if(CAN_FF_STANDARD == receive_message->rx_ff){ + /* get standard identifier */ + receive_message -> rx_sfid = (uint32_t)(GET_RFIFOMI_SFID(CAN_RFIFOMI(can_periph, fifo_number))); + }else{ + /* get extended identifier */ + receive_message -> rx_efid = (uint32_t)(GET_RFIFOMI_EFID(CAN_RFIFOMI(can_periph, fifo_number))); + } + + /* get frame type */ + receive_message -> rx_ft = (uint8_t)(CAN_RFIFOMI_FT & CAN_RFIFOMI(can_periph, fifo_number)); + /* get recevie data length */ + receive_message -> rx_dlen = (uint8_t)(GET_RFIFOMP_DLENC(CAN_RFIFOMP(can_periph, fifo_number))); + /* filtering index */ + receive_message -> rx_fi = (uint8_t)(GET_RFIFOMP_FI(CAN_RFIFOMP(can_periph, fifo_number))); + + /* receive data */ + receive_message -> rx_data[0] = (uint8_t)(GET_RFIFOMDATA0_DB0(CAN_RFIFOMDATA0(can_periph, fifo_number))); + receive_message -> rx_data[1] = (uint8_t)(GET_RFIFOMDATA0_DB1(CAN_RFIFOMDATA0(can_periph, fifo_number))); + receive_message -> rx_data[2] = (uint8_t)(GET_RFIFOMDATA0_DB2(CAN_RFIFOMDATA0(can_periph, fifo_number))); + receive_message -> rx_data[3] = (uint8_t)(GET_RFIFOMDATA0_DB3(CAN_RFIFOMDATA0(can_periph, fifo_number))); + receive_message -> rx_data[4] = (uint8_t)(GET_RFIFOMDATA1_DB4(CAN_RFIFOMDATA1(can_periph, fifo_number))); + receive_message -> rx_data[5] = (uint8_t)(GET_RFIFOMDATA1_DB5(CAN_RFIFOMDATA1(can_periph, fifo_number))); + receive_message -> rx_data[6] = (uint8_t)(GET_RFIFOMDATA1_DB6(CAN_RFIFOMDATA1(can_periph, fifo_number))); + receive_message -> rx_data[7] = (uint8_t)(GET_RFIFOMDATA1_DB7(CAN_RFIFOMDATA1(can_periph, fifo_number))); + + /* release FIFO */ + if(CAN_FIFO0 == fifo_number){ + CAN_RFIFO0(can_periph) |= CAN_RFIFO0_RFD0; + }else{ + CAN_RFIFO1(can_periph) |= CAN_RFIFO1_RFD1; + } +} + +/*! + \brief release FIFO0 + \param[in] can_periph + \arg CANx(x=0,1) + \param[in] fifo_number + only one parameter can be selected which is shown as below: + \arg CAN_FIFOx(x=0,1) + \param[out] none + \retval none +*/ +void can_fifo_release(uint32_t can_periph, uint8_t fifo_number) +{ + if(CAN_FIFO0 == fifo_number){ + CAN_RFIFO0(can_periph) |= CAN_RFIFO0_RFD0; + }else if(CAN_FIFO1 == fifo_number){ + CAN_RFIFO1(can_periph) |= CAN_RFIFO1_RFD1; + }else{ + /* illegal parameters */ + CAN_ERROR_HANDLE("CAN FIFO NUM is invalid \r\n"); + } +} + +/*! + \brief CAN receive message length + \param[in] can_periph + \arg CANx(x=0,1) + \param[in] fifo_number + only one parameter can be selected which is shown as below: + \arg CAN_FIFOx(x=0,1) + \param[out] none + \retval message length +*/ +uint8_t can_receive_message_length_get(uint32_t can_periph, uint8_t fifo_number) +{ + uint8_t val = 0U; + + if(CAN_FIFO0 == fifo_number){ + /* FIFO0 */ + val = (uint8_t)(CAN_RFIFO0(can_periph) & CAN_RFIF_RFL_MASK); + }else if(CAN_FIFO1 == fifo_number){ + /* FIFO1 */ + val = (uint8_t)(CAN_RFIFO1(can_periph) & CAN_RFIF_RFL_MASK); + }else{ + /* illegal parameters */ + } + return val; +} + +/*! + \brief set CAN working mode + \param[in] can_periph + \arg CANx(x=0,1) + \param[in] can_working_mode + only one parameter can be selected which is shown as below: + \arg CAN_MODE_INITIALIZE + \arg CAN_MODE_NORMAL + \arg CAN_MODE_SLEEP + \param[out] none + \retval ErrStatus: SUCCESS or ERROR +*/ +ErrStatus can_working_mode_set(uint32_t can_periph, uint8_t working_mode) +{ + ErrStatus flag = ERROR; + /* timeout for IWS or also for SLPWS bits */ + uint32_t timeout = CAN_TIMEOUT; + + if(CAN_MODE_INITIALIZE == working_mode){ + /* disable sleep mode */ + CAN_CTL(can_periph) &= (~(uint32_t)CAN_CTL_SLPWMOD); + /* set initialize mode */ + CAN_CTL(can_periph) |= (uint8_t)CAN_CTL_IWMOD; + /* wait the acknowledge */ + while((CAN_STAT_IWS != (CAN_STAT(can_periph) & CAN_STAT_IWS)) && (0U != timeout)){ + timeout--; + } + if(CAN_STAT_IWS != (CAN_STAT(can_periph) & CAN_STAT_IWS)){ + flag = ERROR; + }else{ + flag = SUCCESS; + } + }else if(CAN_MODE_NORMAL == working_mode){ + /* enter normal mode */ + CAN_CTL(can_periph) &= ~(uint32_t)(CAN_CTL_SLPWMOD | CAN_CTL_IWMOD); + /* wait the acknowledge */ + while((0U != (CAN_STAT(can_periph) & (CAN_STAT_IWS | CAN_STAT_SLPWS))) && (0U != timeout)){ + timeout--; + } + if(0U != (CAN_STAT(can_periph) & (CAN_STAT_IWS | CAN_STAT_SLPWS))){ + flag = ERROR; + }else{ + flag = SUCCESS; + } + }else if(CAN_MODE_SLEEP == working_mode){ + /* disable initialize mode */ + CAN_CTL(can_periph) &= (~(uint32_t)CAN_CTL_IWMOD); + /* set sleep mode */ + CAN_CTL(can_periph) |= (uint8_t)CAN_CTL_SLPWMOD; + /* wait the acknowledge */ + while((CAN_STAT_SLPWS != (CAN_STAT(can_periph) & CAN_STAT_SLPWS)) && (0U != timeout)){ + timeout--; + } + if(CAN_STAT_SLPWS != (CAN_STAT(can_periph) & CAN_STAT_SLPWS)){ + flag = ERROR; + }else{ + flag = SUCCESS; + } + }else{ + flag = ERROR; + } + return flag; +} + +/*! + \brief wake up CAN + \param[in] can_periph + \arg CANx(x=0,1) + \param[out] none + \retval ErrStatus: SUCCESS or ERROR +*/ +ErrStatus can_wakeup(uint32_t can_periph) +{ + ErrStatus flag = ERROR; + uint32_t timeout = CAN_TIMEOUT; + + /* wakeup */ + CAN_CTL(can_periph) &= ~CAN_CTL_SLPWMOD; + + while((0U != (CAN_STAT(can_periph) & CAN_STAT_SLPWS)) && (0x00U != timeout)){ + timeout--; + } + /* check state */ + if(0U != (CAN_STAT(can_periph) & CAN_STAT_SLPWS)){ + flag = ERROR; + }else{ + flag = SUCCESS; + } + return flag; +} + +/*! + \brief get CAN error type + \param[in] can_periph + \arg CANx(x=0,1) + \param[out] none + \retval can_error_enum + \arg CAN_ERROR_NONE: no error + \arg CAN_ERROR_FILL: fill error + \arg CAN_ERROR_FORMATE: format error + \arg CAN_ERROR_ACK: ACK error + \arg CAN_ERROR_BITRECESSIVE: bit recessive + \arg CAN_ERROR_BITDOMINANTER: bit dominant error + \arg CAN_ERROR_CRC: CRC error + \arg CAN_ERROR_SOFTWARECFG: software configure +*/ +can_error_enum can_error_get(uint32_t can_periph) +{ + can_error_enum error; + error = CAN_ERROR_NONE; + + /* get error type */ + error = (can_error_enum)(GET_ERR_ERRN(CAN_ERR(can_periph))); + return error; +} + +/*! + \brief get CAN receive error number + \param[in] can_periph + \arg CANx(x=0,1) + \param[out] none + \retval error number +*/ +uint8_t can_receive_error_number_get(uint32_t can_periph) +{ + uint8_t val; + + /* get error count */ + val = (uint8_t)(GET_ERR_RECNT(CAN_ERR(can_periph))); + return val; +} + +/*! + \brief get CAN transmit error number + \param[in] can_periph + \arg CANx(x=0,1) + \param[out] none + \retval error number +*/ +uint8_t can_transmit_error_number_get(uint32_t can_periph) +{ + uint8_t val; + + val = (uint8_t)(GET_ERR_TECNT(CAN_ERR(can_periph))); + return val; +} + +/*! + \brief enable CAN interrupt + \param[in] can_periph + \arg CANx(x=0,1) + \param[in] interrupt + one or more parameters can be selected which are shown as below: + \arg CAN_INT_TME: transmit mailbox empty interrupt enable + \arg CAN_INT_RFNE0: receive FIFO0 not empty interrupt enable + \arg CAN_INT_RFF0: receive FIFO0 full interrupt enable + \arg CAN_INT_RFO0: receive FIFO0 overfull interrupt enable + \arg CAN_INT_RFNE1: receive FIFO1 not empty interrupt enable + \arg CAN_INT_RFF1: receive FIFO1 full interrupt enable + \arg CAN_INT_RFO1: receive FIFO1 overfull interrupt enable + \arg CAN_INT_WERR: warning error interrupt enable + \arg CAN_INT_PERR: passive error interrupt enable + \arg CAN_INT_BO: bus-off interrupt enable + \arg CAN_INT_ERRN: error number interrupt enable + \arg CAN_INT_ERR: error interrupt enable + \arg CAN_INT_WAKEUP: wakeup interrupt enable + \arg CAN_INT_SLPW: sleep working interrupt enable + \param[out] none + \retval none +*/ +void can_interrupt_enable(uint32_t can_periph, uint32_t interrupt) +{ + CAN_INTEN(can_periph) |= interrupt; +} + +/*! + \brief disable CAN interrupt + \param[in] can_periph + \arg CANx(x=0,1) + \param[in] interrupt + one or more parameters can be selected which are shown as below: + \arg CAN_INT_TME: transmit mailbox empty interrupt enable + \arg CAN_INT_RFNE0: receive FIFO0 not empty interrupt enable + \arg CAN_INT_RFF0: receive FIFO0 full interrupt enable + \arg CAN_INT_RFO0: receive FIFO0 overfull interrupt enable + \arg CAN_INT_RFNE1: receive FIFO1 not empty interrupt enable + \arg CAN_INT_RFF1: receive FIFO1 full interrupt enable + \arg CAN_INT_RFO1: receive FIFO1 overfull interrupt enable + \arg CAN_INT_WERR: warning error interrupt enable + \arg CAN_INT_PERR: passive error interrupt enable + \arg CAN_INT_BO: bus-off interrupt enable + \arg CAN_INT_ERRN: error number interrupt enable + \arg CAN_INT_ERR: error interrupt enable + \arg CAN_INT_WAKEUP: wakeup interrupt enable + \arg CAN_INT_SLPW: sleep working interrupt enable + \param[out] none + \retval none +*/ +void can_interrupt_disable(uint32_t can_periph, uint32_t interrupt) +{ + CAN_INTEN(can_periph) &= ~interrupt; +} + +/*! + \brief get CAN flag state + \param[in] can_periph + \arg CANx(x=0,1) + \param[in] flag: CAN flags, refer to can_flag_enum + only one parameter can be selected which is shown as below: + \arg CAN_FLAG_RXL: RX level + \arg CAN_FLAG_LASTRX: last sample value of RX pin + \arg CAN_FLAG_RS: receiving state + \arg CAN_FLAG_TS: transmitting state + \arg CAN_FLAG_SLPIF: status change flag of entering sleep working mode + \arg CAN_FLAG_WUIF: status change flag of wakeup from sleep working mode + \arg CAN_FLAG_ERRIF: error flag + \arg CAN_FLAG_SLPWS: sleep working state + \arg CAN_FLAG_IWS: initial working state + \arg CAN_FLAG_TMLS2: transmit mailbox 2 last sending in Tx FIFO + \arg CAN_FLAG_TMLS1: transmit mailbox 1 last sending in Tx FIFO + \arg CAN_FLAG_TMLS0: transmit mailbox 0 last sending in Tx FIFO + \arg CAN_FLAG_TME2: transmit mailbox 2 empty + \arg CAN_FLAG_TME1: transmit mailbox 1 empty + \arg CAN_FLAG_TME0: transmit mailbox 0 empty + \arg CAN_FLAG_MTE2: mailbox 2 transmit error + \arg CAN_FLAG_MTE1: mailbox 1 transmit error + \arg CAN_FLAG_MTE0: mailbox 0 transmit error + \arg CAN_FLAG_MAL2: mailbox 2 arbitration lost + \arg CAN_FLAG_MAL1: mailbox 1 arbitration lost + \arg CAN_FLAG_MAL0: mailbox 0 arbitration lost + \arg CAN_FLAG_MTFNERR2: mailbox 2 transmit finished with no error + \arg CAN_FLAG_MTFNERR1: mailbox 1 transmit finished with no error + \arg CAN_FLAG_MTFNERR0: mailbox 0 transmit finished with no error + \arg CAN_FLAG_MTF2: mailbox 2 transmit finished + \arg CAN_FLAG_MTF1: mailbox 1 transmit finished + \arg CAN_FLAG_MTF0: mailbox 0 transmit finished + \arg CAN_FLAG_RFO0: receive FIFO0 overfull + \arg CAN_FLAG_RFF0: receive FIFO0 full + \arg CAN_FLAG_RFO1: receive FIFO1 overfull + \arg CAN_FLAG_RFF1: receive FIFO1 full + \arg CAN_FLAG_BOERR: bus-off error + \arg CAN_FLAG_PERR: passive error + \arg CAN_FLAG_WERR: warning error + \param[out] none + \retval FlagStatus: SET or RESET +*/ +FlagStatus can_flag_get(uint32_t can_periph, can_flag_enum flag) +{ + /* get flag and interrupt enable state */ + if(RESET != (CAN_REG_VAL(can_periph, flag) & BIT(CAN_BIT_POS(flag)))){ + return SET; + }else{ + return RESET; + } +} + +/*! + \brief clear CAN flag state + \param[in] can_periph + \arg CANx(x=0,1) + \param[in] flag: CAN flags, refer to can_flag_enum + only one parameter can be selected which is shown as below: + \arg CAN_FLAG_SLPIF: status change flag of entering sleep working mode + \arg CAN_FLAG_WUIF: status change flag of wakeup from sleep working mode + \arg CAN_FLAG_ERRIF: error flag + \arg CAN_FLAG_MTE2: mailbox 2 transmit error + \arg CAN_FLAG_MTE1: mailbox 1 transmit error + \arg CAN_FLAG_MTE0: mailbox 0 transmit error + \arg CAN_FLAG_MAL2: mailbox 2 arbitration lost + \arg CAN_FLAG_MAL1: mailbox 1 arbitration lost + \arg CAN_FLAG_MAL0: mailbox 0 arbitration lost + \arg CAN_FLAG_MTFNERR2: mailbox 2 transmit finished with no error + \arg CAN_FLAG_MTFNERR1: mailbox 1 transmit finished with no error + \arg CAN_FLAG_MTFNERR0: mailbox 0 transmit finished with no error + \arg CAN_FLAG_MTF2: mailbox 2 transmit finished + \arg CAN_FLAG_MTF1: mailbox 1 transmit finished + \arg CAN_FLAG_MTF0: mailbox 0 transmit finished + \arg CAN_FLAG_RFO0: receive FIFO0 overfull + \arg CAN_FLAG_RFF0: receive FIFO0 full + \arg CAN_FLAG_RFO1: receive FIFO1 overfull + \arg CAN_FLAG_RFF1: receive FIFO1 full + \param[out] none + \retval none +*/ +void can_flag_clear(uint32_t can_periph, can_flag_enum flag) +{ + if (flag == CAN_FLAG_RFO1){ + CAN_REG_VAL(can_periph, flag) = RFO1_CLEAR_VAL; + } else if (flag == CAN_FLAG_RFF1){ + CAN_REG_VAL(can_periph, flag) = RFF1_CLEAR_VAL; + } else { + CAN_REG_VAL(can_periph, flag) = BIT(CAN_BIT_POS(flag)); + } +} + +/*! + \brief get CAN interrupt flag state + \param[in] can_periph + \arg CANx(x=0,1) + \param[in] flag: CAN interrupt flags, refer to can_interrupt_flag_enum + only one parameter can be selected which is shown as below: + \arg CAN_INT_FLAG_SLPIF: status change interrupt flag of sleep working mode entering + \arg CAN_INT_FLAG_WUIF: status change interrupt flag of wakeup from sleep working mode + \arg CAN_INT_FLAG_ERRIF: error interrupt flag + \arg CAN_INT_FLAG_MTF2: mailbox 2 transmit finished interrupt flag + \arg CAN_INT_FLAG_MTF1: mailbox 1 transmit finished interrupt flag + \arg CAN_INT_FLAG_MTF0: mailbox 0 transmit finished interrupt flag + \arg CAN_INT_FLAG_RFO0: receive FIFO0 overfull interrupt flag + \arg CAN_INT_FLAG_RFF0: receive FIFO0 full interrupt flag + \arg CAN_INT_FLAG_RFL0: receive FIFO0 not empty interrupt flag + \arg CAN_INT_FLAG_RFO1: receive FIFO1 overfull interrupt flag + \arg CAN_INT_FLAG_RFF1: receive FIFO1 full interrupt flag + \arg CAN_INT_FLAG_RFL1: receive FIFO1 not empty interrupt flag + \arg CAN_INT_FLAG_ERRN: error number interrupt flag + \arg CAN_INT_FLAG_BOERR: bus-off error interrupt flag + \arg CAN_INT_FLAG_PERR: passive error interrupt flag + \arg CAN_INT_FLAG_WERR: warning error interrupt flag + \param[out] none + \retval FlagStatus: SET or RESET +*/ +FlagStatus can_interrupt_flag_get(uint32_t can_periph, can_interrupt_flag_enum flag) +{ + uint32_t ret1 = RESET; + uint32_t ret2 = RESET; + + /* get the staus of interrupt flag */ + if (flag == CAN_INT_FLAG_RFL0) { + ret1 = can_receive_message_length_get(can_periph, CAN_FIFO0); + } else if (flag == CAN_INT_FLAG_RFL1) { + ret1 = can_receive_message_length_get(can_periph, CAN_FIFO1); + } else if (flag == CAN_INT_FLAG_ERRN) { + ret1 = can_error_get(can_periph); + } else { + ret1 = CAN_REG_VALS(can_periph, flag) & BIT(CAN_BIT_POS0(flag)); + } + /* get the staus of interrupt enale bit */ + ret2 = CAN_INTEN(can_periph) & BIT(CAN_BIT_POS1(flag)); + if(ret1 && ret2){ + return SET; + }else{ + return RESET; + } +} + +/*! + \brief clear CAN interrupt flag state + \param[in] can_periph + \arg CANx(x=0,1) + \param[in] flag: CAN interrupt flags, refer to can_interrupt_flag_enum + only one parameter can be selected which is shown as below: + \arg CAN_INT_FLAG_SLPIF: status change interrupt flag of sleep working mode entering + \arg CAN_INT_FLAG_WUIF: status change interrupt flag of wakeup from sleep working mode + \arg CAN_INT_FLAG_ERRIF: error interrupt flag + \arg CAN_INT_FLAG_MTF2: mailbox 2 transmit finished interrupt flag + \arg CAN_INT_FLAG_MTF1: mailbox 1 transmit finished interrupt flag + \arg CAN_INT_FLAG_MTF0: mailbox 0 transmit finished interrupt flag + \arg CAN_INT_FLAG_RFO0: receive FIFO0 overfull interrupt flag + \arg CAN_INT_FLAG_RFF0: receive FIFO0 full interrupt flag + \arg CAN_INT_FLAG_RFO1: receive FIFO1 overfull interrupt flag + \arg CAN_INT_FLAG_RFF1: receive FIFO1 full interrupt flag + \param[out] none + \retval none +*/ +void can_interrupt_flag_clear(uint32_t can_periph, can_interrupt_flag_enum flag) +{ + if (flag == CAN_INT_FLAG_RFO1){ + CAN_REG_VALS(can_periph, flag) = RFO1_CLEAR_VAL; + } else if (flag == CAN_INT_FLAG_RFF1){ + CAN_REG_VALS(can_periph, flag) = RFF1_CLEAR_VAL; + } else { + CAN_REG_VALS(can_periph, flag) = BIT(CAN_BIT_POS0(flag)); + } +} diff --git a/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_standard_peripheral/Source/gd32f20x_cau.c b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_standard_peripheral/Source/gd32f20x_cau.c new file mode 100644 index 0000000000..e985e0b5ff --- /dev/null +++ b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_standard_peripheral/Source/gd32f20x_cau.c @@ -0,0 +1,388 @@ +/*! + \file gd32f20x_cau.c + \brief CAU driver + + \version 2015-07-15, V1.0.0, firmware for GD32F20x + \version 2017-06-05, V2.0.0, firmware for GD32F20x + \version 2018-10-31, V2.1.0, firmware for GD32F20x + \version 2020-09-30, V2.2.0, firmware for GD32F20x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "gd32f20x_cau.h" +#include "gd32f20x_rcu.h" + +#define FLAG_MASK ((uint32_t)0x00000020U) + +/*! + \brief reset the CAU peripheral + \param[in] none + \param[out] none + \retval none +*/ +void cau_deinit(void) +{ + /* enable CAU reset state */ + rcu_periph_reset_enable(RCU_CAURST); + /* release CAU from reset state */ + rcu_periph_reset_disable(RCU_CAURST); +} + +/*! + \brief enable the CAU peripheral + \param[in] none + \param[out] none + \retval none +*/ +void cau_enable(void) +{ + /* enable the CAU processor */ + CAU_CTL |= CAU_CTL_CAUEN; +} + +/*! + \brief disable the CAU peripheral + \param[in] none + \param[out] none + \retval none +*/ +void cau_disable(void) +{ + /* disable the CAU processor */ + CAU_CTL &= ~CAU_CTL_CAUEN; +} + +/*! + \brief enable the CAU DMA interface + \param[in] dma_req: specify the CAU DMA transfer request to be enabled + one or more parameters can be selected which are shown as below + \arg CAU_DMA_INFIFO: DMA for incoming(Rx) data transfer + \arg CAU_DMA_OUTFIFO: DMA for outgoing(Tx) data transfer + \param[out] none + \retval none +*/ +void cau_dma_enable(uint32_t dma_req) +{ + /* enable the selected CAU DMA request */ + CAU_DMAEN |= dma_req; +} + +/*! + \brief disable the CAU DMA interface + \param[in] dma_req: specify the CAU DMA transfer request to be disabled + one or more parameters can be selected which are shown as below + \arg CAU_DMA_INFIFO: DMA for incoming(Rx) data transfer + \arg CAU_DMA_OUTFIFO: DMA for outgoing(Tx) data transfer + \param[out] none + \retval none +*/ +void cau_dma_disable(uint32_t dma_req) +{ + /* disable the selected CAU DMA request */ + CAU_DMAEN &= ~(dma_req); +} + +/*! + \brief initialize the CAU peripheral + \param[in] algo_dir: algorithm direction + only one parameter can be selected which is shown as below + \arg CAU_ENCRYPT: encrypt + \arg CAU_DECRYPT: decrypt + \param[in] algo_mode: algorithm mode selection + only one parameter can be selected which is shown as below + \arg CAU_MODE_TDES_ECB: TDES-ECB (3DES Electronic codebook) + \arg CAU_MODE_TDES_CBC: TDES-CBC (3DES Cipher block chaining) + \arg CAU_MODE_DES_ECB: DES-ECB (simple DES Electronic codebook) + \arg CAU_MODE_DES_CBC: DES-CBC (simple DES Cipher block chaining) + \arg CAU_MODE_AES_ECB: AES-ECB (AES Electronic codebook) + \arg CAU_MODE_AES_CBC: AES-CBC (AES Cipher block chaining) + \arg CAU_MODE_AES_CTR: AES-CTR (AES counter mode) + \arg CAU_MODE_AES_KEY: AES decryption key preparation mode + \param[in] swapping: data swapping selection + only one parameter can be selected which is shown as below + \arg CAU_SWAPPING_32BIT: no swapping + \arg CAU_SWAPPING_16BIT: half-word swapping + \arg CAU_SWAPPING_8BIT: bytes swapping + \arg CAU_SWAPPING_1BIT: bit swapping + \param[out] none + \retval none +*/ +void cau_init(uint32_t algo_dir, uint32_t algo_mode, uint32_t swapping) +{ + /* select algorithm mode */ + CAU_CTL &= ~CAU_CTL_ALGM; + CAU_CTL |= algo_mode; + + /* select data swapping */ + CAU_CTL &= ~CAU_CTL_DATAM; + CAU_CTL |= swapping; + + /* select algorithm direction */ + CAU_CTL &= ~CAU_CTL_CAUDIR; + CAU_CTL |= algo_dir; +} + +/*! + \brief configure key size if used AES algorithm + \param[in] key_size: key length selection when aes mode + only one parameter can be selected which is shown as below + \arg CAU_KEYSIZE_128BIT: 128 bit key length + \arg CAU_KEYSIZE_192BIT: 192 bit key length + \arg CAU_KEYSIZE_256BIT: 256 bit key length + \param[out] none + \retval none +*/ +void cau_aes_keysize_config(uint32_t key_size) +{ + CAU_CTL &= ~CAU_CTL_KEYM; + CAU_CTL |= key_size; +} + +/*! + \brief initialize the key parameters + \param[in] key_initpara: key init parameter struct + key_0_high: key 0 high + key_0_low: key 0 low + key_1_high: key 1 high + key_1_low: key 1 low + key_2_high: key 2 high + key_2_low: key 2 low + key_3_high: key 3 high + key_3_low: key 3 low + \param[out] none + \retval none +*/ +void cau_key_init(cau_key_parameter_struct* key_initpara) +{ + CAU_KEY0H = key_initpara->key_0_high; + CAU_KEY0L = key_initpara->key_0_low; + CAU_KEY1H = key_initpara->key_1_high; + CAU_KEY1L = key_initpara->key_1_low; + CAU_KEY2H = key_initpara->key_2_high; + CAU_KEY2L = key_initpara->key_2_low; + CAU_KEY3H = key_initpara->key_3_high; + CAU_KEY3L = key_initpara->key_3_low; +} + +/*! + \brief initialize the sturct cau_key_initpara + \param[in] key_initpara: key init parameter struct + key_0_high: key 0 high + key_0_low: key 0 low + key_1_high: key 1 high + key_1_low: key 1 low + key_2_high: key 2 high + key_2_low: key 2 low + key_3_high: key 3 high + key_3_low: key 3 low + \param[out] none + \retval none +*/ +void cau_key_parameter_init(cau_key_parameter_struct* key_initpara) +{ + key_initpara->key_0_high = 0U; + key_initpara->key_0_low = 0U; + key_initpara->key_1_high = 0U; + key_initpara->key_1_low = 0U; + key_initpara->key_2_high = 0U; + key_initpara->key_2_low = 0U; + key_initpara->key_3_high = 0U; + key_initpara->key_3_low = 0U; +} + +/*! + \brief initialize the vectors parameters + \param[in] iv_initpara: vectors init parameter struct + iv_0_high: init vector 0 high + iv_0_low: init vector 0 low + iv_1_high: init vector 1 high + iv_1_low: init vector 1 low + \param[out] none + \retval none +*/ +void cau_iv_init(cau_iv_parameter_struct* iv_initpara) +{ + CAU_IV0H = iv_initpara->iv_0_high; + CAU_IV0L = iv_initpara->iv_0_low; + CAU_IV1H = iv_initpara->iv_1_high; + CAU_IV1L = iv_initpara->iv_1_low; +} + +/*! + \brief initialize the vectors parameters + \param[in] iv_initpara: vectors init parameter struct + iv_0_high: init vector 0 high + iv_0_low: init vector 0 low + iv_1_high: init vector 1 high + iv_1_low: init vector 1 low + \param[out] none + \retval none +*/ +void cau_iv_parameter_init(cau_iv_parameter_struct* iv_initpara) +{ + iv_initpara->iv_0_high = 0U; + iv_initpara->iv_0_low = 0U; + iv_initpara->iv_1_high = 0U; + iv_initpara->iv_1_low = 0U; +} + +/*! + \brief flush the IN and OUT FIFOs + \param[in] none + \param[out] none + \retval none +*/ +void cau_fifo_flush(void) +{ + /* reset the read and write pointers of the FIFOs */ + CAU_CTL |= CAU_CTL_FFLUSH; +} + +/*! + \brief return whether CAU peripheral is enabled or disabled + \param[in] none + \param[out] none + \retval ControlStatus: ENABLE or DISABLE +*/ +ControlStatus cau_enable_state_get(void) +{ + ControlStatus ret = DISABLE; + if(RESET != (CAU_CTL & CAU_CTL_CAUEN)){ + ret = ENABLE; + } + return ret; +} + +/*! + \brief write data to the IN FIFO + \param[in] data: data to write + \param[out] none + \retval none +*/ +void cau_data_write(uint32_t data) +{ + CAU_DI = data; +} + +/*! + \brief return the last data entered into the output FIFO + \param[in] none + \param[out] none + \retval last data entered into the output FIFO +*/ +uint32_t cau_data_read(void) +{ + return CAU_DO; +} + +/*! + \brief get the CAU flag status + \param[in] flag: CAU flag status + only one parameter can be selected which is shown as below + \arg CAU_FLAG_INFIFO_EMPTY: input FIFO empty + \arg CAU_FLAG_INFIFO_NO_FULL: input FIFO is not full + \arg CAU_FLAG_OUTFIFO_NO_EMPTY: output FIFO not empty + \arg CAU_FLAG_OUTFIFO_FULL: output FIFO is full + \arg CAU_FLAG_BUSY: the CAU core is busy + \arg CAU_FLAG_INFIFO: input FIFO flag status + \arg CAU_FLAG_OUTFIFO: output FIFO flag status + \param[out] none + \retval FlagStatus: SET or RESET +*/ +FlagStatus cau_flag_get(uint32_t flag) +{ + uint32_t reg = 0U; + FlagStatus ret_flag = RESET; + + /* check if the flag is in CAU_STAT1 register */ + if(RESET != (flag & FLAG_MASK)){ + reg = CAU_STAT1; + }else{ + /* the flag is in CAU_STAT0 register */ + reg = CAU_STAT0; + } + + /* check the status of the specified CAU flag */ + if(RESET != (reg & flag)){ + ret_flag = SET; + } + + return ret_flag; +} + +/*! + \brief enable the CAU interrupts + \param[in] interrupt: specify the CAU interrupt source to be enabled + one or more parameters can be selected which are shown as below + \arg CAU_INT_INFIFO: input FIFO interrupt + \arg CAU_INT_OUTFIFO: output FIFO interrupt + \param[out] none + \retval none +*/ +void cau_interrupt_enable(uint32_t interrupt) +{ + /* enable the selected CAU interrupt */ + CAU_INTEN |= interrupt; +} + +/*! + \brief disable the CAU interrupts + \param[in] interrupt: specify the CAU interrupt source to be disabled + one or more parameters can be selected which are shown as below + \arg CAU_INT_INFIFO: input FIFO interrupt + \arg CAU_INT_OUTFIFO: output FIFO interrupt + \param[out] none + \retval none +*/ +void cau_interrupt_disable(uint32_t interrupt) +{ + /* disable the selected CAU interrupt */ + CAU_INTEN &= ~(interrupt); +} + +/*! + \brief get the interrupt flag + \param[in] int_flag: CAU interrupt flag + only one parameter can be selected which is shown as below + \arg CAU_INT_FLAG_INFIFO: input FIFO interrupt + \arg CAU_INT_FLAG_OUTFIFO: output FIFO interrupt + \param[out] none + \retval FlagStatus: SET or RESET +*/ +FlagStatus cau_interrupt_flag_get(uint32_t int_flag) +{ + FlagStatus flag = RESET; + + /* check the status of the specified CAU interrupt */ + if(RESET != (CAU_INTF & int_flag)){ + flag = SET; + } + + return flag; +} diff --git a/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_standard_peripheral/Source/gd32f20x_cau_aes.c b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_standard_peripheral/Source/gd32f20x_cau_aes.c new file mode 100644 index 0000000000..5b7429a54c --- /dev/null +++ b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_standard_peripheral/Source/gd32f20x_cau_aes.c @@ -0,0 +1,372 @@ +/*! + \file gd32f20x_cau_aes.c + \brief CAU_AES driver + + \version 2015-07-15, V1.0.0, firmware for GD32F20x + \version 2017-06-05, V2.0.0, firmware for GD32F20x + \version 2018-10-31, V2.1.0, firmware for GD32F20x + \version 2020-09-30, V2.2.0, firmware for GD32F20x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "gd32f20x_cau.h" + +#define AESBSY_TIMEOUT ((uint32_t)0x00010000U) + +/* AES key structure parameter config */ +static void cau_aes_key_config(uint8_t *key, uint16_t keysize, cau_key_parameter_struct* cau_key_initpara); +/* AES calculate process */ +static ErrStatus cau_aes_calculate(uint8_t *input, uint32_t in_length, uint8_t *output); + +/*! + \brief encrypt and decrypt using AES in ECB mode + \param[in] algo_dir: algorithm direction + only one parameter can be selected which is shown as below + \arg CAU_ENCRYPT: encrypt + \arg CAU_DECRYPT: decrypt + \param[in] key: key used for AES algorithm + \param[in] keysize: length of the key, must be a 128, 192 or 256 + \param[in] text: pointer to the text information struct + input: pointer to the input buffer + in_length: length of the input buffer, must be a multiple of 16 + output: pointer to the returned buffer + \param[out] none + \retval ErrStatus: SUCCESS or ERROR +*/ +ErrStatus cau_aes_ecb(uint32_t algo_dir, uint8_t *key, uint16_t keysize, cau_text_struct *text) +{ + ErrStatus ret = ERROR; + cau_key_parameter_struct key_initpara; + __IO uint32_t counter = 0U; + uint32_t busystatus = 0U; + + /* key structure initialization */ + cau_key_parameter_init(&key_initpara); + /* AES key structure parameter config */ + cau_aes_key_config(key, keysize, &key_initpara); + /* key initialization */ + cau_key_init(&key_initpara); + + /* AES decryption */ + if(CAU_DECRYPT == algo_dir){ + /* flush the IN and OUT FIFOs */ + cau_fifo_flush(); + /* initialize the CAU peripheral */ + cau_init(CAU_DECRYPT, CAU_MODE_AES_KEY, CAU_SWAPPING_32BIT); + + /* enable the CAU peripheral */ + cau_enable(); + + /* wait until the busy flag is RESET */ + do{ + busystatus = cau_flag_get(CAU_FLAG_BUSY); + counter++; + }while((AESBSY_TIMEOUT != counter) && (RESET != busystatus)); + + if(RESET != busystatus){ + return ERROR; + } + } + + /* initialize the CAU peripheral */ + cau_init(algo_dir, CAU_MODE_AES_ECB, CAU_SWAPPING_8BIT); + + /* flush the IN and OUT FIFOs */ + cau_fifo_flush(); + + /* enable the CAU peripheral */ + cau_enable(); + /* AES calculate process */ + ret = cau_aes_calculate(text->input, text->in_length, text->output); + /* disable the CAU peripheral */ + cau_disable(); + + return ret; +} + +/*! + \brief encrypt and decrypt using AES in CBC mode + \param[in] algo_dir: algorithm direction + only one parameter can be selected which is shown as below + \arg CAU_ENCRYPT: encrypt + \arg CAU_DECRYPT: decrypt + \param[in] key: key used for AES algorithm + \param[in] keysize: length of the key, must be a 128, 192 or 256 + \param[in] iv: initialization vectors used for TDES algorithm + \param[in] text: pointer to the text information struct + input: pointer to the input buffer + in_length: length of the input buffer, must be a multiple of 16 + output: pointer to the returned buffer + \param[out] none + \retval ErrStatus: SUCCESS or ERROR +*/ +ErrStatus cau_aes_cbc(uint32_t algo_dir, uint8_t *key, uint16_t keysize, uint8_t iv[16], cau_text_struct *text) +{ + ErrStatus ret = ERROR; + cau_key_parameter_struct key_initpara; + cau_iv_parameter_struct iv_initpara; + __IO uint32_t counter = 0U; + uint32_t busystatus = 0U; + + uint32_t ivaddr = (uint32_t)iv; + + /* key structure initialization */ + cau_key_parameter_init(&key_initpara); + /* AES key structure parameter config */ + cau_aes_key_config(key, keysize, &key_initpara); + /* key initialization */ + cau_key_init(&key_initpara); + + /* AES decryption */ + if(CAU_DECRYPT == algo_dir){ + /* flush the IN and OUT FIFOs */ + cau_fifo_flush(); + /* initialize the CAU peripheral */ + cau_init(CAU_DECRYPT, CAU_MODE_AES_KEY, CAU_SWAPPING_32BIT); + + /* enable the CAU peripheral */ + cau_enable(); + + /* wait until the busy flag is RESET */ + do{ + busystatus = cau_flag_get(CAU_FLAG_BUSY); + counter++; + }while((AESBSY_TIMEOUT != counter) && (RESET != busystatus)); + + if(RESET != busystatus){ + return ERROR; + } + } + + /* initialize the CAU peripheral */ + cau_init(algo_dir, CAU_MODE_AES_CBC, CAU_SWAPPING_8BIT); + + /* vectors initialization */ + iv_initpara.iv_0_high = __REV(*(uint32_t*)(ivaddr)); + ivaddr += 4U; + iv_initpara.iv_0_low = __REV(*(uint32_t*)(ivaddr)); + ivaddr += 4U; + iv_initpara.iv_1_high = __REV(*(uint32_t*)(ivaddr)); + ivaddr += 4U; + iv_initpara.iv_1_low = __REV(*(uint32_t*)(ivaddr)); + cau_iv_init(&iv_initpara); + + /* flush the IN and OUT FIFOs */ + cau_fifo_flush(); + + /* enable the CAU peripheral */ + cau_enable(); + /* AES calculate process */ + ret = cau_aes_calculate(text->input, text->in_length, text->output); + /* disable the CAU peripheral */ + cau_disable(); + + return ret; +} + +/*! + \brief encrypt and decrypt using AES in CTR mode + \param[in] algo_dir: algorithm direction + only one parameter can be selected which is shown as below + \arg CAU_ENCRYPT: encrypt + \arg CAU_DECRYPT: decrypt + \param[in] key: key used for AES algorithm + \param[in] keysize: length of the key, must be a 128, 192 or 256 + \param[in] iv: initialization vectors used for TDES algorithm + \param[in] text: pointer to the text information struct + input: pointer to the input buffer + in_length: length of the input buffer, must be a multiple of 16 + output: pointer to the returned buffer + \param[out] none + \retval ErrStatus: SUCCESS or ERROR +*/ +ErrStatus cau_aes_ctr(uint32_t algo_dir, uint8_t *key, uint16_t keysize, uint8_t iv[16], cau_text_struct *text) +{ + ErrStatus ret = ERROR; + cau_key_parameter_struct key_initpara; + cau_iv_parameter_struct iv_initpara; + + uint32_t ivaddr = (uint32_t)iv; + + /* key structure initialization */ + cau_key_parameter_init(&key_initpara); + /* initialize the CAU peripheral */ + cau_init(algo_dir, CAU_MODE_AES_CTR, CAU_SWAPPING_8BIT); + + /* AES key structure parameter config */ + cau_aes_key_config(key, keysize, &key_initpara); + /* key initialization */ + cau_key_init(&key_initpara); + + /* vectors initialization */ + iv_initpara.iv_0_high = __REV(*(uint32_t*)(ivaddr)); + ivaddr += 4U; + iv_initpara.iv_0_low = __REV(*(uint32_t*)(ivaddr)); + ivaddr += 4U; + iv_initpara.iv_1_high = __REV(*(uint32_t*)(ivaddr)); + ivaddr += 4U; + iv_initpara.iv_1_low = __REV(*(uint32_t*)(ivaddr)); + cau_iv_init(&iv_initpara); + + /* flush the IN and OUT FIFOs */ + cau_fifo_flush(); + + /* enable the CAU peripheral */ + cau_enable(); + /* AES calculate process */ + ret = cau_aes_calculate(text->input, text->in_length, text->output); + /* disable the CAU peripheral */ + cau_disable(); + + return ret; +} + +/*! + \brief AES key structure parameter config + \param[in] key: key used for AES algorithm + \param[in] keysize: length of the key, must be a 128, 192 or 256 + \param[out] cau_key_initpara: key init parameter struct + key_0_high: key 0 high + key_0_low: key 0 low + key_1_high: key 1 high + key_1_low: key 1 low + key_2_high: key 2 high + key_2_low: key 2 low + key_3_high: key 3 high + key_3_low: key 3 low + \retval none +*/ +static void cau_aes_key_config(uint8_t *key, uint16_t keysize, cau_key_parameter_struct* cau_key_initpara) +{ + uint32_t keyaddr = (uint32_t)key; + + switch(keysize){ + case 128: + cau_aes_keysize_config(CAU_KEYSIZE_128BIT); + cau_key_initpara->key_2_high = __REV(*(uint32_t*)(keyaddr)); + keyaddr += 4U; + cau_key_initpara->key_2_low = __REV(*(uint32_t*)(keyaddr)); + keyaddr += 4U; + cau_key_initpara->key_3_high = __REV(*(uint32_t*)(keyaddr)); + keyaddr += 4U; + cau_key_initpara->key_3_low = __REV(*(uint32_t*)(keyaddr)); + break; + case 192: + cau_aes_keysize_config(CAU_KEYSIZE_192BIT); + cau_key_initpara->key_1_high = __REV(*(uint32_t*)(keyaddr)); + keyaddr += 4U; + cau_key_initpara->key_1_low = __REV(*(uint32_t*)(keyaddr)); + keyaddr += 4U; + cau_key_initpara->key_2_high = __REV(*(uint32_t*)(keyaddr)); + keyaddr += 4U; + cau_key_initpara->key_2_low = __REV(*(uint32_t*)(keyaddr)); + keyaddr += 4U; + cau_key_initpara->key_3_high = __REV(*(uint32_t*)(keyaddr)); + keyaddr += 4U; + cau_key_initpara->key_3_low = __REV(*(uint32_t*)(keyaddr)); + break; + case 256: + cau_aes_keysize_config(CAU_KEYSIZE_256BIT); + cau_key_initpara->key_0_high = __REV(*(uint32_t*)(keyaddr)); + keyaddr += 4U; + cau_key_initpara->key_0_low = __REV(*(uint32_t*)(keyaddr)); + keyaddr += 4U; + cau_key_initpara->key_1_high = __REV(*(uint32_t*)(keyaddr)); + keyaddr += 4U; + cau_key_initpara->key_1_low = __REV(*(uint32_t*)(keyaddr)); + keyaddr += 4U; + cau_key_initpara->key_2_high = __REV(*(uint32_t*)(keyaddr)); + keyaddr += 4U; + cau_key_initpara->key_2_low = __REV(*(uint32_t*)(keyaddr)); + keyaddr += 4U; + cau_key_initpara->key_3_high = __REV(*(uint32_t*)(keyaddr)); + keyaddr += 4U; + cau_key_initpara->key_3_low = __REV(*(uint32_t*)(keyaddr)); + break; + default: + break; + } +} + +/*! + \brief AES calculate process + \param[in] input: pointer to the input buffer + \param[in] in_length: length of the input buffer, must be a multiple of 16 + \param[in] output: pointer to the returned buffer + \param[out] none + \retval ErrStatus: SUCCESS or ERROR +*/ +static ErrStatus cau_aes_calculate(uint8_t *input, uint32_t in_length, uint8_t *output) +{ + uint32_t inputaddr = (uint32_t)input; + uint32_t outputaddr = (uint32_t)output; + uint32_t i = 0U; + __IO uint32_t counter = 0U; + uint32_t busystatus = 0U; + + /* the clock is not enabled or there is no embeded CAU peripheral */ + if(DISABLE == cau_enable_state_get()){ + return ERROR; + } + + for(i = 0U; i < in_length; i += 16U){ + /* write data to the IN FIFO */ + cau_data_write(*(uint32_t*)(inputaddr)); + inputaddr += 4U; + cau_data_write(*(uint32_t*)(inputaddr)); + inputaddr += 4U; + cau_data_write(*(uint32_t*)(inputaddr)); + inputaddr += 4U; + cau_data_write(*(uint32_t*)(inputaddr)); + inputaddr += 4U; + + /* wait until the complete message has been processed */ + counter = 0U; + do{ + busystatus = cau_flag_get(CAU_FLAG_BUSY); + counter++; + }while((AESBSY_TIMEOUT != counter) && (RESET != busystatus)); + + if(RESET != busystatus){ + return ERROR; + }else{ + /* read the output block from the output FIFO */ + *(uint32_t*)(outputaddr) = cau_data_read(); + outputaddr += 4U; + *(uint32_t*)(outputaddr) = cau_data_read(); + outputaddr += 4U; + *(uint32_t*)(outputaddr) = cau_data_read(); + outputaddr += 4U; + *(uint32_t*)(outputaddr) = cau_data_read(); + outputaddr += 4U; + } + } + + return SUCCESS; +} diff --git a/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_standard_peripheral/Source/gd32f20x_cau_des.c b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_standard_peripheral/Source/gd32f20x_cau_des.c new file mode 100644 index 0000000000..90cc93cd42 --- /dev/null +++ b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_standard_peripheral/Source/gd32f20x_cau_des.c @@ -0,0 +1,191 @@ +/*! + \file gd32f20x_cau_des.c + \brief CAU_DES driver + + \version 2015-07-15, V1.0.0, firmware for GD32F20x + \version 2017-06-05, V2.0.0, firmware for GD32F20x + \version 2018-10-31, V2.1.0, firmware for GD32F20x + \version 2020-09-30, V2.2.0, firmware for GD32F20x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "gd32f20x_cau.h" + +#define DESBUSY_TIMEOUT ((uint32_t)0x00010000U) + +/* DES calculate process */ +static ErrStatus cau_des_calculate(uint8_t *input, uint32_t in_length, uint8_t *output); + +/*! + \brief encrypt and decrypt using DES in ECB mode + \param[in] algo_dir: algorithm direction + only one parameter can be selected which is shown as below + \arg CAU_ENCRYPT: encrypt + \arg CAU_DECRYPT: decrypt + \param[in] key: key used for DES algorithm + \param[in] text: pointer to the text information struct + input: pointer to the input buffer + in_length: length of the input buffer, must be a multiple of 8 + output: pointer to the returned buffer + \param[out] none + \retval ErrStatus: SUCCESS or ERROR +*/ +ErrStatus cau_des_ecb(uint32_t algo_dir, uint8_t key[24], cau_text_struct *text) +{ + ErrStatus ret = ERROR; + cau_key_parameter_struct key_initpara; + + uint32_t keyaddr = (uint32_t)key; + + /* key structure initialization */ + cau_key_parameter_init(&key_initpara); + /* initialize the CAU peripheral */ + cau_init(algo_dir, CAU_MODE_DES_ECB, CAU_SWAPPING_8BIT); + + /* key initialisation */ + key_initpara.key_1_high = __REV(*(uint32_t*)(keyaddr)); + keyaddr += 4U; + key_initpara.key_1_low= __REV(*(uint32_t*)(keyaddr)); + cau_key_init(& key_initpara); + + /* flush the IN and OUT FIFOs */ + cau_fifo_flush(); + + /* enable the CAU peripheral */ + cau_enable(); + /* DES calculate process */ + ret = cau_des_calculate(text->input, text->in_length, text->output); + /* disable the CAU peripheral */ + cau_disable(); + + return ret; +} + +/*! + \brief encrypt and decrypt using DES in CBC mode + \param[in] algo_dir: algorithm direction + only one parameter can be selected which is shown as below + \arg CAU_ENCRYPT: encrypt + \arg CAU_DECRYPT: decrypt + \param[in] key: key used for DES algorithm + \param[in] iv: initialization vectors used for TDES algorithm + \param[in] text: pointer to the text information struct + input: pointer to the input buffer + in_length: length of the input buffer, must be a multiple of 8 + output: pointer to the returned buffer + \param[out] none + \retval ErrStatus: SUCCESS or ERROR +*/ +ErrStatus cau_des_cbc(uint32_t algo_dir, uint8_t key[24], uint8_t iv[8], cau_text_struct *text) +{ + ErrStatus ret = ERROR; + cau_key_parameter_struct key_initpara; + cau_iv_parameter_struct iv_initpara; + + uint32_t keyaddr = (uint32_t)key; + uint32_t ivaddr = (uint32_t)iv; + + /* key structure initialization */ + cau_key_parameter_init(&key_initpara); + /* initialize the CAU peripheral */ + cau_init(algo_dir, CAU_MODE_DES_CBC, CAU_SWAPPING_8BIT); + + /* key initialisation */ + key_initpara.key_1_high = __REV(*(uint32_t*)(keyaddr)); + keyaddr += 4U; + key_initpara.key_1_low= __REV(*(uint32_t*)(keyaddr)); + cau_key_init(&key_initpara); + + /* vectors initialization */ + iv_initpara.iv_0_high = __REV(*(uint32_t*)(ivaddr)); + ivaddr += 4U; + iv_initpara.iv_0_low= __REV(*(uint32_t*)(ivaddr)); + cau_iv_init(&iv_initpara); + + /* flush the IN and OUT FIFOs */ + cau_fifo_flush(); + + /* enable the CAU peripheral */ + cau_enable(); + /* DES calculate process */ + ret = cau_des_calculate(text->input, text->in_length, text->output); + /* disable the CAU peripheral */ + cau_disable(); + + return ret; +} + +/*! + \brief DES calculate process + \param[in] input: pointer to the input buffer + \param[in] in_length: length of the input buffer, must be a multiple of 8 + \param[in] output: pointer to the returned buffer + \param[out] none + \retval ErrStatus: SUCCESS or ERROR +*/ +static ErrStatus cau_des_calculate(uint8_t *input, uint32_t in_length, uint8_t *output) +{ + uint32_t inputaddr = (uint32_t)input; + uint32_t outputaddr = (uint32_t)output; + uint32_t i = 0U; + __IO uint32_t counter = 0U; + uint32_t busystatus = 0U; + + /* the clock is not enabled or there is no embeded CAU peripheral */ + if(DISABLE == cau_enable_state_get()){ + return ERROR; + } + + for(i = 0U; i < in_length; i += 8U){ + /* write data to the IN FIFO */ + cau_data_write(*(uint32_t*)(inputaddr)); + inputaddr += 4U; + cau_data_write(*(uint32_t*)(inputaddr)); + inputaddr += 4U; + + /* wait until the complete message has been processed */ + counter = 0U; + do{ + busystatus = cau_flag_get(CAU_FLAG_BUSY); + counter++; + }while((DESBUSY_TIMEOUT != counter) && (RESET != busystatus)); + + if(RESET != busystatus){ + return ERROR; + }else{ + /* read the output block from the output FIFO */ + *(uint32_t*)(outputaddr) = cau_data_read(); + outputaddr += 4U; + *(uint32_t*)(outputaddr) = cau_data_read(); + outputaddr += 4U; + } + } + + return SUCCESS; +} diff --git a/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_standard_peripheral/Source/gd32f20x_cau_tdes.c b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_standard_peripheral/Source/gd32f20x_cau_tdes.c new file mode 100644 index 0000000000..07af6c81df --- /dev/null +++ b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_standard_peripheral/Source/gd32f20x_cau_tdes.c @@ -0,0 +1,207 @@ +/*! + \file gd32f20x_cau_tdes.c + \brief CAU_TDES driver + + \version 2015-07-15, V1.0.0, firmware for GD32F20x + \version 2017-06-05, V2.0.0, firmware for GD32F20x + \version 2018-10-31, V2.1.0, firmware for GD32F20x + \version 2020-09-30, V2.2.0, firmware for GD32F20x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "gd32f20x_cau.h" + +#define TDESBSY_TIMEOUT ((uint32_t)0x00010000U) + +/* TDES calculate process */ +static ErrStatus cau_tdes_calculate(uint8_t *input, uint32_t in_length, uint8_t *output); + +/*! + \brief encrypt and decrypt using TDES in ECB mode + \param[in] algo_dir: algorithm direction + only one parameter can be selected which is shown as below + \arg CAU_ENCRYPT: encrypt + \arg CAU_DECRYPT: decrypt + \param[in] key: key used for TDES algorithm + \param[in] text: pointer to the text information struct + input: pointer to the input buffer + in_length: length of the input buffer, must be a multiple of 8 + output: pointer to the returned buffer + \param[out] none + \retval ErrStatus: SUCCESS or ERROR +*/ +ErrStatus cau_tdes_ecb(uint32_t algo_dir, uint8_t key[24], cau_text_struct *text) +{ + ErrStatus ret = ERROR; + cau_key_parameter_struct key_initpara; + + uint32_t keyaddr = (uint32_t)key; + + /* key structure initialization */ + cau_key_parameter_init(&key_initpara); + /* initialize the CAU peripheral */ + cau_init(algo_dir, CAU_MODE_TDES_ECB, CAU_SWAPPING_8BIT); + + /* key initialization */ + key_initpara.key_1_high = __REV(*(uint32_t*)(keyaddr)); + keyaddr += 4U; + key_initpara.key_1_low= __REV(*(uint32_t*)(keyaddr)); + keyaddr += 4U; + key_initpara.key_2_high = __REV(*(uint32_t*)(keyaddr)); + keyaddr += 4U; + key_initpara.key_2_low= __REV(*(uint32_t*)(keyaddr)); + keyaddr += 4U; + key_initpara.key_3_high = __REV(*(uint32_t*)(keyaddr)); + keyaddr += 4U; + key_initpara.key_3_low= __REV(*(uint32_t*)(keyaddr)); + cau_key_init(&key_initpara); + + /* flush the IN and OUT FIFOs */ + cau_fifo_flush(); + + /* enable the CAU peripheral */ + cau_enable(); + /* TDES calculate process */ + ret = cau_tdes_calculate(text->input, text->in_length, text->output); + /* disable the CAU peripheral */ + cau_disable(); + + return ret; +} + +/*! + \brief encrypt and decrypt using TDES in CBC mode + \param[in] algo_dir: algorithm direction + only one parameter can be selected which is shown as below + \arg CAU_ENCRYPT: encrypt + \arg CAU_DECRYPT: decrypt + \param[in] key: key used for TDES algorithm + \param[in] iv: initialization vectors used for TDES algorithm + \param[in] text: pointer to the text information struct + input: pointer to the input buffer + in_length: length of the input buffer, must be a multiple of 8 + output: pointer to the returned buffer + \param[out] none + \retval ErrStatus: SUCCESS or ERROR +*/ +ErrStatus cau_tdes_cbc(uint32_t algo_dir, uint8_t key[24], uint8_t iv[8], cau_text_struct *text) +{ + ErrStatus ret = ERROR; + cau_key_parameter_struct key_initpara; + cau_iv_parameter_struct iv_initpara; + + uint32_t keyaddr = (uint32_t)key; + uint32_t ivaddr = (uint32_t)iv; + + /* key structure initialization */ + cau_key_parameter_init(&key_initpara); + /* initialize the CAU peripheral */ + cau_init(algo_dir, CAU_MODE_TDES_CBC, CAU_SWAPPING_8BIT); + + /* key initialization */ + key_initpara.key_1_high = __REV(*(uint32_t*)(keyaddr)); + keyaddr += 4U; + key_initpara.key_1_low= __REV(*(uint32_t*)(keyaddr)); + keyaddr += 4U; + key_initpara.key_2_high = __REV(*(uint32_t*)(keyaddr)); + keyaddr += 4U; + key_initpara.key_2_low= __REV(*(uint32_t*)(keyaddr)); + keyaddr += 4U; + key_initpara.key_3_high = __REV(*(uint32_t*)(keyaddr)); + keyaddr += 4U; + key_initpara.key_3_low= __REV(*(uint32_t*)(keyaddr)); + cau_key_init(&key_initpara); + + /* vectors initialization */ + iv_initpara.iv_0_high = __REV(*(uint32_t*)(ivaddr)); + ivaddr += 4U; + iv_initpara.iv_0_low= __REV(*(uint32_t*)(ivaddr)); + cau_iv_init(&iv_initpara); + + /* flush the IN and OUT FIFOs */ + cau_fifo_flush(); + + /* enable the CAU peripheral */ + cau_enable(); + /* TDES calculate process */ + ret = cau_tdes_calculate(text->input, text->in_length, text->output); + /* disable the CAU peripheral */ + cau_disable(); + + return ret; +} + +/*! + \brief TDES calculate process + \param[in] input: pointer to the input buffer + \param[in] in_length: length of the input buffer, must be a multiple of 8 + \param[in] output: pointer to the returned buffer + \param[out] none + \retval ErrStatus: SUCCESS or ERROR +*/ +static ErrStatus cau_tdes_calculate(uint8_t *input, uint32_t in_length, uint8_t *output) +{ + uint32_t inputaddr = (uint32_t)input; + uint32_t outputaddr = (uint32_t)output; + uint32_t i = 0U; + __IO uint32_t counter = 0U; + uint32_t busystatus = 0U; + + /* the clock is not enabled or there is no embeded CAU peripheral */ + if(DISABLE == cau_enable_state_get()){ + return ERROR; + } + + for(i = 0U; i < in_length; i += 8U){ + /* write data to the IN FIFO */ + cau_data_write(*(uint32_t*)(inputaddr)); + inputaddr += 4U; + cau_data_write(*(uint32_t*)(inputaddr)); + inputaddr += 4U; + + /* wait until the complete message has been processed */ + counter = 0U; + do{ + busystatus = cau_flag_get(CAU_FLAG_BUSY); + counter++; + }while((TDESBSY_TIMEOUT != counter) && (RESET != busystatus)); + + if(RESET != busystatus){ + return ERROR; + }else{ + /* read the output block from the output FIFO */ + *(uint32_t*)(outputaddr) = cau_data_read(); + outputaddr += 4U; + *(uint32_t*)(outputaddr) = cau_data_read(); + outputaddr += 4U; + } + } + + return SUCCESS; +} diff --git a/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_standard_peripheral/Source/gd32f20x_crc.c b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_standard_peripheral/Source/gd32f20x_crc.c new file mode 100644 index 0000000000..5fc9b2e86f --- /dev/null +++ b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_standard_peripheral/Source/gd32f20x_crc.c @@ -0,0 +1,130 @@ +/*! + \file gd32f20x_crc.c + \brief CRC driver + + \version 2015-07-15, V1.0.0, firmware for GD32F20x + \version 2017-06-05, V2.0.0, firmware for GD32F20x + \version 2018-10-31, V2.1.0, firmware for GD32F20x + \version 2020-09-30, V2.2.0, firmware for GD32F20x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "gd32f20x_crc.h" + +#define CRC_DATA_RESET_VALUE ((uint32_t)0xFFFFFFFFU) +#define CRC_FDATA_RESET_VALUE ((uint32_t)0x00000000U) + +/*! + \brief deinit CRC calculation unit + \param[in] none + \param[out] none + \retval none +*/ +void crc_deinit(void) +{ + CRC_DATA = CRC_DATA_RESET_VALUE; + CRC_FDATA = CRC_FDATA_RESET_VALUE; + CRC_CTL = (uint32_t)CRC_CTL_RST; +} + +/*! + \brief reset data register to the value of initializaiton data register + \param[in] none + \param[out] none + \retval none +*/ +void crc_data_register_reset(void) +{ + CRC_CTL |= (uint32_t)CRC_CTL_RST; +} + +/*! + \brief read the value of the data register + \param[in] none + \param[out] none + \retval 32-bit value of the data register +*/ +uint32_t crc_data_register_read(void) +{ + uint32_t data; + data = CRC_DATA; + return (data); +} + +/*! + \brief read the value of the free data register + \param[in] none + \param[out] none + \retval 8-bit value of the free data register +*/ +uint8_t crc_free_data_register_read(void) +{ + uint8_t fdata; + fdata = (uint8_t)CRC_FDATA; + return (fdata); +} + +/*! + \brief write data to the free data register + \param[in] free_data: specify 8-bit data + \param[out] none + \retval none +*/ +void crc_free_data_register_write(uint8_t free_data) +{ + CRC_FDATA = (uint32_t)free_data; +} + +/*! + \brief calculate the CRC value of a 32-bit data + \param[in] sdata: specified 32-bit data + \param[out] none + \retval 32-bit value calculated by CRC +*/ +uint32_t crc_single_data_calculate(uint32_t sdata) +{ + CRC_DATA = sdata; + return (CRC_DATA); +} + +/*! + \brief calculate the CRC value of an array of 32-bit values + \param[in] array: pointer to an array of 32-bit values + \param[in] size: size of the array + \param[out] none + \retval 32-bit value calculated by CRC +*/ +uint32_t crc_block_data_calculate(uint32_t array[], uint32_t size) +{ + uint32_t index; + for(index = 0U; index < size; index++){ + CRC_DATA = array[index]; + } + return (CRC_DATA); +} diff --git a/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_standard_peripheral/Source/gd32f20x_dac.c b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_standard_peripheral/Source/gd32f20x_dac.c new file mode 100644 index 0000000000..5eb5bd974b --- /dev/null +++ b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_standard_peripheral/Source/gd32f20x_dac.c @@ -0,0 +1,557 @@ +/*! + \file gd32f20x_dac.c + \brief DAC driver + + \version 2015-07-15, V1.0.0, firmware for GD32F20x + \version 2017-06-05, V2.0.0, firmware for GD32F20x + \version 2018-10-31, V2.1.0, firmware for GD32F20x + \version 2020-09-30, V2.2.0, firmware for GD32F20x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "gd32f20x_dac.h" + +/* DAC register bit offset */ +#define DAC1_REG_OFFSET ((uint32_t)16U) +#define DH_12BIT_OFFSET ((uint32_t)16U) +#define DH_8BIT_OFFSET ((uint32_t)8U) + +/*! + \brief deinitialize DAC + \param[in] none + \param[out] none + \retval none +*/ +void dac_deinit(void) +{ + rcu_periph_reset_enable(RCU_DACRST); + rcu_periph_reset_disable(RCU_DACRST); +} + +/*! + \brief enable DAC + \param[in] dac_periph + \arg DACx(x =0,1) + \param[out] none + \retval none +*/ +void dac_enable(uint32_t dac_periph) +{ + if(DAC0 == dac_periph){ + DAC_CTL |= DAC_CTL_DEN0; + }else{ + DAC_CTL |= DAC_CTL_DEN1; + } +} + +/*! + \brief disable DAC + \param[in] dac_periph + \arg DACx(x =0,1) + \param[out] none + \retval none +*/ +void dac_disable(uint32_t dac_periph) +{ + if(DAC0 == dac_periph){ + DAC_CTL &= ~DAC_CTL_DEN0; + }else{ + DAC_CTL &= ~DAC_CTL_DEN1; + } +} + +/*! + \brief enable DAC DMA function + \param[in] dac_periph + \arg DACx(x=0,1) + \param[out] none + \retval none +*/ +void dac_dma_enable(uint32_t dac_periph) +{ + if(DAC0 == dac_periph){ + DAC_CTL |= DAC_CTL_DDMAEN0; + }else{ + DAC_CTL |= DAC_CTL_DDMAEN1; + } +} + +/*! + \brief disable DAC DMA function + \param[in] dac_periph + \arg DACx(x=0,1) + \param[out] none + \retval none +*/ +void dac_dma_disable(uint32_t dac_periph) +{ + if(DAC0 == dac_periph){ + DAC_CTL &= ~DAC_CTL_DDMAEN0; + }else{ + DAC_CTL &= ~DAC_CTL_DDMAEN1; + } +} + +/*! + \brief enable DAC output buffer + \param[in] dac_periph + \arg DACx(x = 0,1) + \param[out] none + \retval none +*/ +void dac_output_buffer_enable(uint32_t dac_periph) +{ + if(DAC0 == dac_periph){ + DAC_CTL &= ~DAC_CTL_DBOFF0; + }else{ + DAC_CTL &= ~DAC_CTL_DBOFF1; + } +} + +/*! + \brief disable DAC output buffer + \param[in] dac_periph + \arg DACx(x = 0,1) + \param[out] none + \retval none +*/ +void dac_output_buffer_disable(uint32_t dac_periph) +{ + if(DAC0 == dac_periph){ + DAC_CTL |= DAC_CTL_DBOFF0; + }else{ + DAC_CTL |= DAC_CTL_DBOFF1; + } +} + +/*! + \brief get DAC output value + \param[in] dac_periph + \arg DACx(x=0,1) + \param[out] none + \retval DAC output data +*/ +uint16_t dac_output_value_get(uint32_t dac_periph) +{ + uint16_t data = 0U; + if(DAC0 == dac_periph){ + /* store the DAC0 output value */ + data = (uint16_t)DAC0_DO; + }else{ + /* store the DAC1 output value */ + data = (uint16_t)DAC1_DO; + } + return data; +} + +/*! + \brief set the DAC specified data holding register value + \param[in] dac_periph + \arg DACx(x=0,1) + \param[in] dac_align + only one parameter can be selected which is shown as below: + \arg DAC_ALIGN_8B_R: data right 8b alignment + \arg DAC_ALIGN_12B_R: data right 12b alignment + \arg DAC_ALIGN_12B_L: data left 12b alignment + \param[in] data: data to be loaded + \param[out] none + \retval none +*/ +void dac_data_set(uint32_t dac_periph, uint32_t dac_align, uint16_t data) +{ + if(DAC0 == dac_periph){ + switch(dac_align){ + /* data right 12b alignment */ + case DAC_ALIGN_12B_R: + DAC0_R12DH = data; + break; + /* data left 12b alignment */ + case DAC_ALIGN_12B_L: + DAC0_L12DH = data; + break; + /* data right 8b alignment */ + case DAC_ALIGN_8B_R: + DAC0_R8DH = data; + break; + default: + break; + } + }else{ + switch(dac_align){ + /* data right 12b alignment */ + case DAC_ALIGN_12B_R: + DAC1_R12DH = data; + break; + /* data left 12b alignment */ + case DAC_ALIGN_12B_L: + DAC1_L12DH = data; + break; + /* data right 8b alignment */ + case DAC_ALIGN_8B_R: + DAC1_R8DH = data; + break; + default: + break; + } + } +} + +/*! + \brief enable DAC trigger + \param[in] dac_periph + \arg DACx(x = 0,1) + \param[out] none + \retval none +*/ +void dac_trigger_enable(uint32_t dac_periph) +{ + if(DAC0 == dac_periph){ + DAC_CTL |= DAC_CTL_DTEN0; + }else{ + DAC_CTL |= DAC_CTL_DTEN1; + } +} + +/*! + \brief disable DAC trigger + \param[in] dac_periph + \arg DACx(x = 0,1) + \param[out] none + \retval none +*/ +void dac_trigger_disable(uint32_t dac_periph) +{ + if(DAC0 == dac_periph){ + DAC_CTL &= ~DAC_CTL_DTEN0; + }else{ + DAC_CTL &= ~DAC_CTL_DTEN1; + } +} + +/*! + \brief set DAC trigger source + \param[in] dac_periph + \arg DACx(x =0,1) + \param[in] triggersource: external triggers of DAC + only one parameter can be selected which is shown as below: + \arg DAC_TRIGGER_T1_TRGO: TIMER1 TRGO + \arg DAC_TRIGGER_T2_TRGO: TIMER2 TRGO + \arg DAC_TRIGGER_T3_TRGO: TIMER3 TRGO + \arg DAC_TRIGGER_T4_TRGO: TIMER4 TRGO + \arg DAC_TRIGGER_T5_TRGO: TIMER5 TRGO + \arg DAC_TRIGGER_T6_TRGO: TIMER6 TRGO + \arg DAC_TRIGGER_EXTI_9: EXTI interrupt line9 event + \arg DAC_TRIGGER_SOFTWARE: software trigger + \param[out] none + \retval none +*/ +void dac_trigger_source_config(uint32_t dac_periph, uint32_t triggersource) +{ + if(DAC0 == dac_periph){ + /* configure DAC0 trigger source */ + DAC_CTL &= ~DAC_CTL_DTSEL0; + DAC_CTL |= triggersource; + }else{ + /* configure DAC1 trigger source */ + DAC_CTL &= ~DAC_CTL_DTSEL1; + DAC_CTL |= (triggersource << DAC1_REG_OFFSET); + } +} + +/*! + \brief enable DAC software trigger + \param[in] dac_periph + \arg DACx(x = 0,1) + \retval none +*/ +void dac_software_trigger_enable(uint32_t dac_periph) +{ + if(DAC0 == dac_periph){ + DAC_SWT |= DAC_SWT_SWTR0; + }else{ + DAC_SWT |= DAC_SWT_SWTR1; + } +} + +/*! + \brief disable DAC software trigger + \param[in] dac_periph + \arg DACx(x = 0,1) + \param[out] none + \retval none +*/ +void dac_software_trigger_disable(uint32_t dac_periph) +{ + if(DAC0 == dac_periph){ + DAC_SWT &= ~DAC_SWT_SWTR0; + }else{ + DAC_SWT &= ~DAC_SWT_SWTR1; + } +} + +/*! + \brief configure DAC wave mode + \param[in] dac_periph + \arg DACx(x=0,1) + \param[in] wave_mode + only one parameter can be selected which is shown as below: + \arg DAC_WAVE_DISABLE: wave disable + \arg DAC_WAVE_MODE_LFSR: LFSR noise mode + \arg DAC_WAVE_MODE_TRIANGLE: triangle noise mode + \param[out] none + \retval none +*/ +void dac_wave_mode_config(uint32_t dac_periph, uint32_t wave_mode) +{ + if(DAC0 == dac_periph){ + /* configure DAC0 wave mode */ + DAC_CTL &= ~DAC_CTL_DWM0; + DAC_CTL |= wave_mode; + }else{ + /* configure DAC1 wave mode */ + DAC_CTL &= ~DAC_CTL_DWM1; + DAC_CTL |= (wave_mode << DAC1_REG_OFFSET); + } +} + +/*! + \brief configure DAC wave bit width + \param[in] dac_periph + \arg DACx(x=0,1) + \param[in] bit_width + only one parameter can be selected which is shown as below: + \arg DAC_WAVE_BIT_WIDTH_1: bit width of the wave signal is 1 + \arg DAC_WAVE_BIT_WIDTH_2: bit width of the wave signal is 2 + \arg DAC_WAVE_BIT_WIDTH_3: bit width of the wave signal is 3 + \arg DAC_WAVE_BIT_WIDTH_4: bit width of the wave signal is 4 + \arg DAC_WAVE_BIT_WIDTH_5: bit width of the wave signal is 5 + \arg DAC_WAVE_BIT_WIDTH_6: bit width of the wave signal is 6 + \arg DAC_WAVE_BIT_WIDTH_7: bit width of the wave signal is 7 + \arg DAC_WAVE_BIT_WIDTH_8: bit width of the wave signal is 8 + \arg DAC_WAVE_BIT_WIDTH_9: bit width of the wave signal is 9 + \arg DAC_WAVE_BIT_WIDTH_10: bit width of the wave signal is 10 + \arg DAC_WAVE_BIT_WIDTH_11: bit width of the wave signal is 11 + \arg DAC_WAVE_BIT_WIDTH_12: bit width of the wave signal is 12 + \param[out] none + \retval none +*/ +void dac_wave_bit_width_config(uint32_t dac_periph, uint32_t bit_width) +{ + if(DAC0 == dac_periph){ + /* configure DAC0 wave bit width */ + DAC_CTL &= ~DAC_CTL_DWBW0; + DAC_CTL |= bit_width; + }else{ + /* configure DAC1 wave bit width */ + DAC_CTL &= ~DAC_CTL_DWBW1; + DAC_CTL |= (bit_width << DAC1_REG_OFFSET); + } +} + +/*! + \brief configure DAC LFSR noise mode + \param[in] dac_periph + \arg DACx(x=0,1) + \param[in] unmask_bits + only one parameter can be selected which is shown as below: + \arg DAC_LFSR_BIT0: unmask the LFSR bit0 + \arg DAC_LFSR_BITS1_0: unmask the LFSR bits[1:0] + \arg DAC_LFSR_BITS2_0: unmask the LFSR bits[2:0] + \arg DAC_LFSR_BITS3_0: unmask the LFSR bits[3:0] + \arg DAC_LFSR_BITS4_0: unmask the LFSR bits[4:0] + \arg DAC_LFSR_BITS5_0: unmask the LFSR bits[5:0] + \arg DAC_LFSR_BITS6_0: unmask the LFSR bits[6:0] + \arg DAC_LFSR_BITS7_0: unmask the LFSR bits[7:0] + \arg DAC_LFSR_BITS8_0: unmask the LFSR bits[8:0] + \arg DAC_LFSR_BITS9_0: unmask the LFSR bits[9:0] + \arg DAC_LFSR_BITS10_0: unmask the LFSR bits[10:0] + \arg DAC_LFSR_BITS11_0: unmask the LFSR bits[11:0] + \param[out] none + \retval none +*/ +void dac_lfsr_noise_config(uint32_t dac_periph, uint32_t unmask_bits) +{ + if(DAC0 == dac_periph){ + /* configure DAC0 LFSR noise mode */ + DAC_CTL &= ~DAC_CTL_DWBW0; + DAC_CTL |= unmask_bits; + }else{ + /* configure DAC1 LFSR noise mode */ + DAC_CTL &= ~DAC_CTL_DWBW1; + DAC_CTL |= (unmask_bits << DAC1_REG_OFFSET); + } +} + +/*! + \brief configure DAC triangle noise mode + \param[in] dac_periph + \arg DACx(x=0,1) + \param[in] amplitude + only one parameter can be selected which is shown as below: + \arg DAC_TRIANGLE_AMPLITUDE_1: triangle amplitude is 1 + \arg DAC_TRIANGLE_AMPLITUDE_3: triangle amplitude is 3 + \arg DAC_TRIANGLE_AMPLITUDE_7: triangle amplitude is 7 + \arg DAC_TRIANGLE_AMPLITUDE_15: triangle amplitude is 15 + \arg DAC_TRIANGLE_AMPLITUDE_31: triangle amplitude is 31 + \arg DAC_TRIANGLE_AMPLITUDE_63: triangle amplitude is 63 + \arg DAC_TRIANGLE_AMPLITUDE_127: triangle amplitude is 127 + \arg DAC_TRIANGLE_AMPLITUDE_255: triangle amplitude is 255 + \arg DAC_TRIANGLE_AMPLITUDE_511: triangle amplitude is 511 + \arg DAC_TRIANGLE_AMPLITUDE_1023: triangle amplitude is 1023 + \arg DAC_TRIANGLE_AMPLITUDE_2047: triangle amplitude is 2047 + \arg DAC_TRIANGLE_AMPLITUDE_4095: triangle amplitude is 4095 + \param[out] none + \retval none +*/ +void dac_triangle_noise_config(uint32_t dac_periph, uint32_t amplitude) +{ + if(DAC0 == dac_periph){ + /* configure DAC0 triangle noise mode */ + DAC_CTL &= ~DAC_CTL_DWBW0; + DAC_CTL |= amplitude; + }else{ + /* configure DAC1 triangle noise mode */ + DAC_CTL &= ~DAC_CTL_DWBW1; + DAC_CTL |= (amplitude << DAC1_REG_OFFSET); + } +} + +/*! + \brief enable DAC concurrent mode + \param[in] none + \param[out] none + \retval none +*/ +void dac_concurrent_enable(void) +{ + uint32_t ctl = 0U; + ctl = DAC_CTL_DEN0 | DAC_CTL_DEN1; + DAC_CTL |= (ctl); +} + +/*! + \brief disable DAC concurrent mode + \param[in] none + \param[out] none + \retval none +*/ +void dac_concurrent_disable(void) +{ + uint32_t ctl = 0U; + ctl = DAC_CTL_DEN0 | DAC_CTL_DEN1; + DAC_CTL &= (~ctl); +} + +/*! + \brief enable DAC concurrent software trigger function + \param[in] none + \param[out] none + \retval none +*/ +void dac_concurrent_software_trigger_enable(void) +{ + uint32_t swt = 0U; + swt = DAC_SWT_SWTR0 | DAC_SWT_SWTR1; + DAC_SWT |= (swt); +} + +/*! + \brief disable DAC concurrent software trigger function + \param[in] none + \param[out] none + \retval none +*/ +void dac_concurrent_software_trigger_disable(void) +{ + uint32_t swt = 0U; + swt = DAC_SWT_SWTR0 | DAC_SWT_SWTR1; + DAC_SWT &= (~swt); +} + +/*! + \brief enable DAC concurrent buffer function + \param[in] none + \param[out] none + \retval none +*/ +void dac_concurrent_output_buffer_enable(void) +{ + uint32_t ctl = 0U; + ctl = DAC_CTL_DBOFF0 | DAC_CTL_DBOFF1; + DAC_CTL &= (~ctl); +} + +/*! + \brief disable DAC concurrent buffer function + \param[in] none + \param[out] none + \retval none +*/ +void dac_concurrent_output_buffer_disable(void) +{ + uint32_t ctl = 0U; + ctl = DAC_CTL_DBOFF0 | DAC_CTL_DBOFF1; + DAC_CTL |= (ctl); +} + +/*! + \brief set DAC concurrent mode data holding register value + \param[in] dac_align + only one parameter can be selected which is shown as below: + \arg DAC_ALIGN_8B_R: data right 8b alignment + \arg DAC_ALIGN_12B_R: data right 12b alignment + \arg DAC_ALIGN_12B_L: data left 12b alignment + \param[in] data0: data to be loaded + \param[in] data1: data to be loaded + \param[out] none + \retval none +*/ +void dac_concurrent_data_set(uint32_t dac_align, uint16_t data0, uint16_t data1) +{ + uint32_t data = 0U; + switch(dac_align){ + /* data right 12b alignment */ + case DAC_ALIGN_12B_R: + data = ((uint32_t)data1 << DH_12BIT_OFFSET) | data0; + DACC_R12DH = data; + break; + /* data left 12b alignment */ + case DAC_ALIGN_12B_L: + data = ((uint32_t)data1 << DH_12BIT_OFFSET) | data0; + DACC_L12DH = data; + break; + /* data right 8b alignment */ + case DAC_ALIGN_8B_R: + data = ((uint32_t)data1 << DH_8BIT_OFFSET) | data0; + DACC_R8DH = data; + break; + default: + break; + } +} diff --git a/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_standard_peripheral/Source/gd32f20x_dbg.c b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_standard_peripheral/Source/gd32f20x_dbg.c new file mode 100644 index 0000000000..f849106dac --- /dev/null +++ b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_standard_peripheral/Source/gd32f20x_dbg.c @@ -0,0 +1,152 @@ +/*! + \file gd32f20x_dbg.c + \brief DBG driver + + \version 2015-07-15, V1.0.0, firmware for GD32F20x + \version 2017-06-05, V2.0.0, firmware for GD32F20x + \version 2018-10-31, V2.1.0, firmware for GD32F20x + \version 2020-09-30, V2.2.0, firmware for GD32F20x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "gd32f20x_dbg.h" + +/*! + \brief read DBG_ID code register + \param[in] none + \param[out] none + \retval DBG_ID code +*/ +uint32_t dbg_id_get(void) +{ + return DBG_ID; +} + +/*! + \brief enable low power behavior when the mcu is in debug mode + \param[in] dbg_low_power: + one or more parameters can be selected which are shown as below: + \arg DBG_LOW_POWER_SLEEP: keep debugger connection during sleep mode + \arg DBG_LOW_POWER_DEEPSLEEP: keep debugger connection during deepsleep mode + \arg DBG_LOW_POWER_STANDBY: keep debugger connection during standby mode + \param[out] none + \retval none +*/ +void dbg_low_power_enable(uint32_t dbg_low_power) +{ + DBG_CTL |= dbg_low_power; +} + +/*! + \brief disable low power behavior when the mcu is in debug mode + \param[in] dbg_low_power: + one or more parameters can be selected which are shown as below: + \arg DBG_LOW_POWER_SLEEP: donot keep debugger connection during sleep mode + \arg DBG_LOW_POWER_DEEPSLEEP: donot keep debugger connection during deepsleep mode + \arg DBG_LOW_POWER_STANDBY: donot keep debugger connection during standby mode + \param[out] none + \retval none +*/ +void dbg_low_power_disable(uint32_t dbg_low_power) +{ + DBG_CTL &= ~dbg_low_power; +} + +/*! + \brief enable peripheral behavior when the mcu is in debug mode + \param[in] dbg_periph: refer to dbg_periph_enum + one or more parameters can be selected which are shown as below: + \arg DBG_FWDGT_HOLD : debug FWDGT kept when core is halted + \arg DBG_WWDGT_HOLD : debug WWDGT kept when core is halted + \arg DBG_CANx_HOLD (x=0,1): hold CANx counter when core is halted + \arg DBG_I2Cx_HOLD (x=0,1): hold I2Cx smbus when core is halted + \arg DBG_TIMERx_HOLD (x=0,1,2,3,4,5,6,7,8,9,10,11,12,13): hold TIMERx counter when core is halted + \param[out] none + \retval none +*/ +void dbg_periph_enable(dbg_periph_enum dbg_periph) +{ + DBG_CTL |= (uint32_t)dbg_periph; +} + +/*! + \brief disable peripheral behavior when the mcu is in debug mode + \param[in] dbg_periph: refer to dbg_periph_enum + one or more parameters can be selected which are shown as below: + \arg DBG_FWDGT_HOLD : debug FWDGT kept when core is halted + \arg DBG_WWDGT_HOLD : debug WWDGT kept when core is halted + \arg DBG_CANx_HOLD (x=0,1): hold CANx counter when core is halted + \arg DBG_I2Cx_HOLD (x=0,1): hold I2Cx smbus when core is halted + \arg DBG_TIMERx_HOLD (x=0,1,2,3,4,5,6,7,8,9,10,11,12,13): hold TIMERx counter when core is halted + \param[out] none + \retval none +*/ +void dbg_periph_disable(dbg_periph_enum dbg_periph) +{ + DBG_CTL &= ~(uint32_t)dbg_periph; +} + +/*! + \brief enable trace pin assignment + \param[in] none + \param[out] none + \retval none +*/ +void dbg_trace_pin_enable(void) +{ + DBG_CTL |= DBG_CTL_TRACE_IOEN; +} + +/*! + \brief disable trace pin assignment + \param[in] none + \param[out] none + \retval none +*/ +void dbg_trace_pin_disable(void) +{ + DBG_CTL &= ~DBG_CTL_TRACE_IOEN; +} + +/*! + \brief trace pin mode selection + \param[in] trace_mode: + only one parameter can be selected which is shown as below: + \arg TRACE_MODE_ASYNC: trace pin used for async mode + \arg TRACE_MODE_SYNC_DATASIZE_1: trace pin used for sync mode and data size is 1 + \arg TRACE_MODE_SYNC_DATASIZE_2: trace pin used for sync mode and data size is 2 + \arg TRACE_MODE_SYNC_DATASIZE_4: trace pin used for sync mode and data size is 4 + \param[out] none + \retval none +*/ +void dbg_trace_pin_mode_set(uint32_t trace_mode) +{ + DBG_CTL &= ~DBG_CTL_TRACE_MODE; + DBG_CTL |= trace_mode; +} diff --git a/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_standard_peripheral/Source/gd32f20x_dci.c b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_standard_peripheral/Source/gd32f20x_dci.c new file mode 100644 index 0000000000..8417460ad7 --- /dev/null +++ b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_standard_peripheral/Source/gd32f20x_dci.c @@ -0,0 +1,344 @@ +/*! + \file gd32f20x_dci.c + \brief DCI driver + + \version 2015-07-15, V1.0.0, firmware for GD32F20x + \version 2017-06-05, V2.0.0, firmware for GD32F20x + \version 2018-10-31, V2.1.0, firmware for GD32F20x + \version 2020-09-30, V2.2.0, firmware for GD32F20x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "gd32f20x_dci.h" + +/*! + \brief DCI deinit + \param[in] none + \param[out] none + \retval none +*/ +void dci_deinit(void) +{ + rcu_periph_reset_enable(RCU_DCIRST); + rcu_periph_reset_disable(RCU_DCIRST); +} + +/*! + \brief initialize DCI registers + \param[in] dci_struct: DCI parameter initialization structure + members of the structure and the member values are shown as below: + capture_mode : DCI_CAPTURE_MODE_CONTINUOUS, DCI_CAPTURE_MODE_SNAPSHOT + colck_polarity : DCI_CK_POLARITY_FALLING, DCI_CK_POLARITY_RISING + hsync_polarity : DCI_HSYNC_POLARITY_LOW, DCI_HSYNC_POLARITY_HIGH + vsync_polarity : DCI_VSYNC_POLARITY_LOW, DCI_VSYNC_POLARITY_HIGH + frame_rate : DCI_FRAME_RATE_ALL, DCI_FRAME_RATE_1_2, DCI_FRAME_RATE_1_4 + interface_format: DCI_INTERFACE_FORMAT_8BITS, DCI_INTERFACE_FORMAT_10BITS, + DCI_INTERFACE_FORMAT_12BITS, DCI_INTERFACE_FORMAT_14BITS + \param[out] none + \retval none +*/ +void dci_init(dci_parameter_struct* dci_struct) +{ + uint32_t reg = 0U; + /* disable capture function and DCI */ + DCI_CTL &= ~(DCI_CTL_CAP | DCI_CTL_DCIEN); + /* configure DCI parameter */ + reg |= dci_struct->capture_mode; + reg |= dci_struct->clock_polarity; + reg |= dci_struct->hsync_polarity; + reg |= dci_struct->vsync_polarity; + reg |= dci_struct->frame_rate; + reg |= dci_struct->interface_format; + + DCI_CTL = reg; +} + +/*! + \brief enable DCI function + \param[in] none + \param[out] none + \retval none +*/ +void dci_enable(void) +{ + DCI_CTL |= DCI_CTL_DCIEN; +} + +/*! + \brief disable DCI function + \param[in] none + \param[out] none + \retval none +*/ +void dci_disable(void) +{ + DCI_CTL &= ~DCI_CTL_DCIEN; +} + +/*! + \brief enable DCI capture + \param[in] none + \param[out] none + \retval none +*/ +void dci_capture_enable(void) +{ + DCI_CTL |= DCI_CTL_CAP; +} + +/*! + \brief disable DCI capture + \param[in] none + \param[out] none + \retval none +*/ +void dci_capture_disable(void) +{ + DCI_CTL &= ~DCI_CTL_CAP; +} + +/*! + \brief enable DCI jpeg mode + \param[in] none + \param[out] none + \retval none +*/ +void dci_jpeg_enable(void) +{ + DCI_CTL |= DCI_CTL_JM; +} + +/*! + \brief disable DCI jpeg mode + \param[in] none + \param[out] none + \retval none +*/ +void dci_jpeg_disable(void) +{ + DCI_CTL &= ~DCI_CTL_JM; +} + +/*! + \brief enable cropping window function + \param[in] none + \param[out] none + \retval none +*/ +void dci_crop_window_enable(void) +{ + DCI_CTL |= DCI_CTL_WDEN; +} + +/*! + \brief disable cropping window function + \param[in] none + \param[out] none + \retval none +*/ +void dci_crop_window_disable(void) +{ + DCI_CTL &= ~DCI_CTL_WDEN; +} + +/*! + \brief configure DCI cropping window + \param[in] start_x: window horizontal start position + \param[in] start_y: window vertical start position + \param[in] size_width: window horizontal size + \param[in] size_height: window vertical size + \param[out] none + \retval none +*/ +void dci_crop_window_config(uint16_t start_x, uint16_t start_y, uint16_t size_width, uint16_t size_height) +{ + DCI_CWSPOS = ((uint32_t)start_x | ((uint32_t)start_y<<16)); + DCI_CWSZ = ((uint32_t)size_width | ((uint32_t)size_height<<16)); +} + +/*! + \brief enable embedded synchronous mode + \param[in] none + \param[out] none + \retval none +*/ +void dci_embedded_sync_enable(void) +{ + DCI_CTL |= DCI_CTL_ESM; +} + +/*! + \brief disble embedded synchronous mode + \param[in] none + \param[out] none + \retval none +*/ +void dci_embedded_sync_disable(void) +{ + DCI_CTL &= ~DCI_CTL_ESM; +} +/*! + \brief config synchronous codes in embedded synchronous mode + \param[in] frame_start: frame start code in embedded synchronous mode + \param[in] line_start: line start code in embedded synchronous mode + \param[in] line_end: line end code in embedded synchronous mode + \param[in] frame_end: frame end code in embedded synchronous mode + \param[out] none + \retval none +*/ +void dci_sync_codes_config(uint8_t frame_start, uint8_t line_start, uint8_t line_end, uint8_t frame_end) +{ + DCI_SC = ((uint32_t)frame_start | ((uint32_t)line_start<<8) | ((uint32_t)line_end<<16) | ((uint32_t)frame_end<<24)); +} + +/*! + \brief config synchronous codes unmask in embedded synchronous mode + \param[in] frame_start: frame start code unmask bits in embedded synchronous mode + \param[in] line_start: line start code unmask bits in embedded synchronous mode + \param[in] line_end: line end code unmask bits in embedded synchronous mode + \param[in] frame_end: frame end code unmask bits in embedded synchronous mode + \param[out] none + \retval none +*/ +void dci_sync_codes_unmask_config(uint8_t frame_start, uint8_t line_start, uint8_t line_end, uint8_t frame_end) +{ + DCI_SCUMSK = ((uint32_t)frame_start | ((uint32_t)line_start<<8) | ((uint32_t)line_end<<16) | ((uint32_t)frame_end<<24)); +} + +/*! + \brief read DCI data register + \param[in] none + \param[out] none + \retval data +*/ +uint32_t dci_data_read(void) +{ + return DCI_DATA; +} + +/*! + \brief get specified flag + \param[in] flag: + \arg DCI_FLAG_HS: HS line status + \arg DCI_FLAG_VS: VS line status + \arg DCI_FLAG_FV:FIFO valid + \arg DCI_FLAG_EF: end of frame flag + \arg DCI_FLAG_OVR: FIFO overrun flag + \arg DCI_FLAG_ESE: embedded synchronous error flag + \arg DCI_FLAG_VSYNC: vsync flag + \arg DCI_FLAG_EL: end of line flag + \param[out] none + \retval FlagStatus: SET or RESET +*/ +FlagStatus dci_flag_get(uint32_t flag) +{ + uint32_t stat = 0U; + + if(flag >> 31){ + /* get flag status from DCI_STAT1 register */ + stat = DCI_STAT1; + }else{ + /* get flag status from DCI_STAT0 register */ + stat = DCI_STAT0; + } + + if(flag & stat){ + return SET; + }else{ + return RESET; + } +} + +/*! + \brief enable specified DCI interrupt + \param[in] interrupt: + \arg DCI_INT_EF: end of frame interrupt + \arg DCI_INT_OVR: FIFO overrun interrupt + \arg DCI_INT_ESE: embedded synchronous error interrupt + \arg DCI_INT_VSYNC: vsync interrupt + \arg DCI_INT_EL: end of line interrupt + \param[out] none + \retval none +*/ +void dci_interrupt_enable(uint32_t interrupt) +{ + DCI_INTEN |= interrupt; +} + +/*! + \brief disable specified DCI interrupt + \param[in] interrupt: + \arg DCI_INT_EF: end of frame interrupt + \arg DCI_INT_OVR: FIFO overrun interrupt + \arg DCI_INT_ESE: embedded synchronous error interrupt + \arg DCI_INT_VSYNC: vsync interrupt + \arg DCI_INT_EL: end of line interrupt + \param[out] none + \retval none +*/ +void dci_interrupt_disable(uint32_t interrupt) +{ + DCI_INTEN &= ~interrupt; +} + +/*! + \brief get specified interrupt flag + \param[in] int_flag: + \arg DCI_INT_FLAG_EF: end of frame interrupt flag + \arg DCI_INT_FLAG_OVR: FIFO overrun interrupt flag + \arg DCI_INT_FLAG_ESE: embedded synchronous error interrupt flag + \arg DCI_INT_FLAG_VSYNC: vsync interrupt flag + \arg DCI_INT_FLAG_EL: end of line interrupt flag + \param[out] none + \retval FlagStatus: SET or RESET +*/ +FlagStatus dci_interrupt_flag_get(uint32_t int_flag) +{ + if(RESET == (DCI_INTF & int_flag)){ + return RESET; + }else{ + return SET; + } +} + +/*! + \brief clear specified interrupt flag + \param[in] int_flag: + \arg DCI_INT_EF: end of frame interrupt + \arg DCI_INT_OVR: FIFO overrun interrupt + \arg DCI_INT_ESE: embedded synchronous error interrupt + \arg DCI_INT_VSYNC: vsync interrupt + \arg DCI_INT_EL: end of line interrupt + \param[out] none + \retval none +*/ +void dci_interrupt_flag_clear(uint32_t int_flag) +{ + DCI_INTC |= int_flag; +} diff --git a/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_standard_peripheral/Source/gd32f20x_dma.c b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_standard_peripheral/Source/gd32f20x_dma.c new file mode 100644 index 0000000000..5795341fa4 --- /dev/null +++ b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_standard_peripheral/Source/gd32f20x_dma.c @@ -0,0 +1,658 @@ +/*! + \file gd32f20x_dma.c + \brief DMA driver + + \version 2015-07-15, V1.0.0, firmware for GD32F20x + \version 2017-06-05, V2.0.0, firmware for GD32F20x + \version 2018-10-31, V2.1.0, firmware for GD32F20x + \version 2020-09-30, V2.2.0, firmware for GD32F20x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "gd32f20x_dma.h" +#include "gd32f20x_rcu.h" + +#define DMA_WRONG_HANDLE while(1){} + +/*! + \brief deinitialize DMA a channel registers + \param[in] dma_periph: DMAx(x=0,1) + \arg DMAx(x=0,1) + \param[in] channelx: specify which DMA channel is deinitialized + only one parameter can be selected which is shown as below: + \arg DMA0: DMA_CHx(x=0..6), DMA1: DMA_CHx(x=0..6) + \param[out] none + \retval none +*/ +void dma_deinit(uint32_t dma_periph, dma_channel_enum channelx) +{ + /* disable DMA channel */ + DMA_CHCTL(dma_periph, channelx) &= ~DMA_CHXCTL_CHEN; + /* reset DMA channel registers */ + DMA_CHCTL(dma_periph, channelx) = DMA_CHCTL_RESET_VALUE; + DMA_CHCNT(dma_periph, channelx) = DMA_CHCNT_RESET_VALUE; + DMA_CHPADDR(dma_periph, channelx) = DMA_CHPADDR_RESET_VALUE; + DMA_CHMADDR(dma_periph, channelx) = DMA_CHMADDR_RESET_VALUE; + DMA_INTC(dma_periph) |= DMA_FLAG_ADD(DMA_CHINTF_RESET_VALUE, channelx); + + if((DMA1 == dma_periph) && (DMA_CH5 == channelx)){ + DMA_ACFG = DMA_ACFG_RESET_VALUE; + } +} + +/*! + \brief initialize the parameters of DMA struct with the default values + \param[in] init_struct: the initialization data needed to initialize DMA channel + \param[out] none + \retval none +*/ +void dma_struct_para_init(dma_parameter_struct* init_struct) +{ + /* set the DMA struct with the default values */ + init_struct->periph_addr = 0U; + init_struct->periph_width = 0U; + init_struct->periph_inc = DMA_PERIPH_INCREASE_DISABLE; + init_struct->memory_addr = 0U; + init_struct->memory_width = 0U; + init_struct->memory_inc = DMA_MEMORY_INCREASE_DISABLE; + init_struct->number = 0U; + init_struct->direction = DMA_PERIPHERAL_TO_MEMORY; + init_struct->priority = DMA_PRIORITY_LOW; +} + +/*! + \brief initialize DMA channel + \param[in] dma_periph: DMAx(x=0,1) + \arg DMAx(x=0,1) + \param[in] channelx: specify which DMA channel is initialized + only one parameter can be selected which is shown as below: + \arg DMA0: DMA_CHx(x=0..6), DMA1: DMA_CHx(x=0..6) + \param[in] init_struct: the data needed to initialize DMA channel + periph_addr: peripheral base address + periph_width: DMA_PERIPHERAL_WIDTH_8BIT, DMA_PERIPHERAL_WIDTH_16BIT, DMA_PERIPHERAL_WIDTH_32BIT + periph_inc: DMA_PERIPH_INCREASE_ENABLE, DMA_PERIPH_INCREASE_DISABLE + memory_addr: memory base address + memory_width: DMA_MEMORY_WIDTH_8BIT, DMA_MEMORY_WIDTH_16BIT, DMA_MEMORY_WIDTH_32BIT + memory_inc: DMA_MEMORY_INCREASE_ENABLE, DMA_MEMORY_INCREASE_DISABLE + direction: DMA_PERIPHERAL_TO_MEMORY, DMA_MEMORY_TO_PERIPHERAL + number: the number of remaining data to be transferred by the DMA + priority: DMA_PRIORITY_LOW, DMA_PRIORITY_MEDIUM, DMA_PRIORITY_HIGH, DMA_PRIORITY_ULTRA_HIGH + \param[out] none + \retval none +*/ +void dma_init(uint32_t dma_periph, dma_channel_enum channelx, dma_parameter_struct *init_struct) +{ + uint32_t ctl; + + /* configure peripheral base address */ + DMA_CHPADDR(dma_periph, channelx) = init_struct->periph_addr; + + /* configure memory base address */ + DMA_CHMADDR(dma_periph, channelx) = init_struct->memory_addr; + + /* configure the number of remaining data to be transferred */ + DMA_CHCNT(dma_periph, channelx) = (init_struct->number & DMA_CHANNEL_CNT_MASK); + + /* configure peripheral transfer width,memory transfer width, */ + ctl = DMA_CHCTL(dma_periph, channelx); + ctl &= ~(DMA_CHXCTL_PWIDTH | DMA_CHXCTL_MWIDTH | DMA_CHXCTL_PRIO); + ctl |= (init_struct->periph_width | init_struct->memory_width | init_struct->priority); + DMA_CHCTL(dma_periph, channelx) = ctl; + + /* configure peripheral increasing mode */ + if(DMA_PERIPH_INCREASE_ENABLE == init_struct->periph_inc){ + DMA_CHCTL(dma_periph, channelx) |= DMA_CHXCTL_PNAGA; + }else{ + DMA_CHCTL(dma_periph, channelx) &= ~DMA_CHXCTL_PNAGA; + } + + /* configure memory increasing mode */ + if(DMA_MEMORY_INCREASE_ENABLE == init_struct->memory_inc){ + DMA_CHCTL(dma_periph, channelx) |= DMA_CHXCTL_MNAGA; + }else{ + DMA_CHCTL(dma_periph, channelx) &= ~DMA_CHXCTL_MNAGA; + } + + /* configure the direction of data transfer */ + if(DMA_PERIPHERAL_TO_MEMORY == init_struct->direction){ + DMA_CHCTL(dma_periph, channelx) &= ~DMA_CHXCTL_DIR; + }else{ + DMA_CHCTL(dma_periph, channelx) |= DMA_CHXCTL_DIR; + } +} + +/*! + \brief enable DMA circulation mode + \param[in] dma_periph: DMAx(x=0,1) + \arg DMAx(x=0,1) + \param[in] channelx: specify which DMA channel + only one parameter can be selected which is shown as below: + \arg DMA0: DMA_CHx(x=0..6), DMA1: DMA_CHx(x=0..6) + \param[out] none + \retval none +*/ +void dma_circulation_enable(uint32_t dma_periph, dma_channel_enum channelx) +{ + DMA_CHCTL(dma_periph, channelx) |= DMA_CHXCTL_CMEN; +} + +/*! + \brief disable DMA circulation mode + \param[in] dma_periph: DMAx(x=0,1) + \arg DMAx(x=0,1) + \param[in] channelx: specify which DMA channel + only one parameter can be selected which is shown as below: + \arg DMA0: DMA_CHx(x=0..6), DMA1: DMA_CHx(x=0..6) + \param[out] none + \retval none +*/ +void dma_circulation_disable(uint32_t dma_periph, dma_channel_enum channelx) +{ + DMA_CHCTL(dma_periph, channelx) &= ~DMA_CHXCTL_CMEN; +} + +/*! + \brief enable memory to memory mode + \param[in] dma_periph: DMAx(x=0,1) + \arg DMAx(x=0,1) + \param[in] channelx: specify which DMA channel + only one parameter can be selected which is shown as below: + \arg DMA0: DMA_CHx(x=0..6), DMA1: DMA_CHx(x=0..6) + \param[out] none + \retval none +*/ +void dma_memory_to_memory_enable(uint32_t dma_periph, dma_channel_enum channelx) +{ + DMA_CHCTL(dma_periph, channelx) |= DMA_CHXCTL_M2M; +} + +/*! + \brief disable memory to memory mode + \param[in] dma_periph: DMAx(x=0,1) + \arg DMAx(x=0,1) + \param[in] channelx: specify which DMA channel + only one parameter can be selected which is shown as below: + \arg DMA0: DMA_CHx(x=0..6), DMA1: DMA_CHx(x=0..6) + \param[out] none + \retval none +*/ +void dma_memory_to_memory_disable(uint32_t dma_periph, dma_channel_enum channelx) +{ + DMA_CHCTL(dma_periph, channelx) &= ~DMA_CHXCTL_M2M; +} + +/*! + \brief enable DMA channel + \param[in] dma_periph: DMAx(x=0,1) + \arg DMAx(x=0,1) + \param[in] channelx: specify which DMA channel + only one parameter can be selected which is shown as below: + \arg DMA0: DMA_CHx(x=0..6), DMA1: DMA_CHx(x=0..6) + \param[out] none + \retval none +*/ +void dma_channel_enable(uint32_t dma_periph, dma_channel_enum channelx) +{ + DMA_CHCTL(dma_periph, channelx) |= DMA_CHXCTL_CHEN; +} + +/*! + \brief disable DMA channel + \param[in] dma_periph: DMAx(x=0,1) + \arg DMAx(x=0,1) + \param[in] channelx: specify which DMA channel + only one parameter can be selected which is shown as below: + \arg DMA0: DMA_CHx(x=0..6), DMA1: DMA_CHx(x=0..6) + \param[out] none + \retval none +*/ +void dma_channel_disable(uint32_t dma_periph, dma_channel_enum channelx) +{ + DMA_CHCTL(dma_periph, channelx) &= ~DMA_CHXCTL_CHEN; +} + +/*! + \brief set DMA peripheral base address + \param[in] dma_periph: DMAx(x=0,1) + \arg DMAx(x=0,1) + \param[in] channelx: specify which DMA channel to set peripheral base address + only one parameter can be selected which is shown as below: + \arg DMA0: DMA_CHx(x=0..6), DMA1: DMA_CHx(x=0..6) + \param[in] address: peripheral base address + \param[out] none + \retval none +*/ +void dma_periph_address_config(uint32_t dma_periph, dma_channel_enum channelx, uint32_t address) +{ + DMA_CHPADDR(dma_periph, channelx) = address; +} + +/*! + \brief set DMA memory base address + \param[in] dma_periph: DMAx(x=0,1) + \arg DMAx(x=0,1) + \param[in] channelx: specify which DMA channel to set memory base address + only one parameter can be selected which is shown as below: + \arg DMA0: DMA_CHx(x=0..6), DMA1: DMA_CHx(x=0..6) + \param[in] address: memory base address + \param[out] none + \retval none +*/ +void dma_memory_address_config(uint32_t dma_periph, dma_channel_enum channelx, uint32_t address) +{ + DMA_CHMADDR(dma_periph, channelx) = address; +} + +/*! + \brief set the number of remaining data to be transferred by the DMA + \param[in] dma_periph: DMAx(x=0,1) + \arg DMAx(x=0,1) + \param[in] channelx: specify which DMA channel to set number + only one parameter can be selected which is shown as below: + \arg DMA0: DMA_CHx(x=0..6), DMA1: DMA_CHx(x=0..6) + \param[in] number: the number of remaining data to be transferred by the DMA + \arg 0x0000-0xFFFF + \param[out] none + \retval none +*/ +void dma_transfer_number_config(uint32_t dma_periph, dma_channel_enum channelx, uint32_t number) +{ + DMA_CHCNT(dma_periph, channelx) = (number & DMA_CHANNEL_CNT_MASK); +} + +/*! + \brief get the number of remaining data to be transferred by the DMA + \param[in] dma_periph: DMAx(x=0,1) + \arg DMAx(x=0,1) + \param[in] channelx: specify which DMA channel to set number + only one parameter can be selected which is shown as below: + \arg DMA0: DMA_CHx(x=0..6), DMA1: DMA_CHx(x=0..6) + \param[out] none + \retval uint32_t: the number of remaining data to be transferred by the DMA +*/ +uint32_t dma_transfer_number_get(uint32_t dma_periph, dma_channel_enum channelx) +{ + return (uint32_t)DMA_CHCNT(dma_periph, channelx); +} + +/*! + \brief configure priority level of DMA channel + \param[in] dma_periph: DMAx(x=0,1) + \arg DMAx(x=0,1) + \param[in] channelx: specify which DMA channel + only one parameter can be selected which is shown as below: + \arg DMA0: DMA_CHx(x=0..6), DMA1: DMA_CHx(x=0..6) + \param[in] priority: priority Level of this channel + only one parameter can be selected which is shown as below: + \arg DMA_PRIORITY_LOW: low priority + \arg DMA_PRIORITY_MEDIUM: medium priority + \arg DMA_PRIORITY_HIGH: high priority + \arg DMA_PRIORITY_ULTRA_HIGH: ultra high priority + \param[out] none + \retval none +*/ +void dma_priority_config(uint32_t dma_periph, dma_channel_enum channelx, uint32_t priority) +{ + uint32_t ctl; + + /* acquire DMA_CHxCTL register */ + ctl = DMA_CHCTL(dma_periph, channelx); + /* assign regiser */ + ctl &= ~DMA_CHXCTL_PRIO; + ctl |= priority; + DMA_CHCTL(dma_periph, channelx) = ctl; +} + +/*! + \brief configure transfer data size of memory + \param[in] dma_periph: DMAx(x=0,1) + \arg DMAx(x=0,1) + \param[in] channelx: specify which DMA channel + only one parameter can be selected which is shown as below: + \arg DMA0: DMA_CHx(x=0..6), DMA1: DMA_CHx(x=0..6) + \param[in] mwidth: transfer data width of memory + only one parameter can be selected which is shown as below: + \arg DMA_MEMORY_WIDTH_8BIT: transfer data width of memory is 8-bit + \arg DMA_MEMORY_WIDTH_16BIT: transfer data width of memory is 16-bit + \arg DMA_MEMORY_WIDTH_32BIT: transfer data width of memory is 32-bit + \param[out] none + \retval none +*/ +void dma_memory_width_config(uint32_t dma_periph, dma_channel_enum channelx, uint32_t mwidth) +{ + uint32_t ctl; + + /* acquire DMA_CHxCTL register */ + ctl = DMA_CHCTL(dma_periph, channelx); + /* assign regiser */ + ctl &= ~DMA_CHXCTL_MWIDTH; + ctl |= mwidth; + DMA_CHCTL(dma_periph, channelx) = ctl; +} + +/*! + \brief configure transfer data size of peripheral + \param[in] dma_periph: DMAx(x=0,1) + \arg DMAx(x=0,1) + \param[in] channelx: specify which DMA channel + only one parameter can be selected which is shown as below: + \arg DMA0: DMA_CHx(x=0..6), DMA1: DMA_CHx(x=0..6) + \param[in] pwidth: transfer data width of peripheral + only one parameter can be selected which is shown as below: + \arg DMA_PERIPHERAL_WIDTH_8BIT: transfer data width of peripheral is 8-bit + \arg DMA_PERIPHERAL_WIDTH_16BIT: transfer data width of peripheral is 16-bit + \arg DMA_PERIPHERAL_WIDTH_32BIT: transfer data width of peripheral is 32-bit + \param[out] none + \retval none +*/ +void dma_periph_width_config(uint32_t dma_periph, dma_channel_enum channelx, uint32_t pwidth) +{ + uint32_t ctl; + + /* acquire DMA_CHxCTL register */ + ctl = DMA_CHCTL(dma_periph, channelx); + /* assign regiser */ + ctl &= ~DMA_CHXCTL_PWIDTH; + ctl |= pwidth; + DMA_CHCTL(dma_periph, channelx) = ctl; +} + +/*! + \brief enable next address increasement algorithm of memory + \param[in] dma_periph: DMAx(x=0,1) + \arg DMAx(x=0,1) + \param[in] channelx: specify which DMA channel + only one parameter can be selected which is shown as below: + \arg DMA0: DMA_CHx(x=0..6), DMA1: DMA_CHx(x=0..6) + \param[out] none + \retval none +*/ +void dma_memory_increase_enable(uint32_t dma_periph, dma_channel_enum channelx) +{ + DMA_CHCTL(dma_periph, channelx) |= DMA_CHXCTL_MNAGA; +} + +/*! + \brief disable next address increasement algorithm of memory + \param[in] dma_periph: DMAx(x=0,1) + \arg DMAx(x=0,1) + \param[in] channelx: specify which DMA channel + only one parameter can be selected which is shown as below: + \arg DMA0: DMA_CHx(x=0..6), DMA1: DMA_CHx(x=0..6) + \param[out] none + \retval none +*/ +void dma_memory_increase_disable(uint32_t dma_periph, dma_channel_enum channelx) +{ + DMA_CHCTL(dma_periph, channelx) &= ~DMA_CHXCTL_MNAGA; +} + +/*! + \brief enable next address increasement algorithm of peripheral + \param[in] dma_periph: DMAx(x=0,1) + \arg DMAx(x=0,1) + \param[in] channelx: specify which DMA channel + only one parameter can be selected which is shown as below: + \arg DMA0: DMA_CHx(x=0..6), DMA1: DMA_CHx(x=0..6) + \param[out] none + \retval none +*/ +void dma_periph_increase_enable(uint32_t dma_periph, dma_channel_enum channelx) +{ + DMA_CHCTL(dma_periph, channelx) |= DMA_CHXCTL_PNAGA; +} + +/*! + \brief disable next address increasement algorithm of peripheral + \param[in] dma_periph: DMAx(x=0,1) + \arg DMAx(x=0,1) + \param[in] channelx: specify which DMA channel + only one parameter can be selected which is shown as below: + \arg DMA0: DMA_CHx(x=0..6), DMA1: DMA_CHx(x=0..6) + \param[out] none + \retval none +*/ +void dma_periph_increase_disable(uint32_t dma_periph, dma_channel_enum channelx) +{ + DMA_CHCTL(dma_periph, channelx) &= ~DMA_CHXCTL_PNAGA; +} + +/*! + \brief configure the direction of data transfer on the channel + \param[in] dma_periph: DMAx(x=0,1) + \arg DMAx(x=0,1) + \param[in] channelx: specify which DMA channel + only one parameter can be selected which is shown as below: + \arg DMA0: DMA_CHx(x=0..6), DMA1: DMA_CHx(x=0..6) + \param[in] direction: specify the direction of data transfer + only one parameter can be selected which is shown as below: + \arg DMA_PERIPHERAL_TO_MEMORY: read from peripheral and write to memory + \arg DMA_MEMORY_TO_PERIPHERAL: read from memory and write to peripheral + \param[out] none + \retval none +*/ +void dma_transfer_direction_config(uint32_t dma_periph, dma_channel_enum channelx, uint8_t direction) +{ + if(DMA_PERIPHERAL_TO_MEMORY == direction){ + DMA_CHCTL(dma_periph, channelx) &= ~DMA_CHXCTL_DIR; + }else{ + DMA_CHCTL(dma_periph, channelx) |= DMA_CHXCTL_DIR; + } +} + +/*! + \brief check DMA flag is set or not + \param[in] dma_periph: DMAx(x=0,1) + \arg DMAx(x=0,1) + \param[in] channelx: specify which DMA channel to get flag + only one parameter can be selected which is shown as below: + \arg DMA0: DMA_CHx(x=0..6), DMA1: DMA_CHx(x=0..6) + \param[in] flag: specify get which flag + only one parameter can be selected which is shown as below: + \arg DMA_FLAG_G: global interrupt flag of channel + \arg DMA_FLAG_FTF: full transfer finish flag of channel + \arg DMA_FLAG_HTF: half transfer finish flag of channel + \arg DMA_FLAG_ERR: error flag of channel + \param[out] none + \retval FlagStatus: SET or RESET +*/ +FlagStatus dma_flag_get(uint32_t dma_periph, dma_channel_enum channelx, uint32_t flag) +{ + FlagStatus reval; + + /* check whether the flag is set or not */ + if(RESET != (DMA_INTF(dma_periph) & DMA_FLAG_ADD(flag, channelx))){ + reval = SET; + }else{ + reval = RESET; + } + + return reval; +} + +/*! + \brief clear the flag of a DMA channel + \param[in] dma_periph: DMAx(x=0,1) + \arg DMAx(x=0,1) + \param[in] channelx: specify which DMA channel to clear flag + only one parameter can be selected which is shown as below: + \arg DMA0: DMA_CHx(x=0..6), DMA1: DMA_CHx(x=0..6) + \param[in] flag: specify get which flag + only one parameter can be selected which is shown as below: + \arg DMA_FLAG_G: global interrupt flag of channel + \arg DMA_FLAG_FTF: full transfer finish flag of channel + \arg DMA_FLAG_HTF: half transfer finish flag of channel + \arg DMA_FLAG_ERR: error flag of channel + \param[out] none + \retval none +*/ +void dma_flag_clear(uint32_t dma_periph, dma_channel_enum channelx, uint32_t flag) +{ + DMA_INTC(dma_periph) |= DMA_FLAG_ADD(flag, channelx); +} + +/*! + \brief check DMA flag and interrupt enable bit is set or not + \param[in] dma_periph: DMAx(x=0,1) + \arg DMAx(x=0,1) + \param[in] channelx: specify which DMA channel to get flag + only one parameter can be selected which is shown as below: + \arg DMA0: DMA_CHx(x=0..6), DMA1: DMA_CHx(x=0..6) + \param[in] flag: specify get which flag + only one parameter can be selected which is shown as below: + \arg DMA_INT_FLAG_G: global interrupt flag of channel + \arg DMA_INT_FLAG_FTF: full transfer finish interrupt flag of channel + \arg DMA_INT_FLAG_HTF: half transfer finish interrupt flag of channel + \arg DMA_INT_FLAG_ERR: error interrupt flag of channel + \param[out] none + \retval FlagStatus: SET or RESET +*/ +FlagStatus dma_interrupt_flag_get(uint32_t dma_periph, dma_channel_enum channelx, uint32_t flag) +{ + uint32_t interrupt_enable = 0U, interrupt_flag = 0U; + uint32_t gif_check = 0x0FU, gif_enable = 0x0EU; + + switch(flag){ + case DMA_INT_FLAG_FTF: + /* check whether the full transfer finish interrupt flag is set and enabled */ + interrupt_flag = DMA_INTF(dma_periph) & DMA_FLAG_ADD(flag, channelx); + interrupt_flag = interrupt_flag >> ((channelx) * 4U); + interrupt_enable = DMA_CHCTL(dma_periph, channelx) & DMA_CHXCTL_FTFIE; + break; + case DMA_INT_FLAG_HTF: + /* check whether the half transfer finish interrupt flag is set and enabled */ + interrupt_flag = DMA_INTF(dma_periph) & DMA_FLAG_ADD(flag, channelx); + interrupt_flag = interrupt_flag >> ((channelx) * 4U); + interrupt_enable = DMA_CHCTL(dma_periph, channelx) & DMA_CHXCTL_HTFIE; + break; + case DMA_INT_FLAG_ERR: + /* check whether the error interrupt flag is set and enabled */ + interrupt_flag = DMA_INTF(dma_periph) & DMA_FLAG_ADD(flag, channelx); + interrupt_flag = interrupt_flag >> ((channelx) * 4U); + interrupt_enable = DMA_CHCTL(dma_periph, channelx) & DMA_CHXCTL_ERRIE; + break; + case DMA_INT_FLAG_G: + interrupt_flag = DMA_INTF(dma_periph) & DMA_FLAG_ADD(gif_check, channelx); + interrupt_flag = interrupt_flag >> ((channelx) * 4U); + interrupt_enable = DMA_CHCTL(dma_periph, channelx) & gif_enable; + break; + default: + DMA_WRONG_HANDLE + } + + /* when the interrupt flag is set and enabled, return SET */ + if(interrupt_flag && interrupt_enable){ + return SET; + }else{ + return RESET; + } +} + +/*! + \brief clear DMA a channel flag + \param[in] dma_periph: DMAx(x=0,1) + \arg DMAx(x=0,1) + \param[in] channelx: specify which DMA channel to clear flag + only one parameter can be selected which is shown as below: + \arg DMA0: DMA_CHx(x=0..6), DMA1: DMA_CHx(x=0..6) + \param[in] flag: specify get which flag + only one parameter can be selected which is shown as below: + \arg DMA_INT_FLAG_G: global interrupt flag of channel + \arg DMA_INT_FLAG_FTF: full transfer finish interrupt flag of channel + \arg DMA_INT_FLAG_HTF: half transfer finish interrupt flag of channel + \arg DMA_INT_FLAG_ERR: error interrupt flag of channel + \param[out] none + \retval none +*/ +void dma_interrupt_flag_clear(uint32_t dma_periph, dma_channel_enum channelx, uint32_t flag) +{ + DMA_INTC(dma_periph) |= DMA_FLAG_ADD(flag, channelx); +} + +/*! + \brief enable DMA interrupt + \param[in] dma_periph: DMAx(x=0,1) + \arg DMAx(x=0,1) + \param[in] channelx: specify which DMA channel + only one parameter can be selected which is shown as below: + \arg DMA0: DMA_CHx(x=0..6), DMA1: DMA_CHx(x=0..6) + \param[in] source: specify which interrupt to enbale + one or more parameters can be selected which are shown as below + \arg DMA_INT_FTF: channel full transfer finish interrupt + \arg DMA_INT_HTF: channel half transfer finish interrupt + \arg DMA_INT_ERR: channel error interrupt + \param[out] none + \retval none +*/ +void dma_interrupt_enable(uint32_t dma_periph, dma_channel_enum channelx, uint32_t source) +{ + DMA_CHCTL(dma_periph, channelx) |= source; +} + +/*! + \brief disable DMA interrupt + \param[in] dma_periph: DMAx(x=0,1) + \arg DMAx(x=0,1) + \param[in] channelx: specify which DMA channel + only one parameter can be selected which is shown as below: + \arg DMA0: DMA_CHx(x=0..6), DMA1: DMA_CHx(x=0..6) + \param[in] source: specify which interrupt to disbale + one or more parameters can be selected which are shown as below + \arg DMA_INT_FTF: channel full transfer finish interrupt + \arg DMA_INT_HTF: channel half transfer finish interrupt + \arg DMA_INT_ERR: channel error interrupt + \param[out] none + \retval none +*/ +void dma_interrupt_disable(uint32_t dma_periph, dma_channel_enum channelx, uint32_t source) +{ + DMA_CHCTL(dma_periph, channelx) &= ~source; +} + +/*! + \brief enable the DMA1 channel 5 Full_Data transfer mode + \param[in] none + \param[out] none + \retval none +*/ +void dma_1_channel_5_fulldata_transfer_enable(void) +{ + DMA_ACFG |= DMA_ACFG_FD_CH5EN; +} + +/*! + \brief disable the DMA1 channel 5 Full_Data transfer mode + \param[in] none + \param[out] none + \retval none +*/ +void dma_1_channel_5_fulldata_transfer_disable(void) +{ + DMA_ACFG &= ~DMA_ACFG_FD_CH5EN; +} diff --git a/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_standard_peripheral/Source/gd32f20x_enet.c b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_standard_peripheral/Source/gd32f20x_enet.c new file mode 100644 index 0000000000..90d47a3f69 --- /dev/null +++ b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_standard_peripheral/Source/gd32f20x_enet.c @@ -0,0 +1,3079 @@ +/*! + \file gd32f20x_enet.c + \brief ENET driver + + \version 2015-07-15, V1.0.0, firmware for GD32F20x + \version 2017-06-05, V2.0.0, firmware for GD32F20x + \version 2018-10-31, V2.1.0, firmware for GD32F20x + \version 2020-09-30, V2.2.0, firmware for GD32F20x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "gd32f20x_enet.h" + +#ifdef GD32F20X_CL + +#if defined (__CC_ARM) /*!< ARM compiler */ +__align(4) +enet_descriptors_struct rxdesc_tab[ENET_RXBUF_NUM]; /*!< ENET RxDMA descriptor */ +__align(4) +enet_descriptors_struct txdesc_tab[ENET_TXBUF_NUM]; /*!< ENET TxDMA descriptor */ +__align(4) +uint8_t rx_buff[ENET_RXBUF_NUM][ENET_RXBUF_SIZE]; /*!< ENET receive buffer */ +__align(4) +uint8_t tx_buff[ENET_TXBUF_NUM][ENET_TXBUF_SIZE]; /*!< ENET transmit buffer */ + +#elif defined ( __ICCARM__ ) /*!< IAR compiler */ +#pragma data_alignment=4 +enet_descriptors_struct rxdesc_tab[ENET_RXBUF_NUM]; /*!< ENET RxDMA descriptor */ +#pragma data_alignment=4 +enet_descriptors_struct txdesc_tab[ENET_TXBUF_NUM]; /*!< ENET TxDMA descriptor */ +#pragma data_alignment=4 +uint8_t rx_buff[ENET_RXBUF_NUM][ENET_RXBUF_SIZE]; /*!< ENET receive buffer */ +#pragma data_alignment=4 +uint8_t tx_buff[ENET_TXBUF_NUM][ENET_TXBUF_SIZE]; /*!< ENET transmit buffer */ + +#elif defined (__GNUC__) /* GNU Compiler */ +enet_descriptors_struct rxdesc_tab[ENET_RXBUF_NUM] __attribute__ ((aligned (4))); /*!< ENET RxDMA descriptor */ +enet_descriptors_struct txdesc_tab[ENET_TXBUF_NUM] __attribute__ ((aligned (4))); /*!< ENET TxDMA descriptor */ +uint8_t rx_buff[ENET_RXBUF_NUM][ENET_RXBUF_SIZE] __attribute__ ((aligned (4))); /*!< ENET receive buffer */ +uint8_t tx_buff[ENET_TXBUF_NUM][ENET_TXBUF_SIZE] __attribute__ ((aligned (4))); /*!< ENET transmit buffer */ + +#endif /* __CC_ARM */ + +/* global transmit and receive descriptors pointers */ +enet_descriptors_struct *dma_current_txdesc; +enet_descriptors_struct *dma_current_rxdesc; + +/* structure pointer of ptp descriptor for normal mode */ +enet_descriptors_struct *dma_current_ptp_txdesc = NULL; +enet_descriptors_struct *dma_current_ptp_rxdesc = NULL; + +/* init structure parameters for ENET initialization */ +static enet_initpara_struct enet_initpara ={0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; + +static uint32_t enet_unknow_err = 0U; + +/* array of register offset for debug information get */ +static const uint16_t enet_reg_tab[] = { +0x0000, 0x0004, 0x0008, 0x000C, 0x0010, 0x0014, 0x0018, 0x1080, 0x001C, 0x0028, 0x002C, +0x0038, 0x003C, 0x0040, 0x0044, 0x0048, 0x004C, 0x0050, 0x0054, 0x0058, 0x005C, + +0x0100, 0x0104, 0x0108, 0x010C, 0x0110, 0x014C, 0x0150, 0x0168, 0x0194, 0x0198, 0x01C4, + +0x0700, 0x0704,0x0708, 0x070C, 0x0710, 0x0714, 0x0718, 0x071C, 0x0720, + +0x1000, 0x1004, 0x1008, 0x100C, 0x1010, 0x1014, 0x1018, 0x101C, 0x1020, 0x1048, 0x104C, +0x1050, 0x1054}; + + +/*! + \brief deinitialize the ENET, and reset structure parameters for ENET initialization + \param[in] none + \param[out] none + \retval none +*/ +void enet_deinit(void) +{ + rcu_periph_reset_enable(RCU_ENETRST); + rcu_periph_reset_disable(RCU_ENETRST); + enet_initpara_reset(); +} + +/*! + \brief configure the parameters which are usually less cared for initialization + note -- this function must be called before enet_init(), otherwise + configuration will be no effect + \param[in] option: different function option, which is related to several parameters, + only one parameter can be selected which is shown as below, refer to enet_option_enum + \arg FORWARD_OPTION: choose to configure the frame forward related parameters + \arg DMABUS_OPTION: choose to configure the DMA bus mode related parameters + \arg DMA_MAXBURST_OPTION: choose to configure the DMA max burst related parameters + \arg DMA_ARBITRATION_OPTION: choose to configure the DMA arbitration related parameters + \arg STORE_OPTION: choose to configure the store forward mode related parameters + \arg DMA_OPTION: choose to configure the DMA descriptor related parameters + \arg VLAN_OPTION: choose to configure vlan related parameters + \arg FLOWCTL_OPTION: choose to configure flow control related parameters + \arg HASHH_OPTION: choose to configure hash high + \arg HASHL_OPTION: choose to configure hash low + \arg FILTER_OPTION: choose to configure frame filter related parameters + \arg HALFDUPLEX_OPTION: choose to configure halfduplex mode related parameters + \arg TIMER_OPTION: choose to configure time counter related parameters + \arg INTERFRAMEGAP_OPTION: choose to configure the inter frame gap related parameters + \param[in] para: the related parameters according to the option + all the related parameters should be configured which are shown as below + FORWARD_OPTION related parameters: + - ENET_AUTO_PADCRC_DROP_ENABLE/ ENET_AUTO_PADCRC_DROP_DISABLE ; + - ENET_FORWARD_ERRFRAMES_ENABLE/ ENET_FORWARD_ERRFRAMES_DISABLE ; + - ENET_FORWARD_UNDERSZ_GOODFRAMES_ENABLE/ ENET_FORWARD_UNDERSZ_GOODFRAMES_DISABLE . + DMABUS_OPTION related parameters: + - ENET_ADDRESS_ALIGN_ENABLE/ ENET_ADDRESS_ALIGN_DISABLE ; + - ENET_FIXED_BURST_ENABLE/ ENET_FIXED_BURST_DISABLE ; + DMA_MAXBURST_OPTION related parameters: + - ENET_RXDP_1BEAT/ ENET_RXDP_2BEAT/ ENET_RXDP_4BEAT/ + ENET_RXDP_8BEAT/ ENET_RXDP_16BEAT/ ENET_RXDP_32BEAT/ + ENET_RXDP_4xPGBL_4BEAT/ ENET_RXDP_4xPGBL_8BEAT/ + ENET_RXDP_4xPGBL_16BEAT/ ENET_RXDP_4xPGBL_32BEAT/ + ENET_RXDP_4xPGBL_64BEAT/ ENET_RXDP_4xPGBL_128BEAT ; + - ENET_PGBL_1BEAT/ ENET_PGBL_2BEAT/ ENET_PGBL_4BEAT/ + ENET_PGBL_8BEAT/ ENET_PGBL_16BEAT/ ENET_PGBL_32BEAT/ + ENET_PGBL_4xPGBL_4BEAT/ ENET_PGBL_4xPGBL_8BEAT/ + ENET_PGBL_4xPGBL_16BEAT/ ENET_PGBL_4xPGBL_32BEAT/ + ENET_PGBL_4xPGBL_64BEAT/ ENET_PGBL_4xPGBL_128BEAT ; + - ENET_RXTX_DIFFERENT_PGBL/ ENET_RXTX_SAME_PGBL ; + DMA_ARBITRATION_OPTION related parameters: + - ENET_ARBITRATION_RXPRIORTX + - ENET_ARBITRATION_RXTX_1_1/ ENET_ARBITRATION_RXTX_2_1/ + ENET_ARBITRATION_RXTX_3_1/ ENET_ARBITRATION_RXTX_4_1/. + STORE_OPTION related parameters: + - ENET_RX_MODE_STOREFORWARD/ ENET_RX_MODE_CUTTHROUGH ; + - ENET_TX_MODE_STOREFORWARD/ ENET_TX_MODE_CUTTHROUGH ; + - ENET_RX_THRESHOLD_64BYTES/ ENET_RX_THRESHOLD_32BYTES/ + ENET_RX_THRESHOLD_96BYTES/ ENET_RX_THRESHOLD_128BYTES ; + - ENET_TX_THRESHOLD_64BYTES/ ENET_TX_THRESHOLD_128BYTES/ + ENET_TX_THRESHOLD_192BYTES/ ENET_TX_THRESHOLD_256BYTES/ + ENET_TX_THRESHOLD_40BYTES/ ENET_TX_THRESHOLD_32BYTES/ + ENET_TX_THRESHOLD_24BYTES/ ENET_TX_THRESHOLD_16BYTES . + DMA_OPTION related parameters: + - ENET_FLUSH_RXFRAME_ENABLE/ ENET_FLUSH_RXFRAME_DISABLE ; + - ENET_SECONDFRAME_OPT_ENABLE/ ENET_SECONDFRAME_OPT_DISABLE . + VLAN_OPTION related parameters: + - ENET_VLANTAGCOMPARISON_12BIT/ ENET_VLANTAGCOMPARISON_16BIT ; + - MAC_VLT_VLTI(regval) . + FLOWCTL_OPTION related parameters: + - MAC_FCTL_PTM(regval) ; + - ENET_ZERO_QUANTA_PAUSE_ENABLE/ ENET_ZERO_QUANTA_PAUSE_DISABLE ; + - ENET_PAUSETIME_MINUS4/ ENET_PAUSETIME_MINUS28/ + ENET_PAUSETIME_MINUS144/ENET_PAUSETIME_MINUS256 ; + - ENET_MAC0_AND_UNIQUE_ADDRESS_PAUSEDETECT/ ENET_UNIQUE_PAUSEDETECT ; + - ENET_RX_FLOWCONTROL_ENABLE/ ENET_RX_FLOWCONTROL_DISABLE ; + - ENET_TX_FLOWCONTROL_ENABLE/ ENET_TX_FLOWCONTROL_DISABLE . + HASHH_OPTION related parameters: + - 0x0~0xFFFF FFFFU + HASHL_OPTION related parameters: + - 0x0~0xFFFF FFFFU + FILTER_OPTION related parameters: + - ENET_SRC_FILTER_NORMAL_ENABLE/ ENET_SRC_FILTER_INVERSE_ENABLE/ + ENET_SRC_FILTER_DISABLE ; + - ENET_DEST_FILTER_INVERSE_ENABLE/ ENET_DEST_FILTER_INVERSE_DISABLE ; + - ENET_MULTICAST_FILTER_HASH_OR_PERFECT/ ENET_MULTICAST_FILTER_HASH/ + ENET_MULTICAST_FILTER_PERFECT/ ENET_MULTICAST_FILTER_NONE ; + - ENET_UNICAST_FILTER_EITHER/ ENET_UNICAST_FILTER_HASH/ + ENET_UNICAST_FILTER_PERFECT ; + - ENET_PCFRM_PREVENT_ALL/ ENET_PCFRM_PREVENT_PAUSEFRAME/ + ENET_PCFRM_FORWARD_ALL/ ENET_PCFRM_FORWARD_FILTERED . + HALFDUPLEX_OPTION related parameters: + - ENET_CARRIERSENSE_ENABLE/ ENET_CARRIERSENSE_DISABLE ; + - ENET_RECEIVEOWN_ENABLE/ ENET_RECEIVEOWN_DISABLE ; + - ENET_RETRYTRANSMISSION_ENABLE/ ENET_RETRYTRANSMISSION_DISABLE ; + - ENET_BACKOFFLIMIT_10/ ENET_BACKOFFLIMIT_8/ + ENET_BACKOFFLIMIT_4/ ENET_BACKOFFLIMIT_1 ; + - ENET_DEFERRALCHECK_ENABLE/ ENET_DEFERRALCHECK_DISABLE . + TIMER_OPTION related parameters: + - ENET_WATCHDOG_ENABLE/ ENET_WATCHDOG_DISABLE ; + - ENET_JABBER_ENABLE/ ENET_JABBER_DISABLE ; + INTERFRAMEGAP_OPTION related parameters: + - ENET_INTERFRAMEGAP_96BIT/ ENET_INTERFRAMEGAP_88BIT/ + ENET_INTERFRAMEGAP_80BIT/ ENET_INTERFRAMEGAP_72BIT/ + ENET_INTERFRAMEGAP_64BIT/ ENET_INTERFRAMEGAP_56BIT/ + ENET_INTERFRAMEGAP_48BIT/ ENET_INTERFRAMEGAP_40BIT . + \param[out] none + \retval none +*/ +void enet_initpara_config(enet_option_enum option, uint32_t para) +{ + switch(option){ + case FORWARD_OPTION: + /* choose to configure forward_frame, and save the configuration parameters */ + enet_initpara.option_enable |= (uint32_t)FORWARD_OPTION; + enet_initpara.forward_frame = para; + break; + case DMABUS_OPTION: + /* choose to configure dmabus_mode, and save the configuration parameters */ + enet_initpara.option_enable |= (uint32_t)DMABUS_OPTION; + enet_initpara.dmabus_mode = para; + break; + case DMA_MAXBURST_OPTION: + /* choose to configure dma_maxburst, and save the configuration parameters */ + enet_initpara.option_enable |= (uint32_t)DMA_MAXBURST_OPTION; + enet_initpara.dma_maxburst = para; + break; + case DMA_ARBITRATION_OPTION: + /* choose to configure dma_arbitration, and save the configuration parameters */ + enet_initpara.option_enable |= (uint32_t)DMA_ARBITRATION_OPTION; + enet_initpara.dma_arbitration = para; + break; + case STORE_OPTION: + /* choose to configure store_forward_mode, and save the configuration parameters */ + enet_initpara.option_enable |= (uint32_t)STORE_OPTION; + enet_initpara.store_forward_mode = para; + break; + case DMA_OPTION: + /* choose to configure dma_function, and save the configuration parameters */ + enet_initpara.option_enable |= (uint32_t)DMA_OPTION; + enet_initpara.dma_function = para; + break; + case VLAN_OPTION: + /* choose to configure vlan_config, and save the configuration parameters */ + enet_initpara.option_enable |= (uint32_t)VLAN_OPTION; + enet_initpara.vlan_config = para; + break; + case FLOWCTL_OPTION: + /* choose to configure flow_control, and save the configuration parameters */ + enet_initpara.option_enable |= (uint32_t)FLOWCTL_OPTION; + enet_initpara.flow_control = para; + break; + case HASHH_OPTION: + /* choose to configure hashtable_high, and save the configuration parameters */ + enet_initpara.option_enable |= (uint32_t)HASHH_OPTION; + enet_initpara.hashtable_high = para; + break; + case HASHL_OPTION: + /* choose to configure hashtable_low, and save the configuration parameters */ + enet_initpara.option_enable |= (uint32_t)HASHL_OPTION; + enet_initpara.hashtable_low = para; + break; + case FILTER_OPTION: + /* choose to configure framesfilter_mode, and save the configuration parameters */ + enet_initpara.option_enable |= (uint32_t)FILTER_OPTION; + enet_initpara.framesfilter_mode = para; + break; + case HALFDUPLEX_OPTION: + /* choose to configure halfduplex_param, and save the configuration parameters */ + enet_initpara.option_enable |= (uint32_t)HALFDUPLEX_OPTION; + enet_initpara.halfduplex_param = para; + break; + case TIMER_OPTION: + /* choose to configure timer_config, and save the configuration parameters */ + enet_initpara.option_enable |= (uint32_t)TIMER_OPTION; + enet_initpara.timer_config = para; + break; + case INTERFRAMEGAP_OPTION: + /* choose to configure interframegap, and save the configuration parameters */ + enet_initpara.option_enable |= (uint32_t)INTERFRAMEGAP_OPTION; + enet_initpara.interframegap = para; + break; + default: + break; + } +} + +/*! + \brief initialize ENET peripheral with generally concerned parameters and the less cared + parameters + \param[in] mediamode: PHY mode and mac loopback configurations, only one parameter can be selected + which is shown as below, refer to enet_mediamode_enum + \arg ENET_AUTO_NEGOTIATION: PHY auto negotiation + \arg ENET_100M_FULLDUPLEX: 100Mbit/s, full-duplex + \arg ENET_100M_HALFDUPLEX: 100Mbit/s, half-duplex + \arg ENET_10M_FULLDUPLEX: 10Mbit/s, full-duplex + \arg ENET_10M_HALFDUPLEX: 10Mbit/s, half-duplex + \arg ENET_LOOPBACKMODE: MAC in loopback mode at the MII + \param[in] checksum: IP frame checksum offload function, only one parameter can be selected + which is shown as below, refer to enet_mediamode_enum + \arg ENET_NO_AUTOCHECKSUM: disable IP frame checksum function + \arg ENET_AUTOCHECKSUM_DROP_FAILFRAMES: enable IP frame checksum function + \arg ENET_AUTOCHECKSUM_ACCEPT_FAILFRAMES: enable IP frame checksum function, and the received frame + with only payload error but no other errors will not be dropped + \param[in] recept: frame filter function, only one parameter can be selected + which is shown as below, refer to enet_frmrecept_enum + \arg ENET_PROMISCUOUS_MODE: promiscuous mode enabled + \arg ENET_RECEIVEALL: all received frame are forwarded to application + \arg ENET_BROADCAST_FRAMES_PASS: the address filters pass all received broadcast frames + \arg ENET_BROADCAST_FRAMES_DROP: the address filters filter all incoming broadcast frames + \param[out] none + \retval ErrStatus: ERROR or SUCCESS +*/ +ErrStatus enet_init(enet_mediamode_enum mediamode, enet_chksumconf_enum checksum, enet_frmrecept_enum recept) +{ + uint32_t reg_value=0U, reg_temp = 0U, temp = 0U; + uint32_t media_temp = 0U; + uint32_t timeout = 0U; + uint16_t phy_value = 0U; + ErrStatus phy_state= ERROR, enet_state = ERROR; + + /* PHY interface configuration, configure SMI clock and reset PHY chip */ + if(ERROR == enet_phy_config()){ + _ENET_DELAY_(PHY_RESETDELAY); + if(ERROR == enet_phy_config()){ + return enet_state; + } + } + /* initialize ENET peripheral with generally concerned parameters */ + enet_default_init(); + + /* 1st, configure mediamode */ + media_temp = (uint32_t)mediamode; + /* if is PHY auto negotiation */ + if((uint32_t)ENET_AUTO_NEGOTIATION == media_temp){ + /* wait for PHY_LINKED_STATUS bit be set */ + do{ + enet_phy_write_read(ENET_PHY_READ, PHY_ADDRESS, PHY_REG_BSR, &phy_value); + phy_value &= PHY_LINKED_STATUS; + timeout++; + }while((RESET == phy_value) && (timeout < PHY_READ_TO)); + /* return ERROR due to timeout */ + if(PHY_READ_TO == timeout){ + return enet_state; + } + /* reset timeout counter */ + timeout = 0U; + + /* enable auto-negotiation */ + phy_value = PHY_AUTONEGOTIATION; + phy_state = enet_phy_write_read(ENET_PHY_WRITE, PHY_ADDRESS, PHY_REG_BCR, &phy_value); + if(!phy_state){ + /* return ERROR due to write timeout */ + return enet_state; + } + + /* wait for the PHY_AUTONEGO_COMPLETE bit be set */ + do{ + enet_phy_write_read(ENET_PHY_READ, PHY_ADDRESS, PHY_REG_BSR, &phy_value); + phy_value &= PHY_AUTONEGO_COMPLETE; + timeout++; + }while((RESET == phy_value) && (timeout < (uint32_t)PHY_READ_TO)); + /* return ERROR due to timeout */ + if(PHY_READ_TO == timeout){ + return enet_state; + } + /* reset timeout counter */ + timeout = 0U; + + /* read the result of the auto-negotiation */ + enet_phy_write_read(ENET_PHY_READ, PHY_ADDRESS, PHY_SR, &phy_value); + /* configure the duplex mode of MAC following the auto-negotiation result */ + if((uint16_t)RESET != (phy_value & PHY_DUPLEX_STATUS)){ + media_temp = ENET_MODE_FULLDUPLEX; + }else{ + media_temp = ENET_MODE_HALFDUPLEX; + } + /* configure the communication speed of MAC following the auto-negotiation result */ + if((uint16_t)RESET !=(phy_value & PHY_SPEED_STATUS)){ + media_temp |= ENET_SPEEDMODE_10M; + }else{ + media_temp |= ENET_SPEEDMODE_100M; + } + }else{ + phy_value = (uint16_t)((media_temp & ENET_MAC_CFG_DPM) >> 3); + phy_value |= (uint16_t)((media_temp & ENET_MAC_CFG_SPD) >> 1); + phy_state = enet_phy_write_read(ENET_PHY_WRITE, PHY_ADDRESS, PHY_REG_BCR, &phy_value); + if(!phy_state){ + /* return ERROR due to write timeout */ + return enet_state; + } + /* PHY configuration need some time */ + _ENET_DELAY_(PHY_CONFIGDELAY); + } + /* after configuring the PHY, use mediamode to configure registers */ + reg_value = ENET_MAC_CFG; + /* configure ENET_MAC_CFG register */ + reg_value &= (~(ENET_MAC_CFG_SPD |ENET_MAC_CFG_DPM |ENET_MAC_CFG_LBM)); + reg_value |= media_temp; + ENET_MAC_CFG = reg_value; + + + /* 2st, configure checksum */ + if(RESET != ((uint32_t)checksum & ENET_CHECKSUMOFFLOAD_ENABLE)){ + ENET_MAC_CFG |= ENET_CHECKSUMOFFLOAD_ENABLE; + + reg_value = ENET_DMA_CTL; + /* configure ENET_DMA_CTL register */ + reg_value &= ~ENET_DMA_CTL_DTCERFD; + reg_value |= ((uint32_t)checksum & ENET_DMA_CTL_DTCERFD); + ENET_DMA_CTL = reg_value; + } + + /* 3rd, configure recept */ + ENET_MAC_FRMF |= (uint32_t)recept; + + /* 4th, configure different function options */ + /* configure forward_frame related registers */ + if(RESET != (enet_initpara.option_enable & (uint32_t)FORWARD_OPTION)){ + reg_temp = enet_initpara.forward_frame; + + reg_value = ENET_MAC_CFG; + temp = reg_temp; + /* configure ENET_MAC_CFG register */ + reg_value &= (~ENET_MAC_CFG_APCD); + temp &= ENET_MAC_CFG_APCD; + reg_value |= temp; + ENET_MAC_CFG = reg_value; + + reg_value = ENET_DMA_CTL; + temp = reg_temp; + /* configure ENET_DMA_CTL register */ + reg_value &= (~(ENET_DMA_CTL_FERF |ENET_DMA_CTL_FUF)); + temp &= ((ENET_DMA_CTL_FERF | ENET_DMA_CTL_FUF)<<2); + reg_value |= (temp >> 2); + ENET_DMA_CTL = reg_value; + } + + /* configure dmabus_mode related registers */ + if(RESET != (enet_initpara.option_enable & (uint32_t)DMABUS_OPTION)){ + temp = enet_initpara.dmabus_mode; + + reg_value = ENET_DMA_BCTL; + /* configure ENET_DMA_BCTL register */ + reg_value &= ~(ENET_DMA_BCTL_AA | ENET_DMA_BCTL_FB \ + |ENET_DMA_BCTL_FPBL); + reg_value |= temp; + ENET_DMA_BCTL = reg_value; + } + + /* configure dma_maxburst related registers */ + if(RESET != (enet_initpara.option_enable & (uint32_t)DMA_MAXBURST_OPTION)){ + temp = enet_initpara.dma_maxburst; + + reg_value = ENET_DMA_BCTL; + /* configure ENET_DMA_BCTL register */ + reg_value &= ~(ENET_DMA_BCTL_RXDP| ENET_DMA_BCTL_PGBL | ENET_DMA_BCTL_UIP); + reg_value |= temp; + ENET_DMA_BCTL = reg_value; + } + + /* configure dma_arbitration related registers */ + if(RESET != (enet_initpara.option_enable & (uint32_t)DMA_ARBITRATION_OPTION)){ + temp = enet_initpara.dma_arbitration; + + reg_value = ENET_DMA_BCTL; + /* configure ENET_DMA_BCTL register */ + reg_value &= ~(ENET_DMA_BCTL_RTPR | ENET_DMA_BCTL_DAB); + reg_value |= temp; + ENET_DMA_BCTL = reg_value; + } + + /* configure store_forward_mode related registers */ + if(RESET != (enet_initpara.option_enable & (uint32_t)STORE_OPTION)){ + temp = enet_initpara.store_forward_mode; + + reg_value = ENET_DMA_CTL; + /* configure ENET_DMA_CTL register */ + reg_value &= ~(ENET_DMA_CTL_RSFD | ENET_DMA_CTL_TSFD| ENET_DMA_CTL_RTHC| ENET_DMA_CTL_TTHC); + reg_value |= temp; + ENET_DMA_CTL = reg_value; + } + + /* configure dma_function related registers */ + if(RESET != (enet_initpara.option_enable & (uint32_t)DMA_OPTION)){ + reg_temp = enet_initpara.dma_function; + + reg_value = ENET_DMA_CTL; + /* configure ENET_DMA_CTL register */ + reg_value &= (~(ENET_DMA_CTL_DAFRF |ENET_DMA_CTL_OSF)); + reg_value |= reg_temp; + ENET_DMA_CTL = reg_value; + } + + /* configure vlan_config related registers */ + if(RESET != (enet_initpara.option_enable & (uint32_t)VLAN_OPTION)){ + reg_temp = enet_initpara.vlan_config; + + reg_value = ENET_MAC_VLT; + /* configure ENET_MAC_VLT register */ + reg_value &= ~(ENET_MAC_VLT_VLTI | ENET_MAC_VLT_VLTC); + reg_value |= reg_temp; + ENET_MAC_VLT = reg_value; + } + + /* configure flow_control related registers */ + if(RESET != (enet_initpara.option_enable & (uint32_t)FLOWCTL_OPTION)){ + reg_temp = enet_initpara.flow_control; + + reg_value = ENET_MAC_FCTL; + temp = reg_temp; + /* configure ENET_MAC_FCTL register */ + reg_value &= ~(ENET_MAC_FCTL_PTM |ENET_MAC_FCTL_DZQP |ENET_MAC_FCTL_PLTS \ + | ENET_MAC_FCTL_UPFDT |ENET_MAC_FCTL_RFCEN |ENET_MAC_FCTL_TFCEN); + temp &= (ENET_MAC_FCTL_PTM |ENET_MAC_FCTL_DZQP |ENET_MAC_FCTL_PLTS \ + | ENET_MAC_FCTL_UPFDT |ENET_MAC_FCTL_RFCEN |ENET_MAC_FCTL_TFCEN); + reg_value |= temp; + ENET_MAC_FCTL = reg_value; + + reg_value = ENET_MAC_FCTH; + temp = reg_temp; + /* configure ENET_MAC_FCTH register */ + reg_value &= ~(ENET_MAC_FCTH_RFA |ENET_MAC_FCTH_RFD); + temp &= ((ENET_MAC_FCTH_RFA | ENET_MAC_FCTH_RFD )<<8); + reg_value |= (temp >> 8); + ENET_MAC_FCTH = reg_value; + } + + /* configure hashtable_high related registers */ + if(RESET != (enet_initpara.option_enable & (uint32_t)HASHH_OPTION)){ + ENET_MAC_HLH = enet_initpara.hashtable_high; + } + + /* configure hashtable_low related registers */ + if(RESET != (enet_initpara.option_enable & (uint32_t)HASHL_OPTION)){ + ENET_MAC_HLL = enet_initpara.hashtable_low; + } + + /* configure framesfilter_mode related registers */ + if(RESET != (enet_initpara.option_enable & (uint32_t)FILTER_OPTION)){ + reg_temp = enet_initpara.framesfilter_mode; + + reg_value = ENET_MAC_FRMF; + /* configure ENET_MAC_FRMF register */ + reg_value &= ~(ENET_MAC_FRMF_SAFLT | ENET_MAC_FRMF_SAIFLT | ENET_MAC_FRMF_DAIFLT \ + | ENET_MAC_FRMF_HMF | ENET_MAC_FRMF_HPFLT | ENET_MAC_FRMF_MFD \ + | ENET_MAC_FRMF_HUF | ENET_MAC_FRMF_PCFRM); + reg_value |= reg_temp; + ENET_MAC_FRMF = reg_value; + } + + /* configure halfduplex_param related registers */ + if(RESET != (enet_initpara.option_enable & (uint32_t)HALFDUPLEX_OPTION)){ + reg_temp = enet_initpara.halfduplex_param; + + reg_value = ENET_MAC_CFG; + /* configure ENET_MAC_CFG register */ + reg_value &= ~(ENET_MAC_CFG_CSD | ENET_MAC_CFG_ROD | ENET_MAC_CFG_RTD \ + | ENET_MAC_CFG_BOL | ENET_MAC_CFG_DFC); + reg_value |= reg_temp; + ENET_MAC_CFG = reg_value; + } + + /* configure timer_config related registers */ + if(RESET != (enet_initpara.option_enable & (uint32_t)TIMER_OPTION)){ + reg_temp = enet_initpara.timer_config; + + reg_value = ENET_MAC_CFG; + /* configure ENET_MAC_CFG register */ + reg_value &= ~(ENET_MAC_CFG_WDD | ENET_MAC_CFG_JBD); + reg_value |= reg_temp; + ENET_MAC_CFG = reg_value; + } + + /* configure interframegap related registers */ + if(RESET != (enet_initpara.option_enable & (uint32_t)INTERFRAMEGAP_OPTION)){ + reg_temp = enet_initpara.interframegap; + + reg_value = ENET_MAC_CFG; + /* configure ENET_MAC_CFG register */ + reg_value &= ~ENET_MAC_CFG_IGBS; + reg_value |= reg_temp; + ENET_MAC_CFG = reg_value; + } + + enet_state = SUCCESS; + return enet_state; +} + +/*! + \brief reset all core internal registers located in CLK_TX and CLK_RX + \param[in] none + \param[out] none + \retval ErrStatus: SUCCESS or ERROR +*/ +ErrStatus enet_software_reset(void) +{ + uint32_t timeout = 0U; + ErrStatus enet_state = ERROR; + uint32_t dma_flag; + + /* reset all core internal registers located in CLK_TX and CLK_RX */ + ENET_DMA_BCTL |= ENET_DMA_BCTL_SWR; + + /* wait for reset operation complete */ + do{ + dma_flag = (ENET_DMA_BCTL & ENET_DMA_BCTL_SWR); + timeout++; + }while((RESET != dma_flag) && (ENET_DELAY_TO != timeout)); + + /* reset operation complete */ + if(RESET == (ENET_DMA_BCTL & ENET_DMA_BCTL_SWR)){ + enet_state = SUCCESS; + } + + return enet_state; +} + +/*! + \brief check receive frame valid and return frame size + \param[in] none + \param[out] none + \retval size of received frame: 0x0 - 0x3FFF +*/ +uint32_t enet_rxframe_size_get(void) +{ + uint32_t size = 0U; + uint32_t status; + + /* get rdes0 information of current RxDMA descriptor */ + status = dma_current_rxdesc->status; + + /* if the desciptor is owned by DMA */ + if((uint32_t)RESET != (status & ENET_RDES0_DAV)){ + return 0U; + } + + /* if has any error, or the frame uses two or more descriptors */ + if((((uint32_t)RESET) != (status & ENET_RDES0_ERRS)) || + (((uint32_t)RESET) == (status & ENET_RDES0_LDES)) || + (((uint32_t)RESET) == (status & ENET_RDES0_FDES))){ + /* drop current receive frame */ + enet_rxframe_drop(); + + return 1U; + } + + /* if is an ethernet-type frame, and IP frame payload error occurred */ + if((((uint32_t)RESET) != (status & ENET_RDES0_FRMT)) && + (((uint32_t)RESET) != (status & ENET_RDES0_PCERR))){ + /* drop current receive frame */ + enet_rxframe_drop(); + + return 1U; + } + + /* if CPU owns current descriptor, no error occured, the frame uses only one descriptor */ + if((((uint32_t)RESET) == (status & ENET_RDES0_DAV)) && + (((uint32_t)RESET) == (status & ENET_RDES0_ERRS)) && + (((uint32_t)RESET) != (status & ENET_RDES0_LDES)) && + (((uint32_t)RESET) != (status & ENET_RDES0_FDES))){ + /* get the size of the received data including CRC */ + size = GET_RDES0_FRML(status); + /* substract the CRC size */ + size = size - 4U; + }else{ + enet_unknow_err++; + enet_rxframe_drop(); + + return 1U; + } + + /* return packet size */ + return size; +} + +/*! + \brief initialize the DMA Tx/Rx descriptors's parameters in chain mode + \param[in] direction: the descriptors which users want to init, refer to enet_dmadirection_enum, + only one parameter can be selected which is shown as below + \arg ENET_DMA_TX: DMA Tx descriptors + \arg ENET_DMA_RX: DMA Rx descriptors + \param[out] none + \retval none +*/ +void enet_descriptors_chain_init(enet_dmadirection_enum direction) +{ + uint32_t num = 0U, count = 0U, maxsize = 0U; + uint32_t desc_status = 0U, desc_bufsize = 0U; + enet_descriptors_struct *desc, *desc_tab; + uint8_t *buf; + + /* if want to initialize DMA Tx descriptors */ + if (ENET_DMA_TX == direction){ + /* save a copy of the DMA Tx descriptors */ + desc_tab = txdesc_tab; + buf = &tx_buff[0][0]; + count = ENET_TXBUF_NUM; + maxsize = ENET_TXBUF_SIZE; + + /* select chain mode */ + desc_status = ENET_TDES0_TCHM; + + /* configure DMA Tx descriptor table address register */ + ENET_DMA_TDTADDR = (uint32_t)desc_tab; + dma_current_txdesc = desc_tab; + }else{ + /* if want to initialize DMA Rx descriptors */ + /* save a copy of the DMA Rx descriptors */ + desc_tab = rxdesc_tab; + buf = &rx_buff[0][0]; + count = ENET_RXBUF_NUM; + maxsize = ENET_RXBUF_SIZE; + + /* enable receiving */ + desc_status = ENET_RDES0_DAV; + /* select receive chained mode and set buffer1 size */ + desc_bufsize = ENET_RDES1_RCHM | (uint32_t)ENET_RXBUF_SIZE; + + /* configure DMA Rx descriptor table address register */ + ENET_DMA_RDTADDR = (uint32_t)desc_tab; + dma_current_rxdesc = desc_tab; + } + dma_current_ptp_rxdesc = NULL; + dma_current_ptp_txdesc = NULL; + + /* configure each descriptor */ + for(num=0U; num < count; num++){ + /* get the pointer to the next descriptor of the descriptor table */ + desc = desc_tab + num; + + /* configure descriptors */ + desc->status = desc_status; + desc->control_buffer_size = desc_bufsize; + desc->buffer1_addr = (uint32_t)(&buf[num * maxsize]); + + /* if is not the last descriptor */ + if(num < (count - 1U)){ + /* configure the next descriptor address */ + desc->buffer2_next_desc_addr = (uint32_t)(desc_tab + num + 1U); + }else{ + /* when it is the last descriptor, the next descriptor address + equals to first descriptor address in descriptor table */ + desc->buffer2_next_desc_addr = (uint32_t) desc_tab; + } + } +} + +/*! + \brief initialize the DMA Tx/Rx descriptors's parameters in ring mode + \param[in] direction: the descriptors which users want to init, refer to enet_dmadirection_enum, + only one parameter can be selected which is shown as below + \arg ENET_DMA_TX: DMA Tx descriptors + \arg ENET_DMA_RX: DMA Rx descriptors + \param[out] none + \retval none +*/ +void enet_descriptors_ring_init(enet_dmadirection_enum direction) +{ + uint32_t num = 0U, count = 0U, maxsize = 0U; + uint32_t desc_status = 0U, desc_bufsize = 0U; + enet_descriptors_struct *desc; + enet_descriptors_struct *desc_tab; + uint8_t *buf; + + /* configure descriptor skip length */ + ENET_DMA_BCTL &= ~ENET_DMA_BCTL_DPSL; + ENET_DMA_BCTL |= DMA_BCTL_DPSL(0); + + /* if want to initialize DMA Tx descriptors */ + if (ENET_DMA_TX == direction){ + /* save a copy of the DMA Tx descriptors */ + desc_tab = txdesc_tab; + buf = &tx_buff[0][0]; + count = ENET_TXBUF_NUM; + maxsize = ENET_TXBUF_SIZE; + + /* configure DMA Tx descriptor table address register */ + ENET_DMA_TDTADDR = (uint32_t)desc_tab; + dma_current_txdesc = desc_tab; + }else{ + /* if want to initialize DMA Rx descriptors */ + /* save a copy of the DMA Rx descriptors */ + desc_tab = rxdesc_tab; + buf = &rx_buff[0][0]; + count = ENET_RXBUF_NUM; + maxsize = ENET_RXBUF_SIZE; + + /* enable receiving */ + desc_status = ENET_RDES0_DAV; + /* set buffer1 size */ + desc_bufsize = ENET_RXBUF_SIZE; + + /* configure DMA Rx descriptor table address register */ + ENET_DMA_RDTADDR = (uint32_t)desc_tab; + dma_current_rxdesc = desc_tab; + } + dma_current_ptp_rxdesc = NULL; + dma_current_ptp_txdesc = NULL; + + /* configure each descriptor */ + for(num=0U; num < count; num++){ + /* get the pointer to the next descriptor of the descriptor table */ + desc = desc_tab + num; + + /* configure descriptors */ + desc->status = desc_status; + desc->control_buffer_size = desc_bufsize; + desc->buffer1_addr = (uint32_t)(&buf[num * maxsize]); + + /* when it is the last descriptor */ + if(num == (count - 1U)){ + if (ENET_DMA_TX == direction){ + /* configure transmit end of ring mode */ + desc->status |= ENET_TDES0_TERM; + }else{ + /* configure receive end of ring mode */ + desc->control_buffer_size |= ENET_RDES1_RERM; + } + } + } +} + +/*! + \brief handle current received frame data to application buffer + \param[in] bufsize: the size of buffer which is the parameter in function + \param[out] buffer: pointer to the received frame data + note -- if the input is NULL, user should copy data in application by himself + \retval ErrStatus: SUCCESS or ERROR +*/ +ErrStatus enet_frame_receive(uint8_t *buffer, uint32_t bufsize) +{ + uint32_t offset = 0U, size = 0U; + + /* the descriptor is busy due to own by the DMA */ + if((uint32_t)RESET != (dma_current_rxdesc->status & ENET_RDES0_DAV)){ + return ERROR; + } + + + /* if buffer pointer is null, indicates that users has copied data in application */ + if(NULL != buffer){ + /* if no error occurs, and the frame uses only one descriptor */ + if((((uint32_t)RESET) == (dma_current_rxdesc->status & ENET_RDES0_ERRS)) && + (((uint32_t)RESET) != (dma_current_rxdesc->status & ENET_RDES0_LDES)) && + (((uint32_t)RESET) != (dma_current_rxdesc->status & ENET_RDES0_FDES))){ + /* get the frame length except CRC */ + size = GET_RDES0_FRML(dma_current_rxdesc->status); + size = size - 4U; + + /* to avoid situation that the frame size exceeds the buffer length */ + if(size > bufsize){ + return ERROR; + } + + /* copy data from Rx buffer to application buffer */ + for(offset = 0U; offsetbuffer1_addr) + offset)); + } + + }else{ + /* return ERROR */ + return ERROR; + } + } + /* enable reception, descriptor is owned by DMA */ + dma_current_rxdesc->status = ENET_RDES0_DAV; + + /* check Rx buffer unavailable flag status */ + if ((uint32_t)RESET != (ENET_DMA_STAT & ENET_DMA_STAT_RBU)){ + /* clear RBU flag */ + ENET_DMA_STAT = ENET_DMA_STAT_RBU; + /* resume DMA reception by writing to the RPEN register*/ + ENET_DMA_RPEN = 0U; + } + + /* update the current RxDMA descriptor pointer to the next decriptor in RxDMA decriptor table */ + /* chained mode */ + if((uint32_t)RESET != (dma_current_rxdesc->control_buffer_size & ENET_RDES1_RCHM)){ + dma_current_rxdesc = (enet_descriptors_struct*) (dma_current_rxdesc->buffer2_next_desc_addr); + }else{ + /* ring mode */ + if((uint32_t)RESET != (dma_current_rxdesc->control_buffer_size & ENET_RDES1_RERM)){ + /* if is the last descriptor in table, the next descriptor is the table header */ + dma_current_rxdesc = (enet_descriptors_struct*) (ENET_DMA_RDTADDR); + }else{ + /* the next descriptor is the current address, add the descriptor size, and descriptor skip length */ + dma_current_rxdesc = (enet_descriptors_struct*) (uint32_t)((uint32_t)dma_current_rxdesc + ETH_DMARXDESC_SIZE + (GET_DMA_BCTL_DPSL(ENET_DMA_BCTL))); + } + } + + return SUCCESS; +} + +/*! + \brief handle application buffer data to transmit it + \param[in] buffer: pointer to the frame data to be transmitted, + note -- if the input is NULL, user should handle the data in application by himself + \param[in] length: the length of frame data to be transmitted + \param[out] none + \retval ErrStatus: SUCCESS or ERROR +*/ +ErrStatus enet_frame_transmit(uint8_t *buffer, uint32_t length) +{ + uint32_t offset = 0U; + uint32_t dma_tbu_flag, dma_tu_flag; + + /* the descriptor is busy due to own by the DMA */ + if((uint32_t)RESET != (dma_current_txdesc->status & ENET_TDES0_DAV)){ + return ERROR; + } + + /* only frame length no more than ENET_MAX_FRAME_SIZE is allowed */ + if(length > ENET_MAX_FRAME_SIZE){ + return ERROR; + } + + /* if buffer pointer is null, indicates that users has handled data in application */ + if(NULL != buffer){ + /* copy frame data from application buffer to Tx buffer */ + for(offset = 0U; offset < length; offset++){ + (*(__IO uint8_t *) (uint32_t)((dma_current_txdesc->buffer1_addr) + offset)) = (*(buffer + offset)); + } + } + + /* set the frame length */ + dma_current_txdesc->control_buffer_size = length; + /* set the segment of frame, frame is transmitted in one descriptor */ + dma_current_txdesc->status |= ENET_TDES0_LSG | ENET_TDES0_FSG; + /* enable the DMA transmission */ + dma_current_txdesc->status |= ENET_TDES0_DAV; + + /* check Tx buffer unavailable flag status */ + dma_tbu_flag = (ENET_DMA_STAT & ENET_DMA_STAT_TBU); + dma_tu_flag = (ENET_DMA_STAT & ENET_DMA_STAT_TU); + + if ((RESET != dma_tbu_flag) || (RESET != dma_tu_flag)){ + /* clear TBU and TU flag */ + ENET_DMA_STAT = (dma_tbu_flag | dma_tu_flag); + /* resume DMA transmission by writing to the TPEN register*/ + ENET_DMA_TPEN = 0U; + } + + /* update the current TxDMA descriptor pointer to the next decriptor in TxDMA decriptor table*/ + /* chained mode */ + if((uint32_t)RESET != (dma_current_txdesc->status & ENET_TDES0_TCHM)){ + dma_current_txdesc = (enet_descriptors_struct*) (dma_current_txdesc->buffer2_next_desc_addr); + }else{ + /* ring mode */ + if((uint32_t)RESET != (dma_current_txdesc->status & ENET_TDES0_TERM)){ + /* if is the last descriptor in table, the next descriptor is the table header */ + dma_current_txdesc = (enet_descriptors_struct*) (ENET_DMA_TDTADDR); + }else{ + /* the next descriptor is the current address, add the descriptor size, and descriptor skip length */ + dma_current_txdesc = (enet_descriptors_struct*) (uint32_t)((uint32_t)dma_current_txdesc + ETH_DMATXDESC_SIZE + (GET_DMA_BCTL_DPSL(ENET_DMA_BCTL))); + } + } + + return SUCCESS; +} + +/*! + \brief configure the transmit IP frame checksum offload calculation and insertion + \param[in] desc: the descriptor pointer which users want to configure + \param[in] checksum: IP frame checksum configuration + only one parameter can be selected which is shown as below + \arg ENET_CHECKSUM_DISABLE: checksum insertion disabled + \arg ENET_CHECKSUM_IPV4HEADER: only IP header checksum calculation and insertion are enabled + \arg ENET_CHECKSUM_TCPUDPICMP_SEGMENT: TCP/UDP/ICMP checksum insertion calculated but pseudo-header + \arg ENET_CHECKSUM_TCPUDPICMP_FULL: TCP/UDP/ICMP checksum insertion fully calculated + \param[out] none + \retval none +*/ +void enet_transmit_checksum_config(enet_descriptors_struct *desc, uint32_t checksum) +{ + desc->status &= ~ENET_TDES0_CM; + desc->status |= checksum; +} + +/*! + \brief ENET Tx and Rx function enable (include MAC and DMA module) + \param[in] none + \param[out] none + \retval none +*/ +void enet_enable(void) +{ + enet_tx_enable(); + enet_rx_enable(); +} + +/*! + \brief ENET Tx and Rx function disable (include MAC and DMA module) + \param[in] none + \param[out] none + \retval none +*/ +void enet_disable(void) +{ + enet_tx_disable(); + enet_rx_disable(); +} + +/*! + \brief configure MAC address + \param[in] mac_addr: select which MAC address will be set, + only one parameter can be selected which is shown as below + \arg ENET_MAC_ADDRESS0: set MAC address 0 filter + \arg ENET_MAC_ADDRESS1: set MAC address 1 filter + \arg ENET_MAC_ADDRESS2: set MAC address 2 filter + \arg ENET_MAC_ADDRESS3: set MAC address 3 filter + \param[in] paddr: the buffer pointer which stores the MAC address + (little-ending store, such as MAC address is aa:bb:cc:dd:ee:22, the buffer is {22, ee, dd, cc, bb, aa}) + \param[out] none + \retval none +*/ +void enet_mac_address_set(enet_macaddress_enum mac_addr, uint8_t paddr[]) +{ + REG32(ENET_ADDRH_BASE + (uint32_t)mac_addr) = ENET_SET_MACADDRH(paddr); + REG32(ENET_ADDRL_BASE + (uint32_t)mac_addr) = ENET_SET_MACADDRL(paddr); +} + +/*! + \brief get MAC address + \param[in] mac_addr: select which MAC address will be get, + only one parameter can be selected which is shown as below + \arg ENET_MAC_ADDRESS0: get MAC address 0 filter + \arg ENET_MAC_ADDRESS1: get MAC address 1 filter + \arg ENET_MAC_ADDRESS2: get MAC address 2 filter + \arg ENET_MAC_ADDRESS3: get MAC address 3 filter + \param[out] paddr: the buffer pointer which is stored the MAC address + (little-ending store, such as mac address is aa:bb:cc:dd:ee:22, the buffer is {22, ee, dd, cc, bb, aa}) + \retval none +*/ +void enet_mac_address_get(enet_macaddress_enum mac_addr, uint8_t paddr[]) +{ + paddr[0] = ENET_GET_MACADDR(mac_addr, 0U); + paddr[1] = ENET_GET_MACADDR(mac_addr, 1U); + paddr[2] = ENET_GET_MACADDR(mac_addr, 2U); + paddr[3] = ENET_GET_MACADDR(mac_addr, 3U); + paddr[4] = ENET_GET_MACADDR(mac_addr, 4U); + paddr[5] = ENET_GET_MACADDR(mac_addr, 5U); +} + +/*! + \brief get the ENET MAC/MSC/PTP/DMA status flag + \param[in] enet_flag: ENET status flag, refer to enet_flag_enum, + only one parameter can be selected which is shown as below + \arg ENET_MAC_FLAG_MPKR: magic packet received flag + \arg ENET_MAC_FLAG_WUFR: wakeup frame received flag + \arg ENET_MAC_FLAG_FLOWCONTROL: flow control status flag + \arg ENET_MAC_FLAG_WUM: WUM status flag + \arg ENET_MAC_FLAG_MSC: MSC status flag + \arg ENET_MAC_FLAG_MSCR: MSC receive status flag + \arg ENET_MAC_FLAG_MSCT: MSC transmit status flag + \arg ENET_MAC_FLAG_TMST: time stamp trigger status flag + \arg ENET_PTP_FLAG_TSSCO: timestamp second counter overflow flag + \arg ENET_PTP_FLAG_TTM: target time match flag + \arg ENET_MSC_FLAG_RFCE: received frames CRC error flag + \arg ENET_MSC_FLAG_RFAE: received frames alignment error flag + \arg ENET_MSC_FLAG_RGUF: received good unicast frames flag + \arg ENET_MSC_FLAG_TGFSC: transmitted good frames single collision flag + \arg ENET_MSC_FLAG_TGFMSC: transmitted good frames more single collision flag + \arg ENET_MSC_FLAG_TGF: transmitted good frames flag + \arg ENET_DMA_FLAG_TS: transmit status flag + \arg ENET_DMA_FLAG_TPS: transmit process stopped status flag + \arg ENET_DMA_FLAG_TBU: transmit buffer unavailable status flag + \arg ENET_DMA_FLAG_TJT: transmit jabber timeout status flag + \arg ENET_DMA_FLAG_RO: receive overflow status flag + \arg ENET_DMA_FLAG_TU: transmit underflow status flag + \arg ENET_DMA_FLAG_RS: receive status flag + \arg ENET_DMA_FLAG_RBU: receive buffer unavailable status flag + \arg ENET_DMA_FLAG_RPS: receive process stopped status flag + \arg ENET_DMA_FLAG_RWT: receive watchdog timeout status flag + \arg ENET_DMA_FLAG_ET: early transmit status flag + \arg ENET_DMA_FLAG_FBE: fatal bus error status flag + \arg ENET_DMA_FLAG_ER: early receive status flag + \arg ENET_DMA_FLAG_AI: abnormal interrupt summary flag + \arg ENET_DMA_FLAG_NI: normal interrupt summary flag + \arg ENET_DMA_FLAG_EB_DMA_ERROR: DMA error flag + \arg ENET_DMA_FLAG_EB_TRANSFER_ERROR: transfer error flag + \arg ENET_DMA_FLAG_EB_ACCESS_ERROR: access error flag + \arg ENET_DMA_FLAG_MSC: MSC status flag + \arg ENET_DMA_FLAG_WUM: WUM status flag + \arg ENET_DMA_FLAG_TST: timestamp trigger status flag + \param[out] none + \retval FlagStatus: SET or RESET +*/ +FlagStatus enet_flag_get(enet_flag_enum enet_flag) +{ + if(RESET != (ENET_REG_VAL(enet_flag) & BIT(ENET_BIT_POS(enet_flag)))){ + return SET; + }else{ + return RESET; + } +} + +/*! + \brief clear the ENET DMA status flag + \param[in] enet_flag: ENET DMA flag clear, refer to enet_flag_clear_enum + only one parameter can be selected which is shown as below + \arg ENET_DMA_FLAG_TS_CLR: transmit status flag clear + \arg ENET_DMA_FLAG_TPS_CLR: transmit process stopped status flag clear + \arg ENET_DMA_FLAG_TBU_CLR: transmit buffer unavailable status flag clear + \arg ENET_DMA_FLAG_TJT_CLR: transmit jabber timeout status flag clear + \arg ENET_DMA_FLAG_RO_CLR: receive overflow status flag clear + \arg ENET_DMA_FLAG_TU_CLR: transmit underflow status flag clear + \arg ENET_DMA_FLAG_RS_CLR: receive status flag clear + \arg ENET_DMA_FLAG_RBU_CLR: receive buffer unavailable status flag clear + \arg ENET_DMA_FLAG_RPS_CLR: receive process stopped status flag clear + \arg ENET_DMA_FLAG_RWT_CLR: receive watchdog timeout status flag clear + \arg ENET_DMA_FLAG_ET_CLR: early transmit status flag clear + \arg ENET_DMA_FLAG_FBE_CLR: fatal bus error status flag clear + \arg ENET_DMA_FLAG_ER_CLR: early receive status flag clear + \arg ENET_DMA_FLAG_AI_CLR: abnormal interrupt summary flag clear + \arg ENET_DMA_FLAG_NI_CLR: normal interrupt summary flag clear + \param[out] none + \retval none +*/ +void enet_flag_clear(enet_flag_clear_enum enet_flag) +{ + /* write 1 to the corresponding bit in ENET_DMA_STAT, to clear it */ + ENET_REG_VAL(enet_flag) = BIT(ENET_BIT_POS(enet_flag)); +} + +/*! + \brief enable ENET MAC/MSC/DMA interrupt + \param[in] enet_int: ENET interrupt, + only one parameter can be selected which is shown as below + \arg ENET_MAC_INT_WUMIM: WUM interrupt mask + \arg ENET_MAC_INT_TMSTIM: timestamp trigger interrupt mask + \arg ENET_MSC_INT_RFCEIM: received frame CRC error interrupt mask + \arg ENET_MSC_INT_RFAEIM: received frames alignment error interrupt mask + \arg ENET_MSC_INT_RGUFIM: received good unicast frames interrupt mask + \arg ENET_MSC_INT_TGFSCIM: transmitted good frames single collision interrupt mask + \arg ENET_MSC_INT_TGFMSCIM: transmitted good frames more single collision interrupt mask + \arg ENET_MSC_INT_TGFIM: transmitted good frames interrupt mask + \arg ENET_DMA_INT_TIE: transmit interrupt enable + \arg ENET_DMA_INT_TPSIE: transmit process stopped interrupt enable + \arg ENET_DMA_INT_TBUIE: transmit buffer unavailable interrupt enable + \arg ENET_DMA_INT_TJTIE: transmit jabber timeout interrupt enable + \arg ENET_DMA_INT_ROIE: receive overflow interrupt enable + \arg ENET_DMA_INT_TUIE: transmit underflow interrupt enable + \arg ENET_DMA_INT_RIE: receive interrupt enable + \arg ENET_DMA_INT_RBUIE: receive buffer unavailable interrupt enable + \arg ENET_DMA_INT_RPSIE: receive process stopped interrupt enable + \arg ENET_DMA_INT_RWTIE: receive watchdog timeout interrupt enable + \arg ENET_DMA_INT_ETIE: early transmit interrupt enable + \arg ENET_DMA_INT_FBEIE: fatal bus error interrupt enable + \arg ENET_DMA_INT_ERIE: early receive interrupt enable + \arg ENET_DMA_INT_AIE: abnormal interrupt summary enable + \arg ENET_DMA_INT_NIE: normal interrupt summary enable + \param[out] none + \retval none +*/ +void enet_interrupt_enable(enet_int_enum enet_int) +{ + if(DMA_INTEN_REG_OFFSET == ((uint32_t)enet_int >> 6)){ + /* ENET_DMA_INTEN register interrupt */ + ENET_REG_VAL(enet_int) |= BIT(ENET_BIT_POS(enet_int)); + }else{ + /* other INTMSK register interrupt */ + ENET_REG_VAL(enet_int) &= ~BIT(ENET_BIT_POS(enet_int)); + } +} + +/*! + \brief disable ENET MAC/MSC/DMA interrupt + \param[in] enet_int: ENET interrupt, + only one parameter can be selected which is shown as below + \arg ENET_MAC_INT_WUMIM: WUM interrupt mask + \arg ENET_MAC_INT_TMSTIM: timestamp trigger interrupt mask + \arg ENET_MSC_INT_RFCEIM: received frame CRC error interrupt mask + \arg ENET_MSC_INT_RFAEIM: received frames alignment error interrupt mask + \arg ENET_MSC_INT_RGUFIM: received good unicast frames interrupt mask + \arg ENET_MSC_INT_TGFSCIM: transmitted good frames single collision interrupt mask + \arg ENET_MSC_INT_TGFMSCIM: transmitted good frames more single collision interrupt mask + \arg ENET_MSC_INT_TGFIM: transmitted good frames interrupt mask + \arg ENET_DMA_INT_TIE: transmit interrupt enable + \arg ENET_DMA_INT_TPSIE: transmit process stopped interrupt enable + \arg ENET_DMA_INT_TBUIE: transmit buffer unavailable interrupt enable + \arg ENET_DMA_INT_TJTIE: transmit jabber timeout interrupt enable + \arg ENET_DMA_INT_ROIE: receive overflow interrupt enable + \arg ENET_DMA_INT_TUIE: transmit underflow interrupt enable + \arg ENET_DMA_INT_RIE: receive interrupt enable + \arg ENET_DMA_INT_RBUIE: receive buffer unavailable interrupt enable + \arg ENET_DMA_INT_RPSIE: receive process stopped interrupt enable + \arg ENET_DMA_INT_RWTIE: receive watchdog timeout interrupt enable + \arg ENET_DMA_INT_ETIE: early transmit interrupt enable + \arg ENET_DMA_INT_FBEIE: fatal bus error interrupt enable + \arg ENET_DMA_INT_ERIE: early receive interrupt enable + \arg ENET_DMA_INT_AIE: abnormal interrupt summary enable + \arg ENET_DMA_INT_NIE: normal interrupt summary enable + \param[out] none + \retval none +*/ +void enet_interrupt_disable(enet_int_enum enet_int) +{ + if(DMA_INTEN_REG_OFFSET == ((uint32_t)enet_int >> 6)){ + /* ENET_DMA_INTEN register interrupt */ + ENET_REG_VAL(enet_int) &= ~BIT(ENET_BIT_POS(enet_int)); + }else{ + /* other INTMSK register interrupt */ + ENET_REG_VAL(enet_int) |= BIT(ENET_BIT_POS(enet_int)); + } +} + +/*! + \brief get ENET MAC/MSC/DMA interrupt flag + \param[in] int_flag: ENET interrupt flag, + only one parameter can be selected which is shown as below + \arg ENET_MAC_INT_FLAG_WUM: WUM status flag + \arg ENET_MAC_INT_FLAG_MSC: MSC status flag + \arg ENET_MAC_INT_FLAG_MSCR: MSC receive status flag + \arg ENET_MAC_INT_FLAG_MSCT: MSC transmit status flag + \arg ENET_MAC_INT_FLAG_TMST: time stamp trigger status flag + \arg ENET_MSC_INT_FLAG_RFCE: received frames CRC error flag + \arg ENET_MSC_INT_FLAG_RFAE: received frames alignment error flag + \arg ENET_MSC_INT_FLAG_RGUF: received good unicast frames flag + \arg ENET_MSC_INT_FLAG_TGFSC: transmitted good frames single collision flag + \arg ENET_MSC_INT_FLAG_TGFMSC: transmitted good frames more single collision flag + \arg ENET_MSC_INT_FLAG_TGF: transmitted good frames flag + \arg ENET_DMA_INT_FLAG_TS: transmit status flag + \arg ENET_DMA_INT_FLAG_TPS: transmit process stopped status flag + \arg ENET_DMA_INT_FLAG_TBU: transmit buffer unavailable status flag + \arg ENET_DMA_INT_FLAG_TJT: transmit jabber timeout status flag + \arg ENET_DMA_INT_FLAG_RO: receive overflow status flag + \arg ENET_DMA_INT_FLAG_TU: transmit underflow status flag + \arg ENET_DMA_INT_FLAG_RS: receive status flag + \arg ENET_DMA_INT_FLAG_RBU: receive buffer unavailable status flag + \arg ENET_DMA_INT_FLAG_RPS: receive process stopped status flag + \arg ENET_DMA_INT_FLAG_RWT: receive watchdog timeout status flag + \arg ENET_DMA_INT_FLAG_ET: early transmit status flag + \arg ENET_DMA_INT_FLAG_FBE: fatal bus error status flag + \arg ENET_DMA_INT_FLAG_ER: early receive status flag + \arg ENET_DMA_INT_FLAG_AI: abnormal interrupt summary flag + \arg ENET_DMA_INT_FLAG_NI: normal interrupt summary flag + \arg ENET_DMA_INT_FLAG_MSC: MSC status flag + \arg ENET_DMA_INT_FLAG_WUM: WUM status flag + \arg ENET_DMA_INT_FLAG_TST: timestamp trigger status flag + \param[out] none + \retval FlagStatus: SET or RESET +*/ +FlagStatus enet_interrupt_flag_get(enet_int_flag_enum int_flag) +{ + if(RESET != (ENET_REG_VAL(int_flag) & BIT(ENET_BIT_POS(int_flag)))){ + return SET; + }else{ + return RESET; + } +} + +/*! + \brief clear ENET DMA interrupt flag + \param[in] int_flag_clear: clear ENET interrupt flag, + only one parameter can be selected which is shown as below + \arg ENET_DMA_INT_FLAG_TS_CLR: transmit status flag + \arg ENET_DMA_INT_FLAG_TPS_CLR: transmit process stopped status flag + \arg ENET_DMA_INT_FLAG_TBU_CLR: transmit buffer unavailable status flag + \arg ENET_DMA_INT_FLAG_TJT_CLR: transmit jabber timeout status flag + \arg ENET_DMA_INT_FLAG_RO_CLR: receive overflow status flag + \arg ENET_DMA_INT_FLAG_TU_CLR: transmit underflow status flag + \arg ENET_DMA_INT_FLAG_RS_CLR: receive status flag + \arg ENET_DMA_INT_FLAG_RBU_CLR: receive buffer unavailable status flag + \arg ENET_DMA_INT_FLAG_RPS_CLR: receive process stopped status flag + \arg ENET_DMA_INT_FLAG_RWT_CLR: receive watchdog timeout status flag + \arg ENET_DMA_INT_FLAG_ET_CLR: early transmit status flag + \arg ENET_DMA_INT_FLAG_FBE_CLR: fatal bus error status flag + \arg ENET_DMA_INT_FLAG_ER_CLR: early receive status flag + \arg ENET_DMA_INT_FLAG_AI_CLR: abnormal interrupt summary flag + \arg ENET_DMA_INT_FLAG_NI_CLR: normal interrupt summary flag + \param[out] none + \retval none +*/ +void enet_interrupt_flag_clear(enet_int_flag_clear_enum int_flag_clear) +{ + /* write 1 to the corresponding bit in ENET_DMA_STAT, to clear it */ + ENET_REG_VAL(int_flag_clear) = BIT(ENET_BIT_POS(int_flag_clear)); +} + +/*! + \brief ENET Tx function enable (include MAC and DMA module) + \param[in] none + \param[out] none + \retval none +*/ +void enet_tx_enable(void) +{ + ENET_MAC_CFG |= ENET_MAC_CFG_TEN; + enet_txfifo_flush(); + ENET_DMA_CTL |= ENET_DMA_CTL_STE; +} + +/*! + \brief ENET Tx function disable (include MAC and DMA module) + \param[in] none + \param[out] none + \retval none +*/ +void enet_tx_disable(void) +{ + ENET_DMA_CTL &= ~ENET_DMA_CTL_STE; + enet_txfifo_flush(); + ENET_MAC_CFG &= ~ENET_MAC_CFG_TEN; +} + +/*! + \brief ENET Rx function enable (include MAC and DMA module) + \param[in] none + \param[out] none + \retval none +*/ +void enet_rx_enable(void) +{ + ENET_MAC_CFG |= ENET_MAC_CFG_REN; + ENET_DMA_CTL |= ENET_DMA_CTL_SRE; +} + +/*! + \brief ENET Rx function disable (include MAC and DMA module) + \param[in] none + \param[out] none + \retval none +*/ +void enet_rx_disable(void) +{ + ENET_DMA_CTL &= ~ENET_DMA_CTL_SRE; + ENET_MAC_CFG &= ~ENET_MAC_CFG_REN; +} + +/*! + \brief put registers value into the application buffer + \param[in] type: register type which will be get, refer to enet_registers_type_enum, + only one parameter can be selected which is shown as below + \arg ALL_MAC_REG: get the registers within the offset scope between ENET_MAC_CFG and ENET_MAC_FCTH + \arg ALL_MSC_REG: get the registers within the offset scope between ENET_MSC_CTL and ENET_MSC_RGUFCNT + \arg ALL_PTP_REG: get the registers within the offset scope between ENET_PTP_TSCTL and ENET_PTP_PPSCTL + \arg ALL_DMA_REG: get the registers within the offset scope between ENET_DMA_BCTL and ENET_DMA_CRBADDR + \param[in] num: the number of registers that the user want to get + \param[out] preg: the application buffer pointer for storing the register value + \retval none +*/ +void enet_registers_get(enet_registers_type_enum type, uint32_t *preg, uint32_t num) +{ + uint32_t offset = 0U, max = 0U, limit = 0U; + + offset = (uint32_t)type; + max = (uint32_t)type + num; + limit = sizeof(enet_reg_tab)/sizeof(uint16_t); + + /* prevent element in this array is out of range */ + if(max > limit){ + max = limit; + } + + for(; offset < max; offset++){ + /* get value of the corresponding register */ + *preg = REG32((ENET) + enet_reg_tab[offset]); + preg++; + } +} + +/*! + \brief enable the MAC address filter + \param[in] mac_addr: select which MAC address will be enable + \arg ENET_MAC_ADDRESS1: enable MAC address 1 filter + \arg ENET_MAC_ADDRESS2: enable MAC address 2 filter + \arg ENET_MAC_ADDRESS3: enable MAC address 3 filter + \param[out] none + \retval none +*/ +void enet_address_filter_enable(enet_macaddress_enum mac_addr) +{ + REG32(ENET_ADDRH_BASE + mac_addr) |= ENET_MAC_ADDR1H_AFE; +} + +/*! + \brief disable the MAC address filter + \param[in] mac_addr: select which MAC address will be disable, + only one parameter can be selected which is shown as below + \arg ENET_MAC_ADDRESS1: disable MAC address 1 filter + \arg ENET_MAC_ADDRESS2: disable MAC address 2 filter + \arg ENET_MAC_ADDRESS3: disable MAC address 3 filter + \param[out] none + \retval none +*/ +void enet_address_filter_disable(enet_macaddress_enum mac_addr) +{ + REG32(ENET_ADDRH_BASE + mac_addr) &= ~ENET_MAC_ADDR1H_AFE; +} + +/*! + \brief configure the MAC address filter + \param[in] mac_addr: select which MAC address will be configured, + only one parameter can be selected which is shown as below + \arg ENET_MAC_ADDRESS1: configure MAC address 1 filter + \arg ENET_MAC_ADDRESS2: configure MAC address 2 filter + \arg ENET_MAC_ADDRESS3: configure MAC address 3 filter + \param[in] addr_mask: select which MAC address bytes will be mask, + one or more parameters can be selected which are shown as below + \arg ENET_ADDRESS_MASK_BYTE0: mask ENET_MAC_ADDR1L[7:0] bits + \arg ENET_ADDRESS_MASK_BYTE1: mask ENET_MAC_ADDR1L[15:8] bits + \arg ENET_ADDRESS_MASK_BYTE2: mask ENET_MAC_ADDR1L[23:16] bits + \arg ENET_ADDRESS_MASK_BYTE3: mask ENET_MAC_ADDR1L [31:24] bits + \arg ENET_ADDRESS_MASK_BYTE4: mask ENET_MAC_ADDR1H [7:0] bits + \arg ENET_ADDRESS_MASK_BYTE5: mask ENET_MAC_ADDR1H [15:8] bits + \param[in] filter_type: select which MAC address filter type will be selected, + only one parameter can be selected which is shown as below + \arg ENET_ADDRESS_FILTER_SA: The MAC address is used to compared with the SA field of the received frame + \arg ENET_ADDRESS_FILTER_DA: The MAC address is used to compared with the DA field of the received frame + \param[out] none + \retval none +*/ +void enet_address_filter_config(enet_macaddress_enum mac_addr, uint32_t addr_mask, uint32_t filter_type) +{ + uint32_t reg; + + /* get the address filter register value which is to be configured */ + reg = REG32(ENET_ADDRH_BASE + mac_addr); + + /* clear and configure the address filter register */ + reg &= ~(ENET_MAC_ADDR1H_MB | ENET_MAC_ADDR1H_SAF); + reg |= (addr_mask | filter_type); + REG32(ENET_ADDRH_BASE + mac_addr) = reg; +} + +/*! + \brief PHY interface configuration (configure SMI clock and reset PHY chip) + \param[in] none + \param[out] none + \retval ErrStatus: SUCCESS or ERROR +*/ +ErrStatus enet_phy_config(void) +{ + uint32_t ahbclk; + uint32_t reg; + uint16_t phy_value; + ErrStatus enet_state = ERROR; + + /* clear the previous MDC clock */ + reg = ENET_MAC_PHY_CTL; + reg &= ~ENET_MAC_PHY_CTL_CLR; + + /* get the HCLK frequency */ + ahbclk = rcu_clock_freq_get(CK_AHB); + + /* configure MDC clock according to HCLK frequency range */ + if(ENET_RANGE(ahbclk, 20000000U, 35000000U)){ + reg |= ENET_MDC_HCLK_DIV16; + }else if(ENET_RANGE(ahbclk, 35000000U, 60000000U)){ + reg |= ENET_MDC_HCLK_DIV26; + }else if(ENET_RANGE(ahbclk, 60000000U, 100000000U)){ + reg |= ENET_MDC_HCLK_DIV42; + }else if((ENET_RANGE(ahbclk, 100000000U, 120000000U))||(120000000U == ahbclk)){ + reg |= ENET_MDC_HCLK_DIV62; + }else{ + return enet_state; + } + ENET_MAC_PHY_CTL = reg; + + /* reset PHY */ + phy_value = PHY_RESET; + if(ERROR == (enet_phy_write_read(ENET_PHY_WRITE, PHY_ADDRESS, PHY_REG_BCR, &phy_value))){ + return enet_state; + } + /* PHY reset need some time */ + _ENET_DELAY_(ENET_DELAY_TO); + + /* check whether PHY reset is complete */ + if(ERROR == (enet_phy_write_read(ENET_PHY_READ, PHY_ADDRESS, PHY_REG_BCR, &phy_value))){ + return enet_state; + } + + /* PHY reset complete */ + if(RESET == (phy_value & PHY_RESET)){ + enet_state = SUCCESS; + } + + return enet_state; +} + +/*! + \brief write to / read from a PHY register + \param[in] direction: only one parameter can be selected which is shown as below + \arg ENET_PHY_WRITE: write data to phy register + \arg ENET_PHY_READ: read data from phy register + \param[in] phy_address: 0x0 - 0x1F + \param[in] phy_reg: 0x0 - 0x1F + \param[in] pvalue: the value will be written to the PHY register in ENET_PHY_WRITE direction + \param[out] pvalue: the value will be read from the PHY register in ENET_PHY_READ direction + \retval ErrStatus: SUCCESS or ERROR +*/ +ErrStatus enet_phy_write_read(enet_phydirection_enum direction, uint16_t phy_address, uint16_t phy_reg, uint16_t *pvalue) +{ + uint32_t reg, phy_flag; + uint32_t timeout = 0U; + ErrStatus enet_state = ERROR; + + /* configure ENET_MAC_PHY_CTL with write/read operation */ + reg = ENET_MAC_PHY_CTL; + reg &= ~(ENET_MAC_PHY_CTL_PB | ENET_MAC_PHY_CTL_PW | ENET_MAC_PHY_CTL_PR | ENET_MAC_PHY_CTL_PA); + reg |= (direction | MAC_PHY_CTL_PR(phy_reg) | MAC_PHY_CTL_PA(phy_address) | ENET_MAC_PHY_CTL_PB); + + /* if do the write operation, write value to the register */ + if(ENET_PHY_WRITE == direction){ + ENET_MAC_PHY_DATA = *pvalue; + } + + /* do PHY write/read operation, and wait the operation complete */ + ENET_MAC_PHY_CTL = reg; + do{ + phy_flag = (ENET_MAC_PHY_CTL & ENET_MAC_PHY_CTL_PB); + timeout++; + } + while((RESET != phy_flag) && (ENET_DELAY_TO != timeout)); + + /* write/read operation complete */ + if(RESET == (ENET_MAC_PHY_CTL & ENET_MAC_PHY_CTL_PB)){ + enet_state = SUCCESS; + } + + /* if do the read operation, get value from the register */ + if(ENET_PHY_READ == direction){ + *pvalue = (uint16_t)ENET_MAC_PHY_DATA; + } + + return enet_state; +} + +/*! + \brief enable the loopback function of PHY chip + \param[in] none + \param[out] none + \retval ErrStatus: ERROR or SUCCESS +*/ +ErrStatus enet_phyloopback_enable(void) +{ + uint16_t temp_phy = 0U; + ErrStatus phy_state = ERROR; + + /* get the PHY configuration to update it */ + enet_phy_write_read(ENET_PHY_READ, PHY_ADDRESS, PHY_REG_BCR, &temp_phy); + + /* enable the PHY loopback mode */ + temp_phy |= PHY_LOOPBACK; + + /* update the PHY control register with the new configuration */ + phy_state = enet_phy_write_read(ENET_PHY_WRITE, PHY_ADDRESS, PHY_REG_BCR, &temp_phy); + + return phy_state; +} + +/*! + \brief disable the loopback function of PHY chip + \param[in] none + \param[out] none + \retval ErrStatus: ERROR or SUCCESS +*/ +ErrStatus enet_phyloopback_disable(void) +{ + uint16_t temp_phy = 0U; + ErrStatus phy_state = ERROR; + + /* get the PHY configuration to update it */ + enet_phy_write_read(ENET_PHY_READ, PHY_ADDRESS, PHY_REG_BCR, &temp_phy); + + /* disable the PHY loopback mode */ + temp_phy &= (uint16_t)~PHY_LOOPBACK; + + /* update the PHY control register with the new configuration */ + phy_state = enet_phy_write_read(ENET_PHY_WRITE, PHY_ADDRESS, PHY_REG_BCR, &temp_phy); + + return phy_state; +} + +/*! + \brief enable ENET forward feature + \param[in] feature: the feature of ENET forward mode, + one or more parameters can be selected which are shown as below + \arg ENET_AUTO_PADCRC_DROP: the function of the MAC strips the Pad/FCS field on received frames + \arg ENET_FORWARD_ERRFRAMES: the function that all frame received with error except runt error are forwarded to memory + \arg ENET_FORWARD_UNDERSZ_GOODFRAMES: the function that forwarding undersized good frames + \param[out] none + \retval none +*/ +void enet_forward_feature_enable(uint32_t feature) +{ + uint32_t mask; + + mask = (feature & (~(ENET_FORWARD_ERRFRAMES | ENET_FORWARD_UNDERSZ_GOODFRAMES))); + ENET_MAC_CFG |= mask; + + mask = (feature & (~(ENET_AUTO_PADCRC_DROP))); + ENET_DMA_CTL |= (mask >> 2); +} + +/*! + \brief disable ENET forward feature + \param[in] feature: the feature of ENET forward mode, + one or more parameters can be selected which are shown as below + \arg ENET_AUTO_PADCRC_DROP: the automatic zero-quanta generation function + \arg ENET_FORWARD_ERRFRAMES: decoding function for the received pause frame and process it + \arg ENET_FORWARD_UNDERSZ_GOODFRAMES: back pressure operation in the MAC(only use in half-dulex mode) + \param[out] none + \retval none +*/ +void enet_forward_feature_disable(uint32_t feature) +{ + uint32_t mask; + + mask = (feature & (~(ENET_FORWARD_ERRFRAMES | ENET_FORWARD_UNDERSZ_GOODFRAMES))); + ENET_MAC_CFG &= ~mask; + + mask = (feature & (~(ENET_AUTO_PADCRC_DROP))); + ENET_DMA_CTL &= ~(mask >> 2); +} + +/*! + \brief enable ENET fliter feature + \param[in] feature: the feature of ENET fliter mode, + one or more parameters can be selected which are shown as below + \arg ENET_SRC_FILTER: filter source address function + \arg ENET_SRC_FILTER_INVERSE: inverse source address filtering result function + \arg ENET_DEST_FILTER_INVERSE: inverse DA filtering result function + \arg ENET_MULTICAST_FILTER_PASS: pass all multicast frames function + \arg ENET_MULTICAST_FILTER_HASH_MODE: HASH multicast filter function + \arg ENET_UNICAST_FILTER_HASH_MODE: HASH unicast filter function + \arg ENET_FILTER_MODE_EITHER: HASH or perfect filter function + \param[out] none + \retval none +*/ +void enet_fliter_feature_enable(uint32_t feature) +{ + ENET_MAC_FRMF |= feature; +} + +/*! + \brief disable ENET fliter feature + \param[in] feature: the feature of ENET fliter mode, + one or more parameters can be selected which are shown as below + \arg ENET_SRC_FILTER: filter source address function + \arg ENET_SRC_FILTER_INVERSE: inverse source address filtering result function + \arg ENET_DEST_FILTER_INVERSE: inverse DA filtering result function + \arg ENET_MULTICAST_FILTER_PASS: pass all multicast frames function + \arg ENET_MULTICAST_FILTER_HASH_MODE: HASH multicast filter function + \arg ENET_UNICAST_FILTER_HASH_MODE: HASH unicast filter function + \arg ENET_FILTER_MODE_EITHER: HASH or perfect filter function + \param[out] none + \retval none +*/ +void enet_fliter_feature_disable(uint32_t feature) +{ + ENET_MAC_FRMF &= ~feature; +} + +/*! + \brief generate the pause frame, ENET will send pause frame after enable transmit flow control + this function only use in full-dulex mode + \param[in] none + \param[out] none + \retval ErrStatus: ERROR or SUCCESS +*/ +ErrStatus enet_pauseframe_generate(void) +{ + ErrStatus enet_state =ERROR; + uint32_t temp = 0U; + + /* in full-duplex mode, must make sure this bit is 0 before writing register */ + temp = ENET_MAC_FCTL & ENET_MAC_FCTL_FLCBBKPA; + if(RESET == temp){ + ENET_MAC_FCTL |= ENET_MAC_FCTL_FLCBBKPA; + enet_state = SUCCESS; + } + return enet_state; +} + +/*! + \brief configure the pause frame detect type + \param[in] detect: pause frame detect type, + only one parameter can be selected which is shown as below + \arg ENET_MAC0_AND_UNIQUE_ADDRESS_PAUSEDETECT: besides the unique multicast address, MAC can also + use the MAC0 address to detecting pause frame + \arg ENET_UNIQUE_PAUSEDETECT: only the unique multicast address for pause frame which is specified + in IEEE802.3 can be detected + \param[out] none + \retval none +*/ +void enet_pauseframe_detect_config(uint32_t detect) +{ + ENET_MAC_FCTL &= ~ENET_MAC_FCTL_UPFDT; + ENET_MAC_FCTL |= detect; +} + +/*! + \brief configure the pause frame parameters + \param[in] pausetime: pause time in transmit pause control frame + \param[in] pause_threshold: the threshold of the pause timer for retransmitting frames automatically, + this value must make sure to be less than configured pause time, only one parameter can be + selected which is shown as below + \arg ENET_PAUSETIME_MINUS4: pause time minus 4 slot times + \arg ENET_PAUSETIME_MINUS28: pause time minus 28 slot times + \arg ENET_PAUSETIME_MINUS144: pause time minus 144 slot times + \arg ENET_PAUSETIME_MINUS256: pause time minus 256 slot times + \param[out] none + \retval none +*/ +void enet_pauseframe_config(uint32_t pausetime, uint32_t pause_threshold) +{ + ENET_MAC_FCTL &= ~(ENET_MAC_FCTL_PTM | ENET_MAC_FCTL_PLTS); + ENET_MAC_FCTL |= (MAC_FCTL_PTM(pausetime) | pause_threshold); +} + +/*! + \brief configure the threshold of the flow control(deactive and active threshold) + \param[in] deactive: the threshold of the deactive flow control, this value + should always be less than active flow control value, only one + parameter can be selected which is shown as below + \arg ENET_DEACTIVE_THRESHOLD_256BYTES: threshold level is 256 bytes + \arg ENET_DEACTIVE_THRESHOLD_512BYTES: threshold level is 512 bytes + \arg ENET_DEACTIVE_THRESHOLD_768BYTES: threshold level is 768 bytes + \arg ENET_DEACTIVE_THRESHOLD_1024BYTES: threshold level is 1024 bytes + \arg ENET_DEACTIVE_THRESHOLD_1280BYTES: threshold level is 1280 bytes + \arg ENET_DEACTIVE_THRESHOLD_1536BYTES: threshold level is 1536 bytes + \arg ENET_DEACTIVE_THRESHOLD_1792BYTES: threshold level is 1792 bytes + \param[in] active: the threshold of the active flow control, only one parameter + can be selected which is shown as below + \arg ENET_ACTIVE_THRESHOLD_256BYTES: threshold level is 256 bytes + \arg ENET_ACTIVE_THRESHOLD_512BYTES: threshold level is 512 bytes + \arg ENET_ACTIVE_THRESHOLD_768BYTES: threshold level is 768 bytes + \arg ENET_ACTIVE_THRESHOLD_1024BYTES: threshold level is 1024 bytes + \arg ENET_ACTIVE_THRESHOLD_1280BYTES: threshold level is 1280 bytes + \arg ENET_ACTIVE_THRESHOLD_1536BYTES: threshold level is 1536 bytes + \arg ENET_ACTIVE_THRESHOLD_1792BYTES: threshold level is 1792 bytes + \param[out] none + \retval none +*/ +void enet_flowcontrol_threshold_config(uint32_t deactive, uint32_t active) +{ + ENET_MAC_FCTH = ((deactive | active) >> 8); +} + +/*! + \brief enable ENET flow control feature + \param[in] feature: the feature of ENET flow control mode + one or more parameters can be selected which are shown as below + \arg ENET_ZERO_QUANTA_PAUSE: the automatic zero-quanta generation function + \arg ENET_TX_FLOWCONTROL: the flow control operation in the MAC + \arg ENET_RX_FLOWCONTROL: decoding function for the received pause frame and process it + \arg ENET_BACK_PRESSURE: back pressure operation in the MAC(only use in half-dulex mode) + \param[out] none + \retval none +*/ +void enet_flowcontrol_feature_enable(uint32_t feature) +{ + if(RESET != (feature & ENET_ZERO_QUANTA_PAUSE)){ + ENET_MAC_FCTL &= ~ENET_ZERO_QUANTA_PAUSE; + } + feature &= ~ENET_ZERO_QUANTA_PAUSE; + ENET_MAC_FCTL |= feature; +} + +/*! + \brief disable ENET flow control feature + \param[in] feature: the feature of ENET flow control mode + one or more parameters can be selected which are shown as below + \arg ENET_ZERO_QUANTA_PAUSE: the automatic zero-quanta generation function + \arg ENET_TX_FLOWCONTROL: the flow control operation in the MAC + \arg ENET_RX_FLOWCONTROL: decoding function for the received pause frame and process it + \arg ENET_BACK_PRESSURE: back pressure operation in the MAC(only use in half-dulex mode) + \param[out] none + \retval none +*/ +void enet_flowcontrol_feature_disable(uint32_t feature) +{ + if(RESET != (feature & ENET_ZERO_QUANTA_PAUSE)){ + ENET_MAC_FCTL |= ENET_ZERO_QUANTA_PAUSE; + } + feature &= ~ENET_ZERO_QUANTA_PAUSE; + ENET_MAC_FCTL &= ~feature; +} + +/*! + \brief get the dma transmit/receive process state + \param[in] direction: choose the direction of dma process which users want to check, + refer to enet_dmadirection_enum, only one parameter can be selected which is shown as below + \arg ENET_DMA_TX: dma transmit process + \arg ENET_DMA_RX: dma receive process + \param[out] none + \retval state of dma process, the value range shows below: + ENET_RX_STATE_STOPPED, ENET_RX_STATE_FETCHING, ENET_RX_STATE_WAITING, + ENET_RX_STATE_SUSPENDED, ENET_RX_STATE_CLOSING, ENET_RX_STATE_QUEUING, + ENET_TX_STATE_STOPPED, ENET_TX_STATE_FETCHING, ENET_TX_STATE_WAITING, + ENET_TX_STATE_READING, ENET_TX_STATE_SUSPENDED, ENET_TX_STATE_CLOSING +*/ +uint32_t enet_dmaprocess_state_get(enet_dmadirection_enum direction) +{ + uint32_t reval; + reval = (uint32_t)(ENET_DMA_STAT & (uint32_t)direction); + return reval; +} + +/*! + \brief poll the DMA transmission/reception enable by writing any value to the + ENET_DMA_TPEN/ENET_DMA_RPEN register, this will make the DMA to resume transmission/reception + \param[in] direction: choose the direction of DMA process which users want to resume, + refer to enet_dmadirection_enum, only one parameter can be selected which is shown as below + \arg ENET_DMA_TX: DMA transmit process + \arg ENET_DMA_RX: DMA receive process + \param[out] none + \retval none +*/ +void enet_dmaprocess_resume(enet_dmadirection_enum direction) +{ + if(ENET_DMA_TX == direction){ + ENET_DMA_TPEN = 0U; + }else{ + ENET_DMA_RPEN = 0U; + } +} + +/*! + \brief check and recover the Rx process + \param[in] none + \param[out] none + \retval none +*/ +void enet_rxprocess_check_recovery(void) +{ + uint32_t status; + + /* get DAV information of current RxDMA descriptor */ + status = dma_current_rxdesc->status; + status &= ENET_RDES0_DAV; + + /* if current descriptor is owned by DMA, but the descriptor address mismatches with + receive descriptor address pointer updated by RxDMA controller */ + if((ENET_DMA_CRDADDR != ((uint32_t)dma_current_rxdesc)) && + (ENET_RDES0_DAV == status)){ + dma_current_rxdesc = (enet_descriptors_struct*)ENET_DMA_CRDADDR; + } +} + +/*! + \brief flush the ENET transmit FIFO, and wait until the flush operation completes + \param[in] none + \param[out] none + \retval ErrStatus: ERROR or SUCCESS +*/ +ErrStatus enet_txfifo_flush(void) +{ + uint32_t flush_state; + uint32_t timeout = 0U; + ErrStatus enet_state = ERROR; + + /* set the FTF bit for flushing transmit FIFO */ + ENET_DMA_CTL |= ENET_DMA_CTL_FTF; + /* wait until the flush operation completes */ + do{ + flush_state = ENET_DMA_CTL & ENET_DMA_CTL_FTF; + timeout++; + }while((RESET != flush_state) && (timeout < ENET_DELAY_TO)); + /* return ERROR due to timeout */ + if(RESET == flush_state){ + enet_state = SUCCESS; + } + + return enet_state; +} + +/*! + \brief get the transmit/receive address of current descriptor, or current buffer, or descriptor table + \param[in] addr_get: choose the address which users want to get, refer to enet_desc_reg_enum, + only one parameter can be selected which is shown as below + \arg ENET_RX_DESC_TABLE: the start address of the receive descriptor table + \arg ENET_RX_CURRENT_DESC: the start descriptor address of the current receive descriptor read by + the RxDMA controller + \arg ENET_RX_CURRENT_BUFFER: the current receive buffer address being read by the RxDMA controller + \arg ENET_TX_DESC_TABLE: the start address of the transmit descriptor table + \arg ENET_TX_CURRENT_DESC: the start descriptor address of the current transmit descriptor read by + the TxDMA controller + \arg ENET_TX_CURRENT_BUFFER: the current transmit buffer address being read by the TxDMA controller + \param[out] none + \retval address value +*/ +uint32_t enet_current_desc_address_get(enet_desc_reg_enum addr_get) +{ + uint32_t reval = 0U; + + reval = REG32((ENET) +(uint32_t)addr_get); + return reval; +} + +/*! + \brief get the Tx or Rx descriptor information + \param[in] desc: the descriptor pointer which users want to get information + \param[in] info_get: the descriptor information type which is selected, + only one parameter can be selected which is shown as below + \arg RXDESC_BUFFER_1_SIZE: receive buffer 1 size + \arg RXDESC_BUFFER_2_SIZE: receive buffer 2 size + \arg RXDESC_FRAME_LENGTH: the byte length of the received frame that was transferred to the buffer + \arg TXDESC_COLLISION_COUNT: the number of collisions occurred before the frame was transmitted + \arg RXDESC_BUFFER_1_ADDR: the buffer1 address of the Rx frame + \arg TXDESC_BUFFER_1_ADDR: the buffer1 address of the Tx frame + \param[out] none + \retval descriptor information, if value is 0xFFFFFFFFU, means the false input parameter +*/ +uint32_t enet_desc_information_get(enet_descriptors_struct *desc, enet_descstate_enum info_get) +{ + uint32_t reval = 0xFFFFFFFFU; + + switch(info_get){ + case RXDESC_BUFFER_1_SIZE: + reval = GET_RDES1_RB1S(desc->control_buffer_size); + break; + case RXDESC_BUFFER_2_SIZE: + reval = GET_RDES1_RB2S(desc->control_buffer_size); + break; + case RXDESC_FRAME_LENGTH: + reval = GET_RDES0_FRML(desc->status); + if(reval > 4U){ + reval = reval - 4U; + }else{ + reval = 0U; + } + break; + case RXDESC_BUFFER_1_ADDR: + reval = desc->buffer1_addr; + break; + case TXDESC_BUFFER_1_ADDR: + reval = desc->buffer1_addr; + break; + case TXDESC_COLLISION_COUNT: + reval = GET_TDES0_COCNT(desc->status); + break; + default: + break; + } + return reval; +} + +/*! + \brief get the number of missed frames during receiving + \param[in] none + \param[out] rxfifo_drop: pointer to the number of frames dropped by RxFIFO + \param[out] rxdma_drop: pointer to the number of frames missed by the RxDMA controller + \retval none +*/ +void enet_missed_frame_counter_get(uint32_t *rxfifo_drop, uint32_t *rxdma_drop) +{ + uint32_t temp_counter = 0U; + + temp_counter = ENET_DMA_MFBOCNT; + *rxfifo_drop = GET_DMA_MFBOCNT_MSFA(temp_counter); + *rxdma_drop = GET_DMA_MFBOCNT_MSFC(temp_counter); +} + +/*! + \brief get the bit flag of ENET DMA descriptor + \param[in] desc: the descriptor pointer which users want to get flag + \param[in] desc_flag: the bit flag of ENET DMA descriptor, + only one parameter can be selected which is shown as below + \arg ENET_TDES0_DB: deferred + \arg ENET_TDES0_UFE: underflow error + \arg ENET_TDES0_EXD: excessive deferral + \arg ENET_TDES0_VFRM: VLAN frame + \arg ENET_TDES0_ECO: excessive collision + \arg ENET_TDES0_LCO: late collision + \arg ENET_TDES0_NCA: no carrier + \arg ENET_TDES0_LCA: loss of carrier + \arg ENET_TDES0_IPPE: IP payload error + \arg ENET_TDES0_FRMF: frame flushed + \arg ENET_TDES0_JT: jabber timeout + \arg ENET_TDES0_ES: error summary + \arg ENET_TDES0_IPHE: IP header error + \arg ENET_TDES0_TTMSS: transmit timestamp status + \arg ENET_TDES0_TCHM: the second address chained mode + \arg ENET_TDES0_TERM: transmit end of ring mode + \arg ENET_TDES0_TTSEN: transmit timestamp function enable + \arg ENET_TDES0_DPAD: disable adding pad + \arg ENET_TDES0_DCRC: disable CRC + \arg ENET_TDES0_FSG: first segment + \arg ENET_TDES0_LSG: last segment + \arg ENET_TDES0_INTC: interrupt on completion + \arg ENET_TDES0_DAV: DAV bit + + \arg ENET_RDES0_PCERR: payload checksum error + \arg ENET_RDES0_CERR: CRC error + \arg ENET_RDES0_DBERR: dribble bit error + \arg ENET_RDES0_RERR: receive error + \arg ENET_RDES0_RWDT: receive watchdog timeout + \arg ENET_RDES0_FRMT: frame type + \arg ENET_RDES0_LCO: late collision + \arg ENET_RDES0_IPHERR: IP frame header error + \arg ENET_RDES0_LDES: last descriptor + \arg ENET_RDES0_FDES: first descriptor + \arg ENET_RDES0_VTAG: VLAN tag + \arg ENET_RDES0_OERR: overflow error + \arg ENET_RDES0_LERR: length error + \arg ENET_RDES0_SAFF: SA filter fail + \arg ENET_RDES0_DERR: descriptor error + \arg ENET_RDES0_ERRS: error summary + \arg ENET_RDES0_DAFF: destination address filter fail + \arg ENET_RDES0_DAV: descriptor available + \param[out] none + \retval FlagStatus: SET or RESET +*/ +FlagStatus enet_desc_flag_get(enet_descriptors_struct *desc, uint32_t desc_flag) +{ + FlagStatus enet_flag = RESET; + + if ((uint32_t)RESET != (desc->status & desc_flag)){ + enet_flag = SET; + } + + return enet_flag; +} + +/*! + \brief set the bit flag of ENET DMA descriptor + \param[in] desc: the descriptor pointer which users want to set flag + \param[in] desc_flag: the bit flag of ENET DMA descriptor, + only one parameter can be selected which is shown as below + \arg ENET_TDES0_VFRM: VLAN frame + \arg ENET_TDES0_FRMF: frame flushed + \arg ENET_TDES0_TCHM: the second address chained mode + \arg ENET_TDES0_TERM: transmit end of ring mode + \arg ENET_TDES0_TTSEN: transmit timestamp function enable + \arg ENET_TDES0_DPAD: disable adding pad + \arg ENET_TDES0_DCRC: disable CRC + \arg ENET_TDES0_FSG: first segment + \arg ENET_TDES0_LSG: last segment + \arg ENET_TDES0_INTC: interrupt on completion + \arg ENET_TDES0_DAV: DAV bit + \arg ENET_RDES0_DAV: descriptor available + \param[out] none + \retval none +*/ +void enet_desc_flag_set(enet_descriptors_struct *desc, uint32_t desc_flag) +{ + desc->status |= desc_flag; +} + +/*! + \brief clear the bit flag of ENET DMA descriptor + \param[in] desc: the descriptor pointer which users want to clear flag + \param[in] desc_flag: the bit flag of ENET DMA descriptor, + only one parameter can be selected which is shown as below + \arg ENET_TDES0_VFRM: VLAN frame + \arg ENET_TDES0_FRMF: frame flushed + \arg ENET_TDES0_TCHM: the second address chained mode + \arg ENET_TDES0_TERM: transmit end of ring mode + \arg ENET_TDES0_TTSEN: transmit timestamp function enable + \arg ENET_TDES0_DPAD: disable adding pad + \arg ENET_TDES0_DCRC: disable CRC + \arg ENET_TDES0_FSG: first segment + \arg ENET_TDES0_LSG: last segment + \arg ENET_TDES0_INTC: interrupt on completion + \arg ENET_TDES0_DAV: DAV bit + \arg ENET_RDES0_DAV: descriptor available + \param[out] none + \retval none +*/ +void enet_desc_flag_clear(enet_descriptors_struct *desc, uint32_t desc_flag) +{ + desc->status &= ~desc_flag; +} + +/*! + \brief when receiving completed, set RS bit in ENET_DMA_STAT register will set + \param[in] desc: the descriptor pointer which users want to configure + \param[out] none + \retval none +*/ +void enet_desc_receive_complete_bit_enable(enet_descriptors_struct *desc) +{ + desc->control_buffer_size &= ~ENET_RDES1_DINTC; +} + +/*! + \brief when receiving completed, set RS bit in ENET_DMA_STAT register will not set + \param[in] desc: the descriptor pointer which users want to configure + \param[out] none + \retval none +*/ +void enet_desc_receive_complete_bit_disable(enet_descriptors_struct *desc) +{ + desc->control_buffer_size |= ENET_RDES1_DINTC; +} + +/*! + \brief drop current receive frame + \param[in] none + \param[out] none + \retval none +*/ +void enet_rxframe_drop(void) +{ + /* enable reception, descriptor is owned by DMA */ + dma_current_rxdesc->status = ENET_RDES0_DAV; + + /* chained mode */ + if((uint32_t)RESET != (dma_current_rxdesc->control_buffer_size & ENET_RDES1_RCHM)){ + if(NULL != dma_current_ptp_rxdesc){ + dma_current_rxdesc = (enet_descriptors_struct*) (dma_current_ptp_rxdesc->buffer2_next_desc_addr); + /* if it is the last ptp descriptor */ + if(0U != dma_current_ptp_rxdesc->status){ + /* pointer back to the first ptp descriptor address in the desc_ptptab list address */ + dma_current_ptp_rxdesc = (enet_descriptors_struct*) (dma_current_ptp_rxdesc->status); + }else{ + /* ponter to the next ptp descriptor */ + dma_current_ptp_rxdesc++; + } + }else{ + dma_current_rxdesc = (enet_descriptors_struct*) (dma_current_rxdesc->buffer2_next_desc_addr); + } + + }else{ + /* ring mode */ + if((uint32_t)RESET != (dma_current_rxdesc->control_buffer_size & ENET_RDES1_RERM)){ + /* if is the last descriptor in table, the next descriptor is the table header */ + dma_current_rxdesc = (enet_descriptors_struct*) (ENET_DMA_RDTADDR); + if(NULL != dma_current_ptp_rxdesc){ + dma_current_ptp_rxdesc = (enet_descriptors_struct*) (dma_current_ptp_rxdesc->status); + } + }else{ + /* the next descriptor is the current address, add the descriptor size, and descriptor skip length */ + dma_current_rxdesc = (enet_descriptors_struct*) (uint32_t)((uint32_t)dma_current_rxdesc + ETH_DMARXDESC_SIZE + GET_DMA_BCTL_DPSL(ENET_DMA_BCTL)); + if(NULL != dma_current_ptp_rxdesc){ + dma_current_ptp_rxdesc++; + } + } + } +} + +/*! + \brief enable DMA feature + \param[in] feature: the feature of DMA mode, + one or more parameters can be selected which are shown as below + \arg ENET_NO_FLUSH_RXFRAME: RxDMA does not flushes frames function + \arg ENET_SECONDFRAME_OPT: TxDMA controller operate on second frame function + \param[out] none + \retval none +*/ +void enet_dma_feature_enable(uint32_t feature) +{ + ENET_DMA_CTL |= feature; +} + +/*! + \brief disable DMA feature + \param[in] feature: the feature of DMA mode, + one or more parameters can be selected which are shown as below + \arg ENET_NO_FLUSH_RXFRAME: RxDMA does not flushes frames function + \arg ENET_SECONDFRAME_OPT: TxDMA controller operate on second frame function + \param[out] none + \retval none +*/ +void enet_dma_feature_disable(uint32_t feature) +{ + ENET_DMA_CTL &= ~feature; +} + +/*! + \brief initialize the DMA Tx/Rx descriptors's parameters in normal chain mode with PTP function + \param[in] direction: the descriptors which users want to init, refer to enet_dmadirection_enum, + only one parameter can be selected which is shown as below + \arg ENET_DMA_TX: DMA Tx descriptors + \arg ENET_DMA_RX: DMA Rx descriptors + \param[in] desc_ptptab: pointer to the first descriptor address of PTP Rx descriptor table + \param[out] none + \retval none +*/ +void enet_ptp_normal_descriptors_chain_init(enet_dmadirection_enum direction, enet_descriptors_struct *desc_ptptab) +{ + uint32_t num = 0U, count = 0U, maxsize = 0U; + uint32_t desc_status = 0U, desc_bufsize = 0U; + enet_descriptors_struct *desc, *desc_tab; + uint8_t *buf; + + /* if want to initialize DMA Tx descriptors */ + if (ENET_DMA_TX == direction){ + /* save a copy of the DMA Tx descriptors */ + desc_tab = txdesc_tab; + buf = &tx_buff[0][0]; + count = ENET_TXBUF_NUM; + maxsize = ENET_TXBUF_SIZE; + + /* select chain mode, and enable transmit timestamp function */ + desc_status = ENET_TDES0_TCHM | ENET_TDES0_TTSEN; + + /* configure DMA Tx descriptor table address register */ + ENET_DMA_TDTADDR = (uint32_t)desc_tab; + dma_current_txdesc = desc_tab; + dma_current_ptp_txdesc = desc_ptptab; + }else{ + /* if want to initialize DMA Rx descriptors */ + /* save a copy of the DMA Rx descriptors */ + desc_tab = rxdesc_tab; + buf = &rx_buff[0][0]; + count = ENET_RXBUF_NUM; + maxsize = ENET_RXBUF_SIZE; + + /* enable receiving */ + desc_status = ENET_RDES0_DAV; + /* select receive chained mode and set buffer1 size */ + desc_bufsize = ENET_RDES1_RCHM | (uint32_t)ENET_RXBUF_SIZE; + + /* configure DMA Rx descriptor table address register */ + ENET_DMA_RDTADDR = (uint32_t)desc_tab; + dma_current_rxdesc = desc_tab; + dma_current_ptp_rxdesc = desc_ptptab; + } + + /* configure each descriptor */ + for(num = 0U; num < count; num++){ + /* get the pointer to the next descriptor of the descriptor table */ + desc = desc_tab + num; + + /* configure descriptors */ + desc->status = desc_status; + desc->control_buffer_size = desc_bufsize; + desc->buffer1_addr = (uint32_t)(&buf[num * maxsize]); + + /* if is not the last descriptor */ + if(num < (count - 1U)){ + /* configure the next descriptor address */ + desc->buffer2_next_desc_addr = (uint32_t)(desc_tab + num + 1U); + }else{ + /* when it is the last descriptor, the next descriptor address + equals to first descriptor address in descriptor table */ + desc->buffer2_next_desc_addr = (uint32_t)desc_tab; + } + /* set desc_ptptab equal to desc_tab */ + (&desc_ptptab[num])->buffer1_addr = desc->buffer1_addr; + (&desc_ptptab[num])->buffer2_next_desc_addr = desc->buffer2_next_desc_addr; + } + /* when it is the last ptp descriptor, preserve the first descriptor + address of desc_ptptab in ptp descriptor status */ + (&desc_ptptab[num-1U])->status = (uint32_t)desc_ptptab; +} + +/*! + \brief initialize the DMA Tx/Rx descriptors's parameters in normal ring mode with PTP function + \param[in] direction: the descriptors which users want to init, refer to enet_dmadirection_enum, + only one parameter can be selected which is shown as below + \arg ENET_DMA_TX: DMA Tx descriptors + \arg ENET_DMA_RX: DMA Rx descriptors + \param[in] desc_ptptab: pointer to the first descriptor address of PTP Rx descriptor table + \param[out] none + \retval none +*/ +void enet_ptp_normal_descriptors_ring_init(enet_dmadirection_enum direction, enet_descriptors_struct *desc_ptptab) +{ + uint32_t num = 0U, count = 0U, maxsize = 0U; + uint32_t desc_status = 0U, desc_bufsize = 0U; + enet_descriptors_struct *desc, *desc_tab; + uint8_t *buf; + + /* configure descriptor skip length */ + ENET_DMA_BCTL &= ~ENET_DMA_BCTL_DPSL; + ENET_DMA_BCTL |= DMA_BCTL_DPSL(0); + + /* if want to initialize DMA Tx descriptors */ + if (ENET_DMA_TX == direction){ + /* save a copy of the DMA Tx descriptors */ + desc_tab = txdesc_tab; + buf = &tx_buff[0][0]; + count = ENET_TXBUF_NUM; + maxsize = ENET_TXBUF_SIZE; + + /* select ring mode, and enable transmit timestamp function */ + desc_status = ENET_TDES0_TTSEN; + + /* configure DMA Tx descriptor table address register */ + ENET_DMA_TDTADDR = (uint32_t)desc_tab; + dma_current_txdesc = desc_tab; + dma_current_ptp_txdesc = desc_ptptab; + }else{ + /* if want to initialize DMA Rx descriptors */ + /* save a copy of the DMA Rx descriptors */ + desc_tab = rxdesc_tab; + buf = &rx_buff[0][0]; + count = ENET_RXBUF_NUM; + maxsize = ENET_RXBUF_SIZE; + + /* enable receiving */ + desc_status = ENET_RDES0_DAV; + /* select receive ring mode and set buffer1 size */ + desc_bufsize = (uint32_t)ENET_RXBUF_SIZE; + + /* configure DMA Rx descriptor table address register */ + ENET_DMA_RDTADDR = (uint32_t)desc_tab; + dma_current_rxdesc = desc_tab; + dma_current_ptp_rxdesc = desc_ptptab; + } + + /* configure each descriptor */ + for(num = 0U; num < count; num++){ + /* get the pointer to the next descriptor of the descriptor table */ + desc = desc_tab + num; + + /* configure descriptors */ + desc->status = desc_status; + desc->control_buffer_size = desc_bufsize; + desc->buffer1_addr = (uint32_t)(&buf[num * maxsize]); + + /* when it is the last descriptor */ + if(num == (count - 1U)){ + if (ENET_DMA_TX == direction){ + /* configure transmit end of ring mode */ + desc->status |= ENET_TDES0_TERM; + }else{ + /* configure receive end of ring mode */ + desc->control_buffer_size |= ENET_RDES1_RERM; + } + } + /* set desc_ptptab equal to desc_tab */ + (&desc_ptptab[num])->buffer1_addr = desc->buffer1_addr; + (&desc_ptptab[num])->buffer2_next_desc_addr = desc->buffer2_next_desc_addr; + } + /* when it is the last ptp descriptor, preserve the first descriptor + address of desc_ptptab in ptp descriptor status */ + (&desc_ptptab[num-1U])->status = (uint32_t)desc_ptptab; +} + +/*! + \brief receive a packet data with timestamp values to application buffer, when the DMA is in normal mode + \param[in] bufsize: the size of buffer which is the parameter in function + \param[out] timestamp: pointer to the table which stores the timestamp high and low + \param[out] buffer: pointer to the application buffer + note -- if the input is NULL, user should copy data in application by himself + \retval ErrStatus: SUCCESS or ERROR +*/ +ErrStatus enet_ptpframe_receive_normal_mode(uint8_t *buffer, uint32_t bufsize, uint32_t timestamp[]) +{ + uint32_t offset = 0U, size = 0U; + + /* the descriptor is busy due to own by the DMA */ + if((uint32_t)RESET != (dma_current_rxdesc->status & ENET_RDES0_DAV)){ + return ERROR; + } + + /* if buffer pointer is null, indicates that users has copied data in application */ + if(NULL != buffer){ + /* if no error occurs, and the frame uses only one descriptor */ + if(((uint32_t)RESET == (dma_current_rxdesc->status & ENET_RDES0_ERRS)) && + ((uint32_t)RESET != (dma_current_rxdesc->status & ENET_RDES0_LDES)) && + ((uint32_t)RESET != (dma_current_rxdesc->status & ENET_RDES0_FDES))){ + + /* get the frame length except CRC */ + size = GET_RDES0_FRML(dma_current_rxdesc->status) - 4U; + + /* to avoid situation that the frame size exceeds the buffer length */ + if(size > bufsize){ + return ERROR; + } + + /* copy data from Rx buffer to application buffer */ + for(offset = 0U; offset < size; offset++){ + (*(buffer + offset)) = (*(__IO uint8_t *)(uint32_t)((dma_current_ptp_rxdesc->buffer1_addr) + offset)); + } + + }else{ + return ERROR; + } + } + /* copy timestamp value from Rx descriptor to application array */ + timestamp[0] = dma_current_rxdesc->buffer1_addr; + timestamp[1] = dma_current_rxdesc->buffer2_next_desc_addr; + + dma_current_rxdesc->buffer1_addr = dma_current_ptp_rxdesc ->buffer1_addr ; + dma_current_rxdesc->buffer2_next_desc_addr = dma_current_ptp_rxdesc ->buffer2_next_desc_addr; + + /* enable reception, descriptor is owned by DMA */ + dma_current_rxdesc->status = ENET_RDES0_DAV; + + /* check Rx buffer unavailable flag status */ + if ((uint32_t)RESET != (ENET_DMA_STAT & ENET_DMA_STAT_RBU)){ + /* clear RBU flag */ + ENET_DMA_STAT = ENET_DMA_STAT_RBU; + /* resume DMA reception by writing to the RPEN register*/ + ENET_DMA_RPEN = 0U; + } + + + /* update the current RxDMA descriptor pointer to the next decriptor in RxDMA decriptor table */ + /* chained mode */ + if((uint32_t)RESET != (dma_current_rxdesc->control_buffer_size & ENET_RDES1_RCHM)){ + dma_current_rxdesc = (enet_descriptors_struct*) (dma_current_ptp_rxdesc->buffer2_next_desc_addr); + /* if it is the last ptp descriptor */ + if(0U != dma_current_ptp_rxdesc->status){ + /* pointer back to the first ptp descriptor address in the desc_ptptab list address */ + dma_current_ptp_rxdesc = (enet_descriptors_struct*) (dma_current_ptp_rxdesc->status); + }else{ + /* ponter to the next ptp descriptor */ + dma_current_ptp_rxdesc++; + } + }else{ + /* ring mode */ + if((uint32_t)RESET != (dma_current_rxdesc->control_buffer_size & ENET_RDES1_RERM)){ + /* if is the last descriptor in table, the next descriptor is the table header */ + dma_current_rxdesc = (enet_descriptors_struct*) (ENET_DMA_RDTADDR); + /* RDES2 and RDES3 will not be covered by buffer address, so do not need to preserve a new table, + use the same table with RxDMA descriptor */ + dma_current_ptp_rxdesc = (enet_descriptors_struct*) (dma_current_ptp_rxdesc->status); + }else{ + /* the next descriptor is the current address, add the descriptor size, and descriptor skip length */ + dma_current_rxdesc = (enet_descriptors_struct*) (uint32_t)((uint32_t)dma_current_rxdesc + ETH_DMARXDESC_SIZE + GET_DMA_BCTL_DPSL(ENET_DMA_BCTL)); + dma_current_ptp_rxdesc ++; + } + } + + return SUCCESS; +} + +/*! + \brief send data with timestamp values in application buffer as a transmit packet, when the DMA is in normal mode + \param[in] buffer: pointer on the application buffer + note -- if the input is NULL, user should copy data in application by himself + \param[in] length: the length of frame data to be transmitted + \param[out] timestamp: pointer to the table which stores the timestamp high and low + note -- if the input is NULL, timestamp is ignored + \retval ErrStatus: SUCCESS or ERROR +*/ +ErrStatus enet_ptpframe_transmit_normal_mode(uint8_t *buffer, uint32_t length, uint32_t timestamp[]) +{ + uint32_t offset = 0U, timeout = 0U; + uint32_t dma_tbu_flag, dma_tu_flag, tdes0_ttmss_flag; + + /* the descriptor is busy due to own by the DMA */ + if((uint32_t)RESET != (dma_current_txdesc->status & ENET_TDES0_DAV)){ + return ERROR; + } + + /* only frame length no more than ENET_MAX_FRAME_SIZE is allowed */ + if(length > ENET_MAX_FRAME_SIZE){ + return ERROR; + } + + /* if buffer pointer is null, indicates that users has handled data in application */ + if(NULL != buffer){ + /* copy frame data from application buffer to Tx buffer */ + for(offset = 0U; offset < length; offset++){ + (*(__IO uint8_t *) (uint32_t)((dma_current_ptp_txdesc->buffer1_addr) + offset)) = (*(buffer + offset)); + } + } + /* set the frame length */ + dma_current_txdesc->control_buffer_size = (length & (uint32_t)0x1FFF); + /* set the segment of frame, frame is transmitted in one descriptor */ + dma_current_txdesc->status |= ENET_TDES0_LSG | ENET_TDES0_FSG; + /* enable the DMA transmission */ + dma_current_txdesc->status |= ENET_TDES0_DAV; + + /* check Tx buffer unavailable flag status */ + dma_tbu_flag = (ENET_DMA_STAT & ENET_DMA_STAT_TBU); + dma_tu_flag = (ENET_DMA_STAT & ENET_DMA_STAT_TU); + + if((RESET != dma_tbu_flag) || (RESET != dma_tu_flag)){ + /* clear TBU and TU flag */ + ENET_DMA_STAT = (dma_tbu_flag | dma_tu_flag); + /* resume DMA transmission by writing to the TPEN register*/ + ENET_DMA_TPEN = 0U; + } + + /* if timestamp pointer is null, indicates that users don't care timestamp in application */ + if(NULL != timestamp){ + /* wait for ENET_TDES0_TTMSS flag to be set, a timestamp was captured */ + do{ + tdes0_ttmss_flag = (dma_current_txdesc->status & ENET_TDES0_TTMSS); + timeout++; + }while((RESET == tdes0_ttmss_flag) && (timeout < ENET_DELAY_TO)); + + /* return ERROR due to timeout */ + if(ENET_DELAY_TO == timeout){ + return ERROR; + } + + /* clear the ENET_TDES0_TTMSS flag */ + dma_current_txdesc->status &= ~ENET_TDES0_TTMSS; + /* get the timestamp value of the transmit frame */ + timestamp[0] = dma_current_txdesc->buffer1_addr; + timestamp[1] = dma_current_txdesc->buffer2_next_desc_addr; + } + dma_current_txdesc->buffer1_addr = dma_current_ptp_txdesc ->buffer1_addr ; + dma_current_txdesc->buffer2_next_desc_addr = dma_current_ptp_txdesc ->buffer2_next_desc_addr; + + /* update the current TxDMA descriptor pointer to the next decriptor in TxDMA decriptor table */ + /* chained mode */ + if((uint32_t)RESET != (dma_current_txdesc->status & ENET_TDES0_TCHM)){ + dma_current_txdesc = (enet_descriptors_struct*) (dma_current_ptp_txdesc->buffer2_next_desc_addr); + /* if it is the last ptp descriptor */ + if(0U != dma_current_ptp_txdesc->status){ + /* pointer back to the first ptp descriptor address in the desc_ptptab list address */ + dma_current_ptp_txdesc = (enet_descriptors_struct*) (dma_current_ptp_txdesc->status); + }else{ + /* ponter to the next ptp descriptor */ + dma_current_ptp_txdesc++; + } + }else{ + /* ring mode */ + if((uint32_t)RESET != (dma_current_txdesc->status & ENET_TDES0_TERM)){ + /* if is the last descriptor in table, the next descriptor is the table header */ + dma_current_txdesc = (enet_descriptors_struct*) (ENET_DMA_TDTADDR); + /* TDES2 and TDES3 will not be covered by buffer address, so do not need to preserve a new table, + use the same table with TxDMA descriptor */ + dma_current_ptp_txdesc = (enet_descriptors_struct*) (dma_current_ptp_txdesc->status); + }else{ + /* the next descriptor is the current address, add the descriptor size, and descriptor skip length */ + dma_current_txdesc = (enet_descriptors_struct*) (uint32_t)((uint32_t)dma_current_txdesc + ETH_DMATXDESC_SIZE + GET_DMA_BCTL_DPSL(ENET_DMA_BCTL)); + dma_current_ptp_txdesc ++; + } + } + return SUCCESS; +} + +/*! + \brief wakeup frame filter register pointer reset + \param[in] none + \param[out] none + \retval none +*/ +void enet_wum_filter_register_pointer_reset(void) +{ + ENET_MAC_WUM |= ENET_MAC_WUM_WUFFRPR; +} + +/*! + \brief set the remote wakeup frame registers + \param[in] pdata: pointer to buffer data which is written to remote wakeup frame registers (8 words total) + \param[out] none + \retval none +*/ +void enet_wum_filter_config(uint32_t pdata[]) +{ + uint32_t num = 0U; + + /* configure ENET_MAC_RWFF register */ + for(num = 0U; num < ETH_WAKEUP_REGISTER_LENGTH; num++){ + ENET_MAC_RWFF = pdata[num]; + } +} + +/*! + \brief enable wakeup management features + \param[in] feature: one or more parameters can be selected which are shown as below + \arg ENET_WUM_POWER_DOWN: power down mode + \arg ENET_WUM_MAGIC_PACKET_FRAME: enable a wakeup event due to magic packet reception + \arg ENET_WUM_WAKE_UP_FRAME: enable a wakeup event due to wakeup frame reception + \arg ENET_WUM_GLOBAL_UNICAST: any received unicast frame passed filter is considered to be a wakeup frame + \param[out] none + \retval none +*/ +void enet_wum_feature_enable(uint32_t feature) +{ + ENET_MAC_WUM |= feature; +} + +/*! + \brief disable wakeup management features + \param[in] feature: one or more parameters can be selected which are shown as below + \arg ENET_WUM_MAGIC_PACKET_FRAME: enable a wakeup event due to magic packet reception + \arg ENET_WUM_WAKE_UP_FRAME: enable a wakeup event due to wakeup frame reception + \arg ENET_WUM_GLOBAL_UNICAST: any received unicast frame passed filter is considered to be a wakeup frame + \param[out] none + \retval none +*/ +void enet_wum_feature_disable(uint32_t feature) +{ + ENET_MAC_WUM &= (~feature); +} + +/*! + \brief reset the MAC statistics counters + \param[in] none + \param[out] none + \retval none +*/ +void enet_msc_counters_reset(void) +{ + /* reset all counters */ + ENET_MSC_CTL |= ENET_MSC_CTL_CTR; +} + +/*! + \brief enable the MAC statistics counter features + \param[in] feature: one or more parameters can be selected which are shown as below + \arg ENET_MSC_COUNTER_STOP_ROLLOVER: counter stop rollover + \arg ENET_MSC_RESET_ON_READ: reset on read + \arg ENET_MSC_COUNTERS_FREEZE: MSC counter freeze + \param[out] none + \retval none +*/ +void enet_msc_feature_enable(uint32_t feature) +{ + ENET_MSC_CTL |= feature; +} + +/*! + \brief disable the MAC statistics counter features + \param[in] feature: one or more parameters can be selected which are shown as below + \arg ENET_MSC_COUNTER_STOP_ROLLOVER: counter stop rollover + \arg ENET_MSC_RESET_ON_READ: reset on read + \arg ENET_MSC_COUNTERS_FREEZE: MSC counter freeze + \param[out] none + \retval none +*/ +void enet_msc_feature_disable(uint32_t feature) +{ + ENET_MSC_CTL &= (~feature); +} + +/*! + \brief get MAC statistics counter + \param[in] counter: MSC counters which is selected, refer to enet_msc_counter_enum, + only one parameter can be selected which is shown as below + \arg ENET_MSC_TX_SCCNT: MSC transmitted good frames after a single collision counter + \arg ENET_MSC_TX_MSCCNT: MSC transmitted good frames after more than a single collision counter + \arg ENET_MSC_TX_TGFCNT: MSC transmitted good frames counter + \arg ENET_MSC_RX_RFCECNT: MSC received frames with CRC error counter + \arg ENET_MSC_RX_RFAECNT: MSC received frames with alignment error counter + \arg ENET_MSC_RX_RGUFCNT: MSC received good unicast frames counter + \param[out] none + \retval the MSC counter value +*/ +uint32_t enet_msc_counters_get(enet_msc_counter_enum counter) +{ + uint32_t reval; + + reval = REG32((ENET + (uint32_t)counter)); + + return reval; +} + +/*! + \brief change subsecond to nanosecond + \param[in] subsecond: subsecond value + \param[out] none + \retval the nanosecond value +*/ +uint32_t enet_ptp_subsecond_2_nanosecond(uint32_t subsecond) +{ + uint64_t val = subsecond * 1000000000Ull; + val >>= 31; + return (uint32_t)val; +} + +/*! + \brief change nanosecond to subsecond + \param[in] nanosecond: nanosecond value + \param[out] none + \retval the subsecond value +*/ +uint32_t enet_ptp_nanosecond_2_subsecond(uint32_t nanosecond) +{ + uint64_t val = nanosecond * 0x80000000Ull; + val /= 1000000000U; + return (uint32_t)val; +} + +/*! + \brief enable the PTP features + \param[in] feature: the feature of ENET PTP mode + one or more parameters can be selected which are shown as below + \arg ENET_RXTX_TIMESTAMP: timestamp function for transmit and receive frames + \arg ENET_PTP_TIMESTAMP_INT: timestamp interrupt trigger + \param[out] none + \retval none +*/ +void enet_ptp_feature_enable(uint32_t feature) +{ + ENET_PTP_TSCTL |= feature; +} + +/*! + \brief disable the PTP features + \param[in] feature: the feature of ENET PTP mode + one or more parameters can be selected which are shown as below + \arg ENET_RXTX_TIMESTAMP: timestamp function for transmit and receive frames + \arg ENET_PTP_TIMESTAMP_INT: timestamp interrupt trigger + \param[out] none + \retval none +*/ +void enet_ptp_feature_disable(uint32_t feature) +{ + ENET_PTP_TSCTL &= ~feature; +} + +/*! + \brief configure the PTP timestamp function + \param[in] func: only one parameter can be selected which is shown as below + \arg ENET_PTP_ADDEND_UPDATE: addend register update + \arg ENET_PTP_SYSTIME_UPDATE: timestamp update + \arg ENET_PTP_SYSTIME_INIT: timestamp initialize + \arg ENET_PTP_FINEMODE: the system timestamp uses the fine method for updating + \arg ENET_PTP_COARSEMODE: the system timestamp uses the coarse method for updating + \param[out] none + \retval ErrStatus: SUCCESS or ERROR +*/ + +ErrStatus enet_ptp_timestamp_function_config(enet_ptp_function_enum func) +{ + uint32_t temp_config = 0U, temp_state = 0U; + uint32_t timeout = 0U; + ErrStatus enet_state = SUCCESS; + + switch(func){ + case ENET_PTP_ADDEND_UPDATE: + /* this bit must be read as zero before application set it */ + do{ + temp_state = ENET_PTP_TSCTL & ENET_PTP_TSCTL_TMSARU; + timeout++; + }while((RESET != temp_state) && (timeout < ENET_DELAY_TO)); + /* return ERROR due to timeout */ + if(ENET_DELAY_TO == timeout){ + enet_state = ERROR; + }else{ + ENET_PTP_TSCTL |= ENET_PTP_TSCTL_TMSARU; + } + break; + case ENET_PTP_SYSTIME_UPDATE: + /* both the TMSSTU and TMSSTI bits must be read as zero before application set this bit */ + do{ + temp_state = ENET_PTP_TSCTL & (ENET_PTP_TSCTL_TMSSTU | ENET_PTP_TSCTL_TMSSTI); + timeout++; + }while((RESET != temp_state) && (timeout < ENET_DELAY_TO)); + /* return ERROR due to timeout */ + if(ENET_DELAY_TO == timeout){ + enet_state = ERROR; + }else{ + ENET_PTP_TSCTL |= ENET_PTP_TSCTL_TMSSTU; + } + break; + case ENET_PTP_SYSTIME_INIT: + /* this bit must be read as zero before application set it */ + do{ + temp_state = ENET_PTP_TSCTL & ENET_PTP_TSCTL_TMSSTI; + timeout++; + }while((RESET != temp_state) && (timeout < ENET_DELAY_TO)); + /* return ERROR due to timeout */ + if(ENET_DELAY_TO == timeout){ + enet_state = ERROR; + }else{ + ENET_PTP_TSCTL |= ENET_PTP_TSCTL_TMSSTI; + } + break; + default: + temp_config = (uint32_t)func & (~BIT(31)); + if(RESET != ((uint32_t)func & BIT(31))){ + ENET_PTP_TSCTL |= temp_config; + }else{ + ENET_PTP_TSCTL &= ~temp_config; + } + break; + } + + return enet_state; +} + +/*! + \brief configure system time subsecond increment value + \param[in] subsecond: the value will be added to the subsecond value of system time, + this value must be between 0 and 0xFF + \param[out] none + \retval none +*/ +void enet_ptp_subsecond_increment_config(uint32_t subsecond) +{ + ENET_PTP_SSINC = PTP_SSINC_STMSSI(subsecond); +} + +/*! + \brief adjusting the clock frequency only in fine update mode + \param[in] add: the value will be added to the accumulator register to achieve time synchronization + \param[out] none + \retval none +*/ +void enet_ptp_timestamp_addend_config(uint32_t add) +{ + ENET_PTP_TSADDEND = add; +} + +/*! + \brief initialize or add/subtract to second of the system time + \param[in] sign: timestamp update positive or negative sign, + only one parameter can be selected which is shown as below + \arg ENET_PTP_ADD_TO_TIME: timestamp update value is added to system time + \arg ENET_PTP_SUBSTRACT_FROM_TIME: timestamp update value is subtracted from system time + \param[in] second: initializing or adding/subtracting to second of the system time + \param[in] subsecond: the current subsecond of the system time + with 0.46 ns accuracy if required accuracy is 20 ns + \param[out] none + \retval none +*/ +void enet_ptp_timestamp_update_config(uint32_t sign, uint32_t second, uint32_t subsecond) +{ + ENET_PTP_TSUH = second; + ENET_PTP_TSUL = sign | PTP_TSUL_TMSUSS(subsecond); +} + +/*! + \brief configure the expected target time + \param[in] second: the expected target second time + \param[in] nanosecond: the expected target nanosecond time (signed) + \param[out] none + \retval none +*/ +void enet_ptp_expected_time_config(uint32_t second, uint32_t nanosecond) +{ + ENET_PTP_ETH = second; + ENET_PTP_ETL = nanosecond; +} + +/*! + \brief get the current system time + \param[in] none + \param[out] systime_struct: pointer to a enet_ptp_systime_struct structure which contains + parameters of PTP system time + members of the structure and the member values are shown as below: + second: 0x0 - 0xFFFF FFFF + nanosecond: 0x0 - 0x7FFF FFFF * 10^9 / 2^31 + sign: ENET_PTP_TIME_POSITIVE, ENET_PTP_TIME_NEGATIVE + \retval none +*/ +void enet_ptp_system_time_get(enet_ptp_systime_struct *systime_struct) +{ + uint32_t temp_sec = 0U, temp_subs = 0U; + + /* get the value of sysytem time registers */ + temp_sec = (uint32_t)ENET_PTP_TSH; + temp_subs = (uint32_t)ENET_PTP_TSL; + + /* get sysytem time and construct the enet_ptp_systime_struct structure */ + systime_struct->second = temp_sec; + systime_struct->nanosecond = GET_PTP_TSL_STMSS(temp_subs); + systime_struct->nanosecond = enet_ptp_subsecond_2_nanosecond(systime_struct->nanosecond); + systime_struct->sign = GET_PTP_TSL_STS(temp_subs); +} + +/*! + \brief configure and start PTP timestamp counter + \param[in] updatemethod: method for updating + \arg ENET_PTP_FINEMODE: fine correction method + \arg ENET_PTP_COARSEMODE: coarse correction method + \param[in] init_sec: second value for initializing system time + \param[in] init_subsec: subsecond value for initializing system time + \param[in] carry_cfg: the value to be added to the accumulator register (in fine method is used) + \param[in] accuracy_cfg: the value to be added to the subsecond value of system time + \param[out] none + \retval none +*/ +void enet_ptp_start(int32_t updatemethod, uint32_t init_sec, uint32_t init_subsec, uint32_t carry_cfg, uint32_t accuracy_cfg) +{ + /* mask the timestamp trigger interrupt */ + enet_interrupt_disable(ENET_MAC_INT_TMSTIM); + + /* enable timestamp */ + enet_ptp_feature_enable(ENET_RXTX_TIMESTAMP); + + /* configure system time subsecond increment based on the PTP clock frequency */ + enet_ptp_subsecond_increment_config(accuracy_cfg); + + if(ENET_PTP_FINEMODE == updatemethod){ + /* fine correction method: configure the timestamp addend, then update */ + enet_ptp_timestamp_addend_config(carry_cfg); + enet_ptp_timestamp_function_config(ENET_PTP_ADDEND_UPDATE); + /* wait until update is completed */ + while(SET == enet_ptp_flag_get((uint32_t)ENET_PTP_ADDEND_UPDATE)){ + } + } + + /* choose the fine correction method */ + enet_ptp_timestamp_function_config((enet_ptp_function_enum)updatemethod); + + /* initialize the system time */ + enet_ptp_timestamp_update_config(ENET_PTP_ADD_TO_TIME, init_sec, init_subsec); + enet_ptp_timestamp_function_config(ENET_PTP_SYSTIME_INIT); +} + +/*! + \brief adjust frequency in fine method by configure addend register + \param[in] carry_cfg: the value to be added to the accumulator register + \param[out] none + \retval none +*/ +void enet_ptp_finecorrection_adjfreq(int32_t carry_cfg) +{ + /* re-configure the timestamp addend, then update */ + enet_ptp_timestamp_addend_config((uint32_t)carry_cfg); + enet_ptp_timestamp_function_config(ENET_PTP_ADDEND_UPDATE); +} + +/*! + \brief update system time in coarse method + \param[in] systime_struct: pointer to a enet_ptp_systime_struct structure which contains + parameters of PTP system time + members of the structure and the member values are shown as below: + second: 0x0 - 0xFFFF FFFF + nanosecond: 0x0 - 0x7FFF FFFF * 10^9 / 2^31 + sign: ENET_PTP_TIME_POSITIVE, ENET_PTP_TIME_NEGATIVE + \param[out] none + \retval none +*/ +void enet_ptp_coarsecorrection_systime_update(enet_ptp_systime_struct *systime_struct) +{ + uint32_t subsecond_val; + uint32_t carry_cfg; + + subsecond_val = enet_ptp_nanosecond_2_subsecond(systime_struct->nanosecond); + + /* save the carry_cfg value */ + carry_cfg = ENET_PTP_TSADDEND_TMSA; + + /* update the system time */ + enet_ptp_timestamp_update_config(systime_struct->sign, systime_struct->second, subsecond_val); + enet_ptp_timestamp_function_config(ENET_PTP_SYSTIME_UPDATE); + + /* wait until the update is completed */ + while(SET == enet_ptp_flag_get((uint32_t)ENET_PTP_SYSTIME_UPDATE)){ + } + + /* write back the carry_cfg value, then update */ + enet_ptp_timestamp_addend_config(carry_cfg); + enet_ptp_timestamp_function_config(ENET_PTP_ADDEND_UPDATE); +} + +/*! + \brief set system time in fine method + \param[in] systime_struct: pointer to a enet_ptp_systime_struct structure which contains + parameters of PTP system time + members of the structure and the member values are shown as below: + second: 0x0 - 0xFFFF FFFF + nanosecond: 0x0 - 0x7FFF FFFF * 10^9 / 2^31 + sign: ENET_PTP_TIME_POSITIVE, ENET_PTP_TIME_NEGATIVE + \param[out] none + \retval none +*/ +void enet_ptp_finecorrection_settime(enet_ptp_systime_struct * systime_struct) +{ + uint32_t subsecond_val; + + subsecond_val = enet_ptp_nanosecond_2_subsecond(systime_struct->nanosecond); + + /* initialize the system time */ + enet_ptp_timestamp_update_config(systime_struct->sign, systime_struct->second, subsecond_val); + enet_ptp_timestamp_function_config(ENET_PTP_SYSTIME_INIT); + + /* wait until the system time initialzation finished */ + while(SET == enet_ptp_flag_get((uint32_t)ENET_PTP_SYSTIME_INIT)){ + } +} + +/*! + \brief get the ptp flag status + \param[in] flag: ptp flag status to be checked + \arg ENET_PTP_ADDEND_UPDATE: addend register update + \arg ENET_PTP_SYSTIME_UPDATE: timestamp update + \arg ENET_PTP_SYSTIME_INIT: timestamp initialize + \param[out] none + \retval FlagStatus: SET or RESET +*/ +FlagStatus enet_ptp_flag_get(uint32_t flag) +{ + FlagStatus bitstatus = RESET; + + if ((uint32_t)RESET != (ENET_PTP_TSCTL & flag)){ + bitstatus = SET; + } + + return bitstatus; +} + +/*! + \brief reset the ENET initpara struct, call it before using enet_initpara_config() + \param[in] none + \param[out] none + \retval none +*/ +void enet_initpara_reset(void) +{ + enet_initpara.option_enable = 0U; + enet_initpara.forward_frame = 0U; + enet_initpara.dmabus_mode = 0U; + enet_initpara.dma_maxburst = 0U; + enet_initpara.dma_arbitration = 0U; + enet_initpara.store_forward_mode = 0U; + enet_initpara.dma_function = 0U; + enet_initpara.vlan_config = 0U; + enet_initpara.flow_control = 0U; + enet_initpara.hashtable_high = 0U; + enet_initpara.hashtable_low = 0U; + enet_initpara.framesfilter_mode = 0U; + enet_initpara.halfduplex_param = 0U; + enet_initpara.timer_config = 0U; + enet_initpara.interframegap = 0U; +} + +/*! + \brief initialize ENET peripheral with generally concerned parameters, call it by enet_init() + \param[in] none + \param[out] none + \retval none +*/ +static void enet_default_init(void) +{ + uint32_t reg_value = 0U; + + /* MAC */ + /* configure ENET_MAC_CFG register */ + reg_value = ENET_MAC_CFG; + reg_value &= MAC_CFG_MASK; + reg_value |= ENET_WATCHDOG_ENABLE | ENET_JABBER_ENABLE | ENET_INTERFRAMEGAP_96BIT \ + | ENET_SPEEDMODE_10M |ENET_MODE_HALFDUPLEX | ENET_LOOPBACKMODE_DISABLE \ + | ENET_CARRIERSENSE_ENABLE | ENET_RECEIVEOWN_ENABLE \ + | ENET_RETRYTRANSMISSION_ENABLE | ENET_BACKOFFLIMIT_10 \ + | ENET_DEFERRALCHECK_DISABLE \ + | ENET_AUTO_PADCRC_DROP_DISABLE \ + | ENET_CHECKSUMOFFLOAD_DISABLE; + ENET_MAC_CFG = reg_value; + + /* configure ENET_MAC_FRMF register */ + ENET_MAC_FRMF = ENET_SRC_FILTER_DISABLE |ENET_DEST_FILTER_INVERSE_DISABLE \ + |ENET_MULTICAST_FILTER_PERFECT |ENET_UNICAST_FILTER_PERFECT \ + |ENET_PCFRM_PREVENT_ALL |ENET_BROADCASTFRAMES_ENABLE \ + |ENET_PROMISCUOUS_DISABLE |ENET_RX_FILTER_ENABLE; + + /* configure ENET_MAC_HLH, ENET_MAC_HLL register */ + ENET_MAC_HLH = 0x0U; + + ENET_MAC_HLL = 0x0U; + + /* configure ENET_MAC_FCTL, ENET_MAC_FCTH register */ + reg_value = ENET_MAC_FCTL; + reg_value &= MAC_FCTL_MASK; + reg_value |= MAC_FCTL_PTM(0) |ENET_ZERO_QUANTA_PAUSE_DISABLE \ + |ENET_PAUSETIME_MINUS4 |ENET_UNIQUE_PAUSEDETECT \ + |ENET_RX_FLOWCONTROL_DISABLE |ENET_TX_FLOWCONTROL_DISABLE; + ENET_MAC_FCTL = reg_value; + + ENET_MAC_FCTH = ENET_DEACTIVE_THRESHOLD_512BYTES |ENET_ACTIVE_THRESHOLD_1536BYTES; + + /* configure ENET_MAC_VLT register */ + ENET_MAC_VLT = ENET_VLANTAGCOMPARISON_16BIT |MAC_VLT_VLTI(0); + + /* DMA */ + /* configure ENET_DMA_CTL register */ + reg_value = ENET_DMA_CTL; + reg_value &= DMA_CTL_MASK; + reg_value |= ENET_TCPIP_CKSUMERROR_DROP |ENET_RX_MODE_STOREFORWARD \ + |ENET_FLUSH_RXFRAME_ENABLE |ENET_TX_MODE_STOREFORWARD \ + |ENET_TX_THRESHOLD_64BYTES |ENET_RX_THRESHOLD_64BYTES \ + |ENET_FORWARD_ERRFRAMES_DISABLE |ENET_FORWARD_UNDERSZ_GOODFRAMES_DISABLE \ + |ENET_SECONDFRAME_OPT_DISABLE; + ENET_DMA_CTL = reg_value; + + /* configure ENET_DMA_BCTL register */ + reg_value = ENET_DMA_BCTL; + reg_value &= DMA_BCTL_MASK; + reg_value = ENET_ADDRESS_ALIGN_ENABLE |ENET_ARBITRATION_RXTX_2_1 \ + |ENET_RXDP_32BEAT |ENET_PGBL_32BEAT |ENET_RXTX_DIFFERENT_PGBL \ + |ENET_FIXED_BURST_ENABLE; + ENET_DMA_BCTL = reg_value; +} + +#ifndef USE_DELAY +/*! + \brief insert a delay time + \param[in] ncount: specifies the delay time length + \param[out] none + \param[out] none +*/ +static void enet_delay(uint32_t ncount) +{ + __IO uint32_t delay_time = 0U; + + for(delay_time = ncount; delay_time != 0U; delay_time--){ + } +} +#endif /* USE_DELAY */ + +#endif /* GD32F20X_CL */ diff --git a/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_standard_peripheral/Source/gd32f20x_exmc.c b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_standard_peripheral/Source/gd32f20x_exmc.c new file mode 100644 index 0000000000..cc2e62728c --- /dev/null +++ b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_standard_peripheral/Source/gd32f20x_exmc.c @@ -0,0 +1,1178 @@ +/*! + \file gd32f20x_exmc.c + \brief EXMC driver + + \version 2015-07-15, V1.0.0, firmware for GD32F20x + \version 2017-06-05, V2.0.0, firmware for GD32F20x + \version 2018-10-31, V2.1.0, firmware for GD32F20x + \version 2020-09-30, V2.2.0, firmware for GD32F20x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "gd32f20x_exmc.h" + +/* EXMC bank0 register reset value */ +#define BANK0_SNCTL_RESET ((uint32_t)0x000030DAU) +#define BANK0_SNTCFG_RESET ((uint32_t)0x0FFFFFFFU) +#define BANK0_SNWTCFG_RESET ((uint32_t)0x0FFFFFFFU) + +/* EXMC bank1/2 register reset mask*/ +#define BANK1_2_NPCTL_RESET ((uint32_t)0x00000008U) +#define BANK1_2_NPINTEN_RESET ((uint32_t)0x00000042U) +#define BANK1_2_NPCTCFG_RESET ((uint32_t)0xFFFFFFFFU) +#define BANK1_2_NPATCFG_RESET ((uint32_t)0xFFFFFFFFU) + +/* EXMC bank3 register reset mask*/ +#define BANK3_NPCTL_RESET ((uint32_t)0x00000008U) +#define BANK3_NPINTEN_RESET ((uint32_t)0x00000043U) +#define BANK3_NPCTCFG_RESET ((uint32_t)0xFFFFFFFFU) +#define BANK3_NPATCFG_RESET ((uint32_t)0xFFFFFFFFU) +#define BANK3_PIOTCFG3_RESET ((uint32_t)0xFFFFFFFFU) + +/* EXMC SDRAM device register reset mask */ +#define SDRAM_DEVICE_SDCTL_RESET ((uint32_t)0x000002D0U) +#define SDRAM_DEVICE_SDTCFG_RESET ((uint32_t)0x0FFFFFFFU) +#define SDRAM_DEVICE_SDCMD_RESET ((uint32_t)0x00000000U) +#define SDRAM_DEVICE_SDARI_RESET ((uint32_t)0x00000000U) +#define SDRAM_DEVICE_SDSTAT_RESET ((uint32_t)0x00000000U) +#define SDRAM_DEVICE_SDRSCTL_RESET ((uint32_t)0x00000000U) + +/* EXMC bank0 SQPI-PSRAM register reset mask */ +#define BANK0_SQPI_SINIT_RESET ((uint32_t)0x18010000U) +#define BANK0_SQPI_SRCMD_RESET ((uint32_t)0x00000000U) +#define BANK0_SQPI_SWCMD_RESET ((uint32_t)0x00000000U) +#define BANK0_SQPI_SIDL_RESET ((uint32_t)0x00000000U) +#define BANK0_SQPI_SIDH_RESET ((uint32_t)0x00000000U) + +/* EXMC register bit offset */ +#define SNCTL_NRMUX_OFFSET ((uint32_t)1U) +#define SNCTL_SBRSTEN_OFFSET ((uint32_t)8U) +#define SNCTL_WRAPEN_OFFSET ((uint32_t)10U) +#define SNCTL_WREN_OFFSET ((uint32_t)12U) +#define SNCTL_NRWTEN_OFFSET ((uint32_t)13U) +#define SNCTL_EXMODEN_OFFSET ((uint32_t)14U) +#define SNCTL_ASYNCWAIT_OFFSET ((uint32_t)15U) + +#define SNTCFG_AHLD_OFFSET ((uint32_t)4U) +#define SNTCFG_DSET_OFFSET ((uint32_t)8U) +#define SNTCFG_BUSLAT_OFFSET ((uint32_t)16U) + +#define NPCTL_NDWTEN_OFFSET ((uint32_t)1U) +#define NPCTL_ECCEN_OFFSET ((uint32_t)6U) + +#define NPCTCFG_COMWAIT_OFFSET ((uint32_t)8U) +#define NPCTCFG_COMHLD_OFFSET ((uint32_t)16U) +#define NPCTCFG_COMHIZ_OFFSET ((uint32_t)24U) + +#define NPATCFG_ATTWAIT_OFFSET ((uint32_t)8U) +#define NPATCFG_ATTHLD_OFFSET ((uint32_t)16U) +#define NPATCFG_ATTHIZ_OFFSET ((uint32_t)24U) + +#define PIOTCFG_IOWAIT_OFFSET ((uint32_t)8U) +#define PIOTCFG_IOHLD_OFFSET ((uint32_t)16U) +#define PIOTCFG_IOHIZ_OFFSET ((uint32_t)24U) + +#define SDCTL_WPEN_OFFSET ((uint32_t)9U) +#define SDCTL_BRSTRD_OFFSET ((uint32_t)12U) + +#define SDTCFG_XSRD_OFFSET ((uint32_t)4U) +#define SDTCFG_RASD_OFFSET ((uint32_t)8U) +#define SDTCFG_ARFD_OFFSET ((uint32_t)12U) +#define SDTCFG_WRD_OFFSET ((uint32_t)16U) +#define SDTCFG_RPD_OFFSET ((uint32_t)20U) +#define SDTCFG_RCD_OFFSET ((uint32_t)24U) + +#define SDCMD_NARF_OFFSET ((uint32_t)5U) +#define SDCMD_MRC_OFFSET ((uint32_t)9U) + +#define SDARI_ARINTV_OFFSET ((uint32_t)1U) + +#define SDRSCTL_SSCR_OFFSET ((uint32_t)1U) +#define SDRSCTL_SDSC_OFFSET ((uint32_t)4U) + +#define SDSTAT_STA0_OFFSET ((uint32_t)1U) +#define SDSTAT_STA1_OFFSET ((uint32_t)3U) + +#define SRCMD_RWAITCYCLE_OFFSET ((uint32_t)16U) +#define SWCMD_WWAITCYCLE_OFFSET ((uint32_t)16U) + +#define INTEN_INTS_OFFSET ((uint32_t)3U) + +/*! + \brief deinitialize EXMC NOR/SRAM region + \param[in] exmc_norsram_region: select the region of bank0 + \arg EXMC_BANK0_NORSRAM_REGIONx(x=0..3) + \param[out] none + \retval none +*/ +void exmc_norsram_deinit(uint32_t exmc_norsram_region) +{ + /* reset the registers */ + EXMC_SNCTL(exmc_norsram_region) = BANK0_SNCTL_RESET; + EXMC_SNTCFG(exmc_norsram_region) = BANK0_SNTCFG_RESET; + EXMC_SNWTCFG(exmc_norsram_region) = BANK0_SNWTCFG_RESET; +} + +/*! + \brief initialize the struct exmc_norsram_parameter_struct + \param[in] none + \param[out] exmc_norsram_init_struct: the initialized struct exmc_norsram_parameter_struct pointer + \retval none +*/ +void exmc_norsram_struct_para_init(exmc_norsram_parameter_struct* exmc_norsram_init_struct) +{ + /* configure the structure with default value */ + exmc_norsram_init_struct->norsram_region = EXMC_BANK0_NORSRAM_REGION0; + exmc_norsram_init_struct->address_data_mux = ENABLE; + exmc_norsram_init_struct->memory_type = EXMC_MEMORY_TYPE_SRAM; + exmc_norsram_init_struct->databus_width = EXMC_NOR_DATABUS_WIDTH_8B; + exmc_norsram_init_struct->burst_mode = DISABLE; + exmc_norsram_init_struct->nwait_polarity = EXMC_NWAIT_POLARITY_LOW; + exmc_norsram_init_struct->wrap_burst_mode = DISABLE; + exmc_norsram_init_struct->nwait_config = EXMC_NWAIT_CONFIG_BEFORE; + exmc_norsram_init_struct->memory_write = ENABLE; + exmc_norsram_init_struct->nwait_signal = ENABLE; + exmc_norsram_init_struct->extended_mode = DISABLE; + exmc_norsram_init_struct->asyn_wait = DISABLE; + exmc_norsram_init_struct->write_mode = EXMC_ASYN_WRITE; + + /* read/write timing configure */ + exmc_norsram_init_struct->read_write_timing->asyn_address_setuptime = 0xFU; + exmc_norsram_init_struct->read_write_timing->asyn_address_holdtime = 0xFU; + exmc_norsram_init_struct->read_write_timing->asyn_data_setuptime = 0xFFU; + exmc_norsram_init_struct->read_write_timing->bus_latency = 0xFU; + exmc_norsram_init_struct->read_write_timing->syn_clk_division = EXMC_SYN_CLOCK_RATIO_16_CLK; + exmc_norsram_init_struct->read_write_timing->syn_data_latency = EXMC_DATALAT_17_CLK; + exmc_norsram_init_struct->read_write_timing->asyn_access_mode = EXMC_ACCESS_MODE_A; + + /* write timing configure, when extended mode is used */ + exmc_norsram_init_struct->write_timing->asyn_address_setuptime = 0xFU; + exmc_norsram_init_struct->write_timing->asyn_address_holdtime = 0xFU; + exmc_norsram_init_struct->write_timing->asyn_data_setuptime = 0xFFU; + exmc_norsram_init_struct->write_timing->bus_latency = 0xFU; + exmc_norsram_init_struct->write_timing->asyn_access_mode = EXMC_ACCESS_MODE_A; +} + +/*! + \brief initialize EXMC NOR/SRAM region + \param[in] exmc_norsram_parameter_struct: configure the EXMC NOR/SRAM parameter + norsram_region: EXMC_BANK0_NORSRAM_REGIONx,x=0..3 + write_mode: EXMC_ASYN_WRITE or EXMC_SYN_WRITE + extended_mode: ENABLE or DISABLE + asyn_wait: ENABLE or DISABLE + nwait_signal: ENABLE or DISABLE + memory_write: ENABLE or DISABLE + nwait_config: EXMC_NWAIT_CONFIG_BEFORE or EXMC_NWAIT_CONFIG_DURING + wrap_burst_mode: ENABLE or DISABLE + nwait_polarity: EXMC_NWAIT_POLARITY_LOW or EXMC_NWAIT_POLARITY_HIGH + burst_mode: ENABLE or DISABLE + databus_width: EXMC_NOR_DATABUS_WIDTH_8B or EXMC_NOR_DATABUS_WIDTH_16B + memory_type: EXMC_MEMORY_TYPE_SRAM / EXMC_MEMORY_TYPE_PSRAM / EXMC_MEMORY_TYPE_NOR + address_data_mux: ENABLE or DISABLE + read_write_timing: struct exmc_norsram_timing_parameter_struct set the time + asyn_access_mode: EXMC_ACCESS_MODE_A, EXMC_ACCESS_MODE_B, EXMC_ACCESS_MODE_C, EXMC_ACCESS_MODE_D + syn_data_latency: EXMC_DATALAT_x_CLK, x=2..17 + syn_clk_division: EXMC_SYN_CLOCK_RATIO_x_CLK, x=2..16 + bus_latency: 0x01U~0x10U + asyn_data_setuptime: 0x02U~0x100U + asyn_address_holdtime: 0x02U~0x10U + asyn_address_setuptime: 0x01U~0x10U + write_timing: struct exmc_norsram_timing_parameter_struct set the time + asyn_access_mode: EXMC_ACCESS_MODE_A, EXMC_ACCESS_MODE_B, EXMC_ACCESS_MODE_C, EXMC_ACCESS_MODE_D + syn_data_latency: EXMC_DATALAT_x_CLK, x=2..17 + syn_clk_division: EXMC_SYN_CLOCK_RATIO_x_CLK, x=2..16 + bus_latency: 0x01U~0x10U + asyn_data_setuptime: 0x02U~0x100U + asyn_address_holdtime: 0x02U~0x10U + asyn_address_setuptime: 0x01U~0x10U + \param[out] none + \retval none +*/ +void exmc_norsram_init(exmc_norsram_parameter_struct* exmc_norsram_init_struct) +{ + uint32_t snctl = 0x00000000U, sntcfg = 0x00000000U, snwtcfg = 0x00000000U; + + /* get the register value */ + snctl = EXMC_SNCTL(exmc_norsram_init_struct->norsram_region); + + /* clear relative bits */ + snctl &= ((uint32_t)~(EXMC_SNCTL_NREN | EXMC_SNCTL_NRTP | EXMC_SNCTL_NRW | EXMC_SNCTL_SBRSTEN | + EXMC_SNCTL_NRWTPOL | EXMC_SNCTL_WRAPEN | EXMC_SNCTL_NRWTCFG | EXMC_SNCTL_WREN | + EXMC_SNCTL_NRWTEN | EXMC_SNCTL_EXMODEN | EXMC_SNCTL_ASYNCWAIT | EXMC_SNCTL_SYNCWR | + EXMC_SNCTL_NRMUX )); + + snctl |= (uint32_t)(exmc_norsram_init_struct->address_data_mux << SNCTL_NRMUX_OFFSET) | + exmc_norsram_init_struct->memory_type | + exmc_norsram_init_struct->databus_width | + (exmc_norsram_init_struct->burst_mode << SNCTL_SBRSTEN_OFFSET) | + exmc_norsram_init_struct->nwait_polarity | + (exmc_norsram_init_struct->wrap_burst_mode << SNCTL_WRAPEN_OFFSET) | + exmc_norsram_init_struct->nwait_config | + (exmc_norsram_init_struct->memory_write << SNCTL_WREN_OFFSET) | + (exmc_norsram_init_struct->nwait_signal << SNCTL_NRWTEN_OFFSET) | + (exmc_norsram_init_struct->extended_mode << SNCTL_EXMODEN_OFFSET) | + (exmc_norsram_init_struct->asyn_wait << SNCTL_ASYNCWAIT_OFFSET) | + exmc_norsram_init_struct->write_mode; + + sntcfg = (uint32_t)((exmc_norsram_init_struct->read_write_timing->asyn_address_setuptime - 1U) & EXMC_SNTCFG_ASET) | + (((exmc_norsram_init_struct->read_write_timing->asyn_address_holdtime - 1U) << SNTCFG_AHLD_OFFSET) & EXMC_SNTCFG_AHLD) | + (((exmc_norsram_init_struct->read_write_timing->asyn_data_setuptime - 1U) << SNTCFG_DSET_OFFSET) & EXMC_SNTCFG_DSET) | + (((exmc_norsram_init_struct->read_write_timing->bus_latency - 1U) << SNTCFG_BUSLAT_OFFSET) & EXMC_SNTCFG_BUSLAT) | + exmc_norsram_init_struct->read_write_timing->syn_clk_division | + exmc_norsram_init_struct->read_write_timing->syn_data_latency | + exmc_norsram_init_struct->read_write_timing->asyn_access_mode; + + /* nor flash access enable */ + if(EXMC_MEMORY_TYPE_NOR == exmc_norsram_init_struct->memory_type){ + snctl |= (uint32_t)EXMC_SNCTL_NREN; + } + + /* extended mode configure */ + if(ENABLE == exmc_norsram_init_struct->extended_mode){ + snwtcfg = (uint32_t)(((exmc_norsram_init_struct->write_timing->asyn_address_setuptime - 1U) & EXMC_SNWTCFG_WASET) | + (((exmc_norsram_init_struct->write_timing->asyn_address_holdtime - 1U) << SNTCFG_AHLD_OFFSET ) & EXMC_SNWTCFG_WAHLD)| + (((exmc_norsram_init_struct->write_timing->asyn_data_setuptime - 1U) << SNTCFG_DSET_OFFSET) & EXMC_SNWTCFG_WDSET) | + exmc_norsram_init_struct->write_timing->asyn_access_mode); + }else{ + snwtcfg = BANK0_SNWTCFG_RESET; + } + + /* configure the registers */ + EXMC_SNCTL(exmc_norsram_init_struct->norsram_region) = snctl; + EXMC_SNTCFG(exmc_norsram_init_struct->norsram_region) = sntcfg; + EXMC_SNWTCFG(exmc_norsram_init_struct->norsram_region) = snwtcfg; +} + +/*! + \brief enable EXMC NOR/PSRAM bank region + \param[in] exmc_norsram_region: specifie the region of NOR/PSRAM bank + \arg EXMC_BANK0_NORSRAM_REGIONx(x=0..3) + \param[out] none + \retval none +*/ +void exmc_norsram_enable(uint32_t exmc_norsram_region) +{ + EXMC_SNCTL(exmc_norsram_region) |= (uint32_t)EXMC_SNCTL_NRBKEN; +} + +/*! + \brief disable EXMC NOR/PSRAM bank region + \param[in] exmc_norsram_region: specifie the region of NOR/PSRAM Bank + \arg EXMC_BANK0_NORSRAM_REGIONx(x=0..3) + \param[out] none + \retval none +*/ +void exmc_norsram_disable(uint32_t exmc_norsram_region) +{ + EXMC_SNCTL(exmc_norsram_region) &= ~(uint32_t)EXMC_SNCTL_NRBKEN; +} + +/*! + \brief deinitialize EXMC NAND bank + \param[in] exmc_nand_bank: select the bank of NAND + \arg EXMC_BANKx_NAND(x=1..2) + \param[out] none + \retval none +*/ +void exmc_nand_deinit(uint32_t exmc_nand_bank) +{ + /* EXMC_BANK1_NAND or EXMC_BANK2_NAND */ + EXMC_NPCTL(exmc_nand_bank) = BANK1_2_NPCTL_RESET; + EXMC_NPINTEN(exmc_nand_bank) = BANK1_2_NPINTEN_RESET; + EXMC_NPCTCFG(exmc_nand_bank) = BANK1_2_NPCTCFG_RESET; + EXMC_NPATCFG(exmc_nand_bank) = BANK1_2_NPATCFG_RESET; +} + +/*! + \brief initialize the struct exmc_nand_init_struct + \param[in] none + \param[out] the initialized struct exmc_nand_init_struct pointer + \retval none +*/ +void exmc_nand_struct_para_init(exmc_nand_parameter_struct* exmc_nand_init_struct) +{ + /* configure the structure with default value */ + exmc_nand_init_struct->nand_bank = EXMC_BANK1_NAND; + exmc_nand_init_struct->wait_feature = DISABLE; + exmc_nand_init_struct->databus_width = EXMC_NAND_DATABUS_WIDTH_8B; + exmc_nand_init_struct->ecc_logic = DISABLE; + exmc_nand_init_struct->ecc_size = EXMC_ECC_SIZE_256BYTES; + exmc_nand_init_struct->ctr_latency = 0x0U; + exmc_nand_init_struct->atr_latency = 0x0U; + exmc_nand_init_struct->common_space_timing->setuptime = 0xFCU; + exmc_nand_init_struct->common_space_timing->waittime = 0xFCU; + exmc_nand_init_struct->common_space_timing->holdtime = 0xFCU; + exmc_nand_init_struct->common_space_timing->databus_hiztime = 0xFCU; + exmc_nand_init_struct->attribute_space_timing->setuptime = 0xFCU; + exmc_nand_init_struct->attribute_space_timing->waittime = 0xFCU; + exmc_nand_init_struct->attribute_space_timing->holdtime = 0xFCU; + exmc_nand_init_struct->attribute_space_timing->databus_hiztime = 0xFCU; +} + +/*! + \brief initialize EXMC NAND bank + \param[in] exmc_nand_parameter_struct: configure the EXMC NAND parameter + nand_bank: EXMC_BANK1_NAND or EXMC_BANK2_NAND + ecc_size: EXMC_ECC_SIZE_xBYTES,x=256,512,1024,2048,4096 + atr_latency: EXMC_ALE_RE_DELAY_x_HCLK,x=1..16 + ctr_latency: EXMC_CLE_RE_DELAY_x_HCLK,x=1..16 + ecc_logic: ENABLE or DISABLE + databus_width: EXMC_NAND_DATABUS_WIDTH_8B or EXMC_NAND_DATABUS_WIDTH_16B + wait_feature: ENABLE or DISABLE + common_space_timing: struct exmc_nand_pccard_timing_parameter_struct set the time + databus_hiztime: 0x01U~0x100U + holdtime: 0x01U~0xFFU + waittime: 0x02U~0x100U + setuptime: 0x01U~0x100U + attribute_space_timing: struct exmc_nand_pccard_timing_parameter_struct set the time + databus_hiztime: 0x01U~0x100U + holdtime: 0x01U~0xFFU + waittime: 0x02U~0x100U + setuptime: 0x01U~0x100U + \param[out] none + \retval none +*/ +void exmc_nand_init(exmc_nand_parameter_struct* exmc_nand_init_struct) +{ + uint32_t npctl = 0x00000000U, npctcfg = 0x00000000U, npatcfg = 0x00000000U; + + npctl = (uint32_t)(exmc_nand_init_struct->wait_feature << NPCTL_NDWTEN_OFFSET)| + EXMC_NPCTL_NDTP | + exmc_nand_init_struct->databus_width | + (exmc_nand_init_struct->ecc_logic << NPCTL_ECCEN_OFFSET)| + exmc_nand_init_struct->ecc_size | + exmc_nand_init_struct->ctr_latency | + exmc_nand_init_struct->atr_latency; + + npctcfg = (uint32_t)((exmc_nand_init_struct->common_space_timing->setuptime - 1U) & EXMC_NPCTCFG_COMSET ) | + (((exmc_nand_init_struct->common_space_timing->waittime - 1U) << NPCTCFG_COMWAIT_OFFSET) & EXMC_NPCTCFG_COMWAIT ) | + ((exmc_nand_init_struct->common_space_timing->holdtime << NPCTCFG_COMHLD_OFFSET) & EXMC_NPCTCFG_COMHLD ) | + (((exmc_nand_init_struct->common_space_timing->databus_hiztime - 1U) << NPCTCFG_COMHIZ_OFFSET) & EXMC_NPCTCFG_COMHIZ ); + + npatcfg = (uint32_t)((exmc_nand_init_struct->attribute_space_timing->setuptime - 1U) & EXMC_NPATCFG_ATTSET ) | + (((exmc_nand_init_struct->attribute_space_timing->waittime - 1U) << NPATCFG_ATTWAIT_OFFSET) & EXMC_NPATCFG_ATTWAIT ) | + ((exmc_nand_init_struct->attribute_space_timing->holdtime << NPATCFG_ATTHLD_OFFSET) & EXMC_NPATCFG_ATTHLD ) | + (((exmc_nand_init_struct->attribute_space_timing->databus_hiztime - 1U) << NPATCFG_ATTHIZ_OFFSET) & EXMC_NPATCFG_ATTHIZ ); + + /* EXMC_BANK1_NAND or EXMC_BANK2_NAND initialize */ + EXMC_NPCTL(exmc_nand_init_struct->nand_bank) = npctl; + EXMC_NPCTCFG(exmc_nand_init_struct->nand_bank) = npctcfg; + EXMC_NPATCFG(exmc_nand_init_struct->nand_bank) = npatcfg; +} + +/*! + \brief enable NAND bank + \param[in] exmc_nand_bank: specifie the NAND bank + \arg EXMC_BANKx_NAND(x=1,2) + \param[out] none + \retval none +*/ +void exmc_nand_enable(uint32_t exmc_nand_bank) +{ + EXMC_NPCTL(exmc_nand_bank) |= EXMC_NPCTL_NDBKEN; +} + +/*! + \brief disable NAND bank + \param[in] exmc_nand_bank: specifie the NAND bank + \arg EXMC_BANKx_NAND(x=1,2) + \param[out] none + \retval none +*/ +void exmc_nand_disable(uint32_t exmc_nand_bank) +{ + EXMC_NPCTL(exmc_nand_bank) &= ~EXMC_NPCTL_NDBKEN; +} + +/*! + \brief enable or disable the EXMC NAND ECC function + \param[in] exmc_nand_bank: specifie the NAND bank + \arg EXMC_BANKx_NAND(x=1,2) + \param[in] newvalue: ENABLE or DISABLE + \param[out] none + \retval none +*/ +void exmc_nand_ecc_config(uint32_t exmc_nand_bank, ControlStatus newvalue) +{ + if (ENABLE == newvalue){ + /* enable the selected NAND bank ECC function */ + EXMC_NPCTL(exmc_nand_bank) |= EXMC_NPCTL_ECCEN; + }else{ + /* disable the selected NAND bank ECC function */ + EXMC_NPCTL(exmc_nand_bank) &= ~EXMC_NPCTL_ECCEN; + } +} + +/*! + \brief get the EXMC ECC value + \param[in] exmc_nand_bank: specifie the NAND bank + \arg EXMC_BANKx_NAND(x=1,2) + \param[out] none + \retval the error correction code(ECC) value +*/ +uint32_t exmc_ecc_get(uint32_t exmc_nand_bank) +{ + return(EXMC_NECC(exmc_nand_bank)); +} + +/*! + \brief deinitialize EXMC PC card bank + \param[in] none + \param[out] none + \retval none +*/ +void exmc_pccard_deinit(void) +{ + /* EXMC_BANK3_PCCARD */ + EXMC_NPCTL3 = BANK3_NPCTL_RESET; + EXMC_NPINTEN3 = BANK3_NPINTEN_RESET; + EXMC_NPCTCFG3 = BANK3_NPCTCFG_RESET; + EXMC_NPATCFG3 = BANK3_NPATCFG_RESET; + EXMC_PIOTCFG3 = BANK3_PIOTCFG3_RESET; +} + +/*! + \brief initialize EXMC PC card bank + \param[in] exmc_pccard_parameter_struct: configure the EXMC NAND parameter + atr_latency: EXMC_ALE_RE_DELAY_x_HCLK,x=1..16 + ctr_latency: EXMC_CLE_RE_DELAY_x_HCLK,x=1..16 + wait_feature: ENABLE or DISABLE + common_space_timing: struct exmc_nand_pccard_timing_parameter_struct set the time + databus_hiztime: 0x01U~0x100U + holdtime: 0x01U~0xFFU + waittime: 0x02U~0x100U + setuptime: 0x01U~0x100U + attribute_space_timing: struct exmc_nand_pccard_timing_parameter_struct set the time + databus_hiztime: 0x01U~0x100U + holdtime: 0x01U~0xFFU + waittime: 0x02U~0x100U + setuptime: 0x01U~0x100U + io_space_timing: exmc_nand_pccard_timing_parameter_struct set the time + databus_hiztime: 0x00U~0xFFU + holdtime: 0x01U~0xFFU + waittime: 0x02U~0x100U + setuptime: 0x01U~0x100U + \param[out] none + \retval none +*/ +void exmc_pccard_init(exmc_pccard_parameter_struct* exmc_pccard_init_struct) +{ + /* configure the EXMC bank3 PC card control register */ + EXMC_NPCTL3 = (uint32_t)(exmc_pccard_init_struct->wait_feature << NPCTL_NDWTEN_OFFSET) | + EXMC_NAND_DATABUS_WIDTH_16B | + exmc_pccard_init_struct->ctr_latency | + exmc_pccard_init_struct->atr_latency ; + + /* configure the EXMC bank3 PC card common space timing configuration register */ + EXMC_NPCTCFG3 = (uint32_t)((exmc_pccard_init_struct->common_space_timing->setuptime - 1U) & EXMC_NPCTCFG_COMSET ) | + (((exmc_pccard_init_struct->common_space_timing->waittime - 1U) << NPCTCFG_COMWAIT_OFFSET) & EXMC_NPCTCFG_COMWAIT ) | + ((exmc_pccard_init_struct->common_space_timing->holdtime << NPCTCFG_COMHLD_OFFSET) & EXMC_NPCTCFG_COMHLD ) | + (((exmc_pccard_init_struct->common_space_timing->databus_hiztime - 1U) << NPCTCFG_COMHIZ_OFFSET) & EXMC_NPCTCFG_COMHIZ ); + + /* configure the EXMC bank3 PC card attribute space timing configuration register */ + EXMC_NPATCFG3 = (uint32_t)((exmc_pccard_init_struct->attribute_space_timing->setuptime - 1U) & EXMC_NPATCFG_ATTSET ) | + (((exmc_pccard_init_struct->attribute_space_timing->waittime - 1U) << NPATCFG_ATTWAIT_OFFSET) & EXMC_NPATCFG_ATTWAIT ) | + ((exmc_pccard_init_struct->attribute_space_timing->holdtime << NPATCFG_ATTHLD_OFFSET) & EXMC_NPATCFG_ATTHLD ) | + (((exmc_pccard_init_struct->attribute_space_timing->databus_hiztime - 1U) << NPATCFG_ATTHIZ_OFFSET) & EXMC_NPATCFG_ATTHIZ); + + /* configure the EXMC bank3 PC card io space timing configuration register */ + EXMC_PIOTCFG3 = (uint32_t)((exmc_pccard_init_struct->io_space_timing->setuptime - 1U) & EXMC_PIOTCFG3_IOSET ) | + (((exmc_pccard_init_struct->io_space_timing->waittime - 1U) << PIOTCFG_IOWAIT_OFFSET) & EXMC_PIOTCFG3_IOWAIT ) | + ((exmc_pccard_init_struct->io_space_timing->holdtime << PIOTCFG_IOHLD_OFFSET) & EXMC_PIOTCFG3_IOHLD ) | + ((exmc_pccard_init_struct->io_space_timing->databus_hiztime << PIOTCFG_IOHIZ_OFFSET) & EXMC_PIOTCFG3_IOHIZ ); +} + +/*! + \brief initialize the struct exmc_pccard_parameter_struct + \param[in] none + \param[out] the initialized struct exmc_pccard_parameter_struct pointer + \retval none +*/ +void exmc_pccard_struct_para_init(exmc_pccard_parameter_struct* exmc_pccard_init_struct) +{ + /* configure the structure with default value */ + exmc_pccard_init_struct->wait_feature = DISABLE; + exmc_pccard_init_struct->ctr_latency = 0x0U; + exmc_pccard_init_struct->atr_latency = 0x0U; + exmc_pccard_init_struct->common_space_timing->setuptime = 0xFCU; + exmc_pccard_init_struct->common_space_timing->waittime = 0xFCU; + exmc_pccard_init_struct->common_space_timing->holdtime = 0xFCU; + exmc_pccard_init_struct->common_space_timing->databus_hiztime = 0xFCU; + exmc_pccard_init_struct->attribute_space_timing->setuptime = 0xFCU; + exmc_pccard_init_struct->attribute_space_timing->waittime = 0xFCU; + exmc_pccard_init_struct->attribute_space_timing->holdtime = 0xFCU; + exmc_pccard_init_struct->attribute_space_timing->databus_hiztime = 0xFCU; + exmc_pccard_init_struct->io_space_timing->setuptime = 0xFCU; + exmc_pccard_init_struct->io_space_timing->waittime = 0xFCU; + exmc_pccard_init_struct->io_space_timing->holdtime = 0xFCU; + exmc_pccard_init_struct->io_space_timing->databus_hiztime = 0xFCU; +} + +/*! + \brief enable PC Card Bank + \param[in] none + \param[out] none + \retval none +*/ +void exmc_pccard_enable(void) +{ + EXMC_NPCTL3 |= EXMC_NPCTL_NDBKEN; +} + +/*! + \brief disable PC Card Bank + \param[in] none + \param[out] none + \retval none +*/ +void exmc_pccard_disable(void) +{ + EXMC_NPCTL3 &= ~EXMC_NPCTL_NDBKEN; +} + +/*! + \brief deinitialize EXMC SDRAM device + \param[in] exmc_sdram_device: + \param[out] none + \retval none +*/ +void exmc_sdram_deinit(uint32_t exmc_sdram_device) +{ + /* reset SDRAM registers */ + EXMC_SDCTL(exmc_sdram_device) = SDRAM_DEVICE_SDCTL_RESET; + EXMC_SDTCFG(exmc_sdram_device) = SDRAM_DEVICE_SDTCFG_RESET; + EXMC_SDCMD = SDRAM_DEVICE_SDCMD_RESET; + EXMC_SDARI = SDRAM_DEVICE_SDARI_RESET; + EXMC_SDRSCTL = SDRAM_DEVICE_SDRSCTL_RESET; +} + +/*! + \brief initialize EXMC SDRAM device + \param[in] exmc_sdram_parameter_struct: configure the EXMC SDRAM parameter + sdram_device: EXMC_SDRAM_DEVICE0 or EXMC_SDRAM_DEVICE1 + pipeline_read_delay: EXMC_PIPELINE_DELAY_x_HCLK, x=0..2 + brust_read_switch: ENABLE or DISABLE + sdclock_config: EXMC_SDCLK_DISABLE,EXMC_SDCLK_PERIODS_2_HCLK,EXMC_SDCLK_PERIODS_3_HCLK + write_protection: ENABLE or DISABLE + cas_latency: EXMC_CAS_LATENCY_x_SDCLK, x=1..3 + internal_bank_number: EXMC_SDRAM_2_INTER_BANK or EXMC_SDRAM_4_INTER_BANK + data_width: EXMC_SDRAM_DATABUS_WIDTH_8B,EXMC_SDRAM_DATABUS_WIDTH_16B,EXMC_SDRAM_DATABUS_WIDTH_32B + row_address_width: EXMC_SDRAM_ROW_ADDRESS_x, x=11..13 + column_address_width: EXMC_SDRAM_COW_ADDRESS_x, x=8..11 + timing: exmc_sdram_timing_parameter_struct set the time + row_to_column_delay: 1U~16U + row_precharge_delay: 1U~16U + write_recovery_delay: 1U~16U + auto_refresh_delay: 1U~16U + row_address_select_delay: 1U~16U + exit_selfrefresh_delay: 1U~16U + load_mode_register_delay: 1U~16U + \param[out] none + \retval none +*/ +void exmc_sdram_init(exmc_sdram_parameter_struct* exmc_sdram_init_struct) +{ + uint32_t sdctl0, sdctl1, sdtcfg0, sdtcfg1; + + /* configuration EXMC_SDCTL0 or EXMC_SDCTL1 */ + if(EXMC_SDRAM_DEVICE0 == exmc_sdram_init_struct->sdram_device){ + /* configuration EXMC_SDCTL0 */ + EXMC_SDCTL(EXMC_SDRAM_DEVICE0) = (uint32_t)exmc_sdram_init_struct->column_address_width | + exmc_sdram_init_struct->row_address_width | + exmc_sdram_init_struct->data_width | + exmc_sdram_init_struct->internal_bank_number | + exmc_sdram_init_struct->cas_latency | + (exmc_sdram_init_struct->write_protection << SDCTL_WPEN_OFFSET)| + exmc_sdram_init_struct->sdclock_config | + (exmc_sdram_init_struct->brust_read_switch << SDCTL_BRSTRD_OFFSET)| + exmc_sdram_init_struct->pipeline_read_delay; + + /* configuration EXMC_SDTCFG0 */ + EXMC_SDTCFG(EXMC_SDRAM_DEVICE0) = (uint32_t)((exmc_sdram_init_struct->timing->load_mode_register_delay)-1U) | + (((exmc_sdram_init_struct->timing->exit_selfrefresh_delay)-1U) << SDTCFG_XSRD_OFFSET) | + (((exmc_sdram_init_struct->timing->row_address_select_delay)-1U) << SDTCFG_RASD_OFFSET) | + (((exmc_sdram_init_struct->timing->auto_refresh_delay)-1U) << SDTCFG_ARFD_OFFSET) | + (((exmc_sdram_init_struct->timing->write_recovery_delay)-1U) << SDTCFG_WRD_OFFSET) | + (((exmc_sdram_init_struct->timing->row_precharge_delay)-1U) << SDTCFG_RPD_OFFSET) | + (((exmc_sdram_init_struct->timing->row_to_column_delay)-1U) << SDTCFG_RCD_OFFSET); + }else{ + /* configuration EXMC_SDCTL0 and EXMC_SDCTL1 */ + /* some bits in the EXMC_SDCTL1 register are reserved */ + sdctl0 = EXMC_SDCTL(EXMC_SDRAM_DEVICE0) & (~( EXMC_SDCTL_PIPED | EXMC_SDCTL_BRSTRD | EXMC_SDCTL_SDCLK )); + + sdctl0 |= (uint32_t)exmc_sdram_init_struct->sdclock_config | + exmc_sdram_init_struct->brust_read_switch | + exmc_sdram_init_struct->pipeline_read_delay; + + sdctl1 = (uint32_t)exmc_sdram_init_struct->column_address_width | + exmc_sdram_init_struct->row_address_width | + exmc_sdram_init_struct->data_width | + exmc_sdram_init_struct->internal_bank_number | + exmc_sdram_init_struct->cas_latency | + exmc_sdram_init_struct->write_protection ; + + EXMC_SDCTL(EXMC_SDRAM_DEVICE0) = sdctl0; + EXMC_SDCTL(EXMC_SDRAM_DEVICE1) = sdctl1; + + /* configuration EXMC_SDTCFG0 and EXMC_SDTCFG1 */ + /* some bits in the EXMC_SDTCFG1 register are reserved */ + sdtcfg0 = EXMC_SDTCFG(EXMC_SDRAM_DEVICE0) & (~(EXMC_SDTCFG_RPD | EXMC_SDTCFG_WRD | EXMC_SDTCFG_ARFD)); + + sdtcfg0 |= (uint32_t)(((exmc_sdram_init_struct->timing->auto_refresh_delay)-1U) << SDTCFG_ARFD_OFFSET) | + (((exmc_sdram_init_struct->timing->row_precharge_delay)-1U) << SDTCFG_RPD_OFFSET) | + (((exmc_sdram_init_struct->timing->write_recovery_delay)-1U) << SDTCFG_WRD_OFFSET); + + sdtcfg1 = (uint32_t)((exmc_sdram_init_struct->timing->load_mode_register_delay)-1U) | + (((exmc_sdram_init_struct->timing->exit_selfrefresh_delay)-1U) << SDTCFG_XSRD_OFFSET) | + (((exmc_sdram_init_struct->timing->row_address_select_delay)-1U) << SDTCFG_RASD_OFFSET) | + (((exmc_sdram_init_struct->timing->row_to_column_delay)-1U) << SDTCFG_RCD_OFFSET); + + EXMC_SDTCFG(EXMC_SDRAM_DEVICE0) = sdtcfg0; + EXMC_SDTCFG(EXMC_SDRAM_DEVICE1) = sdtcfg1; + } +} + +/*! + \brief initialize the struct exmc_sdram_parameter_struct + \param[in] none + \param[out] the initialized struct exmc_sdram_parameter_struct pointer + \retval none +*/ +void exmc_sdram_parameter_init(exmc_sdram_parameter_struct* exmc_sdram_init_struct) +{ + /* configure the structure with default value */ + exmc_sdram_init_struct->sdram_device = EXMC_SDRAM_DEVICE0; + exmc_sdram_init_struct->column_address_width = EXMC_SDRAM_COW_ADDRESS_8; + exmc_sdram_init_struct->row_address_width = EXMC_SDRAM_ROW_ADDRESS_11; + exmc_sdram_init_struct->data_width = EXMC_SDRAM_DATABUS_WIDTH_16B; + exmc_sdram_init_struct->internal_bank_number = EXMC_SDRAM_4_INTER_BANK; + exmc_sdram_init_struct->cas_latency = EXMC_CAS_LATENCY_1_SDCLK; + exmc_sdram_init_struct->write_protection = ENABLE; + exmc_sdram_init_struct->sdclock_config = EXMC_SDCLK_DISABLE; + exmc_sdram_init_struct->brust_read_switch = DISABLE; + exmc_sdram_init_struct->pipeline_read_delay = EXMC_PIPELINE_DELAY_0_HCLK; + + exmc_sdram_init_struct->timing->load_mode_register_delay = 16U; + exmc_sdram_init_struct->timing->exit_selfrefresh_delay = 16U; + exmc_sdram_init_struct->timing->row_address_select_delay = 16U; + exmc_sdram_init_struct->timing->auto_refresh_delay = 16U; + exmc_sdram_init_struct->timing->write_recovery_delay = 16U; + exmc_sdram_init_struct->timing->row_precharge_delay = 16U; + exmc_sdram_init_struct->timing->row_to_column_delay = 16U; +} + +/*! + \brief configure the SDRAM memory command + \param[in] exmc_sdram_command_init_struct: initialize EXMC SDRAM command + mode_register_content: + auto_refresh_number: EXMC_SDRAM_AUTO_REFLESH_x_SDCLK, x=1..15 + bank_select: EXMC_SDRAM_DEVICE0_SELECT, EXMC_SDRAM_DEVICE1_SELECT, EXMC_SDRAM_DEVICE0_1_SELECT + command: EXMC_SDRAM_NORMAL_OPERATION, EXMC_SDRAM_CLOCK_ENABLE, EXMC_SDRAM_PRECHARGE_ALL, + EXMC_SDRAM_AUTO_REFRESH, EXMC_SDRAM_LOAD_MODE_REGISTER, EXMC_SDRAM_SELF_REFRESH, + EXMC_SDRAM_POWERDOWN_ENTRY + \param[out] none + \retval none +*/ +void exmc_sdram_command_config(exmc_sdram_command_parameter_struct* exmc_sdram_command_init_struct) +{ + /* configure command register */ + EXMC_SDCMD = (uint32_t)((exmc_sdram_command_init_struct->command) | + (exmc_sdram_command_init_struct->bank_select) | + ((exmc_sdram_command_init_struct->auto_refresh_number)) | + ((exmc_sdram_command_init_struct->mode_register_content)<> SDSTAT_STA0_OFFSET); + }else{ + sdstat = ((uint32_t)(EXMC_SDSTAT & EXMC_SDSDAT_STA1) >> SDSTAT_STA1_OFFSET); + } + + return sdstat; +} + +/*! + \brief configure the delayed sample clock of read data + \param[in] delay_cell: SDRAM the delayed sample clock of read data + \arg EXMC_SDRAM_x_DELAY_CELL(x=0..15) + \param[in] extra_hclk: sample cycle of read data + \arg EXMC_SDRAM_READSAMPLE_x_EXTRAHCLK(x=0,1) + \param[out] none + \retval none +*/ +void exmc_sdram_readsample_config(uint32_t delay_cell, uint32_t extra_hclk) +{ + uint32_t sdrsctl = 0U; + + sdrsctl = EXMC_SDRSCTL & (~(EXMC_SDRSCTL_SDSC | EXMC_SDRSCTL_SSCR)); + sdrsctl |= (uint32_t)(delay_cell & EXMC_SDRSCTL_SDSC) | + ((extra_hclk << SDRSCTL_SSCR_OFFSET) & EXMC_SDRSCTL_SSCR); + EXMC_SDRSCTL = sdrsctl; +} + +/*! + \brief enable read sample + \param[in] none + \param[out] none + \retval none +*/ +void exmc_sdram_readsample_enable(void) +{ + EXMC_SDRSCTL |= EXMC_SDRSCTL_RSEN; +} + +/*! + \brief disable read sample + \param[in] none + \param[out] none + \retval none +*/ +void exmc_sdram_readsample_disable(void) +{ + EXMC_SDRSCTL &= (uint32_t)(~EXMC_SDRSCTL_RSEN); +} + + +/*! + \brief deinitialize exmc SQPIPSRAM + \param[in] none + \param[out] none + \retval none +*/ +void exmc_sqpipsram_deinit(void) +{ + /* reset the registers */ + EXMC_SINIT = BANK0_SQPI_SINIT_RESET; + EXMC_SRCMD = BANK0_SQPI_SRCMD_RESET; + EXMC_SWCMD = BANK0_SQPI_SWCMD_RESET; + EXMC_SIDL = BANK0_SQPI_SIDL_RESET; + EXMC_SIDH = BANK0_SQPI_SIDH_RESET; +} + +/*! + \brief initialize EXMC SQPIPSRAM + \param[in] exmc_sqpipsram_parameter_struct: configure the EXMC SQPIPSRAM parameter + sample_polarity: EXMC_SQPIPSRAM_SAMPLE_RISING_EDGE, EXMC_SQPIPSRAM_SAMPLE_FALLING_EDGE + id_length: EXMC_SQPIPSRAM_ID_LENGTH_xB,x=8,16,32,64 + address_bits: EXMC_SQPIPSRAM_ADDR_LENGTH_xB,x=1..26 + command_bits: EXMC_SQPIPSRAM_COMMAND_LENGTH_xB,x=4,8,16 + \param[out] none + \retval none +*/ +void exmc_sqpipsram_init(exmc_sqpipsram_parameter_struct* exmc_sqpipsram_init_struct) +{ + /* initialize SQPI controller */ + EXMC_SINIT = (uint32_t)exmc_sqpipsram_init_struct->sample_polarity | + exmc_sqpipsram_init_struct->id_length | + exmc_sqpipsram_init_struct->address_bits | + exmc_sqpipsram_init_struct->command_bits; +} + +/*! + \brief initialize the struct exmc_sqpipsram_parameter_struct + \param[in] the struct exmc_sqpipsram_parameter_struct pointer + \param[out] none + \retval none +*/ +void exmc_sqpipsram_parameter_init(exmc_sqpipsram_parameter_struct* exmc_sqpipsram_init_struct) +{ + /* configure the structure with default value */ + exmc_sqpipsram_init_struct->sample_polarity = EXMC_SQPIPSRAM_SAMPLE_RISING_EDGE; + exmc_sqpipsram_init_struct->id_length = EXMC_SQPIPSRAM_ID_LENGTH_64B; + exmc_sqpipsram_init_struct->address_bits = EXMC_SQPIPSRAM_ADDR_LENGTH_24B; + exmc_sqpipsram_init_struct->command_bits = EXMC_SQPIPSRAM_COMMAND_LENGTH_8B; +} + +/*! + \brief set the read command + \param[in] read_command_mode: configure SPI PSRAM read command mode + \arg EXMC_SQPIPSRAM_READ_MODE_DISABLE: not SPI mode + \arg EXMC_SQPIPSRAM_READ_MODE_SPI: SPI mode + \arg EXMC_SQPIPSRAM_READ_MODE_SQPI: SQPI mode + \arg EXMC_SQPIPSRAM_READ_MODE_QPI: QPI mode + \param[in] read_wait_cycle: wait cycle number after address phase,0..15 + \param[in] read_command_code: read command for AHB read transfer + \param[out] none + \retval none +*/ +void exmc_sqpipsram_read_command_set(uint32_t read_command_mode, uint32_t read_wait_cycle, uint32_t read_command_code) +{ + uint32_t srcmd; + + srcmd = (uint32_t) read_command_mode | + ((read_wait_cycle << SRCMD_RWAITCYCLE_OFFSET) & EXMC_SRCMD_RWAITCYCLE) | + ((read_command_code & EXMC_SRCMD_RCMD)); + EXMC_SRCMD = srcmd; +} + +/*! + \brief set the write command + \param[in] write_command_mode: configure SPI PSRAM write command mode + \arg EXMC_SQPIPSRAM_WRITE_MODE_DISABLE: not SPI mode + \arg EXMC_SQPIPSRAM_WRITE_MODE_SPI: SPI mode + \arg EXMC_SQPIPSRAM_WRITE_MODE_SQPI: SQPI mode + \arg EXMC_SQPIPSRAM_WRITE_MODE_QPI: QPI mode + \param[in] write_wait_cycle: wait cycle number after address phase,0..15 + \param[in] write_command_code: write command for AHB write transfer + \param[out] none + \retval none +*/ +void exmc_sqpipsram_write_command_set(uint32_t write_command_mode, uint32_t write_wait_cycle, uint32_t write_command_code) +{ + uint32_t swcmd; + + swcmd = (uint32_t) write_command_mode | + ((write_wait_cycle << SWCMD_WWAITCYCLE_OFFSET) & EXMC_SWCMD_WWAITCYCLE) | + ((write_command_code & EXMC_SWCMD_WCMD)); + EXMC_SWCMD = swcmd; +} + +/*! + \brief send SPI read ID command + \param[in] none + \param[out] none + \retval none +*/ +void exmc_sqpipsram_read_id_command_send(void) +{ + EXMC_SRCMD |= EXMC_SRCMD_RDID; +} + +/*! + \brief send SPI special command which does not have address and data phase + \param[in] none + \param[out] none + \retval none +*/ +void exmc_sqpipsram_write_cmd_send(void) +{ + EXMC_SWCMD |= EXMC_SWCMD_SC; +} + +/*! + \brief get the EXMC SPI ID low data + \param[in] none + \param[out] none + \retval the ID low data +*/ +uint32_t exmc_sqpipsram_low_id_get(void) +{ + return (EXMC_SIDL); +} + +/*! + \brief get the EXMC SPI ID high data + \param[in] none + \param[out] none + \retval the ID high data +*/ +uint32_t exmc_sqpipsram_high_id_get(void) +{ + return (EXMC_SIDH); +} + +/*! + \brief get the bit value of EXMC send write command bit or read ID command + \param[in] send_command_flag: the send command flag + \arg EXMC_SEND_COMMAND_FLAG_RDID: EXMC_SRCMD_RDID flag bit + \arg EXMC_SEND_COMMAND_FLAG_SC: EXMC_SWCMD_SC flag bit + \param[out] none + \retval the new value of send command flag +*/ +FlagStatus exmc_sqpipsram_send_command_state_get(uint32_t send_command_flag) +{ + uint32_t flag = 0x00000000U; + + if(EXMC_SEND_COMMAND_FLAG_RDID == send_command_flag){ + flag = EXMC_SRCMD; + }else if(EXMC_SEND_COMMAND_FLAG_SC == send_command_flag){ + flag = EXMC_SWCMD; + }else{ + } + + if (flag & send_command_flag){ + /* flag is set */ + return SET; + }else{ + /* flag is reset */ + return RESET; + } +} + +/*! + \brief check EXMC flag is set or not + \param[in] bank: specifies the NAND bank , PC card bank or SDRAM device + \arg EXMC_BANK1_NAND: the NAND bank1 + \arg EXMC_BANK2_NAND: the NAND bank2 + \arg EXMC_BANK3_PCCARD: the PC Card bank + \arg EXMC_SDRAM_DEVICE0: the SDRAM device0 + \arg EXMC_SDRAM_DEVICE1: the SDRAM device1 + \param[in] flag: specify get which flag + \arg EXMC_NAND_PCCARD_FLAG_RISE: interrupt rising edge status + \arg EXMC_NAND_PCCARD_FLAG_LEVEL: interrupt high-level status + \arg EXMC_NAND_PCCARD_FLAG_FALL: interrupt falling edge status + \arg EXMC_NAND_PCCARD_FLAG_FIFOE: FIFO empty flag + \arg EXMC_SDRAM_FLAG_REFRESH: refresh error interrupt flag + \arg EXMC_SDRAM_FLAG_NREADY: not ready status + \param[out] none + \retval FlagStatus: SET or RESET +*/ +FlagStatus exmc_flag_get(uint32_t bank, uint32_t flag) +{ + uint32_t status = 0x00000000U; + + if((EXMC_BANK1_NAND == bank) || (EXMC_BANK2_NAND == bank) || (EXMC_BANK3_PCCARD == bank)){ + /* NAND bank1,bank2 or PC card bank3 */ + status = EXMC_NPINTEN(bank); + }else{ + /* SDRAM device0 or device1 */ + status = EXMC_SDSTAT; + } + + if((status & flag) != (uint32_t)flag){ + /* flag is reset */ + return RESET; + }else{ + /* flag is set */ + return SET; + } +} + +/*! + \brief clear EXMC flag + \param[in] bank: specifie the NAND bank , PCCARD bank or SDRAM device + \arg EXMC_BANK1_NAND: the NAND bank1 + \arg EXMC_BANK2_NAND: the NAND bank2 + \arg EXMC_BANK3_PCCARD: the PC card bank + \arg EXMC_SDRAM_DEVICE0: the SDRAM device0 + \arg EXMC_SDRAM_DEVICE1: the SDRAM device1 + \param[in] flag: specify get which flag + \arg EXMC_NAND_PCCARD_FLAG_RISE: interrupt rising edge status + \arg EXMC_NAND_PCCARD_FLAG_LEVEL: interrupt high-level status + \arg EXMC_NAND_PCCARD_FLAG_FALL: interrupt falling edge status + \arg EXMC_NAND_PCCARD_FLAG_FIFOE: FIFO empty flag + \arg EXMC_SDRAM_FLAG_REFRESH: refresh error interrupt flag + \arg EXMC_SDRAM_FLAG_NREADY: not ready status + \param[out] none + \retval none +*/ +void exmc_flag_clear(uint32_t bank, uint32_t flag) +{ + if((EXMC_BANK1_NAND == bank) || (EXMC_BANK2_NAND == bank) || (EXMC_BANK3_PCCARD == bank)){ + /* NAND bank1,bank2 or PC card bank3 */ + EXMC_NPINTEN(bank) &= ~flag; + }else{ + /* SDRAM device0 or device1 */ + EXMC_SDSTAT &= ~flag; + } +} + +/*! + \brief check EXMC interrupt flag is set or not + \param[in] bank: specifies the NAND bank , PC card bank or SDRAM device + \arg EXMC_BANK1_NAND: the NAND bank1 + \arg EXMC_BANK2_NAND: the NAND bank2 + \arg EXMC_BANK3_PCCARD: the PC card bank + \arg EXMC_SDRAM_DEVICE0: the SDRAM device0 + \arg EXMC_SDRAM_DEVICE1: the SDRAM device1 + \param[in] interrupt_source: specify get which interrupt flag + \arg EXMC_NAND_PCCARD_INT_FLAG_RISE: interrupt source of rising edge + \arg EXMC_NAND_PCCARD_INT_FLAG_LEVEL: interrupt source of high-level + \arg EXMC_NAND_PCCARD_INT_FLAG_FALL: interrupt source of falling edge + \arg EXMC_SDRAM_INT_FLAG_REFRESH: interrupt source of refresh error + \param[out] none + \retval FlagStatus: SET or RESET +*/ +FlagStatus exmc_interrupt_flag_get(uint32_t bank, uint32_t interrupt_source) +{ + uint32_t status = 0x00000000U, interrupt_enable = 0x00000000U, interrupt_state = 0x00000000U; + + if((EXMC_BANK1_NAND == bank) || (EXMC_BANK2_NAND == bank) || (EXMC_BANK3_PCCARD == bank)){ + /* NAND bank1,bank2 or PC card bank3 */ + status = EXMC_NPINTEN(bank); + interrupt_state = (status & (interrupt_source >> INTEN_INTS_OFFSET)); + }else{ + /* SDRAM device0 or device1 */ + status = EXMC_SDARI; + interrupt_state = (EXMC_SDSTAT & EXMC_SDSDAT_REIF); + } + + interrupt_enable = (status & interrupt_source); + + if ((interrupt_enable) && (interrupt_state)){ + /* interrupt flag is set */ + return SET; + }else{ + /* interrupt flag is reset */ + return RESET; + } +} + +/*! + \brief clear EXMC interrupt flag + \param[in] bank: specifies the NAND bank , PC card bank or SDRAM device + \arg EXMC_BANK1_NAND: the NAND bank1 + \arg EXMC_BANK2_NAND: the NAND bank2 + \arg EXMC_BANK3_PCCARD: the PC card bank + \arg EXMC_SDRAM_DEVICE0: the SDRAM device0 + \arg EXMC_SDRAM_DEVICE1: the SDRAM device1 + \param[in] interrupt_source: specify get which interrupt flag + \arg EXMC_NAND_PCCARD_INT_FLAG_RISE: interrupt source of rising edge + \arg EXMC_NAND_PCCARD_INT_FLAG_LEVEL: interrupt source of high-level + \arg EXMC_NAND_PCCARD_INT_FLAG_FALL: interrupt source of falling edge + \arg EXMC_SDRAM_INT_FLAG_REFRESH: interrupt source of refresh error + \param[out] none + \retval none +*/ +void exmc_interrupt_flag_clear(uint32_t bank, uint32_t interrupt_source) +{ + if((EXMC_BANK1_NAND == bank) || (EXMC_BANK2_NAND == bank) || (EXMC_BANK3_PCCARD == bank)){ + /* NAND bank1,bank2 or PC card bank3 */ + EXMC_NPINTEN(bank) &= ~(interrupt_source >> INTEN_INTS_OFFSET); + }else{ + /* SDRAM device0 or device1 */ + EXMC_SDARI |= EXMC_SDARI_REC; + } +} + +/*! + \brief enable EXMC interrupt + \param[in] bank: specifies the NAND bank,PC card bank or SDRAM device + \arg EXMC_BANK1_NAND: the NAND bank1 + \arg EXMC_BANK2_NAND: the NAND bank2 + \arg EXMC_BANK3_PCCARD: the PC card bank + \arg EXMC_SDRAM_DEVICE0: the SDRAM device0 + \arg EXMC_SDRAM_DEVICE1: the SDRAM device1 + \param[in] interrupt_source: specify get which interrupt flag + \arg EXMC_NAND_PCCARD_INT_RISE: interrupt source of rising edge + \arg EXMC_NAND_PCCARD_INT_LEVEL: interrupt source of high-level + \arg EXMC_NAND_PCCARD_INT_FALL: interrupt source of falling edge + \arg EXMC_SDRAM_INT_REFRESH: interrupt source of refresh error + \param[out] none + \retval none +*/ +void exmc_interrupt_enable(uint32_t bank, uint32_t interrupt_source) +{ + if((EXMC_BANK1_NAND == bank) || (EXMC_BANK2_NAND == bank) || (EXMC_BANK3_PCCARD == bank)){ + /* NAND bank1,bank2 or PC card bank3 */ + EXMC_NPINTEN(bank) |= interrupt_source; + }else{ + /* SDRAM device0 or device1 */ + EXMC_SDARI |= EXMC_SDARI_REIE; + } +} + +/*! + \brief disable EXMC interrupt + \param[in] bank: specifies the NAND bank , PC card bank or SDRAM device + \arg EXMC_BANK1_NAND: the NAND bank1 + \arg EXMC_BANK2_NAND: the NAND bank2 + \arg EXMC_BANK3_PCCARD: the PC card bank + \arg EXMC_SDRAM_DEVICE0: the SDRAM device0 + \arg EXMC_SDRAM_DEVICE1: the SDRAM device1 + \param[in] interrupt_source: specify get which interrupt flag + \arg EXMC_NAND_PCCARD_INT_RISE: interrupt source of rising edge + \arg EXMC_NAND_PCCARD_INT_LEVEL: interrupt source of high-level + \arg EXMC_NAND_PCCARD_INT_FALL: interrupt source of falling edge + \arg EXMC_SDRAM_INT_REFRESH: interrupt source of refresh error + \param[out] none + \retval none +*/ +void exmc_interrupt_disable(uint32_t bank, uint32_t interrupt_source) +{ + if((EXMC_BANK1_NAND == bank) || (EXMC_BANK2_NAND == bank) || (EXMC_BANK3_PCCARD == bank)){ + /* NAND bank1,bank2 or PC card bank3 */ + EXMC_NPINTEN(bank) &= ~interrupt_source; + }else{ + /* SDRAM device0 or device1 */ + EXMC_SDARI &= ~EXMC_SDARI_REIE; + } +} diff --git a/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_standard_peripheral/Source/gd32f20x_exti.c b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_standard_peripheral/Source/gd32f20x_exti.c new file mode 100644 index 0000000000..26e29b7994 --- /dev/null +++ b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_standard_peripheral/Source/gd32f20x_exti.c @@ -0,0 +1,255 @@ +/*! + \file gd32f20x_exti.c + \brief EXTI driver + + \version 2015-07-15, V1.0.0, firmware for GD32F20x + \version 2017-06-05, V2.0.0, firmware for GD32F20x + \version 2018-10-31, V2.1.0, firmware for GD32F20x + \version 2020-09-30, V2.2.0, firmware for GD32F20x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "gd32f20x_exti.h" + +#define EXTI_REG_RESET_VALUE ((uint32_t)0x00000000U) + +/*! + \brief deinitialize the EXTI + \param[in] none + \param[out] none + \retval none +*/ +void exti_deinit(void) +{ + /* reset the value of all the EXTI registers */ + EXTI_INTEN = EXTI_REG_RESET_VALUE; + EXTI_EVEN = EXTI_REG_RESET_VALUE; + EXTI_RTEN = EXTI_REG_RESET_VALUE; + EXTI_FTEN = EXTI_REG_RESET_VALUE; + EXTI_SWIEV = EXTI_REG_RESET_VALUE; +} + +/*! + \brief initialize the EXTI + \param[in] linex: EXTI line number, refer to exti_line_enum + only one parameter can be selected which is shown as below: + \arg EXTI_x (x=0..19): EXTI line x + \param[in] mode: interrupt or event mode, refer to exti_mode_enum + only one parameter can be selected which is shown as below: + \arg EXTI_INTERRUPT: interrupt mode + \arg EXTI_EVENT: event mode + \param[in] trig_type: interrupt trigger type, refer to exti_trig_type_enum + only one parameter can be selected which is shown as below: + \arg EXTI_TRIG_RISING: rising edge trigger + \arg EXTI_TRIG_FALLING: falling edge trigger + \arg EXTI_TRIG_BOTH: rising edge and falling edge trigger + \param[out] none + \retval none +*/ +void exti_init(exti_line_enum linex, exti_mode_enum mode, exti_trig_type_enum trig_type) +{ + /* reset the EXTI line x */ + EXTI_INTEN &= ~(uint32_t)linex; + EXTI_EVEN &= ~(uint32_t)linex; + EXTI_RTEN &= ~(uint32_t)linex; + EXTI_FTEN &= ~(uint32_t)linex; + + /* set the EXTI mode and enable the interrupts or events from EXTI line x */ + switch(mode){ + case EXTI_INTERRUPT: + EXTI_INTEN |= (uint32_t)linex; + break; + case EXTI_EVENT: + EXTI_EVEN |= (uint32_t)linex; + break; + default: + break; + } + + /* set the EXTI trigger type */ + switch(trig_type){ + case EXTI_TRIG_RISING: + EXTI_RTEN |= (uint32_t)linex; + EXTI_FTEN &= ~(uint32_t)linex; + break; + case EXTI_TRIG_FALLING: + EXTI_RTEN &= ~(uint32_t)linex; + EXTI_FTEN |= (uint32_t)linex; + break; + case EXTI_TRIG_BOTH: + EXTI_RTEN |= (uint32_t)linex; + EXTI_FTEN |= (uint32_t)linex; + break; + default: + break; + } +} + +/*! + \brief enable the interrupts from EXTI line x + \param[in] linex: EXTI line number, refer to exti_line_enum + only one parameter can be selected which is shown as below: + \arg EXTI_x (x=0..19): EXTI line x + \param[out] none + \retval none +*/ +void exti_interrupt_enable(exti_line_enum linex) +{ + EXTI_INTEN |= (uint32_t)linex; +} + +/*! + \brief enable the events from EXTI line x + \param[in] linex: EXTI line number, refer to exti_line_enum + only one parameter can be selected which is shown as below: + \arg EXTI_x (x=0..19): EXTI line x + \param[out] none + \retval none +*/ +void exti_event_enable(exti_line_enum linex) +{ + EXTI_EVEN |= (uint32_t)linex; +} + +/*! + \brief disable the interrupt from EXTI line x + \param[in] linex: EXTI line number, refer to exti_line_enum + only one parameter can be selected which is shown as below: + \arg EXTI_x (x=0..19): EXTI line x + \param[out] none + \retval none +*/ +void exti_interrupt_disable(exti_line_enum linex) +{ + EXTI_INTEN &= ~(uint32_t)linex; +} + +/*! + \brief disable the events from EXTI line x + \param[in] linex: EXTI line number, refer to exti_line_enum + only one parameter can be selected which is shown as below: + \arg EXTI_x (x=0..19): EXTI line x + \param[out] none + \retval none +*/ +void exti_event_disable(exti_line_enum linex) +{ + EXTI_EVEN &= ~(uint32_t)linex; +} + +/*! + \brief get EXTI lines flag + \param[in] linex: EXTI line number, refer to exti_line_enum + only one parameter can be selected which is shown as below: + \arg EXTI_x (x=0..19): EXTI line x + \param[out] none + \retval FlagStatus: status of flag (RESET or SET) +*/ +FlagStatus exti_flag_get(exti_line_enum linex) +{ + if(RESET != (EXTI_PD & (uint32_t)linex)){ + return SET; + }else{ + return RESET; + } +} + +/*! + \brief clear EXTI lines pending flag + \param[in] linex: EXTI line number, refer to exti_line_enum + only one parameter can be selected which is shown as below: + \arg EXTI_x (x=0..19): EXTI line x + \param[out] none + \retval none +*/ +void exti_flag_clear(exti_line_enum linex) +{ + EXTI_PD = (uint32_t)linex; +} + +/*! + \brief get EXTI lines flag when the interrupt flag is set + \param[in] linex: EXTI line number, refer to exti_line_enum + only one parameter can be selected which is shown as below: + \arg EXTI_x (x=0..19): EXTI line x + \param[out] none + \retval FlagStatus: status of flag (RESET or SET) +*/ +FlagStatus exti_interrupt_flag_get(exti_line_enum linex) +{ + uint32_t flag_left, flag_right; + + flag_left = EXTI_PD & (uint32_t)linex; + flag_right = EXTI_INTEN & (uint32_t)linex; + + if((RESET != flag_left) && (RESET != flag_right)){ + return SET; + }else{ + return RESET; + } +} + +/*! + \brief clear EXTI lines pending flag + \param[in] linex: EXTI line number, refer to exti_line_enum + only one parameter can be selected which is shown as below: + \arg EXTI_x (x=0..19): EXTI line x + \param[out] none + \retval none +*/ +void exti_interrupt_flag_clear(exti_line_enum linex) +{ + EXTI_PD = (uint32_t)linex; +} + +/*! + \brief enable EXTI software interrupt event + \param[in] linex: EXTI line number, refer to exti_line_enum + only one parameter can be selected which is shown as below: + \arg EXTI_x (x=0..19): EXTI line x + \param[out] none + \retval none +*/ +void exti_software_interrupt_enable(exti_line_enum linex) +{ + EXTI_SWIEV |= (uint32_t)linex; +} + +/*! + \brief disable EXTI software interrupt event + \param[in] linex: EXTI line number, refer to exti_line_enum + only one parameter can be selected which is shown as below: + \arg EXTI_x (x=0..19): EXTI line x + \param[out] none + \retval none +*/ +void exti_software_interrupt_disable(exti_line_enum linex) +{ + EXTI_SWIEV &= ~(uint32_t)linex; +} diff --git a/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_standard_peripheral/Source/gd32f20x_fmc.c b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_standard_peripheral/Source/gd32f20x_fmc.c new file mode 100644 index 0000000000..a2a55e4baf --- /dev/null +++ b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_standard_peripheral/Source/gd32f20x_fmc.c @@ -0,0 +1,966 @@ +/*! + \file gd32f20x_fmc.c + \brief FMC driver + + \version 2015-07-15, V1.0.0, firmware for GD32F20x + \version 2017-06-05, V2.0.0, firmware for GD32F20x + \version 2018-10-31, V2.1.0, firmware for GD32F20x + \version 2020-09-30, V2.2.0, firmware for GD32F20x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "gd32f20x_fmc.h" + +/*! + \brief set the wait state counter value + \param[in] wscnt£ºwait state counter value + \arg WS_WSCNT_0: FMC 0 wait state + \arg WS_WSCNT_1: FMC 1 wait state + \arg WS_WSCNT_2: FMC 2 wait state + \param[out] none + \retval none +*/ +void fmc_wscnt_set(uint32_t wscnt) +{ + uint32_t reg; + + reg = FMC_WS; + /* set the wait state counter value */ + reg &= ~FMC_WS_WSCNT; + FMC_WS = (reg | wscnt); +} + +/*! + \brief unlock the main FMC operation + \param[in] none + \param[out] none + \retval none +*/ +void fmc_unlock(void) +{ + if((RESET != (FMC_CTL0 & FMC_CTL0_LK))){ + /* write the FMC unlock key */ + FMC_KEY0 = UNLOCK_KEY0; + FMC_KEY0 = UNLOCK_KEY1; + } + if(FMC_BANK0_SIZE < FMC_SIZE){ + /* write the FMC unlock key */ + if(RESET != (FMC_CTL1 & FMC_CTL1_LK)){ + FMC_KEY1 = UNLOCK_KEY0; + FMC_KEY1 = UNLOCK_KEY1; + } + } +} + +/*! + \brief unlock the FMC bank0 operation + this function can be used for all GD32F20x devices. + for GD32F20x with flash more than 512KB, this function unlocks bank0. + for GD32F20x with flash no more than 512KB and it is equivalent to fmc_unlock function. + \param[in] none + \param[out] none + \retval none +*/ +void fmc_bank0_unlock(void) +{ + if((RESET != (FMC_CTL0 & FMC_CTL0_LK))){ + /* write the FMC unlock key */ + FMC_KEY0 = UNLOCK_KEY0; + FMC_KEY0 = UNLOCK_KEY1; + } +} + +/*! + \brief unlock the FMC bank1 operation + this function can be used for GD32F20x with flash more than 512KB. + \param[in] none + \param[out] none + \retval none +*/ +void fmc_bank1_unlock(void) +{ + if((RESET != (FMC_CTL1 & FMC_CTL1_LK))){ + /* write the FMC unlock key */ + FMC_KEY1 = UNLOCK_KEY0; + FMC_KEY1 = UNLOCK_KEY1; + } +} + +/*! + \brief lock the main FMC operation + \param[in] none + \param[out] none + \retval none +*/ +void fmc_lock(void) +{ + /* set the LK bit */ + FMC_CTL0 |= FMC_CTL0_LK; + + if(FMC_BANK0_SIZE < FMC_SIZE){ + /* set the LK bit */ + FMC_CTL1 |= FMC_CTL1_LK; + } +} + +/*! + \brief lock the FMC bank0 operation + this function can be used for all GD32F20X devices. + for GD32F20x with flash more than 512KB, this function locks bank0. + for GD32F20x with flash no more than 512KB and it is equivalent to fmc_lock function. + \param[in] none + \param[out] none + \retval none +*/ +void fmc_bank0_lock(void) +{ + /* set the LK bit*/ + FMC_CTL0 |= FMC_CTL0_LK; +} + +/*! + \brief lock the FMC bank1 operation + this function can be used for GD32F20x with flash more than 512KB. + \param[in] none + \param[out] none + \retval none +*/ +void fmc_bank1_lock(void) +{ + /* set the LK bit*/ + FMC_CTL1 |= FMC_CTL1_LK; +} + +/*! + \brief erase page + \param[in] page_address: the page address to be erased. + \param[out] none + \retval state of FMC, refer to fmc_state_enum +*/ +fmc_state_enum fmc_page_erase(uint32_t page_address) +{ + fmc_state_enum fmc_state; + /* flash size is greater than 512k */ + if(FMC_BANK0_SIZE < FMC_SIZE){ + if(FMC_BANK0_END_ADDRESS > page_address){ + fmc_state = fmc_bank0_ready_wait(FMC_TIMEOUT_COUNT); + /* if the last operation is completed, start page erase */ + if(FMC_READY == fmc_state){ + FMC_CTL0 |= FMC_CTL0_PER; + FMC_ADDR0 = page_address; + FMC_CTL0 |= FMC_CTL0_START; + /* wait for the FMC ready */ + fmc_state = fmc_bank0_ready_wait(FMC_TIMEOUT_COUNT); + /* reset the PER bit */ + FMC_CTL0 &= ~FMC_CTL0_PER; + } + }else{ + /* wait for the FMC ready */ + fmc_state = fmc_bank1_ready_wait(FMC_TIMEOUT_COUNT); + /* if the last operation is completed, start page erase */ + if(FMC_READY == fmc_state){ + FMC_CTL1 |= FMC_CTL1_PER; + FMC_ADDR1 = page_address; + if(FMC_OBSTAT & FMC_OBSTAT_SPC){ + FMC_ADDR0 = page_address; + } + FMC_CTL1 |= FMC_CTL1_START; + /* wait for the FMC ready */ + fmc_state = fmc_bank1_ready_wait(FMC_TIMEOUT_COUNT); + /* reset the PER bit */ + FMC_CTL1 &= ~FMC_CTL1_PER; + } + } + }else{ + fmc_state = fmc_bank0_ready_wait(FMC_TIMEOUT_COUNT); + /* if the last operation is completed, start page erase */ + if(FMC_READY == fmc_state){ + FMC_CTL0 |= FMC_CTL0_PER; + FMC_ADDR0 = page_address; + FMC_CTL0 |= FMC_CTL0_START; + /* wait for the FMC ready */ + fmc_state = fmc_bank0_ready_wait(FMC_TIMEOUT_COUNT); + /* reset the PER bit */ + FMC_CTL0 &= ~FMC_CTL0_PER; + } + } + /* return the FMC state */ + return fmc_state; +} + +/*! + \brief erase whole chip + \param[in] none + \param[out] none + \retval state of FMC, refer to fmc_state_enum +*/ +fmc_state_enum fmc_mass_erase(void) +{ + fmc_state_enum fmc_state; + /* flash size is greater than 512k */ + if(FMC_BANK0_SIZE < FMC_SIZE){ + /* wait for the FMC ready */ + fmc_state = fmc_bank0_ready_wait(FMC_TIMEOUT_COUNT); + if(FMC_READY == fmc_state){ + /* start whole chip erase */ + FMC_CTL0 |= FMC_CTL0_MER; + FMC_CTL0 |= FMC_CTL0_START; + /* wait for the FMC ready */ + fmc_state = fmc_bank0_ready_wait(FMC_TIMEOUT_COUNT); + /* reset the MER bit */ + FMC_CTL0 &= ~FMC_CTL0_MER; + } + fmc_state = fmc_bank1_ready_wait(FMC_TIMEOUT_COUNT); + if(FMC_READY == fmc_state){ + /* start whole chip erase */ + FMC_CTL1 |= FMC_CTL1_MER; + FMC_CTL1 |= FMC_CTL1_START; + /* wait for the FMC ready */ + fmc_state = fmc_bank1_ready_wait(FMC_TIMEOUT_COUNT); + /* reset the MER bit */ + FMC_CTL1 &= ~FMC_CTL1_MER; + } + }else{ + fmc_state = fmc_bank0_ready_wait(FMC_TIMEOUT_COUNT); + + if(FMC_READY == fmc_state){ + /* start whole chip erase */ + FMC_CTL0 |= FMC_CTL0_MER; + FMC_CTL0 |= FMC_CTL0_START; + /* wait for the FMC ready */ + fmc_state = fmc_bank0_ready_wait(FMC_TIMEOUT_COUNT); + /* reset the MER bit */ + FMC_CTL0 &= ~FMC_CTL0_MER; + } + } + /* return the FMC state */ + return fmc_state; +} + +/*! + \brief erase bank0 + \param[in] none + \param[out] none + \retval state of FMC, refer to fmc_state_enum +*/ +fmc_state_enum fmc_bank0_erase(void) +{ + fmc_state_enum fmc_state = FMC_READY; + /* wait for the FMC ready */ + fmc_state = fmc_bank0_ready_wait(FMC_TIMEOUT_COUNT); + + if(FMC_READY == fmc_state){ + /* start FMC bank0 erase */ + FMC_CTL0 |= FMC_CTL0_MER; + FMC_CTL0 |= FMC_CTL0_START; + /* wait for the FMC ready */ + fmc_state = fmc_bank0_ready_wait(FMC_TIMEOUT_COUNT); + /* reset the MER bit */ + FMC_CTL0 &= ~FMC_CTL0_MER; + } + /* return the fmc state */ + return fmc_state; +} + +/*! + \brief erase bank1 + \param[in] none + \param[out] none + \retval state of FMC, refer to fmc_state_enum +*/ +fmc_state_enum fmc_bank1_erase(void) +{ + fmc_state_enum fmc_state = FMC_READY; + /* wait for the FMC ready */ + fmc_state = fmc_bank1_ready_wait(FMC_TIMEOUT_COUNT); + + if(FMC_READY == fmc_state){ + /* start FMC bank1 erase */ + FMC_CTL1 |= FMC_CTL1_MER; + FMC_CTL1 |= FMC_CTL1_START; + /* wait for the FMC ready */ + fmc_state = fmc_bank1_ready_wait(FMC_TIMEOUT_COUNT); + /* reset the MER bit */ + FMC_CTL1 &= ~FMC_CTL1_MER; + } + /* return the fmc state */ + return fmc_state; +} + +/*! + \brief program a word at the corresponding address + \param[in] address: address to program + \param[in] data: word to program + \param[out] none + \retval state of FMC, refer to fmc_state_enum +*/ +fmc_state_enum fmc_word_program(uint32_t address, uint32_t data) +{ + fmc_state_enum fmc_state = FMC_READY; + /* flash size is greater than 512k */ + if(FMC_BANK0_SIZE < FMC_SIZE){ + if(FMC_BANK0_END_ADDRESS > address){ + fmc_state = fmc_bank0_ready_wait(FMC_TIMEOUT_COUNT); + + if(FMC_READY == fmc_state){ + /* set the PG bit to start program */ + FMC_CTL0 |= FMC_CTL0_PG; + REG32(address) = data; + /* wait for the FMC ready */ + fmc_state = fmc_bank0_ready_wait(FMC_TIMEOUT_COUNT); + /* reset the PG bit */ + FMC_CTL0 &= ~FMC_CTL0_PG; + } + }else{ + fmc_state = fmc_bank1_ready_wait(FMC_TIMEOUT_COUNT); + + if(FMC_READY == fmc_state){ + /* set the PG bit to start program */ + FMC_CTL1 |= FMC_CTL1_PG; + REG32(address) = data; + /* wait for the FMC ready */ + fmc_state = fmc_bank1_ready_wait(FMC_TIMEOUT_COUNT); + /* reset the PG bit */ + FMC_CTL1 &= ~FMC_CTL1_PG; + } + } + }else{ + fmc_state = fmc_bank0_ready_wait(FMC_TIMEOUT_COUNT); + + if(FMC_READY == fmc_state){ + /* set the PG bit to start program */ + FMC_CTL0 |= FMC_CTL0_PG; + REG32(address) = data; + /* wait for the FMC ready */ + fmc_state = fmc_bank0_ready_wait(FMC_TIMEOUT_COUNT); + /* reset the PG bit */ + FMC_CTL0 &= ~FMC_CTL0_PG; + } + } + /* return the FMC state */ + return fmc_state; +} + +/*! + \brief program a half word at the corresponding address + \param[in] address: address to program + \param[in] data: halfword to program + \param[out] none + \retval state of FMC, refer to fmc_state_enum +*/ +fmc_state_enum fmc_halfword_program(uint32_t address, uint16_t data) +{ + fmc_state_enum fmc_state = FMC_READY; + /* flash size is greater than 512k */ + if(FMC_BANK0_SIZE < FMC_SIZE){ + if(FMC_BANK0_END_ADDRESS > address){ + fmc_state = fmc_bank0_ready_wait(FMC_TIMEOUT_COUNT); + + if(FMC_READY == fmc_state){ + /* set the PG bit to start program */ + FMC_CTL0 |= FMC_CTL0_PG; + REG16(address) = data; + /* wait for the FMC ready */ + fmc_state = fmc_bank0_ready_wait(FMC_TIMEOUT_COUNT); + /* reset the PG bit */ + FMC_CTL0 &= ~FMC_CTL0_PG; + } + }else{ + fmc_state = fmc_bank1_ready_wait(FMC_TIMEOUT_COUNT); + + if(FMC_READY == fmc_state){ + /* set the PG bit to start program */ + FMC_CTL1 |= FMC_CTL1_PG; + REG16(address) = data; + /* wait for the FMC ready */ + fmc_state = fmc_bank1_ready_wait(FMC_TIMEOUT_COUNT); + /* reset the PG bit */ + FMC_CTL1 &= ~FMC_CTL1_PG; + } + } + }else{ + fmc_state = fmc_bank0_ready_wait(FMC_TIMEOUT_COUNT); + + if(FMC_READY == fmc_state){ + /* set the PG bit to start program */ + FMC_CTL0 |= FMC_CTL0_PG; + REG16(address) = data; + /* wait for the FMC ready */ + fmc_state = fmc_bank0_ready_wait(FMC_TIMEOUT_COUNT); + /* reset the PG bit */ + FMC_CTL0 &= ~FMC_CTL0_PG; + } + } + /* return the FMC state */ + return fmc_state; +} + +/*! + \brief unlock the option byte operation + \param[in] none + \param[out] none + \retval none +*/ +void ob_unlock(void) +{ + if(RESET == (FMC_CTL0 & FMC_CTL0_OBWEN)){ + /* write the FMC key */ + FMC_OBKEY = UNLOCK_KEY0; + FMC_OBKEY = UNLOCK_KEY1; + } + + /* wait until OBWEN bit is set by hardware */ + while(RESET == (FMC_CTL0 & FMC_CTL0_OBWEN)){ + } +} + +/*! + \brief lock the option byte operation + \param[in] none + \param[out] none + \retval none +*/ +void ob_lock(void) +{ + /* reset the OBWEN bit */ + FMC_CTL0 &= ~FMC_CTL0_OBWEN; +} + +/*! + \brief erase the FMC option byte + unlock the FMC_CTL0 and option byte before calling this function + \param[in] none + \param[out] none + \retval state of FMC, refer to fmc_state_enum +*/ +fmc_state_enum ob_erase(void) +{ + uint16_t temp_spc = FMC_NSPC; + + fmc_state_enum fmc_state = fmc_bank0_ready_wait(FMC_TIMEOUT_COUNT); + + /* check the option byte security protection value */ + if(RESET != ob_spc_get()){ + temp_spc = FMC_USPC; + } + + if(FMC_READY == fmc_state){ + + /* start erase the option byte */ + FMC_CTL0 |= FMC_CTL0_OBER; + FMC_CTL0 |= FMC_CTL0_START; + + /* wait for the FMC ready */ + fmc_state = fmc_bank0_ready_wait(FMC_TIMEOUT_COUNT); + + if(FMC_READY == fmc_state){ + /* reset the OBER bit */ + FMC_CTL0 &= ~FMC_CTL0_OBER; + /* set the OBPG bit */ + FMC_CTL0 |= FMC_CTL0_OBPG; + /* no security protection */ + OB_SPC = (uint16_t)temp_spc; + /* wait for the FMC ready */ + fmc_state = fmc_bank0_ready_wait(FMC_TIMEOUT_COUNT); + if(FMC_TOERR != fmc_state){ + /* reset the OBPG bit */ + FMC_CTL0 &= ~FMC_CTL0_OBPG; + } + }else{ + if(FMC_TOERR != fmc_state){ + /* reset the OBPG bit */ + FMC_CTL0 &= ~FMC_CTL0_OBPG; + } + } + } + /* return the FMC state */ + return fmc_state; +} + +/*! + \brief enable write protection + \param[in] ob_wp: specify sector to be write protected, set the bit to 1 if + you want to protect the corresponding pages. meanwhile, sector + macro could used to set specific sector write protected. + one or more parameters can be selected which are shown as below: + \arg OB_WPx(x = 0..31): write protect specify sector + \arg OB_WP_ALL: write protect all sector + \param[out] none + \retval state of FMC, refer to fmc_state_enum +*/ +fmc_state_enum ob_write_protection_enable(uint32_t ob_wp) +{ + uint16_t temp_wp0, temp_wp1, temp_wp2, temp_wp3; + + fmc_state_enum fmc_state = fmc_bank0_ready_wait(FMC_TIMEOUT_COUNT); + + ob_wp = (uint32_t)(~ob_wp); + temp_wp0 = (uint16_t)(ob_wp & OB_WP0_WP0); + temp_wp1 = (uint16_t)((ob_wp & OB_WP1_WP1) >> 8U); + temp_wp2 = (uint16_t)((ob_wp & OB_WP2_WP2) >> 16U); + temp_wp3 = (uint16_t)((ob_wp & OB_WP3_WP3) >> 24U); + + if(FMC_READY == fmc_state){ + + /* set the OBPG bit*/ + FMC_CTL0 |= FMC_CTL0_OBPG; + + if(0xFFU != temp_wp0){ + OB_WP0 = temp_wp0; + + /* wait for the FMC ready */ + fmc_state = fmc_bank0_ready_wait(FMC_TIMEOUT_COUNT); + } + if((FMC_READY == fmc_state) && (0xFFU != temp_wp1)){ + OB_WP1 = temp_wp1; + + /* wait for the FMC ready */ + fmc_state = fmc_bank0_ready_wait(FMC_TIMEOUT_COUNT); + } + if((FMC_READY == fmc_state) && (0xFFU != temp_wp2)){ + OB_WP2 = temp_wp2; + + /* wait for the FMC ready */ + fmc_state = fmc_bank0_ready_wait(FMC_TIMEOUT_COUNT); + } + if((FMC_READY == fmc_state) && (0xFFU != temp_wp3)){ + OB_WP3 = temp_wp3; + + /* wait for the FMC ready */ + fmc_state = fmc_bank0_ready_wait(FMC_TIMEOUT_COUNT); + } + if(FMC_TOERR != fmc_state){ + /* reset the OBPG bit */ + FMC_CTL0 &= ~FMC_CTL0_OBPG; + } + } + /* return the FMC state */ + return fmc_state; +} + +/*! + \brief configure security protection + \param[in] ob_spc: specify security protection + only one parameter can be selected which is shown as below: + \arg FMC_NSPC: no security protection + \arg FMC_USPC: under security protection + \param[out] none + \retval state of FMC, refer to fmc_state_enum +*/ +fmc_state_enum ob_security_protection_config(uint8_t ob_spc) +{ + fmc_state_enum fmc_state = fmc_bank0_ready_wait(FMC_TIMEOUT_COUNT); + + if(FMC_READY == fmc_state){ + FMC_CTL0 |= FMC_CTL0_OBER; + FMC_CTL0 |= FMC_CTL0_START; + + /* wait for the FMC ready */ + fmc_state = fmc_bank0_ready_wait(FMC_TIMEOUT_COUNT); + + if(FMC_READY == fmc_state){ + /* reset the OBER bit */ + FMC_CTL0 &= ~FMC_CTL0_OBER; + + /* start the option byte program */ + FMC_CTL0 |= FMC_CTL0_OBPG; + + OB_SPC = (uint16_t)ob_spc; + + /* wait for the FMC ready */ + fmc_state = fmc_bank0_ready_wait(FMC_TIMEOUT_COUNT); + + if(FMC_TOERR != fmc_state){ + /* reset the OBPG bit */ + FMC_CTL0 &= ~FMC_CTL0_OBPG; + } + }else{ + if(FMC_TOERR != fmc_state){ + /* reset the OBER bit */ + FMC_CTL0 &= ~FMC_CTL0_OBER; + } + } + } + /* return the FMC state */ + return fmc_state; +} + +/*! + \brief program the FMC user option byte + \param[in] ob_fwdgt: option byte watchdog value + \arg OB_FWDGT_SW: software free watchdog + \arg OB_FWDGT_HW: hardware free watchdog + \param[in] ob_deepsleep: option byte deepsleep reset value + \arg OB_DEEPSLEEP_NRST: no reset when entering deepsleep mode + \arg OB_DEEPSLEEP_RST: generate a reset instead of entering deepsleep mode + \param[in] ob_stdby:option byte standby reset value + \arg OB_STDBY_NRST: no reset when entering standby mode + \arg OB_STDBY_RST: generate a reset instead of entering standby mode + \param[in] ob_boot: specifies the option byte boot bank value + \arg OB_BOOT_B0: boot from bank0 + \arg OB_BOOT_B1: boot from bank1 or bank0 if bank1 is void + \param[out] none + \retval state of FMC, refer to fmc_state_enum +*/ +fmc_state_enum ob_user_write(uint8_t ob_fwdgt, uint8_t ob_deepsleep, uint8_t ob_stdby, uint8_t ob_boot) +{ + fmc_state_enum fmc_state = FMC_READY; + uint8_t temp; + + /* wait for the FMC ready */ + fmc_state = fmc_bank0_ready_wait(FMC_TIMEOUT_COUNT); + + if(FMC_READY == fmc_state){ + /* set the OBPG bit*/ + FMC_CTL0 |= FMC_CTL0_OBPG; + + temp = ((uint8_t)((uint8_t)((uint8_t)(ob_boot | ob_fwdgt) | ob_deepsleep) | ob_stdby) | OB_USER_MASK); + OB_USER = (uint16_t)temp; + + /* wait for the FMC ready */ + fmc_state = fmc_bank0_ready_wait(FMC_TIMEOUT_COUNT); + + if(FMC_TOERR != fmc_state){ + /* reset the OBPG bit */ + FMC_CTL0 &= ~FMC_CTL0_OBPG; + } + } + /* return the FMC state */ + return fmc_state; +} + +/*! + \brief program option bytes data + \param[in] address: the option bytes address to be programmed + \param[in] data: the byte to be programmed + \param[out] none + \retval state of FMC, refer to fmc_state_enum +*/ +fmc_state_enum ob_data_program(uint32_t address, uint8_t data) +{ + fmc_state_enum fmc_state = fmc_bank0_ready_wait(FMC_TIMEOUT_COUNT); + + if(FMC_READY == fmc_state){ + /* set the OBPG bit */ + FMC_CTL0 |= FMC_CTL0_OBPG; + REG16(address) = data; + + /* wait for the FMC ready */ + fmc_state = fmc_bank0_ready_wait(FMC_TIMEOUT_COUNT); + + if(FMC_TOERR != fmc_state){ + /* reset the OBPG bit */ + FMC_CTL0 &= ~FMC_CTL0_OBPG; + } + } + /* return the FMC state */ + return fmc_state; +} + +/*! + \brief get the FMC user option byte + \param[in] none + \param[out] none + \retval the FMC user option byte values +*/ +uint8_t ob_user_get(void) +{ + /* return the FMC user option byte value */ + return (uint8_t)(FMC_OBSTAT >> 2U); +} + +/*! + \brief get OB_DATA in register FMC_OBSTAT + \param[in] none + \param[out] none + \retval ob_data +*/ +uint16_t ob_data_get(void) +{ + return (uint16_t)(FMC_OBSTAT >> 10U); +} + +/*! + \brief get the FMC option byte write protection + \param[in] none + \param[out] none + \retval the FMC write protection option byte value +*/ +uint32_t ob_write_protection_get(void) +{ + /* return the FMC write protection option byte value */ + return FMC_WP; +} + +/*! + \brief get the FMC option byte security protection + \param[in] none + \param[out] none + \retval FlagStatus: SET or RESET +*/ +FlagStatus ob_spc_get(void) +{ + FlagStatus spc_state = RESET; + + if(RESET != (FMC_OBSTAT & FMC_OBSTAT_SPC)){ + spc_state = SET; + }else{ + spc_state = RESET; + } + return spc_state; +} + +/*! + \brief enable FMC interrupt + \param[in] interrupt: the FMC interrupt source + only one parameter can be selected which is shown as below: + \arg FMC_INT_BANK0_END: enable FMC end of program interrupt + \arg FMC_INT_BANK0_ERR: enable FMC error interrupt + \arg FMC_INT_BANK1_END: enable FMC bank1 end of program interrupt + \arg FMC_INT_BANK1_ERR: enable FMC bank1 error interrupt + \param[out] none + \retval none +*/ +void fmc_interrupt_enable(uint32_t interrupt) +{ + FMC_REG_VAL(interrupt) |= BIT(FMC_BIT_POS(interrupt)); +} + +/*! + \brief disable FMC interrupt + \param[in] interrupt: the FMC interrupt source + only one parameter can be selected which is shown as below: + \arg FMC_INT_BANK0_END: enable FMC end of program interrupt + \arg FMC_INT_BANK0_ERR: enable FMC error interrupt + \arg FMC_INT_BANK1_END: enable FMC bank1 end of program interrupt + \arg FMC_INT_BANK1_ERR: enable FMC bank1 error interrupt + \param[out] none + \retval none +*/ +void fmc_interrupt_disable(uint32_t interrupt) +{ + FMC_REG_VAL(interrupt) &= ~BIT(FMC_BIT_POS(interrupt)); +} + +/*! + \brief check flag is set or not + \param[in] flag: check FMC flag + only one parameter can be selected which is shown as below: + \arg FMC_FLAG_BANK0_BUSY: FMC bank0 busy flag bit + \arg FMC_FLAG_BANK0_PGERR: FMC bank0 operation error flag bit + \arg FMC_FLAG_BANK0_WPERR: FMC bank0 erase/program protection error flag bit + \arg FMC_FLAG_BANK0_END: FMC bank0 end of operation flag bit + \arg FMC_FLAG_OBERR: FMC option bytes read error flag bit + \arg FMC_FLAG_BANK1_BUSY: FMC bank1 busy flag bit + \arg FMC_FLAG_BANK1_PGERR: FMC bank1 operation error flag bit + \arg FMC_FLAG_BANK1_WPERR: FMC bank1 erase/program protection error flag bit + \arg FMC_FLAG_BANK1_END: FMC bank1 end of operation flag bit + \param[out] none + \retval FlagStatus: SET or RESET +*/ +FlagStatus fmc_flag_get(uint32_t flag) +{ + if(RESET != (FMC_REG_VAL(flag) & BIT(FMC_BIT_POS(flag)))){ + return SET; + }else{ + return RESET; + } +} + +/*! + \brief clear the FMC flag + \param[in] flag: clear FMC flag + only one parameter can be selected which is shown as below: + \arg FMC_FLAG_BANK0_PGERR: FMC bank0 operation error flag bit + \arg FMC_FLAG_BANK0_WPERR: FMC bank0 erase/program protection error flag bit + \arg FMC_FLAG_BANK0_END: FMC bank0 end of operation flag bit + \arg FMC_FLAG_BANK1_PGERR: FMC bank1 operation error flag bit + \arg FMC_FLAG_BANK1_WPERR: FMC bank1 erase/program protection error flag bit + \arg FMC_FLAG_BANK1_END: FMC bank1 end of operation flag bit + \param[out] none + \retval none +*/ +void fmc_flag_clear(uint32_t flag) +{ + FMC_REG_VAL(flag) |= BIT(FMC_BIT_POS(flag)); +} + +/*! + \brief get FMC interrupt flag state + \param[in] flag: FMC interrupt flags, refer to fmc_interrupt_flag_enum + only one parameter can be selected which is shown as below: + \arg FMC_INT_FLAG_BANK0_PGERR: FMC bank0 operation error interrupt flag bit + \arg FMC_INT_FLAG_BANK0_WPERR: FMC bank0 erase/program protection error interrupt flag bit + \arg FMC_INT_FLAG_BANK0_END: FMC bank0 end of operation interrupt flag bit + \arg FMC_INT_FLAG_BANK1_PGERR: FMC bank1 operation error interrupt flag bit + \arg FMC_INT_FLAG_BANK1_WPERR: FMC bank1 erase/program protection error interrupt flag bit + \arg FMC_INT_FLAG_BANK1_END: FMC bank1 end of operation interrupt flag bit + \param[out] none + \retval FlagStatus: SET or RESET +*/ +FlagStatus fmc_interrupt_flag_get(fmc_interrupt_flag_enum flag) +{ + FlagStatus ret1 = RESET; + FlagStatus ret2 = RESET; + + if(FMC_STAT0_REG_OFFSET == FMC_REG_OFFSET_GET(flag)){ + /* get the staus of interrupt flag */ + ret1 = (FlagStatus)(FMC_REG_VALS(flag) & BIT(FMC_BIT_POS0(flag))); + /* get the staus of interrupt enale bit */ + ret2 = (FlagStatus)(FMC_CTL0 & BIT(FMC_BIT_POS1(flag))); + }else{ + /* get the staus of interrupt flag */ + ret1 = (FlagStatus)(FMC_REG_VALS(flag) & BIT(FMC_BIT_POS0(flag))); + /* get the staus of interrupt enale bit */ + ret2 = (FlagStatus)(FMC_CTL1 & BIT(FMC_BIT_POS1(flag))); + } + + if(ret1 && ret2){ + return SET; + }else{ + return RESET; + } +} + +/*! + \brief clear FMC interrupt flag state + \param[in] flag: FMC interrupt flags, refer to can_interrupt_flag_enum + only one parameter can be selected which is shown as below: + \arg FMC_INT_FLAG_BANK0_PGERR: FMC bank0 operation error interrupt flag bit + \arg FMC_INT_FLAG_BANK0_WPERR: FMC bank0 erase/program protection error interrupt flag bit + \arg FMC_INT_FLAG_BANK0_END: FMC bank0 end of operation interrupt flag bit + \arg FMC_INT_FLAG_BANK1_PGERR: FMC bank1 operation error interrupt flag bit + \arg FMC_INT_FLAG_BANK1_WPERR: FMC bank1 erase/program protection error interrupt flag bit + \arg FMC_INT_FLAG_BANK1_END: FMC bank1 end of operation interrupt flag bit + \param[out] none + \retval none +*/ +void fmc_interrupt_flag_clear(fmc_interrupt_flag_enum flag) +{ + FMC_REG_VALS(flag) |= BIT(FMC_BIT_POS0(flag)); +} + +/*! + \brief get the FMC bank0 state + \param[in] none + \param[out] none + \retval state of FMC, refer to fmc_state_enum +*/ +fmc_state_enum fmc_bank0_state_get(void) +{ + fmc_state_enum fmc_state = FMC_READY; + + if((uint32_t)0x00U != (FMC_STAT0 & FMC_STAT0_BUSY)){ + fmc_state = FMC_BUSY; + }else{ + if((uint32_t)0x00U != (FMC_STAT0 & FMC_STAT0_WPERR)){ + fmc_state = FMC_WPERR; + }else{ + if((uint32_t)0x00U != (FMC_STAT0 & (FMC_STAT0_PGERR))){ + fmc_state = FMC_PGERR; + } + } + } + /* return the FMC state */ + return fmc_state; +} + +/*! + \brief get the FMC bank1 state + \param[in] none + \param[out] none + \retval state of FMC, refer to fmc_state_enum +*/ +fmc_state_enum fmc_bank1_state_get(void) +{ + fmc_state_enum fmc_state = FMC_READY; + + if((uint32_t)0x00U != (FMC_STAT1 & FMC_STAT1_BUSY)){ + fmc_state = FMC_BUSY; + }else{ + if((uint32_t)0x00U != (FMC_STAT1 & FMC_STAT1_WPERR)){ + fmc_state = FMC_WPERR; + }else{ + if((uint32_t)0x00U != (FMC_STAT1 & FMC_STAT1_PGERR)){ + fmc_state = FMC_PGERR; + } + } + } + + /* return the FMC state */ + return fmc_state; +} + +/*! + \brief check whether FMC bank0 is ready or not + \param[in] timeout: count of loop + \param[out] none + \retval state of FMC, refer to fmc_state_enum +*/ +fmc_state_enum fmc_bank0_ready_wait(uint32_t timeout) +{ + fmc_state_enum fmc_state = FMC_BUSY; + + /* wait for FMC ready */ + do{ + /* get FMC state */ + fmc_state = fmc_bank0_state_get(); + timeout--; + }while((FMC_BUSY == fmc_state) && (0x00U != timeout)); + + if(FMC_BUSY == fmc_state){ + fmc_state = FMC_TOERR; + } + /* return the FMC state */ + return fmc_state; +} + +/*! + \brief check whether FMC bank1 is ready or not + \param[in] timeout: count of loop + \param[out] none + \retval state of FMC, refer to fmc_state_enum +*/ +fmc_state_enum fmc_bank1_ready_wait(uint32_t timeout) +{ + fmc_state_enum fmc_state = FMC_BUSY; + + /* wait for FMC ready */ + do{ + /* get FMC state */ + fmc_state = fmc_bank1_state_get(); + timeout--; + }while((FMC_BUSY == fmc_state) && (0x00U != timeout)); + + if(FMC_BUSY == fmc_state){ + fmc_state = FMC_TOERR; + } + /* return the FMC state */ + return fmc_state; +} diff --git a/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_standard_peripheral/Source/gd32f20x_fwdgt.c b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_standard_peripheral/Source/gd32f20x_fwdgt.c new file mode 100644 index 0000000000..be51942db7 --- /dev/null +++ b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_standard_peripheral/Source/gd32f20x_fwdgt.c @@ -0,0 +1,158 @@ +/*! + \file gd32f20x_fwdgt.c + \brief FWDGT driver + + \version 2015-07-15, V1.0.0, firmware for GD32F20x + \version 2017-06-05, V2.0.0, firmware for GD32F20x + \version 2018-10-31, V2.1.0, firmware for GD32F20x + \version 2020-09-30, V2.2.0, firmware for GD32F20x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "gd32f20x_fwdgt.h" + +/* write value to FWDGT_CTL_CMD bit field */ +#define CTL_CMD(regval) (BITS(0,15) & ((uint32_t)(regval) << 0)) +/* write value to FWDGT_RLD_RLD bit field */ +#define RLD_RLD(regval) (BITS(0,11) & ((uint32_t)(regval) << 0)) + +/*! + \brief enable write access to FWDGT_PSC and FWDGT_RLD + \param[in] none + \param[out] none + \retval none +*/ +void fwdgt_write_enable(void) +{ + FWDGT_CTL = FWDGT_WRITEACCESS_ENABLE; +} + +/*! + \brief disable write access to FWDGT_PSC and FWDGT_RLD + \param[in] none + \param[out] none + \retval none +*/ +void fwdgt_write_disable(void) +{ + FWDGT_CTL = FWDGT_WRITEACCESS_DISABLE; +} + +/*! + \brief start the free watchdog timer counter + \param[in] none + \param[out] none + \retval none +*/ +void fwdgt_enable(void) +{ + FWDGT_CTL = FWDGT_KEY_ENABLE; +} + +/*! + \brief reload the counter of FWDGT + \param[in] none + \param[out] none + \retval none +*/ +void fwdgt_counter_reload(void) +{ + FWDGT_CTL = FWDGT_KEY_RELOAD; +} + +/*! + \brief configure counter reload value, and prescaler divider value + \param[in] reload_value: specify reload value(0x0000 - 0x0FFF) + \param[in] prescaler_div: FWDGT prescaler value + only one parameter can be selected which is shown as below: + \arg FWDGT_PSC_DIV4: FWDGT prescaler set to 4 + \arg FWDGT_PSC_DIV8: FWDGT prescaler set to 8 + \arg FWDGT_PSC_DIV16: FWDGT prescaler set to 16 + \arg FWDGT_PSC_DIV32: FWDGT prescaler set to 32 + \arg FWDGT_PSC_DIV64: FWDGT prescaler set to 64 + \arg FWDGT_PSC_DIV128: FWDGT prescaler set to 128 + \arg FWDGT_PSC_DIV256: FWDGT prescaler set to 256 + \param[out] none + \retval ErrStatus: ERROR or SUCCESS +*/ +ErrStatus fwdgt_config(uint16_t reload_value, uint8_t prescaler_div) +{ + uint32_t timeout = FWDGT_PSC_TIMEOUT; + uint32_t flag_status = RESET; + + /* enable write access to FWDGT_PSC,and FWDGT_RLD */ + FWDGT_CTL = FWDGT_WRITEACCESS_ENABLE; + + /* wait until the PUD flag to be reset */ + do{ + flag_status = FWDGT_STAT & FWDGT_STAT_PUD; + }while((--timeout > 0U) && ((uint32_t)RESET != flag_status)); + + if ((uint32_t)RESET != flag_status){ + return ERROR; + } + + /* configure FWDGT */ + FWDGT_PSC = (uint32_t)prescaler_div; + + timeout = FWDGT_RLD_TIMEOUT; + /* wait until the RUD flag to be reset */ + do{ + flag_status = FWDGT_STAT & FWDGT_STAT_RUD; + }while((--timeout > 0U) && ((uint32_t)RESET != flag_status)); + + if ((uint32_t)RESET != flag_status){ + return ERROR; + } + + FWDGT_RLD = RLD_RLD(reload_value); + + /* reload the counter */ + FWDGT_CTL = FWDGT_KEY_RELOAD; + + return SUCCESS; +} + +/*! + \brief get flag state of FWDGT + \param[in] flag: flag to get + only one parameter can be selected which is shown as below: + \arg FWDGT_FLAG_PUD: a write operation to FWDGT_PSC register is on going + \arg FWDGT_FLAG_RUD: a write operation to FWDGT_RLD register is on going + \param[out] none + \retval FlagStatus: SET or RESET +*/ +FlagStatus fwdgt_flag_get(uint16_t flag) +{ + if(FWDGT_STAT & flag){ + return SET; + } + + return RESET; +} diff --git a/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_standard_peripheral/Source/gd32f20x_gpio.c b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_standard_peripheral/Source/gd32f20x_gpio.c new file mode 100644 index 0000000000..b5c1de1eaa --- /dev/null +++ b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_standard_peripheral/Source/gd32f20x_gpio.c @@ -0,0 +1,726 @@ +/*! + \file gd32f20x_gpio.c + \brief GPIO driver + + \version 2015-07-15, V1.0.0, firmware for GD32F20x + \version 2017-06-05, V2.0.0, firmware for GD32F20x + \version 2018-10-31, V2.1.0, firmware for GD32F20x + \version 2020-09-30, V2.2.0, firmware for GD32F20x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "gd32f20x_gpio.h" + +#define AFIO_EXTI_SOURCE_MASK ((uint8_t)0x03U) /*!< AFIO exti source selection mask*/ +#define AFIO_EXTI_SOURCE_FIELDS ((uint8_t)0x04U) /*!< select AFIO exti source registers */ +#define LSB_16BIT_MASK ((uint16_t)0xFFFFU) /*!< LSB 16-bit mask */ +#define PCF_POSITION_MASK ((uint32_t)0x000F0000U) /*!< AFIO_PCF register position mask */ +#define PCF_SWJCFG_MASK ((uint32_t)0xF0FFFFFFU) /*!< AFIO_PCF register SWJCFG mask */ +#define PCF_LOCATION1_MASK ((uint32_t)0x00200000U) /*!< AFIO_PCF register location1 mask */ +#define PCF_LOCATION2_MASK ((uint32_t)0x00100000U) /*!< AFIO_PCF register location2 mask */ +#define AFIO_PCF1_FIELDS ((uint32_t)0x80000000U) /*!< select AFIO_PCF1 register */ +#define GPIO_OUTPUT_PORT_OFFSET ((uint32_t)4U) /*!< GPIO event output port offset*/ + +/*! + \brief reset GPIO port + \param[in] gpio_periph: GPIOx(x = A,B,C,D,E,F,G,H,I) + \param[out] none + \retval none +*/ +void gpio_deinit(uint32_t gpio_periph) +{ + switch(gpio_periph){ + case GPIOA: + /* reset GPIOA */ + rcu_periph_reset_enable(RCU_GPIOARST); + rcu_periph_reset_disable(RCU_GPIOARST); + break; + case GPIOB: + /* reset GPIOB */ + rcu_periph_reset_enable(RCU_GPIOBRST); + rcu_periph_reset_disable(RCU_GPIOBRST); + break; + case GPIOC: + /* reset GPIOC */ + rcu_periph_reset_enable(RCU_GPIOCRST); + rcu_periph_reset_disable(RCU_GPIOCRST); + break; + case GPIOD: + /* reset GPIOD */ + rcu_periph_reset_enable(RCU_GPIODRST); + rcu_periph_reset_disable(RCU_GPIODRST); + break; + case GPIOE: + /* reset GPIOE */ + rcu_periph_reset_enable(RCU_GPIOERST); + rcu_periph_reset_disable(RCU_GPIOERST); + break; + case GPIOF: + /* reset GPIOF */ + rcu_periph_reset_enable(RCU_GPIOFRST); + rcu_periph_reset_disable(RCU_GPIOFRST); + break; + case GPIOG: + /* reset GPIOG */ + rcu_periph_reset_enable(RCU_GPIOGRST); + rcu_periph_reset_disable(RCU_GPIOGRST); + break; + case GPIOH: + /* reset GPIOH */ + rcu_periph_reset_enable(RCU_GPIOHRST); + rcu_periph_reset_disable(RCU_GPIOHRST); + break; + case GPIOI: + /* reset GPIOI */ + rcu_periph_reset_enable(RCU_GPIOIRST); + rcu_periph_reset_disable(RCU_GPIOIRST); + break; + default: + break; + } +} + +/*! + \brief reset alternate function I/O(AFIO) + \param[in] none + \param[out] none + \retval none +*/ +void gpio_afio_deinit(void) +{ + rcu_periph_reset_enable(RCU_AFRST); + rcu_periph_reset_disable(RCU_AFRST); +} + +/*! + \brief GPIO parameter initialization + \param[in] gpio_periph: GPIOx(x = A,B,C,D,E,F,G,H,I) + \param[in] mode: gpio pin mode + only one parameter can be selected which is shown as below: + \arg GPIO_MODE_AIN: analog input mode + \arg GPIO_MODE_IN_FLOATING: floating input mode + \arg GPIO_MODE_IPD: pull-down input mode + \arg GPIO_MODE_IPU: pull-up input mode + \arg GPIO_MODE_OUT_OD: GPIO output with open-drain + \arg GPIO_MODE_OUT_PP: GPIO output with push-pull + \arg GPIO_MODE_AF_OD: AFIO output with open-drain + \arg GPIO_MODE_AF_PP: AFIO output with push-pull + \param[in] speed: gpio output max speed value + only one parameter can be selected which is shown as below: + \arg GPIO_OSPEED_10MHZ: output max speed 10MHz + \arg GPIO_OSPEED_2MHZ: output max speed 2MHz + \arg GPIO_OSPEED_50MHZ: output max speed 50MHz + \param[in] pin: GPIO pin + one or more parameters can be selected which are shown as below: + \arg GPIO_PIN_x(x=0..15), GPIO_PIN_ALL + + \param[out] none + \retval none +*/ +void gpio_init(uint32_t gpio_periph, uint32_t mode, uint32_t speed, uint32_t pin) +{ + uint16_t i; + uint32_t temp_mode = 0U; + uint32_t reg = 0U; + + /* GPIO mode configuration */ + temp_mode = (uint32_t)(mode & ((uint32_t)0x0FU)); + + /* GPIO speed configuration */ + if(((uint32_t)0x00U) != ((uint32_t)mode & ((uint32_t)0x10U))){ + /* output mode max speed:10MHz,2MHz,50MHz */ + temp_mode |= (uint32_t)speed; + } + + /* configure the eight low port pins with GPIO_CTL0 */ + for(i = 0U;i < 8U;i++){ + if((1U << i) & pin){ + reg = GPIO_CTL0(gpio_periph); + + /* clear the specified pin mode bits */ + reg &= ~GPIO_MODE_MASK(i); + /* set the specified pin mode bits */ + reg |= GPIO_MODE_SET(i, temp_mode); + + /* set IPD or IPU */ + if(GPIO_MODE_IPD == mode){ + /* reset the corresponding OCTL bit */ + GPIO_BC(gpio_periph) = (uint32_t)((1U << i) & pin); + }else{ + /* set the corresponding OCTL bit */ + if(GPIO_MODE_IPU == mode){ + GPIO_BOP(gpio_periph) = (uint32_t)((1U << i) & pin); + } + } + /* set GPIO_CTL0 register */ + GPIO_CTL0(gpio_periph) = reg; + } + } + /* configure the eight high port pins with GPIO_CTL1 */ + for(i = 8U;i < 16U;i++){ + if((1U << i) & pin){ + reg = GPIO_CTL1(gpio_periph); + + /* clear the specified pin mode bits */ + reg &= ~GPIO_MODE_MASK(i - 8U); + /* set the specified pin mode bits */ + reg |= GPIO_MODE_SET(i - 8U, temp_mode); + + /* set IPD or IPU */ + if(GPIO_MODE_IPD == mode){ + /* reset the corresponding OCTL bit */ + GPIO_BC(gpio_periph) = (uint32_t)((1U << i) & pin); + }else{ + /* set the corresponding OCTL bit */ + if(GPIO_MODE_IPU == mode){ + GPIO_BOP(gpio_periph) = (uint32_t)((1U << i) & pin); + } + } + /* set GPIO_CTL1 register */ + GPIO_CTL1(gpio_periph) = reg; + } + } +} + +/*! + \brief set GPIO pin + \param[in] gpio_periph: GPIOx(x = A,B,C,D,E,F,G,H,I) + \param[in] pin: GPIO pin + one or more parameters can be selected which are shown as below: + \arg GPIO_PIN_x(x=0..15), GPIO_PIN_ALL + \param[out] none + \retval none +*/ +void gpio_bit_set(uint32_t gpio_periph,uint32_t pin) +{ + GPIO_BOP(gpio_periph) = (uint32_t)pin; +} + +/*! + \brief reset GPIO pin + \param[in] gpio_periph: GPIOx(x = A,B,C,D,E,F,G,H,I) + \param[in] pin: GPIO pin + one or more parameters can be selected which are shown as below: + \arg GPIO_PIN_x(x=0..15), GPIO_PIN_ALL + \param[out] none + \retval none +*/ +void gpio_bit_reset(uint32_t gpio_periph,uint32_t pin) +{ + GPIO_BC(gpio_periph) = (uint32_t)pin; +} + +/*! + \brief write data to the specified GPIO pin + \param[in] gpio_periph: GPIOx(x = A,B,C,D,E,F,G,H,I) + \param[in] pin: GPIO pin + one or more parameters can be selected which are shown as below: + \arg GPIO_PIN_x(x=0..15), GPIO_PIN_ALL + \param[in] bit_value: SET or RESET + \arg RESET: clear the port pin + \arg SET: set the port pin + \param[out] none + \retval none +*/ +void gpio_bit_write(uint32_t gpio_periph,uint32_t pin,bit_status bit_value) +{ + if(RESET != bit_value){ + GPIO_BOP(gpio_periph) = (uint32_t)pin; + }else{ + GPIO_BC(gpio_periph) = (uint32_t)pin; + } +} + +/*! + \brief write data to the specified GPIO port + \param[in] gpio_periph: GPIOx(x = A,B,C,D,E,F,G,H,I) + \param[in] data: specify the value to be written to the port output data register + \param[out] none + \retval none +*/ +void gpio_port_write(uint32_t gpio_periph,uint16_t data) +{ + GPIO_OCTL(gpio_periph) = (uint32_t)data; +} + +/*! + \brief get GPIO pin input status + \param[in] gpio_periph: GPIOx(x = A,B,C,D,E,F,G,H,I) + \param[in] pin: GPIO pin + only one parameter can be selected which are shown as below: + \arg GPIO_PIN_x(x=0..15), GPIO_PIN_ALL + \param[out] none + \retval input status of gpio pin: SET or RESET +*/ +FlagStatus gpio_input_bit_get(uint32_t gpio_periph,uint32_t pin) +{ + if((uint32_t)RESET != (GPIO_ISTAT(gpio_periph)&(pin))){ + return SET; + }else{ + return RESET; + } +} + +/*! + \brief get GPIO port input status + \param[in] gpio_periph: GPIOx(x = A,B,C,D,E,F,G,H,I) + \param[out] none + \retval input status of gpio all pins +*/ +uint16_t gpio_input_port_get(uint32_t gpio_periph) +{ + return (uint16_t)(GPIO_ISTAT(gpio_periph)); +} + +/*! + \brief get GPIO pin output status + \param[in] gpio_periph: GPIOx(x = A,B,C,D,E,F,G,H,I) + \param[in] pin: GPIO pin + only one parameter can be selected which are shown as below: + \arg GPIO_PIN_x(x=0..15), GPIO_PIN_ALL + \param[out] none + \retval output status of gpio pin: SET or RESET +*/ +FlagStatus gpio_output_bit_get(uint32_t gpio_periph,uint32_t pin) +{ + if((uint32_t)RESET !=(GPIO_OCTL(gpio_periph)&(pin))){ + return SET; + }else{ + return RESET; + } +} + +/*! + \brief get GPIO port output status + \param[in] gpio_periph: GPIOx(x = A,B,C,D,E,F,G,H,I) + \param[out] none + \retval output status of gpio all pins +*/ +uint16_t gpio_output_port_get(uint32_t gpio_periph) +{ + return ((uint16_t)GPIO_OCTL(gpio_periph)); +} + +/*! + \brief configure GPIO pin remap + \param[in] gpio_remap: select the pin to remap + \arg GPIO_SPI0_REMAP: SPI0 remapping + \arg GPIO_I2C0_REMAP: I2C0 remapping + \arg GPIO_USART0_REMAP: USART0 remapping + \arg GPIO_USART1_REMAP: USART1 remapping + \arg GPIO_USART2_PARTIAL_REMAP: USART2 partial remapping + \arg GPIO_USART2_FULL_REMAP: USART2 full remapping + \arg GPIO_TIMER0_PARTIAL_REMAP: TIMER0 partial remapping + \arg GPIO_TIMER0_FULL_REMAP: TIMER0 full remapping + \arg GPIO_TIMER1_PARTIAL_REMAP0: TIMER1 partial remapping + \arg GPIO_TIMER1_PARTIAL_REMAP1: TIMER1 partial remapping + \arg GPIO_TIMER1_FULL_REMAP: TIMER1 full remapping + \arg GPIO_TIMER2_PARTIAL_REMAP: TIMER2 partial remapping + \arg GPIO_TIMER2_FULL_REMAP: TIMER2 full remapping + \arg GPIO_TIMER3_REMAP: TIMER3 remapping + \arg GPIO_CAN0_PARTIAL_REMAP: CAN0 partial remapping + \arg GPIO_CAN0_FULL_REMAP: CAN0 full remapping + \arg GPIO_PD01_REMAP: PD01 remapping + \arg GPIO_TIMER4CH3_IREMAP: TIMER4 channel3 internal remapping + \arg GPIO_ADC0_ETRGINS_REMAP: ADC0 external trigger inserted conversion remapping + \arg GPIO_ADC0_ETRGREG_REMAP: ADC0 external trigger regular conversion remapping + \arg GPIO_ADC1_ETRGINS_REMAP: ADC1 external trigger inserted conversion remapping + \arg GPIO_ADC1_ETRGREG_REMAP: ADC1 external trigger regular conversion remapping + \arg GPIO_ENET_REMAP: ENET remapping + \arg GPIO_CAN1_REMAP: CAN1 remapping + \arg GPIO_SWJ_NONJTRST_REMAP: full SWJ(JTAG-DP + SW-DP),but without NJTRST + \arg GPIO_SWJ_SWDPENABLE_REMAP: JTAG-DP disabled and SW-DP enabled + \arg GPIO_SWJ_DISABLE_REMAP: JTAG-DP disabled and SW-DP disabled + \arg GPIO_SPI2_REMAP: SPI2 remapping + \arg GPIO_TIMER1ITI1_REMAP: TIMER1 internal trigger 1 remapping + \arg GPIO_PTP_PPS_REMAP: ethernet PTP PPS remapping + \arg GPIO_TIMER8_REMAP: TIMER8 remapping + \arg GPIO_TIMER9_REMAP: TIMER9 remapping + \arg GPIO_TIMER10_REMAP: TIMER10 remapping + \arg GPIO_TIMER12_REMAP: TIMER12 remapping + \arg GPIO_TIMER13_REMAP: TIMER13 remapping + \arg GPIO_EXMC_NADV_REMAP: EXMC_NADV connect/disconnect + \param[in] newvalue: ENABLE or DISABLE + \param[out] none + \retval none +*/ +void gpio_pin_remap_config(uint32_t gpio_remap, ControlStatus newvalue) +{ + uint32_t remap1 = 0U, remap2 = 0U, temp_reg = 0U, temp_mask = 0U; + + if(AFIO_PCF1_FIELDS == (gpio_remap & AFIO_PCF1_FIELDS)){ + /* get AFIO_PCF1 regiter value */ + temp_reg = AFIO_PCF1; + }else{ + /* get AFIO_PCF0 regiter value */ + temp_reg = AFIO_PCF0; + } + + temp_mask = (gpio_remap & PCF_POSITION_MASK) >> 0x10U; + remap1 = gpio_remap & LSB_16BIT_MASK; + + /* judge pin remap type */ + if((PCF_LOCATION1_MASK | PCF_LOCATION2_MASK) == (gpio_remap & (PCF_LOCATION1_MASK | PCF_LOCATION2_MASK))){ + temp_reg &= PCF_SWJCFG_MASK; + AFIO_PCF0 &= PCF_SWJCFG_MASK; + }else if(PCF_LOCATION2_MASK == (gpio_remap & PCF_LOCATION2_MASK)){ + remap2 = ((uint32_t)0x03U) << temp_mask; + temp_reg &= ~remap2; + temp_reg |= ~PCF_SWJCFG_MASK; + }else{ + temp_reg &= ~(remap1 << ((gpio_remap >> 0x15U)*0x10U)); + temp_reg |= ~PCF_SWJCFG_MASK; + } + + /* set pin remap value */ + if(DISABLE != newvalue){ + temp_reg |= (remap1 << ((gpio_remap >> 0x15U)*0x10U)); + } + + if(AFIO_PCF1_FIELDS == (gpio_remap & AFIO_PCF1_FIELDS)){ + /* set AFIO_PCF1 regiter value */ + AFIO_PCF1 = temp_reg; + }else{ + /* set AFIO_PCF0 regiter value */ + AFIO_PCF0 = temp_reg; + } +} + +/*! + \brief configure GPIO pin remap1 + \param[in] remap_reg: + \arg GPIO_PCF2: AFIO port configuration register 2 + \arg GPIO_PCF3: AFIO port configuration register 3 + \arg GPIO_PCF4: AFIO port configuration register 4 + \arg GPIO_PCF5: AFIO port configuration register 5 + \param[in] remap: select the pin to remap + \arg GPIO_PCF2_DCI_VSYNC_PG9_REMAP: DCI VSYNC remapped to PG9 + \arg GPIO_PCF2_DCI_VSYNC_PI5_REMAP: DCI VSYNC remapped to PI5 + \arg GPIO_PCF2_DCI_D0_PC6_REMAP: DCI D0 remapped to PC6 + \arg GPIO_PCF2_DCI_D0_PH9_REMAP: DCI D0 remapped to PH9 + \arg GPIO_PCF2_DCI_D1_PC7_REMAP: DCI D1 remapped to PC7 + \arg GPIO_PCF2_DCI_D1_PH10_REMAP: DCI D1 remapped to PH10 + \arg GPIO_PCF2_DCI_D2_PE0_REMAP: DCI D2 remapped to PE0 + \arg GPIO_PCF2_DCI_D2_PG10_REMAP: DCI D2 remapped to PG10 + \arg GPIO_PCF2_DCI_D2_PH11_REMAP: DCI D2 remapped to PH11 + \arg GPIO_PCF2_DCI_D3_PE1_REMAP: DCI D3 remapped to PE1 + \arg GPIO_PCF2_DCI_D3_PG11_REMAP: DCI D3 remapped to PG11 + \arg GPIO_PCF2_DCI_D3_PH12_REMAP: DCI D3 remapped to PH12 + \arg GPIO_PCF2_DCI_D4_PE4_REMAP: DCI D4 remapped to PE4 + \arg GPIO_PCF2_DCI_D4_PH14_REMAP: DCI D4 remapped to PH14 + \arg GPIO_PCF2_DCI_D5_PD3_REMAP: DCI D5 remapped to PD3 + \arg GPIO_PCF2_DCI_D5_PI4_REMAP: DCI D5 remapped to PI4 + \arg GPIO_PCF2_DCI_D6_PE5_REMAP: DCI D6 remapped to PE5 + \arg GPIO_PCF2_DCI_D6_PI6_REMAP: DCI D6 remapped to PI6 + \arg GPIO_PCF2_DCI_D7_PE6_REMAP: DCI D7 remapped to PE6 + \arg GPIO_PCF2_DCI_D7_PI7_REMAP: DCI D7 remapped to PI7 + \arg GPIO_PCF2_DCI_D8_PH6_REMAP: DCI D8 remapped to PH6 + \arg GPIO_PCF2_DCI_D8_PI1_REMAP: DCI D8 remapped to PI1 + \arg GPIO_PCF2_DCI_D9_PH7_REMAP: DCI D9 remapped to PH7 + \arg GPIO_PCF2_DCI_D9_PI2_REMAP: DCI D9 remapped to PI2 + \arg GPIO_PCF2_DCI_D10_PD6_REMAP: DCI D10 remapped to PD6 + \arg GPIO_PCF2_DCI_D10_PI3_REMAP: DCI D10 remapped to PI3 + \arg GPIO_PCF2_DCI_D11_PF10_REMAP: DCI D11 remapped to PF10 + \arg GPIO_PCF2_DCI_D11_PH15_REMAP: DCI D11 remapped to PH15 + \arg GPIO_PCF2_DCI_D12_PG6_REMAP: DCI D12 remapped to PG6 + \arg GPIO_PCF2_DCI_D13_PG15_REMAP: DCI D12 remapped to PG15 + \arg GPIO_PCF2_DCI_D13_PI0_REMAP: DCI D13 remapped to PI0 + \arg GPIO_PCF2_DCI_HSYNC_PH8_REMAP: DCI HSYNC to PH8 + \arg GPIO_PCF2_PH01_REMAP: PH0/PH1 remapping + \arg GPIO_PCF3_TLI_B5_PA3_REMAP: TLI B5 remapped to PA3 + \arg GPIO_PCF3_TLI_VSYNC_PA4_REMAP: TLI VSYNC remapped to PA4 + \arg GPIO_PCF3_TLI_G2_PA6_REMAP: TLI G2 remapped to PA6 + \arg GPIO_PCF3_TLI_R6_PA8_REMAP: TLI R6 remapped to PA8 + \arg GPIO_PCF3_TLI_R4_PA11_REMAP: TLI R4 remapped to PA11 + \arg GPIO_PCF3_TLI_R5_PA12_REMAP: TLI R5 remapped to PA12 + \arg GPIO_PCF3_TLI_R3_PB0_REMAP: TLI R3 remapped to PB0 + \arg GPIO_PCF3_TLI_R6_PB1_REMAP: TLI R6 remapped to PB1 + \arg GPIO_PCF3_TLI_B6_PB8_REMAP: TLI B6 remapped to PB8 + \arg GPIO_PCF3_TLI_B7_PB9_REMAP: TLI B7 remapped to PB9 + \arg GPIO_PCF3_TLI_G4_PB10_REMAP: TLI G4 remapped to PB10 + \arg GPIO_PCF3_TLI_G5_PB11_REMAP: TLI G5 remapped to PB11 + \arg GPIO_PCF3_TLI_HSYNC_PC6_REMAP: TLI HSYNC remapped to PC6 + \arg GPIO_PCF3_TLI_G6_PC7_REMAP: TLI G6 remapped to PC7 + \arg GPIO_PCF3_TLI_R2_PC10_REMAP: TLI R2 remapped to PC10 + \arg GPIO_PCF3_TLI_G7_PD3_REMAP: TLI G7 remapped to PD3 + \arg GPIO_PCF3_TLI_B2_PD6_REMAP: TLI B2 remapped to PD6 + \arg GPIO_PCF3_TLI_B3_PD10_REMAP: TLI B3 remapped to PD10 + \arg GPIO_PCF3_TLI_B0_PE4_REMAP: TLI B0 remapped to PE4 + \arg GPIO_PCF3_TLI_G0_PE5_REMAP: TLI G0 remapped to PE5 + \arg GPIO_PCF3_TLI_G1_PE6_REMAP: TLI G1 remapped to PE6 + \arg GPIO_PCF3_TLI_G3_PE11_REMAP: TLI G3 remapped to PE11 + \arg GPIO_PCF3_TLI_B4_PE12_REMAP: TLI B4 remapped to PE12 + \arg GPIO_PCF3_TLI_DE_PE13_REMAP: TLI DE remapped to PE13 + \arg GPIO_PCF3_TLI_CLK_PE14_REMAP: TLI CLK remapped to PE14 + \arg GPIO_PCF3_TLI_R7_PE15_REMAP: TLI R7 remapped to PE15 + \arg GPIO_PCF3_TLI_DE_PF10_REMAP: TLI DE remapped to PF10 + \arg GPIO_PCF3_TLI_R7_PG6_REMAP: TLI R7 remapped to PG6 + \arg GPIO_PCF3_TLI_CLK_PG7_REMAP: TLI CLK remapped to PG7 + \arg GPIO_PCF3_TLI_G3_PG10_REMAP: TLI G3 remapped to PG10 + \arg GPIO_PCF3_TLI_B2_PG10_REMAP: TLI B2 remapped to PG10 + \arg GPIO_PCF3_TLI_B3_PG11_REMAP: TLI B3 remapped to PG11 + \arg GPIO_PCF4_TLI_B4_PG12_REMAP: B4 remapped to PG12 + \arg GPIO_PCF4_TLI_B1_PG12_REMAP: B1 remapped to PG12 + \arg GPIO_PCF4_TLI_R0_PH2_REMAP2: R0 remapped to PH2 + \arg GPIO_PCF4_TLI_R1_PH3_REMAP: TLI R1 remapped to PH3 + \arg GPIO_PCF4_TLI_R2_PH8_REMAP: TLI R2 remapped to PH8 + \arg GPIO_PCF4_TLI_R3_PH9_REMAP: TLI R3 remapped to PH9 + \arg GPIO_PCF4_TLI_R4_PH10_REMAP: TLI R4 remapped to PH10 + \arg GPIO_PCF4_TLI_R5_PH11_REMAP: TLI R5 remapped to PH11 + \arg GPIO_PCF4_TLI_R6_PH12_REMAP: TLI R6 remapped to PH12 + \arg GPIO_PCF4_TLI_G2_PH13_REMAP: TLI G2 remapped to PH13 + \arg GPIO_PCF4_TLI_G3_PH14_REMAP: TLI G3 remapped to PH14 + \arg GPIO_PCF4_TLI_G4_PH15_REMAP: TLI G4 remapped to PH15 + \arg GPIO_PCF4_TLI_G5_PI0_REMAP: TLI G5 remapped to PI0 + \arg GPIO_PCF4_TLI_G6_PI1_REMAP: TLI G6 remapped to PI1 + \arg GPIO_PCF4_TLI_G7_PI2_REMAP: TLI G7 remapped to PI2 + \arg GPIO_PCF4_TLI_B4_PI4_REMAP: TLI B4 remapped to PI4 + \arg GPIO_PCF4_TLI_B5_PI5_REMAP: TLI B5 remapped to PI5 + \arg GPIO_PCF4_TLI_B6_PI6_REMAP: TLI B6 remapped to PI6 + \arg GPIO_PCF4_TLI_B7_PI7_REMAP: TLI B7 remapped to PI7 + \arg GPIO_PCF4_TLI_VSYNC_PI9_REMAP: TLI VSYNC remapped to PI9 + \arg GPIO_PCF4_TLI_HSYNC_PI10_REMAP: TLI HSYNC remapped to PI10 + \arg GPIO_PCF4_TLI_R0_PH4_REMAP: TLI R0 remapped to PH4 + \arg GPIO_PCF4_TLI_R1_PI3_REMAP: TLI R1 remapped to PI3 + \arg GPIO_PCF4_SPI1_SCK_PD3_REMAP: SPI1 SCK remapped to PD3 + \arg GPIO_PCF4_SPI2_MOSI_PD6_REMAP: SPI2 MOSI remapped to PD6 + \arg GPIO_PCF5_I2C2_REMAP0: I2C2 remapping 0 + \arg GPIO_PCF5_I2C2_REMAP1: I2C2 remapping 1 + \arg GPIO_PCF5_TIMER1_CH0_REMAP: TIMER1 CH0 remapped to PA5 + \arg GPIO_PCF5_TIMER4_REMAP: TIMER4 CH0 remapping + \arg GPIO_PCF5_TIMER7_CHON_REMAP0: TIMER7 CHON remapping 0 + \arg GPIO_PCF5_TIMER7_CHON_REMAP1: TIMER7 CHON remapping 1 + \arg GPIO_PCF5_TIMER7_CH_REMAP: TIMER7 CH remapping + \arg GPIO_PCF5_I2C1_REMAP0: I2C1 remapping 0 + \arg GPIO_PCF5_I2C1_REMAP1: I2C1 remapping 1 + \arg GPIO_PCF5_SPI1_NSCK_REMAP0: SPI1 NSS/SCK remapping 0 + \arg GPIO_PCF5_SPI1_NSCK_REMAP1: SPI1 NSS/SCK remapping 1 + \arg GPIO_PCF5_SPI1_IO_REMAP0: SPI1 MISO/MOSI remapping 0 + \arg GPIO_PCF5_SPI1_IO_REMAP1: SPI1 MISO/MOSI remapping 1 + \arg GPIO_PCF5_UART3_REMAP: UART3 remapping + \arg GPIO_PCF5_TIMER11_REMAP: TIMER11 remapping + \arg GPIO_PCF5_CAN0_ADD_REMAP: CAN0 addition remapping + \arg GPIO_PCF5_ENET_TXD3_REMAP: ETH_TXD3 remapped to PE2 + \arg GPIO_PCF5_PPS_HI_REMAP: ETH_PPS_OUT remapped to PG8 + \arg GPIO_PCF5_ENET_TXD01_REMAP: ETH_TX_EN/ETH_TXD0/ETH_TXD1 remapping + \arg GPIO_PCF5_ENET_CRSCOL_REMAP: ETH_MII_CRS/ETH_MII_COL remapping + \arg GPIO_PCF5_ENET_RX_HI_REMAP: ETH_RXD2/ETH_RXD3/ETH_RX_ER remapping + \arg GPIO_PCF5_UART6_REMAP: UART6 remapping + \arg GPIO_PCF5_USART5_CK_PG7_REMAP: USART5 CK remapped to PG7 + \arg GPIO_PCF5_USART5_RTS_PG12_REMAP: USART5 RTS remapped to PG12 + \arg GPIO_PCF5_USART5_CTS_PG13_REMAP: USART5 CTS remapped to PG13 + \arg GPIO_PCF5_USART5_TX_PG14_REMAP: USART5 TX remapped to PG14 + \arg GPIO_PCF5_USART5_RX_PG9_REMAP: USART5 RX remapped to PG9 + \arg GPIO_PCF5_EXMC_SDNWE_PC0_REMAP: EXMC SDNWE remapped to PC0 + \arg GPIO_PCF5_EXMC_SDCKE0_PC3_REMAP: EXMC SDCKE0 remapped to PC3 + \arg GPIO_PCF5_EXMC_SDCKE1_PB5_REMAP: EXMC SDCKE1 remapped to PB5 + \arg GPIO_PCF5_EXMC_SDNE0_PC2_REMAP: EXMC SDNE0 remapped to PC2 + \arg GPIO_PCF5_EXMC_SDNE1_PB6_REMAP: EXMC SDNE1 remapped to PB6 + \param[in] newvalue: ENABLE or DISABLE + \param[out] none + \retval none +*/ +void gpio_pin_remap1_config(uint8_t remap_reg, uint32_t remap, ControlStatus newvalue) +{ + uint32_t reg = 0U; + + if(DISABLE != newvalue){ + /* AFIO port configuration register selection */ + if(GPIO_PCF2 == remap_reg){ + reg = AFIO_PCF2; + reg |= remap; + AFIO_PCF2 = reg; + }else if(GPIO_PCF3 == remap_reg){ + reg = AFIO_PCF3; + reg |= remap; + AFIO_PCF3 = reg; + }else if(GPIO_PCF4 == remap_reg){ + reg = AFIO_PCF4; + reg |= remap; + AFIO_PCF4 = reg; + }else if(GPIO_PCF5 == remap_reg){ + reg = AFIO_PCF5; + reg |= remap; + AFIO_PCF5 = reg; + }else{ + /* illegal parameters */ + } + }else{ + if(GPIO_PCF2 == remap_reg){ + reg = AFIO_PCF2; + reg &= ~remap; + AFIO_PCF2 = reg; + }else if(GPIO_PCF3 == remap_reg){ + reg = AFIO_PCF3; + reg &= ~remap; + AFIO_PCF3 = reg; + }else if(GPIO_PCF4 == remap_reg){ + reg = AFIO_PCF4; + reg &= ~remap; + AFIO_PCF4 = reg; + }else if(GPIO_PCF5 == remap_reg){ + reg = AFIO_PCF5; + reg &= ~remap; + AFIO_PCF5 = reg; + }else{ + /* illegal parameters */ + } + } +} + +/*! + \brief select GPIO pin exti sources + \param[in] output_port: gpio event output port + \arg GPIO_PORT_SOURCE_GPIOA: output port source A + \arg GPIO_PORT_SOURCE_GPIOB: output port source B + \arg GPIO_PORT_SOURCE_GPIOC: output port source C + \arg GPIO_PORT_SOURCE_GPIOD: output port source D + \arg GPIO_PORT_SOURCE_GPIOE: output port source E + \arg GPIO_PORT_SOURCE_GPIOF: output port source F + \arg GPIO_PORT_SOURCE_GPIOG: output port source G + \arg GPIO_PORT_SOURCE_GPIOH: output port source H + \arg GPIO_PORT_SOURCE_GPIOI: output port source I + \param[in] output_pin: GPIO_PIN_SOURCE_x(x=0..15) + \param[out] none + \retval none +*/ +void gpio_exti_source_select(uint8_t output_port, uint8_t output_pin) +{ + uint32_t source = 0U; + source = ((uint32_t)0x0FU) << (AFIO_EXTI_SOURCE_FIELDS * (output_pin & AFIO_EXTI_SOURCE_MASK)); + + /* select EXTI sources */ + if(GPIO_PIN_SOURCE_4 > output_pin){ + /* select EXTI0/EXTI1/EXTI2/EXTI3 */ + AFIO_EXTISS0 &= ~source; + AFIO_EXTISS0 |= (((uint32_t)output_port) << (AFIO_EXTI_SOURCE_FIELDS * (output_pin & AFIO_EXTI_SOURCE_MASK))); + }else if(GPIO_PIN_SOURCE_8 > output_pin){ + /* select EXTI4/EXTI5/EXTI6/EXTI7 */ + AFIO_EXTISS1 &= ~source; + AFIO_EXTISS1 |= (((uint32_t)output_port) << (AFIO_EXTI_SOURCE_FIELDS * (output_pin & AFIO_EXTI_SOURCE_MASK))); + }else if(GPIO_PIN_SOURCE_12 > output_pin){ + /* select EXTI8/EXTI9/EXTI10/EXTI11 */ + AFIO_EXTISS2 &= ~source; + AFIO_EXTISS2 |= (((uint32_t)output_port) << (AFIO_EXTI_SOURCE_FIELDS * (output_pin & AFIO_EXTI_SOURCE_MASK))); + }else{ + /* select EXTI12/EXTI13/EXTI14/EXTI15 */ + AFIO_EXTISS3 &= ~source; + AFIO_EXTISS3 |= (((uint32_t)output_port) << (AFIO_EXTI_SOURCE_FIELDS * (output_pin & AFIO_EXTI_SOURCE_MASK))); + } +} + +/*! + \brief configure GPIO pin event output + \param[in] output_port: gpio event output port + only one parameter can be selected which are shown as below: + \arg GPIO_EVENT_PORT_GPIOA: event output port A + \arg GPIO_EVENT_PORT_GPIOB: event output port B + \arg GPIO_EVENT_PORT_GPIOC: event output port C + \arg GPIO_EVENT_PORT_GPIOD: event output port D + \arg GPIO_EVENT_PORT_GPIOE: event output port E + \param[in] output_pin: + only one parameter can be selected which are shown as below: + \arg GPIO_EVENT_PIN_x(x=0..15) + \param[out] none + \retval none +*/ +void gpio_event_output_config(uint8_t output_port, uint8_t output_pin) +{ + uint32_t reg = 0U; + reg = AFIO_EC; + + /* clear AFIO_EC_PORT and AFIO_EC_PIN bits */ + reg &= (uint32_t)(~(AFIO_EC_PORT|AFIO_EC_PIN)); + + reg |= (uint32_t)((uint32_t)output_port << GPIO_OUTPUT_PORT_OFFSET); + reg |= (uint32_t)output_pin; + + AFIO_EC = reg; +} + +/*! + \brief enable GPIO pin event output + \param[in] none + \param[out] none + \retval none +*/ +void gpio_event_output_enable(void) +{ + AFIO_EC |= AFIO_EC_EOE; +} + +/*! + \brief disable GPIO pin event output + \param[in] none + \param[out] none + \retval none +*/ +void gpio_event_output_disable(void) +{ + AFIO_EC &= (uint32_t)(~AFIO_EC_EOE); +} + +/*! + \brief lock GPIO pin + \param[in] gpio_periph: GPIOx(x = A,B,C,D,E,F,G,H,I) + \param[in] pin: GPIO pin + one or more parameters can be selected which are shown as below: + \arg GPIO_PIN_x(x=0..15), GPIO_PIN_ALL + \param[out] none + \retval none +*/ +void gpio_pin_lock(uint32_t gpio_periph,uint32_t pin) +{ + uint32_t lock = 0x00010000U; + lock |= pin; + + /* lock key writing sequence: write 1 -> write 0 -> write 1 -> read 0 -> read 1 */ + GPIO_LOCK(gpio_periph) = (uint32_t)lock; + GPIO_LOCK(gpio_periph) = (uint32_t)pin; + GPIO_LOCK(gpio_periph) = (uint32_t)lock; + lock = GPIO_LOCK(gpio_periph); + lock = GPIO_LOCK(gpio_periph); +} + +/*! + \brief select ethernet MII or RMII PHY + \param[in] enet_sel: ethernet MII or RMII PHY selection + \arg GPIO_ENET_PHY_MII: configure ethernet MAC for connection with an MII PHY + \arg GPIO_ENET_PHY_RMII: configure ethernet MAC for connection with an RMII PHY + \param[out] none + \retval none +*/ +void gpio_ethernet_phy_select(uint32_t enet_sel) +{ + /* clear AFIO_PCF0_ENET_PHY_SEL bit */ + AFIO_PCF0 &= (uint32_t)(~AFIO_PCF0_ENET_PHY_SEL); + + /* select MII or RMII PHY */ + AFIO_PCF0 |= (uint32_t)enet_sel; +} diff --git a/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_standard_peripheral/Source/gd32f20x_hau.c b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_standard_peripheral/Source/gd32f20x_hau.c new file mode 100644 index 0000000000..429a2382e7 --- /dev/null +++ b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_standard_peripheral/Source/gd32f20x_hau.c @@ -0,0 +1,331 @@ +/*! + \file gd32f20x_cau.c + \brief CAU driver + + \version 2015-07-15, V1.0.0, firmware for GD32F20x + \version 2017-06-05, V2.0.0, firmware for GD32F20x + \version 2018-10-31, V2.1.0, firmware for GD32F20x + \version 2020-09-30, V2.2.0, firmware for GD32F20x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "gd32f20x_hau.h" +#include "gd32f20x_rcu.h" + +/*! + \brief reset the HAU peripheral + \param[in] none + \param[out] none + \retval none +*/ +void hau_deinit(void) +{ + /* enable HAU reset state */ + rcu_periph_reset_enable(RCU_HAURST); + /* release HAU from reset state */ + rcu_periph_reset_disable(RCU_HAURST); +} + +/*! + \brief initialize the HAU peripheral parameters + \param[in] initpara: HAU init parameter struct + members of the structure and the member values are shown as below: + algo: HAU_ALGO_SHA1, HAU_ALGO_SHA224, HAU_ALGO_SHA256, HAU_ALGO_MD5 + mode: HAU_MODE_HASH, HAU_MODE_HMAC + datatype: HAU_SWAPPING_32BIT, HAU_SWAPPING_16BIT, HAU_SWAPPING_8BIT, HAU_SWAPPING_1BIT + keytype: HAU_KEY_SHORTER_64, HAU_KEY_LONGGER_64 + \param[out] none + \retval none +*/ +void hau_init(hau_init_parameter_struct* initpara) +{ + /* configure the algorithm, mode and the data type */ + HAU_CTL &= ~(HAU_CTL_ALGM_0 | HAU_CTL_ALGM_1 | HAU_CTL_DATAM | HAU_CTL_HMS); + HAU_CTL |= (initpara->algo | initpara->datatype | initpara->mode); + + /* when mode is HMAC, set the key */ + if(HAU_MODE_HMAC == initpara->mode){ + HAU_CTL &= ~HAU_CTL_KLM; + HAU_CTL |= initpara->keytype; + } + + /* start the digest of a new message */ + HAU_CTL |= HAU_CTL_START; +} + +/*! + \brief initialize the sturct hau_initpara + \param[in] initpara: HAU init parameter struct + members of the structure and the member values are shown as below: + algo: HAU_ALGO_SHA1, HAU_ALGO_SHA224, HAU_ALGO_SHA256, HAU_ALGO_MD5 + mode: HAU_MODE_HASH, HAU_MODE_HMAC + datatype: HAU_SWAPPING_32BIT, HAU_SWAPPING_16BIT, HAU_SWAPPING_8BIT, HAU_SWAPPING_1BIT + keytype: HAU_KEY_SHORTER_64, HAU_KEY_LONGGER_64 + \param[out] none + \retval none +*/ +void hau_init_parameter_init(hau_init_parameter_struct* initpara) +{ + initpara->algo = HAU_ALGO_SHA1; + initpara->mode = HAU_MODE_HASH; + initpara->datatype = HAU_SWAPPING_32BIT; + initpara->keytype = HAU_KEY_SHORTER_64; +} + +/*! + \brief reset the HAU processor core + \param[in] none + \param[out] none + \retval none +*/ +void hau_reset(void) +{ + /* set to 1 to reset the HAU processor core, then it is ready to start the digest calculation */ + HAU_CTL |= HAU_CTL_START; +} + +/*! + \brief configure the number of valid bits in last word of the message + \param[in] valid_num: number of valid bits in last word of the message + \arg 0x00: all 32 bits of the last data written are valid + \arg 0x01: only bit [31] of the last data written to HAU_DI after data swapping are valid + \arg 0x02: only bits [31:30] of the last data written to HAU_DI after data swapping are valid + \arg 0x03: only bits [31:29] of the last data written to HAU_DI after data swapping are valid + ... + \arg 0x1F: only bit [0] of the last data written to HAU_DI after data swapping are valid + \param[out] none + \retval none +*/ +void hau_last_word_validbits_num_config(uint32_t valid_num) +{ + HAU_CFG &= ~(HAU_CFG_VBL); + HAU_CFG |= CFG_VBL(valid_num); +} + +/*! + \brief write data to the IN FIFO + \param[in] data: data to write + \param[out] none + \retval none +*/ +void hau_data_write(uint32_t data) +{ + HAU_DI = data; +} + +/*! + \brief return the number of words already written into the IN FIFO + \param[in] none + \param[out] none + \retval number of words in the input FIFO +*/ +uint32_t hau_infifo_words_num_get(void) +{ + uint32_t ret = 0U; + ret = GET_CTL_NWIF(HAU_CTL); + return ret; +} + +/*! + \brief read the message digest result + \param[in] none + \param[out] digestpara: HAU digest parameter struct + out[7:0]: message digest result 0-7 + \retval none +*/ +void hau_digest_read(hau_digest_parameter_struct* digestpara) +{ + digestpara->out[0] = HAU_DO0; + digestpara->out[1] = HAU_DO1; + digestpara->out[2] = HAU_DO2; + digestpara->out[3] = HAU_DO3; + digestpara->out[4] = HAU_DO4; + digestpara->out[5] = HAU_DO5; + digestpara->out[6] = HAU_DO6; + digestpara->out[7] = HAU_DO7; +} + +/*! + \brief enable digest calculation + \param[in] none + \param[out] none + \retval none +*/ +void hau_digest_calculation_enable(void) +{ + HAU_CFG |= HAU_CFG_CALEN; +} + +/*! + \brief configure single or multiple DMA is used, and digest calculation at the end of a DMA transfer or not + \param[in] multi_single + only one parameter can be selected which is shown as below + \arg SINGLE_DMA_AUTO_DIGEST: message padding and message digest calculation at the end of a DMA transfer + \arg MULTIPLE_DMA_NO_DIGEST: multiple DMA transfers needed and CALEN bit is not automatically set at the end of a DMA transfer + \param[out] none + \retval none +*/ +void hau_multiple_single_dma_config(uint32_t multi_single) +{ + HAU_CTL &= ~HAU_CTL_MDS; + HAU_CTL |= multi_single; +} + +/*! + \brief enable the HAU DMA interface + \param[in] none + \param[out] none + \retval none +*/ +void hau_dma_enable(void) +{ + HAU_CTL |= HAU_CTL_DMAE; +} + +/*! + \brief disable the HAU DMA interface + \param[in] none + \param[out] none + \retval none +*/ +void hau_dma_disable(void) +{ + HAU_CTL &= ~HAU_CTL_DMAE; +} + +/*! + \brief get the HAU flag status + \param[in] flag: HAU flag status + only one parameter can be selected which is shown as below + \arg HAU_FLAG_DATA_INPUT: there is enough space (16 bytes) in the input FIFO + \arg HAU_FLAG_CALCULATION_COMPLETE: digest calculation is completed + \arg HAU_FLAG_DMA: DMA is enabled (DMAE =1) or a transfer is processing + \arg HAU_FLAG_BUSY: data block is in process + \arg HAU_FLAG_INFIFO_NO_EMPTY: the input FIFO is not empty + \param[out] none + \retval FlagStatus: SET or RESET +*/ +FlagStatus hau_flag_get(uint32_t flag) +{ + uint32_t ret = 0U; + FlagStatus ret_flag = RESET; + + /* check if the flag is in HAU_CTL register */ + if(RESET != (flag & HAU_FLAG_INFIFO_NO_EMPTY)){ + ret = HAU_CTL; + }else{ + ret = HAU_STAT; + } + + if (RESET != (ret & flag)){ + ret_flag = SET; + } + + return ret_flag; +} + +/*! + \brief clear the HAU flag status + \param[in] flag: HAU flag status + one or more parameters can be selected which are shown as below + \arg HAU_FLAG_DATA_INPUT: there is enough space (16 bytes) in the input FIFO + \arg HAU_FLAG_CALCULATION_COMPLETE: digest calculation is completed + \param[out] none + \retval none +*/ +void hau_flag_clear(uint32_t flag) +{ + HAU_STAT = ~(uint32_t)(flag); +} + +/*! + \brief enable the HAU interrupts + \param[in] interrupt: specify the HAU interrupt source to be enabled + one or more parameters can be selected which are shown as below + \arg HAU_INT_DATA_INPUT: a new block can be entered into the IN buffer + \arg HAU_INT_CALCULATION_COMPLETE: calculation complete + \param[out] none + \retval none +*/ +void hau_interrupt_enable(uint32_t interrupt) +{ + HAU_INTEN |= interrupt; +} + +/*! + \brief disable the HAU interrupts + \param[in] interrupt: specify the HAU interrupt source to be disabled + one or more parameters can be selected which are shown as below + \arg HAU_INT_DATA_INPUT: a new block can be entered into the IN buffer + \arg HAU_INT_CALCULATION_COMPLETE: calculation complete + \param[out] none + \retval none +*/ +void hau_interrupt_disable(uint32_t interrupt) +{ + HAU_INTEN &= ~(uint32_t)(interrupt); +} + +/*! + \brief get the HAU interrupt flag status + \param[in] int_flag: HAU interrupt flag status + only one parameter can be selected which is shown as below + \arg HAU_INT_FLAG_DATA_INPUT: there is enough space (16 bytes) in the input FIFO + \arg HAU_INT_FLAG_CALCULATION_COMPLETE: digest calculation is completed + \param[out] none + \retval FlagStatus: SET or RESET +*/ +FlagStatus hau_interrupt_flag_get(uint32_t int_flag) +{ + uint32_t ret = 0U; + FlagStatus flag = RESET; + + /* return the status of the interrupt */ + ret = HAU_STAT; + + if(RESET != ((HAU_INTEN & ret) & int_flag)){ + flag = SET; + } + + return flag; +} + +/*! + \brief clear the HAU interrupt flag status + \param[in] int_flag: HAU interrupt flag status + one or more parameters can be selected which are shown as below + \arg HAU_INT_FLAG_DATA_INPUT: there is enough space (16 bytes) in the input FIFO + \arg HAU_INT_FLAG_CALCULATION_COMPLETE: digest calculation is completed + \param[out] none + \retval none +*/ +void hau_interrupt_flag_clear(uint32_t int_flag) +{ + HAU_STAT = ~(uint32_t)(int_flag); +} diff --git a/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_standard_peripheral/Source/gd32f20x_hau_sha_md5.c b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_standard_peripheral/Source/gd32f20x_hau_sha_md5.c new file mode 100644 index 0000000000..b22cd8f545 --- /dev/null +++ b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_standard_peripheral/Source/gd32f20x_hau_sha_md5.c @@ -0,0 +1,422 @@ +/*! + \file gd32f20x_hau_sha_md5.c + \brief HAU_SHA_MD5 driver + + \version 2015-07-15, V1.0.0, firmware for GD32F20x + \version 2017-06-05, V2.0.0, firmware for GD32F20x + \version 2018-10-31, V2.1.0, firmware for GD32F20x + \version 2020-09-30, V2.2.0, firmware for GD32F20x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "gd32f20x_hau.h" + +#define SHAMD5_BSY_TIMEOUT ((uint32_t)0x00010000U) + +/* HAU SHA/MD5 digest read in HASH mode */ +static void hau_sha_md5_digest_read(uint32_t algo, uint8_t *output); +/* HAU digest calculate process in HASH mode */ +static ErrStatus hau_hash_calculate(uint32_t algo, uint8_t *input, uint32_t in_length, uint8_t *output); +/* HAU digest calculate process in HMAC mode */ +static ErrStatus hau_hmac_calculate(uint32_t algo, uint8_t *key, uint32_t keysize, uint8_t *input, uint32_t in_length, uint8_t *output); + +/*! + \brief calculate digest using SHA1 in HASH mode + \param[in] input: pointer to the input buffer + \param[in] in_length: length of the input buffer + \param[in] output: the result digest + \param[out] none + \retval ErrStatus: SUCCESS or ERROR +*/ +ErrStatus hau_hash_sha_1(uint8_t *input, uint32_t in_length, uint8_t output[20]) +{ + ErrStatus ret = ERROR; + ret = hau_hash_calculate(HAU_ALGO_SHA1, input, in_length, output); + return ret; +} + +/*! + \brief calculate digest using SHA1 in HMAC mode + \param[in] key: pointer to the key used for HMAC + \param[in] keysize: length of the key used for HMAC + \param[in] input: pointer to the input buffer + \param[in] in_length: length of the input buffer + \param[in] output: the result digest + \param[out] none + \retval ErrStatus: SUCCESS or ERROR +*/ +ErrStatus hau_hmac_sha_1(uint8_t *key, uint32_t keysize, uint8_t *input, uint32_t in_length, uint8_t output[20]) +{ + ErrStatus ret = ERROR; + ret = hau_hmac_calculate(HAU_ALGO_SHA1, key, keysize, input, in_length, output); + return ret; +} + +/*! + \brief calculate digest using SHA224 in HASH mode + \param[in] input: pointer to the input buffer + \param[in] in_length: length of the input buffer + \param[in] output: the result digest + \param[out] none + \retval ErrStatus: SUCCESS or ERROR +*/ +ErrStatus hau_hash_sha_224(uint8_t *input, uint32_t in_length, uint8_t output[28]) +{ + ErrStatus ret = ERROR; + ret = hau_hash_calculate(HAU_ALGO_SHA224, input, in_length, output); + return ret; +} + +/*! + \brief calculate digest using SHA224 in HMAC mode + \param[in] key: pointer to the key used for HMAC + \param[in] keysize: length of the key used for HMAC + \param[in] input: pointer to the input buffer + \param[in] in_length: length of the input buffer + \param[in] output: the result digest + \param[out] none + \retval ErrStatus: SUCCESS or ERROR +*/ +ErrStatus hau_hmac_sha_224(uint8_t *key, uint32_t keysize, uint8_t *input, uint32_t in_length, uint8_t output[28]) +{ + ErrStatus ret = ERROR; + ret = hau_hmac_calculate(HAU_ALGO_SHA224, key, keysize, input, in_length, output); + return ret; +} + +/*! + \brief calculate digest using SHA256 in HASH mode + \param[in] input: pointer to the input buffer + \param[in] in_length: length of the input buffer + \param[in] output: the result digest + \param[out] none + \retval ErrStatus: SUCCESS or ERROR +*/ +ErrStatus hau_hash_sha_256(uint8_t *input, uint32_t in_length, uint8_t output[32]) +{ + ErrStatus ret = ERROR; + ret = hau_hash_calculate(HAU_ALGO_SHA256, input, in_length, output); + return ret; +} + +/*! + \brief calculate digest using SHA256 in HMAC mode + \param[in] key: pointer to the key used for HMAC + \param[in] keysize: length of the key used for HMAC + \param[in] input: pointer to the input buffer + \param[in] in_length: length of the input buffer + \param[in] output: the result digest + \param[out] none + \retval ErrStatus: SUCCESS or ERROR +*/ +ErrStatus hau_hmac_sha_256(uint8_t *key, uint32_t keysize, uint8_t *input, uint32_t in_length, uint8_t output[32]) +{ + ErrStatus ret = ERROR; + ret = hau_hmac_calculate(HAU_ALGO_SHA256, key, keysize, input, in_length, output); + return ret; +} + +/*! + \brief calculate digest using MD5 in HASH mode + \param[in] input: pointer to the input buffer + \param[in] in_length: length of the input buffer + \param[in] output: the result digest + \param[out] none + \retval ErrStatus: SUCCESS or ERROR +*/ +ErrStatus hau_hash_md5(uint8_t *input, uint32_t in_length, uint8_t output[16]) +{ + ErrStatus ret = ERROR; + ret = hau_hash_calculate(HAU_ALGO_MD5, input, in_length, output); + return ret; +} + +/*! + \brief calculate digest using MD5 in HMAC mode + \param[in] key: pointer to the key used for HMAC + \param[in] keysize: length of the key used for HMAC + \param[in] input: pointer to the input buffer + \param[in] in_length: length of the input buffer + \param[in] output: the result digest + \param[out] none + \retval ErrStatus: SUCCESS or ERROR +*/ +ErrStatus hau_hmac_md5(uint8_t *key, uint32_t keysize, uint8_t *input, uint32_t in_length, uint8_t output[16]) +{ + ErrStatus ret = ERROR; + ret = hau_hmac_calculate(HAU_ALGO_MD5, key, keysize, input, in_length, output); + return ret; +} + +/*! + \brief HAU SHA/MD5 digest read + \param[in] algo: algorithm selection + \param[out] output: the result digest + \retval none +*/ +static void hau_sha_md5_digest_read(uint32_t algo, uint8_t *output) +{ + hau_digest_parameter_struct digest_para; + uint32_t outputaddr = (uint32_t)output; + + switch(algo){ + case HAU_ALGO_SHA1: + hau_digest_read(&digest_para); + *(uint32_t*)(outputaddr) = __REV(digest_para.out[0]); + outputaddr += 4U; + *(uint32_t*)(outputaddr) = __REV(digest_para.out[1]); + outputaddr += 4U; + *(uint32_t*)(outputaddr) = __REV(digest_para.out[2]); + outputaddr += 4U; + *(uint32_t*)(outputaddr) = __REV(digest_para.out[3]); + outputaddr += 4U; + *(uint32_t*)(outputaddr) = __REV(digest_para.out[4]); + break; + case HAU_ALGO_SHA224: + hau_digest_read(&digest_para); + *(uint32_t*)(outputaddr) = __REV(digest_para.out[0]); + outputaddr += 4U; + *(uint32_t*)(outputaddr) = __REV(digest_para.out[1]); + outputaddr += 4U; + *(uint32_t*)(outputaddr) = __REV(digest_para.out[2]); + outputaddr += 4U; + *(uint32_t*)(outputaddr) = __REV(digest_para.out[3]); + outputaddr += 4U; + *(uint32_t*)(outputaddr) = __REV(digest_para.out[4]); + outputaddr += 4U; + *(uint32_t*)(outputaddr) = __REV(digest_para.out[5]); + outputaddr += 4U; + *(uint32_t*)(outputaddr) = __REV(digest_para.out[6]); + break; + case HAU_ALGO_SHA256: + hau_digest_read(&digest_para); + *(uint32_t*)(outputaddr) = __REV(digest_para.out[0]); + outputaddr += 4U; + *(uint32_t*)(outputaddr) = __REV(digest_para.out[1]); + outputaddr += 4U; + *(uint32_t*)(outputaddr) = __REV(digest_para.out[2]); + outputaddr += 4U; + *(uint32_t*)(outputaddr) = __REV(digest_para.out[3]); + outputaddr += 4U; + *(uint32_t*)(outputaddr) = __REV(digest_para.out[4]); + outputaddr += 4U; + *(uint32_t*)(outputaddr) = __REV(digest_para.out[5]); + outputaddr += 4U; + *(uint32_t*)(outputaddr) = __REV(digest_para.out[6]); + outputaddr += 4U; + *(uint32_t*)(outputaddr) = __REV(digest_para.out[7]); + break; + case HAU_ALGO_MD5: + hau_digest_read(&digest_para); + *(uint32_t*)(outputaddr) = __REV(digest_para.out[0]); + outputaddr += 4U; + *(uint32_t*)(outputaddr) = __REV(digest_para.out[1]); + outputaddr += 4U; + *(uint32_t*)(outputaddr) = __REV(digest_para.out[2]); + outputaddr += 4U; + *(uint32_t*)(outputaddr) = __REV(digest_para.out[3]); + break; + default: + break; + } +} + +/*! + \brief HAU digest calculate process in HASH mode + \param[in] algo: algorithm selection + \param[in] input: pointer to the input buffer + \param[in] in_length: length of the input buffer + \param[in] output: the result digest + \param[out] none + \retval ErrStatus: SUCCESS or ERROR +*/ +static ErrStatus hau_hash_calculate(uint32_t algo, uint8_t *input, uint32_t in_length, uint8_t *output) +{ + hau_init_parameter_struct init_para; + + __IO uint32_t num_last_valid = 0U; + uint32_t i = 0U; + __IO uint32_t counter = 0U; + uint32_t busystatus = 0U; + uint32_t inputaddr = (uint32_t)input; + + /* number of valid bits in last word */ + num_last_valid = 8U * (in_length % 4U); + + /* HAU peripheral initialization */ + hau_deinit(); + + /* HAU configuration */ + init_para.algo = algo; + init_para.mode = HAU_MODE_HASH; + init_para.datatype = HAU_SWAPPING_8BIT; + hau_init(&init_para); + + /* configure the number of valid bits in last word of the message */ + hau_last_word_validbits_num_config(num_last_valid); + + /* write data to the IN FIFO */ + for(i = 0U; i < in_length; i += 4U){ + hau_data_write(*(uint32_t*)inputaddr); + inputaddr += 4U; + } + + /* enable digest calculation */ + hau_digest_calculation_enable(); + + /* wait until the busy flag is reset */ + do{ + busystatus = hau_flag_get(HAU_FLAG_BUSY); + counter++; + }while((SHAMD5_BSY_TIMEOUT != counter) && (RESET != busystatus)); + + if(RESET != busystatus){ + return ERROR; + }else{ + /* read the message digest */ + hau_sha_md5_digest_read(algo, output); + } + return SUCCESS; +} + +/*! + \brief HAU digest calculate process in HMAC mode + \param[in] algo: algorithm selection + \param[in] key: pointer to the key used for HMAC + \param[in] keysize: length of the key used for HMAC + \param[in] input: pointer to the input buffer + \param[in] in_length: length of the input buffer + \param[in] output: the result digest + \param[out] none + \retval ErrStatus: SUCCESS or ERROR +*/ +static ErrStatus hau_hmac_calculate(uint32_t algo, uint8_t *key, uint32_t keysize, uint8_t *input, uint32_t in_length, uint8_t *output) +{ + hau_init_parameter_struct init_para; + + __IO uint16_t num_last_valid = 0U; + __IO uint16_t num_key_valid = 0U; + uint32_t i = 0U; + __IO uint32_t counter = 0U; + uint32_t busystatus = 0U; + uint32_t keyaddr = (uint32_t)key; + uint32_t inputaddr = (uint32_t)input; + + /* number of valid bits in last word of the message */ + num_last_valid = 8U * (uint16_t)(in_length % 4U); + /* number of valid bits in last word of the key */ + num_key_valid = 8U * (uint16_t)(keysize % 4U); + + /* HAU peripheral initialization */ + hau_deinit(); + + /* HAU configuration */ + init_para.algo = algo; + init_para.mode = HAU_MODE_HMAC; + init_para.datatype = HAU_SWAPPING_8BIT; + if(keysize > 64U){ + init_para.keytype = HAU_KEY_LONGGER_64; + }else{ + init_para.keytype = HAU_KEY_SHORTER_64; + } + hau_init(&init_para); + + /* configure the number of valid bits in last word of the key */ + hau_last_word_validbits_num_config((uint32_t)num_key_valid); + + /* write the key */ + for(i = 0U; i < keysize; i += 4U){ + hau_data_write(*(uint32_t*)keyaddr); + keyaddr += 4U; + } + + /* enable digest calculation */ + hau_digest_calculation_enable(); + + /* wait until the busy flag is reset */ + do{ + busystatus = hau_flag_get(HAU_FLAG_BUSY); + counter++; + }while((SHAMD5_BSY_TIMEOUT != counter) && (RESET != busystatus)); + + if(RESET != busystatus){ + return ERROR; + }else{ + /* configure the number of valid bits in last word of the message */ + hau_last_word_validbits_num_config((uint32_t)num_last_valid); + + /* write data to the IN FIFO */ + for(i = 0U; i < in_length; i += 4U){ + hau_data_write(*(uint32_t*)inputaddr); + inputaddr += 4U; + } + + /* enable digest calculation */ + hau_digest_calculation_enable(); + + /* wait until the busy flag is reset */ + counter = 0U; + do{ + busystatus = hau_flag_get(HAU_FLAG_BUSY); + counter++; + }while((SHAMD5_BSY_TIMEOUT != counter) && (RESET != busystatus)); + + if(RESET != busystatus){ + return ERROR; + }else{ + /* configure the number of valid bits in last word of the key */ + hau_last_word_validbits_num_config((uint32_t)num_key_valid); + + /* write the key */ + keyaddr = (uint32_t)key; + for(i = 0U; i < keysize; i += 4U){ + hau_data_write(*(uint32_t*)keyaddr); + keyaddr += 4U; + } + + /* enable digest calculation */ + hau_digest_calculation_enable(); + + /* wait until the busy flag is reset */ + counter =0U; + do{ + busystatus = hau_flag_get(HAU_FLAG_BUSY); + counter++; + }while((SHAMD5_BSY_TIMEOUT != counter) && (RESET != busystatus)); + + if(RESET != busystatus){ + return ERROR; + }else{ + /* read the message digest */ + hau_sha_md5_digest_read(algo, output); + } + } + } + return SUCCESS; +} diff --git a/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_standard_peripheral/Source/gd32f20x_i2c.c b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_standard_peripheral/Source/gd32f20x_i2c.c new file mode 100644 index 0000000000..fe5af0c6fd --- /dev/null +++ b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_standard_peripheral/Source/gd32f20x_i2c.c @@ -0,0 +1,720 @@ +/*! + \file gd32f20x_i2c.c + \brief I2C driver + + \version 2015-07-15, V1.0.0, firmware for GD32F20x + \version 2017-06-05, V2.0.0, firmware for GD32F20x + \version 2018-10-31, V2.1.0, firmware for GD32F20x + \version 2020-09-30, V2.2.0, firmware for GD32F20x + \version 2019-04-16, V2.1.1, firmware for GD32F20x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "gd32f20x_i2c.h" + +/* I2C register bit mask */ +#define I2CCLK_MAX ((uint32_t)0x0000003FU) /*!< i2cclk maximum value */ +#define I2CCLK_MIN ((uint32_t)0x00000002U) /*!< i2cclk minimum value */ +#define I2C_FLAG_MASK ((uint32_t)0x0000FFFFU) /*!< i2c flag mask */ +#define I2C_ADDRESS_MASK ((uint32_t)0x000003FFU) /*!< i2c address mask */ +#define I2C_ADDRESS2_MASK ((uint32_t)0x000000FEU) /*!< the second i2c address mask */ + +/* I2C register bit offset */ +#define STAT1_PECV_OFFSET ((uint32_t)8U) /* bit offset of PECV in I2C_STAT1 */ + +/*! + \brief reset I2C + \param[in] i2c_periph: I2Cx(x=0,1,2) + \param[out] none + \retval none +*/ +void i2c_deinit(uint32_t i2c_periph) +{ + switch(i2c_periph){ + case I2C0: + /* reset I2C0 */ + rcu_periph_reset_enable(RCU_I2C0RST); + rcu_periph_reset_disable(RCU_I2C0RST); + break; + case I2C1: + /* reset I2C1 */ + rcu_periph_reset_enable(RCU_I2C1RST); + rcu_periph_reset_disable(RCU_I2C1RST); + break; + case I2C2: + /* reset I2C2 */ + rcu_periph_reset_enable(RCU_I2C2RST); + rcu_periph_reset_disable(RCU_I2C2RST); + break; + default: + break; + + } +} + +/*! + \brief configure I2C clock + \param[in] i2c_periph: I2Cx(x=0,1,2) + \param[in] clkspeed: I2C clock speed, supports standard mode (up to 100 kHz), fast mode (up to 400 kHz) + and fast mode plus (up to 1MHz) + \param[in] dutycyc: duty cycle in fast mode or fast mode plus + only one parameter can be selected which is shown as below: + \arg I2C_DTCY_2: T_low/T_high=2 + \arg I2C_DTCY_16_9: T_low/T_high=16/9 + \param[out] none + \retval none +*/ +void i2c_clock_config(uint32_t i2c_periph,uint32_t clkspeed,uint32_t dutycyc) +{ + uint32_t pclk1,clkc,freq,risetime; + uint32_t temp; + + pclk1 = rcu_clock_freq_get(CK_APB1); + /* I2C peripheral clock frequency */ + freq = (uint32_t)(pclk1/1000000U); + if(freq >= I2CCLK_MAX){ + freq = I2CCLK_MAX; + } + temp = I2C_CTL1(i2c_periph); + temp &= ~I2C_CTL1_I2CCLK; + temp |= freq; + + I2C_CTL1(i2c_periph) = temp; + + if(100000U >= clkspeed){ + /* the maximum SCL rise time is 1000ns in standard mode */ + risetime = (uint32_t)((pclk1/1000000U)+1U); + if(risetime >= I2CCLK_MAX){ + I2C_RT(i2c_periph) = I2CCLK_MAX; + }else if(risetime <= I2CCLK_MIN){ + I2C_RT(i2c_periph) = I2CCLK_MIN; + }else{ + I2C_RT(i2c_periph) = risetime; + } + clkc = (uint32_t)(pclk1/(clkspeed*2U)); + if(clkc < 0x04U){ + /* the CLKC in standard mode minmum value is 4 */ + clkc = 0x04U; + } + I2C_CKCFG(i2c_periph) |= (I2C_CKCFG_CLKC & clkc); + + }else if(400000U >= clkspeed){ + /* the maximum SCL rise time is 300ns in fast mode */ + I2C_RT(i2c_periph) = (uint32_t)(((freq*(uint32_t)300U)/(uint32_t)1000U)+(uint32_t)1U); + if(I2C_DTCY_2 == dutycyc){ + /* I2C duty cycle is 2 */ + clkc = (uint32_t)(pclk1/(clkspeed*3U)); + I2C_CKCFG(i2c_periph) &= ~I2C_CKCFG_DTCY; + }else{ + /* I2C duty cycle is 16/9 */ + clkc = (uint32_t)(pclk1/(clkspeed*25U)); + I2C_CKCFG(i2c_periph) |= I2C_CKCFG_DTCY; + } + if(0U == (clkc & I2C_CKCFG_CLKC)){ + /* the CLKC in fast mode minmum value is 1 */ + clkc |= 0x0001U; + } + I2C_CKCFG(i2c_periph) |= I2C_CKCFG_FAST; + I2C_CKCFG(i2c_periph) |= clkc; + }else{ + } +} + +/*! + \brief configure I2C address + \param[in] i2c_periph: I2Cx(x=0,1,2) + \param[in] mod: + only one parameter can be selected which is shown as below: + \arg I2C_I2CMODE_ENABLE: I2C mode + \arg I2C_SMBUSMODE_ENABLE: SMBus mode + \param[in] addformat: 7bits or 10bits + only one parameter can be selected which is shown as below: + \arg I2C_ADDFORMAT_7BITS: 7bits + \arg I2C_ADDFORMAT_10BITS: 10bits + \param[in] addr: I2C address + \param[out] none + \retval none +*/ +void i2c_mode_addr_config(uint32_t i2c_periph,uint32_t mode,uint32_t addformat,uint32_t addr) +{ + /* SMBus/I2C mode selected */ + uint32_t ctl = 0U; + + ctl = I2C_CTL0(i2c_periph); + ctl &= ~(I2C_CTL0_SMBEN); + ctl |= mode; + I2C_CTL0(i2c_periph) = ctl; + /* configure address */ + addr = addr & I2C_ADDRESS_MASK; + I2C_SADDR0(i2c_periph) = (addformat | addr); +} + +/*! + \brief SMBus type selection + \param[in] i2c_periph: I2Cx(x=0,1,2) + \param[in] type: + only one parameter can be selected which is shown as below: + \arg I2C_SMBUS_DEVICE: device + \arg I2C_SMBUS_HOST: host + \param[out] none + \retval none +*/ +void i2c_smbus_type_config(uint32_t i2c_periph, uint32_t type) +{ + if(I2C_SMBUS_HOST == type){ + I2C_CTL0(i2c_periph) |= I2C_CTL0_SMBSEL; + }else{ + I2C_CTL0(i2c_periph) &= ~(I2C_CTL0_SMBSEL); + } +} + +/*! + \brief whether or not to send an ACK + \param[in] i2c_periph: I2Cx(x=0,1,2) + \param[in] ack: + only one parameter can be selected which is shown as below: + \arg I2C_ACK_ENABLE: ACK will be sent + \arg I2C_ACK_DISABLE: ACK will not be sent + \param[out] none + \retval none +*/ +void i2c_ack_config(uint32_t i2c_periph, uint32_t ack) +{ + if(I2C_ACK_ENABLE == ack){ + I2C_CTL0(i2c_periph) |= I2C_CTL0_ACKEN; + }else{ + I2C_CTL0(i2c_periph) &= ~(I2C_CTL0_ACKEN); + } +} + +/*! + \brief configure I2C POAP position + \param[in] i2c_periph: I2Cx(x=0,1,2) + \param[in] pos: + only one parameter can be selected which is shown as below: + \arg I2C_ACKPOS_CURRENT: whether to send ACK or not for the current + \arg I2C_ACKPOS_NEXT: whether to send ACK or not for the next byte + \param[out] none + \retval none +*/ +void i2c_ackpos_config(uint32_t i2c_periph, uint32_t pos) +{ + /* configure I2C POAP position */ + if(I2C_ACKPOS_NEXT == pos){ + I2C_CTL0(i2c_periph) |= I2C_CTL0_POAP; + }else{ + I2C_CTL0(i2c_periph) &= ~(I2C_CTL0_POAP); + } +} + +/*! + \brief master sends slave address + \param[in] i2c_periph: I2Cx(x=0,1,2) + \param[in] addr: slave address + \param[in] trandirection: transmitter or receiver + only one parameter can be selected which is shown as below: + \arg I2C_TRANSMITTER: transmitter + \arg I2C_RECEIVER: receiver + \param[out] none + \retval none +*/ +void i2c_master_addressing(uint32_t i2c_periph, uint32_t addr, uint32_t trandirection) +{ + /* master is a transmitter or a receiver */ + if(I2C_TRANSMITTER == trandirection){ + addr = addr & I2C_TRANSMITTER; + }else{ + addr = addr | I2C_RECEIVER; + } + /* send slave address */ + I2C_DATA(i2c_periph) = addr; +} + +/*! + \brief enable dual-address mode + \param[in] i2c_periph: I2Cx(x=0,1,2) + \param[in] addr: the second address in dual-address mode + \param[out] none + \retval none +*/ +void i2c_dualaddr_enable(uint32_t i2c_periph, uint32_t addr) +{ + /* configure address */ + addr = addr & I2C_ADDRESS2_MASK; + I2C_SADDR1(i2c_periph) = (I2C_SADDR1_DUADEN | addr); +} + +/*! + \brief disable dual-address mode + \param[in] i2c_periph: I2Cx(x=0,1,2) + \param[out] none + \retval none +*/ +void i2c_dualaddr_disable(uint32_t i2c_periph) +{ + I2C_SADDR1(i2c_periph) &= ~(I2C_SADDR1_DUADEN); +} + +/*! + \brief enable I2C + \param[in] i2c_periph: I2Cx(x=0,1) + \param[out] none + \retval none +*/ +void i2c_enable(uint32_t i2c_periph) +{ + I2C_CTL0(i2c_periph) |= I2C_CTL0_I2CEN; +} + +/*! + \brief disable I2C + \param[in] i2c_periph: I2Cx(x=0,1) + \param[out] none + \retval none +*/ +void i2c_disable(uint32_t i2c_periph) +{ + I2C_CTL0(i2c_periph) &= ~(I2C_CTL0_I2CEN); +} + +/*! + \brief generate a START condition on I2C bus + \param[in] i2c_periph: I2Cx(x=0,1,2) + \param[out] none + \retval none +*/ +void i2c_start_on_bus(uint32_t i2c_periph) +{ + I2C_CTL0(i2c_periph) |= I2C_CTL0_START; +} + +/*! + \brief generate a STOP condition on I2C bus + \param[in] i2c_periph: I2Cx(x=0,1,2) + \param[out] none + \retval none +*/ +void i2c_stop_on_bus(uint32_t i2c_periph) +{ + I2C_CTL0(i2c_periph) |= I2C_CTL0_STOP; +} + +/*! + \brief I2C transmit data function + \param[in] i2c_periph: I2Cx(x=0,1,2) + \param[in] data: data of transmission + \param[out] none + \retval none +*/ +void i2c_data_transmit(uint32_t i2c_periph, uint8_t data) +{ + I2C_DATA(i2c_periph) = DATA_TRANS(data); +} + +/*! + \brief I2C receive data function + \param[in] i2c_periph: I2Cx(x=0,1,2) + \param[out] none + \retval data of received +*/ +uint8_t i2c_data_receive(uint32_t i2c_periph) +{ + return (uint8_t)DATA_RECV(I2C_DATA(i2c_periph)); +} + +/*! + \brief enable I2C DMA mode + \param[in] i2c_periph: I2Cx(x=0,1,2) + \param[in] dmastate: + only one parameter can be selected which is shown as below: + \arg I2C_DMA_ON: DMA mode enable + \arg I2C_DMA_OFF: DMA mode disable + \param[out] none + \retval none +*/ +void i2c_dma_enable(uint32_t i2c_periph, uint32_t dmastate) +{ + /* configure I2C DMA function */ + uint32_t ctl = 0U; + + ctl = I2C_CTL1(i2c_periph); + ctl &= ~(I2C_CTL1_DMAON); + ctl |= dmastate; + I2C_CTL1(i2c_periph) = ctl; +} + +/*! + \brief configure whether next DMA EOT is DMA last transfer or not + \param[in] i2c_periph: I2Cx(x=0,1,2) + \param[in] dmalast: + only one parameter can be selected which is shown as below: + \arg I2C_DMALST_ON: next DMA EOT is the last transfer + \arg I2C_DMALST_OFF: next DMA EOT is not the last transfer + \param[out] none + \retval none +*/ +void i2c_dma_last_transfer_config(uint32_t i2c_periph, uint32_t dmalast) +{ + /* configure DMA last transfer */ + uint32_t ctl = 0U; + + ctl = I2C_CTL1(i2c_periph); + ctl &= ~(I2C_CTL1_DMALST); + ctl |= dmalast; + I2C_CTL1(i2c_periph) = ctl; +} + +/*! + \brief whether to stretch SCL low when data is not ready in slave mode + \param[in] i2c_periph: I2Cx(x=0,1,2) + \param[in] stretchpara: + only one parameter can be selected which is shown as below: + \arg I2C_SCLSTRETCH_ENABLE: SCL stretching is enabled + \arg I2C_SCLSTRETCH_DISABLE: SCL stretching is disabled + \param[out] none + \retval none +*/ +void i2c_stretch_scl_low_config(uint32_t i2c_periph, uint32_t stretchpara) +{ + /* configure I2C SCL strerching enable or disable */ + uint32_t ctl = 0U; + + ctl = I2C_CTL0(i2c_periph); + ctl &= ~(I2C_CTL0_DISSTRC); + ctl |= stretchpara; + I2C_CTL0(i2c_periph) = ctl; +} + +/*! + \brief whether or not to response to a general call + \param[in] i2c_periph: I2Cx(x=0,1,2) + \param[in] gcallpara: + only one parameter can be selected which is shown as below: + \arg I2C_GCEN_ENABLE: slave will response to a general call + \arg I2C_GCEN_DISABLE: slave will not response to a general call + \param[out] none + \retval none +*/ +void i2c_slave_response_to_gcall_config(uint32_t i2c_periph, uint32_t gcallpara) +{ + /* configure slave response to a general call enable or disable */ + uint32_t ctl = 0U; + + ctl = I2C_CTL0(i2c_periph); + ctl &= ~(I2C_CTL0_GCEN); + ctl |= gcallpara; + I2C_CTL0(i2c_periph) = ctl; +} + +/*! + \brief software reset I2C + \param[in] i2c_periph: I2Cx(x=0,1,2) + \param[in] sreset: + only one parameter can be selected which is shown as below: + \arg I2C_SRESET_SET: I2C is under reset + \arg I2C_SRESET_RESET: I2C is not under reset + \param[out] none + \retval none +*/ +void i2c_software_reset_config(uint32_t i2c_periph, uint32_t sreset) +{ + /* modify CTL0 and configure software reset I2C state */ + uint32_t ctl = 0U; + + ctl = I2C_CTL0(i2c_periph); + ctl &= ~(I2C_CTL0_SRESET); + ctl |= sreset; + I2C_CTL0(i2c_periph) = ctl; +} + +/*! + \brief I2C PEC calculation on or off + \param[in] i2c_periph: I2Cx(x=0,1,2) + \param[in] pecpara: + only one parameter can be selected which is shown as below: + \arg I2C_PEC_ENABLE: PEC calculation on + \arg I2C_PEC_DISABLE: PEC calculation off + \param[out] none + \retval none +*/ +void i2c_pec_enable(uint32_t i2c_periph,uint32_t pecstate) +{ + /* on/off PEC calculation */ + uint32_t ctl = 0U; + + ctl = I2C_CTL0(i2c_periph); + ctl &= ~(I2C_CTL0_PECEN); + ctl |= pecstate; + I2C_CTL0(i2c_periph) = ctl; +} + +/*! + \brief I2C whether to transfer PEC value + \param[in] i2c_periph: I2Cx(x=0,1,2) + \param[in] pecpara: + only one parameter can be selected which is shown as below: + \arg I2C_PECTRANS_ENABLE: transfer PEC + \arg I2C_PECTRANS_DISABLE: not transfer PEC + \param[out] none + \retval none +*/ +void i2c_pec_transfer_enable(uint32_t i2c_periph,uint32_t pecpara) +{ + /* whether to transfer PEC */ + uint32_t ctl = 0U; + ctl = I2C_CTL0(i2c_periph); + ctl &= ~(I2C_CTL0_PECTRANS); + ctl |= pecpara; + I2C_CTL0(i2c_periph) = ctl; +} + +/*! + \brief get packet error checking value + \param[in] i2c_periph: I2Cx(x=0,1,2) + \param[out] none + \retval PEC value +*/ +uint8_t i2c_pec_value_get(uint32_t i2c_periph) +{ + return (uint8_t)((I2C_STAT1(i2c_periph) &I2C_STAT1_ECV) >> STAT1_PECV_OFFSET); +} + +/*! + \brief I2C issue alert through SMBA pin + \param[in] i2c_periph: I2Cx(x=0,1,2) + \param[in] smbuspara: + only one parameter can be selected which is shown as below: + \arg I2C_SALTSEND_ENABLE: issue alert through SMBA pin + \arg I2C_SALTSEND_DISABLE: not issue alert through SMBA pin + \param[out] none + \retval none +*/ +void i2c_smbus_issue_alert(uint32_t i2c_periph, uint32_t smbuspara) +{ + /* issue alert through SMBA pin configure*/ + uint32_t ctl = 0U; + + ctl = I2C_CTL0(i2c_periph); + ctl &= ~(I2C_CTL0_SALT); + ctl |= smbuspara; + I2C_CTL0(i2c_periph) = ctl; +} + +/*! + \brief enable or disable I2C ARP protocol in SMBus switch + \param[in] i2c_periph: I2Cx(x=0,1,2) + \param[in] arpstate: + only one parameter can be selected which is shown as below: + \arg I2C_ARP_ENABLE: enable ARP + \arg I2C_ARP_DISABLE: disable ARP + \param[out] none + \retval none +*/ +void i2c_smbus_arp_enable(uint32_t i2c_periph,uint32_t arpstate) +{ + /* enable or disable I2C ARP protocol*/ + uint32_t ctl = 0U; + + ctl = I2C_CTL0(i2c_periph); + ctl &= ~(I2C_CTL0_ARPEN); + ctl |= arpstate; + I2C_CTL0(i2c_periph) = ctl; +} + +/*! + \brief check I2C flag is set or not + \param[in] i2c_periph: I2Cx(x=0,1,2) + \param[in] flag: I2C flags, refer to i2c_flag_enum + only one parameter can be selected which is shown as below: + \arg I2C_FLAG_SBSEND: start condition send out + \arg I2C_FLAG_ADDSEND: address is sent in master mode or received and matches in slave mode + \arg I2C_FLAG_BTC: byte transmission finishes + \arg I2C_FLAG_ADD10SEND: header of 10-bit address is sent in master mode + \arg I2C_FLAG_STPDET: stop condition detected in slave mode + \arg I2C_FLAG_RBNE: I2C_DATA is not Empty during receiving + \arg I2C_FLAG_TBE: I2C_DATA is empty during transmitting + \arg I2C_FLAG_BERR: a bus error occurs indication a unexpected start or stop condition on I2C bus + \arg I2C_FLAG_LOSTARB: arbitration lost in master mode + \arg I2C_FLAG_AERR: acknowledge error + \arg I2C_FLAG_OUERR: overrun or underrun situation occurs in slave mode + \arg I2C_FLAG_PECERR: PEC error when receiving data + \arg I2C_FLAG_SMBTO: timeout signal in SMBus mode + \arg I2C_FLAG_SMBALT: SMBus alert status + \arg I2C_FLAG_MASTER: a flag indicating whether I2C block is in master or slave mode + \arg I2C_FLAG_I2CBSY: busy flag + \arg I2C_FLAG_TRS: whether the I2C is a transmitter or a receiver + \arg I2C_FLAG_RXGC: general call address (00h) received + \arg I2C_FLAG_DEFSMB: default address of SMBus device + \arg I2C_FLAG_HSTSMB: SMBus host header detected in slave mode + \arg I2C_FLAG_DUMOD: dual flag in slave mode indicating which address is matched in dual-address mode + \param[out] none + \retval FlagStatus: SET or RESET +*/ +FlagStatus i2c_flag_get(uint32_t i2c_periph, i2c_flag_enum flag) +{ + if(RESET != (I2C_REG_VAL(i2c_periph, flag) & BIT(I2C_BIT_POS(flag)))){ + return SET; + }else{ + return RESET; + } +} + +/*! + \brief clear I2C flag + \param[in] i2c_periph: I2Cx(x=0,1,2) + \param[in] flag: I2C flags, refer to i2c_flag_enum + only one parameter can be selected which is shown as below: + \arg I2C_FLAG_SMBALT: SMBus Alert status + \arg I2C_FLAG_SMBTO: timeout signal in SMBus mode + \arg I2C_FLAG_PECERR: PEC error when receiving data + \arg I2C_FLAG_OUERR: over-run or under-run situation occurs in slave mode + \arg I2C_FLAG_AERR: acknowledge error + \arg I2C_FLAG_LOSTARB: arbitration lost in master mode + \arg I2C_FLAG_BERR: a bus error + \arg I2C_FLAG_ADDSEND: cleared by reading I2C_STAT0 and reading I2C_STAT1 + \param[out] none + \retval none +*/ +void i2c_flag_clear(uint32_t i2c_periph, i2c_flag_enum flag) +{ + if(I2C_FLAG_ADDSEND == flag){ + /* read I2C_STAT0 and then read I2C_STAT1 to clear ADDSEND */ + I2C_STAT0(i2c_periph); + I2C_STAT1(i2c_periph); + }else{ + I2C_REG_VAL(i2c_periph, flag) &= ~BIT(I2C_BIT_POS(flag)); + } +} + +/*! + \brief enable I2C interrupt + \param[in] i2c_periph: I2Cx(x=0,1,2) + \param[in] interrupt: I2C interrupts, refer to i2c_interrupt_enum + only one parameter can be selected which is shown as below: + \arg I2C_INT_ERR: error interrupt enable + \arg I2C_INT_EV: event interrupt enable + \arg I2C_INT_BUF: buffer interrupt enable + \param[out] none + \retval none +*/ +void i2c_interrupt_enable(uint32_t i2c_periph, i2c_interrupt_enum interrupt) +{ + I2C_REG_VAL(i2c_periph, interrupt) |= BIT(I2C_BIT_POS(interrupt)); +} + +/*! + \brief disable I2C interrupt + \param[in] i2c_periph: I2Cx(x=0,1,2) + \param[in] interrupt: I2C interrupts, refer to i2c_flag_enum + only one parameter can be selected which is shown as below: + \arg I2C_INT_ERR: error interrupt enable + \arg I2C_INT_EV: event interrupt enable + \arg I2C_INT_BUF: buffer interrupt enable + \param[out] none + \retval none +*/ +void i2c_interrupt_disable(uint32_t i2c_periph, i2c_interrupt_enum interrupt) +{ + I2C_REG_VAL(i2c_periph, interrupt) &= ~BIT(I2C_BIT_POS(interrupt)); +} + +/*! + \brief check I2C interrupt flag + \param[in] i2c_periph: I2Cx(x=0,1,2) + \param[in] int_flag: I2C interrupt flags, refer to i2c_interrupt_flag_enum + only one parameter can be selected which is shown as below: + \arg I2C_INT_FLAG_SBSEND: start condition sent out in master mode interrupt flag + \arg I2C_INT_FLAG_ADDSEND: address is sent in master mode or received and matches in slave mode interrupt flag + \arg I2C_INT_FLAG_BTC: byte transmission finishes + \arg I2C_INT_FLAG_ADD10SEND: header of 10-bit address is sent in master mode interrupt flag + \arg I2C_INT_FLAG_STPDET: etop condition detected in slave mode interrupt flag + \arg I2C_INT_FLAG_RBNE: I2C_DATA is not Empty during receiving interrupt flag + \arg I2C_INT_FLAG_TBE: I2C_DATA is empty during transmitting interrupt flag + \arg I2C_INT_FLAG_BERR: a bus error occurs indication a unexpected start or stop condition on I2C bus interrupt flag + \arg I2C_INT_FLAG_LOSTARB: arbitration lost in master mode interrupt flag + \arg I2C_INT_FLAG_AERR: acknowledge error interrupt flag + \arg I2C_INT_FLAG_OUERR: over-run or under-run situation occurs in slave mode interrupt flag + \arg I2C_INT_FLAG_PECERR: PEC error when receiving data interrupt flag + \arg I2C_INT_FLAG_SMBTO: timeout signal in SMBus mode interrupt flag + \arg I2C_INT_FLAG_SMBALT: SMBus Alert status interrupt flag + \param[out] none + \retval FlagStatus SET or RESET +*/ +FlagStatus i2c_interrupt_flag_get(uint32_t i2c_periph, i2c_interrupt_flag_enum int_flag) +{ + uint32_t intenable = 0U, flagstatus = 0U, bufie; + + /* check BUFIE */ + bufie = I2C_CTL1(i2c_periph)&I2C_CTL1_BUFIE; + + /* get the interrupt enable bit status */ + intenable = (I2C_REG_VAL(i2c_periph, int_flag) & BIT(I2C_BIT_POS(int_flag))); + /* get the corresponding flag bit status */ + flagstatus = (I2C_REG_VAL2(i2c_periph, int_flag) & BIT(I2C_BIT_POS2(int_flag))); + + if((I2C_INT_FLAG_RBNE == int_flag) || (I2C_INT_FLAG_TBE == int_flag)){ + if(intenable && bufie){ + intenable = 1U; + }else{ + intenable = 0U; + } + } + if((0U != flagstatus) && (0U != intenable)){ + return SET; + }else{ + return RESET; + } +} + +/*! + \brief clear I2C interrupt flag + \param[in] i2c_periph: I2Cx(x=0,1,2) + \param[in] intflag: I2C interrupt flags, refer to i2c_interrupt_flag_enum + only one parameter can be selected which is shown as below: + \arg I2C_INT_FLAG_ADDSEND: address is sent in master mode or received and matches in slave mode interrupt flag + \arg I2C_INT_FLAG_BERR: a bus error occurs indication a unexpected start or stop condition on I2C bus interrupt flag + \arg I2C_INT_FLAG_LOSTARB: arbitration lost in master mode interrupt flag + \arg I2C_INT_FLAG_AERR: acknowledge error interrupt flag + \arg I2C_INT_FLAG_OUERR: over-run or under-run situation occurs in slave mode interrupt flag + \arg I2C_INT_FLAG_PECERR: PEC error when receiving data interrupt flag + \arg I2C_INT_FLAG_SMBTO: timeout signal in SMBus mode interrupt flag + \arg I2C_INT_FLAG_SMBALT: SMBus Alert status interrupt flag + \param[out] none + \retval none +*/ +void i2c_interrupt_flag_clear(uint32_t i2c_periph, i2c_interrupt_flag_enum int_flag) +{ + if(I2C_INT_FLAG_ADDSEND == int_flag){ + /* read I2C_STAT0 and then read I2C_STAT1 to clear ADDSEND */ + I2C_STAT0(i2c_periph); + I2C_STAT1(i2c_periph); + }else{ + I2C_REG_VAL2(i2c_periph, int_flag) &= ~BIT(I2C_BIT_POS2(int_flag)); + } +} diff --git a/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_standard_peripheral/Source/gd32f20x_misc.c b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_standard_peripheral/Source/gd32f20x_misc.c new file mode 100644 index 0000000000..9ddb9e97ed --- /dev/null +++ b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_standard_peripheral/Source/gd32f20x_misc.c @@ -0,0 +1,186 @@ +/*! + \file gd32f20x_misc.c + \brief MISC driver + + \version 2015-07-15, V1.0.0, firmware for GD32F20x + \version 2017-06-05, V2.0.0, firmware for GD32F20x + \version 2018-10-31, V2.1.0, firmware for GD32F20x + \version 2020-09-30, V2.2.0, firmware for GD32F20x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "gd32f20x_misc.h" + +/*! + \brief set the priority group + \param[in] nvic_prigroup: the NVIC priority group + \arg NVIC_PRIGROUP_PRE0_SUB4:0 bits for pre-emption priority 4 bits for subpriority + \arg NVIC_PRIGROUP_PRE1_SUB3:1 bits for pre-emption priority 3 bits for subpriority + \arg NVIC_PRIGROUP_PRE2_SUB2:2 bits for pre-emption priority 2 bits for subpriority + \arg NVIC_PRIGROUP_PRE3_SUB1:3 bits for pre-emption priority 1 bits for subpriority + \arg NVIC_PRIGROUP_PRE4_SUB0:4 bits for pre-emption priority 0 bits for subpriority + \param[out] none + \retval none +*/ +void nvic_priority_group_set(uint32_t nvic_prigroup) +{ + /* set the priority group value */ + SCB->AIRCR = NVIC_AIRCR_VECTKEY_MASK | nvic_prigroup; +} + +/*! + \brief enable NVIC request + \param[in] nvic_irq: the NVIC interrupt request, detailed in IRQn_Type + \param[in] nvic_irq_pre_priority: the pre-emption priority needed to set + \param[in] nvic_irq_sub_priority: the subpriority needed to set + \param[out] none + \retval none +*/ +void nvic_irq_enable(uint8_t nvic_irq, + uint8_t nvic_irq_pre_priority, + uint8_t nvic_irq_sub_priority) +{ + uint32_t temp_priority = 0x00U, temp_pre = 0x00U, temp_sub = 0x00U; + + /* use the priority group value to get the temp_pre and the temp_sub */ + switch ((SCB->AIRCR) & (uint32_t)0x700U) { + case NVIC_PRIGROUP_PRE0_SUB4: + temp_pre = 0U; + temp_sub = 0x4U; + break; + case NVIC_PRIGROUP_PRE1_SUB3: + temp_pre = 1U; + temp_sub = 0x3U; + break; + case NVIC_PRIGROUP_PRE2_SUB2: + temp_pre = 2U; + temp_sub = 0x2U; + break; + case NVIC_PRIGROUP_PRE3_SUB1: + temp_pre = 3U; + temp_sub = 0x1U; + break; + case NVIC_PRIGROUP_PRE4_SUB0: + temp_pre = 4U; + temp_sub = 0x0U; + break; + default: + nvic_priority_group_set(NVIC_PRIGROUP_PRE2_SUB2); + temp_pre = 2U; + temp_sub = 0x2U; + break; + } + + /* get the temp_priority to fill the NVIC->IP register */ + temp_priority = (uint32_t)nvic_irq_pre_priority << (0x4U - temp_pre); + temp_priority |= nvic_irq_sub_priority &(0x0FU >> (0x4U - temp_sub)); + temp_priority = temp_priority << 0x04U; + NVIC->IP[nvic_irq] = (uint8_t)temp_priority; + + /* enable the selected IRQ */ + NVIC->ISER[nvic_irq >> 0x05U] = (uint32_t)0x01U << (nvic_irq & (uint8_t)0x1FU); +} + +/*! + \brief disable NVIC request + \param[in] nvic_irq: the NVIC interrupt request, detailed in IRQn_Type + \param[out] none + \retval none +*/ +void nvic_irq_disable(uint8_t nvic_irq) +{ + /* disable the selected IRQ.*/ + NVIC->ICER[nvic_irq >> 0x05U] = (uint32_t)0x01U << (nvic_irq & (uint8_t)0x1FU); +} + +/*! + \brief set the NVIC vector table base address + \param[in] nvic_vict_tab: the RAM or FLASH base address + \arg NVIC_VECTTAB_RAM: RAM base address + \are NVIC_VECTTAB_FLASH: Flash base address + \param[in] offset: Vector Table offset + \param[out] none + \retval none +*/ +void nvic_vector_table_set(uint32_t nvic_vict_tab, uint32_t offset) +{ + SCB->VTOR = nvic_vict_tab | (offset & NVIC_VECTTAB_OFFSET_MASK); +} + +/*! + \brief set the state of the low power mode + \param[in] lowpower_mode: the low power mode state + \arg SCB_LPM_SLEEP_EXIT_ISR: if chose this para, the system always enter low power + mode by exiting from ISR + \arg SCB_LPM_DEEPSLEEP: if chose this para, the system will enter the DEEPSLEEP mode + \arg SCB_LPM_WAKE_BY_ALL_INT: if chose this para, the lowpower mode can be woke up + by all the enable and disable interrupts + \param[out] none + \retval none +*/ +void system_lowpower_set(uint8_t lowpower_mode) +{ + SCB->SCR |= (uint32_t)lowpower_mode; +} + +/*! + \brief reset the state of the low power mode + \param[in] lowpower_mode: the low power mode state + \arg SCB_LPM_SLEEP_EXIT_ISR: if chose this para, the system will exit low power + mode by exiting from ISR + \arg SCB_LPM_DEEPSLEEP: if chose this para, the system will enter the SLEEP mode + \arg SCB_LPM_WAKE_BY_ALL_INT: if chose this para, the lowpower mode only can be + woke up by the enable interrupts + \param[out] none + \retval none +*/ +void system_lowpower_reset(uint8_t lowpower_mode) +{ + SCB->SCR &= (~(uint32_t)lowpower_mode); +} + +/*! + \brief set the systick clock source + \param[in] systick_clksource: the systick clock source needed to choose + \arg SYSTICK_CLKSOURCE_HCLK: systick clock source is from HCLK + \arg SYSTICK_CLKSOURCE_HCLK_DIV8: systick clock source is from HCLK/8 + \param[out] none + \retval none +*/ + +void systick_clksource_set(uint32_t systick_clksource) +{ + if(SYSTICK_CLKSOURCE_HCLK == systick_clksource ){ + /* set the systick clock source from HCLK */ + SysTick->CTRL |= SYSTICK_CLKSOURCE_HCLK; + }else{ + /* set the systick clock source from HCLK/8 */ + SysTick->CTRL &= SYSTICK_CLKSOURCE_HCLK_DIV8; + } +} diff --git a/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_standard_peripheral/Source/gd32f20x_pmu.c b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_standard_peripheral/Source/gd32f20x_pmu.c new file mode 100644 index 0000000000..2010191bbc --- /dev/null +++ b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_standard_peripheral/Source/gd32f20x_pmu.c @@ -0,0 +1,281 @@ +/*! + \file gd32f20x_pmu.c + \brief PMU driver + + \version 2015-07-15, V1.0.0, firmware for GD32F20x + \version 2017-06-05, V2.0.0, firmware for GD32F20x + \version 2018-10-31, V2.1.0, firmware for GD32F20x + \version 2020-09-30, V2.2.0, firmware for GD32F20x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "gd32f20x_pmu.h" + +/*! + \brief reset PMU register + \param[in] none + \param[out] none + \retval none +*/ +void pmu_deinit(void) +{ + /* reset PMU */ + rcu_periph_reset_enable(RCU_PMURST); + rcu_periph_reset_disable(RCU_PMURST); +} + +/*! + \brief select low voltage detector threshold + \param[in] lvdt_n: + only one parameter can be selected which is shown as below: + \arg PMU_LVDT_0: voltage threshold is 2.2V + \arg PMU_LVDT_1: voltage threshold is 2.3V + \arg PMU_LVDT_2: voltage threshold is 2.4V + \arg PMU_LVDT_3: voltage threshold is 2.5V + \arg PMU_LVDT_4: voltage threshold is 2.6V + \arg PMU_LVDT_5: voltage threshold is 2.7V + \arg PMU_LVDT_6: voltage threshold is 2.8V + \arg PMU_LVDT_7: voltage threshold is 2.9V + \param[out] none + \retval none +*/ +void pmu_lvd_select(uint32_t lvdt_n) +{ + /* disable LVD */ + PMU_CTL &= ~PMU_CTL_LVDEN; + /* clear LVDT bits */ + PMU_CTL &= ~PMU_CTL_LVDT; + /* set LVDT bits according to lvdt_n */ + PMU_CTL |= lvdt_n; + /* enable LVD */ + PMU_CTL |= PMU_CTL_LVDEN; +} + +/*! + \brief disable PMU lvd + \param[in] none + \param[out] none + \retval none +*/ +void pmu_lvd_disable(void) +{ + /* disable LVD */ + PMU_CTL &= ~PMU_CTL_LVDEN; +} + +/*! + \brief PMU work at sleep mode + \param[in] sleepmodecmd: + only one parameter can be selected which is shown as below: + \arg WFI_CMD: use WFI command + \arg WFE_CMD: use WFE command + \param[out] none + \retval none +*/ +void pmu_to_sleepmode(uint8_t sleepmodecmd) +{ + /* clear sleepdeep bit of Cortex-M3 system control register */ + SCB->SCR &= ~((uint32_t)SCB_SCR_SLEEPDEEP_Msk); + + /* select WFI or WFE command to enter sleep mode */ + if(WFI_CMD == sleepmodecmd){ + __WFI(); + }else{ + __WFE(); + } +} + +/*! + \brief PMU work at deepsleep mode + \param[in] ldo: + only one parameter can be selected which is shown as below: + \arg PMU_LDO_NORMAL: LDO work at normal power mode when pmu enter deepsleep mode + \arg PMU_LDO_LOWPOWER: LDO work at low power mode when pmu enter deepsleep mode + \param[in] deepsleepmodecmd: + only one parameter can be selected which is shown as below: + \arg WFI_CMD: use WFI command + \arg WFE_CMD: use WFE command + \param[out] none + \retval none +*/ +void pmu_to_deepsleepmode(uint32_t ldo,uint8_t deepsleepmodecmd) +{ + static uint32_t reg_snap[ 4 ]; + /* clear stbmod and ldolp bits */ + PMU_CTL &= ~((uint32_t)(PMU_CTL_STBMOD | PMU_CTL_LDOLP)); + + /* set ldolp bit according to pmu_ldo */ + PMU_CTL |= ldo; + + /* set sleepdeep bit of Cortex-M3 system control register */ + SCB->SCR |= SCB_SCR_SLEEPDEEP_Msk; + + reg_snap[ 0 ] = REG32( 0xE000E010U ); + reg_snap[ 1 ] = REG32( 0xE000E100U ); + reg_snap[ 2 ] = REG32( 0xE000E104U ); + reg_snap[ 3 ] = REG32( 0xE000E108U ); + + REG32( 0xE000E010U ) &= 0x00010004U; + REG32( 0xE000E180U ) = 0XFF7FF83DU; + REG32( 0xE000E184U ) = 0XBFFFF8FFU; + REG32( 0xE000E188U ) = 0xFFFFFFFFU; + + /* select WFI or WFE command to enter deepsleep mode */ + if(WFI_CMD == deepsleepmodecmd){ + __WFI(); + }else{ + __SEV(); + __WFE(); + __WFE(); + } + + REG32( 0xE000E010U ) = reg_snap[ 0 ] ; + REG32( 0xE000E100U ) = reg_snap[ 1 ] ; + REG32( 0xE000E104U ) = reg_snap[ 2 ] ; + REG32( 0xE000E108U ) = reg_snap[ 3 ] ; + + /* reset sleepdeep bit of Cortex-M3 system control register */ + SCB->SCR &= ~((uint32_t)SCB_SCR_SLEEPDEEP_Msk); +} + +/*! + \brief pmu work at standby mode + \param[in] standbymodecmd: + only one parameter can be selected which is shown as below: + \arg WFI_CMD: use WFI command + \arg WFE_CMD: use WFE command + \param[out] none + \retval none +*/ +void pmu_to_standbymode(uint8_t standbymodecmd) +{ + /* set sleepdeep bit of Cortex-M3 system control register */ + SCB->SCR |= SCB_SCR_SLEEPDEEP_Msk; + + /* set stbmod bit */ + PMU_CTL |= PMU_CTL_STBMOD; + + /* reset wakeup flag */ + PMU_CTL |= PMU_CTL_WURST; + + /* select WFI or WFE command to enter standby mode */ + if(WFI_CMD == standbymodecmd){ + __WFI(); + }else{ + __WFE(); + } +} + +/*! + \brief enable wakeup pin + \param[in] none + \param[out] none + \retval none +*/ +void pmu_wakeup_pin_enable(void) +{ + PMU_CS |= PMU_CS_WUPEN; +} + +/*! + \brief disable wakeup pin + \param[in] none + \param[out] none + \retval none +*/ +void pmu_wakeup_pin_disable(void) +{ + PMU_CS &= ~PMU_CS_WUPEN; +} + +/*! + \brief enable write access to the registers in backup domain + \param[in] none + \param[out] none + \retval none +*/ +void pmu_backup_write_enable(void) +{ + PMU_CTL |= PMU_CTL_BKPWEN; +} + +/*! + \brief disable write access to the registers in backup domain + \param[in] none + \param[out] none + \retval none +*/ +void pmu_backup_write_disable(void) +{ + PMU_CTL &= ~PMU_CTL_BKPWEN; +} + +/*! + \brief get flag state + \param[in] flag: + only one parameter can be selected which is shown as below: + \arg PMU_FLAG_WAKEUP: wakeup flag + \arg PMU_FLAG_STANDBY: standby flag + \arg PMU_FLAG_LVD: lvd flag + \param[out] none + \retval FlagStatus SET or RESET +*/ +FlagStatus pmu_flag_get(uint32_t flag) +{ + if(PMU_CS & flag){ + return SET; + }else{ + return RESET; + } +} + +/*! + \brief clear flag bit + \param[in] flag_reset: + only one parameter can be selected which is shown as below: + \arg PMU_FLAG_RESET_WAKEUP: reset wakeup flag + \arg PMU_FLAG_RESET_STANDBY: reset standby flag + \param[out] none + \retval none +*/ +void pmu_flag_clear(uint32_t flag_reset) +{ + switch(flag_reset){ + case PMU_FLAG_RESET_WAKEUP: + /* reset wakeup flag */ + PMU_CTL |= PMU_CTL_WURST; + break; + case PMU_FLAG_RESET_STANDBY: + /* reset standby flag */ + PMU_CTL |= PMU_CTL_STBRST; + break; + default : + break; + } +} diff --git a/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_standard_peripheral/Source/gd32f20x_rcu.c b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_standard_peripheral/Source/gd32f20x_rcu.c new file mode 100644 index 0000000000..8eb52a4019 --- /dev/null +++ b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_standard_peripheral/Source/gd32f20x_rcu.c @@ -0,0 +1,1336 @@ +/*! + \file gd32f20x_rcu.c + \brief RCU driver + + \version 2015-07-15, V1.0.0, firmware for GD32F20x + \version 2017-06-05, V2.0.0, firmware for GD32F20x + \version 2018-10-31, V2.1.0, firmware for GD32F20x + \version 2020-09-30, V2.2.0, firmware for GD32F20x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "gd32f20x_rcu.h" + +/* define clock source */ +#define SEL_IRC8M ((uint16_t)0U) +#define SEL_HXTAL ((uint16_t)1U) +#define SEL_PLL ((uint16_t)2U) + +/* define startup timeout count */ +#define OSC_STARTUP_TIMEOUT ((uint32_t)0xFFFFFU) +#define LXTAL_STARTUP_TIMEOUT ((uint32_t)0x3FFFFFFU) + +/*! + \brief deinitialize the RCU + \param[in] none + \param[out] none + \retval none +*/ +void rcu_deinit(void) +{ + /* enable IRC8M */ + RCU_CTL |= RCU_CTL_IRC8MEN; + rcu_osci_stab_wait(RCU_IRC8M); + + /* reset SCS, AHBPSC, APB1PSC, APB2PSC, ADCPSC, CKOUT0SEL bits */ + RCU_CFG0 &= ~(RCU_CFG0_SCS | RCU_CFG0_AHBPSC | RCU_CFG0_APB1PSC | RCU_CFG0_APB2PSC | + RCU_CFG0_ADCPSC | RCU_CFG0_ADCPSC_2 | RCU_CFG0_CKOUT0SEL); + + /* reset HXTALEN, CKMEN, PLLEN bits */ + RCU_CTL &= ~(RCU_CTL_HXTALEN | RCU_CTL_CKMEN | RCU_CTL_PLLEN ); + + /* Reset HXTALBPS bit */ + RCU_CTL &= ~(RCU_CTL_HXTALBPS); + + /* reset PLLSEL, PREDV0_LSB, PLLMF, USBFSPSC bits */ + RCU_CFG0 &= ~(RCU_CFG0_PLLSEL | RCU_CFG0_PREDV0_LSB | RCU_CFG0_PLLMF | + RCU_CFG0_USBFSPSC | RCU_CFG0_PLLMF_4); + + /* reset PLL1EN and PLL2EN bits */ + RCU_CTL &= ~(RCU_CTL_PLL1EN | RCU_CTL_PLL2EN); + + /* reset CFG1 register */ + RCU_CFG1 = 0x00000000U; + + /* reset INT register */ + RCU_INT = 0x00FF0000U; + + /* reset CFG2 register */ + RCU_CFG2 = 0x00000000U; + + /* reset PLLTCTL register */ + RCU_PLLTCTL &= (~RCU_PLLTCTL_PLLTEN); + + /* reset PLLTINT register */ + RCU_PLLTINT = 0x00400000U; + + /* Reset PLLTCFG register */ + RCU_PLLTCFG = 0x20003010U; +} + +/*! + \brief enable the peripherals clock + \param[in] periph: RCU peripherals, refer to rcu_periph_enum + only one parameter can be selected which is shown as below: + \arg RCU_GPIOx (x=A,B,C,D,E,F,G,H,I): GPIO ports clock + \arg RCU_AF : alternate function clock + \arg RCU_CRC: CRC clock + \arg RCU_DMAx (x=0,1): DMA clock + \arg RCU_ENET: ENET clock + \arg RCU_ENETTX: ENETTX clock + \arg RCU_ENETRX: ENETRX clock + \arg RCU_USBFS: USBFS clock + \arg RCU_EXMC: EXMC clock + \arg RCU_TIMERx (x=0,1,2,3,4,5,6,7,8,9,10,11,12,13): TIMER clock + \arg RCU_WWDGT: WWDGT clock + \arg RCU_SPIx (x=0,1,2): SPI clock + \arg RCU_USARTx (x=0,1,2,5): USART clock + \arg RCU_UARTx (x=3,4,6,7): UART clock + \arg RCU_I2Cx (x=0,1,2): I2C clock + \arg RCU_CANx (x=0,1): CAN clock + \arg RCU_PMU: PMU clock + \arg RCU_DAC: DAC clock + \arg RCU_RTC: RTC clock + \arg RCU_ADCx (x=0,1,2): ADC clock + \arg RCU_SDIO: SDIO clock + \arg RCU_BKPI: BKP interface clock + \arg RCU_TLI: TLI clock + \arg RCU_DCI: DCI clock + \arg RCU_CAU: CAU clock + \arg RCU_HAU: HAU clock + \arg RCU_TRNG: TRNG clock + \param[out] none + \retval none +*/ +void rcu_periph_clock_enable(rcu_periph_enum periph) +{ + RCU_REG_VAL(periph) |= BIT(RCU_BIT_POS(periph)); +} + +/*! + \brief disable the peripherals clock + \param[in] periph: RCU peripherals, refer to rcu_periph_enum + only one parameter can be selected which is shown as below: + \arg RCU_GPIOx (x=A,B,C,D,E,F,G,H,I): GPIO ports clock + \arg RCU_AF : alternate function clock + \arg RCU_CRC: CRC clock + \arg RCU_DMAx (x=0,1): DMA clock + \arg RCU_ENET: ENET clock + \arg RCU_ENETTX: ENETTX clock + \arg RCU_ENETRX: ENETRX clock + \arg RCU_USBFS: USBFS clock + \arg RCU_EXMC: EXMC clock + \arg RCU_TIMERx (x=0,1,2,3,4,5,6,7,8,9,10,11,12,13): TIMER clock + \arg RCU_WWDGT: WWDGT clock + \arg RCU_SPIx (x=0,1,2): SPI clock + \arg RCU_USARTx (x=0,1,2,5): USART clock + \arg RCU_UARTx (x=3,4,6,7): UART clock + \arg RCU_I2Cx (x=0,1,2): I2C clock + \arg RCU_CANx (x=0,1): CAN clock + \arg RCU_PMU: PMU clock + \arg RCU_DAC: DAC clock + \arg RCU_RTC: RTC clock + \arg RCU_ADCx (x=0,1,2): ADC clock + \arg RCU_SDIO: SDIO clock + \arg RCU_BKPI: BKP interface clock + \arg RCU_TLI: TLI clock + \arg RCU_DCI: DCI clock + \arg RCU_CAU: CAU clock + \arg RCU_HAU: HAU clock + \arg RCU_TRNG: TRNG clock + \param[out] none + \retval none +*/ +void rcu_periph_clock_disable(rcu_periph_enum periph) +{ + RCU_REG_VAL(periph) &= ~BIT(RCU_BIT_POS(periph)); +} + +/*! + \brief enable the peripherals clock when sleep mode + \param[in] periph: RCU peripherals, refer to rcu_periph_sleep_enum + only one parameter can be selected which is shown as below: + \arg RCU_FMC_SLP: FMC clock + \arg RCU_SRAM_SLP: SRAM clock + \param[out] none + \retval none +*/ +void rcu_periph_clock_sleep_enable(rcu_periph_sleep_enum periph) +{ + RCU_REG_VAL(periph) |= BIT(RCU_BIT_POS(periph)); +} + +/*! + \brief disable the peripherals clock when sleep mode + \param[in] periph: RCU peripherals, refer to rcu_periph_sleep_enum + only one parameter can be selected which is shown as below: + \arg RCU_FMC_SLP: FMC clock + \arg RCU_SRAM_SLP: SRAM clock + \param[out] none + \retval none +*/ +void rcu_periph_clock_sleep_disable(rcu_periph_sleep_enum periph) +{ + RCU_REG_VAL(periph) &= ~BIT(RCU_BIT_POS(periph)); +} + +/*! + \brief reset the peripherals + \param[in] periph_reset: RCU peripherals reset, refer to rcu_periph_reset_enum + only one parameter can be selected which is shown as below: + \arg RCU_GPIOxRST (x=A,B,C,D,E,F,G,H,I): reset GPIO ports + \arg RCU_AFRST : reset alternate function clock + \arg RCU_ENETRST: reset ENET + \arg RCU_USBFSRST: reset USBFS + \arg RCU_TIMERxRST (x=0,1,2,3,4,5,6,7,8,9,10,11,12,13): reset TIMER + \arg RCU_WWDGTRST: reset WWDGT + \arg RCU_SPIxRST (x=0,1,2): reset SPI + \arg RCU_USARTxRST (x=0,1,2,5): reset USART + \arg RCU_UARTxRST (x=3,4,6,7): reset UART + \arg RCU_I2CxRST (x=0,1,2): reset I2C + \arg RCU_CANxRST (x=0,1): reset CAN + \arg RCU_PMURST: reset PMU + \arg RCU_DACRST: reset DAC + \arg RCU_ADCRST (x=0,1,2): reset ADC + \arg RCU_BKPIRST: reset BKPI + \arg RCU_TLIRST: reset TLI + \arg RCU_DCIRST: reset DCI + \arg RCU_CAURST: reset CAU + \arg RCU_HAURST: reset HAU + \arg RCU_TRNGRST: reset TRNG + \param[out] none + \retval none +*/ +void rcu_periph_reset_enable(rcu_periph_reset_enum periph_reset) +{ + RCU_REG_VAL(periph_reset) |= BIT(RCU_BIT_POS(periph_reset)); +} + +/*! + \brief disable reset the peripheral + \param[in] periph_reset: RCU peripherals reset, refer to rcu_periph_reset_enum + only one parameter can be selected which is shown as below: + \arg RCU_GPIOxRST (x=A,B,C,D,E,F,G,H,I): reset GPIO ports + \arg RCU_AFRST : reset alternate function clock + \arg RCU_ENETRST: reset ENET + \arg RCU_USBFSRST: reset USBFS + \arg RCU_TIMERxRST (x=0,1,2,3,4,5,6,7,8,9,10,11,12,13): reset TIMER + \arg RCU_WWDGTRST: reset WWDGT + \arg RCU_SPIxRST (x=0,1,2): reset SPI + \arg RCU_USARTxRST (x=0,1,2,5): reset USART + \arg RCU_UARTxRST (x=3,4,6,7): reset UART + \arg RCU_I2CxRST (x=0,1,2): reset I2C + \arg RCU_CANxRST (x=0,1): reset CAN + \arg RCU_PMURST: reset PMU + \arg RCU_DACRST: reset DAC + \arg RCU_ADCRST (x=0,1,2): reset ADC + \arg RCU_BKPIRST: reset BKPI + \arg RCU_TLIRST: reset TLI + \arg RCU_DCIRST: reset DCI + \arg RCU_CAURST: reset CAU + \arg RCU_HAURST: reset HAU + \arg RCU_TRNGRST: reset TRNG + \param[out] none + \retval none +*/ +void rcu_periph_reset_disable(rcu_periph_reset_enum periph_reset) +{ + RCU_REG_VAL(periph_reset) &= ~BIT(RCU_BIT_POS(periph_reset)); +} + +/*! + \brief reset the BKP domain + \param[in] none + \param[out] none + \retval none +*/ +void rcu_bkp_reset_enable(void) +{ + RCU_BDCTL |= RCU_BDCTL_BKPRST; +} + +/*! + \brief disable the BKP domain reset + \param[in] none + \param[out] none + \retval none +*/ +void rcu_bkp_reset_disable(void) +{ + RCU_BDCTL &= ~RCU_BDCTL_BKPRST; +} + +/*! + \brief configure the system clock source + \param[in] ck_sys: system clock source select + only one parameter can be selected which is shown as below: + \arg RCU_CKSYSSRC_IRC8M: select CK_IRC8M as the CK_SYS source + \arg RCU_CKSYSSRC_HXTAL: select CK_HXTAL as the CK_SYS source + \arg RCU_CKSYSSRC_PLL: select CK_PLL as the CK_SYS source + \param[out] none + \retval none +*/ +void rcu_system_clock_source_config(uint32_t ck_sys) +{ + uint32_t reg; + + reg = RCU_CFG0; + /* reset the SCS bits and set according to ck_sys */ + reg &= ~RCU_CFG0_SCS; + RCU_CFG0 = (reg | ck_sys); +} + +/*! + \brief get the system clock source + \param[in] none + \param[out] none + \retval which clock is selected as CK_SYS source + \arg RCU_SCSS_IRC8M: CK_IRC8M is selected as the CK_SYS source + \arg RCU_SCSS_HXTAL: CK_HXTAL is selected as the CK_SYS source + \arg RCU_SCSS_PLL: CK_PLL is selected as the CK_SYS source +*/ +uint32_t rcu_system_clock_source_get(void) +{ + return (RCU_CFG0 & RCU_CFG0_SCSS); +} + +/*! + \brief configure the AHB clock prescaler selection + \param[in] ck_ahb: AHB clock prescaler selection + only one parameter can be selected which is shown as below: + \arg RCU_AHB_CKSYS_DIVx, x=1, 2, 4, 8, 16, 64, 128, 256, 512 + \param[out] none + \retval none +*/ +void rcu_ahb_clock_config(uint32_t ck_ahb) +{ + uint32_t reg; + + reg = RCU_CFG0; + + /* reset the AHBPSC bits and set according to ck_ahb */ + reg &= ~RCU_CFG0_AHBPSC; + RCU_CFG0 = (reg | ck_ahb); +} + +/*! + \brief configure the APB1 clock prescaler selection + \param[in] ck_apb1: APB1 clock prescaler selection + only one parameter can be selected which is shown as below: + \arg RCU_APB1_CKAHB_DIV1: select CK_AHB as CK_APB1 + \arg RCU_APB1_CKAHB_DIV2: select CK_AHB/2 as CK_APB1 + \arg RCU_APB1_CKAHB_DIV4: select CK_AHB/4 as CK_APB1 + \arg RCU_APB1_CKAHB_DIV8: select CK_AHB/8 as CK_APB1 + \arg RCU_APB1_CKAHB_DIV16: select CK_AHB/16 as CK_APB1 + \param[out] none + \retval none +*/ +void rcu_apb1_clock_config(uint32_t ck_apb1) +{ + uint32_t reg; + + reg = RCU_CFG0; + + /* reset the APB1PSC and set according to ck_apb1 */ + reg &= ~RCU_CFG0_APB1PSC; + RCU_CFG0 = (reg | ck_apb1); +} + +/*! + \brief configure the APB2 clock prescaler selection + \param[in] ck_apb2: APB2 clock prescaler selection + only one parameter can be selected which is shown as below: + \arg RCU_APB2_CKAHB_DIV1: select CK_AHB as CK_APB2 + \arg RCU_APB2_CKAHB_DIV2: select CK_AHB/2 as CK_APB2 + \arg RCU_APB2_CKAHB_DIV4: select CK_AHB/4 as CK_APB2 + \arg RCU_APB2_CKAHB_DIV8: select CK_AHB/8 as CK_APB2 + \arg RCU_APB2_CKAHB_DIV16: select CK_AHB/16 as CK_APB2 + \param[out] none + \retval none +*/ +void rcu_apb2_clock_config(uint32_t ck_apb2) +{ + uint32_t reg; + + reg = RCU_CFG0; + + /* reset the APB2PSC and set according to ck_apb2 */ + reg &= ~RCU_CFG0_APB2PSC; + RCU_CFG0 = (reg | ck_apb2); +} + +/*! + \brief configure the CK_OUT0 clock source and divider + \param[in] ckout0_src: CK_OUT0 clock source selection + only one parameter can be selected which is shown as below: + \arg RCU_CKOUT0SRC_NONE: no clock selected + \arg RCU_CKOUT0SRC_CKSYS: system clock selected + \arg RCU_CKOUT0SRC_IRC8M: high speed 8M internal oscillator clock selected + \arg RCU_CKOUT0SRC_HXTAL: HXTAL selected + \arg RCU_CKOUT0SRC_CKPLL_DIV2: CK_PLL/2 selected + \arg RCU_CKOUT0SRC_CKPLL1: CK_PLL1 selected + \arg RCU_CKOUT0SRC_CKPLL2_DIV2: CK_PLL2/2 selected + \arg RCU_CKOUT0SRC_EXT1: EXT1 selected + \arg RCU_CKOUT0SRC_CKPLL2: PLL selected + \param[in] ckout0_div: CK_OUT0 divider + \arg RCU_CKOUT0_DIVx(x=1..64): CK_OUT0 is divided by x + \param[out] none + \retval none +*/ +void rcu_ckout0_config(uint32_t ckout0_src, uint32_t ckout0_div) +{ + uint32_t reg; + + reg = RCU_CFG0; + + /* set the CKOUT0SEL according to ckout0_src */ + reg &= ~RCU_CFG0_CKOUT0SEL; + RCU_CFG0 = (reg | ckout0_src); + + reg = RCU_CFG2; + + /* set the CKOUT0DIV according to ckout0_div */ + reg &= ~RCU_CFG2_CKOUT0DIV; + RCU_CFG2 = (reg | ckout0_div); +} + +/*! + \brief configure the CK_OUT1 clock source and divider + \param[in] ckout1_src: CK_OUT1 clock source selection + only one parameter can be selected which is shown as below: + \arg RCU_CKOUT1SRC_NONE: no clock selected + \arg RCU_CKOUT1SRC_CKSYS: system clock selected + \arg RCU_CKOUT1SRC_IRC8M: high speed 8M internal oscillator clock selected + \arg RCU_CKOUT1SRC_HXTAL: HXTAL selected + \arg RCU_CKOUT1SRC_CKPLL_DIV2: CK_PLL/2 selected + \arg RCU_CKOUT1SRC_CKPLL1: CK_PLL1 selected + \arg RCU_CKOUT1SRC_CKPLL2_DIV2: CK_PLL2/2 selected + \arg RCU_CKOUT1SRC_EXT1: EXT1 selected + \arg RCU_CKOUT1SRC_CKPLL2: PLL selected + \param[in] ckout1_div: CK_OUT1 divider + \arg RCU_CKOUT1_DIVx(x=1..64): CK_OUT1 is divided by x + \param[out] none + \retval none +*/ +void rcu_ckout1_config(uint32_t ckout1_src, uint32_t ckout1_div) +{ + uint32_t reg; + + reg = RCU_CFG2; + /* set the CKOUT1SEL and CKOUT1DIV according to ckout1_src and ckout1_div */ + reg &= ~(RCU_CFG2_CKOUT1SEL | RCU_CFG2_CKOUT1DIV); + RCU_CFG2 = (reg | ckout1_src | ckout1_div); + +} + +/*! + \brief configure the main PLL clock + \param[in] pll_src: PLL clock source selection + \arg RCU_PLLSRC_IRC8M_DIV2: IRC8M/2 clock selected as source clock of PLL + \arg RCU_PLLSRC_HXTAL: HXTAL selected as source clock of PLL + \param[in] pll_mul: PLL clock multiplication factor + \arg RCU_PLL_MULx (x = 2..14,16..32,6.5) + \param[out] none + \retval none +*/ +void rcu_pll_config(uint32_t pll_src, uint32_t pll_mul) +{ + uint32_t reg = 0U; + + reg = RCU_CFG0; + + /* PLL clock source and multiplication factor configuration */ + reg &= ~(RCU_CFG0_PLLSEL | RCU_CFG0_PLLMF | RCU_CFG0_PLLMF_4); + reg |= (pll_src | pll_mul); + + RCU_CFG0 = reg; +} + +/*! + \brief configure the PREDV0 division factor and clock source + \param[in] predv0_source: PREDV0 input clock source selection + only one parameter can be selected which is shown as below: + \arg RCU_PREDV0SRC_HXTAL: HXTAL selected as PREDV0 input source clock + \arg RCU_PREDV0SRC_CKPLL1: CK_PLL1 selected as PREDV0 input source clock + \param[in] predv0_div: PREDV0 division factor + only one parameter can be selected which is shown as below: + \arg RCU_PREDV0_DIVx, x = 1..16 + \param[out] none + \retval none +*/ +void rcu_predv0_config(uint32_t predv0_source, uint32_t predv0_div) +{ + uint32_t reg = 0U; + + reg = RCU_CFG1; + /* reset PREDV0SEL and PREDV0 bits */ + reg &= ~(RCU_CFG1_PREDV0SEL | RCU_CFG1_PREDV0); + /* set the PREDV0SEL and PREDV0 division factor */ + reg |= (predv0_source | predv0_div); + + RCU_CFG1 = reg; +} + +/*! + \brief configure the PREDV1 division factor + \param[in] predv1_div: PREDV1 division factor + only one parameter can be selected which is shown as below: + \arg RCU_PREDV1_DIVx, x = 1..16 + \param[out] none + \retval none +*/ +void rcu_predv1_config(uint32_t predv1_div) +{ + uint32_t reg = 0U; + + reg = RCU_CFG1; + /* reset the PREDV1 bits */ + reg &= ~RCU_CFG1_PREDV1; + /* set the PREDV1 division factor */ + reg |= predv1_div; + + RCU_CFG1 = reg; +} + +/*! + \brief configure the PLL1 clock + \param[in] pll_mul: PLL clock multiplication factor + only one parameter can be selected which is shown as below: + \arg RCU_PLL1_MULx (x = 8..16, 20) + \param[out] none + \retval none +*/ +void rcu_pll1_config(uint32_t pll_mul) +{ + RCU_CFG1 &= ~RCU_CFG1_PLL1MF; + RCU_CFG1 |= pll_mul; +} + +/*! + \brief configure the PLL2 clock + \param[in] pll_mul: PLL clock multiplication factor + only one parameter can be selected which is shown as below: + \arg RCU_PLL2_MULx (x = 8..16, 20) + \param[out] none + \retval none +*/ +void rcu_pll2_config(uint32_t pll_mul) +{ + RCU_CFG1 &= ~RCU_CFG1_PLL2MF; + RCU_CFG1 |= pll_mul; +} + +/*! + \brief configure the ADC prescaler factor + \param[in] adc_psc: ADC prescaler factor + only one parameter can be selected which is shown as below: + \arg RCU_CKADC_CKAPB2_DIV2: ADC prescaler select CK_APB2/2 + \arg RCU_CKADC_CKAPB2_DIV4: ADC prescaler select CK_APB2/4 + \arg RCU_CKADC_CKAPB2_DIV6: ADC prescaler select CK_APB2/6 + \arg RCU_CKADC_CKAPB2_DIV8: ADC prescaler select CK_APB2/8 + \arg RCU_CKADC_CKAPB2_DIV12: ADC prescaler select CK_APB2/12 + \arg RCU_CKADC_CKAPB2_DIV16: ADC prescaler select CK_APB2/16 + \param[out] none + \retval none +*/ +void rcu_adc_clock_config(uint32_t adc_psc) +{ + uint32_t reg0 = 0U; + + /* reset the ADCPSC bits */ + reg0 = RCU_CFG0; + reg0 &= ~(RCU_CFG0_ADCPSC_2 | RCU_CFG0_ADCPSC); + + /* set the ADC prescaler factor */ + switch(adc_psc){ + case RCU_CKADC_CKAPB2_DIV2: + case RCU_CKADC_CKAPB2_DIV4: + case RCU_CKADC_CKAPB2_DIV6: + case RCU_CKADC_CKAPB2_DIV8: + reg0 |= (adc_psc << 14); + break; + + case RCU_CKADC_CKAPB2_DIV12: + case RCU_CKADC_CKAPB2_DIV16: + adc_psc &= ~BIT(2); + reg0 |= (adc_psc << 14 | RCU_CFG0_ADCPSC_2); + break; + + default: + break; + } + + /* set the register */ + RCU_CFG0 = reg0; +} + +/*! + \brief configure the USBFS/TRNG prescaler factor + \param[in] usbfs_trng_psc: USBFS/TRNG prescaler factor + \arg RCU_CKUSB_CKPLL_DIV1_5: USBFS/TRNG prescaler select CK_PLL/1.5 + \arg RCU_CKUSB_CKPLL_DIV1: USBFS/TRNG prescaler select CK_PLL/1 + \arg RCU_CKUSB_CKPLL_DIV2_5: USBFS/TRNG prescaler select CK_PLL/2.5 + \arg RCU_CKUSB_CKPLL_DIV2: USBFS/TRNG prescaler select CK_PLL/2 + \param[out] none + \retval none +*/ +void rcu_usbfs_trng_clock_config(uint32_t usbfs_trng_psc) +{ + uint32_t reg = 0U; + + reg = RCU_CFG0; + + /* configure the USBFS/TRNG prescaler factor */ + reg &= ~RCU_CFG0_USBFSPSC; + RCU_CFG0 = (reg | usbfs_trng_psc); +} + + +/*! + \brief configure the RTC clock source selection + \param[in] rtc_clock_source: RTC clock source selection + only one parameter can be selected which is shown as below: + \arg RCU_RTCSRC_NONE: no clock selected + \arg RCU_RTCSRC_LXTAL: CK_LXTAL selected as RTC source clock + \arg RCU_RTCSRC_IRC40K: CK_IRC40K selected as RTC source clock + \arg RCU_RTCSRC_HXTAL_DIV128: CK_HXTAL/128 selected as RTC source clock + \param[out] none + \retval none +*/ +void rcu_rtc_clock_config(uint32_t rtc_clock_source) +{ + uint32_t reg; + + reg = RCU_BDCTL; + /* reset the RTCSRC bits and set according to rtc_clock_source */ + reg &= ~RCU_BDCTL_RTCSRC; + RCU_BDCTL = (reg | rtc_clock_source); +} + +/*! + \brief configure the I2S1 clock source selection + \param[in] i2s_clock_source: I2S1 clock source selection + only one parameter can be selected which is shown as below: + \arg RCU_I2S1SRC_CKSYS: System clock selected as I2S1 source clock + \arg RCU_I2S1SRC_CKPLL2_MUL2: CK_PLL2 x 2 selected as I2S1 source clock + \param[out] none + \retval none +*/ +void rcu_i2s1_clock_config(uint32_t i2s_clock_source) +{ + uint32_t reg; + + reg = RCU_CFG1; + /* reset the I2S1SEL bit and set according to i2s_clock_source */ + reg &= ~RCU_CFG1_I2S1SEL; + RCU_CFG1 = (reg | i2s_clock_source); +} + +/*! + \brief configure the I2S2 clock source selection + \param[in] i2s_clock_source: I2S2 clock source selection + only one parameter can be selected which is shown as below: + \arg RCU_I2S2SRC_CKSYS: system clock selected as I2S2 source clock + \arg RCU_I2S2SRC_CKPLL2_MUL2: CK_PLL2 x 2 selected as I2S2 source clock + \param[out] none + \retval none +*/ +void rcu_i2s2_clock_config(uint32_t i2s_clock_source) +{ + uint32_t reg; + + reg = RCU_CFG1; + /* reset the I2S2SEL bit and set according to i2s_clock_source */ + reg &= ~RCU_CFG1_I2S2SEL; + RCU_CFG1 = (reg | i2s_clock_source); +} + +/*! + \brief get the clock stabilization and periphral reset flags + \param[in] flag: the clock stabilization and periphral reset flags, refer to rcu_flag_enum + only one parameter can be selected which is shown as below: + \arg RCU_FLAG_IRC8MSTB: IRC8M stabilization flag + \arg RCU_FLAG_HXTALSTB: HXTAL stabilization flag + \arg RCU_FLAG_PLLSTB: PLL stabilization flag + \arg RCU_FLAG_PLL1STB: PLL1 stabilization flag + \arg RCU_FLAG_PLL2STB: PLL2 stabilization flag + \arg RCU_FLAG_PLLTSTB: PLLT stabilization flag + \arg RCU_FLAG_LXTALSTB: LXTAL stabilization flag + \arg RCU_FLAG_IRC40KSTB: IRC40K stabilization flag + \arg RCU_FLAG_EPRST: external PIN reset flag + \arg RCU_FLAG_PORRST: power reset flag + \arg RCU_FLAG_SWRST: software reset flag + \arg RCU_FLAG_FWDGTRST: free watchdog timer reset flag + \arg RCU_FLAG_WWDGTRST: window watchdog timer reset flag + \arg RCU_FLAG_LPRST: low-power reset flag + \param[out] none + \retval FlagStatus: SET or RESET +*/ +FlagStatus rcu_flag_get(rcu_flag_enum flag) +{ + /* get the rcu flag */ + if(RESET != (RCU_REG_VAL(flag) & BIT(RCU_BIT_POS(flag)))){ + return SET; + }else{ + return RESET; + } +} + +/*! + \brief clear all the reset flag + \param[in] none + \param[out] none + \retval none +*/ +void rcu_all_reset_flag_clear(void) +{ + RCU_RSTSCK |= RCU_RSTSCK_RSTFC; +} + +/*! + \brief get the clock stabilization and ckm interrupt flags + \param[in] int_flag: interrupt and ckm flags, refer to rcu_int_flag_enum + only one parameter can be selected which is shown as below: + \arg RCU_INT_FLAG_IRC40KSTB: IRC40K stabilization interrupt flag + \arg RCU_INT_FLAG_LXTALSTB: LXTAL stabilization interrupt flag + \arg RCU_INT_FLAG_IRC8MSTB: IRC8M stabilization interrupt flag + \arg RCU_INT_FLAG_HXTALSTB: HXTAL stabilization interrupt flag + \arg RCU_INT_FLAG_PLLSTB: PLL stabilization interrupt flag + \arg RCU_INT_FLAG_PLL1STB: PLL1 stabilization interrupt flag + \arg RCU_INT_FLAG_PLL2STB: PLL2 stabilization interrupt flag + \arg RCU_INT_FLAG_CKM: HXTAL clock stuck interrupt flag + \arg RCU_INT_FLAG_PLLTSTB: PLLT stabilization interrupt flag + \param[out] none + \retval FlagStatus: SET or RESET +*/ +FlagStatus rcu_interrupt_flag_get(rcu_int_flag_enum int_flag) +{ + /* get the rcu interrupt flag */ + if(RESET != (RCU_REG_VAL(int_flag) & BIT(RCU_BIT_POS(int_flag)))){ + return SET; + }else{ + return RESET; + } +} + +/*! + \brief clear the interrupt flags + \param[in] int_flag_clear: clock stabilization and stuck interrupt flags clear, refer to rcu_int_flag_clear_enum + only one parameter can be selected which is shown as below: + \arg RCU_INT_FLAG_IRC40KSTB_CLR: IRC40K stabilization interrupt flag clear + \arg RCU_INT_FLAG_LXTALSTB_CLR: LXTAL stabilization interrupt flag clear + \arg RCU_INT_FLAG_IRC8MSTB_CLR: IRC8M stabilization interrupt flag clear + \arg RCU_INT_FLAG_HXTALSTB_CLR: HXTAL stabilization interrupt flag clear + \arg RCU_INT_FLAG_PLLSTB_CLR: PLL stabilization interrupt flag clear + \arg RCU_INT_FLAG_PLL1STB_CLR: PLL1 stabilization interrupt flag clear + \arg RCU_INT_FLAG_PLL2STB_CLR: PLL2 stabilization interrupt flag clear + \arg RCU_INT_FLAG_CKM_CLR: clock stuck interrupt flag clear + \arg RCU_INT_FLAG_PLLTSTB_CLR: PLLT stabilization interrupt flag clear + \param[out] none + \retval none +*/ +void rcu_interrupt_flag_clear(rcu_int_flag_clear_enum int_flag_clear) +{ + RCU_REG_VAL(int_flag_clear) |= BIT(RCU_BIT_POS(int_flag_clear)); +} + +/*! + \brief enable the stabilization interrupt + \param[in] stab_int: clock stabilization interrupt, refer to rcu_int_enum + Only one parameter can be selected which is shown as below: + \arg RCU_INT_IRC40KSTB: IRC40K stabilization interrupt enable + \arg RCU_INT_LXTALSTB: LXTAL stabilization interrupt enable + \arg RCU_INT_IRC8MSTB: IRC8M stabilization interrupt enable + \arg RCU_INT_HXTALSTB: HXTAL stabilization interrupt enable + \arg RCU_INT_PLLSTB: PLL stabilization interrupt enable + \arg RCU_INT_PLL1STB: PLL1 stabilization interrupt enable + \arg RCU_INT_PLL2STB: PLL2 stabilization interrupt enable + \arg RCU_INT_PLLTSTB: PLLT stabilization interrupt enable + \param[out] none + \retval none +*/ +void rcu_interrupt_enable(rcu_int_enum stab_int) +{ + RCU_REG_VAL(stab_int) |= BIT(RCU_BIT_POS(stab_int)); +} + +/*! + \brief disable the stabilization interrupt + \param[in] stab_int: clock stabilization interrupt, refer to rcu_int_enum + only one parameter can be selected which is shown as below: + \arg RCU_INT_IRC40KSTB: IRC40K stabilization interrupt enable + \arg RCU_INT_LXTALSTB: LXTAL stabilization interrupt enable + \arg RCU_INT_IRC8MSTB: IRC8M stabilization interrupt enable + \arg RCU_INT_HXTALSTB: HXTAL stabilization interrupt enable + \arg RCU_INT_PLLSTB: PLL stabilization interrupt enable + \arg RCU_INT_PLL1STB: PLL1 stabilization interrupt enable + \arg RCU_INT_PLL2STB: PLL2 stabilization interrupt enable + \arg RCU_INT_PLLTSTB: PLLT stabilization interrupt enable + \param[out] none + \retval none +*/ +void rcu_interrupt_disable(rcu_int_enum stab_int) +{ + RCU_REG_VAL(stab_int) &= ~BIT(RCU_BIT_POS(stab_int)); +} + +/*! + \brief configure the LXTAL drive capability + \param[in] lxtal_dricap: drive capability of LXTAL + only one parameter can be selected which is shown as below: + \arg RCU_LXTAL_LOWDRI: lower driving capability + \arg RCU_LXTAL_MED_LOWDRI: medium low driving capability + \arg RCU_LXTAL_MED_HIGHDRI: medium high driving capability + \arg RCU_LXTAL_HIGHDRI: higher driving capability + \param[out] none + \retval none +*/ +void rcu_lxtal_drive_capability_config(uint32_t lxtal_dricap) +{ + uint32_t reg; + + reg = RCU_BDCTL; + + /* reset the LXTALDRI bits and set according to lxtal_dricap */ + reg &= ~RCU_BDCTL_LXTALDRI; + RCU_BDCTL = (reg | lxtal_dricap); +} + +/*! + \brief wait for oscillator stabilization flags is SET or oscillator startup is timeout + \param[in] osci: oscillator types, refer to rcu_osci_type_enum + only one parameter can be selected which is shown as below: + \arg RCU_HXTAL: high speed crystal oscillator(HXTAL) + \arg RCU_LXTAL: low speed crystal oscillator(LXTAL) + \arg RCU_IRC8M: internal 8M RC oscillators(IRC8M) + \arg RCU_IRC40K: internal 40K RC oscillator(IRC40K) + \arg RCU_PLL_CK: phase locked loop(PLL) + \arg RCU_PLL1_CK: phase locked loop 1 + \arg RCU_PLL2_CK: phase locked loop 2 + \arg RCU_PLLT_CK: TLI phase locked loop + \param[out] none + \retval ErrStatus: SUCCESS or ERROR +*/ +ErrStatus rcu_osci_stab_wait(rcu_osci_type_enum osci) +{ + uint32_t stb_cnt = 0U; + ErrStatus reval = ERROR; + FlagStatus osci_stat = RESET; + + switch(osci){ + /* wait HXTAL stable */ + case RCU_HXTAL: + while((RESET == osci_stat) && (HXTAL_STARTUP_TIMEOUT != stb_cnt)){ + osci_stat = rcu_flag_get(RCU_FLAG_HXTALSTB); + stb_cnt++; + } + + /* check whether flag is set or not */ + if(RESET != rcu_flag_get(RCU_FLAG_HXTALSTB)){ + reval = SUCCESS; + } + break; + + /* wait LXTAL stable */ + case RCU_LXTAL: + while((RESET == osci_stat) && (LXTAL_STARTUP_TIMEOUT != stb_cnt)){ + osci_stat = rcu_flag_get(RCU_FLAG_LXTALSTB); + stb_cnt++; + } + + /* check whether flag is set or not */ + if(RESET != rcu_flag_get(RCU_FLAG_LXTALSTB)){ + reval = SUCCESS; + } + break; + + /* wait IRC8M stable */ + case RCU_IRC8M: + while((RESET == osci_stat) && (IRC8M_STARTUP_TIMEOUT != stb_cnt)){ + osci_stat = rcu_flag_get(RCU_FLAG_IRC8MSTB); + stb_cnt++; + } + + /* check whether flag is set or not */ + if(RESET != rcu_flag_get(RCU_FLAG_IRC8MSTB)){ + reval = SUCCESS; + } + break; + + /* wait IRC40K stable */ + case RCU_IRC40K: + while((RESET == osci_stat) && (OSC_STARTUP_TIMEOUT != stb_cnt)){ + osci_stat = rcu_flag_get(RCU_FLAG_IRC40KSTB); + stb_cnt++; + } + + /* check whether flag is set or not */ + if(RESET != rcu_flag_get(RCU_FLAG_IRC40KSTB)){ + reval = SUCCESS; + } + break; + + /* wait PLL stable */ + case RCU_PLL_CK: + while((RESET == osci_stat) && (OSC_STARTUP_TIMEOUT != stb_cnt)){ + osci_stat = rcu_flag_get(RCU_FLAG_PLLSTB); + stb_cnt++; + } + + /* check whether flag is set or not */ + if(RESET != rcu_flag_get(RCU_FLAG_PLLSTB)){ + reval = SUCCESS; + } + break; + + /* wait PLL1 stable */ + case RCU_PLL1_CK: + while((RESET == osci_stat) && (OSC_STARTUP_TIMEOUT != stb_cnt)){ + osci_stat = rcu_flag_get(RCU_FLAG_PLL1STB); + stb_cnt++; + } + + /* check whether flag is set or not */ + if(RESET != rcu_flag_get(RCU_FLAG_PLL1STB)){ + reval = SUCCESS; + } + break; + + /* wait PLL2 stable */ + case RCU_PLL2_CK: + while((RESET == osci_stat) && (OSC_STARTUP_TIMEOUT != stb_cnt)){ + osci_stat = rcu_flag_get(RCU_FLAG_PLL2STB); + stb_cnt++; + } + + /* check whether flag is set or not */ + if(RESET != rcu_flag_get(RCU_FLAG_PLL2STB)){ + reval = SUCCESS; + } + break; + + /* wait PLLT stable */ + case RCU_PLLT_CK: + while((RESET == osci_stat) && (OSC_STARTUP_TIMEOUT != stb_cnt)){ + osci_stat = rcu_flag_get(RCU_FLAG_PLLTSTB); + stb_cnt++; + } + + /* check whether flag is set or not */ + if(RESET != rcu_flag_get(RCU_FLAG_PLLTSTB)){ + reval = SUCCESS; + } + break; + + default: + break; + } + + /* return value */ + return reval; +} + +/*! + \brief turn on the oscillator + \param[in] osci: oscillator types, refer to rcu_osci_type_enum + only one parameter can be selected which is shown as below: + \arg RCU_HXTAL: high speed crystal oscillator(HXTAL) + \arg RCU_LXTAL: low speed crystal oscillator(LXTAL) + \arg RCU_IRC8M: internal 8M RC oscillators(IRC8M) + \arg RCU_IRC40K: internal 40K RC oscillator(IRC40K) + \arg RCU_PLL_CK: phase locked loop(PLL) + \arg RCU_PLL1_CK: phase locked loop 1 + \arg RCU_PLL2_CK: phase locked loop 2 + \arg RCU_PLLT_CK: TLI phase locked loop + \param[out] none + \retval none +*/ +void rcu_osci_on(rcu_osci_type_enum osci) +{ + RCU_REG_VAL(osci) |= BIT(RCU_BIT_POS(osci)); +} + +/*! + \brief turn off the oscillator + \param[in] osci: oscillator types, refer to rcu_osci_type_enum + only one parameter can be selected which is shown as below: + \arg RCU_HXTAL: high speed crystal oscillator(HXTAL) + \arg RCU_LXTAL: low speed crystal oscillator(LXTAL) + \arg RCU_IRC8M: internal 8M RC oscillators(IRC8M) + \arg RCU_IRC40K: internal 40K RC oscillator(IRC40K) + \arg RCU_PLL_CK: phase locked loop(PLL) + \arg RCU_PLL1_CK: phase locked loop 1 + \arg RCU_PLL2_CK: phase locked loop 2 + \arg RCU_PLLT_CK: TLI phase locked loop + \param[out] none + \retval none +*/ +void rcu_osci_off(rcu_osci_type_enum osci) +{ + RCU_REG_VAL(osci) &= ~BIT(RCU_BIT_POS(osci)); +} + +/*! + \brief enable the oscillator bypass mode, HXTALEN or LXTALEN must be reset before it + \param[in] osci: oscillator types, refer to rcu_osci_type_enum + only one parameter can be selected which is shown as below: + \arg RCU_HXTAL: high speed crystal oscillator(HXTAL) + \arg RCU_LXTAL: low speed crystal oscillator(LXTAL) + \param[out] none + \retval none +*/ +void rcu_osci_bypass_mode_enable(rcu_osci_type_enum osci) +{ + uint32_t reg; + + switch(osci){ + /* enable HXTAL to bypass mode */ + case RCU_HXTAL: + reg = RCU_CTL; + RCU_CTL &= ~RCU_CTL_HXTALEN; + RCU_CTL = (reg | RCU_CTL_HXTALBPS); + break; + /* enable LXTAL to bypass mode */ + case RCU_LXTAL: + reg = RCU_BDCTL; + RCU_BDCTL &= ~RCU_BDCTL_LXTALEN; + RCU_BDCTL = (reg | RCU_BDCTL_LXTALBPS); + break; + case RCU_IRC8M: + case RCU_IRC40K: + case RCU_PLL_CK: + case RCU_PLL1_CK: + case RCU_PLL2_CK: + case RCU_PLLT_CK: + break; + default: + break; + } +} + +/*! + \brief disable the oscillator bypass mode, HXTALEN or LXTALEN must be reset before it + \param[in] osci: oscillator types, refer to rcu_osci_type_enum + only one parameter can be selected which is shown as below: + \arg RCU_HXTAL: high speed crystal oscillator(HXTAL) + \arg RCU_LXTAL: low speed crystal oscillator(LXTAL) + \param[out] none + \retval none +*/ +void rcu_osci_bypass_mode_disable(rcu_osci_type_enum osci) +{ + uint32_t reg; + + switch(osci){ + /* disable HXTAL to bypass mode */ + case RCU_HXTAL: + reg = RCU_CTL; + RCU_CTL &= ~RCU_CTL_HXTALEN; + RCU_CTL = (reg & ~RCU_CTL_HXTALBPS); + break; + /* disable LXTAL to bypass mode */ + case RCU_LXTAL: + reg = RCU_BDCTL; + RCU_BDCTL &= ~RCU_BDCTL_LXTALEN; + RCU_BDCTL = (reg & ~RCU_BDCTL_LXTALBPS); + break; + case RCU_IRC8M: + case RCU_IRC40K: + case RCU_PLL_CK: + case RCU_PLL1_CK: + case RCU_PLL2_CK: + case RCU_PLLT_CK: + break; + default: + break; + } +} + +/*! + \brief enable the HXTAL clock monitor + \param[in] none + \param[out] none + \retval none +*/ + +void rcu_hxtal_clock_monitor_enable(void) +{ + RCU_CTL |= RCU_CTL_CKMEN; +} + +/*! + \brief disable the HXTAL clock monitor + \param[in] none + \param[out] none + \retval none +*/ +void rcu_hxtal_clock_monitor_disable(void) +{ + RCU_CTL &= ~RCU_CTL_CKMEN; +} + +/*! + \brief set the IRC8M adjust value + \param[in] irc8m_adjval: IRC8M adjust value, must be between 0 and 0x1F + \param[out] none + \retval none +*/ +void rcu_irc8m_adjust_value_set(uint8_t irc8m_adjval) +{ + uint32_t reg; + + reg = RCU_CTL; + /* reset the IRC8MADJ bits and set according to irc8m_adjval */ + reg &= ~RCU_CTL_IRC8MADJ; + RCU_CTL = (reg | ((irc8m_adjval & 0x1FU) << 3)); +} + +/*! + \brief deep-sleep mode voltage select + \param[in] dsvol: deep sleep mode voltage + only one parameter can be selected which is shown as below: + \arg RCU_DEEPSLEEP_V_1_2: the core voltage is 1.2V + \arg RCU_DEEPSLEEP_V_1_1: the core voltage is 1.1V + \arg RCU_DEEPSLEEP_V_1_0: the core voltage is 1.0V + \arg RCU_DEEPSLEEP_V_0_9: the core voltage is 0.9V + \param[out] none + \retval none +*/ +void rcu_deepsleep_voltage_set(uint32_t dsvol) +{ + dsvol &= RCU_DSV_DSLPVS; + RCU_DSV = dsvol; +} + +/*! + \brief get the system clock, bus and peripheral clock frequency + \param[in] clock: the clock frequency which to get + only one parameter can be selected which is shown as below: + \arg CK_SYS: system clock frequency + \arg CK_AHB: AHB clock frequency + \arg CK_APB1: APB1 clock frequency + \arg CK_APB2: APB2 clock frequency + \param[out] none + \retval clock frequency of system, AHB, APB1, APB2 +*/ +uint32_t rcu_clock_freq_get(rcu_clock_freq_enum clock) +{ + uint32_t sws, ck_freq = 0U; + uint32_t cksys_freq, ahb_freq, apb1_freq, apb2_freq; + uint32_t pllsel, predv0sel, pllmf,ck_src, idx, clk_exp; + uint32_t predv0, predv1, pll1mf; + + /* exponent of AHB, APB1 and APB2 clock divider */ + uint8_t ahb_exp[16] = {0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 6, 7, 8, 9}; + uint8_t apb1_exp[8] = {0, 0, 0, 0, 1, 2, 3, 4}; + uint8_t apb2_exp[8] = {0, 0, 0, 0, 1, 2, 3, 4}; + + sws = GET_BITS(RCU_CFG0, 2, 3); + switch(sws){ + /* IRC8M is selected as CK_SYS */ + case SEL_IRC8M: + cksys_freq = IRC8M_VALUE; + break; + /* HXTAL is selected as CK_SYS */ + case SEL_HXTAL: + cksys_freq = HXTAL_VALUE; + break; + /* PLL is selected as CK_SYS */ + case SEL_PLL: + /* PLL clock source selection HXTAL or IRC8M/2 */ + pllsel = (RCU_CFG0 & RCU_CFG0_PLLSEL); + + if(RCU_PLLSRC_HXTAL == pllsel) { + /* PLL clock source is HXTAL */ + ck_src = HXTAL_VALUE; + + predv0sel = (RCU_CFG1 & RCU_CFG1_PREDV0SEL); + /* source clock use PLL1 */ + if(RCU_PREDV0SRC_CKPLL1 == predv0sel){ + predv1 = (uint32_t)((RCU_CFG1 & RCU_CFG1_PREDV1) >> 4) + 1U; + pll1mf = (uint32_t)((RCU_CFG1 & RCU_CFG1_PLL1MF) >> 8) + 2U; + + if(17U == pll1mf){ + pll1mf = 20U; + } + ck_src = (ck_src/predv1)*pll1mf; + } + predv0 = (RCU_CFG1 & RCU_CFG1_PREDV0) + 1U; + ck_src /= predv0; + }else{ + /* PLL clock source is IRC8M/2 */ + ck_src = IRC8M_VALUE/2U; + } + + /* PLL multiplication factor */ + pllmf = GET_BITS(RCU_CFG0, 18, 21); + if((RCU_CFG0 & RCU_CFG0_PLLMF_4)){ + pllmf |= 0x10U; + } + + if(13U == pllmf){ + /* PLL source clock multiply by 6.5 */ + cksys_freq = ck_src*6U + ck_src/2U; + }else{ + if(pllmf < 15U){ + pllmf += 2U; + }else{ + pllmf += 1U; + } + cksys_freq = ck_src*pllmf; + } + break; + /* IRC8M is selected as CK_SYS */ + default: + cksys_freq = IRC8M_VALUE; + break; + } + + /* calculate AHB clock frequency */ + idx = GET_BITS(RCU_CFG0, 4, 7); + clk_exp = ahb_exp[idx]; + ahb_freq = cksys_freq >> clk_exp; + + /* calculate APB1 clock frequency */ + idx = GET_BITS(RCU_CFG0, 8, 10); + clk_exp = apb1_exp[idx]; + apb1_freq = ahb_freq >> clk_exp; + + /* calculate APB2 clock frequency */ + idx = GET_BITS(RCU_CFG0, 11, 13); + clk_exp = apb2_exp[idx]; + apb2_freq = ahb_freq >> clk_exp; + + /* return the clocks frequency */ + switch(clock){ + case CK_SYS: + ck_freq = cksys_freq; + break; + case CK_AHB: + ck_freq = ahb_freq; + break; + case CK_APB1: + ck_freq = apb1_freq; + break; + case CK_APB2: + ck_freq = apb2_freq; + break; + default: + break; + } + return ck_freq; +} + +/*! + \brief configure the PLLT clock selection + \param[in] pllt_src: PLLT clock source selection + \arg RCU_PLLTSRC_IRC8M: IRC8M selected as source clock of PLLT + \arg RCU_PLLTSRC_HXTAL: HXTAL selected as source clock of PLLT + \param[out] none + \retval none +*/ +void rcu_pllt_config(uint32_t pllt_src) +{ + uint32_t reg = 0U; + + reg = RCU_PLLTCFG; + + /* reset the PLLT clock source bit PLLTSEL */ + reg &= ~RCU_PLLTCFG_PLLTSEL; + + RCU_PLLTCFG = (reg | pllt_src); +} + +/*! + \brief configure the PLLT clock multiplication and division factors + \param[in] pllt_psc: the PLLT VCO input clock division factor + \arg this parameter should be selected between 2 and 63. And this parameter should + be selected correctly to ensure that the VCO input frequency ranges from 1 to 2 MHz + \param[in] pllt_mul: he PLLT VCO output clock multiplication factor + \arg this parameter should be selected between 49 and 432 + \param[in] ppltr_psc: the PLLTR division factor + \arg this parameter should be selected between 2 and 7 + \param[out] none + \retval ErrStatus: SUCCESS or ERROR +*/ +ErrStatus rcu_pllt_vco_config(uint32_t pllt_psc, uint32_t pllt_mul, uint32_t ppltr_psc) +{ + uint32_t reg = 0U; + + /* check the function parameter */ + if((pllt_psc < 2U) || (pllt_psc > 63U)){ + return ERROR; + }else{ + } + + if((pllt_mul < 49U) || (pllt_mul > 432U)){ + return ERROR; + }else{ + } + + if((ppltr_psc < 2U) || (ppltr_psc > 7U)){ + return ERROR; + }else{ + } + + reg = RCU_PLLTCFG; + + /* reset the PLLTRPSC bits, PLLTMF bits and PLLTPSC bits */ + reg &= ~(RCU_PLLTCFG_PLLTRPSC | RCU_PLLTCFG_PLLTMF | RCU_PLLTCFG_PLLTPSC); + + reg |= (PLLTCFG_PLLTPSC(pllt_psc) | PLLTCFG_PLLTMF(pllt_mul) | PLLTCFG_PLLTRPSC(ppltr_psc)); + + RCU_PLLTCFG = reg; + + return SUCCESS; +} + +/*! + \brief configure the TLI prescaler factor from PLLTR clock + \param[in] tli_psc: TLI prescaler factor + only one parameter can be selected which is shown as below: + \arg RCU_CKTLI_CKPLLTR_DIV2: TLI prescaler select CK_PLLTR/2 + \arg RCU_CKTLI_CKPLLTR_DIV4: TLI prescaler select CK_PLLTR/4 + \arg RCU_CKTLI_CKPLLTR_DIV8: TLI prescaler select CK_PLLTR/8 + \arg RCU_CKTLI_CKPLLTR_DIV16: TLI prescaler select CK_PLLTR/16 + \param[out] none + \retval none +*/ +void rcu_tli_clock_config(uint32_t tli_psc) +{ + uint32_t reg = 0U; + + reg = RCU_PLLTCFG; + + /* reset the TLIPSC bits */ + reg &= ~RCU_PLLTCFG_TLIPSC; + + RCU_PLLTCFG = (reg | tli_psc); +} + diff --git a/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_standard_peripheral/Source/gd32f20x_rtc.c b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_standard_peripheral/Source/gd32f20x_rtc.c new file mode 100644 index 0000000000..4f8ae6f7dc --- /dev/null +++ b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_standard_peripheral/Source/gd32f20x_rtc.c @@ -0,0 +1,276 @@ +/*! + \file gd32f20x_rtc.c + \brief RTC driver + + \version 2015-07-15, V1.0.0, firmware for GD32F20x + \version 2017-06-05, V2.0.0, firmware for GD32F20x + \version 2018-10-31, V2.1.0, firmware for GD32F20x + \version 2020-09-30, V2.2.0, firmware for GD32F20x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "gd32f20x_rtc.h" + +/* RTC register high / low bits mask */ +#define RTC_HIGH_BITS_MASK ((uint32_t)0x000F0000U) /* RTC high bits mask */ +#define RTC_LOW_BITS_MASK ((uint32_t)0x0000FFFFU) /* RTC low bits mask */ + +/* RTC register high bits offset */ +#define RTC_HIGH_BITS_OFFSET ((uint32_t)16U) + +/*! + \brief enter RTC configuration mode + \param[in] none + \param[out] none + \retval none +*/ +void rtc_configuration_mode_enter(void) +{ + RTC_CTL |= RTC_CTL_CMF; +} + +/*! + \brief exit RTC configuration mode + \param[in] none + \param[out] none + \retval none +*/ +void rtc_configuration_mode_exit(void) +{ + RTC_CTL &= ~RTC_CTL_CMF; +} + +/*! + \brief set RTC counter value + \param[in] cnt: RTC counter value + \param[out] none + \retval none +*/ +void rtc_counter_set(uint32_t cnt) +{ + rtc_configuration_mode_enter(); + /* set the RTC counter high bits */ + RTC_CNTH = (cnt >> RTC_HIGH_BITS_OFFSET); + /* set the RTC counter low bits */ + RTC_CNTL = (cnt & RTC_LOW_BITS_MASK); + rtc_configuration_mode_exit(); +} + +/*! + \brief set RTC prescaler value + \param[in] psc: RTC prescaler value + \param[out] none + \retval none +*/ +void rtc_prescaler_set(uint32_t psc) +{ + rtc_configuration_mode_enter(); + /* set the RTC prescaler high bits */ + RTC_PSCH = ((psc & RTC_HIGH_BITS_MASK) >> RTC_HIGH_BITS_OFFSET); + /* set the RTC prescaler low bits */ + RTC_PSCL = (psc & RTC_LOW_BITS_MASK); + rtc_configuration_mode_exit(); +} + +/*! + \brief wait RTC last write operation finished flag set + \param[in] none + \param[out] none + \retval none +*/ +void rtc_lwoff_wait(void) +{ + /* loop until LWOFF flag is set */ + while(RESET == (RTC_CTL & RTC_CTL_LWOFF)){ + } +} + +/*! + \brief wait RTC registers synchronized flag set + \param[in] none + \param[out] none + \retval none +*/ +void rtc_register_sync_wait(void) +{ + /* clear RSYNF flag */ + RTC_CTL &= ~RTC_CTL_RSYNF; + /* loop until RSYNF flag is set */ + while(RESET == (RTC_CTL & RTC_CTL_RSYNF)){ + } +} + +/*! + \brief set RTC alarm value + \param[in] alarm: RTC alarm value + \param[out] none + \retval none +*/ +void rtc_alarm_config(uint32_t alarm) +{ + rtc_configuration_mode_enter(); + /* set the alarm high bits */ + RTC_ALRMH = (alarm >> RTC_HIGH_BITS_OFFSET); + /* set the alarm low bits */ + RTC_ALRML = (alarm & RTC_LOW_BITS_MASK); + rtc_configuration_mode_exit(); +} + +/*! + \brief get RTC counter value + \param[in] none + \param[out] none + \retval RTC counter value +*/ +uint32_t rtc_counter_get(void) +{ + uint32_t temp = 0x0U; + + temp = RTC_CNTL; + temp |= (RTC_CNTH << RTC_HIGH_BITS_OFFSET); + return temp; +} + +/*! + \brief get RTC divider value + \param[in] none + \param[out] none + \retval RTC divider value +*/ +uint32_t rtc_divider_get(void) +{ + uint32_t temp = 0x00U; + + temp = ((RTC_DIVH & RTC_DIVH_DIV) << RTC_HIGH_BITS_OFFSET); + temp |= RTC_DIVL; + return temp; +} + +/*! + \brief get RTC flag status + \param[in] flag: specify which flag status to get + only one parameter can be selected which is shown as below: + \arg RTC_FLAG_SECOND: second interrupt flag + \arg RTC_FLAG_ALARM: alarm interrupt flag + \arg RTC_FLAG_OVERFLOW: overflow interrupt flag + \arg RTC_FLAG_RSYN: registers synchronized flag + \arg RTC_FLAG_LWOF: last write operation finished flag + \param[out] none + \retval SET or RESET +*/ +FlagStatus rtc_flag_get(uint32_t flag) +{ + if(RESET != (RTC_CTL & flag)){ + return SET; + }else{ + return RESET; + } +} + +/*! + \brief clear RTC flag status + \param[in] flag: specify which flag status to clear + one or more parameters can be selected which are shown as below: + \arg RTC_FLAG_SECOND: second interrupt flag + \arg RTC_FLAG_ALARM: alarm interrupt flag + \arg RTC_FLAG_OVERFLOW: overflow interrupt flag + \arg RTC_FLAG_RSYN: registers synchronized flag + \param[out] none + \retval none +*/ +void rtc_flag_clear(uint32_t flag) +{ + /* clear RTC flag */ + RTC_CTL &= ~flag; +} + +/*! + \brief get RTC interrupt flag status + \param[in] flag: specify which flag status to get + only one parameter can be selected which is shown as below: + \arg RTC_INT_FLAG_SECOND: second interrupt flag + \arg RTC_INT_FLAG_ALARM: alarm interrupt flag + \arg RTC_INT_FLAG_OVERFLOW: overflow interrupt flag + \param[out] none + \retval SET or RESET +*/ +FlagStatus rtc_interrupt_flag_get(uint32_t flag) +{ + if(RESET != (RTC_CTL & flag)){ + return SET; + }else{ + return RESET; + } +} + +/*! + \brief clear RTC interrupt flag status + \param[in] flag: specify which flag status to clear + one or more parameters can be selected which are shown as below: + \arg RTC_INT_FLAG_SECOND: second interrupt flag + \arg RTC_INT_FLAG_ALARM: alarm interrupt flag + \arg RTC_INT_FLAG_OVERFLOW: overflow interrupt flag + \param[out] none + \retval none +*/ +void rtc_interrupt_flag_clear(uint32_t flag) +{ + /* clear RTC interrupt flag */ + RTC_CTL &= ~flag; +} + +/*! + \brief enable RTC interrupt + \param[in] interrupt: specify which interrupt to enbale + one or more parameters can be selected which are shown as below: + \arg RTC_INT_SECOND: second interrupt + \arg RTC_INT_ALARM: alarm interrupt + \arg RTC_INT_OVERFLOW: overflow interrupt + \param[out] none + \retval none +*/ +void rtc_interrupt_enable(uint32_t interrupt) +{ + RTC_INTEN |= interrupt; +} + +/*! + \brief disable RTC interrupt + \param[in] interrupt: specify which interrupt to disbale + one or more parameters can be selected which are shown as below: + \arg RTC_INT_SECOND: second interrupt + \arg RTC_INT_ALARM: alarm interrupt + \arg RTC_INT_OVERFLOW: overflow interrupt + \param[out] none + \retval none +*/ +void rtc_interrupt_disable(uint32_t interrupt) +{ + RTC_INTEN &= ~interrupt; +} diff --git a/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_standard_peripheral/Source/gd32f20x_sdio.c b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_standard_peripheral/Source/gd32f20x_sdio.c new file mode 100644 index 0000000000..c329af94d0 --- /dev/null +++ b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_standard_peripheral/Source/gd32f20x_sdio.c @@ -0,0 +1,817 @@ +/*! + \file gd32f20x_sdio.c + \brief SDIO driver + + \version 2015-07-15, V1.0.0, firmware for GD32F20x + \version 2017-06-05, V2.0.0, firmware for GD32F20x + \version 2018-10-31, V2.1.0, firmware for GD32F20x + \version 2020-09-30, V2.2.0, firmware for GD32F20x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "gd32f20x_sdio.h" + +#define DEFAULT_RESET_VALUE 0x00000000U + +/*! + \brief deinitialize the SDIO + \param[in] none + \param[out] none + \retval none +*/ +void sdio_deinit(void) +{ + SDIO_PWRCTL = DEFAULT_RESET_VALUE; + SDIO_CLKCTL = DEFAULT_RESET_VALUE; + SDIO_CMDAGMT = DEFAULT_RESET_VALUE; + SDIO_CMDCTL = DEFAULT_RESET_VALUE; + SDIO_DATATO = DEFAULT_RESET_VALUE; + SDIO_DATALEN = DEFAULT_RESET_VALUE; + SDIO_DATACTL = DEFAULT_RESET_VALUE; + SDIO_INTC = DEFAULT_RESET_VALUE; + SDIO_INTEN = DEFAULT_RESET_VALUE; +} + +/*! + \brief configure the SDIO clock + \param[in] clock_edge: SDIO_CLK clock edge + only one parameter can be selected which is shown as below: + \arg SDIO_SDIOCLKEDGE_RISING: select the rising edge of the SDIOCLK to generate SDIO_CLK + \arg SDIO_SDIOCLKEDGE_FALLING: select the falling edge of the SDIOCLK to generate SDIO_CLK + \param[in] clock_bypass: clock bypass + only one parameter can be selected which is shown as below: + \arg SDIO_CLOCKBYPASS_ENABLE: clock bypass + \arg SDIO_CLOCKBYPASS_DISABLE: no bypass + \param[in] clock_powersave: SDIO_CLK clock dynamic switch on/off for power saving + only one parameter can be selected which is shown as below: + \arg SDIO_CLOCKPWRSAVE_ENABLE: SDIO_CLK closed when bus is idle + \arg SDIO_CLOCKPWRSAVE_DISABLE: SDIO_CLK clock is always on + \param[in] clock_division: clock division, less than 512 + \param[out] none + \retval none +*/ +void sdio_clock_config(uint32_t clock_edge, uint32_t clock_bypass, uint32_t clock_powersave, uint16_t clock_division) +{ + uint32_t clock_config = 0U; + clock_config = SDIO_CLKCTL; + /* reset the CLKEDGE, CLKBYP, CLKPWRSAV, DIV */ + clock_config &= ~(SDIO_CLKCTL_CLKEDGE | SDIO_CLKCTL_CLKBYP | SDIO_CLKCTL_CLKPWRSAV | SDIO_CLKCTL_DIV8 | SDIO_CLKCTL_DIV); + /* if the clock division is greater or equal to 256, set the DIV[8] */ + if(clock_division >= 256U){ + clock_config |= SDIO_CLKCTL_DIV8; + clock_division -= 256U; + } + /* configure the SDIO_CLKCTL according to the parameters */ + clock_config |= (clock_edge | clock_bypass | clock_powersave | clock_division); + SDIO_CLKCTL = clock_config; +} + +/*! + \brief enable hardware clock control + \param[in] none + \param[out] none + \retval none +*/ +void sdio_hardware_clock_enable(void) +{ + SDIO_CLKCTL |= SDIO_CLKCTL_HWCLKEN; +} + +/*! + \brief disable hardware clock control + \param[in] none + \param[out] none + \retval none +*/ +void sdio_hardware_clock_disable(void) +{ + SDIO_CLKCTL &= ~SDIO_CLKCTL_HWCLKEN; +} + +/*! + \brief set different SDIO card bus mode + \param[in] bus_mode: SDIO card bus mode + only one parameter can be selected which is shown as below: + \arg SDIO_BUSMODE_1BIT: 1-bit SDIO card bus mode + \arg SDIO_BUSMODE_4BIT: 4-bit SDIO card bus mode + \arg SDIO_BUSMODE_8BIT: 8-bit SDIO card bus mode + \param[out] none + \retval none +*/ +void sdio_bus_mode_set(uint32_t bus_mode) +{ + /* reset the SDIO card bus mode bits and set according to bus_mode */ + SDIO_CLKCTL &= ~SDIO_CLKCTL_BUSMODE; + SDIO_CLKCTL |= bus_mode; +} + +/*! + \brief set the SDIO power state + \param[in] power_state: SDIO power state + only one parameter can be selected which is shown as below: + \arg SDIO_POWER_ON: SDIO power on + \arg SDIO_POWER_OFF: SDIO power off + \param[out] none + \retval none +*/ +void sdio_power_state_set(uint32_t power_state) +{ + SDIO_PWRCTL = power_state; +} + +/*! + \brief get the SDIO power state + \param[in] none + \param[out] none + \retval SDIO power state + only one parameter can be selected which is shown as below: + \arg SDIO_POWER_ON: SDIO power on + \arg SDIO_POWER_OFF: SDIO power off +*/ +uint32_t sdio_power_state_get(void) +{ + return SDIO_PWRCTL; +} + +/*! + \brief enable SDIO_CLK clock output + \param[in] none + \param[out] none + \retval none +*/ +void sdio_clock_enable(void) +{ + SDIO_CLKCTL |= SDIO_CLKCTL_CLKEN; +} + +/*! + \brief disable SDIO_CLK clock output + \param[in] none + \param[out] none + \retval none +*/ +void sdio_clock_disable(void) +{ + SDIO_CLKCTL &= ~SDIO_CLKCTL_CLKEN; +} + +/*! + \brief configure the command and response + \param[in] cmd_index: command index, refer to the related specifications + \param[in] cmd_argument: command argument, refer to the related specifications + \param[in] response_type: response type + only one parameter can be selected which is shown as below: + \arg SDIO_RESPONSETYPE_NO: no response + \arg SDIO_RESPONSETYPE_SHORT: short response + \arg SDIO_RESPONSETYPE_LONG: long response + \param[out] none + \retval none +*/ +void sdio_command_response_config(uint32_t cmd_index, uint32_t cmd_argument, uint32_t response_type) +{ + uint32_t cmd_config = 0U; + /* reset the command index, command argument and response type */ + SDIO_CMDAGMT &= ~SDIO_CMDAGMT_CMDAGMT; + SDIO_CMDAGMT = cmd_argument; + cmd_config = SDIO_CMDCTL; + cmd_config &= ~(SDIO_CMDCTL_CMDIDX | SDIO_CMDCTL_CMDRESP); + /* configure SDIO_CMDCTL and SDIO_CMDAGMT according to the parameters */ + cmd_config |= (cmd_index | response_type); + SDIO_CMDCTL = cmd_config; +} + +/*! + \brief set the command state machine wait type + \param[in] wait_type: wait type + only one parameter can be selected which is shown as below: + \arg SDIO_WAITTYPE_NO: not wait interrupt + \arg SDIO_WAITTYPE_INTERRUPT: wait interrupt + \arg SDIO_WAITTYPE_DATAEND: wait the end of data transfer + \param[out] none + \retval none +*/ +void sdio_wait_type_set(uint32_t wait_type) +{ + /* reset INTWAIT and WAITDEND */ + SDIO_CMDCTL &= ~(SDIO_CMDCTL_INTWAIT | SDIO_CMDCTL_WAITDEND); + /* set the wait type according to wait_type */ + SDIO_CMDCTL |= wait_type; +} + +/*! + \brief enable the CSM(command state machine) + \param[in] none + \param[out] none + \retval none +*/ +void sdio_csm_enable(void) +{ + SDIO_CMDCTL |= SDIO_CMDCTL_CSMEN; +} + +/*! + \brief disable the CSM(command state machine) + \param[in] none + \param[out] none + \retval none +*/ +void sdio_csm_disable(void) +{ + SDIO_CMDCTL &= ~SDIO_CMDCTL_CSMEN; +} + +/*! + \brief get the last response command index + \param[in] none + \param[out] none + \retval last response command index +*/ +uint8_t sdio_command_index_get(void) +{ + return (uint8_t)SDIO_RSPCMDIDX; +} + +/*! + \brief get the response for the last received command + \param[in] responsex: SDIO response + only one parameter can be selected which is shown as below: + \arg SDIO_RESPONSE0: card response[31:0]/card response[127:96] + \arg SDIO_RESPONSE1: card response[95:64] + \arg SDIO_RESPONSE2: card response[63:32] + \arg SDIO_RESPONSE3: card response[31:1], plus bit 0 + \param[out] none + \retval response for the last received command +*/ +uint32_t sdio_response_get(uint32_t responsex) +{ + uint32_t resp_content = 0U; + switch(responsex){ + case SDIO_RESPONSE0: + resp_content = SDIO_RESP0; + break; + case SDIO_RESPONSE1: + resp_content = SDIO_RESP1; + break; + case SDIO_RESPONSE2: + resp_content = SDIO_RESP2; + break; + case SDIO_RESPONSE3: + resp_content = SDIO_RESP3; + break; + default: + break; + } + return resp_content; +} + +/*! + \brief configure the data timeout, data length and data block size + \param[in] data_timeout: data timeout period in card bus clock periods + \param[in] data_length: number of data bytes to be transferred + \param[in] data_blocksize: size of data block for block transfer + only one parameter can be selected which is shown as below: + \arg SDIO_DATABLOCKSIZE_1BYTE: block size = 1 byte + \arg SDIO_DATABLOCKSIZE_2BYTES: block size = 2 bytes + \arg SDIO_DATABLOCKSIZE_4BYTES: block size = 4 bytes + \arg SDIO_DATABLOCKSIZE_8BYTES: block size = 8 bytes + \arg SDIO_DATABLOCKSIZE_16BYTES: block size = 16 bytes + \arg SDIO_DATABLOCKSIZE_32BYTES: block size = 32 bytes + \arg SDIO_DATABLOCKSIZE_64BYTES: block size = 64 bytes + \arg SDIO_DATABLOCKSIZE_128BYTES: block size = 128 bytes + \arg SDIO_DATABLOCKSIZE_256BYTES: block size = 256 bytes + \arg SDIO_DATABLOCKSIZE_512BYTES: block size = 512 bytes + \arg SDIO_DATABLOCKSIZE_1024BYTES: block size = 1024 bytes + \arg SDIO_DATABLOCKSIZE_2048BYTES: block size = 2048 bytes + \arg SDIO_DATABLOCKSIZE_4096BYTES: block size = 4096 bytes + \arg SDIO_DATABLOCKSIZE_8192BYTES: block size = 8192 bytes + \arg SDIO_DATABLOCKSIZE_16384BYTES: block size = 16384 bytes + \param[out] none + \retval none +*/ +void sdio_data_config(uint32_t data_timeout, uint32_t data_length, uint32_t data_blocksize) +{ + /* reset data timeout, data length and data block size */ + SDIO_DATATO &= ~SDIO_DATATO_DATATO; + SDIO_DATALEN &= ~SDIO_DATALEN_DATALEN; + SDIO_DATACTL &= ~SDIO_DATACTL_BLKSZ; + /* configure the related parameters of data */ + SDIO_DATATO = data_timeout; + SDIO_DATALEN = data_length; + SDIO_DATACTL |= data_blocksize; +} + +/*! + \brief configure the data transfer mode and direction + \param[in] transfer_mode: mode of data transfer + only one parameter can be selected which is shown as below: + \arg SDIO_TRANSMODE_BLOCK: block transfer + \arg SDIO_TRANSMODE_STREAM: stream transfer or SDIO multibyte transfer + \param[in] transfer_direction: data transfer direction, read or write + only one parameter can be selected which is shown as below: + \arg SDIO_TRANSDIRECTION_TOCARD: write data to card + \arg SDIO_TRANSDIRECTION_TOSDIO: read data from card + \param[out] none + \retval none +*/ +void sdio_data_transfer_config(uint32_t transfer_mode, uint32_t transfer_direction) +{ + uint32_t data_trans = 0U; + /* reset the data transfer mode, transfer direction and set according to the parameters */ + data_trans = SDIO_DATACTL; + data_trans &= ~(SDIO_DATACTL_TRANSMOD | SDIO_DATACTL_DATADIR); + data_trans |= (transfer_mode | transfer_direction); + SDIO_DATACTL = data_trans; +} + +/*! + \brief enable the DSM(data state machine) for data transfer + \param[in] none + \param[out] none + \retval none +*/ +void sdio_dsm_enable(void) +{ + SDIO_DATACTL |= SDIO_DATACTL_DATAEN; +} + +/*! + \brief disable the DSM(data state machine) + \param[in] none + \param[out] none + \retval none +*/ +void sdio_dsm_disable(void) +{ + SDIO_DATACTL &= ~SDIO_DATACTL_DATAEN; +} + +/*! + \brief write data(one word) to the transmit FIFO + \param[in] data: 32-bit data write to card + \param[out] none + \retval none +*/ +void sdio_data_write(uint32_t data) +{ + SDIO_FIFO = data; +} + +/*! + \brief read data(one word) from the receive FIFO + \param[in] none + \param[out] none + \retval received data +*/ +uint32_t sdio_data_read(void) +{ + return SDIO_FIFO; +} + +/*! + \brief get the number of remaining data bytes to be transferred to card + \param[in] none + \param[out] none + \retval number of remaining data bytes to be transferred +*/ +uint32_t sdio_data_counter_get(void) +{ + return SDIO_DATACNT; +} + +/*! + \brief get the number of words remaining to be written or read from FIFO + \param[in] none + \param[out] none + \retval remaining number of words +*/ +uint32_t sdio_fifo_counter_get(void) +{ + return SDIO_FIFOCNT; +} + +/*! + \brief enable the DMA request for SDIO + \param[in] none + \param[out] none + \retval none +*/ +void sdio_dma_enable(void) +{ + SDIO_DATACTL |= SDIO_DATACTL_DMAEN; +} + +/*! + \brief disable the DMA request for SDIO + \param[in] none + \param[out] none + \retval none +*/ +void sdio_dma_disable(void) +{ + SDIO_DATACTL &= ~SDIO_DATACTL_DMAEN; +} + +/*! + \brief enable the read wait mode(SD I/O only) + \param[in] none + \param[out] none + \retval none +*/ +void sdio_readwait_enable(void) +{ + SDIO_DATACTL |= SDIO_DATACTL_RWEN; +} + +/*! + \brief disable the read wait mode(SD I/O only) + \param[in] none + \param[out] none + \retval none +*/ +void sdio_readwait_disable(void) +{ + SDIO_DATACTL &= ~SDIO_DATACTL_RWEN; +} + +/*! + \brief enable the function that stop the read wait process(SD I/O only) + \param[in] none + \param[out] none + \retval none +*/ +void sdio_stop_readwait_enable(void) +{ + SDIO_DATACTL |= SDIO_DATACTL_RWSTOP; +} + +/*! + \brief disable the function that stop the read wait process(SD I/O only) + \param[in] none + \param[out] none + \retval none +*/ +void sdio_stop_readwait_disable(void) +{ + SDIO_DATACTL &= ~SDIO_DATACTL_RWSTOP; +} + +/*! + \brief set the read wait type(SD I/O only) + \param[in] readwait_type: SD I/O read wait type + only one parameter can be selected which is shown as below: + \arg SDIO_READWAITTYPE_CLK: read wait control by stopping SDIO_CLK + \arg SDIO_READWAITTYPE_DAT2: read wait control using SDIO_DAT[2] + \param[out] none + \retval none +*/ +void sdio_readwait_type_set(uint32_t readwait_type) +{ + if(SDIO_READWAITTYPE_CLK == readwait_type){ + SDIO_DATACTL |= SDIO_DATACTL_RWTYPE; + }else{ + SDIO_DATACTL &= ~SDIO_DATACTL_RWTYPE; + } +} + +/*! + \brief enable the SD I/O mode specific operation(SD I/O only) + \param[in] none + \param[out] none + \retval none +*/ +void sdio_operation_enable(void) +{ + SDIO_DATACTL |= SDIO_DATACTL_IOEN; +} + +/*! + \brief disable the SD I/O mode specific operation(SD I/O only) + \param[in] none + \param[out] none + \retval none +*/ +void sdio_operation_disable(void) +{ + SDIO_DATACTL &= ~SDIO_DATACTL_IOEN; +} + +/*! + \brief enable the SD I/O suspend operation(SD I/O only) + \param[in] none + \param[out] none + \retval none +*/ +void sdio_suspend_enable(void) +{ + SDIO_CMDCTL |= SDIO_CMDCTL_SUSPEND; +} + +/*! + \brief disable the SD I/O suspend operation(SD I/O only) + \param[in] none + \param[out] none + \retval none +*/ +void sdio_suspend_disable(void) +{ + SDIO_CMDCTL &= ~SDIO_CMDCTL_SUSPEND; +} + +/*! + \brief enable the CE-ATA command(CE-ATA only) + \param[in] none + \param[out] none + \retval none +*/ +void sdio_ceata_command_enable(void) +{ + SDIO_CMDCTL |= SDIO_CMDCTL_ATAEN; +} + +/*! + \brief disable the CE-ATA command(CE-ATA only) + \param[in] none + \param[out] none + \retval none +*/ +void sdio_ceata_command_disable(void) +{ + SDIO_CMDCTL &= ~SDIO_CMDCTL_ATAEN; +} + +/*! + \brief enable the CE-ATA interrupt(CE-ATA only) + \param[in] none + \param[out] none + \retval none +*/ +void sdio_ceata_interrupt_enable(void) +{ + SDIO_CMDCTL &= ~SDIO_CMDCTL_NINTEN; +} + +/*! + \brief disable the CE-ATA interrupt(CE-ATA only) + \param[in] none + \param[out] none + \retval none +*/ +void sdio_ceata_interrupt_disable(void) +{ + SDIO_CMDCTL |= SDIO_CMDCTL_NINTEN; +} + +/*! + \brief enable the CE-ATA command completion signal(CE-ATA only) + \param[in] none + \param[out] none + \retval none +*/ +void sdio_ceata_command_completion_enable(void) +{ + SDIO_CMDCTL |= SDIO_CMDCTL_ENCMDC; +} + +/*! + \brief disable the CE-ATA command completion signal(CE-ATA only) + \param[in] none + \param[out] none + \retval none +*/ +void sdio_ceata_command_completion_disable(void) +{ + SDIO_CMDCTL &= ~SDIO_CMDCTL_ENCMDC; +} + +/*! + \brief get the flags state of SDIO + \param[in] flag: flags state of SDIO + only one parameter can be selected which is shown as below: + \arg SDIO_FLAG_CCRCERR: command response received (CRC check failed) flag + \arg SDIO_FLAG_DTCRCERR: data block sent/received (CRC check failed) flag + \arg SDIO_FLAG_CMDTMOUT: command response timeout flag + \arg SDIO_FLAG_DTTMOUT: data timeout flag + \arg SDIO_FLAG_TXURE: transmit FIFO underrun error occurs flag + \arg SDIO_FLAG_RXORE: received FIFO overrun error occurs flag + \arg SDIO_FLAG_CMDRECV: command response received (CRC check passed) flag + \arg SDIO_FLAG_CMDSEND: command sent (no response required) flag + \arg SDIO_FLAG_DTEND: data end (data counter, SDIO_DATACNT, is zero) flag + \arg SDIO_FLAG_STBITE: start bit error in the bus flag + \arg SDIO_FLAG_DTBLKEND: data block sent/received (CRC check passed) flag + \arg SDIO_FLAG_CMDRUN: command transmission in progress flag + \arg SDIO_FLAG_TXRUN: data transmission in progress flag + \arg SDIO_FLAG_RXRUN: data reception in progress flag + \arg SDIO_FLAG_TFH: transmit FIFO is half empty flag: at least 8 words can be written into the FIFO + \arg SDIO_FLAG_RFH: receive FIFO is half full flag: at least 8 words can be read in the FIFO + \arg SDIO_FLAG_TFF: transmit FIFO is full flag + \arg SDIO_FLAG_RFF: receive FIFO is full flag + \arg SDIO_FLAG_TFE: transmit FIFO is empty flag + \arg SDIO_FLAG_RFE: receive FIFO is empty flag + \arg SDIO_FLAG_TXDTVAL: data is valid in transmit FIFO flag + \arg SDIO_FLAG_RXDTVAL: data is valid in receive FIFO flag + \arg SDIO_FLAG_SDIOINT: SD I/O interrupt received flag + \arg SDIO_FLAG_ATAEND: CE-ATA command completion signal received (only for CMD61) flag + \param[out] none + \retval FlagStatus: SET or RESET +*/ +FlagStatus sdio_flag_get(uint32_t flag) +{ + FlagStatus temp_flag = RESET; + if(RESET != (SDIO_STAT & flag)){ + temp_flag = SET; + } + return temp_flag; +} + +/*! + \brief clear the pending flags of SDIO + \param[in] flag: flags state of SDIO + only one parameter can be selected which is shown as below: + \arg SDIO_FLAG_CCRCERR: command response received (CRC check failed) flag + \arg SDIO_FLAG_DTCRCERR: data block sent/received (CRC check failed) flag + \arg SDIO_FLAG_CMDTMOUT: command response timeout flag + \arg SDIO_FLAG_DTTMOUT: data timeout flag + \arg SDIO_FLAG_TXURE: transmit FIFO underrun error occurs flag + \arg SDIO_FLAG_RXORE: received FIFO overrun error occurs flag + \arg SDIO_FLAG_CMDRECV: command response received (CRC check passed) flag + \arg SDIO_FLAG_CMDSEND: command sent (no response required) flag + \arg SDIO_FLAG_DTEND: data end (data counter, SDIO_DATACNT, is zero) flag + \arg SDIO_FLAG_STBITE: start bit error in the bus flag + \arg SDIO_FLAG_DTBLKEND: data block sent/received (CRC check passed) flag + \arg SDIO_FLAG_SDIOINT: SD I/O interrupt received flag + \arg SDIO_FLAG_ATAEND: CE-ATA command completion signal received (only for CMD61) flag + \param[out] none + \retval none +*/ +void sdio_flag_clear(uint32_t flag) +{ + SDIO_INTC = flag; +} + +/*! + \brief enable the SDIO interrupt + \param[in] int_flag: interrupt flags state of SDIO + only one parameter can be selected which is shown as below: + \arg SDIO_INT_CCRCERR: SDIO CCRCERR interrupt + \arg SDIO_INT_DTCRCERR: SDIO DTCRCERR interrupt + \arg SDIO_INT_CMDTMOUT: SDIO CMDTMOUT interrupt + \arg SDIO_INT_DTTMOUT: SDIO DTTMOUT interrupt + \arg SDIO_INT_TXURE: SDIO TXURE interrupt + \arg SDIO_INT_RXORE: SDIO RXORE interrupt + \arg SDIO_INT_CMDRECV: SDIO CMDRECV interrupt + \arg SDIO_INT_CMDSEND: SDIO CMDSEND interrupt + \arg SDIO_INT_DTEND: SDIO DTEND interrupt + \arg SDIO_INT_STBITE: SDIO STBITE interrupt + \arg SDIO_INT_DTBLKEND: SDIO DTBLKEND interrupt + \arg SDIO_INT_CMDRUN: SDIO CMDRUN interrupt + \arg SDIO_INT_TXRUN: SDIO TXRUN interrupt + \arg SDIO_INT_RXRUN: SDIO RXRUN interrupt + \arg SDIO_INT_TFH: SDIO TFH interrupt + \arg SDIO_INT_RFH: SDIO RFH interrupt + \arg SDIO_INT_TFF: SDIO TFF interrupt + \arg SDIO_INT_RFF: SDIO RFF interrupt + \arg SDIO_INT_TFE: SDIO TFE interrupt + \arg SDIO_INT_RFE: SDIO RFE interrupt + \arg SDIO_INT_TXDTVAL: SDIO TXDTVAL interrupt + \arg SDIO_INT_RXDTVAL: SDIO RXDTVAL interrupt + \arg SDIO_INT_SDIOINT: SDIO SDIOINT interrupt + \arg SDIO_INT_ATAEND: SDIO ATAEND interrupt + \param[out] none + \retval none +*/ +void sdio_interrupt_enable(uint32_t int_flag) +{ + SDIO_INTEN |= int_flag; +} + +/*! + \brief disable the SDIO interrupt + \param[in] int_flag: interrupt flags state of SDIO + only one parameter can be selected which is shown as below: + \arg SDIO_INT_CCRCERR: SDIO CCRCERR interrupt + \arg SDIO_INT_DTCRCERR: SDIO DTCRCERR interrupt + \arg SDIO_INT_CMDTMOUT: SDIO CMDTMOUT interrupt + \arg SDIO_INT_DTTMOUT: SDIO DTTMOUT interrupt + \arg SDIO_INT_TXURE: SDIO TXURE interrupt + \arg SDIO_INT_RXORE: SDIO RXORE interrupt + \arg SDIO_INT_CMDRECV: SDIO CMDRECV interrupt + \arg SDIO_INT_CMDSEND: SDIO CMDSEND interrupt + \arg SDIO_INT_DTEND: SDIO DTEND interrupt + \arg SDIO_INT_STBITE: SDIO STBITE interrupt + \arg SDIO_INT_DTBLKEND: SDIO DTBLKEND interrupt + \arg SDIO_INT_CMDRUN: SDIO CMDRUN interrupt + \arg SDIO_INT_TXRUN: SDIO TXRUN interrupt + \arg SDIO_INT_RXRUN: SDIO RXRUN interrupt + \arg SDIO_INT_TFH: SDIO TFH interrupt + \arg SDIO_INT_RFH: SDIO RFH interrupt + \arg SDIO_INT_TFF: SDIO TFF interrupt + \arg SDIO_INT_RFF: SDIO RFF interrupt + \arg SDIO_INT_TFE: SDIO TFE interrupt + \arg SDIO_INT_RFE: SDIO RFE interrupt + \arg SDIO_INT_TXDTVAL: SDIO TXDTVAL interrupt + \arg SDIO_INT_RXDTVAL: SDIO RXDTVAL interrupt + \arg SDIO_INT_SDIOINT: SDIO SDIOINT interrupt + \arg SDIO_INT_ATAEND: SDIO ATAEND interrupt + \param[out] none + \retval none +*/ +void sdio_interrupt_disable(uint32_t int_flag) +{ + SDIO_INTEN &= ~int_flag; +} + +/*! + \brief get the interrupt flags state of SDIO + \param[in] int_flag: interrupt flags state of SDIO + only one parameter can be selected which is shown as below: + \arg SDIO_INT_FLAG_CCRCERR: SDIO CCRCERR interrupt + \arg SDIO_INT_FLAG_DTCRCERR: SDIO DTCRCERR interrupt + \arg SDIO_INT_FLAG_CMDTMOUT: SDIO CMDTMOUT interrupt + \arg SDIO_INT_FLAG_DTTMOUT: SDIO DTTMOUT interrupt + \arg SDIO_INT_FLAG_TXURE: SDIO TXURE interrupt + \arg SDIO_INT_FLAG_RXORE: SDIO RXORE interrupt + \arg SDIO_INT_FLAG_CMDRECV: SDIO CMDRECV interrupt + \arg SDIO_INT_FLAG_CMDSEND: SDIO CMDSEND interrupt + \arg SDIO_INT_FLAG_DTEND: SDIO DTEND interrupt + \arg SDIO_INT_FLAG_STBITE: SDIO STBITE interrupt + \arg SDIO_INT_FLAG_DTBLKEND: SDIO DTBLKEND interrupt + \arg SDIO_INT_FLAG_CMDRUN: SDIO CMDRUN interrupt + \arg SDIO_INT_FLAG_TXRUN: SDIO TXRUN interrupt + \arg SDIO_INT_FLAG_RXRUN: SDIO RXRUN interrupt + \arg SDIO_INT_FLAG_TFH: SDIO TFH interrupt + \arg SDIO_INT_FLAG_RFH: SDIO RFH interrupt + \arg SDIO_INT_FLAG_TFF: SDIO TFF interrupt + \arg SDIO_INT_FLAG_RFF: SDIO RFF interrupt + \arg SDIO_INT_FLAG_TFE: SDIO TFE interrupt + \arg SDIO_INT_FLAG_RFE: SDIO RFE interrupt + \arg SDIO_INT_FLAG_TXDTVAL: SDIO TXDTVAL interrupt + \arg SDIO_INT_FLAG_RXDTVAL: SDIO RXDTVAL interrupt + \arg SDIO_INT_FLAG_SDIOINT: SDIO SDIOINT interrupt + \arg SDIO_INT_FLAG_ATAEND: SDIO ATAEND interrupt + \param[out] none + \retval FlagStatus: SET or RESET +*/ +FlagStatus sdio_interrupt_flag_get(uint32_t int_flag) +{ + uint32_t state = 0U; + state = SDIO_STAT; + if(state & int_flag){ + state = SDIO_INTEN; + /* check whether the corresponding bit in SDIO_INTEN is set or not */ + if(state & int_flag){ + return SET; + } + } + return RESET; +} + +/*! + \brief clear the interrupt pending flags of SDIO + \param[in] int_flag: interrupt flags state of SDIO + only one parameter can be selected which is shown as below: + \arg SDIO_INT_FLAG_CCRCERR: command response received (CRC check failed) flag + \arg SDIO_INT_FLAG_DTCRCERR: data block sent/received (CRC check failed) flag + \arg SDIO_INT_FLAG_CMDTMOUT: command response timeout flag + \arg SDIO_INT_FLAG_DTTMOUT: data timeout flag + \arg SDIO_INT_FLAG_TXURE: transmit FIFO underrun error occurs flag + \arg SDIO_INT_FLAG_RXORE: received FIFO overrun error occurs flag + \arg SDIO_INT_FLAG_CMDRECV: command response received (CRC check passed) flag + \arg SDIO_INT_FLAG_CMDSEND: command sent (no response required) flag + \arg SDIO_INT_FLAG_DTEND: data end (data counter, SDIO_DATACNT, is zero) flag + \arg SDIO_INT_FLAG_STBITE: start bit error in the bus flag + \arg SDIO_INT_FLAG_DTBLKEND: data block sent/received (CRC check passed) flag + \arg SDIO_INT_FLAG_SDIOINT: SD I/O interrupt received flag + \arg SDIO_INT_FLAG_ATAEND: CE-ATA command completion signal received (only for CMD61) flag + \param[out] none + \retval none +*/ +void sdio_interrupt_flag_clear(uint32_t int_flag) +{ + SDIO_INTC = int_flag; +} diff --git a/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_standard_peripheral/Source/gd32f20x_spi.c b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_standard_peripheral/Source/gd32f20x_spi.c new file mode 100644 index 0000000000..93cea07bf9 --- /dev/null +++ b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_standard_peripheral/Source/gd32f20x_spi.c @@ -0,0 +1,782 @@ +/*! + \file gd32f20x_spi.c + \brief SPI driver + + \version 2015-07-15, V1.0.0, firmware for GD32F20x + \version 2017-06-05, V2.0.0, firmware for GD32F20x + \version 2018-10-31, V2.1.0, firmware for GD32F20x + \version 2020-09-30, V2.2.0, firmware for GD32F20x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "gd32f20x_spi.h" + +/* SPI/I2S parameter initialization mask */ +#define SPI_INIT_MASK ((uint32_t)0x00003040U) /*!< SPI parameter initialization mask */ +#define I2S_INIT_MASK ((uint32_t)0x0000F047U) /*!< I2S parameter initialization mask */ + +/* I2S clock source selection, multiplication and division mask */ +#define I2S1_CLOCK_SEL ((uint32_t)0x00020000U) /* I2S1 clock source selection */ +#define I2S2_CLOCK_SEL ((uint32_t)0x00040000U) /* I2S2 clock source selection */ +#define I2S_CLOCK_MUL_MASK ((uint32_t)0x0000F000U) /* I2S clock multiplication mask */ +#define I2S_CLOCK_DIV_MASK ((uint32_t)0x000000F0U) /* I2S clock division mask */ + +/* default value and offset */ +#define SPI_I2SPSC_DEFAULT_VALUE ((uint32_t)0x00000002U) /* default value of SPI_I2SPSC register */ +#define RCU_CFG1_PREDV1_OFFSET 4U /* PREDV1 offset in RCU_CFG1 */ +#define RCU_CFG1_PLL2MF_OFFSET 12U /* PLL2MF offset in RCU_CFG1 */ + +/*! + \brief reset SPI and I2S + \param[in] spi_periph: SPIx(x=0,1,2) + \param[out] none + \retval none +*/ +void spi_i2s_deinit(uint32_t spi_periph) +{ + switch(spi_periph){ + case SPI0: + /* reset SPI0 */ + rcu_periph_reset_enable(RCU_SPI0RST); + rcu_periph_reset_disable(RCU_SPI0RST); + break; + case SPI1: + /* reset SPI1 and I2S1 */ + rcu_periph_reset_enable(RCU_SPI1RST); + rcu_periph_reset_disable(RCU_SPI1RST); + break; + case SPI2: + /* reset SPI2 and I2S2 */ + rcu_periph_reset_enable(RCU_SPI2RST); + rcu_periph_reset_disable(RCU_SPI2RST); + break; + default : + break; + } +} + +/*! + \brief initialize the parameters of SPI struct with the default values + \param[in] spi_struct: SPI parameter stuct + \param[out] none + \retval none +*/ +void spi_struct_para_init(spi_parameter_struct* spi_struct) +{ + /* set the SPI struct with the default values */ + spi_struct->device_mode = SPI_SLAVE; + spi_struct->trans_mode = SPI_TRANSMODE_FULLDUPLEX; + spi_struct->frame_size = SPI_FRAMESIZE_8BIT; + spi_struct->nss = SPI_NSS_HARD; + spi_struct->clock_polarity_phase = SPI_CK_PL_LOW_PH_1EDGE; + spi_struct->prescale = SPI_PSC_2; +} + +/*! + \brief initialize SPI parameter + \param[in] spi_periph: SPIx(x=0,1,2) + \param[in] spi_struct: SPI parameter initialization stuct members of the structure + and the member values are shown as below: + device_mode: SPI_MASTER, SPI_SLAVE + trans_mode: SPI_TRANSMODE_FULLDUPLEX, SPI_TRANSMODE_RECEIVEONLY, + SPI_TRANSMODE_BDRECEIVE, SPI_TRANSMODE_BDTRANSMIT + frame_size: SPI_FRAMESIZE_16BIT, SPI_FRAMESIZE_8BIT + nss: SPI_NSS_SOFT, SPI_NSS_HARD + endian: SPI_ENDIAN_MSB, SPI_ENDIAN_LSB + clock_polarity_phase: SPI_CK_PL_LOW_PH_1EDGE, SPI_CK_PL_HIGH_PH_1EDGE + SPI_CK_PL_LOW_PH_2EDGE, SPI_CK_PL_HIGH_PH_2EDGE + prescale: SPI_PSC_n (n=2,4,8,16,32,64,128,256) + \param[out] none + \retval none +*/ +void spi_init(uint32_t spi_periph, spi_parameter_struct* spi_struct) +{ + uint32_t reg = 0U; + reg = SPI_CTL0(spi_periph); + reg &= SPI_INIT_MASK; + + /* select SPI as master or slave */ + reg |= spi_struct->device_mode; + /* select SPI transfer mode */ + reg |= spi_struct->trans_mode; + /* select SPI frame size */ + reg |= spi_struct->frame_size; + /* select SPI NSS use hardware or software */ + reg |= spi_struct->nss; + /* select SPI LSB or MSB */ + reg |= spi_struct->endian; + /* select SPI polarity and phase */ + reg |= spi_struct->clock_polarity_phase; + /* select SPI prescale to adjust transmit speed */ + reg |= spi_struct->prescale; + + /* write to SPI_CTL0 register */ + SPI_CTL0(spi_periph) = (uint32_t)reg; + + SPI_I2SCTL(spi_periph) &= (uint32_t)(~SPI_I2SCTL_I2SSEL); +} + +/*! + \brief enable SPI + \param[in] spi_periph: SPIx(x=0,1,2) + \param[out] none + \retval none +*/ +void spi_enable(uint32_t spi_periph) +{ + SPI_CTL0(spi_periph) |= (uint32_t)SPI_CTL0_SPIEN; +} + +/*! + \brief disable SPI + \param[in] spi_periph: SPIx(x=0,1,2) + \param[out] none + \retval none +*/ +void spi_disable(uint32_t spi_periph) +{ + SPI_CTL0(spi_periph) &= (uint32_t)(~SPI_CTL0_SPIEN); +} + +/*! + \brief initialize I2S parameter + \param[in] spi_periph: SPIx(x=1,2) + \param[in] mode: I2S operation mode + only one parameter can be selected which is shown as below: + \arg I2S_MODE_SLAVETX: I2S slave transmit mode + \arg I2S_MODE_SLAVERX: I2S slave receive mode + \arg I2S_MODE_MASTERTX: I2S master transmit mode + \arg I2S_MODE_MASTERRX: I2S master receive mode + \param[in] standard: I2S standard + only one parameter can be selected which is shown as below: + \arg I2S_STD_PHILLIPS: I2S phillips standard + \arg I2S_STD_MSB: I2S MSB standard + \arg I2S_STD_LSB: I2S LSB standard + \arg I2S_STD_PCMSHORT: I2S PCM short standard + \arg I2S_STD_PCMLONG: I2S PCM long standard + \param[in] ckpl: I2S idle state clock polarity + only one parameter can be selected which is shown as below: + \arg I2S_CKPL_LOW: I2S clock polarity low level + \arg I2S_CKPL_HIGH: I2S clock polarity high level + \param[out] none + \retval none +*/ +void i2s_init(uint32_t spi_periph, uint32_t mode, uint32_t standard, uint32_t ckpl) +{ + uint32_t reg = 0U; + reg = SPI_I2SCTL(spi_periph); + reg &= I2S_INIT_MASK; + + /* enable I2S mode */ + reg |= (uint32_t)SPI_I2SCTL_I2SSEL; + /* select I2S mode */ + reg |= (uint32_t)mode; + /* select I2S standard */ + reg |= (uint32_t)standard; + /* select I2S polarity */ + reg |= (uint32_t)ckpl; + + /* write to SPI_I2SCTL register */ + SPI_I2SCTL(spi_periph) = (uint32_t)reg; +} + +/*! + \brief configure I2S prescaler + \param[in] spi_periph: SPIx(x=1,2) + \param[in] audiosample: I2S audio sample rate + only one parameter can be selected which is shown as below: + \arg I2S_AUDIOSAMPLE_8K: audio sample rate is 8KHz + \arg I2S_AUDIOSAMPLE_11K: audio sample rate is 11KHz + \arg I2S_AUDIOSAMPLE_16K: audio sample rate is 16KHz + \arg I2S_AUDIOSAMPLE_22K: audio sample rate is 22KHz + \arg I2S_AUDIOSAMPLE_32K: audio sample rate is 32KHz + \arg I2S_AUDIOSAMPLE_44K: audio sample rate is 44KHz + \arg I2S_AUDIOSAMPLE_48K: audio sample rate is 48KHz + \arg I2S_AUDIOSAMPLE_96K: audio sample rate is 96KHz + \arg I2S_AUDIOSAMPLE_192K: audio sample rate is 192KHz + \param[in] frameformat: I2S data length and channel length + only one parameter can be selected which is shown as below: + \arg I2S_FRAMEFORMAT_DT16B_CH16B: I2S data length is 16 bit and channel length is 16 bit + \arg I2S_FRAMEFORMAT_DT16B_CH32B: I2S data length is 16 bit and channel length is 32 bit + \arg I2S_FRAMEFORMAT_DT24B_CH32B: I2S data length is 24 bit and channel length is 32 bit + \arg I2S_FRAMEFORMAT_DT32B_CH32B: I2S data length is 32 bit and channel length is 32 bit + \param[in] mckout: I2S master clock output + only one parameter can be selected which is shown as below: + \arg I2S_MCKOUT_ENABLE: I2S master clock output enable + \arg I2S_MCKOUT_DISABLE: I2S master clock output disable + \param[out] none + \retval none +*/ +void i2s_psc_config(uint32_t spi_periph, uint32_t audiosample, uint32_t frameformat, uint32_t mckout) +{ + uint32_t i2sdiv = 2U, i2sof = 0U; + uint32_t clks = 0U; + uint32_t i2sclock = 0U; + + /* deinit SPI_I2SPSC register */ + SPI_I2SPSC(spi_periph) = SPI_I2SPSC_DEFAULT_VALUE; + + /* get the I2S clock source */ + if(SPI1 == ((uint32_t)spi_periph)){ + /* I2S1 clock source selection */ + clks = I2S1_CLOCK_SEL; + }else{ + /* I2S2 clock source selection */ + clks = I2S2_CLOCK_SEL; + } + + if(0U != (RCU_CFG1 & clks)){ + /* get RCU PLL2 clock multiplication factor */ + clks = (uint32_t)((RCU_CFG1 & I2S_CLOCK_MUL_MASK) >> RCU_CFG1_PLL2MF_OFFSET); + + if((clks > 5U) && (clks < 15U)){ + /* multiplier is between 8 and 14 */ + clks += 2U; + }else{ + if(15U == clks){ + /* multiplier is 20 */ + clks = 20U; + } + } + + /* get the PREDV1 value */ + i2sclock = (uint32_t)(((RCU_CFG1 & I2S_CLOCK_DIV_MASK) >> RCU_CFG1_PREDV1_OFFSET) + 1U); + /* calculate I2S clock based on PLL2 and PREDV1 */ + i2sclock = (uint32_t)((HXTAL_VALUE / i2sclock) * clks * 2U); + }else{ + /* get system clock */ + i2sclock = rcu_clock_freq_get(CK_SYS); + } + + /* config the prescaler depending on the mclk output state, the frame format and audio sample rate */ + if(I2S_MCKOUT_ENABLE == mckout){ + clks = (uint32_t)(((i2sclock / 256U) * 10U) / audiosample); + }else{ + if(I2S_FRAMEFORMAT_DT16B_CH16B == frameformat){ + clks = (uint32_t)(((i2sclock / 32U) *10U ) / audiosample); + }else{ + clks = (uint32_t)(((i2sclock / 64U) *10U ) / audiosample); + } + } + + /* remove the floating point */ + clks = (clks + 5U) / 10U; + i2sof = (clks & 0x00000001U); + i2sdiv = ((clks - i2sof) / 2U); + i2sof = (i2sof << 8U); + + /* set the default values */ + if((i2sdiv < 2U) || (i2sdiv > 255U)){ + i2sdiv = 2U; + i2sof = 0U; + } + + /* configure SPI_I2SPSC */ + SPI_I2SPSC(spi_periph) = (uint32_t)(i2sdiv | i2sof | mckout); + + /* clear SPI_I2SCTL_DTLEN and SPI_I2SCTL_CHLEN bits */ + SPI_I2SCTL(spi_periph) &= (uint32_t)(~(SPI_I2SCTL_DTLEN | SPI_I2SCTL_CHLEN)); + /* configure data frame format */ + SPI_I2SCTL(spi_periph) |= (uint32_t)frameformat; +} + +/*! + \brief enable I2S + \param[in] spi_periph: SPIx(x=1,2) + \param[out] none + \retval none +*/ +void i2s_enable(uint32_t spi_periph) +{ + SPI_I2SCTL(spi_periph) |= (uint32_t)SPI_I2SCTL_I2SEN; +} + +/*! + \brief disable I2S + \param[in] spi_periph: SPIx(x=1,2) + \param[out] none + \retval none +*/ +void i2s_disable(uint32_t spi_periph) +{ + SPI_I2SCTL(spi_periph) &= (uint32_t)(~SPI_I2SCTL_I2SEN); +} + +/*! + \brief enable SPI NSS output + \param[in] spi_periph: SPIx(x=0,1,2) + \param[out] none + \retval none +*/ +void spi_nss_output_enable(uint32_t spi_periph) +{ + SPI_CTL1(spi_periph) |= (uint32_t)SPI_CTL1_NSSDRV; +} + +/*! + \brief disable SPI NSS output + \param[in] spi_periph: SPIx(x=0,1,2) + \param[out] none + \retval none +*/ +void spi_nss_output_disable(uint32_t spi_periph) +{ + SPI_CTL1(spi_periph) &= (uint32_t)(~SPI_CTL1_NSSDRV); +} + +/*! + \brief SPI NSS pin high level in software mode + \param[in] spi_periph: SPIx(x=0,1,2) + \param[out] none + \retval none +*/ +void spi_nss_internal_high(uint32_t spi_periph) +{ + SPI_CTL0(spi_periph) |= (uint32_t)SPI_CTL0_SWNSS; +} + +/*! + \brief SPI NSS pin low level in software mode + \param[in] spi_periph: SPIx(x=0,1,2) + \param[out] none + \retval none +*/ +void spi_nss_internal_low(uint32_t spi_periph) +{ + SPI_CTL0(spi_periph) &= (uint32_t)(~SPI_CTL0_SWNSS); +} + +/*! + \brief enable SPI DMA send or receive + \param[in] spi_periph: SPIx(x=0,1,2) + \param[in] dma: SPI DMA mode + only one parameter can be selected which is shown as below: + \arg SPI_DMA_TRANSMIT: SPI transmit data using DMA + \arg SPI_DMA_RECEIVE: SPI receive data using DMA + \param[out] none + \retval none +*/ +void spi_dma_enable(uint32_t spi_periph, uint8_t dma) +{ + if(SPI_DMA_TRANSMIT == dma){ + SPI_CTL1(spi_periph) |= (uint32_t)SPI_CTL1_DMATEN; + }else{ + SPI_CTL1(spi_periph) |= (uint32_t)SPI_CTL1_DMAREN; + } +} + +/*! + \brief disable SPI DMA send or receive + \param[in] spi_periph: SPIx(x=0,1,2) + \param[in] dma: SPI DMA mode + only one parameter can be selected which is shown as below: + \arg SPI_DMA_TRANSMIT: SPI transmit data using DMA + \arg SPI_DMA_RECEIVE: SPI receive data using DMA + \param[out] none + \retval none +*/ +void spi_dma_disable(uint32_t spi_periph, uint8_t dma) +{ + if(SPI_DMA_TRANSMIT == dma){ + SPI_CTL1(spi_periph) &= (uint32_t)(~SPI_CTL1_DMATEN); + }else{ + SPI_CTL1(spi_periph) &= (uint32_t)(~SPI_CTL1_DMAREN); + } +} + +/*! + \brief configure SPI/I2S data frame format + \param[in] spi_periph: SPIx(x=0,1,2) + \param[in] frame_format: SPI frame size + only one parameter can be selected which is shown as below: + \arg SPI_FRAMESIZE_16BIT: SPI frame size is 16 bits + \arg SPI_FRAMESIZE_8BIT: SPI frame size is 8 bits + \param[out] none + \retval none +*/ +void spi_i2s_data_frame_format_config(uint32_t spi_periph, uint16_t frame_format) +{ + /* clear SPI_CTL0_FF16 bit */ + SPI_CTL0(spi_periph) &= (uint32_t)(~SPI_CTL0_FF16); + /* configure SPI_CTL0_FF16 bit */ + SPI_CTL0(spi_periph) |= (uint32_t)frame_format; +} + +/*! + \brief SPI transmit data + \param[in] spi_periph: SPIx(x=0,1,2) + \param[in] data: 16-bit data + \param[out] none + \retval none +*/ +void spi_i2s_data_transmit(uint32_t spi_periph, uint16_t data) +{ + SPI_DATA(spi_periph) = (uint32_t)data; +} + +/*! + \brief SPI receive data + \param[in] spi_periph: SPIx(x=0,1,2) + \param[out] none + \retval 16-bit data +*/ +uint16_t spi_i2s_data_receive(uint32_t spi_periph) +{ + return ((uint16_t)SPI_DATA(spi_periph)); +} + +/*! + \brief configure SPI bidirectional transfer direction + \param[in] spi_periph: SPIx(x=0,1,2) + \param[in] transfer_direction: SPI transfer direction + only one parameter can be selected which is shown as below: + \arg SPI_BIDIRECTIONAL_TRANSMIT: SPI work in transmit-only mode + \arg SPI_BIDIRECTIONAL_RECEIVE: SPI work in receive-only mode + \param[out] none + \retval none +*/ +void spi_bidirectional_transfer_config(uint32_t spi_periph, uint32_t transfer_direction) +{ + if(SPI_BIDIRECTIONAL_TRANSMIT == transfer_direction){ + /* set the transmit only mode */ + SPI_CTL0(spi_periph) |= (uint32_t)SPI_BIDIRECTIONAL_TRANSMIT; + }else{ + /* set the receive only mode */ + SPI_CTL0(spi_periph) &= SPI_BIDIRECTIONAL_RECEIVE; + } +} + +/*! + \brief set CRC polynomial + \param[in] spi_periph: SPIx(x=0,1,2) + \param[in] crc_poly: CRC polynomial value + \param[out] none + \retval none +*/ +void spi_crc_polynomial_set(uint32_t spi_periph, uint16_t crc_poly) +{ + /* enable SPI CRC */ + SPI_CTL0(spi_periph) |= (uint32_t)SPI_CTL0_CRCEN; + /* set SPI CRC polynomial */ + SPI_CRCPOLY(spi_periph) = (uint32_t)crc_poly; +} + +/*! + \brief get SPI CRC polynomial + \param[in] spi_periph: SPIx(x=0,1,2) + \param[out] none + \retval 16-bit CRC polynomial +*/ +uint16_t spi_crc_polynomial_get(uint32_t spi_periph) +{ + return ((uint16_t)SPI_CRCPOLY(spi_periph)); +} + +/*! + \brief turn on CRC function + \param[in] spi_periph: SPIx(x=0,1,2) + \param[out] none + \retval none +*/ +void spi_crc_on(uint32_t spi_periph) +{ + SPI_CTL0(spi_periph) |= (uint32_t)SPI_CTL0_CRCEN; +} + +/*! + \brief turn off CRC function + \param[in] spi_periph: SPIx(x=0,1,2) + \param[out] none + \retval none +*/ +void spi_crc_off(uint32_t spi_periph) +{ + SPI_CTL0(spi_periph) &= (uint32_t)(~SPI_CTL0_CRCEN); +} + +/*! + \brief SPI next data is CRC value + \param[in] spi_periph: SPIx(x=0,1,2) + \param[out] none + \retval none +*/ +void spi_crc_next(uint32_t spi_periph) +{ + SPI_CTL0(spi_periph) |= (uint32_t)SPI_CTL0_CRCNT; +} + +/*! + \brief get SPI CRC send value or receive value + \param[in] spi_periph: SPIx(x=0,1,2) + \param[in] crc: SPI crc value + only one parameter can be selected which is shown as below: + \arg SPI_CRC_TX: get transmit crc value + \arg SPI_CRC_RX: get receive crc value + \param[out] none + \retval 16-bit CRC value +*/ +uint16_t spi_crc_get(uint32_t spi_periph, uint8_t crc) +{ + if(SPI_CRC_TX == crc){ + return ((uint16_t)(SPI_TCRC(spi_periph))); + }else{ + return ((uint16_t)(SPI_RCRC(spi_periph))); + } +} + +/*! + \brief enable SPI and I2S interrupt + \param[in] spi_periph: SPIx(x=0,1,2) + \param[in] interrupt: SPI/I2S interrupt + only one parameter can be selected which is shown as below: + \arg SPI_I2S_INT_TBE: transmit buffer empty interrupt + \arg SPI_I2S_INT_RBNE: receive buffer not empty interrupt + \arg SPI_I2S_INT_ERR: CRC error,configuration error,reception overrun error, + transmission underrun error and format error interrupt + \param[out] none + \retval none +*/ +void spi_i2s_interrupt_enable(uint32_t spi_periph, uint8_t interrupt) +{ + switch(interrupt){ + /* SPI/I2S transmit buffer empty interrupt */ + case SPI_I2S_INT_TBE: + SPI_CTL1(spi_periph) |= (uint32_t)SPI_CTL1_TBEIE; + break; + /* SPI/I2S receive buffer not empty interrupt */ + case SPI_I2S_INT_RBNE: + SPI_CTL1(spi_periph) |= (uint32_t)SPI_CTL1_RBNEIE; + break; + /* SPI/I2S error */ + case SPI_I2S_INT_ERR: + SPI_CTL1(spi_periph) |= (uint32_t)SPI_CTL1_ERRIE; + break; + default: + break; + } +} + +/*! + \brief disable SPI and I2S interrupt + \param[in] spi_periph: SPIx(x=0,1,2) + \param[in] interrupt: SPI/I2S interrupt + only one parameter can be selected which is shown as below: + \arg SPI_I2S_INT_TBE: transmit buffer empty interrupt + \arg SPI_I2S_INT_RBNE: receive buffer not empty interrupt + \arg SPI_I2S_INT_ERR: CRC error,configuration error,reception overrun error, + transmission underrun error and format error interrupt + \param[out] none + \retval none +*/ +void spi_i2s_interrupt_disable(uint32_t spi_periph, uint8_t interrupt) +{ + switch(interrupt){ + /* SPI/I2S transmit buffer empty interrupt */ + case SPI_I2S_INT_TBE: + SPI_CTL1(spi_periph) &= (uint32_t)(~SPI_CTL1_TBEIE); + break; + /* SPI/I2S receive buffer not empty interrupt */ + case SPI_I2S_INT_RBNE: + SPI_CTL1(spi_periph) &= (uint32_t)(~SPI_CTL1_RBNEIE); + break; + /* SPI/I2S error */ + case SPI_I2S_INT_ERR: + SPI_CTL1(spi_periph) &= (uint32_t)(~SPI_CTL1_ERRIE); + break; + default : + break; + } +} + +/*! + \brief get SPI and I2S interrupt flag status + \param[in] spi_periph: SPIx(x=0,1,2) + \param[in] interrupt: SPI/I2S interrupt flag status + only one parameter can be selected which is shown as below: + \arg SPI_I2S_INT_FLAG_TBE: transmit buffer empty interrupt flag + \arg SPI_I2S_INT_FLAG_RBNE: receive buffer not empty interrupt flag + \arg SPI_I2S_INT_FLAG_RXORERR: overrun interrupt flag + \arg SPI_INT_FLAG_CONFERR: config error interrupt flag + \arg SPI_INT_FLAG_CRCERR: CRC error interrupt flag + \arg I2S_INT_FLAG_TXURERR: underrun error interrupt flag + \param[out] none + \retval FlagStatus: SET or RESET +*/ +FlagStatus spi_i2s_interrupt_flag_get(uint32_t spi_periph, uint8_t interrupt) +{ + uint32_t reg1 = SPI_STAT(spi_periph); + uint32_t reg2 = SPI_CTL1(spi_periph); + + switch(interrupt){ + /* SPI/I2S transmit buffer empty interrupt */ + case SPI_I2S_INT_FLAG_TBE: + reg1 = reg1 & SPI_STAT_TBE; + reg2 = reg2 & SPI_CTL1_TBEIE; + break; + /* SPI/I2S receive buffer not empty interrupt */ + case SPI_I2S_INT_FLAG_RBNE: + reg1 = reg1 & SPI_STAT_RBNE; + reg2 = reg2 & SPI_CTL1_RBNEIE; + break; + /* SPI/I2S overrun interrupt */ + case SPI_I2S_INT_FLAG_RXORERR: + reg1 = reg1 & SPI_STAT_RXORERR; + reg2 = reg2 & SPI_CTL1_ERRIE; + break; + /* SPI config error interrupt */ + case SPI_INT_FLAG_CONFERR: + reg1 = reg1 & SPI_STAT_CONFERR; + reg2 = reg2 & SPI_CTL1_ERRIE; + break; + /* SPI CRC error interrupt */ + case SPI_INT_FLAG_CRCERR: + reg1 = reg1 & SPI_STAT_CRCERR; + reg2 = reg2 & SPI_CTL1_ERRIE; + break; + /* I2S underrun error interrupt */ + case I2S_INT_FLAG_TXURERR: + reg1 = reg1 & SPI_STAT_TXURERR; + reg2 = reg2 & SPI_CTL1_ERRIE; + break; + default : + break; + } + /*get SPI/I2S interrupt flag status */ + if((0U != reg1) && (0U != reg2)){ + return SET; + }else{ + return RESET; + } +} + +/*! + \brief get SPI and I2S flag status + \param[in] spi_periph: SPIx(x=0,1,2) + \param[in] flag: SPI/I2S flag status + only one parameter can be selected which is shown as below: + \arg SPI_FLAG_TBE: transmit buffer empty flag + \arg SPI_FLAG_RBNE: receive buffer not empty flag + \arg SPI_FLAG_TRANS: transmit on-going flag + \arg SPI_FLAG_RXORERR: receive overrun error flag + \arg SPI_FLAG_CONFERR: mode config error flag + \arg SPI_FLAG_CRCERR: CRC error flag + \arg I2S_FLAG_TBE: transmit buffer empty flag + \arg I2S_FLAG_RBNE: receive buffer not empty flag + \arg I2S_FLAG_TRANS: transmit on-going flag + \arg I2S_FLAG_RXORERR: overrun error flag + \arg I2S_FLAG_TXURERR: underrun error flag + \arg I2S_FLAG_CH: channel side flag + \param[out] none + \retval FlagStatus: SET or RESET +*/ +FlagStatus spi_i2s_flag_get(uint32_t spi_periph, uint32_t flag) +{ + if(RESET != (SPI_STAT(spi_periph) & flag)){ + return SET; + }else{ + return RESET; + } +} + +/*! + \brief clear SPI CRC error flag status + \param[in] spi_periph: SPIx(x=0,1,2) + \param[out] none + \retval none +*/ +void spi_crc_error_clear(uint32_t spi_periph) +{ + SPI_STAT(spi_periph) &= (uint32_t)(~SPI_FLAG_CRCERR); +} + +/*! + \brief enable quad wire SPI + \param[in] spi_periph: SPIx(only x=0) + \param[out] none + \retval none +*/ +void qspi_enable(uint32_t spi_periph) +{ + SPI_QCTL(spi_periph) |= (uint32_t)SPI_QCTL_QMOD; +} + +/*! + \brief disable quad wire SPI + \param[in] spi_periph: SPIx(only x=0) + \param[out] none + \retval none +*/ +void qspi_disable(uint32_t spi_periph) +{ + SPI_QCTL(spi_periph) &= (uint32_t)(~SPI_QCTL_QMOD); +} + +/*! + \brief enable quad wire SPI write + \param[in] spi_periph: SPIx(only x=0) + \param[out] none + \retval none +*/ +void qspi_write_enable(uint32_t spi_periph) +{ + SPI_QCTL(spi_periph) &= (uint32_t)(~SPI_QCTL_QRD); +} + +/*! + \brief enable quad wire SPI read + \param[in] spi_periph: SPIx(only x=0) + \param[out] none + \retval none +*/ +void qspi_read_enable(uint32_t spi_periph) +{ + SPI_QCTL(spi_periph) |= (uint32_t)SPI_QCTL_QRD; +} + +/*! + \brief enable SPI_IO2 and SPI_IO3 pin output + \param[in] spi_periph: SPIx(only x=0) + \param[out] none + \retval none +*/ +void qspi_io23_output_enable(uint32_t spi_periph) +{ + SPI_QCTL(spi_periph) |= (uint32_t)SPI_QCTL_IO23_DRV; +} + + /*! + \brief disable SPI_IO2 and SPI_IO3 pin output + \param[in] spi_periph: SPIx(only x=0) + \param[out] none + \retval none +*/ +void qspi_io23_output_disable(uint32_t spi_periph) +{ + SPI_QCTL(spi_periph) &= (uint32_t)(~SPI_QCTL_IO23_DRV); +} diff --git a/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_standard_peripheral/Source/gd32f20x_timer.c b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_standard_peripheral/Source/gd32f20x_timer.c new file mode 100644 index 0000000000..cb160dad57 --- /dev/null +++ b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_standard_peripheral/Source/gd32f20x_timer.c @@ -0,0 +1,2000 @@ +/*! + \file gd32f20x_timer.c + \brief TIMER driver + + \version 2015-07-15, V1.0.0, firmware for GD32F20x + \version 2017-06-05, V2.0.0, firmware for GD32F20x + \version 2018-10-31, V2.1.0, firmware for GD32F20x + \version 2020-09-30, V2.2.0, firmware for GD32F20x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "gd32f20x_timer.h" +/* TIMER init parameter mask */ +#define ALIGNEDMODE_MASK ((uint32_t)0x00000060U) /*!< TIMER init parameter aligne dmode mask */ +#define COUNTERDIRECTION_MASK ((uint32_t)0x00000010U) /*!< TIMER init parameter counter direction mask */ +#define CLOCKDIVISION_MASK ((uint32_t)0x00000300U) /*!< TIMER init parameter clock division value mask */ + +/*! + \brief deinit a TIMER + \param[in] timer_periph: TIMERx(x=0..13) + \param[out] none + \retval none +*/ +void timer_deinit(uint32_t timer_periph) +{ + switch(timer_periph){ + case TIMER0: + /* reset TIMER0 */ + rcu_periph_reset_enable(RCU_TIMER0RST); + rcu_periph_reset_disable(RCU_TIMER0RST); + break; + case TIMER1: + /* reset TIMER1 */ + rcu_periph_reset_enable(RCU_TIMER1RST); + rcu_periph_reset_disable(RCU_TIMER1RST); + break; + case TIMER2: + /* reset TIMER2 */ + rcu_periph_reset_enable(RCU_TIMER2RST); + rcu_periph_reset_disable(RCU_TIMER2RST); + break; + case TIMER3: + /* reset TIMER3 */ + rcu_periph_reset_enable(RCU_TIMER3RST); + rcu_periph_reset_disable(RCU_TIMER3RST); + break; + case TIMER4: + /* reset TIMER4 */ + rcu_periph_reset_enable(RCU_TIMER4RST); + rcu_periph_reset_disable(RCU_TIMER4RST); + break; + case TIMER5: + /* reset TIMER5 */ + rcu_periph_reset_enable(RCU_TIMER5RST); + rcu_periph_reset_disable(RCU_TIMER5RST); + break; + case TIMER6: + /* reset TIMER6 */ + rcu_periph_reset_enable(RCU_TIMER6RST); + rcu_periph_reset_disable(RCU_TIMER6RST); + break; + case TIMER7: + /* reset TIMER7 */ + rcu_periph_reset_enable(RCU_TIMER7RST); + rcu_periph_reset_disable(RCU_TIMER7RST); + break; + case TIMER8: + /* reset TIMER8 */ + rcu_periph_reset_enable(RCU_TIMER8RST); + rcu_periph_reset_disable(RCU_TIMER8RST); + break; + case TIMER9: + /* reset TIMER9 */ + rcu_periph_reset_enable(RCU_TIMER9RST); + rcu_periph_reset_disable(RCU_TIMER9RST); + break; + case TIMER10: + /* reset TIMER10 */ + rcu_periph_reset_enable(RCU_TIMER10RST); + rcu_periph_reset_disable(RCU_TIMER10RST); + break; + case TIMER11: + /* reset TIMER11 */ + rcu_periph_reset_enable(RCU_TIMER11RST); + rcu_periph_reset_disable(RCU_TIMER11RST); + break; + case TIMER12: + /* reset TIMER12 */ + rcu_periph_reset_enable(RCU_TIMER12RST); + rcu_periph_reset_disable(RCU_TIMER12RST); + break; + case TIMER13: + /* reset TIMER13 */ + rcu_periph_reset_enable(RCU_TIMER13RST); + rcu_periph_reset_disable(RCU_TIMER13RST); + break; + default: + break; + } +} + +/*! + \brief initialize TIMER init parameter struct with a default value + \param[in] initpara: init parameter struct + \param[out] none + \retval none +*/ +void timer_struct_para_init(timer_parameter_struct* initpara) +{ + /* initialize the init parameter struct member with the default value */ + initpara->prescaler = 0U; + initpara->alignedmode = TIMER_COUNTER_EDGE; + initpara->counterdirection = TIMER_COUNTER_UP; + initpara->period = 65535U; + initpara->clockdivision = TIMER_CKDIV_DIV1; + initpara->repetitioncounter = 0U; +} + +/*! + \brief initialize TIMER counter + \param[in] timer_periph: TIMERx(x=0..13) + \param[in] initpara: init parameter struct + prescaler: prescaler value of the counter clock,0~65535 + alignedmode: TIMER_COUNTER_EDGE,TIMER_COUNTER_CENTER_DOWN,TIMER_COUNTER_CENTER_UP,TIMER_COUNTER_CENTER_BOTH + counterdirection: TIMER_COUNTER_UP,TIMER_COUNTER_DOWN + period: counter auto reload value,0~65535 + clockdivision: TIMER_CKDIV_DIV1,TIMER_CKDIV_DIV2,TIMER_CKDIV_DIV4 + repetitioncounter: counter repetition value,0~255 + \param[out] none + \retval none +*/ +void timer_init(uint32_t timer_periph, timer_parameter_struct* initpara) +{ + /* configure the counter prescaler value */ + TIMER_PSC(timer_periph) = (uint16_t)initpara->prescaler; + + /* configure the counter direction and aligned mode */ + if((TIMER0 == timer_periph) || (TIMER1 == timer_periph) || (TIMER2 == timer_periph) || (TIMER3 == timer_periph) || + (TIMER4 == timer_periph) || (TIMER7 == timer_periph) || (TIMER8 == timer_periph) || (TIMER9 == timer_periph) || + (TIMER10 == timer_periph) || (TIMER11 == timer_periph) || (TIMER12 == timer_periph) || (TIMER13 == timer_periph)){ + TIMER_CTL0(timer_periph) &= (~(uint32_t)(TIMER_CTL0_DIR | TIMER_CTL0_CAM)); + TIMER_CTL0(timer_periph) |= (uint32_t)(initpara->alignedmode & ALIGNEDMODE_MASK); + TIMER_CTL0(timer_periph) |= (uint32_t)(initpara->counterdirection & COUNTERDIRECTION_MASK); + } + + /* configure the autoreload value */ + TIMER_CAR(timer_periph) = (uint32_t)initpara->period; + + if((TIMER5 != timer_periph) && (TIMER6 != timer_periph)){ + /* reset the CKDIV bit */ + TIMER_CTL0(timer_periph) &= (~(uint32_t)TIMER_CTL0_CKDIV); + TIMER_CTL0(timer_periph) |= (uint32_t)(initpara->clockdivision & CLOCKDIVISION_MASK); + } + + if((TIMER0 == timer_periph) || (TIMER7 == timer_periph)){ + /* configure the repetition counter value */ + TIMER_CREP(timer_periph) = (uint32_t)initpara->repetitioncounter; + } + + /* generate an update event */ + TIMER_SWEVG(timer_periph) |= (uint32_t)TIMER_SWEVG_UPG; +} + +/*! + \brief enable a TIMER + \param[in] timer_periph: TIMERx(x=0..13) + \param[out] none + \retval none +*/ +void timer_enable(uint32_t timer_periph) +{ + TIMER_CTL0(timer_periph) |= (uint32_t)TIMER_CTL0_CEN; +} + +/*! + \brief disable a TIMER + \param[in] timer_periph: TIMERx(x=0..13) + \param[out] none + \retval none +*/ +void timer_disable(uint32_t timer_periph) +{ + TIMER_CTL0(timer_periph) &= ~(uint32_t)TIMER_CTL0_CEN; +} + +/*! + \brief enable the auto reload shadow function + \param[in] timer_periph: TIMERx(x=0..13) + \param[out] none + \retval none +*/ +void timer_auto_reload_shadow_enable(uint32_t timer_periph) +{ + TIMER_CTL0(timer_periph) |= (uint32_t)TIMER_CTL0_ARSE; +} + +/*! + \brief disable the auto reload shadow function + \param[in] timer_periph: TIMERx(x=0..13) + \param[out] none + \retval none +*/ +void timer_auto_reload_shadow_disable(uint32_t timer_periph) +{ + TIMER_CTL0(timer_periph) &= ~(uint32_t)TIMER_CTL0_ARSE; +} + +/*! + \brief enable the update event + \param[in] timer_periph: TIMERx(x=0..13) + \param[out] none + \retval none +*/ +void timer_update_event_enable(uint32_t timer_periph) +{ + TIMER_CTL0(timer_periph) &= ~(uint32_t)TIMER_CTL0_UPDIS; +} + +/*! + \brief disable the update event + \param[in] timer_periph: TIMERx(x=0..13) + \param[out] none + \retval none +*/ +void timer_update_event_disable(uint32_t timer_periph) +{ + TIMER_CTL0(timer_periph) |= (uint32_t) TIMER_CTL0_UPDIS; +} + +/*! + \brief set TIMER counter alignment mode + \param[in] timer_periph: TIMERx(x=0..4,7..13) + \param[in] aligned: + only one parameter can be selected which is shown as below: + \arg TIMER_COUNTER_EDGE: edge-aligned mode + \arg TIMER_COUNTER_CENTER_DOWN: center-aligned and counting down assert mode + \arg TIMER_COUNTER_CENTER_UP: center-aligned and counting up assert mode + \arg TIMER_COUNTER_CENTER_BOTH: center-aligned and counting up/down assert mode + \param[out] none + \retval none +*/ +void timer_counter_alignment(uint32_t timer_periph, uint16_t aligned) +{ + TIMER_CTL0(timer_periph) &= ~(uint32_t)TIMER_CTL0_CAM; + TIMER_CTL0(timer_periph) |= (uint32_t)aligned; +} + +/*! + \brief set TIMER counter up direction + \param[in] timer_periph: TIMERx(x=0..4,7..13) + \param[out] none + \retval none +*/ +void timer_counter_up_direction(uint32_t timer_periph) +{ + TIMER_CTL0(timer_periph) &= ~(uint32_t)TIMER_CTL0_DIR; +} + +/*! + \brief set TIMER counter down direction + \param[in] timer_periph: TIMERx(x=0..4,7..13) + \param[out] none + \retval none +*/ +void timer_counter_down_direction(uint32_t timer_periph) +{ + TIMER_CTL0(timer_periph) |= (uint32_t)TIMER_CTL0_DIR; +} + +/*! + \brief configure TIMER prescaler + \param[in] timer_periph: TIMERx(x=0..13) + \param[in] prescaler: prescaler value + \param[in] pscreload: prescaler reload mode + only one parameter can be selected which is shown as below: + \arg TIMER_PSC_RELOAD_NOW: the prescaler is loaded right now + \arg TIMER_PSC_RELOAD_UPDATE: the prescaler is loaded at the next update event + \param[out] none + \retval none +*/ +void timer_prescaler_config(uint32_t timer_periph, uint16_t prescaler, uint32_t pscreload) +{ + TIMER_PSC(timer_periph) = (uint32_t)prescaler; + + if(TIMER_PSC_RELOAD_NOW == pscreload){ + TIMER_SWEVG(timer_periph) |= (uint32_t)TIMER_SWEVG_UPG; + } +} + +/*! + \brief configure TIMER repetition register value + \param[in] timer_periph: TIMERx(x=0,7) + \param[in] repetition: the counter repetition value,0~255 + \param[out] none + \retval none +*/ +void timer_repetition_value_config(uint32_t timer_periph, uint8_t repetition) +{ + TIMER_CREP(timer_periph) = (uint32_t)repetition; +} + +/*! + \brief configure TIMER autoreload register value + \param[in] timer_periph: TIMERx(x=0..13) + \param[in] autoreload: the counter auto-reload value + \param[out] none + \retval none +*/ +void timer_autoreload_value_config(uint32_t timer_periph, uint32_t autoreload) +{ + TIMER_CAR(timer_periph) = (uint32_t)autoreload; +} + +/*! + \brief configure TIMER counter register value + \param[in] timer_periph: TIMERx(x=0..13) + \param[in] counter: the counter value + \param[out] none + \retval none +*/ +void timer_counter_value_config(uint32_t timer_periph, uint32_t counter) +{ + TIMER_CNT(timer_periph) = (uint32_t)counter; +} + +/*! + \brief read TIMER counter value + \param[in] timer_periph: TIMERx(x=0..13) + \param[out] none + \retval counter value +*/ +uint32_t timer_counter_read(uint32_t timer_periph) +{ + uint32_t count_value = 0U; + count_value = TIMER_CNT(timer_periph); + return (count_value); +} + +/*! + \brief read TIMER prescaler value + \param[in] timer_periph: TIMERx(x=0..13) + \param[out] none + \retval prescaler register value +*/ +uint16_t timer_prescaler_read(uint32_t timer_periph) +{ + uint16_t prescaler_value = 0U; + prescaler_value = (uint16_t)(TIMER_PSC(timer_periph)); + return (prescaler_value); +} + +/*! + \brief configure TIMER single pulse mode + \param[in] timer_periph: TIMERx(x=0..8,11) + \param[in] spmode: + only one parameter can be selected which is shown as below: + \arg TIMER_SP_MODE_SINGLE: single pulse mode + \arg TIMER_SP_MODE_REPETITIVE: repetitive pulse mode + \param[out] none + \retval none +*/ +void timer_single_pulse_mode_config(uint32_t timer_periph, uint32_t spmode) +{ + if(TIMER_SP_MODE_SINGLE == spmode){ + TIMER_CTL0(timer_periph) |= (uint32_t)TIMER_CTL0_SPM; + }else if(TIMER_SP_MODE_REPETITIVE == spmode){ + TIMER_CTL0(timer_periph) &= ~((uint32_t)TIMER_CTL0_SPM); + }else{ + /* illegal parameters */ + } +} + +/*! + \brief configure TIMER update source + \param[in] timer_periph: TIMERx(x=0..13) + \param[in] update: + only one parameter can be selected which is shown as below: + \arg TIMER_UPDATE_SRC_GLOBAL: update generate by setting of UPG bit or the counter overflow/underflow, + or the slave mode controller trigger + \arg TIMER_UPDATE_SRC_REGULAR: update generate only by counter overflow/underflow + \param[out] none + \retval none +*/ +void timer_update_source_config(uint32_t timer_periph, uint32_t update) +{ + if(TIMER_UPDATE_SRC_REGULAR == update){ + TIMER_CTL0(timer_periph) |= (uint32_t)TIMER_CTL0_UPS; + }else if(TIMER_UPDATE_SRC_GLOBAL == update){ + TIMER_CTL0(timer_periph) &= ~(uint32_t)TIMER_CTL0_UPS; + }else{ + /* illegal parameters */ + } +} + +/*! + \brief enable the TIMER DMA + \param[in] timer_periph: TIMERx(x=0,1,2,5,14,15,16) + \param[in] dma: timer DMA source enable + only one parameter can be selected which is shown as below: + \arg TIMER_DMA_UPD: update DMA enable,TIMERx(x=0..7) + \arg TIMER_DMA_CH0D: channel 0 DMA enable,TIMERx(x=0..4,7) + \arg TIMER_DMA_CH1D: channel 1 DMA enable,TIMERx(x=0..4,7) + \arg TIMER_DMA_CH2D: channel 2 DMA enable,TIMERx(x=0..4,7) + \arg TIMER_DMA_CH3D: channel 3 DMA enable,TIMERx(x=0..4,7) + \arg TIMER_DMA_CMTD: commutation DMA request enable,TIMERx(x=0,7) + \arg TIMER_DMA_TRGD: trigger DMA enable,TIMERx(x=0..4,7) + \param[out] none + \retval none +*/ +void timer_dma_enable(uint32_t timer_periph, uint16_t dma) +{ + TIMER_DMAINTEN(timer_periph) |= (uint32_t) dma; +} + +/*! + \brief disable the TIMER DMA + \param[in] timer_periph: please refer to the following parameters + \param[in] dma: timer DMA source disable + only one parameter can be selected which is shown as below: + \arg TIMER_DMA_UPD: update DMA disable,TIMERx(x=0..7) + \arg TIMER_DMA_CH0D: channel 0 DMA disable,TIMERx(x=0..4,7) + \arg TIMER_DMA_CH1D: channel 1 DMA disable,TIMERx(x=0..4,7) + \arg TIMER_DMA_CH2D: channel 2 DMA disable,TIMERx(x=0..4,7) + \arg TIMER_DMA_CH3D: channel 3 DMA disable,TIMERx(x=0..4,7) + \arg TIMER_DMA_CMTD: commutation DMA request disable,TIMERx(x=0,7) + \arg TIMER_DMA_TRGD: trigger DMA disable,TIMERx(x=0..4,7) + \param[out] none + \retval none +*/ +void timer_dma_disable(uint32_t timer_periph, uint16_t dma) +{ + TIMER_DMAINTEN(timer_periph) &= (~(uint32_t)(dma)); +} + +/*! + \brief channel DMA request source selection + \param[in] timer_periph: TIMERx(x=0..4,7) + \param[in] dma_request: channel DMA request source selection + only one parameter can be selected which is shown as below: + \arg TIMER_DMAREQUEST_CHANNELEVENT: DMA request of channel y is sent when channel y event occurs + \arg TIMER_DMAREQUEST_UPDATEEVENT: DMA request of channel y is sent when update event occurs + \param[out] none + \retval none +*/ +void timer_channel_dma_request_source_select(uint32_t timer_periph, uint32_t dma_request) +{ + if(TIMER_DMAREQUEST_UPDATEEVENT == dma_request){ + TIMER_CTL1(timer_periph) |= (uint32_t)TIMER_CTL1_DMAS; + }else if(TIMER_DMAREQUEST_CHANNELEVENT == dma_request){ + TIMER_CTL1(timer_periph) &= ~(uint32_t)TIMER_CTL1_DMAS; + }else{ + /* illegal parameters */ + } +} + +/*! + \brief configure the TIMER DMA transfer + \param[in] timer_periph: please refer to the following parameters + \param[in] dma_baseaddr: + only one parameter can be selected which is shown as below: + \arg TIMER_DMACFG_DMATA_CTL0: DMA transfer address is TIMER_CTL0,TIMERx(x=0..4,7) + \arg TIMER_DMACFG_DMATA_CTL1: DMA transfer address is TIMER_CTL1,TIMERx(x=0..4,7) + \arg TIMER_DMACFG_DMATA_SMCFG: DMA transfer address is TIMER_SMCFG,TIMERx(x=0..4,7) + \arg TIMER_DMACFG_DMATA_DMAINTEN: DMA transfer address is TIMER_DMAINTEN,TIMERx(x=0..4,7) + \arg TIMER_DMACFG_DMATA_INTF: DMA transfer address is TIMER_INTF,TIMERx(x=0..4,7) + \arg TIMER_DMACFG_DMATA_SWEVG: DMA transfer address is TIMER_SWEVG,TIMERx(x=0..4,7) + \arg TIMER_DMACFG_DMATA_CHCTL0: DMA transfer address is TIMER_CHCTL0,TIMERx(x=0..4,7) + \arg TIMER_DMACFG_DMATA_CHCTL1: DMA transfer address is TIMER_CHCTL1,TIMERx(x=0..4,7) + \arg TIMER_DMACFG_DMATA_CHCTL2: DMA transfer address is TIMER_CHCTL2,TIMERx(x=0..4,7) + \arg TIMER_DMACFG_DMATA_CNT: DMA transfer address is TIMER_CNT,TIMERx(x=0..4,7) + \arg TIMER_DMACFG_DMATA_PSC: DMA transfer address is TIMER_PSC,TIMERx(x=0..4,7) + \arg TIMER_DMACFG_DMATA_CAR: DMA transfer address is TIMER_CAR,TIMERx(x=0..4,7) + \arg TIMER_DMACFG_DMATA_CREP: DMA transfer address is TIMER_CREP,TIMERx(x=0,7) + \arg TIMER_DMACFG_DMATA_CH0CV: DMA transfer address is TIMER_CH0CV,TIMERx(x=0..4,7) + \arg TIMER_DMACFG_DMATA_CH1CV: DMA transfer address is TIMER_CH1CV,TIMERx(x=0..4,7) + \arg TIMER_DMACFG_DMATA_CH2CV: DMA transfer address is TIMER_CH2CV,TIMERx(x=0..4,7) + \arg TIMER_DMACFG_DMATA_CH3CV: DMA transfer address is TIMER_CH3CV,TIMERx(x=0..4,7) + \arg TIMER_DMACFG_DMATA_CCHP: DMA transfer address is TIMER_CCHP,TIMERx(x=0,7) + \arg TIMER_DMACFG_DMATA_DMACFG: DMA transfer address is TIMER_DMACFG,TIMERx(x=0..4,7) + \arg TIMER_DMACFG_DMATA_DMATB: DMA transfer address is TIMER_DMATB,TIMERx(x=0..4,7) + \param[in] dma_lenth: + only one parameter can be selected which is shown as below: + \arg TIMER_DMACFG_DMATC_xTRANSFER(x=1..18): DMA transfer x time + \param[out] none + \retval none +*/ +void timer_dma_transfer_config(uint32_t timer_periph, uint32_t dma_baseaddr, uint32_t dma_lenth) +{ + TIMER_DMACFG(timer_periph) &= (~(uint32_t)(TIMER_DMACFG_DMATA | TIMER_DMACFG_DMATC)); + TIMER_DMACFG(timer_periph) |= (uint32_t)(dma_baseaddr | dma_lenth); +} + +/*! + \brief software generate events + \param[in] timer_periph: please refer to the following parameters + \param[in] event: the timer software event generation sources + one or more parameters can be selected which are shown as below: + \arg TIMER_EVENT_SRC_UPG: update event generation, TIMERx(x=0..13) + \arg TIMER_EVENT_SRC_CH0G: channel 0 capture or compare event generation, TIMERx(x=0..4,7..13) + \arg TIMER_EVENT_SRC_CH1G: channel 1 capture or compare event generation, TIMERx(x=0..4,7,8,11) + \arg TIMER_EVENT_SRC_CH2G: channel 2 capture or compare event generation, TIMERx(x=0..4,7) + \arg TIMER_EVENT_SRC_CH3G: channel 3 capture or compare event generation, TIMERx(x=0..4,7) + \arg TIMER_EVENT_SRC_CMTG: channel commutation event generation, TIMERx(x=0,7) + \arg TIMER_EVENT_SRC_TRGG: trigger event generation, TIMERx(x=0..4,7,8,11) + \arg TIMER_EVENT_SRC_BRKG: break event generation, TIMERx(x=0,7) + \param[out] none + \retval none +*/ +void timer_event_software_generate(uint32_t timer_periph, uint16_t event) +{ + TIMER_SWEVG(timer_periph) |= (uint32_t)event; +} + +/*! + \brief initialize TIMER break parameter struct with a default value + \param[in] breakpara: TIMER break parameter struct + \param[out] none + \retval none +*/ +void timer_break_struct_para_init(timer_break_parameter_struct* breakpara) +{ + /* initialize the break parameter struct member with the default value */ + breakpara->runoffstate = TIMER_ROS_STATE_DISABLE; + breakpara->ideloffstate = TIMER_IOS_STATE_DISABLE; + breakpara->deadtime = 0U; + breakpara->breakpolarity = TIMER_BREAK_POLARITY_LOW; + breakpara->outputautostate = TIMER_OUTAUTO_DISABLE; + breakpara->protectmode = TIMER_CCHP_PROT_OFF; + breakpara->breakstate = TIMER_BREAK_DISABLE; +} + +/*! + \brief configure TIMER break function + \param[in] timer_periph: TIMERx(x=0,7) + \param[in] breakpara: TIMER break parameter struct + runoffstate: TIMER_ROS_STATE_ENABLE,TIMER_ROS_STATE_DISABLE + ideloffstate: TIMER_IOS_STATE_ENABLE,TIMER_IOS_STATE_DISABLE + deadtime: 0~255 + breakpolarity: TIMER_BREAK_POLARITY_LOW,TIMER_BREAK_POLARITY_HIGH + outputautostate: TIMER_OUTAUTO_ENABLE,TIMER_OUTAUTO_DISABLE + protectmode: TIMER_CCHP_PROT_OFF,TIMER_CCHP_PROT_0,TIMER_CCHP_PROT_1,TIMER_CCHP_PROT_2 + breakstate: TIMER_BREAK_ENABLE,TIMER_BREAK_DISABLE + \param[out] none + \retval none +*/ +void timer_break_config(uint32_t timer_periph, timer_break_parameter_struct* breakpara) +{ + TIMER_CCHP(timer_periph) = (uint32_t)(((uint32_t)(breakpara->runoffstate)) | + ((uint32_t)(breakpara->ideloffstate)) | + ((uint32_t)(breakpara->deadtime)) | + ((uint32_t)(breakpara->breakpolarity)) | + ((uint32_t)(breakpara->outputautostate)) | + ((uint32_t)(breakpara->protectmode)) | + ((uint32_t)(breakpara->breakstate))) ; +} + +/*! + \brief enable TIMER break function + \param[in] timer_periph: TIMERx(x=0,7) + \param[out] none + \retval none +*/ +void timer_break_enable(uint32_t timer_periph) +{ + TIMER_CCHP(timer_periph) |= (uint32_t)TIMER_CCHP_BRKEN; +} + +/*! + \brief disable TIMER break function + \param[in] timer_periph: TIMERx(x=0,7) + \param[out] none + \retval none +*/ +void timer_break_disable(uint32_t timer_periph) +{ + TIMER_CCHP(timer_periph) &= ~(uint32_t)TIMER_CCHP_BRKEN; +} + +/*! + \brief enable TIMER output automatic function + \param[in] timer_periph: TIMERx(x=0,7) + \param[out] none + \retval none +*/ +void timer_automatic_output_enable(uint32_t timer_periph) +{ + TIMER_CCHP(timer_periph) |= (uint32_t)TIMER_CCHP_OAEN; +} + +/*! + \brief disable TIMER output automatic function + \param[in] timer_periph: TIMERx(x=0,7) + \param[out] none + \retval none +*/ +void timer_automatic_output_disable(uint32_t timer_periph) +{ + TIMER_CCHP(timer_periph) &= ~(uint32_t)TIMER_CCHP_OAEN; +} + +/*! + \brief enable or disable TIMER primary output function + \param[in] timer_periph: TIMERx(x=0,7) + \param[in] newvalue: ENABLE or DISABLE + \param[out] none + \retval none +*/ +void timer_primary_output_config(uint32_t timer_periph, ControlStatus newvalue) +{ + if(ENABLE == newvalue){ + TIMER_CCHP(timer_periph) |= (uint32_t)TIMER_CCHP_POEN; + }else{ + TIMER_CCHP(timer_periph) &= (~(uint32_t)TIMER_CCHP_POEN); + } +} + +/*! + \brief enable or disable channel capture/compare control shadow register + \param[in] timer_periph: TIMERx(x=0,7) + \param[in] newvalue: ENABLE or DISABLE + \param[out] none + \retval none +*/ +void timer_channel_control_shadow_config(uint32_t timer_periph, ControlStatus newvalue) +{ + if(ENABLE == newvalue){ + TIMER_CTL1(timer_periph) |= (uint32_t)TIMER_CTL1_CCSE; + }else{ + TIMER_CTL1(timer_periph) &= (~(uint32_t)TIMER_CTL1_CCSE); + } +} + +/*! + \brief configure TIMER channel control shadow register update control + \param[in] timer_periph: TIMERx(x=0,7) + \param[in] ccuctl: channel control shadow register update control + only one parameter can be selected which is shown as below: + \arg TIMER_UPDATECTL_CCU: the shadow registers update by when CMTG bit is set + \arg TIMER_UPDATECTL_CCUTRI: the shadow registers update by when CMTG bit is set or an rising edge of TRGI occurs + \param[out] none + \retval none +*/ +void timer_channel_control_shadow_update_config(uint32_t timer_periph, uint32_t ccuctl) +{ + if(TIMER_UPDATECTL_CCU == ccuctl){ + TIMER_CTL1(timer_periph) &= (~(uint32_t)TIMER_CTL1_CCUC); + }else if(TIMER_UPDATECTL_CCUTRI == ccuctl){ + TIMER_CTL1(timer_periph) |= (uint32_t)TIMER_CTL1_CCUC; + }else{ + /* illegal parameters */ + } +} + +/*! + \brief initialize TIMER channel output parameter struct with a default value + \param[in] ocpara: TIMER channel n output parameter struct + \param[out] none + \retval none +*/ +void timer_channel_output_struct_para_init(timer_oc_parameter_struct* ocpara) +{ + /* initialize the channel output parameter struct member with the default value */ + ocpara->outputstate = TIMER_CCX_DISABLE; + ocpara->outputnstate = TIMER_CCXN_DISABLE; + ocpara->ocpolarity = TIMER_OC_POLARITY_HIGH; + ocpara->ocnpolarity = TIMER_OCN_POLARITY_HIGH; + ocpara->ocidlestate = TIMER_OC_IDLE_STATE_LOW; + ocpara->ocnidlestate = TIMER_OCN_IDLE_STATE_LOW; +} + +/*! + \brief configure TIMER channel output function + \param[in] timer_periph: please refer to the following parameters + \param[in] channel: + only one parameter can be selected which is shown as below: + \arg TIMER_CH_0: TIMER channel 0(TIMERx(x=0..4,7..13)) + \arg TIMER_CH_1: TIMER channel 1(TIMERx(x=0..4,7,8,11)) + \arg TIMER_CH_2: TIMER channel 2(TIMERx(x=0..4,7)) + \arg TIMER_CH_3: TIMER channel 3(TIMERx(x=0..4,7)) + \param[in] ocpara: TIMER channeln output parameter struct + outputstate: TIMER_CCX_ENABLE,TIMER_CCX_DISABLE + outputnstate: TIMER_CCXN_ENABLE,TIMER_CCXN_DISABLE + ocpolarity: TIMER_OC_POLARITY_HIGH,TIMER_OC_POLARITY_LOW + ocnpolarity: TIMER_OCN_POLARITY_HIGH,TIMER_OCN_POLARITY_LOW + ocidlestate: TIMER_OC_IDLE_STATE_LOW,TIMER_OC_IDLE_STATE_HIGH + ocnidlestate: TIMER_OCN_IDLE_STATE_LOW,TIMER_OCN_IDLE_STATE_HIGH + \param[out] none + \retval none +*/ +void timer_channel_output_config(uint32_t timer_periph, uint16_t channel, timer_oc_parameter_struct* ocpara) +{ + switch(channel){ + /* configure TIMER_CH_0 */ + case TIMER_CH_0: + /* reset the CH0EN bit */ + TIMER_CHCTL2(timer_periph) &= (~(uint32_t)TIMER_CHCTL2_CH0EN); + TIMER_CHCTL0(timer_periph) &= ~(uint32_t)TIMER_CHCTL0_CH0MS; + /* set the CH0EN bit */ + TIMER_CHCTL2(timer_periph) |= (uint32_t)ocpara->outputstate; + /* reset the CH0P bit */ + TIMER_CHCTL2(timer_periph) &= (~(uint32_t)TIMER_CHCTL2_CH0P); + /* set the CH0P bit */ + TIMER_CHCTL2(timer_periph) |= (uint32_t)ocpara->ocpolarity; + + if((TIMER0 == timer_periph) || (TIMER7 == timer_periph)){ + /* reset the CH0NEN bit */ + TIMER_CHCTL2(timer_periph) &= (~(uint32_t)TIMER_CHCTL2_CH0NEN); + /* set the CH0NEN bit */ + TIMER_CHCTL2(timer_periph) |= (uint32_t)ocpara->outputnstate; + /* reset the CH0NP bit */ + TIMER_CHCTL2(timer_periph) &= (~(uint32_t)TIMER_CHCTL2_CH0NP); + /* set the CH0NP bit */ + TIMER_CHCTL2(timer_periph) |= (uint32_t)ocpara->ocnpolarity; + /* reset the ISO0 bit */ + TIMER_CTL1(timer_periph) &= (~(uint32_t)TIMER_CTL1_ISO0); + /* set the ISO0 bit */ + TIMER_CTL1(timer_periph) |= (uint32_t)ocpara->ocidlestate; + /* reset the ISO0N bit */ + TIMER_CTL1(timer_periph) &= (~(uint32_t)TIMER_CTL1_ISO0N); + /* set the ISO0N bit */ + TIMER_CTL1(timer_periph) |= (uint32_t)ocpara->ocnidlestate; + } + break; + /* configure TIMER_CH_1 */ + case TIMER_CH_1: + /* reset the CH1EN bit */ + TIMER_CHCTL2(timer_periph) &= (~(uint32_t)TIMER_CHCTL2_CH1EN); + TIMER_CHCTL0(timer_periph) &= ~(uint32_t)TIMER_CHCTL0_CH1MS; + /* set the CH1EN bit */ + TIMER_CHCTL2(timer_periph) |= (uint32_t)((uint32_t)(ocpara->outputstate) << 4U); + /* reset the CH1P bit */ + TIMER_CHCTL2(timer_periph) &= (~(uint32_t)TIMER_CHCTL2_CH1P); + /* set the CH1P bit */ + TIMER_CHCTL2(timer_periph) |= (uint32_t)((uint32_t)(ocpara->ocpolarity)<< 4U); + + if((TIMER0 == timer_periph) || (TIMER7 == timer_periph)){ + /* reset the CH1NEN bit */ + TIMER_CHCTL2(timer_periph) &= (~(uint32_t)TIMER_CHCTL2_CH1NEN); + /* set the CH1NEN bit */ + TIMER_CHCTL2(timer_periph) |= (uint32_t)((uint32_t)(ocpara->outputnstate)<< 4U); + /* reset the CH1NP bit */ + TIMER_CHCTL2(timer_periph) &= (~(uint32_t)TIMER_CHCTL2_CH1NP); + /* set the CH1NP bit */ + TIMER_CHCTL2(timer_periph) |= (uint32_t)((uint32_t)(ocpara->ocnpolarity)<< 4U); + /* reset the ISO1 bit */ + TIMER_CTL1(timer_periph) &= (~(uint32_t)TIMER_CTL1_ISO1); + /* set the ISO1 bit */ + TIMER_CTL1(timer_periph) |= (uint32_t)((uint32_t)(ocpara->ocidlestate)<< 2U); + /* reset the ISO1N bit */ + TIMER_CTL1(timer_periph) &= (~(uint32_t)TIMER_CTL1_ISO1N); + /* set the ISO1N bit */ + TIMER_CTL1(timer_periph) |= (uint32_t)((uint32_t)(ocpara->ocnidlestate)<< 2U); + } + break; + /* configure TIMER_CH_2 */ + case TIMER_CH_2: + /* reset the CH2EN bit */ + TIMER_CHCTL2(timer_periph) &= (~(uint32_t)TIMER_CHCTL2_CH2EN); + TIMER_CHCTL1(timer_periph) &= ~(uint32_t)TIMER_CHCTL1_CH2MS; + /* set the CH2EN bit */ + TIMER_CHCTL2(timer_periph) |= (uint32_t)((uint32_t)(ocpara->outputstate) << 8U); + /* reset the CH2P bit */ + TIMER_CHCTL2(timer_periph) &= (~(uint32_t)TIMER_CHCTL2_CH2P); + /* set the CH2P bit */ + TIMER_CHCTL2(timer_periph) |= (uint32_t)((uint32_t)(ocpara->ocpolarity)<< 8U); + + if((TIMER0 == timer_periph) || (TIMER7 == timer_periph)){ + /* reset the CH2NEN bit */ + TIMER_CHCTL2(timer_periph) &= (~(uint32_t)TIMER_CHCTL2_CH2NEN); + /* set the CH2NEN bit */ + TIMER_CHCTL2(timer_periph) |= (uint32_t)((uint32_t)(ocpara->outputnstate)<< 8U); + /* reset the CH2NP bit */ + TIMER_CHCTL2(timer_periph) &= (~(uint32_t)TIMER_CHCTL2_CH2NP); + /* set the CH2NP bit */ + TIMER_CHCTL2(timer_periph) |= (uint32_t)((uint32_t)(ocpara->ocnpolarity)<< 8U); + /* reset the ISO2 bit */ + TIMER_CTL1(timer_periph) &= (~(uint32_t)TIMER_CTL1_ISO2); + /* set the ISO2 bit */ + TIMER_CTL1(timer_periph) |= (uint32_t)((uint32_t)(ocpara->ocidlestate)<< 4U); + /* reset the ISO2N bit */ + TIMER_CTL1(timer_periph) &= (~(uint32_t)TIMER_CTL1_ISO2N); + /* set the ISO2N bit */ + TIMER_CTL1(timer_periph) |= (uint32_t)((uint32_t)(ocpara->ocnidlestate)<< 4U); + } + break; + /* configure TIMER_CH_3 */ + case TIMER_CH_3: + /* reset the CH3EN bit */ + TIMER_CHCTL2(timer_periph) &=(~(uint32_t)TIMER_CHCTL2_CH3EN); + TIMER_CHCTL1(timer_periph) &= ~(uint32_t)TIMER_CHCTL1_CH3MS; + /* set the CH3EN bit */ + TIMER_CHCTL2(timer_periph) |= (uint32_t)((uint32_t)(ocpara->outputstate) << 12U); + /* reset the CH3P bit */ + TIMER_CHCTL2(timer_periph) &= (~(uint32_t)TIMER_CHCTL2_CH3P); + /* set the CH3P bit */ + TIMER_CHCTL2(timer_periph) |= (uint32_t)((uint32_t)(ocpara->ocpolarity)<< 12U); + + if((TIMER0 == timer_periph) || (TIMER7 == timer_periph)){ + /* reset the ISO3 bit */ + TIMER_CTL1(timer_periph) &= (~(uint32_t)TIMER_CTL1_ISO3); + /* set the ISO3 bit */ + TIMER_CTL1(timer_periph) |= (uint32_t)((uint32_t)(ocpara->ocidlestate)<< 6U); + } + break; + default: + break; + } +} + +/*! + \brief configure TIMER channel output compare mode + \param[in] timer_periph: please refer to the following parameters + \param[in] channel: + only one parameter can be selected which is shown as below: + \arg TIMER_CH_0: TIMER channel0(TIMERx(x=0..4,7..13)) + \arg TIMER_CH_1: TIMER channel1(TIMERx(x=0..4,7,8,11)) + \arg TIMER_CH_2: TIMER channel2(TIMERx(x=0..4,7)) + \arg TIMER_CH_3: TIMER channel3(TIMERx(x=0..4,7)) + \param[in] ocmode: channel output compare mode + only one parameter can be selected which is shown as below: + \arg TIMER_OC_MODE_TIMING: timing mode + \arg TIMER_OC_MODE_ACTIVE: active mode + \arg TIMER_OC_MODE_INACTIVE: inactive mode + \arg TIMER_OC_MODE_TOGGLE: toggle mode + \arg TIMER_OC_MODE_LOW: force low mode + \arg TIMER_OC_MODE_HIGH: force high mode + \arg TIMER_OC_MODE_PWM0: PWM0 mode + \arg TIMER_OC_MODE_PWM1: PWM1 mode + \param[out] none + \retval none +*/ +void timer_channel_output_mode_config(uint32_t timer_periph, uint16_t channel, uint16_t ocmode) +{ + switch(channel){ + /* configure TIMER_CH_0 */ + case TIMER_CH_0: + TIMER_CHCTL0(timer_periph) &= (~(uint32_t)TIMER_CHCTL0_CH0COMCTL); + TIMER_CHCTL0(timer_periph) |= (uint32_t)ocmode; + break; + /* configure TIMER_CH_1 */ + case TIMER_CH_1: + TIMER_CHCTL0(timer_periph) &= (~(uint32_t)TIMER_CHCTL0_CH1COMCTL); + TIMER_CHCTL0(timer_periph) |= (uint32_t)((uint32_t)(ocmode)<< 8U); + break; + /* configure TIMER_CH_2 */ + case TIMER_CH_2: + TIMER_CHCTL1(timer_periph) &= (~(uint32_t)TIMER_CHCTL1_CH2COMCTL); + TIMER_CHCTL1(timer_periph) |= (uint32_t)ocmode; + break; + /* configure TIMER_CH_3 */ + case TIMER_CH_3: + TIMER_CHCTL1(timer_periph) &= (~(uint32_t)TIMER_CHCTL1_CH3COMCTL); + TIMER_CHCTL1(timer_periph) |= (uint32_t)((uint32_t)(ocmode)<< 8U); + break; + default: + break; + } +} + +/*! + \brief configure TIMER channel output pulse value + \param[in] timer_periph: please refer to the following parameters + \param[in] channel: + only one parameter can be selected which is shown as below: + \arg TIMER_CH_0: TIMER channel0(TIMERx(x=0..4,7..13)) + \arg TIMER_CH_1: TIMER channel1(TIMERx(x=0..4,7,8,11)) + \arg TIMER_CH_2: TIMER channel2(TIMERx(x=0..4,7)) + \arg TIMER_CH_3: TIMER channel3(TIMERx(x=0..4,7)) + \param[in] pulse: channel output pulse value + \param[out] none + \retval none +*/ +void timer_channel_output_pulse_value_config(uint32_t timer_periph, uint16_t channel, uint16_t pulse) +{ + switch(channel){ + /* configure TIMER_CH_0 */ + case TIMER_CH_0: + TIMER_CH0CV(timer_periph) = (uint32_t)pulse; + break; + /* configure TIMER_CH_1 */ + case TIMER_CH_1: + TIMER_CH1CV(timer_periph) = (uint32_t)pulse; + break; + /* configure TIMER_CH_2 */ + case TIMER_CH_2: + TIMER_CH2CV(timer_periph) = (uint32_t)pulse; + break; + /* configure TIMER_CH_3 */ + case TIMER_CH_3: + TIMER_CH3CV(timer_periph) = (uint32_t)pulse; + break; + default: + break; + } +} + +/*! + \brief configure TIMER channel output shadow function + \param[in] timer_periph: please refer to the following parameters + \param[in] channel: + only one parameter can be selected which is shown as below: + \arg TIMER_CH_0: TIMER channel0(TIMERx(x=0..4,7..13)) + \arg TIMER_CH_1: TIMER channel1(TIMERx(x=0..4,7,8,11)) + \arg TIMER_CH_2: TIMER channel2(TIMERx(x=0..4,7)) + \arg TIMER_CH_3: TIMER channel3(TIMERx(x=0..4,7)) + \param[in] ocshadow: channel output shadow state + only one parameter can be selected which is shown as below: + \arg TIMER_OC_SHADOW_ENABLE: channel output shadow state enable + \arg TIMER_OC_SHADOW_DISABLE: channel output shadow state disable + \param[out] none + \retval none +*/ +void timer_channel_output_shadow_config(uint32_t timer_periph, uint16_t channel, uint16_t ocshadow) +{ + switch(channel){ + /* configure TIMER_CH_0 */ + case TIMER_CH_0: + TIMER_CHCTL0(timer_periph) &= (~(uint32_t)TIMER_CHCTL0_CH0COMSEN); + TIMER_CHCTL0(timer_periph) |= (uint32_t)ocshadow; + break; + /* configure TIMER_CH_1 */ + case TIMER_CH_1: + TIMER_CHCTL0(timer_periph) &= (~(uint32_t)TIMER_CHCTL0_CH1COMSEN); + TIMER_CHCTL0(timer_periph) |= (uint32_t)((uint32_t)(ocshadow) << 8U); + break; + /* configure TIMER_CH_2 */ + case TIMER_CH_2: + TIMER_CHCTL1(timer_periph) &= (~(uint32_t)TIMER_CHCTL1_CH2COMSEN); + TIMER_CHCTL1(timer_periph) |= (uint32_t)ocshadow; + break; + /* configure TIMER_CH_3 */ + case TIMER_CH_3: + TIMER_CHCTL1(timer_periph) &= (~(uint32_t)TIMER_CHCTL1_CH3COMSEN); + TIMER_CHCTL1(timer_periph) |= (uint32_t)((uint32_t)(ocshadow) << 8U); + break; + default: + break; + } +} + +/*! + \brief configure TIMER channel output fast function + \param[in] timer_periph: please refer to the following parameters + \param[in] channel: + only one parameter can be selected which is shown as below: + \arg TIMER_CH_0: TIMER channel0(TIMERx(x=0..4,7..13)) + \arg TIMER_CH_1: TIMER channel1(TIMERx(x=0..4,7,8,11)) + \arg TIMER_CH_2: TIMER channel2(TIMERx(x=0..4,7)) + \arg TIMER_CH_3: TIMER channel3(TIMERx(x=0..4,7)) + \param[in] ocfast: channel output fast function + only one parameter can be selected which is shown as below: + \arg TIMER_OC_FAST_ENABLE: channel output fast function enable + \arg TIMER_OC_FAST_DISABLE: channel output fast function disable + \param[out] none + \retval none +*/ +void timer_channel_output_fast_config(uint32_t timer_periph, uint16_t channel, uint16_t ocfast) +{ + switch(channel){ + /* configure TIMER_CH_0 */ + case TIMER_CH_0: + TIMER_CHCTL0(timer_periph) &= (~(uint32_t)TIMER_CHCTL0_CH0COMFEN); + TIMER_CHCTL0(timer_periph) |= (uint32_t)ocfast; + break; + /* configure TIMER_CH_1 */ + case TIMER_CH_1: + TIMER_CHCTL0(timer_periph) &= (~(uint32_t)TIMER_CHCTL0_CH1COMFEN); + TIMER_CHCTL0(timer_periph) |= (uint32_t)((uint32_t)ocfast << 8U); + break; + /* configure TIMER_CH_2 */ + case TIMER_CH_2: + TIMER_CHCTL1(timer_periph) &= (~(uint32_t)TIMER_CHCTL1_CH2COMFEN); + TIMER_CHCTL1(timer_periph) |= (uint32_t)ocfast; + break; + /* configure TIMER_CH_3 */ + case TIMER_CH_3: + TIMER_CHCTL1(timer_periph) &= (~(uint32_t)TIMER_CHCTL1_CH3COMFEN); + TIMER_CHCTL1(timer_periph) |= (uint32_t)((uint32_t)ocfast << 8U); + break; + default: + break; + } +} + +/*! + \brief configure TIMER channel output clear function + \param[in] timer_periph: TIMERx(x=0..4,7) + \param[in] channel: + only one parameter can be selected which is shown as below: + \arg TIMER_CH_0: TIMER channel0 + \arg TIMER_CH_1: TIMER channel1 + \arg TIMER_CH_2: TIMER channel2 + \arg TIMER_CH_3: TIMER channel3 + \param[in] occlear: channel output clear function + only one parameter can be selected which is shown as below: + \arg TIMER_OC_CLEAR_ENABLE: channel output clear function enable + \arg TIMER_OC_CLEAR_DISABLE: channel output clear function disable + \param[out] none + \retval none +*/ +void timer_channel_output_clear_config(uint32_t timer_periph, uint16_t channel, uint16_t occlear) +{ + switch(channel){ + /* configure TIMER_CH_0 */ + case TIMER_CH_0: + TIMER_CHCTL0(timer_periph) &= (~(uint32_t)TIMER_CHCTL0_CH0COMCEN); + TIMER_CHCTL0(timer_periph) |= (uint32_t)occlear; + break; + /* configure TIMER_CH_1 */ + case TIMER_CH_1: + TIMER_CHCTL0(timer_periph) &= (~(uint32_t)TIMER_CHCTL0_CH1COMCEN); + TIMER_CHCTL0(timer_periph) |= (uint32_t)((uint32_t)occlear << 8U); + break; + /* configure TIMER_CH_2 */ + case TIMER_CH_2: + TIMER_CHCTL1(timer_periph) &= (~(uint32_t)TIMER_CHCTL1_CH2COMCEN); + TIMER_CHCTL1(timer_periph) |= (uint32_t)occlear; + break; + /* configure TIMER_CH_3 */ + case TIMER_CH_3: + TIMER_CHCTL1(timer_periph) &= (~(uint32_t)TIMER_CHCTL1_CH3COMCEN); + TIMER_CHCTL1(timer_periph) |= (uint32_t)((uint32_t)occlear << 8U); + break; + default: + break; + } +} + +/*! + \brief configure TIMER channel output polarity + \param[in] timer_periph: please refer to the following parameters + \param[in] channel: + only one parameter can be selected which is shown as below: + \arg TIMER_CH_0: TIMER channel0(TIMERx(x=0..4,7..13)) + \arg TIMER_CH_1: TIMER channel1(TIMERx(x=0..4,7,8,11)) + \arg TIMER_CH_2: TIMER channel2(TIMERx(x=0..4,7)) + \arg TIMER_CH_3: TIMER channel3(TIMERx(x=0..4,7)) + \param[in] ocpolarity: channel output polarity + only one parameter can be selected which is shown as below: + \arg TIMER_OC_POLARITY_HIGH: channel output polarity is high + \arg TIMER_OC_POLARITY_LOW: channel output polarity is low + \param[out] none + \retval none +*/ +void timer_channel_output_polarity_config(uint32_t timer_periph, uint16_t channel, uint16_t ocpolarity) +{ + switch(channel){ + /* configure TIMER_CH_0 */ + case TIMER_CH_0: + TIMER_CHCTL2(timer_periph) &= (~(uint32_t)TIMER_CHCTL2_CH0P); + TIMER_CHCTL2(timer_periph) |= (uint32_t)ocpolarity; + break; + /* configure TIMER_CH_1 */ + case TIMER_CH_1: + TIMER_CHCTL2(timer_periph) &= (~(uint32_t)TIMER_CHCTL2_CH1P); + TIMER_CHCTL2(timer_periph) |= (uint32_t)((uint32_t)ocpolarity << 4U); + break; + /* configure TIMER_CH_2 */ + case TIMER_CH_2: + TIMER_CHCTL2(timer_periph) &= (~(uint32_t)TIMER_CHCTL2_CH2P); + TIMER_CHCTL2(timer_periph) |= (uint32_t)((uint32_t)ocpolarity << 8U); + break; + /* configure TIMER_CH_3 */ + case TIMER_CH_3: + TIMER_CHCTL2(timer_periph) &= (~(uint32_t)TIMER_CHCTL2_CH3P); + TIMER_CHCTL2(timer_periph) |= (uint32_t)((uint32_t)ocpolarity << 12U); + break; + default: + break; + } +} + +/*! + \brief configure TIMER channel complementary output polarity + \param[in] timer_periph: TIMERx(x=0,7) + \param[in] channel: + only one parameter can be selected which is shown as below: + \arg TIMER_CH_0: TIMER channel0(TIMERx(x=0..4,7..13)) + \arg TIMER_CH_1: TIMER channel1(TIMERx(x=0..4,7,8,11)) + \arg TIMER_CH_2: TIMER channel2(TIMERx(x=0..4,7)) + \param[in] ocnpolarity: channel complementary output polarity + only one parameter can be selected which is shown as below: + \arg TIMER_OCN_POLARITY_HIGH: channel complementary output polarity is high + \arg TIMER_OCN_POLARITY_LOW: channel complementary output polarity is low + \param[out] none + \retval none +*/ +void timer_channel_complementary_output_polarity_config(uint32_t timer_periph, uint16_t channel, uint16_t ocnpolarity) +{ + switch(channel){ + /* configure TIMER_CH_0 */ + case TIMER_CH_0: + TIMER_CHCTL2(timer_periph) &= (~(uint32_t)TIMER_CHCTL2_CH0NP); + TIMER_CHCTL2(timer_periph) |= (uint32_t)ocnpolarity; + break; + /* configure TIMER_CH_1 */ + case TIMER_CH_1: + TIMER_CHCTL2(timer_periph) &= (~(uint32_t)TIMER_CHCTL2_CH1NP); + TIMER_CHCTL2(timer_periph) |= (uint32_t)((uint32_t)ocnpolarity << 4U); + break; + /* configure TIMER_CH_2 */ + case TIMER_CH_2: + TIMER_CHCTL2(timer_periph) &= (~(uint32_t)TIMER_CHCTL2_CH2NP); + TIMER_CHCTL2(timer_periph) |= (uint32_t)((uint32_t)ocnpolarity << 8U); + break; + default: + break; + } +} + +/*! + \brief configure TIMER channel enable state + \param[in] timer_periph: please refer to the following parameters + \param[in] channel: + only one parameter can be selected which is shown as below: + \arg TIMER_CH_0: TIMER channel0(TIMERx(x=0..4,7..13)) + \arg TIMER_CH_1: TIMER channel1(TIMERx(x=0..4,7,8,11)) + \arg TIMER_CH_2: TIMER channel2(TIMERx(x=0..4,7)) + \arg TIMER_CH_3: TIMER channel3(TIMERx(x=0..4,7)) + \param[in] state: TIMER channel enable state + only one parameter can be selected which is shown as below: + \arg TIMER_CCX_ENABLE: channel enable + \arg TIMER_CCX_DISABLE: channel disable + \param[out] none + \retval none +*/ +void timer_channel_output_state_config(uint32_t timer_periph, uint16_t channel, uint32_t state) +{ + switch(channel){ + /* configure TIMER_CH_0 */ + case TIMER_CH_0: + TIMER_CHCTL2(timer_periph) &= (~(uint32_t)TIMER_CHCTL2_CH0EN); + TIMER_CHCTL2(timer_periph) |= (uint32_t)state; + break; + /* configure TIMER_CH_1 */ + case TIMER_CH_1: + TIMER_CHCTL2(timer_periph) &= (~(uint32_t)TIMER_CHCTL2_CH1EN); + TIMER_CHCTL2(timer_periph) |= (uint32_t)((uint32_t)state << 4U); + break; + /* configure TIMER_CH_2 */ + case TIMER_CH_2: + TIMER_CHCTL2(timer_periph) &= (~(uint32_t)TIMER_CHCTL2_CH2EN); + TIMER_CHCTL2(timer_periph) |= (uint32_t)((uint32_t)state << 8U); + break; + /* configure TIMER_CH_3 */ + case TIMER_CH_3: + TIMER_CHCTL2(timer_periph) &= (~(uint32_t)TIMER_CHCTL2_CH3EN); + TIMER_CHCTL2(timer_periph) |= (uint32_t)((uint32_t)state << 12U); + break; + default: + break; + } +} + +/*! + \brief configure TIMER channel complementary output enable state + \param[in] timer_periph: TIMERx(x=0,7) + \param[in] channel: + only one parameter can be selected which is shown as below: + \arg TIMER_CH_0: TIMER channel0 + \arg TIMER_CH_1: TIMER channel1 + \arg TIMER_CH_2: TIMER channel2 + \param[in] ocnstate: TIMER channel complementary output enable state + only one parameter can be selected which is shown as below: + \arg TIMER_CCXN_ENABLE: channel complementary enable + \arg TIMER_CCXN_DISABLE: channel complementary disable + \param[out] none + \retval none +*/ +void timer_channel_complementary_output_state_config(uint32_t timer_periph, uint16_t channel, uint16_t ocnstate) +{ + switch(channel){ + /* configure TIMER_CH_0 */ + case TIMER_CH_0: + TIMER_CHCTL2(timer_periph) &= (~(uint32_t)TIMER_CHCTL2_CH0NEN); + TIMER_CHCTL2(timer_periph) |= (uint32_t)ocnstate; + break; + /* configure TIMER_CH_1 */ + case TIMER_CH_1: + TIMER_CHCTL2(timer_periph) &= (~(uint32_t)TIMER_CHCTL2_CH1NEN); + TIMER_CHCTL2(timer_periph) |= (uint32_t)((uint32_t)ocnstate << 4U); + break; + /* configure TIMER_CH_2 */ + case TIMER_CH_2: + TIMER_CHCTL2(timer_periph) &= (~(uint32_t)TIMER_CHCTL2_CH2NEN); + TIMER_CHCTL2(timer_periph) |= (uint32_t)((uint32_t)ocnstate << 8U); + break; + default: + break; + } +} + +/*! + \brief initialize TIMER channel input parameter struct with a default value + \param[in] icpara: TIMER channel intput parameter struct + \param[out] none + \retval none +*/ +void timer_channel_input_struct_para_init(timer_ic_parameter_struct* icpara) +{ + /* initialize the channel input parameter struct member with the default value */ + icpara->icpolarity = TIMER_IC_POLARITY_RISING; + icpara->icselection = TIMER_IC_SELECTION_DIRECTTI; + icpara->icprescaler = TIMER_IC_PSC_DIV1; + icpara->icfilter = 0U; +} + +/*! + \brief configure TIMER input capture parameter + \param[in] timer_periph: please refer to the following parameters + \param[in] channel: + only one parameter can be selected which is shown as below: + \arg TIMER_CH_0: TIMER channel 0(TIMERx(x=0..4,7..13)) + \arg TIMER_CH_1: TIMER channel 1(TIMERx(x=0..4,7,8,11)) + \arg TIMER_CH_2: TIMER channel 2(TIMERx(x=0..4,7)) + \arg TIMER_CH_3: TIMER channel 3(TIMERx(x=0..4,7)) + \param[in] icpara: TIMER channel intput parameter struct + icpolarity: TIMER_IC_POLARITY_RISING, TIMER_IC_POLARITY_FALLING, + TIMER_IC_POLARITY_BOTH_EDGE(only for TIMER1~TIMER8) + icselection: TIMER_IC_SELECTION_DIRECTTI, TIMER_IC_SELECTION_INDIRECTTI, + TIMER_IC_SELECTION_ITS + icprescaler: TIMER_IC_PSC_DIV1, TIMER_IC_PSC_DIV2, TIMER_IC_PSC_DIV4, + TIMER_IC_PSC_DIV8 + icfilter: 0~15 + \param[out] none + \retval none +*/ +void timer_input_capture_config(uint32_t timer_periph, uint16_t channel, timer_ic_parameter_struct* icpara) +{ + switch(channel){ + /* configure TIMER_CH_0 */ + case TIMER_CH_0: + /* reset the CH0EN bit */ + TIMER_CHCTL2(timer_periph) &= (~(uint32_t)TIMER_CHCTL2_CH0EN); + + /* reset the CH0P and CH0NP bits */ + TIMER_CHCTL2(timer_periph) &= (~(uint32_t)(TIMER_CHCTL2_CH0P | TIMER_CHCTL2_CH0NP)); + TIMER_CHCTL2(timer_periph) |= (uint32_t)(icpara->icpolarity); + /* reset the CH0MS bit */ + TIMER_CHCTL0(timer_periph) &= (~(uint32_t)TIMER_CHCTL0_CH0MS); + TIMER_CHCTL0(timer_periph) |= (uint32_t)(icpara->icselection); + /* reset the CH0CAPFLT bit */ + TIMER_CHCTL0(timer_periph) &= (~(uint32_t)TIMER_CHCTL0_CH0CAPFLT); + TIMER_CHCTL0(timer_periph) |= (uint32_t)((uint32_t)(icpara->icfilter) << 4U); + + /* set the CH0EN bit */ + TIMER_CHCTL2(timer_periph) |= (uint32_t)TIMER_CHCTL2_CH0EN; + break; + + /* configure TIMER_CH_1 */ + case TIMER_CH_1: + /* reset the CH1EN bit */ + TIMER_CHCTL2(timer_periph) &= (~(uint32_t)TIMER_CHCTL2_CH1EN); + + /* reset the CH1P and CH1NP bits */ + TIMER_CHCTL2(timer_periph) &= (~(uint32_t)(TIMER_CHCTL2_CH1P | TIMER_CHCTL2_CH1NP)); + TIMER_CHCTL2(timer_periph) |= (uint32_t)((uint32_t)(icpara->icpolarity) << 4U); + /* reset the CH1MS bit */ + TIMER_CHCTL0(timer_periph) &= (~(uint32_t)TIMER_CHCTL0_CH1MS); + TIMER_CHCTL0(timer_periph) |= (uint32_t)((uint32_t)(icpara->icselection) << 8U); + /* reset the CH1CAPFLT bit */ + TIMER_CHCTL0(timer_periph) &= (~(uint32_t)TIMER_CHCTL0_CH1CAPFLT); + TIMER_CHCTL0(timer_periph) |= (uint32_t)((uint32_t)(icpara->icfilter) << 12U); + + /* set the CH1EN bit */ + TIMER_CHCTL2(timer_periph) |= (uint32_t)TIMER_CHCTL2_CH1EN; + break; + /* configure TIMER_CH_2 */ + case TIMER_CH_2: + /* reset the CH2EN bit */ + TIMER_CHCTL2(timer_periph) &= (~(uint32_t)TIMER_CHCTL2_CH2EN); + + /* reset the CH2P and CH2NP bits */ + TIMER_CHCTL2(timer_periph) &= (~(uint32_t)(TIMER_CHCTL2_CH2P | TIMER_CHCTL2_CH2NP)); + TIMER_CHCTL2(timer_periph) |= (uint32_t)((uint32_t)(icpara->icpolarity) << 8U); + + /* reset the CH2MS bit */ + TIMER_CHCTL1(timer_periph) &= (~(uint32_t)TIMER_CHCTL1_CH2MS); + TIMER_CHCTL1(timer_periph) |= (uint32_t)((uint32_t)(icpara->icselection)); + + /* reset the CH2CAPFLT bit */ + TIMER_CHCTL1(timer_periph) &= (~(uint32_t)TIMER_CHCTL1_CH2CAPFLT); + TIMER_CHCTL1(timer_periph) |= (uint32_t)((uint32_t)(icpara->icfilter) << 4U); + + /* set the CH2EN bit */ + TIMER_CHCTL2(timer_periph) |= (uint32_t)TIMER_CHCTL2_CH2EN; + break; + /* configure TIMER_CH_3 */ + case TIMER_CH_3: + /* reset the CH3EN bit */ + TIMER_CHCTL2(timer_periph) &= (~(uint32_t)TIMER_CHCTL2_CH3EN); + + /* reset the CH3P bits */ + TIMER_CHCTL2(timer_periph) &= (~(uint32_t)(TIMER_CHCTL2_CH3P)); + TIMER_CHCTL2(timer_periph) |= (uint32_t)((uint32_t)(icpara->icpolarity) << 12U); + + /* reset the CH3MS bit */ + TIMER_CHCTL1(timer_periph) &= (~(uint32_t)TIMER_CHCTL1_CH3MS); + TIMER_CHCTL1(timer_periph) |= (uint32_t)((uint32_t)(icpara->icselection) << 8U); + + /* reset the CH3CAPFLT bit */ + TIMER_CHCTL1(timer_periph) &= (~(uint32_t)TIMER_CHCTL1_CH3CAPFLT); + TIMER_CHCTL1(timer_periph) |= (uint32_t)((uint32_t)(icpara->icfilter) << 12U); + + /* set the CH3EN bit */ + TIMER_CHCTL2(timer_periph) |= (uint32_t)TIMER_CHCTL2_CH3EN; + break; + default: + break; + } + /* configure TIMER channel input capture prescaler value */ + timer_channel_input_capture_prescaler_config(timer_periph,channel,(uint16_t)(icpara->icprescaler)); +} + +/*! + \brief configure TIMER channel input capture prescaler value + \param[in] timer_periph: please refer to the following parameters + \param[in] channel: + only one parameter can be selected which is shown as below: + \arg TIMER_CH_0: TIMER channel0(TIMERx(x=0..4,7..13)) + \arg TIMER_CH_1: TIMER channel1(TIMERx(x=0..4,7,8,11)) + \arg TIMER_CH_2: TIMER channel2(TIMERx(x=0..4,7)) + \arg TIMER_CH_3: TIMER channel3(TIMERx(x=0..4,7)) + \param[in] prescaler: channel input capture prescaler value + only one parameter can be selected which is shown as below: + \arg TIMER_IC_PSC_DIV1: no prescaler + \arg TIMER_IC_PSC_DIV2: divided by 2 + \arg TIMER_IC_PSC_DIV4: divided by 4 + \arg TIMER_IC_PSC_DIV8: divided by 8 + \param[out] none + \retval none +*/ +void timer_channel_input_capture_prescaler_config(uint32_t timer_periph, uint16_t channel, uint16_t prescaler) +{ + switch(channel){ + /* configure TIMER_CH_0 */ + case TIMER_CH_0: + TIMER_CHCTL0(timer_periph) &= (~(uint32_t)TIMER_CHCTL0_CH0CAPPSC); + TIMER_CHCTL0(timer_periph) |= (uint32_t)prescaler; + break; + /* configure TIMER_CH_1 */ + case TIMER_CH_1: + TIMER_CHCTL0(timer_periph) &= (~(uint32_t)TIMER_CHCTL0_CH1CAPPSC); + TIMER_CHCTL0(timer_periph) |= ((uint32_t)prescaler << 8U); + break; + /* configure TIMER_CH_2 */ + case TIMER_CH_2: + TIMER_CHCTL1(timer_periph) &= (~(uint32_t)TIMER_CHCTL1_CH2CAPPSC); + TIMER_CHCTL1(timer_periph) |= (uint32_t)prescaler; + break; + /* configure TIMER_CH_3 */ + case TIMER_CH_3: + TIMER_CHCTL1(timer_periph) &= (~(uint32_t)TIMER_CHCTL1_CH3CAPPSC); + TIMER_CHCTL1(timer_periph) |= ((uint32_t)prescaler << 8U); + break; + default: + break; + } +} + +/*! + \brief read TIMER channel capture compare register value + \param[in] timer_periph: please refer to the following parameters + \param[in] channel: + only one parameter can be selected which is shown as below: + \arg TIMER_CH_0: TIMER channel0(TIMERx(x=0..4,7..13)) + \arg TIMER_CH_1: TIMER channel1(TIMERx(x=0..4,7,8,11)) + \arg TIMER_CH_2: TIMER channel2(TIMERx(x=0..4,7)) + \arg TIMER_CH_3: TIMER channel3(TIMERx(x=0..4,7)) + \param[out] none + \retval channel capture compare register value +*/ +uint32_t timer_channel_capture_value_register_read(uint32_t timer_periph, uint16_t channel) +{ + uint32_t count_value = 0U; + + switch(channel){ + case TIMER_CH_0: + /* read TIMER channel 0 capture compare register value */ + count_value = TIMER_CH0CV(timer_periph); + break; + case TIMER_CH_1: + /* read TIMER channel 1 capture compare register value */ + count_value = TIMER_CH1CV(timer_periph); + break; + case TIMER_CH_2: + /* read TIMER channel 2 capture compare register value */ + count_value = TIMER_CH2CV(timer_periph); + break; + case TIMER_CH_3: + /* read TIMER channel 3 capture compare register value */ + count_value = TIMER_CH3CV(timer_periph); + break; + default: + break; + } + return (count_value); +} + +/*! + \brief configure TIMER input pwm capture function + \param[in] timer_periph: TIMERx(x=0..4,7,8,11) + \param[in] channel: + only one parameter can be selected which is shown as below: + \arg TIMER_CH_0: TIMER channel0 + \arg TIMER_CH_1: TIMER channel1 + \param[in] icpwm:TIMER channel intput pwm parameter struct + icpolarity: TIMER_IC_POLARITY_RISING,TIMER_IC_POLARITY_FALLING + icselection: TIMER_IC_SELECTION_DIRECTTI,TIMER_IC_SELECTION_INDIRECTTI + icprescaler: TIMER_IC_PSC_DIV1,TIMER_IC_PSC_DIV2,TIMER_IC_PSC_DIV4,TIMER_IC_PSC_DIV8 + icfilter: 0~15 + \param[out] none + \retval none +*/ +void timer_input_pwm_capture_config(uint32_t timer_periph, uint16_t channel, timer_ic_parameter_struct* icpwm) +{ + uint16_t icpolarity = 0x0U; + uint16_t icselection = 0x0U; + + /* Set channel input polarity */ + if(TIMER_IC_POLARITY_RISING == icpwm->icpolarity){ + icpolarity = TIMER_IC_POLARITY_FALLING; + }else{ + icpolarity = TIMER_IC_POLARITY_RISING; + } + /* Set channel input mode selection */ + if(TIMER_IC_SELECTION_DIRECTTI == icpwm->icselection){ + icselection = TIMER_IC_SELECTION_INDIRECTTI; + }else{ + icselection = TIMER_IC_SELECTION_DIRECTTI; + } + + if(TIMER_CH_0 == channel){ + /* reset the CH0EN bit */ + TIMER_CHCTL2(timer_periph) &= (~(uint32_t)TIMER_CHCTL2_CH0EN); + /* reset the CH0P and CH0NP bits */ + TIMER_CHCTL2(timer_periph) &= (~(uint32_t)(TIMER_CHCTL2_CH0P | TIMER_CHCTL2_CH0NP)); + /* set the CH0P and CH0NP bits */ + TIMER_CHCTL2(timer_periph) |= (uint32_t)(icpwm->icpolarity); + /* reset the CH0MS bit */ + TIMER_CHCTL0(timer_periph) &= (~(uint32_t)TIMER_CHCTL0_CH0MS); + /* set the CH0MS bit */ + TIMER_CHCTL0(timer_periph) |= (uint32_t)(icpwm->icselection); + /* reset the CH0CAPFLT bit */ + TIMER_CHCTL0(timer_periph) &= (~(uint32_t)TIMER_CHCTL0_CH0CAPFLT); + /* set the CH0CAPFLT bit */ + TIMER_CHCTL0(timer_periph) |= ((uint32_t)(icpwm->icfilter) << 4U); + /* set the CH0EN bit */ + TIMER_CHCTL2(timer_periph) |= (uint32_t)TIMER_CHCTL2_CH0EN; + /* configure TIMER channel input capture prescaler value */ + timer_channel_input_capture_prescaler_config(timer_periph,TIMER_CH_0,(uint16_t)(icpwm->icprescaler)); + + /* reset the CH1EN bit */ + TIMER_CHCTL2(timer_periph) &= (~(uint32_t)TIMER_CHCTL2_CH1EN); + /* reset the CH1P and CH1NP bits */ + TIMER_CHCTL2(timer_periph) &= (~(uint32_t)(TIMER_CHCTL2_CH1P|TIMER_CHCTL2_CH1NP)); + /* set the CH1P and CH1NP bits */ + TIMER_CHCTL2(timer_periph) |= (uint32_t)((uint32_t)icpolarity<< 4U); + /* reset the CH1MS bit */ + TIMER_CHCTL0(timer_periph) &= (~(uint32_t)TIMER_CHCTL0_CH1MS); + /* set the CH1MS bit */ + TIMER_CHCTL0(timer_periph) |= (uint32_t)((uint32_t)icselection<< 8U); + /* reset the CH1CAPFLT bit */ + TIMER_CHCTL0(timer_periph) &= (~(uint32_t)TIMER_CHCTL0_CH1CAPFLT); + /* set the CH1CAPFLT bit */ + TIMER_CHCTL0(timer_periph) |= (uint32_t)((uint32_t)(icpwm->icfilter)<< 12U); + /* set the CH1EN bit */ + TIMER_CHCTL2(timer_periph) |= (uint32_t)TIMER_CHCTL2_CH1EN; + /* configure TIMER channel input capture prescaler value */ + timer_channel_input_capture_prescaler_config(timer_periph,TIMER_CH_1,(uint16_t)(icpwm->icprescaler)); + }else{ + /* reset the CH1EN bit */ + TIMER_CHCTL2(timer_periph) &= (~(uint32_t)TIMER_CHCTL2_CH1EN); + /* reset the CH1P and CH1NP bits */ + TIMER_CHCTL2(timer_periph) &= (~(uint32_t)(TIMER_CHCTL2_CH1P|TIMER_CHCTL2_CH1NP)); + /* set the CH1P and CH1NP bits */ + TIMER_CHCTL2(timer_periph) |= (uint32_t)((uint32_t)(icpwm->icpolarity)<< 4U); + /* reset the CH1MS bit */ + TIMER_CHCTL0(timer_periph) &= (~(uint32_t)TIMER_CHCTL0_CH1MS); + /* set the CH1MS bit */ + TIMER_CHCTL0(timer_periph) |= (uint32_t)((uint32_t)(icpwm->icselection)<< 8U); + /* reset the CH1CAPFLT bit */ + TIMER_CHCTL0(timer_periph) &= (~(uint32_t)TIMER_CHCTL0_CH1CAPFLT); + /* set the CH1CAPFLT bit */ + TIMER_CHCTL0(timer_periph) |= (uint32_t)((uint32_t)(icpwm->icfilter)<< 12U); + /* set the CH1EN bit */ + TIMER_CHCTL2(timer_periph) |= (uint32_t)TIMER_CHCTL2_CH1EN; + /* configure TIMER channel input capture prescaler value */ + timer_channel_input_capture_prescaler_config(timer_periph,TIMER_CH_1,(uint16_t)(icpwm->icprescaler)); + + /* reset the CH0EN bit */ + TIMER_CHCTL2(timer_periph) &= (~(uint32_t)TIMER_CHCTL2_CH0EN); + /* reset the CH0P and CH0NP bits */ + TIMER_CHCTL2(timer_periph) &= (~(uint32_t)(TIMER_CHCTL2_CH0P|TIMER_CHCTL2_CH0NP)); + /* set the CH0P and CH0NP bits */ + TIMER_CHCTL2(timer_periph) |= (uint32_t)icpolarity; + /* reset the CH0MS bit */ + TIMER_CHCTL0(timer_periph) &= (~(uint32_t)TIMER_CHCTL0_CH0MS); + /* set the CH0MS bit */ + TIMER_CHCTL0(timer_periph) |= (uint32_t)icselection; + /* reset the CH0CAPFLT bit */ + TIMER_CHCTL0(timer_periph) &= (~(uint32_t)TIMER_CHCTL0_CH0CAPFLT); + /* set the CH0CAPFLT bit */ + TIMER_CHCTL0(timer_periph) |= ((uint32_t)(icpwm->icfilter) << 4U); + /* set the CH0EN bit */ + TIMER_CHCTL2(timer_periph) |= (uint32_t)TIMER_CHCTL2_CH0EN; + /* configure TIMER channel input capture prescaler value */ + timer_channel_input_capture_prescaler_config(timer_periph,TIMER_CH_0,(uint16_t)(icpwm->icprescaler)); + } +} + +/*! + \brief configure TIMER hall sensor mode + \param[in] timer_periph: TIMERx(x=0..4,7) + \param[in] hallmode: + only one parameter can be selected which is shown as below: + \arg TIMER_HALLINTERFACE_ENABLE: TIMER hall sensor mode enable + \arg TIMER_HALLINTERFACE_DISABLE: TIMER hall sensor mode disable + \param[out] none + \retval none +*/ +void timer_hall_mode_config(uint32_t timer_periph, uint32_t hallmode) +{ + if(TIMER_HALLINTERFACE_ENABLE == hallmode){ + TIMER_CTL1(timer_periph) |= (uint32_t)TIMER_CTL1_TI0S; + }else if(TIMER_HALLINTERFACE_DISABLE == hallmode){ + TIMER_CTL1(timer_periph) &= ~(uint32_t)TIMER_CTL1_TI0S; + }else{ + /* illegal parameters */ + } +} + +/*! + \brief select TIMER input trigger source + \param[in] timer_periph: please refer to the following parameters + \param[in] intrigger: + only one parameter can be selected which is shown as below: + \arg TIMER_SMCFG_TRGSEL_ITI0: internal trigger 0,TIMERx(x=0..4,7,8,11) + \arg TIMER_SMCFG_TRGSEL_ITI1: internal trigger 1,TIMERx(x=0..4,7,8,11) + \arg TIMER_SMCFG_TRGSEL_ITI2: internal trigger 2,TIMERx(x=0..4,7,8,11) + \arg TIMER_SMCFG_TRGSEL_ITI3: internal trigger 3,TIMERx(x=0..4,7,8,11) + \arg TIMER_SMCFG_TRGSEL_CI0F_ED: TI0 edge detector,TIMERx(x=0..4,7,8,11) + \arg TIMER_SMCFG_TRGSEL_CI0FE0: filtered TIMER input 0,TIMERx(x=0..4,7,8,11) + \arg TIMER_SMCFG_TRGSEL_CI1FE1: filtered TIMER input 1,TIMERx(x=0..4,7,8,11) + \arg TIMER_SMCFG_TRGSEL_ETIFP: external trigger,TIMERx(x=0..4,7) + \param[out] none + \retval none +*/ +void timer_input_trigger_source_select(uint32_t timer_periph, uint32_t intrigger) +{ + TIMER_SMCFG(timer_periph) &= (~(uint32_t)TIMER_SMCFG_TRGS); + TIMER_SMCFG(timer_periph) |= (uint32_t)intrigger; +} + +/*! + \brief select TIMER master mode output trigger source + \param[in] timer_periph: TIMERx(x=0..7) + \param[in] outrigger: + only one parameter can be selected which is shown as below: + \arg TIMER_TRI_OUT_SRC_RESET: the UPG bit as trigger output(TIMERx(x=0..7)) + \arg TIMER_TRI_OUT_SRC_ENABLE: the counter enable signal TIMER_CTL0_CEN as trigger output(TIMERx(x=0..7)) + \arg TIMER_TRI_OUT_SRC_UPDATE: update event as trigger output(TIMERx(x=0..7)) + \arg TIMER_TRI_OUT_SRC_CH0: a capture or a compare match occurred in channel 0 as trigger output TRGO(TIMERx(x=0..4,7)) + \arg TIMER_TRI_OUT_SRC_O0CPRE: O0CPRE as trigger output(TIMERx(x=0..4,7)) + \arg TIMER_TRI_OUT_SRC_O1CPRE: O1CPRE as trigger output(TIMERx(x=0..4,7)) + \arg TIMER_TRI_OUT_SRC_O2CPRE: O2CPRE as trigger output(TIMERx(x=0..4,7)) + \arg TIMER_TRI_OUT_SRC_O3CPRE: O3CPRE as trigger output(TIMERx(x=0..4,7)) + \param[out] none + \retval none +*/ +void timer_master_output_trigger_source_select(uint32_t timer_periph, uint32_t outrigger) +{ + TIMER_CTL1(timer_periph) &= (~(uint32_t)TIMER_CTL1_MMC); + TIMER_CTL1(timer_periph) |= (uint32_t)outrigger; +} + +/*! + \brief select TIMER slave mode + \param[in] timer_periph: TIMERx(x=0..4,7,8,11) + \param[in] slavemode: + only one parameter can be selected which is shown as below: + \arg TIMER_SLAVE_MODE_DISABLE: slave mode disable + \arg TIMER_ENCODER_MODE0: encoder mode 0 + \arg TIMER_ENCODER_MODE1: encoder mode 1 + \arg TIMER_ENCODER_MODE2: encoder mode 2 + \arg TIMER_SLAVE_MODE_RESTART: restart mode + \arg TIMER_SLAVE_MODE_PAUSE: pause mode + \arg TIMER_SLAVE_MODE_EVENT: event mode + \arg TIMER_SLAVE_MODE_EXTERNAL0: external clock mode 0. + \param[out] none + \retval none +*/ + +void timer_slave_mode_select(uint32_t timer_periph, uint32_t slavemode) +{ + TIMER_SMCFG(timer_periph) &= (~(uint32_t)TIMER_SMCFG_SMC); + + TIMER_SMCFG(timer_periph) |= (uint32_t)slavemode; +} + +/*! + \brief configure TIMER master slave mode + \param[in] timer_periph: TIMERx(x=0..4,7,8,11) + \param[in] masterslave: + only one parameter can be selected which is shown as below: + \arg TIMER_MASTER_SLAVE_MODE_ENABLE: master slave mode enable + \arg TIMER_MASTER_SLAVE_MODE_DISABLE: master slave mode disable + \param[out] none + \retval none +*/ +void timer_master_slave_mode_config(uint32_t timer_periph, uint32_t masterslave) +{ + if(TIMER_MASTER_SLAVE_MODE_ENABLE == masterslave){ + TIMER_SMCFG(timer_periph) |= (uint32_t)TIMER_SMCFG_MSM; + }else if(TIMER_MASTER_SLAVE_MODE_DISABLE == masterslave){ + TIMER_SMCFG(timer_periph) &= ~(uint32_t)TIMER_SMCFG_MSM; + }else{ + /* illegal parameters */ + } +} + +/*! + \brief configure TIMER external trigger input + \param[in] timer_periph: TIMERx(x=0..4,7) + \param[in] extprescaler: + only one parameter can be selected which is shown as below: + \arg TIMER_EXT_TRI_PSC_OFF: no divided + \arg TIMER_EXT_TRI_PSC_DIV2: divided by 2 + \arg TIMER_EXT_TRI_PSC_DIV4: divided by 4 + \arg TIMER_EXT_TRI_PSC_DIV8: divided by 8 + \param[in] expolarity: + only one parameter can be selected which is shown as below: + \arg TIMER_ETP_FALLING: active low or falling edge active + \arg TIMER_ETP_RISING: active high or rising edge active + \param[in] extfilter: a value between 0 and 15 + \param[out] none + \retval none +*/ +void timer_external_trigger_config(uint32_t timer_periph, uint32_t extprescaler, uint32_t extpolarity, uint8_t extfilter) +{ + TIMER_SMCFG(timer_periph) &= (~(uint32_t)(TIMER_SMCFG_ETP | TIMER_SMCFG_ETPSC | TIMER_SMCFG_ETFC)); + TIMER_SMCFG(timer_periph) |= (uint32_t)(extprescaler | extpolarity); + TIMER_SMCFG(timer_periph) |= (uint32_t)(extfilter << 8U); +} + +/*! + \brief configure TIMER quadrature decoder mode + \param[in] timer_periph: TIMERx(x=0..4,7,8,11) + \param[in] decomode: + only one parameter can be selected which is shown as below: + \arg TIMER_ENCODER_MODE0: counter counts on CI0FE0 edge depending on CI1FE1 level + \arg TIMER_ENCODER_MODE1: counter counts on CI1FE1 edge depending on CI0FE0 level + \arg TIMER_ENCODER_MODE2: counter counts on both CI0FE0 and CI1FE1 edges depending on the level of the other input + \param[in] ic0polarity: + only one parameter can be selected which is shown as below: + \arg TIMER_IC_POLARITY_RISING: capture rising edge + \arg TIMER_IC_POLARITY_FALLING: capture falling edge + \param[in] ic1polarity: + only one parameter can be selected which is shown as below: + \arg TIMER_IC_POLARITY_RISING: capture rising edge + \arg TIMER_IC_POLARITY_FALLING: capture falling edge + \param[out] none + \retval none +*/ +void timer_quadrature_decoder_mode_config(uint32_t timer_periph, uint32_t decomode, uint16_t ic0polarity, uint16_t ic1polarity) +{ + /* configure the quadrature decoder mode */ + TIMER_SMCFG(timer_periph) &= (~(uint32_t)TIMER_SMCFG_SMC); + TIMER_SMCFG(timer_periph) |= (uint32_t)decomode; + /* configure input capture selection */ + TIMER_CHCTL0(timer_periph) &= (uint32_t)(((~(uint32_t)TIMER_CHCTL0_CH0MS)) & ((~(uint32_t)TIMER_CHCTL0_CH1MS))); + TIMER_CHCTL0(timer_periph) |= (uint32_t)(TIMER_IC_SELECTION_DIRECTTI | ((uint32_t)TIMER_IC_SELECTION_DIRECTTI << 8U)); + /* configure channel input capture polarity */ + TIMER_CHCTL2(timer_periph) &= (~(uint32_t)(TIMER_CHCTL2_CH0P | TIMER_CHCTL2_CH0NP)); + TIMER_CHCTL2(timer_periph) &= (~(uint32_t)(TIMER_CHCTL2_CH1P | TIMER_CHCTL2_CH1NP)); + TIMER_CHCTL2(timer_periph) |= ((uint32_t)ic0polarity | ((uint32_t)ic1polarity << 4U)); +} + +/*! + \brief configure TIMER internal clock mode + \param[in] timer_periph: TIMERx(x=0..4,7,8,11) + \param[out] none + \retval none +*/ +void timer_internal_clock_config(uint32_t timer_periph) +{ + TIMER_SMCFG(timer_periph) &= ~(uint32_t)TIMER_SMCFG_SMC; +} + +/*! + \brief configure TIMER the internal trigger as external clock input + \param[in] timer_periph: TIMERx(x=0..4,7,8,11) + \param[in] intrigger: + only one parameter can be selected which is shown as below: + \arg TIMER_SMCFG_TRGSEL_ITI0: internal trigger 0 + \arg TIMER_SMCFG_TRGSEL_ITI1: internal trigger 1 + \arg TIMER_SMCFG_TRGSEL_ITI2: internal trigger 2 + \arg TIMER_SMCFG_TRGSEL_ITI3: internal trigger 3 + \param[out] none + \retval none +*/ +void timer_internal_trigger_as_external_clock_config(uint32_t timer_periph, uint32_t intrigger) +{ + timer_input_trigger_source_select(timer_periph,intrigger); + TIMER_SMCFG(timer_periph) &= ~(uint32_t)TIMER_SMCFG_SMC; + TIMER_SMCFG(timer_periph) |= (uint32_t)TIMER_SLAVE_MODE_EXTERNAL0; +} + +/*! + \brief configure TIMER the external trigger as external clock input + \param[in] timer_periph: TIMERx(x=0..4,7,8,11) + \param[in] extrigger: + only one parameter can be selected which is shown as below: + \arg TIMER_SMCFG_TRGSEL_CI0F_ED: TI0 edge detector + \arg TIMER_SMCFG_TRGSEL_CI0FE0: filtered TIMER input 0 + \arg TIMER_SMCFG_TRGSEL_CI1FE1: filtered TIMER input 1 + \param[in] expolarity: + only one parameter can be selected which is shown as below: + \arg TIMER_IC_POLARITY_RISING: active high or rising edge active + \arg TIMER_IC_POLARITY_FALLING: active low or falling edge active + \param[in] extfilter: a value between 0 and 15 + \param[out] none + \retval none +*/ +void timer_external_trigger_as_external_clock_config(uint32_t timer_periph, uint32_t extrigger, uint16_t extpolarity, uint8_t extfilter) +{ + if(TIMER_SMCFG_TRGSEL_CI1FE1 == extrigger){ + /* reset the CH1EN bit */ + TIMER_CHCTL2(timer_periph) &= (~(uint32_t)TIMER_CHCTL2_CH1EN); + /* reset the CH1NP bit */ + TIMER_CHCTL2(timer_periph) &= (~(uint32_t)(TIMER_CHCTL2_CH1P|TIMER_CHCTL2_CH1NP)); + /* set the CH1NP bit */ + TIMER_CHCTL2(timer_periph) |= (uint32_t)((uint32_t)extpolarity << 4U); + /* reset the CH1MS bit */ + TIMER_CHCTL0(timer_periph) &= (~(uint32_t)TIMER_CHCTL0_CH1MS); + /* set the CH1MS bit */ + TIMER_CHCTL0(timer_periph) |= (uint32_t)((uint32_t)TIMER_IC_SELECTION_DIRECTTI<< 8U); + /* reset the CH1CAPFLT bit */ + TIMER_CHCTL0(timer_periph) &= (~(uint32_t)TIMER_CHCTL0_CH1CAPFLT); + /* set the CH1CAPFLT bit */ + TIMER_CHCTL0(timer_periph) |= (uint32_t)(extfilter << 12U); + /* set the CH1EN bit */ + TIMER_CHCTL2(timer_periph) |= (uint32_t)TIMER_CHCTL2_CH1EN; + }else{ + /* reset the CH0EN bit */ + TIMER_CHCTL2(timer_periph) &= (~(uint32_t)TIMER_CHCTL2_CH0EN); + /* reset the CH0P and CH0NP bits */ + TIMER_CHCTL2(timer_periph) &= (~(uint32_t)(TIMER_CHCTL2_CH0P|TIMER_CHCTL2_CH0NP)); + /* set the CH0P and CH0NP bits */ + TIMER_CHCTL2(timer_periph) |= (uint32_t)extpolarity; + /* reset the CH0MS bit */ + TIMER_CHCTL0(timer_periph) &= (~(uint32_t)TIMER_CHCTL0_CH0MS); + /* set the CH0MS bit */ + TIMER_CHCTL0(timer_periph) |= (uint32_t)TIMER_IC_SELECTION_DIRECTTI; + /* reset the CH0CAPFLT bit */ + TIMER_CHCTL0(timer_periph) &= (~(uint32_t)TIMER_CHCTL0_CH0CAPFLT); + /* reset the CH0CAPFLT bit */ + TIMER_CHCTL0(timer_periph) |= (uint32_t)(extfilter << 4U); + /* set the CH0EN bit */ + TIMER_CHCTL2(timer_periph) |= (uint32_t)TIMER_CHCTL2_CH0EN; + } + /* select TIMER input trigger source */ + timer_input_trigger_source_select(timer_periph, extrigger); + /* reset the SMC bit */ + TIMER_SMCFG(timer_periph) &= (~(uint32_t)TIMER_SMCFG_SMC); + /* set the SMC bit */ + TIMER_SMCFG(timer_periph) |= (uint32_t)TIMER_SLAVE_MODE_EXTERNAL0; +} + +/*! + \brief configure TIMER the external clock mode0 + \param[in] timer_periph: TIMERx(x=0..4,7,8,11) + \param[in] extprescaler: + only one parameter can be selected which is shown as below: + \arg TIMER_EXT_TRI_PSC_OFF: no divided + \arg TIMER_EXT_TRI_PSC_DIV2: divided by 2 + \arg TIMER_EXT_TRI_PSC_DIV4: divided by 4 + \arg TIMER_EXT_TRI_PSC_DIV8: divided by 8 + \param[in] expolarity: + only one parameter can be selected which is shown as below: + \arg TIMER_ETP_FALLING: active low or falling edge active + \arg TIMER_ETP_RISING: active high or rising edge active + \param[in] extfilter: a value between 0 and 15 + \param[out] none + \retval none +*/ +void timer_external_clock_mode0_config(uint32_t timer_periph, uint32_t extprescaler, uint32_t extpolarity, uint8_t extfilter) +{ + /* configure TIMER external trigger input */ + timer_external_trigger_config(timer_periph, extprescaler, extpolarity, extfilter); + /* reset the SMC bit,TRGS bit */ + TIMER_SMCFG(timer_periph) &= (~(uint32_t)(TIMER_SMCFG_SMC | TIMER_SMCFG_TRGS)); + /* set the SMC bit,TRGS bit */ + TIMER_SMCFG(timer_periph) |= (uint32_t)(TIMER_SLAVE_MODE_EXTERNAL0 | TIMER_SMCFG_TRGSEL_ETIFP); +} + +/*! + \brief configure TIMER the external clock mode1 + \param[in] timer_periph: TIMERx(x=0..4,7) + \param[in] extprescaler: + only one parameter can be selected which is shown as below: + \arg TIMER_EXT_TRI_PSC_OFF: no divided + \arg TIMER_EXT_TRI_PSC_DIV2: divided by 2 + \arg TIMER_EXT_TRI_PSC_DIV4: divided by 4 + \arg TIMER_EXT_TRI_PSC_DIV8: divided by 8 + \param[in] extpolarity: + only one parameter can be selected which is shown as below: + \arg TIMER_ETP_FALLING: active low or falling edge active + \arg TIMER_ETP_RISING: active high or rising edge active + \param[in] extfilter: a value between 0 and 15 + \param[out] none + \retval none +*/ +void timer_external_clock_mode1_config(uint32_t timer_periph, uint32_t extprescaler, uint32_t extpolarity, uint8_t extfilter) +{ + /* configure TIMER external trigger input */ + timer_external_trigger_config(timer_periph, extprescaler, extpolarity, extfilter); + TIMER_SMCFG(timer_periph) |= (uint32_t)TIMER_SMCFG_SMC1; +} + +/*! + \brief disable TIMER the external clock mode1 + \param[in] timer_periph: TIMERx(x=0..4,7) + \param[out] none + \retval none +*/ +void timer_external_clock_mode1_disable(uint32_t timer_periph) +{ + TIMER_SMCFG(timer_periph) &= ~(uint32_t)TIMER_SMCFG_SMC1; +} + +/*! + \brief enable the TIMER interrupt + \param[in] timer_periph: please refer to the following parameters + \param[in] interrupt: timer interrupt enable source + only one parameter can be selected which is shown as below: + \arg TIMER_INT_UP: update interrupt enable, TIMERx(x=0..13) + \arg TIMER_INT_CH0: channel 0 interrupt enable, TIMERx(x=0..4,7..13) + \arg TIMER_INT_CH1: channel 1 interrupt enable, TIMERx(x=0..4,7,8,11) + \arg TIMER_INT_CH2: channel 2 interrupt enable, TIMERx(x=0..4,7) + \arg TIMER_INT_CH3: channel 3 interrupt enable , TIMERx(x=0..4,7) + \arg TIMER_INT_CMT: commutation interrupt enable, TIMERx(x=0,7) + \arg TIMER_INT_TRG: trigger interrupt enable, TIMERx(x=0..4,7,8,11) + \arg TIMER_INT_BRK: break interrupt enable, TIMERx(x=0,7) + \param[out] none + \retval none +*/ +void timer_interrupt_enable(uint32_t timer_periph, uint32_t interrupt) +{ + TIMER_DMAINTEN(timer_periph) |= (uint32_t) interrupt; +} + +/*! + \brief disable the TIMER interrupt + \param[in] timer_periph: please refer to the following parameters + \param[in] interrupt: timer interrupt source disable + only one parameter can be selected which is shown as below: + \arg TIMER_INT_UP: update interrupt disable, TIMERx(x=0..13) + \arg TIMER_INT_CH0: channel 0 interrupt disable, TIMERx(x=0..4,7..13) + \arg TIMER_INT_CH1: channel 1 interrupt disable, TIMERx(x=0..4,7,8,11) + \arg TIMER_INT_CH2: channel 2 interrupt disable, TIMERx(x=0..4,7) + \arg TIMER_INT_CH3: channel 3 interrupt disable , TIMERx(x=0..4,7) + \arg TIMER_INT_CMT: commutation interrupt disable, TIMERx(x=0,7) + \arg TIMER_INT_TRG: trigger interrupt disable, TIMERx(x=0..4,7,8,11) + \arg TIMER_INT_BRK: break interrupt disable, TIMERx(x=0,7) + \param[out] none + \retval none +*/ +void timer_interrupt_disable(uint32_t timer_periph, uint32_t interrupt) +{ + TIMER_DMAINTEN(timer_periph) &= (~(uint32_t)interrupt); +} + +/*! + \brief get timer interrupt flag + \param[in] timer_periph: please refer to the following parameters + \param[in] interrupt: the timer interrupt bits + only one parameter can be selected which is shown as below: + \arg TIMER_INT_FLAG_UP: update interrupt flag,TIMERx(x=0..13) + \arg TIMER_INT_FLAG_CH0: channel 0 interrupt flag,TIMERx(x=0..4,7..13) + \arg TIMER_INT_FLAG_CH1: channel 1 interrupt flag,TIMERx(x=0..4,7,8,11) + \arg TIMER_INT_FLAG_CH2: channel 2 interrupt flag,TIMERx(x=0..4,7) + \arg TIMER_INT_FLAG_CH3: channel 3 interrupt flag,TIMERx(x=0..4,7) + \arg TIMER_INT_FLAG_CMT: channel commutation interrupt flag,TIMERx(x=0,7) + \arg TIMER_INT_FLAG_TRG: trigger interrupt flag,TIMERx(x=0,7,8,11) + \arg TIMER_INT_FLAG_BRK: break interrupt flag,TIMERx(x=0,7) + \param[out] none + \retval FlagStatus: SET or RESET +*/ +FlagStatus timer_interrupt_flag_get(uint32_t timer_periph, uint32_t interrupt) +{ + uint32_t val; + val = (TIMER_DMAINTEN(timer_periph) & interrupt); + if((RESET != (TIMER_INTF(timer_periph) & interrupt) ) && (RESET != val)){ + return SET; + }else{ + return RESET; + } +} + +/*! + \brief clear TIMER interrupt flag + \param[in] timer_periph: please refer to the following parameters + \param[in] interrupt: the timer interrupt bits + only one parameter can be selected which is shown as below: + \arg TIMER_INT_FLAG_UP: update interrupt flag,TIMERx(x=0..13) + \arg TIMER_INT_FLAG_CH0: channel 0 interrupt flag,TIMERx(x=0..4,7..13) + \arg TIMER_INT_FLAG_CH1: channel 1 interrupt flag,TIMERx(x=0..4,7,8,11) + \arg TIMER_INT_FLAG_CH2: channel 2 interrupt flag,TIMERx(x=0..4,7) + \arg TIMER_INT_FLAG_CH3: channel 3 interrupt flag,TIMERx(x=0..4,7) + \arg TIMER_INT_FLAG_CMT: channel commutation interrupt flag,TIMERx(x=0,7) + \arg TIMER_INT_FLAG_TRG: trigger interrupt flag,TIMERx(x=0,7,8,11) + \arg TIMER_INT_FLAG_BRK: break interrupt flag,TIMERx(x=0,7) + \param[out] none + \retval none +*/ +void timer_interrupt_flag_clear(uint32_t timer_periph, uint32_t interrupt) +{ + TIMER_INTF(timer_periph) = (~(uint32_t)interrupt); +} + +/*! + \brief get TIMER flags + \param[in] timer_periph: please refer to the following parameters + \param[in] flag: the timer interrupt flags + only one parameter can be selected which is shown as below: + \arg TIMER_FLAG_UP: update flag,TIMERx(x=0..13) + \arg TIMER_FLAG_CH0: channel 0 flag,TIMERx(x=0..4,7..13) + \arg TIMER_FLAG_CH1: channel 1 flag,TIMERx(x=0..4,7,8,11) + \arg TIMER_FLAG_CH2: channel 2 flag,TIMERx(x=0..4,7) + \arg TIMER_FLAG_CH3: channel 3 flag,TIMERx(x=0..4,7) + \arg TIMER_FLAG_CMT: channel commutation flag,TIMERx(x=0,7) + \arg TIMER_FLAG_TRG: trigger flag,TIMERx(x=0,7,8,11) + \arg TIMER_FLAG_BRK: break flag,TIMERx(x=0,7) + \arg TIMER_FLAG_CH0O: channel 0 overcapture flag,TIMERx(x=0..4,7..11) + \arg TIMER_FLAG_CH1O: channel 1 overcapture flag,TIMERx(x=0..4,7,8,11) + \arg TIMER_FLAG_CH2O: channel 2 overcapture flag,TIMERx(x=0..4,7) + \arg TIMER_FLAG_CH3O: channel 3 overcapture flag,TIMERx(x=0..4,7) + \param[out] none + \retval FlagStatus: SET or RESET +*/ +FlagStatus timer_flag_get(uint32_t timer_periph, uint32_t flag) +{ + if(RESET != (TIMER_INTF(timer_periph) & flag)){ + return SET; + }else{ + return RESET; + } +} + +/*! + \brief clear TIMER flags + \param[in] timer_periph: please refer to the following parameters + \param[in] flag: the timer interrupt flags + only one parameter can be selected which is shown as below: + \arg TIMER_FLAG_UP: update flag,TIMERx(x=0..13) + \arg TIMER_FLAG_CH0: channel 0 flag,TIMERx(x=0..4,7..13) + \arg TIMER_FLAG_CH1: channel 1 flag,TIMERx(x=0..4,7,8,11) + \arg TIMER_FLAG_CH2: channel 2 flag,TIMERx(x=0..4,7) + \arg TIMER_FLAG_CH3: channel 3 flag,TIMERx(x=0..4,7) + \arg TIMER_FLAG_CMT: channel control update flag,TIMERx(x=0,7) + \arg TIMER_FLAG_TRG: trigger flag,TIMERx(x=0,7,8,11) + \arg TIMER_FLAG_BRK: break flag,TIMERx(x=0,7) + \arg TIMER_FLAG_CH0O: channel 0 overcapture flag,TIMERx(x=0..4,7..11) + \arg TIMER_FLAG_CH1O: channel 1 overcapture flag,TIMERx(x=0..4,7,8,11) + \arg TIMER_FLAG_CH2O: channel 2 overcapture flag,TIMERx(x=0..4,7) + \arg TIMER_FLAG_CH3O: channel 3 overcapture flag,TIMERx(x=0..4,7) + \param[out] none + \retval none +*/ +void timer_flag_clear(uint32_t timer_periph, uint32_t flag) +{ + TIMER_INTF(timer_periph) = (~(uint32_t)flag); +} diff --git a/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_standard_peripheral/Source/gd32f20x_tli.c b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_standard_peripheral/Source/gd32f20x_tli.c new file mode 100644 index 0000000000..1e653dbc99 --- /dev/null +++ b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_standard_peripheral/Source/gd32f20x_tli.c @@ -0,0 +1,481 @@ +/*! + \file gd32f20x_tli.c + \brief TLI driver + + \version 2015-07-15, V1.0.0, firmware for GD32F20x + \version 2017-06-05, V2.0.0, firmware for GD32F20x + \version 2018-10-31, V2.1.0, firmware for GD32F20x + \version 2020-09-30, V2.2.0, firmware for GD32F20x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "gd32f20x_tli.h" + +/*! + \brief deinitialize TLI registers + \param[in] none + \param[out] none + \retval none +*/ +void tli_deinit(void) +{ + rcu_periph_reset_enable(RCU_TLIRST); + rcu_periph_reset_disable(RCU_TLIRST); +} + +/*! + \brief initialize TLI display timing parameters + \param[in] tli_struct: the data needed to initialize tli + synpsz_vpsz: size of the vertical synchronous pulse + synpsz_hpsz: size of the horizontal synchronous pulse + backpsz_vbpsz: size of the vertical back porch plus synchronous pulse + backpsz_hbpsz: size of the horizontal back porch plus synchronous pulse + activesz_vasz: size of the vertical active area width plus back porch and synchronous pulse + activesz_hasz: size of the horizontal active area width plus back porch and synchronous pulse + totalsz_vtsz: vertical total size of the display, including active area, back porch, synchronous + totalsz_htsz: vorizontal total size of the display, including active area, back porch, synchronous + backcolor_red: background value red + backcolor_green: background value green + backcolor_blue: background value blue + signalpolarity_hs: TLI_HSYN_ACTLIVE_LOW,TLI_HSYN_ACTLIVE_HIGHT + signalpolarity_vs: TLI_VSYN_ACTLIVE_LOW,TLI_VSYN_ACTLIVE_HIGHT + signalpolarity_de: TLI_DE_ACTLIVE_LOW,TLI_DE_ACTLIVE_HIGHT + signalpolarity_pixelck: TLI_PIXEL_CLOCK_TLI,TLI_PIXEL_CLOCK_INVERTEDTLI + \param[out] none + \retval none +*/ +void tli_init(tli_parameter_struct *tli_struct) +{ + /* synchronous pulse size configuration */ + TLI_SPSZ &= ~(TLI_SPSZ_VPSZ|TLI_SPSZ_HPSZ); + TLI_SPSZ = (tli_struct->synpsz_vpsz|(tli_struct->synpsz_hpsz<<16U)); + /* back-porch size configuration */ + TLI_BPSZ &= ~(TLI_BPSZ_VBPSZ|TLI_BPSZ_HBPSZ); + TLI_BPSZ = (tli_struct->backpsz_vbpsz|(tli_struct->backpsz_hbpsz<<16U)); + /* active size configuration */ + TLI_ASZ &= ~(TLI_ASZ_VASZ|TLI_ASZ_HASZ); + TLI_ASZ = (tli_struct->activesz_vasz|(tli_struct->activesz_hasz<<16U)); + /* total size configuration */ + TLI_TSZ &= ~(TLI_TSZ_VTSZ|TLI_TSZ_HTSZ); + TLI_TSZ = (tli_struct->totalsz_vtsz|(tli_struct->totalsz_htsz<<16U)); + /* background color configuration */ + TLI_BGC &= ~(TLI_BGC_BVB|(TLI_BGC_BVG)|(TLI_BGC_BVR)); + TLI_BGC = (tli_struct->backcolor_blue|(tli_struct->backcolor_green<<8U)|(tli_struct->backcolor_red<<16U)); + TLI_CTL &= ~(TLI_CTL_HPPS|TLI_CTL_VPPS|TLI_CTL_DEPS|TLI_CTL_CLKPS); + TLI_CTL |= (tli_struct->signalpolarity_hs|tli_struct->signalpolarity_vs|\ + tli_struct->signalpolarity_de|tli_struct->signalpolarity_pixelck); +} + +/*! + \brief configure TLI dither function + \param[in] ditherstat + \arg TLI_DITHER_ENABLE + \arg TLI_DITHER_DISABLE + \param[out] none + \retval none +*/ +void tli_dither_config(uint8_t ditherstat) +{ + if(TLI_DITHER_ENABLE == ditherstat){ + TLI_CTL |= TLI_CTL_DFEN; + }else{ + TLI_CTL &= ~(TLI_CTL_DFEN); + } +} + +/*! + \brief TLI enable + \param[in] none + \param[out] none + \retval none +*/ +void tli_enable(void) +{ + TLI_CTL |= TLI_CTL_TLIEN; +} + +/*! + \brief TLI disable + \param[in] none + \param[out] none + \retval none +*/ +void tli_disable(void) +{ + TLI_CTL &= ~(TLI_CTL_TLIEN); +} + +/*! + \brief configure TLI reload mode + \param[in] reloadmode + \arg TLI_FRAME_BLANK_RELOAD_EN + \arg TLI_REQUEST_RELOAD_EN + \param[out] none + \retval none +*/ +void tli_reload_config(uint8_t reloadmode) +{ + if(TLI_FRAME_BLANK_RELOAD_EN == reloadmode){ + TLI_RL |= TLI_RL_FBR; + }else{ + TLI_RL |= TLI_RL_RQR; + } +} + +/*! + \brief set line mark value + \param[in] linenum: line number + \param[out] none + \retval none +*/ +void tli_line_mark_set(uint32_t linenum) +{ + TLI_LM &= ~(TLI_LM_LM); + TLI_LM = linenum; +} + +/*! + \brief get current displayed position + \param[in] none + \param[out] none + \retval none +*/ +uint32_t tli_current_pos_get(void) +{ + return TLI_CPPOS; +} + +/*! + \brief TLI layer enable + \param[in] layerx: LAYERx(x=0,1) + \param[out] none + \retval none +*/ +void tli_layer_enable(uint32_t layerx) +{ + TLI_LxCTL(layerx) |= TLI_LxCTL_LEN; +} + +/*! + \brief TLI layer disable + \param[in] layerx: LAYERx(x=0,1) + \param[out] none + \retval none +*/ +void tli_layer_disable(uint32_t layerx) +{ + TLI_LxCTL(layerx) &= ~(TLI_LxCTL_LEN); +} + +/*! + \brief TLI layer color keying enable + \param[in] layerx: LAYERx(x=0,1) + \param[out] none + \retval none +*/ +void tli_color_key_enable(uint32_t layerx) +{ + TLI_LxCTL(layerx) |= TLI_LxCTL_CKEYEN; +} + +/*! + \brief TLI layer color keying disable + \param[in] layerx: LAYERx(x=0,1) + \param[out] none + \retval none +*/ +void tli_color_key_disable(uint32_t layerx) +{ + TLI_LxCTL(layerx) &= ~(TLI_LxCTL_CKEYEN); +} + +/*! + \brief TLI layer LUT enable + \param[in] layerx: LAYERx(x=0,1) + \param[out] none + \retval none +*/ +void tli_lut_enable(uint32_t layerx) +{ + TLI_LxCTL(layerx) |= TLI_LxCTL_LUTEN; +} + +/*! + \brief TLI layer LUT disable + \param[in] layerx: LAYERx(x=0,1) + \param[out] none + \retval none +*/ +void tli_lut_disable(uint32_t layerx) +{ + TLI_LxCTL(layerx) &= ~(TLI_LxCTL_LUTEN); +} + +/*! + \brief TLI layer initialize + \param[in] layerx: LAYERx(x=0,1) + \param[in] layer_struct: TLI Layer parameter struct + layer_window_rightpos: window right position + layer_window_leftpos: window left position + layer_window_bottompos: window bottom position + layer_window_toppos: window top position + layer_ppf: LAYER_PPF_ARGB8888,LAYER_PPF_RGB888,LAYER_PPF_RGB565, + LAYER_PPF_ARG1555,LAYER_PPF_ARGB4444,LAYER_PPF_L8, + LAYER_PPF_AL44,LAYER_PPF_AL88 + layer_sa: specified alpha + layer_default_alpha: the default color alpha + layer_default_red: the default color red + layer_default_green: the default color green + layer_default_blue: the default color blue + layer_acf1: LAYER_ACF1_SA,LAYER_ACF1_PASA + layer_acf2: LAYER_ACF2_SA,LAYER_ACF2_PASA + layer_frame_bufaddr: frame buffer base address + layer_frame_buf_stride_offset: frame buffer stride offset + layer_frame_line_length: frame line length + layer_frame_total_line_number: frame total line number + \param[out] none + \retval none +*/ +void tli_layer_init(uint32_t layerx,tli_layer_parameter_struct *layer_struct) +{ + /* configure layer window horizontal position */ + TLI_LxHPOS(layerx) &= ~(TLI_LxHPOS_WLP|(TLI_LxHPOS_WRP)); + TLI_LxHPOS(layerx) = (layer_struct->layer_window_leftpos | (layer_struct->layer_window_rightpos<<16U)); + /* configure layer window vertical position */ + TLI_LxVPOS(layerx) &= ~(TLI_LxVPOS_WTP|(TLI_LxVPOS_WBP)); + TLI_LxVPOS(layerx) = (layer_struct->layer_window_toppos |(layer_struct->layer_window_bottompos<<16U)); + /* configure layer packeted pixel format */ + TLI_LxPPF(layerx) &= ~(TLI_LxPPF_PPF); + TLI_LxPPF(layerx) = layer_struct->layer_ppf; + /* configure layer specified alpha */ + TLI_LxSA(layerx) &= ~(TLI_LxSA_SA); + TLI_LxSA(layerx) = layer_struct->layer_sa; + /* configure layer default color */ + TLI_LxDC(layerx) &= ~(TLI_LxDC_DCB|(TLI_LxDC_DCG)|(TLI_LxDC_DCR)|(TLI_LxDC_DCA)); + TLI_LxDC(layerx) = (layer_struct->layer_default_blue |(layer_struct->layer_default_green<<8U) + |(layer_struct->layer_default_red<<16U) + |(layer_struct->layer_default_alpha<<24U)); + + /* configure layer alpha calculation factors */ + TLI_LxBLEND(layerx) &= ~(TLI_LxBLEND_ACF2|(TLI_LxBLEND_ACF1)); + TLI_LxBLEND(layerx) = ((layer_struct->layer_acf2)|(layer_struct->layer_acf1)); + /* configure layer frame buffer base address */ + TLI_LxFBADDR(layerx) &= ~(TLI_LxFBADDR_FBADD); + TLI_LxFBADDR(layerx) = (layer_struct->layer_frame_bufaddr); + /* configure layer frame line length */ + TLI_LxFLLEN(layerx) &= ~(TLI_LxFLLEN_FLL|(TLI_LxFLLEN_STDOFF)); + TLI_LxFLLEN(layerx) = (layer_struct->layer_frame_line_length|(layer_struct->layer_frame_buf_stride_offset<<16U)); + /* configure layer frame buffer base address */ + TLI_LxFBADDR(layerx) &= ~(TLI_LxFBADDR_FBADD); + TLI_LxFBADDR(layerx) = (layer_struct->layer_frame_bufaddr); + /* configure layer frame total line number */ + TLI_LxFTLN(layerx) &= ~(TLI_LxFTLN_FTLN); + TLI_LxFTLN(layerx) = (layer_struct->layer_frame_total_line_number); +} + +/*! + \brief reconfigure window position + \param[in] layerx: LAYERx(x=0,1) + \param[in] offset_x: new horizontal offset + \param[in] offset_y: new vertical offset + \param[out] none + \retval none +*/ +void tli_layer_window_offset_modify(uint32_t layerx,uint32_t offset_x,uint32_t offset_y) +{ + /* configure window start position */ + uint32_t layer_ppf,line_length,line_num,hstart,vstart; + TLI_LxHPOS(layerx) &= ~(TLI_LxHPOS_WLP|(TLI_LxHPOS_WRP)); + TLI_LxVPOS(layerx) &= ~(TLI_LxVPOS_WTP|(TLI_LxVPOS_WBP)); + hstart = offset_x+(((TLI_BPSZ & TLI_BPSZ_HBPSZ)>>16U)+1U); + vstart = offset_y+((TLI_BPSZ & TLI_BPSZ_VBPSZ)+1U); + line_num = (TLI_LxFTLN(layerx) & TLI_LxFTLN_FTLN); + layer_ppf = (TLI_LxPPF(layerx) & TLI_LxPPF_PPF); + /* the bytes of a line equal TLI_LxFLLEN_FLL bits value minus 3 */ + switch(layer_ppf){ + case LAYER_PPF_ARGB8888: + /* each pixel includes 4bytes,when pixel format is ARGB8888 */ + line_length = (((TLI_LxFLLEN(layerx) & TLI_LxFLLEN_FLL)-3U)/4U); + break; + case LAYER_PPF_RGB888: + /* each pixel includes 3bytes,when pixel format is RGB888 */ + line_length = (((TLI_LxFLLEN(layerx) & TLI_LxFLLEN_FLL)-3U)/3U); + break; + case LAYER_PPF_RGB565: + case LAYER_PPF_ARGB1555: + case LAYER_PPF_ARGB4444: + case LAYER_PPF_AL88: + /* each pixel includes 2bytes,when pixel format is RGB565,ARG1555,ARGB4444 or AL88 */ + line_length = (((TLI_LxFLLEN(layerx) & TLI_LxFLLEN_FLL)-3U)/2U); + break; + case LAYER_PPF_L8: + case LAYER_PPF_AL44: + /* each pixel includes 1byte,when pixel format is L8 or AL44 */ + line_length = (((TLI_LxFLLEN(layerx) & TLI_LxFLLEN_FLL)-3U)); + break; + default: + break; + } + /* reconfigure window position */ + TLI_LxHPOS(layerx) = (hstart|((hstart+line_length-1U)<<16U)); + TLI_LxVPOS(layerx) = (vstart|((vstart+line_num-1U)<<16U)); +} + +/*! + \brief TLI layer LUT initialize + \param[in] layerx: LAYERx(x=0,1) + \param[in] lut_struct: TLI layer LUT parameter struct + layer_table_addr: window right position + layer_lut_channel_red: window left position + layer_window_bottompos: window bottom position + layer_window_toppos: window top position + \param[out] none + \retval none +*/ +void tli_lut_init(uint32_t layerx,tli_layer_lut_parameter_struct *lut_struct) +{ + TLI_LxLUT(layerx) &= ~(TLI_LxLUT_TB|TLI_LxLUT_TG|TLI_LxLUT_TR|TLI_LxLUT_TADD); + TLI_LxLUT(layerx) = ((lut_struct->layer_lut_channel_blue)|(lut_struct->layer_lut_channel_green<<8) + |(lut_struct->layer_lut_channel_red<<16 + |(lut_struct->layer_table_addr<<24))); +} + +/*! + \brief TLI layer key initialize + \param[in] layerx: LAYERx(x=0,1) + \param[in] redkey: color key red + \param[in] greenkey: color key green + \param[in] bluekey: color key blue + \param[out] none + \retval none +*/ +void tli_ckey_init(uint32_t layerx,uint32_t redkey,uint32_t greenkey,uint32_t bluekey) +{ + TLI_LxCKEY(layerx) = ((bluekey)|(greenkey<<8U)|(redkey<<16U)); +} + +/*! + \brief get TLI flag or state + \param[in] flag: TLI flags or states + \arg TLI_FLAG_VDE: current VDE state + \arg TLI_FLAG_HDE: current HDE state + \arg TLI_FLAG_VS: current vs state + \arg TLI_FLAG_HS: current hs state + \arg TLI_FLAG_LM: line mark interrupt flag + \arg TLI_FLAG_FE: FIFO error interrupt flag + \arg TLI_FLAG_TE: transaction error interrupt flag + \arg TLI_FLAG_LCR: layer configuration reloaded interrupt flag + \param[out] none + \retval FlagStatus: SET or RESET +*/ +FlagStatus tli_flag_get(uint32_t flag) +{ + uint32_t stat; + if(flag >> 31){ + /* get flag status from TLI_INTF register */ + stat = TLI_INTF; + }else{ + /* get flag status from TLI_STAT register */ + stat = TLI_STAT; + } + if(flag & stat){ + return SET; + }else{ + return RESET; + } +} + +/*! + \brief enable TLI interrupt + \param[in] interrupt: TLI interrupt flags + \arg TLI_INT_LM: line mark interrupt + \arg TLI_INT_FE: FIFO error interrupt + \arg TLI_INT_TE: transaction error interrupt + \arg TLI_INT_LCR: layer configuration reloaded interrupt + \param[out] none + \retval none +*/ +void tli_interrupt_enable(uint32_t interrupt) +{ + TLI_INTEN |= (interrupt); +} + +/*! + \brief disable TLI interrupt + \param[in] interrupt: TLI interrupt flags + \arg TLI_INT_LM: line mark interrupt + \arg TLI_INT_FE: FIFO error interrupt + \arg TLI_INT_TE: transaction error interrupt + \arg TLI_INT_LCR: layer configuration reloaded interrupt + \param[out] none + \retval none +*/ +void tli_interrupt_disable(uint32_t interrupt) +{ + TLI_INTEN &= ~(interrupt); +} + +/*! + \brief get TLI interrupt flag + \param[in] int_flag: TLI interrupt flags + \arg TLI_INT_FLAG_LM: line mark interrupt flag + \arg TLI_INT_FLAG_FE: FIFO error interrupt flag + \arg TLI_INT_FLAG_TE: transaction error interrupt flag + \arg TLI_INT_FLAG_LCR: layer configuration reloaded interrupt flag + \param[out] none + \retval FlagStatus: SET or RESET +*/ +FlagStatus tli_interrupt_flag_get(uint32_t int_flag) +{ + uint32_t state; + state = TLI_INTF; + if(state & int_flag){ + state = TLI_INTEN; + /* check whether the corresponding bit in TLI_INTEN is set or not */ + if(state & int_flag){ + return SET; + } + } + return RESET; +} + +/*! + \brief clear TLI interrupt flag + \param[in] int_flag: TLI interrupt flags + \arg TLI_INT_FLAG_LM: line mark interrupt flag + \arg TLI_INT_FLAG_FE: FIFO error interrupt flag + \arg TLI_INT_FLAG_TE: transaction error interrupt flag + \arg TLI_INT_FLAG_LCR: layer configuration reloaded interrupt flag + \param[out] none + \retval none +*/ +void tli_interrupt_flag_clear(uint32_t int_flag) +{ + TLI_INTC |= (int_flag); +} diff --git a/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_standard_peripheral/Source/gd32f20x_trng.c b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_standard_peripheral/Source/gd32f20x_trng.c new file mode 100644 index 0000000000..866b46053b --- /dev/null +++ b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_standard_peripheral/Source/gd32f20x_trng.c @@ -0,0 +1,156 @@ +/*! + \file gd32f20x_trng.c + \brief TRNG driver + + \version 2015-07-15, V1.0.0, firmware for GD32F20x + \version 2017-06-05, V2.0.0, firmware for GD32F20x + \version 2018-10-31, V2.1.0, firmware for GD32F20x + \version 2020-09-30, V2.2.0, firmware for GD32F20x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "gd32f20x_trng.h" + +/*! + \brief deinitialize the TRNG + \param[in] none + \param[out] none + \retval none +*/ +void trng_deinit(void) +{ + rcu_periph_reset_enable(RCU_TRNGRST); + rcu_periph_reset_disable(RCU_TRNGRST); +} + +/*! + \brief enable the TRNG interface + \param[in] none + \param[out] none + \retval none +*/ +void trng_enable(void) +{ + TRNG_CTL |= TRNG_CTL_TRNGEN; +} + +/*! + \brief disable the TRNG interface + \param[in] none + \param[out] none + \retval none +*/ +void trng_disable(void) +{ + TRNG_CTL &= ~TRNG_CTL_TRNGEN; +} + +/*! + \brief get the true random data + \param[in] none + \param[out] none + \retval the generated random data +*/ +uint32_t trng_get_true_random_data(void) +{ + return (TRNG_DATA); +} + +/*! + \brief get the trng status flags + \param[in] flag: trng status flag, refer to trng_flag_enum + only one parameter can be selected which is shown as below: + \arg TRNG_FLAG_DRDY: Random Data ready status + \arg TRNG_FLAG_CECS: Clock error current status + \arg TRNG_FLAG_SECS: Seed error current status + \param[out] none + \retval FlagStatus: SET or RESET +*/ +FlagStatus trng_flag_get(trng_flag_enum flag) +{ + if(RESET != (TRNG_STAT & flag)){ + return SET; + }else{ + return RESET; + } +} + +/*! + \brief enable the TRNG interrupt + \param[in] none + \param[out] none + \retval none +*/ +void trng_interrupt_enable(void) +{ + TRNG_CTL |= TRNG_CTL_IE; +} + +/*! + \brief disable the TRNG interrupt + \param[in] none + \param[out] none + \retval none +*/ +void trng_interrupt_disable(void) +{ + TRNG_CTL &= ~TRNG_CTL_IE; +} + +/*! + \brief get the trng interrupt flags + \param[in] int_flag: trng interrupt flag, refer to trng_int_flag_enum + only one parameter can be selected which is shown as below: + \arg TRNG_INT_FLAG_CE: clock error interrupt flag + \arg TRNG_INT_FLAG_SE: Seed error interrupt flag + \param[out] none + \retval FlagStatus: SET or RESET +*/ +FlagStatus trng_interrupt_flag_get(trng_int_flag_enum int_flag) +{ + if(RESET != (TRNG_STAT & int_flag)){ + return SET; + }else{ + return RESET; + } +} + +/*! + \brief clear the trng interrupt flags + \param[in] int_flag: trng interrupt flag, refer to trng_int_flag_enum + only one parameter can be selected which is shown as below: + \arg TRNG_INT_FLAG_CE: clock error interrupt flag + \arg TRNG_INT_FLAG_SE: Seed error interrupt flag + \param[out] none + \retval none +*/ +void trng_interrupt_flag_clear(trng_int_flag_enum int_flag) +{ + TRNG_STAT &= ~(uint32_t)int_flag; +} diff --git a/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_standard_peripheral/Source/gd32f20x_usart.c b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_standard_peripheral/Source/gd32f20x_usart.c new file mode 100644 index 0000000000..d2767da8d2 --- /dev/null +++ b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_standard_peripheral/Source/gd32f20x_usart.c @@ -0,0 +1,923 @@ +/*! + \file gd32f20x_usart.c + \brief USART driver + + \version 2015-07-15, V1.0.0, firmware for GD32F20x + \version 2017-06-05, V2.0.0, firmware for GD32F20x + \version 2018-10-31, V2.1.0, firmware for GD32F20x + \version 2020-09-30, V2.2.0, firmware for GD32F20x + \version 2019-04-11, V2.1.1, firmware for GD32F20x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "gd32f20x_usart.h" + +/*! + \brief reset USART/UART + \param[in] usart_periph: USARTx(x=0,1,2,5)/UARTx(x=3,4,6,7) + \param[out] none + \retval none +*/ +void usart_deinit(uint32_t usart_periph) +{ + switch(usart_periph){ + case USART0: + /* reset USART0 */ + rcu_periph_reset_enable(RCU_USART0RST); + rcu_periph_reset_disable(RCU_USART0RST); + break; + case USART1: + /* reset USART1 */ + rcu_periph_reset_enable(RCU_USART1RST); + rcu_periph_reset_disable(RCU_USART1RST); + break; + case USART2: + /* reset USART2 */ + rcu_periph_reset_enable(RCU_USART2RST); + rcu_periph_reset_disable(RCU_USART2RST); + break; + case USART5: + /* reset USART5 */ + rcu_periph_reset_enable(RCU_USART5RST); + rcu_periph_reset_disable(RCU_USART5RST); + break; + case UART3: + /* reset UART3 */ + rcu_periph_reset_enable(RCU_UART3RST); + rcu_periph_reset_disable(RCU_UART3RST); + break; + case UART4: + /* reset UART4 */ + rcu_periph_reset_enable(RCU_UART4RST); + rcu_periph_reset_disable(RCU_UART4RST); + break; + case UART6: + /* reset UART6 */ + rcu_periph_reset_enable(RCU_UART6RST); + rcu_periph_reset_disable(RCU_UART6RST); + break; + case UART7: + /* reset UART7 */ + rcu_periph_reset_enable(RCU_UART7RST); + rcu_periph_reset_disable(RCU_UART7RST); + break; + default: + break; + } +} + +/*! + \brief configure USART baud rate value + \param[in] usart_periph: USARTx(x=0,1,2,5)/UARTx(x=3,4,6,7) + \param[in] baudval: baud rate value + \param[out] none + \retval none +*/ +void usart_baudrate_set(uint32_t usart_periph, uint32_t baudval) +{ + uint32_t uclk=0U, intdiv=0U, fradiv=0U, udiv=0U; + switch(usart_periph){ + /* get clock frequency */ + case USART0: + /* get USART0 clock */ + uclk=rcu_clock_freq_get(CK_APB2); + break; + case USART5: + /* get USART5 clock */ + uclk=rcu_clock_freq_get(CK_APB2); + break; + case USART1: + /* get USART1 clock */ + uclk=rcu_clock_freq_get(CK_APB1); + break; + case USART2: + /* get USART2 clock */ + uclk=rcu_clock_freq_get(CK_APB1); + break; + case UART3: + /* get UART3 clock */ + uclk=rcu_clock_freq_get(CK_APB1); + break; + case UART4: + /* get UART4 clock */ + uclk=rcu_clock_freq_get(CK_APB1); + break; + case UART6: + /* get UART6 clock */ + uclk=rcu_clock_freq_get(CK_APB1); + break; + case UART7: + /* get UART7 clock */ + uclk=rcu_clock_freq_get(CK_APB1); + break; + default: + break; + } + /* when oversampling by 16, configure the value of USART_BAUD */ + udiv = (uclk+baudval/2U)/baudval; + intdiv = udiv & 0xfff0U; + fradiv = udiv & 0xfU; + USART_BAUD(usart_periph) = ((USART_BAUD_FRADIV | USART_BAUD_INTDIV) & (intdiv | fradiv)); +} + +/*! + \brief configure USART parity + \param[in] usart_periph: USARTx(x=0,1,2,5)/UARTx(x=3,4,6,7) + \param[in] paritycfg: configure USART parity + only one parameter can be selected which is shown as below: + \arg USART_PM_NONE: no parity + \arg USART_PM_ODD: odd parity + \arg USART_PM_EVEN: even parity + \param[out] none + \retval none +*/ +void usart_parity_config(uint32_t usart_periph, uint32_t paritycfg) +{ + /* clear USART_CTL0 PM,PCEN Bits */ + USART_CTL0(usart_periph) &= ~(USART_CTL0_PM | USART_CTL0_PCEN); + /* configure USART parity mode */ + USART_CTL0(usart_periph) |= paritycfg; +} + +/*! + \brief configure USART word length + \param[in] usart_periph: USARTx(x=0,1,2,5)/UARTx(x=3,4,6,7) + \param[in] wlen: USART word length configure + only one parameter can be selected which is shown as below: + \arg USART_WL_8BIT: 8 bits + \arg USART_WL_9BIT: 9 bits + \param[out] none + \retval none +*/ +void usart_word_length_set(uint32_t usart_periph, uint32_t wlen) +{ + /* clear USART_CTL0 WL bit */ + USART_CTL0(usart_periph) &= ~USART_CTL0_WL; + /* configure USART word length */ + USART_CTL0(usart_periph) |= wlen; +} + +/*! + \brief configure USART stop bit length + \param[in] usart_periph: USARTx(x=0,1,2,5)/UARTx(x=3,4,6,7) + \param[in] stblen: USART stop bit configure + only one parameter can be selected which is shown as below: + \arg USART_STB_1BIT: 1 bit + \arg USART_STB_0_5BIT: 0.5 bit(not available for UARTx(x=3,4,6,7)) + \arg USART_STB_2BIT: 2 bits + \arg USART_STB_1_5BIT: 1.5 bits(not available for UARTx(x=3,4,6,7)) + \param[out] none + \retval none +*/ +void usart_stop_bit_set(uint32_t usart_periph, uint32_t stblen) +{ + /* clear USART_CTL1 STB bits */ + USART_CTL1(usart_periph) &= ~USART_CTL1_STB; + /* configure USART stop bits */ + USART_CTL1(usart_periph) |= stblen; +} +/*! + \brief enable USART + \param[in] usart_periph: USARTx(x=0,1,2,5)/UARTx(x=3,4,6,7) + \param[out] none + \retval none +*/ +void usart_enable(uint32_t usart_periph) +{ + USART_CTL0(usart_periph) |= USART_CTL0_UEN; +} + +/*! + \brief disable USART + \param[in] usart_periph: USARTx(x=0,1,2,5)/UARTx(x=3,4,6,7) + \param[out] none + \retval none +*/ +void usart_disable(uint32_t usart_periph) +{ + USART_CTL0(usart_periph) &= ~(USART_CTL0_UEN); +} + +/*! + \brief configure USART transmitter + \param[in] usart_periph: USARTx(x=0,1,2,5)/UARTx(x=3,4,6,7) + \param[in] txconfig: enable or disable USART transmitter + only one parameter can be selected which is shown as below: + \arg USART_TRANSMIT_ENABLE: enable USART transmission + \arg USART_TRANSMIT_DISABLE: enable USART transmission + \param[out] none + \retval none +*/ +void usart_transmit_config(uint32_t usart_periph, uint32_t txconfig) +{ + uint32_t ctl = 0U; + + ctl = USART_CTL0(usart_periph); + ctl &= ~USART_CTL0_TEN; + ctl |= txconfig; + /* configure transfer mode */ + USART_CTL0(usart_periph) = ctl; +} + +/*! + \brief configure USART receiver + \param[in] usart_periph: USARTx(x=0,1,2,5)/UARTx(x=3,4,6,7) + \param[in] rxconfig: enable or disable USART receiver + only one parameter can be selected which is shown as below: + \arg USART_RECEIVE_ENABLE: enable USART reception + \arg USART_RECEIVE_DISABLE: disable USART reception + \param[out] none + \retval none +*/ +void usart_receive_config(uint32_t usart_periph, uint32_t rxconfig) +{ + uint32_t ctl = 0U; + + ctl = USART_CTL0(usart_periph); + ctl &= ~USART_CTL0_REN; + ctl |= rxconfig; + /* configure receiver mode */ + USART_CTL0(usart_periph) = ctl; +} + +/*! + \brief data is transmitted/received with the LSB/MSB first + \param[in] usart_periph: USARTx(x=0,1,2,5) + \param[in] msbf: LSB/MSB + \arg USART_MSBF_LSB: LSB first + \arg USART_MSBF_MSB: MSB first + \param[out] none + \retval none +*/ +void usart_data_first_config(uint32_t usart_periph, uint32_t msbf) +{ + USART_CTL3(usart_periph) &= ~(USART_CTL3_MSBF); + USART_CTL3(usart_periph) |= msbf; +} + +/*! + \brief configure USART inversion + \param[in] usart_periph: USARTx(x=0,1,2,5) + \param[in] invertpara: refer to enum USART_INVERT_CONFIG + \arg USART_DINV_ENABLE: data bit level inversion + \arg USART_DINV_DISABLE: data bit level not inversion + \arg USART_TXPIN_ENABLE: TX pin level inversion + \arg USART_TXPIN_DISABLE: TX pin level not inversion + \arg USART_RXPIN_ENABLE: RX pin level inversion + \arg USART_RXPIN_DISABLE: RX pin level not inversion + \param[out] none + \retval none +*/ +void usart_invert_config(uint32_t usart_periph, usart_invert_enum invertpara) +{ + /* inverted or not the specified siginal */ + switch(invertpara){ + case USART_DINV_ENABLE: + USART_CTL3(usart_periph) |= USART_CTL3_DINV; + break; + case USART_TXPIN_ENABLE: + USART_CTL3(usart_periph) |= USART_CTL3_TINV; + break; + case USART_RXPIN_ENABLE: + USART_CTL3(usart_periph) |= USART_CTL3_RINV; + break; + case USART_DINV_DISABLE: + USART_CTL3(usart_periph) &= ~(USART_CTL3_DINV); + break; + case USART_TXPIN_DISABLE: + USART_CTL3(usart_periph) &= ~(USART_CTL3_TINV); + break; + case USART_RXPIN_DISABLE: + USART_CTL3(usart_periph) &= ~(USART_CTL3_RINV); + break; + default: + break; + } +} + +/*! + \brief enable receiver timeout of USART + \param[in] usart_periph: USARTx(x=0,1,2,5) + \param[out] none + \retval none +*/ +void usart_receiver_timeout_enable(uint32_t usart_periph) +{ + USART_CTL3(usart_periph) |= USART_CTL3_RTEN; +} + +/*! + \brief disable receiver timeout of USART + \param[in] usart_periph: USARTx(x=0,1,2,5) + \param[out] none + \retval none +*/ +void usart_receiver_timeout_disable(uint32_t usart_periph) +{ + USART_CTL3(usart_periph) &= ~(USART_CTL3_RTEN); +} + +/*! + \brief set the receiver timeout threshold of USART + \param[in] usart_periph: USARTx(x=0,1,2,5) + \param[in] rtimeout: 0-0xFFFFFF + \param[out] none + \retval none +*/ +void usart_receiver_timeout_threshold_config(uint32_t usart_periph, uint32_t rtimeout) +{ + USART_RT(usart_periph) &= ~(USART_RT_RT); + USART_RT(usart_periph) |= rtimeout; +} + +/*! + \brief USART transmit data function + \param[in] usart_periph: USARTx(x=0,1,2,5)/UARTx(x=3,4,6,7) + \param[in] data: data of transmission + \param[out] none + \retval none +*/ +void usart_data_transmit(uint32_t usart_periph, uint16_t data) +{ + USART_DATA(usart_periph) = ((uint16_t)USART_DATA_DATA & data); +} + +/*! + \brief USART receive data function + \param[in] usart_periph: USARTx(x=0,1,2,5)/UARTx(x=3,4,6,7) + \param[out] none + \retval data of received +*/ +uint16_t usart_data_receive(uint32_t usart_periph) +{ + return (uint16_t)(GET_BITS(USART_DATA(usart_periph), 0U, 8U)); +} + +/*! + \brief configure the address of the USART in wake up by address match mode + \param[in] usart_periph: USARTx(x=0,1,2,5)/UARTx(x=3,4,6,7) + \param[in] addr: address of USART/UART + \param[out] none + \retval none +*/ +void usart_address_config(uint32_t usart_periph, uint8_t addr) +{ + USART_CTL1(usart_periph) &= ~(USART_CTL1_ADDR); + USART_CTL1(usart_periph) |= (USART_CTL1_ADDR & addr); +} + +/*! + \brief receiver in mute mode + \param[in] usart_periph: USARTx(x=0,1,2,5)/UARTx(x=3,4,6,7) + \param[out] none + \retval none +*/ +void usart_mute_mode_enable(uint32_t usart_periph) +{ + USART_CTL0(usart_periph) |= USART_CTL0_RWU; +} + +/*! + \brief receiver in active mode + \param[in] usart_periph: USARTx(x=0,1,2,5)/UARTx(x=3,4,6,7) + \param[out] none + \retval none +*/ +void usart_mute_mode_disable(uint32_t usart_periph) +{ + USART_CTL0(usart_periph) &= ~(USART_CTL0_RWU); +} + +/*! + \brief configure wakeup method in mute mode + \param[in] usart_periph: USARTx(x=0,1,2,5)/UARTx(x=3,4,6,7) + \param[in] wmethod: two methods be used to enter or exit the mute mode + only one parameter can be selected which is shown as below: + \arg USART_WM_IDLE: idle line + \arg USART_WM_ADDR: address mask + \param[out] none + \retval none +*/ +void usart_mute_mode_wakeup_config(uint32_t usart_periph, uint32_t wmethod) +{ + USART_CTL0(usart_periph) &= ~(USART_CTL0_WM); + USART_CTL0(usart_periph) |= wmethod; +} + +/*! + \brief enable LIN mode + \param[in] usart_periph: USARTx(x=0,1,2,5)/UARTx(x=3,4,6,7) + \param[out] none + \retval none +*/ +void usart_lin_mode_enable(uint32_t usart_periph) +{ + USART_CTL1(usart_periph) |= USART_CTL1_LMEN; +} + +/*! + \brief disable LIN mode + \param[in] usart_periph: USARTx(x=0,1,2,5)/UARTx(x=3,4,6,7) + \param[out] none + \retval none +*/ +void usart_lin_mode_disable(uint32_t usart_periph) +{ + USART_CTL1(usart_periph) &= ~(USART_CTL1_LMEN); +} + +/*! + \brief configure lin break frame length + \param[in] usart_periph: USARTx(x=0,1,2,5)/UARTx(x=3,4,6,7) + \param[in] lblen: lin break frame length + only one parameter can be selected which is shown as below: + \arg USART_LBLEN_10B: 10 bits + \arg USART_LBLEN_11B: 11 bits + \param[out] none + \retval none +*/ +void usart_lin_break_detection_length_config(uint32_t usart_periph, uint32_t lblen) +{ + USART_CTL1(usart_periph) &= ~(USART_CTL1_LBLEN); + USART_CTL1(usart_periph) |= (USART_CTL1_LBLEN & lblen); +} + +/*! + \brief send break frame + \param[in] usart_periph: USARTx(x=0,1,2,5)/UARTx(x=3,4,6,7) + \param[out] none + \retval none +*/ +void usart_send_break(uint32_t usart_periph) +{ + USART_CTL0(usart_periph) |= USART_CTL0_SBKCMD; +} + +/*! + \brief enable half duplex mode + \param[in] usart_periph: USARTx(x=0,1,2,5)/UARTx(x=3,4,6,7) + \param[out] none + \retval none +*/ +void usart_halfduplex_enable(uint32_t usart_periph) +{ + USART_CTL2(usart_periph) |= USART_CTL2_HDEN; +} + +/*! + \brief disable half duplex mode + \param[in] usart_periph: USARTx(x=0,1,2,5)/UARTx(x=3,4,6,7) + \param[out] none + \retval none +*/ +void usart_halfduplex_disable(uint32_t usart_periph) +{ + USART_CTL2(usart_periph) &= ~(USART_CTL2_HDEN); +} + +/*! + \brief enable CK pin in synchronous mode + \param[in] usart_periph: USARTx(x=0,1,2,5) + \param[out] none + \retval none +*/ +void usart_synchronous_clock_enable(uint32_t usart_periph) +{ + USART_CTL1(usart_periph) |= USART_CTL1_CKEN; +} + +/*! + \brief disable CK pin in synchronous mode + \param[in] usart_periph: USARTx(x=0,1,2,5) + \param[out] none + \retval none +*/ +void usart_synchronous_clock_disable(uint32_t usart_periph) +{ + USART_CTL1(usart_periph) &= ~(USART_CTL1_CKEN); +} + +/*! + \brief configure USART synchronous mode parameters + \param[in] usart_periph: USARTx(x=0,1,2,5) + \param[in] clen: CK length + only one parameter can be selected which is shown as below: + \arg USART_CLEN_NONE: there are 7 CK pulses for an 8 bit frame and 8 CK pulses for a 9 bit frame + \arg USART_CLEN_EN: there are 8 CK pulses for an 8 bit frame and 9 CK pulses for a 9 bit frame + \param[in] cph: clock phase + only one parameter can be selected which is shown as below: + \arg USART_CPH_1CK: first clock transition is the first data capture edge + \arg USART_CPH_2CK: second clock transition is the first data capture edge + \param[in] cpl: clock polarity + only one parameter can be selected which is shown as below: + \arg USART_CPL_LOW: steady low value on CK pin + \arg USART_CPL_HIGH: steady high value on CK pin + \param[out] none + \retval none +*/ +void usart_synchronous_clock_config(uint32_t usart_periph, uint32_t clen, uint32_t cph, uint32_t cpl) +{ + uint32_t ctl = 0U; + + /* read USART_CTL1 register */ + ctl = USART_CTL1(usart_periph); + ctl &= ~(USART_CTL1_CLEN | USART_CTL1_CPH | USART_CTL1_CPL); + /* set CK length, CK phase, CK polarity */ + ctl |= (USART_CTL1_CLEN & clen) | (USART_CTL1_CPH & cph) | (USART_CTL1_CPL & cpl); + + USART_CTL1(usart_periph) = ctl; +} + +/*! + \brief configure guard time value in smartcard mode + \param[in] usart_periph: USARTx(x=0,1,2,5) + \param[in] guat: guard time value + \param[out] none + \retval none +*/ +void usart_guard_time_config(uint32_t usart_periph,uint32_t guat) +{ + USART_GP(usart_periph) &= ~(USART_GP_GUAT); + USART_GP(usart_periph) |= (USART_GP_GUAT & ((guat)<<8)); +} + +/*! + \brief enable smartcard mode + \param[in] usart_periph: USARTx(x=0,1,2,5) + \param[out] none + \retval none +*/ +void usart_smartcard_mode_enable(uint32_t usart_periph) +{ + USART_CTL2(usart_periph) |= USART_CTL2_SCEN; +} + +/*! + \brief disable smartcard mode + \param[in] usart_periph: USARTx(x=0,1,2,5) + \param[out] none + \retval none +*/ +void usart_smartcard_mode_disable(uint32_t usart_periph) +{ + USART_CTL2(usart_periph) &= ~(USART_CTL2_SCEN); +} + +/*! + \brief enable NACK in smartcard mode + \param[in] usart_periph: USARTx(x=0,1,2,5) + \param[out] none + \retval none +*/ +void usart_smartcard_mode_nack_enable(uint32_t usart_periph) +{ + USART_CTL2(usart_periph) |= USART_CTL2_NKEN; +} + +/*! + \brief disable NACK in smartcard mode + \param[in] usart_periph: USARTx(x=0,1,2,5) + \param[out] none + \retval none +*/ +void usart_smartcard_mode_nack_disable(uint32_t usart_periph) +{ + USART_CTL2(usart_periph) &= ~(USART_CTL2_NKEN); +} + +/*! + \brief configure smartcard auto-retry number + \param[in] usart_periph: USARTx(x=0,1,2,5) + \param[in] scrtnum: smartcard auto-retry number + \param[out] none + \retval none +*/ +void usart_smartcard_autoretry_config(uint32_t usart_periph, uint32_t scrtnum) +{ + USART_CTL3(usart_periph) &= ~(USART_CTL3_SCRTNUM); + USART_CTL3(usart_periph) |= (USART_CTL3_SCRTNUM & ((scrtnum)<<1)); +} + +/*! + \brief configure block length in Smartcard T=1 reception + \param[in] usart_periph: USARTx(x=0,1,2,5) + \param[in] bl: block length + \param[out] none + \retval none +*/ +void usart_block_length_config(uint32_t usart_periph, uint32_t bl) +{ + USART_RT(usart_periph) &= ~(USART_RT_BL); + USART_RT(usart_periph) |= (USART_RT_BL & ((bl)<<24)); +} + +/*! + \brief enable IrDA mode + \param[in] usart_periph: USARTx(x=0,1,2,5)/UARTx(x=3,4,6,7) + \param[out] none + \retval none +*/ +void usart_irda_mode_enable(uint32_t usart_periph) +{ + USART_CTL2(usart_periph) |= USART_CTL2_IREN; +} + +/*! + \brief disable IrDA mode + \param[in] usart_periph: USARTx(x=0,1,2,5)/UARTx(x=3,4,6,7) + \param[out] none + \retval none +*/ +void usart_irda_mode_disable(uint32_t usart_periph) +{ + USART_CTL2(usart_periph) &= ~(USART_CTL2_IREN); +} + +/*! + \brief configure the peripheral clock prescaler in USART IrDA low-power mode + \param[in] usart_periph: USARTx(x=0,1,2,5)/UARTx(x=3,4,6,7) + \param[in] psc: 0x00-0xFF + \param[out] none + \retval none +*/ +void usart_prescaler_config(uint32_t usart_periph, uint8_t psc) +{ + USART_GP(usart_periph) &= ~(USART_GP_PSC); + USART_GP(usart_periph) |= psc; +} + +/*! + \brief configure IrDA low-power + \param[in] usart_periph: USARTx(x=0,1,2,5)/UARTx(x=3,4,6,7) + \param[in] irlp: IrDA low-power or normal + only one parameter can be selected which is shown as below: + \arg USART_IRLP_LOW: low-power + \arg USART_IRLP_NORMAL: normal + \param[out] none + \retval none +*/ +void usart_irda_lowpower_config(uint32_t usart_periph, uint32_t irlp) +{ + USART_CTL2(usart_periph) &= ~(USART_CTL2_IRLP); + USART_CTL2(usart_periph) |= (USART_CTL2_IRLP & irlp); +} + +/*! + \brief configure hardware flow control RTS + \param[in] usart_periph: USARTx(x=0,1,2,5) + \param[in] hardwareflow: enable or disable RTS + only one parameter can be selected which is shown as below: + \arg USART_RTS_ENABLE: enable RTS + \arg USART_RTS_DISABLE: disable RTS + \param[out] none + \retval none +*/ +void usart_hardware_flow_rts_config(uint32_t usart_periph, uint32_t rtsconfig) +{ + uint32_t ctl = 0U; + + ctl = USART_CTL2(usart_periph); + ctl &= ~USART_CTL2_RTSEN; + ctl |= rtsconfig; + /* configure RTS */ + USART_CTL2(usart_periph) = ctl; +} + +/*! + \brief configure hardware flow control CTS + \param[in] usart_periph: USARTx(x=0,1,2,5) + \param[in] hardwareflow: enable or disable CTS + only one parameter can be selected which is shown as below: + \arg USART_CTS_ENABLE: enable CTS + \arg USART_CTS_DISABLE: disable CTS + \param[out] none + \retval none +*/ +void usart_hardware_flow_cts_config(uint32_t usart_periph, uint32_t ctsconfig) +{ + uint32_t ctl = 0U; + + ctl = USART_CTL2(usart_periph); + ctl &= ~USART_CTL2_CTSEN; + ctl |= ctsconfig; + /* configure CTS */ + USART_CTL2(usart_periph) = ctl; +} + +/*! + \brief configure USART DMA reception + \param[in] usart_periph: USARTx(x=0,1,2,5)/UARTx(x=3,4,6,7) + \param[in] dmacmd: enable or disable DMA for reception + only one parameter can be selected which is shown as below: + \arg USART_DENR_ENABLE: DMA enable for reception + \arg USART_DENR_DISABLE: DMA disable for reception + \param[out] none + \retval none +*/ +void usart_dma_receive_config(uint32_t usart_periph, uint32_t dmacmd) +{ + uint32_t ctl = 0U; + + ctl = USART_CTL2(usart_periph); + ctl &= ~USART_CTL2_DENR; + ctl |= dmacmd; + /* configure DMA reception */ + USART_CTL2(usart_periph) = ctl; +} + +/*! + \brief configure USART DMA transmission + \param[in] usart_periph: USARTx(x=0,1,2,5)/UARTx(x=3,4,6,7) + \param[in] dmacmd: enable or disable DMA for transmission + only one parameter can be selected which is shown as below: + \arg USART_DENT_ENABLE: DMA enable for transmission + \arg USART_DENT_DISABLE: DMA disable for transmission + \param[out] none + \retval none +*/ +void usart_dma_transmit_config(uint32_t usart_periph, uint32_t dmacmd) +{ + uint32_t ctl = 0U; + + ctl = USART_CTL2(usart_periph); + ctl &= ~USART_CTL2_DENT; + ctl |= dmacmd; + /* configure DMA transmission */ + USART_CTL2(usart_periph) = ctl; +} + +/*! + \brief get flag in STAT0/STAT1 register + \param[in] usart_periph: USARTx(x=0,1,2,5)/UARTx(x=3,4,6,7) + \param[in] flag: USART flags, refer to usart_flag_enum + only one parameter can be selected which is shown as below: + \arg USART_FLAG_CTS: CTS change flag + \arg USART_FLAG_LBD: LIN break detected flag + \arg USART_FLAG_TBE: transmit data buffer empty + \arg USART_FLAG_TC: transmission complete + \arg USART_FLAG_RBNE: read data buffer not empty + \arg USART_FLAG_IDLE: IDLE frame detected flag + \arg USART_FLAG_ORERR: overrun error + \arg USART_FLAG_NERR: noise error flag + \arg USART_FLAG_FERR: frame error flag + \arg USART_FLAG_PERR: parity error flag + \arg USART_FLAG_BSY: busy flag + \arg USART_FLAG_EB: end of block flag + \arg USART_FLAG_RT: receiver timeout flag + \param[out] none + \retval FlagStatus: SET or RESET +*/ +FlagStatus usart_flag_get(uint32_t usart_periph, usart_flag_enum flag) +{ + if(RESET != (USART_REG_VAL(usart_periph, flag) & BIT(USART_BIT_POS(flag)))){ + return SET; + }else{ + return RESET; + } +} + +/*! + \brief clear flag in STAT0/STAT1 register + \param[in] usart_periph: USARTx(x=0,1,2,5)/UARTx(x=3,4,6,7) + \param[in] flag: USART flags, refer to usart_flag_enum + only one parameter can be selected which is shown as below: + \arg USART_FLAG_CTS: CTS change flag + \arg USART_FLAG_LBD: LIN break detected flag + \arg USART_FLAG_TC: transmission complete + \arg USART_FLAG_RBNE: read data buffer not empty + \arg USART_FLAG_EB: end of block flag + \arg USART_FLAG_RT: receiver timeout flag + \param[out] none + \retval none +*/ +void usart_flag_clear(uint32_t usart_periph, usart_flag_enum flag) +{ + USART_REG_VAL(usart_periph, flag) &= ~BIT(USART_BIT_POS(flag)); +} + +/*! + \brief enable USART interrupt + \param[in] usart_periph: USARTx(x=0,1,2,5)/UARTx(x=3,4,6,7) + \param[in] int_flag + only one parameter can be selected which is shown as below: + \arg USART_INT_PERR: parity error interrupt + \arg USART_INT_TBE: transmitter buffer empty interrupt + \arg USART_INT_TC: transmission complete interrupt + \arg USART_INT_RBNE: read data buffer not empty interrupt and overrun error interrupt + \arg USART_INT_IDLE: IDLE line detected interrupt + \arg USART_INT_LBD: LIN break detected interrupt + \arg USART_INT_ERR: error interrupt + \arg USART_INT_CTS: CTS interrupt + \arg USART_INT_RT: interrupt enable bit of receive timeout event + \arg USART_INT_EB: interrupt enable bit of end of block event + \param[out] none + \retval none +*/ +void usart_interrupt_enable(uint32_t usart_periph, uint32_t int_flag) +{ + USART_REG_VAL(usart_periph, int_flag) |= BIT(USART_BIT_POS(int_flag)); +} + +/*! + \brief disable USART interrupt + \param[in] usart_periph: USARTx(x=0,1,2,5)/UARTx(x=3,4,6,7) + \param[in] int_flag + only one parameter can be selected which is shown as below: + \arg USART_INT_PERR: parity error interrupt + \arg USART_INT_TBE: transmitter buffer empty interrupt + \arg USART_INT_TC: transmission complete interrupt + \arg USART_INT_RBNE: read data buffer not empty interrupt and overrun error interrupt + \arg USART_INT_IDLE: IDLE line detected interrupt + \arg USART_INT_LBD: LIN break detected interrupt + \arg USART_INT_ERR: error interrupt + \arg USART_INT_CTS: CTS interrupt + \arg USART_INT_RT: interrupt enable bit of receive timeout event + \arg USART_INT_EB: interrupt enable bit of end of block event + \param[out] none + \retval none +*/ +void usart_interrupt_disable(uint32_t usart_periph, uint32_t int_flag) +{ + USART_REG_VAL(usart_periph, int_flag) &= ~BIT(USART_BIT_POS(int_flag)); +} + +/*! + \brief get USART interrupt and flag status + \param[in] usart_periph: USARTx(x=0,1,2,5)/UARTx(x=3,4,6,7) + \param[in] int_flag + only one parameter can be selected which is shown as below: + \arg USART_INT_FLAG_PERR: parity error interrupt and flag + \arg USART_INT_FLAG_TBE: transmitter buffer empty interrupt and flag + \arg USART_INT_FLAG_TC: transmission complete interrupt and flag + \arg USART_INT_FLAG_RBNE: read data buffer not empty interrupt and flag + \arg USART_INT_FLAG_RBNE_ORERR: read data buffer not empty interrupt and overrun error flag + \arg USART_INT_FLAG_IDLE: IDLE line detected interrupt and flag + \arg USART_INT_FLAG_LBD: LIN break detected interrupt and flag + \arg USART_INT_FLAG_CTS: CTS interrupt and flag + \arg USART_INT_FLAG_ERR_ORERR: error interrupt and overrun error + \arg USART_INT_FLAG_ERR_NERR: error interrupt and noise error flag + \arg USART_INT_FLAG_ERR_FERR: error interrupt and frame error flag + \arg USART_INT_FLAG_EB: interrupt enable bit of end of block event and flag + \arg USART_INT_FLAG_RT: interrupt enable bit of receive timeout event and flag + \param[out] none + \retval FlagStatus +*/ +FlagStatus usart_interrupt_flag_get(uint32_t usart_periph, uint32_t int_flag) +{ + uint32_t intenable = 0U, flagstatus = 0U; + /* get the interrupt enable bit status */ + intenable = (USART_REG_VAL(usart_periph, int_flag) & BIT(USART_BIT_POS(int_flag))); + /* get the corresponding flag bit status */ + flagstatus = (USART_REG_VAL2(usart_periph, int_flag) & BIT(USART_BIT_POS2(int_flag))); + + if(flagstatus && intenable){ + return SET; + }else{ + return RESET; + } +} + +/*! + \brief clear USART interrupt flag in STAT0/STAT1 register + \param[in] usart_periph: USARTx(x=0,1,2,5)/UARTx(x=3,4,6,7) + \param[in] flag: USART interrupt flag + only one parameter can be selected which is shown as below: + \arg USART_INT_FLAG_CTS: CTS interrupt and flag + \arg USART_INT_FLAG_LBD: LIN break detected interrupt and flag + \arg USART_INT_FLAG_TC: transmission complete interrupt and flag + \arg USART_INT_FLAG_RBNE: read data buffer not empty interrupt and flag + \arg USART_INT_FLAG_EB: interrupt enable bit of end of block event and flag + \arg USART_INT_FLAG_RT: interrupt enable bit of receive timeout event and flag + \param[out] none + \retval none +*/ +void usart_interrupt_flag_clear(uint32_t usart_periph, uint32_t flag) +{ + USART_REG_VAL2(usart_periph, flag) &= ~BIT(USART_BIT_POS2(flag)); +} diff --git a/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_standard_peripheral/Source/gd32f20x_wwdgt.c b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_standard_peripheral/Source/gd32f20x_wwdgt.c new file mode 100644 index 0000000000..b61152551f --- /dev/null +++ b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_standard_peripheral/Source/gd32f20x_wwdgt.c @@ -0,0 +1,149 @@ +/*! + \file gd32f20x_wwdgt.c + \brief WWDGT driver + + \version 2015-07-15, V1.0.0, firmware for GD32F20x + \version 2017-06-05, V2.0.0, firmware for GD32F20x + \version 2018-10-31, V2.1.0, firmware for GD32F20x + \version 2020-09-30, V2.2.0, firmware for GD32F20x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "gd32f20x_wwdgt.h" + +/* write value to WWDGT_CTL_CNT bit field */ +#define CTL_CNT(regval) (BITS(0,6) & ((uint32_t)(regval) << 0)) +/* write value to WWDGT_CFG_WIN bit field */ +#define CFG_WIN(regval) (BITS(0,6) & ((uint32_t)(regval) << 0)) + +/*! + \brief reset the window watchdog timer configuration + \param[in] none + \param[out] none + \retval none +*/ +void wwdgt_deinit(void) +{ + rcu_periph_reset_enable(RCU_WWDGTRST); + rcu_periph_reset_disable(RCU_WWDGTRST); +} + +/*! + \brief start the window watchdog timer counter + \param[in] none + \param[out] none + \retval none +*/ +void wwdgt_enable(void) +{ + WWDGT_CTL |= WWDGT_CTL_WDGTEN; +} + +/*! + \brief configure the window watchdog timer counter value + \param[in] counter_value: 0x00 - 0x7F + \param[out] none + \retval none +*/ +void wwdgt_counter_update(uint16_t counter_value) +{ + uint32_t reg = 0U; + + reg = (WWDGT_CTL & (~WWDGT_CTL_CNT)); + reg |= CTL_CNT(counter_value); + + WWDGT_CTL = reg; +} + +/*! + \brief configure counter value, window value, and prescaler divider value + \param[in] counter: 0x00 - 0x7F + \param[in] window: 0x00 - 0x7F + \param[in] prescaler: wwdgt prescaler value + only one parameter can be selected which is shown as below: + \arg WWDGT_CFG_PSC_DIV1: the time base of window watchdog counter = (PCLK1/4096)/1 + \arg WWDGT_CFG_PSC_DIV2: the time base of window watchdog counter = (PCLK1/4096)/2 + \arg WWDGT_CFG_PSC_DIV4: the time base of window watchdog counter = (PCLK1/4096)/4 + \arg WWDGT_CFG_PSC_DIV8: the time base of window watchdog counter = (PCLK1/4096)/8 + \param[out] none + \retval none +*/ +void wwdgt_config(uint16_t counter, uint16_t window, uint32_t prescaler) +{ + uint32_t reg_cfg = 0U, reg_ctl = 0U; + + /* clear WIN and PSC bits, clear CNT bit */ + reg_cfg = (WWDGT_CFG &(~(WWDGT_CFG_WIN|WWDGT_CFG_PSC))); + reg_ctl = (WWDGT_CTL &(~WWDGT_CTL_CNT)); + + /* configure WIN and PSC bits, configure CNT bit */ + reg_cfg |= CFG_WIN(window); + reg_cfg |= prescaler; + reg_ctl |= CTL_CNT(counter); + + WWDGT_CTL = reg_ctl; + WWDGT_CFG = reg_cfg; +} + +/*! + \brief enable early wakeup interrupt of WWDGT + \param[in] none + \param[out] none + \retval none +*/ +void wwdgt_interrupt_enable(void) +{ + WWDGT_CFG |= WWDGT_CFG_EWIE; +} + +/*! + \brief check early wakeup interrupt state of WWDGT + \param[in] none + \param[out] none + \retval FlagStatus: SET or RESET +*/ +FlagStatus wwdgt_flag_get(void) +{ + if(WWDGT_STAT & WWDGT_STAT_EWIF){ + return SET; + } + + return RESET; +} + +/*! + \brief clear early wakeup interrupt state of WWDGT + \param[in] none + \param[out] none + \retval none +*/ +void wwdgt_flag_clear(void) +{ + WWDGT_STAT &= (~WWDGT_STAT_EWIF); +} diff --git a/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/device/class/audio/Include/audio_core.h b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/device/class/audio/Include/audio_core.h new file mode 100644 index 0000000000..4e17823725 --- /dev/null +++ b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/device/class/audio/Include/audio_core.h @@ -0,0 +1,300 @@ +/*! + \file audio_core.h + \brief the header file of USB audio device class core functions + + \version 2020-07-28, V3.0.0, firmware for GD32F20x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef __AUDIO_CORE_H +#define __AUDIO_CORE_H + +#include "usbd_enum.h" + +#define FORMAT_24BIT(x) (uint8_t)(x);(uint8_t)(x >> 8U);(uint8_t)(x >> 16U) + +/* number of sub-packets in the audio transfer buffer. you can modify this value but always make sure + that it is an even number and higher than 3 */ +#define OUT_PACKET_NUM 4U + +/* total size of the audio transfer buffer */ +#define OUT_BUF_MARGIN 4U +#define TOTAL_OUT_BUF_SIZE ((uint32_t)((SPEAKER_OUT_PACKET + OUT_BUF_MARGIN) * OUT_PACKET_NUM)) + +#define AUDIO_CONFIG_DESC_SET_LEN (sizeof(usb_desc_config_set)) +#define AUDIO_INTERFACE_DESC_SIZE 9U + +#define USB_AUDIO_DESC_SIZ 0x09U +#define AUDIO_STANDARD_EP_DESC_SIZE 0x09U +#define AUDIO_STREAMING_EP_DESC_SIZE 0x07U + +/* audio interface class code */ +#define USB_CLASS_AUDIO 0x01U + +/* audio interface subclass codes */ +#define AUDIO_SUBCLASS_CONTROL 0x01U +#define AUDIO_SUBCLASS_AUDIOSTREAMING 0x02U +#define AUDIO_SUBCLASS_MIDISTREAMING 0x03U + +/* audio interface protocol codes */ +#define AUDIO_PROTOCOL_UNDEFINED 0x00U +#define AUDIO_STREAMING_GENERAL 0x01U +#define AUDIO_STREAMING_FORMAT_TYPE 0x02U + +/* audio class-specific descriptor types */ +#define AUDIO_DESCTYPE_UNDEFINED 0x20U +#define AUDIO_DESCTYPE_DEVICE 0x21U +#define AUDIO_DESCTYPE_CONFIGURATION 0x22U +#define AUDIO_DESCTYPE_STRING 0x23U +#define AUDIO_DESCTYPE_INTERFACE 0x24U +#define AUDIO_DESCTYPE_ENDPOINT 0x25U + +/* audio control interface descriptor subtypes */ +#define AUDIO_CONTROL_HEADER 0x01U +#define AUDIO_CONTROL_INPUT_TERMINAL 0x02U +#define AUDIO_CONTROL_OUTPUT_TERMINAL 0x03U +#define AUDIO_CONTROL_MIXER_UNIT 0x04U +#define AUDIO_CONTROL_SELECTOR_UNIT 0x05U +#define AUDIO_CONTROL_FEATURE_UNIT 0x06U +#define AUDIO_CONTROL_PROCESSING_UNIT 0x07U +#define AUDIO_CONTROL_EXTENSION_UNIT 0x08U + +#define AUDIO_INPUT_TERMINAL_DESC_SIZE 0x0CU +#define AUDIO_OUTPUT_TERMINAL_DESC_SIZE 0x09U +#define AUDIO_STREAMING_INTERFACE_DESC_SIZE 0x07U + +#define AUDIO_CONTROL_MUTE 0x01U +#define AUDIO_CONTROL_VOLUME 0x02U + +#define AUDIO_FORMAT_TYPE_I 0x01U +#define AUDIO_FORMAT_TYPE_III 0x03U + +#define USB_ENDPOINT_TYPE_ISOCHRONOUS 0x01U +#define AUDIO_ENDPOINT_GENERAL 0x01U + +#define AUDIO_REQ_UNDEFINED 0x00U +#define AUDIO_REQ_SET_CUR 0x01U +#define AUDIO_REQ_GET_CUR 0x81U +#define AUDIO_REQ_SET_MIN 0x02U +#define AUDIO_REQ_GET_MIN 0x82U +#define AUDIO_REQ_SET_MAX 0x03U +#define AUDIO_REQ_GET_MAX 0x83U +#define AUDIO_REQ_SET_RES 0x04U +#define AUDIO_REQ_GET_RES 0x84U +#define AUDIO_REQ_SET_MEM 0x05U +#define AUDIO_REQ_GET_MEM 0x85U +#define AUDIO_REQ_GET_STAT 0xFFU + +#define AUDIO_OUT_STREAMING_CTRL 0x05U +#define AUDIO_IN_STREAMING_CTRL 0x02U + +/* audio stream interface number */ +enum +{ +#ifdef USE_USB_AUDIO_MICPHONE + MIC_INTERFACE_COUNT, +#endif +#ifdef USE_USB_AUDIO_SPEAKER + SPEAK_INTERFACE_COUNT, +#endif + CONFIG_DESC_AS_ITF_COUNT, +}; + +#define AC_ITF_TOTAL_LEN (sizeof(usb_desc_AC_itf) + CONFIG_DESC_AS_ITF_COUNT*(sizeof(usb_desc_input_terminal) + \ + sizeof(usb_desc_mono_feature_unit) + sizeof(usb_desc_output_terminal))) + +#pragma pack(1) + +typedef struct +{ + usb_desc_header header; /*!< descriptor header, including type and size */ + uint8_t bDescriptorSubtype; /*!< header descriptor subtype */ + uint16_t bcdADC; /*!< audio device class specification release number in binary-coded decimal */ + uint16_t wTotalLength; /*!< total number of bytes */ + uint8_t bInCollection; /*!< the number of the streaming interfaces */ +#ifdef USE_USB_AUDIO_MICPHONE + uint8_t baInterfaceNr0; /*!< interface number of the streaming interfaces */ +#endif + +#ifdef USE_USB_AUDIO_SPEAKER + uint8_t baInterfaceNr1; /*!< interface number of the streaming interfaces */ +#endif +} usb_desc_AC_itf; + +typedef struct +{ + usb_desc_header header; /*!< descriptor header, including type and size */ + uint8_t bDescriptorSubtype; /*!< AS_GENERAL descriptor subtype */ + uint8_t bTerminalLink; /*!< the terminal ID */ + uint8_t bDelay; /*!< delay introduced by the data path */ + uint16_t wFormatTag; /*!< the audio data format */ +} usb_desc_AS_itf; + +typedef struct +{ + usb_desc_header header; /*!< descriptor header, including type and size */ + uint8_t bDescriptorSubtype; /*!< INPUT_TERMINAL descriptor subtype. */ + uint8_t bTerminalID; /*!< constant uniquely identifying the terminal within the audio function */ + uint16_t wTerminalType; /*!< constant characterizing the type of terminal */ + uint8_t bAssocTerminal; /*!< ID of the output terminal */ + uint8_t bNrChannels; /*!< number of logical output channels */ + uint16_t wChannelConfig; /*!< describes the spatial location of the logical channels */ + uint8_t iChannelNames; /*!< index of a string descriptor */ + uint8_t iTerminal; /*!< index of a string descriptor */ +} usb_desc_input_terminal; + +typedef struct +{ + usb_desc_header header; /*!< descriptor header, including type and size */ + uint8_t bDescriptorSubtype; /*!< OUTPUT_TERMINAL descriptor subtype */ + uint8_t bTerminalID; /*!< constant uniquely identifying the terminal within the audio function */ + uint16_t wTerminalType; /*!< constant characterizing the type of terminal */ + uint8_t bAssocTerminal; /*!< constant, identifying the input terminal to which this output terminal is associated */ + uint8_t bSourceID; /*!< ID of the unit or terminal */ + uint8_t iTerminal; /*!< index of a string descriptor */ +} usb_desc_output_terminal; + +typedef struct +{ + usb_desc_header header; /*!< descriptor header, including type and size */ + uint8_t bDescriptorSubtype; /*!< FEATURE_UNIT descriptor subtype */ + uint8_t bUnitID; /*!< constant uniquely identifying the unit within the audio function */ + uint8_t bSourceID; /*!< ID of the unit or terminal */ + uint8_t bControlSize; /*!< size in bytes of an element of the bmaControls() array */ + uint8_t bmaControls0; /*!< a bit set to 1 indicates that the mentioned control is supported for master channel 0 */ + uint8_t bmaControls1; /*!< a bit set to 1 indicates that the mentioned control is supported for logical channel 1 */ + uint8_t iFeature; /*!< index of a string descriptor */ +} usb_desc_mono_feature_unit; + +typedef struct +{ + usb_desc_header header; /*!< descriptor header, including type and size */ + uint8_t bDescriptorSubtype; /*!< FEATURE_UNIT descriptor subtype */ + uint8_t bUnitID; /*!< constant uniquely identifying the unit within the audio function */ + uint8_t bSourceID; /*!< ID of the unit or terminal */ + uint8_t bControlSize; /*!< size in bytes of an element of the bmaControls() array */ + uint16_t bmaControls0; /*!< a bit set to 1 indicates that the mentioned control is supported for master channel 0 */ + uint16_t bmaControls1; /*!< a bit set to 1 indicates that the mentioned control is supported for logical channel 1 */ + uint16_t bmaControls2; /*!< a bit set to 1 indicates that the mentioned control is supported for logical channel 2 */ + uint8_t iFeature; /*!< index of a string descriptor */ +} usb_desc_stereo_feature_unit; + +typedef struct +{ + usb_desc_header header; /*!< descriptor header, including type and size */ + uint8_t bDescriptorSubtype; /*!< FORMAT_TYPE descriptor subtype */ + uint8_t bFormatType; /*!< constant identifying the format type */ + uint8_t bNrChannels; /*!< indicates the number of physical channels in the audio data stream */ + uint8_t bSubFrameSize; /*!< the number of bytes occupied by one audio subframe */ + uint8_t bBitResolution; /*!< the number of effectively used bits from the available bits in an audio subframe */ + uint8_t bSamFreqType; /*!< indicates how the sampling frequency can be programmed */ + uint8_t bSamFreq[3]; /*!< sampling frequency ns in Hz for this isochronous data endpoint */ +} usb_desc_format_type; + +typedef struct +{ + usb_desc_header header; /*!< descriptor header, including type and size */ + uint8_t bEndpointAddress; /*!< the address of the endpoint */ + uint8_t bmAttributes; /*!< transfer type and synchronization type */ + uint16_t wMaxPacketSize; /*!< maximum packet size this endpoint is capable of sending or receiving */ + uint8_t bInterval; /*!< left to the designer's discretion */ + uint8_t bRefresh; /*!< reset to 0 */ + uint8_t bSynchAddress; /*!< reset to 0 */ +} usb_desc_std_ep; + +typedef struct +{ + usb_desc_header header; /*!< descriptor header, including type and size */ + uint8_t bDescriptorSubtype; /*!< EP_GENERAL descriptor subtype */ + uint8_t bmAttributes; /*!< transfer type and synchronization type */ + uint8_t bLockDelayUnits; /*!< indicates the units used for the wLockDelay field */ + uint16_t wLockDelay; /*!< indicates the time it takes this endpoint to reliably lock its internal clock recovery circuitry */ +} usb_desc_AS_ep; + +#pragma pack() + +/* USB configuration descriptor structure */ +typedef struct +{ + usb_desc_config config; + usb_desc_itf std_itf; + usb_desc_AC_itf ac_itf; + +#ifdef USE_USB_AUDIO_MICPHONE + usb_desc_input_terminal mic_in_terminal; + usb_desc_mono_feature_unit mic_feature_unit; + usb_desc_output_terminal mic_out_terminal; +#endif + +#ifdef USE_USB_AUDIO_SPEAKER + usb_desc_input_terminal speak_in_terminal; + usb_desc_mono_feature_unit speak_feature_unit; + usb_desc_output_terminal speak_out_terminal; +#endif + +#ifdef USE_USB_AUDIO_MICPHONE + usb_desc_itf mic_std_as_itf_zeroband; + usb_desc_itf mic_std_as_itf_opera; + usb_desc_AS_itf mic_as_itf; + usb_desc_format_type mic_format_typeI; + usb_desc_std_ep mic_std_endpoint; + usb_desc_AS_ep mic_as_endpoint; +#endif + +#ifdef USE_USB_AUDIO_SPEAKER + usb_desc_itf speak_std_as_itf_zeroband; + usb_desc_itf speak_std_as_itf_opera; + usb_desc_AS_itf speak_as_itf; + usb_desc_format_type speak_format_typeI; + usb_desc_std_ep speak_std_endpoint; + usb_desc_AS_ep speak_as_endpoint; +#endif +} usb_desc_config_set; + +typedef struct +{ + /* main buffer for audio data out transfers and its relative pointers */ + uint8_t isoc_out_buff[TOTAL_OUT_BUF_SIZE * 2U]; + uint8_t* isoc_out_wrptr; + uint8_t* isoc_out_rdptr; + + /* main buffer for audio control requests transfers and its relative variables */ + uint8_t audioctl[64]; + uint8_t audioctl_unit; + uint32_t audioctl_len; + +#ifdef USE_USB_AUDIO_SPEAKER + uint32_t play_flag; +#endif /* USE_USB_AUDIO_SPEAKER */ +} usbd_audio_handler; + +extern usb_desc audio_desc; +extern usb_class_core usbd_audio_cb; + +#endif /* __AUDIO_CORE_H */ diff --git a/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/device/class/audio/Include/audio_out_itf.h b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/device/class/audio/Include/audio_out_itf.h new file mode 100644 index 0000000000..06c7dd63e8 --- /dev/null +++ b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/device/class/audio/Include/audio_out_itf.h @@ -0,0 +1,76 @@ +/*! + \file audio_out_itf.h + \brief audio OUT (playback) interface header file + + \version 2020-07-28, V3.0.0, firmware for GD32F20x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef __AUDIO_OUT_ITF_H +#define __AUDIO_OUT_ITF_H + +#include "usbd_conf.h" + +/* audio commands enumeration */ +typedef enum +{ + AUDIO_CMD_PLAY = 1U, + AUDIO_CMD_PAUSE, + AUDIO_CMD_STOP, +}audio_cmd_enum; + +/* mute commands */ +#define AUDIO_MUTE 0x01U +#define AUDIO_UNMUTE 0x00U + +/* functions return value */ +#define AUDIO_OK 0x00U +#define AUDIO_FAIL 0xFFU + +/* audio machine states */ +#define AUDIO_STATE_INACTIVE 0x00U +#define AUDIO_STATE_ACTIVE 0x01U +#define AUDIO_STATE_PLAYING 0x02U +#define AUDIO_STATE_PAUSED 0x03U +#define AUDIO_STATE_STOPPED 0x04U +#define AUDIO_STATE_ERROR 0x05U + +typedef struct { + uint8_t (*audio_init) (uint32_t audio_freq, uint32_t volume, uint32_t options); + uint8_t (*audio_deinit) (uint32_t options); + uint8_t (*audio_cmd) (uint8_t* pbuf, uint32_t size, uint8_t cmd); + uint8_t (*audio_volume_ctl) (uint8_t vol); + uint8_t (*audio_mute_ctl) (uint8_t cmd); + uint8_t (*audio_periodic_tc) (uint8_t cmd); + uint8_t (*audio_state_get) (void); +} audio_fops_struct; + +extern audio_fops_struct audio_out_fops; + +#endif /* __AUDIO_OUT_ITF_H */ diff --git a/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/device/class/audio/Source/audio_core.c b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/device/class/audio/Source/audio_core.c new file mode 100644 index 0000000000..3d4422647c --- /dev/null +++ b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/device/class/audio/Source/audio_core.c @@ -0,0 +1,787 @@ +/*! + \file audio_core.c + \brief USB audio device class core functions + + \version 2020-07-28, V3.0.0, firmware for GD32F20x + \version 2020-12-10, V3.0.1, firmware for GD32F20x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "audio_out_itf.h" +#include "audio_core.h" + +#include + +#define USBD_VID 0x28E9U +#define USBD_PID 0x9574U + +#ifdef USE_USB_AUDIO_MICPHONE +extern volatile uint32_t count_data; +extern const char wavetestdata[]; +#define LENGTH_DATA (1747 * 32) +#endif + +/* local function prototypes ('static') */ +static uint8_t audio_init (usb_dev *udev, uint8_t config_index); +static uint8_t audio_deinit (usb_dev *udev, uint8_t config_index); +static uint8_t audio_req_handler (usb_dev *udev, usb_req *req); +static uint8_t audio_data_in (usb_dev *udev, uint8_t ep_num); +static uint8_t audio_ctlx_out (usb_dev *udev); +static uint8_t audio_data_out (usb_dev *udev, uint8_t ep_num); +static uint8_t usbd_audio_sof (usb_dev *udev); + +usb_class_core usbd_audio_cb = { + .init = audio_init, + .deinit = audio_deinit, + .req_proc = audio_req_handler, + .ctlx_out = audio_ctlx_out, + .data_in = audio_data_in, + .data_out = audio_data_out, + .SOF = usbd_audio_sof +}; + +#define VOL_MIN 0U /* Volume Minimum Value */ +#define VOL_MAX 100U /* Volume Maximum Value */ +#define VOL_RES 1U /* Volume Resolution */ +#define VOL_0dB 70U /* 0dB is in the middle of VOL_MIN and VOL_MAX */ + +/* note:it should use the c99 standard when compiling the below codes */ +/* USB standard device descriptor */ +const usb_desc_dev audio_dev_desc = +{ + .header = + { + .bLength = USB_DEV_DESC_LEN, + .bDescriptorType = USB_DESCTYPE_DEV + }, + .bcdUSB = 0x0200U, + .bDeviceClass = 0x00U, + .bDeviceSubClass = 0x00U, + .bDeviceProtocol = 0x00U, + .bMaxPacketSize0 = USB_FS_EP0_MAX_LEN, + .idVendor = USBD_VID, + .idProduct = USBD_PID, + .bcdDevice = 0x0100U, + .iManufacturer = STR_IDX_MFC, + .iProduct = STR_IDX_PRODUCT, + .iSerialNumber = STR_IDX_SERIAL, + .bNumberConfigurations = USBD_CFG_MAX_NUM +}; + +/* USB device configuration descriptor */ +const usb_desc_config_set audio_config_set = +{ + .config = + { + .header = + { + .bLength = sizeof(usb_desc_config), + .bDescriptorType = USB_DESCTYPE_CONFIG + }, + .wTotalLength = AUDIO_CONFIG_DESC_SET_LEN, + .bNumInterfaces = 0x01U + CONFIG_DESC_AS_ITF_COUNT, + .bConfigurationValue = 0x01U, + .iConfiguration = 0x00U, + .bmAttributes = 0xC0U, + .bMaxPower = 0x32U + }, + + .std_itf = + { + .header = + { + .bLength = sizeof(usb_desc_itf), + .bDescriptorType = USB_DESCTYPE_ITF + }, + .bInterfaceNumber = 0x00U, + .bAlternateSetting = 0x00U, + .bNumEndpoints = 0x00U, + .bInterfaceClass = USB_CLASS_AUDIO, + .bInterfaceSubClass = AUDIO_SUBCLASS_CONTROL, + .bInterfaceProtocol = AUDIO_PROTOCOL_UNDEFINED, + .iInterface = 0x00U + }, + + .ac_itf = + { + .header = + { + .bLength = sizeof(usb_desc_AC_itf), + .bDescriptorType = AUDIO_DESCTYPE_INTERFACE + }, + .bDescriptorSubtype = 0x01U, + .bcdADC = 0x0100U, + .wTotalLength = AC_ITF_TOTAL_LEN, + .bInCollection = CONFIG_DESC_AS_ITF_COUNT, +#ifdef USE_USB_AUDIO_MICPHONE + .baInterfaceNr0 = 0x01U, +#endif +#ifdef USE_USB_AUDIO_SPEAKER + .baInterfaceNr1 = 0x02U +#endif + }, + +#ifdef USE_USB_AUDIO_MICPHONE + .mic_in_terminal = + { + .header = + { + .bLength = sizeof(usb_desc_input_terminal), + .bDescriptorType = AUDIO_DESCTYPE_INTERFACE + }, + .bDescriptorSubtype = 0x02U, + .bTerminalID = 0x01U, + .wTerminalType = 0x0201U, + .bAssocTerminal = 0x00U, + .bNrChannels = 0x02U, + .wChannelConfig = 0x0003U, + .iChannelNames = 0x00U, + .iTerminal = 0x00U + }, + + .mic_feature_unit = + { + .header = + { + .bLength = sizeof(usb_desc_mono_feature_unit), + .bDescriptorType = AUDIO_DESCTYPE_INTERFACE + }, + .bDescriptorSubtype = AUDIO_CONTROL_FEATURE_UNIT, + .bUnitID = AUDIO_IN_STREAMING_CTRL, + .bSourceID = 0x01U, + .bControlSize = 0x01U, + .bmaControls0 = AUDIO_CONTROL_MUTE, + .bmaControls1 = AUDIO_CONTROL_VOLUME, + .iFeature = 0x00U + }, + + .mic_out_terminal = + { + .header = + { + .bLength = sizeof(usb_desc_output_terminal), + .bDescriptorType = AUDIO_DESCTYPE_INTERFACE + }, + .bDescriptorSubtype = AUDIO_CONTROL_OUTPUT_TERMINAL, + .bTerminalID = 0x03U, + .wTerminalType = 0x0101U, + .bAssocTerminal = 0x00U, + .bSourceID = 0x02U, + .iTerminal = 0x00U + }, +#endif + +#ifdef USE_USB_AUDIO_SPEAKER + .speak_in_terminal = + { + .header = + { + .bLength = sizeof(usb_desc_input_terminal), + .bDescriptorType = AUDIO_DESCTYPE_INTERFACE + }, + .bDescriptorSubtype = AUDIO_CONTROL_INPUT_TERMINAL, + .bTerminalID = 0x04U, + .wTerminalType = 0x0101U, + .bAssocTerminal = 0x00U, + .bNrChannels = 0x02U, + .wChannelConfig = 0x0003U, + .iChannelNames = 0x00U, + .iTerminal = 0x00U + }, + + .speak_feature_unit = + { + .header = + { + .bLength = sizeof(usb_desc_mono_feature_unit), + .bDescriptorType = AUDIO_DESCTYPE_INTERFACE + }, + .bDescriptorSubtype = AUDIO_CONTROL_FEATURE_UNIT, + .bUnitID = AUDIO_OUT_STREAMING_CTRL, + .bSourceID = 0x04U, + .bControlSize = 0x01U, + .bmaControls0 = AUDIO_CONTROL_MUTE, + .bmaControls1 = AUDIO_CONTROL_VOLUME, + .iFeature = 0x00U + }, + + .speak_out_terminal = + { + .header = + { + .bLength = sizeof(usb_desc_output_terminal), + .bDescriptorType = AUDIO_DESCTYPE_INTERFACE + }, + .bDescriptorSubtype = AUDIO_CONTROL_OUTPUT_TERMINAL, + .bTerminalID = 0x06U, + .wTerminalType = 0x0301U, + .bAssocTerminal = 0x00U, + .bSourceID = 0x05U, + .iTerminal = 0x00U + }, +#endif + +#ifdef USE_USB_AUDIO_MICPHONE + .mic_std_as_itf_zeroband = + { + .header = + { + .bLength = sizeof(usb_desc_itf), + .bDescriptorType = USB_DESCTYPE_ITF + }, + .bInterfaceNumber = 0x01U, + .bAlternateSetting = 0x00U, + .bNumEndpoints = 0x00U, + .bInterfaceClass = USB_CLASS_AUDIO, + .bInterfaceSubClass = AUDIO_SUBCLASS_AUDIOSTREAMING, + .bInterfaceProtocol = AUDIO_PROTOCOL_UNDEFINED, + .iInterface = 0x00U + }, + + .mic_std_as_itf_opera = + { + .header = + { + .bLength = sizeof(usb_desc_itf), + .bDescriptorType = USB_DESCTYPE_ITF + }, + .bInterfaceNumber = 0x01U, + .bAlternateSetting = 0x01U, + .bNumEndpoints = 0x01U, + .bInterfaceClass = USB_CLASS_AUDIO, + .bInterfaceSubClass = AUDIO_SUBCLASS_AUDIOSTREAMING, + .bInterfaceProtocol = AUDIO_PROTOCOL_UNDEFINED, + .iInterface = 0x00U + }, + + .mic_as_itf = + { + .header = + { + .bLength = sizeof(usb_desc_AS_itf), + .bDescriptorType = AUDIO_DESCTYPE_INTERFACE + }, + .bDescriptorSubtype = AUDIO_STREAMING_GENERAL, + .bTerminalLink = 0x03U, + .bDelay = 0x01U, + .wFormatTag = 0x0001U, + }, + + .mic_format_typeI = + { + .header = + { + .bLength = sizeof(usb_desc_format_type), + .bDescriptorType = AUDIO_DESCTYPE_INTERFACE + }, + .bDescriptorSubtype = AUDIO_STREAMING_FORMAT_TYPE, + .bFormatType = AUDIO_FORMAT_TYPE_I, + .bNrChannels = MIC_IN_CHANNEL_NBR, + .bSubFrameSize = 0x02U, + .bBitResolution = MIC_IN_BIT_RESOLUTION, + .bSamFreqType = 0x01U, + .bSamFreq[0] = (uint8_t)USBD_MIC_FREQ, + .bSamFreq[1] = USBD_MIC_FREQ >> 8U, + .bSamFreq[2] = USBD_MIC_FREQ >> 16U + }, + + .mic_std_endpoint = + { + .header = + { + .bLength = sizeof(usb_desc_std_ep), + .bDescriptorType = USB_DESCTYPE_EP + }, + .bEndpointAddress = AUDIO_IN_EP, + .bmAttributes = USB_ENDPOINT_TYPE_ISOCHRONOUS, + .wMaxPacketSize = MIC_IN_PACKET, + .bInterval = 0x01U, + .bRefresh = 0x00U, + .bSynchAddress = 0x00U + }, + + .mic_as_endpoint = + { + .header = + { + .bLength = sizeof(usb_desc_AS_ep), + .bDescriptorType = AUDIO_DESCTYPE_ENDPOINT + }, + .bDescriptorSubtype = AUDIO_ENDPOINT_GENERAL, + .bmAttributes = 0x00U, + .bLockDelayUnits = 0x00U, + .wLockDelay = 0x0000U, + }, +#endif + +#ifdef USE_USB_AUDIO_SPEAKER + .speak_std_as_itf_zeroband = + { + .header = + { + .bLength = sizeof(usb_desc_itf), + .bDescriptorType = USB_DESCTYPE_ITF + }, + .bInterfaceNumber = 0x02U, + .bAlternateSetting = 0x00U, + .bNumEndpoints = 0x00U, + .bInterfaceClass = USB_CLASS_AUDIO, + .bInterfaceSubClass = AUDIO_SUBCLASS_AUDIOSTREAMING, + .bInterfaceProtocol = AUDIO_PROTOCOL_UNDEFINED, + .iInterface = 0x00U + }, + + .speak_std_as_itf_opera = + { + .header = + { + .bLength = sizeof(usb_desc_itf), + .bDescriptorType = USB_DESCTYPE_ITF + }, + .bInterfaceNumber = 0x02U, + .bAlternateSetting = 0x01U, + .bNumEndpoints = 0x01U, + .bInterfaceClass = USB_CLASS_AUDIO, + .bInterfaceSubClass = AUDIO_SUBCLASS_AUDIOSTREAMING, + .bInterfaceProtocol = AUDIO_PROTOCOL_UNDEFINED, + .iInterface = 0x00U + }, + + .speak_as_itf = + { + .header = + { + .bLength = sizeof(usb_desc_AS_itf), + .bDescriptorType = AUDIO_DESCTYPE_INTERFACE + }, + .bDescriptorSubtype = AUDIO_STREAMING_GENERAL, + .bTerminalLink = 0x04U, + .bDelay = 0x01U, + .wFormatTag = 0x0001U, + }, + + .speak_format_typeI = + { + .header = + { + .bLength = sizeof(usb_desc_format_type), + .bDescriptorType = AUDIO_DESCTYPE_INTERFACE + }, + .bDescriptorSubtype = AUDIO_STREAMING_FORMAT_TYPE, + .bFormatType = AUDIO_FORMAT_TYPE_I, + .bNrChannels = SPEAKER_OUT_CHANNEL_NBR, + .bSubFrameSize = 0x02U, + .bBitResolution = SPEAKER_OUT_BIT_RESOLUTION, + .bSamFreqType = 0x01U, + .bSamFreq[0] = (uint8_t)USBD_SPEAKER_FREQ, + .bSamFreq[1] = USBD_SPEAKER_FREQ >> 8U, + .bSamFreq[2] = USBD_SPEAKER_FREQ >> 16U + }, + + .speak_std_endpoint = + { + .header = + { + .bLength = sizeof(usb_desc_std_ep), + .bDescriptorType = USB_DESCTYPE_EP + }, + .bEndpointAddress = AUDIO_OUT_EP, + .bmAttributes = USB_ENDPOINT_TYPE_ISOCHRONOUS, + .wMaxPacketSize = SPEAKER_OUT_PACKET, + .bInterval = 0x01U, + .bRefresh = 0x00U, + .bSynchAddress = 0x00U + }, + + .speak_as_endpoint = + { + .header = + { + .bLength = sizeof(usb_desc_AS_ep), + .bDescriptorType = AUDIO_DESCTYPE_ENDPOINT + }, + .bDescriptorSubtype = AUDIO_ENDPOINT_GENERAL, + .bmAttributes = 0x00U, + .bLockDelayUnits = 0x00U, + .wLockDelay = 0x0000U, + } +#endif +}; + +/* USB language ID descriptor */ +static const usb_desc_LANGID usbd_language_id_desc = +{ + .header = + { + .bLength = sizeof(usb_desc_LANGID), + .bDescriptorType = USB_DESCTYPE_STR + }, + + .wLANGID = ENG_LANGID +}; + +/* USB manufacture string */ +static const usb_desc_str manufacturer_string = +{ + .header = + { + .bLength = USB_STRING_LEN(10), + .bDescriptorType = USB_DESCTYPE_STR, + }, + .unicode_string = {'G', 'i', 'g', 'a', 'D', 'e', 'v', 'i', 'c', 'e'} +}; + +/* USB product string */ +static const usb_desc_str product_string = +{ + .header = + { + .bLength = USB_STRING_LEN(14), + .bDescriptorType = USB_DESCTYPE_STR, + }, + .unicode_string = {'G', 'D', '3', '2', '-', 'U', 'S', 'B', '_', 'A', 'u', 'd', 'i', 'o'} +}; + +/* USBD serial string */ +static usb_desc_str serial_string = +{ + .header = + { + .bLength = USB_STRING_LEN(12), + .bDescriptorType = USB_DESCTYPE_STR, + } +}; + +/* USB string descriptor */ +void *const usbd_audio_strings[] = +{ + [STR_IDX_LANGID] = (uint8_t *)&usbd_language_id_desc, + [STR_IDX_MFC] = (uint8_t *)&manufacturer_string, + [STR_IDX_PRODUCT] = (uint8_t *)&product_string, + [STR_IDX_SERIAL] = (uint8_t *)&serial_string +}; + +usb_desc audio_desc = { + .dev_desc = (uint8_t *)&audio_dev_desc, + .config_desc = (uint8_t *)&audio_config_set, + .strings = usbd_audio_strings +}; + +/*! + \brief initialize the AUDIO device + \param[in] udev: pointer to USB device instance + \param[in] config_index: configuration index + \param[out] none + \retval USB device operation status +*/ +static uint8_t audio_init (usb_dev *udev, uint8_t config_index) +{ + static usbd_audio_handler audio_handler; + + memset((void *)&audio_handler, 0, sizeof(usbd_audio_handler)); + +#ifdef USE_USB_AUDIO_MICPHONE +{ + usb_desc_std_ep std_ep = audio_config_set.mic_std_endpoint; + + usb_desc_ep ep = { + .header = std_ep.header, + .bEndpointAddress = std_ep.bEndpointAddress, + .bmAttributes = std_ep.bmAttributes, + .wMaxPacketSize = std_ep.wMaxPacketSize, + .bInterval = std_ep.bInterval + }; + + /* initialize Tx endpoint */ + usbd_ep_setup (udev, &ep); +} +#endif + +#ifdef USE_USB_AUDIO_SPEAKER +{ + audio_handler.isoc_out_rdptr = audio_handler.isoc_out_buff; + audio_handler.isoc_out_wrptr = audio_handler.isoc_out_buff; + + usb_desc_std_ep std_ep = audio_config_set.speak_std_endpoint; + + usb_desc_ep ep = { + .header = std_ep.header, + .bEndpointAddress = std_ep.bEndpointAddress, + .bmAttributes = std_ep.bmAttributes, + .wMaxPacketSize = std_ep.wMaxPacketSize, + .bInterval = std_ep.bInterval + }; + + /* initialize Rx endpoint */ + usbd_ep_setup (udev, &ep); + + /* initialize the audio output hardware layer */ + if (USBD_OK != audio_out_fops.audio_init(USBD_AUDIO_FREQ_16K, DEFAULT_VOLUME, 0U)) { + return USBD_FAIL; + } + + /* prepare OUT endpoint to receive audio data */ + usbd_ep_recev (udev, AUDIO_OUT_EP, (uint8_t*)audio_handler.isoc_out_buff, SPEAKER_OUT_PACKET); +} +#endif + + udev->dev.class_data[USBD_AUDIO_INTERFACE] = (void *)&audio_handler; + + return USBD_OK; +} + +/*! + \brief deinitialize the AUDIO device + \param[in] udev: pointer to USB device instance + \param[in] config_index: configuration index + \param[out] none + \retval USB device operation status +*/ +static uint8_t audio_deinit (usb_dev *udev, uint8_t config_index) +{ +#ifdef USE_USB_AUDIO_MICPHONE + /* deinitialize AUDIO endpoints */ + usbd_ep_clear(udev, AUDIO_IN_EP); +#endif + +#ifdef USE_USB_AUDIO_SPEAKER + /* deinitialize AUDIO endpoints */ + usbd_ep_clear(udev, AUDIO_OUT_EP); + + /* deinitialize the audio output hardware layer */ + if (USBD_OK != audio_out_fops.audio_deinit(0U)) { + return USBD_FAIL; + } +#endif + + return USBD_OK; +} + +/*! + \brief handle the AUDIO class-specific requests + \param[in] udev: pointer to USB device instance + \param[in] req: device class-specific request + \param[out] none + \retval USB device operation status +*/ +static uint8_t audio_req_handler (usb_dev *udev, usb_req *req) +{ + uint8_t status = REQ_NOTSUPP; + + usbd_audio_handler *audio = (usbd_audio_handler *)udev->dev.class_data[USBD_AUDIO_INTERFACE]; + + usb_transc *transc_in = &udev->dev.transc_in[0]; + usb_transc *transc_out = &udev->dev.transc_out[0]; + + switch (req->bRequest) { + case AUDIO_REQ_GET_CUR: + transc_in->xfer_buf = audio->audioctl; + transc_in->remain_len = req->wLength; + + status = REQ_SUPP; + break; + + case AUDIO_REQ_SET_CUR: + if (req->wLength) { + transc_out->xfer_buf = audio->audioctl; + transc_out->remain_len = req->wLength; + + udev->dev.class_core->command = AUDIO_REQ_SET_CUR; + + audio->audioctl_len = req->wLength; + audio->audioctl_unit = BYTE_HIGH(req->wIndex); + + status = REQ_SUPP; + } + break; + + case AUDIO_REQ_GET_MIN: + *((uint16_t *)audio->audioctl) = VOL_MIN; + transc_in->xfer_buf = audio->audioctl; + transc_in->remain_len = req->wLength; + status = REQ_SUPP; + break; + + case AUDIO_REQ_GET_MAX: + *((uint16_t *)audio->audioctl) = VOL_MAX; + transc_in->xfer_buf = audio->audioctl; + transc_in->remain_len = req->wLength; + status = REQ_SUPP; + break; + + case AUDIO_REQ_GET_RES: + *((uint16_t *)audio->audioctl) = VOL_RES; + transc_in->xfer_buf = audio->audioctl; + transc_in->remain_len = req->wLength; + status = REQ_SUPP; + break; + + default: + break; + } + + return status; +} + +static uint8_t audio_ctlx_out (usb_dev *udev) +{ +#ifdef USE_USB_AUDIO_SPEAKER + usbd_audio_handler *audio = (usbd_audio_handler *)udev->dev.class_data[USBD_AUDIO_INTERFACE]; + + /* check if an audio_control request has been issued */ + if (AUDIO_REQ_SET_CUR == udev->dev.class_core->command) { + /* in this driver, to simplify code, only SET_CUR request is managed */ + + /* check for which addressed unit the audio_control request has been issued */ + if (AUDIO_OUT_STREAMING_CTRL == audio->audioctl_unit) { + /* in this driver, to simplify code, only one unit is manage */ + + /* call the audio interface mute function */ + audio_out_fops.audio_mute_ctl(audio->audioctl[0]); + + /* reset the audioctl_cmd variable to prevent re-entering this function */ + udev->dev.class_core->command = 0U; + + audio->audioctl_len = 0U; + } + } +#endif /* USE_USB_AUDIO_SPEAKER */ + + return USBD_OK; +} + +/*! + \brief handles the audio IN data stage + \param[in] udev: pointer to USB device instance + \param[in] ep_num: endpoint number + \param[out] none + \retval USB device operation status +*/ +static uint8_t audio_data_in (usb_dev *udev, uint8_t ep_num) +{ +#ifdef USE_USB_AUDIO_MICPHONE + if(count_data < LENGTH_DATA){ + /* Prepare next buffer to be sent: dummy data */ + usbd_ep_send(udev, AUDIO_IN_EP,(uint8_t*)&wavetestdata[count_data],MIC_IN_PACKET); + count_data += MIC_IN_PACKET; + } else { + usbd_ep_send(udev, AUDIO_IN_EP,(uint8_t*)wavetestdata,MIC_IN_PACKET); + count_data = MIC_IN_PACKET; + } +#endif + + return USBD_OK; +} + +/*! + \brief handles the audio OUT data stage + \param[in] udev: pointer to USB device instance + \param[in] ep_num: endpoint number + \param[out] none + \retval USB device operation status +*/ +static uint8_t audio_data_out (usb_dev *udev, uint8_t ep_num) +{ +#ifdef USE_USB_AUDIO_SPEAKER + usbd_audio_handler *audio = (usbd_audio_handler *)udev->dev.class_data[USBD_AUDIO_INTERFACE]; + + /* increment the Buffer pointer or roll it back when all buffers are full */ + if (audio->isoc_out_wrptr >= (audio->isoc_out_buff + (SPEAKER_OUT_PACKET * OUT_PACKET_NUM))) { + /* all buffers are full: roll back */ + audio->isoc_out_wrptr = audio->isoc_out_buff; + } else { + /* increment the buffer pointer */ + audio->isoc_out_wrptr += SPEAKER_OUT_PACKET; + } + + /* Toggle the frame index */ + udev->dev.transc_out[ep_num].frame_num = + (udev->dev.transc_out[ep_num].frame_num)? 0U:1U; + + /* prepare out endpoint to receive next audio packet */ + usbd_ep_recev (udev, AUDIO_OUT_EP, (uint8_t*)(audio->isoc_out_wrptr), SPEAKER_OUT_PACKET); + + /* trigger the start of streaming only when half buffer is full */ + if ((0U == audio->play_flag) && (audio->isoc_out_wrptr >= (audio->isoc_out_buff + ((SPEAKER_OUT_PACKET * OUT_PACKET_NUM) / 2U)))) { + /* enable start of streaming */ + audio->play_flag = 1U; + } +#endif + + return USBD_OK; +} + +/*! + \brief handles the SOF event (data buffer update and synchronization) + \param[in] udev: pointer to USB device instance + \param[out] none + \retval USB device operation status +*/ +static uint8_t usbd_audio_sof (usb_dev *udev) +{ +#ifdef USE_USB_AUDIO_SPEAKER + usbd_audio_handler *audio = (usbd_audio_handler *)udev->dev.class_data[USBD_AUDIO_INTERFACE]; + + /* check if there are available data in stream buffer. + in this function, a single variable (play_flag) is used to avoid software delays. + the play operation must be executed as soon as possible after the SOF detection. */ + if (audio->play_flag) { + /* start playing received packet */ + audio_out_fops.audio_cmd((uint8_t*)(audio->isoc_out_rdptr), /* samples buffer pointer */ + SPEAKER_OUT_PACKET, /* number of samples in Bytes */ + AUDIO_CMD_PLAY); /* command to be processed */ + + /* increment the Buffer pointer or roll it back when all buffers all full */ + if (audio->isoc_out_rdptr >= (audio->isoc_out_buff + (SPEAKER_OUT_PACKET * OUT_PACKET_NUM))) { + /* roll back to the start of buffer */ + audio->isoc_out_rdptr = audio->isoc_out_buff; + } else { + /* increment to the next sub-buffer */ + audio->isoc_out_rdptr += SPEAKER_OUT_PACKET; + } + + /* if all available buffers have been consumed, stop playing */ + if (audio->isoc_out_rdptr == audio->isoc_out_wrptr) { + /* Pause the audio stream */ + audio_out_fops.audio_cmd((uint8_t*)(audio->isoc_out_buff), /* samples buffer pointer */ + SPEAKER_OUT_PACKET, /* number of samples in Bytes */ + AUDIO_CMD_PAUSE); /* command to be processed */ + + /* stop entering play loop */ + audio->play_flag = 0U; + + /* reset buffer pointers */ + audio->isoc_out_rdptr = audio->isoc_out_buff; + audio->isoc_out_wrptr = audio->isoc_out_buff; + } + } +#endif + + return USBD_OK; +} diff --git a/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/device/class/audio/Source/audio_out_itf.c b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/device/class/audio/Source/audio_out_itf.c new file mode 100644 index 0000000000..cff230f7c9 --- /dev/null +++ b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/device/class/audio/Source/audio_out_itf.c @@ -0,0 +1,228 @@ +/*! + \file audio_out_itf.c + \brief audio OUT (playback) interface functions + + \version 2020-07-28, V3.0.0, firmware for GD32F20x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "audio_core.h" +#include "audio_out_itf.h" + +static uint8_t init (uint32_t audiofreq, uint32_t volume, uint32_t options); +static uint8_t deinit (uint32_t options); +static uint8_t audio_cmd (uint8_t* pbuf, uint32_t size, uint8_t cmd); +static uint8_t volume_ctl (uint8_t vol); +static uint8_t mute_ctl (uint8_t cmd); +static uint8_t periodic_tc (uint8_t cmd); +static uint8_t get_state (void); + +audio_fops_struct audio_out_fops = +{ + init, + deinit, + audio_cmd, + volume_ctl, + mute_ctl, + periodic_tc, + get_state +}; + +static uint8_t audio_state = AUDIO_STATE_INACTIVE; + +/*! + \brief initialize and configures all required resources for audio play function + \param[in] audio_freq: statrt_up audio frequency + \param[in] volume: start_up volume to be set + \param[in] options: specific options passed to low layer function + \param[out] none + \retval AUDIO_OK if all operations succeed, AUDIO_FAIL else +*/ +static uint8_t init (uint32_t audio_freq, uint32_t volume, uint32_t options) +{ + static uint32_t initialized = 0U; + + /* check if the low layer has already been initialized */ + if (0U == initialized) { + /* call low layer function */ + if (0U != eval_audio_init(OUTPUT_DEVICE_AUTO, (uint8_t)volume, audio_freq)) { + audio_state = AUDIO_STATE_ERROR; + + return AUDIO_FAIL; + } + + /* set the initialization flag to prevent reinitializing the interface again */ + initialized = 1U; + } + + /* update the audio state machine */ + audio_state = AUDIO_STATE_ACTIVE; + + return AUDIO_OK; +} + +/*! + \brief free all resources used by low layer and stops audio-play function + \param[in] options: specific options passed to low layer function + \param[out] none + \retval AUDIO_OK if all operations succeed, AUDIO_FAIL else +*/ +static uint8_t deinit (uint32_t options) +{ + /* update the audio state machine */ + audio_state = AUDIO_STATE_INACTIVE; + + return AUDIO_OK; +} + +/*! + \brief play, stop, pause or resume current file + \param[in] pbuf: address from which file should be played + \param[in] size: size of the current buffer/file + \param[in] cmd: command to be executed, can be: + \arg AUDIO_CMD_PLAY + \arg AUDIO_CMD_PAUSE + \arg AUDIO_CMD_RESUME + \arg AUDIO_CMD_STOP + \param[out] none + \retval AUDIO_OK if all operations succeed, AUDIO_FAIL else +*/ +static uint8_t audio_cmd (uint8_t* pbuf, uint32_t size, uint8_t cmd) +{ + /* check the current state */ + if ((AUDIO_STATE_INACTIVE == audio_state) || (AUDIO_STATE_ERROR == audio_state)) { + audio_state = AUDIO_STATE_ERROR; + + return AUDIO_FAIL; + } + + switch (cmd) { + /* process the play command */ + case AUDIO_CMD_PLAY: + /* if current state is active or stopped */ + if ((AUDIO_STATE_ACTIVE == audio_state) || \ + (AUDIO_STATE_STOPPED == audio_state) || \ + (AUDIO_STATE_PLAYING == audio_state)) { + audio_mal_play((uint32_t)pbuf, size); + audio_state = AUDIO_STATE_PLAYING; + + return AUDIO_OK; + } else if (AUDIO_STATE_PAUSED == audio_state) { + if (eval_audio_pause_resume(AUDIO_RESUME, (uint32_t)pbuf, (size / 2U))) { + audio_state = AUDIO_STATE_ERROR; + + return AUDIO_FAIL; + } else { + audio_state = AUDIO_STATE_PLAYING; + + return AUDIO_OK; + } + } else { + return AUDIO_FAIL; + } + + /* process the stop command */ + case AUDIO_CMD_STOP: + if (AUDIO_STATE_PLAYING != audio_state) { + /* unsupported command */ + return AUDIO_FAIL; + } else if (eval_audio_stop(CODEC_PDWN_SW)) { + audio_state = AUDIO_STATE_ERROR; + + return AUDIO_FAIL; + } else { + audio_state = AUDIO_STATE_STOPPED; + + return AUDIO_OK; + } + + /* process the pause command */ + case AUDIO_CMD_PAUSE: + if (AUDIO_STATE_PLAYING != audio_state) { + /* unsupported command */ + return AUDIO_FAIL; + } else if (eval_audio_pause_resume(AUDIO_PAUSE, (uint32_t)pbuf, (size / 2U))) { + audio_state = AUDIO_STATE_ERROR; + + return AUDIO_FAIL; + } else { + audio_state = AUDIO_STATE_PAUSED; + + return AUDIO_OK; + } + + /* unsupported command */ + default: + return AUDIO_FAIL; + } +} + +/*! + \brief set the volume level + \param[in] vol: volume level to be set in % (from 0% to 100%) + \param[out] none + \retval AUDIO_OK if all operations succeed, AUDIO_FAIL else +*/ +static uint8_t volume_ctl (uint8_t vol) +{ + return AUDIO_OK; +} + +/*! + \brief mute or unmute the audio current output + \param[in] cmd: can be 0 to unmute, or 1 to mute + \param[out] none + \retval AUDIO_OK if all operations succeed, AUDIO_FAIL else +*/ +static uint8_t mute_ctl (uint8_t cmd) +{ + return AUDIO_OK; +} + +/*! + \brief periodic transfer control + \param[in] cmd: command + \param[out] none + \retval AUDIO_OK if all operations succeed, AUDIO_FAIL else +*/ +static uint8_t periodic_tc (uint8_t cmd) +{ + return AUDIO_OK; +} + +/*! + \brief return the current state of the audio machine + \param[in] none + \param[out] none + \retval AUDIO_OK if all operations succeed, AUDIO_FAIL else +*/ +static uint8_t get_state (void) +{ + return audio_state; +} diff --git a/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/device/class/cdc/Include/cdc_acm_core.h b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/device/class/cdc/Include/cdc_acm_core.h new file mode 100644 index 0000000000..e135a566f6 --- /dev/null +++ b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/device/class/cdc/Include/cdc_acm_core.h @@ -0,0 +1,66 @@ +/*! + \file cdc_acm_core.h + \brief the header file of CDC ACM driver + + \version 2020-07-28, V3.0.0, firmware for GD32F20x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef __CDC_ACM_CORE_H +#define __CDC_ACM_CORE_H + +#include "usbd_enum.h" +#include "usb_cdc.h" + +#define USB_CDC_RX_LEN 64 + +typedef struct { + uint8_t packet_sent; + uint8_t packet_receive; + + uint8_t data[USB_CDC_RX_LEN]; + uint8_t cmd[USB_CDC_CMD_PACKET_SIZE]; + + uint32_t receive_length; + + acm_line line_coding; +} usb_cdc_handler; + +extern usb_desc cdc_desc; +extern usb_class_core cdc_class; + +/* function declarations */ +/* check CDC ACM is ready for data transfer */ +uint8_t cdc_acm_check_ready(usb_dev *udev); +/* send CDC ACM data */ +void cdc_acm_data_send(usb_dev *udev); +/* receive CDC ACM data */ +void cdc_acm_data_receive(usb_dev *udev); + +#endif /* __CDC_ACM_CORE_H */ diff --git a/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/device/class/cdc/Source/cdc_acm_core.c b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/device/class/cdc/Source/cdc_acm_core.c new file mode 100644 index 0000000000..f77bcada34 --- /dev/null +++ b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/device/class/cdc/Source/cdc_acm_core.c @@ -0,0 +1,525 @@ +/*! + \file cdc_acm_core.c + \brief CDC ACM driver + + \version 2020-07-28, V3.0.0, firmware for GD32F20x + \version 2020-12-10, V3.0.1, firmware for GD32F20x + \version 2020-12-14, V3.0.2, firmware for GD32F20x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "cdc_acm_core.h" + +#define USBD_VID 0x28E9U +#define USBD_PID 0x018AU + +/* note:it should use the C99 standard when compiling the below codes */ +/* USB standard device descriptor */ +const usb_desc_dev cdc_dev_desc = +{ + .header = + { + .bLength = USB_DEV_DESC_LEN, + .bDescriptorType = USB_DESCTYPE_DEV, + }, + .bcdUSB = 0x0200U, + .bDeviceClass = USB_CLASS_CDC, + .bDeviceSubClass = 0x00U, + .bDeviceProtocol = 0x00U, + .bMaxPacketSize0 = USB_FS_EP0_MAX_LEN, + .idVendor = USBD_VID, + .idProduct = USBD_PID, + .bcdDevice = 0x0100U, + .iManufacturer = STR_IDX_MFC, + .iProduct = STR_IDX_PRODUCT, + .iSerialNumber = STR_IDX_SERIAL, + .bNumberConfigurations = USBD_CFG_MAX_NUM, +}; + +/* USB device configuration descriptor */ +const usb_cdc_desc_config_set cdc_config_desc = +{ + .config = + { + .header = + { + .bLength = sizeof(usb_desc_config), + .bDescriptorType = USB_DESCTYPE_CONFIG, + }, + .wTotalLength = USB_CDC_ACM_CONFIG_DESC_SIZE, + .bNumInterfaces = 0x02U, + .bConfigurationValue = 0x01U, + .iConfiguration = 0x00U, + .bmAttributes = 0x80U, + .bMaxPower = 0x32U + }, + + .cmd_itf = + { + .header = + { + .bLength = sizeof(usb_desc_itf), + .bDescriptorType = USB_DESCTYPE_ITF + }, + .bInterfaceNumber = 0x00U, + .bAlternateSetting = 0x00U, + .bNumEndpoints = 0x01U, + .bInterfaceClass = USB_CLASS_CDC, + .bInterfaceSubClass = USB_CDC_SUBCLASS_ACM, + .bInterfaceProtocol = USB_CDC_PROTOCOL_AT, + .iInterface = 0x00U + }, + + .cdc_header = + { + .header = + { + .bLength = sizeof(usb_desc_header_func), + .bDescriptorType = USB_DESCTYPE_CS_INTERFACE + }, + .bDescriptorSubtype = 0x00U, + .bcdCDC = 0x0110U + }, + + .cdc_call_managment = + { + .header = + { + .bLength = sizeof(usb_desc_call_managment_func), + .bDescriptorType = USB_DESCTYPE_CS_INTERFACE + }, + .bDescriptorSubtype = 0x01U, + .bmCapabilities = 0x00U, + .bDataInterface = 0x01U + }, + + .cdc_acm = + { + .header = + { + .bLength = sizeof(usb_desc_acm_func), + .bDescriptorType = USB_DESCTYPE_CS_INTERFACE + }, + .bDescriptorSubtype = 0x02U, + .bmCapabilities = 0x02U, + }, + + .cdc_union = + { + .header = + { + .bLength = sizeof(usb_desc_union_func), + .bDescriptorType = USB_DESCTYPE_CS_INTERFACE + }, + .bDescriptorSubtype = 0x06U, + .bMasterInterface = 0x00U, + .bSlaveInterface0 = 0x01U, + }, + + .cdc_cmd_endpoint = + { + .header = + { + .bLength = sizeof(usb_desc_ep), + .bDescriptorType = USB_DESCTYPE_EP, + }, + .bEndpointAddress = CDC_CMD_EP, + .bmAttributes = USB_EP_ATTR_INT, + .wMaxPacketSize = USB_CDC_CMD_PACKET_SIZE, + .bInterval = 0x0AU + }, + + .cdc_data_interface = + { + .header = + { + .bLength = sizeof(usb_desc_itf), + .bDescriptorType = USB_DESCTYPE_ITF, + }, + .bInterfaceNumber = 0x01U, + .bAlternateSetting = 0x00U, + .bNumEndpoints = 0x02U, + .bInterfaceClass = USB_CLASS_DATA, + .bInterfaceSubClass = 0x00U, + .bInterfaceProtocol = USB_CDC_PROTOCOL_NONE, + .iInterface = 0x00U + }, + + .cdc_out_endpoint = + { + .header = + { + .bLength = sizeof(usb_desc_ep), + .bDescriptorType = USB_DESCTYPE_EP, + }, + .bEndpointAddress = CDC_DATA_OUT_EP, + .bmAttributes = USB_EP_ATTR_BULK, + .wMaxPacketSize = USB_CDC_DATA_PACKET_SIZE, + .bInterval = 0x00U + }, + + .cdc_in_endpoint = + { + .header = + { + .bLength = sizeof(usb_desc_ep), + .bDescriptorType = USB_DESCTYPE_EP + }, + .bEndpointAddress = CDC_DATA_IN_EP, + .bmAttributes = USB_EP_ATTR_BULK, + .wMaxPacketSize = USB_CDC_DATA_PACKET_SIZE, + .bInterval = 0x00U + } +}; + +/* USB language ID Descriptor */ +static const usb_desc_LANGID usbd_language_id_desc = +{ + .header = + { + .bLength = sizeof(usb_desc_LANGID), + .bDescriptorType = USB_DESCTYPE_STR, + }, + .wLANGID = ENG_LANGID +}; + +/* USB manufacture string */ +static const usb_desc_str manufacturer_string = +{ + .header = + { + .bLength = USB_STRING_LEN(10), + .bDescriptorType = USB_DESCTYPE_STR, + }, + .unicode_string = {'G', 'i', 'g', 'a', 'D', 'e', 'v', 'i', 'c', 'e'} +}; + +/* USB product string */ +static const usb_desc_str product_string = +{ + .header = + { + .bLength = USB_STRING_LEN(12), + .bDescriptorType = USB_DESCTYPE_STR, + }, + .unicode_string = {'G', 'D', '3', '2', '-', 'C', 'D', 'C', '_', 'A', 'C', 'M'} +}; + +/* USBD serial string */ +static usb_desc_str serial_string = +{ + .header = + { + .bLength = USB_STRING_LEN(12), + .bDescriptorType = USB_DESCTYPE_STR, + } +}; + +/* USB string descriptor set */ +void *const usbd_cdc_strings[] = +{ + [STR_IDX_LANGID] = (uint8_t *)&usbd_language_id_desc, + [STR_IDX_MFC] = (uint8_t *)&manufacturer_string, + [STR_IDX_PRODUCT] = (uint8_t *)&product_string, + [STR_IDX_SERIAL] = (uint8_t *)&serial_string +}; + +usb_desc cdc_desc = +{ + .dev_desc = (uint8_t *)&cdc_dev_desc, + .config_desc = (uint8_t *)&cdc_config_desc, + .strings = usbd_cdc_strings +}; + +/* local function prototypes ('static') */ +static uint8_t cdc_acm_init (usb_dev *udev, uint8_t config_index); +static uint8_t cdc_acm_deinit (usb_dev *udev, uint8_t config_index); +static uint8_t cdc_acm_req (usb_dev *udev, usb_req *req); +static uint8_t cdc_acm_ctlx_out (usb_dev *udev); +static uint8_t cdc_acm_in (usb_dev *udev, uint8_t ep_num); +static uint8_t cdc_acm_out (usb_dev *udev, uint8_t ep_num); + +/* USB CDC device class callbacks structure */ +usb_class_core cdc_class = +{ + .command = NO_CMD, + .alter_set = 0U, + + .init = cdc_acm_init, + .deinit = cdc_acm_deinit, + + .req_proc = cdc_acm_req, + + .ctlx_out = cdc_acm_ctlx_out, + .data_in = cdc_acm_in, + .data_out = cdc_acm_out +}; + +/*! + \brief check CDC ACM is ready for data transfer + \param[in] udev: pointer to USB device instance + \param[out] none + \retval 0 if CDC is ready, 5 else +*/ +uint8_t cdc_acm_check_ready(usb_dev *udev) +{ + if (udev->dev.class_data[CDC_COM_INTERFACE] != NULL) { + usb_cdc_handler *cdc = (usb_cdc_handler *)udev->dev.class_data[CDC_COM_INTERFACE]; + + if ((1U == cdc->packet_receive) && (1U == cdc->packet_sent)) { + return 0U; + } + } + + return 1U; +} + +/*! + \brief send CDC ACM data + \param[in] udev: pointer to USB device instance + \param[out] none + \retval USB device operation status +*/ +void cdc_acm_data_send (usb_dev *udev) +{ + usb_cdc_handler *cdc = (usb_cdc_handler *)udev->dev.class_data[CDC_COM_INTERFACE]; + + if (0U != cdc->receive_length) { + cdc->packet_sent = 0U; + + usbd_ep_send (udev, CDC_DATA_IN_EP, (uint8_t*)(cdc->data), cdc->receive_length); + + cdc->receive_length = 0U; + } +} + +/*! + \brief receive CDC ACM data + \param[in] udev: pointer to USB device instance + \param[out] none + \retval USB device operation status +*/ +void cdc_acm_data_receive (usb_dev *udev) +{ + usb_cdc_handler *cdc = (usb_cdc_handler *)udev->dev.class_data[CDC_COM_INTERFACE]; + + cdc->packet_receive = 0U; + cdc->packet_sent = 0U; + + usbd_ep_recev(udev, CDC_DATA_OUT_EP, (uint8_t*)(cdc->data), USB_CDC_DATA_PACKET_SIZE); +} + +/*! + \brief initialize the CDC ACM device + \param[in] udev: pointer to USB device instance + \param[in] config_index: configuration index + \param[out] none + \retval USB device operation status +*/ +static uint8_t cdc_acm_init (usb_dev *udev, uint8_t config_index) +{ + static usb_cdc_handler cdc_handler; + + /* initialize the data Tx endpoint */ + usbd_ep_setup (udev, &(cdc_config_desc.cdc_in_endpoint)); + + /* initialize the data Rx endpoint */ + usbd_ep_setup (udev, &(cdc_config_desc.cdc_out_endpoint)); + + /* initialize the command Tx endpoint */ + usbd_ep_setup (udev, &(cdc_config_desc.cdc_cmd_endpoint)); + + /* initialize CDC handler structure */ + cdc_handler.packet_receive = 1U; + cdc_handler.packet_sent = 1U; + cdc_handler.receive_length = 0U; + + cdc_handler.line_coding = (acm_line){ + .dwDTERate = 115200, + .bCharFormat = 0, + .bParityType = 0, + .bDataBits = 0x08 + }; + + udev->dev.class_data[CDC_COM_INTERFACE] = (void *)&cdc_handler; + + return USBD_OK; +} + +/*! + \brief deinitialize the CDC ACM device + \param[in] udev: pointer to USB device instance + \param[in] config_index: configuration index + \param[out] none + \retval USB device operation status +*/ +static uint8_t cdc_acm_deinit (usb_dev *udev, uint8_t config_index) +{ + /* deinitialize the data Tx/Rx endpoint */ + usbd_ep_clear (udev, CDC_DATA_IN_EP); + usbd_ep_clear (udev, CDC_DATA_OUT_EP); + + /* deinitialize the command Tx endpoint */ + usbd_ep_clear (udev, CDC_CMD_EP); + + return USBD_OK; +} + +/*! + \brief handle the CDC ACM class-specific requests + \param[in] udev: pointer to USB device instance + \param[in] req: device class-specific request + \param[out] none + \retval USB device operation status +*/ +static uint8_t cdc_acm_req (usb_dev *udev, usb_req *req) +{ + usb_cdc_handler *cdc = (usb_cdc_handler *)udev->dev.class_data[CDC_COM_INTERFACE]; + + usb_transc *transc = NULL; + + switch (req->bRequest) { + case SEND_ENCAPSULATED_COMMAND: + /* no operation for this driver */ + break; + + case GET_ENCAPSULATED_RESPONSE: + /* no operation for this driver */ + break; + + case SET_COMM_FEATURE: + /* no operation for this driver */ + break; + + case GET_COMM_FEATURE: + /* no operation for this driver */ + break; + + case CLEAR_COMM_FEATURE: + /* no operation for this driver */ + break; + + case SET_LINE_CODING: + /* set the value of the current command to be processed */ + udev->dev.class_core->alter_set = req->bRequest; + + /* enable EP0 prepare to receive command data packet */ + transc = &udev->dev.transc_in[0]; + transc->remain_len = req->wLength; + transc->xfer_buf = cdc->cmd; + break; + + case GET_LINE_CODING: + cdc->cmd[0] = (uint8_t)(cdc->line_coding.dwDTERate); + cdc->cmd[1] = (uint8_t)(cdc->line_coding.dwDTERate >> 8); + cdc->cmd[2] = (uint8_t)(cdc->line_coding.dwDTERate >> 16); + cdc->cmd[3] = (uint8_t)(cdc->line_coding.dwDTERate >> 24); + cdc->cmd[4] = cdc->line_coding.bCharFormat; + cdc->cmd[5] = cdc->line_coding.bParityType; + cdc->cmd[6] = cdc->line_coding.bDataBits; + + transc = &udev->dev.transc_out[0]; + transc->xfer_buf = cdc->cmd; + transc->remain_len = 7U; + break; + + case SET_CONTROL_LINE_STATE: + /* no operation for this driver */ + break; + + case SEND_BREAK: + /* no operation for this driver */ + break; + + default: + break; + } + + return USBD_OK; +} + +/*! + \brief handle CDC ACM data + \param[in] udev: pointer to USB device instance + \param[in] ep_num: endpoint identifier + \param[out] none + \retval USB device operation status +*/ +static uint8_t cdc_acm_in (usb_dev *udev, uint8_t ep_num) +{ + usb_transc *transc = &udev->dev.transc_in[EP_ID(ep_num)]; + + usb_cdc_handler *cdc = (usb_cdc_handler *)udev->dev.class_data[CDC_COM_INTERFACE]; + + if ((0U == transc->xfer_len % transc->max_len) && (0U != transc->xfer_len)) { + usbd_ep_send (udev, ep_num, NULL, 0U); + } else { + cdc->packet_sent = 1U; + } + + return USBD_OK; +} + +static uint8_t cdc_acm_ctlx_out (usb_dev *udev) +{ + usb_cdc_handler *cdc = (usb_cdc_handler *)udev->dev.class_data[CDC_COM_INTERFACE]; + + if (udev->dev.class_core->alter_set != NO_CMD) { + /* process the command data */ + cdc->line_coding.dwDTERate = (uint32_t)((uint32_t)cdc->cmd[0] | + ((uint32_t)cdc->cmd[1] << 8U) | + ((uint32_t)cdc->cmd[2] << 16U) | + ((uint32_t)cdc->cmd[3] << 24U)); + + cdc->line_coding.bCharFormat = cdc->cmd[4]; + cdc->line_coding.bParityType = cdc->cmd[5]; + cdc->line_coding.bDataBits = cdc->cmd[6]; + + udev->dev.class_core->alter_set = NO_CMD; + } + + return USBD_OK; +} + +/*! + \brief handle CDC ACM data + \param[in] udev: pointer to USB device instance + \param[in] ep_num: endpoint identifier + \param[out] none + \retval USB device operation status +*/ +static uint8_t cdc_acm_out (usb_dev *udev, uint8_t ep_num) +{ + usb_cdc_handler *cdc = (usb_cdc_handler *)udev->dev.class_data[CDC_COM_INTERFACE]; + + cdc->packet_receive = 1U; + cdc->receive_length = ((usb_core_driver *)udev)->dev.transc_out[ep_num].xfer_count; + + return USBD_OK; +} diff --git a/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/device/class/dfu/Include/dfu_core.h b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/device/class/dfu/Include/dfu_core.h new file mode 100644 index 0000000000..1dfd377581 --- /dev/null +++ b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/device/class/dfu/Include/dfu_core.h @@ -0,0 +1,176 @@ +/*! + \file dfu_core.h + \brief the header file of USB DFU device class core functions + + \version 2020-07-28, V3.0.0, firmware for GD32F20x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef __DFU_CORE_H +#define __DFU_CORE_H + +#include "usbd_enum.h" + +/* DFU class code */ +#define USB_DFU_CLASS 0xFEU + +/* DFU subclass code */ +#define USB_DFU_SUBCLASS_UPGRADE 0x01U + +/* DFU protocol code */ +#define USB_DFU_PROTOCL_RUNTIME 0x01U +#define USB_DFU_PROTOCL_DFU 0x02U + +/* manifestation state */ +#define MANIFEST_COMPLETE 0x00U +#define MANIFEST_IN_PROGRESS 0x01U + +/* DFU attributes code */ +#define USB_DFU_CAN_DOWNLOAD 0x01U +#define USB_DFU_CAN_UPLOAD 0x02U +#define USB_DFU_MANIFEST_TOLERANT 0x04U +#define USB_DFU_WILL_DETACH 0x08U + +/* special commands with download request */ +#define GET_COMMANDS 0x00U +#define SET_ADDRESS_POINTER 0x21U +#define ERASE 0x41U + +/* memory operation command */ +#define CMD_ERASE 0U +#define CMD_WRITE 1U + +#define _BYTE1(x) (uint8_t)((x) & 0xFFU) /*!< addressing cycle 1st byte */ +#define _BYTE2(x) (uint8_t)(((x) & 0xFF00U) >> 8U) /*!< addressing cycle 2nd byte */ +#define _BYTE3(x) (uint8_t)(((x) & 0xFF0000U) >> 16U) /*!< addressing cycle 3rd byte */ + +#define FLASH_ERASE_TIMEOUT 60U +#define FLASH_WRITE_TIMEOUT 80U + +/* bit detach capable = bit 3 in bmAttributes field */ +#define DFU_DETACH_MASK (uint8_t)(0x10U) + +#define USB_SERIAL_STR_LEN 0x06U + +#define USB_DFU_CONFIG_DESC_SIZE 27U + +#define DFU_DESC_TYPE 0x21U + +/* DFU device state defines */ +typedef enum { + STATE_APP_IDLE = 0x00U, + 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 +} dfu_state; + +/* DFU device status defines */ +typedef enum { + STATUS_OK = 0x00U, + STATUS_ERR_TARGET, + STATUS_ERR_FILE, + STATUS_ERR_WRITE, + STATUS_ERR_ERASE, + STATUS_ERR_CHECK_ERASED, + STATUS_ERR_PROG, + STATUS_ERR_VERIFY, + STATUS_ERR_ADDRESS, + STATUS_ERR_NOTDONE, + STATUS_ERR_FIRMWARE, + STATUS_ERR_VENDOR, + STATUS_ERR_USBR, + STATUS_ERR_POR, + STATUS_ERR_UNKNOWN, + STATUS_ERR_STALLEDPKT +} dfu_status; + +/* DFU class-specific requests */ +typedef enum { + DFU_DETACH = 0U, + DFU_DNLOAD, + DFU_UPLOAD, + DFU_GETSTATUS, + DFU_CLRSTATUS, + DFU_GETSTATE, + DFU_ABORT, + DFU_REQ_MAX +} dfu_requests; + +#pragma pack(1) + +/* USB DFU function descriptor structure */ +typedef struct +{ + usb_desc_header header; /*!< descriptor header, including type and size */ + uint8_t bmAttributes; /*!< DFU attributes */ + uint16_t wDetachTimeOut; /*!< time, in milliseconds, that the device will wait after receipt of the DFU_DETACH request. If */ + uint16_t wTransferSize; /*!< maximum number of bytes that the device can accept per control-write transaction */ + uint16_t bcdDFUVersion; /*!< numeric expression identifying the version of the DFU Specification release. */ +} usb_desc_dfu_func; + +#pragma pack() + +/* USB configuration descriptor structure */ +typedef struct +{ + usb_desc_config config; + usb_desc_itf dfu_itf; + usb_desc_dfu_func dfu_func; +} usb_dfu_desc_config_set; + +typedef struct +{ + uint8_t bStatus; + uint8_t bwPollTimeout0; + uint8_t bwPollTimeout1; + uint8_t bwPollTimeout2; + uint8_t bState; + uint8_t iString; + + uint8_t manifest_state; + uint32_t data_len; + uint16_t block_num; + uint32_t base_addr; + + uint8_t buf[TRANSFER_SIZE]; +} usbd_dfu_handler; + +typedef void (*app_func) (void); + +extern usb_desc dfu_desc; +extern usb_class_core dfu_class; + +#endif /* DFU_CORE_H */ diff --git a/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/device/class/dfu/Include/dfu_mal.h b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/device/class/dfu/Include/dfu_mal.h new file mode 100644 index 0000000000..466bd36682 --- /dev/null +++ b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/device/class/dfu/Include/dfu_mal.h @@ -0,0 +1,84 @@ +/*! + \file dfu_mal.h + \brief USB DFU device media access layer header file + + \version 2020-07-28, V3.0.0, firmware for GD32F20x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef __DFU_MAL_H +#define __DFU_MAL_H + +#include "usbd_conf.h" + +typedef struct _dfu_mal_prop +{ + const uint8_t* pstr_desc; + + uint8_t (*mal_init) (void); + uint8_t (*mal_deinit) (void); + uint8_t (*mal_erase) (uint32_t addr); + uint8_t (*mal_write) (uint8_t *buf, uint32_t addr, uint32_t len); + uint8_t* (*mal_read) (uint8_t *buf, uint32_t addr, uint32_t len); + uint8_t (*mal_checkaddr) (uint32_t addr); + + const uint32_t erase_timeout; + const uint32_t write_timeout; +} dfu_mal_prop; + +typedef enum +{ + MAL_OK = 0, + MAL_FAIL +} MAL_Status; + +#define _1st_BYTE(x) (uint8_t)((x) & 0xFF) /*!< addressing cycle 1st byte */ +#define _2nd_BYTE(x) (uint8_t)(((x) & 0xFF00) >> 8) /*!< addressing cycle 2nd byte */ +#define _3rd_BYTE(x) (uint8_t)(((x) & 0xFF0000) >> 16) /*!< addressing cycle 3rd byte */ + +#define SET_POLLING_TIMEOUT(x) buffer[0] = _1st_BYTE(x);\ + buffer[1] = _2nd_BYTE(x);\ + buffer[2] = _3rd_BYTE(x); + +/* function declarations */ +/* initialize the memory media on the GD32 */ +uint8_t dfu_mal_init(void); +/* deinitialize the memory media on the GD32 */ +uint8_t dfu_mal_deinit(void); +/* erase a memory sector */ +uint8_t dfu_mal_erase(uint32_t addr); +/* write data to sectors of memory */ +uint8_t dfu_mal_write(uint8_t *buf, uint32_t addr, uint32_t len); +/* read data from sectors of memory */ +uint8_t* dfu_mal_read(uint8_t *buf, uint32_t addr, uint32_t len); +/* get the status of a given memory and store in buffer */ +uint8_t dfu_mal_getstatus(uint32_t addr, uint8_t cmd, uint8_t *buffer); + +#endif /* __DFU_MAL_H */ + diff --git a/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/device/class/dfu/Source/dfu_core.c b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/device/class/dfu/Source/dfu_core.c new file mode 100644 index 0000000000..daeeb332cb --- /dev/null +++ b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/device/class/dfu/Source/dfu_core.c @@ -0,0 +1,653 @@ +/*! + \file dfu_core.c + \brief USB DFU device class core functions + + \version 2020-07-28, V3.0.0, firmware for GD32F20x + \version 2020-12-10, V3.0.1, firmware for GD32F20x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "dfu_core.h" +#include "drv_usb_hw.h" +#include "dfu_mal.h" +#include "flash_if.h" +#include + +#define USBD_VID 0x28E9U +#define USBD_PID 0x0189U + +/* local function prototypes ('static') */ +static uint8_t dfu_init(usb_dev *udev, uint8_t config_index); +static uint8_t dfu_deinit(usb_dev *udev, uint8_t config_index); +static uint8_t dfu_req_handler(usb_dev *udev, usb_req *req); +static uint8_t dfu_ctlx_in(usb_dev *udev); + +static void dfu_detach(usb_dev *udev, usb_req *req); +static void dfu_dnload(usb_dev *udev, usb_req *req); +static void dfu_upload(usb_dev *udev, usb_req *req); +static void dfu_getstatus(usb_dev *udev, usb_req *req); +static void dfu_clrstatus(usb_dev *udev, usb_req *req); +static void dfu_getstate(usb_dev *udev, usb_req *req); +static void dfu_abort(usb_dev *udev, usb_req *req); +static void dfu_mode_leave(usb_dev *udev); +static uint8_t dfu_getstatus_complete (usb_dev *udev); + +static void (*dfu_request_process[])(usb_dev *udev, usb_req *req) = +{ + [DFU_DETACH] = dfu_detach, + [DFU_DNLOAD] = dfu_dnload, + [DFU_UPLOAD] = dfu_upload, + [DFU_GETSTATUS] = dfu_getstatus, + [DFU_CLRSTATUS] = dfu_clrstatus, + [DFU_GETSTATE] = dfu_getstate, + [DFU_ABORT] = dfu_abort +}; + +/* note:it should use the c99 standard when compiling the below codes */ +/* USB standard device descriptor */ +const usb_desc_dev dfu_dev_desc = +{ + .header = + { + .bLength = USB_DEV_DESC_LEN, + .bDescriptorType = USB_DESCTYPE_DEV + }, + .bcdUSB = 0x0200U, + .bDeviceClass = 0x00U, + .bDeviceSubClass = 0x00U, + .bDeviceProtocol = 0x00U, + .bMaxPacketSize0 = USB_FS_EP0_MAX_LEN, + .idVendor = USBD_VID, + .idProduct = USBD_PID, + .bcdDevice = 0x0100U, + .iManufacturer = STR_IDX_MFC, + .iProduct = STR_IDX_PRODUCT, + .iSerialNumber = STR_IDX_SERIAL, + .bNumberConfigurations = USBD_CFG_MAX_NUM +}; + +/* USB device configuration descriptor */ +const usb_dfu_desc_config_set dfu_config_desc = +{ + .config = + { + .header = + { + .bLength = sizeof(usb_desc_config), + .bDescriptorType = USB_DESCTYPE_CONFIG + }, + .wTotalLength = USB_DFU_CONFIG_DESC_SIZE, + .bNumInterfaces = 0x01U, + .bConfigurationValue = 0x01U, + .iConfiguration = 0x00U, + .bmAttributes = 0x80U, + .bMaxPower = 0x32U + }, + + .dfu_itf = + { + .header = + { + .bLength = sizeof(usb_desc_itf), + .bDescriptorType = USB_DESCTYPE_ITF + }, + .bInterfaceNumber = 0x00U, + .bAlternateSetting = 0x00U, + .bNumEndpoints = 0x00U, + .bInterfaceClass = USB_DFU_CLASS, + .bInterfaceSubClass = USB_DFU_SUBCLASS_UPGRADE, + .bInterfaceProtocol = USB_DFU_PROTOCL_DFU, + .iInterface = 0x05U + }, + + .dfu_func = + { + .header = + { + .bLength = sizeof(usb_desc_dfu_func), + .bDescriptorType = DFU_DESC_TYPE + }, + .bmAttributes = USB_DFU_CAN_DOWNLOAD | USB_DFU_CAN_UPLOAD | USB_DFU_WILL_DETACH, + .wDetachTimeOut = 0x00FFU, + .wTransferSize = TRANSFER_SIZE, + .bcdDFUVersion = 0x011AU, + }, +}; + +/* USB language ID Descriptor */ +static const usb_desc_LANGID usbd_language_id_desc = +{ + .header = { + .bLength = sizeof(usb_desc_LANGID), + .bDescriptorType = USB_DESCTYPE_STR + }, + .wLANGID = ENG_LANGID +}; + +/* USB manufacture string */ +static const usb_desc_str manufacturer_string = +{ + .header = + { + .bLength = USB_STRING_LEN(10U), + .bDescriptorType = USB_DESCTYPE_STR, + }, + .unicode_string = {'G', 'i', 'g', 'a', 'D', 'e', 'v', 'i', 'c', 'e'} +}; + +/* USB product string */ +static const usb_desc_str product_string = +{ + .header = + { + .bLength = USB_STRING_LEN(12U), + .bDescriptorType = USB_DESCTYPE_STR, + }, + .unicode_string = {'G', 'D', '3', '2', '-', 'U', 'S', 'B', '_', 'D', 'F', 'U'} +}; + +/* USBD serial string */ +static usb_desc_str serial_string = +{ + .header = + { + .bLength = USB_STRING_LEN(2U), + .bDescriptorType = USB_DESCTYPE_STR, + } +}; + +/* USB configure string */ +static const usb_desc_str config_string = +{ + .header = + { + .bLength = USB_STRING_LEN(15U), + .bDescriptorType = USB_DESCTYPE_STR, + }, + .unicode_string = {'G', 'D', '3', '2', ' ', 'U', 'S', 'B', ' ', 'C', 'O', 'N', 'F', 'I', 'G'} +}; + +static const usb_desc_str interface_string = +{ + .header = + { + .bLength = USB_STRING_LEN(44U), + .bDescriptorType = USB_DESCTYPE_STR, + }, + .unicode_string = {'@', 'I', 'n', 't', 'e', 'r', 'n', 'a', 'l', 'F', 'l', 'a', 's', 'h', ' ', '/', '0', 'x', '0', '8', '0', '0', + '0', '0', '0', '0', '/', '1', '6', '*', '0', '0', '1', 'K', 'a', ',', '4', '8', '*', '0', '0', '1', 'K', 'g'} +}; + +void *const usbd_dfu_strings[] = +{ + [STR_IDX_LANGID] = (uint8_t *)&usbd_language_id_desc, + [STR_IDX_MFC] = (uint8_t *)&manufacturer_string, + [STR_IDX_PRODUCT] = (uint8_t *)&product_string, + [STR_IDX_SERIAL] = (uint8_t *)&serial_string, + [STR_IDX_CONFIG] = (uint8_t *)&config_string, + [STR_IDX_ITF] = (uint8_t *)&interface_string +}; + +usb_desc dfu_desc = { + .dev_desc = (uint8_t *)&dfu_dev_desc, + .config_desc = (uint8_t *)&dfu_config_desc, + .strings = usbd_dfu_strings +}; + +usb_class_core dfu_class = { + .init = dfu_init, + .deinit = dfu_deinit, + .req_proc = dfu_req_handler, + .ctlx_in = dfu_ctlx_in, +}; + +/*! + \brief initialize the DFU device + \param[in] udev: pointer to USB device instance + \param[in] config_index: configuration index + \param[out] none + \retval USB device operation status +*/ +static uint8_t dfu_init (usb_dev *udev, uint8_t config_index) +{ + static usbd_dfu_handler dfu_handler; + + /* unlock the internal flash */ + dfu_mal_init(); + + memset((void *)&dfu_handler, 0, sizeof(usbd_dfu_handler)); + + dfu_handler.base_addr = APP_LOADED_ADDR; + dfu_handler.manifest_state = MANIFEST_COMPLETE; + dfu_handler.bState = STATE_DFU_IDLE; + dfu_handler.bStatus = STATUS_OK; + + udev->dev.class_data[USBD_DFU_INTERFACE] = (void *)&dfu_handler; + + return USBD_OK; +} + +/*! + \brief deinitialize the DFU device + \param[in] udev: pointer to USB device instance + \param[in] config_index: configuration index + \param[out] none + \retval USB device operation status +*/ +static uint8_t dfu_deinit (usb_dev *udev, uint8_t config_index) +{ + usbd_dfu_handler *dfu = (usbd_dfu_handler *)udev->dev.class_data[USBD_DFU_INTERFACE]; + + /* restore device default state */ + memset(udev->dev.class_data[USBD_DFU_INTERFACE], 0, sizeof(usbd_dfu_handler)); + + dfu->bState = STATE_DFU_IDLE; + dfu->bStatus = STATUS_OK; + + /* lock the internal flash */ + dfu_mal_deinit(); + + return USBD_OK; +} + +/*! + \brief handle the DFU class-specific requests + \param[in] udev: pointer to USB device instance + \param[in] req: device class-specific request + \param[out] none + \retval USB device operation status +*/ +static uint8_t dfu_req_handler (usb_dev *udev, usb_req *req) +{ + if (req->bRequest < DFU_REQ_MAX) { + dfu_request_process[req->bRequest](udev, req); + } else { + return USBD_FAIL; + } + + return USBD_OK; +} + +/*! + \brief handle data Stage + \param[in] udev: pointer to USB device instance + \param[in] ep_num: the endpoint number + \param[out] none + \retval USB device operation status +*/ +static uint8_t dfu_ctlx_in (usb_dev *udev) +{ + dfu_getstatus_complete(udev); + + return USBD_OK; +} + +/*! + \brief leave DFU mode and reset device to jump to user loaded code + \param[in] udev: pointer to USB device instance + \param[out] none + \retval none +*/ +static void dfu_mode_leave (usb_dev *udev) +{ + usbd_dfu_handler *dfu = (usbd_dfu_handler *)udev->dev.class_data[USBD_DFU_INTERFACE]; + + dfu->manifest_state = MANIFEST_COMPLETE; + + if (dfu_config_desc.dfu_func.bmAttributes & 0x04U) { + dfu->bState = STATE_DFU_MANIFEST_SYNC; + } else { + dfu->bState = STATE_DFU_MANIFEST_WAIT_RESET; + + /* lock the internal flash */ + dfu_mal_deinit(); + + /* generate system reset to allow jumping to the user code */ + NVIC_SystemReset(); + } +} + +/*! + \brief handle data IN stage in control endpoint 0 + \param[in] udev: pointer to usb device instance + \param[out] none + \retval usb device operation status + */ +static uint8_t dfu_getstatus_complete (usb_dev *udev) +{ + uint32_t addr; + + usbd_dfu_handler *dfu = (usbd_dfu_handler *)udev->dev.class_data[USBD_DFU_INTERFACE]; + + if (STATE_DFU_DNBUSY == dfu->bState) { + /* decode the special command */ + if (0U == dfu->block_num) { + if (1U == dfu->data_len){ + if (GET_COMMANDS == dfu->buf[0]) { + /* no operation */ + } + } else if (5U == dfu->data_len) { + if (SET_ADDRESS_POINTER == dfu->buf[0]) { + /* set flash operation address */ + dfu->base_addr = *(uint32_t *)(dfu->buf + 1U); + } else if (ERASE == dfu->buf[0]) { + dfu->base_addr = *(uint32_t *)(dfu->buf + 1U); + + dfu_mal_erase(dfu->base_addr); + } else { + /* no operation */ + } + } else { + /* no operation */ + } + } else if (dfu->block_num > 1U) { /* regular download command */ + /* decode the required address */ + addr = (dfu->block_num - 2U) * TRANSFER_SIZE + dfu->base_addr; + + dfu_mal_write (dfu->buf, addr, dfu->data_len); + + dfu->block_num = 0U; + } else { + /* no operation */ + } + + dfu->data_len = 0U; + + /* update the device state and poll timeout */ + dfu->bState = STATE_DFU_DNLOAD_SYNC; + + return USBD_OK; + } else if (dfu->bState == STATE_DFU_MANIFEST) { /* manifestation in progress */ + /* start leaving DFU mode */ + dfu_mode_leave(udev); + } else { + /* no operation */ + } + + return USBD_OK; +} + +/*! + \brief handle the DFU_DETACH request + \param[in] udev: pointer to usb device instance + \param[in] req: DFU class request + \param[out] none + \retval none. +*/ +static void dfu_detach(usb_dev *udev, usb_req *req) +{ + usbd_dfu_handler *dfu = (usbd_dfu_handler *)udev->dev.class_data[USBD_DFU_INTERFACE]; + + switch (dfu->bState) { + case STATE_DFU_IDLE: + case STATE_DFU_DNLOAD_SYNC: + case STATE_DFU_DNLOAD_IDLE: + case STATE_DFU_MANIFEST_SYNC: + case STATE_DFU_UPLOAD_IDLE: + dfu->bStatus = STATUS_OK; + dfu->bState = STATE_DFU_IDLE; + dfu->iString = 0U; /* iString */ + + dfu->block_num = 0U; + dfu->data_len = 0U; + break; + + default: + break; + } + + /* check the detach capability in the DFU functional descriptor */ + if (dfu_config_desc.dfu_func.wDetachTimeOut & DFU_DETACH_MASK) { + usbd_disconnect (udev); + + usbd_connect (udev); + } else { + /* wait for the period of time specified in detach request */ + usb_mdelay (4U); + } +} + +/*! + \brief handle the DFU_DNLOAD request + \param[in] udev: pointer to usb device instance + \param[in] req: DFU class request + \param[out] none + \retval none +*/ +static void dfu_dnload(usb_dev *udev, usb_req *req) +{ + usb_transc *transc = &udev->dev.transc_out[0]; + usbd_dfu_handler *dfu = (usbd_dfu_handler *)udev->dev.class_data[USBD_DFU_INTERFACE]; + + switch (dfu->bState) { + case STATE_DFU_IDLE: + case STATE_DFU_DNLOAD_IDLE: + if (req->wLength > 0U) { + /* update the global length and block number */ + dfu->block_num = req->wValue; + dfu->data_len = req->wLength; + + dfu->bState = STATE_DFU_DNLOAD_SYNC; + + transc->remain_len = dfu->data_len; + transc->xfer_buf = dfu->buf; + } else { + dfu->manifest_state = MANIFEST_IN_PROGRESS; + dfu->bState = STATE_DFU_MANIFEST_SYNC; + } + break; + + default: + break; + } +} + +/*! + \brief handles the DFU UPLOAD request. + \param[in] udev: pointer to usb device instance + \param[in] req: DFU class request + \param[out] none + \retval none +*/ +static void dfu_upload (usb_dev *udev, usb_req *req) +{ + uint8_t *phy_addr = NULL; + uint32_t addr = 0U; + usbd_dfu_handler *dfu = (usbd_dfu_handler *)udev->dev.class_data[USBD_DFU_INTERFACE]; + + usb_transc *transc = &udev->dev.transc_in[0]; + + if(req->wLength <= 0U) { + dfu->bState = STATE_DFU_IDLE; + return; + } + + switch (dfu->bState) { + case STATE_DFU_IDLE: + case STATE_DFU_UPLOAD_IDLE: + /* update the global length and block number */ + dfu->block_num = req->wValue; + dfu->data_len = req->wLength; + + /* DFU get command */ + if (0U == dfu->block_num) { + /* update the state machine */ + dfu->bState = (dfu->data_len > 3U) ? STATE_DFU_IDLE : STATE_DFU_UPLOAD_IDLE; + + /* store the values of all supported commands */ + dfu->buf[0] = GET_COMMANDS; + dfu->buf[1] = SET_ADDRESS_POINTER; + dfu->buf[2] = ERASE; + + /* send the status data over EP0 */ + transc->xfer_buf = &(dfu->buf[0]); + transc->remain_len = 3U; + } else if (dfu->block_num > 1U) { + dfu->bState = STATE_DFU_UPLOAD_IDLE; + + /* change is accelerated */ + addr = (dfu->block_num - 2U) * TRANSFER_SIZE + dfu->base_addr; + + /* return the physical address where data are stored */ + phy_addr = dfu_mal_read (dfu->buf, addr, dfu->data_len); + + /* send the status data over EP0 */ + transc->xfer_buf = phy_addr; + transc->remain_len = dfu->data_len; + } else { + dfu->bState = STATUS_ERR_STALLEDPKT; + } + break; + + default: + dfu->data_len = 0U; + dfu->block_num = 0U; + break; + } +} + +/*! + \brief handle the DFU_GETSTATUS request + \param[in] udev: pointer to usb device instance + \param[in] req: DFU class request + \param[out] none + \retval none +*/ +static void dfu_getstatus (usb_dev *udev, usb_req *req) +{ + usbd_dfu_handler *dfu = (usbd_dfu_handler *)udev->dev.class_data[USBD_DFU_INTERFACE]; + + usb_transc *transc = &udev->dev.transc_in[0]; + + switch (dfu->bState) { + case STATE_DFU_DNLOAD_SYNC: + if (0U != dfu->data_len) { + dfu->bState = STATE_DFU_DNBUSY; + + if (0U == dfu->block_num) { + if (ERASE == dfu->buf[0]) { + dfu_mal_getstatus (dfu->base_addr, CMD_ERASE, (uint8_t *)&dfu->bwPollTimeout0); + } else { + dfu_mal_getstatus (dfu->base_addr, CMD_WRITE, (uint8_t *)&dfu->bwPollTimeout0); + } + } + } else { + dfu->bState = STATE_DFU_DNLOAD_IDLE; + } + break; + + case STATE_DFU_MANIFEST_SYNC: + if (MANIFEST_IN_PROGRESS == dfu->manifest_state) { + dfu->bState = STATE_DFU_MANIFEST; + dfu->bwPollTimeout0 = 1U; + } else if ((MANIFEST_COMPLETE == dfu->manifest_state) && \ + (dfu_config_desc.dfu_func.bmAttributes & 0x04U)){ + dfu->bState = STATE_DFU_IDLE; + dfu->bwPollTimeout0 = 0U; + } else { + /* no operation */ + } + break; + + default: + break; + } + + /* send the status data of DFU interface to host over EP0 */ + transc->xfer_buf = (uint8_t *)&(dfu->bStatus); + transc->remain_len = 6U; +} + +/*! + \brief handle the DFU_CLRSTATUS request + \param udev: pointer to usb device instance + \param[out] none + \retval none +*/ +static void dfu_clrstatus (usb_dev *udev, usb_req *req) +{ + usbd_dfu_handler *dfu = (usbd_dfu_handler *)udev->dev.class_data[USBD_DFU_INTERFACE]; + + if (STATE_DFU_ERROR == dfu->bState) { + dfu->bStatus = STATUS_OK; + dfu->bState = STATE_DFU_IDLE; + } else { + /* state error */ + dfu->bStatus = STATUS_ERR_UNKNOWN; + dfu->bState = STATE_DFU_ERROR; + } + + dfu->iString = 0U; /* iString: index = 0 */ +} + +/*! + \brief handle the DFU_GETSTATE request + \param[in] udev: pointer to usb device instance + \param[out] none + \retval none +*/ +static void dfu_getstate (usb_dev *udev, usb_req *req) +{ + usbd_dfu_handler *dfu = (usbd_dfu_handler *)udev->dev.class_data[USBD_DFU_INTERFACE]; + + usb_transc *transc = &udev->dev.transc_in[0]; + + /* send the current state of the DFU interface to host */ + transc->xfer_buf = &(dfu->bState); + transc->remain_len = 1U; +} + +/*! + \brief handle the DFU_ABORT request + \param[in] udev: pointer to usb device instance + \param[out] none + \retval none +*/ +static void dfu_abort (usb_dev *udev, usb_req *req) +{ + usbd_dfu_handler *dfu = (usbd_dfu_handler *)udev->dev.class_data[USBD_DFU_INTERFACE]; + + switch (dfu->bState){ + case STATE_DFU_IDLE: + case STATE_DFU_DNLOAD_SYNC: + case STATE_DFU_DNLOAD_IDLE: + case STATE_DFU_MANIFEST_SYNC: + case STATE_DFU_UPLOAD_IDLE: + dfu->bStatus = STATUS_OK; + dfu->bState = STATE_DFU_IDLE; + dfu->iString = 0U; /* iString: index = 0 */ + + dfu->block_num = 0U; + dfu->data_len = 0U; + break; + + default: + break; + } +} diff --git a/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/device/class/dfu/Source/dfu_mal.c b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/device/class/dfu/Source/dfu_mal.c new file mode 100644 index 0000000000..ea4b155ac1 --- /dev/null +++ b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/device/class/dfu/Source/dfu_mal.c @@ -0,0 +1,233 @@ +/*! + \file dfu_mal.c + \brief USB DFU device media access layer functions + + \version 2020-07-28, V3.0.0, firmware for GD32F20x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "dfu_mal.h" +#include "flash_if.h" +#include "drv_usb_hw.h" +#include "usbd_transc.h" + +extern usb_core_driver usb_dfu_dev; + +extern struct { + uint8_t buf[TRANSFER_SIZE]; + uint16_t data_len; + uint16_t block_num; + uint32_t base_addr; +} prog; + +dfu_mal_prop* tMALTab[MAX_USED_MEMORY_MEDIA] = { + &DFU_Flash_cb +}; + +/* The list of memory interface string descriptor pointers. This list + can be updated whenever a memory has to be added or removed */ +const uint8_t* USBD_DFU_StringDesc[MAX_USED_MEMORY_MEDIA] = +{ + (const uint8_t *)FLASH_IF_STRING +}; + +static uint8_t dfu_mal_checkaddr (uint32_t addr); + +/*! + \brief initialize the memory media on the GD32 + \param[in] none + \param[out] none + \retval MAL_OK +*/ +uint8_t dfu_mal_init (void) +{ + uint32_t mem_index = 0U; + + /* initialize all supported memory medias */ + for (mem_index = 0U; mem_index < MAX_USED_MEMORY_MEDIA; mem_index++) { + /* check if the memory media exists */ + if (NULL != tMALTab[mem_index]->mal_init) { + tMALTab[mem_index]->mal_init(); + } + } + + return MAL_OK; +} + +/*! + \brief deinitialize the memory media on the GD32 + \param[in] none + \param[out] none + \retval MAL_OK +*/ +uint8_t dfu_mal_deinit (void) +{ + uint32_t mem_index = 0U; + + /* deinitialize all supported memory medias */ + for (mem_index = 0U; mem_index < MAX_USED_MEMORY_MEDIA; mem_index++) { + /* check if the memory media exists */ + if (NULL != tMALTab[mem_index]->mal_deinit) { + tMALTab[mem_index]->mal_deinit(); + } + } + + return MAL_OK; +} + +/*! + \brief erase a memory sector + \param[in] addr: memory sector address/code + \param[out] none + \retval MAL_OK +*/ +uint8_t dfu_mal_erase (uint32_t addr) +{ + uint32_t mem_index = dfu_mal_checkaddr(addr); + + /* check if the address is in protected area */ + if (IS_PROTECTED_AREA(addr)) { + return MAL_FAIL; + } + + if (mem_index < MAX_USED_MEMORY_MEDIA) { + /* check if the operation is supported */ + if (NULL != tMALTab[mem_index]->mal_erase) { + return tMALTab[mem_index]->mal_erase(addr); + } else { + return MAL_FAIL; + } + } else { + return MAL_FAIL; + } +} + +/*! + \brief write data to sectors of memory + \param[in] buf: the data buffer to be write + \param[in] addr: memory sector address/code + \param[in] len: data length + \param[out] none + \retval MAL_OK +*/ +uint8_t dfu_mal_write (uint8_t *buf, uint32_t addr, uint32_t len) +{ + uint32_t mem_index = dfu_mal_checkaddr(addr); + + /* check if the address is in protected area */ + if (IS_PROTECTED_AREA(addr)) { + return MAL_FAIL; + } + + if (mem_index < MAX_USED_MEMORY_MEDIA) { + /* check if the operation is supported */ + if (NULL != tMALTab[mem_index]->mal_write) { + return tMALTab[mem_index]->mal_write(buf, addr, len); + } else { + return MAL_FAIL; + } + } else { + return MAL_FAIL; + } +} + +/*! + \brief read data from sectors of memory + \param[in] buf: the data buffer to be write + \param[in] addr: memory sector address/code + \param[in] len: data length + \param[out] none + \retval pointer to buffer +*/ +uint8_t* dfu_mal_read (uint8_t *buf, uint32_t addr, uint32_t len) +{ + uint32_t mem_index = 0U; + + if (OB_RDPT != addr) { + mem_index = dfu_mal_checkaddr(addr); + } + + if (mem_index < MAX_USED_MEMORY_MEDIA) { + /* check if the operation is supported */ + if (NULL != tMALTab[mem_index]->mal_read) { + return tMALTab[mem_index]->mal_read(buf, addr, len); + } else { + return buf; + } + } else { + return buf; + } +} + +/*! + \brief get the status of a given memory and store in buffer + \param[in] addr: memory sector address/code + \param[in] cmd: 0 for erase and 1 for write + \param[in] buffer: pointer to the buffer where the status data will be stored + \param[out] none + \retval MAL_OK if all operations are OK, MAL_FAIL else +*/ +uint8_t dfu_mal_getstatus (uint32_t addr, uint8_t cmd, uint8_t *buffer) +{ + uint32_t mem_index = dfu_mal_checkaddr(addr); + + if (mem_index < MAX_USED_MEMORY_MEDIA) { + if (cmd & 0x01U) { + SET_POLLING_TIMEOUT(tMALTab[mem_index]->write_timeout); + } else { + SET_POLLING_TIMEOUT(tMALTab[mem_index]->erase_timeout); + } + + return MAL_OK; + } else { + return MAL_FAIL; + } +} + +/*! + \brief check the address is supported + \param[in] addr: memory sector address/code + \param[out] none + \retval index of the addressed memory +*/ +static uint8_t dfu_mal_checkaddr (uint32_t addr) +{ + uint8_t mem_index = 0U; + + /* check with all supported memories */ + for (mem_index = 0U; mem_index < MAX_USED_MEMORY_MEDIA; mem_index++) { + /* if the check address is supported, return the memory index */ + if (MAL_OK == tMALTab[mem_index]->mal_checkaddr(addr)) { + return mem_index; + } + } + + /* if there is no memory found, return MAX_USED_MEMORY_MEDIA */ + return (MAX_USED_MEMORY_MEDIA); +} diff --git a/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/device/class/hid/Include/custom_hid_core.h b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/device/class/hid/Include/custom_hid_core.h new file mode 100644 index 0000000000..826f4022ea --- /dev/null +++ b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/device/class/hid/Include/custom_hid_core.h @@ -0,0 +1,69 @@ +/*! + \file custom_hid_core.h + \brief definitions for HID core + + \version 2020-07-28, V3.0.0, firmware for GD32F20x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef __CUSTOM_HID_CORE_H +#define __CUSTOM_HID_CORE_H + +#include "usbd_enum.h" +#include "usb_hid.h" + +#define DESC_LEN_REPORT 96U +#define DESC_LEN_CONFIG 41U + +#define NO_CMD 0xFFU + +#define MAX_PERIPH_NUM 4U + +typedef struct { + uint8_t data[2]; + + uint8_t reportID; + uint8_t idlestate; + uint8_t protocol; +} custom_hid_handler; + +typedef struct { + void (*periph_config[MAX_PERIPH_NUM])(void); +} hid_fop_handler; + +extern usb_desc custom_hid_desc; +extern usb_class_core usbd_custom_hid_cb; + +/* function declarations */ +/* register HID interface operation functions */ +uint8_t custom_hid_itfop_register (usb_dev *udev, hid_fop_handler *hid_fop); +/* send custom HID report */ +uint8_t custom_hid_report_send (usb_dev *udev, uint8_t *report, uint32_t len); + +#endif /* __CUSTOM_HID_CORE_H */ diff --git a/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/device/class/hid/Include/standard_hid_core.h b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/device/class/hid/Include/standard_hid_core.h new file mode 100644 index 0000000000..d6eff10ef1 --- /dev/null +++ b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/device/class/hid/Include/standard_hid_core.h @@ -0,0 +1,68 @@ +/*! + \file standard_hid_core.h + \brief definitions for HID core + + \version 2020-07-28, V3.0.0, firmware for GD32F20x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef __STANDARD_HID_CORE_H +#define __STANDARD_HID_CORE_H + +#include "usbd_enum.h" +#include "usb_hid.h" + +#define USB_HID_CONFIG_DESC_LEN 0x22U +#define USB_HID_REPORT_DESC_LEN 0x2EU + +#define NO_CMD 0xFFU + +typedef struct { + uint32_t protocol; + uint32_t idle_state; + + uint8_t data[HID_IN_PACKET]; + __IO uint8_t prev_transfer_complete; +} standard_hid_handler; + +typedef struct { + void (*hid_itf_config) (void); + void (*hid_itf_data_process) (usb_dev *udev); +} hid_fop_handler; + +extern usb_desc hid_desc; +extern usb_class_core usbd_hid_cb; + +/* function declarations */ +/* register HID interface operation functions */ +uint8_t hid_itfop_register (usb_dev *udev, hid_fop_handler *hid_fop); +/* send keyboard report */ +uint8_t hid_report_send (usb_dev *udev, uint8_t *report, uint32_t len); + +#endif /* __STANDARD_HID_CORE_H */ diff --git a/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/device/class/hid/Source/custom_hid_core.c b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/device/class/hid/Source/custom_hid_core.c new file mode 100644 index 0000000000..42c7495795 --- /dev/null +++ b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/device/class/hid/Source/custom_hid_core.c @@ -0,0 +1,490 @@ +/*! + \file custom_hid_core.c + \brief custom HID class driver + + \version 2020-07-28, V3.0.0, firmware for GD32F20x + \version 2020-12-10, V3.0.1, firmware for GD32F20x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "custom_hid_core.h" +#include "usbd_enum.h" + +#include + +#define USBD_VID 0x28E9U +#define USBD_PID 0x028AU + +/* Note:it should use the C99 standard when compiling the below codes */ +/* USB standard device descriptor */ +const usb_desc_dev custom_hid_dev_desc = +{ + .header = + { + .bLength = USB_DEV_DESC_LEN, + .bDescriptorType = USB_DESCTYPE_DEV, + }, + .bcdUSB = 0x0200U, + .bDeviceClass = 0x00U, + .bDeviceSubClass = 0x00U, + .bDeviceProtocol = 0x00U, + .bMaxPacketSize0 = USB_FS_EP0_MAX_LEN, + .idVendor = USBD_VID, + .idProduct = USBD_PID, + .bcdDevice = 0x0100U, + .iManufacturer = STR_IDX_MFC, + .iProduct = STR_IDX_PRODUCT, + .iSerialNumber = STR_IDX_SERIAL, + .bNumberConfigurations = USBD_CFG_MAX_NUM, +}; + +/* USB device configuration descriptor */ +const usb_hid_desc_config_set custom_hid_config_desc = +{ + .config = + { + .header = + { + .bLength = sizeof(usb_desc_config), + .bDescriptorType = USB_DESCTYPE_CONFIG + }, + .wTotalLength = DESC_LEN_CONFIG, + .bNumInterfaces = 0x01U, + .bConfigurationValue = 0x01U, + .iConfiguration = 0x00U, + .bmAttributes = 0x80U, + .bMaxPower = 0x32U + }, + + .hid_itf = + { + .header = + { + .bLength = sizeof(usb_desc_itf), + .bDescriptorType = USB_DESCTYPE_ITF + }, + .bInterfaceNumber = 0x00U, + .bAlternateSetting = 0x00U, + .bNumEndpoints = 0x02U, + .bInterfaceClass = USB_HID_CLASS, + .bInterfaceSubClass = 0x00U, + .bInterfaceProtocol = 0x00U, + .iInterface = 0x00U + }, + + .hid_vendor = + { + .header = + { + .bLength = sizeof(usb_desc_hid), + .bDescriptorType = USB_DESCTYPE_HID + }, + .bcdHID = 0x0111U, + .bCountryCode = 0x00U, + .bNumDescriptors = 0x01U, + .bDescriptorType = USB_DESCTYPE_REPORT, + .wDescriptorLength = DESC_LEN_REPORT, + }, + + .hid_epin = + { + .header = + { + .bLength = sizeof(usb_desc_ep), + .bDescriptorType = USB_DESCTYPE_EP + }, + .bEndpointAddress = CUSTOMHID_IN_EP, + .bmAttributes = USB_EP_ATTR_INT, + .wMaxPacketSize = CUSTOMHID_IN_PACKET, + .bInterval = 0x20U + }, + + .hid_epout = + { + .header = + { + .bLength = sizeof(usb_desc_ep), + .bDescriptorType = USB_DESCTYPE_EP + }, + .bEndpointAddress = CUSTOMHID_OUT_EP, + .bmAttributes = USB_EP_ATTR_INT, + .wMaxPacketSize = CUSTOMHID_OUT_PACKET, + .bInterval = 0x20U + } +}; + +/* USB language ID descriptor */ +static const usb_desc_LANGID usbd_language_id_desc = +{ + .header = + { + .bLength = sizeof(usb_desc_LANGID), + .bDescriptorType = USB_DESCTYPE_STR + }, + .wLANGID = ENG_LANGID +}; + +/* USB manufacture string */ +static const usb_desc_str manufacturer_string = +{ + .header = + { + .bLength = USB_STRING_LEN(10U), + .bDescriptorType = USB_DESCTYPE_STR, + }, + .unicode_string = {'G', 'i', 'g', 'a', 'D', 'e', 'v', 'i', 'c', 'e'} +}; + +/* USB product string */ +static const usb_desc_str product_string = +{ + .header = + { + .bLength = USB_STRING_LEN(14U), + .bDescriptorType = USB_DESCTYPE_STR, + }, + .unicode_string = {'G', 'D', '3', '2', '-', 'C', 'u', 's', 't', 'o', 'm', 'H', 'I', 'D'} +}; + +/* USBD serial string */ +static usb_desc_str serial_string = +{ + .header = + { + .bLength = USB_STRING_LEN(12U), + .bDescriptorType = USB_DESCTYPE_STR, + } +}; + +/* USB string descriptor set */ +void *const usbd_hid_strings[] = +{ + [STR_IDX_LANGID] = (uint8_t *)&usbd_language_id_desc, + [STR_IDX_MFC] = (uint8_t *)&manufacturer_string, + [STR_IDX_PRODUCT] = (uint8_t *)&product_string, + [STR_IDX_SERIAL] = (uint8_t *)&serial_string +}; + +usb_desc custom_hid_desc = { + .dev_desc = (uint8_t *)&custom_hid_dev_desc, + .config_desc = (uint8_t *)&custom_hid_config_desc, + .strings = usbd_hid_strings +}; + +const uint8_t customhid_report_descriptor[DESC_LEN_REPORT] = +{ + 0x06, 0x00, 0xFF, /* USAGE_PAGE (Vendor Defined: 0xFF00) */ + 0x09, 0x00, /* USAGE (Custom Device) */ + 0xa1, 0x01, /* COLLECTION (Application) */ + + /* led 1 */ + 0x85, 0x11, /* REPORT_ID (0x11) */ + 0x09, 0x01, /* USAGE (LED 1) */ + 0x15, 0x00, /* LOGICAL_MINIMUM (0) */ + 0x25, 0x01, /* LOGICAL_MAXIMUM (1) */ + 0x75, 0x08, /* REPORT_SIZE (8) */ + 0x95, 0x01, /* REPORT_COUNT (1) */ + 0x91, 0x82, /* OUTPUT (Data,Var,Abs,Vol) */ + + /* led 2 */ + 0x85, 0x12, /* REPORT_ID (0x12) */ + 0x09, 0x02, /* USAGE (LED 2) */ + 0x15, 0x00, /* LOGICAL_MINIMUM (0) */ + 0x25, 0x01, /* LOGICAL_MAXIMUM (1) */ + 0x75, 0x08, /* REPORT_SIZE (8) */ + 0x95, 0x01, /* REPORT_COUNT (1) */ + 0x91, 0x82, /* OUTPUT (Data,Var,Abs,Vol) */ + + /* led 3 */ + 0x85, 0x13, /* REPORT_ID (0x13) */ + 0x09, 0x03, /* USAGE (LED 3) */ + 0x15, 0x00, /* LOGICAL_MINIMUM (0) */ + 0x25, 0x01, /* LOGICAL_MAXIMUM (1) */ + 0x75, 0x08, /* REPORT_SIZE (8) */ + 0x95, 0x01, /* REPORT_COUNT (1) */ + 0x91, 0x82, /* OUTPUT (Data,Var,Abs,Vol) */ + + /* led 4 */ + 0x85, 0x14, /* REPORT_ID (0x14) */ + 0x09, 0x04, /* USAGE (LED 4) */ + 0x15, 0x00, /* LOGICAL_MINIMUM (0) */ + 0x25, 0x01, /* LOGICAL_MAXIMUM (1) */ + 0x75, 0x08, /* REPORT_SIZE (8) */ + 0x95, 0x01, /* REPORT_COUNT (1) */ + 0x91, 0x82, /* OUTPUT (Data,Var,Abs,Vol) */ + + /* wakeup key */ + 0x85, 0x15, /* REPORT_ID (0x15) */ + 0x09, 0x05, /* USAGE (Push Button) */ + 0x15, 0x00, /* LOGICAL_MINIMUM (0) */ + 0x25, 0x01, /* LOGICAL_MAXIMUM (1) */ + 0x75, 0x01, /* REPORT_SIZE (1) */ + 0x81, 0x02, /* INPUT (Data,Var,Abs,Vol) */ + + 0x75, 0x07, /* REPORT_SIZE (7) */ + 0x81, 0x03, /* INPUT (Cnst,Var,Abs,Vol) */ + + /* tamper key */ + 0x85, 0x16, /* REPORT_ID (0x16) */ + 0x09, 0x06, /* USAGE (Push Button) */ + 0x15, 0x00, /* LOGICAL_MINIMUM (0) */ + 0x25, 0x01, /* LOGICAL_MAXIMUM (1) */ + 0x75, 0x01, /* REPORT_SIZE (1) */ + 0x81, 0x02, /* INPUT (Data,Var,Abs,Vol) */ + + 0x75, 0x07, /* REPORT_SIZE (7) */ + 0x81, 0x03, /* INPUT (Cnst,Var,Abs,Vol) */ + + 0xc0 /* END_COLLECTION */ +}; + +/* local function prototypes ('static') */ +static uint8_t custom_hid_init (usb_dev *udev, uint8_t config_index); +static uint8_t custom_hid_deinit (usb_dev *udev, uint8_t config_index); +static uint8_t custom_hid_req_handler (usb_dev *udev, usb_req *req); + +static uint8_t custom_hid_data_in (usb_dev *udev, uint8_t ep_num); +static uint8_t custom_hid_data_out (usb_dev *udev, uint8_t ep_num); + +usb_class_core usbd_custom_hid_cb = +{ + .command = NO_CMD, + .alter_set = 0U, + + .init = custom_hid_init, + .deinit = custom_hid_deinit, + + .req_proc = custom_hid_req_handler, + + .data_in = custom_hid_data_in, + .data_out = custom_hid_data_out +}; + +/*! + \brief register HID interface operation functions + \param[in] udev: pointer to USB device instance + \param[in] hid_fop: HID operation functions structure + \param[out] none + \retval USB device operation status +*/ +uint8_t custom_hid_itfop_register (usb_dev *udev, hid_fop_handler *hid_fop) +{ + if (NULL != hid_fop) { + udev->dev.user_data = hid_fop; + + return USBD_OK; + } + + return USBD_FAIL; +} + +/*! + \brief send custom HID report + \param[in] udev: pointer to USB device instance + \param[in] report: pointer to HID report + \param[in] len: data length + \param[out] none + \retval USB device operation status +*/ +uint8_t custom_hid_report_send (usb_dev *udev, uint8_t *report, uint32_t len) +{ + usbd_ep_send (udev, CUSTOMHID_IN_EP, report, len); + + return USBD_OK; +} + +/*! + \brief initialize the HID device + \param[in] udev: pointer to USB device instance + \param[in] config_index: configuration index + \param[out] none + \retval USB device operation status +*/ +static uint8_t custom_hid_init (usb_dev *udev, uint8_t config_index) +{ + static custom_hid_handler hid_handler; + + memset((void *)&hid_handler, 0U, sizeof(custom_hid_handler)); + + /* initialize the data Tx endpoint */ + usbd_ep_setup (udev, &(custom_hid_config_desc.hid_epin)); + + /* initialize the data Rx endpoint */ + usbd_ep_setup (udev, &(custom_hid_config_desc.hid_epout)); + + /* prepare receive data */ + usbd_ep_recev (udev, CUSTOMHID_OUT_EP, hid_handler.data, 2U); + + udev->dev.class_data[CUSTOM_HID_INTERFACE] = (void *)&hid_handler; + + if (udev->dev.user_data != NULL) { + for (uint8_t i = 0U; i < MAX_PERIPH_NUM; i++) { + if (((hid_fop_handler *)udev->dev.user_data)->periph_config[i] != NULL) { + ((hid_fop_handler *)udev->dev.user_data)->periph_config[i](); + } + } + } + + return USBD_OK; +} + +/*! + \brief deinitialize the HID device + \param[in] udev: pointer to USB device instance + \param[in] config_index: configuration index + \param[out] none + \retval USB device operation status +*/ +static uint8_t custom_hid_deinit (usb_dev *udev, uint8_t config_index) +{ + /* deinitialize HID endpoints */ + usbd_ep_clear(udev, CUSTOMHID_IN_EP); + usbd_ep_clear(udev, CUSTOMHID_OUT_EP); + + return USBD_OK; +} + +/*! + \brief handle the HID class-specific requests + \param[in] udev: pointer to USB device instance + \param[in] req: device class-specific request + \param[out] none + \retval USB device operation status +*/ +static uint8_t custom_hid_req_handler (usb_dev *udev, usb_req *req) +{ + usb_transc *transc = &udev->dev.transc_in[0]; + + custom_hid_handler *hid = (custom_hid_handler *)udev->dev.class_data[CUSTOM_HID_INTERFACE]; + + switch (req->bRequest) { + case GET_REPORT: + break; + + case GET_IDLE: + transc->xfer_buf = (uint8_t *)&hid->idlestate; + transc->remain_len = 1U; + break; + + case GET_PROTOCOL: + transc->xfer_buf = (uint8_t *)&hid->protocol; + transc->remain_len = 1U; + break; + + case SET_REPORT: + hid->reportID = (uint8_t)(req->wValue); + break; + + case SET_IDLE: + hid->idlestate = (uint8_t)(req->wValue >> 8U); + break; + + case SET_PROTOCOL: + hid->protocol = (uint8_t)(req->wValue); + break; + + case USB_GET_DESCRIPTOR: + if (USB_DESCTYPE_REPORT == (req->wValue >> 8U)) { + transc->remain_len = USB_MIN(DESC_LEN_REPORT, req->wLength); + transc->xfer_buf = (uint8_t *)customhid_report_descriptor; + } + break; + + default: + return USBD_FAIL; + } + + return USBD_OK; +} + +/*! + \brief handle custom HID data + \param[in] udev: pointer to USB device instance + \param[in] ep_num: endpoint identifier + \param[out] none + \retval USB device operation status +*/ +static uint8_t custom_hid_data_in (usb_dev *udev, uint8_t ep_num) +{ + return USBD_OK; +} + +/*! + \brief handle custom HID data + \param[in] udev: pointer to USB device instance + \param[in] ep_num: endpoint identifier + \param[out] none + \retval USB device operation status +*/ +static uint8_t custom_hid_data_out (usb_dev *udev, uint8_t ep_num) +{ + custom_hid_handler *hid = (custom_hid_handler *)udev->dev.class_data[CUSTOM_HID_INTERFACE]; + + switch (hid->data[0]){ + case 0x11U: + if (RESET != hid->data[1]) { + gd_eval_led_on(LED1); + } else { + gd_eval_led_off(LED1); + } + break; + + case 0x12U: + if (RESET != hid->data[1]) { + gd_eval_led_on(LED2); + } else { + gd_eval_led_off(LED2); + } + break; + + case 0x13U: + if (RESET != hid->data[1]) { + gd_eval_led_on(LED3); + } else { + gd_eval_led_off(LED3); + } + break; + + case 0x14U: + if (RESET != hid->data[1]) { + gd_eval_led_on(LED4); + } else { + gd_eval_led_off(LED4); + } + break; + + + default: + break; + } + + usbd_ep_recev (udev, CUSTOMHID_IN_EP, hid->data, 2U); + + return USBD_OK; +} diff --git a/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/device/class/hid/Source/standard_hid_core.c b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/device/class/hid/Source/standard_hid_core.c new file mode 100644 index 0000000000..4de0cae8c5 --- /dev/null +++ b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/device/class/hid/Source/standard_hid_core.c @@ -0,0 +1,390 @@ +/*! + \file standard_hid_core.c + \brief HID class driver + + \version 2020-07-28, V3.0.0, firmware for GD32F20x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "standard_hid_core.h" + +#include + +#define USBD_VID 0x28e9U +#define USBD_PID 0x0380U + +/* Note:it should use the C99 standard when compiling the below codes */ +/* USB standard device descriptor */ +const usb_desc_dev hid_dev_desc = +{ + .header = + { + .bLength = USB_DEV_DESC_LEN, + .bDescriptorType = USB_DESCTYPE_DEV + }, + .bcdUSB = 0x0200U, + .bDeviceClass = 0x00U, + .bDeviceSubClass = 0x00U, + .bDeviceProtocol = 0x00U, + .bMaxPacketSize0 = USB_FS_EP0_MAX_LEN, + .idVendor = USBD_VID, + .idProduct = USBD_PID, + .bcdDevice = 0x0100U, + .iManufacturer = STR_IDX_MFC, + .iProduct = STR_IDX_PRODUCT, + .iSerialNumber = STR_IDX_SERIAL, + .bNumberConfigurations = USBD_CFG_MAX_NUM +}; + +const usb_hid_desc_config_set hid_config_desc = +{ + .config = + { + .header = + { + .bLength = sizeof(usb_desc_config), + .bDescriptorType = USB_DESCTYPE_CONFIG + }, + .wTotalLength = USB_HID_CONFIG_DESC_LEN, + .bNumInterfaces = 0x01U, + .bConfigurationValue = 0x01U, + .iConfiguration = 0x00U, + .bmAttributes = 0xA0U, + .bMaxPower = 0x32U + }, + + .hid_itf = + { + .header = + { + .bLength = sizeof(usb_desc_itf), + .bDescriptorType = USB_DESCTYPE_ITF + }, + .bInterfaceNumber = 0x00U, + .bAlternateSetting = 0x00U, + .bNumEndpoints = 0x01U, + .bInterfaceClass = USB_HID_CLASS, + .bInterfaceSubClass = USB_HID_SUBCLASS_BOOT_ITF, + .bInterfaceProtocol = USB_HID_PROTOCOL_KEYBOARD, + .iInterface = 0x00U + }, + + .hid_vendor = + { + .header = + { + .bLength = sizeof(usb_desc_hid), + .bDescriptorType = USB_DESCTYPE_HID + }, + .bcdHID = 0x0111U, + .bCountryCode = 0x00U, + .bNumDescriptors = 0x01U, + .bDescriptorType = USB_DESCTYPE_REPORT, + .wDescriptorLength = USB_HID_REPORT_DESC_LEN, + }, + + .hid_epin = + { + .header = + { + .bLength = sizeof(usb_desc_ep), + .bDescriptorType = USB_DESCTYPE_EP + }, + .bEndpointAddress = HID_IN_EP, + .bmAttributes = USB_EP_ATTR_INT, + .wMaxPacketSize = HID_IN_PACKET, + .bInterval = 0x40U + } +}; + +/* USB language ID Descriptor */ +const usb_desc_LANGID usbd_language_id_desc = +{ + .header = + { + .bLength = sizeof(usb_desc_LANGID), + .bDescriptorType = USB_DESCTYPE_STR + }, + .wLANGID = ENG_LANGID +}; + +/* USB manufacture string */ +static const usb_desc_str manufacturer_string = +{ + .header = + { + .bLength = USB_STRING_LEN(10U), + .bDescriptorType = USB_DESCTYPE_STR, + }, + .unicode_string = {'G', 'i', 'g', 'a', 'D', 'e', 'v', 'i', 'c', 'e'} +}; + +/* USB product string */ +static const usb_desc_str product_string = +{ + .header = + { + .bLength = USB_STRING_LEN(17U), + .bDescriptorType = USB_DESCTYPE_STR, + }, + .unicode_string = {'G', 'D', '3', '2', '-','U', 'S', 'B', '_', 'K', 'e', 'y', 'b', 'o', 'a', 'r', 'd'} +}; + +/* USBD serial string */ +static usb_desc_str serial_string = +{ + .header = + { + .bLength = USB_STRING_LEN(12U), + .bDescriptorType = USB_DESCTYPE_STR, + } +}; + +void *const usbd_hid_strings[] = +{ + [STR_IDX_LANGID] = (uint8_t *)&usbd_language_id_desc, + [STR_IDX_MFC] = (uint8_t *)&manufacturer_string, + [STR_IDX_PRODUCT] = (uint8_t *)&product_string, + [STR_IDX_SERIAL] = (uint8_t *)&serial_string +}; + +usb_desc hid_desc = { + .dev_desc = (uint8_t *)&hid_dev_desc, + .config_desc = (uint8_t *)&hid_config_desc, + .strings = usbd_hid_strings +}; + +const uint8_t hid_report_desc[USB_HID_REPORT_DESC_LEN] = +{ + 0x05, 0x01, /* USAGE_PAGE (Generic Desktop) */ + 0x09, 0x06, /* USAGE (Keyboard) */ + 0xa1, 0x01, /* COLLECTION (Application) */ + + 0x05, 0x07, /* USAGE_PAGE (Keyboard/Keypad) */ + 0x19, 0xe0, /* USAGE_MINIMUM (Keyboard LeftControl) */ + 0x29, 0xe7, /* USAGE_MAXIMUM (Keyboard Right GUI) */ + 0x15, 0x00, /* LOGICAL_MINIMUM (0) */ + 0x25, 0x01, /* LOGICAL_MAXIMUM (1) */ + 0x95, 0x08, /* REPORT_COUNT (8) */ + 0x75, 0x01, /* REPORT_SIZE (1) */ + 0x81, 0x02, /* INPUT (Data,Var,Abs) */ + + 0x95, 0x01, /* REPORT_COUNT (1) */ + 0x75, 0x08, /* REPORT_SIZE (8) */ + 0x81, 0x03, /* INPUT (Cnst,Var,Abs) */ + + 0x95, 0x06, /* REPORT_COUNT (6) */ + 0x75, 0x08, /* REPORT_SIZE (8) */ + 0x15, 0x00, /* LOGICAL_MINIMUM (0) */ + 0x26, 0xFF, 0x00, /* LOGICAL_MAXIMUM (255) */ + 0x05, 0x07, /* USAGE_PAGE (Keyboard/Keypad) */ + 0x19, 0x00, /* USAGE_MINIMUM (Reserved (no event indicated)) */ + 0x29, 0x65, /* USAGE_MAXIMUM (Keyboard Application) */ + 0x81, 0x00, /* INPUT (Data,Ary,Abs) */ + + 0xc0 /* END_COLLECTION */ +}; + +/* local function prototypes ('static') */ +static uint8_t hid_init (usb_dev *udev, uint8_t config_index); +static uint8_t hid_deinit (usb_dev *udev, uint8_t config_index); +static uint8_t hid_req (usb_dev *udev, usb_req *req); +static uint8_t hid_data_in (usb_dev *udev, uint8_t ep_num); + +usb_class_core usbd_hid_cb = { + .command = NO_CMD, + .alter_set = 0U, + + .init = hid_init, + .deinit = hid_deinit, + .req_proc = hid_req, + .data_in = hid_data_in +}; + +/*! + \brief register HID interface operation functions + \param[in] udev: pointer to USB device instance + \param[in] hid_fop: HID operation functions structure + \param[out] none + \retval USB device operation status +*/ +uint8_t hid_itfop_register (usb_dev *udev, hid_fop_handler *hid_fop) +{ + if (NULL != hid_fop) { + udev->dev.user_data = (void *)hid_fop; + + return USBD_OK; + } + + return USBD_FAIL; +} + +/*! + \brief send keyboard report + \param[in] udev: pointer to USB device instance + \param[in] report: pointer to HID report + \param[in] len: data length + \param[out] none + \retval USB device operation status +*/ +uint8_t hid_report_send (usb_dev *udev, uint8_t *report, uint32_t len) +{ + standard_hid_handler *hid = (standard_hid_handler *)udev->dev.class_data[USBD_HID_INTERFACE]; + + hid->prev_transfer_complete = 0U; + + usbd_ep_send(udev, HID_IN_EP, report, len); + + return USBD_OK; +} + +/*! + \brief initialize the HID device + \param[in] udev: pointer to USB device instance + \param[in] config_index: configuration index + \param[out] none + \retval USB device operation status +*/ +static uint8_t hid_init (usb_dev *udev, uint8_t config_index) +{ + static standard_hid_handler hid_handler; + + memset((void *)&hid_handler, 0U, sizeof(standard_hid_handler)); + + /* Initialize the data Tx endpoint */ + usbd_ep_setup (udev, &(hid_config_desc.hid_epin)); + + hid_handler.prev_transfer_complete = 1U; + + udev->dev.class_data[USBD_HID_INTERFACE] = (void *)&hid_handler; + + if (NULL != udev->dev.user_data) { + ((hid_fop_handler *)udev->dev.user_data)->hid_itf_config(); + } + + return USBD_OK; +} + +/*! + \brief deinitialize the HID device + \param[in] udev: pointer to USB device instance + \param[in] config_index: configuration index + \param[out] none + \retval USB device operation status +*/ +static uint8_t hid_deinit (usb_dev *udev, uint8_t config_index) +{ + /* deinitialize HID endpoints */ + usbd_ep_clear(udev, HID_IN_EP); + + return USBD_OK; +} + +/*! + \brief handle the HID class-specific requests + \param[in] udev: pointer to USB device instance + \param[in] req: device class-specific request + \param[out] none + \retval USB device operation status +*/ +static uint8_t hid_req (usb_dev *udev, usb_req *req) +{ + usb_transc *transc = &udev->dev.transc_in[0]; + + standard_hid_handler *hid = (standard_hid_handler *)udev->dev.class_data[USBD_HID_INTERFACE]; + + switch (req->bRequest) { + case GET_REPORT: + /* no use for this driver */ + break; + + case GET_IDLE: + transc->xfer_buf = (uint8_t *)&hid->idle_state; + + transc->remain_len = 1U; + break; + + case GET_PROTOCOL: + transc->xfer_buf = (uint8_t *)&hid->protocol; + + transc->remain_len = 1U; + break; + + case SET_REPORT: + /* no use for this driver */ + break; + + case SET_IDLE: + hid->idle_state = (uint8_t)(req->wValue >> 8U); + break; + + case SET_PROTOCOL: + hid->protocol = (uint8_t)(req->wValue); + break; + + case USB_GET_DESCRIPTOR: + if (USB_DESCTYPE_REPORT == (req->wValue >> 8U)) { + transc->remain_len = USB_MIN(USB_HID_REPORT_DESC_LEN, req->wLength); + transc->xfer_buf = (uint8_t *)hid_report_desc; + + return REQ_SUPP; + } else if (USB_DESCTYPE_HID == (req->wValue >> 8U)) { + transc->remain_len = USB_MIN(9U, req->wLength); + transc->xfer_buf = (uint8_t *)(&(hid_config_desc.hid_vendor)); + } + break; + + default: + break; + } + + return USBD_OK; +} + +/*! + \brief handle data stage + \param[in] udev: pointer to USB device instance + \param[in] ep_num: endpoint identifier + \param[out] none + \retval USB device operation status +*/ +static uint8_t hid_data_in (usb_dev *udev, uint8_t ep_num) +{ + standard_hid_handler *hid = (standard_hid_handler *)udev->dev.class_data[USBD_HID_INTERFACE]; + + if (0U != hid->data[2]) { + hid->data[2] = 0x00U; + + usbd_ep_send(udev, HID_IN_EP, hid->data, HID_IN_PACKET); + } else { + hid->prev_transfer_complete = 1U; + } + + return USBD_OK; +} diff --git a/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/device/class/iap/Include/usb_iap_core.h b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/device/class/iap/Include/usb_iap_core.h new file mode 100644 index 0000000000..30f8c3548e --- /dev/null +++ b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/device/class/iap/Include/usb_iap_core.h @@ -0,0 +1,87 @@ +/*! + \file usb_iap_core.h + \brief the header file of IAP driver + + \version 2020-07-28, V3.0.0, firmware for GD32F20x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef __USB_IAP_CORE_H +#define __USB_IAP_CORE_H + +#include "usbd_enum.h" +#include "usb_hid.h" + +#define USB_SERIAL_STRING_SIZE 0x06U + +#ifdef USE_USB_FS + #define USB_DESC_LEN_IAP_REPORT 35U +#endif +#define USB_DESC_LEN_IAP_CONFIG_SET 41U + +/* special commands with download request */ +#define IAP_OPTION_BYTE1 0x01U +#define IAP_ERASE 0x02U +#define IAP_DNLOAD 0x03U +#define IAP_LEAVE 0x04U +#define IAP_GETBIN_ADDRESS 0x05U +#define IAP_OPTION_BYTE2 0x06U + +typedef struct +{ + uint8_t report_buf[IAP_OUT_PACKET + 1U]; + uint8_t option_byte[IAP_IN_PACKET]; + + /* state machine variables */ + uint8_t dev_status[IAP_IN_PACKET]; + uint8_t bin_addr[IAP_IN_PACKET]; + + uint8_t reportID; + uint8_t flag; + + uint32_t protocol; + uint32_t idlestate; + + uint16_t transfer_times; + uint16_t page_count; + uint16_t lps; /* last packet size */ + uint32_t file_length; + uint32_t base_address; +} usbd_iap_handler; + +typedef void (*app_func) (void); + +extern usb_desc iap_desc; +extern usb_class_core iap_class; + +/* function declarations */ +/* send iap report */ +uint8_t iap_report_send (usb_dev *udev, uint8_t *report, uint32_t len); + +#endif /* __USB_IAP_CORE_H */ diff --git a/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/device/class/iap/Source/usb_iap_core.c b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/device/class/iap/Source/usb_iap_core.c new file mode 100644 index 0000000000..82fb216f61 --- /dev/null +++ b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/device/class/iap/Source/usb_iap_core.c @@ -0,0 +1,571 @@ +/*! + \file usb_iap_core.c + \brief IAP driver + + \version 2020-07-28, V3.0.0, firmware for GD32F20x + \version 2020-12-10, V3.0.1, firmware for GD32F20x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "usb_iap_core.h" +#include "flash_operation.h" + +#include + +#define USBD_VID 0x28E9U +#define USBD_PID 0x0228U + +/* Note:it should use the C99 standard when compiling the below codes */ +/* USB standard device descriptor */ +__ALIGN_BEGIN const usb_desc_dev iap_dev_desc __ALIGN_END = +{ + .header = + { + .bLength = USB_DEV_DESC_LEN, + .bDescriptorType = USB_DESCTYPE_DEV + }, + .bcdUSB = 0x0200U, + .bDeviceClass = 0x00U, + .bDeviceSubClass = 0x00U, + .bDeviceProtocol = 0x00U, + .bMaxPacketSize0 = USB_FS_EP0_MAX_LEN, + .idVendor = USBD_VID, + .idProduct = USBD_PID, + .bcdDevice = 0x0100U, + .iManufacturer = STR_IDX_MFC, + .iProduct = STR_IDX_PRODUCT, + .iSerialNumber = STR_IDX_SERIAL, + .bNumberConfigurations = USBD_CFG_MAX_NUM +}; + +__ALIGN_BEGIN const usb_hid_desc_config_set iap_config_desc __ALIGN_END = +{ + .config = + { + .header = + { + .bLength = sizeof(usb_desc_config), + .bDescriptorType = USB_DESCTYPE_CONFIG + }, + .wTotalLength = USB_DESC_LEN_IAP_CONFIG_SET, + .bNumInterfaces = 0x01U, + .bConfigurationValue = 0x01U, + .iConfiguration = 0x00U, + .bmAttributes = 0x80U, + .bMaxPower = 0x32U + }, + + .hid_itf = + { + .header = + { + .bLength = sizeof(usb_desc_itf), + .bDescriptorType = USB_DESCTYPE_ITF + }, + .bInterfaceNumber = 0x00U, + .bAlternateSetting = 0x00U, + .bNumEndpoints = 0x02U, + .bInterfaceClass = USB_HID_CLASS, + .bInterfaceSubClass = 0x00U, + .bInterfaceProtocol = 0x00U, + .iInterface = 0x00U + }, + + .hid_vendor = + { + .header = + { + .bLength = sizeof(usb_desc_hid), + .bDescriptorType = USB_DESCTYPE_HID + }, + .bcdHID = 0x0111U, + .bCountryCode = 0x00U, + .bNumDescriptors = 0x01U, + .bDescriptorType = USB_DESCTYPE_REPORT, + .wDescriptorLength = USB_DESC_LEN_IAP_REPORT, + }, + + .hid_epin = + { + .header = + { + .bLength = sizeof(usb_desc_ep), + .bDescriptorType = USB_DESCTYPE_EP + }, + .bEndpointAddress = IAP_IN_EP, + .bmAttributes = USB_EP_ATTR_INT, + .wMaxPacketSize = IAP_IN_PACKET, + .bInterval = 0x01U + }, + + .hid_epout = + { + .header = + { + .bLength = sizeof(usb_desc_ep), + .bDescriptorType = USB_DESCTYPE_EP + }, + .bEndpointAddress = IAP_OUT_EP, + .bmAttributes = USB_EP_ATTR_INT, + .wMaxPacketSize = IAP_OUT_PACKET, + .bInterval = 0x01U + } +}; + +/* USB language ID Descriptor */ +static __ALIGN_BEGIN const usb_desc_LANGID usbd_language_id_desc __ALIGN_END = +{ + .header = + { + .bLength = sizeof(usb_desc_LANGID), + .bDescriptorType = USB_DESCTYPE_STR + }, + .wLANGID = ENG_LANGID +}; + +/* USB manufacture string */ +static __ALIGN_BEGIN const usb_desc_str manufacturer_string __ALIGN_END = +{ + .header = + { + .bLength = USB_STRING_LEN(10U), + .bDescriptorType = USB_DESCTYPE_STR, + }, + .unicode_string = {'G', 'i', 'g', 'a', 'D', 'e', 'v', 'i', 'c', 'e'} +}; + +/* USB product string */ +static __ALIGN_BEGIN const usb_desc_str product_string __ALIGN_END = +{ + .header = + { + .bLength = USB_STRING_LEN(12U), + .bDescriptorType = USB_DESCTYPE_STR, + }, + .unicode_string = {'G', 'D', '3', '2', '-', 'U', 'S', 'B', '_', 'I', 'A', 'P'} +}; + +/* USBD serial string */ +static __ALIGN_BEGIN usb_desc_str serial_string __ALIGN_END = +{ + .header = + { + .bLength = USB_STRING_LEN(2U), + .bDescriptorType = USB_DESCTYPE_STR, + } +}; + +void *const usbd_iap_strings[] = +{ + [STR_IDX_LANGID] = (uint8_t *)&usbd_language_id_desc, + [STR_IDX_MFC] = (uint8_t *)&manufacturer_string, + [STR_IDX_PRODUCT] = (uint8_t *)&product_string, + [STR_IDX_SERIAL] = (uint8_t *)&serial_string +}; + +usb_desc iap_desc = { + .dev_desc = (uint8_t *)&iap_dev_desc, + .config_desc = (uint8_t *)&iap_config_desc, + .strings = usbd_iap_strings +}; + +/* local function prototypes ('static') */ +static uint8_t iap_init (usb_dev *udev, uint8_t config_index); +static uint8_t iap_deinit (usb_dev *udev, uint8_t config_index); +static uint8_t iap_req_handler (usb_dev *udev, usb_req *req); +static uint8_t iap_data_out (usb_dev *udev, uint8_t ep_num); +static uint8_t iap_data_in (usb_dev *udev, uint8_t ep_num); + +/* IAP requests management functions */ +static void iap_req_erase (usb_dev *udev); +static void iap_req_dnload (usb_dev *udev); +static void iap_req_optionbyte(usb_dev *udev, uint8_t option_num); +static void iap_req_leave (usb_dev *udev); +static void iap_address_send (usb_dev *udev); + +usb_class_core iap_class = { + .init = iap_init, + .deinit = iap_deinit, + .req_proc = iap_req_handler, + .data_out = iap_data_out, + .data_in = iap_data_in, +}; + +/* USB custom HID device report descriptor */ +__ALIGN_BEGIN const uint8_t iap_report_desc[USB_DESC_LEN_IAP_REPORT] __ALIGN_END = +{ + 0x05, 0x01, /* USAGE_PAGE (Generic Desktop) */ + 0x09, 0x00, /* USAGE (Custom Device) */ + 0xa1, 0x01, /* COLLECTION (Application) */ + + /* IAP command and data */ + 0x85, 0x01, /* REPORT_ID (0x01) */ + 0x09, 0x01, /* USAGE (IAP command) */ + 0x15, 0x00, /* LOGICAL_MINIMUM (0) */ + 0x25, 0xff, /* LOGICAL_MAXIMUM (255) */ + 0x75, 0x08, /* REPORT_SIZE (8) */ + 0x95, REPORT_OUT_COUNT, + 0x91, 0x82, /* OUTPUT (Data,Var,Abs,Vol) */ + + /* device status and option byte */ + 0x85, 0x02, /* REPORT_ID (0x02) */ + 0x09, 0x02, /* USAGE (Status and option byte) */ + 0x15, 0x00, /* LOGICAL_MINIMUM (0) */ + 0x25, 0xff, /* LOGICAL_MAXIMUM (255) */ + 0x75, 0x08, /* REPORT_SIZE (8) */ + 0x95, REPORT_IN_COUNT, /* REPORT_COUNT (23) */ + 0x81, 0x82, /* INPUT (Data,Var,Abs,Vol) */ + + 0xc0 /* END_COLLECTION */ +}; + +/*! + \brief send iap report + \param[in] udev: pointer to USB device instance + \param[in] report: pointer to HID report + \param[in] len: data length + \param[out] none + \retval USB device operation status +*/ +uint8_t iap_report_send (usb_dev *udev, uint8_t *report, uint32_t len) +{ + usbd_ep_send (udev, IAP_IN_EP, report, len); + + return USBD_OK; +} + +/*! + \brief initialize the IAP device + \param[in] udev: pointer to USB device instance + \param[in] config_index: configuration index + \param[out] none + \retval USB device operation status +*/ +static uint8_t iap_init (usb_dev *udev, uint8_t config_index) +{ + static __ALIGN_BEGIN usbd_iap_handler iap_handler __ALIGN_END; + + /* initialize Tx endpoint */ + usbd_ep_setup(udev, &(iap_config_desc.hid_epin)); + + /* initialize Rx endpoint */ + usbd_ep_setup(udev, &(iap_config_desc.hid_epout)); + + /* unlock the internal flash */ + fmc_unlock(); + + memset((void *)&iap_handler, 0U, sizeof(usbd_iap_handler)); + + /* prepare receive data */ + usbd_ep_recev(udev, IAP_OUT_EP, iap_handler.report_buf, IAP_OUT_PACKET); + + iap_handler.base_address = APP_LOADED_ADDR; + + udev->dev.class_data[USBD_IAP_INTERFACE] = (void *)&iap_handler; + + return USBD_OK; +} + +/*! + \brief deinitialize the iap device + \param[in] udev: pointer to USB device instance + \param[in] config_index: configuration index + \param[out] none + \retval USB device operation status +*/ +static uint8_t iap_deinit (usb_dev *udev, uint8_t config_index) +{ + /* deinitialize iap endpoints */ + usbd_ep_clear (udev, IAP_IN_EP); + usbd_ep_clear (udev, IAP_OUT_EP); + + /* lock the internal flash */ + fmc_lock(); + + return USBD_OK; +} + +/*! + \brief handle the iap class-specific requests + \param[in] udev: pointer to USB device instance + \param[in] req: device class-specific request + \param[out] none + \retval USB device operation status +*/ +static uint8_t iap_req_handler (usb_dev *udev, usb_req *req) +{ + usb_transc *transc = &udev->dev.transc_in[0]; + + usbd_iap_handler *iap = (usbd_iap_handler *)udev->dev.class_data[USBD_IAP_INTERFACE]; + + switch (req->bRequest) { + case GET_REPORT: + /* no use for this driver */ + break; + + case GET_IDLE: + transc->xfer_buf = (uint8_t *)&iap->idlestate; + transc->remain_len = 1U; + break; + + case GET_PROTOCOL: + transc->xfer_buf = (uint8_t *)&iap->protocol; + transc->remain_len = 1U; + break; + + case SET_REPORT: + iap->reportID = (uint8_t)(req->wValue); + break; + + case SET_IDLE: + iap->idlestate = (uint8_t)(req->wValue >> 8U); + break; + + case SET_PROTOCOL: + iap->protocol = (uint8_t)(req->wValue); + break; + + case USB_GET_DESCRIPTOR: + if (USB_DESCTYPE_REPORT == (req->wValue >> 8U)) { + transc->remain_len = USB_MIN(USB_DESC_LEN_IAP_REPORT, req->wLength); + transc->xfer_buf = (uint8_t *)iap_report_desc; + } + break; + + default: + return USBD_FAIL; + } + + return USBD_OK; +} + +/*! + \brief handle data out stage + \param[in] udev: pointer to USB device instance + \param[in] ep_num: endpoint identifier + \param[out] none + \retval none +*/ +static uint8_t iap_data_out (usb_dev *udev ,uint8_t ep_num) +{ + usbd_iap_handler *iap = (usbd_iap_handler *)udev->dev.class_data[USBD_IAP_INTERFACE]; + + if (0x01U == iap->report_buf[0]) { + switch (iap->report_buf[1]) { + case IAP_DNLOAD: + iap_req_dnload(udev); + break; + + case IAP_ERASE: + iap_req_erase(udev); + break; + + case IAP_OPTION_BYTE1: + iap_req_optionbyte(udev, 0x01U); + break; + + case IAP_LEAVE: + iap_req_leave(udev); + break; + + case IAP_GETBIN_ADDRESS: + iap_address_send(udev); + break; + + case IAP_OPTION_BYTE2: + iap_req_optionbyte(udev, 0x02U); + break; + + default: + break; + } + } + + usbd_ep_recev(udev, IAP_OUT_EP, iap->report_buf, IAP_OUT_PACKET); + + + return USBD_OK; +} + +static uint8_t iap_data_in (usb_dev *udev, uint8_t ep_num) +{ + return USBD_OK; +} + +/*! + \brief handle the IAP_DNLOAD request + \param[in] udev: pointer to usb device instance + \param[out] none + \retval none +*/ +static void iap_req_dnload(usb_dev *udev) +{ + usbd_iap_handler *iap = (usbd_iap_handler *)udev->dev.class_data[USBD_IAP_INTERFACE]; + + if (0U != iap->transfer_times) { + if (1U == iap->transfer_times) { + if (0U == iap->lps) { + iap_data_write(&iap->report_buf[2], iap->base_address, TRANSFER_SIZE); + } else { + iap_data_write(&iap->report_buf[2], iap->base_address, iap->file_length % TRANSFER_SIZE); + iap->lps = 0U; + } + + iap->dev_status[0] = 0x02U; + iap->dev_status[1] = 0x02U; + iap_report_send (udev, iap->dev_status, IAP_IN_PACKET); + } else { + iap_data_write(&iap->report_buf[2], iap->base_address, TRANSFER_SIZE); + + iap->base_address += TRANSFER_SIZE; + } + + iap->transfer_times--; + } +} + +/*! + \brief handle the IAP_ERASE request + \param[in] udev: pointer to usb device instance + \param[out] none + \retval none +*/ +static void iap_req_erase(usb_dev *udev) +{ + uint32_t addr = 0U; + + usbd_iap_handler *iap = (usbd_iap_handler *)udev->dev.class_data[USBD_IAP_INTERFACE]; + + /* get base address to erase */ + iap->base_address = iap->report_buf[2]; + iap->base_address |= iap->report_buf[3] << 8U; + iap->base_address |= iap->report_buf[4] << 16U; + iap->base_address |= iap->report_buf[5] << 24U; + + /* get file length */ + iap->file_length = iap->report_buf[7]; + iap->file_length |= iap->report_buf[8] << 8U; + iap->file_length |= iap->report_buf[9] << 16U; + iap->file_length |= iap->report_buf[10] << 24U; + + iap->lps = iap->file_length % TRANSFER_SIZE; + if (0U == iap->lps) { + iap->transfer_times = iap->file_length / TRANSFER_SIZE; + } else { + iap->transfer_times = iap->file_length / TRANSFER_SIZE + 1U; + } + + /* check if the address is in protected area */ + if (IS_PROTECTED_AREA(iap->base_address)) { + return; + } + + addr = iap->base_address; + + /* unlock the flash program erase controller */ + fmc_unlock(); + + flash_erase(addr, iap->file_length, iap->report_buf); + + fmc_lock(); + + iap->dev_status[0] = 0x02U; + iap->dev_status[1] = 0x01U; + + usbd_ep_send(udev, IAP_IN_EP, iap->dev_status, IAP_IN_PACKET); +} + +/*! + \brief handle the IAP_OPTION_BYTE request + \param[in] udev: pointer to USB device instance + \param[in] option_num: number of option byte + \param[out] none + \retval none +*/ +static void iap_req_optionbyte(usb_dev *udev, uint8_t option_num) +{ + uint8_t i = 0U; + uint32_t address = 0U; + + usbd_iap_handler *iap = (usbd_iap_handler *)udev->dev.class_data[USBD_IAP_INTERFACE]; + + iap->option_byte[0]= 0x02U; + + if (0x01U == option_num) { + address = OPT_BYTE_ADDR1; +#ifdef OPT_BYTE_ADDR2 + } else if (0x02U == option_num) { + address = OPT_BYTE_ADDR2; +#endif + } else { + return; + } + + for (i = 1U; i < 17U; i++) { + iap->option_byte[i] = *(uint8_t *)address; + address++; + } + + iap_report_send (udev, iap->option_byte, IAP_IN_PACKET); +} + +/*! + \brief handle the IAP_LEAVE request + \param[in] udev: pointer to usb device instance + \param[out] none + \retval none +*/ +static void iap_req_leave(usb_dev *udev) +{ + /* lock the internal flash */ + fmc_lock(); + + /* generate system reset to allow jumping to the user code */ + NVIC_SystemReset(); +} + +/*! + \brief handle the IAP_SEND_ADDRESS request + \param[in] udev: pointer to usb device instance + \param[out] none + \retval none +*/ +static void iap_address_send(usb_dev *udev) +{ + usbd_iap_handler *iap = (usbd_iap_handler *)udev->dev.class_data[USBD_IAP_INTERFACE]; + + iap->bin_addr[0] = 0x02U; + + iap->bin_addr[1] = (uint8_t)(APP_LOADED_ADDR); + iap->bin_addr[2] = (uint8_t)(APP_LOADED_ADDR >> 8U); + iap->bin_addr[3] = (uint8_t)(APP_LOADED_ADDR >> 16U); + iap->bin_addr[4] = (uint8_t)(APP_LOADED_ADDR >> 24U); + + iap_report_send (udev, iap->bin_addr, IAP_IN_PACKET); +} diff --git a/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/device/class/msc/Include/usbd_msc_bbb.h b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/device/class/msc/Include/usbd_msc_bbb.h new file mode 100644 index 0000000000..bfaf8d7f27 --- /dev/null +++ b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/device/class/msc/Include/usbd_msc_bbb.h @@ -0,0 +1,101 @@ +/*! + \file usbd_msc_bbb.h + \brief the header file of the usbd_msc_bot.c file + + \version 2020-07-28, V3.0.0, firmware for GD32F20x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef __USBD_MSC_BBB_H +#define __USBD_MSC_BBB_H + +#include "usbd_core.h" +#include "msc_bbb.h" +#include "usbd_msc_mem.h" +#include "usbd_msc_scsi.h" + +/* MSC BBB state */ +enum msc_bbb_state { + BBB_IDLE = 0U, /*!< idle state */ + BBB_DATA_OUT, /*!< data OUT state */ + BBB_DATA_IN, /*!< data IN state */ + BBB_LAST_DATA_IN, /*!< last data IN state */ + BBB_SEND_DATA /*!< send immediate data state */ +}; + +/* MSC BBB status */ +enum msc_bbb_status { + BBB_STATUS_NORMAL = 0U, /*!< normal status */ + BBB_STATUS_RECOVERY, /*!< recovery status*/ + BBB_STATUS_ERROR /*!< error status */ +}; + +typedef struct +{ + uint8_t bbb_data[MSC_MEDIA_PACKET_SIZE]; + + uint8_t max_lun; + uint8_t bbb_state; + uint8_t bbb_status; + + uint32_t bbb_datalen; + + msc_bbb_cbw bbb_cbw; + msc_bbb_csw bbb_csw; + + uint8_t scsi_sense_head; + uint8_t scsi_sense_tail; + + uint32_t scsi_blk_size[MEM_LUN_NUM]; + uint32_t scsi_blk_nbr[MEM_LUN_NUM]; + + uint32_t scsi_blk_addr; + uint32_t scsi_blk_len; + uint32_t scsi_disk_pop; + + msc_scsi_sense scsi_sense[SENSE_LIST_DEEPTH]; +} usbd_msc_handler; + +/* function declarations */ +/* initialize the bbb process */ +void msc_bbb_init (usb_core_driver *udev); +/* reset the BBB machine */ +void msc_bbb_reset (usb_core_driver *udev); +/* deinitialize the BBB machine */ +void msc_bbb_deinit (usb_core_driver *udev); +/* handle BBB data IN stage */ +void msc_bbb_data_in (usb_core_driver *udev, uint8_t ep_num); +/* handle BBB data OUT stage */ +void msc_bbb_data_out (usb_core_driver *udev, uint8_t ep_num); +/* send the CSW(command status wrapper) */ +void msc_bbb_csw_send (usb_core_driver *udev, uint8_t csw_status); +/* complete the clear feature request */ +void msc_bbb_clrfeature (usb_core_driver *udev, uint8_t ep_num); + +#endif /* __USBD_MSC_BBB_H */ diff --git a/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/device/class/msc/Include/usbd_msc_core.h b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/device/class/msc/Include/usbd_msc_core.h new file mode 100644 index 0000000000..bc59a7341a --- /dev/null +++ b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/device/class/msc/Include/usbd_msc_core.h @@ -0,0 +1,59 @@ +/*! + \file usbd_msc_core.h + \brief the header file of USB MSC device class core functions + + \version 2020-07-28, V3.0.0, firmware for GD32F20x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef __USBD_MSC_CORE_H +#define __USBD_MSC_CORE_H + +#include "usbd_core.h" +#include "usb_msc.h" + +#define USB_MSC_CONFIG_DESC_SIZE 32U + +#define MSC_EPIN_SIZE MSC_DATA_PACKET_SIZE +#define MSC_EPOUT_SIZE MSC_DATA_PACKET_SIZE + +/* USB configuration descriptor structure */ +typedef struct +{ + usb_desc_config config; + + usb_desc_itf msc_itf; + usb_desc_ep msc_epin; + usb_desc_ep msc_epout; +} usb_desc_config_set; + +extern usb_desc msc_desc; +extern usb_class_core msc_class; + +#endif /* __USBD_MSC_CORE_H */ diff --git a/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/device/class/msc/Include/usbd_msc_data.h b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/device/class/msc/Include/usbd_msc_data.h new file mode 100644 index 0000000000..99ca1488d3 --- /dev/null +++ b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/device/class/msc/Include/usbd_msc_data.h @@ -0,0 +1,49 @@ +/*! + \file usbd_msc_data.h + \brief the header file of the usbd_msc_data.c file + + \version 2020-07-28, V3.0.0, firmware for GD32F20x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef __USBD_MSC_DATA_H +#define __USBD_MSC_DATA_H + +#include "usbd_conf.h" + +#define MODE_SENSE6_LENGTH 8U +#define MODE_SENSE10_LENGTH 8U +#define INQUIRY_PAGE00_LENGTH 96U +#define FORMAT_CAPACITIES_LENGTH 20U + +extern const uint8_t msc_page00_inquiry_data[]; +extern const uint8_t msc_mode_sense6_data[]; +extern const uint8_t msc_mode_sense10_data[]; + +#endif /* __USBD_MSC_DATA_H */ diff --git a/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/device/class/msc/Include/usbd_msc_mem.h b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/device/class/msc/Include/usbd_msc_mem.h new file mode 100644 index 0000000000..a55e9a7a9d --- /dev/null +++ b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/device/class/msc/Include/usbd_msc_mem.h @@ -0,0 +1,59 @@ +/*! + \file usbd_msc_mem.h + \brief header file for storage memory + + \version 2020-07-28, V3.0.0, firmware for GD32F20x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef __USBD_MSC_MEM_H +#define __USBD_MSC_MEM_H + +#include "usbd_conf.h" + +#define USBD_STD_INQUIRY_LENGTH 36U + +typedef struct +{ + int8_t (*mem_init) (uint8_t lun); + int8_t (*mem_ready) (uint8_t lun); + int8_t (*mem_protected) (uint8_t lun); + int8_t (*mem_read) (uint8_t lun, uint8_t *buf, uint32_t block_addr, uint16_t block_len); + int8_t (*mem_write) (uint8_t lun, uint8_t *buf, uint32_t block_addr, uint16_t block_len); + int8_t (*mem_maxlun) (void); + + uint8_t *mem_toc_data; + uint8_t *mem_inquiry_data[MEM_LUN_NUM]; + uint32_t mem_block_size[MEM_LUN_NUM]; + uint32_t mem_block_len[MEM_LUN_NUM]; +}usbd_mem_cb; + +extern usbd_mem_cb *usbd_mem_fops; + +#endif /* __USBD_MSC_MEM_H */ diff --git a/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/device/class/msc/Include/usbd_msc_scsi.h b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/device/class/msc/Include/usbd_msc_scsi.h new file mode 100644 index 0000000000..e69a913285 --- /dev/null +++ b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/device/class/msc/Include/usbd_msc_scsi.h @@ -0,0 +1,50 @@ +/*! + \file usbd_msc_scsi.h + \brief the header file of the usbd_msc_scsi.c file + + \version 2020-07-28, V3.0.0, firmware for GD32F20x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef __USBD_MSC_SCSI_H +#define __USBD_MSC_SCSI_H + +#include "usbd_msc_data.h" +#include "usbd_msc_bbb.h" +#include "msc_scsi.h" + +#define SENSE_LIST_DEEPTH 4U + +/* function declarations */ +/* process SCSI commands */ +int8_t scsi_process_cmd (usb_core_driver *udev, uint8_t lun, uint8_t *cmd); +/* load the last error code in the error list */ +void scsi_sense_code (usb_core_driver *udev, uint8_t lun, uint8_t skey, uint8_t asc); + +#endif /* __USBD_MSC_SCSI_H */ diff --git a/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/device/class/msc/Source/usbd_msc_bbb.c b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/device/class/msc/Source/usbd_msc_bbb.c new file mode 100644 index 0000000000..efe159276f --- /dev/null +++ b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/device/class/msc/Source/usbd_msc_bbb.c @@ -0,0 +1,287 @@ +/*! + \file usbd_msc_bbb.c + \brief USB BBB(Bulk/Bulk/Bulk) protocol core functions + \note BBB means Bulk-only transport protocol for USB MSC + + \version 2020-07-28, V3.0.0, firmware for GD32F20x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "usbd_enum.h" +#include "usbd_msc_bbb.h" + +/* local function prototypes ('static') */ +static void msc_bbb_cbw_decode (usb_core_driver *udev); +static void msc_bbb_data_send (usb_core_driver *udev, uint8_t *pbuf, uint32_t Len); +static void msc_bbb_abort (usb_core_driver *udev); + +/*! + \brief initialize the bbb process + \param[in] udev: pointer to USB device instance + \param[out] none + \retval none +*/ +void msc_bbb_init (usb_core_driver *udev) +{ + uint8_t lun_num; + + usbd_msc_handler *msc = (usbd_msc_handler *)udev->dev.class_data[USBD_MSC_INTERFACE]; + + msc->bbb_state = BBB_IDLE; + msc->bbb_status = BBB_STATUS_NORMAL; + + /* initialize the storage logic unit */ + for(lun_num = 0U; lun_num < MEM_LUN_NUM; lun_num++) { + usbd_mem_fops->mem_init(lun_num); + } + + /* flush the Rx FIFO */ + usbd_fifo_flush (udev, MSC_OUT_EP); + + /* flush the Tx FIFO */ + usbd_fifo_flush (udev, MSC_IN_EP); + + /* prepare endpoint to receive the first BBB CBW */ + usbd_ep_recev (udev, MSC_OUT_EP, (uint8_t *)&msc->bbb_cbw, BBB_CBW_LENGTH); +} + +/*! + \brief reset the BBB machine + \param[in] udev: pointer to USB device instance + \param[out] none + \retval none +*/ +void msc_bbb_reset (usb_core_driver *udev) +{ + usbd_msc_handler *msc = (usbd_msc_handler *)udev->dev.class_data[USBD_MSC_INTERFACE]; + + msc->bbb_state = BBB_IDLE; + msc->bbb_status = BBB_STATUS_RECOVERY; + + /* prepare endpoint to receive the first BBB command */ + usbd_ep_recev (udev, MSC_OUT_EP, (uint8_t *)&msc->bbb_cbw, BBB_CBW_LENGTH); +} + +/*! + \brief deinitialize the BBB machine + \param[in] udev: pointer to USB device instance + \param[out] none + \retval none +*/ +void msc_bbb_deinit (usb_core_driver *udev) +{ + usbd_msc_handler *msc = (usbd_msc_handler *)udev->dev.class_data[USBD_MSC_INTERFACE]; + + msc->bbb_state = BBB_IDLE; +} + +/*! + \brief handle BBB data IN stage + \param[in] udev: pointer to USB device instance + \param[in] ep_num: endpoint number + \param[out] none + \retval none +*/ +void msc_bbb_data_in (usb_core_driver *udev, uint8_t ep_num) +{ + usbd_msc_handler *msc = (usbd_msc_handler *)udev->dev.class_data[USBD_MSC_INTERFACE]; + + switch (msc->bbb_state) { + case BBB_DATA_IN: + if (scsi_process_cmd (udev, msc->bbb_cbw.bCBWLUN, &msc->bbb_cbw.CBWCB[0]) < 0) { + msc_bbb_csw_send (udev, CSW_CMD_FAILED); + } + break; + + case BBB_SEND_DATA: + case BBB_LAST_DATA_IN: + msc_bbb_csw_send (udev, CSW_CMD_PASSED); + break; + + default: + break; + } +} + +/*! + \brief handle BBB data OUT stage + \param[in] udev: pointer to USB device instance + \param[in] ep_num: endpoint number + \param[out] none + \retval none +*/ +void msc_bbb_data_out (usb_core_driver *udev, uint8_t ep_num) +{ + usbd_msc_handler *msc = (usbd_msc_handler *)udev->dev.class_data[USBD_MSC_INTERFACE]; + + switch (msc->bbb_state) { + case BBB_IDLE: + msc_bbb_cbw_decode (udev); + break; + + case BBB_DATA_OUT: + if (scsi_process_cmd (udev, msc->bbb_cbw.bCBWLUN, &msc->bbb_cbw.CBWCB[0]) < 0) { + msc_bbb_csw_send (udev, CSW_CMD_FAILED); + } + break; + + default: + break; + } +} + +/*! + \brief send the CSW(command status wrapper) + \param[in] udev: pointer to USB device instance + \param[in] csw_status: CSW status + \param[out] none + \retval none +*/ +void msc_bbb_csw_send (usb_core_driver *udev, uint8_t csw_status) +{ + usbd_msc_handler *msc = (usbd_msc_handler *)udev->dev.class_data[USBD_MSC_INTERFACE]; + + msc->bbb_csw.dCSWSignature = BBB_CSW_SIGNATURE; + msc->bbb_csw.bCSWStatus = csw_status; + msc->bbb_state = BBB_IDLE; + + usbd_ep_send (udev, MSC_IN_EP, (uint8_t *)&msc->bbb_csw, BBB_CSW_LENGTH); + + /* prepare endpoint to receive next command */ + usbd_ep_recev (udev, MSC_OUT_EP, (uint8_t *)&msc->bbb_cbw, BBB_CBW_LENGTH); +} + +/*! + \brief complete the clear feature request + \param[in] udev: pointer to USB device instance + \param[in] ep_num: endpoint number + \param[out] none + \retval none +*/ +void msc_bbb_clrfeature (usb_core_driver *udev, uint8_t ep_num) +{ + usbd_msc_handler *msc = (usbd_msc_handler *)udev->dev.class_data[USBD_MSC_INTERFACE]; + + if (msc->bbb_status == BBB_STATUS_ERROR)/* bad CBW signature */ { + usbd_ep_stall(udev, MSC_IN_EP); + + msc->bbb_status = BBB_STATUS_NORMAL; + } else if(((ep_num & 0x80U) == 0x80U) && (msc->bbb_status != BBB_STATUS_RECOVERY)) { + msc_bbb_csw_send (udev, CSW_CMD_FAILED); + } else { + + } +} + +/*! + \brief decode the CBW command and set the BBB state machine accordingly + \param[in] udev: pointer to USB device instance + \param[out] none + \retval none +*/ +static void msc_bbb_cbw_decode (usb_core_driver *udev) +{ + usbd_msc_handler *msc = (usbd_msc_handler *)udev->dev.class_data[USBD_MSC_INTERFACE]; + + msc->bbb_csw.dCSWTag = msc->bbb_cbw.dCBWTag; + msc->bbb_csw.dCSWDataResidue = msc->bbb_cbw.dCBWDataTransferLength; + + if ((BBB_CBW_LENGTH != usbd_rxcount_get (udev, MSC_OUT_EP)) || + (BBB_CBW_SIGNATURE != msc->bbb_cbw.dCBWSignature)|| + (msc->bbb_cbw.bCBWLUN > 1U) || + (msc->bbb_cbw.bCBWCBLength < 1U) || + (msc->bbb_cbw.bCBWCBLength > 16U)) { + /* illegal command handler */ + scsi_sense_code (udev, msc->bbb_cbw.bCBWLUN, ILLEGAL_REQUEST, INVALID_CDB); + + msc->bbb_status = BBB_STATUS_ERROR; + + msc_bbb_abort (udev); + } else { + if (scsi_process_cmd (udev, msc->bbb_cbw.bCBWLUN, &msc->bbb_cbw.CBWCB[0]) < 0) { + msc_bbb_abort (udev); + } else if ((BBB_DATA_IN != msc->bbb_state) && + (BBB_DATA_OUT != msc->bbb_state) && + (BBB_LAST_DATA_IN != msc->bbb_state)) { /* burst xfer handled internally */ + if (msc->bbb_datalen > 0U) { + msc_bbb_data_send (udev, msc->bbb_data, msc->bbb_datalen); + } else if (0U == msc->bbb_datalen) { + msc_bbb_csw_send (udev, CSW_CMD_PASSED); + } else { + + } + } else { + + } + } +} + +/*! + \brief send the requested data + \param[in] udev: pointer to USB device instance + \param[in] buf: pointer to data buffer + \param[in] len: data length + \param[out] none + \retval none +*/ +static void msc_bbb_data_send (usb_core_driver *udev, uint8_t *buf, uint32_t len) +{ + usbd_msc_handler *msc = (usbd_msc_handler *)udev->dev.class_data[USBD_MSC_INTERFACE]; + + len = USB_MIN (msc->bbb_cbw.dCBWDataTransferLength, len); + + msc->bbb_csw.dCSWDataResidue -= len; + msc->bbb_csw.bCSWStatus = CSW_CMD_PASSED; + msc->bbb_state = BBB_SEND_DATA; + + usbd_ep_send (udev, MSC_IN_EP, buf, len); +} + +/*! + \brief abort the current transfer + \param[in] udev: pointer to USB device instance + \param[out] none + \retval none +*/ +static void msc_bbb_abort (usb_core_driver *udev) +{ + usbd_msc_handler *msc = (usbd_msc_handler *)udev->dev.class_data[USBD_MSC_INTERFACE]; + + if ((0U == msc->bbb_cbw.bmCBWFlags) && + (0U != msc->bbb_cbw.dCBWDataTransferLength) && + (BBB_STATUS_NORMAL == msc->bbb_status)) { + usbd_ep_stall(udev, MSC_OUT_EP); + } + + usbd_ep_stall(udev, MSC_IN_EP); + + if (msc->bbb_status == BBB_STATUS_ERROR) { + usbd_ep_recev (udev, MSC_OUT_EP, (uint8_t *)&msc->bbb_cbw, BBB_CBW_LENGTH); + } +} diff --git a/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/device/class/msc/Source/usbd_msc_core.c b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/device/class/msc/Source/usbd_msc_core.c new file mode 100644 index 0000000000..d81a382cd4 --- /dev/null +++ b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/device/class/msc/Source/usbd_msc_core.c @@ -0,0 +1,319 @@ +/*! + \file usbd_msc_core.c + \brief USB MSC device class core functions + + \version 2020-07-28, V3.0.0, firmware for GD32F20x + \version 2020-12-10, V3.0.1, firmware for GD32F20x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "usbd_enum.h" +#include "usbd_msc_bbb.h" +#include "usbd_msc_core.h" +#include + +#define USBD_VID 0x28E9U +#define USBD_PID 0x028FU + +/* local function prototypes ('static') */ +static uint8_t msc_core_init (usb_dev *udev, uint8_t config_index); +static uint8_t msc_core_deinit (usb_dev *udev, uint8_t config_index); +static uint8_t msc_core_req (usb_dev *udev, usb_req *req); +static uint8_t msc_core_in (usb_dev *udev, uint8_t ep_num); +static uint8_t msc_core_out (usb_dev *udev, uint8_t ep_num); + +usb_class_core msc_class = +{ + .init = msc_core_init, + .deinit = msc_core_deinit, + + .req_proc = msc_core_req, + + .data_in = msc_core_in, + .data_out = msc_core_out +}; + +/* note: it should use the C99 standard when compiling the below codes */ +/* USB standard device descriptor */ +__ALIGN_BEGIN const usb_desc_dev msc_dev_desc __ALIGN_END = +{ + .header = { + .bLength = USB_DEV_DESC_LEN, + .bDescriptorType = USB_DESCTYPE_DEV + }, + .bcdUSB = 0x0200U, + .bDeviceClass = 0x00U, + .bDeviceSubClass = 0x00U, + .bDeviceProtocol = 0x00U, + .bMaxPacketSize0 = USB_FS_EP0_MAX_LEN, + .idVendor = USBD_VID, + .idProduct = USBD_PID, + .bcdDevice = 0x0100U, + .iManufacturer = STR_IDX_MFC, + .iProduct = STR_IDX_PRODUCT, + .iSerialNumber = STR_IDX_SERIAL, + .bNumberConfigurations = USBD_CFG_MAX_NUM +}; + +/* USB device configuration descriptor */ +__ALIGN_BEGIN const usb_desc_config_set msc_config_desc __ALIGN_END = +{ + .config = + { + .header = { + .bLength = sizeof(usb_desc_config), + .bDescriptorType = USB_DESCTYPE_CONFIG + }, + .wTotalLength = USB_MSC_CONFIG_DESC_SIZE, + .bNumInterfaces = 0x01U, + .bConfigurationValue = 0x01U, + .iConfiguration = 0x00U, + .bmAttributes = 0xC0U, + .bMaxPower = 0x32U + }, + + .msc_itf = + { + .header = { + .bLength = sizeof(usb_desc_itf), + .bDescriptorType = USB_DESCTYPE_ITF + }, + .bInterfaceNumber = 0x00U, + .bAlternateSetting = 0x00U, + .bNumEndpoints = 0x02U, + .bInterfaceClass = USB_CLASS_MSC, + .bInterfaceSubClass = USB_MSC_SUBCLASS_SCSI, + .bInterfaceProtocol = USB_MSC_PROTOCOL_BBB, + .iInterface = 0x00U + }, + + .msc_epin = + { + .header = { + .bLength = sizeof(usb_desc_ep), + .bDescriptorType = USB_DESCTYPE_EP + }, + .bEndpointAddress = MSC_IN_EP, + .bmAttributes = USB_EP_ATTR_BULK, + .wMaxPacketSize = MSC_EPIN_SIZE, + .bInterval = 0x00U + }, + + .msc_epout = + { + .header = { + .bLength = sizeof(usb_desc_ep), + .bDescriptorType = USB_DESCTYPE_EP + }, + .bEndpointAddress = MSC_OUT_EP, + .bmAttributes = USB_EP_ATTR_BULK, + .wMaxPacketSize = MSC_EPOUT_SIZE, + .bInterval = 0x00U + } +}; + +/* USB language ID descriptor */ +__ALIGN_BEGIN const usb_desc_LANGID usbd_language_id_desc __ALIGN_END = +{ + .header = + { + .bLength = sizeof(usb_desc_LANGID), + .bDescriptorType = USB_DESCTYPE_STR + }, + .wLANGID = ENG_LANGID +}; + +/* USB manufacture string */ +static __ALIGN_BEGIN const usb_desc_str manufacturer_string __ALIGN_END = +{ + .header = + { + .bLength = USB_STRING_LEN(10U), + .bDescriptorType = USB_DESCTYPE_STR, + }, + .unicode_string = {'G', 'i', 'g', 'a', 'D', 'e', 'v', 'i', 'c', 'e'} +}; + +/* USB product string */ +static __ALIGN_BEGIN const usb_desc_str product_string __ALIGN_END = +{ + .header = + { + .bLength = USB_STRING_LEN(12U), + .bDescriptorType = USB_DESCTYPE_STR, + }, + .unicode_string = {'G', 'D', '3', '2', '-', 'U', 'S', 'B', '_', 'M', 'S', 'C'} +}; + +/* USBD serial string */ +static __ALIGN_BEGIN usb_desc_str serial_string __ALIGN_END = +{ + .header = + { + .bLength = USB_STRING_LEN(12U), + .bDescriptorType = USB_DESCTYPE_STR, + } +}; + +/* USB string descriptor */ +void *const usbd_msc_strings[] = +{ + [STR_IDX_LANGID] = (uint8_t *)&usbd_language_id_desc, + [STR_IDX_MFC] = (uint8_t *)&manufacturer_string, + [STR_IDX_PRODUCT] = (uint8_t *)&product_string, + [STR_IDX_SERIAL] = (uint8_t *)&serial_string +}; + +usb_desc msc_desc = { + .dev_desc = (uint8_t *)&msc_dev_desc, + .config_desc = (uint8_t *)&msc_config_desc, + .strings = usbd_msc_strings +}; + +static __ALIGN_BEGIN uint8_t usbd_msc_maxlun = 0U __ALIGN_END; + +/*! + \brief initialize the MSC device + \param[in] udev: pointer to USB device instance + \param[in] config_index: configuration index + \param[out] none + \retval USB device operation status +*/ +static uint8_t msc_core_init (usb_dev *udev, uint8_t config_index) +{ + static __ALIGN_BEGIN usbd_msc_handler msc_handler __ALIGN_END; + + memset((void *)&msc_handler, 0U, sizeof(usbd_msc_handler)); + + udev->dev.class_data[USBD_MSC_INTERFACE] = (void *)&msc_handler; + + /* configure MSC Tx endpoint */ + usbd_ep_setup (udev, &(msc_config_desc.msc_epin)); + + /* configure MSC Rx endpoint */ + usbd_ep_setup (udev, &(msc_config_desc.msc_epout)); + + /* initialize the BBB layer */ + msc_bbb_init(udev); + + return USBD_OK; +} + +/*! + \brief deinitialize the MSC device + \param[in] udev: pointer to USB device instance + \param[in] config_index: configuration index + \param[out] none + \retval USB device operation status +*/ +static uint8_t msc_core_deinit (usb_dev *udev, uint8_t config_index) +{ + /* clear MSC endpoints */ + usbd_ep_clear (udev, MSC_IN_EP); + usbd_ep_clear (udev, MSC_OUT_EP); + + /* deinitialize the BBB layer */ + msc_bbb_deinit(udev); + + return USBD_OK; +} + +/*! + \brief handle the MSC class-specific and standard requests + \param[in] udev: pointer to USB device instance + \param[in] req: device class-specific request + \param[out] none + \retval USB device operation status +*/ +static uint8_t msc_core_req (usb_dev *udev, usb_req *req) +{ + usb_transc *transc = &udev->dev.transc_in[0]; + + switch (req->bRequest) { + case BBB_GET_MAX_LUN : + if((0U == req->wValue) && + (1U == req->wLength) && + (0x80U == (req->bmRequestType & 0x80U))) { + usbd_msc_maxlun = (uint8_t)usbd_mem_fops->mem_maxlun(); + + transc->xfer_buf = &usbd_msc_maxlun; + transc->remain_len = 1U; + } else { + return USBD_FAIL; + } + break; + + case BBB_RESET : + if((0U == req->wValue) && + (0U == req->wLength) && + (0x80U != (req->bmRequestType & 0x80U))) { + msc_bbb_reset(udev); + } else { + return USBD_FAIL; + } + break; + + case USB_CLEAR_FEATURE: + msc_bbb_clrfeature (udev, (uint8_t)req->wIndex); + break; + + default: + return USBD_FAIL; + } + + return USBD_OK; +} + +/*! + \brief handle data in stage + \param[in] udev: pointer to USB device instance + \param[in] ep_num: the endpoint number + \param[out] none + \retval none +*/ +static uint8_t msc_core_in (usb_dev *udev, uint8_t ep_num) +{ + msc_bbb_data_in(udev, ep_num); + + return USBD_OK; +} + +/*! + \brief handle data out stage + \param[in] udev: pointer to USB device instance + \param[in] ep_num: the endpoint number + \param[out] none + \retval none +*/ +static uint8_t msc_core_out (usb_dev *udev, uint8_t ep_num) +{ + msc_bbb_data_out (udev, ep_num); + + return USBD_OK; +} diff --git a/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/device/class/msc/Source/usbd_msc_data.c b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/device/class/msc/Source/usbd_msc_data.c new file mode 100644 index 0000000000..bc9fde2fd3 --- /dev/null +++ b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/device/class/msc/Source/usbd_msc_data.c @@ -0,0 +1,73 @@ +/*! + \file usbd_msc_data.c + \brief USB MSC vital inquiry pages and sense data + + \version 2020-07-28, V3.0.0, firmware for GD32F20x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "usbd_msc_data.h" + +/* USB mass storage page 0 inquiry data */ +const uint8_t msc_page00_inquiry_data[] = +{ + 0x00U, + 0x00U, + 0x00U, + 0x00U, + (INQUIRY_PAGE00_LENGTH - 4U), + 0x80U, + 0x83U, +}; + +/* USB mass storage sense 6 data */ +const uint8_t msc_mode_sense6_data[] = +{ + 0x00U, + 0x00U, + 0x00U, + 0x00U, + 0x00U, + 0x00U, + 0x00U, + 0x00U +}; + +/* USB mass storage sense 10 data */ +const uint8_t msc_mode_sense10_data[] = +{ + 0x00U, + 0x06U, + 0x00U, + 0x00U, + 0x00U, + 0x00U, + 0x00U, + 0x00U +}; diff --git a/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/device/class/msc/Source/usbd_msc_scsi.c b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/device/class/msc/Source/usbd_msc_scsi.c new file mode 100644 index 0000000000..39ddfd8f85 --- /dev/null +++ b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/device/class/msc/Source/usbd_msc_scsi.c @@ -0,0 +1,725 @@ +/*! + \file usbd_msc_scsi.c + \brief USB SCSI layer functions + + \version 2020-07-28, V3.0.0, firmware for GD32F20x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "usbd_enum.h" +#include "usbd_msc_bbb.h" +#include "usbd_msc_scsi.h" +#include "usbd_msc_data.h" + +/* local function prototypes ('static') */ +static int8_t scsi_test_unit_ready (usb_core_driver *udev, uint8_t lun, uint8_t *params); +static int8_t scsi_mode_select6 (usb_core_driver *udev, uint8_t lun, uint8_t *params); +static int8_t scsi_mode_select10 (usb_core_driver *udev, uint8_t lun, uint8_t *params); +static int8_t scsi_inquiry (usb_core_driver *udev, uint8_t lun, uint8_t *params); +static int8_t scsi_read_format_capacity (usb_core_driver *udev, uint8_t lun, uint8_t *params); +static int8_t scsi_read_capacity10 (usb_core_driver *udev, uint8_t lun, uint8_t *params); +static int8_t scsi_request_sense (usb_core_driver *udev, uint8_t lun, uint8_t *params); +static int8_t scsi_mode_sense6 (usb_core_driver *udev, uint8_t lun, uint8_t *params); +static int8_t scsi_toc_cmd_read (usb_core_driver *udev, uint8_t lun, uint8_t *params); +static int8_t scsi_mode_sense10 (usb_core_driver *udev, uint8_t lun, uint8_t *params); +static int8_t scsi_write10 (usb_core_driver *udev, uint8_t lun, uint8_t *params); +static int8_t scsi_read10 (usb_core_driver *udev, uint8_t lun, uint8_t *params); +static int8_t scsi_verify10 (usb_core_driver *udev, uint8_t lun, uint8_t *params); + +static int8_t scsi_process_read (usb_core_driver *udev, uint8_t lun); +static int8_t scsi_process_write (usb_core_driver *udev, uint8_t lun); + +static inline int8_t scsi_check_address_range (usb_core_driver *udev, uint8_t lun, uint32_t blk_offset, uint16_t blk_nbr); +static inline int8_t scsi_format_cmd (usb_core_driver *udev, uint8_t lun); +static inline int8_t scsi_start_stop_unit (usb_core_driver *udev, uint8_t lun, uint8_t *params); +static inline int8_t scsi_allow_medium_removal (usb_core_driver *udev, uint8_t lun, uint8_t *params); + +/*! + \brief process SCSI commands + \param[in] udev: pointer to USB device instance + \param[in] lun: logical unit number + \param[in] params: command parameters + \param[out] none + \retval status +*/ +int8_t scsi_process_cmd(usb_core_driver *udev, uint8_t lun, uint8_t *params) +{ + switch (params[0]) { + case SCSI_TEST_UNIT_READY: + return scsi_test_unit_ready (udev, lun, params); + + case SCSI_REQUEST_SENSE: + return scsi_request_sense (udev, lun, params); + + case SCSI_INQUIRY: + return scsi_inquiry (udev, lun, params); + + case SCSI_START_STOP_UNIT: + return scsi_start_stop_unit (udev, lun, params); + + case SCSI_ALLOW_MEDIUM_REMOVAL: + return scsi_allow_medium_removal (udev, lun, params); + + case SCSI_MODE_SENSE6: + return scsi_mode_sense6 (udev, lun, params); + + case SCSI_MODE_SENSE10: + return scsi_mode_sense10 (udev, lun, params); + + case SCSI_READ_FORMAT_CAPACITIES: + return scsi_read_format_capacity (udev, lun, params); + + case SCSI_READ_CAPACITY10: + return scsi_read_capacity10 (udev, lun, params); + + case SCSI_READ10: + return scsi_read10 (udev, lun, params); + + case SCSI_WRITE10: + return scsi_write10 (udev, lun, params); + + case SCSI_VERIFY10: + return scsi_verify10 (udev, lun, params); + + case SCSI_FORMAT_UNIT: + return scsi_format_cmd (udev, lun); + + case SCSI_READ_TOC_DATA: + return scsi_toc_cmd_read (udev, lun, params); + + case SCSI_MODE_SELECT6: + return scsi_mode_select6 (udev, lun, params); + + case SCSI_MODE_SELECT10: + return scsi_mode_select10 (udev, lun, params); + + default: + scsi_sense_code (udev, lun, ILLEGAL_REQUEST, INVALID_CDB); + return -1; + } +} + +/*! + \brief load the last error code in the error list + \param[in] udev: pointer to USB device instance + \param[in] lun: logical unit number + \param[in] skey: sense key + \param[in] asc: additional sense key + \param[out] none + \retval none +*/ +void scsi_sense_code (usb_core_driver *udev, uint8_t lun, uint8_t skey, uint8_t asc) +{ + usbd_msc_handler *msc = (usbd_msc_handler *)udev->dev.class_data[USBD_MSC_INTERFACE]; + + msc->scsi_sense[msc->scsi_sense_tail].SenseKey = skey; + msc->scsi_sense[msc->scsi_sense_tail].ASC = asc << 8U; + msc->scsi_sense_tail++; + + if (SENSE_LIST_DEEPTH == msc->scsi_sense_tail) { + msc->scsi_sense_tail = 0U; + } +} + +/*! + \brief process SCSI Test Unit Ready command + \param[in] udev: pointer to USB device instance + \param[in] lun: logical unit number + \param[in] params: command parameters + \param[out] none + \retval status +*/ +static int8_t scsi_test_unit_ready (usb_core_driver *udev, uint8_t lun, uint8_t *params) +{ + usbd_msc_handler *msc = (usbd_msc_handler *)udev->dev.class_data[USBD_MSC_INTERFACE]; + + /* case 9 : Hi > D0 */ + if (0U != msc->bbb_cbw.dCBWDataTransferLength) { + scsi_sense_code (udev, msc->bbb_cbw.bCBWLUN, ILLEGAL_REQUEST, INVALID_CDB); + + return -1; + } + + if (0 != usbd_mem_fops->mem_ready(lun)) { + scsi_sense_code(udev, lun, NOT_READY, MEDIUM_NOT_PRESENT); + + return -1; + } + + msc->bbb_datalen = 0U; + + return 0; +} + +/*! + \brief process Inquiry command + \param[in] udev: pointer to USB device instance + \param[in] lun: logical unit number + \param[in] params: command parameters + \param[out] none + \retval status +*/ +static int8_t scsi_mode_select6 (usb_core_driver *udev, uint8_t lun, uint8_t *params) +{ + usbd_msc_handler *msc = (usbd_msc_handler *)udev->dev.class_data[USBD_MSC_INTERFACE]; + + msc->bbb_datalen = 0U; + + return 0; +} + +/*! + \brief process Inquiry command + \param[in] udev: pointer to USB device instance + \param[in] lun: logical unit number + \param[in] params: command parameters + \param[out] none + \retval status +*/ +static int8_t scsi_mode_select10 (usb_core_driver *udev, uint8_t lun, uint8_t *params) +{ + usbd_msc_handler *msc = (usbd_msc_handler *)udev->dev.class_data[USBD_MSC_INTERFACE]; + + msc->bbb_datalen = 0U; + + return 0; +} + +/*! + \brief process Inquiry command + \param[in] udev: pointer to USB device instance + \param[in] lun: logical unit number + \param[in] params: command parameters + \param[out] none + \retval status +*/ +static int8_t scsi_inquiry (usb_core_driver *udev, uint8_t lun, uint8_t *params) +{ + uint8_t *page = NULL; + uint16_t len = 0U; + + usbd_msc_handler *msc = (usbd_msc_handler *)udev->dev.class_data[USBD_MSC_INTERFACE]; + + if (params[1] & 0x01U) { + /* Evpd is set */ + page = (uint8_t *)msc_page00_inquiry_data; + + len = INQUIRY_PAGE00_LENGTH; + } else { + page = (uint8_t *)usbd_mem_fops->mem_inquiry_data[lun]; + + len = (uint16_t)(page[4] + 5U); + + if (params[4] <= len) { + len = params[4]; + } + } + + msc->bbb_datalen = len; + + while (len) { + len--; + msc->bbb_data[len] = page[len]; + } + + return 0; +} + +/*! + \brief process Read Capacity 10 command + \param[in] udev: pointer to USB device instance + \param[in] lun: logical unit number + \param[in] params: command parameters + \param[out] none + \retval status +*/ +static int8_t scsi_read_capacity10 (usb_core_driver *udev, uint8_t lun, uint8_t *params) +{ + uint32_t blk_num = usbd_mem_fops->mem_block_len[lun] - 1U; + usbd_msc_handler *msc = (usbd_msc_handler *)udev->dev.class_data[USBD_MSC_INTERFACE]; + + msc->scsi_blk_nbr[lun] = usbd_mem_fops->mem_block_len[lun]; + msc->scsi_blk_size[lun] = usbd_mem_fops->mem_block_size[lun]; + + msc->bbb_data[0] = (uint8_t)(blk_num >> 24U); + msc->bbb_data[1] = (uint8_t)(blk_num >> 16U); + msc->bbb_data[2] = (uint8_t)(blk_num >> 8U); + msc->bbb_data[3] = (uint8_t)(blk_num); + + msc->bbb_data[4] = (uint8_t)(msc->scsi_blk_size[lun] >> 24U); + msc->bbb_data[5] = (uint8_t)(msc->scsi_blk_size[lun] >> 16U); + msc->bbb_data[6] = (uint8_t)(msc->scsi_blk_size[lun] >> 8U); + msc->bbb_data[7] = (uint8_t)(msc->scsi_blk_size[lun]); + + msc->bbb_datalen = 8U; + + return 0; +} + +/*! + \brief process Read Format Capacity command + \param[in] udev: pointer to USB device instance + \param[in] lun: logical unit number + \param[in] params: command parameters + \param[out] none + \retval status +*/ +static int8_t scsi_read_format_capacity (usb_core_driver *udev, uint8_t lun, uint8_t *params) +{ + uint16_t i = 0U; + uint32_t blk_size = usbd_mem_fops->mem_block_size[lun]; + uint32_t blk_num = usbd_mem_fops->mem_block_len[lun]; + uint32_t blk_nbr = blk_num - 1U; + + usbd_msc_handler *msc = (usbd_msc_handler *)udev->dev.class_data[USBD_MSC_INTERFACE]; + + for (i = 0U; i < 12U; i++) { + msc->bbb_data[i] = 0U; + } + + msc->bbb_data[3] = 0x08U; + msc->bbb_data[4] = (uint8_t)(blk_nbr >> 24U); + msc->bbb_data[5] = (uint8_t)(blk_nbr >> 16U); + msc->bbb_data[6] = (uint8_t)(blk_nbr >> 8U); + msc->bbb_data[7] = (uint8_t)(blk_nbr); + + msc->bbb_data[8] = 0x02U; + msc->bbb_data[9] = (uint8_t)(blk_size >> 16U); + msc->bbb_data[10] = (uint8_t)(blk_size >> 8U); + msc->bbb_data[11] = (uint8_t)(blk_size); + + msc->bbb_datalen = 12U; + + return 0; +} + +/*! + \brief process Mode Sense6 command + \param[in] udev: pointer to USB device instance + \param[in] lun: logical unit number + \param[in] params: command parameters + \param[out] none + \retval status +*/ +static int8_t scsi_mode_sense6 (usb_core_driver *udev, uint8_t lun, uint8_t *params) +{ + uint16_t len = 8U; + usbd_msc_handler *msc = (usbd_msc_handler *)udev->dev.class_data[USBD_MSC_INTERFACE]; + + msc->bbb_datalen = len; + + while (len) { + len--; + msc->bbb_data[len] = msc_mode_sense6_data[len]; + } + + return 0; +} + +/*! + \brief process Mode Sense10 command + \param[in] udev: pointer to USB device instance + \param[in] lun: logical unit number + \param[in] params: command parameters + \param[out] none + \retval status +*/ +static int8_t scsi_mode_sense10 (usb_core_driver *udev, uint8_t lun, uint8_t *params) +{ + uint16_t len = 8U; + usbd_msc_handler *msc = (usbd_msc_handler *)udev->dev.class_data[USBD_MSC_INTERFACE]; + + msc->bbb_datalen = len; + + while (len) { + len--; + msc->bbb_data[len] = msc_mode_sense10_data[len]; + } + + return 0; +} + +/*! + \brief process Request Sense command + \param[in] udev: pointer to USB device instance + \param[in] lun: logical unit number + \param[in] params: command parameters + \param[out] none + \retval status +*/ +static int8_t scsi_request_sense (usb_core_driver *udev, uint8_t lun, uint8_t *params) +{ + uint8_t i = 0U; + usbd_msc_handler *msc = (usbd_msc_handler *)udev->dev.class_data[USBD_MSC_INTERFACE]; + + for (i = 0U; i < REQUEST_SENSE_DATA_LEN; i++) { + msc->bbb_data[i] = 0U; + } + + msc->bbb_data[0] = 0x70U; + msc->bbb_data[7] = REQUEST_SENSE_DATA_LEN - 6U; + + if ((msc->scsi_sense_head != msc->scsi_sense_tail)) { + msc->bbb_data[2] = msc->scsi_sense[msc->scsi_sense_head].SenseKey; + msc->bbb_data[12] = msc->scsi_sense[msc->scsi_sense_head].ASCQ; + msc->bbb_data[13] = msc->scsi_sense[msc->scsi_sense_head].ASC; + msc->scsi_sense_head++; + + if (msc->scsi_sense_head == SENSE_LIST_DEEPTH) { + msc->scsi_sense_head = 0U; + } + } + + msc->bbb_datalen = USB_MIN(REQUEST_SENSE_DATA_LEN, params[4]); + + return 0; +} + +/*! + \brief process Start Stop Unit command + \param[in] udev: pointer to USB device instance + \param[in] lun: logical unit number + \param[in] params: command parameters + \param[out] none + \retval status +*/ +static inline int8_t scsi_start_stop_unit (usb_core_driver *udev, uint8_t lun, uint8_t *params) +{ + usbd_msc_handler *msc = (usbd_msc_handler *)udev->dev.class_data[USBD_MSC_INTERFACE]; + + msc->bbb_datalen = 0U; + msc->scsi_disk_pop = 1U; + + return 0; +} + +/*! + \brief process Allow Medium Removal command + \param[in] udev: pointer to USB device instance + \param[in] lun: logical unit number + \param[in] params: command parameters + \param[out] none + \retval status +*/ +static inline int8_t scsi_allow_medium_removal (usb_core_driver *udev, uint8_t lun, uint8_t *params) +{ + usbd_msc_handler *msc = (usbd_msc_handler *)udev->dev.class_data[USBD_MSC_INTERFACE]; + + msc->bbb_datalen = 0U; + + return 0; +} + +/*! + \brief process Read10 command + \param[in] udev: pointer to USB device instance + \param[in] lun: logical unit number + \param[in] params: command parameters + \param[out] none + \retval status +*/ +static int8_t scsi_read10 (usb_core_driver *udev, uint8_t lun, uint8_t *params) +{ + usbd_msc_handler *msc = (usbd_msc_handler *)udev->dev.class_data[USBD_MSC_INTERFACE]; + + if (msc->bbb_state == BBB_IDLE) { + /* direction is from device to host */ + if (0x80U != (msc->bbb_cbw.bmCBWFlags & 0x80U)) { + scsi_sense_code (udev, msc->bbb_cbw.bCBWLUN, ILLEGAL_REQUEST, INVALID_CDB); + + return -1; + } + + if (0 != usbd_mem_fops->mem_ready(lun)) { + scsi_sense_code (udev, lun, NOT_READY, MEDIUM_NOT_PRESENT); + + return -1; + } + + msc->scsi_blk_addr = (params[2] << 24U) | (params[3] << 16U) | \ + (params[4] << 8U) | params[5]; + + msc->scsi_blk_len = (params[7] << 8U) | params[8]; + + if (scsi_check_address_range (udev, lun, msc->scsi_blk_addr, (uint16_t)msc->scsi_blk_len) < 0) { + return -1; /* error */ + } + + msc->bbb_state = BBB_DATA_IN; + + msc->scsi_blk_addr *= msc->scsi_blk_size[lun]; + msc->scsi_blk_len *= msc->scsi_blk_size[lun]; + + /* cases 4,5 : Hi <> Dn */ + if (msc->bbb_cbw.dCBWDataTransferLength != msc->scsi_blk_len) { + scsi_sense_code (udev, msc->bbb_cbw.bCBWLUN, ILLEGAL_REQUEST, INVALID_CDB); + + return -1; + } + } + + msc->bbb_datalen = MSC_MEDIA_PACKET_SIZE; + + return scsi_process_read (udev, lun); +} + +/*! + \brief process Write10 command + \param[in] udev: pointer to USB device instance + \param[in] lun: logical unit number + \param[in] params: command parameters + \param[out] none + \retval status +*/ +static int8_t scsi_write10 (usb_core_driver *udev, uint8_t lun, uint8_t *params) +{ + usbd_msc_handler *msc = (usbd_msc_handler *)udev->dev.class_data[USBD_MSC_INTERFACE]; + + if (BBB_IDLE == msc->bbb_state) { + /* case 8 : Hi <> Do */ + if (0x80U == (msc->bbb_cbw.bmCBWFlags & 0x80U)) { + scsi_sense_code (udev, msc->bbb_cbw.bCBWLUN, ILLEGAL_REQUEST, INVALID_CDB); + + return -1; + } + + /* check whether media is ready */ + if (0 != usbd_mem_fops->mem_ready(lun)) { + scsi_sense_code (udev, lun, NOT_READY, MEDIUM_NOT_PRESENT); + + return -1; + } + + /* check if media is write-protected */ + if (0 != usbd_mem_fops->mem_protected(lun)) { + scsi_sense_code (udev, lun, NOT_READY, WRITE_PROTECTED); + + return -1; + } + + msc->scsi_blk_addr = (params[2] << 24U) | (params[3] << 16U) | \ + (params[4] << 8U) | params[5]; + + msc->scsi_blk_len = (params[7] << 8U) | params[8]; + + /* check if LBA address is in the right range */ + if (scsi_check_address_range (udev, lun, msc->scsi_blk_addr, (uint16_t)msc->scsi_blk_len) < 0) { + return -1; /* error */ + } + + msc->scsi_blk_addr *= msc->scsi_blk_size[lun]; + msc->scsi_blk_len *= msc->scsi_blk_size[lun]; + + /* cases 3,11,13 : Hn,Ho <> D0 */ + if (msc->bbb_cbw.dCBWDataTransferLength != msc->scsi_blk_len) { + scsi_sense_code (udev, msc->bbb_cbw.bCBWLUN, ILLEGAL_REQUEST, INVALID_CDB); + + return -1; + } + + /* prepare endpoint to receive first data packet */ + msc->bbb_state = BBB_DATA_OUT; + + usbd_ep_recev (udev, + MSC_OUT_EP, + msc->bbb_data, + USB_MIN (msc->scsi_blk_len, MSC_MEDIA_PACKET_SIZE)); + } else { /* write process ongoing */ + return scsi_process_write (udev, lun); + } + + return 0; +} + +/*! + \brief process Verify10 command + \param[in] udev: pointer to USB device instance + \param[in] lun: logical unit number + \param[in] params: command parameters + \param[out] none + \retval status +*/ +static int8_t scsi_verify10 (usb_core_driver *udev, uint8_t lun, uint8_t *params) +{ + usbd_msc_handler *msc = (usbd_msc_handler *)udev->dev.class_data[USBD_MSC_INTERFACE]; + + if (0x02U == (params[1] & 0x02U)) { + scsi_sense_code (udev, lun, ILLEGAL_REQUEST, INVALID_FIELED_IN_COMMAND); + + return -1; /* error, verify mode not supported*/ + } + + if (scsi_check_address_range (udev, lun, msc->scsi_blk_addr, (uint16_t)msc->scsi_blk_len) < 0) { + return -1; /* error */ + } + + msc->bbb_datalen = 0U; + + return 0; +} + +/*! + \brief check address range + \param[in] udev: pointer to USB device instance + \param[in] lun: logical unit number + \param[in] blk_offset: block offset + \param[in] blk_nbr: number of block to be processed + \param[out] none + \retval status +*/ +static inline int8_t scsi_check_address_range (usb_core_driver *udev, uint8_t lun, uint32_t blk_offset, uint16_t blk_nbr) +{ + usbd_msc_handler *msc = (usbd_msc_handler *)udev->dev.class_data[USBD_MSC_INTERFACE]; + + if ((blk_offset + blk_nbr) > msc->scsi_blk_nbr[lun]) { + scsi_sense_code (udev, lun, ILLEGAL_REQUEST, ADDRESS_OUT_OF_RANGE); + + return -1; + } + + return 0; +} + +/*! + \brief handle read process + \param[in] udev: pointer to USB device instance + \param[in] lun: logical unit number + \param[out] none + \retval status +*/ +static int8_t scsi_process_read (usb_core_driver *udev, uint8_t lun) +{ + usbd_msc_handler *msc = (usbd_msc_handler *)udev->dev.class_data[USBD_MSC_INTERFACE]; + + uint32_t len = USB_MIN(msc->scsi_blk_len, MSC_MEDIA_PACKET_SIZE); + + if (usbd_mem_fops->mem_read(lun, + msc->bbb_data, + msc->scsi_blk_addr, + (uint16_t)(len / msc->scsi_blk_size[lun])) < 0) { + scsi_sense_code(udev, lun, HARDWARE_ERROR, UNRECOVERED_READ_ERROR); + + return -1; + } + + usbd_ep_send (udev, MSC_IN_EP, msc->bbb_data, len); + + msc->scsi_blk_addr += len; + msc->scsi_blk_len -= len; + + /* case 6 : Hi = Di */ + msc->bbb_csw.dCSWDataResidue -= len; + + if (0U == msc->scsi_blk_len) { + msc->bbb_state = BBB_LAST_DATA_IN; + } + + return 0; +} + +/*! + \brief handle write process + \param[in] udev: pointer to USB device instance + \param[in] lun: logical unit number + \param[out] none + \retval status +*/ +static int8_t scsi_process_write (usb_core_driver *udev, uint8_t lun) +{ + usbd_msc_handler *msc = (usbd_msc_handler *)udev->dev.class_data[USBD_MSC_INTERFACE]; + + uint32_t len = USB_MIN(msc->scsi_blk_len, MSC_MEDIA_PACKET_SIZE); + + if (usbd_mem_fops->mem_write (lun, + msc->bbb_data, + msc->scsi_blk_addr, + (uint16_t)(len / msc->scsi_blk_size[lun])) < 0) { + scsi_sense_code(udev, lun, HARDWARE_ERROR, WRITE_FAULT); + + return -1; + } + + msc->scsi_blk_addr += len; + msc->scsi_blk_len -= len; + + /* case 12 : Ho = Do */ + msc->bbb_csw.dCSWDataResidue -= len; + + if (0U == msc->scsi_blk_len) { + msc_bbb_csw_send (udev, CSW_CMD_PASSED); + } else { + /* prepare endpoint to receive next packet */ + usbd_ep_recev (udev, + MSC_OUT_EP, + msc->bbb_data, + USB_MIN (msc->scsi_blk_len, MSC_MEDIA_PACKET_SIZE)); + } + + return 0; +} + +/*! + \brief process Format Unit command + \param[in] udev: pointer to USB device instance + \param[in] lun: logical unit number + \param[out] none + \retval status +*/ +static inline int8_t scsi_format_cmd (usb_core_driver *udev, uint8_t lun) +{ + return 0; +} + +/*! + \brief process Read_Toc command + \param[in] udev: pointer to USB device instance + \param[in] lun: logical unit number + \param[in] params: command parameters + \param[out] none + \retval status +*/ +static int8_t scsi_toc_cmd_read (usb_core_driver *udev, uint8_t lun, uint8_t *params) +{ + uint8_t* pPage; + uint16_t len; + + usbd_msc_handler *msc = (usbd_msc_handler *)udev->dev.class_data[USBD_MSC_INTERFACE]; + + pPage = (uint8_t *)&usbd_mem_fops->mem_toc_data[lun * READ_TOC_CMD_LEN]; + len = (uint16_t)pPage[1] + 2U; + + msc->bbb_datalen = len; + + while (len) { + len--; + msc->bbb_data[len] = pPage[len]; + } + + return 0; +} diff --git a/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/device/class/printer/Include/printer_core.h b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/device/class/printer/Include/printer_core.h new file mode 100644 index 0000000000..0bc192d608 --- /dev/null +++ b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/device/class/printer/Include/printer_core.h @@ -0,0 +1,78 @@ +/*! + \file printer_core.h + \brief the header file of USB printer device class core functions + + \version 2020-07-28, V3.0.0, firmware for GD32F20x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef __PRINTER_CORE_H +#define __PRINTER_CORE_H + +#include "usbd_enum.h" +#include "usb_ch9_std.h" + +/* USB printing device class code */ +#define USB_CLASS_PRINTER 0x07U + +/* printing device subclass code */ +#define USB_SUBCLASS_PRINTER 0x01U + +/* printing device protocol code */ +#define PROTOCOL_UNIDIRECTIONAL_ITF 0x01U +#define PROTOCOL_BI_DIRECTIONAL_ITF 0x02U +#define PROTOCOL_1284_4_ITF 0x03U +#define PROTOCOL_VENDOR 0xFFU + +#define DEVICE_ID_LEN 103U + +#define USB_PRINTER_CONFIG_DESC_LEN 32U + +/* printing device specific-class request */ +#define GET_DEVICE_ID 0x00U +#define GET_PORT_STATUS 0x01U +#define SOFT_RESET 0x02U + +#pragma pack(1) + +/* USB configuration descriptor structure */ +typedef struct +{ + usb_desc_config config; + usb_desc_itf printer_itf; + usb_desc_ep printer_epin; + usb_desc_ep printer_epout; +} usb_printer_desc_config_set; + +#pragma pack() + +extern usb_desc printer_desc; +extern usb_class_core usbd_printer_cb; + +#endif /* __PRINTER_CORE_H */ diff --git a/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/device/class/printer/Source/printer_core.c b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/device/class/printer/Source/printer_core.c new file mode 100644 index 0000000000..b023f4e0e8 --- /dev/null +++ b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/device/class/printer/Source/printer_core.c @@ -0,0 +1,310 @@ +/*! + \file printer_core.c + \brief USB printer device class core functions + + \version 2020-07-28, V3.0.0, firmware for GD32F20x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "printer_core.h" + +#define USBD_VID 0x28E9U +#define USBD_PID 0x028DU + +/* printer port status: paper not empty/selected/no error */ +static uint8_t g_port_status = 0x18U; + +uint8_t g_printer_data_buf[PRINTER_OUT_PACKET]; + +uint8_t PRINTER_DEVICE_ID[DEVICE_ID_LEN] = +{ + 0x00, 0x67, + 'M', 'A', 'N', 'U', 'F', 'A', 'C', 'T', 'U', 'R', 'E', 'R', ':', + 'G', 'I', 'G', 'A', ' ', 'D', 'E', 'V', 'I', 'C', 'E', '-', ';', + 'C', 'O', 'M', 'M', 'A', 'N', 'D', ' ', 'S', 'E', 'T', ':', + 'P', 'C', 'L', ',', 'M', 'P', 'L', ';', + 'M', 'O', 'D', 'E', 'L', ':', + 'L', 'a', 's', 'e', 'r', 'B', 'e', 'a', 'm', '?', ';', + 'C', 'O', 'M', 'M', 'E', 'N', 'T', ':', + 'G', 'o', 'o', 'd', ' ', '!', ';', + 'A', 'C', 'T', 'I', 'V', 'E', ' ', 'C', 'O', 'M', 'M', 'A', 'N', 'D', ' ', 'S', 'E', 'T', ':', + 'P', 'C', 'L', ';' +}; + +/* USB standard device descriptor */ +const usb_desc_dev printer_dev_desc = +{ + .header = + { + .bLength = USB_DEV_DESC_LEN, + .bDescriptorType = USB_DESCTYPE_DEV, + }, + .bcdUSB = 0x0200U, + .bDeviceClass = 0x00U, + .bDeviceSubClass = 0x00U, + .bDeviceProtocol = 0x00U, + .bMaxPacketSize0 = USB_FS_EP0_MAX_LEN, + .idVendor = USBD_VID, + .idProduct = USBD_PID, + .bcdDevice = 0x0100U, + .iManufacturer = STR_IDX_MFC, + .iProduct = STR_IDX_PRODUCT, + .iSerialNumber = STR_IDX_SERIAL, + .bNumberConfigurations = USBD_CFG_MAX_NUM, +}; + +/* USB device configuration descriptor */ +const usb_printer_desc_config_set printer_config_desc = +{ + .config = + { + .header = + { + .bLength = sizeof(usb_desc_config), + .bDescriptorType = USB_DESCTYPE_CONFIG + }, + .wTotalLength = USB_PRINTER_CONFIG_DESC_LEN, + .bNumInterfaces = 0x01U, + .bConfigurationValue = 0x01U, + .iConfiguration = 0x00U, + .bmAttributes = 0xA0U, + .bMaxPower = 0x32U + }, + + .printer_itf = + { + .header = + { + .bLength = sizeof(usb_desc_itf), + .bDescriptorType = USB_DESCTYPE_ITF + }, + .bInterfaceNumber = 0x00U, + .bAlternateSetting = 0x00U, + .bNumEndpoints = 0x02U, + .bInterfaceClass = USB_CLASS_PRINTER, + .bInterfaceSubClass = USB_SUBCLASS_PRINTER, + .bInterfaceProtocol = PROTOCOL_BI_DIRECTIONAL_ITF, + .iInterface = 0x00U + }, + + .printer_epin = + { + .header = + { + .bLength = sizeof(usb_desc_ep), + .bDescriptorType = USB_DESCTYPE_EP + }, + .bEndpointAddress = PRINTER_IN_EP, + .bmAttributes = USB_EP_ATTR_BULK, + .wMaxPacketSize = PRINTER_IN_PACKET, + .bInterval = 0x00U + }, + + .printer_epout = + { + .header = + { + .bLength = sizeof(usb_desc_ep), + .bDescriptorType = USB_DESCTYPE_EP + }, + .bEndpointAddress = PRINTER_OUT_EP, + .bmAttributes = USB_EP_ATTR_BULK, + .wMaxPacketSize = PRINTER_OUT_PACKET, + .bInterval = 0x00U + }, +}; + +/* USB language ID Descriptor */ +static const usb_desc_LANGID usbd_language_id_desc = +{ + .header = + { + .bLength = sizeof(usb_desc_LANGID), + .bDescriptorType = USB_DESCTYPE_STR, + }, + .wLANGID = ENG_LANGID +}; + +/* USB manufacture string */ +static const usb_desc_str manufacturer_string = +{ + .header = + { + .bLength = USB_STRING_LEN(10U), + .bDescriptorType = USB_DESCTYPE_STR, + }, + .unicode_string = {'G', 'i', 'g', 'a', 'D', 'e', 'v', 'i', 'c', 'e'} +}; + +/* USB product string */ +static const usb_desc_str product_string = +{ + .header = + { + .bLength = USB_STRING_LEN(16U), + .bDescriptorType = USB_DESCTYPE_STR, + }, + .unicode_string = {'G', 'D', '3', '2', '-', 'U', 'S', 'B', '_', 'P', 'r', 'i', 'n', 't', 'e', 'r'} +}; + +/* USBD serial string */ +static usb_desc_str serial_string = +{ + .header = + { + .bLength = USB_STRING_LEN(12U), + .bDescriptorType = USB_DESCTYPE_STR, + } +}; + +/* USB string descriptor */ +static void *const usbd_msc_strings[] = +{ + [STR_IDX_LANGID] = (uint8_t *)&usbd_language_id_desc, + [STR_IDX_MFC] = (uint8_t *)&manufacturer_string, + [STR_IDX_PRODUCT] = (uint8_t *)&product_string, + [STR_IDX_SERIAL] = (uint8_t *)&serial_string +}; + +usb_desc printer_desc = { + .dev_desc = (uint8_t *)&printer_dev_desc, + .config_desc = (uint8_t *)&printer_config_desc, + .strings = usbd_msc_strings +}; + +/* local function prototypes ('static') */ +static uint8_t printer_init (usb_dev *udev, uint8_t config_index); +static uint8_t printer_deinit (usb_dev *udev, uint8_t config_index); +static uint8_t printer_req (usb_dev *udev, usb_req *req); +static uint8_t printer_in (usb_dev *udev, uint8_t ep_num); +static uint8_t printer_out (usb_dev *udev, uint8_t ep_num); + +usb_class_core usbd_printer_cb = { + .init = printer_init, + .deinit = printer_deinit, + + .req_proc = printer_req, + + .data_in = printer_in, + .data_out = printer_out +}; + +/*! + \brief initialize the printer device + \param[in] udev: pointer to usb device instance + \param[in] config_index: configuration index + \param[out] none + \retval usb device operation status +*/ +static uint8_t printer_init (usb_dev *udev, uint8_t config_index) +{ + /* initialize the data Tx endpoint */ + usbd_ep_setup (udev, &(printer_config_desc.printer_epin)); + + /* initialize the data Rx endpoint */ + usbd_ep_setup (udev, &(printer_config_desc.printer_epout)); + + /* prepare to receive data */ + usbd_ep_recev(udev, PRINTER_OUT_EP, g_printer_data_buf, PRINTER_OUT_PACKET); + + return USBD_OK; +} + +/*! + \brief deinitialize the printer device + \param[in] udev: pointer to usb device instance + \param[in] config_index: configuration index + \param[out] none + \retval usb device operation status +*/ +static uint8_t printer_deinit (usb_dev *udev, uint8_t config_index) +{ + /* deinitialize the data Tx/Rx endpoint */ + usbd_ep_clear (udev, PRINTER_IN_EP); + usbd_ep_clear (udev, PRINTER_OUT_EP); + + return USBD_OK; +} + +/*! + \brief handle the printer class-specific requests + \param[in] udev: pointer to usb device instance + \param[in] req: device class-specific request + \param[out] none + \retval usb device operation status +*/ +static uint8_t printer_req(usb_dev *udev, usb_req *req) +{ + usb_transc *transc = &udev->dev.transc_in[0]; + + switch (req->bRequest) { + case GET_DEVICE_ID: + transc->xfer_buf = (uint8_t *)PRINTER_DEVICE_ID; + transc->remain_len = DEVICE_ID_LEN; + break; + + case GET_PORT_STATUS: + transc->xfer_buf = (uint8_t *)&g_port_status; + transc->remain_len = 1U; + break; + + case SOFT_RESET: + usbd_ep_recev(udev, PRINTER_OUT_EP, g_printer_data_buf, PRINTER_OUT_PACKET); + break; + + default: + return USBD_FAIL; + } + + return USBD_OK; +} + +/*! + \brief handle printer data + \param[in] udev: pointer to USB device instance + \param[in] ep_num: endpoint number + \param[out] none + \retval USB device operation status +*/ +static uint8_t printer_in (usb_dev *udev, uint8_t ep_num) +{ + return USBD_OK; +} + +/*! + \brief handle printer data + \param[in] udev: pointer to USB device instance + \param[in] ep_num: endpoint number + \param[out] none + \retval USB device operation status +*/ +static uint8_t printer_out (usb_dev *udev, uint8_t ep_num) +{ + return USBD_OK; +} diff --git a/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/device/core/Include/usbd_core.h b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/device/core/Include/usbd_core.h new file mode 100644 index 0000000000..a3df6e8fbd --- /dev/null +++ b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/device/core/Include/usbd_core.h @@ -0,0 +1,103 @@ +/*! + \file usbd_core.h + \brief USB device mode core functions prototype + + \version 2020-07-28, V3.0.0, firmware for GD32F20x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef __USBD_CORE_H +#define __USBD_CORE_H + +#include "drv_usb_core.h" +#include "drv_usb_dev.h" + +typedef enum +{ + USBD_OK = 0U, /*!< status OK */ + USBD_BUSY, /*!< status busy */ + USBD_FAIL, /*!< status fail */ +} usbd_status; + +enum _usbd_status { + USBD_DEFAULT = 1U, /*!< default status */ + USBD_ADDRESSED = 2U, /*!< address send status */ + USBD_CONFIGURED = 3U, /*!< configured status */ + USBD_SUSPENDED = 4U /*!< suspended status */ +}; + +/* static inline function definitions */ + +/*! + \brief set USB device address + \param[in] udev: pointer to USB core instance + \param[in] addr: device address to set + \param[out] none + \retval none +*/ +__STATIC_INLINE void usbd_addr_set (usb_core_driver *udev, uint8_t addr) +{ + usb_devaddr_set(udev, addr); +} + +/*! + \brief get the received data length + \param[in] udev: pointer to USB device instance + \param[in] ep_num: endpoint number + \param[out] none + \retval USB device operation cur_status +*/ +__STATIC_INLINE uint16_t usbd_rxcount_get (usb_core_driver *udev, uint8_t ep_num) +{ + return (uint16_t)udev->dev.transc_out[ep_num].xfer_count; +} + +/* function declarations */ +/* initializes the USB device-mode stack and load the class driver */ +void usbd_init (usb_core_driver *udev, usb_core_enum core, usb_desc *desc, usb_class_core *class_core); +/* endpoint initialization */ +uint32_t usbd_ep_setup (usb_core_driver *udev, const usb_desc_ep *ep_desc); +/* configure the endpoint when it is disabled */ +uint32_t usbd_ep_clear (usb_core_driver *udev, uint8_t ep_addr); +/* endpoint prepare to receive data */ +uint32_t usbd_ep_recev (usb_core_driver *udev, uint8_t ep_addr, uint8_t *pbuf, uint32_t len); +/* endpoint prepare to transmit data */ +uint32_t usbd_ep_send (usb_core_driver *udev, uint8_t ep_addr, uint8_t *pbuf, uint32_t len); +/* set an endpoint to STALL status */ +uint32_t usbd_ep_stall (usb_core_driver *udev, uint8_t ep_addr); +/* clear endpoint STALLed status */ +uint32_t usbd_ep_stall_clear (usb_core_driver *udev, uint8_t ep_addr); +/* flush the endpoint FIFOs */ +uint32_t usbd_fifo_flush (usb_core_driver *udev, uint8_t ep_addr); +/* device connect */ +void usbd_connect (usb_core_driver *udev); +/* device disconnect */ +void usbd_disconnect (usb_core_driver *udev); + +#endif /* __USBD_CORE_H */ diff --git a/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/device/core/Include/usbd_enum.h b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/device/core/Include/usbd_enum.h new file mode 100644 index 0000000000..f01202a773 --- /dev/null +++ b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/device/core/Include/usbd_enum.h @@ -0,0 +1,105 @@ +/*! + \file usbd_enum.h + \brief USB enumeration definitions + + \version 2020-07-28, V3.0.0, firmware for GD32F20x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef __USBD_ENUM_H +#define __USBD_ENUM_H + +#include "usbd_core.h" +#include "usbd_conf.h" +#include + +#ifndef NULL + #define NULL 0U +#endif + +typedef enum _usb_reqsta { + REQ_SUPP = 0x0U, /* request support */ + REQ_NOTSUPP = 0x1U, /* request not support */ +} usb_reqsta; + +/* string descriptor index */ +enum _str_index +{ + STR_IDX_LANGID = 0x0U, /* language ID string index */ + STR_IDX_MFC = 0x1U, /* manufacturer string index */ + STR_IDX_PRODUCT = 0x2U, /* product string index */ + STR_IDX_SERIAL = 0x3U, /* serial string index */ + STR_IDX_CONFIG = 0x4U, /* configuration string index */ + STR_IDX_ITF = 0x5U, /* interface string index */ +#ifndef WINUSB_EXEMPT_DRIVER + STR_IDX_MAX = 0x6U, /* string maximum index */ +#else + STR_IDX_MAX = 0xEFU, /* string maximum index */ +#endif /* WINUSB_EXEMPT_DRIVER */ +}; + +typedef enum _usb_pwrsta { + USB_PWRSTA_SELF_POWERED = 0x1U, /* USB is in self powered status */ + USB_PWRSTA_REMOTE_WAKEUP = 0x2U, /* USB is in remote wakeup status */ +} usb_pwrsta; + +typedef enum _usb_feature +{ + USB_FEATURE_EP_HALT = 0x0U, /* USB has endpoint halt feature */ + USB_FEATURE_REMOTE_WAKEUP = 0x1U, /* USB has endpoint remote wakeup feature */ + USB_FEATURE_TEST_MODE = 0x2U, /* USB has endpoint test mode feature */ +} usb_feature; + +#define ENG_LANGID 0x0409U /* english language ID */ +#define CHN_LANGID 0x0804U /* chinese language ID */ + +/* USB device exported macros */ +#define CTL_EP(ep) (((ep) == 0x00U) || ((ep) == 0x80U)) + +#define DEVICE_ID1 (0x1FFFF7E8U) /* device ID1 */ +#define DEVICE_ID2 (0x1FFFF7ECU) /* device ID2 */ +#define DEVICE_ID3 (0x1FFFF7F0U) /* device ID3 */ + +#define DEVICE_ID (0x40022100U) + +/* function declarations */ +/* handle USB standard device request */ +usb_reqsta usbd_standard_request (usb_core_driver *udev, usb_req *req); +/* handle USB device class request */ +usb_reqsta usbd_class_request (usb_core_driver *udev, usb_req *req); +/* handle USB vendor request */ +usb_reqsta usbd_vendor_request (usb_core_driver *udev, usb_req *req); +/* handle USB enumeration error */ +void usbd_enum_error (usb_core_driver *udev, usb_req *req); +/* convert hex 32bits value into unicode char */ +void int_to_unicode (uint32_t value, uint8_t *pbuf, uint8_t len); +/* get serial string */ +void serial_string_get (uint16_t *unicode_str); + +#endif /* __USBD_ENUM_H */ diff --git a/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/device/core/Include/usbd_transc.h b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/device/core/Include/usbd_transc.h new file mode 100644 index 0000000000..f8e2c8201a --- /dev/null +++ b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/device/core/Include/usbd_transc.h @@ -0,0 +1,56 @@ +/*! + \file usbd_transc.h + \brief USB transaction core functions prototype + + \version 2020-07-28, V3.0.0, firmware for GD32F20x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef __USBD_TRANSC_H +#define __USBD_TRANSC_H + +#include "usbd_core.h" + +/* function declarations */ +/* USB send data in the control transaction */ +usbd_status usbd_ctl_send (usb_core_driver *udev); +/* USB receive data in control transaction */ +usbd_status usbd_ctl_recev (usb_core_driver *udev); +/* USB send control transaction status */ +usbd_status usbd_ctl_status_send (usb_core_driver *udev); +/* USB control receive status */ +usbd_status usbd_ctl_status_recev (usb_core_driver *udev); +/* USB setup stage processing */ +uint8_t usbd_setup_transc (usb_core_driver *udev); +/* data out stage processing */ +uint8_t usbd_out_transc (usb_core_driver *udev, uint8_t ep_num); +/* data in stage processing */ +uint8_t usbd_in_transc (usb_core_driver *udev, uint8_t ep_num); + +#endif /* __USBD_TRANSC_H */ diff --git a/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/device/core/Source/usbd_core.c b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/device/core/Source/usbd_core.c new file mode 100644 index 0000000000..5daee80d2d --- /dev/null +++ b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/device/core/Source/usbd_core.c @@ -0,0 +1,320 @@ +/*! + \file usbd_core.c + \brief USB device mode core functions + + \version 2020-07-28, V3.0.0, firmware for GD32F20x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "usbd_core.h" +#include "usbd_enum.h" +#include "drv_usb_hw.h" + +/* endpoint type */ +const uint32_t ep_type[] = { + [USB_EP_ATTR_CTL] = (uint32_t)USB_EPTYPE_CTRL, + [USB_EP_ATTR_BULK] = (uint32_t)USB_EPTYPE_BULK, + [USB_EP_ATTR_INT] = (uint32_t)USB_EPTYPE_INTR, + [USB_EP_ATTR_ISO] = (uint32_t)USB_EPTYPE_ISOC +}; + +/*! + \brief initializes the USB device-mode stack and load the class driver + \param[in] udev: pointer to USB core instance + \param[in] core: USB core type + \param[in] desc: pointer to USB descriptor + \param[in] class_core: class driver + \param[out] none + \retval none +*/ +void usbd_init (usb_core_driver *udev, usb_core_enum core, usb_desc *desc, usb_class_core *class_core) +{ + udev->dev.desc = desc; + + /* class callbacks */ + udev->dev.class_core = class_core; + + /* create serial string */ + serial_string_get(udev->dev.desc->strings[STR_IDX_SERIAL]); + + /* configure USB capabilities */ + (void)usb_basic_init (&udev->bp, &udev->regs, core); + + usb_globalint_disable(&udev->regs); + + /* initializes the USB core*/ + (void)usb_core_init (udev->bp, &udev->regs); + + /* set device disconnect */ + usbd_disconnect (udev); + +#ifndef USE_OTG_MODE + usb_curmode_set(&udev->regs, DEVICE_MODE); +#endif + + /* initializes device mode */ + (void)usb_devcore_init (udev); + + usb_globalint_enable(&udev->regs); + + /* set device connect */ + usbd_connect (udev); + + udev->dev.cur_status = (uint8_t)USBD_DEFAULT; +} + +/*! + \brief endpoint initialization + \param[in] udev: pointer to USB core instance + \param[in] ep_desc: pointer to endpoint descriptor + \param[out] none + \retval none +*/ +uint32_t usbd_ep_setup (usb_core_driver *udev, const usb_desc_ep *ep_desc) +{ + usb_transc *transc; + + uint8_t ep_addr = ep_desc->bEndpointAddress; + uint16_t max_len = ep_desc->wMaxPacketSize; + + /* set endpoint direction */ + if (EP_DIR(ep_addr)) { + transc = &udev->dev.transc_in[EP_ID(ep_addr)]; + + transc->ep_addr.dir = 1U; + } else { + transc = &udev->dev.transc_out[ep_addr]; + + transc->ep_addr.dir = 0U; + } + + transc->ep_addr.num = EP_ID(ep_addr); + transc->max_len = max_len; + transc->ep_type = (uint8_t)ep_type[ep_desc->bmAttributes & (uint8_t)USB_EPTYPE_MASK]; + + /* active USB endpoint function */ + (void)usb_transc_active (udev, transc); + + return 0U; +} + +/*! + \brief configure the endpoint when it is disabled + \param[in] udev: pointer to USB core instance + \param[in] ep_addr: endpoint address + in this parameter: + bit0..bit6: endpoint number (0..7) + bit7: endpoint direction which can be IN(1) or OUT(0) + \param[out] none + \retval none +*/ +uint32_t usbd_ep_clear (usb_core_driver *udev, uint8_t ep_addr) +{ + usb_transc *transc; + + if (EP_DIR(ep_addr)) { + transc = &udev->dev.transc_in[EP_ID(ep_addr)]; + } else { + transc = &udev->dev.transc_out[ep_addr]; + } + + /* deactivate USB endpoint function */ + (void)usb_transc_deactivate (udev, transc); + + return 0U; +} + +/*! + \brief endpoint prepare to receive data + \param[in] udev: pointer to USB core instance + \param[in] ep_addr: endpoint address + in this parameter: + bit0..bit6: endpoint number (0..7) + bit7: endpoint direction which can be IN(1) or OUT(0) + \param[in] pbuf: user buffer address pointer + \param[in] len: buffer length + \param[out] none + \retval none +*/ +uint32_t usbd_ep_recev (usb_core_driver *udev, uint8_t ep_addr, uint8_t *pbuf, uint32_t len) +{ + usb_transc *transc = &udev->dev.transc_out[EP_ID(ep_addr)]; + + /* setup the transfer */ + transc->xfer_buf = pbuf; + transc->xfer_len = len; + transc->xfer_count = 0U; + + if ((uint8_t)USB_USE_DMA == udev->bp.transfer_mode) { + transc->dma_addr = (uint32_t)pbuf; + } + + /* start the transfer */ + (void)usb_transc_outxfer (udev, transc); + + return 0U; +} + +/*! + \brief endpoint prepare to transmit data + \param[in] udev: pointer to USB core instance + \param[in] ep_addr: endpoint address + in this parameter: + bit0..bit6: endpoint number (0..7) + bit7: endpoint direction which can be IN(1) or OUT(0) + \param[in] pbuf: transmit buffer address pointer + \param[in] len: buffer length + \param[out] none + \retval none +*/ +uint32_t usbd_ep_send (usb_core_driver *udev, uint8_t ep_addr, uint8_t *pbuf, uint32_t len) +{ + usb_transc *transc = &udev->dev.transc_in[EP_ID(ep_addr)]; + + /* setup the transfer */ + transc->xfer_buf = pbuf; + transc->xfer_len = len; + transc->xfer_count = 0U; + + if ((uint8_t)USB_USE_DMA == udev->bp.transfer_mode) { + transc->dma_addr = (uint32_t)pbuf; + } + + /* start the transfer */ + (void)usb_transc_inxfer (udev, transc); + + return 0U; +} + +/*! + \brief set an endpoint to STALL status + \param[in] udev: pointer to USB core instance + \param[in] ep_addr: endpoint address + in this parameter: + bit0..bit6: endpoint number (0..7) + bit7: endpoint direction which can be IN(1) or OUT(0) + \param[out] none + \retval none +*/ +uint32_t usbd_ep_stall (usb_core_driver *udev, uint8_t ep_addr) +{ + usb_transc *transc = NULL; + + if (EP_DIR(ep_addr)) { + transc = &udev->dev.transc_in[EP_ID(ep_addr)]; + } else { + transc = &udev->dev.transc_out[ep_addr]; + } + + transc->ep_stall = 1U; + + (void)usb_transc_stall (udev, transc); + + return (0U); +} + +/*! + \brief clear endpoint STALLed status + \param[in] udev: pointer to usb core instance + \param[in] ep_addr: endpoint address + in this parameter: + bit0..bit6: endpoint number (0..7) + bit7: endpoint direction which can be IN(1) or OUT(0) + \param[out] none + \retval none +*/ +uint32_t usbd_ep_stall_clear (usb_core_driver *udev, uint8_t ep_addr) +{ + usb_transc *transc = NULL; + + if (EP_DIR(ep_addr)) { + transc = &udev->dev.transc_in[EP_ID(ep_addr)]; + } else { + transc = &udev->dev.transc_out[ep_addr]; + } + + transc->ep_stall = 0U; + + (void)usb_transc_clrstall (udev, transc); + + return (0U); +} + +/*! + \brief flush the endpoint FIFOs + \param[in] udev: pointer to USB core instance + \param[in] ep_addr: endpoint address + in this parameter: + bit0..bit6: endpoint number (0..7) + bit7: endpoint direction which can be IN(1) or OUT(0) + \param[out] none + \retval none +*/ +uint32_t usbd_fifo_flush (usb_core_driver *udev, uint8_t ep_addr) +{ + if (EP_DIR(ep_addr)) { + (void)usb_txfifo_flush (&udev->regs, EP_ID(ep_addr)); + } else { + (void)usb_rxfifo_flush (&udev->regs); + } + + return (0U); +} + +/*! + \brief device connect + \param[in] udev: pointer to USB device instance + \param[out] none + \retval none +*/ +void usbd_connect (usb_core_driver *udev) +{ +#ifndef USE_OTG_MODE + /* connect device */ + usb_dev_connect (udev); + + usb_mdelay(3U); +#endif /* USE_OTG_MODE */ +} + +/*! + \brief device disconnect + \param[in] udev: pointer to USB device instance + \param[out] none + \retval none +*/ +void usbd_disconnect (usb_core_driver *udev) +{ +#ifndef USE_OTG_MODE + /* disconnect device for 3ms */ + usb_dev_disconnect (udev); + + usb_mdelay(3U); +#endif /* USE_OTG_MODE */ +} diff --git a/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/device/core/Source/usbd_enum.c b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/device/core/Source/usbd_enum.c new file mode 100644 index 0000000000..68526e445e --- /dev/null +++ b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/device/core/Source/usbd_enum.c @@ -0,0 +1,764 @@ +/*! + \file usbd_enum.c + \brief USB enumeration function + + \version 2020-07-28, V3.0.0, firmware for GD32F20x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "usbd_enum.h" +#include "usb_ch9_std.h" + +#ifdef WINUSB_EXEMPT_DRIVER + +extern usbd_status usbd_OEM_req(usb_dev *udev, usb_req *req); + +#endif /* WINUSB_EXEMPT_DRIVER */ + +/* local function prototypes ('static') */ +static usb_reqsta _usb_std_reserved (usb_core_driver *udev, usb_req *req); +static uint8_t* _usb_dev_desc_get (usb_core_driver *udev, uint8_t index, uint16_t *len); +static uint8_t* _usb_config_desc_get (usb_core_driver *udev, uint8_t index, uint16_t *len); +static uint8_t* _usb_bos_desc_get (usb_core_driver *udev, uint8_t index, uint16_t *len); +static uint8_t* _usb_str_desc_get (usb_core_driver *udev, uint8_t index, uint16_t *len); +static usb_reqsta _usb_std_getstatus (usb_core_driver *udev, usb_req *req); +static usb_reqsta _usb_std_clearfeature (usb_core_driver *udev, usb_req *req); +static usb_reqsta _usb_std_setfeature (usb_core_driver *udev, usb_req *req); +static usb_reqsta _usb_std_setaddress (usb_core_driver *udev, usb_req *req); +static usb_reqsta _usb_std_getdescriptor (usb_core_driver *udev, usb_req *req); +static usb_reqsta _usb_std_setdescriptor (usb_core_driver *udev, usb_req *req); +static usb_reqsta _usb_std_getconfiguration (usb_core_driver *udev, usb_req *req); +static usb_reqsta _usb_std_setconfiguration (usb_core_driver *udev, usb_req *req); +static usb_reqsta _usb_std_getinterface (usb_core_driver *udev, usb_req *req); +static usb_reqsta _usb_std_setinterface (usb_core_driver *udev, usb_req *req); +static usb_reqsta _usb_std_synchframe (usb_core_driver *udev, usb_req *req); + +static usb_reqsta (*_std_dev_req[])(usb_core_driver *udev, usb_req *req) = +{ + [USB_GET_STATUS] = _usb_std_getstatus, + [USB_CLEAR_FEATURE] = _usb_std_clearfeature, + [USB_RESERVED2] = _usb_std_reserved, + [USB_SET_FEATURE] = _usb_std_setfeature, + [USB_RESERVED4] = _usb_std_reserved, + [USB_SET_ADDRESS] = _usb_std_setaddress, + [USB_GET_DESCRIPTOR] = _usb_std_getdescriptor, + [USB_SET_DESCRIPTOR] = _usb_std_setdescriptor, + [USB_GET_CONFIGURATION] = _usb_std_getconfiguration, + [USB_SET_CONFIGURATION] = _usb_std_setconfiguration, + [USB_GET_INTERFACE] = _usb_std_getinterface, + [USB_SET_INTERFACE] = _usb_std_setinterface, + [USB_SYNCH_FRAME] = _usb_std_synchframe, +}; + +/* get standard descriptor handler */ +static uint8_t* (*std_desc_get[])(usb_core_driver *udev, uint8_t index, uint16_t *len) = { + [(uint8_t)USB_DESCTYPE_DEV - 1U] = _usb_dev_desc_get, + [(uint8_t)USB_DESCTYPE_CONFIG - 1U] = _usb_config_desc_get, + [(uint8_t)USB_DESCTYPE_STR - 1U] = _usb_str_desc_get +}; + +/*! + \brief handle USB standard device request + \param[in] udev: pointer to USB device instance + \param[in] req: pointer to USB device request + \param[out] none + \retval USB device request status +*/ +usb_reqsta usbd_standard_request (usb_core_driver *udev, usb_req *req) +{ + return (*_std_dev_req[req->bRequest])(udev, req); +} + +/*! + \brief handle USB device class request + \param[in] udev: pointer to USB device instance + \param[in] req: pointer to USB device class request + \param[out] none + \retval USB device request status +*/ +usb_reqsta usbd_class_request (usb_core_driver *udev, usb_req *req) +{ + if ((uint8_t)USBD_CONFIGURED == udev->dev.cur_status) { + if (BYTE_LOW(req->wIndex) <= USBD_ITF_MAX_NUM) { + /* call device class handle function */ + return (usb_reqsta)udev->dev.class_core->req_proc(udev, req); + } + } + + return REQ_NOTSUPP; +} + +/*! + \brief handle USB vendor request + \param[in] udev: pointer to USB device instance + \param[in] req: pointer to USB vendor request + \param[out] none + \retval USB device request status +*/ +usb_reqsta usbd_vendor_request (usb_core_driver *udev, usb_req *req) +{ + (void)udev; + (void)req; + + /* added by user... */ +#ifdef WINUSB_EXEMPT_DRIVER + usbd_OEM_req(udev, req); +#endif + + return REQ_SUPP; +} + +/*! + \brief handle USB enumeration error + \param[in] udev: pointer to USB device instance + \param[in] req: pointer to USB device request + \param[out] none + \retval none +*/ +void usbd_enum_error (usb_core_driver *udev, usb_req *req) +{ + (void)req; + + (void)usbd_ep_stall (udev, 0x80U); + (void)usbd_ep_stall (udev, 0x00U); + + usb_ctlep_startout(udev); +} + +/*! + \brief convert hex 32bits value into unicode char + \param[in] value: hex 32bits value + \param[in] pbuf: buffer pointer to store unicode char + \param[in] len: value length + \param[out] none + \retval none +*/ +void int_to_unicode (uint32_t value, uint8_t *pbuf, uint8_t len) +{ + uint8_t index; + + for (index = 0U; index < len; index++) { + if ((value >> 28U) < 0x0AU) { + pbuf[2U * index] = (uint8_t)((value >> 28U) + '0'); + } else { + pbuf[2U * index] = (uint8_t)((value >> 28U) + 'A' - 10U); + } + + value = value << 4U; + + pbuf[2U * index + 1U] = 0U; + } +} + +/*! + \brief convert hex 32bits value into unicode char + \param[in] unicode_str: pointer to unicode string + \param[out] none + \retval none +*/ +void serial_string_get (uint16_t *unicode_str) +{ + if ((unicode_str[0] & 0x00FFU) != 6U) { + uint32_t DeviceSerial0, DeviceSerial1, DeviceSerial2; + + DeviceSerial0 = *(uint32_t*)DEVICE_ID1; + DeviceSerial1 = *(uint32_t*)DEVICE_ID2; + DeviceSerial2 = *(uint32_t*)DEVICE_ID3; + + DeviceSerial0 += DeviceSerial2; + + if (0U != DeviceSerial0) { + int_to_unicode(DeviceSerial0, (uint8_t*)&(unicode_str[1]), 8U); + int_to_unicode(DeviceSerial1, (uint8_t*)&(unicode_str[9]), 4U); + } + } else { + uint32_t device_serial = *(uint32_t*)DEVICE_ID; + + if(0U != device_serial) { + unicode_str[1] = (uint16_t)(device_serial & 0x0000FFFFU); + unicode_str[2] = (uint16_t)((device_serial & 0xFFFF0000U) >> 16U); + + } + } +} + +/*! + \brief no operation, just for reserved + \param[in] udev: pointer to USB device instance + \param[in] req: pointer to USB vendor request + \param[out] none + \retval USB device request status +*/ +static usb_reqsta _usb_std_reserved (usb_core_driver *udev, usb_req *req) +{ + (void)udev; + (void)req; + + /* no operation... */ + + return REQ_NOTSUPP; +} + +/*! + \brief get the device descriptor + \param[in] udev: pointer to USB device instance + \param[in] index: no use + \param[out] len: data length pointer + \retval descriptor buffer pointer +*/ +static uint8_t* _usb_dev_desc_get (usb_core_driver *udev, uint8_t index, uint16_t *len) +{ + (void)index; + + *len = udev->dev.desc->dev_desc[0]; + + return udev->dev.desc->dev_desc; +} + +/*! + \brief get the configuration descriptor + \brief[in] udev: pointer to USB device instance + \brief[in] index: no use + \param[out] len: data length pointer + \retval descriptor buffer pointer +*/ +static uint8_t* _usb_config_desc_get (usb_core_driver *udev, uint8_t index, uint16_t *len) +{ + (void)index; + + *len = udev->dev.desc->config_desc[2]; + + return udev->dev.desc->config_desc; +} + +/*! + \brief get the BOS descriptor + \brief[in] udev: pointer to USB device instance + \brief[in] index: no use + \param[out] len: data length pointer + \retval descriptor buffer pointer +*/ +static uint8_t* _usb_bos_desc_get (usb_core_driver *udev, uint8_t index, uint16_t *len) +{ + (void)index; + + *len = udev->dev.desc->bos_desc[2]; + + return udev->dev.desc->bos_desc; +} + +/*! + \brief get string descriptor + \param[in] udev: pointer to USB device instance + \param[in] index: string descriptor index + \param[out] len: pointer to string length + \retval descriptor buffer pointer +*/ +static uint8_t* _usb_str_desc_get (usb_core_driver *udev, uint8_t index, uint16_t *len) +{ + uint8_t *desc = udev->dev.desc->strings[index]; + + *len = desc[0]; + + return desc; +} + +/*! + \brief handle Get_Status request + \param[in] udev: pointer to USB device instance + \param[in] req: pointer to USB device request + \param[out] none + \retval USB device request status +*/ +static usb_reqsta _usb_std_getstatus (usb_core_driver *udev, usb_req *req) +{ + uint8_t recp = BYTE_LOW(req->wIndex); + usb_reqsta req_status = REQ_NOTSUPP; + usb_transc *transc = &udev->dev.transc_in[0]; + + static uint8_t status[2] = {0}; + + switch(req->bmRequestType & (uint8_t)USB_RECPTYPE_MASK) { + case USB_RECPTYPE_DEV: + if (((uint8_t)USBD_ADDRESSED == udev->dev.cur_status) || \ + ((uint8_t)USBD_CONFIGURED == udev->dev.cur_status)) { + + if (udev->dev.pm.power_mode) { + status[0] = USB_STATUS_SELF_POWERED; + } else { + status[0] = 0U; + } + + if (udev->dev.pm.dev_remote_wakeup) { + status[0] |= USB_STATUS_REMOTE_WAKEUP; + } else { + status[0] = 0U; + } + + req_status = REQ_SUPP; + } + break; + + case USB_RECPTYPE_ITF: + if (((uint8_t)USBD_CONFIGURED == udev->dev.cur_status) && (recp <= USBD_ITF_MAX_NUM)) { + req_status = REQ_SUPP; + } + break; + + case USB_RECPTYPE_EP: + if ((uint8_t)USBD_CONFIGURED == udev->dev.cur_status) { + if (0x80U == (recp & 0x80U)) { + status[0] = udev->dev.transc_in[EP_ID(recp)].ep_stall; + } else { + status[0] = udev->dev.transc_out[recp].ep_stall; + } + + req_status = REQ_SUPP; + } + break; + + default: + break; + } + + if (REQ_SUPP == req_status) { + transc->xfer_buf = status; + transc->remain_len = 2U; + } + + return req_status; +} + +/*! + \brief handle USB Clear_Feature request + \param[in] udev: pointer to USB device instance + \param[in] req: USB device request + \param[out] none + \retval USB device request status +*/ +static usb_reqsta _usb_std_clearfeature (usb_core_driver *udev, usb_req *req) +{ + uint8_t ep = 0U; + + switch(req->bmRequestType & (uint8_t)USB_RECPTYPE_MASK) { + case USB_RECPTYPE_DEV: + if (((uint8_t)USBD_ADDRESSED == udev->dev.cur_status) || \ + ((uint8_t)USBD_CONFIGURED == udev->dev.cur_status)) { + + /* clear device remote wakeup feature */ + if ((uint16_t)USB_FEATURE_REMOTE_WAKEUP == req->wValue) { + udev->dev.pm.dev_remote_wakeup = 0U; + + return REQ_SUPP; + } + } + break; + + case USB_RECPTYPE_ITF: + break; + + case USB_RECPTYPE_EP: + /* get endpoint address */ + ep = BYTE_LOW(req->wIndex); + + if ((uint8_t)USBD_CONFIGURED == udev->dev.cur_status) { + /* clear endpoint halt feature */ + if (((uint16_t)USB_FEATURE_EP_HALT == req->wValue) && (!CTL_EP(ep))) { + (void)usbd_ep_stall_clear (udev, ep); + + (void)udev->dev.class_core->req_proc (udev, req); + } + + return REQ_SUPP; + } + break; + + default: + break; + } + + return REQ_NOTSUPP; +} + +/*! + \brief handle USB Set_Feature request + \param[in] udev: pointer to USB device instance + \param[in] req: pointer to USB device request + \param[out] none + \retval USB device request status +*/ +static usb_reqsta _usb_std_setfeature (usb_core_driver *udev, usb_req *req) +{ + uint8_t ep = 0U; + + switch (req->bmRequestType & (uint8_t)USB_RECPTYPE_MASK) { + case USB_RECPTYPE_DEV: + if (((uint8_t)USBD_ADDRESSED == udev->dev.cur_status) || \ + ((uint8_t)USBD_CONFIGURED == udev->dev.cur_status)) { + /* set device remote wakeup feature */ + if ((uint16_t)USB_FEATURE_REMOTE_WAKEUP == req->wValue) { + udev->dev.pm.dev_remote_wakeup = 1U; + } + + return REQ_SUPP; + } + break; + + case USB_RECPTYPE_ITF: + break; + + case USB_RECPTYPE_EP: + /* get endpoint address */ + ep = BYTE_LOW(req->wIndex); + + if ((uint8_t)USBD_CONFIGURED == udev->dev.cur_status) { + /* set endpoint halt feature */ + if (((uint16_t)USB_FEATURE_EP_HALT == req->wValue) && (!CTL_EP(ep))) { + (void)usbd_ep_stall (udev, ep); + } + + return REQ_SUPP; + } + break; + + default: + break; + } + + return REQ_NOTSUPP; +} + +/*! + \brief handle USB Set_Address request + \param[in] udev: pointer to USB device instance + \param[in] req: pointer to USB device request + \param[out] none + \retval USB device request status +*/ +static usb_reqsta _usb_std_setaddress (usb_core_driver *udev, usb_req *req) +{ + if ((0U == req->wIndex) && (0U == req->wLength)) { + udev->dev.dev_addr = (uint8_t)(req->wValue) & 0x7FU; + + if (udev->dev.cur_status != (uint8_t)USBD_CONFIGURED) { + usbd_addr_set (udev, udev->dev.dev_addr); + + if (udev->dev.dev_addr) { + udev->dev.cur_status = (uint8_t)USBD_ADDRESSED; + } else { + udev->dev.cur_status = (uint8_t)USBD_DEFAULT; + } + + return REQ_SUPP; + } + } + + return REQ_NOTSUPP; +} + +/*! + \brief handle USB Get_Descriptor request + \param[in] udev: pointer to USB device instance + \param[in] req: pointer to USB device request + \param[out] none + \retval USB device request status +*/ +static usb_reqsta _usb_std_getdescriptor (usb_core_driver *udev, usb_req *req) +{ + uint8_t desc_type = 0U; + uint8_t desc_index = 0U; + + usb_reqsta status = REQ_NOTSUPP; + + usb_transc *transc = &udev->dev.transc_in[0]; + + /* get device standard descriptor */ + switch (req->bmRequestType & USB_RECPTYPE_MASK) { + case USB_RECPTYPE_DEV: + desc_type = BYTE_HIGH(req->wValue); + desc_index = BYTE_LOW(req->wValue); + + switch (desc_type) { + case USB_DESCTYPE_DEV: + transc->xfer_buf = std_desc_get[desc_type - 1U](udev, desc_index, (uint16_t *)&(transc->remain_len)); + + if (64U == req->wLength) { + transc->remain_len = 8U; + } + break; + + case USB_DESCTYPE_CONFIG: + transc->xfer_buf = std_desc_get[desc_type - 1U](udev, desc_index, (uint16_t *)&(transc->remain_len)); + break; + + case USB_DESCTYPE_STR: + if (desc_index < (uint8_t)STR_IDX_MAX) { + transc->xfer_buf = std_desc_get[desc_type - 1U](udev, desc_index, (uint16_t *)&(transc->remain_len)); + } + break; + + case USB_DESCTYPE_ITF: + case USB_DESCTYPE_EP: + case USB_DESCTYPE_DEV_QUALIFIER: + case USB_DESCTYPE_OTHER_SPD_CONFIG: + case USB_DESCTYPE_ITF_POWER: + break; + + case USB_DESCTYPE_BOS: + transc->xfer_buf = _usb_bos_desc_get(udev, desc_index, (uint16_t *)&(transc->remain_len)); + break; + + default: + break; + } + break; + + case USB_RECPTYPE_ITF: + /* get device class special descriptor */ + status = (usb_reqsta)(udev->dev.class_core->req_proc(udev, req)); + break; + + case USB_RECPTYPE_EP: + break; + + default: + break; + } + + if ((0U != transc->remain_len) && (0U != req->wLength)) { + if (transc->remain_len < req->wLength) { + if ((transc->remain_len >= transc->max_len) && (0U == (transc->remain_len % transc->max_len))) { + udev->dev.control.ctl_zlp = 1U; + } + } else { + transc->remain_len = req->wLength; + } + + status = REQ_SUPP; + } + + return status; +} + +/*! + \brief handle USB Set_Descriptor request + \param[in] udev: pointer to USB device instance + \param[in] req: pointer to USB device request + \param[out] none + \retval USB device request status +*/ +static usb_reqsta _usb_std_setdescriptor (usb_core_driver *udev, usb_req *req) +{ + (void)udev; + (void)req; + + /* no handle... */ + return REQ_SUPP; +} + +/*! + \brief handle USB Get_Configuration request + \param[in] udev: pointer to USB device instance + \param[in] req: pointer to USB device request + \param[out] none + \retval USB device request status +*/ +static usb_reqsta _usb_std_getconfiguration (usb_core_driver *udev, usb_req *req) +{ + (void)req; + + usb_reqsta req_status = REQ_NOTSUPP; + usb_transc *transc = &udev->dev.transc_in[0]; + + switch (udev->dev.cur_status) { + case USBD_ADDRESSED: + if (USB_DEFAULT_CONFIG == udev->dev.config) { + req_status = REQ_SUPP; + } + break; + + case USBD_CONFIGURED: + if (udev->dev.config != USB_DEFAULT_CONFIG) { + req_status = REQ_SUPP; + } + break; + + default: + break; + } + + if (REQ_SUPP == req_status) { + transc->xfer_buf = &(udev->dev.config); + transc->remain_len = 1U; + } + + return req_status; +} + +/*! + \brief handle USB Set_Configuration request + \param[in] udev: pointer to USB device instance + \param[in] req: pointer to USB device request + \param[out] none + \retval USB device request status +*/ +static usb_reqsta _usb_std_setconfiguration (usb_core_driver *udev, usb_req *req) +{ + static uint8_t config; + usb_reqsta status = REQ_NOTSUPP; + + config = (uint8_t)(req->wValue); + + if (config <= USBD_CFG_MAX_NUM) { + switch (udev->dev.cur_status) { + case USBD_ADDRESSED: + if (config){ + (void)udev->dev.class_core->init(udev, config); + + udev->dev.config = config; + udev->dev.cur_status = (uint8_t)USBD_CONFIGURED; + } + + status = REQ_SUPP; + break; + + case USBD_CONFIGURED: + if (USB_DEFAULT_CONFIG == config) { + (void)udev->dev.class_core->deinit(udev, config); + + udev->dev.config = config; + udev->dev.cur_status = (uint8_t)USBD_ADDRESSED; + } else if (config != udev->dev.config) { + /* clear old configuration */ + (void)udev->dev.class_core->deinit(udev, config); + + /* set new configuration */ + udev->dev.config = config; + + (void)udev->dev.class_core->init(udev, config); + } else { + /* no operation */ + } + + status = REQ_SUPP; + break; + + case USBD_DEFAULT: + break; + + default: + break; + } + } + + return status; +} + +/*! + \brief handle USB Get_Interface request + \param[in] udev: pointer to USB device instance + \param[in] req: pointer to USB device request + \param[out] none + \retval USB device request status +*/ +static usb_reqsta _usb_std_getinterface (usb_core_driver *udev, usb_req *req) +{ + switch (udev->dev.cur_status) { + case USBD_DEFAULT: + break; + + case USBD_ADDRESSED: + break; + + case USBD_CONFIGURED: + if (BYTE_LOW(req->wIndex) <= USBD_ITF_MAX_NUM) { + usb_transc *transc = &udev->dev.transc_in[0]; + + transc->xfer_buf = &(udev->dev.class_core->alter_set); + transc->remain_len = 1U; + + return REQ_SUPP; + } + break; + + default: + break; + } + + return REQ_NOTSUPP; +} + +/*! + \brief handle USB Set_Interface request + \param[in] udev: pointer to USB device instance + \param[in] req: pointer to USB device request + \param[out] none + \retval USB device request status +*/ +static usb_reqsta _usb_std_setinterface (usb_core_driver *udev, usb_req *req) +{ + switch (udev->dev.cur_status) { + case USBD_DEFAULT: + break; + + case USBD_ADDRESSED: + break; + + case USBD_CONFIGURED: + if (BYTE_LOW(req->wIndex) <= USBD_ITF_MAX_NUM) { + if (NULL != udev->dev.class_core->set_intf) { + (void)udev->dev.class_core->set_intf (udev, req); + } + + return REQ_SUPP; + } + break; + + default: + break; + } + + return REQ_NOTSUPP; +} + +/*! + \brief handle USB SynchFrame request + \param[in] udev: pointer to USB device instance + \param[in] req: pointer to USB device request + \param[out] none + \retval USB device request status +*/ +static usb_reqsta _usb_std_synchframe (usb_core_driver *udev, usb_req *req) +{ + (void)udev; + (void)req; + + /* no handle */ + return REQ_SUPP; +} diff --git a/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/device/core/Source/usbd_transc.c b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/device/core/Source/usbd_transc.c new file mode 100644 index 0000000000..2c8c2823c2 --- /dev/null +++ b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/device/core/Source/usbd_transc.c @@ -0,0 +1,265 @@ +/*! + \file usbd_transc.c + \brief USB transaction core functions + + \version 2020-07-28, V3.0.0, firmware for GD32F20x + \version 2020-12-10, V3.0.1, firmware for GD32F20x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "usbd_enum.h" +#include "usbd_transc.h" + +/*! + \brief USB send data in the control transaction + \param[in] udev: pointer to USB device instance + \param[out] none + \retval USB device operation cur_status +*/ +usbd_status usbd_ctl_send (usb_core_driver *udev) +{ + usb_transc *transc = &udev->dev.transc_in[0]; + + (void)usbd_ep_send(udev, 0U, transc->xfer_buf, transc->remain_len); + + if (transc->remain_len > transc->max_len) { + udev->dev.control.ctl_state = (uint8_t)USB_CTL_DATA_IN; + } else { + udev->dev.control.ctl_state = (uint8_t)USB_CTL_LAST_DATA_IN; + } + + return USBD_OK; +} + +/*! + \brief USB receive data in control transaction + \param[in] udev: pointer to USB device instance + \param[out] none + \retval USB device operation cur_status +*/ +usbd_status usbd_ctl_recev (usb_core_driver *udev) +{ + usb_transc *transc = &udev->dev.transc_out[0]; + + (void)usbd_ep_recev (udev, 0U, transc->xfer_buf, transc->remain_len); + + if (transc->remain_len > transc->max_len) { + udev->dev.control.ctl_state = (uint8_t)USB_CTL_DATA_OUT; + } else { + udev->dev.control.ctl_state = (uint8_t)USB_CTL_LAST_DATA_OUT; + } + + return USBD_OK; +} + +/*! + \brief USB send control transaction status + \param[in] udev: pointer to USB device instance + \param[out] none + \retval USB device operation cur_status +*/ +usbd_status usbd_ctl_status_send (usb_core_driver *udev) +{ + udev->dev.control.ctl_state = (uint8_t)USB_CTL_STATUS_IN; + + (void)usbd_ep_send (udev, 0U, NULL, 0U); + + usb_ctlep_startout(udev); + + return USBD_OK; +} + +/*! + \brief USB control receive status + \param[in] udev: pointer to USB device instance + \param[out] none + \retval USB device operation cur_status +*/ +usbd_status usbd_ctl_status_recev (usb_core_driver *udev) +{ + udev->dev.control.ctl_state = (uint8_t)USB_CTL_STATUS_OUT; + + (void)usbd_ep_recev (udev, 0U, NULL, 0U); + + usb_ctlep_startout(udev); + + return USBD_OK; +} + +/*! + \brief USB setup stage processing + \param[in] udev: pointer to USB device instance + \param[out] none + \retval USB device operation cur_status +*/ +uint8_t usbd_setup_transc (usb_core_driver *udev) +{ + usb_reqsta reqstat = REQ_NOTSUPP; + + usb_req req = udev->dev.control.req; + + switch (req.bmRequestType & USB_REQTYPE_MASK) { + /* standard device request */ + case USB_REQTYPE_STRD: + reqstat = usbd_standard_request (udev, &req); + break; + + /* device class request */ + case USB_REQTYPE_CLASS: + reqstat = usbd_class_request (udev, &req); + break; + + /* vendor defined request */ + case USB_REQTYPE_VENDOR: + reqstat = usbd_vendor_request (udev, &req); + break; + + default: + break; + } + + if (REQ_SUPP == reqstat) { + if (0U == req.wLength) { + (void)usbd_ctl_status_send (udev); + } else { + if (req.bmRequestType & 0x80U) { + (void)usbd_ctl_send (udev); + } else { + (void)usbd_ctl_recev (udev); + } + } + } else { + usbd_enum_error (udev, &req); + } + + return (uint8_t)USBD_OK; +} + +/*! + \brief data out stage processing + \param[in] udev: pointer to USB device instance + \param[in] ep_num: endpoint identifier(0..7) + \param[out] none + \retval USB device operation cur_status +*/ +uint8_t usbd_out_transc (usb_core_driver *udev, uint8_t ep_num) +{ + if (0U == ep_num) { + usb_transc *transc = &udev->dev.transc_out[0]; + + switch (udev->dev.control.ctl_state) { + case USB_CTL_DATA_OUT: + /* update transfer length */ + transc->remain_len -= transc->max_len; + + if ((uint8_t)USB_USE_DMA == udev->bp.transfer_mode) { + transc->xfer_buf += transc->max_len; + } + + (void)usbd_ctl_recev (udev); + break; + + case USB_CTL_LAST_DATA_OUT: + if (udev->dev.cur_status == (uint8_t)USBD_CONFIGURED) { + if (udev->dev.class_core->ctlx_out != NULL) { + (void)udev->dev.class_core->ctlx_out (udev); + } + } + + transc->remain_len = 0U; + + (void)usbd_ctl_status_send (udev); + break; + + default: + break; + } + } else if ((udev->dev.class_core->data_out != NULL) && (udev->dev.cur_status == (uint8_t)USBD_CONFIGURED)) { + (void)udev->dev.class_core->data_out (udev, ep_num); + } else { + /* no operation */ + } + + return (uint8_t)USBD_OK; +} + +/*! + \brief data in stage processing + \param[in] udev: pointer to USB device instance + \param[in] ep_num: endpoint identifier(0..7) + \param[out] none + \retval USB device operation cur_status +*/ +uint8_t usbd_in_transc (usb_core_driver *udev, uint8_t ep_num) +{ + if (0U == ep_num) { + usb_transc *transc = &udev->dev.transc_in[0]; + + switch (udev->dev.control.ctl_state) { + case USB_CTL_DATA_IN: + /* update transfer length */ + transc->remain_len -= transc->max_len; + + if ((uint8_t)USB_USE_DMA == udev->bp.transfer_mode) { + transc->xfer_buf += transc->max_len; + } + + (void)usbd_ctl_send (udev); + break; + + case USB_CTL_LAST_DATA_IN: + /* last packet is MPS multiple, so send ZLP packet */ + if (udev->dev.control.ctl_zlp) { + (void)usbd_ep_send (udev, 0U, NULL, 0U); + + udev->dev.control.ctl_zlp = 0U; + } else { + if (udev->dev.cur_status == (uint8_t)USBD_CONFIGURED) { + if (udev->dev.class_core->ctlx_in != NULL) { + (void)udev->dev.class_core->ctlx_in (udev); + } + } + + transc->remain_len = 0U; + + (void)usbd_ctl_status_recev (udev); + } + break; + + default: + break; + } + } else { + if ((udev->dev.cur_status == (uint8_t)USBD_CONFIGURED) && (udev->dev.class_core->data_in != NULL)) { + (void)udev->dev.class_core->data_in (udev, ep_num); + } + } + + return (uint8_t)USBD_OK; +} diff --git a/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/driver/Include/drv_usb_core.h b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/driver/Include/drv_usb_core.h new file mode 100644 index 0000000000..668d19cbea --- /dev/null +++ b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/driver/Include/drv_usb_core.h @@ -0,0 +1,163 @@ +/*! + \file drv_usb_core.h + \brief USB core low level driver header file + + \version 2020-07-28, V3.0.0, firmware for GD32F20x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef __DRV_USB_CORE_H +#define __DRV_USB_CORE_H + +#include "drv_usb_regs.h" +#include "usb_ch9_std.h" + +#define USB_FS_EP0_MAX_LEN 64U /*!< maximum packet size of endpoint 0 */ +#define HC_MAX_PACKET_COUNT 140U /*!< maximum packet count */ + +#define EP_ID(x) ((uint8_t)((x) & 0x7FU)) /*!< endpoint number */ +#define EP_DIR(x) ((uint8_t)((x) >> 7)) /*!< endpoint direction */ + +enum _usb_mode { + DEVICE_MODE = 0U, /*!< device mode */ + HOST_MODE, /*!< host mode */ + OTG_MODE /*!< OTG mode */ +}; + +enum _usb_eptype { + USB_EPTYPE_CTRL = 0U, /*!< control endpoint type */ + USB_EPTYPE_ISOC = 1U, /*!< isochronous endpoint type */ + USB_EPTYPE_BULK = 2U, /*!< bulk endpoint type */ + USB_EPTYPE_INTR = 3U, /*!< interrupt endpoint type */ + USB_EPTYPE_MASK = 3U /*!< endpoint type mask */ +}; + +typedef enum +{ + USB_OTG_OK = 0U, /*!< USB OTG status OK*/ + USB_OTG_FAIL /*!< USB OTG status fail*/ +} usb_otg_status; + +typedef enum +{ + USB_OK = 0U, /*!< USB status OK*/ + USB_FAIL /*!< USB status fail*/ +} usb_status; + +typedef enum +{ + USB_USE_FIFO, /*!< USB use FIFO transfer mode */ + USB_USE_DMA /*!< USB use DMA transfer mode */ +} usb_transfer_mode; + +typedef struct +{ + uint8_t core_enum; /*!< USB core type */ + uint8_t core_speed; /*!< USB core speed */ + uint8_t num_pipe; /*!< USB host channel numbers */ + uint8_t num_ep; /*!< USB device endpoint numbers */ + uint8_t transfer_mode; /*!< USB transfer mode */ + uint8_t phy_itf; /*!< USB core PHY interface */ + uint8_t sof_enable; /*!< USB SOF output */ + uint8_t low_power; /*!< USB low power */ + uint8_t lpm_enable; /*!< USB link power mode(LPM) */ + uint8_t vbus_sensing_enable; /*!< USB VBUS sensing feature */ + uint8_t use_dedicated_ep1; /*!< USB dedicated endpoint1 interrupt */ + uint8_t use_external_vbus; /*!< enable or disable the use of the external VBUS */ + uint32_t base_reg; /*!< base register address */ +} usb_core_basic; + +/* static inline function definitions */ + +/*! + \brief get the global interrupts + \param[in] usb_regs: pointer to USB core registers + \param[out] none + \retval interrupt status +*/ +__STATIC_INLINE uint32_t usb_coreintr_get(usb_core_regs *usb_regs) +{ + return usb_regs->gr->GINTEN & usb_regs->gr->GINTF; +} + +/*! + \brief set USB RX FIFO size + \param[in] usb_regs: pointer to USB core registers + \param[in] size: assigned FIFO size + \param[out] none + \retval none +*/ +__STATIC_INLINE void usb_set_rxfifo(usb_core_regs *usb_regs, uint16_t size) +{ + usb_regs->gr->GRFLEN = size; +} + +/*! + \brief enable the global interrupts + \param[in] usb_regs: pointer to USB core registers + \param[out] none + \retval none +*/ +__STATIC_INLINE void usb_globalint_enable(usb_core_regs *usb_regs) +{ + /* enable USB global interrupt */ + usb_regs->gr->GAHBCS |= GAHBCS_GINTEN; +} + +/*! + \brief disable the global interrupts + \param[in] usb_regs: pointer to USB core registers + \param[out] none + \retval none +*/ +__STATIC_INLINE void usb_globalint_disable(usb_core_regs *usb_regs) +{ + /* disable USB global interrupt */ + usb_regs->gr->GAHBCS &= ~GAHBCS_GINTEN; +} + +/* function declarations */ +/* configure core capabilities */ +usb_status usb_basic_init (usb_core_basic *usb_basic, usb_core_regs *usb_regs, usb_core_enum usb_core); +/* initializes the USB controller registers and prepares the core device mode or host mode operation */ +usb_status usb_core_init (usb_core_basic usb_basic, usb_core_regs *usb_regs); +/* write a packet into the Tx FIFO associated with the endpoint */ +usb_status usb_txfifo_write (usb_core_regs *usb_regs, uint8_t *src_buf, uint8_t fifo_num, uint16_t byte_count); +/* read a packet from the Rx FIFO associated with the endpoint */ +void *usb_rxfifo_read (usb_core_regs *usb_regs, uint8_t *dest_buf, uint16_t byte_count); +/* flush a Tx FIFO or all Tx FIFOs */ +usb_status usb_txfifo_flush (usb_core_regs *usb_regs, uint8_t fifo_num); +/* flush the entire Rx FIFO */ +usb_status usb_rxfifo_flush (usb_core_regs *usb_regs); +/* set endpoint or channel TX FIFO size */ +void usb_set_txfifo(usb_core_regs *usb_regs, uint8_t fifo, uint16_t size); +/* set USB current mode */ +void usb_curmode_set(usb_core_regs *usb_regs, uint8_t mode); + +#endif /* __DRV_USB_CORE_H */ diff --git a/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/driver/Include/drv_usb_dev.h b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/driver/Include/drv_usb_dev.h new file mode 100644 index 0000000000..ce9ebdc9a8 --- /dev/null +++ b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/driver/Include/drv_usb_dev.h @@ -0,0 +1,299 @@ +/*! + \file drv_usb_dev.h + \brief USB device low level driver header file + + \version 2020-07-28, V3.0.0, firmware for GD32F20x + \version 2020-12-10, V3.0.1, firmware for GD32F20x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef __DRV_USB_DEV_H +#define __DRV_USB_DEV_H + +#include "usbd_conf.h" +#include "drv_usb_core.h" + +enum usb_ctl_status { + USB_CTL_IDLE = 0U, /*!< USB control transfer idle state */ + USB_CTL_DATA_IN, /*!< USB control transfer data in state */ + USB_CTL_LAST_DATA_IN, /*!< USB control transfer last data in state */ + USB_CTL_DATA_OUT, /*!< USB control transfer data out state */ + USB_CTL_LAST_DATA_OUT, /*!< USB control transfer last data out state */ + USB_CTL_STATUS_IN, /*!< USB control transfer status in state*/ + USB_CTL_STATUS_OUT /*!< USB control transfer status out state */ +}; + +#define EP_IN(x) ((uint8_t)(0x80U | (x))) /*!< device IN endpoint */ +#define EP_OUT(x) ((uint8_t)(x)) /*!< device OUT endpoint */ + +/* USB descriptor */ +typedef struct _usb_desc { + uint8_t *dev_desc; /*!< device descriptor */ + uint8_t *config_desc; /*!< configure descriptor */ + uint8_t *bos_desc; /*!< BOS descriptor */ + + void* const *strings; /*!< string descriptor */ +} usb_desc; + +/* USB power management */ +typedef struct _usb_pm { + uint8_t power_mode; /*!< power mode */ + uint8_t power_low; /*!< power low */ + uint8_t dev_remote_wakeup; /*!< remote wakeup */ + uint8_t remote_wakeup_on; /*!< remote wakeup on */ +} usb_pm; + +/* USB control information */ +typedef struct _usb_control { + usb_req req; /*!< USB standard device request */ + + uint8_t ctl_state; /*!< USB control transfer state */ + uint8_t ctl_zlp; /*!< zero length package */ +} usb_control; + +typedef struct +{ + struct { + uint8_t num: 4; /*!< the endpoint number.it can be from 0 to 6 */ + uint8_t pad: 3; /*!< padding between number and direction */ + uint8_t dir: 1; /*!< the endpoint direction */ + } ep_addr; + + uint8_t ep_type; /*!< USB endpoint type */ + uint8_t ep_stall; /*!< USB endpoint stall status */ + + uint8_t frame_num; /*!< number of frame */ + uint16_t max_len; /*!< Maximum packet length */ + + /* transaction level variables */ + uint8_t *xfer_buf; /*!< transmit buffer */ + uint32_t xfer_len; /*!< transmit buffer length */ + uint32_t xfer_count; /*!< transmit buffer count */ + + uint32_t remain_len; /*!< remain packet length */ + + uint32_t dma_addr; /*!< DMA address */ +} usb_transc; + +typedef struct _usb_core_driver usb_dev; + +typedef struct _usb_class_core +{ + uint8_t command; /*!< device class request command */ + uint8_t alter_set; /*!< alternative set */ + + uint8_t (*init) (usb_dev *udev, uint8_t config_index); /*!< initialize handler */ + uint8_t (*deinit) (usb_dev *udev, uint8_t config_index); /*!< deinitialize handler */ + + uint8_t (*req_proc) (usb_dev *udev, usb_req *req); /*!< device request handler */ + + uint8_t (*set_intf) (usb_dev *udev, usb_req *req); /*!< device set interface callback */ + + uint8_t (*ctlx_in) (usb_dev *udev); /*!< device control in handler */ + uint8_t (*ctlx_out) (usb_dev *udev); /*!< device control out handler */ + uint8_t (*data_in) (usb_dev *udev, uint8_t ep_num); /*!< device data in handler */ + uint8_t (*data_out) (usb_dev *udev, uint8_t ep_num); /*!< device data out handler */ + + uint8_t (*SOF) (usb_dev *udev); /*!< Start of frame handler */ + + uint8_t (*incomplete_isoc_in) (usb_dev *udev); /*!< Incomplete synchronization IN transfer handler */ + uint8_t (*incomplete_isoc_out) (usb_dev *udev); /*!< Incomplete synchronization OUT transfer handler */ +} usb_class_core; + +typedef struct _usb_perp_dev +{ + uint8_t config; /*!< configuration */ + uint8_t dev_addr; /*!< device address */ + + __IO uint8_t cur_status; /*!< current status */ + __IO uint8_t backup_status; /*!< backup status */ + + usb_transc transc_in[USBFS_MAX_TX_FIFOS]; /*!< endpoint IN transaction */ + usb_transc transc_out[USBFS_MAX_TX_FIFOS]; /*!< endpoint OUT transaction */ + + usb_pm pm; /*!< power management */ + usb_control control; /*!< USB control information */ + usb_desc *desc; /*!< USB descriptors pointer */ + usb_class_core *class_core; /*!< class driver */ + void *class_data[USBD_ITF_MAX_NUM]; /*!< class data pointer */ + void *user_data; /*!< user data pointer */ + void *pdata; /*!< reserved data pointer */ +} usb_perp_dev; + +typedef struct _usb_core_driver +{ + usb_core_basic bp; /*!< USB basic parameters */ + usb_core_regs regs; /*!< USB registers */ + usb_perp_dev dev; /*!< USB peripheral device */ +} usb_core_driver; + +/* static inline function definitions */ + +/*! + \brief configure the USB device to be disconnected + \param[in] udev: pointer to USB device + \param[out] none + \retval operation status +*/ +__STATIC_INLINE void usb_dev_disconnect (usb_core_driver *udev) +{ + udev->regs.dr->DCTL |= DCTL_SD; +} + +/*! + \brief configure the USB device to be connected + \param[in] udev: pointer to USB device + \param[out] none + \retval operation status +*/ +__STATIC_INLINE void usb_dev_connect (usb_core_driver *udev) +{ + udev->regs.dr->DCTL &= ~DCTL_SD; +} + +/*! + \brief set the USB device address + \param[in] udev: pointer to USB device + \param[in] dev_addr: device address for setting + \param[out] none + \retval operation status +*/ +__STATIC_INLINE void usb_devaddr_set (usb_core_driver *udev, uint8_t dev_addr) +{ + udev->regs.dr->DCFG &= ~DCFG_DAR; + udev->regs.dr->DCFG |= (uint32_t)dev_addr << 4U; +} + +/*! + \brief read device all OUT endpoint interrupt register + \param[in] udev: pointer to USB device + \param[out] none + \retval interrupt status +*/ +__STATIC_INLINE uint32_t usb_oepintnum_read (usb_core_driver *udev) +{ + uint32_t value = udev->regs.dr->DAEPINT; + + value &= udev->regs.dr->DAEPINTEN; + + return (value & DAEPINT_OEPITB) >> 16U; +} + +/*! + \brief read device OUT endpoint interrupt flag register + \param[in] udev: pointer to USB device + \param[in] ep_num: endpoint number + \param[out] none + \retval interrupt status +*/ +__STATIC_INLINE uint32_t usb_oepintr_read (usb_core_driver *udev, uint8_t ep_num) +{ + uint32_t value = udev->regs.er_out[ep_num]->DOEPINTF; + + value &= udev->regs.dr->DOEPINTEN; + + return value; +} + +/*! + \brief read device all IN endpoint interrupt register + \param[in] udev: pointer to USB device + \param[out] none + \retval interrupt status +*/ +__STATIC_INLINE uint32_t usb_iepintnum_read (usb_core_driver *udev) +{ + uint32_t value = udev->regs.dr->DAEPINT; + + value &= udev->regs.dr->DAEPINTEN; + + return value & DAEPINT_IEPITB; +} + +/*! + \brief set remote wakeup signaling + \param[in] udev: pointer to USB device + \param[out] none + \retval none +*/ +__STATIC_INLINE void usb_rwkup_set (usb_core_driver *udev) +{ + if (udev->dev.pm.dev_remote_wakeup) { + /* enable remote wakeup signaling */ + udev->regs.dr->DCTL |= DCTL_RWKUP; + } +} + +/*! + \brief reset remote wakeup signaling + \param[in] udev: pointer to USB device + \param[out] none + \retval none +*/ +__STATIC_INLINE void usb_rwkup_reset (usb_core_driver *udev) +{ + if (udev->dev.pm.dev_remote_wakeup) { + /* disable remote wakeup signaling */ + udev->regs.dr->DCTL &= ~DCTL_RWKUP; + } +} + +/* function declarations */ +/* initialize USB core registers for device mode */ +usb_status usb_devcore_init (usb_core_driver *udev); +/* enable the USB device mode interrupts */ +usb_status usb_devint_enable (usb_core_driver *udev); +/* active the USB endpoint 0 transaction */ +usb_status usb_transc0_active (usb_core_driver *udev, usb_transc *transc); +/* active the USB transaction */ +usb_status usb_transc_active (usb_core_driver *udev, usb_transc *transc); +/* deactivate the USB transaction */ +usb_status usb_transc_deactivate (usb_core_driver *udev, usb_transc *transc); +/* configure USB transaction to start IN transfer */ +usb_status usb_transc_inxfer (usb_core_driver *udev, usb_transc *transc); +/* configure USB transaction to start OUT transfer */ +usb_status usb_transc_outxfer (usb_core_driver *udev, usb_transc *transc); +/* set the USB transaction STALL status */ +usb_status usb_transc_stall (usb_core_driver *udev, usb_transc *transc); +/* clear the USB transaction STALL status */ +usb_status usb_transc_clrstall (usb_core_driver *udev, usb_transc *transc); +/* read device IN endpoint interrupt flag register */ +uint32_t usb_iepintr_read (usb_core_driver *udev, uint8_t ep_num); +/* configures OUT endpoint 0 to receive SETUP packets */ +void usb_ctlep_startout (usb_core_driver *udev); +/* active remote wakeup signaling */ +void usb_rwkup_active (usb_core_driver *udev); +/* active USB core clock */ +void usb_clock_active (usb_core_driver *udev); +/* USB device suspend */ +void usb_dev_suspend (usb_core_driver *udev); +/* stop the device and clean up FIFOs */ +void usb_dev_stop (usb_core_driver *udev); + +#endif /* __DRV_USB_DEV_H */ diff --git a/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/driver/Include/drv_usb_host.h b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/driver/Include/drv_usb_host.h new file mode 100644 index 0000000000..02bbbef2b4 --- /dev/null +++ b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/driver/Include/drv_usb_host.h @@ -0,0 +1,193 @@ +/*! + \file drv_usb_host.h + \brief USB host mode low level driver header file + + \version 2020-07-28, V3.0.0, firmware for GD32F20x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef __DRV_USB_HOST_H +#define __DRV_USB_HOST_H + +#include "drv_usb_regs.h" +#include "usb_ch9_std.h" +#include "drv_usb_core.h" + +typedef enum _usb_pipe_status +{ + PIPE_IDLE = 0U, + PIPE_XF, + PIPE_HALTED, + PIPE_NAK, + PIPE_NYET, + PIPE_STALL, + PIPE_TRACERR, + PIPE_BBERR, + PIPE_REQOVR, + PIPE_DTGERR, +} usb_pipe_staus; + +typedef enum _usb_pipe_mode +{ + PIPE_PERIOD = 0U, + PIPE_NON_PERIOD = 1U +} usb_pipe_mode; + +typedef enum _usb_urb_state +{ + URB_IDLE = 0U, + URB_DONE, + URB_NOTREADY, + URB_ERROR, + URB_STALL, + URB_PING +} usb_urb_state; + +typedef struct _usb_pipe +{ + uint8_t in_used; + uint8_t dev_addr; + uint32_t dev_speed; + + struct { + uint8_t num; + uint8_t dir; + uint8_t type; + uint16_t mps; + } ep; + + uint8_t ping; + uint32_t DPID; + + uint8_t *xfer_buf; + uint32_t xfer_len; + uint32_t xfer_count; + + uint8_t data_toggle_in; + uint8_t data_toggle_out; + + __IO uint32_t err_count; + __IO usb_pipe_staus pp_status; + __IO usb_urb_state urb_state; +} usb_pipe; + + +typedef struct _usb_host_drv +{ + __IO uint32_t connect_status; + __IO uint32_t port_enabled; + __IO uint32_t backup_xfercount[USBFS_MAX_TX_FIFOS]; + + usb_pipe pipe[USBFS_MAX_TX_FIFOS]; + void *data; +} usb_host_drv; + +typedef struct _usb_core_driver +{ + usb_core_basic bp; + usb_core_regs regs; + usb_host_drv host; +} usb_core_driver; + +/*! + \brief get USB even frame + \param[in] udev: pointer to USB device + \param[out] none + \retval none +*/ +__STATIC_INLINE uint8_t usb_frame_even (usb_core_driver *udev) +{ + return (uint8_t)!(udev->regs.hr->HFINFR & 0x01U); +} + +/*! + \brief configure USB clock of PHY + \param[in] udev: pointer to USB device + \param[in] clock: PHY clock + \param[out] none + \retval none +*/ +__STATIC_INLINE void usb_phyclock_config (usb_core_driver *udev, uint8_t clock) +{ + udev->regs.hr->HCTL &= ~HCTL_CLKSEL; + udev->regs.hr->HCTL |= clock; +} + +/*! + \brief read USB port + \param[in] udev: pointer to USB device + \param[out] none + \retval port status +*/ +__STATIC_INLINE uint32_t usb_port_read (usb_core_driver *udev) +{ + return *udev->regs.HPCS & ~(HPCS_PE | HPCS_PCD | HPCS_PEDC); +} + +/*! + \brief get USB current speed + \param[in] udev: pointer to USB device + \param[out] none + \retval USB current speed +*/ +__STATIC_INLINE uint32_t usb_curspeed_get (usb_core_driver *udev) +{ + return *udev->regs.HPCS & HPCS_PS; +} + +/*! + \brief get USB current frame + \param[in] udev: pointer to USB device + \param[out] none + \retval USB current frame +*/ +__STATIC_INLINE uint32_t usb_curframe_get (usb_core_driver *udev) +{ + return (udev->regs.hr->HFINFR & 0xFFFFU); +} + +/* function declarations */ +/* initializes USB core for host mode */ +usb_status usb_host_init (usb_core_driver *udev); +/* control the VBUS to power */ +void usb_portvbus_switch (usb_core_driver *udev, uint8_t state); +/* reset host port */ +uint32_t usb_port_reset (usb_core_driver *udev); +/* initialize host pipe */ +usb_status usb_pipe_init (usb_core_driver *udev, uint8_t pipe_num); +/* prepare host pipe for transferring packets */ +usb_status usb_pipe_xfer (usb_core_driver *udev, uint8_t pipe_num); +/* halt host pipe */ +usb_status usb_pipe_halt (usb_core_driver *udev, uint8_t pipe_num); +/* configure host pipe to do ping operation */ +usb_status usb_pipe_ping (usb_core_driver *udev, uint8_t pipe_num); +/* stop the USB host and clean up FIFO */ +void usb_host_stop (usb_core_driver *udev); + +#endif /* __DRV_USB_HOST_H */ diff --git a/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/driver/Include/drv_usb_hw.h b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/driver/Include/drv_usb_hw.h new file mode 100644 index 0000000000..fe84e310e3 --- /dev/null +++ b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/driver/Include/drv_usb_hw.h @@ -0,0 +1,64 @@ +/*! + \file drv_usb_hw.h + \brief usb hardware configuration header file + + \version 2020-07-28, V3.0.0, firmware for GD32F20x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef __DRV_USB_HW_H +#define __DRV_USB_HW_H + +#include "usb_conf.h" + +/* function declarations */ +/* configure USB clock */ +void usb_rcu_config (void); +/* configure USB interrupt */ +void usb_intr_config (void); +/* initializes delay unit using Timer2 */ +void usb_timer_init (void); +/* delay in micro seconds */ +void usb_udelay (const uint32_t usec); +/* delay in milliseconds */ +void usb_mdelay (const uint32_t msec); +/* configures system clock after wakeup from STOP mode */ +void system_clk_config_stop(void); + +#ifdef USE_HOST_MODE + void systick_config(void); + + /* configure USB VBus */ + void usb_vbus_config (void); + + /* drive USB VBus */ + void usb_vbus_drive (uint8_t State); +#endif /* USE_HOST_MODE */ + +#endif /* __DRV_USB_HW_H */ diff --git a/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/driver/Include/drv_usb_regs.h b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/driver/Include/drv_usb_regs.h new file mode 100644 index 0000000000..8421e8779f --- /dev/null +++ b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/driver/Include/drv_usb_regs.h @@ -0,0 +1,661 @@ +/*! + \file drv_usb_regs.h + \brief USB cell registers definition and handle macros + + \version 2020-07-28, V3.0.0, firmware for GD32F20x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef __DRV_USB_REGS_H +#define __DRV_USB_REGS_H + +#include "usb_conf.h" + +#define USBHS_REG_BASE 0x40040000L /*!< base address of USBHS registers */ +#define USBFS_REG_BASE 0x50000000L /*!< base address of USBFS registers */ + +#define USBFS_MAX_TX_FIFOS 15U /*!< FIFO number */ + +#define USBFS_MAX_PACKET_SIZE 64U /*!< USBFS max packet size */ +#define USBFS_MAX_CHANNEL_COUNT 8U /*!< USBFS host channel count */ +#define USBFS_MAX_EP_COUNT 4U /*!< USBFS device endpoint count */ +#define USBFS_MAX_FIFO_WORDLEN 320U /*!< USBFS max fifo size in words */ + +#define USBHS_MAX_PACKET_SIZE 512U /*!< USBHS max packet size */ +#define USBHS_MAX_CHANNEL_COUNT 12U /*!< USBHS host channel count */ +#define USBHS_MAX_EP_COUNT 6U /*!< USBHS device endpoint count */ +#define USBHS_MAX_FIFO_WORDLEN 1280U /*!< USBHS max fifo size in words */ + +#define USB_DATA_FIFO_OFFSET 0x1000U /*!< USB data fifo offset */ +#define USB_DATA_FIFO_SIZE 0x1000U /*!< USB data fifo size */ + +typedef enum +{ + USB_CORE_ENUM_HS = 0, /*!< USB core type is HS */ + USB_CORE_ENUM_FS = 1 /*!< USB core type is FS */ +} usb_core_enum; + +enum USB_SPEED { + USB_SPEED_UNKNOWN = 0, /*!< USB speed unknown */ + USB_SPEED_LOW, /*!< USB speed low */ + USB_SPEED_FULL, /*!< USB speed full */ + USB_SPEED_HIGH, /*!< USB speed high */ +}; + +enum usb_reg_offset { + USB_REG_OFFSET_CORE = 0x0000U, /*!< global OTG control and status register */ + USB_REG_OFFSET_DEV = 0x0800U, /*!< device mode control and status registers */ + USB_REG_OFFSET_EP = 0x0020U, + USB_REG_OFFSET_EP_IN = 0x0900U, /*!< device IN endpoint 0 control register */ + USB_REG_OFFSET_EP_OUT = 0x0B00U, /*!< device OUT endpoint 0 control register */ + USB_REG_OFFSET_HOST = 0x0400U, /*!< host control register */ + USB_REG_OFFSET_CH = 0x0020U, + USB_REG_OFFSET_PORT = 0x0440U, /*!< host port control and status register */ + USB_REG_OFFSET_CH_INOUT = 0x0500U, /*!< Host channel-x control registers */ + USB_REG_OFFSET_PWRCLKCTL = 0x0E00U, /*!< power and clock register */ +}; + +typedef struct +{ + __IO uint32_t GOTGCS; /*!< USB global OTG control and status register 000h */ + __IO uint32_t GOTGINTF; /*!< USB global OTG interrupt flag register 004h */ + __IO uint32_t GAHBCS; /*!< USB global AHB control and status register 008h */ + __IO uint32_t GUSBCS; /*!< USB global USB control and status register 00Ch */ + __IO uint32_t GRSTCTL; /*!< USB global reset control register 010h */ + __IO uint32_t GINTF; /*!< USB global interrupt flag register 014h */ + __IO uint32_t GINTEN; /*!< USB global interrupt enable register 018h */ + __IO uint32_t GRSTATR; /*!< USB receive status debug read register 01Ch */ + __IO uint32_t GRSTATP; /*!< USB receive status and pop register 020h */ + __IO uint32_t GRFLEN; /*!< USB global receive FIFO length register 024h */ + __IO uint32_t DIEP0TFLEN_HNPTFLEN; /*!< USB device IN endpoint 0/host non-periodic transmit FIFO length register 028h */ + __IO uint32_t HNPTFQSTAT; /*!< USB host non-periodic FIFO/queue status register 02Ch */ + uint32_t Reserved30[2]; /*!< Reserved 030h */ + __IO uint32_t GCCFG; /*!< USB global core configuration register 038h */ + __IO uint32_t CID; /*!< USB core ID register 03Ch */ + uint32_t Reserved40[48]; /*!< Reserved 040h-0FFh */ + __IO uint32_t HPTFLEN; /*!< USB host periodic transmit FIFO length register 100h */ + __IO uint32_t DIEPTFLEN[15]; /*!< USB device IN endpoint transmit FIFO length register 104h */ +} usb_gr; + + +typedef struct +{ + __IO uint32_t HCTL; /*!< USB host control register 400h */ + __IO uint32_t HFT; /*!< USB host frame interval register 404h */ + __IO uint32_t HFINFR; /*!< USB host frame information remaining register 408h */ + uint32_t Reserved40C; /*!< Reserved 40Ch */ + __IO uint32_t HPTFQSTAT; /*!< USB host periodic transmit FIFO/queue status register 410h */ + __IO uint32_t HACHINT; /*!< USB host all channels interrupt register 414h */ + __IO uint32_t HACHINTEN; /*!< USB host all channels interrupt enable register 418h */ +} usb_hr; + +typedef struct +{ + __IO uint32_t HCHCTL; /*!< USB host channel control register 500h */ + __IO uint32_t HCHSTCTL; /*!< Reserved 504h */ + __IO uint32_t HCHINTF; /*!< USB host channel interrupt flag register 508h */ + __IO uint32_t HCHINTEN; /*!< USB host channel interrupt enable register 50Ch */ + __IO uint32_t HCHLEN; /*!< USB host channel transfer length register 510h */ + __IO uint32_t HCHDMAADDR; /*!< USB host channel-x DMA address register 514h*/ + uint32_t Reserved[2]; +} usb_pr; + +typedef struct +{ + __IO uint32_t DCFG; /*!< USB device configuration register 800h */ + __IO uint32_t DCTL; /*!< USB device control register 804h */ + __IO uint32_t DSTAT; /*!< USB device status register 808h */ + uint32_t Reserved0C; /*!< Reserved 80Ch */ + __IO uint32_t DIEPINTEN; /*!< USB device IN endpoint common interrupt enable register 810h */ + __IO uint32_t DOEPINTEN; /*!< USB device OUT endpoint common interrupt enable register 814h */ + __IO uint32_t DAEPINT; /*!< USB device all endpoints interrupt register 818h */ + __IO uint32_t DAEPINTEN; /*!< USB device all endpoints interrupt enable register 81Ch */ + uint32_t Reserved20; /*!< Reserved 820h */ + uint32_t Reserved24; /*!< Reserved 824h */ + __IO uint32_t DVBUSDT; /*!< USB device VBUS discharge time register 828h */ + __IO uint32_t DVBUSPT; /*!< USB device VBUS pulsing time register 82Ch */ + __IO uint32_t DTHRCTL; /*!< device threshold control 830h */ + __IO uint32_t DIEPFEINTEN; /*!< USB Device IN endpoint FIFO empty interrupt enable register 834h */ + __IO uint32_t DEP1INT; /*!< USB device endpoint 1 interrupt register 838h */ + __IO uint32_t DEP1INTEN; /*!< USB device endpoint 1 interrupt enable register 83Ch */ + uint32_t Reserved40; /*!< Reserved 840h */ + __IO uint32_t DIEP1INTEN; /*!< USB device IN endpoint-1 interrupt enable register 844h */ + uint32_t Reserved48[15]; /*!< Reserved 848-880h */ + __IO uint32_t DOEP1INTEN; /*!< USB device OUT endpoint-1 interrupt enable register 884h */ +} usb_dr; + +typedef struct +{ + __IO uint32_t DIEPCTL; /*!< USB device IN endpoint control register 900h + (EpNum * 20h) + 00h */ + uint32_t Reserved04; /*!< Reserved 900h + (EpNum * 20h) + 04h */ + __IO uint32_t DIEPINTF; /*!< USB device IN endpoint interrupt flag register 900h + (EpNum * 20h) + 08h */ + uint32_t Reserved0C; /*!< Reserved 900h + (EpNum * 20h) + 0Ch */ + __IO uint32_t DIEPLEN; /*!< USB device IN endpoint transfer length register 900h + (EpNum * 20h) + 10h */ + __IO uint32_t DIEPDMAADDR; /*!< Device IN endpoint-x DMA address register 900h + (EpNum * 20h) + 14h */ + __IO uint32_t DIEPTFSTAT; /*!< USB device IN endpoint transmit FIFO status register 900h + (EpNum * 20h) + 18h */ +} usb_erin; + +typedef struct +{ + __IO uint32_t DOEPCTL; /*!< USB device IN endpoint control register B00h + (EpNum * 20h) + 00h */ + uint32_t Reserved04; /*!< Reserved B00h + (EpNum * 20h) + 04h */ + __IO uint32_t DOEPINTF; /*!< USB device IN endpoint interrupt flag register B00h + (EpNum * 20h) + 08h */ + uint32_t Reserved0C; /*!< Reserved B00h + (EpNum * 20h) + 0Ch */ + __IO uint32_t DOEPLEN; /*!< USB device IN endpoint transfer length register B00h + (EpNum * 20h) + 10h */ + __IO uint32_t DOEPDMAADDR; /*!< Device OUT endpoint-x DMA address register B00h + (EpNum * 20h) + 0Ch */ +} usb_erout; + +typedef struct _usb_regs +{ + usb_gr *gr; /*!< USBFS global registers */ + usb_dr *dr; /*!< Device control and status registers */ + usb_hr *hr; /*!< Host control and status registers */ + usb_erin *er_in[6]; /*!< USB device IN endpoint register */ + usb_erout *er_out[6]; /*!< USB device OUT endpoint register */ + usb_pr *pr[15]; /*!< USB Host channel-x control register */ + + __IO uint32_t *HPCS; /*!< USB host port control and status register */ + __IO uint32_t *DFIFO[USBFS_MAX_TX_FIFOS]; + __IO uint32_t *PWRCLKCTL; /*!< USB power and clock control register */ +} usb_core_regs; + +/* global OTG control and status register bits definitions */ +#define GOTGCS_BSV BIT(19) /*!< B-Session Valid */ +#define GOTGCS_ASV BIT(18) /*!< A-session valid */ +#define GOTGCS_DI BIT(17) /*!< debounce interval */ +#define GOTGCS_CIDPS BIT(16) /*!< id pin status */ +#define GOTGCS_DHNPEN BIT(11) /*!< device HNP enable */ +#define GOTGCS_HHNPEN BIT(10) /*!< host HNP enable */ +#define GOTGCS_HNPREQ BIT(9) /*!< HNP request */ +#define GOTGCS_HNPS BIT(8) /*!< HNP successes */ +#define GOTGCS_SRPREQ BIT(1) /*!< SRP request */ +#define GOTGCS_SRPS BIT(0) /*!< SRP successes */ + +/* global OTG interrupt flag register bits definitions */ +#define GOTGINTF_DF BIT(19) /*!< debounce finish */ +#define GOTGINTF_ADTO BIT(18) /*!< A-device timeout */ +#define GOTGINTF_HNPDET BIT(17) /*!< host negotiation request detected */ +#define GOTGINTF_HNPEND BIT(9) /*!< HNP end */ +#define GOTGINTF_SRPEND BIT(8) /*!< SRP end */ +#define GOTGINTF_SESEND BIT(2) /*!< session end */ + +/* global AHB control and status register bits definitions */ +#define GAHBCS_PTXFTH BIT(8) /*!< periodic Tx FIFO threshold */ +#define GAHBCS_TXFTH BIT(7) /*!< tx FIFO threshold */ +#define GAHBCS_DMAEN BIT(5) /*!< DMA function Enable */ +#define GAHBCS_BURST BITS(1, 4) /*!< the AHB burst type used by DMA */ +#define GAHBCS_GINTEN BIT(0) /*!< global interrupt enable */ + +/* global USB control and status register bits definitions */ +#define GUSBCS_FDM BIT(30) /*!< force device mode */ +#define GUSBCS_FHM BIT(29) /*!< force host mode */ +#define GUSBCS_ULPIEOI BIT(21) /*!< ULPI external over-current indicator */ +#define GUSBCS_ULPIEVD BIT(20) /*!< ULPI external VBUS driver */ +#define GUSBCS_UTT BITS(10, 13) /*!< USB turnaround time */ +#define GUSBCS_HNPCEN BIT(9) /*!< HNP capability enable */ +#define GUSBCS_SRPCEN BIT(8) /*!< SRP capability enable */ +#define GUSBCS_EMBPHY BIT(6) /*!< embedded PHY selected */ +#define GUSBCS_TOC BITS(0, 2) /*!< timeout calibration */ + +/* global reset control register bits definitions */ +#define GRSTCTL_DMAIDL BIT(31) /*!< DMA idle state */ +#define GRSTCTL_DMABSY BIT(30) /*!< DMA busy */ +#define GRSTCTL_TXFNUM BITS(6, 10) /*!< tx FIFO number */ +#define GRSTCTL_TXFF BIT(5) /*!< tx FIFO flush */ +#define GRSTCTL_RXFF BIT(4) /*!< rx FIFO flush */ +#define GRSTCTL_HFCRST BIT(2) /*!< host frame counter reset */ +#define GRSTCTL_HCSRST BIT(1) /*!< HCLK soft reset */ +#define GRSTCTL_CSRST BIT(0) /*!< core soft reset */ + +/* global interrupt flag register bits definitions */ +#define GINTF_WKUPIF BIT(31) /*!< wakeup interrupt flag */ +#define GINTF_SESIF BIT(30) /*!< session interrupt flag */ +#define GINTF_DISCIF BIT(29) /*!< disconnect interrupt flag */ +#define GINTF_IDPSC BIT(28) /*!< id pin status change */ +#define GINTF_PTXFEIF BIT(26) /*!< periodic tx FIFO empty interrupt flag */ +#define GINTF_HCIF BIT(25) /*!< host channels interrupt flag */ +#define GINTF_HPIF BIT(24) /*!< host port interrupt flag */ +#define GINTF_PXNCIF BIT(21) /*!< periodic transfer not complete interrupt flag */ +#define GINTF_ISOONCIF BIT(21) /*!< isochronous OUT transfer not complete interrupt flag */ +#define GINTF_ISOINCIF BIT(20) /*!< isochronous IN transfer not complete interrupt flag */ +#define GINTF_OEPIF BIT(19) /*!< OUT endpoint interrupt flag */ +#define GINTF_IEPIF BIT(18) /*!< IN endpoint interrupt flag */ +#define GINTF_EOPFIF BIT(15) /*!< end of periodic frame interrupt flag */ +#define GINTF_ISOOPDIF BIT(14) /*!< isochronous OUT packet dropped interrupt flag */ +#define GINTF_ENUMFIF BIT(13) /*!< enumeration finished */ +#define GINTF_RST BIT(12) /*!< USB reset */ +#define GINTF_SP BIT(11) /*!< USB suspend */ +#define GINTF_ESP BIT(10) /*!< early suspend */ +#define GINTF_GONAK BIT(7) /*!< global OUT NAK effective */ +#define GINTF_GNPINAK BIT(6) /*!< global IN non-periodic NAK effective */ +#define GINTF_NPTXFEIF BIT(5) /*!< non-periodic tx FIFO empty interrupt flag */ +#define GINTF_RXFNEIF BIT(4) /*!< rx FIFO non-empty interrupt flag */ +#define GINTF_SOF BIT(3) /*!< start of frame */ +#define GINTF_OTGIF BIT(2) /*!< OTG interrupt flag */ +#define GINTF_MFIF BIT(1) /*!< mode fault interrupt flag */ +#define GINTF_COPM BIT(0) /*!< current operation mode */ + +/* global interrupt enable register bits definitions */ +#define GINTEN_WKUPIE BIT(31) /*!< wakeup interrupt enable */ +#define GINTEN_SESIE BIT(30) /*!< session interrupt enable */ +#define GINTEN_DISCIE BIT(29) /*!< disconnect interrupt enable */ +#define GINTEN_IDPSCIE BIT(28) /*!< id pin status change interrupt enable */ +#define GINTEN_PTXFEIE BIT(26) /*!< periodic tx FIFO empty interrupt enable */ +#define GINTEN_HCIE BIT(25) /*!< host channels interrupt enable */ +#define GINTEN_HPIE BIT(24) /*!< host port interrupt enable */ +#define GINTEN_IPXIE BIT(21) /*!< periodic transfer not complete interrupt enable */ +#define GINTEN_ISOONCIE BIT(21) /*!< isochronous OUT transfer not complete interrupt enable */ +#define GINTEN_ISOINCIE BIT(20) /*!< isochronous IN transfer not complete interrupt enable */ +#define GINTEN_OEPIE BIT(19) /*!< OUT endpoints interrupt enable */ +#define GINTEN_IEPIE BIT(18) /*!< IN endpoints interrupt enable */ +#define GINTEN_EOPFIE BIT(15) /*!< end of periodic frame interrupt enable */ +#define GINTEN_ISOOPDIE BIT(14) /*!< isochronous OUT packet dropped interrupt enable */ +#define GINTEN_ENUMFIE BIT(13) /*!< enumeration finish enable */ +#define GINTEN_RSTIE BIT(12) /*!< USB reset interrupt enable */ +#define GINTEN_SPIE BIT(11) /*!< USB suspend interrupt enable */ +#define GINTEN_ESPIE BIT(10) /*!< early suspend interrupt enable */ +#define GINTEN_GONAKIE BIT(7) /*!< global OUT NAK effective interrupt enable */ +#define GINTEN_GNPINAKIE BIT(6) /*!< global non-periodic IN NAK effective interrupt enable */ +#define GINTEN_NPTXFEIE BIT(5) /*!< non-periodic Tx FIFO empty interrupt enable */ +#define GINTEN_RXFNEIE BIT(4) /*!< receive FIFO non-empty interrupt enable */ +#define GINTEN_SOFIE BIT(3) /*!< start of frame interrupt enable */ +#define GINTEN_OTGIE BIT(2) /*!< OTG interrupt enable */ +#define GINTEN_MFIE BIT(1) /*!< mode fault interrupt enable */ + +/* global receive status read and pop register bits definitions */ +#define GRSTATRP_RPCKST BITS(17, 20) /*!< received packet status */ +#define GRSTATRP_DPID BITS(15, 16) /*!< data PID */ +#define GRSTATRP_BCOUNT BITS(4, 14) /*!< byte count */ +#define GRSTATRP_CNUM BITS(0, 3) /*!< channel number */ +#define GRSTATRP_EPNUM BITS(0, 3) /*!< endpoint number */ + +/* global receive FIFO length register bits definitions */ +#define GRFLEN_RXFD BITS(0, 15) /*!< rx FIFO depth */ + +/* host non-periodic transmit FIFO length register bits definitions */ +#define HNPTFLEN_HNPTXFD BITS(16, 31) /*!< non-periodic Tx FIFO depth */ +#define HNPTFLEN_HNPTXRSAR BITS(0, 15) /*!< non-periodic Tx RAM start address */ + + +/* USB IN endpoint 0 transmit FIFO length register bits definitions */ +#define DIEP0TFLEN_IEP0TXFD BITS(16, 31) /*!< IN Endpoint 0 Tx FIFO depth */ +#define DIEP0TFLEN_IEP0TXRSAR BITS(0, 15) /*!< IN Endpoint 0 TX RAM start address */ + +/* host non-periodic transmit FIFO/queue status register bits definitions */ +#define HNPTFQSTAT_NPTXRQTOP BITS(24, 30) /*!< top entry of the non-periodic Tx request queue */ +#define HNPTFQSTAT_NPTXRQS BITS(16, 23) /*!< non-periodic Tx request queue space */ +#define HNPTFQSTAT_NPTXFS BITS(0, 15) /*!< non-periodic Tx FIFO space */ +#define HNPTFQSTAT_CNUM BITS(27, 30) /*!< channel number*/ +#define HNPTFQSTAT_EPNUM BITS(27, 30) /*!< endpoint number */ +#define HNPTFQSTAT_TYPE BITS(25, 26) /*!< token type */ +#define HNPTFQSTAT_TMF BIT(24) /*!< terminate flag */ + +/* global core configuration register bits definitions */ +#define GCCFG_VBUSIG BIT(21) /*!< vbus ignored */ +#define GCCFG_SOFOEN BIT(20) /*!< SOF output enable */ +#define GCCFG_VBUSBCEN BIT(19) /*!< the VBUS B-device comparer enable */ +#define GCCFG_VBUSACEN BIT(18) /*!< the VBUS A-device comparer enable */ +#define GCCFG_PWRON BIT(16) /*!< power on */ + +/* core ID register bits definitions */ +#define CID_CID BITS(0, 31) /*!< core ID */ + +/* host periodic transmit FIFO length register bits definitions */ +#define HPTFLEN_HPTXFD BITS(16, 31) /*!< host periodic Tx FIFO depth */ +#define HPTFLEN_HPTXFSAR BITS(0, 15) /*!< host periodic Tx RAM start address */ + +/* device IN endpoint transmit FIFO length register bits definitions */ +#define DIEPTFLEN_IEPTXFD BITS(16, 31) /*!< IN endpoint Tx FIFO x depth */ +#define DIEPTFLEN_IEPTXRSAR BITS(0, 15) /*!< IN endpoint FIFOx Tx x RAM start address */ + +/* host control register bits definitions */ +#define HCTL_SPDFSLS BIT(2) /*!< speed limited to FS and LS */ +#define HCTL_CLKSEL BITS(0, 1) /*!< clock select for USB clock */ + +/* host frame interval register bits definitions */ +#define HFT_FRI BITS(0, 15) /*!< frame interval */ + +/* host frame information remaining register bits definitions */ +#define HFINFR_FRT BITS(16, 31) /*!< frame remaining time */ +#define HFINFR_FRNUM BITS(0, 15) /*!< frame number */ + +/* host periodic transmit FIFO/queue status register bits definitions */ +#define HPTFQSTAT_PTXREQT BITS(24, 31) /*!< top entry of the periodic Tx request queue */ +#define HPTFQSTAT_PTXREQS BITS(16, 23) /*!< periodic Tx request queue space */ +#define HPTFQSTAT_PTXFS BITS(0, 15) /*!< periodic Tx FIFO space */ +#define HPTFQSTAT_OEFRM BIT(31) /*!< odd/eveb frame */ +#define HPTFQSTAT_CNUM BITS(27, 30) /*!< channel number */ +#define HPTFQSTAT_EPNUM BITS(27, 30) /*!< endpoint number */ +#define HPTFQSTAT_TYPE BITS(25, 26) /*!< token type */ +#define HPTFQSTAT_TMF BIT(24) /*!< terminate flag */ + + +#define TFQSTAT_TXFS BITS(0, 15) +#define TFQSTAT_CNUM BITS(27, 30) + +/* host all channels interrupt register bits definitions */ +#define HACHINT_HACHINT BITS(0, 11) /*!< host all channel interrupts */ + +/* host all channels interrupt enable register bits definitions */ +#define HACHINTEN_CINTEN BITS(0, 11) /*!< channel interrupt enable */ + +/* host port control and status register bits definitions */ +#define HPCS_PS BITS(17, 18) /*!< port speed */ +#define HPCS_PP BIT(12) /*!< port power */ +#define HPCS_PLST BITS(10, 11) /*!< port line status */ +#define HPCS_PRST BIT(8) /*!< port reset */ +#define HPCS_PSP BIT(7) /*!< port suspend */ +#define HPCS_PREM BIT(6) /*!< port resume */ +#define HPCS_PEDC BIT(3) /*!< port enable/disable change */ +#define HPCS_PE BIT(2) /*!< port enable */ +#define HPCS_PCD BIT(1) /*!< port connect detected */ +#define HPCS_PCST BIT(0) /*!< port connect status */ + +/* host channel-x control register bits definitions */ +#define HCHCTL_CEN BIT(31) /*!< channel enable */ +#define HCHCTL_CDIS BIT(30) /*!< channel disable */ +#define HCHCTL_ODDFRM BIT(29) /*!< odd frame */ +#define HCHCTL_DAR BITS(22, 28) /*!< device address */ +#define HCHCTL_MPC BITS(20, 21) /*!< multiple packet count */ +#define HCHCTL_EPTYPE BITS(18, 19) /*!< endpoint type */ +#define HCHCTL_LSD BIT(17) /*!< low-speed device */ +#define HCHCTL_EPDIR BIT(15) /*!< endpoint direction */ +#define HCHCTL_EPNUM BITS(11, 14) /*!< endpoint number */ +#define HCHCTL_MPL BITS(0, 10) /*!< maximum packet length */ + +/* host channel-x split transaction register bits definitions */ +#define HCHSTCTL_SPLEN BIT(31) /*!< enable high-speed split transaction */ +#define HCHSTCTL_CSPLT BIT(16) /*!< complete-split enable */ +#define HCHSTCTL_ISOPCE BITS(14, 15) /*!< isochronous OUT payload continuation encoding */ +#define HCHSTCTL_HADDR BITS(7, 13) /*!< HUB address */ +#define HCHSTCTL_PADDR BITS(0, 6) /*!< port address */ + +/* host channel-x interrupt flag register bits definitions */ +#define HCHINTF_DTER BIT(10) /*!< data toggle error */ +#define HCHINTF_REQOVR BIT(9) /*!< request queue overrun */ +#define HCHINTF_BBER BIT(8) /*!< babble error */ +#define HCHINTF_USBER BIT(7) /*!< USB bus Error */ +#define HCHINTF_NYET BIT(6) /*!< NYET */ +#define HCHINTF_ACK BIT(5) /*!< ACK */ +#define HCHINTF_NAK BIT(4) /*!< NAK */ +#define HCHINTF_STALL BIT(3) /*!< STALL */ +#define HCHINTF_DMAER BIT(2) /*!< DMA error */ +#define HCHINTF_CH BIT(1) /*!< channel halted */ +#define HCHINTF_TF BIT(0) /*!< transfer finished */ + +/* host channel-x interrupt enable register bits definitions */ +#define HCHINTEN_DTERIE BIT(10) /*!< data toggle error interrupt enable */ +#define HCHINTEN_REQOVRIE BIT(9) /*!< request queue overrun interrupt enable */ +#define HCHINTEN_BBERIE BIT(8) /*!< babble error interrupt enable */ +#define HCHINTEN_USBERIE BIT(7) /*!< USB bus error interrupt enable */ +#define HCHINTEN_NYETIE BIT(6) /*!< NYET interrupt enable */ +#define HCHINTEN_ACKIE BIT(5) /*!< ACK interrupt enable */ +#define HCHINTEN_NAKIE BIT(4) /*!< NAK interrupt enable */ +#define HCHINTEN_STALLIE BIT(3) /*!< STALL interrupt enable */ +#define HCHINTEN_DMAERIE BIT(2) /*!< DMA error interrupt enable */ +#define HCHINTEN_CHIE BIT(1) /*!< channel halted interrupt enable */ +#define HCHINTEN_TFIE BIT(0) /*!< transfer finished interrupt enable */ + +/* host channel-x transfer length register bits definitions */ +#define HCHLEN_PING BIT(31) /*!< PING token request */ +#define HCHLEN_DPID BITS(29, 30) /*!< data PID */ +#define HCHLEN_PCNT BITS(19, 28) /*!< packet count */ +#define HCHLEN_TLEN BITS(0, 18) /*!< transfer length */ + +/* host channel-x DMA address register bits definitions */ +#define HCHDMAADDR_DMAADDR BITS(0, 31) /*!< DMA address */ + + +#define PORT_SPEED(x) (((uint32_t)(x) << 17) & HPCS_PS) /*!< Port speed */ + +#define PORT_SPEED_HIGH PORT_SPEED(0U) /*!< high speed */ +#define PORT_SPEED_FULL PORT_SPEED(1U) /*!< full speed */ +#define PORT_SPEED_LOW PORT_SPEED(2U) /*!< low speed */ + +#define PIPE_CTL_DAR(x) (((uint32_t)(x) << 22) & HCHCTL_DAR) /*!< device address */ +#define PIPE_CTL_EPTYPE(x) (((uint32_t)(x) << 18) & HCHCTL_EPTYPE) /*!< endpoint type */ +#define PIPE_CTL_EPNUM(x) (((uint32_t)(x) << 11) & HCHCTL_EPNUM) /*!< endpoint number */ +#define PIPE_CTL_EPDIR(x) (((uint32_t)(x) << 15) & HCHCTL_EPDIR) /*!< endpoint direction */ +#define PIPE_CTL_EPMPL(x) (((uint32_t)(x) << 0) & HCHCTL_MPL) /*!< maximum packet length */ +#define PIPE_CTL_LSD(x) (((uint32_t)(x) << 17) & HCHCTL_LSD) /*!< low-Speed device */ + +#define PIPE_XFER_PCNT(x) (((uint32_t)(x) << 19) & HCHLEN_PCNT) /*!< packet count */ +#define PIPE_XFER_DPID(x) (((uint32_t)(x) << 29) & HCHLEN_DPID) /*!< data PID */ + +#define PIPE_DPID_DATA0 PIPE_XFER_DPID(0) /*!< DATA0 */ +#define PIPE_DPID_DATA1 PIPE_XFER_DPID(2) /*!< DATA1 */ +#define PIPE_DPID_DATA2 PIPE_XFER_DPID(1) /*!< DATA2 */ +#define PIPE_DPID_SETUP PIPE_XFER_DPID(3) /*!< MDATA (non-control)/SETUP (control) */ + +extern const uint32_t PIPE_DPID[2]; + +/* device configuration registers bits definitions */ +#define DCFG_EOPFT BITS(11, 12) /*!< end of periodic frame time */ +#define DCFG_DAR BITS(4, 10) /*!< device address */ +#define DCFG_NZLSOH BIT(2) /*!< non-zero-length status OUT handshake */ +#define DCFG_DS BITS(0, 1) /*!< device speed */ + +/* device control registers bits definitions */ +#define DCTL_POIF BIT(11) /*!< power-on initialization finished */ +#define DCTL_CGONAK BIT(10) /*!< clear global OUT NAK */ +#define DCTL_SGONAK BIT(9) /*!< set global OUT NAK */ +#define DCTL_CGINAK BIT(8) /*!< clear global IN NAK */ +#define DCTL_SGINAK BIT(7) /*!< set global IN NAK */ +#define DCTL_GONS BIT(3) /*!< global OUT NAK status */ +#define DCTL_GINS BIT(2) /*!< global IN NAK status */ +#define DCTL_SD BIT(1) /*!< soft disconnect */ +#define DCTL_RWKUP BIT(0) /*!< remote wakeup */ + +/* device status registers bits definitions */ +#define DSTAT_FNRSOF BITS(8, 21) /*!< the frame number of the received SOF. */ +#define DSTAT_ES BITS(1, 2) /*!< enumerated speed */ +#define DSTAT_SPST BIT(0) /*!< suspend status */ + +/* device IN endpoint common interrupt enable registers bits definitions */ +#define DIEPINTEN_NAKEN BIT(13) /*!< NAK handshake sent by USBHS interrupt enable bit */ +#define DIEPINTEN_TXFEEN BIT(7) /*!< transmit FIFO empty interrupt enable bit */ +#define DIEPINTEN_IEPNEEN BIT(6) /*!< IN endpoint NAK effective interrupt enable bit */ +#define DIEPINTEN_EPTXFUDEN BIT(4) /*!< endpoint Tx FIFO underrun interrupt enable bit */ +#define DIEPINTEN_CITOEN BIT(3) /*!< control In Timeout interrupt enable bit */ +#define DIEPINTEN_EPDISEN BIT(1) /*!< endpoint disabled interrupt enable bit */ +#define DIEPINTEN_TFEN BIT(0) /*!< transfer finished interrupt enable bit */ + +/* device OUT endpoint common interrupt enable registers bits definitions */ +#define DOEPINTEN_NYETEN BIT(14) /*!< NYET handshake is sent interrupt enable bit */ +#define DOEPINTEN_BTBSTPEN BIT(6) /*!< back-to-back SETUP packets interrupt enable bit */ +#define DOEPINTEN_EPRXFOVREN BIT(4) /*!< endpoint Rx FIFO overrun interrupt enable bit */ +#define DOEPINTEN_STPFEN BIT(3) /*!< SETUP phase finished interrupt enable bit */ +#define DOEPINTEN_EPDISEN BIT(1) /*!< endpoint disabled interrupt enable bit */ +#define DOEPINTEN_TFEN BIT(0) /*!< transfer finished interrupt enable bit */ + +/* device all endpoints interrupt registers bits definitions */ +#define DAEPINT_OEPITB BITS(16, 21) /*!< device all OUT endpoint interrupt bits */ +#define DAEPINT_IEPITB BITS(0, 5) /*!< device all IN endpoint interrupt bits */ + +/* device all endpoints interrupt enable registers bits definitions */ +#define DAEPINTEN_OEPIE BITS(16, 21) /*!< OUT endpoint interrupt enable */ +#define DAEPINTEN_IEPIE BITS(0, 3) /*!< IN endpoint interrupt enable */ + +/* device Vbus discharge time registers bits definitions */ +#define DVBUSDT_DVBUSDT BITS(0, 15) /*!< device VBUS discharge time */ + +/* device Vbus pulsing time registers bits definitions */ +#define DVBUSPT_DVBUSPT BITS(0, 11) /*!< device VBUS pulsing time */ + +/* device IN endpoint FIFO empty interrupt enable register bits definitions */ +#define DIEPFEINTEN_IEPTXFEIE BITS(0, 5) /*!< IN endpoint Tx FIFO empty interrupt enable bits */ + +/* device endpoint 0 control register bits definitions */ +#define DEP0CTL_EPEN BIT(31) /*!< endpoint enable */ +#define DEP0CTL_EPD BIT(30) /*!< endpoint disable */ +#define DEP0CTL_SNAK BIT(27) /*!< set NAK */ +#define DEP0CTL_CNAK BIT(26) /*!< clear NAK */ +#define DIEP0CTL_TXFNUM BITS(22, 25) /*!< tx FIFO number */ +#define DEP0CTL_STALL BIT(21) /*!< STALL handshake */ +#define DOEP0CTL_SNOOP BIT(20) /*!< snoop mode */ +#define DEP0CTL_EPTYPE BITS(18, 19) /*!< endpoint type */ +#define DEP0CTL_NAKS BIT(17) /*!< NAK status */ +#define DEP0CTL_EPACT BIT(15) /*!< endpoint active */ +#define DEP0CTL_MPL BITS(0, 1) /*!< maximum packet length */ + +/* device endpoint x control register bits definitions */ +#define DEPCTL_EPEN BIT(31) /*!< endpoint enable */ +#define DEPCTL_EPD BIT(30) /*!< endpoint disable */ +#define DEPCTL_SODDFRM BIT(29) /*!< set odd frame */ +#define DEPCTL_SD1PID BIT(29) /*!< set DATA1 PID */ +#define DEPCTL_SEVNFRM BIT(28) /*!< set even frame */ +#define DEPCTL_SD0PID BIT(28) /*!< set DATA0 PID */ +#define DEPCTL_SNAK BIT(27) /*!< set NAK */ +#define DEPCTL_CNAK BIT(26) /*!< clear NAK */ +#define DIEPCTL_TXFNUM BITS(22, 25) /*!< tx FIFO number */ +#define DEPCTL_STALL BIT(21) /*!< STALL handshake */ +#define DOEPCTL_SNOOP BIT(20) /*!< snoop mode */ +#define DEPCTL_EPTYPE BITS(18, 19) /*!< endpoint type */ +#define DEPCTL_NAKS BIT(17) /*!< NAK status */ +#define DEPCTL_EOFRM BIT(16) /*!< even/odd frame */ +#define DEPCTL_DPID BIT(16) /*!< endpoint data PID */ +#define DEPCTL_EPACT BIT(15) /*!< endpoint active */ +#define DEPCTL_MPL BITS(0, 10) /*!< maximum packet length */ + +/* device IN endpoint-x interrupt flag register bits definitions */ +#define DIEPINTF_NAK BIT(13) /*!< NAK handshake sent by USBHS */ +#define DIEPINTF_TXFE BIT(7) /*!< transmit FIFO empty */ +#define DIEPINTF_IEPNE BIT(6) /*!< IN endpoint NAK effective */ +#define DIEPINTF_EPTXFUD BIT(4) /*!< endpoint Tx FIFO underrun */ +#define DIEPINTF_CITO BIT(3) /*!< control In Timeout interrupt */ +#define DIEPINTF_EPDIS BIT(1) /*!< endpoint disabled */ +#define DIEPINTF_TF BIT(0) /*!< transfer finished */ + +/* device OUT endpoint-x interrupt flag register bits definitions */ +#define DOEPINTF_NYET BIT(14) /*!< NYET handshake is sent */ +#define DOEPINTF_BTBSTP BIT(6) /*!< back-to-back SETUP packets */ +#define DOEPINTF_EPRXFOVR BIT(4) /*!< endpoint Rx FIFO overrun */ +#define DOEPINTF_STPF BIT(3) /*!< SETUP phase finished */ +#define DOEPINTF_EPDIS BIT(1) /*!< endpoint disabled */ +#define DOEPINTF_TF BIT(0) /*!< transfer finished */ + +/* device IN endpoint 0 transfer length register bits definitions */ +#define DIEP0LEN_PCNT BITS(19, 20) /*!< packet count */ +#define DIEP0LEN_TLEN BITS(0, 6) /*!< transfer length */ + +/* device OUT endpoint 0 transfer length register bits definitions */ +#define DOEP0LEN_STPCNT BITS(29, 30) /*!< SETUP packet count */ +#define DOEP0LEN_PCNT BIT(19) /*!< packet count */ +#define DOEP0LEN_TLEN BITS(0, 6) /*!< transfer length */ + +/* device OUT endpoint-x transfer length register bits definitions */ +#define DOEPLEN_RXDPID BITS(29, 30) /*!< received data PID */ +#define DOEPLEN_STPCNT BITS(29, 30) /*!< SETUP packet count */ +#define DIEPLEN_MCNT BITS(29, 30) /*!< multi count */ +#define DEPLEN_PCNT BITS(19, 28) /*!< packet count */ +#define DEPLEN_TLEN BITS(0, 18) /*!< transfer length */ + +/* device IN endpoint-x DMA address register bits definitions */ +#define DIEPDMAADDR_DMAADDR BITS(0, 31) /*!< DMA address */ + +/* device OUT endpoint-x DMA address register bits definitions */ +#define DOEPDMAADDR_DMAADDR BITS(0, 31) /*!< DMA address */ + +/* device IN endpoint-x transmit FIFO status register bits definitions */ +#define DIEPTFSTAT_IEPTFS BITS(0, 15) /*!< IN endpoint Tx FIFO space remaining */ + +/* USB power and clock registers bits definition */ +#define PWRCLKCTL_SHCLK BIT(1) /*!< stop HCLK */ +#define PWRCLKCTL_SUCLK BIT(0) /*!< stop the USB clock */ + +#define RSTAT_GOUT_NAK 1U /* global OUT NAK (triggers an interrupt) */ +#define RSTAT_DATA_UPDT 2U /* OUT data packet received */ +#define RSTAT_XFER_COMP 3U /* OUT transfer completed (triggers an interrupt) */ +#define RSTAT_SETUP_COMP 4U /* SETUP transaction completed (triggers an interrupt) */ +#define RSTAT_SETUP_UPDT 6U /* SETUP data packet received */ + +#define DSTAT_EM_HS_PHY_30MHZ_60MHZ 0U /* USB enumerate speed use high-speed PHY clock in 30MHz or 60MHz */ +#define DSTAT_EM_FS_PHY_30MHZ_60MHZ 1U /* USB enumerate speed use full-speed PHY clock in 30MHz or 60MHz */ +#define DSTAT_EM_LS_PHY_6MHZ 2U /* USB enumerate speed use low-speed PHY clock in 6MHz */ +#define DSTAT_EM_FS_PHY_48MHZ 3U /* USB enumerate speed use full-speed PHY clock in 48MHz */ + +#define DPID_DATA0 0U /* device endpoint data PID is DATA0 */ +#define DPID_DATA1 2U /* device endpoint data PID is DATA1 */ +#define DPID_DATA2 1U /* device endpoint data PID is DATA2 */ +#define DPID_MDATA 3U /* device endpoint data PID is MDATA */ + +#define GAHBCS_DMAINCR(regval) (GAHBCS_BURST & ((regval) << 1)) /*!< AHB burst type used by DMA*/ + +#define DMA_INCR0 GAHBCS_DMAINCR(0U) /*!< single burst type used by DMA*/ +#define DMA_INCR1 GAHBCS_DMAINCR(1U) /*!< 4-beat incrementing burst type used by DMA*/ +#define DMA_INCR4 GAHBCS_DMAINCR(3U) /*!< 8-beat incrementing burst type used by DMA*/ +#define DMA_INCR8 GAHBCS_DMAINCR(5U) /*!< 16-beat incrementing burst type used by DMA*/ +#define DMA_INCR16 GAHBCS_DMAINCR(7U) /*!< 32-beat incrementing burst type used by DMA*/ + +#define DCFG_PFRI(regval) (DCFG_EOPFT & ((regval) << 11)) /*!< end of periodic frame time configuration */ + +#define FRAME_INTERVAL_80 DCFG_PFRI(0U) /*!< 80% of the frame time */ +#define FRAME_INTERVAL_85 DCFG_PFRI(1U) /*!< 85% of the frame time */ +#define FRAME_INTERVAL_90 DCFG_PFRI(2U) /*!< 90% of the frame time */ +#define FRAME_INTERVAL_95 DCFG_PFRI(3U) /*!< 95% of the frame time */ + +#define DCFG_DEVSPEED(regval) (DCFG_DS & ((regval) << 0)) /*!< device speed configuration */ + +#define USB_SPEED_EXP_HIGH DCFG_DEVSPEED(0U) /*!< device external PHY high speed */ +#define USB_SPEED_EXP_FULL DCFG_DEVSPEED(1U) /*!< device external PHY full speed */ +#define USB_SPEED_INP_FULL DCFG_DEVSPEED(3U) /*!< device internal PHY full speed */ + +#define DEP0_MPL(regval) (DEP0CTL_MPL & ((regval) << 0)) /*!< maximum packet length configuration */ + +#define EP0MPL_64 DEP0_MPL(0U) /*!< maximum packet length 64 bytes */ +#define EP0MPL_32 DEP0_MPL(1U) /*!< maximum packet length 32 bytes */ +#define EP0MPL_16 DEP0_MPL(2U) /*!< maximum packet length 16 bytes */ +#define EP0MPL_8 DEP0_MPL(3U) /*!< maximum packet length 8 bytes */ + +#define DOEP0_TLEN(regval) (DOEP0LEN_TLEN & ((regval) << 0)) /*!< Transfer length */ +#define DOEP0_PCNT(regval) (DOEP0LEN_PCNT & ((regval) << 19)) /*!< Packet count */ +#define DOEP0_STPCNT(regval) (DOEP0LEN_STPCNT & ((regval) << 29)) /*!< SETUP packet count */ + +#define USB_ULPI_PHY 1U /*!< ULPI interface external PHY */ +#define USB_EMBEDDED_PHY 2U /*!< Embedded PHY */ + +#define GRXSTS_PKTSTS_IN 2U +#define GRXSTS_PKTSTS_IN_XFER_COMP 3U +#define GRXSTS_PKTSTS_DATA_TOGGLE_ERR 5U +#define GRXSTS_PKTSTS_CH_HALTED 7U + +#define HCTL_30_60MHZ 0U /*!< USB clock 30-60MHZ */ +#define HCTL_48MHZ 1U /*!< USB clock 48MHZ */ +#define HCTL_6MHZ 2U /*!< USB clock 6MHZ */ + +#define EP0_OUT ((uint8_t)0x00) /*!< endpoint out 0 */ +#define EP0_IN ((uint8_t)0x80) /*!< endpoint in 0 */ +#define EP1_OUT ((uint8_t)0x01) /*!< endpoint out 1 */ +#define EP1_IN ((uint8_t)0x81) /*!< endpoint in 1 */ +#define EP2_OUT ((uint8_t)0x02) /*!< endpoint out 2 */ +#define EP2_IN ((uint8_t)0x82) /*!< endpoint in 2 */ +#define EP3_OUT ((uint8_t)0x03) /*!< endpoint out 3 */ +#define EP3_IN ((uint8_t)0x83) /*!< endpoint in 3 */ + +#endif /* __DRV_USB_REGS_H */ diff --git a/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/driver/Include/drv_usbd_int.h b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/driver/Include/drv_usbd_int.h new file mode 100644 index 0000000000..6988702f2f --- /dev/null +++ b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/driver/Include/drv_usbd_int.h @@ -0,0 +1,45 @@ +/*! + \file drv_usbd_int.h + \brief USB device mode interrupt header file + + \version 2020-07-28, V3.0.0, firmware for GD32F20x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef __DRV_USBD_INT_H +#define __DRV_USBD_INT_H + +#include "drv_usb_core.h" +#include "drv_usb_dev.h" + +/* function declarations */ +/* USB device-mode interrupts global service routine handler */ +void usbd_isr (usb_core_driver *udev); + +#endif /* __DRV_USBD_INT_H */ diff --git a/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/driver/Include/drv_usbh_int.h b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/driver/Include/drv_usbh_int.h new file mode 100644 index 0000000000..5a79112e9b --- /dev/null +++ b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/driver/Include/drv_usbh_int.h @@ -0,0 +1,56 @@ +/*! + \file drv_usbh_int.h.h + \brief USB host mode interrupt management header file + + \version 2020-07-28, V3.0.0, firmware for GD32F20x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef __DRV_USBH_INT_H +#define __DRV_USBH_INT_H + +#include "drv_usb_host.h" +#include "usbh_core.h" + +typedef struct _usbh_int_cb +{ + uint8_t (*connect) (usbh_host *uhost); + uint8_t (*disconnect) (usbh_host *uhost); + uint8_t (*port_enabled) (usbh_host *uhost); + uint8_t (*port_disabled) (usbh_host *uhost); + uint8_t (*SOF) (usbh_host *uhost); +} usbh_int_cb; + +extern usbh_int_cb *usbh_int_fop; + +/* function declarations */ +/* handle global host interrupt */ +uint32_t usbh_isr (usb_core_driver *udev); + +#endif /* __DRV_USBH_INT_H */ diff --git a/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/driver/Source/drv_usb_core.c b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/driver/Source/drv_usb_core.c new file mode 100644 index 0000000000..392d63f0a1 --- /dev/null +++ b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/driver/Source/drv_usb_core.c @@ -0,0 +1,344 @@ +/*! + \file drv_usb_core.c + \brief USB core driver which can operate in host and device mode + + \version 2020-07-28, V3.0.0, firmware for GD32F20x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "drv_usb_core.h" +#include "drv_usb_hw.h" + +/* local function prototypes ('static') */ +static void usb_core_reset (usb_core_regs *usb_regs); + +/*! + \brief configure USB core basic + \param[in] usb_basic: pointer to usb capabilities + \param[in] usb_regs: USB core registers + \param[in] usb_core: USB core + \param[out] none + \retval operation status +*/ +usb_status usb_basic_init (usb_core_basic *usb_basic, + usb_core_regs *usb_regs, + usb_core_enum usb_core) +{ + /* configure USB default transfer mode as FIFO mode */ + usb_basic->transfer_mode = (uint8_t)USB_USE_FIFO; + + /* USB default speed is full-speed */ + usb_basic->core_speed = (uint8_t)USB_SPEED_FULL; + + usb_basic->core_enum = (uint8_t)usb_core; + + switch (usb_core) { + case USB_CORE_ENUM_FS: + usb_basic->base_reg = (uint32_t)USBFS_REG_BASE; + + /* set the host channel numbers */ + usb_basic->num_pipe = USBFS_MAX_CHANNEL_COUNT; + + /* set the device endpoint numbers */ + usb_basic->num_ep = USBFS_MAX_EP_COUNT; + + /* USBFS core use embedded physical layer */ + usb_basic->phy_itf = USB_EMBEDDED_PHY; + break; + + default: + return USB_FAIL; + } + + usb_basic->sof_enable = USB_SOF_OUTPUT; + usb_basic->low_power = USB_LOW_POWER; + + /* assign main registers address */ + *usb_regs = (usb_core_regs) { + .gr = (usb_gr*) (usb_basic->base_reg + USB_REG_OFFSET_CORE), + .hr = (usb_hr*) (usb_basic->base_reg + USB_REG_OFFSET_HOST), + .dr = (usb_dr*) (usb_basic->base_reg + USB_REG_OFFSET_DEV), + + .HPCS = (uint32_t*) (usb_basic->base_reg + USB_REG_OFFSET_PORT), + .PWRCLKCTL = (uint32_t*) (usb_basic->base_reg + USB_REG_OFFSET_PWRCLKCTL) + }; + + /* assign device endpoint registers address */ + for (uint8_t i = 0U; i < usb_basic->num_ep; i++) { + usb_regs->er_in[i] = (usb_erin *) \ + (usb_basic->base_reg + USB_REG_OFFSET_EP_IN + (i * USB_REG_OFFSET_EP)); + + usb_regs->er_out[i] = (usb_erout *)\ + (usb_basic->base_reg + USB_REG_OFFSET_EP_OUT + (i * USB_REG_OFFSET_EP)); + } + + /* assign host pipe registers address */ + for (uint8_t i = 0U; i < usb_basic->num_pipe; i++) { + usb_regs->pr[i] = (usb_pr *) \ + (usb_basic->base_reg + USB_REG_OFFSET_CH_INOUT + (i * USB_REG_OFFSET_CH)); + + usb_regs->DFIFO[i] = (uint32_t *) \ + (usb_basic->base_reg + USB_DATA_FIFO_OFFSET + (i * USB_DATA_FIFO_SIZE)); + } + + return USB_OK; +} + +/*! + \brief initializes the USB controller registers and + prepares the core device mode or host mode operation + \param[in] usb_basic: pointer to USB capabilities + \param[in] usb_regs: pointer to USB core registers + \param[out] none + \retval operation status +*/ +usb_status usb_core_init (usb_core_basic usb_basic, usb_core_regs *usb_regs) +{ + if (USB_ULPI_PHY == usb_basic.phy_itf) { + usb_regs->gr->GCCFG &= ~GCCFG_PWRON; + + if (usb_basic.sof_enable) { + usb_regs->gr->GCCFG |= GCCFG_SOFOEN; + } + + /* initializes the ULPI interface */ + usb_regs->gr->GUSBCS &= ~(GUSBCS_EMBPHY | GUSBCS_ULPIEOI); + +#ifdef USBHS_EXTERNAL_VBUS_ENABLED + /* use external VBUS driver */ + usb_regs->gr->GUSBCS |= GUSBCS_ULPIEVD; +#else + /* use internal VBUS driver */ + usb_regs->gr->GUSBCS &= ~GUSBCS_ULPIEVD; +#endif /* USBHS_EXTERNAL_VBUS_ENABLED */ + + /* soft reset the core */ + usb_core_reset (usb_regs); + } else { + usb_regs->gr->GUSBCS |= GUSBCS_EMBPHY; + + /* soft reset the core */ + usb_core_reset (usb_regs); + + /* active the transceiver and enable VBUS sensing */ + usb_regs->gr->GCCFG |= GCCFG_PWRON | GCCFG_VBUSACEN | GCCFG_VBUSBCEN; + +#ifndef VBUS_SENSING_ENABLED + usb_regs->gr->GCCFG |= GCCFG_VBUSIG; +#endif /* VBUS_SENSING_ENABLED */ + + /* enable SOF output */ + if (usb_basic.sof_enable) { + usb_regs->gr->GCCFG |= GCCFG_SOFOEN; + } + + usb_mdelay(20U); + } + + if ((uint8_t)USB_USE_DMA == usb_basic.transfer_mode) { + usb_regs->gr->GAHBCS &= ~GAHBCS_BURST; + usb_regs->gr->GAHBCS |= DMA_INCR8 | GAHBCS_DMAEN; + } + +#ifdef USE_OTG_MODE + + /* enable USB OTG features */ + usb_regs->gr->GUSBCS |= GUSBCS_HNPCEN | GUSBCS_SRPCEN; + + /* enable the USB wakeup and suspend interrupts */ + usb_regs->gr->GINTF = 0xBFFFFFFFU; + + usb_regs->gr->GINTEN = GINTEN_WKUPIE | GINTEN_SPIE | \ + GINTEN_OTGIE | GINTEN_SESIE | GINTEN_CIDPSCIE; + +#endif /* USE_OTG_MODE */ + + return USB_OK; +} + +/*! + \brief write a packet into the Tx FIFO associated with the endpoint + \param[in] usb_regs: pointer to USB core registers + \param[in] src_buf: pointer to source buffer + \param[in] fifo_num: FIFO number which is in (0..3) + \param[in] byte_count: packet byte count + \param[out] none + \retval operation status +*/ +usb_status usb_txfifo_write (usb_core_regs *usb_regs, + uint8_t *src_buf, + uint8_t fifo_num, + uint16_t byte_count) +{ + uint32_t word_count = (byte_count + 3U) / 4U; + + __IO uint32_t *fifo = usb_regs->DFIFO[fifo_num]; + + while (word_count-- > 0U) { + *fifo = *((__packed uint32_t *)src_buf); + + src_buf += 4U; + } + + return USB_OK; +} + +/*! + \brief read a packet from the Rx FIFO associated with the endpoint + \param[in] usb_regs: pointer to USB core registers + \param[in] dest_buf: pointer to destination buffer + \param[in] byte_count: packet byte count + \param[out] none + \retval void type pointer +*/ +void *usb_rxfifo_read (usb_core_regs *usb_regs, uint8_t *dest_buf, uint16_t byte_count) +{ + uint32_t word_count = (byte_count + 3U) / 4U; + + __IO uint32_t *fifo = usb_regs->DFIFO[0]; + + while (word_count-- > 0U) { + *(__packed uint32_t *)dest_buf = *fifo; + + dest_buf += 4U; + } + + return ((void *)dest_buf); +} + +/*! + \brief flush a Tx FIFO or all Tx FIFOs + \param[in] usb_regs: pointer to USB core registers + \param[in] fifo_num: FIFO number which is in (0..3) + \param[out] none + \retval operation status +*/ +usb_status usb_txfifo_flush (usb_core_regs *usb_regs, uint8_t fifo_num) +{ + usb_regs->gr->GRSTCTL = ((uint32_t)fifo_num << 6U) | GRSTCTL_TXFF; + + /* wait for Tx FIFO flush bit is set */ + while (usb_regs->gr->GRSTCTL & GRSTCTL_TXFF) { + /* no operation */ + } + + /* wait for 3 PHY clocks*/ + usb_udelay(3U); + + return USB_OK; +} + +/*! + \brief flush the entire Rx FIFO + \param[in] usb_regs: pointer to usb core registers + \param[out] none + \retval operation status +*/ +usb_status usb_rxfifo_flush (usb_core_regs *usb_regs) +{ + usb_regs->gr->GRSTCTL = GRSTCTL_RXFF; + + /* wait for Rx FIFO flush bit is set */ + while (usb_regs->gr->GRSTCTL & GRSTCTL_RXFF) { + /* no operation */ + } + + /* wait for 3 PHY clocks */ + usb_udelay(3U); + + return USB_OK; +} + +/*! + \brief set endpoint or channel TX FIFO size + \param[in] usb_regs: pointer to USB core registers + \param[in] fifo: TX FIFO number + \param[in] size: assigned TX FIFO size + \param[out] none + \retval none +*/ +void usb_set_txfifo(usb_core_regs *usb_regs, uint8_t fifo, uint16_t size) +{ + uint32_t tx_offset; + + tx_offset = usb_regs->gr->GRFLEN; + + if (0U == fifo) { + usb_regs->gr->DIEP0TFLEN_HNPTFLEN = ((uint32_t)size << 16) | tx_offset; + } else { + tx_offset += (usb_regs->gr->DIEP0TFLEN_HNPTFLEN) >> 16; + + for (uint8_t i = 0U; i < (fifo - 1U); i++) { + tx_offset += (usb_regs->gr->DIEPTFLEN[i] >> 16); + } + + /* multiply Tx_Size by 2 to get higher performance */ + usb_regs->gr->DIEPTFLEN[fifo - 1U] = ((uint32_t)size << 16) | tx_offset; + } +} + +/*! + \brief set USB current mode + \param[in] usb_regs: pointer to USB core registers + \param[out] none + \retval none +*/ +void usb_curmode_set(usb_core_regs *usb_regs, uint8_t mode) +{ + usb_regs->gr->GUSBCS &= ~(GUSBCS_FDM | GUSBCS_FHM); + + if (DEVICE_MODE == mode) { + usb_regs->gr->GUSBCS |= GUSBCS_FDM; + } else if (HOST_MODE == mode) { + usb_regs->gr->GUSBCS |= GUSBCS_FHM; + } else { + /* OTG mode and other mode can not be here! */ + } +} + +/*! + \brief configure USB core to soft reset + \param[in] usb_regs: pointer to USB core registers + \param[out] none + \retval none +*/ +static void usb_core_reset (usb_core_regs *usb_regs) +{ + /* enable core soft reset */ + usb_regs->gr->GRSTCTL |= GRSTCTL_CSRST; + + /* wait for the core to be soft reset */ + while (usb_regs->gr->GRSTCTL & GRSTCTL_CSRST) { + /* no operation */ + } + + /* wait for additional 3 PHY clocks */ + usb_udelay(3U); +} + diff --git a/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/driver/Source/drv_usb_dev.c b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/driver/Source/drv_usb_dev.c new file mode 100644 index 0000000000..dae3b0e610 --- /dev/null +++ b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/driver/Source/drv_usb_dev.c @@ -0,0 +1,612 @@ +/*! + \file drv_usb_dev.c + \brief USB device mode low level driver + + \version 2020-07-28, V3.0.0, firmware for GD32F20x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "drv_usb_hw.h" +#include "drv_usb_core.h" +#include "drv_usb_dev.h" + +/* endpoint 0 max packet length */ +static const uint8_t EP0_MAXLEN[4] = { + [DSTAT_EM_HS_PHY_30MHZ_60MHZ] = EP0MPL_64, + [DSTAT_EM_FS_PHY_30MHZ_60MHZ] = EP0MPL_64, + [DSTAT_EM_FS_PHY_48MHZ] = EP0MPL_64, + [DSTAT_EM_LS_PHY_6MHZ] = EP0MPL_8 +}; + +#ifdef USB_FS_CORE + +/* USB endpoint Tx FIFO size */ +static uint16_t USBFS_TX_FIFO_SIZE[USBFS_MAX_EP_COUNT] = +{ + (uint16_t)TX0_FIFO_FS_SIZE, + (uint16_t)TX1_FIFO_FS_SIZE, + (uint16_t)TX2_FIFO_FS_SIZE, + (uint16_t)TX3_FIFO_FS_SIZE +}; + +#endif /* USBFS_CORE */ + +/*! + \brief initialize USB core registers for device mode + \param[in] udev: pointer to USB device + \param[out] none + \retval operation status +*/ +usb_status usb_devcore_init (usb_core_driver *udev) +{ + uint8_t i; + + /* restart the PHY clock (maybe don't need to...) */ + *udev->regs.PWRCLKCTL = 0U; + + /* configure periodic frame interval to default value */ + udev->regs.dr->DCFG &= ~DCFG_EOPFT; + udev->regs.dr->DCFG |= FRAME_INTERVAL_80; + + udev->regs.dr->DCFG &= ~DCFG_DS; + +#ifdef USB_FS_CORE + if (udev->bp.core_enum == (uint8_t)USB_CORE_ENUM_FS) { + /* set full-speed PHY */ + udev->regs.dr->DCFG |= USB_SPEED_INP_FULL; + + /* set Rx FIFO size */ + usb_set_rxfifo(&udev->regs, RX_FIFO_FS_SIZE); + + /* set endpoint 1 to 3's Tx FIFO length and RAM address */ + for (i = 0U; i < USBFS_MAX_EP_COUNT; i++) { + usb_set_txfifo(&udev->regs, i, USBFS_TX_FIFO_SIZE[i]); + } + } +#endif /* USB_FS_CORE */ + + /* make sure all FIFOs are flushed */ + + /* flush all Tx FIFOs */ + (void)usb_txfifo_flush (&udev->regs, 0x10U); + + /* flush entire Rx FIFO */ + (void)usb_rxfifo_flush (&udev->regs); + + /* clear all pending device interrupts */ + udev->regs.dr->DIEPINTEN = 0U; + udev->regs.dr->DOEPINTEN = 0U; + udev->regs.dr->DAEPINT = 0xFFFFFFFFU; + udev->regs.dr->DAEPINTEN = 0U; + + /* configure all IN/OUT endpoints */ + for (i = 0U; i < udev->bp.num_ep; i++) { + if (udev->regs.er_in[i]->DIEPCTL & DEPCTL_EPEN) { + udev->regs.er_in[i]->DIEPCTL |= DEPCTL_EPD | DEPCTL_SNAK; + } else { + udev->regs.er_in[i]->DIEPCTL = 0U; + } + + /* set IN endpoint transfer length to 0 */ + udev->regs.er_in[i]->DIEPLEN = 0U; + + /* clear all pending IN endpoint interrupts */ + udev->regs.er_in[i]->DIEPINTF = 0xFFU; + + if (udev->regs.er_out[i]->DOEPCTL & DEPCTL_EPEN) { + udev->regs.er_out[i]->DOEPCTL |= DEPCTL_EPD | DEPCTL_SNAK; + } else { + udev->regs.er_out[i]->DOEPCTL = 0U; + } + + /* set OUT endpoint transfer length to 0 */ + udev->regs.er_out[i]->DOEPLEN = 0U; + + /* clear all pending OUT endpoint interrupts */ + udev->regs.er_out[i]->DOEPINTF = 0xFFU; + } + + udev->regs.dr->DIEPINTEN |= DIEPINTEN_EPTXFUDEN; + + (void)usb_devint_enable (udev); + + return USB_OK; +} + +/*! + \brief enable the USB device mode interrupts + \param[in] udev: pointer to USB device + \param[out] none + \retval operation status +*/ +usb_status usb_devint_enable (usb_core_driver *udev) +{ + /* clear any pending USB OTG interrupts */ + udev->regs.gr->GOTGINTF = 0xFFFFFFFFU; + + /* clear any pending interrupts */ + udev->regs.gr->GINTF = 0xBFFFFFFFU; + + /* enable the USB wakeup and suspend interrupts */ + udev->regs.gr->GINTEN = GINTEN_WKUPIE | GINTEN_SPIE; + + /* enable device_mode-related interrupts */ + if ((uint8_t)USB_USE_FIFO == udev->bp.transfer_mode) { + udev->regs.gr->GINTEN |= GINTEN_RXFNEIE; + } + + udev->regs.gr->GINTEN |= GINTEN_RSTIE | GINTEN_ENUMFIE | GINTEN_IEPIE |\ + GINTEN_OEPIE | GINTEN_SOFIE | GINTEN_ISOONCIE | GINTEN_ISOINCIE; + +#ifdef VBUS_SENSING_ENABLED + udev->regs.gr->GINTEN |= GINTEN_SESIE | GINTEN_OTGIE; +#endif /* VBUS_SENSING_ENABLED */ + + return USB_OK; +} + +/*! + \brief active the USB endpoint0 transaction + \param[in] udev: pointer to USB device + \param[in] transc: the USB endpoint0 transaction + \param[out] none + \retval operation status +*/ +usb_status usb_transc0_active (usb_core_driver *udev, usb_transc *transc) +{ + __IO uint32_t *reg_addr = NULL; + + /* get the endpoint number */ + uint8_t ep_num = transc->ep_addr.num; + + if (ep_num) { + /* not endpoint 0 */ + return USB_FAIL; + } + + if (transc->ep_addr.dir) { + reg_addr = &udev->regs.er_in[0]->DIEPCTL; + } else { + reg_addr = &udev->regs.er_out[0]->DOEPCTL; + } + + /* endpoint 0 is activated after USB clock is enabled */ + + *reg_addr &= ~(DEPCTL_MPL | DEPCTL_EPTYPE | DIEPCTL_TXFNUM); + + /* set endpoint 0 maximum packet length */ + *reg_addr |= EP0_MAXLEN[udev->regs.dr->DSTAT & DSTAT_ES]; + + /* activate endpoint */ + *reg_addr |= ((uint32_t)transc->ep_type << 18U) | ((uint32_t)ep_num << 22U) | DEPCTL_SD0PID | DEPCTL_EPACT; + + return USB_OK; +} + +/*! + \brief active the USB transaction + \param[in] udev: pointer to USB device + \param[in] transc: the USB transaction + \param[out] none + \retval status +*/ +usb_status usb_transc_active (usb_core_driver *udev, usb_transc *transc) +{ + __IO uint32_t *reg_addr = NULL; + __IO uint32_t epinten = 0U; + + /* get the endpoint number */ + uint8_t ep_num = transc->ep_addr.num; + + /* enable endpoint interrupt number */ + if (transc->ep_addr.dir) { + reg_addr = &udev->regs.er_in[ep_num]->DIEPCTL; + + epinten = 1U << ep_num; + } else { + reg_addr = &udev->regs.er_out[ep_num]->DOEPCTL; + + epinten = 1U << (16U + ep_num); + } + + /* if the endpoint is not active, need change the endpoint control register */ + if (!(*reg_addr & DEPCTL_EPACT)) { + *reg_addr &= ~(DEPCTL_MPL | DEPCTL_EPTYPE | DIEPCTL_TXFNUM); + + /* set endpoint maximum packet length */ + if (0U == ep_num) { + *reg_addr |= EP0_MAXLEN[udev->regs.dr->DSTAT & DSTAT_ES]; + } else { + *reg_addr |= transc->max_len; + } + + /* activate endpoint */ + *reg_addr |= ((uint32_t)transc->ep_type << 18U) | ((uint32_t)ep_num << 22U) | DEPCTL_SD0PID | DEPCTL_EPACT; + } + + + /* enable the interrupts for this endpoint */ + udev->regs.dr->DAEPINTEN |= epinten; + + return USB_OK; +} + +/*! + \brief deactivate the USB transaction + \param[in] udev: pointer to USB device + \param[in] transc: the USB transaction + \param[out] none + \retval status +*/ +usb_status usb_transc_deactivate(usb_core_driver *udev, usb_transc *transc) +{ + uint32_t epinten = 0U; + + uint8_t ep_num = transc->ep_addr.num; + + /* disable endpoint interrupt number */ + if (transc->ep_addr.dir) { + epinten = 1U << ep_num; + + udev->regs.er_in[ep_num]->DIEPCTL &= ~DEPCTL_EPACT; + } else { + epinten = 1U << (ep_num + 16U); + + udev->regs.er_out[ep_num]->DOEPCTL &= ~DEPCTL_EPACT; + } + + + /* disable the interrupts for this endpoint */ + udev->regs.dr->DAEPINTEN &= ~epinten; + + return USB_OK; +} + +/*! + \brief configure USB transaction to start IN transfer + \param[in] udev: pointer to USB device + \param[in] transc: the USB IN transaction + \param[out] none + \retval operation status +*/ +usb_status usb_transc_inxfer (usb_core_driver *udev, usb_transc *transc) +{ + usb_status status = USB_OK; + + uint8_t ep_num = transc->ep_addr.num; + + __IO uint32_t epctl = udev->regs.er_in[ep_num]->DIEPCTL; + __IO uint32_t eplen = udev->regs.er_in[ep_num]->DIEPLEN; + + eplen &= ~(DEPLEN_TLEN | DEPLEN_PCNT); + + /* zero length packet or endpoint 0 */ + if (0U == transc->xfer_len) { + /* set transfer packet count to 1 */ + eplen |= 1U << 19U; + } else { + /* set transfer packet count */ + if (0U == ep_num) { + transc->xfer_len = USB_MIN(transc->xfer_len, transc->max_len); + + eplen |= 1U << 19U; + } else { + eplen |= (((transc->xfer_len - 1U) + transc->max_len) / transc->max_len) << 19U; + } + + /* set endpoint transfer length */ + eplen |= transc->xfer_len; + + if (transc->ep_type == (uint8_t)USB_EPTYPE_ISOC) { + eplen |= DIEPLEN_MCNT & (1U << 29U); + } + } + + udev->regs.er_in[ep_num]->DIEPLEN = eplen; + + if (transc->ep_type == (uint8_t)USB_EPTYPE_ISOC) { + if (((udev->regs.dr->DSTAT & DSTAT_FNRSOF) >> 8U) & 0x01U) { + epctl |= DEPCTL_SEVNFRM; + } else { + epctl |= DEPCTL_SODDFRM; + } + } + + if ((uint8_t)USB_USE_DMA == udev->bp.transfer_mode) { + udev->regs.er_in[ep_num]->DIEPDMAADDR = transc->dma_addr; + } + + /* enable the endpoint and clear the NAK */ + epctl |= DEPCTL_CNAK | DEPCTL_EPEN; + + udev->regs.er_in[ep_num]->DIEPCTL = epctl; + + if ((uint8_t)USB_USE_FIFO == udev->bp.transfer_mode) { + udev->regs.er_in[ep_num]->DIEPCTL = epctl; + + if (transc->ep_type != (uint8_t)USB_EPTYPE_ISOC) { + /* enable the Tx FIFO empty interrupt for this endpoint */ + if (transc->xfer_len > 0U) { + udev->regs.dr->DIEPFEINTEN |= 1U << ep_num; + } + } else { + (void)usb_txfifo_write (&udev->regs, transc->xfer_buf, ep_num, (uint16_t)transc->xfer_len); + } + } + + return status; +} + +/*! + \brief configure usb transaction to start OUT transfer + \param[in] udev: pointer to usb device + \param[in] transc: the usb OUT transaction + \param[out] none + \retval status +*/ +usb_status usb_transc_outxfer (usb_core_driver *udev, usb_transc *transc) +{ + usb_status status = USB_OK; + + uint8_t ep_num = transc->ep_addr.num; + + uint32_t epctl = udev->regs.er_out[ep_num]->DOEPCTL; + uint32_t eplen = udev->regs.er_out[ep_num]->DOEPLEN; + + eplen &= ~(DEPLEN_TLEN | DEPLEN_PCNT); + + /* zero length packet or endpoint 0 */ + if ((0U == transc->xfer_len) || (0U == ep_num)) { + /* set the transfer length to max packet size */ + eplen |= transc->max_len; + + /* set the transfer packet count to 1 */ + eplen |= 1U << 19U; + } else { + /* configure the transfer size and packet count as follows: + * pktcnt = N + * xfersize = N * maxpacket + */ + uint32_t packet_count = (transc->xfer_len + transc->max_len - 1U) / transc->max_len; + + eplen |= packet_count << 19U; + eplen |= packet_count * transc->max_len; + } + + udev->regs.er_out[ep_num]->DOEPLEN = eplen; + + if ((uint8_t)USB_USE_DMA == udev->bp.transfer_mode) { + udev->regs.er_out[ep_num]->DOEPDMAADDR = transc->dma_addr; + } + + if (transc->ep_type == (uint8_t)USB_EPTYPE_ISOC) { + if (transc->frame_num) { + epctl |= DEPCTL_SD1PID; + } else { + epctl |= DEPCTL_SD0PID; + } + } + + /* enable the endpoint and clear the NAK */ + epctl |= DEPCTL_EPEN | DEPCTL_CNAK; + + udev->regs.er_out[ep_num]->DOEPCTL = epctl; + + return status; +} + +/*! + \brief set the USB transaction STALL status + \param[in] udev: pointer to USB device + \param[in] transc: the USB transaction + \param[out] none + \retval status +*/ +usb_status usb_transc_stall (usb_core_driver *udev, usb_transc *transc) +{ + __IO uint32_t *reg_addr = NULL; + + uint8_t ep_num = transc->ep_addr.num; + + if (transc->ep_addr.dir) { + reg_addr = &(udev->regs.er_in[ep_num]->DIEPCTL); + + /* set the endpoint disable bit */ + if (*reg_addr & DEPCTL_EPEN) { + *reg_addr |= DEPCTL_EPD; + } + } else { + /* set the endpoint stall bit */ + reg_addr = &(udev->regs.er_out[ep_num]->DOEPCTL); + } + + /* set the endpoint stall bit */ + *reg_addr |= DEPCTL_STALL; + + return USB_OK; +} + +/*! + \brief clear the USB transaction STALL status + \param[in] udev: pointer to USB device + \param[in] transc: the USB transaction + \param[out] none + \retval operation status +*/ +usb_status usb_transc_clrstall(usb_core_driver *udev, usb_transc *transc) +{ + __IO uint32_t *reg_addr = NULL; + + uint8_t ep_num = transc->ep_addr.num; + + if (transc->ep_addr.dir) { + reg_addr = &(udev->regs.er_in[ep_num]->DIEPCTL); + } else { + reg_addr = &(udev->regs.er_out[ep_num]->DOEPCTL); + } + + /* clear the endpoint stall bits */ + *reg_addr &= ~DEPCTL_STALL; + + /* reset data PID of the periodic endpoints */ + if ((transc->ep_type == (uint8_t)USB_EPTYPE_INTR) || (transc->ep_type == (uint8_t)USB_EPTYPE_BULK)) { + *reg_addr |= DEPCTL_SD0PID; + } + + return USB_OK; +} + +/*! + \brief read device IN endpoint interrupt flag register + \param[in] udev: pointer to USB device + \param[in] ep_num: endpoint number + \param[out] none + \retval interrupt value +*/ +uint32_t usb_iepintr_read (usb_core_driver *udev, uint8_t ep_num) +{ + uint32_t value = 0U, fifoemptymask, commonintmask; + + commonintmask = udev->regs.dr->DIEPINTEN; + fifoemptymask = udev->regs.dr->DIEPFEINTEN; + + /* check FIFO empty interrupt enable bit */ + commonintmask |= ((fifoemptymask >> ep_num) & 0x1U) << 7; + + value = udev->regs.er_in[ep_num]->DIEPINTF & commonintmask; + + return value; +} + +/*! + \brief configures OUT endpoint 0 to receive SETUP packets + \param[in] udev: pointer to USB device + \param[out] none + \retval none +*/ +void usb_ctlep_startout (usb_core_driver *udev) +{ + /* set OUT endpoint 0 receive length to 24 bytes, 1 packet and 3 setup packets */ + udev->regs.er_out[0]->DOEPLEN = DOEP0_TLEN(8U * 3U) | DOEP0_PCNT(1U) | DOEP0_STPCNT(3U); + + if ((uint8_t)USB_USE_DMA == udev->bp.transfer_mode) { + udev->regs.er_out[0]->DOEPDMAADDR = (uint32_t)&udev->dev.control.req; + + /* endpoint enable */ + udev->regs.er_out[0]->DOEPCTL |= DEPCTL_EPACT | DEPCTL_EPEN; + } +} + +/*! + \brief active remote wakeup signaling + \param[in] udev: pointer to USB device + \param[out] none + \retval none +*/ +void usb_rwkup_active (usb_core_driver *udev) +{ + if (udev->dev.pm.dev_remote_wakeup) { + if (udev->regs.dr->DSTAT & DSTAT_SPST) { + if (udev->bp.low_power) { + /* ungate USB core clock */ + *udev->regs.PWRCLKCTL &= ~(PWRCLKCTL_SHCLK | PWRCLKCTL_SUCLK); + } + + /* active remote wakeup signaling */ + udev->regs.dr->DCTL |= DCTL_RWKUP; + + usb_mdelay(5U); + + udev->regs.dr->DCTL &= ~DCTL_RWKUP; + } + } +} + +/*! + \brief active USB core clock + \param[in] udev: pointer to USB device + \param[out] none + \retval none +*/ +void usb_clock_active (usb_core_driver *udev) +{ + if (udev->bp.low_power) { + if (udev->regs.dr->DSTAT & DSTAT_SPST) { + /* ungate USB Core clock */ + *udev->regs.PWRCLKCTL &= ~(PWRCLKCTL_SHCLK | PWRCLKCTL_SUCLK); + } + } +} + +/*! + \brief USB device suspend + \param[in] udev: pointer to USB device + \param[out] none + \retval none +*/ +void usb_dev_suspend (usb_core_driver *udev) +{ + __IO uint32_t devstat = udev->regs.dr->DSTAT; + + if ((udev->bp.low_power) && (devstat & DSTAT_SPST)) { + /* switch-off the USB clocks */ + *udev->regs.PWRCLKCTL |= PWRCLKCTL_SHCLK; + + /* enter DEEP_SLEEP mode with LDO in low power mode */ + pmu_to_deepsleepmode(PMU_LDO_LOWPOWER, WFI_CMD); + } +} + +/*! + \brief stop the device and clean up FIFOs + \param[in] udev: pointer to USB device + \param[out] none + \retval none +*/ +void usb_dev_stop (usb_core_driver *udev) +{ + uint32_t i; + + udev->dev.cur_status = 1U; + + /* clear all interrupt flag and enable bits */ + for (i = 0U; i < udev->bp.num_ep; i++) { + udev->regs.er_in[i]->DIEPINTF = 0xFFU; + udev->regs.er_out[i]->DOEPINTF = 0xFFU; + } + + udev->regs.dr->DIEPINTEN = 0U; + udev->regs.dr->DOEPINTEN = 0U; + udev->regs.dr->DAEPINTEN = 0U; + udev->regs.dr->DAEPINT = 0xFFFFFFFFU; + + /* flush the FIFO */ + (void)usb_rxfifo_flush (&udev->regs); + (void)usb_txfifo_flush (&udev->regs, 0x10U); +} diff --git a/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/driver/Source/drv_usb_host.c b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/driver/Source/drv_usb_host.c new file mode 100644 index 0000000000..803a91bbab --- /dev/null +++ b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/driver/Source/drv_usb_host.c @@ -0,0 +1,452 @@ +/*! + \file drv_usb_host.c + \brief USB host mode low level driver + + \version 2020-07-28, V3.0.0, firmware for GD32F20x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "drv_usb_hw.h" +#include "drv_usb_core.h" +#include "drv_usb_host.h" + +const uint32_t PIPE_DPID[2] = { + PIPE_DPID_DATA0, + PIPE_DPID_DATA1 +}; + +/*! + \brief initializes USB core for host mode + \param[in] udev: pointer to selected usb host + \param[out] none + \retval operation status +*/ +usb_status usb_host_init (usb_core_driver *udev) +{ + uint32_t i = 0U, inten = 0U; + + uint32_t nptxfifolen = 0U; + uint32_t ptxfifolen = 0U; + + /* restart the PHY Clock */ + *udev->regs.PWRCLKCTL = 0U; + + /* support FS/LS only */ + udev->regs.hr->HCTL &= ~HCTL_SPDFSLS; + + /* configure data FIFOs size */ +#ifdef USB_FS_CORE + if (USB_CORE_ENUM_FS == udev->bp.core_enum) { + /* set Rx FIFO size */ + udev->regs.gr->GRFLEN = USB_RX_FIFO_FS_SIZE; + + /* set non-periodic Tx FIFO size and address */ + nptxfifolen |= USB_RX_FIFO_FS_SIZE; + nptxfifolen |= USB_HTX_NPFIFO_FS_SIZE << 16U; + udev->regs.gr->DIEP0TFLEN_HNPTFLEN = nptxfifolen; + + /* set periodic Tx FIFO size and address */ + ptxfifolen |= USB_RX_FIFO_FS_SIZE + USB_HTX_PFIFO_FS_SIZE; + ptxfifolen |= USB_HTX_PFIFO_FS_SIZE << 16U; + udev->regs.gr->HPTFLEN = ptxfifolen; + } +#endif /* USB_FS_CORE */ + +#ifdef USE_OTG_MODE + + /* clear host set HNP enable in the usb_otg control register */ + udev->regs.gr->GOTGCS &= ~GOTGCS_HHNPEN; + +#endif /* USE_OTG_MODE */ + + /* make sure the FIFOs are flushed */ + + /* flush all Tx FIFOs in device or host mode */ + usb_txfifo_flush (&udev->regs, 0x10U); + + /* flush the entire Rx FIFO */ + usb_rxfifo_flush (&udev->regs); + + /* disable all interrupts */ + udev->regs.gr->GINTEN = 0U; + + /* clear any pending USB OTG interrupts */ + udev->regs.gr->GOTGINTF = 0xFFFFFFFFU; + + /* enable the USB wakeup and suspend interrupts */ + udev->regs.gr->GINTF = 0xBFFFFFFFU; + + /* clear all pending host channel interrupts */ + for (i = 0U; i < udev->bp.num_pipe; i++) { + udev->regs.pr[i]->HCHINTF = 0xFFFFFFFFU; + udev->regs.pr[i]->HCHINTEN = 0U; + } + +#ifndef USE_OTG_MODE + usb_portvbus_switch (udev, 1U); +#endif /* USE_OTG_MODE */ + + udev->regs.gr->GINTEN = GINTEN_WKUPIE | GINTEN_SPIE; + + /* enable host_mode-related interrupts */ + if (USB_USE_FIFO == udev->bp.transfer_mode) { + inten = GINTEN_RXFNEIE; + } + + inten |= GINTEN_SESIE | GINTEN_HPIE | GINTEN_HCIE | GINTEN_ISOINCIE; + + udev->regs.gr->GINTEN |= inten; + + inten = GINTEN_DISCIE | GINTEN_SOFIE; + + udev->regs.gr->GINTEN &= ~inten; + + return USB_OK; +} + +/*! + \brief control the VBUS to power + \param[in] udev: pointer to selected usb host + \param[in] state: VBUS state + \param[out] none + \retval none +*/ +void usb_portvbus_switch (usb_core_driver *udev, uint8_t state) +{ + uint32_t port = 0U; + + /* enable or disable the external charge pump */ + usb_vbus_drive (state); + + /* turn on the host port power. */ + port = usb_port_read (udev); + + if (!(port & HPCS_PP) && (1U == state)) { + port |= HPCS_PP; + } + + if ((port & HPCS_PP) && (0U == state)) { + port &= ~HPCS_PP; + } + + *udev->regs.HPCS = port; + + usb_mdelay (200U); +} + +/*! + \brief reset host port + \param[in] udev: pointer to usb device + \param[out] none + \retval operation status +*/ +uint32_t usb_port_reset (usb_core_driver *udev) +{ + __IO uint32_t port = usb_port_read (udev); + + *udev->regs.HPCS = port | HPCS_PRST; + + usb_mdelay(20U); /* see note */ + + *udev->regs.HPCS = port & ~HPCS_PRST; + + usb_mdelay(20U); + + return 1U; +} + +/*! + \brief initialize host pipe + \param[in] udev: pointer to usb device + \param[in] pipe_num: host pipe number which is in (0..7) + \param[out] none + \retval operation status +*/ +usb_status usb_pipe_init (usb_core_driver *udev, uint8_t pipe_num) +{ + usb_status status = USB_OK; + + __IO uint32_t pp_ctl = 0U; + __IO uint32_t pp_inten = HCHINTEN_TFIE; + + usb_pipe *pp = &udev->host.pipe[pipe_num]; + + /* clear old interrupt conditions for this host channel */ + udev->regs.pr[pipe_num]->HCHINTF = 0xFFFFFFFFU; + + if (USB_USE_DMA == udev->bp.transfer_mode) { + pp_inten |= HCHINTEN_DMAERIE; + } + + if (pp->ep.dir) { + pp_inten |= HCHINTEN_BBERIE; + } + + /* enable channel interrupts required for this transfer */ + switch (pp->ep.type) { + case USB_EPTYPE_CTRL: + case USB_EPTYPE_BULK: + pp_inten |= HCHINTEN_STALLIE | HCHINTEN_USBERIE \ + | HCHINTEN_DTERIE | HCHINTEN_NAKIE; + + if (!pp->ep.dir) { + pp_inten |= HCHINTEN_NYETIE; + + if (pp->ping) { + pp_inten |= HCHINTEN_ACKIE; + } + } + break; + + case USB_EPTYPE_INTR: + pp_inten |= HCHINTEN_STALLIE | HCHINTEN_USBERIE | HCHINTEN_DTERIE \ + | HCHINTEN_NAKIE | HCHINTEN_REQOVRIE; + break; + + case USB_EPTYPE_ISOC: + pp_inten |= HCHINTEN_REQOVRIE | HCHINTEN_ACKIE; + + if (pp->ep.dir) { + pp_inten |= HCHINTEN_USBERIE; + } + break; + + default: + break; + } + + udev->regs.pr[pipe_num]->HCHINTEN = pp_inten; + + /* enable the top level host channel interrupt */ + udev->regs.hr->HACHINTEN |= 1U << pipe_num; + + /* make sure host channel interrupts are enabled */ + udev->regs.gr->GINTEN |= GINTEN_HCIE; + + /* program the host channel control register */ + pp_ctl |= PIPE_CTL_DAR(pp->dev_addr); + pp_ctl |= PIPE_CTL_EPNUM(pp->ep.num); + pp_ctl |= PIPE_CTL_EPDIR(pp->ep.dir); + pp_ctl |= PIPE_CTL_EPTYPE(pp->ep.type); + pp_ctl |= PIPE_CTL_LSD(pp->dev_speed == PORT_SPEED_LOW); + + pp_ctl |= pp->ep.mps; + pp_ctl |= ((uint32_t)(pp->ep.type == USB_EPTYPE_INTR) << 29U) & HCHCTL_ODDFRM; + + udev->regs.pr[pipe_num]->HCHCTL = pp_ctl; + + return status; +} + +/*! + \brief prepare host channel for transferring packets + \param[in] udev: pointer to usb device + \param[in] pipe_num: host pipe number which is in (0..7) + \param[out] none + \retval operation status +*/ +usb_status usb_pipe_xfer (usb_core_driver *udev, uint8_t pipe_num) +{ + usb_status status = USB_OK; + + uint16_t dword_len = 0U; + uint16_t packet_count = 0U; + + __IO uint32_t pp_ctl = 0U; + + usb_pipe *pp = &udev->host.pipe[pipe_num]; + + uint16_t max_packet_len = pp->ep.mps; + + /* compute the expected number of packets associated to the transfer */ + if (pp->xfer_len > 0U) { + packet_count = (uint16_t)((pp->xfer_len + max_packet_len - 1U) / max_packet_len); + + if (packet_count > HC_MAX_PACKET_COUNT) { + packet_count = HC_MAX_PACKET_COUNT; + pp->xfer_len = (uint16_t)(packet_count * max_packet_len); + } + } else { + packet_count = 1U; + } + + if (pp->ep.dir) { + pp->xfer_len = (uint16_t)(packet_count * max_packet_len); + } + + /* initialize the host channel transfer information */ + udev->regs.pr[pipe_num]->HCHLEN = pp->xfer_len | pp->DPID | PIPE_XFER_PCNT(packet_count); + + if (USB_USE_DMA == udev->bp.transfer_mode) { + udev->regs.pr[pipe_num]->HCHDMAADDR = (unsigned int)pp->xfer_buf; + } + + pp_ctl = udev->regs.pr[pipe_num]->HCHCTL; + + if (usb_frame_even(udev)) { + pp_ctl |= HCHCTL_ODDFRM; + } else { + pp_ctl &= ~HCHCTL_ODDFRM; + } + + /* set host channel enabled */ + pp_ctl |= HCHCTL_CEN; + pp_ctl &= ~HCHCTL_CDIS; + + udev->regs.pr[pipe_num]->HCHCTL = pp_ctl; + + if (USB_USE_FIFO == udev->bp.transfer_mode) { + if ((0U == pp->ep.dir) && (pp->xfer_len > 0U)) { + switch (pp->ep.type) { + /* non-periodic transfer */ + case USB_EPTYPE_CTRL: + case USB_EPTYPE_BULK: + dword_len = (uint16_t)((pp->xfer_len + 3U) / 4U); + + /* check if there is enough space in fifo space */ + if (dword_len > (udev->regs.gr->HNPTFQSTAT & HNPTFQSTAT_NPTXFS)) { + /* need to process data in nptxfempty interrupt */ + udev->regs.gr->GINTEN |= GINTEN_NPTXFEIE; + } + break; + + /* periodic transfer */ + case USB_EPTYPE_INTR: + case USB_EPTYPE_ISOC: + dword_len = (uint16_t)((pp->xfer_len + 3U) / 4U); + + /* check if there is enough space in fifo space */ + if (dword_len > (udev->regs.hr->HPTFQSTAT & HPTFQSTAT_PTXFS)) { + /* need to process data in ptxfempty interrupt */ + udev->regs.gr->GINTEN |= GINTEN_PTXFEIE; + } + break; + + default: + break; + } + + /* write packet into the Tx fifo. */ + usb_txfifo_write (&udev->regs, pp->xfer_buf, pipe_num, (uint16_t)pp->xfer_len); + } + } + + return status; +} + +/*! + \brief halt pipe + \param[in] udev: pointer to usb device + \param[in] pipe_num: host pipe number which is in (0..7) + \param[out] none + \retval operation status +*/ +usb_status usb_pipe_halt (usb_core_driver *udev, uint8_t pipe_num) +{ + __IO uint32_t pp_ctl = udev->regs.pr[pipe_num]->HCHCTL; + + uint8_t ep_type = (uint8_t)((pp_ctl & HCHCTL_EPTYPE) >> 18U); + + pp_ctl |= HCHCTL_CEN | HCHCTL_CDIS; + + switch (ep_type) { + case USB_EPTYPE_CTRL: + case USB_EPTYPE_BULK: + if (0U == (udev->regs.gr->HNPTFQSTAT & HNPTFQSTAT_NPTXFS)) { + pp_ctl &= ~HCHCTL_CEN; + } + break; + + case USB_EPTYPE_INTR: + case USB_EPTYPE_ISOC: + if (0U == (udev->regs.hr->HPTFQSTAT & HPTFQSTAT_PTXFS)) { + pp_ctl &= ~HCHCTL_CEN; + } + break; + + default: + break; + } + + udev->regs.pr[pipe_num]->HCHCTL = pp_ctl; + + return USB_OK; +} + +/*! + \brief configure host pipe to do ping operation + \param[in] udev: pointer to usb device + \param[in] pipe_num: host pipe number which is in (0..7) + \param[out] none + \retval operation status +*/ +usb_status usb_pipe_ping (usb_core_driver *udev, uint8_t pipe_num) +{ + uint32_t pp_ctl = 0U; + + udev->regs.pr[pipe_num]->HCHLEN = HCHLEN_PING | (HCHLEN_PCNT & (1U << 19U)); + + pp_ctl = udev->regs.pr[pipe_num]->HCHCTL; + + pp_ctl |= HCHCTL_CEN; + pp_ctl &= ~HCHCTL_CDIS; + + udev->regs.pr[pipe_num]->HCHCTL = pp_ctl; + + return USB_OK; +} + +/*! + \brief stop the USB host and clean up FIFO + \param[in] udev: pointer to usb device + \param[out] none + \retval none +*/ +void usb_host_stop (usb_core_driver *udev) +{ + uint32_t i; + __IO uint32_t pp_ctl = 0U; + + udev->regs.hr->HACHINTEN = 0x0U; + udev->regs.hr->HACHINT = 0xFFFFFFFFU; + + /* flush out any leftover queued requests. */ + for (i = 0U; i < udev->bp.num_pipe; i++) { + pp_ctl = udev->regs.pr[i]->HCHCTL; + + pp_ctl &= ~(HCHCTL_CEN | HCHCTL_EPDIR); + pp_ctl |= HCHCTL_CDIS; + + udev->regs.pr[i]->HCHCTL = pp_ctl; + } + + /* flush the FIFO */ + usb_rxfifo_flush (&udev->regs); + usb_txfifo_flush (&udev->regs, 0x10U); +} diff --git a/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/driver/Source/drv_usbd_int.c b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/driver/Source/drv_usbd_int.c new file mode 100644 index 0000000000..3ba5128bba --- /dev/null +++ b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/driver/Source/drv_usbd_int.c @@ -0,0 +1,510 @@ +/*! + \file drv_usbd_int.c + \brief USB device mode interrupt routines + + \version 2020-07-28, V3.0.0, firmware for GD32F20x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "usbd_conf.h" +#include "drv_usbd_int.h" +#include "usbd_transc.h" + +static uint32_t usbd_int_epout (usb_core_driver *udev); +static uint32_t usbd_int_epin (usb_core_driver *udev); +static uint32_t usbd_int_rxfifo (usb_core_driver *udev); +static uint32_t usbd_int_reset (usb_core_driver *udev); +static uint32_t usbd_int_enumfinish (usb_core_driver *udev); +static uint32_t usbd_int_suspend (usb_core_driver *udev); + +static uint32_t usbd_emptytxfifo_write (usb_core_driver *udev, uint32_t ep_num); + +static const uint8_t USB_SPEED[4] = { + [DSTAT_EM_HS_PHY_30MHZ_60MHZ] = (uint8_t)USB_SPEED_HIGH, + [DSTAT_EM_FS_PHY_30MHZ_60MHZ] = (uint8_t)USB_SPEED_FULL, + [DSTAT_EM_FS_PHY_48MHZ] = (uint8_t)USB_SPEED_FULL, + [DSTAT_EM_LS_PHY_6MHZ] = (uint8_t)USB_SPEED_LOW +}; + +__IO uint8_t setupc_flag = 0U; + +/*! + \brief USB device-mode interrupts global service routine handler + \param[in] udev: pointer to USB device instance + \param[out] none + \retval none +*/ +void usbd_isr (usb_core_driver *udev) +{ + if (HOST_MODE != (udev->regs.gr->GINTF & GINTF_COPM)) { + uint32_t intr = udev->regs.gr->GINTF & udev->regs.gr->GINTEN; + + /* there are no interrupts, avoid spurious interrupt */ + if (!intr) { + return; + } + + /* OUT endpoints interrupts */ + if (intr & GINTF_OEPIF) { + (void)usbd_int_epout (udev); + } + + /* IN endpoints interrupts */ + if (intr & GINTF_IEPIF) { + (void)usbd_int_epin (udev); + } + + /* suspend interrupt */ + if (intr & GINTF_SP) { + (void)usbd_int_suspend (udev); + } + + /* wakeup interrupt */ + if (intr & GINTF_WKUPIF) { + /* inform upper layer by the resume event */ + + udev->dev.cur_status = (uint8_t)USBD_CONFIGURED; + + /* clear interrupt */ + udev->regs.gr->GINTF = GINTF_WKUPIF; + } + + /* start of frame interrupt */ + if (intr & GINTF_SOF) { + if (udev->dev.class_core->SOF) { + (void)udev->dev.class_core->SOF(udev); + } + + if (0U != setupc_flag) { + setupc_flag ++; + + if (setupc_flag >= 3U) { + usbd_setup_transc (udev); + + setupc_flag = 0U; + } + } + + /* clear interrupt */ + udev->regs.gr->GINTF = GINTF_SOF; + } + + /* receive FIFO not empty interrupt */ + if (intr & GINTF_RXFNEIF) { + (void)usbd_int_rxfifo (udev); + } + + /* USB reset interrupt */ + if (intr & GINTF_RST) { + (void)usbd_int_reset (udev); + } + + /* enumeration has been done interrupt */ + if (intr & GINTF_ENUMFIF) { + (void)usbd_int_enumfinish (udev); + } + + /* incomplete synchronization IN transfer interrupt*/ + if (intr & GINTF_ISOINCIF) { + if (NULL != udev->dev.class_core->incomplete_isoc_in) { + (void)udev->dev.class_core->incomplete_isoc_in(udev); + } + + /* Clear interrupt */ + udev->regs.gr->GINTF = GINTF_ISOINCIF; + } + + /* incomplete synchronization OUT transfer interrupt*/ + if (intr & GINTF_ISOONCIF) { + if (NULL != udev->dev.class_core->incomplete_isoc_out) { + (void)udev->dev.class_core->incomplete_isoc_out(udev); + } + + /* clear interrupt */ + udev->regs.gr->GINTF = GINTF_ISOONCIF; + } + +#ifdef VBUS_SENSING_ENABLED + + /* Session request interrupt */ + if (intr & GINTF_SESIF) { + udev->regs.gr->GINTF = GINTF_SESIF; + } + + /* OTG mode interrupt */ + if (intr & GINTF_OTGIF) { + if(udev->regs.gr->GOTGINTF & GOTGINTF_SESEND) { + + } + + /* Clear OTG interrupt */ + udev->regs.gr->GINTF = GINTF_OTGIF; + } +#endif /* VBUS_SENSING_ENABLED */ + } +} + +/*! + \brief indicates that an OUT endpoint has a pending interrupt + \param[in] udev: pointer to USB device instance + \param[out] none + \retval operation status +*/ +static uint32_t usbd_int_epout (usb_core_driver *udev) +{ + uint32_t epintnum = 0U; + uint8_t ep_num = 0U; + + for (epintnum = usb_oepintnum_read (udev); epintnum; epintnum >>= 1, ep_num++) { + if (epintnum & 0x01U) { + __IO uint32_t oepintr = usb_oepintr_read (udev, ep_num); + + /* transfer complete interrupt */ + if (oepintr & DOEPINTF_TF) { + /* clear the bit in DOEPINTF for this interrupt */ + udev->regs.er_out[ep_num]->DOEPINTF = DOEPINTF_TF; + + if ((uint8_t)USB_USE_DMA == udev->bp.transfer_mode) { + __IO uint32_t eplen = udev->regs.er_out[ep_num]->DOEPLEN; + + udev->dev.transc_out[ep_num].xfer_count = udev->dev.transc_out[ep_num].max_len - \ + (eplen & DEPLEN_TLEN); + } + + /* inform upper layer: data ready */ + (void)usbd_out_transc (udev, ep_num); + + if ((uint8_t)USB_USE_DMA == udev->bp.transfer_mode) { + if ((0U == ep_num) && ((uint8_t)USB_CTL_STATUS_OUT == udev->dev.control.ctl_state)) { + usb_ctlep_startout (udev); + } + } + } + + /* setup phase finished interrupt (control endpoints) */ + if (oepintr & DOEPINTF_STPF) { + if ((0U == ep_num) && (0U != setupc_flag)) { + /* inform the upper layer that a setup packet is available */ + (void)usbd_setup_transc (udev); + + udev->regs.er_out[ep_num]->DOEPINTF = DOEPINTF_STPF; + + setupc_flag = 0U; + } + } + } + } + + return 1U; +} + +/*! + \brief indicates that an IN endpoint has a pending interrupt + \param[in] udev: pointer to USB device instance + \param[out] none + \retval operation status +*/ +static uint32_t usbd_int_epin (usb_core_driver *udev) +{ + uint32_t epintnum = 0U; + uint8_t ep_num = 0U; + + for (epintnum = usb_iepintnum_read (udev); epintnum; epintnum >>= 1, ep_num++) { + if (epintnum & 0x1U) { + __IO uint32_t iepintr = usb_iepintr_read (udev, ep_num); + + if (iepintr & DIEPINTF_TF) { + udev->regs.er_in[ep_num]->DIEPINTF = DIEPINTF_TF; + + /* data transmission is completed */ + (void)usbd_in_transc (udev, ep_num); + + if ((uint8_t)USB_USE_DMA == udev->bp.transfer_mode) { + if ((0U == ep_num) && ((uint8_t)USB_CTL_STATUS_IN == udev->dev.control.ctl_state)) { + usb_ctlep_startout (udev); + } + } + } + + if (iepintr & DIEPINTF_TXFE) { + usbd_emptytxfifo_write (udev, (uint32_t)ep_num); + + udev->regs.er_in[ep_num]->DIEPINTF = DIEPINTF_TXFE; + } + } + } + + return 1U; +} + +/*! + \brief handle the RX status queue level interrupt + \param[in] udev: pointer to USB device instance + \param[out] none + \retval operation status +*/ +static uint32_t usbd_int_rxfifo (usb_core_driver *udev) +{ + usb_transc *transc = NULL; + + uint8_t data_PID = 0U; + uint32_t bcount = 0U; + + __IO uint32_t devrxstat = 0U; + + /* disable the Rx status queue non-empty interrupt */ + udev->regs.gr->GINTEN &= ~GINTEN_RXFNEIE; + + /* get the status from the top of the FIFO */ + devrxstat = udev->regs.gr->GRSTATP; + + uint8_t ep_num = (uint8_t)(devrxstat & GRSTATRP_EPNUM); + + transc = &udev->dev.transc_out[ep_num]; + + bcount = (devrxstat & GRSTATRP_BCOUNT) >> 4U; + data_PID = (uint8_t)((devrxstat & GRSTATRP_DPID) >> 15U); + + switch ((devrxstat & GRSTATRP_RPCKST) >> 17U) { + case RSTAT_GOUT_NAK: + break; + + case RSTAT_DATA_UPDT: + if (bcount > 0U) { + (void)usb_rxfifo_read (&udev->regs, transc->xfer_buf, (uint16_t)bcount); + + transc->xfer_buf += bcount; + transc->xfer_count += bcount; + } + break; + + case RSTAT_XFER_COMP: + /* trigger the OUT endpoint interrupt */ + break; + + case RSTAT_SETUP_COMP: + /* trigger the OUT endpoint interrupt */ + break; + + case RSTAT_SETUP_UPDT: + if ((0U == transc->ep_addr.num) && (8U == bcount) && (DPID_DATA0 == data_PID)) { + /* copy the setup packet received in FIFO into the setup buffer in RAM */ + (void)usb_rxfifo_read (&udev->regs, (uint8_t *)&udev->dev.control.req, (uint16_t)bcount); + + transc->xfer_count += bcount; + + setupc_flag = 1; + } + break; + + default: + break; + } + + /* enable the Rx status queue level interrupt */ + udev->regs.gr->GINTEN |= GINTEN_RXFNEIE; + + return 1U; +} + +/*! + \brief handle USB reset interrupt + \param[in] udev: pointer to USB device instance + \param[out] none + \retval status +*/ +static uint32_t usbd_int_reset (usb_core_driver *udev) +{ + uint32_t i; + + /* clear the remote wakeup signaling */ + udev->regs.dr->DCTL &= ~DCTL_RWKUP; + + /* flush the Tx FIFO */ + (void)usb_txfifo_flush (&udev->regs, 0U); + + for (i = 0U; i < udev->bp.num_ep; i++) { + udev->regs.er_in[i]->DIEPINTF = 0xFFU; + udev->regs.er_out[i]->DOEPINTF = 0xFFU; + } + + /* clear all pending device endpoint interrupts */ + udev->regs.dr->DAEPINT = 0xFFFFFFFFU; + + /* enable endpoint 0 interrupts */ + udev->regs.dr->DAEPINTEN = 1U | (1U << 16U); + + /* enable OUT endpoint interrupts */ + udev->regs.dr->DOEPINTEN = DOEPINTEN_STPFEN | DOEPINTEN_TFEN; + + /* enable IN endpoint interrupts */ + udev->regs.dr->DIEPINTEN = DIEPINTEN_TFEN; + + /* reset device address */ + udev->regs.dr->DCFG &= ~DCFG_DAR; + + /* configure endpoint 0 to receive SETUP packets */ + usb_ctlep_startout (udev); + + /* clear USB reset interrupt */ + udev->regs.gr->GINTF = GINTF_RST; + + udev->dev.transc_out[0] = (usb_transc) { + .ep_type = USB_EPTYPE_CTRL, + .max_len = USB_FS_EP0_MAX_LEN + }; + + (void)usb_transc_active (udev, &udev->dev.transc_out[0]); + + udev->dev.transc_in[0] = (usb_transc) { + .ep_addr = { + .dir = 1U + }, + + .ep_type = USB_EPTYPE_CTRL, + .max_len = USB_FS_EP0_MAX_LEN + }; + + (void)usb_transc_active (udev, &udev->dev.transc_in[0]); + + /* upon reset call user call back */ + udev->dev.cur_status = (uint8_t)USBD_DEFAULT; + + return 1U; +} + +/*! + \brief handle USB speed enumeration finish interrupt + \param[in] udev: pointer to USB device instance + \param[out] none + \retval status +*/ +static uint32_t usbd_int_enumfinish (usb_core_driver *udev) +{ + uint8_t enum_speed = (uint8_t)((udev->regs.dr->DSTAT & DSTAT_ES) >> 1U); + + udev->regs.dr->DCTL &= ~DCTL_CGINAK; + udev->regs.dr->DCTL |= DCTL_CGINAK; + + udev->regs.gr->GUSBCS &= ~GUSBCS_UTT; + + /* set USB turn-around time based on device speed and PHY interface */ + if (USB_SPEED[enum_speed] == (uint8_t)USB_SPEED_HIGH) { + udev->bp.core_speed = (uint8_t)USB_SPEED_HIGH; + + udev->regs.gr->GUSBCS |= 0x09U << 10U; + } else { + udev->bp.core_speed = (uint8_t)USB_SPEED_FULL; + + udev->regs.gr->GUSBCS |= 0x05U << 10U; + } + + /* clear interrupt */ + udev->regs.gr->GINTF = GINTF_ENUMFIF; + + return 1U; +} + +/*! + \brief USB suspend interrupt handler + \param[in] udev: pointer to USB device instance + \param[out] none + \retval operation status +*/ +static uint32_t usbd_int_suspend (usb_core_driver *udev) +{ + __IO uint8_t low_power = udev->bp.low_power; + __IO uint8_t suspend = (uint8_t)(udev->regs.dr->DSTAT & DSTAT_SPST); + __IO uint8_t is_configured = (udev->dev.cur_status == (uint8_t)USBD_CONFIGURED)? 1U : 0U; + + udev->dev.backup_status = udev->dev.cur_status; + udev->dev.cur_status = (uint8_t)USBD_SUSPENDED; + + if (low_power && suspend && is_configured) { + /* switch-off the OTG clocks */ + *udev->regs.PWRCLKCTL |= PWRCLKCTL_SUCLK | PWRCLKCTL_SHCLK; + + /* enter DEEP_SLEEP mode with LDO in low power mode */ + pmu_to_deepsleepmode(PMU_LDO_LOWPOWER, WFI_CMD); + } + + /* clear interrupt */ + udev->regs.gr->GINTF = GINTF_SP; + + return 1U; +} + +/*! + \brief check FIFO for the next packet to be loaded + \param[in] udev: pointer to USB device instance + \param[in] ep_num: endpoint identifier which is in (0..3) + \param[out] none + \retval status +*/ +static uint32_t usbd_emptytxfifo_write (usb_core_driver *udev, uint32_t ep_num) +{ + uint32_t len; + uint32_t word_count; + + usb_transc *transc = &udev->dev.transc_in[ep_num]; + + len = transc->xfer_len - transc->xfer_count; + + /* get the data length to write */ + if (len > transc->max_len) { + len = transc->max_len; + } + + word_count = (len + 3U) / 4U; + + while (((udev->regs.er_in[ep_num]->DIEPTFSTAT & DIEPTFSTAT_IEPTFS) >= word_count) && \ + (transc->xfer_count < transc->xfer_len)) { + len = transc->xfer_len - transc->xfer_count; + + if (len > transc->max_len) { + len = transc->max_len; + } + + /* write FIFO in word(4bytes) */ + word_count = (len + 3U) / 4U; + + /* write the FIFO */ + (void)usb_txfifo_write (&udev->regs, transc->xfer_buf, (uint8_t)ep_num, (uint16_t)len); + + transc->xfer_buf += len; + transc->xfer_count += len; + + if (transc->xfer_count == transc->xfer_len) { + /* disable the device endpoint FIFO empty interrupt */ + udev->regs.dr->DIEPFEINTEN &= ~(0x01U << ep_num); + } + } + + return 1U; +} diff --git a/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/driver/Source/drv_usbh_int.c b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/driver/Source/drv_usbh_int.c new file mode 100644 index 0000000000..8cecd56a4f --- /dev/null +++ b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/driver/Source/drv_usbh_int.c @@ -0,0 +1,622 @@ +/*! + \file drv_usbh_int.c + \brief USB host mode interrupt handler file + + \version 2020-07-28, V3.0.0, firmware for GD32F20x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "drv_usb_core.h" +#include "drv_usb_host.h" +#include "drv_usbh_int.h" +#include "usbh_core.h" + +#if defined (__CC_ARM) /*!< ARM compiler */ + #pragma O0 +#elif defined (__GNUC__) /*!< GNU compiler */ + #pragma GCC optimize ("O0") +#elif defined (__TASKING__) /*!< TASKING compiler */ + #pragma optimize=0 +#endif /* __CC_ARM */ + +/* local function prototypes ('static') */ +static uint32_t usbh_int_port (usb_core_driver *udev); +static uint32_t usbh_int_pipe (usb_core_driver *udev); +static uint32_t usbh_int_pipe_in (usb_core_driver *udev, uint32_t pp_num); +static uint32_t usbh_int_pipe_out (usb_core_driver *udev, uint32_t pp_num); +static uint32_t usbh_int_rxfifonoempty (usb_core_driver *udev); +static uint32_t usbh_int_txfifoempty (usb_core_driver *udev, usb_pipe_mode pp_mode); + +/*! + \brief handle global host interrupt + \param[in] udev: pointer to USB core instance + \param[out] none + \retval operation status +*/ +uint32_t usbh_isr (usb_core_driver *udev) +{ + uint32_t retval = 0U; + + __IO uint32_t intr = 0U; + + /* check if host mode */ + if (HOST_MODE == (udev->regs.gr->GINTF & GINTF_COPM)) { + intr = usb_coreintr_get(&udev->regs); + + if (!intr) { + return 0U; + } + + if (intr & GINTF_SOF) { + usbh_int_fop->SOF(udev->host.data); + + /* clear interrupt */ + udev->regs.gr->GINTF = GINTF_SOF; + } + + if (intr & GINTF_RXFNEIF) { + retval |= usbh_int_rxfifonoempty (udev); + } + + if (intr & GINTF_NPTXFEIF) { + retval |= usbh_int_txfifoempty (udev, PIPE_NON_PERIOD); + } + + if (intr & GINTF_PTXFEIF) { + retval |= usbh_int_txfifoempty (udev, PIPE_PERIOD); + } + + if (intr & GINTF_HCIF) { + retval |= usbh_int_pipe (udev); + } + + if (intr & GINTF_HPIF) { + retval |= usbh_int_port (udev); + } + + if (intr & GINTF_DISCIF) { + usbh_int_fop->disconnect(udev->host.data); + + /* clear interrupt */ + udev->regs.gr->GINTF = GINTF_DISCIF; + } + + if (intr & GINTF_ISOONCIF) { + udev->regs.pr[0]->HCHCTL |= HCHCTL_CEN | HCHCTL_CDIS; + + /* clear interrupt */ + udev->regs.gr->GINTF = GINTF_ISOONCIF; + } + + if (intr & GINTF_SESIF) { + usb_portvbus_switch (udev, 1U); + + udev->regs.gr->GINTF = GINTF_SESIF; + } + + if (intr & GINTF_WKUPIF) { + /* clear interrupt */ + udev->regs.gr->GINTF = GINTF_WKUPIF; + } + } + + return retval; +} + +/*! + \brief handle USB pipe halt + \param[in] udev: pointer to USB core instance + \param[in] pp_num: pp_num: host channel number which is in (0..7) + \param[in] pp_int: pipe interrupt + \param[in] pp_status: pipe status + \param[out] none + \retval none +*/ +static inline void usb_pp_halt (usb_core_driver *udev, + uint8_t pp_num, + uint32_t pp_int, + usb_pipe_staus pp_status) +{ + udev->regs.pr[pp_num]->HCHINTEN |= HCHINTEN_CHIE; + + usb_pipe_halt(udev, pp_num); + + udev->regs.pr[pp_num]->HCHINTF = pp_int; + + udev->host.pipe[pp_num].pp_status = pp_status; +} + +/*! + \brief handle the host port interrupt + \param[in] udev: pointer to USB device instance + \param[out] none + \retval operation status +*/ +#if defined (__ICCARM__) /*!< IAR compiler */ + #pragma optimize = none +#endif /* __ICCARM */ +static uint32_t usbh_int_port (usb_core_driver *udev) +{ + uint32_t retval = 0U; + + /* note: when the USB PHY use USB HS PHY, the flag is needed */ + uint8_t port_reset = 0U; + + __IO uint32_t port_state = *udev->regs.HPCS; + + /* clear the interrupt bits in GINTSTS */ + port_state &= ~(HPCS_PE | HPCS_PCD | HPCS_PEDC); + + /* port connect detected */ + if (*udev->regs.HPCS & HPCS_PCD) { + port_state |= HPCS_PCD; + + usbh_int_fop->connect(udev->host.data); + + retval |= 1U; + } + + /* port enable changed */ + if (*udev->regs.HPCS & HPCS_PEDC) { + port_state |= HPCS_PEDC; + + if (*udev->regs.HPCS & HPCS_PE) { + uint32_t port_speed = usb_curspeed_get(udev); + uint32_t clock_type = udev->regs.hr->HCTL & HCTL_CLKSEL; + + udev->host.connect_status = 1U; + + if (PORT_SPEED_LOW == port_speed) { + udev->regs.hr->HFT = 6000U; + + if (HCTL_6MHZ != clock_type) { + if (USB_EMBEDDED_PHY == udev->bp.phy_itf) { + usb_phyclock_config (udev, HCTL_6MHZ); + } + + port_reset = 1U; + } + } else if (PORT_SPEED_FULL == port_speed) { + udev->regs.hr->HFT = 48000U; + + if (HCTL_48MHZ != clock_type) { + usb_phyclock_config (udev, HCTL_48MHZ); + } + + port_reset = 1U; + } else { + /* for high speed device and others */ + port_reset = 1U; + } + + usbh_int_fop->port_enabled(udev->host.data); + + udev->regs.gr->GINTEN |= GINTEN_DISCIE | GINTEN_SOFIE; + } else { + usbh_int_fop->port_disabled(udev->host.data); + } + } + + if (port_reset) { + usb_port_reset(udev); + } + + /* clear port interrupts */ + *udev->regs.HPCS = port_state; + + return retval; +} + +/*! + \brief handle all host channels interrupt + \param[in] udev: pointer to USB device instance + \param[out] none + \retval operation status +*/ +static uint32_t usbh_int_pipe (usb_core_driver *udev) +{ + uint32_t pp_num = 0U; + uint32_t retval = 0U; + + for (pp_num = 0U; pp_num < udev->bp.num_pipe; pp_num++) { + if ((udev->regs.hr->HACHINT & HACHINT_HACHINT) & (1UL << pp_num)) { + if (udev->regs.pr[pp_num]->HCHCTL & HCHCTL_EPDIR) { + retval |= usbh_int_pipe_in (udev, pp_num); + } else { + retval |= usbh_int_pipe_out (udev, pp_num); + } + } + } + + return retval; +} + +/*! + \brief handle the IN channel interrupt + \param[in] udev: pointer to USB device instance + \param[in] pp_num: host channel number which is in (0..7) + \param[out] none + \retval operation status +*/ +#if defined (__ICCARM__) /*!< IAR compiler */ + #pragma optimize = none +#endif /* __ICCARM */ +static uint32_t usbh_int_pipe_in (usb_core_driver *udev, uint32_t pp_num) +{ + usb_pr *pp_reg = udev->regs.pr[pp_num]; + + usb_pipe *pp = &udev->host.pipe[pp_num]; + + __IO uint32_t intr_pp = pp_reg->HCHINTF & pp_reg->HCHINTEN; + + uint8_t ep_type = (uint8_t)((pp_reg->HCHCTL & HCHCTL_EPTYPE) >> 18U); + + if (intr_pp & HCHINTF_ACK) { + pp_reg->HCHINTF = HCHINTF_ACK; + } else if (intr_pp & HCHINTF_STALL) { + usb_pp_halt (udev, (uint8_t)pp_num, HCHINTF_STALL, PIPE_STALL); + pp_reg->HCHINTF = HCHINTF_NAK; + + /* note: When there is a 'STALL', reset also NAK, + else, the udev->host.pp_status = HC_STALL + will be overwritten by 'NAK' in code below */ + intr_pp &= ~HCHINTF_NAK; + } else if (intr_pp & HCHINTF_DTER) { + usb_pp_halt (udev, (uint8_t)pp_num, HCHINTF_DTER, PIPE_DTGERR); + pp_reg->HCHINTF = HCHINTF_NAK; + } else { + /* no operation */ + } + + if (intr_pp & HCHINTF_REQOVR) { + usb_pp_halt (udev, (uint8_t)pp_num, HCHINTF_REQOVR, PIPE_REQOVR); + } else if (intr_pp & HCHINTF_TF) { + if ((uint8_t)USB_USE_DMA == udev->bp.transfer_mode) { + udev->host.backup_xfercount[pp_num] = pp->xfer_len - (pp_reg->HCHLEN & HCHLEN_TLEN); + } + + pp->pp_status = PIPE_XF; + pp->err_count = 0U; + + pp_reg->HCHINTF = HCHINTF_TF; + + switch (ep_type) { + case USB_EPTYPE_CTRL: + case USB_EPTYPE_BULK: + usb_pp_halt (udev, (uint8_t)pp_num, HCHINTF_NAK, PIPE_XF); + + pp->data_toggle_in ^= 1U; + break; + + case USB_EPTYPE_INTR: + case USB_EPTYPE_ISOC: + pp_reg->HCHCTL |= HCHCTL_ODDFRM; + pp->urb_state = URB_DONE; + break; + + default: + break; + } + } else if (intr_pp & HCHINTF_CH) { + pp_reg->HCHINTEN &= ~HCHINTEN_CHIE; + + switch (pp->pp_status) { + case PIPE_XF: + pp->urb_state = URB_DONE; + break; + + case PIPE_STALL: + pp->urb_state = URB_STALL; + break; + + case PIPE_TRACERR: + case PIPE_DTGERR: + pp->err_count = 0U; + pp->urb_state = URB_ERROR; + + pp->data_toggle_in ^= 1U; + break; + + case PIPE_IDLE: + case PIPE_HALTED: + case PIPE_NAK: + case PIPE_NYET: + case PIPE_BBERR: + case PIPE_REQOVR: + default: + if((uint8_t)USB_EPTYPE_INTR == ep_type) { + pp->data_toggle_in ^= 1U; + } + break; + } + + pp_reg->HCHINTF = HCHINTF_CH; + } else if (intr_pp & HCHINTF_USBER) { + pp->err_count++; + usb_pp_halt (udev, (uint8_t)pp_num, HCHINTF_USBER, PIPE_TRACERR); + } else if (intr_pp & HCHINTF_NAK) { + switch (ep_type) { + case USB_EPTYPE_CTRL: + case USB_EPTYPE_BULK: + /* re-activate the channel */ + pp_reg->HCHCTL = (pp_reg->HCHCTL | HCHCTL_CEN) & ~HCHCTL_CDIS; + break; + + case USB_EPTYPE_INTR: + pp_reg->HCHINTEN |= HCHINTEN_CHIE; + + (void)usb_pipe_halt(udev, (uint8_t)pp_num); + break; + + default: + break; + } + + pp->pp_status = PIPE_NAK; + + pp_reg->HCHINTF = HCHINTF_NAK; + } else { + /* no operation */ + } + + return 1U; +} + +/*! + \brief handle the OUT channel interrupt + \param[in] udev: pointer to USB device instance + \param[in] pp_num: host channel number which is in (0..7) + \param[out] none + \retval operation status +*/ +#if defined (__ICCARM__) /*!< IAR compiler */ + #pragma optimize = none +#endif /* __ICCARM */ +static uint32_t usbh_int_pipe_out (usb_core_driver *udev, uint32_t pp_num) +{ + usb_pr *pp_reg = udev->regs.pr[pp_num]; + + usb_pipe *pp = &udev->host.pipe[pp_num]; + + uint32_t intr_pp = pp_reg->HCHINTF & pp_reg->HCHINTEN; + + if (intr_pp & HCHINTF_ACK) { + if (URB_PING == pp->urb_state) { + pp->err_count = 0U; + usb_pp_halt (udev, (uint8_t)pp_num, HCHINTF_TF, PIPE_XF); + } + + pp_reg->HCHINTF = HCHINTF_ACK; + } else if (intr_pp & HCHINTF_STALL) { + usb_pp_halt (udev, (uint8_t)pp_num, HCHINTF_STALL, PIPE_STALL); + } else if (intr_pp & HCHINTF_DTER) { + usb_pp_halt (udev, (uint8_t)pp_num, HCHINTF_DTER, PIPE_DTGERR); + pp_reg->HCHINTF = HCHINTF_NAK; + } else if (intr_pp & HCHINTF_REQOVR) { + usb_pp_halt (udev, (uint8_t)pp_num, HCHINTF_REQOVR, PIPE_REQOVR); + } else if (intr_pp & HCHINTF_TF) { + pp->err_count = 0U; + usb_pp_halt (udev, (uint8_t)pp_num, HCHINTF_TF, PIPE_XF); + } else if (intr_pp & HCHINTF_NAK) { + pp->err_count = 0U; + usb_pp_halt (udev, (uint8_t)pp_num, HCHINTF_NAK, PIPE_NAK); + } else if (intr_pp & HCHINTF_USBER) { + pp->err_count++; + usb_pp_halt (udev, (uint8_t)pp_num, HCHINTF_USBER, PIPE_TRACERR); + } else if (intr_pp & HCHINTF_NYET) { + pp->err_count = 0U; + usb_pp_halt (udev, (uint8_t)pp_num, HCHINTF_NYET, PIPE_NYET); + } else if (intr_pp & HCHINTF_CH) { + udev->regs.pr[pp_num]->HCHINTEN &= ~HCHINTEN_CHIE; + + switch (pp->pp_status) { + case PIPE_XF: + pp->urb_state = URB_DONE; + + if ((uint8_t)USB_EPTYPE_BULK == ((pp_reg->HCHCTL & HCHCTL_EPTYPE) >> 18U)) { + pp->data_toggle_out ^= 1U; + } + break; + + case PIPE_NAK: + + if (URB_PING == pp->urb_state) { + (void)usb_pipe_ping (udev, (uint8_t)pp_num); + } else { + pp->urb_state = URB_NOTREADY; + } + break; + + case PIPE_NYET: + if (1U == udev->host.pipe[pp_num].ping) { + (void)usb_pipe_ping (udev, (uint8_t)pp_num); + pp->urb_state = URB_PING; + } + else { + pp->urb_state = URB_NOTREADY; + } + break; + + case PIPE_STALL: + pp->urb_state = URB_STALL; + break; + + case PIPE_TRACERR: + if (3U == pp->err_count) { + pp->urb_state = URB_ERROR; + pp->err_count = 0U; + } + break; + + case PIPE_IDLE: + case PIPE_HALTED: + case PIPE_BBERR: + case PIPE_REQOVR: + case PIPE_DTGERR: + default: + break; + } + + pp_reg->HCHINTF = HCHINTF_CH; + } else { + /* no operation */ + } + + return 1U; +} + +/*! + \brief handle the RX FIFO non-empty interrupt + \param[in] udev: pointer to USB device instance + \param[out] none + \retval operation status +*/ +#if defined (__ICCARM__) /*!< IAR compiler */ + #pragma optimize = none +#endif /* __ICCARM */ +static uint32_t usbh_int_rxfifonoempty (usb_core_driver *udev) +{ + uint32_t count = 0U; + + __IO uint8_t pp_num = 0U; + __IO uint32_t rx_stat = 0U; + + /* disable the RX status queue level interrupt */ + udev->regs.gr->GINTEN &= ~GINTEN_RXFNEIE; + + rx_stat = udev->regs.gr->GRSTATP; + pp_num = (uint8_t)(rx_stat & GRSTATRP_CNUM); + + switch ((rx_stat & GRSTATRP_RPCKST) >> 17U) { + case GRXSTS_PKTSTS_IN: + count = (rx_stat & GRSTATRP_BCOUNT) >> 4U; + + /* read the data into the host buffer. */ + if ((count > 0U) && (NULL != udev->host.pipe[pp_num].xfer_buf)) { + (void)usb_rxfifo_read (&udev->regs, udev->host.pipe[pp_num].xfer_buf, (uint16_t)count); + + /* manage multiple transfer packet */ + udev->host.pipe[pp_num].xfer_buf += count; + udev->host.pipe[pp_num].xfer_count += count; + + udev->host.backup_xfercount[pp_num] = udev->host.pipe[pp_num].xfer_count; + + if (udev->regs.pr[pp_num]->HCHLEN & HCHLEN_PCNT) { + /* re-activate the channel when more packets are expected */ + __IO uint32_t pp_ctl = udev->regs.pr[pp_num]->HCHCTL; + + pp_ctl |= HCHCTL_CEN; + pp_ctl &= ~HCHCTL_CDIS; + + udev->regs.pr[pp_num]->HCHCTL = pp_ctl; + } + } + break; + + case GRXSTS_PKTSTS_IN_XFER_COMP: + break; + + case GRXSTS_PKTSTS_DATA_TOGGLE_ERR: + count = (rx_stat & GRSTATRP_BCOUNT) >> 4U; + + while (count > 0U) { + rx_stat = udev->regs.gr->GRSTATP; + count--; + } + break; + + case GRXSTS_PKTSTS_CH_HALTED: + break; + + default: + break; + } + + /* enable the RX status queue level interrupt */ + udev->regs.gr->GINTEN |= GINTEN_RXFNEIE; + + return 1U; +} + +/*! + \brief handle the TX FIFO empty interrupt + \param[in] udev: pointer to USB device instance + \param[in] pp_mode: pipe mode + \param[out] none + \retval operation status +*/ +#if defined (__ICCARM__) /*!< IAR compiler */ + #pragma optimize = none +#endif /* __ICCARM */ +static uint32_t usbh_int_txfifoempty (usb_core_driver *udev, usb_pipe_mode pp_mode) +{ + uint8_t pp_num = 0U; + uint16_t word_count = 0U, len = 0U; + __IO uint32_t *txfiforeg = 0U, txfifostate = 0U; + + if (PIPE_NON_PERIOD == pp_mode) { + txfiforeg = &udev->regs.gr->HNPTFQSTAT; + } else if (PIPE_PERIOD == pp_mode) { + txfiforeg = &udev->regs.hr->HPTFQSTAT; + } else { + return 0U; + } + + txfifostate = *txfiforeg; + + pp_num = (uint8_t)((txfifostate & TFQSTAT_CNUM) >> 27U); + + word_count = (uint16_t)(udev->host.pipe[pp_num].xfer_len + 3U) / 4U; + + while (((txfifostate & TFQSTAT_TXFS) >= word_count) && (0U != udev->host.pipe[pp_num].xfer_len)) { + len = (uint16_t)(txfifostate & TFQSTAT_TXFS) * 4U; + + if (len > udev->host.pipe[pp_num].xfer_len) { + /* last packet */ + len = (uint16_t)udev->host.pipe[pp_num].xfer_len; + + if (PIPE_NON_PERIOD == pp_mode) { + udev->regs.gr->GINTEN &= ~GINTEN_NPTXFEIE; + } else { + udev->regs.gr->GINTEN &= ~GINTEN_PTXFEIE; + } + } + + word_count = (uint16_t)((udev->host.pipe[pp_num].xfer_len + 3U) / 4U); + usb_txfifo_write (&udev->regs, udev->host.pipe[pp_num].xfer_buf, pp_num, len); + + udev->host.pipe[pp_num].xfer_buf += len; + udev->host.pipe[pp_num].xfer_len -= len; + udev->host.pipe[pp_num].xfer_count += len; + + txfifostate = *txfiforeg; + } + + return 1U; +} diff --git a/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/host/class/hid/Include/usbh_hid_core.h b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/host/class/hid/Include/usbh_hid_core.h new file mode 100644 index 0000000000..341d20bb47 --- /dev/null +++ b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/host/class/hid/Include/usbh_hid_core.h @@ -0,0 +1,212 @@ +/*! + \file usbh_hid_core.h + \brief header file for the usbh_hid_core.c + + \version 2020-07-28, V3.0.0, firmware for GD32F20x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef __USBH_HID_CORE_H +#define __USBH_HID_CORE_H + +#include "usb_hid.h" +#include "usbh_enum.h" +#include "usbh_transc.h" + +#define HID_MIN_POLL 10U +#define HID_REPORT_SIZE 16U +#define HID_MAX_USAGE 10U +#define HID_MAX_NBR_REPORT_FMT 10U +#define HID_QUEUE_SIZE 10U + +#define HID_ITEM_LONG 0xFEU + +#define HID_ITEM_TYPE_MAIN 0x00U +#define HID_ITEM_TYPE_GLOBAL 0x01U +#define HID_ITEM_TYPE_LOCAL 0x02U +#define HID_ITEM_TYPE_RESERVED 0x03U + +#define HID_MAIN_ITEM_TAG_INPUT 0x08U +#define HID_MAIN_ITEM_TAG_OUTPUT 0x09U +#define HID_MAIN_ITEM_TAG_COLLECTION 0x0AU +#define HID_MAIN_ITEM_TAG_FEATURE 0x0BU +#define HID_MAIN_ITEM_TAG_ENDCOLLECTION 0x0CU + +#define HID_GLOBAL_ITEM_TAG_USAGE_PAGE 0x00U +#define HID_GLOBAL_ITEM_TAG_LOG_MIN 0x01U +#define HID_GLOBAL_ITEM_TAG_LOG_MAX 0x02U +#define HID_GLOBAL_ITEM_TAG_PHY_MIN 0x03U +#define HID_GLOBAL_ITEM_TAG_PHY_MAX 0x04U +#define HID_GLOBAL_ITEM_TAG_UNIT_EXPONENT 0x05U +#define HID_GLOBAL_ITEM_TAG_UNIT 0x06U +#define HID_GLOBAL_ITEM_TAG_REPORT_SIZE 0x07U +#define HID_GLOBAL_ITEM_TAG_REPORT_ID 0x08U +#define HID_GLOBAL_ITEM_TAG_REPORT_COUNT 0x09U +#define HID_GLOBAL_ITEM_TAG_PUSH 0x0AU +#define HID_GLOBAL_ITEM_TAG_POP 0x0BU + +#define HID_LOCAL_ITEM_TAG_USAGE 0x00U +#define HID_LOCAL_ITEM_TAG_USAGE_MIN 0x01U +#define HID_LOCAL_ITEM_TAG_USAGE_MAX 0x02U +#define HID_LOCAL_ITEM_TAG_DESIGNATOR_INDEX 0x03U +#define HID_LOCAL_ITEM_TAG_DESIGNATOR_MIN 0x04U +#define HID_LOCAL_ITEM_TAG_DESIGNATOR_MAX 0x05U +#define HID_LOCAL_ITEM_TAG_STRING_INDEX 0x07U +#define HID_LOCAL_ITEM_TAG_STRING_MIN 0x08U +#define HID_LOCAL_ITEM_TAG_STRING_MAX 0x09U +#define HID_LOCAL_ITEM_TAG_DELIMITER 0x0AU + +#define USB_HID_DESC_SIZE 9U + +/* states for HID state machine */ +typedef enum { + HID_INIT = 0U, + HID_IDLE, + HID_SEND_DATA, + HID_BUSY, + HID_GET_DATA, + HID_SYNC, + HID_POLL, + HID_ERROR, +} hid_state; + +typedef enum { + HID_REQ_INIT = 0U, + HID_REQ_IDLE, + HID_REQ_GET_REPORT_DESC, + HID_REQ_GET_HID_DESC, + HID_REQ_SET_IDLE, + HID_REQ_SET_PROTOCOL, + HID_REQ_SET_REPORT, +} hid_ctlstate; + +typedef enum +{ + HID_MOUSE = 0x01U, + HID_KEYBOARD = 0x02U, + HID_UNKNOWN = 0xFFU, +} hid_type; + +typedef struct _hid_report_data +{ + uint8_t ReportID; + uint8_t ReportType; + uint16_t UsagePage; + uint32_t Usage[HID_MAX_USAGE]; + uint32_t NbrUsage; + uint32_t UsageMin; + uint32_t UsageMax; + int32_t LogMin; + int32_t LogMax; + int32_t PhyMin; + int32_t PhyMax; + int32_t UnitExp; + uint32_t Unit; + uint32_t ReportSize; + uint32_t ReportCnt; + uint32_t Flag; + uint32_t PhyUsage; + uint32_t AppUsage; + uint32_t LogUsage; +} hid_report_data; + +typedef struct _hid_report_ID +{ + uint8_t size; /*!< report size return by the device ID */ + uint8_t reportID; /*!< report ID */ + uint8_t type; /*!< report type (INPUT/OUTPUT/FEATURE) */ +} hid_report_ID; + +typedef struct _hid_collection +{ + uint32_t usage; + uint8_t type; + struct _hid_collection *next_ptr; +} hid_collection; + +typedef struct _hid_appcollection +{ + uint32_t usage; + uint8_t type; + uint8_t nbr_report_fmt; + hid_report_data report_data[HID_MAX_NBR_REPORT_FMT]; +} hid_appcollection; + +typedef struct +{ + uint8_t *buf; + uint16_t head; + uint16_t tail; + uint16_t size; + uint8_t lock; +} data_fifo; + +/* structure for HID process */ +typedef struct _hid_process +{ + uint8_t pipe_in; + uint8_t pipe_out; + uint8_t ep_addr; + uint8_t ep_in; + uint8_t ep_out; + __IO uint8_t data_ready; + uint8_t *pdata; + uint16_t len; + uint16_t poll; + + __IO uint32_t timer; + + data_fifo fifo; + usb_desc_hid hid_desc; + hid_report_data hid_report; + + hid_state state; + hid_ctlstate ctl_state; + usbh_status (*init)(usb_core_driver *udev, usbh_host *uhost); + void (*machine)(usb_core_driver *udev, usbh_host *uhost); +} usbh_hid_handler; + +extern usbh_class usbh_hid; + +/* function declarations */ +/* set HID report */ +usbh_status usbh_set_report (usb_core_driver *udev, + usbh_host *uhost, + uint8_t report_type, + uint8_t report_ID, + uint8_t report_len, + uint8_t *report_buf); +/* read data from FIFO */ +uint16_t usbh_hid_fifo_read (data_fifo *fifo, void *buf, uint16_t nbytes); +/* write data to FIFO */ +uint16_t usbh_hid_fifo_write (data_fifo *fifo, void *buf, uint16_t nbytes); +/* initialize FIFO */ +void usbh_hid_fifo_init (data_fifo *fifo, uint8_t *buf, uint16_t size); + +#endif /* __USBH_HID_CORE_H */ diff --git a/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/host/class/hid/Include/usbh_hid_keybd.h b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/host/class/hid/Include/usbh_hid_keybd.h new file mode 100644 index 0000000000..633687ddf5 --- /dev/null +++ b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/host/class/hid/Include/usbh_hid_keybd.h @@ -0,0 +1,303 @@ +/*! + \file usbh_hid_keybd.h + \brief header file for usbh_hid_keybd.c + + \version 2020-07-28, V3.0.0, firmware for GD32F20x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef __USBH_HID_KEYBD_H +#define __USBH_HID_KEYBD_H + +#include "usb_conf.h" +#include "usbh_hid_core.h" + +//#define AZERTY_KEYBOARD +#define QWERTY_KEYBOARD + +#define KBD_LEFT_CTRL 0x01U +#define KBD_LEFT_SHIFT 0x02U +#define KBD_LEFT_ALT 0x04U +#define KBD_LEFT_GUI 0x08U +#define KBD_RIGHT_CTRL 0x10U +#define KBD_RIGHT_SHIFT 0x20U +#define KBD_RIGHT_ALT 0x40U +#define KBD_RIGHT_GUI 0x80U + +#define KEY_NONE 0x00U +#define KEY_ERRORROLLOVER 0x01U +#define KEY_POSTFAIL 0x02U +#define KEY_ERRORUNDEFINED 0x03U +#define KEY_A 0x04U +#define KEY_B 0x05U +#define KEY_C 0x06U +#define KEY_D 0x07U +#define KEY_E 0x08U +#define KEY_F 0x09U +#define KEY_G 0x0AU +#define KEY_H 0x0BU +#define KEY_I 0x0CU +#define KEY_J 0x0DU +#define KEY_K 0x0EU +#define KEY_L 0x0FU +#define KEY_M 0x10U +#define KEY_N 0x11U +#define KEY_O 0x12U +#define KEY_P 0x13U +#define KEY_Q 0x14U +#define KEY_R 0x15U +#define KEY_S 0x16U +#define KEY_T 0x17U +#define KEY_U 0x18U +#define KEY_V 0x19U +#define KEY_W 0x1AU +#define KEY_X 0x1BU +#define KEY_Y 0x1CU +#define KEY_Z 0x1DU +#define KEY_1_EXCLAMATION_MARK 0x1EU +#define KEY_2_AT 0x1FU +#define KEY_3_NUMBER_SIGN 0x20U +#define KEY_4_DOLLAR 0x21U +#define KEY_5_PERCENT 0x22U +#define KEY_6_CARET 0x23U +#define KEY_7_AMPERSAND 0x24U +#define KEY_8_ASTERISK 0x25U +#define KEY_9_OPARENTHESIS 0x26U +#define KEY_0_CPARENTHESIS 0x27U +#define KEY_ENTER 0x28U +#define KEY_ESCAPE 0x29U +#define KEY_BACKSPACE 0x2AU +#define KEY_TAB 0x2BU +#define KEY_SPACEBAR 0x2CU +#define KEY_MINUS_UNDERSCORE 0x2DU +#define KEY_EQUAL_PLUS 0x2EU +#define KEY_OBRACKET_AND_OBRACE 0x2FU +#define KEY_CBRACKET_AND_CBRACE 0x30U +#define KEY_BACKSLASH_VERTICAL_BAR 0x31U +#define KEY_NONUS_NUMBER_SIGN_TILDE 0x32U +#define KEY_SEMICOLON_COLON 0x33U +#define KEY_SINGLE_AND_DOUBLE_QUOTE 0x34U +#define KEY_GRAVE ACCENT AND TILDE 0x35U +#define KEY_COMMA_AND_LESS 0x36U +#define KEY_DOT_GREATER 0x37U +#define KEY_SLASH_QUESTION 0x38U +#define KEY_CAPS LOCK 0x39U +#define KEY_F1 0x3AU +#define KEY_F2 0x3BU +#define KEY_F3 0x3CU +#define KEY_F4 0x3DU +#define KEY_F5 0x3EU +#define KEY_F6 0x3FU +#define KEY_F7 0x40U +#define KEY_F8 0x41U +#define KEY_F9 0x42U +#define KEY_F10 0x43U +#define KEY_F11 0x44U +#define KEY_F12 0x45U +#define KEY_PRINTSCREEN 0x46U +#define KEY_SCROLL LOCK 0x47U +#define KEY_PAUSE 0x48U +#define KEY_INSERT 0x49U +#define KEY_HOME 0x4AU +#define KEY_PAGEUP 0x4BU +#define KEY_DELETE 0x4CU +#define KEY_END1 0x4DU +#define KEY_PAGEDOWN 0x4EU +#define KEY_RIGHTARROW 0x4FU +#define KEY_LEFTARROW 0x50U +#define KEY_DOWNARROW 0x51U +#define KEY_UPARROW 0x52U +#define KEY_KEYPAD_NUM_LOCK_AND_CLEAR 0x53U +#define KEY_KEYPAD_SLASH 0x54U +#define KEY_KEYPAD_ASTERIKS 0x55U +#define KEY_KEYPAD_MINUS 0x56U +#define KEY_KEYPAD_PLUS 0x57U +#define KEY_KEYPAD_ENTER 0x58U +#define KEY_KEYPAD_1_END 0x59U +#define KEY_KEYPAD_2_DOWN_ARROW 0x5AU +#define KEY_KEYPAD_3_PAGEDN 0x5BU +#define KEY_KEYPAD_4_LEFT_ARROW 0x5CU +#define KEY_KEYPAD_5 0x5DU +#define KEY_KEYPAD_6_RIGHT_ARROW 0x5EU +#define KEY_KEYPAD_7_HOME 0x5FU +#define KEY_KEYPAD_8_UP_ARROW 0x60U +#define KEY_KEYPAD_9_PAGEUP 0x61U +#define KEY_KEYPAD_0_INSERT 0x62U +#define KEY_KEYPAD_DECIMAL_SEPARATOR_DELETE 0x63U +#define KEY_NONUS_BACK_SLASH_VERTICAL_BAR 0x64U +#define KEY_APPLICATION 0x65U +#define KEY_POWER 0x66U +#define KEY_KEYPAD_EQUAL 0x67U +#define KEY_F13 0x68U +#define KEY_F14 0x69U +#define KEY_F15 0x6AU +#define KEY_F16 0x6BU +#define KEY_F17 0x6CU +#define KEY_F18 0x6DU +#define KEY_F19 0x6EU +#define KEY_F20 0x6FU +#define KEY_F21 0x70U +#define KEY_F22 0x71U +#define KEY_F23 0x72U +#define KEY_F24 0x73U +#define KEY_EXECUTE 0x74U +#define KEY_HELP 0x75U +#define KEY_MENU 0x76U +#define KEY_SELECT 0x77U +#define KEY_STOP 0x78U +#define KEY_AGAIN 0x79U +#define KEY_UNDO 0x7AU +#define KEY_CUT 0x7BU +#define KEY_COPY 0x7CU +#define KEY_PASTE 0x7DU +#define KEY_FIND 0x7EU +#define KEY_MUTE 0x7FU +#define KEY_VOLUME_UP 0x80U +#define KEY_VOLUME_DOWN 0x81U +#define KEY_LOCKING_CAPS_LOCK 0x82U +#define KEY_LOCKING_NUM_LOCK 0x83U +#define KEY_LOCKING_SCROLL_LOCK 0x84U +#define KEY_KEYPAD_COMMA 0x85U +#define KEY_KEYPAD_EQUAL_SIGN 0x86U +#define KEY_INTERNATIONAL1 0x87U +#define KEY_INTERNATIONAL2 0x88U +#define KEY_INTERNATIONAL3 0x89U +#define KEY_INTERNATIONAL4 0x8AU +#define KEY_INTERNATIONAL5 0x8BU +#define KEY_INTERNATIONAL6 0x8CU +#define KEY_INTERNATIONAL7 0x8DU +#define KEY_INTERNATIONAL8 0x8EU +#define KEY_INTERNATIONAL9 0x8FU +#define KEY_LANG1 0x90U +#define KEY_LANG2 0x91U +#define KEY_LANG3 0x92U +#define KEY_LANG4 0x93U +#define KEY_LANG5 0x94U +#define KEY_LANG6 0x95U +#define KEY_LANG7 0x96U +#define KEY_LANG8 0x97U +#define KEY_LANG9 0x98U +#define KEY_ALTERNATE_ERASE 0x99U +#define KEY_SYSREQ 0x9AU +#define KEY_CANCEL 0x9BU +#define KEY_CLEAR 0x9CU +#define KEY_PRIOR 0x9DU +#define KEY_RETURN 0x9EU +#define KEY_SEPARATOR 0x9FU +#define KEY_OUT 0xA0U +#define KEY_OPER 0xA1U +#define KEY_CLEAR_AGAIN 0xA2U +#define KEY_CRSEL 0xA3U +#define KEY_EXSEL 0xA4U +#define KEY_KEYPAD_00 0xB0U +#define KEY_KEYPAD_000 0xB1U +#define KEY_THOUSANDS_SEPARATOR 0xB2U +#define KEY_DECIMAL_SEPARATOR 0xB3U +#define KEY_CURRENCY_UNIT 0xB4U +#define KEY_CURRENCY_SUB_UNIT 0xB5U +#define KEY_KEYPAD_OPARENTHESIS 0xB6U +#define KEY_KEYPAD_CPARENTHESIS 0xB7U +#define KEY_KEYPAD_OBRACE 0xB8U +#define KEY_KEYPAD_CBRACE 0xB9U +#define KEY_KEYPAD_TAB 0xBAU +#define KEY_KEYPAD_BACKSPACE 0xBBU +#define KEY_KEYPAD_A 0xBCU +#define KEY_KEYPAD_B 0xBDU +#define KEY_KEYPAD_C 0xBEU +#define KEY_KEYPAD_D 0xBFU +#define KEY_KEYPAD_E 0xC0U +#define KEY_KEYPAD_F 0xC1U +#define KEY_KEYPAD_XOR 0xC2U +#define KEY_KEYPAD_CARET 0xC3U +#define KEY_KEYPAD_PERCENT 0xC4U +#define KEY_KEYPAD_LESS 0xC5U +#define KEY_KEYPAD_GREATER 0xC6U +#define KEY_KEYPAD_AMPERSAND 0xC7U +#define KEY_KEYPAD_LOGICAL_AND 0xC8U +#define KEY_KEYPAD_VERTICAL_BAR 0xC9U +#define KEY_KEYPAD_LOGIACL_OR 0xCAU +#define KEY_KEYPAD_COLON 0xCBU +#define KEY_KEYPAD_NUMBER_SIGN 0xCCU +#define KEY_KEYPAD_SPACE 0xCDU +#define KEY_KEYPAD_AT 0xCEU +#define KEY_KEYPAD_EXCLAMATION_MARK 0xCFU +#define KEY_KEYPAD_MEMORY_STORE 0xD0U +#define KEY_KEYPAD_MEMORY_RECALL 0xD1U +#define KEY_KEYPAD_MEMORY_CLEAR 0xD2U +#define KEY_KEYPAD_MEMORY_ADD 0xD3U +#define KEY_KEYPAD_MEMORY_SUBTRACT 0xD4U +#define KEY_KEYPAD_MEMORY_MULTIPLY 0xD5U +#define KEY_KEYPAD_MEMORY_DIVIDE 0xD6U +#define KEY_KEYPAD_PLUSMINUS 0xD7U +#define KEY_KEYPAD_CLEAR 0xD8U +#define KEY_KEYPAD_CLEAR_ENTRY 0xD9U +#define KEY_KEYPAD_BINARY 0xDAU +#define KEY_KEYPAD_OCTAL 0xDBU +#define KEY_KEYPAD_DECIMAL 0xDCU +#define KEY_KEYPAD_HEXADECIMAL 0xDDU +#define KEY_LEFTCONTROL 0xE0U +#define KEY_LEFTSHIFT 0xE1U +#define KEY_LEFTALT 0xE2U +#define KEY_LEFT_GUI 0xE3U +#define KEY_RIGHTCONTROL 0xE4U +#define KEY_RIGHTSHIFT 0xE5U +#define KEY_RIGHTALT 0xE6U +#define KEY_RIGHT_GUI 0xE7U + +#define KBR_MAX_NBR_PRESSED 6U + +typedef struct +{ + uint8_t state; + uint8_t lctrl; + uint8_t lshift; + uint8_t lalt; + uint8_t lgui; + uint8_t rctrl; + uint8_t rshift; + uint8_t ralt; + uint8_t rgui; + uint8_t keys[6]; +} hid_keybd_info; + +/* function declarations */ +/* initialize keyboard */ +void usr_keybrd_init (void); +/* process keyboard data */ +void usr_keybrd_process_data (uint8_t pbuf); +/* initialize the keyboard function */ +usbh_status usbh_hid_keybd_init (usb_core_driver *udev, usbh_host *uhost); +/* get keyboard information */ +hid_keybd_info *usbh_hid_keybd_info_get (usb_core_driver *udev, usbh_host *uhost); +/* get the ascii code of hid */ +uint8_t usbh_hid_ascii_code_get (hid_keybd_info *info); +/* keyboard machine */ +void usbh_hid_keybrd_machine (usb_core_driver *udev, usbh_host *uhost); + +#endif /* __USBH_HID_KEYBD_H */ diff --git a/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/host/class/hid/Include/usbh_hid_mouse.h b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/host/class/hid/Include/usbh_hid_mouse.h new file mode 100644 index 0000000000..83fcb37439 --- /dev/null +++ b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/host/class/hid/Include/usbh_hid_mouse.h @@ -0,0 +1,59 @@ +/*! + \file usbh_hid_mouse.h + \brief header file for the usbh_hid_mouse.c + + \version 2020-07-28, V3.0.0, firmware for GD32F20x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef __USBH_HID_MOUSE_H +#define __USBH_HID_MOUSE_H + +#include "usbh_hid_core.h" + +typedef struct _hid_mouse_info +{ + uint8_t x; + uint8_t y; + uint8_t buttons[3]; +} hid_mouse_info; + +/* function declarations */ +/* initialize mouse */ +void usr_mouse_init (void); +/* process mouse data */ +void usr_mouse_process_data (hid_mouse_info *data); +/* initialize mouse function */ +usbh_status usbh_hid_mouse_init (usb_core_driver *udev, usbh_host *uhost); +/* get mouse information */ +hid_mouse_info *usbh_hid_mouse_info_get (usb_core_driver *udev, usbh_host *uhost); +/* mouse machine */ +void usbh_hid_mouse_machine (usb_core_driver *udev, usbh_host *uhost); + +#endif /* __USBH_HID_MOUSE_H */ diff --git a/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/host/class/hid/Include/usbh_hid_parser.h b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/host/class/hid/Include/usbh_hid_parser.h new file mode 100644 index 0000000000..e77455d91b --- /dev/null +++ b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/host/class/hid/Include/usbh_hid_parser.h @@ -0,0 +1,62 @@ +/*! + \file usbh_hid_core.h + \brief header file for the usbh_hid_core.c + + \version 2020-07-28, V3.0.0, firmware for GD32F20x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + + +#ifndef __USBH_HID_PARSER_H +#define __USBH_HID_PARSER_H + +#include "usbh_hid_core.h" +#include "usbh_hid_usage.h" + +typedef struct +{ + uint8_t *data; + uint32_t size; + uint8_t shift; + uint8_t count; + uint8_t sign; + uint32_t logical_min; /*min value device can return*/ + uint32_t logical_max; /*max value device can return*/ + uint32_t physical_min; /*min vale read can report*/ + uint32_t physical_max; /*max value read can report*/ + uint32_t resolution; +} hid_report_item; + +/* function declarations */ +/* read a hid report item */ +uint32_t hid_item_read (hid_report_item *ri, uint8_t ndx); +/* write a hid report item */ +uint32_t hid_item_write (hid_report_item *ri, uint32_t value, uint8_t ndx); + +#endif /* __USBH_HID_PARSER_H */ diff --git a/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/host/class/hid/Include/usbh_hid_usage.h b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/host/class/hid/Include/usbh_hid_usage.h new file mode 100644 index 0000000000..bca1fdf77c --- /dev/null +++ b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/host/class/hid/Include/usbh_hid_usage.h @@ -0,0 +1,141 @@ +/*! + \file usbh_hid_core.h + \brief header file for the usbh_hid_core.c + + \version 2020-07-28, V3.0.0, firmware for GD32F20x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef __USDH_HID_USAGE_H +#define __USDH_HID_USAGE_H + +/* HID 1.11 usage pages */ +#define HID_USAGE_PAGE_UNDEFINED uint16_t (0x00) /* Undefined */ + +/* top level pages */ +#define HID_USAGE_PAGE_GEN_DES uint16_t (0x01) /* Generic Desktop Controls*/ +#define HID_USAGE_PAGE_SIM_CTR uint16_t (0x02) /* Simulation Controls */ +#define HID_USAGE_PAGE_VR_CTR uint16_t (0x03) /* VR Controls */ +#define HID_USAGE_PAGE_SPORT_CTR uint16_t (0x04) /* Sport Controls */ +#define HID_USAGE_PAGE_GAME_CTR uint16_t (0x05) /* Game Controls */ +#define HID_USAGE_PAGE_GEN_DEV uint16_t (0x06) /* Generic Device Controls */ +#define HID_USAGE_PAGE_KEYB uint16_t (0x07) /* Keyboard/Keypad */ +#define HID_USAGE_PAGE_LED uint16_t (0x08) /* LEDs */ +#define HID_USAGE_PAGE_BUTTON uint16_t (0x09) /* Button */ +#define HID_USAGE_PAGE_ORDINAL uint16_t (0x0A) /* Ordinal */ +#define HID_USAGE_PAGE_PHONE uint16_t (0x0B) /* Telephony */ +#define HID_USAGE_PAGE_CONSUMER uint16_t (0x0C) /* Consumer */ +#define HID_USAGE_PAGE_DIGITIZER uint16_t (0x0D) /* Digitizer*/ +#define HID_USAGE_PAGE_PID uint16_t (0x0F) /* PID Page (force feedback and related devices) */ +#define HID_USAGE_PAGE_UNICODE uint16_t (0x10) /* Unicode */ +#define HID_USAGE_PAGE_ALNUM_DISP uint16_t (0x14) /* Alphanumeric Display */ +/* end of top level pages */ + +#define HID_USAGE_PAGE_MEDICAL uint16_t (0x40) /* Medical Instruments */ + +/* 80-83 Monitor pages USB Device Class Definition for Monitor Devices */ +/* 84-87 Power pages USB Device Class Definition for Power Devices */ +#define HID_USAGE_PAGE_BARCODE uint16_t (0x8C) /* Bar Code Scanner page */ +#define HID_USAGE_PAGE_SCALE uint16_t (0x8D) /* Scale page */ +#define HID_USAGE_PAGE_MSR uint16_t (0x8E) /* Magnetic Stripe Reading (MSR) Devices */ +#define HID_USAGE_PAGE_POS uint16_t (0x8F) /* Reserved Point of Sale pages */ +#define HID_USAGE_PAGE_CAMERA_CTR uint16_t (0x90) /* Camera Control Page */ +#define HID_USAGE_PAGE_ARCADE uint16_t (0x91) /* Arcade Page */ + +/* usage definitions for the "generic desktop" page */ +#define HID_USAGE_UNDEFINED uint16_t (0x00) /* Undefined */ +#define HID_USAGE_POINTER uint16_t (0x01) /* Pointer (Physical Collection) */ +#define HID_USAGE_MOUSE uint16_t (0x02) /* Mouse (Application Collection) */ +#define HID_USAGE_JOYSTICK uint16_t (0x04) /* Joystick (Application Collection) */ +#define HID_USAGE_GAMEPAD uint16_t (0x05) /* Game Pad (Application Collection) */ +#define HID_USAGE_KBD uint16_t (0x06) /* Keyboard (Application Collection) */ +#define HID_USAGE_KEYPAD uint16_t (0x07) /* Keypad (Application Collection) */ +#define HID_USAGE_MAX_CTR uint16_t (0x08) /* Multi-axis Controller (Application Collection) */ +#define HID_USAGE_X uint16_t (0x30) /* X (Dynamic Value) */ +#define HID_USAGE_Y uint16_t (0x31) /* Y (Dynamic Value) */ +#define HID_USAGE_Z uint16_t (0x32) /* Z (Dynamic Value) */ +#define HID_USAGE_RX uint16_t (0x33) /* Rx (Dynamic Value) */ +#define HID_USAGE_RY uint16_t (0x34) /* Ry (Dynamic Value) */ +#define HID_USAGE_RZ uint16_t (0x35) /* Rz (Dynamic Value) */ +#define HID_USAGE_SLIDER uint16_t (0x36) /* Slider (Dynamic Value) */ +#define HID_USAGE_DIAL uint16_t (0x37) /* Dial (Dynamic Value) */ +#define HID_USAGE_WHEEL uint16_t (0x38) /* Wheel (Dynamic Value) */ +#define HID_USAGE_HATSW uint16_t (0x39) /* Hat switch (Dynamic Value) */ +#define HID_USAGE_COUNTEDBUF uint16_t (0x3A) /* Counted Buffer (Logical Collection) */ +#define HID_USAGE_BYTECOUNT uint16_t (0x3B) /* Byte Count (Dynamic Value) */ +#define HID_USAGE_MOTIONWAKE uint16_t (0x3C) /* Motion Wakeup (One Shot Control) */ +#define HID_USAGE_START uint16_t (0x3D) /* Start (On/Off Control) */ +#define HID_USAGE_SELECT uint16_t (0x3E) /* Select (On/Off Control) */ +#define HID_USAGE_VX uint16_t (0x40) /* Vx (Dynamic Value) */ +#define HID_USAGE_VY uint16_t (0x41) /* Vy (Dynamic Value) */ +#define HID_USAGE_VZ uint16_t (0x42) /* Vz (Dynamic Value) */ +#define HID_USAGE_VBRX uint16_t (0x43) /* Vbrx (Dynamic Value) */ +#define HID_USAGE_VBRY uint16_t (0x44) /* Vbry (Dynamic Value) */ +#define HID_USAGE_VBRZ uint16_t (0x45) /* Vbrz (Dynamic Value) */ +#define HID_USAGE_VNO uint16_t (0x46) /* Vno (Dynamic Value) */ +#define HID_USAGE_FEATNOTIF uint16_t (0x47) /* Feature Notification (Dynamic Value),(Dynamic Flag) */ +#define HID_USAGE_SYSCTL uint16_t (0x80) /* System Control (Application Collection) */ +#define HID_USAGE_PWDOWN uint16_t (0x81) /* System Power Down (One Shot Control) */ +#define HID_USAGE_SLEEP uint16_t (0x82) /* System Sleep (One Shot Control) */ +#define HID_USAGE_WAKEUP uint16_t (0x83) /* System Wake Up (One Shot Control) */ +#define HID_USAGE_CONTEXTM uint16_t (0x84) /* System Context Menu (One Shot Control) */ +#define HID_USAGE_MAINM uint16_t (0x85) /* System Main Menu (One Shot Control) */ +#define HID_USAGE_APPM uint16_t (0x86) /* System App Menu (One Shot Control) */ +#define HID_USAGE_MENUHELP uint16_t (0x87) /* System Menu Help (One Shot Control) */ +#define HID_USAGE_MENUEXIT uint16_t (0x88) /* System Menu Exit (One Shot Control) */ +#define HID_USAGE_MENUSELECT uint16_t (0x89) /* System Menu Select (One Shot Control) */ +#define HID_USAGE_SYSM_RIGHT uint16_t (0x8A) /* System Menu Right (Re-Trigger Control) */ +#define HID_USAGE_SYSM_LEFT uint16_t (0x8B) /* System Menu Left (Re-Trigger Control) */ +#define HID_USAGE_SYSM_UP uint16_t (0x8C) /* System Menu Up (Re-Trigger Control) */ +#define HID_USAGE_SYSM_DOWN uint16_t (0x8D) /* System Menu Down (Re-Trigger Control) */ +#define HID_USAGE_COLDRESET uint16_t (0x8E) /* System Cold Restart (One Shot Control) */ +#define HID_USAGE_WARMRESET uint16_t (0x8F) /* System Warm Restart (One Shot Control) */ +#define HID_USAGE_DUP uint16_t (0x90) /* D-pad Up (On/Off Control) */ +#define HID_USAGE_DDOWN uint16_t (0x91) /* D-pad Down (On/Off Control) */ +#define HID_USAGE_DRIGHT uint16_t (0x92) /* D-pad Right (On/Off Control) */ +#define HID_USAGE_DLEFT uint16_t (0x93) /* D-pad Left (On/Off Control) */ +#define HID_USAGE_SYS_DOCK uint16_t (0xA0) /* System Dock (One Shot Control) */ +#define HID_USAGE_SYS_UNDOCK uint16_t (0xA1) /* System Undock (One Shot Control) */ +#define HID_USAGE_SYS_SETUP uint16_t (0xA2) /* System Setup (One Shot Control) */ +#define HID_USAGE_SYS_BREAK uint16_t (0xA3) /* System Break (One Shot Control) */ +#define HID_USAGE_SYS_DBGBRK uint16_t (0xA4) /* System Debugger Break (One Shot Control) */ +#define HID_USAGE_APP_BRK uint16_t (0xA5) /* Application Break (One Shot Control) */ +#define HID_USAGE_APP_DBGBRK uint16_t (0xA6) /* Application Debugger Break (One Shot Control) */ +#define HID_USAGE_SYS_SPKMUTE uint16_t (0xA7) /* System Speaker Mute (One Shot Control) */ +#define HID_USAGE_SYS_HIBERN uint16_t (0xA8) /* System Hibernate (One Shot Control) */ +#define HID_USAGE_SYS_SIDPINV uint16_t (0xB0) /* System Display Invert (One Shot Control) */ +#define HID_USAGE_SYS_DISPINT uint16_t (0xB1) /* System Display Internal (One Shot Control) */ +#define HID_USAGE_SYS_DISPEXT uint16_t (0xB2) /* System Display External (One Shot Control) */ +#define HID_USAGE_SYS_DISPBOTH uint16_t (0xB3) /* System Display Both (One Shot Control) */ +#define HID_USAGE_SYS_DISPDUAL uint16_t (0xB4) /* System Display Dual (One Shot Control) */ +#define HID_USAGE_SYS_DISPTGLIE uint16_t (0xB5) /* System Display Toggle Int/Ext (One Shot Control) */ +#define HID_USAGE_SYS_DISP_SWAP uint16_t (0xB6) /* System Display Swap Primary/Secondary (One Shot Control) */ +#define HID_USAGE_SYS_DIPS_LCDA uint16_t (0xB7) /* System Display LCD Autoscale (One Shot Control) */ + +#endif /* __USDH_HID_USAGE_H */ diff --git a/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/host/class/hid/Source/usbh_hid_core.c b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/host/class/hid/Source/usbh_hid_core.c new file mode 100644 index 0000000000..2c04da12ab --- /dev/null +++ b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/host/class/hid/Source/usbh_hid_core.c @@ -0,0 +1,676 @@ +/*! + \file usbh_hid_core.c + \brief USB host HID class driver + + \version 2020-07-28, V3.0.0, firmware for GD32F20x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "usbh_pipe.h" +#include "usbh_hid_core.h" +#include "usbh_hid_mouse.h" +#include "usbh_hid_keybd.h" +#include +#include + +/* local function prototypes ('static') */ +static void usbh_hiddesc_parse (usb_desc_hid *hid_desc, uint8_t *buf); +static void usbh_hid_itf_deinit (usbh_host *uhost); +static usbh_status usbh_hid_itf_init (usbh_host *uhost); +static usbh_status usbh_hid_class_req (usbh_host *uhost); +static usbh_status usbh_hid_handle (usbh_host *uhost); +static usbh_status usbh_hid_reportdesc_get (usbh_host *uhost, uint16_t len); +static usbh_status usbh_hid_sof(usbh_host *uhost); +static usbh_status usbh_hid_desc_get (usbh_host *uhost, uint16_t len); +static usbh_status usbh_set_idle (usbh_host *uhost, uint8_t duration, uint8_t report_ID); +static usbh_status usbh_set_protocol (usbh_host *uhost, uint8_t protocol); + +usbh_class usbh_hid = +{ + USB_HID_CLASS, + usbh_hid_itf_init, + usbh_hid_itf_deinit, + usbh_hid_class_req, + usbh_hid_handle, + usbh_hid_sof +}; + +/*! + \brief get report + \param[in] uhost: pointer to usb host + \param[in] report_type: duration for HID set idle request + \param[in] report_ID: targeted report ID for HID set idle request + \param[in] report_len: length of data report to be send + \param[in] report_buf: report buffer + \param[out] none + \retval operation status +*/ +usbh_status usbh_get_report (usbh_host *uhost, + uint8_t report_type, + uint8_t report_ID, + uint8_t report_len, + uint8_t *report_buf) +{ + usbh_status status = USBH_BUSY; + + if (CTL_IDLE == uhost->control.ctl_state) { + uhost->control.setup.req = (usb_req) { + .bmRequestType = USB_TRX_IN | USB_RECPTYPE_ITF | USB_REQTYPE_CLASS, + .bRequest = GET_REPORT, + .wValue = (report_type << 8U) | report_ID, + .wIndex = 0U, + .wLength = report_len + }; + + usbh_ctlstate_config (uhost, report_buf, report_len); + } + + status = usbh_ctl_handler (uhost); + + return status; +} + +/*! + \brief set report + \param[in] udev: pointer to usb core instance + \param[in] uhost: pointer to usb host + \param[in] report_type: duration for HID set idle request + \param[in] report_ID: targeted report ID for HID set idle request + \param[in] report_len: length of data report to be send + \param[in] report_buf: report buffer + \param[out] none + \retval operation status +*/ +usbh_status usbh_set_report (usb_core_driver *udev, + usbh_host *uhost, + uint8_t report_type, + uint8_t report_ID, + uint8_t report_len, + uint8_t *report_buf) +{ + usbh_status status = USBH_BUSY; + + if (CTL_IDLE == uhost->control.ctl_state) { + uhost->control.setup.req = (usb_req) { + .bmRequestType = USB_TRX_OUT | USB_RECPTYPE_ITF | USB_REQTYPE_CLASS, + .bRequest = SET_REPORT, + .wValue = (report_type << 8U) | report_ID, + .wIndex = 0U, + .wLength = report_len + }; + + usbh_ctlstate_config (uhost, report_buf, report_len); + } + + status = usbh_ctl_handler (uhost); + + return status; +} + +/*! + \brief de-initialize the host pipes used for the HID class + \param[in] uhost: pointer to usb host + \param[out] none + \retval operation status +*/ +void usbh_hid_itf_deinit (usbh_host *uhost) +{ + usbh_hid_handler *hid = (usbh_hid_handler *)uhost->active_class->class_data; + + if (0x00U != hid->pipe_in) { + usb_pipe_halt (uhost->data, hid->pipe_in); + + usbh_pipe_free (uhost->data, hid->pipe_in); + + hid->pipe_in = 0U; /* reset the pipe as free */ + } + + if (0x00U != hid->pipe_out) { + usb_pipe_halt (uhost->data, hid->pipe_out); + + usbh_pipe_free (uhost->data, hid->pipe_out); + + hid->pipe_out = 0U; /* reset the channel as free */ + } +} + +/*! + \brief return device type + \param[in] udev: pointer to usb core instance + \param[in] uhost: pointer to usb host + \param[out] none + \retval hid_type +*/ +hid_type usbh_hid_device_type_get(usb_core_driver *udev, usbh_host *uhost) +{ + hid_type type = HID_UNKNOWN; + uint8_t interface_protocol; + + if (HOST_CLASS_HANDLER == uhost->cur_state) { + interface_protocol = uhost->dev_prop.cfg_desc_set.itf_desc_set[uhost->dev_prop.cur_itf][0].itf_desc.bInterfaceProtocol; + + if (USB_HID_PROTOCOL_KEYBOARD == interface_protocol) { + type = HID_KEYBOARD; + } else { + if (USB_HID_PROTOCOL_MOUSE == interface_protocol) { + type = HID_MOUSE; + } + } + } + + return type; +} + +/*! + \brief return HID device poll time + \param[in] udev: pointer to usb core instance + \param[in] uhost: pointer to usb host + \param[out] none + \retval poll time (ms) +*/ +uint8_t usbh_hid_poll_interval_get (usb_core_driver *udev, usbh_host *uhost) +{ + usbh_hid_handler *hid = (usbh_hid_handler *)uhost->active_class->class_data; + + if ((HOST_CLASS_ENUM == uhost->cur_state) || + (HOST_USER_INPUT == uhost->cur_state) || + (HOST_CHECK_CLASS == uhost->cur_state) || + (HOST_CLASS_HANDLER == uhost->cur_state)) { + return (uint8_t)(hid->poll); + } else { + return 0U; + } +} + +/*! + \brief read from FIFO + \param[in] fifo: fifo address + \param[in] buf: read buffer + \param[in] nbytes: number of item to read + \param[out] none + \retval number of read items +*/ +uint16_t usbh_hid_fifo_read (data_fifo *fifo, void *buf, uint16_t nbytes) +{ + uint16_t i = 0U; + uint8_t *p = (uint8_t*) buf; + + if (0U == fifo->lock) { + fifo->lock = 1U; + + for (i = 0U; i < nbytes; i++) { + if (fifo->tail != fifo->head) { + *p++ = fifo->buf[fifo->tail]; + fifo->tail++; + + if (fifo->tail == fifo->size) { + fifo->tail = 0U; + } + } else { + fifo->lock = 0U; + + return i; + } + } + } + + fifo->lock = 0U; + + return nbytes; +} + +/*! + \brief write to FIFO + \param[in] fifo: fifo address + \param[in] buf: read buffer + \param[in] nbytes: number of item to read + \param[out] none + \retval number of write items +*/ +uint16_t usbh_hid_fifo_write (data_fifo *fifo, void *buf, uint16_t nbytes) +{ + uint16_t i = 0U; + uint8_t *p = (uint8_t*) buf; + + if (0U == fifo->lock) { + fifo->lock = 1U; + + for (i = 0U; i < nbytes; i++) { + if ((fifo->head + 1U == fifo->tail) || + ((fifo->head + 1U == fifo->size) && (0U == fifo->tail))) { + fifo->lock = 0U; + + return i; + } else { + fifo->buf[fifo->head] = *p++; + fifo->head++; + + if (fifo->head == fifo->size) { + fifo->head = 0U; + } + } + } + } + + fifo->lock = 0U; + + return nbytes; +} + +/*! + \brief initialize FIFO + \param[in] fifo: fifo address + \param[in] buf: read buffer + \param[in] size: size of FIFO + \param[out] none + \retval none +*/ +void usbh_hid_fifo_init (data_fifo *fifo, uint8_t *buf, uint16_t size) +{ + fifo->head = 0U; + fifo->tail = 0U; + fifo->lock = 0U; + fifo->size = size; + fifo->buf = buf; +} + +/*! + \brief initialize the hid class + \param[in] uhost: pointer to usb host + \param[out] none + \retval operation status +*/ +static usbh_status usbh_hid_itf_init (usbh_host *uhost) +{ + uint8_t num = 0U, ep_num = 0U, interface = 0U; + usbh_status status = USBH_BUSY; + + interface = usbh_interface_find(&uhost->dev_prop, USB_HID_CLASS, USB_HID_SUBCLASS_BOOT_ITF, 0xFFU); + + if (0xFFU == interface) { + uhost->usr_cb->dev_not_supported(); + + status = USBH_FAIL; + } else { + usbh_interface_select(&uhost->dev_prop, interface); + + static usbh_hid_handler hid_handler; + + memset((void*)&hid_handler, 0, sizeof(usbh_hid_handler)); + + hid_handler.state = HID_ERROR; + + uint8_t itf_protocol = uhost->dev_prop.cfg_desc_set.itf_desc_set[uhost->dev_prop.cur_itf][0].itf_desc.bInterfaceProtocol; + if (USB_HID_PROTOCOL_KEYBOARD == itf_protocol) { + hid_handler.init = usbh_hid_keybd_init; + hid_handler.machine = usbh_hid_keybrd_machine; + } else if (USB_HID_PROTOCOL_MOUSE == itf_protocol) { + hid_handler.init = usbh_hid_mouse_init; + hid_handler.machine = usbh_hid_mouse_machine; + } else { + status = USBH_FAIL; + } + + hid_handler.state = HID_INIT; + hid_handler.ctl_state = HID_REQ_INIT; + hid_handler.ep_addr = uhost->dev_prop.cfg_desc_set.itf_desc_set[uhost->dev_prop.cur_itf][0].ep_desc[0].bEndpointAddress; + hid_handler.len = uhost->dev_prop.cfg_desc_set.itf_desc_set[uhost->dev_prop.cur_itf][0].ep_desc[0].wMaxPacketSize; + hid_handler.poll = uhost->dev_prop.cfg_desc_set.itf_desc_set[uhost->dev_prop.cur_itf][0].ep_desc[0].bInterval; + + if (hid_handler.poll < HID_MIN_POLL) { + hid_handler.poll = HID_MIN_POLL; + } + + /* check for available number of endpoints */ + /* find the number of endpoints in the interface descriptor */ + /* choose the lower number in order not to overrun the buffer allocated */ + ep_num = USB_MIN(uhost->dev_prop.cfg_desc_set.itf_desc_set[uhost->dev_prop.cur_itf][0].itf_desc.bNumEndpoints, USBH_MAX_EP_NUM); + + /* decode endpoint IN and OUT address from interface descriptor */ + for (num = 0U; num < ep_num; num++) { + usb_desc_ep *ep_desc = &uhost->dev_prop.cfg_desc_set.itf_desc_set[uhost->dev_prop.cur_itf][0].ep_desc[num]; + + uint8_t ep_addr = ep_desc->bEndpointAddress; + + if (ep_addr & 0x80U) { + hid_handler.ep_in = ep_addr; + hid_handler.pipe_in = usbh_pipe_allocate (uhost->data, ep_addr); + + /* open channel for IN endpoint */ + usbh_pipe_create (uhost->data, + &uhost->dev_prop, + hid_handler.pipe_in, + USB_EPTYPE_INTR, + hid_handler.len); + + usbh_pipe_toggle_set(uhost->data, hid_handler.pipe_in, 0U); + } else { + hid_handler.ep_out = ep_addr; + hid_handler.pipe_out = usbh_pipe_allocate (uhost->data, ep_addr); + + /* open channel for OUT endpoint */ + usbh_pipe_create (uhost->data, + &uhost->dev_prop, + hid_handler.pipe_out, + USB_EPTYPE_INTR, + hid_handler.len); + + usbh_pipe_toggle_set(uhost->data, hid_handler.pipe_out, 0U); + } + } + + uhost->active_class->class_data = (void *)&hid_handler; + + status = USBH_OK; + } + + return status; +} + +/*! + \brief handle HID class requests for HID class + \param[in] uhost: pointer to usb host + \param[out] none + \retval operation status +*/ +static usbh_status usbh_hid_class_req (usbh_host *uhost) +{ + usbh_status status = USBH_BUSY; + usbh_status class_req_status = USBH_BUSY; + + usbh_hid_handler *hid = (usbh_hid_handler *)uhost->active_class->class_data; + + /* handle HID control state machine */ + switch (hid->ctl_state) { + case HID_REQ_INIT: + case HID_REQ_GET_HID_DESC: + /* get HID descriptor */ + if (USBH_OK == usbh_hid_desc_get (uhost, USB_HID_DESC_SIZE)) { + usbh_hiddesc_parse(&hid->hid_desc, uhost->dev_prop.data); + + hid->ctl_state = HID_REQ_GET_REPORT_DESC; + } + break; + + case HID_REQ_GET_REPORT_DESC: + /* get report descriptor */ + if (USBH_OK == usbh_hid_reportdesc_get(uhost, hid->hid_desc.wDescriptorLength)) { + hid->ctl_state = HID_REQ_SET_IDLE; + } + break; + + case HID_REQ_SET_IDLE: + class_req_status = usbh_set_idle (uhost, 0U, 0U); + + /* set idle */ + if (USBH_OK == class_req_status) { + hid->ctl_state = HID_REQ_SET_PROTOCOL; + } else { + if(USBH_NOT_SUPPORTED == class_req_status) { + hid->ctl_state = HID_REQ_SET_PROTOCOL; + } + } + break; + + case HID_REQ_SET_PROTOCOL: + /* set protocol */ + if (USBH_OK == usbh_set_protocol (uhost, 0U)) { + hid->ctl_state = HID_REQ_IDLE; + + /* all requests performed */ + status = USBH_OK; + } + break; + + case HID_REQ_IDLE: + default: + break; + } + + return status; +} + +/*! + \brief manage state machine for HID data transfers + \param[in] uhost: pointer to usb host + \param[out] none + \retval operation status +*/ +static usbh_status usbh_hid_handle (usbh_host *uhost) +{ + usbh_status status = USBH_OK; + usbh_hid_handler *hid = (usbh_hid_handler *)uhost->active_class->class_data; + + switch (hid->state) { + case HID_INIT: + hid->init(uhost->data, uhost); + hid->state = HID_IDLE; + break; + + case HID_IDLE: + hid->state = HID_SYNC; + status = USBH_OK; + break; + + case HID_SYNC: + /* sync with start of even frame */ + if (true == usb_frame_even(uhost->data)) { + hid->state = HID_GET_DATA; + } + break; + + case HID_GET_DATA: + usbh_data_recev (uhost->data, hid->pdata, hid->pipe_in, hid->len); + + hid->state = HID_POLL; + hid->timer = usb_curframe_get (uhost->data); + hid->data_ready = 0U; + break; + + case HID_POLL: + if (URB_DONE == usbh_urbstate_get (uhost->data, hid->pipe_in)) { + if (0U == hid->data_ready) { /* handle data once */ + usbh_hid_fifo_write(&hid->fifo, hid->pdata, hid->len); + hid->data_ready = 1U; + + hid->machine(uhost->data, uhost); + } + } else { + if (URB_STALL == usbh_urbstate_get (uhost->data, hid->pipe_in)) { /* IN endpoint stalled */ + /* issue clear feature on interrupt in endpoint */ + if (USBH_OK == (usbh_clrfeature (uhost, hid->ep_addr, hid->pipe_in))) { + /* change state to issue next in token */ + hid->state = HID_GET_DATA; + } + } + } + break; + + default: + break; + } + return status; +} + +/*! + \brief send get report descriptor command to the device + \param[in] uhost: pointer to usb host + \param[in] len: HID report descriptor length + \param[out] none + \retval operation status +*/ +static usbh_status usbh_hid_reportdesc_get (usbh_host *uhost, uint16_t len) +{ + usbh_status status = USBH_BUSY; + + if (CTL_IDLE == uhost->control.ctl_state) { + uhost->control.setup.req = (usb_req) { + .bmRequestType = USB_TRX_IN | USB_RECPTYPE_ITF | USB_REQTYPE_STRD, + .bRequest = USB_GET_DESCRIPTOR, + .wValue = USBH_DESC(USB_DESCTYPE_REPORT), + .wIndex = 0U, + .wLength = len + }; + + usbh_ctlstate_config (uhost, uhost->dev_prop.data, len); + } + + status = usbh_ctl_handler (uhost); + + return status; +} + +/*! + \brief managing the SOF process + \param[in] uhost: pointer to usb host + \param[out] none + \retval operation status +*/ +static usbh_status usbh_hid_sof(usbh_host *uhost) +{ + usbh_hid_handler *hid = (usbh_hid_handler *)uhost->active_class->class_data; + + if (HID_POLL == hid->state) { + uint32_t frame_count = usb_curframe_get (uhost->data); + + if ((frame_count > hid->timer) && ((frame_count - hid->timer) >= hid->poll)) { + hid->state = HID_GET_DATA; + } else if ((frame_count < hid->timer) && ((frame_count + 0x3FFFU - hid->timer) >= hid->poll)) { + hid->state = HID_GET_DATA; + } else { + /* no operation */ + } + } + + return USBH_OK; +} + +/*! + \brief send the command of get HID descriptor to the device + \param[in] uhost: pointer to usb host + \param[in] len: HID descriptor length + \param[out] none + \retval operation status +*/ +static usbh_status usbh_hid_desc_get (usbh_host *uhost, uint16_t len) +{ + usbh_status status = USBH_BUSY; + + if (CTL_IDLE == uhost->control.ctl_state) { + uhost->control.setup.req = (usb_req) { + .bmRequestType = USB_TRX_IN | USB_RECPTYPE_ITF | USB_REQTYPE_STRD, + .bRequest = USB_GET_DESCRIPTOR, + .wValue = USBH_DESC(USB_DESCTYPE_HID), + .wIndex = 0U, + .wLength = len + }; + + usbh_ctlstate_config (uhost, uhost->dev_prop.data, len); + } + + status = usbh_ctl_handler (uhost); + + return status; +} + +/*! + \brief set idle state + \param[in] uhost: pointer to usb host + \param[in] duration: duration for HID set idle request + \param[in] report_ID: targetted report ID for HID set idle request + \param[out] none + \retval operation status +*/ +static usbh_status usbh_set_idle (usbh_host *uhost, uint8_t duration, uint8_t report_ID) +{ + usbh_status status = USBH_BUSY; + + if (CTL_IDLE == uhost->control.ctl_state) { + uhost->control.setup.req = (usb_req) { + .bmRequestType = USB_TRX_OUT | USB_RECPTYPE_ITF | USB_REQTYPE_CLASS, + .bRequest = SET_IDLE, + .wValue = (duration << 8U) | report_ID, + .wIndex = 0U, + .wLength = 0U + }; + + usbh_ctlstate_config (uhost, NULL, 0U); + } + + status = usbh_ctl_handler (uhost); + + return status; +} + +/*! + \brief set protocol state + \param[in] uhost: pointer to usb host + \param[in] protocol: boot/report protocol + \param[out] none + \retval operation status +*/ +static usbh_status usbh_set_protocol (usbh_host *uhost, uint8_t protocol) +{ + usbh_status status = USBH_BUSY; + + if (CTL_IDLE == uhost->control.ctl_state) { + uhost->control.setup.req = (usb_req) { + .bmRequestType = USB_TRX_OUT | USB_RECPTYPE_ITF | USB_REQTYPE_CLASS, + .bRequest = SET_PROTOCOL, + .wValue = !protocol, + .wIndex = 0U, + .wLength = 0U + }; + + usbh_ctlstate_config (uhost, NULL, 0U); + } + + status = usbh_ctl_handler (uhost); + + return status; +} + +/*! + \brief parse the HID descriptor + \param[in] hid_desc: pointer to HID descriptor + \param[in] buf: pointer to buffer where the source descriptor is available + \param[out] none + \retval none +*/ +static void usbh_hiddesc_parse (usb_desc_hid *hid_desc, uint8_t *buf) +{ + hid_desc->header.bLength = *(uint8_t *)(buf + 0U); + hid_desc->header.bDescriptorType = *(uint8_t *)(buf + 1U); + hid_desc->bcdHID = BYTE_SWAP(buf + 2U); + hid_desc->bCountryCode = *(uint8_t *)(buf + 4U); + hid_desc->bNumDescriptors = *(uint8_t *)(buf + 5U); + hid_desc->bDescriptorType = *(uint8_t *)(buf + 6U); + hid_desc->wDescriptorLength = BYTE_SWAP(buf + 7U); +} + diff --git a/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/host/class/hid/Source/usbh_hid_keybd.c b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/host/class/hid/Source/usbh_hid_keybd.c new file mode 100644 index 0000000000..645bad1f63 --- /dev/null +++ b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/host/class/hid/Source/usbh_hid_keybd.c @@ -0,0 +1,399 @@ +/*! + \file usbh_hid_keybd.c + \brief USB host HID keyboard driver + + \version 2020-07-28, V3.0.0, firmware for GD32F20x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "usbh_hid_keybd.h" +#include "usbh_hid_parser.h" +#include + +hid_keybd_info keybd_info; + +uint32_t keybd_report_data[2]; + +static const hid_report_item imp_0_lctrl = +{ + (uint8_t*)(void *)keybd_report_data + 0, /* data */ + 1, /* size */ + 0, /* shift */ + 0, /* count (only for array items) */ + 0, /* signed */ + 0, /* min value read can return */ + 1, /* max value read can return */ + 0, /* min vale device can report */ + 1, /* max value device can report */ + 1 /* resolution */ +}; + +static const hid_report_item imp_0_lshift = +{ + (uint8_t*)(void *)keybd_report_data + 0, /* data */ + 1, /* size */ + 1, /* shift */ + 0, /* count (only for array items) */ + 0, /* signed */ + 0, /* min value read can return */ + 1, /* max value read can return */ + 0, /* min vale device can report */ + 1, /* max value device can report */ + 1 /* resolution */ +}; + +static const hid_report_item imp_0_lalt = +{ + (uint8_t*)(void *)keybd_report_data + 0, /* data */ + 1, /* size */ + 2, /* shift */ + 0, /* count (only for array items) */ + 0, /* signed */ + 0, /* min value read can return */ + 1, /* max value read can return */ + 0, /* min vale device can report */ + 1, /* max value device can report */ + 1 /* resolution */ +}; + +static const hid_report_item imp_0_lgui = +{ + (uint8_t*)(void *)keybd_report_data + 0, /* data */ + 1, /* size */ + 3, /* shift */ + 0, /* count (only for array items) */ + 0, /* signed */ + 0, /* min value read can return */ + 1, /* max value read can return */ + 0, /* min vale device can report */ + 1, /* max value device can report */ + 1 /* resolution */ +}; + +static const hid_report_item imp_0_rctrl = +{ + (uint8_t*)(void *)keybd_report_data + 0, /* data */ + 1, /* size */ + 4, /* shift */ + 0, /* count (only for array items) */ + 0, /* signed */ + 0, /* min value read can return */ + 1, /* max value read can return */ + 0, /* min vale device can report */ + 1, /* max value device can report */ + 1 /* resolution */ +}; + +static const hid_report_item imp_0_rshift = +{ + (uint8_t*)(void *)keybd_report_data + 0, /* data */ + 1, /* size */ + 5, /* shift */ + 0, /* count (only for array items) */ + 0, /* signed */ + 0, /* min value read can return */ + 1, /* max value read can return */ + 0, /* min vale device can report */ + 1, /* max value device can report */ + 1 /* resolution */ +}; + +static const hid_report_item imp_0_ralt = +{ + (uint8_t*)(void *)keybd_report_data + 0, /* data */ + 1, /* size */ + 6, /* shift */ + 0, /* count (only for array items) */ + 0, /* signed */ + 0, /* min value read can return */ + 1, /* max value read can return */ + 0, /* min vale device can report */ + 1, /* max value device can report */ + 1 /* resolution */ +}; + +static const hid_report_item imp_0_rgui = +{ + (uint8_t*)(void *)keybd_report_data + 0, /* data */ + 1, /* size */ + 7, /* shift */ + 0, /* count (only for array items) */ + 0, /* signed */ + 0, /* min value read can return */ + 1, /* max value read can return */ + 0, /* min vale device can report */ + 1, /* max value device can report */ + 1 /* resolution */ +}; + +static const hid_report_item imp_0_key_array = +{ + (uint8_t*)(void *)keybd_report_data + 2, /* data */ + 8, /* size */ + 0, /* shift */ + 6, /* count (only for array items) */ + 0, /* signed */ + 0, /* min value read can return */ + 101, /* max value read can return */ + 0, /* min vale device can report */ + 101, /* max value device can report */ + 1 /* resolution */ +}; + +/* local constants */ +static const uint8_t hid_keybrd_codes[] = +{ + 0, 0, 0, 0, 31, 50, 48, 33, + 19, 34, 35, 36, 24, 37, 38, 39, /* 0x00 - 0x0F */ + 52, 51, 25, 26, 17, 20, 32, 21, + 23, 49, 18, 47, 22, 46, 2, 3, /* 0x10 - 0x1F */ + 4, 5, 6, 7, 8, 9, 10, 11, + 43, 110, 15, 16, 61, 12, 13, 27, /* 0x20 - 0x2F */ + 28, 29, 42, 40, 41, 1, 53, 54, + 55, 30, 112, 113, 114, 115, 116, 117, /* 0x30 - 0x3F */ + 118, 119, 120, 121, 122, 123, 124, 125, + 126, 75, 80, 85, 76, 81, 86, 89, /* 0x40 - 0x4F */ + 79, 84, 83, 90, 95, 100, 105, 106, + 108, 93, 98, 103, 92, 97, 102, 91, /* 0x50 - 0x5F */ + 96, 101, 99, 104, 45, 129, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, /* 0x60 - 0x6F */ + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, /* 0x70 - 0x7F */ + 0, 0, 0, 0, 0, 107, 0, 56, + 0, 0, 0, 0, 0, 0, 0, 0, /* 0x80 - 0x8F */ + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, /* 0x90 - 0x9F */ + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, /* 0xA0 - 0xAF */ + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, /* 0xB0 - 0xBF */ + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, /* 0xC0 - 0xCF */ + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, /* 0xD0 - 0xDF */ + 58, 44, 60, 127, 64, 57, 62, 128 /* 0xE0 - 0xE7 */ +}; + +#ifdef QWERTY_KEYBOARD + +static const int8_t hid_keybrd_key[] = +{ + '\0', '`', '1', '2', '3', '4', '5', '6', + '7', '8', '9', '0', '-', '=', '\0', '\r', + '\t', 'q', 'w', 'e', 'r', 't', 'y', 'u', + 'i', 'o', 'p', '[', ']', '\\', + '\0', 'a', 's', 'd', 'f', 'g', 'h', 'j', + 'k', 'l', ';', '\'', '\0', '\n', + '\0', '\0', 'z', 'x', 'c', 'v', 'b', 'n', + 'm', ',', '.', '/', '\0', '\0', + '\0', '\0', '\0', ' ', '\0', '\0', '\0', '\0', + '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', + '\0', '\0', '\0', '\0', '\0', '\r', '\0', '\0', + '\0', '\0', '\0', '\0', '\0', '\0', + '\0', '\0', '7', '4', '1', + '\0', '/', '8', '5', '2', + '0', '*', '9', '6', '3', + '.', '-', '+', '\0', '\n', '\0', '\0', '\0', '\0', '\0', '\0', + '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', + '\0', '\0', '\0', '\0' +}; + +static const int8_t hid_keybrd_shiftkey[] = { + '\0', '~', '!', '@', '#', '$', '%', '^', '&', '*', '(', ')', + '_', '+', '\0', '\0', '\0', 'Q', 'W', 'E', 'R', 'T', 'Y', 'U', + 'I', 'O', 'P', '{', '}', '|', '\0', 'A', 'S', 'D', 'F', 'G', + 'H', 'J', 'K', 'L', ':', '"', '\0', '\n', '\0', '\0', 'Z', 'X', + 'C', 'V', 'B', 'N', 'M', '<', '>', '?', '\0', '\0', '\0', '\0', + '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', + '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', + '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', + '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', + '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', + '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0' +}; + +#else + +static const int8_t hid_keybrd_key[] = { + '\0', '`', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', + '-', '=', '\0', '\r', '\t', 'a', 'z', 'e', 'r', 't', 'y', 'u', + 'i', 'o', 'p', '[', ']', '\\', '\0', 'q', 's', 'd', 'f', 'g', + 'h', 'j', 'k', 'l', 'm', '\0', '\0', '\n', '\0', '\0', 'w', 'x', + 'c', 'v', 'b', 'n', ',', ';', ':', '!', '\0', '\0', '\0', '\0', + '\0', ' ', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', + '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\r', '\0', '\0', '\0', + '\0', '\0', '\0', '\0', '\0', '\0', '\0', '7', '4', '1', '\0', '/', + '8', '5', '2', '0', '*', '9', '6', '3', '.', '-', '+', '\0', + '\n', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', + '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0' +}; + +static const int8_t hid_keybrd_shiftkey[] = { + '\0', '~', '!', '@', '#', '$', '%', '^', '&', '*', '(', ')', '_', + '+', '\0', '\0', '\0', 'A', 'Z', 'E', 'R', 'T', 'Y', 'U', 'I', 'O', + 'P', '{', '}', '*', '\0', 'Q', 'S', 'D', 'F', 'G', 'H', 'J', 'K', + 'L', 'M', '%', '\0', '\n', '\0', '\0', 'W', 'X', 'C', 'V', 'B', 'N', + '?', '.', '/', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', + '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', + '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', + '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', + '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', + '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0' +}; + +#endif + +/* local function prototypes ('static') */ +static usbh_status usbh_hid_keybrd_decode (usb_core_driver *udev, usbh_host *uhost); + +/*! + \brief initialize the keyboard function + \param[in] udev: pointer to usb core instance + \param[in] uhost: pointer to usb host + \param[out] none + \retval operation status +*/ +usbh_status usbh_hid_keybd_init (usb_core_driver *udev, usbh_host *uhost) +{ + usbh_hid_handler *hid = (usbh_hid_handler *)uhost->active_class->class_data; + + keybd_info.lctrl = keybd_info.lshift = 0U; + keybd_info.lalt = keybd_info.lgui = 0U; + keybd_info.rctrl = keybd_info.rshift = 0U; + keybd_info.ralt = keybd_info.rgui = 0U; + + for (uint32_t x = 0U; x < (sizeof(keybd_report_data) / sizeof(uint32_t)); x++) { + keybd_report_data[x] = 0U; + } + + if (hid->len > (sizeof(keybd_report_data) / sizeof(uint32_t))) { + hid->len = (sizeof(keybd_report_data) / sizeof(uint32_t)); + } + + hid->pdata = (uint8_t*)(void *)keybd_report_data; + + usbh_hid_fifo_init (&hid->fifo, uhost->dev_prop.data, HID_QUEUE_SIZE * sizeof(keybd_report_data)); + + /* call user init*/ + usr_keybrd_init(); + + return USBH_OK; +} + +/*! + \brief get keyboard information + \param[in] udev: pointer to USB core instance + \param[in] uhost: pointer to USB host handler + \param[out] none + \retval keyboard information +*/ +hid_keybd_info *usbh_hid_keybd_info_get (usb_core_driver *udev, usbh_host *uhost) +{ + if (USBH_OK == usbh_hid_keybrd_decode(udev, uhost)) { + return &keybd_info; + } else { + return NULL; + } +} + +/*! + \brief get ascii code + \param[in] info: keyboard information + \param[out] none + \retval output +*/ +uint8_t usbh_hid_ascii_code_get (hid_keybd_info *info) +{ + uint8_t output; + if ((1U == info->lshift) || (info->rshift)) { + output = hid_keybrd_shiftkey[hid_keybrd_codes[info->keys[0]]]; + } else { + output = hid_keybrd_key[hid_keybrd_codes[info->keys[0]]]; + } + + return output; +} + +/*! + \brief decode the pressed keys + \param[in] udev: pointer to usb core instance + \param[in] uhost: pointer to usb host + \param[out] none + \retval none +*/ +void usbh_hid_keybrd_machine (usb_core_driver *udev, usbh_host *uhost) +{ + hid_keybd_info *k_pinfo; + + k_pinfo = usbh_hid_keybd_info_get(udev, uhost); + + if (k_pinfo != NULL) { + char c = usbh_hid_ascii_code_get(k_pinfo); + + if (c != 0U) { + usr_keybrd_process_data(c); + } + } +} + +/*! + \brief decode keyboard information + \param[in] udev: pointer to usb core instance + \param[in] uhost: pointer to usb host + \param[out] none + \retval operation status +*/ +static usbh_status usbh_hid_keybrd_decode (usb_core_driver *udev, usbh_host *uhost) +{ + usbh_hid_handler *hid = (usbh_hid_handler *)uhost->active_class->class_data; + + if (hid->len == 0U) { + return USBH_FAIL; + } + + /* fill report */ + if (usbh_hid_fifo_read (&hid->fifo, &keybd_report_data, hid->len) == hid->len) { + keybd_info.lctrl = (uint8_t)hid_item_read((hid_report_item *)&imp_0_lctrl, 0U); + keybd_info.lshift = (uint8_t)hid_item_read((hid_report_item *)&imp_0_lshift, 0U); + keybd_info.lalt = (uint8_t)hid_item_read((hid_report_item *)&imp_0_lalt, 0U); + keybd_info.lgui = (uint8_t)hid_item_read((hid_report_item *)&imp_0_lgui, 0U); + keybd_info.rctrl = (uint8_t)hid_item_read((hid_report_item *)&imp_0_rctrl, 0U); + keybd_info.rshift = (uint8_t)hid_item_read((hid_report_item *)&imp_0_rshift, 0U); + keybd_info.ralt = (uint8_t)hid_item_read((hid_report_item *)&imp_0_ralt, 0U); + keybd_info.rgui = (uint8_t)hid_item_read((hid_report_item *)&imp_0_rgui, 0U); + + for (uint8_t x = 0U; x < sizeof(keybd_info.keys); x++) { + keybd_info.keys[x] = (uint8_t)hid_item_read((hid_report_item *)&imp_0_key_array, x); + } + + return USBH_OK; + } + + return USBH_FAIL; +} diff --git a/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/host/class/hid/Source/usbh_hid_mouse.c b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/host/class/hid/Source/usbh_hid_mouse.c new file mode 100644 index 0000000000..09073ba971 --- /dev/null +++ b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/host/class/hid/Source/usbh_hid_mouse.c @@ -0,0 +1,216 @@ +/*! + \file usbh_hid_mouse.c + \brief USB host HID mouse driver + + \version 2020-07-28, V3.0.0, firmware for GD32F20x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "usbh_hid_mouse.h" +#include "usbh_hid_parser.h" + +hid_mouse_info mouse_info; +uint32_t mouse_report_data[1]; + +/* structures defining how to access items in a hid mouse report */ +/* access button 1 state. */ +static const hid_report_item prop_b1 = +{ + (uint8_t *)(void *)mouse_report_data + 0, /* data */ + 1, /* size */ + 0, /* shift */ + 0, /* count (only for array items) */ + 0, /* signed? */ + 0, /* min value read can return */ + 1, /* max value read can return */ + 0, /* min value device can report */ + 1, /* max value device can report */ + 1 /* resolution */ +}; + +/* access button 2 state. */ +static const hid_report_item prop_b2 = +{ + (uint8_t *)(void *)mouse_report_data + 0, /* data */ + 1, /* size */ + 1, /* shift */ + 0, /* count (only for array items) */ + 0, /* signed? */ + 0, /* min value read can return */ + 1, /* max value read can return */ + 0, /* min value device can report */ + 1, /* max value device can report */ + 1 /* resolution */ +}; + +/* access button 3 state. */ +static const hid_report_item prop_b3 = +{ + (uint8_t *)(void *)mouse_report_data + 0, /* data */ + 1, /* size */ + 2, /* shift */ + 0, /* count (only for array items) */ + 0, /* signed? */ + 0, /* min value read can return */ + 1, /* max value read can return */ + 0, /* min vale device can report */ + 1, /* max value device can report */ + 1 /* resolution */ +}; + +/* access x coordinate change. */ +static const hid_report_item prop_x = +{ + (uint8_t *)(void *)mouse_report_data + 1, /* data */ + 8, /* size */ + 0, /* shift */ + 0, /* count (only for array items) */ + 1, /* signed? */ + 0, /* min value read can return */ + 0xFFFF,/* max value read can return */ + 0, /* min vale device can report */ + 0xFFFF,/* max value device can report */ + 1 /* resolution */ +}; + +/* access y coordinate change. */ +static const hid_report_item prop_y = +{ + (uint8_t *)(void *)mouse_report_data + 2, /* data */ + 8, /* size */ + 0, /* shift */ + 0, /* count (only for array items) */ + 1, /* signed? */ + 0, /* min value read can return */ + 0xFFFF,/* max value read can return */ + 0, /* min vale device can report */ + 0xFFFF,/* max value device can report */ + 1 /* resolution */ +}; + +/* local function prototypes ('static') */ +static usbh_status usbh_hid_mouse_decode(usb_core_driver *udev, usbh_host *uhost); + +/*! + \brief initialize the mouse function + \param[in] udev: pointer to usb core instance + \param[in] uhost: pointer to usb host + \param[out] none + \retval none +*/ +usbh_status usbh_hid_mouse_init (usb_core_driver *udev, usbh_host *uhost) +{ + usbh_hid_handler *hid = (usbh_hid_handler *)uhost->active_class->class_data; + + mouse_info.x = 0U; + mouse_info.y = 0U; + mouse_info.buttons[0] = 0U; + mouse_info.buttons[1] = 0U; + mouse_info.buttons[2] = 0U; + + mouse_report_data[0] = 0U; + + if(hid->len > sizeof(mouse_report_data)) { + hid->len = sizeof(mouse_report_data); + } + + hid->pdata = (uint8_t *)(void *)mouse_report_data; + + usbh_hid_fifo_init(&hid->fifo, uhost->dev_prop.data, HID_QUEUE_SIZE * sizeof(mouse_report_data)); + + usr_mouse_init(); + + return USBH_OK; +} + +/*! + \brief get mouse information + \param[in] udev: pointer to usb core instance + \param[in] uhost: pointer to usb host + \param[out] none + \retval mouse information +*/ +hid_mouse_info *usbh_hid_mouse_info_get (usb_core_driver *udev, usbh_host *uhost) +{ + if(usbh_hid_mouse_decode(udev, uhost)== USBH_OK) { + return &mouse_info; + } else { + return NULL; + } +} + +/*! + \brief decode mouse data + \param[in] udev: pointer to usb core instance + \param[in] uhost: pointer to usb host + \param[out] none + \retval none +*/ +void usbh_hid_mouse_machine (usb_core_driver *udev, usbh_host *uhost) +{ + hid_mouse_info *m_pinfo = NULL; + + m_pinfo = usbh_hid_mouse_info_get(udev, uhost); + + if (NULL != m_pinfo) { + /* handle mouse data position */ + usr_mouse_process_data(&mouse_info); + } +} + +/*! + \brief decode mouse information + \param[in] udev: pointer to usb core instance + \param[in] uhost: pointer to usb host + \param[out] none + \retval operation status +*/ +static usbh_status usbh_hid_mouse_decode(usb_core_driver *udev, usbh_host *uhost) +{ + usbh_hid_handler *hid = (usbh_hid_handler *)uhost->active_class->class_data; + + if (0U == hid->len) { + return USBH_FAIL; + } + + /* fill report */ + if (usbh_hid_fifo_read(&hid->fifo, &mouse_report_data, hid->len) == hid->len) { + /* decode report */ + mouse_info.x = (uint8_t)hid_item_read((hid_report_item *)&prop_x, 0U); + mouse_info.y = (uint8_t)hid_item_read((hid_report_item *)&prop_y, 0U); + + mouse_info.buttons[0] = (uint8_t)hid_item_read((hid_report_item *)&prop_b1, 0U); + mouse_info.buttons[1] = (uint8_t)hid_item_read((hid_report_item *)&prop_b2, 0U); + mouse_info.buttons[2] = (uint8_t)hid_item_read((hid_report_item *)&prop_b3, 0U); + + return USBH_OK; + } + + return USBH_FAIL; +} diff --git a/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/host/class/hid/Source/usbh_hid_parser.c b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/host/class/hid/Source/usbh_hid_parser.c new file mode 100644 index 0000000000..35750e7db9 --- /dev/null +++ b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/host/class/hid/Source/usbh_hid_parser.c @@ -0,0 +1,148 @@ +/*! + \file usbh_hid_parser.c + \brief USB host HID parser driver + + \version 2020-07-28, V3.0.0, firmware for GD32F20x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "usbh_hid_parser.h" + +/*! + \brief read a hid report item + \param[in] ri: pointer to report item + \param[in] ndx: report index + \param[out] none + \retval operation status (0: fail otherwise: item value) +*/ +uint32_t hid_item_read (hid_report_item *ri, uint8_t ndx) +{ + uint32_t val = 0U; + uint32_t bofs = 0U; + uint8_t *data = ri->data; + uint8_t shift = ri->shift; + + /* get the logical value of the item */ + + /* if this is an array, wee may need to offset ri->data.*/ + if (ri->count > 0U) { + /* if app tries to read outside of the array. */ + if (ri->count <= ndx) { + return(0U); + } + + /* calculate bit offset */ + bofs = ndx * ri->size; + bofs += shift; + + /* calculate byte offset + shift pair from bit offset. */ + data += bofs / 8U; + shift = (uint8_t)(bofs % 8U); + } + + /* read data bytes in little endian order */ + for (uint32_t x = 0U; x < ((ri->size & 0x7U) ? (ri->size / 8U) + 1U : (ri->size / 8U)); x++) { + val=(uint32_t)((uint32_t)(*data) << (x * 8U)); + } + + val=(val >> shift) & ((1U << ri->size) - 1U); + + if ((val < ri->logical_min) || (val > ri->logical_max)) { + return(0U); + } + + /* convert logical value to physical value */ + /* see if the number is negative or not. */ + if ((ri->sign) && (val & (1U << (ri->size - 1U)))) { + /* yes, so sign extend value to 32 bits. */ + uint32_t vs = (uint32_t)((0xffffffffU & ~((1U << (ri->size)) - 1U)) | val); + + if (1U == ri->resolution) { + return((uint32_t)vs); + } + return((uint32_t)(vs * ri->resolution)); + } else { + if (1U == ri->resolution) { + return(val); + } + + return (val * ri->resolution); + } +} + +/*! + \brief write a hid report item + \param[in] ri: pointer to report item + \param[in] value: the value to be write + \param[in] ndx: report index + \param[out] none + \retval operation status (1: fail 0: Ok) +*/ +uint32_t hid_item_write(hid_report_item *ri, uint32_t value, uint8_t ndx) +{ + uint32_t mask; + uint32_t bofs; + uint8_t *data = ri->data; + uint8_t shift = ri->shift; + + if ((value < ri->physical_min) || (value > ri->physical_max)) { + return(1U); + } + + /* if this is an array, wee may need to offset ri->data.*/ + if (ri->count > 0U) { + /* if app tries to read outside of the array. */ + if (ri->count >= ndx) { + return(0U); + } + + /* calculate bit offset */ + bofs = ndx * ri->size; + bofs += shift; + + /* calculate byte offset + shift pair from bit offset. */ + data += bofs / 8U; + shift = (uint8_t)(bofs % 8U); + } + + /* convert physical value to logical value. */ + if (1U != ri->resolution) { + value = value / ri->resolution; + } + + /* write logical value to report in little endian order. */ + mask = (1U << ri->size) - 1U; + value = (value & mask) << shift; + + for (uint32_t x = 0U; x < ((ri->size & 0x7U) ? (ri->size / 8U) + 1U : (ri->size / 8U)); x++) { + *(ri->data + x) = (uint8_t)((*(ri->data+x) & ~(mask>>(x* 8U))) | ((value >> (x * 8U)) & (mask >> (x * 8U)))); + } + + return 0U; +} diff --git a/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/host/class/msc/Include/usbh_msc_bbb.h b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/host/class/msc/Include/usbh_msc_bbb.h new file mode 100644 index 0000000000..42ccd19da6 --- /dev/null +++ b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/host/class/msc/Include/usbh_msc_bbb.h @@ -0,0 +1,150 @@ +/*! + \file usbh_msc_bbb.h + \brief header file for usbh_msc_bbb.c + + \version 2020-07-28, V3.0.0, firmware for GD32F20x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef __USBH_MSC_BBB_H +#define __USBH_MSC_BBB_H + +#include "usbh_enum.h" +#include "msc_bbb.h" + +typedef union { + msc_bbb_cbw field; + + uint8_t CBWArray[31]; +}usbh_cbw_pkt; + +typedef union { + msc_bbb_csw field; + + uint8_t CSWArray[13]; +}usbh_csw_pkt; + +enum usbh_msc_state { + USBH_MSC_BOT_INIT_STATE = 0U, + USBH_MSC_BOT_RESET, + USBH_MSC_GET_MAX_LUN, + USBH_MSC_TEST_UNIT_READY, + USBH_MSC_READ_CAPACITY10, + USBH_MSC_MODE_SENSE6, + USBH_MSC_REQUEST_SENSE, + USBH_MSC_BOT_USB_TRANSFERS, + USBH_MSC_DEFAULT_APPLI_STATE, + USBH_MSC_CTRL_ERROR_STATE, + USBH_MSC_UNRECOVERED_STATE +}; + +typedef enum +{ + BOT_OK = 0U, + BOT_FAIL, + BOT_PHASE_ERROR, + BOT_BUSY +} bot_status; + +typedef enum +{ + BOT_CMD_IDLE = 0U, + BOT_CMD_SEND, + BOT_CMD_WAIT, +} bot_cmd_state; + +/* csw status definitions */ +typedef enum +{ + BOT_CSW_CMD_PASSED = 0U, + BOT_CSW_CMD_FAILED, + BOT_CSW_PHASE_ERROR, +} bot_csw_status; + +typedef enum +{ + BOT_SEND_CBW = 1U, + BOT_SEND_CBW_WAIT, + BOT_DATA_IN, + BOT_DATA_IN_WAIT, + BOT_DATA_OUT, + BOT_DATA_OUT_WAIT, + BOT_RECEIVE_CSW, + BOT_RECEIVE_CSW_WAIT, + BOT_ERROR_IN, + BOT_ERROR_OUT, + BOT_UNRECOVERED_ERROR +} bot_state; + +typedef struct +{ + uint8_t *pbuf; + uint32_t data[16]; + bot_state state; + bot_state prev_state; + bot_cmd_state cmd_state; + usbh_cbw_pkt cbw; + usbh_csw_pkt csw; +} bot_handle; + +#define USBH_MSC_BOT_CBW_TAG 0x20304050U + +#define USBH_MSC_CSW_MAX_LENGTH 63U + +#define USBH_MSC_SEND_CSW_DISABLE 0U +#define USBH_MSC_SEND_CSW_ENABLE 1U + +#define USBH_MSC_DIR_IN 0U +#define USBH_MSC_DIR_OUT 1U +#define USBH_MSC_BOTH_DIR 2U + +#define USBH_MSC_PAGE_LENGTH 512U + +#define CBW_CB_LENGTH 16U +#define CBW_LENGTH 10U +#define CBW_LENGTH_TEST_UNIT_READY 0U + +#define MAX_BULK_STALL_COUNT_LIMIT 0x04U /*!< If STALL is seen on Bulk + Endpoint continously, this means + that device and Host has phase error + Hence a Reset is needed */ + +/* function declarations */ +/* initialize the mass storage parameters */ +void usbh_msc_bot_init (usbh_host *uhost); +/* manage the different states of BOT transfer and updates the status to upper layer */ +usbh_status usbh_msc_bot_process (usbh_host *uhost, uint8_t lun); +/* manages the different error handling for stall */ +usbh_status usbh_msc_bot_abort (usbh_host *uhost, uint8_t direction); +/* reset msc bot request structure */ +usbh_status usbh_msc_bot_reset (usbh_host *uhost); +/* decode the CSW received by the device and updates the same to upper layer */ +bot_csw_status usbh_msc_csw_decode (usbh_host *uhost); + +#endif /* __USBH_MSC_BBB_H */ diff --git a/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/host/class/msc/Include/usbh_msc_core.h b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/host/class/msc/Include/usbh_msc_core.h new file mode 100644 index 0000000000..48b103b652 --- /dev/null +++ b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/host/class/msc/Include/usbh_msc_core.h @@ -0,0 +1,124 @@ +/*! + \file usbh_core.h + \brief header file for the usbh_core.c + + \version 2020-07-28, V3.0.0, firmware for GD32F20x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef __USBH_MSC_CORE_H +#define __USBH_MSC_CORE_H + +#include "usb_msc.h" +#include "usbh_msc_scsi.h" +#include "usbh_msc_bbb.h" + +#define MSC_MAX_SUPPORTED_LUN 2U + +typedef enum +{ + MSC_INIT = 0U, + MSC_IDLE, + MSC_TEST_UNIT_READY, + MSC_READ_CAPACITY10, + MSC_READ_INQUIRY, + MSC_REQUEST_SENSE, + MSC_READ, + MSC_WRITE, + MSC_UNRECOVERED_ERROR, + MSC_PERIODIC_CHECK, +} msc_state; + +typedef enum +{ + MSC_OK, + MSC_NOT_READY, + MSC_ERROR, +} msc_error; + +typedef enum +{ + MSC_REQ_IDLE = 0U, + MSC_REQ_RESET, + MSC_REQ_GET_MAX_LUN, + MSC_REQ_ERROR, +} msc_req_state; + +/* Structure for LUN */ +typedef struct +{ + msc_state state; + msc_error error; + msc_scsi_sense sense; + scsi_capacity capacity; + scsi_std_inquiry_data inquiry; + usbh_status prev_ready_state; + uint8_t state_changed; +} msc_lun; + +/* structure for msc process */ +typedef struct _msc_process +{ + uint8_t pipe_in; + uint8_t pipe_out; + uint8_t ep_in; + uint8_t ep_out; + uint16_t ep_size_in; + uint16_t ep_size_out; + uint8_t cur_lun; + uint16_t rw_lun; + uint32_t max_lun; + msc_state state; + msc_error error; + msc_req_state req_state; + msc_req_state prev_req_state; + bot_handle bot; + msc_lun unit[MSC_MAX_SUPPORTED_LUN]; + uint32_t timer; +} usbh_msc_handler; + +extern usbh_class usbh_msc; + +/* function declarations */ +/* get msc logic unit information */ +usbh_status usbh_msc_lun_info_get (usbh_host *uhost, uint8_t lun, msc_lun *info); +/* msc read interface */ +usbh_status usbh_msc_read (usbh_host *uhost, + uint8_t lun, + uint32_t address, + uint8_t *pbuf, + uint32_t length); +/* msc write interface */ +usbh_status usbh_msc_write (usbh_host *uhost, + uint8_t lun, + uint32_t address, + uint8_t *pbuf, + uint32_t length); + +#endif /* __USBH_MSC_CORE_H */ diff --git a/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/host/class/msc/Include/usbh_msc_scsi.h b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/host/class/msc/Include/usbh_msc_scsi.h new file mode 100644 index 0000000000..24bc0b3db4 --- /dev/null +++ b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/host/class/msc/Include/usbh_msc_scsi.h @@ -0,0 +1,100 @@ +/*! + \file usbh_msc_scsi.h + \brief header file for usbh_msc_scsi.c + + \version 2020-07-28, V3.0.0, firmware for GD32F20x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef __USBH_MSC_SCSI_H +#define __USBH_MSC_SCSI_H + +#include "msc_scsi.h" +#include "usbh_enum.h" + +/* capacity data */ +typedef struct +{ + uint32_t block_nbr; + uint16_t block_size; +} scsi_capacity; + +/* inquiry data */ +typedef struct +{ + uint8_t peripheral_qualifier; + uint8_t device_type; + uint8_t removable_media; + uint8_t vendor_id[9]; + uint8_t product_id[17]; + uint8_t revision_id[5]; +} scsi_std_inquiry_data; + +typedef struct +{ + uint32_t msc_capacity; + uint32_t msc_sense_key; + uint16_t msc_page_len; + uint8_t msc_write_protect; +}usbh_msc_parameter; + +#define DESC_REQUEST_SENSE 0x00U +#define ALLOCATION_LENGTH_REQUEST_SENSE 63U +#define XFER_LEN_MODE_SENSE6 63U + +#define MASK_MODE_SENSE_WRITE_PROTECT 0x80U +#define MODE_SENSE_PAGE_CONTROL_FIELD 0x00U +#define MODE_SENSE_PAGE_CODE 0x3FU +#define DISK_WRITE_PROTECTED 0x01U + +/* function declarations */ +/* send 'Inquiry' command to the device */ +usbh_status usbh_msc_scsi_inquiry (usbh_host *uhost, uint8_t lun, scsi_std_inquiry_data *inquiry); +/* send 'Test unit ready' command to the device */ +usbh_status usbh_msc_test_unitready (usbh_host *uhost, uint8_t lun); +/* send the read capacity command to the device */ +usbh_status usbh_msc_read_capacity10 (usbh_host *uhost, uint8_t lun, scsi_capacity *capacity); +/* send the mode sense6 command to the device */ +usbh_status usbh_msc_mode_sense6 (usbh_host *uhost, uint8_t lun); +/* send the Request Sense command to the device */ +usbh_status usbh_msc_request_sense (usbh_host *uhost, uint8_t lun, msc_scsi_sense *sense_data); +/* send the write10 command to the device */ +usbh_status usbh_msc_write10 (usbh_host *uhost, + uint8_t lun, + uint8_t *data_buf, + uint32_t addr, + uint32_t byte_num); +/* send the read10 command to the device */ +usbh_status usbh_msc_read10 (usbh_host *uhost, + uint8_t lun, + uint8_t *data_buf, + uint32_t addr, + uint32_t byte_num); + +#endif /* __USBH_MSC_SCSI_H */ diff --git a/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/host/class/msc/Source/usbh_msc_bbb.c b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/host/class/msc/Source/usbh_msc_bbb.c new file mode 100644 index 0000000000..1877f35d2f --- /dev/null +++ b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/host/class/msc/Source/usbh_msc_bbb.c @@ -0,0 +1,362 @@ +/*! + \file usbh_msc_bbb.c + \brief USB MSC BBB protocol related functions + + \version 2020-07-28, V3.0.0, firmware for GD32F20x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "usbh_pipe.h" +#include "usbh_msc_core.h" +#include "usbh_msc_scsi.h" +#include "usbh_msc_bbb.h" +#include "usbh_transc.h" +#include "drv_usbh_int.h" + +/*! + \brief initialize the mass storage parameters + \param[in] uhost: pointer to usb host handler + \param[out] none + \retval none +*/ +void usbh_msc_bot_init (usbh_host *uhost) +{ + usbh_msc_handler *msc = (usbh_msc_handler *)uhost->active_class->class_data; + + msc->bot.cbw.field.dCBWSignature = BBB_CBW_SIGNATURE; + msc->bot.cbw.field.dCBWTag = USBH_MSC_BOT_CBW_TAG; + msc->bot.state = BOT_SEND_CBW; + msc->bot.cmd_state = BOT_CMD_SEND; +} + +/*! + \brief manage the different states of BOT transfer and updates the status to upper layer + \param[in] uhost: pointer to usb host handler + \param[in] lun: logic unit number + \param[out] none + \retval operation status +*/ +usbh_status usbh_msc_bot_process (usbh_host *uhost, uint8_t lun) +{ + bot_csw_status csw_status = BOT_CSW_CMD_FAILED; + usbh_status status = USBH_BUSY; + usbh_status error = USBH_BUSY; + usb_urb_state urb_status = URB_IDLE; + usbh_msc_handler *msc = (usbh_msc_handler *)uhost->active_class->class_data; + + switch (msc->bot.state) { + case BOT_SEND_CBW: + msc->bot.cbw.field.bCBWLUN = lun; + msc->bot.state = BOT_SEND_CBW_WAIT; + /* send CBW */ + usbh_data_send (uhost->data, + msc->bot.cbw.CBWArray, + msc->pipe_out, + BBB_CBW_LENGTH); + break; + + case BOT_SEND_CBW_WAIT: + urb_status = usbh_urbstate_get(uhost->data, msc->pipe_out); + + if (URB_DONE == urb_status) { + if (0U != msc->bot.cbw.field.dCBWDataTransferLength) { + if (USB_TRX_IN == (msc->bot.cbw.field.bmCBWFlags & USB_TRX_MASK)) { + msc->bot.state = BOT_DATA_IN; + } else { + msc->bot.state = BOT_DATA_OUT; + } + } else { + msc->bot.state = BOT_RECEIVE_CSW; + } + + } else if (URB_NOTREADY == urb_status) { + msc->bot.state = BOT_SEND_CBW; + } else { + if (URB_STALL == urb_status) { + msc->bot.state = BOT_ERROR_OUT; + } + } + break; + + case BOT_DATA_IN: + usbh_data_recev (uhost->data, + msc->bot.pbuf, + msc->pipe_in, + msc->ep_size_in); + + msc->bot.state = BOT_DATA_IN_WAIT; + break; + + case BOT_DATA_IN_WAIT: + urb_status = usbh_urbstate_get(uhost->data, msc->pipe_in); + + /* BOT DATA IN stage */ + if (URB_DONE == urb_status) { + if (msc->bot.cbw.field.dCBWDataTransferLength > msc->ep_size_in) { + msc->bot.pbuf += msc->ep_size_in; + msc->bot.cbw.field.dCBWDataTransferLength -= msc->ep_size_in; + } else { + msc->bot.cbw.field.dCBWDataTransferLength = 0U; + } + + if (msc->bot.cbw.field.dCBWDataTransferLength > 0U) { + usbh_data_recev (uhost->data, + msc->bot.pbuf, + msc->pipe_in, + msc->ep_size_in); + } else { + msc->bot.state = BOT_RECEIVE_CSW; + } + } else if(URB_STALL == urb_status) { + /* this is data stage stall condition */ + msc->bot.state = BOT_ERROR_IN; + } else { + /* no operation */ + } + break; + + case BOT_DATA_OUT: + usbh_data_send (uhost->data, + msc->bot.pbuf, + msc->pipe_out, + msc->ep_size_out); + + msc->bot.state = BOT_DATA_OUT_WAIT; + break; + + case BOT_DATA_OUT_WAIT: + /* BOT DATA OUT stage */ + urb_status = usbh_urbstate_get(uhost->data, msc->pipe_out); + if (URB_DONE == urb_status) { + if (msc->bot.cbw.field.dCBWDataTransferLength > msc->ep_size_out) { + msc->bot.pbuf += msc->ep_size_out; + msc->bot.cbw.field.dCBWDataTransferLength -= msc->ep_size_out; + } else { + msc->bot.cbw.field.dCBWDataTransferLength = 0; /* reset this value and keep in same state */ + } + + if (msc->bot.cbw.field.dCBWDataTransferLength > 0) { + usbh_data_send (uhost->data, + msc->bot.pbuf, + msc->pipe_out, + msc->ep_size_out); + } else { + msc->bot.state = BOT_RECEIVE_CSW; + } + } else if (URB_NOTREADY == urb_status) { + msc->bot.state = BOT_DATA_OUT; + } else if (URB_STALL == urb_status) { + msc->bot.state = BOT_ERROR_OUT; + } else { + /* no operation */ + } + break; + + case BOT_RECEIVE_CSW: + /* BOT CSW stage */ + usbh_data_recev (uhost->data, + msc->bot.csw.CSWArray, + msc->pipe_in, + BBB_CSW_LENGTH); + + msc->bot.state = BOT_RECEIVE_CSW_WAIT; + break; + + case BOT_RECEIVE_CSW_WAIT: + urb_status = usbh_urbstate_get(uhost->data, msc->pipe_in); + + /* decode CSW */ + if (URB_DONE == urb_status) { + msc->bot.state = BOT_SEND_CBW; + msc->bot.cmd_state = BOT_CMD_SEND; + + csw_status = usbh_msc_csw_decode(uhost); + if (BOT_CSW_CMD_PASSED == csw_status) { + status = USBH_OK; + } else { + status = USBH_FAIL; + } + } else if (URB_STALL == urb_status) { + msc->bot.state = BOT_ERROR_IN; + } else { + /* no operation */ + } + break; + + case BOT_ERROR_IN: + error = usbh_msc_bot_abort(uhost, USBH_MSC_DIR_IN); + + if (USBH_OK == error) { + msc->bot.state = BOT_RECEIVE_CSW; + } else if (USBH_UNRECOVERED_ERROR == status) { + /* this means that there is a stall error limit, do reset recovery */ + msc->bot.state = BOT_UNRECOVERED_ERROR; + } else { + /* no operation */ + } + break; + + case BOT_ERROR_OUT: + status = usbh_msc_bot_abort (uhost, USBH_MSC_DIR_OUT); + + if (USBH_OK == status) { + uint8_t toggle = usbh_pipe_toggle_get(uhost->data, msc->pipe_out); + usbh_pipe_toggle_set(uhost->data, msc->pipe_out, 1U - toggle); + usbh_pipe_toggle_set(uhost->data, msc->pipe_in, 0U); + msc->bot.state = BOT_ERROR_IN; + } else { + if (USBH_UNRECOVERED_ERROR == status) { + msc->bot.state = BOT_UNRECOVERED_ERROR; + } + } + break; + + case BOT_UNRECOVERED_ERROR: + status = usbh_msc_bot_reset(uhost); + if (USBH_OK == status) { + msc->bot.state = BOT_SEND_CBW; + } + break; + + default: + break; + } + + return status; +} + +/*! + \brief manages the different error handling for stall + \param[in] uhost: pointer to usb host handler + \param[in] direction: data IN or OUT + \param[out] none + \retval operation status +*/ +usbh_status usbh_msc_bot_abort (usbh_host *uhost, uint8_t direction) +{ + usbh_status status = USBH_BUSY; + usbh_msc_handler *msc = (usbh_msc_handler *)uhost->active_class->class_data; + + switch (direction) { + case USBH_MSC_DIR_IN : + /* send clrfeture command on bulk IN endpoint */ + status = usbh_clrfeature(uhost, + msc->ep_in, + msc->pipe_in); + break; + + case USBH_MSC_DIR_OUT : + /*send clrfeature command on bulk OUT endpoint */ + status = usbh_clrfeature(uhost, + msc->ep_out, + msc->pipe_out); + break; + + default: + break; + } + + return status; +} + +/*! + \brief reset msc bot transfer + \param[in] uhost: pointer to usb host handler + \param[out] none + \retval operation status +*/ +usbh_status usbh_msc_bot_reset (usbh_host *uhost) +{ + usbh_status status = USBH_BUSY; + + if (CTL_IDLE == uhost->control.ctl_state) { + uhost->control.setup.req = (usb_req) { + .bmRequestType = USB_TRX_OUT | USB_REQTYPE_CLASS | USB_RECPTYPE_ITF, + .bRequest = BBB_RESET, + .wValue = 0U, + .wIndex = 0U, + .wLength = 0U + }; + + usbh_ctlstate_config (uhost, NULL, 0U); + } + + status = usbh_ctl_handler (uhost); + + return status; +} + +/*! + \brief decode the CSW received by the device and updates the same to upper layer + \param[in] uhost: pointer to usb host + \param[out] none + \retval on success USBH_MSC_OK, on failure USBH_MSC_FAIL + \notes + Refer to USB Mass-Storage Class: BOT (www.usb.org) + 6.3.1 Valid CSW Conditions : + The host shall consider the CSW valid when: + 1. dCSWSignature is equal to 53425355h + 2. the CSW is 13 (Dh) bytes in length, + 3. dCSWTag matches the dCBWTag from the corresponding CBW. +*/ +bot_csw_status usbh_msc_csw_decode (usbh_host *uhost) +{ + bot_csw_status status = BOT_CSW_CMD_FAILED; + usbh_msc_handler *msc = (usbh_msc_handler *)uhost->active_class->class_data; + + /* checking if the transfer length is different than 13 */ + if (BBB_CSW_LENGTH != usbh_xfercount_get (uhost->data, msc->pipe_in)) { + status = BOT_CSW_PHASE_ERROR; + } else { + /* CSW length is correct */ + + /* check validity of the CSW Signature and CSWStatus */ + if (BBB_CSW_SIGNATURE == msc->bot.csw.field.dCSWSignature) { + /* check condition 1. dCSWSignature is equal to 53425355h */ + if (msc->bot.csw.field.dCSWTag == msc->bot.cbw.field.dCBWTag) { + /* check condition 3. dCSWTag matches the dCBWTag from the corresponding CBW */ + if (0U == msc->bot.csw.field.bCSWStatus) { + status = BOT_CSW_CMD_PASSED; + } else if (1U == msc->bot.csw.field.bCSWStatus) { + status = BOT_CSW_CMD_FAILED; + } else if (2U == msc->bot.csw.field.bCSWStatus) { + status = BOT_CSW_PHASE_ERROR; + } else { + /* no operation */ + } + } + } else { + /* If the CSW signature is not valid, we shall return the phase error to + upper layers for reset recovery */ + status = BOT_CSW_PHASE_ERROR; + } + } + + return status; +} diff --git a/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/host/class/msc/Source/usbh_msc_core.c b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/host/class/msc/Source/usbh_msc_core.c new file mode 100644 index 0000000000..9f88e2db3e --- /dev/null +++ b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/host/class/msc/Source/usbh_msc_core.c @@ -0,0 +1,556 @@ +/*! + \file usbh_core.c + \brief USB MSC(mass storage device) class driver + + \version 2020-07-28, V3.0.0, firmware for GD32F20x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "usbh_msc_core.h" +#include "usbh_msc_scsi.h" +#include "usbh_msc_bbb.h" +#include "usbh_pipe.h" +#include "usbh_transc.h" +#include +#include + +/* local function prototypes ('static') */ +static void usbh_msc_itf_deinit (usbh_host *uhost); +static usbh_status usbh_msc_itf_init (usbh_host *uhost); +static usbh_status usbh_msc_req (usbh_host *uhost); +static usbh_status usbh_msc_handle (usbh_host *uhost); +static usbh_status usbh_msc_maxlun_get (usbh_host *uhost, uint8_t *maxlun); +static usbh_status usbh_msc_rdwr_process(usbh_host *uhost, uint8_t lun); + +usbh_class usbh_msc = +{ + USB_CLASS_MSC, + usbh_msc_itf_init, + usbh_msc_itf_deinit, + usbh_msc_req, + usbh_msc_handle, +}; + +/*! + \brief interface initialization for MSC class + \param[in] uhost: pointer to usb host + \param[out] none + \retval operation status +*/ +static usbh_status usbh_msc_itf_init (usbh_host *uhost) +{ + usbh_status status = USBH_OK; + + uint8_t interface = usbh_interface_find(&uhost->dev_prop, MSC_CLASS, USB_MSC_SUBCLASS_SCSI, MSC_PROTOCOL); + + if (0xFFU == interface) { + uhost->usr_cb->dev_not_supported(); + + status = USBH_FAIL; + } else { + static usbh_msc_handler msc_handler; + + memset((void*)&msc_handler, 0, sizeof(usbh_msc_handler)); + + uhost->active_class->class_data = (void *)&msc_handler; + + usbh_interface_select(&uhost->dev_prop, interface); + + usb_desc_ep *ep_desc = &uhost->dev_prop.cfg_desc_set.itf_desc_set[interface][0].ep_desc[0]; + + if (ep_desc->bEndpointAddress & 0x80) { + msc_handler.ep_in = ep_desc->bEndpointAddress; + msc_handler.ep_size_in = ep_desc->wMaxPacketSize; + } else { + msc_handler.ep_out = ep_desc->bEndpointAddress; + msc_handler.ep_size_out = ep_desc->wMaxPacketSize; + } + + ep_desc = &uhost->dev_prop.cfg_desc_set.itf_desc_set[interface][0].ep_desc[1]; + + if (ep_desc->bEndpointAddress & 0x80) { + msc_handler.ep_in = ep_desc->bEndpointAddress; + msc_handler.ep_size_in = ep_desc->wMaxPacketSize; + } else { + msc_handler.ep_out = ep_desc->bEndpointAddress; + msc_handler.ep_size_out = ep_desc->wMaxPacketSize; + } + + msc_handler.state = MSC_INIT; + msc_handler.error = MSC_OK; + msc_handler.req_state = MSC_REQ_IDLE; + msc_handler.pipe_out = usbh_pipe_allocate(uhost->data, msc_handler.ep_out); + msc_handler.pipe_in = usbh_pipe_allocate(uhost->data, msc_handler.ep_in); + + usbh_msc_bot_init(uhost); + + /* open the new channels */ + usbh_pipe_create (uhost->data, + &uhost->dev_prop, + msc_handler.pipe_out, + USB_EPTYPE_BULK, + msc_handler.ep_size_out); + + usbh_pipe_create (uhost->data, + &uhost->dev_prop, + msc_handler.pipe_in, + USB_EPTYPE_BULK, + msc_handler.ep_size_in); + + usbh_pipe_toggle_set (uhost->data, msc_handler.pipe_out, 0U); + usbh_pipe_toggle_set (uhost->data, msc_handler.pipe_in, 0U); + } + + return status; +} + +/*! + \brief de-initialize interface by freeing host channels allocated to interface + \param[in] uhost: pointer to usb host + \param[out] none + \retval operation status +*/ +void usbh_msc_itf_deinit (usbh_host *uhost) +{ + usbh_msc_handler *msc = (usbh_msc_handler *)uhost->active_class->class_data; + + if (msc->pipe_out) { + usb_pipe_halt (uhost->data, msc->pipe_out); + usbh_pipe_free (uhost->data, msc->pipe_out); + + msc->pipe_out = 0U; + } + + if (msc->pipe_in) { + usb_pipe_halt (uhost->data, msc->pipe_in); + usbh_pipe_free (uhost->data, msc->pipe_in); + + msc->pipe_in = 0U; + } +} + +/*! + \brief initialize the MSC state machine + \param[in] uhost: pointer to usb host + \param[out] none + \retval operation status +*/ +static usbh_status usbh_msc_req (usbh_host *uhost) +{ + usbh_status status = USBH_BUSY; + usbh_msc_handler *msc = (usbh_msc_handler *)uhost->active_class->class_data; + + switch (msc->req_state) { + case MSC_REQ_IDLE: + case MSC_REQ_GET_MAX_LUN: + /* issue Get_MaxLun request */ + status = usbh_msc_maxlun_get (uhost, (uint8_t *)&msc->max_lun); + + if (USBH_OK == status) { + msc->max_lun = ((uint8_t)msc->max_lun > MSC_MAX_SUPPORTED_LUN) ? MSC_MAX_SUPPORTED_LUN : (uint8_t)msc->max_lun + 1U; + + for (uint8_t i = 0U; i < msc->max_lun; i++) { + msc->unit[i].prev_ready_state = USBH_FAIL; + msc->unit[i].state_changed = 0U; + } + } else { + if (USBH_NOT_SUPPORTED == status) { + msc->max_lun = 0U; + status = USBH_OK; + } + } + break; + + case MSC_REQ_ERROR: + /* issue clear feature request */ + if (USBH_OK == usbh_clrfeature(uhost, 0x00U, uhost->control.pipe_out_num)) { + msc->req_state = msc->prev_req_state; + } + break; + + default: + break; + } + + return status; +} + +/*! + \brief MSC state machine handler + \param[in] uhost: pointer to usb host + \param[out] none + \retval operation status +*/ +static usbh_status usbh_msc_handle (usbh_host *uhost) +{ + usbh_status status = USBH_BUSY; + uint8_t scsi_status = USBH_BUSY; + uint8_t ready_status = USBH_BUSY; + usbh_msc_handler *msc = (usbh_msc_handler *)uhost->active_class->class_data; + + + switch (msc->state) { + case MSC_INIT: + if (msc->cur_lun < msc->max_lun) { + msc->unit[msc->cur_lun].error = MSC_NOT_READY; + + switch (msc->unit[msc->cur_lun].state) { + case MSC_INIT: + msc->unit[msc->cur_lun].state = MSC_READ_INQUIRY; + msc->timer = uhost->control.timer; + break; + + case MSC_READ_INQUIRY: + scsi_status = usbh_msc_scsi_inquiry(uhost, msc->cur_lun, &msc->unit[msc->cur_lun].inquiry); + + if (USBH_OK == scsi_status) { + msc->unit[msc->cur_lun].state = MSC_TEST_UNIT_READY; + } else if (scsi_status == USBH_FAIL) { + msc->unit[msc->cur_lun].state = MSC_REQUEST_SENSE; + } else { + if (scsi_status == USBH_UNRECOVERED_ERROR) { + msc->unit[msc->cur_lun].state = MSC_IDLE; + msc->unit[msc->cur_lun].error = MSC_ERROR; + } + } + break; + + case MSC_TEST_UNIT_READY: + /* issue SCSI command TestUnitReady */ + ready_status = usbh_msc_test_unitready(uhost, msc->cur_lun); + + if (USBH_OK == ready_status) { + if (USBH_OK != msc->unit[msc->cur_lun].prev_ready_state) { + msc->unit[msc->cur_lun].state_changed = 1U; + } else { + msc->unit[msc->cur_lun].state_changed = 0U; + } + + msc->unit[msc->cur_lun].state = MSC_READ_CAPACITY10; + msc->unit[msc->cur_lun].error = MSC_OK; + msc->unit[msc->cur_lun].prev_ready_state = USBH_OK; + } else if (USBH_FAIL == ready_status) { + if (USBH_FAIL != msc->unit[msc->cur_lun].prev_ready_state) { + msc->unit[msc->cur_lun].state_changed = 1U; + } else { + msc->unit[msc->cur_lun].state_changed = 0U; + } + + msc->unit[msc->cur_lun].state = MSC_REQUEST_SENSE; + msc->unit[msc->cur_lun].error = MSC_NOT_READY; + msc->unit[msc->cur_lun].prev_ready_state = USBH_FAIL; + } else { + if (USBH_UNRECOVERED_ERROR == ready_status) { + msc->unit[msc->cur_lun].state = MSC_IDLE; + msc->unit[msc->cur_lun].error = MSC_ERROR; + } + } + break; + + case MSC_READ_CAPACITY10: + /* issue READ_CAPACITY10 SCSI command */ + scsi_status = usbh_msc_read_capacity10(uhost, msc->cur_lun, &msc->unit[msc->cur_lun].capacity); + + if (USBH_OK == scsi_status) { + if (1U == msc->unit[msc->cur_lun].state_changed) { + } + msc->unit[msc->cur_lun].state = MSC_IDLE; + msc->unit[msc->cur_lun].error = MSC_OK; + msc->cur_lun ++; + } else if (USBH_FAIL == scsi_status) { + msc->unit[msc->cur_lun].state = MSC_REQUEST_SENSE; + } else { + if (USBH_UNRECOVERED_ERROR == scsi_status) { + msc->unit[msc->cur_lun].state = MSC_IDLE; + msc->unit[msc->cur_lun].error = MSC_ERROR; + } + } + break; + + case MSC_REQUEST_SENSE: + /* issue RequestSense SCSI command for retreiving error code */ + scsi_status = usbh_msc_request_sense (uhost, msc->cur_lun, &msc->unit[msc->cur_lun].sense); + if (USBH_OK == scsi_status) { + if ((msc->unit[msc->cur_lun].sense.SenseKey == UNIT_ATTENTION) || (msc->unit[msc->cur_lun].sense.SenseKey == NOT_READY)) { + if ((uhost->control.timer - msc->timer) < 10000U) { + msc->unit[msc->cur_lun].state = MSC_TEST_UNIT_READY; + break; + } + } + + msc->unit[msc->cur_lun].state = MSC_IDLE; + msc->cur_lun++; + } else if (USBH_FAIL == scsi_status) { + msc->unit[msc->cur_lun].state = MSC_UNRECOVERED_ERROR; + } else { + if (MSC_UNRECOVERED_ERROR == scsi_status) { + msc->unit[msc->cur_lun].state = MSC_IDLE; + msc->unit[msc->cur_lun].error = MSC_ERROR; + } + } + break; + + case MSC_UNRECOVERED_ERROR: + msc->cur_lun ++; + break; + + default: + break; + } + } else { + msc->cur_lun = 0U; + msc->state = MSC_IDLE; + } + break; + + case MSC_IDLE: + uhost->usr_cb->dev_user_app(); + status = USBH_OK; + break; + + default: + break; + } + + return status; +} + +/*! + \brief get max lun of the mass storage device + \param[in] uhost: pointer to USB host + \param[in] maxlun: pointer to max lun + \param[out] none + \retval operation status +*/ +static usbh_status usbh_msc_maxlun_get (usbh_host *uhost, uint8_t *maxlun) +{ + usbh_status status = USBH_BUSY; + + if (uhost->control.ctl_state == CTL_IDLE) { + uhost->control.setup.req = (usb_req) { + .bmRequestType = USB_TRX_IN | USB_REQTYPE_CLASS | USB_RECPTYPE_ITF, + .bRequest = BBB_GET_MAX_LUN, + .wValue = 0U, + .wIndex = 0U, + .wLength = 1U + }; + + usbh_ctlstate_config (uhost, maxlun, 1U); + } + + status = usbh_ctl_handler (uhost); + + return status; +} + +/*! + \brief get max lun of the mass storage device + \param[in] uhost: pointer to USB host + \param[in] lun: logic unit number + \param[out] none + \retval operation status +*/ +static usbh_status usbh_msc_rdwr_process(usbh_host *uhost, uint8_t lun) +{ + usbh_status error = USBH_BUSY; + usbh_status scsi_status = USBH_BUSY; + usbh_msc_handler *msc = (usbh_msc_handler *)uhost->active_class->class_data; + + /* switch msc req state machine */ + switch (msc->unit[lun].state) { + case MSC_READ: + scsi_status = usbh_msc_read10(uhost, lun, NULL, 0U, 0U); + + if (USBH_OK == scsi_status) { + msc->unit[lun].state = MSC_IDLE; + error = USBH_OK; + } else if (USBH_FAIL == scsi_status) { + msc->unit[lun].state = MSC_REQUEST_SENSE; + } else { + if (USBH_UNRECOVERED_ERROR == scsi_status) { + msc->unit[lun].state = MSC_UNRECOVERED_ERROR; + error = USBH_FAIL; + } + } + break; + + case MSC_WRITE: + scsi_status = usbh_msc_write10(uhost, lun, NULL, 0U, 0U); + + if (USBH_OK == scsi_status) { + msc->unit[lun].state = MSC_IDLE; + error = USBH_OK; + } else if(USBH_FAIL == scsi_status) { + msc->unit[lun].state = MSC_REQUEST_SENSE; + } else { + if (USBH_UNRECOVERED_ERROR == scsi_status) { + msc->unit[lun].state = MSC_UNRECOVERED_ERROR; + error = USBH_FAIL; + } + } + break; + + case MSC_REQUEST_SENSE: + scsi_status = usbh_msc_request_sense (uhost, lun, &msc->unit[lun].sense); + + if (USBH_OK == scsi_status) { + msc->unit[lun].state = MSC_IDLE; + msc->unit[lun].error = MSC_ERROR; + + error = USBH_FAIL; + } + + if (USBH_FAIL == scsi_status) { + } else { + if (USBH_UNRECOVERED_ERROR == scsi_status) { + msc->unit[lun].state = MSC_UNRECOVERED_ERROR; + error = USBH_FAIL; + } + } + break; + + default: + break; + } + + return error; +} + +/*! + \brief get lun information + \param[in] uhost: pointer to USB host + \param[in] lun: logic unit number + \param[in] info: pointer to lun information + \param[out] none + \retval operation status +*/ +usbh_status usbh_msc_lun_info_get (usbh_host *uhost, uint8_t lun, msc_lun *info) +{ + usbh_msc_handler *msc = (usbh_msc_handler *)uhost->active_class->class_data; + + if (HOST_CLASS_HANDLER == uhost->cur_state) { + memcpy(info, &msc->unit[lun], sizeof(msc_lun)); + + return USBH_OK; + } else { + return USBH_FAIL; + } +} + +/*! + \brief handle msc read operation + \param[in] uhost: pointer to USB host + \param[in] lun: logic unit number + \param[in] address: data address + \param[in] pbuf: pointer to data buffer + \param[in] length: buffer length + \param[out] none + \retval operation status +*/ +usbh_status usbh_msc_read (usbh_host *uhost, + uint8_t lun, + uint32_t address, + uint8_t *pbuf, + uint32_t length) +{ + uint32_t timeout = 0U; + usbh_msc_handler *msc = (usbh_msc_handler *)uhost->active_class->class_data; + usb_core_driver *udev = (usb_core_driver *)uhost->data; + + if ((0U == udev->host.connect_status) || + (HOST_CLASS_HANDLER != uhost->cur_state) || + (MSC_IDLE != msc->unit[lun].state)) { + return USBH_FAIL; + } + + msc->state = MSC_READ; + msc->unit[lun].state = MSC_READ; + msc->rw_lun = lun; + + usbh_msc_read10(uhost, lun, pbuf, address, length); + + timeout = uhost->control.timer; + + while (USBH_BUSY == usbh_msc_rdwr_process(uhost, lun)) { + if (((uhost->control.timer - timeout) > (1000U * length)) || (0U == udev->host.connect_status)) { + msc->state = MSC_IDLE; + return USBH_FAIL; + } + } + + msc->state = MSC_IDLE; + + return USBH_OK; +} + +/*! + \brief handle msc write operation + \param[in] uhost: pointer to USB host + \param[in] lun: logic unit number + \param[in] address: data address + \param[in] pbuf: pointer to data buffer + \param[in] length: buffer length + \param[out] none + \retval operation status +*/ +usbh_status usbh_msc_write (usbh_host *uhost, + uint8_t lun, + uint32_t address, + uint8_t *pbuf, + uint32_t length) +{ + uint32_t timeout = 0U; + usb_core_driver *udev = (usb_core_driver *)uhost->data; + usbh_msc_handler *msc = (usbh_msc_handler *)uhost->active_class->class_data; + + if ((0U == udev->host.connect_status) || + (HOST_CLASS_HANDLER != uhost->cur_state) || + (MSC_IDLE != msc->unit[lun].state)) { + return USBH_FAIL; + } + + msc->state = MSC_WRITE; + msc->unit[lun].state = MSC_WRITE; + msc->rw_lun = lun; + + usbh_msc_write10(uhost, lun, pbuf, address, length); + + timeout = uhost->control.timer; + + while (USBH_BUSY == usbh_msc_rdwr_process(uhost, lun)) { + if (((uhost->control.timer - timeout) > (1000U * length)) || (0U == udev->host.connect_status)) { + msc->state = MSC_IDLE; + return USBH_FAIL; + } + } + + msc->state = MSC_IDLE; + + return USBH_OK; +} diff --git a/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/host/class/msc/Source/usbh_msc_fatfs.c b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/host/class/msc/Source/usbh_msc_fatfs.c new file mode 100644 index 0000000000..e710d86a1f --- /dev/null +++ b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/host/class/msc/Source/usbh_msc_fatfs.c @@ -0,0 +1,233 @@ +/*! + \file usbh_msc_fatfs.c + \brief USB MSC host FATFS related functions + + \version 2020-07-28, V3.0.0, firmware for GD32F20x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "usb_conf.h" +#include "diskio.h" +#include "usbh_msc_core.h" + +static volatile DSTATUS state = STA_NOINIT; /* disk status */ + +extern usbh_host usb_host; + +/*! + \brief initialize the disk drive + \param[in] drv: physical drive number (0) + \param[out] none + \retval operation status +*/ +DSTATUS disk_initialize (BYTE drv) +{ + usb_core_driver *udev = (usb_core_driver *)usb_host.data; + + if (udev->host.connect_status) { + state &= ~STA_NOINIT; + } + + return state; +} + +/*! + \brief get disk status + \param[in] drv: physical drive number (0) + \param[out] none + \retval operation status +*/ +DSTATUS disk_status (BYTE drv) +{ + if (drv) { + return STA_NOINIT; /* supports only single drive */ + } + + return state; +} + +/*! + \brief read sectors + \param[in] drv: physical drive number (0) + \param[in] buff: pointer to the data buffer to store read data + \param[in] sector: start sector number (LBA) + \param[in] count: sector count (1..255) + \param[out] none + \retval operation status +*/ +DRESULT disk_read (BYTE drv, BYTE *buff, DWORD sector, UINT count) +{ + BYTE status = USBH_OK; + usb_core_driver *udev = (usb_core_driver *)usb_host.data; + + if (drv || (!count)) { + return RES_PARERR; + } + + if (state & STA_NOINIT) { + return RES_NOTRDY; + } + + if (udev->host.connect_status) { + do { + status = usbh_msc_read (&usb_host, drv, sector, buff, count); + + if (!udev->host.connect_status) { + return RES_ERROR; + } + } while(status == USBH_BUSY); + } + + if (status == USBH_OK) { + return RES_OK; + } + + return RES_ERROR; +} + +#if _READONLY == 0U + +/*! + \brief write sectors + \param[in] drv: physical drive number (0) + \param[in] buff: pointer to the data buffer to store read data + \param[in] sector: start sector number (LBA) + \param[in] count: sector count (1..255) + \param[out] none + \retval operation status +*/ +DRESULT disk_write (BYTE drv, const BYTE *buff, DWORD sector, UINT count) +{ + BYTE status = USBH_OK; + usb_core_driver *udev = (usb_core_driver *)usb_host.data; + + if ((!count) || drv) { + return RES_PARERR; + } + + if (state & STA_NOINIT) { + return RES_NOTRDY; + } + + if (state & STA_PROTECT) { + return RES_WRPRT; + } + + if (udev->host.connect_status) { + do { + status = usbh_msc_write (&usb_host, drv, sector, (BYTE*)buff, count); + + if (!udev->host.connect_status) { + return RES_ERROR; + } + } while(status == USBH_BUSY); + } + + if (status == USBH_OK) { + return RES_OK; + } + + return RES_ERROR; +} + +#endif /* _READONLY == 0 */ + +/*! + \brief I/O control function + \param[in] drv: physical drive number (0) + \param[in] ctrl: control code + \param[in] buff: pointer to the data buffer to store read data + \param[out] none + \retval operation status +*/ +DRESULT disk_ioctl (BYTE drv, BYTE ctrl, void *buff) +{ + DRESULT res = RES_OK; + msc_lun info; + + if (drv) { + return RES_PARERR; + } + + res = RES_ERROR; + + if (state & STA_NOINIT) { + return RES_NOTRDY; + } + + switch (ctrl) { + /* make sure that no pending write process */ + case CTRL_SYNC: + res = RES_OK; + break; + + /* get number of sectors on the disk (dword) */ + case GET_SECTOR_COUNT: + if (USBH_OK == usbh_msc_lun_info_get(&usb_host, drv, &info)) { + *(DWORD*)buff = (DWORD)info.capacity.block_nbr; + res = RES_OK; + } + break; + + /* get r/w sector size (word) */ + case GET_SECTOR_SIZE: + if (USBH_OK == usbh_msc_lun_info_get(&usb_host, drv, &info)) { + *(WORD*)buff = (DWORD)info.capacity.block_size; + res = RES_OK; + } + break; + + /* get erase block size in unit of sector (dword) */ + case GET_BLOCK_SIZE: + *(DWORD*)buff = 512U; + break; + + default: + res = RES_PARERR; + break; + } + + return res; +} + +/*! + \brief get fat time + \param[in] none + \param[out] none + \retval time value +*/ +DWORD get_fattime(void) { + + return ((DWORD)(2019U - 1980U) << 25U) /* year 2019 */ + | ((DWORD)1U << 21U) /* month 1 */ + | ((DWORD)1U << 16U) /* day 1 */ + | ((DWORD)0U << 11U) /* hour 0 */ + | ((DWORD)0U << 5U) /* min 0 */ + | ((DWORD)0U >> 1U); /* sec 0 */ +} diff --git a/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/host/class/msc/Source/usbh_msc_scsi.c b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/host/class/msc/Source/usbh_msc_scsi.c new file mode 100644 index 0000000000..1439698467 --- /dev/null +++ b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/host/class/msc/Source/usbh_msc_scsi.c @@ -0,0 +1,400 @@ +/*! + \file usbh_msc_scsi.c + \brief USB MSC SCSI commands implementing + + \version 2020-07-28, V3.0.0, firmware for GD32F20x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "usbh_msc_core.h" +#include "usbh_msc_scsi.h" +#include "usbh_msc_bbb.h" + +#include + +/*! + \brief send 'Inquiry' command to the device + \param[in] uhost: pointer to usb host handler + \param[in] lun: logic unit number + \param[in] inquiry: pointer to the inquiry structure + \param[out] none + \retval operation status +*/ +usbh_status usbh_msc_scsi_inquiry (usbh_host *uhost, uint8_t lun, scsi_std_inquiry_data *inquiry) +{ + usbh_status error = USBH_FAIL; + usbh_msc_handler *msc = (usbh_msc_handler *)uhost->active_class->class_data; + + switch (msc->bot.cmd_state) { + case BOT_CMD_SEND: + /* prepare the cbw and relevant field*/ + msc->bot.cbw.field.dCBWDataTransferLength = STANDARD_INQUIRY_DATA_LEN; + msc->bot.cbw.field.bmCBWFlags = USB_TRX_IN; + msc->bot.cbw.field.bCBWCBLength = CBW_LENGTH; + + memset(msc->bot.cbw.field.CBWCB, 0U, CBW_LENGTH); + + msc->bot.cbw.field.CBWCB[0] = SCSI_INQUIRY; + msc->bot.cbw.field.CBWCB[1] = (lun << 5U); + msc->bot.cbw.field.CBWCB[4] = 0x24U; + + msc->bot.state = BOT_SEND_CBW; + msc->bot.cmd_state = BOT_CMD_WAIT; + msc->bot.pbuf = (uint8_t *)(void *)msc->bot.data; + error = USBH_BUSY; + break; + + case BOT_CMD_WAIT: + error = usbh_msc_bot_process(uhost, lun); + + if (USBH_OK == error) { + memset(inquiry, 0U, sizeof(scsi_std_inquiry_data)); + + /* assign inquiry data */ + inquiry->device_type = msc->bot.pbuf[0] & 0x1FU; + inquiry->peripheral_qualifier = msc->bot.pbuf[0] >> 5U; + + if (0x80U == ((uint32_t)msc->bot.pbuf[1] & 0x80U)) { + inquiry->removable_media = 1U; + } else { + inquiry->removable_media = 0U; + } + + memcpy (inquiry->vendor_id, &msc->bot.pbuf[8], 8U); + memcpy (inquiry->product_id, &msc->bot.pbuf[16], 16U); + memcpy (inquiry->revision_id, &msc->bot.pbuf[32], 4U); + } + break; + + default: + break; + } + + return error; +} + +/*! + \brief send 'Test unit ready' command to the device + \param[in] uhost: pointer to USB host handler + \param[in] lun: logic unit number + \param[out] none + \retval operation status +*/ +usbh_status usbh_msc_test_unitready (usbh_host *uhost, uint8_t lun) +{ + usbh_status status = USBH_FAIL; + usbh_msc_handler *msc = (usbh_msc_handler *)uhost->active_class->class_data; + + + switch (msc->bot.cmd_state) { + case BOT_CMD_SEND: + /* prepare the CBW and relevant field */ + msc->bot.cbw.field.dCBWDataTransferLength = CBW_LENGTH_TEST_UNIT_READY; + msc->bot.cbw.field.bmCBWFlags = USB_TRX_OUT; + msc->bot.cbw.field.bCBWCBLength = CBW_LENGTH; + + memset(msc->bot.cbw.field.CBWCB, 0U, CBW_CB_LENGTH); + + msc->bot.cbw.field.CBWCB[0] = SCSI_TEST_UNIT_READY; + msc->bot.state = BOT_SEND_CBW; + msc->bot.cmd_state = BOT_CMD_WAIT; + + status = USBH_BUSY; + break; + + case BOT_CMD_WAIT: + status = usbh_msc_bot_process(uhost, lun); + break; + + default: + break; + } + + return status; +} + +/*! + \brief send the read capacity command to the device + \param[in] uhost: pointer to usb host handler + \param[in] lun: logic unit number + \param[in] capacity: pointer to SCSI capacity + \param[out] none + \retval operation status +*/ +usbh_status usbh_msc_read_capacity10 (usbh_host *uhost, uint8_t lun, scsi_capacity *capacity) +{ + usbh_status status = USBH_FAIL; + usbh_msc_handler *msc = (usbh_msc_handler *)uhost->active_class->class_data; + + switch (msc->bot.cmd_state) { + case BOT_CMD_SEND: + /* prepare the CBW and relevant field */ + msc->bot.cbw.field.dCBWDataTransferLength = READ_CAPACITY10_DATA_LEN; + msc->bot.cbw.field.bmCBWFlags = USB_TRX_IN; + msc->bot.cbw.field.bCBWCBLength = CBW_LENGTH; + + memset(msc->bot.cbw.field.CBWCB, 0U, CBW_CB_LENGTH); + + msc->bot.cbw.field.CBWCB[0] = SCSI_READ_CAPACITY10; + msc->bot.state = BOT_SEND_CBW; + msc->bot.cmd_state = BOT_CMD_WAIT; + msc->bot.pbuf = (uint8_t *)(void *)msc->bot.data; + + status = USBH_BUSY; + break; + + case BOT_CMD_WAIT: + status = usbh_msc_bot_process(uhost, lun); + + if (USBH_OK == status) { + capacity->block_nbr = msc->bot.pbuf[3] | \ + ((uint32_t)msc->bot.pbuf[2] << 8U) | \ + ((uint32_t)msc->bot.pbuf[1] << 16U) | \ + ((uint32_t)msc->bot.pbuf[0] << 24U); + + capacity->block_size = (uint16_t)(msc->bot.pbuf[7] | ((uint32_t)msc->bot.pbuf[6] << 8U)); + } + break; + + default: + break; + } + + return status; +} + +/*! + \brief send the mode sense6 command to the device + \param[in] uhost: pointer to usb host handler + \param[in] lun: logic unit number + \param[out] none + \retval operation status +*/ +usbh_status usbh_msc_mode_sense6 (usbh_host *uhost, uint8_t lun) +{ + usbh_status status = USBH_FAIL; + usbh_msc_handler *msc = (usbh_msc_handler *)uhost->active_class->class_data; + + + switch (msc->bot.cmd_state) { + case BOT_CMD_SEND: + /* prepare the CBW and relevant field */ + msc->bot.cbw.field.dCBWDataTransferLength = XFER_LEN_MODE_SENSE6; + msc->bot.cbw.field.bmCBWFlags = USB_TRX_IN; + msc->bot.cbw.field.bCBWCBLength = CBW_LENGTH; + + memset(msc->bot.cbw.field.CBWCB, 0U, CBW_CB_LENGTH); + + msc->bot.cbw.field.CBWCB[0] = SCSI_MODE_SENSE6; + msc->bot.cbw.field.CBWCB[2] = MODE_SENSE_PAGE_CONTROL_FIELD | MODE_SENSE_PAGE_CODE; + msc->bot.cbw.field.CBWCB[4] = XFER_LEN_MODE_SENSE6; + msc->bot.state = BOT_SEND_CBW; + msc->bot.cmd_state = BOT_CMD_WAIT; + msc->bot.pbuf = (uint8_t *)(void *)msc->bot.data; + + status = USBH_BUSY; + break; + + case BOT_CMD_WAIT: + status = usbh_msc_bot_process(uhost, lun); + + if (USBH_OK == status) { + if (msc->bot.data[2] & MASK_MODE_SENSE_WRITE_PROTECT) { + + } else { + + } + } + break; + + default: + break; + } + + + return status; +} + +/*! + \brief send the Request Sense command to the device + \param[in] uhost: pointer to usb host handler + \param[in] lun: logic unit number + \param[in] sense_data: pointer to sense data + \param[out] none + \retval operation status +*/ +usbh_status usbh_msc_request_sense (usbh_host *uhost, uint8_t lun, msc_scsi_sense *sense_data) +{ + usbh_status status = USBH_FAIL; + usbh_msc_handler *msc = (usbh_msc_handler *)uhost->active_class->class_data; + + switch (msc->bot.cmd_state) { + case BOT_CMD_SEND: + /* prepare the cbw and relevant field */ + msc->bot.cbw.field.dCBWDataTransferLength = ALLOCATION_LENGTH_REQUEST_SENSE; + msc->bot.cbw.field.bmCBWFlags = USB_TRX_IN; + msc->bot.cbw.field.bCBWCBLength = CBW_LENGTH; + + memset(msc->bot.cbw.field.CBWCB, 0U, CBW_CB_LENGTH); + + msc->bot.cbw.field.CBWCB[0] = SCSI_REQUEST_SENSE; + msc->bot.cbw.field.CBWCB[1] = (lun << 5U); + msc->bot.cbw.field.CBWCB[4] = ALLOCATION_LENGTH_REQUEST_SENSE; + + msc->bot.state = BOT_SEND_CBW; + msc->bot.cmd_state = BOT_CMD_WAIT; + msc->bot.pbuf = (uint8_t *)(void *)msc->bot.data; + + status = USBH_BUSY; + break; + + case BOT_CMD_WAIT: + status = usbh_msc_bot_process(uhost, lun); + + if (status == USBH_OK) { + /* get sense data */ + sense_data->SenseKey = msc->bot.pbuf[2] & 0x0FU; + sense_data->ASC = msc->bot.pbuf[12]; + sense_data->ASCQ = msc->bot.pbuf[13]; + } + break; + + default: + break; + } + + return status; +} + +/*! + \brief send the write10 command to the device + \param[in] uhost: pointer to usb host handler + \param[in] lun: logic unit number + \param[in] data_buf: data buffer contains the data to write + \param[in] addr: address to which the data will be written + \param[in] sector_num: number of sector to be written + \param[out] none + \retval operation status +*/ +usbh_status usbh_msc_write10 (usbh_host *uhost, uint8_t lun, uint8_t *data_buf, uint32_t addr, uint32_t sector_num) +{ + usbh_status status = USBH_FAIL; + usbh_msc_handler *msc = (usbh_msc_handler *)uhost->active_class->class_data; + + switch (msc->bot.cmd_state) { + case BOT_CMD_SEND: + msc->bot.cbw.field.dCBWDataTransferLength = sector_num * msc->unit[lun].capacity.block_size; + msc->bot.cbw.field.bmCBWFlags = USB_TRX_OUT; + msc->bot.cbw.field.bCBWCBLength = CBW_LENGTH; + + memset(msc->bot.cbw.field.CBWCB, 0U, CBW_CB_LENGTH); + + msc->bot.cbw.field.CBWCB[0] = SCSI_WRITE10; + + /* logical block address */ + msc->bot.cbw.field.CBWCB[2] = (((uint8_t*)&addr)[3]); + msc->bot.cbw.field.CBWCB[3] = (((uint8_t*)&addr)[2]); + msc->bot.cbw.field.CBWCB[4] = (((uint8_t*)&addr)[1]); + msc->bot.cbw.field.CBWCB[5] = (((uint8_t*)&addr)[0]); + + /* transfer length */ + msc->bot.cbw.field.CBWCB[7] = (((uint8_t *)§or_num)[1]); + msc->bot.cbw.field.CBWCB[8] = (((uint8_t *)§or_num)[0]); + + msc->bot.state = BOT_SEND_CBW; + msc->bot.cmd_state = BOT_CMD_WAIT; + msc->bot.pbuf = data_buf; + + status = USBH_BUSY; + break; + + case BOT_CMD_WAIT: + status = usbh_msc_bot_process(uhost, lun); + break; + + default: + break; + } + + return status; +} + +/*! + \brief send the read10 command to the device + \param[in] uhost: pointer to usb host handler + \param[in] lun: logic unit number + \param[in] data_buf: data buffer contains the data to write + \param[in] addr: address to which the data will be read + \param[in] sector_num: number of sector to be read + \param[out] none + \retval operation status +*/ +usbh_status usbh_msc_read10 (usbh_host *uhost, uint8_t lun, uint8_t *data_buf, uint32_t addr, uint32_t sector_num) +{ + usbh_status status = USBH_FAIL; + usbh_msc_handler *msc = (usbh_msc_handler *)uhost->active_class->class_data; + + switch (msc->bot.cmd_state) { + case BOT_CMD_SEND: + /* prepare the CBW and relevant field */ + msc->bot.cbw.field.dCBWDataTransferLength = sector_num * msc->unit[lun].capacity.block_size; + msc->bot.cbw.field.bmCBWFlags = USB_TRX_IN; + msc->bot.cbw.field.bCBWCBLength = CBW_LENGTH; + + memset(msc->bot.cbw.field.CBWCB, 0U, CBW_CB_LENGTH); + + msc->bot.cbw.field.CBWCB[0] = SCSI_READ10; + + /* logical block address */ + msc->bot.cbw.field.CBWCB[2] = (((uint8_t*)&addr)[3]); + msc->bot.cbw.field.CBWCB[3] = (((uint8_t*)&addr)[2]); + msc->bot.cbw.field.CBWCB[4] = (((uint8_t*)&addr)[1]); + msc->bot.cbw.field.CBWCB[5] = (((uint8_t*)&addr)[0]); + + /* transfer length */ + msc->bot.cbw.field.CBWCB[7] = (((uint8_t *)§or_num)[1]); + msc->bot.cbw.field.CBWCB[8] = (((uint8_t *)§or_num)[0]); + + msc->bot.state = BOT_SEND_CBW; + msc->bot.cmd_state = BOT_CMD_WAIT; + msc->bot.pbuf = data_buf; + + status = USBH_BUSY; + break; + + case BOT_CMD_WAIT: + status = usbh_msc_bot_process(uhost, lun); + break; + + default: + break; + } + + return status; +} diff --git a/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/host/core/Include/usbh_core.h b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/host/core/Include/usbh_core.h new file mode 100644 index 0000000000..d2d6269496 --- /dev/null +++ b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/host/core/Include/usbh_core.h @@ -0,0 +1,274 @@ +/*! + \file usbh_core.h + \brief USB host core state machine header file + + \version 2020-07-28, V3.0.0, firmware for GD32F20x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef __USBH_CORE_H +#define __USBH_CORE_H + +#include "usbh_conf.h" +#include "drv_usb_host.h" + +#define MSC_CLASS 0x08U +#define HID_CLASS 0x03U +#define MSC_PROTOCOL 0x50U +#define CBI_PROTOCOL 0x01U + +#define USBH_MAX_ERROR_COUNT 3U + +#define USBH_DEV_ADDR_DEFAULT 0U +#define USBH_DEV_ADDR 1U + +typedef enum +{ + USBH_OK = 0U, + USBH_BUSY, + USBH_FAIL, + USBH_NOT_SUPPORTED, + USBH_UNRECOVERED_ERROR, + USBH_SPEED_UNKNOWN_ERROR, + USBH_APPLY_DEINIT +} usbh_status; + +/* USB host global operation state */ +typedef enum +{ + HOST_DEFAULT = 0U, + HOST_DETECT_DEV_SPEED, + HOST_DEV_ATTACHED, + HOST_DEV_DETACHED, + HOST_ENUM, + HOST_SET_WAKEUP_FEATURE, + HOST_CHECK_CLASS, + HOST_CLASS_ENUM, + HOST_CLASS_HANDLER, + HOST_USER_INPUT, + HOST_SUSPENDED, + HOST_WAKEUP, + HOST_ERROR +} usb_host_state; + +/* USB host enumeration state */ +typedef enum +{ + ENUM_DEFAULT = 0U, + ENUM_GET_DEV_DESC, + ENUM_SET_ADDR, + ENUM_GET_CFG_DESC, + ENUM_GET_CFG_DESC_SET, + ENUM_GET_STR_DESC, +#ifdef USB_MTP + ENUM_GET_MTP_STR, +#endif + ENUM_SET_CONFIGURATION, + ENUM_DEV_CONFIGURED +} usbh_enum_state; + +/* USB host control transfer state */ +typedef enum +{ + CTL_IDLE = 0U, + CTL_SETUP, + CTL_SETUP_WAIT, + CTL_DATA_IN, + CTL_DATA_IN_WAIT, + CTL_DATA_OUT, + CTL_DATA_OUT_WAIT, + CTL_STATUS_IN, + CTL_STATUS_IN_WAIT, + CTL_STATUS_OUT, + CTL_STATUS_OUT_WAIT, + CTL_ERROR, + CTL_FINISH +} usbh_ctl_state; + +/* user action state */ +typedef enum +{ + USBH_USER_NO_RESP = 0U, + USBH_USER_RESP_OK = 1U, +} usbh_user_status; + +typedef enum +{ + USBH_PORT_EVENT = 1U, + USBH_URB_EVENT, + USBH_CONTROL_EVENT, + USBH_CLASS_EVENT, + USBH_STATE_CHANGED_EVENT, +}usbh_os_event; + +/* control transfer information */ +typedef struct _usbh_control +{ + uint8_t pipe_in_num; + uint8_t pipe_out_num; + uint8_t max_len; + uint8_t error_count; + + uint8_t *buf; + uint16_t ctl_len; + uint16_t timer; + + usb_setup setup; + usbh_ctl_state ctl_state; +} usbh_control; + +/* USB interface descriptor set */ +typedef struct _usb_desc_itf_set +{ + usb_desc_itf itf_desc; + usb_desc_ep ep_desc[USBH_MAX_EP_NUM]; +} usb_desc_itf_set; + +/* USB configure descriptor set */ +typedef struct _usb_desc_cfg_set +{ + usb_desc_config cfg_desc; + usb_desc_itf_set itf_desc_set[USBH_MAX_INTERFACES_NUM][USBH_MAX_ALT_SETTING]; +} usb_desc_cfg_set; + +/* USB device property */ +typedef struct +{ + uint8_t data[USBH_DATA_BUF_MAX_LEN]; /* if DMA is used, the data array must be located in the first position */ + uint8_t cur_itf; + uint8_t addr; + + uint32_t speed; + + usb_desc_dev dev_desc; + usb_desc_cfg_set cfg_desc_set; + +#if (USBH_KEEP_CFG_DESCRIPTOR == 1U) + uint8_t cfgdesc_rawdata[USBH_CFGSET_MAX_LEN]; +#endif /* (USBH_KEEP_CFG_DESCRIPTOR == 1U) */ +} usb_dev_prop; + +struct _usbh_host; + +/* device class callbacks */ +typedef struct +{ + uint8_t class_code; /*!< USB class type */ + + usbh_status (*class_init) (struct _usbh_host *phost); + void (*class_deinit) (struct _usbh_host *phost); + usbh_status (*class_requests) (struct _usbh_host *phost); + usbh_status (*class_machine) (struct _usbh_host *phost); + usbh_status (*class_sof) (struct _usbh_host *uhost); + + void *class_data; +} usbh_class; + +/* user callbacks */ +typedef struct +{ + void (*dev_init) (void); + void (*dev_deinit) (void); + void (*dev_attach) (void); + void (*dev_reset) (void); + void (*dev_detach) (void); + void (*dev_over_currented) (void); + void (*dev_speed_detected) (uint32_t dev_speed); + void (*dev_devdesc_assigned) (void *dev_desc); + void (*dev_address_set) (void); + + void (*dev_cfgdesc_assigned) (usb_desc_config *cfg_desc, + usb_desc_itf *itf_desc, + usb_desc_ep *ep_desc); + + void (*dev_mfc_str) (void *mfc_str); + void (*dev_prod_str) (void *prod_str); + void (*dev_seral_str) (void *serial_str); + void (*dev_enumerated) (void); + usbh_user_status (*dev_user_input) (void); + int (*dev_user_app) (void); + void (*dev_not_supported) (void); + void (*dev_error) (void); +} usbh_user_cb; + +/* host information */ +typedef struct _usbh_host +{ + usb_host_state cur_state; /*!< host state machine value */ + usb_host_state backup_state; /*!< backup of previous state machine value */ + usbh_enum_state enum_state; /*!< enumeration state machine */ + usbh_control control; /*!< USB host control state machine */ + usb_dev_prop dev_prop; /*!< USB device property */ + + usbh_class *uclass[USBH_MAX_SUPPORTED_CLASS]; /*!< USB host supported class */ + usbh_class *active_class; /*!< USB active class */ + usbh_user_cb *usr_cb; /*!< USB user callback */ + + uint8_t class_num; /*!< USB class number */ + + void *data; /*!< used for... */ +} usbh_host; + +/*! + \brief get USB URB state + \param[in] udev: pointer to USB core instance + \param[in] pp_num: pipe number + \param[out] none + \retval none +*/ +static inline usb_urb_state usbh_urbstate_get (usb_core_driver *udev, uint8_t pp_num) +{ + return udev->host.pipe[pp_num].urb_state; +} + +/*! + \brief get USB transfer data count + \param[in] udev: pointer to USB core instance + \param[in] pp_num: pipe number + \param[out] none + \retval none +*/ +static inline uint32_t usbh_xfercount_get (usb_core_driver *udev, uint8_t pp_num) +{ + return udev->host.backup_xfercount[pp_num]; +} + +/* function declarations */ +/* USB host stack initializations */ +void usbh_init (usbh_host *uhost, usbh_user_cb *user_cb); +/* USB host register device class */ +usbh_status usbh_class_register (usbh_host *uhost, usbh_class *puclass); +/* deinitialize USB host */ +usbh_status usbh_deinit (usbh_host *uhost); +/* USB host core main state machine process */ +void usbh_core_task (usbh_host *uhost); +/* handle the error on USB host side */ +void usbh_error_handler (usbh_host *uhost, usbh_status err_type); + +#endif /* __USBH_CORE_H */ diff --git a/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/host/core/Include/usbh_enum.h b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/host/core/Include/usbh_enum.h new file mode 100644 index 0000000000..084c2879c2 --- /dev/null +++ b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/host/core/Include/usbh_enum.h @@ -0,0 +1,71 @@ +/*! + \file usbh_enum.h + \brief USB host mode USB enumeration header file + + \version 2020-07-28, V3.0.0, firmware for GD32F20x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef __USBH_ENUM_H +#define __USBH_ENUM_H + +#include "usb_conf.h" +#include "usbh_core.h" + +/* function declarations */ +/* configure USB control status parameters */ +void usbh_ctlstate_config (usbh_host *uhost, uint8_t *buf, uint16_t len); +/* get device descriptor from the USB device */ +usbh_status usbh_devdesc_get (usbh_host *uhost, uint8_t len); +/* get configuration descriptor from the USB device */ +usbh_status usbh_cfgdesc_get (usbh_host *uhost, uint16_t len); +/* get string descriptor from the USB device */ +usbh_status usbh_strdesc_get (usbh_host *uhost,uint8_t str_index, uint8_t *buf, uint16_t len); +/* set the address to the connected device */ +usbh_status usbh_setaddress (usbh_host *uhost, uint8_t dev_addr); +/* set the configuration value to the connected device */ +usbh_status usbh_setcfg (usbh_host *uhost, uint16_t config); +/* set the interface value to the connected device */ +usbh_status usbh_setinterface (usbh_host *uhost, uint8_t itf_num, uint8_t alter_setting); +/* set or enable a specific device feature */ +usbh_status usbh_setdevfeature (usbh_host *uhost, uint8_t feature_selector, uint16_t windex); +/* clear or disable a specific device feature */ +usbh_status usbh_clrdevfeature (usbh_host *uhost, uint8_t feature_selector, uint16_t windex); +/* clear or disable a specific feature */ +usbh_status usbh_clrfeature (usbh_host *uhost, uint8_t ep_addr, uint8_t pp_num); +/* get the next descriptor header */ +usb_desc_header *usbh_nextdesc_get (uint8_t *pbuf, uint16_t *ptr); +/* select an interface */ +usbh_status usbh_interface_select (usb_dev_prop *udev, uint8_t interface); +/* find the interface index for a specific class */ +uint8_t usbh_interface_find (usb_dev_prop *udev, uint8_t main_class, uint8_t sub_class, uint8_t protocol); +/* find the interface index for a specific class interface and alternate setting number */ +uint8_t usbh_interfaceindex_find (usb_dev_prop *udev, uint8_t interface_number, uint8_t alt_settings); + +#endif /* __USBH_ENUM_H */ diff --git a/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/host/core/Include/usbh_pipe.h b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/host/core/Include/usbh_pipe.h new file mode 100644 index 0000000000..91d17f4266 --- /dev/null +++ b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/host/core/Include/usbh_pipe.h @@ -0,0 +1,100 @@ +/*! + \file usbh_pipe.h + \brief USB host mode pipe header file + + \version 2020-07-28, V3.0.0, firmware for GD32F20x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef __USBH_PIPE_H +#define __USBH_PIPE_H + +#include "usbh_core.h" + +#define HC_MAX 8U + +#define HC_OK 0x0000U +#define HC_USED 0x8000U +#define HC_ERROR 0xFFFFU +#define HC_USED_MASK 0x7FFFU + +/*! + \brief set toggle for a pipe + \param[in] udev: pointer to USB core instance + \param[in] pp_num: pipe number + \param[in] toggle: toggle (0/1) + \param[out] none + \retval operation status +*/ +__STATIC_INLINE void usbh_pipe_toggle_set (usb_core_driver *udev, uint8_t pp_num, uint8_t toggle) +{ + if (udev->host.pipe[pp_num].ep.dir) { + udev->host.pipe[pp_num].data_toggle_in = toggle; + } else { + udev->host.pipe[pp_num].data_toggle_out = toggle; + } +} + +/*! + \brief get toggle flag of pipe + \param[in] udev: pointer to USB core instance + \param[in] pp_num: pipe number + \param[out] none + \retval operation status +*/ +__STATIC_INLINE uint8_t usbh_pipe_toggle_get (usb_core_driver *udev, uint8_t pp_num) +{ + if (udev->host.pipe[pp_num].ep.dir) { + return udev->host.pipe[pp_num].data_toggle_in; + } else { + return udev->host.pipe[pp_num].data_toggle_out; + } +} + +/* function declarations */ +/* create a pipe */ +uint8_t usbh_pipe_create (usb_core_driver *udev, + usb_dev_prop *dev, + uint8_t pp_num, + uint8_t ep_type, + uint16_t ep_mpl); +/* modify a pipe */ +uint8_t usbh_pipe_update (usb_core_driver *udev, + uint8_t pp_num, + uint8_t dev_addr, + uint32_t dev_speed, + uint16_t ep_mpl); +/* allocate a new pipe */ +uint8_t usbh_pipe_allocate (usb_core_driver *udev, uint8_t ep_addr); +/* free a pipe */ +uint8_t usbh_pipe_free (usb_core_driver *udev, uint8_t pp_num); +/* delete all USB host pipe */ +uint8_t usbh_pipe_delete (usb_core_driver *udev); + +#endif /* __USBH_PIPE_H */ diff --git a/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/host/core/Include/usbh_transc.h b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/host/core/Include/usbh_transc.h new file mode 100644 index 0000000000..677a9598a6 --- /dev/null +++ b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/host/core/Include/usbh_transc.h @@ -0,0 +1,51 @@ +/*! + \file usbh_transc.h + \brief USB host mode transactions header file + + \version 2020-07-28, V3.0.0, firmware for GD32F20x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef __USBH_TRANSC_H +#define __USBH_TRANSC_H + +#include "usb_conf.h" +#include "usbh_core.h" + +/* function declarations */ +/* send the setup packet to the USB device */ +usbh_status usbh_ctlsetup_send (usb_core_driver *udev, uint8_t *buf, uint8_t pp_num); +/* send a data packet to the USB device */ +usbh_status usbh_data_send (usb_core_driver *udev, uint8_t *buf, uint8_t pp_num, uint16_t len); +/* receive a data packet from the USB device */ +usbh_status usbh_data_recev (usb_core_driver *udev, uint8_t *buf, uint8_t pp_num, uint16_t len); +/* USB control transfer handler */ +usbh_status usbh_ctl_handler (usbh_host *uhost); + +#endif /* __USBH_TRANSC_H */ diff --git a/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/host/core/Source/usbh_core.c b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/host/core/Source/usbh_core.c new file mode 100644 index 0000000000..2758d2a4b0 --- /dev/null +++ b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/host/core/Source/usbh_core.c @@ -0,0 +1,650 @@ +/*! + \file usbh_core.c + \brief USB host core state machine driver + + \version 2020-07-28, V3.0.0, firmware for GD32F20x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "drv_usb_hw.h" +#include "usbh_pipe.h" +#include "usbh_enum.h" +#include "usbh_core.h" +#include "drv_usbh_int.h" +#include + +usb_core_driver usbh_core; + +/* local function prototypes ('static') */ +static uint8_t usbh_sof (usbh_host *uhost); +static uint8_t usbh_connect (usbh_host *uhost); +static uint8_t usbh_disconnect (usbh_host *uhost); +static uint8_t usbh_port_enabled (usbh_host *uhost); +static uint8_t usbh_port_disabled (usbh_host *uhost); +static usbh_status usbh_enum_task (usbh_host *uhost); + +#ifdef USB_FS_LOW_PWR_ENABLE +static void usb_hwp_suspend(usb_core_driver *udev); +static void usb_hwp_resume(usb_core_driver *udev); +#endif + +usbh_int_cb usbh_int_op = +{ + usbh_connect, + usbh_disconnect, + usbh_port_enabled, + usbh_port_disabled, + usbh_sof +}; + +usbh_int_cb *usbh_int_fop = &usbh_int_op; + +/*! + \brief USB host stack initializations + \param[in] uhost: pointer to USB host + \param[in] user_cb: pointer to user callback + \param[out] none + \retval none +*/ +void usbh_init (usbh_host *uhost, usbh_user_cb *user_cb) +{ + /* host deinitialization */ + usbh_deinit(uhost); + + uhost->usr_cb = user_cb; + + usbh_core.host.connect_status = 0U; + + for (uint8_t i = 0U; i < USBFS_MAX_TX_FIFOS; i++) { + usbh_core.host.pipe[i].err_count = 0U; + usbh_core.host.pipe[i].pp_status = PIPE_IDLE; + usbh_core.host.backup_xfercount[i] = 0U; + } + + usbh_core.host.pipe[0].ep.mps = 8U; + +#ifdef USE_USB_FS + usb_basic_init (&usbh_core.bp, &usbh_core.regs, USB_CORE_ENUM_FS); +#endif /* USE_USB_FS */ + +#ifndef DUAL_ROLE_MODE_ENABLED + usb_globalint_disable(&usbh_core.regs); + + usb_core_init (usbh_core.bp, &usbh_core.regs); + +#ifndef USE_OTG_MODE + usb_curmode_set (&usbh_core.regs, HOST_MODE); +#endif /* USE_OTG_MODE */ + + usb_host_init (&usbh_core); + + usb_globalint_enable(&usbh_core.regs); +#endif /* DUAL_ROLE_MODE_ENABLED */ + + /* link driver to the stack */ + usbh_core.host.data = (void *)uhost; + uhost->data = (void *)&usbh_core; + + /* upon initialize call usr call back */ + uhost->usr_cb->dev_init(); +} + +/*! + \brief USB host register device class + \param[in] uhost: pointer to usb host instance + \param[in] puclass: pointer to USB device class + \param[out] none + \retval operation status +*/ +usbh_status usbh_class_register (usbh_host *uhost, usbh_class *puclass) +{ + usbh_status status = USBH_OK; + + if (NULL != puclass) { + if (uhost->class_num < USBH_MAX_SUPPORTED_CLASS) { + uhost->uclass[uhost->class_num++] = puclass; + } else { + status = USBH_FAIL; + } + } else { + status = USBH_FAIL; + } + + return status; +} + +/*! + \brief deinitialize USB host + \param[in] uhost: pointer to USB host + \param[out] none + \retval operation status +*/ +usbh_status usbh_deinit(usbh_host *uhost) +{ + /* software initialize */ + uhost->cur_state = HOST_DEFAULT; + uhost->backup_state = HOST_DEFAULT; + uhost->enum_state = ENUM_DEFAULT; + + uhost->control.ctl_state = CTL_IDLE; + uhost->control.max_len = USB_FS_EP0_MAX_LEN; + + uhost->dev_prop.addr = USBH_DEV_ADDR_DEFAULT; + uhost->dev_prop.speed = PORT_SPEED_FULL; + uhost->dev_prop.cur_itf = 0xFFU; + + usbh_pipe_free(&usbh_core, uhost->control.pipe_in_num); + usbh_pipe_free(&usbh_core, uhost->control.pipe_out_num); + + return USBH_OK; +} + +/*! + \brief USB host core main state machine process + \param[in] uhost: pointer to USB host + \param[out] none + \retval none +*/ +void usbh_core_task (usbh_host *uhost) +{ + volatile usbh_status status = USBH_FAIL; + + /* check for host port events */ + if (((0U == usbh_core.host.connect_status) || (0U == usbh_core.host.port_enabled)) && (HOST_DEFAULT != uhost->cur_state)) { + if (uhost->cur_state != HOST_DEV_DETACHED) { + uhost->cur_state = HOST_DEV_DETACHED; + } + } + + switch (uhost->cur_state) { + case HOST_DEFAULT: + if (usbh_core.host.connect_status) { + uhost->cur_state = HOST_DETECT_DEV_SPEED; + + usb_mdelay (100U); + + usb_port_reset (&usbh_core); + + uhost->usr_cb->dev_reset(); + } + break; + + case HOST_DETECT_DEV_SPEED: + if (usbh_core.host.port_enabled) { + uhost->cur_state = HOST_DEV_ATTACHED; + + uhost->dev_prop.speed = usb_curspeed_get (&usbh_core); + + uhost->usr_cb->dev_speed_detected(uhost->dev_prop.speed); + + usb_mdelay (50U); + } + break; + + case HOST_DEV_ATTACHED: + uhost->usr_cb->dev_attach(); + uhost->control.pipe_out_num = usbh_pipe_allocate(&usbh_core, 0x00U); + uhost->control.pipe_in_num = usbh_pipe_allocate(&usbh_core, 0x80U); + + /* open IN control pipe */ + usbh_pipe_create (&usbh_core, + &uhost->dev_prop, + uhost->control.pipe_in_num, + USB_EPTYPE_CTRL, + (uint16_t)uhost->control.max_len); + + /* open OUT control pipe */ + usbh_pipe_create (&usbh_core, + &uhost->dev_prop, + uhost->control.pipe_out_num, + USB_EPTYPE_CTRL, + (uint16_t)uhost->control.max_len); + + uhost->cur_state = HOST_ENUM; + break; + + case HOST_ENUM: + /* check for enumeration status */ + if (USBH_OK == usbh_enum_task (uhost)) { + /* the function shall return USBH_OK when full enumeration is complete */ + + /* user callback for end of device basic enumeration */ + uhost->usr_cb->dev_enumerated(); + +#ifdef USB_FS_LOW_PWR_ENABLE + uhost->cur_state = HOST_SUSPENDED; +#else + uhost->cur_state = HOST_SET_WAKEUP_FEATURE; +#endif + } + break; + + case HOST_SET_WAKEUP_FEATURE: + if ((uhost->dev_prop.cfg_desc_set.cfg_desc.bmAttributes) & (1U << 5)) { + if (usbh_setdevfeature(uhost, FEATURE_SELECTOR_REMOTEWAKEUP, 0U) == USBH_OK) { + uhost->cur_state = HOST_CHECK_CLASS; + } + } else { + uhost->cur_state = HOST_CHECK_CLASS; + } + break; + + case HOST_CHECK_CLASS: + if (uhost->class_num == 0U) { + uhost->cur_state = HOST_ERROR; + } else { + uhost->active_class = NULL; + + uint8_t itf_class = uhost->dev_prop.cfg_desc_set.itf_desc_set[0][0].itf_desc.bInterfaceClass; + + for (uint8_t index = 0U; index < uhost->class_num; index++) { + if ((uhost->uclass[index]->class_code == itf_class) || (0xFFU == itf_class)) { + uhost->active_class = uhost->uclass[index]; + } + } + + if (uhost->active_class != NULL) { + uhost->cur_state = HOST_USER_INPUT; + } else { + uhost->cur_state = HOST_ERROR; + } + } + break; + + case HOST_USER_INPUT: + /* the function should return user response true to move to class state */ + if (USBH_USER_RESP_OK == uhost->usr_cb->dev_user_input()) { + if ((USBH_OK == uhost->active_class->class_init(uhost))) { + uhost->cur_state = HOST_CLASS_ENUM; + } + } + break; + +#ifdef USB_FS_LOW_PWR_ENABLE + case HOST_SUSPENDED: + if (USBH_OK == usbh_setdevfeature(uhost, FEATURE_SELECTOR_DEV, 0U)) { + uhost->suspend_flag = 1; + usb_hwp_suspend(uhost->data); + uhost->usr_cb->dev_user_input(); + pmu_to_deepsleepmode(PMU_LDO_LOWPOWER, WFI_CMD); + uhost->cur_state = HOST_WAKEUP; + } + break; + + case HOST_WAKEUP: + if (USBH_OK == usbh_clrdevfeature(uhost, FEATURE_SELECTOR_DEV, 0U)) { + /* user callback for initialization */ + uhost->usr_cb->dev_init(); + + uhost->cur_state = HOST_CHECK_CLASS; + } + break; +#endif + + case HOST_CLASS_ENUM: + /* process class standard control requests state machine */ + status = uhost->active_class->class_requests(uhost); + + if (USBH_OK == status) { + uhost->cur_state = HOST_CLASS_HANDLER; + } else { + usbh_error_handler (uhost, status); + } + break; + + case HOST_CLASS_HANDLER: + /* process class state machine */ + status = uhost->active_class->class_machine(uhost); + + usbh_error_handler (uhost, status); + break; + + case HOST_ERROR: + /* re-initialize host for new enumeration */ + usbh_deinit (uhost); + uhost->usr_cb->dev_deinit(); + uhost->active_class->class_deinit(uhost); + break; + + case HOST_DEV_DETACHED: + /* manage user disconnect operations*/ + uhost->usr_cb->dev_detach(); + + /* re-initialize host for new enumeration */ + usbh_deinit(uhost); + uhost->usr_cb->dev_deinit(); + uhost->active_class->class_deinit(uhost); + usbh_pipe_delete(&usbh_core); + uhost->cur_state = HOST_DEFAULT; + break; + + default: + break; + } +} + +/*! + \brief handle the error on USB host side + \param[in] uhost: pointer to USB host + \param[in] err_type: type of error or busy/OK state + \param[out] none + \retval none +*/ +void usbh_error_handler (usbh_host *uhost, usbh_status err_type) +{ + /* error unrecovered or not supported device speed */ + if ((USBH_SPEED_UNKNOWN_ERROR == err_type) || (USBH_UNRECOVERED_ERROR == err_type)) { + uhost->usr_cb->dev_error(); + + uhost->cur_state = HOST_ERROR; + } else if (USBH_APPLY_DEINIT == err_type) { + uhost->cur_state = HOST_ERROR; + + /* user callback for initialization */ + uhost->usr_cb->dev_init(); + } else { + /* no operation */ + } +} + +/*! + \brief USB SOF callback function from the interrupt + \param[in] uhost: pointer to usb host + \param[out] none + \retval operation status +*/ +static uint8_t usbh_sof (usbh_host *uhost) +{ + /* this callback could be used to implement a scheduler process */ + uhost->control.timer = (uint16_t)usb_curframe_get(&usbh_core); + + if (uhost->active_class != NULL) { + if (uhost->active_class->class_sof != NULL) { + uhost->active_class->class_sof(uhost); + } + } + + return 0U; +} + +/*! + \brief USB connect callback function from the interrupt + \param[in] uhost: pointer to usb host + \param[out] none + \retval operation status +*/ +static uint8_t usbh_connect (usbh_host *uhost) +{ + usbh_core.host.connect_status = 1U; + + return 0U; +} + +/*! + \brief USB disconnect callback function from the interrupt + \param[in] uhost: pointer to usb host + \param[out] none + \retval operation status +*/ +static uint8_t usbh_disconnect (usbh_host *uhost) +{ + usbh_core.host.connect_status = 0U; + + return 0U; +} + +/*! + \brief USB port enable callback function from the interrupt + \param[in] uhost: pointer to usb host + \param[out] none + \retval operation status +*/ +static uint8_t usbh_port_enabled (usbh_host *uhost) +{ + usbh_core.host.port_enabled = 1U; + + return 0U; +} + +/*! + \brief USB port disabled callback function from the interrupt + \param[in] uhost: pointer to usb host + \param[out] none + \retval operation status +*/ +static uint8_t usbh_port_disabled (usbh_host *uhost) +{ + usbh_core.host.port_enabled = 0U; + + return 0U; +} + +/*! + \brief handle the USB enumeration task + \param[in] uhost: pointer to host + \param[out] none + \retval none +*/ +static usbh_status usbh_enum_task (usbh_host *uhost) +{ + uint8_t str_buf[64]; + + usbh_status status = USBH_BUSY; + + static uint8_t index_mfc_str = 0U, index_prod_str = 0U, index_serial_str = 0U; + + switch (uhost->enum_state) { + case ENUM_DEFAULT: + /* get device descriptor for only 1st 8 bytes : to get ep0 maxpacketsize */ + if (USBH_OK == usbh_devdesc_get (uhost, 8U)) { + uhost->control.max_len = uhost->dev_prop.dev_desc.bMaxPacketSize0; + + /* modify control channels configuration for maximum packet size */ + usbh_pipe_update (&usbh_core, + uhost->control.pipe_out_num, + 0U, 0U, + (uint16_t)uhost->control.max_len); + + usbh_pipe_update (&usbh_core, + uhost->control.pipe_in_num, + 0U, 0U, + (uint16_t)uhost->control.max_len); + + uhost->enum_state = ENUM_GET_DEV_DESC; + } + break; + + case ENUM_GET_DEV_DESC: + /* get full device descriptor */ + if (USBH_OK == usbh_devdesc_get (uhost, USB_DEV_DESC_LEN)) { + uhost->usr_cb->dev_devdesc_assigned(&uhost->dev_prop.dev_desc); + + index_mfc_str = uhost->dev_prop.dev_desc.iManufacturer; + index_prod_str = uhost->dev_prop.dev_desc.iProduct; + index_serial_str = uhost->dev_prop.dev_desc.iSerialNumber; + + uhost->enum_state = ENUM_SET_ADDR; + } + break; + + case ENUM_SET_ADDR: + /* set address */ + if (USBH_OK == usbh_setaddress (uhost, USBH_DEV_ADDR)) { + usb_mdelay (2U); + + uhost->dev_prop.addr = USBH_DEV_ADDR; + + /* user callback for device address assigned */ + uhost->usr_cb->dev_address_set(); + + /* modify control channels to update device address */ + usbh_pipe_update (&usbh_core, + uhost->control.pipe_in_num, + uhost->dev_prop.addr, + 0U, 0U); + + usbh_pipe_update (&usbh_core, + uhost->control.pipe_out_num, + uhost->dev_prop.addr, + 0U, 0U); + + uhost->enum_state = ENUM_GET_CFG_DESC; + } + break; + + case ENUM_GET_CFG_DESC: + /* get standard configuration descriptor */ + if (USBH_OK == usbh_cfgdesc_get (uhost, USB_CFG_DESC_LEN)) { + uhost->enum_state = ENUM_GET_CFG_DESC_SET; + } + break; + + case ENUM_GET_CFG_DESC_SET: + /* get full configure descriptor (config, interface, endpoints) */ + if (USBH_OK == usbh_cfgdesc_get (uhost, uhost->dev_prop.cfg_desc_set.cfg_desc.wTotalLength)) { + /* user callback for configuration descriptors available */ + uhost->usr_cb->dev_cfgdesc_assigned (&uhost->dev_prop.cfg_desc_set.cfg_desc, + &uhost->dev_prop.cfg_desc_set.itf_desc_set[0][0].itf_desc, + &uhost->dev_prop.cfg_desc_set.itf_desc_set[0][0].ep_desc[0]); + + uhost->enum_state = ENUM_GET_STR_DESC; + } + break; + + case ENUM_GET_STR_DESC: + if (index_mfc_str) { + if (USBH_OK == usbh_strdesc_get (uhost, + uhost->dev_prop.dev_desc.iManufacturer, + str_buf, + 0xFFU)) { + /* user callback for manufacturing string */ + uhost->usr_cb->dev_mfc_str(str_buf); + + index_mfc_str = 0U; + } + } else { + if (index_prod_str) { + /* check that product string is available */ + if (USBH_OK == usbh_strdesc_get (uhost, + uhost->dev_prop.dev_desc.iProduct, + str_buf, + 0xFFU)) { + uhost->usr_cb->dev_prod_str(str_buf); + + index_prod_str = 0U; + } + } else { + if (index_serial_str) { + if (USBH_OK == usbh_strdesc_get (uhost, + uhost->dev_prop.dev_desc.iSerialNumber, + str_buf, + 0xFFU)) { + uhost->usr_cb->dev_seral_str(str_buf); + uhost->enum_state = ENUM_SET_CONFIGURATION; + index_serial_str = 0U; + } + } else { + uhost->enum_state = ENUM_SET_CONFIGURATION; + } + } + } + break; + + case ENUM_SET_CONFIGURATION: + if (USBH_OK == usbh_setcfg (uhost, (uint16_t)uhost->dev_prop.cfg_desc_set.cfg_desc.bConfigurationValue)) { + uhost->enum_state = ENUM_DEV_CONFIGURED; + } + break; + + case ENUM_DEV_CONFIGURED: + status = USBH_OK; + break; + + default: + break; + } + + return status; +} + + +#ifdef USB_FS_LOW_PWR_ENABLE + +/*! + \brief handles the USB resume from suspend mode + \param[in] udev: pointer to selected USB device + \param[out] none + \retval none +*/ +static void usb_hwp_resume(usb_core_driver *udev) +{ + __IO uint32_t hprt = 0U; + + /* switch-on the clocks */ + *udev->regs.PWRCLKCTL &= ~PWRCLKCTL_SUCLK; + + *udev->regs.PWRCLKCTL &= ~PWRCLKCTL_SHCLK; + + hprt = usb_port_read(udev); + + hprt &= ~HPCS_PSP; + hprt |= HPCS_PREM; + + *udev->regs.HPCS = hprt; + + usb_mdelay (20U); + + hprt &= ~HPCS_PREM; + + *udev->regs.HPCS = hprt; +} + +/*! + \brief handles the USB enter to suspend mode + \param[in] udev: pointer to selected USB device + \param[out] none + \retval none +*/ +static void usb_hwp_suspend(usb_core_driver *udev) +{ + __IO uint32_t hprt = 0U; + + hprt = usb_port_read(udev); + + hprt |= HPCS_PSP; + + *udev->regs.HPCS = hprt; + + /* switch-off the clocks */ + *udev->regs.PWRCLKCTL |= PWRCLKCTL_SUCLK; + + *udev->regs.PWRCLKCTL |= PWRCLKCTL_SHCLK; +} + +#endif diff --git a/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/host/core/Source/usbh_enum.c b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/host/core/Source/usbh_enum.c new file mode 100644 index 0000000000..98c6c5ce8b --- /dev/null +++ b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/host/core/Source/usbh_enum.c @@ -0,0 +1,693 @@ +/*! + \file usbh_enum.c + \brief USB host mode enumberation driver + + \version 2020-07-28, V3.0.0, firmware for GD32F20x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "usbh_pipe.h" +#include "usbh_transc.h" +#include "usbh_enum.h" + +/* local function prototypes ('static') */ +static void usbh_devdesc_parse (usb_desc_dev *dev_desc, uint8_t *buf, uint16_t len); +static void usbh_cfgdesc_parse (usb_desc_config *cfg_desc, uint8_t *buf); +static void usbh_cfgset_parse (usb_dev_prop *udev, uint8_t *buf); +static void usbh_itfdesc_parse (usb_desc_itf *itf_desc, uint8_t *buf); +static void usbh_epdesc_parse (usb_desc_ep *ep_desc, uint8_t *buf); +static void usbh_strdesc_parse (uint8_t *psrc, uint8_t *pdest, uint16_t len); + +/*! + \brief configure USB control status parameters + \param[in] uhost: pointer to usb host + \param[in] buf: control transfer data buffer pointer + \param[in] len: length of the data buffer + \param[out] none + \retval none +*/ +void usbh_ctlstate_config (usbh_host *uhost, uint8_t *buf, uint16_t len) +{ + /* prepare the transactions */ + uhost->control.buf = buf; + uhost->control.ctl_len = len; + + uhost->control.ctl_state = CTL_SETUP; +} + +/*! + \brief get device descriptor from the USB device + \param[in] uhost: pointer to usb host + \param[in] len: length of the descriptor + \param[out] none + \retval operation status +*/ +usbh_status usbh_devdesc_get (usbh_host *uhost, uint8_t len) +{ + usbh_status status = USBH_BUSY; + + usbh_control *usb_ctl = &uhost->control; + + if (CTL_IDLE == usb_ctl->ctl_state) { + usb_ctl->setup.req = (usb_req) { + .bmRequestType = USB_TRX_IN | USB_RECPTYPE_DEV | USB_REQTYPE_STRD, + .bRequest = USB_GET_DESCRIPTOR, + .wValue = USBH_DESC(USB_DESCTYPE_DEV), + .wIndex = 0U, + .wLength = len + }; + + usbh_ctlstate_config (uhost, uhost->dev_prop.data, (uint16_t)len); + } + + status = usbh_ctl_handler (uhost); + + if (USBH_OK == status) { + /* commands successfully sent and response received */ + usbh_devdesc_parse (&uhost->dev_prop.dev_desc, uhost->dev_prop.data, (uint16_t)len); + } + + return status; +} + +/*! + \brief get configuration descriptor from the USB device + \param[in] uhost: pointer to usb host + \param[in] len: length of the descriptor + \param[out] none + \retval operation status +*/ +usbh_status usbh_cfgdesc_get (usbh_host *uhost, uint16_t len) +{ + uint8_t *pdata = NULL; + + usbh_status status = USBH_BUSY; + + usbh_control *usb_ctl = &uhost->control; + +#if (USBH_KEEP_CFG_DESCRIPTOR == 1U) + pdata = uhost->dev_prop.cfgdesc_rawdata; +#else + pdata = uhost->dev_prop.data; +#endif + + if (CTL_IDLE == usb_ctl->ctl_state) { + usb_ctl->setup.req = (usb_req) { + .bmRequestType = USB_TRX_IN | USB_RECPTYPE_DEV | USB_REQTYPE_STRD, + .bRequest = USB_GET_DESCRIPTOR, + .wValue = USBH_DESC(USB_DESCTYPE_CONFIG), + .wIndex = 0U, + .wLength = len + }; + + usbh_ctlstate_config (uhost, pdata, len); + } + + status = usbh_ctl_handler (uhost); + + if (USBH_OK == status) { + if (len <= USB_CFG_DESC_LEN) { + usbh_cfgdesc_parse (&uhost->dev_prop.cfg_desc_set.cfg_desc, pdata); + } else { + usbh_cfgset_parse (&uhost->dev_prop, pdata); + } + } + + return status; +} + +/*! + \brief get string descriptor from the USB device + \param[in] uhost: pointer to usb host + \param[in] str_index: index for the string descriptor + \param[in] buf: buffer pointer to the string descriptor + \param[in] len: length of the descriptor + \param[out] none + \retval operation status +*/ +usbh_status usbh_strdesc_get (usbh_host *uhost, + uint8_t str_index, + uint8_t *buf, + uint16_t len) +{ + usbh_status status = USBH_BUSY; + + usbh_control *usb_ctl = &uhost->control; + + if (CTL_IDLE == usb_ctl->ctl_state) { + usb_ctl->setup.req = (usb_req) { + .bmRequestType = USB_TRX_IN | USB_RECPTYPE_DEV | USB_REQTYPE_STRD, + .bRequest = USB_GET_DESCRIPTOR, + .wValue = USBH_DESC(USB_DESCTYPE_STR) | str_index, + .wIndex = 0x0409U, + .wLength = len + }; + + usbh_ctlstate_config (uhost, uhost->dev_prop.data, len); + } + + status = usbh_ctl_handler (uhost); + + if (USBH_OK == status) { + /* commands successfully sent and response received */ + usbh_strdesc_parse (uhost->dev_prop.data, buf, len); + } + + return status; +} + +/*! + \brief set the address to the connected device + \param[in] uhost: pointer to usb host + \param[in] dev_addr: device address to assign + \param[out] none + \retval operation status +*/ +usbh_status usbh_setaddress (usbh_host *uhost, uint8_t dev_addr) +{ + usbh_status status = USBH_BUSY; + + usbh_control *usb_ctl = &uhost->control; + + if (CTL_IDLE == usb_ctl->ctl_state) { + usb_ctl->setup.req = (usb_req) { + .bmRequestType = USB_TRX_OUT | USB_RECPTYPE_DEV | USB_REQTYPE_STRD, + .bRequest = USB_SET_ADDRESS, + .wValue = (uint16_t)dev_addr, + .wIndex = 0U, + .wLength = 0U + }; + + usbh_ctlstate_config (uhost, NULL, 0U); + } + + status = usbh_ctl_handler (uhost); + + return status; +} + +/*! + \brief set the configuration value to the connected device + \param[in] uhost: pointer to usb host + \param[in] config_index: configuration value + \param[out] none + \retval operation status +*/ +usbh_status usbh_setcfg (usbh_host *uhost, uint16_t config_index) +{ + usbh_status status = USBH_BUSY; + + usbh_control *usb_ctl = &uhost->control; + + if (CTL_IDLE == usb_ctl->ctl_state) { + usb_ctl->setup.req = (usb_req) { + .bmRequestType = USB_TRX_OUT | USB_RECPTYPE_DEV | USB_REQTYPE_STRD, + .bRequest = USB_SET_CONFIGURATION, + .wValue = config_index, + .wIndex = 0U, + .wLength = 0U + }; + + usbh_ctlstate_config (uhost, NULL, 0U); + } + + status = usbh_ctl_handler (uhost); + + return status; +} + +/*! + \brief set the interface value to the connected device + \param[in] uhost: pointer to usb host + \param[in] itf_num: interface number + \param[in] set: alternated setting value + \param[out] none + \retval operation status +*/ +usbh_status usbh_setinterface (usbh_host *uhost, uint8_t itf_num, uint8_t set) +{ + usbh_status status = USBH_BUSY; + + usbh_control *usb_ctl = &uhost->control; + + if (CTL_IDLE == usb_ctl->ctl_state) { + usb_ctl->setup.req = (usb_req) { + .bmRequestType = USB_TRX_OUT | USB_RECPTYPE_ITF | USB_REQTYPE_STRD, + .bRequest = USB_SET_INTERFACE, + .wValue = set, + .wIndex = itf_num, + .wLength = 0U + }; + + usbh_ctlstate_config (uhost, NULL, 0U); + } + + status = usbh_ctl_handler (uhost); + + return status; +} + +/*! + \brief set the interface value to the connected device + \param[in] uhost: pointer to usb host + \param[in] feature_selector: feature selector + \param[in] windex: index value + \param[out] none + \retval operation status +*/ +usbh_status usbh_setdevfeature (usbh_host *uhost, uint8_t feature_selector, uint16_t windex) +{ + usbh_status status = USBH_BUSY; + + usbh_control *usb_ctl = &uhost->control; + + if (CTL_IDLE == usb_ctl->ctl_state) { + usb_ctl->setup.req = (usb_req) { + .bmRequestType = USB_TRX_OUT | USB_RECPTYPE_DEV | USB_REQTYPE_STRD, + .bRequest = USB_SET_FEATURE, + .wValue = feature_selector, + .wIndex = windex, + .wLength = 0U + }; + + usbh_ctlstate_config (uhost, NULL, 0U); + } + + status = usbh_ctl_handler (uhost); + + return status; +} + +/*! + \brief clear the interface value to the connected device + \param[in] uhost: pointer to usb host + \param[in] feature_selector: feature selector + \param[in] windex: index value + \param[out] none + \retval operation status +*/ +usbh_status usbh_clrdevfeature (usbh_host *uhost, uint8_t feature_selector, uint16_t windex) +{ + usbh_status status = USBH_BUSY; + + usbh_control *usb_ctl = &uhost->control; + + if (CTL_IDLE == usb_ctl->ctl_state) { + usb_ctl->setup.req = (usb_req) { + .bmRequestType = USB_TRX_OUT | USB_RECPTYPE_DEV | USB_REQTYPE_STRD, + .bRequest = USB_CLEAR_FEATURE, + .wValue = feature_selector, + .wIndex = windex, + .wLength = 0U + }; + + usbh_ctlstate_config (uhost, NULL, 0U); + } + + status = usbh_ctl_handler (uhost); + + return status; +} + +/*! + \brief clear or disable a specific feature + \param[in] uhost: pointer to usb host + \param[in] ep_addr: endpoint address + \param[in] pp_num: pipe number + \param[out] none + \retval operation status +*/ +usbh_status usbh_clrfeature (usbh_host *uhost, uint8_t ep_addr, uint8_t pp_num) +{ + usbh_status status = USBH_BUSY; + usbh_control *usb_ctl = &uhost->control; + usb_core_driver *udev = (usb_core_driver *)uhost->data; + + if (CTL_IDLE == usb_ctl->ctl_state) { + usb_ctl->setup.req = (usb_req) { + .bmRequestType = USB_TRX_OUT | USB_RECPTYPE_EP | USB_REQTYPE_STRD, + .bRequest = USB_CLEAR_FEATURE, + .wValue = FEATURE_SELECTOR_EP, + .wIndex = ep_addr, + .wLength = 0U + }; + + if (EP_ID(ep_addr) == udev->host.pipe[pp_num].ep.num) { + usbh_pipe_toggle_set(udev, pp_num, 0U); + } else { + return USBH_FAIL; + } + + usbh_ctlstate_config (uhost, NULL, 0U); + } + + status = usbh_ctl_handler (uhost); + + return status; +} + +/*! + \brief get the next descriptor header + \param[in] pbuf: pointer to buffer where the configuration descriptor set is available + \param[in] ptr: data pointer inside the configuration descriptor set + \param[out] none + \retval return descriptor header +*/ +usb_desc_header *usbh_nextdesc_get (uint8_t *pbuf, uint16_t *ptr) +{ + usb_desc_header *pnext; + + *ptr += ((usb_desc_header *)pbuf)->bLength; + + pnext = (usb_desc_header *)((uint8_t *)pbuf + ((usb_desc_header *)pbuf)->bLength); + + return (pnext); +} + +/*! + \brief get the next descriptor header + \param[in] udev: pointer to device property + \param[in] interface: interface number + \param[out] none + \retval operation status +*/ +usbh_status usbh_interface_select (usb_dev_prop *udev, uint8_t interface) +{ + usbh_status status = USBH_OK; + + if (interface < udev->cfg_desc_set.cfg_desc.bNumInterfaces) { + udev->cur_itf = interface; + } else { + status = USBH_FAIL; + } + + return status; +} + +/*! + \brief find the interface index for a specific class + \param[in] udev: pointer to device property + \param[in] main_class: class code + \param[in] sub_class: subclass code + \param[in] protocol: Protocol code + \param[out] none + \retval interface index in the configuration structure + \note interface index 0xFF means interface index not found +*/ +uint8_t usbh_interface_find (usb_dev_prop *udev, uint8_t main_class, uint8_t sub_class, uint8_t protocol) +{ + usb_desc_itf *pif; + + uint8_t if_ix = 0U; + + pif = (usb_desc_itf *)0; + + while (if_ix < udev->cfg_desc_set.cfg_desc.bNumInterfaces) { + pif = &udev->cfg_desc_set.itf_desc_set[if_ix][0].itf_desc; + + if (((pif->bInterfaceClass == main_class) || (main_class == 0xFFU))&& + ((pif->bInterfaceSubClass == sub_class) || (sub_class == 0xFFU))&& + ((pif->bInterfaceProtocol == protocol) || (protocol == 0xFFU))) { + return if_ix; + } + + if_ix++; + } + + return 0xFFU; +} + +/*! + \brief find the interface index for a specific class interface and alternate setting number + \param[in] udev: pointer to device property + \param[in] interface_number: interface number + \param[in] alt_settings: alternate setting number + \param[out] none + \retval interface index in the configuration structure + \note interface index 0xFF means interface index not found +*/ +uint8_t usbh_interfaceindex_find (usb_dev_prop *udev, uint8_t interface_number, uint8_t alt_settings) +{ + usb_desc_itf *pif; + + uint8_t if_ix = 0U; + + pif = (usb_desc_itf *)0; + + while (if_ix < USBH_MAX_INTERFACES_NUM) { + pif = &udev->cfg_desc_set.itf_desc_set[if_ix][alt_settings].itf_desc; + + if ((pif->bInterfaceNumber == interface_number) && (pif->bAlternateSetting == alt_settings)) { + return if_ix; + } + + if_ix++; + } + + return 0xFFU; +} + +/*! + \brief parse the device descriptor + \param[in] dev_desc: pointer to usb device descriptor buffer + \param[in] buf: pointer to the source descriptor buffer + \param[in] len: length of the descriptor + \param[out] none + \retval none +*/ +static void usbh_devdesc_parse (usb_desc_dev *dev_desc, uint8_t *buf, uint16_t len) +{ + *dev_desc = (usb_desc_dev) { + .header = { + .bLength = *(uint8_t *)(buf + 0U), + .bDescriptorType = *(uint8_t *)(buf + 1U) + }, + + .bcdUSB = BYTE_SWAP(buf + 2U), + .bDeviceClass = *(uint8_t *)(buf + 4U), + .bDeviceSubClass = *(uint8_t *)(buf + 5U), + .bDeviceProtocol = *(uint8_t *)(buf + 6U), + .bMaxPacketSize0 = *(uint8_t *)(buf + 7U) + }; + + if (len > 8U) { + /* for 1st time after device connection, host may issue only 8 bytes for device descriptor length */ + dev_desc->idVendor = BYTE_SWAP(buf + 8U); + dev_desc->idProduct = BYTE_SWAP(buf + 10U); + dev_desc->bcdDevice = BYTE_SWAP(buf + 12U); + dev_desc->iManufacturer = *(uint8_t *)(buf + 14U); + dev_desc->iProduct = *(uint8_t *)(buf + 15U); + dev_desc->iSerialNumber = *(uint8_t *)(buf + 16U); + dev_desc->bNumberConfigurations = *(uint8_t *)(buf + 17U); + } +} + +/*! + \brief parse the configuration descriptor + \param[in] cfg_desc: pointer to usb configuration descriptor buffer + \param[in] buf: pointer to the source descriptor buffer + \param[out] none + \retval none +*/ +static void usbh_cfgdesc_parse (usb_desc_config *cfg_desc, uint8_t *buf) +{ + /* parse configuration descriptor */ + *cfg_desc = (usb_desc_config) { + .header = { + .bLength = *(uint8_t *)(buf + 0U), + .bDescriptorType = *(uint8_t *)(buf + 1U), + }, + + .wTotalLength = BYTE_SWAP(buf + 2U), + .bNumInterfaces = *(uint8_t *)(buf + 4U), + .bConfigurationValue = *(uint8_t *)(buf + 5U), + .iConfiguration = *(uint8_t *)(buf + 6U), + .bmAttributes = *(uint8_t *)(buf + 7U), + .bMaxPower = *(uint8_t *)(buf + 8U) + }; +} + +/*! + \brief parse the configuration descriptor set + \param[in] udev: pointer to device property + \param[in] buf: pointer to the source descriptor buffer + \param[out] none + \retval none +*/ +static void usbh_cfgset_parse (usb_dev_prop *udev, uint8_t *buf) +{ + usb_desc_ep *ep = NULL; + usb_desc_itf_set *itf = NULL; + usb_desc_itf itf_value; + usb_desc_config *cfg = NULL; + + usb_desc_header *pdesc = (usb_desc_header *)buf; + + uint8_t itf_index = 0U, ep_index = 0U, alt_setting = 0U; + uint8_t pre_itf_index = 0U; + uint16_t ptr; + + /* parse configuration descriptor */ + usbh_cfgdesc_parse (&udev->cfg_desc_set.cfg_desc, buf); + cfg = &udev->cfg_desc_set.cfg_desc; + ptr = USB_CFG_DESC_LEN; + + if (cfg->bNumInterfaces > USBH_MAX_INTERFACES_NUM) { + return; + } + + while (ptr < cfg->wTotalLength) { + pdesc = usbh_nextdesc_get ((uint8_t *)pdesc, &ptr); + + if (pdesc->bDescriptorType == USB_DESCTYPE_ITF) { + itf_index = *(((uint8_t *)pdesc) + 2U); + + if (pre_itf_index != itf_index) { + alt_setting = 0U; + } + + itf = &udev->cfg_desc_set.itf_desc_set[itf_index][alt_setting]; + + alt_setting++; + + if ((*((uint8_t *)pdesc + 3U)) < 3U) { + usbh_itfdesc_parse (&itf_value, (uint8_t *)pdesc); + + /* parse endpoint descriptors relative to the current interface */ + if (itf_value.bNumEndpoints > USBH_MAX_EP_NUM) { + return; + } + + usbh_itfdesc_parse (&itf->itf_desc, (uint8_t *)&itf_value); + + /* store the previous interface index */ + pre_itf_index = itf_index; + + if (0U == itf_value.bNumEndpoints) { + continue; + } + + for (ep_index = 0U; ep_index < itf_value.bNumEndpoints; ) { + pdesc = usbh_nextdesc_get ((void*)pdesc, &ptr); + + if (pdesc->bDescriptorType == USB_DESCTYPE_EP) { + ep = &itf->ep_desc[ep_index]; + + usbh_epdesc_parse (ep, (uint8_t *)pdesc); + + ep_index++; + } + } + } + } + } +} + +/*! + \brief parse the interface descriptor + \param[in] itf_desc: pointer to usb interface descriptor buffer + \param[in] buf: pointer to the source descriptor buffer + \param[out] none + \retval none +*/ +static void usbh_itfdesc_parse (usb_desc_itf *itf_desc, uint8_t *buf) +{ + *itf_desc = (usb_desc_itf) { + .header = { + .bLength = *(uint8_t *)(buf + 0U), + .bDescriptorType = *(uint8_t *)(buf + 1U), + }, + + .bInterfaceNumber = *(uint8_t *)(buf + 2U), + .bAlternateSetting = *(uint8_t *)(buf + 3U), + .bNumEndpoints = *(uint8_t *)(buf + 4U), + .bInterfaceClass = *(uint8_t *)(buf + 5U), + .bInterfaceSubClass = *(uint8_t *)(buf + 6U), + .bInterfaceProtocol = *(uint8_t *)(buf + 7U), + .iInterface = *(uint8_t *)(buf + 8U) + }; +} + +/*! + \brief parse the endpoint descriptor + \param[in] ep_desc: pointer to usb endpoint descriptor buffer + \param[in] buf: pointer to the source descriptor buffer + \param[out] none + \retval none +*/ +static void usbh_epdesc_parse (usb_desc_ep *ep_desc, uint8_t *buf) +{ + *ep_desc = (usb_desc_ep) { + .header = { + .bLength = *(uint8_t *)(buf + 0U), + .bDescriptorType = *(uint8_t *)(buf + 1U) + }, + + .bEndpointAddress = *(uint8_t *)(buf + 2U), + .bmAttributes = *(uint8_t *)(buf + 3U), + .wMaxPacketSize = BYTE_SWAP(buf + 4U), + .bInterval = *(uint8_t *)(buf + 6U) + }; +} + +/*! + \brief parse the string descriptor + \param[in] psrc: source pointer containing the descriptor data + \param[in] pdest: destination address pointer + \param[in] len: length of the descriptor + \param[out] none + \retval none +*/ +static void usbh_strdesc_parse (uint8_t *psrc, uint8_t *pdest, uint16_t len) +{ + uint16_t str_len = 0U, index = 0U; + + /* the unicode string descriptor is not NULL-terminated. The string length is + * computed by abstracting two from the value of the first byte of the descriptor. + */ + + /* check which is lower size, the size of string or the length of bytes read from the device */ + if (USB_DESCTYPE_STR == psrc[1]) { + /* make sure the descriptor is string type */ + + /* psrc[0] contains Size of Descriptor, subtract 2 to get the length of string */ + str_len = USB_MIN((uint16_t)psrc[0] - 2U, len); + + psrc += 2U; /* adjust the offset ignoring the string len and descriptor type */ + + for (index = 0U; index < str_len; index += 2U) { + /* copy only the string and ignore the unicode id, hence add the src */ + *pdest = psrc[index]; + + pdest++; + } + + *pdest = 0U; /* mark end of string */ + } +} diff --git a/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/host/core/Source/usbh_pipe.c b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/host/core/Source/usbh_pipe.c new file mode 100644 index 0000000000..a080d1eedf --- /dev/null +++ b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/host/core/Source/usbh_pipe.c @@ -0,0 +1,174 @@ +/*! + \file usbh_pipe.c + \brief USB host mode pipe operation driver + + \version 2020-07-28, V3.0.0, firmware for GD32F20x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "usbh_pipe.h" + +/* local function prototypes ('static') */ +static uint16_t usbh_freepipe_get (usb_core_driver *udev); + +/*! + \brief create a pipe + \param[in] udev: pointer to usb core instance + \param[in] udev: USB device + \param[in] pp_num: pipe number + \param[in] ep_type: endpoint type + \param[in] ep_mpl: endpoint max packet length + \param[out] none + \retval operation status +*/ +uint8_t usbh_pipe_create (usb_core_driver *udev, + usb_dev_prop *dev, + uint8_t pp_num, + uint8_t ep_type, + uint16_t ep_mpl) +{ + usb_pipe *pp = &udev->host.pipe[pp_num]; + + pp->dev_addr = dev->addr; + pp->dev_speed = dev->speed; + pp->ep.type = ep_type; + pp->ep.mps = ep_mpl; + pp->ping = (uint8_t)(dev->speed == PORT_SPEED_HIGH); + + usb_pipe_init (udev, pp_num); + + return HC_OK; +} + +/*! + \brief modify a pipe + \param[in] udev: pointer to usb core instance + \param[in] pp_num: pipe number + \param[in] dev_addr: device address + \param[in] dev_speed: device speed + \param[in] ep_mpl: endpoint max packet length + \param[out] none + \retval operation status +*/ +uint8_t usbh_pipe_update (usb_core_driver *udev, + uint8_t pp_num, + uint8_t dev_addr, + uint32_t dev_speed, + uint16_t ep_mpl) +{ + usb_pipe *pp = &udev->host.pipe[pp_num]; + + if ((pp->dev_addr != dev_addr) && (dev_addr)) { + pp->dev_addr = dev_addr; + } + + if ((pp->dev_speed != dev_speed) && (dev_speed)) { + pp->dev_speed = dev_speed; + } + + if ((pp->ep.mps != ep_mpl) && (ep_mpl)) { + pp->ep.mps = ep_mpl; + } + + usb_pipe_init (udev, pp_num); + + return HC_OK; +} + +/*! + \brief allocate a new pipe + \param[in] udev: pointer to usb core instance + \param[in] ep_addr: endpoint address + \param[out] none + \retval operation status +*/ +uint8_t usbh_pipe_allocate (usb_core_driver *udev, uint8_t ep_addr) +{ + uint16_t pp_num = usbh_freepipe_get (udev); + + if (HC_ERROR != pp_num) { + udev->host.pipe[pp_num].in_used = 1U; + udev->host.pipe[pp_num].ep.dir = EP_DIR(ep_addr); + udev->host.pipe[pp_num].ep.num = EP_ID(ep_addr); + } + + return (uint8_t)pp_num; +} + +/*! + \brief free a pipe + \param[in] udev: pointer to usb core instance + \param[in] pp_num: pipe number + \param[out] none + \retval operation status +*/ +uint8_t usbh_pipe_free (usb_core_driver *udev, uint8_t pp_num) +{ + if (pp_num < HC_MAX) { + udev->host.pipe[pp_num].in_used = 0U; + } + + return USBH_OK; +} + +/*! + \brief delete all USB host pipe + \param[in] udev: pointer to usb core instance + \param[out] none + \retval operation status +*/ +uint8_t usbh_pipe_delete (usb_core_driver *udev) +{ + uint8_t pp_num = 0U; + + for (pp_num = 2U; pp_num < HC_MAX; pp_num++) { + udev->host.pipe[pp_num] = (usb_pipe) {0}; + } + + return USBH_OK; +} + +/*! + \brief get a free pipe number for allocation + \param[in] udev: pointer to usb core instance + \param[out] none + \retval operation status +*/ +static uint16_t usbh_freepipe_get (usb_core_driver *udev) +{ + uint8_t pp_num = 0U; + + for (pp_num = 0U; pp_num < HC_MAX; pp_num++) { + if (0U == udev->host.pipe[pp_num].in_used) { + return (uint16_t)pp_num; + } + } + + return HC_ERROR; +} diff --git a/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/host/core/Source/usbh_transc.c b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/host/core/Source/usbh_transc.c new file mode 100644 index 0000000000..a69cedfdcc --- /dev/null +++ b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/host/core/Source/usbh_transc.c @@ -0,0 +1,371 @@ +/*! + \file usbh_transc.c + \brief USB host mode transactions driver + + \version 2020-07-28, V3.0.0, firmware for GD32F20x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "drv_usb_hw.h" +#include "usbh_pipe.h" +#include "usbh_transc.h" + +/* local function prototypes ('static') */ +static usb_urb_state usbh_urb_wait (usbh_host *uhost, uint8_t pp_num, uint32_t wait_time); +static void usbh_setup_transc (usbh_host *uhost); +static void usbh_data_in_transc (usbh_host *uhost); +static void usbh_data_out_transc (usbh_host *uhost); +static void usbh_status_in_transc (usbh_host *uhost); +static void usbh_status_out_transc (usbh_host *uhost); +static uint32_t usbh_request_submit (usb_core_driver *udev, uint8_t pp_num); + +/*! + \brief send the setup packet to the USB device + \param[in] udev: pointer to usb core instance + \param[in] buf: data buffer which will be sent to USB device + \param[in] pp_num: pipe number + \param[out] none + \retval operation status +*/ +usbh_status usbh_ctlsetup_send (usb_core_driver *udev, uint8_t *buf, uint8_t pp_num) +{ + usb_pipe *pp = &udev->host.pipe[pp_num]; + + pp->DPID = PIPE_DPID_SETUP; + pp->xfer_buf = buf; + pp->xfer_len = USB_SETUP_PACKET_LEN; + + return (usbh_status)usbh_request_submit (udev, pp_num); +} + +/*! + \brief send a data packet to the USB device + \param[in] udev: pointer to usb core instance + \param[in] buf: data buffer which will be sent to USB device + \param[in] pp_num: pipe number + \param[in] len: length of the data to be sent + \param[out] none + \retval operation status +*/ +usbh_status usbh_data_send (usb_core_driver *udev, uint8_t *buf, uint8_t pp_num, uint16_t len) +{ + usb_pipe *pp = &udev->host.pipe[pp_num]; + + pp->xfer_buf = buf; + pp->xfer_len = len; + + switch (pp->ep.type) { + case USB_EPTYPE_CTRL: + if (0U == len) { + pp->data_toggle_out = 1U; + } + + pp->DPID = PIPE_DPID[pp->data_toggle_out]; + break; + + case USB_EPTYPE_INTR: + pp->DPID = PIPE_DPID[pp->data_toggle_out]; + + pp->data_toggle_out ^= 1U; + break; + + case USB_EPTYPE_BULK: + pp->DPID = PIPE_DPID[pp->data_toggle_out]; + break; + + case USB_EPTYPE_ISOC: + pp->DPID = PIPE_DPID[0]; + break; + + default: + break; + } + + usbh_request_submit (udev, pp_num); + + return USBH_OK; +} + +/*! + \brief receive a data packet from the USB device + \param[in] udev: pointer to usb core instance + \param[in] buf: data buffer which will be received from USB device + \param[in] pp_num: pipe number + \param[in] len: length of the data to be received + \param[out] none + \retval operation status +*/ +usbh_status usbh_data_recev (usb_core_driver *udev, uint8_t *buf, uint8_t pp_num, uint16_t len) +{ + usb_pipe *pp = &udev->host.pipe[pp_num]; + + pp->xfer_buf = buf; + pp->xfer_len = len; + + switch (pp->ep.type) { + case USB_EPTYPE_CTRL: + pp->DPID = PIPE_DPID[1]; + break; + + case USB_EPTYPE_INTR: + pp->DPID = PIPE_DPID[pp->data_toggle_in]; + + /* toggle DATA PID */ + pp->data_toggle_in ^= 1U; + break; + + case USB_EPTYPE_BULK: + pp->DPID = PIPE_DPID[pp->data_toggle_in]; + break; + + case USB_EPTYPE_ISOC: + pp->DPID = PIPE_DPID[0]; + break; + + default: + break; + } + + usbh_request_submit (udev, pp_num); + + return USBH_OK; +} + +/*! + \brief USB control transfer handler + \param[in] uhost: pointer to USB host + \param[out] none + \retval operation status +*/ +usbh_status usbh_ctl_handler (usbh_host *uhost) +{ + usbh_status status = USBH_BUSY; + + switch (uhost->control.ctl_state) { + case CTL_SETUP: + usbh_setup_transc (uhost); + break; + + case CTL_DATA_IN: + usbh_data_in_transc (uhost); + break; + + case CTL_DATA_OUT: + usbh_data_out_transc (uhost); + break; + + case CTL_STATUS_IN: + usbh_status_in_transc (uhost); + break; + + case CTL_STATUS_OUT: + usbh_status_out_transc (uhost); + break; + + case CTL_FINISH: + uhost->control.ctl_state = CTL_IDLE; + + status = USBH_OK; + break; + + case CTL_ERROR: + if (++uhost->control.error_count <= USBH_MAX_ERROR_COUNT) { + /* do the transmission again, starting from SETUP packet */ + uhost->control.ctl_state = CTL_SETUP; + } else { + status = USBH_FAIL; + } + break; + + default: + break; + } + + return status; +} + +/*! + \brief wait for USB URB(USB request block) state + \param[in] uhost: pointer to USB host + \param[in] pp_num: pipe number + \param[in] wait_time: wait time + \param[out] none + \retval USB URB state +*/ +static usb_urb_state usbh_urb_wait (usbh_host *uhost, uint8_t pp_num, uint32_t wait_time) +{ + usb_urb_state urb_status = URB_IDLE; + + while (URB_DONE != (urb_status = usbh_urbstate_get(uhost->data, pp_num))) { + if (URB_NOTREADY == urb_status) { + break; + } else if (URB_STALL == urb_status) { + uhost->control.ctl_state = CTL_SETUP; + break; + } else if (URB_ERROR == urb_status) { + uhost->control.ctl_state = CTL_ERROR; + break; + } else if ((wait_time > 0U) && ((usb_curframe_get(uhost->data)- uhost->control.timer) > wait_time)) { + /* timeout for in transfer */ + uhost->control.ctl_state = CTL_ERROR; + break; + } else { + /* no operation, just wait */ + } + } + + return urb_status; +} + +/*! + \brief USB setup transaction + \param[in] uhost: pointer to USB host + \param[out] none + \retval none +*/ +static void usbh_setup_transc (usbh_host *uhost) +{ + /* send a SETUP packet */ + usbh_ctlsetup_send (uhost->data, + uhost->control.setup.data, + uhost->control.pipe_out_num); + + if (URB_DONE == usbh_urb_wait (uhost, uhost->control.pipe_out_num, 0U)) { + uint8_t dir = (uhost->control.setup.req.bmRequestType & USB_TRX_MASK); + + if (uhost->control.setup.req.wLength) { + if (USB_TRX_IN == dir) { + uhost->control.ctl_state = CTL_DATA_IN; + } else { + uhost->control.ctl_state = CTL_DATA_OUT; + } + } else { + if (USB_TRX_IN == dir) { + uhost->control.ctl_state = CTL_STATUS_OUT; + } else { + uhost->control.ctl_state = CTL_STATUS_IN; + } + } + + /* set the delay timer to enable timeout for data stage completion */ + uhost->control.timer = (uint16_t)usb_curframe_get(uhost->data); + } +} + +/*! + \brief USB data IN transaction + \param[in] uhost: pointer to USB host + \param[out] none + \retval none +*/ +static void usbh_data_in_transc (usbh_host *uhost) +{ + usbh_data_recev (uhost->data, + uhost->control.buf, + uhost->control.pipe_in_num, + uhost->control.ctl_len); + + if (URB_DONE == usbh_urb_wait (uhost, uhost->control.pipe_in_num, DATA_STAGE_TIMEOUT)) { + uhost->control.ctl_state = CTL_STATUS_OUT; + + uhost->control.timer = (uint16_t)usb_curframe_get(uhost->data); + } +} + +/*! + \brief USB data OUT transaction + \param[in] uhost: pointer to USB host + \param[out] none + \retval none +*/ +static void usbh_data_out_transc (usbh_host *uhost) +{ + usbh_pipe_toggle_set(uhost->data, uhost->control.pipe_out_num, 1U); + + usbh_data_send (uhost->data, + uhost->control.buf, + uhost->control.pipe_out_num, + uhost->control.ctl_len); + + if (URB_DONE == usbh_urb_wait (uhost, uhost->control.pipe_out_num, DATA_STAGE_TIMEOUT)) { + uhost->control.ctl_state = CTL_STATUS_IN; + + uhost->control.timer = (uint16_t)usb_curframe_get(uhost->data); + } +} + +/*! + \brief USB status IN transaction + \param[in] uhost: pointer to USB host + \param[out] none + \retval none +*/ +static void usbh_status_in_transc (usbh_host *uhost) +{ + uint8_t pp_num = uhost->control.pipe_in_num; + + usbh_data_recev (uhost->data, NULL, pp_num, 0U); + + if (URB_DONE == usbh_urb_wait (uhost, pp_num, NODATA_STAGE_TIMEOUT)) { + uhost->control.ctl_state = CTL_FINISH; + } +} + +/*! + \brief USB status OUT transaction + \param[in] uhost: pointer to USB host + \param[out] none + \retval none +*/ +static void usbh_status_out_transc (usbh_host *uhost) +{ + uint8_t pp_num = uhost->control.pipe_out_num; + + usbh_data_send (uhost->data, NULL, pp_num, 0U); + + if (URB_DONE == usbh_urb_wait (uhost, pp_num, NODATA_STAGE_TIMEOUT)) { + uhost->control.ctl_state = CTL_FINISH; + } +} + +/*! + \brief prepare a pipe and start a transfer + \param[in] udev: pointer to usb core instance + \param[in] pp_num: pipe number + \param[out] none + \retval operation status +*/ +static uint32_t usbh_request_submit (usb_core_driver *udev, uint8_t pp_num) +{ + udev->host.pipe[pp_num].urb_state = URB_IDLE; + udev->host.pipe[pp_num].xfer_count = 0U; + + return (uint32_t)usb_pipe_xfer (udev, pp_num); +} + diff --git a/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/ustd/class/cdc/usb_cdc.h b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/ustd/class/cdc/usb_cdc.h new file mode 100644 index 0000000000..2d7f3a00c4 --- /dev/null +++ b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/ustd/class/cdc/usb_cdc.h @@ -0,0 +1,180 @@ +/*! + \file usb_cdc.h + \brief the header file of communication device class standard + + \version 2020-07-28, V3.0.0, firmware for GD32F20x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef __USB_CDC_H +#define __USB_CDC_H + +#include "usb_ch9_std.h" + +/* communications device class code */ +#define USB_CLASS_CDC 0x02U + +/* communications interface class control protocol codes */ +#define USB_CDC_PROTOCOL_NONE 0x00U +#define USB_CDC_PROTOCOL_AT 0x01U +#define USB_CDC_PROTOCOL_VENDOR 0xFFU + +/* data interface class code */ +#define USB_CLASS_DATA 0x0AU + +#define USB_DESCTYPE_CDC_ACM 0x21U +#define USB_DESCTYPE_CS_INTERFACE 0x24U + +#define USB_CDC_ACM_CONFIG_DESC_SIZE 0x43U + +/* class-specific notification codes for pstn subclasses */ +#define USB_CDC_NOTIFY_SERIAL_STATE 0x20U + +/* class-specific request codes */ +#define SEND_ENCAPSULATED_COMMAND 0x00U +#define GET_ENCAPSULATED_RESPONSE 0x01U +#define SET_COMM_FEATURE 0x02U +#define GET_COMM_FEATURE 0x03U +#define CLEAR_COMM_FEATURE 0x04U + +#define SET_AUX_LINE_STATE 0x10U +#define SET_HOOK_STATE 0x11U +#define PULSE_SETUP 0x12U +#define SEND_PULSE 0x13U +#define SET_PULSE_TIME 0x14U +#define RING_AUX_JACK 0x15U + +#define SET_LINE_CODING 0x20U +#define GET_LINE_CODING 0x21U +#define SET_CONTROL_LINE_STATE 0x22U +#define SEND_BREAK 0x23U +#define NO_CMD 0xFFU + +#define SET_RINGER_PARMS 0x30U +#define GET_RINGER_PARMS 0x31U +#define SET_OPERATION_PARMS 0x32U +#define GET_OPERATION_PARMS 0x33U +#define SET_LINE_PARMS 0x34U +#define GET_LINE_PARMS 0x35U +#define DIAL_DIGITS 0x36U +#define SET_UNIT_PARAMETER 0x37U +#define GET_UNIT_PARAMETER 0x38U +#define CLEAR_UNIT_PARAMETER 0x39U +#define GET_PROFILE 0x3AU + +#define SET_ETHERNET_MULTICAST_FILTERS 0x40U +#define SET_ETHERNET_POWER_MANAGEMENT_PATTERN FILTER 0x41U +#define GET_ETHERNET_POWER_MANAGEMENT_PATTERN FILTER 0x42U +#define SET_ETHERNET_PACKET_FILTER 0x43U +#define GET_ETHERNET_STATISTIC 0x44U + +#define SET_ATM_DATA_FORMAT 0x50U +#define GET_ATM_DEVICE_STATISTICS 0x51U +#define SET_ATM_DEFAULT_VC 0x52U +#define GET_ATM_VC_STATISTICS 0x53U + +/* wValue for set control line state */ +#define CDC_ACTIVATE_CARRIER_SIGNAL_RTS 0x0002U +#define CDC_DEACTIVATE_CARRIER_SIGNAL_RTS 0x0000U +#define CDC_ACTIVATE_SIGNAL_DTR 0x0001U +#define CDC_DEACTIVATE_SIGNAL_DTR 0x0000U + +/* CDC subclass code */ +enum usb_cdc_subclass { + USB_CDC_SUBCLASS_RESERVED = 0U, /*!< reserved */ + USB_CDC_SUBCLASS_DLCM, /*!< direct line control mode */ + USB_CDC_SUBCLASS_ACM, /*!< abstract control mode */ + USB_CDC_SUBCLASS_TCM, /*!< telephone control mode */ + USB_CDC_SUBCLASS_MCM, /*!< multichannel control model */ + USB_CDC_SUBCLASS_CCM, /*!< CAPI control model */ + USB_CDC_SUBCLASS_ENCM, /*!< ethernet networking control model */ + USB_CDC_SUBCLASS_ANCM /*!< ATM networking control model */ +}; + +#pragma pack(1) + +/* cdc acm line coding structure */ +typedef struct { + uint32_t dwDTERate; /*!< data terminal rate */ + uint8_t bCharFormat; /*!< stop bits */ + uint8_t bParityType; /*!< parity */ + uint8_t bDataBits; /*!< data bits */ +} acm_line; + +/* notification structure */ +typedef struct { + uint8_t bmRequestType; /*!< type of request */ + uint8_t bNotification; /*!< communication interface class notifications */ + uint16_t wValue; /*!< value of notification */ + uint16_t wIndex; /*!< index of interface */ + uint16_t wLength; /*!< length of notification data */ +} acm_notification; + +typedef struct { + usb_desc_header header; /*!< descriptor header, including type and size. */ + uint8_t bDescriptorSubtype; /*!< bDescriptorSubtype: header function descriptor */ + uint16_t bcdCDC; /*!< bcdCDC: low byte of spec release number (CDC1.10) */ +} usb_desc_header_func; + +typedef struct { + usb_desc_header header; /*!< descriptor header, including type and size. */ + uint8_t bDescriptorSubtype; /*!< bDescriptorSubtype: call management function descriptor */ + uint8_t bmCapabilities; /*!< bmCapabilities: D0 is reset, D1 is ignored */ + uint8_t bDataInterface; /*!< bDataInterface: 1 interface used for call management */ +} usb_desc_call_managment_func; + +typedef struct { + usb_desc_header header; /*!< descriptor header, including type and size. */ + uint8_t bDescriptorSubtype; /*!< bDescriptorSubtype: abstract control management descriptor */ + uint8_t bmCapabilities; /*!< bmCapabilities: D1 */ +} usb_desc_acm_func; + +typedef struct { + usb_desc_header header; /*!< descriptor header, including type and size. */ + uint8_t bDescriptorSubtype; /*!< bDescriptorSubtype: union function descriptor */ + uint8_t bMasterInterface; /*!< bMasterInterface: communication class interface */ + uint8_t bSlaveInterface0; /*!< bSlaveInterface0: data class interface */ +} usb_desc_union_func; + +#pragma pack() + +typedef struct { + usb_desc_config config; + usb_desc_itf cmd_itf; + usb_desc_header_func cdc_header; + usb_desc_call_managment_func cdc_call_managment; + usb_desc_acm_func cdc_acm; + usb_desc_union_func cdc_union; + usb_desc_ep cdc_cmd_endpoint; + usb_desc_itf cdc_data_interface; + usb_desc_ep cdc_out_endpoint; + usb_desc_ep cdc_in_endpoint; +} usb_cdc_desc_config_set; + +#endif /* __USB_CDC_H */ diff --git a/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/ustd/class/hid/usb_hid.h b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/ustd/class/hid/usb_hid.h new file mode 100644 index 0000000000..ec00f44aed --- /dev/null +++ b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/ustd/class/hid/usb_hid.h @@ -0,0 +1,83 @@ +/*! + \file usb_hid.h + \brief definitions for the USB HID class + + \version 2020-07-28, V3.0.0, firmware for GD32F20x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef __USB_HID_H +#define __USB_HID_H + +#include "usb_ch9_std.h" + +#define USB_HID_CLASS 0x03U + +#define USB_DESCTYPE_HID 0x21U +#define USB_DESCTYPE_REPORT 0x22U + +/* HID subclass code */ +#define USB_HID_SUBCLASS_BOOT_ITF 0x01U + +/* HID protocol codes */ +#define USB_HID_PROTOCOL_KEYBOARD 0x01U +#define USB_HID_PROTOCOL_MOUSE 0x02U + +#define GET_REPORT 0x01U +#define GET_IDLE 0x02U +#define GET_PROTOCOL 0x03U +#define SET_REPORT 0x09U +#define SET_IDLE 0x0AU +#define SET_PROTOCOL 0x0BU + +#pragma pack(1) + +typedef struct +{ + usb_desc_header header; /*!< regular descriptor header containing the descriptor's type and length */ + + uint16_t bcdHID; /*!< BCD encoded version that the HID descriptor and device complies to */ + uint8_t bCountryCode; /*!< country code of the localized device, or zero if universal */ + uint8_t bNumDescriptors; /*!< total number of HID report descriptors for the interface */ + uint8_t bDescriptorType; /*!< type of HID report */ + uint16_t wDescriptorLength; /*!< length of the associated HID report descriptor, in bytes */ +} usb_desc_hid; + +#pragma pack() + +typedef struct +{ + usb_desc_config config; + usb_desc_itf hid_itf; + usb_desc_hid hid_vendor; + usb_desc_ep hid_epin; + usb_desc_ep hid_epout; +}usb_hid_desc_config_set; + +#endif /* __USB_HID_H */ diff --git a/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/ustd/class/msc/msc_bbb.h b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/ustd/class/msc/msc_bbb.h new file mode 100644 index 0000000000..1661f9351f --- /dev/null +++ b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/ustd/class/msc/msc_bbb.h @@ -0,0 +1,69 @@ +/*! + \file msc_bbb.h + \brief definitions for the USB MSC BBB(bulk/bulk/bulk) protocol + + \version 2020-07-28, V3.0.0, firmware for GD32F20x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef __MSC_BBB_H +#define __MSC_BBB_H + +#include "usb_ch9_std.h" + +#define BBB_CBW_SIGNATURE 0x43425355U +#define BBB_CSW_SIGNATURE 0x53425355U +#define BBB_CBW_LENGTH 31U +#define BBB_CSW_LENGTH 13U + +typedef struct { + uint32_t dCBWSignature; + uint32_t dCBWTag; + uint32_t dCBWDataTransferLength; + uint8_t bmCBWFlags; + uint8_t bCBWLUN; + uint8_t bCBWCBLength; + uint8_t CBWCB[16]; +}msc_bbb_cbw; + +typedef struct { + uint32_t dCSWSignature; + uint32_t dCSWTag; + uint32_t dCSWDataResidue; + uint8_t bCSWStatus; +}msc_bbb_csw; + +/* CSW command status */ +enum msc_csw_status { + CSW_CMD_PASSED = 0, + CSW_CMD_FAILED, + CSW_PHASE_ERROR +}; + +#endif /* __MSC_BBB_H */ diff --git a/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/ustd/class/msc/msc_scsi.h b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/ustd/class/msc/msc_scsi.h new file mode 100644 index 0000000000..d8e083b50c --- /dev/null +++ b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/ustd/class/msc/msc_scsi.h @@ -0,0 +1,117 @@ +/*! + \file msc_scsi.h + \brief definitions for the USB MSC SCSI commands + + \version 2020-07-28, V3.0.0, firmware for GD32F20x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef __MSC_SCSI_H +#define __MSC_SCSI_H + +#include "usb_ch9_std.h" + +/* SCSI commands */ +#define SCSI_FORMAT_UNIT 0x04U +#define SCSI_INQUIRY 0x12U +#define SCSI_MODE_SELECT6 0x15U +#define SCSI_MODE_SELECT10 0x55U +#define SCSI_MODE_SENSE6 0x1AU +#define SCSI_READ_TOC_DATA 0x43U +#define SCSI_MODE_SENSE10 0x5AU +#define SCSI_ALLOW_MEDIUM_REMOVAL 0x1EU +#define SCSI_READ6 0x08U +#define SCSI_READ10 0x28U +#define SCSI_READ12 0xA8U +#define SCSI_READ16 0x88U + +#define SCSI_READ_CAPACITY10 0x25U +#define SCSI_READ_CAPACITY16 0x9EU + +#define SCSI_REQUEST_SENSE 0x03U +#define SCSI_START_STOP_UNIT 0x1BU +#define SCSI_TEST_UNIT_READY 0x00U +#define SCSI_WRITE6 0x0AU +#define SCSI_WRITE10 0x2AU +#define SCSI_WRITE12 0xAAU +#define SCSI_WRITE16 0x8AU + +#define SCSI_VERIFY10 0x2FU +#define SCSI_VERIFY12 0xAFU +#define SCSI_VERIFY16 0x8FU + +#define SCSI_SEND_DIAGNOSTIC 0x1DU +#define SCSI_READ_FORMAT_CAPACITIES 0x23U + +#define INVALID_CDB 0x20U +#define INVALID_FIELED_IN_COMMAND 0x24U +#define PARAMETER_LIST_LENGTH_ERROR 0x1AU +#define INVALID_FIELD_IN_PARAMETER_LIST 0x26U +#define ADDRESS_OUT_OF_RANGE 0x21U +#define MEDIUM_NOT_PRESENT 0x3AU +#define MEDIUM_HAVE_CHANGED 0x28U +#define WRITE_PROTECTED 0x27U +#define UNRECOVERED_READ_ERROR 0x11U +#define WRITE_FAULT 0x03U + +#define READ_FORMAT_CAPACITY_DATA_LEN 0x0CU +#define READ_CAPACITY10_DATA_LEN 0x08U +#define MODE_SENSE10_DATA_LEN 0x08U +#define MODE_SENSE6_DATA_LEN 0x04U +#define READ_TOC_CMD_LEN 0x14U +#define REQUEST_SENSE_DATA_LEN 0x12U +#define STANDARD_INQUIRY_DATA_LEN 0x24U +#define BLKVFY 0x04U + +enum sense_state { + NO_SENSE = 0U, + RECOVERED_ERROR, + NOT_READY, + MEDIUM_ERROR, + HARDWARE_ERROR, + ILLEGAL_REQUEST, + UNIT_ATTENTION, + DATA_PROTECT, + BLANK_CHECK, + VENDOR_SPECIFIC, + COPY_ABORTED, + ABORTED_COMMAND, + RESERVED, + VOLUME_OVERFLOW, + MISCOMPARE +}; + +typedef struct { + uint8_t SenseKey; + uint32_t Information; + uint8_t ASC; + uint8_t ASCQ; +} msc_scsi_sense; + +#endif /* __MSC_SCSI_H */ diff --git a/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/ustd/class/msc/usb_msc.h b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/ustd/class/msc/usb_msc.h new file mode 100644 index 0000000000..3aa557ee21 --- /dev/null +++ b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/ustd/class/msc/usb_msc.h @@ -0,0 +1,68 @@ +/*! + \file usb_msc.h + \brief definitions for the USB MSC class + + \version 2020-07-28, V3.0.0, firmware for GD32F20x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef __USB_MSC_H +#define __USB_MSC_H + +#include "usb_ch9_std.h" + +/* mass storage device class code */ +#define USB_CLASS_MSC 0x08U + +/* mass storage subclass code */ +#define USB_MSC_SUBCLASS_RBC 0x01U +#define USB_MSC_SUBCLASS_ATAPI 0x02U +#define USB_MSC_SUBCLASS_UFI 0x04U +#define USB_MSC_SUBCLASS_SCSI 0x06U +#define USB_MSC_SUBCLASS_LOCKABLE 0x07U +#define USB_MSC_SUBCLASS_IEEE1667 0x08U + +/* mass storage interface class control protocol codes */ +#define USB_MSC_PROTOCOL_CBI 0x00U +#define USB_MSC_PROTOCOL_CBI_ALT 0x01U +#define USB_MSC_PROTOCOL_BBB 0x50U + +/* mass storage request codes */ +#define USB_MSC_REQ_CODES_ADSC 0x00U +#define USB_MSC_REQ_CODES_GET 0xFCU +#define USB_MSC_REQ_CODES_PUT 0xFDU +#define USB_MSC_REQ_CODES_GML 0xFEU +#define USB_MSC_REQ_CODES_BOMSR 0xFFU + +#define BBB_GET_MAX_LUN 0xFEU +#define BBB_RESET 0xFFU + +#define SCSI_CMD_LENGTH 16U + +#endif /* __USB_MSC_H */ diff --git a/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/ustd/common/usb_ch9_std.h b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/ustd/common/usb_ch9_std.h new file mode 100644 index 0000000000..e567e8a59e --- /dev/null +++ b/bsp/gd32/libraries/GD32F20x_Firmware_Library/GD32F20x_usbfs_library/ustd/common/usb_ch9_std.h @@ -0,0 +1,248 @@ +/*! + \file usb_ch9_std.h + \brief USB 2.0 standard defines + + \version 2020-07-28, V3.0.0, firmware for GD32F20x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef __USB_CH9_STD_H +#define __USB_CH9_STD_H + +#include "usb_conf.h" + +#define USB_DEV_QUALIFIER_DESC_LEN 0x0AU /*!< USB device qualifier descriptor length */ +#define USB_DEV_DESC_LEN 0x12U /*!< USB device descriptor length */ +#define USB_CFG_DESC_LEN 0x09U /*!< USB configuration descriptor length */ +#define USB_ITF_DESC_LEN 0x09U /*!< USB interface descriptor length */ +#define USB_EP_DESC_LEN 0x07U /*!< USB endpoint descriptor length */ +#define USB_IAD_DESC_LEN 0x08U /*!< USB IAD descriptor length */ +#define USB_OTG_DESC_LEN 0x03U /*!< USB device OTG descriptor length */ + +#define USB_SETUP_PACKET_LEN 0x08U /*!< USB setup packet length */ + +/* bit 7 of bmRequestType: data phase transfer direction */ +#define USB_TRX_MASK 0x80U /*!< USB transfer direction mask */ +#define USB_TRX_OUT 0x00U /*!< USB transfer OUT direction */ +#define USB_TRX_IN 0x80U /*!< USB transfer IN direction */ + +/* bit 6..5 of bmRequestType: request type */ +#define USB_REQTYPE_STRD 0x00U /*!< USB standard request */ +#define USB_REQTYPE_CLASS 0x20U /*!< USB class request */ +#define USB_REQTYPE_VENDOR 0x40U /*!< USB vendor request */ +#define USB_REQTYPE_MASK 0x60U /*!< USB request mask */ + +#define USBD_BUS_POWERED 0x00U /*!< USB bus power supply */ +#define USBD_SELF_POWERED 0x01U /*!< USB self power supply */ + +#define USB_STATUS_REMOTE_WAKEUP 2U /*!< USB is in remote wakeup status */ +#define USB_STATUS_SELF_POWERED 1U /*!< USB is in self powered status */ + +/* bit 4..0 of bmRequestType: recipient type */ +enum _usb_recp_type { + USB_RECPTYPE_DEV = 0x0U, /*!< USB device request type */ + USB_RECPTYPE_ITF = 0x1U, /*!< USB interface request type */ + USB_RECPTYPE_EP = 0x2U, /*!< USB endpoint request type */ + USB_RECPTYPE_MASK = 0x3U /*!< USB request type mask */ +}; + +/* bRequest value */ +enum _usb_request { + USB_GET_STATUS = 0x0U, /*!< USB get status request */ + USB_CLEAR_FEATURE = 0x1U, /*!< USB clear feature request */ + USB_RESERVED2 = 0x2U, + USB_SET_FEATURE = 0x3U, /*!< USB set feature request */ + USB_RESERVED4 = 0x4U, + USB_SET_ADDRESS = 0x5U, /*!< USB set address request */ + USB_GET_DESCRIPTOR = 0x6U, /*!< USB get descriptor request */ + USB_SET_DESCRIPTOR = 0x7U, /*!< USB set descriptor request */ + USB_GET_CONFIGURATION = 0x8U, /*!< USB get configuration request */ + USB_SET_CONFIGURATION = 0x9U, /*!< USB set configuration request */ + USB_GET_INTERFACE = 0xAU, /*!< USB get interface request */ + USB_SET_INTERFACE = 0xBU, /*!< USB set interface request */ + USB_SYNCH_FRAME = 0xCU /*!< USB synchronize frame request */ +}; + +/* descriptor types of USB specifications */ +enum _usb_desctype { + USB_DESCTYPE_DEV = 0x1U, /*!< USB device descriptor type */ + USB_DESCTYPE_CONFIG = 0x2U, /*!< USB configuration descriptor type */ + USB_DESCTYPE_STR = 0x3U, /*!< USB string descriptor type */ + USB_DESCTYPE_ITF = 0x4U, /*!< USB interface descriptor type */ + USB_DESCTYPE_EP = 0x5U, /*!< USB endpoint descriptor type */ + USB_DESCTYPE_DEV_QUALIFIER = 0x6U, /*!< USB device qualifier descriptor type */ + USB_DESCTYPE_OTHER_SPD_CONFIG = 0x7U, /*!< USB other speed configuration descriptor type */ + USB_DESCTYPE_ITF_POWER = 0x8U, /*!< USB interface power descriptor type */ + USB_DESCTYPE_IAD = 0xBU, /*!< USB interface association descriptor type */ + USB_DESCTYPE_BOS = 0xFU /*!< USB BOS descriptor type */ +}; + +/* USB Endpoint Descriptor bmAttributes bit definitions */ +/* bits 1..0 : transfer type */ +enum _usbx_type { + USB_EP_ATTR_CTL = 0x0U, /*!< USB control transfer type */ + USB_EP_ATTR_ISO = 0x1U, /*!< USB Isochronous transfer type */ + USB_EP_ATTR_BULK = 0x2U, /*!< USB Bulk transfer type */ + USB_EP_ATTR_INT = 0x3U /*!< USB Interrupt transfer type */ +}; + +/* bits 3..2 : Sync type (only if ISOCHRONOUS) */ +#define USB_EP_ATTR_NOSYNC 0x00U /*!< No Synchronization */ +#define USB_EP_ATTR_ASYNC 0x04U /*!< Asynchronous */ +#define USB_EP_ATTR_ADAPTIVE 0x08U /*!< Adaptive */ +#define USB_EP_ATTR_SYNC 0x0CU /*!< Synchronous */ +#define USB_EP_ATTR_SYNCTYPE 0x0CU /*!< Synchronous type */ + +/* bits 5..4 : usage type (only if ISOCHRONOUS) */ +#define USB_EP_ATTR_DATA 0x00U /*!< Data endpoint */ +#define USB_EP_ATTR_FEEDBACK 0x10U /*!< Feedback endpoint */ +#define USB_EP_ATTR_IMPLICIT_FEEDBACK_DATA 0x20U /*!< Implicit feedback Data endpoint */ +#define USB_EP_ATTR_USAGETYPE 0x30U /*!< Usage type */ + +/* endpoint max packet size bits12..11 */ +#define USB_EP_MPS_ADD_0 (0x00 << 11) /*!< None(1 transaction per microframe */ +#define USB_EP_MPS_ADD_1 (0x01 << 11) /*!< 1 additional(2 transaction per microframe */ +#define USB_EP_MPS_ADD_2 (0x02 << 11) /*!< 2 additional(3 transaction per microframe */ + +#define FEATURE_SELECTOR_EP 0x00U /*!< USB endpoint feature selector */ +#define FEATURE_SELECTOR_DEV 0x01U /*!< USB device feature selector */ +#define FEATURE_SELECTOR_REMOTEWAKEUP 0x01U /*!< USB feature selector remote wakeup */ + +#define BYTE_SWAP(addr) (((uint16_t)(*((uint8_t *)(addr)))) + \ + (uint16_t)(((uint16_t)(*(((uint8_t *)(addr)) + 1U))) << 8U)) + +#define BYTE_LOW(x) ((uint8_t)((x) & 0x00FFU)) +#define BYTE_HIGH(x) ((uint8_t)(((x) & 0xFF00U) >> 8U)) + +#define USB_MIN(a, b) (((a) < (b)) ? (a) : (b)) + +#define USB_DEFAULT_CONFIG 0U + +/* USB classes */ +#define USB_CLASS_HID 0x03U /*!< USB HID class */ +#define USB_CLASS_MSC 0x08U /*!< USB MSC class */ + +/* use the following values when USB host need to get descriptor */ +#define USBH_DESC(x) (((x)<< 8U) & 0xFF00U) + +/* as per USB specs 9.2.6.4 :standard request with data request timeout: 5sec + standard request with no data stage timeout : 50ms */ +#define DATA_STAGE_TIMEOUT 5000U /*!< USB data stage timeout*/ +#define NODATA_STAGE_TIMEOUT 50U /*!< USB no data stage timeout*/ + +#pragma pack(1) + +/* USB standard device request structure */ +typedef struct _usb_req { + uint8_t bmRequestType; /*!< type of request */ + uint8_t bRequest; /*!< request of setup packet */ + uint16_t wValue; /*!< value of setup packet */ + uint16_t wIndex; /*!< index of setup packet */ + uint16_t wLength; /*!< length of setup packet */ +} usb_req; + +/* USB setup packet define */ +typedef union _usb_setup { + uint8_t data[8]; + + usb_req req; +} usb_setup; + +/* USB descriptor defines */ + +typedef struct _usb_desc_header { + uint8_t bLength; /*!< size of the descriptor */ + uint8_t bDescriptorType; /*!< type of the descriptor */ +} usb_desc_header; + +typedef struct _usb_desc_dev { + usb_desc_header header; /*!< descriptor header, including type and size */ + + uint16_t bcdUSB; /*!< BCD of the supported USB specification */ + uint8_t bDeviceClass; /*!< USB device class */ + uint8_t bDeviceSubClass; /*!< USB device subclass */ + uint8_t bDeviceProtocol; /*!< USB device protocol */ + uint8_t bMaxPacketSize0; /*!< size of the control (address 0) endpoint's bank in bytes */ + uint16_t idVendor; /*!< vendor ID for the USB product */ + uint16_t idProduct; /*!< unique product ID for the USB product */ + uint16_t bcdDevice; /*!< product release (version) number */ + uint8_t iManufacturer; /*!< string index for the manufacturer's name */ + uint8_t iProduct; /*!< string index for the product name/details */ + uint8_t iSerialNumber; /*!< string index for the product's globally unique hexadecimal serial number */ + uint8_t bNumberConfigurations; /*!< total number of configurations supported by the device */ +} usb_desc_dev; + +typedef struct _usb_desc_config { + usb_desc_header header; /*!< descriptor header, including type and size */ + + uint16_t wTotalLength; /*!< size of the configuration descriptor header,and all sub descriptors inside the configuration */ + uint8_t bNumInterfaces; /*!< total number of interfaces in the configuration */ + uint8_t bConfigurationValue; /*!< configuration index of the current configuration */ + uint8_t iConfiguration; /*!< index of a string descriptor describing the configuration */ + uint8_t bmAttributes; /*!< configuration attributes */ + uint8_t bMaxPower; /*!< maximum power consumption of the device while in the current configuration */ +} usb_desc_config; + +typedef struct _usb_desc_itf { + usb_desc_header header; /*!< descriptor header, including type and size */ + + uint8_t bInterfaceNumber; /*!< index of the interface in the current configuration */ + uint8_t bAlternateSetting; /*!< alternate setting for the interface number */ + uint8_t bNumEndpoints; /*!< total number of endpoints in the interface */ + uint8_t bInterfaceClass; /*!< interface class ID */ + uint8_t bInterfaceSubClass; /*!< interface subclass ID */ + uint8_t bInterfaceProtocol; /*!< interface protocol ID */ + uint8_t iInterface; /*!< index of the string descriptor describing the interface */ +} usb_desc_itf; + +typedef struct _usb_desc_ep { + usb_desc_header header; /*!< descriptor header, including type and size. */ + + uint8_t bEndpointAddress; /*!< logical address of the endpoint */ + uint8_t bmAttributes; /*!< endpoint attributes */ + uint16_t wMaxPacketSize; /*!< size of the endpoint bank, in bytes */ + uint8_t bInterval; /*!< polling interval in milliseconds for the endpoint if it is an INTERRUPT or ISOCHRONOUS type */ +} usb_desc_ep; + +typedef struct _usb_desc_LANGID { + usb_desc_header header; /*!< descriptor header, including type and size. */ + uint16_t wLANGID; /*!< LANGID code */ +} usb_desc_LANGID; + +typedef struct _usb_desc_str { + usb_desc_header header; /*!< descriptor header, including type and size. */ + uint16_t unicode_string[64]; /*!< unicode string data */ +} usb_desc_str; + +#pragma pack() + +/* compute string descriptor length */ +#define USB_STRING_LEN(unicode_chars) (sizeof(usb_desc_header) + ((unicode_chars) << 1U)) + +#endif /* __USB_CH9_STD_H */ diff --git a/bsp/gd32/libraries/GD32F20x_Firmware_Library/SConscript b/bsp/gd32/libraries/GD32F20x_Firmware_Library/SConscript new file mode 100644 index 0000000000..90cca69a13 --- /dev/null +++ b/bsp/gd32/libraries/GD32F20x_Firmware_Library/SConscript @@ -0,0 +1,57 @@ +import rtconfig +from building import * + +# get current directory +cwd = GetCurrentDir() + +# The set of source files associated with this SConscript file. + +src = Split(''' +CMSIS/GD/GD32F20x/Source/system_gd32f20x.c +GD32F20x_standard_peripheral/Source/gd32f20x_gpio.c +GD32F20x_standard_peripheral/Source/gd32f20x_rcu.c +GD32F20x_standard_peripheral/Source/gd32f20x_exti.c +GD32F20x_standard_peripheral/Source/gd32f20x_misc.c +''') + +if GetDepend(['RT_USING_SERIAL']): + src += ['GD32F20x_standard_peripheral/Source/gd32f20x_usart.c'] + +if GetDepend(['RT_USING_I2C']): + src += ['GD32F20x_standard_peripheral/Source/gd32f20x_i2c.c'] + +if GetDepend(['RT_USING_SPI']): + src += ['GD32F20x_standard_peripheral/Source/gd32f20x_spi.c'] + +if GetDepend(['RT_USING_CAN']): + src += ['GD32F20x_standard_peripheral/Source/gd32f20x_can.c'] + +if GetDepend(['BSP_USING_ETH']): + src += ['GD32F20x_standard_peripheral/Source/gd32f20x_enet.c'] + +if GetDepend(['RT_USING_ADC']): + src += ['GD32F20x_standard_peripheral/Source/gd32f20x_adc.c'] + +if GetDepend(['RT_USING_DAC']): + src += ['GD32F20x_standard_peripheral/Source/gd32f20x_dac.c'] + +if GetDepend(['RT_USING_RTC']): + src += ['GD32F20x_standard_peripheral/Source/gd32f20x_rtc.c'] + +if GetDepend(['RT_USING_WDT']): + src += ['GD32F20x_standard_peripheral/Source/gd32f20x_wwdgt.c'] + src += ['GD32F20x_standard_peripheral/Source/gd32f20x_fwdgt.c'] + +if GetDepend(['RT_USING_SDIO']): + src += ['GD32F20x_standard_peripheral/Source/gd32f20x_sdio.c'] + +path = [ + cwd + '/CMSIS/GD/GD32F20x/Include', + cwd + '/CMSIS', + cwd + '/GD32F20x_standard_peripheral/Include',] + +CPPDEFINES = ['USE_STDPERIPH_DRIVER'] + +group = DefineGroup('Libraries', src, depend = [''], CPPPATH = path, CPPDEFINES = CPPDEFINES) + +Return('group') diff --git a/bsp/gd32/libraries/GD32F30x_Firmware_Library/CMSIS/GD/GD32F30x/Include/gd32f30x.h b/bsp/gd32/libraries/GD32F30x_Firmware_Library/CMSIS/GD/GD32F30x/Include/gd32f30x.h new file mode 100644 index 0000000000..c9ba4bb0d1 --- /dev/null +++ b/bsp/gd32/libraries/GD32F30x_Firmware_Library/CMSIS/GD/GD32F30x/Include/gd32f30x.h @@ -0,0 +1,356 @@ +/*! + \file gd32f30x.h + \brief general definitions for GD32F30x + + \version 2017-02-10, V1.0.0, firmware for GD32F30x + \version 2018-10-10, V1.1.0, firmware for GD32F30x + \version 2018-12-25, V2.0.0, firmware for GD32F30x + \version 2020-09-30, V2.1.0, firmware for GD32F30x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef GD32F30X_H +#define GD32F30X_H + +#ifdef __cplusplus + extern "C" { +#endif + +/* define GD32F30x */ +#if !defined (GD32F30X_HD) && !defined (GD32F30X_XD) && !defined (GD32F30X_CL) + /* #define GD32F30X_HD */ + /* #define GD32F30X_XD */ + /* #define GD32F30X_CL */ +#endif /* define GD32F30x */ + +#if !defined (GD32F30X_HD) && !defined (GD32F30X_XD) && !defined (GD32F30X_CL) + #error "Please select the target GD32F30x device in gd32f30x.h file" +#endif /* undefine GD32F30x tip */ + +/* define value of high speed crystal oscillator (HXTAL) in Hz */ +#if !defined HXTAL_VALUE +#ifdef GD32F30X_CL +#define HXTAL_VALUE ((uint32_t)25000000) /*!< value of the external oscillator in Hz */ +#else +#define HXTAL_VALUE ((uint32_t)8000000) /* !< from 4M to 32M *!< value of the external oscillator in Hz*/ +#endif /* HXTAL_VALUE */ +#endif /* high speed crystal oscillator value */ + +/* define startup timeout value of high speed crystal oscillator (HXTAL) */ +#if !defined (HXTAL_STARTUP_TIMEOUT) +#define HXTAL_STARTUP_TIMEOUT ((uint16_t)0xFFFF) +#endif /* high speed crystal oscillator startup timeout */ + +/* define value of internal 48MHz RC oscillator (IRC48M) in Hz */ +#if !defined (IRC48M_VALUE) +#define IRC48M_VALUE ((uint32_t)48000000) +#endif /* internal 48MHz RC oscillator value */ + +/* define value of internal 8MHz RC oscillator (IRC8M) in Hz */ +#if !defined (IRC8M_VALUE) +#define IRC8M_VALUE ((uint32_t)8000000) +#endif /* internal 8MHz RC oscillator value */ + +/* define startup timeout value of internal 8MHz RC oscillator (IRC8M) */ +#if !defined (IRC8M_STARTUP_TIMEOUT) +#define IRC8M_STARTUP_TIMEOUT ((uint16_t)0x0500) +#endif /* internal 8MHz RC oscillator startup timeout */ + +/* define value of internal 40KHz RC oscillator(IRC40K) in Hz */ +#if !defined (IRC40K_VALUE) +#define IRC40K_VALUE ((uint32_t)40000) +#endif /* internal 40KHz RC oscillator value */ + +/* define value of low speed crystal oscillator (LXTAL)in Hz */ +#if !defined (LXTAL_VALUE) +#define LXTAL_VALUE ((uint32_t)32768) +#endif /* low speed crystal oscillator value */ + +/* GD32F30x firmware library version number V1.0 */ +#define __GD32F30x_STDPERIPH_VERSION_MAIN (0x01) /*!< [31:24] main version */ +#define __GD32F30x_STDPERIPH_VERSION_SUB1 (0x00) /*!< [23:16] sub1 version */ +#define __GD32F30x_STDPERIPH_VERSION_SUB2 (0x00) /*!< [15:8] sub2 version */ +#define __GD32F30x_STDPERIPH_VERSION_RC (0x00) /*!< [7:0] release candidate */ +#define __GD32F30x_STDPERIPH_VERSION ((__GD32F30x_STDPERIPH_VERSION_MAIN << 24)\ + |(__GD32F30x_STDPERIPH_VERSION_SUB1 << 16)\ + |(__GD32F30x_STDPERIPH_VERSION_SUB2 << 8)\ + |(__GD32F30x_STDPERIPH_VERSION_RC)) + +/* configuration of the Cortex-M4 processor and core peripherals */ +#define __CM4_REV 0x0001 /*!< Core revision r0p1 */ +#define __MPU_PRESENT 1 /*!< GD32F30x provide MPU */ +#define __NVIC_PRIO_BITS 4 /*!< GD32F30x uses 4 bits for the priority levels */ +#define __Vendor_SysTickConfig 0 /*!< set to 1 if different sysTick config is used */ +#define __FPU_PRESENT 1 /*!< FPU present */ +/* define interrupt number */ +typedef enum IRQn +{ + /* Cortex-M4 processor exceptions numbers */ + NonMaskableInt_IRQn = -14, /*!< 2 non maskable interrupt */ + MemoryManagement_IRQn = -12, /*!< 4 Cortex-M4 memory management interrupt */ + BusFault_IRQn = -11, /*!< 5 Cortex-M4 bus fault interrupt */ + UsageFault_IRQn = -10, /*!< 6 Cortex-M4 usage fault interrupt */ + SVCall_IRQn = -5, /*!< 11 Cortex-M4 SV call interrupt */ + DebugMonitor_IRQn = -4, /*!< 12 Cortex-M4 debug monitor interrupt */ + PendSV_IRQn = -2, /*!< 14 Cortex-M4 pend SV interrupt */ + SysTick_IRQn = -1, /*!< 15 Cortex-M4 system tick interrupt */ + /* interruput numbers */ + WWDGT_IRQn = 0, /*!< window watchDog timer interrupt */ + LVD_IRQn = 1, /*!< LVD through EXTI line detect interrupt */ + TAMPER_IRQn = 2, /*!< tamper through EXTI line detect */ + RTC_IRQn = 3, /*!< RTC through EXTI line interrupt */ + FMC_IRQn = 4, /*!< FMC interrupt */ + RCU_CTC_IRQn = 5, /*!< RCU and CTC interrupt */ + EXTI0_IRQn = 6, /*!< EXTI line 0 interrupt */ + EXTI1_IRQn = 7, /*!< EXTI line 1 interrupt */ + EXTI2_IRQn = 8, /*!< EXTI line 2 interrupt */ + EXTI3_IRQn = 9, /*!< EXTI line 3 interrupt */ + EXTI4_IRQn = 10, /*!< EXTI line 4 interrupt */ + DMA0_Channel0_IRQn = 11, /*!< DMA0 channel0 interrupt */ + DMA0_Channel1_IRQn = 12, /*!< DMA0 channel1 interrupt */ + DMA0_Channel2_IRQn = 13, /*!< DMA0 channel2 interrupt */ + DMA0_Channel3_IRQn = 14, /*!< DMA0 channel3 interrupt */ + DMA0_Channel4_IRQn = 15, /*!< DMA0 channel4 interrupt */ + DMA0_Channel5_IRQn = 16, /*!< DMA0 channel5 interrupt */ + DMA0_Channel6_IRQn = 17, /*!< DMA0 channel6 interrupt */ + ADC0_1_IRQn = 18, /*!< ADC0 and ADC1 interrupt */ +#ifdef GD32F30X_HD + USBD_HP_CAN0_TX_IRQn = 19, /*!< CAN0 TX interrupts */ + USBD_LP_CAN0_RX0_IRQn = 20, /*!< CAN0 RX0 interrupts */ + CAN0_RX1_IRQn = 21, /*!< CAN0 RX1 interrupt */ + CAN0_EWMC_IRQn = 22, /*!< CAN0 EWMC interrupt */ + EXTI5_9_IRQn = 23, /*!< EXTI[9:5] interrupts */ + TIMER0_BRK_IRQn = 24, /*!< TIMER0 break interrupt */ + TIMER0_UP_IRQn = 25, /*!< TIMER0 update interrupt */ + TIMER0_TRG_CMT_IRQn = 26, /*!< TIMER0 trigger and commutation interrupt */ + TIMER0_Channel_IRQn = 27, /*!< TIMER0 channel capture compare interrupt */ + TIMER1_IRQn = 28, /*!< TIMER1 interrupt */ + TIMER2_IRQn = 29, /*!< TIMER2 interrupt */ + TIMER3_IRQn = 30, /*!< TIMER3 interrupt */ + I2C0_EV_IRQn = 31, /*!< I2C0 event interrupt */ + I2C0_ER_IRQn = 32, /*!< I2C0 error interrupt */ + I2C1_EV_IRQn = 33, /*!< I2C1 event interrupt */ + I2C1_ER_IRQn = 34, /*!< I2C1 error interrupt */ + SPI0_IRQn = 35, /*!< SPI0 interrupt */ + SPI1_IRQn = 36, /*!< SPI1 interrupt */ + USART0_IRQn = 37, /*!< USART0 interrupt */ + USART1_IRQn = 38, /*!< USART1 interrupt */ + USART2_IRQn = 39, /*!< USART2 interrupt */ + EXTI10_15_IRQn = 40, /*!< EXTI[15:10] interrupts */ + RTC_Alarm_IRQn = 41, /*!< RTC alarm interrupt */ + USBD_WKUP_IRQn = 42, /*!< USBD Wakeup interrupt */ + TIMER7_BRK_IRQn = 43, /*!< TIMER7 break interrupt */ + TIMER7_UP_IRQn = 44, /*!< TIMER7 update interrupt */ + TIMER7_TRG_CMT_IRQn = 45, /*!< TIMER7 trigger and commutation interrupt */ + TIMER7_Channel_IRQn = 46, /*!< TIMER7 channel capture compare interrupt */ + ADC2_IRQn = 47, /*!< ADC2 global interrupt */ + EXMC_IRQn = 48, /*!< EXMC global interrupt */ + SDIO_IRQn = 49, /*!< SDIO global interrupt */ + TIMER4_IRQn = 50, /*!< TIMER4 global interrupt */ + SPI2_IRQn = 51, /*!< SPI2 global interrupt */ + UART3_IRQn = 52, /*!< UART3 global interrupt */ + UART4_IRQn = 53, /*!< UART4 global interrupt */ + TIMER5_IRQn = 54, /*!< TIMER5 global interrupt */ + TIMER6_IRQn = 55, /*!< TIMER6 global interrupt */ + DMA1_Channel0_IRQn = 56, /*!< DMA1 channel0 global interrupt */ + DMA1_Channel1_IRQn = 57, /*!< DMA1 channel1 global interrupt */ + DMA1_Channel2_IRQn = 58, /*!< DMA1 channel2 global interrupt */ + DMA1_Channel3_Channel4_IRQn = 59, /*!< DMA1 channel3 and channel4 global Interrupt */ +#endif /* GD32F30X_HD */ + +#ifdef GD32F30X_XD + USBD_HP_CAN0_TX_IRQn = 19, /*!< CAN0 TX interrupts */ + USBD_LP_CAN0_RX0_IRQn = 20, /*!< CAN0 RX0 interrupts */ + CAN0_RX1_IRQn = 21, /*!< CAN0 RX1 interrupt */ + CAN0_EWMC_IRQn = 22, /*!< CAN0 EWMC interrupt */ + EXTI5_9_IRQn = 23, /*!< EXTI[9:5] interrupts */ + TIMER0_BRK_TIMER8_IRQn = 24, /*!< TIMER0 break and TIMER8 interrupt */ + TIMER0_UP_TIMER9_IRQn = 25, /*!< TIMER0 update and TIMER9 interrupt */ + TIMER0_TRG_CMT_TIMER10_IRQn = 26, /*!< TIMER0 trigger and commutation and TIMER10 interrupt */ + TIMER0_Channel_IRQn = 27, /*!< TIMER0 channel capture compare interrupt */ + TIMER1_IRQn = 28, /*!< TIMER1 interrupt */ + TIMER2_IRQn = 29, /*!< TIMER2 interrupt */ + TIMER3_IRQn = 30, /*!< TIMER3 interrupt */ + I2C0_EV_IRQn = 31, /*!< I2C0 event interrupt */ + I2C0_ER_IRQn = 32, /*!< I2C0 error interrupt */ + I2C1_EV_IRQn = 33, /*!< I2C1 event interrupt */ + I2C1_ER_IRQn = 34, /*!< I2C1 error interrupt */ + SPI0_IRQn = 35, /*!< SPI0 interrupt */ + SPI1_IRQn = 36, /*!< SPI1 interrupt */ + USART0_IRQn = 37, /*!< USART0 interrupt */ + USART1_IRQn = 38, /*!< USART1 interrupt */ + USART2_IRQn = 39, /*!< USART2 interrupt */ + EXTI10_15_IRQn = 40, /*!< EXTI[15:10] interrupts */ + RTC_Alarm_IRQn = 41, /*!< RTC alarm interrupt */ + USBD_WKUP_IRQn = 42, /*!< USBD wakeup interrupt */ + TIMER7_BRK_TIMER11_IRQn = 43, /*!< TIMER7 break and TIMER11 interrupt */ + TIMER7_UP_TIMER12_IRQn = 44, /*!< TIMER7 update and TIMER12 interrupt */ + TIMER7_TRG_CMT_TIMER13_IRQn = 45, /*!< TIMER7 trigger and commutation and TIMER13 interrupt */ + TIMER7_Channel_IRQn = 46, /*!< TIMER7 channel capture compare interrupt */ + ADC2_IRQn = 47, /*!< ADC2 global interrupt */ + EXMC_IRQn = 48, /*!< EXMC global interrupt */ + SDIO_IRQn = 49, /*!< SDIO global interrupt */ + TIMER4_IRQn = 50, /*!< TIMER4 global interrupt */ + SPI2_IRQn = 51, /*!< SPI2 global interrupt */ + UART3_IRQn = 52, /*!< UART3 global interrupt */ + UART4_IRQn = 53, /*!< UART4 global interrupt */ + TIMER5_IRQn = 54, /*!< TIMER5 global interrupt */ + TIMER6_IRQn = 55, /*!< TIMER6 global interrupt */ + DMA1_Channel0_IRQn = 56, /*!< DMA1 channel0 global interrupt */ + DMA1_Channel1_IRQn = 57, /*!< DMA1 channel1 global interrupt */ + DMA1_Channel2_IRQn = 58, /*!< DMA1 channel2 global interrupt */ + DMA1_Channel3_Channel4_IRQn = 59, /*!< DMA1 channel3 and channel4 global interrupt */ +#endif /* GD32F30X_XD */ + +#ifdef GD32F30X_CL + CAN0_TX_IRQn = 19, /*!< CAN0 TX interrupt */ + CAN0_RX0_IRQn = 20, /*!< CAN0 RX0 interrupt */ + CAN0_RX1_IRQn = 21, /*!< CAN0 RX1 interrupt */ + CAN0_EWMC_IRQn = 22, /*!< CAN0 EWMC interrupt */ + EXTI5_9_IRQn = 23, /*!< EXTI[9:5] interrupts */ + TIMER0_BRK_TIMER8_IRQn = 24, /*!< TIMER0 break and TIMER8 interrupt */ + TIMER0_UP_TIMER9_IRQn = 25, /*!< TIMER0 update and TIMER9 interrupt */ + TIMER0_TRG_CMT_TIMER10_IRQn = 26, /*!< TIMER0 trigger and commutation and TIMER10 interrupt */ + TIMER0_Channel_IRQn = 27, /*!< TIMER0 channel capture compare interrupt */ + TIMER1_IRQn = 28, /*!< TIMER1 interrupt */ + TIMER2_IRQn = 29, /*!< TIMER2 interrupt */ + TIMER3_IRQn = 30, /*!< TIMER3 interrupt */ + I2C0_EV_IRQn = 31, /*!< I2C0 event interrupt */ + I2C0_ER_IRQn = 32, /*!< I2C0 error interrupt */ + I2C1_EV_IRQn = 33, /*!< I2C1 event interrupt */ + I2C1_ER_IRQn = 34, /*!< I2C1 error interrupt */ + SPI0_IRQn = 35, /*!< SPI0 interrupt */ + SPI1_IRQn = 36, /*!< SPI1 interrupt */ + USART0_IRQn = 37, /*!< USART0 interrupt */ + USART1_IRQn = 38, /*!< USART1 interrupt */ + USART2_IRQn = 39, /*!< USART2 interrupt */ + EXTI10_15_IRQn = 40, /*!< EXTI[15:10] interrupts */ + RTC_ALARM_IRQn = 41, /*!< RTC alarm interrupt */ + USBFS_WKUP_IRQn = 42, /*!< USBFS wakeup interrupt */ + TIMER7_BRK_TIMER11_IRQn = 43, /*!< TIMER7 break and TIMER11 interrupt */ + TIMER7_UP_TIMER12_IRQn = 44, /*!< TIMER7 update and TIMER12 interrupt */ + TIMER7_TRG_CMT_TIMER13_IRQn = 45, /*!< TIMER7 trigger and commutation and TIMER13 interrupt */ + TIMER7_Channel_IRQn = 46, /*!< TIMER7 channel capture compare interrupt */ + EXMC_IRQn = 48, /*!< EXMC global interrupt */ + TIMER4_IRQn = 50, /*!< TIMER4 global interrupt */ + SPI2_IRQn = 51, /*!< SPI2 global interrupt */ + UART3_IRQn = 52, /*!< UART3 global interrupt */ + UART4_IRQn = 53, /*!< UART4 global interrupt */ + TIMER5_IRQn = 54, /*!< TIMER5 global interrupt */ + TIMER6_IRQn = 55, /*!< TIMER6 global interrupt */ + DMA1_Channel0_IRQn = 56, /*!< DMA1 channel0 global interrupt */ + DMA1_Channel1_IRQn = 57, /*!< DMA1 channel1 global interrupt */ + DMA1_Channel2_IRQn = 58, /*!< DMA1 channel2 global interrupt */ + DMA1_Channel3_IRQn = 59, /*!< DMA1 channel3 global interrupt */ + DMA1_Channel4_IRQn = 60, /*!< DMA1 channel3 global interrupt */ + ENET_IRQn = 61, /*!< ENET global interrupt */ + ENET_WKUP_IRQn = 62, /*!< ENET Wakeup interrupt */ + CAN1_TX_IRQn = 63, /*!< CAN1 TX interrupt */ + CAN1_RX0_IRQn = 64, /*!< CAN1 RX0 interrupt */ + CAN1_RX1_IRQn = 65, /*!< CAN1 RX1 interrupt */ + CAN1_EWMC_IRQn = 66, /*!< CAN1 EWMC interrupt */ + USBFS_IRQn = 67, /*!< USBFS global interrupt */ +#endif /* GD32F30X_CL */ + +} IRQn_Type; + +/* includes */ +#include "core_cm4.h" +#include "system_gd32f30x.h" +#include + +/* enum definitions */ +typedef enum {DISABLE = 0, ENABLE = !DISABLE} EventStatus, ControlStatus; +typedef enum {RESET = 0, SET = !RESET} FlagStatus; +typedef enum {ERROR = 0, SUCCESS = !ERROR} ErrStatus; + +/* bit operations */ +#define REG32(addr) (*(volatile uint32_t *)(uint32_t)(addr)) +#define REG16(addr) (*(volatile uint16_t *)(uint32_t)(addr)) +#define REG8(addr) (*(volatile uint8_t *)(uint32_t)(addr)) +#define BIT(x) ((uint32_t)((uint32_t)0x01U<<(x))) +#define BITS(start, end) ((0xFFFFFFFFUL << (start)) & (0xFFFFFFFFUL >> (31U - (uint32_t)(end)))) +#define GET_BITS(regval, start, end) (((regval) & BITS((start),(end))) >> (start)) + +/* main flash and SRAM memory map */ +#define FLASH_BASE ((uint32_t)0x08000000U) /*!< main FLASH base address */ +#define SRAM_BASE ((uint32_t)0x20000000U) /*!< SRAM0 base address */ +#define OB_BASE ((uint32_t)0x1FFFF800U) /*!< OB base address */ +#define DBG_BASE ((uint32_t)0xE0042000U) /*!< DBG base address */ +#define EXMC_BASE ((uint32_t)0xA0000000U) /*!< EXMC register base address */ + +/* peripheral memory map */ +#define APB1_BUS_BASE ((uint32_t)0x40000000U) /*!< apb1 base address */ +#define APB2_BUS_BASE ((uint32_t)0x40010000U) /*!< apb2 base address */ +#define AHB1_BUS_BASE ((uint32_t)0x40018000U) /*!< ahb1 base address */ +#define AHB3_BUS_BASE ((uint32_t)0x60000000U) /*!< ahb3 base address */ + +/* advanced peripheral bus 1 memory map */ +#define TIMER_BASE (APB1_BUS_BASE + 0x00000000U) /*!< TIMER base address */ +#define RTC_BASE (APB1_BUS_BASE + 0x00002800U) /*!< RTC base address */ +#define WWDGT_BASE (APB1_BUS_BASE + 0x00002C00U) /*!< WWDGT base address */ +#define FWDGT_BASE (APB1_BUS_BASE + 0x00003000U) /*!< FWDGT base address */ +#define SPI_BASE (APB1_BUS_BASE + 0x00003800U) /*!< SPI base address */ +#define USART_BASE (APB1_BUS_BASE + 0x00004400U) /*!< USART base address */ +#define I2C_BASE (APB1_BUS_BASE + 0x00005400U) /*!< I2C base address */ +#define USBD_BASE (APB1_BUS_BASE + 0x00005C00U) /*!< USBD base address */ +#define USBD_RAM_BASE (APB1_BUS_BASE + 0x00006000U) /*!< USBD RAM base address */ +#define CAN_BASE (APB1_BUS_BASE + 0x00006400U) /*!< CAN base address */ +#define BKP_BASE (APB1_BUS_BASE + 0x00006C00U) /*!< BKP base address */ +#define PMU_BASE (APB1_BUS_BASE + 0x00007000U) /*!< PMU base address */ +#define DAC_BASE (APB1_BUS_BASE + 0x00007400U) /*!< DAC base address */ +#define CTC_BASE (APB1_BUS_BASE + 0x0000C800U) /*!< CTC base address */ + +/* advanced peripheral bus 2 memory map */ +#define AFIO_BASE (APB2_BUS_BASE + 0x00000000U) /*!< AFIO base address */ +#define EXTI_BASE (APB2_BUS_BASE + 0x00000400U) /*!< EXTI base address */ +#define GPIO_BASE (APB2_BUS_BASE + 0x00000800U) /*!< GPIO base address */ +#define ADC_BASE (APB2_BUS_BASE + 0x00002400U) /*!< ADC base address */ + +/* advanced high performance bus 1 memory map */ +#define SDIO_BASE (AHB1_BUS_BASE + 0x00000000U) /*!< SDIO base address */ +#define DMA_BASE (AHB1_BUS_BASE + 0x00008000U) /*!< DMA base address */ +#define RCU_BASE (AHB1_BUS_BASE + 0x00009000U) /*!< RCU base address */ +#define FMC_BASE (AHB1_BUS_BASE + 0x0000A000U) /*!< FMC base address */ +#define CRC_BASE (AHB1_BUS_BASE + 0x0000B000U) /*!< CRC base address */ +#define ENET_BASE (AHB1_BUS_BASE + 0x00010000U) /*!< ENET base address */ +#define USBFS_BASE (AHB1_BUS_BASE + 0x0FFE8000U) /*!< USBFS base address */ + +/* define marco USE_STDPERIPH_DRIVER */ +#if !defined USE_STDPERIPH_DRIVER +#define USE_STDPERIPH_DRIVER +#endif +#ifdef USE_STDPERIPH_DRIVER +#include "gd32f30x_libopt.h" +#endif /* USE_STDPERIPH_DRIVER */ + +#ifdef __cplusplus +} +#endif +#endif diff --git a/bsp/gd32/libraries/GD32F30x_Firmware_Library/CMSIS/GD/GD32F30x/Include/system_gd32f30x.h b/bsp/gd32/libraries/GD32F30x_Firmware_Library/CMSIS/GD/GD32F30x/Include/system_gd32f30x.h new file mode 100644 index 0000000000..69e7366e38 --- /dev/null +++ b/bsp/gd32/libraries/GD32F30x_Firmware_Library/CMSIS/GD/GD32F30x/Include/system_gd32f30x.h @@ -0,0 +1,57 @@ +/*! + \file system_gd32f30x.h + \brief CMSIS Cortex-M4 Device Peripheral Access Layer Header File for + GD32F30x Device Series +*/ + +/* Copyright (c) 2012 ARM LIMITED + + All rights reserved. + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + - Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + - Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + - Neither the name of ARM nor the names of its contributors may be used + to endorse or promote products derived from this software without + specific prior written permission. + * + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDERS AND CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + ---------------------------------------------------------------------------*/ +/* This file refers the CMSIS standard, some adjustments are made according to GigaDevice chips */ + +#ifndef SYSTEM_GD32F30X_H +#define SYSTEM_GD32F30X_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include + +/* system clock frequency (core clock) */ +extern uint32_t SystemCoreClock; + +/* function declarations */ +/* initialize the system and update the SystemCoreClock variable */ +extern void SystemInit (void); +/* update the SystemCoreClock with current core clock retrieved from cpu registers */ +extern void SystemCoreClockUpdate (void); + +#ifdef __cplusplus +} +#endif + +#endif /* SYSTEM_GD32F30X_H */ diff --git a/bsp/gd32/libraries/GD32F30x_Firmware_Library/CMSIS/GD/GD32F30x/Source/ARM/startup_gd32f30x_cl.s b/bsp/gd32/libraries/GD32F30x_Firmware_Library/CMSIS/GD/GD32F30x/Source/ARM/startup_gd32f30x_cl.s new file mode 100644 index 0000000000..b274d61156 --- /dev/null +++ b/bsp/gd32/libraries/GD32F30x_Firmware_Library/CMSIS/GD/GD32F30x/Source/ARM/startup_gd32f30x_cl.s @@ -0,0 +1,385 @@ +;/*! +; \file startup_gd32f30x_cl.s +; \brief start up file +; +; \version 2017-02-10, V1.0.0, firmware for GD32F30x +; \version 2018-10-10, V1.1.0, firmware for GD32F30x +; \version 2018-12-25, V2.0.0, firmware for GD32F30x +; \version 2020-09-30, V2.1.0, firmware for GD32F30x +;*/ +; +;/* +; Copyright (c) 2020, GigaDevice Semiconductor Inc. + +; Redistribution and use in source and binary forms, with or without modification, +;are permitted provided that the following conditions are met: +; +; 1. Redistributions of source code must retain the above copyright notice, this +; list of conditions and the following disclaimer. +; 2. Redistributions in binary form must reproduce the above copyright notice, +; this list of conditions and the following disclaimer in the documentation +; and/or other materials provided with the distribution. +; 3. Neither the name of the copyright holder nor the names of its contributors +; may be used to endorse or promote products derived from this software without +; specific prior written permission. +; +; THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +;AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +;WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +;IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +;INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +;NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +;PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +;WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +;ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +;OF SUCH DAMAGE. +;*/ + +; Stack Configuration +; Stack Size (in Bytes) <0x0-0xFFFFFFFF:8> +; + +Stack_Size EQU 0x00000400 + + AREA STACK, NOINIT, READWRITE, ALIGN=3 +Stack_Mem SPACE Stack_Size +__initial_sp + + +; Heap Configuration +; Heap Size (in Bytes) <0x0-0xFFFFFFFF:8> +; + +Heap_Size EQU 0x00000400 + + AREA HEAP, NOINIT, READWRITE, ALIGN=3 +__heap_base +Heap_Mem SPACE Heap_Size +__heap_limit + + PRESERVE8 + THUMB + +; /* reset Vector Mapped to at Address 0 */ + AREA RESET, DATA, READONLY + EXPORT __Vectors + EXPORT __Vectors_End + EXPORT __Vectors_Size + +__Vectors DCD __initial_sp ; Top of Stack + DCD Reset_Handler ; Reset Handler + DCD NMI_Handler ; NMI Handler + DCD HardFault_Handler ; Hard Fault Handler + DCD MemManage_Handler ; MPU Fault Handler + DCD BusFault_Handler ; Bus Fault Handler + DCD UsageFault_Handler ; Usage Fault Handler + DCD 0 ; Reserved + DCD 0 ; Reserved + DCD 0 ; Reserved + DCD 0 ; Reserved + DCD SVC_Handler ; SVCall Handler + DCD DebugMon_Handler ; Debug Monitor Handler + DCD 0 ; Reserved + DCD PendSV_Handler ; PendSV Handler + DCD SysTick_Handler ; SysTick Handler + +; /* external interrupts handler */ + DCD WWDGT_IRQHandler ; 16:Window Watchdog Timer + DCD LVD_IRQHandler ; 17:LVD through EXTI Line detect + DCD TAMPER_IRQHandler ; 18:Tamper through EXTI Line detect + DCD RTC_IRQHandler ; 19:RTC through EXTI Line + DCD FMC_IRQHandler ; 20:FMC + DCD RCU_CTC_IRQHandler ; 21:RCU and CTC + DCD EXTI0_IRQHandler ; 22:EXTI Line 0 + DCD EXTI1_IRQHandler ; 23:EXTI Line 1 + DCD EXTI2_IRQHandler ; 24:EXTI Line 2 + DCD EXTI3_IRQHandler ; 25:EXTI Line 3 + DCD EXTI4_IRQHandler ; 26:EXTI Line 4 + DCD DMA0_Channel0_IRQHandler ; 27:DMA0 Channel0 + DCD DMA0_Channel1_IRQHandler ; 28:DMA0 Channel1 + DCD DMA0_Channel2_IRQHandler ; 29:DMA0 Channel2 + DCD DMA0_Channel3_IRQHandler ; 30:DMA0 Channel3 + DCD DMA0_Channel4_IRQHandler ; 31:DMA0 Channel4 + DCD DMA0_Channel5_IRQHandler ; 32:DMA0 Channel5 + DCD DMA0_Channel6_IRQHandler ; 33:DMA0 Channel6 + DCD ADC0_1_IRQHandler ; 34:ADC0 and ADC1 + DCD CAN0_TX_IRQHandler ; 35:CAN0 TX + DCD CAN0_RX0_IRQHandler ; 36:CAN0 RX0 + DCD CAN0_RX1_IRQHandler ; 37:CAN0 RX1 + DCD CAN0_EWMC_IRQHandler ; 38:CAN0 EWMC + DCD EXTI5_9_IRQHandler ; 39:EXTI5 to EXTI9 + DCD TIMER0_BRK_TIMER8_IRQHandler ; 40:TIMER0 Break and TIMER8 + DCD TIMER0_UP_TIMER9_IRQHandler ; 41:TIMER0 Update and TIMER9 + DCD TIMER0_TRG_CMT_TIMER10_IRQHandler ; 42:TIMER0 Trigger and Commutation and TIMER10 + DCD TIMER0_Channel_IRQHandler ; 43:TIMER0 Channel Capture Compare + DCD TIMER1_IRQHandler ; 44:TIMER1 + DCD TIMER2_IRQHandler ; 45:TIMER2 + DCD TIMER3_IRQHandler ; 46:TIMER3 + DCD I2C0_EV_IRQHandler ; 47:I2C0 Event + DCD I2C0_ER_IRQHandler ; 48:I2C0 Error + DCD I2C1_EV_IRQHandler ; 49:I2C1 Event + DCD I2C1_ER_IRQHandler ; 50:I2C1 Error + DCD SPI0_IRQHandler ; 51:SPI0 + DCD SPI1_IRQHandler ; 52:SPI1 + DCD USART0_IRQHandler ; 53:USART0 + DCD USART1_IRQHandler ; 54:USART1 + DCD USART2_IRQHandler ; 55:USART2 + DCD EXTI10_15_IRQHandler ; 56:EXTI10 to EXTI15 + DCD RTC_Alarm_IRQHandler ; 57:RTC Alarm + DCD USBFS_WKUP_IRQHandler ; 58:USBFS Wakeup + DCD TIMER7_BRK_TIMER11_IRQHandler ; 59:TIMER7 Break and TIMER11 + DCD TIMER7_UP_TIMER12_IRQHandler ; 60:TIMER7 Update and TIMER12 + DCD TIMER7_TRG_CMT_TIMER13_IRQHandler ; 61:TIMER7 Trigger and Commutation and TIMER13 + DCD TIMER7_Channel_IRQHandler ; 62:TIMER7 Channel Capture Compare + DCD 0 ; Reserved + DCD EXMC_IRQHandler ; 64:EXMC + DCD 0 ; Reserved + DCD TIMER4_IRQHandler ; 66:TIMER4 + DCD SPI2_IRQHandler ; 67:SPI2 + DCD UART3_IRQHandler ; 68:UART3 + DCD UART4_IRQHandler ; 69:UART4 + DCD TIMER5_IRQHandler ; 70:TIMER5 + DCD TIMER6_IRQHandler ; 71:TIMER6 + DCD DMA1_Channel0_IRQHandler ; 72:DMA1 Channel0 + DCD DMA1_Channel1_IRQHandler ; 73:DMA1 Channel1 + DCD DMA1_Channel2_IRQHandler ; 74:DMA1 Channel2 + DCD DMA1_Channel3_IRQHandler ; 75:DMA1 Channel3 + DCD DMA1_Channel4_IRQHandler ; 76:DMA1 Channel4 + DCD ENET_IRQHandler ; 77:Ethernet + DCD ENET_WKUP_IRQHandler ; 78:Ethernet Wakeup through EXTI Line + DCD CAN1_TX_IRQHandler ; 79:CAN1 TX + DCD CAN1_RX0_IRQHandler ; 80:CAN1 RX0 + DCD CAN1_RX1_IRQHandler ; 81:CAN1 RX1 + DCD CAN1_EWMC_IRQHandler ; 82:CAN1 EWMC + DCD USBFS_IRQHandler ; 83:USBFS + +__Vectors_End + +__Vectors_Size EQU __Vectors_End - __Vectors + + AREA |.text|, CODE, READONLY + +;/* reset Handler */ +Reset_Handler PROC + EXPORT Reset_Handler [WEAK] + IMPORT SystemInit + IMPORT __main + LDR R0, =SystemInit + BLX R0 + LDR R0, =__main + BX R0 + ENDP + +;/* dummy Exception Handlers */ +NMI_Handler PROC + EXPORT NMI_Handler [WEAK] + B . + ENDP +HardFault_Handler\ + PROC + EXPORT HardFault_Handler [WEAK] + B . + ENDP +MemManage_Handler\ + PROC + EXPORT MemManage_Handler [WEAK] + B . + ENDP +BusFault_Handler\ + PROC + EXPORT BusFault_Handler [WEAK] + B . + ENDP +UsageFault_Handler\ + PROC + EXPORT UsageFault_Handler [WEAK] + B . + ENDP +SVC_Handler PROC + EXPORT SVC_Handler [WEAK] + B . + ENDP +DebugMon_Handler\ + PROC + EXPORT DebugMon_Handler [WEAK] + B . + ENDP +PendSV_Handler\ + PROC + EXPORT PendSV_Handler [WEAK] + B . + ENDP +SysTick_Handler\ + PROC + EXPORT SysTick_Handler [WEAK] + B . + ENDP + +Default_Handler PROC +; /* external interrupts handler */ + EXPORT WWDGT_IRQHandler [WEAK] + EXPORT LVD_IRQHandler [WEAK] + EXPORT TAMPER_IRQHandler [WEAK] + EXPORT RTC_IRQHandler [WEAK] + EXPORT FMC_IRQHandler [WEAK] + EXPORT RCU_CTC_IRQHandler [WEAK] + EXPORT EXTI0_IRQHandler [WEAK] + EXPORT EXTI1_IRQHandler [WEAK] + EXPORT EXTI2_IRQHandler [WEAK] + EXPORT EXTI3_IRQHandler [WEAK] + EXPORT EXTI4_IRQHandler [WEAK] + EXPORT DMA0_Channel0_IRQHandler [WEAK] + EXPORT DMA0_Channel1_IRQHandler [WEAK] + EXPORT DMA0_Channel2_IRQHandler [WEAK] + EXPORT DMA0_Channel3_IRQHandler [WEAK] + EXPORT DMA0_Channel4_IRQHandler [WEAK] + EXPORT DMA0_Channel5_IRQHandler [WEAK] + EXPORT DMA0_Channel6_IRQHandler [WEAK] + EXPORT ADC0_1_IRQHandler [WEAK] + EXPORT CAN0_TX_IRQHandler [WEAK] + EXPORT CAN0_RX0_IRQHandler [WEAK] + EXPORT CAN0_RX1_IRQHandler [WEAK] + EXPORT CAN0_EWMC_IRQHandler [WEAK] + EXPORT EXTI5_9_IRQHandler [WEAK] + EXPORT TIMER0_BRK_TIMER8_IRQHandler [WEAK] + EXPORT TIMER0_UP_TIMER9_IRQHandler [WEAK] + EXPORT TIMER0_TRG_CMT_TIMER10_IRQHandler [WEAK] + EXPORT TIMER0_Channel_IRQHandler [WEAK] + EXPORT TIMER1_IRQHandler [WEAK] + EXPORT TIMER2_IRQHandler [WEAK] + EXPORT TIMER3_IRQHandler [WEAK] + EXPORT I2C0_EV_IRQHandler [WEAK] + EXPORT I2C0_ER_IRQHandler [WEAK] + EXPORT I2C1_EV_IRQHandler [WEAK] + EXPORT I2C1_ER_IRQHandler [WEAK] + EXPORT SPI0_IRQHandler [WEAK] + EXPORT SPI1_IRQHandler [WEAK] + EXPORT USART0_IRQHandler [WEAK] + EXPORT USART1_IRQHandler [WEAK] + EXPORT USART2_IRQHandler [WEAK] + EXPORT EXTI10_15_IRQHandler [WEAK] + EXPORT RTC_Alarm_IRQHandler [WEAK] + EXPORT USBFS_WKUP_IRQHandler [WEAK] + EXPORT TIMER7_BRK_TIMER11_IRQHandler [WEAK] + EXPORT TIMER7_UP_TIMER12_IRQHandler [WEAK] + EXPORT TIMER7_TRG_CMT_TIMER13_IRQHandler [WEAK] + EXPORT TIMER7_Channel_IRQHandler [WEAK] + EXPORT EXMC_IRQHandler [WEAK] + EXPORT TIMER4_IRQHandler [WEAK] + EXPORT SPI2_IRQHandler [WEAK] + EXPORT UART3_IRQHandler [WEAK] + EXPORT UART4_IRQHandler [WEAK] + EXPORT TIMER5_IRQHandler [WEAK] + EXPORT TIMER6_IRQHandler [WEAK] + EXPORT DMA1_Channel0_IRQHandler [WEAK] + EXPORT DMA1_Channel1_IRQHandler [WEAK] + EXPORT DMA1_Channel2_IRQHandler [WEAK] + EXPORT DMA1_Channel3_IRQHandler [WEAK] + EXPORT DMA1_Channel4_IRQHandler [WEAK] + EXPORT ENET_IRQHandler [WEAK] + EXPORT ENET_WKUP_IRQHandler [WEAK] + EXPORT CAN1_TX_IRQHandler [WEAK] + EXPORT CAN1_RX0_IRQHandler [WEAK] + EXPORT CAN1_RX1_IRQHandler [WEAK] + EXPORT CAN1_EWMC_IRQHandler [WEAK] + EXPORT USBFS_IRQHandler [WEAK] + +;/* external interrupts handler */ +WWDGT_IRQHandler +LVD_IRQHandler +TAMPER_IRQHandler +RTC_IRQHandler +FMC_IRQHandler +RCU_CTC_IRQHandler +EXTI0_IRQHandler +EXTI1_IRQHandler +EXTI2_IRQHandler +EXTI3_IRQHandler +EXTI4_IRQHandler +DMA0_Channel0_IRQHandler +DMA0_Channel1_IRQHandler +DMA0_Channel2_IRQHandler +DMA0_Channel3_IRQHandler +DMA0_Channel4_IRQHandler +DMA0_Channel5_IRQHandler +DMA0_Channel6_IRQHandler +ADC0_1_IRQHandler +CAN0_TX_IRQHandler +CAN0_RX0_IRQHandler +CAN0_RX1_IRQHandler +CAN0_EWMC_IRQHandler +EXTI5_9_IRQHandler +TIMER0_BRK_TIMER8_IRQHandler +TIMER0_UP_TIMER9_IRQHandler +TIMER0_TRG_CMT_TIMER10_IRQHandler +TIMER0_Channel_IRQHandler +TIMER1_IRQHandler +TIMER2_IRQHandler +TIMER3_IRQHandler +I2C0_EV_IRQHandler +I2C0_ER_IRQHandler +I2C1_EV_IRQHandler +I2C1_ER_IRQHandler +SPI0_IRQHandler +SPI1_IRQHandler +USART0_IRQHandler +USART1_IRQHandler +USART2_IRQHandler +EXTI10_15_IRQHandler +RTC_Alarm_IRQHandler +USBFS_WKUP_IRQHandler +TIMER7_BRK_TIMER11_IRQHandler +TIMER7_UP_TIMER12_IRQHandler +TIMER7_TRG_CMT_TIMER13_IRQHandler +TIMER7_Channel_IRQHandler +EXMC_IRQHandler +TIMER4_IRQHandler +SPI2_IRQHandler +UART3_IRQHandler +UART4_IRQHandler +TIMER5_IRQHandler +TIMER6_IRQHandler +DMA1_Channel0_IRQHandler +DMA1_Channel1_IRQHandler +DMA1_Channel2_IRQHandler +DMA1_Channel3_IRQHandler +DMA1_Channel4_IRQHandler +ENET_IRQHandler +ENET_WKUP_IRQHandler +CAN1_TX_IRQHandler +CAN1_RX0_IRQHandler +CAN1_RX1_IRQHandler +CAN1_EWMC_IRQHandler +USBFS_IRQHandler + + B . + ENDP + + ALIGN + +; user Initial Stack & Heap + + IF :DEF:__MICROLIB + + EXPORT __initial_sp + EXPORT __heap_base + EXPORT __heap_limit + + ELSE + + IMPORT __use_two_region_memory + EXPORT __user_initial_stackheap + +__user_initial_stackheap PROC + LDR R0, = Heap_Mem + LDR R1, =(Stack_Mem + Stack_Size) + LDR R2, = (Heap_Mem + Heap_Size) + LDR R3, = Stack_Mem + BX LR + ENDP + + ALIGN + + ENDIF + + END diff --git a/bsp/gd32/libraries/GD32F30x_Firmware_Library/CMSIS/GD/GD32F30x/Source/ARM/startup_gd32f30x_hd.s b/bsp/gd32/libraries/GD32F30x_Firmware_Library/CMSIS/GD/GD32F30x/Source/ARM/startup_gd32f30x_hd.s new file mode 100644 index 0000000000..cbc0764d63 --- /dev/null +++ b/bsp/gd32/libraries/GD32F30x_Firmware_Library/CMSIS/GD/GD32F30x/Source/ARM/startup_gd32f30x_hd.s @@ -0,0 +1,365 @@ +;/*! +; \file startup_gd32f30x_hd.s +; \brief start up file +; +; \version 2017-02-10, V1.0.0, firmware for GD32F30x +; \version 2018-10-10, V1.1.0, firmware for GD32F30x +; \version 2018-12-25, V2.0.0, firmware for GD32F30x +; \version 2020-09-30, V2.1.0, firmware for GD32F30x +;*/ +; +;/* +; Copyright (c) 2020, GigaDevice Semiconductor Inc. + +; Redistribution and use in source and binary forms, with or without modification, +;are permitted provided that the following conditions are met: +; +; 1. Redistributions of source code must retain the above copyright notice, this +; list of conditions and the following disclaimer. +; 2. Redistributions in binary form must reproduce the above copyright notice, +; this list of conditions and the following disclaimer in the documentation +; and/or other materials provided with the distribution. +; 3. Neither the name of the copyright holder nor the names of its contributors +; may be used to endorse or promote products derived from this software without +; specific prior written permission. +; +; THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +;AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +;WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +;IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +;INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +;NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +;PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +;WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +;ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +;OF SUCH DAMAGE. +;*/ + +; Stack Configuration +; Stack Size (in Bytes) <0x0-0xFFFFFFFF:8> +; + +Stack_Size EQU 0x00000400 + + AREA STACK, NOINIT, READWRITE, ALIGN=3 +Stack_Mem SPACE Stack_Size +__initial_sp + + +; Heap Configuration +; Heap Size (in Bytes) <0x0-0xFFFFFFFF:8> +; + +Heap_Size EQU 0x00000400 + + AREA HEAP, NOINIT, READWRITE, ALIGN=3 +__heap_base +Heap_Mem SPACE Heap_Size +__heap_limit + + PRESERVE8 + THUMB + +; /* reset Vector Mapped to at Address 0 */ + AREA RESET, DATA, READONLY + EXPORT __Vectors + EXPORT __Vectors_End + EXPORT __Vectors_Size + +__Vectors DCD __initial_sp ; Top of Stack + DCD Reset_Handler ; Reset Handler + DCD NMI_Handler ; NMI Handler + DCD HardFault_Handler ; Hard Fault Handler + DCD MemManage_Handler ; MPU Fault Handler + DCD BusFault_Handler ; Bus Fault Handler + DCD UsageFault_Handler ; Usage Fault Handler + DCD 0 ; Reserved + DCD 0 ; Reserved + DCD 0 ; Reserved + DCD 0 ; Reserved + DCD SVC_Handler ; SVCall Handler + DCD DebugMon_Handler ; Debug Monitor Handler + DCD 0 ; Reserved + DCD PendSV_Handler ; PendSV Handler + DCD SysTick_Handler ; SysTick Handler + +; /* external interrupts handler */ + DCD WWDGT_IRQHandler ; 16:Window Watchdog Timer + DCD LVD_IRQHandler ; 17:LVD through EXTI Line detect + DCD TAMPER_IRQHandler ; 18:Tamper through EXTI Line detect + DCD RTC_IRQHandler ; 19:RTC through EXTI Line + DCD FMC_IRQHandler ; 20:FMC + DCD RCU_CTC_IRQHandler ; 21:RCU and CTC + DCD EXTI0_IRQHandler ; 22:EXTI Line 0 + DCD EXTI1_IRQHandler ; 23:EXTI Line 1 + DCD EXTI2_IRQHandler ; 24:EXTI Line 2 + DCD EXTI3_IRQHandler ; 25:EXTI Line 3 + DCD EXTI4_IRQHandler ; 26:EXTI Line 4 + DCD DMA0_Channel0_IRQHandler ; 27:DMA0 Channel0 + DCD DMA0_Channel1_IRQHandler ; 28:DMA0 Channel1 + DCD DMA0_Channel2_IRQHandler ; 29:DMA0 Channel2 + DCD DMA0_Channel3_IRQHandler ; 30:DMA0 Channel3 + DCD DMA0_Channel4_IRQHandler ; 31:DMA0 Channel4 + DCD DMA0_Channel5_IRQHandler ; 32:DMA0 Channel5 + DCD DMA0_Channel6_IRQHandler ; 33:DMA0 Channel6 + DCD ADC0_1_IRQHandler ; 34:ADC0 and ADC1 + DCD USBD_HP_CAN0_TX_IRQHandler ; 35:USBD HP and CAN0 TX + DCD USBD_LP_CAN0_RX0_IRQHandler ; 36:USBD LP and CAN0 RX0 + DCD CAN0_RX1_IRQHandler ; 37:CAN0 RX1 + DCD CAN0_EWMC_IRQHandler ; 38:CAN0 EWMC + DCD EXTI5_9_IRQHandler ; 39:EXTI5 to EXTI9 + DCD TIMER0_BRK_IRQHandler ; 40:TIMER0 Break + DCD TIMER0_UP_IRQHandler ; 41:TIMER0 Update + DCD TIMER0_TRG_CMT_IRQHandler ; 42:TIMER0 Trigger and Commutation + DCD TIMER0_Channel_IRQHandler ; 43:TIMER0 Channel Capture Compare + DCD TIMER1_IRQHandler ; 44:TIMER1 + DCD TIMER2_IRQHandler ; 45:TIMER2 + DCD TIMER3_IRQHandler ; 46:TIMER3 + DCD I2C0_EV_IRQHandler ; 47:I2C0 Event + DCD I2C0_ER_IRQHandler ; 48:I2C0 Error + DCD I2C1_EV_IRQHandler ; 49:I2C1 Event + DCD I2C1_ER_IRQHandler ; 50:I2C1 Error + DCD SPI0_IRQHandler ; 51:SPI0 + DCD SPI1_IRQHandler ; 52:SPI1 + DCD USART0_IRQHandler ; 53:USART0 + DCD USART1_IRQHandler ; 54:USART1 + DCD USART2_IRQHandler ; 55:USART2 + DCD EXTI10_15_IRQHandler ; 56:EXTI10 to EXTI15 + DCD RTC_Alarm_IRQHandler ; 57:RTC Alarm + DCD USBD_WKUP_IRQHandler ; 58:USBD Wakeup + DCD TIMER7_BRK_IRQHandler ; 59:TIMER7 Break + DCD TIMER7_UP_IRQHandler ; 60:TIMER7 Update + DCD TIMER7_TRG_CMT_IRQHandler ; 61:TIMER7 Trigger and Commutation + DCD TIMER7_Channel_IRQHandler ; 62:TIMER7 Channel Capture Compare + DCD ADC2_IRQHandler ; 63:ADC2 + DCD EXMC_IRQHandler ; 64:EXMC + DCD SDIO_IRQHandler ; 65:SDIO + DCD TIMER4_IRQHandler ; 66:TIMER4 + DCD SPI2_IRQHandler ; 67:SPI2 + DCD UART3_IRQHandler ; 68:UART3 + DCD UART4_IRQHandler ; 69:UART4 + DCD TIMER5_IRQHandler ; 70:TIMER5 + DCD TIMER6_IRQHandler ; 71:TIMER6 + DCD DMA1_Channel0_IRQHandler ; 72:DMA1 Channel0 + DCD DMA1_Channel1_IRQHandler ; 73:DMA1 Channel1 + DCD DMA1_Channel2_IRQHandler ; 74:DMA1 Channel2 + DCD DMA1_Channel3_4_IRQHandler ; 75:DMA1 Channel3 and Channel4 + +__Vectors_End + +__Vectors_Size EQU __Vectors_End - __Vectors + + AREA |.text|, CODE, READONLY + +;/* reset Handler */ +Reset_Handler PROC + EXPORT Reset_Handler [WEAK] + IMPORT SystemInit + IMPORT __main + LDR R0, =SystemInit + BLX R0 + LDR R0, =__main + BX R0 + ENDP + +;/* dummy Exception Handlers */ +NMI_Handler PROC + EXPORT NMI_Handler [WEAK] + B . + ENDP +HardFault_Handler\ + PROC + EXPORT HardFault_Handler [WEAK] + B . + ENDP +MemManage_Handler\ + PROC + EXPORT MemManage_Handler [WEAK] + B . + ENDP +BusFault_Handler\ + PROC + EXPORT BusFault_Handler [WEAK] + B . + ENDP +UsageFault_Handler\ + PROC + EXPORT UsageFault_Handler [WEAK] + B . + ENDP +SVC_Handler PROC + EXPORT SVC_Handler [WEAK] + B . + ENDP +DebugMon_Handler\ + PROC + EXPORT DebugMon_Handler [WEAK] + B . + ENDP +PendSV_Handler\ + PROC + EXPORT PendSV_Handler [WEAK] + B . + ENDP +SysTick_Handler\ + PROC + EXPORT SysTick_Handler [WEAK] + B . + ENDP + +Default_Handler PROC +; /* external interrupts handler */ + EXPORT WWDGT_IRQHandler [WEAK] + EXPORT LVD_IRQHandler [WEAK] + EXPORT TAMPER_IRQHandler [WEAK] + EXPORT RTC_IRQHandler [WEAK] + EXPORT FMC_IRQHandler [WEAK] + EXPORT RCU_CTC_IRQHandler [WEAK] + EXPORT EXTI0_IRQHandler [WEAK] + EXPORT EXTI1_IRQHandler [WEAK] + EXPORT EXTI2_IRQHandler [WEAK] + EXPORT EXTI3_IRQHandler [WEAK] + EXPORT EXTI4_IRQHandler [WEAK] + EXPORT DMA0_Channel0_IRQHandler [WEAK] + EXPORT DMA0_Channel1_IRQHandler [WEAK] + EXPORT DMA0_Channel2_IRQHandler [WEAK] + EXPORT DMA0_Channel3_IRQHandler [WEAK] + EXPORT DMA0_Channel4_IRQHandler [WEAK] + EXPORT DMA0_Channel5_IRQHandler [WEAK] + EXPORT DMA0_Channel6_IRQHandler [WEAK] + EXPORT ADC0_1_IRQHandler [WEAK] + EXPORT USBD_HP_CAN0_TX_IRQHandler [WEAK] + EXPORT USBD_LP_CAN0_RX0_IRQHandler [WEAK] + EXPORT CAN0_RX1_IRQHandler [WEAK] + EXPORT CAN0_EWMC_IRQHandler [WEAK] + EXPORT EXTI5_9_IRQHandler [WEAK] + EXPORT TIMER0_BRK_IRQHandler [WEAK] + EXPORT TIMER0_UP_IRQHandler [WEAK] + EXPORT TIMER0_TRG_CMT_IRQHandler [WEAK] + EXPORT TIMER0_Channel_IRQHandler [WEAK] + EXPORT TIMER1_IRQHandler [WEAK] + EXPORT TIMER2_IRQHandler [WEAK] + EXPORT TIMER3_IRQHandler [WEAK] + EXPORT I2C0_EV_IRQHandler [WEAK] + EXPORT I2C0_ER_IRQHandler [WEAK] + EXPORT I2C1_EV_IRQHandler [WEAK] + EXPORT I2C1_ER_IRQHandler [WEAK] + EXPORT SPI0_IRQHandler [WEAK] + EXPORT SPI1_IRQHandler [WEAK] + EXPORT USART0_IRQHandler [WEAK] + EXPORT USART1_IRQHandler [WEAK] + EXPORT USART2_IRQHandler [WEAK] + EXPORT EXTI10_15_IRQHandler [WEAK] + EXPORT RTC_Alarm_IRQHandler [WEAK] + EXPORT USBD_WKUP_IRQHandler [WEAK] + EXPORT TIMER7_BRK_IRQHandler [WEAK] + EXPORT TIMER7_UP_IRQHandler [WEAK] + EXPORT TIMER7_TRG_CMT_IRQHandler [WEAK] + EXPORT TIMER7_Channel_IRQHandler [WEAK] + EXPORT ADC2_IRQHandler [WEAK] + EXPORT EXMC_IRQHandler [WEAK] + EXPORT SDIO_IRQHandler [WEAK] + EXPORT TIMER4_IRQHandler [WEAK] + EXPORT SPI2_IRQHandler [WEAK] + EXPORT UART3_IRQHandler [WEAK] + EXPORT UART4_IRQHandler [WEAK] + EXPORT TIMER5_IRQHandler [WEAK] + EXPORT TIMER6_IRQHandler [WEAK] + EXPORT DMA1_Channel0_IRQHandler [WEAK] + EXPORT DMA1_Channel1_IRQHandler [WEAK] + EXPORT DMA1_Channel2_IRQHandler [WEAK] + EXPORT DMA1_Channel3_4_IRQHandler [WEAK] + +;/* external interrupts handler */ +WWDGT_IRQHandler +LVD_IRQHandler +TAMPER_IRQHandler +RTC_IRQHandler +FMC_IRQHandler +RCU_CTC_IRQHandler +EXTI0_IRQHandler +EXTI1_IRQHandler +EXTI2_IRQHandler +EXTI3_IRQHandler +EXTI4_IRQHandler +DMA0_Channel0_IRQHandler +DMA0_Channel1_IRQHandler +DMA0_Channel2_IRQHandler +DMA0_Channel3_IRQHandler +DMA0_Channel4_IRQHandler +DMA0_Channel5_IRQHandler +DMA0_Channel6_IRQHandler +ADC0_1_IRQHandler +USBD_HP_CAN0_TX_IRQHandler +USBD_LP_CAN0_RX0_IRQHandler +CAN0_RX1_IRQHandler +CAN0_EWMC_IRQHandler +EXTI5_9_IRQHandler +TIMER0_BRK_IRQHandler +TIMER0_UP_IRQHandler +TIMER0_TRG_CMT_IRQHandler +TIMER0_Channel_IRQHandler +TIMER1_IRQHandler +TIMER2_IRQHandler +TIMER3_IRQHandler +I2C0_EV_IRQHandler +I2C0_ER_IRQHandler +I2C1_EV_IRQHandler +I2C1_ER_IRQHandler +SPI0_IRQHandler +SPI1_IRQHandler +USART0_IRQHandler +USART1_IRQHandler +USART2_IRQHandler +EXTI10_15_IRQHandler +RTC_Alarm_IRQHandler +USBD_WKUP_IRQHandler +TIMER7_BRK_IRQHandler +TIMER7_UP_IRQHandler +TIMER7_TRG_CMT_IRQHandler +TIMER7_Channel_IRQHandler +ADC2_IRQHandler +EXMC_IRQHandler +SDIO_IRQHandler +TIMER4_IRQHandler +SPI2_IRQHandler +UART3_IRQHandler +UART4_IRQHandler +TIMER5_IRQHandler +TIMER6_IRQHandler +DMA1_Channel0_IRQHandler +DMA1_Channel1_IRQHandler +DMA1_Channel2_IRQHandler +DMA1_Channel3_4_IRQHandler + + B . + ENDP + + ALIGN + +; user Initial Stack & Heap + + IF :DEF:__MICROLIB + + EXPORT __initial_sp + EXPORT __heap_base + EXPORT __heap_limit + + ELSE + + IMPORT __use_two_region_memory + EXPORT __user_initial_stackheap + +__user_initial_stackheap PROC + LDR R0, = Heap_Mem + LDR R1, =(Stack_Mem + Stack_Size) + LDR R2, = (Heap_Mem + Heap_Size) + LDR R3, = Stack_Mem + BX LR + ENDP + + ALIGN + + ENDIF + + END diff --git a/bsp/gd32/libraries/GD32F30x_Firmware_Library/CMSIS/GD/GD32F30x/Source/ARM/startup_gd32f30x_xd.s b/bsp/gd32/libraries/GD32F30x_Firmware_Library/CMSIS/GD/GD32F30x/Source/ARM/startup_gd32f30x_xd.s new file mode 100644 index 0000000000..4475675eca --- /dev/null +++ b/bsp/gd32/libraries/GD32F30x_Firmware_Library/CMSIS/GD/GD32F30x/Source/ARM/startup_gd32f30x_xd.s @@ -0,0 +1,365 @@ +;/*! +; \file startup_gd32f30x_xd.s +; \brief start up file +; +; \version 2017-02-10, V1.0.0, firmware for GD32F30x +; \version 2018-10-10, V1.1.0, firmware for GD32F30x +; \version 2018-12-25, V2.0.0, firmware for GD32F30x +; \version 2020-09-30, V2.1.0, firmware for GD32F30x +;*/ +; +;/* +; Copyright (c) 2020, GigaDevice Semiconductor Inc. + +; Redistribution and use in source and binary forms, with or without modification, +;are permitted provided that the following conditions are met: +; +; 1. Redistributions of source code must retain the above copyright notice, this +; list of conditions and the following disclaimer. +; 2. Redistributions in binary form must reproduce the above copyright notice, +; this list of conditions and the following disclaimer in the documentation +; and/or other materials provided with the distribution. +; 3. Neither the name of the copyright holder nor the names of its contributors +; may be used to endorse or promote products derived from this software without +; specific prior written permission. +; +; THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +;AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +;WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +;IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +;INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +;NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +;PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +;WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +;ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +;OF SUCH DAMAGE. +;*/ + +; Stack Configuration +; Stack Size (in Bytes) <0x0-0xFFFFFFFF:8> +; + +Stack_Size EQU 0x00000400 + + AREA STACK, NOINIT, READWRITE, ALIGN=3 +Stack_Mem SPACE Stack_Size +__initial_sp + + +; Heap Configuration +; Heap Size (in Bytes) <0x0-0xFFFFFFFF:8> +; + +Heap_Size EQU 0x00000400 + + AREA HEAP, NOINIT, READWRITE, ALIGN=3 +__heap_base +Heap_Mem SPACE Heap_Size +__heap_limit + + PRESERVE8 + THUMB + +; /* reset Vector Mapped to at Address 0 */ + AREA RESET, DATA, READONLY + EXPORT __Vectors + EXPORT __Vectors_End + EXPORT __Vectors_Size + +__Vectors DCD __initial_sp ; Top of Stack + DCD Reset_Handler ; Reset Handler + DCD NMI_Handler ; NMI Handler + DCD HardFault_Handler ; Hard Fault Handler + DCD MemManage_Handler ; MPU Fault Handler + DCD BusFault_Handler ; Bus Fault Handler + DCD UsageFault_Handler ; Usage Fault Handler + DCD 0 ; Reserved + DCD 0 ; Reserved + DCD 0 ; Reserved + DCD 0 ; Reserved + DCD SVC_Handler ; SVCall Handler + DCD DebugMon_Handler ; Debug Monitor Handler + DCD 0 ; Reserved + DCD PendSV_Handler ; PendSV Handler + DCD SysTick_Handler ; SysTick Handler + +; /* external interrupts handler */ + DCD WWDGT_IRQHandler ; 16:Window Watchdog Timer + DCD LVD_IRQHandler ; 17:LVD through EXTI Line detect + DCD TAMPER_IRQHandler ; 18:Tamper through EXTI Line detect + DCD RTC_IRQHandler ; 19:RTC through EXTI Line + DCD FMC_IRQHandler ; 20:FMC + DCD RCU_CTC_IRQHandler ; 21:RCU and CTC + DCD EXTI0_IRQHandler ; 22:EXTI Line 0 + DCD EXTI1_IRQHandler ; 23:EXTI Line 1 + DCD EXTI2_IRQHandler ; 24:EXTI Line 2 + DCD EXTI3_IRQHandler ; 25:EXTI Line 3 + DCD EXTI4_IRQHandler ; 26:EXTI Line 4 + DCD DMA0_Channel0_IRQHandler ; 27:DMA0 Channel0 + DCD DMA0_Channel1_IRQHandler ; 28:DMA0 Channel1 + DCD DMA0_Channel2_IRQHandler ; 29:DMA0 Channel2 + DCD DMA0_Channel3_IRQHandler ; 30:DMA0 Channel3 + DCD DMA0_Channel4_IRQHandler ; 31:DMA0 Channel4 + DCD DMA0_Channel5_IRQHandler ; 32:DMA0 Channel5 + DCD DMA0_Channel6_IRQHandler ; 33:DMA0 Channel6 + DCD ADC0_1_IRQHandler ; 34:ADC0 and ADC1 + DCD USBD_HP_CAN0_TX_IRQHandler ; 35:USBD HP and CAN0 TX + DCD USBD_LP_CAN0_RX0_IRQHandler ; 36:USBD LP and CAN0 RX0 + DCD CAN0_RX1_IRQHandler ; 37:CAN0 RX1 + DCD CAN0_EWMC_IRQHandler ; 38:CAN0 EWMC + DCD EXTI5_9_IRQHandler ; 39:EXTI5 to EXTI9 + DCD TIMER0_BRK_TIMER8_IRQHandler ; 40:TIMER0 Break and TIMER8 + DCD TIMER0_UP_TIMER9_IRQHandler ; 41:TIMER0 Update and TIMER9 + DCD TIMER0_TRG_CMT_TIMER10_IRQHandler ; 42:TIMER0 Trigger and Commutation and TIMER10 + DCD TIMER0_Channel_IRQHandler ; 43:TIMER0 Channel Capture Compare + DCD TIMER1_IRQHandler ; 44:TIMER1 + DCD TIMER2_IRQHandler ; 45:TIMER2 + DCD TIMER3_IRQHandler ; 46:TIMER3 + DCD I2C0_EV_IRQHandler ; 47:I2C0 Event + DCD I2C0_ER_IRQHandler ; 48:I2C0 Error + DCD I2C1_EV_IRQHandler ; 49:I2C1 Event + DCD I2C1_ER_IRQHandler ; 50:I2C1 Error + DCD SPI0_IRQHandler ; 51:SPI0 + DCD SPI1_IRQHandler ; 52:SPI1 + DCD USART0_IRQHandler ; 53:USART0 + DCD USART1_IRQHandler ; 54:USART1 + DCD USART2_IRQHandler ; 55:USART2 + DCD EXTI10_15_IRQHandler ; 56:EXTI10 to EXTI15 + DCD RTC_Alarm_IRQHandler ; 57:RTC Alarm + DCD USBD_WKUP_IRQHandler ; 58:USBD Wakeup + DCD TIMER7_BRK_TIMER11_IRQHandler ; 59:TIMER7 Break and TIMER11 + DCD TIMER7_UP_TIMER12_IRQHandler ; 60:TIMER7 Update and TIMER12 + DCD TIMER7_TRG_CMT_TIMER13_IRQHandler ; 61:TIMER7 Trigger and Commutation and TIMER13 + DCD TIMER7_Channel_IRQHandler ; 62:TIMER7 Channel Capture Compare + DCD ADC2_IRQHandler ; 63:ADC2 + DCD EXMC_IRQHandler ; 64:EXMC + DCD SDIO_IRQHandler ; 65:SDIO + DCD TIMER4_IRQHandler ; 66:TIMER4 + DCD SPI2_IRQHandler ; 67:SPI2 + DCD UART3_IRQHandler ; 68:UART3 + DCD UART4_IRQHandler ; 69:UART4 + DCD TIMER5_IRQHandler ; 70:TIMER5 + DCD TIMER6_IRQHandler ; 71:TIMER6 + DCD DMA1_Channel0_IRQHandler ; 72:DMA1 Channel0 + DCD DMA1_Channel1_IRQHandler ; 73:DMA1 Channel1 + DCD DMA1_Channel2_IRQHandler ; 74:DMA1 Channel2 + DCD DMA1_Channel3_4_IRQHandler ; 75:DMA1 Channel3 and Channel4 + +__Vectors_End + +__Vectors_Size EQU __Vectors_End - __Vectors + + AREA |.text|, CODE, READONLY + +;/* reset Handler */ +Reset_Handler PROC + EXPORT Reset_Handler [WEAK] + IMPORT SystemInit + IMPORT __main + LDR R0, =SystemInit + BLX R0 + LDR R0, =__main + BX R0 + ENDP + +;/* dummy Exception Handlers */ +NMI_Handler PROC + EXPORT NMI_Handler [WEAK] + B . + ENDP +HardFault_Handler\ + PROC + EXPORT HardFault_Handler [WEAK] + B . + ENDP +MemManage_Handler\ + PROC + EXPORT MemManage_Handler [WEAK] + B . + ENDP +BusFault_Handler\ + PROC + EXPORT BusFault_Handler [WEAK] + B . + ENDP +UsageFault_Handler\ + PROC + EXPORT UsageFault_Handler [WEAK] + B . + ENDP +SVC_Handler PROC + EXPORT SVC_Handler [WEAK] + B . + ENDP +DebugMon_Handler\ + PROC + EXPORT DebugMon_Handler [WEAK] + B . + ENDP +PendSV_Handler\ + PROC + EXPORT PendSV_Handler [WEAK] + B . + ENDP +SysTick_Handler\ + PROC + EXPORT SysTick_Handler [WEAK] + B . + ENDP + +Default_Handler PROC +; /* external interrupts handler */ + EXPORT WWDGT_IRQHandler [WEAK] + EXPORT LVD_IRQHandler [WEAK] + EXPORT TAMPER_IRQHandler [WEAK] + EXPORT RTC_IRQHandler [WEAK] + EXPORT FMC_IRQHandler [WEAK] + EXPORT RCU_CTC_IRQHandler [WEAK] + EXPORT EXTI0_IRQHandler [WEAK] + EXPORT EXTI1_IRQHandler [WEAK] + EXPORT EXTI2_IRQHandler [WEAK] + EXPORT EXTI3_IRQHandler [WEAK] + EXPORT EXTI4_IRQHandler [WEAK] + EXPORT DMA0_Channel0_IRQHandler [WEAK] + EXPORT DMA0_Channel1_IRQHandler [WEAK] + EXPORT DMA0_Channel2_IRQHandler [WEAK] + EXPORT DMA0_Channel3_IRQHandler [WEAK] + EXPORT DMA0_Channel4_IRQHandler [WEAK] + EXPORT DMA0_Channel5_IRQHandler [WEAK] + EXPORT DMA0_Channel6_IRQHandler [WEAK] + EXPORT ADC0_1_IRQHandler [WEAK] + EXPORT USBD_HP_CAN0_TX_IRQHandler [WEAK] + EXPORT USBD_LP_CAN0_RX0_IRQHandler [WEAK] + EXPORT CAN0_RX1_IRQHandler [WEAK] + EXPORT CAN0_EWMC_IRQHandler [WEAK] + EXPORT EXTI5_9_IRQHandler [WEAK] + EXPORT TIMER0_BRK_TIMER8_IRQHandler [WEAK] + EXPORT TIMER0_UP_TIMER9_IRQHandler [WEAK] + EXPORT TIMER0_TRG_CMT_TIMER10_IRQHandler [WEAK] + EXPORT TIMER0_Channel_IRQHandler [WEAK] + EXPORT TIMER1_IRQHandler [WEAK] + EXPORT TIMER2_IRQHandler [WEAK] + EXPORT TIMER3_IRQHandler [WEAK] + EXPORT I2C0_EV_IRQHandler [WEAK] + EXPORT I2C0_ER_IRQHandler [WEAK] + EXPORT I2C1_EV_IRQHandler [WEAK] + EXPORT I2C1_ER_IRQHandler [WEAK] + EXPORT SPI0_IRQHandler [WEAK] + EXPORT SPI1_IRQHandler [WEAK] + EXPORT USART0_IRQHandler [WEAK] + EXPORT USART1_IRQHandler [WEAK] + EXPORT USART2_IRQHandler [WEAK] + EXPORT EXTI10_15_IRQHandler [WEAK] + EXPORT RTC_Alarm_IRQHandler [WEAK] + EXPORT USBD_WKUP_IRQHandler [WEAK] + EXPORT TIMER7_BRK_TIMER11_IRQHandler [WEAK] + EXPORT TIMER7_UP_TIMER12_IRQHandler [WEAK] + EXPORT TIMER7_TRG_CMT_TIMER13_IRQHandler [WEAK] + EXPORT TIMER7_Channel_IRQHandler [WEAK] + EXPORT ADC2_IRQHandler [WEAK] + EXPORT EXMC_IRQHandler [WEAK] + EXPORT SDIO_IRQHandler [WEAK] + EXPORT TIMER4_IRQHandler [WEAK] + EXPORT SPI2_IRQHandler [WEAK] + EXPORT UART3_IRQHandler [WEAK] + EXPORT UART4_IRQHandler [WEAK] + EXPORT TIMER5_IRQHandler [WEAK] + EXPORT TIMER6_IRQHandler [WEAK] + EXPORT DMA1_Channel0_IRQHandler [WEAK] + EXPORT DMA1_Channel1_IRQHandler [WEAK] + EXPORT DMA1_Channel2_IRQHandler [WEAK] + EXPORT DMA1_Channel3_4_IRQHandler [WEAK] + +;/* external interrupts handler */ +WWDGT_IRQHandler +LVD_IRQHandler +TAMPER_IRQHandler +RTC_IRQHandler +FMC_IRQHandler +RCU_CTC_IRQHandler +EXTI0_IRQHandler +EXTI1_IRQHandler +EXTI2_IRQHandler +EXTI3_IRQHandler +EXTI4_IRQHandler +DMA0_Channel0_IRQHandler +DMA0_Channel1_IRQHandler +DMA0_Channel2_IRQHandler +DMA0_Channel3_IRQHandler +DMA0_Channel4_IRQHandler +DMA0_Channel5_IRQHandler +DMA0_Channel6_IRQHandler +ADC0_1_IRQHandler +USBD_HP_CAN0_TX_IRQHandler +USBD_LP_CAN0_RX0_IRQHandler +CAN0_RX1_IRQHandler +CAN0_EWMC_IRQHandler +EXTI5_9_IRQHandler +TIMER0_BRK_TIMER8_IRQHandler +TIMER0_UP_TIMER9_IRQHandler +TIMER0_TRG_CMT_TIMER10_IRQHandler +TIMER0_Channel_IRQHandler +TIMER1_IRQHandler +TIMER2_IRQHandler +TIMER3_IRQHandler +I2C0_EV_IRQHandler +I2C0_ER_IRQHandler +I2C1_EV_IRQHandler +I2C1_ER_IRQHandler +SPI0_IRQHandler +SPI1_IRQHandler +USART0_IRQHandler +USART1_IRQHandler +USART2_IRQHandler +EXTI10_15_IRQHandler +RTC_Alarm_IRQHandler +USBD_WKUP_IRQHandler +TIMER7_BRK_TIMER11_IRQHandler +TIMER7_UP_TIMER12_IRQHandler +TIMER7_TRG_CMT_TIMER13_IRQHandler +TIMER7_Channel_IRQHandler +ADC2_IRQHandler +EXMC_IRQHandler +SDIO_IRQHandler +TIMER4_IRQHandler +SPI2_IRQHandler +UART3_IRQHandler +UART4_IRQHandler +TIMER5_IRQHandler +TIMER6_IRQHandler +DMA1_Channel0_IRQHandler +DMA1_Channel1_IRQHandler +DMA1_Channel2_IRQHandler +DMA1_Channel3_4_IRQHandler + + B . + ENDP + + ALIGN + +; user Initial Stack & Heap + + IF :DEF:__MICROLIB + + EXPORT __initial_sp + EXPORT __heap_base + EXPORT __heap_limit + + ELSE + + IMPORT __use_two_region_memory + EXPORT __user_initial_stackheap + +__user_initial_stackheap PROC + LDR R0, = Heap_Mem + LDR R1, =(Stack_Mem + Stack_Size) + LDR R2, = (Heap_Mem + Heap_Size) + LDR R3, = Stack_Mem + BX LR + ENDP + + ALIGN + + ENDIF + + END diff --git a/bsp/gd32/libraries/GD32F30x_Firmware_Library/CMSIS/GD/GD32F30x/Source/GCC/startup_gd32f30x_cl.s b/bsp/gd32/libraries/GD32F30x_Firmware_Library/CMSIS/GD/GD32F30x/Source/GCC/startup_gd32f30x_cl.s new file mode 100644 index 0000000000..8db890e280 --- /dev/null +++ b/bsp/gd32/libraries/GD32F30x_Firmware_Library/CMSIS/GD/GD32F30x/Source/GCC/startup_gd32f30x_cl.s @@ -0,0 +1,271 @@ +;/* +; * Copyright (c) 2006-2021, RT-Thread Development Team +; * +; * SPDX-License-Identifier: Apache-2.0 +; * +; * Change Logs: +; * Date Author Notes +; * 2021-12-18 BruceOu first implementation +; */ + +.syntax unified +.cpu cortex-m4 +.fpu softvfp +.thumb + +.global g_pfnVectors +.global Default_Handler + + .section .isr_vector,"a",%progbits + .type g_pfnVectors, %object + +g_pfnVectors: + .word _estack // Top of Stack + .word Reset_Handler // Reset Handler + .word NMI_Handler // NMI Handler + .word HardFault_Handler // Hard Fault Handler + .word MemManage_Handler // MPU Fault Handler + .word BusFault_Handler // Bus Fault Handler + .word UsageFault_Handler // Usage Fault Handler + .word 0 // Reserved + .word 0 // Reserved + .word 0 // Reserved + .word 0 // Reserved + .word SVC_Handler // SVCall Handler + .word DebugMon_Handler // Debug Monitor Handler + .word 0 // Reserved + .word PendSV_Handler // PendSV Handler + .word SysTick_Handler // SysTick Handler + + // external interrupts handler + .word WWDGT_IRQHandler // 16:Window Watchdog Timer + .word LVD_IRQHandler // 17:LVD through EXTI Line detect + .word TAMPER_IRQHandler // 18:Tamper through EXTI Line detect + .word RTC_IRQHandler // 19:RTC through EXTI Line + .word FMC_IRQHandler // 20:FMC + .word RCU_CTC_IRQHandler // 21:RCU and CTC + .word EXTI0_IRQHandler // 22:EXTI Line 0 + .word EXTI1_IRQHandler // 23:EXTI Line 1 + .word EXTI2_IRQHandler // 24:EXTI Line 2 + .word EXTI3_IRQHandler // 25:EXTI Line 3 + .word EXTI4_IRQHandler // 26:EXTI Line 4 + .word DMA0_Channel0_IRQHandler // 27:DMA0 Channel0 + .word DMA0_Channel1_IRQHandler // 28:DMA0 Channel1 + .word DMA0_Channel2_IRQHandler // 29:DMA0 Channel2 + .word DMA0_Channel3_IRQHandler // 30:DMA0 Channel3 + .word DMA0_Channel4_IRQHandler // 31:DMA0 Channel4 + .word DMA0_Channel5_IRQHandler // 32:DMA0 Channel5 + .word DMA0_Channel6_IRQHandler // 33:DMA0 Channel6 + .word ADC0_1_IRQHandler // 34:ADC0 and ADC1 + .word USBD_HP_CAN0_TX_IRQHandler // 35:USBD HP and CAN0 TX + .word USBD_LP_CAN0_RX0_IRQHandler // 36:USBD LP and CAN0 RX0 + .word CAN0_RX1_IRQHandler // 37:CAN0 RX1 + .word CAN0_EWMC_IRQHandler // 38:CAN0 EWMC + .word EXTI5_9_IRQHandler // 39:EXTI5 to EXTI9 + .word TIMER0_BRK_IRQHandler // 40:TIMER0 Break + .word TIMER0_UP_IRQHandler // 41:TIMER0 Update + .word TIMER0_TRG_CMT_IRQHandler // 42:TIMER0 Trigger and Commutation + .word TIMER0_Channel_IRQHandler // 43:TIMER0 Channel Capture Compare + .word TIMER1_IRQHandler // 44:TIMER1 + .word TIMER2_IRQHandler // 45:TIMER2 + .word TIMER3_IRQHandler // 46:TIMER3 + .word I2C0_EV_IRQHandler // 47:I2C0 Event + .word I2C0_ER_IRQHandler // 48:I2C0 Error + .word I2C1_EV_IRQHandler // 49:I2C1 Event + .word I2C1_ER_IRQHandler // 50:I2C1 Error + .word SPI0_IRQHandler // 51:SPI0 + .word SPI1_IRQHandler // 52:SPI1 + .word USART0_IRQHandler // 53:USART0 + .word USART1_IRQHandler // 54:USART1 + .word USART2_IRQHandler // 55:USART2 + .word EXTI10_15_IRQHandler // 56:EXTI10 to EXTI15 + .word RTC_Alarm_IRQHandler // 57:RTC Alarm + .word USBD_WKUP_IRQHandler // 58:USBD Wakeup + .word TIMER7_BRK_IRQHandler // 59:TIMER7 Break + .word TIMER7_UP_IRQHandler // 60:TIMER7 Update + .word TIMER7_TRG_CMT_IRQHandler // 61:TIMER7 Trigger and Commutation + .word TIMER7_Channel_IRQHandler // 62:TIMER7 Channel Capture Compare + .word 0 // 63:Reserved + .word EXMC_IRQHandler // 64:EXMC + .word 0 // 65:Reserved + .word TIMER4_IRQHandler // 66:TIMER4 + .word SPI2_IRQHandler // 67:SPI2 + .word UART3_IRQHandler // 68:UART3 + .word UART4_IRQHandler // 69:UART4 + .word TIMER5_IRQHandler // 70:TIMER5 + .word TIMER6_IRQHandler // 71:TIMER6 + .word DMA1_Channel0_IRQHandler // 72:DMA1 Channel0 + .word DMA1_Channel1_IRQHandler // 73:DMA1 Channel1 + .word DMA1_Channel2_IRQHandler // 74:DMA1 Channel2 + .word DMA1_Channel3_IRQHandler // 75:DMA1 Channel3 + .word ENET_IRQHandler // 77:Ethernet + .word ENET_WKUP_IRQHandler // 78:Ethernet Wakeup through EXTI Line + .word CAN1_TX_IRQHandler // 79:CAN1 TX + .word CAN1_RX0_IRQHandler // 80:CAN1 RX0 + .word CAN1_RX1_IRQHandler // 81:CAN1 RX1 + .word CAN1_EWMC_IRQHandler // 82:CAN1 EWMC + .word USBFS_IRQHandler // 83:USBFS + + .size g_pfnVectors, .-g_pfnVectors + + .section .text.Reset_Handler + .weak Reset_Handler + .type Reset_Handler, %function +Reset_Handler: + ldr r1, =_sidata + ldr r2, =_sdata + ldr r3, =_edata + + subs r3, r2 + ble fill_bss_start + +loop_copy_data: + subs r3, #4 + ldr r0, [r1,r3] + str r0, [r2,r3] + bgt loop_copy_data + +fill_bss_start: + ldr r1, =__bss_start + ldr r2, =__bss_end + movs r0, 0 + subs r2, r1 + ble startup_enter + +loop_fill_bss: + subs r2, #4 + str r0, [r1, r2] + bgt loop_fill_bss + +startup_enter: + bl SystemInit + bl entry + + /* Exception Handlers */ + .weak NMI_Handler + .type NMI_Handler, %function +NMI_Handler: + b . + .size NMI_Handler, . - NMI_Handler + + .weak MemManage_Handler + .type MemManage_Handler, %function +MemManage_Handler: + b . + .size MemManage_Handler, . - MemManage_Handler + + .weak BusFault_Handler + .type BusFault_Handler, %function +BusFault_Handler: + b . + .size BusFault_Handler, . - BusFault_Handler + + .weak UsageFault_Handler + .type UsageFault_Handler, %function +UsageFault_Handler: + b . + .size UsageFault_Handler, . - UsageFault_Handler + + .weak SVC_Handler + .type SVC_Handler, %function +SVC_Handler: + b . + .size SVC_Handler, . - SVC_Handler + + .weak DebugMon_Handler + .type DebugMon_Handler, %function +DebugMon_Handler: + b . + .size DebugMon_Handler, . - DebugMon_Handler + + .weak PendSV_Handler + .type PendSV_Handler, %function +PendSV_Handler: + b . + .size PendSV_Handler, . - PendSV_Handler + + .weak SysTick_Handler + .type SysTick_Handler, %function +SysTick_Handler: + b . + .size SysTick_Handler, . - SysTick_Handler + + /* IQR Handler */ + .section .text.Default_Handler,"ax",%progbits + .type Default_Handler, %function +Default_Handler: + b . + .size Default_Handler, . - Default_Handler + + .macro IRQ handler + .weak \handler + .set \handler, Default_Handler + .endm + + IRQ WWDGT_IRQHandler + IRQ LVD_IRQHandler + IRQ TAMPER_IRQHandler + IRQ RTC_IRQHandler + IRQ FMC_IRQHandler + IRQ RCU_CTC_IRQHandler + IRQ EXTI0_IRQHandler + IRQ EXTI1_IRQHandler + IRQ EXTI2_IRQHandler + IRQ EXTI3_IRQHandler + IRQ EXTI4_IRQHandler + IRQ DMA0_Channel0_IRQHandler + IRQ DMA0_Channel1_IRQHandler + IRQ DMA0_Channel2_IRQHandler + IRQ DMA0_Channel3_IRQHandler + IRQ DMA0_Channel4_IRQHandler + IRQ DMA0_Channel5_IRQHandler + IRQ DMA0_Channel6_IRQHandler + IRQ ADC0_1_IRQHandler + IRQ USBD_HP_CAN0_TX_IRQHandler + IRQ USBD_LP_CAN0_RX0_IRQHandler + IRQ CAN0_RX1_IRQHandler + IRQ CAN0_EWMC_IRQHandler + IRQ EXTI5_9_IRQHandler + IRQ TIMER0_BRK_IRQHandler + IRQ TIMER0_UP_IRQHandler + IRQ TIMER0_TRG_CMT_IRQHandler + IRQ TIMER0_Channel_IRQHandler + IRQ TIMER1_IRQHandler + IRQ TIMER2_IRQHandler + IRQ TIMER3_IRQHandler + IRQ I2C0_EV_IRQHandler + IRQ I2C0_ER_IRQHandler + IRQ I2C1_EV_IRQHandler + IRQ I2C1_ER_IRQHandler + IRQ SPI0_IRQHandler + IRQ SPI1_IRQHandler + IRQ USART0_IRQHandler + IRQ USART1_IRQHandler + IRQ USART2_IRQHandler + IRQ EXTI10_15_IRQHandler + IRQ RTC_Alarm_IRQHandler + IRQ USBD_WKUP_IRQHandler + IRQ TIMER7_BRK_IRQHandler + IRQ TIMER7_UP_IRQHandler + IRQ TIMER7_TRG_CMT_IRQHandler + IRQ TIMER7_Channel_IRQHandler + IRQ ADC2_IRQHandler + IRQ EXMC_IRQHandler + IRQ SDIO_IRQHandler + IRQ TIMER4_IRQHandler + IRQ SPI2_IRQHandler + IRQ UART3_IRQHandler + IRQ UART4_IRQHandler + IRQ TIMER5_IRQHandler + IRQ TIMER6_IRQHandler + IRQ DMA1_Channel0_IRQHandler + IRQ DMA1_Channel1_IRQHandler + IRQ DMA1_Channel2_IRQHandler + IRQ DMA1_Channel3_IRQHandler + IRQ ENET_IRQHandler + IRQ ENET_WKUP_IRQHandler + IRQ CAN1_TX_IRQHandler + IRQ CAN1_RX0_IRQHandler + IRQ CAN1_RX1_IRQHandler + IRQ CAN1_EWMC_IRQHandler + IRQ USBFS_IRQHandlerBFS diff --git a/bsp/gd32/libraries/GD32F30x_Firmware_Library/CMSIS/GD/GD32F30x/Source/GCC/startup_gd32f30x_hd.s b/bsp/gd32/libraries/GD32F30x_Firmware_Library/CMSIS/GD/GD32F30x/Source/GCC/startup_gd32f30x_hd.s new file mode 100644 index 0000000000..a65aa8ed0c --- /dev/null +++ b/bsp/gd32/libraries/GD32F30x_Firmware_Library/CMSIS/GD/GD32F30x/Source/GCC/startup_gd32f30x_hd.s @@ -0,0 +1,257 @@ +;/* +; * Copyright (c) 2006-2021, RT-Thread Development Team +; * +; * SPDX-License-Identifier: Apache-2.0 +; * +; * Change Logs: +; * Date Author Notes +; * 2021-12-18 BruceOu first implementation +; */ + +.syntax unified +.cpu cortex-m4 +.fpu softvfp +.thumb + +.global g_pfnVectors +.global Default_Handler + + .section .isr_vector,"a",%progbits + .type g_pfnVectors, %object + +g_pfnVectors: + .word _estack // Top of Stack + .word Reset_Handler // Reset Handler + .word NMI_Handler // NMI Handler + .word HardFault_Handler // Hard Fault Handler + .word MemManage_Handler // MPU Fault Handler + .word BusFault_Handler // Bus Fault Handler + .word UsageFault_Handler // Usage Fault Handler + .word 0 // Reserved + .word 0 // Reserved + .word 0 // Reserved + .word 0 // Reserved + .word SVC_Handler // SVCall Handler + .word DebugMon_Handler // Debug Monitor Handler + .word 0 // Reserved + .word PendSV_Handler // PendSV Handler + .word SysTick_Handler // SysTick Handler + + // external interrupts handler + .word WWDGT_IRQHandler // 16:Window Watchdog Timer + .word LVD_IRQHandler // 17:LVD through EXTI Line detect + .word TAMPER_IRQHandler // 18:Tamper through EXTI Line detect + .word RTC_IRQHandler // 19:RTC through EXTI Line + .word FMC_IRQHandler // 20:FMC + .word RCU_CTC_IRQHandler // 21:RCU and CTC + .word EXTI0_IRQHandler // 22:EXTI Line 0 + .word EXTI1_IRQHandler // 23:EXTI Line 1 + .word EXTI2_IRQHandler // 24:EXTI Line 2 + .word EXTI3_IRQHandler // 25:EXTI Line 3 + .word EXTI4_IRQHandler // 26:EXTI Line 4 + .word DMA0_Channel0_IRQHandler // 27:DMA0 Channel0 + .word DMA0_Channel1_IRQHandler // 28:DMA0 Channel1 + .word DMA0_Channel2_IRQHandler // 29:DMA0 Channel2 + .word DMA0_Channel3_IRQHandler // 30:DMA0 Channel3 + .word DMA0_Channel4_IRQHandler // 31:DMA0 Channel4 + .word DMA0_Channel5_IRQHandler // 32:DMA0 Channel5 + .word DMA0_Channel6_IRQHandler // 33:DMA0 Channel6 + .word ADC0_1_IRQHandler // 34:ADC0 and ADC1 + .word USBD_HP_CAN0_TX_IRQHandler // 35:USBD HP and CAN0 TX + .word USBD_LP_CAN0_RX0_IRQHandler // 36:USBD LP and CAN0 RX0 + .word CAN0_RX1_IRQHandler // 37:CAN0 RX1 + .word CAN0_EWMC_IRQHandler // 38:CAN0 EWMC + .word EXTI5_9_IRQHandler // 39:EXTI5 to EXTI9 + .word TIMER0_BRK_IRQHandler // 40:TIMER0 Break + .word TIMER0_UP_IRQHandler // 41:TIMER0 Update + .word TIMER0_TRG_CMT_IRQHandler // 42:TIMER0 Trigger and Commutation + .word TIMER0_Channel_IRQHandler // 43:TIMER0 Channel Capture Compare + .word TIMER1_IRQHandler // 44:TIMER1 + .word TIMER2_IRQHandler // 45:TIMER2 + .word TIMER3_IRQHandler // 46:TIMER3 + .word I2C0_EV_IRQHandler // 47:I2C0 Event + .word I2C0_ER_IRQHandler // 48:I2C0 Error + .word I2C1_EV_IRQHandler // 49:I2C1 Event + .word I2C1_ER_IRQHandler // 50:I2C1 Error + .word SPI0_IRQHandler // 51:SPI0 + .word SPI1_IRQHandler // 52:SPI1 + .word USART0_IRQHandler // 53:USART0 + .word USART1_IRQHandler // 54:USART1 + .word USART2_IRQHandler // 55:USART2 + .word EXTI10_15_IRQHandler // 56:EXTI10 to EXTI15 + .word RTC_Alarm_IRQHandler // 57:RTC Alarm + .word USBD_WKUP_IRQHandler // 58:USBD Wakeup + .word TIMER7_BRK_IRQHandler // 59:TIMER7 Break + .word TIMER7_UP_IRQHandler // 60:TIMER7 Update + .word TIMER7_TRG_CMT_IRQHandler // 61:TIMER7 Trigger and Commutation + .word TIMER7_Channel_IRQHandler // 62:TIMER7 Channel Capture Compare + .word ADC2_IRQHandler // 63:ADC2 + .word EXMC_IRQHandler // 64:EXMC + .word SDIO_IRQHandler // 65:SDIO + .word TIMER4_IRQHandler // 66:TIMER4 + .word SPI2_IRQHandler // 67:SPI2 + .word UART3_IRQHandler // 68:UART3 + .word UART4_IRQHandler // 69:UART4 + .word TIMER5_IRQHandler // 70:TIMER5 + .word TIMER6_IRQHandler // 71:TIMER6 + .word DMA1_Channel0_IRQHandler // 72:DMA1 Channel0 + .word DMA1_Channel1_IRQHandler // 73:DMA1 Channel1 + .word DMA1_Channel2_IRQHandler // 74:DMA1 Channel2 + .word DMA1_Channel3_4_IRQHandler // 75:DMA1 Channel3 and Channel4 + + .size g_pfnVectors, .-g_pfnVectors + + .section .text.Reset_Handler + .weak Reset_Handler + .type Reset_Handler, %function +Reset_Handler: + ldr r1, =_sidata + ldr r2, =_sdata + ldr r3, =_edata + + subs r3, r2 + ble fill_bss_start + +loop_copy_data: + subs r3, #4 + ldr r0, [r1,r3] + str r0, [r2,r3] + bgt loop_copy_data + +fill_bss_start: + ldr r1, =__bss_start + ldr r2, =__bss_end + movs r0, 0 + subs r2, r1 + ble startup_enter + +loop_fill_bss: + subs r2, #4 + str r0, [r1, r2] + bgt loop_fill_bss + +startup_enter: + bl SystemInit + bl entry + + /* Exception Handlers */ + .weak NMI_Handler + .type NMI_Handler, %function +NMI_Handler: + b . + .size NMI_Handler, . - NMI_Handler + + .weak MemManage_Handler + .type MemManage_Handler, %function +MemManage_Handler: + b . + .size MemManage_Handler, . - MemManage_Handler + + .weak BusFault_Handler + .type BusFault_Handler, %function +BusFault_Handler: + b . + .size BusFault_Handler, . - BusFault_Handler + + .weak UsageFault_Handler + .type UsageFault_Handler, %function +UsageFault_Handler: + b . + .size UsageFault_Handler, . - UsageFault_Handler + + .weak SVC_Handler + .type SVC_Handler, %function +SVC_Handler: + b . + .size SVC_Handler, . - SVC_Handler + + .weak DebugMon_Handler + .type DebugMon_Handler, %function +DebugMon_Handler: + b . + .size DebugMon_Handler, . - DebugMon_Handler + + .weak PendSV_Handler + .type PendSV_Handler, %function +PendSV_Handler: + b . + .size PendSV_Handler, . - PendSV_Handler + + .weak SysTick_Handler + .type SysTick_Handler, %function +SysTick_Handler: + b . + .size SysTick_Handler, . - SysTick_Handler + + /* IQR Handler */ + .section .text.Default_Handler,"ax",%progbits + .type Default_Handler, %function +Default_Handler: + b . + .size Default_Handler, . - Default_Handler + + .macro IRQ handler + .weak \handler + .set \handler, Default_Handler + .endm + + IRQ WWDGT_IRQHandler + IRQ LVD_IRQHandler + IRQ TAMPER_IRQHandler + IRQ RTC_IRQHandler + IRQ FMC_IRQHandler + IRQ RCU_CTC_IRQHandler + IRQ EXTI0_IRQHandler + IRQ EXTI1_IRQHandler + IRQ EXTI2_IRQHandler + IRQ EXTI3_IRQHandler + IRQ EXTI4_IRQHandler + IRQ DMA0_Channel0_IRQHandler + IRQ DMA0_Channel1_IRQHandler + IRQ DMA0_Channel2_IRQHandler + IRQ DMA0_Channel3_IRQHandler + IRQ DMA0_Channel4_IRQHandler + IRQ DMA0_Channel5_IRQHandler + IRQ DMA0_Channel6_IRQHandler + IRQ ADC0_1_IRQHandler + IRQ USBD_HP_CAN0_TX_IRQHandler + IRQ USBD_LP_CAN0_RX0_IRQHandler + IRQ CAN0_RX1_IRQHandler + IRQ CAN0_EWMC_IRQHandler + IRQ EXTI5_9_IRQHandler + IRQ TIMER0_BRK_IRQHandler + IRQ TIMER0_UP_IRQHandler + IRQ TIMER0_TRG_CMT_IRQHandler + IRQ TIMER0_Channel_IRQHandler + IRQ TIMER1_IRQHandler + IRQ TIMER2_IRQHandler + IRQ TIMER3_IRQHandler + IRQ I2C0_EV_IRQHandler + IRQ I2C0_ER_IRQHandler + IRQ I2C1_EV_IRQHandler + IRQ I2C1_ER_IRQHandler + IRQ SPI0_IRQHandler + IRQ SPI1_IRQHandler + IRQ USART0_IRQHandler + IRQ USART1_IRQHandler + IRQ USART2_IRQHandler + IRQ EXTI10_15_IRQHandler + IRQ RTC_Alarm_IRQHandler + IRQ USBD_WKUP_IRQHandler + IRQ TIMER7_BRK_IRQHandler + IRQ TIMER7_UP_IRQHandler + IRQ TIMER7_TRG_CMT_IRQHandler + IRQ TIMER7_Channel_IRQHandler + IRQ ADC2_IRQHandler + IRQ EXMC_IRQHandler + IRQ SDIO_IRQHandler + IRQ TIMER4_IRQHandler + IRQ SPI2_IRQHandler + IRQ UART3_IRQHandler + IRQ UART4_IRQHandler + IRQ TIMER5_IRQHandler + IRQ TIMER6_IRQHandler + IRQ DMA1_Channel0_IRQHandler + IRQ DMA1_Channel1_IRQHandler + IRQ DMA1_Channel2_IRQHandler + IRQ DMA1_Channel3_4_IRQHandler diff --git a/bsp/gd32/libraries/GD32F30x_Firmware_Library/CMSIS/GD/GD32F30x/Source/GCC/startup_gd32f30x_xd.s b/bsp/gd32/libraries/GD32F30x_Firmware_Library/CMSIS/GD/GD32F30x/Source/GCC/startup_gd32f30x_xd.s new file mode 100644 index 0000000000..a65aa8ed0c --- /dev/null +++ b/bsp/gd32/libraries/GD32F30x_Firmware_Library/CMSIS/GD/GD32F30x/Source/GCC/startup_gd32f30x_xd.s @@ -0,0 +1,257 @@ +;/* +; * Copyright (c) 2006-2021, RT-Thread Development Team +; * +; * SPDX-License-Identifier: Apache-2.0 +; * +; * Change Logs: +; * Date Author Notes +; * 2021-12-18 BruceOu first implementation +; */ + +.syntax unified +.cpu cortex-m4 +.fpu softvfp +.thumb + +.global g_pfnVectors +.global Default_Handler + + .section .isr_vector,"a",%progbits + .type g_pfnVectors, %object + +g_pfnVectors: + .word _estack // Top of Stack + .word Reset_Handler // Reset Handler + .word NMI_Handler // NMI Handler + .word HardFault_Handler // Hard Fault Handler + .word MemManage_Handler // MPU Fault Handler + .word BusFault_Handler // Bus Fault Handler + .word UsageFault_Handler // Usage Fault Handler + .word 0 // Reserved + .word 0 // Reserved + .word 0 // Reserved + .word 0 // Reserved + .word SVC_Handler // SVCall Handler + .word DebugMon_Handler // Debug Monitor Handler + .word 0 // Reserved + .word PendSV_Handler // PendSV Handler + .word SysTick_Handler // SysTick Handler + + // external interrupts handler + .word WWDGT_IRQHandler // 16:Window Watchdog Timer + .word LVD_IRQHandler // 17:LVD through EXTI Line detect + .word TAMPER_IRQHandler // 18:Tamper through EXTI Line detect + .word RTC_IRQHandler // 19:RTC through EXTI Line + .word FMC_IRQHandler // 20:FMC + .word RCU_CTC_IRQHandler // 21:RCU and CTC + .word EXTI0_IRQHandler // 22:EXTI Line 0 + .word EXTI1_IRQHandler // 23:EXTI Line 1 + .word EXTI2_IRQHandler // 24:EXTI Line 2 + .word EXTI3_IRQHandler // 25:EXTI Line 3 + .word EXTI4_IRQHandler // 26:EXTI Line 4 + .word DMA0_Channel0_IRQHandler // 27:DMA0 Channel0 + .word DMA0_Channel1_IRQHandler // 28:DMA0 Channel1 + .word DMA0_Channel2_IRQHandler // 29:DMA0 Channel2 + .word DMA0_Channel3_IRQHandler // 30:DMA0 Channel3 + .word DMA0_Channel4_IRQHandler // 31:DMA0 Channel4 + .word DMA0_Channel5_IRQHandler // 32:DMA0 Channel5 + .word DMA0_Channel6_IRQHandler // 33:DMA0 Channel6 + .word ADC0_1_IRQHandler // 34:ADC0 and ADC1 + .word USBD_HP_CAN0_TX_IRQHandler // 35:USBD HP and CAN0 TX + .word USBD_LP_CAN0_RX0_IRQHandler // 36:USBD LP and CAN0 RX0 + .word CAN0_RX1_IRQHandler // 37:CAN0 RX1 + .word CAN0_EWMC_IRQHandler // 38:CAN0 EWMC + .word EXTI5_9_IRQHandler // 39:EXTI5 to EXTI9 + .word TIMER0_BRK_IRQHandler // 40:TIMER0 Break + .word TIMER0_UP_IRQHandler // 41:TIMER0 Update + .word TIMER0_TRG_CMT_IRQHandler // 42:TIMER0 Trigger and Commutation + .word TIMER0_Channel_IRQHandler // 43:TIMER0 Channel Capture Compare + .word TIMER1_IRQHandler // 44:TIMER1 + .word TIMER2_IRQHandler // 45:TIMER2 + .word TIMER3_IRQHandler // 46:TIMER3 + .word I2C0_EV_IRQHandler // 47:I2C0 Event + .word I2C0_ER_IRQHandler // 48:I2C0 Error + .word I2C1_EV_IRQHandler // 49:I2C1 Event + .word I2C1_ER_IRQHandler // 50:I2C1 Error + .word SPI0_IRQHandler // 51:SPI0 + .word SPI1_IRQHandler // 52:SPI1 + .word USART0_IRQHandler // 53:USART0 + .word USART1_IRQHandler // 54:USART1 + .word USART2_IRQHandler // 55:USART2 + .word EXTI10_15_IRQHandler // 56:EXTI10 to EXTI15 + .word RTC_Alarm_IRQHandler // 57:RTC Alarm + .word USBD_WKUP_IRQHandler // 58:USBD Wakeup + .word TIMER7_BRK_IRQHandler // 59:TIMER7 Break + .word TIMER7_UP_IRQHandler // 60:TIMER7 Update + .word TIMER7_TRG_CMT_IRQHandler // 61:TIMER7 Trigger and Commutation + .word TIMER7_Channel_IRQHandler // 62:TIMER7 Channel Capture Compare + .word ADC2_IRQHandler // 63:ADC2 + .word EXMC_IRQHandler // 64:EXMC + .word SDIO_IRQHandler // 65:SDIO + .word TIMER4_IRQHandler // 66:TIMER4 + .word SPI2_IRQHandler // 67:SPI2 + .word UART3_IRQHandler // 68:UART3 + .word UART4_IRQHandler // 69:UART4 + .word TIMER5_IRQHandler // 70:TIMER5 + .word TIMER6_IRQHandler // 71:TIMER6 + .word DMA1_Channel0_IRQHandler // 72:DMA1 Channel0 + .word DMA1_Channel1_IRQHandler // 73:DMA1 Channel1 + .word DMA1_Channel2_IRQHandler // 74:DMA1 Channel2 + .word DMA1_Channel3_4_IRQHandler // 75:DMA1 Channel3 and Channel4 + + .size g_pfnVectors, .-g_pfnVectors + + .section .text.Reset_Handler + .weak Reset_Handler + .type Reset_Handler, %function +Reset_Handler: + ldr r1, =_sidata + ldr r2, =_sdata + ldr r3, =_edata + + subs r3, r2 + ble fill_bss_start + +loop_copy_data: + subs r3, #4 + ldr r0, [r1,r3] + str r0, [r2,r3] + bgt loop_copy_data + +fill_bss_start: + ldr r1, =__bss_start + ldr r2, =__bss_end + movs r0, 0 + subs r2, r1 + ble startup_enter + +loop_fill_bss: + subs r2, #4 + str r0, [r1, r2] + bgt loop_fill_bss + +startup_enter: + bl SystemInit + bl entry + + /* Exception Handlers */ + .weak NMI_Handler + .type NMI_Handler, %function +NMI_Handler: + b . + .size NMI_Handler, . - NMI_Handler + + .weak MemManage_Handler + .type MemManage_Handler, %function +MemManage_Handler: + b . + .size MemManage_Handler, . - MemManage_Handler + + .weak BusFault_Handler + .type BusFault_Handler, %function +BusFault_Handler: + b . + .size BusFault_Handler, . - BusFault_Handler + + .weak UsageFault_Handler + .type UsageFault_Handler, %function +UsageFault_Handler: + b . + .size UsageFault_Handler, . - UsageFault_Handler + + .weak SVC_Handler + .type SVC_Handler, %function +SVC_Handler: + b . + .size SVC_Handler, . - SVC_Handler + + .weak DebugMon_Handler + .type DebugMon_Handler, %function +DebugMon_Handler: + b . + .size DebugMon_Handler, . - DebugMon_Handler + + .weak PendSV_Handler + .type PendSV_Handler, %function +PendSV_Handler: + b . + .size PendSV_Handler, . - PendSV_Handler + + .weak SysTick_Handler + .type SysTick_Handler, %function +SysTick_Handler: + b . + .size SysTick_Handler, . - SysTick_Handler + + /* IQR Handler */ + .section .text.Default_Handler,"ax",%progbits + .type Default_Handler, %function +Default_Handler: + b . + .size Default_Handler, . - Default_Handler + + .macro IRQ handler + .weak \handler + .set \handler, Default_Handler + .endm + + IRQ WWDGT_IRQHandler + IRQ LVD_IRQHandler + IRQ TAMPER_IRQHandler + IRQ RTC_IRQHandler + IRQ FMC_IRQHandler + IRQ RCU_CTC_IRQHandler + IRQ EXTI0_IRQHandler + IRQ EXTI1_IRQHandler + IRQ EXTI2_IRQHandler + IRQ EXTI3_IRQHandler + IRQ EXTI4_IRQHandler + IRQ DMA0_Channel0_IRQHandler + IRQ DMA0_Channel1_IRQHandler + IRQ DMA0_Channel2_IRQHandler + IRQ DMA0_Channel3_IRQHandler + IRQ DMA0_Channel4_IRQHandler + IRQ DMA0_Channel5_IRQHandler + IRQ DMA0_Channel6_IRQHandler + IRQ ADC0_1_IRQHandler + IRQ USBD_HP_CAN0_TX_IRQHandler + IRQ USBD_LP_CAN0_RX0_IRQHandler + IRQ CAN0_RX1_IRQHandler + IRQ CAN0_EWMC_IRQHandler + IRQ EXTI5_9_IRQHandler + IRQ TIMER0_BRK_IRQHandler + IRQ TIMER0_UP_IRQHandler + IRQ TIMER0_TRG_CMT_IRQHandler + IRQ TIMER0_Channel_IRQHandler + IRQ TIMER1_IRQHandler + IRQ TIMER2_IRQHandler + IRQ TIMER3_IRQHandler + IRQ I2C0_EV_IRQHandler + IRQ I2C0_ER_IRQHandler + IRQ I2C1_EV_IRQHandler + IRQ I2C1_ER_IRQHandler + IRQ SPI0_IRQHandler + IRQ SPI1_IRQHandler + IRQ USART0_IRQHandler + IRQ USART1_IRQHandler + IRQ USART2_IRQHandler + IRQ EXTI10_15_IRQHandler + IRQ RTC_Alarm_IRQHandler + IRQ USBD_WKUP_IRQHandler + IRQ TIMER7_BRK_IRQHandler + IRQ TIMER7_UP_IRQHandler + IRQ TIMER7_TRG_CMT_IRQHandler + IRQ TIMER7_Channel_IRQHandler + IRQ ADC2_IRQHandler + IRQ EXMC_IRQHandler + IRQ SDIO_IRQHandler + IRQ TIMER4_IRQHandler + IRQ SPI2_IRQHandler + IRQ UART3_IRQHandler + IRQ UART4_IRQHandler + IRQ TIMER5_IRQHandler + IRQ TIMER6_IRQHandler + IRQ DMA1_Channel0_IRQHandler + IRQ DMA1_Channel1_IRQHandler + IRQ DMA1_Channel2_IRQHandler + IRQ DMA1_Channel3_4_IRQHandler diff --git a/bsp/gd32/libraries/GD32F30x_Firmware_Library/CMSIS/GD/GD32F30x/Source/IAR/startup_gd32f30x_cl.s b/bsp/gd32/libraries/GD32F30x_Firmware_Library/CMSIS/GD/GD32F30x/Source/IAR/startup_gd32f30x_cl.s new file mode 100644 index 0000000000..4e1fd63ef4 --- /dev/null +++ b/bsp/gd32/libraries/GD32F30x_Firmware_Library/CMSIS/GD/GD32F30x/Source/IAR/startup_gd32f30x_cl.s @@ -0,0 +1,525 @@ +;/*! +; \file startup_gd32f30x_cl.s +; \brief start up file +; +; \version 2018-10-10, V1.1.0, firmware for GD32F30x +; \version 2020-09-30, V2.1.0, firmware for GD32F30x +;*/ +; +;/* +; Copyright (c) 2020, GigaDevice Semiconductor Inc. + +; Redistribution and use in source and binary forms, with or without modification, +;are permitted provided that the following conditions are met: +; +; 1. Redistributions of source code must retain the above copyright notice, this +; list of conditions and the following disclaimer. +; 2. Redistributions in binary form must reproduce the above copyright notice, +; this list of conditions and the following disclaimer in the documentation +; and/or other materials provided with the distribution. +; 3. Neither the name of the copyright holder nor the names of its contributors +; may be used to endorse or promote products derived from this software without +; specific prior written permission. +; +; THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +;AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +;WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +;IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +;INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +;NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +;PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +;WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +;ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +;OF SUCH DAMAGE. +;*/ + + MODULE ?cstartup + + ;; Forward declaration of sections. + SECTION CSTACK:DATA:NOROOT(3) + + SECTION .intvec:CODE:NOROOT(2) + + EXTERN __iar_program_start + EXTERN SystemInit + PUBLIC __vector_table + + DATA +__vector_table + DCD sfe(CSTACK) ; top of stack + DCD Reset_Handler ; Vector Number 1,Reset Handler + + DCD NMI_Handler ; Vector Number 2,NMI Handler + DCD HardFault_Handler ; Vector Number 3,Hard Fault Handler + DCD MemManage_Handler ; Vector Number 4,MPU Fault Handler + DCD BusFault_Handler ; Vector Number 5,Bus Fault Handler + DCD UsageFault_Handler ; Vector Number 6,Usage Fault Handler + DCD 0 ; Reserved + DCD 0 ; Reserved + DCD 0 ; Reserved + DCD 0 ; Reserved + DCD SVC_Handler ; Vector Number 11,SVCall Handler + DCD DebugMon_Handler ; Vector Number 12,Debug Monitor Handler + DCD 0 ; Reserved + DCD PendSV_Handler ; Vector Number 14,PendSV Handler + DCD SysTick_Handler ; Vector Number 15,SysTick Handler + + ; External Interrupts + DCD WWDGT_IRQHandler ; 16:Window Watchdog Timer + DCD LVD_IRQHandler ; 17:LVD through EXTI Line detect + DCD TAMPER_IRQHandler ; 18:Tamper through EXTI Line detect + DCD RTC_IRQHandler ; 19:RTC through EXTI Line + DCD FMC_IRQHandler ; 20:FMC + DCD RCU_CTC_IRQHandler ; 21:RCU and CTC + DCD EXTI0_IRQHandler ; 22:EXTI Line 0 + DCD EXTI1_IRQHandler ; 23:EXTI Line 1 + DCD EXTI2_IRQHandler ; 24:EXTI Line 2 + DCD EXTI3_IRQHandler ; 25:EXTI Line 3 + DCD EXTI4_IRQHandler ; 26:EXTI Line 4 + DCD DMA0_Channel0_IRQHandler ; 27:DMA0 Channel0 + DCD DMA0_Channel1_IRQHandler ; 28:DMA0 Channel1 + DCD DMA0_Channel2_IRQHandler ; 29:DMA0 Channel2 + DCD DMA0_Channel3_IRQHandler ; 30:DMA0 Channel3 + DCD DMA0_Channel4_IRQHandler ; 31:DMA0 Channel4 + DCD DMA0_Channel5_IRQHandler ; 32:DMA0 Channel5 + DCD DMA0_Channel6_IRQHandler ; 33:DMA0 Channel6 + DCD ADC0_1_IRQHandler ; 34:ADC0 and ADC1 + DCD CAN0_TX_IRQHandler ; 35:CAN0 TX + DCD CAN0_RX0_IRQHandler ; 36:CAN0 RX0 + DCD CAN0_RX1_IRQHandler ; 37:CAN0 RX1 + DCD CAN0_EWMC_IRQHandler ; 38:CAN0 EWMC + DCD EXTI5_9_IRQHandler ; 39:EXTI5 to EXTI9 + DCD TIMER0_BRK_TIMER8_IRQHandler ; 40:TIMER0 Break and TIMER8 + DCD TIMER0_UP_TIMER9_IRQHandler ; 41:TIMER0 Update and TIMER9 + DCD TIMER0_TRG_CMT_TIMER10_IRQHandler ; 42:TIMER0 Trigger and Commucation and TIMER10 + DCD TIMER0_Channel_IRQHandler ; 43:TIMER0 Channel Capture Compare + DCD TIMER1_IRQHandler ; 44:TIMER1 + DCD TIMER2_IRQHandler ; 45:TIMER2 + DCD TIMER3_IRQHandler ; 46:TIMER3 + DCD I2C0_EV_IRQHandler ; 47:I2C0 Event + DCD I2C0_ER_IRQHandler ; 48:I2C0 Error + DCD I2C1_EV_IRQHandler ; 49:I2C1 Event + DCD I2C1_ER_IRQHandler ; 50:I2C1 Error + DCD SPI0_IRQHandler ; 51:SPI0 + DCD SPI1_IRQHandler ; 52:SPI1 + DCD USART0_IRQHandler ; 53:USART0 + DCD USART1_IRQHandler ; 54:USART1 + DCD USART2_IRQHandler ; 55:USART2 + DCD EXTI10_15_IRQHandler ; 56:EXTI10 to EXTI15 + DCD RTC_Alarm_IRQHandler ; 57:RTC Alarm + DCD USBFS_WKUP_IRQHandler ; 58:USBFS Wakeup + DCD TIMER7_BRK_TIMER11_IRQHandler ; 59:TIMER7 Break and TIMER11 + DCD TIMER7_UP_TIMER12_IRQHandler ; 60:TIMER7 Update and TIMER12 + DCD TIMER7_TRG_CMT_TIMER13_IRQHandler ; 61:TIMER7 Trigger and Commucation and TIMER13 + DCD TIMER7_Channel_IRQHandler ; 62:TIMER7 Channel Capture Compare + DCD 0 ; 63:Reserved + DCD EXMC_IRQHandler ; 64:EXMC + DCD 0 ; 65:Reserved + DCD TIMER4_IRQHandler ; 66:TIMER4 + DCD SPI2_IRQHandler ; 67:SPI2 + DCD UART3_IRQHandler ; 68:UART3 + DCD UART4_IRQHandler ; 69:UART4 + DCD TIMER5_IRQHandler ; 70:TIMER5 + DCD TIMER6_IRQHandler ; 71:TIMER6 + DCD DMA1_Channel0_IRQHandler ; 72:DMA1 Channel0 + DCD DMA1_Channel1_IRQHandler ; 73:DMA1 Channel1 + DCD DMA1_Channel2_IRQHandler ; 74:DMA1 Channel2 + DCD DMA1_Channel3_IRQHandler ; 75:DMA1 Channel3 + DCD DMA1_Channel4_IRQHandler ; 76:DMA1 Channel4 + DCD ENET_IRQHandler ; 77:Ethernet + DCD ENET_WKUP_IRQHandler ; 78:Ethernet Wakeup through EXTI Line + DCD CAN1_TX_IRQHandler ; 79:CAN1 TX + DCD CAN1_RX0_IRQHandler ; 80:CAN1 RX0 + DCD CAN1_RX1_IRQHandler ; 81:CAN1 RX1 + DCD CAN1_EWMC_IRQHandler ; 82:CAN1 EWMC + DCD USBFS_IRQHandler ; 83:USBFS + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; +;; Default interrupt handlers. +;; + THUMB + + PUBWEAK Reset_Handler + SECTION .text:CODE:NOROOT:REORDER(2) +Reset_Handler + LDR R0, =SystemInit + BLX R0 + LDR R0, =__iar_program_start + BX R0 + + PUBWEAK NMI_Handler + SECTION .text:CODE:NOROOT:REORDER(1) +NMI_Handler + B NMI_Handler + + PUBWEAK HardFault_Handler + SECTION .text:CODE:NOROOT:REORDER(1) +HardFault_Handler + B HardFault_Handler + + PUBWEAK MemManage_Handler + SECTION .text:CODE:NOROOT:REORDER(1) +MemManage_Handler + B MemManage_Handler + + PUBWEAK BusFault_Handler + SECTION .text:CODE:NOROOT:REORDER(1) +BusFault_Handler + B BusFault_Handler + + PUBWEAK UsageFault_Handler + SECTION .text:CODE:NOROOT:REORDER(1) +UsageFault_Handler + B UsageFault_Handler + + PUBWEAK SVC_Handler + SECTION .text:CODE:NOROOT:REORDER(1) +SVC_Handler + B SVC_Handler + + PUBWEAK DebugMon_Handler + SECTION .text:CODE:NOROOT:REORDER(1) +DebugMon_Handler + B DebugMon_Handler + + PUBWEAK PendSV_Handler + SECTION .text:CODE:NOROOT:REORDER(1) +PendSV_Handler + B PendSV_Handler + + PUBWEAK SysTick_Handler + SECTION .text:CODE:NOROOT:REORDER(1) +SysTick_Handler + B SysTick_Handler + + PUBWEAK WWDGT_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +WWDGT_IRQHandler + B WWDGT_IRQHandler + + PUBWEAK LVD_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +LVD_IRQHandler + B LVD_IRQHandler + + PUBWEAK TAMPER_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +TAMPER_IRQHandler + B TAMPER_IRQHandler + + PUBWEAK RTC_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +RTC_IRQHandler + B RTC_IRQHandler + + PUBWEAK FMC_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +FMC_IRQHandler + B FMC_IRQHandler + + PUBWEAK RCU_CTC_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +RCU_CTC_IRQHandler + B RCU_CTC_IRQHandler + + PUBWEAK EXTI0_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +EXTI0_IRQHandler + B EXTI0_IRQHandler + + PUBWEAK EXTI1_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +EXTI1_IRQHandler + B EXTI1_IRQHandler + + PUBWEAK EXTI2_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +EXTI2_IRQHandler + B EXTI2_IRQHandler + + PUBWEAK EXTI3_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +EXTI3_IRQHandler + B EXTI3_IRQHandler + + PUBWEAK EXTI4_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +EXTI4_IRQHandler + B EXTI4_IRQHandler + + PUBWEAK DMA0_Channel0_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +DMA0_Channel0_IRQHandler + B DMA0_Channel0_IRQHandler + + PUBWEAK DMA0_Channel1_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +DMA0_Channel1_IRQHandler + B DMA0_Channel1_IRQHandler + + PUBWEAK DMA0_Channel2_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +DMA0_Channel2_IRQHandler + B DMA0_Channel2_IRQHandler + + PUBWEAK DMA0_Channel3_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +DMA0_Channel3_IRQHandler + B DMA0_Channel3_IRQHandler + + PUBWEAK DMA0_Channel4_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +DMA0_Channel4_IRQHandler + B DMA0_Channel4_IRQHandler + + PUBWEAK DMA0_Channel5_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +DMA0_Channel5_IRQHandler + B DMA0_Channel5_IRQHandler + + PUBWEAK DMA0_Channel6_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +DMA0_Channel6_IRQHandler + B DMA0_Channel6_IRQHandler + + PUBWEAK ADC0_1_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +ADC0_1_IRQHandler + B ADC0_1_IRQHandler + + PUBWEAK CAN0_TX_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +CAN0_TX_IRQHandler + B CAN0_TX_IRQHandler + + PUBWEAK CAN0_RX0_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +CAN0_RX0_IRQHandler + B CAN0_RX0_IRQHandler + + PUBWEAK CAN0_RX1_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +CAN0_RX1_IRQHandler + B CAN0_RX1_IRQHandler + + PUBWEAK CAN0_EWMC_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +CAN0_EWMC_IRQHandler + B CAN0_EWMC_IRQHandler + + PUBWEAK EXTI5_9_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +EXTI5_9_IRQHandler + B EXTI5_9_IRQHandler + + PUBWEAK TIMER0_BRK_TIMER8_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +TIMER0_BRK_TIMER8_IRQHandler + B TIMER0_BRK_TIMER8_IRQHandler + + PUBWEAK TIMER0_UP_TIMER9_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +TIMER0_UP_TIMER9_IRQHandler + B TIMER0_UP_TIMER9_IRQHandler + + PUBWEAK TIMER0_TRG_CMT_TIMER10_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +TIMER0_TRG_CMT_TIMER10_IRQHandler + B TIMER0_TRG_CMT_TIMER10_IRQHandler + + PUBWEAK TIMER0_Channel_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +TIMER0_Channel_IRQHandler + B TIMER0_Channel_IRQHandler + + PUBWEAK TIMER1_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +TIMER1_IRQHandler + B TIMER1_IRQHandler + + PUBWEAK TIMER2_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +TIMER2_IRQHandler + B TIMER2_IRQHandler + + PUBWEAK TIMER3_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +TIMER3_IRQHandler + B TIMER3_IRQHandler + + PUBWEAK I2C0_EV_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +I2C0_EV_IRQHandler + B I2C0_EV_IRQHandler + + PUBWEAK I2C0_ER_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +I2C0_ER_IRQHandler + B I2C0_ER_IRQHandler + + PUBWEAK I2C1_EV_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +I2C1_EV_IRQHandler + B I2C1_EV_IRQHandler + + PUBWEAK I2C1_ER_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +I2C1_ER_IRQHandler + B I2C1_ER_IRQHandler + + PUBWEAK SPI0_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +SPI0_IRQHandler + B SPI0_IRQHandler + + PUBWEAK SPI1_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +SPI1_IRQHandler + B SPI1_IRQHandler + + PUBWEAK USART0_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +USART0_IRQHandler + B USART0_IRQHandler + + PUBWEAK USART1_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +USART1_IRQHandler + B USART1_IRQHandler + + PUBWEAK USART2_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +USART2_IRQHandler + B USART2_IRQHandler + + PUBWEAK EXTI10_15_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +EXTI10_15_IRQHandler + B EXTI10_15_IRQHandler + + PUBWEAK RTC_Alarm_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +RTC_Alarm_IRQHandler + B RTC_Alarm_IRQHandler + + PUBWEAK USBFS_WKUP_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +USBFS_WKUP_IRQHandler + B USBFS_WKUP_IRQHandler + + PUBWEAK TIMER7_BRK_TIMER11_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +TIMER7_BRK_TIMER11_IRQHandler + B TIMER7_BRK_TIMER11_IRQHandler + + PUBWEAK TIMER7_UP_TIMER12_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +TIMER7_UP_TIMER12_IRQHandler + B TIMER7_UP_TIMER12_IRQHandler + + PUBWEAK TIMER7_TRG_CMT_TIMER13_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +TIMER7_TRG_CMT_TIMER13_IRQHandler + B TIMER7_TRG_CMT_TIMER13_IRQHandler + + PUBWEAK TIMER7_Channel_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +TIMER7_Channel_IRQHandler + B TIMER7_Channel_IRQHandler + + PUBWEAK EXMC_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +EXMC_IRQHandler + B EXMC_IRQHandler + + PUBWEAK TIMER4_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +TIMER4_IRQHandler + B TIMER4_IRQHandler + + PUBWEAK SPI2_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +SPI2_IRQHandler + B SPI2_IRQHandler + + PUBWEAK UART3_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +UART3_IRQHandler + B UART3_IRQHandler + + PUBWEAK UART4_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +UART4_IRQHandler + B UART4_IRQHandler + + PUBWEAK TIMER5_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +TIMER5_IRQHandler + B TIMER5_IRQHandler + + PUBWEAK TIMER6_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +TIMER6_IRQHandler + B TIMER6_IRQHandler + + PUBWEAK DMA1_Channel0_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +DMA1_Channel0_IRQHandler + B DMA1_Channel0_IRQHandler + + PUBWEAK DMA1_Channel1_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +DMA1_Channel1_IRQHandler + B DMA1_Channel1_IRQHandler + + PUBWEAK DMA1_Channel2_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +DMA1_Channel2_IRQHandler + B DMA1_Channel2_IRQHandler + + PUBWEAK DMA1_Channel3_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +DMA1_Channel3_IRQHandler + B DMA1_Channel3_IRQHandler + + PUBWEAK DMA1_Channel4_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +DMA1_Channel4_IRQHandler + B DMA1_Channel4_IRQHandler + + PUBWEAK ENET_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +ENET_IRQHandler + B ENET_IRQHandler + + PUBWEAK ENET_WKUP_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +ENET_WKUP_IRQHandler + B ENET_WKUP_IRQHandler + + PUBWEAK CAN1_TX_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +CAN1_TX_IRQHandler + B CAN1_TX_IRQHandler + + PUBWEAK CAN1_RX0_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +CAN1_RX0_IRQHandler + B CAN1_RX0_IRQHandler + + PUBWEAK CAN1_RX1_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +CAN1_RX1_IRQHandler + B CAN1_RX1_IRQHandler + + PUBWEAK CAN1_EWMC_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +CAN1_EWMC_IRQHandler + B CAN1_EWMC_IRQHandler + + PUBWEAK USBFS_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +USBFS_IRQHandler + B USBFS_IRQHandler + END \ No newline at end of file diff --git a/bsp/gd32/libraries/GD32F30x_Firmware_Library/CMSIS/GD/GD32F30x/Source/IAR/startup_gd32f30x_hd.s b/bsp/gd32/libraries/GD32F30x_Firmware_Library/CMSIS/GD/GD32F30x/Source/IAR/startup_gd32f30x_hd.s new file mode 100644 index 0000000000..71b952f830 --- /dev/null +++ b/bsp/gd32/libraries/GD32F30x_Firmware_Library/CMSIS/GD/GD32F30x/Source/IAR/startup_gd32f30x_hd.s @@ -0,0 +1,487 @@ +;/*! +; \file startup_gd32f30x_hd.s +; \brief start up file +; +; \version 2018-10-10, V1.1.0, firmware for GD32F30x +; \version 2020-09-30, V2.1.0, firmware for GD32F30x +;*/ +; +;/* +; Copyright (c) 2020, GigaDevice Semiconductor Inc. + +; Redistribution and use in source and binary forms, with or without modification, +;are permitted provided that the following conditions are met: +; +; 1. Redistributions of source code must retain the above copyright notice, this +; list of conditions and the following disclaimer. +; 2. Redistributions in binary form must reproduce the above copyright notice, +; this list of conditions and the following disclaimer in the documentation +; and/or other materials provided with the distribution. +; 3. Neither the name of the copyright holder nor the names of its contributors +; may be used to endorse or promote products derived from this software without +; specific prior written permission. +; +; THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +;AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +;WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +;IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +;INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +;NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +;PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +;WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +;ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +;OF SUCH DAMAGE. +;*/ + + MODULE ?cstartup + + ;; Forward declaration of sections. + SECTION CSTACK:DATA:NOROOT(3) + + SECTION .intvec:CODE:NOROOT(2) + + EXTERN __iar_program_start + EXTERN SystemInit + PUBLIC __vector_table + + DATA +__vector_table + DCD sfe(CSTACK) ; top of stack + DCD Reset_Handler ; Vector Number 1,Reset Handler + + DCD NMI_Handler ; Vector Number 2,NMI Handler + DCD HardFault_Handler ; Vector Number 3,Hard Fault Handler + DCD MemManage_Handler ; Vector Number 4,MPU Fault Handler + DCD BusFault_Handler ; Vector Number 5,Bus Fault Handler + DCD UsageFault_Handler ; Vector Number 6,Usage Fault Handler + DCD 0 ; Reserved + DCD 0 ; Reserved + DCD 0 ; Reserved + DCD 0 ; Reserved + DCD SVC_Handler ; Vector Number 11,SVCall Handler + DCD DebugMon_Handler ; Vector Number 12,Debug Monitor Handler + DCD 0 ; Reserved + DCD PendSV_Handler ; Vector Number 14,PendSV Handler + DCD SysTick_Handler ; Vector Number 15,SysTick Handler + + ; External Interrupts + DCD WWDGT_IRQHandler ; 16:Window Watchdog Timer + DCD LVD_IRQHandler ; 17:LVD through EXTI Line detect + DCD TAMPER_IRQHandler ; 18:Tamper through EXTI Line detect + DCD RTC_IRQHandler ; 19:RTC through EXTI Line + DCD FMC_IRQHandler ; 20:FMC + DCD RCU_CTC_IRQHandler ; 21:RCU and CTC + DCD EXTI0_IRQHandler ; 22:EXTI Line 0 + DCD EXTI1_IRQHandler ; 23:EXTI Line 1 + DCD EXTI2_IRQHandler ; 24:EXTI Line 2 + DCD EXTI3_IRQHandler ; 25:EXTI Line 3 + DCD EXTI4_IRQHandler ; 26:EXTI Line 4 + DCD DMA0_Channel0_IRQHandler ; 27:DMA0 Channel0 + DCD DMA0_Channel1_IRQHandler ; 28:DMA0 Channel1 + DCD DMA0_Channel2_IRQHandler ; 29:DMA0 Channel2 + DCD DMA0_Channel3_IRQHandler ; 30:DMA0 Channel3 + DCD DMA0_Channel4_IRQHandler ; 31:DMA0 Channel4 + DCD DMA0_Channel5_IRQHandler ; 32:DMA0 Channel5 + DCD DMA0_Channel6_IRQHandler ; 33:DMA0 Channel6 + DCD ADC0_1_IRQHandler ; 34:ADC0 and ADC1 + DCD USBD_HP_CAN0_TX_IRQHandler ; 35:USBD HP and CAN0 TX + DCD USBD_LP_CAN0_RX0_IRQHandler ; 36:USBD LP and CAN0 RX0 + DCD CAN0_RX1_IRQHandler ; 37:CAN0 RX1 + DCD CAN0_EWMC_IRQHandler ; 38:CAN0 EWMC + DCD EXTI5_9_IRQHandler ; 39:EXTI5 to EXTI9 + DCD TIMER0_BRK_IRQHandler ; 40:TIMER0 Break + DCD TIMER0_UP_IRQHandler ; 41:TIMER0 Update + DCD TIMER0_TRG_CMT_IRQHandler ; 42:TIMER0 Trigger and Commucation + DCD TIMER0_Channel_IRQHandler ; 43:TIMER0 Channel Capture Compare + DCD TIMER1_IRQHandler ; 44:TIMER1 + DCD TIMER2_IRQHandler ; 45:TIMER2 + DCD TIMER3_IRQHandler ; 46:TIMER3 + DCD I2C0_EV_IRQHandler ; 47:I2C0 Event + DCD I2C0_ER_IRQHandler ; 48:I2C0 Error + DCD I2C1_EV_IRQHandler ; 49:I2C1 Event + DCD I2C1_ER_IRQHandler ; 50:I2C1 Error + DCD SPI0_IRQHandler ; 51:SPI0 + DCD SPI1_IRQHandler ; 52:SPI1 + DCD USART0_IRQHandler ; 53:USART0 + DCD USART1_IRQHandler ; 54:USART1 + DCD USART2_IRQHandler ; 55:USART2 + DCD EXTI10_15_IRQHandler ; 56:EXTI10 to EXTI15 + DCD RTC_Alarm_IRQHandler ; 57:RTC Alarm + DCD USBD_WKUP_IRQHandler ; 58:USBD Wakeup + DCD TIMER7_BRK_IRQHandler ; 59:TIMER7 Break + DCD TIMER7_UP_IRQHandler ; 60:TIMER7 Update + DCD TIMER7_TRG_CMT_IRQHandler ; 61:TIMER7 Trigger and Commucation + DCD TIMER7_Channel_IRQHandler ; 62:TIMER7 Channel Capture Compare + DCD ADC2_IRQHandler ; 63:ADC2 + DCD EXMC_IRQHandler ; 64:EXMC + DCD SDIO_IRQHandler ; 65:SDIO + DCD TIMER4_IRQHandler ; 66:TIMER4 + DCD SPI2_IRQHandler ; 67:SPI2 + DCD UART3_IRQHandler ; 68:UART3 + DCD UART4_IRQHandler ; 69:UART4 + DCD TIMER5_IRQHandler ; 70:TIMER5 + DCD TIMER6_IRQHandler ; 71:TIMER6 + DCD DMA1_Channel0_IRQHandler ; 72:DMA1 Channel0 + DCD DMA1_Channel1_IRQHandler ; 73:DMA1 Channel1 + DCD DMA1_Channel2_IRQHandler ; 74:DMA1 Channel2 + DCD DMA1_Channel3_4_IRQHandler ; 75:DMA1 Channel3 and channel4 + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; +;; Default interrupt handlers. +;; + THUMB + + PUBWEAK Reset_Handler + SECTION .text:CODE:NOROOT:REORDER(2) +Reset_Handler + LDR R0, =SystemInit + BLX R0 + LDR R0, =__iar_program_start + BX R0 + + PUBWEAK NMI_Handler + SECTION .text:CODE:NOROOT:REORDER(1) +NMI_Handler + B NMI_Handler + + PUBWEAK HardFault_Handler + SECTION .text:CODE:NOROOT:REORDER(1) +HardFault_Handler + B HardFault_Handler + + PUBWEAK MemManage_Handler + SECTION .text:CODE:NOROOT:REORDER(1) +MemManage_Handler + B MemManage_Handler + + PUBWEAK BusFault_Handler + SECTION .text:CODE:NOROOT:REORDER(1) +BusFault_Handler + B BusFault_Handler + + PUBWEAK UsageFault_Handler + SECTION .text:CODE:NOROOT:REORDER(1) +UsageFault_Handler + B UsageFault_Handler + + PUBWEAK SVC_Handler + SECTION .text:CODE:NOROOT:REORDER(1) +SVC_Handler + B SVC_Handler + + PUBWEAK DebugMon_Handler + SECTION .text:CODE:NOROOT:REORDER(1) +DebugMon_Handler + B DebugMon_Handler + + PUBWEAK PendSV_Handler + SECTION .text:CODE:NOROOT:REORDER(1) +PendSV_Handler + B PendSV_Handler + + PUBWEAK SysTick_Handler + SECTION .text:CODE:NOROOT:REORDER(1) +SysTick_Handler + B SysTick_Handler + + PUBWEAK WWDGT_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +WWDGT_IRQHandler + B WWDGT_IRQHandler + + PUBWEAK LVD_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +LVD_IRQHandler + B LVD_IRQHandler + + PUBWEAK TAMPER_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +TAMPER_IRQHandler + B TAMPER_IRQHandler + + PUBWEAK RTC_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +RTC_IRQHandler + B RTC_IRQHandler + + PUBWEAK FMC_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +FMC_IRQHandler + B FMC_IRQHandler + + PUBWEAK RCU_CTC_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +RCU_CTC_IRQHandler + B RCU_CTC_IRQHandler + + PUBWEAK EXTI0_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +EXTI0_IRQHandler + B EXTI0_IRQHandler + + PUBWEAK EXTI1_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +EXTI1_IRQHandler + B EXTI1_IRQHandler + + PUBWEAK EXTI2_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +EXTI2_IRQHandler + B EXTI2_IRQHandler + + PUBWEAK EXTI3_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +EXTI3_IRQHandler + B EXTI3_IRQHandler + + PUBWEAK EXTI4_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +EXTI4_IRQHandler + B EXTI4_IRQHandler + + PUBWEAK DMA0_Channel0_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +DMA0_Channel0_IRQHandler + B DMA0_Channel0_IRQHandler + + PUBWEAK DMA0_Channel1_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +DMA0_Channel1_IRQHandler + B DMA0_Channel1_IRQHandler + + PUBWEAK DMA0_Channel2_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +DMA0_Channel2_IRQHandler + B DMA0_Channel2_IRQHandler + + PUBWEAK DMA0_Channel3_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +DMA0_Channel3_IRQHandler + B DMA0_Channel3_IRQHandler + + PUBWEAK DMA0_Channel4_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +DMA0_Channel4_IRQHandler + B DMA0_Channel4_IRQHandler + + PUBWEAK DMA0_Channel5_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +DMA0_Channel5_IRQHandler + B DMA0_Channel5_IRQHandler + + PUBWEAK DMA0_Channel6_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +DMA0_Channel6_IRQHandler + B DMA0_Channel6_IRQHandler + + PUBWEAK ADC0_1_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +ADC0_1_IRQHandler + B ADC0_1_IRQHandler + + PUBWEAK USBD_HP_CAN0_TX_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +USBD_HP_CAN0_TX_IRQHandler + B USBD_HP_CAN0_TX_IRQHandler + + PUBWEAK USBD_LP_CAN0_RX0_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +USBD_LP_CAN0_RX0_IRQHandler + B USBD_LP_CAN0_RX0_IRQHandler + + PUBWEAK CAN0_RX1_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +CAN0_RX1_IRQHandler + B CAN0_RX1_IRQHandler + + PUBWEAK CAN0_EWMC_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +CAN0_EWMC_IRQHandler + B CAN0_EWMC_IRQHandler + + PUBWEAK EXTI5_9_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +EXTI5_9_IRQHandler + B EXTI5_9_IRQHandler + + PUBWEAK TIMER0_BRK_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +TIMER0_BRK_IRQHandler + B TIMER0_BRK_IRQHandler + + PUBWEAK TIMER0_UP_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +TIMER0_UP_IRQHandler + B TIMER0_UP_IRQHandler + + PUBWEAK TIMER0_TRG_CMT_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +TIMER0_TRG_CMT_IRQHandler + B TIMER0_TRG_CMT_IRQHandler + + PUBWEAK TIMER0_Channel_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +TIMER0_Channel_IRQHandler + B TIMER0_Channel_IRQHandler + + PUBWEAK TIMER1_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +TIMER1_IRQHandler + B TIMER1_IRQHandler + + PUBWEAK TIMER2_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +TIMER2_IRQHandler + B TIMER2_IRQHandler + + PUBWEAK TIMER3_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +TIMER3_IRQHandler + B TIMER3_IRQHandler + + PUBWEAK I2C0_EV_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +I2C0_EV_IRQHandler + B I2C0_EV_IRQHandler + + PUBWEAK I2C0_ER_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +I2C0_ER_IRQHandler + B I2C0_ER_IRQHandler + + PUBWEAK I2C1_EV_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +I2C1_EV_IRQHandler + B I2C1_EV_IRQHandler + + PUBWEAK I2C1_ER_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +I2C1_ER_IRQHandler + B I2C1_ER_IRQHandler + + PUBWEAK SPI0_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +SPI0_IRQHandler + B SPI0_IRQHandler + + PUBWEAK SPI1_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +SPI1_IRQHandler + B SPI1_IRQHandler + + PUBWEAK USART0_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +USART0_IRQHandler + B USART0_IRQHandler + + PUBWEAK USART1_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +USART1_IRQHandler + B USART1_IRQHandler + + PUBWEAK USART2_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +USART2_IRQHandler + B USART2_IRQHandler + + PUBWEAK EXTI10_15_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +EXTI10_15_IRQHandler + B EXTI10_15_IRQHandler + + PUBWEAK RTC_Alarm_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +RTC_Alarm_IRQHandler + B RTC_Alarm_IRQHandler + + PUBWEAK USBD_WKUP_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +USBD_WKUP_IRQHandler + B USBD_WKUP_IRQHandler + + PUBWEAK TIMER7_BRK_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +TIMER7_BRK_IRQHandler + B TIMER7_BRK_IRQHandler + + PUBWEAK TIMER7_UP_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +TIMER7_UP_IRQHandler + B TIMER7_UP_IRQHandler + + PUBWEAK TIMER7_TRG_CMT_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +TIMER7_TRG_CMT_IRQHandler + B TIMER7_TRG_CMT_IRQHandler + + PUBWEAK TIMER7_Channel_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +TIMER7_Channel_IRQHandler + B TIMER7_Channel_IRQHandler + + PUBWEAK ADC2_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +ADC2_IRQHandler + B ADC2_IRQHandler + + PUBWEAK EXMC_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +EXMC_IRQHandler + B EXMC_IRQHandler + + PUBWEAK SDIO_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +SDIO_IRQHandler + B SDIO_IRQHandler + + PUBWEAK TIMER4_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +TIMER4_IRQHandler + B TIMER4_IRQHandler + + PUBWEAK SPI2_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +SPI2_IRQHandler + B SPI2_IRQHandler + + PUBWEAK UART3_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +UART3_IRQHandler + B UART3_IRQHandler + + PUBWEAK UART4_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +UART4_IRQHandler + B UART4_IRQHandler + + PUBWEAK TIMER5_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +TIMER5_IRQHandler + B TIMER5_IRQHandler + + PUBWEAK TIMER6_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +TIMER6_IRQHandler + B TIMER6_IRQHandler + + PUBWEAK DMA1_Channel0_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +DMA1_Channel0_IRQHandler + B DMA1_Channel0_IRQHandler + + PUBWEAK DMA1_Channel1_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +DMA1_Channel1_IRQHandler + B DMA1_Channel1_IRQHandler + + PUBWEAK DMA1_Channel2_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +DMA1_Channel2_IRQHandler + B DMA1_Channel2_IRQHandler + + PUBWEAK DMA1_Channel3_4_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +DMA1_Channel3_4_IRQHandler + B DMA1_Channel3_4_IRQHandler + END \ No newline at end of file diff --git a/bsp/gd32/libraries/GD32F30x_Firmware_Library/CMSIS/GD/GD32F30x/Source/IAR/startup_gd32f30x_xd.s b/bsp/gd32/libraries/GD32F30x_Firmware_Library/CMSIS/GD/GD32F30x/Source/IAR/startup_gd32f30x_xd.s new file mode 100644 index 0000000000..1eb465900d --- /dev/null +++ b/bsp/gd32/libraries/GD32F30x_Firmware_Library/CMSIS/GD/GD32F30x/Source/IAR/startup_gd32f30x_xd.s @@ -0,0 +1,487 @@ +;/*! +; \file startup_gd32f30x_xd.s +; \brief start up file +; +; \version 2018-10-10, V1.1.0, firmware for GD32F30x +; \version 2020-09-30, V2.1.0, firmware for GD32F30x +;*/ +; +;/* +; Copyright (c) 2020, GigaDevice Semiconductor Inc. + +; Redistribution and use in source and binary forms, with or without modification, +;are permitted provided that the following conditions are met: +; +; 1. Redistributions of source code must retain the above copyright notice, this +; list of conditions and the following disclaimer. +; 2. Redistributions in binary form must reproduce the above copyright notice, +; this list of conditions and the following disclaimer in the documentation +; and/or other materials provided with the distribution. +; 3. Neither the name of the copyright holder nor the names of its contributors +; may be used to endorse or promote products derived from this software without +; specific prior written permission. +; +; THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +;AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +;WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +;IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +;INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +;NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +;PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +;WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +;ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +;OF SUCH DAMAGE. +;*/ + + MODULE ?cstartup + + ;; Forward declaration of sections. + SECTION CSTACK:DATA:NOROOT(3) + + SECTION .intvec:CODE:NOROOT(2) + + EXTERN __iar_program_start + EXTERN SystemInit + PUBLIC __vector_table + + DATA +__vector_table + DCD sfe(CSTACK) ; top of stack + DCD Reset_Handler ; Vector Number 1,Reset Handler + + DCD NMI_Handler ; Vector Number 2,NMI Handler + DCD HardFault_Handler ; Vector Number 3,Hard Fault Handler + DCD MemManage_Handler ; Vector Number 4,MPU Fault Handler + DCD BusFault_Handler ; Vector Number 5,Bus Fault Handler + DCD UsageFault_Handler ; Vector Number 6,Usage Fault Handler + DCD 0 ; Reserved + DCD 0 ; Reserved + DCD 0 ; Reserved + DCD 0 ; Reserved + DCD SVC_Handler ; Vector Number 11,SVCall Handler + DCD DebugMon_Handler ; Vector Number 12,Debug Monitor Handler + DCD 0 ; Reserved + DCD PendSV_Handler ; Vector Number 14,PendSV Handler + DCD SysTick_Handler ; Vector Number 15,SysTick Handler + + ; External Interrupts + DCD WWDGT_IRQHandler ; 16:Window Watchdog Timer + DCD LVD_IRQHandler ; 17:LVD through EXTI Line detect + DCD TAMPER_IRQHandler ; 18:Tamper through EXTI Line detect + DCD RTC_IRQHandler ; 19:RTC through EXTI Line + DCD FMC_IRQHandler ; 20:FMC + DCD RCU_CTC_IRQHandler ; 21:RCU and CTC + DCD EXTI0_IRQHandler ; 22:EXTI Line 0 + DCD EXTI1_IRQHandler ; 23:EXTI Line 1 + DCD EXTI2_IRQHandler ; 24:EXTI Line 2 + DCD EXTI3_IRQHandler ; 25:EXTI Line 3 + DCD EXTI4_IRQHandler ; 26:EXTI Line 4 + DCD DMA0_Channel0_IRQHandler ; 27:DMA0 Channel0 + DCD DMA0_Channel1_IRQHandler ; 28:DMA0 Channel1 + DCD DMA0_Channel2_IRQHandler ; 29:DMA0 Channel2 + DCD DMA0_Channel3_IRQHandler ; 30:DMA0 Channel3 + DCD DMA0_Channel4_IRQHandler ; 31:DMA0 Channel4 + DCD DMA0_Channel5_IRQHandler ; 32:DMA0 Channel5 + DCD DMA0_Channel6_IRQHandler ; 33:DMA0 Channel6 + DCD ADC0_1_IRQHandler ; 34:ADC0 and ADC1 + DCD USBD_HP_CAN0_TX_IRQHandler ; 35:USBD HP and CAN0 TX + DCD USBD_LP_CAN0_RX0_IRQHandler ; 36:USBD LP and CAN0 RX0 + DCD CAN0_RX1_IRQHandler ; 37:CAN0 RX1 + DCD CAN0_EWMC_IRQHandler ; 38:CAN0 EWMC + DCD EXTI5_9_IRQHandler ; 39:EXTI5 to EXTI9 + DCD TIMER0_BRK_TIMER8_IRQHandler ; 40:TIMER0 Break and TIMER8 + DCD TIMER0_UP_TIMER9_IRQHandler ; 41:TIMER0 Update and TIMER9 + DCD TIMER0_TRG_CMT_TIMER10_IRQHandler ; 42:TIMER0 Trigger and Commucation and TIMER10 + DCD TIMER0_Channel_IRQHandler ; 43:TIMER0 Channel Capture Compare + DCD TIMER1_IRQHandler ; 44:TIMER1 + DCD TIMER2_IRQHandler ; 45:TIMER2 + DCD TIMER3_IRQHandler ; 46:TIMER3 + DCD I2C0_EV_IRQHandler ; 47:I2C0 Event + DCD I2C0_ER_IRQHandler ; 48:I2C0 Error + DCD I2C1_EV_IRQHandler ; 49:I2C1 Event + DCD I2C1_ER_IRQHandler ; 50:I2C1 Error + DCD SPI0_IRQHandler ; 51:SPI0 + DCD SPI1_IRQHandler ; 52:SPI1 + DCD USART0_IRQHandler ; 53:USART0 + DCD USART1_IRQHandler ; 54:USART1 + DCD USART2_IRQHandler ; 55:USART2 + DCD EXTI10_15_IRQHandler ; 56:EXTI10 to EXTI15 + DCD RTC_Alarm_IRQHandler ; 57:RTC Alarm + DCD USBD_WKUP_IRQHandler ; 58:USBD Wakeup + DCD TIMER7_BRK_TIMER11_IRQHandler ; 59:TIMER7 Break and TIMER11 + DCD TIMER7_UP_TIMER12_IRQHandler ; 60:TIMER7 Update and TIMER12 + DCD TIMER7_TRG_CMT_TIMER13_IRQHandler ; 61:TIMER7 Trigger and Commucation and TIMER13 + DCD TIMER7_Channel_IRQHandler ; 62:TIMER7 Channel Capture Compare + DCD ADC2_IRQHandler ; 63:ADC2 + DCD EXMC_IRQHandler ; 64:EXMC + DCD SDIO_IRQHandler ; 65:SDIO + DCD TIMER4_IRQHandler ; 66:TIMER4 + DCD SPI2_IRQHandler ; 67:SPI2 + DCD UART3_IRQHandler ; 68:UART3 + DCD UART4_IRQHandler ; 69:UART4 + DCD TIMER5_IRQHandler ; 70:TIMER5 + DCD TIMER6_IRQHandler ; 71:TIMER6 + DCD DMA1_Channel0_IRQHandler ; 72:DMA1 Channel0 + DCD DMA1_Channel1_IRQHandler ; 73:DMA1 Channel1 + DCD DMA1_Channel2_IRQHandler ; 74:DMA1 Channel2 + DCD DMA1_Channel3_4_IRQHandler ; 75:DMA1 Channel3 and channel4 + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; +;; Default interrupt handlers. +;; + THUMB + + PUBWEAK Reset_Handler + SECTION .text:CODE:NOROOT:REORDER(2) +Reset_Handler + LDR R0, =SystemInit + BLX R0 + LDR R0, =__iar_program_start + BX R0 + + PUBWEAK NMI_Handler + SECTION .text:CODE:NOROOT:REORDER(1) +NMI_Handler + B NMI_Handler + + PUBWEAK HardFault_Handler + SECTION .text:CODE:NOROOT:REORDER(1) +HardFault_Handler + B HardFault_Handler + + PUBWEAK MemManage_Handler + SECTION .text:CODE:NOROOT:REORDER(1) +MemManage_Handler + B MemManage_Handler + + PUBWEAK BusFault_Handler + SECTION .text:CODE:NOROOT:REORDER(1) +BusFault_Handler + B BusFault_Handler + + PUBWEAK UsageFault_Handler + SECTION .text:CODE:NOROOT:REORDER(1) +UsageFault_Handler + B UsageFault_Handler + + PUBWEAK SVC_Handler + SECTION .text:CODE:NOROOT:REORDER(1) +SVC_Handler + B SVC_Handler + + PUBWEAK DebugMon_Handler + SECTION .text:CODE:NOROOT:REORDER(1) +DebugMon_Handler + B DebugMon_Handler + + PUBWEAK PendSV_Handler + SECTION .text:CODE:NOROOT:REORDER(1) +PendSV_Handler + B PendSV_Handler + + PUBWEAK SysTick_Handler + SECTION .text:CODE:NOROOT:REORDER(1) +SysTick_Handler + B SysTick_Handler + + PUBWEAK WWDGT_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +WWDGT_IRQHandler + B WWDGT_IRQHandler + + PUBWEAK LVD_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +LVD_IRQHandler + B LVD_IRQHandler + + PUBWEAK TAMPER_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +TAMPER_IRQHandler + B TAMPER_IRQHandler + + PUBWEAK RTC_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +RTC_IRQHandler + B RTC_IRQHandler + + PUBWEAK FMC_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +FMC_IRQHandler + B FMC_IRQHandler + + PUBWEAK RCU_CTC_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +RCU_CTC_IRQHandler + B RCU_CTC_IRQHandler + + PUBWEAK EXTI0_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +EXTI0_IRQHandler + B EXTI0_IRQHandler + + PUBWEAK EXTI1_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +EXTI1_IRQHandler + B EXTI1_IRQHandler + + PUBWEAK EXTI2_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +EXTI2_IRQHandler + B EXTI2_IRQHandler + + PUBWEAK EXTI3_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +EXTI3_IRQHandler + B EXTI3_IRQHandler + + PUBWEAK EXTI4_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +EXTI4_IRQHandler + B EXTI4_IRQHandler + + PUBWEAK DMA0_Channel0_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +DMA0_Channel0_IRQHandler + B DMA0_Channel0_IRQHandler + + PUBWEAK DMA0_Channel1_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +DMA0_Channel1_IRQHandler + B DMA0_Channel1_IRQHandler + + PUBWEAK DMA0_Channel2_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +DMA0_Channel2_IRQHandler + B DMA0_Channel2_IRQHandler + + PUBWEAK DMA0_Channel3_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +DMA0_Channel3_IRQHandler + B DMA0_Channel3_IRQHandler + + PUBWEAK DMA0_Channel4_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +DMA0_Channel4_IRQHandler + B DMA0_Channel4_IRQHandler + + PUBWEAK DMA0_Channel5_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +DMA0_Channel5_IRQHandler + B DMA0_Channel5_IRQHandler + + PUBWEAK DMA0_Channel6_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +DMA0_Channel6_IRQHandler + B DMA0_Channel6_IRQHandler + + PUBWEAK ADC0_1_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +ADC0_1_IRQHandler + B ADC0_1_IRQHandler + + PUBWEAK USBD_HP_CAN0_TX_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +USBD_HP_CAN0_TX_IRQHandler + B USBD_HP_CAN0_TX_IRQHandler + + PUBWEAK USBD_LP_CAN0_RX0_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +USBD_LP_CAN0_RX0_IRQHandler + B USBD_LP_CAN0_RX0_IRQHandler + + PUBWEAK CAN0_RX1_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +CAN0_RX1_IRQHandler + B CAN0_RX1_IRQHandler + + PUBWEAK CAN0_EWMC_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +CAN0_EWMC_IRQHandler + B CAN0_EWMC_IRQHandler + + PUBWEAK EXTI5_9_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +EXTI5_9_IRQHandler + B EXTI5_9_IRQHandler + + PUBWEAK TIMER0_BRK_TIMER8_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +TIMER0_BRK_TIMER8_IRQHandler + B TIMER0_BRK_TIMER8_IRQHandler + + PUBWEAK TIMER0_UP_TIMER9_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +TIMER0_UP_TIMER9_IRQHandler + B TIMER0_UP_TIMER9_IRQHandler + + PUBWEAK TIMER0_TRG_CMT_TIMER10_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +TIMER0_TRG_CMT_TIMER10_IRQHandler + B TIMER0_TRG_CMT_TIMER10_IRQHandler + + PUBWEAK TIMER0_Channel_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +TIMER0_Channel_IRQHandler + B TIMER0_Channel_IRQHandler + + PUBWEAK TIMER1_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +TIMER1_IRQHandler + B TIMER1_IRQHandler + + PUBWEAK TIMER2_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +TIMER2_IRQHandler + B TIMER2_IRQHandler + + PUBWEAK TIMER3_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +TIMER3_IRQHandler + B TIMER3_IRQHandler + + PUBWEAK I2C0_EV_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +I2C0_EV_IRQHandler + B I2C0_EV_IRQHandler + + PUBWEAK I2C0_ER_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +I2C0_ER_IRQHandler + B I2C0_ER_IRQHandler + + PUBWEAK I2C1_EV_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +I2C1_EV_IRQHandler + B I2C1_EV_IRQHandler + + PUBWEAK I2C1_ER_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +I2C1_ER_IRQHandler + B I2C1_ER_IRQHandler + + PUBWEAK SPI0_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +SPI0_IRQHandler + B SPI0_IRQHandler + + PUBWEAK SPI1_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +SPI1_IRQHandler + B SPI1_IRQHandler + + PUBWEAK USART0_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +USART0_IRQHandler + B USART0_IRQHandler + + PUBWEAK USART1_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +USART1_IRQHandler + B USART1_IRQHandler + + PUBWEAK USART2_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +USART2_IRQHandler + B USART2_IRQHandler + + PUBWEAK EXTI10_15_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +EXTI10_15_IRQHandler + B EXTI10_15_IRQHandler + + PUBWEAK RTC_Alarm_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +RTC_Alarm_IRQHandler + B RTC_Alarm_IRQHandler + + PUBWEAK USBD_WKUP_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +USBD_WKUP_IRQHandler + B USBD_WKUP_IRQHandler + + PUBWEAK TIMER7_BRK_TIMER11_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +TIMER7_BRK_TIMER11_IRQHandler + B TIMER7_BRK_TIMER11_IRQHandler + + PUBWEAK TIMER7_UP_TIMER12_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +TIMER7_UP_TIMER12_IRQHandler + B TIMER7_UP_TIMER12_IRQHandler + + PUBWEAK TIMER7_TRG_CMT_TIMER13_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +TIMER7_TRG_CMT_TIMER13_IRQHandler + B TIMER7_TRG_CMT_TIMER13_IRQHandler + + PUBWEAK TIMER7_Channel_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +TIMER7_Channel_IRQHandler + B TIMER7_Channel_IRQHandler + + PUBWEAK ADC2_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +ADC2_IRQHandler + B ADC2_IRQHandler + + PUBWEAK EXMC_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +EXMC_IRQHandler + B EXMC_IRQHandler + + PUBWEAK SDIO_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +SDIO_IRQHandler + B SDIO_IRQHandler + + PUBWEAK TIMER4_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +TIMER4_IRQHandler + B TIMER4_IRQHandler + + PUBWEAK SPI2_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +SPI2_IRQHandler + B SPI2_IRQHandler + + PUBWEAK UART3_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +UART3_IRQHandler + B UART3_IRQHandler + + PUBWEAK UART4_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +UART4_IRQHandler + B UART4_IRQHandler + + PUBWEAK TIMER5_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +TIMER5_IRQHandler + B TIMER5_IRQHandler + + PUBWEAK TIMER6_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +TIMER6_IRQHandler + B TIMER6_IRQHandler + + PUBWEAK DMA1_Channel0_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +DMA1_Channel0_IRQHandler + B DMA1_Channel0_IRQHandler + + PUBWEAK DMA1_Channel1_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +DMA1_Channel1_IRQHandler + B DMA1_Channel1_IRQHandler + + PUBWEAK DMA1_Channel2_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +DMA1_Channel2_IRQHandler + B DMA1_Channel2_IRQHandler + + PUBWEAK DMA1_Channel3_4_IRQHandler + SECTION .text:CODE:NOROOT:REORDER(1) +DMA1_Channel3_4_IRQHandler + B DMA1_Channel3_4_IRQHandler + END \ No newline at end of file diff --git a/bsp/gd32/libraries/GD32F30x_Firmware_Library/CMSIS/GD/GD32F30x/Source/system_gd32f30x.c b/bsp/gd32/libraries/GD32F30x_Firmware_Library/CMSIS/GD/GD32F30x/Source/system_gd32f30x.c new file mode 100644 index 0000000000..65455622f0 --- /dev/null +++ b/bsp/gd32/libraries/GD32F30x_Firmware_Library/CMSIS/GD/GD32F30x/Source/system_gd32f30x.c @@ -0,0 +1,996 @@ +/*! + \file system_gd32f30x.c + \brief CMSIS Cortex-M4 Device Peripheral Access Layer Source File for + GD32F30x Device Series +*/ + +/* Copyright (c) 2012 ARM LIMITED + + All rights reserved. + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + - Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + - Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + - Neither the name of ARM nor the names of its contributors may be used + to endorse or promote products derived from this software without + specific prior written permission. + * + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDERS AND CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + ---------------------------------------------------------------------------*/ +/* This file refers the CMSIS standard, some adjustments are made according to GigaDevice chips */ + +#include "gd32f30x.h" + +/* system frequency define */ +#define __IRC8M (IRC8M_VALUE) /* internal 8 MHz RC oscillator frequency */ +#define __HXTAL (HXTAL_VALUE) /* high speed crystal oscillator frequency */ +#define __SYS_OSC_CLK (__IRC8M) /* main oscillator frequency */ + +/* select a system clock by uncommenting the following line */ +/* use IRC8M */ +//#define __SYSTEM_CLOCK_IRC8M (uint32_t)(__IRC8M) +//#define __SYSTEM_CLOCK_48M_PLL_IRC8M (uint32_t)(48000000) +//#define __SYSTEM_CLOCK_72M_PLL_IRC8M (uint32_t)(72000000) +//#define __SYSTEM_CLOCK_108M_PLL_IRC8M (uint32_t)(108000000) +//#define __SYSTEM_CLOCK_120M_PLL_IRC8M (uint32_t)(120000000) + +/* use HXTAL(XD series CK_HXTAL = 8M, CL series CK_HXTAL = 25M) */ +//#define __SYSTEM_CLOCK_HXTAL (uint32_t)(__HXTAL) +//#define __SYSTEM_CLOCK_48M_PLL_HXTAL (uint32_t)(48000000) +//#define __SYSTEM_CLOCK_72M_PLL_HXTAL (uint32_t)(72000000) +//#define __SYSTEM_CLOCK_108M_PLL_HXTAL (uint32_t)(108000000) +#define __SYSTEM_CLOCK_120M_PLL_HXTAL (uint32_t)(120000000) + +#define SEL_IRC8M 0x00U +#define SEL_HXTAL 0x01U +#define SEL_PLL 0x02U +#define RCU_MODIFY {volatile uint32_t i; \ + RCU_CFG0 |= RCU_AHB_CKSYS_DIV2; \ + for(i=0;i<20000;i++);} + +/* set the system clock frequency and declare the system clock configuration function */ +#ifdef __SYSTEM_CLOCK_IRC8M +uint32_t SystemCoreClock = __SYSTEM_CLOCK_IRC8M; +static void system_clock_8m_irc8m(void); +#elif defined (__SYSTEM_CLOCK_48M_PLL_IRC8M) +uint32_t SystemCoreClock = __SYSTEM_CLOCK_48M_PLL_IRC8M; +static void system_clock_48m_irc8m(void); +#elif defined (__SYSTEM_CLOCK_72M_PLL_IRC8M) +uint32_t SystemCoreClock = __SYSTEM_CLOCK_72M_PLL_IRC8M; +static void system_clock_72m_irc8m(void); +#elif defined (__SYSTEM_CLOCK_108M_PLL_IRC8M) +uint32_t SystemCoreClock = __SYSTEM_CLOCK_108M_PLL_IRC8M; +static void system_clock_108m_irc8m(void); +#elif defined (__SYSTEM_CLOCK_120M_PLL_IRC8M) +uint32_t SystemCoreClock = __SYSTEM_CLOCK_120M_PLL_IRC8M; +static void system_clock_120m_irc8m(void); + +#elif defined (__SYSTEM_CLOCK_HXTAL) +uint32_t SystemCoreClock = __SYSTEM_CLOCK_HXTAL; +static void system_clock_hxtal(void); +#elif defined (__SYSTEM_CLOCK_48M_PLL_HXTAL) +uint32_t SystemCoreClock = __SYSTEM_CLOCK_48M_PLL_HXTAL; +static void system_clock_48m_hxtal(void); +#elif defined (__SYSTEM_CLOCK_72M_PLL_HXTAL) +uint32_t SystemCoreClock = __SYSTEM_CLOCK_72M_PLL_HXTAL; +static void system_clock_72m_hxtal(void); +#elif defined (__SYSTEM_CLOCK_108M_PLL_HXTAL) +uint32_t SystemCoreClock = __SYSTEM_CLOCK_108M_PLL_HXTAL; +static void system_clock_108m_hxtal(void); +#elif defined (__SYSTEM_CLOCK_120M_PLL_HXTAL) +uint32_t SystemCoreClock = __SYSTEM_CLOCK_120M_PLL_HXTAL; +static void system_clock_120m_hxtal(void); +#endif /* __SYSTEM_CLOCK_IRC8M */ + +/* configure the system clock */ +static void system_clock_config(void); + +/*! + \brief setup the microcontroller system, initialize the system + \param[in] none + \param[out] none + \retval none +*/ +void SystemInit (void) +{ + /* FPU settings */ +#if (__FPU_PRESENT == 1) && (__FPU_USED == 1) + SCB->CPACR |= ((3UL << 10*2)|(3UL << 11*2)); /* set CP10 and CP11 Full Access */ +#endif + /* reset the RCU clock configuration to the default reset state */ + /* Set IRC8MEN bit */ + RCU_CTL |= RCU_CTL_IRC8MEN; + + RCU_MODIFY + + /* Reset CFG0 and CFG1 registers */ + RCU_CFG0 = 0x00000000U; + RCU_CFG1 = 0x00000000U; + +#if (defined(GD32F30X_HD) || defined(GD32F30X_XD)) + /* reset HXTALEN, CKMEN and PLLEN bits */ + RCU_CTL &= ~(RCU_CTL_PLLEN | RCU_CTL_CKMEN | RCU_CTL_HXTALEN); + /* disable all interrupts */ + RCU_INT = 0x009f0000U; +#elif defined(GD32F30X_CL) + /* Reset HXTALEN, CKMEN, PLLEN, PLL1EN and PLL2EN bits */ + RCU_CTL &= ~(RCU_CTL_PLLEN |RCU_CTL_PLL1EN | RCU_CTL_PLL2EN | RCU_CTL_CKMEN | RCU_CTL_HXTALEN); + /* disable all interrupts */ + RCU_INT = 0x00ff0000U; +#endif + + /* reset HXTALBPS bit */ + RCU_CTL &= ~(RCU_CTL_HXTALBPS); + + /* configure the system clock source, PLL Multiplier, AHB/APBx prescalers and Flash settings */ + system_clock_config(); +} +/*! + \brief configure the system clock + \param[in] none + \param[out] none + \retval none +*/ +static void system_clock_config(void) +{ +#ifdef __SYSTEM_CLOCK_IRC8M + system_clock_8m_irc8m(); +#elif defined (__SYSTEM_CLOCK_48M_PLL_IRC8M) + system_clock_48m_irc8m(); +#elif defined (__SYSTEM_CLOCK_72M_PLL_IRC8M) + system_clock_72m_irc8m(); +#elif defined (__SYSTEM_CLOCK_108M_PLL_IRC8M) + system_clock_108m_irc8m(); +#elif defined (__SYSTEM_CLOCK_120M_PLL_IRC8M) + system_clock_120m_irc8m(); + +#elif defined (__SYSTEM_CLOCK_HXTAL) + system_clock_hxtal(); +#elif defined (__SYSTEM_CLOCK_48M_PLL_HXTAL) + system_clock_48m_hxtal(); +#elif defined (__SYSTEM_CLOCK_72M_PLL_HXTAL) + system_clock_72m_hxtal(); +#elif defined (__SYSTEM_CLOCK_108M_PLL_HXTAL) + system_clock_108m_hxtal(); +#elif defined (__SYSTEM_CLOCK_120M_PLL_HXTAL) + system_clock_120m_hxtal(); +#endif /* __SYSTEM_CLOCK_IRC8M */ +} + +#ifdef __SYSTEM_CLOCK_IRC8M +/*! + \brief configure the system clock to 8M by IRC8M + \param[in] none + \param[out] none + \retval none +*/ +static void system_clock_8m_irc8m(void) +{ + uint32_t timeout = 0U; + uint32_t stab_flag = 0U; + + /* enable IRC8M */ + RCU_CTL |= RCU_CTL_IRC8MEN; + + /* wait until IRC8M is stable or the startup time is longer than IRC8M_STARTUP_TIMEOUT */ + do{ + timeout++; + stab_flag = (RCU_CTL & RCU_CTL_IRC8MSTB); + } + while((0U == stab_flag) && (IRC8M_STARTUP_TIMEOUT != timeout)); + + /* if fail */ + if(0U == (RCU_CTL & RCU_CTL_IRC8MSTB)){ + while(1){ + } + } + + /* AHB = SYSCLK */ + RCU_CFG0 |= RCU_AHB_CKSYS_DIV1; + /* APB2 = AHB/1 */ + RCU_CFG0 |= RCU_APB2_CKAHB_DIV1; + /* APB1 = AHB/2 */ + RCU_CFG0 |= RCU_APB1_CKAHB_DIV2; + + /* select IRC8M as system clock */ + RCU_CFG0 &= ~RCU_CFG0_SCS; + RCU_CFG0 |= RCU_CKSYSSRC_IRC8M; + + /* wait until IRC8M is selected as system clock */ + while(0U != (RCU_CFG0 & RCU_SCSS_IRC8M)){ + } +} + +#elif defined (__SYSTEM_CLOCK_48M_PLL_IRC8M) +/*! + \brief configure the system clock to 48M by PLL which selects IRC8M as its clock source + \param[in] none + \param[out] none + \retval none +*/ +static void system_clock_48m_irc8m(void) +{ + uint32_t timeout = 0U; + uint32_t stab_flag = 0U; + + /* enable IRC8M */ + RCU_CTL |= RCU_CTL_IRC8MEN; + + /* wait until IRC8M is stable or the startup time is longer than IRC8M_STARTUP_TIMEOUT */ + do{ + timeout++; + stab_flag = (RCU_CTL & RCU_CTL_IRC8MSTB); + } + while((0U == stab_flag) && (IRC8M_STARTUP_TIMEOUT != timeout)); + + /* if fail */ + if(0U == (RCU_CTL & RCU_CTL_IRC8MSTB)){ + while(1){ + } + } + + /* LDO output voltage high mode */ + RCU_APB1EN |= RCU_APB1EN_PMUEN; + PMU_CTL |= PMU_CTL_LDOVS; + + /* IRC8M is stable */ + /* AHB = SYSCLK */ + RCU_CFG0 |= RCU_AHB_CKSYS_DIV1; + /* APB2 = AHB/1 */ + RCU_CFG0 |= RCU_APB2_CKAHB_DIV1; + /* APB1 = AHB/2 */ + RCU_CFG0 |= RCU_APB1_CKAHB_DIV2; + + /* CK_PLL = (CK_IRC8M/2) * 12 = 48 MHz */ + RCU_CFG0 &= ~(RCU_CFG0_PLLMF | RCU_CFG0_PLLMF_4 | RCU_CFG0_PLLMF_5); + RCU_CFG0 |= RCU_PLL_MUL12; + + /* enable PLL */ + RCU_CTL |= RCU_CTL_PLLEN; + + /* wait until PLL is stable */ + while(0U == (RCU_CTL & RCU_CTL_PLLSTB)){ + } + + /* enable the high-drive to extend the clock frequency to 120 MHz */ + PMU_CTL |= PMU_CTL_HDEN; + while(0U == (PMU_CS & PMU_CS_HDRF)){ + } + + /* select the high-drive mode */ + PMU_CTL |= PMU_CTL_HDS; + while(0U == (PMU_CS & PMU_CS_HDSRF)){ + } + + /* select PLL as system clock */ + RCU_CFG0 &= ~RCU_CFG0_SCS; + RCU_CFG0 |= RCU_CKSYSSRC_PLL; + + /* wait until PLL is selected as system clock */ + while(0U == (RCU_CFG0 & RCU_SCSS_PLL)){ + } +} + +#elif defined (__SYSTEM_CLOCK_72M_PLL_IRC8M) +/*! + \brief configure the system clock to 72M by PLL which selects IRC8M as its clock source + \param[in] none + \param[out] none + \retval none +*/ +static void system_clock_72m_irc8m(void) +{ + uint32_t timeout = 0U; + uint32_t stab_flag = 0U; + + /* enable IRC8M */ + RCU_CTL |= RCU_CTL_IRC8MEN; + + /* wait until IRC8M is stable or the startup time is longer than IRC8M_STARTUP_TIMEOUT */ + do{ + timeout++; + stab_flag = (RCU_CTL & RCU_CTL_IRC8MSTB); + }while((0U == stab_flag) && (IRC8M_STARTUP_TIMEOUT != timeout)); + + /* if fail */ + if(0U == (RCU_CTL & RCU_CTL_IRC8MSTB)){ + while(1){ + } + } + + /* LDO output voltage high mode */ + RCU_APB1EN |= RCU_APB1EN_PMUEN; + PMU_CTL |= PMU_CTL_LDOVS; + + /* IRC8M is stable */ + /* AHB = SYSCLK */ + RCU_CFG0 |= RCU_AHB_CKSYS_DIV1; + /* APB2 = AHB/1 */ + RCU_CFG0 |= RCU_APB2_CKAHB_DIV1; + /* APB1 = AHB/2 */ + RCU_CFG0 |= RCU_APB1_CKAHB_DIV2; + + /* CK_PLL = (CK_IRC8M/2) * 18 = 72 MHz */ + RCU_CFG0 &= ~(RCU_CFG0_PLLMF | RCU_CFG0_PLLMF_4 | RCU_CFG0_PLLMF_5); + RCU_CFG0 |= RCU_PLL_MUL18; + + /* enable PLL */ + RCU_CTL |= RCU_CTL_PLLEN; + + /* wait until PLL is stable */ + while(0U == (RCU_CTL & RCU_CTL_PLLSTB)){ + } + + /* enable the high-drive to extend the clock frequency to 120 MHz */ + PMU_CTL |= PMU_CTL_HDEN; + while(0U == (PMU_CS & PMU_CS_HDRF)){ + } + + /* select the high-drive mode */ + PMU_CTL |= PMU_CTL_HDS; + while(0U == (PMU_CS & PMU_CS_HDSRF)){ + } + + /* select PLL as system clock */ + RCU_CFG0 &= ~RCU_CFG0_SCS; + RCU_CFG0 |= RCU_CKSYSSRC_PLL; + + /* wait until PLL is selected as system clock */ + while(0U == (RCU_CFG0 & RCU_SCSS_PLL)){ + } +} + +#elif defined (__SYSTEM_CLOCK_108M_PLL_IRC8M) +/*! + \brief configure the system clock to 108M by PLL which selects IRC8M as its clock source + \param[in] none + \param[out] none + \retval none +*/ +static void system_clock_108m_irc8m(void) +{ + uint32_t timeout = 0U; + uint32_t stab_flag = 0U; + + /* enable IRC8M */ + RCU_CTL |= RCU_CTL_IRC8MEN; + + /* wait until IRC8M is stable or the startup time is longer than IRC8M_STARTUP_TIMEOUT */ + do{ + timeout++; + stab_flag = (RCU_CTL & RCU_CTL_IRC8MSTB); + }while((0U == stab_flag) && (IRC8M_STARTUP_TIMEOUT != timeout)); + + /* if fail */ + if(0U == (RCU_CTL & RCU_CTL_IRC8MSTB)){ + while(1){ + } + } + + /* LDO output voltage high mode */ + RCU_APB1EN |= RCU_APB1EN_PMUEN; + PMU_CTL |= PMU_CTL_LDOVS; + + /* IRC8M is stable */ + /* AHB = SYSCLK */ + RCU_CFG0 |= RCU_AHB_CKSYS_DIV1; + /* APB2 = AHB/1 */ + RCU_CFG0 |= RCU_APB2_CKAHB_DIV1; + /* APB1 = AHB/2 */ + RCU_CFG0 |= RCU_APB1_CKAHB_DIV2; + + /* CK_PLL = (CK_IRC8M/2) * 27 = 108 MHz */ + RCU_CFG0 &= ~(RCU_CFG0_PLLMF | RCU_CFG0_PLLMF_4 | RCU_CFG0_PLLMF_5); + RCU_CFG0 |= RCU_PLL_MUL27; + + /* enable PLL */ + RCU_CTL |= RCU_CTL_PLLEN; + + /* wait until PLL is stable */ + while(0U == (RCU_CTL & RCU_CTL_PLLSTB)){ + } + + /* enable the high-drive to extend the clock frequency to 120 MHz */ + PMU_CTL |= PMU_CTL_HDEN; + while(0U == (PMU_CS & PMU_CS_HDRF)){ + } + + /* select the high-drive mode */ + PMU_CTL |= PMU_CTL_HDS; + while(0U == (PMU_CS & PMU_CS_HDSRF)){ + } + + /* select PLL as system clock */ + RCU_CFG0 &= ~RCU_CFG0_SCS; + RCU_CFG0 |= RCU_CKSYSSRC_PLL; + + /* wait until PLL is selected as system clock */ + while(0U == (RCU_CFG0 & RCU_SCSS_PLL)){ + } +} + +#elif defined (__SYSTEM_CLOCK_120M_PLL_IRC8M) +/*! + \brief configure the system clock to 120M by PLL which selects IRC8M as its clock source + \param[in] none + \param[out] none + \retval none +*/ +static void system_clock_120m_irc8m(void) +{ + uint32_t timeout = 0U; + uint32_t stab_flag = 0U; + + /* enable IRC8M */ + RCU_CTL |= RCU_CTL_IRC8MEN; + + /* wait until IRC8M is stable or the startup time is longer than IRC8M_STARTUP_TIMEOUT */ + do{ + timeout++; + stab_flag = (RCU_CTL & RCU_CTL_IRC8MSTB); + }while((0U == stab_flag) && (IRC8M_STARTUP_TIMEOUT != timeout)); + + /* if fail */ + if(0U == (RCU_CTL & RCU_CTL_IRC8MSTB)){ + while(1){ + } + } + + /* LDO output voltage high mode */ + RCU_APB1EN |= RCU_APB1EN_PMUEN; + PMU_CTL |= PMU_CTL_LDOVS; + + /* IRC8M is stable */ + /* AHB = SYSCLK */ + RCU_CFG0 |= RCU_AHB_CKSYS_DIV1; + /* APB2 = AHB/1 */ + RCU_CFG0 |= RCU_APB2_CKAHB_DIV1; + /* APB1 = AHB/2 */ + RCU_CFG0 |= RCU_APB1_CKAHB_DIV2; + + /* CK_PLL = (CK_IRC8M/2) * 30 = 120 MHz */ + RCU_CFG0 &= ~(RCU_CFG0_PLLMF | RCU_CFG0_PLLMF_4 | RCU_CFG0_PLLMF_5); + RCU_CFG0 |= RCU_PLL_MUL30; + + /* enable PLL */ + RCU_CTL |= RCU_CTL_PLLEN; + + /* wait until PLL is stable */ + while(0U == (RCU_CTL & RCU_CTL_PLLSTB)){ + } + + /* enable the high-drive to extend the clock frequency to 120 MHz */ + PMU_CTL |= PMU_CTL_HDEN; + while(0U == (PMU_CS & PMU_CS_HDRF)){ + } + + /* select the high-drive mode */ + PMU_CTL |= PMU_CTL_HDS; + while(0U == (PMU_CS & PMU_CS_HDSRF)){ + } + + /* select PLL as system clock */ + RCU_CFG0 &= ~RCU_CFG0_SCS; + RCU_CFG0 |= RCU_CKSYSSRC_PLL; + + /* wait until PLL is selected as system clock */ + while(0U == (RCU_CFG0 & RCU_SCSS_PLL)){ + } +} + +#elif defined (__SYSTEM_CLOCK_HXTAL) +/*! + \brief configure the system clock to HXTAL + \param[in] none + \param[out] none + \retval none +*/ +static void system_clock_hxtal(void) +{ + uint32_t timeout = 0U; + uint32_t stab_flag = 0U; + + /* enable HXTAL */ + RCU_CTL |= RCU_CTL_HXTALEN; + + /* wait until HXTAL is stable or the startup time is longer than HXTAL_STARTUP_TIMEOUT */ + do{ + timeout++; + stab_flag = (RCU_CTL & RCU_CTL_HXTALSTB); + }while((0U == stab_flag) && (HXTAL_STARTUP_TIMEOUT != timeout)); + + /* if fail */ + if(0U == (RCU_CTL & RCU_CTL_HXTALSTB)){ + while(1){ + } + } + + /* AHB = SYSCLK */ + RCU_CFG0 |= RCU_AHB_CKSYS_DIV1; + /* APB2 = AHB/1 */ + RCU_CFG0 |= RCU_APB2_CKAHB_DIV1; + /* APB1 = AHB/2 */ + RCU_CFG0 |= RCU_APB1_CKAHB_DIV2; + + /* select HXTAL as system clock */ + RCU_CFG0 &= ~RCU_CFG0_SCS; + RCU_CFG0 |= RCU_CKSYSSRC_HXTAL; + + /* wait until HXTAL is selected as system clock */ + while(0 == (RCU_CFG0 & RCU_SCSS_HXTAL)){ + } +} + +#elif defined (__SYSTEM_CLOCK_48M_PLL_HXTAL) +/*! + \brief configure the system clock to 48M by PLL which selects HXTAL(8M) as its clock source + \param[in] none + \param[out] none + \retval none +*/ +static void system_clock_48m_hxtal(void) +{ + uint32_t timeout = 0U; + uint32_t stab_flag = 0U; + + /* enable HXTAL */ + RCU_CTL |= RCU_CTL_HXTALEN; + + /* wait until HXTAL is stable or the startup time is longer than HXTAL_STARTUP_TIMEOUT */ + do{ + timeout++; + stab_flag = (RCU_CTL & RCU_CTL_HXTALSTB); + }while((0U == stab_flag) && (HXTAL_STARTUP_TIMEOUT != timeout)); + + /* if fail */ + if(0U == (RCU_CTL & RCU_CTL_HXTALSTB)){ + while(1){ + } + } + + RCU_APB1EN |= RCU_APB1EN_PMUEN; + PMU_CTL |= PMU_CTL_LDOVS; + + /* HXTAL is stable */ + /* AHB = SYSCLK */ + RCU_CFG0 |= RCU_AHB_CKSYS_DIV1; + /* APB2 = AHB/1 */ + RCU_CFG0 |= RCU_APB2_CKAHB_DIV1; + /* APB1 = AHB/2 */ + RCU_CFG0 |= RCU_APB1_CKAHB_DIV2; + +#if (defined(GD32F30X_HD) || defined(GD32F30X_XD)) + /* select HXTAL/2 as clock source */ + RCU_CFG0 &= ~(RCU_CFG0_PLLSEL | RCU_CFG0_PREDV0); + RCU_CFG0 |= (RCU_PLLSRC_HXTAL_IRC48M | RCU_CFG0_PREDV0); + + /* CK_PLL = (CK_HXTAL/2) * 12 = 48 MHz */ + RCU_CFG0 &= ~(RCU_CFG0_PLLMF | RCU_CFG0_PLLMF_4 | RCU_CFG0_PLLMF_5); + RCU_CFG0 |= RCU_PLL_MUL12; + +#elif defined(GD32F30X_CL) + /* CK_PLL = (CK_PREDIV0) * 12 = 48 MHz */ + RCU_CFG0 &= ~(RCU_CFG0_PLLMF | RCU_CFG0_PLLMF_4 | RCU_CFG0_PLLMF_5); + RCU_CFG0 |= (RCU_PLLSRC_HXTAL_IRC48M | RCU_PLL_MUL12); + + /* CK_PREDIV0 = (CK_HXTAL)/5 *8 /10 = 4 MHz */ + RCU_CFG1 &= ~(RCU_CFG1_PLLPRESEL | RCU_CFG1_PREDV0SEL | RCU_CFG1_PLL1MF | RCU_CFG1_PREDV1 | RCU_CFG1_PREDV0); + RCU_CFG1 |= (RCU_PLLPRESRC_HXTAL | RCU_PREDV0SRC_CKPLL1 | RCU_PLL1_MUL8 | RCU_PREDV1_DIV5 | RCU_PREDV0_DIV10); + + /* enable PLL1 */ + RCU_CTL |= RCU_CTL_PLL1EN; + /* wait till PLL1 is ready */ + while((RCU_CTL & RCU_CTL_PLL1STB) == 0){ + } +#endif /* GD32F30X_HD and GD32F30X_XD */ + + /* enable PLL */ + RCU_CTL |= RCU_CTL_PLLEN; + + /* wait until PLL is stable */ + while(0U == (RCU_CTL & RCU_CTL_PLLSTB)){ + } + + /* enable the high-drive to extend the clock frequency to 120 MHz */ + PMU_CTL |= PMU_CTL_HDEN; + while(0U == (PMU_CS & PMU_CS_HDRF)){ + } + + /* select the high-drive mode */ + PMU_CTL |= PMU_CTL_HDS; + while(0U == (PMU_CS & PMU_CS_HDSRF)){ + } + + /* select PLL as system clock */ + RCU_CFG0 &= ~RCU_CFG0_SCS; + RCU_CFG0 |= RCU_CKSYSSRC_PLL; + + /* wait until PLL is selected as system clock */ + while(0U == (RCU_CFG0 & RCU_SCSS_PLL)){ + } +} +#elif defined (__SYSTEM_CLOCK_72M_PLL_HXTAL) +/*! + \brief configure the system clock to 72M by PLL which selects HXTAL(8M) as its clock source + \param[in] none + \param[out] none + \retval none +*/ +static void system_clock_72m_hxtal(void) +{ + uint32_t timeout = 0U; + uint32_t stab_flag = 0U; + + /* enable HXTAL */ + RCU_CTL |= RCU_CTL_HXTALEN; + + /* wait until HXTAL is stable or the startup time is longer than HXTAL_STARTUP_TIMEOUT */ + do{ + timeout++; + stab_flag = (RCU_CTL & RCU_CTL_HXTALSTB); + }while((0U == stab_flag) && (HXTAL_STARTUP_TIMEOUT != timeout)); + + /* if fail */ + if(0U == (RCU_CTL & RCU_CTL_HXTALSTB)){ + while(1){ + } + } + + RCU_APB1EN |= RCU_APB1EN_PMUEN; + PMU_CTL |= PMU_CTL_LDOVS; + + /* HXTAL is stable */ + /* AHB = SYSCLK */ + RCU_CFG0 |= RCU_AHB_CKSYS_DIV1; + /* APB2 = AHB/1 */ + RCU_CFG0 |= RCU_APB2_CKAHB_DIV1; + /* APB1 = AHB/2 */ + RCU_CFG0 |= RCU_APB1_CKAHB_DIV2; + +#if (defined(GD32F30X_HD) || defined(GD32F30X_XD)) + /* select HXTAL/2 as clock source */ + RCU_CFG0 &= ~(RCU_CFG0_PLLSEL | RCU_CFG0_PREDV0); + RCU_CFG0 |= (RCU_PLLSRC_HXTAL_IRC48M | RCU_CFG0_PREDV0); + + /* CK_PLL = (CK_HXTAL/2) * 18 = 72 MHz */ + RCU_CFG0 &= ~(RCU_CFG0_PLLMF | RCU_CFG0_PLLMF_4 | RCU_CFG0_PLLMF_5); + RCU_CFG0 |= RCU_PLL_MUL18; + +#elif defined(GD32F30X_CL) + /* CK_PLL = (CK_PREDIV0) * 18 = 72 MHz */ + RCU_CFG0 &= ~(RCU_CFG0_PLLMF | RCU_CFG0_PLLMF_4 | RCU_CFG0_PLLMF_5); + RCU_CFG0 |= (RCU_PLLSRC_HXTAL_IRC48M | RCU_PLL_MUL18); + + /* CK_PREDIV0 = (CK_HXTAL)/5 *8 /10 = 4 MHz */ + RCU_CFG1 &= ~(RCU_CFG1_PLLPRESEL | RCU_CFG1_PREDV0SEL | RCU_CFG1_PLL1MF | RCU_CFG1_PREDV1 | RCU_CFG1_PREDV0); + RCU_CFG1 |= (RCU_PLLPRESRC_HXTAL | RCU_PREDV0SRC_CKPLL1 | RCU_PLL1_MUL8 | RCU_PREDV1_DIV5 | RCU_PREDV0_DIV10); + + /* enable PLL1 */ + RCU_CTL |= RCU_CTL_PLL1EN; + /* wait till PLL1 is ready */ + while((RCU_CTL & RCU_CTL_PLL1STB) == 0){ + } +#endif /* GD32F30X_HD and GD32F30X_XD */ + + /* enable PLL */ + RCU_CTL |= RCU_CTL_PLLEN; + + /* wait until PLL is stable */ + while(0U == (RCU_CTL & RCU_CTL_PLLSTB)){ + } + + /* enable the high-drive to extend the clock frequency to 120 MHz */ + PMU_CTL |= PMU_CTL_HDEN; + while(0U == (PMU_CS & PMU_CS_HDRF)){ + } + + /* select the high-drive mode */ + PMU_CTL |= PMU_CTL_HDS; + while(0U == (PMU_CS & PMU_CS_HDSRF)){ + } + + /* select PLL as system clock */ + RCU_CFG0 &= ~RCU_CFG0_SCS; + RCU_CFG0 |= RCU_CKSYSSRC_PLL; + + /* wait until PLL is selected as system clock */ + while(0U == (RCU_CFG0 & RCU_SCSS_PLL)){ + } +} + +#elif defined (__SYSTEM_CLOCK_108M_PLL_HXTAL) +/*! + \brief configure the system clock to 108M by PLL which selects HXTAL(8M) as its clock source + \param[in] none + \param[out] none + \retval none +*/ +static void system_clock_108m_hxtal(void) +{ + uint32_t timeout = 0U; + uint32_t stab_flag = 0U; + + /* enable HXTAL */ + RCU_CTL |= RCU_CTL_HXTALEN; + + /* wait until HXTAL is stable or the startup time is longer than HXTAL_STARTUP_TIMEOUT */ + do{ + timeout++; + stab_flag = (RCU_CTL & RCU_CTL_HXTALSTB); + }while((0U == stab_flag) && (HXTAL_STARTUP_TIMEOUT != timeout)); + + /* if fail */ + if(0U == (RCU_CTL & RCU_CTL_HXTALSTB)){ + while(1){ + } + } + + RCU_APB1EN |= RCU_APB1EN_PMUEN; + PMU_CTL |= PMU_CTL_LDOVS; + + /* HXTAL is stable */ + /* AHB = SYSCLK */ + RCU_CFG0 |= RCU_AHB_CKSYS_DIV1; + /* APB2 = AHB/1 */ + RCU_CFG0 |= RCU_APB2_CKAHB_DIV1; + /* APB1 = AHB/2 */ + RCU_CFG0 |= RCU_APB1_CKAHB_DIV2; + +#if (defined(GD32F30X_HD) || defined(GD32F30X_XD)) + /* select HXTAL/2 as clock source */ + RCU_CFG0 &= ~(RCU_CFG0_PLLSEL | RCU_CFG0_PREDV0); + RCU_CFG0 |= (RCU_PLLSRC_HXTAL_IRC48M | RCU_CFG0_PREDV0); + + /* CK_PLL = (CK_HXTAL/2) * 27 = 108 MHz */ + RCU_CFG0 &= ~(RCU_CFG0_PLLMF | RCU_CFG0_PLLMF_4 | RCU_CFG0_PLLMF_5); + RCU_CFG0 |= RCU_PLL_MUL27; + +#elif defined(GD32F30X_CL) + /* CK_PLL = (CK_PREDIV0) * 27 = 108 MHz */ + RCU_CFG0 &= ~(RCU_CFG0_PLLMF | RCU_CFG0_PLLMF_4 | RCU_CFG0_PLLMF_5); + RCU_CFG0 |= (RCU_PLLSRC_HXTAL_IRC48M | RCU_PLL_MUL27); + + /* CK_PREDIV0 = (CK_HXTAL)/5 *8 /10 = 4 MHz */ + RCU_CFG1 &= ~(RCU_CFG1_PLLPRESEL | RCU_CFG1_PREDV0SEL | RCU_CFG1_PLL1MF | RCU_CFG1_PREDV1 | RCU_CFG1_PREDV0); + RCU_CFG1 |= (RCU_PLLPRESRC_HXTAL | RCU_PREDV0SRC_CKPLL1 | RCU_PLL1_MUL8 | RCU_PREDV1_DIV5 | RCU_PREDV0_DIV10); + + /* enable PLL1 */ + RCU_CTL |= RCU_CTL_PLL1EN; + /* wait till PLL1 is ready */ + while((RCU_CTL & RCU_CTL_PLL1STB) == 0){ + } +#endif /* GD32F30X_HD and GD32F30X_XD */ + + /* enable PLL */ + RCU_CTL |= RCU_CTL_PLLEN; + + /* wait until PLL is stable */ + while(0U == (RCU_CTL & RCU_CTL_PLLSTB)){ + } + + /* enable the high-drive to extend the clock frequency to 120 MHz */ + PMU_CTL |= PMU_CTL_HDEN; + while(0U == (PMU_CS & PMU_CS_HDRF)){ + } + + /* select the high-drive mode */ + PMU_CTL |= PMU_CTL_HDS; + while(0U == (PMU_CS & PMU_CS_HDSRF)){ + } + + /* select PLL as system clock */ + RCU_CFG0 &= ~RCU_CFG0_SCS; + RCU_CFG0 |= RCU_CKSYSSRC_PLL; + + /* wait until PLL is selected as system clock */ + while(0U == (RCU_CFG0 & RCU_SCSS_PLL)){ + } +} + +#elif defined (__SYSTEM_CLOCK_120M_PLL_HXTAL) +/*! + \brief configure the system clock to 120M by PLL which selects HXTAL(8M) as its clock source + \param[in] none + \param[out] none + \retval none +*/ +static void system_clock_120m_hxtal(void) +{ + uint32_t timeout = 0U; + uint32_t stab_flag = 0U; + + /* enable HXTAL */ + RCU_CTL |= RCU_CTL_HXTALEN; + + /* wait until HXTAL is stable or the startup time is longer than HXTAL_STARTUP_TIMEOUT */ + do{ + timeout++; + stab_flag = (RCU_CTL & RCU_CTL_HXTALSTB); + }while((0U == stab_flag) && (HXTAL_STARTUP_TIMEOUT != timeout)); + + /* if fail */ + if(0U == (RCU_CTL & RCU_CTL_HXTALSTB)){ + while(1){ + } + } + + RCU_APB1EN |= RCU_APB1EN_PMUEN; + PMU_CTL |= PMU_CTL_LDOVS; + + /* HXTAL is stable */ + /* AHB = SYSCLK */ + RCU_CFG0 |= RCU_AHB_CKSYS_DIV1; + /* APB2 = AHB/1 */ + RCU_CFG0 |= RCU_APB2_CKAHB_DIV1; + /* APB1 = AHB/2 */ + RCU_CFG0 |= RCU_APB1_CKAHB_DIV2; + +#if (defined(GD32F30X_HD) || defined(GD32F30X_XD)) + /* select HXTAL/2 as clock source */ + RCU_CFG0 &= ~(RCU_CFG0_PLLSEL | RCU_CFG0_PREDV0); + RCU_CFG0 |= (RCU_PLLSRC_HXTAL_IRC48M | RCU_CFG0_PREDV0); + + /* CK_PLL = (CK_HXTAL/2) * 30 = 120 MHz */ + RCU_CFG0 &= ~(RCU_CFG0_PLLMF | RCU_CFG0_PLLMF_4 | RCU_CFG0_PLLMF_5); + RCU_CFG0 |= RCU_PLL_MUL30; + +#elif defined(GD32F30X_CL) + /* CK_PLL = (CK_PREDIV0) * 30 = 120 MHz */ + RCU_CFG0 &= ~(RCU_CFG0_PLLMF | RCU_CFG0_PLLMF_4 | RCU_CFG0_PLLMF_5); + RCU_CFG0 |= (RCU_PLLSRC_HXTAL_IRC48M | RCU_PLL_MUL30); + + /* CK_PREDIV0 = (CK_HXTAL)/5 *8 /10 = 4 MHz */ + RCU_CFG1 &= ~(RCU_CFG1_PLLPRESEL | RCU_CFG1_PREDV0SEL | RCU_CFG1_PLL1MF | RCU_CFG1_PREDV1 | RCU_CFG1_PREDV0); + RCU_CFG1 |= (RCU_PLLPRESRC_HXTAL | RCU_PREDV0SRC_CKPLL1 | RCU_PLL1_MUL8 | RCU_PREDV1_DIV5 | RCU_PREDV0_DIV10); + + /* enable PLL1 */ + RCU_CTL |= RCU_CTL_PLL1EN; + /* wait till PLL1 is ready */ + while((RCU_CTL & RCU_CTL_PLL1STB) == 0U){ + } +#endif /* GD32F30X_HD and GD32F30X_XD */ + + /* enable PLL */ + RCU_CTL |= RCU_CTL_PLLEN; + + /* wait until PLL is stable */ + while(0U == (RCU_CTL & RCU_CTL_PLLSTB)){ + } + + /* enable the high-drive to extend the clock frequency to 120 MHz */ + PMU_CTL |= PMU_CTL_HDEN; + while(0U == (PMU_CS & PMU_CS_HDRF)){ + } + + /* select the high-drive mode */ + PMU_CTL |= PMU_CTL_HDS; + while(0U == (PMU_CS & PMU_CS_HDSRF)){ + } + + /* select PLL as system clock */ + RCU_CFG0 &= ~RCU_CFG0_SCS; + RCU_CFG0 |= RCU_CKSYSSRC_PLL; + + /* wait until PLL is selected as system clock */ + while(0U == (RCU_CFG0 & RCU_SCSS_PLL)){ + } +} +#endif /* __SYSTEM_CLOCK_IRC8M */ + +/*! + \brief update the SystemCoreClock with current core clock retrieved from cpu registers + \param[in] none + \param[out] none + \retval none +*/ +void SystemCoreClockUpdate(void) +{ + uint32_t sws; + uint32_t pllsel, pllpresel, predv0sel, pllmf, ck_src, idx, clk_exp; + /* exponent of AHB, APB1 and APB2 clock divider */ + const uint8_t ahb_exp[16] = {0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 6, 7, 8, 9}; +#ifdef GD32F30X_CL + uint32_t predv0, predv1, pll1mf; +#endif /* GD32F30X_CL */ + + sws = GET_BITS(RCU_CFG0, 2, 3); + switch(sws){ + /* IRC8M is selected as CK_SYS */ + case SEL_IRC8M: + SystemCoreClock = IRC8M_VALUE; + break; + /* HXTAL is selected as CK_SYS */ + case SEL_HXTAL: + SystemCoreClock = HXTAL_VALUE; + break; + /* PLL is selected as CK_SYS */ + case SEL_PLL: + /* PLL clock source selection, HXTAL, IRC48M or IRC8M/2 */ + pllsel = (RCU_CFG0 & RCU_CFG0_PLLSEL); + + if(RCU_PLLSRC_HXTAL_IRC48M == pllsel){ + /* PLL clock source is HXTAL or IRC48M */ + pllpresel = (RCU_CFG1 & RCU_CFG1_PLLPRESEL); + + if(RCU_PLLPRESRC_HXTAL == pllpresel){ + /* PLL clock source is HXTAL */ + ck_src = HXTAL_VALUE; + }else{ + /* PLL clock source is IRC48 */ + ck_src = IRC48M_VALUE; + } + +#if (defined(GD32F30X_HD) || defined(GD32F30X_XD)) + predv0sel = (RCU_CFG0 & RCU_CFG0_PREDV0); + /* PREDV0 input source clock divided by 2 */ + if(RCU_CFG0_PREDV0 == predv0sel){ + ck_src = HXTAL_VALUE / 2U; + } +#elif defined(GD32F30X_CL) + predv0sel = (RCU_CFG1 & RCU_CFG1_PREDV0SEL); + /* source clock use PLL1 */ + if(RCU_PREDV0SRC_CKPLL1 == predv0sel){ + predv1 = ((RCU_CFG1 & RCU_CFG1_PREDV1) >> 4) + 1U; + pll1mf = ((RCU_CFG1 & RCU_CFG1_PLL1MF) >> 8) + 2U; + if(17U == pll1mf){ + pll1mf = 20U; + } + ck_src = (ck_src / predv1) * pll1mf; + } + predv0 = (RCU_CFG1 & RCU_CFG1_PREDV0) + 1U; + ck_src /= predv0; +#endif /* GD32F30X_HD and GD32F30X_XD */ + }else{ + /* PLL clock source is IRC8M/2 */ + ck_src = IRC8M_VALUE / 2U; + } + + /* PLL multiplication factor */ + pllmf = GET_BITS(RCU_CFG0, 18, 21); + + if((RCU_CFG0 & RCU_CFG0_PLLMF_4)){ + pllmf |= 0x10U; + } + if((RCU_CFG0 & RCU_CFG0_PLLMF_5)){ + pllmf |= 0x20U; + } + + if( pllmf >= 15U){ + pllmf += 1U; + }else{ + pllmf += 2U; + } + if(pllmf > 61U){ + pllmf = 63U; + } + SystemCoreClock = ck_src * pllmf; + #ifdef GD32F30X_CL + if(15U == pllmf){ + SystemCoreClock = (ck_src * 6U) + (ck_src / 2U); + } + #endif /* GD32F30X_CL */ + break; + /* IRC8M is selected as CK_SYS */ + default: + SystemCoreClock = IRC8M_VALUE; + break; + } + + /* calculate AHB clock frequency */ + idx = GET_BITS(RCU_CFG0, 4, 7); + clk_exp = ahb_exp[idx]; + SystemCoreClock = SystemCoreClock >> clk_exp; +} diff --git a/bsp/gd32/libraries/GD32F4xx_HAL/CMSIS/core_cm4.h b/bsp/gd32/libraries/GD32F30x_Firmware_Library/CMSIS/core_cm4.h similarity index 100% rename from bsp/gd32/libraries/GD32F4xx_HAL/CMSIS/core_cm4.h rename to bsp/gd32/libraries/GD32F30x_Firmware_Library/CMSIS/core_cm4.h diff --git a/bsp/gd32/libraries/GD32F4xx_HAL/CMSIS/core_cm4_simd.h b/bsp/gd32/libraries/GD32F30x_Firmware_Library/CMSIS/core_cm4_simd.h similarity index 100% rename from bsp/gd32/libraries/GD32F4xx_HAL/CMSIS/core_cm4_simd.h rename to bsp/gd32/libraries/GD32F30x_Firmware_Library/CMSIS/core_cm4_simd.h diff --git a/bsp/gd32/libraries/GD32F30x_Firmware_Library/CMSIS/core_cmFunc.h b/bsp/gd32/libraries/GD32F30x_Firmware_Library/CMSIS/core_cmFunc.h new file mode 100644 index 0000000000..3c932e0d6e --- /dev/null +++ b/bsp/gd32/libraries/GD32F30x_Firmware_Library/CMSIS/core_cmFunc.h @@ -0,0 +1,616 @@ +/**************************************************************************//** + * @file core_cmFunc.h + * @brief CMSIS Cortex-M Core Function Access Header File + * @version V3.01 + * @date 06. March 2012 + * + * @note + * Copyright (C) 2009-2012 ARM Limited. All rights reserved. + * + * @par + * ARM Limited (ARM) is supplying this software for use with Cortex-M + * processor based microcontrollers. This file can be freely distributed + * within development tools that are supporting such ARM based processors. + * + * @par + * THIS SOFTWARE IS PROVIDED "AS IS". NO WARRANTIES, WHETHER EXPRESS, IMPLIED + * OR STATUTORY, INCLUDING, BUT NOT LIMITED TO, IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE APPLY TO THIS SOFTWARE. + * ARM SHALL NOT, IN ANY CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL, OR + * CONSEQUENTIAL DAMAGES, FOR ANY REASON WHATSOEVER. + * + ******************************************************************************/ + +#ifndef __CORE_CMFUNC_H +#define __CORE_CMFUNC_H + + +/* ########################### Core Function Access ########################### */ +/** \ingroup CMSIS_Core_FunctionInterface + \defgroup CMSIS_Core_RegAccFunctions CMSIS Core Register Access Functions + @{ + */ + +#if defined ( __CC_ARM ) /*------------------RealView Compiler -----------------*/ +/* ARM armcc specific functions */ + +#if (__ARMCC_VERSION < 400677) + #error "Please use ARM Compiler Toolchain V4.0.677 or later!" +#endif + +/* intrinsic void __enable_irq(); */ +/* intrinsic void __disable_irq(); */ + +/** \brief Get Control Register + + This function returns the content of the Control Register. + + \return Control Register value + */ +__STATIC_INLINE uint32_t __get_CONTROL(void) +{ + register uint32_t __regControl __ASM("control"); + return(__regControl); +} + + +/** \brief Set Control Register + + This function writes the given value to the Control Register. + + \param [in] control Control Register value to set + */ +__STATIC_INLINE void __set_CONTROL(uint32_t control) +{ + register uint32_t __regControl __ASM("control"); + __regControl = control; +} + + +/** \brief Get IPSR Register + + This function returns the content of the IPSR Register. + + \return IPSR Register value + */ +__STATIC_INLINE uint32_t __get_IPSR(void) +{ + register uint32_t __regIPSR __ASM("ipsr"); + return(__regIPSR); +} + + +/** \brief Get APSR Register + + This function returns the content of the APSR Register. + + \return APSR Register value + */ +__STATIC_INLINE uint32_t __get_APSR(void) +{ + register uint32_t __regAPSR __ASM("apsr"); + return(__regAPSR); +} + + +/** \brief Get xPSR Register + + This function returns the content of the xPSR Register. + + \return xPSR Register value + */ +__STATIC_INLINE uint32_t __get_xPSR(void) +{ + register uint32_t __regXPSR __ASM("xpsr"); + return(__regXPSR); +} + + +/** \brief Get Process Stack Pointer + + This function returns the current value of the Process Stack Pointer (PSP). + + \return PSP Register value + */ +__STATIC_INLINE uint32_t __get_PSP(void) +{ + register uint32_t __regProcessStackPointer __ASM("psp"); + return(__regProcessStackPointer); +} + + +/** \brief Set Process Stack Pointer + + This function assigns the given value to the Process Stack Pointer (PSP). + + \param [in] topOfProcStack Process Stack Pointer value to set + */ +__STATIC_INLINE void __set_PSP(uint32_t topOfProcStack) +{ + register uint32_t __regProcessStackPointer __ASM("psp"); + __regProcessStackPointer = topOfProcStack; +} + + +/** \brief Get Main Stack Pointer + + This function returns the current value of the Main Stack Pointer (MSP). + + \return MSP Register value + */ +__STATIC_INLINE uint32_t __get_MSP(void) +{ + register uint32_t __regMainStackPointer __ASM("msp"); + return(__regMainStackPointer); +} + + +/** \brief Set Main Stack Pointer + + This function assigns the given value to the Main Stack Pointer (MSP). + + \param [in] topOfMainStack Main Stack Pointer value to set + */ +__STATIC_INLINE void __set_MSP(uint32_t topOfMainStack) +{ + register uint32_t __regMainStackPointer __ASM("msp"); + __regMainStackPointer = topOfMainStack; +} + + +/** \brief Get Priority Mask + + This function returns the current state of the priority mask bit from the Priority Mask Register. + + \return Priority Mask value + */ +__STATIC_INLINE uint32_t __get_PRIMASK(void) +{ + register uint32_t __regPriMask __ASM("primask"); + return(__regPriMask); +} + + +/** \brief Set Priority Mask + + This function assigns the given value to the Priority Mask Register. + + \param [in] priMask Priority Mask + */ +__STATIC_INLINE void __set_PRIMASK(uint32_t priMask) +{ + register uint32_t __regPriMask __ASM("primask"); + __regPriMask = (priMask); +} + + +#if (__CORTEX_M >= 0x03) + +/** \brief Enable FIQ + + This function enables FIQ interrupts by clearing the F-bit in the CPSR. + Can only be executed in Privileged modes. + */ +#define __enable_fault_irq __enable_fiq + + +/** \brief Disable FIQ + + This function disables FIQ interrupts by setting the F-bit in the CPSR. + Can only be executed in Privileged modes. + */ +#define __disable_fault_irq __disable_fiq + + +/** \brief Get Base Priority + + This function returns the current value of the Base Priority register. + + \return Base Priority register value + */ +__STATIC_INLINE uint32_t __get_BASEPRI(void) +{ + register uint32_t __regBasePri __ASM("basepri"); + return(__regBasePri); +} + + +/** \brief Set Base Priority + + This function assigns the given value to the Base Priority register. + + \param [in] basePri Base Priority value to set + */ +__STATIC_INLINE void __set_BASEPRI(uint32_t basePri) +{ + register uint32_t __regBasePri __ASM("basepri"); + __regBasePri = (basePri & 0xff); +} + + +/** \brief Get Fault Mask + + This function returns the current value of the Fault Mask register. + + \return Fault Mask register value + */ +__STATIC_INLINE uint32_t __get_FAULTMASK(void) +{ + register uint32_t __regFaultMask __ASM("faultmask"); + return(__regFaultMask); +} + + +/** \brief Set Fault Mask + + This function assigns the given value to the Fault Mask register. + + \param [in] faultMask Fault Mask value to set + */ +__STATIC_INLINE void __set_FAULTMASK(uint32_t faultMask) +{ + register uint32_t __regFaultMask __ASM("faultmask"); + __regFaultMask = (faultMask & (uint32_t)1); +} + +#endif /* (__CORTEX_M >= 0x03) */ + + +#if (__CORTEX_M == 0x04) + +/** \brief Get FPSCR + + This function returns the current value of the Floating Point Status/Control register. + + \return Floating Point Status/Control register value + */ +__STATIC_INLINE uint32_t __get_FPSCR(void) +{ +#if (__FPU_PRESENT == 1) && (__FPU_USED == 1) + register uint32_t __regfpscr __ASM("fpscr"); + return(__regfpscr); +#else + return(0); +#endif +} + + +/** \brief Set FPSCR + + This function assigns the given value to the Floating Point Status/Control register. + + \param [in] fpscr Floating Point Status/Control value to set + */ +__STATIC_INLINE void __set_FPSCR(uint32_t fpscr) +{ +#if (__FPU_PRESENT == 1) && (__FPU_USED == 1) + register uint32_t __regfpscr __ASM("fpscr"); + __regfpscr = (fpscr); +#endif +} + +#endif /* (__CORTEX_M == 0x04) */ + + +#elif defined ( __ICCARM__ ) /*------------------ ICC Compiler -------------------*/ +/* IAR iccarm specific functions */ + +#include + + +#elif defined ( __TMS470__ ) /*---------------- TI CCS Compiler ------------------*/ +/* TI CCS specific functions */ + +#include + + +#elif defined ( __GNUC__ ) /*------------------ GNU Compiler ---------------------*/ +/* GNU gcc specific functions */ + +/** \brief Enable IRQ Interrupts + + This function enables IRQ interrupts by clearing the I-bit in the CPSR. + Can only be executed in Privileged modes. + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE void __enable_irq(void) +{ + __ASM volatile ("cpsie i"); +} + + +/** \brief Disable IRQ Interrupts + + This function disables IRQ interrupts by setting the I-bit in the CPSR. + Can only be executed in Privileged modes. + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE void __disable_irq(void) +{ + __ASM volatile ("cpsid i"); +} + + +/** \brief Get Control Register + + This function returns the content of the Control Register. + + \return Control Register value + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __get_CONTROL(void) +{ + uint32_t result; + + __ASM volatile ("MRS %0, control" : "=r" (result) ); + return(result); +} + + +/** \brief Set Control Register + + This function writes the given value to the Control Register. + + \param [in] control Control Register value to set + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE void __set_CONTROL(uint32_t control) +{ + __ASM volatile ("MSR control, %0" : : "r" (control) ); +} + + +/** \brief Get IPSR Register + + This function returns the content of the IPSR Register. + + \return IPSR Register value + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __get_IPSR(void) +{ + uint32_t result; + + __ASM volatile ("MRS %0, ipsr" : "=r" (result) ); + return(result); +} + + +/** \brief Get APSR Register + + This function returns the content of the APSR Register. + + \return APSR Register value + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __get_APSR(void) +{ + uint32_t result; + + __ASM volatile ("MRS %0, apsr" : "=r" (result) ); + return(result); +} + + +/** \brief Get xPSR Register + + This function returns the content of the xPSR Register. + + \return xPSR Register value + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __get_xPSR(void) +{ + uint32_t result; + + __ASM volatile ("MRS %0, xpsr" : "=r" (result) ); + return(result); +} + + +/** \brief Get Process Stack Pointer + + This function returns the current value of the Process Stack Pointer (PSP). + + \return PSP Register value + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __get_PSP(void) +{ + register uint32_t result; + + __ASM volatile ("MRS %0, psp\n" : "=r" (result) ); + return(result); +} + + +/** \brief Set Process Stack Pointer + + This function assigns the given value to the Process Stack Pointer (PSP). + + \param [in] topOfProcStack Process Stack Pointer value to set + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE void __set_PSP(uint32_t topOfProcStack) +{ + __ASM volatile ("MSR psp, %0\n" : : "r" (topOfProcStack) ); +} + + +/** \brief Get Main Stack Pointer + + This function returns the current value of the Main Stack Pointer (MSP). + + \return MSP Register value + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __get_MSP(void) +{ + register uint32_t result; + + __ASM volatile ("MRS %0, msp\n" : "=r" (result) ); + return(result); +} + + +/** \brief Set Main Stack Pointer + + This function assigns the given value to the Main Stack Pointer (MSP). + + \param [in] topOfMainStack Main Stack Pointer value to set + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE void __set_MSP(uint32_t topOfMainStack) +{ + __ASM volatile ("MSR msp, %0\n" : : "r" (topOfMainStack) ); +} + + +/** \brief Get Priority Mask + + This function returns the current state of the priority mask bit from the Priority Mask Register. + + \return Priority Mask value + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __get_PRIMASK(void) +{ + uint32_t result; + + __ASM volatile ("MRS %0, primask" : "=r" (result) ); + return(result); +} + + +/** \brief Set Priority Mask + + This function assigns the given value to the Priority Mask Register. + + \param [in] priMask Priority Mask + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE void __set_PRIMASK(uint32_t priMask) +{ + __ASM volatile ("MSR primask, %0" : : "r" (priMask) ); +} + + +#if (__CORTEX_M >= 0x03) + +/** \brief Enable FIQ + + This function enables FIQ interrupts by clearing the F-bit in the CPSR. + Can only be executed in Privileged modes. + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE void __enable_fault_irq(void) +{ + __ASM volatile ("cpsie f"); +} + + +/** \brief Disable FIQ + + This function disables FIQ interrupts by setting the F-bit in the CPSR. + Can only be executed in Privileged modes. + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE void __disable_fault_irq(void) +{ + __ASM volatile ("cpsid f"); +} + + +/** \brief Get Base Priority + + This function returns the current value of the Base Priority register. + + \return Base Priority register value + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __get_BASEPRI(void) +{ + uint32_t result; + + __ASM volatile ("MRS %0, basepri_max" : "=r" (result) ); + return(result); +} + + +/** \brief Set Base Priority + + This function assigns the given value to the Base Priority register. + + \param [in] basePri Base Priority value to set + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE void __set_BASEPRI(uint32_t value) +{ + __ASM volatile ("MSR basepri, %0" : : "r" (value) ); +} + + +/** \brief Get Fault Mask + + This function returns the current value of the Fault Mask register. + + \return Fault Mask register value + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __get_FAULTMASK(void) +{ + uint32_t result; + + __ASM volatile ("MRS %0, faultmask" : "=r" (result) ); + return(result); +} + + +/** \brief Set Fault Mask + + This function assigns the given value to the Fault Mask register. + + \param [in] faultMask Fault Mask value to set + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE void __set_FAULTMASK(uint32_t faultMask) +{ + __ASM volatile ("MSR faultmask, %0" : : "r" (faultMask) ); +} + +#endif /* (__CORTEX_M >= 0x03) */ + + +#if (__CORTEX_M == 0x04) + +/** \brief Get FPSCR + + This function returns the current value of the Floating Point Status/Control register. + + \return Floating Point Status/Control register value + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __get_FPSCR(void) +{ +#if (__FPU_PRESENT == 1) && (__FPU_USED == 1) + uint32_t result; + + __ASM volatile ("VMRS %0, fpscr" : "=r" (result) ); + return(result); +#else + return(0); +#endif +} + + +/** \brief Set FPSCR + + This function assigns the given value to the Floating Point Status/Control register. + + \param [in] fpscr Floating Point Status/Control value to set + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE void __set_FPSCR(uint32_t fpscr) +{ +#if (__FPU_PRESENT == 1) && (__FPU_USED == 1) + __ASM volatile ("VMSR fpscr, %0" : : "r" (fpscr) ); +#endif +} + +#endif /* (__CORTEX_M == 0x04) */ + + +#elif defined ( __TASKING__ ) /*------------------ TASKING Compiler --------------*/ +/* TASKING carm specific functions */ + +/* + * The CMSIS functions have been implemented as intrinsics in the compiler. + * Please use "carm -?i" to get an up to date list of all instrinsics, + * Including the CMSIS ones. + */ + +#endif + +/*@} end of CMSIS_Core_RegAccFunctions */ + + +#endif /* __CORE_CMFUNC_H */ diff --git a/bsp/gd32/libraries/GD32F30x_Firmware_Library/CMSIS/core_cmInstr.h b/bsp/gd32/libraries/GD32F30x_Firmware_Library/CMSIS/core_cmInstr.h new file mode 100644 index 0000000000..597e64df04 --- /dev/null +++ b/bsp/gd32/libraries/GD32F30x_Firmware_Library/CMSIS/core_cmInstr.h @@ -0,0 +1,618 @@ +/**************************************************************************//** + * @file core_cmInstr.h + * @brief CMSIS Cortex-M Core Instruction Access Header File + * @version V3.01 + * @date 06. March 2012 + * + * @note + * Copyright (C) 2009-2012 ARM Limited. All rights reserved. + * + * @par + * ARM Limited (ARM) is supplying this software for use with Cortex-M + * processor based microcontrollers. This file can be freely distributed + * within development tools that are supporting such ARM based processors. + * + * @par + * THIS SOFTWARE IS PROVIDED "AS IS". NO WARRANTIES, WHETHER EXPRESS, IMPLIED + * OR STATUTORY, INCLUDING, BUT NOT LIMITED TO, IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE APPLY TO THIS SOFTWARE. + * ARM SHALL NOT, IN ANY CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL, OR + * CONSEQUENTIAL DAMAGES, FOR ANY REASON WHATSOEVER. + * + ******************************************************************************/ + +#ifndef __CORE_CMINSTR_H +#define __CORE_CMINSTR_H + + +/* ########################## Core Instruction Access ######################### */ +/** \defgroup CMSIS_Core_InstructionInterface CMSIS Core Instruction Interface + Access to dedicated instructions + @{ +*/ + +#if defined ( __CC_ARM ) /*------------------RealView Compiler -----------------*/ +/* ARM armcc specific functions */ + +#if (__ARMCC_VERSION < 400677) + #error "Please use ARM Compiler Toolchain V4.0.677 or later!" +#endif + + +/** \brief No Operation + + No Operation does nothing. This instruction can be used for code alignment purposes. + */ +#define __NOP __nop + + +/** \brief Wait For Interrupt + + Wait For Interrupt is a hint instruction that suspends execution + until one of a number of events occurs. + */ +#define __WFI __wfi + + +/** \brief Wait For Event + + Wait For Event is a hint instruction that permits the processor to enter + a low-power state until one of a number of events occurs. + */ +#define __WFE __wfe + + +/** \brief Send Event + + Send Event is a hint instruction. It causes an event to be signaled to the CPU. + */ +#define __SEV __sev + + +/** \brief Instruction Synchronization Barrier + + Instruction Synchronization Barrier flushes the pipeline in the processor, + so that all instructions following the ISB are fetched from cache or + memory, after the instruction has been completed. + */ +#define __ISB() __isb(0xF) + + +/** \brief Data Synchronization Barrier + + This function acts as a special kind of Data Memory Barrier. + It completes when all explicit memory accesses before this instruction complete. + */ +#define __DSB() __dsb(0xF) + + +/** \brief Data Memory Barrier + + This function ensures the apparent order of the explicit memory operations before + and after the instruction, without ensuring their completion. + */ +#define __DMB() __dmb(0xF) + + +/** \brief Reverse byte order (32 bit) + + This function reverses the byte order in integer value. + + \param [in] value Value to reverse + \return Reversed value + */ +#define __REV __rev + + +/** \brief Reverse byte order (16 bit) + + This function reverses the byte order in two unsigned short values. + + \param [in] value Value to reverse + \return Reversed value + */ +__attribute__((section(".rev16_text"))) __STATIC_INLINE __ASM uint32_t __REV16(uint32_t value) +{ + rev16 r0, r0 + bx lr +} + + +/** \brief Reverse byte order in signed short value + + This function reverses the byte order in a signed short value with sign extension to integer. + + \param [in] value Value to reverse + \return Reversed value + */ +__attribute__((section(".revsh_text"))) __STATIC_INLINE __ASM int32_t __REVSH(int32_t value) +{ + revsh r0, r0 + bx lr +} + + +/** \brief Rotate Right in unsigned value (32 bit) + + This function Rotate Right (immediate) provides the value of the contents of a register rotated by a variable number of bits. + + \param [in] value Value to rotate + \param [in] value Number of Bits to rotate + \return Rotated value + */ +#define __ROR __ror + + +#if (__CORTEX_M >= 0x03) + +/** \brief Reverse bit order of value + + This function reverses the bit order of the given value. + + \param [in] value Value to reverse + \return Reversed value + */ +#define __RBIT __rbit + + +/** \brief LDR Exclusive (8 bit) + + This function performs a exclusive LDR command for 8 bit value. + + \param [in] ptr Pointer to data + \return value of type uint8_t at (*ptr) + */ +#define __LDREXB(ptr) ((uint8_t ) __ldrex(ptr)) + + +/** \brief LDR Exclusive (16 bit) + + This function performs a exclusive LDR command for 16 bit values. + + \param [in] ptr Pointer to data + \return value of type uint16_t at (*ptr) + */ +#define __LDREXH(ptr) ((uint16_t) __ldrex(ptr)) + + +/** \brief LDR Exclusive (32 bit) + + This function performs a exclusive LDR command for 32 bit values. + + \param [in] ptr Pointer to data + \return value of type uint32_t at (*ptr) + */ +#define __LDREXW(ptr) ((uint32_t ) __ldrex(ptr)) + + +/** \brief STR Exclusive (8 bit) + + This function performs a exclusive STR command for 8 bit values. + + \param [in] value Value to store + \param [in] ptr Pointer to location + \return 0 Function succeeded + \return 1 Function failed + */ +#define __STREXB(value, ptr) __strex(value, ptr) + + +/** \brief STR Exclusive (16 bit) + + This function performs a exclusive STR command for 16 bit values. + + \param [in] value Value to store + \param [in] ptr Pointer to location + \return 0 Function succeeded + \return 1 Function failed + */ +#define __STREXH(value, ptr) __strex(value, ptr) + + +/** \brief STR Exclusive (32 bit) + + This function performs a exclusive STR command for 32 bit values. + + \param [in] value Value to store + \param [in] ptr Pointer to location + \return 0 Function succeeded + \return 1 Function failed + */ +#define __STREXW(value, ptr) __strex(value, ptr) + + +/** \brief Remove the exclusive lock + + This function removes the exclusive lock which is created by LDREX. + + */ +#define __CLREX __clrex + + +/** \brief Signed Saturate + + This function saturates a signed value. + + \param [in] value Value to be saturated + \param [in] sat Bit position to saturate to (1..32) + \return Saturated value + */ +#define __SSAT __ssat + + +/** \brief Unsigned Saturate + + This function saturates an unsigned value. + + \param [in] value Value to be saturated + \param [in] sat Bit position to saturate to (0..31) + \return Saturated value + */ +#define __USAT __usat + + +/** \brief Count leading zeros + + This function counts the number of leading zeros of a data value. + + \param [in] value Value to count the leading zeros + \return number of leading zeros in value + */ +#define __CLZ __clz + +#endif /* (__CORTEX_M >= 0x03) */ + + + +#elif defined ( __ICCARM__ ) /*------------------ ICC Compiler -------------------*/ +/* IAR iccarm specific functions */ + +#include + + +#elif defined ( __TMS470__ ) /*---------------- TI CCS Compiler ------------------*/ +/* TI CCS specific functions */ + +#include + + +#elif defined ( __GNUC__ ) /*------------------ GNU Compiler ---------------------*/ +/* GNU gcc specific functions */ + +/** \brief No Operation + + No Operation does nothing. This instruction can be used for code alignment purposes. + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE void __NOP(void) +{ + __ASM volatile ("nop"); +} + + +/** \brief Wait For Interrupt + + Wait For Interrupt is a hint instruction that suspends execution + until one of a number of events occurs. + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE void __WFI(void) +{ + __ASM volatile ("wfi"); +} + + +/** \brief Wait For Event + + Wait For Event is a hint instruction that permits the processor to enter + a low-power state until one of a number of events occurs. + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE void __WFE(void) +{ + __ASM volatile ("wfe"); +} + + +/** \brief Send Event + + Send Event is a hint instruction. It causes an event to be signaled to the CPU. + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE void __SEV(void) +{ + __ASM volatile ("sev"); +} + + +/** \brief Instruction Synchronization Barrier + + Instruction Synchronization Barrier flushes the pipeline in the processor, + so that all instructions following the ISB are fetched from cache or + memory, after the instruction has been completed. + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE void __ISB(void) +{ + __ASM volatile ("isb"); +} + + +/** \brief Data Synchronization Barrier + + This function acts as a special kind of Data Memory Barrier. + It completes when all explicit memory accesses before this instruction complete. + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE void __DSB(void) +{ + __ASM volatile ("dsb"); +} + + +/** \brief Data Memory Barrier + + This function ensures the apparent order of the explicit memory operations before + and after the instruction, without ensuring their completion. + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE void __DMB(void) +{ + __ASM volatile ("dmb"); +} + + +/** \brief Reverse byte order (32 bit) + + This function reverses the byte order in integer value. + + \param [in] value Value to reverse + \return Reversed value + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __REV(uint32_t value) +{ + uint32_t result; + + __ASM volatile ("rev %0, %1" : "=r" (result) : "r" (value) ); + return(result); +} + + +/** \brief Reverse byte order (16 bit) + + This function reverses the byte order in two unsigned short values. + + \param [in] value Value to reverse + \return Reversed value + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __REV16(uint32_t value) +{ + uint32_t result; + + __ASM volatile ("rev16 %0, %1" : "=r" (result) : "r" (value) ); + return(result); +} + + +/** \brief Reverse byte order in signed short value + + This function reverses the byte order in a signed short value with sign extension to integer. + + \param [in] value Value to reverse + \return Reversed value + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE int32_t __REVSH(int32_t value) +{ + uint32_t result; + + __ASM volatile ("revsh %0, %1" : "=r" (result) : "r" (value) ); + return(result); +} + + +/** \brief Rotate Right in unsigned value (32 bit) + + This function Rotate Right (immediate) provides the value of the contents of a register rotated by a variable number of bits. + + \param [in] value Value to rotate + \param [in] value Number of Bits to rotate + \return Rotated value + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __ROR(uint32_t op1, uint32_t op2) +{ + + __ASM volatile ("ror %0, %0, %1" : "+r" (op1) : "r" (op2) ); + return(op1); +} + + +#if (__CORTEX_M >= 0x03) + +/** \brief Reverse bit order of value + + This function reverses the bit order of the given value. + + \param [in] value Value to reverse + \return Reversed value + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __RBIT(uint32_t value) +{ + uint32_t result; + + __ASM volatile ("rbit %0, %1" : "=r" (result) : "r" (value) ); + return(result); +} + + +/** \brief LDR Exclusive (8 bit) + + This function performs a exclusive LDR command for 8 bit value. + + \param [in] ptr Pointer to data + \return value of type uint8_t at (*ptr) + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE uint8_t __LDREXB(volatile uint8_t *addr) +{ + uint8_t result; + + __ASM volatile ("ldrexb %0, [%1]" : "=r" (result) : "r" (addr) ); + return(result); +} + + +/** \brief LDR Exclusive (16 bit) + + This function performs a exclusive LDR command for 16 bit values. + + \param [in] ptr Pointer to data + \return value of type uint16_t at (*ptr) + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE uint16_t __LDREXH(volatile uint16_t *addr) +{ + uint16_t result; + + __ASM volatile ("ldrexh %0, [%1]" : "=r" (result) : "r" (addr) ); + return(result); +} + + +/** \brief LDR Exclusive (32 bit) + + This function performs a exclusive LDR command for 32 bit values. + + \param [in] ptr Pointer to data + \return value of type uint32_t at (*ptr) + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __LDREXW(volatile uint32_t *addr) +{ + uint32_t result; + + __ASM volatile ("ldrex %0, [%1]" : "=r" (result) : "r" (addr) ); + return(result); +} + + +/** \brief STR Exclusive (8 bit) + + This function performs a exclusive STR command for 8 bit values. + + \param [in] value Value to store + \param [in] ptr Pointer to location + \return 0 Function succeeded + \return 1 Function failed + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __STREXB(uint8_t value, volatile uint8_t *addr) +{ + uint32_t result; + + __ASM volatile ("strexb %0, %2, [%1]" : "=&r" (result) : "r" (addr), "r" (value) ); + return(result); +} + + +/** \brief STR Exclusive (16 bit) + + This function performs a exclusive STR command for 16 bit values. + + \param [in] value Value to store + \param [in] ptr Pointer to location + \return 0 Function succeeded + \return 1 Function failed + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __STREXH(uint16_t value, volatile uint16_t *addr) +{ + uint32_t result; + + __ASM volatile ("strexh %0, %2, [%1]" : "=&r" (result) : "r" (addr), "r" (value) ); + return(result); +} + + +/** \brief STR Exclusive (32 bit) + + This function performs a exclusive STR command for 32 bit values. + + \param [in] value Value to store + \param [in] ptr Pointer to location + \return 0 Function succeeded + \return 1 Function failed + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __STREXW(uint32_t value, volatile uint32_t *addr) +{ + uint32_t result; + + __ASM volatile ("strex %0, %2, [%1]" : "=&r" (result) : "r" (addr), "r" (value) ); + return(result); +} + + +/** \brief Remove the exclusive lock + + This function removes the exclusive lock which is created by LDREX. + + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE void __CLREX(void) +{ + __ASM volatile ("clrex"); +} + + +/** \brief Signed Saturate + + This function saturates a signed value. + + \param [in] value Value to be saturated + \param [in] sat Bit position to saturate to (1..32) + \return Saturated value + */ +#define __SSAT(ARG1,ARG2) \ +({ \ + uint32_t __RES, __ARG1 = (ARG1); \ + __ASM ("ssat %0, %1, %2" : "=r" (__RES) : "I" (ARG2), "r" (__ARG1) ); \ + __RES; \ + }) + + +/** \brief Unsigned Saturate + + This function saturates an unsigned value. + + \param [in] value Value to be saturated + \param [in] sat Bit position to saturate to (0..31) + \return Saturated value + */ +#define __USAT(ARG1,ARG2) \ +({ \ + uint32_t __RES, __ARG1 = (ARG1); \ + __ASM ("usat %0, %1, %2" : "=r" (__RES) : "I" (ARG2), "r" (__ARG1) ); \ + __RES; \ + }) + + +/** \brief Count leading zeros + + This function counts the number of leading zeros of a data value. + + \param [in] value Value to count the leading zeros + \return number of leading zeros in value + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE uint8_t __CLZ(uint32_t value) +{ + uint8_t result; + + __ASM volatile ("clz %0, %1" : "=r" (result) : "r" (value) ); + return(result); +} + +#endif /* (__CORTEX_M >= 0x03) */ + + + + +#elif defined ( __TASKING__ ) /*------------------ TASKING Compiler --------------*/ +/* TASKING carm specific functions */ + +/* + * The CMSIS functions have been implemented as intrinsics in the compiler. + * Please use "carm -?i" to get an up to date list of all intrinsics, + * Including the CMSIS ones. + */ + +#endif + +/*@}*/ /* end of group CMSIS_Core_InstructionInterface */ + +#endif /* __CORE_CMINSTR_H */ diff --git a/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_standard_peripheral/Include/gd32f30x_adc.h b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_standard_peripheral/Include/gd32f30x_adc.h new file mode 100644 index 0000000000..7a778867dd --- /dev/null +++ b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_standard_peripheral/Include/gd32f30x_adc.h @@ -0,0 +1,403 @@ +/*! + \file gd32f30x_adc.h + \brief definitions for the ADC + + \version 2017-02-10, V1.0.0, firmware for GD32F30x + \version 2018-10-10, V1.1.0, firmware for GD32F30x + \version 2018-12-25, V2.0.0, firmware for GD32F30x + \version 2020-09-30, V2.1.0, firmware for GD32F30x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef GD32F30X_ADC_H +#define GD32F30X_ADC_H + +#include "gd32f30x.h" + +/* ADC definitions */ +#define ADC0 ADC_BASE +#define ADC1 (ADC_BASE + 0x400U) +#if (defined(GD32F30X_HD) || defined(GD32F30X_XD)) +#define ADC2 (ADC_BASE + 0x1800U) +#endif + +/* registers definitions */ +#define ADC_STAT(adcx) REG32((adcx) + 0x00U) /*!< ADC status register */ +#define ADC_CTL0(adcx) REG32((adcx) + 0x04U) /*!< ADC control register 0 */ +#define ADC_CTL1(adcx) REG32((adcx) + 0x08U) /*!< ADC control register 1 */ +#define ADC_SAMPT0(adcx) REG32((adcx) + 0x0CU) /*!< ADC sampling time register 0 */ +#define ADC_SAMPT1(adcx) REG32((adcx) + 0x10U) /*!< ADC sampling time register 1 */ +#define ADC_IOFF0(adcx) REG32((adcx) + 0x14U) /*!< ADC inserted channel data offset register 0 */ +#define ADC_IOFF1(adcx) REG32((adcx) + 0x18U) /*!< ADC inserted channel data offset register 1 */ +#define ADC_IOFF2(adcx) REG32((adcx) + 0x1CU) /*!< ADC inserted channel data offset register 2 */ +#define ADC_IOFF3(adcx) REG32((adcx) + 0x20U) /*!< ADC inserted channel data offset register 3 */ +#define ADC_WDHT(adcx) REG32((adcx) + 0x24U) /*!< ADC watchdog high threshold register */ +#define ADC_WDLT(adcx) REG32((adcx) + 0x28U) /*!< ADC watchdog low threshold register */ +#define ADC_RSQ0(adcx) REG32((adcx) + 0x2CU) /*!< ADC regular sequence register 0 */ +#define ADC_RSQ1(adcx) REG32((adcx) + 0x30U) /*!< ADC regular sequence register 1 */ +#define ADC_RSQ2(adcx) REG32((adcx) + 0x34U) /*!< ADC regular sequence register 2 */ +#define ADC_ISQ(adcx) REG32((adcx) + 0x38U) /*!< ADC inserted sequence register */ +#define ADC_IDATA0(adcx) REG32((adcx) + 0x3CU) /*!< ADC inserted data register 0 */ +#define ADC_IDATA1(adcx) REG32((adcx) + 0x40U) /*!< ADC inserted data register 1 */ +#define ADC_IDATA2(adcx) REG32((adcx) + 0x44U) /*!< ADC inserted data register 2 */ +#define ADC_IDATA3(adcx) REG32((adcx) + 0x48U) /*!< ADC inserted data register 3 */ +#define ADC_RDATA(adcx) REG32((adcx) + 0x4CU) /*!< ADC regular data register */ +#define ADC_OVSAMPCTL(adcx) REG32((adcx) + 0x80U) /*!< ADC oversampling control register */ + +/* bits definitions */ +/* ADC_STAT */ +#define ADC_STAT_WDE BIT(0) /*!< analog watchdog event flag */ +#define ADC_STAT_EOC BIT(1) /*!< end of conversion */ +#define ADC_STAT_EOIC BIT(2) /*!< inserted channel end of conversion */ +#define ADC_STAT_STIC BIT(3) /*!< inserted channel start flag */ +#define ADC_STAT_STRC BIT(4) /*!< regular channel start flag */ + +/* ADC_CTL0 */ +#define ADC_CTL0_WDCHSEL BITS(0,4) /*!< analog watchdog channel select bits */ +#define ADC_CTL0_EOCIE BIT(5) /*!< interrupt enable for EOC */ +#define ADC_CTL0_WDEIE BIT(6) /*!< analog watchdog interrupt enable */ +#define ADC_CTL0_EOICIE BIT(7) /*!< interrupt enable for inserted channels */ +#define ADC_CTL0_SM BIT(8) /*!< scan mode */ +#define ADC_CTL0_WDSC BIT(9) /*!< when in scan mode, analog watchdog is effective on a single channel */ +#define ADC_CTL0_ICA BIT(10) /*!< automatic inserted group conversion */ +#define ADC_CTL0_DISRC BIT(11) /*!< discontinuous mode on regular channels */ +#define ADC_CTL0_DISIC BIT(12) /*!< discontinuous mode on inserted channels */ +#define ADC_CTL0_DISNUM BITS(13,15) /*!< discontinuous mode channel count */ +#define ADC_CTL0_SYNCM BITS(16,19) /*!< sync mode selection */ +#define ADC_CTL0_IWDEN BIT(22) /*!< analog watchdog enable on inserted channels */ +#define ADC_CTL0_RWDEN BIT(23) /*!< analog watchdog enable on regular channels */ +#define ADC_CTL0_DRES BITS(24,25) /*!< ADC data resolution */ + +/* ADC_CTL1 */ +#define ADC_CTL1_ADCON BIT(0) /*!< ADC converter on */ +#define ADC_CTL1_CTN BIT(1) /*!< continuous conversion */ +#define ADC_CTL1_CLB BIT(2) /*!< ADC calibration */ +#define ADC_CTL1_RSTCLB BIT(3) /*!< reset calibration */ +#define ADC_CTL1_DMA BIT(8) /*!< direct memory access mode */ +#define ADC_CTL1_DAL BIT(11) /*!< data alignment */ +#define ADC_CTL1_ETSIC BITS(12,14) /*!< external trigger select for inserted channel */ +#define ADC_CTL1_ETEIC BIT(15) /*!< external trigger enable for inserted channel */ +#define ADC_CTL1_ETSRC BITS(17,19) /*!< external trigger select for regular channel */ +#define ADC_CTL1_ETERC BIT(20) /*!< external trigger conversion mode for inserted channels */ +#define ADC_CTL1_SWICST BIT(21) /*!< start on inserted channel */ +#define ADC_CTL1_SWRCST BIT(22) /*!< start on regular channel */ +#define ADC_CTL1_TSVREN BIT(23) /*!< channel 16 and 17 enable of ADC0 */ + +/* ADC_SAMPTx x=0..1 */ +#define ADC_SAMPTX_SPTN BITS(0,2) /*!< channel x sample time selection */ + +/* ADC_IOFFx x=0..3 */ +#define ADC_IOFFX_IOFF BITS(0,11) /*!< data offset for inserted channel x */ + +/* ADC_WDHT */ +#define ADC_WDHT_WDHT BITS(0,11) /*!< analog watchdog high threshold */ + +/* ADC_WDLT */ +#define ADC_WDLT_WDLT BITS(0,11) /*!< analog watchdog low threshold */ + +/* ADC_RSQx */ +#define ADC_RSQX_RSQN BITS(0,4) /*!< x conversion in regular sequence */ +#define ADC_RSQ0_RL BITS(20,23) /*!< regular channel sequence length */ + +/* ADC_ISQ */ +#define ADC_ISQ_ISQN BITS(0,4) /*!< x conversion in regular sequence */ +#define ADC_ISQ_IL BITS(20,21) /*!< inserted sequence length */ + +/* ADC_IDATAx x=0..3*/ +#define ADC_IDATAX_IDATAN BITS(0,15) /*!< inserted data x */ + +/* ADC_RDATA */ +#define ADC_RDATA_RDATA BITS(0,15) /*!< regular data */ +#define ADC_RDATA_ADC1RDTR BITS(16,31) /*!< ADC1 regular channel data */ + +/* ADC_OVSAMPCTL */ +#define ADC_OVSAMPCTL_OVSEN BIT(0) /*!< oversampling enable */ +#define ADC_OVSAMPCTL_OVSR BITS(2,4) /*!< oversampling ratio */ +#define ADC_OVSAMPCTL_OVSS BITS(5,8) /*!< oversampling shift */ +#define ADC_OVSAMPCTL_TOVS BIT(9) /*!< triggered oversampling */ +#define ADC_OVSAMPCTL_DRES BITS(12,13) /*!< oversampling shift */ + + +/* constants definitions */ +/* ADC status flag */ +#define ADC_FLAG_WDE ADC_STAT_WDE /*!< analog watchdog event flag */ +#define ADC_FLAG_EOC ADC_STAT_EOC /*!< end of conversion */ +#define ADC_FLAG_EOIC ADC_STAT_EOIC /*!< inserted channel end of conversion */ +#define ADC_FLAG_STIC ADC_STAT_STIC /*!< inserted channel start flag */ +#define ADC_FLAG_STRC ADC_STAT_STRC /*!< regular channel start flag */ + +/* adc_ctl0 register value */ +#define CTL0_DISNUM(regval) (BITS(13,15) & ((uint32_t)(regval) << 13)) /*!< write value to ADC_CTL0_DISNUM bit field */ + +/* ADC special function definitions */ +#define ADC_SCAN_MODE ADC_CTL0_SM /*!< scan mode */ +#define ADC_INSERTED_CHANNEL_AUTO ADC_CTL0_ICA /*!< inserted channel group convert automatically */ +#define ADC_CONTINUOUS_MODE ADC_CTL1_CTN /*!< continuous mode */ + +/* ADC synchronization mode */ +#define CTL0_SYNCM(regval) (BITS(16,19) & ((uint32_t)(regval) << 16)) /*!< write value to ADC_CTL0_SYNCM bit field */ +#define ADC_MODE_FREE CTL0_SYNCM(0) /*!< all the ADCs work independently */ +#define ADC_DAUL_REGULAL_PARALLEL_INSERTED_PARALLEL CTL0_SYNCM(1) /*!< ADC0 and ADC1 work in combined regular parallel + inserted parallel mode */ +#define ADC_DAUL_REGULAL_PARALLEL_INSERTED_ROTATION CTL0_SYNCM(2) /*!< ADC0 and ADC1 work in combined regular parallel + trigger rotation mode */ +#define ADC_DAUL_INSERTED_PARALLEL_REGULAL_FOLLOWUP_FAST CTL0_SYNCM(3) /*!< ADC0 and ADC1 work in combined inserted parallel + follow-up fast mode */ +#define ADC_DAUL_INSERTED_PARALLEL_REGULAL_FOLLOWUP_SLOW CTL0_SYNCM(4) /*!< ADC0 and ADC1 work in combined inserted parallel + follow-up slow mode */ +#define ADC_DAUL_INSERTED_PARALLEL CTL0_SYNCM(5) /*!< ADC0 and ADC1 work in inserted parallel mode only */ +#define ADC_DAUL_REGULAL_PARALLEL CTL0_SYNCM(6) /*!< ADC0 and ADC1 work in regular parallel mode only */ +#define ADC_DAUL_REGULAL_FOLLOWUP_FAST CTL0_SYNCM(7) /*!< ADC0 and ADC1 work in follow-up fast mode only */ +#define ADC_DAUL_REGULAL_FOLLOWUP_SLOW CTL0_SYNCM(8) /*!< ADC0 and ADC1 work in follow-up slow mode only */ +#define ADC_DAUL_INSERTED_TRRIGGER_ROTATION CTL0_SYNCM(9) /*!< ADC0 and ADC1 work in trigger rotation mode only */ + +/* ADC data alignment */ +#define ADC_DATAALIGN_RIGHT ((uint32_t)0x00000000U) /*!< LSB alignment */ +#define ADC_DATAALIGN_LEFT ADC_CTL1_DAL /*!< MSB alignment */ + +/* ADC external trigger select for regular channel */ +#define CTL1_ETSRC(regval) (BITS(17,19) & ((uint32_t)(regval) << 17)) /*!< write value to ADC_CTL1_ETSRC bit field */ +#define ADC0_1_EXTTRIG_REGULAR_T0_CH0 CTL1_ETSRC(0) /*!< timer 0 CC0 event select */ +#define ADC0_1_EXTTRIG_REGULAR_T0_CH1 CTL1_ETSRC(1) /*!< timer 0 CC1 event select */ +#define ADC0_1_EXTTRIG_REGULAR_T0_CH2 CTL1_ETSRC(2) /*!< timer 0 CC2 event select */ +#define ADC0_1_EXTTRIG_REGULAR_T1_CH1 CTL1_ETSRC(3) /*!< timer 1 CC1 event select */ +#define ADC0_1_EXTTRIG_REGULAR_T2_TRGO CTL1_ETSRC(4) /*!< timer 2 TRGO event select */ +#define ADC0_1_EXTTRIG_REGULAR_T3_CH3 CTL1_ETSRC(5) /*!< timer 3 CC3 event select */ +#define ADC0_1_EXTTRIG_REGULAR_T7_TRGO CTL1_ETSRC(6) /*!< timer 7 TRGO event select */ +#define ADC0_1_EXTTRIG_REGULAR_EXTI_11 CTL1_ETSRC(6) /*!< external interrupt line 11 */ +#define ADC0_1_2_EXTTRIG_REGULAR_NONE CTL1_ETSRC(7) /*!< software trigger */ + +#define ADC2_EXTTRIG_REGULAR_T2_CH0 CTL1_ETSRC(0) /*!< timer 2 CC0 event select */ +#define ADC2_EXTTRIG_REGULAR_T1_CH2 CTL1_ETSRC(1) /*!< timer 1 CC2 event select */ +#define ADC2_EXTTRIG_REGULAR_T0_CH2 CTL1_ETSRC(2) /*!< timer 0 CC2 event select */ +#define ADC2_EXTTRIG_REGULAR_T7_CH0 CTL1_ETSRC(3) /*!< timer 7 CC0 event select */ +#define ADC2_EXTTRIG_REGULAR_T7_TRGO CTL1_ETSRC(4) /*!< timer 7 TRGO event select */ +#define ADC2_EXTTRIG_REGULAR_T4_CH0 CTL1_ETSRC(5) /*!< timer 4 CC0 event select */ +#define ADC2_EXTTRIG_REGULAR_T4_CH2 CTL1_ETSRC(6) /*!< timer 4 CC2 event select */ + +/* ADC external trigger select for inserted channel */ +#define CTL1_ETSIC(regval) (BITS(12,14) & ((uint32_t)(regval) << 12)) /*!< write value to ADC_CTL1_ETSIC bit field */ +#define ADC0_1_EXTTRIG_INSERTED_T0_TRGO CTL1_ETSIC(0) /*!< timer 0 TRGO event select */ +#define ADC0_1_EXTTRIG_INSERTED_T0_CH3 CTL1_ETSIC(1) /*!< timer 0 CC3 event select */ +#define ADC0_1_EXTTRIG_INSERTED_T1_TRGO CTL1_ETSIC(2) /*!< timer 1 TRGO event select */ +#define ADC0_1_EXTTRIG_INSERTED_T1_CH0 CTL1_ETSIC(3) /*!< timer 1 CC0 event select */ +#define ADC0_1_EXTTRIG_INSERTED_T2_CH3 CTL1_ETSIC(4) /*!< timer 2 CC3 event select */ +#define ADC0_1_EXTTRIG_INSERTED_T3_TRGO CTL1_ETSIC(5) /*!< timer 3 TRGO event select */ +#define ADC0_1_EXTTRIG_INSERTED_EXTI_15 CTL1_ETSIC(6) /*!< external interrupt line 15 */ +#define ADC0_1_EXTTRIG_INSERTED_T7_CH3 CTL1_ETSIC(6) /*!< timer 7 CC3 event select */ +#define ADC0_1_2_EXTTRIG_INSERTED_NONE CTL1_ETSIC(7) /*!< software trigger */ + +#define ADC2_EXTTRIG_INSERTED_T0_TRGO CTL1_ETSIC(0) /*!< timer 0 TRGO event select */ +#define ADC2_EXTTRIG_INSERTED_T0_CH3 CTL1_ETSIC(1) /*!< timer 0 CC3 event select */ +#define ADC2_EXTTRIG_INSERTED_T3_CH2 CTL1_ETSIC(2) /*!< timer 3 CC2 event select */ +#define ADC2_EXTTRIG_INSERTED_T7_CH1 CTL1_ETSIC(3) /*!< timer 7 CC1 event select */ +#define ADC2_EXTTRIG_INSERTED_T7_CH3 CTL1_ETSIC(4) /*!< timer 7 CC3 event select */ +#define ADC2_EXTTRIG_INSERTED_T4_TRGO CTL1_ETSIC(5) /*!< timer 4 TRGO event select */ +#define ADC2_EXTTRIG_INSERTED_T4_CH3 CTL1_ETSIC(6) /*!< timer 4 CC3 event select */ + +/* ADC channel sample time */ +#define SAMPTX_SPT(regval) (BITS(0,2) & ((uint32_t)(regval) << 0)) /*!< write value to ADC_SAMPTX_SPT bit field */ +#define ADC_SAMPLETIME_1POINT5 SAMPTX_SPT(0) /*!< 1.5 sampling cycles */ +#define ADC_SAMPLETIME_7POINT5 SAMPTX_SPT(1) /*!< 7.5 sampling cycles */ +#define ADC_SAMPLETIME_13POINT5 SAMPTX_SPT(2) /*!< 13.5 sampling cycles */ +#define ADC_SAMPLETIME_28POINT5 SAMPTX_SPT(3) /*!< 28.5 sampling cycles */ +#define ADC_SAMPLETIME_41POINT5 SAMPTX_SPT(4) /*!< 41.5 sampling cycles */ +#define ADC_SAMPLETIME_55POINT5 SAMPTX_SPT(5) /*!< 55.5 sampling cycles */ +#define ADC_SAMPLETIME_71POINT5 SAMPTX_SPT(6) /*!< 71.5 sampling cycles */ +#define ADC_SAMPLETIME_239POINT5 SAMPTX_SPT(7) /*!< 239.5 sampling cycles */ + +/* adc_ioffx register value */ +#define IOFFX_IOFF(regval) (BITS(0,11) & ((uint32_t)(regval) << 0)) /*!< write value to ADC_IOFFX_IOFF bit field */ + +/* adc_wdht register value */ +#define WDHT_WDHT(regval) (BITS(0,11) & ((uint32_t)(regval) << 0)) /*!< write value to ADC_WDHT_WDHT bit field */ + +/* adc_wdlt register value */ +#define WDLT_WDLT(regval) (BITS(0,11) & ((uint32_t)(regval) << 0)) /*!< write value to ADC_WDLT_WDLT bit field */ + +/* adc_rsqx register value */ +#define RSQ0_RL(regval) (BITS(20,23) & ((uint32_t)(regval) << 20)) /*!< write value to ADC_RSQ0_RL bit field */ + +/* adc_isq register value */ +#define ISQ_IL(regval) (BITS(20,21) & ((uint32_t)(regval) << 20)) /*!< write value to ADC_ISQ_IL bit field */ + +/* adc_ovsampctl register value */ +/* ADC resolution */ +#define OVSAMPCTL_DRES(regval) (BITS(12,13) & ((uint32_t)(regval) << 12)) /*!< write value to ADC_OVSAMPCTL_DRES bit field */ +#define ADC_RESOLUTION_12B OVSAMPCTL_DRES(0) /*!< 12-bit ADC resolution */ +#define ADC_RESOLUTION_10B OVSAMPCTL_DRES(1) /*!< 10-bit ADC resolution */ +#define ADC_RESOLUTION_8B OVSAMPCTL_DRES(2) /*!< 8-bit ADC resolution */ +#define ADC_RESOLUTION_6B OVSAMPCTL_DRES(3) /*!< 6-bit ADC resolution */ + +/* oversampling shift */ +#define OVSAMPCTL_OVSS(regval) (BITS(5,8) & ((uint32_t)(regval) << 5)) /*!< write value to ADC_OVSAMPCTL_OVSS bit field */ +#define ADC_OVERSAMPLING_SHIFT_NONE OVSAMPCTL_OVSS(0) /*!< no oversampling shift */ +#define ADC_OVERSAMPLING_SHIFT_1B OVSAMPCTL_OVSS(1) /*!< 1-bit oversampling shift */ +#define ADC_OVERSAMPLING_SHIFT_2B OVSAMPCTL_OVSS(2) /*!< 2-bit oversampling shift */ +#define ADC_OVERSAMPLING_SHIFT_3B OVSAMPCTL_OVSS(3) /*!< 3-bit oversampling shift */ +#define ADC_OVERSAMPLING_SHIFT_4B OVSAMPCTL_OVSS(4) /*!< 4-bit oversampling shift */ +#define ADC_OVERSAMPLING_SHIFT_5B OVSAMPCTL_OVSS(5) /*!< 5-bit oversampling shift */ +#define ADC_OVERSAMPLING_SHIFT_6B OVSAMPCTL_OVSS(6) /*!< 6-bit oversampling shift */ +#define ADC_OVERSAMPLING_SHIFT_7B OVSAMPCTL_OVSS(7) /*!< 7-bit oversampling shift */ +#define ADC_OVERSAMPLING_SHIFT_8B OVSAMPCTL_OVSS(8) /*!< 8-bit oversampling shift */ + +/* oversampling ratio */ +#define OVSAMPCTL_OVSR(regval) (BITS(2,4) & ((uint32_t)(regval) << 2)) /*!< write value to ADC_OVSAMPCTL_OVSR bit field */ +#define ADC_OVERSAMPLING_RATIO_MUL2 OVSAMPCTL_OVSR(0) /*!< oversampling ratio multiple 2 */ +#define ADC_OVERSAMPLING_RATIO_MUL4 OVSAMPCTL_OVSR(1) /*!< oversampling ratio multiple 4 */ +#define ADC_OVERSAMPLING_RATIO_MUL8 OVSAMPCTL_OVSR(2) /*!< oversampling ratio multiple 8 */ +#define ADC_OVERSAMPLING_RATIO_MUL16 OVSAMPCTL_OVSR(3) /*!< oversampling ratio multiple 16 */ +#define ADC_OVERSAMPLING_RATIO_MUL32 OVSAMPCTL_OVSR(4) /*!< oversampling ratio multiple 32 */ +#define ADC_OVERSAMPLING_RATIO_MUL64 OVSAMPCTL_OVSR(5) /*!< oversampling ratio multiple 64 */ +#define ADC_OVERSAMPLING_RATIO_MUL128 OVSAMPCTL_OVSR(6) /*!< oversampling ratio multiple 128 */ +#define ADC_OVERSAMPLING_RATIO_MUL256 OVSAMPCTL_OVSR(7) /*!< oversampling ratio multiple 256 */ + +/* triggered oversampling */ +#define ADC_OVERSAMPLING_ALL_CONVERT ((uint32_t)0x00000000U) /*!< all oversampled conversions for a channel are done consecutively after a trigger */ +#define ADC_OVERSAMPLING_ONE_CONVERT ADC_OVSAMPCTL_TOVS /*!< each oversampled conversion for a channel needs a trigger */ + +/* ADC channel group definitions */ +#define ADC_REGULAR_CHANNEL ((uint8_t)0x01U) /*!< adc regular channel group */ +#define ADC_INSERTED_CHANNEL ((uint8_t)0x02U) /*!< adc inserted channel group */ +#define ADC_REGULAR_INSERTED_CHANNEL ((uint8_t)0x03U) /*!< both regular and inserted channel group */ + +#define ADC_CHANNEL_DISCON_DISABLE ((uint8_t)0x04U) /*!< disable discontinuous mode of regular & inserted channel */ + +/* ADC inserted channel definitions */ +#define ADC_INSERTED_CHANNEL_0 ((uint8_t)0x00U) /*!< adc inserted channel 0 */ +#define ADC_INSERTED_CHANNEL_1 ((uint8_t)0x01U) /*!< adc inserted channel 1 */ +#define ADC_INSERTED_CHANNEL_2 ((uint8_t)0x02U) /*!< adc inserted channel 2 */ +#define ADC_INSERTED_CHANNEL_3 ((uint8_t)0x03U) /*!< adc inserted channel 3 */ + +/* ADC channel definitions */ +#define ADC_CHANNEL_0 ((uint8_t)0x00U) /*!< ADC channel 0 */ +#define ADC_CHANNEL_1 ((uint8_t)0x01U) /*!< ADC channel 1 */ +#define ADC_CHANNEL_2 ((uint8_t)0x02U) /*!< ADC channel 2 */ +#define ADC_CHANNEL_3 ((uint8_t)0x03U) /*!< ADC channel 3 */ +#define ADC_CHANNEL_4 ((uint8_t)0x04U) /*!< ADC channel 4 */ +#define ADC_CHANNEL_5 ((uint8_t)0x05U) /*!< ADC channel 5 */ +#define ADC_CHANNEL_6 ((uint8_t)0x06U) /*!< ADC channel 6 */ +#define ADC_CHANNEL_7 ((uint8_t)0x07U) /*!< ADC channel 7 */ +#define ADC_CHANNEL_8 ((uint8_t)0x08U) /*!< ADC channel 8 */ +#define ADC_CHANNEL_9 ((uint8_t)0x09U) /*!< ADC channel 9 */ +#define ADC_CHANNEL_10 ((uint8_t)0x0AU) /*!< ADC channel 10 */ +#define ADC_CHANNEL_11 ((uint8_t)0x0BU) /*!< ADC channel 11 */ +#define ADC_CHANNEL_12 ((uint8_t)0x0CU) /*!< ADC channel 12 */ +#define ADC_CHANNEL_13 ((uint8_t)0x0DU) /*!< ADC channel 13 */ +#define ADC_CHANNEL_14 ((uint8_t)0x0EU) /*!< ADC channel 14 */ +#define ADC_CHANNEL_15 ((uint8_t)0x0FU) /*!< ADC channel 15 */ +#define ADC_CHANNEL_16 ((uint8_t)0x10U) /*!< ADC channel 16 */ +#define ADC_CHANNEL_17 ((uint8_t)0x11U) /*!< ADC channel 17 */ + +/* ADC interrupt */ +#define ADC_INT_WDE ADC_STAT_WDE /*!< analog watchdog event interrupt */ +#define ADC_INT_EOC ADC_STAT_EOC /*!< end of group conversion interrupt */ +#define ADC_INT_EOIC ADC_STAT_EOIC /*!< end of inserted group conversion interrupt */ + +/* ADC interrupt flag */ +#define ADC_INT_FLAG_WDE ADC_STAT_WDE /*!< analog watchdog event interrupt flag */ +#define ADC_INT_FLAG_EOC ADC_STAT_EOC /*!< end of group conversion interrupt flag */ +#define ADC_INT_FLAG_EOIC ADC_STAT_EOIC /*!< end of inserted group conversion interrupt flag */ + +/* function declarations */ +/* reset ADC */ +void adc_deinit(uint32_t adc_periph); +/* enable ADC interface */ +void adc_enable(uint32_t adc_periph); +/* disable ADC interface */ +void adc_disable(uint32_t adc_periph); +/* ADC calibration and reset calibration */ +void adc_calibration_enable(uint32_t adc_periph); +/* enable DMA request */ +void adc_dma_mode_enable(uint32_t adc_periph); +/* disable DMA request */ +void adc_dma_mode_disable(uint32_t adc_periph); +/* enable the temperature sensor and Vrefint channel */ +void adc_tempsensor_vrefint_enable(void); +/* disable the temperature sensor and Vrefint channel */ +void adc_tempsensor_vrefint_disable(void); + +/* configure ADC resolution */ +void adc_resolution_config(uint32_t adc_periph , uint32_t resolution); +/* configure ADC discontinuous mode */ +void adc_discontinuous_mode_config(uint32_t adc_periph , uint8_t adc_channel_group , uint8_t length); + +/* configure the ADC mode */ +void adc_mode_config(uint32_t mode); +/* enable or disable ADC special function */ +void adc_special_function_config(uint32_t adc_periph , uint32_t function , ControlStatus newvalue); +/* configure ADC data alignment */ +void adc_data_alignment_config(uint32_t adc_periph , uint32_t data_alignment); +/* configure the length of regular channel group or inserted channel group */ +void adc_channel_length_config(uint32_t adc_periph , uint8_t adc_channel_group , uint32_t length); +/* configure ADC regular channel */ +void adc_regular_channel_config(uint32_t adc_periph , uint8_t rank , uint8_t adc_channel , uint32_t sample_time); +/* configure ADC inserted channel */ +void adc_inserted_channel_config(uint32_t adc_periph , uint8_t rank , uint8_t adc_channel , uint32_t sample_time); +/* configure ADC inserted channel offset */ +void adc_inserted_channel_offset_config(uint32_t adc_periph , uint8_t inserted_channel , uint16_t offset); +/* enable ADC external trigger */ +void adc_external_trigger_config(uint32_t adc_periph, uint8_t adc_channel_group, ControlStatus newvalue); +/* configure ADC external trigger source */ +void adc_external_trigger_source_config(uint32_t adc_periph, uint8_t adc_channel_group, uint32_t external_trigger_source); +/* enable ADC software trigger */ +void adc_software_trigger_enable(uint32_t adc_periph , uint8_t adc_channel_group); + +/* read ADC regular group data register */ +uint16_t adc_regular_data_read(uint32_t adc_periph); +/* read ADC inserted group data register */ +uint16_t adc_inserted_data_read(uint32_t adc_periph , uint8_t inserted_channel); +/* read the last ADC0 and ADC1 conversion result data in sync mode */ +uint32_t adc_sync_mode_convert_value_read(void); + +/* get the ADC flag bits */ +FlagStatus adc_flag_get(uint32_t adc_periph , uint32_t adc_flag); +/* clear the ADC flag bits */ +void adc_flag_clear(uint32_t adc_periph , uint32_t adc_flag); +/* get the ADC interrupt bits */ +FlagStatus adc_interrupt_flag_get(uint32_t adc_periph , uint32_t adc_interrupt); +/* clear the ADC flag */ +void adc_interrupt_flag_clear(uint32_t adc_periph , uint32_t adc_interrupt); +/* enable ADC interrupt */ +void adc_interrupt_enable(uint32_t adc_periph , uint32_t adc_interrupt); +/* disable ADC interrupt */ +void adc_interrupt_disable(uint32_t adc_periph , uint32_t adc_interrupt); + +/* configure ADC analog watchdog single channel */ +void adc_watchdog_single_channel_enable(uint32_t adc_periph, uint8_t adc_channel); +/* configure ADC analog watchdog group channel */ +void adc_watchdog_group_channel_enable(uint32_t adc_periph, uint8_t adc_channel_group); +/* disable ADC analog watchdog */ +void adc_watchdog_disable(uint32_t adc_periph); +/* configure ADC analog watchdog threshold */ +void adc_watchdog_threshold_config(uint32_t adc_periph , uint16_t low_threshold , uint16_t high_threshold); + +/* configure ADC oversample mode */ +void adc_oversample_mode_config(uint32_t adc_periph , uint32_t mode , uint16_t shift , uint8_t ratio); +/* enable ADC oversample mode */ +void adc_oversample_mode_enable(uint32_t adc_periph); +/* disable ADC oversample mode */ +void adc_oversample_mode_disable(uint32_t adc_periph); +#endif /* GD32F30X_ADC_H */ diff --git a/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_standard_peripheral/Include/gd32f30x_bkp.h b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_standard_peripheral/Include/gd32f30x_bkp.h new file mode 100644 index 0000000000..31636783b3 --- /dev/null +++ b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_standard_peripheral/Include/gd32f30x_bkp.h @@ -0,0 +1,244 @@ +/*! + \file gd32f30x_bkp.h + \brief definitions for the BKP + + \version 2017-02-10, V1.0.0, firmware for GD32F30x + \version 2018-10-10, V1.1.0, firmware for GD32F30x + \version 2018-12-25, V2.0.0, firmware for GD32F30x + \version 2020-09-30, V2.1.0, firmware for GD32F30x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef GD32F30X_BKP_H +#define GD32F30X_BKP_H + +#include "gd32f30x.h" + +/* BKP definitions */ +#define BKP BKP_BASE /*!< BKP base address */ + +/* registers definitions */ +#define BKP_DATA0 REG16((BKP) + 0x04U) /*!< BKP data register 0 */ +#define BKP_DATA1 REG16((BKP) + 0x08U) /*!< BKP data register 1 */ +#define BKP_DATA2 REG16((BKP) + 0x0CU) /*!< BKP data register 2 */ +#define BKP_DATA3 REG16((BKP) + 0x10U) /*!< BKP data register 3 */ +#define BKP_DATA4 REG16((BKP) + 0x14U) /*!< BKP data register 4 */ +#define BKP_DATA5 REG16((BKP) + 0x18U) /*!< BKP data register 5 */ +#define BKP_DATA6 REG16((BKP) + 0x1CU) /*!< BKP data register 6 */ +#define BKP_DATA7 REG16((BKP) + 0x20U) /*!< BKP data register 7 */ +#define BKP_DATA8 REG16((BKP) + 0x24U) /*!< BKP data register 8 */ +#define BKP_DATA9 REG16((BKP) + 0x28U) /*!< BKP data register 9 */ +#define BKP_DATA10 REG16((BKP) + 0x40U) /*!< BKP data register 10 */ +#define BKP_DATA11 REG16((BKP) + 0x44U) /*!< BKP data register 11 */ +#define BKP_DATA12 REG16((BKP) + 0x48U) /*!< BKP data register 12 */ +#define BKP_DATA13 REG16((BKP) + 0x4CU) /*!< BKP data register 13 */ +#define BKP_DATA14 REG16((BKP) + 0x50U) /*!< BKP data register 14 */ +#define BKP_DATA15 REG16((BKP) + 0x54U) /*!< BKP data register 15 */ +#define BKP_DATA16 REG16((BKP) + 0x58U) /*!< BKP data register 16 */ +#define BKP_DATA17 REG16((BKP) + 0x5CU) /*!< BKP data register 17 */ +#define BKP_DATA18 REG16((BKP) + 0x60U) /*!< BKP data register 18 */ +#define BKP_DATA19 REG16((BKP) + 0x64U) /*!< BKP data register 19 */ +#define BKP_DATA20 REG16((BKP) + 0x68U) /*!< BKP data register 20 */ +#define BKP_DATA21 REG16((BKP) + 0x6CU) /*!< BKP data register 21 */ +#define BKP_DATA22 REG16((BKP) + 0x70U) /*!< BKP data register 22 */ +#define BKP_DATA23 REG16((BKP) + 0x74U) /*!< BKP data register 23 */ +#define BKP_DATA24 REG16((BKP) + 0x78U) /*!< BKP data register 24 */ +#define BKP_DATA25 REG16((BKP) + 0x7CU) /*!< BKP data register 25 */ +#define BKP_DATA26 REG16((BKP) + 0x80U) /*!< BKP data register 26 */ +#define BKP_DATA27 REG16((BKP) + 0x84U) /*!< BKP data register 27 */ +#define BKP_DATA28 REG16((BKP) + 0x88U) /*!< BKP data register 28 */ +#define BKP_DATA29 REG16((BKP) + 0x8CU) /*!< BKP data register 29 */ +#define BKP_DATA30 REG16((BKP) + 0x90U) /*!< BKP data register 30 */ +#define BKP_DATA31 REG16((BKP) + 0x94U) /*!< BKP data register 31 */ +#define BKP_DATA32 REG16((BKP) + 0x98U) /*!< BKP data register 32 */ +#define BKP_DATA33 REG16((BKP) + 0x9CU) /*!< BKP data register 33 */ +#define BKP_DATA34 REG16((BKP) + 0xA0U) /*!< BKP data register 34 */ +#define BKP_DATA35 REG16((BKP) + 0xA4U) /*!< BKP data register 35 */ +#define BKP_DATA36 REG16((BKP) + 0xA8U) /*!< BKP data register 36 */ +#define BKP_DATA37 REG16((BKP) + 0xACU) /*!< BKP data register 37 */ +#define BKP_DATA38 REG16((BKP) + 0xB0U) /*!< BKP data register 38 */ +#define BKP_DATA39 REG16((BKP) + 0xB4U) /*!< BKP data register 39 */ +#define BKP_DATA40 REG16((BKP) + 0xB8U) /*!< BKP data register 40 */ +#define BKP_DATA41 REG16((BKP) + 0xBCU) /*!< BKP data register 41 */ +#define BKP_OCTL REG16((BKP) + 0x2CU) /*!< RTC signal output control register */ +#define BKP_TPCTL REG16((BKP) + 0x30U) /*!< tamper pin control register */ +#define BKP_TPCS REG16((BKP) + 0x34U) /*!< tamper control and status register */ + +/* bits definitions */ +/* BKP_DATA */ +#define BKP_DATA BITS(0,15) /*!< backup data */ + +/* BKP_OCTL */ +#define BKP_OCTL_RCCV BITS(0,6) /*!< RTC clock calibration value */ +#define BKP_OCTL_COEN BIT(7) /*!< RTC clock calibration output enable */ +#define BKP_OCTL_ASOEN BIT(8) /*!< RTC alarm or second signal output enable */ +#define BKP_OCTL_ROSEL BIT(9) /*!< RTC output selection */ +#define BKP_OCTL_CCOSEL BIT(14) /*!< RTC clock output selection */ +#define BKP_OCTL_CALDIR BIT(15) /*!< RTC clock calibration direction */ + +/* BKP_TPCTL */ +#define BKP_TPCTL_TPEN BIT(0) /*!< tamper detection enable */ +#define BKP_TPCTL_TPAL BIT(1) /*!< tamper pin active level */ + +/* BKP_TPCS */ +#define BKP_TPCS_TER BIT(0) /*!< tamper event reset */ +#define BKP_TPCS_TIR BIT(1) /*!< tamper interrupt reset */ +#define BKP_TPCS_TPIE BIT(2) /*!< tamper interrupt enable */ +#define BKP_TPCS_TEF BIT(8) /*!< tamper event flag */ +#define BKP_TPCS_TIF BIT(9) /*!< tamper interrupt flag */ + +/* constants definitions */ +/* BKP register */ +#define BKP_DATA0_9(number) REG16((BKP) + 0x04U + (number) * 0x04U) +#define BKP_DATA10_41(number) REG16((BKP) + 0x40U + ((number)-10U) * 0x04U) + +/* get data of BKP data register */ +#define BKP_DATA_GET(regval) GET_BITS((uint32_t)(regval), 0, 15) + +/* RTC clock calibration value */ +#define OCTL_RCCV(regval) (BITS(0,6) & ((uint32_t)(regval) << 0)) + +/* RTC output selection */ +#define RTC_OUTPUT_ALARM_PULSE ((uint16_t)0x0000U) /*!< RTC alarm pulse is selected as the RTC output */ +#define RTC_OUTPUT_SECOND_PULSE ((uint16_t)0x0200U) /*!< RTC second pulse is selected as the RTC output */ + +/* RTC clock output selection */ +#define RTC_CLOCK_DIV_64 ((uint16_t)0x0000U) /*!< RTC clock div 64 */ +#define RTC_CLOCK_DIV_1 ((uint16_t)0x4000U) /*!< RTC clock div 1 */ + +/* RTC clock calibration direction */ +#define RTC_CLOCK_SLOWED_DOWN ((uint16_t)0x0000U) /*!< RTC clock slow down */ +#define RTC_CLOCK_SPEED_UP ((uint16_t)0x8000U) /*!< RTC clock speed up */ + +/* tamper pin active level */ +#define TAMPER_PIN_ACTIVE_HIGH ((uint16_t)0x0000U) /*!< the tamper pin is active high */ +#define TAMPER_PIN_ACTIVE_LOW ((uint16_t)0x0002U) /*!< the tamper pin is active low */ + +/* tamper flag */ +#define BKP_FLAG_TAMPER BKP_TPCS_TEF /*!< tamper event flag */ + +/* tamper interrupt flag */ +#define BKP_INT_FLAG_TAMPER BKP_TPCS_TIF /*!< tamper interrupt flag */ + +/* BKP data register number */ +typedef enum +{ + BKP_DATA_0 = 1, /*!< BKP data register 0 */ + BKP_DATA_1, /*!< BKP data register 1 */ + BKP_DATA_2, /*!< BKP data register 2 */ + BKP_DATA_3, /*!< BKP data register 3 */ + BKP_DATA_4, /*!< BKP data register 4 */ + BKP_DATA_5, /*!< BKP data register 5 */ + BKP_DATA_6, /*!< BKP data register 6 */ + BKP_DATA_7, /*!< BKP data register 7 */ + BKP_DATA_8, /*!< BKP data register 8 */ + BKP_DATA_9, /*!< BKP data register 9 */ + BKP_DATA_10, /*!< BKP data register 10 */ + BKP_DATA_11, /*!< BKP data register 11 */ + BKP_DATA_12, /*!< BKP data register 12 */ + BKP_DATA_13, /*!< BKP data register 13 */ + BKP_DATA_14, /*!< BKP data register 14 */ + BKP_DATA_15, /*!< BKP data register 15 */ + BKP_DATA_16, /*!< BKP data register 16 */ + BKP_DATA_17, /*!< BKP data register 17 */ + BKP_DATA_18, /*!< BKP data register 18 */ + BKP_DATA_19, /*!< BKP data register 19 */ + BKP_DATA_20, /*!< BKP data register 20 */ + BKP_DATA_21, /*!< BKP data register 21 */ + BKP_DATA_22, /*!< BKP data register 22 */ + BKP_DATA_23, /*!< BKP data register 23 */ + BKP_DATA_24, /*!< BKP data register 24 */ + BKP_DATA_25, /*!< BKP data register 25 */ + BKP_DATA_26, /*!< BKP data register 26 */ + BKP_DATA_27, /*!< BKP data register 27 */ + BKP_DATA_28, /*!< BKP data register 28 */ + BKP_DATA_29, /*!< BKP data register 29 */ + BKP_DATA_30, /*!< BKP data register 30 */ + BKP_DATA_31, /*!< BKP data register 31 */ + BKP_DATA_32, /*!< BKP data register 32 */ + BKP_DATA_33, /*!< BKP data register 33 */ + BKP_DATA_34, /*!< BKP data register 34 */ + BKP_DATA_35, /*!< BKP data register 35 */ + BKP_DATA_36, /*!< BKP data register 36 */ + BKP_DATA_37, /*!< BKP data register 37 */ + BKP_DATA_38, /*!< BKP data register 38 */ + BKP_DATA_39, /*!< BKP data register 39 */ + BKP_DATA_40, /*!< BKP data register 40 */ + BKP_DATA_41, /*!< BKP data register 41 */ +}bkp_data_register_enum; + +/* function declarations */ +/* reset BKP registers */ +void bkp_deinit(void); +/* write BKP data register */ +void bkp_write_data(bkp_data_register_enum register_number, uint16_t data); +/* read BKP data register */ +uint16_t bkp_read_data(bkp_data_register_enum register_number); + +/* RTC related functions */ +/* enable RTC clock calibration output */ +void bkp_rtc_calibration_output_enable(void); +/* disable RTC clock calibration output */ +void bkp_rtc_calibration_output_disable(void); +/* enable RTC alarm or second signal output */ +void bkp_rtc_signal_output_enable(void); +/* disable RTC alarm or second signal output */ +void bkp_rtc_signal_output_disable(void); +/* RTC output selection */ +void bkp_rtc_output_select(uint16_t outputsel); +/* RTC clock output selection */ +void bkp_rtc_clock_output_select(uint16_t clocksel); +/* RTC clock calibration direction */ +void bkp_rtc_clock_calibration_direction(uint16_t direction); +/* set RTC clock calibration value */ +void bkp_rtc_calibration_value_set(uint8_t value); + +/* tamper pin related functions */ +/* enable tamper pin detection */ +void bkp_tamper_detection_enable(void); +/* disable tamper pin detection */ +void bkp_tamper_detection_disable(void); +/* set tamper pin active level */ +void bkp_tamper_active_level_set(uint16_t level); +/* enable tamper pin interrupt */ +void bkp_tamper_interrupt_enable(void); +/* disable tamper pin interrupt */ +void bkp_tamper_interrupt_disable(void); + +/* flag functions */ +/* get BKP flag state */ +FlagStatus bkp_flag_get(uint16_t flag); +/* clear BKP flag state */ +void bkp_flag_clear(uint16_t flag); +/* get BKP interrupt flag state */ +FlagStatus bkp_interrupt_flag_get(uint16_t flag); +/* clear BKP interrupt flag state */ +void bkp_interrupt_flag_clear(uint16_t flag); + +#endif /* GD32F30X_BKP_H */ diff --git a/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_standard_peripheral/Include/gd32f30x_can.h b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_standard_peripheral/Include/gd32f30x_can.h new file mode 100644 index 0000000000..c3953d1293 --- /dev/null +++ b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_standard_peripheral/Include/gd32f30x_can.h @@ -0,0 +1,754 @@ +/*! + \file gd32f30x_can.h + \brief definitions for the CAN + + \version 2017-02-10, V1.0.0, firmware for GD32F30x + \version 2018-10-10, V1.1.0, firmware for GD32F30x + \version 2018-12-25, V2.0.0, firmware for GD32F30x + \version 2019-11-27, V2.0.1, firmware for GD32F30x + \version 2020-09-30, V2.1.0, firmware for GD32F30x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef GD32F30X_CAN_H +#define GD32F30X_CAN_H + +#include "gd32f30x.h" + +/* CAN definitions */ +#define CAN0 CAN_BASE /*!< CAN0 base address */ +#define CAN1 (CAN0 + 0x00000400U) /*!< CAN1 base address */ + +/* registers definitions */ +#define CAN_CTL(canx) REG32((canx) + 0x00U) /*!< CAN control register */ +#define CAN_STAT(canx) REG32((canx) + 0x04U) /*!< CAN status register */ +#define CAN_TSTAT(canx) REG32((canx) + 0x08U) /*!< CAN transmit status register*/ +#define CAN_RFIFO0(canx) REG32((canx) + 0x0CU) /*!< CAN receive FIFO0 register */ +#define CAN_RFIFO1(canx) REG32((canx) + 0x10U) /*!< CAN receive FIFO1 register */ +#define CAN_INTEN(canx) REG32((canx) + 0x14U) /*!< CAN interrupt enable register */ +#define CAN_ERR(canx) REG32((canx) + 0x18U) /*!< CAN error register */ +#define CAN_BT(canx) REG32((canx) + 0x1CU) /*!< CAN bit timing register */ +#define CAN_TMI0(canx) REG32((canx) + 0x180U) /*!< CAN transmit mailbox0 identifier register */ +#define CAN_TMP0(canx) REG32((canx) + 0x184U) /*!< CAN transmit mailbox0 property register */ +#define CAN_TMDATA00(canx) REG32((canx) + 0x188U) /*!< CAN transmit mailbox0 data0 register */ +#define CAN_TMDATA10(canx) REG32((canx) + 0x18CU) /*!< CAN transmit mailbox0 data1 register */ +#define CAN_TMI1(canx) REG32((canx) + 0x190U) /*!< CAN transmit mailbox1 identifier register */ +#define CAN_TMP1(canx) REG32((canx) + 0x194U) /*!< CAN transmit mailbox1 property register */ +#define CAN_TMDATA01(canx) REG32((canx) + 0x198U) /*!< CAN transmit mailbox1 data0 register */ +#define CAN_TMDATA11(canx) REG32((canx) + 0x19CU) /*!< CAN transmit mailbox1 data1 register */ +#define CAN_TMI2(canx) REG32((canx) + 0x1A0U) /*!< CAN transmit mailbox2 identifier register */ +#define CAN_TMP2(canx) REG32((canx) + 0x1A4U) /*!< CAN transmit mailbox2 property register */ +#define CAN_TMDATA02(canx) REG32((canx) + 0x1A8U) /*!< CAN transmit mailbox2 data0 register */ +#define CAN_TMDATA12(canx) REG32((canx) + 0x1ACU) /*!< CAN transmit mailbox2 data1 register */ +#define CAN_RFIFOMI0(canx) REG32((canx) + 0x1B0U) /*!< CAN receive FIFO0 mailbox identifier register */ +#define CAN_RFIFOMP0(canx) REG32((canx) + 0x1B4U) /*!< CAN receive FIFO0 mailbox property register */ +#define CAN_RFIFOMDATA00(canx) REG32((canx) + 0x1B8U) /*!< CAN receive FIFO0 mailbox data0 register */ +#define CAN_RFIFOMDATA10(canx) REG32((canx) + 0x1BCU) /*!< CAN receive FIFO0 mailbox data1 register */ +#define CAN_RFIFOMI1(canx) REG32((canx) + 0x1C0U) /*!< CAN receive FIFO1 mailbox identifier register */ +#define CAN_RFIFOMP1(canx) REG32((canx) + 0x1C4U) /*!< CAN receive FIFO1 mailbox property register */ +#define CAN_RFIFOMDATA01(canx) REG32((canx) + 0x1C8U) /*!< CAN receive FIFO1 mailbox data0 register */ +#define CAN_RFIFOMDATA11(canx) REG32((canx) + 0x1CCU) /*!< CAN receive FIFO1 mailbox data1 register */ +#define CAN_FCTL(canx) REG32((canx) + 0x200U) /*!< CAN filter control register */ +#define CAN_FMCFG(canx) REG32((canx) + 0x204U) /*!< CAN filter mode register */ +#define CAN_FSCFG(canx) REG32((canx) + 0x20CU) /*!< CAN filter scale register */ +#define CAN_FAFIFO(canx) REG32((canx) + 0x214U) /*!< CAN filter associated FIFO register */ +#define CAN_FW(canx) REG32((canx) + 0x21CU) /*!< CAN filter working register */ +#define CAN_F0DATA0(canx) REG32((canx) + 0x240U) /*!< CAN filter 0 data 0 register */ +#define CAN_F1DATA0(canx) REG32((canx) + 0x248U) /*!< CAN filter 1 data 0 register */ +#define CAN_F2DATA0(canx) REG32((canx) + 0x250U) /*!< CAN filter 2 data 0 register */ +#define CAN_F3DATA0(canx) REG32((canx) + 0x258U) /*!< CAN filter 3 data 0 register */ +#define CAN_F4DATA0(canx) REG32((canx) + 0x260U) /*!< CAN filter 4 data 0 register */ +#define CAN_F5DATA0(canx) REG32((canx) + 0x268U) /*!< CAN filter 5 data 0 register */ +#define CAN_F6DATA0(canx) REG32((canx) + 0x270U) /*!< CAN filter 6 data 0 register */ +#define CAN_F7DATA0(canx) REG32((canx) + 0x278U) /*!< CAN filter 7 data 0 register */ +#define CAN_F8DATA0(canx) REG32((canx) + 0x280U) /*!< CAN filter 8 data 0 register */ +#define CAN_F9DATA0(canx) REG32((canx) + 0x288U) /*!< CAN filter 9 data 0 register */ +#define CAN_F10DATA0(canx) REG32((canx) + 0x290U) /*!< CAN filter 10 data 0 register */ +#define CAN_F11DATA0(canx) REG32((canx) + 0x298U) /*!< CAN filter 11 data 0 register */ +#define CAN_F12DATA0(canx) REG32((canx) + 0x2A0U) /*!< CAN filter 12 data 0 register */ +#define CAN_F13DATA0(canx) REG32((canx) + 0x2A8U) /*!< CAN filter 13 data 0 register */ +#define CAN_F14DATA0(canx) REG32((canx) + 0x2B0U) /*!< CAN filter 14 data 0 register */ +#define CAN_F15DATA0(canx) REG32((canx) + 0x2B8U) /*!< CAN filter 15 data 0 register */ +#define CAN_F16DATA0(canx) REG32((canx) + 0x2C0U) /*!< CAN filter 16 data 0 register */ +#define CAN_F17DATA0(canx) REG32((canx) + 0x2C8U) /*!< CAN filter 17 data 0 register */ +#define CAN_F18DATA0(canx) REG32((canx) + 0x2D0U) /*!< CAN filter 18 data 0 register */ +#define CAN_F19DATA0(canx) REG32((canx) + 0x2D8U) /*!< CAN filter 19 data 0 register */ +#define CAN_F20DATA0(canx) REG32((canx) + 0x2E0U) /*!< CAN filter 20 data 0 register */ +#define CAN_F21DATA0(canx) REG32((canx) + 0x2E8U) /*!< CAN filter 21 data 0 register */ +#define CAN_F22DATA0(canx) REG32((canx) + 0x2F0U) /*!< CAN filter 22 data 0 register */ +#define CAN_F23DATA0(canx) REG32((canx) + 0x3F8U) /*!< CAN filter 23 data 0 register */ +#define CAN_F24DATA0(canx) REG32((canx) + 0x300U) /*!< CAN filter 24 data 0 register */ +#define CAN_F25DATA0(canx) REG32((canx) + 0x308U) /*!< CAN filter 25 data 0 register */ +#define CAN_F26DATA0(canx) REG32((canx) + 0x310U) /*!< CAN filter 26 data 0 register */ +#define CAN_F27DATA0(canx) REG32((canx) + 0x318U) /*!< CAN filter 27 data 0 register */ +#define CAN_F0DATA1(canx) REG32((canx) + 0x244U) /*!< CAN filter 0 data 1 register */ +#define CAN_F1DATA1(canx) REG32((canx) + 0x24CU) /*!< CAN filter 1 data 1 register */ +#define CAN_F2DATA1(canx) REG32((canx) + 0x254U) /*!< CAN filter 2 data 1 register */ +#define CAN_F3DATA1(canx) REG32((canx) + 0x25CU) /*!< CAN filter 3 data 1 register */ +#define CAN_F4DATA1(canx) REG32((canx) + 0x264U) /*!< CAN filter 4 data 1 register */ +#define CAN_F5DATA1(canx) REG32((canx) + 0x26CU) /*!< CAN filter 5 data 1 register */ +#define CAN_F6DATA1(canx) REG32((canx) + 0x274U) /*!< CAN filter 6 data 1 register */ +#define CAN_F7DATA1(canx) REG32((canx) + 0x27CU) /*!< CAN filter 7 data 1 register */ +#define CAN_F8DATA1(canx) REG32((canx) + 0x284U) /*!< CAN filter 8 data 1 register */ +#define CAN_F9DATA1(canx) REG32((canx) + 0x28CU) /*!< CAN filter 9 data 1 register */ +#define CAN_F10DATA1(canx) REG32((canx) + 0x294U) /*!< CAN filter 10 data 1 register */ +#define CAN_F11DATA1(canx) REG32((canx) + 0x29CU) /*!< CAN filter 11 data 1 register */ +#define CAN_F12DATA1(canx) REG32((canx) + 0x2A4U) /*!< CAN filter 12 data 1 register */ +#define CAN_F13DATA1(canx) REG32((canx) + 0x2ACU) /*!< CAN filter 13 data 1 register */ +#define CAN_F14DATA1(canx) REG32((canx) + 0x2B4U) /*!< CAN filter 14 data 1 register */ +#define CAN_F15DATA1(canx) REG32((canx) + 0x2BCU) /*!< CAN filter 15 data 1 register */ +#define CAN_F16DATA1(canx) REG32((canx) + 0x2C4U) /*!< CAN filter 16 data 1 register */ +#define CAN_F17DATA1(canx) REG32((canx) + 0x24CU) /*!< CAN filter 17 data 1 register */ +#define CAN_F18DATA1(canx) REG32((canx) + 0x2D4U) /*!< CAN filter 18 data 1 register */ +#define CAN_F19DATA1(canx) REG32((canx) + 0x2DCU) /*!< CAN filter 19 data 1 register */ +#define CAN_F20DATA1(canx) REG32((canx) + 0x2E4U) /*!< CAN filter 20 data 1 register */ +#define CAN_F21DATA1(canx) REG32((canx) + 0x2ECU) /*!< CAN filter 21 data 1 register */ +#define CAN_F22DATA1(canx) REG32((canx) + 0x2F4U) /*!< CAN filter 22 data 1 register */ +#define CAN_F23DATA1(canx) REG32((canx) + 0x2FCU) /*!< CAN filter 23 data 1 register */ +#define CAN_F24DATA1(canx) REG32((canx) + 0x304U) /*!< CAN filter 24 data 1 register */ +#define CAN_F25DATA1(canx) REG32((canx) + 0x30CU) /*!< CAN filter 25 data 1 register */ +#define CAN_F26DATA1(canx) REG32((canx) + 0x314U) /*!< CAN filter 26 data 1 register */ +#define CAN_F27DATA1(canx) REG32((canx) + 0x31CU) /*!< CAN filter 27 data 1 register */ + +/* CAN transmit mailbox bank */ +#define CAN_TMI(canx, bank) REG32((canx) + 0x180U + ((bank) * 0x10U)) /*!< CAN transmit mailbox identifier register */ +#define CAN_TMP(canx, bank) REG32((canx) + 0x184U + ((bank) * 0x10U)) /*!< CAN transmit mailbox property register */ +#define CAN_TMDATA0(canx, bank) REG32((canx) + 0x188U + ((bank) * 0x10U)) /*!< CAN transmit mailbox data0 register */ +#define CAN_TMDATA1(canx, bank) REG32((canx) + 0x18CU + ((bank) * 0x10U)) /*!< CAN transmit mailbox data1 register */ + +/* CAN filter bank */ +#define CAN_FDATA0(canx, bank) REG32((canx) + 0x240U + ((bank) * 0x8U) + 0x0U) /*!< CAN filter data 0 register */ +#define CAN_FDATA1(canx, bank) REG32((canx) + 0x240U + ((bank) * 0x8U) + 0x4U) /*!< CAN filter data 1 register */ + +/* CAN receive fifo mailbox bank */ +#define CAN_RFIFOMI(canx, bank) REG32((canx) + 0x1B0U + ((bank) * 0x10U)) /*!< CAN receive FIFO mailbox identifier register */ +#define CAN_RFIFOMP(canx, bank) REG32((canx) + 0x1B4U + ((bank) * 0x10U)) /*!< CAN receive FIFO mailbox property register */ +#define CAN_RFIFOMDATA0(canx, bank) REG32((canx) + 0x1B8U + ((bank) * 0x10U)) /*!< CAN receive FIFO mailbox data0 register */ +#define CAN_RFIFOMDATA1(canx, bank) REG32((canx) + 0x1BCU + ((bank) * 0x10U)) /*!< CAN receive FIFO mailbox data1 register */ + +/* bits definitions */ +/* CAN_CTL */ +#define CAN_CTL_IWMOD BIT(0) /*!< initial working mode */ +#define CAN_CTL_SLPWMOD BIT(1) /*!< sleep working mode */ +#define CAN_CTL_TFO BIT(2) /*!< transmit FIFO order */ +#define CAN_CTL_RFOD BIT(3) /*!< receive FIFO overwrite disable */ +#define CAN_CTL_ARD BIT(4) /*!< automatic retransmission disable */ +#define CAN_CTL_AWU BIT(5) /*!< automatic wakeup */ +#define CAN_CTL_ABOR BIT(6) /*!< automatic bus-off recovery */ +#define CAN_CTL_TTC BIT(7) /*!< time triggered communication */ +#define CAN_CTL_SWRST BIT(15) /*!< CAN software reset */ +#define CAN_CTL_DFZ BIT(16) /*!< CAN debug freeze */ + +/* CAN_STAT */ +#define CAN_STAT_IWS BIT(0) /*!< initial working state */ +#define CAN_STAT_SLPWS BIT(1) /*!< sleep working state */ +#define CAN_STAT_ERRIF BIT(2) /*!< error interrupt flag*/ +#define CAN_STAT_WUIF BIT(3) /*!< status change interrupt flag of wakeup from sleep working mode */ +#define CAN_STAT_SLPIF BIT(4) /*!< status change interrupt flag of sleep working mode entering */ +#define CAN_STAT_TS BIT(8) /*!< transmitting state */ +#define CAN_STAT_RS BIT(9) /*!< receiving state */ +#define CAN_STAT_LASTRX BIT(10) /*!< last sample value of rx pin */ +#define CAN_STAT_RXL BIT(11) /*!< CAN rx signal */ + +/* CAN_TSTAT */ +#define CAN_TSTAT_MTF0 BIT(0) /*!< mailbox0 transmit finished */ +#define CAN_TSTAT_MTFNERR0 BIT(1) /*!< mailbox0 transmit finished and no error */ +#define CAN_TSTAT_MAL0 BIT(2) /*!< mailbox0 arbitration lost */ +#define CAN_TSTAT_MTE0 BIT(3) /*!< mailbox0 transmit error */ +#define CAN_TSTAT_MST0 BIT(7) /*!< mailbox0 stop transmitting */ +#define CAN_TSTAT_MTF1 BIT(8) /*!< mailbox1 transmit finished */ +#define CAN_TSTAT_MTFNERR1 BIT(9) /*!< mailbox1 transmit finished and no error */ +#define CAN_TSTAT_MAL1 BIT(10) /*!< mailbox1 arbitration lost */ +#define CAN_TSTAT_MTE1 BIT(11) /*!< mailbox1 transmit error */ +#define CAN_TSTAT_MST1 BIT(15) /*!< mailbox1 stop transmitting */ +#define CAN_TSTAT_MTF2 BIT(16) /*!< mailbox2 transmit finished */ +#define CAN_TSTAT_MTFNERR2 BIT(17) /*!< mailbox2 transmit finished and no error */ +#define CAN_TSTAT_MAL2 BIT(18) /*!< mailbox2 arbitration lost */ +#define CAN_TSTAT_MTE2 BIT(19) /*!< mailbox2 transmit error */ +#define CAN_TSTAT_MST2 BIT(23) /*!< mailbox2 stop transmitting */ +#define CAN_TSTAT_NUM BITS(24,25) /*!< mailbox number */ +#define CAN_TSTAT_TME0 BIT(26) /*!< transmit mailbox0 empty */ +#define CAN_TSTAT_TME1 BIT(27) /*!< transmit mailbox1 empty */ +#define CAN_TSTAT_TME2 BIT(28) /*!< transmit mailbox2 empty */ +#define CAN_TSTAT_TMLS0 BIT(29) /*!< last sending priority flag for mailbox0 */ +#define CAN_TSTAT_TMLS1 BIT(30) /*!< last sending priority flag for mailbox1 */ +#define CAN_TSTAT_TMLS2 BIT(31) /*!< last sending priority flag for mailbox2 */ + +/* CAN_RFIFO0 */ +#define CAN_RFIFO0_RFL0 BITS(0,1) /*!< receive FIFO0 length */ +#define CAN_RFIFO0_RFF0 BIT(3) /*!< receive FIFO0 full */ +#define CAN_RFIFO0_RFO0 BIT(4) /*!< receive FIFO0 overfull */ +#define CAN_RFIFO0_RFD0 BIT(5) /*!< receive FIFO0 dequeue */ + +/* CAN_RFIFO1 */ +#define CAN_RFIFO1_RFL1 BITS(0,1) /*!< receive FIFO1 length */ +#define CAN_RFIFO1_RFF1 BIT(3) /*!< receive FIFO1 full */ +#define CAN_RFIFO1_RFO1 BIT(4) /*!< receive FIFO1 overfull */ +#define CAN_RFIFO1_RFD1 BIT(5) /*!< receive FIFO1 dequeue */ + +/* CAN_INTEN */ +#define CAN_INTEN_TMEIE BIT(0) /*!< transmit mailbox empty interrupt enable */ +#define CAN_INTEN_RFNEIE0 BIT(1) /*!< receive FIFO0 not empty interrupt enable */ +#define CAN_INTEN_RFFIE0 BIT(2) /*!< receive FIFO0 full interrupt enable */ +#define CAN_INTEN_RFOIE0 BIT(3) /*!< receive FIFO0 overfull interrupt enable */ +#define CAN_INTEN_RFNEIE1 BIT(4) /*!< receive FIFO1 not empty interrupt enable */ +#define CAN_INTEN_RFFIE1 BIT(5) /*!< receive FIFO1 full interrupt enable */ +#define CAN_INTEN_RFOIE1 BIT(6) /*!< receive FIFO1 overfull interrupt enable */ +#define CAN_INTEN_WERRIE BIT(8) /*!< warning error interrupt enable */ +#define CAN_INTEN_PERRIE BIT(9) /*!< passive error interrupt enable */ +#define CAN_INTEN_BOIE BIT(10) /*!< bus-off interrupt enable */ +#define CAN_INTEN_ERRNIE BIT(11) /*!< error number interrupt enable */ +#define CAN_INTEN_ERRIE BIT(15) /*!< error interrupt enable */ +#define CAN_INTEN_WIE BIT(16) /*!< wakeup interrupt enable */ +#define CAN_INTEN_SLPWIE BIT(17) /*!< sleep working interrupt enable */ + +/* CAN_ERR */ +#define CAN_ERR_WERR BIT(0) /*!< warning error */ +#define CAN_ERR_PERR BIT(1) /*!< passive error */ +#define CAN_ERR_BOERR BIT(2) /*!< bus-off error */ +#define CAN_ERR_ERRN BITS(4,6) /*!< error number */ +#define CAN_ERR_TECNT BITS(16,23) /*!< transmit error count */ +#define CAN_ERR_RECNT BITS(24,31) /*!< receive error count */ + +/* CAN_BT */ +#define CAN_BT_BAUDPSC BITS(0,9) /*!< baudrate prescaler */ +#define CAN_BT_BS1 BITS(16,19) /*!< bit segment 1 */ +#define CAN_BT_BS2 BITS(20,22) /*!< bit segment 2 */ +#define CAN_BT_SJW BITS(24,25) /*!< resynchronization jump width */ +#define CAN_BT_LCMOD BIT(30) /*!< loopback communication mode */ +#define CAN_BT_SCMOD BIT(31) /*!< silent communication mode */ + +/* CAN_TMIx */ +#define CAN_TMI_TEN BIT(0) /*!< transmit enable */ +#define CAN_TMI_FT BIT(1) /*!< frame type */ +#define CAN_TMI_FF BIT(2) /*!< frame format */ +#define CAN_TMI_EFID BITS(3,31) /*!< the frame identifier */ +#define CAN_TMI_SFID BITS(21,31) /*!< the frame identifier */ + +/* CAN_TMPx */ +#define CAN_TMP_DLENC BITS(0,3) /*!< data length code */ +#define CAN_TMP_TSEN BIT(8) /*!< time stamp enable */ +#define CAN_TMP_TS BITS(16,31) /*!< time stamp */ + +/* CAN_TMDATA0x */ +#define CAN_TMDATA0_DB0 BITS(0,7) /*!< transmit data byte 0 */ +#define CAN_TMDATA0_DB1 BITS(8,15) /*!< transmit data byte 1 */ +#define CAN_TMDATA0_DB2 BITS(16,23) /*!< transmit data byte 2 */ +#define CAN_TMDATA0_DB3 BITS(24,31) /*!< transmit data byte 3 */ + +/* CAN_TMDATA1x */ +#define CAN_TMDATA1_DB4 BITS(0,7) /*!< transmit data byte 4 */ +#define CAN_TMDATA1_DB5 BITS(8,15) /*!< transmit data byte 5 */ +#define CAN_TMDATA1_DB6 BITS(16,23) /*!< transmit data byte 6 */ +#define CAN_TMDATA1_DB7 BITS(24,31) /*!< transmit data byte 7 */ + +/* CAN_RFIFOMIx */ +#define CAN_RFIFOMI_FT BIT(1) /*!< frame type */ +#define CAN_RFIFOMI_FF BIT(2) /*!< frame format */ +#define CAN_RFIFOMI_EFID BITS(3,31) /*!< the frame identifier */ +#define CAN_RFIFOMI_SFID BITS(21,31) /*!< the frame identifier */ + +/* CAN_RFIFOMPx */ +#define CAN_RFIFOMP_DLENC BITS(0,3) /*!< receive data length code */ +#define CAN_RFIFOMP_FI BITS(8,15) /*!< filter index */ +#define CAN_RFIFOMP_TS BITS(16,31) /*!< time stamp */ + +/* CAN_RFIFOMDATA0x */ +#define CAN_RFIFOMDATA0_DB0 BITS(0,7) /*!< receive data byte 0 */ +#define CAN_RFIFOMDATA0_DB1 BITS(8,15) /*!< receive data byte 1 */ +#define CAN_RFIFOMDATA0_DB2 BITS(16,23) /*!< receive data byte 2 */ +#define CAN_RFIFOMDATA0_DB3 BITS(24,31) /*!< receive data byte 3 */ + +/* CAN_RFIFOMDATA1x */ +#define CAN_RFIFOMDATA1_DB4 BITS(0,7) /*!< receive data byte 4 */ +#define CAN_RFIFOMDATA1_DB5 BITS(8,15) /*!< receive data byte 5 */ +#define CAN_RFIFOMDATA1_DB6 BITS(16,23) /*!< receive data byte 6 */ +#define CAN_RFIFOMDATA1_DB7 BITS(24,31) /*!< receive data byte 7 */ + +/* CAN_FCTL */ +#define CAN_FCTL_FLD BIT(0) /*!< filter lock disable */ +#define CAN_FCTL_HBC1F BITS(8,13) /*!< header bank of CAN1 filter */ + +/* CAN_FMCFG */ +#define CAN_FMCFG_FMOD(regval) BIT(regval) /*!< filter mode, list or mask*/ + +/* CAN_FSCFG */ +#define CAN_FSCFG_FS(regval) BIT(regval) /*!< filter scale, 32 bits or 16 bits*/ + +/* CAN_FAFIFO */ +#define CAN_FAFIFOR_FAF(regval) BIT(regval) /*!< filter associated with FIFO */ + +/* CAN_FW */ +#define CAN_FW_FW(regval) BIT(regval) /*!< filter working */ + +/* CAN_FxDATAy */ +#define CAN_FDATA_FD(regval) BIT(regval) /*!< filter data */ + +/* consts definitions */ +/* define the CAN bit position and its register index offset */ +#define CAN_REGIDX_BIT(regidx, bitpos) (((uint32_t)(regidx) << 6) | (uint32_t)(bitpos)) +#define CAN_REG_VAL(canx, offset) (REG32((canx) + ((uint32_t)(offset) >> 6))) +#define CAN_BIT_POS(val) ((uint32_t)(val) & 0x1FU) + +#define CAN_REGIDX_BITS(regidx, bitpos0, bitpos1) (((uint32_t)(regidx) << 12) | ((uint32_t)(bitpos0) << 6) | (uint32_t)(bitpos1)) +#define CAN_REG_VALS(canx, offset) (REG32((canx) + ((uint32_t)(offset) >> 12))) +#define CAN_BIT_POS0(val) (((uint32_t)(val) >> 6) & 0x1FU) +#define CAN_BIT_POS1(val) ((uint32_t)(val) & 0x1FU) + +/* register offset */ +#define STAT_REG_OFFSET ((uint8_t)0x04U) /*!< STAT register offset */ +#define TSTAT_REG_OFFSET ((uint8_t)0x08U) /*!< TSTAT register offset */ +#define RFIFO0_REG_OFFSET ((uint8_t)0x0CU) /*!< RFIFO0 register offset */ +#define RFIFO1_REG_OFFSET ((uint8_t)0x10U) /*!< RFIFO1 register offset */ +#define ERR_REG_OFFSET ((uint8_t)0x18U) /*!< ERR register offset */ + +/* CAN flags */ +typedef enum +{ + /* flags in STAT register */ + CAN_FLAG_RXL = CAN_REGIDX_BIT(STAT_REG_OFFSET, 11U), /*!< RX level */ + CAN_FLAG_LASTRX = CAN_REGIDX_BIT(STAT_REG_OFFSET, 10U), /*!< last sample value of RX pin */ + CAN_FLAG_RS = CAN_REGIDX_BIT(STAT_REG_OFFSET, 9U), /*!< receiving state */ + CAN_FLAG_TS = CAN_REGIDX_BIT(STAT_REG_OFFSET, 8U), /*!< transmitting state */ + CAN_FLAG_SLPIF = CAN_REGIDX_BIT(STAT_REG_OFFSET, 4U), /*!< status change flag of entering sleep working mode */ + CAN_FLAG_WUIF = CAN_REGIDX_BIT(STAT_REG_OFFSET, 3U), /*!< status change flag of wakeup from sleep working mode */ + CAN_FLAG_ERRIF = CAN_REGIDX_BIT(STAT_REG_OFFSET, 2U), /*!< error flag */ + CAN_FLAG_SLPWS = CAN_REGIDX_BIT(STAT_REG_OFFSET, 1U), /*!< sleep working state */ + CAN_FLAG_IWS = CAN_REGIDX_BIT(STAT_REG_OFFSET, 0U), /*!< initial working state */ + /* flags in TSTAT register */ + CAN_FLAG_TMLS2 = CAN_REGIDX_BIT(TSTAT_REG_OFFSET, 31U), /*!< transmit mailbox 2 last sending in Tx FIFO */ + CAN_FLAG_TMLS1 = CAN_REGIDX_BIT(TSTAT_REG_OFFSET, 30U), /*!< transmit mailbox 1 last sending in Tx FIFO */ + CAN_FLAG_TMLS0 = CAN_REGIDX_BIT(TSTAT_REG_OFFSET, 29U), /*!< transmit mailbox 0 last sending in Tx FIFO */ + CAN_FLAG_TME2 = CAN_REGIDX_BIT(TSTAT_REG_OFFSET, 28U), /*!< transmit mailbox 2 empty */ + CAN_FLAG_TME1 = CAN_REGIDX_BIT(TSTAT_REG_OFFSET, 27U), /*!< transmit mailbox 1 empty */ + CAN_FLAG_TME0 = CAN_REGIDX_BIT(TSTAT_REG_OFFSET, 26U), /*!< transmit mailbox 0 empty */ + CAN_FLAG_MTE2 = CAN_REGIDX_BIT(TSTAT_REG_OFFSET, 19U), /*!< mailbox 2 transmit error */ + CAN_FLAG_MTE1 = CAN_REGIDX_BIT(TSTAT_REG_OFFSET, 11U), /*!< mailbox 1 transmit error */ + CAN_FLAG_MTE0 = CAN_REGIDX_BIT(TSTAT_REG_OFFSET, 3U), /*!< mailbox 0 transmit error */ + CAN_FLAG_MAL2 = CAN_REGIDX_BIT(TSTAT_REG_OFFSET, 18U), /*!< mailbox 2 arbitration lost */ + CAN_FLAG_MAL1 = CAN_REGIDX_BIT(TSTAT_REG_OFFSET, 10U), /*!< mailbox 1 arbitration lost */ + CAN_FLAG_MAL0 = CAN_REGIDX_BIT(TSTAT_REG_OFFSET, 2U), /*!< mailbox 0 arbitration lost */ + CAN_FLAG_MTFNERR2 = CAN_REGIDX_BIT(TSTAT_REG_OFFSET, 17U), /*!< mailbox 2 transmit finished with no error */ + CAN_FLAG_MTFNERR1 = CAN_REGIDX_BIT(TSTAT_REG_OFFSET, 9U), /*!< mailbox 1 transmit finished with no error */ + CAN_FLAG_MTFNERR0 = CAN_REGIDX_BIT(TSTAT_REG_OFFSET, 1U), /*!< mailbox 0 transmit finished with no error */ + CAN_FLAG_MTF2 = CAN_REGIDX_BIT(TSTAT_REG_OFFSET, 16U), /*!< mailbox 2 transmit finished */ + CAN_FLAG_MTF1 = CAN_REGIDX_BIT(TSTAT_REG_OFFSET, 8U), /*!< mailbox 1 transmit finished */ + CAN_FLAG_MTF0 = CAN_REGIDX_BIT(TSTAT_REG_OFFSET, 0U), /*!< mailbox 0 transmit finished */ + /* flags in RFIFO0 register */ + CAN_FLAG_RFO0 = CAN_REGIDX_BIT(RFIFO0_REG_OFFSET, 4U), /*!< receive FIFO0 overfull */ + CAN_FLAG_RFF0 = CAN_REGIDX_BIT(RFIFO0_REG_OFFSET, 3U), /*!< receive FIFO0 full */ + /* flags in RFIFO1 register */ + CAN_FLAG_RFO1 = CAN_REGIDX_BIT(RFIFO1_REG_OFFSET, 4U), /*!< receive FIFO1 overfull */ + CAN_FLAG_RFF1 = CAN_REGIDX_BIT(RFIFO1_REG_OFFSET, 3U), /*!< receive FIFO1 full */ + /* flags in ERR register */ + CAN_FLAG_BOERR = CAN_REGIDX_BIT(ERR_REG_OFFSET, 2U), /*!< bus-off error */ + CAN_FLAG_PERR = CAN_REGIDX_BIT(ERR_REG_OFFSET, 1U), /*!< passive error */ + CAN_FLAG_WERR = CAN_REGIDX_BIT(ERR_REG_OFFSET, 0U), /*!< warning error */ +}can_flag_enum; + +/* CAN interrupt flags */ +typedef enum +{ + /* interrupt flags in STAT register */ + CAN_INT_FLAG_SLPIF = CAN_REGIDX_BITS(STAT_REG_OFFSET, 4U, 17U), /*!< status change interrupt flag of sleep working mode entering */ + CAN_INT_FLAG_WUIF = CAN_REGIDX_BITS(STAT_REG_OFFSET, 3U, 16), /*!< status change interrupt flag of wakeup from sleep working mode */ + CAN_INT_FLAG_ERRIF = CAN_REGIDX_BITS(STAT_REG_OFFSET, 2U, 15), /*!< error interrupt flag */ + /* interrupt flags in TSTAT register */ + CAN_INT_FLAG_MTF2 = CAN_REGIDX_BITS(TSTAT_REG_OFFSET, 16U, 0U), /*!< mailbox 2 transmit finished interrupt flag */ + CAN_INT_FLAG_MTF1 = CAN_REGIDX_BITS(TSTAT_REG_OFFSET, 8U, 0U), /*!< mailbox 1 transmit finished interrupt flag */ + CAN_INT_FLAG_MTF0 = CAN_REGIDX_BITS(TSTAT_REG_OFFSET, 0U, 0U), /*!< mailbox 0 transmit finished interrupt flag */ + /* interrupt flags in RFIFO0 register */ + CAN_INT_FLAG_RFO0 = CAN_REGIDX_BITS(RFIFO0_REG_OFFSET, 4U, 3U), /*!< receive FIFO0 overfull interrupt flag */ + CAN_INT_FLAG_RFF0 = CAN_REGIDX_BITS(RFIFO0_REG_OFFSET, 3U, 2U), /*!< receive FIFO0 full interrupt flag */ + CAN_INT_FLAG_RFL0 = CAN_REGIDX_BITS(RFIFO0_REG_OFFSET, 2U, 1U), /*!< receive FIFO0 not empty interrupt flag */ + /* interrupt flags in RFIFO0 register */ + CAN_INT_FLAG_RFO1 = CAN_REGIDX_BITS(RFIFO1_REG_OFFSET, 4U, 6U), /*!< receive FIFO1 overfull interrupt flag */ + CAN_INT_FLAG_RFF1 = CAN_REGIDX_BITS(RFIFO1_REG_OFFSET, 3U, 5U), /*!< receive FIFO1 full interrupt flag */ + CAN_INT_FLAG_RFL1 = CAN_REGIDX_BITS(RFIFO1_REG_OFFSET, 2U, 4U), /*!< receive FIFO1 not empty interrupt flag */ + /* interrupt flags in ERR register */ + CAN_INT_FLAG_ERRN = CAN_REGIDX_BITS(ERR_REG_OFFSET, 3U, 11U), /*!< error number interrupt flag */ + CAN_INT_FLAG_BOERR = CAN_REGIDX_BITS(ERR_REG_OFFSET, 2U, 10U), /*!< bus-off error interrupt flag */ + CAN_INT_FLAG_PERR = CAN_REGIDX_BITS(ERR_REG_OFFSET, 1U, 9U), /*!< passive error interrupt flag */ + CAN_INT_FLAG_WERR = CAN_REGIDX_BITS(ERR_REG_OFFSET, 0U, 8U), /*!< warning error interrupt flag */ +}can_interrupt_flag_enum; + +/* CAN initiliaze parameters struct */ +typedef struct +{ + uint8_t working_mode; /*!< CAN working mode */ + uint8_t resync_jump_width; /*!< CAN resynchronization jump width */ + uint8_t time_segment_1; /*!< time segment 1 */ + uint8_t time_segment_2; /*!< time segment 2 */ + ControlStatus time_triggered; /*!< time triggered communication mode */ + ControlStatus auto_bus_off_recovery; /*!< automatic bus-off recovery */ + ControlStatus auto_wake_up; /*!< automatic wake-up mode */ + ControlStatus no_auto_retrans; /*!< automatic retransmission mode disable */ + ControlStatus rec_fifo_overwrite; /*!< receive FIFO overwrite mode */ + ControlStatus trans_fifo_order; /*!< transmit FIFO order */ + uint16_t prescaler; /*!< baudrate prescaler */ +}can_parameter_struct; + +/* CAN transmit message struct */ +typedef struct +{ + uint32_t tx_sfid; /*!< standard format frame identifier */ + uint32_t tx_efid; /*!< extended format frame identifier */ + uint8_t tx_ff; /*!< format of frame, standard or extended format */ + uint8_t tx_ft; /*!< type of frame, data or remote */ + uint8_t tx_dlen; /*!< data length */ + uint8_t tx_data[8]; /*!< transmit data */ +}can_trasnmit_message_struct; + +/* CAN receive message struct */ +typedef struct +{ + uint32_t rx_sfid; /*!< standard format frame identifier */ + uint32_t rx_efid; /*!< extended format frame identifier */ + uint8_t rx_ff; /*!< format of frame, standard or extended format */ + uint8_t rx_ft; /*!< type of frame, data or remote */ + uint8_t rx_dlen; /*!< data length */ + uint8_t rx_data[8]; /*!< receive data */ + uint8_t rx_fi; /*!< filtering index */ +} can_receive_message_struct; + +/* CAN filter parameters struct */ +typedef struct +{ + uint16_t filter_list_high; /*!< filter list number high bits*/ + uint16_t filter_list_low; /*!< filter list number low bits */ + uint16_t filter_mask_high; /*!< filter mask number high bits */ + uint16_t filter_mask_low; /*!< filter mask number low bits */ + uint16_t filter_fifo_number; /*!< receive FIFO associated with the filter */ + uint16_t filter_number; /*!< filter number */ + uint16_t filter_mode; /*!< filter mode, list or mask */ + uint16_t filter_bits; /*!< filter scale */ + ControlStatus filter_enable; /*!< filter work or not */ +}can_filter_parameter_struct; + +/* CAN errors */ +typedef enum +{ + CAN_ERROR_NONE = 0, /*!< no error */ + CAN_ERROR_FILL, /*!< fill error */ + CAN_ERROR_FORMATE, /*!< format error */ + CAN_ERROR_ACK, /*!< ACK error */ + CAN_ERROR_BITRECESSIVE, /*!< bit recessive error */ + CAN_ERROR_BITDOMINANTER, /*!< bit dominant error */ + CAN_ERROR_CRC, /*!< CRC error */ + CAN_ERROR_SOFTWARECFG, /*!< software configure */ +}can_error_enum; + +/* transmit states */ +typedef enum +{ + CAN_TRANSMIT_FAILED = 0U, /*!< CAN transmitted failure */ + CAN_TRANSMIT_OK = 1U, /*!< CAN transmitted success */ + CAN_TRANSMIT_PENDING = 2U, /*!< CAN transmitted pending */ + CAN_TRANSMIT_NOMAILBOX = 4U, /*!< no empty mailbox to be used for CAN */ +}can_transmit_state_enum; + +typedef enum +{ + CAN_INIT_STRUCT = 0, /* CAN initiliaze parameters struct */ + CAN_FILTER_STRUCT, /* CAN filter parameters struct */ + CAN_TX_MESSAGE_STRUCT, /* CAN transmit message struct */ + CAN_RX_MESSAGE_STRUCT, /* CAN receive message struct */ +}can_struct_type_enum; + +/* CAN baudrate prescaler*/ +#define BT_BAUDPSC(regval) (BITS(0,9) & ((uint32_t)(regval) << 0)) + +/* CAN bit segment 1*/ +#define BT_BS1(regval) (BITS(16,19) & ((uint32_t)(regval) << 16)) + +/* CAN bit segment 2*/ +#define BT_BS2(regval) (BITS(20,22) & ((uint32_t)(regval) << 20)) + +/* CAN resynchronization jump width*/ +#define BT_SJW(regval) (BITS(24,25) & ((uint32_t)(regval) << 24)) + +/* CAN communication mode*/ +#define BT_MODE(regval) (BITS(30,31) & ((uint32_t)(regval) << 30)) + +/* CAN FDATA high 16 bits */ +#define FDATA_MASK_HIGH(regval) (BITS(16,31) & ((uint32_t)(regval) << 16)) + +/* CAN FDATA low 16 bits */ +#define FDATA_MASK_LOW(regval) (BITS(0,15) & ((uint32_t)(regval) << 0)) + +/* CAN1 filter start bank_number*/ +#define FCTL_HBC1F(regval) (BITS(8,13) & ((uint32_t)(regval) << 8)) + +/* CAN transmit mailbox extended identifier*/ +#define TMI_EFID(regval) (BITS(3,31) & ((uint32_t)(regval) << 3)) + +/* CAN transmit mailbox standard identifier*/ +#define TMI_SFID(regval) (BITS(21,31) & ((uint32_t)(regval) << 21)) + +/* transmit data byte 0 */ +#define TMDATA0_DB0(regval) (BITS(0,7) & ((uint32_t)(regval) << 0)) + +/* transmit data byte 1 */ +#define TMDATA0_DB1(regval) (BITS(8,15) & ((uint32_t)(regval) << 8)) + +/* transmit data byte 2 */ +#define TMDATA0_DB2(regval) (BITS(16,23) & ((uint32_t)(regval) << 16)) + +/* transmit data byte 3 */ +#define TMDATA0_DB3(regval) (BITS(24,31) & ((uint32_t)(regval) << 24)) + +/* transmit data byte 4 */ +#define TMDATA1_DB4(regval) (BITS(0,7) & ((uint32_t)(regval) << 0)) + +/* transmit data byte 5 */ +#define TMDATA1_DB5(regval) (BITS(8,15) & ((uint32_t)(regval) << 8)) + +/* transmit data byte 6 */ +#define TMDATA1_DB6(regval) (BITS(16,23) & ((uint32_t)(regval) << 16)) + +/* transmit data byte 7 */ +#define TMDATA1_DB7(regval) (BITS(24,31) & ((uint32_t)(regval) << 24)) + +/* receive mailbox extended identifier*/ +#define GET_RFIFOMI_EFID(regval) GET_BITS((uint32_t)(regval), 3U, 31U) + +/* receive mailbox standrad identifier*/ +#define GET_RFIFOMI_SFID(regval) GET_BITS((uint32_t)(regval), 21U, 31U) + +/* receive data length */ +#define GET_RFIFOMP_DLENC(regval) GET_BITS((uint32_t)(regval), 0U, 3U) + +/* the index of the filter by which the frame is passed */ +#define GET_RFIFOMP_FI(regval) GET_BITS((uint32_t)(regval), 8U, 15U) + +/* receive data byte 0 */ +#define GET_RFIFOMDATA0_DB0(regval) GET_BITS((uint32_t)(regval), 0U, 7U) + +/* receive data byte 1 */ +#define GET_RFIFOMDATA0_DB1(regval) GET_BITS((uint32_t)(regval), 8U, 15U) + +/* receive data byte 2 */ +#define GET_RFIFOMDATA0_DB2(regval) GET_BITS((uint32_t)(regval), 16U, 23U) + +/* receive data byte 3 */ +#define GET_RFIFOMDATA0_DB3(regval) GET_BITS((uint32_t)(regval), 24U, 31U) + +/* receive data byte 4 */ +#define GET_RFIFOMDATA1_DB4(regval) GET_BITS((uint32_t)(regval), 0U, 7U) + +/* receive data byte 5 */ +#define GET_RFIFOMDATA1_DB5(regval) GET_BITS((uint32_t)(regval), 8U, 15U) + +/* receive data byte 6 */ +#define GET_RFIFOMDATA1_DB6(regval) GET_BITS((uint32_t)(regval), 16U, 23U) + +/* receive data byte 7 */ +#define GET_RFIFOMDATA1_DB7(regval) GET_BITS((uint32_t)(regval), 24U, 31U) + +/* error number */ +#define GET_ERR_ERRN(regval) GET_BITS((uint32_t)(regval), 4U, 6U) + +/* transmit error count */ +#define GET_ERR_TECNT(regval) GET_BITS((uint32_t)(regval), 16U, 23U) + +/* receive error count */ +#define GET_ERR_RECNT(regval) GET_BITS((uint32_t)(regval), 24U, 31U) + +/* CAN errors */ +#define ERR_ERRN(regval) (BITS(4,6) & ((uint32_t)(regval) << 4)) +#define CAN_ERRN_0 ERR_ERRN(0U) /* no error */ +#define CAN_ERRN_1 ERR_ERRN(1U) /*!< fill error */ +#define CAN_ERRN_2 ERR_ERRN(2U) /*!< format error */ +#define CAN_ERRN_3 ERR_ERRN(3U) /*!< ACK error */ +#define CAN_ERRN_4 ERR_ERRN(4U) /*!< bit recessive error */ +#define CAN_ERRN_5 ERR_ERRN(5U) /*!< bit dominant error */ +#define CAN_ERRN_6 ERR_ERRN(6U) /*!< CRC error */ +#define CAN_ERRN_7 ERR_ERRN(7U) /*!< software error */ + +#define CAN_STATE_PENDING ((uint32_t)0x00000000U) /*!< CAN pending */ + +/* CAN communication mode */ +#define CAN_NORMAL_MODE ((uint8_t)0x00U) /*!< normal communication mode */ +#define CAN_LOOPBACK_MODE ((uint8_t)0x01U) /*!< loopback communication mode */ +#define CAN_SILENT_MODE ((uint8_t)0x02U) /*!< silent communication mode */ +#define CAN_SILENT_LOOPBACK_MODE ((uint8_t)0x03U) /*!< loopback and silent communication mode */ + +/* CAN resynchronisation jump width */ +#define CAN_BT_SJW_1TQ ((uint8_t)0x00U) /*!< 1 time quanta */ +#define CAN_BT_SJW_2TQ ((uint8_t)0x01U) /*!< 2 time quanta */ +#define CAN_BT_SJW_3TQ ((uint8_t)0x02U) /*!< 3 time quanta */ +#define CAN_BT_SJW_4TQ ((uint8_t)0x03U) /*!< 4 time quanta */ + +/* CAN time segment 1 */ +#define CAN_BT_BS1_1TQ ((uint8_t)0x00U) /*!< 1 time quanta */ +#define CAN_BT_BS1_2TQ ((uint8_t)0x01U) /*!< 2 time quanta */ +#define CAN_BT_BS1_3TQ ((uint8_t)0x02U) /*!< 3 time quanta */ +#define CAN_BT_BS1_4TQ ((uint8_t)0x03U) /*!< 4 time quanta */ +#define CAN_BT_BS1_5TQ ((uint8_t)0x04U) /*!< 5 time quanta */ +#define CAN_BT_BS1_6TQ ((uint8_t)0x05U) /*!< 6 time quanta */ +#define CAN_BT_BS1_7TQ ((uint8_t)0x06U) /*!< 7 time quanta */ +#define CAN_BT_BS1_8TQ ((uint8_t)0x07U) /*!< 8 time quanta */ +#define CAN_BT_BS1_9TQ ((uint8_t)0x08U) /*!< 9 time quanta */ +#define CAN_BT_BS1_10TQ ((uint8_t)0x09U) /*!< 10 time quanta */ +#define CAN_BT_BS1_11TQ ((uint8_t)0x0AU) /*!< 11 time quanta */ +#define CAN_BT_BS1_12TQ ((uint8_t)0x0BU) /*!< 12 time quanta */ +#define CAN_BT_BS1_13TQ ((uint8_t)0x0CU) /*!< 13 time quanta */ +#define CAN_BT_BS1_14TQ ((uint8_t)0x0DU) /*!< 14 time quanta */ +#define CAN_BT_BS1_15TQ ((uint8_t)0x0EU) /*!< 15 time quanta */ +#define CAN_BT_BS1_16TQ ((uint8_t)0x0FU) /*!< 16 time quanta */ + +/* CAN time segment 2 */ +#define CAN_BT_BS2_1TQ ((uint8_t)0x00U) /*!< 1 time quanta */ +#define CAN_BT_BS2_2TQ ((uint8_t)0x01U) /*!< 2 time quanta */ +#define CAN_BT_BS2_3TQ ((uint8_t)0x02U) /*!< 3 time quanta */ +#define CAN_BT_BS2_4TQ ((uint8_t)0x03U) /*!< 4 time quanta */ +#define CAN_BT_BS2_5TQ ((uint8_t)0x04U) /*!< 5 time quanta */ +#define CAN_BT_BS2_6TQ ((uint8_t)0x05U) /*!< 6 time quanta */ +#define CAN_BT_BS2_7TQ ((uint8_t)0x06U) /*!< 7 time quanta */ +#define CAN_BT_BS2_8TQ ((uint8_t)0x07U) /*!< 8 time quanta */ + +/* CAN mailbox number */ +#define CAN_MAILBOX0 ((uint8_t)0x00U) /*!< mailbox0 */ +#define CAN_MAILBOX1 ((uint8_t)0x01U) /*!< mailbox1 */ +#define CAN_MAILBOX2 ((uint8_t)0x02U) /*!< mailbox2 */ +#define CAN_NOMAILBOX ((uint8_t)0x03U) /*!< no mailbox empty */ + +/* CAN frame format */ +#define CAN_FF_STANDARD ((uint32_t)0x00000000U) /*!< standard frame */ +#define CAN_FF_EXTENDED ((uint32_t)0x00000004U) /*!< extended frame */ + +/* CAN receive fifo */ +#define CAN_FIFO0 ((uint8_t)0x00U) /*!< receive FIFO0 */ +#define CAN_FIFO1 ((uint8_t)0x01U) /*!< receive FIFO1 */ + +/* frame number of receive fifo */ +#define CAN_RFIF_RFL_MASK ((uint32_t)0x00000003U) /*!< mask for frame number in receive FIFOx */ + +#define CAN_SFID_MASK ((uint32_t)0x000007FFU) /*!< mask of standard identifier */ +#define CAN_EFID_MASK ((uint32_t)0x1FFFFFFFU) /*!< mask of extended identifier */ + +/* CAN working mode */ +#define CAN_MODE_INITIALIZE ((uint8_t)0x01U) /*!< CAN initialize mode */ +#define CAN_MODE_NORMAL ((uint8_t)0x02U) /*!< CAN normal mode */ +#define CAN_MODE_SLEEP ((uint8_t)0x04U) /*!< CAN sleep mode */ + +/* filter bits */ +#define CAN_FILTERBITS_16BIT ((uint8_t)0x00U) /*!< CAN filter 16 bits */ +#define CAN_FILTERBITS_32BIT ((uint8_t)0x01U) /*!< CAN filter 32 bits */ + +/* filter mode */ +#define CAN_FILTERMODE_MASK ((uint8_t)0x00U) /*!< mask mode */ +#define CAN_FILTERMODE_LIST ((uint8_t)0x01U) /*!< list mode */ + +/* filter 16 bits mask */ +#define CAN_FILTER_MASK_16BITS ((uint32_t)0x0000FFFFU) /*!< can filter 16 bits mask */ + +/* frame type */ +#define CAN_FT_DATA ((uint32_t)0x00000000U) /*!< data frame */ +#define CAN_FT_REMOTE ((uint32_t)0x00000002U) /*!< remote frame */ + +/* CAN timeout */ +#define CAN_TIMEOUT ((uint32_t)0x0000FFFFU) /*!< timeout value */ + +/* interrupt enable bits */ +#define CAN_INT_TME CAN_INTEN_TMEIE /*!< transmit mailbox empty interrupt enable */ +#define CAN_INT_RFNE0 CAN_INTEN_RFNEIE0 /*!< receive FIFO0 not empty interrupt enable */ +#define CAN_INT_RFF0 CAN_INTEN_RFFIE0 /*!< receive FIFO0 full interrupt enable */ +#define CAN_INT_RFO0 CAN_INTEN_RFOIE0 /*!< receive FIFO0 overfull interrupt enable */ +#define CAN_INT_RFNE1 CAN_INTEN_RFNEIE1 /*!< receive FIFO1 not empty interrupt enable */ +#define CAN_INT_RFF1 CAN_INTEN_RFFIE1 /*!< receive FIFO1 full interrupt enable */ +#define CAN_INT_RFO1 CAN_INTEN_RFOIE1 /*!< receive FIFO1 overfull interrupt enable */ +#define CAN_INT_WERR CAN_INTEN_WERRIE /*!< warning error interrupt enable */ +#define CAN_INT_PERR CAN_INTEN_PERRIE /*!< passive error interrupt enable */ +#define CAN_INT_BO CAN_INTEN_BOIE /*!< bus-off interrupt enable */ +#define CAN_INT_ERRN CAN_INTEN_ERRNIE /*!< error number interrupt enable */ +#define CAN_INT_ERR CAN_INTEN_ERRIE /*!< error interrupt enable */ +#define CAN_INT_WAKEUP CAN_INTEN_WIE /*!< wakeup interrupt enable */ +#define CAN_INT_SLPW CAN_INTEN_SLPWIE /*!< sleep working interrupt enable */ + +/* function declarations */ +/* deinitialize CAN */ +void can_deinit(uint32_t can_periph); +/* initialize CAN struct */ +void can_struct_para_init(can_struct_type_enum type, void* p_struct); +/* initialize CAN */ +ErrStatus can_init(uint32_t can_periph, can_parameter_struct* can_parameter_init); +/* CAN filter init */ +void can_filter_init(can_filter_parameter_struct* can_filter_parameter_init); +/* set can1 fliter start bank number */ +void can1_filter_start_bank(uint8_t start_bank); +/* enable functions */ +/* CAN debug freeze enable */ +void can_debug_freeze_enable(uint32_t can_periph); +/* CAN debug freeze disable */ +void can_debug_freeze_disable(uint32_t can_periph); +/* CAN time trigger mode enable */ +void can_time_trigger_mode_enable(uint32_t can_periph); +/* CAN time trigger mode disable */ +void can_time_trigger_mode_disable(uint32_t can_periph); + +/* transmit functions */ +/* transmit CAN message */ +uint8_t can_message_transmit(uint32_t can_periph, can_trasnmit_message_struct* transmit_message); +/* get CAN transmit state */ +can_transmit_state_enum can_transmit_states(uint32_t can_periph, uint8_t mailbox_number); +/* stop CAN transmission */ +void can_transmission_stop(uint32_t can_periph, uint8_t mailbox_number); +/* CAN receive message */ +void can_message_receive(uint32_t can_periph, uint8_t fifo_number, can_receive_message_struct* receive_message); +/* CAN release fifo */ +void can_fifo_release(uint32_t can_periph, uint8_t fifo_number); +/* CAN receive message length */ +uint8_t can_receive_message_length_get(uint32_t can_periph, uint8_t fifo_number); +/* CAN working mode */ +ErrStatus can_working_mode_set(uint32_t can_periph, uint8_t working_mode); +/* CAN wakeup from sleep mode */ +ErrStatus can_wakeup(uint32_t can_periph); + +/* CAN get error */ +can_error_enum can_error_get(uint32_t can_periph); +/* get CAN receive error number */ +uint8_t can_receive_error_number_get(uint32_t can_periph); +/* get CAN transmit error number */ +uint8_t can_transmit_error_number_get(uint32_t can_periph); + +/* CAN interrupt enable */ +void can_interrupt_enable(uint32_t can_periph, uint32_t interrupt); +/* CAN interrupt disable */ +void can_interrupt_disable(uint32_t can_periph, uint32_t interrupt); +/* CAN get flag state */ +FlagStatus can_flag_get(uint32_t can_periph, can_flag_enum flag); +/* CAN clear flag state */ +void can_flag_clear(uint32_t can_periph, can_flag_enum flag); +/* CAN get interrupt flag state */ +FlagStatus can_interrupt_flag_get(uint32_t can_periph, can_interrupt_flag_enum flag); +/* CAN clear interrupt flag state */ +void can_interrupt_flag_clear(uint32_t can_periph, can_interrupt_flag_enum flag); + +#endif /* GD32F30X_CAN_H */ diff --git a/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_standard_peripheral/Include/gd32f30x_crc.h b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_standard_peripheral/Include/gd32f30x_crc.h new file mode 100644 index 0000000000..bc3c43ffe4 --- /dev/null +++ b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_standard_peripheral/Include/gd32f30x_crc.h @@ -0,0 +1,81 @@ +/*! + \file gd32f30x_crc.h + \brief definitions for the CRC + + \version 2017-02-10, V1.0.0, firmware for GD32F30x + \version 2018-10-10, V1.1.0, firmware for GD32F30x + \version 2018-12-25, V2.0.0, firmware for GD32F30x + \version 2020-09-30, V2.1.0, firmware for GD32F30x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef GD32F30X_CRC_H +#define GD32F30X_CRC_H + +#include "gd32f30x.h" + +/* CRC definitions */ +#define CRC CRC_BASE + +/* registers definitions */ +#define CRC_DATA REG32(CRC + 0x00U) /*!< CRC data register */ +#define CRC_FDATA REG32(CRC + 0x04U) /*!< CRC free data register */ +#define CRC_CTL REG32(CRC + 0x08U) /*!< CRC control register */ + +/* bits definitions */ +/* CRC_DATA */ +#define CRC_DATA_DATA BITS(0,31) /*!< CRC calculation result bits */ + +/* CRC_FDATA */ +#define CRC_FDATA_FDATA BITS(0,7) /*!< CRC free data bits */ + +/* CRC_CTL */ +#define CRC_CTL_RST BIT(0) /*!< CRC reset CRC_DATA register bit */ + + +/* function declarations */ +/* deinit CRC calculation unit */ +void crc_deinit(void); + +/* reset data register(CRC_DATA) to the value of 0xFFFFFFFF */ +void crc_data_register_reset(void); +/* read the value of the data register */ +uint32_t crc_data_register_read(void); + +/* read the value of the free data register */ +uint8_t crc_free_data_register_read(void); +/* write data to the free data register */ +void crc_free_data_register_write(uint8_t free_data); + +/* calculate the CRC value of a 32-bit data */ +uint32_t crc_single_data_calculate(uint32_t sdata); +/* calculate the CRC value of an array of 32-bit values */ +uint32_t crc_block_data_calculate(const uint32_t *array, uint32_t size); + +#endif /* GD32F30X_CRC_H */ diff --git a/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_standard_peripheral/Include/gd32f30x_ctc.h b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_standard_peripheral/Include/gd32f30x_ctc.h new file mode 100644 index 0000000000..5602447bad --- /dev/null +++ b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_standard_peripheral/Include/gd32f30x_ctc.h @@ -0,0 +1,186 @@ +/*! + \file gd32f30x_ctc.h + \brief definitions for the CTC + + \version 2017-02-10, V1.0.0, firmware for GD32F30x + \version 2018-10-10, V1.1.0, firmware for GD32F30x + \version 2018-12-25, V2.0.0, firmware for GD32F30x + \version 2020-09-30, V2.1.0, firmware for GD32F30x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef GD32F30X_CTC_H +#define GD32F30X_CTC_H + +#include "gd32f30x.h" + +/* CTC definitions */ +#define CTC CTC_BASE + +/* registers definitions */ +#define CTC_CTL0 REG32((CTC) + 0x00U) /*!< CTC control register 0 */ +#define CTC_CTL1 REG32((CTC) + 0x04U) /*!< CTC control register 1 */ +#define CTC_STAT REG32((CTC) + 0x08U) /*!< CTC status register */ +#define CTC_INTC REG32((CTC) + 0x0CU) /*!< CTC interrupt clear register */ + +/* bits definitions */ +/* CTC_CTL0 */ +#define CTC_CTL0_CKOKIE BIT(0) /*!< clock trim OK(CKOKIF) interrupt enable */ +#define CTC_CTL0_CKWARNIE BIT(1) /*!< clock trim warning(CKWARNIF) interrupt enable */ +#define CTC_CTL0_ERRIE BIT(2) /*!< error(ERRIF) interrupt enable */ +#define CTC_CTL0_EREFIE BIT(3) /*!< EREFIF interrupt enable */ +#define CTC_CTL0_CNTEN BIT(5) /*!< CTC counter enable */ +#define CTC_CTL0_AUTOTRIM BIT(6) /*!< hardware automatically trim mode */ +#define CTC_CTL0_SWREFPUL BIT(7) /*!< software reference source sync pulse */ +#define CTC_CTL0_TRIMVALUE BITS(8,13) /*!< IRC48M trim value */ + +/* CTC_CTL1 */ +#define CTC_CTL1_RLVALUE BITS(0,15) /*!< CTC counter reload value */ +#define CTC_CTL1_CKLIM BITS(16,23) /*!< clock trim base limit value */ +#define CTC_CTL1_REFPSC BITS(24,26) /*!< reference signal source prescaler */ +#define CTC_CTL1_REFSEL BITS(28,29) /*!< reference signal source selection */ +#define CTC_CTL1_REFPOL BIT(31) /*!< reference signal source polarity */ + +/* CTC_STAT */ +#define CTC_STAT_CKOKIF BIT(0) /*!< clock trim OK interrupt flag */ +#define CTC_STAT_CKWARNIF BIT(1) /*!< clock trim warning interrupt flag */ +#define CTC_STAT_ERRIF BIT(2) /*!< error interrupt flag */ +#define CTC_STAT_EREFIF BIT(3) /*!< expect reference interrupt flag */ +#define CTC_STAT_CKERR BIT(8) /*!< clock trim error bit */ +#define CTC_STAT_REFMISS BIT(9) /*!< reference sync pulse miss */ +#define CTC_STAT_TRIMERR BIT(10) /*!< trim value error bit */ +#define CTC_STAT_REFDIR BIT(15) /*!< CTC trim counter direction when reference sync pulse occurred */ +#define CTC_STAT_REFCAP BITS(16,31) /*!< CTC counter capture when reference sync pulse occurred */ + +/* CTC_INTC */ +#define CTC_INTC_CKOKIC BIT(0) /*!< CKOKIF interrupt clear bit */ +#define CTC_INTC_CKWARNIC BIT(1) /*!< CKWARNIF interrupt clear bit */ +#define CTC_INTC_ERRIC BIT(2) /*!< ERRIF interrupt clear bit */ +#define CTC_INTC_EREFIC BIT(3) /*!< EREFIF interrupt clear bit */ + +/* constants definitions */ +/* hardware automatically trim mode definitions */ +#define CTC_HARDWARE_TRIM_MODE_ENABLE CTC_CTL0_AUTOTRIM /*!< hardware automatically trim mode enable*/ +#define CTC_HARDWARE_TRIM_MODE_DISABLE ((uint32_t)0x00000000U) /*!< hardware automatically trim mode disable*/ + +/* reference signal source polarity definitions */ +#define CTC_REFSOURCE_POLARITY_FALLING CTC_CTL1_REFPOL /*!< reference signal source polarity is falling edge*/ +#define CTC_REFSOURCE_POLARITY_RISING ((uint32_t)0x00000000U) /*!< reference signal source polarity is rising edge*/ + +/* reference signal source selection definitions */ +#define CTL1_REFSEL(regval) (BITS(28,29) & ((uint32_t)(regval) << 28)) +#define CTC_REFSOURCE_GPIO CTL1_REFSEL(0) /*!< GPIO is selected */ +#define CTC_REFSOURCE_LXTAL CTL1_REFSEL(1) /*!< LXTAL is selected */ +#define CTC_REFSOURCE_USB_SOF CTL1_REFSEL(2) /*!< USBD_SOF or USBFS_SOF is selected */ + +/* reference signal source prescaler definitions */ +#define CTL1_REFPSC(regval) (BITS(24,26) & ((uint32_t)(regval) << 24)) +#define CTC_REFSOURCE_PSC_OFF CTL1_REFPSC(0) /*!< reference signal not divided */ +#define CTC_REFSOURCE_PSC_DIV2 CTL1_REFPSC(1) /*!< reference signal divided by 2 */ +#define CTC_REFSOURCE_PSC_DIV4 CTL1_REFPSC(2) /*!< reference signal divided by 4 */ +#define CTC_REFSOURCE_PSC_DIV8 CTL1_REFPSC(3) /*!< reference signal divided by 8 */ +#define CTC_REFSOURCE_PSC_DIV16 CTL1_REFPSC(4) /*!< reference signal divided by 16 */ +#define CTC_REFSOURCE_PSC_DIV32 CTL1_REFPSC(5) /*!< reference signal divided by 32 */ +#define CTC_REFSOURCE_PSC_DIV64 CTL1_REFPSC(6) /*!< reference signal divided by 64 */ +#define CTC_REFSOURCE_PSC_DIV128 CTL1_REFPSC(7) /*!< reference signal divided by 128 */ + +/* CTC interrupt enable definitions */ +#define CTC_INT_CKOK CTC_CTL0_CKOKIE /*!< clock trim OK interrupt enable */ +#define CTC_INT_CKWARN CTC_CTL0_CKWARNIE /*!< clock trim warning interrupt enable */ +#define CTC_INT_ERR CTC_CTL0_ERRIE /*!< error interrupt enable */ +#define CTC_INT_EREF CTC_CTL0_EREFIE /*!< expect reference interrupt enable */ + +/* CTC interrupt source definitions */ +#define CTC_INT_FLAG_CKOK CTC_STAT_CKOKIF /*!< clock trim OK interrupt flag */ +#define CTC_INT_FLAG_CKWARN CTC_STAT_CKWARNIF /*!< clock trim warning interrupt flag */ +#define CTC_INT_FLAG_ERR CTC_STAT_ERRIF /*!< error interrupt flag */ +#define CTC_INT_FLAG_EREF CTC_STAT_EREFIF /*!< expect reference interrupt flag */ +#define CTC_INT_FLAG_CKERR CTC_STAT_CKERR /*!< clock trim error bit */ +#define CTC_INT_FLAG_REFMISS CTC_STAT_REFMISS /*!< reference sync pulse miss */ +#define CTC_INT_FLAG_TRIMERR CTC_STAT_TRIMERR /*!< trim value error */ + +/* CTC flag definitions */ +#define CTC_FLAG_CKOK CTC_STAT_CKOKIF /*!< clock trim OK flag */ +#define CTC_FLAG_CKWARN CTC_STAT_CKWARNIF /*!< clock trim warning flag */ +#define CTC_FLAG_ERR CTC_STAT_ERRIF /*!< error flag */ +#define CTC_FLAG_EREF CTC_STAT_EREFIF /*!< expect reference flag */ +#define CTC_FLAG_CKERR CTC_STAT_CKERR /*!< clock trim error bit */ +#define CTC_FLAG_REFMISS CTC_STAT_REFMISS /*!< reference sync pulse miss */ +#define CTC_FLAG_TRIMERR CTC_STAT_TRIMERR /*!< trim value error bit */ + +/* function declarations */ +/* reset ctc clock trim controller */ +void ctc_deinit(void); +/* enable CTC trim counter */ +void ctc_counter_enable(void); +/* disable CTC trim counter */ +void ctc_counter_disable(void); + +/* configure the IRC48M trim value */ +void ctc_irc48m_trim_value_config(uint8_t trim_value); +/* generate software reference source sync pulse */ +void ctc_software_refsource_pulse_generate(void); +/* configure hardware automatically trim mode */ +void ctc_hardware_trim_mode_config(uint32_t hardmode); + +/* configure reference signal source polarity */ +void ctc_refsource_polarity_config(uint32_t polarity); +/* select reference signal source */ +void ctc_refsource_signal_select(uint32_t refs); +/* configure reference signal source prescaler */ +void ctc_refsource_prescaler_config(uint32_t prescaler); +/* configure clock trim base limit value */ +void ctc_clock_limit_value_config(uint8_t limit_value); +/* configure CTC counter reload value */ +void ctc_counter_reload_value_config(uint16_t reload_value); + +/* read CTC counter capture value when reference sync pulse occurred */ +uint16_t ctc_counter_capture_value_read(void); +/* read CTC trim counter direction when reference sync pulse occurred */ +FlagStatus ctc_counter_direction_read(void); +/* read CTC counter reload value */ +uint16_t ctc_counter_reload_value_read(void); +/* read the IRC48M trim value */ +uint8_t ctc_irc48m_trim_value_read(void); + +/* interrupt & flag functions */ +/* enable the CTC interrupt */ +void ctc_interrupt_enable(uint32_t interrupt); +/* disable the CTC interrupt */ +void ctc_interrupt_disable(uint32_t interrupt); +/* get CTC interrupt flag */ +FlagStatus ctc_interrupt_flag_get(uint32_t int_flag); +/* clear CTC interrupt flag */ +void ctc_interrupt_flag_clear(uint32_t int_flag); +/* get CTC flag */ +FlagStatus ctc_flag_get(uint32_t flag); +/* clear CTC flag */ +void ctc_flag_clear(uint32_t flag); + +#endif /* GD32F30X_CTC_H */ diff --git a/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_standard_peripheral/Include/gd32f30x_dac.h b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_standard_peripheral/Include/gd32f30x_dac.h new file mode 100644 index 0000000000..f2d3b2d693 --- /dev/null +++ b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_standard_peripheral/Include/gd32f30x_dac.h @@ -0,0 +1,250 @@ +/*! + \file gd32f30x_dac.h + \brief definitions for the DAC + + \version 2017-02-10, V1.0.0, firmware for GD32F30x + \version 2018-10-10, V1.1.0, firmware for GD32F30x + \version 2018-12-25, V2.0.0, firmware for GD32F30x + \version 2020-09-30, V2.1.0, firmware for GD32F30x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef GD32F30X_DAC_H +#define GD32F30X_DAC_H + +#include "gd32f30x.h" + +/* DACx(x=0,1) definitions */ +#define DAC DAC_BASE +#define DAC0 0U +#define DAC1 1U + +/* registers definitions */ +#define DAC_CTL REG32(DAC + 0x00U) /*!< DAC control register */ +#define DAC_SWT REG32(DAC + 0x04U) /*!< DAC software trigger register */ +#define DAC0_R12DH REG32(DAC + 0x08U) /*!< DAC0 12-bit right-aligned data holding register */ +#define DAC0_L12DH REG32(DAC + 0x0CU) /*!< DAC0 12-bit left-aligned data holding register */ +#define DAC0_R8DH REG32(DAC + 0x10U) /*!< DAC0 8-bit right-aligned data holding register */ +#define DAC1_R12DH REG32(DAC + 0x14U) /*!< DAC1 12-bit right-aligned data holding register */ +#define DAC1_L12DH REG32(DAC + 0x18U) /*!< DAC1 12-bit left-aligned data holding register */ +#define DAC1_R8DH REG32(DAC + 0x1CU) /*!< DAC1 8-bit right-aligned data holding register */ +#define DACC_R12DH REG32(DAC + 0x20U) /*!< DAC concurrent mode 12-bit right-aligned data holding register */ +#define DACC_L12DH REG32(DAC + 0x24U) /*!< DAC concurrent mode 12-bit left-aligned data holding register */ +#define DACC_R8DH REG32(DAC + 0x28U) /*!< DAC concurrent mode 8-bit right-aligned data holding register */ +#define DAC0_DO REG32(DAC + 0x2CU) /*!< DAC0 data output register */ +#define DAC1_DO REG32(DAC + 0x30U) /*!< DAC1 data output register */ + +/* bits definitions */ +/* DAC_CTL */ +#define DAC_CTL_DEN0 BIT(0) /*!< DAC0 enable/disable bit */ +#define DAC_CTL_DBOFF0 BIT(1) /*!< DAC0 output buffer turn on/turn off bit */ +#define DAC_CTL_DTEN0 BIT(2) /*!< DAC0 trigger enable/disable bit */ +#define DAC_CTL_DTSEL0 BITS(3,5) /*!< DAC0 trigger source selection enable/disable bits */ +#define DAC_CTL_DWM0 BITS(6,7) /*!< DAC0 noise wave mode */ +#define DAC_CTL_DWBW0 BITS(8,11) /*!< DAC0 noise wave bit width */ +#define DAC_CTL_DDMAEN0 BIT(12) /*!< DAC0 DMA enable/disable bit */ +#define DAC_CTL_DEN1 BIT(16) /*!< DAC1 enable/disable bit */ +#define DAC_CTL_DBOFF1 BIT(17) /*!< DAC1 output buffer turn on/turn off bit */ +#define DAC_CTL_DTEN1 BIT(18) /*!< DAC1 trigger enable/disable bit */ +#define DAC_CTL_DTSEL1 BITS(19,21) /*!< DAC1 trigger source selection enable/disable bits */ +#define DAC_CTL_DWM1 BITS(22,23) /*!< DAC1 noise wave mode */ +#define DAC_CTL_DWBW1 BITS(24,27) /*!< DAC1 noise wave bit width */ +#define DAC_CTL_DDMAEN1 BIT(28) /*!< DAC1 DMA enable/disable bit */ + +/* DAC_SWT */ +#define DAC_SWT_SWTR0 BIT(0) /*!< DAC0 software trigger bit, cleared by hardware */ +#define DAC_SWT_SWTR1 BIT(1) /*!< DAC1 software trigger bit, cleared by hardware */ + +/* DAC0_R12DH */ +#define DAC0_R12DH_DAC0_DH BITS(0,11) /*!< DAC0 12-bit right-aligned data bits */ + +/* DAC0_L12DH */ +#define DAC0_L12DH_DAC0_DH BITS(4,15) /*!< DAC0 12-bit left-aligned data bits */ + +/* DAC0_R8DH */ +#define DAC0_R8DH_DAC0_DH BITS(0,7) /*!< DAC0 8-bit right-aligned data bits */ + +/* DAC1_R12DH */ +#define DAC1_R12DH_DAC1_DH BITS(0,11) /*!< DAC1 12-bit right-aligned data bits */ + +/* DAC1_L12DH */ +#define DAC1_L12DH_DAC1_DH BITS(4,15) /*!< DAC1 12-bit left-aligned data bits */ + +/* DAC1_R8DH */ +#define DAC1_R8DH_DAC1_DH BITS(0,7) /*!< DAC1 8-bit right-aligned data bits */ + +/* DACC_R12DH */ +#define DACC_R12DH_DAC0_DH BITS(0,11) /*!< DAC concurrent mode DAC0 12-bit right-aligned data bits */ +#define DACC_R12DH_DAC1_DH BITS(16,27) /*!< DAC concurrent mode DAC1 12-bit right-aligned data bits */ + +/* DACC_L12DH */ +#define DACC_L12DH_DAC0_DH BITS(4,15) /*!< DAC concurrent mode DAC0 12-bit left-aligned data bits */ +#define DACC_L12DH_DAC1_DH BITS(20,31) /*!< DAC concurrent mode DAC1 12-bit left-aligned data bits */ + +/* DACC_R8DH */ +#define DACC_R8DH_DAC0_DH BITS(0,7) /*!< DAC concurrent mode DAC0 8-bit right-aligned data bits */ +#define DACC_R8DH_DAC1_DH BITS(8,15) /*!< DAC concurrent mode DAC1 8-bit right-aligned data bits */ + +/* DAC0_DO */ +#define DAC0_DO_DAC0_DO BITS(0,11) /*!< DAC0 12-bit output data bits */ + +/* DAC1_DO */ +#define DAC1_DO_DAC1_DO BITS(0,11) /*!< DAC1 12-bit output data bits */ + +/* constants definitions */ +/* DAC trigger source */ +#define CTL_DTSEL(regval) (BITS(3,5) & ((uint32_t)(regval) << 3)) +#define DAC_TRIGGER_T5_TRGO CTL_DTSEL(0) /*!< TIMER5 TRGO */ +#if (defined(GD32F30X_HD) || defined(GD32F30X_XD)) +#define DAC_TRIGGER_T7_TRGO CTL_DTSEL(1) /*!< TIMER7 TRGO */ +#elif defined(GD32F30X_CL) +#define DAC_TRIGGER_T2_TRGO CTL_DTSEL(1) /*!< TIMER2 TRGO */ +#endif /* GD32F30X_HD and GD32F30X_XD */ +#define DAC_TRIGGER_T6_TRGO CTL_DTSEL(2) /*!< TIMER6 TRGO */ +#define DAC_TRIGGER_T4_TRGO CTL_DTSEL(3) /*!< TIMER4 TRGO */ +#define DAC_TRIGGER_T1_TRGO CTL_DTSEL(4) /*!< TIMER1 TRGO */ +#define DAC_TRIGGER_T3_TRGO CTL_DTSEL(5) /*!< TIMER3 TRGO */ +#define DAC_TRIGGER_EXTI_9 CTL_DTSEL(6) /*!< EXTI interrupt line9 event */ +#define DAC_TRIGGER_SOFTWARE CTL_DTSEL(7) /*!< software trigger */ + +/* DAC noise wave mode */ +#define CTL_DWM(regval) (BITS(6,7) & ((uint32_t)(regval) << 6)) +#define DAC_WAVE_DISABLE CTL_DWM(0) /*!< wave disable */ +#define DAC_WAVE_MODE_LFSR CTL_DWM(1) /*!< LFSR noise mode */ +#define DAC_WAVE_MODE_TRIANGLE CTL_DWM(2) /*!< triangle noise mode */ + +/* DAC noise wave bit width */ +#define DWBW(regval) (BITS(8,11) & ((uint32_t)(regval) << 8)) +#define DAC_WAVE_BIT_WIDTH_1 DWBW(0) /*!< bit width of the wave signal is 1 */ +#define DAC_WAVE_BIT_WIDTH_2 DWBW(1) /*!< bit width of the wave signal is 2 */ +#define DAC_WAVE_BIT_WIDTH_3 DWBW(2) /*!< bit width of the wave signal is 3 */ +#define DAC_WAVE_BIT_WIDTH_4 DWBW(3) /*!< bit width of the wave signal is 4 */ +#define DAC_WAVE_BIT_WIDTH_5 DWBW(4) /*!< bit width of the wave signal is 5 */ +#define DAC_WAVE_BIT_WIDTH_6 DWBW(5) /*!< bit width of the wave signal is 6 */ +#define DAC_WAVE_BIT_WIDTH_7 DWBW(6) /*!< bit width of the wave signal is 7 */ +#define DAC_WAVE_BIT_WIDTH_8 DWBW(7) /*!< bit width of the wave signal is 8 */ +#define DAC_WAVE_BIT_WIDTH_9 DWBW(8) /*!< bit width of the wave signal is 9 */ +#define DAC_WAVE_BIT_WIDTH_10 DWBW(9) /*!< bit width of the wave signal is 10 */ +#define DAC_WAVE_BIT_WIDTH_11 DWBW(10) /*!< bit width of the wave signal is 11 */ +#define DAC_WAVE_BIT_WIDTH_12 DWBW(11) /*!< bit width of the wave signal is 12 */ + +/* unmask LFSR bits in DAC LFSR noise mode */ +#define DAC_LFSR_BIT0 DAC_WAVE_BIT_WIDTH_1 /*!< unmask the LFSR bit0 */ +#define DAC_LFSR_BITS1_0 DAC_WAVE_BIT_WIDTH_2 /*!< unmask the LFSR bits[1:0] */ +#define DAC_LFSR_BITS2_0 DAC_WAVE_BIT_WIDTH_3 /*!< unmask the LFSR bits[2:0] */ +#define DAC_LFSR_BITS3_0 DAC_WAVE_BIT_WIDTH_4 /*!< unmask the LFSR bits[3:0] */ +#define DAC_LFSR_BITS4_0 DAC_WAVE_BIT_WIDTH_5 /*!< unmask the LFSR bits[4:0] */ +#define DAC_LFSR_BITS5_0 DAC_WAVE_BIT_WIDTH_6 /*!< unmask the LFSR bits[5:0] */ +#define DAC_LFSR_BITS6_0 DAC_WAVE_BIT_WIDTH_7 /*!< unmask the LFSR bits[6:0] */ +#define DAC_LFSR_BITS7_0 DAC_WAVE_BIT_WIDTH_8 /*!< unmask the LFSR bits[7:0] */ +#define DAC_LFSR_BITS8_0 DAC_WAVE_BIT_WIDTH_9 /*!< unmask the LFSR bits[8:0] */ +#define DAC_LFSR_BITS9_0 DAC_WAVE_BIT_WIDTH_10 /*!< unmask the LFSR bits[9:0] */ +#define DAC_LFSR_BITS10_0 DAC_WAVE_BIT_WIDTH_11 /*!< unmask the LFSR bits[10:0] */ +#define DAC_LFSR_BITS11_0 DAC_WAVE_BIT_WIDTH_12 /*!< unmask the LFSR bits[11:0] */ + +/* DAC data alignment */ +#define DATA_ALIGN(regval) (BITS(0,1) & ((uint32_t)(regval) << 0)) +#define DAC_ALIGN_12B_R DATA_ALIGN(0) /*!< data right 12 bit alignment */ +#define DAC_ALIGN_12B_L DATA_ALIGN(1) /*!< data left 12 bit alignment */ +#define DAC_ALIGN_8B_R DATA_ALIGN(2) /*!< data right 8 bit alignment */ + +/* triangle amplitude in DAC triangle noise mode */ +#define DAC_TRIANGLE_AMPLITUDE_1 DAC_WAVE_BIT_WIDTH_1 /*!< triangle amplitude is 1 */ +#define DAC_TRIANGLE_AMPLITUDE_3 DAC_WAVE_BIT_WIDTH_2 /*!< triangle amplitude is 3 */ +#define DAC_TRIANGLE_AMPLITUDE_7 DAC_WAVE_BIT_WIDTH_3 /*!< triangle amplitude is 7 */ +#define DAC_TRIANGLE_AMPLITUDE_15 DAC_WAVE_BIT_WIDTH_4 /*!< triangle amplitude is 15 */ +#define DAC_TRIANGLE_AMPLITUDE_31 DAC_WAVE_BIT_WIDTH_5 /*!< triangle amplitude is 31 */ +#define DAC_TRIANGLE_AMPLITUDE_63 DAC_WAVE_BIT_WIDTH_6 /*!< triangle amplitude is 63 */ +#define DAC_TRIANGLE_AMPLITUDE_127 DAC_WAVE_BIT_WIDTH_7 /*!< triangle amplitude is 127 */ +#define DAC_TRIANGLE_AMPLITUDE_255 DAC_WAVE_BIT_WIDTH_8 /*!< triangle amplitude is 255 */ +#define DAC_TRIANGLE_AMPLITUDE_511 DAC_WAVE_BIT_WIDTH_9 /*!< triangle amplitude is 511 */ +#define DAC_TRIANGLE_AMPLITUDE_1023 DAC_WAVE_BIT_WIDTH_10 /*!< triangle amplitude is 1023 */ +#define DAC_TRIANGLE_AMPLITUDE_2047 DAC_WAVE_BIT_WIDTH_11 /*!< triangle amplitude is 2047 */ +#define DAC_TRIANGLE_AMPLITUDE_4095 DAC_WAVE_BIT_WIDTH_12 /*!< triangle amplitude is 4095 */ + +/* function declarations */ +/* initialization functions */ +/* deinitialize DAC */ +void dac_deinit(void); +/* enable DAC */ +void dac_enable(uint32_t dac_periph); +/* disable DAC */ +void dac_disable(uint32_t dac_periph); +/* enable DAC DMA */ +void dac_dma_enable(uint32_t dac_periph); +/* disable DAC DMA */ +void dac_dma_disable(uint32_t dac_periph); +/* enable DAC output buffer */ +void dac_output_buffer_enable(uint32_t dac_periph); +/* disable DAC output buffer */ +void dac_output_buffer_disable(uint32_t dac_periph); +/* get the last data output value */ +uint16_t dac_output_value_get(uint32_t dac_periph); +/* set DAC data holding register value */ +void dac_data_set(uint32_t dac_periph, uint32_t dac_align, uint16_t data); + +/* DAC trigger configuration */ +/* enable DAC trigger */ +void dac_trigger_enable(uint32_t dac_periph); +/* disable DAC trigger */ +void dac_trigger_disable(uint32_t dac_periph); +/* configure DAC trigger source */ +void dac_trigger_source_config(uint32_t dac_periph, uint32_t triggersource); +/* enable DAC software trigger */ +void dac_software_trigger_enable(uint32_t dac_periph); +/* disable DAC software trigger */ +void dac_software_trigger_disable(uint32_t dac_periph); + +/* DAC wave mode configuration */ +/* configure DAC wave mode */ +void dac_wave_mode_config(uint32_t dac_periph, uint32_t wave_mode); +/* configure DAC wave bit width */ +void dac_wave_bit_width_config(uint32_t dac_periph, uint32_t bit_width); +/* configure DAC LFSR noise mode */ +void dac_lfsr_noise_config(uint32_t dac_periph, uint32_t unmask_bits); +/* configure DAC triangle noise mode */ +void dac_triangle_noise_config(uint32_t dac_periph, uint32_t amplitude); + +/* DAC concurrent mode configuration */ +/* enable DAC concurrent mode */ +void dac_concurrent_enable(void); +/* disable DAC concurrent mode */ +void dac_concurrent_disable(void); +/* enable DAC concurrent software trigger */ +void dac_concurrent_software_trigger_enable(void); +/* disable DAC concurrent software trigger */ +void dac_concurrent_software_trigger_disable(void); +/* enable DAC concurrent buffer function */ +void dac_concurrent_output_buffer_enable(void); +/* disable DAC concurrent buffer function */ +void dac_concurrent_output_buffer_disable(void); +/* set DAC concurrent mode data holding register value */ +void dac_concurrent_data_set(uint32_t dac_align, uint16_t data0, uint16_t data1); + +#endif /* GD32F30X_DAC_H */ diff --git a/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_standard_peripheral/Include/gd32f30x_dbg.h b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_standard_peripheral/Include/gd32f30x_dbg.h new file mode 100644 index 0000000000..7129eacc16 --- /dev/null +++ b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_standard_peripheral/Include/gd32f30x_dbg.h @@ -0,0 +1,158 @@ +/*! + \file gd32f30x_dbg.h + \brief definitions for the DBG + + \version 2017-02-10, V1.0.0, firmware for GD32F30x + \version 2018-10-10, V1.1.0, firmware for GD32F30x + \version 2018-12-25, V2.0.0, firmware for GD32F30x + \version 2020-09-30, V2.1.0, firmware for GD32F30x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef GD32F30X_DBG_H +#define GD32F30X_DBG_H + +#include "gd32f30x.h" + +/* DBG definitions */ +#define DBG DBG_BASE + +/* registers definitions */ +#define DBG_ID REG32(DBG + 0x00U) /*!< DBG_ID code register */ +#define DBG_CTL0 REG32(DBG + 0x04U) /*!< DBG control register 0 */ + +/* bits definitions */ +/* DBG_ID */ +#define DBG_ID_ID_CODE BITS(0,31) /*!< DBG ID code values */ + +/* DBG_CTL0 */ +#define DBG_CTL0_SLP_HOLD BIT(0) /*!< keep debugger connection during sleep mode */ +#define DBG_CTL0_DSLP_HOLD BIT(1) /*!< keep debugger connection during deepsleep mode */ +#define DBG_CTL0_STB_HOLD BIT(2) /*!< keep debugger connection during standby mode */ +#define DBG_CTL0_TRACE_IOEN BIT(5) /*!< enable trace pin assignment */ +#define DBG_CTL0_TRACE_MODE BITS(6,7) /*!< trace pin mode selection */ +#define DBG_CTL0_FWDGT_HOLD BIT(8) /*!< debug FWDGT kept when core is halted */ +#define DBG_CTL0_WWDGT_HOLD BIT(9) /*!< debug WWDGT kept when core is halted */ +#define DBG_CTL0_TIMER0_HOLD BIT(10) /*!< hold TIMER0 counter when core is halted */ +#define DBG_CTL0_TIMER1_HOLD BIT(11) /*!< hold TIMER1 counter when core is halted */ +#define DBG_CTL0_TIMER2_HOLD BIT(12) /*!< hold TIMER2 counter when core is halted */ +#define DBG_CTL0_TIMER3_HOLD BIT(13) /*!< hold TIMER3 counter when core is halted */ +#define DBG_CTL0_CAN0_HOLD BIT(14) /*!< debug CAN0 kept when core is halted */ +#define DBG_CTL0_I2C0_HOLD BIT(15) /*!< hold I2C0 smbus when core is halted */ +#define DBG_CTL0_I2C1_HOLD BIT(16) /*!< hold I2C1 smbus when core is halted */ +#define DBG_CTL0_TIMER7_HOLD BIT(17) /*!< hold TIMER7 counter when core is halted */ +#define DBG_CTL0_TIMER4_HOLD BIT(18) /*!< hold TIMER4 counter when core is halted */ +#define DBG_CTL0_TIMER5_HOLD BIT(19) /*!< hold TIMER5 counter when core is halted */ +#define DBG_CTL0_TIMER6_HOLD BIT(20) /*!< hold TIMER6 counter when core is halted */ +#ifdef GD32F30X_CL +#define DBG_CTL0_CAN1_HOLD BIT(21) /*!< debug CAN1 kept when core is halted */ +#endif /* GD32F30X_CL */ +#ifndef GD32F30X_HD +#define DBG_CTL0_TIMER11_HOLD BIT(25) /*!< hold TIMER11 counter when core is halted */ +#define DBG_CTL0_TIMER12_HOLD BIT(26) /*!< hold TIMER12 counter when core is halted */ +#define DBG_CTL0_TIMER13_HOLD BIT(27) /*!< hold TIMER13 counter when core is halted */ +#define DBG_CTL0_TIMER8_HOLD BIT(28) /*!< hold TIMER8 counter when core is halted */ +#define DBG_CTL0_TIMER9_HOLD BIT(29) /*!< hold TIMER9 counter when core is halted */ +#define DBG_CTL0_TIMER10_HOLD BIT(30) /*!< hold TIMER10 counter when core is halted */ +#endif /* GD32F30X_HD */ + +/* constants definitions */ +#define DBG_LOW_POWER_SLEEP DBG_CTL0_SLP_HOLD /*!< keep debugger connection during sleep mode */ +#define DBG_LOW_POWER_DEEPSLEEP DBG_CTL0_DSLP_HOLD /*!< keep debugger connection during deepsleep mode */ +#define DBG_LOW_POWER_STANDBY DBG_CTL0_STB_HOLD /*!< keep debugger connection during standby mode */ + +/* define the peripheral debug hold bit position and its register index offset */ +#define DBG_REGIDX_BIT(regidx, bitpos) (((regidx) << 6) | (bitpos)) +#define DBG_REG_VAL(periph) (REG32(DBG + ((uint32_t)(periph) >> 6))) +#define DBG_BIT_POS(val) ((uint32_t)(val) & 0x1FU) + +/* register index */ +enum dbg_reg_idx +{ + DBG_IDX_CTL0 = 0x04U +}; + +typedef enum +{ + DBG_FWDGT_HOLD = DBG_REGIDX_BIT(DBG_IDX_CTL0, 8U), /*!< debug FWDGT kept when core is halted */ + DBG_WWDGT_HOLD = DBG_REGIDX_BIT(DBG_IDX_CTL0, 9U), /*!< debug WWDGT kept when core is halted */ + DBG_TIMER0_HOLD = DBG_REGIDX_BIT(DBG_IDX_CTL0, 10U), /*!< hold TIMER0 counter when core is halted */ + DBG_TIMER1_HOLD = DBG_REGIDX_BIT(DBG_IDX_CTL0, 11U), /*!< hold TIMER1 counter when core is halted */ + DBG_TIMER2_HOLD = DBG_REGIDX_BIT(DBG_IDX_CTL0, 12U), /*!< hold TIMER2 counter when core is halted */ + DBG_TIMER3_HOLD = DBG_REGIDX_BIT(DBG_IDX_CTL0, 13U), /*!< hold TIMER3 counter when core is halted */ + DBG_CAN0_HOLD = DBG_REGIDX_BIT(DBG_IDX_CTL0, 14U), /*!< debug CAN0 kept when core is halted */ + DBG_I2C0_HOLD = DBG_REGIDX_BIT(DBG_IDX_CTL0, 15U), /*!< hold I2C0 smbus when core is halted */ + DBG_I2C1_HOLD = DBG_REGIDX_BIT(DBG_IDX_CTL0, 16U), /*!< hold I2C1 smbus when core is halted */ + DBG_TIMER7_HOLD = DBG_REGIDX_BIT(DBG_IDX_CTL0, 17U), /*!< hold TIMER7 counter when core is halted */ + DBG_TIMER4_HOLD = DBG_REGIDX_BIT(DBG_IDX_CTL0, 18U), /*!< hold TIMER4 counter when core is halted */ + DBG_TIMER5_HOLD = DBG_REGIDX_BIT(DBG_IDX_CTL0, 19U), /*!< hold TIMER5 counter when core is halted */ + DBG_TIMER6_HOLD = DBG_REGIDX_BIT(DBG_IDX_CTL0, 20U), /*!< hold TIMER6 counter when core is halted */ +#ifdef GD32F30X_CL + DBG_CAN1_HOLD = DBG_REGIDX_BIT(DBG_IDX_CTL0, 21U), /*!< debug CAN1 kept when core is halted */ +#endif /* GD32F30X_CL */ +#ifndef GD32F30X_HD + DBG_TIMER11_HOLD = DBG_REGIDX_BIT(DBG_IDX_CTL0, 25U), /*!< hold TIMER11 counter when core is halted */ + DBG_TIMER12_HOLD = DBG_REGIDX_BIT(DBG_IDX_CTL0, 26U), /*!< hold TIMER12 counter when core is halted */ + DBG_TIMER13_HOLD = DBG_REGIDX_BIT(DBG_IDX_CTL0, 27U), /*!< hold TIMER13 counter when core is halted */ + DBG_TIMER8_HOLD = DBG_REGIDX_BIT(DBG_IDX_CTL0, 28U), /*!< hold TIMER8 counter when core is halted */ + DBG_TIMER9_HOLD = DBG_REGIDX_BIT(DBG_IDX_CTL0, 29U), /*!< hold TIMER9 counter when core is halted */ + DBG_TIMER10_HOLD = DBG_REGIDX_BIT(DBG_IDX_CTL0, 30U), /*!< hold TIMER10 counter when core is halted */ +#endif /* GD32F30X_HD */ +}dbg_periph_enum; + +#define CTL0_TRACE_MODE(regval) (BITS(6,7)&((uint32_t)(regval)<<6)) +#define TRACE_MODE_ASYNC CTL0_TRACE_MODE(0) /*!< trace pin used for async mode */ +#define TRACE_MODE_SYNC_DATASIZE_1 CTL0_TRACE_MODE(1) /*!< trace pin used for sync mode and data size is 1 */ +#define TRACE_MODE_SYNC_DATASIZE_2 CTL0_TRACE_MODE(2) /*!< trace pin used for sync mode and data size is 2 */ +#define TRACE_MODE_SYNC_DATASIZE_4 CTL0_TRACE_MODE(3) /*!< trace pin used for sync mode and data size is 4 */ + +/* function declarations */ +/* deinitialize the DBG */ +void dbg_deinit(void); +/* read DBG_ID code register */ +uint32_t dbg_id_get(void); + +/* enable low power behavior when the MCU is in debug mode */ +void dbg_low_power_enable(uint32_t dbg_low_power); +/* disable low power behavior when the MCU is in debug mode */ +void dbg_low_power_disable(uint32_t dbg_low_power); + +/* enable peripheral behavior when the MCU is in debug mode */ +void dbg_periph_enable(dbg_periph_enum dbg_periph); +/* disable peripheral behavior when the MCU is in debug mode */ +void dbg_periph_disable(dbg_periph_enum dbg_periph); + +/* enable trace pin assignment */ +void dbg_trace_pin_enable(void); +/* disable trace pin assignment */ +void dbg_trace_pin_disable(void); +/* set trace pin mode */ +void dbg_trace_pin_mode_set(uint32_t trace_mode); + +#endif /* GD32F30X_DBG_H */ diff --git a/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_standard_peripheral/Include/gd32f30x_dma.h b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_standard_peripheral/Include/gd32f30x_dma.h new file mode 100644 index 0000000000..73b1a516fe --- /dev/null +++ b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_standard_peripheral/Include/gd32f30x_dma.h @@ -0,0 +1,285 @@ +/*! + \file gd32f30x_dma.h + \brief definitions for the DMA + + \version 2017-02-10, V1.0.0, firmware for GD32F30x + \version 2018-10-10, V1.1.0, firmware for GD32F30x + \version 2018-12-25, V2.0.0, firmware for GD32F30x + \version 2020-09-30, V2.1.0, firmware for GD32F30x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef GD32F30X_DMA_H +#define GD32F30X_DMA_H + +#include "gd32f30x.h" + +/* DMA definitions */ +#define DMA0 (DMA_BASE) /*!< DMA0 base address */ +#define DMA1 (DMA_BASE + 0x0400U) /*!< DMA1 base address */ + +/* registers definitions */ +#define DMA_INTF(dmax) REG32((dmax) + 0x00U) /*!< DMA interrupt flag register */ +#define DMA_INTC(dmax) REG32((dmax) + 0x04U) /*!< DMA interrupt flag clear register */ + +#define DMA_CH0CTL(dmax) REG32((dmax) + 0x08U) /*!< DMA channel 0 control register */ +#define DMA_CH0CNT(dmax) REG32((dmax) + 0x0CU) /*!< DMA channel 0 counter register */ +#define DMA_CH0PADDR(dmax) REG32((dmax) + 0x10U) /*!< DMA channel 0 peripheral base address register */ +#define DMA_CH0MADDR(dmax) REG32((dmax) + 0x14U) /*!< DMA channel 0 memory base address register */ + +#define DMA_CH1CTL(dmax) REG32((dmax) + 0x1CU) /*!< DMA channel 1 control register */ +#define DMA_CH1CNT(dmax) REG32((dmax) + 0x20U) /*!< DMA channel 1 counter register */ +#define DMA_CH1PADDR(dmax) REG32((dmax) + 0x24U) /*!< DMA channel 1 peripheral base address register */ +#define DMA_CH1MADDR(dmax) REG32((dmax) + 0x28U) /*!< DMA channel 1 memory base address register */ + +#define DMA_CH2CTL(dmax) REG32((dmax) + 0x30U) /*!< DMA channel 2 control register */ +#define DMA_CH2CNT(dmax) REG32((dmax) + 0x34U) /*!< DMA channel 2 counter register */ +#define DMA_CH2PADDR(dmax) REG32((dmax) + 0x38U) /*!< DMA channel 2 peripheral base address register */ +#define DMA_CH2MADDR(dmax) REG32((dmax) + 0x3CU) /*!< DMA channel 2 memory base address register */ + +#define DMA_CH3CTL(dmax) REG32((dmax) + 0x44U) /*!< DMA channel 3 control register */ +#define DMA_CH3CNT(dmax) REG32((dmax) + 0x48U) /*!< DMA channel 3 counter register */ +#define DMA_CH3PADDR(dmax) REG32((dmax) + 0x4CU) /*!< DMA channel 3 peripheral base address register */ +#define DMA_CH3MADDR(dmax) REG32((dmax) + 0x50U) /*!< DMA channel 3 memory base address register */ + +#define DMA_CH4CTL(dmax) REG32((dmax) + 0x58U) /*!< DMA channel 4 control register */ +#define DMA_CH4CNT(dmax) REG32((dmax) + 0x5CU) /*!< DMA channel 4 counter register */ +#define DMA_CH4PADDR(dmax) REG32((dmax) + 0x60U) /*!< DMA channel 4 peripheral base address register */ +#define DMA_CH4MADDR(dmax) REG32((dmax) + 0x64U) /*!< DMA channel 4 memory base address register */ + +#define DMA_CH5CTL(dmax) REG32((dmax) + 0x6CU) /*!< DMA channel 5 control register */ +#define DMA_CH5CNT(dmax) REG32((dmax) + 0x70U) /*!< DMA channel 5 counter register */ +#define DMA_CH5PADDR(dmax) REG32((dmax) + 0x74U) /*!< DMA channel 5 peripheral base address register */ +#define DMA_CH5MADDR(dmax) REG32((dmax) + 0x78U) /*!< DMA channel 5 memory base address register */ + +#define DMA_CH6CTL(dmax) REG32((dmax) + 0x80U) /*!< DMA channel 6 control register */ +#define DMA_CH6CNT(dmax) REG32((dmax) + 0x84U) /*!< DMA channel 6 counter register */ +#define DMA_CH6PADDR(dmax) REG32((dmax) + 0x88U) /*!< DMA channel 6 peripheral base address register */ +#define DMA_CH6MADDR(dmax) REG32((dmax) + 0x8CU) /*!< DMA channel 6 memory base address register */ + +/* bits definitions */ +/* DMA_INTF */ +#define DMA_INTF_GIF BIT(0) /*!< global interrupt flag of channel */ +#define DMA_INTF_FTFIF BIT(1) /*!< full transfer finish flag of channel */ +#define DMA_INTF_HTFIF BIT(2) /*!< half transfer finish flag of channel */ +#define DMA_INTF_ERRIF BIT(3) /*!< error flag of channel */ + +/* DMA_INTC */ +#define DMA_INTC_GIFC BIT(0) /*!< clear global interrupt flag of channel */ +#define DMA_INTC_FTFIFC BIT(1) /*!< clear transfer finish flag of channel */ +#define DMA_INTC_HTFIFC BIT(2) /*!< clear half transfer finish flag of channel */ +#define DMA_INTC_ERRIFC BIT(3) /*!< clear error flag of channel */ + +/* DMA_CHxCTL, x=0..6 */ +#define DMA_CHXCTL_CHEN BIT(0) /*!< channel enable */ +#define DMA_CHXCTL_FTFIE BIT(1) /*!< enable bit for channel full transfer finish interrupt */ +#define DMA_CHXCTL_HTFIE BIT(2) /*!< enable bit for channel half transfer finish interrupt */ +#define DMA_CHXCTL_ERRIE BIT(3) /*!< enable bit for channel error interrupt */ +#define DMA_CHXCTL_DIR BIT(4) /*!< transfer direction */ +#define DMA_CHXCTL_CMEN BIT(5) /*!< circular mode enable */ +#define DMA_CHXCTL_PNAGA BIT(6) /*!< next address generation algorithm of peripheral */ +#define DMA_CHXCTL_MNAGA BIT(7) /*!< next address generation algorithm of memory */ +#define DMA_CHXCTL_PWIDTH BITS(8,9) /*!< transfer data width of peripheral */ +#define DMA_CHXCTL_MWIDTH BITS(10,11) /*!< transfer data width of memory */ +#define DMA_CHXCTL_PRIO BITS(12,13) /*!< priority level */ +#define DMA_CHXCTL_M2M BIT(14) /*!< memory to memory mode */ + +/* DMA_CHxCNT,x=0..6 */ +#define DMA_CHXCNT_CNT BITS(0,15) /*!< transfer counter */ + +/* DMA_CHxPADDR,x=0..6 */ +#define DMA_CHXPADDR_PADDR BITS(0,31) /*!< peripheral base address */ + +/* DMA_CHxMADDR,x=0..6 */ +#define DMA_CHXMADDR_MADDR BITS(0,31) /*!< memory base address */ + +/* constants definitions */ +/* DMA channel select */ +typedef enum +{ + DMA_CH0 = 0, /*!< DMA Channel0 */ + DMA_CH1, /*!< DMA Channel1 */ + DMA_CH2, /*!< DMA Channel2 */ + DMA_CH3, /*!< DMA Channel3 */ + DMA_CH4, /*!< DMA Channel4 */ + DMA_CH5, /*!< DMA Channel5 */ + DMA_CH6 /*!< DMA Channel6 */ +} dma_channel_enum; + +/* DMA initialize struct */ +typedef struct +{ + uint32_t periph_addr; /*!< peripheral base address */ + uint32_t periph_width; /*!< transfer data size of peripheral */ + uint32_t memory_addr; /*!< memory base address */ + uint32_t memory_width; /*!< transfer data size of memory */ + uint32_t number; /*!< channel transfer number */ + uint32_t priority; /*!< channel priority level */ + uint8_t periph_inc; /*!< peripheral increasing mode */ + uint8_t memory_inc; /*!< memory increasing mode */ + uint8_t direction; /*!< channel data transfer direction */ + +} dma_parameter_struct; + +#define DMA_FLAG_ADD(flag, shift) ((flag) << ((shift) * 4U)) /*!< DMA channel flag shift */ + +/* DMA_register address */ +#define DMA_CHCTL(dma, channel) REG32(((dma) + 0x08U) + 0x14U * (uint32_t)(channel)) /*!< the address of DMA channel CHXCTL register */ +#define DMA_CHCNT(dma, channel) REG32(((dma) + 0x0CU) + 0x14U * (uint32_t)(channel)) /*!< the address of DMA channel CHXCNT register */ +#define DMA_CHPADDR(dma, channel) REG32(((dma) + 0x10U) + 0x14U * (uint32_t)(channel)) /*!< the address of DMA channel CHXPADDR register */ +#define DMA_CHMADDR(dma, channel) REG32(((dma) + 0x14U) + 0x14U * (uint32_t)(channel)) /*!< the address of DMA channel CHXMADDR register */ + +/* DMA reset value */ +#define DMA_CHCTL_RESET_VALUE ((uint32_t)0x00000000U) /*!< the reset value of DMA channel CHXCTL register */ +#define DMA_CHCNT_RESET_VALUE ((uint32_t)0x00000000U) /*!< the reset value of DMA channel CHXCNT register */ +#define DMA_CHPADDR_RESET_VALUE ((uint32_t)0x00000000U) /*!< the reset value of DMA channel CHXPADDR register */ +#define DMA_CHMADDR_RESET_VALUE ((uint32_t)0x00000000U) /*!< the reset value of DMA channel CHXMADDR register */ +#define DMA_CHINTF_RESET_VALUE (DMA_INTF_GIF | DMA_INTF_FTFIF | \ + DMA_INTF_HTFIF | DMA_INTF_ERRIF) /*!< clear DMA channel DMA_INTF register */ + +/* DMA_INTF register */ +/* interrupt flag bits */ +#define DMA_INT_FLAG_G DMA_INTF_GIF /*!< global interrupt flag of channel */ +#define DMA_INT_FLAG_FTF DMA_INTF_FTFIF /*!< full transfer finish interrupt flag of channel */ +#define DMA_INT_FLAG_HTF DMA_INTF_HTFIF /*!< half transfer finish interrupt flag of channel */ +#define DMA_INT_FLAG_ERR DMA_INTF_ERRIF /*!< error interrupt flag of channel */ + +/* flag bits */ +#define DMA_FLAG_G DMA_INTF_GIF /*!< global interrupt flag of channel */ +#define DMA_FLAG_FTF DMA_INTF_FTFIF /*!< full transfer finish flag of channel */ +#define DMA_FLAG_HTF DMA_INTF_HTFIF /*!< half transfer finish flag of channel */ +#define DMA_FLAG_ERR DMA_INTF_ERRIF /*!< error flag of channel */ + +/* DMA_CHxCTL register */ +/* interrupt enable bits */ +#define DMA_INT_FTF DMA_CHXCTL_FTFIE /*!< enable bit for channel full transfer finish interrupt */ +#define DMA_INT_HTF DMA_CHXCTL_HTFIE /*!< enable bit for channel half transfer finish interrupt */ +#define DMA_INT_ERR DMA_CHXCTL_ERRIE /*!< enable bit for channel error interrupt */ + +/* transfer direction */ +#define DMA_PERIPHERAL_TO_MEMORY ((uint8_t)0x0000U) /*!< read from peripheral and write to memory */ +#define DMA_MEMORY_TO_PERIPHERAL ((uint8_t)0x0001U) /*!< read from memory and write to peripheral */ + +/* peripheral increasing mode */ +#define DMA_PERIPH_INCREASE_DISABLE ((uint8_t)0x0000U) /*!< next address of peripheral is fixed address mode */ +#define DMA_PERIPH_INCREASE_ENABLE ((uint8_t)0x0001U) /*!< next address of peripheral is increasing address mode */ + +/* memory increasing mode */ +#define DMA_MEMORY_INCREASE_DISABLE ((uint8_t)0x0000U) /*!< next address of memory is fixed address mode */ +#define DMA_MEMORY_INCREASE_ENABLE ((uint8_t)0x0001U) /*!< next address of memory is increasing address mode */ + +/* transfer data size of peripheral */ +#define CHCTL_PWIDTH(regval) (BITS(8,9) & ((uint32_t)(regval) << 8)) /*!< transfer data size of peripheral */ +#define DMA_PERIPHERAL_WIDTH_8BIT CHCTL_PWIDTH(0) /*!< transfer data size of peripheral is 8-bit */ +#define DMA_PERIPHERAL_WIDTH_16BIT CHCTL_PWIDTH(1) /*!< transfer data size of peripheral is 16-bit */ +#define DMA_PERIPHERAL_WIDTH_32BIT CHCTL_PWIDTH(2) /*!< transfer data size of peripheral is 32-bit */ + +/* transfer data size of memory */ +#define CHCTL_MWIDTH(regval) (BITS(10,11) & ((uint32_t)(regval) << 10)) /*!< transfer data size of memory */ +#define DMA_MEMORY_WIDTH_8BIT CHCTL_MWIDTH(0) /*!< transfer data size of memory is 8-bit */ +#define DMA_MEMORY_WIDTH_16BIT CHCTL_MWIDTH(1) /*!< transfer data size of memory is 16-bit */ +#define DMA_MEMORY_WIDTH_32BIT CHCTL_MWIDTH(2) /*!< transfer data size of memory is 32-bit */ + +/* channel priority level */ +#define CHCTL_PRIO(regval) (BITS(12,13) & ((uint32_t)(regval) << 12)) /*!< DMA channel priority level */ +#define DMA_PRIORITY_LOW CHCTL_PRIO(0) /*!< low priority */ +#define DMA_PRIORITY_MEDIUM CHCTL_PRIO(1) /*!< medium priority */ +#define DMA_PRIORITY_HIGH CHCTL_PRIO(2) /*!< high priority */ +#define DMA_PRIORITY_ULTRA_HIGH CHCTL_PRIO(3) /*!< ultra high priority */ + +/* memory to memory mode */ +#define DMA_MEMORY_TO_MEMORY_DISABLE ((uint32_t)0x00000000U) +#define DMA_MEMORY_TO_MEMORY_ENABLE ((uint32_t)0x00000001U) + +/* DMA_CHxCNT register */ +/* transfer counter */ +#define DMA_CHANNEL_CNT_MASK DMA_CHXCNT_CNT /*!< transfer counter mask */ + +/* function declarations */ +/* DMA deinitialization and initialization functions */ +/* deinitialize DMA a channel registers */ +void dma_deinit(uint32_t dma_periph, dma_channel_enum channelx); +/* initialize the parameters of DMA struct with the default values */ +void dma_struct_para_init(dma_parameter_struct* init_struct); +/* initialize DMA channel */ +void dma_init(uint32_t dma_periph, dma_channel_enum channelx, dma_parameter_struct* init_struct); +/* enable DMA circulation mode */ +void dma_circulation_enable(uint32_t dma_periph, dma_channel_enum channelx); +/* disable DMA circulation mode */ +void dma_circulation_disable(uint32_t dma_periph, dma_channel_enum channelx); +/* enable memory to memory mode */ +void dma_memory_to_memory_enable(uint32_t dma_periph, dma_channel_enum channelx); +/* disable memory to memory mode */ +void dma_memory_to_memory_disable(uint32_t dma_periph, dma_channel_enum channelx); +/* enable DMA channel */ +void dma_channel_enable(uint32_t dma_periph, dma_channel_enum channelx); +/* disable DMA channel */ +void dma_channel_disable(uint32_t dma_periph, dma_channel_enum channelx); + +/* DMA configuration functions */ +/* set DMA peripheral base address */ +void dma_periph_address_config(uint32_t dma_periph, dma_channel_enum channelx, uint32_t address); +/* set DMA memory base address */ +void dma_memory_address_config(uint32_t dma_periph, dma_channel_enum channelx, uint32_t address); +/* set the number of remaining data to be transferred by the DMA */ +void dma_transfer_number_config(uint32_t dma_periph, dma_channel_enum channelx, uint32_t number); +/* get the number of remaining data to be transferred by the DMA */ +uint32_t dma_transfer_number_get(uint32_t dma_periph, dma_channel_enum channelx); +/* configure priority level of DMA channel */ +void dma_priority_config(uint32_t dma_periph, dma_channel_enum channelx, uint32_t priority); +/* configure transfer data size of memory */ +void dma_memory_width_config(uint32_t dma_periph, dma_channel_enum channelx, uint32_t mwidth); +/* configure transfer data size of peripheral */ +void dma_periph_width_config (uint32_t dma_periph, dma_channel_enum channelx, uint32_t pwidth); +/* enable next address increasement algorithm of memory */ +void dma_memory_increase_enable(uint32_t dma_periph, dma_channel_enum channelx); +/* disable next address increasement algorithm of memory */ +void dma_memory_increase_disable(uint32_t dma_periph, dma_channel_enum channelx); +/* enable next address increasement algorithm of peripheral */ +void dma_periph_increase_enable(uint32_t dma_periph, dma_channel_enum channelx); +/* disable next address increasement algorithm of peripheral */ +void dma_periph_increase_disable(uint32_t dma_periph, dma_channel_enum channelx); +/* configure the direction of data transfer on the channel */ +void dma_transfer_direction_config(uint32_t dma_periph, dma_channel_enum channelx, uint32_t direction); + +/* flag and interrupt functions */ +/* check DMA flag is set or not */ +FlagStatus dma_flag_get(uint32_t dma_periph, dma_channel_enum channelx, uint32_t flag); +/* clear DMA a channel flag */ +void dma_flag_clear(uint32_t dma_periph, dma_channel_enum channelx, uint32_t flag); +/* check DMA flag and interrupt enable bit is set or not */ +FlagStatus dma_interrupt_flag_get(uint32_t dma_periph, dma_channel_enum channelx, uint32_t flag); +/* clear DMA a channel flag */ +void dma_interrupt_flag_clear(uint32_t dma_periph, dma_channel_enum channelx, uint32_t flag); +/* enable DMA interrupt */ +void dma_interrupt_enable(uint32_t dma_periph, dma_channel_enum channelx, uint32_t source); +/* disable DMA interrupt */ +void dma_interrupt_disable(uint32_t dma_periph, dma_channel_enum channelx, uint32_t source); + +#endif /* GD32F30X_DMA_H */ diff --git a/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_standard_peripheral/Include/gd32f30x_enet.h b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_standard_peripheral/Include/gd32f30x_enet.h new file mode 100644 index 0000000000..1b3ca7cfdc --- /dev/null +++ b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_standard_peripheral/Include/gd32f30x_enet.h @@ -0,0 +1,1702 @@ +/*! + \file gd32f30x_enet.h + \brief definitions for the ENET + + \version 2017-02-10, V1.0.0, firmware for GD32F30x + \version 2018-10-10, V1.1.0, firmware for GD32F30x + \version 2018-12-25, V2.0.0, firmware for GD32F30x + \version 2020-04-02, V2.0.1, firmware for GD32F30x + \version 2020-09-30, V2.1.0, firmware for GD32F30x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef GD32F30X_ENET_H +#define GD32F30X_ENET_H + +#include "gd32f30x.h" + +#define IF_USE_EXTERNPHY_LIB 0 +#if (1 == IF_USE_EXTERNPHY_LIB) +#include "phy.h" +#endif + +#ifndef ENET_RXBUF_NUM +#define ENET_RXBUF_NUM 5U /*!< ethernet Rx DMA descriptor number */ +#endif + +#ifndef ENET_TXBUF_NUM +#define ENET_TXBUF_NUM 5U /*!< ethernet Tx DMA descriptor number */ +#endif + +#ifndef ENET_RXBUF_SIZE +#define ENET_RXBUF_SIZE ENET_MAX_FRAME_SIZE /*!< ethernet receive buffer size */ +#endif + +#ifndef ENET_TXBUF_SIZE +#define ENET_TXBUF_SIZE ENET_MAX_FRAME_SIZE /*!< ethernet transmit buffer size */ +#endif + +/* #define SELECT_DESCRIPTORS_ENHANCED_MODE */ + +/* #define USE_DELAY */ + +#ifndef _PHY_H_ +#define DP83848 0 +#define LAN8700 1 +#define PHY_TYPE DP83848 + +#define PHY_ADDRESS ((uint16_t)1U) /*!< phy address determined by the hardware */ + +/* PHY read write timeouts */ +#define PHY_READ_TO ((uint32_t)0x0004FFFFU) /*!< PHY read timeout */ +#define PHY_WRITE_TO ((uint32_t)0x0004FFFFU) /*!< PHY write timeout */ + +/* PHY delay */ +#define PHY_RESETDELAY ((uint32_t)0x008FFFFFU) /*!< PHY reset delay */ +#define PHY_CONFIGDELAY ((uint32_t)0x00FFFFFFU) /*!< PHY configure delay */ + +/* PHY register address */ +#define PHY_REG_BCR 0U /*!< tranceiver basic control register */ +#define PHY_REG_BSR 1U /*!< tranceiver basic status register */ + +/* PHY basic control register */ +#define PHY_RESET ((uint16_t)0x8000) /*!< PHY reset */ +#define PHY_LOOPBACK ((uint16_t)0x4000) /*!< enable phy loop-back mode */ +#define PHY_FULLDUPLEX_100M ((uint16_t)0x2100) /*!< configure speed to 100 Mbit/s and the full-duplex mode */ +#define PHY_HALFDUPLEX_100M ((uint16_t)0x2000) /*!< configure speed to 100 Mbit/s and the half-duplex mode */ +#define PHY_FULLDUPLEX_10M ((uint16_t)0x0100) /*!< configure speed to 10 Mbit/s and the full-duplex mode */ +#define PHY_HALFDUPLEX_10M ((uint16_t)0x0000) /*!< configure speed to 10 Mbit/s and the half-duplex mode */ +#define PHY_AUTONEGOTIATION ((uint16_t)0x1000) /*!< enable auto-negotiation function */ +#define PHY_RESTART_AUTONEGOTIATION ((uint16_t)0x0200) /*!< restart auto-negotiation function */ +#define PHY_POWERDOWN ((uint16_t)0x0800) /*!< enable the power down mode */ +#define PHY_ISOLATE ((uint16_t)0x0400) /*!< isolate PHY from MII */ + +/* PHY basic status register */ +#define PHY_AUTONEGO_COMPLETE ((uint16_t)0x0020) /*!< auto-negotioation process completed */ +#define PHY_LINKED_STATUS ((uint16_t)0x0004) /*!< valid link established */ +#define PHY_JABBER_DETECTION ((uint16_t)0x0002) /*!< jabber condition detected */ + +#if(PHY_TYPE == LAN8700) +#define PHY_SR 31U /*!< tranceiver status register */ +#define PHY_SPEED_STATUS ((uint16_t)0x0004) /*!< configured information of speed: 10Mbit/s */ +#define PHY_DUPLEX_STATUS ((uint16_t)0x0010) /*!< configured information of duplex: full-duplex */ +#elif(PHY_TYPE == DP83848) +#define PHY_SR 16U /*!< tranceiver status register */ +#define PHY_SPEED_STATUS ((uint16_t)0x0002) /*!< configured information of speed: 10Mbit/s */ +#define PHY_DUPLEX_STATUS ((uint16_t)0x0004) /*!< configured information of duplex: full-duplex */ +#endif /* PHY_TYPE */ + +#endif /* _PHY_H_ */ + + +/* ENET definitions */ +#define ENET ENET_BASE + +/* registers definitions */ +#define ENET_MAC_CFG REG32((ENET) + 0x00U) /*!< ethernet MAC configuration register */ +#define ENET_MAC_FRMF REG32((ENET) + 0x04U) /*!< ethernet MAC frame filter register */ +#define ENET_MAC_HLH REG32((ENET) + 0x08U) /*!< ethernet MAC hash list high register */ +#define ENET_MAC_HLL REG32((ENET) + 0x0CU) /*!< ethernet MAC hash list low register */ +#define ENET_MAC_PHY_CTL REG32((ENET) + 0x10U) /*!< ethernet MAC PHY control register */ +#define ENET_MAC_PHY_DATA REG32((ENET) + 0x14U) /*!< ethernet MAC MII data register */ +#define ENET_MAC_FCTL REG32((ENET) + 0x18U) /*!< ethernet MAC flow control register */ +#define ENET_MAC_VLT REG32((ENET) + 0x1CU) /*!< ethernet MAC VLAN tag register */ +#define ENET_MAC_RWFF REG32((ENET) + 0x28U) /*!< ethernet MAC remote wakeup frame filter register */ +#define ENET_MAC_WUM REG32((ENET) + 0x2CU) /*!< ethernet MAC wakeup management register */ +#define ENET_MAC_DBG REG32((ENET) + 0x34U) /*!< ethernet MAC debug register */ +#define ENET_MAC_INTF REG32((ENET) + 0x38U) /*!< ethernet MAC interrupt flag register */ +#define ENET_MAC_INTMSK REG32((ENET) + 0x3CU) /*!< ethernet MAC interrupt mask register */ +#define ENET_MAC_ADDR0H REG32((ENET) + 0x40U) /*!< ethernet MAC address 0 high register */ +#define ENET_MAC_ADDR0L REG32((ENET) + 0x44U) /*!< ethernet MAC address 0 low register */ +#define ENET_MAC_ADDR1H REG32((ENET) + 0x48U) /*!< ethernet MAC address 1 high register */ +#define ENET_MAC_ADDR1L REG32((ENET) + 0x4CU) /*!< ethernet MAC address 1 low register */ +#define ENET_MAC_ADDT2H REG32((ENET) + 0x50U) /*!< ethernet MAC address 2 high register */ +#define ENET_MAC_ADDR2L REG32((ENET) + 0x54U) /*!< ethernet MAC address 2 low register */ +#define ENET_MAC_ADDR3H REG32((ENET) + 0x58U) /*!< ethernet MAC address 3 high register */ +#define ENET_MAC_ADDR3L REG32((ENET) + 0x5CU) /*!< ethernet MAC address 3 low register */ +#define ENET_MAC_FCTH REG32((ENET) + 0x1080U) /*!< ethernet MAC flow control threshold register */ + +#define ENET_MSC_CTL REG32((ENET) + 0x100U) /*!< ethernet MSC control register */ +#define ENET_MSC_RINTF REG32((ENET) + 0x104U) /*!< ethernet MSC receive interrupt flag register */ +#define ENET_MSC_TINTF REG32((ENET) + 0x108U) /*!< ethernet MSC transmit interrupt flag register */ +#define ENET_MSC_RINTMSK REG32((ENET) + 0x10CU) /*!< ethernet MSC receive interrupt mask register */ +#define ENET_MSC_TINTMSK REG32((ENET) + 0x110U) /*!< ethernet MSC transmit interrupt mask register */ +#define ENET_MSC_SCCNT REG32((ENET) + 0x14CU) /*!< ethernet MSC transmitted good frames after a single collision counter register */ +#define ENET_MSC_MSCCNT REG32((ENET) + 0x150U) /*!< ethernet MSC transmitted good frames after more than a single collision counter register */ +#define ENET_MSC_TGFCNT REG32((ENET) + 0x168U) /*!< ethernet MSC transmitted good frames counter register */ +#define ENET_MSC_RFCECNT REG32((ENET) + 0x194U) /*!< ethernet MSC received frames with CRC error counter register */ +#define ENET_MSC_RFAECNT REG32((ENET) + 0x198U) /*!< ethernet MSC received frames with alignment error counter register */ +#define ENET_MSC_RGUFCNT REG32((ENET) + 0x1C4U) /*!< ethernet MSC received good unicast frames counter register */ + +#define ENET_PTP_TSCTL REG32((ENET) + 0x700U) /*!< ethernet PTP time stamp control register */ +#define ENET_PTP_SSINC REG32((ENET) + 0x704U) /*!< ethernet PTP subsecond increment register */ +#define ENET_PTP_TSH REG32((ENET) + 0x708U) /*!< ethernet PTP time stamp high register */ +#define ENET_PTP_TSL REG32((ENET) + 0x70CU) /*!< ethernet PTP time stamp low register */ +#define ENET_PTP_TSUH REG32((ENET) + 0x710U) /*!< ethernet PTP time stamp update high register */ +#define ENET_PTP_TSUL REG32((ENET) + 0x714U) /*!< ethernet PTP time stamp update low register */ +#define ENET_PTP_TSADDEND REG32((ENET) + 0x718U) /*!< ethernet PTP time stamp addend register */ +#define ENET_PTP_ETH REG32((ENET) + 0x71CU) /*!< ethernet PTP expected time high register */ +#define ENET_PTP_ETL REG32((ENET) + 0x720U) /*!< ethernet PTP expected time low register */ +#define ENET_PTP_TSF REG32((ENET) + 0x728U) /*!< ethernet PTP time stamp flag register */ +#define ENET_PTP_PPSCTL REG32((ENET) + 0x72CU) /*!< ethernet PTP PPS control register */ + +#define ENET_DMA_BCTL REG32((ENET) + 0x1000U) /*!< ethernet DMA bus control register */ +#define ENET_DMA_TPEN REG32((ENET) + 0x1004U) /*!< ethernet DMA transmit poll enable register */ +#define ENET_DMA_RPEN REG32((ENET) + 0x1008U) /*!< ethernet DMA receive poll enable register */ +#define ENET_DMA_RDTADDR REG32((ENET) + 0x100CU) /*!< ethernet DMA receive descriptor table address register */ +#define ENET_DMA_TDTADDR REG32((ENET) + 0x1010U) /*!< ethernet DMA transmit descriptor table address register */ +#define ENET_DMA_STAT REG32((ENET) + 0x1014U) /*!< ethernet DMA status register */ +#define ENET_DMA_CTL REG32((ENET) + 0x1018U) /*!< ethernet DMA control register */ +#define ENET_DMA_INTEN REG32((ENET) + 0x101CU) /*!< ethernet DMA interrupt enable register */ +#define ENET_DMA_MFBOCNT REG32((ENET) + 0x1020U) /*!< ethernet DMA missed frame and buffer overflow counter register */ +#define ENET_DMA_RSWDC REG32((ENET) + 0x1024U) /*!< ethernet DMA receive state watchdog counter register */ +#define ENET_DMA_CTDADDR REG32((ENET) + 0x1048U) /*!< ethernet DMA current transmit descriptor address register */ +#define ENET_DMA_CRDADDR REG32((ENET) + 0x104CU) /*!< ethernet DMA current receive descriptor address register */ +#define ENET_DMA_CTBADDR REG32((ENET) + 0x1050U) /*!< ethernet DMA current transmit buffer address register */ +#define ENET_DMA_CRBADDR REG32((ENET) + 0x1054U) /*!< ethernet DMA current receive buffer address register */ + +/* bits definitions */ +/* ENET_MAC_CFG */ +#define ENET_MAC_CFG_REN BIT(2) /*!< receiver enable */ +#define ENET_MAC_CFG_TEN BIT(3) /*!< transmitter enable */ +#define ENET_MAC_CFG_DFC BIT(4) /*!< defferal check */ +#define ENET_MAC_CFG_BOL BITS(5,6) /*!< back-off limit */ +#define ENET_MAC_CFG_APCD BIT(7) /*!< automatic pad/CRC drop */ +#define ENET_MAC_CFG_RTD BIT(9) /*!< retry disable */ +#define ENET_MAC_CFG_IPFCO BIT(10) /*!< IP frame checksum offload */ +#define ENET_MAC_CFG_DPM BIT(11) /*!< duplex mode */ +#define ENET_MAC_CFG_LBM BIT(12) /*!< loopback mode */ +#define ENET_MAC_CFG_ROD BIT(13) /*!< receive own disable */ +#define ENET_MAC_CFG_SPD BIT(14) /*!< fast eneternet speed */ +#define ENET_MAC_CFG_CSD BIT(16) /*!< carrier sense disable */ +#define ENET_MAC_CFG_IGBS BITS(17,19) /*!< inter-frame gap bit selection */ +#define ENET_MAC_CFG_JBD BIT(22) /*!< jabber disable */ +#define ENET_MAC_CFG_WDD BIT(23) /*!< watchdog disable */ +#define ENET_MAC_CFG_TFCD BIT(25) /*!< type frame CRC dropping */ + +/* ENET_MAC_FRMF */ +#define ENET_MAC_FRMF_PM BIT(0) /*!< promiscuous mode */ +#define ENET_MAC_FRMF_HUF BIT(1) /*!< hash unicast filter */ +#define ENET_MAC_FRMF_HMF BIT(2) /*!< hash multicast filter */ +#define ENET_MAC_FRMF_DAIFLT BIT(3) /*!< destination address inverse filtering enable */ +#define ENET_MAC_FRMF_MFD BIT(4) /*!< multicast filter disable */ +#define ENET_MAC_FRMF_BFRMD BIT(5) /*!< broadcast frame disable */ +#define ENET_MAC_FRMF_PCFRM BITS(6,7) /*!< pass control frames */ +#define ENET_MAC_FRMF_SAIFLT BIT(8) /*!< source address inverse filtering */ +#define ENET_MAC_FRMF_SAFLT BIT(9) /*!< source address filter */ +#define ENET_MAC_FRMF_HPFLT BIT(10) /*!< hash or perfect filter */ +#define ENET_MAC_FRMF_FAR BIT(31) /*!< frames all receive */ + +/* ENET_MAC_HLH */ +#define ENET_MAC_HLH_HLH BITS(0,31) /*!< hash list high */ + +/* ENET_MAC_HLL */ +#define ENET_MAC_HLL_HLL BITS(0,31) /*!< hash list low */ + +/* ENET_MAC_PHY_CTL */ +#define ENET_MAC_PHY_CTL_PB BIT(0) /*!< PHY busy */ +#define ENET_MAC_PHY_CTL_PW BIT(1) /*!< PHY write */ +#define ENET_MAC_PHY_CTL_CLR BITS(2,4) /*!< clock range */ +#define ENET_MAC_PHY_CTL_PR BITS(6,10) /*!< PHY register */ +#define ENET_MAC_PHY_CTL_PA BITS(11,15) /*!< PHY address */ + +/* ENET_MAC_PHY_DATA */ +#define ENET_MAC_PHY_DATA_PD BITS(0,15) /*!< PHY data */ + +/* ENET_MAC_FCTL */ +#define ENET_MAC_FCTL_FLCBBKPA BIT(0) /*!< flow control busy(in full duplex mode)/backpressure activate(in half duplex mode) */ +#define ENET_MAC_FCTL_TFCEN BIT(1) /*!< transmit flow control enable */ +#define ENET_MAC_FCTL_RFCEN BIT(2) /*!< receive flow control enable */ +#define ENET_MAC_FCTL_UPFDT BIT(3) /*!< unicast pause frame detect */ +#define ENET_MAC_FCTL_PLTS BITS(4,5) /*!< pause low threshold */ +#define ENET_MAC_FCTL_DZQP BIT(7) /*!< disable zero-quanta pause */ +#define ENET_MAC_FCTL_PTM BITS(16,31) /*!< pause time */ + +/* ENET_MAC_VLT */ +#define ENET_MAC_VLT_VLTI BITS(0,15) /*!< VLAN tag identifier(for receive frames) */ +#define ENET_MAC_VLT_VLTC BIT(16) /*!< 12-bit VLAN tag comparison */ + +/* ENET_MAC_RWFF */ +#define ENET_MAC_RWFF_DATA BITS(0,31) /*!< wakeup frame filter register data */ + +/* ENET_MAC_WUM */ +#define ENET_MAC_WUM_PWD BIT(0) /*!< power down */ +#define ENET_MAC_WUM_MPEN BIT(1) /*!< magic packet enable */ +#define ENET_MAC_WUM_WFEN BIT(2) /*!< wakeup frame enable */ +#define ENET_MAC_WUM_MPKR BIT(5) /*!< magic packet received */ +#define ENET_MAC_WUM_WUFR BIT(6) /*!< wakeup frame received */ +#define ENET_MAC_WUM_GU BIT(9) /*!< global unicast */ +#define ENET_MAC_WUM_WUFFRPR BIT(31) /*!< wakeup frame filter register pointer reset */ + +/* ENET_MAC_DBG */ +#define ENET_MAC_DBG_MRNI BIT(0) /*!< MAC receive state not idle */ +#define ENET_MAC_DBG_RXAFS BITS(1,2) /*!< Rx asynchronous FIFO status */ +#define ENET_MAC_DBG_RXFW BIT(4) /*!< RxFIFO is writing */ +#define ENET_MAC_DBG_RXFRS BITS(5,6) /*!< RxFIFO read operation status */ +#define ENET_MAC_DBG_RXFS BITS(8,9) /*!< RxFIFO state */ +#define ENET_MAC_DBG_MTNI BIT(16) /*!< MAC transmit state not idle */ +#define ENET_MAC_DBG_SOMT BITS(17,18) /*!< status of mac transmitter */ +#define ENET_MAC_DBG_PCS BIT(19) /*!< pause condition status */ +#define ENET_MAC_DBG_TXFRS BITS(20,21) /*!< TxFIFO read operation status */ +#define ENET_MAC_DBG_TXFW BIT(22) /*!< TxFIFO is writing */ +#define ENET_MAC_DBG_TXFNE BIT(24) /*!< TxFIFO not empty flag */ +#define ENET_MAC_DBG_TXFF BIT(25) /*!< TxFIFO full flag */ + +/* ENET_MAC_INTF */ +#define ENET_MAC_INTF_WUM BIT(3) /*!< WUM status */ +#define ENET_MAC_INTF_MSC BIT(4) /*!< MSC status */ +#define ENET_MAC_INTF_MSCR BIT(5) /*!< MSC receive status */ +#define ENET_MAC_INTF_MSCT BIT(6) /*!< MSC transmit status */ +#define ENET_MAC_INTF_TMST BIT(9) /*!< timestamp trigger status */ + +/* ENET_MAC_INTMSK */ +#define ENET_MAC_INTMSK_WUMIM BIT(3) /*!< WUM interrupt mask */ +#define ENET_MAC_INTMSK_TMSTIM BIT(9) /*!< timestamp trigger interrupt mask */ + +/* ENET_MAC_ADDR0H */ +#define ENET_MAC_ADDR0H_ADDR0H BITS(0,15) /*!< MAC address0 high */ +#define ENET_MAC_ADDR0H_MO BIT(31) /*!< always read 1 and must be kept */ + +/* ENET_MAC_ADDR0L */ +#define ENET_MAC_ADDR0L_ADDR0L BITS(0,31) /*!< MAC address0 low */ + +/* ENET_MAC_ADDR1H */ +#define ENET_MAC_ADDR1H_ADDR1H BITS(0,15) /*!< MAC address1 high */ +#define ENET_MAC_ADDR1H_MB BITS(24,29) /*!< mask byte */ +#define ENET_MAC_ADDR1H_SAF BIT(30) /*!< source address filter */ +#define ENET_MAC_ADDR1H_AFE BIT(31) /*!< address filter enable */ + +/* ENET_MAC_ADDR1L */ +#define ENET_MAC_ADDR1L_ADDR1L BITS(0,31) /*!< MAC address1 low */ + +/* ENET_MAC_ADDR2H */ +#define ENET_MAC_ADDR2H_ADDR2H BITS(0,15) /*!< MAC address2 high */ +#define ENET_MAC_ADDR2H_MB BITS(24,29) /*!< mask byte */ +#define ENET_MAC_ADDR2H_SAF BIT(30) /*!< source address filter */ +#define ENET_MAC_ADDR2H_AFE BIT(31) /*!< address filter enable */ + +/* ENET_MAC_ADDR2L */ +#define ENET_MAC_ADDR2L_ADDR2L BITS(0,31) /*!< MAC address2 low */ + +/* ENET_MAC_ADDR3H */ +#define ENET_MAC_ADDR3H_ADDR3H BITS(0,15) /*!< MAC address3 high */ +#define ENET_MAC_ADDR3H_MB BITS(24,29) /*!< mask byte */ +#define ENET_MAC_ADDR3H_SAF BIT(30) /*!< source address filter */ +#define ENET_MAC_ADDR3H_AFE BIT(31) /*!< address filter enable */ + +/* ENET_MAC_ADDR3L */ +#define ENET_MAC_ADDR3L_ADDR3L BITS(0,31) /*!< MAC address3 low */ + +/* ENET_MAC_FCTH */ +#define ENET_MAC_FCTH_RFA BITS(0,2) /*!< threshold of active flow control */ +#define ENET_MAC_FCTH_RFD BITS(4,6) /*!< threshold of deactive flow control */ + +/* ENET_MSC_CTL */ +#define ENET_MSC_CTL_CTR BIT(0) /*!< counter reset */ +#define ENET_MSC_CTL_CTSR BIT(1) /*!< counter stop rollover */ +#define ENET_MSC_CTL_RTOR BIT(2) /*!< reset on read */ +#define ENET_MSC_CTL_MCFZ BIT(3) /*!< MSC counter freeze */ +#define ENET_MSC_CTL_PMC BIT(4) /*!< preset MSC counter */ +#define ENET_MSC_CTL_AFHPM BIT(5) /*!< almost full or half preset mode */ + +/* ENET_MSC_RINTF */ +#define ENET_MSC_RINTF_RFCE BIT(5) /*!< received frames CRC error */ +#define ENET_MSC_RINTF_RFAE BIT(6) /*!< received frames alignment error */ +#define ENET_MSC_RINTF_RGUF BIT(17) /*!< receive good unicast frames */ + +/* ENET_MSC_TINTF */ +#define ENET_MSC_TINTF_TGFSC BIT(14) /*!< transmitted good frames single collision */ +#define ENET_MSC_TINTF_TGFMSC BIT(15) /*!< transmitted good frames more single collision */ +#define ENET_MSC_TINTF_TGF BIT(21) /*!< transmitted good frames */ + +/* ENET_MSC_RINTMSK */ +#define ENET_MSC_RINTMSK_RFCEIM BIT(5) /*!< received frame CRC error interrupt mask */ +#define ENET_MSC_RINTMSK_RFAEIM BIT(6) /*!< received frames alignment error interrupt mask */ +#define ENET_MSC_RINTMSK_RGUFIM BIT(17) /*!< received good unicast frames interrupt mask */ + +/* ENET_MSC_TINTMSK */ +#define ENET_MSC_TINTMSK_TGFSCIM BIT(14) /*!< transmitted good frames single collision interrupt mask */ +#define ENET_MSC_TINTMSK_TGFMSCIM BIT(15) /*!< transmitted good frames more single collision interrupt mask */ +#define ENET_MSC_TINTMSK_TGFIM BIT(21) /*!< transmitted good frames interrupt mask */ + +/* ENET_MSC_SCCNT */ +#define ENET_MSC_SCCNT_SCC BITS(0,31) /*!< transmitted good frames single collision counter */ + +/* ENET_MSC_MSCCNT */ +#define ENET_MSC_MSCCNT_MSCC BITS(0,31) /*!< transmitted good frames more one single collision counter */ + +/* ENET_MSC_TGFCNT */ +#define ENET_MSC_TGFCNT_TGF BITS(0,31) /*!< transmitted good frames counter */ + +/* ENET_MSC_RFCECNT */ +#define ENET_MSC_RFCECNT_RFCER BITS(0,31) /*!< received frames with CRC error counter */ + +/* ENET_MSC_RFAECNT */ +#define ENET_MSC_RFAECNT_RFAER BITS(0,31) /*!< received frames alignment error counter */ + +/* ENET_MSC_RGUFCNT */ +#define ENET_MSC_RGUFCNT_RGUF BITS(0,31) /*!< received good unicast frames counter */ + +/* ENET_PTP_TSCTL */ +#define ENET_PTP_TSCTL_TMSEN BIT(0) /*!< timestamp enable */ +#define ENET_PTP_TSCTL_TMSFCU BIT(1) /*!< timestamp fine or coarse update */ +#define ENET_PTP_TSCTL_TMSSTI BIT(2) /*!< timestamp system time initialize */ +#define ENET_PTP_TSCTL_TMSSTU BIT(3) /*!< timestamp system time update */ +#define ENET_PTP_TSCTL_TMSITEN BIT(4) /*!< timestamp interrupt trigger enable */ +#define ENET_PTP_TSCTL_TMSARU BIT(5) /*!< timestamp addend register update */ +#define ENET_PTP_TSCTL_ARFSEN BIT(8) /*!< all received frames snapshot enable */ +#define ENET_PTP_TSCTL_SCROM BIT(9) /*!< subsecond counter rollover mode */ +#define ENET_PTP_TSCTL_PFSV BIT(10) /*!< PTP frame snooping version */ +#define ENET_PTP_TSCTL_ESEN BIT(11) /*!< received Ethernet snapshot enable */ +#define ENET_PTP_TSCTL_IP6SEN BIT(12) /*!< received IPv6 snapshot enable */ +#define ENET_PTP_TSCTL_IP4SEN BIT(13) /*!< received IPv4 snapshot enable */ +#define ENET_PTP_TSCTL_ETMSEN BIT(14) /*!< received event type message snapshot enable */ +#define ENET_PTP_TSCTL_MNMSEN BIT(15) /*!< received master node message snapshot enable */ +#define ENET_PTP_TSCTL_CKNT BITS(16,17) /*!< clock node type for time stamp */ +#define ENET_PTP_TSCTL_MAFEN BIT(18) /*!< MAC address filter enable for PTP frame */ + +/* ENET_PTP_SSINC */ +#define ENET_PTP_SSINC_STMSSI BITS(0,7) /*!< system time subsecond increment */ + +/* ENET_PTP_TSH */ +#define ENET_PTP_TSH_STMS BITS(0,31) /*!< system time second */ + +/* ENET_PTP_TSL */ +#define ENET_PTP_TSL_STMSS BITS(0,30) /*!< system time subseconds */ +#define ENET_PTP_TSL_STS BIT(31) /*!< system time sign */ + +/* ENET_PTP_TSUH */ +#define ENET_PTP_TSUH_TMSUS BITS(0,31) /*!< timestamp update seconds */ + +/* ENET_PTP_TSUL */ +#define ENET_PTP_TSUL_TMSUSS BITS(0,30) /*!< timestamp update subseconds */ +#define ENET_PTP_TSUL_TMSUPNS BIT(31) /*!< timestamp update positive or negative sign */ + +/* ENET_PTP_TSADDEND */ +#define ENET_PTP_TSADDEND_TMSA BITS(0,31) /*!< timestamp addend */ + +/* ENET_PTP_ETH */ +#define ENET_PTP_ETH_ETSH BITS(0,31) /*!< expected time high */ + +/* ENET_PTP_ETL */ +#define ENET_PTP_ETL_ETSL BITS(0,31) /*!< expected time low */ + +/* ENET_PTP_TSF */ +#define ENET_PTP_TSF_TSSCO BIT(0) /*!< timestamp second counter overflow */ +#define ENET_PTP_TSF_TTM BIT(1) /*!< target time match */ + +/* ENET_PTP_PPSCTL */ +#define ENET_PTP_PPSCTL_PPSOFC BITS(0,3) /*!< PPS output frequency configure */ + +/* ENET_DMA_BCTL */ +#define ENET_DMA_BCTL_SWR BIT(0) /*!< software reset */ +#define ENET_DMA_BCTL_DAB BIT(1) /*!< DMA arbitration */ +#define ENET_DMA_BCTL_DPSL BITS(2,6) /*!< descriptor skip length */ +#define ENET_DMA_BCTL_DFM BIT(7) /*!< descriptor format mode */ +#define ENET_DMA_BCTL_PGBL BITS(8,13) /*!< programmable burst length */ +#define ENET_DMA_BCTL_RTPR BITS(14,15) /*!< RxDMA and TxDMA transfer priority ratio */ +#define ENET_DMA_BCTL_FB BIT(16) /*!< fixed Burst */ +#define ENET_DMA_BCTL_RXDP BITS(17,22) /*!< RxDMA PGBL */ +#define ENET_DMA_BCTL_UIP BIT(23) /*!< use independent PGBL */ +#define ENET_DMA_BCTL_FPBL BIT(24) /*!< four times PGBL mode */ +#define ENET_DMA_BCTL_AA BIT(25) /*!< address-aligned */ +#define ENET_DMA_BCTL_MB BIT(26) /*!< mixed burst */ + +/* ENET_DMA_TPEN */ +#define ENET_DMA_TPEN_TPE BITS(0,31) /*!< transmit poll enable */ + +/* ENET_DMA_RPEN */ +#define ENET_DMA_RPEN_RPE BITS(0,31) /*!< receive poll enable */ + +/* ENET_DMA_RDTADDR */ +#define ENET_DMA_RDTADDR_SRT BITS(0,31) /*!< start address of receive table */ + +/* ENET_DMA_TDTADDR */ +#define ENET_DMA_TDTADDR_STT BITS(0,31) /*!< start address of transmit table */ + +/* ENET_DMA_STAT */ +#define ENET_DMA_STAT_TS BIT(0) /*!< transmit status */ +#define ENET_DMA_STAT_TPS BIT(1) /*!< transmit process stopped status */ +#define ENET_DMA_STAT_TBU BIT(2) /*!< transmit buffer unavailable status */ +#define ENET_DMA_STAT_TJT BIT(3) /*!< transmit jabber timeout status */ +#define ENET_DMA_STAT_RO BIT(4) /*!< receive overflow status */ +#define ENET_DMA_STAT_TU BIT(5) /*!< transmit underflow status */ +#define ENET_DMA_STAT_RS BIT(6) /*!< receive status */ +#define ENET_DMA_STAT_RBU BIT(7) /*!< receive buffer unavailable status */ +#define ENET_DMA_STAT_RPS BIT(8) /*!< receive process stopped status */ +#define ENET_DMA_STAT_RWT BIT(9) /*!< receive watchdog timeout status */ +#define ENET_DMA_STAT_ET BIT(10) /*!< early transmit status */ +#define ENET_DMA_STAT_FBE BIT(13) /*!< fatal bus error status */ +#define ENET_DMA_STAT_ER BIT(14) /*!< early receive status */ +#define ENET_DMA_STAT_AI BIT(15) /*!< abnormal interrupt summary */ +#define ENET_DMA_STAT_NI BIT(16) /*!< normal interrupt summary */ +#define ENET_DMA_STAT_RP BITS(17,19) /*!< receive process state */ +#define ENET_DMA_STAT_TP BITS(20,22) /*!< transmit process state */ +#define ENET_DMA_STAT_EB BITS(23,25) /*!< error bits status */ +#define ENET_DMA_STAT_MSC BIT(27) /*!< MSC status */ +#define ENET_DMA_STAT_WUM BIT(28) /*!< WUM status */ +#define ENET_DMA_STAT_TST BIT(29) /*!< timestamp trigger status */ + +/* ENET_DMA_CTL */ +#define ENET_DMA_CTL_SRE BIT(1) /*!< start/stop receive enable */ +#define ENET_DMA_CTL_OSF BIT(2) /*!< operate on second frame */ +#define ENET_DMA_CTL_RTHC BITS(3,4) /*!< receive threshold control */ +#define ENET_DMA_CTL_FUF BIT(6) /*!< forward undersized good frames */ +#define ENET_DMA_CTL_FERF BIT(7) /*!< forward error frames */ +#define ENET_DMA_CTL_STE BIT(13) /*!< start/stop transmission enable */ +#define ENET_DMA_CTL_TTHC BITS(14,16) /*!< transmit threshold control */ +#define ENET_DMA_CTL_FTF BIT(20) /*!< flush transmit FIFO */ +#define ENET_DMA_CTL_TSFD BIT(21) /*!< transmit store-and-forward */ +#define ENET_DMA_CTL_DAFRF BIT(24) /*!< disable flushing of received frames */ +#define ENET_DMA_CTL_RSFD BIT(25) /*!< receive store-and-forward */ +#define ENET_DMA_CTL_DTCERFD BIT(26) /*!< dropping of TCP/IP checksum error frames disable */ + +/* ENET_DMA_INTEN */ +#define ENET_DMA_INTEN_TIE BIT(0) /*!< transmit interrupt enable */ +#define ENET_DMA_INTEN_TPSIE BIT(1) /*!< transmit process stopped interrupt enable */ +#define ENET_DMA_INTEN_TBUIE BIT(2) /*!< transmit buffer unavailable interrupt enable */ +#define ENET_DMA_INTEN_TJTIE BIT(3) /*!< transmit jabber timeout interrupt enable */ +#define ENET_DMA_INTEN_ROIE BIT(4) /*!< receive overflow interrupt enable */ +#define ENET_DMA_INTEN_TUIE BIT(5) /*!< transmit underflow interrupt enable */ +#define ENET_DMA_INTEN_RIE BIT(6) /*!< receive interrupt enable */ +#define ENET_DMA_INTEN_RBUIE BIT(7) /*!< receive buffer unavailable interrupt enable */ +#define ENET_DMA_INTEN_RPSIE BIT(8) /*!< receive process stopped interrupt enable */ +#define ENET_DMA_INTEN_RWTIE BIT(9) /*!< receive watchdog timeout interrupt enable */ +#define ENET_DMA_INTEN_ETIE BIT(10) /*!< early transmit interrupt enable */ +#define ENET_DMA_INTEN_FBEIE BIT(13) /*!< fatal bus error interrupt enable */ +#define ENET_DMA_INTEN_ERIE BIT(14) /*!< early receive interrupt enable */ +#define ENET_DMA_INTEN_AIE BIT(15) /*!< abnormal interrupt summary enable */ +#define ENET_DMA_INTEN_NIE BIT(16) /*!< normal interrupt summary enable */ + +/* ENET_DMA_MFBOCNT */ +#define ENET_DMA_MFBOCNT_MSFC BITS(0,15) /*!< missed frames by the controller */ +#define ENET_DMA_MFBOCNT_MSFA BITS(17,27) /*!< missed frames by the application */ + +/* ENET_DMA_RSWDC */ +#define ENET_DMA_RSWDC_WDCFRS BITS(0,7) /*!< watchdog counter for receive status (RS) */ + +/* ENET_DMA_CTDADDR */ +#define ENET_DMA_CTDADDR_TDAP BITS(0,31) /*!< transmit descriptor address pointer */ + +/* ENET_DMA_CRDADDR */ +#define ENET_DMA_CRDADDR_RDAP BITS(0,31) /*!< receive descriptor address pointer */ + +/* ENET_DMA_CTBADDR */ +#define ENET_DMA_CTBADDR_TBAP BITS(0,31) /*!< transmit buffer address pointer */ + +/* ENET_DMA_CRBADDR */ +#define ENET_DMA_CRBADDR_RBAP BITS(0,31) /*!< receive buffer address pointer */ + +/* ENET DMA Tx descriptor TDES0 */ +#define ENET_TDES0_DB BIT(0) /*!< deferred */ +#define ENET_TDES0_UFE BIT(1) /*!< underflow error */ +#define ENET_TDES0_EXD BIT(2) /*!< excessive deferral */ +#define ENET_TDES0_COCNT BITS(3,6) /*!< collision count */ +#define ENET_TDES0_VFRM BIT(7) /*!< VLAN frame */ +#define ENET_TDES0_ECO BIT(8) /*!< excessive collision */ +#define ENET_TDES0_LCO BIT(9) /*!< late collision */ +#define ENET_TDES0_NCA BIT(10) /*!< no carrier */ +#define ENET_TDES0_LCA BIT(11) /*!< loss of carrier */ +#define ENET_TDES0_IPPE BIT(12) /*!< IP payload error */ +#define ENET_TDES0_FRMF BIT(13) /*!< frame flushed */ +#define ENET_TDES0_JT BIT(14) /*!< jabber timeout */ +#define ENET_TDES0_ES BIT(15) /*!< error summary */ +#define ENET_TDES0_IPHE BIT(16) /*!< IP header error */ +#define ENET_TDES0_TTMSS BIT(17) /*!< transmit timestamp status */ +#define ENET_TDES0_TCHM BIT(20) /*!< the second address chained mode */ +#define ENET_TDES0_TERM BIT(21) /*!< transmit end of ring mode*/ +#define ENET_TDES0_CM BITS(22,23) /*!< checksum mode */ +#define ENET_TDES0_TTSEN BIT(25) /*!< transmit timestamp function enable */ +#define ENET_TDES0_DPAD BIT(26) /*!< disable adding pad */ +#define ENET_TDES0_DCRC BIT(27) /*!< disable CRC */ +#define ENET_TDES0_FSG BIT(28) /*!< first segment */ +#define ENET_TDES0_LSG BIT(29) /*!< last segment */ +#define ENET_TDES0_INTC BIT(30) /*!< interrupt on completion */ +#define ENET_TDES0_DAV BIT(31) /*!< DAV bit */ + +/* ENET DMA Tx descriptor TDES1 */ +#define ENET_TDES1_TB1S BITS(0,12) /*!< transmit buffer 1 size */ +#define ENET_TDES1_TB2S BITS(16,28) /*!< transmit buffer 2 size */ + +/* ENET DMA Tx descriptor TDES2 */ +#define ENET_TDES2_TB1AP BITS(0,31) /*!< transmit buffer 1 address pointer/transmit frame timestamp low 32-bit value */ + +/* ENET DMA Tx descriptor TDES3 */ +#define ENET_TDES3_TB2AP BITS(0,31) /*!< transmit buffer 2 address pointer (or next descriptor address) / transmit frame timestamp high 32-bit value */ + +#ifdef SELECT_DESCRIPTORS_ENHANCED_MODE +/* ENET DMA Tx descriptor TDES6 */ +#define ENET_TDES6_TTSL BITS(0,31) /*!< transmit frame timestamp low 32-bit value */ + +/* ENET DMA Tx descriptor TDES7 */ +#define ENET_TDES7_TTSH BITS(0,31) /*!< transmit frame timestamp high 32-bit value */ +#endif /* SELECT_DESCRIPTORS_ENHANCED_MODE */ + +/* ENET DMA Rx descriptor RDES0 */ +#define ENET_RDES0_PCERR BIT(0) /*!< payload checksum error */ +#define ENET_RDES0_EXSV BIT(0) /*!< extended status valid */ +#define ENET_RDES0_CERR BIT(1) /*!< CRC error */ +#define ENET_RDES0_DBERR BIT(2) /*!< dribble bit error */ +#define ENET_RDES0_RERR BIT(3) /*!< receive error */ +#define ENET_RDES0_RWDT BIT(4) /*!< receive watchdog timeout */ +#define ENET_RDES0_FRMT BIT(5) /*!< frame type */ +#define ENET_RDES0_LCO BIT(6) /*!< late collision */ +#define ENET_RDES0_IPHERR BIT(7) /*!< IP frame header error */ +#define ENET_RDES0_TSV BIT(7) /*!< timestamp valid */ +#define ENET_RDES0_LDES BIT(8) /*!< last descriptor */ +#define ENET_RDES0_FDES BIT(9) /*!< first descriptor */ +#define ENET_RDES0_VTAG BIT(10) /*!< VLAN tag */ +#define ENET_RDES0_OERR BIT(11) /*!< overflow Error */ +#define ENET_RDES0_LERR BIT(12) /*!< length error */ +#define ENET_RDES0_SAFF BIT(13) /*!< SA filter fail */ +#define ENET_RDES0_DERR BIT(14) /*!< descriptor error */ +#define ENET_RDES0_ERRS BIT(15) /*!< error summary */ +#define ENET_RDES0_FRML BITS(16,29) /*!< frame length */ +#define ENET_RDES0_DAFF BIT(30) /*!< destination address filter fail */ +#define ENET_RDES0_DAV BIT(31) /*!< descriptor available */ + +/* ENET DMA Rx descriptor RDES1 */ +#define ENET_RDES1_RB1S BITS(0,12) /*!< receive buffer 1 size */ +#define ENET_RDES1_RCHM BIT(14) /*!< receive chained mode for second address */ +#define ENET_RDES1_RERM BIT(15) /*!< receive end of ring mode*/ +#define ENET_RDES1_RB2S BITS(16,28) /*!< receive buffer 2 size */ +#define ENET_RDES1_DINTC BIT(31) /*!< disable interrupt on completion */ + +/* ENET DMA Rx descriptor RDES2 */ +#define ENET_RDES2_RB1AP BITS(0,31) /*!< receive buffer 1 address pointer / receive frame timestamp low 32-bit */ + +/* ENET DMA Rx descriptor RDES3 */ +#define ENET_RDES3_RB2AP BITS(0,31) /*!< receive buffer 2 address pointer (next descriptor address)/receive frame timestamp high 32-bit value */ + +#ifdef SELECT_DESCRIPTORS_ENHANCED_MODE +/* ENET DMA Rx descriptor RDES4 */ +#define ENET_RDES4_IPPLDT BITS(0,2) /*!< IP frame payload type */ +#define ENET_RDES4_IPHERR BIT(3) /*!< IP frame header error */ +#define ENET_RDES4_IPPLDERR BIT(4) /*!< IP frame payload error */ +#define ENET_RDES4_IPCKSB BIT(5) /*!< IP frame checksum bypassed */ +#define ENET_RDES4_IPF4 BIT(6) /*!< IP frame in version 4 */ +#define ENET_RDES4_IPF6 BIT(7) /*!< IP frame in version 6 */ +#define ENET_RDES4_PTPMT BITS(8,11) /*!< PTP message type */ +#define ENET_RDES4_PTPOEF BIT(12) /*!< PTP on ethernet frame */ +#define ENET_RDES4_PTPVF BIT(13) /*!< PTP version format */ + +/* ENET DMA Rx descriptor RDES6 */ +#define ENET_RDES6_RTSL BITS(0,31) /*!< receive frame timestamp low 32-bit value */ + +/* ENET DMA Rx descriptor RDES7 */ +#define ENET_RDES7_RTSH BITS(0,31) /*!< receive frame timestamp high 32-bit value */ +#endif /* SELECT_DESCRIPTORS_ENHANCED_MODE */ + +/* constants definitions */ +/* define bit position and its register index offset */ +#define ENET_REGIDX_BIT(regidx, bitpos) (((uint32_t)(regidx) << 6) | (uint32_t)(bitpos)) +#define ENET_REG_VAL(periph) (REG32(ENET + ((uint32_t)(periph)>>6))) +#define ENET_BIT_POS(val) ((uint32_t)(val) & 0x1FU) + +/* ENET clock range judgement */ +#define ENET_RANGE(hclk, n, m) (((hclk) >= (n))&&((hclk) < (m))) + +/* define MAC address configuration and reference address */ +#define ENET_SET_MACADDRH(p) (((uint32_t)(p)[5] << 8) | (uint32_t)(p)[4]) +#define ENET_SET_MACADDRL(p) (((uint32_t)(p)[3] << 24) | ((uint32_t)(p)[2] << 16) | ((uint32_t)(p)[1] << 8) | (uint32_t)(p)[0]) +#define ENET_ADDRH_BASE ((ENET) + 0x40U) +#define ENET_ADDRL_BASE ((ENET) + 0x44U) +#define ENET_GET_MACADDR(offset, n) ((uint8_t)((REG32((ENET_ADDRL_BASE + (offset)) - (((n) / 4U) * 4U)) >> (8U * ((n) % 4U))) & 0xFFU)) + +/* register offset */ +#define MAC_FCTL_REG_OFFSET 0x0018U /*!< MAC flow control register offset */ +#define MAC_WUM_REG_OFFSET 0x002CU /*!< MAC wakeup management register offset */ +#define MAC_INTF_REG_OFFSET 0x0038U /*!< MAC interrupt flag register offset */ +#define MAC_INTMSK_REG_OFFSET 0x003CU /*!< MAC interrupt mask register offset */ + +#define MSC_RINTF_REG_OFFSET 0x0104U /*!< MSC receive interrupt flag register offset */ +#define MSC_TINTF_REG_OFFSET 0x0108U /*!< MSC transmit interrupt flag register offset */ +#define MSC_RINTMSK_REG_OFFSET 0x010CU /*!< MSC receive interrupt mask register offset */ +#define MSC_TINTMSK_REG_OFFSET 0x0110U /*!< MSC transmit interrupt mask register offset */ +#define MSC_SCCNT_REG_OFFSET 0x014CU /*!< MSC transmitted good frames after a single collision counter register offset */ +#define MSC_MSCCNT_REG_OFFSET 0x0150U /*!< MSC transmitted good frames after more than a single collision counter register offset */ +#define MSC_TGFCNT_REG_OFFSET 0x0168U /*!< MSC transmitted good frames counter register offset */ +#define MSC_RFCECNT_REG_OFFSET 0x0194U /*!< MSC received frames with CRC error counter register offset */ +#define MSC_RFAECNT_REG_OFFSET 0x0198U /*!< MSC received frames with alignment error counter register offset */ +#define MSC_RGUFCNT_REG_OFFSET 0x01C4U /*!< MSC received good unicast frames counter register offset */ + +#define PTP_TSF_REG_OFFSET 0x0728U /*!< PTP time stamp flag register offset */ + +#define DMA_STAT_REG_OFFSET 0x1014U /*!< DMA status register offset */ +#define DMA_INTEN_REG_OFFSET 0x101CU /*!< DMA interrupt enable register offset */ +#define DMA_TDTADDR_REG_OFFSET 0x1010U /*!< DMA transmit descriptor table address register offset */ +#define DMA_CTDADDR_REG_OFFSET 0x1048U /*!< DMA current transmit descriptor address register */ +#define DMA_CTBADDR_REG_OFFSET 0x1050U /*!< DMA current transmit buffer address register */ +#define DMA_RDTADDR_REG_OFFSET 0x100CU /*!< DMA receive descriptor table address register */ +#define DMA_CRDADDR_REG_OFFSET 0x104CU /*!< DMA current receive descriptor address register */ +#define DMA_CRBADDR_REG_OFFSET 0x1054U /*!< DMA current receive buffer address register */ + +/* ENET status flag get */ +typedef enum +{ + /* ENET_MAC_WUM register */ + ENET_MAC_FLAG_MPKR = ENET_REGIDX_BIT(MAC_WUM_REG_OFFSET, 5U), /*!< magic packet received flag */ + ENET_MAC_FLAG_WUFR = ENET_REGIDX_BIT(MAC_WUM_REG_OFFSET, 6U), /*!< wakeup frame received flag */ + /* ENET_MAC_FCTL register */ + ENET_MAC_FLAG_FLOWCONTROL = ENET_REGIDX_BIT(MAC_FCTL_REG_OFFSET, 0U), /*!< flow control status flag */ + /* ENET_MAC_INTF register */ + ENET_MAC_FLAG_WUM = ENET_REGIDX_BIT(MAC_INTF_REG_OFFSET, 3U), /*!< WUM status flag */ + ENET_MAC_FLAG_MSC = ENET_REGIDX_BIT(MAC_INTF_REG_OFFSET, 4U), /*!< MSC status flag */ + ENET_MAC_FLAG_MSCR = ENET_REGIDX_BIT(MAC_INTF_REG_OFFSET, 5U), /*!< MSC receive status flag */ + ENET_MAC_FLAG_MSCT = ENET_REGIDX_BIT(MAC_INTF_REG_OFFSET, 6U), /*!< MSC transmit status flag */ + ENET_MAC_FLAG_TMST = ENET_REGIDX_BIT(MAC_INTF_REG_OFFSET, 9U), /*!< timestamp trigger status flag */ + /* ENET_PTP_TSF register */ + ENET_PTP_FLAG_TSSCO = ENET_REGIDX_BIT(PTP_TSF_REG_OFFSET, 0U), /*!< timestamp second counter overflow flag */ + ENET_PTP_FLAG_TTM = ENET_REGIDX_BIT(PTP_TSF_REG_OFFSET, 1U), /*!< target time match flag */ + /* ENET_MSC_RINTF register */ + ENET_MSC_FLAG_RFCE = ENET_REGIDX_BIT(MSC_RINTF_REG_OFFSET, 5U), /*!< received frames CRC error flag */ + ENET_MSC_FLAG_RFAE = ENET_REGIDX_BIT(MSC_RINTF_REG_OFFSET, 6U), /*!< received frames alignment error flag */ + ENET_MSC_FLAG_RGUF = ENET_REGIDX_BIT(MSC_RINTF_REG_OFFSET, 17U), /*!< received good unicast frames flag */ + /* ENET_MSC_TINTF register */ + ENET_MSC_FLAG_TGFSC = ENET_REGIDX_BIT(MSC_TINTF_REG_OFFSET, 14U), /*!< transmitted good frames single collision flag */ + ENET_MSC_FLAG_TGFMSC = ENET_REGIDX_BIT(MSC_TINTF_REG_OFFSET, 15U), /*!< transmitted good frames more single collision flag */ + ENET_MSC_FLAG_TGF = ENET_REGIDX_BIT(MSC_TINTF_REG_OFFSET, 21U), /*!< transmitted good frames flag */ + /* ENET_DMA_STAT register */ + ENET_DMA_FLAG_TS = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 0U), /*!< transmit status flag */ + ENET_DMA_FLAG_TPS = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 1U), /*!< transmit process stopped status flag */ + ENET_DMA_FLAG_TBU = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 2U), /*!< transmit buffer unavailable status flag */ + ENET_DMA_FLAG_TJT = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 3U), /*!< transmit jabber timeout status flag */ + ENET_DMA_FLAG_RO = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 4U), /*!< receive overflow status flag */ + ENET_DMA_FLAG_TU = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 5U), /*!< transmit underflow status flag */ + ENET_DMA_FLAG_RS = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 6U), /*!< receive status flag */ + ENET_DMA_FLAG_RBU = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 7U), /*!< receive buffer unavailable status flag */ + ENET_DMA_FLAG_RPS = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 8U), /*!< receive process stopped status flag */ + ENET_DMA_FLAG_RWT = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 9U), /*!< receive watchdog timeout status flag */ + ENET_DMA_FLAG_ET = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 10U), /*!< early transmit status flag */ + ENET_DMA_FLAG_FBE = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 13U), /*!< fatal bus error status flag */ + ENET_DMA_FLAG_ER = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 14U), /*!< early receive status flag */ + ENET_DMA_FLAG_AI = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 15U), /*!< abnormal interrupt summary flag */ + ENET_DMA_FLAG_NI = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 16U), /*!< normal interrupt summary flag */ + ENET_DMA_FLAG_EB_DMA_ERROR = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 23U), /*!< error during data transfer by RxDMA/TxDMA flag */ + ENET_DMA_FLAG_EB_TRANSFER_ERROR = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 24U), /*!< error during write/read transfer flag */ + ENET_DMA_FLAG_EB_ACCESS_ERROR = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 25U), /*!< error during data buffer/descriptor access flag */ + ENET_DMA_FLAG_MSC = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 27U), /*!< MSC status flag */ + ENET_DMA_FLAG_WUM = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 28U), /*!< WUM status flag */ + ENET_DMA_FLAG_TST = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 29U), /*!< timestamp trigger status flag */ +}enet_flag_enum; + +/* ENET stutus flag clear */ +typedef enum +{ + /* ENET_DMA_STAT register */ + ENET_DMA_FLAG_TS_CLR = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 0U), /*!< transmit status flag */ + ENET_DMA_FLAG_TPS_CLR = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 1U), /*!< transmit process stopped status flag */ + ENET_DMA_FLAG_TBU_CLR = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 2U), /*!< transmit buffer unavailable status flag */ + ENET_DMA_FLAG_TJT_CLR = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 3U), /*!< transmit jabber timeout status flag */ + ENET_DMA_FLAG_RO_CLR = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 4U), /*!< receive overflow status flag */ + ENET_DMA_FLAG_TU_CLR = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 5U), /*!< transmit underflow status flag */ + ENET_DMA_FLAG_RS_CLR = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 6U), /*!< receive status flag */ + ENET_DMA_FLAG_RBU_CLR = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 7U), /*!< receive buffer unavailable status flag */ + ENET_DMA_FLAG_RPS_CLR = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 8U), /*!< receive process stopped status flag */ + ENET_DMA_FLAG_RWT_CLR = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 9U), /*!< receive watchdog timeout status flag */ + ENET_DMA_FLAG_ET_CLR = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 10U), /*!< early transmit status flag */ + ENET_DMA_FLAG_FBE_CLR = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 13U), /*!< fatal bus error status flag */ + ENET_DMA_FLAG_ER_CLR = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 14U), /*!< early receive status flag */ + ENET_DMA_FLAG_AI_CLR = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 15U), /*!< abnormal interrupt summary flag */ + ENET_DMA_FLAG_NI_CLR = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 16U), /*!< normal interrupt summary flag */ +}enet_flag_clear_enum; + +/* ENET interrupt enable/disable */ +typedef enum +{ + /* ENET_MAC_INTMSK register */ + ENET_MAC_INT_WUMIM = ENET_REGIDX_BIT(MAC_INTMSK_REG_OFFSET, 3U), /*!< WUM interrupt mask */ + ENET_MAC_INT_TMSTIM = ENET_REGIDX_BIT(MAC_INTMSK_REG_OFFSET, 9U), /*!< timestamp trigger interrupt mask */ + /* ENET_MSC_RINTMSK register */ + ENET_MSC_INT_RFCEIM = ENET_REGIDX_BIT(MSC_RINTMSK_REG_OFFSET, 5U), /*!< received frame CRC error interrupt mask */ + ENET_MSC_INT_RFAEIM = ENET_REGIDX_BIT(MSC_RINTMSK_REG_OFFSET, 6U), /*!< received frames alignment error interrupt mask */ + ENET_MSC_INT_RGUFIM = ENET_REGIDX_BIT(MSC_RINTMSK_REG_OFFSET, 17U), /*!< received good unicast frames interrupt mask */ + /* ENET_MSC_TINTMSK register */ + ENET_MSC_INT_TGFSCIM = ENET_REGIDX_BIT(MSC_TINTMSK_REG_OFFSET, 14U), /*!< transmitted good frames single collision interrupt mask */ + ENET_MSC_INT_TGFMSCIM = ENET_REGIDX_BIT(MSC_TINTMSK_REG_OFFSET, 15U), /*!< transmitted good frames more single collision interrupt mask */ + ENET_MSC_INT_TGFIM = ENET_REGIDX_BIT(MSC_TINTMSK_REG_OFFSET, 21U), /*!< transmitted good frames interrupt mask */ + /* ENET_DMA_INTEN register */ + ENET_DMA_INT_TIE = ENET_REGIDX_BIT(DMA_INTEN_REG_OFFSET, 0U), /*!< transmit interrupt enable */ + ENET_DMA_INT_TPSIE = ENET_REGIDX_BIT(DMA_INTEN_REG_OFFSET, 1U), /*!< transmit process stopped interrupt enable */ + ENET_DMA_INT_TBUIE = ENET_REGIDX_BIT(DMA_INTEN_REG_OFFSET, 2U), /*!< transmit buffer unavailable interrupt enable */ + ENET_DMA_INT_TJTIE = ENET_REGIDX_BIT(DMA_INTEN_REG_OFFSET, 3U), /*!< transmit jabber timeout interrupt enable */ + ENET_DMA_INT_ROIE = ENET_REGIDX_BIT(DMA_INTEN_REG_OFFSET, 4U), /*!< receive overflow interrupt enable */ + ENET_DMA_INT_TUIE = ENET_REGIDX_BIT(DMA_INTEN_REG_OFFSET, 5U), /*!< transmit underflow interrupt enable */ + ENET_DMA_INT_RIE = ENET_REGIDX_BIT(DMA_INTEN_REG_OFFSET, 6U), /*!< receive interrupt enable */ + ENET_DMA_INT_RBUIE = ENET_REGIDX_BIT(DMA_INTEN_REG_OFFSET, 7U), /*!< receive buffer unavailable interrupt enable */ + ENET_DMA_INT_RPSIE = ENET_REGIDX_BIT(DMA_INTEN_REG_OFFSET, 8U), /*!< receive process stopped interrupt enable */ + ENET_DMA_INT_RWTIE = ENET_REGIDX_BIT(DMA_INTEN_REG_OFFSET, 9U), /*!< receive watchdog timeout interrupt enable */ + ENET_DMA_INT_ETIE = ENET_REGIDX_BIT(DMA_INTEN_REG_OFFSET, 10U), /*!< early transmit interrupt enable */ + ENET_DMA_INT_FBEIE = ENET_REGIDX_BIT(DMA_INTEN_REG_OFFSET, 13U), /*!< fatal bus error interrupt enable */ + ENET_DMA_INT_ERIE = ENET_REGIDX_BIT(DMA_INTEN_REG_OFFSET, 14U), /*!< early receive interrupt enable */ + ENET_DMA_INT_AIE = ENET_REGIDX_BIT(DMA_INTEN_REG_OFFSET, 15U), /*!< abnormal interrupt summary enable */ + ENET_DMA_INT_NIE = ENET_REGIDX_BIT(DMA_INTEN_REG_OFFSET, 16U), /*!< normal interrupt summary enable */ +}enet_int_enum; + +/* ENET interrupt flag get */ +typedef enum +{ + /* ENET_MAC_INTF register */ + ENET_MAC_INT_FLAG_WUM = ENET_REGIDX_BIT(MAC_INTF_REG_OFFSET, 3U), /*!< WUM status flag */ + ENET_MAC_INT_FLAG_MSC = ENET_REGIDX_BIT(MAC_INTF_REG_OFFSET, 4U), /*!< MSC status flag */ + ENET_MAC_INT_FLAG_MSCR = ENET_REGIDX_BIT(MAC_INTF_REG_OFFSET, 5U), /*!< MSC receive status flag */ + ENET_MAC_INT_FLAG_MSCT = ENET_REGIDX_BIT(MAC_INTF_REG_OFFSET, 6U), /*!< MSC transmit status flag */ + ENET_MAC_INT_FLAG_TMST = ENET_REGIDX_BIT(MAC_INTF_REG_OFFSET, 9U), /*!< timestamp trigger status flag */ + /* ENET_MSC_RINTF register */ + ENET_MSC_INT_FLAG_RFCE = ENET_REGIDX_BIT(MSC_RINTF_REG_OFFSET, 5U), /*!< received frames CRC error flag */ + ENET_MSC_INT_FLAG_RFAE = ENET_REGIDX_BIT(MSC_RINTF_REG_OFFSET, 6U), /*!< received frames alignment error flag */ + ENET_MSC_INT_FLAG_RGUF = ENET_REGIDX_BIT(MSC_RINTF_REG_OFFSET, 17U), /*!< received good unicast frames flag */ + /* ENET_MSC_TINTF register */ + ENET_MSC_INT_FLAG_TGFSC = ENET_REGIDX_BIT(MSC_TINTF_REG_OFFSET, 14U), /*!< transmitted good frames single collision flag */ + ENET_MSC_INT_FLAG_TGFMSC = ENET_REGIDX_BIT(MSC_TINTF_REG_OFFSET, 15U), /*!< transmitted good frames more single collision flag */ + ENET_MSC_INT_FLAG_TGF = ENET_REGIDX_BIT(MSC_TINTF_REG_OFFSET, 21U), /*!< transmitted good frames flag */ + /* ENET_DMA_STAT register */ + ENET_DMA_INT_FLAG_TS = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 0U), /*!< transmit status flag */ + ENET_DMA_INT_FLAG_TPS = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 1U), /*!< transmit process stopped status flag */ + ENET_DMA_INT_FLAG_TBU = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 2U), /*!< transmit buffer unavailable status flag */ + ENET_DMA_INT_FLAG_TJT = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 3U), /*!< transmit jabber timeout status flag */ + ENET_DMA_INT_FLAG_RO = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 4U), /*!< receive overflow status flag */ + ENET_DMA_INT_FLAG_TU = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 5U), /*!< transmit underflow status flag */ + ENET_DMA_INT_FLAG_RS = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 6U), /*!< receive status flag */ + ENET_DMA_INT_FLAG_RBU = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 7U), /*!< receive buffer unavailable status flag */ + ENET_DMA_INT_FLAG_RPS = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 8U), /*!< receive process stopped status flag */ + ENET_DMA_INT_FLAG_RWT = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 9U), /*!< receive watchdog timeout status flag */ + ENET_DMA_INT_FLAG_ET = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 10U), /*!< early transmit status flag */ + ENET_DMA_INT_FLAG_FBE = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 13U), /*!< fatal bus error status flag */ + ENET_DMA_INT_FLAG_ER = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 14U), /*!< early receive status flag */ + ENET_DMA_INT_FLAG_AI = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 15U), /*!< abnormal interrupt summary flag */ + ENET_DMA_INT_FLAG_NI = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 16U), /*!< normal interrupt summary flag */ + ENET_DMA_INT_FLAG_MSC = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 27U), /*!< MSC status flag */ + ENET_DMA_INT_FLAG_WUM = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 28U), /*!< WUM status flag */ + ENET_DMA_INT_FLAG_TST = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 29U), /*!< timestamp trigger status flag */ +}enet_int_flag_enum; + +/* ENET interrupt flag clear */ +typedef enum +{ + /* ENET_DMA_STAT register */ + ENET_DMA_INT_FLAG_TS_CLR = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 0U), /*!< transmit status flag */ + ENET_DMA_INT_FLAG_TPS_CLR = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 1U), /*!< transmit process stopped status flag */ + ENET_DMA_INT_FLAG_TBU_CLR = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 2U), /*!< transmit buffer unavailable status flag */ + ENET_DMA_INT_FLAG_TJT_CLR = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 3U), /*!< transmit jabber timeout status flag */ + ENET_DMA_INT_FLAG_RO_CLR = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 4U), /*!< receive overflow status flag */ + ENET_DMA_INT_FLAG_TU_CLR = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 5U), /*!< transmit underflow status flag */ + ENET_DMA_INT_FLAG_RS_CLR = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 6U), /*!< receive status flag */ + ENET_DMA_INT_FLAG_RBU_CLR = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 7U), /*!< receive buffer unavailable status flag */ + ENET_DMA_INT_FLAG_RPS_CLR = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 8U), /*!< receive process stopped status flag */ + ENET_DMA_INT_FLAG_RWT_CLR = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 9U), /*!< receive watchdog timeout status flag */ + ENET_DMA_INT_FLAG_ET_CLR = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 10U), /*!< early transmit status flag */ + ENET_DMA_INT_FLAG_FBE_CLR = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 13U), /*!< fatal bus error status flag */ + ENET_DMA_INT_FLAG_ER_CLR = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 14U), /*!< early receive status flag */ + ENET_DMA_INT_FLAG_AI_CLR = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 15U), /*!< abnormal interrupt summary flag */ + ENET_DMA_INT_FLAG_NI_CLR = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 16U), /*!< normal interrupt summary flag */ +}enet_int_flag_clear_enum; + +/* current RX/TX descriptor/buffer/descriptor table address get */ +typedef enum +{ + ENET_RX_DESC_TABLE = DMA_RDTADDR_REG_OFFSET, /*!< RX descriptor table */ + ENET_RX_CURRENT_DESC = DMA_CRDADDR_REG_OFFSET, /*!< current RX descriptor */ + ENET_RX_CURRENT_BUFFER = DMA_CRBADDR_REG_OFFSET, /*!< current RX buffer */ + ENET_TX_DESC_TABLE = DMA_TDTADDR_REG_OFFSET, /*!< TX descriptor table */ + ENET_TX_CURRENT_DESC = DMA_CTDADDR_REG_OFFSET, /*!< current TX descriptor */ + ENET_TX_CURRENT_BUFFER = DMA_CTBADDR_REG_OFFSET /*!< current TX buffer */ +}enet_desc_reg_enum; + +/* MAC statistics counter get */ +typedef enum +{ + ENET_MSC_TX_SCCNT = MSC_SCCNT_REG_OFFSET, /*!< MSC transmitted good frames after a single collision counter */ + ENET_MSC_TX_MSCCNT = MSC_MSCCNT_REG_OFFSET, /*!< MSC transmitted good frames after more than a single collision counter */ + ENET_MSC_TX_TGFCNT = MSC_TGFCNT_REG_OFFSET, /*!< MSC transmitted good frames counter */ + ENET_MSC_RX_RFCECNT = MSC_RFCECNT_REG_OFFSET, /*!< MSC received frames with CRC error counter */ + ENET_MSC_RX_RFAECNT = MSC_RFAECNT_REG_OFFSET, /*!< MSC received frames with alignment error counter */ + ENET_MSC_RX_RGUFCNT = MSC_RGUFCNT_REG_OFFSET /*!< MSC received good unicast frames counter */ +}enet_msc_counter_enum; + +/* function option, used for ENET initialization */ +typedef enum +{ + FORWARD_OPTION = BIT(0), /*!< configure the frame forward related parameters */ + DMABUS_OPTION = BIT(1), /*!< configure the DMA bus mode related parameters */ + DMA_MAXBURST_OPTION = BIT(2), /*!< configure the DMA max burst related parameters */ + DMA_ARBITRATION_OPTION = BIT(3), /*!< configure the DMA arbitration related parameters */ + STORE_OPTION = BIT(4), /*!< configure the store forward mode related parameters */ + DMA_OPTION = BIT(5), /*!< configure the DMA control related parameters */ + VLAN_OPTION = BIT(6), /*!< configure the VLAN tag related parameters */ + FLOWCTL_OPTION = BIT(7), /*!< configure the flow control related parameters */ + HASHH_OPTION = BIT(8), /*!< configure the hash list high 32-bit related parameters */ + HASHL_OPTION = BIT(9), /*!< configure the hash list low 32-bit related parameters */ + FILTER_OPTION = BIT(10), /*!< configure the frame filter control related parameters */ + HALFDUPLEX_OPTION = BIT(11), /*!< configure the halfduplex related parameters */ + TIMER_OPTION = BIT(12), /*!< configure the frame timer related parameters */ + INTERFRAMEGAP_OPTION = BIT(13), /*!< configure the inter frame gap related parameters */ +}enet_option_enum; + +/* phy mode and mac loopback configurations */ +typedef enum +{ + ENET_AUTO_NEGOTIATION = 0x01u, /*!< PHY auto negotiation */ + ENET_100M_FULLDUPLEX = (ENET_MAC_CFG_SPD | ENET_MAC_CFG_DPM), /*!< 100Mbit/s, full-duplex */ + ENET_100M_HALFDUPLEX = ENET_MAC_CFG_SPD , /*!< 100Mbit/s, half-duplex */ + ENET_10M_FULLDUPLEX = ENET_MAC_CFG_DPM, /*!< 10Mbit/s, full-duplex */ + ENET_10M_HALFDUPLEX = (uint32_t)0x00000000U, /*!< 10Mbit/s, half-duplex */ + ENET_LOOPBACKMODE = (ENET_MAC_CFG_LBM | ENET_MAC_CFG_DPM) /*!< MAC in loopback mode at the MII */ +}enet_mediamode_enum; + +/* IP frame checksum function */ +typedef enum +{ + ENET_NO_AUTOCHECKSUM = (uint32_t)0x00000000U, /*!< disable IP frame checksum function */ + ENET_AUTOCHECKSUM_DROP_FAILFRAMES = ENET_MAC_CFG_IPFCO, /*!< enable IP frame checksum function */ + ENET_AUTOCHECKSUM_ACCEPT_FAILFRAMES = (ENET_MAC_CFG_IPFCO|ENET_DMA_CTL_DTCERFD) /*!< enable IP frame checksum function, and the received frame + with only payload error but no other errors will not be dropped */ +}enet_chksumconf_enum; + +/* received frame filter function */ +typedef enum +{ + ENET_PROMISCUOUS_MODE = ENET_MAC_FRMF_PM, /*!< promiscuous mode enabled */ + ENET_RECEIVEALL = (int32_t)ENET_MAC_FRMF_FAR, /*!< all received frame are forwarded to application */ + ENET_BROADCAST_FRAMES_PASS = (uint32_t)0x00000000U, /*!< the address filters pass all received broadcast frames */ + ENET_BROADCAST_FRAMES_DROP = ENET_MAC_FRMF_BFRMD /*!< the address filters filter all incoming broadcast frames */ +}enet_frmrecept_enum; + +/* register group value get */ +typedef enum +{ + ALL_MAC_REG = 0, /*!< MAC register group */ + ALL_MSC_REG = 22, /*!< MSC register group */ + ALL_PTP_REG = 33, /*!< PTP register group */ + ALL_DMA_REG = 44, /*!< DMA register group */ +}enet_registers_type_enum; + +/* dma direction select */ +typedef enum +{ + ENET_DMA_TX = ENET_DMA_STAT_TP, /*!< DMA transmit direction */ + ENET_DMA_RX = ENET_DMA_STAT_RP /*!< DMA receive direction */ +}enet_dmadirection_enum; + +/* PHY operation direction select */ +typedef enum +{ + ENET_PHY_READ = (uint32_t)0x00000000, /*!< read PHY */ + ENET_PHY_WRITE = ENET_MAC_PHY_CTL_PW /*!< write PHY */ +}enet_phydirection_enum; + +/* register operation direction select */ +typedef enum +{ + ENET_REG_READ, /*!< read register */ + ENET_REG_WRITE /*!< write register */ +}enet_regdirection_enum; + +/* ENET MAC addresses */ +typedef enum +{ + ENET_MAC_ADDRESS0 = ((uint32_t)0x00000000), /*!< MAC address0 */ + ENET_MAC_ADDRESS1 = ((uint32_t)0x00000008), /*!< MAC address1 */ + ENET_MAC_ADDRESS2 = ((uint32_t)0x00000010), /*!< MAC address2 */ + ENET_MAC_ADDRESS3 = ((uint32_t)0x00000018) /*!< MAC address3 */ +}enet_macaddress_enum; + +/* descriptor information */ +typedef enum +{ + TXDESC_COLLISION_COUNT, /*!< the number of collisions occurred before the frame was transmitted */ + TXDESC_BUFFER_1_ADDR, /*!< transmit frame buffer 1 address */ + RXDESC_FRAME_LENGTH, /*!< the byte length of the received frame that was transferred to the buffer */ + RXDESC_BUFFER_1_SIZE, /*!< receive buffer 1 size */ + RXDESC_BUFFER_2_SIZE, /*!< receive buffer 2 size */ + RXDESC_BUFFER_1_ADDR /*!< receive frame buffer 1 address */ +}enet_descstate_enum; + +/* MSC counters preset mode */ +typedef enum +{ + ENET_MSC_PRESET_NONE = 0U, /*!< do not preset MSC counter */ + ENET_MSC_PRESET_HALF = ENET_MSC_CTL_PMC, /*!< preset all MSC counters to almost-half(0x7FFF FFF0) value */ + ENET_MSC_PRESET_FULL = ENET_MSC_CTL_PMC | ENET_MSC_CTL_AFHPM /*!< preset all MSC counters to almost-full(0xFFFF FFF0) value */ +}enet_msc_preset_enum; + +/* structure for initialization of the ENET */ +typedef struct +{ + uint32_t option_enable; /*!< select which function to configure */ + uint32_t forward_frame; /*!< frame forward related parameters */ + uint32_t dmabus_mode; /*!< DMA bus mode related parameters */ + uint32_t dma_maxburst; /*!< DMA max burst related parameters */ + uint32_t dma_arbitration; /*!< DMA Tx and Rx arbitration related parameters */ + uint32_t store_forward_mode; /*!< store forward mode related parameters */ + uint32_t dma_function; /*!< DMA control related parameters */ + uint32_t vlan_config; /*!< VLAN tag related parameters */ + uint32_t flow_control; /*!< flow control related parameters */ + uint32_t hashtable_high; /*!< hash list high 32-bit related parameters */ + uint32_t hashtable_low; /*!< hash list low 32-bit related parameters */ + uint32_t framesfilter_mode; /*!< frame filter control related parameters */ + uint32_t halfduplex_param; /*!< halfduplex related parameters */ + uint32_t timer_config; /*!< frame timer related parameters */ + uint32_t interframegap; /*!< inter frame gap related parameters */ +}enet_initpara_struct; + +/* structure for ENET DMA desciptors */ +typedef struct +{ + uint32_t status; /*!< status */ + uint32_t control_buffer_size; /*!< control and buffer1, buffer2 lengths */ + uint32_t buffer1_addr; /*!< buffer1 address pointer/timestamp low */ + uint32_t buffer2_next_desc_addr; /*!< buffer2 or next descriptor address pointer/timestamp high */ + +#ifdef SELECT_DESCRIPTORS_ENHANCED_MODE + uint32_t extended_status; /*!< extended status */ + uint32_t reserved; /*!< reserved */ + uint32_t timestamp_low; /*!< timestamp low */ + uint32_t timestamp_high; /*!< timestamp high */ +#endif /* SELECT_DESCRIPTORS_ENHANCED_MODE */ + +} enet_descriptors_struct; + +/* structure of PTP system time */ +typedef struct +{ + uint32_t second; /*!< second of system time */ + uint32_t nanosecond; /*!< nanosecond of system time */ + uint32_t sign; /*!< sign of system time */ +}enet_ptp_systime_struct; + +/* mac_cfg register value */ +#define MAC_CFG_BOL(regval) (BITS(5,6) & ((uint32_t)(regval) << 5)) /*!< write value to ENET_MAC_CFG_BOL bit field */ +#define ENET_BACKOFFLIMIT_10 MAC_CFG_BOL(0) /*!< min (n, 10) */ +#define ENET_BACKOFFLIMIT_8 MAC_CFG_BOL(1) /*!< min (n, 8) */ +#define ENET_BACKOFFLIMIT_4 MAC_CFG_BOL(2) /*!< min (n, 4) */ +#define ENET_BACKOFFLIMIT_1 MAC_CFG_BOL(3) /*!< min (n, 1) */ + +#define MAC_CFG_IGBS(regval) (BITS(17,19) & ((uint32_t)(regval) << 17)) /*!< write value to ENET_MAC_CFG_IGBS bit field */ +#define ENET_INTERFRAMEGAP_96BIT MAC_CFG_IGBS(0) /*!< minimum 96 bit times */ +#define ENET_INTERFRAMEGAP_88BIT MAC_CFG_IGBS(1) /*!< minimum 88 bit times */ +#define ENET_INTERFRAMEGAP_80BIT MAC_CFG_IGBS(2) /*!< minimum 80 bit times */ +#define ENET_INTERFRAMEGAP_72BIT MAC_CFG_IGBS(3) /*!< minimum 72 bit times */ +#define ENET_INTERFRAMEGAP_64BIT MAC_CFG_IGBS(4) /*!< minimum 64 bit times */ +#define ENET_INTERFRAMEGAP_56BIT MAC_CFG_IGBS(5) /*!< minimum 56 bit times */ +#define ENET_INTERFRAMEGAP_48BIT MAC_CFG_IGBS(6) /*!< minimum 48 bit times */ +#define ENET_INTERFRAMEGAP_40BIT MAC_CFG_IGBS(7) /*!< minimum 40 bit times */ + +#define ENET_TYPEFRAME_CRC_DROP_ENABLE ENET_MAC_CFG_TFCD /*!< FCS field(last 4 bytes) of frame will be dropped before forwarding */ +#define ENET_TYPEFRAME_CRC_DROP_DISABLE ((uint32_t)0x00000000U) /*!< FCS field(last 4 bytes) of frame will not be dropped before forwarding */ +#define ENET_TYPEFRAME_CRC_DROP ENET_MAC_CFG_TFCD /*!< the function that FCS field(last 4 bytes) of frame will be dropped before forwarding */ + +#define ENET_WATCHDOG_ENABLE ((uint32_t)0x00000000U) /*!< the MAC allows no more than 2048 bytes of the frame being received */ +#define ENET_WATCHDOG_DISABLE ENET_MAC_CFG_WDD /*!< the MAC disables the watchdog timer on the receiver, and can receive frames of up to 16384 bytes */ + +#define ENET_JABBER_ENABLE ((uint32_t)0x00000000U) /*!< the maximum transmission byte is 2048 */ +#define ENET_JABBER_DISABLE ENET_MAC_CFG_JBD /*!< the maximum transmission byte can be 16384 */ + +#define ENET_CARRIERSENSE_ENABLE ((uint32_t)0x00000000U) /*!< the MAC transmitter generates carrier sense error and aborts the transmission */ +#define ENET_CARRIERSENSE_DISABLE ENET_MAC_CFG_CSD /*!< the MAC transmitter ignores the MII CRS signal during frame transmission in half-duplex mode */ + +#define ENET_SPEEDMODE_10M ((uint32_t)0x00000000U) /*!< 10 Mbit/s */ +#define ENET_SPEEDMODE_100M ENET_MAC_CFG_SPD /*!< 100 Mbit/s */ + +#define ENET_RECEIVEOWN_ENABLE ((uint32_t)0x00000000U) /*!< the MAC receives all packets that are given by the PHY while transmitting */ +#define ENET_RECEIVEOWN_DISABLE ENET_MAC_CFG_ROD /*!< the MAC disables the reception of frames in half-duplex mode */ + +#define ENET_LOOPBACKMODE_ENABLE ENET_MAC_CFG_LBM /*!< the MAC operates in loopback mode at the MII */ +#define ENET_LOOPBACKMODE_DISABLE ((uint32_t)0x00000000U) /*!< the MAC operates in normal mode */ + +#define ENET_MODE_FULLDUPLEX ENET_MAC_CFG_DPM /*!< full-duplex mode enable */ +#define ENET_MODE_HALFDUPLEX ((uint32_t)0x00000000U) /*!< half-duplex mode enable */ + +#define ENET_CHECKSUMOFFLOAD_ENABLE ENET_MAC_CFG_IPFCO /*!< IP frame checksum offload function enabled for received IP frame */ +#define ENET_CHECKSUMOFFLOAD_DISABLE ((uint32_t)0x00000000U) /*!< the checksum offload function in the receiver is disabled */ + +#define ENET_RETRYTRANSMISSION_ENABLE ((uint32_t)0x00000000U) /*!< the MAC attempts retries up to 16 times based on the settings of BOL*/ +#define ENET_RETRYTRANSMISSION_DISABLE ENET_MAC_CFG_RTD /*!< the MAC attempts only 1 transmission */ + +#define ENET_AUTO_PADCRC_DROP_ENABLE ENET_MAC_CFG_APCD /*!< the MAC strips the Pad/FCS field on received frames */ +#define ENET_AUTO_PADCRC_DROP_DISABLE ((uint32_t)0x00000000U) /*!< the MAC forwards all received frames without modify it */ +#define ENET_AUTO_PADCRC_DROP ENET_MAC_CFG_APCD /*!< the function of the MAC strips the Pad/FCS field on received frames */ + +#define ENET_DEFERRALCHECK_ENABLE ENET_MAC_CFG_DFC /*!< the deferral check function is enabled in the MAC */ +#define ENET_DEFERRALCHECK_DISABLE ((uint32_t)0x00000000U) /*!< the deferral check function is disabled */ + +/* mac_frmf register value */ +#define MAC_FRMF_PCFRM(regval) (BITS(6,7) & ((uint32_t)(regval) << 6)) /*!< write value to ENET_MAC_FRMF_PCFRM bit field */ +#define ENET_PCFRM_PREVENT_ALL MAC_FRMF_PCFRM(0) /*!< MAC prevents all control frames from reaching the application */ +#define ENET_PCFRM_PREVENT_PAUSEFRAME MAC_FRMF_PCFRM(1) /*!< MAC only forwards all other control frames except pause control frame */ +#define ENET_PCFRM_FORWARD_ALL MAC_FRMF_PCFRM(2) /*!< MAC forwards all control frames to application even if they fail the address filter */ +#define ENET_PCFRM_FORWARD_FILTERED MAC_FRMF_PCFRM(3) /*!< MAC forwards control frames that only pass the address filter */ + +#define ENET_RX_FILTER_DISABLE ENET_MAC_FRMF_FAR /*!< all received frame are forwarded to application */ +#define ENET_RX_FILTER_ENABLE ((uint32_t)0x00000000U) /*!< only the frame passed the filter can be forwarded to application */ + +#define ENET_SRC_FILTER_NORMAL_ENABLE ENET_MAC_FRMF_SAFLT /*!< filter source address */ +#define ENET_SRC_FILTER_INVERSE_ENABLE (ENET_MAC_FRMF_SAFLT | ENET_MAC_FRMF_SAIFLT) /*!< inverse source address filtering result */ +#define ENET_SRC_FILTER_DISABLE ((uint32_t)0x00000000U) /*!< source address function in filter disable */ +#define ENET_SRC_FILTER ENET_MAC_FRMF_SAFLT /*!< filter source address function */ +#define ENET_SRC_FILTER_INVERSE ENET_MAC_FRMF_SAIFLT /*!< inverse source address filtering result function */ + +#define ENET_BROADCASTFRAMES_ENABLE ((uint32_t)0x00000000U) /*!< the address filters pass all received broadcast frames */ +#define ENET_BROADCASTFRAMES_DISABLE ENET_MAC_FRMF_BFRMD /*!< the address filters filter all incoming broadcast frames */ + +#define ENET_DEST_FILTER_INVERSE_ENABLE ENET_MAC_FRMF_DAIFLT /*!< inverse DA filtering result */ +#define ENET_DEST_FILTER_INVERSE_DISABLE ((uint32_t)0x00000000U) /*!< not inverse DA filtering result */ +#define ENET_DEST_FILTER_INVERSE ENET_MAC_FRMF_DAIFLT /*!< inverse DA filtering result function */ + +#define ENET_PROMISCUOUS_ENABLE ENET_MAC_FRMF_PM /*!< promiscuous mode enabled */ +#define ENET_PROMISCUOUS_DISABLE ((uint32_t)0x00000000U) /*!< promiscuous mode disabled */ + +#define ENET_MULTICAST_FILTER_HASH_OR_PERFECT (ENET_MAC_FRMF_HMF | ENET_MAC_FRMF_HPFLT) /*!< pass multicast frames that match either the perfect or the hash filtering */ +#define ENET_MULTICAST_FILTER_HASH ENET_MAC_FRMF_HMF /*!< pass multicast frames that match the hash filtering */ +#define ENET_MULTICAST_FILTER_PERFECT ((uint32_t)0x00000000U) /*!< pass multicast frames that match the perfect filtering */ +#define ENET_MULTICAST_FILTER_NONE ENET_MAC_FRMF_MFD /*!< all multicast frames are passed */ +#define ENET_MULTICAST_FILTER_PASS ENET_MAC_FRMF_MFD /*!< pass all multicast frames function */ +#define ENET_MULTICAST_FILTER_HASH_MODE ENET_MAC_FRMF_HMF /*!< HASH multicast filter function */ +#define ENET_FILTER_MODE_EITHER ENET_MAC_FRMF_HPFLT /*!< HASH or perfect filter function */ + +#define ENET_UNICAST_FILTER_EITHER (ENET_MAC_FRMF_HUF | ENET_MAC_FRMF_HPFLT) /*!< pass unicast frames that match either the perfect or the hash filtering */ +#define ENET_UNICAST_FILTER_HASH ENET_MAC_FRMF_HUF /*!< pass unicast frames that match the hash filtering */ +#define ENET_UNICAST_FILTER_PERFECT ((uint32_t)0x00000000U) /*!< pass unicast frames that match the perfect filtering */ +#define ENET_UNICAST_FILTER_HASH_MODE ENET_MAC_FRMF_HUF /*!< HASH unicast filter function */ + +/* mac_phy_ctl register value */ +#define MAC_PHY_CTL_CLR(regval) (BITS(2,4) & ((uint32_t)(regval) << 2)) /*!< write value to ENET_MAC_PHY_CTL_CLR bit field */ +#define ENET_MDC_HCLK_DIV42 MAC_PHY_CTL_CLR(0) /*!< HCLK:60-100 MHz; MDC clock= HCLK/42 */ +#define ENET_MDC_HCLK_DIV62 MAC_PHY_CTL_CLR(1) /*!< HCLK:100-120 MHz; MDC clock= HCLK/62 */ +#define ENET_MDC_HCLK_DIV16 MAC_PHY_CTL_CLR(2) /*!< HCLK:20-35 MHz; MDC clock= HCLK/16 */ +#define ENET_MDC_HCLK_DIV26 MAC_PHY_CTL_CLR(3) /*!< HCLK:35-60 MHz; MDC clock= HCLK/26 */ + +#define MAC_PHY_CTL_PR(regval) (BITS(6,10) & ((uint32_t)(regval) << 6)) /*!< write value to ENET_MAC_PHY_CTL_PR bit field */ + +#define MAC_PHY_CTL_PA(regval) (BITS(11,15) & ((uint32_t)(regval) << 11)) /*!< write value to ENET_MAC_PHY_CTL_PA bit field */ + +/* mac_phy_data register value */ +#define MAC_PHY_DATA_PD(regval) (BITS(0,15) & ((uint32_t)(regval) << 0)) /*!< write value to ENET_MAC_PHY_DATA_PD bit field */ + +/* mac_fctl register value */ +#define MAC_FCTL_PLTS(regval) (BITS(4,5) & ((uint32_t)(regval) << 4)) /*!< write value to ENET_MAC_FCTL_PLTS bit field */ +#define ENET_PAUSETIME_MINUS4 MAC_FCTL_PLTS(0) /*!< pause time minus 4 slot times */ +#define ENET_PAUSETIME_MINUS28 MAC_FCTL_PLTS(1) /*!< pause time minus 28 slot times */ +#define ENET_PAUSETIME_MINUS144 MAC_FCTL_PLTS(2) /*!< pause time minus 144 slot times */ +#define ENET_PAUSETIME_MINUS256 MAC_FCTL_PLTS(3) /*!< pause time minus 256 slot times */ + +#define ENET_ZERO_QUANTA_PAUSE_ENABLE ((uint32_t)0x00000000U) /*!< enable the automatic zero-quanta generation function */ +#define ENET_ZERO_QUANTA_PAUSE_DISABLE ENET_MAC_FCTL_DZQP /*!< disable the automatic zero-quanta generation function */ +#define ENET_ZERO_QUANTA_PAUSE ENET_MAC_FCTL_DZQP /*!< the automatic zero-quanta generation function */ + +#define ENET_MAC0_AND_UNIQUE_ADDRESS_PAUSEDETECT ENET_MAC_FCTL_UPFDT /*!< besides the unique multicast address, MAC also use the MAC0 address to detect pause frame */ +#define ENET_UNIQUE_PAUSEDETECT ((uint32_t)0x00000000U) /*!< only the unique multicast address for pause frame which is specified in IEEE802.3 can be detected */ + +#define ENET_RX_FLOWCONTROL_ENABLE ENET_MAC_FCTL_RFCEN /*!< enable decoding function for the received pause frame and process it */ +#define ENET_RX_FLOWCONTROL_DISABLE ((uint32_t)0x00000000U) /*!< decode function for pause frame is disabled */ +#define ENET_RX_FLOWCONTROL ENET_MAC_FCTL_RFCEN /*!< decoding function for the received pause frame and process it */ + +#define ENET_TX_FLOWCONTROL_ENABLE ENET_MAC_FCTL_TFCEN /*!< enable the flow control operation in the MAC */ +#define ENET_TX_FLOWCONTROL_DISABLE ((uint32_t)0x00000000U) /*!< disable the flow control operation in the MAC */ +#define ENET_TX_FLOWCONTROL ENET_MAC_FCTL_TFCEN /*!< the flow control operation in the MAC */ + +#define ENET_BACK_PRESSURE_ENABLE ENET_MAC_FCTL_FLCBBKPA /*!< enable the back pressure operation in the MAC */ +#define ENET_BACK_PRESSURE_DISABLE ((uint32_t)0x00000000U) /*!< disable the back pressure operation in the MAC */ +#define ENET_BACK_PRESSURE ENET_MAC_FCTL_FLCBBKPA /*!< the back pressure operation in the MAC */ + +#define MAC_FCTL_PTM(regval) (BITS(16,31) & ((uint32_t)(regval) << 16)) /*!< write value to ENET_MAC_FCTL_PTM bit field */ +/* mac_vlt register value */ +#define MAC_VLT_VLTI(regval) (BITS(0,15) & ((uint32_t)(regval) << 0)) /*!< write value to ENET_MAC_VLT_VLTI bit field */ + +#define ENET_VLANTAGCOMPARISON_12BIT ENET_MAC_VLT_VLTC /*!< only low 12 bits of the VLAN tag are used for comparison */ +#define ENET_VLANTAGCOMPARISON_16BIT ((uint32_t)0x00000000U) /*!< all 16 bits of the VLAN tag are used for comparison */ + +/* mac_wum register value */ +#define ENET_WUM_FLAG_WUFFRPR ENET_MAC_WUM_WUFFRPR /*!< wakeup frame filter register poniter reset */ +#define ENET_WUM_FLAG_WUFR ENET_MAC_WUM_WUFR /*!< wakeup frame received */ +#define ENET_WUM_FLAG_MPKR ENET_MAC_WUM_MPKR /*!< magic packet received */ +#define ENET_WUM_POWER_DOWN ENET_MAC_WUM_PWD /*!< power down mode */ +#define ENET_WUM_MAGIC_PACKET_FRAME ENET_MAC_WUM_MPEN /*!< enable a wakeup event due to magic packet reception */ +#define ENET_WUM_WAKE_UP_FRAME ENET_MAC_WUM_WFEN /*!< enable a wakeup event due to wakeup frame reception */ +#define ENET_WUM_GLOBAL_UNICAST ENET_MAC_WUM_GU /*!< any received unicast frame passed filter is considered to be a wakeup frame */ + +/* mac_dbg register value */ +#define ENET_MAC_RECEIVER_NOT_IDLE ENET_MAC_DBG_MRNI /*!< MAC receiver is not in idle state */ +#define ENET_RX_ASYNCHRONOUS_FIFO_STATE ENET_MAC_DBG_RXAFS /*!< Rx asynchronous FIFO status */ +#define ENET_RXFIFO_WRITING ENET_MAC_DBG_RXFW /*!< RxFIFO is doing write operation */ +#define ENET_RXFIFO_READ_STATUS ENET_MAC_DBG_RXFRS /*!< RxFIFO read operation status */ +#define ENET_RXFIFO_STATE ENET_MAC_DBG_RXFS /*!< RxFIFO state */ +#define ENET_MAC_TRANSMITTER_NOT_IDLE ENET_MAC_DBG_MTNI /*!< MAC transmitter is not in idle state */ +#define ENET_MAC_TRANSMITTER_STATUS ENET_MAC_DBG_SOMT /*!< status of MAC transmitter */ +#define ENET_PAUSE_CONDITION_STATUS ENET_MAC_DBG_PCS /*!< pause condition status */ +#define ENET_TXFIFO_READ_STATUS ENET_MAC_DBG_TXFRS /*!< TxFIFO read operation status */ +#define ENET_TXFIFO_WRITING ENET_MAC_DBG_TXFW /*!< TxFIFO is doing write operation */ +#define ENET_TXFIFO_NOT_EMPTY ENET_MAC_DBG_TXFNE /*!< TxFIFO is not empty */ +#define ENET_TXFIFO_FULL ENET_MAC_DBG_TXFF /*!< TxFIFO is full */ + +#define GET_MAC_DBG_RXAFS(regval) GET_BITS((regval),1,2) /*!< get value of ENET_MAC_DBG_RXAFS bit field */ + +#define GET_MAC_DBG_RXFRS(regval) GET_BITS((regval),5,6) /*!< get value of ENET_MAC_DBG_RXFRS bit field */ + +#define GET_MAC_DBG_RXFS(regval) GET_BITS((regval),8,9) /*!< get value of ENET_MAC_DBG_RXFS bit field */ + +#define GET_MAC_DBG_SOMT(regval) GET_BITS((regval),17,18) /*!< get value of ENET_MAC_DBG_SOMT bit field */ + +#define GET_MAC_DBG_TXFRS(regval) GET_BITS((regval),20,21) /*!< get value of ENET_MAC_DBG_TXFRS bit field */ + +/* mac_addr0h register value */ +#define MAC_ADDR0H_ADDR0H(regval) (BITS(0,15) & ((uint32_t)(regval) << 0)) /*!< write value to ENET_MAC_ADDR0H_ADDR0H bit field */ + +/* mac_addrxh register value, x = 1,2,3 */ +#define MAC_ADDR123H_ADDR123H(regval) (BITS(0,15) & ((uint32_t)(regval) << 0)) /*!< write value to ENET_MAC_ADDRxH_ADDRxH(x=1,2,3) bit field */ + +#define ENET_ADDRESS_MASK_BYTE0 BIT(24) /*!< low register bits [7:0] */ +#define ENET_ADDRESS_MASK_BYTE1 BIT(25) /*!< low register bits [15:8] */ +#define ENET_ADDRESS_MASK_BYTE2 BIT(26) /*!< low register bits [23:16] */ +#define ENET_ADDRESS_MASK_BYTE3 BIT(27) /*!< low register bits [31:24] */ +#define ENET_ADDRESS_MASK_BYTE4 BIT(28) /*!< high register bits [7:0] */ +#define ENET_ADDRESS_MASK_BYTE5 BIT(29) /*!< high register bits [15:8] */ + +#define ENET_ADDRESS_FILTER_SA BIT(30) /*!< use MAC address[47:0] is to compare with the SA fields of the received frame */ +#define ENET_ADDRESS_FILTER_DA ((uint32_t)0x00000000) /*!< use MAC address[47:0] is to compare with the DA fields of the received frame */ + +/* mac_fcth register value */ +#define MAC_FCTH_RFA(regval) ((BITS(0,2) & ((uint32_t)(regval) << 0)) << 8) /*!< write value to ENET_MAC_FCTH_RFA bit field */ +#define ENET_ACTIVE_THRESHOLD_256BYTES MAC_FCTH_RFA(0) /*!< threshold level is 256 bytes */ +#define ENET_ACTIVE_THRESHOLD_512BYTES MAC_FCTH_RFA(1) /*!< threshold level is 512 bytes */ +#define ENET_ACTIVE_THRESHOLD_768BYTES MAC_FCTH_RFA(2) /*!< threshold level is 768 bytes */ +#define ENET_ACTIVE_THRESHOLD_1024BYTES MAC_FCTH_RFA(3) /*!< threshold level is 1024 bytes */ +#define ENET_ACTIVE_THRESHOLD_1280BYTES MAC_FCTH_RFA(4) /*!< threshold level is 1280 bytes */ +#define ENET_ACTIVE_THRESHOLD_1536BYTES MAC_FCTH_RFA(5) /*!< threshold level is 1536 bytes */ +#define ENET_ACTIVE_THRESHOLD_1792BYTES MAC_FCTH_RFA(6) /*!< threshold level is 1792 bytes */ + +#define MAC_FCTH_RFD(regval) ((BITS(4,6) & ((uint32_t)(regval) << 4)) << 8) /*!< write value to ENET_MAC_FCTH_RFD bit field */ +#define ENET_DEACTIVE_THRESHOLD_256BYTES MAC_FCTH_RFD(0) /*!< threshold level is 256 bytes */ +#define ENET_DEACTIVE_THRESHOLD_512BYTES MAC_FCTH_RFD(1) /*!< threshold level is 512 bytes */ +#define ENET_DEACTIVE_THRESHOLD_768BYTES MAC_FCTH_RFD(2) /*!< threshold level is 768 bytes */ +#define ENET_DEACTIVE_THRESHOLD_1024BYTES MAC_FCTH_RFD(3) /*!< threshold level is 1024 bytes */ +#define ENET_DEACTIVE_THRESHOLD_1280BYTES MAC_FCTH_RFD(4) /*!< threshold level is 1280 bytes */ +#define ENET_DEACTIVE_THRESHOLD_1536BYTES MAC_FCTH_RFD(5) /*!< threshold level is 1536 bytes */ +#define ENET_DEACTIVE_THRESHOLD_1792BYTES MAC_FCTH_RFD(6) /*!< threshold level is 1792 bytes */ + +/* msc_ctl register value */ +#define ENET_MSC_COUNTER_STOP_ROLLOVER ENET_MSC_CTL_CTSR /*!< counter stop rollover */ +#define ENET_MSC_RESET_ON_READ ENET_MSC_CTL_RTOR /*!< reset on read */ +#define ENET_MSC_COUNTERS_FREEZE ENET_MSC_CTL_MCFZ /*!< MSC counter freeze */ + +/* ptp_tsctl register value */ +#define PTP_TSCTL_CKNT(regval) (BITS(16,17) & ((uint32_t)(regval) << 16)) /*!< write value to ENET_PTP_TSCTL_CKNT bit field */ + +#define ENET_RXTX_TIMESTAMP ENET_PTP_TSCTL_TMSEN /*!< enable timestamp function for transmit and receive frames */ +#define ENET_PTP_TIMESTAMP_INT ENET_PTP_TSCTL_TMSITEN /*!< timestamp interrupt trigger enable */ +#define ENET_ALL_RX_TIMESTAMP ENET_PTP_TSCTL_ARFSEN /*!< all received frames are taken snapshot */ +#define ENET_NONTYPE_FRAME_SNAPSHOT ENET_PTP_TSCTL_ESEN /*!< take snapshot when received non type frame */ +#define ENET_IPV6_FRAME_SNAPSHOT ENET_PTP_TSCTL_IP6SEN /*!< take snapshot for IPv6 frame */ +#define ENET_IPV4_FRAME_SNAPSHOT ENET_PTP_TSCTL_IP4SEN /*!< take snapshot for IPv4 frame */ +#define ENET_PTP_FRAME_USE_MACADDRESS_FILTER ENET_PTP_TSCTL_MAFEN /*!< enable MAC address1-3 to filter the PTP frame */ + +/* ptp_ssinc register value */ +#define PTP_SSINC_STMSSI(regval) (BITS(0,7) & ((uint32_t)(regval) << 0)) /*!< write value to ENET_PTP_SSINC_STMSSI bit field */ + +/* ptp_tsl register value */ +#define GET_PTP_TSL_STMSS(regval) GET_BITS((uint32_t)(regval),0,30) /*!< get value of ENET_PTP_TSL_STMSS bit field */ + +#define ENET_PTP_TIME_POSITIVE ((uint32_t)0x00000000) /*!< time value is positive */ +#define ENET_PTP_TIME_NEGATIVE ENET_PTP_TSL_STS /*!< time value is negative */ + +#define GET_PTP_TSL_STS(regval) (((regval) & BIT(31)) >> (31U)) /*!< get value of ENET_PTP_TSL_STS bit field */ + +/* ptp_tsul register value */ +#define PTP_TSUL_TMSUSS(regval) (BITS(0,30) & ((uint32_t)(regval) << 0)) /*!< write value to ENET_PTP_TSUL_TMSUSS bit field */ + +#define ENET_PTP_ADD_TO_TIME ((uint32_t)0x00000000) /*!< timestamp update value is added to system time */ +#define ENET_PTP_SUBSTRACT_FROM_TIME ENET_PTP_TSUL_TMSUPNS /*!< timestamp update value is subtracted from system time */ + +/* ptp_ppsctl register value */ +#define PTP_PPSCTL_PPSOFC(regval) (BITS(0,3) & ((uint32_t)(regval) << 0)) /*!< write value to ENET_PTP_PPSCTL_PPSOFC bit field */ +#define ENET_PPSOFC_1HZ PTP_PPSCTL_PPSOFC(0) /*!< PPS output 1Hz frequency */ +#define ENET_PPSOFC_2HZ PTP_PPSCTL_PPSOFC(1) /*!< PPS output 2Hz frequency */ +#define ENET_PPSOFC_4HZ PTP_PPSCTL_PPSOFC(2) /*!< PPS output 4Hz frequency */ +#define ENET_PPSOFC_8HZ PTP_PPSCTL_PPSOFC(3) /*!< PPS output 8Hz frequency */ +#define ENET_PPSOFC_16HZ PTP_PPSCTL_PPSOFC(4) /*!< PPS output 16Hz frequency */ +#define ENET_PPSOFC_32HZ PTP_PPSCTL_PPSOFC(5) /*!< PPS output 32Hz frequency */ +#define ENET_PPSOFC_64HZ PTP_PPSCTL_PPSOFC(6) /*!< PPS output 64Hz frequency */ +#define ENET_PPSOFC_128HZ PTP_PPSCTL_PPSOFC(7) /*!< PPS output 128Hz frequency */ +#define ENET_PPSOFC_256HZ PTP_PPSCTL_PPSOFC(8) /*!< PPS output 256Hz frequency */ +#define ENET_PPSOFC_512HZ PTP_PPSCTL_PPSOFC(9) /*!< PPS output 512Hz frequency */ +#define ENET_PPSOFC_1024HZ PTP_PPSCTL_PPSOFC(10) /*!< PPS output 1024Hz frequency */ +#define ENET_PPSOFC_2048HZ PTP_PPSCTL_PPSOFC(11) /*!< PPS output 2048Hz frequency */ +#define ENET_PPSOFC_4096HZ PTP_PPSCTL_PPSOFC(12) /*!< PPS output 4096Hz frequency */ +#define ENET_PPSOFC_8192HZ PTP_PPSCTL_PPSOFC(13) /*!< PPS output 8192Hz frequency */ +#define ENET_PPSOFC_16384HZ PTP_PPSCTL_PPSOFC(14) /*!< PPS output 16384Hz frequency */ +#define ENET_PPSOFC_32768HZ PTP_PPSCTL_PPSOFC(15) /*!< PPS output 32768Hz frequency */ + +/* dma_bctl register value */ +#define DMA_BCTL_DPSL(regval) (BITS(2,6) & ((uint32_t)(regval) << 2)) /*!< write value to ENET_DMA_BCTL_DPSL bit field */ +#define GET_DMA_BCTL_DPSL(regval) GET_BITS((regval),2,6) /*!< get value of ENET_DMA_BCTL_DPSL bit field */ + +#define ENET_ENHANCED_DESCRIPTOR ENET_DMA_BCTL_DFM /*!< enhanced mode descriptor */ +#define ENET_NORMAL_DESCRIPTOR ((uint32_t)0x00000000) /*!< normal mode descriptor */ + +#define DMA_BCTL_PGBL(regval) (BITS(8,13) & ((uint32_t)(regval) << 8)) /*!< write value to ENET_DMA_BCTL_PGBL bit field */ +#define ENET_PGBL_1BEAT DMA_BCTL_PGBL(1) /*!< maximum number of beats is 1 */ +#define ENET_PGBL_2BEAT DMA_BCTL_PGBL(2) /*!< maximum number of beats is 2 */ +#define ENET_PGBL_4BEAT DMA_BCTL_PGBL(4) /*!< maximum number of beats is 4 */ +#define ENET_PGBL_8BEAT DMA_BCTL_PGBL(8) /*!< maximum number of beats is 8 */ +#define ENET_PGBL_16BEAT DMA_BCTL_PGBL(16) /*!< maximum number of beats is 16 */ +#define ENET_PGBL_32BEAT DMA_BCTL_PGBL(32) /*!< maximum number of beats is 32 */ +#define ENET_PGBL_4xPGBL_4BEAT (DMA_BCTL_PGBL(1)|ENET_DMA_BCTL_FPBL) /*!< maximum number of beats is 4 */ +#define ENET_PGBL_4xPGBL_8BEAT (DMA_BCTL_PGBL(2)|ENET_DMA_BCTL_FPBL) /*!< maximum number of beats is 8 */ +#define ENET_PGBL_4xPGBL_16BEAT (DMA_BCTL_PGBL(4)|ENET_DMA_BCTL_FPBL) /*!< maximum number of beats is 16 */ +#define ENET_PGBL_4xPGBL_32BEAT (DMA_BCTL_PGBL(8)|ENET_DMA_BCTL_FPBL) /*!< maximum number of beats is 32 */ +#define ENET_PGBL_4xPGBL_64BEAT (DMA_BCTL_PGBL(16)|ENET_DMA_BCTL_FPBL) /*!< maximum number of beats is 64 */ +#define ENET_PGBL_4xPGBL_128BEAT (DMA_BCTL_PGBL(32)|ENET_DMA_BCTL_FPBL) /*!< maximum number of beats is 128 */ + +#define DMA_BCTL_RTPR(regval) (BITS(14,15) & ((uint32_t)(regval) << 14)) /*!< write value to ENET_DMA_BCTL_RTPR bit field */ +#define ENET_ARBITRATION_RXTX_1_1 DMA_BCTL_RTPR(0) /*!< receive and transmit priority ratio is 1:1*/ +#define ENET_ARBITRATION_RXTX_2_1 DMA_BCTL_RTPR(1) /*!< receive and transmit priority ratio is 2:1*/ +#define ENET_ARBITRATION_RXTX_3_1 DMA_BCTL_RTPR(2) /*!< receive and transmit priority ratio is 3:1 */ +#define ENET_ARBITRATION_RXTX_4_1 DMA_BCTL_RTPR(3) /*!< receive and transmit priority ratio is 4:1 */ +#define ENET_ARBITRATION_RXPRIORTX ENET_DMA_BCTL_DAB /*!< RxDMA has higher priority than TxDMA */ + +#define ENET_FIXED_BURST_ENABLE ENET_DMA_BCTL_FB /*!< AHB can only use SINGLE/INCR4/INCR8/INCR16 during start of normal burst transfers */ +#define ENET_FIXED_BURST_DISABLE ((uint32_t)0x00000000) /*!< AHB can use SINGLE/INCR burst transfer operations */ + +#define DMA_BCTL_RXDP(regval) (BITS(17,22) & ((uint32_t)(regval) << 17)) /*!< write value to ENET_DMA_BCTL_RXDP bit field */ +#define ENET_RXDP_1BEAT DMA_BCTL_RXDP(1) /*!< maximum number of beats 1 */ +#define ENET_RXDP_2BEAT DMA_BCTL_RXDP(2) /*!< maximum number of beats 2 */ +#define ENET_RXDP_4BEAT DMA_BCTL_RXDP(4) /*!< maximum number of beats 4 */ +#define ENET_RXDP_8BEAT DMA_BCTL_RXDP(8) /*!< maximum number of beats 8 */ +#define ENET_RXDP_16BEAT DMA_BCTL_RXDP(16) /*!< maximum number of beats 16 */ +#define ENET_RXDP_32BEAT DMA_BCTL_RXDP(32) /*!< maximum number of beats 32 */ +#define ENET_RXDP_4xPGBL_4BEAT (DMA_BCTL_RXDP(1)|ENET_DMA_BCTL_FPBL) /*!< maximum number of beats 4 */ +#define ENET_RXDP_4xPGBL_8BEAT (DMA_BCTL_RXDP(2)|ENET_DMA_BCTL_FPBL) /*!< maximum number of beats 8 */ +#define ENET_RXDP_4xPGBL_16BEAT (DMA_BCTL_RXDP(4)|ENET_DMA_BCTL_FPBL) /*!< maximum number of beats 16 */ +#define ENET_RXDP_4xPGBL_32BEAT (DMA_BCTL_RXDP(8)|ENET_DMA_BCTL_FPBL) /*!< maximum number of beats 32 */ +#define ENET_RXDP_4xPGBL_64BEAT (DMA_BCTL_RXDP(16)|ENET_DMA_BCTL_FPBL) /*!< maximum number of beats 64 */ +#define ENET_RXDP_4xPGBL_128BEAT (DMA_BCTL_RXDP(32)|ENET_DMA_BCTL_FPBL) /*!< maximum number of beats 128 */ + +#define ENET_RXTX_DIFFERENT_PGBL ENET_DMA_BCTL_UIP /*!< RxDMA uses the RXDP[5:0], while TxDMA uses the PGBL[5:0] */ +#define ENET_RXTX_SAME_PGBL ((uint32_t)0x00000000) /*!< RxDMA/TxDMA uses PGBL[5:0] */ + +#define ENET_ADDRESS_ALIGN_ENABLE ENET_DMA_BCTL_AA /*!< enabled address-aligned */ +#define ENET_ADDRESS_ALIGN_DISABLE ((uint32_t)0x00000000) /*!< disable address-aligned */ + +#define ENET_MIXED_BURST_ENABLE ENET_DMA_BCTL_MB /*!< AHB master interface transfer burst length greater than 16 with INCR */ +#define ENET_MIXED_BURST_DISABLE ((uint32_t)0x00000000) /*!< AHB master interface only transfer fixed burst length with 16 and below */ + +/* dma_stat register value */ +#define GET_DMA_STAT_RP(regval) GET_BITS((uint32_t)(regval),17,19) /*!< get value of ENET_DMA_STAT_RP bit field */ +#define ENET_RX_STATE_STOPPED ((uint32_t)0x00000000) /*!< reset or stop rx command issued */ +#define ENET_RX_STATE_FETCHING BIT(17) /*!< fetching the Rx descriptor */ +#define ENET_RX_STATE_WAITING (BIT(17)|BIT(18)) /*!< waiting for receive packet */ +#define ENET_RX_STATE_SUSPENDED BIT(19) /*!< Rx descriptor unavailable */ +#define ENET_RX_STATE_CLOSING (BIT(17)|BIT(19)) /*!< closing receive descriptor */ +#define ENET_RX_STATE_QUEUING ENET_DMA_STAT_RP /*!< transferring the receive packet data from recevie buffer to host memory */ + +#define GET_DMA_STAT_TP(regval) GET_BITS((uint32_t)(regval),20,22) /*!< get value of ENET_DMA_STAT_TP bit field */ +#define ENET_TX_STATE_STOPPED ((uint32_t)0x00000000) /*!< reset or stop Tx Command issued */ +#define ENET_TX_STATE_FETCHING BIT(20) /*!< fetching the Tx descriptor */ +#define ENET_TX_STATE_WAITING BIT(21) /*!< waiting for status */ +#define ENET_TX_STATE_READING (BIT(20)|BIT(21)) /*!< reading the data from host memory buffer and queuing it to transmit buffer */ +#define ENET_TX_STATE_SUSPENDED (BIT(21)|BIT(22)) /*!< Tx descriptor unavailabe or transmit buffer underflow */ +#define ENET_TX_STATE_CLOSING ENET_DMA_STAT_TP /*!< closing Tx descriptor */ + +#define GET_DMA_STAT_EB(regval) GET_BITS((uint32_t)(regval),23,25) /*!< get value of ENET_DMA_STAT_EB bit field */ +#define ENET_ERROR_TXDATA_TRANSFER BIT(23) /*!< error during data transfer by TxDMA or RxDMA */ +#define ENET_ERROR_READ_TRANSFER BIT(24) /*!< error during write transfer or read transfer */ +#define ENET_ERROR_DESC_ACCESS BIT(25) /*!< error during descriptor or buffer access */ + +/* dma_ctl register value */ +#define DMA_CTL_RTHC(regval) (BITS(3,4) & ((uint32_t)(regval) << 3)) /*!< write value to ENET_DMA_CTL_RTHC bit field */ +#define ENET_RX_THRESHOLD_64BYTES DMA_CTL_RTHC(0) /*!< threshold level is 64 Bytes */ +#define ENET_RX_THRESHOLD_32BYTES DMA_CTL_RTHC(1) /*!< threshold level is 32 Bytes */ +#define ENET_RX_THRESHOLD_96BYTES DMA_CTL_RTHC(2) /*!< threshold level is 96 Bytes */ +#define ENET_RX_THRESHOLD_128BYTES DMA_CTL_RTHC(3) /*!< threshold level is 128 Bytes */ + +#define DMA_CTL_TTHC(regval) (BITS(14,16) & ((uint32_t)(regval) << 14)) /*!< write value to ENET_DMA_CTL_TTHC bit field */ +#define ENET_TX_THRESHOLD_64BYTES DMA_CTL_TTHC(0) /*!< threshold level is 64 Bytes */ +#define ENET_TX_THRESHOLD_128BYTES DMA_CTL_TTHC(1) /*!< threshold level is 128 Bytes */ +#define ENET_TX_THRESHOLD_192BYTES DMA_CTL_TTHC(2) /*!< threshold level is 192 Bytes */ +#define ENET_TX_THRESHOLD_256BYTES DMA_CTL_TTHC(3) /*!< threshold level is 256 Bytes */ +#define ENET_TX_THRESHOLD_40BYTES DMA_CTL_TTHC(4) /*!< threshold level is 40 Bytes */ +#define ENET_TX_THRESHOLD_32BYTES DMA_CTL_TTHC(5) /*!< threshold level is 32 Bytes */ +#define ENET_TX_THRESHOLD_24BYTES DMA_CTL_TTHC(6) /*!< threshold level is 24 Bytes */ +#define ENET_TX_THRESHOLD_16BYTES DMA_CTL_TTHC(7) /*!< threshold level is 16 Bytes */ + +#define ENET_TCPIP_CKSUMERROR_ACCEPT ENET_DMA_CTL_DTCERFD /*!< Rx frame with only payload error but no other errors will not be dropped */ +#define ENET_TCPIP_CKSUMERROR_DROP ((uint32_t)0x00000000) /*!< all error frames will be dropped when FERF = 0 */ + +#define ENET_RX_MODE_STOREFORWARD ENET_DMA_CTL_RSFD /*!< RxFIFO operates in store-and-forward mode */ +#define ENET_RX_MODE_CUTTHROUGH ((uint32_t)0x00000000) /*!< RxFIFO operates in cut-through mode */ + +#define ENET_FLUSH_RXFRAME_ENABLE ((uint32_t)0x00000000) /*!< RxDMA flushes all frames */ +#define ENET_FLUSH_RXFRAME_DISABLE ENET_DMA_CTL_DAFRF /*!< RxDMA does not flush any frames */ +#define ENET_NO_FLUSH_RXFRAME ENET_DMA_CTL_DAFRF /*!< RxDMA does not flush frames function */ + +#define ENET_TX_MODE_STOREFORWARD ENET_DMA_CTL_TSFD /*!< TxFIFO operates in store-and-forward mode */ +#define ENET_TX_MODE_CUTTHROUGH ((uint32_t)0x00000000) /*!< TxFIFO operates in cut-through mode */ + +#define ENET_FORWARD_ERRFRAMES_ENABLE (ENET_DMA_CTL_FERF << 2) /*!< all frame received with error except runt error are forwarded to memory */ +#define ENET_FORWARD_ERRFRAMES_DISABLE ((uint32_t)0x00000000) /*!< RxFIFO drop error frame */ +#define ENET_FORWARD_ERRFRAMES (ENET_DMA_CTL_FERF << 2) /*!< the function that all frame received with error except runt error are forwarded to memory */ + +#define ENET_FORWARD_UNDERSZ_GOODFRAMES_ENABLE (ENET_DMA_CTL_FUF << 2) /*!< forward undersized good frames */ +#define ENET_FORWARD_UNDERSZ_GOODFRAMES_DISABLE ((uint32_t)0x00000000) /*!< RxFIFO drops all frames whose length is less than 64 bytes */ +#define ENET_FORWARD_UNDERSZ_GOODFRAMES (ENET_DMA_CTL_FUF << 2) /*!< the function that forwarding undersized good frames */ + +#define ENET_SECONDFRAME_OPT_ENABLE ENET_DMA_CTL_OSF /*!< TxDMA controller operate on second frame mode enable*/ +#define ENET_SECONDFRAME_OPT_DISABLE ((uint32_t)0x00000000) /*!< TxDMA controller operate on second frame mode disable */ +#define ENET_SECONDFRAME_OPT ENET_DMA_CTL_OSF /*!< TxDMA controller operate on second frame function */ + +/* dma_mfbocnt register value */ +#define GET_DMA_MFBOCNT_MSFC(regval) GET_BITS((regval),0,15) /*!< get value of ENET_DMA_MFBOCNT_MSFC bit field */ + +#define GET_DMA_MFBOCNT_MSFA(regval) GET_BITS((regval),17,27) /*!< get value of ENET_DMA_MFBOCNT_MSFA bit field */ + +/* dma_rswdc register value */ +#define DMA_RSWDC_WDCFRS(regval) (BITS(0,7) & ((uint32_t)(regval) << 0)) /*!< write value to ENET_DMA_RSWDC_WDCFRS bit field */ + +/* dma tx descriptor tdes0 register value */ +#define TDES0_CONT(regval) (BITS(3,6) & ((uint32_t)(regval) << 3)) /*!< write value to ENET DMA TDES0 CONT bit field */ +#define GET_TDES0_COCNT(regval) GET_BITS((regval),3,6) /*!< get value of ENET DMA TDES0 CONT bit field */ + +#define TDES0_CM(regval) (BITS(22,23) & ((uint32_t)(regval) << 22)) /*!< write value to ENET DMA TDES0 CM bit field */ +#define ENET_CHECKSUM_DISABLE TDES0_CM(0) /*!< checksum insertion disabled */ +#define ENET_CHECKSUM_IPV4HEADER TDES0_CM(1) /*!< only IP header checksum calculation and insertion are enabled */ +#define ENET_CHECKSUM_TCPUDPICMP_SEGMENT TDES0_CM(2) /*!< TCP/UDP/ICMP checksum insertion calculated but pseudo-header */ +#define ENET_CHECKSUM_TCPUDPICMP_FULL TDES0_CM(3) /*!< TCP/UDP/ICMP checksum insertion fully calculated */ + +/* dma tx descriptor tdes1 register value */ +#define TDES1_TB1S(regval) (BITS(0,12) & ((uint32_t)(regval) << 0)) /*!< write value to ENET DMA TDES1 TB1S bit field */ + +#define TDES1_TB2S(regval) (BITS(16,28) & ((uint32_t)(regval) << 16)) /*!< write value to ENET DMA TDES1 TB2S bit field */ + +/* dma rx descriptor rdes0 register value */ +#define RDES0_FRML(regval) (BITS(16,29) & ((uint32_t)(regval) << 16)) /*!< write value to ENET DMA RDES0 FRML bit field */ +#define GET_RDES0_FRML(regval) GET_BITS((regval),16,29) /*!< get value of ENET DMA RDES0 FRML bit field */ + +/* dma rx descriptor rdes1 register value */ +#define ENET_RECEIVE_COMPLETE_INT_ENABLE ((uint32_t)0x00000000U) /*!< RS bit immediately set after Rx completed */ +#define ENET_RECEIVE_COMPLETE_INT_DISABLE ENET_RDES1_DINTC /*!< RS bit not immediately set after Rx completed */ + +#define GET_RDES1_RB1S(regval) GET_BITS((regval),0,12) /*!< get value of ENET DMA RDES1 RB1S bit field */ + +#define GET_RDES1_RB2S(regval) GET_BITS((regval),16,28) /*!< get value of ENET DMA RDES1 RB2S bit field */ + +/* dma rx descriptor rdes4 register value */ +#define RDES4_IPPLDT(regval) (BITS(0,2) & ((uint32_t)(regval) << 0)) /*!< write value to ENET DMA RDES4 IPPLDT bit field */ +#define GET_RDES4_IPPLDT(regval) GET_BITS((regval),0,2) /*!< get value of ENET DMA RDES4 IPPLDT bit field */ + +#define RDES4_PTPMT(regval) (BITS(8,11) & ((uint32_t)(regval) << 8)) /*!< write value to ENET DMA RDES4 PTPMT bit field */ +#define GET_RDES4_PTPMT(regval) GET_BITS((regval),8,11) /*!< get value of ENET DMA RDES4 PTPMT bit field */ + +/* ENET register mask value */ +#define MAC_CFG_MASK ((uint32_t)0xFD30810FU) /*!< ENET_MAC_CFG register mask */ +#define MAC_FCTL_MASK ((uint32_t)0x0000FF41U) /*!< ENET_MAC_FCTL register mask */ +#define DMA_CTL_MASK ((uint32_t)0xF8DE3F23U) /*!< ENET_DMA_CTL register mask */ +#define DMA_BCTL_MASK ((uint32_t)0xF800007DU) /*!< ENET_DMA_BCTL register mask */ +#define ENET_MSC_PRESET_MASK (~(ENET_MSC_CTL_PMC | ENET_MSC_CTL_AFHPM)) /*!< ENET_MSC_CTL preset mask */ + +#ifdef SELECT_DESCRIPTORS_ENHANCED_MODE +#define ETH_DMATXDESC_SIZE 0x20U /*!< TxDMA enhanced descriptor size */ +#define ETH_DMARXDESC_SIZE 0x20U /*!< RxDMA enhanced descriptor size */ +#else +#define ETH_DMATXDESC_SIZE 0x10U /*!< TxDMA descriptor size */ +#define ETH_DMARXDESC_SIZE 0x10U /*!< RxDMA descriptor size */ +#endif /* SELECT_DESCRIPTORS_ENHANCED_MODE */ + + +typedef enum{ + ENET_CKNT_ORDINARY = PTP_TSCTL_CKNT(0), /*!< type of ordinary clock node type for timestamp */ + ENET_CKNT_BOUNDARY = PTP_TSCTL_CKNT(1), /*!< type of boundary clock node type for timestamp */ + ENET_CKNT_END_TO_END = PTP_TSCTL_CKNT(2), /*!< type of end-to-end transparent clock node type for timestamp */ + ENET_CKNT_PEER_TO_PEER = PTP_TSCTL_CKNT(3), /*!< type of peer-to-peer transparent clock node type for timestamp */ + ENET_PTP_SYSTIME_INIT = ENET_PTP_TSCTL_TMSSTI, /*!< timestamp initialize */ + ENET_PTP_SYSTIME_UPDATE = ENET_PTP_TSCTL_TMSSTU, /*!< timestamp update */ + ENET_PTP_ADDEND_UPDATE = ENET_PTP_TSCTL_TMSARU, /*!< addend register update */ + ENET_PTP_FINEMODE = (int32_t)(ENET_PTP_TSCTL_TMSFCU| BIT(31)), /*!< the system timestamp uses the fine method for updating */ + ENET_PTP_COARSEMODE = ENET_PTP_TSCTL_TMSFCU, /*!< the system timestamp uses the coarse method for updating */ + ENET_SUBSECOND_DIGITAL_ROLLOVER = (int32_t)(ENET_PTP_TSCTL_SCROM | BIT(31)), /*!< digital rollover mode */ + ENET_SUBSECOND_BINARY_ROLLOVER = ENET_PTP_TSCTL_SCROM, /*!< binary rollover mode */ + ENET_SNOOPING_PTP_VERSION_2 = (int32_t)(ENET_PTP_TSCTL_PFSV| BIT(31)), /*!< version 2 */ + ENET_SNOOPING_PTP_VERSION_1 = ENET_PTP_TSCTL_PFSV, /*!< version 1 */ + ENET_EVENT_TYPE_MESSAGES_SNAPSHOT = (int32_t)(ENET_PTP_TSCTL_ETMSEN| BIT(31)), /*!< only event type messages are taken snapshot */ + ENET_ALL_TYPE_MESSAGES_SNAPSHOT = ENET_PTP_TSCTL_ETMSEN, /*!< all type messages are taken snapshot except announce, management and signaling message */ + ENET_MASTER_NODE_MESSAGE_SNAPSHOT = (int32_t)(ENET_PTP_TSCTL_MNMSEN| BIT(31)), /*!< snapshot is only take for master node message */ + ENET_SLAVE_NODE_MESSAGE_SNAPSHOT = ENET_PTP_TSCTL_MNMSEN, /*!< snapshot is only taken for slave node message */ +}enet_ptp_function_enum; + + +/* ENET remote wake-up frame register length */ +#define ETH_WAKEUP_REGISTER_LENGTH 8U /*!< remote wake-up frame register length */ + +/* ENET frame size */ +#define ENET_MAX_FRAME_SIZE 1524U /*!< header + frame_extra + payload + CRC */ + +/* ENET delay timeout */ +#define ENET_DELAY_TO ((uint32_t)0x0004FFFFU) /*!< ENET delay timeout */ +#define ENET_RESET_TO ((uint32_t)0x000004FFU) /*!< ENET reset timeout */ + + + +/* function declarations */ +/* main function */ +/* deinitialize the ENET, and reset structure parameters for ENET initialization */ +void enet_deinit(void); +/* configure the parameters which are usually less cared for initialization */ +void enet_initpara_config(enet_option_enum option, uint32_t para); +/* initialize ENET peripheral with generally concerned parameters and the less cared parameters */ +ErrStatus enet_init(enet_mediamode_enum mediamode, enet_chksumconf_enum checksum, enet_frmrecept_enum recept); +/* reset all core internal registers located in CLK_TX and CLK_RX */ +ErrStatus enet_software_reset(void); +/* check receive frame valid and return frame size */ +uint32_t enet_rxframe_size_get(void); +/* initialize the dma tx/rx descriptors's parameters in chain mode */ +void enet_descriptors_chain_init(enet_dmadirection_enum direction); +/* initialize the dma tx/rx descriptors's parameters in ring mode */ +void enet_descriptors_ring_init(enet_dmadirection_enum direction); +/* handle current received frame data to application buffer */ +ErrStatus enet_frame_receive(uint8_t *buffer, uint32_t bufsize); +/* handle current received frame but without data copy to application buffer */ +#define ENET_NOCOPY_FRAME_RECEIVE() enet_frame_receive(NULL, 0U) +/* handle application buffer data to transmit it */ +ErrStatus enet_frame_transmit(uint8_t *buffer, uint32_t length); +/* handle current transmit frame but without data copy from application buffer */ +#define ENET_NOCOPY_FRAME_TRANSMIT(len) enet_frame_transmit(NULL, (len)) +/* configure the transmit IP frame checksum offload calculation and insertion */ +ErrStatus enet_transmit_checksum_config(enet_descriptors_struct *desc, uint32_t checksum); +/* ENET Tx and Rx function enable (include MAC and DMA module) */ +void enet_enable(void); +/* ENET Tx and Rx function disable (include MAC and DMA module) */ +void enet_disable(void); +/* configure MAC address */ +void enet_mac_address_set(enet_macaddress_enum mac_addr, uint8_t paddr[]); +/* get MAC address */ +ErrStatus enet_mac_address_get(enet_macaddress_enum mac_addr, uint8_t paddr[], uint8_t bufsize); + +/* get the ENET MAC/MSC/PTP/DMA status flag */ +FlagStatus enet_flag_get(enet_flag_enum enet_flag); +/* clear the ENET DMA status flag */ +void enet_flag_clear(enet_flag_clear_enum enet_flag); +/* enable ENET MAC/MSC/DMA interrupt */ +void enet_interrupt_enable(enet_int_enum enet_int); +/* disable ENET MAC/MSC/DMA interrupt */ +void enet_interrupt_disable(enet_int_enum enet_int); +/* get ENET MAC/MSC/DMA interrupt flag */ +FlagStatus enet_interrupt_flag_get(enet_int_flag_enum int_flag); +/* clear ENET DMA interrupt flag */ +void enet_interrupt_flag_clear(enet_int_flag_clear_enum int_flag_clear); + +/* MAC function */ +/* ENET Tx function enable (include MAC and DMA module) */ +void enet_tx_enable(void); +/* ENET Tx function disable (include MAC and DMA module) */ +void enet_tx_disable(void); +/* ENET Rx function enable (include MAC and DMA module) */ +void enet_rx_enable(void); +/* ENET Rx function disable (include MAC and DMA module) */ +void enet_rx_disable(void); +/* put registers value into the application buffer */ +void enet_registers_get(enet_registers_type_enum type, uint32_t *preg, uint32_t num); +/* get the enet debug status from the debug register */ +uint32_t enet_debug_status_get(uint32_t mac_debug); +/* enable the MAC address filter */ +void enet_address_filter_enable(enet_macaddress_enum mac_addr); +/* disable the MAC address filter */ +void enet_address_filter_disable(enet_macaddress_enum mac_addr); +/* configure the MAC address filter */ +void enet_address_filter_config(enet_macaddress_enum mac_addr, uint32_t addr_mask, uint32_t filter_type); +/* PHY interface configuration (configure SMI clock and reset PHY chip) */ +ErrStatus enet_phy_config(void); +/* write to/read from a PHY register */ +ErrStatus enet_phy_write_read(enet_phydirection_enum direction, uint16_t phy_address, uint16_t phy_reg, uint16_t *pvalue); +/* enable the loopback function of phy chip */ +ErrStatus enet_phyloopback_enable(void); +/* disable the loopback function of phy chip */ +ErrStatus enet_phyloopback_disable(void); +/* enable ENET forward feature */ +void enet_forward_feature_enable(uint32_t feature); +/* disable ENET forward feature */ +void enet_forward_feature_disable(uint32_t feature); +/* enable ENET fliter feature */ +void enet_fliter_feature_enable(uint32_t feature); +/* disable ENET fliter feature */ +void enet_fliter_feature_disable(uint32_t feature); + +/* flow control function */ +/* generate the pause frame, ENET will send pause frame after enable transmit flow control */ +ErrStatus enet_pauseframe_generate(void); +/* configure the pause frame detect type */ +void enet_pauseframe_detect_config(uint32_t detect); +/* configure the pause frame parameters */ +void enet_pauseframe_config(uint32_t pausetime, uint32_t pause_threshold); +/* configure the threshold of the flow control(deactive and active threshold) */ +void enet_flowcontrol_threshold_config(uint32_t deactive, uint32_t active); +/* enable ENET flow control feature */ +void enet_flowcontrol_feature_enable(uint32_t feature); +/* disable ENET flow control feature */ +void enet_flowcontrol_feature_disable(uint32_t feature); + +/* DMA function */ +/* get the dma transmit/receive process state */ +uint32_t enet_dmaprocess_state_get(enet_dmadirection_enum direction); +/* poll the dma transmission/reception enable */ +void enet_dmaprocess_resume(enet_dmadirection_enum direction); +/* check and recover the Rx process */ +void enet_rxprocess_check_recovery(void); +/* flush the ENET transmit fifo, and wait until the flush operation completes */ +ErrStatus enet_txfifo_flush(void); +/* get the transmit/receive address of current descriptor, or current buffer, or descriptor table */ +uint32_t enet_current_desc_address_get(enet_desc_reg_enum addr_get); +/* get the Tx or Rx descriptor information */ +uint32_t enet_desc_information_get(enet_descriptors_struct *desc, enet_descstate_enum info_get); +/* get the number of missed frames during receiving */ +void enet_missed_frame_counter_get(uint32_t *rxfifo_drop, uint32_t *rxdma_drop); + +/* descriptor function */ +/* get the bit flag of ENET dma descriptor */ +FlagStatus enet_desc_flag_get(enet_descriptors_struct *desc, uint32_t desc_flag); +/* set the bit flag of ENET dma tx descriptor */ +void enet_desc_flag_set(enet_descriptors_struct *desc, uint32_t desc_flag); +/* clear the bit flag of ENET dma tx descriptor */ +void enet_desc_flag_clear(enet_descriptors_struct *desc, uint32_t desc_flag); +/* when receiving the completed, set RS bit in ENET_DMA_STAT register will immediately set */ +void enet_rx_desc_immediate_receive_complete_interrupt(enet_descriptors_struct *desc); +/* when receiving the completed, set RS bit in ENET_DMA_STAT register will is set after a configurable delay time */ +void enet_rx_desc_delay_receive_complete_interrupt(enet_descriptors_struct *desc, uint32_t delay_time); +/* drop current receive frame */ +void enet_rxframe_drop(void); +/* enable DMA feature */ +void enet_dma_feature_enable(uint32_t feature); +/* disable DMA feature */ +void enet_dma_feature_disable(uint32_t feature); + + +/* special enhanced mode function */ +#ifdef SELECT_DESCRIPTORS_ENHANCED_MODE +/* get the bit of extended status flag in ENET DMA descriptor */ +uint32_t enet_rx_desc_enhanced_status_get(enet_descriptors_struct *desc, uint32_t desc_status); +/* configure descriptor to work in enhanced mode */ +void enet_desc_select_enhanced_mode(void); +/* initialize the dma Tx/Rx descriptors's parameters in enhanced chain mode with ptp function */ +void enet_ptp_enhanced_descriptors_chain_init(enet_dmadirection_enum direction); +/* initialize the dma Tx/Rx descriptors's parameters in enhanced ring mode with ptp function */ +void enet_ptp_enhanced_descriptors_ring_init(enet_dmadirection_enum direction); +/* receive a packet data with timestamp values to application buffer, when the DMA is in enhanced mode */ +ErrStatus enet_ptpframe_receive_enhanced_mode(uint8_t *buffer, uint32_t bufsize, uint32_t timestamp[]); +/* handle current received frame but without data copy to application buffer in PTP enhanced mode */ +#define ENET_NOCOPY_PTPFRAME_RECEIVE_ENHANCED_MODE(ptr) enet_ptpframe_receive_enhanced_mode(NULL, 0U, (ptr)) +/* send data with timestamp values in application buffer as a transmit packet, when the DMA is in enhanced mode */ +ErrStatus enet_ptpframe_transmit_enhanced_mode(uint8_t *buffer, uint32_t length, uint32_t timestamp[]); +/* handle current transmit frame but without data copy from application buffer in PTP enhanced mode */ +#define ENET_NOCOPY_PTPFRAME_TRANSMIT_ENHANCED_MODE(len, ptr) enet_ptpframe_transmit_enhanced_mode(NULL, (len), (ptr)) + +#else + +/* configure descriptor to work in normal mode */ +void enet_desc_select_normal_mode(void); +/* initialize the dma Tx/Rx descriptors's parameters in normal chain mode with ptp function */ +void enet_ptp_normal_descriptors_chain_init(enet_dmadirection_enum direction, enet_descriptors_struct *desc_ptptab); +/* initialize the dma Tx/Rx descriptors's parameters in normal ring mode with ptp function */ +void enet_ptp_normal_descriptors_ring_init(enet_dmadirection_enum direction, enet_descriptors_struct *desc_ptptab); +/* receive a packet data with timestamp values to application buffer, when the DMA is in normal mode */ +ErrStatus enet_ptpframe_receive_normal_mode(uint8_t *buffer, uint32_t bufsize, uint32_t timestamp[]); +/* handle current received frame but without data copy to application buffer in PTP normal mode */ +#define ENET_NOCOPY_PTPFRAME_RECEIVE_NORMAL_MODE(ptr) enet_ptpframe_receive_normal_mode(NULL, 0U, (ptr)) +/* send data with timestamp values in application buffer as a transmit packet, when the DMA is in normal mode */ +ErrStatus enet_ptpframe_transmit_normal_mode(uint8_t *buffer, uint32_t length, uint32_t timestamp[]); +/* handle current transmit frame but without data copy from application buffer in PTP normal mode */ +#define ENET_NOCOPY_PTPFRAME_TRANSMIT_NORMAL_MODE(len, ptr) enet_ptpframe_transmit_normal_mode(NULL, (len), (ptr)) + +#endif /* SELECT_DESCRIPTORS_ENHANCED_MODE */ + +/* WUM function */ +/* wakeup frame filter register pointer reset */ +void enet_wum_filter_register_pointer_reset(void); +/* set the remote wakeup frame registers */ +void enet_wum_filter_config(uint32_t pdata[]); +/* enable wakeup management features */ +void enet_wum_feature_enable(uint32_t feature); +/* disable wakeup management features */ +void enet_wum_feature_disable(uint32_t feature); + +/* MSC function */ +/* reset the MAC statistics counters */ +void enet_msc_counters_reset(void); +/* enable the MAC statistics counter features */ +void enet_msc_feature_enable(uint32_t feature); +/* disable the MAC statistics counter features */ +void enet_msc_feature_disable(uint32_t feature); +/* configure MAC statistics counters preset mode */ +void enet_msc_counters_preset_config(enet_msc_preset_enum mode); +/* get MAC statistics counter */ +uint32_t enet_msc_counters_get(enet_msc_counter_enum counter); + +/* PTP function */ +/* change subsecond to nanosecond */ +uint32_t enet_ptp_subsecond_2_nanosecond(uint32_t subsecond); +/* change nanosecond to subsecond */ +uint32_t enet_ptp_nanosecond_2_subsecond(uint32_t nanosecond); +/* enable the PTP features */ +void enet_ptp_feature_enable(uint32_t feature); +/* disable the PTP features */ +void enet_ptp_feature_disable(uint32_t feature); +/* configure the PTP timestamp function */ +ErrStatus enet_ptp_timestamp_function_config(enet_ptp_function_enum func); +/* configure the PTP system time subsecond increment value */ +void enet_ptp_subsecond_increment_config(uint32_t subsecond); +/* adjusting the PTP clock frequency only in fine update mode */ +void enet_ptp_timestamp_addend_config(uint32_t add); +/* initializing or adding/subtracting to second of the PTP system time */ +void enet_ptp_timestamp_update_config(uint32_t sign, uint32_t second, uint32_t subsecond); +/* configure the PTP expected target time */ +void enet_ptp_expected_time_config(uint32_t second, uint32_t nanosecond); +/* get the PTP current system time */ +void enet_ptp_system_time_get(enet_ptp_systime_struct *systime_struct); +/* configure the PPS output frequency */ +void enet_ptp_pps_output_frequency_config(uint32_t freq); +/* configure and start PTP timestamp counter */ +void enet_ptp_start(int32_t updatemethod, uint32_t init_sec, uint32_t init_subsec, uint32_t carry_cfg, uint32_t accuracy_cfg); +/* adjust frequency in fine method by configure addend register */ +void enet_ptp_finecorrection_adjfreq(int32_t carry_cfg); +/* update system time in coarse method */ +void enet_ptp_coarsecorrection_systime_update(enet_ptp_systime_struct *systime_struct); +/* set system time in fine method */ +void enet_ptp_finecorrection_settime(enet_ptp_systime_struct * systime_struct); +/* get the ptp flag status */ +FlagStatus enet_ptp_flag_get(uint32_t flag); + +/* internal function */ +/* reset the ENET initpara struct, call it before using enet_initpara_config() */ +void enet_initpara_reset(void); +#ifdef USE_DELAY +/* user can provide more timing precise _ENET_DELAY_ function */ +#define _ENET_DELAY_ delay_ms +#else +/* default _ENET_DELAY_ function with less precise timing */ +#define _ENET_DELAY_ enet_delay +#endif + +#endif /* GD32F30X_ENET_H */ diff --git a/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_standard_peripheral/Include/gd32f30x_exmc.h b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_standard_peripheral/Include/gd32f30x_exmc.h new file mode 100644 index 0000000000..96cac05fba --- /dev/null +++ b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_standard_peripheral/Include/gd32f30x_exmc.h @@ -0,0 +1,446 @@ +/*! + \file gd32f30x_exmc.h + \brief definitions for the EXMC + + \version 2017-02-10, V1.0.0, firmware for GD32F30x + \version 2018-10-10, V1.1.0, firmware for GD32F30x + \version 2018-12-25, V2.0.0, firmware for GD32F30x + \version 2020-09-30, V2.1.0, firmware for GD32F30x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef GD32F30X_EXMC_H +#define GD32F30X_EXMC_H + +#include "gd32f30x.h" + +/* EXMC definitions */ +#define EXMC (EXMC_BASE) /*!< EXMC register base address */ + +/* registers definitions */ +/* NOR/PSRAM */ +#define EXMC_SNCTL0 REG32(EXMC + 0x00U) /*!< EXMC SRAM/NOR flash control register0 */ +#define EXMC_SNTCFG0 REG32(EXMC + 0x04U) /*!< EXMC SRAM/NOR flash timing configuration register0 */ +#define EXMC_SNWTCFG0 REG32(EXMC + 0x104U) /*!< EXMC SRAM/NOR flash write timing configuration register0 */ + +#define EXMC_SNCTL1 REG32(EXMC + 0x08U) /*!< EXMC SRAM/NOR flash control register1 */ +#define EXMC_SNTCFG1 REG32(EXMC + 0x0CU) /*!< EXMC SRAM/NOR flash timing configuration register1 */ +#define EXMC_SNWTCFG1 REG32(EXMC + 0x10CU) /*!< EXMC SRAM/NOR flash write timing configuration register1 */ + +#define EXMC_SNCTL2 REG32(EXMC + 0x10U) /*!< EXMC SRAM/NOR flash control register2 */ +#define EXMC_SNTCFG2 REG32(EXMC + 0x14U) /*!< EXMC SRAM/NOR flash timing configuration register2 */ +#define EXMC_SNWTCFG2 REG32(EXMC + 0x114U) /*!< EXMC SRAM/NOR flash write timing configuration register2 */ + +#define EXMC_SNCTL3 REG32(EXMC + 0x18U) /*!< EXMC SRAM/NOR flash control register3 */ +#define EXMC_SNTCFG3 REG32(EXMC + 0x1CU) /*!< EXMC SRAM/NOR flash timing configuration register3 */ +#define EXMC_SNWTCFG3 REG32(EXMC + 0x11CU) /*!< EXMC SRAM/NOR flash write timing configuration register3 */ + +/* NAND/PC card */ +#define EXMC_NPCTL1 REG32(EXMC + 0x60U) /*!< EXMC NAND/PC card control register1 */ +#define EXMC_NPINTEN1 REG32(EXMC + 0x64U) /*!< EXMC NAND/PC card interrupt enable register1 */ +#define EXMC_NPCTCFG1 REG32(EXMC + 0x68U) /*!< EXMC NAND/PC card common space timing configuration register1 */ +#define EXMC_NPATCFG1 REG32(EXMC + 0x6CU) /*!< EXMC NAND/PC card attribute space timing configuration register1 */ +#define EXMC_NECC1 REG32(EXMC + 0x74U) /*!< EXMC NAND ECC register1 */ + +#define EXMC_NPCTL2 REG32(EXMC + 0x80U) /*!< EXMC NAND/PC card control register2 */ +#define EXMC_NPINTEN2 REG32(EXMC + 0x84U) /*!< EXMC NAND/PC card interrupt enable register2 */ +#define EXMC_NPCTCFG2 REG32(EXMC + 0x88U) /*!< EXMC NAND/PC card common space timing configuration register2 */ +#define EXMC_NPATCFG2 REG32(EXMC + 0x8CU) /*!< EXMC NAND/PC card attribute space timing configuration register2 */ +#define EXMC_NECC2 REG32(EXMC + 0x94U) /*!< EXMC NAND ECC register2 */ + +#define EXMC_NPCTL3 REG32(EXMC + 0xA0U) /*!< EXMC NAND/PC card control register3 */ +#define EXMC_NPINTEN3 REG32(EXMC + 0xA4U) /*!< EXMC NAND/PC card interrupt enable register3 */ +#define EXMC_NPCTCFG3 REG32(EXMC + 0xA8U) /*!< EXMC NAND/PC card common space timing configuration register3 */ +#define EXMC_NPATCFG3 REG32(EXMC + 0xACU) /*!< EXMC NAND/PC card attribute space timing configuration register3 */ +#define EXMC_PIOTCFG3 REG32(EXMC + 0xB0U) /*!< EXMC PC card I/O space timing configuration register */ + +/* bits definitions */ +/* EXMC_SNCTLx,x=0..3 */ +#define EXMC_SNCTL_NRBKEN BIT(0) /*!< NOR bank enable */ +#define EXMC_SNCTL_NRMUX BIT(1) /*!< NOR bank memory address/data multiplexing enable */ +#define EXMC_SNCTL_NRTP BITS(2,3) /*!< NOR bank memory type */ +#define EXMC_SNCTL_NRW BITS(4,5) /*!< NOR bank memory data bus width */ +#define EXMC_SNCTL_NREN BIT(6) /*!< NOR flash access enable */ +#define EXMC_SNCTL_SBRSTEN BIT(8) /*!< synchronous burst enable */ +#define EXMC_SNCTL_NRWTPOL BIT(9) /*!< NWAIT signal polarity */ +#define EXMC_SNCTL_WRAPEN BIT(10) /*!< wrapped burst mode enable */ +#define EXMC_SNCTL_NRWTCFG BIT(11) /*!< NWAIT signal configuration, only work in synchronous mode */ +#define EXMC_SNCTL_WREN BIT(12) /*!< write enable */ +#define EXMC_SNCTL_NRWTEN BIT(13) /*!< NWAIT signal enable */ +#define EXMC_SNCTL_EXMODEN BIT(14) /*!< extended mode enable */ +#define EXMC_SNCTL_ASYNCWAIT BIT(15) /*!< asynchronous wait enable */ +#define EXMC_SNCTL_CPS BITS(16,18) /*!< CRAM page size */ +#define EXMC_SNCTL_SYNCWR BIT(19) /*!< synchronous write config */ + +/* EXMC_SNTCFGx,x=0..3 */ +#define EXMC_SNTCFG_ASET BITS(0,3) /*!< asynchronous address setup time */ +#define EXMC_SNTCFG_AHLD BITS(4,7) /*!< asynchronous address hold time */ +#define EXMC_SNTCFG_DSET BITS(8,15) /*!< asynchronous data setup time */ +#define EXMC_SNTCFG_BUSLAT BITS(16,19) /*!< bus latency */ +#define EXMC_SNTCFG_CKDIV BITS(20,23) /*!< synchronous clock divide ratio */ +#define EXMC_SNTCFG_DLAT BITS(24,27) /*!< synchronous data latency for NOR flash */ +#define EXMC_SNTCFG_ASYNCMOD BITS(28,29) /*!< asynchronous access mode */ + +/* EXMC_SNWTCFGx,x=0..3 */ +#define EXMC_SNWTCFG_WASET BITS(0,3) /*!< asynchronous address setup time */ +#define EXMC_SNWTCFG_WAHLD BITS(4,7) /*!< asynchronous address hold time */ +#define EXMC_SNWTCFG_WDSET BITS(8,15) /*!< asynchronous data setup time */ +#define EXMC_SNWTCFG_WBUSLAT BITS(16,19) /*!< bus latency */ +#define EXMC_SNWTCFG_WASYNCMOD BITS(28,29) /*!< asynchronous access mode */ + +/* EXMC_NPCTLx,x=1..3 */ +#define EXMC_NPCTL_NDWTEN BIT(1) /*!< wait feature enable */ +#define EXMC_NPCTL_NDBKEN BIT(2) /*!< NAND bank enable */ +#define EXMC_NPCTL_NDTP BIT(3) /*!< NAND bank memory type */ +#define EXMC_NPCTL_NDW BITS(4,5) /*!< NAND bank memory data bus width */ +#define EXMC_NPCTL_ECCEN BIT(6) /*!< ECC enable */ +#define EXMC_NPCTL_CTR BITS(9,12) /*!< CLE to RE delay */ +#define EXMC_NPCTL_ATR BITS(13,16) /*!< ALE to RE delay */ +#define EXMC_NPCTL_ECCSZ BITS(17,19) /*!< ECC size */ + +/* EXMC_NPINTENx,x=1..3 */ +#define EXMC_NPINTEN_INTRS BIT(0) /*!< interrupt rising edge status */ +#define EXMC_NPINTEN_INTHS BIT(1) /*!< interrupt high-level status */ +#define EXMC_NPINTEN_INTFS BIT(2) /*!< interrupt falling edge status */ +#define EXMC_NPINTEN_INTREN BIT(3) /*!< interrupt rising edge detection enable */ +#define EXMC_NPINTEN_INTHEN BIT(4) /*!< interrupt high-level detection enable */ +#define EXMC_NPINTEN_INTFEN BIT(5) /*!< interrupt falling edge detection enable */ +#define EXMC_NPINTEN_FFEPT BIT(6) /*!< FIFO empty flag */ + +/* EXMC_NPCTCFGx,x=1..3 */ +#define EXMC_NPCTCFG_COMSET BITS(0,7) /*!< common memory setup time */ +#define EXMC_NPCTCFG_COMWAIT BITS(8,15) /*!< common memory wait time */ +#define EXMC_NPCTCFG_COMHLD BITS(16,23) /*!< common memory hold time */ +#define EXMC_NPCTCFG_COMHIZ BITS(24,31) /*!< common memory data bus HiZ time */ + +/* EXMC_NPATCFGx,x=1..3 */ +#define EXMC_NPATCFG_ATTSET BITS(0,7) /*!< attribute memory setup time */ +#define EXMC_NPATCFG_ATTWAIT BITS(8,15) /*!< attribute memory wait time */ +#define EXMC_NPATCFG_ATTHLD BITS(16,23) /*!< attribute memory hold time */ +#define EXMC_NPATCFG_ATTHIZ BITS(24,31) /*!< attribute memory data bus HiZ time */ + +/* EXMC_PIOTCFG3 */ +#define EXMC_PIOTCFG3_IOSET BITS(0,7) /*!< IO space setup time */ +#define EXMC_PIOTCFG3_IOWAIT BITS(8,15) /*!< IO space wait time */ +#define EXMC_PIOTCFG3_IOHLD BITS(16,23) /*!< IO space hold time */ +#define EXMC_PIOTCFG3_IOHIZ BITS(24,31) /*!< IO space data bus HiZ time */ + +/* EXMC_NECCx,x=1,2 */ +#define EXMC_NECC_ECC BITS(0,31) /*!< ECC result */ + +/* constants definitions */ +/* EXMC NOR/SRAM timing initialize struct */ +typedef struct +{ + uint32_t asyn_access_mode; /*!< asynchronous access mode */ + uint32_t syn_data_latency; /*!< configure the data latency */ + uint32_t syn_clk_division; /*!< configure the clock divide ratio */ + uint32_t bus_latency; /*!< configure the bus latency */ + uint32_t asyn_data_setuptime; /*!< configure the data setup time,asynchronous access mode valid */ + uint32_t asyn_address_holdtime; /*!< configure the address hold time,asynchronous access mode valid */ + uint32_t asyn_address_setuptime; /*!< configure the data setup time,asynchronous access mode valid */ +}exmc_norsram_timing_parameter_struct; + +/* EXMC NOR/SRAM initialize struct */ +typedef struct +{ + uint32_t norsram_region; /*!< select the region of EXMC NOR/SRAM bank */ + uint32_t write_mode; /*!< the write mode, synchronous mode or asynchronous mode */ + uint32_t extended_mode; /*!< enable or disable the extended mode */ + uint32_t asyn_wait; /*!< enable or disable the asynchronous wait function */ + uint32_t nwait_signal; /*!< enable or disable the NWAIT signal while in synchronous bust mode */ + uint32_t memory_write; /*!< enable or disable the write operation */ + uint32_t nwait_config; /*!< NWAIT signal configuration */ + uint32_t wrap_burst_mode; /*!< enable or disable the wrap burst mode */ + uint32_t nwait_polarity; /*!< specifies the polarity of NWAIT signal from memory */ + uint32_t burst_mode; /*!< enable or disable the burst mode */ + uint32_t databus_width; /*!< specifies the databus width of external memory */ + uint32_t memory_type; /*!< specifies the type of external memory */ + uint32_t address_data_mux; /*!< specifies whether the data bus and address bus are multiplexed */ + exmc_norsram_timing_parameter_struct* read_write_timing; /*!< timing parameters for read and write if the extended mode is not used or the timing + parameters for read if the extended mode is used */ + exmc_norsram_timing_parameter_struct* write_timing; /*!< timing parameters for write when the extended mode is used */ +}exmc_norsram_parameter_struct; + +/* EXMC NAND/PC card timing initialize struct */ +typedef struct +{ + uint32_t databus_hiztime; /*!< configure the dadtabus HiZ time for write operation */ + uint32_t holdtime; /*!< configure the address hold time(or the data hold time for write operation) */ + uint32_t waittime; /*!< configure the minimum wait time */ + uint32_t setuptime; /*!< configure the address setup time */ +}exmc_nand_pccard_timing_parameter_struct; + +/* EXMC NAND initialize struct */ +typedef struct +{ + uint32_t nand_bank; /*!< select the bank of NAND */ + uint32_t ecc_size; /*!< the page size for the ECC calculation */ + uint32_t atr_latency; /*!< configure the latency of ALE low to RB low */ + uint32_t ctr_latency; /*!< configure the latency of CLE low to RB low */ + uint32_t ecc_logic; /*!< enable or disable the ECC calculation logic */ + uint32_t databus_width; /*!< the NAND flash databus width */ + uint32_t wait_feature; /*!< enable or disable the wait feature */ + exmc_nand_pccard_timing_parameter_struct* common_space_timing; /*!< the timing parameters for NAND flash common space */ + exmc_nand_pccard_timing_parameter_struct* attribute_space_timing; /*!< the timing parameters for NAND flash attribute space */ +}exmc_nand_parameter_struct; + +/* EXMC PC card initialize struct */ +typedef struct +{ + uint32_t atr_latency; /*!< configure the latency of ALE low to RB low */ + uint32_t ctr_latency; /*!< configure the latency of CLE low to RB low */ + uint32_t wait_feature; /*!< enable or disable the wait feature */ + exmc_nand_pccard_timing_parameter_struct* common_space_timing; /*!< the timing parameters for PC card common space */ + exmc_nand_pccard_timing_parameter_struct* attribute_space_timing; /*!< the timing parameters for PC card attribute space */ + exmc_nand_pccard_timing_parameter_struct* io_space_timing; /*!< the timing parameters for PC card IO space */ +}exmc_pccard_parameter_struct; + +/* EXMC_register address */ +#define EXMC_SNCTL(region) REG32(EXMC + 0x08U * (region)) /*!< EXMC SRAM/NOR flash control registers, region = 0,1,2,3 */ +#define EXMC_SNTCFG(region) REG32(EXMC + 0x04U + 0x08U * (region)) /*!< EXMC SRAM/NOR flash timing configuration registers, region = 0,1,2,3 */ +#define EXMC_SNWTCFG(region) REG32(EXMC + 0x104U + 0x08U * (region)) /*!< EXMC SRAM/NOR flash write timing configuration registers, region = 0,1,2,3 */ + +#define EXMC_NPCTL(bank) REG32(EXMC + 0x40U + 0x20U * (bank)) /*!< EXMC NAND/PC card control registers, bank = 1,2,3 */ +#define EXMC_NPINTEN(bank) REG32(EXMC + 0x44U + 0x20U * (bank)) /*!< EXMC NAND/PC card interrupt enable registers, bank = 1,2,3 */ +#define EXMC_NPCTCFG(bank) REG32(EXMC + 0x48U + 0x20U * (bank)) /*!< EXMC NAND/PC card common space timing configuration registers, bank = 1,2,3 */ +#define EXMC_NPATCFG(bank) REG32(EXMC + 0x4CU + 0x20U * (bank)) /*!< EXMC NAND/PC card attribute space timing configuration registers, bank = 1,2,3 */ +#define EXMC_NECC(bank) REG32(EXMC + 0x54U + 0x20U * (bank)) /*!< EXMC NAND ECC registers, bank = 1,2 */ + +/* CRAM page size */ +#define SNCTL_CPS(regval) (BITS(16,18) & ((uint32_t)(regval) << 16)) +#define EXMC_CRAM_AUTO_SPLIT SNCTL_CPS(0) /*!< automatic burst split on page boundary crossing */ +#define EXMC_CRAM_PAGE_SIZE_128_BYTES SNCTL_CPS(1) /*!< page size is 128 bytes */ +#define EXMC_CRAM_PAGE_SIZE_256_BYTES SNCTL_CPS(2) /*!< page size is 256 bytes */ +#define EXMC_CRAM_PAGE_SIZE_512_BYTES SNCTL_CPS(3) /*!< page size is 512 bytes */ +#define EXMC_CRAM_PAGE_SIZE_1024_BYTES SNCTL_CPS(4) /*!< page size is 1024 bytes */ + +/* NOR bank memory data bus width */ +#define SNCTL_NRW(regval) (BITS(4,5) & ((uint32_t)(regval) << 4)) +#define EXMC_NOR_DATABUS_WIDTH_8B SNCTL_NRW(0) /*!< NOR data width is 8 bits */ +#define EXMC_NOR_DATABUS_WIDTH_16B SNCTL_NRW(1) /*!< NOR data width is 16 bits */ + +/* NOR bank memory type */ +#define SNCTL_NRTP(regval) (BITS(2,3) & ((uint32_t)(regval) << 2)) +#define EXMC_MEMORY_TYPE_SRAM SNCTL_NRTP(0) /*!< SRAM,ROM */ +#define EXMC_MEMORY_TYPE_PSRAM SNCTL_NRTP(1) /*!< PSRAM,CRAM */ +#define EXMC_MEMORY_TYPE_NOR SNCTL_NRTP(2) /*!< NOR flash */ + +/* asynchronous access mode */ +#define SNTCFG_ASYNCMOD(regval) (BITS(28,29) & ((uint32_t)(regval) << 28)) +#define EXMC_ACCESS_MODE_A SNTCFG_ASYNCMOD(0) /*!< mode A access */ +#define EXMC_ACCESS_MODE_B SNTCFG_ASYNCMOD(1) /*!< mode B access */ +#define EXMC_ACCESS_MODE_C SNTCFG_ASYNCMOD(2) /*!< mode C access */ +#define EXMC_ACCESS_MODE_D SNTCFG_ASYNCMOD(3) /*!< mode D access */ + +/* data latency for NOR flash */ +#define SNTCFG_DLAT(regval) (BITS(24,27) & ((uint32_t)(regval) << 24)) +#define EXMC_DATALAT_2_CLK SNTCFG_DLAT(0) /*!< data latency of first burst access is 2 EXMC_CLK */ +#define EXMC_DATALAT_3_CLK SNTCFG_DLAT(1) /*!< data latency of first burst access is 3 EXMC_CLK */ +#define EXMC_DATALAT_4_CLK SNTCFG_DLAT(2) /*!< data latency of first burst access is 4 EXMC_CLK */ +#define EXMC_DATALAT_5_CLK SNTCFG_DLAT(3) /*!< data latency of first burst access is 5 EXMC_CLK */ +#define EXMC_DATALAT_6_CLK SNTCFG_DLAT(4) /*!< data latency of first burst access is 6 EXMC_CLK */ +#define EXMC_DATALAT_7_CLK SNTCFG_DLAT(5) /*!< data latency of first burst access is 7 EXMC_CLK */ +#define EXMC_DATALAT_8_CLK SNTCFG_DLAT(6) /*!< data latency of first burst access is 8 EXMC_CLK */ +#define EXMC_DATALAT_9_CLK SNTCFG_DLAT(7) /*!< data latency of first burst access is 9 EXMC_CLK */ +#define EXMC_DATALAT_10_CLK SNTCFG_DLAT(8) /*!< data latency of first burst access is 10 EXMC_CLK */ +#define EXMC_DATALAT_11_CLK SNTCFG_DLAT(9) /*!< data latency of first burst access is 11 EXMC_CLK */ +#define EXMC_DATALAT_12_CLK SNTCFG_DLAT(10) /*!< data latency of first burst access is 12 EXMC_CLK */ +#define EXMC_DATALAT_13_CLK SNTCFG_DLAT(11) /*!< data latency of first burst access is 13 EXMC_CLK */ +#define EXMC_DATALAT_14_CLK SNTCFG_DLAT(12) /*!< data latency of first burst access is 14 EXMC_CLK */ +#define EXMC_DATALAT_15_CLK SNTCFG_DLAT(13) /*!< data latency of first burst access is 15 EXMC_CLK */ +#define EXMC_DATALAT_16_CLK SNTCFG_DLAT(14) /*!< data latency of first burst access is 16 EXMC_CLK */ +#define EXMC_DATALAT_17_CLK SNTCFG_DLAT(15) /*!< data latency of first burst access is 17 EXMC_CLK */ + +/* synchronous clock divide ratio */ +#define SNTCFG_CKDIV(regval) (BITS(20,23) & ((uint32_t)(regval) << 20)) +#define EXMC_SYN_CLOCK_RATIO_DISABLE SNTCFG_CKDIV(0) /*!< EXMC_CLK disable */ +#define EXMC_SYN_CLOCK_RATIO_2_CLK SNTCFG_CKDIV(1) /*!< EXMC_CLK = 2*HCLK */ +#define EXMC_SYN_CLOCK_RATIO_3_CLK SNTCFG_CKDIV(2) /*!< EXMC_CLK = 3*HCLK */ +#define EXMC_SYN_CLOCK_RATIO_4_CLK SNTCFG_CKDIV(3) /*!< EXMC_CLK = 4*HCLK */ +#define EXMC_SYN_CLOCK_RATIO_5_CLK SNTCFG_CKDIV(4) /*!< EXMC_CLK = 5*HCLK */ +#define EXMC_SYN_CLOCK_RATIO_6_CLK SNTCFG_CKDIV(5) /*!< EXMC_CLK = 6*HCLK */ +#define EXMC_SYN_CLOCK_RATIO_7_CLK SNTCFG_CKDIV(6) /*!< EXMC_CLK = 7*HCLK */ +#define EXMC_SYN_CLOCK_RATIO_8_CLK SNTCFG_CKDIV(7) /*!< EXMC_CLK = 8*HCLK */ +#define EXMC_SYN_CLOCK_RATIO_9_CLK SNTCFG_CKDIV(8) /*!< EXMC_CLK = 9*HCLK */ +#define EXMC_SYN_CLOCK_RATIO_10_CLK SNTCFG_CKDIV(9) /*!< EXMC_CLK = 10*HCLK */ +#define EXMC_SYN_CLOCK_RATIO_11_CLK SNTCFG_CKDIV(10) /*!< EXMC_CLK = 11*HCLK */ +#define EXMC_SYN_CLOCK_RATIO_12_CLK SNTCFG_CKDIV(11) /*!< EXMC_CLK = 12*HCLK */ +#define EXMC_SYN_CLOCK_RATIO_13_CLK SNTCFG_CKDIV(12) /*!< EXMC_CLK = 13*HCLK */ +#define EXMC_SYN_CLOCK_RATIO_14_CLK SNTCFG_CKDIV(13) /*!< EXMC_CLK = 14*HCLK */ +#define EXMC_SYN_CLOCK_RATIO_15_CLK SNTCFG_CKDIV(14) /*!< EXMC_CLK = 15*HCLK */ +#define EXMC_SYN_CLOCK_RATIO_16_CLK SNTCFG_CKDIV(15) /*!< EXMC_CLK = 16*HCLK */ + +/* ECC size */ +#define NPCTL_ECCSZ(regval) (BITS(17,19) & ((uint32_t)(regval) << 17)) +#define EXMC_ECC_SIZE_256BYTES NPCTL_ECCSZ(0) /* ECC size is 256 bytes */ +#define EXMC_ECC_SIZE_512BYTES NPCTL_ECCSZ(1) /* ECC size is 512 bytes */ +#define EXMC_ECC_SIZE_1024BYTES NPCTL_ECCSZ(2) /* ECC size is 1024 bytes */ +#define EXMC_ECC_SIZE_2048BYTES NPCTL_ECCSZ(3) /* ECC size is 2048 bytes */ +#define EXMC_ECC_SIZE_4096BYTES NPCTL_ECCSZ(4) /* ECC size is 4096 bytes */ +#define EXMC_ECC_SIZE_8192BYTES NPCTL_ECCSZ(5) /* ECC size is 8192 bytes */ + +/* ALE to RE delay */ +#define NPCTL_ATR(regval) (BITS(13,16) & ((uint32_t)(regval) << 13)) +#define EXMC_ALE_RE_DELAY_1_HCLK NPCTL_ATR(0) /* ALE to RE delay = 1*HCLK */ +#define EXMC_ALE_RE_DELAY_2_HCLK NPCTL_ATR(1) /* ALE to RE delay = 2*HCLK */ +#define EXMC_ALE_RE_DELAY_3_HCLK NPCTL_ATR(2) /* ALE to RE delay = 3*HCLK */ +#define EXMC_ALE_RE_DELAY_4_HCLK NPCTL_ATR(3) /* ALE to RE delay = 4*HCLK */ +#define EXMC_ALE_RE_DELAY_5_HCLK NPCTL_ATR(4) /* ALE to RE delay = 5*HCLK */ +#define EXMC_ALE_RE_DELAY_6_HCLK NPCTL_ATR(5) /* ALE to RE delay = 6*HCLK */ +#define EXMC_ALE_RE_DELAY_7_HCLK NPCTL_ATR(6) /* ALE to RE delay = 7*HCLK */ +#define EXMC_ALE_RE_DELAY_8_HCLK NPCTL_ATR(7) /* ALE to RE delay = 8*HCLK */ +#define EXMC_ALE_RE_DELAY_9_HCLK NPCTL_ATR(8) /* ALE to RE delay = 9*HCLK */ +#define EXMC_ALE_RE_DELAY_10_HCLK NPCTL_ATR(9) /* ALE to RE delay = 10*HCLK */ +#define EXMC_ALE_RE_DELAY_11_HCLK NPCTL_ATR(10) /* ALE to RE delay = 11*HCLK */ +#define EXMC_ALE_RE_DELAY_12_HCLK NPCTL_ATR(11) /* ALE to RE delay = 12*HCLK */ +#define EXMC_ALE_RE_DELAY_13_HCLK NPCTL_ATR(12) /* ALE to RE delay = 13*HCLK */ +#define EXMC_ALE_RE_DELAY_14_HCLK NPCTL_ATR(13) /* ALE to RE delay = 14*HCLK */ +#define EXMC_ALE_RE_DELAY_15_HCLK NPCTL_ATR(14) /* ALE to RE delay = 15*HCLK */ +#define EXMC_ALE_RE_DELAY_16_HCLK NPCTL_ATR(15) /* ALE to RE delay = 16*HCLK */ + +/* CLE to RE delay */ +#define NPCTL_CTR(regval) (BITS(9,12) & ((uint32_t)(regval) << 9)) +#define EXMC_CLE_RE_DELAY_1_HCLK NPCTL_CTR(0) /* CLE to RE delay = 1*HCLK */ +#define EXMC_CLE_RE_DELAY_2_HCLK NPCTL_CTR(1) /* CLE to RE delay = 2*HCLK */ +#define EXMC_CLE_RE_DELAY_3_HCLK NPCTL_CTR(2) /* CLE to RE delay = 3*HCLK */ +#define EXMC_CLE_RE_DELAY_4_HCLK NPCTL_CTR(3) /* CLE to RE delay = 4*HCLK */ +#define EXMC_CLE_RE_DELAY_5_HCLK NPCTL_CTR(4) /* CLE to RE delay = 5*HCLK */ +#define EXMC_CLE_RE_DELAY_6_HCLK NPCTL_CTR(5) /* CLE to RE delay = 6*HCLK */ +#define EXMC_CLE_RE_DELAY_7_HCLK NPCTL_CTR(6) /* CLE to RE delay = 7*HCLK */ +#define EXMC_CLE_RE_DELAY_8_HCLK NPCTL_CTR(7) /* CLE to RE delay = 8*HCLK */ +#define EXMC_CLE_RE_DELAY_9_HCLK NPCTL_CTR(8) /* CLE to RE delay = 9*HCLK */ +#define EXMC_CLE_RE_DELAY_10_HCLK NPCTL_CTR(9) /* CLE to RE delay = 10*HCLK */ +#define EXMC_CLE_RE_DELAY_11_HCLK NPCTL_CTR(10) /* CLE to RE delay = 11*HCLK */ +#define EXMC_CLE_RE_DELAY_12_HCLK NPCTL_CTR(11) /* CLE to RE delay = 12*HCLK */ +#define EXMC_CLE_RE_DELAY_13_HCLK NPCTL_CTR(12) /* CLE to RE delay = 13*HCLK */ +#define EXMC_CLE_RE_DELAY_14_HCLK NPCTL_CTR(13) /* CLE to RE delay = 14*HCLK */ +#define EXMC_CLE_RE_DELAY_15_HCLK NPCTL_CTR(14) /* CLE to RE delay = 15*HCLK */ +#define EXMC_CLE_RE_DELAY_16_HCLK NPCTL_CTR(15) /* CLE to RE delay = 16*HCLK */ + +/* NAND bank memory data bus width */ +#define NPCTL_NDW(regval) (BITS(4,5) & ((uint32_t)(regval) << 4)) +#define EXMC_NAND_DATABUS_WIDTH_8B NPCTL_NDW(0) /*!< NAND data width is 8 bits */ +#define EXMC_NAND_DATABUS_WIDTH_16B NPCTL_NDW(1) /*!< NAND data width is 16 bits */ + +/* EXMC NOR/SRAM bank region definition */ +#define EXMC_BANK0_NORSRAM_REGION0 ((uint32_t)0x00000000U) /*!< bank0 NOR/SRAM region0 */ +#define EXMC_BANK0_NORSRAM_REGION1 ((uint32_t)0x00000001U) /*!< bank0 NOR/SRAM region1 */ +#define EXMC_BANK0_NORSRAM_REGION2 ((uint32_t)0x00000002U) /*!< bank0 NOR/SRAM region2 */ +#define EXMC_BANK0_NORSRAM_REGION3 ((uint32_t)0x00000003U) /*!< bank0 NOR/SRAM region3 */ + +/* EXMC NOR/SRAM write mode */ +#define EXMC_ASYN_WRITE ((uint32_t)0x00000000U) /*!< asynchronous write mode */ +#define EXMC_SYN_WRITE EXMC_SNCTL_SYNCWR /*!< synchronous write mode */ + +/* EXMC NWAIT signal configuration */ +#define EXMC_NWAIT_CONFIG_BEFORE ((uint32_t)0x00000000U) /*!< NWAIT signal is active one data cycle before wait state */ +#define EXMC_NWAIT_CONFIG_DURING EXMC_SNCTL_NRWTCFG /*!< NWAIT signal is active during wait state */ + +/* EXMC NWAIT signal polarity configuration */ +#define EXMC_NWAIT_POLARITY_LOW ((uint32_t)0x00000000U) /*!< low level is active of NWAIT */ +#define EXMC_NWAIT_POLARITY_HIGH EXMC_SNCTL_NRWTPOL /*!< high level is active of NWAIT */ + +/* EXMC NAND/PC card bank definition */ +#define EXMC_BANK1_NAND ((uint32_t)0x00000001U) /*!< bank1 NAND flash */ +#define EXMC_BANK2_NAND ((uint32_t)0x00000002U) /*!< bank2 NAND flash */ +#define EXMC_BANK3_PCCARD ((uint32_t)0x00000003U) /*!< bank3 PC card */ + +/* EXMC flag bits */ +#define EXMC_NAND_PCCARD_FLAG_RISE EXMC_NPINTEN_INTRS /*!< interrupt rising edge status */ +#define EXMC_NAND_PCCARD_FLAG_LEVEL EXMC_NPINTEN_INTHS /*!< interrupt high-level status */ +#define EXMC_NAND_PCCARD_FLAG_FALL EXMC_NPINTEN_INTFS /*!< interrupt falling edge status */ +#define EXMC_NAND_PCCARD_FLAG_FIFOE EXMC_NPINTEN_FFEPT /*!< FIFO empty flag */ + +/* EXMC interrupt flag bits */ +#define EXMC_NAND_PCCARD_INT_FLAG_RISE EXMC_NPINTEN_INTREN /*!< rising edge interrupt and flag */ +#define EXMC_NAND_PCCARD_INT_FLAG_LEVEL EXMC_NPINTEN_INTHEN /*!< high-level interrupt and flag */ +#define EXMC_NAND_PCCARD_INT_FLAG_FALL EXMC_NPINTEN_INTFEN /*!< falling edge interrupt and flag */ + +/* function declarations */ +/* initialization functions */ +/* NOR/SRAM */ +/* deinitialize EXMC NOR/SRAM region */ +void exmc_norsram_deinit(uint32_t exmc_norsram_region); +/* initialize exmc_norsram_parameter_struct with the default values */ +void exmc_norsram_struct_para_init(exmc_norsram_parameter_struct* exmc_norsram_init_struct); +/* initialize EXMC NOR/SRAM region */ +void exmc_norsram_init(exmc_norsram_parameter_struct* exmc_norsram_init_struct); +/* enable EXMC NOR/SRAM region */ +void exmc_norsram_enable(uint32_t exmc_norsram_region); +/* disable EXMC NOR/SRAM region */ +void exmc_norsram_disable(uint32_t exmc_norsram_region); +/* NAND */ +/* deinitialize EXMC NAND bank */ +void exmc_nand_deinit(uint32_t exmc_nand_bank); +/* initialize exmc_norsram_parameter_struct with the default values */ +void exmc_nand_struct_para_init(exmc_nand_parameter_struct* exmc_nand_init_struct); +/* initialize EXMC NAND bank */ +void exmc_nand_init(exmc_nand_parameter_struct* exmc_nand_init_struct); +/* enable EXMC NAND bank */ +void exmc_nand_enable(uint32_t exmc_nand_bank); +/* disable EXMC NAND bank */ +void exmc_nand_disable(uint32_t exmc_nand_bank); +/* PC card */ +/* deinitialize EXMC PC card bank */ +void exmc_pccard_deinit(void); +/* initialize exmc_pccard_parameter_struct parameter with the default values */ +void exmc_pccard_struct_para_init(exmc_pccard_parameter_struct* exmc_pccard_init_struct); +/* initialize EXMC PC card bank */ +void exmc_pccard_init(exmc_pccard_parameter_struct* exmc_pccard_init_struct); +/* enable EXMC PC card bank */ +void exmc_pccard_enable(void); +/* disable EXMC PC card bank */ +void exmc_pccard_disable(void); + +/* function configuration */ +/* NOR/SRAM */ +/* configure CRAM page size */ +void exmc_norsram_page_size_config(uint32_t exmc_norsram_region, uint32_t page_size); +/* NAND */ +/* enable or disable the EXMC NAND ECC function */ +void exmc_nand_ecc_config(uint32_t exmc_nand_bank, ControlStatus newvalue); +/* get the EXMC ECC value */ +uint32_t exmc_ecc_get(uint32_t exmc_nand_bank); + +/* interrupt & flag functions */ +/* enable EXMC interrupt */ +void exmc_interrupt_enable(uint32_t exmc_bank,uint32_t interrupt); +/* disable EXMC interrupt */ +void exmc_interrupt_disable(uint32_t exmc_bank,uint32_t interrupt); +/* get EXMC flag status */ +FlagStatus exmc_flag_get(uint32_t exmc_bank,uint32_t flag); +/* clear EXMC flag status */ +void exmc_flag_clear(uint32_t exmc_bank,uint32_t flag); +/* get EXMC interrupt flag */ +FlagStatus exmc_interrupt_flag_get(uint32_t exmc_bank,uint32_t interrupt); +/* clear EXMC interrupt flag */ +void exmc_interrupt_flag_clear(uint32_t exmc_bank,uint32_t interrupt); + +#endif /* GD32F30X_EXMC_H */ diff --git a/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_standard_peripheral/Include/gd32f30x_exti.h b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_standard_peripheral/Include/gd32f30x_exti.h new file mode 100644 index 0000000000..36a1098968 --- /dev/null +++ b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_standard_peripheral/Include/gd32f30x_exti.h @@ -0,0 +1,255 @@ +/*! + \file gd32f30x_exti.h + \brief definitions for the EXTI + + \version 2017-02-10, V1.0.0, firmware for GD32F30x + \version 2018-10-10, V1.1.0, firmware for GD32F30x + \version 2018-12-25, V2.0.0, firmware for GD32F30x + \version 2020-09-30, V2.1.0, firmware for GD32F30x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef GD32F30X_EXTI_H +#define GD32F30X_EXTI_H + +#include "gd32f30x.h" + +/* EXTI definitions */ +#define EXTI EXTI_BASE + +/* registers definitions */ +#define EXTI_INTEN REG32(EXTI + 0x00U) /*!< interrupt enable register */ +#define EXTI_EVEN REG32(EXTI + 0x04U) /*!< event enable register */ +#define EXTI_RTEN REG32(EXTI + 0x08U) /*!< rising edge trigger enable register */ +#define EXTI_FTEN REG32(EXTI + 0x0CU) /*!< falling trigger enable register */ +#define EXTI_SWIEV REG32(EXTI + 0x10U) /*!< software interrupt event register */ +#define EXTI_PD REG32(EXTI + 0x14U) /*!< pending register */ + +/* bits definitions */ +/* EXTI_INTEN */ +#define EXTI_INTEN_INTEN0 BIT(0) /*!< interrupt from line 0 */ +#define EXTI_INTEN_INTEN1 BIT(1) /*!< interrupt from line 1 */ +#define EXTI_INTEN_INTEN2 BIT(2) /*!< interrupt from line 2 */ +#define EXTI_INTEN_INTEN3 BIT(3) /*!< interrupt from line 3 */ +#define EXTI_INTEN_INTEN4 BIT(4) /*!< interrupt from line 4 */ +#define EXTI_INTEN_INTEN5 BIT(5) /*!< interrupt from line 5 */ +#define EXTI_INTEN_INTEN6 BIT(6) /*!< interrupt from line 6 */ +#define EXTI_INTEN_INTEN7 BIT(7) /*!< interrupt from line 7 */ +#define EXTI_INTEN_INTEN8 BIT(8) /*!< interrupt from line 8 */ +#define EXTI_INTEN_INTEN9 BIT(9) /*!< interrupt from line 9 */ +#define EXTI_INTEN_INTEN10 BIT(10) /*!< interrupt from line 10 */ +#define EXTI_INTEN_INTEN11 BIT(11) /*!< interrupt from line 11 */ +#define EXTI_INTEN_INTEN12 BIT(12) /*!< interrupt from line 12 */ +#define EXTI_INTEN_INTEN13 BIT(13) /*!< interrupt from line 13 */ +#define EXTI_INTEN_INTEN14 BIT(14) /*!< interrupt from line 14 */ +#define EXTI_INTEN_INTEN15 BIT(15) /*!< interrupt from line 15 */ +#define EXTI_INTEN_INTEN16 BIT(16) /*!< interrupt from line 16 */ +#define EXTI_INTEN_INTEN17 BIT(17) /*!< interrupt from line 17 */ +#define EXTI_INTEN_INTEN18 BIT(18) /*!< interrupt from line 18 */ +#define EXTI_INTEN_INTEN19 BIT(19) /*!< interrupt from line 19 */ + +/* EXTI_EVEN */ +#define EXTI_EVEN_EVEN0 BIT(0) /*!< event from line 0 */ +#define EXTI_EVEN_EVEN1 BIT(1) /*!< event from line 1 */ +#define EXTI_EVEN_EVEN2 BIT(2) /*!< event from line 2 */ +#define EXTI_EVEN_EVEN3 BIT(3) /*!< event from line 3 */ +#define EXTI_EVEN_EVEN4 BIT(4) /*!< event from line 4 */ +#define EXTI_EVEN_EVEN5 BIT(5) /*!< event from line 5 */ +#define EXTI_EVEN_EVEN6 BIT(6) /*!< event from line 6 */ +#define EXTI_EVEN_EVEN7 BIT(7) /*!< event from line 7 */ +#define EXTI_EVEN_EVEN8 BIT(8) /*!< event from line 8 */ +#define EXTI_EVEN_EVEN9 BIT(9) /*!< event from line 9 */ +#define EXTI_EVEN_EVEN10 BIT(10) /*!< event from line 10 */ +#define EXTI_EVEN_EVEN11 BIT(11) /*!< event from line 11 */ +#define EXTI_EVEN_EVEN12 BIT(12) /*!< event from line 12 */ +#define EXTI_EVEN_EVEN13 BIT(13) /*!< event from line 13 */ +#define EXTI_EVEN_EVEN14 BIT(14) /*!< event from line 14 */ +#define EXTI_EVEN_EVEN15 BIT(15) /*!< event from line 15 */ +#define EXTI_EVEN_EVEN16 BIT(16) /*!< event from line 16 */ +#define EXTI_EVEN_EVEN17 BIT(17) /*!< event from line 17 */ +#define EXTI_EVEN_EVEN18 BIT(18) /*!< event from line 18 */ +#define EXTI_EVEN_EVEN19 BIT(19) /*!< event from line 19 */ + +/* EXTI_RTEN */ +#define EXTI_RTEN_RTEN0 BIT(0) /*!< rising edge from line 0 */ +#define EXTI_RTEN_RTEN1 BIT(1) /*!< rising edge from line 1 */ +#define EXTI_RTEN_RTEN2 BIT(2) /*!< rising edge from line 2 */ +#define EXTI_RTEN_RTEN3 BIT(3) /*!< rising edge from line 3 */ +#define EXTI_RTEN_RTEN4 BIT(4) /*!< rising edge from line 4 */ +#define EXTI_RTEN_RTEN5 BIT(5) /*!< rising edge from line 5 */ +#define EXTI_RTEN_RTEN6 BIT(6) /*!< rising edge from line 6 */ +#define EXTI_RTEN_RTEN7 BIT(7) /*!< rising edge from line 7 */ +#define EXTI_RTEN_RTEN8 BIT(8) /*!< rising edge from line 8 */ +#define EXTI_RTEN_RTEN9 BIT(9) /*!< rising edge from line 9 */ +#define EXTI_RTEN_RTEN10 BIT(10) /*!< rising edge from line 10 */ +#define EXTI_RTEN_RTEN11 BIT(11) /*!< rising edge from line 11 */ +#define EXTI_RTEN_RTEN12 BIT(12) /*!< rising edge from line 12 */ +#define EXTI_RTEN_RTEN13 BIT(13) /*!< rising edge from line 13 */ +#define EXTI_RTEN_RTEN14 BIT(14) /*!< rising edge from line 14 */ +#define EXTI_RTEN_RTEN15 BIT(15) /*!< rising edge from line 15 */ +#define EXTI_RTEN_RTEN16 BIT(16) /*!< rising edge from line 16 */ +#define EXTI_RTEN_RTEN17 BIT(17) /*!< rising edge from line 17 */ +#define EXTI_RTEN_RTEN18 BIT(18) /*!< rising edge from line 18 */ +#define EXTI_RTEN_RTEN19 BIT(19) /*!< rising edge from line 19 */ + +/* EXTI_FTEN */ +#define EXTI_FTEN_FTEN0 BIT(0) /*!< falling edge from line 0 */ +#define EXTI_FTEN_FTEN1 BIT(1) /*!< falling edge from line 1 */ +#define EXTI_FTEN_FTEN2 BIT(2) /*!< falling edge from line 2 */ +#define EXTI_FTEN_FTEN3 BIT(3) /*!< falling edge from line 3 */ +#define EXTI_FTEN_FTEN4 BIT(4) /*!< falling edge from line 4 */ +#define EXTI_FTEN_FTEN5 BIT(5) /*!< falling edge from line 5 */ +#define EXTI_FTEN_FTEN6 BIT(6) /*!< falling edge from line 6 */ +#define EXTI_FTEN_FTEN7 BIT(7) /*!< falling edge from line 7 */ +#define EXTI_FTEN_FTEN8 BIT(8) /*!< falling edge from line 8 */ +#define EXTI_FTEN_FTEN9 BIT(9) /*!< falling edge from line 9 */ +#define EXTI_FTEN_FTEN10 BIT(10) /*!< falling edge from line 10 */ +#define EXTI_FTEN_FTEN11 BIT(11) /*!< falling edge from line 11 */ +#define EXTI_FTEN_FTEN12 BIT(12) /*!< falling edge from line 12 */ +#define EXTI_FTEN_FTEN13 BIT(13) /*!< falling edge from line 13 */ +#define EXTI_FTEN_FTEN14 BIT(14) /*!< falling edge from line 14 */ +#define EXTI_FTEN_FTEN15 BIT(15) /*!< falling edge from line 15 */ +#define EXTI_FTEN_FTEN16 BIT(16) /*!< falling edge from line 16 */ +#define EXTI_FTEN_FTEN17 BIT(17) /*!< falling edge from line 17 */ +#define EXTI_FTEN_FTEN18 BIT(18) /*!< falling edge from line 18 */ +#define EXTI_FTEN_FTEN19 BIT(19) /*!< falling edge from line 19 */ + +/* EXTI_SWIEV */ +#define EXTI_SWIEV_SWIEV0 BIT(0) /*!< software interrupt/event request from line 0 */ +#define EXTI_SWIEV_SWIEV1 BIT(1) /*!< software interrupt/event request from line 1 */ +#define EXTI_SWIEV_SWIEV2 BIT(2) /*!< software interrupt/event request from line 2 */ +#define EXTI_SWIEV_SWIEV3 BIT(3) /*!< software interrupt/event request from line 3 */ +#define EXTI_SWIEV_SWIEV4 BIT(4) /*!< software interrupt/event request from line 4 */ +#define EXTI_SWIEV_SWIEV5 BIT(5) /*!< software interrupt/event request from line 5 */ +#define EXTI_SWIEV_SWIEV6 BIT(6) /*!< software interrupt/event request from line 6 */ +#define EXTI_SWIEV_SWIEV7 BIT(7) /*!< software interrupt/event request from line 7 */ +#define EXTI_SWIEV_SWIEV8 BIT(8) /*!< software interrupt/event request from line 8 */ +#define EXTI_SWIEV_SWIEV9 BIT(9) /*!< software interrupt/event request from line 9 */ +#define EXTI_SWIEV_SWIEV10 BIT(10) /*!< software interrupt/event request from line 10 */ +#define EXTI_SWIEV_SWIEV11 BIT(11) /*!< software interrupt/event request from line 11 */ +#define EXTI_SWIEV_SWIEV12 BIT(12) /*!< software interrupt/event request from line 12 */ +#define EXTI_SWIEV_SWIEV13 BIT(13) /*!< software interrupt/event request from line 13 */ +#define EXTI_SWIEV_SWIEV14 BIT(14) /*!< software interrupt/event request from line 14 */ +#define EXTI_SWIEV_SWIEV15 BIT(15) /*!< software interrupt/event request from line 15 */ +#define EXTI_SWIEV_SWIEV16 BIT(16) /*!< software interrupt/event request from line 16 */ +#define EXTI_SWIEV_SWIEV17 BIT(17) /*!< software interrupt/event request from line 17 */ +#define EXTI_SWIEV_SWIEV18 BIT(18) /*!< software interrupt/event request from line 18 */ +#define EXTI_SWIEV_SWIEV19 BIT(19) /*!< software interrupt/event request from line 19 */ + +/* EXTI_PD */ +#define EXTI_PD_PD0 BIT(0) /*!< interrupt/event pending status from line 0 */ +#define EXTI_PD_PD1 BIT(1) /*!< interrupt/event pending status from line 1 */ +#define EXTI_PD_PD2 BIT(2) /*!< interrupt/event pending status from line 2 */ +#define EXTI_PD_PD3 BIT(3) /*!< interrupt/event pending status from line 3 */ +#define EXTI_PD_PD4 BIT(4) /*!< interrupt/event pending status from line 4 */ +#define EXTI_PD_PD5 BIT(5) /*!< interrupt/event pending status from line 5 */ +#define EXTI_PD_PD6 BIT(6) /*!< interrupt/event pending status from line 6 */ +#define EXTI_PD_PD7 BIT(7) /*!< interrupt/event pending status from line 7 */ +#define EXTI_PD_PD8 BIT(8) /*!< interrupt/event pending status from line 8 */ +#define EXTI_PD_PD9 BIT(9) /*!< interrupt/event pending status from line 9 */ +#define EXTI_PD_PD10 BIT(10) /*!< interrupt/event pending status from line 10 */ +#define EXTI_PD_PD11 BIT(11) /*!< interrupt/event pending status from line 11 */ +#define EXTI_PD_PD12 BIT(12) /*!< interrupt/event pending status from line 12 */ +#define EXTI_PD_PD13 BIT(13) /*!< interrupt/event pending status from line 13 */ +#define EXTI_PD_PD14 BIT(14) /*!< interrupt/event pending status from line 14 */ +#define EXTI_PD_PD15 BIT(15) /*!< interrupt/event pending status from line 15 */ +#define EXTI_PD_PD16 BIT(16) /*!< interrupt/event pending status from line 16 */ +#define EXTI_PD_PD17 BIT(17) /*!< interrupt/event pending status from line 17 */ +#define EXTI_PD_PD18 BIT(18) /*!< interrupt/event pending status from line 18 */ +#define EXTI_PD_PD19 BIT(19) /*!< interrupt/event pending status from line 19 */ + +/* constants definitions */ +/* EXTI line number */ +typedef enum +{ + EXTI_0 = BIT(0), /*!< EXTI line 0 */ + EXTI_1 = BIT(1), /*!< EXTI line 1 */ + EXTI_2 = BIT(2), /*!< EXTI line 2 */ + EXTI_3 = BIT(3), /*!< EXTI line 3 */ + EXTI_4 = BIT(4), /*!< EXTI line 4 */ + EXTI_5 = BIT(5), /*!< EXTI line 5 */ + EXTI_6 = BIT(6), /*!< EXTI line 6 */ + EXTI_7 = BIT(7), /*!< EXTI line 7 */ + EXTI_8 = BIT(8), /*!< EXTI line 8 */ + EXTI_9 = BIT(9), /*!< EXTI line 9 */ + EXTI_10 = BIT(10), /*!< EXTI line 10 */ + EXTI_11 = BIT(11), /*!< EXTI line 11 */ + EXTI_12 = BIT(12), /*!< EXTI line 12 */ + EXTI_13 = BIT(13), /*!< EXTI line 13 */ + EXTI_14 = BIT(14), /*!< EXTI line 14 */ + EXTI_15 = BIT(15), /*!< EXTI line 15 */ + EXTI_16 = BIT(16), /*!< EXTI line 16 */ + EXTI_17 = BIT(17), /*!< EXTI line 17 */ + EXTI_18 = BIT(18), /*!< EXTI line 18 */ + EXTI_19 = BIT(19), /*!< EXTI line 19 */ +}exti_line_enum; + +/* external interrupt and event */ +typedef enum +{ + EXTI_INTERRUPT = 0, /*!< EXTI interrupt mode */ + EXTI_EVENT /*!< EXTI event mode */ +}exti_mode_enum; + +/* interrupt trigger mode */ +typedef enum +{ + EXTI_TRIG_RISING = 0, /*!< EXTI rising edge trigger */ + EXTI_TRIG_FALLING, /*!< EXTI falling edge trigger */ + EXTI_TRIG_BOTH /*!< EXTI rising and falling edge trigger */ +}exti_trig_type_enum; + +/* function declarations */ +/* deinitialize the EXTI */ +void exti_deinit(void); +/* enable the configuration of EXTI initialize */ +void exti_init(exti_line_enum linex, exti_mode_enum mode, exti_trig_type_enum trig_type); +/* enable the interrupts from EXTI line x */ +void exti_interrupt_enable(exti_line_enum linex); +/* enable the events from EXTI line x */ +void exti_event_enable(exti_line_enum linex); +/* disable the interrupts from EXTI line x */ +void exti_interrupt_disable(exti_line_enum linex); +/* disable the events from EXTI line x */ +void exti_event_disable(exti_line_enum linex); + +/* get EXTI lines pending flag */ +FlagStatus exti_flag_get(exti_line_enum linex); +/* clear EXTI lines pending flag */ +void exti_flag_clear(exti_line_enum linex); +/* get EXTI lines flag when the interrupt flag is set */ +FlagStatus exti_interrupt_flag_get(exti_line_enum linex); +/* clear EXTI lines pending flag */ +void exti_interrupt_flag_clear(exti_line_enum linex); +/* enable the EXTI software interrupt event */ +void exti_software_interrupt_enable(exti_line_enum linex); +/* disable the EXTI software interrupt event */ +void exti_software_interrupt_disable(exti_line_enum linex); + +#endif /* GD32F30X_EXTI_H */ diff --git a/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_standard_peripheral/Include/gd32f30x_fmc.h b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_standard_peripheral/Include/gd32f30x_fmc.h new file mode 100644 index 0000000000..77a2997293 --- /dev/null +++ b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_standard_peripheral/Include/gd32f30x_fmc.h @@ -0,0 +1,375 @@ +/*! + \file gd32f30x_fmc.h + \brief definitions for the FMC + + \version 2017-02-10, V1.0.0, firmware for GD32F30x + \version 2018-10-10, V1.1.0, firmware for GD32F30x + \version 2018-12-25, V2.0.0, firmware for GD32F30x + \version 2020-09-30, V2.1.0, firmware for GD32F30x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + + +#ifndef GD32F30X_FMC_H +#define GD32F30X_FMC_H + +#include "gd32f30x.h" + +/* FMC and option byte definition */ +#define FMC FMC_BASE /*!< FMC register base address */ +#define OB OB_BASE /*!< option bytes base address */ + +/* registers definitions */ +#define FMC_WS REG32((FMC) + 0x00U) /*!< FMC wait state register */ +#define FMC_KEY0 REG32((FMC) + 0x04U) /*!< FMC unlock key register 0 */ +#define FMC_OBKEY REG32((FMC) + 0x08U) /*!< FMC option bytes unlock key register */ +#define FMC_STAT0 REG32((FMC) + 0x0CU) /*!< FMC status register 0 */ +#define FMC_CTL0 REG32((FMC) + 0x10U) /*!< FMC control register 0 */ +#define FMC_ADDR0 REG32((FMC) + 0x14U) /*!< FMC address register 0 */ +#define FMC_OBSTAT REG32((FMC) + 0x1CU) /*!< FMC option bytes status register */ +#define FMC_WP REG32((FMC) + 0x20U) /*!< FMC erase/program protection register */ +#define FMC_KEY1 REG32((FMC) + 0x44U) /*!< FMC unlock key register 1 */ +#define FMC_STAT1 REG32((FMC) + 0x4CU) /*!< FMC status register 1 */ +#define FMC_CTL1 REG32((FMC) + 0x50U) /*!< FMC control register 1 */ +#define FMC_ADDR1 REG32((FMC) + 0x54U) /*!< FMC address register 1 */ +#define FMC_WSEN REG32((FMC) + 0xFCU) /*!< FMC wait state enable register */ +#define FMC_PID REG32((FMC) + 0x100U) /*!< FMC product ID register */ + +#define OB_SPC REG16((OB) + 0x00U) /*!< option byte security protection value */ +#define OB_USER REG16((OB) + 0x02U) /*!< option byte user value*/ +#define OB_DATA1 REG16((OB) + 0x04U) /*!< option byte data1 value*/ +#define OB_DATA2 REG16((OB) + 0x06U) /*!< option byte data2 value*/ +#define OB_WP0 REG16((OB) + 0x08U) /*!< option byte write protection 0 */ +#define OB_WP1 REG16((OB) + 0x0AU) /*!< option byte write protection 1 */ +#define OB_WP2 REG16((OB) + 0x0CU) /*!< option byte write protection 2 */ +#define OB_WP3 REG16((OB) + 0x0EU) /*!< option byte write protection 3 */ + +/* bits definitions */ +/* FMC_WS */ +#define FMC_WS_WSCNT BITS(0,2) /*!< wait state counter */ + +/* FMC_KEY0 */ +#define FMC_KEY0_KEY BITS(0,31) /*!< FMC_CTL0 unlock key bits */ + +/* FMC_OBKEY */ +#define FMC_OBKEY_OBKEY BITS(0,31) /*!< option bytes unlock key bits */ + +/* FMC_STAT0 */ +#define FMC_STAT0_BUSY BIT(0) /*!< flash busy flag bit */ +#define FMC_STAT0_PGERR BIT(2) /*!< flash program error flag bit */ +#define FMC_STAT0_WPERR BIT(4) /*!< erase/program protection error flag bit */ +#define FMC_STAT0_ENDF BIT(5) /*!< end of operation flag bit */ + +/* FMC_CTL0 */ +#define FMC_CTL0_PG BIT(0) /*!< main flash program for bank0 command bit */ +#define FMC_CTL0_PER BIT(1) /*!< main flash page erase for bank0 command bit */ +#define FMC_CTL0_MER BIT(2) /*!< main flash mass erase for bank0 command bit */ +#define FMC_CTL0_OBPG BIT(4) /*!< option bytes program command bit */ +#define FMC_CTL0_OBER BIT(5) /*!< option bytes erase command bit */ +#define FMC_CTL0_START BIT(6) /*!< send erase command to FMC bit */ +#define FMC_CTL0_LK BIT(7) /*!< FMC_CTL0 lock bit */ +#define FMC_CTL0_OBWEN BIT(9) /*!< option bytes erase/program enable bit */ +#define FMC_CTL0_ERRIE BIT(10) /*!< error interrupt enable bit */ +#define FMC_CTL0_ENDIE BIT(12) /*!< end of operation interrupt enable bit */ + +/* FMC_ADDR0 */ +#define FMC_ADDR0_ADDR BITS(0,31) /*!< Flash erase/program command address bits */ + +/* FMC_OBSTAT */ +#define FMC_OBSTAT_OBERR BIT(0) /*!< option bytes read error bit. */ +#define FMC_OBSTAT_SPC BIT(1) /*!< option bytes security protection code */ +#define FMC_OBSTAT_USER BITS(2,9) /*!< store USER of option bytes block after system reset */ +#define FMC_OBSTAT_DATA BITS(10,25) /*!< store DATA of option bytes block after system reset. */ + +/* FMC_WP */ +#define FMC_WP_WP BITS(0,31) /*!< store WP of option bytes block after system reset */ + +/* FMC_KEY1 */ +#define FMC_KEY1_KEY BITS(0,31) /*!< FMC_CTL1 unlock key bits */ + +/* FMC_STAT1 */ +#define FMC_STAT1_BUSY BIT(0) /*!< flash busy flag bit */ +#define FMC_STAT1_PGERR BIT(2) /*!< flash program error flag bit */ +#define FMC_STAT1_WPERR BIT(4) /*!< erase/program protection error flag bit */ +#define FMC_STAT1_ENDF BIT(5) /*!< end of operation flag bit */ + +/* FMC_CTL1 */ +#define FMC_CTL1_PG BIT(0) /*!< main flash program for bank1 command bit */ +#define FMC_CTL1_PER BIT(1) /*!< main flash page erase for bank1 command bit */ +#define FMC_CTL1_MER BIT(2) /*!< main flash mass erase for bank1 command bit */ +#define FMC_CTL1_START BIT(6) /*!< send erase command to FMC bit */ +#define FMC_CTL1_LK BIT(7) /*!< FMC_CTL1 lock bit */ +#define FMC_CTL1_ERRIE BIT(10) /*!< error interrupt enable bit */ +#define FMC_CTL1_ENDIE BIT(12) /*!< end of operation interrupt enable bit */ + +/* FMC_ADDR1 */ +#define FMC_ADDR1_ADDR BITS(0,31) /*!< Flash erase/program command address bits */ + +/* FMC_WSEN */ +#define FMC_WSEN_WSEN BIT(0) /*!< FMC wait state enable bit */ +#define FMC_WSEN_BPEN BIT(1) /*!< FMC bit program enable bit */ + +/* FMC_PID */ +#define FMC_PID_PID BITS(0,31) /*!< product ID bits */ + +/* constants definitions */ +/* define the FMC bit position and its register index offset */ +#define FMC_REGIDX_BIT(regidx, bitpos) (((uint32_t)(regidx) << 6) | (uint32_t)(bitpos)) +#define FMC_REG_VAL(offset) (REG32(FMC + ((uint32_t)(offset) >> 6))) +#define FMC_BIT_POS(val) ((uint32_t)(val) & 0x1FU) +#define FMC_REGIDX_BITS(regidx, bitpos0, bitpos1) (((uint32_t)(regidx) << 12) | ((uint32_t)(bitpos0) << 6) | (uint32_t)(bitpos1)) +#define FMC_REG_VALS(offset) (REG32(FMC + ((uint32_t)(offset) >> 12))) +#define FMC_BIT_POS0(val) (((uint32_t)(val) >> 6) & 0x1FU) +#define FMC_BIT_POS1(val) ((uint32_t)(val) & 0x1FU) +#define FMC_REG_OFFSET_GET(flag) ((uint32_t)(flag) >> 12) + +/* configuration register */ +#define FMC_STAT0_REG_OFFSET 0x0CU /*!< status register 0 offset */ +#define FMC_CTL0_REG_OFFSET 0x10U /*!< control register 0 offset */ +#define FMC_STAT1_REG_OFFSET 0x4CU /*!< status register 1 offset */ +#define FMC_CTL1_REG_OFFSET 0x50U /*!< control register 1 offset */ +#define FMC_OBSTAT_REG_OFFSET 0x1CU /*!< option byte status register offset */ + +/* fmc state */ +typedef enum +{ + FMC_READY, /*!< the operation has been completed */ + FMC_BUSY, /*!< the operation is in progress */ + FMC_PGERR, /*!< program error */ + FMC_WPERR, /*!< erase/program protection error */ + FMC_TOERR, /*!< timeout error */ +}fmc_state_enum; + +/* FMC interrupt enable */ +typedef enum +{ + FMC_INT_BANK0_END = FMC_REGIDX_BIT(FMC_CTL0_REG_OFFSET, 12U), /*!< enable FMC end of program interrupt */ + FMC_INT_BANK0_ERR = FMC_REGIDX_BIT(FMC_CTL0_REG_OFFSET, 10U), /*!< enable FMC error interrupt */ + FMC_INT_BANK1_END = FMC_REGIDX_BIT(FMC_CTL1_REG_OFFSET, 12U), /*!< enable FMC bank1 end of program interrupt */ + FMC_INT_BANK1_ERR = FMC_REGIDX_BIT(FMC_CTL1_REG_OFFSET, 10U), /*!< enable FMC bank1 error interrupt */ +}fmc_int_enum; + +/* FMC flags */ +typedef enum +{ + FMC_FLAG_BANK0_BUSY = FMC_REGIDX_BIT(FMC_STAT0_REG_OFFSET, 0U), /*!< FMC bank0 busy flag */ + FMC_FLAG_BANK0_PGERR = FMC_REGIDX_BIT(FMC_STAT0_REG_OFFSET, 2U), /*!< FMC bank0 operation error flag bit */ + FMC_FLAG_BANK0_WPERR = FMC_REGIDX_BIT(FMC_STAT0_REG_OFFSET, 4U), /*!< FMC bank0 erase/program protection error flag bit */ + FMC_FLAG_BANK0_END = FMC_REGIDX_BIT(FMC_STAT0_REG_OFFSET, 5U), /*!< FMC bank0 end of operation flag bit */ + FMC_FLAG_OBERR = FMC_REGIDX_BIT(FMC_OBSTAT_REG_OFFSET, 0U), /*!< FMC option bytes read error flag */ + FMC_FLAG_BANK1_BUSY = FMC_REGIDX_BIT(FMC_STAT1_REG_OFFSET, 0U), /*!< FMC bank1 busy flag */ + FMC_FLAG_BANK1_PGERR = FMC_REGIDX_BIT(FMC_STAT1_REG_OFFSET, 2U), /*!< FMC bank1 operation error flag bit */ + FMC_FLAG_BANK1_WPERR = FMC_REGIDX_BIT(FMC_STAT1_REG_OFFSET, 4U), /*!< FMC bank1 erase/program protection error flag bit */ + FMC_FLAG_BANK1_END = FMC_REGIDX_BIT(FMC_STAT1_REG_OFFSET, 5U), /*!< FMC bank1 end of operation flag bit */ +}fmc_flag_enum; + +/* FMC interrupt flags */ +typedef enum +{ + FMC_INT_FLAG_BANK0_PGERR = FMC_REGIDX_BITS(FMC_STAT0_REG_OFFSET, 2U, 10U), /*!< FMC bank0 operation error interrupt flag bit */ + FMC_INT_FLAG_BANK0_WPERR = FMC_REGIDX_BITS(FMC_STAT0_REG_OFFSET, 4U, 10U), /*!< FMC bank0 erase/program protection error interrupt flag bit */ + FMC_INT_FLAG_BANK0_END = FMC_REGIDX_BITS(FMC_STAT0_REG_OFFSET, 5U, 12U), /*!< FMC bank0 end of operation interrupt flag bit */ + FMC_INT_FLAG_BANK1_PGERR = FMC_REGIDX_BITS(FMC_STAT1_REG_OFFSET, 2U, 10U), /*!< FMC bank1 operation error interrupt flag bit */ + FMC_INT_FLAG_BANK1_WPERR = FMC_REGIDX_BITS(FMC_STAT1_REG_OFFSET, 4U, 10U), /*!< FMC bank1 erase/program protection error interrupt flag bit */ + FMC_INT_FLAG_BANK1_END = FMC_REGIDX_BITS(FMC_STAT1_REG_OFFSET, 5U, 12U), /*!< FMC bank1 end of operation interrupt flag bit */ +}fmc_interrupt_flag_enum; + +/* unlock key */ +#define UNLOCK_KEY0 ((uint32_t)0x45670123U) /*!< unlock key 0 */ +#define UNLOCK_KEY1 ((uint32_t)0xCDEF89ABU) /*!< unlock key 1 */ + +/* FMC wait state counter */ +#define WS_WSCNT(regval) (BITS(0,2) & ((uint32_t)(regval))) +#define WS_WSCNT_0 WS_WSCNT(0) /*!< FMC 0 wait */ +#define WS_WSCNT_1 WS_WSCNT(1) /*!< FMC 1 wait */ +#define WS_WSCNT_2 WS_WSCNT(2) /*!< FMC 2 wait */ + +/* option bytes software/hardware free watch dog timer */ +#define OB_FWDGT_SW ((uint8_t)0x01U) /*!< software free watchdog */ +#define OB_FWDGT_HW ((uint8_t)0x00U) /*!< hardware free watchdog */ + +/* option bytes reset or not entering deep sleep mode */ +#define OB_DEEPSLEEP_NRST ((uint8_t)0x02U) /*!< no reset when entering deepsleep mode */ +#define OB_DEEPSLEEP_RST ((uint8_t)0x00U) /*!< generate a reset instead of entering deepsleep mode */ + +/* option bytes reset or not entering standby mode */ +#define OB_STDBY_NRST ((uint8_t)0x04U) /*!< no reset when entering deepsleep mode */ +#define OB_STDBY_RST ((uint8_t)0x00U) /*!< generate a reset instead of entering standby mode */ + +/* option bytes boot bank value */ +#define OB_BOOT_B0 ((uint8_t)0x08U) /*!< boot from bank0 */ +#define OB_BOOT_B1 ((uint8_t)0x00U) /*!< boot from bank1 */ + +#define OB_USER_MASK ((uint8_t)0xF0U) /*!< MASK value */ + +/* read protect configure */ +#define FMC_NSPC ((uint8_t)0xA5U) /*!< no security protection */ +#define FMC_USPC ((uint8_t)0xBBU) /*!< under security protection */ + +/* OB_SPC */ +#define OB_SPC_SPC ((uint32_t)0x000000FFU) /*!< option byte security protection value */ +#define OB_SPC_SPC_N ((uint32_t)0x0000FF00U) /*!< option byte security protection complement value */ + +/* OB_USER */ +#define OB_USER_USER ((uint32_t)0x00FF0000U) /*!< user option value */ +#define OB_USER_USER_N ((uint32_t)0xFF000000U) /*!< user option complement value */ + +/* OB_WP0 */ +#define OB_WP0_WP0 ((uint32_t)0x000000FFU) /*!< FMC write protection option value */ + +/* OB_WP1 */ +#define OB_WP1_WP1 ((uint32_t)0x0000FF00U) /*!< FMC write protection option complement value */ + +/* OB_WP2 */ +#define OB_WP2_WP2 ((uint32_t)0x00FF0000U) /*!< FMC write protection option value */ + +/* OB_WP3 */ +#define OB_WP3_WP3 ((uint32_t)0xFF000000U) /*!< FMC write protection option complement value */ + +/* option bytes write protection */ +#define OB_WP_0 ((uint32_t)0x00000001U) /*!< erase/program protection of sector 0 */ +#define OB_WP_1 ((uint32_t)0x00000002U) /*!< erase/program protection of sector 1 */ +#define OB_WP_2 ((uint32_t)0x00000004U) /*!< erase/program protection of sector 2 */ +#define OB_WP_3 ((uint32_t)0x00000008U) /*!< erase/program protection of sector 3 */ +#define OB_WP_4 ((uint32_t)0x00000010U) /*!< erase/program protection of sector 4 */ +#define OB_WP_5 ((uint32_t)0x00000020U) /*!< erase/program protection of sector 5 */ +#define OB_WP_6 ((uint32_t)0x00000040U) /*!< erase/program protection of sector 6 */ +#define OB_WP_7 ((uint32_t)0x00000080U) /*!< erase/program protection of sector 7 */ +#define OB_WP_8 ((uint32_t)0x00000100U) /*!< erase/program protection of sector 8 */ +#define OB_WP_9 ((uint32_t)0x00000200U) /*!< erase/program protection of sector 9 */ +#define OB_WP_10 ((uint32_t)0x00000400U) /*!< erase/program protection of sector 10 */ +#define OB_WP_11 ((uint32_t)0x00000800U) /*!< erase/program protection of sector 11 */ +#define OB_WP_12 ((uint32_t)0x00001000U) /*!< erase/program protection of sector 12 */ +#define OB_WP_13 ((uint32_t)0x00002000U) /*!< erase/program protection of sector 13 */ +#define OB_WP_14 ((uint32_t)0x00004000U) /*!< erase/program protection of sector 14 */ +#define OB_WP_15 ((uint32_t)0x00008000U) /*!< erase/program protection of sector 15 */ +#define OB_WP_16 ((uint32_t)0x00010000U) /*!< erase/program protection of sector 16 */ +#define OB_WP_17 ((uint32_t)0x00020000U) /*!< erase/program protection of sector 17 */ +#define OB_WP_18 ((uint32_t)0x00040000U) /*!< erase/program protection of sector 18 */ +#define OB_WP_19 ((uint32_t)0x00080000U) /*!< erase/program protection of sector 19 */ +#define OB_WP_20 ((uint32_t)0x00100000U) /*!< erase/program protection of sector 20 */ +#define OB_WP_21 ((uint32_t)0x00200000U) /*!< erase/program protection of sector 21 */ +#define OB_WP_22 ((uint32_t)0x00400000U) /*!< erase/program protection of sector 22 */ +#define OB_WP_23 ((uint32_t)0x00800000U) /*!< erase/program protection of sector 23 */ +#define OB_WP_24 ((uint32_t)0x01000000U) /*!< erase/program protection of sector 24 */ +#define OB_WP_25 ((uint32_t)0x02000000U) /*!< erase/program protection of sector 25 */ +#define OB_WP_26 ((uint32_t)0x04000000U) /*!< erase/program protection of sector 26 */ +#define OB_WP_27 ((uint32_t)0x08000000U) /*!< erase/program protection of sector 27 */ +#define OB_WP_28 ((uint32_t)0x10000000U) /*!< erase/program protection of sector 28 */ +#define OB_WP_29 ((uint32_t)0x20000000U) /*!< erase/program protection of sector 29 */ +#define OB_WP_30 ((uint32_t)0x40000000U) /*!< erase/program protection of sector 30 */ +#define OB_WP_31 ((uint32_t)0x80000000U) /*!< erase/program protection of sector 31 */ +#define OB_WP_ALL ((uint32_t)0xFFFFFFFFU) /*!< erase/program protection of all sectors */ + +/* FMC timeout */ +#define FMC_TIMEOUT_COUNT ((uint32_t)0x0FFF0000U) /*!< FMC timeout count value */ + +/* FMC BANK address */ +#define FMC_BANK0_END_ADDRESS ((uint32_t)0x0807FFFFU) /*!< FMC bank0 end address */ +#define FMC_BANK0_SIZE ((uint32_t)0x00000200U) /*!< FMC bank0 size */ +#define FMC_SIZE (*(uint16_t *)0x1FFFF7E0U) /*!< FMC size */ + +/* function declarations */ +/* FMC main memory programming functions */ +/* set the FMC wait state counter */ +void fmc_wscnt_set(uint32_t wscnt); +/* unlock the main FMC operation */ +void fmc_unlock(void); +/* unlock the FMC bank0 operation */ +void fmc_bank0_unlock(void); +/* unlock the FMC bank1 operation */ +void fmc_bank1_unlock(void); +/* lock the main FMC operation */ +void fmc_lock(void); +/* lock the bank0 FMC operation */ +void fmc_bank0_lock(void); +/* lock the bank1 FMC operation */ +void fmc_bank1_lock(void); +/* FMC erase page */ +fmc_state_enum fmc_page_erase(uint32_t page_address); +/* FMC erase whole chip */ +fmc_state_enum fmc_mass_erase(void); +/* FMC erase whole bank0 */ +fmc_state_enum fmc_bank0_erase(void); +/* FMC erase whole bank1 */ +fmc_state_enum fmc_bank1_erase(void); +/* FMC program a word at the corresponding address */ +fmc_state_enum fmc_word_program(uint32_t address, uint32_t data); +/* FMC program a half word at the corresponding address */ +fmc_state_enum fmc_halfword_program(uint32_t address, uint16_t data); +/* FMC reprogram a word at the corresponding address without erasing */ +fmc_state_enum fmc_word_reprogram(uint32_t address, uint32_t data); + +/* FMC option bytes programming functions */ +/* unlock the option byte operation */ +void ob_unlock(void); +/* lock the option byte operation */ +void ob_lock(void); +/* erase the option byte */ +fmc_state_enum ob_erase(void); +/* enable write protect */ +fmc_state_enum ob_write_protection_enable(uint32_t ob_wp); +/* configure the option byte security protection */ +fmc_state_enum ob_security_protection_config(uint8_t ob_spc); +/* write the FMC option byte */ +fmc_state_enum ob_user_write(uint8_t ob_fwdgt, uint8_t ob_deepsleep, uint8_t ob_stdby, uint8_t ob_boot); +/* program option bytes data */ +fmc_state_enum ob_data_program(uint32_t address, uint8_t data); +/* get the FMC option byte user */ +uint8_t ob_user_get(void); +/* get OB_DATA in register FMC_OBSTAT */ +uint16_t ob_data_get(void); +/* get the FMC option byte write protection */ +uint32_t ob_write_protection_get(void); +/* get option byte security protection code value */ +FlagStatus ob_spc_get(void); + +/* FMC interrupts and flags management functions */ +/* enable FMC interrupt */ +void fmc_interrupt_enable(uint32_t interrupt); +/* disable FMC interrupt */ +void fmc_interrupt_disable(uint32_t interrupt); +/* check flag is set or not */ +FlagStatus fmc_flag_get(uint32_t flag); +/* clear the FMC flag */ +void fmc_flag_clear(uint32_t flag); +/* get FMC interrupt flag state */ +FlagStatus fmc_interrupt_flag_get(fmc_interrupt_flag_enum flag); +/* clear FMC interrupt flag state */ +void fmc_interrupt_flag_clear(fmc_interrupt_flag_enum flag); +/* return the FMC bank0 state */ +fmc_state_enum fmc_bank0_state_get(void); +/* return the FMC bank1 state */ +fmc_state_enum fmc_bank1_state_get(void); +/* check FMC bank0 ready or not */ +fmc_state_enum fmc_bank0_ready_wait(uint32_t timeout); +/* check FMC bank1 ready or not */ +fmc_state_enum fmc_bank1_ready_wait(uint32_t timeout); + +#endif /* GD32F30X_FMC_H */ diff --git a/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_standard_peripheral/Include/gd32f30x_fwdgt.h b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_standard_peripheral/Include/gd32f30x_fwdgt.h new file mode 100644 index 0000000000..0803cc01cf --- /dev/null +++ b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_standard_peripheral/Include/gd32f30x_fwdgt.h @@ -0,0 +1,107 @@ +/*! + \file gd32f30x_fwdgt.h + \brief definitions for the FWDGT + + \version 2017-02-10, V1.0.0, firmware for GD32F30x + \version 2018-10-10, V1.1.0, firmware for GD32F30x + \version 2018-12-25, V2.0.0, firmware for GD32F30x + \version 2020-09-30, V2.1.0, firmware for GD32F30x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef GD32F30X_FWDGT_H +#define GD32F30X_FWDGT_H + +#include "gd32f30x.h" + +/* FWDGT definitions */ +#define FWDGT FWDGT_BASE + +/* registers definitions */ +#define FWDGT_CTL REG32((FWDGT) + 0x00U) /*!< FWDGT control register */ +#define FWDGT_PSC REG32((FWDGT) + 0x04U) /*!< FWDGT prescaler register */ +#define FWDGT_RLD REG32((FWDGT) + 0x08U) /*!< FWDGT reload register */ +#define FWDGT_STAT REG32((FWDGT) + 0x0CU) /*!< FWDGT status register */ + +/* bits definitions */ +/* FWDGT_CTL */ +#define FWDGT_CTL_CMD BITS(0,15) /*!< FWDGT command value */ + +/* FWDGT_PSC */ +#define FWDGT_PSC_PSC BITS(0,2) /*!< FWDGT prescaler divider value */ + +/* FWDGT_RLD */ +#define FWDGT_RLD_RLD BITS(0,11) /*!< FWDGT counter reload value */ + +/* FWDGT_STAT */ +#define FWDGT_STAT_PUD BIT(0) /*!< FWDGT prescaler divider value update */ +#define FWDGT_STAT_RUD BIT(1) /*!< FWDGT counter reload value update */ + +/* constants definitions */ +/* psc register value */ +#define PSC_PSC(regval) (BITS(0,2) & ((uint32_t)(regval) << 0)) +#define FWDGT_PSC_DIV4 ((uint8_t)PSC_PSC(0)) /*!< FWDGT prescaler set to 4 */ +#define FWDGT_PSC_DIV8 ((uint8_t)PSC_PSC(1)) /*!< FWDGT prescaler set to 8 */ +#define FWDGT_PSC_DIV16 ((uint8_t)PSC_PSC(2)) /*!< FWDGT prescaler set to 16 */ +#define FWDGT_PSC_DIV32 ((uint8_t)PSC_PSC(3)) /*!< FWDGT prescaler set to 32 */ +#define FWDGT_PSC_DIV64 ((uint8_t)PSC_PSC(4)) /*!< FWDGT prescaler set to 64 */ +#define FWDGT_PSC_DIV128 ((uint8_t)PSC_PSC(5)) /*!< FWDGT prescaler set to 128 */ +#define FWDGT_PSC_DIV256 ((uint8_t)PSC_PSC(6)) /*!< FWDGT prescaler set to 256 */ + +/* control value */ +#define FWDGT_WRITEACCESS_ENABLE ((uint16_t)0x5555U) /*!< FWDGT_CTL bits write access enable value */ +#define FWDGT_WRITEACCESS_DISABLE ((uint16_t)0x0000U) /*!< FWDGT_CTL bits write access disable value */ +#define FWDGT_KEY_RELOAD ((uint16_t)0xAAAAU) /*!< FWDGT_CTL bits fwdgt counter reload value */ +#define FWDGT_KEY_ENABLE ((uint16_t)0xCCCCU) /*!< FWDGT_CTL bits fwdgt counter enable value */ + +/* FWDGT timeout value */ +#define FWDGT_PSC_TIMEOUT ((uint32_t)0x000FFFFFU) /*!< FWDGT_PSC register write operation state flag timeout */ +#define FWDGT_RLD_TIMEOUT ((uint32_t)0x000FFFFFU) /*!< FWDGT_RLD register write operation state flag timeout */ + +/* FWDGT flag definitions */ +#define FWDGT_FLAG_PUD FWDGT_STAT_PUD /*!< FWDGT prescaler divider value update flag */ +#define FWDGT_FLAG_RUD FWDGT_STAT_RUD /*!< FWDGT counter reload value update flag */ + +/* function declarations */ +/* enable write access to FWDGT_PSC and FWDGT_RLD */ +void fwdgt_write_enable(void); +/* disable write access to FWDGT_PSC and FWDGT_RLD */ +void fwdgt_write_disable(void); +/* start the free watchdog timer counter */ +void fwdgt_enable(void); + +/* reload the counter of FWDGT */ +void fwdgt_counter_reload(void); +/* configure counter reload value, and prescaler divider value */ +ErrStatus fwdgt_config(uint16_t reload_value, uint8_t prescaler_div); + +/* get flag state of FWDGT */ +FlagStatus fwdgt_flag_get(uint16_t flag); + +#endif /* GD32F30X_FWDGT_H */ diff --git a/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_standard_peripheral/Include/gd32f30x_gpio.h b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_standard_peripheral/Include/gd32f30x_gpio.h new file mode 100644 index 0000000000..47ff29a083 --- /dev/null +++ b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_standard_peripheral/Include/gd32f30x_gpio.h @@ -0,0 +1,536 @@ +/*! + \file gd32f30x_gpio.h + \brief definitions for the GPIO + + \version 2017-02-10, V1.0.0, firmware for GD32F30x + \version 2018-10-10, V1.1.0, firmware for GD32F30x + \version 2018-12-25, V2.0.0, firmware for GD32F30x + \version 2020-09-30, V2.1.0, firmware for GD32F30x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef GD32F30X_GPIO_H +#define GD32F30X_GPIO_H + +#include "gd32f30x.h" + +/* GPIOx(x=A,B,C,D,E,F,G) definitions */ +#define GPIOA (GPIO_BASE + 0x00000000U) +#define GPIOB (GPIO_BASE + 0x00000400U) +#define GPIOC (GPIO_BASE + 0x00000800U) +#define GPIOD (GPIO_BASE + 0x00000C00U) +#define GPIOE (GPIO_BASE + 0x00001000U) +#define GPIOF (GPIO_BASE + 0x00001400U) +#define GPIOG (GPIO_BASE + 0x00001800U) + +/* AFIO definitions */ +#define AFIO AFIO_BASE + +/* registers definitions */ +/* GPIO registers definitions */ +#define GPIO_CTL0(gpiox) REG32((gpiox) + 0x00U) /*!< GPIO port control register 0 */ +#define GPIO_CTL1(gpiox) REG32((gpiox) + 0x04U) /*!< GPIO port control register 1 */ +#define GPIO_ISTAT(gpiox) REG32((gpiox) + 0x08U) /*!< GPIO port input status register */ +#define GPIO_OCTL(gpiox) REG32((gpiox) + 0x0CU) /*!< GPIO port output control register */ +#define GPIO_BOP(gpiox) REG32((gpiox) + 0x10U) /*!< GPIO port bit operation register */ +#define GPIO_BC(gpiox) REG32((gpiox) + 0x14U) /*!< GPIO bit clear register */ +#define GPIO_LOCK(gpiox) REG32((gpiox) + 0x18U) /*!< GPIO port configuration lock register */ +#define GPIOx_SPD(gpiox) REG32((gpiox) + 0x3CU) /*!< GPIO port bit speed register */ + +/* AFIO registers definitions */ +#define AFIO_EC REG32(AFIO + 0x00U) /*!< AFIO event control register */ +#define AFIO_PCF0 REG32(AFIO + 0x04U) /*!< AFIO port configuration register 0 */ +#define AFIO_EXTISS0 REG32(AFIO + 0x08U) /*!< AFIO port EXTI sources selection register 0 */ +#define AFIO_EXTISS1 REG32(AFIO + 0x0CU) /*!< AFIO port EXTI sources selection register 1 */ +#define AFIO_EXTISS2 REG32(AFIO + 0x10U) /*!< AFIO port EXTI sources selection register 2 */ +#define AFIO_EXTISS3 REG32(AFIO + 0x14U) /*!< AFIO port EXTI sources selection register 3 */ +#define AFIO_PCF1 REG32(AFIO + 0x1CU) /*!< AFIO port configuration register 1 */ +#define AFIO_CPSCTL REG32(AFIO + 0x20U) /*!< IO compensation control register */ + +/* bits definitions */ +/* GPIO_CTL0 */ +#define GPIO_CTL0_MD0 BITS(0,1) /*!< port 0 mode bits */ +#define GPIO_CTL0_CTL0 BITS(2,3) /*!< pin 0 configuration bits */ +#define GPIO_CTL0_MD1 BITS(4,5) /*!< port 1 mode bits */ +#define GPIO_CTL0_CTL1 BITS(6,7) /*!< pin 1 configuration bits */ +#define GPIO_CTL0_MD2 BITS(8,9) /*!< port 2 mode bits */ +#define GPIO_CTL0_CTL2 BITS(10,11) /*!< pin 2 configuration bits */ +#define GPIO_CTL0_MD3 BITS(12,13) /*!< port 3 mode bits */ +#define GPIO_CTL0_CTL3 BITS(14,15) /*!< pin 3 configuration bits */ +#define GPIO_CTL0_MD4 BITS(16,17) /*!< port 4 mode bits */ +#define GPIO_CTL0_CTL4 BITS(18,19) /*!< pin 4 configuration bits */ +#define GPIO_CTL0_MD5 BITS(20,21) /*!< port 5 mode bits */ +#define GPIO_CTL0_CTL5 BITS(22,23) /*!< pin 5 configuration bits */ +#define GPIO_CTL0_MD6 BITS(24,25) /*!< port 6 mode bits */ +#define GPIO_CTL0_CTL6 BITS(26,27) /*!< pin 6 configuration bits */ +#define GPIO_CTL0_MD7 BITS(28,29) /*!< port 7 mode bits */ +#define GPIO_CTL0_CTL7 BITS(30,31) /*!< pin 7 configuration bits */ + +/* GPIO_CTL1 */ +#define GPIO_CTL1_MD8 BITS(0,1) /*!< port 8 mode bits */ +#define GPIO_CTL1_CTL8 BITS(2,3) /*!< pin 8 configuration bits */ +#define GPIO_CTL1_MD9 BITS(4,5) /*!< port 9 mode bits */ +#define GPIO_CTL1_CTL9 BITS(6,7) /*!< pin 9 configuration bits */ +#define GPIO_CTL1_MD10 BITS(8,9) /*!< port 10 mode bits */ +#define GPIO_CTL1_CTL10 BITS(10,11) /*!< pin 10 configuration bits */ +#define GPIO_CTL1_MD11 BITS(12,13) /*!< port 11 mode bits */ +#define GPIO_CTL1_CTL11 BITS(14,15) /*!< pin 11 configuration bits */ +#define GPIO_CTL1_MD12 BITS(16,17) /*!< port 12 mode bits */ +#define GPIO_CTL1_CTL12 BITS(18,19) /*!< pin 12 configuration bits */ +#define GPIO_CTL1_MD13 BITS(20,21) /*!< port 13 mode bits */ +#define GPIO_CTL1_CTL13 BITS(22,23) /*!< pin 13 configuration bits */ +#define GPIO_CTL1_MD14 BITS(24,25) /*!< port 14 mode bits */ +#define GPIO_CTL1_CTL14 BITS(26,27) /*!< pin 14 configuration bits */ +#define GPIO_CTL1_MD15 BITS(28,29) /*!< port 15 mode bits */ +#define GPIO_CTL1_CTL15 BITS(30,31) /*!< pin 15 configuration bits */ + +/* GPIO_ISTAT */ +#define GPIO_ISTAT_ISTAT0 BIT(0) /*!< pin 0 input status */ +#define GPIO_ISTAT_ISTAT1 BIT(1) /*!< pin 1 input status */ +#define GPIO_ISTAT_ISTAT2 BIT(2) /*!< pin 2 input status */ +#define GPIO_ISTAT_ISTAT3 BIT(3) /*!< pin 3 input status */ +#define GPIO_ISTAT_ISTAT4 BIT(4) /*!< pin 4 input status */ +#define GPIO_ISTAT_ISTAT5 BIT(5) /*!< pin 5 input status */ +#define GPIO_ISTAT_ISTAT6 BIT(6) /*!< pin 6 input status */ +#define GPIO_ISTAT_ISTAT7 BIT(7) /*!< pin 7 input status */ +#define GPIO_ISTAT_ISTAT8 BIT(8) /*!< pin 8 input status */ +#define GPIO_ISTAT_ISTAT9 BIT(9) /*!< pin 9 input status */ +#define GPIO_ISTAT_ISTAT10 BIT(10) /*!< pin 10 input status */ +#define GPIO_ISTAT_ISTAT11 BIT(11) /*!< pin 11 input status */ +#define GPIO_ISTAT_ISTAT12 BIT(12) /*!< pin 12 input status */ +#define GPIO_ISTAT_ISTAT13 BIT(13) /*!< pin 13 input status */ +#define GPIO_ISTAT_ISTAT14 BIT(14) /*!< pin 14 input status */ +#define GPIO_ISTAT_ISTAT15 BIT(15) /*!< pin 15 input status */ + +/* GPIO_OCTL */ +#define GPIO_OCTL_OCTL0 BIT(0) /*!< pin 0 output bit */ +#define GPIO_OCTL_OCTL1 BIT(1) /*!< pin 1 output bit */ +#define GPIO_OCTL_OCTL2 BIT(2) /*!< pin 2 output bit */ +#define GPIO_OCTL_OCTL3 BIT(3) /*!< pin 3 output bit */ +#define GPIO_OCTL_OCTL4 BIT(4) /*!< pin 4 output bit */ +#define GPIO_OCTL_OCTL5 BIT(5) /*!< pin 5 output bit */ +#define GPIO_OCTL_OCTL6 BIT(6) /*!< pin 6 output bit */ +#define GPIO_OCTL_OCTL7 BIT(7) /*!< pin 7 output bit */ +#define GPIO_OCTL_OCTL8 BIT(8) /*!< pin 8 output bit */ +#define GPIO_OCTL_OCTL9 BIT(9) /*!< pin 9 output bit */ +#define GPIO_OCTL_OCTL10 BIT(10) /*!< pin 10 output bit */ +#define GPIO_OCTL_OCTL11 BIT(11) /*!< pin 11 output bit */ +#define GPIO_OCTL_OCTL12 BIT(12) /*!< pin 12 output bit */ +#define GPIO_OCTL_OCTL13 BIT(13) /*!< pin 13 output bit */ +#define GPIO_OCTL_OCTL14 BIT(14) /*!< pin 14 output bit */ +#define GPIO_OCTL_OCTL15 BIT(15) /*!< pin 15 output bit */ + +/* GPIO_BOP */ +#define GPIO_BOP_BOP0 BIT(0) /*!< pin 0 set bit */ +#define GPIO_BOP_BOP1 BIT(1) /*!< pin 1 set bit */ +#define GPIO_BOP_BOP2 BIT(2) /*!< pin 2 set bit */ +#define GPIO_BOP_BOP3 BIT(3) /*!< pin 3 set bit */ +#define GPIO_BOP_BOP4 BIT(4) /*!< pin 4 set bit */ +#define GPIO_BOP_BOP5 BIT(5) /*!< pin 5 set bit */ +#define GPIO_BOP_BOP6 BIT(6) /*!< pin 6 set bit */ +#define GPIO_BOP_BOP7 BIT(7) /*!< pin 7 set bit */ +#define GPIO_BOP_BOP8 BIT(8) /*!< pin 8 set bit */ +#define GPIO_BOP_BOP9 BIT(9) /*!< pin 9 set bit */ +#define GPIO_BOP_BOP10 BIT(10) /*!< pin 10 set bit */ +#define GPIO_BOP_BOP11 BIT(11) /*!< pin 11 set bit */ +#define GPIO_BOP_BOP12 BIT(12) /*!< pin 12 set bit */ +#define GPIO_BOP_BOP13 BIT(13) /*!< pin 13 set bit */ +#define GPIO_BOP_BOP14 BIT(14) /*!< pin 14 set bit */ +#define GPIO_BOP_BOP15 BIT(15) /*!< pin 15 set bit */ +#define GPIO_BOP_CR0 BIT(16) /*!< pin 0 clear bit */ +#define GPIO_BOP_CR1 BIT(17) /*!< pin 1 clear bit */ +#define GPIO_BOP_CR2 BIT(18) /*!< pin 2 clear bit */ +#define GPIO_BOP_CR3 BIT(19) /*!< pin 3 clear bit */ +#define GPIO_BOP_CR4 BIT(20) /*!< pin 4 clear bit */ +#define GPIO_BOP_CR5 BIT(21) /*!< pin 5 clear bit */ +#define GPIO_BOP_CR6 BIT(22) /*!< pin 6 clear bit */ +#define GPIO_BOP_CR7 BIT(23) /*!< pin 7 clear bit */ +#define GPIO_BOP_CR8 BIT(24) /*!< pin 8 clear bit */ +#define GPIO_BOP_CR9 BIT(25) /*!< pin 9 clear bit */ +#define GPIO_BOP_CR10 BIT(26) /*!< pin 10 clear bit */ +#define GPIO_BOP_CR11 BIT(27) /*!< pin 11 clear bit */ +#define GPIO_BOP_CR12 BIT(28) /*!< pin 12 clear bit */ +#define GPIO_BOP_CR13 BIT(29) /*!< pin 13 clear bit */ +#define GPIO_BOP_CR14 BIT(30) /*!< pin 14 clear bit */ +#define GPIO_BOP_CR15 BIT(31) /*!< pin 15 clear bit */ + +/* GPIO_BC */ +#define GPIO_BC_CR0 BIT(0) /*!< pin 0 clear bit */ +#define GPIO_BC_CR1 BIT(1) /*!< pin 1 clear bit */ +#define GPIO_BC_CR2 BIT(2) /*!< pin 2 clear bit */ +#define GPIO_BC_CR3 BIT(3) /*!< pin 3 clear bit */ +#define GPIO_BC_CR4 BIT(4) /*!< pin 4 clear bit */ +#define GPIO_BC_CR5 BIT(5) /*!< pin 5 clear bit */ +#define GPIO_BC_CR6 BIT(6) /*!< pin 6 clear bit */ +#define GPIO_BC_CR7 BIT(7) /*!< pin 7 clear bit */ +#define GPIO_BC_CR8 BIT(8) /*!< pin 8 clear bit */ +#define GPIO_BC_CR9 BIT(9) /*!< pin 9 clear bit */ +#define GPIO_BC_CR10 BIT(10) /*!< pin 10 clear bit */ +#define GPIO_BC_CR11 BIT(11) /*!< pin 11 clear bit */ +#define GPIO_BC_CR12 BIT(12) /*!< pin 12 clear bit */ +#define GPIO_BC_CR13 BIT(13) /*!< pin 13 clear bit */ +#define GPIO_BC_CR14 BIT(14) /*!< pin 14 clear bit */ +#define GPIO_BC_CR15 BIT(15) /*!< pin 15 clear bit */ + +/* GPIO_LOCK */ +#define GPIO_LOCK_LK0 BIT(0) /*!< pin 0 lock bit */ +#define GPIO_LOCK_LK1 BIT(1) /*!< pin 1 lock bit */ +#define GPIO_LOCK_LK2 BIT(2) /*!< pin 2 lock bit */ +#define GPIO_LOCK_LK3 BIT(3) /*!< pin 3 lock bit */ +#define GPIO_LOCK_LK4 BIT(4) /*!< pin 4 lock bit */ +#define GPIO_LOCK_LK5 BIT(5) /*!< pin 5 lock bit */ +#define GPIO_LOCK_LK6 BIT(6) /*!< pin 6 lock bit */ +#define GPIO_LOCK_LK7 BIT(7) /*!< pin 7 lock bit */ +#define GPIO_LOCK_LK8 BIT(8) /*!< pin 8 lock bit */ +#define GPIO_LOCK_LK9 BIT(9) /*!< pin 9 lock bit */ +#define GPIO_LOCK_LK10 BIT(10) /*!< pin 10 lock bit */ +#define GPIO_LOCK_LK11 BIT(11) /*!< pin 11 lock bit */ +#define GPIO_LOCK_LK12 BIT(12) /*!< pin 12 lock bit */ +#define GPIO_LOCK_LK13 BIT(13) /*!< pin 13 lock bit */ +#define GPIO_LOCK_LK14 BIT(14) /*!< pin 14 lock bit */ +#define GPIO_LOCK_LK15 BIT(15) /*!< pin 15 lock bit */ +#define GPIO_LOCK_LKK BIT(16) /*!< pin sequence lock key */ + +/* GPIO_SPD */ +#define GPIO_SPD_SPD0 BIT(0) /*!< pin 0 set very high output speed when MDx is 0b11 */ +#define GPIO_SPD_SPD1 BIT(1) /*!< pin 1 set very high output speed when MDx is 0b11 */ +#define GPIO_SPD_SPD2 BIT(2) /*!< pin 2 set very high output speed when MDx is 0b11 */ +#define GPIO_SPD_SPD3 BIT(3) /*!< pin 3 set very high output speed when MDx is 0b11 */ +#define GPIO_SPD_SPD4 BIT(4) /*!< pin 4 set very high output speed when MDx is 0b11 */ +#define GPIO_SPD_SPD5 BIT(5) /*!< pin 5 set very high output speed when MDx is 0b11 */ +#define GPIO_SPD_SPD6 BIT(6) /*!< pin 6 set very high output speed when MDx is 0b11 */ +#define GPIO_SPD_SPD7 BIT(7) /*!< pin 7 set very high output speed when MDx is 0b11 */ +#define GPIO_SPD_SPD8 BIT(8) /*!< pin 8 set very high output speed when MDx is 0b11 */ +#define GPIO_SPD_SPD9 BIT(9) /*!< pin 9 set very high output speed when MDx is 0b11 */ +#define GPIO_SPD_SPD10 BIT(10) /*!< pin 10 set very high output speed when MDx is 0b11 */ +#define GPIO_SPD_SPD11 BIT(11) /*!< pin 11 set very high output speed when MDx is 0b11 */ +#define GPIO_SPD_SPD12 BIT(12) /*!< pin 12 set very high output speed when MDx is 0b11 */ +#define GPIO_SPD_SPD13 BIT(13) /*!< pin 13 set very high output speed when MDx is 0b11 */ +#define GPIO_SPD_SPD14 BIT(14) /*!< pin 14 set very high output speed when MDx is 0b11 */ +#define GPIO_SPD_SPD15 BIT(15) /*!< pin 15 set very high output speed when MDx is 0b11 */ + +/* AFIO_EC */ +#define AFIO_EC_PIN BITS(0,3) /*!< event output pin selection */ +#define AFIO_EC_PORT BITS(4,6) /*!< event output port selection */ +#define AFIO_EC_EOE BIT(7) /*!< event output enable */ + +/* AFIO_PCF0 */ +#ifdef GD32F30X_CL +/* memory map and bit definitions for GD32F30X_CL devices */ +#define AFIO_PCF0_SPI0_REMAP BIT(0) /*!< SPI0 remapping */ +#define AFIO_PCF0_I2C0_REMAP BIT(1) /*!< I2C0 remapping */ +#define AFIO_PCF0_USART0_REMAP BIT(2) /*!< USART0 remapping */ +#define AFIO_PCF0_USART1_REMAP BIT(3) /*!< USART1 remapping */ +#define AFIO_PCF0_USART2_REMAP BITS(4,5) /*!< USART2 remapping */ +#define AFIO_PCF0_TIMER0_REMAP BITS(6,7) /*!< TIMER0 remapping */ +#define AFIO_PCF0_TIMER1_REMAP BITS(8,9) /*!< TIMER1 remapping */ +#define AFIO_PCF0_TIMER2_REMAP BITS(10,11) /*!< TIMER2 remapping */ +#define AFIO_PCF0_TIMER3_REMAP BIT(12) /*!< TIMER3 remapping */ +#define AFIO_PCF0_CAN0_REMAP BITS(13,14) /*!< CAN0 remapping */ +#define AFIO_PCF0_PD01_REMAP BIT(15) /*!< port D0/port D1 mapping on OSC_IN/OSC_OUT */ +#define AFIO_PCF0_TIMER4CH3_IREMAP BIT(16) /*!< TIMER4 channel3 internal remapping */ +#define AFIO_PCF0_ENET_REMAP BIT(21) /*!< ethernet MAC I/O remapping */ +#define AFIO_PCF0_CAN1_REMAP BIT(22) /*!< CAN1 remapping */ +#define AFIO_PCF0_ENET_PHY_SEL BIT(23) /*!< ethernet MII or RMII PHY selection */ +#define AFIO_PCF0_SWJ_CFG BITS(24,26) /*!< serial wire JTAG configuration */ +#define AFIO_PCF0_SPI2_REMAP BIT(28) /*!< SPI2/I2S2 remapping */ +#define AFIO_PCF0_TIMER1ITR0_REMAP BIT(29) /*!< TIMER1 internal trigger 0 remapping */ +#define AFIO_PCF0_PTP_PPS_REMAP BIT(30) /*!< ethernet PTP PPS remapping */ + +#else +/* memory map and bit definitions for GD32F30X_HD devices and GD32F30X_XD devices */ +#define AFIO_PCF0_SPI0_REMAP BIT(0) /*!< SPI0 remapping */ +#define AFIO_PCF0_I2C0_REMAP BIT(1) /*!< I2C0 remapping */ +#define AFIO_PCF0_USART0_REMAP BIT(2) /*!< USART0 remapping */ +#define AFIO_PCF0_USART1_REMAP BIT(3) /*!< USART1 remapping */ +#define AFIO_PCF0_USART2_REMAP BITS(4,5) /*!< USART2 remapping */ +#define AFIO_PCF0_TIMER0_REMAP BITS(6,7) /*!< TIMER0 remapping */ +#define AFIO_PCF0_TIMER1_REMAP BITS(8,9) /*!< TIMER1 remapping */ +#define AFIO_PCF0_TIMER2_REMAP BITS(10,11) /*!< TIMER2 remapping */ +#define AFIO_PCF0_TIMER3_REMAP BIT(12) /*!< TIMER3 remapping */ +#define AFIO_PCF0_CAN_REMAP BITS(13,14) /*!< CAN remapping */ +#define AFIO_PCF0_PD01_REMAP BIT(15) /*!< port D0/port D1 mapping on OSC_IN/OSC_OUT */ +#define AFIO_PCF0_TIMER4CH3_IREMAP BIT(16) /*!< TIMER4 channel3 internal remapping */ +#define AFIO_PCF0_ADC0_ETRGINS_REMAP BIT(17) /*!< ADC 0 external trigger inserted conversion remapping */ +#define AFIO_PCF0_ADC0_ETRGREG_REMAP BIT(18) /*!< ADC 0 external trigger regular conversion remapping */ +#define AFIO_PCF0_ADC1_ETRGINS_REMAP BIT(19) /*!< ADC 1 external trigger inserted conversion remapping */ +#define AFIO_PCF0_ADC1_ETRGREG_REMAP BIT(20) /*!< ADC 1 external trigger regular conversion remapping */ +#define AFIO_PCF0_SWJ_CFG BITS(24,26) /*!< serial wire JTAG configuration */ +#define AFIO_PCF0_SPI2_REMAP BIT(28) /*!< SPI2/I2S2 remapping */ +#endif /* GD32F30X_CL */ + +/* AFIO_EXTISS0 */ +#define AFIO_EXTI0_SS BITS(0,3) /*!< EXTI 0 sources selection */ +#define AFIO_EXTI1_SS BITS(4,7) /*!< EXTI 1 sources selection */ +#define AFIO_EXTI2_SS BITS(8,11) /*!< EXTI 2 sources selection */ +#define AFIO_EXTI3_SS BITS(12,15) /*!< EXTI 3 sources selection */ + +/* AFIO_EXTISS1 */ +#define AFIO_EXTI4_SS BITS(0,3) /*!< EXTI 4 sources selection */ +#define AFIO_EXTI5_SS BITS(4,7) /*!< EXTI 5 sources selection */ +#define AFIO_EXTI6_SS BITS(8,11) /*!< EXTI 6 sources selection */ +#define AFIO_EXTI7_SS BITS(12,15) /*!< EXTI 7 sources selection */ + +/* AFIO_EXTISS2 */ +#define AFIO_EXTI8_SS BITS(0,3) /*!< EXTI 8 sources selection */ +#define AFIO_EXTI9_SS BITS(4,7) /*!< EXTI 9 sources selection */ +#define AFIO_EXTI10_SS BITS(8,11) /*!< EXTI 10 sources selection */ +#define AFIO_EXTI11_SS BITS(12,15) /*!< EXTI 11 sources selection */ + +/* AFIO_EXTISS3 */ +#define AFIO_EXTI12_SS BITS(0,3) /*!< EXTI 12 sources selection */ +#define AFIO_EXTI13_SS BITS(4,7) /*!< EXTI 13 sources selection */ +#define AFIO_EXTI14_SS BITS(8,11) /*!< EXTI 14 sources selection */ +#define AFIO_EXTI15_SS BITS(12,15) /*!< EXTI 15 sources selection */ + +/* AFIO_PCF1 */ +#define AFIO_PCF1_TIMER8_REMAP BIT(5) /*!< TIMER8 remapping */ +#define AFIO_PCF1_TIMER9_REMAP BIT(6) /*!< TIMER9 remapping */ +#define AFIO_PCF1_TIMER10_REMAP BIT(7) /*!< TIMER10 remapping */ +#define AFIO_PCF1_TIMER12_REMAP BIT(8) /*!< TIMER12 remapping */ +#define AFIO_PCF1_TIMER13_REMAP BIT(9) /*!< TIMER13 remapping */ +#define AFIO_PCF1_EXMC_NADV BIT(10) /*!< EXMC_NADV connect/disconnect */ +#define AFIO_PCF1_CTC_REMAP BITS(11,12) /*!< CTC remapping */ + +/* AFIO_CPSCTL */ +#define AFIO_CPSCTL_CPS_EN BIT(0) /*!< I/O compensation cell enable */ +#define AFIO_CPSCTL_CPS_RDY BIT(8) /*!< I/O compensation cell is ready or not */ + +/* constants definitions */ +typedef FlagStatus bit_status; + +/* GPIO mode values set */ +#define GPIO_MODE_SET(n, mode) ((uint32_t)((uint32_t)(mode) << (4U * (n)))) +#define GPIO_MODE_MASK(n) (0xFU << (4U * (n))) + +/* GPIO mode definitions */ +#define GPIO_MODE_AIN ((uint8_t)0x00U) /*!< analog input mode */ +#define GPIO_MODE_IN_FLOATING ((uint8_t)0x04U) /*!< floating input mode */ +#define GPIO_MODE_IPD ((uint8_t)0x28U) /*!< pull-down input mode */ +#define GPIO_MODE_IPU ((uint8_t)0x48U) /*!< pull-up input mode */ +#define GPIO_MODE_OUT_OD ((uint8_t)0x14U) /*!< GPIO output with open-drain */ +#define GPIO_MODE_OUT_PP ((uint8_t)0x10U) /*!< GPIO output with push-pull */ +#define GPIO_MODE_AF_OD ((uint8_t)0x1CU) /*!< AFIO output with open-drain */ +#define GPIO_MODE_AF_PP ((uint8_t)0x18U) /*!< AFIO output with push-pull */ + +/* GPIO output max speed value */ +#define GPIO_OSPEED_10MHZ ((uint8_t)0x01U) /*!< output max speed 10MHz */ +#define GPIO_OSPEED_2MHZ ((uint8_t)0x02U) /*!< output max speed 2MHz */ +#define GPIO_OSPEED_50MHZ ((uint8_t)0x03U) /*!< output max speed 50MHz */ +#define GPIO_OSPEED_MAX ((uint8_t)0x04U) /*!< GPIO very high output speed, max speed more than 50MHz */ + +/* GPIO event output port definitions */ +#define GPIO_EVENT_PORT_GPIOA ((uint8_t)0x00U) /*!< event output port A */ +#define GPIO_EVENT_PORT_GPIOB ((uint8_t)0x01U) /*!< event output port B */ +#define GPIO_EVENT_PORT_GPIOC ((uint8_t)0x02U) /*!< event output port C */ +#define GPIO_EVENT_PORT_GPIOD ((uint8_t)0x03U) /*!< event output port D */ +#define GPIO_EVENT_PORT_GPIOE ((uint8_t)0x04U) /*!< event output port E */ + +/* GPIO output port source definitions */ +#define GPIO_PORT_SOURCE_GPIOA ((uint8_t)0x00U) /*!< output port source A */ +#define GPIO_PORT_SOURCE_GPIOB ((uint8_t)0x01U) /*!< output port source B */ +#define GPIO_PORT_SOURCE_GPIOC ((uint8_t)0x02U) /*!< output port source C */ +#define GPIO_PORT_SOURCE_GPIOD ((uint8_t)0x03U) /*!< output port source D */ +#define GPIO_PORT_SOURCE_GPIOE ((uint8_t)0x04U) /*!< output port source E */ +#define GPIO_PORT_SOURCE_GPIOF ((uint8_t)0x05U) /*!< output port source F */ +#define GPIO_PORT_SOURCE_GPIOG ((uint8_t)0x06U) /*!< output port source G */ + +/* GPIO event output pin definitions */ +#define GPIO_EVENT_PIN_0 ((uint8_t)0x00U) /*!< GPIO event pin 0 */ +#define GPIO_EVENT_PIN_1 ((uint8_t)0x01U) /*!< GPIO event pin 1 */ +#define GPIO_EVENT_PIN_2 ((uint8_t)0x02U) /*!< GPIO event pin 2 */ +#define GPIO_EVENT_PIN_3 ((uint8_t)0x03U) /*!< GPIO event pin 3 */ +#define GPIO_EVENT_PIN_4 ((uint8_t)0x04U) /*!< GPIO event pin 4 */ +#define GPIO_EVENT_PIN_5 ((uint8_t)0x05U) /*!< GPIO event pin 5 */ +#define GPIO_EVENT_PIN_6 ((uint8_t)0x06U) /*!< GPIO event pin 6 */ +#define GPIO_EVENT_PIN_7 ((uint8_t)0x07U) /*!< GPIO event pin 7 */ +#define GPIO_EVENT_PIN_8 ((uint8_t)0x08U) /*!< GPIO event pin 8 */ +#define GPIO_EVENT_PIN_9 ((uint8_t)0x09U) /*!< GPIO event pin 9 */ +#define GPIO_EVENT_PIN_10 ((uint8_t)0x0AU) /*!< GPIO event pin 10 */ +#define GPIO_EVENT_PIN_11 ((uint8_t)0x0BU) /*!< GPIO event pin 11 */ +#define GPIO_EVENT_PIN_12 ((uint8_t)0x0CU) /*!< GPIO event pin 12 */ +#define GPIO_EVENT_PIN_13 ((uint8_t)0x0DU) /*!< GPIO event pin 13 */ +#define GPIO_EVENT_PIN_14 ((uint8_t)0x0EU) /*!< GPIO event pin 14 */ +#define GPIO_EVENT_PIN_15 ((uint8_t)0x0FU) /*!< GPIO event pin 15 */ + +/* GPIO output pin source definitions */ +#define GPIO_PIN_SOURCE_0 ((uint8_t)0x00U) /*!< GPIO pin source 0 */ +#define GPIO_PIN_SOURCE_1 ((uint8_t)0x01U) /*!< GPIO pin source 1 */ +#define GPIO_PIN_SOURCE_2 ((uint8_t)0x02U) /*!< GPIO pin source 2 */ +#define GPIO_PIN_SOURCE_3 ((uint8_t)0x03U) /*!< GPIO pin source 3 */ +#define GPIO_PIN_SOURCE_4 ((uint8_t)0x04U) /*!< GPIO pin source 4 */ +#define GPIO_PIN_SOURCE_5 ((uint8_t)0x05U) /*!< GPIO pin source 5 */ +#define GPIO_PIN_SOURCE_6 ((uint8_t)0x06U) /*!< GPIO pin source 6 */ +#define GPIO_PIN_SOURCE_7 ((uint8_t)0x07U) /*!< GPIO pin source 7 */ +#define GPIO_PIN_SOURCE_8 ((uint8_t)0x08U) /*!< GPIO pin source 8 */ +#define GPIO_PIN_SOURCE_9 ((uint8_t)0x09U) /*!< GPIO pin source 9 */ +#define GPIO_PIN_SOURCE_10 ((uint8_t)0x0AU) /*!< GPIO pin source 10 */ +#define GPIO_PIN_SOURCE_11 ((uint8_t)0x0BU) /*!< GPIO pin source 11 */ +#define GPIO_PIN_SOURCE_12 ((uint8_t)0x0CU) /*!< GPIO pin source 12 */ +#define GPIO_PIN_SOURCE_13 ((uint8_t)0x0DU) /*!< GPIO pin source 13 */ +#define GPIO_PIN_SOURCE_14 ((uint8_t)0x0EU) /*!< GPIO pin source 14 */ +#define GPIO_PIN_SOURCE_15 ((uint8_t)0x0FU) /*!< GPIO pin source 15 */ + +/* GPIO pin definitions */ +#define GPIO_PIN_0 BIT(0) /*!< GPIO pin 0 */ +#define GPIO_PIN_1 BIT(1) /*!< GPIO pin 1 */ +#define GPIO_PIN_2 BIT(2) /*!< GPIO pin 2 */ +#define GPIO_PIN_3 BIT(3) /*!< GPIO pin 3 */ +#define GPIO_PIN_4 BIT(4) /*!< GPIO pin 4 */ +#define GPIO_PIN_5 BIT(5) /*!< GPIO pin 5 */ +#define GPIO_PIN_6 BIT(6) /*!< GPIO pin 6 */ +#define GPIO_PIN_7 BIT(7) /*!< GPIO pin 7 */ +#define GPIO_PIN_8 BIT(8) /*!< GPIO pin 8 */ +#define GPIO_PIN_9 BIT(9) /*!< GPIO pin 9 */ +#define GPIO_PIN_10 BIT(10) /*!< GPIO pin 10 */ +#define GPIO_PIN_11 BIT(11) /*!< GPIO pin 11 */ +#define GPIO_PIN_12 BIT(12) /*!< GPIO pin 12 */ +#define GPIO_PIN_13 BIT(13) /*!< GPIO pin 13 */ +#define GPIO_PIN_14 BIT(14) /*!< GPIO pin 14 */ +#define GPIO_PIN_15 BIT(15) /*!< GPIO pin 15 */ +#define GPIO_PIN_ALL BITS(0,15) /*!< GPIO pin all */ + +/* AFIO remap mask */ +#define PCF0_USART2_REMAP(regval) (BITS(4,5) & ((uint32_t)(regval) << 4)) /*!< USART2 remapping */ +#define PCF0_TIMER0_REMAP(regval) (BITS(6,7) & ((uint32_t)(regval) << 6)) /*!< TIMER0 remapping */ +#define PCF0_TIMER1_REMAP(regval) (BITS(8,9) & ((uint32_t)(regval) << 8)) /*!< TIMER1 remapping */ +#define PCF0_TIMER2_REMAP(regval) (BITS(10,11) & ((uint32_t)(regval) << 10)) /*!< TIMER2 remapping */ +#define PCF0_CAN_REMAP(regval) (BITS(13,14) & ((uint32_t)(regval) << 13)) /*!< CAN remapping */ +#define PCF0_SWJ_CFG(regval) (BITS(24,26) & ((uint32_t)(regval) << 24)) /*!< serial wire JTAG configuration */ +#define PCF1_CTC_REMAP(regval) (BITS(11,12) & ((uint32_t)(regval) << 11)) /*!< CTC remapping */ + +/* GPIO remap definitions */ +#define GPIO_SPI0_REMAP AFIO_PCF0_SPI0_REMAP /*!< SPI0 remapping */ +#define GPIO_I2C0_REMAP AFIO_PCF0_I2C0_REMAP /*!< I2C0 remapping */ +#define GPIO_USART0_REMAP AFIO_PCF0_USART0_REMAP /*!< USART0 remapping */ +#define GPIO_USART1_REMAP AFIO_PCF0_USART1_REMAP /*!< USART1 remapping */ +#define GPIO_USART2_PARTIAL_REMAP ((uint32_t)0x00140000U | PCF0_USART2_REMAP(1)) /*!< USART2 partial remapping */ +#define GPIO_USART2_FULL_REMAP ((uint32_t)0x00140000U | PCF0_USART2_REMAP(3)) /*!< USART2 full remapping */ +#define GPIO_TIMER0_PARTIAL_REMAP ((uint32_t)0x00160000U | PCF0_TIMER0_REMAP(1)) /*!< TIMER0 partial remapping */ +#define GPIO_TIMER0_FULL_REMAP ((uint32_t)0x00160000U | PCF0_TIMER0_REMAP(3)) /*!< TIMER0 full remapping */ +#define GPIO_TIMER1_PARTIAL_REMAP0 ((uint32_t)0x00180000U | PCF0_TIMER1_REMAP(1)) /*!< TIMER1 partial remapping */ +#define GPIO_TIMER1_PARTIAL_REMAP1 ((uint32_t)0x00180000U | PCF0_TIMER1_REMAP(2)) /*!< TIMER1 partial remapping */ +#define GPIO_TIMER1_FULL_REMAP ((uint32_t)0x00180000U | PCF0_TIMER1_REMAP(3)) /*!< TIMER1 full remapping */ +#define GPIO_TIMER2_PARTIAL_REMAP ((uint32_t)0x001A0000U | PCF0_TIMER2_REMAP(2)) /*!< TIMER2 partial remapping */ +#define GPIO_TIMER2_FULL_REMAP ((uint32_t)0x001A0000U | PCF0_TIMER2_REMAP(3)) /*!< TIMER2 full remapping */ +#define GPIO_TIMER3_REMAP AFIO_PCF0_TIMER3_REMAP /*!< TIMER3 remapping */ +#define GPIO_PD01_REMAP AFIO_PCF0_PD01_REMAP /*!< PD01 remapping */ +#define GPIO_TIMER4CH3_IREMAP ((uint32_t)0x00200000U | (AFIO_PCF0_TIMER4CH3_IREMAP >> 16)) /*!< TIMER4 channel3 internal remapping */ +#if (defined(GD32F30X_HD) || defined(GD32F30X_XD)) +#define GPIO_CAN_PARTIAL_REMAP ((uint32_t)0x001D0000U | PCF0_CAN_REMAP(2)) /*!< CAN partial remapping(only for GD32F30X_HD devices and GD32F30X_XD devices) */ +#define GPIO_CAN_FULL_REMAP ((uint32_t)0x001D0000U | PCF0_CAN_REMAP(3)) /*!< CAN full remapping(only for GD32F30X_HD devices and GD32F30X_XD devices) */ +#endif /* GD32F30X_HD||GD32F30X_XD */ +#if (defined(GD32F30X_HD) || defined(GD32F30X_XD)) +#define GPIO_ADC0_ETRGINS_REMAP ((uint32_t)0x00200000U | (AFIO_PCF0_ADC0_ETRGINS_REMAP >> 16)) /*!< ADC0 external trigger inserted conversion remapping(only for GD32F30X_HD devices and GD32F30X_XD devices) */ +#define GPIO_ADC0_ETRGREG_REMAP ((uint32_t)0x00200000U | (AFIO_PCF0_ADC0_ETRGREG_REMAP >> 16)) /*!< ADC0 external trigger regular conversion remapping(only for GD32F30X_HD devices and GD32F30X_XD devices) */ +#define GPIO_ADC1_ETRGINS_REMAP ((uint32_t)0x00200000U | (AFIO_PCF0_ADC1_ETRGINS_REMAP >> 16)) /*!< ADC1 external trigger inserted conversion remapping(only for GD32F30X_HD devices and GD32F30X_XD devices) */ +#define GPIO_ADC1_ETRGREG_REMAP ((uint32_t)0x00200000U | (AFIO_PCF0_ADC1_ETRGREG_REMAP >> 16)) /*!< ADC1 external trigger regular conversion remapping(only for GD32F30X_HD devices and GD32F30X_XD devices) */ +#endif /* GD32F30X_HD||GD32F30X_XD */ +#define GPIO_SWJ_NONJTRST_REMAP ((uint32_t)0x00300000U | (PCF0_SWJ_CFG(1) >> 16)) /*!< full SWJ(JTAG-DP + SW-DP),but without NJTRST */ +#define GPIO_SWJ_SWDPENABLE_REMAP ((uint32_t)0x00300000U | (PCF0_SWJ_CFG(2) >> 16)) /*!< JTAG-DP disabled and SW-DP enabled */ +#define GPIO_SWJ_DISABLE_REMAP ((uint32_t)0x00300000U | (PCF0_SWJ_CFG(4) >> 16)) /*!< JTAG-DP disabled and SW-DP disabled */ +#define GPIO_SPI2_REMAP ((uint32_t)0x00200000U | (AFIO_PCF0_SPI2_REMAP >> 16)) /*!< SPI2 remapping*/ +#ifdef GD32F30X_CL +#define GPIO_CAN0_PARTIAL_REMAP ((uint32_t)0x001D0000U | PCF0_CAN_REMAP(2)) /*!< CAN0 partial remapping(only for GD32F30X_CL devices) */ +#define GPIO_CAN0_FULL_REMAP ((uint32_t)0x001D0000U | PCF0_CAN_REMAP(3)) /*!< CAN0 full remapping(only for GD32F30X_CL devices) */ +#define GPIO_ENET_REMAP ((uint32_t)0x00200000U | (AFIO_PCF0_ENET_REMAP >> 16)) /*!< ENET remapping(only for GD32F30X_CL devices) */ +#define GPIO_CAN1_REMAP ((uint32_t)0x00200000U | (AFIO_PCF0_CAN1_REMAP >> 16)) /*!< CAN1 remapping(only for GD32F30X_CL devices) */ +#define GPIO_TIMER1ITR0_REMAP ((uint32_t)0x00200000U | (AFIO_PCF0_TIMER1ITR0_REMAP >> 16)) /*!< TIMER1 internal trigger 0 remapping(only for GD32F30X_CL devices) */ +#define GPIO_PTP_PPS_REMAP ((uint32_t)0x00200000U | (AFIO_PCF0_PTP_PPS_REMAP >> 16)) /*!< ethernet PTP PPS remapping(only for GD32F30X_CL devices) */ +#endif /* GD32F30X_CL */ +#define GPIO_TIMER8_REMAP ((uint32_t)0x80000000U | AFIO_PCF1_TIMER8_REMAP) /*!< TIMER8 remapping */ +#define GPIO_TIMER9_REMAP ((uint32_t)0x80000000U | AFIO_PCF1_TIMER9_REMAP) /*!< TIMER9 remapping */ +#define GPIO_TIMER10_REMAP ((uint32_t)0x80000000U | AFIO_PCF1_TIMER10_REMAP) /*!< TIMER10 remapping */ +#define GPIO_TIMER12_REMAP ((uint32_t)0x80000000U | AFIO_PCF1_TIMER12_REMAP) /*!< TIMER12 remapping */ +#define GPIO_TIMER13_REMAP ((uint32_t)0x80000000U | AFIO_PCF1_TIMER13_REMAP) /*!< TIMER13 remapping */ +#define GPIO_EXMC_NADV_REMAP ((uint32_t)0x80000000U | AFIO_PCF1_EXMC_NADV) /*!< EXMC_NADV connect/disconnect */ +#define GPIO_CTC_REMAP0 ((uint32_t)0x801B0000U | PCF1_CTC_REMAP(1)) /*!< CTC remapping(PD15) */ +#define GPIO_CTC_REMAP1 ((uint32_t)0x801B0000U | PCF1_CTC_REMAP(2)) /*!< CTC remapping(PF0) */ + +#ifdef GD32F30X_CL +/* ethernet MII or RMII PHY selection */ +#define GPIO_ENET_PHY_MII ((uint32_t)0x00000000U) /*!< configure ethernet MAC for connection with an MII PHY */ +#define GPIO_ENET_PHY_RMII AFIO_PCF0_ENET_PHY_SEL /*!< configure ethernet MAC for connection with an RMII PHY */ +#endif /* GD32F30X_CL */ + +/* I/O compensation cell enable/disable */ +#define GPIO_COMPENSATION_ENABLE AFIO_CPSCTL_CPS_EN /*!< I/O compensation cell is enable */ +#define GPIO_COMPENSATION_DISABLE ((uint32_t)0x00000000U) /*!< I/O compensation cell is disable */ + +/* function declarations */ +/* reset GPIO port */ +void gpio_deinit(uint32_t gpio_periph); +/* reset alternate function I/O(AFIO) */ +void gpio_afio_deinit(void); +/* GPIO parameter initialization */ +void gpio_init(uint32_t gpio_periph, uint32_t mode, uint32_t speed, uint32_t pin); + +/* set GPIO pin bit */ +void gpio_bit_set(uint32_t gpio_periph, uint32_t pin); +/* reset GPIO pin bit */ +void gpio_bit_reset(uint32_t gpio_periph, uint32_t pin); +/* write data to the specified GPIO pin */ +void gpio_bit_write(uint32_t gpio_periph, uint32_t pin, bit_status bit_value); +/* write data to the specified GPIO port */ +void gpio_port_write(uint32_t gpio_periph, uint16_t data); + +/* get GPIO pin input status */ +FlagStatus gpio_input_bit_get(uint32_t gpio_periph, uint32_t pin); +/* get GPIO port input status */ +uint16_t gpio_input_port_get(uint32_t gpio_periph); +/* get GPIO pin output status */ +FlagStatus gpio_output_bit_get(uint32_t gpio_periph, uint32_t pin); +/* get GPIO port output status */ +uint16_t gpio_output_port_get(uint32_t gpio_periph); +/* configure GPIO pin remap */ +void gpio_pin_remap_config(uint32_t remap, ControlStatus newvalue); + +#ifdef GD32F30X_CL +/* select ethernet MII or RMII PHY */ +void gpio_ethernet_phy_select(uint32_t enet_sel); +#endif /* GD32F30X_CL */ + +/* select GPIO pin exti sources */ +void gpio_exti_source_select(uint8_t output_port, uint8_t output_pin); + +/* configure GPIO pin event output */ +void gpio_event_output_config(uint8_t output_port, uint8_t output_pin); +/* enable GPIO pin event output */ +void gpio_event_output_enable(void); +/* disable GPIO pin event output */ +void gpio_event_output_disable(void); + +/* lock GPIO pin bit */ +void gpio_pin_lock(uint32_t gpio_periph, uint32_t pin); +/* configure the I/O compensation cell */ +void gpio_compensation_config(uint32_t compensation); +/* check the I/O compensation cell is ready or not */ +FlagStatus gpio_compensation_flag_get(void); + +#endif /* GD32F30X_GPIO_H */ diff --git a/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_standard_peripheral/Include/gd32f30x_i2c.h b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_standard_peripheral/Include/gd32f30x_i2c.h new file mode 100644 index 0000000000..169429f60e --- /dev/null +++ b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_standard_peripheral/Include/gd32f30x_i2c.h @@ -0,0 +1,355 @@ +/*! + \file gd32f30x_i2c.h + \brief definitions for the I2C + + \version 2017-02-10, V1.0.0, firmware for GD32F30x + \version 2018-10-10, V1.1.0, firmware for GD32F30x + \version 2018-12-25, V2.0.0, firmware for GD32F30x + \version 2019-04-16, V2.0.1, firmware for GD32F30x + \version 2020-09-30, V2.1.0, firmware for GD32F30x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef GD32F30X_I2C_H +#define GD32F30X_I2C_H + +#include "gd32f30x.h" + +/* I2Cx(x=0,1) definitions */ +#define I2C0 I2C_BASE /*!< I2C0 base address */ +#define I2C1 (I2C_BASE + 0x00000400U) /*!< I2C1 base address */ + +/* registers definitions */ +#define I2C_CTL0(i2cx) REG32((i2cx) + 0x00U) /*!< I2C control register 0 */ +#define I2C_CTL1(i2cx) REG32((i2cx) + 0x04U) /*!< I2C control register 1 */ +#define I2C_SADDR0(i2cx) REG32((i2cx) + 0x08U) /*!< I2C slave address register 0*/ +#define I2C_SADDR1(i2cx) REG32((i2cx) + 0x0CU) /*!< I2C slave address register */ +#define I2C_DATA(i2cx) REG32((i2cx) + 0x10U) /*!< I2C transfer buffer register */ +#define I2C_STAT0(i2cx) REG32((i2cx) + 0x14U) /*!< I2C transfer status register 0 */ +#define I2C_STAT1(i2cx) REG32((i2cx) + 0x18U) /*!< I2C transfer status register */ +#define I2C_CKCFG(i2cx) REG32((i2cx) + 0x1CU) /*!< I2C clock configure register */ +#define I2C_RT(i2cx) REG32((i2cx) + 0x20U) /*!< I2C rise time register */ +#define I2C_FMPCFG(i2cx) REG32((i2cx) + 0x90U) /*!< I2C fast-mode-plus configure register */ + +/* bits definitions */ +/* I2Cx_CTL0 */ +#define I2C_CTL0_I2CEN BIT(0) /*!< peripheral enable */ +#define I2C_CTL0_SMBEN BIT(1) /*!< SMBus mode */ +#define I2C_CTL0_SMBSEL BIT(3) /*!< SMBus type */ +#define I2C_CTL0_ARPEN BIT(4) /*!< ARP enable */ +#define I2C_CTL0_PECEN BIT(5) /*!< PEC enable */ +#define I2C_CTL0_GCEN BIT(6) /*!< general call enable */ +#define I2C_CTL0_SS BIT(7) /*!< clock stretching disable (slave mode) */ +#define I2C_CTL0_START BIT(8) /*!< start generation */ +#define I2C_CTL0_STOP BIT(9) /*!< stop generation */ +#define I2C_CTL0_ACKEN BIT(10) /*!< acknowledge enable */ +#define I2C_CTL0_POAP BIT(11) /*!< acknowledge/PEC position (for data reception) */ +#define I2C_CTL0_PECTRANS BIT(12) /*!< packet error checking */ +#define I2C_CTL0_SALT BIT(13) /*!< SMBus alert */ +#define I2C_CTL0_SRESET BIT(15) /*!< software reset */ + +/* I2Cx_CTL1 */ +#define I2C_CTL1_I2CCLK BITS(0,6) /*!< I2CCLK[6:0] bits (peripheral clock frequency) */ +#define I2C_CTL1_ERRIE BIT(8) /*!< error interrupt inable */ +#define I2C_CTL1_EVIE BIT(9) /*!< event interrupt enable */ +#define I2C_CTL1_BUFIE BIT(10) /*!< buffer interrupt enable */ +#define I2C_CTL1_DMAON BIT(11) /*!< DMA requests enable */ +#define I2C_CTL1_DMALST BIT(12) /*!< DMA last transfer */ + +/* I2Cx_SADDR0 */ +#define I2C_SADDR0_ADDRESS0 BIT(0) /*!< bit 0 of a 10-bit address */ +#define I2C_SADDR0_ADDRESS BITS(1,7) /*!< 7-bit address or bits 7:1 of a 10-bit address */ +#define I2C_SADDR0_ADDRESS_H BITS(8,9) /*!< highest two bits of a 10-bit address */ +#define I2C_SADDR0_ADDFORMAT BIT(15) /*!< address mode for the I2C slave */ + +/* I2Cx_SADDR1 */ +#define I2C_SADDR1_DUADEN BIT(0) /*!< aual-address mode switch */ +#define I2C_SADDR1_ADDRESS2 BITS(1,7) /*!< second I2C address for the slave in dual-address mode */ + +/* I2Cx_DATA */ +#define I2C_DATA_TRB BITS(0,7) /*!< 8-bit data register */ + +/* I2Cx_STAT0 */ +#define I2C_STAT0_SBSEND BIT(0) /*!< start bit (master mode) */ +#define I2C_STAT0_ADDSEND BIT(1) /*!< address sent (master mode)/matched (slave mode) */ +#define I2C_STAT0_BTC BIT(2) /*!< byte transfer finished */ +#define I2C_STAT0_ADD10SEND BIT(3) /*!< 10-bit header sent (master mode) */ +#define I2C_STAT0_STPDET BIT(4) /*!< stop detection (slave mode) */ +#define I2C_STAT0_RBNE BIT(6) /*!< data register not empty (receivers) */ +#define I2C_STAT0_TBE BIT(7) /*!< data register empty (transmitters) */ +#define I2C_STAT0_BERR BIT(8) /*!< bus error */ +#define I2C_STAT0_LOSTARB BIT(9) /*!< arbitration lost (master mode) */ +#define I2C_STAT0_AERR BIT(10) /*!< acknowledge failure */ +#define I2C_STAT0_OUERR BIT(11) /*!< overrun/underrun */ +#define I2C_STAT0_PECERR BIT(12) /*!< PEC error in reception */ +#define I2C_STAT0_SMBTO BIT(14) /*!< timeout signal in SMBus mode */ +#define I2C_STAT0_SMBALT BIT(15) /*!< SMBus alert status */ + +/* I2Cx_STAT1 */ +#define I2C_STAT1_MASTER BIT(0) /*!< master/slave */ +#define I2C_STAT1_I2CBSY BIT(1) /*!< bus busy */ +#define I2C_STAT1_TR BIT(2) /*!< transmitter/receiver */ +#define I2C_STAT1_RXGC BIT(4) /*!< general call address (slave mode) */ +#define I2C_STAT1_DEFSMB BIT(5) /*!< SMBus device default address (slave mode) */ +#define I2C_STAT1_HSTSMB BIT(6) /*!< SMBus host header (slave mode) */ +#define I2C_STAT1_DUMODF BIT(7) /*!< dual flag (slave mode) */ +#define I2C_STAT1_PECV BITS(8,15) /*!< packet error checking value */ + +/* I2Cx_CKCFG */ +#define I2C_CKCFG_CLKC BITS(0,11) /*!< clock control register in fast/standard mode or fast mode plus(master mode) */ +#define I2C_CKCFG_DTCY BIT(14) /*!< duty cycle of fast mode or fast mode plus */ +#define I2C_CKCFG_FAST BIT(15) /*!< I2C speed selection in master mode */ + +/* I2Cx_RT */ +#define I2C_RT_RISETIME BITS(0,6) /*!< maximum rise time in fast/standard mode or fast mode plus(master mode) */ + +/* I2Cx_FMPCFG */ +#define I2C_FMPCFG_FMPEN BIT(0) /*!< fast mode plus enable bit */ + +/* constants definitions */ +/* define the I2C bit position and its register index offset */ +#define I2C_REGIDX_BIT(regidx, bitpos) (((uint32_t)(regidx) << 6) | (uint32_t)(bitpos)) +#define I2C_REG_VAL(i2cx, offset) (REG32((i2cx) + (((uint32_t)(offset) & 0xFFFFU) >> 6))) +#define I2C_BIT_POS(val) ((uint32_t)(val) & 0x1FU) +#define I2C_REGIDX_BIT2(regidx, bitpos, regidx2, bitpos2) (((uint32_t)(regidx2) << 22) | (uint32_t)((bitpos2) << 16)\ + | (((uint32_t)(regidx) << 6) | (uint32_t)(bitpos))) +#define I2C_REG_VAL2(i2cx, offset) (REG32((i2cx) + ((uint32_t)(offset) >> 22))) +#define I2C_BIT_POS2(val) (((uint32_t)(val) & 0x1F0000U) >> 16) + +/* register offset */ +#define I2C_CTL1_REG_OFFSET 0x04U /*!< CTL1 register offset */ +#define I2C_STAT0_REG_OFFSET 0x14U /*!< STAT0 register offset */ +#define I2C_STAT1_REG_OFFSET 0x18U /*!< STAT1 register offset */ + +/* I2C flags */ +typedef enum +{ + /* flags in STAT0 register */ + I2C_FLAG_SBSEND = I2C_REGIDX_BIT(I2C_STAT0_REG_OFFSET, 0U), /*!< start condition sent out in master mode */ + I2C_FLAG_ADDSEND = I2C_REGIDX_BIT(I2C_STAT0_REG_OFFSET, 1U), /*!< address is sent in master mode or received and matches in slave mode */ + I2C_FLAG_BTC = I2C_REGIDX_BIT(I2C_STAT0_REG_OFFSET, 2U), /*!< byte transmission finishes */ + I2C_FLAG_ADD10SEND = I2C_REGIDX_BIT(I2C_STAT0_REG_OFFSET, 3U), /*!< header of 10-bit address is sent in master mode */ + I2C_FLAG_STPDET = I2C_REGIDX_BIT(I2C_STAT0_REG_OFFSET, 4U), /*!< stop condition detected in slave mode */ + I2C_FLAG_RBNE = I2C_REGIDX_BIT(I2C_STAT0_REG_OFFSET, 6U), /*!< I2C_DATA is not Empty during receiving */ + I2C_FLAG_TBE = I2C_REGIDX_BIT(I2C_STAT0_REG_OFFSET, 7U), /*!< I2C_DATA is empty during transmitting */ + I2C_FLAG_BERR = I2C_REGIDX_BIT(I2C_STAT0_REG_OFFSET, 8U), /*!< a bus error occurs indication a unexpected start or stop condition on I2C bus */ + I2C_FLAG_LOSTARB = I2C_REGIDX_BIT(I2C_STAT0_REG_OFFSET, 9U), /*!< arbitration lost in master mode */ + I2C_FLAG_AERR = I2C_REGIDX_BIT(I2C_STAT0_REG_OFFSET, 10U), /*!< acknowledge error */ + I2C_FLAG_OUERR = I2C_REGIDX_BIT(I2C_STAT0_REG_OFFSET, 11U), /*!< over-run or under-run situation occurs in slave mode */ + I2C_FLAG_PECERR = I2C_REGIDX_BIT(I2C_STAT0_REG_OFFSET, 12U), /*!< PEC error when receiving data */ + I2C_FLAG_SMBTO = I2C_REGIDX_BIT(I2C_STAT0_REG_OFFSET, 14U), /*!< timeout signal in SMBus mode */ + I2C_FLAG_SMBALT = I2C_REGIDX_BIT(I2C_STAT0_REG_OFFSET, 15U), /*!< SMBus alert status */ + /* flags in STAT1 register */ + I2C_FLAG_MASTER = I2C_REGIDX_BIT(I2C_STAT1_REG_OFFSET, 0U), /*!< a flag indicating whether I2C block is in master or slave mode */ + I2C_FLAG_I2CBSY = I2C_REGIDX_BIT(I2C_STAT1_REG_OFFSET, 1U), /*!< busy flag */ + I2C_FLAG_TRS = I2C_REGIDX_BIT(I2C_STAT1_REG_OFFSET, 2U), /*!< whether the I2C is a transmitter or a receiver */ + I2C_FLAG_RXGC = I2C_REGIDX_BIT(I2C_STAT1_REG_OFFSET, 4U), /*!< general call address (00h) received */ + I2C_FLAG_DEFSMB = I2C_REGIDX_BIT(I2C_STAT1_REG_OFFSET, 5U), /*!< default address of SMBus device */ + I2C_FLAG_HSTSMB = I2C_REGIDX_BIT(I2C_STAT1_REG_OFFSET, 6U), /*!< SMBus host header detected in slave mode */ + I2C_FLAG_DUMOD = I2C_REGIDX_BIT(I2C_STAT1_REG_OFFSET, 7U) /*!< dual flag in slave mode indicating which address is matched in dual-address mode */ +}i2c_flag_enum; + +/* I2C interrupt flags */ +typedef enum +{ + /* interrupt flags in CTL1 register */ + I2C_INT_FLAG_SBSEND = I2C_REGIDX_BIT2(I2C_CTL1_REG_OFFSET, 9U, I2C_STAT0_REG_OFFSET, 0U), /*!< start condition sent out in master mode interrupt flag */ + I2C_INT_FLAG_ADDSEND = I2C_REGIDX_BIT2(I2C_CTL1_REG_OFFSET, 9U, I2C_STAT0_REG_OFFSET, 1U), /*!< address is sent in master mode or received and matches in slave mode interrupt flag */ + I2C_INT_FLAG_BTC = I2C_REGIDX_BIT2(I2C_CTL1_REG_OFFSET, 9U, I2C_STAT0_REG_OFFSET, 2U), /*!< byte transmission finishes */ + I2C_INT_FLAG_ADD10SEND = I2C_REGIDX_BIT2(I2C_CTL1_REG_OFFSET, 9U, I2C_STAT0_REG_OFFSET, 3U), /*!< header of 10-bit address is sent in master mode interrupt flag */ + I2C_INT_FLAG_STPDET = I2C_REGIDX_BIT2(I2C_CTL1_REG_OFFSET, 9U, I2C_STAT0_REG_OFFSET, 4U), /*!< stop condition detected in slave mode interrupt flag */ + I2C_INT_FLAG_RBNE = I2C_REGIDX_BIT2(I2C_CTL1_REG_OFFSET, 9U, I2C_STAT0_REG_OFFSET, 6U), /*!< I2C_DATA is not Empty during receiving interrupt flag */ + I2C_INT_FLAG_TBE = I2C_REGIDX_BIT2(I2C_CTL1_REG_OFFSET, 9U, I2C_STAT0_REG_OFFSET, 7U), /*!< I2C_DATA is empty during transmitting interrupt flag */ + I2C_INT_FLAG_BERR = I2C_REGIDX_BIT2(I2C_CTL1_REG_OFFSET, 8U, I2C_STAT0_REG_OFFSET, 8U), /*!< a bus error occurs indication a unexpected start or stop condition on I2C bus interrupt flag */ + I2C_INT_FLAG_LOSTARB = I2C_REGIDX_BIT2(I2C_CTL1_REG_OFFSET, 8U, I2C_STAT0_REG_OFFSET, 9U), /*!< arbitration lost in master mode interrupt flag */ + I2C_INT_FLAG_AERR = I2C_REGIDX_BIT2(I2C_CTL1_REG_OFFSET, 8U, I2C_STAT0_REG_OFFSET, 10U), /*!< acknowledge error interrupt flag */ + I2C_INT_FLAG_OUERR = I2C_REGIDX_BIT2(I2C_CTL1_REG_OFFSET, 8U, I2C_STAT0_REG_OFFSET, 11U), /*!< over-run or under-run situation occurs in slave mode interrupt flag */ + I2C_INT_FLAG_PECERR = I2C_REGIDX_BIT2(I2C_CTL1_REG_OFFSET, 8U, I2C_STAT0_REG_OFFSET, 12U), /*!< PEC error when receiving data interrupt flag */ + I2C_INT_FLAG_SMBTO = I2C_REGIDX_BIT2(I2C_CTL1_REG_OFFSET, 8U, I2C_STAT0_REG_OFFSET, 14U), /*!< timeout signal in SMBus mode interrupt flag */ + I2C_INT_FLAG_SMBALT = I2C_REGIDX_BIT2(I2C_CTL1_REG_OFFSET, 8U, I2C_STAT0_REG_OFFSET, 15U), /*!< SMBus Alert status interrupt flag */ +}i2c_interrupt_flag_enum; + +/* I2C interrupt enable or disable */ +typedef enum +{ + /* interrupt in CTL1 register */ + I2C_INT_ERR = I2C_REGIDX_BIT(I2C_CTL1_REG_OFFSET, 8U), /*!< error interrupt enable */ + I2C_INT_EV = I2C_REGIDX_BIT(I2C_CTL1_REG_OFFSET, 9U), /*!< event interrupt enable */ + I2C_INT_BUF = I2C_REGIDX_BIT(I2C_CTL1_REG_OFFSET, 10U), /*!< buffer interrupt enable */ +}i2c_interrupt_enum; + +/* SMBus/I2C mode switch and SMBus type selection */ +#define I2C_I2CMODE_ENABLE ((uint32_t)0x00000000U) /*!< I2C mode */ +#define I2C_SMBUSMODE_ENABLE I2C_CTL0_SMBEN /*!< SMBus mode */ + +/* SMBus/I2C mode switch and SMBus type selection */ +#define I2C_SMBUS_DEVICE ((uint32_t)0x00000000U) /*!< SMBus mode device type */ +#define I2C_SMBUS_HOST I2C_CTL0_SMBSEL /*!< SMBus mode host type */ + +/* I2C transfer direction */ +#define I2C_RECEIVER ((uint32_t)0x00000001U) /*!< receiver */ +#define I2C_TRANSMITTER ((uint32_t)0xFFFFFFFEU) /*!< transmitter */ + +/* whether or not to send an ACK */ +#define I2C_ACK_DISABLE ((uint32_t)0x00000000U) /*!< ACK will be not sent */ +#define I2C_ACK_ENABLE ((uint32_t)0x00000001U) /*!< ACK will be sent */ + +/* I2C POAP position*/ +#define I2C_ACKPOS_NEXT ((uint32_t)0x00000000U) /*!< ACKEN bit decides whether or not to send ACK for the next byte */ +#define I2C_ACKPOS_CURRENT ((uint32_t)0x00000001U) /*!< ACKEN bit decides whether or not to send ACK or not for the current byte */ + +/* I2C dual-address mode switch */ +#define I2C_DUADEN_DISABLE ((uint32_t)0x00000000U) /*!< dual-address mode disabled */ +#define I2C_DUADEN_ENABLE ((uint32_t)0x00000001U) /*!< dual-address mode enabled */ + +/* whether or not to stretch SCL low */ +#define I2C_SCLSTRETCH_ENABLE ((uint32_t)0x00000000U) /*!< SCL stretching is enabled */ +#define I2C_SCLSTRETCH_DISABLE I2C_CTL0_SS /*!< SCL stretching is disabled */ + +/* whether or not to response to a general call */ +#define I2C_GCEN_ENABLE I2C_CTL0_GCEN /*!< slave will response to a general call */ +#define I2C_GCEN_DISABLE ((uint32_t)0x00000000U) /*!< slave will not response to a general call */ + +/* software reset I2C */ +#define I2C_SRESET_SET I2C_CTL0_SRESET /*!< I2C is under reset */ +#define I2C_SRESET_RESET ((uint32_t)0x00000000U) /*!< I2C is not under reset */ + +/* I2C DMA mode configure */ +/* DMA mode switch */ +#define I2C_DMA_ON I2C_CTL1_DMAON /*!< DMA mode enabled */ +#define I2C_DMA_OFF ((uint32_t)0x00000000U) /*!< DMA mode disabled */ + +/* flag indicating DMA last transfer */ +#define I2C_DMALST_ON I2C_CTL1_DMALST /*!< next DMA EOT is the last transfer */ +#define I2C_DMALST_OFF ((uint32_t)0x00000000U) /*!< next DMA EOT is not the last transfer */ + +/* I2C PEC configure */ +/* PEC enable */ +#define I2C_PEC_ENABLE I2C_CTL0_PECEN /*!< PEC calculation on */ +#define I2C_PEC_DISABLE ((uint32_t)0x00000000U) /*!< PEC calculation off */ + +/* PEC transfer */ +#define I2C_PECTRANS_ENABLE I2C_CTL0_PECTRANS /*!< transfer PEC */ +#define I2C_PECTRANS_DISABLE ((uint32_t)0x00000000U) /*!< not transfer PEC value */ + +/* I2C SMBus configure */ +/* issue or not alert through SMBA pin */ +#define I2C_SALTSEND_ENABLE I2C_CTL0_SALT /*!< issue alert through SMBA pin */ +#define I2C_SALTSEND_DISABLE ((uint32_t)0x00000000U) /*!< not issue alert through SMBA */ + +/* ARP protocol in SMBus switch */ +#define I2C_ARP_ENABLE I2C_CTL0_ARPEN /*!< ARP enable */ +#define I2C_ARP_DISABLE ((uint32_t)0x00000000U) /*!< ARP disable */ + +/* fast mode plus enable */ +#define I2C_FAST_MODE_PLUS_ENABLE I2C_FMPCFG_FMPEN /*!< fast mode plus enable */ +#define I2C_FAST_MODE_PLUS_DISABLE ((uint32_t)0x00000000U) /*!< fast mode plus disable */ + +/* transmit I2C data */ +#define DATA_TRANS(regval) (BITS(0,7) & ((uint32_t)(regval) << 0)) + +/* receive I2C data */ +#define DATA_RECV(regval) GET_BITS((uint32_t)(regval), 0, 7) + +/* I2C duty cycle in fast mode or fast mode plus */ +#define I2C_DTCY_2 ((uint32_t)0x00000000U) /*!< in I2C fast mode or fast mode plus Tlow/Thigh = 2 */ +#define I2C_DTCY_16_9 I2C_CKCFG_DTCY /*!< in I2C fast mode or fast mode plus Tlow/Thigh = 16/9 */ + +/* address mode for the I2C slave */ +#define I2C_ADDFORMAT_7BITS ((uint32_t)0x00000000U) /*!< address:7 bits */ +#define I2C_ADDFORMAT_10BITS I2C_SADDR0_ADDFORMAT /*!< address:10 bits */ + +/* function declarations */ +/* reset I2C */ +void i2c_deinit(uint32_t i2c_periph); +/* configure I2C clock */ +void i2c_clock_config(uint32_t i2c_periph, uint32_t clkspeed, uint32_t dutycyc); +/* configure I2C address */ +void i2c_mode_addr_config(uint32_t i2c_periph, uint32_t mode, uint32_t addformat, uint32_t addr); +/* SMBus type selection */ +void i2c_smbus_type_config(uint32_t i2c_periph, uint32_t type); +/* whether or not to send an ACK */ +void i2c_ack_config(uint32_t i2c_periph, uint32_t ack); +/* configure I2C POAP position */ +void i2c_ackpos_config(uint32_t i2c_periph, uint32_t pos); +/* master sends slave address */ +void i2c_master_addressing(uint32_t i2c_periph, uint32_t addr, uint32_t trandirection); +/* enable dual-address mode */ +void i2c_dualaddr_enable(uint32_t i2c_periph, uint32_t dualaddr); +/* disable dual-address mode */ +void i2c_dualaddr_disable(uint32_t i2c_periph); +/* enable I2C */ +void i2c_enable(uint32_t i2c_periph); +/* disable I2C */ +void i2c_disable(uint32_t i2c_periph); + +/* generate a START condition on I2C bus */ +void i2c_start_on_bus(uint32_t i2c_periph); +/* generate a STOP condition on I2C bus */ +void i2c_stop_on_bus(uint32_t i2c_periph); +/* I2C transmit data function */ +void i2c_data_transmit(uint32_t i2c_periph, uint8_t data); +/* I2C receive data function */ +uint8_t i2c_data_receive(uint32_t i2c_periph); +/* enable I2C DMA mode */ +void i2c_dma_enable(uint32_t i2c_periph, uint32_t dmastate); +/* configure whether next DMA EOT is DMA last transfer or not */ +void i2c_dma_last_transfer_config(uint32_t i2c_periph, uint32_t dmalast); +/* whether to stretch SCL low when data is not ready in slave mode */ +void i2c_stretch_scl_low_config(uint32_t i2c_periph, uint32_t stretchpara); +/* whether or not to response to a general call */ +void i2c_slave_response_to_gcall_config(uint32_t i2c_periph, uint32_t gcallpara); +/* software reset I2C */ +void i2c_software_reset_config(uint32_t i2c_periph, uint32_t sreset); + +/* I2C PEC calculation on or off */ +void i2c_pec_enable(uint32_t i2c_periph, uint32_t pecstate); +/* I2C whether to transfer PEC value */ +void i2c_pec_transfer_enable(uint32_t i2c_periph, uint32_t pecpara); +/* packet error checking value */ +uint8_t i2c_pec_value_get(uint32_t i2c_periph); +/* I2C issue alert through SMBA pin */ +void i2c_smbus_issue_alert(uint32_t i2c_periph, uint32_t smbuspara); +/* I2C ARP protocol in SMBus switch */ +void i2c_smbus_arp_enable(uint32_t i2c_periph, uint32_t arpstate); + +/* check I2C flag is set or not */ +FlagStatus i2c_flag_get(uint32_t i2c_periph, i2c_flag_enum flag); +/* clear I2C flag */ +void i2c_flag_clear(uint32_t i2c_periph, i2c_flag_enum flag); +/* enable I2C interrupt */ +void i2c_interrupt_enable(uint32_t i2c_periph, i2c_interrupt_enum interrupt); +/* disable I2C interrupt */ +void i2c_interrupt_disable(uint32_t i2c_periph, i2c_interrupt_enum interrupt); +/* check I2C interrupt flag */ +FlagStatus i2c_interrupt_flag_get(uint32_t i2c_periph, i2c_interrupt_flag_enum int_flag); +/* clear I2C interrupt flag */ +void i2c_interrupt_flag_clear(uint32_t i2c_periph, i2c_interrupt_flag_enum int_flag); + +#endif /* GD32F30X_I2C_H */ diff --git a/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_standard_peripheral/Include/gd32f30x_misc.h b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_standard_peripheral/Include/gd32f30x_misc.h new file mode 100644 index 0000000000..392c690bf4 --- /dev/null +++ b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_standard_peripheral/Include/gd32f30x_misc.h @@ -0,0 +1,94 @@ +/*! + \file gd32f30x_misc.h + \brief definitions for the MISC + + \version 2017-02-10, V1.0.0, firmware for GD32F30x + \version 2018-10-10, V1.1.0, firmware for GD32F30x + \version 2018-12-25, V2.0.0, firmware for GD32F30x + \version 2020-09-30, V2.1.0, firmware for GD32F30x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef GD32F30X_MISC_H +#define GD32F30X_MISC_H + +#include "gd32f30x.h" + +/* constants definitions */ +/* set the RAM and FLASH base address */ +#define NVIC_VECTTAB_RAM ((uint32_t)0x20000000) /*!< RAM base address */ +#define NVIC_VECTTAB_FLASH ((uint32_t)0x08000000) /*!< Flash base address */ + +/* set the NVIC vector table offset mask */ +#define NVIC_VECTTAB_OFFSET_MASK ((uint32_t)0x1FFFFF80) + +/* the register key mask, if you want to do the write operation, you should write 0x5FA to VECTKEY bits */ +#define NVIC_AIRCR_VECTKEY_MASK ((uint32_t)0x05FA0000) + +/* priority group - define the pre-emption priority and the subpriority */ +#define NVIC_PRIGROUP_PRE0_SUB4 ((uint32_t)0x700) /*!< 0 bits for pre-emption priority 4 bits for subpriority */ +#define NVIC_PRIGROUP_PRE1_SUB3 ((uint32_t)0x600) /*!< 1 bits for pre-emption priority 3 bits for subpriority */ +#define NVIC_PRIGROUP_PRE2_SUB2 ((uint32_t)0x500) /*!< 2 bits for pre-emption priority 2 bits for subpriority */ +#define NVIC_PRIGROUP_PRE3_SUB1 ((uint32_t)0x400) /*!< 3 bits for pre-emption priority 1 bits for subpriority */ +#define NVIC_PRIGROUP_PRE4_SUB0 ((uint32_t)0x300) /*!< 4 bits for pre-emption priority 0 bits for subpriority */ + +/* choose the method to enter or exit the lowpower mode */ +#define SCB_SCR_SLEEPONEXIT ((uint8_t)0x02) /*!< choose the the system whether enter low power mode by exiting from ISR */ +#define SCB_SCR_SLEEPDEEP ((uint8_t)0x04) /*!< choose the the system enter the DEEPSLEEP mode or SLEEP mode */ +#define SCB_SCR_SEVONPEND ((uint8_t)0x10) /*!< choose the interrupt source that can wake up the lowpower mode */ + +#define SCB_LPM_SLEEP_EXIT_ISR SCB_SCR_SLEEPONEXIT +#define SCB_LPM_DEEPSLEEP SCB_SCR_SLEEPDEEP +#define SCB_LPM_WAKE_BY_ALL_INT SCB_SCR_SEVONPEND + +/* choose the systick clock source */ +#define SYSTICK_CLKSOURCE_HCLK_DIV8 ((uint32_t)0xFFFFFFFBU) /*!< systick clock source is from HCLK/8 */ +#define SYSTICK_CLKSOURCE_HCLK ((uint32_t)0x00000004U) /*!< systick clock source is from HCLK */ + +/* function declarations */ +/* set the priority group */ +void nvic_priority_group_set(uint32_t nvic_prigroup); + +/* enable NVIC request */ +void nvic_irq_enable(uint8_t nvic_irq, uint8_t nvic_irq_pre_priority, uint8_t nvic_irq_sub_priority); +/* disable NVIC request */ +void nvic_irq_disable(uint8_t nvic_irq); + +/* set the NVIC vector table base address */ +void nvic_vector_table_set(uint32_t nvic_vict_tab, uint32_t offset); + +/* set the state of the low power mode */ +void system_lowpower_set(uint8_t lowpower_mode); +/* reset the state of the low power mode */ +void system_lowpower_reset(uint8_t lowpower_mode); + +/* set the systick clock source */ +void systick_clksource_set(uint32_t systick_clksource); + +#endif /* GD32F30X_MISC_H */ diff --git a/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_standard_peripheral/Include/gd32f30x_pmu.h b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_standard_peripheral/Include/gd32f30x_pmu.h new file mode 100644 index 0000000000..bb7ffdaeb0 --- /dev/null +++ b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_standard_peripheral/Include/gd32f30x_pmu.h @@ -0,0 +1,187 @@ +/*! + \file gd32f30x_pmu.h + \brief definitions for the PMU + + \version 2017-02-10, V1.0.0, firmware for GD32F30x + \version 2018-10-10, V1.1.0, firmware for GD32F30x + \version 2018-12-25, V2.0.0, firmware for GD32F30x + \version 2020-09-30, V2.1.0, firmware for GD32F30x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + + +#ifndef GD32F30X_PMU_H +#define GD32F30X_PMU_H + +#include "gd32f30x.h" + +/* PMU definitions */ +#define PMU PMU_BASE /*!< PMU base address */ + +/* registers definitions */ +#define PMU_CTL REG32((PMU) + 0x00U) /*!< PMU control register */ +#define PMU_CS REG32((PMU) + 0x04U) /*!< PMU control and status register */ + +/* bits definitions */ +/* PMU_CTL */ +#define PMU_CTL_LDOLP BIT(0) /*!< LDO low power mode */ +#define PMU_CTL_STBMOD BIT(1) /*!< standby mode */ +#define PMU_CTL_WURST BIT(2) /*!< wakeup flag reset */ +#define PMU_CTL_STBRST BIT(3) /*!< standby flag reset */ +#define PMU_CTL_LVDEN BIT(4) /*!< low voltage detector enable */ +#define PMU_CTL_LVDT BITS(5,7) /*!< low voltage detector threshold */ +#define PMU_CTL_BKPWEN BIT(8) /*!< backup domain write enable */ +#define PMU_CTL_LDLP BIT(10) /*!< low-driver mode when use low power LDO */ +#define PMU_CTL_LDNP BIT(11) /*!< low-driver mode when use normal power LDO */ +#define PMU_CTL_LDOVS BITS(14,15) /*!< LDO output voltage select */ +#define PMU_CTL_HDEN BIT(16) /*!< high-driver mode enable */ +#define PMU_CTL_HDS BIT(17) /*!< high-driver mode switch */ +#define PMU_CTL_LDEN BITS(18,19) /*!< low-driver mode enable in deep-sleep mode */ + +/* PMU_CS */ +#define PMU_CS_WUF BIT(0) /*!< wakeup flag */ +#define PMU_CS_STBF BIT(1) /*!< standby flag */ +#define PMU_CS_LVDF BIT(2) /*!< low voltage detector status flag */ +#define PMU_CS_WUPEN BIT(8) /*!< wakeup pin enable */ +#define PMU_CS_LDOVSRF BIT(14) /*!< LDO voltage select ready flag */ +#define PMU_CS_HDRF BIT(16) /*!< high-driver ready flag */ +#define PMU_CS_HDSRF BIT(17) /*!< high-driver switch ready flag */ +#define PMU_CS_LDRF BITS(18,19) /*!< Low-driver mode ready flag */ + +/* constants definitions */ +/* PMU low voltage detector threshold definitions */ +#define CTL_LVDT(regval) (BITS(5,7)&((uint32_t)(regval)<<5)) +#define PMU_LVDT_0 CTL_LVDT(0) /*!< voltage threshold is 2.1V */ +#define PMU_LVDT_1 CTL_LVDT(1) /*!< voltage threshold is 2.3V */ +#define PMU_LVDT_2 CTL_LVDT(2) /*!< voltage threshold is 2.4V */ +#define PMU_LVDT_3 CTL_LVDT(3) /*!< voltage threshold is 2.6V */ +#define PMU_LVDT_4 CTL_LVDT(4) /*!< voltage threshold is 2.7V */ +#define PMU_LVDT_5 CTL_LVDT(5) /*!< voltage threshold is 2.9V */ +#define PMU_LVDT_6 CTL_LVDT(6) /*!< voltage threshold is 3.0V */ +#define PMU_LVDT_7 CTL_LVDT(7) /*!< voltage threshold is 3.1V */ + +/* PMU LDO output voltage select definitions */ +#define CTL_LDOVS(regval) (BITS(14,15)&((uint32_t)(regval)<<14)) +#define PMU_LDOVS_LOW CTL_LDOVS(1) /*!< LDO output voltage low mode */ +#define PMU_LDOVS_MID CTL_LDOVS(2) /*!< LDO output voltage mid mode */ +#define PMU_LDOVS_HIGH CTL_LDOVS(3) /*!< LDO output voltage high mode */ + +/* PMU high-driver mode switch */ +#define CTL_HDS(regval) (BIT(17)&((uint32_t)(regval)<<17)) +#define PMU_HIGHDR_SWITCH_NONE CTL_HDS(0) /*!< no high-driver mode switch */ +#define PMU_HIGHDR_SWITCH_EN CTL_HDS(1) /*!< high-driver mode switch */ + +/* PMU low-driver mode when use low power LDO */ +#define CTL_LDLP(regval) (BIT(10)&((uint32_t)(regval)<<10)) +#define PMU_NORMALDR_LOWPWR CTL_LDLP(0) /*!< normal driver when use low power LDO */ +#define PMU_LOWDR_LOWPWR CTL_LDLP(1) /*!< low-driver mode enabled when LDEN is 11 and use low power LDO */ + +/* PMU low-driver mode when use normal power LDO */ +#define CTL_LDNP(regval) (BIT(11)&((uint32_t)(regval)<<11)) +#define PMU_NORMALDR_NORMALPWR CTL_LDNP(0) /*!< normal driver when use normal power LDO */ +#define PMU_LOWDR_NORMALPWR CTL_LDNP(1) /*!< low-driver mode enabled when LDEN is 11 and use normal power LDO */ + +/* PMU low power mode ready flag definitions */ +#define CS_LDRF(regval) (BITS(18,19)&((uint32_t)(regval)<<18)) +#define PMU_LDRF_NORMAL CS_LDRF(0) /*!< normal driver in deep-sleep mode */ +#define PMU_LDRF_LOWDRIVER CS_LDRF(3) /*!< low-driver mode in deep-sleep mode */ + +/* PMU flag definitions */ +#define PMU_FLAG_WAKEUP PMU_CS_WUF /*!< wakeup flag status */ +#define PMU_FLAG_STANDBY PMU_CS_STBF /*!< standby flag status */ +#define PMU_FLAG_LVD PMU_CS_LVDF /*!< lvd flag status */ +#define PMU_FLAG_LDOVSRF PMU_CS_LDOVSRF /*!< LDO voltage select ready flag */ +#define PMU_FLAG_HDRF PMU_CS_HDRF /*!< high-driver ready flag */ +#define PMU_FLAG_HDSRF PMU_CS_HDSRF /*!< high-driver switch ready flag */ +#define PMU_FLAG_LDRF PMU_CS_LDRF /*!< low-driver mode ready flag */ + +/* PMU ldo definitions */ +#define PMU_LDO_NORMAL ((uint32_t)0x00000000U) /*!< LDO normal work when PMU enter deepsleep mode */ +#define PMU_LDO_LOWPOWER PMU_CTL_LDOLP /*!< LDO work at low power status when PMU enter deepsleep mode */ + +/* PMU flag reset definitions */ +#define PMU_FLAG_RESET_WAKEUP ((uint8_t)0x00U) /*!< wakeup flag reset */ +#define PMU_FLAG_RESET_STANDBY ((uint8_t)0x01U) /*!< standby flag reset */ + +/* PMU command constants definitions */ +#define WFI_CMD ((uint8_t)0x00U) /*!< use WFI command */ +#define WFE_CMD ((uint8_t)0x01U) /*!< use WFE command */ + +/* function declarations */ +/* reset PMU registers */ +void pmu_deinit(void); + +/* select low voltage detector threshold */ +void pmu_lvd_select(uint32_t lvdt_n); +/* select LDO output voltage */ +void pmu_ldo_output_select(uint32_t ldo_output); +/* disable PMU lvd */ +void pmu_lvd_disable(void); + +/* functions of low-driver mode and high-driver mode in deep-sleep mode */ +/* switch high-driver mode */ +void pmu_highdriver_switch_select(uint32_t highdr_switch); +/* enable high-driver mode */ +void pmu_highdriver_mode_enable(void); +/* disable high-driver mode */ +void pmu_highdriver_mode_disable(void); +/* enable low-driver mode in deep-sleep mode */ +void pmu_lowdriver_mode_enable(void); +/* disable low-driver mode in deep-sleep mode */ +void pmu_lowdriver_mode_disable(void); +/* in deep-sleep mode, driver mode when use low power LDO */ +void pmu_lowpower_driver_config(uint32_t mode); +/* in deep-sleep mode, driver mode when use normal power LDO */ +void pmu_normalpower_driver_config(uint32_t mode); + +/* set PMU mode */ +/* PMU work at sleep mode */ +void pmu_to_sleepmode(uint8_t sleepmodecmd); +/* PMU work at deepsleep mode */ +void pmu_to_deepsleepmode(uint32_t ldo, uint8_t deepsleepmodecmd); +/* PMU work at standby mode */ +void pmu_to_standbymode(uint8_t standbymodecmd); +/* enable PMU wakeup pin */ +void pmu_wakeup_pin_enable(void); +/* disable PMU wakeup pin */ +void pmu_wakeup_pin_disable(void); + +/* backup related functions */ +/* enable backup domain write */ +void pmu_backup_write_enable(void); +/* disable backup domain write */ +void pmu_backup_write_disable(void); + +/* flag functions */ +/* clear flag bit */ +void pmu_flag_clear(uint32_t flag_reset); +/* get flag state */ +FlagStatus pmu_flag_get(uint32_t flag); + +#endif /* GD32F30X_PMU_H */ diff --git a/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_standard_peripheral/Include/gd32f30x_rcu.h b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_standard_peripheral/Include/gd32f30x_rcu.h new file mode 100644 index 0000000000..d3724e7811 --- /dev/null +++ b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_standard_peripheral/Include/gd32f30x_rcu.h @@ -0,0 +1,1053 @@ +/*! + \file gd32f30x_rcu.h + \brief definitions for the RCU + + \version 2017-02-10, V1.0.0, firmware for GD32F30x + \version 2018-10-10, V1.1.0, firmware for GD32F30x + \version 2018-12-25, V2.0.0, firmware for GD32F30x + \version 2020-09-30, V2.1.0, firmware for GD32F30x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef GD32F30X_RCU_H +#define GD32F30X_RCU_H + +#include "gd32f30x.h" + +/* RCU definitions */ +#define RCU RCU_BASE + +/* registers definitions */ +#if (defined(GD32F30X_HD) || defined(GD32F30X_XD)) +#define RCU_CTL REG32(RCU + 0x00U) /*!< control register */ +#define RCU_CFG0 REG32(RCU + 0x04U) /*!< clock configuration register 0 */ +#define RCU_INT REG32(RCU + 0x08U) /*!< clock interrupt register */ +#define RCU_APB2RST REG32(RCU + 0x0CU) /*!< APB2 reset register */ +#define RCU_APB1RST REG32(RCU + 0x10U) /*!< APB1 reset register */ +#define RCU_AHBEN REG32(RCU + 0x14U) /*!< AHB enable register */ +#define RCU_APB2EN REG32(RCU + 0x18U) /*!< APB2 enable register */ +#define RCU_APB1EN REG32(RCU + 0x1CU) /*!< APB1 enable register */ +#define RCU_BDCTL REG32(RCU + 0x20U) /*!< backup domain control register */ +#define RCU_RSTSCK REG32(RCU + 0x24U) /*!< reset source / clock register */ +#define RCU_CFG1 REG32(RCU + 0x2CU) /*!< clock configuration register 1 */ +#define RCU_DSV REG32(RCU + 0x34U) /*!< deep-sleep mode voltage register */ +#define RCU_ADDCTL REG32(RCU + 0xC0U) /*!< Additional clock control register */ +#define RCU_ADDINT REG32(RCU + 0xCCU) /*!< Additional clock interrupt register */ +#define RCU_ADDAPB1RST REG32(RCU + 0xE0U) /*!< APB1 additional reset register */ +#define RCU_ADDAPB1EN REG32(RCU + 0xE4U) /*!< APB1 additional enable register */ +#elif defined(GD32F30X_CL) +#define RCU_CTL REG32(RCU + 0x00U) /*!< control register */ +#define RCU_CFG0 REG32(RCU + 0x04U) /*!< clock configuration register 0 */ +#define RCU_INT REG32(RCU + 0x08U) /*!< clock interrupt register */ +#define RCU_APB2RST REG32(RCU + 0x0CU) /*!< APB2 reset register */ +#define RCU_APB1RST REG32(RCU + 0x10U) /*!< APB1 reset register */ +#define RCU_AHBEN REG32(RCU + 0x14U) /*!< AHB1 enable register */ +#define RCU_APB2EN REG32(RCU + 0x18U) /*!< APB2 enable register */ +#define RCU_APB1EN REG32(RCU + 0x1CU) /*!< APB1 enable register */ +#define RCU_BDCTL REG32(RCU + 0x20U) /*!< backup domain control register */ +#define RCU_RSTSCK REG32(RCU + 0x24U) /*!< reset source / clock register */ +#define RCU_AHBRST REG32(RCU + 0x28U) /*!< AHB reset register */ +#define RCU_CFG1 REG32(RCU + 0x2CU) /*!< clock configuration register 1 */ +#define RCU_DSV REG32(RCU + 0x34U) /*!< deep-sleep mode voltage register */ +#define RCU_ADDCTL REG32(RCU + 0xC0U) /*!< Additional clock control register */ +#define RCU_ADDINT REG32(RCU + 0xCCU) /*!< Additional clock interrupt register */ +#define RCU_ADDAPB1RST REG32(RCU + 0xE0U) /*!< APB1 additional reset register */ +#define RCU_ADDAPB1EN REG32(RCU + 0xE4U) /*!< APB1 additional enable register */ +#endif /* GD32F30X_HD and GD32F30X_XD */ + +/* bits definitions */ +/* RCU_CTL */ +#if (defined(GD32F30X_HD) || defined(GD32F30X_XD)) +#define RCU_CTL_IRC8MEN BIT(0) /*!< internal high speed oscillator enable */ +#define RCU_CTL_IRC8MSTB BIT(1) /*!< IRC8M high speed internal oscillator stabilization flag */ +#define RCU_CTL_IRC8MADJ BITS(3,7) /*!< high speed internal oscillator clock trim adjust value */ +#define RCU_CTL_IRC8MCALIB BITS(8,15) /*!< high speed internal oscillator calibration value register */ +#define RCU_CTL_HXTALEN BIT(16) /*!< external high speed oscillator enable */ +#define RCU_CTL_HXTALSTB BIT(17) /*!< external crystal oscillator clock stabilization flag */ +#define RCU_CTL_HXTALBPS BIT(18) /*!< external crystal oscillator clock bypass mode enable */ +#define RCU_CTL_CKMEN BIT(19) /*!< HXTAL clock monitor enable */ +#define RCU_CTL_PLLEN BIT(24) /*!< PLL enable */ +#define RCU_CTL_PLLSTB BIT(25) /*!< PLL clock stabilization flag */ +#elif defined(GD32F30X_CL) +#define RCU_CTL_IRC8MEN BIT(0) /*!< internal high speed oscillator enable */ +#define RCU_CTL_IRC8MSTB BIT(1) /*!< IRC8M high speed internal oscillator stabilization flag */ +#define RCU_CTL_IRC8MADJ BITS(3,7) /*!< high speed internal oscillator clock trim adjust value */ +#define RCU_CTL_IRC8MCALIB BITS(8,15) /*!< high speed internal oscillator calibration value register */ +#define RCU_CTL_HXTALEN BIT(16) /*!< external high speed oscillator enable */ +#define RCU_CTL_HXTALSTB BIT(17) /*!< external crystal oscillator clock stabilization flag */ +#define RCU_CTL_HXTALBPS BIT(18) /*!< external crystal oscillator clock bypass mode enable */ +#define RCU_CTL_CKMEN BIT(19) /*!< HXTAL clock monitor enable */ +#define RCU_CTL_PLLEN BIT(24) /*!< PLL enable */ +#define RCU_CTL_PLLSTB BIT(25) /*!< PLL clock stabilization flag */ +#define RCU_CTL_PLL1EN BIT(26) /*!< PLL1 enable */ +#define RCU_CTL_PLL1STB BIT(27) /*!< PLL1 clock stabilization flag */ +#define RCU_CTL_PLL2EN BIT(28) /*!< PLL2 enable */ +#define RCU_CTL_PLL2STB BIT(29) /*!< PLL2 clock stabilization flag */ +#endif /* GD32F30X_HD and GD32F30X_XD */ + +/* RCU_CFG0 */ +#if (defined(GD32F30X_HD) || defined(GD32F30X_XD)) +#define RCU_CFG0_SCS BITS(0,1) /*!< system clock switch */ +#define RCU_CFG0_SCSS BITS(2,3) /*!< system clock switch status */ +#define RCU_CFG0_AHBPSC BITS(4,7) /*!< AHB prescaler selection */ +#define RCU_CFG0_APB1PSC BITS(8,10) /*!< APB1 prescaler selection */ +#define RCU_CFG0_APB2PSC BITS(11,13) /*!< APB2 prescaler selection */ +#define RCU_CFG0_ADCPSC BITS(14,15) /*!< ADC prescaler selection */ +#define RCU_CFG0_PLLSEL BIT(16) /*!< PLL clock source selection */ +#define RCU_CFG0_PREDV0 BIT(17) /*!< PREDV0 division factor */ +#define RCU_CFG0_PLLMF BITS(18,21) /*!< PLL clock multiplication factor */ +#define RCU_CFG0_USBDPSC BITS(22,23) /*!< USBD clock prescaler selection */ +#define RCU_CFG0_CKOUT0SEL BITS(24,26) /*!< CKOUT0 clock source selection */ +#define RCU_CFG0_PLLMF_4 BIT(27) /*!< bit 4 of PLLMF */ +#define RCU_CFG0_ADCPSC_2 BIT(28) /*!< bit 2 of ADCPSC */ +#define RCU_CFG0_PLLMF_5 BIT(30) /*!< bit 5 of PLLMF */ +#define RCU_CFG0_USBDPSC_2 BIT(31) /*!< bit 2 of USBDPSC */ +#elif defined(GD32F30X_CL) +#define RCU_CFG0_SCS BITS(0,1) /*!< system clock switch */ +#define RCU_CFG0_SCSS BITS(2,3) /*!< system clock switch status */ +#define RCU_CFG0_AHBPSC BITS(4,7) /*!< AHB prescaler selection */ +#define RCU_CFG0_APB1PSC BITS(8,10) /*!< APB1 prescaler selection */ +#define RCU_CFG0_APB2PSC BITS(11,13) /*!< APB2 prescaler selection */ +#define RCU_CFG0_ADCPSC BITS(14,15) /*!< ADC prescaler selection */ +#define RCU_CFG0_PLLSEL BIT(16) /*!< PLL clock source selection */ +#define RCU_CFG0_PREDV0_LSB BIT(17) /*!< the LSB of PREDV0 division factor */ +#define RCU_CFG0_PLLMF BITS(18,21) /*!< PLL clock multiplication factor */ +#define RCU_CFG0_USBFSPSC BITS(22,23) /*!< USBFS clock prescaler selection */ +#define RCU_CFG0_CKOUT0SEL BITS(24,27) /*!< CKOUT0 clock source selection */ +#define RCU_CFG0_ADCPSC_2 BIT(28) /*!< bit 2 of ADCPSC */ +#define RCU_CFG0_PLLMF_4 BIT(29) /*!< bit 4 of PLLMF */ +#define RCU_CFG0_PLLMF_5 BIT(30) /*!< bit 5 of PLLMF */ +#define RCU_CFG0_USBFSPSC_2 BIT(31) /*!< bit 2 of USBFSPSC */ +#endif /* GD32F30X_HD and GD32F30X_XD */ + +/* RCU_INT */ +#if (defined(GD32F30X_HD) || defined(GD32F30X_XD)) +#define RCU_INT_IRC40KSTBIF BIT(0) /*!< IRC40K stabilization interrupt flag */ +#define RCU_INT_LXTALSTBIF BIT(1) /*!< LXTAL stabilization interrupt flag */ +#define RCU_INT_IRC8MSTBIF BIT(2) /*!< IRC8M stabilization interrupt flag */ +#define RCU_INT_HXTALSTBIF BIT(3) /*!< HXTAL stabilization interrupt flag */ +#define RCU_INT_PLLSTBIF BIT(4) /*!< PLL stabilization interrupt flag */ +#define RCU_INT_CKMIF BIT(7) /*!< HXTAL clock stuck interrupt flag */ +#define RCU_INT_IRC40KSTBIE BIT(8) /*!< IRC40K stabilization interrupt enable */ +#define RCU_INT_LXTALSTBIE BIT(9) /*!< LXTAL stabilization interrupt enable */ +#define RCU_INT_IRC8MSTBIE BIT(10) /*!< IRC8M stabilization interrupt enable */ +#define RCU_INT_HXTALSTBIE BIT(11) /*!< HXTAL stabilization interrupt enable */ +#define RCU_INT_PLLSTBIE BIT(12) /*!< PLL stabilization interrupt enable */ +#define RCU_INT_IRC40KSTBIC BIT(16) /*!< IRC40K Stabilization interrupt clear */ +#define RCU_INT_LXTALSTBIC BIT(17) /*!< LXTAL Stabilization interrupt clear */ +#define RCU_INT_IRC8MSTBIC BIT(18) /*!< IRC8M Stabilization interrupt clear */ +#define RCU_INT_HXTALSTBIC BIT(19) /*!< HXTAL Stabilization interrupt clear */ +#define RCU_INT_PLLSTBIC BIT(20) /*!< PLL stabilization interrupt clear */ +#define RCU_INT_CKMIC BIT(23) /*!< HXTAL clock stuck interrupt clear */ +#elif defined(GD32F30X_CL) +#define RCU_INT_IRC40KSTBIF BIT(0) /*!< IRC40K stabilization interrupt flag */ +#define RCU_INT_LXTALSTBIF BIT(1) /*!< LXTAL stabilization interrupt flag */ +#define RCU_INT_IRC8MSTBIF BIT(2) /*!< IRC8M stabilization interrupt flag */ +#define RCU_INT_HXTALSTBIF BIT(3) /*!< HXTAL stabilization interrupt flag */ +#define RCU_INT_PLLSTBIF BIT(4) /*!< PLL stabilization interrupt flag */ +#define RCU_INT_PLL1STBIF BIT(5) /*!< PLL1 stabilization interrupt flag */ +#define RCU_INT_PLL2STBIF BIT(6) /*!< PLL2 stabilization interrupt flag */ +#define RCU_INT_CKMIF BIT(7) /*!< HXTAL clock stuck interrupt flag */ +#define RCU_INT_IRC40KSTBIE BIT(8) /*!< IRC40K stabilization interrupt enable */ +#define RCU_INT_LXTALSTBIE BIT(9) /*!< LXTAL stabilization interrupt enable */ +#define RCU_INT_IRC8MSTBIE BIT(10) /*!< IRC8M stabilization interrupt enable */ +#define RCU_INT_HXTALSTBIE BIT(11) /*!< HXTAL stabilization interrupt enable */ +#define RCU_INT_PLLSTBIE BIT(12) /*!< PLL stabilization interrupt enable */ +#define RCU_INT_PLL1STBIE BIT(13) /*!< PLL1 stabilization interrupt enable */ +#define RCU_INT_PLL2STBIE BIT(14) /*!< PLL2 stabilization interrupt enable */ +#define RCU_INT_IRC40KSTBIC BIT(16) /*!< IRC40K stabilization interrupt clear */ +#define RCU_INT_LXTALSTBIC BIT(17) /*!< LXTAL stabilization interrupt clear */ +#define RCU_INT_IRC8MSTBIC BIT(18) /*!< IRC8M stabilization interrupt clear */ +#define RCU_INT_HXTALSTBIC BIT(19) /*!< HXTAL stabilization interrupt clear */ +#define RCU_INT_PLLSTBIC BIT(20) /*!< PLL stabilization interrupt clear */ +#define RCU_INT_PLL1STBIC BIT(21) /*!< PLL1 stabilization interrupt clear */ +#define RCU_INT_PLL2STBIC BIT(22) /*!< PLL2 stabilization interrupt clear */ +#define RCU_INT_CKMIC BIT(23) /*!< HXTAL clock stuck interrupt clear */ +#endif /* GD32F30X_HD and GD32F30X_XD */ + +/* RCU_APB2RST */ +#define RCU_APB2RST_AFRST BIT(0) /*!< alternate function I/O reset */ +#define RCU_APB2RST_PARST BIT(2) /*!< GPIO port A reset */ +#define RCU_APB2RST_PBRST BIT(3) /*!< GPIO port B reset */ +#define RCU_APB2RST_PCRST BIT(4) /*!< GPIO port C reset */ +#define RCU_APB2RST_PDRST BIT(5) /*!< GPIO port D reset */ +#define RCU_APB2RST_PERST BIT(6) /*!< GPIO port E reset */ +#define RCU_APB2RST_PFRST BIT(7) /*!< GPIO port F reset */ +#define RCU_APB2RST_PGRST BIT(8) /*!< GPIO port G reset */ +#define RCU_APB2RST_ADC0RST BIT(9) /*!< ADC0 reset */ +#define RCU_APB2RST_ADC1RST BIT(10) /*!< ADC1 reset */ +#define RCU_APB2RST_TIMER0RST BIT(11) /*!< TIMER0 reset */ +#define RCU_APB2RST_SPI0RST BIT(12) /*!< SPI0 reset */ +#define RCU_APB2RST_TIMER7RST BIT(13) /*!< TIMER7 reset */ +#define RCU_APB2RST_USART0RST BIT(14) /*!< USART0 reset */ +#ifndef GD32F30X_CL +#define RCU_APB2RST_ADC2RST BIT(15) /*!< ADC2 reset */ +#endif /* GD32F30X_CL */ +#ifndef GD32F30X_HD +#define RCU_APB2RST_TIMER8RST BIT(19) /*!< TIMER8 reset */ +#define RCU_APB2RST_TIMER9RST BIT(20) /*!< TIMER9 reset */ +#define RCU_APB2RST_TIMER10RST BIT(21) /*!< TIMER10 reset */ +#endif /* GD32F30X_HD */ + +/* RCU_APB1RST */ +#define RCU_APB1RST_TIMER1RST BIT(0) /*!< TIMER1 reset */ +#define RCU_APB1RST_TIMER2RST BIT(1) /*!< TIMER2 reset */ +#define RCU_APB1RST_TIMER3RST BIT(2) /*!< TIMER3 reset */ +#define RCU_APB1RST_TIMER4RST BIT(3) /*!< TIMER4 reset */ +#define RCU_APB1RST_TIMER5RST BIT(4) /*!< TIMER5 reset */ +#define RCU_APB1RST_TIMER6RST BIT(5) /*!< TIMER6 reset */ +#ifndef GD32F30X_HD +#define RCU_APB1RST_TIMER11RST BIT(6) /*!< TIMER11 reset */ +#define RCU_APB1RST_TIMER12RST BIT(7) /*!< TIMER12 reset */ +#define RCU_APB1RST_TIMER13RST BIT(8) /*!< TIMER13 reset */ +#endif /* GD32F30X_HD */ +#define RCU_APB1RST_WWDGTRST BIT(11) /*!< WWDGT reset */ +#define RCU_APB1RST_SPI1RST BIT(14) /*!< SPI1 reset */ +#define RCU_APB1RST_SPI2RST BIT(15) /*!< SPI2 reset */ +#define RCU_APB1RST_USART1RST BIT(17) /*!< USART1 reset */ +#define RCU_APB1RST_USART2RST BIT(18) /*!< USART2 reset */ +#define RCU_APB1RST_UART3RST BIT(19) /*!< UART3 reset */ +#define RCU_APB1RST_UART4RST BIT(20) /*!< UART4 reset */ +#define RCU_APB1RST_I2C0RST BIT(21) /*!< I2C0 reset */ +#define RCU_APB1RST_I2C1RST BIT(22) /*!< I2C1 reset */ +#if (defined(GD32F30X_HD) || defined(GD32F30X_XD)) +#define RCU_APB1RST_USBDRST BIT(23) /*!< USBD reset */ +#endif /* GD32F30X_HD and GD32F30X_XD */ +#define RCU_APB1RST_CAN0RST BIT(25) /*!< CAN0 reset */ +#ifdef GD32F30X_CL +#define RCU_APB1RST_CAN1RST BIT(26) /*!< CAN1 reset */ +#endif /* GD32F30X_CL */ +#define RCU_APB1RST_BKPIRST BIT(27) /*!< backup interface reset */ +#define RCU_APB1RST_PMURST BIT(28) /*!< PMU reset */ +#define RCU_APB1RST_DACRST BIT(29) /*!< DAC reset */ + +/* RCU_AHBEN */ +#define RCU_AHBEN_DMA0EN BIT(0) /*!< DMA0 clock enable */ +#define RCU_AHBEN_DMA1EN BIT(1) /*!< DMA1 clock enable */ +#define RCU_AHBEN_SRAMSPEN BIT(2) /*!< SRAM clock enable when sleep mode */ +#define RCU_AHBEN_FMCSPEN BIT(4) /*!< FMC clock enable when sleep mode */ +#define RCU_AHBEN_CRCEN BIT(6) /*!< CRC clock enable */ +#define RCU_AHBEN_EXMCEN BIT(8) /*!< EXMC clock enable */ +#if (defined(GD32F30X_HD) || defined(GD32F30X_XD)) +#define RCU_AHBEN_SDIOEN BIT(10) /*!< SDIO clock enable */ +#elif defined(GD32F30X_CL) +#define RCU_AHBEN_USBFSEN BIT(12) /*!< USBFS clock enable */ +#define RCU_AHBEN_ENETEN BIT(14) /*!< ENET clock enable */ +#define RCU_AHBEN_ENETTXEN BIT(15) /*!< Ethernet TX clock enable */ +#define RCU_AHBEN_ENETRXEN BIT(16) /*!< Ethernet RX clock enable */ +#endif /* GD32F30X_HD and GD32F30X_XD */ + +/* RCU_APB2EN */ +#define RCU_APB2EN_AFEN BIT(0) /*!< alternate function IO clock enable */ +#define RCU_APB2EN_PAEN BIT(2) /*!< GPIO port A clock enable */ +#define RCU_APB2EN_PBEN BIT(3) /*!< GPIO port B clock enable */ +#define RCU_APB2EN_PCEN BIT(4) /*!< GPIO port C clock enable */ +#define RCU_APB2EN_PDEN BIT(5) /*!< GPIO port D clock enable */ +#define RCU_APB2EN_PEEN BIT(6) /*!< GPIO port E clock enable */ +#define RCU_APB2EN_PFEN BIT(7) /*!< GPIO port F clock enable */ +#define RCU_APB2EN_PGEN BIT(8) /*!< GPIO port G clock enable */ +#define RCU_APB2EN_ADC0EN BIT(9) /*!< ADC0 clock enable */ +#define RCU_APB2EN_ADC1EN BIT(10) /*!< ADC1 clock enable */ +#define RCU_APB2EN_TIMER0EN BIT(11) /*!< TIMER0 clock enable */ +#define RCU_APB2EN_SPI0EN BIT(12) /*!< SPI0 clock enable */ +#define RCU_APB2EN_TIMER7EN BIT(13) /*!< TIMER7 clock enable */ +#define RCU_APB2EN_USART0EN BIT(14) /*!< USART0 clock enable */ +#ifndef GD32F30X_CL +#define RCU_APB2EN_ADC2EN BIT(15) /*!< ADC2 clock enable */ +#endif /* GD32F30X_CL */ +#ifndef GD32F30X_HD +#define RCU_APB2EN_TIMER8EN BIT(19) /*!< TIMER8 clock enable */ +#define RCU_APB2EN_TIMER9EN BIT(20) /*!< TIMER9 clock enable */ +#define RCU_APB2EN_TIMER10EN BIT(21) /*!< TIMER10 clock enable */ +#endif /* GD32F30X_HD */ + +/* RCU_APB1EN */ +#define RCU_APB1EN_TIMER1EN BIT(0) /*!< TIMER1 clock enable */ +#define RCU_APB1EN_TIMER2EN BIT(1) /*!< TIMER2 clock enable */ +#define RCU_APB1EN_TIMER3EN BIT(2) /*!< TIMER3 clock enable */ +#define RCU_APB1EN_TIMER4EN BIT(3) /*!< TIMER4 clock enable */ +#define RCU_APB1EN_TIMER5EN BIT(4) /*!< TIMER5 clock enable */ +#define RCU_APB1EN_TIMER6EN BIT(5) /*!< TIMER6 clock enable */ +#ifndef GD32F30X_HD +#define RCU_APB1EN_TIMER11EN BIT(6) /*!< TIMER11 clock enable */ +#define RCU_APB1EN_TIMER12EN BIT(7) /*!< TIMER12 clock enable */ +#define RCU_APB1EN_TIMER13EN BIT(8) /*!< TIMER13 clock enable */ +#endif /* GD32F30X_HD */ +#define RCU_APB1EN_WWDGTEN BIT(11) /*!< WWDGT clock enable */ +#define RCU_APB1EN_SPI1EN BIT(14) /*!< SPI1 clock enable */ +#define RCU_APB1EN_SPI2EN BIT(15) /*!< SPI2 clock enable */ +#define RCU_APB1EN_USART1EN BIT(17) /*!< USART1 clock enable */ +#define RCU_APB1EN_USART2EN BIT(18) /*!< USART2 clock enable */ +#define RCU_APB1EN_UART3EN BIT(19) /*!< UART3 clock enable */ +#define RCU_APB1EN_UART4EN BIT(20) /*!< UART4 clock enable */ +#define RCU_APB1EN_I2C0EN BIT(21) /*!< I2C0 clock enable */ +#define RCU_APB1EN_I2C1EN BIT(22) /*!< I2C1 clock enable */ +#if (defined(GD32F30X_HD) || defined(GD32F30X_XD)) +#define RCU_APB1EN_USBDEN BIT(23) /*!< USBD clock enable */ +#endif /* GD32F30X_HD and GD32F30X_XD */ +#define RCU_APB1EN_CAN0EN BIT(25) /*!< CAN0 clock enable */ +#ifdef GD32F30X_CL +#define RCU_APB1EN_CAN1EN BIT(26) /*!< CAN1 clock enable */ +#endif /* GD32F30X_CL */ +#define RCU_APB1EN_BKPIEN BIT(27) /*!< backup interface clock enable */ +#define RCU_APB1EN_PMUEN BIT(28) /*!< PMU clock enable */ +#define RCU_APB1EN_DACEN BIT(29) /*!< DAC clock enable */ + +/* RCU_BDCTL */ +#define RCU_BDCTL_LXTALEN BIT(0) /*!< LXTAL enable */ +#define RCU_BDCTL_LXTALSTB BIT(1) /*!< low speed crystal oscillator stabilization flag */ +#define RCU_BDCTL_LXTALBPS BIT(2) /*!< LXTAL bypass mode enable */ +#define RCU_BDCTL_LXTALDRI BITS(3,4) /*!< LXTAL drive capability */ +#define RCU_BDCTL_RTCSRC BITS(8,9) /*!< RTC clock entry selection */ +#define RCU_BDCTL_RTCEN BIT(15) /*!< RTC clock enable */ +#define RCU_BDCTL_BKPRST BIT(16) /*!< backup domain reset */ + +/* RCU_RSTSCK */ +#define RCU_RSTSCK_IRC40KEN BIT(0) /*!< IRC40K enable */ +#define RCU_RSTSCK_IRC40KSTB BIT(1) /*!< IRC40K stabilization flag */ +#define RCU_RSTSCK_RSTFC BIT(24) /*!< reset flag clear */ +#define RCU_RSTSCK_EPRSTF BIT(26) /*!< external pin reset flag */ +#define RCU_RSTSCK_PORRSTF BIT(27) /*!< power reset flag */ +#define RCU_RSTSCK_SWRSTF BIT(28) /*!< software reset flag */ +#define RCU_RSTSCK_FWDGTRSTF BIT(29) /*!< free watchdog timer reset flag */ +#define RCU_RSTSCK_WWDGTRSTF BIT(30) /*!< window watchdog timer reset flag */ +#define RCU_RSTSCK_LPRSTF BIT(31) /*!< low-power reset flag */ + +#ifdef GD32F30X_CL +/* RCU_AHBRST */ +#define RCU_AHBRST_USBFSRST BIT(12) /*!< USBFS reset */ +#define RCU_AHBRST_ENETRST BIT(14) /*!< ENET reset */ +#endif /* GD32F30X_CL */ + +/* RCU_CFG1 */ +#if (defined(GD32F30X_HD) || defined(GD32F30X_XD)) +#define RCU_CFG1_ADCPSC_3 BIT(29) /*!< bit 4 of ADCPSC */ +#define RCU_CFG1_PLLPRESEL BIT(30) /*!< PLL clock source selection */ +#elif defined(GD32F30X_CL) +#define RCU_CFG1_PREDV0 BITS(0,3) /*!< PREDV0 division factor */ +#define RCU_CFG1_PREDV1 BITS(4,7) /*!< PREDV1 division factor */ +#define RCU_CFG1_PLL1MF BITS(8,11) /*!< PLL1 clock multiplication factor */ +#define RCU_CFG1_PLL2MF BITS(12,15) /*!< PLL2 clock multiplication factor */ +#define RCU_CFG1_PREDV0SEL BIT(16) /*!< PREDV0 input clock source selection */ +#define RCU_CFG1_I2S1SEL BIT(17) /*!< I2S1 clock source selection */ +#define RCU_CFG1_I2S2SEL BIT(18) /*!< I2S2 clock source selection */ +#define RCU_CFG1_ADCPSC_3 BIT(29) /*!< bit 4 of ADCPSC */ +#define RCU_CFG1_PLLPRESEL BIT(30) /*!< PLL clock source selection */ +#define RCU_CFG1_PLL2MF_4 BIT(31) /*!< bit 5 of PLL2MF */ +#endif /* GD32F30X_HD and GD32F30X_XD */ + +/* RCU_DSV */ +#define RCU_DSV_DSLPVS BITS(0,2) /*!< deep-sleep mode voltage select */ + +/* RCU_ADDCTL */ +#define RCU_ADDCTL_CK48MSEL BIT(0) /*!< 48MHz clock selection */ +#define RCU_ADDCTL_IRC48MEN BIT(16) /*!< internal 48MHz RC oscillator enable */ +#define RCU_ADDCTL_IRC48MSTB BIT(17) /*!< internal 48MHz RC oscillator clock stabilization flag */ +#define RCU_ADDCTL_IRC48MCAL BITS(24,31) /*!< internal 48MHz RC oscillator calibration value register */ + +/* RCU_ADDINT */ +#define RCU_ADDINT_IRC48MSTBIF BIT(6) /*!< IRC48M stabilization interrupt flag */ +#define RCU_ADDINT_IRC48MSTBIE BIT(14) /*!< internal 48 MHz RC oscillator stabilization interrupt enable */ +#define RCU_ADDINT_IRC48MSTBIC BIT(22) /*!< internal 48 MHz RC oscillator stabilization interrupt clear */ + +/* RCU_ADDAPB1RST */ +#define RCU_ADDAPB1RST_CTCRST BIT(27) /*!< CTC reset */ + +/* RCU_ADDAPB1EN */ +#define RCU_ADDAPB1EN_CTCEN BIT(27) /*!< CTC clock enable */ + + +/* constants definitions */ +/* define the peripheral clock enable bit position and its register index offset */ +#define RCU_REGIDX_BIT(regidx, bitpos) (((uint32_t)(regidx) << 6) | (uint32_t)(bitpos)) +#define RCU_REG_VAL(periph) (REG32(RCU + ((uint32_t)(periph) >> 6))) +#define RCU_BIT_POS(val) ((uint32_t)(val) & 0x1FU) + +/* register offset */ +/* peripherals enable */ +#define AHBEN_REG_OFFSET 0x14U /*!< AHB enable register offset */ +#define APB1EN_REG_OFFSET 0x1CU /*!< APB1 enable register offset */ +#define APB2EN_REG_OFFSET 0x18U /*!< APB2 enable register offset */ +#define ADD_APB1EN_REG_OFFSET 0xE4U /*!< APB1 additional enable register offset */ + +/* peripherals reset */ +#define AHBRST_REG_OFFSET 0x28U /*!< AHB reset register offset */ +#define APB1RST_REG_OFFSET 0x10U /*!< APB1 reset register offset */ +#define APB2RST_REG_OFFSET 0x0CU /*!< APB2 reset register offset */ +#define ADD_APB1RST_REG_OFFSET 0xE0U /*!< APB1 additional reset register offset */ +#define RSTSCK_REG_OFFSET 0x24U /*!< reset source/clock register offset */ + +/* clock control */ +#define CTL_REG_OFFSET 0x00U /*!< control register offset */ +#define BDCTL_REG_OFFSET 0x20U /*!< backup domain control register offset */ +#define ADDCTL_REG_OFFSET 0xC0U /*!< additional clock control register offset */ + +/* clock stabilization and stuck interrupt */ +#define INT_REG_OFFSET 0x08U /*!< clock interrupt register offset */ +#define ADDINT_REG_OFFSET 0xCCU /*!< additional clock interrupt register offset */ + +/* configuration register */ +#define CFG0_REG_OFFSET 0x04U /*!< clock configuration register 0 offset */ +#define CFG1_REG_OFFSET 0x2CU /*!< clock configuration register 1 offset */ + +/* peripheral clock enable */ +typedef enum +{ + /* AHB peripherals */ + RCU_DMA0 = RCU_REGIDX_BIT(AHBEN_REG_OFFSET, 0U), /*!< DMA0 clock */ + RCU_DMA1 = RCU_REGIDX_BIT(AHBEN_REG_OFFSET, 1U), /*!< DMA1 clock */ + RCU_CRC = RCU_REGIDX_BIT(AHBEN_REG_OFFSET, 6U), /*!< CRC clock */ + RCU_EXMC = RCU_REGIDX_BIT(AHBEN_REG_OFFSET, 8U), /*!< EXMC clock */ +#if (defined(GD32F30X_HD) || defined(GD32F30X_XD)) + RCU_SDIO = RCU_REGIDX_BIT(AHBEN_REG_OFFSET, 10U), /*!< SDIO clock */ +#elif defined(GD32F30X_CL) + RCU_USBFS = RCU_REGIDX_BIT(AHBEN_REG_OFFSET, 12U), /*!< USBFS clock */ + RCU_ENET = RCU_REGIDX_BIT(AHBEN_REG_OFFSET, 14U), /*!< ENET clock */ + RCU_ENETTX = RCU_REGIDX_BIT(AHBEN_REG_OFFSET, 15U), /*!< ENETTX clock */ + RCU_ENETRX = RCU_REGIDX_BIT(AHBEN_REG_OFFSET, 16U), /*!< ENETRX clock */ +#endif /* GD32F30X_HD and GD32F30X_XD */ + + /* APB1 peripherals */ + RCU_TIMER1 = RCU_REGIDX_BIT(APB1EN_REG_OFFSET, 0U), /*!< TIMER1 clock */ + RCU_TIMER2 = RCU_REGIDX_BIT(APB1EN_REG_OFFSET, 1U), /*!< TIMER2 clock */ + RCU_TIMER3 = RCU_REGIDX_BIT(APB1EN_REG_OFFSET, 2U), /*!< TIMER3 clock */ + RCU_TIMER4 = RCU_REGIDX_BIT(APB1EN_REG_OFFSET, 3U), /*!< TIMER4 clock */ + RCU_TIMER5 = RCU_REGIDX_BIT(APB1EN_REG_OFFSET, 4U), /*!< TIMER5 clock */ + RCU_TIMER6 = RCU_REGIDX_BIT(APB1EN_REG_OFFSET, 5U), /*!< TIMER6 clock */ +#ifndef GD32F30X_HD + RCU_TIMER11 = RCU_REGIDX_BIT(APB1EN_REG_OFFSET, 6U), /*!< TIMER11 clock */ + RCU_TIMER12 = RCU_REGIDX_BIT(APB1EN_REG_OFFSET, 7U), /*!< TIMER12 clock */ + RCU_TIMER13 = RCU_REGIDX_BIT(APB1EN_REG_OFFSET, 8U), /*!< TIMER13 clock */ +#endif /* GD32F30X_HD */ + RCU_WWDGT = RCU_REGIDX_BIT(APB1EN_REG_OFFSET, 11U), /*!< WWDGT clock */ + RCU_SPI1 = RCU_REGIDX_BIT(APB1EN_REG_OFFSET, 14U), /*!< SPI1 clock */ + RCU_SPI2 = RCU_REGIDX_BIT(APB1EN_REG_OFFSET, 15U), /*!< SPI2 clock */ + RCU_USART1 = RCU_REGIDX_BIT(APB1EN_REG_OFFSET, 17U), /*!< USART1 clock */ + RCU_USART2 = RCU_REGIDX_BIT(APB1EN_REG_OFFSET, 18U), /*!< USART2 clock */ + RCU_UART3 = RCU_REGIDX_BIT(APB1EN_REG_OFFSET, 19U), /*!< UART3 clock */ + RCU_UART4 = RCU_REGIDX_BIT(APB1EN_REG_OFFSET, 20U), /*!< UART4 clock */ + RCU_I2C0 = RCU_REGIDX_BIT(APB1EN_REG_OFFSET, 21U), /*!< I2C0 clock */ + RCU_I2C1 = RCU_REGIDX_BIT(APB1EN_REG_OFFSET, 22U), /*!< I2C1 clock */ +#if (defined(GD32F30X_HD) || defined(GD32F30X_XD)) + RCU_USBD = RCU_REGIDX_BIT(APB1EN_REG_OFFSET, 23U), /*!< USBD clock */ +#endif /* GD32F30X_HD and GD32F30X_XD */ + RCU_CAN0 = RCU_REGIDX_BIT(APB1EN_REG_OFFSET, 25U), /*!< CAN0 clock */ +#ifdef GD32F30X_CL + RCU_CAN1 = RCU_REGIDX_BIT(APB1EN_REG_OFFSET, 26U), /*!< CAN1 clock */ +#endif /* GD32F30X_CL */ + RCU_BKPI = RCU_REGIDX_BIT(APB1EN_REG_OFFSET, 27U), /*!< BKPI clock */ + RCU_PMU = RCU_REGIDX_BIT(APB1EN_REG_OFFSET, 28U), /*!< PMU clock */ + RCU_DAC = RCU_REGIDX_BIT(APB1EN_REG_OFFSET, 29U), /*!< DAC clock */ + RCU_RTC = RCU_REGIDX_BIT(BDCTL_REG_OFFSET, 15U), /*!< RTC clock */ + RCU_CTC = RCU_REGIDX_BIT(ADD_APB1EN_REG_OFFSET, 27U), /*!< CTC clock */ + + /* APB2 peripherals */ + RCU_AF = RCU_REGIDX_BIT(APB2EN_REG_OFFSET, 0U), /*!< alternate function clock */ + RCU_GPIOA = RCU_REGIDX_BIT(APB2EN_REG_OFFSET, 2U), /*!< GPIOA clock */ + RCU_GPIOB = RCU_REGIDX_BIT(APB2EN_REG_OFFSET, 3U), /*!< GPIOB clock */ + RCU_GPIOC = RCU_REGIDX_BIT(APB2EN_REG_OFFSET, 4U), /*!< GPIOC clock */ + RCU_GPIOD = RCU_REGIDX_BIT(APB2EN_REG_OFFSET, 5U), /*!< GPIOD clock */ + RCU_GPIOE = RCU_REGIDX_BIT(APB2EN_REG_OFFSET, 6U), /*!< GPIOE clock */ + RCU_GPIOF = RCU_REGIDX_BIT(APB2EN_REG_OFFSET, 7U), /*!< GPIOF clock */ + RCU_GPIOG = RCU_REGIDX_BIT(APB2EN_REG_OFFSET, 8U), /*!< GPIOG clock */ + RCU_ADC0 = RCU_REGIDX_BIT(APB2EN_REG_OFFSET, 9U), /*!< ADC0 clock */ + RCU_ADC1 = RCU_REGIDX_BIT(APB2EN_REG_OFFSET, 10U), /*!< ADC1 clock */ + RCU_TIMER0 = RCU_REGIDX_BIT(APB2EN_REG_OFFSET, 11U), /*!< TIMER0 clock */ + RCU_SPI0 = RCU_REGIDX_BIT(APB2EN_REG_OFFSET, 12U), /*!< SPI0 clock */ + RCU_TIMER7 = RCU_REGIDX_BIT(APB2EN_REG_OFFSET, 13U), /*!< TIMER7 clock */ + RCU_USART0 = RCU_REGIDX_BIT(APB2EN_REG_OFFSET, 14U), /*!< USART0 clock */ +#ifndef GD32F30X_CL + RCU_ADC2 = RCU_REGIDX_BIT(APB2EN_REG_OFFSET, 15U), /*!< ADC2 clock */ +#endif /* GD32F30X_CL */ +#ifndef GD32F30X_HD + RCU_TIMER8 = RCU_REGIDX_BIT(APB2EN_REG_OFFSET, 19U), /*!< TIMER8 clock */ + RCU_TIMER9 = RCU_REGIDX_BIT(APB2EN_REG_OFFSET, 20U), /*!< TIMER9 clock */ + RCU_TIMER10 = RCU_REGIDX_BIT(APB2EN_REG_OFFSET, 21U), /*!< TIMER10 clock */ +#endif /* GD32F30X_HD */ +}rcu_periph_enum; + +/* peripheral clock enable when sleep mode*/ +typedef enum +{ + /* AHB peripherals */ + RCU_SRAM_SLP = RCU_REGIDX_BIT(AHBEN_REG_OFFSET, 2U), /*!< SRAM clock */ + RCU_FMC_SLP = RCU_REGIDX_BIT(AHBEN_REG_OFFSET, 4U), /*!< FMC clock */ +}rcu_periph_sleep_enum; + +/* peripherals reset */ +typedef enum +{ + /* AHB peripherals */ +#ifdef GD32F30X_CL + RCU_USBFSRST = RCU_REGIDX_BIT(AHBRST_REG_OFFSET, 12U), /*!< USBFS clock reset */ + RCU_ENETRST = RCU_REGIDX_BIT(AHBRST_REG_OFFSET, 14U), /*!< ENET clock reset */ +#endif /* GD32F30X_CL */ + + /* APB1 peripherals */ + RCU_TIMER1RST = RCU_REGIDX_BIT(APB1RST_REG_OFFSET, 0U), /*!< TIMER1 clock reset */ + RCU_TIMER2RST = RCU_REGIDX_BIT(APB1RST_REG_OFFSET, 1U), /*!< TIMER2 clock reset */ + RCU_TIMER3RST = RCU_REGIDX_BIT(APB1RST_REG_OFFSET, 2U), /*!< TIMER3 clock reset */ + RCU_TIMER4RST = RCU_REGIDX_BIT(APB1RST_REG_OFFSET, 3U), /*!< TIMER4 clock reset */ + RCU_TIMER5RST = RCU_REGIDX_BIT(APB1RST_REG_OFFSET, 4U), /*!< TIMER5 clock reset */ + RCU_TIMER6RST = RCU_REGIDX_BIT(APB1RST_REG_OFFSET, 5U), /*!< TIMER6 clock reset */ +#ifndef GD32F30X_HD + RCU_TIMER11RST = RCU_REGIDX_BIT(APB1RST_REG_OFFSET, 6U), /*!< TIMER11 clock reset */ + RCU_TIMER12RST = RCU_REGIDX_BIT(APB1RST_REG_OFFSET, 7U), /*!< TIMER12 clock reset */ + RCU_TIMER13RST = RCU_REGIDX_BIT(APB1RST_REG_OFFSET, 8U), /*!< TIMER13 clock reset */ +#endif /* GD32F30X_HD */ + RCU_WWDGTRST = RCU_REGIDX_BIT(APB1RST_REG_OFFSET, 11U), /*!< WWDGT clock reset */ + RCU_SPI1RST = RCU_REGIDX_BIT(APB1RST_REG_OFFSET, 14U), /*!< SPI1 clock reset */ + RCU_SPI2RST = RCU_REGIDX_BIT(APB1RST_REG_OFFSET, 15U), /*!< SPI2 clock reset */ + RCU_USART1RST = RCU_REGIDX_BIT(APB1RST_REG_OFFSET, 17U), /*!< USART1 clock reset */ + RCU_USART2RST = RCU_REGIDX_BIT(APB1RST_REG_OFFSET, 18U), /*!< USART2 clock reset */ + RCU_UART3RST = RCU_REGIDX_BIT(APB1RST_REG_OFFSET, 19U), /*!< UART3 clock reset */ + RCU_UART4RST = RCU_REGIDX_BIT(APB1RST_REG_OFFSET, 20U), /*!< UART4 clock reset */ + RCU_I2C0RST = RCU_REGIDX_BIT(APB1RST_REG_OFFSET, 21U), /*!< I2C0 clock reset */ + RCU_I2C1RST = RCU_REGIDX_BIT(APB1RST_REG_OFFSET, 22U), /*!< I2C1 clock reset */ +#if (defined(GD32F30X_HD) || defined(GD32F30X_XD)) + RCU_USBDRST = RCU_REGIDX_BIT(APB1RST_REG_OFFSET, 23U), /*!< USBD clock reset */ +#endif /* GD32F30X_HD and GD32F30X_XD */ + RCU_CAN0RST = RCU_REGIDX_BIT(APB1RST_REG_OFFSET, 25U), /*!< CAN0 clock reset */ +#ifdef GD32F30X_CL + RCU_CAN1RST = RCU_REGIDX_BIT(APB1RST_REG_OFFSET, 26U), /*!< CAN1 clock reset */ +#endif /* GD32F30X_CL */ + RCU_BKPIRST = RCU_REGIDX_BIT(APB1RST_REG_OFFSET, 27U), /*!< BKPI clock reset */ + RCU_PMURST = RCU_REGIDX_BIT(APB1RST_REG_OFFSET, 28U), /*!< PMU clock reset */ + RCU_DACRST = RCU_REGIDX_BIT(APB1RST_REG_OFFSET, 29U), /*!< DAC clock reset */ + RCU_CTCRST = RCU_REGIDX_BIT(ADD_APB1RST_REG_OFFSET, 27U), /*!< RTC clock reset */ + + /* APB2 peripherals */ + RCU_AFRST = RCU_REGIDX_BIT(APB2RST_REG_OFFSET, 0U), /*!< alternate function clock reset */ + RCU_GPIOARST = RCU_REGIDX_BIT(APB2RST_REG_OFFSET, 2U), /*!< GPIOA clock reset */ + RCU_GPIOBRST = RCU_REGIDX_BIT(APB2RST_REG_OFFSET, 3U), /*!< GPIOB clock reset */ + RCU_GPIOCRST = RCU_REGIDX_BIT(APB2RST_REG_OFFSET, 4U), /*!< GPIOC clock reset */ + RCU_GPIODRST = RCU_REGIDX_BIT(APB2RST_REG_OFFSET, 5U), /*!< GPIOD clock reset */ + RCU_GPIOERST = RCU_REGIDX_BIT(APB2RST_REG_OFFSET, 6U), /*!< GPIOE clock reset */ + RCU_GPIOFRST = RCU_REGIDX_BIT(APB2RST_REG_OFFSET, 7U), /*!< GPIOF clock reset */ + RCU_GPIOGRST = RCU_REGIDX_BIT(APB2RST_REG_OFFSET, 8U), /*!< GPIOG clock reset */ + RCU_ADC0RST = RCU_REGIDX_BIT(APB2RST_REG_OFFSET, 9U), /*!< ADC0 clock reset */ + RCU_ADC1RST = RCU_REGIDX_BIT(APB2RST_REG_OFFSET, 10U), /*!< ADC1 clock reset */ + RCU_TIMER0RST = RCU_REGIDX_BIT(APB2RST_REG_OFFSET, 11U), /*!< TIMER0 clock reset */ + RCU_SPI0RST = RCU_REGIDX_BIT(APB2RST_REG_OFFSET, 12U), /*!< SPI0 clock reset */ + RCU_TIMER7RST = RCU_REGIDX_BIT(APB2RST_REG_OFFSET, 13U), /*!< TIMER7 clock reset */ + RCU_USART0RST = RCU_REGIDX_BIT(APB2RST_REG_OFFSET, 14U), /*!< USART0 clock reset */ +#ifndef GD32F30X_CL + RCU_ADC2RST = RCU_REGIDX_BIT(APB2RST_REG_OFFSET, 15U), /*!< ADC2 clock reset */ +#endif /* GD32F30X_CL */ +#ifndef GD32F30X_HD + RCU_TIMER8RST = RCU_REGIDX_BIT(APB2RST_REG_OFFSET, 19U), /*!< TIMER8 clock reset */ + RCU_TIMER9RST = RCU_REGIDX_BIT(APB2RST_REG_OFFSET, 20U), /*!< TIMER9 clock reset */ + RCU_TIMER10RST = RCU_REGIDX_BIT(APB2RST_REG_OFFSET, 21U), /*!< TIMER10 clock reset */ +#endif /* GD32F30X_HD */ +}rcu_periph_reset_enum; + +/* clock stabilization and peripheral reset flags */ +typedef enum +{ + /* clock stabilization flags */ + RCU_FLAG_IRC8MSTB = RCU_REGIDX_BIT(CTL_REG_OFFSET, 1U), /*!< IRC8M stabilization flags */ + RCU_FLAG_HXTALSTB = RCU_REGIDX_BIT(CTL_REG_OFFSET, 17U), /*!< HXTAL stabilization flags */ + RCU_FLAG_PLLSTB = RCU_REGIDX_BIT(CTL_REG_OFFSET, 25U), /*!< PLL stabilization flags */ +#ifdef GD32F30X_CL + RCU_FLAG_PLL1STB = RCU_REGIDX_BIT(CTL_REG_OFFSET, 27U), /*!< PLL1 stabilization flags */ + RCU_FLAG_PLL2STB = RCU_REGIDX_BIT(CTL_REG_OFFSET, 29U), /*!< PLL2 stabilization flags */ +#endif /* GD32F30X_CL */ + RCU_FLAG_LXTALSTB = RCU_REGIDX_BIT(BDCTL_REG_OFFSET, 1U), /*!< LXTAL stabilization flags */ + RCU_FLAG_IRC40KSTB = RCU_REGIDX_BIT(RSTSCK_REG_OFFSET, 1U), /*!< IRC40K stabilization flags */ + RCU_FLAG_IRC48MSTB = RCU_REGIDX_BIT(ADDCTL_REG_OFFSET, 17U), /*!< IRC48M stabilization flags */ + /* reset source flags */ + RCU_FLAG_EPRST = RCU_REGIDX_BIT(RSTSCK_REG_OFFSET, 26U), /*!< external PIN reset flags */ + RCU_FLAG_PORRST = RCU_REGIDX_BIT(RSTSCK_REG_OFFSET, 27U), /*!< power reset flags */ + RCU_FLAG_SWRST = RCU_REGIDX_BIT(RSTSCK_REG_OFFSET, 28U), /*!< software reset flags */ + RCU_FLAG_FWDGTRST = RCU_REGIDX_BIT(RSTSCK_REG_OFFSET, 29U), /*!< FWDGT reset flags */ + RCU_FLAG_WWDGTRST = RCU_REGIDX_BIT(RSTSCK_REG_OFFSET, 30U), /*!< WWDGT reset flags */ + RCU_FLAG_LPRST = RCU_REGIDX_BIT(RSTSCK_REG_OFFSET, 31U), /*!< low-power reset flags */ +}rcu_flag_enum; + +/* clock stabilization and ckm interrupt flags */ +typedef enum +{ + RCU_INT_FLAG_IRC40KSTB = RCU_REGIDX_BIT(INT_REG_OFFSET, 0U), /*!< IRC40K stabilization interrupt flag */ + RCU_INT_FLAG_LXTALSTB = RCU_REGIDX_BIT(INT_REG_OFFSET, 1U), /*!< LXTAL stabilization interrupt flag */ + RCU_INT_FLAG_IRC8MSTB = RCU_REGIDX_BIT(INT_REG_OFFSET, 2U), /*!< IRC8M stabilization interrupt flag */ + RCU_INT_FLAG_HXTALSTB = RCU_REGIDX_BIT(INT_REG_OFFSET, 3U), /*!< HXTAL stabilization interrupt flag */ + RCU_INT_FLAG_PLLSTB = RCU_REGIDX_BIT(INT_REG_OFFSET, 4U), /*!< PLL stabilization interrupt flag */ +#ifdef GD32F30X_CL + RCU_INT_FLAG_PLL1STB = RCU_REGIDX_BIT(INT_REG_OFFSET, 5U), /*!< PLL1 stabilization interrupt flag */ + RCU_INT_FLAG_PLL2STB = RCU_REGIDX_BIT(INT_REG_OFFSET, 6U), /*!< PLL2 stabilization interrupt flag */ +#endif /* GD32F30X_CL */ + RCU_INT_FLAG_CKM = RCU_REGIDX_BIT(INT_REG_OFFSET, 7U), /*!< HXTAL clock stuck interrupt flag */ + RCU_INT_FLAG_IRC48MSTB = RCU_REGIDX_BIT(ADDINT_REG_OFFSET, 6U), /*!< IRC48M stabilization interrupt flag */ +}rcu_int_flag_enum; + +/* clock stabilization and stuck interrupt flags clear */ +typedef enum +{ + RCU_INT_FLAG_IRC40KSTB_CLR = RCU_REGIDX_BIT(INT_REG_OFFSET, 16U), /*!< IRC40K stabilization interrupt flags clear */ + RCU_INT_FLAG_LXTALSTB_CLR = RCU_REGIDX_BIT(INT_REG_OFFSET, 17U), /*!< LXTAL stabilization interrupt flags clear */ + RCU_INT_FLAG_IRC8MSTB_CLR = RCU_REGIDX_BIT(INT_REG_OFFSET, 18U), /*!< IRC8M stabilization interrupt flags clear */ + RCU_INT_FLAG_HXTALSTB_CLR = RCU_REGIDX_BIT(INT_REG_OFFSET, 19U), /*!< HXTAL stabilization interrupt flags clear */ + RCU_INT_FLAG_PLLSTB_CLR = RCU_REGIDX_BIT(INT_REG_OFFSET, 20U), /*!< PLL stabilization interrupt flags clear */ +#ifdef GD32F30X_CL + RCU_INT_FLAG_PLL1STB_CLR = RCU_REGIDX_BIT(INT_REG_OFFSET, 21U), /*!< PLL1 stabilization interrupt flags clear */ + RCU_INT_FLAG_PLL2STB_CLR = RCU_REGIDX_BIT(INT_REG_OFFSET, 22U), /*!< PLL2 stabilization interrupt flags clear */ +#endif /* GD32F30X_CL */ + RCU_INT_FLAG_CKM_CLR = RCU_REGIDX_BIT(INT_REG_OFFSET, 23U), /*!< CKM interrupt flags clear */ + RCU_INT_FLAG_IRC48MSTB_CLR = RCU_REGIDX_BIT(ADDINT_REG_OFFSET, 22U), /*!< internal 48 MHz RC oscillator stabilization interrupt clear */ +}rcu_int_flag_clear_enum; + +/* clock stabilization interrupt enable or disable */ +typedef enum +{ + RCU_INT_IRC40KSTB = RCU_REGIDX_BIT(INT_REG_OFFSET, 8U), /*!< IRC40K stabilization interrupt */ + RCU_INT_LXTALSTB = RCU_REGIDX_BIT(INT_REG_OFFSET, 9U), /*!< LXTAL stabilization interrupt */ + RCU_INT_IRC8MSTB = RCU_REGIDX_BIT(INT_REG_OFFSET, 10U), /*!< IRC8M stabilization interrupt */ + RCU_INT_HXTALSTB = RCU_REGIDX_BIT(INT_REG_OFFSET, 11U), /*!< HXTAL stabilization interrupt */ + RCU_INT_PLLSTB = RCU_REGIDX_BIT(INT_REG_OFFSET, 12U), /*!< PLL stabilization interrupt */ +#ifdef GD32F30X_CL + RCU_INT_PLL1STB = RCU_REGIDX_BIT(INT_REG_OFFSET, 13U), /*!< PLL1 stabilization interrupt */ + RCU_INT_PLL2STB = RCU_REGIDX_BIT(INT_REG_OFFSET, 14U), /*!< PLL2 stabilization interrupt */ +#endif /* GD32F30X_CL */ + RCU_INT_IRC48MSTB = RCU_REGIDX_BIT(ADDINT_REG_OFFSET, 14U), /*!< internal 48 MHz RC oscillator stabilization interrupt */ +}rcu_int_enum; + +/* oscillator types */ +typedef enum +{ + RCU_HXTAL = RCU_REGIDX_BIT(CTL_REG_OFFSET, 16U), /*!< HXTAL */ + RCU_LXTAL = RCU_REGIDX_BIT(BDCTL_REG_OFFSET, 0U), /*!< LXTAL */ + RCU_IRC8M = RCU_REGIDX_BIT(CTL_REG_OFFSET, 0U), /*!< IRC8M */ + RCU_IRC48M = RCU_REGIDX_BIT(ADDCTL_REG_OFFSET, 16U), /*!< IRC48M */ + RCU_IRC40K = RCU_REGIDX_BIT(RSTSCK_REG_OFFSET, 0U), /*!< IRC40K */ + RCU_PLL_CK = RCU_REGIDX_BIT(CTL_REG_OFFSET, 24U), /*!< PLL */ +#ifdef GD32F30X_CL + RCU_PLL1_CK = RCU_REGIDX_BIT(CTL_REG_OFFSET, 26U), /*!< PLL1 */ + RCU_PLL2_CK = RCU_REGIDX_BIT(CTL_REG_OFFSET, 28U), /*!< PLL2 */ +#endif /* GD32F30X_CL */ +}rcu_osci_type_enum; + +/* rcu clock frequency */ +typedef enum +{ + CK_SYS = 0, /*!< system clock */ + CK_AHB, /*!< AHB clock */ + CK_APB1, /*!< APB1 clock */ + CK_APB2, /*!< APB2 clock */ +}rcu_clock_freq_enum; + +/* RCU_CFG0 register bit define */ +/* system clock source select */ +#define CFG0_SCS(regval) (BITS(0,1) & ((uint32_t)(regval) << 0)) +#define RCU_CKSYSSRC_IRC8M CFG0_SCS(0) /*!< system clock source select IRC8M */ +#define RCU_CKSYSSRC_HXTAL CFG0_SCS(1) /*!< system clock source select HXTAL */ +#define RCU_CKSYSSRC_PLL CFG0_SCS(2) /*!< system clock source select PLL */ + +/* system clock source select status */ +#define CFG0_SCSS(regval) (BITS(2,3) & ((uint32_t)(regval) << 2)) +#define RCU_SCSS_IRC8M CFG0_SCSS(0) /*!< system clock source select IRC8M */ +#define RCU_SCSS_HXTAL CFG0_SCSS(1) /*!< system clock source select HXTAL */ +#define RCU_SCSS_PLL CFG0_SCSS(2) /*!< system clock source select PLLP */ + +/* AHB prescaler selection */ +#define CFG0_AHBPSC(regval) (BITS(4,7) & ((uint32_t)(regval) << 4)) +#define RCU_AHB_CKSYS_DIV1 CFG0_AHBPSC(0) /*!< AHB prescaler select CK_SYS */ +#define RCU_AHB_CKSYS_DIV2 CFG0_AHBPSC(8) /*!< AHB prescaler select CK_SYS/2 */ +#define RCU_AHB_CKSYS_DIV4 CFG0_AHBPSC(9) /*!< AHB prescaler select CK_SYS/4 */ +#define RCU_AHB_CKSYS_DIV8 CFG0_AHBPSC(10) /*!< AHB prescaler select CK_SYS/8 */ +#define RCU_AHB_CKSYS_DIV16 CFG0_AHBPSC(11) /*!< AHB prescaler select CK_SYS/16 */ +#define RCU_AHB_CKSYS_DIV64 CFG0_AHBPSC(12) /*!< AHB prescaler select CK_SYS/64 */ +#define RCU_AHB_CKSYS_DIV128 CFG0_AHBPSC(13) /*!< AHB prescaler select CK_SYS/128 */ +#define RCU_AHB_CKSYS_DIV256 CFG0_AHBPSC(14) /*!< AHB prescaler select CK_SYS/256 */ +#define RCU_AHB_CKSYS_DIV512 CFG0_AHBPSC(15) /*!< AHB prescaler select CK_SYS/512 */ + +/* APB1 prescaler selection */ +#define CFG0_APB1PSC(regval) (BITS(8,10) & ((uint32_t)(regval) << 8)) +#define RCU_APB1_CKAHB_DIV1 CFG0_APB1PSC(0) /*!< APB1 prescaler select CK_AHB */ +#define RCU_APB1_CKAHB_DIV2 CFG0_APB1PSC(4) /*!< APB1 prescaler select CK_AHB/2 */ +#define RCU_APB1_CKAHB_DIV4 CFG0_APB1PSC(5) /*!< APB1 prescaler select CK_AHB/4 */ +#define RCU_APB1_CKAHB_DIV8 CFG0_APB1PSC(6) /*!< APB1 prescaler select CK_AHB/8 */ +#define RCU_APB1_CKAHB_DIV16 CFG0_APB1PSC(7) /*!< APB1 prescaler select CK_AHB/16 */ + +/* APB2 prescaler selection */ +#define CFG0_APB2PSC(regval) (BITS(11,13) & ((uint32_t)(regval) << 11)) +#define RCU_APB2_CKAHB_DIV1 CFG0_APB2PSC(0) /*!< APB2 prescaler select CK_AHB */ +#define RCU_APB2_CKAHB_DIV2 CFG0_APB2PSC(4) /*!< APB2 prescaler select CK_AHB/2 */ +#define RCU_APB2_CKAHB_DIV4 CFG0_APB2PSC(5) /*!< APB2 prescaler select CK_AHB/4 */ +#define RCU_APB2_CKAHB_DIV8 CFG0_APB2PSC(6) /*!< APB2 prescaler select CK_AHB/8 */ +#define RCU_APB2_CKAHB_DIV16 CFG0_APB2PSC(7) /*!< APB2 prescaler select CK_AHB/16 */ + +/* ADC prescaler select */ +#define RCU_CKADC_CKAPB2_DIV2 ((uint32_t)0x00000000U) /*!< ADC prescaler select CK_APB2/2 */ +#define RCU_CKADC_CKAPB2_DIV4 ((uint32_t)0x00000001U) /*!< ADC prescaler select CK_APB2/4 */ +#define RCU_CKADC_CKAPB2_DIV6 ((uint32_t)0x00000002U) /*!< ADC prescaler select CK_APB2/6 */ +#define RCU_CKADC_CKAPB2_DIV8 ((uint32_t)0x00000003U) /*!< ADC prescaler select CK_APB2/8 */ +#define RCU_CKADC_CKAPB2_DIV12 ((uint32_t)0x00000005U) /*!< ADC prescaler select CK_APB2/12 */ +#define RCU_CKADC_CKAPB2_DIV16 ((uint32_t)0x00000007U) /*!< ADC prescaler select CK_APB2/16 */ +#define RCU_CKADC_CKAHB_DIV5 ((uint32_t)0x00000008U) /*!< ADC prescaler select CK_AHB/5 */ +#define RCU_CKADC_CKAHB_DIV6 ((uint32_t)0x00000009U) /*!< ADC prescaler select CK_AHB/6 */ +#define RCU_CKADC_CKAHB_DIV10 ((uint32_t)0x0000000AU) /*!< ADC prescaler select CK_AHB/10 */ +#define RCU_CKADC_CKAHB_DIV20 ((uint32_t)0x0000000BU) /*!< ADC prescaler select CK_AHB/20 */ + +/* PLL clock source selection */ +#define RCU_PLLSRC_IRC8M_DIV2 ((uint32_t)0x00000000U) /*!< IRC8M/2 clock selected as source clock of PLL */ +#define RCU_PLLSRC_HXTAL_IRC48M RCU_CFG0_PLLSEL /*!< HXTAL or IRC48M selected as source clock of PLL */ + +/* PLL clock multiplication factor */ +#define PLLMF_4 RCU_CFG0_PLLMF_4 /* bit 4 of PLLMF */ +#define PLLMF_5 RCU_CFG0_PLLMF_5 /* bit 5 of PLLMF */ +#define PLLMF_4_5 (PLLMF_4 | PLLMF_5) /* bit 4 and 5 of PLLMF */ + +#define CFG0_PLLMF(regval) (BITS(18,21) & ((uint32_t)(regval) << 18)) +#define RCU_PLL_MUL2 CFG0_PLLMF(0) /*!< PLL source clock multiply by 2 */ +#define RCU_PLL_MUL3 CFG0_PLLMF(1) /*!< PLL source clock multiply by 3 */ +#define RCU_PLL_MUL4 CFG0_PLLMF(2) /*!< PLL source clock multiply by 4 */ +#define RCU_PLL_MUL5 CFG0_PLLMF(3) /*!< PLL source clock multiply by 5 */ +#define RCU_PLL_MUL6 CFG0_PLLMF(4) /*!< PLL source clock multiply by 6 */ +#define RCU_PLL_MUL7 CFG0_PLLMF(5) /*!< PLL source clock multiply by 7 */ +#define RCU_PLL_MUL8 CFG0_PLLMF(6) /*!< PLL source clock multiply by 8 */ +#define RCU_PLL_MUL9 CFG0_PLLMF(7) /*!< PLL source clock multiply by 9 */ +#define RCU_PLL_MUL10 CFG0_PLLMF(8) /*!< PLL source clock multiply by 10 */ +#define RCU_PLL_MUL11 CFG0_PLLMF(9) /*!< PLL source clock multiply by 11 */ +#define RCU_PLL_MUL12 CFG0_PLLMF(10) /*!< PLL source clock multiply by 12 */ +#define RCU_PLL_MUL13 CFG0_PLLMF(11) /*!< PLL source clock multiply by 13 */ +#define RCU_PLL_MUL14 CFG0_PLLMF(12) /*!< PLL source clock multiply by 14 */ +#if(defined(GD32F30X_HD) || defined(GD32F30X_XD)) +#define RCU_PLL_MUL15 CFG0_PLLMF(13) /*!< PLL source clock multiply by 15 */ +#elif defined(GD32F30X_CL) +#define RCU_PLL_MUL6_5 CFG0_PLLMF(13) /*!< PLL source clock multiply by 6.5 */ +#endif /* GD32F30X_HD and GD32F30X_XD */ +#define RCU_PLL_MUL16 CFG0_PLLMF(14) /*!< PLL source clock multiply by 16 */ +#define RCU_PLL_MUL17 (PLLMF_4 | CFG0_PLLMF(0)) /*!< PLL source clock multiply by 17 */ +#define RCU_PLL_MUL18 (PLLMF_4 | CFG0_PLLMF(1)) /*!< PLL source clock multiply by 18 */ +#define RCU_PLL_MUL19 (PLLMF_4 | CFG0_PLLMF(2)) /*!< PLL source clock multiply by 19 */ +#define RCU_PLL_MUL20 (PLLMF_4 | CFG0_PLLMF(3)) /*!< PLL source clock multiply by 20 */ +#define RCU_PLL_MUL21 (PLLMF_4 | CFG0_PLLMF(4)) /*!< PLL source clock multiply by 21 */ +#define RCU_PLL_MUL22 (PLLMF_4 | CFG0_PLLMF(5)) /*!< PLL source clock multiply by 22 */ +#define RCU_PLL_MUL23 (PLLMF_4 | CFG0_PLLMF(6)) /*!< PLL source clock multiply by 23 */ +#define RCU_PLL_MUL24 (PLLMF_4 | CFG0_PLLMF(7)) /*!< PLL source clock multiply by 24 */ +#define RCU_PLL_MUL25 (PLLMF_4 | CFG0_PLLMF(8)) /*!< PLL source clock multiply by 25 */ +#define RCU_PLL_MUL26 (PLLMF_4 | CFG0_PLLMF(9)) /*!< PLL source clock multiply by 26 */ +#define RCU_PLL_MUL27 (PLLMF_4 | CFG0_PLLMF(10)) /*!< PLL source clock multiply by 27 */ +#define RCU_PLL_MUL28 (PLLMF_4 | CFG0_PLLMF(11)) /*!< PLL source clock multiply by 28 */ +#define RCU_PLL_MUL29 (PLLMF_4 | CFG0_PLLMF(12)) /*!< PLL source clock multiply by 29 */ +#define RCU_PLL_MUL30 (PLLMF_4 | CFG0_PLLMF(13)) /*!< PLL source clock multiply by 30 */ +#define RCU_PLL_MUL31 (PLLMF_4 | CFG0_PLLMF(14)) /*!< PLL source clock multiply by 31 */ +#define RCU_PLL_MUL32 (PLLMF_4 | CFG0_PLLMF(15)) /*!< PLL source clock multiply by 32 */ +#define RCU_PLL_MUL33 (PLLMF_5 | CFG0_PLLMF(0)) /*!< PLL source clock multiply by 33 */ +#define RCU_PLL_MUL34 (PLLMF_5 | CFG0_PLLMF(1)) /*!< PLL source clock multiply by 34 */ +#define RCU_PLL_MUL35 (PLLMF_5 | CFG0_PLLMF(2)) /*!< PLL source clock multiply by 35 */ +#define RCU_PLL_MUL36 (PLLMF_5 | CFG0_PLLMF(3)) /*!< PLL source clock multiply by 36 */ +#define RCU_PLL_MUL37 (PLLMF_5 | CFG0_PLLMF(4)) /*!< PLL source clock multiply by 37 */ +#define RCU_PLL_MUL38 (PLLMF_5 | CFG0_PLLMF(5)) /*!< PLL source clock multiply by 38 */ +#define RCU_PLL_MUL39 (PLLMF_5 | CFG0_PLLMF(6)) /*!< PLL source clock multiply by 39 */ +#define RCU_PLL_MUL40 (PLLMF_5 | CFG0_PLLMF(7)) /*!< PLL source clock multiply by 40 */ +#define RCU_PLL_MUL41 (PLLMF_5 | CFG0_PLLMF(8)) /*!< PLL source clock multiply by 41 */ +#define RCU_PLL_MUL42 (PLLMF_5 | CFG0_PLLMF(9)) /*!< PLL source clock multiply by 42 */ +#define RCU_PLL_MUL43 (PLLMF_5 | CFG0_PLLMF(10)) /*!< PLL source clock multiply by 43 */ +#define RCU_PLL_MUL44 (PLLMF_5 | CFG0_PLLMF(11)) /*!< PLL source clock multiply by 44 */ +#define RCU_PLL_MUL45 (PLLMF_5 | CFG0_PLLMF(12)) /*!< PLL source clock multiply by 45 */ +#define RCU_PLL_MUL46 (PLLMF_5 | CFG0_PLLMF(13)) /*!< PLL source clock multiply by 46 */ +#define RCU_PLL_MUL47 (PLLMF_5 | CFG0_PLLMF(14)) /*!< PLL source clock multiply by 47 */ +#define RCU_PLL_MUL48 (PLLMF_5 | CFG0_PLLMF(15)) /*!< PLL source clock multiply by 48 */ +#define RCU_PLL_MUL49 (PLLMF_4_5 | CFG0_PLLMF(0)) /*!< PLL source clock multiply by 49 */ +#define RCU_PLL_MUL50 (PLLMF_4_5 | CFG0_PLLMF(1)) /*!< PLL source clock multiply by 50 */ +#define RCU_PLL_MUL51 (PLLMF_4_5 | CFG0_PLLMF(2)) /*!< PLL source clock multiply by 51 */ +#define RCU_PLL_MUL52 (PLLMF_4_5 | CFG0_PLLMF(3)) /*!< PLL source clock multiply by 52 */ +#define RCU_PLL_MUL53 (PLLMF_4_5 | CFG0_PLLMF(4)) /*!< PLL source clock multiply by 53 */ +#define RCU_PLL_MUL54 (PLLMF_4_5 | CFG0_PLLMF(5)) /*!< PLL source clock multiply by 54 */ +#define RCU_PLL_MUL55 (PLLMF_4_5 | CFG0_PLLMF(6)) /*!< PLL source clock multiply by 55 */ +#define RCU_PLL_MUL56 (PLLMF_4_5 | CFG0_PLLMF(7)) /*!< PLL source clock multiply by 56 */ +#define RCU_PLL_MUL57 (PLLMF_4_5 | CFG0_PLLMF(8)) /*!< PLL source clock multiply by 57 */ +#define RCU_PLL_MUL58 (PLLMF_4_5 | CFG0_PLLMF(9)) /*!< PLL source clock multiply by 58 */ +#define RCU_PLL_MUL59 (PLLMF_4_5 | CFG0_PLLMF(10)) /*!< PLL source clock multiply by 59 */ +#define RCU_PLL_MUL60 (PLLMF_4_5 | CFG0_PLLMF(11)) /*!< PLL source clock multiply by 60 */ +#define RCU_PLL_MUL61 (PLLMF_4_5 | CFG0_PLLMF(12)) /*!< PLL source clock multiply by 61 */ +#define RCU_PLL_MUL62 (PLLMF_4_5 | CFG0_PLLMF(13)) /*!< PLL source clock multiply by 62 */ +#define RCU_PLL_MUL63 (PLLMF_4_5 | CFG0_PLLMF(14)) /*!< PLL source clock multiply by 63 */ + +#if(defined(GD32F30X_HD) || defined(GD32F30X_XD)) +#define USBPSC_2 RCU_CFG0_USBDPSC_2 +#elif defined(GD32F30X_CL) +#define USBPSC_2 RCU_CFG0_USBFSPSC_2 +#endif /* GD32F30X_HD and GD32F30X_XD */ + +/* USBD/USBFS prescaler select */ +#define CFG0_USBPSC(regval) (BITS(22,23) & ((uint32_t)(regval) << 22)) +#define RCU_CKUSB_CKPLL_DIV1_5 CFG0_USBPSC(0) /*!< USBD/USBFS prescaler select CK_PLL/1.5 */ +#define RCU_CKUSB_CKPLL_DIV1 CFG0_USBPSC(1) /*!< USBD/USBFS prescaler select CK_PLL/1 */ +#define RCU_CKUSB_CKPLL_DIV2_5 CFG0_USBPSC(2) /*!< USBD/USBFS prescaler select CK_PLL/2.5 */ +#define RCU_CKUSB_CKPLL_DIV2 CFG0_USBPSC(3) /*!< USBD/USBFS prescaler select CK_PLL/2 */ +#define RCU_CKUSB_CKPLL_DIV3 (USBPSC_2 |CFG0_USBPSC(0)) /*!< USBD/USBFS prescaler select CK_PLL/3 */ +#define RCU_CKUSB_CKPLL_DIV3_5 (USBPSC_2 |CFG0_USBPSC(1)) /*!< USBD/USBFS prescaler select CK_PLL/3.5 */ +#define RCU_CKUSB_CKPLL_DIV4 (USBPSC_2 |CFG0_USBPSC(2)) /*!< USBD/USBFS prescaler select CK_PLL/4 */ + +/* CKOUT0 Clock source selection */ +#define CFG0_CKOUT0SEL(regval) (BITS(24,27) & ((uint32_t)(regval) << 24)) +#define RCU_CKOUT0SRC_NONE CFG0_CKOUT0SEL(0) /*!< no clock selected */ +#define RCU_CKOUT0SRC_CKSYS CFG0_CKOUT0SEL(4) /*!< system clock selected */ +#define RCU_CKOUT0SRC_IRC8M CFG0_CKOUT0SEL(5) /*!< internal 8M RC oscillator clock selected */ +#define RCU_CKOUT0SRC_HXTAL CFG0_CKOUT0SEL(6) /*!< high speed crystal oscillator clock (HXTAL) selected */ +#define RCU_CKOUT0SRC_CKPLL_DIV2 CFG0_CKOUT0SEL(7) /*!< CK_PLL/2 clock selected */ +#ifdef GD32F30X_CL +#define RCU_CKOUT0SRC_CKPLL1 CFG0_CKOUT0SEL(8) /*!< CK_PLL1 clock selected */ +#define RCU_CKOUT0SRC_CKPLL2_DIV2 CFG0_CKOUT0SEL(9) /*!< CK_PLL2/2 clock selected */ +#define RCU_CKOUT0SRC_EXT1 CFG0_CKOUT0SEL(10) /*!< EXT1 selected, to provide the external clock for ENET */ +#define RCU_CKOUT0SRC_CKPLL2 CFG0_CKOUT0SEL(11) /*!< CK_PLL2 clock selected */ +#endif /* GD32F30X_CL */ + +/* LXTAL drive capability */ +#define BDCTL_LXTALDRI(regval) (BITS(3,4) & ((uint32_t)(regval) << 3)) +#define RCU_LXTAL_LOWDRI BDCTL_LXTALDRI(0) /*!< lower driving capability */ +#define RCU_LXTAL_MED_LOWDRI BDCTL_LXTALDRI(1) /*!< medium low driving capability */ +#define RCU_LXTAL_MED_HIGHDRI BDCTL_LXTALDRI(2) /*!< medium high driving capability */ +#define RCU_LXTAL_HIGHDRI BDCTL_LXTALDRI(3) /*!< higher driving capability */ + +/* RTC clock entry selection */ +#define BDCTL_RTCSRC(regval) (BITS(8,9) & ((uint32_t)(regval) << 8)) +#define RCU_RTCSRC_NONE BDCTL_RTCSRC(0) /*!< no clock selected */ +#define RCU_RTCSRC_LXTAL BDCTL_RTCSRC(1) /*!< RTC source clock select LXTAL */ +#define RCU_RTCSRC_IRC40K BDCTL_RTCSRC(2) /*!< RTC source clock select IRC40K */ +#define RCU_RTCSRC_HXTAL_DIV_128 BDCTL_RTCSRC(3) /*!< RTC source clock select HXTAL/128 */ + +/* PREDV0 division factor */ +#define CFG1_PREDV0(regval) (BITS(0,3) & ((uint32_t)(regval) << 0)) +#define RCU_PREDV0_DIV1 CFG1_PREDV0(0) /*!< PREDV0 input source clock not divided */ +#define RCU_PREDV0_DIV2 CFG1_PREDV0(1) /*!< PREDV0 input source clock divided by 2 */ +#define RCU_PREDV0_DIV3 CFG1_PREDV0(2) /*!< PREDV0 input source clock divided by 3 */ +#define RCU_PREDV0_DIV4 CFG1_PREDV0(3) /*!< PREDV0 input source clock divided by 4 */ +#define RCU_PREDV0_DIV5 CFG1_PREDV0(4) /*!< PREDV0 input source clock divided by 5 */ +#define RCU_PREDV0_DIV6 CFG1_PREDV0(5) /*!< PREDV0 input source clock divided by 6 */ +#define RCU_PREDV0_DIV7 CFG1_PREDV0(6) /*!< PREDV0 input source clock divided by 7 */ +#define RCU_PREDV0_DIV8 CFG1_PREDV0(7) /*!< PREDV0 input source clock divided by 8 */ +#define RCU_PREDV0_DIV9 CFG1_PREDV0(8) /*!< PREDV0 input source clock divided by 9 */ +#define RCU_PREDV0_DIV10 CFG1_PREDV0(9) /*!< PREDV0 input source clock divided by 10 */ +#define RCU_PREDV0_DIV11 CFG1_PREDV0(10) /*!< PREDV0 input source clock divided by 11 */ +#define RCU_PREDV0_DIV12 CFG1_PREDV0(11) /*!< PREDV0 input source clock divided by 12 */ +#define RCU_PREDV0_DIV13 CFG1_PREDV0(12) /*!< PREDV0 input source clock divided by 13 */ +#define RCU_PREDV0_DIV14 CFG1_PREDV0(13) /*!< PREDV0 input source clock divided by 14 */ +#define RCU_PREDV0_DIV15 CFG1_PREDV0(14) /*!< PREDV0 input source clock divided by 15 */ +#define RCU_PREDV0_DIV16 CFG1_PREDV0(15) /*!< PREDV0 input source clock divided by 16 */ + +/* PREDV1 division factor */ +#define CFG1_PREDV1(regval) (BITS(4,7) & ((uint32_t)(regval) << 4)) +#define RCU_PREDV1_DIV1 CFG1_PREDV1(0) /*!< PREDV1 input source clock not divided */ +#define RCU_PREDV1_DIV2 CFG1_PREDV1(1) /*!< PREDV1 input source clock divided by 2 */ +#define RCU_PREDV1_DIV3 CFG1_PREDV1(2) /*!< PREDV1 input source clock divided by 3 */ +#define RCU_PREDV1_DIV4 CFG1_PREDV1(3) /*!< PREDV1 input source clock divided by 4 */ +#define RCU_PREDV1_DIV5 CFG1_PREDV1(4) /*!< PREDV1 input source clock divided by 5 */ +#define RCU_PREDV1_DIV6 CFG1_PREDV1(5) /*!< PREDV1 input source clock divided by 6 */ +#define RCU_PREDV1_DIV7 CFG1_PREDV1(6) /*!< PREDV1 input source clock divided by 7 */ +#define RCU_PREDV1_DIV8 CFG1_PREDV1(7) /*!< PREDV1 input source clock divided by 8 */ +#define RCU_PREDV1_DIV9 CFG1_PREDV1(8) /*!< PREDV1 input source clock divided by 9 */ +#define RCU_PREDV1_DIV10 CFG1_PREDV1(9) /*!< PREDV1 input source clock divided by 10 */ +#define RCU_PREDV1_DIV11 CFG1_PREDV1(10) /*!< PREDV1 input source clock divided by 11 */ +#define RCU_PREDV1_DIV12 CFG1_PREDV1(11) /*!< PREDV1 input source clock divided by 12 */ +#define RCU_PREDV1_DIV13 CFG1_PREDV1(12) /*!< PREDV1 input source clock divided by 13 */ +#define RCU_PREDV1_DIV14 CFG1_PREDV1(13) /*!< PREDV1 input source clock divided by 14 */ +#define RCU_PREDV1_DIV15 CFG1_PREDV1(14) /*!< PREDV1 input source clock divided by 15 */ +#define RCU_PREDV1_DIV16 CFG1_PREDV1(15) /*!< PREDV1 input source clock divided by 16 */ + +/* PLL1 clock multiplication factor */ +#define CFG1_PLL1MF(regval) (BITS(8,11) & ((uint32_t)(regval) << 8)) +#define RCU_PLL1_MUL8 CFG1_PLL1MF(6) /*!< PLL1 source clock multiply by 8 */ +#define RCU_PLL1_MUL9 CFG1_PLL1MF(7) /*!< PLL1 source clock multiply by 9 */ +#define RCU_PLL1_MUL10 CFG1_PLL1MF(8) /*!< PLL1 source clock multiply by 10 */ +#define RCU_PLL1_MUL11 CFG1_PLL1MF(9) /*!< PLL1 source clock multiply by 11 */ +#define RCU_PLL1_MUL12 CFG1_PLL1MF(10) /*!< PLL1 source clock multiply by 12 */ +#define RCU_PLL1_MUL13 CFG1_PLL1MF(11) /*!< PLL1 source clock multiply by 13 */ +#define RCU_PLL1_MUL14 CFG1_PLL1MF(12) /*!< PLL1 source clock multiply by 14 */ +#define RCU_PLL1_MUL15 CFG1_PLL1MF(13) /*!< PLL1 source clock multiply by 15 */ +#define RCU_PLL1_MUL16 CFG1_PLL1MF(14) /*!< PLL1 source clock multiply by 16 */ +#define RCU_PLL1_MUL20 CFG1_PLL1MF(15) /*!< PLL1 source clock multiply by 20 */ + +/* PLL2 clock multiplication factor */ +#define PLL2MF_4 RCU_CFG1_PLL2MF_4 /* bit 4 of PLL2MF */ + +#define CFG1_PLL2MF(regval) (BITS(12,15) & ((uint32_t)(regval) << 12)) +#define RCU_PLL2_MUL8 CFG1_PLL2MF(6) /*!< PLL2 source clock multiply by 8 */ +#define RCU_PLL2_MUL9 CFG1_PLL2MF(7) /*!< PLL2 source clock multiply by 9 */ +#define RCU_PLL2_MUL10 CFG1_PLL2MF(8) /*!< PLL2 source clock multiply by 10 */ +#define RCU_PLL2_MUL11 CFG1_PLL2MF(9) /*!< PLL2 source clock multiply by 11 */ +#define RCU_PLL2_MUL12 CFG1_PLL2MF(10) /*!< PLL2 source clock multiply by 12 */ +#define RCU_PLL2_MUL13 CFG1_PLL2MF(11) /*!< PLL2 source clock multiply by 13 */ +#define RCU_PLL2_MUL14 CFG1_PLL2MF(12) /*!< PLL2 source clock multiply by 14 */ +#define RCU_PLL2_MUL15 CFG1_PLL2MF(13) /*!< PLL2 source clock multiply by 15 */ +#define RCU_PLL2_MUL16 CFG1_PLL2MF(14) /*!< PLL2 source clock multiply by 16 */ +#define RCU_PLL2_MUL20 CFG1_PLL2MF(15) /*!< PLL2 source clock multiply by 20 */ +#define RCU_PLL2_MUL18 (PLL2MF_4 | CFG1_PLL2MF(0)) /*!< PLL2 source clock multiply by 18 */ +#define RCU_PLL2_MUL19 (PLL2MF_4 | CFG1_PLL2MF(1)) /*!< PLL2 source clock multiply by 19 */ +#define RCU_PLL2_MUL21 (PLL2MF_4 | CFG1_PLL2MF(3)) /*!< PLL2 source clock multiply by 21 */ +#define RCU_PLL2_MUL22 (PLL2MF_4 | CFG1_PLL2MF(4)) /*!< PLL2 source clock multiply by 22 */ +#define RCU_PLL2_MUL23 (PLL2MF_4 | CFG1_PLL2MF(5)) /*!< PLL2 source clock multiply by 23 */ +#define RCU_PLL2_MUL24 (PLL2MF_4 | CFG1_PLL2MF(6)) /*!< PLL2 source clock multiply by 24 */ +#define RCU_PLL2_MUL25 (PLL2MF_4 | CFG1_PLL2MF(7)) /*!< PLL2 source clock multiply by 25 */ +#define RCU_PLL2_MUL26 (PLL2MF_4 | CFG1_PLL2MF(8)) /*!< PLL2 source clock multiply by 26 */ +#define RCU_PLL2_MUL27 (PLL2MF_4 | CFG1_PLL2MF(9)) /*!< PLL2 source clock multiply by 27 */ +#define RCU_PLL2_MUL28 (PLL2MF_4 | CFG1_PLL2MF(10)) /*!< PLL2 source clock multiply by 28 */ +#define RCU_PLL2_MUL29 (PLL2MF_4 | CFG1_PLL2MF(11)) /*!< PLL2 source clock multiply by 29 */ +#define RCU_PLL2_MUL30 (PLL2MF_4 | CFG1_PLL2MF(12)) /*!< PLL2 source clock multiply by 30 */ +#define RCU_PLL2_MUL31 (PLL2MF_4 | CFG1_PLL2MF(13)) /*!< PLL2 source clock multiply by 31 */ +#define RCU_PLL2_MUL32 (PLL2MF_4 | CFG1_PLL2MF(14)) /*!< PLL2 source clock multiply by 32 */ +#define RCU_PLL2_MUL40 (PLL2MF_4 | CFG1_PLL2MF(15)) /*!< PLL2 source clock multiply by 40 */ + +#ifdef GD32F30X_CL +/* PREDV0 input clock source selection */ +#define RCU_PREDV0SRC_HXTAL_IRC48M ((uint32_t)0x00000000U) /*!< HXTAL or IRC48M selected as PREDV0 input source clock */ +#define RCU_PREDV0SRC_CKPLL1 RCU_CFG1_PREDV0SEL /*!< CK_PLL1 selected as PREDV0 input source clock */ + +/* I2S1 clock source selection */ +#define RCU_I2S1SRC_CKSYS ((uint32_t)0x00000000U) /*!< system clock selected as I2S1 source clock */ +#define RCU_I2S1SRC_CKPLL2_MUL2 RCU_CFG1_I2S1SEL /*!< (CK_PLL2 x 2) selected as I2S1 source clock */ + +/* I2S2 clock source selection */ +#define RCU_I2S2SRC_CKSYS ((uint32_t)0x00000000U) /*!< system clock selected as I2S2 source clock */ +#define RCU_I2S2SRC_CKPLL2_MUL2 RCU_CFG1_I2S2SEL /*!< (CK_PLL2 x 2) selected as I2S2 source clock */ +#endif /* GD32F30X_CL */ + +/* PLL input clock source selection */ +#define RCU_PLLPRESRC_HXTAL ((uint32_t)0x00000000U) /*!< HXTAL selected as PLL source clock */ +#define RCU_PLLPRESRC_IRC48M RCU_CFG1_PLLPRESEL /*!< CK_PLL selected as PREDV0 input source clock */ + +/* deep-sleep mode voltage */ +#define DSV_DSLPVS(regval) (BITS(0,2) & ((uint32_t)(regval) << 0)) +#define RCU_DEEPSLEEP_V_1_0 DSV_DSLPVS(0) /*!< core voltage is 1.0V in deep-sleep mode */ +#define RCU_DEEPSLEEP_V_0_9 DSV_DSLPVS(1) /*!< core voltage is 0.9V in deep-sleep mode */ +#define RCU_DEEPSLEEP_V_0_8 DSV_DSLPVS(2) /*!< core voltage is 0.8V in deep-sleep mode */ +#define RCU_DEEPSLEEP_V_0_7 DSV_DSLPVS(3) /*!< core voltage is 0.7V in deep-sleep mode */ + +/* 48MHz clock selection */ +#define RCU_CK48MSRC_CKPLL ((uint32_t)0x00000000U) /*!< use CK_PLL clock */ +#define RCU_CK48MSRC_IRC48M RCU_ADDCTL_CK48MSEL /*!< select IRC48M clock */ + +/* function declarations */ +/* deinitialize the RCU */ +void rcu_deinit(void); +/* enable the peripherals clock */ +void rcu_periph_clock_enable(rcu_periph_enum periph); +/* disable the peripherals clock */ +void rcu_periph_clock_disable(rcu_periph_enum periph); +/* enable the peripherals clock when sleep mode */ +void rcu_periph_clock_sleep_enable(rcu_periph_sleep_enum periph); +/* disable the peripherals clock when sleep mode */ +void rcu_periph_clock_sleep_disable(rcu_periph_sleep_enum periph); +/* reset the peripherals */ +void rcu_periph_reset_enable(rcu_periph_reset_enum periph_reset); +/* disable reset the peripheral */ +void rcu_periph_reset_disable(rcu_periph_reset_enum periph_reset); +/* reset the BKP domain */ +void rcu_bkp_reset_enable(void); +/* disable the BKP domain reset */ +void rcu_bkp_reset_disable(void); + +/* configure the system clock source */ +void rcu_system_clock_source_config(uint32_t ck_sys); +/* get the system clock source */ +uint32_t rcu_system_clock_source_get(void); +/* configure the AHB prescaler selection */ +void rcu_ahb_clock_config(uint32_t ck_ahb); +/* configure the APB1 prescaler selection */ +void rcu_apb1_clock_config(uint32_t ck_apb1); +/* configure the APB2 prescaler selection */ +void rcu_apb2_clock_config(uint32_t ck_apb2); +/* configure the CK_OUT0 clock source and divider */ +void rcu_ckout0_config(uint32_t ckout0_src); +/* configure the PLL clock source selection and PLL multiply factor */ +void rcu_pll_config(uint32_t pll_src, uint32_t pll_mul); +/* configure the PLL clock source preselection */ +void rcu_pllpresel_config(uint32_t pll_presel); +#if(defined(GD32F30X_HD) || defined(GD32F30X_XD)) +/* configure the PREDV0 division factor and clock source */ +void rcu_predv0_config(uint32_t predv0_div); +#elif defined(GD32F30X_CL) +/* configure the PREDV0 division factor and clock source */ +void rcu_predv0_config(uint32_t predv0_source, uint32_t predv0_div); +/* configure the PREDV1 division factor */ +void rcu_predv1_config(uint32_t predv1_div); +/* configure the PLL1 clock */ +void rcu_pll1_config(uint32_t pll_mul); +/* configure the PLL2 clock */ +void rcu_pll2_config(uint32_t pll_mul); +#endif /* GD32F30X_HD and GD32F30X_XD */ + +/* configure the ADC division factor */ +void rcu_adc_clock_config(uint32_t adc_psc); +/* configure the USBD/USBFS prescaler factor */ +void rcu_usb_clock_config(uint32_t usb_psc); +/* configure the RTC clock source selection */ +void rcu_rtc_clock_config(uint32_t rtc_clock_source); +#ifdef GD32F30X_CL +/* configure the I2S1 clock source selection */ +void rcu_i2s1_clock_config(uint32_t i2s_clock_source); +/* configure the I2S2 clock source selection */ +void rcu_i2s2_clock_config(uint32_t i2s_clock_source); +#endif /* GD32F30X_CL */ +/* configure the CK48M clock selection */ +void rcu_ck48m_clock_config(uint32_t ck48m_clock_source); + + +/* get the clock stabilization and periphral reset flags */ +FlagStatus rcu_flag_get(rcu_flag_enum flag); +/* clear the reset flag */ +void rcu_all_reset_flag_clear(void); +/* get the clock stabilization interrupt and ckm flags */ +FlagStatus rcu_interrupt_flag_get(rcu_int_flag_enum int_flag); +/* clear the interrupt flags */ +void rcu_interrupt_flag_clear(rcu_int_flag_clear_enum int_flag); +/* enable the stabilization interrupt */ +void rcu_interrupt_enable(rcu_int_enum interrupt); +/* disable the stabilization interrupt */ +void rcu_interrupt_disable(rcu_int_enum interrupt); + +/* configure the LXTAL drive capability */ +void rcu_lxtal_drive_capability_config(uint32_t lxtal_dricap); +/* wait for oscillator stabilization flags is SET or oscillator startup is timeout */ +ErrStatus rcu_osci_stab_wait(rcu_osci_type_enum osci); +/* turn on the oscillator */ +void rcu_osci_on(rcu_osci_type_enum osci); +/* turn off the oscillator */ +void rcu_osci_off(rcu_osci_type_enum osci); +/* enable the oscillator bypass mode, HXTALEN or LXTALEN must be reset before it */ +void rcu_osci_bypass_mode_enable(rcu_osci_type_enum osci); +/* disable the oscillator bypass mode, HXTALEN or LXTALEN must be reset before it */ +void rcu_osci_bypass_mode_disable(rcu_osci_type_enum osci); +/* enable the HXTAL clock monitor */ +void rcu_hxtal_clock_monitor_enable(void); +/* disable the HXTAL clock monitor */ +void rcu_hxtal_clock_monitor_disable(void); + +/* set the IRC8M adjust value */ +void rcu_irc8m_adjust_value_set(uint32_t irc8m_adjval); + +/* set the deep sleep mode voltage */ +void rcu_deepsleep_voltage_set(uint32_t dsvol); + +/* get the system clock, bus and peripheral clock frequency */ +uint32_t rcu_clock_freq_get(rcu_clock_freq_enum clock); + +#endif /* GD32F30X_RCU_H */ diff --git a/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_standard_peripheral/Include/gd32f30x_rtc.h b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_standard_peripheral/Include/gd32f30x_rtc.h new file mode 100644 index 0000000000..3aace0d0c3 --- /dev/null +++ b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_standard_peripheral/Include/gd32f30x_rtc.h @@ -0,0 +1,138 @@ +/*! + \file gd32f30x_rtc.h + \brief definitions for the RTC + + \version 2017-02-10, V1.0.0, firmware for GD32F30x + \version 2018-10-10, V1.1.0, firmware for GD32F30x + \version 2018-12-25, V2.0.0, firmware for GD32F30x + \version 2020-09-30, V2.1.0, firmware for GD32F30x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + + +#ifndef GD32F30X_RTC_H +#define GD32F30X_RTC_H + +#include "gd32f30x.h" + +/* RTC definitions */ +#define RTC RTC_BASE + +/* registers definitions */ +#define RTC_INTEN REG32(RTC + 0x00U) /*!< interrupt enable register */ +#define RTC_CTL REG32(RTC + 0x04U) /*!< control register */ +#define RTC_PSCH REG32(RTC + 0x08U) /*!< prescaler high register */ +#define RTC_PSCL REG32(RTC + 0x0CU) /*!< prescaler low register */ +#define RTC_DIVH REG32(RTC + 0x10U) /*!< divider high register */ +#define RTC_DIVL REG32(RTC + 0x14U) /*!< divider low register */ +#define RTC_CNTH REG32(RTC + 0x18U) /*!< counter high register */ +#define RTC_CNTL REG32(RTC + 0x1CU) /*!< counter low register */ +#define RTC_ALRMH REG32(RTC + 0x20U) /*!< alarm high register */ +#define RTC_ALRML REG32(RTC + 0x24U) /*!< alarm low register */ + +/* bits definitions */ +/* RTC_INTEN */ +#define RTC_INTEN_SCIE BIT(0) /*!< second interrupt enable */ +#define RTC_INTEN_ALRMIE BIT(1) /*!< alarm interrupt enable */ +#define RTC_INTEN_OVIE BIT(2) /*!< overflow interrupt enable */ + +/* RTC_CTL */ +#define RTC_CTL_SCIF BIT(0) /*!< second interrupt flag */ +#define RTC_CTL_ALRMIF BIT(1) /*!< alarm interrupt flag */ +#define RTC_CTL_OVIF BIT(2) /*!< overflow interrupt flag */ +#define RTC_CTL_RSYNF BIT(3) /*!< registers synchronized flag */ +#define RTC_CTL_CMF BIT(4) /*!< configuration mode flag */ +#define RTC_CTL_LWOFF BIT(5) /*!< last write operation finished flag */ + +/* RTC_PSC */ +#define RTC_PSCH_PSC BITS(0, 3) /*!< prescaler high value */ +#define RTC_PSCL_PSC BITS(0, 15) /*!< prescaler low value */ + +/* RTC_DIV */ +#define RTC_DIVH_DIV BITS(0, 3) /*!< divider high value */ +#define RTC_DIVL_DIV BITS(0, 15) /*!< divider low value */ + +/* RTC_CNT */ +#define RTC_CNTH_CNT BITS(0, 15) /*!< counter high value */ +#define RTC_CNTL_CNT BITS(0, 15) /*!< counter low value */ + +/* RTC_ALRM */ +#define RTC_ALRMH_ALRM BITS(0, 15) /*!< alarm high value */ +#define RTC_ALRML_ALRM BITS(0, 15) /*!< alarm low value */ + +/* constants definitions */ +#define RTC_HIGH_VALUE 0x000F0000U /*!< RTC high value */ +#define RTC_LOW_VALUE 0x0000FFFFU /*!< RTC low value */ + +/* RTC interrupt enable or disable definitions */ +#define RTC_INT_SECOND RTC_INTEN_SCIE /*!< second interrupt enable */ +#define RTC_INT_ALARM RTC_INTEN_ALRMIE /*!< alarm interrupt enable */ +#define RTC_INT_OVERFLOW RTC_INTEN_OVIE /*!< overflow interrupt enable */ + +/* RTC flag definitions */ +#define RTC_FLAG_SECOND RTC_CTL_SCIF /*!< second interrupt flag */ +#define RTC_FLAG_ALARM RTC_CTL_ALRMIF /*!< alarm interrupt flag */ +#define RTC_FLAG_OVERFLOW RTC_CTL_OVIF /*!< overflow interrupt flag */ +#define RTC_FLAG_RSYN RTC_CTL_RSYNF /*!< registers synchronized flag */ +#define RTC_FLAG_LWOF RTC_CTL_LWOFF /*!< last write operation finished flag */ + +/* function declarations */ +/* enable RTC interrupt */ +void rtc_interrupt_enable(uint32_t interrupt); +/* disable RTC interrupt */ +void rtc_interrupt_disable(uint32_t interrupt); + +/* enter RTC configuration mode */ +void rtc_configuration_mode_enter(void); +/* exit RTC configuration mode */ +void rtc_configuration_mode_exit(void); + +/* wait RTC last write operation finished flag set */ +void rtc_lwoff_wait(void); +/* wait RTC registers synchronized flag set */ +void rtc_register_sync_wait(void); + +/* get RTC counter value */ +uint32_t rtc_counter_get(void); +/* set RTC counter value */ +void rtc_counter_set(uint32_t cnt); + +/* set RTC prescaler value */ +void rtc_prescaler_set(uint32_t psc); +/* set RTC alarm value */ +void rtc_alarm_config(uint32_t alarm); +/* get RTC divider value */ +uint32_t rtc_divider_get(void); + +/* get RTC flag status */ +FlagStatus rtc_flag_get(uint32_t flag); +/* clear RTC flag status */ +void rtc_flag_clear(uint32_t flag); + +#endif /* GD32F30X_RTC_H */ diff --git a/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_standard_peripheral/Include/gd32f30x_sdio.h b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_standard_peripheral/Include/gd32f30x_sdio.h new file mode 100644 index 0000000000..6555fc1039 --- /dev/null +++ b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_standard_peripheral/Include/gd32f30x_sdio.h @@ -0,0 +1,434 @@ +/*! + \file gd32f30x_sdio.h + \brief definitions for the SDIO + + \version 2017-02-10, V1.0.0, firmware for GD32F30x + \version 2018-10-10, V1.1.0, firmware for GD32F30x + \version 2018-12-25, V2.0.0, firmware for GD32F30x + \version 2020-09-30, V2.1.0, firmware for GD32F30x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef GD32F30X_SDIO_H +#define GD32F30X_SDIO_H + +#include "gd32f30x.h" + +/* SDIO definitions */ +#define SDIO SDIO_BASE + +/* registers definitions */ +#define SDIO_PWRCTL REG32(SDIO + 0x00U) /*!< SDIO power control register */ +#define SDIO_CLKCTL REG32(SDIO + 0x04U) /*!< SDIO clock control register */ +#define SDIO_CMDAGMT REG32(SDIO + 0x08U) /*!< SDIO command argument register */ +#define SDIO_CMDCTL REG32(SDIO + 0x0CU) /*!< SDIO command control register */ +#define SDIO_RSPCMDIDX REG32(SDIO + 0x10U) /*!< SDIO command index response register */ +#define SDIO_RESP0 REG32(SDIO + 0x14U) /*!< SDIO response register 0 */ +#define SDIO_RESP1 REG32(SDIO + 0x18U) /*!< SDIO response register 1 */ +#define SDIO_RESP2 REG32(SDIO + 0x1CU) /*!< SDIO response register 2 */ +#define SDIO_RESP3 REG32(SDIO + 0x20U) /*!< SDIO response register 3 */ +#define SDIO_DATATO REG32(SDIO + 0x24U) /*!< SDIO data timeout register */ +#define SDIO_DATALEN REG32(SDIO + 0x28U) /*!< SDIO data length register */ +#define SDIO_DATACTL REG32(SDIO + 0x2CU) /*!< SDIO data control register */ +#define SDIO_DATACNT REG32(SDIO + 0x30U) /*!< SDIO data counter register */ +#define SDIO_STAT REG32(SDIO + 0x34U) /*!< SDIO status register */ +#define SDIO_INTC REG32(SDIO + 0x38U) /*!< SDIO interrupt clear register */ +#define SDIO_INTEN REG32(SDIO + 0x3CU) /*!< SDIO interrupt enable register */ +#define SDIO_FIFOCNT REG32(SDIO + 0x48U) /*!< SDIO FIFO counter register */ +#define SDIO_FIFO REG32(SDIO + 0x80U) /*!< SDIO FIFO data register */ + +/* bits definitions */ +/* SDIO_PWRCTL */ +#define SDIO_PWRCTL_PWRCTL BITS(0,1) /*!< SDIO power control bits */ + +/* SDIO_CLKCTL */ +#define SDIO_CLKCTL_DIV BITS(0,7) /*!< clock division */ +#define SDIO_CLKCTL_CLKEN BIT(8) /*!< SDIO_CLK clock output enable bit */ +#define SDIO_CLKCTL_CLKPWRSAV BIT(9) /*!< SDIO_CLK clock dynamic switch on/off for power saving */ +#define SDIO_CLKCTL_CLKBYP BIT(10) /*!< clock bypass enable bit */ +#define SDIO_CLKCTL_BUSMODE BITS(11,12) /*!< SDIO card bus mode control bit */ +#define SDIO_CLKCTL_CLKEDGE BIT(13) /*!< SDIO_CLK clock edge selection bit */ +#define SDIO_CLKCTL_HWCLKEN BIT(14) /*!< hardware clock control enable bit */ +#define SDIO_CLKCTL_DIV8 BIT(31) /*!< MSB of clock division */ + +/* SDIO_CMDAGMT */ +#define SDIO_CMDAGMT_CMDAGMT BITS(0,31) /*!< SDIO card command argument */ + +/* SDIO_CMDCTL */ +#define SDIO_CMDCTL_CMDIDX BITS(0,5) /*!< command index */ +#define SDIO_CMDCTL_CMDRESP BITS(6,7) /*!< command response type bits */ +#define SDIO_CMDCTL_INTWAIT BIT(8) /*!< interrupt wait instead of timeout */ +#define SDIO_CMDCTL_WAITDEND BIT(9) /*!< wait for ends of data transfer */ +#define SDIO_CMDCTL_CSMEN BIT(10) /*!< command state machine(CSM) enable bit */ +#define SDIO_CMDCTL_SUSPEND BIT(11) /*!< SD I/O suspend command(SD I/O only) */ +#define SDIO_CMDCTL_ENCMDC BIT(12) /*!< CMD completion signal enabled (CE-ATA only) */ +#define SDIO_CMDCTL_NINTEN BIT(13) /*!< no CE-ATA interrupt (CE-ATA only) */ +#define SDIO_CMDCTL_ATAEN BIT(14) /*!< CE-ATA command enable(CE-ATA only) */ + +/* SDIO_DATATO */ +#define SDIO_DATATO_DATATO BITS(0,31) /*!< data timeout period */ + +/* SDIO_DATALEN */ +#define SDIO_DATALEN_DATALEN BITS(0,24) /*!< data transfer length */ + +/* SDIO_DATACTL */ +#define SDIO_DATACTL_DATAEN BIT(0) /*!< data transfer enabled bit */ +#define SDIO_DATACTL_DATADIR BIT(1) /*!< data transfer direction */ +#define SDIO_DATACTL_TRANSMOD BIT(2) /*!< data transfer mode */ +#define SDIO_DATACTL_DMAEN BIT(3) /*!< DMA enable bit */ +#define SDIO_DATACTL_BLKSZ BITS(4,7) /*!< data block size */ +#define SDIO_DATACTL_RWEN BIT(8) /*!< read wait mode enabled(SD I/O only) */ +#define SDIO_DATACTL_RWSTOP BIT(9) /*!< read wait stop(SD I/O only) */ +#define SDIO_DATACTL_RWTYPE BIT(10) /*!< read wait type(SD I/O only) */ +#define SDIO_DATACTL_IOEN BIT(11) /*!< SD I/O specific function enable(SD I/O only) */ + +/* SDIO_STAT */ +#define SDIO_STAT_CCRCERR BIT(0) /*!< command response received (CRC check failed) */ +#define SDIO_STAT_DTCRCERR BIT(1) /*!< data block sent/received (CRC check failed) */ +#define SDIO_STAT_CMDTMOUT BIT(2) /*!< command response timeout */ +#define SDIO_STAT_DTTMOUT BIT(3) /*!< data timeout */ +#define SDIO_STAT_TXURE BIT(4) /*!< transmit FIFO underrun error occurs */ +#define SDIO_STAT_RXORE BIT(5) /*!< received FIFO overrun error occurs */ +#define SDIO_STAT_CMDRECV BIT(6) /*!< command response received (CRC check passed) */ +#define SDIO_STAT_CMDSEND BIT(7) /*!< command sent (no response required) */ +#define SDIO_STAT_DTEND BIT(8) /*!< data end (data counter, SDIO_DATACNT, is zero) */ +#define SDIO_STAT_STBITE BIT(9) /*!< start bit error in the bus */ +#define SDIO_STAT_DTBLKEND BIT(10) /*!< data block sent/received (CRC check passed) */ +#define SDIO_STAT_CMDRUN BIT(11) /*!< command transmission in progress */ +#define SDIO_STAT_TXRUN BIT(12) /*!< data transmission in progress */ +#define SDIO_STAT_RXRUN BIT(13) /*!< data reception in progress */ +#define SDIO_STAT_TFH BIT(14) /*!< transmit FIFO is half empty: at least 8 words can be written into the FIFO */ +#define SDIO_STAT_RFH BIT(15) /*!< receive FIFO is half full: at least 8 words can be read in the FIFO */ +#define SDIO_STAT_TFF BIT(16) /*!< transmit FIFO is full */ +#define SDIO_STAT_RFF BIT(17) /*!< receive FIFO is full */ +#define SDIO_STAT_TFE BIT(18) /*!< transmit FIFO is empty */ +#define SDIO_STAT_RFE BIT(19) /*!< receive FIFO is empty */ +#define SDIO_STAT_TXDTVAL BIT(20) /*!< data is valid in transmit FIFO */ +#define SDIO_STAT_RXDTVAL BIT(21) /*!< data is valid in receive FIFO */ +#define SDIO_STAT_SDIOINT BIT(22) /*!< SD I/O interrupt received */ +#define SDIO_STAT_ATAEND BIT(23) /*!< CE-ATA command completion signal received (only for CMD61) */ + +/* SDIO_INTC */ +#define SDIO_INTC_CCRCERRC BIT(0) /*!< CCRCERR flag clear bit */ +#define SDIO_INTC_DTCRCERRC BIT(1) /*!< DTCRCERR flag clear bit */ +#define SDIO_INTC_CMDTMOUTC BIT(2) /*!< CMDTMOUT flag clear bit */ +#define SDIO_INTC_DTTMOUTC BIT(3) /*!< DTTMOUT flag clear bit */ +#define SDIO_INTC_TXUREC BIT(4) /*!< TXURE flag clear bit */ +#define SDIO_INTC_RXOREC BIT(5) /*!< RXORE flag clear bit */ +#define SDIO_INTC_CMDRECVC BIT(6) /*!< CMDRECV flag clear bit */ +#define SDIO_INTC_CMDSENDC BIT(7) /*!< CMDSEND flag clear bit */ +#define SDIO_INTC_DTENDC BIT(8) /*!< DTEND flag clear bit */ +#define SDIO_INTC_STBITEC BIT(9) /*!< STBITE flag clear bit */ +#define SDIO_INTC_DTBLKENDC BIT(10) /*!< DTBLKEND flag clear bit */ +#define SDIO_INTC_SDIOINTC BIT(22) /*!< SDIOINT flag clear bit */ +#define SDIO_INTC_ATAENDC BIT(23) /*!< ATAEND flag clear bit */ + +/* SDIO_INTEN */ +#define SDIO_INTEN_CCRCERRIE BIT(0) /*!< command response CRC fail interrupt enable */ +#define SDIO_INTEN_DTCRCERRIE BIT(1) /*!< data CRC fail interrupt enable */ +#define SDIO_INTEN_CMDTMOUTIE BIT(2) /*!< command response timeout interrupt enable */ +#define SDIO_INTEN_DTTMOUTIE BIT(3) /*!< data timeout interrupt enable */ +#define SDIO_INTEN_TXUREIE BIT(4) /*!< transmit FIFO underrun error interrupt enable */ +#define SDIO_INTEN_RXOREIE BIT(5) /*!< received FIFO overrun error interrupt enable */ +#define SDIO_INTEN_CMDRECVIE BIT(6) /*!< command response received interrupt enable */ +#define SDIO_INTEN_CMDSENDIE BIT(7) /*!< command sent interrupt enable */ +#define SDIO_INTEN_DTENDIE BIT(8) /*!< data end interrupt enable */ +#define SDIO_INTEN_STBITEIE BIT(9) /*!< start bit error interrupt enable */ +#define SDIO_INTEN_DTBLKENDIE BIT(10) /*!< data block end interrupt enable */ +#define SDIO_INTEN_CMDRUNIE BIT(11) /*!< command transmission interrupt enable */ +#define SDIO_INTEN_TXRUNIE BIT(12) /*!< data transmission interrupt enable */ +#define SDIO_INTEN_RXRUNIE BIT(13) /*!< data reception interrupt enable */ +#define SDIO_INTEN_TFHIE BIT(14) /*!< transmit FIFO half empty interrupt enable */ +#define SDIO_INTEN_RFHIE BIT(15) /*!< receive FIFO half full interrupt enable */ +#define SDIO_INTEN_TFFIE BIT(16) /*!< transmit FIFO full interrupt enable */ +#define SDIO_INTEN_RFFIE BIT(17) /*!< receive FIFO full interrupt enable */ +#define SDIO_INTEN_TFEIE BIT(18) /*!< transmit FIFO empty interrupt enable */ +#define SDIO_INTEN_RFEIE BIT(19) /*!< receive FIFO empty interrupt enable */ +#define SDIO_INTEN_TXDTVALIE BIT(20) /*!< data valid in transmit FIFO interrupt enable */ +#define SDIO_INTEN_RXDTVALIE BIT(21) /*!< data valid in receive FIFO interrupt enable */ +#define SDIO_INTEN_SDIOINTIE BIT(22) /*!< SD I/O interrupt received interrupt enable */ +#define SDIO_INTEN_ATAENDIE BIT(23) /*!< CE-ATA command completion signal received interrupt enable */ + +/* SDIO_FIFO */ +#define SDIO_FIFO_FIFODT BITS(0,31) /*!< receive FIFO data or transmit FIFO data */ + +/* constants definitions */ +/* SDIO flags */ +#define SDIO_FLAG_CCRCERR BIT(0) /*!< command response received (CRC check failed) flag */ +#define SDIO_FLAG_DTCRCERR BIT(1) /*!< data block sent/received (CRC check failed) flag */ +#define SDIO_FLAG_CMDTMOUT BIT(2) /*!< command response timeout flag */ +#define SDIO_FLAG_DTTMOUT BIT(3) /*!< data timeout flag */ +#define SDIO_FLAG_TXURE BIT(4) /*!< transmit FIFO underrun error occurs flag */ +#define SDIO_FLAG_RXORE BIT(5) /*!< received FIFO overrun error occurs flag */ +#define SDIO_FLAG_CMDRECV BIT(6) /*!< command response received (CRC check passed) flag */ +#define SDIO_FLAG_CMDSEND BIT(7) /*!< command sent (no response required) flag */ +#define SDIO_FLAG_DTEND BIT(8) /*!< data end (data counter, SDIO_DATACNT, is zero) flag */ +#define SDIO_FLAG_STBITE BIT(9) /*!< start bit error in the bus flag */ +#define SDIO_FLAG_DTBLKEND BIT(10) /*!< data block sent/received (CRC check passed) flag */ +#define SDIO_FLAG_CMDRUN BIT(11) /*!< command transmission in progress flag */ +#define SDIO_FLAG_TXRUN BIT(12) /*!< data transmission in progress flag */ +#define SDIO_FLAG_RXRUN BIT(13) /*!< data reception in progress flag */ +#define SDIO_FLAG_TFH BIT(14) /*!< transmit FIFO is half empty flag: at least 8 words can be written into the FIFO */ +#define SDIO_FLAG_RFH BIT(15) /*!< receive FIFO is half full flag: at least 8 words can be read in the FIFO */ +#define SDIO_FLAG_TFF BIT(16) /*!< transmit FIFO is full flag */ +#define SDIO_FLAG_RFF BIT(17) /*!< receive FIFO is full flag */ +#define SDIO_FLAG_TFE BIT(18) /*!< transmit FIFO is empty flag */ +#define SDIO_FLAG_RFE BIT(19) /*!< receive FIFO is empty flag */ +#define SDIO_FLAG_TXDTVAL BIT(20) /*!< data is valid in transmit FIFO flag */ +#define SDIO_FLAG_RXDTVAL BIT(21) /*!< data is valid in receive FIFO flag */ +#define SDIO_FLAG_SDIOINT BIT(22) /*!< SD I/O interrupt received flag */ +#define SDIO_FLAG_ATAEND BIT(23) /*!< CE-ATA command completion signal received (only for CMD61) flag */ + +/* SDIO interrupt enable or disable */ +#define SDIO_INT_CCRCERR BIT(0) /*!< SDIO CCRCERR interrupt */ +#define SDIO_INT_DTCRCERR BIT(1) /*!< SDIO DTCRCERR interrupt */ +#define SDIO_INT_CMDTMOUT BIT(2) /*!< SDIO CMDTMOUT interrupt */ +#define SDIO_INT_DTTMOUT BIT(3) /*!< SDIO DTTMOUT interrupt */ +#define SDIO_INT_TXURE BIT(4) /*!< SDIO TXURE interrupt */ +#define SDIO_INT_RXORE BIT(5) /*!< SDIO RXORE interrupt */ +#define SDIO_INT_CMDRECV BIT(6) /*!< SDIO CMDRECV interrupt */ +#define SDIO_INT_CMDSEND BIT(7) /*!< SDIO CMDSEND interrupt */ +#define SDIO_INT_DTEND BIT(8) /*!< SDIO DTEND interrupt */ +#define SDIO_INT_STBITE BIT(9) /*!< SDIO STBITE interrupt */ +#define SDIO_INT_DTBLKEND BIT(10) /*!< SDIO DTBLKEND interrupt */ +#define SDIO_INT_CMDRUN BIT(11) /*!< SDIO CMDRUN interrupt */ +#define SDIO_INT_TXRUN BIT(12) /*!< SDIO TXRUN interrupt */ +#define SDIO_INT_RXRUN BIT(13) /*!< SDIO RXRUN interrupt */ +#define SDIO_INT_TFH BIT(14) /*!< SDIO TFH interrupt */ +#define SDIO_INT_RFH BIT(15) /*!< SDIO RFH interrupt */ +#define SDIO_INT_TFF BIT(16) /*!< SDIO TFF interrupt */ +#define SDIO_INT_RFF BIT(17) /*!< SDIO RFF interrupt */ +#define SDIO_INT_TFE BIT(18) /*!< SDIO TFE interrupt */ +#define SDIO_INT_RFE BIT(19) /*!< SDIO RFE interrupt */ +#define SDIO_INT_TXDTVAL BIT(20) /*!< SDIO TXDTVAL interrupt */ +#define SDIO_INT_RXDTVAL BIT(21) /*!< SDIO RXDTVAL interrupt */ +#define SDIO_INT_SDIOINT BIT(22) /*!< SDIO SDIOINT interrupt */ +#define SDIO_INT_ATAEND BIT(23) /*!< SDIO ATAEND interrupt */ + +/* SDIO interrupt flags */ +#define SDIO_INT_FLAG_CCRCERR BIT(0) /*!< SDIO CCRCERR interrupt flag */ +#define SDIO_INT_FLAG_DTCRCERR BIT(1) /*!< SDIO DTCRCERR interrupt flag */ +#define SDIO_INT_FLAG_CMDTMOUT BIT(2) /*!< SDIO CMDTMOUT interrupt flag */ +#define SDIO_INT_FLAG_DTTMOUT BIT(3) /*!< SDIO DTTMOUT interrupt flag */ +#define SDIO_INT_FLAG_TXURE BIT(4) /*!< SDIO TXURE interrupt flag */ +#define SDIO_INT_FLAG_RXORE BIT(5) /*!< SDIO RXORE interrupt flag */ +#define SDIO_INT_FLAG_CMDRECV BIT(6) /*!< SDIO CMDRECV interrupt flag */ +#define SDIO_INT_FLAG_CMDSEND BIT(7) /*!< SDIO CMDSEND interrupt flag */ +#define SDIO_INT_FLAG_DTEND BIT(8) /*!< SDIO DTEND interrupt flag */ +#define SDIO_INT_FLAG_STBITE BIT(9) /*!< SDIO STBITE interrupt flag */ +#define SDIO_INT_FLAG_DTBLKEND BIT(10) /*!< SDIO DTBLKEND interrupt flag */ +#define SDIO_INT_FLAG_CMDRUN BIT(11) /*!< SDIO CMDRUN interrupt flag */ +#define SDIO_INT_FLAG_TXRUN BIT(12) /*!< SDIO TXRUN interrupt flag */ +#define SDIO_INT_FLAG_RXRUN BIT(13) /*!< SDIO RXRUN interrupt flag */ +#define SDIO_INT_FLAG_TFH BIT(14) /*!< SDIO TFH interrupt flag */ +#define SDIO_INT_FLAG_RFH BIT(15) /*!< SDIO RFH interrupt flag */ +#define SDIO_INT_FLAG_TFF BIT(16) /*!< SDIO TFF interrupt flag */ +#define SDIO_INT_FLAG_RFF BIT(17) /*!< SDIO RFF interrupt flag */ +#define SDIO_INT_FLAG_TFE BIT(18) /*!< SDIO TFE interrupt flag */ +#define SDIO_INT_FLAG_RFE BIT(19) /*!< SDIO RFE interrupt flag */ +#define SDIO_INT_FLAG_TXDTVAL BIT(20) /*!< SDIO TXDTVAL interrupt flag */ +#define SDIO_INT_FLAG_RXDTVAL BIT(21) /*!< SDIO RXDTVAL interrupt flag */ +#define SDIO_INT_FLAG_SDIOINT BIT(22) /*!< SDIO SDIOINT interrupt flag */ +#define SDIO_INT_FLAG_ATAEND BIT(23) /*!< SDIO ATAEND interrupt flag */ + +/* SDIO power control */ +#define PWRCTL_PWRCTL(regval) (BITS(0,1) & ((uint32_t)(regval) << 0)) +#define SDIO_POWER_OFF PWRCTL_PWRCTL(0) /*!< SDIO power off */ +#define SDIO_POWER_ON PWRCTL_PWRCTL(3) /*!< SDIO power on */ + +/* SDIO card bus mode control */ +#define CLKCTL_BUSMODE(regval) (BITS(11,12) & ((uint32_t)(regval) << 11)) +#define SDIO_BUSMODE_1BIT CLKCTL_BUSMODE(0) /*!< 1-bit SDIO card bus mode */ +#define SDIO_BUSMODE_4BIT CLKCTL_BUSMODE(1) /*!< 4-bit SDIO card bus mode */ +#define SDIO_BUSMODE_8BIT CLKCTL_BUSMODE(2) /*!< 8-bit SDIO card bus mode */ + +/* SDIO_CLK clock edge selection */ +#define SDIO_SDIOCLKEDGE_RISING (uint32_t)0x00000000U /*!< select the rising edge of the SDIOCLK to generate SDIO_CLK */ +#define SDIO_SDIOCLKEDGE_FALLING SDIO_CLKCTL_CLKEDGE /*!< select the falling edge of the SDIOCLK to generate SDIO_CLK */ + +/* clock bypass enable or disable */ +#define SDIO_CLOCKBYPASS_DISABLE (uint32_t)0x00000000U /*!< no bypass */ +#define SDIO_CLOCKBYPASS_ENABLE SDIO_CLKCTL_CLKBYP /*!< clock bypass */ + +/* SDIO_CLK clock dynamic switch on/off for power saving */ +#define SDIO_CLOCKPWRSAVE_DISABLE (uint32_t)0x00000000U /*!< SDIO_CLK clock is always on */ +#define SDIO_CLOCKPWRSAVE_ENABLE SDIO_CLKCTL_CLKPWRSAV /*!< SDIO_CLK closed when bus is idle */ + +/* SDIO command response type */ +#define CMDCTL_CMDRESP(regval) (BITS(6,7) & ((uint32_t)(regval) << 6)) +#define SDIO_RESPONSETYPE_NO CMDCTL_CMDRESP(0) /*!< no response */ +#define SDIO_RESPONSETYPE_SHORT CMDCTL_CMDRESP(1) /*!< short response */ +#define SDIO_RESPONSETYPE_LONG CMDCTL_CMDRESP(3) /*!< long response */ + +/* command state machine wait type */ +#define SDIO_WAITTYPE_NO (uint32_t)0x00000000U /*!< not wait interrupt */ +#define SDIO_WAITTYPE_INTERRUPT SDIO_CMDCTL_INTWAIT /*!< wait interrupt */ +#define SDIO_WAITTYPE_DATAEND SDIO_CMDCTL_WAITDEND /*!< wait the end of data transfer */ + +#define SDIO_RESPONSE0 (uint32_t)0x00000000U /*!< card response[31:0]/card response[127:96] */ +#define SDIO_RESPONSE1 (uint32_t)0x00000001U /*!< card response[95:64] */ +#define SDIO_RESPONSE2 (uint32_t)0x00000002U /*!< card response[63:32] */ +#define SDIO_RESPONSE3 (uint32_t)0x00000003U /*!< card response[31:1], plus bit 0 */ + +/* SDIO data block size */ +#define DATACTL_BLKSZ(regval) (BITS(4,7) & ((uint32_t)(regval) << 4)) +#define SDIO_DATABLOCKSIZE_1BYTE DATACTL_BLKSZ(0) /*!< block size = 1 byte */ +#define SDIO_DATABLOCKSIZE_2BYTES DATACTL_BLKSZ(1) /*!< block size = 2 bytes */ +#define SDIO_DATABLOCKSIZE_4BYTES DATACTL_BLKSZ(2) /*!< block size = 4 bytes */ +#define SDIO_DATABLOCKSIZE_8BYTES DATACTL_BLKSZ(3) /*!< block size = 8 bytes */ +#define SDIO_DATABLOCKSIZE_16BYTES DATACTL_BLKSZ(4) /*!< block size = 16 bytes */ +#define SDIO_DATABLOCKSIZE_32BYTES DATACTL_BLKSZ(5) /*!< block size = 32 bytes */ +#define SDIO_DATABLOCKSIZE_64BYTES DATACTL_BLKSZ(6) /*!< block size = 64 bytes */ +#define SDIO_DATABLOCKSIZE_128BYTES DATACTL_BLKSZ(7) /*!< block size = 128 bytes */ +#define SDIO_DATABLOCKSIZE_256BYTES DATACTL_BLKSZ(8) /*!< block size = 256 bytes */ +#define SDIO_DATABLOCKSIZE_512BYTES DATACTL_BLKSZ(9) /*!< block size = 512 bytes */ +#define SDIO_DATABLOCKSIZE_1024BYTES DATACTL_BLKSZ(10) /*!< block size = 1024 bytes */ +#define SDIO_DATABLOCKSIZE_2048BYTES DATACTL_BLKSZ(11) /*!< block size = 2048 bytes */ +#define SDIO_DATABLOCKSIZE_4096BYTES DATACTL_BLKSZ(12) /*!< block size = 4096 bytes */ +#define SDIO_DATABLOCKSIZE_8192BYTES DATACTL_BLKSZ(13) /*!< block size = 8192 bytes */ +#define SDIO_DATABLOCKSIZE_16384BYTES DATACTL_BLKSZ(14) /*!< block size = 16384 bytes */ + +/* SDIO data transfer mode */ +#define SDIO_TRANSMODE_BLOCK (uint32_t)0x00000000U /*!< block transfer */ +#define SDIO_TRANSMODE_STREAM SDIO_DATACTL_TRANSMOD /*!< stream transfer or SDIO multibyte transfer */ + +/* SDIO data transfer direction */ +#define SDIO_TRANSDIRECTION_TOCARD (uint32_t)0x00000000U /*!< write data to card */ +#define SDIO_TRANSDIRECTION_TOSDIO SDIO_DATACTL_DATADIR /*!< read data from card */ + +/* SDIO read wait type */ +#define SDIO_READWAITTYPE_DAT2 (uint32_t)0x00000000U /*!< read wait control using SDIO_DAT[2] */ +#define SDIO_READWAITTYPE_CLK SDIO_DATACTL_RWTYPE /*!< read wait control by stopping SDIO_CLK */ + +/* function declarations */ +/* de/initialization functions, hardware clock, bus mode, power_state and SDIO clock configuration */ +/* deinitialize the SDIO */ +void sdio_deinit(void); +/* configure the SDIO clock */ +void sdio_clock_config(uint32_t clock_edge, uint32_t clock_bypass, uint32_t clock_powersave, uint16_t clock_division); +/* enable hardware clock control */ +void sdio_hardware_clock_enable(void); +/* disable hardware clock control */ +void sdio_hardware_clock_disable(void); +/* set different SDIO card bus mode */ +void sdio_bus_mode_set(uint32_t bus_mode); +/* set the SDIO power state */ +void sdio_power_state_set(uint32_t power_state); +/* get the SDIO power state */ +uint32_t sdio_power_state_get(void); +/* enable SDIO_CLK clock output */ +void sdio_clock_enable(void); +/* disable SDIO_CLK clock output */ +void sdio_clock_disable(void); + +/* configure the command index, argument, response type, wait type and CSM to send command functions */ +/* configure the command and response */ +void sdio_command_response_config(uint32_t cmd_index, uint32_t cmd_argument, uint32_t response_type); +/* set the command state machine wait type */ +void sdio_wait_type_set(uint32_t wait_type); +/* enable the CSM(command state machine) */ +void sdio_csm_enable(void); +/* disable the CSM(command state machine) */ +void sdio_csm_disable(void); +/* get the last response command index */ +uint8_t sdio_command_index_get(void); +/* get the response for the last received command */ +uint32_t sdio_response_get(uint32_t responsex); + +/* configure the data timeout, length, block size, transfer mode, direction and DSM for data transfer functions */ +/* configure the data timeout, data length and data block size */ +void sdio_data_config(uint32_t data_timeout, uint32_t data_length, uint32_t data_blocksize); +/* configure the data transfer mode and direction */ +void sdio_data_transfer_config(uint32_t transfer_mode, uint32_t transfer_direction); +/* enable the DSM(data state machine) for data transfer */ +void sdio_dsm_enable(void); +/* disable the DSM(data state machine) */ +void sdio_dsm_disable(void); +/* write data(one word) to the transmit FIFO */ +void sdio_data_write(uint32_t data); +/* read data(one word) from the receive FIFO */ +uint32_t sdio_data_read(void); +/* get the number of remaining data bytes to be transferred to card */ +uint32_t sdio_data_counter_get(void); +/* get the number of words remaining to be written or read from FIFO */ +uint32_t sdio_fifo_counter_get(void); +/* enable the DMA request for SDIO */ +void sdio_dma_enable(void); +/* disable the DMA request for SDIO */ +void sdio_dma_disable(void); + +/* flag and interrupt functions */ +/* get the flags state of SDIO */ +FlagStatus sdio_flag_get(uint32_t flag); +/* clear the pending flags of SDIO */ +void sdio_flag_clear(uint32_t flag); +/* enable the SDIO interrupt */ +void sdio_interrupt_enable(uint32_t int_flag); +/* disable the SDIO interrupt */ +void sdio_interrupt_disable(uint32_t int_flag); +/* get the interrupt flags state of SDIO */ +FlagStatus sdio_interrupt_flag_get(uint32_t int_flag); +/* clear the interrupt pending flags of SDIO */ +void sdio_interrupt_flag_clear(uint32_t int_flag); + +/* SD I/O card functions */ +/* enable the read wait mode(SD I/O only) */ +void sdio_readwait_enable(void); +/* disable the read wait mode(SD I/O only) */ +void sdio_readwait_disable(void); +/* enable the function that stop the read wait process(SD I/O only) */ +void sdio_stop_readwait_enable(void); +/* disable the function that stop the read wait process(SD I/O only) */ +void sdio_stop_readwait_disable(void); +/* set the read wait type(SD I/O only) */ +void sdio_readwait_type_set(uint32_t readwait_type); +/* enable the SD I/O mode specific operation(SD I/O only) */ +void sdio_operation_enable(void); +/* disable the SD I/O mode specific operation(SD I/O only) */ +void sdio_operation_disable(void); +/* enable the SD I/O suspend operation(SD I/O only) */ +void sdio_suspend_enable(void); +/* disable the SD I/O suspend operation(SD I/O only) */ +void sdio_suspend_disable(void); + +/* CE-ATA functions */ +/* enable the CE-ATA command(CE-ATA only) */ +void sdio_ceata_command_enable(void); +/* disable the CE-ATA command(CE-ATA only) */ +void sdio_ceata_command_disable(void); +/* enable the CE-ATA interrupt(CE-ATA only) */ +void sdio_ceata_interrupt_enable(void); +/* disable the CE-ATA interrupt(CE-ATA only) */ +void sdio_ceata_interrupt_disable(void); +/* enable the CE-ATA command completion signal(CE-ATA only) */ +void sdio_ceata_command_completion_enable(void); +/* disable the CE-ATA command completion signal(CE-ATA only) */ +void sdio_ceata_command_completion_disable(void); + +#endif /* GD32F30X_SDIO_H */ diff --git a/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_standard_peripheral/Include/gd32f30x_spi.h b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_standard_peripheral/Include/gd32f30x_spi.h new file mode 100644 index 0000000000..44d691d07e --- /dev/null +++ b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_standard_peripheral/Include/gd32f30x_spi.h @@ -0,0 +1,365 @@ +/*! + \file gd32f30x_spi.h + \brief definitions for the SPI + + \version 2017-02-10, V1.0.0, firmware for GD32F30x + \version 2018-10-10, V1.1.0, firmware for GD32F30x + \version 2018-12-25, V2.0.0, firmware for GD32F30x + \version 2020-09-30, V2.1.0, firmware for GD32F30x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef GD32F30X_SPI_H +#define GD32F30X_SPI_H + +#include "gd32f30x.h" + +/* SPIx(x=0,1,2) definitions */ +#define SPI0 (SPI_BASE + 0x0000F800U) +#define SPI1 SPI_BASE +#define SPI2 (SPI_BASE + 0x00000400U) + +/* SPI registers definitions */ +#define SPI_CTL0(spix) REG32((spix) + 0x00U) /*!< SPI control register 0 */ +#define SPI_CTL1(spix) REG32((spix) + 0x04U) /*!< SPI control register 1*/ +#define SPI_STAT(spix) REG32((spix) + 0x08U) /*!< SPI status register */ +#define SPI_DATA(spix) REG32((spix) + 0x0CU) /*!< SPI data register */ +#define SPI_CRCPOLY(spix) REG32((spix) + 0x10U) /*!< SPI CRC polynomial register */ +#define SPI_RCRC(spix) REG32((spix) + 0x14U) /*!< SPI receive CRC register */ +#define SPI_TCRC(spix) REG32((spix) + 0x18U) /*!< SPI transmit CRC register */ +#define SPI_I2SCTL(spix) REG32((spix) + 0x1CU) /*!< SPI I2S control register */ +#define SPI_I2SPSC(spix) REG32((spix) + 0x20U) /*!< SPI I2S clock prescaler register */ +#define SPI_QCTL(spix) REG32((spix) + 0x80U) /*!< SPI quad mode control register(only SPI0) */ + +/* bits definitions */ +/* SPI_CTL0 */ +#define SPI_CTL0_CKPH BIT(0) /*!< clock phase selection*/ +#define SPI_CTL0_CKPL BIT(1) /*!< clock polarity selection */ +#define SPI_CTL0_MSTMOD BIT(2) /*!< master mode enable */ +#define SPI_CTL0_PSC BITS(3,5) /*!< master clock prescaler selection */ +#define SPI_CTL0_SPIEN BIT(6) /*!< SPI enable*/ +#define SPI_CTL0_LF BIT(7) /*!< LSB first mode */ +#define SPI_CTL0_SWNSS BIT(8) /*!< NSS pin selection in NSS software mode */ +#define SPI_CTL0_SWNSSEN BIT(9) /*!< NSS software mode selection */ +#define SPI_CTL0_RO BIT(10) /*!< receive only */ +#define SPI_CTL0_FF16 BIT(11) /*!< data frame size */ +#define SPI_CTL0_CRCNT BIT(12) /*!< CRC next transfer */ +#define SPI_CTL0_CRCEN BIT(13) /*!< CRC calculation enable */ +#define SPI_CTL0_BDOEN BIT(14) /*!< bidirectional transmit output enable*/ +#define SPI_CTL0_BDEN BIT(15) /*!< bidirectional enable */ + +/* SPI_CTL1 */ +#define SPI_CTL1_DMAREN BIT(0) /*!< receive buffer dma enable */ +#define SPI_CTL1_DMATEN BIT(1) /*!< transmit buffer dma enable */ +#define SPI_CTL1_NSSDRV BIT(2) /*!< drive NSS output */ +#define SPI_CTL1_NSSP BIT(3) /*!< SPI NSS pulse mode enable */ +#define SPI_CTL1_TMOD BIT(4) /*!< SPI TI mode enable */ +#define SPI_CTL1_ERRIE BIT(5) /*!< errors interrupt enable */ +#define SPI_CTL1_RBNEIE BIT(6) /*!< receive buffer not empty interrupt enable */ +#define SPI_CTL1_TBEIE BIT(7) /*!< transmit buffer empty interrupt enable */ + +/* SPI_STAT */ +#define SPI_STAT_RBNE BIT(0) /*!< receive buffer not empty */ +#define SPI_STAT_TBE BIT(1) /*!< transmit buffer empty */ +#define SPI_STAT_I2SCH BIT(2) /*!< I2S channel side */ +#define SPI_STAT_TXURERR BIT(3) /*!< I2S transmission underrun error bit */ +#define SPI_STAT_CRCERR BIT(4) /*!< SPI CRC error bit */ +#define SPI_STAT_CONFERR BIT(5) /*!< SPI configuration error bit */ +#define SPI_STAT_RXORERR BIT(6) /*!< SPI reception overrun error bit */ +#define SPI_STAT_TRANS BIT(7) /*!< transmitting on-going bit */ +#define SPI_STAT_FERR BIT(8) /*!< format error bit */ + +/* SPI_DATA */ +#define SPI_DATA_DATA BITS(0,15) /*!< data transfer register */ + +/* SPI_CRCPOLY */ +#define SPI_CRCPOLY_CPR BITS(0,15) /*!< CRC polynomial register */ + +/* SPI_RCRC */ +#define SPI_RCRC_RCR BITS(0,15) /*!< RX CRC register */ + +/* SPI_TCRC */ +#define SPI_TCRC_TCR BITS(0,15) /*!< TX CRC register */ + +/* SPI_I2SCTL */ +#define SPI_I2SCTL_CHLEN BIT(0) /*!< channel length */ +#define SPI_I2SCTL_DTLEN BITS(1,2) /*!< data length */ +#define SPI_I2SCTL_CKPL BIT(3) /*!< idle state clock polarity */ +#define SPI_I2SCTL_I2SSTD BITS(4,5) /*!< I2S standard selection */ +#define SPI_I2SCTL_PCMSMOD BIT(7) /*!< PCM frame synchronization mode */ +#define SPI_I2SCTL_I2SOPMOD BITS(8,9) /*!< I2S operation mode */ +#define SPI_I2SCTL_I2SEN BIT(10) /*!< I2S enable */ +#define SPI_I2SCTL_I2SSEL BIT(11) /*!< I2S mode selection */ + +/* SPI_I2SPSC */ +#define SPI_I2SPSC_DIV BITS(0,7) /*!< dividing factor for the prescaler */ +#define SPI_I2SPSC_OF BIT(8) /*!< odd factor for the prescaler */ +#define SPI_I2SPSC_MCKOEN BIT(9) /*!< I2S MCK output enable */ + +/* SPI_QCTL(only for SPI0) */ +#define SPI_QCTL_QMOD BIT(0) /*!< quad-SPI mode enable */ +#define SPI_QCTL_QRD BIT(1) /*!< quad-SPI mode read select */ +#define SPI_QCTL_IO23_DRV BIT(2) /*!< drive SPI_IO2 and SPI_IO3 enable */ + +/* constants definitions */ +/* SPI and I2S parameter struct definitions */ +typedef struct +{ + uint32_t device_mode; /*!< SPI master or slave */ + uint32_t trans_mode; /*!< SPI transtype */ + uint32_t frame_size; /*!< SPI frame size */ + uint32_t nss; /*!< SPI NSS control by handware or software */ + uint32_t endian; /*!< SPI big endian or little endian */ + uint32_t clock_polarity_phase; /*!< SPI clock phase and polarity */ + uint32_t prescale; /*!< SPI prescale factor */ +}spi_parameter_struct; + +/* SPI mode definitions */ +#define SPI_MASTER (SPI_CTL0_MSTMOD | SPI_CTL0_SWNSS) /*!< SPI as master */ +#define SPI_SLAVE ((uint32_t)0x00000000U) /*!< SPI as slave */ + +/* SPI bidirectional transfer direction */ +#define SPI_BIDIRECTIONAL_TRANSMIT SPI_CTL0_BDOEN /*!< SPI work in transmit-only mode */ +#define SPI_BIDIRECTIONAL_RECEIVE (~SPI_CTL0_BDOEN) /*!< SPI work in receive-only mode */ + +/* SPI transmit type */ +#define SPI_TRANSMODE_FULLDUPLEX ((uint32_t)0x00000000U) /*!< SPI receive and send data at fullduplex communication */ +#define SPI_TRANSMODE_RECEIVEONLY SPI_CTL0_RO /*!< SPI only receive data */ +#define SPI_TRANSMODE_BDRECEIVE SPI_CTL0_BDEN /*!< bidirectional receive data */ +#define SPI_TRANSMODE_BDTRANSMIT (SPI_CTL0_BDEN | SPI_CTL0_BDOEN) /*!< bidirectional transmit data*/ + +/* SPI frame size */ +#define SPI_FRAMESIZE_16BIT SPI_CTL0_FF16 /*!< SPI frame size is 16 bits */ +#define SPI_FRAMESIZE_8BIT ((uint32_t)0x00000000U) /*!< SPI frame size is 8 bits */ + +/* SPI NSS control mode */ +#define SPI_NSS_SOFT SPI_CTL0_SWNSSEN /*!< SPI NSS control by sofrware */ +#define SPI_NSS_HARD ((uint32_t)0x00000000U) /*!< SPI NSS control by hardware */ + +/* SPI transmit way */ +#define SPI_ENDIAN_MSB ((uint32_t)0x00000000U) /*!< SPI transmit way is big endian: transmit MSB first */ +#define SPI_ENDIAN_LSB SPI_CTL0_LF /*!< SPI transmit way is little endian: transmit LSB first */ + +/* SPI clock phase and polarity */ +#define SPI_CK_PL_LOW_PH_1EDGE ((uint32_t)0x00000000U) /*!< SPI clock polarity is low level and phase is first edge */ +#define SPI_CK_PL_HIGH_PH_1EDGE SPI_CTL0_CKPL /*!< SPI clock polarity is high level and phase is first edge */ +#define SPI_CK_PL_LOW_PH_2EDGE SPI_CTL0_CKPH /*!< SPI clock polarity is low level and phase is second edge */ +#define SPI_CK_PL_HIGH_PH_2EDGE (SPI_CTL0_CKPL | SPI_CTL0_CKPH) /*!< SPI clock polarity is high level and phase is second edge */ + +/* SPI clock prescale factor */ +#define CTL0_PSC(regval) (BITS(3,5) & ((uint32_t)(regval) << 3)) +#define SPI_PSC_2 CTL0_PSC(0) /*!< SPI clock prescale factor is 2 */ +#define SPI_PSC_4 CTL0_PSC(1) /*!< SPI clock prescale factor is 4 */ +#define SPI_PSC_8 CTL0_PSC(2) /*!< SPI clock prescale factor is 8 */ +#define SPI_PSC_16 CTL0_PSC(3) /*!< SPI clock prescale factor is 16 */ +#define SPI_PSC_32 CTL0_PSC(4) /*!< SPI clock prescale factor is 32 */ +#define SPI_PSC_64 CTL0_PSC(5) /*!< SPI clock prescale factor is 64 */ +#define SPI_PSC_128 CTL0_PSC(6) /*!< SPI clock prescale factor is 128 */ +#define SPI_PSC_256 CTL0_PSC(7) /*!< SPI clock prescale factor is 256 */ + +/* I2S audio sample rate */ +#define I2S_AUDIOSAMPLE_8K ((uint32_t)8000U) /*!< I2S audio sample rate is 8KHz */ +#define I2S_AUDIOSAMPLE_11K ((uint32_t)11025U) /*!< I2S audio sample rate is 11KHz */ +#define I2S_AUDIOSAMPLE_16K ((uint32_t)16000U) /*!< I2S audio sample rate is 16KHz */ +#define I2S_AUDIOSAMPLE_22K ((uint32_t)22050U) /*!< I2S audio sample rate is 22KHz */ +#define I2S_AUDIOSAMPLE_32K ((uint32_t)32000U) /*!< I2S audio sample rate is 32KHz */ +#define I2S_AUDIOSAMPLE_44K ((uint32_t)44100U) /*!< I2S audio sample rate is 44KHz */ +#define I2S_AUDIOSAMPLE_48K ((uint32_t)48000U) /*!< I2S audio sample rate is 48KHz */ +#define I2S_AUDIOSAMPLE_96K ((uint32_t)96000U) /*!< I2S audio sample rate is 96KHz */ +#define I2S_AUDIOSAMPLE_192K ((uint32_t)192000U) /*!< I2S audio sample rate is 192KHz */ + +/* I2S frame format */ +#define I2SCTL_DTLEN(regval) (BITS(1,2) & ((uint32_t)(regval) << 1)) +#define I2S_FRAMEFORMAT_DT16B_CH16B I2SCTL_DTLEN(0) /*!< I2S data length is 16 bit and channel length is 16 bit */ +#define I2S_FRAMEFORMAT_DT16B_CH32B (I2SCTL_DTLEN(0) | SPI_I2SCTL_CHLEN) /*!< I2S data length is 16 bit and channel length is 32 bit */ +#define I2S_FRAMEFORMAT_DT24B_CH32B (I2SCTL_DTLEN(1) | SPI_I2SCTL_CHLEN) /*!< I2S data length is 24 bit and channel length is 32 bit */ +#define I2S_FRAMEFORMAT_DT32B_CH32B (I2SCTL_DTLEN(2) | SPI_I2SCTL_CHLEN) /*!< I2S data length is 32 bit and channel length is 32 bit */ + +/* I2S master clock output */ +#define I2S_MCKOUT_DISABLE ((uint32_t)0x00000000U) /*!< I2S master clock output disable */ +#define I2S_MCKOUT_ENABLE SPI_I2SPSC_MCKOEN /*!< I2S master clock output enable */ + +/* I2S operation mode */ +#define I2SCTL_I2SOPMOD(regval) (BITS(8,9) & ((uint32_t)(regval) << 8)) +#define I2S_MODE_SLAVETX I2SCTL_I2SOPMOD(0) /*!< I2S slave transmit mode */ +#define I2S_MODE_SLAVERX I2SCTL_I2SOPMOD(1) /*!< I2S slave receive mode */ +#define I2S_MODE_MASTERTX I2SCTL_I2SOPMOD(2) /*!< I2S master transmit mode */ +#define I2S_MODE_MASTERRX I2SCTL_I2SOPMOD(3) /*!< I2S master receive mode */ + +/* I2S standard */ +#define I2SCTL_I2SSTD(regval) (BITS(4,5) & ((uint32_t)(regval) << 4)) +#define I2S_STD_PHILLIPS I2SCTL_I2SSTD(0) /*!< I2S phillips standard */ +#define I2S_STD_MSB I2SCTL_I2SSTD(1) /*!< I2S MSB standard */ +#define I2S_STD_LSB I2SCTL_I2SSTD(2) /*!< I2S LSB standard */ +#define I2S_STD_PCMSHORT I2SCTL_I2SSTD(3) /*!< I2S PCM short standard */ +#define I2S_STD_PCMLONG (I2SCTL_I2SSTD(3) | SPI_I2SCTL_PCMSMOD) /*!< I2S PCM long standard */ + +/* I2S clock polarity */ +#define I2S_CKPL_LOW ((uint32_t)0x00000000U) /*!< I2S clock polarity low level */ +#define I2S_CKPL_HIGH SPI_I2SCTL_CKPL /*!< I2S clock polarity high level */ + +/* SPI DMA constants definitions */ +#define SPI_DMA_TRANSMIT ((uint8_t)0x00U) /*!< SPI transmit data use DMA */ +#define SPI_DMA_RECEIVE ((uint8_t)0x01U) /*!< SPI receive data use DMA */ + +/* SPI CRC constants definitions */ +#define SPI_CRC_TX ((uint8_t)0x00U) /*!< SPI transmit CRC value */ +#define SPI_CRC_RX ((uint8_t)0x01U) /*!< SPI receive CRC value */ + +/* SPI/I2S interrupt enable/disable constants definitions */ +#define SPI_I2S_INT_TBE ((uint8_t)0x00U) /*!< transmit buffer empty interrupt */ +#define SPI_I2S_INT_RBNE ((uint8_t)0x01U) /*!< receive buffer not empty interrupt */ +#define SPI_I2S_INT_ERR ((uint8_t)0x02U) /*!< error interrupt */ + +/* SPI/I2S interrupt flag constants definitions */ +#define SPI_I2S_INT_FLAG_TBE ((uint8_t)0x00U) /*!< transmit buffer empty interrupt flag */ +#define SPI_I2S_INT_FLAG_RBNE ((uint8_t)0x01U) /*!< receive buffer not empty interrupt flag */ +#define SPI_I2S_INT_FLAG_RXORERR ((uint8_t)0x02U) /*!< overrun interrupt flag */ +#define SPI_INT_FLAG_CONFERR ((uint8_t)0x03U) /*!< config error interrupt flag */ +#define SPI_INT_FLAG_CRCERR ((uint8_t)0x04U) /*!< CRC error interrupt flag */ +#define I2S_INT_FLAG_TXURERR ((uint8_t)0x05U) /*!< underrun error interrupt flag */ +#define SPI_I2S_INT_FLAG_FERR ((uint8_t)0x06U) /*!< format error interrupt flag */ + +/* SPI/I2S flag definitions */ +#define SPI_FLAG_RBNE SPI_STAT_RBNE /*!< receive buffer not empty flag */ +#define SPI_FLAG_TBE SPI_STAT_TBE /*!< transmit buffer empty flag */ +#define SPI_FLAG_CRCERR SPI_STAT_CRCERR /*!< CRC error flag */ +#define SPI_FLAG_CONFERR SPI_STAT_CONFERR /*!< mode config error flag */ +#define SPI_FLAG_RXORERR SPI_STAT_RXORERR /*!< receive overrun error flag */ +#define SPI_FLAG_TRANS SPI_STAT_TRANS /*!< transmit on-going flag */ +#define SPI_FLAG_FERR SPI_STAT_FERR /*!< format error flag */ +#define I2S_FLAG_RBNE SPI_STAT_RBNE /*!< receive buffer not empty flag */ +#define I2S_FLAG_TBE SPI_STAT_TBE /*!< transmit buffer empty flag */ +#define I2S_FLAG_CH SPI_STAT_I2SCH /*!< channel side flag */ +#define I2S_FLAG_TXURERR SPI_STAT_TXURERR /*!< underrun error flag */ +#define I2S_FLAG_RXORERR SPI_STAT_RXORERR /*!< overrun error flag */ +#define I2S_FLAG_TRANS SPI_STAT_TRANS /*!< transmit on-going flag */ +#define I2S_FLAG_FERR SPI_STAT_FERR /*!< format error flag */ + +/* function declarations */ +/* SPI/I2S deinitialization and initialization functions */ +/* reset SPI and I2S */ +void spi_i2s_deinit(uint32_t spi_periph); +/* initialize the parameters of SPI struct with the default values */ +void spi_struct_para_init(spi_parameter_struct* spi_struct); +/* initialize SPI parameter */ +void spi_init(uint32_t spi_periph, spi_parameter_struct* spi_struct); +/* enable SPI */ +void spi_enable(uint32_t spi_periph); +/* disable SPI */ +void spi_disable(uint32_t spi_periph); + +/* initialize I2S parameter */ +void i2s_init(uint32_t spi_periph, uint32_t i2s_mode, uint32_t i2s_standard, uint32_t i2s_ckpl); +/* configure I2S prescaler */ +void i2s_psc_config(uint32_t spi_periph, uint32_t i2s_audiosample, uint32_t i2s_frameformat, uint32_t i2s_mckout); +/* enable I2S */ +void i2s_enable(uint32_t spi_periph); +/* disable I2S */ +void i2s_disable(uint32_t spi_periph); + +/* NSS functions */ +/* enable SPI NSS output */ +void spi_nss_output_enable(uint32_t spi_periph); +/* disable SPI NSS output */ +void spi_nss_output_disable(uint32_t spi_periph); +/* SPI NSS pin high level in software mode */ +void spi_nss_internal_high(uint32_t spi_periph); +/* SPI NSS pin low level in software mode */ +void spi_nss_internal_low(uint32_t spi_periph); + +/* SPI DMA functions */ +/* enable SPI DMA */ +void spi_dma_enable(uint32_t spi_periph, uint8_t dma); +/* disable SPI DMA */ +void spi_dma_disable(uint32_t spi_periph, uint8_t dma); + +/* SPI/I2S transfer configure functions */ +/* configure SPI/I2S data frame format */ +void spi_i2s_data_frame_format_config(uint32_t spi_periph, uint16_t frame_format); +/* SPI transmit data */ +void spi_i2s_data_transmit(uint32_t spi_periph, uint16_t data); +/* SPI receive data */ +uint16_t spi_i2s_data_receive(uint32_t spi_periph); +/* configure SPI bidirectional transfer direction */ +void spi_bidirectional_transfer_config(uint32_t spi_periph, uint32_t transfer_direction); + +/* SPI CRC functions */ +/* set SPI CRC polynomial */ +void spi_crc_polynomial_set(uint32_t spi_periph, uint16_t crc_poly); +/* get SPI CRC polynomial */ +uint16_t spi_crc_polynomial_get(uint32_t spi_periph); +/* turn on SPI CRC function */ +void spi_crc_on(uint32_t spi_periph); +/* turn off SPI CRC function */ +void spi_crc_off(uint32_t spi_periph); +/* SPI next data is CRC value */ +void spi_crc_next(uint32_t spi_periph); +/* get SPI CRC send value or receive value */ +uint16_t spi_crc_get(uint32_t spi_periph, uint8_t crc); + +/* SPI TI mode functions */ +/* enable SPI TI mode */ +void spi_ti_mode_enable(uint32_t spi_periph); +/* disable SPI TI mode */ +void spi_ti_mode_disable(uint32_t spi_periph); + +/* SPI NSS pulse mode functions */ +/* enable SPI NSS pulse mode */ +void spi_nssp_mode_enable(uint32_t spi_periph); +/* disable SPI NSS pulse mode */ +void spi_nssp_mode_disable(uint32_t spi_periph); + +/* quad wire SPI functions */ +/* enable quad wire SPI */ +void qspi_enable(uint32_t spi_periph); +/* disable quad wire SPI */ +void qspi_disable(uint32_t spi_periph); +/* enable quad wire SPI write */ +void qspi_write_enable(uint32_t spi_periph); +/* enable quad wire SPI read */ +void qspi_read_enable(uint32_t spi_periph); +/* enable quad wire SPI_IO2 and SPI_IO3 pin output */ +void qspi_io23_output_enable(uint32_t spi_periph); +/* disable quad wire SPI_IO2 and SPI_IO3 pin output */ +void qspi_io23_output_disable(uint32_t spi_periph); + +/* flag and interrupt functions */ +/* enable SPI and I2S interrupt */ +void spi_i2s_interrupt_enable(uint32_t spi_periph, uint8_t interrupt); +/* disable SPI and I2S interrupt */ +void spi_i2s_interrupt_disable(uint32_t spi_periph, uint8_t interrupt); +/* get SPI and I2S interrupt status */ +FlagStatus spi_i2s_interrupt_flag_get(uint32_t spi_periph, uint8_t interrupt); +/* get SPI and I2S flag status */ +FlagStatus spi_i2s_flag_get(uint32_t spi_periph, uint32_t flag); +/* clear SPI CRC error flag status */ +void spi_crc_error_clear(uint32_t spi_periph); + +#endif /* GD32F30X_SPI_H */ diff --git a/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_standard_peripheral/Include/gd32f30x_timer.h b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_standard_peripheral/Include/gd32f30x_timer.h new file mode 100644 index 0000000000..7196b3a694 --- /dev/null +++ b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_standard_peripheral/Include/gd32f30x_timer.h @@ -0,0 +1,752 @@ +/*! + \file gd32f30x_timer.h + \brief definitions for the TIMER + + \version 2017-02-10, V1.0.0, firmware for GD32F30x + \version 2018-10-10, V1.1.0, firmware for GD32F30x + \version 2018-12-25, V2.0.0, firmware for GD32F30x + \version 2020-09-30, V2.1.0, firmware for GD32F30x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef GD32F30X_TIMER_H +#define GD32F30X_TIMER_H + +#include "gd32f30x.h" + +/* TIMERx(x=0..13) definitions */ +#define TIMER0 (TIMER_BASE + 0x00012C00U) +#define TIMER1 (TIMER_BASE + 0x00000000U) +#define TIMER2 (TIMER_BASE + 0x00000400U) +#define TIMER3 (TIMER_BASE + 0x00000800U) +#define TIMER4 (TIMER_BASE + 0x00000C00U) +#define TIMER5 (TIMER_BASE + 0x00001000U) +#define TIMER6 (TIMER_BASE + 0x00001400U) +#define TIMER7 (TIMER_BASE + 0x00013400U) +#define TIMER8 (TIMER_BASE + 0x00014C00U) +#define TIMER9 (TIMER_BASE + 0x00015000U) +#define TIMER10 (TIMER_BASE + 0x00015400U) +#define TIMER11 (TIMER_BASE + 0x00001800U) +#define TIMER12 (TIMER_BASE + 0x00001C00U) +#define TIMER13 (TIMER_BASE + 0x00002000U) + +/* registers definitions */ +#define TIMER_CTL0(timerx) REG32((timerx) + 0x00U) /*!< TIMER control register 0 */ +#define TIMER_CTL1(timerx) REG32((timerx) + 0x04U) /*!< TIMER control register 1 */ +#define TIMER_SMCFG(timerx) REG32((timerx) + 0x08U) /*!< TIMER slave mode configuration register */ +#define TIMER_DMAINTEN(timerx) REG32((timerx) + 0x0CU) /*!< TIMER DMA and interrupt enable register */ +#define TIMER_INTF(timerx) REG32((timerx) + 0x10U) /*!< TIMER interrupt flag register */ +#define TIMER_SWEVG(timerx) REG32((timerx) + 0x14U) /*!< TIMER software event generation register */ +#define TIMER_CHCTL0(timerx) REG32((timerx) + 0x18U) /*!< TIMER channel control register 0 */ +#define TIMER_CHCTL1(timerx) REG32((timerx) + 0x1CU) /*!< TIMER channel control register 1 */ +#define TIMER_CHCTL2(timerx) REG32((timerx) + 0x20U) /*!< TIMER channel control register 2 */ +#define TIMER_CNT(timerx) REG32((timerx) + 0x24U) /*!< TIMER counter register */ +#define TIMER_PSC(timerx) REG32((timerx) + 0x28U) /*!< TIMER prescaler register */ +#define TIMER_CAR(timerx) REG32((timerx) + 0x2CU) /*!< TIMER counter auto reload register */ +#define TIMER_CREP(timerx) REG32((timerx) + 0x30U) /*!< TIMER counter repetition register */ +#define TIMER_CH0CV(timerx) REG32((timerx) + 0x34U) /*!< TIMER channel 0 capture/compare value register */ +#define TIMER_CH1CV(timerx) REG32((timerx) + 0x38U) /*!< TIMER channel 1 capture/compare value register */ +#define TIMER_CH2CV(timerx) REG32((timerx) + 0x3CU) /*!< TIMER channel 2 capture/compare value register */ +#define TIMER_CH3CV(timerx) REG32((timerx) + 0x40U) /*!< TIMER channel 3 capture/compare value register */ +#define TIMER_CCHP(timerx) REG32((timerx) + 0x44U) /*!< TIMER complementary channel protection register */ +#define TIMER_DMACFG(timerx) REG32((timerx) + 0x48U) /*!< TIMER DMA configuration register */ +#define TIMER_DMATB(timerx) REG32((timerx) + 0x4CU) /*!< TIMER DMA transfer buffer register */ +#define TIMER_IRMP(timerx) REG32((timerx) + 0x50U) /*!< TIMER channel input remap register */ +#define TIMER_CFG(timerx) REG32((timerx) + 0xFCU) /*!< TIMER configuration register */ + +/* bits definitions */ +/* TIMER_CTL0 */ +#define TIMER_CTL0_CEN BIT(0) /*!< TIMER counter enable */ +#define TIMER_CTL0_UPDIS BIT(1) /*!< update disable */ +#define TIMER_CTL0_UPS BIT(2) /*!< update source */ +#define TIMER_CTL0_SPM BIT(3) /*!< single pulse mode */ +#define TIMER_CTL0_DIR BIT(4) /*!< timer counter direction */ +#define TIMER_CTL0_CAM BITS(5,6) /*!< center-aligned mode selection */ +#define TIMER_CTL0_ARSE BIT(7) /*!< auto-reload shadow enable */ +#define TIMER_CTL0_CKDIV BITS(8,9) /*!< clock division */ + +/* TIMER_CTL1 */ +#define TIMER_CTL1_CCSE BIT(0) /*!< commutation control shadow enable */ +#define TIMER_CTL1_CCUC BIT(2) /*!< commutation control shadow register update control */ +#define TIMER_CTL1_DMAS BIT(3) /*!< DMA request source selection */ +#define TIMER_CTL1_MMC BITS(4,6) /*!< master mode control */ +#define TIMER_CTL1_TI0S BIT(7) /*!< channel 0 trigger input selection(hall mode selection) */ +#define TIMER_CTL1_ISO0 BIT(8) /*!< idle state of channel 0 output */ +#define TIMER_CTL1_ISO0N BIT(9) /*!< idle state of channel 0 complementary output */ +#define TIMER_CTL1_ISO1 BIT(10) /*!< idle state of channel 1 output */ +#define TIMER_CTL1_ISO1N BIT(11) /*!< idle state of channel 1 complementary output */ +#define TIMER_CTL1_ISO2 BIT(12) /*!< idle state of channel 2 output */ +#define TIMER_CTL1_ISO2N BIT(13) /*!< idle state of channel 2 complementary output */ +#define TIMER_CTL1_ISO3 BIT(14) /*!< idle state of channel 3 output */ + +/* TIMER_SMCFG */ +#define TIMER_SMCFG_SMC BITS(0,2) /*!< slave mode control */ +#define TIMER_SMCFG_TRGS BITS(4,6) /*!< trigger selection */ +#define TIMER_SMCFG_MSM BIT(7) /*!< master-slave mode */ +#define TIMER_SMCFG_ETFC BITS(8,11) /*!< external trigger filter control */ +#define TIMER_SMCFG_ETPSC BITS(12,13) /*!< external trigger prescaler */ +#define TIMER_SMCFG_SMC1 BIT(14) /*!< part of SMC for enable external clock mode 1 */ +#define TIMER_SMCFG_ETP BIT(15) /*!< external trigger polarity */ + +/* TIMER_DMAINTEN */ +#define TIMER_DMAINTEN_UPIE BIT(0) /*!< update interrupt enable */ +#define TIMER_DMAINTEN_CH0IE BIT(1) /*!< channel 0 capture/compare interrupt enable */ +#define TIMER_DMAINTEN_CH1IE BIT(2) /*!< channel 1 capture/compare interrupt enable */ +#define TIMER_DMAINTEN_CH2IE BIT(3) /*!< channel 2 capture/compare interrupt enable */ +#define TIMER_DMAINTEN_CH3IE BIT(4) /*!< channel 3 capture/compare interrupt enable */ +#define TIMER_DMAINTEN_CMTIE BIT(5) /*!< commutation interrupt request enable */ +#define TIMER_DMAINTEN_TRGIE BIT(6) /*!< trigger interrupt enable */ +#define TIMER_DMAINTEN_BRKIE BIT(7) /*!< break interrupt enable */ +#define TIMER_DMAINTEN_UPDEN BIT(8) /*!< update DMA request enable */ +#define TIMER_DMAINTEN_CH0DEN BIT(9) /*!< channel 0 DMA request enable */ +#define TIMER_DMAINTEN_CH1DEN BIT(10) /*!< channel 1 DMA request enable */ +#define TIMER_DMAINTEN_CH2DEN BIT(11) /*!< channel 2 DMA request enable */ +#define TIMER_DMAINTEN_CH3DEN BIT(12) /*!< channel 3 DMA request enable */ +#define TIMER_DMAINTEN_CMTDEN BIT(13) /*!< commutation DMA request enable */ +#define TIMER_DMAINTEN_TRGDEN BIT(14) /*!< trigger DMA request enable */ + +/* TIMER_INTF */ +#define TIMER_INTF_UPIF BIT(0) /*!< update interrupt flag */ +#define TIMER_INTF_CH0IF BIT(1) /*!< channel 0 capture/compare interrupt flag */ +#define TIMER_INTF_CH1IF BIT(2) /*!< channel 1 capture/compare interrupt flag */ +#define TIMER_INTF_CH2IF BIT(3) /*!< channel 2 capture/compare interrupt flag */ +#define TIMER_INTF_CH3IF BIT(4) /*!< channel 3 capture/compare interrupt flag */ +#define TIMER_INTF_CMTIF BIT(5) /*!< channel commutation interrupt flag */ +#define TIMER_INTF_TRGIF BIT(6) /*!< trigger interrupt flag */ +#define TIMER_INTF_BRKIF BIT(7) /*!< break interrupt flag */ +#define TIMER_INTF_CH0OF BIT(9) /*!< channel 0 overcapture flag */ +#define TIMER_INTF_CH1OF BIT(10) /*!< channel 1 overcapture flag */ +#define TIMER_INTF_CH2OF BIT(11) /*!< channel 2 overcapture flag */ +#define TIMER_INTF_CH3OF BIT(12) /*!< channel 3 overcapture flag */ + +/* TIMER_SWEVG */ +#define TIMER_SWEVG_UPG BIT(0) /*!< update event generate */ +#define TIMER_SWEVG_CH0G BIT(1) /*!< channel 0 capture or compare event generation */ +#define TIMER_SWEVG_CH1G BIT(2) /*!< channel 1 capture or compare event generation */ +#define TIMER_SWEVG_CH2G BIT(3) /*!< channel 2 capture or compare event generation */ +#define TIMER_SWEVG_CH3G BIT(4) /*!< channel 3 capture or compare event generation */ +#define TIMER_SWEVG_CMTG BIT(5) /*!< channel commutation event generation */ +#define TIMER_SWEVG_TRGG BIT(6) /*!< trigger event generation */ +#define TIMER_SWEVG_BRKG BIT(7) /*!< break event generation */ + +/* TIMER_CHCTL0 */ +/* output compare mode */ +#define TIMER_CHCTL0_CH0MS BITS(0,1) /*!< channel 0 mode selection */ +#define TIMER_CHCTL0_CH0COMFEN BIT(2) /*!< channel 0 output compare fast enable */ +#define TIMER_CHCTL0_CH0COMSEN BIT(3) /*!< channel 0 output compare shadow enable */ +#define TIMER_CHCTL0_CH0COMCTL BITS(4,6) /*!< channel 0 output compare mode */ +#define TIMER_CHCTL0_CH0COMCEN BIT(7) /*!< channel 0 output compare clear enable */ +#define TIMER_CHCTL0_CH1MS BITS(8,9) /*!< channel 1 mode selection */ +#define TIMER_CHCTL0_CH1COMFEN BIT(10) /*!< channel 1 output compare fast enable */ +#define TIMER_CHCTL0_CH1COMSEN BIT(11) /*!< channel 1 output compare shadow enable */ +#define TIMER_CHCTL0_CH1COMCTL BITS(12,14) /*!< channel 1 output compare mode */ +#define TIMER_CHCTL0_CH1COMCEN BIT(15) /*!< channel 1 output compare clear enable */ +/* input capture mode */ +#define TIMER_CHCTL0_CH0CAPPSC BITS(2,3) /*!< channel 0 input capture prescaler */ +#define TIMER_CHCTL0_CH0CAPFLT BITS(4,7) /*!< channel 0 input capture filter control */ +#define TIMER_CHCTL0_CH1CAPPSC BITS(10,11) /*!< channel 1 input capture prescaler */ +#define TIMER_CHCTL0_CH1CAPFLT BITS(12,15) /*!< channel 1 input capture filter control */ + +/* TIMER_CHCTL1 */ +/* output compare mode */ +#define TIMER_CHCTL1_CH2MS BITS(0,1) /*!< channel 2 mode selection */ +#define TIMER_CHCTL1_CH2COMFEN BIT(2) /*!< channel 2 output compare fast enable */ +#define TIMER_CHCTL1_CH2COMSEN BIT(3) /*!< channel 2 output compare shadow enable */ +#define TIMER_CHCTL1_CH2COMCTL BITS(4,6) /*!< channel 2 output compare mode */ +#define TIMER_CHCTL1_CH2COMCEN BIT(7) /*!< channel 2 output compare clear enable */ +#define TIMER_CHCTL1_CH3MS BITS(8,9) /*!< channel 3 mode selection */ +#define TIMER_CHCTL1_CH3COMFEN BIT(10) /*!< channel 3 output compare fast enable */ +#define TIMER_CHCTL1_CH3COMSEN BIT(11) /*!< channel 3 output compare shadow enable */ +#define TIMER_CHCTL1_CH3COMCTL BITS(12,14) /*!< channel 3 output compare mode */ +#define TIMER_CHCTL1_CH3COMCEN BIT(15) /*!< channel 3 output compare clear enable */ +/* input capture mode */ +#define TIMER_CHCTL1_CH2CAPPSC BITS(2,3) /*!< channel 2 input capture prescaler */ +#define TIMER_CHCTL1_CH2CAPFLT BITS(4,7) /*!< channel 2 input capture filter control */ +#define TIMER_CHCTL1_CH3CAPPSC BITS(10,11) /*!< channel 3 input capture prescaler */ +#define TIMER_CHCTL1_CH3CAPFLT BITS(12,15) /*!< channel 3 input capture filter control */ + +/* TIMER_CHCTL2 */ +#define TIMER_CHCTL2_CH0EN BIT(0) /*!< channel 0 capture/compare function enable */ +#define TIMER_CHCTL2_CH0P BIT(1) /*!< channel 0 capture/compare function polarity */ +#define TIMER_CHCTL2_CH0NEN BIT(2) /*!< channel 0 complementary output enable */ +#define TIMER_CHCTL2_CH0NP BIT(3) /*!< channel 0 complementary output polarity */ +#define TIMER_CHCTL2_CH1EN BIT(4) /*!< channel 1 capture/compare function enable */ +#define TIMER_CHCTL2_CH1P BIT(5) /*!< channel 1 capture/compare function polarity */ +#define TIMER_CHCTL2_CH1NEN BIT(6) /*!< channel 1 complementary output enable */ +#define TIMER_CHCTL2_CH1NP BIT(7) /*!< channel 1 complementary output polarity */ +#define TIMER_CHCTL2_CH2EN BIT(8) /*!< channel 2 capture/compare function enable */ +#define TIMER_CHCTL2_CH2P BIT(9) /*!< channel 2 capture/compare function polarity */ +#define TIMER_CHCTL2_CH2NEN BIT(10) /*!< channel 2 complementary output enable */ +#define TIMER_CHCTL2_CH2NP BIT(11) /*!< channel 2 complementary output polarity */ +#define TIMER_CHCTL2_CH3EN BIT(12) /*!< channel 3 capture/compare function enable */ +#define TIMER_CHCTL2_CH3P BIT(13) /*!< channel 3 capture/compare function polarity */ + +/* TIMER_CNT */ +#define TIMER_CNT_CNT BITS(0,15) /*!< 16 bit timer counter */ + +/* TIMER_PSC */ +#define TIMER_PSC_PSC BITS(0,15) /*!< prescaler value of the counter clock */ + +/* TIMER_CAR */ +#define TIMER_CAR_CARL BITS(0,15) /*!< 16 bit counter auto reload value */ + +/* TIMER_CREP */ +#define TIMER_CREP_CREP BITS(0,7) /*!< counter repetition value */ + +/* TIMER_CH0CV */ +#define TIMER_CH0CV_CH0VAL BITS(0,15) /*!< 16 bit capture/compare value of channel 0 */ + +/* TIMER_CH1CV */ +#define TIMER_CH1CV_CH1VAL BITS(0,15) /*!< 16 bit capture/compare value of channel 1 */ + +/* TIMER_CH2CV */ +#define TIMER_CH2CV_CH2VAL BITS(0,15) /*!< 16 bit capture/compare value of channel 2 */ + +/* TIMER_CH3CV */ +#define TIMER_CH3CV_CH3VAL BITS(0,15) /*!< 16 bit capture/compare value of channel 3 */ + +/* TIMER_CCHP */ +#define TIMER_CCHP_DTCFG BITS(0,7) /*!< dead time configure */ +#define TIMER_CCHP_PROT BITS(8,9) /*!< complementary register protect control */ +#define TIMER_CCHP_IOS BIT(10) /*!< idle mode off-state configure */ +#define TIMER_CCHP_ROS BIT(11) /*!< run mode off-state configure */ +#define TIMER_CCHP_BRKEN BIT(12) /*!< break enable */ +#define TIMER_CCHP_BRKP BIT(13) /*!< break polarity */ +#define TIMER_CCHP_OAEN BIT(14) /*!< output automatic enable */ +#define TIMER_CCHP_POEN BIT(15) /*!< primary output enable */ + +/* TIMER_DMACFG */ +#define TIMER_DMACFG_DMATA BITS(0,4) /*!< DMA transfer access start address */ +#define TIMER_DMACFG_DMATC BITS(8,12) /*!< DMA transfer count */ + +/* TIMER_DMATB */ +#define TIMER_DMATB_DMATB BITS(0,15) /*!< DMA transfer buffer address */ + +/* TIMER_IRMP */ +#define TIMER10_IRMP_ITI1_RMP BITS(0,1) /*!< TIMER10 internal trigger input 1 remap */ + +/* TIMER_CFG */ +#define TIMER_CFG_OUTSEL BIT(0) /*!< the output value selection */ +#define TIMER_CFG_CHVSEL BIT(1) /*!< write CHxVAL register selection */ + +/* constants definitions */ +/* TIMER init parameter struct definitions*/ +typedef struct +{ + uint16_t prescaler; /*!< prescaler value */ + uint16_t alignedmode; /*!< aligned mode */ + uint16_t counterdirection; /*!< counter direction */ + uint16_t clockdivision; /*!< clock division value */ + uint32_t period; /*!< period value */ + uint8_t repetitioncounter; /*!< the counter repetition value */ +}timer_parameter_struct; + +/* break parameter struct definitions*/ +typedef struct +{ + uint16_t runoffstate; /*!< run mode off-state */ + uint16_t ideloffstate; /*!< idle mode off-state */ + uint16_t deadtime; /*!< dead time */ + uint16_t breakpolarity; /*!< break polarity */ + uint16_t outputautostate; /*!< output automatic enable */ + uint16_t protectmode; /*!< complementary register protect control */ + uint16_t breakstate; /*!< break enable */ +}timer_break_parameter_struct; + +/* channel output parameter struct definitions */ +typedef struct +{ + uint16_t outputstate; /*!< channel output state */ + uint16_t outputnstate; /*!< channel complementary output state */ + uint16_t ocpolarity; /*!< channel output polarity */ + uint16_t ocnpolarity; /*!< channel complementary output polarity */ + uint16_t ocidlestate; /*!< idle state of channel output */ + uint16_t ocnidlestate; /*!< idle state of channel complementary output */ +}timer_oc_parameter_struct; + +/* channel input parameter struct definitions */ +typedef struct +{ + uint16_t icpolarity; /*!< channel input polarity */ + uint16_t icselection; /*!< channel input mode selection */ + uint16_t icprescaler; /*!< channel input capture prescaler */ + uint16_t icfilter; /*!< channel input capture filter control */ +}timer_ic_parameter_struct; + +/* TIMER interrupt enable or disable */ +#define TIMER_INT_UP TIMER_DMAINTEN_UPIE /*!< update interrupt */ +#define TIMER_INT_CH0 TIMER_DMAINTEN_CH0IE /*!< channel 0 interrupt */ +#define TIMER_INT_CH1 TIMER_DMAINTEN_CH1IE /*!< channel 1 interrupt */ +#define TIMER_INT_CH2 TIMER_DMAINTEN_CH2IE /*!< channel 2 interrupt */ +#define TIMER_INT_CH3 TIMER_DMAINTEN_CH3IE /*!< channel 3 interrupt */ +#define TIMER_INT_CMT TIMER_DMAINTEN_CMTIE /*!< channel commutation interrupt flag */ +#define TIMER_INT_TRG TIMER_DMAINTEN_TRGIE /*!< trigger interrupt */ +#define TIMER_INT_BRK TIMER_DMAINTEN_BRKIE /*!< break interrupt */ + +/* TIMER flag */ +#define TIMER_FLAG_UP TIMER_INTF_UPIF /*!< update flag */ +#define TIMER_FLAG_CH0 TIMER_INTF_CH0IF /*!< channel 0 flag */ +#define TIMER_FLAG_CH1 TIMER_INTF_CH1IF /*!< channel 1 flag */ +#define TIMER_FLAG_CH2 TIMER_INTF_CH2IF /*!< channel 2 flag */ +#define TIMER_FLAG_CH3 TIMER_INTF_CH3IF /*!< channel 3 flag */ +#define TIMER_FLAG_CMT TIMER_INTF_CMTIF /*!< channel commutation flag */ +#define TIMER_FLAG_TRG TIMER_INTF_TRGIF /*!< trigger flag */ +#define TIMER_FLAG_BRK TIMER_INTF_BRKIF /*!< break flag */ +#define TIMER_FLAG_CH0O TIMER_INTF_CH0OF /*!< channel 0 overcapture flag */ +#define TIMER_FLAG_CH1O TIMER_INTF_CH1OF /*!< channel 1 overcapture flag */ +#define TIMER_FLAG_CH2O TIMER_INTF_CH2OF /*!< channel 2 overcapture flag */ +#define TIMER_FLAG_CH3O TIMER_INTF_CH3OF /*!< channel 3 overcapture flag */ + +/* TIMER interrupt flag */ +#define TIMER_INT_FLAG_UP TIMER_INTF_UPIF /*!< update interrupt flag */ +#define TIMER_INT_FLAG_CH0 TIMER_INTF_CH0IF /*!< channel 0 interrupt flag */ +#define TIMER_INT_FLAG_CH1 TIMER_INTF_CH1IF /*!< channel 1 interrupt flag */ +#define TIMER_INT_FLAG_CH2 TIMER_INTF_CH2IF /*!< channel 2 interrupt flag */ +#define TIMER_INT_FLAG_CH3 TIMER_INTF_CH3IF /*!< channel 3 interrupt flag */ +#define TIMER_INT_FLAG_CMT TIMER_INTF_CMTIF /*!< channel commutation interrupt flag */ +#define TIMER_INT_FLAG_TRG TIMER_INTF_TRGIF /*!< trigger interrupt flag */ +#define TIMER_INT_FLAG_BRK TIMER_INTF_BRKIF + + + +/* TIMER DMA source enable */ +#define TIMER_DMA_UPD ((uint16_t)TIMER_DMAINTEN_UPDEN) /*!< update DMA enable */ +#define TIMER_DMA_CH0D ((uint16_t)TIMER_DMAINTEN_CH0DEN) /*!< channel 0 DMA enable */ +#define TIMER_DMA_CH1D ((uint16_t)TIMER_DMAINTEN_CH1DEN) /*!< channel 1 DMA enable */ +#define TIMER_DMA_CH2D ((uint16_t)TIMER_DMAINTEN_CH2DEN) /*!< channel 2 DMA enable */ +#define TIMER_DMA_CH3D ((uint16_t)TIMER_DMAINTEN_CH3DEN) /*!< channel 3 DMA enable */ +#define TIMER_DMA_CMTD ((uint16_t)TIMER_DMAINTEN_CMTDEN) /*!< commutation DMA request enable */ +#define TIMER_DMA_TRGD ((uint16_t)TIMER_DMAINTEN_TRGDEN) /*!< trigger DMA enable */ + +/* channel DMA request source selection */ +#define TIMER_DMAREQUEST_UPDATEEVENT ((uint8_t)0x00U) /*!< DMA request of channel y is sent when update event occurs */ +#define TIMER_DMAREQUEST_CHANNELEVENT ((uint8_t)0x01U) /*!< DMA request of channel y is sent when channel y event occurs */ + +/* DMA access base address */ +#define DMACFG_DMATA(regval) (BITS(0, 4) & ((uint32_t)(regval) << 0U)) +#define TIMER_DMACFG_DMATA_CTL0 DMACFG_DMATA(0) /*!< DMA transfer address is TIMER_CTL0 */ +#define TIMER_DMACFG_DMATA_CTL1 DMACFG_DMATA(1) /*!< DMA transfer address is TIMER_CTL1 */ +#define TIMER_DMACFG_DMATA_SMCFG DMACFG_DMATA(2) /*!< DMA transfer address is TIMER_SMCFG */ +#define TIMER_DMACFG_DMATA_DMAINTEN DMACFG_DMATA(3) /*!< DMA transfer address is TIMER_DMAINTEN */ +#define TIMER_DMACFG_DMATA_INTF DMACFG_DMATA(4) /*!< DMA transfer address is TIMER_INTF */ +#define TIMER_DMACFG_DMATA_SWEVG DMACFG_DMATA(5) /*!< DMA transfer address is TIMER_SWEVG */ +#define TIMER_DMACFG_DMATA_CHCTL0 DMACFG_DMATA(6) /*!< DMA transfer address is TIMER_CHCTL0 */ +#define TIMER_DMACFG_DMATA_CHCTL1 DMACFG_DMATA(7) /*!< DMA transfer address is TIMER_CHCTL1 */ +#define TIMER_DMACFG_DMATA_CHCTL2 DMACFG_DMATA(8) /*!< DMA transfer address is TIMER_CHCTL2 */ +#define TIMER_DMACFG_DMATA_CNT DMACFG_DMATA(9) /*!< DMA transfer address is TIMER_CNT */ +#define TIMER_DMACFG_DMATA_PSC DMACFG_DMATA(10) /*!< DMA transfer address is TIMER_PSC */ +#define TIMER_DMACFG_DMATA_CAR DMACFG_DMATA(11) /*!< DMA transfer address is TIMER_CAR */ +#define TIMER_DMACFG_DMATA_CREP DMACFG_DMATA(12) /*!< DMA transfer address is TIMER_CREP */ +#define TIMER_DMACFG_DMATA_CH0CV DMACFG_DMATA(13) /*!< DMA transfer address is TIMER_CH0CV */ +#define TIMER_DMACFG_DMATA_CH1CV DMACFG_DMATA(14) /*!< DMA transfer address is TIMER_CH1CV */ +#define TIMER_DMACFG_DMATA_CH2CV DMACFG_DMATA(15) /*!< DMA transfer address is TIMER_CH2CV */ +#define TIMER_DMACFG_DMATA_CH3CV DMACFG_DMATA(16) /*!< DMA transfer address is TIMER_CH3CV */ +#define TIMER_DMACFG_DMATA_CCHP DMACFG_DMATA(17) /*!< DMA transfer address is TIMER_CCHP */ +#define TIMER_DMACFG_DMATA_DMACFG DMACFG_DMATA(18) /*!< DMA transfer address is TIMER_DMACFG */ +#define TIMER_DMACFG_DMATA_DMATB DMACFG_DMATA(19) /*!< DMA transfer address is TIMER_DMATB */ + +/* DMA access burst length */ +#define DMACFG_DMATC(regval) (BITS(8, 12) & ((uint32_t)(regval) << 8U)) +#define TIMER_DMACFG_DMATC_1TRANSFER DMACFG_DMATC(0) /*!< DMA transfer 1 time */ +#define TIMER_DMACFG_DMATC_2TRANSFER DMACFG_DMATC(1) /*!< DMA transfer 2 times */ +#define TIMER_DMACFG_DMATC_3TRANSFER DMACFG_DMATC(2) /*!< DMA transfer 3 times */ +#define TIMER_DMACFG_DMATC_4TRANSFER DMACFG_DMATC(3) /*!< DMA transfer 4 times */ +#define TIMER_DMACFG_DMATC_5TRANSFER DMACFG_DMATC(4) /*!< DMA transfer 5 times */ +#define TIMER_DMACFG_DMATC_6TRANSFER DMACFG_DMATC(5) /*!< DMA transfer 6 times */ +#define TIMER_DMACFG_DMATC_7TRANSFER DMACFG_DMATC(6) /*!< DMA transfer 7 times */ +#define TIMER_DMACFG_DMATC_8TRANSFER DMACFG_DMATC(7) /*!< DMA transfer 8 times */ +#define TIMER_DMACFG_DMATC_9TRANSFER DMACFG_DMATC(8) /*!< DMA transfer 9 times */ +#define TIMER_DMACFG_DMATC_10TRANSFER DMACFG_DMATC(9) /*!< DMA transfer 10 times */ +#define TIMER_DMACFG_DMATC_11TRANSFER DMACFG_DMATC(10) /*!< DMA transfer 11 times */ +#define TIMER_DMACFG_DMATC_12TRANSFER DMACFG_DMATC(11) /*!< DMA transfer 12 times */ +#define TIMER_DMACFG_DMATC_13TRANSFER DMACFG_DMATC(12) /*!< DMA transfer 13 times */ +#define TIMER_DMACFG_DMATC_14TRANSFER DMACFG_DMATC(13) /*!< DMA transfer 14 times */ +#define TIMER_DMACFG_DMATC_15TRANSFER DMACFG_DMATC(14) /*!< DMA transfer 15 times */ +#define TIMER_DMACFG_DMATC_16TRANSFER DMACFG_DMATC(15) /*!< DMA transfer 16 times */ +#define TIMER_DMACFG_DMATC_17TRANSFER DMACFG_DMATC(16) /*!< DMA transfer 17 times */ +#define TIMER_DMACFG_DMATC_18TRANSFER DMACFG_DMATC(17) /*!< DMA transfer 18 times */ + +/* TIMER software event generation source */ +#define TIMER_EVENT_SRC_UPG ((uint16_t)0x0001U) /*!< update event generation */ +#define TIMER_EVENT_SRC_CH0G ((uint16_t)0x0002U) /*!< channel 0 capture or compare event generation */ +#define TIMER_EVENT_SRC_CH1G ((uint16_t)0x0004U) /*!< channel 1 capture or compare event generation */ +#define TIMER_EVENT_SRC_CH2G ((uint16_t)0x0008U) /*!< channel 2 capture or compare event generation */ +#define TIMER_EVENT_SRC_CH3G ((uint16_t)0x0010U) /*!< channel 3 capture or compare event generation */ +#define TIMER_EVENT_SRC_CMTG ((uint16_t)0x0020U) /*!< channel commutation event generation */ +#define TIMER_EVENT_SRC_TRGG ((uint16_t)0x0040U) /*!< trigger event generation */ +#define TIMER_EVENT_SRC_BRKG ((uint16_t)0x0080U) /*!< break event generation */ + +/* center-aligned mode selection */ +#define CTL0_CAM(regval) ((uint16_t)(BITS(5, 6) & ((uint32_t)(regval) << 5U))) +#define TIMER_COUNTER_EDGE CTL0_CAM(0) /*!< edge-aligned mode */ +#define TIMER_COUNTER_CENTER_DOWN CTL0_CAM(1) /*!< center-aligned and counting down assert mode */ +#define TIMER_COUNTER_CENTER_UP CTL0_CAM(2) /*!< center-aligned and counting up assert mode */ +#define TIMER_COUNTER_CENTER_BOTH CTL0_CAM(3) /*!< center-aligned and counting up/down assert mode */ + +/* TIMER prescaler reload mode */ +#define TIMER_PSC_RELOAD_NOW ((uint32_t)0x00000000U) /*!< the prescaler is loaded right now */ +#define TIMER_PSC_RELOAD_UPDATE ((uint32_t)0x00000001U) /*!< the prescaler is loaded at the next update event */ + +/* count direction */ +#define TIMER_COUNTER_UP ((uint16_t)0x0000U) /*!< counter up direction */ +#define TIMER_COUNTER_DOWN ((uint16_t)TIMER_CTL0_DIR) /*!< counter down direction */ + +/* specify division ratio between TIMER clock and dead-time and sampling clock */ +#define CTL0_CKDIV(regval) ((uint16_t)(BITS(8, 9) & ((uint32_t)(regval) << 8U))) +#define TIMER_CKDIV_DIV1 CTL0_CKDIV(0) /*!< clock division value is 1,fDTS=fTIMER_CK */ +#define TIMER_CKDIV_DIV2 CTL0_CKDIV(1) /*!< clock division value is 2,fDTS= fTIMER_CK/2 */ +#define TIMER_CKDIV_DIV4 CTL0_CKDIV(2) /*!< clock division value is 4, fDTS= fTIMER_CK/4 */ + +/* single pulse mode */ +#define TIMER_SP_MODE_SINGLE ((uint32_t)0x00000000U) /*!< single pulse mode */ +#define TIMER_SP_MODE_REPETITIVE ((uint32_t)0x00000001U) /*!< repetitive pulse mode */ + +/* update source */ +#define TIMER_UPDATE_SRC_REGULAR ((uint32_t)0x00000000U) /*!< update generate only by counter overflow/underflow */ +#define TIMER_UPDATE_SRC_GLOBAL ((uint32_t)0x00000001U) /*!< update generate by setting of UPG bit or the counter overflow/underflow,or the slave mode controller trigger */ + +/* run mode off-state configure */ +#define TIMER_ROS_STATE_ENABLE ((uint16_t)TIMER_CCHP_ROS) /*!< when POEN bit is set, the channel output signals (CHx_O/CHx_ON) are enabled, with relationship to CHxEN/CHxNEN bits */ +#define TIMER_ROS_STATE_DISABLE ((uint16_t)0x0000U) /*!< when POEN bit is set, the channel output signals (CHx_O/CHx_ON) are disabled */ + +/* idle mode off-state configure */ +#define TIMER_IOS_STATE_ENABLE ((uint16_t)TIMER_CCHP_IOS) /*!< when POEN bit is reset, he channel output signals (CHx_O/CHx_ON) are enabled, with relationship to CHxEN/CHxNEN bits */ +#define TIMER_IOS_STATE_DISABLE ((uint16_t)0x0000U) /*!< when POEN bit is reset, the channel output signals (CHx_O/CHx_ON) are disabled */ + +/* break input polarity */ +#define TIMER_BREAK_POLARITY_LOW ((uint16_t)0x0000U) /*!< break input polarity is low */ +#define TIMER_BREAK_POLARITY_HIGH ((uint16_t)TIMER_CCHP_BRKP) /*!< break input polarity is high */ + +/* output automatic enable */ +#define TIMER_OUTAUTO_ENABLE ((uint16_t)TIMER_CCHP_OAEN) /*!< output automatic enable */ +#define TIMER_OUTAUTO_DISABLE ((uint16_t)0x0000U) /*!< output automatic disable */ + +/* complementary register protect control */ +#define CCHP_PROT(regval) ((uint16_t)(BITS(8, 9) & ((uint32_t)(regval) << 8U))) +#define TIMER_CCHP_PROT_OFF CCHP_PROT(0) /*!< protect disable */ +#define TIMER_CCHP_PROT_0 CCHP_PROT(1) /*!< PROT mode 0 */ +#define TIMER_CCHP_PROT_1 CCHP_PROT(2) /*!< PROT mode 1 */ +#define TIMER_CCHP_PROT_2 CCHP_PROT(3) /*!< PROT mode 2 */ + +/* break input enable */ +#define TIMER_BREAK_ENABLE ((uint16_t)TIMER_CCHP_BRKEN) /*!< break input enable */ +#define TIMER_BREAK_DISABLE ((uint16_t)0x0000U) /*!< break input disable */ + +/* TIMER channel n(n=0,1,2,3) */ +#define TIMER_CH_0 ((uint16_t)0x0000U) /*!< TIMER channel 0(TIMERx(x=0..4,7..13)) */ +#define TIMER_CH_1 ((uint16_t)0x0001U) /*!< TIMER channel 1(TIMERx(x=0..4,7,8,11)) */ +#define TIMER_CH_2 ((uint16_t)0x0002U) /*!< TIMER channel 2(TIMERx(x=0..4,7)) */ +#define TIMER_CH_3 ((uint16_t)0x0003U) /*!< TIMER channel 3(TIMERx(x=0..4,7)) */ + +/* channel enable state*/ +#define TIMER_CCX_ENABLE ((uint32_t)0x00000001U) /*!< channel enable */ +#define TIMER_CCX_DISABLE ((uint32_t)0x00000000U) /*!< channel disable */ + +/* channel complementary output enable state*/ +#define TIMER_CCXN_ENABLE ((uint16_t)0x0004U) /*!< channel complementary enable */ +#define TIMER_CCXN_DISABLE ((uint16_t)0x0000U) /*!< channel complementary disable */ + +/* channel output polarity */ +#define TIMER_OC_POLARITY_HIGH ((uint16_t)0x0000U) /*!< channel output polarity is high */ +#define TIMER_OC_POLARITY_LOW ((uint16_t)0x0002U) /*!< channel output polarity is low */ + +/* channel complementary output polarity */ +#define TIMER_OCN_POLARITY_HIGH ((uint16_t)0x0000U) /*!< channel complementary output polarity is high */ +#define TIMER_OCN_POLARITY_LOW ((uint16_t)0x0008U) /*!< channel complementary output polarity is low */ + +/* idle state of channel output */ +#define TIMER_OC_IDLE_STATE_HIGH ((uint16_t)0x0100) /*!< idle state of channel output is high */ +#define TIMER_OC_IDLE_STATE_LOW ((uint16_t)0x0000) /*!< idle state of channel output is low */ + +/* idle state of channel complementary output */ +#define TIMER_OCN_IDLE_STATE_HIGH ((uint16_t)0x0200U) /*!< idle state of channel complementary output is high */ +#define TIMER_OCN_IDLE_STATE_LOW ((uint16_t)0x0000U) /*!< idle state of channel complementary output is low */ + +/* channel output compare mode */ +#define TIMER_OC_MODE_TIMING ((uint16_t)0x0000U) /*!< timing mode */ +#define TIMER_OC_MODE_ACTIVE ((uint16_t)0x0010U) /*!< active mode */ +#define TIMER_OC_MODE_INACTIVE ((uint16_t)0x0020U) /*!< inactive mode */ +#define TIMER_OC_MODE_TOGGLE ((uint16_t)0x0030U) /*!< toggle mode */ +#define TIMER_OC_MODE_LOW ((uint16_t)0x0040U) /*!< force low mode */ +#define TIMER_OC_MODE_HIGH ((uint16_t)0x0050U) /*!< force high mode */ +#define TIMER_OC_MODE_PWM0 ((uint16_t)0x0060U) /*!< PWM0 mode */ +#define TIMER_OC_MODE_PWM1 ((uint16_t)0x0070U) /*!< PWM1 mode*/ + +/* channel output compare shadow enable */ +#define TIMER_OC_SHADOW_ENABLE ((uint16_t)0x0008U) /*!< channel output shadow state enable */ +#define TIMER_OC_SHADOW_DISABLE ((uint16_t)0x0000U) /*!< channel output shadow state disable */ + +/* channel output compare fast enable */ +#define TIMER_OC_FAST_ENABLE ((uint16_t)0x0004) /*!< channel output fast function enable */ +#define TIMER_OC_FAST_DISABLE ((uint16_t)0x0000) /*!< channel output fast function disable */ + +/* channel output compare clear enable */ +#define TIMER_OC_CLEAR_ENABLE ((uint16_t)0x0080U) /*!< channel output clear function enable */ +#define TIMER_OC_CLEAR_DISABLE ((uint16_t)0x0000U) /*!< channel output clear function disable */ + +/* channel control shadow register update control */ +#define TIMER_UPDATECTL_CCU ((uint32_t)0x00000000U) /*!< the shadow registers are updated when CMTG bit is set */ +#define TIMER_UPDATECTL_CCUTRI ((uint32_t)0x00000001U) /*!< the shadow registers update by when CMTG bit is set or an rising edge of TRGI occurs */ + +/* channel input capture polarity */ +#define TIMER_IC_POLARITY_RISING ((uint16_t)0x0000U) /*!< input capture rising edge */ +#define TIMER_IC_POLARITY_FALLING ((uint16_t)0x0002U) /*!< input capture falling edge */ + +/* TIMER input capture selection */ +#define TIMER_IC_SELECTION_DIRECTTI ((uint16_t)0x0001U) /*!< channel y is configured as input and icy is mapped on CIy */ +#define TIMER_IC_SELECTION_INDIRECTTI ((uint16_t)0x0002U) /*!< channel y is configured as input and icy is mapped on opposite input */ +#define TIMER_IC_SELECTION_ITS ((uint16_t)0x0003U) /*!< channel y is configured as input and icy is mapped on ITS */ + +/* channel input capture prescaler */ +#define TIMER_IC_PSC_DIV1 ((uint16_t)0x0000U) /*!< no prescaler */ +#define TIMER_IC_PSC_DIV2 ((uint16_t)0x0004U) /*!< divided by 2 */ +#define TIMER_IC_PSC_DIV4 ((uint16_t)0x0008U) /*!< divided by 4*/ +#define TIMER_IC_PSC_DIV8 ((uint16_t)0x000CU) /*!< divided by 8 */ + +/* trigger selection */ +#define SMCFG_TRGSEL(regval) (BITS(4, 6) & ((uint32_t)(regval) << 4U)) +#define TIMER_SMCFG_TRGSEL_ITI0 SMCFG_TRGSEL(0) /*!< internal trigger 0 */ +#define TIMER_SMCFG_TRGSEL_ITI1 SMCFG_TRGSEL(1) /*!< internal trigger 1 */ +#define TIMER_SMCFG_TRGSEL_ITI2 SMCFG_TRGSEL(2) /*!< internal trigger 2 */ +#define TIMER_SMCFG_TRGSEL_ITI3 SMCFG_TRGSEL(3) /*!< internal trigger 3 */ +#define TIMER_SMCFG_TRGSEL_CI0F_ED SMCFG_TRGSEL(4) /*!< TI0 Edge Detector */ +#define TIMER_SMCFG_TRGSEL_CI0FE0 SMCFG_TRGSEL(5) /*!< filtered TIMER input 0 */ +#define TIMER_SMCFG_TRGSEL_CI1FE1 SMCFG_TRGSEL(6) /*!< filtered TIMER input 1 */ +#define TIMER_SMCFG_TRGSEL_ETIFP SMCFG_TRGSEL(7) /*!< external trigger */ + +/* master mode control */ +#define CTL1_MMC(regval) (BITS(4, 6) & ((uint32_t)(regval) << 4U)) +#define TIMER_TRI_OUT_SRC_RESET CTL1_MMC(0) /*!< the UPG bit as trigger output */ +#define TIMER_TRI_OUT_SRC_ENABLE CTL1_MMC(1) /*!< the counter enable signal TIMER_CTL0_CEN as trigger output */ +#define TIMER_TRI_OUT_SRC_UPDATE CTL1_MMC(2) /*!< update event as trigger output */ +#define TIMER_TRI_OUT_SRC_CH0 CTL1_MMC(3) /*!< a capture or a compare match occurred in channal0 as trigger output TRGO */ +#define TIMER_TRI_OUT_SRC_O0CPRE CTL1_MMC(4) /*!< O0CPRE as trigger output */ +#define TIMER_TRI_OUT_SRC_O1CPRE CTL1_MMC(5) /*!< O1CPRE as trigger output */ +#define TIMER_TRI_OUT_SRC_O2CPRE CTL1_MMC(6) /*!< O2CPRE as trigger output */ +#define TIMER_TRI_OUT_SRC_O3CPRE CTL1_MMC(7) /*!< O3CPRE as trigger output */ + +/* slave mode control */ +#define SMCFG_SMC(regval) (BITS(0, 2) & ((uint32_t)(regval) << 0U)) +#define TIMER_SLAVE_MODE_DISABLE SMCFG_SMC(0) /*!< slave mode disable */ +#define TIMER_ENCODER_MODE0 SMCFG_SMC(1) /*!< encoder mode 0 */ +#define TIMER_ENCODER_MODE1 SMCFG_SMC(2) /*!< encoder mode 1 */ +#define TIMER_ENCODER_MODE2 SMCFG_SMC(3) /*!< encoder mode 2 */ +#define TIMER_SLAVE_MODE_RESTART SMCFG_SMC(4) /*!< restart mode */ +#define TIMER_SLAVE_MODE_PAUSE SMCFG_SMC(5) /*!< pause mode */ +#define TIMER_SLAVE_MODE_EVENT SMCFG_SMC(6) /*!< event mode */ +#define TIMER_SLAVE_MODE_EXTERNAL0 SMCFG_SMC(7) /*!< external clock mode 0 */ + +/* master slave mode selection */ +#define TIMER_MASTER_SLAVE_MODE_ENABLE ((uint32_t)0x00000000U) /*!< master slave mode enable */ +#define TIMER_MASTER_SLAVE_MODE_DISABLE ((uint32_t)0x00000001U) /*!< master slave mode disable */ + +/* external trigger prescaler */ +#define SMCFG_ETPSC(regval) (BITS(12, 13) & ((uint32_t)(regval) << 12U)) +#define TIMER_EXT_TRI_PSC_OFF SMCFG_ETPSC(0) /*!< no divided */ +#define TIMER_EXT_TRI_PSC_DIV2 SMCFG_ETPSC(1) /*!< divided by 2 */ +#define TIMER_EXT_TRI_PSC_DIV4 SMCFG_ETPSC(2) /*!< divided by 4 */ +#define TIMER_EXT_TRI_PSC_DIV8 SMCFG_ETPSC(3) /*!< divided by 8 */ + +/* external trigger polarity */ +#define TIMER_ETP_FALLING TIMER_SMCFG_ETP /*!< active low or falling edge active */ +#define TIMER_ETP_RISING ((uint32_t)0x00000000U) /*!< active high or rising edge active */ + +/* channel 0 trigger input selection */ +#define TIMER_HALLINTERFACE_ENABLE ((uint32_t)0x00000000U) /*!< TIMER hall sensor mode enable */ +#define TIMER_HALLINTERFACE_DISABLE ((uint32_t)0x00000001U) /*!< TIMER hall sensor mode disable */ + +/* TIMERx(x=0,1,2,13,14,15,16) write cc register selection */ +#define TIMER_CHVSEL_ENABLE ((uint16_t)0x0002U) /*!< write CHxVAL register selection enable */ +#define TIMER_CHVSEL_DISABLE ((uint16_t)0x0000U) /*!< write CHxVAL register selection disable */ + +/* the output value selection */ +#define TIMER_OUTSEL_ENABLE ((uint16_t)0x0001U) /*!< output value selection enable */ +#define TIMER_OUTSEL_DISABLE ((uint16_t)0x0000U) /*!< output value selection disable */ + + +/* function declarations */ +/* TIMER timebase */ +/* deinit a TIMER */ +void timer_deinit(uint32_t timer_periph); +/* initialize TIMER init parameter struct */ +void timer_struct_para_init(timer_parameter_struct* initpara); +/* initialize TIMER counter */ +void timer_init(uint32_t timer_periph, timer_parameter_struct* initpara); +/* enable a TIMER */ +void timer_enable(uint32_t timer_periph); +/* disable a TIMER */ +void timer_disable(uint32_t timer_periph); +/* enable the auto reload shadow function */ +void timer_auto_reload_shadow_enable(uint32_t timer_periph); +/* disable the auto reload shadow function */ +void timer_auto_reload_shadow_disable(uint32_t timer_periph); +/* enable the update event */ +void timer_update_event_enable(uint32_t timer_periph); +/* disable the update event */ +void timer_update_event_disable(uint32_t timer_periph); +/* set TIMER counter alignment mode */ +void timer_counter_alignment(uint32_t timer_periph, uint16_t aligned); +/* set TIMER counter up direction */ +void timer_counter_up_direction(uint32_t timer_periph); +/* set TIMER counter down direction */ +void timer_counter_down_direction(uint32_t timer_periph); +/* configure TIMER prescaler */ +void timer_prescaler_config(uint32_t timer_periph, uint16_t prescaler, uint8_t pscreload); +/* configure TIMER repetition register value */ +void timer_repetition_value_config(uint32_t timer_periph, uint16_t repetition); +/* configure TIMER autoreload register value */ +void timer_autoreload_value_config(uint32_t timer_periph, uint16_t autoreload); +/* configure TIMER counter register value */ +void timer_counter_value_config(uint32_t timer_periph , uint16_t counter); +/* read TIMER counter value */ +uint32_t timer_counter_read(uint32_t timer_periph); +/* read TIMER prescaler value */ +uint16_t timer_prescaler_read(uint32_t timer_periph); +/* configure TIMER single pulse mode */ +void timer_single_pulse_mode_config(uint32_t timer_periph, uint32_t spmode); +/* configure TIMER update source */ +void timer_update_source_config(uint32_t timer_periph, uint32_t update); + +/* TIMER interrupt and flag*/ +/* enable the TIMER interrupt */ +void timer_interrupt_enable(uint32_t timer_periph, uint32_t interrupt); +/* disable the TIMER interrupt */ +void timer_interrupt_disable(uint32_t timer_periph, uint32_t interrupt); +/* get timer interrupt flag */ +FlagStatus timer_interrupt_flag_get(uint32_t timer_periph, uint32_t interrupt); +/* clear TIMER interrupt flag */ +void timer_interrupt_flag_clear(uint32_t timer_periph, uint32_t interrupt); +/* get TIMER flags */ +FlagStatus timer_flag_get(uint32_t timer_periph, uint32_t flag); +/* clear TIMER flags */ +void timer_flag_clear(uint32_t timer_periph, uint32_t flag); + +/* timer DMA and event*/ +/* enable the TIMER DMA */ +void timer_dma_enable(uint32_t timer_periph, uint16_t dma); +/* disable the TIMER DMA */ +void timer_dma_disable(uint32_t timer_periph, uint16_t dma); +/* channel DMA request source selection */ +void timer_channel_dma_request_source_select(uint32_t timer_periph, uint8_t dma_request); +/* configure the TIMER DMA transfer */ +void timer_dma_transfer_config(uint32_t timer_periph,uint32_t dma_baseaddr, uint32_t dma_lenth); +/* software generate events */ +void timer_event_software_generate(uint32_t timer_periph, uint16_t event); + +/* TIMER channel complementary protection */ +/* initialize TIMER break parameter struct */ +void timer_break_struct_para_init(timer_break_parameter_struct* breakpara); +/* configure TIMER break function */ +void timer_break_config(uint32_t timer_periph, timer_break_parameter_struct* breakpara); +/* enable TIMER break function */ +void timer_break_enable(uint32_t timer_periph); +/* disable TIMER break function */ +void timer_break_disable(uint32_t timer_periph); +/* enable TIMER output automatic function */ +void timer_automatic_output_enable(uint32_t timer_periph); +/* disable TIMER output automatic function */ +void timer_automatic_output_disable(uint32_t timer_periph); +/* enable or disable TIMER primary output function */ +void timer_primary_output_config(uint32_t timer_periph, ControlStatus newvalue); +/* enable or disable channel capture/compare control shadow register */ +void timer_channel_control_shadow_config(uint32_t timer_periph, ControlStatus newvalue); +/* configure TIMER channel control shadow register update control */ +void timer_channel_control_shadow_update_config(uint32_t timer_periph, uint8_t ccuctl); + +/* TIMER channel output */ +/* initialize TIMER channel output parameter struct */ +void timer_channel_output_struct_para_init(timer_oc_parameter_struct* ocpara); +/* configure TIMER channel output function */ +void timer_channel_output_config(uint32_t timer_periph,uint16_t channel, timer_oc_parameter_struct* ocpara); +/* configure TIMER channel output compare mode */ +void timer_channel_output_mode_config(uint32_t timer_periph, uint16_t channel,uint16_t ocmode); +/* configure TIMER channel output pulse value */ +void timer_channel_output_pulse_value_config(uint32_t timer_periph, uint16_t channel, uint32_t pulse); +/* configure TIMER channel output shadow function */ +void timer_channel_output_shadow_config(uint32_t timer_periph, uint16_t channel, uint16_t ocshadow); +/* configure TIMER channel output fast function */ +void timer_channel_output_fast_config(uint32_t timer_periph, uint16_t channel, uint16_t ocfast); +/* configure TIMER channel output clear function */ +void timer_channel_output_clear_config(uint32_t timer_periph,uint16_t channel,uint16_t occlear); +/* configure TIMER channel output polarity */ +void timer_channel_output_polarity_config(uint32_t timer_periph, uint16_t channel, uint16_t ocpolarity); +/* configure TIMER channel complementary output polarity */ +void timer_channel_complementary_output_polarity_config(uint32_t timer_periph, uint16_t channel, uint16_t ocnpolarity); +/* configure TIMER channel enable state */ +void timer_channel_output_state_config(uint32_t timer_periph, uint16_t channel, uint32_t state); +/* configure TIMER channel complementary output enable state */ +void timer_channel_complementary_output_state_config(uint32_t timer_periph, uint16_t channel, uint16_t ocnstate); + +/* TIMER channel input */ +/* initialize TIMER channel input parameter struct */ +void timer_channel_input_struct_para_init(timer_ic_parameter_struct* icpara); +/* configure TIMER input capture parameter */ +void timer_input_capture_config(uint32_t timer_periph, uint16_t channel, timer_ic_parameter_struct* icpara); +/* configure TIMER channel input capture prescaler value */ +void timer_channel_input_capture_prescaler_config(uint32_t timer_periph, uint16_t channel, uint16_t prescaler); +/* read TIMER channel capture compare register value */ +uint32_t timer_channel_capture_value_register_read(uint32_t timer_periph, uint16_t channel); +/* configure TIMER input pwm capture function */ +void timer_input_pwm_capture_config(uint32_t timer_periph, uint16_t channel, timer_ic_parameter_struct* icpwm); +/* configure TIMER hall sensor mode */ +void timer_hall_mode_config(uint32_t timer_periph, uint32_t hallmode); + +/* TIMER master and slave */ +/* select TIMER input trigger source */ +void timer_input_trigger_source_select(uint32_t timer_periph, uint32_t intrigger); +/* select TIMER master mode output trigger source */ +void timer_master_output_trigger_source_select(uint32_t timer_periph, uint32_t outrigger); +/* select TIMER slave mode */ +void timer_slave_mode_select(uint32_t timer_periph,uint32_t slavemode); +/* configure TIMER master slave mode */ +void timer_master_slave_mode_config(uint32_t timer_periph, uint32_t masterslave); +/* configure TIMER external trigger input */ +void timer_external_trigger_config(uint32_t timer_periph, uint32_t extprescaler, uint32_t extpolarity, uint32_t extfilter); +/* configure TIMER quadrature decoder mode */ +void timer_quadrature_decoder_mode_config(uint32_t timer_periph, uint32_t decomode, uint16_t ic0polarity, uint16_t ic1polarity); +/* configure TIMER internal clock mode */ +void timer_internal_clock_config(uint32_t timer_periph); +/* configure TIMER the internal trigger as external clock input */ +void timer_internal_trigger_as_external_clock_config(uint32_t timer_periph, uint32_t intrigger); +/* configure TIMER the external trigger as external clock input */ +void timer_external_trigger_as_external_clock_config(uint32_t timer_periph, uint32_t extrigger, uint16_t extpolarity,uint32_t extfilter); +/* configure TIMER the external clock mode 0 */ +void timer_external_clock_mode0_config(uint32_t timer_periph, uint32_t extprescaler, uint32_t extpolarity, uint32_t extfilter); +/* configure TIMER the external clock mode 1 */ +void timer_external_clock_mode1_config(uint32_t timer_periph, uint32_t extprescaler, uint32_t extpolarity, uint32_t extfilter); +/* disable TIMER the external clock mode 1 */ +void timer_external_clock_mode1_disable(uint32_t timer_periph); + +/* TIMER configure */ +/* configure TIMER write CHxVAL register selection */ +void timer_write_chxval_register_config(uint32_t timer_periph, uint16_t ccsel); +/* configure TIMER output value selection */ +void timer_output_value_selection_config(uint32_t timer_periph, uint16_t outsel); + +#endif /* GD32F30X_TIMER_H */ diff --git a/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_standard_peripheral/Include/gd32f30x_usart.h b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_standard_peripheral/Include/gd32f30x_usart.h new file mode 100644 index 0000000000..2443676318 --- /dev/null +++ b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_standard_peripheral/Include/gd32f30x_usart.h @@ -0,0 +1,444 @@ +/*! + \file gd32f30x_usart.h + \brief definitions for the USART + + \version 2017-02-10, V1.0.0, firmware for GD32F30x + \version 2018-10-10, V1.1.0, firmware for GD32F30x + \version 2018-12-25, V2.0.0, firmware for GD32F30x + \version 2020-09-30, V2.1.0, firmware for GD32F30x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef GD32F30X_USART_H +#define GD32F30X_USART_H + +#include "gd32f30x.h" + +/* USARTx(x=0,1,2)/UARTx(x=3,4) definitions */ +#define USART1 USART_BASE /*!< USART1 base address */ +#define USART2 (USART_BASE+0x00000400U) /*!< USART2 base address */ +#define UART3 (USART_BASE+0x00000800U) /*!< UART3 base address */ +#define UART4 (USART_BASE+0x00000C00U) /*!< UART4 base address */ +#define USART0 (USART_BASE+0x0000F400U) /*!< USART0 base address */ + +/* registers definitions */ +#define USART_STAT0(usartx) REG32((usartx) + 0x00U) /*!< USART status register 0 */ +#define USART_DATA(usartx) REG32((usartx) + 0x04U) /*!< USART data register */ +#define USART_BAUD(usartx) REG32((usartx) + 0x08U) /*!< USART baud rate register */ +#define USART_CTL0(usartx) REG32((usartx) + 0x0CU) /*!< USART control register 0 */ +#define USART_CTL1(usartx) REG32((usartx) + 0x10U) /*!< USART control register 1 */ +#define USART_CTL2(usartx) REG32((usartx) + 0x14U) /*!< USART control register 2 */ +#define USART_GP(usartx) REG32((usartx) + 0x18U) /*!< USART guard time and prescaler register */ +#define USART_CTL3(usartx) REG32((usartx) + 0x80U) /*!< USART control register 3 */ +#define USART_RT(usartx) REG32((usartx) + 0x84U) /*!< USART receiver timeout register */ +#define USART_STAT1(usartx) REG32((usartx) + 0x88U) /*!< USART status register 1 */ + +/* bits definitions */ +/* USARTx_STAT0 */ +#define USART_STAT0_PERR BIT(0) /*!< parity error flag */ +#define USART_STAT0_FERR BIT(1) /*!< frame error flag */ +#define USART_STAT0_NERR BIT(2) /*!< noise error flag */ +#define USART_STAT0_ORERR BIT(3) /*!< overrun error */ +#define USART_STAT0_IDLEF BIT(4) /*!< IDLE frame detected flag */ +#define USART_STAT0_RBNE BIT(5) /*!< read data buffer not empty */ +#define USART_STAT0_TC BIT(6) /*!< transmission complete */ +#define USART_STAT0_TBE BIT(7) /*!< transmit data buffer empty */ +#define USART_STAT0_LBDF BIT(8) /*!< LIN break detected flag */ +#define USART_STAT0_CTSF BIT(9) /*!< CTS change flag */ + +/* USARTx_DATA */ +#define USART_DATA_DATA BITS(0,8) /*!< transmit or read data value */ + +/* USARTx_BAUD */ +#define USART_BAUD_FRADIV BITS(0,3) /*!< fraction part of baud-rate divider */ +#define USART_BAUD_INTDIV BITS(4,15) /*!< integer part of baud-rate divider */ + +/* USARTx_CTL0 */ +#define USART_CTL0_SBKCMD BIT(0) /*!< send break command */ +#define USART_CTL0_RWU BIT(1) /*!< receiver wakeup from mute mode */ +#define USART_CTL0_REN BIT(2) /*!< receiver enable */ +#define USART_CTL0_TEN BIT(3) /*!< transmitter enable */ +#define USART_CTL0_IDLEIE BIT(4) /*!< idle line detected interrupt enable */ +#define USART_CTL0_RBNEIE BIT(5) /*!< read data buffer not empty interrupt and overrun error interrupt enable */ +#define USART_CTL0_TCIE BIT(6) /*!< transmission complete interrupt enable */ +#define USART_CTL0_TBEIE BIT(7) /*!< transmitter buffer empty interrupt enable */ +#define USART_CTL0_PERRIE BIT(8) /*!< parity error interrupt enable */ +#define USART_CTL0_PM BIT(9) /*!< parity mode */ +#define USART_CTL0_PCEN BIT(10) /*!< parity check function enable */ +#define USART_CTL0_WM BIT(11) /*!< wakeup method in mute mode */ +#define USART_CTL0_WL BIT(12) /*!< word length */ +#define USART_CTL0_UEN BIT(13) /*!< USART enable */ + +/* USARTx_CTL1 */ +#define USART_CTL1_ADDR BITS(0,3) /*!< address of USART */ +#define USART_CTL1_LBLEN BIT(5) /*!< LIN break frame length */ +#define USART_CTL1_LBDIE BIT(6) /*!< LIN break detected interrupt eanble */ +#define USART_CTL1_CLEN BIT(8) /*!< CK length */ +#define USART_CTL1_CPH BIT(9) /*!< CK phase */ +#define USART_CTL1_CPL BIT(10) /*!< CK polarity */ +#define USART_CTL1_CKEN BIT(11) /*!< CK pin enable */ +#define USART_CTL1_STB BITS(12,13) /*!< STOP bits length */ +#define USART_CTL1_LMEN BIT(14) /*!< LIN mode enable */ + +/* USARTx_CTL2 */ +#define USART_CTL2_ERRIE BIT(0) /*!< error interrupt enable */ +#define USART_CTL2_IREN BIT(1) /*!< IrDA mode enable */ +#define USART_CTL2_IRLP BIT(2) /*!< IrDA low-power */ +#define USART_CTL2_HDEN BIT(3) /*!< half-duplex enable */ +#define USART_CTL2_NKEN BIT(4) /*!< NACK enable in smartcard mode */ +#define USART_CTL2_SCEN BIT(5) /*!< smartcard mode enable */ +#define USART_CTL2_DENR BIT(6) /*!< DMA request enable for reception */ +#define USART_CTL2_DENT BIT(7) /*!< DMA request enable for transmission */ +#define USART_CTL2_RTSEN BIT(8) /*!< RTS enable */ +#define USART_CTL2_CTSEN BIT(9) /*!< CTS enable */ +#define USART_CTL2_CTSIE BIT(10) /*!< CTS interrupt enable */ + +/* USARTx_GP */ +#define USART_GP_PSC BITS(0,7) /*!< prescaler value for dividing the system clock */ +#define USART_GP_GUAT BITS(8,15) /*!< guard time value in smartcard mode */ + +/* USARTx_CTL3 */ +#define USART_CTL3_RTEN BIT(0) /*!< receiver timeout enable */ +#define USART_CTL3_SCRTNUM BITS(1,3) /*!< smartcard auto-retry number */ +#define USART_CTL3_RTIE BIT(4) /*!< interrupt enable bit of receive timeout event */ +#define USART_CTL3_EBIE BIT(5) /*!< interrupt enable bit of end of block event */ +#define USART_CTL3_RINV BIT(8) /*!< RX pin level inversion */ +#define USART_CTL3_TINV BIT(9) /*!< TX pin level inversion */ +#define USART_CTL3_DINV BIT(10) /*!< data bit level inversion */ +#define USART_CTL3_MSBF BIT(11) /*!< most significant bit first */ + +/* USARTx_RT */ +#define USART_RT_RT BITS(0,23) /*!< receiver timeout threshold */ +#define USART_RT_BL BITS(24,31) /*!< block length */ + +/* USARTx_STAT1 */ +#define USART_STAT1_RTF BIT(11) /*!< receiver timeout flag */ +#define USART_STAT1_EBF BIT(12) /*!< end of block flag */ +#define USART_STAT1_BSY BIT(16) /*!< busy flag */ + +/* constants definitions */ +/* define the USART bit position and its register index offset */ +#define USART_REGIDX_BIT(regidx, bitpos) (((uint32_t)(regidx) << 6) | (uint32_t)(bitpos)) +#define USART_REG_VAL(usartx, offset) (REG32((usartx) + (((uint32_t)(offset) & 0xFFFFU) >> 6))) +#define USART_BIT_POS(val) ((uint32_t)(val) & 0x1FU) +#define USART_REGIDX_BIT2(regidx, bitpos, regidx2, bitpos2) (((uint32_t)(regidx2) << 22) | (uint32_t)((bitpos2) << 16)\ + | (((uint32_t)(regidx) << 6) | (uint32_t)(bitpos))) +#define USART_REG_VAL2(usartx, offset) (REG32((usartx) + ((uint32_t)(offset) >> 22))) +#define USART_BIT_POS2(val) (((uint32_t)(val) & 0x1F0000U) >> 16) + +/* register offset */ +#define USART_STAT0_REG_OFFSET 0x00U /*!< STAT0 register offset */ +#define USART_STAT1_REG_OFFSET 0x88U /*!< STAT1 register offset */ +#define USART_CTL0_REG_OFFSET 0x0CU /*!< CTL0 register offset */ +#define USART_CTL1_REG_OFFSET 0x10U /*!< CTL1 register offset */ +#define USART_CTL2_REG_OFFSET 0x14U /*!< CTL2 register offset */ +#define USART_CTL3_REG_OFFSET 0x80U /*!< CTL3 register offset */ + +/* USART flags */ +typedef enum +{ + /* flags in STAT0 register */ + USART_FLAG_CTS = USART_REGIDX_BIT(USART_STAT0_REG_OFFSET, 9U), /*!< CTS change flag */ + USART_FLAG_LBD = USART_REGIDX_BIT(USART_STAT0_REG_OFFSET, 8U), /*!< LIN break detected flag */ + USART_FLAG_TBE = USART_REGIDX_BIT(USART_STAT0_REG_OFFSET, 7U), /*!< transmit data buffer empty */ + USART_FLAG_TC = USART_REGIDX_BIT(USART_STAT0_REG_OFFSET, 6U), /*!< transmission complete */ + USART_FLAG_RBNE = USART_REGIDX_BIT(USART_STAT0_REG_OFFSET, 5U), /*!< read data buffer not empty */ + USART_FLAG_IDLE = USART_REGIDX_BIT(USART_STAT0_REG_OFFSET, 4U), /*!< IDLE frame detected flag */ + USART_FLAG_ORERR = USART_REGIDX_BIT(USART_STAT0_REG_OFFSET, 3U), /*!< overrun error */ + USART_FLAG_NERR = USART_REGIDX_BIT(USART_STAT0_REG_OFFSET, 2U), /*!< noise error flag */ + USART_FLAG_FERR = USART_REGIDX_BIT(USART_STAT0_REG_OFFSET, 1U), /*!< frame error flag */ + USART_FLAG_PERR = USART_REGIDX_BIT(USART_STAT0_REG_OFFSET, 0U), /*!< parity error flag */ + /* flags in STAT1 register */ + USART_FLAG_BSY = USART_REGIDX_BIT(USART_STAT1_REG_OFFSET, 16U), /*!< busy flag */ + USART_FLAG_EB = USART_REGIDX_BIT(USART_STAT1_REG_OFFSET, 12U), /*!< end of block flag */ + USART_FLAG_RT = USART_REGIDX_BIT(USART_STAT1_REG_OFFSET, 11U), /*!< receiver timeout flag */ +}usart_flag_enum; + +/* USART interrupt flags */ +typedef enum +{ + /* interrupt flags in CTL0 register */ + USART_INT_FLAG_PERR = USART_REGIDX_BIT2(USART_CTL0_REG_OFFSET, 8U, USART_STAT0_REG_OFFSET, 0U), /*!< parity error interrupt and flag */ + USART_INT_FLAG_TBE = USART_REGIDX_BIT2(USART_CTL0_REG_OFFSET, 7U, USART_STAT0_REG_OFFSET, 7U), /*!< transmitter buffer empty interrupt and flag */ + USART_INT_FLAG_TC = USART_REGIDX_BIT2(USART_CTL0_REG_OFFSET, 6U, USART_STAT0_REG_OFFSET, 6U), /*!< transmission complete interrupt and flag */ + USART_INT_FLAG_RBNE = USART_REGIDX_BIT2(USART_CTL0_REG_OFFSET, 5U, USART_STAT0_REG_OFFSET, 5U), /*!< read data buffer not empty interrupt and flag */ + USART_INT_FLAG_RBNE_ORERR = USART_REGIDX_BIT2(USART_CTL0_REG_OFFSET, 5U, USART_STAT0_REG_OFFSET, 3U), /*!< read data buffer not empty interrupt and overrun error flag */ + USART_INT_FLAG_IDLE = USART_REGIDX_BIT2(USART_CTL0_REG_OFFSET, 4U, USART_STAT0_REG_OFFSET, 4U), /*!< IDLE line detected interrupt and flag */ + /* interrupt flags in CTL1 register */ + USART_INT_FLAG_LBD = USART_REGIDX_BIT2(USART_CTL1_REG_OFFSET, 6U, USART_STAT0_REG_OFFSET, 8U), /*!< LIN break detected interrupt and flag */ + /* interrupt flags in CTL2 register */ + USART_INT_FLAG_CTS = USART_REGIDX_BIT2(USART_CTL2_REG_OFFSET, 10U, USART_STAT0_REG_OFFSET, 9U), /*!< CTS interrupt and flag */ + USART_INT_FLAG_ERR_ORERR = USART_REGIDX_BIT2(USART_CTL2_REG_OFFSET, 0U, USART_STAT0_REG_OFFSET, 3U), /*!< error interrupt and overrun error */ + USART_INT_FLAG_ERR_NERR = USART_REGIDX_BIT2(USART_CTL2_REG_OFFSET, 0U, USART_STAT0_REG_OFFSET, 2U), /*!< error interrupt and noise error flag */ + USART_INT_FLAG_ERR_FERR = USART_REGIDX_BIT2(USART_CTL2_REG_OFFSET, 0U, USART_STAT0_REG_OFFSET, 1U), /*!< error interrupt and frame error flag */ + /* interrupt flags in CTL3 register */ + USART_INT_FLAG_EB = USART_REGIDX_BIT2(USART_CTL3_REG_OFFSET, 5U, USART_STAT1_REG_OFFSET, 12U), /*!< interrupt enable bit of end of block event and flag */ + USART_INT_FLAG_RT = USART_REGIDX_BIT2(USART_CTL3_REG_OFFSET, 4U, USART_STAT1_REG_OFFSET, 11U), /*!< interrupt enable bit of receive timeout event and flag */ +}usart_interrupt_flag_enum; + +/* USART interrupt enable or disable */ +typedef enum +{ + /* interrupt in CTL0 register */ + USART_INT_PERR = USART_REGIDX_BIT(USART_CTL0_REG_OFFSET, 8U), /*!< parity error interrupt */ + USART_INT_TBE = USART_REGIDX_BIT(USART_CTL0_REG_OFFSET, 7U), /*!< transmitter buffer empty interrupt */ + USART_INT_TC = USART_REGIDX_BIT(USART_CTL0_REG_OFFSET, 6U), /*!< transmission complete interrupt */ + USART_INT_RBNE = USART_REGIDX_BIT(USART_CTL0_REG_OFFSET, 5U), /*!< read data buffer not empty interrupt and overrun error interrupt */ + USART_INT_IDLE = USART_REGIDX_BIT(USART_CTL0_REG_OFFSET, 4U), /*!< IDLE line detected interrupt */ + /* interrupt in CTL1 register */ + USART_INT_LBD = USART_REGIDX_BIT(USART_CTL1_REG_OFFSET, 6U), /*!< LIN break detected interrupt */ + /* interrupt in CTL2 register */ + USART_INT_CTS = USART_REGIDX_BIT(USART_CTL2_REG_OFFSET, 10U), /*!< CTS interrupt */ + USART_INT_ERR = USART_REGIDX_BIT(USART_CTL2_REG_OFFSET, 0U), /*!< error interrupt */ + /* interrupt in CTL3 register */ + USART_INT_EB = USART_REGIDX_BIT(USART_CTL3_REG_OFFSET, 5U), /*!< end of block interrupt */ + USART_INT_RT = USART_REGIDX_BIT(USART_CTL3_REG_OFFSET, 4U), /*!< receive timeout interrupt */ +}usart_interrupt_enum; + +/* USART invert configure */ +typedef enum +{ + /* data bit level inversion */ + USART_DINV_ENABLE, /*!< data bit level inversion */ + USART_DINV_DISABLE, /*!< data bit level not inversion */ + /* TX pin level inversion */ + USART_TXPIN_ENABLE, /*!< TX pin level inversion */ + USART_TXPIN_DISABLE, /*!< TX pin level not inversion */ + /* RX pin level inversion */ + USART_RXPIN_ENABLE, /*!< RX pin level inversion */ + USART_RXPIN_DISABLE, /*!< RX pin level not inversion */ +}usart_invert_enum; + +/* USART receiver configure */ +#define CTL0_REN(regval) (BIT(2) & ((uint32_t)(regval) << 2)) +#define USART_RECEIVE_ENABLE CTL0_REN(1) /*!< enable receiver */ +#define USART_RECEIVE_DISABLE CTL0_REN(0) /*!< disable receiver */ + +/* USART transmitter configure */ +#define CTL0_TEN(regval) (BIT(3) & ((uint32_t)(regval) << 3)) +#define USART_TRANSMIT_ENABLE CTL0_TEN(1) /*!< enable transmitter */ +#define USART_TRANSMIT_DISABLE CTL0_TEN(0) /*!< disable transmitter */ + +/* USART parity bits definitions */ +#define CTL0_PM(regval) (BITS(9,10) & ((uint32_t)(regval) << 9)) +#define USART_PM_NONE CTL0_PM(0) /*!< no parity */ +#define USART_PM_EVEN CTL0_PM(2) /*!< even parity */ +#define USART_PM_ODD CTL0_PM(3) /*!< odd parity */ + +/* USART wakeup method in mute mode */ +#define CTL0_WM(regval) (BIT(11) & ((uint32_t)(regval) << 11)) +#define USART_WM_IDLE CTL0_WM(0) /*!< idle line */ +#define USART_WM_ADDR CTL0_WM(1) /*!< address match */ + +/* USART word length definitions */ +#define CTL0_WL(regval) (BIT(12) & ((uint32_t)(regval) << 12)) +#define USART_WL_8BIT CTL0_WL(0) /*!< 8 bits */ +#define USART_WL_9BIT CTL0_WL(1) /*!< 9 bits */ + +/* USART stop bits definitions */ +#define CTL1_STB(regval) (BITS(12,13) & ((uint32_t)(regval) << 12)) +#define USART_STB_1BIT CTL1_STB(0) /*!< 1 bit */ +#define USART_STB_0_5BIT CTL1_STB(1) /*!< 0.5 bit */ +#define USART_STB_2BIT CTL1_STB(2) /*!< 2 bits */ +#define USART_STB_1_5BIT CTL1_STB(3) /*!< 1.5 bits */ + +/* USART LIN break frame length */ +#define CTL1_LBLEN(regval) (BIT(5) & ((uint32_t)(regval) << 5)) +#define USART_LBLEN_10B CTL1_LBLEN(0) /*!< 10 bits */ +#define USART_LBLEN_11B CTL1_LBLEN(1) /*!< 11 bits */ + +/* USART CK length */ +#define CTL1_CLEN(regval) (BIT(8) & ((uint32_t)(regval) << 8)) +#define USART_CLEN_NONE CTL1_CLEN(0) /*!< there are 7 CK pulses for an 8 bit frame and 8 CK pulses for a 9 bit frame */ +#define USART_CLEN_EN CTL1_CLEN(1) /*!< there are 8 CK pulses for an 8 bit frame and 9 CK pulses for a 9 bit frame */ + +/* USART clock phase */ +#define CTL1_CPH(regval) (BIT(9) & ((uint32_t)(regval) << 9)) +#define USART_CPH_1CK CTL1_CPH(0) /*!< first clock transition is the first data capture edge */ +#define USART_CPH_2CK CTL1_CPH(1) /*!< second clock transition is the first data capture edge */ + +/* USART clock polarity */ +#define CTL1_CPL(regval) (BIT(10) & ((uint32_t)(regval) << 10)) +#define USART_CPL_LOW CTL1_CPL(0) /*!< steady low value on CK pin */ +#define USART_CPL_HIGH CTL1_CPL(1) /*!< steady high value on CK pin */ + +/* USART DMA request for receive configure */ +#define CLT2_DENR(regval) (BIT(6) & ((uint32_t)(regval) << 6)) +#define USART_DENR_ENABLE CLT2_DENR(1) /*!< DMA request enable for reception */ +#define USART_DENR_DISABLE CLT2_DENR(0) /*!< DMA request disable for reception */ + +/* USART DMA request for transmission configure */ +#define CLT2_DENT(regval) (BIT(7) & ((uint32_t)(regval) << 7)) +#define USART_DENT_ENABLE CLT2_DENT(1) /*!< DMA request enable for transmission */ +#define USART_DENT_DISABLE CLT2_DENT(0) /*!< DMA request disable for transmission */ + +/* USART RTS configure */ +#define CLT2_RTSEN(regval) (BIT(8) & ((uint32_t)(regval) << 8)) +#define USART_RTS_ENABLE CLT2_RTSEN(1) /*!< RTS enable */ +#define USART_RTS_DISABLE CLT2_RTSEN(0) /*!< RTS disable */ + +/* USART CTS configure */ +#define CLT2_CTSEN(regval) (BIT(9) & ((uint32_t)(regval) << 9)) +#define USART_CTS_ENABLE CLT2_CTSEN(1) /*!< CTS enable */ +#define USART_CTS_DISABLE CLT2_CTSEN(0) /*!< CTS disable */ + +/* USART IrDA low-power enable */ +#define CTL2_IRLP(regval) (BIT(2) & ((uint32_t)(regval) << 2)) +#define USART_IRLP_LOW CTL2_IRLP(1) /*!< low-power */ +#define USART_IRLP_NORMAL CTL2_IRLP(0) /*!< normal */ + +/* USART data is transmitted/received with the LSB/MSB first */ +#define CTL3_MSBF(regval) (BIT(11) & ((uint32_t)(regval) << 11)) +#define USART_MSBF_LSB CTL3_MSBF(0) /*!< LSB first */ +#define USART_MSBF_MSB CTL3_MSBF(1) /*!< MSB first */ + +/* function declarations */ +/* initialization functions */ +/* reset USART */ +void usart_deinit(uint32_t usart_periph); +/* configure USART baud rate value */ +void usart_baudrate_set(uint32_t usart_periph, uint32_t baudval); +/* configure USART parity function */ +void usart_parity_config(uint32_t usart_periph, uint32_t paritycfg); +/* configure USART word length */ +void usart_word_length_set(uint32_t usart_periph, uint32_t wlen); +/* configure USART stop bit length */ +void usart_stop_bit_set(uint32_t usart_periph, uint32_t stblen); +/* enable USART */ +void usart_enable(uint32_t usart_periph); +/* disable USART */ +void usart_disable(uint32_t usart_periph); +/* configure USART transmitter */ +void usart_transmit_config(uint32_t usart_periph, uint32_t txconfig); +/* configure USART receiver */ +void usart_receive_config(uint32_t usart_periph, uint32_t rxconfig); + +/* USART normal mode communication */ +/* data is transmitted/received with the LSB/MSB first */ +void usart_data_first_config(uint32_t usart_periph, uint32_t msbf); +/* configure USART inverted */ +void usart_invert_config(uint32_t usart_periph, usart_invert_enum invertpara); +/* enable receiver timeout */ +void usart_receiver_timeout_enable(uint32_t usart_periph); +/* disable receiver timeout */ +void usart_receiver_timeout_disable(uint32_t usart_periph); +/* configure receiver timeout threshold */ +void usart_receiver_timeout_threshold_config(uint32_t usart_periph, uint32_t rtimeout); +/* USART transmit data function */ +void usart_data_transmit(uint32_t usart_periph, uint32_t data); +/* USART receive data function */ +uint16_t usart_data_receive(uint32_t usart_periph); + +/* multi-processor communication */ +/* configure address of the USART */ +void usart_address_config(uint32_t usart_periph, uint8_t addr); +/* enable mute mode */ +void usart_mute_mode_enable(uint32_t usart_periph); +/* disable mute mode */ +void usart_mute_mode_disable(uint32_t usart_periph); +/* configure wakeup method in mute mode */ +void usart_mute_mode_wakeup_config(uint32_t usart_periph, uint32_t wmethod); + +/* LIN mode communication */ +/* enable LIN mode */ +void usart_lin_mode_enable(uint32_t usart_periph); +/* disable LIN mode */ +void usart_lin_mode_disable(uint32_t usart_periph); +/* LIN break detection length */ +void usart_lin_break_detection_length_config(uint32_t usart_periph, uint32_t lblen); +/* send break frame */ +void usart_send_break(uint32_t usart_periph); + +/* half-duplex communication */ +/* enable half-duplex mode */ +void usart_halfduplex_enable(uint32_t usart_periph); +/* disable half-duplex mode */ +void usart_halfduplex_disable(uint32_t usart_periph); + +/* synchronous communication */ +/* enable CK pin in synchronous mode */ +void usart_synchronous_clock_enable(uint32_t usart_periph); +/* disable CK pin in synchronous mode */ +void usart_synchronous_clock_disable(uint32_t usart_periph); +/* configure usart synchronous mode parameters */ +void usart_synchronous_clock_config(uint32_t usart_periph, uint32_t clen, uint32_t cph, uint32_t cpl); + +/* smartcard communication */ +/* configure guard time value in smartcard mode */ +void usart_guard_time_config(uint32_t usart_periph,uint32_t guat); +/* enable smartcard mode */ +void usart_smartcard_mode_enable(uint32_t usart_periph); +/* disable smartcard mode */ +void usart_smartcard_mode_disable(uint32_t usart_periph); +/* enable NACK in smartcard mode */ +void usart_smartcard_mode_nack_enable(uint32_t usart_periph); +/* disable NACK in smartcard mode */ +void usart_smartcard_mode_nack_disable(uint32_t usart_periph); +/* configure smartcard auto-retry number */ +void usart_smartcard_autoretry_config(uint32_t usart_periph, uint32_t scrtnum); +/* configure block length */ +void usart_block_length_config(uint32_t usart_periph, uint32_t bl); + +/* IrDA communication */ +/* enable IrDA mode */ +void usart_irda_mode_enable(uint32_t usart_periph); +/* disable IrDA mode */ +void usart_irda_mode_disable(uint32_t usart_periph); +/* configure the peripheral clock prescaler */ +void usart_prescaler_config(uint32_t usart_periph, uint8_t psc); +/* configure IrDA low-power */ +void usart_irda_lowpower_config(uint32_t usart_periph, uint32_t irlp); + +/* hardware flow communication */ +/* configure hardware flow control RTS */ +void usart_hardware_flow_rts_config(uint32_t usart_periph, uint32_t rtsconfig); +/* configure hardware flow control CTS */ +void usart_hardware_flow_cts_config(uint32_t usart_periph, uint32_t ctsconfig); + +/* DMA communication */ +/* configure USART DMA for reception */ +void usart_dma_receive_config(uint32_t usart_periph, uint32_t dmacmd); +/* configure USART DMA for transmission */ +void usart_dma_transmit_config(uint32_t usart_periph, uint32_t dmacmd); + +/* flag & interrupt functions */ +/* get flag in STAT0/STAT1 register */ +FlagStatus usart_flag_get(uint32_t usart_periph, usart_flag_enum flag); +/* clear flag in STAT0/STAT1 register */ +void usart_flag_clear(uint32_t usart_periph, usart_flag_enum flag); +/* enable USART interrupt */ +void usart_interrupt_enable(uint32_t usart_periph, usart_interrupt_enum interrupt); +/* disable USART interrupt */ +void usart_interrupt_disable(uint32_t usart_periph, usart_interrupt_enum interrupt); +/* get USART interrupt and flag status */ +FlagStatus usart_interrupt_flag_get(uint32_t usart_periph, usart_interrupt_flag_enum int_flag); +/* clear interrupt flag in STAT0/STAT1 register */ +void usart_interrupt_flag_clear(uint32_t usart_periph, usart_interrupt_flag_enum int_flag); + +#endif /* GD32F30x_USART_H */ diff --git a/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_standard_peripheral/Include/gd32f30x_wwdgt.h b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_standard_peripheral/Include/gd32f30x_wwdgt.h new file mode 100644 index 0000000000..17c4738acf --- /dev/null +++ b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_standard_peripheral/Include/gd32f30x_wwdgt.h @@ -0,0 +1,90 @@ +/*! + \file gd32f30x_wwdgt.h + \brief definitions for the WWDGT + + \version 2017-02-10, V1.0.0, firmware for GD32F30x + \version 2018-10-10, V1.1.0, firmware for GD32F30x + \version 2018-12-25, V2.0.0, firmware for GD32F30x + \version 2020-09-30, V2.1.0, firmware for GD32F30x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + + +#ifndef GD32F30X_WWDGT_H +#define GD32F30X_WWDGT_H + +#include "gd32f30x.h" + +/* WWDGT definitions */ +#define WWDGT WWDGT_BASE + +/* registers definitions */ +#define WWDGT_CTL REG32((WWDGT) + 0x00U) /*!< WWDGT control register */ +#define WWDGT_CFG REG32((WWDGT) + 0x04U) /*!< WWDGT configuration register */ +#define WWDGT_STAT REG32((WWDGT) + 0x08U) /*!< WWDGT status register */ + +/* bits definitions */ +/* WWDGT_CTL */ +#define WWDGT_CTL_CNT BITS(0,6) /*!< WWDGT counter value */ +#define WWDGT_CTL_WDGTEN BIT(7) /*!< WWDGT counter enable */ + +/* WWDGT_CFG */ +#define WWDGT_CFG_WIN BITS(0,6) /*!< WWDGT counter window value */ +#define WWDGT_CFG_PSC BITS(7,8) /*!< WWDGT prescaler divider value */ +#define WWDGT_CFG_EWIE BIT(9) /*!< early wakeup interrupt enable */ + +/* WWDGT_STAT */ +#define WWDGT_STAT_EWIF BIT(0) /*!< early wakeup interrupt flag */ + +/* constants definitions */ +#define CFG_PSC(regval) (BITS(7,8) & ((uint32_t)(regval) << 7)) /*!< write value to WWDGT_CFG_PSC bit field */ +#define WWDGT_CFG_PSC_DIV1 CFG_PSC(0) /*!< the time base of WWDGT = (PCLK1/4096)/1 */ +#define WWDGT_CFG_PSC_DIV2 CFG_PSC(1) /*!< the time base of WWDGT = (PCLK1/4096)/2 */ +#define WWDGT_CFG_PSC_DIV4 CFG_PSC(2) /*!< the time base of WWDGT = (PCLK1/4096)/4 */ +#define WWDGT_CFG_PSC_DIV8 CFG_PSC(3) /*!< the time base of WWDGT = (PCLK1/4096)/8 */ + +/* function declarations */ +/* reset the window watchdog timer configuration */ +void wwdgt_deinit(void); +/* start the window watchdog timer counter */ +void wwdgt_enable(void); + +/* configure the window watchdog timer counter value */ +void wwdgt_counter_update(uint16_t counter_value); +/* configure counter value, window value, and prescaler divider value */ +void wwdgt_config(uint16_t counter, uint16_t window, uint32_t prescaler); + +/* enable early wakeup interrupt of WWDGT */ +void wwdgt_interrupt_enable(void); +/* check early wakeup interrupt state of WWDGT */ +FlagStatus wwdgt_flag_get(void); +/* clear early wakeup interrupt state of WWDGT */ +void wwdgt_flag_clear(void); + +#endif /* GD32F30X_WWDGT_H */ diff --git a/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_standard_peripheral/Source/gd32f30x_adc.c b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_standard_peripheral/Source/gd32f30x_adc.c new file mode 100644 index 0000000000..1374e23dc2 --- /dev/null +++ b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_standard_peripheral/Source/gd32f30x_adc.c @@ -0,0 +1,941 @@ +/*! + \file gd32f30x_adc.c + \brief ADC driver + + \version 2017-02-10, V1.0.0, firmware for GD32F30x + \version 2018-10-10, V1.1.0, firmware for GD32F30x + \version 2018-12-25, V2.0.0, firmware for GD32F30x + \version 2020-09-30, V2.1.0, firmware for GD32F30x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "gd32f30x_adc.h" + +/*! + \brief reset ADC + \param[in] adc_periph: ADCx,x=0,1,2 + only one among these parameters can be selected + \param[out] none + \retval none +*/ +void adc_deinit(uint32_t adc_periph) +{ + switch(adc_periph){ + case ADC0: + rcu_periph_reset_enable(RCU_ADC0RST); + rcu_periph_reset_disable(RCU_ADC0RST); + break; + case ADC1: + rcu_periph_reset_enable(RCU_ADC1RST); + rcu_periph_reset_disable(RCU_ADC1RST); + break; +#if (defined(GD32F30X_HD) || defined(GD32F30X_XD)) + case ADC2: + rcu_periph_reset_enable(RCU_ADC2RST); + rcu_periph_reset_disable(RCU_ADC2RST); + break; +#endif + default: + break; + } +} + +/*! + \brief enable ADC interface + \param[in] adc_periph: ADCx,x=0,1,2 + only one among these parameters can be selected + \param[out] none + \retval none +*/ +void adc_enable(uint32_t adc_periph) +{ + if(RESET == (ADC_CTL1(adc_periph) & ADC_CTL1_ADCON)){ + ADC_CTL1(adc_periph) |= (uint32_t)ADC_CTL1_ADCON; + } +} + +/*! + \brief disable ADC interface + \param[in] adc_periph: ADCx,x=0,1,2 + only one among these parameters can be selected + \param[out] none + \retval none +*/ +void adc_disable(uint32_t adc_periph) +{ + ADC_CTL1(adc_periph) &= ~((uint32_t)ADC_CTL1_ADCON); +} + +/*! + \brief ADC calibration and reset calibration + \param[in] adc_periph: ADCx,x=0,1,2 + only one among these parameters can be selected + \param[out] none + \retval none +*/ +void adc_calibration_enable(uint32_t adc_periph) +{ + /* reset the selected ADC calibration registers */ + ADC_CTL1(adc_periph) |= (uint32_t) ADC_CTL1_RSTCLB; + /* check the RSTCLB bit state */ + while((ADC_CTL1(adc_periph) & ADC_CTL1_RSTCLB)){ + } + /* enable ADC calibration process */ + ADC_CTL1(adc_periph) |= ADC_CTL1_CLB; + /* check the CLB bit state */ + while((ADC_CTL1(adc_periph) & ADC_CTL1_CLB)){ + } +} + +/*! + \brief enable DMA request + \param[in] adc_periph: ADCx,x=0,1,2 + only one among these parameters can be selected + \param[out] none + \retval none +*/ +void adc_dma_mode_enable(uint32_t adc_periph) +{ + ADC_CTL1(adc_periph) |= (uint32_t)(ADC_CTL1_DMA); +} + +/*! + \brief disable DMA request + \param[in] adc_periph: ADCx,x=0,1,2 + only one among these parameters can be selected + \param[out] none + \retval none +*/ +void adc_dma_mode_disable(uint32_t adc_periph) +{ + ADC_CTL1(adc_periph) &= ~((uint32_t)ADC_CTL1_DMA); +} + +/*! + \brief enable the temperature sensor and Vrefint channel + \param[in] none + \param[out] none + \retval none +*/ +void adc_tempsensor_vrefint_enable(void) +{ + /* enable the temperature sensor and Vrefint channel */ + ADC_CTL1(ADC0) |= ADC_CTL1_TSVREN; +} + +/*! + \brief disable the temperature sensor and Vrefint channel + \param[in] none + \param[out] none + \retval none +*/ +void adc_tempsensor_vrefint_disable(void) +{ + /* disable the temperature sensor and Vrefint channel */ + ADC_CTL1(ADC0) &= ~ADC_CTL1_TSVREN; +} + +/*! + \brief configure ADC resolution + \param[in] adc_periph: ADCx,x=0,1,2 + only one among these parameters can be selected + \param[in] resolution: ADC resolution + only one among these parameters can be selected + \arg ADC_RESOLUTION_12B: 12-bit ADC resolution + \arg ADC_RESOLUTION_10B: 10-bit ADC resolution + \arg ADC_RESOLUTION_8B: 8-bit ADC resolution + \arg ADC_RESOLUTION_6B: 6-bit ADC resolution + \param[out] none + \retval none +*/ +void adc_resolution_config(uint32_t adc_periph , uint32_t resolution) +{ + ADC_OVSAMPCTL(adc_periph) &= ~((uint32_t)ADC_OVSAMPCTL_DRES); + ADC_OVSAMPCTL(adc_periph) |= (uint32_t)resolution; +} + +/*! + \brief configure ADC discontinuous mode + \param[in] adc_periph: ADCx,x=0,1,2 + only one among these parameters can be selected + \param[in] adc_channel_group: select the channel group + only one among these parameters can be selected + \arg ADC_REGULAR_CHANNEL: regular channel group + \arg ADC_INSERTED_CHANNEL: inserted channel group + \arg ADC_CHANNEL_DISCON_DISABLE: disable discontinuous mode of regular & inserted channel + \param[in] length: number of conversions in discontinuous mode,the number can be 1..8 + for regular channel ,the number has no effect for inserted channel + \param[out] none + \retval none +*/ +void adc_discontinuous_mode_config(uint32_t adc_periph, uint8_t adc_channel_group, uint8_t length) +{ + ADC_CTL0(adc_periph) &= ~((uint32_t)( ADC_CTL0_DISRC | ADC_CTL0_DISIC )); + switch(adc_channel_group){ + case ADC_REGULAR_CHANNEL: + /* config the number of conversions in discontinuous mode */ + ADC_CTL0(adc_periph) &= ~((uint32_t)ADC_CTL0_DISNUM); + ADC_CTL0(adc_periph) |= CTL0_DISNUM(((uint32_t)length - 1U)); + + ADC_CTL0(adc_periph) |= (uint32_t)ADC_CTL0_DISRC; + break; + case ADC_INSERTED_CHANNEL: + ADC_CTL0(adc_periph) |= (uint32_t)ADC_CTL0_DISIC; + break; + case ADC_CHANNEL_DISCON_DISABLE: + default: + break; + } +} + +/*! + \brief configure the ADC sync mode + \param[in] mode: ADC mode + only one among these parameters can be selected + \arg ADC_MODE_FREE: all the ADCs work independently + \arg ADC_DAUL_REGULAL_PARALLEL_INSERTED_PARALLEL: ADC0 and ADC1 work in combined regular parallel + inserted parallel mode + \arg ADC_DAUL_REGULAL_PARALLEL_INSERTED_ROTATION: ADC0 and ADC1 work in combined regular parallel + trigger rotation mode + \arg ADC_DAUL_INSERTED_PARALLEL_REGULAL_FOLLOWUP_FAST: ADC0 and ADC1 work in combined inserted parallel + follow-up fast mode + \arg ADC_DAUL_INSERTED_PARALLEL_REGULAL_FOLLOWUP_SLOW: ADC0 and ADC1 work in combined inserted parallel + follow-up slow mode + \arg ADC_DAUL_INSERTED_PARALLEL: ADC0 and ADC1 work in inserted parallel mode only + \arg ADC_DAUL_REGULAL_PARALLEL: ADC0 and ADC1 work in regular parallel mode only + \arg ADC_DAUL_REGULAL_FOLLOWUP_FAST: ADC0 and ADC1 work in follow-up fast mode only + \arg ADC_DAUL_REGULAL_FOLLOWUP_SLOW: ADC0 and ADC1 work in follow-up slow mode only + \arg ADC_DAUL_INSERTED_TRRIGGER_ROTATION: ADC0 and ADC1 work in trigger rotation mode only + \param[out] none + \retval none +*/ +void adc_mode_config(uint32_t mode) +{ + ADC_CTL0(ADC0) &= ~(ADC_CTL0_SYNCM); + ADC_CTL0(ADC0) |= mode; +} + +/*! + \brief enable or disable ADC special function + \param[in] adc_periph: ADCx,x=0,1,2 + only one among these parameters can be selected + \param[in] function: the function to config + one or more parameters can be selected below + \arg ADC_SCAN_MODE: scan mode select + \arg ADC_INSERTED_CHANNEL_AUTO: inserted channel group convert automatically + \arg ADC_CONTINUOUS_MODE: continuous mode select + \param[in] newvalue: ENABLE or DISABLE + \param[out] none + \retval none +*/ +void adc_special_function_config(uint32_t adc_periph , uint32_t function , ControlStatus newvalue) +{ + if(newvalue){ + if(0U != (function & ADC_SCAN_MODE)){ + ADC_CTL0(adc_periph) |= ADC_SCAN_MODE; + } + if(0U != (function & ADC_INSERTED_CHANNEL_AUTO)){ + ADC_CTL0(adc_periph) |= ADC_INSERTED_CHANNEL_AUTO; + } + if(0U != (function & ADC_CONTINUOUS_MODE)){ + ADC_CTL1(adc_periph) |= ADC_CONTINUOUS_MODE; + } + }else{ + if(0U != (function & ADC_SCAN_MODE)){ + ADC_CTL0(adc_periph) &= ~ADC_SCAN_MODE; + } + if(0U != (function & ADC_INSERTED_CHANNEL_AUTO)){ + ADC_CTL0(adc_periph) &= ~ADC_INSERTED_CHANNEL_AUTO; + } + if(0U != (function & ADC_CONTINUOUS_MODE)){ + ADC_CTL1(adc_periph) &= ~ADC_CONTINUOUS_MODE; + } + } +} + +/*! + \brief configure ADC data alignment + \param[in] adc_periph: ADCx,x=0,1,2 + only one among these parameters can be selected + \param[in] data_alignment: data alignment select + only one parameter can be selected + \arg ADC_DATAALIGN_RIGHT: LSB alignment + \arg ADC_DATAALIGN_LEFT: MSB alignment + \param[out] none + \retval none +*/ +void adc_data_alignment_config(uint32_t adc_periph , uint32_t data_alignment) +{ + if(ADC_DATAALIGN_RIGHT != data_alignment){ + ADC_CTL1(adc_periph) |= ADC_CTL1_DAL; + }else{ + ADC_CTL1(adc_periph) &= ~((uint32_t)ADC_CTL1_DAL); + } +} + +/*! + \brief configure the length of regular channel group or inserted channel group + \param[in] adc_periph: ADCx,x=0,1,2 + only one among these parameters can be selected + \param[in] adc_channel_group: select the channel group + only one parameter can be selected + \arg ADC_REGULAR_CHANNEL: regular channel group + \arg ADC_INSERTED_CHANNEL: inserted channel group + \param[in] length: the length of the channel + regular channel 1-16 + inserted channel 1-4 + \param[out] none + \retval none +*/ +void adc_channel_length_config(uint32_t adc_periph, uint8_t adc_channel_group, uint32_t length) +{ + switch(adc_channel_group){ + case ADC_REGULAR_CHANNEL: + ADC_RSQ0(adc_periph) &= ~((uint32_t)ADC_RSQ0_RL); + ADC_RSQ0(adc_periph) |= RSQ0_RL((uint32_t)(length-1U)); + + break; + case ADC_INSERTED_CHANNEL: + ADC_ISQ(adc_periph) &= ~((uint32_t)ADC_ISQ_IL); + ADC_ISQ(adc_periph) |= ISQ_IL((uint32_t)(length-1U)); + + break; + default: + break; + } +} + +/*! + \brief configure ADC regular channel + \param[in] adc_periph: ADCx,x=0,1,2 + only one among these parameters can be selected + \param[in] rank: the regular group sequence rank,this parameter must be between 0 to 15 + \param[in] adc_channel: the selected ADC channel + only one among these parameters can be selected + \arg ADC_CHANNEL_x(x=0..17)(x=16 and x=17 are only for ADC0): ADC Channelx + \param[in] sample_time: the sample time value + only one parameter can be selected + \arg ADC_SAMPLETIME_1POINT5: 1.5 cycles + \arg ADC_SAMPLETIME_7POINT5: 7.5 cycles + \arg ADC_SAMPLETIME_13POINT5: 13.5 cycles + \arg ADC_SAMPLETIME_28POINT5: 28.5 cycles + \arg ADC_SAMPLETIME_41POINT5: 41.5 cycles + \arg ADC_SAMPLETIME_55POINT5: 55.5 cycles + \arg ADC_SAMPLETIME_71POINT5: 71.5 cycles + \arg ADC_SAMPLETIME_239POINT5: 239.5 cycles + \param[out] none + \retval none +*/ +void adc_regular_channel_config(uint32_t adc_periph , uint8_t rank , uint8_t adc_channel , uint32_t sample_time) +{ + uint32_t rsq,sampt; + + /* ADC regular sequence config */ + if(rank < 6U){ + rsq = ADC_RSQ2(adc_periph); + rsq &= ~((uint32_t)(ADC_RSQX_RSQN << (5U*rank))); + rsq |= ((uint32_t)adc_channel << (5U*rank)); + ADC_RSQ2(adc_periph) = rsq; + }else if(rank < 12U){ + rsq = ADC_RSQ1(adc_periph); + rsq &= ~((uint32_t)(ADC_RSQX_RSQN << (5U*(rank-6U)))); + rsq |= ((uint32_t)adc_channel << (5U*(rank-6U))); + ADC_RSQ1(adc_periph) = rsq; + }else if(rank < 16U){ + rsq = ADC_RSQ0(adc_periph); + rsq &= ~((uint32_t)(ADC_RSQX_RSQN << (5U*(rank-12U)))); + rsq |= ((uint32_t)adc_channel << (5U*(rank-12U))); + ADC_RSQ0(adc_periph) = rsq; + }else{ + } + + /* ADC sampling time config */ + if(adc_channel < 10U){ + sampt = ADC_SAMPT1(adc_periph); + sampt &= ~((uint32_t)(ADC_SAMPTX_SPTN << (3U*adc_channel))); + sampt |= (uint32_t)(sample_time << (3U*adc_channel)); + ADC_SAMPT1(adc_periph) = sampt; + }else if(adc_channel < 18U){ + sampt = ADC_SAMPT0(adc_periph); + sampt &= ~((uint32_t)(ADC_SAMPTX_SPTN << (3U*(adc_channel-10U)))); + sampt |= (uint32_t)(sample_time << (3U*(adc_channel-10U))); + ADC_SAMPT0(adc_periph) = sampt; + }else{ + } +} + +/*! + \brief configure ADC inserted channel + \param[in] adc_periph: ADCx,x=0,1,2 + only one among these parameters can be selected + \param[in] rank: the inserted group sequencer rank,this parameter must be between 0 to 3 + \param[in] adc_channel: the selected ADC channel + only one among these parameters can be selected + \arg ADC_CHANNEL_x(x=0..17)(x=16 and x=17 are only for ADC0): ADC Channelx + \param[in] sample_time: The sample time value + only one parameter can be selected + \arg ADC_SAMPLETIME_1POINT5: 1.5 cycles + \arg ADC_SAMPLETIME_7POINT5: 7.5 cycles + \arg ADC_SAMPLETIME_13POINT5: 13.5 cycles + \arg ADC_SAMPLETIME_28POINT5: 28.5 cycles + \arg ADC_SAMPLETIME_41POINT5: 41.5 cycles + \arg ADC_SAMPLETIME_55POINT5: 55.5 cycles + \arg ADC_SAMPLETIME_71POINT5: 71.5 cycles + \arg ADC_SAMPLETIME_239POINT5: 239.5 cycles + \param[out] none + \retval none +*/ +void adc_inserted_channel_config(uint32_t adc_periph , uint8_t rank , uint8_t adc_channel , uint32_t sample_time) +{ + uint8_t inserted_length; + uint32_t isq,sampt; + + inserted_length = (uint8_t)GET_BITS(ADC_ISQ(adc_periph) , 20U , 21U); + + isq = ADC_ISQ(adc_periph); + isq &= ~((uint32_t)(ADC_ISQ_ISQN << (5U * ((3 + rank) - inserted_length)))); + isq |= ((uint32_t)adc_channel << (5U * ((3 + rank) - inserted_length))); + ADC_ISQ(adc_periph) = isq; + + /* ADC sampling time config */ + if(adc_channel < 10U){ + sampt = ADC_SAMPT1(adc_periph); + sampt &= ~((uint32_t)(ADC_SAMPTX_SPTN << (3U*adc_channel))); + sampt |= (uint32_t) sample_time << (3U*adc_channel); + ADC_SAMPT1(adc_periph) = sampt; + }else if(adc_channel < 18U){ + sampt = ADC_SAMPT0(adc_periph); + sampt &= ~((uint32_t)(ADC_SAMPTX_SPTN << (3U*(adc_channel-10U)))); + sampt |= ((uint32_t)sample_time << (3U*(adc_channel-10U))); + ADC_SAMPT0(adc_periph) = sampt; + }else{ + } +} + +/*! + \brief configure ADC inserted channel offset + \param[in] adc_periph: ADCx,x=0,1,2 + only one among these parameters can be selected + \param[in] inserted_channel : insert channel select + only one parameter can be selected + \arg ADC_INSERTED_CHANNEL_0: inserted channel0 + \arg ADC_INSERTED_CHANNEL_1: inserted channel1 + \arg ADC_INSERTED_CHANNEL_2: inserted channel2 + \arg ADC_INSERTED_CHANNEL_3: inserted channel3 + \param[in] offset : the offset data + \param[out] none + \retval none +*/ +void adc_inserted_channel_offset_config(uint32_t adc_periph , uint8_t inserted_channel , uint16_t offset) +{ + uint8_t inserted_length; + uint32_t num = 0U; + + inserted_length = (uint8_t)GET_BITS(ADC_ISQ(adc_periph) , 20U , 21U); + num = 3U - (inserted_length - inserted_channel); + + if(num <= 3U){ + /* calculate the offset of the register */ + num = num * 4U; + /* config the offset of the selected channels */ + REG32((adc_periph) + 0x14U + num) = IOFFX_IOFF((uint32_t)offset); + } +} + +/*! + \brief enable ADC external trigger + \param[in] adc_periph: ADCx,x=0,1,2 + only one among these parameters can be selected + \param[in] adc_channel_group: select the channel group + one or more parameters can be selected + \arg ADC_REGULAR_CHANNEL: regular channel group + \arg ADC_INSERTED_CHANNEL: inserted channel group + \param[in] newvalue: ENABLE or DISABLE + \param[out] none + \retval none +*/ +void adc_external_trigger_config(uint32_t adc_periph, uint8_t adc_channel_group, ControlStatus newvalue) +{ + if(newvalue){ + if(0U != (adc_channel_group & ADC_REGULAR_CHANNEL)){ + ADC_CTL1(adc_periph) |= ADC_CTL1_ETERC; + } + if(0U != (adc_channel_group & ADC_INSERTED_CHANNEL)){ + ADC_CTL1(adc_periph) |= ADC_CTL1_ETEIC; + } + }else{ + if(0U != (adc_channel_group & ADC_REGULAR_CHANNEL)){ + ADC_CTL1(adc_periph) &= ~ADC_CTL1_ETERC; + } + if(0U != (adc_channel_group & ADC_INSERTED_CHANNEL)){ + ADC_CTL1(adc_periph) &= ~ADC_CTL1_ETEIC; + } + } +} + +/*! + \brief configure ADC external trigger source + \param[in] adc_periph: ADCx,x=0,1,2 + only one among these parameters can be selected + \param[in] adc_channel_group: select the channel group + only one parameter can be selected + \arg ADC_REGULAR_CHANNEL: regular channel group + \arg ADC_INSERTED_CHANNEL: inserted channel group + \param[in] external_trigger_source: regular or inserted group trigger source + only one parameter can be selected + for regular channel: + \arg ADC0_1_EXTTRIG_REGULAR_T0_CH0: timer 0 CC0 event select + \arg ADC0_1_EXTTRIG_REGULAR_T0_CH1: timer 0 CC1 event select + \arg ADC0_1_EXTTRIG_REGULAR_T0_CH2: timer 0 CC2 event select + \arg ADC0_1_EXTTRIG_REGULAR_T1_CH1: timer 1 CC1 event select + \arg ADC0_1_EXTTRIG_REGULAR_T2_TRGO: timer 2 TRGO event select + \arg ADC0_1_EXTTRIG_REGULAR_T3_CH3: timer 3 CC3 event select + \arg ADC0_1_EXTTRIG_REGULAR_T7_TRGO: timer 7 TRGO event select + \arg ADC0_1_EXTTRIG_REGULAR_EXTI_11 : external interrupt line 11 + \arg ADC2_EXTTRIG_REGULAR_T2_CH0: timer 2 CC0 event select + \arg ADC2_EXTTRIG_REGULAR_T1_CH2: timer 1 CC2 event select + \arg ADC2_EXTTRIG_REGULAR_T0_CH2: timer 0 CC2 event select + \arg ADC2_EXTTRIG_REGULAR_T7_CH0: timer 7 CC0 event select + \arg ADC2_EXTTRIG_REGULAR_T7_TRGO: timer 7 TRGO event select + \arg ADC2_EXTTRIG_REGULAR_T4_CH0: timer 4 CC0 event select + \arg ADC2_EXTTRIG_REGULAR_T4_CH2: timer 4 CC2 event select + \arg ADC0_1_2_EXTTRIG_REGULAR_NONE: software trigger + for inserted channel: + \arg ADC0_1_EXTTRIG_INSERTED_T0_TRGO: timer 0 TRGO event select + \arg ADC0_1_EXTTRIG_INSERTED_T0_CH3: timer 0 CC3 event select + \arg ADC0_1_EXTTRIG_INSERTED_T1_TRGO: timer 1 TRGO event select + \arg ADC0_1_EXTTRIG_INSERTED_T1_CH0: timer 1 CC0 event select + \arg ADC0_1_EXTTRIG_INSERTED_T2_CH3: timer 2 CC3 event select + \arg ADC0_1_EXTTRIG_INSERTED_T3_TRGO: timer 3 TRGO event select + \arg ADC0_1_EXTTRIG_INSERTED_EXTI_15: external interrupt line 15 + \arg ADC0_1_EXTTRIG_INSERTED_T7_CH3: timer 7 CC3 event select + \arg ADC2_EXTTRIG_INSERTED_T0_TRGO: timer 0 TRGO event select + \arg ADC2_EXTTRIG_INSERTED_T0_CH3: timer 0 CC3 event select + \arg ADC2_EXTTRIG_INSERTED_T3_CH2: timer 3 CC2 event select + \arg ADC2_EXTTRIG_INSERTED_T7_CH1: timer 7 CC1 event select + \arg ADC2_EXTTRIG_INSERTED_T7_CH3: timer 7 CC3 event select + \arg ADC2_EXTTRIG_INSERTED_T4_TRGO: timer 4 TRGO event select + \arg ADC2_EXTTRIG_INSERTED_T4_CH3: timer 4 CC3 event select + \arg ADC0_1_2_EXTTRIG_INSERTED_NONE: software trigger + \param[out] none + \retval none +*/ +void adc_external_trigger_source_config(uint32_t adc_periph, uint8_t adc_channel_group, uint32_t external_trigger_source) +{ + switch(adc_channel_group){ + case ADC_REGULAR_CHANNEL: + ADC_CTL1(adc_periph) &= ~((uint32_t)ADC_CTL1_ETSRC); + ADC_CTL1(adc_periph) |= (uint32_t)external_trigger_source; + break; + case ADC_INSERTED_CHANNEL: + ADC_CTL1(adc_periph) &= ~((uint32_t)ADC_CTL1_ETSIC); + ADC_CTL1(adc_periph) |= (uint32_t)external_trigger_source; + break; + default: + break; + } +} + +/*! + \brief enable ADC software trigger + \param[in] adc_periph: ADCx,x=0,1,2 + only one among these parameters can be selected + \param[in] adc_channel_group: select the channel group + one or more parameters can be selected + \arg ADC_REGULAR_CHANNEL: regular channel group + \arg ADC_INSERTED_CHANNEL: inserted channel group + \param[out] none + \retval none +*/ +void adc_software_trigger_enable(uint32_t adc_periph , uint8_t adc_channel_group) +{ + if(0U != (adc_channel_group & ADC_REGULAR_CHANNEL)){ + ADC_CTL1(adc_periph) |= ADC_CTL1_SWRCST; + } + if(0U != (adc_channel_group & ADC_INSERTED_CHANNEL)){ + ADC_CTL1(adc_periph) |= ADC_CTL1_SWICST; + } +} + +/*! + \brief read ADC regular group data register + \param[in] adc_periph: ADCx,x=0,1,2 + only one among these parameters can be selected + \param[in] none + \param[out] none + \retval the conversion value +*/ +uint16_t adc_regular_data_read(uint32_t adc_periph) +{ + return (uint16_t)(ADC_RDATA(adc_periph)); +} + +/*! + \brief read ADC inserted group data register + \param[in] adc_periph: ADCx,x=0,1,2 + only one among these parameters can be selected + \param[in] inserted_channel : insert channel select + only one parameter can be selected + \arg ADC_INSERTED_CHANNEL_0: inserted Channel0 + \arg ADC_INSERTED_CHANNEL_1: inserted channel1 + \arg ADC_INSERTED_CHANNEL_2: inserted Channel2 + \arg ADC_INSERTED_CHANNEL_3: inserted Channel3 + \param[out] none + \retval the conversion value +*/ +uint16_t adc_inserted_data_read(uint32_t adc_periph , uint8_t inserted_channel) +{ + uint32_t idata; + /* read the data of the selected channel */ + switch(inserted_channel){ + case ADC_INSERTED_CHANNEL_0: + idata = ADC_IDATA0(adc_periph); + break; + case ADC_INSERTED_CHANNEL_1: + idata = ADC_IDATA1(adc_periph); + break; + case ADC_INSERTED_CHANNEL_2: + idata = ADC_IDATA2(adc_periph); + break; + case ADC_INSERTED_CHANNEL_3: + idata = ADC_IDATA3(adc_periph); + break; + default: + idata = 0U; + break; + } + return (uint16_t)idata; +} + +/*! + \brief read the last ADC0 and ADC1 conversion result data in sync mode + \param[in] none + \param[out] none + \retval the conversion value +*/ +uint32_t adc_sync_mode_convert_value_read(void) +{ + /* return conversion value */ + return ADC_RDATA(ADC0); +} + +/*! + \brief get the ADC flag bits + \param[in] adc_periph: ADCx,x=0,1,2 + only one among these parameters can be selected + \param[in] adc_flag: the adc flag bits + only one parameter can be selected + \arg ADC_FLAG_WDE: analog watchdog event flag + \arg ADC_FLAG_EOC: end of group conversion flag + \arg ADC_FLAG_EOIC: end of inserted group conversion flag + \arg ADC_FLAG_STIC: start flag of inserted channel group + \arg ADC_FLAG_STRC: start flag of regular channel group + \param[out] none + \retval FlagStatus: SET or RESET +*/ +FlagStatus adc_flag_get(uint32_t adc_periph , uint32_t adc_flag) +{ + FlagStatus reval = RESET; + if(ADC_STAT(adc_periph) & adc_flag){ + reval = SET; + } + return reval; +} + +/*! + \brief clear the ADC flag bits + \param[in] adc_periph: ADCx,x=0,1,2 + only one among these parameters can be selected + \param[in] adc_flag: the adc flag bits + one or more parameters can be selected + \arg ADC_FLAG_WDE: analog watchdog event flag + \arg ADC_FLAG_EOC: end of group conversion flag + \arg ADC_FLAG_EOIC: end of inserted group conversion flag + \arg ADC_FLAG_STIC: start flag of inserted channel group + \arg ADC_FLAG_STRC: start flag of regular channel group + \param[out] none + \retval none +*/ +void adc_flag_clear(uint32_t adc_periph , uint32_t adc_flag) +{ + ADC_STAT(adc_periph) &= ~((uint32_t)adc_flag); +} + +/*! + \brief get the ADC interrupt bits + \param[in] adc_periph: ADCx,x=0,1,2 + only one among these parameters can be selected + \param[in] adc_interrupt: the adc interrupt bits + only oneparameter can be selected + \arg ADC_INT_FLAG_WDE: analog watchdog interrupt + \arg ADC_INT_FLAG_EOC: end of group conversion interrupt + \arg ADC_INT_FLAG_EOIC: end of inserted group conversion interrupt + \param[out] none + \retval FlagStatus: SET or RESET +*/ +FlagStatus adc_interrupt_flag_get(uint32_t adc_periph , uint32_t adc_interrupt) +{ + FlagStatus interrupt_flag = RESET; + uint32_t state; + /* check the interrupt bits */ + switch(adc_interrupt){ + case ADC_INT_FLAG_WDE: + state = ADC_STAT(adc_periph) & ADC_STAT_WDE; + if((ADC_CTL0(adc_periph) & ADC_CTL0_WDEIE) && state){ + interrupt_flag = SET; + } + break; + case ADC_INT_FLAG_EOC: + state = ADC_STAT(adc_periph) & ADC_STAT_EOC; + if((ADC_CTL0(adc_periph) & ADC_CTL0_EOCIE) && state){ + interrupt_flag = SET; + } + break; + case ADC_INT_FLAG_EOIC: + state = ADC_STAT(adc_periph) & ADC_STAT_EOIC; + if((ADC_CTL0(adc_periph) & ADC_CTL0_EOICIE) && state){ + interrupt_flag = SET; + } + break; + default: + break; + } + return interrupt_flag; +} + +/*! + \brief clear the ADC flag + \param[in] adc_periph: ADCx,x=0,1,2 + only one among these parameters can be selected + \param[in] adc_interrupt: the adc status flag + one or more parameters can be selected + \arg ADC_INT_FLAG_WDE: analog watchdog interrupt + \arg ADC_INT_FLAG_EOC: end of group conversion interrupt + \arg ADC_INT_FLAG_EOIC: end of inserted group conversion interrupt + \param[out] none + \retval none +*/ +void adc_interrupt_flag_clear(uint32_t adc_periph , uint32_t adc_interrupt) +{ + ADC_STAT(adc_periph) &= ~((uint32_t)adc_interrupt); +} + +/*! + \brief enable ADC interrupt + \param[in] adc_periph: ADCx,x=0,1,2 + only one among these parameters can be selected + \param[in] adc_interrupt: the adc interrupt + one or more parameters can be selected + \arg ADC_INT_WDE: analog watchdog interrupt flag + \arg ADC_INT_EOC: end of group conversion interrupt flag + \arg ADC_INT_EOIC: end of inserted group conversion interrupt flag + \param[out] none + \retval none +*/ +void adc_interrupt_enable(uint32_t adc_periph , uint32_t adc_interrupt) +{ + if(0U != (adc_interrupt & ADC_INT_WDE)){ + ADC_CTL0(adc_periph) |= (uint32_t) ADC_CTL0_WDEIE; + } + + if(0U != (adc_interrupt & ADC_INT_EOC)){ + ADC_CTL0(adc_periph) |= (uint32_t) ADC_CTL0_EOCIE; + } + + if(0U != (adc_interrupt & ADC_INT_EOIC)){ + ADC_CTL0(adc_periph) |= (uint32_t) ADC_CTL0_EOICIE; + } +} + +/*! + \brief disable ADC interrupt + \param[in] adc_periph: ADCx,x=0,1,2 + only one among these parameters can be selected + \param[in] adc_interrupt: the adc interrupt flag + one or more parameters can be selected + \arg ADC_INT_WDE: analog watchdog interrupt flag + \arg ADC_INT_EOC: end of group conversion interrupt flag + \arg ADC_INT_EOIC: end of inserted group conversion interrupt flag + \param[out] none + \retval none +*/ +void adc_interrupt_disable(uint32_t adc_periph, uint32_t adc_interrupt) +{ + if(0U != (adc_interrupt & ADC_INT_WDE)){ + ADC_CTL0(adc_periph) &= ~(uint32_t) ADC_CTL0_WDEIE; + } + + if(0U != (adc_interrupt & ADC_INT_EOC)){ + ADC_CTL0(adc_periph) &= ~(uint32_t) ADC_CTL0_EOCIE; + } + + if(0U != (adc_interrupt & ADC_INT_EOIC)){ + ADC_CTL0(adc_periph) &= ~(uint32_t) ADC_CTL0_EOICIE; + } +} + +/*! + \brief configure ADC analog watchdog single channel + \param[in] adc_periph: ADCx,x=0,1,2 + only one among these parameters can be selected + \param[in] adc_channel: the selected ADC channel + only one among these parameters can be selected + \arg ADC_CHANNEL_x: ADC Channelx(x=0..17)(x=16 and x=17 are only for ADC0) + \param[out] none + \retval none +*/ +void adc_watchdog_single_channel_enable(uint32_t adc_periph, uint8_t adc_channel) +{ + ADC_CTL0(adc_periph) &= (uint32_t)~(ADC_CTL0_RWDEN | ADC_CTL0_IWDEN | ADC_CTL0_WDSC | ADC_CTL0_WDCHSEL); + + ADC_CTL0(adc_periph) |= (uint32_t)adc_channel; + ADC_CTL0(adc_periph) |= (uint32_t)(ADC_CTL0_RWDEN | ADC_CTL0_IWDEN | ADC_CTL0_WDSC); +} + +/*! + \brief configure ADC analog watchdog group channel + \param[in] adc_periph: ADCx,x=0,1,2 + only one among these parameters can be selected + \param[in] adc_channel_group: the channel group use analog watchdog + only one parameter can be selected + \arg ADC_REGULAR_CHANNEL: regular channel group + \arg ADC_INSERTED_CHANNEL: inserted channel group + \arg ADC_REGULAR_INSERTED_CHANNEL: both regular and inserted group + \param[out] none + \retval none +*/ +void adc_watchdog_group_channel_enable(uint32_t adc_periph, uint8_t adc_channel_group) +{ + ADC_CTL0(adc_periph) &= (uint32_t)~(ADC_CTL0_RWDEN | ADC_CTL0_IWDEN | ADC_CTL0_WDSC); + /* select the group */ + switch(adc_channel_group){ + case ADC_REGULAR_CHANNEL: + ADC_CTL0(adc_periph) |= (uint32_t) ADC_CTL0_RWDEN; + break; + case ADC_INSERTED_CHANNEL: + ADC_CTL0(adc_periph) |= (uint32_t) ADC_CTL0_IWDEN; + break; + case ADC_REGULAR_INSERTED_CHANNEL: + ADC_CTL0(adc_periph) |= (uint32_t)(ADC_CTL0_RWDEN | ADC_CTL0_IWDEN); + break; + default: + break; + } +} + +/*! + \brief disable ADC analog watchdog + \param[in] adc_periph: ADCx,x=0,1,2 + only one among these parameters can be selected + \param[out] none + \retval none +*/ +void adc_watchdog_disable(uint32_t adc_periph) +{ + ADC_CTL0(adc_periph) &= (uint32_t)~(ADC_CTL0_RWDEN | ADC_CTL0_IWDEN | ADC_CTL0_WDSC | ADC_CTL0_WDCHSEL); +} + +/*! + \brief configure ADC analog watchdog threshold + \param[in] adc_periph: ADCx,x=0,1,2 + only one among these parameters can be selected + \param[in] low_threshold: analog watchdog low threshold,0..4095 + \param[in] high_threshold: analog watchdog high threshold,0..4095 + \param[out] none + \retval none +*/ +void adc_watchdog_threshold_config(uint32_t adc_periph , uint16_t low_threshold , uint16_t high_threshold) +{ + ADC_WDLT(adc_periph) = (uint32_t)WDLT_WDLT(low_threshold); + ADC_WDHT(adc_periph) = (uint32_t)WDHT_WDHT(high_threshold); +} + +/*! + \brief configure ADC oversample mode + \param[in] adc_periph: ADCx,x=0,1,2 + only one among these parameters can be selected + \param[in] mode: ADC oversampling mode + only oneparameter can be selected + \arg ADC_OVERSAMPLING_ALL_CONVERT: all oversampled conversions for a channel are done consecutively after a trigger + \arg ADC_OVERSAMPLING_ONE_CONVERT: each oversampled conversion for a channel needs a trigger + \param[in] shift: ADC oversampling shift + only oneparameter can be selected + \arg ADC_OVERSAMPLING_SHIFT_NONE: no oversampling shift + \arg ADC_OVERSAMPLING_SHIFT_1B: 1-bit oversampling shift + \arg ADC_OVERSAMPLING_SHIFT_2B: 2-bit oversampling shift + \arg ADC_OVERSAMPLING_SHIFT_3B: 3-bit oversampling shift + \arg ADC_OVERSAMPLING_SHIFT_4B: 3-bit oversampling shift + \arg ADC_OVERSAMPLING_SHIFT_5B: 5-bit oversampling shift + \arg ADC_OVERSAMPLING_SHIFT_6B: 6-bit oversampling shift + \arg ADC_OVERSAMPLING_SHIFT_7B: 7-bit oversampling shift + \arg ADC_OVERSAMPLING_SHIFT_8B: 8-bit oversampling shift + \param[in] ratio: ADC oversampling ratio + only oneparameter can be selected + \arg ADC_OVERSAMPLING_RATIO_MUL2: oversampling ratio multiple 2 + \arg ADC_OVERSAMPLING_RATIO_MUL4: oversampling ratio multiple 4 + \arg ADC_OVERSAMPLING_RATIO_MUL8: oversampling ratio multiple 8 + \arg ADC_OVERSAMPLING_RATIO_MUL16: oversampling ratio multiple 16 + \arg ADC_OVERSAMPLING_RATIO_MUL32: oversampling ratio multiple 32 + \arg ADC_OVERSAMPLING_RATIO_MUL64: oversampling ratio multiple 64 + \arg ADC_OVERSAMPLING_RATIO_MUL128: oversampling ratio multiple 128 + \arg ADC_OVERSAMPLING_RATIO_MUL256: oversampling ratio multiple 256 + \param[out] none + \retval none +*/ +void adc_oversample_mode_config(uint32_t adc_periph, uint32_t mode, uint16_t shift, uint8_t ratio) +{ + if(ADC_OVERSAMPLING_ONE_CONVERT == mode){ + ADC_OVSAMPCTL(adc_periph) |= (uint32_t)ADC_OVSAMPCTL_TOVS; + }else{ + ADC_OVSAMPCTL(adc_periph) &= ~((uint32_t)ADC_OVSAMPCTL_TOVS); + } + /* config the shift and ratio */ + ADC_OVSAMPCTL(adc_periph) &= ~((uint32_t)(ADC_OVSAMPCTL_OVSR | ADC_OVSAMPCTL_OVSS)); + ADC_OVSAMPCTL(adc_periph) |= ((uint32_t)shift | (uint32_t)ratio); +} + +/*! + \brief enable ADC oversample mode + \param[in] adc_periph: ADCx,x=0,1,2 + only one among these parameters can be selected + \param[out] none + \retval none +*/ +void adc_oversample_mode_enable(uint32_t adc_periph) +{ + ADC_OVSAMPCTL(adc_periph) |= ADC_OVSAMPCTL_OVSEN; +} + +/*! + \brief disable ADC oversample mode + \param[in] adc_periph: ADCx,x=0,1,2 + only one among these parameters can be selected + \param[out] none + \retval none +*/ +void adc_oversample_mode_disable(uint32_t adc_periph) +{ + ADC_OVSAMPCTL(adc_periph) &= ~((uint32_t)ADC_OVSAMPCTL_OVSEN); +} diff --git a/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_standard_peripheral/Source/gd32f30x_bkp.c b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_standard_peripheral/Source/gd32f30x_bkp.c new file mode 100644 index 0000000000..3aeab280e2 --- /dev/null +++ b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_standard_peripheral/Source/gd32f30x_bkp.c @@ -0,0 +1,328 @@ +/*! + \file gd32f30x_bkp.c + \brief BKP driver + + \version 2017-02-10, V1.0.0, firmware for GD32F30x + \version 2018-10-10, V1.1.0, firmware for GD32F30x + \version 2018-12-25, V2.0.0, firmware for GD32F30x + \version 2020-09-30, V2.1.0, firmware for GD32F30x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "gd32f30x_bkp.h" + +#define TAMPER_FLAG_SHIFT ((uint8_t)8U) + +/*! + \brief reset BKP registers + \param[in] none + \param[out] none + \retval none +*/ +void bkp_deinit(void) +{ + /* reset BKP domain register*/ + rcu_bkp_reset_enable(); + rcu_bkp_reset_disable(); +} + +/*! + \brief write BKP data register + \param[in] register_number: refer to bkp_data_register_enum, only one parameter can be selected + \arg BKP_DATA_x(x = 0..41): bkp data register number x + \param[in] data: the data to be write in BKP data register + \param[out] none + \retval none +*/ +void bkp_write_data(bkp_data_register_enum register_number, uint16_t data) +{ + if((register_number >= BKP_DATA_10) && (register_number <= BKP_DATA_41)){ + BKP_DATA10_41(register_number-1U) = data; + }else if((register_number >= BKP_DATA_0) && (register_number <= BKP_DATA_9)){ + BKP_DATA0_9(register_number-1U) = data; + }else{ + /* illegal parameters */ + } +} + +/*! + \brief read BKP data register + \param[in] register_number: refer to bkp_data_register_enum, only one parameter can be selected + \arg BKP_DATA_x(x = 0..41): bkp data register number x + \param[out] none + \retval data of BKP data register +*/ +uint16_t bkp_read_data(bkp_data_register_enum register_number) +{ + uint16_t data = 0U; + + /* get the data from the BKP data register */ + if((register_number >= BKP_DATA_10) && (register_number <= BKP_DATA_41)){ + data = BKP_DATA10_41(register_number-1U); + }else if((register_number >= BKP_DATA_0) && (register_number <= BKP_DATA_9)){ + data = BKP_DATA0_9(register_number-1U); + }else{ + /* illegal parameters */ + } + return data; +} + +/*! + \brief enable RTC clock calibration output + \param[in] none + \param[out] none + \retval none +*/ +void bkp_rtc_calibration_output_enable(void) +{ + BKP_OCTL |= (uint16_t)BKP_OCTL_COEN; +} + +/*! + \brief disable RTC clock calibration output + \param[in] none + \param[out] none + \retval none +*/ +void bkp_rtc_calibration_output_disable(void) +{ + BKP_OCTL &= (uint16_t)~BKP_OCTL_COEN; +} + +/*! + \brief enable RTC alarm or second signal output + \param[in] none + \param[out] none + \retval none +*/ +void bkp_rtc_signal_output_enable(void) +{ + BKP_OCTL |= (uint16_t)BKP_OCTL_ASOEN; +} + +/*! + \brief disable RTC alarm or second signal output + \param[in] none + \param[out] none + \retval none +*/ +void bkp_rtc_signal_output_disable(void) +{ + BKP_OCTL &= (uint16_t)~BKP_OCTL_ASOEN; +} + +/*! + \brief select RTC output + \param[in] outputsel: RTC output selection + \arg RTC_OUTPUT_ALARM_PULSE: RTC alarm pulse is selected as the RTC output + \arg RTC_OUTPUT_SECOND_PULSE: RTC second pulse is selected as the RTC output + \param[out] none + \retval none +*/ +void bkp_rtc_output_select(uint16_t outputsel) +{ + uint16_t ctl = 0U; + + ctl = BKP_OCTL; + ctl &= (uint16_t)~BKP_OCTL_ROSEL; + ctl |= outputsel; + BKP_OCTL = ctl; +} + +/*! + \brief select RTC clock output + \param[in] clocksel: RTC clock output selection + \arg RTC_CLOCK_DIV_64: RTC clock div 64 + \arg RTC_CLOCK_DIV_1: RTC clock + \param[out] none + \retval none +*/ +void bkp_rtc_clock_output_select(uint16_t clocksel) +{ + uint16_t ctl = 0U; + + ctl = BKP_OCTL; + ctl &= (uint16_t)~BKP_OCTL_CCOSEL; + ctl |= clocksel; + BKP_OCTL = ctl; +} + +/*! + \brief RTC clock calibration direction + \param[in] direction: RTC clock calibration direction + \arg RTC_CLOCK_SLOWED_DOWN: RTC clock slow down + \arg RTC_CLOCK_SPEED_UP: RTC clock speed up + \param[out] none + \retval none +*/ +void bkp_rtc_clock_calibration_direction(uint16_t direction) +{ + uint16_t ctl = 0U; + + ctl = BKP_OCTL; + ctl &= (uint16_t)~BKP_OCTL_CALDIR; + ctl |= direction; + BKP_OCTL = ctl; +} + +/*! + \brief set RTC clock calibration value + \param[in] value: RTC clock calibration value + \arg 0x00 - 0x7F + \param[out] none + \retval none +*/ +void bkp_rtc_calibration_value_set(uint8_t value) +{ + uint16_t ctl; + + ctl = BKP_OCTL; + ctl &= ~(uint16_t)BKP_OCTL_RCCV; + ctl |= (uint16_t)OCTL_RCCV(value); + BKP_OCTL = ctl; +} + +/*! + \brief enable tamper detection + \param[in] none + \param[out] none + \retval none +*/ +void bkp_tamper_detection_enable(void) +{ + BKP_TPCTL |= (uint16_t)BKP_TPCTL_TPEN; +} + +/*! + \brief disable tamper detection + \param[in] none + \param[out] none + \retval none +*/ +void bkp_tamper_detection_disable(void) +{ + BKP_TPCTL &= (uint16_t)~BKP_TPCTL_TPEN; +} + +/*! + \brief set tamper pin active level + \param[in] level: tamper active level + \arg TAMPER_PIN_ACTIVE_HIGH: the tamper pin is active high + \arg TAMPER_PIN_ACTIVE_LOW: the tamper pin is active low + \param[out] none + \retval none +*/ +void bkp_tamper_active_level_set(uint16_t level) +{ + uint16_t ctl = 0U; + + ctl = BKP_TPCTL; + ctl &= (uint16_t)~BKP_TPCTL_TPAL; + ctl |= level; + BKP_TPCTL = ctl; +} + +/*! + \brief enable tamper interrupt + \param[in] none + \param[out] none + \retval none +*/ +void bkp_tamper_interrupt_enable(void) +{ + BKP_TPCS |= (uint16_t)BKP_TPCS_TPIE; +} + +/*! + \brief disable tamper interrupt + \param[in] none + \param[out] none + \retval none +*/ +void bkp_tamper_interrupt_disable(void) +{ + BKP_TPCS &= (uint16_t)~BKP_TPCS_TPIE; +} + +/*! + \brief get bkp flag state + \param[in] flag + \arg BKP_FLAG_TAMPER: tamper event flag + \param[out] none + \retval FlagStatus: SET or RESET +*/ +FlagStatus bkp_flag_get(uint16_t flag) +{ + if(RESET != (BKP_TPCS & flag)){ + return SET; + }else{ + return RESET; + } +} + +/*! + \brief clear bkp flag state + \param[in] flag + \arg BKP_FLAG_TAMPER: tamper event flag + \param[out] none + \retval none +*/ +void bkp_flag_clear(uint16_t flag) +{ + BKP_TPCS |= (uint16_t)(flag >> TAMPER_FLAG_SHIFT); +} + +/*! + \brief get bkp interrupt flag state + \param[in] flag + \arg BKP_INT_FLAG_TAMPER: tamper interrupt flag + \param[out] none + \retval FlagStatus: SET or RESET +*/ +FlagStatus bkp_interrupt_flag_get(uint16_t flag) +{ + if(RESET != (BKP_TPCS & flag)){ + return SET; + }else{ + return RESET; + } +} + +/*! + \brief clear bkp interrupt flag state + \param[in] flag + \arg BKP_INT_FLAG_TAMPER: tamper interrupt flag + \param[out] none + \retval none +*/ +void bkp_interrupt_flag_clear(uint16_t flag) +{ + BKP_TPCS |= (uint16_t)(flag >> TAMPER_FLAG_SHIFT); +} + diff --git a/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_standard_peripheral/Source/gd32f30x_can.c b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_standard_peripheral/Source/gd32f30x_can.c new file mode 100644 index 0000000000..e26e5df00a --- /dev/null +++ b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_standard_peripheral/Source/gd32f30x_can.c @@ -0,0 +1,1042 @@ +/*! + \file gd32f30x_can.c + \brief CAN driver + + \version 2017-02-10, V1.0.0, firmware for GD32F30x + \version 2018-10-10, V1.1.0, firmware for GD32F30x + \version 2018-12-25, V2.0.0, firmware for GD32F30x + \version 2019-11-27, V2.0.1, firmware for GD32F30x + \version 2020-03-02, V2.0.2, firmware for GD32F30x + \version 2020-07-14, V2.0.3, firmware for GD32F30x + \version 2020-09-30, V2.1.0, firmware for GD32F30x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "gd32f30x_can.h" +#include + +#define CAN_ERROR_HANDLE(s) do{}while(1) + +/*! + \brief deinitialize CAN + \param[in] can_periph + \arg CANx(x=0,1),the CAN1 only for GD32F30X_CL + \param[out] none + \retval none +*/ +void can_deinit(uint32_t can_periph) +{ +#ifdef GD32F30X_CL + if(CAN0 == can_periph){ + rcu_periph_reset_enable(RCU_CAN0RST); + rcu_periph_reset_disable(RCU_CAN0RST); + }else{ + rcu_periph_reset_enable(RCU_CAN1RST); + rcu_periph_reset_disable(RCU_CAN1RST); + } +#else + if(CAN0 == can_periph){ + rcu_periph_reset_enable(RCU_CAN0RST); + rcu_periph_reset_disable(RCU_CAN0RST); + } +#endif +} + +/*! + \brief initialize CAN parameter struct with a default value + \param[in] type: the type of CAN parameter struct + only one parameter can be selected which is shown as below: + \arg CAN_INIT_STRUCT: the CAN initial struct + \arg CAN_FILTER_STRUCT: the CAN filter struct + \arg CAN_TX_MESSAGE_STRUCT: the CAN TX message struct + \arg CAN_RX_MESSAGE_STRUCT: the CAN RX message struct + \param[in] p_struct: the pointer of the specific struct + \param[out] none + \retval none +*/ +void can_struct_para_init(can_struct_type_enum type, void* p_struct) +{ + uint8_t i; + + if(NULL == p_struct){ + CAN_ERROR_HANDLE("struct parameter can not be NULL \r\n"); + } + + /* get type of the struct */ + switch(type){ + /* used for can_init() */ + case CAN_INIT_STRUCT: + ((can_parameter_struct*)p_struct)->auto_bus_off_recovery = DISABLE; + ((can_parameter_struct*)p_struct)->no_auto_retrans = DISABLE; + ((can_parameter_struct*)p_struct)->auto_wake_up = DISABLE; + ((can_parameter_struct*)p_struct)->prescaler = 0x03FFU; + ((can_parameter_struct*)p_struct)->rec_fifo_overwrite = DISABLE; + ((can_parameter_struct*)p_struct)->resync_jump_width = CAN_BT_SJW_1TQ; + ((can_parameter_struct*)p_struct)->time_segment_1 = CAN_BT_BS1_3TQ; + ((can_parameter_struct*)p_struct)->time_segment_2 = CAN_BT_BS2_1TQ; + ((can_parameter_struct*)p_struct)->time_triggered = DISABLE; + ((can_parameter_struct*)p_struct)->trans_fifo_order = DISABLE; + ((can_parameter_struct*)p_struct)->working_mode = CAN_NORMAL_MODE; + + break; + /* used for can_filter_init() */ + case CAN_FILTER_STRUCT: + ((can_filter_parameter_struct*)p_struct)->filter_bits = CAN_FILTERBITS_32BIT; + ((can_filter_parameter_struct*)p_struct)->filter_enable = DISABLE; + ((can_filter_parameter_struct*)p_struct)->filter_fifo_number = CAN_FIFO0; + ((can_filter_parameter_struct*)p_struct)->filter_list_high = 0x0000U; + ((can_filter_parameter_struct*)p_struct)->filter_list_low = 0x0000U; + ((can_filter_parameter_struct*)p_struct)->filter_mask_high = 0x0000U; + ((can_filter_parameter_struct*)p_struct)->filter_mask_low = 0x0000U; + ((can_filter_parameter_struct*)p_struct)->filter_mode = CAN_FILTERMODE_MASK; + ((can_filter_parameter_struct*)p_struct)->filter_number = 0U; + + break; + /* used for can_message_transmit() */ + case CAN_TX_MESSAGE_STRUCT: + for(i = 0U; i < 8U; i++){ + ((can_trasnmit_message_struct*)p_struct)->tx_data[i] = 0U; + } + + ((can_trasnmit_message_struct*)p_struct)->tx_dlen = 0u; + ((can_trasnmit_message_struct*)p_struct)->tx_efid = 0U; + ((can_trasnmit_message_struct*)p_struct)->tx_ff = (uint8_t)CAN_FF_STANDARD; + ((can_trasnmit_message_struct*)p_struct)->tx_ft = (uint8_t)CAN_FT_DATA; + ((can_trasnmit_message_struct*)p_struct)->tx_sfid = 0U; + + break; + /* used for can_message_receive() */ + case CAN_RX_MESSAGE_STRUCT: + for(i = 0U; i < 8U; i++){ + ((can_receive_message_struct*)p_struct)->rx_data[i] = 0U; + } + + ((can_receive_message_struct*)p_struct)->rx_dlen = 0U; + ((can_receive_message_struct*)p_struct)->rx_efid = 0U; + ((can_receive_message_struct*)p_struct)->rx_ff = (uint8_t)CAN_FF_STANDARD; + ((can_receive_message_struct*)p_struct)->rx_fi = 0U; + ((can_receive_message_struct*)p_struct)->rx_ft = (uint8_t)CAN_FT_DATA; + ((can_receive_message_struct*)p_struct)->rx_sfid = 0U; + + break; + + default: + CAN_ERROR_HANDLE("parameter is invalid \r\n"); + } +} + +/*! + \brief initialize CAN + \param[in] can_periph + \arg CANx(x=0,1),the CAN1 only for GD32F30X_CL + \param[in] can_parameter_init: parameters for CAN initializtion + \arg working_mode: CAN_NORMAL_MODE, CAN_LOOPBACK_MODE, CAN_SILENT_MODE, CAN_SILENT_LOOPBACK_MODE + \arg resync_jump_width: CAN_BT_SJW_xTQ(x=1, 2, 3, 4) + \arg time_segment_1: CAN_BT_BS1_xTQ(1..16) + \arg time_segment_2: CAN_BT_BS2_xTQ(1..8) + \arg time_triggered: ENABLE or DISABLE + \arg auto_bus_off_recovery: ENABLE or DISABLE + \arg auto_wake_up: ENABLE or DISABLE + \arg no_auto_retrans: ENABLE or DISABLE + \arg rec_fifo_overwrite: ENABLE or DISABLE + \arg trans_fifo_order: ENABLE or DISABLE + \arg prescaler: 0x0001 - 0x0400 + \param[out] none + \retval ErrStatus: SUCCESS or ERROR +*/ +ErrStatus can_init(uint32_t can_periph, can_parameter_struct* can_parameter_init) +{ + uint32_t timeout = CAN_TIMEOUT; + ErrStatus flag = ERROR; + + /* disable sleep mode */ + CAN_CTL(can_periph) &= ~CAN_CTL_SLPWMOD; + /* enable initialize mode */ + CAN_CTL(can_periph) |= CAN_CTL_IWMOD; + /* wait ACK */ + while((CAN_STAT_IWS != (CAN_STAT(can_periph) & CAN_STAT_IWS)) && (0U != timeout)){ + timeout--; + } + /* check initialize working success */ + if(CAN_STAT_IWS != (CAN_STAT(can_periph) & CAN_STAT_IWS)){ + flag = ERROR; + }else{ + /* set the bit timing register */ + CAN_BT(can_periph) = (BT_MODE((uint32_t)can_parameter_init->working_mode) | \ + BT_SJW((uint32_t)can_parameter_init->resync_jump_width) | \ + BT_BS1((uint32_t)can_parameter_init->time_segment_1) | \ + BT_BS2((uint32_t)can_parameter_init->time_segment_2) | \ + BT_BAUDPSC(((uint32_t)(can_parameter_init->prescaler) - 1U))); + + /* time trigger communication mode */ + if(ENABLE == can_parameter_init->time_triggered){ + CAN_CTL(can_periph) |= CAN_CTL_TTC; + }else{ + CAN_CTL(can_periph) &= ~CAN_CTL_TTC; + } + /* automatic bus-off managment */ + if(ENABLE == can_parameter_init->auto_bus_off_recovery){ + CAN_CTL(can_periph) |= CAN_CTL_ABOR; + }else{ + CAN_CTL(can_periph) &= ~CAN_CTL_ABOR; + } + /* automatic wakeup mode */ + if(ENABLE == can_parameter_init->auto_wake_up){ + CAN_CTL(can_periph) |= CAN_CTL_AWU; + }else{ + CAN_CTL(can_periph) &= ~CAN_CTL_AWU; + } + /* automatic retransmission mode disable */ + if(ENABLE == can_parameter_init->no_auto_retrans){ + CAN_CTL(can_periph) |= CAN_CTL_ARD; + }else{ + CAN_CTL(can_periph) &= ~CAN_CTL_ARD; + } + /* receive fifo overwrite mode */ + if(ENABLE == can_parameter_init->rec_fifo_overwrite){ + CAN_CTL(can_periph) |= CAN_CTL_RFOD; + }else{ + CAN_CTL(can_periph) &= ~CAN_CTL_RFOD; + } + /* transmit fifo order */ + if(ENABLE == can_parameter_init->trans_fifo_order){ + CAN_CTL(can_periph) |= CAN_CTL_TFO; + }else{ + CAN_CTL(can_periph) &= ~CAN_CTL_TFO; + } + /* disable initialize mode */ + CAN_CTL(can_periph) &= ~CAN_CTL_IWMOD; + timeout = CAN_TIMEOUT; + /* wait the ACK */ + while((CAN_STAT_IWS == (CAN_STAT(can_periph) & CAN_STAT_IWS)) && (0U != timeout)){ + timeout--; + } + /* check exit initialize mode */ + if(0U != timeout){ + flag = SUCCESS; + } + } + return flag; +} + +/*! + \brief initialize CAN filter + \param[in] can_filter_parameter_init: struct for CAN filter initialization + \arg filter_list_high: 0x0000 - 0xFFFF + \arg filter_list_low: 0x0000 - 0xFFFF + \arg filter_mask_high: 0x0000 - 0xFFFF + \arg filter_mask_low: 0x0000 - 0xFFFF + \arg filter_fifo_number: CAN_FIFO0, CAN_FIFO1 + \arg filter_number: 0 - 27 + \arg filter_mode: CAN_FILTERMODE_MASK, CAN_FILTERMODE_LIST + \arg filter_bits: CAN_FILTERBITS_32BIT, CAN_FILTERBITS_16BIT + \arg filter_enable: ENABLE or DISABLE + \param[out] none + \retval none +*/ +void can_filter_init(can_filter_parameter_struct* can_filter_parameter_init) +{ + uint32_t val = 0U; + + val = ((uint32_t)1) << (can_filter_parameter_init->filter_number); + /* filter lock disable */ + CAN_FCTL(CAN0) |= CAN_FCTL_FLD; + /* disable filter */ + CAN_FW(CAN0) &= ~(uint32_t)val; + + /* filter 16 bits */ + if(CAN_FILTERBITS_16BIT == can_filter_parameter_init->filter_bits){ + /* set filter 16 bits */ + CAN_FSCFG(CAN0) &= ~(uint32_t)val; + /* first 16 bits list and first 16 bits mask or first 16 bits list and second 16 bits list */ + CAN_FDATA0(CAN0, can_filter_parameter_init->filter_number) = \ + FDATA_MASK_HIGH((can_filter_parameter_init->filter_mask_low) & CAN_FILTER_MASK_16BITS) | \ + FDATA_MASK_LOW((can_filter_parameter_init->filter_list_low) & CAN_FILTER_MASK_16BITS); + /* second 16 bits list and second 16 bits mask or third 16 bits list and fourth 16 bits list */ + CAN_FDATA1(CAN0, can_filter_parameter_init->filter_number) = \ + FDATA_MASK_HIGH((can_filter_parameter_init->filter_mask_high) & CAN_FILTER_MASK_16BITS) | \ + FDATA_MASK_LOW((can_filter_parameter_init->filter_list_high) & CAN_FILTER_MASK_16BITS); + } + /* filter 32 bits */ + if(CAN_FILTERBITS_32BIT == can_filter_parameter_init->filter_bits){ + /* set filter 32 bits */ + CAN_FSCFG(CAN0) |= (uint32_t)val; + /* 32 bits list or first 32 bits list */ + CAN_FDATA0(CAN0, can_filter_parameter_init->filter_number) = \ + FDATA_MASK_HIGH((can_filter_parameter_init->filter_list_high) & CAN_FILTER_MASK_16BITS) | + FDATA_MASK_LOW((can_filter_parameter_init->filter_list_low) & CAN_FILTER_MASK_16BITS); + /* 32 bits mask or second 32 bits list */ + CAN_FDATA1(CAN0, can_filter_parameter_init->filter_number) = \ + FDATA_MASK_HIGH((can_filter_parameter_init->filter_mask_high) & CAN_FILTER_MASK_16BITS) | + FDATA_MASK_LOW((can_filter_parameter_init->filter_mask_low) & CAN_FILTER_MASK_16BITS); + } + + /* filter mode */ + if(CAN_FILTERMODE_MASK == can_filter_parameter_init->filter_mode){ + /* mask mode */ + CAN_FMCFG(CAN0) &= ~(uint32_t)val; + }else{ + /* list mode */ + CAN_FMCFG(CAN0) |= (uint32_t)val; + } + + /* filter FIFO */ + if(CAN_FIFO0 == (can_filter_parameter_init->filter_fifo_number)){ + /* FIFO0 */ + CAN_FAFIFO(CAN0) &= ~(uint32_t)val; + }else{ + /* FIFO1 */ + CAN_FAFIFO(CAN0) |= (uint32_t)val; + } + + /* filter working */ + if(ENABLE == can_filter_parameter_init->filter_enable){ + + CAN_FW(CAN0) |= (uint32_t)val; + } + + /* filter lock enable */ + CAN_FCTL(CAN0) &= ~CAN_FCTL_FLD; +} + +/*! + \brief set CAN1 fliter start bank number + \param[in] start_bank: CAN1 start bank number + only one parameter can be selected which is shown as below: + \arg (1..27) + \param[out] none + \retval none +*/ +void can1_filter_start_bank(uint8_t start_bank) +{ + /* filter lock disable */ + CAN_FCTL(CAN0) |= CAN_FCTL_FLD; + /* set CAN1 filter start number */ + CAN_FCTL(CAN0) &= ~(uint32_t)CAN_FCTL_HBC1F; + CAN_FCTL(CAN0) |= FCTL_HBC1F(start_bank); + /* filter lock enaable */ + CAN_FCTL(CAN0) &= ~CAN_FCTL_FLD; +} + +/*! + \brief enable CAN debug freeze + \param[in] can_periph + \arg CANx(x=0,1),the CAN1 only for GD32F30X_CL + \param[out] none + \retval none +*/ +void can_debug_freeze_enable(uint32_t can_periph) +{ + CAN_CTL(can_periph) |= CAN_CTL_DFZ; +#ifdef GD32F30X_CL + if(CAN0 == can_periph){ + dbg_periph_enable(DBG_CAN0_HOLD); + }else{ + dbg_periph_enable(DBG_CAN1_HOLD); + } +#else + if(CAN0 == can_periph){ + dbg_periph_enable(DBG_CAN0_HOLD); + } +#endif +} + +/*! + \brief disable CAN debug freeze + \param[in] can_periph + \arg CANx(x=0,1),the CAN1 only for GD32F30X_CL + \param[out] none + \retval none +*/ +void can_debug_freeze_disable(uint32_t can_periph) +{ + CAN_CTL(can_periph) &= ~CAN_CTL_DFZ; +#ifdef GD32F30X_CL + if(CAN0 == can_periph){ + dbg_periph_disable(DBG_CAN0_HOLD); + }else{ + dbg_periph_disable(DBG_CAN1_HOLD); + } +#else + if(CAN0 == can_periph){ + dbg_periph_enable(DBG_CAN0_HOLD); + } +#endif +} + +/*! + \brief enable CAN time trigger mode + \param[in] can_periph + \arg CANx(x=0,1),the CAN1 only for GD32F30X_CL + \param[out] none + \retval none +*/ +void can_time_trigger_mode_enable(uint32_t can_periph) +{ + uint8_t mailbox_number; + + /* enable the tcc mode */ + CAN_CTL(can_periph) |= CAN_CTL_TTC; + /* enable time stamp */ + for(mailbox_number = 0U; mailbox_number < 3U; mailbox_number++){ + CAN_TMP(can_periph, mailbox_number) |= CAN_TMP_TSEN; + } +} + +/*! + \brief disable CAN time trigger mode + \param[in] can_periph + \arg CANx(x=0,1),the CAN1 only for GD32F30X_CL + \param[out] none + \retval none +*/ +void can_time_trigger_mode_disable(uint32_t can_periph) +{ + uint8_t mailbox_number; + + /* disable the TCC mode */ + CAN_CTL(can_periph) &= ~CAN_CTL_TTC; + /* reset TSEN bits */ + for(mailbox_number = 0U; mailbox_number < 3U; mailbox_number++){ + CAN_TMP(can_periph, mailbox_number) &= ~CAN_TMP_TSEN; + } +} + +/*! + \brief transmit CAN message + \param[in] can_periph + \arg CANx(x=0,1),the CAN1 only for GD32F30X_CL + \param[in] transmit_message: struct for CAN transmit message + \arg tx_sfid: 0x00000000 - 0x000007FF + \arg tx_efid: 0x00000000 - 0x1FFFFFFF + \arg tx_ff: CAN_FF_STANDARD, CAN_FF_EXTENDED + \arg tx_ft: CAN_FT_DATA, CAN_FT_REMOTE + \arg tx_dlen: 0 - 8 + \arg tx_data[]: 0x00 - 0xFF + \param[out] none + \retval mailbox_number +*/ +uint8_t can_message_transmit(uint32_t can_periph, can_trasnmit_message_struct* transmit_message) +{ + uint8_t mailbox_number = CAN_MAILBOX0; + + /* select one empty mailbox */ + if(CAN_TSTAT_TME0 == (CAN_TSTAT(can_periph)&CAN_TSTAT_TME0)){ + mailbox_number = CAN_MAILBOX0; + }else if(CAN_TSTAT_TME1 == (CAN_TSTAT(can_periph)&CAN_TSTAT_TME1)){ + mailbox_number = CAN_MAILBOX1; + }else if(CAN_TSTAT_TME2 == (CAN_TSTAT(can_periph)&CAN_TSTAT_TME2)){ + mailbox_number = CAN_MAILBOX2; + }else{ + mailbox_number = CAN_NOMAILBOX; + } + /* return no mailbox empty */ + if(CAN_NOMAILBOX == mailbox_number){ + return CAN_NOMAILBOX; + } + + CAN_TMI(can_periph, mailbox_number) &= CAN_TMI_TEN; + if(CAN_FF_STANDARD == transmit_message->tx_ff){ + /* set transmit mailbox standard identifier */ + CAN_TMI(can_periph, mailbox_number) |= (uint32_t)(TMI_SFID(transmit_message->tx_sfid) | \ + transmit_message->tx_ft); + }else{ + /* set transmit mailbox extended identifier */ + CAN_TMI(can_periph, mailbox_number) |= (uint32_t)(TMI_EFID(transmit_message->tx_efid) | \ + transmit_message->tx_ff | \ + transmit_message->tx_ft); + } + /* set the data length */ + CAN_TMP(can_periph, mailbox_number) &= ~CAN_TMP_DLENC; + CAN_TMP(can_periph, mailbox_number) |= transmit_message->tx_dlen; + /* set the data */ + CAN_TMDATA0(can_periph, mailbox_number) = TMDATA0_DB3(transmit_message->tx_data[3]) | \ + TMDATA0_DB2(transmit_message->tx_data[2]) | \ + TMDATA0_DB1(transmit_message->tx_data[1]) | \ + TMDATA0_DB0(transmit_message->tx_data[0]); + CAN_TMDATA1(can_periph, mailbox_number) = TMDATA1_DB7(transmit_message->tx_data[7]) | \ + TMDATA1_DB6(transmit_message->tx_data[6]) | \ + TMDATA1_DB5(transmit_message->tx_data[5]) | \ + TMDATA1_DB4(transmit_message->tx_data[4]); + /* enable transmission */ + CAN_TMI(can_periph, mailbox_number) |= CAN_TMI_TEN; + + return mailbox_number; +} + +/*! + \brief get CAN transmit state + \param[in] can_periph + \arg CANx(x=0,1),the CAN1 only for GD32F30X_CL + \param[in] mailbox_number + only one parameter can be selected which is shown as below: + \arg CAN_MAILBOX(x=0,1,2) + \param[out] none + \retval can_transmit_state_enum +*/ +can_transmit_state_enum can_transmit_states(uint32_t can_periph, uint8_t mailbox_number) +{ + can_transmit_state_enum state = CAN_TRANSMIT_FAILED; + uint32_t val = 0U; + + /* check selected mailbox state */ + switch(mailbox_number){ + /* mailbox0 */ + case CAN_MAILBOX0: + val = CAN_TSTAT(can_periph) & (CAN_TSTAT_MTF0 | CAN_TSTAT_MTFNERR0 | CAN_TSTAT_TME0); + break; + /* mailbox1 */ + case CAN_MAILBOX1: + val = CAN_TSTAT(can_periph) & (CAN_TSTAT_MTF1 | CAN_TSTAT_MTFNERR1 | CAN_TSTAT_TME1); + break; + /* mailbox2 */ + case CAN_MAILBOX2: + val = CAN_TSTAT(can_periph) & (CAN_TSTAT_MTF2 | CAN_TSTAT_MTFNERR2 | CAN_TSTAT_TME2); + break; + default: + val = CAN_TRANSMIT_FAILED; + break; + } + + switch(val){ + /* transmit pending */ + case (CAN_STATE_PENDING): + state = CAN_TRANSMIT_PENDING; + break; + /* mailbox0 transmit succeeded */ + case (CAN_TSTAT_MTF0 | CAN_TSTAT_MTFNERR0 | CAN_TSTAT_TME0): + state = CAN_TRANSMIT_OK; + break; + /* mailbox1 transmit succeeded */ + case (CAN_TSTAT_MTF1 | CAN_TSTAT_MTFNERR1 | CAN_TSTAT_TME1): + state = CAN_TRANSMIT_OK; + break; + /* mailbox2 transmit succeeded */ + case (CAN_TSTAT_MTF2 | CAN_TSTAT_MTFNERR2 | CAN_TSTAT_TME2): + state = CAN_TRANSMIT_OK; + break; + /* transmit failed */ + default: + state = CAN_TRANSMIT_FAILED; + break; + } + return state; +} + +/*! + \brief stop CAN transmission + \param[in] can_periph + \arg CANx(x=0,1),the CAN1 only for GD32F30X_CL + \param[in] mailbox_number + only one parameter can be selected which is shown as below: + \arg CAN_MAILBOXx(x=0,1,2) + \param[out] none + \retval none +*/ +void can_transmission_stop(uint32_t can_periph, uint8_t mailbox_number) +{ + if(CAN_MAILBOX0 == mailbox_number){ + CAN_TSTAT(can_periph) |= CAN_TSTAT_MST0; + while(CAN_TSTAT_MST0 == (CAN_TSTAT(can_periph) & CAN_TSTAT_MST0)){ + } + }else if(CAN_MAILBOX1 == mailbox_number){ + CAN_TSTAT(can_periph) |= CAN_TSTAT_MST1; + while(CAN_TSTAT_MST1 == (CAN_TSTAT(can_periph) & CAN_TSTAT_MST1)){ + } + }else if(CAN_MAILBOX2 == mailbox_number){ + CAN_TSTAT(can_periph) |= CAN_TSTAT_MST2; + while(CAN_TSTAT_MST2 == (CAN_TSTAT(can_periph) & CAN_TSTAT_MST2)){ + } + }else{ + /* illegal parameters */ + } +} + +/*! + \brief CAN receive message + \param[in] can_periph + \arg CANx(x=0,1),the CAN1 only for GD32F30X_CL + \param[in] fifo_number + \arg CAN_FIFOx(x=0,1) + \param[out] receive_message: struct for CAN receive message + \arg rx_sfid: 0x00000000 - 0x000007FF + \arg rx_efid: 0x00000000 - 0x1FFFFFFF + \arg rx_ff: CAN_FF_STANDARD, CAN_FF_EXTENDED + \arg rx_ft: CAN_FT_DATA, CAN_FT_REMOTE + \arg rx_dlen: 0 - 8 + \arg rx_data[]: 0x00 - 0xFF + \arg rx_fi: 0 - 27 + \retval none +*/ +void can_message_receive(uint32_t can_periph, uint8_t fifo_number, can_receive_message_struct* receive_message) +{ + /* get the frame format */ + receive_message->rx_ff = (uint8_t)(CAN_RFIFOMI_FF & CAN_RFIFOMI(can_periph, fifo_number)); + if(CAN_FF_STANDARD == receive_message->rx_ff){ + /* get standard identifier */ + receive_message->rx_sfid = (uint32_t)(GET_RFIFOMI_SFID(CAN_RFIFOMI(can_periph, fifo_number))); + }else{ + /* get extended identifier */ + receive_message->rx_efid = (uint32_t)(GET_RFIFOMI_EFID(CAN_RFIFOMI(can_periph, fifo_number))); + } + + /* get frame type */ + receive_message->rx_ft = (uint8_t)(CAN_RFIFOMI_FT & CAN_RFIFOMI(can_periph, fifo_number)); + /* filtering index */ + receive_message->rx_fi = (uint8_t)(GET_RFIFOMP_FI(CAN_RFIFOMP(can_periph, fifo_number))); + /* get recevie data length */ + receive_message->rx_dlen = (uint8_t)(GET_RFIFOMP_DLENC(CAN_RFIFOMP(can_periph, fifo_number))); + + /* receive data */ + receive_message -> rx_data[0] = (uint8_t)(GET_RFIFOMDATA0_DB0(CAN_RFIFOMDATA0(can_periph, fifo_number))); + receive_message -> rx_data[1] = (uint8_t)(GET_RFIFOMDATA0_DB1(CAN_RFIFOMDATA0(can_periph, fifo_number))); + receive_message -> rx_data[2] = (uint8_t)(GET_RFIFOMDATA0_DB2(CAN_RFIFOMDATA0(can_periph, fifo_number))); + receive_message -> rx_data[3] = (uint8_t)(GET_RFIFOMDATA0_DB3(CAN_RFIFOMDATA0(can_periph, fifo_number))); + receive_message -> rx_data[4] = (uint8_t)(GET_RFIFOMDATA1_DB4(CAN_RFIFOMDATA1(can_periph, fifo_number))); + receive_message -> rx_data[5] = (uint8_t)(GET_RFIFOMDATA1_DB5(CAN_RFIFOMDATA1(can_periph, fifo_number))); + receive_message -> rx_data[6] = (uint8_t)(GET_RFIFOMDATA1_DB6(CAN_RFIFOMDATA1(can_periph, fifo_number))); + receive_message -> rx_data[7] = (uint8_t)(GET_RFIFOMDATA1_DB7(CAN_RFIFOMDATA1(can_periph, fifo_number))); + + /* release FIFO */ + if(CAN_FIFO0 == fifo_number){ + CAN_RFIFO0(can_periph) |= CAN_RFIFO0_RFD0; + }else{ + CAN_RFIFO1(can_periph) |= CAN_RFIFO1_RFD1; + } +} + +/*! + \brief release FIFO0 + \param[in] can_periph + \arg CANx(x=0,1),the CAN1 only for GD32F30X_CL + \param[in] fifo_number + only one parameter can be selected which is shown as below: + \arg CAN_FIFOx(x=0,1) + \param[out] none + \retval none +*/ +void can_fifo_release(uint32_t can_periph, uint8_t fifo_number) +{ + if(CAN_FIFO0 == fifo_number){ + CAN_RFIFO0(can_periph) |= CAN_RFIFO0_RFD0; + }else if(CAN_FIFO1 == fifo_number){ + CAN_RFIFO1(can_periph) |= CAN_RFIFO1_RFD1; + }else{ + /* illegal parameters */ + CAN_ERROR_HANDLE("CAN FIFO NUM is invalid \r\n"); + } +} + +/*! + \brief CAN receive message length + \param[in] can_periph + \arg CANx(x=0,1),the CAN1 only for GD32F30X_CL + \param[in] fifo_number + only one parameter can be selected which is shown as below: + \arg CAN_FIFOx(x=0,1) + \param[out] none + \retval message length +*/ +uint8_t can_receive_message_length_get(uint32_t can_periph, uint8_t fifo_number) +{ + uint8_t val = 0U; + + if(CAN_FIFO0 == fifo_number){ + /* FIFO0 */ + val = (uint8_t)(CAN_RFIFO0(can_periph) & CAN_RFIF_RFL_MASK); + }else if(CAN_FIFO1 == fifo_number){ + /* FIFO1 */ + val = (uint8_t)(CAN_RFIFO1(can_periph) & CAN_RFIF_RFL_MASK); + }else{ + /* illegal parameters */ + } + return val; +} + +/*! + \brief set CAN working mode + \param[in] can_periph + \arg CANx(x=0,1),the CAN1 only for GD32F30X_CL + \param[in] can_working_mode + only one parameter can be selected which is shown as below: + \arg CAN_MODE_INITIALIZE + \arg CAN_MODE_NORMAL + \arg CAN_MODE_SLEEP + \param[out] none + \retval ErrStatus: SUCCESS or ERROR +*/ +ErrStatus can_working_mode_set(uint32_t can_periph, uint8_t working_mode) +{ + ErrStatus flag = ERROR; + /* timeout for IWS or also for SLPWS bits */ + uint32_t timeout = CAN_TIMEOUT; + + if(CAN_MODE_INITIALIZE == working_mode){ + /* disable sleep mode */ + CAN_CTL(can_periph) &= (~(uint32_t)CAN_CTL_SLPWMOD); + /* set initialize mode */ + CAN_CTL(can_periph) |= (uint8_t)CAN_CTL_IWMOD; + /* wait the acknowledge */ + while((CAN_STAT_IWS != (CAN_STAT(can_periph) & CAN_STAT_IWS)) && (0U != timeout)){ + timeout--; + } + if(CAN_STAT_IWS != (CAN_STAT(can_periph) & CAN_STAT_IWS)){ + flag = ERROR; + }else{ + flag = SUCCESS; + } + }else if(CAN_MODE_NORMAL == working_mode){ + /* enter normal mode */ + CAN_CTL(can_periph) &= ~(uint32_t)(CAN_CTL_SLPWMOD | CAN_CTL_IWMOD); + /* wait the acknowledge */ + while((0U != (CAN_STAT(can_periph) & (CAN_STAT_IWS | CAN_STAT_SLPWS))) && (0U != timeout)){ + timeout--; + } + if(0U != (CAN_STAT(can_periph) & (CAN_STAT_IWS | CAN_STAT_SLPWS))){ + flag = ERROR; + }else{ + flag = SUCCESS; + } + }else if(CAN_MODE_SLEEP == working_mode){ + /* disable initialize mode */ + CAN_CTL(can_periph) &= (~(uint32_t)CAN_CTL_IWMOD); + /* set sleep mode */ + CAN_CTL(can_periph) |= (uint8_t)CAN_CTL_SLPWMOD; + /* wait the acknowledge */ + while((CAN_STAT_SLPWS != (CAN_STAT(can_periph) & CAN_STAT_SLPWS)) && (0U != timeout)){ + timeout--; + } + if(CAN_STAT_SLPWS != (CAN_STAT(can_periph) & CAN_STAT_SLPWS)){ + flag = ERROR; + }else{ + flag = SUCCESS; + } + }else{ + flag = ERROR; + } + return flag; +} + +/*! + \brief wake up CAN + \param[in] can_periph + \arg CANx(x=0,1),the CAN1 only for GD32F30X_CL + \param[out] none + \retval ErrStatus: SUCCESS or ERROR +*/ +ErrStatus can_wakeup(uint32_t can_periph) +{ + ErrStatus flag = ERROR; + uint32_t timeout = CAN_TIMEOUT; + + /* wakeup */ + CAN_CTL(can_periph) &= ~CAN_CTL_SLPWMOD; + + while((0U != (CAN_STAT(can_periph) & CAN_STAT_SLPWS)) && (0x00U != timeout)){ + timeout--; + } + /* check state */ + if(0U != (CAN_STAT(can_periph) & CAN_STAT_SLPWS)){ + flag = ERROR; + }else{ + flag = SUCCESS; + } + return flag; +} + +/*! + \brief get CAN error type + \param[in] can_periph + \arg CANx(x=0,1),the CAN1 only for GD32F30X_CL + \param[out] none + \retval can_error_enum + \arg CAN_ERROR_NONE: no error + \arg CAN_ERROR_FILL: fill error + \arg CAN_ERROR_FORMATE: format error + \arg CAN_ERROR_ACK: ACK error + \arg CAN_ERROR_BITRECESSIVE: bit recessive + \arg CAN_ERROR_BITDOMINANTER: bit dominant error + \arg CAN_ERROR_CRC: CRC error + \arg CAN_ERROR_SOFTWARECFG: software configure +*/ +can_error_enum can_error_get(uint32_t can_periph) +{ + can_error_enum error; + error = CAN_ERROR_NONE; + + /* get error type */ + error = (can_error_enum)(GET_ERR_ERRN(CAN_ERR(can_periph))); + return error; +} + +/*! + \brief get CAN receive error number + \param[in] can_periph + \arg CANx(x=0,1),the CAN1 only for GD32F30X_CL + \param[out] none + \retval error number +*/ +uint8_t can_receive_error_number_get(uint32_t can_periph) +{ + uint8_t val; + + /* get error count */ + val = (uint8_t)(GET_ERR_RECNT(CAN_ERR(can_periph))); + return val; +} + +/*! + \brief get CAN transmit error number + \param[in] can_periph + \arg CANx(x=0,1),the CAN1 only for GD32F30X_CL + \param[out] none + \retval error number +*/ +uint8_t can_transmit_error_number_get(uint32_t can_periph) +{ + uint8_t val; + + val = (uint8_t)(GET_ERR_TECNT(CAN_ERR(can_periph))); + return val; +} + +/*! + \brief enable CAN interrupt + \param[in] can_periph + \arg CANx(x=0,1),the CAN1 only for GD32F30X_CL + \param[in] interrupt + one or more parameters can be selected which are shown as below: + \arg CAN_INT_TME: transmit mailbox empty interrupt enable + \arg CAN_INT_RFNE0: receive FIFO0 not empty interrupt enable + \arg CAN_INT_RFF0: receive FIFO0 full interrupt enable + \arg CAN_INT_RFO0: receive FIFO0 overfull interrupt enable + \arg CAN_INT_RFNE1: receive FIFO1 not empty interrupt enable + \arg CAN_INT_RFF1: receive FIFO1 full interrupt enable + \arg CAN_INT_RFO1: receive FIFO1 overfull interrupt enable + \arg CAN_INT_WERR: warning error interrupt enable + \arg CAN_INT_PERR: passive error interrupt enable + \arg CAN_INT_BO: bus-off interrupt enable + \arg CAN_INT_ERRN: error number interrupt enable + \arg CAN_INT_ERR: error interrupt enable + \arg CAN_INT_WU: wakeup interrupt enable + \arg CAN_INT_SLPW: sleep working interrupt enable + \param[out] none + \retval none +*/ +void can_interrupt_enable(uint32_t can_periph, uint32_t interrupt) +{ + CAN_INTEN(can_periph) |= interrupt; +} + +/*! + \brief disable CAN interrupt + \param[in] can_periph + \arg CANx(x=0,1),the CAN1 only for GD32F30X_CL + \param[in] interrupt + one or more parameters can be selected which are shown as below: + \arg CAN_INT_TME: transmit mailbox empty interrupt enable + \arg CAN_INT_RFNE0: receive FIFO0 not empty interrupt enable + \arg CAN_INT_RFF0: receive FIFO0 full interrupt enable + \arg CAN_INT_RFO0: receive FIFO0 overfull interrupt enable + \arg CAN_INT_RFNE1: receive FIFO1 not empty interrupt enable + \arg CAN_INT_RFF1: receive FIFO1 full interrupt enable + \arg CAN_INT_RFO1: receive FIFO1 overfull interrupt enable + \arg CAN_INT_WERR: warning error interrupt enable + \arg CAN_INT_PERR: passive error interrupt enable + \arg CAN_INT_BO: bus-off interrupt enable + \arg CAN_INT_ERRN: error number interrupt enable + \arg CAN_INT_ERR: error interrupt enable + \arg CAN_INT_WU: wakeup interrupt enable + \arg CAN_INT_SLPW: sleep working interrupt enable + \param[out] none + \retval none +*/ +void can_interrupt_disable(uint32_t can_periph, uint32_t interrupt) +{ + CAN_INTEN(can_periph) &= ~interrupt; +} + +/*! + \brief get CAN flag state + \param[in] can_periph + \arg CANx(x=0,1),the CAN1 only for GD32F30X_CL + \param[in] flag: CAN flags, refer to can_flag_enum + only one parameter can be selected which is shown as below: + \arg CAN_FLAG_RXL: RX level + \arg CAN_FLAG_LASTRX: last sample value of RX pin + \arg CAN_FLAG_RS: receiving state + \arg CAN_FLAG_TS: transmitting state + \arg CAN_FLAG_SLPIF: status change flag of entering sleep working mode + \arg CAN_FLAG_WUIF: status change flag of wakeup from sleep working mode + \arg CAN_FLAG_ERRIF: error flag + \arg CAN_FLAG_SLPWS: sleep working state + \arg CAN_FLAG_IWS: initial working state + \arg CAN_FLAG_TMLS2: transmit mailbox 2 last sending in Tx FIFO + \arg CAN_FLAG_TMLS1: transmit mailbox 1 last sending in Tx FIFO + \arg CAN_FLAG_TMLS0: transmit mailbox 0 last sending in Tx FIFO + \arg CAN_FLAG_TME2: transmit mailbox 2 empty + \arg CAN_FLAG_TME1: transmit mailbox 1 empty + \arg CAN_FLAG_TME0: transmit mailbox 0 empty + \arg CAN_FLAG_MTE2: mailbox 2 transmit error + \arg CAN_FLAG_MTE1: mailbox 1 transmit error + \arg CAN_FLAG_MTE0: mailbox 0 transmit error + \arg CAN_FLAG_MAL2: mailbox 2 arbitration lost + \arg CAN_FLAG_MAL1: mailbox 1 arbitration lost + \arg CAN_FLAG_MAL0: mailbox 0 arbitration lost + \arg CAN_FLAG_MTFNERR2: mailbox 2 transmit finished with no error + \arg CAN_FLAG_MTFNERR1: mailbox 1 transmit finished with no error + \arg CAN_FLAG_MTFNERR0: mailbox 0 transmit finished with no error + \arg CAN_FLAG_MTF2: mailbox 2 transmit finished + \arg CAN_FLAG_MTF1: mailbox 1 transmit finished + \arg CAN_FLAG_MTF0: mailbox 0 transmit finished + \arg CAN_FLAG_RFO0: receive FIFO0 overfull + \arg CAN_FLAG_RFF0: receive FIFO0 full + \arg CAN_FLAG_RFO1: receive FIFO1 overfull + \arg CAN_FLAG_RFF1: receive FIFO1 full + \arg CAN_FLAG_BOERR: bus-off error + \arg CAN_FLAG_PERR: passive error + \arg CAN_FLAG_WERR: warning error + \param[out] none + \retval FlagStatus: SET or RESET +*/ +FlagStatus can_flag_get(uint32_t can_periph, can_flag_enum flag) +{ + /* get flag and interrupt enable state */ + if(RESET != (CAN_REG_VAL(can_periph, flag) & BIT(CAN_BIT_POS(flag)))){ + return SET; + }else{ + return RESET; + } +} + +/*! + \brief clear CAN flag state + \param[in] can_periph + \arg CANx(x=0,1),the CAN1 only for GD32F30X_CL + \param[in] flag: CAN flags, refer to can_flag_enum + only one parameter can be selected which is shown as below: + \arg CAN_FLAG_SLPIF: status change flag of entering sleep working mode + \arg CAN_FLAG_WUIF: status change flag of wakeup from sleep working mode + \arg CAN_FLAG_ERRIF: error flag + \arg CAN_FLAG_MTE2: mailbox 2 transmit error + \arg CAN_FLAG_MTE1: mailbox 1 transmit error + \arg CAN_FLAG_MTE0: mailbox 0 transmit error + \arg CAN_FLAG_MAL2: mailbox 2 arbitration lost + \arg CAN_FLAG_MAL1: mailbox 1 arbitration lost + \arg CAN_FLAG_MAL0: mailbox 0 arbitration lost + \arg CAN_FLAG_MTFNERR2: mailbox 2 transmit finished with no error + \arg CAN_FLAG_MTFNERR1: mailbox 1 transmit finished with no error + \arg CAN_FLAG_MTFNERR0: mailbox 0 transmit finished with no error + \arg CAN_FLAG_MTF2: mailbox 2 transmit finished + \arg CAN_FLAG_MTF1: mailbox 1 transmit finished + \arg CAN_FLAG_MTF0: mailbox 0 transmit finished + \arg CAN_FLAG_RFO0: receive FIFO0 overfull + \arg CAN_FLAG_RFF0: receive FIFO0 full + \arg CAN_FLAG_RFO1: receive FIFO1 overfull + \arg CAN_FLAG_RFF1: receive FIFO1 full + \param[out] none + \retval none +*/ +void can_flag_clear(uint32_t can_periph, can_flag_enum flag) +{ + CAN_REG_VAL(can_periph, flag) = BIT(CAN_BIT_POS(flag)); +} + +/*! + \brief get CAN interrupt flag state + \param[in] can_periph + \arg CANx(x=0,1),the CAN1 only for GD32F30X_CL + \param[in] flag: CAN interrupt flags, refer to can_interrupt_flag_enum + only one parameter can be selected which is shown as below: + \arg CAN_INT_FLAG_SLPIF: status change interrupt flag of sleep working mode entering + \arg CAN_INT_FLAG_WUIF: status change interrupt flag of wakeup from sleep working mode + \arg CAN_INT_FLAG_ERRIF: error interrupt flag + \arg CAN_INT_FLAG_MTF2: mailbox 2 transmit finished interrupt flag + \arg CAN_INT_FLAG_MTF1: mailbox 1 transmit finished interrupt flag + \arg CAN_INT_FLAG_MTF0: mailbox 0 transmit finished interrupt flag + \arg CAN_INT_FLAG_RFO0: receive FIFO0 overfull interrupt flag + \arg CAN_INT_FLAG_RFF0: receive FIFO0 full interrupt flag + \arg CAN_INT_FLAG_RFL0: receive FIFO0 not empty interrupt flag + \arg CAN_INT_FLAG_RFO1: receive FIFO1 overfull interrupt flag + \arg CAN_INT_FLAG_RFF1: receive FIFO1 full interrupt flag + \arg CAN_INT_FLAG_RFL1: receive FIFO1 not empty interrupt flag + \arg CAN_INT_FLAG_ERRN: error number interrupt flag + \arg CAN_INT_FLAG_BOERR: bus-off error interrupt flag + \arg CAN_INT_FLAG_PERR: passive error interrupt flag + \arg CAN_INT_FLAG_WERR: warning error interrupt flag + \param[out] none + \retval FlagStatus: SET or RESET +*/ +FlagStatus can_interrupt_flag_get(uint32_t can_periph, can_interrupt_flag_enum flag) +{ + uint32_t ret1 = RESET; + uint32_t ret2 = RESET; + + /* get the staus of interrupt flag */ + if (flag == CAN_INT_FLAG_RFL0) { + ret1 = can_receive_message_length_get(can_periph, CAN_FIFO0); + } else if (flag == CAN_INT_FLAG_RFL1) { + ret1 = can_receive_message_length_get(can_periph, CAN_FIFO1); + } else if (flag == CAN_INT_FLAG_ERRN) { + ret1 = can_error_get(can_periph); + } else { + ret1 = CAN_REG_VALS(can_periph, flag) & BIT(CAN_BIT_POS0(flag)); + } + /* get the staus of interrupt enale bit */ + ret2 = CAN_INTEN(can_periph) & BIT(CAN_BIT_POS1(flag)); + if(ret1 && ret2){ + return SET; + }else{ + return RESET; + } +} + +/*! + \brief clear CAN interrupt flag state + \param[in] can_periph + \arg CANx(x=0,1),the CAN1 only for GD32F30X_CL + \param[in] flag: CAN interrupt flags, refer to can_interrupt_flag_enum + only one parameter can be selected which is shown as below: + \arg CAN_INT_FLAG_SLPIF: status change interrupt flag of sleep working mode entering + \arg CAN_INT_FLAG_WUIF: status change interrupt flag of wakeup from sleep working mode + \arg CAN_INT_FLAG_ERRIF: error interrupt flag + \arg CAN_INT_FLAG_MTF2: mailbox 2 transmit finished interrupt flag + \arg CAN_INT_FLAG_MTF1: mailbox 1 transmit finished interrupt flag + \arg CAN_INT_FLAG_MTF0: mailbox 0 transmit finished interrupt flag + \arg CAN_INT_FLAG_RFO0: receive FIFO0 overfull interrupt flag + \arg CAN_INT_FLAG_RFF0: receive FIFO0 full interrupt flag + \arg CAN_INT_FLAG_RFO1: receive FIFO1 overfull interrupt flag + \arg CAN_INT_FLAG_RFF1: receive FIFO1 full interrupt flag + \param[out] none + \retval none +*/ +void can_interrupt_flag_clear(uint32_t can_periph, can_interrupt_flag_enum flag) +{ + CAN_REG_VALS(can_periph, flag) = BIT(CAN_BIT_POS0(flag)); +} diff --git a/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_standard_peripheral/Source/gd32f30x_crc.c b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_standard_peripheral/Source/gd32f30x_crc.c new file mode 100644 index 0000000000..c3b961fca8 --- /dev/null +++ b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_standard_peripheral/Source/gd32f30x_crc.c @@ -0,0 +1,130 @@ +/*! + \file gd32f30x_crc.c + \brief CRC driver + + \version 2017-02-10, V1.0.0, firmware for GD32F30x + \version 2018-10-10, V1.1.0, firmware for GD32F30x + \version 2018-12-25, V2.0.0, firmware for GD32F30x + \version 2020-09-30, V2.1.0, firmware for GD32F30x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "gd32f30x_crc.h" + +#define CRC_DATA_RESET_VALUE ((uint32_t)0xFFFFFFFFU) +#define CRC_FDATA_RESET_VALUE ((uint32_t)0x00000000U) + +/*! + \brief deinit CRC calculation unit + \param[in] none + \param[out] none + \retval none +*/ +void crc_deinit(void) +{ + CRC_DATA = CRC_DATA_RESET_VALUE; + CRC_FDATA = CRC_FDATA_RESET_VALUE; + CRC_CTL = (uint32_t)CRC_CTL_RST; +} + +/*! + \brief reset data register(CRC_DATA) to the value of 0xFFFFFFFF + \param[in] none + \param[out] none + \retval none +*/ +void crc_data_register_reset(void) +{ + CRC_CTL |= (uint32_t)CRC_CTL_RST; +} + +/*! + \brief read the value of the data register + \param[in] none + \param[out] none + \retval 32-bit value of the data register +*/ +uint32_t crc_data_register_read(void) +{ + uint32_t data; + data = CRC_DATA; + return (data); +} + +/*! + \brief read the value of the free data register + \param[in] none + \param[out] none + \retval 8-bit value of the free data register +*/ +uint8_t crc_free_data_register_read(void) +{ + uint8_t fdata; + fdata = (uint8_t)CRC_FDATA; + return (fdata); +} + +/*! + \brief write data to the free data register + \param[in] free_data: specified 8-bit data + \param[out] none + \retval none +*/ +void crc_free_data_register_write(uint8_t free_data) +{ + CRC_FDATA = (uint32_t)free_data; +} + +/*! + \brief calculate the CRC value of a 32-bit data + \param[in] sdata: specified 32-bit data + \param[out] none + \retval 32-bit value calculated by CRC +*/ +uint32_t crc_single_data_calculate(uint32_t sdata) +{ + CRC_DATA = sdata; + return (CRC_DATA); +} + +/*! + \brief calculate the CRC value of an array of 32-bit values + \param[in] array: pointer to an array of 32-bit values + \param[in] size: size of the array + \param[out] none + \retval 32-bit value calculated by CRC +*/ +uint32_t crc_block_data_calculate(const uint32_t *array, uint32_t size) +{ + uint32_t index; + for(index = 0U; index < size; index++){ + CRC_DATA = *(array+index); + } + return (CRC_DATA); +} diff --git a/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_standard_peripheral/Source/gd32f30x_ctc.c b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_standard_peripheral/Source/gd32f30x_ctc.c new file mode 100644 index 0000000000..ac20e8f46c --- /dev/null +++ b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_standard_peripheral/Source/gd32f30x_ctc.c @@ -0,0 +1,393 @@ +/*! + \file gd32f30x_ctc.c + \brief CTC driver + + \version 2017-02-10, V1.0.0, firmware for GD32F30x + \version 2018-10-10, V1.1.0, firmware for GD32F30x + \version 2018-12-25, V2.0.0, firmware for GD32F30x + \version 2020-09-30, V2.1.0, firmware for GD32F30x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "gd32f30x_ctc.h" + +#define CTC_FLAG_MASK ((uint32_t)0x00000700U) + +/* CTC register bit offset */ +#define CTC_TRIMVALUE_OFFSET ((uint32_t)8U) +#define CTC_TRIM_VALUE_OFFSET ((uint32_t)8U) +#define CTC_REFCAP_OFFSET ((uint32_t)16U) +#define CTC_LIMIT_VALUE_OFFSET ((uint32_t)16U) + +/*! + \brief reset CTC clock trim controller + \param[in] none + \param[out] none + \retval none +*/ +void ctc_deinit(void) +{ + /* reset CTC */ + rcu_periph_reset_enable(RCU_CTCRST); + rcu_periph_reset_disable(RCU_CTCRST); +} + + + +/*! + \brief enable CTC trim counter + \param[in] none + \param[out] none + \retval none +*/ +void ctc_counter_enable(void) +{ + CTC_CTL0 |= (uint32_t)CTC_CTL0_CNTEN; +} + +/*! + \brief disable CTC trim counter + \param[in] none + \param[out] none + \retval none +*/ +void ctc_counter_disable(void) +{ + CTC_CTL0 &= (uint32_t)(~CTC_CTL0_CNTEN); +} + +/*! + \brief configure the IRC48M trim value + \param[in] ctc_trim_value: 8-bit IRC48M trim value + \arg 0x00 - 0x3F + \param[out] none + \retval none +*/ +void ctc_irc48m_trim_value_config(uint8_t trim_value) +{ + /* clear TRIMVALUE bits */ + CTC_CTL0 &= (~(uint32_t)CTC_CTL0_TRIMVALUE); + /* set TRIMVALUE bits */ + CTC_CTL0 |= ((uint32_t)trim_value << CTC_TRIM_VALUE_OFFSET); +} + +/*! + \brief generate software reference source sync pulse + \param[in] none + \param[out] none + \retval none +*/ +void ctc_software_refsource_pulse_generate(void) +{ + CTC_CTL0 |= (uint32_t)CTC_CTL0_SWREFPUL; +} + +/*! + \brief configure hardware automatically trim mode + \param[in] hardmode: + only one parameter can be selected which is shown as below: + \arg CTC_HARDWARE_TRIM_MODE_ENABLE: hardware automatically trim mode enable + \arg CTC_HARDWARE_TRIM_MODE_DISABLE: hardware automatically trim mode disable + \param[out] none + \retval none +*/ +void ctc_hardware_trim_mode_config(uint32_t hardmode) +{ + CTC_CTL0 &= (uint32_t)(~CTC_CTL0_AUTOTRIM); + CTC_CTL0 |= (uint32_t)hardmode; +} +/*! + \brief configure reference signal source polarity + \param[in] polarity: + only one parameter can be selected which is shown as below: + \arg CTC_REFSOURCE_POLARITY_FALLING: reference signal source polarity is falling edge + \arg CTC_REFSOURCE_POLARITY_RISING: reference signal source polarity is rising edge + \param[out] none + \retval none +*/ +void ctc_refsource_polarity_config(uint32_t polarity) +{ + CTC_CTL1 &= (uint32_t)(~CTC_CTL1_REFPOL); + CTC_CTL1 |= (uint32_t)polarity; +} + +/*! + \brief select reference signal source + \param[in] refs: + only one parameter can be selected which is shown as below: + \arg CTC_REFSOURCE_GPIO: GPIO is selected + \arg CTC_REFSOURCE_LXTAL: LXTAL is selected + \arg CTC_REFSOURCE_USBSOF: USBD_SOF or USBFS_SOF is selected + \param[out] none + \retval none +*/ +void ctc_refsource_signal_select(uint32_t refs) +{ + CTC_CTL1 &= (uint32_t)(~CTC_CTL1_REFSEL); + CTC_CTL1 |= (uint32_t)refs; +} + +/*! + \brief configure reference signal source prescaler + \param[in] prescaler: + only one parameter can be selected which is shown as below: + \arg CTC_REFSOURCE_PSC_OFF: reference signal not divided + \arg CTC_REFSOURCE_PSC_DIV2: reference signal divided by 2 + \arg CTC_REFSOURCE_PSC_DIV4: reference signal divided by 4 + \arg CTC_REFSOURCE_PSC_DIV8: reference signal divided by 8 + \arg CTC_REFSOURCE_PSC_DIV16: reference signal divided by 16 + \arg CTC_REFSOURCE_PSC_DIV32: reference signal divided by 32 + \arg CTC_REFSOURCE_PSC_DIV64: reference signal divided by 64 + \arg CTC_REFSOURCE_PSC_DIV128: reference signal divided by 128 + \param[out] none + \retval none +*/ +void ctc_refsource_prescaler_config(uint32_t prescaler) +{ + CTC_CTL1 &= (uint32_t)(~CTC_CTL1_REFPSC); + CTC_CTL1 |= (uint32_t)prescaler; +} + +/*! + \brief configure clock trim base limit value + \param[in] limit_value: 8-bit clock trim base limit value + \arg 0x00 - 0xFF + \param[out] none + \retval none +*/ +void ctc_clock_limit_value_config(uint8_t limit_value) +{ + CTC_CTL1 &= (uint32_t)(~CTC_CTL1_CKLIM); + CTC_CTL1 |= (uint32_t)((uint32_t)limit_value << CTC_LIMIT_VALUE_OFFSET); +} + +/*! + \brief configure CTC counter reload value + \param[in] reload_value: 16-bit CTC counter reload value + \arg 0x0000 - 0xFFFF + \param[out] none + \retval none +*/ +void ctc_counter_reload_value_config(uint16_t reload_value) +{ + CTC_CTL1 &= (uint32_t)(~CTC_CTL1_RLVALUE); + CTC_CTL1 |= (uint32_t)reload_value; +} + +/*! + \brief read CTC counter capture value when reference sync pulse occurred + \param[in] none + \param[out] none + \retval the 16-bit CTC counter capture value +*/ +uint16_t ctc_counter_capture_value_read(void) +{ + uint16_t capture_value = 0U; + capture_value = (uint16_t)((CTC_STAT & CTC_STAT_REFCAP)>> CTC_REFCAP_OFFSET); + return (capture_value); +} + +/*! + \brief read CTC trim counter direction when reference sync pulse occurred + \param[in] none + \param[out] none + \retval FlagStatus: SET or RESET + \arg SET: CTC trim counter direction is down-counting + \arg RESET: CTC trim counter direction is up-counting +*/ +FlagStatus ctc_counter_direction_read(void) +{ + if(RESET != (CTC_STAT & CTC_STAT_REFDIR)){ + return SET; + }else{ + return RESET; + } +} + +/*! + \brief read CTC counter reload value + \param[in] none + \param[out] none + \retval the 16-bit CTC counter reload value +*/ +uint16_t ctc_counter_reload_value_read(void) +{ + uint16_t reload_value = 0U; + reload_value = (uint16_t)(CTC_CTL1 & CTC_CTL1_RLVALUE); + return (reload_value); +} + +/*! + \brief read the IRC48M trim value + \param[in] none + \param[out] none + \retval the 8-bit IRC48M trim value +*/ +uint8_t ctc_irc48m_trim_value_read(void) +{ + uint8_t trim_value = 0U; + trim_value = (uint8_t)((CTC_CTL0 & CTC_CTL0_TRIMVALUE) >> CTC_TRIMVALUE_OFFSET); + return (trim_value); +} + +/*! + \brief enable the CTC interrupt + \param[in] interrupt: CTC interrupt enable + one or more parameters can be selected which are shown as below: + \arg CTC_INT_CKOK: clock trim OK interrupt enable + \arg CTC_INT_CKWARN: clock trim warning interrupt enable + \arg CTC_INT_ERR: error interrupt enable + \arg CTC_INT_EREF: expect reference interrupt enable + \param[out] none + \retval none +*/ +void ctc_interrupt_enable(uint32_t interrupt) +{ + CTC_CTL0 |= (uint32_t)interrupt; +} + +/*! + \brief disable the CTC interrupt + \param[in] interrupt: CTC interrupt enable source + one or more parameters can be selected which are shown as below: + \arg CTC_INT_CKOK: clock trim OK interrupt enable + \arg CTC_INT_CKWARN: clock trim warning interrupt enable + \arg CTC_INT_ERR: error interrupt enable + \arg CTC_INT_EREF: expect reference interrupt enable + \param[out] none + \retval none +*/ +void ctc_interrupt_disable(uint32_t interrupt) +{ + CTC_CTL0 &= (uint32_t)(~interrupt); +} + +/*! + \brief get CTC interrupt flag + \param[in] int_flag: the CTC interrupt flag + only one parameter can be selected which is shown as below: + \arg CTC_INT_FLAG_CKOK: clock trim OK interrupt + \arg CTC_INT_FLAG_CKWARN: clock trim warning interrupt + \arg CTC_INT_FLAG_ERR: error interrupt + \arg CTC_INT_FLAG_EREF: expect reference interrupt + \arg CTC_INT_FLAG_CKERR: clock trim error bit interrupt + \arg CTC_INT_FLAG_REFMISS: reference sync pulse miss interrupt + \arg CTC_INT_FLAG_TRIMERR: trim value error interrupt + \param[out] none + \retval FlagStatus: SET or RESET +*/ +FlagStatus ctc_interrupt_flag_get(uint32_t int_flag) +{ + uint32_t interrupt_flag = 0U, intenable = 0U; + + /* check whether the interrupt is enabled */ + if(RESET != (int_flag & CTC_FLAG_MASK)){ + intenable = CTC_CTL0 & CTC_CTL0_ERRIE; + }else{ + intenable = CTC_CTL0 & int_flag; + } + + /* get interrupt flag status */ + interrupt_flag = CTC_STAT & int_flag; + + if(interrupt_flag && intenable){ + return SET; + }else{ + return RESET; + } +} + +/*! + \brief clear CTC interrupt flag + \param[in] int_flag: the CTC interrupt flag + only one parameter can be selected which is shown as below: + \arg CTC_INT_FLAG_CKOK: clock trim OK interrupt + \arg CTC_INT_FLAG_CKWARN: clock trim warning interrupt + \arg CTC_INT_FLAG_ERR: error interrupt + \arg CTC_INT_FLAG_EREF: expect reference interrupt + \arg CTC_INT_FLAG_CKERR: clock trim error bit interrupt + \arg CTC_INT_FLAG_REFMISS: reference sync pulse miss interrupt + \arg CTC_INT_FLAG_TRIMERR: trim value error interrupt + \param[out] none + \retval none +*/ +void ctc_interrupt_flag_clear(uint32_t int_flag) +{ + if(RESET != (int_flag & CTC_FLAG_MASK)){ + CTC_INTC |= CTC_INTC_ERRIC; + }else{ + CTC_INTC |= int_flag; + } +} + +/*! + \brief get CTC flag + \param[in] flag: the CTC flag + only one parameter can be selected which is shown as below: + \arg CTC_FLAG_CKOK: clock trim OK flag + \arg CTC_FLAG_CKWARN: clock trim warning flag + \arg CTC_FLAG_ERR: error flag + \arg CTC_FLAG_EREF: expect reference flag + \arg CTC_FLAG_CKERR: clock trim error bit + \arg CTC_FLAG_REFMISS: reference sync pulse miss + \arg CTC_FLAG_TRIMERR: trim value error bit + \param[out] none + \retval FlagStatus: SET or RESET +*/ +FlagStatus ctc_flag_get(uint32_t flag) +{ + if(RESET != (CTC_STAT & flag)){ + return SET; + }else{ + return RESET; + } +} + +/*! + \brief clear CTC flag + \param[in] flag: the CTC flag + only one parameter can be selected which is shown as below: + \arg CTC_FLAG_CKOK: clock trim OK flag + \arg CTC_FLAG_CKWARN: clock trim warning flag + \arg CTC_FLAG_ERR: error flag + \arg CTC_FLAG_EREF: expect reference flag + \arg CTC_FLAG_CKERR: clock trim error bit + \arg CTC_FLAG_REFMISS: reference sync pulse miss + \arg CTC_FLAG_TRIMERR: trim value error bit + \param[out] none + \retval none +*/ +void ctc_flag_clear(uint32_t flag) +{ + if(RESET != (flag & CTC_FLAG_MASK)){ + CTC_INTC |= CTC_INTC_ERRIC; + }else{ + CTC_INTC |= flag; + } +} diff --git a/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_standard_peripheral/Source/gd32f30x_dac.c b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_standard_peripheral/Source/gd32f30x_dac.c new file mode 100644 index 0000000000..55a53f75ab --- /dev/null +++ b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_standard_peripheral/Source/gd32f30x_dac.c @@ -0,0 +1,541 @@ +/*! + \file gd32f30x_dac.c + \brief DAC driver + + \version 2017-02-10, V1.0.0, firmware for GD32F30x + \version 2018-10-10, V1.1.0, firmware for GD32F30x + \version 2018-12-25, V2.0.0, firmware for GD32F30x + \version 2020-09-30, V2.1.0, firmware for GD32F30x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "gd32f30x_dac.h" + +/* DAC register bit offset */ +#define DAC1_REG_OFFSET ((uint32_t)16U) +#define DH_12BIT_OFFSET ((uint32_t)16U) +#define DH_8BIT_OFFSET ((uint32_t)8U) + +/*! + \brief deinitialize DAC + \param[in] none + \param[out] none + \retval none +*/ +void dac_deinit(void) +{ + rcu_periph_reset_enable(RCU_DACRST); + rcu_periph_reset_disable(RCU_DACRST); +} + +/*! + \brief enable DAC + \param[in] dac_periph: DACx(x = 0,1) + \param[out] none + \retval none +*/ +void dac_enable(uint32_t dac_periph) +{ + if(DAC0 == dac_periph){ + DAC_CTL |= DAC_CTL_DEN0; + }else{ + DAC_CTL |= DAC_CTL_DEN1; + } +} + +/*! + \brief disable DAC + \param[in] dac_periph: DACx(x = 0,1) + \param[out] none + \retval none +*/ +void dac_disable(uint32_t dac_periph) +{ + if(DAC0 == dac_periph){ + DAC_CTL &= ~DAC_CTL_DEN0; + }else{ + DAC_CTL &= ~DAC_CTL_DEN1; + } +} + +/*! + \brief enable DAC DMA function + \param[in] dac_periph: DACx(x = 0,1) + \param[out] none + \retval none +*/ +void dac_dma_enable(uint32_t dac_periph) +{ + if(DAC0 == dac_periph){ + DAC_CTL |= DAC_CTL_DDMAEN0; + }else{ + DAC_CTL |= DAC_CTL_DDMAEN1; + } +} + +/*! + \brief disable DAC DMA function + \param[in] dac_periph: DACx(x = 0,1) + \param[out] none + \retval none +*/ +void dac_dma_disable(uint32_t dac_periph) +{ + if(DAC0 == dac_periph){ + DAC_CTL &= ~DAC_CTL_DDMAEN0; + }else{ + DAC_CTL &= ~DAC_CTL_DDMAEN1; + } +} + +/*! + \brief enable DAC output buffer + \param[in] dac_periph: DACx(x = 0,1) + \param[out] none + \retval none +*/ +void dac_output_buffer_enable(uint32_t dac_periph) +{ + if(DAC0 == dac_periph){ + DAC_CTL &= ~DAC_CTL_DBOFF0; + }else{ + DAC_CTL &= ~DAC_CTL_DBOFF1; + } +} + +/*! + \brief disable DAC output buffer + \param[in] dac_periph: DACx(x = 0,1) + \param[out] none + \retval none +*/ +void dac_output_buffer_disable(uint32_t dac_periph) +{ + if(DAC0 == dac_periph){ + DAC_CTL |= DAC_CTL_DBOFF0; + }else{ + DAC_CTL |= DAC_CTL_DBOFF1; + } +} + +/*! + \brief get DAC output value + \param[in] dac_periph: DACx(x = 0,1) + \param[out] none + \retval DAC output data +*/ +uint16_t dac_output_value_get(uint32_t dac_periph) +{ + uint16_t data = 0U; + if(DAC0 == dac_periph){ + /* store the DAC0 output value */ + data = (uint16_t)DAC0_DO; + }else{ + /* store the DAC1 output value */ + data = (uint16_t)DAC1_DO; + } + return data; +} + +/*! + \brief set the DAC specified data holding register value + \param[in] dac_periph: DACx(x = 0,1) + \param[in] dac_align: data alignment + only one parameter can be selected which is shown as below: + \arg DAC_ALIGN_8B_R: data right 8 bit alignment + \arg DAC_ALIGN_12B_R: data right 12 bit alignment + \arg DAC_ALIGN_12B_L: data left 12 bit alignment + \param[in] data: data to be loaded + \param[out] none + \retval none +*/ +void dac_data_set(uint32_t dac_periph, uint32_t dac_align, uint16_t data) +{ + if(DAC0 == dac_periph){ + switch(dac_align){ + /* data right 12 bit alignment */ + case DAC_ALIGN_12B_R: + DAC0_R12DH = data; + break; + /* data left 12 bit alignment */ + case DAC_ALIGN_12B_L: + DAC0_L12DH = data; + break; + /* data right 8 bit alignment */ + case DAC_ALIGN_8B_R: + DAC0_R8DH = data; + break; + default: + break; + } + }else{ + switch(dac_align){ + /* data right 12 bit alignment */ + case DAC_ALIGN_12B_R: + DAC1_R12DH = data; + break; + /* data left 12 bit alignment */ + case DAC_ALIGN_12B_L: + DAC1_L12DH = data; + break; + /* data right 8 bit alignment */ + case DAC_ALIGN_8B_R: + DAC1_R8DH = data; + break; + default: + break; + } + } +} + +/*! + \brief enable DAC trigger + \param[in] dac_periph: DACx(x = 0,1) + \param[out] none + \retval none +*/ +void dac_trigger_enable(uint32_t dac_periph) +{ + if(DAC0 == dac_periph){ + DAC_CTL |= DAC_CTL_DTEN0; + }else{ + DAC_CTL |= DAC_CTL_DTEN1; + } +} + +/*! + \brief disable DAC trigger + \param[in] dac_periph: DACx(x = 0,1) + \param[out] none + \retval none +*/ +void dac_trigger_disable(uint32_t dac_periph) +{ + if(DAC0 == dac_periph){ + DAC_CTL &= ~DAC_CTL_DTEN0; + }else{ + DAC_CTL &= ~DAC_CTL_DTEN1; + } +} + +/*! + \brief set DAC trigger source + \param[in] dac_periph: DACx(x = 0,1) + \param[in] triggersource: external triggers of DAC + only one parameter can be selected which is shown as below: + \arg DAC_TRIGGER_T1_TRGO: TIMER1 TRGO + \arg DAC_TRIGGER_T2_TRGO: TIMER2 TRGO (for GD32F30X_CL) + \arg DAC_TRIGGER_T3_TRGO: TIMER3 TRGO + \arg DAC_TRIGGER_T4_TRGO: TIMER4 TRGO + \arg DAC_TRIGGER_T5_TRGO: TIMER5 TRGO + \arg DAC_TRIGGER_T6_TRGO: TIMER6 TRGO + \arg DAC_TRIGGER_T7_TRGO: TIMER7 TRGO (for GD32F30X_HD and GD32F30X_XD) + \arg DAC_TRIGGER_EXTI_9: EXTI interrupt line9 event + \arg DAC_TRIGGER_SOFTWARE: software trigger + \param[out] none + \retval none +*/ +void dac_trigger_source_config(uint32_t dac_periph,uint32_t triggersource) +{ + if(DAC0 == dac_periph){ + /* configure DAC0 trigger source */ + DAC_CTL &= ~DAC_CTL_DTSEL0; + DAC_CTL |= triggersource; + }else{ + /* configure DAC1 trigger source */ + DAC_CTL &= ~DAC_CTL_DTSEL1; + DAC_CTL |= (triggersource << DAC1_REG_OFFSET); + } +} + +/*! + \brief enable DAC software trigger + \param[in] dac_periph: DACx(x = 0,1) + \retval none +*/ +void dac_software_trigger_enable(uint32_t dac_periph) +{ + if(DAC0 == dac_periph){ + DAC_SWT |= DAC_SWT_SWTR0; + }else{ + DAC_SWT |= DAC_SWT_SWTR1; + } +} + +/*! + \brief disable DAC software trigger + \param[in] dac_periph: DACx(x = 0,1) + \param[out] none + \retval none +*/ +void dac_software_trigger_disable(uint32_t dac_periph) +{ + if(DAC0 == dac_periph){ + DAC_SWT &= ~DAC_SWT_SWTR0; + }else{ + DAC_SWT &= ~DAC_SWT_SWTR1; + } +} + +/*! + \brief configure DAC wave mode + \param[in] dac_periph: DACx(x = 0,1) + \param[in] wave_mode: noise wave mode + only one parameter can be selected which is shown as below: + \arg DAC_WAVE_DISABLE: wave disable + \arg DAC_WAVE_MODE_LFSR: LFSR noise mode + \arg DAC_WAVE_MODE_TRIANGLE: triangle noise mode + \param[out] none + \retval none +*/ +void dac_wave_mode_config(uint32_t dac_periph, uint32_t wave_mode) +{ + if(DAC0 == dac_periph){ + /* configure DAC0 wave mode */ + DAC_CTL &= ~DAC_CTL_DWM0; + DAC_CTL |= wave_mode; + }else{ + /* configure DAC1 wave mode */ + DAC_CTL &= ~DAC_CTL_DWM1; + DAC_CTL |= (wave_mode << DAC1_REG_OFFSET); + } +} + +/*! + \brief configure DAC wave bit width + \param[in] dac_periph: DACx(x = 0,1) + \param[in] bit_width: noise wave bit width + only one parameter can be selected which is shown as below: + \arg DAC_WAVE_BIT_WIDTH_1: bit width of the wave signal is 1 + \arg DAC_WAVE_BIT_WIDTH_2: bit width of the wave signal is 2 + \arg DAC_WAVE_BIT_WIDTH_3: bit width of the wave signal is 3 + \arg DAC_WAVE_BIT_WIDTH_4: bit width of the wave signal is 4 + \arg DAC_WAVE_BIT_WIDTH_5: bit width of the wave signal is 5 + \arg DAC_WAVE_BIT_WIDTH_6: bit width of the wave signal is 6 + \arg DAC_WAVE_BIT_WIDTH_7: bit width of the wave signal is 7 + \arg DAC_WAVE_BIT_WIDTH_8: bit width of the wave signal is 8 + \arg DAC_WAVE_BIT_WIDTH_9: bit width of the wave signal is 9 + \arg DAC_WAVE_BIT_WIDTH_10: bit width of the wave signal is 10 + \arg DAC_WAVE_BIT_WIDTH_11: bit width of the wave signal is 11 + \arg DAC_WAVE_BIT_WIDTH_12: bit width of the wave signal is 12 + \param[out] none + \retval none +*/ +void dac_wave_bit_width_config(uint32_t dac_periph, uint32_t bit_width) +{ + if(DAC0 == dac_periph){ + /* configure DAC0 wave bit width */ + DAC_CTL &= ~DAC_CTL_DWBW0; + DAC_CTL |= bit_width; + }else{ + /* configure DAC1 wave bit width */ + DAC_CTL &= ~DAC_CTL_DWBW1; + DAC_CTL |= (bit_width << DAC1_REG_OFFSET); + } +} + +/*! + \brief configure DAC LFSR noise mode + \param[in] dac_periph: DACx(x = 0,1) + \param[in] unmask_bits: unmask LFSR bits in DAC LFSR noise mode + only one parameter can be selected which is shown as below: + \arg DAC_LFSR_BIT0: unmask the LFSR bit0 + \arg DAC_LFSR_BITS1_0: unmask the LFSR bits[1:0] + \arg DAC_LFSR_BITS2_0: unmask the LFSR bits[2:0] + \arg DAC_LFSR_BITS3_0: unmask the LFSR bits[3:0] + \arg DAC_LFSR_BITS4_0: unmask the LFSR bits[4:0] + \arg DAC_LFSR_BITS5_0: unmask the LFSR bits[5:0] + \arg DAC_LFSR_BITS6_0: unmask the LFSR bits[6:0] + \arg DAC_LFSR_BITS7_0: unmask the LFSR bits[7:0] + \arg DAC_LFSR_BITS8_0: unmask the LFSR bits[8:0] + \arg DAC_LFSR_BITS9_0: unmask the LFSR bits[9:0] + \arg DAC_LFSR_BITS10_0: unmask the LFSR bits[10:0] + \arg DAC_LFSR_BITS11_0: unmask the LFSR bits[11:0] + \param[out] none + \retval none +*/ +void dac_lfsr_noise_config(uint32_t dac_periph, uint32_t unmask_bits) +{ + if(DAC0 == dac_periph){ + /* configure DAC0 LFSR noise mode */ + DAC_CTL &= ~DAC_CTL_DWBW0; + DAC_CTL |= unmask_bits; + }else{ + /* configure DAC1 LFSR noise mode */ + DAC_CTL &= ~DAC_CTL_DWBW1; + DAC_CTL |= (unmask_bits << DAC1_REG_OFFSET); + } +} + +/*! + \brief configure DAC triangle noise mode + \param[in] dac_periph: DACx(x = 0,1) + \param[in] amplitude: triangle amplitude in DAC triangle noise mode + only one parameter can be selected which is shown as below: + \arg DAC_TRIANGLE_AMPLITUDE_1: triangle amplitude is 1 + \arg DAC_TRIANGLE_AMPLITUDE_3: triangle amplitude is 3 + \arg DAC_TRIANGLE_AMPLITUDE_7: triangle amplitude is 7 + \arg DAC_TRIANGLE_AMPLITUDE_15: triangle amplitude is 15 + \arg DAC_TRIANGLE_AMPLITUDE_31: triangle amplitude is 31 + \arg DAC_TRIANGLE_AMPLITUDE_63: triangle amplitude is 63 + \arg DAC_TRIANGLE_AMPLITUDE_127: triangle amplitude is 127 + \arg DAC_TRIANGLE_AMPLITUDE_255: triangle amplitude is 255 + \arg DAC_TRIANGLE_AMPLITUDE_511: triangle amplitude is 511 + \arg DAC_TRIANGLE_AMPLITUDE_1023: triangle amplitude is 1023 + \arg DAC_TRIANGLE_AMPLITUDE_2047: triangle amplitude is 2047 + \arg DAC_TRIANGLE_AMPLITUDE_4095: triangle amplitude is 4095 + \param[out] none + \retval none +*/ +void dac_triangle_noise_config(uint32_t dac_periph, uint32_t amplitude) +{ + if(DAC0 == dac_periph){ + /* configure DAC0 triangle noise mode */ + DAC_CTL &= ~DAC_CTL_DWBW0; + DAC_CTL |= amplitude; + }else{ + /* configure DAC1 triangle noise mode */ + DAC_CTL &= ~DAC_CTL_DWBW1; + DAC_CTL |= (amplitude << DAC1_REG_OFFSET); + } +} + +/*! + \brief enable DAC concurrent mode + \param[in] none + \param[out] none + \retval none +*/ +void dac_concurrent_enable(void) +{ + uint32_t ctl = 0U; + ctl = DAC_CTL_DEN0 | DAC_CTL_DEN1; + DAC_CTL |= (ctl); +} + +/*! + \brief disable DAC concurrent mode + \param[in] none + \param[out] none + \retval none +*/ +void dac_concurrent_disable(void) +{ + uint32_t ctl = 0U; + ctl = DAC_CTL_DEN0 | DAC_CTL_DEN1; + DAC_CTL &= (~ctl); +} + +/*! + \brief enable DAC concurrent software trigger function + \param[in] none + \param[out] none + \retval none +*/ +void dac_concurrent_software_trigger_enable(void) +{ + uint32_t swt = 0U; + swt = DAC_SWT_SWTR0 | DAC_SWT_SWTR1; + DAC_SWT |= (swt); +} + +/*! + \brief disable DAC concurrent software trigger function + \param[in] none + \param[out] none + \retval none +*/ +void dac_concurrent_software_trigger_disable(void) +{ + uint32_t swt = 0U; + swt = DAC_SWT_SWTR0 | DAC_SWT_SWTR1; + DAC_SWT &= (~swt); +} + +/*! + \brief enable DAC concurrent buffer function + \param[in] none + \param[out] none + \retval none +*/ +void dac_concurrent_output_buffer_enable(void) +{ + uint32_t ctl = 0U; + ctl = DAC_CTL_DBOFF0 | DAC_CTL_DBOFF1; + DAC_CTL &= (~ctl); +} + +/*! + \brief disable DAC concurrent buffer function + \param[in] none + \param[out] none + \retval none +*/ +void dac_concurrent_output_buffer_disable(void) +{ + uint32_t ctl = 0U; + ctl = DAC_CTL_DBOFF0 | DAC_CTL_DBOFF1; + DAC_CTL |= (ctl); +} + +/*! + \brief set DAC concurrent mode data holding register value + \param[in] dac_align: data alignment + only one parameter can be selected which is shown as below: + \arg DAC_ALIGN_8B_R: data right 8b alignment + \arg DAC_ALIGN_12B_R: data right 12b alignment + \arg DAC_ALIGN_12B_L: data left 12b alignment + \param[in] data0: data to be loaded + \param[in] data1: data to be loaded + \param[out] none + \retval none +*/ +void dac_concurrent_data_set(uint32_t dac_align, uint16_t data0, uint16_t data1) +{ + uint32_t data = 0U; + switch(dac_align){ + /* data right 12b alignment */ + case DAC_ALIGN_12B_R: + data = ((uint32_t)data1 << DH_12BIT_OFFSET) | data0; + DACC_R12DH = data; + break; + /* data left 12b alignment */ + case DAC_ALIGN_12B_L: + data = ((uint32_t)data1 << DH_12BIT_OFFSET) | data0; + DACC_L12DH = data; + break; + /* data right 8b alignment */ + case DAC_ALIGN_8B_R: + data = ((uint32_t)data1 << DH_8BIT_OFFSET) | data0; + DACC_R8DH = data; + break; + default: + break; + } +} diff --git a/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_standard_peripheral/Source/gd32f30x_dbg.c b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_standard_peripheral/Source/gd32f30x_dbg.c new file mode 100644 index 0000000000..8cae11f6ce --- /dev/null +++ b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_standard_peripheral/Source/gd32f30x_dbg.c @@ -0,0 +1,164 @@ +/*! + \file gd32f30x_dbg.c + \brief DBG driver + + \version 2017-02-10, V1.0.0, firmware for GD32F30x + \version 2018-10-10, V1.1.0, firmware for GD32F30x + \version 2018-12-25, V2.0.0, firmware for GD32F30x + \version 2020-09-30, V2.1.0, firmware for GD32F30x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "gd32f30x_dbg.h" + +#define DBG_RESET_VAL 0x00000000U + +/*! + \brief deinitialize the DBG + \param[in] none + \param[out] none + \retval none +*/ +void dbg_deinit(void) +{ + DBG_CTL0 = DBG_RESET_VAL; +} + +/*! + \brief read DBG_ID code register + \param[in] none + \param[out] none + \retval DBG_ID code +*/ +uint32_t dbg_id_get(void) +{ + return DBG_ID; +} + +/*! + \brief enable low power behavior when the mcu is in debug mode + \param[in] dbg_low_power: + this parameter can be any combination of the following values: + \arg DBG_LOW_POWER_SLEEP: keep debugger connection during sleep mode + \arg DBG_LOW_POWER_DEEPSLEEP: keep debugger connection during deepsleep mode + \arg DBG_LOW_POWER_STANDBY: keep debugger connection during standby mode + \param[out] none + \retval none +*/ +void dbg_low_power_enable(uint32_t dbg_low_power) +{ + DBG_CTL0 |= dbg_low_power; +} + +/*! + \brief disable low power behavior when the mcu is in debug mode + \param[in] dbg_low_power: + this parameter can be any combination of the following values: + \arg DBG_LOW_POWER_SLEEP: donot keep debugger connection during sleep mode + \arg DBG_LOW_POWER_DEEPSLEEP: donot keep debugger connection during deepsleep mode + \arg DBG_LOW_POWER_STANDBY: donot keep debugger connection during standby mode + \param[out] none + \retval none +*/ +void dbg_low_power_disable(uint32_t dbg_low_power) +{ + DBG_CTL0 &= ~dbg_low_power; +} + +/*! + \brief enable peripheral behavior when the mcu is in debug mode + \param[in] dbg_periph: refer to dbg_periph_enum + only one parameter can be selected which is shown as below: + \arg DBG_FWDGT_HOLD : debug FWDGT kept when core is halted + \arg DBG_WWDGT_HOLD : debug WWDGT kept when core is halted + \arg DBG_CANx_HOLD (x=0,1,CAN1 is only available for CL series): hold CANx counter when core is halted + \arg DBG_I2Cx_HOLD (x=0,1): hold I2Cx smbus when core is halted + \arg DBG_TIMERx_HOLD (x=0,1,2,3,4,5,6,7,8,9,10,11,12,13,TIMER8..13 are not available for HD series): hold TIMERx counter when core is halted + \param[out] none + \retval none +*/ +void dbg_periph_enable(dbg_periph_enum dbg_periph) +{ + DBG_REG_VAL(dbg_periph) |= BIT(DBG_BIT_POS(dbg_periph)); +} + +/*! + \brief disable peripheral behavior when the mcu is in debug mode + \param[in] dbg_periph: refer to dbg_periph_enum + only one parameter can be selected which is shown as below: + \arg DBG_FWDGT_HOLD : debug FWDGT kept when core is halted + \arg DBG_WWDGT_HOLD : debug WWDGT kept when core is halted + \arg DBG_CANx_HOLD (x=0,1,CAN1 is only available for CL series): hold CAN0 counter when core is halted + \arg DBG_I2Cx_HOLD (x=0,1): hold I2Cx smbus when core is halted + \arg DBG_TIMERx_HOLD (x=0,1,2,3,4,5,6,7,8,9,10,11,12,13,TIMER8..13 are not available for HD series): hold TIMERx counter when core is halted + \param[out] none + \retval none +*/ +void dbg_periph_disable(dbg_periph_enum dbg_periph) +{ + DBG_REG_VAL(dbg_periph) &= ~BIT(DBG_BIT_POS(dbg_periph)); +} + +/*! + \brief enable trace pin assignment + \param[in] none + \param[out] none + \retval none +*/ +void dbg_trace_pin_enable(void) +{ + DBG_CTL0 |= DBG_CTL0_TRACE_IOEN; +} + +/*! + \brief disable trace pin assignment + \param[in] none + \param[out] none + \retval none +*/ +void dbg_trace_pin_disable(void) +{ + DBG_CTL0 &= ~DBG_CTL0_TRACE_IOEN; +} + +/*! + \brief trace pin mode selection + \param[in] trace_mode: + \arg TRACE_MODE_ASYNC: trace pin used for async mode + \arg TRACE_MODE_SYNC_DATASIZE_1: trace pin used for sync mode and data size is 1 + \arg TRACE_MODE_SYNC_DATASIZE_2: trace pin used for sync mode and data size is 2 + \arg TRACE_MODE_SYNC_DATASIZE_4: trace pin used for sync mode and data size is 4 + \param[out] none + \retval none +*/ +void dbg_trace_pin_mode_set(uint32_t trace_mode) +{ + DBG_CTL0 &= ~DBG_CTL0_TRACE_MODE; + DBG_CTL0 |= trace_mode; +} diff --git a/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_standard_peripheral/Source/gd32f30x_dma.c b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_standard_peripheral/Source/gd32f30x_dma.c new file mode 100644 index 0000000000..342025c5d1 --- /dev/null +++ b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_standard_peripheral/Source/gd32f30x_dma.c @@ -0,0 +1,735 @@ +/*! + \file gd32f30x_dma.c + \brief DMA driver + + \version 2017-02-10, V1.0.0, firmware for GD32F30x + \version 2018-10-10, V1.1.0, firmware for GD32F30x + \version 2018-12-25, V2.0.0, firmware for GD32F30x + \version 2020-09-30, V2.1.0, firmware for GD32F30x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "gd32f30x_dma.h" +#include + +#define DMA_WRONG_HANDLE while(1){} + +/* check whether peripheral matches channels or not */ +static ErrStatus dma_periph_and_channel_check(uint32_t dma_periph, dma_channel_enum channelx); + +/*! + \brief deinitialize DMA a channel registers + \param[in] dma_periph: DMAx(x=0,1) + \arg DMAx(x=0,1) + \param[in] channelx: specify which DMA channel is deinitialized + only one parameter can be selected which is shown as below: + \arg DMA0: DMA_CHx(x=0..6), DMA1: DMA_CHx(x=0..4) + \param[out] none + \retval none +*/ +void dma_deinit(uint32_t dma_periph, dma_channel_enum channelx) +{ + if(ERROR == dma_periph_and_channel_check(dma_periph, channelx)){ + DMA_WRONG_HANDLE + } + + /* disable DMA a channel */ + DMA_CHCTL(dma_periph, channelx) &= ~DMA_CHXCTL_CHEN; + /* reset DMA channel registers */ + DMA_CHCTL(dma_periph, channelx) = DMA_CHCTL_RESET_VALUE; + DMA_CHCNT(dma_periph, channelx) = DMA_CHCNT_RESET_VALUE; + DMA_CHPADDR(dma_periph, channelx) = DMA_CHPADDR_RESET_VALUE; + DMA_CHMADDR(dma_periph, channelx) = DMA_CHMADDR_RESET_VALUE; + DMA_INTC(dma_periph) |= DMA_FLAG_ADD(DMA_CHINTF_RESET_VALUE, channelx); +} + +/*! + \brief initialize the parameters of DMA struct with the default values + \param[in] init_struct: the initialization data needed to initialize DMA channel + \param[out] none + \retval none +*/ +void dma_struct_para_init(dma_parameter_struct* init_struct) +{ + if(NULL == init_struct){ + DMA_WRONG_HANDLE + } + + /* set the DMA struct with the default values */ + init_struct->periph_addr = 0U; + init_struct->periph_width = 0U; + init_struct->periph_inc = DMA_PERIPH_INCREASE_DISABLE; + init_struct->memory_addr = 0U; + init_struct->memory_width = 0U; + init_struct->memory_inc = DMA_MEMORY_INCREASE_DISABLE; + init_struct->number = 0U; + init_struct->direction = DMA_PERIPHERAL_TO_MEMORY; + init_struct->priority = DMA_PRIORITY_LOW; +} + +/*! + \brief initialize DMA channel + \param[in] dma_periph: DMAx(x=0,1) + \arg DMAx(x=0,1) + \param[in] channelx: specify which DMA channel is initialized + only one parameter can be selected which is shown as below: + \arg DMA0: DMA_CHx(x=0..6), DMA1: DMA_CHx(x=0..4) + \param[in] init_struct: the data needed to initialize DMA channel + periph_addr: peripheral base address + periph_width: DMA_PERIPHERAL_WIDTH_8BIT, DMA_PERIPHERAL_WIDTH_16BIT, DMA_PERIPHERAL_WIDTH_32BIT + periph_inc: DMA_PERIPH_INCREASE_ENABLE, DMA_PERIPH_INCREASE_DISABLE + memory_addr: memory base address + memory_width: DMA_MEMORY_WIDTH_8BIT, DMA_MEMORY_WIDTH_16BIT, DMA_MEMORY_WIDTH_32BIT + memory_inc: DMA_MEMORY_INCREASE_ENABLE, DMA_MEMORY_INCREASE_DISABLE + direction: DMA_PERIPHERAL_TO_MEMORY, DMA_MEMORY_TO_PERIPHERAL + number: the number of remaining data to be transferred by the DMA + priority: DMA_PRIORITY_LOW, DMA_PRIORITY_MEDIUM, DMA_PRIORITY_HIGH, DMA_PRIORITY_ULTRA_HIGH + \param[out] none + \retval none +*/ +void dma_init(uint32_t dma_periph, dma_channel_enum channelx, dma_parameter_struct* init_struct) +{ + uint32_t ctl; + + if(ERROR == dma_periph_and_channel_check(dma_periph, channelx)){ + DMA_WRONG_HANDLE + } + + /* configure peripheral base address */ + DMA_CHPADDR(dma_periph, channelx) = init_struct->periph_addr; + + /* configure memory base address */ + DMA_CHMADDR(dma_periph, channelx) = init_struct->memory_addr; + + /* configure the number of remaining data to be transferred */ + DMA_CHCNT(dma_periph, channelx) = (init_struct->number & DMA_CHANNEL_CNT_MASK); + + /* configure peripheral transfer width,memory transfer width and priority */ + ctl = DMA_CHCTL(dma_periph, channelx); + ctl &= ~(DMA_CHXCTL_PWIDTH | DMA_CHXCTL_MWIDTH | DMA_CHXCTL_PRIO); + ctl |= (init_struct->periph_width | init_struct->memory_width | init_struct->priority); + DMA_CHCTL(dma_periph, channelx) = ctl; + + /* configure peripheral increasing mode */ + if(DMA_PERIPH_INCREASE_ENABLE == init_struct->periph_inc){ + DMA_CHCTL(dma_periph, channelx) |= DMA_CHXCTL_PNAGA; + }else{ + DMA_CHCTL(dma_periph, channelx) &= ~DMA_CHXCTL_PNAGA; + } + + /* configure memory increasing mode */ + if(DMA_MEMORY_INCREASE_ENABLE == init_struct->memory_inc){ + DMA_CHCTL(dma_periph, channelx) |= DMA_CHXCTL_MNAGA; + }else{ + DMA_CHCTL(dma_periph, channelx) &= ~DMA_CHXCTL_MNAGA; + } + + /* configure the direction of data transfer */ + if(DMA_PERIPHERAL_TO_MEMORY == init_struct->direction){ + DMA_CHCTL(dma_periph, channelx) &= ~DMA_CHXCTL_DIR; + }else{ + DMA_CHCTL(dma_periph, channelx) |= DMA_CHXCTL_DIR; + } +} + +/*! + \brief enable DMA circulation mode + \param[in] dma_periph: DMAx(x=0,1) + \arg DMAx(x=0,1) + \param[in] channelx: specify which DMA channel + only one parameter can be selected which is shown as below: + \arg DMA0: DMA_CHx(x=0..6), DMA1: DMA_CHx(x=0..4) + \param[out] none + \retval none +*/ +void dma_circulation_enable(uint32_t dma_periph, dma_channel_enum channelx) +{ + if(ERROR == dma_periph_and_channel_check(dma_periph, channelx)){ + DMA_WRONG_HANDLE + } + + DMA_CHCTL(dma_periph, channelx) |= DMA_CHXCTL_CMEN; +} + +/*! + \brief disable DMA circulation mode + \param[in] dma_periph: DMAx(x=0,1) + \arg DMAx(x=0,1) + \param[in] channelx: specify which DMA channel + only one parameter can be selected which is shown as below: + \arg DMA0: DMA_CHx(x=0..6), DMA1: DMA_CHx(x=0..4) + \param[out] none + \retval none +*/ +void dma_circulation_disable(uint32_t dma_periph, dma_channel_enum channelx) +{ + if(ERROR == dma_periph_and_channel_check(dma_periph, channelx)){ + DMA_WRONG_HANDLE + } + + DMA_CHCTL(dma_periph, channelx) &= ~DMA_CHXCTL_CMEN; +} + +/*! + \brief enable memory to memory mode + \param[in] dma_periph: DMAx(x=0,1) + \arg DMAx(x=0,1) + \param[in] channelx: specify which DMA channel + only one parameter can be selected which is shown as below: + \arg DMA0: DMA_CHx(x=0..6), DMA1: DMA_CHx(x=0..4) + \param[out] none + \retval none +*/ +void dma_memory_to_memory_enable(uint32_t dma_periph, dma_channel_enum channelx) +{ + if(ERROR == dma_periph_and_channel_check(dma_periph, channelx)){ + DMA_WRONG_HANDLE + } + + DMA_CHCTL(dma_periph, channelx) |= DMA_CHXCTL_M2M; +} + +/*! + \brief disable memory to memory mode + \param[in] dma_periph: DMAx(x=0,1) + \arg DMAx(x=0,1) + \param[in] channelx: specify which DMA channel + only one parameter can be selected which is shown as below: + \arg DMA0: DMA_CHx(x=0..6), DMA1: DMA_CHx(x=0..4) + \param[out] none + \retval none +*/ +void dma_memory_to_memory_disable(uint32_t dma_periph, dma_channel_enum channelx) +{ + if(ERROR == dma_periph_and_channel_check(dma_periph, channelx)){ + DMA_WRONG_HANDLE + } + + DMA_CHCTL(dma_periph, channelx) &= ~DMA_CHXCTL_M2M; +} + +/*! + \brief enable DMA channel + \param[in] dma_periph: DMAx(x=0,1) + \arg DMAx(x=0,1) + \param[in] channelx: specify which DMA channel + only one parameter can be selected which is shown as below: + \arg DMA0: DMA_CHx(x=0..6), DMA1: DMA_CHx(x=0..4) + \param[out] none + \retval none +*/ +void dma_channel_enable(uint32_t dma_periph, dma_channel_enum channelx) +{ + if(ERROR == dma_periph_and_channel_check(dma_periph, channelx)){ + DMA_WRONG_HANDLE + } + + DMA_CHCTL(dma_periph, channelx) |= DMA_CHXCTL_CHEN; +} + +/*! + \brief disable DMA channel + \param[in] dma_periph: DMAx(x=0,1) + \arg DMAx(x=0,1) + \param[in] channelx: specify which DMA channel + only one parameter can be selected which is shown as below: + \arg DMA0: DMA_CHx(x=0..6), DMA1: DMA_CHx(x=0..4) + \param[out] none + \retval none +*/ +void dma_channel_disable(uint32_t dma_periph, dma_channel_enum channelx) +{ + if(ERROR == dma_periph_and_channel_check(dma_periph, channelx)){ + DMA_WRONG_HANDLE + } + + DMA_CHCTL(dma_periph, channelx) &= ~DMA_CHXCTL_CHEN; +} + +/*! + \brief set DMA peripheral base address + \param[in] dma_periph: DMAx(x=0,1) + \arg DMAx(x=0,1) + \param[in] channelx: specify which DMA channel to set peripheral base address + only one parameter can be selected which is shown as below: + \arg DMA0: DMA_CHx(x=0..6), DMA1: DMA_CHx(x=0..4) + \param[in] address: peripheral base address + \param[out] none + \retval none +*/ +void dma_periph_address_config(uint32_t dma_periph, dma_channel_enum channelx, uint32_t address) +{ + if(ERROR == dma_periph_and_channel_check(dma_periph, channelx)){ + DMA_WRONG_HANDLE + } + + DMA_CHPADDR(dma_periph, channelx) = address; +} + +/*! + \brief set DMA memory base address + \param[in] dma_periph: DMAx(x=0,1) + \arg DMAx(x=0,1) + \param[in] channelx: specify which DMA channel to set memory base address + only one parameter can be selected which is shown as below: + \arg DMA0: DMA_CHx(x=0..6), DMA1: DMA_CHx(x=0..4) + \param[in] address: memory base address + \param[out] none + \retval none +*/ +void dma_memory_address_config(uint32_t dma_periph, dma_channel_enum channelx, uint32_t address) +{ + if(ERROR == dma_periph_and_channel_check(dma_periph, channelx)){ + DMA_WRONG_HANDLE + } + + DMA_CHMADDR(dma_periph, channelx) = address; +} + +/*! + \brief set the number of remaining data to be transferred by the DMA + \param[in] dma_periph: DMAx(x=0,1) + \arg DMAx(x=0,1) + \param[in] channelx: specify which DMA channel to set number + only one parameter can be selected which is shown as below: + \arg DMA0: DMA_CHx(x=0..6), DMA1: DMA_CHx(x=0..4) + \param[in] number: the number of remaining data to be transferred by the DMA + \param[out] none + \retval none +*/ +void dma_transfer_number_config(uint32_t dma_periph, dma_channel_enum channelx, uint32_t number) +{ + if(ERROR == dma_periph_and_channel_check(dma_periph, channelx)){ + DMA_WRONG_HANDLE + } + + DMA_CHCNT(dma_periph, channelx) = (number & DMA_CHANNEL_CNT_MASK); +} + +/*! + \brief get the number of remaining data to be transferred by the DMA + \param[in] dma_periph: DMAx(x=0,1) + \arg DMAx(x=0,1) + \param[in] channelx: specify which DMA channel to set number + only one parameter can be selected which is shown as below: + \arg DMA0: DMA_CHx(x=0..6), DMA1: DMA_CHx(x=0..4) + \param[out] none + \retval uint32_t: the number of remaining data to be transferred by the DMA +*/ +uint32_t dma_transfer_number_get(uint32_t dma_periph, dma_channel_enum channelx) +{ + if(ERROR == dma_periph_and_channel_check(dma_periph, channelx)){ + DMA_WRONG_HANDLE + } + + return (uint32_t)DMA_CHCNT(dma_periph, channelx); +} + +/*! + \brief configure priority level of DMA channel + \param[in] dma_periph: DMAx(x=0,1) + \arg DMAx(x=0,1) + \param[in] channelx: specify which DMA channel + only one parameter can be selected which is shown as below: + \arg DMA0: DMA_CHx(x=0..6), DMA1: DMA_CHx(x=0..4) + \param[in] priority: priority Level of this channel + only one parameter can be selected which is shown as below: + \arg DMA_PRIORITY_LOW: low priority + \arg DMA_PRIORITY_MEDIUM: medium priority + \arg DMA_PRIORITY_HIGH: high priority + \arg DMA_PRIORITY_ULTRA_HIGH: ultra high priority + \param[out] none + \retval none +*/ +void dma_priority_config(uint32_t dma_periph, dma_channel_enum channelx, uint32_t priority) +{ + uint32_t ctl; + + if(ERROR == dma_periph_and_channel_check(dma_periph, channelx)){ + DMA_WRONG_HANDLE + } + + /* acquire DMA_CHxCTL register */ + ctl = DMA_CHCTL(dma_periph, channelx); + /* assign regiser */ + ctl &= ~DMA_CHXCTL_PRIO; + ctl |= priority; + DMA_CHCTL(dma_periph, channelx) = ctl; +} + +/*! + \brief configure transfer data size of memory + \param[in] dma_periph: DMAx(x=0,1) + \arg DMAx(x=0,1) + \param[in] channelx: specify which DMA channel + only one parameter can be selected which is shown as below: + \arg DMA0: DMA_CHx(x=0..6), DMA1: DMA_CHx(x=0..4) + \param[in] mwidth: transfer data width of memory + only one parameter can be selected which is shown as below: + \arg DMA_MEMORY_WIDTH_8BIT: transfer data width of memory is 8-bit + \arg DMA_MEMORY_WIDTH_16BIT: transfer data width of memory is 16-bit + \arg DMA_MEMORY_WIDTH_32BIT: transfer data width of memory is 32-bit + \param[out] none + \retval none +*/ +void dma_memory_width_config(uint32_t dma_periph, dma_channel_enum channelx, uint32_t mwidth) +{ + uint32_t ctl; + + if(ERROR == dma_periph_and_channel_check(dma_periph, channelx)){ + DMA_WRONG_HANDLE + } + + /* acquire DMA_CHxCTL register */ + ctl = DMA_CHCTL(dma_periph, channelx); + /* assign regiser */ + ctl &= ~DMA_CHXCTL_MWIDTH; + ctl |= mwidth; + DMA_CHCTL(dma_periph, channelx) = ctl; +} + +/*! + \brief configure transfer data size of peripheral + \param[in] dma_periph: DMAx(x=0,1) + \arg DMAx(x=0,1) + \param[in] channelx: specify which DMA channel + only one parameter can be selected which is shown as below: + \arg DMA0: DMA_CHx(x=0..6), DMA1: DMA_CHx(x=0..4) + \param[in] pwidth: transfer data width of peripheral + only one parameter can be selected which is shown as below: + \arg DMA_PERIPHERAL_WIDTH_8BIT: transfer data width of peripheral is 8-bit + \arg DMA_PERIPHERAL_WIDTH_16BIT: transfer data width of peripheral is 16-bit + \arg DMA_PERIPHERAL_WIDTH_32BIT: transfer data width of peripheral is 32-bit + \param[out] none + \retval none +*/ +void dma_periph_width_config (uint32_t dma_periph, dma_channel_enum channelx, uint32_t pwidth) +{ + uint32_t ctl; + + if(ERROR == dma_periph_and_channel_check(dma_periph, channelx)){ + DMA_WRONG_HANDLE + } + + /* acquire DMA_CHxCTL register */ + ctl = DMA_CHCTL(dma_periph, channelx); + /* assign regiser */ + ctl &= ~DMA_CHXCTL_PWIDTH; + ctl |= pwidth; + DMA_CHCTL(dma_periph, channelx) = ctl; +} + +/*! + \brief enable next address increasement algorithm of memory + \param[in] dma_periph: DMAx(x=0,1) + \arg DMAx(x=0,1) + \param[in] channelx: specify which DMA channel + only one parameter can be selected which is shown as below: + \arg DMA0: DMA_CHx(x=0..6), DMA1: DMA_CHx(x=0..4) + \param[out] none + \retval none +*/ +void dma_memory_increase_enable(uint32_t dma_periph, dma_channel_enum channelx) +{ + if(ERROR == dma_periph_and_channel_check(dma_periph, channelx)){ + DMA_WRONG_HANDLE + } + + DMA_CHCTL(dma_periph, channelx) |= DMA_CHXCTL_MNAGA; +} + +/*! + \brief disable next address increasement algorithm of memory + \param[in] dma_periph: DMAx(x=0,1) + \arg DMAx(x=0,1) + \param[in] channelx: specify which DMA channel + only one parameter can be selected which is shown as below: + \arg DMA0: DMA_CHx(x=0..6), DMA1: DMA_CHx(x=0..4) + \param[out] none + \retval none +*/ +void dma_memory_increase_disable(uint32_t dma_periph, dma_channel_enum channelx) +{ + if(ERROR == dma_periph_and_channel_check(dma_periph, channelx)){ + DMA_WRONG_HANDLE + } + + DMA_CHCTL(dma_periph, channelx) &= ~DMA_CHXCTL_MNAGA; +} + +/*! + \brief enable next address increasement algorithm of peripheral + \param[in] dma_periph: DMAx(x=0,1) + \arg DMAx(x=0,1) + \param[in] channelx: specify which DMA channel + only one parameter can be selected which is shown as below: + \arg DMA0: DMA_CHx(x=0..6), DMA1: DMA_CHx(x=0..4) + \param[out] none + \retval none +*/ +void dma_periph_increase_enable(uint32_t dma_periph, dma_channel_enum channelx) +{ + if(ERROR == dma_periph_and_channel_check(dma_periph, channelx)){ + DMA_WRONG_HANDLE + } + + DMA_CHCTL(dma_periph, channelx) |= DMA_CHXCTL_PNAGA; +} + +/*! + \brief disable next address increasement algorithm of peripheral + \param[in] dma_periph: DMAx(x=0,1) + \arg DMAx(x=0,1) + \param[in] channelx: specify which DMA channel + only one parameter can be selected which is shown as below: + \arg DMA0: DMA_CHx(x=0..6), DMA1: DMA_CHx(x=0..4) + \param[out] none + \retval none +*/ +void dma_periph_increase_disable(uint32_t dma_periph, dma_channel_enum channelx) +{ + if(ERROR == dma_periph_and_channel_check(dma_periph, channelx)){ + DMA_WRONG_HANDLE + } + + DMA_CHCTL(dma_periph, channelx) &= ~DMA_CHXCTL_PNAGA; +} + +/*! + \brief configure the direction of data transfer on the channel + \param[in] dma_periph: DMAx(x=0,1) + \arg DMAx(x=0,1) + \param[in] channelx: specify which DMA channel + only one parameter can be selected which is shown as below: + \arg DMA0: DMA_CHx(x=0..6), DMA1: DMA_CHx(x=0..4) + \param[in] direction: specify the direction of data transfer + only one parameter can be selected which is shown as below: + \arg DMA_PERIPHERAL_TO_MEMORY: read from peripheral and write to memory + \arg DMA_MEMORY_TO_PERIPHERAL: read from memory and write to peripheral + \param[out] none + \retval none +*/ +void dma_transfer_direction_config(uint32_t dma_periph, dma_channel_enum channelx, uint32_t direction) +{ + if(ERROR == dma_periph_and_channel_check(dma_periph, channelx)){ + DMA_WRONG_HANDLE + } + + if(DMA_PERIPHERAL_TO_MEMORY == direction){ + DMA_CHCTL(dma_periph, channelx) &= ~DMA_CHXCTL_DIR; + } else { + DMA_CHCTL(dma_periph, channelx) |= DMA_CHXCTL_DIR; + } +} + +/*! + \brief check DMA flag is set or not + \param[in] dma_periph: DMAx(x=0,1) + \arg DMAx(x=0,1) + \param[in] channelx: specify which DMA channel to get flag + only one parameter can be selected which is shown as below: + \arg DMA0: DMA_CHx(x=0..6), DMA1: DMA_CHx(x=0..4) + \param[in] flag: specify get which flag + only one parameter can be selected which is shown as below: + \arg DMA_FLAG_G: global interrupt flag of channel + \arg DMA_FLAG_FTF: full transfer finish flag of channel + \arg DMA_FLAG_HTF: half transfer finish flag of channel + \arg DMA_FLAG_ERR: error flag of channel + \param[out] none + \retval FlagStatus: SET or RESET +*/ +FlagStatus dma_flag_get(uint32_t dma_periph, dma_channel_enum channelx, uint32_t flag) +{ + FlagStatus reval; + + if(RESET != (DMA_INTF(dma_periph) & DMA_FLAG_ADD(flag, channelx))){ + reval = SET; + }else{ + reval = RESET; + } + + return reval; +} + +/*! + \brief clear DMA a channel flag + \param[in] dma_periph: DMAx(x=0,1) + \arg DMAx(x=0,1) + \param[in] channelx: specify which DMA channel to clear flag + only one parameter can be selected which is shown as below: + \arg DMA0: DMA_CHx(x=0..6), DMA1: DMA_CHx(x=0..4) + \param[in] flag: specify get which flag + only one parameter can be selected which is shown as below: + \arg DMA_FLAG_G: global interrupt flag of channel + \arg DMA_FLAG_FTF: full transfer finish flag of channel + \arg DMA_FLAG_HTF: half transfer finish flag of channel + \arg DMA_FLAG_ERR: error flag of channel + \param[out] none + \retval none +*/ +void dma_flag_clear(uint32_t dma_periph, dma_channel_enum channelx, uint32_t flag) +{ + DMA_INTC(dma_periph) |= DMA_FLAG_ADD(flag, channelx); +} + +/*! + \brief check DMA flag and interrupt enable bit is set or not + \param[in] dma_periph: DMAx(x=0,1) + \arg DMAx(x=0,1) + \param[in] channelx: specify which DMA channel to get flag + only one parameter can be selected which is shown as below: + \arg DMA0: DMA_CHx(x=0..6), DMA1: DMA_CHx(x=0..4) + \param[in] flag: specify get which flag + only one parameter can be selected which is shown as below: + \arg DMA_INT_FLAG_FTF: full transfer finish interrupt flag of channel + \arg DMA_INT_FLAG_HTF: half transfer finish interrupt flag of channel + \arg DMA_INT_FLAG_ERR: error interrupt flag of channel + \param[out] none + \retval FlagStatus: SET or RESET +*/ +FlagStatus dma_interrupt_flag_get(uint32_t dma_periph, dma_channel_enum channelx, uint32_t flag) +{ + uint32_t interrupt_enable = 0U, interrupt_flag = 0U; + + switch(flag){ + case DMA_INT_FLAG_FTF: + interrupt_flag = DMA_INTF(dma_periph) & DMA_FLAG_ADD(flag, channelx); + interrupt_enable = DMA_CHCTL(dma_periph, channelx) & DMA_CHXCTL_FTFIE; + break; + case DMA_INT_FLAG_HTF: + interrupt_flag = DMA_INTF(dma_periph) & DMA_FLAG_ADD(flag, channelx); + interrupt_enable = DMA_CHCTL(dma_periph, channelx) & DMA_CHXCTL_HTFIE; + break; + case DMA_INT_FLAG_ERR: + interrupt_flag = DMA_INTF(dma_periph) & DMA_FLAG_ADD(flag, channelx); + interrupt_enable = DMA_CHCTL(dma_periph, channelx) & DMA_CHXCTL_ERRIE; + break; + default: + DMA_WRONG_HANDLE + } + + if(interrupt_flag && interrupt_enable){ + return SET; + }else{ + return RESET; + } +} + +/*! + \brief clear DMA a channel flag + \param[in] dma_periph: DMAx(x=0,1) + \arg DMAx(x=0,1) + \param[in] channelx: specify which DMA channel to clear flag + only one parameter can be selected which is shown as below: + \arg DMA0: DMA_CHx(x=0..6), DMA1: DMA_CHx(x=0..4) + \param[in] flag: specify get which flag + only one parameter can be selected which is shown as below: + \arg DMA_INT_FLAG_G: global interrupt flag of channel + \arg DMA_INT_FLAG_FTF: full transfer finish interrupt flag of channel + \arg DMA_INT_FLAG_HTF: half transfer finish interrupt flag of channel + \arg DMA_INT_FLAG_ERR: error interrupt flag of channel + \param[out] none + \retval none +*/ +void dma_interrupt_flag_clear(uint32_t dma_periph, dma_channel_enum channelx, uint32_t flag) +{ + DMA_INTC(dma_periph) |= DMA_FLAG_ADD(flag, channelx); +} + +/*! + \brief enable DMA interrupt + \param[in] dma_periph: DMAx(x=0,1) + \arg DMAx(x=0,1) + \param[in] channelx: specify which DMA channel + only one parameter can be selected which is shown as below: + \arg DMA0: DMA_CHx(x=0..6), DMA1: DMA_CHx(x=0..4) + \param[in] source: specify which interrupt to enbale + one or more parameters can be selected which are shown as below + \arg DMA_INT_FTF: channel full transfer finish interrupt + \arg DMA_INT_HTF: channel half transfer finish interrupt + \arg DMA_INT_ERR: channel error interrupt + \param[out] none + \retval none +*/ +void dma_interrupt_enable(uint32_t dma_periph, dma_channel_enum channelx, uint32_t source) +{ + if(ERROR == dma_periph_and_channel_check(dma_periph, channelx)){ + DMA_WRONG_HANDLE + } + + DMA_CHCTL(dma_periph, channelx) |= source; +} + +/*! + \brief disable DMA interrupt + \param[in] dma_periph: DMAx(x=0,1) + \arg DMAx(x=0,1) + \param[in] channelx: specify which DMA channel + only one parameter can be selected which is shown as below: + \arg DMA0: DMA_CHx(x=0..6), DMA1: DMA_CHx(x=0..4) + \param[in] source: specify which interrupt to disbale + one or more parameters can be selected which are shown as below + \arg DMA_INT_FTF: channel full transfer finish interrupt + \arg DMA_INT_HTF: channel half transfer finish interrupt + \arg DMA_INT_ERR: channel error interrupt + \param[out] none + \retval none +*/ +void dma_interrupt_disable(uint32_t dma_periph, dma_channel_enum channelx, uint32_t source) +{ + if(ERROR == dma_periph_and_channel_check(dma_periph, channelx)){ + DMA_WRONG_HANDLE + } + + DMA_CHCTL(dma_periph, channelx) &= ~source; +} + +/*! + \brief check whether peripheral and channels match + \param[in] dma_periph: DMAx(x=0,1) + \arg DMAx(x=0,1) + \param[in] channelx: specify which DMA channel + only one parameter can be selected which is shown as below: + \arg DMA_CHx(x=0..6) + \param[out] none + \retval none +*/ +static ErrStatus dma_periph_and_channel_check(uint32_t dma_periph, dma_channel_enum channelx) +{ + ErrStatus val = SUCCESS; + + if(DMA1 == dma_periph){ + /* for DMA1, the channel is from DMA_CH0 to DMA_CH4 */ + if(channelx > DMA_CH4){ + val = ERROR; + } + } + + return val; +} diff --git a/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_standard_peripheral/Source/gd32f30x_enet.c b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_standard_peripheral/Source/gd32f30x_enet.c new file mode 100644 index 0000000000..78d82a99a4 --- /dev/null +++ b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_standard_peripheral/Source/gd32f30x_enet.c @@ -0,0 +1,3680 @@ +/*! + \file gd32f30x_enet.c + \brief ENET driver + + \version 2017-02-10, V1.0.0, firmware for GD32F30x + \version 2018-10-10, V1.1.0, firmware for GD32F30x + \version 2018-12-25, V2.0.0, firmware for GD32F30x + \version 2020-04-02, V2.0.1, firmware for GD32F30x + \version 2020-09-30, V2.1.0, firmware for GD32F30x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "gd32f30x_enet.h" +#include + +#ifdef GD32F30X_CL + +#if defined (__CC_ARM) /*!< ARM compiler */ +__align(4) +enet_descriptors_struct rxdesc_tab[ENET_RXBUF_NUM]; /*!< ENET RxDMA descriptor */ +__align(4) +enet_descriptors_struct txdesc_tab[ENET_TXBUF_NUM]; /*!< ENET TxDMA descriptor */ +__align(4) +uint8_t rx_buff[ENET_RXBUF_NUM][ENET_RXBUF_SIZE]; /*!< ENET receive buffer */ +__align(4) +uint8_t tx_buff[ENET_TXBUF_NUM][ENET_TXBUF_SIZE]; /*!< ENET transmit buffer */ + +#elif defined ( __ICCARM__ ) /*!< IAR compiler */ +#pragma data_alignment=4 +enet_descriptors_struct rxdesc_tab[ENET_RXBUF_NUM]; /*!< ENET RxDMA descriptor */ +#pragma data_alignment=4 +enet_descriptors_struct txdesc_tab[ENET_TXBUF_NUM]; /*!< ENET TxDMA descriptor */ +#pragma data_alignment=4 +uint8_t rx_buff[ENET_RXBUF_NUM][ENET_RXBUF_SIZE]; /*!< ENET receive buffer */ +#pragma data_alignment=4 +uint8_t tx_buff[ENET_TXBUF_NUM][ENET_TXBUF_SIZE]; /*!< ENET transmit buffer */ + +#elif defined (__GNUC__) /* GNU Compiler */ +enet_descriptors_struct rxdesc_tab[ENET_RXBUF_NUM] __attribute__ ((aligned (4))); /*!< ENET RxDMA descriptor */ +enet_descriptors_struct txdesc_tab[ENET_TXBUF_NUM] __attribute__ ((aligned (4))); /*!< ENET TxDMA descriptor */ +uint8_t rx_buff[ENET_RXBUF_NUM][ENET_RXBUF_SIZE] __attribute__ ((aligned (4))); /*!< ENET receive buffer */ +uint8_t tx_buff[ENET_TXBUF_NUM][ENET_TXBUF_SIZE] __attribute__ ((aligned (4))); /*!< ENET transmit buffer */ + +#endif /* __CC_ARM */ + +/* global transmit and receive descriptors pointers */ +enet_descriptors_struct *dma_current_txdesc; +enet_descriptors_struct *dma_current_rxdesc; + +/* structure pointer of ptp descriptor for normal mode */ +enet_descriptors_struct *dma_current_ptp_txdesc = NULL; +enet_descriptors_struct *dma_current_ptp_rxdesc = NULL; + +/* init structure parameters for ENET initialization */ +static enet_initpara_struct enet_initpara ={0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; + +static uint32_t enet_unknow_err = 0U; +/* array of register offset for debug information get */ +static const uint16_t enet_reg_tab[] = { +0x0000, 0x0004, 0x0008, 0x000C, 0x0010, 0x0014, 0x0018, 0x001C, 0x0028, 0x002C, 0x0034, +0x0038, 0x003C, 0x0040, 0x0044, 0x0048, 0x004C, 0x0050, 0x0054, 0x0058, 0x005C, 0x1080, + +0x0100, 0x0104, 0x0108, 0x010C, 0x0110, 0x014C, 0x0150, 0x0168, 0x0194, 0x0198, 0x01C4, + +0x0700, 0x0704,0x0708, 0x070C, 0x0710, 0x0714, 0x0718, 0x071C, 0x0720, 0x0728, 0x072C, + +0x1000, 0x1004, 0x1008, 0x100C, 0x1010, 0x1014, 0x1018, 0x101C, 0x1020, 0x1024, 0x1048, +0x104C, 0x1050, 0x1054}; + +/* initialize ENET peripheral with generally concerned parameters, call it by enet_init() */ +static void enet_default_init(void); + +#ifndef USE_DELAY +/* insert a delay time */ +static void enet_delay(uint32_t ncount); +#endif /* USE_DELAY */ + +/*! + \brief deinitialize the ENET, and reset structure parameters for ENET initialization + \param[in] none + \param[out] none + \retval none +*/ +void enet_deinit(void) +{ + rcu_periph_reset_enable(RCU_ENETRST); + rcu_periph_reset_disable(RCU_ENETRST); + enet_initpara_reset(); +} + +/*! + \brief configure the parameters which are usually less cared for initialization + note -- this function must be called before enet_init(), otherwise + configuration will be no effect + \param[in] option: different function option, which is related to several parameters, + only one parameter can be selected which is shown as below, refer to enet_option_enum + \arg FORWARD_OPTION: choose to configure the frame forward related parameters + \arg DMABUS_OPTION: choose to configure the DMA bus mode related parameters + \arg DMA_MAXBURST_OPTION: choose to configure the DMA max burst related parameters + \arg DMA_ARBITRATION_OPTION: choose to configure the DMA arbitration related parameters + \arg STORE_OPTION: choose to configure the store forward mode related parameters + \arg DMA_OPTION: choose to configure the DMA descriptor related parameters + \arg VLAN_OPTION: choose to configure vlan related parameters + \arg FLOWCTL_OPTION: choose to configure flow control related parameters + \arg HASHH_OPTION: choose to configure hash high + \arg HASHL_OPTION: choose to configure hash low + \arg FILTER_OPTION: choose to configure frame filter related parameters + \arg HALFDUPLEX_OPTION: choose to configure halfduplex mode related parameters + \arg TIMER_OPTION: choose to configure time counter related parameters + \arg INTERFRAMEGAP_OPTION: choose to configure the inter frame gap related parameters + \param[in] para: the related parameters according to the option + all the related parameters should be configured which are shown as below + FORWARD_OPTION related parameters: + - ENET_AUTO_PADCRC_DROP_ENABLE/ ENET_AUTO_PADCRC_DROP_DISABLE ; + - ENET_TYPEFRAME_CRC_DROP_ENABLE/ ENET_TYPEFRAME_CRC_DROP_DISABLE ; + - ENET_FORWARD_ERRFRAMES_ENABLE/ ENET_FORWARD_ERRFRAMES_DISABLE ; + - ENET_FORWARD_UNDERSZ_GOODFRAMES_ENABLE/ ENET_FORWARD_UNDERSZ_GOODFRAMES_DISABLE . + DMABUS_OPTION related parameters: + - ENET_ADDRESS_ALIGN_ENABLE/ ENET_ADDRESS_ALIGN_DISABLE ; + - ENET_FIXED_BURST_ENABLE/ ENET_FIXED_BURST_DISABLE ; + - ENET_MIXED_BURST_ENABLE/ ENET_MIXED_BURST_DISABLE ; + DMA_MAXBURST_OPTION related parameters: + - ENET_RXDP_1BEAT/ ENET_RXDP_2BEAT/ ENET_RXDP_4BEAT/ + ENET_RXDP_8BEAT/ ENET_RXDP_16BEAT/ ENET_RXDP_32BEAT/ + ENET_RXDP_4xPGBL_4BEAT/ ENET_RXDP_4xPGBL_8BEAT/ + ENET_RXDP_4xPGBL_16BEAT/ ENET_RXDP_4xPGBL_32BEAT/ + ENET_RXDP_4xPGBL_64BEAT/ ENET_RXDP_4xPGBL_128BEAT ; + - ENET_PGBL_1BEAT/ ENET_PGBL_2BEAT/ ENET_PGBL_4BEAT/ + ENET_PGBL_8BEAT/ ENET_PGBL_16BEAT/ ENET_PGBL_32BEAT/ + ENET_PGBL_4xPGBL_4BEAT/ ENET_PGBL_4xPGBL_8BEAT/ + ENET_PGBL_4xPGBL_16BEAT/ ENET_PGBL_4xPGBL_32BEAT/ + ENET_PGBL_4xPGBL_64BEAT/ ENET_PGBL_4xPGBL_128BEAT ; + - ENET_RXTX_DIFFERENT_PGBL/ ENET_RXTX_SAME_PGBL ; + DMA_ARBITRATION_OPTION related parameters: + - ENET_ARBITRATION_RXPRIORTX + - ENET_ARBITRATION_RXTX_1_1/ ENET_ARBITRATION_RXTX_2_1/ + ENET_ARBITRATION_RXTX_3_1/ ENET_ARBITRATION_RXTX_4_1/. + STORE_OPTION related parameters: + - ENET_RX_MODE_STOREFORWARD/ ENET_RX_MODE_CUTTHROUGH ; + - ENET_TX_MODE_STOREFORWARD/ ENET_TX_MODE_CUTTHROUGH ; + - ENET_RX_THRESHOLD_64BYTES/ ENET_RX_THRESHOLD_32BYTES/ + ENET_RX_THRESHOLD_96BYTES/ ENET_RX_THRESHOLD_128BYTES ; + - ENET_TX_THRESHOLD_64BYTES/ ENET_TX_THRESHOLD_128BYTES/ + ENET_TX_THRESHOLD_192BYTES/ ENET_TX_THRESHOLD_256BYTES/ + ENET_TX_THRESHOLD_40BYTES/ ENET_TX_THRESHOLD_32BYTES/ + ENET_TX_THRESHOLD_24BYTES/ ENET_TX_THRESHOLD_16BYTES . + DMA_OPTION related parameters: + - ENET_FLUSH_RXFRAME_ENABLE/ ENET_FLUSH_RXFRAME_DISABLE ; + - ENET_SECONDFRAME_OPT_ENABLE/ ENET_SECONDFRAME_OPT_DISABLE ; + - ENET_ENHANCED_DESCRIPTOR/ ENET_NORMAL_DESCRIPTOR . + VLAN_OPTION related parameters: + - ENET_VLANTAGCOMPARISON_12BIT/ ENET_VLANTAGCOMPARISON_16BIT ; + - MAC_VLT_VLTI(regval) . + FLOWCTL_OPTION related parameters: + - MAC_FCTL_PTM(regval) ; + - ENET_ZERO_QUANTA_PAUSE_ENABLE/ ENET_ZERO_QUANTA_PAUSE_DISABLE ; + - ENET_PAUSETIME_MINUS4/ ENET_PAUSETIME_MINUS28/ + ENET_PAUSETIME_MINUS144/ENET_PAUSETIME_MINUS256 ; + - ENET_MAC0_AND_UNIQUE_ADDRESS_PAUSEDETECT/ ENET_UNIQUE_PAUSEDETECT ; + - ENET_RX_FLOWCONTROL_ENABLE/ ENET_RX_FLOWCONTROL_DISABLE ; + - ENET_TX_FLOWCONTROL_ENABLE/ ENET_TX_FLOWCONTROL_DISABLE ; + - ENET_ACTIVE_THRESHOLD_256BYTES/ ENET_ACTIVE_THRESHOLD_512BYTES ; + - ENET_ACTIVE_THRESHOLD_768BYTES/ ENET_ACTIVE_THRESHOLD_1024BYTES ; + - ENET_ACTIVE_THRESHOLD_1280BYTES/ ENET_ACTIVE_THRESHOLD_1536BYTES ; + - ENET_ACTIVE_THRESHOLD_1792BYTES ; + - ENET_DEACTIVE_THRESHOLD_256BYTES/ ENET_DEACTIVE_THRESHOLD_512BYTES ; + - ENET_DEACTIVE_THRESHOLD_768BYTES/ ENET_DEACTIVE_THRESHOLD_1024BYTES ; + - ENET_DEACTIVE_THRESHOLD_1280BYTES/ ENET_DEACTIVE_THRESHOLD_1536BYTES ; + - ENET_DEACTIVE_THRESHOLD_1792BYTES . + HASHH_OPTION related parameters: + - 0x0~0xFFFF FFFFU + HASHL_OPTION related parameters: + - 0x0~0xFFFF FFFFU + FILTER_OPTION related parameters: + - ENET_SRC_FILTER_NORMAL_ENABLE/ ENET_SRC_FILTER_INVERSE_ENABLE/ + ENET_SRC_FILTER_DISABLE ; + - ENET_DEST_FILTER_INVERSE_ENABLE/ ENET_DEST_FILTER_INVERSE_DISABLE ; + - ENET_MULTICAST_FILTER_HASH_OR_PERFECT/ ENET_MULTICAST_FILTER_HASH/ + ENET_MULTICAST_FILTER_PERFECT/ ENET_MULTICAST_FILTER_NONE ; + - ENET_UNICAST_FILTER_EITHER/ ENET_UNICAST_FILTER_HASH/ + ENET_UNICAST_FILTER_PERFECT ; + - ENET_PCFRM_PREVENT_ALL/ ENET_PCFRM_PREVENT_PAUSEFRAME/ + ENET_PCFRM_FORWARD_ALL/ ENET_PCFRM_FORWARD_FILTERED . + HALFDUPLEX_OPTION related parameters: + - ENET_CARRIERSENSE_ENABLE/ ENET_CARRIERSENSE_DISABLE ; + - ENET_RECEIVEOWN_ENABLE/ ENET_RECEIVEOWN_DISABLE ; + - ENET_RETRYTRANSMISSION_ENABLE/ ENET_RETRYTRANSMISSION_DISABLE ; + - ENET_BACKOFFLIMIT_10/ ENET_BACKOFFLIMIT_8/ + ENET_BACKOFFLIMIT_4/ ENET_BACKOFFLIMIT_1 ; + - ENET_DEFERRALCHECK_ENABLE/ ENET_DEFERRALCHECK_DISABLE . + TIMER_OPTION related parameters: + - ENET_WATCHDOG_ENABLE/ ENET_WATCHDOG_DISABLE ; + - ENET_JABBER_ENABLE/ ENET_JABBER_DISABLE ; + INTERFRAMEGAP_OPTION related parameters: + - ENET_INTERFRAMEGAP_96BIT/ ENET_INTERFRAMEGAP_88BIT/ + ENET_INTERFRAMEGAP_80BIT/ ENET_INTERFRAMEGAP_72BIT/ + ENET_INTERFRAMEGAP_64BIT/ ENET_INTERFRAMEGAP_56BIT/ + ENET_INTERFRAMEGAP_48BIT/ ENET_INTERFRAMEGAP_40BIT . + \param[out] none + \retval none +*/ +void enet_initpara_config(enet_option_enum option, uint32_t para) +{ + switch(option){ + case FORWARD_OPTION: + /* choose to configure forward_frame, and save the configuration parameters */ + enet_initpara.option_enable |= (uint32_t)FORWARD_OPTION; + enet_initpara.forward_frame = para; + break; + case DMABUS_OPTION: + /* choose to configure dmabus_mode, and save the configuration parameters */ + enet_initpara.option_enable |= (uint32_t)DMABUS_OPTION; + enet_initpara.dmabus_mode = para; + break; + case DMA_MAXBURST_OPTION: + /* choose to configure dma_maxburst, and save the configuration parameters */ + enet_initpara.option_enable |= (uint32_t)DMA_MAXBURST_OPTION; + enet_initpara.dma_maxburst = para; + break; + case DMA_ARBITRATION_OPTION: + /* choose to configure dma_arbitration, and save the configuration parameters */ + enet_initpara.option_enable |= (uint32_t)DMA_ARBITRATION_OPTION; + enet_initpara.dma_arbitration = para; + break; + case STORE_OPTION: + /* choose to configure store_forward_mode, and save the configuration parameters */ + enet_initpara.option_enable |= (uint32_t)STORE_OPTION; + enet_initpara.store_forward_mode = para; + break; + case DMA_OPTION: + /* choose to configure dma_function, and save the configuration parameters */ + enet_initpara.option_enable |= (uint32_t)DMA_OPTION; + +#ifndef SELECT_DESCRIPTORS_ENHANCED_MODE + para &= ~ENET_ENHANCED_DESCRIPTOR; +#endif /* SELECT_DESCRIPTORS_ENHANCED_MODE */ + + enet_initpara.dma_function = para; + break; + case VLAN_OPTION: + /* choose to configure vlan_config, and save the configuration parameters */ + enet_initpara.option_enable |= (uint32_t)VLAN_OPTION; + enet_initpara.vlan_config = para; + break; + case FLOWCTL_OPTION: + /* choose to configure flow_control, and save the configuration parameters */ + enet_initpara.option_enable |= (uint32_t)FLOWCTL_OPTION; + enet_initpara.flow_control = para; + break; + case HASHH_OPTION: + /* choose to configure hashtable_high, and save the configuration parameters */ + enet_initpara.option_enable |= (uint32_t)HASHH_OPTION; + enet_initpara.hashtable_high = para; + break; + case HASHL_OPTION: + /* choose to configure hashtable_low, and save the configuration parameters */ + enet_initpara.option_enable |= (uint32_t)HASHL_OPTION; + enet_initpara.hashtable_low = para; + break; + case FILTER_OPTION: + /* choose to configure framesfilter_mode, and save the configuration parameters */ + enet_initpara.option_enable |= (uint32_t)FILTER_OPTION; + enet_initpara.framesfilter_mode = para; + break; + case HALFDUPLEX_OPTION: + /* choose to configure halfduplex_param, and save the configuration parameters */ + enet_initpara.option_enable |= (uint32_t)HALFDUPLEX_OPTION; + enet_initpara.halfduplex_param = para; + break; + case TIMER_OPTION: + /* choose to configure timer_config, and save the configuration parameters */ + enet_initpara.option_enable |= (uint32_t)TIMER_OPTION; + enet_initpara.timer_config = para; + break; + case INTERFRAMEGAP_OPTION: + /* choose to configure interframegap, and save the configuration parameters */ + enet_initpara.option_enable |= (uint32_t)INTERFRAMEGAP_OPTION; + enet_initpara.interframegap = para; + break; + default: + break; + } +} + +/*! + \brief initialize ENET peripheral with generally concerned parameters and the less cared + parameters + \param[in] mediamode: PHY mode and mac loopback configurations, only one parameter can be selected + which is shown as below, refer to enet_mediamode_enum + \arg ENET_AUTO_NEGOTIATION: PHY auto negotiation + \arg ENET_100M_FULLDUPLEX: 100Mbit/s, full-duplex + \arg ENET_100M_HALFDUPLEX: 100Mbit/s, half-duplex + \arg ENET_10M_FULLDUPLEX: 10Mbit/s, full-duplex + \arg ENET_10M_HALFDUPLEX: 10Mbit/s, half-duplex + \arg ENET_LOOPBACKMODE: MAC in loopback mode at the MII + \param[in] checksum: IP frame checksum offload function, only one parameter can be selected + which is shown as below, refer to enet_mediamode_enum + \arg ENET_NO_AUTOCHECKSUM: disable IP frame checksum function + \arg ENET_AUTOCHECKSUM_DROP_FAILFRAMES: enable IP frame checksum function + \arg ENET_AUTOCHECKSUM_ACCEPT_FAILFRAMES: enable IP frame checksum function, and the received frame + with only payload error but no other errors will not be dropped + \param[in] recept: frame filter function, only one parameter can be selected + which is shown as below, refer to enet_frmrecept_enum + \arg ENET_PROMISCUOUS_MODE: promiscuous mode enabled + \arg ENET_RECEIVEALL: all received frame are forwarded to application + \arg ENET_BROADCAST_FRAMES_PASS: the address filters pass all received broadcast frames + \arg ENET_BROADCAST_FRAMES_DROP: the address filters filter all incoming broadcast frames + \param[out] none + \retval ErrStatus: ERROR or SUCCESS +*/ +ErrStatus enet_init(enet_mediamode_enum mediamode, enet_chksumconf_enum checksum, enet_frmrecept_enum recept) +{ + uint32_t reg_value=0U, reg_temp = 0U, temp = 0U; + uint32_t media_temp = 0U; + uint32_t timeout = 0U; + uint16_t phy_value = 0U; + ErrStatus phy_state= ERROR, enet_state = ERROR; + + /* PHY interface configuration, configure SMI clock and reset PHY chip */ + if(ERROR == enet_phy_config()){ + _ENET_DELAY_(PHY_RESETDELAY); + if(ERROR == enet_phy_config()){ + return enet_state; + } + } + /* initialize ENET peripheral with generally concerned parameters */ + enet_default_init(); + + /* 1st, configure mediamode */ + media_temp = (uint32_t)mediamode; + /* if is PHY auto negotiation */ + if((uint32_t)ENET_AUTO_NEGOTIATION == media_temp){ + /* wait for PHY_LINKED_STATUS bit be set */ + do{ + enet_phy_write_read(ENET_PHY_READ, PHY_ADDRESS, PHY_REG_BSR, &phy_value); + phy_value &= PHY_LINKED_STATUS; + timeout++; + }while((RESET == phy_value) && (timeout < PHY_READ_TO)); + /* return ERROR due to timeout */ + if(PHY_READ_TO == timeout){ + return enet_state; + } + /* reset timeout counter */ + timeout = 0U; + + /* enable auto-negotiation */ + phy_value = PHY_AUTONEGOTIATION; + phy_state = enet_phy_write_read(ENET_PHY_WRITE, PHY_ADDRESS, PHY_REG_BCR, &phy_value); + if(!phy_state){ + /* return ERROR due to write timeout */ + return enet_state; + } + + /* wait for the PHY_AUTONEGO_COMPLETE bit be set */ + do{ + enet_phy_write_read(ENET_PHY_READ, PHY_ADDRESS, PHY_REG_BSR, &phy_value); + phy_value &= PHY_AUTONEGO_COMPLETE; + timeout++; + }while((RESET == phy_value) && (timeout < (uint32_t)PHY_READ_TO)); + /* return ERROR due to timeout */ + if(PHY_READ_TO == timeout){ + return enet_state; + } + /* reset timeout counter */ + timeout = 0U; + + /* read the result of the auto-negotiation */ + enet_phy_write_read(ENET_PHY_READ, PHY_ADDRESS, PHY_SR, &phy_value); + /* configure the duplex mode of MAC following the auto-negotiation result */ + if((uint16_t)RESET != (phy_value & PHY_DUPLEX_STATUS)){ + media_temp = ENET_MODE_FULLDUPLEX; + }else{ + media_temp = ENET_MODE_HALFDUPLEX; + } + /* configure the communication speed of MAC following the auto-negotiation result */ + if((uint16_t)RESET !=(phy_value & PHY_SPEED_STATUS)){ + media_temp |= ENET_SPEEDMODE_10M; + }else{ + media_temp |= ENET_SPEEDMODE_100M; + } + }else{ + phy_value = (uint16_t)((media_temp & ENET_MAC_CFG_DPM) >> 3); + phy_value |= (uint16_t)((media_temp & ENET_MAC_CFG_SPD) >> 1); + phy_state = enet_phy_write_read(ENET_PHY_WRITE, PHY_ADDRESS, PHY_REG_BCR, &phy_value); + if(!phy_state){ + /* return ERROR due to write timeout */ + return enet_state; + } + /* PHY configuration need some time */ + _ENET_DELAY_(PHY_CONFIGDELAY); + } + /* after configuring the PHY, use mediamode to configure registers */ + reg_value = ENET_MAC_CFG; + /* configure ENET_MAC_CFG register */ + reg_value &= (~(ENET_MAC_CFG_SPD |ENET_MAC_CFG_DPM |ENET_MAC_CFG_LBM)); + reg_value |= media_temp; + ENET_MAC_CFG = reg_value; + + /* 2st, configure checksum */ + if(RESET != ((uint32_t)checksum & ENET_CHECKSUMOFFLOAD_ENABLE)){ + ENET_MAC_CFG |= ENET_CHECKSUMOFFLOAD_ENABLE; + + reg_value = ENET_DMA_CTL; + /* configure ENET_DMA_CTL register */ + reg_value &= ~ENET_DMA_CTL_DTCERFD; + reg_value |= ((uint32_t)checksum & ENET_DMA_CTL_DTCERFD); + ENET_DMA_CTL = reg_value; + } + + /* 3rd, configure recept */ + ENET_MAC_FRMF |= (uint32_t)recept; + + /* 4th, configure different function options */ + /* configure forward_frame related registers */ + if(RESET != (enet_initpara.option_enable & (uint32_t)FORWARD_OPTION)){ + reg_temp = enet_initpara.forward_frame; + + reg_value = ENET_MAC_CFG; + temp = reg_temp; + /* configure ENET_MAC_CFG register */ + reg_value &= (~(ENET_MAC_CFG_TFCD |ENET_MAC_CFG_APCD)); + temp &= (ENET_MAC_CFG_TFCD | ENET_MAC_CFG_APCD); + reg_value |= temp; + ENET_MAC_CFG = reg_value; + + reg_value = ENET_DMA_CTL; + temp = reg_temp; + /* configure ENET_DMA_CTL register */ + reg_value &= (~(ENET_DMA_CTL_FERF |ENET_DMA_CTL_FUF)); + temp &= ((ENET_DMA_CTL_FERF | ENET_DMA_CTL_FUF)<<2); + reg_value |= (temp >> 2); + ENET_DMA_CTL = reg_value; + } + + /* configure dmabus_mode related registers */ + if(RESET != (enet_initpara.option_enable & (uint32_t)DMABUS_OPTION)){ + temp = enet_initpara.dmabus_mode; + + reg_value = ENET_DMA_BCTL; + /* configure ENET_DMA_BCTL register */ + reg_value &= ~(ENET_DMA_BCTL_AA | ENET_DMA_BCTL_FB \ + |ENET_DMA_BCTL_FPBL | ENET_DMA_BCTL_MB); + reg_value |= temp; + ENET_DMA_BCTL = reg_value; + } + + /* configure dma_maxburst related registers */ + if(RESET != (enet_initpara.option_enable & (uint32_t)DMA_MAXBURST_OPTION)){ + temp = enet_initpara.dma_maxburst; + + reg_value = ENET_DMA_BCTL; + /* configure ENET_DMA_BCTL register */ + reg_value &= ~(ENET_DMA_BCTL_RXDP| ENET_DMA_BCTL_PGBL | ENET_DMA_BCTL_UIP); + reg_value |= temp; + ENET_DMA_BCTL = reg_value; + } + + /* configure dma_arbitration related registers */ + if(RESET != (enet_initpara.option_enable & (uint32_t)DMA_ARBITRATION_OPTION)){ + temp = enet_initpara.dma_arbitration; + + reg_value = ENET_DMA_BCTL; + /* configure ENET_DMA_BCTL register */ + reg_value &= ~(ENET_DMA_BCTL_RTPR | ENET_DMA_BCTL_DAB); + reg_value |= temp; + ENET_DMA_BCTL = reg_value; + } + + /* configure store_forward_mode related registers */ + if(RESET != (enet_initpara.option_enable & (uint32_t)STORE_OPTION)){ + temp = enet_initpara.store_forward_mode; + + reg_value = ENET_DMA_CTL; + /* configure ENET_DMA_CTL register */ + reg_value &= ~(ENET_DMA_CTL_RSFD | ENET_DMA_CTL_TSFD| ENET_DMA_CTL_RTHC| ENET_DMA_CTL_TTHC); + reg_value |= temp; + ENET_DMA_CTL = reg_value; + } + + /* configure dma_function related registers */ + if(RESET != (enet_initpara.option_enable & (uint32_t)DMA_OPTION)){ + reg_temp = enet_initpara.dma_function; + + reg_value = ENET_DMA_CTL; + temp = reg_temp; + /* configure ENET_DMA_CTL register */ + reg_value &= (~(ENET_DMA_CTL_DAFRF |ENET_DMA_CTL_OSF)); + temp &= (ENET_DMA_CTL_DAFRF | ENET_DMA_CTL_OSF); + reg_value |= temp; + ENET_DMA_CTL = reg_value; + + reg_value = ENET_DMA_BCTL; + temp = reg_temp; + /* configure ENET_DMA_BCTL register */ + reg_value &= (~ENET_DMA_BCTL_DFM); + temp &= ENET_DMA_BCTL_DFM; + reg_value |= temp; + ENET_DMA_BCTL = reg_value; + } + + /* configure vlan_config related registers */ + if(RESET != (enet_initpara.option_enable & (uint32_t)VLAN_OPTION)){ + reg_temp = enet_initpara.vlan_config; + + reg_value = ENET_MAC_VLT; + /* configure ENET_MAC_VLT register */ + reg_value &= ~(ENET_MAC_VLT_VLTI | ENET_MAC_VLT_VLTC); + reg_value |= reg_temp; + ENET_MAC_VLT = reg_value; + } + + /* configure flow_control related registers */ + if(RESET != (enet_initpara.option_enable & (uint32_t)FLOWCTL_OPTION)){ + reg_temp = enet_initpara.flow_control; + + reg_value = ENET_MAC_FCTL; + temp = reg_temp; + /* configure ENET_MAC_FCTL register */ + reg_value &= ~(ENET_MAC_FCTL_PTM |ENET_MAC_FCTL_DZQP |ENET_MAC_FCTL_PLTS \ + | ENET_MAC_FCTL_UPFDT |ENET_MAC_FCTL_RFCEN |ENET_MAC_FCTL_TFCEN); + temp &= (ENET_MAC_FCTL_PTM |ENET_MAC_FCTL_DZQP |ENET_MAC_FCTL_PLTS \ + | ENET_MAC_FCTL_UPFDT |ENET_MAC_FCTL_RFCEN |ENET_MAC_FCTL_TFCEN); + reg_value |= temp; + ENET_MAC_FCTL = reg_value; + + reg_value = ENET_MAC_FCTH; + temp = reg_temp; + /* configure ENET_MAC_FCTH register */ + reg_value &= ~(ENET_MAC_FCTH_RFA |ENET_MAC_FCTH_RFD); + temp &= ((ENET_MAC_FCTH_RFA | ENET_MAC_FCTH_RFD )<<8); + reg_value |= (temp >> 8); + ENET_MAC_FCTH = reg_value; + } + + /* configure hashtable_high related registers */ + if(RESET != (enet_initpara.option_enable & (uint32_t)HASHH_OPTION)){ + ENET_MAC_HLH = enet_initpara.hashtable_high; + } + + /* configure hashtable_low related registers */ + if(RESET != (enet_initpara.option_enable & (uint32_t)HASHL_OPTION)){ + ENET_MAC_HLL = enet_initpara.hashtable_low; + } + + /* configure framesfilter_mode related registers */ + if(RESET != (enet_initpara.option_enable & (uint32_t)FILTER_OPTION)){ + reg_temp = enet_initpara.framesfilter_mode; + + reg_value = ENET_MAC_FRMF; + /* configure ENET_MAC_FRMF register */ + reg_value &= ~(ENET_MAC_FRMF_SAFLT | ENET_MAC_FRMF_SAIFLT | ENET_MAC_FRMF_DAIFLT \ + | ENET_MAC_FRMF_HMF | ENET_MAC_FRMF_HPFLT | ENET_MAC_FRMF_MFD \ + | ENET_MAC_FRMF_HUF | ENET_MAC_FRMF_PCFRM); + reg_value |= reg_temp; + ENET_MAC_FRMF = reg_value; + } + + /* configure halfduplex_param related registers */ + if(RESET != (enet_initpara.option_enable & (uint32_t)HALFDUPLEX_OPTION)){ + reg_temp = enet_initpara.halfduplex_param; + + reg_value = ENET_MAC_CFG; + /* configure ENET_MAC_CFG register */ + reg_value &= ~(ENET_MAC_CFG_CSD | ENET_MAC_CFG_ROD | ENET_MAC_CFG_RTD \ + | ENET_MAC_CFG_BOL | ENET_MAC_CFG_DFC); + reg_value |= reg_temp; + ENET_MAC_CFG = reg_value; + } + + /* configure timer_config related registers */ + if(RESET != (enet_initpara.option_enable & (uint32_t)TIMER_OPTION)){ + reg_temp = enet_initpara.timer_config; + + reg_value = ENET_MAC_CFG; + /* configure ENET_MAC_CFG register */ + reg_value &= ~(ENET_MAC_CFG_WDD | ENET_MAC_CFG_JBD); + reg_value |= reg_temp; + ENET_MAC_CFG = reg_value; + } + + /* configure interframegap related registers */ + if(RESET != (enet_initpara.option_enable & (uint32_t)INTERFRAMEGAP_OPTION)){ + reg_temp = enet_initpara.interframegap; + + reg_value = ENET_MAC_CFG; + /* configure ENET_MAC_CFG register */ + reg_value &= ~ENET_MAC_CFG_IGBS; + reg_value |= reg_temp; + ENET_MAC_CFG = reg_value; + } + + enet_state = SUCCESS; + return enet_state; +} + +/*! + \brief reset all core internal registers located in CLK_TX and CLK_RX + \param[in] none + \param[out] none + \retval ErrStatus: SUCCESS or ERROR +*/ +ErrStatus enet_software_reset(void) +{ + uint32_t timeout = 0U; + ErrStatus enet_state = ERROR; + uint32_t dma_flag; + + /* reset all core internal registers located in CLK_TX and CLK_RX */ + ENET_DMA_BCTL |= ENET_DMA_BCTL_SWR; + + /* wait for reset operation complete */ + do{ + dma_flag = (ENET_DMA_BCTL & ENET_DMA_BCTL_SWR); + timeout++; + }while((RESET != dma_flag) && (ENET_DELAY_TO != timeout)); + + /* reset operation complete */ + if(RESET == (ENET_DMA_BCTL & ENET_DMA_BCTL_SWR)){ + enet_state = SUCCESS; + } + + return enet_state; +} + +/*! + \brief check receive frame valid and return frame size + \param[in] none + \param[out] none + \retval size of received frame: 0x0 - 0x3FFF +*/ +uint32_t enet_rxframe_size_get(void) +{ + uint32_t size = 0U; + uint32_t status; + + /* get rdes0 information of current RxDMA descriptor */ + status = dma_current_rxdesc->status; + + /* if the desciptor is owned by DMA */ + if((uint32_t)RESET != (status & ENET_RDES0_DAV)){ + return 0U; + } + + /* if has any error, or the frame uses two or more descriptors */ + if((((uint32_t)RESET) != (status & ENET_RDES0_ERRS)) || + (((uint32_t)RESET) == (status & ENET_RDES0_LDES)) || + (((uint32_t)RESET) == (status & ENET_RDES0_FDES))){ + /* drop current receive frame */ + enet_rxframe_drop(); + + return 1U; + } +#ifdef SELECT_DESCRIPTORS_ENHANCED_MODE + /* if is an ethernet-type frame, and IP frame payload error occurred */ + if(((uint32_t)RESET) != (dma_current_rxdesc->status & ENET_RDES0_FRMT) && + ((uint32_t)RESET) != (dma_current_rxdesc->extended_status & ENET_RDES4_IPPLDERR)){ + /* drop current receive frame */ + enet_rxframe_drop(); + + return 1U; + } +#else + /* if is an ethernet-type frame, and IP frame payload error occurred */ + if((((uint32_t)RESET) != (status & ENET_RDES0_FRMT)) && + (((uint32_t)RESET) != (status & ENET_RDES0_PCERR))){ + /* drop current receive frame */ + enet_rxframe_drop(); + + return 1U; + } +#endif + /* if CPU owns current descriptor, no error occured, the frame uses only one descriptor */ + if((((uint32_t)RESET) == (status & ENET_RDES0_DAV)) && + (((uint32_t)RESET) == (status & ENET_RDES0_ERRS)) && + (((uint32_t)RESET) != (status & ENET_RDES0_LDES)) && + (((uint32_t)RESET) != (status & ENET_RDES0_FDES))){ + /* get the size of the received data including CRC */ + size = GET_RDES0_FRML(status); + /* substract the CRC size */ + size = size - 4U; + + /* if is a type frame, and CRC is not included in forwarding frame */ + if((RESET != (ENET_MAC_CFG & ENET_MAC_CFG_TFCD)) && (RESET != (status & ENET_RDES0_FRMT))){ + size = size + 4U; + } + }else{ + enet_unknow_err++; + enet_rxframe_drop(); + + return 1U; + } + + /* return packet size */ + return size; +} + +/*! + \brief initialize the DMA Tx/Rx descriptors's parameters in chain mode + \param[in] direction: the descriptors which users want to init, refer to enet_dmadirection_enum, + only one parameter can be selected which is shown as below + \arg ENET_DMA_TX: DMA Tx descriptors + \arg ENET_DMA_RX: DMA Rx descriptors + \param[out] none + \retval none +*/ +void enet_descriptors_chain_init(enet_dmadirection_enum direction) +{ + uint32_t num = 0U, count = 0U, maxsize = 0U; + uint32_t desc_status = 0U, desc_bufsize = 0U; + enet_descriptors_struct *desc, *desc_tab; + uint8_t *buf; + + /* if want to initialize DMA Tx descriptors */ + if (ENET_DMA_TX == direction){ + /* save a copy of the DMA Tx descriptors */ + desc_tab = txdesc_tab; + buf = &tx_buff[0][0]; + count = ENET_TXBUF_NUM; + maxsize = ENET_TXBUF_SIZE; + + /* select chain mode */ + desc_status = ENET_TDES0_TCHM; + + /* configure DMA Tx descriptor table address register */ + ENET_DMA_TDTADDR = (uint32_t)desc_tab; + dma_current_txdesc = desc_tab; + }else{ + /* if want to initialize DMA Rx descriptors */ + /* save a copy of the DMA Rx descriptors */ + desc_tab = rxdesc_tab; + buf = &rx_buff[0][0]; + count = ENET_RXBUF_NUM; + maxsize = ENET_RXBUF_SIZE; + + /* enable receiving */ + desc_status = ENET_RDES0_DAV; + /* select receive chained mode and set buffer1 size */ + desc_bufsize = ENET_RDES1_RCHM | (uint32_t)ENET_RXBUF_SIZE; + + /* configure DMA Rx descriptor table address register */ + ENET_DMA_RDTADDR = (uint32_t)desc_tab; + dma_current_rxdesc = desc_tab; + } + dma_current_ptp_rxdesc = NULL; + dma_current_ptp_txdesc = NULL; + + /* configure each descriptor */ + for(num=0U; num < count; num++){ + /* get the pointer to the next descriptor of the descriptor table */ + desc = desc_tab + num; + + /* configure descriptors */ + desc->status = desc_status; + desc->control_buffer_size = desc_bufsize; + desc->buffer1_addr = (uint32_t)(&buf[num * maxsize]); + + /* if is not the last descriptor */ + if(num < (count - 1U)){ + /* configure the next descriptor address */ + desc->buffer2_next_desc_addr = (uint32_t)(desc_tab + num + 1U); + }else{ + /* when it is the last descriptor, the next descriptor address + equals to first descriptor address in descriptor table */ + desc->buffer2_next_desc_addr = (uint32_t) desc_tab; + } + } +} + +/*! + \brief initialize the DMA Tx/Rx descriptors's parameters in ring mode + \param[in] direction: the descriptors which users want to init, refer to enet_dmadirection_enum, + only one parameter can be selected which is shown as below + \arg ENET_DMA_TX: DMA Tx descriptors + \arg ENET_DMA_RX: DMA Rx descriptors + \param[out] none + \retval none +*/ +void enet_descriptors_ring_init(enet_dmadirection_enum direction) +{ + uint32_t num = 0U, count = 0U, maxsize = 0U; + uint32_t desc_status = 0U, desc_bufsize = 0U; + enet_descriptors_struct *desc; + enet_descriptors_struct *desc_tab; + uint8_t *buf; + + /* configure descriptor skip length */ + ENET_DMA_BCTL &= ~ENET_DMA_BCTL_DPSL; + ENET_DMA_BCTL |= DMA_BCTL_DPSL(0); + + /* if want to initialize DMA Tx descriptors */ + if (ENET_DMA_TX == direction){ + /* save a copy of the DMA Tx descriptors */ + desc_tab = txdesc_tab; + buf = &tx_buff[0][0]; + count = ENET_TXBUF_NUM; + maxsize = ENET_TXBUF_SIZE; + + /* configure DMA Tx descriptor table address register */ + ENET_DMA_TDTADDR = (uint32_t)desc_tab; + dma_current_txdesc = desc_tab; + }else{ + /* if want to initialize DMA Rx descriptors */ + /* save a copy of the DMA Rx descriptors */ + desc_tab = rxdesc_tab; + buf = &rx_buff[0][0]; + count = ENET_RXBUF_NUM; + maxsize = ENET_RXBUF_SIZE; + + /* enable receiving */ + desc_status = ENET_RDES0_DAV; + /* set buffer1 size */ + desc_bufsize = ENET_RXBUF_SIZE; + + /* configure DMA Rx descriptor table address register */ + ENET_DMA_RDTADDR = (uint32_t)desc_tab; + dma_current_rxdesc = desc_tab; + } + dma_current_ptp_rxdesc = NULL; + dma_current_ptp_txdesc = NULL; + + /* configure each descriptor */ + for(num=0U; num < count; num++){ + /* get the pointer to the next descriptor of the descriptor table */ + desc = desc_tab + num; + + /* configure descriptors */ + desc->status = desc_status; + desc->control_buffer_size = desc_bufsize; + desc->buffer1_addr = (uint32_t)(&buf[num * maxsize]); + + /* when it is the last descriptor */ + if(num == (count - 1U)){ + if (ENET_DMA_TX == direction){ + /* configure transmit end of ring mode */ + desc->status |= ENET_TDES0_TERM; + }else{ + /* configure receive end of ring mode */ + desc->control_buffer_size |= ENET_RDES1_RERM; + } + } + } +} + +/*! + \brief handle current received frame data to application buffer + \param[in] bufsize: the size of buffer which is the parameter in function + \param[out] buffer: pointer to the received frame data + note -- if the input is NULL, user should copy data in application by himself + \retval ErrStatus: SUCCESS or ERROR +*/ +ErrStatus enet_frame_receive(uint8_t *buffer, uint32_t bufsize) +{ + uint32_t offset = 0U, size = 0U; + + /* the descriptor is busy due to own by the DMA */ + if((uint32_t)RESET != (dma_current_rxdesc->status & ENET_RDES0_DAV)){ + return ERROR; + } + + /* if buffer pointer is null, indicates that users has copied data in application */ + if(NULL != buffer){ + /* if no error occurs, and the frame uses only one descriptor */ + if((((uint32_t)RESET) == (dma_current_rxdesc->status & ENET_RDES0_ERRS)) && + (((uint32_t)RESET) != (dma_current_rxdesc->status & ENET_RDES0_LDES)) && + (((uint32_t)RESET) != (dma_current_rxdesc->status & ENET_RDES0_FDES))){ + /* get the frame length except CRC */ + size = GET_RDES0_FRML(dma_current_rxdesc->status); + size = size - 4U; + + /* if is a type frame, and CRC is not included in forwarding frame */ + if((RESET != (ENET_MAC_CFG & ENET_MAC_CFG_TFCD)) && (RESET != (dma_current_rxdesc->status & ENET_RDES0_FRMT))){ + size = size + 4U; + } + + /* to avoid situation that the frame size exceeds the buffer length */ + if(size > bufsize){ + return ERROR; + } + + /* copy data from Rx buffer to application buffer */ + for(offset = 0U; offsetbuffer1_addr) + offset)); + } + + }else{ + /* return ERROR */ + return ERROR; + } + } + /* enable reception, descriptor is owned by DMA */ + dma_current_rxdesc->status = ENET_RDES0_DAV; + + /* check Rx buffer unavailable flag status */ + if ((uint32_t)RESET != (ENET_DMA_STAT & ENET_DMA_STAT_RBU)){ + /* clear RBU flag */ + ENET_DMA_STAT = ENET_DMA_STAT_RBU; + /* resume DMA reception by writing to the RPEN register*/ + ENET_DMA_RPEN = 0U; + } + + /* update the current RxDMA descriptor pointer to the next decriptor in RxDMA decriptor table */ + /* chained mode */ + if((uint32_t)RESET != (dma_current_rxdesc->control_buffer_size & ENET_RDES1_RCHM)){ + dma_current_rxdesc = (enet_descriptors_struct*) (dma_current_rxdesc->buffer2_next_desc_addr); + }else{ + /* ring mode */ + if((uint32_t)RESET != (dma_current_rxdesc->control_buffer_size & ENET_RDES1_RERM)){ + /* if is the last descriptor in table, the next descriptor is the table header */ + dma_current_rxdesc = (enet_descriptors_struct*) (ENET_DMA_RDTADDR); + }else{ + /* the next descriptor is the current address, add the descriptor size, and descriptor skip length */ + dma_current_rxdesc = (enet_descriptors_struct*) (uint32_t)((uint32_t)dma_current_rxdesc + ETH_DMARXDESC_SIZE + (GET_DMA_BCTL_DPSL(ENET_DMA_BCTL))); + } + } + + return SUCCESS; +} + +/*! + \brief handle application buffer data to transmit it + \param[in] buffer: pointer to the frame data to be transmitted, + note -- if the input is NULL, user should handle the data in application by himself + \param[in] length: the length of frame data to be transmitted + \param[out] none + \retval ErrStatus: SUCCESS or ERROR +*/ +ErrStatus enet_frame_transmit(uint8_t *buffer, uint32_t length) +{ + uint32_t offset = 0U; + uint32_t dma_tbu_flag, dma_tu_flag; + + /* the descriptor is busy due to own by the DMA */ + if((uint32_t)RESET != (dma_current_txdesc->status & ENET_TDES0_DAV)){ + return ERROR; + } + + /* only frame length no more than ENET_MAX_FRAME_SIZE is allowed */ + if(length > ENET_MAX_FRAME_SIZE){ + return ERROR; + } + + /* if buffer pointer is null, indicates that users has handled data in application */ + if(NULL != buffer){ + /* copy frame data from application buffer to Tx buffer */ + for(offset = 0U; offset < length; offset++){ + (*(__IO uint8_t *) (uint32_t)((dma_current_txdesc->buffer1_addr) + offset)) = (*(buffer + offset)); + } + } + + /* set the frame length */ + dma_current_txdesc->control_buffer_size = length; + /* set the segment of frame, frame is transmitted in one descriptor */ + dma_current_txdesc->status |= ENET_TDES0_LSG | ENET_TDES0_FSG; + /* enable the DMA transmission */ + dma_current_txdesc->status |= ENET_TDES0_DAV; + + /* check Tx buffer unavailable flag status */ + dma_tbu_flag = (ENET_DMA_STAT & ENET_DMA_STAT_TBU); + dma_tu_flag = (ENET_DMA_STAT & ENET_DMA_STAT_TU); + + if ((RESET != dma_tbu_flag) || (RESET != dma_tu_flag)){ + /* clear TBU and TU flag */ + ENET_DMA_STAT = (dma_tbu_flag | dma_tu_flag); + /* resume DMA transmission by writing to the TPEN register*/ + ENET_DMA_TPEN = 0U; + } + + /* update the current TxDMA descriptor pointer to the next decriptor in TxDMA decriptor table*/ + /* chained mode */ + if((uint32_t)RESET != (dma_current_txdesc->status & ENET_TDES0_TCHM)){ + dma_current_txdesc = (enet_descriptors_struct*) (dma_current_txdesc->buffer2_next_desc_addr); + }else{ + /* ring mode */ + if((uint32_t)RESET != (dma_current_txdesc->status & ENET_TDES0_TERM)){ + /* if is the last descriptor in table, the next descriptor is the table header */ + dma_current_txdesc = (enet_descriptors_struct*) (ENET_DMA_TDTADDR); + }else{ + /* the next descriptor is the current address, add the descriptor size, and descriptor skip length */ + dma_current_txdesc = (enet_descriptors_struct*) (uint32_t)((uint32_t)dma_current_txdesc + ETH_DMATXDESC_SIZE + (GET_DMA_BCTL_DPSL(ENET_DMA_BCTL))); + } + } + + return SUCCESS; +} + +/*! + \brief configure the transmit IP frame checksum offload calculation and insertion + \param[in] desc: the descriptor pointer which users want to configure + \param[in] checksum: IP frame checksum configuration + only one parameter can be selected which is shown as below + \arg ENET_CHECKSUM_DISABLE: checksum insertion disabled + \arg ENET_CHECKSUM_IPV4HEADER: only IP header checksum calculation and insertion are enabled + \arg ENET_CHECKSUM_TCPUDPICMP_SEGMENT: TCP/UDP/ICMP checksum insertion calculated but pseudo-header + \arg ENET_CHECKSUM_TCPUDPICMP_FULL: TCP/UDP/ICMP checksum insertion fully calculated + \param[out] none + \retval ErrStatus: ERROR, SUCCESS +*/ +ErrStatus enet_transmit_checksum_config(enet_descriptors_struct *desc, uint32_t checksum) +{ + if(NULL != desc){ + desc->status &= ~ENET_TDES0_CM; + desc->status |= checksum; + return SUCCESS; + }else{ + return ERROR; + } +} + +/*! + \brief ENET Tx and Rx function enable (include MAC and DMA module) + \param[in] none + \param[out] none + \retval none +*/ +void enet_enable(void) +{ + enet_tx_enable(); + enet_rx_enable(); +} + +/*! + \brief ENET Tx and Rx function disable (include MAC and DMA module) + \param[in] none + \param[out] none + \retval none +*/ +void enet_disable(void) +{ + enet_tx_disable(); + enet_rx_disable(); +} + +/*! + \brief configure MAC address + \param[in] mac_addr: select which MAC address will be set, + only one parameter can be selected which is shown as below + \arg ENET_MAC_ADDRESS0: set MAC address 0 filter + \arg ENET_MAC_ADDRESS1: set MAC address 1 filter + \arg ENET_MAC_ADDRESS2: set MAC address 2 filter + \arg ENET_MAC_ADDRESS3: set MAC address 3 filter + \param[in] paddr: the buffer pointer which stores the MAC address + (little-ending store, such as MAC address is aa:bb:cc:dd:ee:22, the buffer is {22, ee, dd, cc, bb, aa}) + \param[out] none + \retval none +*/ +void enet_mac_address_set(enet_macaddress_enum mac_addr, uint8_t paddr[]) +{ + REG32(ENET_ADDRH_BASE + (uint32_t)mac_addr) = ENET_SET_MACADDRH(paddr); + REG32(ENET_ADDRL_BASE + (uint32_t)mac_addr) = ENET_SET_MACADDRL(paddr); +} + +/*! + \brief get MAC address + \param[in] mac_addr: select which MAC address will be get, + only one parameter can be selected which is shown as below + \arg ENET_MAC_ADDRESS0: get MAC address 0 filter + \arg ENET_MAC_ADDRESS1: get MAC address 1 filter + \arg ENET_MAC_ADDRESS2: get MAC address 2 filter + \arg ENET_MAC_ADDRESS3: get MAC address 3 filter + \param[out] paddr: the buffer pointer which is stored the MAC address + (little-ending store, such as mac address is aa:bb:cc:dd:ee:22, the buffer is {22, ee, dd, cc, bb, aa}) + \param[in] bufsize: refer to the size of the buffer which stores the MAC address + \arg 6 - 255 + \retval ErrStatus: ERROR, SUCCESS +*/ +ErrStatus enet_mac_address_get(enet_macaddress_enum mac_addr, uint8_t paddr[], uint8_t bufsize) +{ + if(bufsize < 6U){ + return ERROR; + } + paddr[0] = ENET_GET_MACADDR(mac_addr, 0U); + paddr[1] = ENET_GET_MACADDR(mac_addr, 1U); + paddr[2] = ENET_GET_MACADDR(mac_addr, 2U); + paddr[3] = ENET_GET_MACADDR(mac_addr, 3U); + paddr[4] = ENET_GET_MACADDR(mac_addr, 4U); + paddr[5] = ENET_GET_MACADDR(mac_addr, 5U); + return SUCCESS; +} + +/*! + \brief get the ENET MAC/MSC/PTP/DMA status flag + \param[in] enet_flag: ENET status flag, refer to enet_flag_enum, + only one parameter can be selected which is shown as below + \arg ENET_MAC_FLAG_MPKR: magic packet received flag + \arg ENET_MAC_FLAG_WUFR: wakeup frame received flag + \arg ENET_MAC_FLAG_FLOWCONTROL: flow control status flag + \arg ENET_MAC_FLAG_WUM: WUM status flag + \arg ENET_MAC_FLAG_MSC: MSC status flag + \arg ENET_MAC_FLAG_MSCR: MSC receive status flag + \arg ENET_MAC_FLAG_MSCT: MSC transmit status flag + \arg ENET_MAC_FLAG_TMST: time stamp trigger status flag + \arg ENET_PTP_FLAG_TSSCO: timestamp second counter overflow flag + \arg ENET_PTP_FLAG_TTM: target time match flag + \arg ENET_MSC_FLAG_RFCE: received frames CRC error flag + \arg ENET_MSC_FLAG_RFAE: received frames alignment error flag + \arg ENET_MSC_FLAG_RGUF: received good unicast frames flag + \arg ENET_MSC_FLAG_TGFSC: transmitted good frames single collision flag + \arg ENET_MSC_FLAG_TGFMSC: transmitted good frames more single collision flag + \arg ENET_MSC_FLAG_TGF: transmitted good frames flag + \arg ENET_DMA_FLAG_TS: transmit status flag + \arg ENET_DMA_FLAG_TPS: transmit process stopped status flag + \arg ENET_DMA_FLAG_TBU: transmit buffer unavailable status flag + \arg ENET_DMA_FLAG_TJT: transmit jabber timeout status flag + \arg ENET_DMA_FLAG_RO: receive overflow status flag + \arg ENET_DMA_FLAG_TU: transmit underflow status flag + \arg ENET_DMA_FLAG_RS: receive status flag + \arg ENET_DMA_FLAG_RBU: receive buffer unavailable status flag + \arg ENET_DMA_FLAG_RPS: receive process stopped status flag + \arg ENET_DMA_FLAG_RWT: receive watchdog timeout status flag + \arg ENET_DMA_FLAG_ET: early transmit status flag + \arg ENET_DMA_FLAG_FBE: fatal bus error status flag + \arg ENET_DMA_FLAG_ER: early receive status flag + \arg ENET_DMA_FLAG_AI: abnormal interrupt summary flag + \arg ENET_DMA_FLAG_NI: normal interrupt summary flag + \arg ENET_DMA_FLAG_EB_DMA_ERROR: DMA error flag + \arg ENET_DMA_FLAG_EB_TRANSFER_ERROR: transfer error flag + \arg ENET_DMA_FLAG_EB_ACCESS_ERROR: access error flag + \arg ENET_DMA_FLAG_MSC: MSC status flag + \arg ENET_DMA_FLAG_WUM: WUM status flag + \arg ENET_DMA_FLAG_TST: timestamp trigger status flag + \param[out] none + \retval FlagStatus: SET or RESET +*/ +FlagStatus enet_flag_get(enet_flag_enum enet_flag) +{ + if(RESET != (ENET_REG_VAL(enet_flag) & BIT(ENET_BIT_POS(enet_flag)))){ + return SET; + }else{ + return RESET; + } +} + +/*! + \brief clear the ENET DMA status flag + \param[in] enet_flag: ENET DMA flag clear, refer to enet_flag_clear_enum + only one parameter can be selected which is shown as below + \arg ENET_DMA_FLAG_TS_CLR: transmit status flag clear + \arg ENET_DMA_FLAG_TPS_CLR: transmit process stopped status flag clear + \arg ENET_DMA_FLAG_TBU_CLR: transmit buffer unavailable status flag clear + \arg ENET_DMA_FLAG_TJT_CLR: transmit jabber timeout status flag clear + \arg ENET_DMA_FLAG_RO_CLR: receive overflow status flag clear + \arg ENET_DMA_FLAG_TU_CLR: transmit underflow status flag clear + \arg ENET_DMA_FLAG_RS_CLR: receive status flag clear + \arg ENET_DMA_FLAG_RBU_CLR: receive buffer unavailable status flag clear + \arg ENET_DMA_FLAG_RPS_CLR: receive process stopped status flag clear + \arg ENET_DMA_FLAG_RWT_CLR: receive watchdog timeout status flag clear + \arg ENET_DMA_FLAG_ET_CLR: early transmit status flag clear + \arg ENET_DMA_FLAG_FBE_CLR: fatal bus error status flag clear + \arg ENET_DMA_FLAG_ER_CLR: early receive status flag clear + \arg ENET_DMA_FLAG_AI_CLR: abnormal interrupt summary flag clear + \arg ENET_DMA_FLAG_NI_CLR: normal interrupt summary flag clear + \param[out] none + \retval none +*/ +void enet_flag_clear(enet_flag_clear_enum enet_flag) +{ + /* write 1 to the corresponding bit in ENET_DMA_STAT, to clear it */ + ENET_REG_VAL(enet_flag) = BIT(ENET_BIT_POS(enet_flag)); +} + +/*! + \brief enable ENET MAC/MSC/DMA interrupt + \param[in] enet_int: ENET interrupt, + only one parameter can be selected which is shown as below + \arg ENET_MAC_INT_WUMIM: WUM interrupt mask + \arg ENET_MAC_INT_TMSTIM: timestamp trigger interrupt mask + \arg ENET_MSC_INT_RFCEIM: received frame CRC error interrupt mask + \arg ENET_MSC_INT_RFAEIM: received frames alignment error interrupt mask + \arg ENET_MSC_INT_RGUFIM: received good unicast frames interrupt mask + \arg ENET_MSC_INT_TGFSCIM: transmitted good frames single collision interrupt mask + \arg ENET_MSC_INT_TGFMSCIM: transmitted good frames more single collision interrupt mask + \arg ENET_MSC_INT_TGFIM: transmitted good frames interrupt mask + \arg ENET_DMA_INT_TIE: transmit interrupt enable + \arg ENET_DMA_INT_TPSIE: transmit process stopped interrupt enable + \arg ENET_DMA_INT_TBUIE: transmit buffer unavailable interrupt enable + \arg ENET_DMA_INT_TJTIE: transmit jabber timeout interrupt enable + \arg ENET_DMA_INT_ROIE: receive overflow interrupt enable + \arg ENET_DMA_INT_TUIE: transmit underflow interrupt enable + \arg ENET_DMA_INT_RIE: receive interrupt enable + \arg ENET_DMA_INT_RBUIE: receive buffer unavailable interrupt enable + \arg ENET_DMA_INT_RPSIE: receive process stopped interrupt enable + \arg ENET_DMA_INT_RWTIE: receive watchdog timeout interrupt enable + \arg ENET_DMA_INT_ETIE: early transmit interrupt enable + \arg ENET_DMA_INT_FBEIE: fatal bus error interrupt enable + \arg ENET_DMA_INT_ERIE: early receive interrupt enable + \arg ENET_DMA_INT_AIE: abnormal interrupt summary enable + \arg ENET_DMA_INT_NIE: normal interrupt summary enable + \param[out] none + \retval none +*/ +void enet_interrupt_enable(enet_int_enum enet_int) +{ + if(DMA_INTEN_REG_OFFSET == ((uint32_t)enet_int >> 6)){ + /* ENET_DMA_INTEN register interrupt */ + ENET_REG_VAL(enet_int) |= BIT(ENET_BIT_POS(enet_int)); + }else{ + /* other INTMSK register interrupt */ + ENET_REG_VAL(enet_int) &= ~BIT(ENET_BIT_POS(enet_int)); + } +} + +/*! + \brief disable ENET MAC/MSC/DMA interrupt + \param[in] enet_int: ENET interrupt, + only one parameter can be selected which is shown as below + \arg ENET_MAC_INT_WUMIM: WUM interrupt mask + \arg ENET_MAC_INT_TMSTIM: timestamp trigger interrupt mask + \arg ENET_MSC_INT_RFCEIM: received frame CRC error interrupt mask + \arg ENET_MSC_INT_RFAEIM: received frames alignment error interrupt mask + \arg ENET_MSC_INT_RGUFIM: received good unicast frames interrupt mask + \arg ENET_MSC_INT_TGFSCIM: transmitted good frames single collision interrupt mask + \arg ENET_MSC_INT_TGFMSCIM: transmitted good frames more single collision interrupt mask + \arg ENET_MSC_INT_TGFIM: transmitted good frames interrupt mask + \arg ENET_DMA_INT_TIE: transmit interrupt enable + \arg ENET_DMA_INT_TPSIE: transmit process stopped interrupt enable + \arg ENET_DMA_INT_TBUIE: transmit buffer unavailable interrupt enable + \arg ENET_DMA_INT_TJTIE: transmit jabber timeout interrupt enable + \arg ENET_DMA_INT_ROIE: receive overflow interrupt enable + \arg ENET_DMA_INT_TUIE: transmit underflow interrupt enable + \arg ENET_DMA_INT_RIE: receive interrupt enable + \arg ENET_DMA_INT_RBUIE: receive buffer unavailable interrupt enable + \arg ENET_DMA_INT_RPSIE: receive process stopped interrupt enable + \arg ENET_DMA_INT_RWTIE: receive watchdog timeout interrupt enable + \arg ENET_DMA_INT_ETIE: early transmit interrupt enable + \arg ENET_DMA_INT_FBEIE: fatal bus error interrupt enable + \arg ENET_DMA_INT_ERIE: early receive interrupt enable + \arg ENET_DMA_INT_AIE: abnormal interrupt summary enable + \arg ENET_DMA_INT_NIE: normal interrupt summary enable + \param[out] none + \retval none +*/ +void enet_interrupt_disable(enet_int_enum enet_int) +{ + if(DMA_INTEN_REG_OFFSET == ((uint32_t)enet_int >> 6)){ + /* ENET_DMA_INTEN register interrupt */ + ENET_REG_VAL(enet_int) &= ~BIT(ENET_BIT_POS(enet_int)); + }else{ + /* other INTMSK register interrupt */ + ENET_REG_VAL(enet_int) |= BIT(ENET_BIT_POS(enet_int)); + } +} + +/*! + \brief get ENET MAC/MSC/DMA interrupt flag + \param[in] int_flag: ENET interrupt flag, + only one parameter can be selected which is shown as below + \arg ENET_MAC_INT_FLAG_WUM: WUM status flag + \arg ENET_MAC_INT_FLAG_MSC: MSC status flag + \arg ENET_MAC_INT_FLAG_MSCR: MSC receive status flag + \arg ENET_MAC_INT_FLAG_MSCT: MSC transmit status flag + \arg ENET_MAC_INT_FLAG_TMST: time stamp trigger status flag + \arg ENET_MSC_INT_FLAG_RFCE: received frames CRC error flag + \arg ENET_MSC_INT_FLAG_RFAE: received frames alignment error flag + \arg ENET_MSC_INT_FLAG_RGUF: received good unicast frames flag + \arg ENET_MSC_INT_FLAG_TGFSC: transmitted good frames single collision flag + \arg ENET_MSC_INT_FLAG_TGFMSC: transmitted good frames more single collision flag + \arg ENET_MSC_INT_FLAG_TGF: transmitted good frames flag + \arg ENET_DMA_INT_FLAG_TS: transmit status flag + \arg ENET_DMA_INT_FLAG_TPS: transmit process stopped status flag + \arg ENET_DMA_INT_FLAG_TBU: transmit buffer unavailable status flag + \arg ENET_DMA_INT_FLAG_TJT: transmit jabber timeout status flag + \arg ENET_DMA_INT_FLAG_RO: receive overflow status flag + \arg ENET_DMA_INT_FLAG_TU: transmit underflow status flag + \arg ENET_DMA_INT_FLAG_RS: receive status flag + \arg ENET_DMA_INT_FLAG_RBU: receive buffer unavailable status flag + \arg ENET_DMA_INT_FLAG_RPS: receive process stopped status flag + \arg ENET_DMA_INT_FLAG_RWT: receive watchdog timeout status flag + \arg ENET_DMA_INT_FLAG_ET: early transmit status flag + \arg ENET_DMA_INT_FLAG_FBE: fatal bus error status flag + \arg ENET_DMA_INT_FLAG_ER: early receive status flag + \arg ENET_DMA_INT_FLAG_AI: abnormal interrupt summary flag + \arg ENET_DMA_INT_FLAG_NI: normal interrupt summary flag + \arg ENET_DMA_INT_FLAG_MSC: MSC status flag + \arg ENET_DMA_INT_FLAG_WUM: WUM status flag + \arg ENET_DMA_INT_FLAG_TST: timestamp trigger status flag + \param[out] none + \retval FlagStatus: SET or RESET +*/ +FlagStatus enet_interrupt_flag_get(enet_int_flag_enum int_flag) +{ + if(RESET != (ENET_REG_VAL(int_flag) & BIT(ENET_BIT_POS(int_flag)))){ + return SET; + }else{ + return RESET; + } +} + +/*! + \brief clear ENET DMA interrupt flag + \param[in] int_flag_clear: clear ENET interrupt flag, + only one parameter can be selected which is shown as below + \arg ENET_DMA_INT_FLAG_TS_CLR: transmit status flag + \arg ENET_DMA_INT_FLAG_TPS_CLR: transmit process stopped status flag + \arg ENET_DMA_INT_FLAG_TBU_CLR: transmit buffer unavailable status flag + \arg ENET_DMA_INT_FLAG_TJT_CLR: transmit jabber timeout status flag + \arg ENET_DMA_INT_FLAG_RO_CLR: receive overflow status flag + \arg ENET_DMA_INT_FLAG_TU_CLR: transmit underflow status flag + \arg ENET_DMA_INT_FLAG_RS_CLR: receive status flag + \arg ENET_DMA_INT_FLAG_RBU_CLR: receive buffer unavailable status flag + \arg ENET_DMA_INT_FLAG_RPS_CLR: receive process stopped status flag + \arg ENET_DMA_INT_FLAG_RWT_CLR: receive watchdog timeout status flag + \arg ENET_DMA_INT_FLAG_ET_CLR: early transmit status flag + \arg ENET_DMA_INT_FLAG_FBE_CLR: fatal bus error status flag + \arg ENET_DMA_INT_FLAG_ER_CLR: early receive status flag + \arg ENET_DMA_INT_FLAG_AI_CLR: abnormal interrupt summary flag + \arg ENET_DMA_INT_FLAG_NI_CLR: normal interrupt summary flag + \param[out] none + \retval none +*/ +void enet_interrupt_flag_clear(enet_int_flag_clear_enum int_flag_clear) +{ + /* write 1 to the corresponding bit in ENET_DMA_STAT, to clear it */ + ENET_REG_VAL(int_flag_clear) = BIT(ENET_BIT_POS(int_flag_clear)); +} + +/*! + \brief ENET Tx function enable (include MAC and DMA module) + \param[in] none + \param[out] none + \retval none +*/ +void enet_tx_enable(void) +{ + ENET_MAC_CFG |= ENET_MAC_CFG_TEN; + enet_txfifo_flush(); + ENET_DMA_CTL |= ENET_DMA_CTL_STE; +} + +/*! + \brief ENET Tx function disable (include MAC and DMA module) + \param[in] none + \param[out] none + \retval none +*/ +void enet_tx_disable(void) +{ + ENET_DMA_CTL &= ~ENET_DMA_CTL_STE; + enet_txfifo_flush(); + ENET_MAC_CFG &= ~ENET_MAC_CFG_TEN; +} + +/*! + \brief ENET Rx function enable (include MAC and DMA module) + \param[in] none + \param[out] none + \retval none +*/ +void enet_rx_enable(void) +{ + ENET_MAC_CFG |= ENET_MAC_CFG_REN; + ENET_DMA_CTL |= ENET_DMA_CTL_SRE; +} + +/*! + \brief ENET Rx function disable (include MAC and DMA module) + \param[in] none + \param[out] none + \retval none +*/ +void enet_rx_disable(void) +{ + ENET_DMA_CTL &= ~ENET_DMA_CTL_SRE; + ENET_MAC_CFG &= ~ENET_MAC_CFG_REN; +} + +/*! + \brief put registers value into the application buffer + \param[in] type: register type which will be get, refer to enet_registers_type_enum, + only one parameter can be selected which is shown as below + \arg ALL_MAC_REG: get the registers within the offset scope between ENET_MAC_CFG and ENET_MAC_FCTH + \arg ALL_MSC_REG: get the registers within the offset scope between ENET_MSC_CTL and ENET_MSC_RGUFCNT + \arg ALL_PTP_REG: get the registers within the offset scope between ENET_PTP_TSCTL and ENET_PTP_PPSCTL + \arg ALL_DMA_REG: get the registers within the offset scope between ENET_DMA_BCTL and ENET_DMA_CRBADDR + \param[in] num: the number of registers that the user want to get + \param[out] preg: the application buffer pointer for storing the register value + \retval none +*/ +void enet_registers_get(enet_registers_type_enum type, uint32_t *preg, uint32_t num) +{ + uint32_t offset = 0U, max = 0U, limit = 0U; + + offset = (uint32_t)type; + max = (uint32_t)type + num; + limit = sizeof(enet_reg_tab)/sizeof(uint16_t); + + /* prevent element in this array is out of range */ + if(max > limit){ + max = limit; + } + + for(; offset < max; offset++){ + /* get value of the corresponding register */ + *preg = REG32((ENET) + enet_reg_tab[offset]); + preg++; + } +} + +/*! + \brief get the enet debug status from the debug register + \param[in] mac_debug: enet debug status, + only one parameter can be selected which is shown as below + \arg ENET_MAC_RECEIVER_NOT_IDLE: MAC receiver is not in idle state + \arg ENET_RX_ASYNCHRONOUS_FIFO_STATE: Rx asynchronous FIFO status + \arg ENET_RXFIFO_WRITING: RxFIFO is doing write operation + \arg ENET_RXFIFO_READ_STATUS: RxFIFO read operation status + \arg ENET_RXFIFO_STATE: RxFIFO state + \arg ENET_MAC_TRANSMITTER_NOT_IDLE: MAC transmitter is not in idle state + \arg ENET_MAC_TRANSMITTER_STATUS: status of MAC transmitter + \arg ENET_PAUSE_CONDITION_STATUS: pause condition status + \arg ENET_TXFIFO_READ_STATUS: TxFIFO read operation status + \arg ENET_TXFIFO_WRITING: TxFIFO is doing write operation + \arg ENET_TXFIFO_NOT_EMPTY: TxFIFO is not empty + \arg ENET_TXFIFO_FULL: TxFIFO is full + \param[out] none + \retval value of the status users want to get +*/ +uint32_t enet_debug_status_get(uint32_t mac_debug) +{ + uint32_t temp_state = 0U; + + switch(mac_debug){ + case ENET_RX_ASYNCHRONOUS_FIFO_STATE: + temp_state = GET_MAC_DBG_RXAFS(ENET_MAC_DBG); + break; + case ENET_RXFIFO_READ_STATUS: + temp_state = GET_MAC_DBG_RXFRS(ENET_MAC_DBG); + break; + case ENET_RXFIFO_STATE: + temp_state = GET_MAC_DBG_RXFS(ENET_MAC_DBG); + break; + case ENET_MAC_TRANSMITTER_STATUS: + temp_state = GET_MAC_DBG_SOMT(ENET_MAC_DBG); + break; + case ENET_TXFIFO_READ_STATUS: + temp_state = GET_MAC_DBG_TXFRS(ENET_MAC_DBG); + break; + default: + if(RESET != (ENET_MAC_DBG & mac_debug)){ + temp_state = 0x1U; + } + break; + } + return temp_state; +} + +/*! + \brief enable the MAC address filter + \param[in] mac_addr: select which MAC address will be enable + \arg ENET_MAC_ADDRESS1: enable MAC address 1 filter + \arg ENET_MAC_ADDRESS2: enable MAC address 2 filter + \arg ENET_MAC_ADDRESS3: enable MAC address 3 filter + \param[out] none + \retval none +*/ +void enet_address_filter_enable(enet_macaddress_enum mac_addr) +{ + REG32(ENET_ADDRH_BASE + mac_addr) |= ENET_MAC_ADDR1H_AFE; +} + +/*! + \brief disable the MAC address filter + \param[in] mac_addr: select which MAC address will be disable, + only one parameter can be selected which is shown as below + \arg ENET_MAC_ADDRESS1: disable MAC address 1 filter + \arg ENET_MAC_ADDRESS2: disable MAC address 2 filter + \arg ENET_MAC_ADDRESS3: disable MAC address 3 filter + \param[out] none + \retval none +*/ +void enet_address_filter_disable(enet_macaddress_enum mac_addr) +{ + REG32(ENET_ADDRH_BASE + mac_addr) &= ~ENET_MAC_ADDR1H_AFE; +} + +/*! + \brief configure the MAC address filter + \param[in] mac_addr: select which MAC address will be configured, + only one parameter can be selected which is shown as below + \arg ENET_MAC_ADDRESS1: configure MAC address 1 filter + \arg ENET_MAC_ADDRESS2: configure MAC address 2 filter + \arg ENET_MAC_ADDRESS3: configure MAC address 3 filter + \param[in] addr_mask: select which MAC address bytes will be mask, + one or more parameters can be selected which are shown as below + \arg ENET_ADDRESS_MASK_BYTE0: mask ENET_MAC_ADDR1L[7:0] bits + \arg ENET_ADDRESS_MASK_BYTE1: mask ENET_MAC_ADDR1L[15:8] bits + \arg ENET_ADDRESS_MASK_BYTE2: mask ENET_MAC_ADDR1L[23:16] bits + \arg ENET_ADDRESS_MASK_BYTE3: mask ENET_MAC_ADDR1L [31:24] bits + \arg ENET_ADDRESS_MASK_BYTE4: mask ENET_MAC_ADDR1H [7:0] bits + \arg ENET_ADDRESS_MASK_BYTE5: mask ENET_MAC_ADDR1H [15:8] bits + \param[in] filter_type: select which MAC address filter type will be selected, + only one parameter can be selected which is shown as below + \arg ENET_ADDRESS_FILTER_SA: The MAC address is used to compared with the SA field of the received frame + \arg ENET_ADDRESS_FILTER_DA: The MAC address is used to compared with the DA field of the received frame + \param[out] none + \retval none +*/ +void enet_address_filter_config(enet_macaddress_enum mac_addr, uint32_t addr_mask, uint32_t filter_type) +{ + uint32_t reg; + + /* get the address filter register value which is to be configured */ + reg = REG32(ENET_ADDRH_BASE + mac_addr); + + /* clear and configure the address filter register */ + reg &= ~(ENET_MAC_ADDR1H_MB | ENET_MAC_ADDR1H_SAF); + reg |= (addr_mask | filter_type); + REG32(ENET_ADDRH_BASE + mac_addr) = reg; +} + +/*! + \brief PHY interface configuration (configure SMI clock and reset PHY chip) + \param[in] none + \param[out] none + \retval ErrStatus: SUCCESS or ERROR +*/ +ErrStatus enet_phy_config(void) +{ + uint32_t ahbclk; + uint32_t reg; + uint16_t phy_value; + ErrStatus enet_state = ERROR; + + /* clear the previous MDC clock */ + reg = ENET_MAC_PHY_CTL; + reg &= ~ENET_MAC_PHY_CTL_CLR; + + /* get the HCLK frequency */ + ahbclk = rcu_clock_freq_get(CK_AHB); + + /* configure MDC clock according to HCLK frequency range */ + if(ENET_RANGE(ahbclk, 20000000U, 35000000U)){ + reg |= ENET_MDC_HCLK_DIV16; + }else if(ENET_RANGE(ahbclk, 35000000U, 60000000U)){ + reg |= ENET_MDC_HCLK_DIV26; + }else if(ENET_RANGE(ahbclk, 60000000U, 100000000U)){ + reg |= ENET_MDC_HCLK_DIV42; + }else if((ENET_RANGE(ahbclk, 100000000U, 168000000U))||(168000000U == ahbclk)){ + reg |= ENET_MDC_HCLK_DIV62; + }else{ + return enet_state; + } + ENET_MAC_PHY_CTL = reg; + + /* reset PHY */ + phy_value = PHY_RESET; + if(ERROR == (enet_phy_write_read(ENET_PHY_WRITE, PHY_ADDRESS, PHY_REG_BCR, &phy_value))){ + return enet_state; + } + /* PHY reset need some time */ + _ENET_DELAY_(ENET_DELAY_TO); + + /* check whether PHY reset is complete */ + if(ERROR == (enet_phy_write_read(ENET_PHY_READ, PHY_ADDRESS, PHY_REG_BCR, &phy_value))){ + return enet_state; + } + + /* PHY reset complete */ + if(RESET == (phy_value & PHY_RESET)){ + enet_state = SUCCESS; + } + + return enet_state; +} + +/*! + \brief write to / read from a PHY register + \param[in] direction: only one parameter can be selected which is shown as below + \arg ENET_PHY_WRITE: write data to phy register + \arg ENET_PHY_READ: read data from phy register + \param[in] phy_address: 0x0 - 0x1F + \param[in] phy_reg: 0x0 - 0x1F + \param[in] pvalue: the value will be written to the PHY register in ENET_PHY_WRITE direction + \param[out] pvalue: the value will be read from the PHY register in ENET_PHY_READ direction + \retval ErrStatus: SUCCESS or ERROR +*/ +ErrStatus enet_phy_write_read(enet_phydirection_enum direction, uint16_t phy_address, uint16_t phy_reg, uint16_t *pvalue) +{ + uint32_t reg, phy_flag; + uint32_t timeout = 0U; + ErrStatus enet_state = ERROR; + + /* configure ENET_MAC_PHY_CTL with write/read operation */ + reg = ENET_MAC_PHY_CTL; + reg &= ~(ENET_MAC_PHY_CTL_PB | ENET_MAC_PHY_CTL_PW | ENET_MAC_PHY_CTL_PR | ENET_MAC_PHY_CTL_PA); + reg |= (direction | MAC_PHY_CTL_PR(phy_reg) | MAC_PHY_CTL_PA(phy_address) | ENET_MAC_PHY_CTL_PB); + + /* if do the write operation, write value to the register */ + if(ENET_PHY_WRITE == direction){ + ENET_MAC_PHY_DATA = *pvalue; + } + + /* do PHY write/read operation, and wait the operation complete */ + ENET_MAC_PHY_CTL = reg; + do{ + phy_flag = (ENET_MAC_PHY_CTL & ENET_MAC_PHY_CTL_PB); + timeout++; + } + while((RESET != phy_flag) && (ENET_DELAY_TO != timeout)); + + /* write/read operation complete */ + if(RESET == (ENET_MAC_PHY_CTL & ENET_MAC_PHY_CTL_PB)){ + enet_state = SUCCESS; + } + + /* if do the read operation, get value from the register */ + if(ENET_PHY_READ == direction){ + *pvalue = (uint16_t)ENET_MAC_PHY_DATA; + } + + return enet_state; +} + +/*! + \brief enable the loopback function of PHY chip + \param[in] none + \param[out] none + \retval ErrStatus: ERROR or SUCCESS +*/ +ErrStatus enet_phyloopback_enable(void) +{ + uint16_t temp_phy = 0U; + ErrStatus phy_state = ERROR; + + /* get the PHY configuration to update it */ + enet_phy_write_read(ENET_PHY_READ, PHY_ADDRESS, PHY_REG_BCR, &temp_phy); + + /* enable the PHY loopback mode */ + temp_phy |= PHY_LOOPBACK; + + /* update the PHY control register with the new configuration */ + phy_state = enet_phy_write_read(ENET_PHY_WRITE, PHY_ADDRESS, PHY_REG_BCR, &temp_phy); + + return phy_state; +} + +/*! + \brief disable the loopback function of PHY chip + \param[in] none + \param[out] none + \retval ErrStatus: ERROR or SUCCESS +*/ +ErrStatus enet_phyloopback_disable(void) +{ + uint16_t temp_phy = 0U; + ErrStatus phy_state = ERROR; + + /* get the PHY configuration to update it */ + enet_phy_write_read(ENET_PHY_READ, PHY_ADDRESS, PHY_REG_BCR, &temp_phy); + + /* disable the PHY loopback mode */ + temp_phy &= (uint16_t)~PHY_LOOPBACK; + + /* update the PHY control register with the new configuration */ + phy_state = enet_phy_write_read(ENET_PHY_WRITE, PHY_ADDRESS, PHY_REG_BCR, &temp_phy); + + return phy_state; +} + +/*! + \brief enable ENET forward feature + \param[in] feature: the feature of ENET forward mode, + one or more parameters can be selected which are shown as below + \arg ENET_AUTO_PADCRC_DROP: the function of the MAC strips the Pad/FCS field on received frames + \arg ENET_TYPEFRAME_CRC_DROP: the function that FCS field(last 4 bytes) of frame will be dropped before forwarding + \arg ENET_FORWARD_ERRFRAMES: the function that all frame received with error except runt error are forwarded to memory + \arg ENET_FORWARD_UNDERSZ_GOODFRAMES: the function that forwarding undersized good frames + \param[out] none + \retval none +*/ +void enet_forward_feature_enable(uint32_t feature) +{ + uint32_t mask; + + mask = (feature & (~(ENET_FORWARD_ERRFRAMES | ENET_FORWARD_UNDERSZ_GOODFRAMES))); + ENET_MAC_CFG |= mask; + + mask = (feature & (~(ENET_AUTO_PADCRC_DROP | ENET_TYPEFRAME_CRC_DROP))); + ENET_DMA_CTL |= (mask >> 2); +} + +/*! + \brief disable ENET forward feature + \param[in] feature: the feature of ENET forward mode, + one or more parameters can be selected which are shown as below + \arg ENET_AUTO_PADCRC_DROP: the function of the MAC strips the Pad/FCS field on received frames + \arg ENET_TYPEFRAME_CRC_DROP: the function that FCS field(last 4 bytes) of frame will be dropped before forwarding + \arg ENET_FORWARD_ERRFRAMES: the function that all frame received with error except runt error are forwarded to memory + \arg ENET_FORWARD_UNDERSZ_GOODFRAMES: the function that forwarding undersized good frames + \param[out] none + \retval none +*/ +void enet_forward_feature_disable(uint32_t feature) +{ + uint32_t mask; + + mask = (feature & (~(ENET_FORWARD_ERRFRAMES | ENET_FORWARD_UNDERSZ_GOODFRAMES))); + ENET_MAC_CFG &= ~mask; + + mask = (feature & (~(ENET_AUTO_PADCRC_DROP | ENET_TYPEFRAME_CRC_DROP))); + ENET_DMA_CTL &= ~(mask >> 2); +} + +/*! + \brief enable ENET fliter feature + \param[in] feature: the feature of ENET fliter mode, + one or more parameters can be selected which are shown as below + \arg ENET_SRC_FILTER: filter source address function + \arg ENET_SRC_FILTER_INVERSE: inverse source address filtering result function + \arg ENET_DEST_FILTER_INVERSE: inverse DA filtering result function + \arg ENET_MULTICAST_FILTER_PASS: pass all multicast frames function + \arg ENET_MULTICAST_FILTER_HASH_MODE: HASH multicast filter function + \arg ENET_UNICAST_FILTER_HASH_MODE: HASH unicast filter function + \arg ENET_FILTER_MODE_EITHER: HASH or perfect filter function + \param[out] none + \retval none +*/ +void enet_fliter_feature_enable(uint32_t feature) +{ + ENET_MAC_FRMF |= feature; +} + +/*! + \brief disable ENET fliter feature + \param[in] feature: the feature of ENET fliter mode, + one or more parameters can be selected which are shown as below + \arg ENET_SRC_FILTER: filter source address function + \arg ENET_SRC_FILTER_INVERSE: inverse source address filtering result function + \arg ENET_DEST_FILTER_INVERSE: inverse DA filtering result function + \arg ENET_MULTICAST_FILTER_PASS: pass all multicast frames function + \arg ENET_MULTICAST_FILTER_HASH_MODE: HASH multicast filter function + \arg ENET_UNICAST_FILTER_HASH_MODE: HASH unicast filter function + \arg ENET_FILTER_MODE_EITHER: HASH or perfect filter function + \param[out] none + \retval none +*/ +void enet_fliter_feature_disable(uint32_t feature) +{ + ENET_MAC_FRMF &= ~feature; +} + +/*! + \brief generate the pause frame, ENET will send pause frame after enable transmit flow control + this function only use in full-dulex mode + \param[in] none + \param[out] none + \retval ErrStatus: ERROR or SUCCESS +*/ +ErrStatus enet_pauseframe_generate(void) +{ + ErrStatus enet_state =ERROR; + uint32_t temp = 0U; + + /* in full-duplex mode, must make sure this bit is 0 before writing register */ + temp = ENET_MAC_FCTL & ENET_MAC_FCTL_FLCBBKPA; + if(RESET == temp){ + ENET_MAC_FCTL |= ENET_MAC_FCTL_FLCBBKPA; + enet_state = SUCCESS; + } + return enet_state; +} + +/*! + \brief configure the pause frame detect type + \param[in] detect: pause frame detect type, + only one parameter can be selected which is shown as below + \arg ENET_MAC0_AND_UNIQUE_ADDRESS_PAUSEDETECT: besides the unique multicast address, MAC can also + use the MAC0 address to detecting pause frame + \arg ENET_UNIQUE_PAUSEDETECT: only the unique multicast address for pause frame which is specified + in IEEE802.3 can be detected + \param[out] none + \retval none +*/ +void enet_pauseframe_detect_config(uint32_t detect) +{ + ENET_MAC_FCTL &= ~ENET_MAC_FCTL_UPFDT; + ENET_MAC_FCTL |= detect; +} + +/*! + \brief configure the pause frame parameters + \param[in] pausetime: pause time in transmit pause control frame + \param[in] pause_threshold: the threshold of the pause timer for retransmitting frames automatically, + this value must make sure to be less than configured pause time, only one parameter can be + selected which is shown as below + \arg ENET_PAUSETIME_MINUS4: pause time minus 4 slot times + \arg ENET_PAUSETIME_MINUS28: pause time minus 28 slot times + \arg ENET_PAUSETIME_MINUS144: pause time minus 144 slot times + \arg ENET_PAUSETIME_MINUS256: pause time minus 256 slot times + \param[out] none + \retval none +*/ +void enet_pauseframe_config(uint32_t pausetime, uint32_t pause_threshold) +{ + ENET_MAC_FCTL &= ~(ENET_MAC_FCTL_PTM | ENET_MAC_FCTL_PLTS); + ENET_MAC_FCTL |= (MAC_FCTL_PTM(pausetime) | pause_threshold); +} + +/*! + \brief configure the threshold of the flow control(deactive and active threshold) + \param[in] deactive: the threshold of the deactive flow control, this value + should always be less than active flow control value, only one + parameter can be selected which is shown as below + \arg ENET_DEACTIVE_THRESHOLD_256BYTES: threshold level is 256 bytes + \arg ENET_DEACTIVE_THRESHOLD_512BYTES: threshold level is 512 bytes + \arg ENET_DEACTIVE_THRESHOLD_768BYTES: threshold level is 768 bytes + \arg ENET_DEACTIVE_THRESHOLD_1024BYTES: threshold level is 1024 bytes + \arg ENET_DEACTIVE_THRESHOLD_1280BYTES: threshold level is 1280 bytes + \arg ENET_DEACTIVE_THRESHOLD_1536BYTES: threshold level is 1536 bytes + \arg ENET_DEACTIVE_THRESHOLD_1792BYTES: threshold level is 1792 bytes + \param[in] active: the threshold of the active flow control, only one parameter + can be selected which is shown as below + \arg ENET_ACTIVE_THRESHOLD_256BYTES: threshold level is 256 bytes + \arg ENET_ACTIVE_THRESHOLD_512BYTES: threshold level is 512 bytes + \arg ENET_ACTIVE_THRESHOLD_768BYTES: threshold level is 768 bytes + \arg ENET_ACTIVE_THRESHOLD_1024BYTES: threshold level is 1024 bytes + \arg ENET_ACTIVE_THRESHOLD_1280BYTES: threshold level is 1280 bytes + \arg ENET_ACTIVE_THRESHOLD_1536BYTES: threshold level is 1536 bytes + \arg ENET_ACTIVE_THRESHOLD_1792BYTES: threshold level is 1792 bytes + \param[out] none + \retval none +*/ +void enet_flowcontrol_threshold_config(uint32_t deactive, uint32_t active) +{ + ENET_MAC_FCTH = ((deactive | active) >> 8); +} + +/*! + \brief enable ENET flow control feature + \param[in] feature: the feature of ENET flow control mode + one or more parameters can be selected which are shown as below + \arg ENET_ZERO_QUANTA_PAUSE: the automatic zero-quanta generation function + \arg ENET_TX_FLOWCONTROL: the flow control operation in the MAC + \arg ENET_RX_FLOWCONTROL: decoding function for the received pause frame and process it + \arg ENET_BACK_PRESSURE: back pressure operation in the MAC(only use in half-dulex mode) + \param[out] none + \retval none +*/ +void enet_flowcontrol_feature_enable(uint32_t feature) +{ + if(RESET != (feature & ENET_ZERO_QUANTA_PAUSE)){ + ENET_MAC_FCTL &= ~ENET_ZERO_QUANTA_PAUSE; + } + feature &= ~ENET_ZERO_QUANTA_PAUSE; + ENET_MAC_FCTL |= feature; +} + +/*! + \brief disable ENET flow control feature + \param[in] feature: the feature of ENET flow control mode + one or more parameters can be selected which are shown as below + \arg ENET_ZERO_QUANTA_PAUSE: the automatic zero-quanta generation function + \arg ENET_TX_FLOWCONTROL: the flow control operation in the MAC + \arg ENET_RX_FLOWCONTROL: decoding function for the received pause frame and process it + \arg ENET_BACK_PRESSURE: back pressure operation in the MAC(only use in half-dulex mode) + \param[out] none + \retval none +*/ +void enet_flowcontrol_feature_disable(uint32_t feature) +{ + if(RESET != (feature & ENET_ZERO_QUANTA_PAUSE)){ + ENET_MAC_FCTL |= ENET_ZERO_QUANTA_PAUSE; + } + feature &= ~ENET_ZERO_QUANTA_PAUSE; + ENET_MAC_FCTL &= ~feature; +} + +/*! + \brief get the dma transmit/receive process state + \param[in] direction: choose the direction of dma process which users want to check, + refer to enet_dmadirection_enum, only one parameter can be selected which is shown as below + \arg ENET_DMA_TX: dma transmit process + \arg ENET_DMA_RX: dma receive process + \param[out] none + \retval state of dma process, the value range shows below: + ENET_RX_STATE_STOPPED, ENET_RX_STATE_FETCHING, ENET_RX_STATE_WAITING, + ENET_RX_STATE_SUSPENDED, ENET_RX_STATE_CLOSING, ENET_RX_STATE_QUEUING, + ENET_TX_STATE_STOPPED, ENET_TX_STATE_FETCHING, ENET_TX_STATE_WAITING, + ENET_TX_STATE_READING, ENET_TX_STATE_SUSPENDED, ENET_TX_STATE_CLOSING +*/ +uint32_t enet_dmaprocess_state_get(enet_dmadirection_enum direction) +{ + uint32_t reval; + reval = (uint32_t)(ENET_DMA_STAT & (uint32_t)direction); + return reval; +} + +/*! + \brief poll the DMA transmission/reception enable by writing any value to the + ENET_DMA_TPEN/ENET_DMA_RPEN register, this will make the DMA to resume transmission/reception + \param[in] direction: choose the direction of DMA process which users want to resume, + refer to enet_dmadirection_enum, only one parameter can be selected which is shown as below + \arg ENET_DMA_TX: DMA transmit process + \arg ENET_DMA_RX: DMA receive process + \param[out] none + \retval none +*/ +void enet_dmaprocess_resume(enet_dmadirection_enum direction) +{ + if(ENET_DMA_TX == direction){ + ENET_DMA_TPEN = 0U; + }else{ + ENET_DMA_RPEN = 0U; + } +} + +/*! + \brief check and recover the Rx process + \param[in] none + \param[out] none + \retval none +*/ +void enet_rxprocess_check_recovery(void) +{ + uint32_t status; + + /* get DAV information of current RxDMA descriptor */ + status = dma_current_rxdesc->status; + status &= ENET_RDES0_DAV; + + /* if current descriptor is owned by DMA, but the descriptor address mismatches with + receive descriptor address pointer updated by RxDMA controller */ + if((ENET_DMA_CRDADDR != ((uint32_t)dma_current_rxdesc)) && + (ENET_RDES0_DAV == status)){ + dma_current_rxdesc = (enet_descriptors_struct*)ENET_DMA_CRDADDR; + } +} + +/*! + \brief flush the ENET transmit FIFO, and wait until the flush operation completes + \param[in] none + \param[out] none + \retval ErrStatus: ERROR or SUCCESS +*/ +ErrStatus enet_txfifo_flush(void) +{ + uint32_t flush_state; + uint32_t timeout = 0U; + ErrStatus enet_state = ERROR; + + /* set the FTF bit for flushing transmit FIFO */ + ENET_DMA_CTL |= ENET_DMA_CTL_FTF; + /* wait until the flush operation completes */ + do{ + flush_state = ENET_DMA_CTL & ENET_DMA_CTL_FTF; + timeout++; + }while((RESET != flush_state) && (timeout < ENET_DELAY_TO)); + /* return ERROR due to timeout */ + if(RESET == flush_state){ + enet_state = SUCCESS; + } + + return enet_state; +} + +/*! + \brief get the transmit/receive address of current descriptor, or current buffer, or descriptor table + \param[in] addr_get: choose the address which users want to get, refer to enet_desc_reg_enum, + only one parameter can be selected which is shown as below + \arg ENET_RX_DESC_TABLE: the start address of the receive descriptor table + \arg ENET_RX_CURRENT_DESC: the start descriptor address of the current receive descriptor read by + the RxDMA controller + \arg ENET_RX_CURRENT_BUFFER: the current receive buffer address being read by the RxDMA controller + \arg ENET_TX_DESC_TABLE: the start address of the transmit descriptor table + \arg ENET_TX_CURRENT_DESC: the start descriptor address of the current transmit descriptor read by + the TxDMA controller + \arg ENET_TX_CURRENT_BUFFER: the current transmit buffer address being read by the TxDMA controller + \param[out] none + \retval address value +*/ +uint32_t enet_current_desc_address_get(enet_desc_reg_enum addr_get) +{ + uint32_t reval = 0U; + + reval = REG32((ENET) +(uint32_t)addr_get); + return reval; +} + +/*! + \brief get the Tx or Rx descriptor information + \param[in] desc: the descriptor pointer which users want to get information + \param[in] info_get: the descriptor information type which is selected, + only one parameter can be selected which is shown as below + \arg RXDESC_BUFFER_1_SIZE: receive buffer 1 size + \arg RXDESC_BUFFER_2_SIZE: receive buffer 2 size + \arg RXDESC_FRAME_LENGTH: the byte length of the received frame that was transferred to the buffer + \arg TXDESC_COLLISION_COUNT: the number of collisions occurred before the frame was transmitted + \arg RXDESC_BUFFER_1_ADDR: the buffer1 address of the Rx frame + \arg TXDESC_BUFFER_1_ADDR: the buffer1 address of the Tx frame + \param[out] none + \retval descriptor information, if value is 0xFFFFFFFFU, means the false input parameter +*/ +uint32_t enet_desc_information_get(enet_descriptors_struct *desc, enet_descstate_enum info_get) +{ + uint32_t reval = 0xFFFFFFFFU; + + switch(info_get){ + case RXDESC_BUFFER_1_SIZE: + reval = GET_RDES1_RB1S(desc->control_buffer_size); + break; + case RXDESC_BUFFER_2_SIZE: + reval = GET_RDES1_RB2S(desc->control_buffer_size); + break; + case RXDESC_FRAME_LENGTH: + reval = GET_RDES0_FRML(desc->status); + if(reval > 4U){ + reval = reval - 4U; + + /* if is a type frame, and CRC is not included in forwarding frame */ + if((RESET != (ENET_MAC_CFG & ENET_MAC_CFG_TFCD)) && (RESET != (desc->status & ENET_RDES0_FRMT))){ + reval = reval + 4U; + } + }else{ + reval = 0U; + } + + break; + case RXDESC_BUFFER_1_ADDR: + reval = desc->buffer1_addr; + break; + case TXDESC_BUFFER_1_ADDR: + reval = desc->buffer1_addr; + break; + case TXDESC_COLLISION_COUNT: + reval = GET_TDES0_COCNT(desc->status); + break; + default: + break; + } + return reval; +} + +/*! + \brief get the number of missed frames during receiving + \param[in] none + \param[out] rxfifo_drop: pointer to the number of frames dropped by RxFIFO + \param[out] rxdma_drop: pointer to the number of frames missed by the RxDMA controller + \retval none +*/ +void enet_missed_frame_counter_get(uint32_t *rxfifo_drop, uint32_t *rxdma_drop) +{ + uint32_t temp_counter = 0U; + + temp_counter = ENET_DMA_MFBOCNT; + *rxfifo_drop = GET_DMA_MFBOCNT_MSFA(temp_counter); + *rxdma_drop = GET_DMA_MFBOCNT_MSFC(temp_counter); +} + +/*! + \brief get the bit flag of ENET DMA descriptor + \param[in] desc: the descriptor pointer which users want to get flag + \param[in] desc_flag: the bit flag of ENET DMA descriptor, + only one parameter can be selected which is shown as below + \arg ENET_TDES0_DB: deferred + \arg ENET_TDES0_UFE: underflow error + \arg ENET_TDES0_EXD: excessive deferral + \arg ENET_TDES0_VFRM: VLAN frame + \arg ENET_TDES0_ECO: excessive collision + \arg ENET_TDES0_LCO: late collision + \arg ENET_TDES0_NCA: no carrier + \arg ENET_TDES0_LCA: loss of carrier + \arg ENET_TDES0_IPPE: IP payload error + \arg ENET_TDES0_FRMF: frame flushed + \arg ENET_TDES0_JT: jabber timeout + \arg ENET_TDES0_ES: error summary + \arg ENET_TDES0_IPHE: IP header error + \arg ENET_TDES0_TTMSS: transmit timestamp status + \arg ENET_TDES0_TCHM: the second address chained mode + \arg ENET_TDES0_TERM: transmit end of ring mode + \arg ENET_TDES0_TTSEN: transmit timestamp function enable + \arg ENET_TDES0_DPAD: disable adding pad + \arg ENET_TDES0_DCRC: disable CRC + \arg ENET_TDES0_FSG: first segment + \arg ENET_TDES0_LSG: last segment + \arg ENET_TDES0_INTC: interrupt on completion + \arg ENET_TDES0_DAV: DAV bit + + \arg ENET_RDES0_PCERR: payload checksum error + \arg ENET_RDES0_EXSV: extended status valid + \arg ENET_RDES0_CERR: CRC error + \arg ENET_RDES0_DBERR: dribble bit error + \arg ENET_RDES0_RERR: receive error + \arg ENET_RDES0_RWDT: receive watchdog timeout + \arg ENET_RDES0_FRMT: frame type + \arg ENET_RDES0_LCO: late collision + \arg ENET_RDES0_IPHERR: IP frame header error + \arg ENET_RDES0_TSV: timestamp valid + \arg ENET_RDES0_LDES: last descriptor + \arg ENET_RDES0_FDES: first descriptor + \arg ENET_RDES0_VTAG: VLAN tag + \arg ENET_RDES0_OERR: overflow error + \arg ENET_RDES0_LERR: length error + \arg ENET_RDES0_SAFF: SA filter fail + \arg ENET_RDES0_DERR: descriptor error + \arg ENET_RDES0_ERRS: error summary + \arg ENET_RDES0_DAFF: destination address filter fail + \arg ENET_RDES0_DAV: descriptor available + \param[out] none + \retval FlagStatus: SET or RESET +*/ +FlagStatus enet_desc_flag_get(enet_descriptors_struct *desc, uint32_t desc_flag) +{ + FlagStatus enet_flag = RESET; + + if((uint32_t)RESET != (desc->status & desc_flag)){ + enet_flag = SET; + } + + return enet_flag; +} + +/*! + \brief set the bit flag of ENET DMA descriptor + \param[in] desc: the descriptor pointer which users want to set flag + \param[in] desc_flag: the bit flag of ENET DMA descriptor, + only one parameter can be selected which is shown as below + \arg ENET_TDES0_VFRM: VLAN frame + \arg ENET_TDES0_FRMF: frame flushed + \arg ENET_TDES0_TCHM: the second address chained mode + \arg ENET_TDES0_TERM: transmit end of ring mode + \arg ENET_TDES0_TTSEN: transmit timestamp function enable + \arg ENET_TDES0_DPAD: disable adding pad + \arg ENET_TDES0_DCRC: disable CRC + \arg ENET_TDES0_FSG: first segment + \arg ENET_TDES0_LSG: last segment + \arg ENET_TDES0_INTC: interrupt on completion + \arg ENET_TDES0_DAV: DAV bit + \arg ENET_RDES0_DAV: descriptor available + \param[out] none + \retval none +*/ +void enet_desc_flag_set(enet_descriptors_struct *desc, uint32_t desc_flag) +{ + desc->status |= desc_flag; +} + +/*! + \brief clear the bit flag of ENET DMA descriptor + \param[in] desc: the descriptor pointer which users want to clear flag + \param[in] desc_flag: the bit flag of ENET DMA descriptor, + only one parameter can be selected which is shown as below + \arg ENET_TDES0_VFRM: VLAN frame + \arg ENET_TDES0_FRMF: frame flushed + \arg ENET_TDES0_TCHM: the second address chained mode + \arg ENET_TDES0_TERM: transmit end of ring mode + \arg ENET_TDES0_TTSEN: transmit timestamp function enable + \arg ENET_TDES0_DPAD: disable adding pad + \arg ENET_TDES0_DCRC: disable CRC + \arg ENET_TDES0_FSG: first segment + \arg ENET_TDES0_LSG: last segment + \arg ENET_TDES0_INTC: interrupt on completion + \arg ENET_TDES0_DAV: DAV bit + \arg ENET_RDES0_DAV: descriptor available + \param[out] none + \retval none +*/ +void enet_desc_flag_clear(enet_descriptors_struct *desc, uint32_t desc_flag) +{ + desc->status &= ~desc_flag; +} + +/*! + \brief when receiving completed, set RS bit in ENET_DMA_STAT register will immediately set + \param[in] desc: the descriptor pointer which users want to configure + \param[out] none + \retval none +*/ +void enet_rx_desc_immediate_receive_complete_interrupt(enet_descriptors_struct *desc) +{ + desc->control_buffer_size &= ~ENET_RDES1_DINTC; +} + +/*! + \brief when receiving completed, set RS bit in ENET_DMA_STAT register will is set after a configurable delay time + \param[in] desc: the descriptor pointer which users want to configure + \param[in] delay_time: delay a time of 256*delay_time HCLK, this value must be between 0 and 0xFF + \param[out] none + \retval none +*/ +void enet_rx_desc_delay_receive_complete_interrupt(enet_descriptors_struct *desc, uint32_t delay_time) +{ + desc->control_buffer_size |= ENET_RDES1_DINTC; + ENET_DMA_RSWDC = DMA_RSWDC_WDCFRS(delay_time); +} + +/*! + \brief drop current receive frame + \param[in] none + \param[out] none + \retval none +*/ +void enet_rxframe_drop(void) +{ + /* enable reception, descriptor is owned by DMA */ + dma_current_rxdesc->status = ENET_RDES0_DAV; + + /* chained mode */ + if((uint32_t)RESET != (dma_current_rxdesc->control_buffer_size & ENET_RDES1_RCHM)){ + if(NULL != dma_current_ptp_rxdesc){ + dma_current_rxdesc = (enet_descriptors_struct*) (dma_current_ptp_rxdesc->buffer2_next_desc_addr); + /* if it is the last ptp descriptor */ + if(0U != dma_current_ptp_rxdesc->status){ + /* pointer back to the first ptp descriptor address in the desc_ptptab list address */ + dma_current_ptp_rxdesc = (enet_descriptors_struct*) (dma_current_ptp_rxdesc->status); + }else{ + /* ponter to the next ptp descriptor */ + dma_current_ptp_rxdesc++; + } + }else{ + dma_current_rxdesc = (enet_descriptors_struct*) (dma_current_rxdesc->buffer2_next_desc_addr); + } + + }else{ + /* ring mode */ + if((uint32_t)RESET != (dma_current_rxdesc->control_buffer_size & ENET_RDES1_RERM)){ + /* if is the last descriptor in table, the next descriptor is the table header */ + dma_current_rxdesc = (enet_descriptors_struct*) (ENET_DMA_RDTADDR); + if(NULL != dma_current_ptp_rxdesc){ + dma_current_ptp_rxdesc = (enet_descriptors_struct*) (dma_current_ptp_rxdesc->status); + } + }else{ + /* the next descriptor is the current address, add the descriptor size, and descriptor skip length */ + dma_current_rxdesc = (enet_descriptors_struct*) (uint32_t)((uint32_t)dma_current_rxdesc + ETH_DMARXDESC_SIZE + GET_DMA_BCTL_DPSL(ENET_DMA_BCTL)); + if(NULL != dma_current_ptp_rxdesc){ + dma_current_ptp_rxdesc++; + } + } + } +} + +/*! + \brief enable DMA feature + \param[in] feature: the feature of DMA mode, + one or more parameters can be selected which are shown as below + \arg ENET_NO_FLUSH_RXFRAME: RxDMA does not flushes frames function + \arg ENET_SECONDFRAME_OPT: TxDMA controller operate on second frame function + \param[out] none + \retval none +*/ +void enet_dma_feature_enable(uint32_t feature) +{ + ENET_DMA_CTL |= feature; +} + +/*! + \brief disable DMA feature + \param[in] feature: the feature of DMA mode, + one or more parameters can be selected which are shown as below + \arg ENET_NO_FLUSH_RXFRAME: RxDMA does not flushes frames function + \arg ENET_SECONDFRAME_OPT: TxDMA controller operate on second frame function + \param[out] none + \retval none +*/ +void enet_dma_feature_disable(uint32_t feature) +{ + ENET_DMA_CTL &= ~feature; +} + +#ifdef SELECT_DESCRIPTORS_ENHANCED_MODE +/*! + \brief get the bit of extended status flag in ENET DMA descriptor + \param[in] desc: the descriptor pointer which users want to get the extended status flag + \param[in] desc_status: the extended status want to get, + only one parameter can be selected which is shown as below + \arg ENET_RDES4_IPPLDT: IP frame payload type + \arg ENET_RDES4_IPHERR: IP frame header error + \arg ENET_RDES4_IPPLDERR: IP frame payload error + \arg ENET_RDES4_IPCKSB: IP frame checksum bypassed + \arg ENET_RDES4_IPF4: IP frame in version 4 + \arg ENET_RDES4_IPF6: IP frame in version 6 + \arg ENET_RDES4_PTPMT: PTP message type + \arg ENET_RDES4_PTPOEF: PTP on ethernet frame + \arg ENET_RDES4_PTPVF: PTP version format + \param[out] none + \retval value of extended status +*/ +uint32_t enet_rx_desc_enhanced_status_get(enet_descriptors_struct *desc, uint32_t desc_status) +{ + uint32_t reval = 0xFFFFFFFFU; + + switch (desc_status){ + case ENET_RDES4_IPPLDT: + reval = GET_RDES4_IPPLDT(desc->extended_status); + break; + case ENET_RDES4_PTPMT: + reval = GET_RDES4_PTPMT(desc->extended_status); + break; + default: + if ((uint32_t)RESET != (desc->extended_status & desc_status)){ + reval = 1U; + }else{ + reval = 0U; + } + } + + return reval; +} + +/*! + \brief configure descriptor to work in enhanced mode + \param[in] none + \param[out] none + \retval none +*/ +void enet_desc_select_enhanced_mode(void) +{ + ENET_DMA_BCTL |= ENET_DMA_BCTL_DFM; +} + +/*! + \brief initialize the DMA Tx/Rx descriptors's parameters in enhanced chain mode with ptp function + \param[in] direction: the descriptors which users want to init, refer to enet_dmadirection_enum, + only one parameter can be selected which is shown as below + \arg ENET_DMA_TX: DMA Tx descriptors + \arg ENET_DMA_RX: DMA Rx descriptors + \param[out] none + \retval none +*/ +void enet_ptp_enhanced_descriptors_chain_init(enet_dmadirection_enum direction) +{ + uint32_t num = 0U, count = 0U, maxsize = 0U; + uint32_t desc_status = 0U, desc_bufsize = 0U; + enet_descriptors_struct *desc, *desc_tab; + uint8_t *buf; + + /* if want to initialize DMA Tx descriptors */ + if (ENET_DMA_TX == direction){ + /* save a copy of the DMA Tx descriptors */ + desc_tab = txdesc_tab; + buf = &tx_buff[0][0]; + count = ENET_TXBUF_NUM; + maxsize = ENET_TXBUF_SIZE; + + /* select chain mode, and enable transmit timestamp function */ + desc_status = ENET_TDES0_TCHM | ENET_TDES0_TTSEN; + + /* configure DMA Tx descriptor table address register */ + ENET_DMA_TDTADDR = (uint32_t)desc_tab; + dma_current_txdesc = desc_tab; + }else{ + /* if want to initialize DMA Rx descriptors */ + /* save a copy of the DMA Rx descriptors */ + desc_tab = rxdesc_tab; + buf = &rx_buff[0][0]; + count = ENET_RXBUF_NUM; + maxsize = ENET_RXBUF_SIZE; + + /* enable receiving */ + desc_status = ENET_RDES0_DAV; + /* select receive chained mode and set buffer1 size */ + desc_bufsize = ENET_RDES1_RCHM | (uint32_t)ENET_RXBUF_SIZE; + + /* configure DMA Rx descriptor table address register */ + ENET_DMA_RDTADDR = (uint32_t)desc_tab; + dma_current_rxdesc = desc_tab; + } + + /* configuration each descriptor */ + for(num = 0U; num < count; num++){ + /* get the pointer to the next descriptor of the descriptor table */ + desc = desc_tab + num; + + /* configure descriptors */ + desc->status = desc_status; + desc->control_buffer_size = desc_bufsize; + desc->buffer1_addr = (uint32_t)(&buf[num * maxsize]); + + /* if is not the last descriptor */ + if(num < (count - 1U)){ + /* configure the next descriptor address */ + desc->buffer2_next_desc_addr = (uint32_t)(desc_tab + num + 1U); + }else{ + /* when it is the last descriptor, the next descriptor address + equals to first descriptor address in descriptor table */ + desc->buffer2_next_desc_addr = (uint32_t)desc_tab; + } + } +} + +/*! + \brief initialize the DMA Tx/Rx descriptors's parameters in enhanced ring mode with ptp function + \param[in] direction: the descriptors which users want to init, refer to enet_dmadirection_enum, + only one parameter can be selected which is shown as below + \arg ENET_DMA_TX: DMA Tx descriptors + \arg ENET_DMA_RX: DMA Rx descriptors + \param[out] none + \retval none +*/ +void enet_ptp_enhanced_descriptors_ring_init(enet_dmadirection_enum direction) +{ + uint32_t num = 0U, count = 0U, maxsize = 0U; + uint32_t desc_status = 0U, desc_bufsize = 0U; + enet_descriptors_struct *desc; + enet_descriptors_struct *desc_tab; + uint8_t *buf; + + /* configure descriptor skip length */ + ENET_DMA_BCTL &= ~ENET_DMA_BCTL_DPSL; + ENET_DMA_BCTL |= DMA_BCTL_DPSL(0); + + /* if want to initialize DMA Tx descriptors */ + if (ENET_DMA_TX == direction){ + /* save a copy of the DMA Tx descriptors */ + desc_tab = txdesc_tab; + buf = &tx_buff[0][0]; + count = ENET_TXBUF_NUM; + maxsize = ENET_TXBUF_SIZE; + + /* select ring mode, and enable transmit timestamp function */ + desc_status = ENET_TDES0_TTSEN; + + /* configure DMA Tx descriptor table address register */ + ENET_DMA_TDTADDR = (uint32_t)desc_tab; + dma_current_txdesc = desc_tab; + }else{ + /* if want to initialize DMA Rx descriptors */ + /* save a copy of the DMA Rx descriptors */ + desc_tab = rxdesc_tab; + buf = &rx_buff[0][0]; + count = ENET_RXBUF_NUM; + maxsize = ENET_RXBUF_SIZE; + + /* enable receiving */ + desc_status = ENET_RDES0_DAV; + /* set buffer1 size */ + desc_bufsize = ENET_RXBUF_SIZE; + + /* configure DMA Rx descriptor table address register */ + ENET_DMA_RDTADDR = (uint32_t)desc_tab; + dma_current_rxdesc = desc_tab; + } + + /* configure each descriptor */ + for(num=0U; num < count; num++){ + /* get the pointer to the next descriptor of the descriptor table */ + desc = desc_tab + num; + + /* configure descriptors */ + desc->status = desc_status; + desc->control_buffer_size = desc_bufsize; + desc->buffer1_addr = (uint32_t)(&buf[num * maxsize]); + + /* when it is the last descriptor */ + if(num == (count - 1U)){ + if (ENET_DMA_TX == direction){ + /* configure transmit end of ring mode */ + desc->status |= ENET_TDES0_TERM; + }else{ + /* configure receive end of ring mode */ + desc->control_buffer_size |= ENET_RDES1_RERM; + } + } + } +} + +/*! + \brief receive a packet data with timestamp values to application buffer, when the DMA is in enhanced mode + \param[in] bufsize: the size of buffer which is the parameter in function + \param[out] buffer: pointer to the application buffer + note -- if the input is NULL, user should copy data in application by himself + \param[out] timestamp: pointer to the table which stores the timestamp high and low + note -- if the input is NULL, timestamp is ignored + \retval ErrStatus: SUCCESS or ERROR +*/ +ErrStatus enet_ptpframe_receive_enhanced_mode(uint8_t *buffer, uint32_t bufsize, uint32_t timestamp[]) +{ + uint32_t offset = 0U, size = 0U; + uint32_t timeout = 0U; + uint32_t rdes0_tsv_flag; + + /* the descriptor is busy due to own by the DMA */ + if((uint32_t)RESET != (dma_current_rxdesc->status & ENET_RDES0_DAV)){ + return ERROR; + } + + /* if buffer pointer is null, indicates that users has copied data in application */ + if(NULL != buffer){ + /* if no error occurs, and the frame uses only one descriptor */ + if(((uint32_t)RESET == (dma_current_rxdesc->status & ENET_RDES0_ERRS)) && + ((uint32_t)RESET != (dma_current_rxdesc->status & ENET_RDES0_LDES)) && + ((uint32_t)RESET != (dma_current_rxdesc->status & ENET_RDES0_FDES))){ + /* get the frame length except CRC */ + size = GET_RDES0_FRML(dma_current_rxdesc->status) - 4U; + + /* if is a type frame, and CRC is not included in forwarding frame */ + if((RESET != (ENET_MAC_CFG & ENET_MAC_CFG_TFCD)) && (RESET != (dma_current_rxdesc->status & ENET_RDES0_FRMT))){ + size = size + 4U; + } + + /* to avoid situation that the frame size exceeds the buffer length */ + if(size > bufsize){ + return ERROR; + } + + /* copy data from Rx buffer to application buffer */ + for(offset = 0; offset < size; offset++){ + (*(buffer + offset)) = (*(__IO uint8_t *)((dma_current_rxdesc->buffer1_addr) + offset)); + } + }else{ + return ERROR; + } + } + + /* if timestamp pointer is null, indicates that users don't care timestamp in application */ + if(NULL != timestamp){ + /* wait for ENET_RDES0_TSV flag to be set, the timestamp value is taken and + write to the RDES6 and RDES7 */ + do{ + rdes0_tsv_flag = (dma_current_rxdesc->status & ENET_RDES0_TSV); + timeout++; + }while ((RESET == rdes0_tsv_flag) && (timeout < ENET_DELAY_TO)); + + /* return ERROR due to timeout */ + if(ENET_DELAY_TO == timeout){ + return ERROR; + } + + /* clear the ENET_RDES0_TSV flag */ + dma_current_rxdesc->status &= ~ENET_RDES0_TSV; + /* get the timestamp value of the received frame */ + timestamp[0] = dma_current_rxdesc->timestamp_low; + timestamp[1] = dma_current_rxdesc->timestamp_high; + } + + /* enable reception, descriptor is owned by DMA */ + dma_current_rxdesc->status = ENET_RDES0_DAV; + + /* check Rx buffer unavailable flag status */ + if ((uint32_t)RESET != (ENET_DMA_STAT & ENET_DMA_STAT_RBU)){ + /* Clear RBU flag */ + ENET_DMA_STAT = ENET_DMA_STAT_RBU; + /* resume DMA reception by writing to the RPEN register*/ + ENET_DMA_RPEN = 0; + } + + /* update the current RxDMA descriptor pointer to the next decriptor in RxDMA decriptor table */ + /* chained mode */ + if((uint32_t)RESET != (dma_current_rxdesc->control_buffer_size & ENET_RDES1_RCHM)){ + dma_current_rxdesc = (enet_descriptors_struct*) (dma_current_rxdesc->buffer2_next_desc_addr); + }else{ + /* ring mode */ + if((uint32_t)RESET != (dma_current_rxdesc->control_buffer_size & ENET_RDES1_RERM)){ + /* if is the last descriptor in table, the next descriptor is the table header */ + dma_current_rxdesc = (enet_descriptors_struct*) (ENET_DMA_RDTADDR); + }else{ + /* the next descriptor is the current address, add the descriptor size, and descriptor skip length */ + dma_current_rxdesc = (enet_descriptors_struct*) ((uint32_t)dma_current_rxdesc + ETH_DMARXDESC_SIZE + GET_DMA_BCTL_DPSL(ENET_DMA_BCTL)); + } + } + + return SUCCESS; +} + +/*! + \brief send data with timestamp values in application buffer as a transmit packet, when the DMA is in enhanced mode + \param[in] buffer: pointer on the application buffer + note -- if the input is NULL, user should copy data in application by himself + \param[in] length: the length of frame data to be transmitted + \param[out] timestamp: pointer to the table which stores the timestamp high and low + note -- if the input is NULL, timestamp is ignored + \param[out] none + \retval ErrStatus: SUCCESS or ERROR +*/ +ErrStatus enet_ptpframe_transmit_enhanced_mode(uint8_t *buffer, uint32_t length, uint32_t timestamp[]) +{ + uint32_t offset = 0; + uint32_t dma_tbu_flag, dma_tu_flag; + uint32_t tdes0_ttmss_flag; + uint32_t timeout = 0; + + /* the descriptor is busy due to own by the DMA */ + if((uint32_t)RESET != (dma_current_txdesc->status & ENET_TDES0_DAV)){ + return ERROR; + } + + /* only frame length no more than ENET_MAX_FRAME_SIZE is allowed */ + if(length > ENET_MAX_FRAME_SIZE){ + return ERROR; + } + + /* if buffer pointer is null, indicates that users has handled data in application */ + if(NULL != buffer){ + /* copy frame data from application buffer to Tx buffer */ + for(offset = 0; offset < length; offset++){ + (*(__IO uint8_t *)((dma_current_txdesc->buffer1_addr) + offset)) = (*(buffer + offset)); + } + } + /* set the frame length */ + dma_current_txdesc->control_buffer_size = length; + /* set the segment of frame, frame is transmitted in one descriptor */ + dma_current_txdesc->status |= ENET_TDES0_LSG | ENET_TDES0_FSG; + /* enable the DMA transmission */ + dma_current_txdesc->status |= ENET_TDES0_DAV; + + /* check Tx buffer unavailable flag status */ + dma_tbu_flag = (ENET_DMA_STAT & ENET_DMA_STAT_TBU); + dma_tu_flag = (ENET_DMA_STAT & ENET_DMA_STAT_TU); + + if ((RESET != dma_tbu_flag) || (RESET != dma_tu_flag)){ + /* Clear TBU and TU flag */ + ENET_DMA_STAT = (dma_tbu_flag | dma_tu_flag); + /* resume DMA transmission by writing to the TPEN register*/ + ENET_DMA_TPEN = 0; + } + + /* if timestamp pointer is null, indicates that users don't care timestamp in application */ + if(NULL != timestamp){ + /* wait for ENET_TDES0_TTMSS flag to be set, a timestamp was captured */ + do{ + tdes0_ttmss_flag = (dma_current_txdesc->status & ENET_TDES0_TTMSS); + timeout++; + }while((RESET == tdes0_ttmss_flag) && (timeout < ENET_DELAY_TO)); + + /* return ERROR due to timeout */ + if(ENET_DELAY_TO == timeout){ + return ERROR; + } + + /* clear the ENET_TDES0_TTMSS flag */ + dma_current_txdesc->status &= ~ENET_TDES0_TTMSS; + /* get the timestamp value of the transmit frame */ + timestamp[0] = dma_current_txdesc->timestamp_low; + timestamp[1] = dma_current_txdesc->timestamp_high; + } + + /* update the current TxDMA descriptor pointer to the next decriptor in TxDMA decriptor table*/ + /* chained mode */ + if((uint32_t)RESET != (dma_current_txdesc->status & ENET_TDES0_TCHM)){ + dma_current_txdesc = (enet_descriptors_struct*) (dma_current_txdesc->buffer2_next_desc_addr); + }else{ + /* ring mode */ + if((uint32_t)RESET != (dma_current_txdesc->status & ENET_TDES0_TERM)){ + /* if is the last descriptor in table, the next descriptor is the table header */ + dma_current_txdesc = (enet_descriptors_struct*) (ENET_DMA_TDTADDR); + }else{ + /* the next descriptor is the current address, add the descriptor size, and descriptor skip length */ + dma_current_txdesc = (enet_descriptors_struct*) ((uint32_t)dma_current_txdesc + ETH_DMATXDESC_SIZE + GET_DMA_BCTL_DPSL(ENET_DMA_BCTL)); + } + } + + return SUCCESS; +} + +#else + +/*! + \brief configure descriptor to work in normal mode + \param[in] none + \param[out] none + \retval none +*/ +void enet_desc_select_normal_mode(void) +{ + ENET_DMA_BCTL &= ~ENET_DMA_BCTL_DFM; +} + +/*! + \brief initialize the DMA Tx/Rx descriptors's parameters in normal chain mode with PTP function + \param[in] direction: the descriptors which users want to init, refer to enet_dmadirection_enum, + only one parameter can be selected which is shown as below + \arg ENET_DMA_TX: DMA Tx descriptors + \arg ENET_DMA_RX: DMA Rx descriptors + \param[in] desc_ptptab: pointer to the first descriptor address of PTP Rx descriptor table + \param[out] none + \retval none +*/ +void enet_ptp_normal_descriptors_chain_init(enet_dmadirection_enum direction, enet_descriptors_struct *desc_ptptab) +{ + uint32_t num = 0U, count = 0U, maxsize = 0U; + uint32_t desc_status = 0U, desc_bufsize = 0U; + enet_descriptors_struct *desc, *desc_tab; + uint8_t *buf; + + /* if want to initialize DMA Tx descriptors */ + if(ENET_DMA_TX == direction){ + /* save a copy of the DMA Tx descriptors */ + desc_tab = txdesc_tab; + buf = &tx_buff[0][0]; + count = ENET_TXBUF_NUM; + maxsize = ENET_TXBUF_SIZE; + + /* select chain mode, and enable transmit timestamp function */ + desc_status = ENET_TDES0_TCHM | ENET_TDES0_TTSEN; + + /* configure DMA Tx descriptor table address register */ + ENET_DMA_TDTADDR = (uint32_t)desc_tab; + dma_current_txdesc = desc_tab; + dma_current_ptp_txdesc = desc_ptptab; + }else{ + /* if want to initialize DMA Rx descriptors */ + /* save a copy of the DMA Rx descriptors */ + desc_tab = rxdesc_tab; + buf = &rx_buff[0][0]; + count = ENET_RXBUF_NUM; + maxsize = ENET_RXBUF_SIZE; + + /* enable receiving */ + desc_status = ENET_RDES0_DAV; + /* select receive chained mode and set buffer1 size */ + desc_bufsize = ENET_RDES1_RCHM | (uint32_t)ENET_RXBUF_SIZE; + + /* configure DMA Rx descriptor table address register */ + ENET_DMA_RDTADDR = (uint32_t)desc_tab; + dma_current_rxdesc = desc_tab; + dma_current_ptp_rxdesc = desc_ptptab; + } + + /* configure each descriptor */ + for(num = 0U; num < count; num++){ + /* get the pointer to the next descriptor of the descriptor table */ + desc = desc_tab + num; + + /* configure descriptors */ + desc->status = desc_status; + desc->control_buffer_size = desc_bufsize; + desc->buffer1_addr = (uint32_t)(&buf[num * maxsize]); + + /* if is not the last descriptor */ + if(num < (count - 1U)){ + /* configure the next descriptor address */ + desc->buffer2_next_desc_addr = (uint32_t)(desc_tab + num + 1U); + }else{ + /* when it is the last descriptor, the next descriptor address + equals to first descriptor address in descriptor table */ + desc->buffer2_next_desc_addr = (uint32_t)desc_tab; + } + /* set desc_ptptab equal to desc_tab */ + (&desc_ptptab[num])->buffer1_addr = desc->buffer1_addr; + (&desc_ptptab[num])->buffer2_next_desc_addr = desc->buffer2_next_desc_addr; + } + /* when it is the last ptp descriptor, preserve the first descriptor + address of desc_ptptab in ptp descriptor status */ + (&desc_ptptab[num-1U])->status = (uint32_t)desc_ptptab; +} + +/*! + \brief initialize the DMA Tx/Rx descriptors's parameters in normal ring mode with PTP function + \param[in] direction: the descriptors which users want to init, refer to enet_dmadirection_enum, + only one parameter can be selected which is shown as below + \arg ENET_DMA_TX: DMA Tx descriptors + \arg ENET_DMA_RX: DMA Rx descriptors + \param[in] desc_ptptab: pointer to the first descriptor address of PTP Rx descriptor table + \param[out] none + \retval none +*/ +void enet_ptp_normal_descriptors_ring_init(enet_dmadirection_enum direction, enet_descriptors_struct *desc_ptptab) +{ + uint32_t num = 0U, count = 0U, maxsize = 0U; + uint32_t desc_status = 0U, desc_bufsize = 0U; + enet_descriptors_struct *desc, *desc_tab; + uint8_t *buf; + + /* configure descriptor skip length */ + ENET_DMA_BCTL &= ~ENET_DMA_BCTL_DPSL; + ENET_DMA_BCTL |= DMA_BCTL_DPSL(0); + + /* if want to initialize DMA Tx descriptors */ + if(ENET_DMA_TX == direction){ + /* save a copy of the DMA Tx descriptors */ + desc_tab = txdesc_tab; + buf = &tx_buff[0][0]; + count = ENET_TXBUF_NUM; + maxsize = ENET_TXBUF_SIZE; + + /* select ring mode, and enable transmit timestamp function */ + desc_status = ENET_TDES0_TTSEN; + + /* configure DMA Tx descriptor table address register */ + ENET_DMA_TDTADDR = (uint32_t)desc_tab; + dma_current_txdesc = desc_tab; + dma_current_ptp_txdesc = desc_ptptab; + }else{ + /* if want to initialize DMA Rx descriptors */ + /* save a copy of the DMA Rx descriptors */ + desc_tab = rxdesc_tab; + buf = &rx_buff[0][0]; + count = ENET_RXBUF_NUM; + maxsize = ENET_RXBUF_SIZE; + + /* enable receiving */ + desc_status = ENET_RDES0_DAV; + /* select receive ring mode and set buffer1 size */ + desc_bufsize = (uint32_t)ENET_RXBUF_SIZE; + + /* configure DMA Rx descriptor table address register */ + ENET_DMA_RDTADDR = (uint32_t)desc_tab; + dma_current_rxdesc = desc_tab; + dma_current_ptp_rxdesc = desc_ptptab; + } + + /* configure each descriptor */ + for(num = 0U; num < count; num++){ + /* get the pointer to the next descriptor of the descriptor table */ + desc = desc_tab + num; + + /* configure descriptors */ + desc->status = desc_status; + desc->control_buffer_size = desc_bufsize; + desc->buffer1_addr = (uint32_t)(&buf[num * maxsize]); + + /* when it is the last descriptor */ + if(num == (count - 1U)){ + if (ENET_DMA_TX == direction){ + /* configure transmit end of ring mode */ + desc->status |= ENET_TDES0_TERM; + }else{ + /* configure receive end of ring mode */ + desc->control_buffer_size |= ENET_RDES1_RERM; + } + } + /* set desc_ptptab equal to desc_tab */ + (&desc_ptptab[num])->buffer1_addr = desc->buffer1_addr; + (&desc_ptptab[num])->buffer2_next_desc_addr = desc->buffer2_next_desc_addr; + } + /* when it is the last ptp descriptor, preserve the first descriptor + address of desc_ptptab in ptp descriptor status */ + (&desc_ptptab[num-1U])->status = (uint32_t)desc_ptptab; +} + +/*! + \brief receive a packet data with timestamp values to application buffer, when the DMA is in normal mode + \param[in] bufsize: the size of buffer which is the parameter in function + \param[out] timestamp: pointer to the table which stores the timestamp high and low + \param[out] buffer: pointer to the application buffer + note -- if the input is NULL, user should copy data in application by himself + \retval ErrStatus: SUCCESS or ERROR +*/ +ErrStatus enet_ptpframe_receive_normal_mode(uint8_t *buffer, uint32_t bufsize, uint32_t timestamp[]) +{ + uint32_t offset = 0U, size = 0U; + + /* the descriptor is busy due to own by the DMA */ + if((uint32_t)RESET != (dma_current_rxdesc->status & ENET_RDES0_DAV)){ + return ERROR; + } + + /* if buffer pointer is null, indicates that users has copied data in application */ + if(NULL != buffer){ + /* if no error occurs, and the frame uses only one descriptor */ + if(((uint32_t)RESET == (dma_current_rxdesc->status & ENET_RDES0_ERRS)) && + ((uint32_t)RESET != (dma_current_rxdesc->status & ENET_RDES0_LDES)) && + ((uint32_t)RESET != (dma_current_rxdesc->status & ENET_RDES0_FDES))){ + + /* get the frame length except CRC */ + size = GET_RDES0_FRML(dma_current_rxdesc->status) - 4U; + /* if is a type frame, and CRC is not included in forwarding frame */ + if((RESET != (ENET_MAC_CFG & ENET_MAC_CFG_TFCD)) && (RESET != (dma_current_rxdesc->status & ENET_RDES0_FRMT))){ + size = size + 4U; + } + + /* to avoid situation that the frame size exceeds the buffer length */ + if(size > bufsize){ + return ERROR; + } + + /* copy data from Rx buffer to application buffer */ + for(offset = 0U; offset < size; offset++){ + (*(buffer + offset)) = (*(__IO uint8_t *)(uint32_t)((dma_current_ptp_rxdesc->buffer1_addr) + offset)); + } + + }else{ + return ERROR; + } + } + /* copy timestamp value from Rx descriptor to application array */ + timestamp[0] = dma_current_rxdesc->buffer1_addr; + timestamp[1] = dma_current_rxdesc->buffer2_next_desc_addr; + + dma_current_rxdesc->buffer1_addr = dma_current_ptp_rxdesc ->buffer1_addr ; + dma_current_rxdesc->buffer2_next_desc_addr = dma_current_ptp_rxdesc ->buffer2_next_desc_addr; + + /* enable reception, descriptor is owned by DMA */ + dma_current_rxdesc->status = ENET_RDES0_DAV; + + /* check Rx buffer unavailable flag status */ + if ((uint32_t)RESET != (ENET_DMA_STAT & ENET_DMA_STAT_RBU)){ + /* clear RBU flag */ + ENET_DMA_STAT = ENET_DMA_STAT_RBU; + /* resume DMA reception by writing to the RPEN register*/ + ENET_DMA_RPEN = 0U; + } + + /* update the current RxDMA descriptor pointer to the next decriptor in RxDMA decriptor table */ + /* chained mode */ + if((uint32_t)RESET != (dma_current_rxdesc->control_buffer_size & ENET_RDES1_RCHM)){ + dma_current_rxdesc = (enet_descriptors_struct*) (dma_current_ptp_rxdesc->buffer2_next_desc_addr); + /* if it is the last ptp descriptor */ + if(0U != dma_current_ptp_rxdesc->status){ + /* pointer back to the first ptp descriptor address in the desc_ptptab list address */ + dma_current_ptp_rxdesc = (enet_descriptors_struct*) (dma_current_ptp_rxdesc->status); + }else{ + /* ponter to the next ptp descriptor */ + dma_current_ptp_rxdesc++; + } + }else{ + /* ring mode */ + if((uint32_t)RESET != (dma_current_rxdesc->control_buffer_size & ENET_RDES1_RERM)){ + /* if is the last descriptor in table, the next descriptor is the table header */ + dma_current_rxdesc = (enet_descriptors_struct*) (ENET_DMA_RDTADDR); + /* RDES2 and RDES3 will not be covered by buffer address, so do not need to preserve a new table, + use the same table with RxDMA descriptor */ + dma_current_ptp_rxdesc = (enet_descriptors_struct*) (dma_current_ptp_rxdesc->status); + }else{ + /* the next descriptor is the current address, add the descriptor size, and descriptor skip length */ + dma_current_rxdesc = (enet_descriptors_struct*) (uint32_t)((uint32_t)dma_current_rxdesc + ETH_DMARXDESC_SIZE + GET_DMA_BCTL_DPSL(ENET_DMA_BCTL)); + dma_current_ptp_rxdesc ++; + } + } + + return SUCCESS; +} + +/*! + \brief send data with timestamp values in application buffer as a transmit packet, when the DMA is in normal mode + \param[in] buffer: pointer on the application buffer + note -- if the input is NULL, user should copy data in application by himself + \param[in] length: the length of frame data to be transmitted + \param[out] timestamp: pointer to the table which stores the timestamp high and low + note -- if the input is NULL, timestamp is ignored + \retval ErrStatus: SUCCESS or ERROR +*/ +ErrStatus enet_ptpframe_transmit_normal_mode(uint8_t *buffer, uint32_t length, uint32_t timestamp[]) +{ + uint32_t offset = 0U, timeout = 0U; + uint32_t dma_tbu_flag, dma_tu_flag, tdes0_ttmss_flag; + + /* the descriptor is busy due to own by the DMA */ + if((uint32_t)RESET != (dma_current_txdesc->status & ENET_TDES0_DAV)){ + return ERROR; + } + + /* only frame length no more than ENET_MAX_FRAME_SIZE is allowed */ + if(length > ENET_MAX_FRAME_SIZE){ + return ERROR; + } + + /* if buffer pointer is null, indicates that users has handled data in application */ + if(NULL != buffer){ + /* copy frame data from application buffer to Tx buffer */ + for(offset = 0U; offset < length; offset++){ + (*(__IO uint8_t *) (uint32_t)((dma_current_ptp_txdesc->buffer1_addr) + offset)) = (*(buffer + offset)); + } + } + /* set the frame length */ + dma_current_txdesc->control_buffer_size = (length & (uint32_t)0x1FFF); + /* set the segment of frame, frame is transmitted in one descriptor */ + dma_current_txdesc->status |= ENET_TDES0_LSG | ENET_TDES0_FSG; + /* enable the DMA transmission */ + dma_current_txdesc->status |= ENET_TDES0_DAV; + + /* check Tx buffer unavailable flag status */ + dma_tbu_flag = (ENET_DMA_STAT & ENET_DMA_STAT_TBU); + dma_tu_flag = (ENET_DMA_STAT & ENET_DMA_STAT_TU); + + if((RESET != dma_tbu_flag) || (RESET != dma_tu_flag)){ + /* clear TBU and TU flag */ + ENET_DMA_STAT = (dma_tbu_flag | dma_tu_flag); + /* resume DMA transmission by writing to the TPEN register*/ + ENET_DMA_TPEN = 0U; + } + + /* if timestamp pointer is null, indicates that users don't care timestamp in application */ + if(NULL != timestamp){ + /* wait for ENET_TDES0_TTMSS flag to be set, a timestamp was captured */ + do{ + tdes0_ttmss_flag = (dma_current_txdesc->status & ENET_TDES0_TTMSS); + timeout++; + }while((RESET == tdes0_ttmss_flag) && (timeout < ENET_DELAY_TO)); + + /* return ERROR due to timeout */ + if(ENET_DELAY_TO == timeout){ + return ERROR; + } + + /* clear the ENET_TDES0_TTMSS flag */ + dma_current_txdesc->status &= ~ENET_TDES0_TTMSS; + /* get the timestamp value of the transmit frame */ + timestamp[0] = dma_current_txdesc->buffer1_addr; + timestamp[1] = dma_current_txdesc->buffer2_next_desc_addr; + } + dma_current_txdesc->buffer1_addr = dma_current_ptp_txdesc ->buffer1_addr ; + dma_current_txdesc->buffer2_next_desc_addr = dma_current_ptp_txdesc ->buffer2_next_desc_addr; + + /* update the current TxDMA descriptor pointer to the next decriptor in TxDMA decriptor table */ + /* chained mode */ + if((uint32_t)RESET != (dma_current_txdesc->status & ENET_TDES0_TCHM)){ + dma_current_txdesc = (enet_descriptors_struct*) (dma_current_ptp_txdesc->buffer2_next_desc_addr); + /* if it is the last ptp descriptor */ + if(0U != dma_current_ptp_txdesc->status){ + /* pointer back to the first ptp descriptor address in the desc_ptptab list address */ + dma_current_ptp_txdesc = (enet_descriptors_struct*) (dma_current_ptp_txdesc->status); + }else{ + /* ponter to the next ptp descriptor */ + dma_current_ptp_txdesc++; + } + }else{ + /* ring mode */ + if((uint32_t)RESET != (dma_current_txdesc->status & ENET_TDES0_TERM)){ + /* if is the last descriptor in table, the next descriptor is the table header */ + dma_current_txdesc = (enet_descriptors_struct*) (ENET_DMA_TDTADDR); + /* TDES2 and TDES3 will not be covered by buffer address, so do not need to preserve a new table, + use the same table with TxDMA descriptor */ + dma_current_ptp_txdesc = (enet_descriptors_struct*) (dma_current_ptp_txdesc->status); + }else{ + /* the next descriptor is the current address, add the descriptor size, and descriptor skip length */ + dma_current_txdesc = (enet_descriptors_struct*) (uint32_t)((uint32_t)dma_current_txdesc + ETH_DMATXDESC_SIZE + GET_DMA_BCTL_DPSL(ENET_DMA_BCTL)); + dma_current_ptp_txdesc ++; + } + } + return SUCCESS; +} + +#endif /* SELECT_DESCRIPTORS_ENHANCED_MODE */ + +/*! + \brief wakeup frame filter register pointer reset + \param[in] none + \param[out] none + \retval none +*/ +void enet_wum_filter_register_pointer_reset(void) +{ + ENET_MAC_WUM |= ENET_MAC_WUM_WUFFRPR; +} + +/*! + \brief set the remote wakeup frame registers + \param[in] pdata: pointer to buffer data which is written to remote wakeup frame registers (8 words total) + \param[out] none + \retval none +*/ +void enet_wum_filter_config(uint32_t pdata[]) +{ + uint32_t num = 0U; + + /* configure ENET_MAC_RWFF register */ + for(num = 0U; num < ETH_WAKEUP_REGISTER_LENGTH; num++){ + ENET_MAC_RWFF = pdata[num]; + } +} + +/*! + \brief enable wakeup management features + \param[in] feature: one or more parameters can be selected which are shown as below + \arg ENET_WUM_POWER_DOWN: power down mode + \arg ENET_WUM_MAGIC_PACKET_FRAME: enable a wakeup event due to magic packet reception + \arg ENET_WUM_WAKE_UP_FRAME: enable a wakeup event due to wakeup frame reception + \arg ENET_WUM_GLOBAL_UNICAST: any received unicast frame passed filter is considered to be a wakeup frame + \param[out] none + \retval none +*/ +void enet_wum_feature_enable(uint32_t feature) +{ + ENET_MAC_WUM |= feature; +} + +/*! + \brief disable wakeup management features + \param[in] feature: one or more parameters can be selected which are shown as below + \arg ENET_WUM_MAGIC_PACKET_FRAME: enable a wakeup event due to magic packet reception + \arg ENET_WUM_WAKE_UP_FRAME: enable a wakeup event due to wakeup frame reception + \arg ENET_WUM_GLOBAL_UNICAST: any received unicast frame passed filter is considered to be a wakeup frame + \param[out] none + \retval none +*/ +void enet_wum_feature_disable(uint32_t feature) +{ + ENET_MAC_WUM &= (~feature); +} + +/*! + \brief reset the MAC statistics counters + \param[in] none + \param[out] none + \retval none +*/ +void enet_msc_counters_reset(void) +{ + /* reset all counters */ + ENET_MSC_CTL |= ENET_MSC_CTL_CTR; +} + +/*! + \brief enable the MAC statistics counter features + \param[in] feature: one or more parameters can be selected which are shown as below + \arg ENET_MSC_COUNTER_STOP_ROLLOVER: counter stop rollover + \arg ENET_MSC_RESET_ON_READ: reset on read + \arg ENET_MSC_COUNTERS_FREEZE: MSC counter freeze + \param[out] none + \retval none +*/ +void enet_msc_feature_enable(uint32_t feature) +{ + ENET_MSC_CTL |= feature; +} + +/*! + \brief disable the MAC statistics counter features + \param[in] feature: one or more parameters can be selected which are shown as below + \arg ENET_MSC_COUNTER_STOP_ROLLOVER: counter stop rollover + \arg ENET_MSC_RESET_ON_READ: reset on read + \arg ENET_MSC_COUNTERS_FREEZE: MSC counter freeze + \param[out] none + \retval none +*/ +void enet_msc_feature_disable(uint32_t feature) +{ + ENET_MSC_CTL &= (~feature); +} + +/*! + \brief configure MAC statistics counters preset mode + \param[in] mode: MSC counters preset mode, refer to enet_msc_preset_enum, + only one parameter can be selected which is shown as below + \arg ENET_MSC_PRESET_NONE: do not preset MSC counter + \arg ENET_MSC_PRESET_HALF: preset all MSC counters to almost-half(0x7FFF FFF0) value + \arg ENET_MSC_PRESET_FULL: preset all MSC counters to almost-full(0xFFFF FFF0) value + \param[out] none + \retval none +*/ +void enet_msc_counters_preset_config(enet_msc_preset_enum mode) +{ + ENET_MSC_CTL &= ENET_MSC_PRESET_MASK; + ENET_MSC_CTL |= (uint32_t)mode; +} + +/*! + \brief get MAC statistics counter + \param[in] counter: MSC counters which is selected, refer to enet_msc_counter_enum, + only one parameter can be selected which is shown as below + \arg ENET_MSC_TX_SCCNT: MSC transmitted good frames after a single collision counter + \arg ENET_MSC_TX_MSCCNT: MSC transmitted good frames after more than a single collision counter + \arg ENET_MSC_TX_TGFCNT: MSC transmitted good frames counter + \arg ENET_MSC_RX_RFCECNT: MSC received frames with CRC error counter + \arg ENET_MSC_RX_RFAECNT: MSC received frames with alignment error counter + \arg ENET_MSC_RX_RGUFCNT: MSC received good unicast frames counter + \param[out] none + \retval the MSC counter value +*/ +uint32_t enet_msc_counters_get(enet_msc_counter_enum counter) +{ + uint32_t reval; + + reval = REG32((ENET + (uint32_t)counter)); + + return reval; +} + +/*! + \brief change subsecond to nanosecond + \param[in] subsecond: subsecond value + \param[out] none + \retval the nanosecond value +*/ +uint32_t enet_ptp_subsecond_2_nanosecond(uint32_t subsecond) +{ + uint64_t val = subsecond * 1000000000Ull; + val >>= 31; + return (uint32_t)val; +} + +/*! + \brief change nanosecond to subsecond + \param[in] nanosecond: nanosecond value + \param[out] none + \retval the subsecond value +*/ +uint32_t enet_ptp_nanosecond_2_subsecond(uint32_t nanosecond) +{ + uint64_t val = nanosecond * 0x80000000Ull; + val /= 1000000000U; + return (uint32_t)val; +} + +/*! + \brief enable the PTP features + \param[in] feature: the feature of ENET PTP mode + one or more parameters can be selected which are shown as below + \arg ENET_RXTX_TIMESTAMP: timestamp function for transmit and receive frames + \arg ENET_PTP_TIMESTAMP_INT: timestamp interrupt trigger + \arg ENET_ALL_RX_TIMESTAMP: all received frames are taken snapshot + \arg ENET_NONTYPE_FRAME_SNAPSHOT: take snapshot when received non type frame + \arg ENET_IPV6_FRAME_SNAPSHOT: take snapshot for IPv6 frame + \arg ENET_IPV4_FRAME_SNAPSHOT: take snapshot for IPv4 frame + \arg ENET_PTP_FRAME_USE_MACADDRESS_FILTER: use MAC address1-3 to filter the PTP frame + \param[out] none + \retval none +*/ +void enet_ptp_feature_enable(uint32_t feature) +{ + ENET_PTP_TSCTL |= feature; +} + +/*! + \brief disable the PTP features + \param[in] feature: the feature of ENET PTP mode + one or more parameters can be selected which are shown as below + \arg ENET_RXTX_TIMESTAMP: timestamp function for transmit and receive frames + \arg ENET_PTP_TIMESTAMP_INT: timestamp interrupt trigger + \arg ENET_ALL_RX_TIMESTAMP: all received frames are taken snapshot + \arg ENET_NONTYPE_FRAME_SNAPSHOT: take snapshot when received non type frame + \arg ENET_IPV6_FRAME_SNAPSHOT: take snapshot for IPv6 frame + \arg ENET_IPV4_FRAME_SNAPSHOT: take snapshot for IPv4 frame + \arg ENET_PTP_FRAME_USE_MACADDRESS_FILTER: use MAC address1-3 to filter the PTP frame + \param[out] none + \retval none +*/ +void enet_ptp_feature_disable(uint32_t feature) +{ + ENET_PTP_TSCTL &= ~feature; +} + +/*! + \brief configure the PTP timestamp function + \param[in] func: only one parameter can be selected which is shown as below + \arg ENET_CKNT_ORDINARY: type of ordinary clock node type for timestamp + \arg ENET_CKNT_BOUNDARY: type of boundary clock node type for timestamp + \arg ENET_CKNT_END_TO_END: type of end-to-end transparent clock node type for timestamp + \arg ENET_CKNT_PEER_TO_PEER: type of peer-to-peer transparent clock node type for timestamp + \arg ENET_PTP_ADDEND_UPDATE: addend register update + \arg ENET_PTP_SYSTIME_UPDATE: timestamp update + \arg ENET_PTP_SYSTIME_INIT: timestamp initialize + \arg ENET_PTP_FINEMODE: the system timestamp uses the fine method for updating + \arg ENET_PTP_COARSEMODE: the system timestamp uses the coarse method for updating + \arg ENET_SUBSECOND_DIGITAL_ROLLOVER: digital rollover mode + \arg ENET_SUBSECOND_BINARY_ROLLOVER: binary rollover mode + \arg ENET_SNOOPING_PTP_VERSION_2: version 2 + \arg ENET_SNOOPING_PTP_VERSION_1: version 1 + \arg ENET_EVENT_TYPE_MESSAGES_SNAPSHOT: only event type messages are taken snapshot + \arg ENET_ALL_TYPE_MESSAGES_SNAPSHOT: all type messages are taken snapshot except announce, + management and signaling message + \arg ENET_MASTER_NODE_MESSAGE_SNAPSHOT: snapshot is only take for master node message + \arg ENET_SLAVE_NODE_MESSAGE_SNAPSHOT: snapshot is only taken for slave node message + \param[out] none + \retval ErrStatus: SUCCESS or ERROR +*/ +ErrStatus enet_ptp_timestamp_function_config(enet_ptp_function_enum func) +{ + uint32_t temp_config = 0U, temp_state = 0U; + uint32_t timeout = 0U; + ErrStatus enet_state = SUCCESS; + + switch(func){ + case ENET_CKNT_ORDINARY: + case ENET_CKNT_BOUNDARY: + case ENET_CKNT_END_TO_END: + case ENET_CKNT_PEER_TO_PEER: + ENET_PTP_TSCTL &= ~ENET_PTP_TSCTL_CKNT; + ENET_PTP_TSCTL |= (uint32_t)func; + break; + case ENET_PTP_ADDEND_UPDATE: + /* this bit must be read as zero before application set it */ + do{ + temp_state = ENET_PTP_TSCTL & ENET_PTP_TSCTL_TMSARU; + timeout++; + }while((RESET != temp_state) && (timeout < ENET_DELAY_TO)); + /* return ERROR due to timeout */ + if(ENET_DELAY_TO == timeout){ + enet_state = ERROR; + }else{ + ENET_PTP_TSCTL |= ENET_PTP_TSCTL_TMSARU; + } + break; + case ENET_PTP_SYSTIME_UPDATE: + /* both the TMSSTU and TMSSTI bits must be read as zero before application set this bit */ + do{ + temp_state = ENET_PTP_TSCTL & (ENET_PTP_TSCTL_TMSSTU | ENET_PTP_TSCTL_TMSSTI); + timeout++; + }while((RESET != temp_state) && (timeout < ENET_DELAY_TO)); + /* return ERROR due to timeout */ + if(ENET_DELAY_TO == timeout){ + enet_state = ERROR; + }else{ + ENET_PTP_TSCTL |= ENET_PTP_TSCTL_TMSSTU; + } + break; + case ENET_PTP_SYSTIME_INIT: + /* this bit must be read as zero before application set it */ + do{ + temp_state = ENET_PTP_TSCTL & ENET_PTP_TSCTL_TMSSTI; + timeout++; + }while((RESET != temp_state) && (timeout < ENET_DELAY_TO)); + /* return ERROR due to timeout */ + if(ENET_DELAY_TO == timeout){ + enet_state = ERROR; + }else{ + ENET_PTP_TSCTL |= ENET_PTP_TSCTL_TMSSTI; + } + break; + default: + temp_config = (uint32_t)func & (~BIT(31)); + if(RESET != ((uint32_t)func & BIT(31))){ + ENET_PTP_TSCTL |= temp_config; + }else{ + ENET_PTP_TSCTL &= ~temp_config; + } + break; + } + + return enet_state; +} + +/*! + \brief configure system time subsecond increment value + \param[in] subsecond: the value will be added to the subsecond value of system time, + this value must be between 0 and 0xFF + \param[out] none + \retval none +*/ +void enet_ptp_subsecond_increment_config(uint32_t subsecond) +{ + ENET_PTP_SSINC = PTP_SSINC_STMSSI(subsecond); +} + +/*! + \brief adjusting the clock frequency only in fine update mode + \param[in] add: the value will be added to the accumulator register to achieve time synchronization + \param[out] none + \retval none +*/ +void enet_ptp_timestamp_addend_config(uint32_t add) +{ + ENET_PTP_TSADDEND = add; +} + +/*! + \brief initialize or add/subtract to second of the system time + \param[in] sign: timestamp update positive or negative sign, + only one parameter can be selected which is shown as below + \arg ENET_PTP_ADD_TO_TIME: timestamp update value is added to system time + \arg ENET_PTP_SUBSTRACT_FROM_TIME: timestamp update value is subtracted from system time + \param[in] second: initializing or adding/subtracting to second of the system time + \param[in] subsecond: the current subsecond of the system time + with 0.46 ns accuracy if required accuracy is 20 ns + \param[out] none + \retval none +*/ +void enet_ptp_timestamp_update_config(uint32_t sign, uint32_t second, uint32_t subsecond) +{ + ENET_PTP_TSUH = second; + ENET_PTP_TSUL = sign | PTP_TSUL_TMSUSS(subsecond); +} + +/*! + \brief configure the expected target time + \param[in] second: the expected target second time + \param[in] nanosecond: the expected target nanosecond time (signed) + \param[out] none + \retval none +*/ +void enet_ptp_expected_time_config(uint32_t second, uint32_t nanosecond) +{ + ENET_PTP_ETH = second; + ENET_PTP_ETL = nanosecond; +} + +/*! + \brief get the current system time + \param[in] none + \param[out] systime_struct: pointer to a enet_ptp_systime_struct structure which contains + parameters of PTP system time + members of the structure and the member values are shown as below: + second: 0x0 - 0xFFFF FFFF + nanosecond: 0x0 - 0x7FFF FFFF * 10^9 / 2^31 + sign: ENET_PTP_TIME_POSITIVE, ENET_PTP_TIME_NEGATIVE + \retval none +*/ +void enet_ptp_system_time_get(enet_ptp_systime_struct *systime_struct) +{ + uint32_t temp_sec = 0U, temp_subs = 0U; + + /* get the value of sysytem time registers */ + temp_sec = (uint32_t)ENET_PTP_TSH; + temp_subs = (uint32_t)ENET_PTP_TSL; + + /* get sysytem time and construct the enet_ptp_systime_struct structure */ + systime_struct->second = temp_sec; + systime_struct->nanosecond = GET_PTP_TSL_STMSS(temp_subs); + systime_struct->nanosecond = enet_ptp_subsecond_2_nanosecond(systime_struct->nanosecond); + systime_struct->sign = GET_PTP_TSL_STS(temp_subs); +} + +/*! + \brief configure the PPS output frequency + \param[in] freq: PPS output frequency, + only one parameter can be selected which is shown as below + \arg ENET_PPSOFC_1HZ: PPS output 1Hz frequency + \arg ENET_PPSOFC_2HZ: PPS output 2Hz frequency + \arg ENET_PPSOFC_4HZ: PPS output 4Hz frequency + \arg ENET_PPSOFC_8HZ: PPS output 8Hz frequency + \arg ENET_PPSOFC_16HZ: PPS output 16Hz frequency + \arg ENET_PPSOFC_32HZ: PPS output 32Hz frequency + \arg ENET_PPSOFC_64HZ: PPS output 64Hz frequency + \arg ENET_PPSOFC_128HZ: PPS output 128Hz frequency + \arg ENET_PPSOFC_256HZ: PPS output 256Hz frequency + \arg ENET_PPSOFC_512HZ: PPS output 512Hz frequency + \arg ENET_PPSOFC_1024HZ: PPS output 1024Hz frequency + \arg ENET_PPSOFC_2048HZ: PPS output 2048Hz frequency + \arg ENET_PPSOFC_4096HZ: PPS output 4096Hz frequency + \arg ENET_PPSOFC_8192HZ: PPS output 8192Hz frequency + \arg ENET_PPSOFC_16384HZ: PPS output 16384Hz frequency + \arg ENET_PPSOFC_32768HZ: PPS output 32768Hz frequency + \param[out] none + \retval none +*/ +void enet_ptp_pps_output_frequency_config(uint32_t freq) +{ + ENET_PTP_PPSCTL = freq; +} + +/*! + \brief configure and start PTP timestamp counter + \param[in] updatemethod: method for updating + \arg ENET_PTP_FINEMODE: fine correction method + \arg ENET_PTP_COARSEMODE: coarse correction method + \param[in] init_sec: second value for initializing system time + \param[in] init_subsec: subsecond value for initializing system time + \param[in] carry_cfg: the value to be added to the accumulator register (in fine method is used) + \param[in] accuracy_cfg: the value to be added to the subsecond value of system time + \param[out] none + \retval none +*/ +void enet_ptp_start(int32_t updatemethod, uint32_t init_sec, uint32_t init_subsec, uint32_t carry_cfg, uint32_t accuracy_cfg) +{ + /* mask the timestamp trigger interrupt */ + enet_interrupt_disable(ENET_MAC_INT_TMSTIM); + + /* enable timestamp */ + enet_ptp_feature_enable(ENET_ALL_RX_TIMESTAMP | ENET_RXTX_TIMESTAMP); + + /* configure system time subsecond increment based on the PTP clock frequency */ + enet_ptp_subsecond_increment_config(accuracy_cfg); + + if(ENET_PTP_FINEMODE == updatemethod){ + /* fine correction method: configure the timestamp addend, then update */ + enet_ptp_timestamp_addend_config(carry_cfg); + enet_ptp_timestamp_function_config(ENET_PTP_ADDEND_UPDATE); + /* wait until update is completed */ + while(SET == enet_ptp_flag_get((uint32_t)ENET_PTP_ADDEND_UPDATE)){ + } + } + + /* choose the fine correction method */ + enet_ptp_timestamp_function_config((enet_ptp_function_enum)updatemethod); + + /* initialize the system time */ + enet_ptp_timestamp_update_config(ENET_PTP_ADD_TO_TIME, init_sec, init_subsec); + enet_ptp_timestamp_function_config(ENET_PTP_SYSTIME_INIT); + +#ifdef SELECT_DESCRIPTORS_ENHANCED_MODE + enet_desc_select_enhanced_mode(); +#endif /* SELECT_DESCRIPTORS_ENHANCED_MODE */ +} + +/*! + \brief adjust frequency in fine method by configure addend register + \param[in] carry_cfg: the value to be added to the accumulator register + \param[out] none + \retval none +*/ +void enet_ptp_finecorrection_adjfreq(int32_t carry_cfg) +{ + /* re-configure the timestamp addend, then update */ + enet_ptp_timestamp_addend_config((uint32_t)carry_cfg); + enet_ptp_timestamp_function_config(ENET_PTP_ADDEND_UPDATE); +} + +/*! + \brief update system time in coarse method + \param[in] systime_struct: : pointer to a enet_ptp_systime_struct structure which contains + parameters of PTP system time + members of the structure and the member values are shown as below: + second: 0x0 - 0xFFFF FFFF + nanosecond: 0x0 - 0x7FFF FFFF * 10^9 / 2^31 + sign: ENET_PTP_TIME_POSITIVE, ENET_PTP_TIME_NEGATIVE + \param[out] none + \retval none +*/ +void enet_ptp_coarsecorrection_systime_update(enet_ptp_systime_struct *systime_struct) +{ + uint32_t subsecond_val; + uint32_t carry_cfg; + + subsecond_val = enet_ptp_nanosecond_2_subsecond(systime_struct->nanosecond); + + /* save the carry_cfg value */ + carry_cfg = ENET_PTP_TSADDEND_TMSA; + + /* update the system time */ + enet_ptp_timestamp_update_config(systime_struct->sign, systime_struct->second, subsecond_val); + enet_ptp_timestamp_function_config(ENET_PTP_SYSTIME_UPDATE); + + /* wait until the update is completed */ + while(SET == enet_ptp_flag_get((uint32_t)ENET_PTP_SYSTIME_UPDATE)){ + } + + /* write back the carry_cfg value, then update */ + enet_ptp_timestamp_addend_config(carry_cfg); + enet_ptp_timestamp_function_config(ENET_PTP_ADDEND_UPDATE); +} + +/*! + \brief set system time in fine method + \param[in] systime_struct: : pointer to a enet_ptp_systime_struct structure which contains + parameters of PTP system time + members of the structure and the member values are shown as below: + second: 0x0 - 0xFFFF FFFF + nanosecond: 0x0 - 0x7FFF FFFF * 10^9 / 2^31 + sign: ENET_PTP_TIME_POSITIVE, ENET_PTP_TIME_NEGATIVE + \param[out] none + \retval none +*/ +void enet_ptp_finecorrection_settime(enet_ptp_systime_struct * systime_struct) +{ + uint32_t subsecond_val; + + subsecond_val = enet_ptp_nanosecond_2_subsecond(systime_struct->nanosecond); + + /* initialize the system time */ + enet_ptp_timestamp_update_config(systime_struct->sign, systime_struct->second, subsecond_val); + enet_ptp_timestamp_function_config(ENET_PTP_SYSTIME_INIT); + + /* wait until the system time initialzation finished */ + while(SET == enet_ptp_flag_get((uint32_t)ENET_PTP_SYSTIME_INIT)){ + } +} + +/*! + \brief get the ptp flag status + \param[in] flag: ptp flag status to be checked + \arg ENET_PTP_ADDEND_UPDATE: addend register update + \arg ENET_PTP_SYSTIME_UPDATE: timestamp update + \arg ENET_PTP_SYSTIME_INIT: timestamp initialize + \param[out] none + \retval FlagStatus: SET or RESET +*/ +FlagStatus enet_ptp_flag_get(uint32_t flag) +{ + FlagStatus bitstatus = RESET; + + if ((uint32_t)RESET != (ENET_PTP_TSCTL & flag)){ + bitstatus = SET; + } + + return bitstatus; +} + +/*! + \brief reset the ENET initpara struct, call it before using enet_initpara_config() + \param[in] none + \param[out] none + \retval none +*/ +void enet_initpara_reset(void) +{ + enet_initpara.option_enable = 0U; + enet_initpara.forward_frame = 0U; + enet_initpara.dmabus_mode = 0U; + enet_initpara.dma_maxburst = 0U; + enet_initpara.dma_arbitration = 0U; + enet_initpara.store_forward_mode = 0U; + enet_initpara.dma_function = 0U; + enet_initpara.vlan_config = 0U; + enet_initpara.flow_control = 0U; + enet_initpara.hashtable_high = 0U; + enet_initpara.hashtable_low = 0U; + enet_initpara.framesfilter_mode = 0U; + enet_initpara.halfduplex_param = 0U; + enet_initpara.timer_config = 0U; + enet_initpara.interframegap = 0U; +} + +/*! + \brief initialize ENET peripheral with generally concerned parameters, call it by enet_init() + \param[in] none + \param[out] none + \retval none +*/ +static void enet_default_init(void) +{ + uint32_t reg_value = 0U; + + /* MAC */ + /* configure ENET_MAC_CFG register */ + reg_value = ENET_MAC_CFG; + reg_value &= MAC_CFG_MASK; + reg_value |= ENET_WATCHDOG_ENABLE | ENET_JABBER_ENABLE | ENET_INTERFRAMEGAP_96BIT \ + | ENET_SPEEDMODE_10M |ENET_MODE_HALFDUPLEX | ENET_LOOPBACKMODE_DISABLE \ + | ENET_CARRIERSENSE_ENABLE | ENET_RECEIVEOWN_ENABLE \ + | ENET_RETRYTRANSMISSION_ENABLE | ENET_BACKOFFLIMIT_10 \ + | ENET_DEFERRALCHECK_DISABLE \ + | ENET_TYPEFRAME_CRC_DROP_DISABLE \ + | ENET_AUTO_PADCRC_DROP_DISABLE \ + | ENET_CHECKSUMOFFLOAD_DISABLE; + ENET_MAC_CFG = reg_value; + + /* configure ENET_MAC_FRMF register */ + ENET_MAC_FRMF = ENET_SRC_FILTER_DISABLE |ENET_DEST_FILTER_INVERSE_DISABLE \ + |ENET_MULTICAST_FILTER_PERFECT |ENET_UNICAST_FILTER_PERFECT \ + |ENET_PCFRM_PREVENT_ALL |ENET_BROADCASTFRAMES_ENABLE \ + |ENET_PROMISCUOUS_DISABLE |ENET_RX_FILTER_ENABLE; + + /* configure ENET_MAC_HLH, ENET_MAC_HLL register */ + ENET_MAC_HLH = 0x0U; + + ENET_MAC_HLL = 0x0U; + + /* configure ENET_MAC_FCTL, ENET_MAC_FCTH register */ + reg_value = ENET_MAC_FCTL; + reg_value &= MAC_FCTL_MASK; + reg_value |= MAC_FCTL_PTM(0) |ENET_ZERO_QUANTA_PAUSE_DISABLE \ + |ENET_PAUSETIME_MINUS4 |ENET_UNIQUE_PAUSEDETECT \ + |ENET_RX_FLOWCONTROL_DISABLE |ENET_TX_FLOWCONTROL_DISABLE; + ENET_MAC_FCTL = reg_value; + + /* configure ENET_MAC_VLT register */ + ENET_MAC_VLT = ENET_VLANTAGCOMPARISON_16BIT |MAC_VLT_VLTI(0); + + /* DMA */ + /* configure ENET_DMA_CTL register */ + reg_value = ENET_DMA_CTL; + reg_value &= DMA_CTL_MASK; + reg_value |= ENET_TCPIP_CKSUMERROR_DROP |ENET_RX_MODE_STOREFORWARD \ + |ENET_FLUSH_RXFRAME_ENABLE |ENET_TX_MODE_STOREFORWARD \ + |ENET_TX_THRESHOLD_64BYTES |ENET_RX_THRESHOLD_64BYTES \ + |ENET_SECONDFRAME_OPT_DISABLE; + ENET_DMA_CTL = reg_value; + + /* configure ENET_DMA_BCTL register */ + reg_value = ENET_DMA_BCTL; + reg_value &= DMA_BCTL_MASK; + reg_value = ENET_ADDRESS_ALIGN_ENABLE |ENET_ARBITRATION_RXTX_2_1 \ + |ENET_RXDP_32BEAT |ENET_PGBL_32BEAT |ENET_RXTX_DIFFERENT_PGBL \ + |ENET_FIXED_BURST_ENABLE |ENET_MIXED_BURST_DISABLE \ + |ENET_NORMAL_DESCRIPTOR; + ENET_DMA_BCTL = reg_value; +} + +#ifndef USE_DELAY +/*! + \brief insert a delay time + \param[in] ncount: specifies the delay time length + \param[out] none + \param[out] none +*/ +static void enet_delay(uint32_t ncount) +{ + __IO uint32_t delay_time = 0U; + + for(delay_time = ncount; delay_time != 0U; delay_time--){ + } +} +#endif /* USE_DELAY */ + +#endif /* GD32F30X_CL */ diff --git a/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_standard_peripheral/Source/gd32f30x_exmc.c b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_standard_peripheral/Source/gd32f30x_exmc.c new file mode 100644 index 0000000000..8b0fb49e52 --- /dev/null +++ b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_standard_peripheral/Source/gd32f30x_exmc.c @@ -0,0 +1,677 @@ +/*! + \file gd32f30x_exmc.c + \brief EXMC driver + + \version 2017-02-10, V1.0.0, firmware for GD32F30x + \version 2018-10-10, V1.1.0, firmware for GD32F30x + \version 2018-12-25, V2.0.0, firmware for GD32F30x + \version 2020-09-30, V2.1.0, firmware for GD32F30x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "gd32f30x_exmc.h" + +/* EXMC bank0 register reset value */ +#define BANK0_SNCTL_REGION0_RESET ((uint32_t)0x000030DBU) +#define BANK0_SNCTL_REGION1_2_3_RESET ((uint32_t)0x000030D2U) +#define BANK0_SNTCFG_RESET ((uint32_t)0x0FFFFFFFU) +#define BANK0_SNWTCFG_RESET ((uint32_t)0x0FFFFFFFU) + +/* EXMC bank1/2 register reset mask */ +#define BANK1_2_NPCTL_RESET ((uint32_t)0x00000018U) +#define BANK1_2_NPINTEN_RESET ((uint32_t)0x00000042U) +#define BANK1_2_NPCTCFG_RESET ((uint32_t)0xFCFCFCFCU) +#define BANK1_2_NPATCFG_RESET ((uint32_t)0xFCFCFCFCU) + +/* EXMC bank3 register reset mask */ +#define BANK3_NPCTL_RESET ((uint32_t)0x00000018U) +#define BANK3_NPINTEN_RESET ((uint32_t)0x00000043U) +#define BANK3_NPCTCFG_RESET ((uint32_t)0xFCFCFCFCU) +#define BANK3_NPATCFG_RESET ((uint32_t)0xFCFCFCFCU) +#define BANK3_PIOTCFG3_RESET ((uint32_t)0xFCFCFCFCU) + +/* EXMC register bit offset */ +#define SNCTL_NRMUX_OFFSET ((uint32_t)1U) +#define SNCTL_SBRSTEN_OFFSET ((uint32_t)8U) +#define SNCTL_WRAPEN_OFFSET ((uint32_t)10U) +#define SNCTL_WREN_OFFSET ((uint32_t)12U) +#define SNCTL_NRWTEN_OFFSET ((uint32_t)13U) +#define SNCTL_EXMODEN_OFFSET ((uint32_t)14U) +#define SNCTL_ASYNCWAIT_OFFSET ((uint32_t)15U) + +#define SNTCFG_AHLD_OFFSET ((uint32_t)4U) +#define SNTCFG_DSET_OFFSET ((uint32_t)8U) +#define SNTCFG_BUSLAT_OFFSET ((uint32_t)16U) + +#define SNWTCFG_WAHLD_OFFSET ((uint32_t)4U) +#define SNWTCFG_WDSET_OFFSET ((uint32_t)8U) +#define SNWTCFG_WBUSLAT_OFFSET ((uint32_t)16U) + +#define NPCTL_NDWTEN_OFFSET ((uint32_t)1U) +#define NPCTL_ECCEN_OFFSET ((uint32_t)6U) + +#define NPCTCFG_COMWAIT_OFFSET ((uint32_t)8U) +#define NPCTCFG_COMHLD_OFFSET ((uint32_t)16U) +#define NPCTCFG_COMHIZ_OFFSET ((uint32_t)24U) + +#define NPATCFG_ATTWAIT_OFFSET ((uint32_t)8U) +#define NPATCFG_ATTHLD_OFFSET ((uint32_t)16U) +#define NPATCFG_ATTHIZ_OFFSET ((uint32_t)24U) + +#define PIOTCFG_IOWAIT_OFFSET ((uint32_t)8U) +#define PIOTCFG_IOHLD_OFFSET ((uint32_t)16U) +#define PIOTCFG_IOHIZ_OFFSET ((uint32_t)24U) + +#define INTEN_INTS_OFFSET ((uint32_t)3U) + +/*! + \brief deinitialize EXMC NOR/SRAM region + \param[in] exmc_norsram_region: select the region of bank0 + only one parameter can be selected which is shown as below: + \arg EXMC_BANK0_NORSRAM_REGIONx(x=0..3) + \param[out] none + \retval none +*/ +void exmc_norsram_deinit(uint32_t exmc_norsram_region) +{ + /* reset the registers */ + if(EXMC_BANK0_NORSRAM_REGION0 == exmc_norsram_region){ + EXMC_SNCTL(exmc_norsram_region) = BANK0_SNCTL_REGION0_RESET; + }else{ + EXMC_SNCTL(exmc_norsram_region) = BANK0_SNCTL_REGION1_2_3_RESET; + } + EXMC_SNTCFG(exmc_norsram_region) = BANK0_SNTCFG_RESET; + EXMC_SNWTCFG(exmc_norsram_region) = BANK0_SNWTCFG_RESET; +} + +/*! + \brief initialize exmc_norsram_parameter_struct with the default values + \param[in] none + \param[out] exmc_norsram_init_struct: the initialized struct exmc_norsram_parameter_struct pointer + \retval none +*/ +void exmc_norsram_struct_para_init(exmc_norsram_parameter_struct* exmc_norsram_init_struct) +{ + /* configure the structure with default values */ + exmc_norsram_init_struct->norsram_region = EXMC_BANK0_NORSRAM_REGION0; + exmc_norsram_init_struct->address_data_mux = ENABLE; + exmc_norsram_init_struct->memory_type = EXMC_MEMORY_TYPE_SRAM; + exmc_norsram_init_struct->databus_width = EXMC_NOR_DATABUS_WIDTH_8B; + exmc_norsram_init_struct->burst_mode = DISABLE; + exmc_norsram_init_struct->nwait_polarity = EXMC_NWAIT_POLARITY_LOW; + exmc_norsram_init_struct->wrap_burst_mode = DISABLE; + exmc_norsram_init_struct->nwait_config = EXMC_NWAIT_CONFIG_BEFORE; + exmc_norsram_init_struct->memory_write = ENABLE; + exmc_norsram_init_struct->nwait_signal = ENABLE; + exmc_norsram_init_struct->extended_mode = DISABLE; + exmc_norsram_init_struct->asyn_wait = DISABLE; + exmc_norsram_init_struct->write_mode = EXMC_ASYN_WRITE; + + /* read/write timing configure */ + exmc_norsram_init_struct->read_write_timing->asyn_address_setuptime = 0xFU; + exmc_norsram_init_struct->read_write_timing->asyn_address_holdtime = 0xFU; + exmc_norsram_init_struct->read_write_timing->asyn_data_setuptime = 0xFFU; + exmc_norsram_init_struct->read_write_timing->bus_latency = 0xFU; + exmc_norsram_init_struct->read_write_timing->syn_clk_division = EXMC_SYN_CLOCK_RATIO_16_CLK; + exmc_norsram_init_struct->read_write_timing->syn_data_latency = EXMC_DATALAT_17_CLK; + exmc_norsram_init_struct->read_write_timing->asyn_access_mode = EXMC_ACCESS_MODE_A; + + /* write timing configure, when extended mode is used */ + exmc_norsram_init_struct->write_timing->asyn_address_setuptime = 0xFU; + exmc_norsram_init_struct->write_timing->asyn_address_holdtime = 0xFU; + exmc_norsram_init_struct->write_timing->asyn_data_setuptime = 0xFFU; + exmc_norsram_init_struct->write_timing->bus_latency = 0xFU; + exmc_norsram_init_struct->write_timing->asyn_access_mode = EXMC_ACCESS_MODE_A; +} + +/*! + \brief initialize EXMC NOR/SRAM region + \param[in] exmc_norsram_parameter_struct: configure the EXMC NOR/SRAM parameter + norsram_region: EXMC_BANK0_NORSRAM_REGIONx,x=0..3 + write_mode: EXMC_ASYN_WRITE,EXMC_SYN_WRITE + extended_mode: ENABLE or DISABLE + asyn_wait: ENABLE or DISABLE + nwait_signal: ENABLE or DISABLE + memory_write: ENABLE or DISABLE + nwait_config: EXMC_NWAIT_CONFIG_BEFORE,EXMC_NWAIT_CONFIG_DURING + wrap_burst_mode: ENABLE or DISABLE + nwait_polarity: EXMC_NWAIT_POLARITY_LOW,EXMC_NWAIT_POLARITY_HIGH + burst_mode: ENABLE or DISABLE + databus_width: EXMC_NOR_DATABUS_WIDTH_8B,EXMC_NOR_DATABUS_WIDTH_16B + memory_type: EXMC_MEMORY_TYPE_SRAM,EXMC_MEMORY_TYPE_PSRAM,EXMC_MEMORY_TYPE_NOR + address_data_mux: ENABLE or DISABLE + read_write_timing: struct exmc_norsram_timing_parameter_struct set the time + write_timing: struct exmc_norsram_timing_parameter_struct set the time + \param[out] none + \retval none +*/ +void exmc_norsram_init(exmc_norsram_parameter_struct* exmc_norsram_init_struct) +{ + uint32_t snctl = 0x00000000U,sntcfg = 0x00000000U,snwtcfg = 0x00000000U; + + /* get the register value */ + snctl = EXMC_SNCTL(exmc_norsram_init_struct->norsram_region); + + /* clear relative bits */ + snctl &= ((uint32_t)~(EXMC_SNCTL_NRMUX | EXMC_SNCTL_NRTP | EXMC_SNCTL_NRW | EXMC_SNCTL_SBRSTEN | + EXMC_SNCTL_NREN | EXMC_SNCTL_NRWTPOL | EXMC_SNCTL_WRAPEN | EXMC_SNCTL_NRWTCFG | + EXMC_SNCTL_WREN | EXMC_SNCTL_NRWTEN | EXMC_SNCTL_EXMODEN | EXMC_SNCTL_ASYNCWAIT | + EXMC_SNCTL_SYNCWR )); + + snctl |= (uint32_t)(exmc_norsram_init_struct->address_data_mux << SNCTL_NRMUX_OFFSET) | + exmc_norsram_init_struct->memory_type | + exmc_norsram_init_struct->databus_width | + (exmc_norsram_init_struct->burst_mode << SNCTL_SBRSTEN_OFFSET) | + exmc_norsram_init_struct->nwait_polarity | + (exmc_norsram_init_struct->wrap_burst_mode << SNCTL_WRAPEN_OFFSET) | + exmc_norsram_init_struct->nwait_config | + (exmc_norsram_init_struct->memory_write << SNCTL_WREN_OFFSET) | + (exmc_norsram_init_struct->nwait_signal << SNCTL_NRWTEN_OFFSET) | + (exmc_norsram_init_struct->extended_mode << SNCTL_EXMODEN_OFFSET) | + (exmc_norsram_init_struct->asyn_wait << SNCTL_ASYNCWAIT_OFFSET) | + exmc_norsram_init_struct->write_mode; + + sntcfg = (uint32_t)((exmc_norsram_init_struct->read_write_timing->asyn_address_setuptime - 1U ) & EXMC_SNTCFG_ASET )| + (((exmc_norsram_init_struct->read_write_timing->asyn_address_holdtime - 1U ) << SNTCFG_AHLD_OFFSET ) & EXMC_SNTCFG_AHLD ) | + (((exmc_norsram_init_struct->read_write_timing->asyn_data_setuptime - 1U ) << SNTCFG_DSET_OFFSET ) & EXMC_SNTCFG_DSET ) | + (((exmc_norsram_init_struct->read_write_timing->bus_latency - 1U ) << SNTCFG_BUSLAT_OFFSET ) & EXMC_SNTCFG_BUSLAT )| + exmc_norsram_init_struct->read_write_timing->syn_clk_division | + exmc_norsram_init_struct->read_write_timing->syn_data_latency | + exmc_norsram_init_struct->read_write_timing->asyn_access_mode; + + /* nor flash access enable */ + if(EXMC_MEMORY_TYPE_NOR == exmc_norsram_init_struct->memory_type){ + snctl |= (uint32_t)EXMC_SNCTL_NREN; + } + + /* extended mode configure */ + if(ENABLE == exmc_norsram_init_struct->extended_mode){ + snwtcfg = (uint32_t)((exmc_norsram_init_struct->write_timing->asyn_address_setuptime - 1U) & EXMC_SNWTCFG_WASET ) | + (((exmc_norsram_init_struct->write_timing->asyn_address_holdtime -1U ) << SNWTCFG_WAHLD_OFFSET ) & EXMC_SNWTCFG_WAHLD )| + (((exmc_norsram_init_struct->write_timing->asyn_data_setuptime -1U ) << SNWTCFG_WDSET_OFFSET ) & EXMC_SNWTCFG_WDSET )| + (((exmc_norsram_init_struct->write_timing->bus_latency - 1U ) << SNWTCFG_WBUSLAT_OFFSET ) & EXMC_SNWTCFG_WBUSLAT ) | + exmc_norsram_init_struct->write_timing->asyn_access_mode; + }else{ + snwtcfg = BANK0_SNWTCFG_RESET; + } + + /* configure the registers */ + EXMC_SNCTL(exmc_norsram_init_struct->norsram_region) = snctl; + EXMC_SNTCFG(exmc_norsram_init_struct->norsram_region) = sntcfg; + EXMC_SNWTCFG(exmc_norsram_init_struct->norsram_region) = snwtcfg; +} + +/*! + \brief enable EXMC NOR/PSRAM bank region + \param[in] exmc_norsram_region: specifie the region of NOR/PSRAM bank + only one parameter can be selected which is shown as below: + \arg EXMC_BANK0_NORSRAM_REGIONx(x=0..3) + \param[out] none + \retval none +*/ +void exmc_norsram_enable(uint32_t exmc_norsram_region) +{ + EXMC_SNCTL(exmc_norsram_region) |= (uint32_t)EXMC_SNCTL_NRBKEN; +} + +/*! + \brief disable EXMC NOR/PSRAM bank region + \param[in] exmc_norsram_region: specifie the region of NOR/PSRAM Bank + only one parameter can be selected which is shown as below: + \arg EXMC_BANK0_NORSRAM_REGIONx(x=0..3) + \param[out] none + \retval none +*/ +void exmc_norsram_disable(uint32_t exmc_norsram_region) +{ + EXMC_SNCTL(exmc_norsram_region) &= ~(uint32_t)EXMC_SNCTL_NRBKEN; +} + +/*! + \brief deinitialize EXMC NAND bank + \param[in] exmc_nand_bank: select the bank of NAND + only one parameter can be selected which is shown as below: + \arg EXMC_BANKx_NAND(x=1..2) + \param[out] none + \retval none +*/ +void exmc_nand_deinit(uint32_t exmc_nand_bank) +{ + /* EXMC_BANK1_NAND or EXMC_BANK2_NAND */ + EXMC_NPCTL(exmc_nand_bank) = BANK1_2_NPCTL_RESET; + EXMC_NPINTEN(exmc_nand_bank) = BANK1_2_NPINTEN_RESET; + EXMC_NPCTCFG(exmc_nand_bank) = BANK1_2_NPCTCFG_RESET; + EXMC_NPATCFG(exmc_nand_bank) = BANK1_2_NPATCFG_RESET; +} + +/*! + \brief initialize exmc_norsram_parameter_struct with the default values + \param[in] none + \param[out] the initialized struct exmc_norsram_parameter_struct pointer + \retval none +*/ +void exmc_nand_struct_para_init(exmc_nand_parameter_struct* exmc_nand_init_struct) +{ + /* configure the structure with default values */ + exmc_nand_init_struct->nand_bank = EXMC_BANK1_NAND; + exmc_nand_init_struct->wait_feature = DISABLE; + exmc_nand_init_struct->databus_width = EXMC_NAND_DATABUS_WIDTH_8B; + exmc_nand_init_struct->ecc_logic = DISABLE; + exmc_nand_init_struct->ecc_size = EXMC_ECC_SIZE_256BYTES; + exmc_nand_init_struct->ctr_latency = 0x0U; + exmc_nand_init_struct->atr_latency = 0x0U; + exmc_nand_init_struct->common_space_timing->setuptime = 0xFCU; + exmc_nand_init_struct->common_space_timing->waittime = 0xFCU; + exmc_nand_init_struct->common_space_timing->holdtime = 0xFCU; + exmc_nand_init_struct->common_space_timing->databus_hiztime = 0xFCU; + exmc_nand_init_struct->attribute_space_timing->setuptime = 0xFCU; + exmc_nand_init_struct->attribute_space_timing->waittime = 0xFCU; + exmc_nand_init_struct->attribute_space_timing->holdtime = 0xFCU; + exmc_nand_init_struct->attribute_space_timing->databus_hiztime = 0xFCU; +} + +/*! + \brief initialize EXMC NAND bank + \param[in] exmc_nand_parameter_struct: configure the EXMC NAND parameter + nand_bank: EXMC_BANK1_NAND,EXMC_BANK2_NAND + ecc_size: EXMC_ECC_SIZE_xBYTES,x=256,512,1024,2048,4096 + atr_latency: EXMC_ALE_RE_DELAY_x_HCLK,x=1..16 + ctr_latency: EXMC_CLE_RE_DELAY_x_HCLK,x=1..16 + ecc_logic: ENABLE or DISABLE + databus_width: EXMC_NAND_DATABUS_WIDTH_8B,EXMC_NAND_DATABUS_WIDTH_16B + wait_feature: ENABLE or DISABLE + common_space_timing: struct exmc_nand_pccard_timing_parameter_struct set the time + attribute_space_timing: struct exmc_nand_pccard_timing_parameter_struct set the time + \param[out] none + \retval none +*/ +void exmc_nand_init(exmc_nand_parameter_struct* exmc_nand_init_struct) +{ + uint32_t npctl = 0x00000000U, npctcfg = 0x00000000U, npatcfg = 0x00000000U; + + npctl = (uint32_t)(exmc_nand_init_struct->wait_feature << NPCTL_NDWTEN_OFFSET)| + EXMC_NPCTL_NDTP | + exmc_nand_init_struct->databus_width | + (exmc_nand_init_struct->ecc_logic << NPCTL_ECCEN_OFFSET)| + exmc_nand_init_struct->ecc_size | + exmc_nand_init_struct->ctr_latency | + exmc_nand_init_struct->atr_latency; + + npctcfg = (uint32_t)((exmc_nand_init_struct->common_space_timing->setuptime - 1U) & EXMC_NPCTCFG_COMSET ) | + (((exmc_nand_init_struct->common_space_timing->waittime - 1U) << NPCTCFG_COMWAIT_OFFSET) & EXMC_NPCTCFG_COMWAIT ) | + ((exmc_nand_init_struct->common_space_timing->holdtime << NPCTCFG_COMHLD_OFFSET) & EXMC_NPCTCFG_COMHLD ) | + (((exmc_nand_init_struct->common_space_timing->databus_hiztime - 1U) << NPCTCFG_COMHIZ_OFFSET) & EXMC_NPCTCFG_COMHIZ ); + + npatcfg = (uint32_t)((exmc_nand_init_struct->attribute_space_timing->setuptime - 1U) & EXMC_NPATCFG_ATTSET ) | + (((exmc_nand_init_struct->attribute_space_timing->waittime - 1U) << NPATCFG_ATTWAIT_OFFSET) & EXMC_NPATCFG_ATTWAIT ) | + ((exmc_nand_init_struct->attribute_space_timing->holdtime << NPATCFG_ATTHLD_OFFSET) & EXMC_NPATCFG_ATTHLD ) | + (((exmc_nand_init_struct->attribute_space_timing->databus_hiztime -1U) << NPATCFG_ATTHIZ_OFFSET) & EXMC_NPATCFG_ATTHIZ ); + + /* EXMC_BANK1_NAND or EXMC_BANK2_NAND initialize */ + EXMC_NPCTL(exmc_nand_init_struct->nand_bank) = npctl; + EXMC_NPCTCFG(exmc_nand_init_struct->nand_bank) = npctcfg; + EXMC_NPATCFG(exmc_nand_init_struct->nand_bank) = npatcfg; +} + +/*! + \brief enable NAND bank + \param[in] exmc_nand_bank: specifie the NAND bank + only one parameter can be selected which is shown as below: + \arg EXMC_BANKx_NAND(x=1,2) + \param[out] none + \retval none +*/ +void exmc_nand_enable(uint32_t exmc_nand_bank) +{ + EXMC_NPCTL(exmc_nand_bank) |= EXMC_NPCTL_NDBKEN; +} + +/*! + \brief disable NAND bank + \param[in] exmc_nand_bank: specifie the NAND bank + only one parameter can be selected which is shown as below: + \arg EXMC_BANKx_NAND(x=1,2) + \param[out] none + \retval none +*/ +void exmc_nand_disable(uint32_t exmc_nand_bank) +{ + EXMC_NPCTL(exmc_nand_bank) &= (~EXMC_NPCTL_NDBKEN); +} + +/*! + \brief deinitialize EXMC PC card bank + \param[in] none + \param[out] none + \retval none +*/ +void exmc_pccard_deinit(void) +{ + /* EXMC_BANK3_PCCARD */ + EXMC_NPCTL3 = BANK3_NPCTL_RESET; + EXMC_NPINTEN3 = BANK3_NPINTEN_RESET; + EXMC_NPCTCFG3 = BANK3_NPCTCFG_RESET; + EXMC_NPATCFG3 = BANK3_NPATCFG_RESET; + EXMC_PIOTCFG3 = BANK3_PIOTCFG3_RESET; +} + +/*! + \brief initialize exmc_pccard_parameter_struct parameter with the default values + \param[in] none + \param[out] the initialized struct exmc_pccard_parameter_struct pointer + \retval none +*/ +void exmc_pccard_struct_para_init(exmc_pccard_parameter_struct* exmc_pccard_init_struct) +{ + /* configure the structure with default values */ + exmc_pccard_init_struct->wait_feature = DISABLE; + exmc_pccard_init_struct->ctr_latency = 0x0U; + exmc_pccard_init_struct->atr_latency = 0x0U; + exmc_pccard_init_struct->common_space_timing->setuptime = 0xFCU; + exmc_pccard_init_struct->common_space_timing->waittime = 0xFCU; + exmc_pccard_init_struct->common_space_timing->holdtime = 0xFCU; + exmc_pccard_init_struct->common_space_timing->databus_hiztime = 0xFCU; + exmc_pccard_init_struct->attribute_space_timing->setuptime = 0xFCU; + exmc_pccard_init_struct->attribute_space_timing->waittime = 0xFCU; + exmc_pccard_init_struct->attribute_space_timing->holdtime = 0xFCU; + exmc_pccard_init_struct->attribute_space_timing->databus_hiztime = 0xFCU; + exmc_pccard_init_struct->io_space_timing->setuptime = 0xFCU; + exmc_pccard_init_struct->io_space_timing->waittime = 0xFCU; + exmc_pccard_init_struct->io_space_timing->holdtime = 0xFCU; + exmc_pccard_init_struct->io_space_timing->databus_hiztime = 0xFCU; +} + +/*! + \brief initialize EXMC PC card bank + \param[in] exmc_pccard_parameter_struct: configure the EXMC NAND parameter + atr_latency: EXMC_ALE_RE_DELAY_x_HCLK,x=1..16 + ctr_latency: EXMC_CLE_RE_DELAY_x_HCLK,x=1..16 + wait_feature: ENABLE or DISABLE + common_space_timing: struct exmc_nand_pccard_timing_parameter_struct set the time + attribute_space_timing: struct exmc_nand_pccard_timing_parameter_struct set the time + io_space_timing: exmc_nand_pccard_timing_parameter_struct set the time + \param[out] none + \retval none +*/ +void exmc_pccard_init(exmc_pccard_parameter_struct* exmc_pccard_init_struct) +{ + /* configure the EXMC bank3 PC card control register */ + EXMC_NPCTL3 = (uint32_t)(exmc_pccard_init_struct->wait_feature << NPCTL_NDWTEN_OFFSET) | + EXMC_NAND_DATABUS_WIDTH_16B | + exmc_pccard_init_struct->ctr_latency | + exmc_pccard_init_struct->atr_latency ; + + /* configure the EXMC bank3 PC card common space timing configuration register */ + EXMC_NPCTCFG3 = (uint32_t)((exmc_pccard_init_struct->common_space_timing->setuptime - 1U)& EXMC_NPCTCFG_COMSET ) | + (((exmc_pccard_init_struct->common_space_timing->waittime - 1U) << NPCTCFG_COMWAIT_OFFSET) & EXMC_NPCTCFG_COMWAIT ) | + ((exmc_pccard_init_struct->common_space_timing->holdtime << NPCTCFG_COMHLD_OFFSET) & EXMC_NPCTCFG_COMHLD ) | + (((exmc_pccard_init_struct->common_space_timing->databus_hiztime - 1U) << NPCTCFG_COMHIZ_OFFSET) & EXMC_NPCTCFG_COMHIZ ); + + /* configure the EXMC bank3 PC card attribute space timing configuration register */ + EXMC_NPATCFG3 = (uint32_t)((exmc_pccard_init_struct->attribute_space_timing->setuptime - 1U) & EXMC_NPATCFG_ATTSET ) | + (((exmc_pccard_init_struct->attribute_space_timing->waittime - 1U) << NPATCFG_ATTWAIT_OFFSET) & EXMC_NPATCFG_ATTWAIT ) | + ((exmc_pccard_init_struct->attribute_space_timing->holdtime << NPATCFG_ATTHLD_OFFSET) & EXMC_NPATCFG_ATTHLD )| + (((exmc_pccard_init_struct->attribute_space_timing->databus_hiztime -1U) << NPATCFG_ATTHIZ_OFFSET) & EXMC_NPATCFG_ATTHIZ ); + + /* configure the EXMC bank3 PC card io space timing configuration register */ + EXMC_PIOTCFG3 = (uint32_t)((exmc_pccard_init_struct->io_space_timing->setuptime - 1U) & EXMC_PIOTCFG3_IOSET ) | + (((exmc_pccard_init_struct->io_space_timing->waittime - 1U) << PIOTCFG_IOWAIT_OFFSET) & EXMC_PIOTCFG3_IOWAIT ) | + ((exmc_pccard_init_struct->io_space_timing->holdtime << PIOTCFG_IOHLD_OFFSET) & EXMC_PIOTCFG3_IOHLD )| + ((exmc_pccard_init_struct->io_space_timing->databus_hiztime << PIOTCFG_IOHIZ_OFFSET) & EXMC_PIOTCFG3_IOHIZ ); +} + +/*! + \brief enable PC Card Bank + \param[in] none + \param[out] none + \retval none +*/ +void exmc_pccard_enable(void) +{ + EXMC_NPCTL3 |= EXMC_NPCTL_NDBKEN; +} + +/*! + \brief disable PC Card Bank + \param[in] none + \param[out] none + \retval none +*/ +void exmc_pccard_disable(void) +{ + EXMC_NPCTL3 &= (~EXMC_NPCTL_NDBKEN); +} + +/*! + \brief configure CRAM page size + \param[in] exmc_norsram_region: specifie the region of NOR/PSRAM bank + only one parameter can be selected which is shown as below: + \arg EXMC_BANK0_NORSRAM_REGIONx(x=0..3) + \param[in] page_size: CRAM page size + only one parameter can be selected which is shown as below: + \arg EXMC_CRAM_AUTO_SPLIT: the clock is generated only during synchronous access + \arg EXMC_CRAM_PAGE_SIZE_128_BYTES: page size is 128 bytes + \arg EXMC_CRAM_PAGE_SIZE_256_BYTES: page size is 256 bytes + \arg EXMC_CRAM_PAGE_SIZE_512_BYTES: page size is 512 bytes + \arg EXMC_CRAM_PAGE_SIZE_1024_BYTES: page size is 1024 bytes + \param[out] none + \retval none +*/ +void exmc_norsram_page_size_config(uint32_t exmc_norsram_region, uint32_t page_size) +{ + /* reset the bits */ + EXMC_SNCTL(exmc_norsram_region) &= ~EXMC_SNCTL_CPS; + + /* set the CPS bits */ + EXMC_SNCTL(exmc_norsram_region) |= page_size; +} + +/*! + \brief enable or disable the EXMC NAND ECC function + \param[in] exmc_nand_bank: specifie the NAND bank + only one parameter can be selected which is shown as below: + \arg EXMC_BANKx_NAND(x=1,2) + \param[in] newvalue: ENABLE or DISABLE + \param[out] none + \retval none +*/ +void exmc_nand_ecc_config(uint32_t exmc_nand_bank, ControlStatus newvalue) +{ + if (ENABLE == newvalue){ + /* enable the selected NAND bank ECC function */ + EXMC_NPCTL(exmc_nand_bank) |= EXMC_NPCTL_ECCEN; + }else{ + /* disable the selected NAND bank ECC function */ + EXMC_NPCTL(exmc_nand_bank) &= (~EXMC_NPCTL_ECCEN); + } +} + +/*! + \brief get the EXMC ECC value + \param[in] exmc_nand_bank: specifie the NAND bank + only one parameter can be selected which is shown as below: + \arg EXMC_BANKx_NAND(x=1,2) + \param[out] none + \retval the error correction code(ECC) value +*/ +uint32_t exmc_ecc_get(uint32_t exmc_nand_bank) +{ + return (EXMC_NECC(exmc_nand_bank)); +} + +/*! + \brief enable EXMC interrupt + \param[in] exmc_bank: specifies the NAND bank,PC card bank + only one parameter can be selected which is shown as below: + \arg EXMC_BANK1_NAND: the NAND bank1 + \arg EXMC_BANK2_NAND: the NAND bank2 + \arg EXMC_BANK3_PCCARD: the PC card bank + \param[in] interrupt: EXMC interrupt flag + only one parameter can be selected which are shown as below: + \arg EXMC_NAND_PCCARD_INT_FLAG_RISE: rising edge interrupt and flag + \arg EXMC_NAND_PCCARD_INT_FLAG_LEVEL: high-level interrupt and flag + \arg EXMC_NAND_PCCARD_INT_FLAG_FALL: falling edge interrupt and flag + \param[out] none + \retval none +*/ +void exmc_interrupt_enable(uint32_t exmc_bank,uint32_t interrupt) +{ + /* NAND bank1,bank2 or PC card bank3 */ + EXMC_NPINTEN(exmc_bank) |= interrupt; +} + +/*! + \brief disable EXMC interrupt + \param[in] exmc_bank: specifies the NAND bank , PC card bank + only one parameter can be selected which is shown as below: + \arg EXMC_BANK1_NAND: the NAND bank1 + \arg EXMC_BANK2_NAND: the NAND bank2 + \arg EXMC_BANK3_PCCARD: the PC card bank + \param[in] interrupt: EXMC interrupt flag + only one parameter can be selected which are shown as below: + \arg EXMC_NAND_PCCARD_INT_FLAG_RISE: rising edge interrupt and flag + \arg EXMC_NAND_PCCARD_INT_FLAG_LEVEL: high-level interrupt and flag + \arg EXMC_NAND_PCCARD_INT_FLAG_FALL: falling edge interrupt and flag + \param[out] none + \retval none +*/ +void exmc_interrupt_disable(uint32_t exmc_bank,uint32_t interrupt) +{ + /* NAND bank1,bank2 or PC card bank3 */ + EXMC_NPINTEN(exmc_bank) &= (~interrupt); +} + +/*! + \brief get EXMC flag status + \param[in] exmc_bank: specifies the NAND bank , PC card bank + only one parameter can be selected which is shown as below: + \arg EXMC_BANK1_NAND: the NAND bank1 + \arg EXMC_BANK2_NAND: the NAND bank2 + \arg EXMC_BANK3_PCCARD: the PC Card bank + \param[in] flag: EXMC status and flag + only one parameter can be selected which are shown as below: + \arg EXMC_NAND_PCCARD_FLAG_RISE: interrupt rising edge status + \arg EXMC_NAND_PCCARD_FLAG_LEVEL: interrupt high-level status + \arg EXMC_NAND_PCCARD_FLAG_FALL: interrupt falling edge status + \arg EXMC_NAND_PCCARD_FLAG_FIFOE: FIFO empty flag + \param[out] none + \retval FlagStatus: SET or RESET +*/ +FlagStatus exmc_flag_get(uint32_t exmc_bank,uint32_t flag) +{ + uint32_t status = 0x00000000U; + + /* NAND bank1,bank2 or PC card bank3 */ + status = EXMC_NPINTEN(exmc_bank); + + if ((status & flag) != (uint32_t)flag ){ + /* flag is reset */ + return RESET; + }else{ + /* flag is set */ + return SET; + } +} + +/*! + \brief clear EXMC flag status + \param[in] exmc_bank: specifie the NAND bank , PCCARD bank + only one parameter can be selected which is shown as below: + \arg EXMC_BANK1_NAND: the NAND bank1 + \arg EXMC_BANK2_NAND: the NAND bank2 + \arg EXMC_BANK3_PCCARD: the PC card bank + \param[in] flag: EXMC status and flag + only one parameter can be selected which are shown as below: + \arg EXMC_NAND_PCCARD_FLAG_RISE: interrupt rising edge status + \arg EXMC_NAND_PCCARD_FLAG_LEVEL: interrupt high-level status + \arg EXMC_NAND_PCCARD_FLAG_FALL: interrupt falling edge status + \arg EXMC_NAND_PCCARD_FLAG_FIFOE: FIFO empty flag + \param[out] none + \retval none +*/ +void exmc_flag_clear(uint32_t exmc_bank,uint32_t flag) +{ + /* NAND bank1,bank2 or PC card bank3 */ + EXMC_NPINTEN(exmc_bank) &= (~flag); +} + +/*! + \brief get EXMC interrupt flag + \param[in] exmc_bank: specifies the NAND bank , PC card bank + only one parameter can be selected which is shown as below: + \arg EXMC_BANK1_NAND: the NAND bank1 + \arg EXMC_BANK2_NAND: the NAND bank2 + \arg EXMC_BANK3_PCCARD: the PC card bank + \param[in] interrupt: EXMC interrupt flag + only one parameter can be selected which are shown as below: + \arg EXMC_NAND_PCCARD_INT_FLAG_RISE: rising edge interrupt and flag + \arg EXMC_NAND_PCCARD_INT_FLAG_LEVEL: high-level interrupt and flag + \arg EXMC_NAND_PCCARD_INT_FLAG_FALL: falling edge interrupt and flag + \param[out] none + \retval FlagStatus: SET or RESET +*/ +FlagStatus exmc_interrupt_flag_get(uint32_t exmc_bank,uint32_t interrupt) +{ + uint32_t status = 0x00000000U,interrupt_enable = 0x00000000U,interrupt_state = 0x00000000U; + + /* NAND bank1,bank2 or PC card bank3 */ + status = EXMC_NPINTEN(exmc_bank); + interrupt_state = (status & (interrupt >> INTEN_INTS_OFFSET)); + + interrupt_enable = (status & interrupt); + + if ((interrupt_enable) && (interrupt_state)){ + /* interrupt flag is set */ + return SET; + }else{ + /* interrupt flag is reset */ + return RESET; + } +} + +/*! + \brief clear EXMC interrupt flag + \param[in] exmc_bank: specifies the NAND bank , PC card bank + only one parameter can be selected which is shown as below: + \arg EXMC_BANK1_NAND: the NAND bank1 + \arg EXMC_BANK2_NAND: the NAND bank2 + \arg EXMC_BANK3_PCCARD: the PC card bank + \param[in] interrupt: EXMC interrupt flag + only one parameter can be selected which are shown as below: + \arg EXMC_NAND_PCCARD_INT_FLAG_RISE: rising edge interrupt and flag + \arg EXMC_NAND_PCCARD_INT_FLAG_LEVEL: high-level interrupt and flag + \arg EXMC_NAND_PCCARD_INT_FLAG_FALL: falling edge interrupt and flag + \param[out] none + \retval none +*/ +void exmc_interrupt_flag_clear(uint32_t exmc_bank,uint32_t interrupt) +{ + /* NAND bank1,bank2 or PC card bank3 */ + EXMC_NPINTEN(exmc_bank) &= ~(interrupt >> INTEN_INTS_OFFSET); +} diff --git a/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_standard_peripheral/Source/gd32f30x_exti.c b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_standard_peripheral/Source/gd32f30x_exti.c new file mode 100644 index 0000000000..4708a15627 --- /dev/null +++ b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_standard_peripheral/Source/gd32f30x_exti.c @@ -0,0 +1,253 @@ +/*! + \file gd32f30x_exti.c + \brief EXTI driver + + \version 2017-02-10, V1.0.0, firmware for GD32F30x + \version 2018-10-10, V1.1.0, firmware for GD32F30x + \version 2018-12-25, V2.0.0, firmware for GD32F30x + \version 2020-09-30, V2.1.0, firmware for GD32F30x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "gd32f30x_exti.h" + +/*! + \brief deinitialize the EXTI + \param[in] none + \param[out] none + \retval none +*/ +void exti_deinit(void) +{ + /* reset the value of all the EXTI registers */ + EXTI_INTEN = (uint32_t)0x00000000U; + EXTI_EVEN = (uint32_t)0x00000000U; + EXTI_RTEN = (uint32_t)0x00000000U; + EXTI_FTEN = (uint32_t)0x00000000U; + EXTI_SWIEV = (uint32_t)0x00000000U; +} + +/*! + \brief initialize the EXTI + \param[in] linex: EXTI line number, refer to exti_line_enum + only one parameter can be selected which is shown as below: + \arg EXTI_x (x=0..19): EXTI line x + \param[in] mode: interrupt or event mode, refer to exti_mode_enum + only one parameter can be selected which is shown as below: + \arg EXTI_INTERRUPT: interrupt mode + \arg EXTI_EVENT: event mode + \param[in] trig_type: interrupt trigger type, refer to exti_trig_type_enum + only one parameter can be selected which is shown as below: + \arg EXTI_TRIG_RISING: rising edge trigger + \arg EXTI_TRIG_FALLING: falling trigger + \arg EXTI_TRIG_BOTH: rising and falling trigger + \param[out] none + \retval none +*/ +void exti_init(exti_line_enum linex, exti_mode_enum mode, exti_trig_type_enum trig_type) +{ + /* reset the EXTI line x */ + EXTI_INTEN &= ~(uint32_t)linex; + EXTI_EVEN &= ~(uint32_t)linex; + EXTI_RTEN &= ~(uint32_t)linex; + EXTI_FTEN &= ~(uint32_t)linex; + + /* set the EXTI mode and enable the interrupts or events from EXTI line x */ + switch(mode){ + case EXTI_INTERRUPT: + EXTI_INTEN |= (uint32_t)linex; + break; + case EXTI_EVENT: + EXTI_EVEN |= (uint32_t)linex; + break; + default: + break; + } + + /* set the EXTI trigger type */ + switch(trig_type){ + case EXTI_TRIG_RISING: + EXTI_RTEN |= (uint32_t)linex; + EXTI_FTEN &= ~(uint32_t)linex; + break; + case EXTI_TRIG_FALLING: + EXTI_RTEN &= ~(uint32_t)linex; + EXTI_FTEN |= (uint32_t)linex; + break; + case EXTI_TRIG_BOTH: + EXTI_RTEN |= (uint32_t)linex; + EXTI_FTEN |= (uint32_t)linex; + break; + default: + break; + } +} + +/*! + \brief enable the interrupts from EXTI line x + \param[in] linex: EXTI line number, refer to exti_line_enum + only one parameter can be selected which is shown as below: + \arg EXTI_x (x=0..19): EXTI line x + \param[out] none + \retval none +*/ +void exti_interrupt_enable(exti_line_enum linex) +{ + EXTI_INTEN |= (uint32_t)linex; +} + +/*! + \brief enable the events from EXTI line x + \param[in] linex: EXTI line number, refer to exti_line_enum + only one parameter can be selected which is shown as below: + \arg EXTI_x (x=0..19): EXTI line x + \param[out] none + \retval none +*/ +void exti_event_enable(exti_line_enum linex) +{ + EXTI_EVEN |= (uint32_t)linex; +} + +/*! + \brief disable the interrupt from EXTI line x + \param[in] linex: EXTI line number, refer to exti_line_enum + only one parameter can be selected which is shown as below: + \arg EXTI_x (x=0..19): EXTI line x + \param[out] none + \retval none +*/ +void exti_interrupt_disable(exti_line_enum linex) +{ + EXTI_INTEN &= ~(uint32_t)linex; +} + +/*! + \brief disable the events from EXTI line x + \param[in] linex: EXTI line number, refer to exti_line_enum + only one parameter can be selected which is shown as below: + \arg EXTI_x (x=0..19): EXTI line x + \param[out] none + \retval none +*/ +void exti_event_disable(exti_line_enum linex) +{ + EXTI_EVEN &= ~(uint32_t)linex; +} + +/*! + \brief get EXTI lines flag + \param[in] linex: EXTI line number, refer to exti_line_enum + only one parameter can be selected which is shown as below: + \arg EXTI_x (x=0..19): EXTI line x + \param[out] none + \retval FlagStatus: status of flag (RESET or SET) +*/ +FlagStatus exti_flag_get(exti_line_enum linex) +{ + if(RESET != (EXTI_PD & (uint32_t)linex)){ + return SET; + }else{ + return RESET; + } +} + +/*! + \brief clear EXTI lines pending flag + \param[in] linex: EXTI line number, refer to exti_line_enum + only one parameter can be selected which is shown as below: + \arg EXTI_x (x=0..19): EXTI line x + \param[out] none + \retval none +*/ +void exti_flag_clear(exti_line_enum linex) +{ + EXTI_PD = (uint32_t)linex; +} + +/*! + \brief get EXTI lines flag when the interrupt flag is set + \param[in] linex: EXTI line number, refer to exti_line_enum + only one parameter can be selected which is shown as below: + \arg EXTI_x (x=0..19): EXTI line x + \param[out] none + \retval FlagStatus: status of flag (RESET or SET) +*/ +FlagStatus exti_interrupt_flag_get(exti_line_enum linex) +{ + uint32_t flag_left, flag_right; + + flag_left = EXTI_PD & (uint32_t)linex; + flag_right = EXTI_INTEN & (uint32_t)linex; + + if((RESET != flag_left) && (RESET != flag_right)){ + return SET; + }else{ + return RESET; + } +} + +/*! + \brief clear EXTI lines pending flag + \param[in] linex: EXTI line number, refer to exti_line_enum + only one parameter can be selected which is shown as below: + \arg EXTI_x (x=0..19): EXTI line x + \param[out] none + \retval none +*/ +void exti_interrupt_flag_clear(exti_line_enum linex) +{ + EXTI_PD = (uint32_t)linex; +} + +/*! + \brief enable EXTI software interrupt event + \param[in] linex: EXTI line number, refer to exti_line_enum + only one parameter can be selected which is shown as below: + \arg EXTI_x (x=0..19): EXTI line x + \param[out] none + \retval none +*/ +void exti_software_interrupt_enable(exti_line_enum linex) +{ + EXTI_SWIEV |= (uint32_t)linex; +} + +/*! + \brief disable EXTI software interrupt event + \param[in] linex: EXTI line number, refer to exti_line_enum + only one parameter can be selected which is shown as below: + \arg EXTI_x (x=0..19): EXTI line x + \param[out] none + \retval none +*/ +void exti_software_interrupt_disable(exti_line_enum linex) +{ + EXTI_SWIEV &= ~(uint32_t)linex; +} diff --git a/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_standard_peripheral/Source/gd32f30x_fmc.c b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_standard_peripheral/Source/gd32f30x_fmc.c new file mode 100644 index 0000000000..d3b1a12256 --- /dev/null +++ b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_standard_peripheral/Source/gd32f30x_fmc.c @@ -0,0 +1,1009 @@ +/*! + \file gd32f30x_fmc.c + \brief FMC driver + + \version 2017-02-10, V1.0.0, firmware for GD32F30x + \version 2018-10-10, V1.1.0, firmware for GD32F30x + \version 2018-12-25, V2.0.0, firmware for GD32F30x + \version 2020-09-30, V2.1.0, firmware for GD32F30x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + + +#include "gd32f30x_fmc.h" + +/*! + \brief set the wait state counter value + \param[in] wscnt:wait state counter value + \arg WS_WSCNT_0: FMC 0 wait + \arg WS_WSCNT_1: FMC 1 wait + \arg WS_WSCNT_2: FMC 2 wait + \param[out] none + \retval none +*/ +void fmc_wscnt_set(uint32_t wscnt) +{ + uint32_t reg; + + reg = FMC_WS; + /* set the wait state counter value */ + reg &= ~FMC_WS_WSCNT; + FMC_WS = (reg | wscnt); +} + +/*! + \brief unlock the main FMC operation + \param[in] none + \param[out] none + \retval none +*/ +void fmc_unlock(void) +{ + if((RESET != (FMC_CTL0 & FMC_CTL0_LK))){ + /* write the FMC unlock key */ + FMC_KEY0 = UNLOCK_KEY0; + FMC_KEY0 = UNLOCK_KEY1; + } + if(FMC_BANK0_SIZE < FMC_SIZE){ + /* write the FMC unlock key */ + if(RESET != (FMC_CTL1 & FMC_CTL1_LK)){ + FMC_KEY1 = UNLOCK_KEY0; + FMC_KEY1 = UNLOCK_KEY1; + } + } +} + +/*! + \brief unlock the FMC bank0 operation + this function can be used for all GD32F30x devices. + for GD32F30x with flash more than 512KB, this function unlocks bank0. + for GD32F30x with flash no more than 512KB and it is equivalent to fmc_unlock function. + \param[in] none + \param[out] none + \retval none +*/ +void fmc_bank0_unlock(void) +{ + if((RESET != (FMC_CTL0 & FMC_CTL0_LK))){ + /* write the FMC unlock key */ + FMC_KEY0 = UNLOCK_KEY0; + FMC_KEY0 = UNLOCK_KEY1; + } +} + +/*! + \brief unlock the FMC bank1 operation + this function can be used for GD32F30x with flash more than 512KB. + \param[in] none + \param[out] none + \retval none +*/ +void fmc_bank1_unlock(void) +{ + if((RESET != (FMC_CTL1 & FMC_CTL1_LK))){ + /* write the FMC unlock key */ + FMC_KEY1 = UNLOCK_KEY0; + FMC_KEY1 = UNLOCK_KEY1; + } +} + +/*! + \brief lock the main FMC operation + \param[in] none + \param[out] none + \retval none +*/ +void fmc_lock(void) +{ + /* set the LK bit */ + FMC_CTL0 |= FMC_CTL0_LK; + + if(FMC_BANK0_SIZE < FMC_SIZE){ + /* set the LK bit */ + FMC_CTL1 |= FMC_CTL1_LK; + } +} + +/*! + \brief lock the FMC bank0 operation + this function can be used for all GD32F30X devices. + for GD32F30x with flash more than 512KB, this function locks bank0. + for GD32F30x with flash no more than 512KB and it is equivalent to fmc_lock function. + \param[in] none + \param[out] none + \retval none +*/ +void fmc_bank0_lock(void) +{ + /* set the LK bit*/ + FMC_CTL0 |= FMC_CTL0_LK; +} + +/*! + \brief lock the FMC bank1 operation + this function can be used for GD32F30x with flash more than 512KB. + \param[in] none + \param[out] none + \retval none +*/ +void fmc_bank1_lock(void) +{ + /* set the LK bit*/ + FMC_CTL1 |= FMC_CTL1_LK; +} + +/*! + \brief erase page + \param[in] page_address: the page address to be erased. + \param[out] none + \retval state of FMC, refer to fmc_state_enum +*/ +fmc_state_enum fmc_page_erase(uint32_t page_address) +{ + fmc_state_enum fmc_state; + + if(FMC_BANK0_SIZE < FMC_SIZE){ + if(FMC_BANK0_END_ADDRESS > page_address){ + fmc_state = fmc_bank0_ready_wait(FMC_TIMEOUT_COUNT); + /* if the last operation is completed, start page erase */ + if(FMC_READY == fmc_state){ + FMC_CTL0 |= FMC_CTL0_PER; + FMC_ADDR0 = page_address; + FMC_CTL0 |= FMC_CTL0_START; + /* wait for the FMC ready */ + fmc_state = fmc_bank0_ready_wait(FMC_TIMEOUT_COUNT); + /* reset the PER bit */ + FMC_CTL0 &= ~FMC_CTL0_PER; + } + }else{ + /* wait for the FMC ready */ + fmc_state = fmc_bank1_ready_wait(FMC_TIMEOUT_COUNT); + /* if the last operation is completed, start page erase */ + if(FMC_READY == fmc_state){ + FMC_CTL1 |= FMC_CTL1_PER; + FMC_ADDR1 = page_address; + if(FMC_OBSTAT & FMC_OBSTAT_SPC){ + FMC_ADDR0 = page_address; + } + FMC_CTL1 |= FMC_CTL1_START; + /* wait for the FMC ready */ + fmc_state = fmc_bank1_ready_wait(FMC_TIMEOUT_COUNT); + /* reset the PER bit */ + FMC_CTL1 &= ~FMC_CTL1_PER; + } + } + }else{ + fmc_state = fmc_bank0_ready_wait(FMC_TIMEOUT_COUNT); + /* if the last operation is completed, start page erase */ + if(FMC_READY == fmc_state){ + FMC_CTL0 |= FMC_CTL0_PER; + FMC_ADDR0 = page_address; + FMC_CTL0 |= FMC_CTL0_START; + /* wait for the FMC ready */ + fmc_state = fmc_bank0_ready_wait(FMC_TIMEOUT_COUNT); + /* reset the PER bit */ + FMC_CTL0 &= ~FMC_CTL0_PER; + } + } + /* return the FMC state */ + return fmc_state; +} + +/*! + \brief erase whole chip + \param[in] none + \param[out] none + \retval state of FMC, refer to fmc_state_enum +*/ +fmc_state_enum fmc_mass_erase(void) +{ + fmc_state_enum fmc_state; + if(FMC_BANK0_SIZE < FMC_SIZE){ + /* wait for the FMC ready */ + fmc_state = fmc_bank0_ready_wait(FMC_TIMEOUT_COUNT); + if(FMC_READY == fmc_state){ + /* start whole chip erase */ + FMC_CTL0 |= FMC_CTL0_MER; + FMC_CTL0 |= FMC_CTL0_START; + /* wait for the FMC ready */ + fmc_state = fmc_bank0_ready_wait(FMC_TIMEOUT_COUNT); + if(FMC_READY != fmc_state){ + return fmc_state; + } + /* reset the MER bit */ + FMC_CTL0 &= ~FMC_CTL0_MER; + } + fmc_state = fmc_bank1_ready_wait(FMC_TIMEOUT_COUNT); + if(FMC_READY == fmc_state){ + /* start whole chip erase */ + FMC_CTL1 |= FMC_CTL1_MER; + FMC_CTL1 |= FMC_CTL1_START; + /* wait for the FMC ready */ + fmc_state = fmc_bank1_ready_wait(FMC_TIMEOUT_COUNT); + /* reset the MER bit */ + FMC_CTL1 &= ~FMC_CTL1_MER; + } + }else{ + fmc_state = fmc_bank0_ready_wait(FMC_TIMEOUT_COUNT); + if(FMC_READY == fmc_state){ + /* start whole chip erase */ + FMC_CTL0 |= FMC_CTL0_MER; + FMC_CTL0 |= FMC_CTL0_START; + /* wait for the FMC ready */ + fmc_state = fmc_bank0_ready_wait(FMC_TIMEOUT_COUNT); + /* reset the MER bit */ + FMC_CTL0 &= ~FMC_CTL0_MER; + } + } + /* return the FMC state */ + return fmc_state; +} + +/*! + \brief erase bank0 + \param[in] none + \param[out] none + \retval state of FMC, refer to fmc_state_enum +*/ +fmc_state_enum fmc_bank0_erase(void) +{ + fmc_state_enum fmc_state = FMC_READY; + /* wait for the FMC ready */ + fmc_state = fmc_bank0_ready_wait(FMC_TIMEOUT_COUNT); + + if(FMC_READY == fmc_state){ + /* start FMC bank0 erase */ + FMC_CTL0 |= FMC_CTL0_MER; + FMC_CTL0 |= FMC_CTL0_START; + /* wait for the FMC ready */ + fmc_state = fmc_bank0_ready_wait(FMC_TIMEOUT_COUNT); + /* reset the MER bit */ + FMC_CTL0 &= ~FMC_CTL0_MER; + } + /* return the fmc state */ + return fmc_state; +} + +/*! + \brief erase bank1 + \param[in] none + \param[out] none + \retval state of FMC, refer to fmc_state_enum +*/ +fmc_state_enum fmc_bank1_erase(void) +{ + fmc_state_enum fmc_state = FMC_READY; + /* wait for the FMC ready */ + fmc_state = fmc_bank1_ready_wait(FMC_TIMEOUT_COUNT); + + if(FMC_READY == fmc_state){ + /* start FMC bank1 erase */ + FMC_CTL1 |= FMC_CTL1_MER; + FMC_CTL1 |= FMC_CTL1_START; + /* wait for the FMC ready */ + fmc_state = fmc_bank1_ready_wait(FMC_TIMEOUT_COUNT); + /* reset the MER bit */ + FMC_CTL1 &= ~FMC_CTL1_MER; + } + /* return the fmc state */ + return fmc_state; +} + +/*! + \brief program a word at the corresponding address + \param[in] address: address to program + \param[in] data: word to program + \param[out] none + \retval state of FMC, refer to fmc_state_enum +*/ +fmc_state_enum fmc_word_program(uint32_t address, uint32_t data) +{ + fmc_state_enum fmc_state = FMC_READY; + if(FMC_BANK0_SIZE < FMC_SIZE){ + if(FMC_BANK0_END_ADDRESS > address){ + fmc_state = fmc_bank0_ready_wait(FMC_TIMEOUT_COUNT); + + if(FMC_READY == fmc_state){ + /* set the PG bit to start program */ + FMC_CTL0 |= FMC_CTL0_PG; + REG32(address) = data; + /* wait for the FMC ready */ + fmc_state = fmc_bank0_ready_wait(FMC_TIMEOUT_COUNT); + /* reset the PG bit */ + FMC_CTL0 &= ~FMC_CTL0_PG; + } + }else{ + fmc_state = fmc_bank1_ready_wait(FMC_TIMEOUT_COUNT); + + if(FMC_READY == fmc_state){ + /* set the PG bit to start program */ + FMC_CTL1 |= FMC_CTL1_PG; + REG32(address) = data; + /* wait for the FMC ready */ + fmc_state = fmc_bank1_ready_wait(FMC_TIMEOUT_COUNT); + /* reset the PG bit */ + FMC_CTL1 &= ~FMC_CTL1_PG; + } + } + }else{ + fmc_state = fmc_bank0_ready_wait(FMC_TIMEOUT_COUNT); + + if(FMC_READY == fmc_state){ + /* set the PG bit to start program */ + FMC_CTL0 |= FMC_CTL0_PG; + REG32(address) = data; + /* wait for the FMC ready */ + fmc_state = fmc_bank0_ready_wait(FMC_TIMEOUT_COUNT); + /* reset the PG bit */ + FMC_CTL0 &= ~FMC_CTL0_PG; + } + } + /* return the FMC state */ + return fmc_state; +} + +/*! + \brief program a half word at the corresponding address + \param[in] address: address to program + \param[in] data: halfword to program + \param[out] none + \retval state of FMC, refer to fmc_state_enum +*/ +fmc_state_enum fmc_halfword_program(uint32_t address, uint16_t data) +{ + fmc_state_enum fmc_state = FMC_READY; + if(FMC_BANK0_SIZE < FMC_SIZE){ + if(FMC_BANK0_END_ADDRESS > address){ + fmc_state = fmc_bank0_ready_wait(FMC_TIMEOUT_COUNT); + + if(FMC_READY == fmc_state){ + /* set the PG bit to start program */ + FMC_CTL0 |= FMC_CTL0_PG; + REG16(address) = data; + /* wait for the FMC ready */ + fmc_state = fmc_bank0_ready_wait(FMC_TIMEOUT_COUNT); + /* reset the PG bit */ + FMC_CTL0 &= ~FMC_CTL0_PG; + } + }else{ + fmc_state = fmc_bank1_ready_wait(FMC_TIMEOUT_COUNT); + + if(FMC_READY == fmc_state){ + /* set the PG bit to start program */ + FMC_CTL1 |= FMC_CTL1_PG; + REG16(address) = data; + /* wait for the FMC ready */ + fmc_state = fmc_bank1_ready_wait(FMC_TIMEOUT_COUNT); + /* reset the PG bit */ + FMC_CTL1 &= ~FMC_CTL1_PG; + } + } + }else{ + fmc_state = fmc_bank0_ready_wait(FMC_TIMEOUT_COUNT); + + if(FMC_READY == fmc_state){ + /* set the PG bit to start program */ + FMC_CTL0 |= FMC_CTL0_PG; + REG16(address) = data; + /* wait for the FMC ready */ + fmc_state = fmc_bank0_ready_wait(FMC_TIMEOUT_COUNT); + /* reset the PG bit */ + FMC_CTL0 &= ~FMC_CTL0_PG; + } + } + /* return the FMC state */ + return fmc_state; +} + +/*! + \brief program a word at the corresponding address without erasing + \param[in] address: address to program + \param[in] data: word to program + \param[out] none + \retval fmc_state +*/ +fmc_state_enum fmc_word_reprogram(uint32_t address, uint32_t data) +{ + fmc_state_enum fmc_state = FMC_READY; + if(FMC_BANK0_SIZE < FMC_SIZE){ + if(FMC_BANK0_END_ADDRESS > address){ + fmc_state = fmc_bank0_ready_wait(FMC_TIMEOUT_COUNT); + FMC_WSEN |= FMC_WSEN_BPEN; + if(FMC_READY == fmc_state){ + /* set the PG bit to start program */ + FMC_CTL0 |= FMC_CTL0_PG; + REG32(address) = data; + /* wait for the FMC ready */ + fmc_state = fmc_bank0_ready_wait(FMC_TIMEOUT_COUNT); + /* reset the PG bit */ + FMC_CTL0 &= ~FMC_CTL0_PG; + } + }else{ + fmc_state = fmc_bank1_ready_wait(FMC_TIMEOUT_COUNT); + FMC_WSEN |= FMC_WSEN_BPEN; + if(FMC_READY == fmc_state){ + /* set the PG bit to start program */ + FMC_CTL1 |= FMC_CTL1_PG; + REG32(address) = data; + /* wait for the FMC ready */ + fmc_state = fmc_bank1_ready_wait(FMC_TIMEOUT_COUNT); + /* reset the PG bit */ + FMC_CTL1 &= ~FMC_CTL1_PG; + } + } + }else{ + fmc_state = fmc_bank0_ready_wait(FMC_TIMEOUT_COUNT); + FMC_WSEN |= FMC_WSEN_BPEN; + if(FMC_READY == fmc_state){ + /* set the PG bit to start program */ + FMC_CTL0 |= FMC_CTL0_PG; + REG32(address) = data; + /* wait for the FMC ready */ + fmc_state = fmc_bank0_ready_wait(FMC_TIMEOUT_COUNT); + /* reset the PG bit */ + FMC_CTL0 &= ~FMC_CTL0_PG; + } + } + /* return the FMC state */ + return fmc_state; +} + +/*! + \brief unlock the option byte operation + \param[in] none + \param[out] none + \retval none +*/ +void ob_unlock(void) +{ + if(RESET == (FMC_CTL0 & FMC_CTL0_OBWEN)){ + /* write the FMC key */ + FMC_OBKEY = UNLOCK_KEY0; + FMC_OBKEY = UNLOCK_KEY1; + } +} + +/*! + \brief lock the option byte operation + \param[in] none + \param[out] none + \retval none +*/ +void ob_lock(void) +{ + /* reset the OBWEN bit */ + FMC_CTL0 &= ~FMC_CTL0_OBWEN; +} + +/*! + \brief erase the FMC option byte + unlock the FMC_CTL0 and option byte before calling this function + \param[in] none + \param[out] none + \retval state of FMC, refer to fmc_state_enum +*/ +fmc_state_enum ob_erase(void) +{ + uint16_t temp_spc = FMC_NSPC; + + fmc_state_enum fmc_state = fmc_bank0_ready_wait(FMC_TIMEOUT_COUNT); + + /* check the option byte security protection value */ + if(RESET != ob_spc_get()){ + temp_spc = FMC_USPC; + } + + if(FMC_READY == fmc_state){ + + /* start erase the option byte */ + FMC_CTL0 |= FMC_CTL0_OBER; + FMC_CTL0 |= FMC_CTL0_START; + + /* wait for the FMC ready */ + fmc_state = fmc_bank0_ready_wait(FMC_TIMEOUT_COUNT); + + if(FMC_READY == fmc_state){ + /* reset the OBER bit */ + FMC_CTL0 &= ~FMC_CTL0_OBER; + /* set the OBPG bit */ + FMC_CTL0 |= FMC_CTL0_OBPG; + /* no security protection */ + OB_SPC = (uint16_t)temp_spc; + /* wait for the FMC ready */ + fmc_state = fmc_bank0_ready_wait(FMC_TIMEOUT_COUNT); + if(FMC_TOERR != fmc_state){ + /* reset the OBPG bit */ + FMC_CTL0 &= ~FMC_CTL0_OBPG; + } + }else{ + if(FMC_TOERR != fmc_state){ + /* reset the OBPG bit */ + FMC_CTL0 &= ~FMC_CTL0_OBPG; + } + } + } + /* return the FMC state */ + return fmc_state; +} + +/*! + \brief enable write protection + \param[in] ob_wp: specify sector to be write protected + \arg OB_WPx(x=0..31): write protect specify sector + \arg OB_WP_ALL: write protect all sector + \param[out] none + \retval state of FMC, refer to fmc_state_enum +*/ +fmc_state_enum ob_write_protection_enable(uint32_t ob_wp) +{ + uint16_t temp_wp0, temp_wp1, temp_wp2, temp_wp3; + + fmc_state_enum fmc_state = fmc_bank0_ready_wait(FMC_TIMEOUT_COUNT); + + ob_wp = (uint32_t)(~ob_wp); + temp_wp0 = (uint16_t)(ob_wp & OB_WP0_WP0); + temp_wp1 = (uint16_t)((ob_wp & OB_WP1_WP1) >> 8U); + temp_wp2 = (uint16_t)((ob_wp & OB_WP2_WP2) >> 16U); + temp_wp3 = (uint16_t)((ob_wp & OB_WP3_WP3) >> 24U); + + if(FMC_READY == fmc_state){ + + /* set the OBPG bit*/ + FMC_CTL0 |= FMC_CTL0_OBPG; + + if(0xFFU != temp_wp0){ + OB_WP0 = temp_wp0; + + /* wait for the FMC ready */ + fmc_state = fmc_bank0_ready_wait(FMC_TIMEOUT_COUNT); + } + if((FMC_READY == fmc_state) && (0xFFU != temp_wp1)){ + OB_WP1 = temp_wp1; + + /* wait for the FMC ready */ + fmc_state = fmc_bank0_ready_wait(FMC_TIMEOUT_COUNT); + } + if((FMC_READY == fmc_state) && (0xFFU != temp_wp2)){ + OB_WP2 = temp_wp2; + + /* wait for the FMC ready */ + fmc_state = fmc_bank0_ready_wait(FMC_TIMEOUT_COUNT); + } + if((FMC_READY == fmc_state) && (0xFFU != temp_wp3)){ + OB_WP3 = temp_wp3; + + /* wait for the FMC ready */ + fmc_state = fmc_bank0_ready_wait(FMC_TIMEOUT_COUNT); + } + if(FMC_TOERR != fmc_state){ + /* reset the OBPG bit */ + FMC_CTL0 &= ~FMC_CTL0_OBPG; + } + } + /* return the FMC state */ + return fmc_state; +} + +/*! + \brief configure security protection + \param[in] ob_spc: specify security protection + \arg FMC_NSPC: no security protection + \arg FMC_USPC: under security protection + \param[out] none + \retval state of FMC, refer to fmc_state_enum +*/ +fmc_state_enum ob_security_protection_config(uint8_t ob_spc) +{ + fmc_state_enum fmc_state = fmc_bank0_ready_wait(FMC_TIMEOUT_COUNT); + + if(FMC_READY == fmc_state){ + FMC_CTL0 |= FMC_CTL0_OBER; + FMC_CTL0 |= FMC_CTL0_START; + + /* wait for the FMC ready */ + fmc_state = fmc_bank0_ready_wait(FMC_TIMEOUT_COUNT); + + if(FMC_READY == fmc_state){ + /* reset the OBER bit */ + FMC_CTL0 &= ~FMC_CTL0_OBER; + + /* start the option byte program */ + FMC_CTL0 |= FMC_CTL0_OBPG; + + OB_SPC = (uint16_t)ob_spc; + + /* wait for the FMC ready */ + fmc_state = fmc_bank0_ready_wait(FMC_TIMEOUT_COUNT); + + if(FMC_TOERR != fmc_state){ + /* reset the OBPG bit */ + FMC_CTL0 &= ~FMC_CTL0_OBPG; + } + }else{ + if(FMC_TOERR != fmc_state){ + /* reset the OBER bit */ + FMC_CTL0 &= ~FMC_CTL0_OBER; + } + } + } + /* return the FMC state */ + return fmc_state; +} + +/*! + \brief program the FMC user option byte + \param[in] ob_fwdgt: option byte watchdog value + \arg OB_FWDGT_SW: software free watchdog + \arg OB_FWDGT_HW: hardware free watchdog + \param[in] ob_deepsleep: option byte deepsleep reset value + \arg OB_DEEPSLEEP_NRST: no reset when entering deepsleep mode + \arg OB_DEEPSLEEP_RST: generate a reset instead of entering deepsleep mode + \param[in] ob_stdby:option byte standby reset value + \arg OB_STDBY_NRST: no reset when entering standby mode + \arg OB_STDBY_RST: generate a reset instead of entering standby mode + \param[in] ob_boot: specifies the option byte boot bank value + \arg OB_BOOT_B0: boot from bank0 + \arg OB_BOOT_B1: boot from bank1 or bank0 if bank1 is void + \param[out] none + \retval state of FMC, refer to fmc_state_enum +*/ +fmc_state_enum ob_user_write(uint8_t ob_fwdgt, uint8_t ob_deepsleep, uint8_t ob_stdby, uint8_t ob_boot) +{ + fmc_state_enum fmc_state = FMC_READY; + uint8_t temp; + + /* wait for the FMC ready */ + fmc_state = fmc_bank0_ready_wait(FMC_TIMEOUT_COUNT); + + if(FMC_READY == fmc_state){ + /* set the OBPG bit*/ + FMC_CTL0 |= FMC_CTL0_OBPG; + + temp = ((uint8_t)((uint8_t)((uint8_t)(ob_boot | ob_fwdgt) | ob_deepsleep) | ob_stdby) | OB_USER_MASK); + OB_USER = (uint16_t)temp; + + /* wait for the FMC ready */ + fmc_state = fmc_bank0_ready_wait(FMC_TIMEOUT_COUNT); + + if(FMC_TOERR != fmc_state){ + /* reset the OBPG bit */ + FMC_CTL0 &= ~FMC_CTL0_OBPG; + } + } + /* return the FMC state */ + return fmc_state; +} + +/*! + \brief program option bytes data + \param[in] address: the option bytes address to be programmed + \param[in] data: the byte to be programmed + \param[out] none + \retval state of FMC, refer to fmc_state_enum +*/ +fmc_state_enum ob_data_program(uint32_t address, uint8_t data) +{ + fmc_state_enum fmc_state = fmc_bank0_ready_wait(FMC_TIMEOUT_COUNT); + + if(FMC_READY == fmc_state){ + /* set the OBPG bit */ + FMC_CTL0 |= FMC_CTL0_OBPG; + REG16(address) = data; + + /* wait for the FMC ready */ + fmc_state = fmc_bank0_ready_wait(FMC_TIMEOUT_COUNT); + + if(FMC_TOERR != fmc_state){ + /* reset the OBPG bit */ + FMC_CTL0 &= ~FMC_CTL0_OBPG; + } + } + /* return the FMC state */ + return fmc_state; +} + +/*! + \brief get the FMC user option byte + \param[in] none + \param[out] none + \retval the FMC user option byte values +*/ +uint8_t ob_user_get(void) +{ + /* return the FMC user option byte value */ + return (uint8_t)(FMC_OBSTAT >> 2U); +} + +/*! + \brief get OB_DATA in register FMC_OBSTAT + \param[in] none + \param[out] none + \retval ob_data +*/ +uint16_t ob_data_get(void) +{ + return (uint16_t)(FMC_OBSTAT >> 10U); +} + +/*! + \brief get the FMC option byte write protection + \param[in] none + \param[out] none + \retval the FMC write protection option byte value +*/ +uint32_t ob_write_protection_get(void) +{ + /* return the FMC write protection option byte value */ + return FMC_WP; +} + +/*! + \brief get the FMC option byte security protection + \param[in] none + \param[out] none + \retval FlagStatus: SET or RESET +*/ +FlagStatus ob_spc_get(void) +{ + FlagStatus spc_state = RESET; + + if(RESET != (FMC_OBSTAT & FMC_OBSTAT_SPC)){ + spc_state = SET; + }else{ + spc_state = RESET; + } + return spc_state; +} + +/*! + \brief enable FMC interrupt + \param[in] interrupt: the FMC interrupt source + \arg FMC_INT_BANK0_END: FMC bank0 end of program interrupt + \arg FMC_INT_BANK0_ERR: FMC bank0 error interrupt + \arg FMC_INT_BANK1_END: FMC bank1 end of program interrupt + \arg FMC_INT_BANK1_ERR: FMC bank1 error interrupt + \param[out] none + \retval none +*/ +void fmc_interrupt_enable(uint32_t interrupt) +{ + FMC_REG_VAL(interrupt) |= BIT(FMC_BIT_POS(interrupt)); +} + +/*! + \brief disable FMC interrupt + \param[in] interrupt: the FMC interrupt source + \arg FMC_INT_BANK0_END: FMC bank0 end of program interrupt + \arg FMC_INT_BANK0_ERR: FMC bank0 error interrupt + \arg FMC_INT_BANK1_END: FMC bank1 end of program interrupt + \arg FMC_INT_BANK1_ERR: FMC bank1 error interrupt + \param[out] none + \retval none +*/ +void fmc_interrupt_disable(uint32_t interrupt) +{ + FMC_REG_VAL(interrupt) &= ~BIT(FMC_BIT_POS(interrupt)); +} + +/*! + \brief check flag is set or not + \param[in] flag: check FMC flag + only one parameter can be selected which is shown as below: + \arg FMC_FLAG_BANK0_BUSY: FMC bank0 busy flag bit + \arg FMC_FLAG_BANK0_PGERR: FMC bank0 operation error flag bit + \arg FMC_FLAG_BANK0_WPERR: FMC bank0 erase/program protection error flag bit + \arg FMC_FLAG_BANK0_END: FMC bank0 end of operation flag bit + \arg FMC_FLAG_OBERR: FMC option bytes read error flag bit + \arg FMC_FLAG_BANK1_BUSY: FMC bank1 busy flag bit + \arg FMC_FLAG_BANK1_PGERR: FMC bank1 operation error flag bit + \arg FMC_FLAG_BANK1_WPERR: FMC bank1 erase/program protection error flag bit + \arg FMC_FLAG_BANK1_END: FMC bank1 end of operation flag bit + \param[out] none + \retval FlagStatus: SET or RESET +*/ +FlagStatus fmc_flag_get(uint32_t flag) +{ + if(RESET != (FMC_REG_VAL(flag) & BIT(FMC_BIT_POS(flag)))){ + return SET; + }else{ + return RESET; + } +} + +/*! + \brief clear the FMC flag + \param[in] flag: clear FMC flag + only one parameter can be selected which is shown as below: + \arg FMC_FLAG_BANK0_PGERR: FMC bank0 operation error flag bit + \arg FMC_FLAG_BANK0_WPERR: FMC bank0 erase/program protection error flag bit + \arg FMC_FLAG_BANK0_END: FMC bank0 end of operation flag bit + \arg FMC_FLAG_BANK1_PGERR: FMC bank1 operation error flag bit + \arg FMC_FLAG_BANK1_WPERR: FMC bank1 erase/program protection error flag bit + \arg FMC_FLAG_BANK1_END: FMC bank1 end of operation flag bit + \param[out] none + \retval none +*/ +void fmc_flag_clear(uint32_t flag) +{ + FMC_REG_VAL(flag) |= BIT(FMC_BIT_POS(flag)); +} + +/*! + \brief get FMC interrupt flag state + \param[in] flag: FMC interrupt flags, refer to fmc_interrupt_flag_enum + only one parameter can be selected which is shown as below: + \arg FMC_INT_FLAG_BANK0_PGERR: FMC bank0 operation error interrupt flag bit + \arg FMC_INT_FLAG_BANK0_WPERR: FMC bank0 erase/program protection error interrupt flag bit + \arg FMC_INT_FLAG_BANK0_END: FMC bank0 end of operation interrupt flag bit + \arg FMC_INT_FLAG_BANK1_PGERR: FMC bank1 operation error interrupt flag bit + \arg FMC_INT_FLAG_BANK1_WPERR: FMC bank1 erase/program protection error interrupt flag bit + \arg FMC_INT_FLAG_BANK1_END: FMC bank1 end of operation interrupt flag bit + \param[out] none + \retval FlagStatus: SET or RESET +*/ +FlagStatus fmc_interrupt_flag_get(fmc_interrupt_flag_enum flag) +{ + FlagStatus ret1 = RESET; + FlagStatus ret2 = RESET; + + if(FMC_STAT0_REG_OFFSET == FMC_REG_OFFSET_GET(flag)){ + /* get the staus of interrupt flag */ + ret1 = (FlagStatus)(FMC_REG_VALS(flag) & BIT(FMC_BIT_POS0(flag))); + /* get the staus of interrupt enale bit */ + ret2 = (FlagStatus)(FMC_CTL0 & BIT(FMC_BIT_POS1(flag))); + }else{ + /* get the staus of interrupt flag */ + ret1 = (FlagStatus)(FMC_REG_VALS(flag) & BIT(FMC_BIT_POS0(flag))); + /* get the staus of interrupt enale bit */ + ret2 = (FlagStatus)(FMC_CTL1 & BIT(FMC_BIT_POS1(flag))); + } + + if(ret1 && ret2){ + return SET; + }else{ + return RESET; + } +} + +/*! + \brief clear FMC interrupt flag state + \param[in] flag: FMC interrupt flags, refer to can_interrupt_flag_enum + only one parameter can be selected which is shown as below: + \arg FMC_INT_FLAG_BANK0_PGERR: FMC bank0 operation error interrupt flag bit + \arg FMC_INT_FLAG_BANK0_WPERR: FMC bank0 erase/program protection error interrupt flag bit + \arg FMC_INT_FLAG_BANK0_END: FMC bank0 end of operation interrupt flag bit + \arg FMC_INT_FLAG_BANK1_PGERR: FMC bank1 operation error interrupt flag bit + \arg FMC_INT_FLAG_BANK1_WPERR: FMC bank1 erase/program protection error interrupt flag bit + \arg FMC_INT_FLAG_BANK1_END: FMC bank1 end of operation interrupt flag bit + \param[out] none + \retval none +*/ +void fmc_interrupt_flag_clear(fmc_interrupt_flag_enum flag) +{ + FMC_REG_VALS(flag) |= BIT(FMC_BIT_POS0(flag)); +} + +/*! + \brief get the FMC bank0 state + \param[in] none + \param[out] none + \retval state of FMC, refer to fmc_state_enum +*/ +fmc_state_enum fmc_bank0_state_get(void) +{ + fmc_state_enum fmc_state = FMC_READY; + + if((uint32_t)0x00U != (FMC_STAT0 & FMC_STAT0_BUSY)){ + fmc_state = FMC_BUSY; + }else{ + if((uint32_t)0x00U != (FMC_STAT0 & FMC_STAT0_WPERR)){ + fmc_state = FMC_WPERR; + }else{ + if((uint32_t)0x00U != (FMC_STAT0 & (FMC_STAT0_PGERR))){ + fmc_state = FMC_PGERR; + } + } + } + /* return the FMC state */ + return fmc_state; +} + +/*! + \brief get the FMC bank1 state + \param[in] none + \param[out] none + \retval state of FMC, refer to fmc_state_enum +*/ +fmc_state_enum fmc_bank1_state_get(void) +{ + fmc_state_enum fmc_state = FMC_READY; + + if((uint32_t)0x00U != (FMC_STAT1 & FMC_STAT1_BUSY)){ + fmc_state = FMC_BUSY; + }else{ + if((uint32_t)0x00U != (FMC_STAT1 & FMC_STAT1_WPERR)){ + fmc_state = FMC_WPERR; + }else{ + if((uint32_t)0x00U != (FMC_STAT1 & FMC_STAT1_PGERR)){ + fmc_state = FMC_PGERR; + } + } + } + + /* return the FMC state */ + return fmc_state; +} + +/*! + \brief check whether FMC bank0 is ready or not + \param[in] timeout: count of loop + \param[out] none + \retval state of FMC, refer to fmc_state_enum +*/ +fmc_state_enum fmc_bank0_ready_wait(uint32_t timeout) +{ + fmc_state_enum fmc_state = FMC_BUSY; + + /* wait for FMC ready */ + do{ + /* get FMC state */ + fmc_state = fmc_bank0_state_get(); + timeout--; + }while((FMC_BUSY == fmc_state) && (0x00U != timeout)); + + if(FMC_BUSY == fmc_state){ + fmc_state = FMC_TOERR; + } + /* return the FMC state */ + return fmc_state; +} + +/*! + \brief check whether FMC bank1 is ready or not + \param[in] timeout: count of loop + \param[out] none + \retval state of FMC, refer to fmc_state_enum +*/ +fmc_state_enum fmc_bank1_ready_wait(uint32_t timeout) +{ + fmc_state_enum fmc_state = FMC_BUSY; + + /* wait for FMC ready */ + do{ + /* get FMC state */ + fmc_state = fmc_bank1_state_get(); + timeout--; + }while((FMC_BUSY == fmc_state) && (0x00U != timeout)); + + if(FMC_BUSY == fmc_state){ + fmc_state = FMC_TOERR; + } + /* return the FMC state */ + return fmc_state; +} diff --git a/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_standard_peripheral/Source/gd32f30x_fwdgt.c b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_standard_peripheral/Source/gd32f30x_fwdgt.c new file mode 100644 index 0000000000..9a5014ae43 --- /dev/null +++ b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_standard_peripheral/Source/gd32f30x_fwdgt.c @@ -0,0 +1,158 @@ +/*! + \file gd32f30x_fwdgt.c + \brief FWDGT driver + + \version 2017-02-10, V1.0.0, firmware for GD32F30x + \version 2018-10-10, V1.1.0, firmware for GD32F30x + \version 2018-12-25, V2.0.0, firmware for GD32F30x + \version 2020-09-30, V2.1.0, firmware for GD32F30x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "gd32f30x_fwdgt.h" + +/* write value to FWDGT_CTL_CMD bit field */ +#define CTL_CMD(regval) (BITS(0,15) & ((uint32_t)(regval) << 0)) +/* write value to FWDGT_RLD_RLD bit field */ +#define RLD_RLD(regval) (BITS(0,11) & ((uint32_t)(regval) << 0)) + +/*! + \brief enable write access to FWDGT_PSC and FWDGT_RLD + \param[in] none + \param[out] none + \retval none +*/ +void fwdgt_write_enable(void) +{ + FWDGT_CTL = FWDGT_WRITEACCESS_ENABLE; +} + +/*! + \brief disable write access to FWDGT_PSC and FWDGT_RLD + \param[in] none + \param[out] none + \retval none +*/ +void fwdgt_write_disable(void) +{ + FWDGT_CTL = FWDGT_WRITEACCESS_DISABLE; +} + +/*! + \brief start the free watchdog timer counter + \param[in] none + \param[out] none + \retval none +*/ +void fwdgt_enable(void) +{ + FWDGT_CTL = FWDGT_KEY_ENABLE; +} + +/*! + \brief reload the counter of FWDGT + \param[in] none + \param[out] none + \retval none +*/ +void fwdgt_counter_reload(void) +{ + FWDGT_CTL = FWDGT_KEY_RELOAD; +} + +/*! + \brief configure counter reload value, and prescaler divider value + \param[in] reload_value: specify reload value(0x0000 - 0x0FFF) + \param[in] prescaler_div: FWDGT prescaler value + only one parameter can be selected which is shown as below: + \arg FWDGT_PSC_DIV4: FWDGT prescaler set to 4 + \arg FWDGT_PSC_DIV8: FWDGT prescaler set to 8 + \arg FWDGT_PSC_DIV16: FWDGT prescaler set to 16 + \arg FWDGT_PSC_DIV32: FWDGT prescaler set to 32 + \arg FWDGT_PSC_DIV64: FWDGT prescaler set to 64 + \arg FWDGT_PSC_DIV128: FWDGT prescaler set to 128 + \arg FWDGT_PSC_DIV256: FWDGT prescaler set to 256 + \param[out] none + \retval ErrStatus: ERROR or SUCCESS +*/ +ErrStatus fwdgt_config(uint16_t reload_value, uint8_t prescaler_div) +{ + uint32_t timeout = FWDGT_PSC_TIMEOUT; + uint32_t flag_status = RESET; + + /* enable write access to FWDGT_PSC,and FWDGT_RLD */ + FWDGT_CTL = FWDGT_WRITEACCESS_ENABLE; + + /* wait until the PUD flag to be reset */ + do{ + flag_status = FWDGT_STAT & FWDGT_STAT_PUD; + }while((--timeout > 0U) && ((uint32_t)RESET != flag_status)); + + if ((uint32_t)RESET != flag_status){ + return ERROR; + } + + /* configure FWDGT */ + FWDGT_PSC = (uint32_t)prescaler_div; + + timeout = FWDGT_RLD_TIMEOUT; + /* wait until the RUD flag to be reset */ + do{ + flag_status = FWDGT_STAT & FWDGT_STAT_RUD; + }while((--timeout > 0U) && ((uint32_t)RESET != flag_status)); + + if ((uint32_t)RESET != flag_status){ + return ERROR; + } + + FWDGT_RLD = RLD_RLD(reload_value); + + /* reload the counter */ + FWDGT_CTL = FWDGT_KEY_RELOAD; + + return SUCCESS; +} + +/*! + \brief get flag state of FWDGT + \param[in] flag: flag to get + only one parameter can be selected which is shown as below: + \arg FWDGT_FLAG_PUD: a write operation to FWDGT_PSC register is on going + \arg FWDGT_FLAG_RUD: a write operation to FWDGT_RLD register is on going + \param[out] none + \retval FlagStatus: SET or RESET +*/ +FlagStatus fwdgt_flag_get(uint16_t flag) +{ + if(RESET != (FWDGT_STAT & flag)){ + return SET; + } + + return RESET; +} diff --git a/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_standard_peripheral/Source/gd32f30x_gpio.c b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_standard_peripheral/Source/gd32f30x_gpio.c new file mode 100644 index 0000000000..dd0ff97eeb --- /dev/null +++ b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_standard_peripheral/Source/gd32f30x_gpio.c @@ -0,0 +1,583 @@ +/*! + \file gd32f30x_gpio.c + \brief GPIO driver + + \version 2017-02-10, V1.0.0, firmware for GD32F30x + \version 2018-10-10, V1.1.0, firmware for GD32F30x + \version 2018-12-25, V2.0.0, firmware for GD32F30x + \version 2020-09-30, V2.1.0, firmware for GD32F30x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "gd32f30x_gpio.h" + +#define AFIO_EXTI_SOURCE_MASK ((uint8_t)0x03U) /*!< AFIO exti source selection mask*/ +#define AFIO_EXTI_SOURCE_FIELDS ((uint8_t)0x04U) /*!< select AFIO exti source registers */ +#define LSB_16BIT_MASK ((uint16_t)0xFFFFU) /*!< LSB 16-bit mask */ +#define PCF_POSITION_MASK ((uint32_t)0x000F0000U) /*!< AFIO_PCF register position mask */ +#define PCF_SWJCFG_MASK ((uint32_t)0xF8FFFFFFU) /*!< AFIO_PCF register SWJCFG mask */ +#define PCF_LOCATION1_MASK ((uint32_t)0x00200000U) /*!< AFIO_PCF register location1 mask */ +#define PCF_LOCATION2_MASK ((uint32_t)0x00100000U) /*!< AFIO_PCF register location2 mask */ +#define AFIO_PCF1_FIELDS ((uint32_t)0x80000000U) /*!< select AFIO_PCF1 register */ +#define GPIO_OUTPUT_PORT_OFFSET ((uint32_t)4U) /*!< GPIO event output port offset*/ + +/*! + \brief reset GPIO port + \param[in] gpio_periph: GPIOx(x = A,B,C,D,E,F,G) + \param[out] none + \retval none +*/ +void gpio_deinit(uint32_t gpio_periph) +{ + switch(gpio_periph){ + case GPIOA: + /* reset GPIOA */ + rcu_periph_reset_enable(RCU_GPIOARST); + rcu_periph_reset_disable(RCU_GPIOARST); + break; + case GPIOB: + /* reset GPIOB */ + rcu_periph_reset_enable(RCU_GPIOBRST); + rcu_periph_reset_disable(RCU_GPIOBRST); + break; + case GPIOC: + /* reset GPIOC */ + rcu_periph_reset_enable(RCU_GPIOCRST); + rcu_periph_reset_disable(RCU_GPIOCRST); + break; + case GPIOD: + /* reset GPIOD */ + rcu_periph_reset_enable(RCU_GPIODRST); + rcu_periph_reset_disable(RCU_GPIODRST); + break; + case GPIOE: + /* reset GPIOE */ + rcu_periph_reset_enable(RCU_GPIOERST); + rcu_periph_reset_disable(RCU_GPIOERST); + break; + case GPIOF: + /* reset GPIOF */ + rcu_periph_reset_enable(RCU_GPIOFRST); + rcu_periph_reset_disable(RCU_GPIOFRST); + break; + case GPIOG: + /* reset GPIOG */ + rcu_periph_reset_enable(RCU_GPIOGRST); + rcu_periph_reset_disable(RCU_GPIOGRST); + break; + default: + break; + } +} + +/*! + \brief reset alternate function I/O(AFIO) + \param[in] none + \param[out] none + \retval none +*/ +void gpio_afio_deinit(void) +{ + rcu_periph_reset_enable(RCU_AFRST); + rcu_periph_reset_disable(RCU_AFRST); +} + +/*! + \brief GPIO parameter initialization + \param[in] gpio_periph: GPIOx(x = A,B,C,D,E,F,G) + \param[in] mode: gpio pin mode + only one parameter can be selected which is shown as below: + \arg GPIO_MODE_AIN: analog input mode + \arg GPIO_MODE_IN_FLOATING: floating input mode + \arg GPIO_MODE_IPD: pull-down input mode + \arg GPIO_MODE_IPU: pull-up input mode + \arg GPIO_MODE_OUT_OD: GPIO output with open-drain + \arg GPIO_MODE_OUT_PP: GPIO output with push-pull + \arg GPIO_MODE_AF_OD: AFIO output with open-drain + \arg GPIO_MODE_AF_PP: AFIO output with push-pull + \param[in] speed: gpio output max speed value + only one parameter can be selected which is shown as below: + \arg GPIO_OSPEED_10MHZ: output max speed 10MHz + \arg GPIO_OSPEED_2MHZ: output max speed 2MHz + \arg GPIO_OSPEED_50MHZ: output max speed 50MHz + \arg GPIO_OSPEED_MAX: output max speed more than 50MHz + \param[in] pin: GPIO pin + one or more parameters can be selected which are shown as below: + \arg GPIO_PIN_x(x=0..15), GPIO_PIN_ALL + \param[out] none + \retval none +*/ +void gpio_init(uint32_t gpio_periph, uint32_t mode, uint32_t speed, uint32_t pin) +{ + uint16_t i; + uint32_t temp_mode = 0U; + uint32_t reg = 0U; + + /* GPIO mode configuration */ + temp_mode = (uint32_t)(mode & ((uint32_t)0x0FU)); + + /* GPIO speed configuration */ + if(((uint32_t)0x00U) != ((uint32_t)mode & ((uint32_t)0x10U))){ + /* output mode max speed */ + if(GPIO_OSPEED_MAX == (uint32_t)speed){ + temp_mode |= (uint32_t)0x03U; + /* set the corresponding SPD bit */ + GPIOx_SPD(gpio_periph) |= (uint32_t)pin ; + }else{ + /* output mode max speed:10MHz,2MHz,50MHz */ + temp_mode |= (uint32_t)speed; + } + } + + /* configure the eight low port pins with GPIO_CTL0 */ + for(i = 0U;i < 8U;i++){ + if((1U << i) & pin){ + reg = GPIO_CTL0(gpio_periph); + + /* clear the specified pin mode bits */ + reg &= ~GPIO_MODE_MASK(i); + /* set the specified pin mode bits */ + reg |= GPIO_MODE_SET(i, temp_mode); + + /* set IPD or IPU */ + if(GPIO_MODE_IPD == mode){ + /* reset the corresponding OCTL bit */ + GPIO_BC(gpio_periph) = (uint32_t)((1U << i) & pin); + }else{ + /* set the corresponding OCTL bit */ + if(GPIO_MODE_IPU == mode){ + GPIO_BOP(gpio_periph) = (uint32_t)((1U << i) & pin); + } + } + /* set GPIO_CTL0 register */ + GPIO_CTL0(gpio_periph) = reg; + } + } + /* configure the eight high port pins with GPIO_CTL1 */ + for(i = 8U;i < 16U;i++){ + if((1U << i) & pin){ + reg = GPIO_CTL1(gpio_periph); + + /* clear the specified pin mode bits */ + reg &= ~GPIO_MODE_MASK(i - 8U); + /* set the specified pin mode bits */ + reg |= GPIO_MODE_SET(i - 8U, temp_mode); + + /* set IPD or IPU */ + if(GPIO_MODE_IPD == mode){ + /* reset the corresponding OCTL bit */ + GPIO_BC(gpio_periph) = (uint32_t)((1U << i) & pin); + }else{ + /* set the corresponding OCTL bit */ + if(GPIO_MODE_IPU == mode){ + GPIO_BOP(gpio_periph) = (uint32_t)((1U << i) & pin); + } + } + /* set GPIO_CTL1 register */ + GPIO_CTL1(gpio_periph) = reg; + } + } +} + +/*! + \brief set GPIO pin + \param[in] gpio_periph: GPIOx(x = A,B,C,D,E,F,G) + \param[in] pin: GPIO pin + one or more parameters can be selected which are shown as below: + \arg GPIO_PIN_x(x=0..15), GPIO_PIN_ALL + \param[out] none + \retval none +*/ +void gpio_bit_set(uint32_t gpio_periph,uint32_t pin) +{ + GPIO_BOP(gpio_periph) = (uint32_t)pin; +} + +/*! + \brief reset GPIO pin + \param[in] gpio_periph: GPIOx(x = A,B,C,D,E,F,G) + \param[in] pin: GPIO pin + one or more parameters can be selected which are shown as below: + \arg GPIO_PIN_x(x=0..15), GPIO_PIN_ALL + \param[out] none + \retval none +*/ +void gpio_bit_reset(uint32_t gpio_periph,uint32_t pin) +{ + GPIO_BC(gpio_periph) = (uint32_t)pin; +} + +/*! + \brief write data to the specified GPIO pin + \param[in] gpio_periph: GPIOx(x = A,B,C,D,E,F,G) + \param[in] pin: GPIO pin + one or more parameters can be selected which are shown as below: + \arg GPIO_PIN_x(x=0..15), GPIO_PIN_ALL + \param[in] bit_value: SET or RESET + \arg RESET: clear the port pin + \arg SET: set the port pin + \param[out] none + \retval none +*/ +void gpio_bit_write(uint32_t gpio_periph,uint32_t pin,bit_status bit_value) +{ + if(RESET != bit_value){ + GPIO_BOP(gpio_periph) = (uint32_t)pin; + }else{ + GPIO_BC(gpio_periph) = (uint32_t)pin; + } +} + +/*! + \brief write data to the specified GPIO port + \param[in] gpio_periph: GPIOx(x = A,B,C,D,E,F,G) + \param[in] data: specify the value to be written to the port output data register + \param[out] none + \retval none +*/ +void gpio_port_write(uint32_t gpio_periph,uint16_t data) +{ + GPIO_OCTL(gpio_periph) = (uint32_t)data; +} + +/*! + \brief get GPIO pin input status + \param[in] gpio_periph: GPIOx(x = A,B,C,D,E,F,G) + \param[in] pin: GPIO pin + only one parameter can be selected which are shown as below: + \arg GPIO_PIN_x(x=0..15), GPIO_PIN_ALL + \param[out] none + \retval input status of gpio pin: SET or RESET +*/ +FlagStatus gpio_input_bit_get(uint32_t gpio_periph,uint32_t pin) +{ + if((uint32_t)RESET != (GPIO_ISTAT(gpio_periph)&(pin))){ + return SET; + }else{ + return RESET; + } +} + +/*! + \brief get GPIO port input status + \param[in] gpio_periph: GPIOx(x = A,B,C,D,E,F,G) + \param[out] none + \retval input status of gpio all pins +*/ +uint16_t gpio_input_port_get(uint32_t gpio_periph) +{ + return (uint16_t)(GPIO_ISTAT(gpio_periph)); +} + +/*! + \brief get GPIO pin output status + \param[in] gpio_periph: GPIOx(x = A,B,C,D,E,F,G) + \param[in] pin: GPIO pin + only one parameter can be selected which are shown as below: + \arg GPIO_PIN_x(x=0..15), GPIO_PIN_ALL + \param[out] none + \retval output status of gpio pin: SET or RESET +*/ +FlagStatus gpio_output_bit_get(uint32_t gpio_periph,uint32_t pin) +{ + if((uint32_t)RESET !=(GPIO_OCTL(gpio_periph)&(pin))){ + return SET; + }else{ + return RESET; + } +} + +/*! + \brief get GPIO port output status + \param[in] gpio_periph: GPIOx(x = A,B,C,D,E,F,G) + \param[out] none + \retval output status of gpio all pins +*/ +uint16_t gpio_output_port_get(uint32_t gpio_periph) +{ + return ((uint16_t)GPIO_OCTL(gpio_periph)); +} + +/*! + \brief configure GPIO pin remap + \param[in] gpio_remap: select the pin to remap + only one parameter can be selected which are shown as below: + \arg GPIO_SPI0_REMAP: SPI0 remapping + \arg GPIO_I2C0_REMAP: I2C0 remapping + \arg GPIO_USART0_REMAP: USART0 remapping + \arg GPIO_USART1_REMAP: USART1 remapping + \arg GPIO_USART2_PARTIAL_REMAP: USART2 partial remapping + \arg GPIO_USART2_FULL_REMAP: USART2 full remapping + \arg GPIO_TIMER0_PARTIAL_REMAP: TIMER0 partial remapping + \arg GPIO_TIMER0_FULL_REMAP: TIMER0 full remapping + \arg GPIO_TIMER1_PARTIAL_REMAP0: TIMER1 partial remapping + \arg GPIO_TIMER1_PARTIAL_REMAP1: TIMER1 partial remapping + \arg GPIO_TIMER1_FULL_REMAP: TIMER1 full remapping + \arg GPIO_TIMER2_PARTIAL_REMAP: TIMER2 partial remapping + \arg GPIO_TIMER2_FULL_REMAP: TIMER2 full remapping + \arg GPIO_TIMER3_REMAP: TIMER3 remapping + \arg GPIO_CAN_PARTIAL_REMAP: CAN partial remapping(only for GD32F30X_HD devices and GD32F30X_XD devices) + \arg GPIO_CAN_FULL_REMAP: CAN full remapping(only for GD32F30X_HD devices and GD32F30X_XD devices) + \arg GPIO_CAN0_PARTIAL_REMAP: CAN0 partial remapping(only for GD32F30X_CL devices) + \arg GPIO_CAN0_FULL_REMAP: CAN0 full remapping(only for GD32F30X_CL devices) + \arg GPIO_PD01_REMAP: PD01 remapping + \arg GPIO_TIMER4CH3_IREMAP: TIMER4 channel3 internal remapping + \arg GPIO_ADC0_ETRGINS_REMAP: ADC0 external trigger inserted conversion remapping(only for GD32F30X_HD devices and GD32F30X_XD devices) + \arg GPIO_ADC0_ETRGREG_REMAP: ADC0 external trigger regular conversion remapping(only for GD32F30X_HD devices and GD32F30X_XD devices) + \arg GPIO_ADC1_ETRGINS_REMAP: ADC1 external trigger inserted conversion remapping(only for GD32F30X_HD devices and GD32F30X_XD devices) + \arg GPIO_ADC1_ETRGREG_REMAP: ADC1 external trigger regular conversion remapping(only for GD32F30X_HD devices and GD32F30X_XD devices) + \arg GPIO_ENET_REMAP: ENET remapping(only for GD32F30X_CL devices) + \arg GPIO_CAN1_REMAP: CAN1 remapping(only for GD32F30X_CL devices) + \arg GPIO_SWJ_NONJTRST_REMAP: full SWJ(JTAG-DP + SW-DP),but without NJTRST + \arg GPIO_SWJ_SWDPENABLE_REMAP: JTAG-DP disabled and SW-DP enabled + \arg GPIO_SWJ_DISABLE_REMAP: JTAG-DP disabled and SW-DP disabled + \arg GPIO_SPI2_REMAP: SPI2 remapping + \arg GPIO_TIMER1ITR0_REMAP: TIMER1 internal trigger 0 remapping(only for GD32F30X_CL devices) + \arg GPIO_PTP_PPS_REMAP: ethernet PTP PPS remapping(only for GD32F30X_CL devices) + \arg GPIO_TIMER8_REMAP: TIMER8 remapping + \arg GPIO_TIMER9_REMAP: TIMER9 remapping + \arg GPIO_TIMER10_REMAP: TIMER10 remapping + \arg GPIO_TIMER12_REMAP: TIMER12 remapping + \arg GPIO_TIMER13_REMAP: TIMER13 remapping + \arg GPIO_EXMC_NADV_REMAP: EXMC_NADV connect/disconnect + \arg GPIO_CTC_REMAP0: CTC remapping(PD15) + \arg GPIO_CTC_REMAP1: CTC remapping(PF0) + \param[in] newvalue: ENABLE or DISABLE + \param[out] none + \retval none +*/ +void gpio_pin_remap_config(uint32_t remap, ControlStatus newvalue) +{ + uint32_t remap1 = 0U, remap2 = 0U, temp_reg = 0U, temp_mask = 0U; + + if(((uint32_t)0x80000000U) == (remap & 0x80000000U)){ + /* get AFIO_PCF1 regiter value */ + temp_reg = AFIO_PCF1; + }else{ + /* get AFIO_PCF0 regiter value */ + temp_reg = AFIO_PCF0; + } + + temp_mask = (remap & PCF_POSITION_MASK) >> 0x10U; + remap1 = remap & LSB_16BIT_MASK; + + /* judge pin remap type */ + if((PCF_LOCATION1_MASK | PCF_LOCATION2_MASK) == (remap & (PCF_LOCATION1_MASK | PCF_LOCATION2_MASK))){ + temp_reg &= PCF_SWJCFG_MASK; + AFIO_PCF0 &= PCF_SWJCFG_MASK; + }else if(PCF_LOCATION2_MASK == (remap & PCF_LOCATION2_MASK)){ + remap2 = ((uint32_t)0x03U) << temp_mask; + temp_reg &= ~remap2; + temp_reg |= ~PCF_SWJCFG_MASK; + }else{ + temp_reg &= ~(remap1 << ((remap >> 0x15U)*0x10U)); + temp_reg |= ~PCF_SWJCFG_MASK; + } + + /* set pin remap value */ + if(DISABLE != newvalue){ + temp_reg |= (remap1 << ((remap >> 0x15U)*0x10U)); + } + + if(AFIO_PCF1_FIELDS == (remap & AFIO_PCF1_FIELDS)){ + /* set AFIO_PCF1 regiter value */ + AFIO_PCF1 = temp_reg; + }else{ + /* set AFIO_PCF0 regiter value */ + AFIO_PCF0 = temp_reg; + } +} + +#ifdef GD32F30X_CL +/*! + \brief select ethernet MII or RMII PHY + \param[in] enet_sel: ethernet MII or RMII PHY selection + \arg GPIO_ENET_PHY_MII: configure ethernet MAC for connection with an MII PHY + \arg GPIO_ENET_PHY_RMII: configure ethernet MAC for connection with an RMII PHY + \param[out] none + \retval none +*/ +void gpio_ethernet_phy_select(uint32_t enet_sel) +{ + /* clear AFIO_PCF0_ENET_PHY_SEL bit */ + AFIO_PCF0 &= (uint32_t)(~AFIO_PCF0_ENET_PHY_SEL); + + /* select MII or RMII PHY */ + AFIO_PCF0 |= (uint32_t)enet_sel; +} +#endif /* GD32F30X_CL */ + +/*! + \brief select GPIO pin exti sources + \param[in] output_port: gpio event output port + only one parameter can be selected which are shown as below: + \arg GPIO_PORT_SOURCE_GPIOA: output port source A + \arg GPIO_PORT_SOURCE_GPIOB: output port source B + \arg GPIO_PORT_SOURCE_GPIOC: output port source C + \arg GPIO_PORT_SOURCE_GPIOD: output port source D + \arg GPIO_PORT_SOURCE_GPIOE: output port source E + \arg GPIO_PORT_SOURCE_GPIOF: output port source F + \arg GPIO_PORT_SOURCE_GPIOG: output port source G + \param[in] output_pin: GPIO output pin source + only one parameter can be selected which are shown as below: + \arg GPIO_PIN_SOURCE_x(x=0..15) + \param[out] none + \retval none +*/ +void gpio_exti_source_select(uint8_t output_port, uint8_t output_pin) +{ + uint32_t source = 0U; + source = ((uint32_t)0x0FU) << (AFIO_EXTI_SOURCE_FIELDS * (output_pin & AFIO_EXTI_SOURCE_MASK)); + + /* select EXTI sources */ + if(GPIO_PIN_SOURCE_4 > output_pin){ + /* select EXTI0/EXTI1/EXTI2/EXTI3 */ + AFIO_EXTISS0 &= ~source; + AFIO_EXTISS0 |= (((uint32_t)output_port) << (AFIO_EXTI_SOURCE_FIELDS * (output_pin & AFIO_EXTI_SOURCE_MASK))); + }else if(GPIO_PIN_SOURCE_8 > output_pin){ + /* select EXTI4/EXTI5/EXTI6/EXTI7 */ + AFIO_EXTISS1 &= ~source; + AFIO_EXTISS1 |= (((uint32_t)output_port) << (AFIO_EXTI_SOURCE_FIELDS * (output_pin & AFIO_EXTI_SOURCE_MASK))); + }else if(GPIO_PIN_SOURCE_12 > output_pin){ + /* select EXTI8/EXTI9/EXTI10/EXTI11 */ + AFIO_EXTISS2 &= ~source; + AFIO_EXTISS2 |= (((uint32_t)output_port) << (AFIO_EXTI_SOURCE_FIELDS * (output_pin & AFIO_EXTI_SOURCE_MASK))); + }else{ + /* select EXTI12/EXTI13/EXTI14/EXTI15 */ + AFIO_EXTISS3 &= ~source; + AFIO_EXTISS3 |= (((uint32_t)output_port) << (AFIO_EXTI_SOURCE_FIELDS * (output_pin & AFIO_EXTI_SOURCE_MASK))); + } +} + +/*! + \brief configure GPIO pin event output + \param[in] output_port: gpio event output port + only one parameter can be selected which are shown as below: + \arg GPIO_EVENT_PORT_GPIOA: event output port A + \arg GPIO_EVENT_PORT_GPIOB: event output port B + \arg GPIO_EVENT_PORT_GPIOC: event output port C + \arg GPIO_EVENT_PORT_GPIOD: event output port D + \arg GPIO_EVENT_PORT_GPIOE: event output port E + \param[in] output_pin: GPIO event output pin + only one parameter can be selected which are shown as below: + \arg GPIO_EVENT_PIN_x(x=0..15) + \param[out] none + \retval none +*/ +void gpio_event_output_config(uint8_t output_port, uint8_t output_pin) +{ + uint32_t reg = 0U; + reg = AFIO_EC; + + /* clear AFIO_EC_PORT and AFIO_EC_PIN bits */ + reg &= (uint32_t)(~(AFIO_EC_PORT|AFIO_EC_PIN)); + + reg |= (uint32_t)((uint32_t)output_port << GPIO_OUTPUT_PORT_OFFSET); + reg |= (uint32_t)output_pin; + + AFIO_EC = reg; +} + +/*! + \brief enable GPIO pin event output + \param[in] none + \param[out] none + \retval none +*/ +void gpio_event_output_enable(void) +{ + AFIO_EC |= AFIO_EC_EOE; +} + +/*! + \brief disable GPIO pin event output + \param[in] none + \param[out] none + \retval none +*/ +void gpio_event_output_disable(void) +{ + AFIO_EC &= (uint32_t)(~AFIO_EC_EOE); +} + +/*! + \brief lock GPIO pin + \param[in] gpio_periph: GPIOx(x = A,B,C,D,E,F,G) + \param[in] pin: GPIO pin + one or more parameters can be selected which are shown as below: + \arg GPIO_PIN_x(x=0..15), GPIO_PIN_ALL + \param[out] none + \retval none +*/ +void gpio_pin_lock(uint32_t gpio_periph,uint32_t pin) +{ + uint32_t lock = 0x00010000U; + lock |= pin; + + /* lock key writing sequence: write 1 -> write 0 -> write 1 -> read 0 -> read 1 */ + GPIO_LOCK(gpio_periph) = (uint32_t)lock; + GPIO_LOCK(gpio_periph) = (uint32_t)pin; + GPIO_LOCK(gpio_periph) = (uint32_t)lock; + lock = GPIO_LOCK(gpio_periph); + lock = GPIO_LOCK(gpio_periph); +} + +/*! + \brief configure the I/O compensation cell + \param[in] compensation: specifies the I/O compensation cell mode + only one parameter can be selected which are shown as below: + \arg GPIO_COMPENSATION_ENABLE: I/O compensation cell is enabled + \arg GPIO_COMPENSATION_DISABLE: I/O compensation cell is disabled + \param[out] none + \retval none +*/ +void gpio_compensation_config(uint32_t compensation) +{ + uint32_t reg; + reg = AFIO_CPSCTL; + + /* reset the AFIO_CPSCTL_CPS_EN bit and set according to gpio_compensation */ + reg &= ~AFIO_CPSCTL_CPS_EN; + AFIO_CPSCTL = (reg | compensation); +} + +/*! + \brief check the I/O compensation cell is ready or not + \param[in] none + \param[out] none + \retval FlagStatus: SET or RESET + */ +FlagStatus gpio_compensation_flag_get(void) +{ + if(((uint32_t)RESET) != (AFIO_CPSCTL & AFIO_CPSCTL_CPS_RDY)){ + return SET; + }else{ + return RESET; + } +} diff --git a/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_standard_peripheral/Source/gd32f30x_i2c.c b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_standard_peripheral/Source/gd32f30x_i2c.c new file mode 100644 index 0000000000..2da8dac538 --- /dev/null +++ b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_standard_peripheral/Source/gd32f30x_i2c.c @@ -0,0 +1,737 @@ +/*! + \file gd32f30x_i2c.c + \brief I2C driver + + \version 2017-02-10, V1.0.0, firmware for GD32F30x + \version 2018-10-10, V1.1.0, firmware for GD32F30x + \version 2018-12-25, V2.0.0, firmware for GD32F30x + \version 2019-04-16, V2.0.1, firmware for GD32F30x + \version 2020-09-30, V2.1.0, firmware for GD32F30x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "gd32f30x_i2c.h" + +#define I2C_ERROR_HANDLE(s) do{}while(1) + +#define I2CCLK_MAX ((uint32_t)0x0000003CU) /*!< i2cclk maximum value */ +#define I2CCLK_MIN ((uint32_t)0x00000002U) /*!< i2cclk minimum value */ +#define I2C_FLAG_MASK ((uint32_t)0x0000FFFFU) /*!< i2c flag mask */ +#define I2C_ADDRESS_MASK ((uint32_t)0x000003FFU) /*!< i2c address mask */ +#define I2C_ADDRESS2_MASK ((uint32_t)0x000000FEU) /*!< the second i2c address mask */ + +/* I2C register bit offset */ +#define STAT1_PECV_OFFSET ((uint32_t)8U) /* bit offset of PECV in I2C_STAT1 */ + +/*! + \brief reset I2C + \param[in] i2c_periph: I2Cx(x=0,1) + \param[out] none + \retval none +*/ +void i2c_deinit(uint32_t i2c_periph) +{ + switch(i2c_periph){ + case I2C0: + /* reset I2C0 */ + rcu_periph_reset_enable(RCU_I2C0RST); + rcu_periph_reset_disable(RCU_I2C0RST); + break; + case I2C1: + /* reset I2C1 */ + rcu_periph_reset_enable(RCU_I2C1RST); + rcu_periph_reset_disable(RCU_I2C1RST); + break; + default: + break; + } +} + +/*! + \brief configure I2C clock + \param[in] i2c_periph: I2Cx(x=0,1) + \param[in] clkspeed: I2C clock speed, supports standard mode (up to 100 kHz), fast mode (up to 400 kHz) + and fast mode plus (up to 1MHz) + \param[in] dutycyc: duty cycle in fast mode or fast mode plus + only one parameter can be selected which is shown as below: + \arg I2C_DTCY_2: T_low/T_high=2 + \arg I2C_DTCY_16_9: T_low/T_high=16/9 + \param[out] none + \retval none +*/ +void i2c_clock_config(uint32_t i2c_periph, uint32_t clkspeed, uint32_t dutycyc) +{ + uint32_t pclk1, clkc, freq, risetime; + uint32_t temp; + + /* check the clkspeed value */ + if(0U == clkspeed){ + I2C_ERROR_HANDLE("the parameter can not be 0 \r\n"); + } + + pclk1 = rcu_clock_freq_get(CK_APB1); + /* I2C peripheral clock frequency */ + freq = (uint32_t)(pclk1/1000000U); + if(freq >= I2CCLK_MAX){ + freq = I2CCLK_MAX; + } + temp = I2C_CTL1(i2c_periph); + temp &= ~I2C_CTL1_I2CCLK; + temp |= freq; + + I2C_CTL1(i2c_periph) = temp; + + if(100000U >= clkspeed){ + /* the maximum SCL rise time is 1000ns in standard mode */ + risetime = (uint32_t)((pclk1/1000000U)+1U); + if(risetime >= I2CCLK_MAX){ + I2C_RT(i2c_periph) = I2CCLK_MAX; + }else if(risetime <= I2CCLK_MIN){ + I2C_RT(i2c_periph) = I2CCLK_MIN; + }else{ + I2C_RT(i2c_periph) = risetime; + } + clkc = (uint32_t)(pclk1/(clkspeed*2U)); + if(clkc < 0x04U){ + /* the CLKC in standard mode minmum value is 4 */ + clkc = 0x04U; + } + I2C_CKCFG(i2c_periph) |= (I2C_CKCFG_CLKC & clkc); + + }else if(400000U >= clkspeed){ + /* the maximum SCL rise time is 300ns in fast mode */ + I2C_RT(i2c_periph) = (uint32_t)(((freq*(uint32_t)300U)/(uint32_t)1000U)+(uint32_t)1U); + if(I2C_DTCY_2 == dutycyc){ + /* I2C duty cycle is 2 */ + clkc = (uint32_t)(pclk1/(clkspeed*3U)); + I2C_CKCFG(i2c_periph) &= ~I2C_CKCFG_DTCY; + }else{ + /* I2C duty cycle is 16/9 */ + clkc = (uint32_t)(pclk1/(clkspeed*25U)); + I2C_CKCFG(i2c_periph) |= I2C_CKCFG_DTCY; + } + if(0U == (clkc & I2C_CKCFG_CLKC)){ + /* the CLKC in fast mode minmum value is 1 */ + clkc |= 0x0001U; + } + I2C_CKCFG(i2c_periph) |= I2C_CKCFG_FAST; + I2C_CKCFG(i2c_periph) |= clkc; + }else{ + /* fast mode plus, the maximum SCL rise time is 120ns */ + I2C_RT(i2c_periph) = (uint32_t)(((freq*(uint32_t)120U)/(uint32_t)1000U)+(uint32_t)1U); + if(I2C_DTCY_2 == dutycyc){ + /* I2C duty cycle is 2 */ + clkc = (uint32_t)(pclk1/(clkspeed*3U)); + I2C_CKCFG(i2c_periph) &= ~I2C_CKCFG_DTCY; + }else{ + /* I2C duty cycle is 16/9 */ + clkc = (uint32_t)(pclk1/(clkspeed*25U)); + I2C_CKCFG(i2c_periph) |= I2C_CKCFG_DTCY; + } + /* enable fast mode */ + I2C_CKCFG(i2c_periph) |= I2C_CKCFG_FAST; + I2C_CKCFG(i2c_periph) |= clkc; + /* enable I2C fast mode plus */ + I2C_FMPCFG(i2c_periph) = I2C_FMPCFG_FMPEN; + } +} + +/*! + \brief configure I2C address + \param[in] i2c_periph: I2Cx(x=0,1) + \param[in] mode: + only one parameter can be selected which is shown as below: + \arg I2C_I2CMODE_ENABLE: I2C mode + \arg I2C_SMBUSMODE_ENABLE: SMBus mode + \param[in] addformat: 7bits or 10bits + only one parameter can be selected which is shown as below: + \arg I2C_ADDFORMAT_7BITS: 7bits + \arg I2C_ADDFORMAT_10BITS: 10bits + \param[in] addr: I2C address + \param[out] none + \retval none +*/ +void i2c_mode_addr_config(uint32_t i2c_periph, uint32_t mode, uint32_t addformat, uint32_t addr) +{ + /* SMBus/I2C mode selected */ + uint32_t ctl = 0U; + + ctl = I2C_CTL0(i2c_periph); + ctl &= ~(I2C_CTL0_SMBEN); + ctl |= mode; + I2C_CTL0(i2c_periph) = ctl; + /* configure address */ + addr = addr & I2C_ADDRESS_MASK; + I2C_SADDR0(i2c_periph) = (addformat | addr); +} + +/*! + \brief SMBus type selection + \param[in] i2c_periph: I2Cx(x=0,1) + \param[in] type: + only one parameter can be selected which is shown as below: + \arg I2C_SMBUS_DEVICE: device + \arg I2C_SMBUS_HOST: host + \param[out] none + \retval none +*/ +void i2c_smbus_type_config(uint32_t i2c_periph, uint32_t type) +{ + if(I2C_SMBUS_HOST == type){ + I2C_CTL0(i2c_periph) |= I2C_CTL0_SMBSEL; + }else{ + I2C_CTL0(i2c_periph) &= ~(I2C_CTL0_SMBSEL); + } +} + +/*! + \brief whether or not to send an ACK + \param[in] i2c_periph: I2Cx(x=0,1) + \param[in] ack: + only one parameter can be selected which is shown as below: + \arg I2C_ACK_ENABLE: ACK will be sent + \arg I2C_ACK_DISABLE: ACK will not be sent + \param[out] none + \retval none +*/ +void i2c_ack_config(uint32_t i2c_periph, uint32_t ack) +{ + if(I2C_ACK_ENABLE == ack){ + I2C_CTL0(i2c_periph) |= I2C_CTL0_ACKEN; + }else{ + I2C_CTL0(i2c_periph) &= ~(I2C_CTL0_ACKEN); + } +} + +/*! + \brief configure I2C POAP position + \param[in] i2c_periph: I2Cx(x=0,1) + \param[in] pos: + only one parameter can be selected which is shown as below: + \arg I2C_ACKPOS_CURRENT: whether to send ACK or not for the current + \arg I2C_ACKPOS_NEXT: whether to send ACK or not for the next byte + \param[out] none + \retval none +*/ +void i2c_ackpos_config(uint32_t i2c_periph, uint32_t pos) +{ + /* configure I2C POAP position */ + if(I2C_ACKPOS_NEXT == pos){ + I2C_CTL0(i2c_periph) |= I2C_CTL0_POAP; + }else{ + I2C_CTL0(i2c_periph) &= ~(I2C_CTL0_POAP); + } +} + +/*! + \brief master sends slave address + \param[in] i2c_periph: I2Cx(x=0,1) + \param[in] addr: slave address + \param[in] trandirection: transmitter or receiver + only one parameter can be selected which is shown as below: + \arg I2C_TRANSMITTER: transmitter + \arg I2C_RECEIVER: receiver + \param[out] none + \retval none +*/ +void i2c_master_addressing(uint32_t i2c_periph, uint32_t addr, uint32_t trandirection) +{ + /* master is a transmitter or a receiver */ + if(I2C_TRANSMITTER == trandirection){ + addr = addr & I2C_TRANSMITTER; + }else{ + addr = addr | I2C_RECEIVER; + } + /* send slave address */ + I2C_DATA(i2c_periph) = addr; +} + +/*! + \brief enable dual-address mode + \param[in] i2c_periph: I2Cx(x=0,1) + \param[in] dualaddr: the second address in dual-address mode + \param[out] none + \retval none +*/ +void i2c_dualaddr_enable(uint32_t i2c_periph, uint32_t dualaddr) +{ + /* configure address */ + dualaddr = dualaddr & I2C_ADDRESS2_MASK; + I2C_SADDR1(i2c_periph) = (I2C_SADDR1_DUADEN | dualaddr); +} + +/*! + \brief disable dual-address mode + \param[in] i2c_periph: I2Cx(x=0,1) + \param[out] none + \retval none +*/ +void i2c_dualaddr_disable(uint32_t i2c_periph) +{ + I2C_SADDR1(i2c_periph) &= ~(I2C_SADDR1_DUADEN); +} + +/*! + \brief enable I2C + \param[in] i2c_periph: I2Cx(x=0,1) + \param[out] none + \retval none +*/ +void i2c_enable(uint32_t i2c_periph) +{ + I2C_CTL0(i2c_periph) |= I2C_CTL0_I2CEN; +} + +/*! + \brief disable I2C + \param[in] i2c_periph: I2Cx(x=0,1) + \param[out] none + \retval none +*/ +void i2c_disable(uint32_t i2c_periph) +{ + I2C_CTL0(i2c_periph) &= ~(I2C_CTL0_I2CEN); +} + +/*! + \brief generate a START condition on I2C bus + \param[in] i2c_periph: I2Cx(x=0,1) + \param[out] none + \retval none +*/ +void i2c_start_on_bus(uint32_t i2c_periph) +{ + I2C_CTL0(i2c_periph) |= I2C_CTL0_START; +} + +/*! + \brief generate a STOP condition on I2C bus + \param[in] i2c_periph: I2Cx(x=0,1) + \param[out] none + \retval none +*/ +void i2c_stop_on_bus(uint32_t i2c_periph) +{ + I2C_CTL0(i2c_periph) |= I2C_CTL0_STOP; +} + +/*! + \brief I2C transmit data function + \param[in] i2c_periph: I2Cx(x=0,1) + \param[in] data: data of transmission + \param[out] none + \retval none +*/ +void i2c_data_transmit(uint32_t i2c_periph, uint8_t data) +{ + I2C_DATA(i2c_periph) = DATA_TRANS(data); +} + +/*! + \brief I2C receive data function + \param[in] i2c_periph: I2Cx(x=0,1) + \param[out] none + \retval data of received +*/ +uint8_t i2c_data_receive(uint32_t i2c_periph) +{ + return (uint8_t)DATA_RECV(I2C_DATA(i2c_periph)); +} + +/*! + \brief enable I2C DMA mode + \param[in] i2c_periph: I2Cx(x=0,1) + \param[in] dmastate: + only one parameter can be selected which is shown as below: + \arg I2C_DMA_ON: DMA mode enable + \arg I2C_DMA_OFF: DMA mode disable + \param[out] none + \retval none +*/ +void i2c_dma_enable(uint32_t i2c_periph, uint32_t dmastate) +{ + /* configure I2C DMA function */ + uint32_t ctl = 0U; + + ctl = I2C_CTL1(i2c_periph); + ctl &= ~(I2C_CTL1_DMAON); + ctl |= dmastate; + I2C_CTL1(i2c_periph) = ctl; +} + +/*! + \brief configure whether next DMA EOT is DMA last transfer or not + \param[in] i2c_periph: I2Cx(x=0,1) + \param[in] dmalast: + only one parameter can be selected which is shown as below: + \arg I2C_DMALST_ON: next DMA EOT is the last transfer + \arg I2C_DMALST_OFF: next DMA EOT is not the last transfer + \param[out] none + \retval none +*/ +void i2c_dma_last_transfer_config(uint32_t i2c_periph, uint32_t dmalast) +{ + /* configure DMA last transfer */ + uint32_t ctl = 0U; + + ctl = I2C_CTL1(i2c_periph); + ctl &= ~(I2C_CTL1_DMALST); + ctl |= dmalast; + I2C_CTL1(i2c_periph) = ctl; +} + +/*! + \brief whether to stretch SCL low when data is not ready in slave mode + \param[in] i2c_periph: I2Cx(x=0,1) + \param[in] stretchpara: + only one parameter can be selected which is shown as below: + \arg I2C_SCLSTRETCH_ENABLE: SCL stretching is enabled + \arg I2C_SCLSTRETCH_DISABLE: SCL stretching is disabled + \param[out] none + \retval none +*/ +void i2c_stretch_scl_low_config(uint32_t i2c_periph, uint32_t stretchpara) +{ + /* configure I2C SCL strerching enable or disable */ + uint32_t ctl = 0U; + + ctl = I2C_CTL0(i2c_periph); + ctl &= ~(I2C_CTL0_SS); + ctl |= stretchpara; + I2C_CTL0(i2c_periph) = ctl; +} + +/*! + \brief whether or not to response to a general call + \param[in] i2c_periph: I2Cx(x=0,1) + \param[in] gcallpara: + only one parameter can be selected which is shown as below: + \arg I2C_GCEN_ENABLE: slave will response to a general call + \arg I2C_GCEN_DISABLE: slave will not response to a general call + \param[out] none + \retval none +*/ +void i2c_slave_response_to_gcall_config(uint32_t i2c_periph, uint32_t gcallpara) +{ + /* configure slave response to a general call enable or disable */ + uint32_t ctl = 0U; + + ctl = I2C_CTL0(i2c_periph); + ctl &= ~(I2C_CTL0_GCEN); + ctl |= gcallpara; + I2C_CTL0(i2c_periph) = ctl; +} + +/*! + \brief software reset I2C + \param[in] i2c_periph: I2Cx(x=0,1) + \param[in] sreset: + only one parameter can be selected which is shown as below: + \arg I2C_SRESET_SET: I2C is under reset + \arg I2C_SRESET_RESET: I2C is not under reset + \param[out] none + \retval none +*/ +void i2c_software_reset_config(uint32_t i2c_periph, uint32_t sreset) +{ + /* modify CTL0 and configure software reset I2C state */ + uint32_t ctl = 0U; + + ctl = I2C_CTL0(i2c_periph); + ctl &= ~(I2C_CTL0_SRESET); + ctl |= sreset; + I2C_CTL0(i2c_periph) = ctl; +} + +/*! + \brief I2C PEC calculation on or off + \param[in] i2c_periph: I2Cx(x=0,1) + \param[in] pecpara: + only one parameter can be selected which is shown as below: + \arg I2C_PEC_ENABLE: PEC calculation on + \arg I2C_PEC_DISABLE: PEC calculation off + \param[out] none + \retval none +*/ +void i2c_pec_enable(uint32_t i2c_periph, uint32_t pecstate) +{ + /* on/off PEC calculation */ + uint32_t ctl = 0U; + + ctl = I2C_CTL0(i2c_periph); + ctl &= ~(I2C_CTL0_PECEN); + ctl |= pecstate; + I2C_CTL0(i2c_periph) = ctl; +} + +/*! + \brief I2C whether to transfer PEC value + \param[in] i2c_periph: I2Cx(x=0,1) + \param[in] pecpara: + only one parameter can be selected which is shown as below: + \arg I2C_PECTRANS_ENABLE: transfer PEC + \arg I2C_PECTRANS_DISABLE: not transfer PEC + \param[out] none + \retval none +*/ +void i2c_pec_transfer_enable(uint32_t i2c_periph, uint32_t pecpara) +{ + /* whether to transfer PEC */ + uint32_t ctl = 0U; + + ctl = I2C_CTL0(i2c_periph); + ctl &= ~(I2C_CTL0_PECTRANS); + ctl |= pecpara; + I2C_CTL0(i2c_periph) = ctl; +} + +/*! + \brief get packet error checking value + \param[in] i2c_periph: I2Cx(x=0,1) + \param[out] none + \retval PEC value +*/ +uint8_t i2c_pec_value_get(uint32_t i2c_periph) +{ + return (uint8_t)((I2C_STAT1(i2c_periph) & I2C_STAT1_PECV)>>STAT1_PECV_OFFSET); +} + +/*! + \brief I2C issue alert through SMBA pin + \param[in] i2c_periph: I2Cx(x=0,1) + \param[in] smbuspara: + only one parameter can be selected which is shown as below: + \arg I2C_SALTSEND_ENABLE: issue alert through SMBA pin + \arg I2C_SALTSEND_DISABLE: not issue alert through SMBA pin + \param[out] none + \retval none +*/ +void i2c_smbus_issue_alert(uint32_t i2c_periph, uint32_t smbuspara) +{ + /* issue alert through SMBA pin configure*/ + uint32_t ctl = 0U; + + ctl = I2C_CTL0(i2c_periph); + ctl &= ~(I2C_CTL0_SALT); + ctl |= smbuspara; + I2C_CTL0(i2c_periph) = ctl; +} + +/*! + \brief enable or disable I2C ARP protocol in SMBus switch + \param[in] i2c_periph: I2Cx(x=0,1) + \param[in] smbuspara: + only one parameter can be selected which is shown as below: + \arg I2C_ARP_ENABLE: enable ARP + \arg I2C_ARP_DISABLE: disable ARP + \param[out] none + \retval none +*/ +void i2c_smbus_arp_enable(uint32_t i2c_periph, uint32_t arpstate) +{ + /* enable or disable I2C ARP protocol*/ + uint32_t ctl = 0U; + + ctl = I2C_CTL0(i2c_periph); + ctl &= ~(I2C_CTL0_ARPEN); + ctl |= arpstate; + I2C_CTL0(i2c_periph) = ctl; +} + +/*! + \brief check I2C flag is set or not + \param[in] i2c_periph: I2Cx(x=0,1) + \param[in] flag: I2C flags, refer to i2c_flag_enum + only one parameter can be selected which is shown as below: + \arg I2C_FLAG_SBSEND: start condition send out + \arg I2C_FLAG_ADDSEND: address is sent in master mode or received and matches in slave mode + \arg I2C_FLAG_BTC: byte transmission finishes + \arg I2C_FLAG_ADD10SEND: header of 10-bit address is sent in master mode + \arg I2C_FLAG_STPDET: stop condition detected in slave mode + \arg I2C_FLAG_RBNE: I2C_DATA is not Empty during receiving + \arg I2C_FLAG_TBE: I2C_DATA is empty during transmitting + \arg I2C_FLAG_BERR: a bus error occurs indication a unexpected start or stop condition on I2C bus + \arg I2C_FLAG_LOSTARB: arbitration lost in master mode + \arg I2C_FLAG_AERR: acknowledge error + \arg I2C_FLAG_OUERR: overrun or underrun situation occurs in slave mode + \arg I2C_FLAG_PECERR: PEC error when receiving data + \arg I2C_FLAG_SMBTO: timeout signal in SMBus mode + \arg I2C_FLAG_SMBALT: SMBus alert status + \arg I2C_FLAG_MASTER: a flag indicating whether I2C block is in master or slave mode + \arg I2C_FLAG_I2CBSY: busy flag + \arg I2C_FLAG_TRS: whether the I2C is a transmitter or a receiver + \arg I2C_FLAG_RXGC: general call address (00h) received + \arg I2C_FLAG_DEFSMB: default address of SMBus device + \arg I2C_FLAG_HSTSMB: SMBus host header detected in slave mode + \arg I2C_FLAG_DUMOD: dual flag in slave mode indicating which address is matched in dual-address mode + \param[out] none + \retval FlagStatus: SET or RESET +*/ +FlagStatus i2c_flag_get(uint32_t i2c_periph, i2c_flag_enum flag) +{ + if(RESET != (I2C_REG_VAL(i2c_periph, flag) & BIT(I2C_BIT_POS(flag)))){ + return SET; + }else{ + return RESET; + } +} + +/*! + \brief clear I2C flag + \param[in] i2c_periph: I2Cx(x=0,1) + \param[in] flag: I2C flags, refer to i2c_flag_enum + only one parameter can be selected which is shown as below: + \arg I2C_FLAG_SMBALT: SMBus Alert status + \arg I2C_FLAG_SMBTO: timeout signal in SMBus mode + \arg I2C_FLAG_PECERR: PEC error when receiving data + \arg I2C_FLAG_OUERR: over-run or under-run situation occurs in slave mode + \arg I2C_FLAG_AERR: acknowledge error + \arg I2C_FLAG_LOSTARB: arbitration lost in master mode + \arg I2C_FLAG_BERR: a bus error + \arg I2C_FLAG_ADDSEND: cleared by reading I2C_STAT0 and reading I2C_STAT1 + \param[out] none + \retval none +*/ +void i2c_flag_clear(uint32_t i2c_periph, i2c_flag_enum flag) +{ + if(I2C_FLAG_ADDSEND == flag){ + /* read I2C_STAT0 and then read I2C_STAT1 to clear ADDSEND */ + I2C_STAT0(i2c_periph); + I2C_STAT1(i2c_periph); + }else{ + I2C_REG_VAL(i2c_periph, flag) &= ~BIT(I2C_BIT_POS(flag)); + } +} + +/*! + \brief enable I2C interrupt + \param[in] i2c_periph: I2Cx(x=0,1) + \param[in] interrupt: I2C interrupts, refer to i2c_interrupt_enum + only one parameter can be selected which is shown as below: + \arg I2C_INT_ERR: error interrupt enable + \arg I2C_INT_EV: event interrupt enable + \arg I2C_INT_BUF: buffer interrupt enable + \param[out] none + \retval none +*/ +void i2c_interrupt_enable(uint32_t i2c_periph, i2c_interrupt_enum interrupt) +{ + I2C_REG_VAL(i2c_periph, interrupt) |= BIT(I2C_BIT_POS(interrupt)); +} + +/*! + \brief disable I2C interrupt + \param[in] i2c_periph: I2Cx(x=0,1) + \param[in] interrupt: I2C interrupts, refer to i2c_flag_enum + only one parameter can be selected which is shown as below: + \arg I2C_INT_ERR: error interrupt enable + \arg I2C_INT_EV: event interrupt enable + \arg I2C_INT_BUF: buffer interrupt enable + \param[out] none + \retval none +*/ +void i2c_interrupt_disable(uint32_t i2c_periph, i2c_interrupt_enum interrupt) +{ + I2C_REG_VAL(i2c_periph, interrupt) &= ~BIT(I2C_BIT_POS(interrupt)); +} + +/*! + \brief check I2C interrupt flag + \param[in] i2c_periph: I2Cx(x=0,1) + \param[in] int_flag: I2C interrupt flags, refer to i2c_interrupt_flag_enum + only one parameter can be selected which is shown as below: + \arg I2C_INT_FLAG_SBSEND: start condition sent out in master mode interrupt flag + \arg I2C_INT_FLAG_ADDSEND: address is sent in master mode or received and matches in slave mode interrupt flag + \arg I2C_INT_FLAG_BTC: byte transmission finishes + \arg I2C_INT_FLAG_ADD10SEND: header of 10-bit address is sent in master mode interrupt flag + \arg I2C_INT_FLAG_STPDET: etop condition detected in slave mode interrupt flag + \arg I2C_INT_FLAG_RBNE: I2C_DATA is not Empty during receiving interrupt flag + \arg I2C_INT_FLAG_TBE: I2C_DATA is empty during transmitting interrupt flag + \arg I2C_INT_FLAG_BERR: a bus error occurs indication a unexpected start or stop condition on I2C bus interrupt flag + \arg I2C_INT_FLAG_LOSTARB: arbitration lost in master mode interrupt flag + \arg I2C_INT_FLAG_AERR: acknowledge error interrupt flag + \arg I2C_INT_FLAG_OUERR: over-run or under-run situation occurs in slave mode interrupt flag + \arg I2C_INT_FLAG_PECERR: PEC error when receiving data interrupt flag + \arg I2C_INT_FLAG_SMBTO: timeout signal in SMBus mode interrupt flag + \arg I2C_INT_FLAG_SMBALT: SMBus Alert status interrupt flag + \param[out] none + \retval FlagStatus: SET or RESET +*/ +FlagStatus i2c_interrupt_flag_get(uint32_t i2c_periph, i2c_interrupt_flag_enum int_flag) +{ + uint32_t intenable = 0U, flagstatus = 0U, bufie; + + /* check BUFIE */ + bufie = I2C_CTL1(i2c_periph)&I2C_CTL1_BUFIE; + + /* get the interrupt enable bit status */ + intenable = (I2C_REG_VAL(i2c_periph, int_flag) & BIT(I2C_BIT_POS(int_flag))); + /* get the corresponding flag bit status */ + flagstatus = (I2C_REG_VAL2(i2c_periph, int_flag) & BIT(I2C_BIT_POS2(int_flag))); + + if((I2C_INT_FLAG_RBNE == int_flag) || (I2C_INT_FLAG_TBE == int_flag)){ + if(intenable && bufie){ + intenable = 1U; + }else{ + intenable = 0U; + } + } + if((0U != flagstatus) && (0U != intenable)){ + return SET; + }else{ + return RESET; + } +} + +/*! + \brief clear I2C interrupt flag + \param[in] i2c_periph: I2Cx(x=0,1) + \param[in] intflag: I2C interrupt flags, refer to i2c_interrupt_flag_enum + only one parameter can be selected which is shown as below: + \arg I2C_INT_FLAG_ADDSEND: address is sent in master mode or received and matches in slave mode interrupt flag + \arg I2C_INT_FLAG_BERR: a bus error occurs indication a unexpected start or stop condition on I2C bus interrupt flag + \arg I2C_INT_FLAG_LOSTARB: arbitration lost in master mode interrupt flag + \arg I2C_INT_FLAG_AERR: acknowledge error interrupt flag + \arg I2C_INT_FLAG_OUERR: over-run or under-run situation occurs in slave mode interrupt flag + \arg I2C_INT_FLAG_PECERR: PEC error when receiving data interrupt flag + \arg I2C_INT_FLAG_SMBTO: timeout signal in SMBus mode interrupt flag + \arg I2C_INT_FLAG_SMBALT: SMBus Alert status interrupt flag + \param[out] none + \retval none +*/ +void i2c_interrupt_flag_clear(uint32_t i2c_periph, i2c_interrupt_flag_enum int_flag) +{ + if(I2C_INT_FLAG_ADDSEND == int_flag){ + /* read I2C_STAT0 and then read I2C_STAT1 to clear ADDSEND */ + I2C_STAT0(i2c_periph); + I2C_STAT1(i2c_periph); + }else{ + I2C_REG_VAL2(i2c_periph, int_flag) &= ~BIT(I2C_BIT_POS2(int_flag)); + } +} diff --git a/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_standard_peripheral/Source/gd32f30x_misc.c b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_standard_peripheral/Source/gd32f30x_misc.c new file mode 100644 index 0000000000..884d312355 --- /dev/null +++ b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_standard_peripheral/Source/gd32f30x_misc.c @@ -0,0 +1,175 @@ +/*! + \file gd32f30x_misc.c + \brief MISC driver + + \version 2017-02-10, V1.0.0, firmware for GD32F30x + \version 2018-10-10, V1.1.0, firmware for GD32F30x + \version 2018-12-25, V2.0.0, firmware for GD32F30x + \version 2020-09-30, V2.1.0, firmware for GD32F30x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "gd32f30x_misc.h" + +/*! + \brief set the priority group + \param[in] nvic_prigroup: the NVIC priority group + \arg NVIC_PRIGROUP_PRE0_SUB4:0 bits for pre-emption priority 4 bits for subpriority + \arg NVIC_PRIGROUP_PRE1_SUB3:1 bits for pre-emption priority 3 bits for subpriority + \arg NVIC_PRIGROUP_PRE2_SUB2:2 bits for pre-emption priority 2 bits for subpriority + \arg NVIC_PRIGROUP_PRE3_SUB1:3 bits for pre-emption priority 1 bits for subpriority + \arg NVIC_PRIGROUP_PRE4_SUB0:4 bits for pre-emption priority 0 bits for subpriority + \param[out] none + \retval none +*/ +void nvic_priority_group_set(uint32_t nvic_prigroup) +{ + /* set the priority group value */ + SCB->AIRCR = NVIC_AIRCR_VECTKEY_MASK | nvic_prigroup; +} + +/*! + \brief enable NVIC request + \param[in] nvic_irq: the NVIC interrupt request, detailed in IRQn_Type + \param[in] nvic_irq_pre_priority: the pre-emption priority needed to set + \param[in] nvic_irq_sub_priority: the subpriority needed to set + \param[out] none + \retval none +*/ +void nvic_irq_enable(uint8_t nvic_irq, uint8_t nvic_irq_pre_priority, + uint8_t nvic_irq_sub_priority) +{ + uint32_t temp_priority = 0x00U, temp_pre = 0x00U, temp_sub = 0x00U; + /* use the priority group value to get the temp_pre and the temp_sub */ + if(((SCB->AIRCR) & (uint32_t)0x700U)==NVIC_PRIGROUP_PRE0_SUB4){ + temp_pre=0U; + temp_sub=0x4U; + }else if(((SCB->AIRCR) & (uint32_t)0x700U)==NVIC_PRIGROUP_PRE1_SUB3){ + temp_pre=1U; + temp_sub=0x3U; + }else if(((SCB->AIRCR) & (uint32_t)0x700U)==NVIC_PRIGROUP_PRE2_SUB2){ + temp_pre=2U; + temp_sub=0x2U; + }else if(((SCB->AIRCR) & (uint32_t)0x700U)==NVIC_PRIGROUP_PRE3_SUB1){ + temp_pre=3U; + temp_sub=0x1U; + }else if(((SCB->AIRCR) & (uint32_t)0x700U)==NVIC_PRIGROUP_PRE4_SUB0){ + temp_pre=4U; + temp_sub=0x0U; + }else{ + nvic_priority_group_set(NVIC_PRIGROUP_PRE2_SUB2); + temp_pre=2U; + temp_sub=0x2U; + } + /* get the temp_priority to fill the NVIC->IP register */ + temp_priority = (uint32_t)nvic_irq_pre_priority << (0x4U - temp_pre); + temp_priority |= nvic_irq_sub_priority &(0x0FU >> (0x4U - temp_sub)); + temp_priority = temp_priority << 0x04U; + NVIC->IP[nvic_irq] = (uint8_t)temp_priority; + /* enable the selected IRQ */ + NVIC->ISER[nvic_irq >> 0x05U] = (uint32_t)0x01U << (nvic_irq & (uint8_t)0x1FU); +} + +/*! + \brief disable NVIC request + \param[in] nvic_irq: the NVIC interrupt request, detailed in IRQn_Type + \param[out] none + \retval none +*/ +void nvic_irq_disable(uint8_t nvic_irq) +{ + /* disable the selected IRQ.*/ + NVIC->ICER[nvic_irq >> 0x05] = (uint32_t)0x01 << (nvic_irq & (uint8_t)0x1F); +} + +/*! + \brief set the NVIC vector table base address + \param[in] nvic_vict_tab: the RAM or FLASH base address + \arg NVIC_VECTTAB_RAM: RAM base address + \are NVIC_VECTTAB_FLASH: Flash base address + \param[in] offset: Vector Table offset + \param[out] none + \retval none +*/ +void nvic_vector_table_set(uint32_t nvic_vict_tab, uint32_t offset) +{ + SCB->VTOR = nvic_vict_tab | (offset & NVIC_VECTTAB_OFFSET_MASK); +} + +/*! + \brief set the state of the low power mode + \param[in] lowpower_mode: the low power mode state + \arg SCB_LPM_SLEEP_EXIT_ISR: if chose this para, the system always enter low power + mode by exiting from ISR + \arg SCB_LPM_DEEPSLEEP: if chose this para, the system will enter the DEEPSLEEP mode + \arg SCB_LPM_WAKE_BY_ALL_INT: if chose this para, the lowpower mode can be woke up + by all the enable and disable interrupts + \param[out] none + \retval none +*/ +void system_lowpower_set(uint8_t lowpower_mode) +{ + SCB->SCR |= (uint32_t)lowpower_mode; +} + +/*! + \brief reset the state of the low power mode + \param[in] lowpower_mode: the low power mode state + \arg SCB_LPM_SLEEP_EXIT_ISR: if chose this para, the system will exit low power + mode by exiting from ISR + \arg SCB_LPM_DEEPSLEEP: if chose this para, the system will enter the SLEEP mode + \arg SCB_LPM_WAKE_BY_ALL_INT: if chose this para, the lowpower mode only can be + woke up by the enable interrupts + \param[out] none + \retval none +*/ +void system_lowpower_reset(uint8_t lowpower_mode) +{ + SCB->SCR &= (~(uint32_t)lowpower_mode); +} + +/*! + \brief set the systick clock source + \param[in] systick_clksource: the systick clock source needed to choose + \arg SYSTICK_CLKSOURCE_HCLK: systick clock source is from HCLK + \arg SYSTICK_CLKSOURCE_HCLK_DIV8: systick clock source is from HCLK/8 + \param[out] none + \retval none +*/ + +void systick_clksource_set(uint32_t systick_clksource) +{ + if(SYSTICK_CLKSOURCE_HCLK == systick_clksource ){ + /* set the systick clock source from HCLK */ + SysTick->CTRL |= SYSTICK_CLKSOURCE_HCLK; + }else{ + /* set the systick clock source from HCLK/8 */ + SysTick->CTRL &= SYSTICK_CLKSOURCE_HCLK_DIV8; + } +} diff --git a/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_standard_peripheral/Source/gd32f30x_pmu.c b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_standard_peripheral/Source/gd32f30x_pmu.c new file mode 100644 index 0000000000..164274c0eb --- /dev/null +++ b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_standard_peripheral/Source/gd32f30x_pmu.c @@ -0,0 +1,386 @@ +/*! + \file gd32f30x_pmu.c + \brief PMU driver + + \version 2017-02-10, V1.0.0, firmware for GD32F30x + \version 2018-10-10, V1.1.0, firmware for GD32F30x + \version 2018-12-25, V2.0.0, firmware for GD32F30x + \version 2020-09-30, V2.1.0, firmware for GD32F30x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + + +#include "gd32f30x_pmu.h" + +/*! + \brief reset PMU register + \param[in] none + \param[out] none + \retval none +*/ +void pmu_deinit(void) +{ + /* reset PMU */ + rcu_periph_reset_enable(RCU_PMURST); + rcu_periph_reset_disable(RCU_PMURST); +} + +/*! + \brief select low voltage detector threshold + \param[in] lvdt_n: + \arg PMU_LVDT_0: voltage threshold is 2.1V + \arg PMU_LVDT_1: voltage threshold is 2.3V + \arg PMU_LVDT_2: voltage threshold is 2.4V + \arg PMU_LVDT_3: voltage threshold is 2.6V + \arg PMU_LVDT_4: voltage threshold is 2.7V + \arg PMU_LVDT_5: voltage threshold is 2.9V + \arg PMU_LVDT_6: voltage threshold is 3.0V + \arg PMU_LVDT_7: voltage threshold is 3.1V + \param[out] none + \retval none +*/ +void pmu_lvd_select(uint32_t lvdt_n) +{ + /* disable LVD */ + PMU_CTL &= ~PMU_CTL_LVDEN; + /* clear LVDT bits */ + PMU_CTL &= ~PMU_CTL_LVDT; + /* set LVDT bits according to lvdt_n */ + PMU_CTL |= lvdt_n; + /* enable LVD */ + PMU_CTL |= PMU_CTL_LVDEN; +} + +/*! + \brief select LDO output voltage + this bit set by software when the main PLL closed, before closing PLL, change the system clock to IRC16M or HXTAL + \param[in] ldo_output: + \arg PMU_LDOVS_LOW: LDO output voltage low mode + \arg PMU_LDOVS_MID: LDO output voltage mid mode + \arg PMU_LDOVS_HIGH: LDO output voltage high mode + \param[out] none + \retval none +*/ +void pmu_ldo_output_select(uint32_t ldo_output) +{ + PMU_CTL &= ~PMU_CTL_LDOVS; + PMU_CTL |= ldo_output; +} + +/*! + \brief disable PMU lvd + \param[in] none + \param[out] none + \retval none +*/ +void pmu_lvd_disable(void) +{ + /* disable LVD */ + PMU_CTL &= ~PMU_CTL_LVDEN; +} + +/*! + \brief switch high-driver mode + this bit set by software only when IRC16M or HXTAL used as system clock + \param[in] highdr_switch: + \arg PMU_HIGHDR_SWITCH_NONE: disable high-driver mode switch + \arg PMU_HIGHDR_SWITCH_EN: enable high-driver mode switch + \param[out] none + \retval none +*/ +void pmu_highdriver_switch_select(uint32_t highdr_switch) +{ + /* wait for HDRF flag set */ + while(SET != pmu_flag_get(PMU_FLAG_HDRF)){ + } + PMU_CTL &= ~PMU_CTL_HDS; + PMU_CTL |= highdr_switch; +} + +/*! + \brief enable high-driver mode + this bit set by software only when IRC16M or HXTAL used as system clock + \param[in] none + \param[out] none + \retval none +*/ +void pmu_highdriver_mode_enable(void) +{ + PMU_CTL |= PMU_CTL_HDEN; +} + +/*! + \brief disable high-driver mode + \param[in] none + \param[out] none + \retval none +*/ +void pmu_highdriver_mode_disable(void) +{ + PMU_CTL &= ~PMU_CTL_HDEN; +} + +/*! + \brief enable low-driver mode in deep-sleep mode + \param[in] none + \param[out] none + \retval none +*/ +void pmu_lowdriver_mode_enable(void) +{ + PMU_CTL |= PMU_CTL_LDEN; +} + +/*! + \brief disable low-driver mode in deep-sleep mode + \param[in] none + \param[out] none + \retval none +*/ +void pmu_lowdriver_mode_disable(void) +{ + PMU_CTL &= ~PMU_CTL_LDEN; +} + +/*! + \brief driver mode when use low power LDO + \param[in] mode: + \arg PMU_NORMALDR_LOWPWR: normal driver when use low power LDO + \arg PMU_LOWDR_LOWPWR: low-driver mode enabled when LDEN is 11 and use low power LDO + \param[out] none + \retval none +*/ +void pmu_lowpower_driver_config(uint32_t mode) +{ + PMU_CTL &= ~PMU_CTL_LDLP; + PMU_CTL |= mode; +} + +/*! + \brief driver mode when use normal power LDO + \param[in] mode: + \arg PMU_NORMALDR_NORMALPWR: normal driver when use normal power LDO + \arg PMU_LOWDR_NORMALPWR: low-driver mode enabled when LDEN is 11 and use normal power LDO + \param[out] none + \retval none +*/ +void pmu_normalpower_driver_config(uint32_t mode) +{ + PMU_CTL &= ~PMU_CTL_LDNP; + PMU_CTL |= mode; +} + +/*! + \brief PMU work at sleep mode + \param[in] sleepmodecmd: + \arg WFI_CMD: use WFI command + \arg WFE_CMD: use WFE command + \param[out] none + \retval none +*/ +void pmu_to_sleepmode(uint8_t sleepmodecmd) +{ + /* clear sleepdeep bit of Cortex-M4 system control register */ + SCB->SCR &= ~((uint32_t)SCB_SCR_SLEEPDEEP_Msk); + + /* select WFI or WFE command to enter sleep mode */ + if(WFI_CMD == sleepmodecmd){ + __WFI(); + }else{ + __WFE(); + } +} + +/*! + \brief PMU work at deepsleep mode + \param[in] ldo + \arg PMU_LDO_NORMAL: LDO normal work when pmu enter deepsleep mode + \arg PMU_LDO_LOWPOWER: LDO work at low power mode when pmu enter deepsleep mode + \param[in] deepsleepmodecmd: + \arg WFI_CMD: use WFI command + \arg WFE_CMD: use WFE command + \param[out] none + \retval none +*/ +void pmu_to_deepsleepmode(uint32_t ldo,uint8_t deepsleepmodecmd) +{ + static uint32_t reg_snap[ 4 ]; + /* clear stbmod and ldolp bits */ + PMU_CTL &= ~((uint32_t)(PMU_CTL_STBMOD | PMU_CTL_LDOLP)); + + /* set ldolp bit according to pmu_ldo */ + PMU_CTL |= ldo; + + /* set sleepdeep bit of Cortex-M4 system control register */ + SCB->SCR |= SCB_SCR_SLEEPDEEP_Msk; + + reg_snap[ 0 ] = REG32( 0xE000E010U ); + reg_snap[ 1 ] = REG32( 0xE000E100U ); + reg_snap[ 2 ] = REG32( 0xE000E104U ); + reg_snap[ 3 ] = REG32( 0xE000E108U ); + + REG32( 0xE000E010U ) &= 0x00010004U; + REG32( 0xE000E180U ) = 0XFF7FF83DU; + REG32( 0xE000E184U ) = 0XBFFFF8FFU; + REG32( 0xE000E188U ) = 0xFFFFFFFFU; + + /* select WFI or WFE command to enter deepsleep mode */ + if(WFI_CMD == deepsleepmodecmd){ + __WFI(); + }else{ + __SEV(); + __WFE(); + __WFE(); + } + + REG32( 0xE000E010U ) = reg_snap[ 0 ] ; + REG32( 0xE000E100U ) = reg_snap[ 1 ] ; + REG32( 0xE000E104U ) = reg_snap[ 2 ] ; + REG32( 0xE000E108U ) = reg_snap[ 3 ] ; + + /* reset sleepdeep bit of Cortex-M4 system control register */ + SCB->SCR &= ~((uint32_t)SCB_SCR_SLEEPDEEP_Msk); +} + +/*! + \brief pmu work at standby mode + \param[in] standbymodecmd: + \arg WFI_CMD: use WFI command + \arg WFE_CMD: use WFE command + \param[out] none + \retval none +*/ +void pmu_to_standbymode(uint8_t standbymodecmd) +{ + /* set sleepdeep bit of Cortex-M4 system control register */ + SCB->SCR |= SCB_SCR_SLEEPDEEP_Msk; + + /* set stbmod bit */ + PMU_CTL |= PMU_CTL_STBMOD; + + /* reset wakeup flag */ + PMU_CTL |= PMU_CTL_WURST; + + /* select WFI or WFE command to enter standby mode */ + if(WFI_CMD == standbymodecmd){ + __WFI(); + }else{ + __WFE(); + } +} + +/*! + \brief enable backup domain write + \param[in] none + \param[out] none + \retval none +*/ +void pmu_backup_write_enable(void) +{ + PMU_CTL |= PMU_CTL_BKPWEN; +} + +/*! + \brief disable backup domain write + \param[in] none + \param[out] none + \retval none +*/ +void pmu_backup_write_disable(void) +{ + PMU_CTL &= ~PMU_CTL_BKPWEN; +} + +/*! + \brief enable wakeup pin + \param[in] none + \param[out] none + \retval none +*/ +void pmu_wakeup_pin_enable(void) +{ + PMU_CS |= PMU_CS_WUPEN; +} + +/*! + \brief disable wakeup pin + \param[in] none + \param[out] none + \retval none +*/ +void pmu_wakeup_pin_disable(void) +{ + PMU_CS &= ~PMU_CS_WUPEN; +} + +/*! + \brief clear flag bit + \param[in] flag_reset: + \arg PMU_FLAG_RESET_WAKEUP: reset wakeup flag + \arg PMU_FLAG_RESET_STANDBY: reset standby flag + \param[out] none + \retval none +*/ +void pmu_flag_clear(uint32_t flag_reset) +{ + switch(flag_reset){ + case PMU_FLAG_RESET_WAKEUP: + /* reset wakeup flag */ + PMU_CTL |= PMU_CTL_WURST; + break; + case PMU_FLAG_RESET_STANDBY: + /* reset standby flag */ + PMU_CTL |= PMU_CTL_STBRST; + break; + default : + break; + } +} + +/*! + \brief get flag state + \param[in] flag: + \arg PMU_FLAG_WAKEUP: wakeup flag + \arg PMU_FLAG_STANDBY: standby flag + \arg PMU_FLAG_LVD: lvd flag + \arg PMU_FLAG_LDOVSRF: LDO voltage select ready flag + \arg PMU_FLAG_HDRF: high-driver ready flag + \arg PMU_FLAG_HDSRF: high-driver switch ready flag + \arg PMU_FLAG_LDRF: low-driver mode ready flag + \param[out] none + \retval FlagStatus SET or RESET +*/ +FlagStatus pmu_flag_get(uint32_t flag) +{ + if(PMU_CS & flag){ + return SET; + }else{ + return RESET; + } +} diff --git a/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_standard_peripheral/Source/gd32f30x_rcu.c b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_standard_peripheral/Source/gd32f30x_rcu.c new file mode 100644 index 0000000000..f731d22c58 --- /dev/null +++ b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_standard_peripheral/Source/gd32f30x_rcu.c @@ -0,0 +1,1326 @@ +/*! + \file gd32f30x_rcu.c + \brief RCU driver + + \version 2017-02-10, V1.0.0, firmware for GD32F30x + \version 2018-10-10, V1.1.0, firmware for GD32F30x + \version 2018-12-25, V2.0.0, firmware for GD32F30x + \version 2020-09-30, V2.1.0, firmware for GD32F30x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "gd32f30x_rcu.h" + +/* define clock source */ +#define SEL_IRC8M ((uint16_t)0U) /* IRC8M is selected as CK_SYS */ +#define SEL_HXTAL ((uint16_t)1U) /* HXTAL is selected as CK_SYS */ +#define SEL_PLL ((uint16_t)2U) /* PLL is selected as CK_SYS */ + +/* define startup timeout count */ +#define OSC_STARTUP_TIMEOUT ((uint32_t)0x000FFFFFU) +#define LXTAL_STARTUP_TIMEOUT ((uint32_t)0x03FFFFFFU) + +/* ADC clock prescaler offset */ +#define RCU_ADC_PSC_OFFSET ((uint32_t)14U) + +/* RCU IRC8M adjust value mask and offset*/ +#define RCU_IRC8M_ADJUST_MASK ((uint8_t)0x1FU) +#define RCU_IRC8M_ADJUST_OFFSET ((uint32_t)3U) + +/* RCU PLL1 clock multiplication factor offset */ +#define RCU_CFG1_PLL1MF_OFFSET ((uint32_t)8U) +/* RCU PREDV1 division factor offset*/ +#define RCU_CFG1_PREDV1_OFFSET ((uint32_t)4U) + + +/*! + \brief deinitialize the RCU + \param[in] none + \param[out] none + \retval none +*/ +void rcu_deinit(void) +{ + /* enable IRC8M */ + RCU_CTL |= RCU_CTL_IRC8MEN; + rcu_osci_stab_wait(RCU_IRC8M); + + /* reset CFG0 register */ +#if (defined(GD32F30X_HD) || defined(GD32F30X_XD)) + RCU_CFG0 &= ~(RCU_CFG0_SCS | RCU_CFG0_AHBPSC | RCU_CFG0_APB1PSC | RCU_CFG0_APB2PSC | + RCU_CFG0_ADCPSC | RCU_CFG0_PLLSEL | RCU_CFG0_PREDV0 | RCU_CFG0_PLLMF | + RCU_CFG0_USBDPSC | RCU_CFG0_CKOUT0SEL | RCU_CFG0_PLLMF_4 | RCU_CFG0_ADCPSC_2 | RCU_CFG0_PLLMF_5 | RCU_CFG0_USBDPSC_2); +#elif defined(GD32F30X_CL) + RCU_CFG0 &= ~(RCU_CFG0_SCS | RCU_CFG0_AHBPSC | RCU_CFG0_APB1PSC | RCU_CFG0_APB2PSC | + RCU_CFG0_ADCPSC | RCU_CFG0_PLLSEL | RCU_CFG0_PREDV0_LSB | RCU_CFG0_PLLMF | + RCU_CFG0_USBFSPSC | RCU_CFG0_CKOUT0SEL | RCU_CFG0_ADCPSC_2 | RCU_CFG0_PLLMF_4 | RCU_CFG0_PLLMF_5 | RCU_CFG0_USBFSPSC_2); +#endif /* GD32F30X_HD and GD32F30X_XD */ + /* reset CTL register */ + RCU_CTL &= ~(RCU_CTL_HXTALEN | RCU_CTL_CKMEN | RCU_CTL_PLLEN); + RCU_CTL &= ~RCU_CTL_HXTALBPS; +#ifdef GD32F30X_CL + RCU_CTL &= ~(RCU_CTL_PLL1EN | RCU_CTL_PLL2EN); +#endif /* GD32F30X_CL */ + + /* reset INT and CFG1 register */ +#if (defined(GD32F30X_HD) || defined(GD32F30X_XD)) + RCU_INT = 0x009f0000U; + RCU_CFG1 &= ~(RCU_CFG1_ADCPSC_3 | RCU_CFG1_PLLPRESEL); +#elif defined(GD32F30X_CL) + RCU_INT = 0x00ff0000U; + RCU_CFG1 &= ~(RCU_CFG1_PREDV0 | RCU_CFG1_PREDV1 | RCU_CFG1_PLL1MF | RCU_CFG1_PLL2MF | + RCU_CFG1_PREDV0SEL | RCU_CFG1_I2S1SEL | RCU_CFG1_I2S2SEL | RCU_CFG1_ADCPSC_3 | + RCU_CFG1_PLLPRESEL | RCU_CFG1_PLL2MF_4); +#endif /* GD32F30X_HD and GD32F30X_XD */ +} + +/*! + \brief enable the peripherals clock + \param[in] periph: RCU peripherals, refer to rcu_periph_enum + only one parameter can be selected which is shown as below: + \arg RCU_GPIOx (x=A,B,C,D,E,F,G): GPIO ports clock + \arg RCU_AF : alternate function clock + \arg RCU_CRC: CRC clock + \arg RCU_DMAx (x=0,1): DMA clock + \arg RCU_ENET: ENET clock(CL series available) + \arg RCU_ENETTX: ENETTX clock(CL series available) + \arg RCU_ENETRX: ENETRX clock(CL series available) + \arg RCU_USBD: USBD clock(HD,XD series available) + \arg RCU_USBFS: USBFS clock(CL series available) + \arg RCU_EXMC: EXMC clock + \arg RCU_TIMERx (x=0,1,2,3,4,5,6,7,8,9,10,11,12,13,TIMER8..13 are not available for HD series): TIMER clock + \arg RCU_WWDGT: WWDGT clock + \arg RCU_SPIx (x=0,1,2): SPI clock + \arg RCU_USARTx (x=0,1,2): USART clock + \arg RCU_UARTx (x=3,4): UART clock + \arg RCU_I2Cx (x=0,1): I2C clock + \arg RCU_CANx (x=0,1,CAN1 is only available for CL series): CAN clock + \arg RCU_PMU: PMU clock + \arg RCU_DAC: DAC clock + \arg RCU_RTC: RTC clock + \arg RCU_ADCx (x=0,1,2,ADC2 is not available for CL series): ADC clock + \arg RCU_SDIO: SDIO clock(not available for CL series) + \arg RCU_CTC: CTC clock + \arg RCU_BKPI: BKP interface clock + \param[out] none + \retval none +*/ +void rcu_periph_clock_enable(rcu_periph_enum periph) +{ + RCU_REG_VAL(periph) |= BIT(RCU_BIT_POS(periph)); +} + +/*! + \brief disable the peripherals clock + \param[in] periph: RCU peripherals, refer to rcu_periph_enum + only one parameter can be selected which is shown as below: + \arg RCU_GPIOx (x=A,B,C,D,E,F,G): GPIO ports clock + \arg RCU_AF: alternate function clock + \arg RCU_CRC: CRC clock + \arg RCU_DMAx (x=0,1): DMA clock + \arg RCU_ENET: ENET clock(CL series available) + \arg RCU_ENETTX: ENETTX clock(CL series available) + \arg RCU_ENETRX: ENETRX clock(CL series available) + \arg RCU_USBD: USBD clock(HD,XD series available) + \arg RCU_USBFS: USBFS clock(CL series available) + \arg RCU_EXMC: EXMC clock + \arg RCU_TIMERx (x=0,1,2,3,4,5,6,7,8,9,10,11,12,13,TIMER8..13 are not available for HD series): TIMER clock + \arg RCU_WWDGT: WWDGT clock + \arg RCU_SPIx (x=0,1,2): SPI clock + \arg RCU_USARTx (x=0,1,2): USART clock + \arg RCU_UARTx (x=3,4): UART clock + \arg RCU_I2Cx (x=0,1): I2C clock + \arg RCU_CANx (x=0,1,CAN1 is only available for CL series): CAN clock + \arg RCU_PMU: PMU clock + \arg RCU_DAC: DAC clock + \arg RCU_RTC: RTC clock + \arg RCU_ADCx (x=0,1,2,ADC2 is not available for CL series): ADC clock + \arg RCU_SDIO: SDIO clock(not available for CL series) + \arg RCU_CTC: CTC clock + \arg RCU_BKPI: BKP interface clock + \param[out] none + \retval none +*/ +void rcu_periph_clock_disable(rcu_periph_enum periph) +{ + RCU_REG_VAL(periph) &= ~BIT(RCU_BIT_POS(periph)); +} + +/*! + \brief enable the peripherals clock when sleep mode + \param[in] periph: RCU peripherals, refer to rcu_periph_sleep_enum + only one parameter can be selected which is shown as below: + \arg RCU_FMC_SLP: FMC clock + \arg RCU_SRAM_SLP: SRAM clock + \param[out] none + \retval none +*/ +void rcu_periph_clock_sleep_enable(rcu_periph_sleep_enum periph) +{ + RCU_REG_VAL(periph) |= BIT(RCU_BIT_POS(periph)); +} + +/*! + \brief disable the peripherals clock when sleep mode + \param[in] periph: RCU peripherals, refer to rcu_periph_sleep_enum + only one parameter can be selected which is shown as below: + \arg RCU_FMC_SLP: FMC clock + \arg RCU_SRAM_SLP: SRAM clock + \param[out] none + \retval none +*/ +void rcu_periph_clock_sleep_disable(rcu_periph_sleep_enum periph) +{ + RCU_REG_VAL(periph) &= ~BIT(RCU_BIT_POS(periph)); +} + +/*! + \brief reset the peripherals + \param[in] periph_reset: RCU peripherals reset, refer to rcu_periph_reset_enum + only one parameter can be selected which is shown as below: + \arg RCU_GPIOxRST (x=A,B,C,D,E,F,G): reset GPIO ports + \arg RCU_AFRST : reset alternate function clock + \arg RCU_ENETRST: reset ENET(CL series available) + \arg RCU_USBDRST: reset USBD(HD,XD series available) + \arg RCU_USBFSRST: reset USBFS(CL series available) + \arg RCU_TIMERxRST (x=0,1,2,3,4,5,6,7,8,9,10,11,12,13,TIMER8..13 are not available for HD series): reset TIMER + \arg RCU_WWDGTRST: reset WWDGT + \arg RCU_SPIxRST (x=0,1,2): reset SPI + \arg RCU_USARTxRST (x=0,1,2): reset USART + \arg RCU_UARTxRST (x=3,4): reset UART + \arg RCU_I2CxRST (x=0,1): reset I2C + \arg RCU_CANxRST (x=0,1,CAN1 is only available for CL series): reset CAN + \arg RCU_PMURST: reset PMU + \arg RCU_DACRST: reset DAC + \arg RCU_ADCRST (x=0,1,2,ADC2 is not available for CL series): reset ADC + \arg RCU_CTCRST: reset CTC + \arg RCU_BKPIRST: reset BKPI + \param[out] none + \retval none +*/ +void rcu_periph_reset_enable(rcu_periph_reset_enum periph_reset) +{ + RCU_REG_VAL(periph_reset) |= BIT(RCU_BIT_POS(periph_reset)); +} + +/*! + \brief disable reset the peripheral + \param[in] periph_reset: RCU peripherals reset, refer to rcu_periph_reset_enum + only one parameter can be selected which is shown as below: + \arg RCU_GPIOxRST (x=A,B,C,D,E,F,G): reset GPIO ports + \arg RCU_AFRST : reset alternate function clock + \arg RCU_ENETRST: reset ENET(CL series available) + \arg RCU_USBDRST: reset USBD(HD,XD series available) + \arg RCU_USBFSRST: reset USBFS(CL series available) + \arg RCU_TIMERxRST (x=0,1,2,3,4,5,6,7,8,9,10,11,12,13,TIMER8..13 are not available for HD series): reset TIMER + \arg RCU_WWDGTRST: reset WWDGT + \arg RCU_SPIxRST (x=0,1,2): reset SPI + \arg RCU_USARTxRST (x=0,1,2): reset USART + \arg RCU_UARTxRST (x=3,4): reset UART + \arg RCU_I2CxRST (x=0,1): reset I2C + \arg RCU_CANxRST (x=0,1,CAN1 is only available for CL series): reset CAN + \arg RCU_PMURST: reset PMU + \arg RCU_DACRST: reset DAC + \arg RCU_ADCRST (x=0,1,2,ADC2 is not available for CL series): reset ADC + \arg RCU_CTCRST: reset CTC + \arg RCU_BKPIRST: reset BKPI + \param[out] none + \retval none +*/ +void rcu_periph_reset_disable(rcu_periph_reset_enum periph_reset) +{ + RCU_REG_VAL(periph_reset) &= ~BIT(RCU_BIT_POS(periph_reset)); +} + +/*! + \brief reset the BKP domain + \param[in] none + \param[out] none + \retval none +*/ +void rcu_bkp_reset_enable(void) +{ + RCU_BDCTL |= RCU_BDCTL_BKPRST; +} + +/*! + \brief disable the BKP domain reset + \param[in] none + \param[out] none + \retval none +*/ +void rcu_bkp_reset_disable(void) +{ + RCU_BDCTL &= ~RCU_BDCTL_BKPRST; +} + +/*! + \brief configure the system clock source + \param[in] ck_sys: system clock source select + only one parameter can be selected which is shown as below: + \arg RCU_CKSYSSRC_IRC8M: select CK_IRC8M as the CK_SYS source + \arg RCU_CKSYSSRC_HXTAL: select CK_HXTAL as the CK_SYS source + \arg RCU_CKSYSSRC_PLL: select CK_PLL as the CK_SYS source + \param[out] none + \retval none +*/ +void rcu_system_clock_source_config(uint32_t ck_sys) +{ + uint32_t reg; + + reg = RCU_CFG0; + /* reset the SCS bits and set according to ck_sys */ + reg &= ~RCU_CFG0_SCS; + RCU_CFG0 = (reg | ck_sys); +} + +/*! + \brief get the system clock source + \param[in] none + \param[out] none + \retval which clock is selected as CK_SYS source + \arg RCU_SCSS_IRC8M: CK_IRC8M is selected as the CK_SYS source + \arg RCU_SCSS_HXTAL: CK_HXTAL is selected as the CK_SYS source + \arg RCU_SCSS_PLL: CK_PLL is selected as the CK_SYS source +*/ +uint32_t rcu_system_clock_source_get(void) +{ + return (RCU_CFG0 & RCU_CFG0_SCSS); +} + +/*! + \brief configure the AHB clock prescaler selection + \param[in] ck_ahb: AHB clock prescaler selection + only one parameter can be selected which is shown as below: + \arg RCU_AHB_CKSYS_DIVx, x=1, 2, 4, 8, 16, 64, 128, 256, 512 + \param[out] none + \retval none +*/ +void rcu_ahb_clock_config(uint32_t ck_ahb) +{ + uint32_t reg; + + reg = RCU_CFG0; + + /* reset the AHBPSC bits and set according to ck_ahb */ + reg &= ~RCU_CFG0_AHBPSC; + RCU_CFG0 = (reg | ck_ahb); +} + +/*! + \brief configure the APB1 clock prescaler selection + \param[in] ck_apb1: APB1 clock prescaler selection + only one parameter can be selected which is shown as below: + \arg RCU_APB1_CKAHB_DIV1: select CK_AHB as CK_APB1 + \arg RCU_APB1_CKAHB_DIV2: select CK_AHB/2 as CK_APB1 + \arg RCU_APB1_CKAHB_DIV4: select CK_AHB/4 as CK_APB1 + \arg RCU_APB1_CKAHB_DIV8: select CK_AHB/8 as CK_APB1 + \arg RCU_APB1_CKAHB_DIV16: select CK_AHB/16 as CK_APB1 + \param[out] none + \retval none +*/ +void rcu_apb1_clock_config(uint32_t ck_apb1) +{ + uint32_t reg; + + reg = RCU_CFG0; + + /* reset the APB1PSC and set according to ck_apb1 */ + reg &= ~RCU_CFG0_APB1PSC; + RCU_CFG0 = (reg | ck_apb1); +} + +/*! + \brief configure the APB2 clock prescaler selection + \param[in] ck_apb2: APB2 clock prescaler selection + only one parameter can be selected which is shown as below: + \arg RCU_APB2_CKAHB_DIV1: select CK_AHB as CK_APB2 + \arg RCU_APB2_CKAHB_DIV2: select CK_AHB/2 as CK_APB2 + \arg RCU_APB2_CKAHB_DIV4: select CK_AHB/4 as CK_APB2 + \arg RCU_APB2_CKAHB_DIV8: select CK_AHB/8 as CK_APB2 + \arg RCU_APB2_CKAHB_DIV16: select CK_AHB/16 as CK_APB2 + \param[out] none + \retval none +*/ +void rcu_apb2_clock_config(uint32_t ck_apb2) +{ + uint32_t reg; + + reg = RCU_CFG0; + + /* reset the APB2PSC and set according to ck_apb2 */ + reg &= ~RCU_CFG0_APB2PSC; + RCU_CFG0 = (reg | ck_apb2); +} + +/*! + \brief configure the CK_OUT0 clock source + \param[in] ckout0_src: CK_OUT0 clock source selection + only one parameter can be selected which is shown as below: + \arg RCU_CKOUT0SRC_NONE: no clock selected + \arg RCU_CKOUT0SRC_CKSYS: system clock selected + \arg RCU_CKOUT0SRC_IRC8M: high speed 8M internal oscillator clock selected + \arg RCU_CKOUT0SRC_HXTAL: HXTAL selected + \arg RCU_CKOUT0SRC_CKPLL_DIV2: CK_PLL/2 selected + \arg RCU_CKOUT0SRC_CKPLL1: CK_PLL1 selected + \arg RCU_CKOUT0SRC_CKPLL2_DIV2: CK_PLL2/2 selected + \arg RCU_CKOUT0SRC_EXT1: EXT1 selected + \arg RCU_CKOUT0SRC_CKPLL2: PLL selected + \param[out] none + \retval none +*/ +void rcu_ckout0_config(uint32_t ckout0_src) +{ + uint32_t reg; + + reg = RCU_CFG0; + + /* reset the CKOUT0SRC, set according to ckout0_src */ + reg &= ~RCU_CFG0_CKOUT0SEL; + RCU_CFG0 = (reg | ckout0_src); +} + +/*! + \brief configure the main PLL clock + \param[in] pll_src: PLL clock source selection + only one parameter can be selected which is shown as below: + \arg RCU_PLLSRC_IRC8M_DIV2: IRC8M/2 clock selected as source clock of PLL + \arg RCU_PLLSRC_HXTAL_IRC48M: HXTAL or IRC48M selected as source clock of PLL + \param[in] pll_mul: PLL clock multiplication factor + only one parameter can be selected which is shown as below: + \arg RCU_PLL_MULx (XD series x = 2..63, CL series x = 2..14, 16..63, 6.5) + \param[out] none + \retval none +*/ +void rcu_pll_config(uint32_t pll_src, uint32_t pll_mul) +{ + uint32_t reg = 0U; + + reg = RCU_CFG0; + + /* PLL clock source and multiplication factor configuration */ + reg &= ~(RCU_CFG0_PLLSEL | RCU_CFG0_PLLMF | RCU_CFG0_PLLMF_4 | RCU_CFG0_PLLMF_5); + reg |= (pll_src | pll_mul); + + RCU_CFG0 = reg; +} + +/*! + \brief configure the PLL clock source preselection + \param[in] pll_presel: PLL clock source preselection + only one parameter can be selected which is shown as below: + \arg RCU_PLLPRESRC_HXTAL: HXTAL selected as PLL source clock + \arg RCU_PLLPRESRC_IRC48M: CK_PLL selected as PREDV0 input source clock + \param[out] none + \retval none +*/ +void rcu_pllpresel_config(uint32_t pll_presel) +{ + uint32_t reg = 0U; + + reg = RCU_CFG1; + + /* PLL clock source preselection */ + reg &= ~RCU_CFG1_PLLPRESEL; + reg |= pll_presel; + + RCU_CFG1 = reg; +} + +#if (defined(GD32F30X_HD) || defined(GD32F30X_XD)) +/*! + \brief configure the PREDV0 division factor + \param[in] predv0_div: PREDV0 division factor + \arg RCU_PREDV0_DIVx, x = 1,2 + \param[out] none + \retval none +*/ +void rcu_predv0_config(uint32_t predv0_div) +{ + uint32_t reg = 0U; + + reg = RCU_CFG0; + /* reset PREDV0 bit */ + reg &= ~RCU_CFG0_PREDV0; + if(RCU_PREDV0_DIV2 == predv0_div){ + /* set the PREDV0 bit */ + reg |= RCU_CFG0_PREDV0; + } + + RCU_CFG0 = reg; +} +#elif defined(GD32F30X_CL) +/*! + \brief configure the PREDV0 division factor and clock source + \param[in] predv0_source: PREDV0 input clock source selection + only one parameter can be selected which is shown as below: + \arg RCU_PREDV0SRC_HXTAL_IRC48M: HXTAL or IRC48M selected as PREDV0 input source clock + \arg RCU_PREDV0SRC_CKPLL1: CK_PLL1 selected as PREDV0 input source clock + \param[in] predv0_div: PREDV0 division factor + only one parameter can be selected which is shown as below: + \arg RCU_PREDV0_DIVx, x = 1..16 + \param[out] none + \retval none +*/ +void rcu_predv0_config(uint32_t predv0_source, uint32_t predv0_div) +{ + uint32_t reg = 0U; + + reg = RCU_CFG1; + /* reset PREDV0SEL and PREDV0 bits */ + reg &= ~(RCU_CFG1_PREDV0SEL | RCU_CFG1_PREDV0); + /* set the PREDV0SEL and PREDV0 division factor */ + reg |= (predv0_source | predv0_div); + + RCU_CFG1 = reg; +} + +/*! + \brief configure the PREDV1 division factor + \param[in] predv1_div: PREDV1 division factor + only one parameter can be selected which is shown as below: + \arg RCU_PREDV1_DIVx, x = 1..16 + \param[out] none + \retval none +*/ +void rcu_predv1_config(uint32_t predv1_div) +{ + uint32_t reg = 0U; + + reg = RCU_CFG1; + /* reset the PREDV1 bits */ + reg &= ~RCU_CFG1_PREDV1; + /* set the PREDV1 division factor */ + reg |= predv1_div; + + RCU_CFG1 = reg; +} + +/*! + \brief configure the PLL1 clock + \param[in] pll_mul: PLL clock multiplication factor + only one parameter can be selected which is shown as below: + \arg RCU_PLL1_MULx (x = 8..14,16,20) + \param[out] none + \retval none +*/ +void rcu_pll1_config(uint32_t pll_mul) +{ + RCU_CFG1 &= ~RCU_CFG1_PLL1MF; + RCU_CFG1 |= pll_mul; +} + +/*! + \brief configure the PLL2 clock + \param[in] pll_mul: PLL clock multiplication factor + only one parameter can be selected which is shown as below: + \arg RCU_PLL2_MULx (x = 8..14,16,20,18..32,40) + \param[out] none + \retval none +*/ +void rcu_pll2_config(uint32_t pll_mul) +{ + RCU_CFG1 &= ~RCU_CFG1_PLL2MF; + RCU_CFG1 |= pll_mul; +} +#endif /* GD32F30X_HD and GD32F30X_XD */ + +/*! + \brief configure the ADC prescaler factor + \param[in] adc_psc: ADC prescaler factor + only one parameter can be selected which is shown as below: + \arg RCU_CKADC_CKAPB2_DIV2: ADC prescaler select CK_APB2/2 + \arg RCU_CKADC_CKAPB2_DIV4: ADC prescaler select CK_APB2/4 + \arg RCU_CKADC_CKAPB2_DIV6: ADC prescaler select CK_APB2/6 + \arg RCU_CKADC_CKAPB2_DIV8: ADC prescaler select CK_APB2/8 + \arg RCU_CKADC_CKAPB2_DIV12: ADC prescaler select CK_APB2/12 + \arg RCU_CKADC_CKAPB2_DIV16: ADC prescaler select CK_APB2/16 + \arg RCU_CKADC_CKAHB_DIV5: ADC prescaler select CK_AHB/5 + \arg RCU_CKADC_CKAHB_DIV6: ADC prescaler select CK_AHB/6 + \arg RCU_CKADC_CKAHB_DIV10: ADC prescaler select CK_AHB/10 + \arg RCU_CKADC_CKAHB_DIV20: ADC prescaler select CK_AHB/20 + \param[out] none + \retval none +*/ +void rcu_adc_clock_config(uint32_t adc_psc) +{ + uint32_t reg0,reg1; + + /* reset the ADCPSC bits */ + reg0 = RCU_CFG0; + reg0 &= ~(RCU_CFG0_ADCPSC_2 | RCU_CFG0_ADCPSC); + reg1 = RCU_CFG1; + reg1 &= ~RCU_CFG1_ADCPSC_3; + + /* set the ADC prescaler factor */ + switch(adc_psc){ + case RCU_CKADC_CKAPB2_DIV2: + case RCU_CKADC_CKAPB2_DIV4: + case RCU_CKADC_CKAPB2_DIV6: + case RCU_CKADC_CKAPB2_DIV8: + reg0 |= (adc_psc << RCU_ADC_PSC_OFFSET); + break; + + case RCU_CKADC_CKAPB2_DIV12: + case RCU_CKADC_CKAPB2_DIV16: + adc_psc &= ~BIT(2); + reg0 |= ((adc_psc << RCU_ADC_PSC_OFFSET) | RCU_CFG0_ADCPSC_2); + break; + + case RCU_CKADC_CKAHB_DIV5: + case RCU_CKADC_CKAHB_DIV6: + case RCU_CKADC_CKAHB_DIV10: + case RCU_CKADC_CKAHB_DIV20: + adc_psc &= ~BITS(2,3); + reg0 |= (adc_psc << RCU_ADC_PSC_OFFSET); + reg1 |= RCU_CFG1_ADCPSC_3; + break; + + default: + break; + } + + /* set the register */ + RCU_CFG0 = reg0; + RCU_CFG1 = reg1; +} + +/*! + \brief configure the USBD/USBFS prescaler factor + \param[in] usb_psc: USB prescaler factor + only one parameter can be selected which is shown as below: + \arg RCU_CKUSB_CKPLL_DIV1_5: USBD/USBFS prescaler select CK_PLL/1.5 + \arg RCU_CKUSB_CKPLL_DIV1: USBD/USBFS prescaler select CK_PLL/1 + \arg RCU_CKUSB_CKPLL_DIV2_5: USBD/USBFS prescaler select CK_PLL/2.5 + \arg RCU_CKUSB_CKPLL_DIV2: USBD/USBFS prescaler select CK_PLL/2 + \arg RCU_CKUSB_CKPLL_DIV3: USBD/USBFS prescaler select CK_PLL/3 + \arg RCU_CKUSB_CKPLL_DIV3_5: USBD/USBFS prescaler select CK_PLL/3.5 + \arg RCU_CKUSB_CKPLL_DIV4: USBD/USBFS prescaler select CK_PLL/4 + \param[out] none + \retval none +*/ +void rcu_usb_clock_config(uint32_t usb_psc) +{ + uint32_t reg; + + reg = RCU_CFG0; + + /* configure the USBD/USBFS prescaler factor */ +#if (defined(GD32F30X_HD) || defined(GD32F30X_XD)) + reg &= ~RCU_CFG0_USBDPSC; +#elif defined(GD32F30X_CL) + reg &= ~RCU_CFG0_USBFSPSC; +#endif /* GD32F30X_HD and GD32F30X_XD */ + + RCU_CFG0 = (reg | usb_psc); +} + +/*! + \brief configure the RTC clock source selection + \param[in] rtc_clock_source: RTC clock source selection + only one parameter can be selected which is shown as below: + \arg RCU_RTCSRC_NONE: no clock selected + \arg RCU_RTCSRC_LXTAL: CK_LXTAL selected as RTC source clock + \arg RCU_RTCSRC_IRC40K: CK_IRC40K selected as RTC source clock + \arg RCU_RTCSRC_HXTAL_DIV_128: CK_HXTAL/128 selected as RTC source clock + \param[out] none + \retval none +*/ +void rcu_rtc_clock_config(uint32_t rtc_clock_source) +{ + uint32_t reg; + + reg = RCU_BDCTL; + /* reset the RTCSRC bits and set according to rtc_clock_source */ + reg &= ~RCU_BDCTL_RTCSRC; + RCU_BDCTL = (reg | rtc_clock_source); +} + +#ifdef GD32F30X_CL +/*! + \brief configure the I2S1 clock source selection + \param[in] i2s_clock_source: I2S1 clock source selection + only one parameter can be selected which is shown as below: + \arg RCU_I2S1SRC_CKSYS: System clock selected as I2S1 source clock + \arg RCU_I2S1SRC_CKPLL2_MUL2: CK_PLL2x2 selected as I2S1 source clock + \param[out] none + \retval none +*/ +void rcu_i2s1_clock_config(uint32_t i2s_clock_source) +{ + uint32_t reg; + + reg = RCU_CFG1; + /* reset the I2S1SEL bit and set according to i2s_clock_source */ + reg &= ~RCU_CFG1_I2S1SEL; + RCU_CFG1 = (reg | i2s_clock_source); +} + +/*! + \brief configure the I2S2 clock source selection + \param[in] i2s_clock_source: I2S2 clock source selection + only one parameter can be selected which is shown as below: + \arg RCU_I2S2SRC_CKSYS: system clock selected as I2S2 source clock + \arg RCU_I2S2SRC_CKPLL2_MUL2: CK_PLL2x2 selected as I2S2 source clock + \param[out] none + \retval none +*/ +void rcu_i2s2_clock_config(uint32_t i2s_clock_source) +{ + uint32_t reg; + + reg = RCU_CFG1; + /* reset the I2S2SEL bit and set according to i2s_clock_source */ + reg &= ~RCU_CFG1_I2S2SEL; + RCU_CFG1 = (reg | i2s_clock_source); +} +#endif /* GD32F30X_CL */ + +/*! + \brief configure the CK48M clock source selection + \param[in] ck48m_clock_source: CK48M clock source selection + only one parameter can be selected which is shown as below: + \arg RCU_CK48MSRC_CKPLL: CK_PLL selected as CK48M source clock + \arg RCU_CK48MSRC_IRC48M: CK_IRC48M selected as CK48M source clock + \param[out] none + \retval none +*/ +void rcu_ck48m_clock_config(uint32_t ck48m_clock_source) +{ + uint32_t reg; + + reg = RCU_ADDCTL; + /* reset the CK48MSEL bit and set according to ck48m_clock_source */ + reg &= ~RCU_ADDCTL_CK48MSEL; + RCU_ADDCTL = (reg | ck48m_clock_source); +} + +/*! + \brief get the clock stabilization and periphral reset flags + \param[in] flag: the clock stabilization and periphral reset flags, refer to rcu_flag_enum + only one parameter can be selected which is shown as below: + \arg RCU_FLAG_IRC8MSTB: IRC8M stabilization flag + \arg RCU_FLAG_HXTALSTB: HXTAL stabilization flag + \arg RCU_FLAG_PLLSTB: PLL stabilization flag + \arg RCU_FLAG_PLL1STB: PLL1 stabilization flag(CL series only) + \arg RCU_FLAG_PLL2STB: PLL2 stabilization flag(CL series only) + \arg RCU_FLAG_LXTALSTB: LXTAL stabilization flag + \arg RCU_FLAG_IRC40KSTB: IRC40K stabilization flag + \arg RCU_FLAG_IRC48MSTB: IRC48M stabilization flag + \arg RCU_FLAG_EPRST: external PIN reset flag + \arg RCU_FLAG_PORRST: power reset flag + \arg RCU_FLAG_SWRST: software reset flag + \arg RCU_FLAG_FWDGTRST: free watchdog timer reset flag + \arg RCU_FLAG_WWDGTRST: window watchdog timer reset flag + \arg RCU_FLAG_LPRST: low-power reset flag + \param[out] none + \retval none +*/ +FlagStatus rcu_flag_get(rcu_flag_enum flag) +{ + /* get the rcu flag */ + if(RESET != (RCU_REG_VAL(flag) & BIT(RCU_BIT_POS(flag)))){ + return SET; + }else{ + return RESET; + } +} + +/*! + \brief clear all the reset flag + \param[in] none + \param[out] none + \retval none +*/ +void rcu_all_reset_flag_clear(void) +{ + RCU_RSTSCK |= RCU_RSTSCK_RSTFC; +} + +/*! + \brief get the clock stabilization interrupt and ckm flags + \param[in] int_flag: interrupt and ckm flags, refer to rcu_int_flag_enum + only one parameter can be selected which is shown as below: + \arg RCU_INT_FLAG_IRC40KSTB: IRC40K stabilization interrupt flag + \arg RCU_INT_FLAG_LXTALSTB: LXTAL stabilization interrupt flag + \arg RCU_INT_FLAG_IRC8MSTB: IRC8M stabilization interrupt flag + \arg RCU_INT_FLAG_HXTALSTB: HXTAL stabilization interrupt flag + \arg RCU_INT_FLAG_PLLSTB: PLL stabilization interrupt flag + \arg RCU_INT_FLAG_PLL1STB: PLL1 stabilization interrupt flag(CL series only) + \arg RCU_INT_FLAG_PLL2STB: PLL2 stabilization interrupt flag(CL series only) + \arg RCU_INT_FLAG_CKM: HXTAL clock stuck interrupt flag + \arg RCU_INT_FLAG_IRC48MSTB: IRC48M stabilization interrupt flag + \param[out] none + \retval FlagStatus: SET or RESET +*/ +FlagStatus rcu_interrupt_flag_get(rcu_int_flag_enum int_flag) +{ + /* get the rcu interrupt flag */ + if(RESET != (RCU_REG_VAL(int_flag) & BIT(RCU_BIT_POS(int_flag)))){ + return SET; + }else{ + return RESET; + } +} + +/*! + \brief clear the interrupt flags + \param[in] int_flag: clock stabilization and stuck interrupt flags clear, refer to rcu_int_flag_clear_enum + only one parameter can be selected which is shown as below: + \arg RCU_INT_FLAG_IRC40KSTB_CLR: IRC40K stabilization interrupt flag clear + \arg RCU_INT_FLAG_LXTALSTB_CLR: LXTAL stabilization interrupt flag clear + \arg RCU_INT_FLAG_IRC8MSTB_CLR: IRC8M stabilization interrupt flag clear + \arg RCU_INT_FLAG_HXTALSTB_CLR: HXTAL stabilization interrupt flag clear + \arg RCU_INT_FLAG_PLLSTB_CLR: PLL stabilization interrupt flag clear + \arg RCU_INT_FLAG_PLL1STB_CLR: PLL1 stabilization interrupt flag clear(CL series only) + \arg RCU_INT_FLAG_PLL2STB_CLR: PLL2 stabilization interrupt flag clear(CL series only) + \arg RCU_INT_FLAG_CKM_CLR: clock stuck interrupt flag clear + \arg RCU_INT_FLAG_IRC48MSTB_CLR: IRC48M stabilization interrupt flag clear + \param[out] none + \retval none +*/ +void rcu_interrupt_flag_clear(rcu_int_flag_clear_enum int_flag) +{ + RCU_REG_VAL(int_flag) |= BIT(RCU_BIT_POS(int_flag)); +} + +/*! + \brief enable the stabilization interrupt + \param[in] interrupt clock stabilization interrupt, refer to rcu_int_enum + only one parameter can be selected which is shown as below: + \arg RCU_INT_IRC40KSTB: IRC40K stabilization interrupt enable + \arg RCU_INT_LXTALSTB: LXTAL stabilization interrupt enable + \arg RCU_INT_IRC8MSTB: IRC8M stabilization interrupt enable + \arg RCU_INT_HXTALSTB: HXTAL stabilization interrupt enable + \arg RCU_INT_PLLSTB: PLL stabilization interrupt enable + \arg RCU_INT_PLL1STB: PLL1 stabilization interrupt enable(CL series only) + \arg RCU_INT_PLL2STB: PLL2 stabilization interrupt enable(CL series only) + \arg RCU_INT_IRC48MSTB: IRC48M stabilization interrupt enable + \param[out] none + \retval none +*/ +void rcu_interrupt_enable(rcu_int_enum interrupt) +{ + RCU_REG_VAL(interrupt) |= BIT(RCU_BIT_POS(interrupt)); +} + +/*! + \brief disable the stabilization interrupt + \param[in] interrupt clock stabilization interrupt, refer to rcu_int_enum + only one parameter can be selected which is shown as below: + \arg RCU_INT_IRC40KSTB: IRC40K stabilization interrupt enable + \arg RCU_INT_LXTALSTB: LXTAL stabilization interrupt enable + \arg RCU_INT_IRC8MSTB: IRC8M stabilization interrupt enable + \arg RCU_INT_HXTALSTB: HXTAL stabilization interrupt enable + \arg RCU_INT_PLLSTB: PLL stabilization interrupt enable + \arg RCU_INT_PLL1STB: PLL1 stabilization interrupt enable(CL series only) + \arg RCU_INT_PLL2STB: PLL2 stabilization interrupt enable(CL series only) + \arg RCU_INT_IRC48MSTB: IRC48M stabilization interrupt enable + \param[out] none + \retval none +*/ +void rcu_interrupt_disable(rcu_int_enum interrupt) +{ + RCU_REG_VAL(interrupt) &= ~BIT(RCU_BIT_POS(interrupt)); +} + +/*! + \brief configure the LXTAL drive capability + \param[in] lxtal_dricap: drive capability of LXTAL + only one parameter can be selected which is shown as below: + \arg RCU_LXTAL_LOWDRI: lower driving capability + \arg RCU_LXTAL_MED_LOWDRI: medium low driving capability + \arg RCU_LXTAL_MED_HIGHDRI: medium high driving capability + \arg RCU_LXTAL_HIGHDRI: higher driving capability + \param[out] none + \retval none +*/ +void rcu_lxtal_drive_capability_config(uint32_t lxtal_dricap) +{ + uint32_t reg; + + reg = RCU_BDCTL; + + /* reset the LXTALDRI bits and set according to lxtal_dricap */ + reg &= ~RCU_BDCTL_LXTALDRI; + RCU_BDCTL = (reg | lxtal_dricap); +} + +/*! + \brief wait for oscillator stabilization flags is SET or oscillator startup is timeout + \param[in] osci: oscillator types, refer to rcu_osci_type_enum + only one parameter can be selected which is shown as below: + \arg RCU_HXTAL: high speed crystal oscillator(HXTAL) + \arg RCU_LXTAL: low speed crystal oscillator(LXTAL) + \arg RCU_IRC8M: internal 8M RC oscillators(IRC8M) + \arg RCU_IRC48M: internal 48M RC oscillators(IRC48M) + \arg RCU_IRC40K: internal 40K RC oscillator(IRC40K) + \arg RCU_PLL_CK: phase locked loop(PLL) + \arg RCU_PLL1_CK: phase locked loop 1(CL series only) + \arg RCU_PLL2_CK: phase locked loop 2(CL series only) + \param[out] none + \retval ErrStatus: SUCCESS or ERROR +*/ +ErrStatus rcu_osci_stab_wait(rcu_osci_type_enum osci) +{ + uint32_t stb_cnt = 0U; + ErrStatus reval = ERROR; + FlagStatus osci_stat = RESET; + + switch(osci){ + /* wait HXTAL stable */ + case RCU_HXTAL: + while((RESET == osci_stat) && (HXTAL_STARTUP_TIMEOUT != stb_cnt)){ + osci_stat = rcu_flag_get(RCU_FLAG_HXTALSTB); + stb_cnt++; + } + + /* check whether flag is set or not */ + if(RESET != rcu_flag_get(RCU_FLAG_HXTALSTB)){ + reval = SUCCESS; + } + break; + + /* wait LXTAL stable */ + case RCU_LXTAL: + while((RESET == osci_stat) && (LXTAL_STARTUP_TIMEOUT != stb_cnt)){ + osci_stat = rcu_flag_get(RCU_FLAG_LXTALSTB); + stb_cnt++; + } + + /* check whether flag is set or not */ + if(RESET != rcu_flag_get(RCU_FLAG_LXTALSTB)){ + reval = SUCCESS; + } + break; + + /* wait IRC8M stable */ + case RCU_IRC8M: + while((RESET == osci_stat) && (IRC8M_STARTUP_TIMEOUT != stb_cnt)){ + osci_stat = rcu_flag_get(RCU_FLAG_IRC8MSTB); + stb_cnt++; + } + + /* check whether flag is set or not */ + if(RESET != rcu_flag_get(RCU_FLAG_IRC8MSTB)){ + reval = SUCCESS; + } + break; + + /* wait IRC48M stable */ + case RCU_IRC48M: + while((RESET == osci_stat) && (OSC_STARTUP_TIMEOUT != stb_cnt)){ + osci_stat = rcu_flag_get(RCU_FLAG_IRC48MSTB); + stb_cnt++; + } + + /* check whether flag is set or not */ + if (RESET != rcu_flag_get(RCU_FLAG_IRC48MSTB)){ + reval = SUCCESS; + } + break; + + /* wait IRC40K stable */ + case RCU_IRC40K: + while((RESET == osci_stat) && (OSC_STARTUP_TIMEOUT != stb_cnt)){ + osci_stat = rcu_flag_get(RCU_FLAG_IRC40KSTB); + stb_cnt++; + } + + /* check whether flag is set or not */ + if(RESET != rcu_flag_get(RCU_FLAG_IRC40KSTB)){ + reval = SUCCESS; + } + break; + + /* wait PLL stable */ + case RCU_PLL_CK: + while((RESET == osci_stat) && (OSC_STARTUP_TIMEOUT != stb_cnt)){ + osci_stat = rcu_flag_get(RCU_FLAG_PLLSTB); + stb_cnt++; + } + + /* check whether flag is set or not */ + if(RESET != rcu_flag_get(RCU_FLAG_PLLSTB)){ + reval = SUCCESS; + } + break; + +#ifdef GD32F30X_CL + /* wait PLL1 stable */ + case RCU_PLL1_CK: + while((RESET == osci_stat) && (OSC_STARTUP_TIMEOUT != stb_cnt)){ + osci_stat = rcu_flag_get(RCU_FLAG_PLL1STB); + stb_cnt++; + } + + /* check whether flag is set or not */ + if(RESET != rcu_flag_get(RCU_FLAG_PLL1STB)){ + reval = SUCCESS; + } + break; + /* wait PLL2 stable */ + case RCU_PLL2_CK: + while((RESET == osci_stat) && (OSC_STARTUP_TIMEOUT != stb_cnt)){ + osci_stat = rcu_flag_get(RCU_FLAG_PLL2STB); + stb_cnt++; + } + + /* check whether flag is set or not */ + if(RESET != rcu_flag_get(RCU_FLAG_PLL2STB)){ + reval = SUCCESS; + } + break; +#endif /* GD32F30X_CL */ + + default: + break; + } + + /* return value */ + return reval; +} + +/*! + \brief turn on the oscillator + \param[in] osci: oscillator types, refer to rcu_osci_type_enum + only one parameter can be selected which is shown as below: + \arg RCU_HXTAL: high speed crystal oscillator(HXTAL) + \arg RCU_LXTAL: low speed crystal oscillator(LXTAL) + \arg RCU_IRC8M: internal 8M RC oscillators(IRC8M) + \arg RCU_IRC48M: internal 48M RC oscillators(IRC48M) + \arg RCU_IRC40K: internal 40K RC oscillator(IRC40K) + \arg RCU_PLL_CK: phase locked loop(PLL) + \arg RCU_PLL1_CK: phase locked loop 1(CL series only) + \arg RCU_PLL2_CK: phase locked loop 2(CL series only) + \param[out] none + \retval none +*/ +void rcu_osci_on(rcu_osci_type_enum osci) +{ + RCU_REG_VAL(osci) |= BIT(RCU_BIT_POS(osci)); +} + +/*! + \brief turn off the oscillator + \param[in] osci: oscillator types, refer to rcu_osci_type_enum + only one parameter can be selected which is shown as below: + \arg RCU_HXTAL: high speed crystal oscillator(HXTAL) + \arg RCU_LXTAL: low speed crystal oscillator(LXTAL) + \arg RCU_IRC8M: internal 8M RC oscillators(IRC8M) + \arg RCU_IRC48M: internal 48M RC oscillators(IRC48M) + \arg RCU_IRC40K: internal 40K RC oscillator(IRC40K) + \arg RCU_PLL_CK: phase locked loop(PLL) + \arg RCU_PLL1_CK: phase locked loop 1(CL series only) + \arg RCU_PLL2_CK: phase locked loop 2(CL series only) + \param[out] none + \retval none +*/ +void rcu_osci_off(rcu_osci_type_enum osci) +{ + RCU_REG_VAL(osci) &= ~BIT(RCU_BIT_POS(osci)); +} + +/*! + \brief enable the oscillator bypass mode, HXTALEN or LXTALEN must be reset before it + \param[in] osci: oscillator types, refer to rcu_osci_type_enum + only one parameter can be selected which is shown as below: + \arg RCU_HXTAL: high speed crystal oscillator(HXTAL) + \arg RCU_LXTAL: low speed crystal oscillator(LXTAL) + \param[out] none + \retval none +*/ +void rcu_osci_bypass_mode_enable(rcu_osci_type_enum osci) +{ + uint32_t reg; + + switch(osci){ + /* enable HXTAL to bypass mode */ + case RCU_HXTAL: + reg = RCU_CTL; + RCU_CTL &= ~RCU_CTL_HXTALEN; + RCU_CTL = (reg | RCU_CTL_HXTALBPS); + break; + /* enable LXTAL to bypass mode */ + case RCU_LXTAL: + reg = RCU_BDCTL; + RCU_BDCTL &= ~RCU_BDCTL_LXTALEN; + RCU_BDCTL = (reg | RCU_BDCTL_LXTALBPS); + break; + case RCU_IRC8M: + case RCU_IRC48M: + case RCU_IRC40K: + case RCU_PLL_CK: +#ifdef GD32F30X_CL + case RCU_PLL1_CK: + case RCU_PLL2_CK: +#endif /* GD32F30X_CL */ + break; + default: + break; + } +} + +/*! + \brief disable the oscillator bypass mode, HXTALEN or LXTALEN must be reset before it + \param[in] osci: oscillator types, refer to rcu_osci_type_enum + only one parameter can be selected which is shown as below: + \arg RCU_HXTAL: high speed crystal oscillator(HXTAL) + \arg RCU_LXTAL: low speed crystal oscillator(LXTAL) + \param[out] none + \retval none +*/ +void rcu_osci_bypass_mode_disable(rcu_osci_type_enum osci) +{ + uint32_t reg; + + switch(osci){ + /* disable HXTAL to bypass mode */ + case RCU_HXTAL: + reg = RCU_CTL; + RCU_CTL &= ~RCU_CTL_HXTALEN; + RCU_CTL = (reg & ~RCU_CTL_HXTALBPS); + break; + /* disable LXTAL to bypass mode */ + case RCU_LXTAL: + reg = RCU_BDCTL; + RCU_BDCTL &= ~RCU_BDCTL_LXTALEN; + RCU_BDCTL = (reg & ~RCU_BDCTL_LXTALBPS); + break; + case RCU_IRC8M: + case RCU_IRC48M: + case RCU_IRC40K: + case RCU_PLL_CK: +#ifdef GD32F30X_CL + case RCU_PLL1_CK: + case RCU_PLL2_CK: +#endif /* GD32F30X_CL */ + break; + default: + break; + } +} + +/*! + \brief enable the HXTAL clock monitor + \param[in] none + \param[out] none + \retval none +*/ + +void rcu_hxtal_clock_monitor_enable(void) +{ + RCU_CTL |= RCU_CTL_CKMEN; +} + +/*! + \brief disable the HXTAL clock monitor + \param[in] none + \param[out] none + \retval none +*/ +void rcu_hxtal_clock_monitor_disable(void) +{ + RCU_CTL &= ~RCU_CTL_CKMEN; +} + +/*! + \brief set the IRC8M adjust value + \param[in] irc8m_adjval: IRC8M adjust value, must be between 0 and 0x1F + \arg 0x00 - 0x1F + \param[out] none + \retval none +*/ +void rcu_irc8m_adjust_value_set(uint32_t irc8m_adjval) +{ + uint32_t reg; + + reg = RCU_CTL; + /* reset the IRC8MADJ bits and set according to irc8m_adjval */ + reg &= ~RCU_CTL_IRC8MADJ; + RCU_CTL = (reg | ((irc8m_adjval & RCU_IRC8M_ADJUST_MASK) << RCU_IRC8M_ADJUST_OFFSET)); +} + +/*! + \brief deep-sleep mode voltage select + \param[in] dsvol: deep sleep mode voltage + only one parameter can be selected which is shown as below: + \arg RCU_DEEPSLEEP_V_1_0: the core voltage is 1.0V + \arg RCU_DEEPSLEEP_V_0_9: the core voltage is 0.9V + \arg RCU_DEEPSLEEP_V_0_8: the core voltage is 0.8V + \arg RCU_DEEPSLEEP_V_0_7: the core voltage is 0.7V + \param[out] none + \retval none +*/ +void rcu_deepsleep_voltage_set(uint32_t dsvol) +{ + dsvol &= RCU_DSV_DSLPVS; + RCU_DSV = dsvol; +} + +/*! + \brief get the system clock, bus and peripheral clock frequency + \param[in] clock: the clock frequency which to get + only one parameter can be selected which is shown as below: + \arg CK_SYS: system clock frequency + \arg CK_AHB: AHB clock frequency + \arg CK_APB1: APB1 clock frequency + \arg CK_APB2: APB2 clock frequency + \param[out] none + \retval clock frequency of system, AHB, APB1, APB2 +*/ +uint32_t rcu_clock_freq_get(rcu_clock_freq_enum clock) +{ + uint32_t sws, ck_freq = 0U; + uint32_t cksys_freq, ahb_freq, apb1_freq, apb2_freq; + uint32_t pllsel, pllpresel, predv0sel, pllmf,ck_src, idx, clk_exp; +#ifdef GD32F30X_CL + uint32_t predv0, predv1, pll1mf; +#endif /* GD32F30X_CL */ + + /* exponent of AHB, APB1 and APB2 clock divider */ + uint8_t ahb_exp[16] = {0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 6, 7, 8, 9}; + uint8_t apb1_exp[8] = {0, 0, 0, 0, 1, 2, 3, 4}; + uint8_t apb2_exp[8] = {0, 0, 0, 0, 1, 2, 3, 4}; + + sws = GET_BITS(RCU_CFG0, 2, 3); + switch(sws){ + /* IRC8M is selected as CK_SYS */ + case SEL_IRC8M: + cksys_freq = IRC8M_VALUE; + break; + /* HXTAL is selected as CK_SYS */ + case SEL_HXTAL: + cksys_freq = HXTAL_VALUE; + break; + /* PLL is selected as CK_SYS */ + case SEL_PLL: + /* PLL clock source selection, HXTAL, IRC48M or IRC8M/2 */ + pllsel = (RCU_CFG0 & RCU_CFG0_PLLSEL); + + if(RCU_PLLSRC_HXTAL_IRC48M == pllsel) { + /* PLL clock source is HXTAL or IRC48M */ + pllpresel = (RCU_CFG1 & RCU_CFG1_PLLPRESEL); + + if(RCU_PLLPRESRC_HXTAL == pllpresel){ + /* PLL clock source is HXTAL */ + ck_src = HXTAL_VALUE; + }else{ + /* PLL clock source is IRC48 */ + ck_src = IRC48M_VALUE; + } + +#if (defined(GD32F30X_HD) || defined(GD32F30X_XD)) + predv0sel = (RCU_CFG0 & RCU_CFG0_PREDV0); + /* PREDV0 input source clock divided by 2 */ + if(RCU_CFG0_PREDV0 == predv0sel){ + ck_src = HXTAL_VALUE/2U; + } +#elif defined(GD32F30X_CL) + predv0sel = (RCU_CFG1 & RCU_CFG1_PREDV0SEL); + /* source clock use PLL1 */ + if(RCU_PREDV0SRC_CKPLL1 == predv0sel){ + predv1 = ((RCU_CFG1 & RCU_CFG1_PREDV1) >> RCU_CFG1_PREDV1_OFFSET) + 1U; + pll1mf = (uint32_t)((RCU_CFG1 & RCU_CFG1_PLL1MF) >> RCU_CFG1_PLL1MF_OFFSET) + 2U; + if(17U == pll1mf){ + pll1mf = 20U; + } + ck_src = (ck_src/predv1)*pll1mf; + } + predv0 = (RCU_CFG1 & RCU_CFG1_PREDV0) + 1U; + ck_src /= predv0; +#endif /* GD32F30X_HD and GD32F30X_XD */ + }else{ + /* PLL clock source is IRC8M/2 */ + ck_src = IRC8M_VALUE/2U; + } + + /* PLL multiplication factor */ + pllmf = GET_BITS(RCU_CFG0, 18, 21); + if((RCU_CFG0 & RCU_CFG0_PLLMF_4)){ + pllmf |= 0x10U; + } + if((RCU_CFG0 & RCU_CFG0_PLLMF_5)){ + pllmf |= 0x20U; + } + if(pllmf < 15U){ + pllmf += 2U; + }else if((pllmf >= 15U) && (pllmf <= 62U)){ + pllmf += 1U; + }else{ + pllmf = 63U; + } + cksys_freq = ck_src*pllmf; + #ifdef GD32F30X_CL + if(15U == pllmf){ + cksys_freq = ck_src*6U + ck_src/2U; + } + #endif /* GD32F30X_CL */ + + break; + /* IRC8M is selected as CK_SYS */ + default: + cksys_freq = IRC8M_VALUE; + break; + } + + /* calculate AHB clock frequency */ + idx = GET_BITS(RCU_CFG0, 4, 7); + clk_exp = ahb_exp[idx]; + ahb_freq = cksys_freq >> clk_exp; + + /* calculate APB1 clock frequency */ + idx = GET_BITS(RCU_CFG0, 8, 10); + clk_exp = apb1_exp[idx]; + apb1_freq = ahb_freq >> clk_exp; + + /* calculate APB2 clock frequency */ + idx = GET_BITS(RCU_CFG0, 11, 13); + clk_exp = apb2_exp[idx]; + apb2_freq = ahb_freq >> clk_exp; + + /* return the clocks frequency */ + switch(clock){ + case CK_SYS: + ck_freq = cksys_freq; + break; + case CK_AHB: + ck_freq = ahb_freq; + break; + case CK_APB1: + ck_freq = apb1_freq; + break; + case CK_APB2: + ck_freq = apb2_freq; + break; + default: + break; + } + return ck_freq; +} diff --git a/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_standard_peripheral/Source/gd32f30x_rtc.c b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_standard_peripheral/Source/gd32f30x_rtc.c new file mode 100644 index 0000000000..8fe1ef957f --- /dev/null +++ b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_standard_peripheral/Source/gd32f30x_rtc.c @@ -0,0 +1,230 @@ +/*! + \file gd32f30x_rtc.c + \brief RTC driver + + \version 2017-02-10, V1.0.0, firmware for GD32F30x + \version 2018-10-10, V1.1.0, firmware for GD32F30x + \version 2018-12-25, V2.0.0, firmware for GD32F30x + \version 2020-09-30, V2.1.0, firmware for GD32F30x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + + +#include "gd32f30x_rtc.h" + +/*! + \brief enable RTC interrupt + \param[in] interrupt: specify which interrupt to enbale + \arg RTC_INT_SECOND: second interrupt + \arg RTC_INT_ALARM: alarm interrupt + \arg RTC_INT_OVERFLOW: overflow interrupt + \param[out] none + \retval none +*/ +void rtc_interrupt_enable(uint32_t interrupt) +{ + RTC_INTEN |= interrupt; +} + +/*! + \brief disable RTC interrupt + \param[in] interrupt: specify which interrupt to disbale + \arg RTC_INT_SECOND: second interrupt + \arg RTC_INT_ALARM: alarm interrupt + \arg RTC_INT_OVERFLOW: overflow interrupt + \param[out] none + \retval none +*/ +void rtc_interrupt_disable(uint32_t interrupt) +{ + RTC_INTEN &= ~interrupt; +} + +/*! + \brief enter RTC configuration mode + \param[in] none + \param[out] none + \retval none +*/ +void rtc_configuration_mode_enter(void) +{ + RTC_CTL |= RTC_CTL_CMF; +} + +/*! + \brief exit RTC configuration mode + \param[in] none + \param[out] none + \retval none +*/ +void rtc_configuration_mode_exit(void) +{ + RTC_CTL &= ~RTC_CTL_CMF; +} + +/*! + \brief wait RTC last write operation finished flag set + \param[in] none + \param[out] none + \retval none +*/ +void rtc_lwoff_wait(void) +{ + /* loop until LWOFF flag is set */ + while (RESET == (RTC_CTL & RTC_CTL_LWOFF)){ + } +} + +/*! + \brief wait RTC registers synchronized flag set + \param[in] none + \param[out] none + \retval none +*/ +void rtc_register_sync_wait(void) +{ + /* clear RSYNF flag */ + RTC_CTL &= ~RTC_CTL_RSYNF; + /* loop until RSYNF flag is set */ + while (RESET == (RTC_CTL & RTC_CTL_RSYNF)){ + } +} + +/*! + \brief get RTC counter value + \param[in] none + \param[out] none + \retval RTC counter value +*/ +uint32_t rtc_counter_get(void) +{ + uint32_t temp = 0x0U; + temp = RTC_CNTL; + temp |= (RTC_CNTH << 16); + return temp; +} + +/*! + \brief set RTC counter value + \param[in] cnt: RTC counter value + \param[out] none + \retval none +*/ +void rtc_counter_set(uint32_t cnt) +{ + rtc_configuration_mode_enter(); + /* set the RTC counter high bits */ + RTC_CNTH = cnt >> 16; + /* set the RTC counter low bits */ + RTC_CNTL = (cnt & RTC_LOW_VALUE); + rtc_configuration_mode_exit(); +} + +/*! + \brief set RTC prescaler value + \param[in] psc: RTC prescaler value + \param[out] none + \retval none +*/ +void rtc_prescaler_set(uint32_t psc) +{ + rtc_configuration_mode_enter(); + /* set the RTC prescaler high bits */ + RTC_PSCH = (psc & RTC_HIGH_VALUE) >> 16; + /* set the RTC prescaler low bits */ + RTC_PSCL = (psc & RTC_LOW_VALUE); + rtc_configuration_mode_exit(); +} + +/*! + \brief set RTC alarm value + \param[in] alarm: RTC alarm value + \param[out] none + \retval none +*/ +void rtc_alarm_config(uint32_t alarm) +{ + rtc_configuration_mode_enter(); + /* set the alarm high bits */ + RTC_ALRMH = alarm >> 16; + /* set the alarm low bits */ + RTC_ALRML = (alarm & RTC_LOW_VALUE); + rtc_configuration_mode_exit(); +} + +/*! + \brief get RTC divider value + \param[in] none + \param[out] none + \retval RTC divider value +*/ +uint32_t rtc_divider_get(void) +{ + uint32_t temp = 0x00U; + temp = (RTC_DIVH & RTC_DIVH_DIV) << 16; + temp |= RTC_DIVL; + return temp; +} + +/*! + \brief get RTC flag status + \param[in] flag: specify which flag status to get + \arg RTC_FLAG_SECOND: second interrupt flag + \arg RTC_FLAG_ALARM: alarm interrupt flag + \arg RTC_FLAG_OVERFLOW: overflow interrupt flag + \arg RTC_FLAG_RSYN: registers synchronized flag + \arg RTC_FLAG_LWOF: last write operation finished flag + \param[out] none + \retval SET or RESET +*/ +FlagStatus rtc_flag_get(uint32_t flag) +{ + if(RESET != (RTC_CTL & flag)){ + return SET; + }else{ + return RESET; + } +} + +/*! + \brief clear RTC flag status + \param[in] flag: specify which flag status to clear + \arg RTC_FLAG_SECOND: second interrupt flag + \arg RTC_FLAG_ALARM: alarm interrupt flag + \arg RTC_FLAG_OVERFLOW: overflow interrupt flag + \arg RTC_FLAG_RSYN: registers synchronized flag + \param[out] none + \retval none +*/ +void rtc_flag_clear(uint32_t flag) +{ + /* clear RTC flag */ + RTC_CTL &= ~flag; +} + diff --git a/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_standard_peripheral/Source/gd32f30x_sdio.c b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_standard_peripheral/Source/gd32f30x_sdio.c new file mode 100644 index 0000000000..b7b54ea9a6 --- /dev/null +++ b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_standard_peripheral/Source/gd32f30x_sdio.c @@ -0,0 +1,809 @@ +/*! + \file gd32f30x_sdio.c + \brief SDIO driver + + \version 2017-02-10, V1.0.0, firmware for GD32F30x + \version 2018-10-10, V1.1.0, firmware for GD32F30x + \version 2018-12-25, V2.0.0, firmware for GD32F30x + \version 2020-09-30, V2.1.0, firmware for GD32F30x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "gd32f30x_sdio.h" + +#define DEFAULT_RESET_VALUE 0x00000000U + +/*! + \brief deinitialize the SDIO + \param[in] none + \param[out] none + \retval none +*/ +void sdio_deinit(void) +{ + SDIO_PWRCTL = DEFAULT_RESET_VALUE; + SDIO_CLKCTL = DEFAULT_RESET_VALUE; + SDIO_CMDAGMT = DEFAULT_RESET_VALUE; + SDIO_CMDCTL = DEFAULT_RESET_VALUE; + SDIO_DATATO = DEFAULT_RESET_VALUE; + SDIO_DATALEN = DEFAULT_RESET_VALUE; + SDIO_DATACTL = DEFAULT_RESET_VALUE; + SDIO_INTC = DEFAULT_RESET_VALUE; + SDIO_INTEN = DEFAULT_RESET_VALUE; +} + +/*! + \brief configure the SDIO clock + \param[in] clock_edge: SDIO_CLK clock edge + only one parameter can be selected which is shown as below: + \arg SDIO_SDIOCLKEDGE_RISING: select the rising edge of the SDIOCLK to generate SDIO_CLK + \arg SDIO_SDIOCLKEDGE_FALLING: select the falling edge of the SDIOCLK to generate SDIO_CLK + \param[in] clock_bypass: clock bypass + only one parameter can be selected which is shown as below: + \arg SDIO_CLOCKBYPASS_ENABLE: clock bypass + \arg SDIO_CLOCKBYPASS_DISABLE: no bypass + \param[in] clock_powersave: SDIO_CLK clock dynamic switch on/off for power saving + only one parameter can be selected which is shown as below: + \arg SDIO_CLOCKPWRSAVE_ENABLE: SDIO_CLK closed when bus is idle + \arg SDIO_CLOCKPWRSAVE_DISABLE: SDIO_CLK clock is always on + \param[in] clock_division: clock division, less than 512 + \param[out] none + \retval none +*/ +void sdio_clock_config(uint32_t clock_edge, uint32_t clock_bypass, uint32_t clock_powersave, uint16_t clock_division) +{ + uint32_t clock_config = 0U; + clock_config = SDIO_CLKCTL; + /* reset the CLKEDGE, CLKBYP, CLKPWRSAV, DIV */ + clock_config &= ~(SDIO_CLKCTL_CLKEDGE | SDIO_CLKCTL_CLKBYP | SDIO_CLKCTL_CLKPWRSAV | SDIO_CLKCTL_DIV8 | SDIO_CLKCTL_DIV); + /* if the clock division is greater or equal to 256, set the DIV[8] */ + if(clock_division >= 256U){ + clock_config |= SDIO_CLKCTL_DIV8; + clock_division -= 256U; + } + /* configure the SDIO_CLKCTL according to the parameters */ + clock_config |= (clock_edge | clock_bypass | clock_powersave | clock_division); + SDIO_CLKCTL = clock_config; +} + +/*! + \brief enable hardware clock control + \param[in] none + \param[out] none + \retval none +*/ +void sdio_hardware_clock_enable(void) +{ + SDIO_CLKCTL |= SDIO_CLKCTL_HWCLKEN; +} + +/*! + \brief disable hardware clock control + \param[in] none + \param[out] none + \retval none +*/ +void sdio_hardware_clock_disable(void) +{ + SDIO_CLKCTL &= ~SDIO_CLKCTL_HWCLKEN; +} + +/*! + \brief set different SDIO card bus mode + \param[in] bus_mode: SDIO card bus mode + only one parameter can be selected which is shown as below: + \arg SDIO_BUSMODE_1BIT: 1-bit SDIO card bus mode + \arg SDIO_BUSMODE_4BIT: 4-bit SDIO card bus mode + \arg SDIO_BUSMODE_8BIT: 8-bit SDIO card bus mode + \param[out] none + \retval none +*/ +void sdio_bus_mode_set(uint32_t bus_mode) +{ + /* reset the SDIO card bus mode bits and set according to bus_mode */ + SDIO_CLKCTL &= ~SDIO_CLKCTL_BUSMODE; + SDIO_CLKCTL |= bus_mode; +} + +/*! + \brief set the SDIO power state + \param[in] power_state: SDIO power state + only one parameter can be selected which is shown as below: + \arg SDIO_POWER_ON: SDIO power on + \arg SDIO_POWER_OFF: SDIO power off + \param[out] none + \retval none +*/ +void sdio_power_state_set(uint32_t power_state) +{ + SDIO_PWRCTL = power_state; +} + +/*! + \brief get the SDIO power state + \param[in] none + \param[out] none + \retval SDIO power state + \arg SDIO_POWER_ON: SDIO power on + \arg SDIO_POWER_OFF: SDIO power off +*/ +uint32_t sdio_power_state_get(void) +{ + return SDIO_PWRCTL; +} + +/*! + \brief enable SDIO_CLK clock output + \param[in] none + \param[out] none + \retval none +*/ +void sdio_clock_enable(void) +{ + SDIO_CLKCTL |= SDIO_CLKCTL_CLKEN; +} + +/*! + \brief disable SDIO_CLK clock output + \param[in] none + \param[out] none + \retval none +*/ +void sdio_clock_disable(void) +{ + SDIO_CLKCTL &= ~SDIO_CLKCTL_CLKEN; +} + +/*! + \brief configure the command and response + \param[in] cmd_index: command index, refer to the related specifications + \param[in] cmd_argument: command argument, refer to the related specifications + \param[in] response_type: response type + only one parameter can be selected which is shown as below: + \arg SDIO_RESPONSETYPE_NO: no response + \arg SDIO_RESPONSETYPE_SHORT: short response + \arg SDIO_RESPONSETYPE_LONG: long response + \param[out] none + \retval none +*/ +void sdio_command_response_config(uint32_t cmd_index, uint32_t cmd_argument, uint32_t response_type) +{ + uint32_t cmd_config = 0U; + /* reset the command index, command argument and response type */ + SDIO_CMDAGMT &= ~SDIO_CMDAGMT_CMDAGMT; + SDIO_CMDAGMT = cmd_argument; + cmd_config = SDIO_CMDCTL; + cmd_config &= ~(SDIO_CMDCTL_CMDIDX | SDIO_CMDCTL_CMDRESP); + /* configure SDIO_CMDCTL and SDIO_CMDAGMT according to the parameters */ + cmd_config |= (cmd_index | response_type); + SDIO_CMDCTL = cmd_config; +} + +/*! + \brief set the command state machine wait type + \param[in] wait_type: wait type + only one parameter can be selected which is shown as below: + \arg SDIO_WAITTYPE_NO: not wait interrupt + \arg SDIO_WAITTYPE_INTERRUPT: wait interrupt + \arg SDIO_WAITTYPE_DATAEND: wait the end of data transfer + \param[out] none + \retval none +*/ +void sdio_wait_type_set(uint32_t wait_type) +{ + /* reset INTWAIT and WAITDEND */ + SDIO_CMDCTL &= ~(SDIO_CMDCTL_INTWAIT | SDIO_CMDCTL_WAITDEND); + /* set the wait type according to wait_type */ + SDIO_CMDCTL |= wait_type; +} + +/*! + \brief enable the CSM(command state machine) + \param[in] none + \param[out] none + \retval none +*/ +void sdio_csm_enable(void) +{ + SDIO_CMDCTL |= SDIO_CMDCTL_CSMEN; +} + +/*! + \brief disable the CSM(command state machine) + \param[in] none + \param[out] none + \retval none +*/ +void sdio_csm_disable(void) +{ + SDIO_CMDCTL &= ~SDIO_CMDCTL_CSMEN; +} + +/*! + \brief get the last response command index + \param[in] none + \param[out] none + \retval last response command index +*/ +uint8_t sdio_command_index_get(void) +{ + return (uint8_t)SDIO_RSPCMDIDX; +} + +/*! + \brief get the response for the last received command + \param[in] responsex: SDIO response + only one parameter can be selected which is shown as below: + \arg SDIO_RESPONSE0: card response[31:0]/card response[127:96] + \arg SDIO_RESPONSE1: card response[95:64] + \arg SDIO_RESPONSE2: card response[63:32] + \arg SDIO_RESPONSE3: card response[31:1], plus bit 0 + \param[out] none + \retval response for the last received command +*/ +uint32_t sdio_response_get(uint32_t responsex) +{ + uint32_t resp_content = 0U; + switch(responsex){ + case SDIO_RESPONSE0: + resp_content = SDIO_RESP0; + break; + case SDIO_RESPONSE1: + resp_content = SDIO_RESP1; + break; + case SDIO_RESPONSE2: + resp_content = SDIO_RESP2; + break; + case SDIO_RESPONSE3: + resp_content = SDIO_RESP3; + break; + default: + break; + } + return resp_content; +} + +/*! + \brief configure the data timeout, data length and data block size + \param[in] data_timeout: data timeout period in card bus clock periods + \param[in] data_length: number of data bytes to be transferred + \param[in] data_blocksize: size of data block for block transfer + only one parameter can be selected which is shown as below: + \arg SDIO_DATABLOCKSIZE_1BYTE: block size = 1 byte + \arg SDIO_DATABLOCKSIZE_2BYTES: block size = 2 bytes + \arg SDIO_DATABLOCKSIZE_4BYTES: block size = 4 bytes + \arg SDIO_DATABLOCKSIZE_8BYTES: block size = 8 bytes + \arg SDIO_DATABLOCKSIZE_16BYTES: block size = 16 bytes + \arg SDIO_DATABLOCKSIZE_32BYTES: block size = 32 bytes + \arg SDIO_DATABLOCKSIZE_64BYTES: block size = 64 bytes + \arg SDIO_DATABLOCKSIZE_128BYTES: block size = 128 bytes + \arg SDIO_DATABLOCKSIZE_256BYTES: block size = 256 bytes + \arg SDIO_DATABLOCKSIZE_512BYTES: block size = 512 bytes + \arg SDIO_DATABLOCKSIZE_1024BYTES: block size = 1024 bytes + \arg SDIO_DATABLOCKSIZE_2048BYTES: block size = 2048 bytes + \arg SDIO_DATABLOCKSIZE_4096BYTES: block size = 4096 bytes + \arg SDIO_DATABLOCKSIZE_8192BYTES: block size = 8192 bytes + \arg SDIO_DATABLOCKSIZE_16384BYTES: block size = 16384 bytes + \param[out] none + \retval none +*/ +void sdio_data_config(uint32_t data_timeout, uint32_t data_length, uint32_t data_blocksize) +{ + /* reset data timeout, data length and data block size */ + SDIO_DATATO &= ~SDIO_DATATO_DATATO; + SDIO_DATALEN &= ~SDIO_DATALEN_DATALEN; + SDIO_DATACTL &= ~SDIO_DATACTL_BLKSZ; + /* configure the related parameters of data */ + SDIO_DATATO = data_timeout; + SDIO_DATALEN = data_length; + SDIO_DATACTL |= data_blocksize; +} + +/*! + \brief configure the data transfer mode and direction + \param[in] transfer_mode: mode of data transfer + only one parameter can be selected which is shown as below: + \arg SDIO_TRANSMODE_BLOCK: block transfer + \arg SDIO_TRANSMODE_STREAM: stream transfer or SDIO multibyte transfer + \param[in] transfer_direction: data transfer direction, read or write + only one parameter can be selected which is shown as below: + \arg SDIO_TRANSDIRECTION_TOCARD: write data to card + \arg SDIO_TRANSDIRECTION_TOSDIO: read data from card + \param[out] none + \retval none +*/ +void sdio_data_transfer_config(uint32_t transfer_mode, uint32_t transfer_direction) +{ + uint32_t data_trans = 0U; + /* reset the data transfer mode, transfer direction and set according to the parameters */ + data_trans = SDIO_DATACTL; + data_trans &= ~(SDIO_DATACTL_TRANSMOD | SDIO_DATACTL_DATADIR); + data_trans |= (transfer_mode | transfer_direction); + SDIO_DATACTL = data_trans; +} + +/*! + \brief enable the DSM(data state machine) for data transfer + \param[in] none + \param[out] none + \retval none +*/ +void sdio_dsm_enable(void) +{ + SDIO_DATACTL |= SDIO_DATACTL_DATAEN; +} + +/*! + \brief disable the DSM(data state machine) + \param[in] none + \param[out] none + \retval none +*/ +void sdio_dsm_disable(void) +{ + SDIO_DATACTL &= ~SDIO_DATACTL_DATAEN; +} + +/*! + \brief write data(one word) to the transmit FIFO + \param[in] data: 32-bit data write to card + \param[out] none + \retval none +*/ +void sdio_data_write(uint32_t data) +{ + SDIO_FIFO = data; +} + +/*! + \brief read data(one word) from the receive FIFO + \param[in] none + \param[out] none + \retval received data +*/ +uint32_t sdio_data_read(void) +{ + return SDIO_FIFO; +} + +/*! + \brief get the number of remaining data bytes to be transferred to card + \param[in] none + \param[out] none + \retval number of remaining data bytes to be transferred +*/ +uint32_t sdio_data_counter_get(void) +{ + return SDIO_DATACNT; +} + +/*! + \brief get the number of words remaining to be written or read from FIFO + \param[in] none + \param[out] none + \retval remaining number of words +*/ +uint32_t sdio_fifo_counter_get(void) +{ + return SDIO_FIFOCNT; +} + +/*! + \brief enable the DMA request for SDIO + \param[in] none + \param[out] none + \retval none +*/ +void sdio_dma_enable(void) +{ + SDIO_DATACTL |= SDIO_DATACTL_DMAEN; +} + +/*! + \brief disable the DMA request for SDIO + \param[in] none + \param[out] none + \retval none +*/ +void sdio_dma_disable(void) +{ + SDIO_DATACTL &= ~SDIO_DATACTL_DMAEN; +} + +/*! + \brief get the flags state of SDIO + \param[in] flag: flags state of SDIO + one or more parameters can be selected which are shown as below: + \arg SDIO_FLAG_CCRCERR: command response received (CRC check failed) flag + \arg SDIO_FLAG_DTCRCERR: data block sent/received (CRC check failed) flag + \arg SDIO_FLAG_CMDTMOUT: command response timeout flag + \arg SDIO_FLAG_DTTMOUT: data timeout flag + \arg SDIO_FLAG_TXURE: transmit FIFO underrun error occurs flag + \arg SDIO_FLAG_RXORE: received FIFO overrun error occurs flag + \arg SDIO_FLAG_CMDRECV: command response received (CRC check passed) flag + \arg SDIO_FLAG_CMDSEND: command sent (no response required) flag + \arg SDIO_FLAG_DTEND: data end (data counter, SDIO_DATACNT, is zero) flag + \arg SDIO_FLAG_STBITE: start bit error in the bus flag + \arg SDIO_FLAG_DTBLKEND: data block sent/received (CRC check passed) flag + \arg SDIO_FLAG_CMDRUN: command transmission in progress flag + \arg SDIO_FLAG_TXRUN: data transmission in progress flag + \arg SDIO_FLAG_RXRUN: data reception in progress flag + \arg SDIO_FLAG_TFH: transmit FIFO is half empty flag: at least 8 words can be written into the FIFO + \arg SDIO_FLAG_RFH: receive FIFO is half full flag: at least 8 words can be read in the FIFO + \arg SDIO_FLAG_TFF: transmit FIFO is full flag + \arg SDIO_FLAG_RFF: receive FIFO is full flag + \arg SDIO_FLAG_TFE: transmit FIFO is empty flag + \arg SDIO_FLAG_RFE: receive FIFO is empty flag + \arg SDIO_FLAG_TXDTVAL: data is valid in transmit FIFO flag + \arg SDIO_FLAG_RXDTVAL: data is valid in receive FIFO flag + \arg SDIO_FLAG_SDIOINT: SD I/O interrupt received flag + \arg SDIO_FLAG_ATAEND: CE-ATA command completion signal received (only for CMD61) flag + \param[out] none + \retval FlagStatus: SET or RESET +*/ +FlagStatus sdio_flag_get(uint32_t flag) +{ + if(RESET != (SDIO_STAT & flag)){ + return SET; + } + return RESET; +} + +/*! + \brief clear the pending flags of SDIO + \param[in] flag: flags state of SDIO + one or more parameters can be selected which are shown as below: + \arg SDIO_FLAG_CCRCERR: command response received (CRC check failed) flag + \arg SDIO_FLAG_DTCRCERR: data block sent/received (CRC check failed) flag + \arg SDIO_FLAG_CMDTMOUT: command response timeout flag + \arg SDIO_FLAG_DTTMOUT: data timeout flag + \arg SDIO_FLAG_TXURE: transmit FIFO underrun error occurs flag + \arg SDIO_FLAG_RXORE: received FIFO overrun error occurs flag + \arg SDIO_FLAG_CMDRECV: command response received (CRC check passed) flag + \arg SDIO_FLAG_CMDSEND: command sent (no response required) flag + \arg SDIO_FLAG_DTEND: data end (data counter, SDIO_DATACNT, is zero) flag + \arg SDIO_FLAG_STBITE: start bit error in the bus flag + \arg SDIO_FLAG_DTBLKEND: data block sent/received (CRC check passed) flag + \arg SDIO_FLAG_SDIOINT: SD I/O interrupt received flag + \arg SDIO_FLAG_ATAEND: CE-ATA command completion signal received (only for CMD61) flag + \param[out] none + \retval none +*/ +void sdio_flag_clear(uint32_t flag) +{ + SDIO_INTC = flag; +} + +/*! + \brief enable the SDIO interrupt + \param[in] int_flag: interrupt flags state of SDIO + one or more parameters can be selected which are shown as below: + \arg SDIO_INT_CCRCERR: SDIO CCRCERR interrupt + \arg SDIO_INT_DTCRCERR: SDIO DTCRCERR interrupt + \arg SDIO_INT_CMDTMOUT: SDIO CMDTMOUT interrupt + \arg SDIO_INT_DTTMOUT: SDIO DTTMOUT interrupt + \arg SDIO_INT_TXURE: SDIO TXURE interrupt + \arg SDIO_INT_RXORE: SDIO RXORE interrupt + \arg SDIO_INT_CMDRECV: SDIO CMDRECV interrupt + \arg SDIO_INT_CMDSEND: SDIO CMDSEND interrupt + \arg SDIO_INT_DTEND: SDIO DTEND interrupt + \arg SDIO_INT_STBITE: SDIO STBITE interrupt + \arg SDIO_INT_DTBLKEND: SDIO DTBLKEND interrupt + \arg SDIO_INT_CMDRUN: SDIO CMDRUN interrupt + \arg SDIO_INT_TXRUN: SDIO TXRUN interrupt + \arg SDIO_INT_RXRUN: SDIO RXRUN interrupt + \arg SDIO_INT_TFH: SDIO TFH interrupt + \arg SDIO_INT_RFH: SDIO RFH interrupt + \arg SDIO_INT_TFF: SDIO TFF interrupt + \arg SDIO_INT_RFF: SDIO RFF interrupt + \arg SDIO_INT_TFE: SDIO TFE interrupt + \arg SDIO_INT_RFE: SDIO RFE interrupt + \arg SDIO_INT_TXDTVAL: SDIO TXDTVAL interrupt + \arg SDIO_INT_RXDTVAL: SDIO RXDTVAL interrupt + \arg SDIO_INT_SDIOINT: SDIO SDIOINT interrupt + \arg SDIO_INT_ATAEND: SDIO ATAEND interrupt + \param[out] none + \retval none +*/ +void sdio_interrupt_enable(uint32_t int_flag) +{ + SDIO_INTEN |= int_flag; +} + +/*! + \brief disable the SDIO interrupt + \param[in] int_flag: interrupt flags state of SDIO + one or more parameters can be selected which are shown as below: + \arg SDIO_INT_CCRCERR: SDIO CCRCERR interrupt + \arg SDIO_INT_DTCRCERR: SDIO DTCRCERR interrupt + \arg SDIO_INT_CMDTMOUT: SDIO CMDTMOUT interrupt + \arg SDIO_INT_DTTMOUT: SDIO DTTMOUT interrupt + \arg SDIO_INT_TXURE: SDIO TXURE interrupt + \arg SDIO_INT_RXORE: SDIO RXORE interrupt + \arg SDIO_INT_CMDRECV: SDIO CMDRECV interrupt + \arg SDIO_INT_CMDSEND: SDIO CMDSEND interrupt + \arg SDIO_INT_DTEND: SDIO DTEND interrupt + \arg SDIO_INT_STBITE: SDIO STBITE interrupt + \arg SDIO_INT_DTBLKEND: SDIO DTBLKEND interrupt + \arg SDIO_INT_CMDRUN: SDIO CMDRUN interrupt + \arg SDIO_INT_TXRUN: SDIO TXRUN interrupt + \arg SDIO_INT_RXRUN: SDIO RXRUN interrupt + \arg SDIO_INT_TFH: SDIO TFH interrupt + \arg SDIO_INT_RFH: SDIO RFH interrupt + \arg SDIO_INT_TFF: SDIO TFF interrupt + \arg SDIO_INT_RFF: SDIO RFF interrupt + \arg SDIO_INT_TFE: SDIO TFE interrupt + \arg SDIO_INT_RFE: SDIO RFE interrupt + \arg SDIO_INT_TXDTVAL: SDIO TXDTVAL interrupt + \arg SDIO_INT_RXDTVAL: SDIO RXDTVAL interrupt + \arg SDIO_INT_SDIOINT: SDIO SDIOINT interrupt + \arg SDIO_INT_ATAEND: SDIO ATAEND interrupt + \param[out] none + \retval none +*/ +void sdio_interrupt_disable(uint32_t int_flag) +{ + SDIO_INTEN &= ~int_flag; +} + +/*! + \brief get the interrupt flags state of SDIO + \param[in] int_flag: interrupt flags state of SDIO + one or more parameters can be selected which are shown as below: + \arg SDIO_INT_FLAG_CCRCERR: SDIO CCRCERR interrupt flag + \arg SDIO_INT_FLAG_DTCRCERR: SDIO DTCRCERR interrupt flag + \arg SDIO_INT_FLAG_CMDTMOUT: SDIO CMDTMOUT interrupt flag + \arg SDIO_INT_FLAG_DTTMOUT: SDIO DTTMOUT interrupt flag + \arg SDIO_INT_FLAG_TXURE: SDIO TXURE interrupt flag + \arg SDIO_INT_FLAG_RXORE: SDIO RXORE interrupt flag + \arg SDIO_INT_FLAG_CMDRECV: SDIO CMDRECV interrupt flag + \arg SDIO_INT_FLAG_CMDSEND: SDIO CMDSEND interrupt flag + \arg SDIO_INT_FLAG_DTEND: SDIO DTEND interrupt flag + \arg SDIO_INT_FLAG_STBITE: SDIO STBITE interrupt flag + \arg SDIO_INT_FLAG_DTBLKEND: SDIO DTBLKEND interrupt flag + \arg SDIO_INT_FLAG_CMDRUN: SDIO CMDRUN interrupt flag + \arg SDIO_INT_FLAG_TXRUN: SDIO TXRUN interrupt flag + \arg SDIO_INT_FLAG_RXRUN: SDIO RXRUN interrupt flag + \arg SDIO_INT_FLAG_TFH: SDIO TFH interrupt flag + \arg SDIO_INT_FLAG_RFH: SDIO RFH interrupt flag + \arg SDIO_INT_FLAG_TFF: SDIO TFF interrupt flag + \arg SDIO_INT_FLAG_RFF: SDIO RFF interrupt flag + \arg SDIO_INT_FLAG_TFE: SDIO TFE interrupt flag + \arg SDIO_INT_FLAG_RFE: SDIO RFE interrupt flag + \arg SDIO_INT_FLAG_TXDTVAL: SDIO TXDTVAL interrupt flag + \arg SDIO_INT_FLAG_RXDTVAL: SDIO RXDTVAL interrupt flag + \arg SDIO_INT_FLAG_SDIOINT: SDIO SDIOINT interrupt flag + \arg SDIO_INT_FLAG_ATAEND: SDIO ATAEND interrupt flag + \param[out] none + \retval FlagStatus: SET or RESET +*/ +FlagStatus sdio_interrupt_flag_get(uint32_t int_flag) +{ + if(RESET != (SDIO_STAT & int_flag)){ + return SET; + } + return RESET; +} + +/*! + \brief clear the interrupt pending flags of SDIO + \param[in] int_flag: interrupt flags state of SDIO + one or more parameters can be selected which are shown as below: + \arg SDIO_INT_FLAG_CCRCERR: command response received (CRC check failed) flag + \arg SDIO_INT_FLAG_DTCRCERR: data block sent/received (CRC check failed) flag + \arg SDIO_INT_FLAG_CMDTMOUT: command response timeout flag + \arg SDIO_INT_FLAG_DTTMOUT: data timeout flag + \arg SDIO_INT_FLAG_TXURE: transmit FIFO underrun error occurs flag + \arg SDIO_INT_FLAG_RXORE: received FIFO overrun error occurs flag + \arg SDIO_INT_FLAG_CMDRECV: command response received (CRC check passed) flag + \arg SDIO_INT_FLAG_CMDSEND: command sent (no response required) flag + \arg SDIO_INT_FLAG_DTEND: data end (data counter, SDIO_DATACNT, is zero) flag + \arg SDIO_INT_FLAG_STBITE: start bit error in the bus flag + \arg SDIO_INT_FLAG_DTBLKEND: data block sent/received (CRC check passed) flag + \arg SDIO_INT_FLAG_SDIOINT: SD I/O interrupt received flag + \arg SDIO_INT_FLAG_ATAEND: CE-ATA command completion signal received (only for CMD61) flag + \param[out] none + \retval none +*/ +void sdio_interrupt_flag_clear(uint32_t int_flag) +{ + SDIO_INTC = int_flag; +} + +/*! + \brief enable the read wait mode(SD I/O only) + \param[in] none + \param[out] none + \retval none +*/ +void sdio_readwait_enable(void) +{ + SDIO_DATACTL |= SDIO_DATACTL_RWEN; +} + +/*! + \brief disable the read wait mode(SD I/O only) + \param[in] none + \param[out] none + \retval none +*/ +void sdio_readwait_disable(void) +{ + SDIO_DATACTL &= ~SDIO_DATACTL_RWEN; +} + +/*! + \brief enable the function that stop the read wait process(SD I/O only) + \param[in] none + \param[out] none + \retval none +*/ +void sdio_stop_readwait_enable(void) +{ + SDIO_DATACTL |= SDIO_DATACTL_RWSTOP; +} + +/*! + \brief disable the function that stop the read wait process(SD I/O only) + \param[in] none + \param[out] none + \retval none +*/ +void sdio_stop_readwait_disable(void) +{ + SDIO_DATACTL &= ~SDIO_DATACTL_RWSTOP; +} + +/*! + \brief set the read wait type(SD I/O only) + \param[in] readwait_type: SD I/O read wait type + only one parameter can be selected which is shown as below: + \arg SDIO_READWAITTYPE_CLK: read wait control by stopping SDIO_CLK + \arg SDIO_READWAITTYPE_DAT2: read wait control using SDIO_DAT[2] + \param[out] none + \retval none +*/ +void sdio_readwait_type_set(uint32_t readwait_type) +{ + if(SDIO_READWAITTYPE_CLK == readwait_type){ + SDIO_DATACTL |= SDIO_DATACTL_RWTYPE; + }else{ + SDIO_DATACTL &= ~SDIO_DATACTL_RWTYPE; + } +} + +/*! + \brief enable the SD I/O mode specific operation(SD I/O only) + \param[in] none + \param[out] none + \retval none +*/ +void sdio_operation_enable(void) +{ + SDIO_DATACTL |= SDIO_DATACTL_IOEN; +} + +/*! + \brief disable the SD I/O mode specific operation(SD I/O only) + \param[in] none + \param[out] none + \retval none +*/ +void sdio_operation_disable(void) +{ + SDIO_DATACTL &= ~SDIO_DATACTL_IOEN; +} + +/*! + \brief enable the SD I/O suspend operation(SD I/O only) + \param[in] none + \param[out] none + \retval none +*/ +void sdio_suspend_enable(void) +{ + SDIO_CMDCTL |= SDIO_CMDCTL_SUSPEND; +} + +/*! + \brief disable the SD I/O suspend operation(SD I/O only) + \param[in] none + \param[out] none + \retval none +*/ +void sdio_suspend_disable(void) +{ + SDIO_CMDCTL &= ~SDIO_CMDCTL_SUSPEND; +} + +/*! + \brief enable the CE-ATA command(CE-ATA only) + \param[in] none + \param[out] none + \retval none +*/ +void sdio_ceata_command_enable(void) +{ + SDIO_CMDCTL |= SDIO_CMDCTL_ATAEN; +} + +/*! + \brief disable the CE-ATA command(CE-ATA only) + \param[in] none + \param[out] none + \retval none +*/ +void sdio_ceata_command_disable(void) +{ + SDIO_CMDCTL &= ~SDIO_CMDCTL_ATAEN; +} + +/*! + \brief enable the CE-ATA interrupt(CE-ATA only) + \param[in] none + \param[out] none + \retval none +*/ +void sdio_ceata_interrupt_enable(void) +{ + SDIO_CMDCTL &= ~SDIO_CMDCTL_NINTEN; +} + +/*! + \brief disable the CE-ATA interrupt(CE-ATA only) + \param[in] none + \param[out] none + \retval none +*/ +void sdio_ceata_interrupt_disable(void) +{ + SDIO_CMDCTL |= SDIO_CMDCTL_NINTEN; +} + +/*! + \brief enable the CE-ATA command completion signal(CE-ATA only) + \param[in] none + \param[out] none + \retval none +*/ +void sdio_ceata_command_completion_enable(void) +{ + SDIO_CMDCTL |= SDIO_CMDCTL_ENCMDC; +} + +/*! + \brief disable the CE-ATA command completion signal(CE-ATA only) + \param[in] none + \param[out] none + \retval none +*/ +void sdio_ceata_command_completion_disable(void) +{ + SDIO_CMDCTL &= ~SDIO_CMDCTL_ENCMDC; +} diff --git a/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_standard_peripheral/Source/gd32f30x_spi.c b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_standard_peripheral/Source/gd32f30x_spi.c new file mode 100644 index 0000000000..6af0a4049a --- /dev/null +++ b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_standard_peripheral/Source/gd32f30x_spi.c @@ -0,0 +1,859 @@ +/*! + \file gd32f30x_spi.c + \brief SPI driver + + \version 2017-02-10, V1.0.0, firmware for GD32F30x + \version 2018-10-10, V1.1.0, firmware for GD32F30x + \version 2018-12-25, V2.0.0, firmware for GD32F30x + \version 2020-09-30, V2.1.0, firmware for GD32F30x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "gd32f30x_spi.h" + +#define SPI_ERROR_HANDLE(s) do{}while(1) + +/* SPI/I2S parameter initialization mask */ +#define SPI_INIT_MASK ((uint32_t)0x00003040U) /*!< SPI parameter initialization mask */ +#define I2S_INIT_MASK ((uint32_t)0x0000F047U) /*!< I2S parameter initialization mask */ + +/* default value */ +#define SPI_I2SPSC_DEFAULT_VALUE ((uint32_t)0x00000002U) /*!< default value of SPI_I2SPSC register */ + +/* I2S clock source selection, multiplication and division mask */ +#define I2S1_CLOCK_SEL ((uint32_t)0x00020000U) /*!< I2S1 clock source selection */ +#define I2S2_CLOCK_SEL ((uint32_t)0x00040000U) /*!< I2S2 clock source selection */ +#define I2S_CLOCK_MUL_MASK ((uint32_t)0x0000F000U) /*!< I2S clock multiplication mask */ +#define I2S_CLOCK_DIV_MASK ((uint32_t)0x000000F0U) /*!< I2S clock division mask */ + +/*! + \brief reset SPI and I2S + \param[in] spi_periph: SPIx(x=0,1,2) + \param[out] none + \retval none +*/ +void spi_i2s_deinit(uint32_t spi_periph) +{ + switch(spi_periph){ + case SPI0: + /* reset SPI0 */ + rcu_periph_reset_enable(RCU_SPI0RST); + rcu_periph_reset_disable(RCU_SPI0RST); + break; + case SPI1: + /* reset SPI1 and I2S1 */ + rcu_periph_reset_enable(RCU_SPI1RST); + rcu_periph_reset_disable(RCU_SPI1RST); + break; + case SPI2: + /* reset SPI2 and I2S2 */ + rcu_periph_reset_enable(RCU_SPI2RST); + rcu_periph_reset_disable(RCU_SPI2RST); + break; + default : + break; + } +} + +/*! + \brief initialize the parameters of SPI struct with default values + \param[in] none + \param[out] spi_parameter_struct: the initialized struct spi_parameter_struct pointer + \retval none +*/ +void spi_struct_para_init(spi_parameter_struct *spi_struct) +{ + /* configure the structure with default value */ + spi_struct->device_mode = SPI_SLAVE; + spi_struct->trans_mode = SPI_TRANSMODE_FULLDUPLEX; + spi_struct->frame_size = SPI_FRAMESIZE_8BIT; + spi_struct->nss = SPI_NSS_HARD; + spi_struct->clock_polarity_phase = SPI_CK_PL_LOW_PH_1EDGE; + spi_struct->prescale = SPI_PSC_2; + spi_struct->endian = SPI_ENDIAN_MSB; +} + +/*! + \brief initialize SPI parameter + \param[in] spi_periph: SPIx(x=0,1,2) + \param[in] spi_struct: SPI parameter initialization stuct members of the structure + and the member values are shown as below: + device_mode: SPI_MASTER, SPI_SLAVE + trans_mode: SPI_TRANSMODE_FULLDUPLEX, SPI_TRANSMODE_RECEIVEONLY, + SPI_TRANSMODE_BDRECEIVE, SPI_TRANSMODE_BDTRANSMIT + frame_size: SPI_FRAMESIZE_16BIT, SPI_FRAMESIZE_8BIT + nss: SPI_NSS_SOFT, SPI_NSS_HARD + endian: SPI_ENDIAN_MSB, SPI_ENDIAN_LSB + clock_polarity_phase: SPI_CK_PL_LOW_PH_1EDGE, SPI_CK_PL_HIGH_PH_1EDGE + SPI_CK_PL_LOW_PH_2EDGE, SPI_CK_PL_HIGH_PH_2EDGE + prescale: SPI_PSC_n (n=2,4,8,16,32,64,128,256) + \param[out] none + \retval none +*/ +void spi_init(uint32_t spi_periph, spi_parameter_struct* spi_struct) +{ + uint32_t reg = 0U; + reg = SPI_CTL0(spi_periph); + reg &= SPI_INIT_MASK; + + /* select SPI as master or slave */ + reg |= spi_struct->device_mode; + /* select SPI transfer mode */ + reg |= spi_struct->trans_mode; + /* select SPI frame size */ + reg |= spi_struct->frame_size; + /* select SPI NSS use hardware or software */ + reg |= spi_struct->nss; + /* select SPI LSB or MSB */ + reg |= spi_struct->endian; + /* select SPI polarity and phase */ + reg |= spi_struct->clock_polarity_phase; + /* select SPI prescale to adjust transmit speed */ + reg |= spi_struct->prescale; + + /* write to SPI_CTL0 register */ + SPI_CTL0(spi_periph) = (uint32_t)reg; + + SPI_I2SCTL(spi_periph) &= (uint32_t)(~SPI_I2SCTL_I2SSEL); +} + +/*! + \brief enable SPI + \param[in] spi_periph: SPIx(x=0,1,2) + \param[out] none + \retval none +*/ +void spi_enable(uint32_t spi_periph) +{ + SPI_CTL0(spi_periph) |= (uint32_t)SPI_CTL0_SPIEN; +} + +/*! + \brief disable SPI + \param[in] spi_periph: SPIx(x=0,1,2) + \param[out] none + \retval none +*/ +void spi_disable(uint32_t spi_periph) +{ + SPI_CTL0(spi_periph) &= (uint32_t)(~SPI_CTL0_SPIEN); +} + +/*! + \brief initialize I2S parameter + \param[in] spi_periph: SPIx(x=1,2) + \param[in] i2s_mode: I2S operation mode + only one parameter can be selected which is shown as below: + \arg I2S_MODE_SLAVETX: I2S slave transmit mode + \arg I2S_MODE_SLAVERX: I2S slave receive mode + \arg I2S_MODE_MASTERTX: I2S master transmit mode + \arg I2S_MODE_MASTERRX: I2S master receive mode + \param[in] i2s_standard: I2S standard + only one parameter can be selected which is shown as below: + \arg I2S_STD_PHILLIPS: I2S phillips standard + \arg I2S_STD_MSB: I2S MSB standard + \arg I2S_STD_LSB: I2S LSB standard + \arg I2S_STD_PCMSHORT: I2S PCM short standard + \arg I2S_STD_PCMLONG: I2S PCM long standard + \param[in] i2s_ckpl: I2S idle state clock polarity + only one parameter can be selected which is shown as below: + \arg I2S_CKPL_LOW: I2S clock polarity low level + \arg I2S_CKPL_HIGH: I2S clock polarity high level + \param[out] none + \retval none +*/ +void i2s_init(uint32_t spi_periph, uint32_t i2s_mode, uint32_t i2s_standard, uint32_t i2s_ckpl) +{ + uint32_t reg= 0U; + reg = SPI_I2SCTL(spi_periph); + reg &= I2S_INIT_MASK; + + /* enable I2S mode */ + reg |= (uint32_t)SPI_I2SCTL_I2SSEL; + /* select I2S mode */ + reg |= (uint32_t)i2s_mode; + /* select I2S standard */ + reg |= (uint32_t)i2s_standard; + /* select I2S polarity */ + reg |= (uint32_t)i2s_ckpl; + + /* write to SPI_I2SCTL register */ + SPI_I2SCTL(spi_periph) = (uint32_t)reg; +} + +/*! + \brief configure I2S prescaler + \param[in] spi_periph: SPIx(x=1,2) + \param[in] i2s_audiosample: I2S audio sample rate + only one parameter can be selected which is shown as below: + \arg I2S_AUDIOSAMPLE_8K: audio sample rate is 8KHz + \arg I2S_AUDIOSAMPLE_11K: audio sample rate is 11KHz + \arg I2S_AUDIOSAMPLE_16K: audio sample rate is 16KHz + \arg I2S_AUDIOSAMPLE_22K: audio sample rate is 22KHz + \arg I2S_AUDIOSAMPLE_32K: audio sample rate is 32KHz + \arg I2S_AUDIOSAMPLE_44K: audio sample rate is 44KHz + \arg I2S_AUDIOSAMPLE_48K: audio sample rate is 48KHz + \arg I2S_AUDIOSAMPLE_96K: audio sample rate is 96KHz + \arg I2S_AUDIOSAMPLE_192K: audio sample rate is 192KHz + \param[in] i2s_frameformat: I2S data length and channel length + only one parameter can be selected which is shown as below: + \arg I2S_FRAMEFORMAT_DT16B_CH16B: I2S data length is 16 bit and channel length is 16 bit + \arg I2S_FRAMEFORMAT_DT16B_CH32B: I2S data length is 16 bit and channel length is 32 bit + \arg I2S_FRAMEFORMAT_DT24B_CH32B: I2S data length is 24 bit and channel length is 32 bit + \arg I2S_FRAMEFORMAT_DT32B_CH32B: I2S data length is 32 bit and channel length is 32 bit + \param[in] i2s_mckout: I2S master clock output + only one parameter can be selected which is shown as below: + \arg I2S_MCKOUT_ENABLE: I2S master clock output enable + \arg I2S_MCKOUT_DISABLE: I2S master clock output disable + \param[out] none + \retval none +*/ +void i2s_psc_config(uint32_t spi_periph, uint32_t i2s_audiosample, uint32_t i2s_frameformat, uint32_t i2s_mckout) +{ + uint32_t i2sdiv = 2U, i2sof = 0U; + uint32_t clks = 0U; + uint32_t i2sclock = 0U; + +#ifdef GD32F30X_CL + uint32_t pll2mf_4 = 0U; +#endif /* GD32F30X_CL */ + + /* judge whether the audiosample is 0 */ + if(0U == i2s_audiosample){ + SPI_ERROR_HANDLE("the parameter can not be 0 \r\n"); + } + /* deinit SPI_I2SPSC register */ + SPI_I2SPSC(spi_periph) = SPI_I2SPSC_DEFAULT_VALUE; + +#ifdef GD32F30X_CL + /* get the I2S clock source */ + if(((uint32_t)spi_periph) == SPI1){ + /* I2S1 clock source selection */ + clks = I2S1_CLOCK_SEL; + }else{ + /* I2S2 clock source selection */ + clks = I2S2_CLOCK_SEL; + } + + if(0U != (RCU_CFG1 & clks)){ + /* get RCU PLL2 clock multiplication factor */ + clks = (uint32_t)((RCU_CFG1 & I2S_CLOCK_MUL_MASK) >> 12U); + + pll2mf_4 = RCU_CFG1 & RCU_CFG1_PLL2MF_4; + + if( 0U == pll2mf_4){ + if((clks > 5U) && (clks < 15U)){ + /* multiplier is between 8 and 16 */ + clks += 2U; + }else{ + if(15U == clks){ + /* multiplier is 20 */ + clks = 20U; + } + } + }else{ + if(clks < 15U){ + /* multiplier is between 18 and 32 */ + clks += 18U; + }else{ + if(15U == clks){ + /* multiplier is 40 */ + clks = 40U; + } + } + } + + /* get the PREDV1 value */ + i2sclock = (uint32_t)(((RCU_CFG1 & I2S_CLOCK_DIV_MASK) >> 4U) + 1U); + /* calculate i2sclock based on PLL2 and PREDV1 */ + i2sclock = (uint32_t)((HXTAL_VALUE / i2sclock) * clks * 2U); + }else{ + /* get system clock */ + i2sclock = rcu_clock_freq_get(CK_SYS); + } +#else + /* get system clock */ + i2sclock = rcu_clock_freq_get(CK_SYS); +#endif /* GD32F30X_CL */ + + /* config the prescaler depending on the mclk output state, the frame format and audio sample rate */ + if(I2S_MCKOUT_ENABLE == i2s_mckout){ + clks = (uint32_t)(((i2sclock / 256U) * 10U) / i2s_audiosample); + }else{ + if(I2S_FRAMEFORMAT_DT16B_CH16B == i2s_frameformat){ + clks = (uint32_t)(((i2sclock / 32U) *10U ) / i2s_audiosample); + }else{ + clks = (uint32_t)(((i2sclock / 64U) *10U ) / i2s_audiosample); + } + } + + /* remove the floating point */ + clks = (clks + 5U) / 10U; + i2sof = (clks & 0x00000001U); + i2sdiv = ((clks - i2sof) / 2U); + i2sof = (i2sof << 8U); + + /* set the default values */ + if((i2sdiv < 2U) || (i2sdiv > 255U)){ + i2sdiv = 2U; + i2sof = 0U; + } + + /* configure SPI_I2SPSC */ + SPI_I2SPSC(spi_periph) = (uint32_t)(i2sdiv | i2sof | i2s_mckout); + + /* clear SPI_I2SCTL_DTLEN and SPI_I2SCTL_CHLEN bits */ + SPI_I2SCTL(spi_periph) &= (uint32_t)(~(SPI_I2SCTL_DTLEN | SPI_I2SCTL_CHLEN)); + /* configure data frame format */ + SPI_I2SCTL(spi_periph) |= (uint32_t)i2s_frameformat; +} + +/*! + \brief enable I2S + \param[in] spi_periph: SPIx(x=1,2) + \param[out] none + \retval none +*/ +void i2s_enable(uint32_t spi_periph) +{ + SPI_I2SCTL(spi_periph) |= (uint32_t)SPI_I2SCTL_I2SEN; +} + +/*! + \brief disable I2S + \param[in] spi_periph: SPIx(x=1,2) + \param[out] none + \retval none +*/ +void i2s_disable(uint32_t spi_periph) +{ + SPI_I2SCTL(spi_periph) &= (uint32_t)(~SPI_I2SCTL_I2SEN); +} + +/*! + \brief enable SPI NSS output + \param[in] spi_periph: SPIx(x=0,1,2) + \param[out] none + \retval none +*/ +void spi_nss_output_enable(uint32_t spi_periph) +{ + SPI_CTL1(spi_periph) |= (uint32_t)SPI_CTL1_NSSDRV; +} + +/*! + \brief disable SPI NSS output + \param[in] spi_periph: SPIx(x=0,1,2) + \param[out] none + \retval none +*/ +void spi_nss_output_disable(uint32_t spi_periph) +{ + SPI_CTL1(spi_periph) &= (uint32_t)(~SPI_CTL1_NSSDRV); +} + +/*! + \brief SPI NSS pin high level in software mode + \param[in] spi_periph: SPIx(x=0,1,2) + \param[out] none + \retval none +*/ +void spi_nss_internal_high(uint32_t spi_periph) +{ + SPI_CTL0(spi_periph) |= (uint32_t)SPI_CTL0_SWNSS; +} + +/*! + \brief SPI NSS pin low level in software mode + \param[in] spi_periph: SPIx(x=0,1,2) + \param[out] none + \retval none +*/ +void spi_nss_internal_low(uint32_t spi_periph) +{ + SPI_CTL0(spi_periph) &= (uint32_t)(~SPI_CTL0_SWNSS); +} + +/*! + \brief enable SPI DMA send or receive + \param[in] spi_periph: SPIx(x=0,1,2) + \param[in] dma: SPI DMA mode + only one parameter can be selected which is shown as below: + \arg SPI_DMA_TRANSMIT: SPI transmit data use DMA + \arg SPI_DMA_RECEIVE: SPI receive data use DMA + \param[out] none + \retval none +*/ +void spi_dma_enable(uint32_t spi_periph, uint8_t dma) +{ + if(SPI_DMA_TRANSMIT == dma){ + SPI_CTL1(spi_periph) |= (uint32_t)SPI_CTL1_DMATEN; + }else{ + SPI_CTL1(spi_periph) |= (uint32_t)SPI_CTL1_DMAREN; + } +} + +/*! + \brief disable SPI DMA send or receive + \param[in] spi_periph: SPIx(x=0,1,2) + \param[in] dma: SPI DMA mode + only one parameter can be selected which is shown as below: + \arg SPI_DMA_TRANSMIT: SPI transmit data use DMA + \arg SPI_DMA_RECEIVE: SPI receive data use DMA + \param[out] none + \retval none +*/ +void spi_dma_disable(uint32_t spi_periph, uint8_t dma) +{ + if(SPI_DMA_TRANSMIT == dma){ + SPI_CTL1(spi_periph) &= (uint32_t)(~SPI_CTL1_DMATEN); + }else{ + SPI_CTL1(spi_periph) &= (uint32_t)(~SPI_CTL1_DMAREN); + } +} + +/*! + \brief configure SPI/I2S data frame format + \param[in] spi_periph: SPIx(x=0,1,2) + \param[in] frame_format: SPI frame size + only one parameter can be selected which is shown as below: + \arg SPI_FRAMESIZE_16BIT: SPI frame size is 16 bits + \arg SPI_FRAMESIZE_8BIT: SPI frame size is 8 bits + \param[out] none + \retval none +*/ +void spi_i2s_data_frame_format_config(uint32_t spi_periph, uint16_t frame_format) +{ + /* clear SPI_CTL0_FF16 bit */ + SPI_CTL0(spi_periph) &= (uint32_t)(~SPI_CTL0_FF16); + /* confige SPI_CTL0_FF16 bit */ + SPI_CTL0(spi_periph) |= (uint32_t)frame_format; +} + +/*! + \brief SPI transmit data + \param[in] spi_periph: SPIx(x=0,1,2) + \param[in] data: 16-bit data + \param[out] none + \retval none +*/ +void spi_i2s_data_transmit(uint32_t spi_periph, uint16_t data) +{ + SPI_DATA(spi_periph) = (uint32_t)data; +} + +/*! + \brief SPI receive data + \param[in] spi_periph: SPIx(x=0,1,2) + \param[out] none + \retval 16-bit data +*/ +uint16_t spi_i2s_data_receive(uint32_t spi_periph) +{ + return ((uint16_t)SPI_DATA(spi_periph)); +} + +/*! + \brief configure SPI bidirectional transfer direction + \param[in] spi_periph: SPIx(x=0,1,2) + \param[in] transfer_direction: SPI transfer direction + only one parameter can be selected which is shown as below: + \arg SPI_BIDIRECTIONAL_TRANSMIT: SPI work in transmit-only mode + \arg SPI_BIDIRECTIONAL_RECEIVE: SPI work in receive-only mode + \retval none +*/ +void spi_bidirectional_transfer_config(uint32_t spi_periph, uint32_t transfer_direction) +{ + if(SPI_BIDIRECTIONAL_TRANSMIT == transfer_direction){ + /* set the transmit only mode */ + SPI_CTL0(spi_periph) |= (uint32_t)SPI_BIDIRECTIONAL_TRANSMIT; + }else{ + /* set the receive only mode */ + SPI_CTL0(spi_periph) &= SPI_BIDIRECTIONAL_RECEIVE; + } +} + +/*! + \brief set SPI CRC polynomial + \param[in] spi_periph: SPIx(x=0,1,2) + \param[in] crc_poly: CRC polynomial value + \param[out] none + \retval none +*/ +void spi_crc_polynomial_set(uint32_t spi_periph,uint16_t crc_poly) +{ + /* set SPI CRC polynomial */ + SPI_CRCPOLY(spi_periph) = (uint32_t)crc_poly; +} + +/*! + \brief get SPI CRC polynomial + \param[in] spi_periph: SPIx(x=0,1,2) + \param[out] none + \retval 16-bit CRC polynomial +*/ +uint16_t spi_crc_polynomial_get(uint32_t spi_periph) +{ + return ((uint16_t)SPI_CRCPOLY(spi_periph)); +} + +/*! + \brief turn on CRC function + \param[in] spi_periph: SPIx(x=0,1,2) + \param[out] none + \retval none +*/ +void spi_crc_on(uint32_t spi_periph) +{ + SPI_CTL0(spi_periph) |= (uint32_t)SPI_CTL0_CRCEN; +} + +/*! + \brief turn off CRC function + \param[in] spi_periph: SPIx(x=0,1,2) + \param[out] none + \retval none +*/ +void spi_crc_off(uint32_t spi_periph) +{ + SPI_CTL0(spi_periph) &= (uint32_t)(~SPI_CTL0_CRCEN); +} + +/*! + \brief SPI next data is CRC value + \param[in] spi_periph: SPIx(x=0,1,2) + \param[out] none + \retval none +*/ +void spi_crc_next(uint32_t spi_periph) +{ + SPI_CTL0(spi_periph) |= (uint32_t)SPI_CTL0_CRCNT; +} + +/*! + \brief get SPI CRC send value or receive value + \param[in] spi_periph: SPIx(x=0,1,2) + \param[in] crc: SPI crc value + only one parameter can be selected which is shown as below: + \arg SPI_CRC_TX: get transmit crc value + \arg SPI_CRC_RX: get receive crc value + \param[out] none + \retval 16-bit CRC value +*/ +uint16_t spi_crc_get(uint32_t spi_periph,uint8_t crc) +{ + if(SPI_CRC_TX == crc){ + return ((uint16_t)(SPI_TCRC(spi_periph))); + }else{ + return ((uint16_t)(SPI_RCRC(spi_periph))); + } +} + +/*! + \brief enable SPI TI mode + \param[in] spi_periph: SPIx(x=0,1,2) + \param[out] none + \retval none +*/ +void spi_ti_mode_enable(uint32_t spi_periph) +{ + SPI_CTL1(spi_periph) |= (uint32_t)SPI_CTL1_TMOD; +} + +/*! + \brief disable SPI TI mode + \param[in] spi_periph: SPIx(x=0,1,2) + \param[out] none + \retval none +*/ +void spi_ti_mode_disable(uint32_t spi_periph) +{ + SPI_CTL1(spi_periph) &= (uint32_t)(~SPI_CTL1_TMOD); +} + +/*! + \brief enable SPI NSS pulse mode + \param[in] spi_periph: SPIx(x=0,1,2) + \param[out] none + \retval none +*/ +void spi_nssp_mode_enable(uint32_t spi_periph) +{ + SPI_CTL1(spi_periph) |= (uint32_t)SPI_CTL1_NSSP; +} + +/*! + \brief disable SPI NSS pulse mode + \param[in] spi_periph: SPIx(x=0,1,2) + \param[out] none + \retval none +*/ +void spi_nssp_mode_disable(uint32_t spi_periph) +{ + SPI_CTL1(spi_periph) &= (uint32_t)(~SPI_CTL1_NSSP); +} + +/*! + \brief enable quad wire SPI + \param[in] spi_periph: SPIx(only x=0) + \param[out] none + \retval none +*/ +void qspi_enable(uint32_t spi_periph) +{ + SPI_QCTL(spi_periph) |= (uint32_t)SPI_QCTL_QMOD; +} + +/*! + \brief disable quad wire SPI + \param[in] spi_periph: SPIx(only x=0) + \param[out] none + \retval none +*/ +void qspi_disable(uint32_t spi_periph) +{ + SPI_QCTL(spi_periph) &= (uint32_t)(~SPI_QCTL_QMOD); +} + +/*! + \brief enable quad wire SPI write + \param[in] spi_periph: SPIx(only x=0) + \param[out] none + \retval none +*/ +void qspi_write_enable(uint32_t spi_periph) +{ + SPI_QCTL(spi_periph) &= (uint32_t)(~SPI_QCTL_QRD); +} + +/*! + \brief enable quad wire SPI read + \param[in] spi_periph: SPIx(only x=0) + \param[out] none + \retval none +*/ +void qspi_read_enable(uint32_t spi_periph) +{ + SPI_QCTL(spi_periph) |= (uint32_t)SPI_QCTL_QRD; +} + +/*! + \brief enable SPI_IO2 and SPI_IO3 pin output + \param[in] spi_periph: SPIx(only x=0) + \param[out] none + \retval none +*/ +void qspi_io23_output_enable(uint32_t spi_periph) +{ + SPI_QCTL(spi_periph) |= (uint32_t)SPI_QCTL_IO23_DRV; +} + + /*! + \brief disable SPI_IO2 and SPI_IO3 pin output + \param[in] spi_periph: SPIx(only x=0) + \param[out] none + \retval none +*/ + void qspi_io23_output_disable(uint32_t spi_periph) +{ + SPI_QCTL(spi_periph) &= (uint32_t)(~SPI_QCTL_IO23_DRV); +} + +/*! + \brief enable SPI and I2S interrupt + \param[in] spi_periph: SPIx(x=0,1,2) + \param[in] interrupt: SPI/I2S interrupt + only one parameter can be selected which is shown as below: + \arg SPI_I2S_INT_TBE: transmit buffer empty interrupt + \arg SPI_I2S_INT_RBNE: receive buffer not empty interrupt + \arg SPI_I2S_INT_ERR: CRC error,configuration error,reception overrun error, + transmission underrun error and format error interrupt + \param[out] none + \retval none +*/ +void spi_i2s_interrupt_enable(uint32_t spi_periph, uint8_t interrupt) +{ + switch(interrupt){ + /* SPI/I2S transmit buffer empty interrupt */ + case SPI_I2S_INT_TBE: + SPI_CTL1(spi_periph) |= (uint32_t)SPI_CTL1_TBEIE; + break; + /* SPI/I2S receive buffer not empty interrupt */ + case SPI_I2S_INT_RBNE: + SPI_CTL1(spi_periph) |= (uint32_t)SPI_CTL1_RBNEIE; + break; + /* SPI/I2S error */ + case SPI_I2S_INT_ERR: + SPI_CTL1(spi_periph) |= (uint32_t)SPI_CTL1_ERRIE; + break; + default: + break; + } +} + +/*! + \brief disable SPI and I2S interrupt + \param[in] spi_periph: SPIx(x=0,1,2) + \param[in] interrupt: SPI/I2S interrupt + only one parameter can be selected which is shown as below: + \arg SPI_I2S_INT_TBE: transmit buffer empty interrupt + \arg SPI_I2S_INT_RBNE: receive buffer not empty interrupt + \arg SPI_I2S_INT_ERR: CRC error,configuration error,reception overrun error, + transmission underrun error and format error interrupt + \param[out] none + \retval none +*/ +void spi_i2s_interrupt_disable(uint32_t spi_periph, uint8_t interrupt) +{ + switch(interrupt){ + /* SPI/I2S transmit buffer empty interrupt */ + case SPI_I2S_INT_TBE: + SPI_CTL1(spi_periph) &= (uint32_t)(~SPI_CTL1_TBEIE); + break; + /* SPI/I2S receive buffer not empty interrupt */ + case SPI_I2S_INT_RBNE: + SPI_CTL1(spi_periph) &= (uint32_t)(~SPI_CTL1_RBNEIE); + break; + /* SPI/I2S error */ + case SPI_I2S_INT_ERR: + SPI_CTL1(spi_periph) &= (uint32_t)(~SPI_CTL1_ERRIE); + break; + default : + break; + } +} + +/*! + \brief get SPI and I2S interrupt flag status + \param[in] spi_periph: SPIx(x=0,1,2) + \param[in] interrupt: SPI/I2S interrupt flag status + only one parameter can be selected which is shown as below: + \arg SPI_I2S_INT_FLAG_TBE: transmit buffer empty interrupt flag + \arg SPI_I2S_INT_FLAG_RBNE: receive buffer not empty interrupt flag + \arg SPI_I2S_INT_FLAG_RXORERR: overrun interrupt flag + \arg SPI_INT_FLAG_CONFERR: config error interrupt flag + \arg SPI_INT_FLAG_CRCERR: CRC error interrupt flag + \arg I2S_INT_FLAG_TXURERR: underrun error interrupt flag + \arg SPI_I2S_INT_FLAG_FERR: format error interrupt flag + \param[out] none + \retval FlagStatus: SET or RESET +*/ +FlagStatus spi_i2s_interrupt_flag_get(uint32_t spi_periph, uint8_t interrupt) +{ + uint32_t reg1 = SPI_STAT(spi_periph); + uint32_t reg2 = SPI_CTL1(spi_periph); + + switch(interrupt){ + /* SPI/I2S transmit buffer empty interrupt */ + case SPI_I2S_INT_FLAG_TBE: + reg1 = reg1 & SPI_STAT_TBE; + reg2 = reg2 & SPI_CTL1_TBEIE; + break; + /* SPI/I2S receive buffer not empty interrupt */ + case SPI_I2S_INT_FLAG_RBNE: + reg1 = reg1 & SPI_STAT_RBNE; + reg2 = reg2 & SPI_CTL1_RBNEIE; + break; + /* SPI/I2S overrun interrupt */ + case SPI_I2S_INT_FLAG_RXORERR: + reg1 = reg1 & SPI_STAT_RXORERR; + reg2 = reg2 & SPI_CTL1_ERRIE; + break; + /* SPI config error interrupt */ + case SPI_INT_FLAG_CONFERR: + reg1 = reg1 & SPI_STAT_CONFERR; + reg2 = reg2 & SPI_CTL1_ERRIE; + break; + /* SPI CRC error interrupt */ + case SPI_INT_FLAG_CRCERR: + reg1 = reg1 & SPI_STAT_CRCERR; + reg2 = reg2 & SPI_CTL1_ERRIE; + break; + /* I2S underrun error interrupt */ + case I2S_INT_FLAG_TXURERR: + reg1 = reg1 & SPI_STAT_TXURERR; + reg2 = reg2 & SPI_CTL1_ERRIE; + break; + /* SPI/I2S format error interrupt */ + case SPI_I2S_INT_FLAG_FERR: + reg1 = reg1 & SPI_STAT_FERR; + reg2 = reg2 & SPI_CTL1_ERRIE; + break; + default : + break; + } + /*get SPI/I2S interrupt flag status */ + if(reg1 && reg2){ + return SET; + }else{ + return RESET; + } +} + +/*! + \brief get SPI and I2S flag status + \param[in] spi_periph: SPIx(x=0,1,2) + \param[in] flag: SPI/I2S flag status + only one parameter can be selected which is shown as below: + \arg SPI_FLAG_TBE: transmit buffer empty flag + \arg SPI_FLAG_RBNE: receive buffer not empty flag + \arg SPI_FLAG_TRANS: transmit on-going flag + \arg SPI_FLAG_RXORERR: receive overrun error flag + \arg SPI_FLAG_CONFERR: mode config error flag + \arg SPI_FLAG_CRCERR: CRC error flag + \arg SPI_FLAG_FERR: format error flag + \arg I2S_FLAG_TBE: transmit buffer empty flag + \arg I2S_FLAG_RBNE: receive buffer not empty flag + \arg I2S_FLAG_TRANS: transmit on-going flag + \arg I2S_FLAG_RXORERR: overrun error flag + \arg I2S_FLAG_TXURERR: underrun error flag + \arg I2S_FLAG_CH: channel side flag + \arg I2S_FLAG_FERR: format error flag + \param[out] none + \retval FlagStatus: SET or RESET +*/ +FlagStatus spi_i2s_flag_get(uint32_t spi_periph, uint32_t flag) +{ + if(SPI_STAT(spi_periph) & flag){ + return SET; + }else{ + return RESET; + } +} + +/*! + \brief clear SPI CRC error flag status + \param[in] spi_periph: SPIx(x=0,1,2) + \param[out] none + \retval none +*/ +void spi_crc_error_clear(uint32_t spi_periph) +{ + SPI_STAT(spi_periph) &= (uint32_t)(~SPI_FLAG_CRCERR); +} diff --git a/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_standard_peripheral/Source/gd32f30x_timer.c b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_standard_peripheral/Source/gd32f30x_timer.c new file mode 100644 index 0000000000..47531ad495 --- /dev/null +++ b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_standard_peripheral/Source/gd32f30x_timer.c @@ -0,0 +1,2042 @@ +/*! + \file gd32f30x_timer.c + \brief TIMER driver + + \version 2017-02-10, V1.0.0, firmware for GD32F30x + \version 2018-10-10, V1.1.0, firmware for GD32F30x + \version 2018-12-25, V2.0.0, firmware for GD32F30x + \version 2020-09-30, V2.1.0, firmware for GD32F30x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "gd32f30x_timer.h" + +/*! + \brief deinit a TIMER + \param[in] timer_periph: TIMERx(x=0..13) + \param[out] none + \retval none +*/ +void timer_deinit(uint32_t timer_periph) +{ + switch(timer_periph){ + case TIMER0: + /* reset TIMER0 */ + rcu_periph_reset_enable(RCU_TIMER0RST); + rcu_periph_reset_disable(RCU_TIMER0RST); + break; + case TIMER1: + /* reset TIMER1 */ + rcu_periph_reset_enable(RCU_TIMER1RST); + rcu_periph_reset_disable(RCU_TIMER1RST); + break; + case TIMER2: + /* reset TIMER2 */ + rcu_periph_reset_enable(RCU_TIMER2RST); + rcu_periph_reset_disable(RCU_TIMER2RST); + break; + case TIMER3: + /* reset TIMER3 */ + rcu_periph_reset_enable(RCU_TIMER3RST); + rcu_periph_reset_disable(RCU_TIMER3RST); + break; + case TIMER4: + /* reset TIMER4 */ + rcu_periph_reset_enable(RCU_TIMER4RST); + rcu_periph_reset_disable(RCU_TIMER4RST); + break; + case TIMER5: + /* reset TIMER5 */ + rcu_periph_reset_enable(RCU_TIMER5RST); + rcu_periph_reset_disable(RCU_TIMER5RST); + break; + case TIMER6: + /* reset TIMER6 */ + rcu_periph_reset_enable(RCU_TIMER6RST); + rcu_periph_reset_disable(RCU_TIMER6RST); + break; + case TIMER7: + /* reset TIMER7 */ + rcu_periph_reset_enable(RCU_TIMER7RST); + rcu_periph_reset_disable(RCU_TIMER7RST); + break; +#ifndef GD32F30X_HD + case TIMER8: + /* reset TIMER8 */ + rcu_periph_reset_enable(RCU_TIMER8RST); + rcu_periph_reset_disable(RCU_TIMER8RST); + break; + case TIMER9: + /* reset TIMER9 */ + rcu_periph_reset_enable(RCU_TIMER9RST); + rcu_periph_reset_disable(RCU_TIMER9RST); + break; + case TIMER10: + /* reset TIMER10 */ + rcu_periph_reset_enable(RCU_TIMER10RST); + rcu_periph_reset_disable(RCU_TIMER10RST); + break; + case TIMER11: + /* reset TIMER11 */ + rcu_periph_reset_enable(RCU_TIMER11RST); + rcu_periph_reset_disable(RCU_TIMER11RST); + break; + case TIMER12: + /* reset TIMER12 */ + rcu_periph_reset_enable(RCU_TIMER12RST); + rcu_periph_reset_disable(RCU_TIMER12RST); + break; + case TIMER13: + /* reset TIMER13 */ + rcu_periph_reset_enable(RCU_TIMER13RST); + rcu_periph_reset_disable(RCU_TIMER13RST); + break; +#endif /* GD32F30X_HD */ + default: + break; + } +} + +/*! + \brief initialize TIMER init parameter struct with a default value + \param[in] initpara: init parameter struct + \param[out] none + \retval none +*/ +void timer_struct_para_init(timer_parameter_struct* initpara) +{ + /* initialize the init parameter struct member with the default value */ + initpara->prescaler = 0U; + initpara->alignedmode = TIMER_COUNTER_EDGE; + initpara->counterdirection = TIMER_COUNTER_UP; + initpara->period = 65535U; + initpara->clockdivision = TIMER_CKDIV_DIV1; + initpara->repetitioncounter = 0U; +} + +/*! + \brief initialize TIMER counter + \param[in] timer_periph: TIMERx(x=0..13) + \param[in] initpara: init parameter struct + prescaler: prescaler value of the counter clock, 0~65535 + alignedmode: TIMER_COUNTER_EDGE, TIMER_COUNTER_CENTER_DOWN, TIMER_COUNTER_CENTER_UP, TIMER_COUNTER_CENTER_BOTH + counterdirection: TIMER_COUNTER_UP, TIMER_COUNTER_DOWN + period: counter auto reload value, 0~65535 + clockdivision: TIMER_CKDIV_DIV1, TIMER_CKDIV_DIV2, TIMER_CKDIV_DIV4 + repetitioncounter: counter repetition value, 0~255 + \param[out] none + \retval none +*/ +void timer_init(uint32_t timer_periph, timer_parameter_struct* initpara) +{ + /* configure the counter prescaler value */ + TIMER_PSC(timer_periph) = (uint16_t)initpara->prescaler; + + /* configure the counter direction and aligned mode */ + if((TIMER0 == timer_periph) || (TIMER1 == timer_periph) || (TIMER2 == timer_periph) + || (TIMER3 == timer_periph) || (TIMER4 == timer_periph) || (TIMER7 == timer_periph)){ + TIMER_CTL0(timer_periph) &= ~(uint32_t)(TIMER_CTL0_DIR|TIMER_CTL0_CAM); + TIMER_CTL0(timer_periph) |= (uint32_t)initpara->alignedmode; + TIMER_CTL0(timer_periph) |= (uint32_t)initpara->counterdirection; + } + + /* configure the autoreload value */ + TIMER_CAR(timer_periph) = (uint32_t)initpara->period; + + if((TIMER5 != timer_periph) && (TIMER6 != timer_periph)){ + /* reset the CKDIV bit */ + TIMER_CTL0(timer_periph) &= ~(uint32_t)TIMER_CTL0_CKDIV; + TIMER_CTL0(timer_periph) |= (uint32_t)initpara->clockdivision; + } + + if((TIMER0 == timer_periph) || (TIMER7 == timer_periph)){ + /* configure the repetition counter value */ + TIMER_CREP(timer_periph) = (uint32_t)initpara->repetitioncounter; + } + + /* generate an update event */ + TIMER_SWEVG(timer_periph) |= (uint32_t)TIMER_SWEVG_UPG; +} + +/*! + \brief enable a TIMER + \param[in] timer_periph: TIMERx(x=0..13) + \param[out] none + \retval none +*/ +void timer_enable(uint32_t timer_periph) +{ + TIMER_CTL0(timer_periph) |= (uint32_t)TIMER_CTL0_CEN; +} + +/*! + \brief disable a TIMER + \param[in] timer_periph: TIMERx(x=0..13) + \param[out] none + \retval none +*/ +void timer_disable(uint32_t timer_periph) +{ + TIMER_CTL0(timer_periph) &= ~(uint32_t)TIMER_CTL0_CEN; +} + +/*! + \brief enable the auto reload shadow function + \param[in] timer_periph: TIMERx(x=0..13) + \param[out] none + \retval none +*/ +void timer_auto_reload_shadow_enable(uint32_t timer_periph) +{ + TIMER_CTL0(timer_periph) |= (uint32_t)TIMER_CTL0_ARSE; +} + +/*! + \brief disable the auto reload shadow function + \param[in] timer_periph: TIMERx(x=0..13) + \param[out] none + \retval none +*/ +void timer_auto_reload_shadow_disable(uint32_t timer_periph) +{ + TIMER_CTL0(timer_periph) &= ~(uint32_t)TIMER_CTL0_ARSE; +} + +/*! + \brief enable the update event + \param[in] timer_periph: TIMERx(x=0..13) + \param[out] none + \retval none +*/ +void timer_update_event_enable(uint32_t timer_periph) +{ + TIMER_CTL0(timer_periph) &= ~(uint32_t)TIMER_CTL0_UPDIS; +} + +/*! + \brief disable the update event + \param[in] timer_periph: TIMERx(x=0..13) + \param[out] none + \retval none +*/ +void timer_update_event_disable(uint32_t timer_periph) +{ + TIMER_CTL0(timer_periph) |= (uint32_t) TIMER_CTL0_UPDIS; +} + +/*! + \brief set TIMER counter alignment mode + \param[in] timer_periph: TIMERx(x=0..4,7) + \param[in] aligned: + only one parameter can be selected which is shown as below: + \arg TIMER_COUNTER_EDGE: edge-aligned mode + \arg TIMER_COUNTER_CENTER_DOWN: center-aligned and counting down assert mode + \arg TIMER_COUNTER_CENTER_UP: center-aligned and counting up assert mode + \arg TIMER_COUNTER_CENTER_BOTH: center-aligned and counting up/down assert mode + \param[out] none + \retval none +*/ +void timer_counter_alignment(uint32_t timer_periph, uint16_t aligned) +{ + TIMER_CTL0(timer_periph) &= ~(uint32_t)TIMER_CTL0_CAM; + TIMER_CTL0(timer_periph) |= (uint32_t)aligned; +} + +/*! + \brief set TIMER counter up direction + \param[in] timer_periph: TIMERx(x=0..4,7) + \param[out] none + \retval none +*/ +void timer_counter_up_direction(uint32_t timer_periph) +{ + TIMER_CTL0(timer_periph) &= ~(uint32_t)TIMER_CTL0_DIR; +} + +/*! + \brief set TIMER counter down direction + \param[in] timer_periph: TIMERx(x=0..4,7) + \param[out] none + \retval none +*/ +void timer_counter_down_direction(uint32_t timer_periph) +{ + TIMER_CTL0(timer_periph) |= (uint32_t)TIMER_CTL0_DIR; +} + +/*! + \brief configure TIMER prescaler + \param[in] timer_periph: TIMERx(x=0..13) + \param[in] prescaler: prescaler value,0~65535 + \param[in] pscreload: prescaler reload mode + only one parameter can be selected which is shown as below: + \arg TIMER_PSC_RELOAD_NOW: the prescaler is loaded right now + \arg TIMER_PSC_RELOAD_UPDATE: the prescaler is loaded at the next update event + \param[out] none + \retval none +*/ +void timer_prescaler_config(uint32_t timer_periph, uint16_t prescaler, uint8_t pscreload) +{ + TIMER_PSC(timer_periph) = (uint32_t)prescaler; + + if(TIMER_PSC_RELOAD_NOW == pscreload){ + TIMER_SWEVG(timer_periph) |= (uint32_t)TIMER_SWEVG_UPG; + } +} + +/*! + \brief configure TIMER repetition register value + \param[in] timer_periph: TIMERx(x=0,7) + \param[in] repetition: the counter repetition value,0~255 + \param[out] none + \retval none +*/ +void timer_repetition_value_config(uint32_t timer_periph, uint16_t repetition) +{ + TIMER_CREP(timer_periph) = (uint32_t)repetition; +} + +/*! + \brief configure TIMER autoreload register value + \param[in] timer_periph: TIMERx(x=0..13) + \param[in] autoreload: the counter auto-reload value,0~65535 + \param[out] none + \retval none +*/ +void timer_autoreload_value_config(uint32_t timer_periph, uint16_t autoreload) +{ + TIMER_CAR(timer_periph) = (uint32_t)autoreload; +} + +/*! + \brief configure TIMER counter register value + \param[in] timer_periph: TIMERx(x=0..13) + \param[in] counter: the counter value,0~65535 + \param[out] none + \retval none +*/ +void timer_counter_value_config(uint32_t timer_periph, uint16_t counter) +{ + TIMER_CNT(timer_periph) = (uint32_t)counter; +} + +/*! + \brief read TIMER counter value + \param[in] timer_periph: TIMERx(x=0..13) + \param[out] none + \retval counter value +*/ +uint32_t timer_counter_read(uint32_t timer_periph) +{ + uint32_t count_value = 0U; + count_value = TIMER_CNT(timer_periph); + return (count_value); +} + +/*! + \brief read TIMER prescaler value + \param[in] timer_periph: TIMERx(x=0..13) + \param[out] none + \retval prescaler register value +*/ +uint16_t timer_prescaler_read(uint32_t timer_periph) +{ + uint16_t prescaler_value = 0U; + prescaler_value = (uint16_t)(TIMER_PSC(timer_periph)); + return (prescaler_value); +} + +/*! + \brief configure TIMER single pulse mode + \param[in] timer_periph: TIMERx(x=0..8,11) + \param[in] spmode: + only one parameter can be selected which is shown as below: + \arg TIMER_SP_MODE_SINGLE: single pulse mode + \arg TIMER_SP_MODE_REPETITIVE: repetitive pulse mode + \param[out] none + \retval none +*/ +void timer_single_pulse_mode_config(uint32_t timer_periph, uint32_t spmode) +{ + if(TIMER_SP_MODE_SINGLE == spmode){ + TIMER_CTL0(timer_periph) |= (uint32_t)TIMER_CTL0_SPM; + }else if(TIMER_SP_MODE_REPETITIVE == spmode){ + TIMER_CTL0(timer_periph) &= ~((uint32_t)TIMER_CTL0_SPM); + }else{ + /* illegal parameters */ + } +} + +/*! + \brief configure TIMER update source + \param[in] timer_periph: TIMERx(x=0..13) + \param[in] update: + only one parameter can be selected which is shown as below: + \arg TIMER_UPDATE_SRC_GLOBAL: update generate by setting of UPG bit or the counter overflow/underflow,or the slave mode controller trigger + \arg TIMER_UPDATE_SRC_REGULAR: update generate only by counter overflow/underflow + \param[out] none + \retval none +*/ +void timer_update_source_config(uint32_t timer_periph, uint32_t update) +{ + if(TIMER_UPDATE_SRC_REGULAR == update){ + TIMER_CTL0(timer_periph) |= (uint32_t)TIMER_CTL0_UPS; + }else if(TIMER_UPDATE_SRC_GLOBAL == update){ + TIMER_CTL0(timer_periph) &= ~(uint32_t)TIMER_CTL0_UPS; + }else{ + /* illegal parameters */ + } +} + +/*! + \brief enable the TIMER interrupt + \param[in] timer_periph: please refer to the following parameters + \param[in] interrupt: timer interrupt enable source + only one parameter can be selected which is shown as below: + \arg TIMER_INT_UP: update interrupt enable, TIMERx(x=0..13) + \arg TIMER_INT_CH0: channel 0 interrupt enable, TIMERx(x=0..4,7..13) + \arg TIMER_INT_CH1: channel 1 interrupt enable, TIMERx(x=0..4,7,8,11) + \arg TIMER_INT_CH2: channel 2 interrupt enable, TIMERx(x=0..4,7) + \arg TIMER_INT_CH3: channel 3 interrupt enable , TIMERx(x=0..4,7) + \arg TIMER_INT_CMT: commutation interrupt enable, TIMERx(x=0,7) + \arg TIMER_INT_TRG: trigger interrupt enable, TIMERx(x=0..4,7,8,11) + \arg TIMER_INT_BRK: break interrupt enable, TIMERx(x=0,7) + \param[out] none + \retval none +*/ +void timer_interrupt_enable(uint32_t timer_periph, uint32_t interrupt) +{ + TIMER_DMAINTEN(timer_periph) |= (uint32_t) interrupt; +} + +/*! + \brief disable the TIMER interrupt + \param[in] timer_periph: please refer to the following parameters + \param[in] interrupt: timer interrupt source disable + only one parameter can be selected which is shown as below: + \arg TIMER_INT_UP: update interrupt disable, TIMERx(x=0..13) + \arg TIMER_INT_CH0: channel 0 interrupt disable, TIMERx(x=0..4,7..13) + \arg TIMER_INT_CH1: channel 1 interrupt disable, TIMERx(x=0..4,7,8,11) + \arg TIMER_INT_CH2: channel 2 interrupt disable, TIMERx(x=0..4,7) + \arg TIMER_INT_CH3: channel 3 interrupt disable , TIMERx(x=0..4,7) + \arg TIMER_INT_CMT: commutation interrupt disable, TIMERx(x=0,7) + \arg TIMER_INT_TRG: trigger interrupt disable, TIMERx(x=0..4,7,8,11) + \arg TIMER_INT_BRK: break interrupt disable, TIMERx(x=0,7) + \param[out] none + \retval none +*/ +void timer_interrupt_disable(uint32_t timer_periph, uint32_t interrupt) +{ + TIMER_DMAINTEN(timer_periph) &= (~(uint32_t)interrupt); +} + +/*! + \brief get timer interrupt flag + \param[in] timer_periph: please refer to the following parameters + \param[in] interrupt: the timer interrupt bits + only one parameter can be selected which is shown as below: + \arg TIMER_INT_FLAG_UP: update interrupt flag,TIMERx(x=0..13) + \arg TIMER_INT_FLAG_CH0: channel 0 interrupt flag,TIMERx(x=0..4,7..13) + \arg TIMER_INT_FLAG_CH1: channel 1 interrupt flag,TIMERx(x=0..4,7,8,11) + \arg TIMER_INT_FLAG_CH2: channel 2 interrupt flag,TIMERx(x=0..4,7) + \arg TIMER_INT_FLAG_CH3: channel 3 interrupt flag,TIMERx(x=0..4,7) + \arg TIMER_INT_FLAG_CMT: channel commutation interrupt flag,TIMERx(x=0,7) + \arg TIMER_INT_FLAG_TRG: trigger interrupt flag,TIMERx(x=0,7,8,11) + \arg TIMER_INT_FLAG_BRK: break interrupt flag,TIMERx(x=0,7) + \param[out] none + \retval FlagStatus: SET or RESET +*/ +FlagStatus timer_interrupt_flag_get(uint32_t timer_periph, uint32_t interrupt) +{ + uint32_t val; + val = (TIMER_DMAINTEN(timer_periph) & interrupt); + if((RESET != (TIMER_INTF(timer_periph) & interrupt) ) && (RESET != val)){ + return SET; + }else{ + return RESET; + } +} + +/*! + \brief clear TIMER interrupt flag + \param[in] timer_periph: please refer to the following parameters + \param[in] interrupt: the timer interrupt bits + only one parameter can be selected which is shown as below: + \arg TIMER_INT_FLAG_UP: update interrupt flag,TIMERx(x=0..13) + \arg TIMER_INT_FLAG_CH0: channel 0 interrupt flag,TIMERx(x=0..4,7..13) + \arg TIMER_INT_FLAG_CH1: channel 1 interrupt flag,TIMERx(x=0..4,7,8,11) + \arg TIMER_INT_FLAG_CH2: channel 2 interrupt flag,TIMERx(x=0..4,7) + \arg TIMER_INT_FLAG_CH3: channel 3 interrupt flag,TIMERx(x=0..4,7) + \arg TIMER_INT_FLAG_CMT: channel commutation interrupt flag,TIMERx(x=0,7) + \arg TIMER_INT_FLAG_TRG: trigger interrupt flag,TIMERx(x=0,7,8,11) + \arg TIMER_INT_FLAG_BRK: break interrupt flag,TIMERx(x=0,7) + \param[out] none + \retval none +*/ +void timer_interrupt_flag_clear(uint32_t timer_periph, uint32_t interrupt) +{ + TIMER_INTF(timer_periph) = (~(uint32_t)interrupt); +} + +/*! + \brief get TIMER flags + \param[in] timer_periph: please refer to the following parameters + \param[in] flag: the timer interrupt flags + only one parameter can be selected which is shown as below: + \arg TIMER_FLAG_UP: update flag,TIMERx(x=0..13) + \arg TIMER_FLAG_CH0: channel 0 flag,TIMERx(x=0..4,7..13) + \arg TIMER_FLAG_CH1: channel 1 flag,TIMERx(x=0..4,7,8,11) + \arg TIMER_FLAG_CH2: channel 2 flag,TIMERx(x=0..4,7) + \arg TIMER_FLAG_CH3: channel 3 flag,TIMERx(x=0..4,7) + \arg TIMER_FLAG_CMT: channel control update flag,TIMERx(x=0,7) + \arg TIMER_FLAG_TRG: trigger flag,TIMERx(x=0,7,8,11) + \arg TIMER_FLAG_BRK: break flag,TIMERx(x=0,7) + \arg TIMER_FLAG_CH0O: channel 0 overcapture flag,TIMERx(x=0..4,7..11) + \arg TIMER_FLAG_CH1O: channel 1 overcapture flag,TIMERx(x=0..4,7,8,11) + \arg TIMER_FLAG_CH2O: channel 2 overcapture flag,TIMERx(x=0..4,7) + \arg TIMER_FLAG_CH3O: channel 3 overcapture flag,TIMERx(x=0..4,7) + \param[out] none + \retval FlagStatus: SET or RESET +*/ +FlagStatus timer_flag_get(uint32_t timer_periph, uint32_t flag) +{ + if(RESET != (TIMER_INTF(timer_periph) & flag)){ + return SET; + }else{ + return RESET; + } +} + +/*! + \brief clear TIMER flags + \param[in] timer_periph: please refer to the following parameters + \param[in] flag: the timer interrupt flags + only one parameter can be selected which is shown as below: + \arg TIMER_FLAG_UP: update flag,TIMERx(x=0..13) + \arg TIMER_FLAG_CH0: channel 0 flag,TIMERx(x=0..4,7..13) + \arg TIMER_FLAG_CH1: channel 1 flag,TIMERx(x=0..4,7,8,11) + \arg TIMER_FLAG_CH2: channel 2 flag,TIMERx(x=0..4,7) + \arg TIMER_FLAG_CH3: channel 3 flag,TIMERx(x=0..4,7) + \arg TIMER_FLAG_CMT: channel control update flag,TIMERx(x=0,7) + \arg TIMER_FLAG_TRG: trigger flag,TIMERx(x=0,7,8,11) + \arg TIMER_FLAG_BRK: break flag,TIMERx(x=0,7) + \arg TIMER_FLAG_CH0O: channel 0 overcapture flag,TIMERx(x=0..4,7..11) + \arg TIMER_FLAG_CH1O: channel 1 overcapture flag,TIMERx(x=0..4,7,8,11) + \arg TIMER_FLAG_CH2O: channel 2 overcapture flag,TIMERx(x=0..4,7) + \arg TIMER_FLAG_CH3O: channel 3 overcapture flag,TIMERx(x=0..4,7) + \param[out] none + \retval none +*/ +void timer_flag_clear(uint32_t timer_periph, uint32_t flag) +{ + TIMER_INTF(timer_periph) = (~(uint32_t)flag); +} + +/*! + \brief enable the TIMER DMA + \param[in] timer_periph: please refer to the following parameters + \param[in] dma: specify which DMA to enable + only one parameter can be selected which is shown as below: + \arg TIMER_DMA_UPD: update DMA enable,TIMERx(x=0..7) + \arg TIMER_DMA_CH0D: channel 0 DMA enable,TIMERx(x=0..4,7) + \arg TIMER_DMA_CH1D: channel 1 DMA enable,TIMERx(x=0..4,7) + \arg TIMER_DMA_CH2D: channel 2 DMA enable,TIMERx(x=0..4,7) + \arg TIMER_DMA_CH3D: channel 3 DMA enable,TIMERx(x=0..4,7) + \arg TIMER_DMA_CMTD: commutation DMA request enable,TIMERx(x=0,7) + \arg TIMER_DMA_TRGD: trigger DMA enable,TIMERx(x=0..4,7) + \param[out] none + \retval none +*/ +void timer_dma_enable(uint32_t timer_periph, uint16_t dma) +{ + TIMER_DMAINTEN(timer_periph) |= (uint32_t) dma; +} + +/*! + \brief disable the TIMER DMA + \param[in] timer_periph: please refer to the following parameters + \param[in] dma: specify which DMA to enable + one or more parameters can be selected which are shown as below: + \arg TIMER_DMA_UPD: update DMA ,TIMERx(x=0..7) + \arg TIMER_DMA_CH0D: channel 0 DMA request,TIMERx(x=0..4,7) + \arg TIMER_DMA_CH1D: channel 1 DMA request,TIMERx(x=0..4,7) + \arg TIMER_DMA_CH2D: channel 2 DMA request,TIMERx(x=0..4,7) + \arg TIMER_DMA_CH3D: channel 3 DMA request,TIMERx(x=0..4,7) + \arg TIMER_DMA_CMTD: commutation DMA request ,TIMERx(x=0,7) + \arg TIMER_DMA_TRGD: trigger DMA request,TIMERx(x=0..4,7) + \param[out] none + \retval none +*/ +void timer_dma_disable(uint32_t timer_periph, uint16_t dma) +{ + TIMER_DMAINTEN(timer_periph) &= (~(uint32_t)(dma)); +} + +/*! + \brief channel DMA request source selection + \param[in] timer_periph: TIMERx(x=0..4,7) + \param[in] dma_request: channel DMA request source selection + only one parameter can be selected which is shown as below: + \arg TIMER_DMAREQUEST_CHANNELEVENT: DMA request of channel y is sent when channel y event occurs + \arg TIMER_DMAREQUEST_UPDATEEVENT: DMA request of channel y is sent when update event occurs + \param[out] none + \retval none +*/ +void timer_channel_dma_request_source_select(uint32_t timer_periph, uint8_t dma_request) +{ + if(TIMER_DMAREQUEST_UPDATEEVENT == dma_request){ + TIMER_CTL1(timer_periph) |= (uint32_t)TIMER_CTL1_DMAS; + }else if(TIMER_DMAREQUEST_CHANNELEVENT == dma_request){ + TIMER_CTL1(timer_periph) &= ~(uint32_t)TIMER_CTL1_DMAS; + }else{ + /* illegal parameters */ + } +} + +/*! + \brief configure the TIMER DMA transfer + \param[in] timer_periph: please refer to the following parameters + \param[in] dma_baseaddr: + only one parameter can be selected which is shown as below: + \arg TIMER_DMACFG_DMATA_CTL0: DMA transfer address is TIMER_CTL0,TIMERx(x=0..4,7) + \arg TIMER_DMACFG_DMATA_CTL1: DMA transfer address is TIMER_CTL1,TIMERx(x=0..4,7) + \arg TIMER_DMACFG_DMATA_SMCFG: DMA transfer address is TIMER_SMCFG,TIMERx(x=0..4,7) + \arg TIMER_DMACFG_DMATA_DMAINTEN: DMA transfer address is TIMER_DMAINTEN,TIMERx(x=0..4,7) + \arg TIMER_DMACFG_DMATA_INTF: DMA transfer address is TIMER_INTF,TIMERx(x=0..4,7) + \arg TIMER_DMACFG_DMATA_SWEVG: DMA transfer address is TIMER_SWEVG,TIMERx(x=0..4,7) + \arg TIMER_DMACFG_DMATA_CHCTL0: DMA transfer address is TIMER_CHCTL0,TIMERx(x=0..4,7) + \arg TIMER_DMACFG_DMATA_CHCTL1: DMA transfer address is TIMER_CHCTL1,TIMERx(x=0..4,7) + \arg TIMER_DMACFG_DMATA_CHCTL2: DMA transfer address is TIMER_CHCTL2,TIMERx(x=0..4,7) + \arg TIMER_DMACFG_DMATA_CNT: DMA transfer address is TIMER_CNT,TIMERx(x=0..4,7) + \arg TIMER_DMACFG_DMATA_PSC: DMA transfer address is TIMER_PSC,TIMERx(x=0..4,7) + \arg TIMER_DMACFG_DMATA_CAR: DMA transfer address is TIMER_CAR,TIMERx(x=0..4,7) + \arg TIMER_DMACFG_DMATA_CREP: DMA transfer address is TIMER_CREP,TIMERx(x=0,7) + \arg TIMER_DMACFG_DMATA_CH0CV: DMA transfer address is TIMER_CH0CV,TIMERx(x=0..4,7) + \arg TIMER_DMACFG_DMATA_CH1CV: DMA transfer address is TIMER_CH1CV,TIMERx(x=0..4,7) + \arg TIMER_DMACFG_DMATA_CH2CV: DMA transfer address is TIMER_CH2CV,TIMERx(x=0..4,7) + \arg TIMER_DMACFG_DMATA_CH3CV: DMA transfer address is TIMER_CH3CV,TIMERx(x=0..4,7) + \arg TIMER_DMACFG_DMATA_CCHP: DMA transfer address is TIMER_CCHP,TIMERx(x=0,7) + \arg TIMER_DMACFG_DMATA_DMACFG: DMA transfer address is TIMER_DMACFG,TIMERx(x=0..4,7) + \arg TIMER_DMACFG_DMATA_DMATB: DMA transfer address is TIMER_DMATB,TIMERx(x=0..4,7) + \param[in] dma_lenth: + only one parameter can be selected which is shown as below: + \arg TIMER_DMACFG_DMATC_xTRANSFER(x=1..18): DMA transfer x time + \param[out] none + \retval none +*/ +void timer_dma_transfer_config(uint32_t timer_periph, uint32_t dma_baseaddr, uint32_t dma_lenth) +{ + TIMER_DMACFG(timer_periph) &= (~(uint32_t)(TIMER_DMACFG_DMATA | TIMER_DMACFG_DMATC)); + TIMER_DMACFG(timer_periph) |= (uint32_t)(dma_baseaddr | dma_lenth); +} + +/*! + \brief software generate events + \param[in] timer_periph: please refer to the following parameters + \param[in] event: the timer software event generation sources + one or more parameters can be selected which are shown as below: + \arg TIMER_EVENT_SRC_UPG: update event,TIMERx(x=0..13) + \arg TIMER_EVENT_SRC_CH0G: channel 0 capture or compare event generation,TIMERx(x=0..4,7..13) + \arg TIMER_EVENT_SRC_CH1G: channel 1 capture or compare event generation,TIMERx(x=0..4,7,8,11) + \arg TIMER_EVENT_SRC_CH2G: channel 2 capture or compare event generation,TIMERx(x=0..4,7) + \arg TIMER_EVENT_SRC_CH3G: channel 3 capture or compare event generation,TIMERx(x=0..4,7) + \arg TIMER_EVENT_SRC_CMTG: channel commutation event generation,TIMERx(x=0,7) + \arg TIMER_EVENT_SRC_TRGG: trigger event generation,TIMERx(x=0..4,7,8,11) + \arg TIMER_EVENT_SRC_BRKG: break event generation,TIMERx(x=0,7) + \param[out] none + \retval none +*/ +void timer_event_software_generate(uint32_t timer_periph, uint16_t event) +{ + TIMER_SWEVG(timer_periph) |= (uint32_t)event; +} + +/*! + \brief initialize TIMER break parameter struct with a default value + \param[in] breakpara: TIMER break parameter struct + \param[out] none + \retval none +*/ +void timer_break_struct_para_init(timer_break_parameter_struct* breakpara) +{ + /* initialize the break parameter struct member with the default value */ + breakpara->runoffstate = TIMER_ROS_STATE_DISABLE; + breakpara->ideloffstate = TIMER_IOS_STATE_DISABLE; + breakpara->deadtime = 0U; + breakpara->breakpolarity = TIMER_BREAK_POLARITY_LOW; + breakpara->outputautostate = TIMER_OUTAUTO_DISABLE; + breakpara->protectmode = TIMER_CCHP_PROT_OFF; + breakpara->breakstate = TIMER_BREAK_DISABLE; +} + +/*! + \brief configure TIMER break function + \param[in] timer_periph: TIMERx(x=0,7) + \param[in] breakpara: TIMER break parameter struct + runoffstate: TIMER_ROS_STATE_ENABLE,TIMER_ROS_STATE_DISABLE + ideloffstate: TIMER_IOS_STATE_ENABLE,TIMER_IOS_STATE_DISABLE + deadtime: 0~255 + breakpolarity: TIMER_BREAK_POLARITY_LOW,TIMER_BREAK_POLARITY_HIGH + outputautostate: TIMER_OUTAUTO_ENABLE,TIMER_OUTAUTO_DISABLE + protectmode: TIMER_CCHP_PROT_OFF,TIMER_CCHP_PROT_0,TIMER_CCHP_PROT_1,TIMER_CCHP_PROT_2 + breakstate: TIMER_BREAK_ENABLE,TIMER_BREAK_DISABLE + \param[out] none + \retval none +*/ +void timer_break_config(uint32_t timer_periph, timer_break_parameter_struct* breakpara) +{ + TIMER_CCHP(timer_periph) = (uint32_t)(((uint32_t)(breakpara->runoffstate))| + ((uint32_t)(breakpara->ideloffstate))| + ((uint32_t)(breakpara->deadtime))| + ((uint32_t)(breakpara->breakpolarity))| + ((uint32_t)(breakpara->outputautostate)) | + ((uint32_t)(breakpara->protectmode))| + ((uint32_t)(breakpara->breakstate))) ; +} + +/*! + \brief enable TIMER break function + \param[in] timer_periph: TIMERx(x=0,7) + \param[out] none + \retval none +*/ +void timer_break_enable(uint32_t timer_periph) +{ + TIMER_CCHP(timer_periph) |= (uint32_t)TIMER_CCHP_BRKEN; +} + +/*! + \brief disable TIMER break function + \param[in] timer_periph: TIMERx(x=0,7) + \param[out] none + \retval none +*/ +void timer_break_disable(uint32_t timer_periph) +{ + TIMER_CCHP(timer_periph) &= ~(uint32_t)TIMER_CCHP_BRKEN; +} + +/*! + \brief enable TIMER output automatic function + \param[in] timer_periph: TIMERx(x=0,7) + \param[out] none + \retval none +*/ +void timer_automatic_output_enable(uint32_t timer_periph) +{ + TIMER_CCHP(timer_periph) |= (uint32_t)TIMER_CCHP_OAEN; +} + +/*! + \brief disable TIMER output automatic function + \param[in] timer_periph: TIMERx(x=0,7) + \param[out] none + \retval none +*/ +void timer_automatic_output_disable(uint32_t timer_periph) +{ + TIMER_CCHP(timer_periph) &= ~(uint32_t)TIMER_CCHP_OAEN; +} + +/*! + \brief configure TIMER primary output function + \param[in] timer_periph: TIMERx(x=0,7) + \param[in] newvalue: ENABLE or DISABLE + \param[out] none + \retval none +*/ +void timer_primary_output_config(uint32_t timer_periph, ControlStatus newvalue) +{ + if(ENABLE == newvalue){ + TIMER_CCHP(timer_periph) |= (uint32_t)TIMER_CCHP_POEN; + }else{ + TIMER_CCHP(timer_periph) &= (~(uint32_t)TIMER_CCHP_POEN); + } +} + +/*! + \brief enable or disable channel capture/compare control shadow register + \param[in] timer_periph: TIMERx(x=0,7) + \param[in] newvalue: ENABLE or DISABLE + \param[out] none + \retval none +*/ +void timer_channel_control_shadow_config(uint32_t timer_periph, ControlStatus newvalue) +{ + if(ENABLE == newvalue){ + TIMER_CTL1(timer_periph) |= (uint32_t)TIMER_CTL1_CCSE; + }else{ + TIMER_CTL1(timer_periph) &= (~(uint32_t)TIMER_CTL1_CCSE); + } +} + +/*! + \brief configure TIMER channel control shadow register update control + \param[in] timer_periph: TIMERx(x=0,7) + \param[in] ccuctl: channel control shadow register update control + only one parameter can be selected which is shown as below: + \arg TIMER_UPDATECTL_CCU: the shadow registers update by when CMTG bit is set + \arg TIMER_UPDATECTL_CCUTRI: the shadow registers update by when CMTG bit is set or an rising edge of TRGI occurs + \param[out] none + \retval none +*/ +void timer_channel_control_shadow_update_config(uint32_t timer_periph, uint8_t ccuctl) +{ + if(TIMER_UPDATECTL_CCU == ccuctl){ + TIMER_CTL1(timer_periph) &= (~(uint32_t)TIMER_CTL1_CCUC); + }else if(TIMER_UPDATECTL_CCUTRI == ccuctl){ + TIMER_CTL1(timer_periph) |= (uint32_t)TIMER_CTL1_CCUC; + }else{ + /* illegal parameters */ + } +} + +/*! + \brief initialize TIMER channel output parameter struct with a default value + \param[in] ocpara: TIMER channel n output parameter struct + \param[out] none + \retval none +*/ +void timer_channel_output_struct_para_init(timer_oc_parameter_struct* ocpara) +{ + /* initialize the channel output parameter struct member with the default value */ + ocpara->outputstate = (uint16_t)TIMER_CCX_DISABLE; + ocpara->outputnstate = TIMER_CCXN_DISABLE; + ocpara->ocpolarity = TIMER_OC_POLARITY_HIGH; + ocpara->ocnpolarity = TIMER_OCN_POLARITY_HIGH; + ocpara->ocidlestate = TIMER_OC_IDLE_STATE_LOW; + ocpara->ocnidlestate = TIMER_OCN_IDLE_STATE_LOW; +} + +/*! + \brief configure TIMER channel output function + \param[in] timer_periph: please refer to the following parameters + \param[in] channel: + only one parameter can be selected which is shown as below: + \arg TIMER_CH_0: TIMER channel 0(TIMERx(x=0..4,7..13)) + \arg TIMER_CH_1: TIMER channel 1(TIMERx(x=0..4,7,8,11)) + \arg TIMER_CH_2: TIMER channel 2(TIMERx(x=0..4,7)) + \arg TIMER_CH_3: TIMER channel 3(TIMERx(x=0..4,7)) + \param[in] ocpara: TIMER channeln output parameter struct + outputstate: TIMER_CCX_ENABLE,TIMER_CCX_DISABLE + outputnstate: TIMER_CCXN_ENABLE,TIMER_CCXN_DISABLE + ocpolarity: TIMER_OC_POLARITY_HIGH,TIMER_OC_POLARITY_LOW + ocnpolarity: TIMER_OCN_POLARITY_HIGH,TIMER_OCN_POLARITY_LOW + ocidlestate: TIMER_OC_IDLE_STATE_LOW,TIMER_OC_IDLE_STATE_HIGH + ocnidlestate: TIMER_OCN_IDLE_STATE_LOW,TIMER_OCN_IDLE_STATE_HIGH + \param[out] none + \retval none +*/ +void timer_channel_output_config(uint32_t timer_periph, uint16_t channel, timer_oc_parameter_struct* ocpara) +{ + switch(channel){ + /* configure TIMER_CH_0 */ + case TIMER_CH_0: + /* reset the CH0EN bit */ + TIMER_CHCTL2(timer_periph) &= (~(uint32_t)TIMER_CHCTL2_CH0EN); + TIMER_CHCTL0(timer_periph) &= ~(uint32_t)TIMER_CHCTL0_CH0MS; + /* set the CH0EN bit */ + TIMER_CHCTL2(timer_periph) |= (uint32_t)ocpara->outputstate; + /* reset the CH0P bit */ + TIMER_CHCTL2(timer_periph) &= (~(uint32_t)TIMER_CHCTL2_CH0P); + /* set the CH0P bit */ + TIMER_CHCTL2(timer_periph) |= (uint32_t)ocpara->ocpolarity; + + if((TIMER0 == timer_periph) || (TIMER7 == timer_periph)){ + /* reset the CH0NEN bit */ + TIMER_CHCTL2(timer_periph) &= (~(uint32_t)TIMER_CHCTL2_CH0NEN); + /* set the CH0NEN bit */ + TIMER_CHCTL2(timer_periph) |= (uint32_t)ocpara->outputnstate; + /* reset the CH0NP bit */ + TIMER_CHCTL2(timer_periph) &= (~(uint32_t)TIMER_CHCTL2_CH0NP); + /* set the CH0NP bit */ + TIMER_CHCTL2(timer_periph) |= (uint32_t)ocpara->ocnpolarity; + /* reset the ISO0 bit */ + TIMER_CTL1(timer_periph) &= (~(uint32_t)TIMER_CTL1_ISO0); + /* set the ISO0 bit */ + TIMER_CTL1(timer_periph) |= (uint32_t)ocpara->ocidlestate; + /* reset the ISO0N bit */ + TIMER_CTL1(timer_periph) &= (~(uint32_t)TIMER_CTL1_ISO0N); + /* set the ISO0N bit */ + TIMER_CTL1(timer_periph) |= (uint32_t)ocpara->ocnidlestate; + } + break; + /* configure TIMER_CH_1 */ + case TIMER_CH_1: + /* reset the CH1EN bit */ + TIMER_CHCTL2(timer_periph) &= (~(uint32_t)TIMER_CHCTL2_CH1EN); + TIMER_CHCTL0(timer_periph) &= ~(uint32_t)TIMER_CHCTL0_CH1MS; + /* set the CH1EN bit */ + TIMER_CHCTL2(timer_periph) |= (uint32_t)((uint32_t)ocpara->outputstate << 4U); + /* reset the CH1P bit */ + TIMER_CHCTL2(timer_periph) &= (~(uint32_t)TIMER_CHCTL2_CH1P); + /* set the CH1P bit */ + TIMER_CHCTL2(timer_periph) |= (uint32_t)((uint32_t)(ocpara->ocpolarity) << 4U); + + if((TIMER0 == timer_periph) || (TIMER7 == timer_periph)){ + /* reset the CH1NEN bit */ + TIMER_CHCTL2(timer_periph) &= (~(uint32_t)TIMER_CHCTL2_CH1NEN); + /* set the CH1NEN bit */ + TIMER_CHCTL2(timer_periph) |= (uint32_t)((uint32_t)(ocpara->outputnstate) << 4U); + /* reset the CH1NP bit */ + TIMER_CHCTL2(timer_periph) &= (~(uint32_t)TIMER_CHCTL2_CH1NP); + /* set the CH1NP bit */ + TIMER_CHCTL2(timer_periph) |= (uint32_t)((uint32_t)(ocpara->ocnpolarity) << 4U); + /* reset the ISO1 bit */ + TIMER_CTL1(timer_periph) &= (~(uint32_t)TIMER_CTL1_ISO1); + /* set the ISO1 bit */ + TIMER_CTL1(timer_periph) |= (uint32_t)((uint32_t)(ocpara->ocidlestate) << 2U); + /* reset the ISO1N bit */ + TIMER_CTL1(timer_periph) &= (~(uint32_t)TIMER_CTL1_ISO1N); + /* set the ISO1N bit */ + TIMER_CTL1(timer_periph) |= (uint32_t)((uint32_t)(ocpara->ocnidlestate) << 2U); + } + break; + /* configure TIMER_CH_2 */ + case TIMER_CH_2: + /* reset the CH2EN bit */ + TIMER_CHCTL2(timer_periph) &= (~(uint32_t)TIMER_CHCTL2_CH2EN); + TIMER_CHCTL1(timer_periph) &= ~(uint32_t)TIMER_CHCTL1_CH2MS; + /* set the CH2EN bit */ + TIMER_CHCTL2(timer_periph) |= (uint32_t)((uint32_t)ocpara->outputstate << 8U); + /* reset the CH2P bit */ + TIMER_CHCTL2(timer_periph) &= (~(uint32_t)TIMER_CHCTL2_CH2P); + /* set the CH2P bit */ + TIMER_CHCTL2(timer_periph) |= (uint32_t)((uint32_t)(ocpara->ocpolarity) << 8U); + + if((TIMER0 == timer_periph) || (TIMER7 == timer_periph)){ + /* reset the CH2NEN bit */ + TIMER_CHCTL2(timer_periph) &= (~(uint32_t)TIMER_CHCTL2_CH2NEN); + /* set the CH2NEN bit */ + TIMER_CHCTL2(timer_periph) |= (uint32_t)((uint32_t)(ocpara->outputnstate) << 8U); + /* reset the CH2NP bit */ + TIMER_CHCTL2(timer_periph) &= (~(uint32_t)TIMER_CHCTL2_CH2NP); + /* set the CH2NP bit */ + TIMER_CHCTL2(timer_periph) |= (uint32_t)((uint32_t)(ocpara->ocnpolarity) << 8U); + /* reset the ISO2 bit */ + TIMER_CTL1(timer_periph) &= (~(uint32_t)TIMER_CTL1_ISO2); + /* set the ISO2 bit */ + TIMER_CTL1(timer_periph) |= (uint32_t)((uint32_t)(ocpara->ocidlestate) << 4U); + /* reset the ISO2N bit */ + TIMER_CTL1(timer_periph) &= (~(uint32_t)TIMER_CTL1_ISO2N); + /* set the ISO2N bit */ + TIMER_CTL1(timer_periph) |= (uint32_t)((uint32_t)(ocpara->ocnidlestate) << 4U); + } + break; + /* configure TIMER_CH_3 */ + case TIMER_CH_3: + /* reset the CH3EN bit */ + TIMER_CHCTL2(timer_periph) &=(~(uint32_t)TIMER_CHCTL2_CH3EN); + TIMER_CHCTL1(timer_periph) &= ~(uint32_t)TIMER_CHCTL1_CH3MS; + /* set the CH3EN bit */ + TIMER_CHCTL2(timer_periph) |= (uint32_t)((uint32_t)ocpara->outputstate << 12U); + /* reset the CH3P bit */ + TIMER_CHCTL2(timer_periph) &= (~(uint32_t)TIMER_CHCTL2_CH3P); + /* set the CH3P bit */ + TIMER_CHCTL2(timer_periph) |= (uint32_t)((uint32_t)(ocpara->ocpolarity) << 12U); + + if((TIMER0 == timer_periph) || (TIMER7 == timer_periph)){ + /* reset the ISO3 bit */ + TIMER_CTL1(timer_periph) &= (~(uint32_t)TIMER_CTL1_ISO3); + /* set the ISO3 bit */ + TIMER_CTL1(timer_periph) |= (uint32_t)((uint32_t)(ocpara->ocidlestate) << 6U); + } + break; + default: + break; + } +} + +/*! + \brief configure TIMER channel output compare mode + \param[in] timer_periph: please refer to the following parameters + \param[in] channel: + only one parameter can be selected which is shown as below: + \arg TIMER_CH_0: TIMER channel0(TIMERx(x=0..4,7..13)) + \arg TIMER_CH_1: TIMER channel1(TIMERx(x=0..4,7,8,11)) + \arg TIMER_CH_2: TIMER channel2(TIMERx(x=0..4,7)) + \arg TIMER_CH_3: TIMER channel3(TIMERx(x=0..4,7)) + \param[in] ocmode: channel output compare mode + only one parameter can be selected which is shown as below: + \arg TIMER_OC_MODE_TIMING: timing mode + \arg TIMER_OC_MODE_ACTIVE: active mode + \arg TIMER_OC_MODE_INACTIVE: inactive mode + \arg TIMER_OC_MODE_TOGGLE: toggle mode + \arg TIMER_OC_MODE_LOW: force low mode + \arg TIMER_OC_MODE_HIGH: force high mode + \arg TIMER_OC_MODE_PWM0: PWM0 mode + \arg TIMER_OC_MODE_PWM1: PWM1 mode + \param[out] none + \retval none +*/ +void timer_channel_output_mode_config(uint32_t timer_periph, uint16_t channel, uint16_t ocmode) +{ + switch(channel){ + /* configure TIMER_CH_0 */ + case TIMER_CH_0: + TIMER_CHCTL0(timer_periph) &= (~(uint32_t)TIMER_CHCTL0_CH0COMCTL); + TIMER_CHCTL0(timer_periph) |= (uint32_t)ocmode; + break; + /* configure TIMER_CH_1 */ + case TIMER_CH_1: + TIMER_CHCTL0(timer_periph) &= (~(uint32_t)TIMER_CHCTL0_CH1COMCTL); + TIMER_CHCTL0(timer_periph) |= (uint32_t)((uint32_t)(ocmode) << 8U); + break; + /* configure TIMER_CH_2 */ + case TIMER_CH_2: + TIMER_CHCTL1(timer_periph) &= (~(uint32_t)TIMER_CHCTL1_CH2COMCTL); + TIMER_CHCTL1(timer_periph) |= (uint32_t)ocmode; + break; + /* configure TIMER_CH_3 */ + case TIMER_CH_3: + TIMER_CHCTL1(timer_periph) &= (~(uint32_t)TIMER_CHCTL1_CH3COMCTL); + TIMER_CHCTL1(timer_periph) |= (uint32_t)((uint32_t)(ocmode) << 8U); + break; + default: + break; + } +} + +/*! + \brief configure TIMER channel output pulse value + \param[in] timer_periph: please refer to the following parameters + \param[in] channel: + only one parameter can be selected which is shown as below: + \arg TIMER_CH_0: TIMER channel0(TIMERx(x=0..4,7..13)) + \arg TIMER_CH_1: TIMER channel1(TIMERx(x=0..4,7,8,11)) + \arg TIMER_CH_2: TIMER channel2(TIMERx(x=0..4,7)) + \arg TIMER_CH_3: TIMER channel3(TIMERx(x=0..4,7)) + \param[in] pulse: channel output pulse value,0~65535 + \param[out] none + \retval none +*/ +void timer_channel_output_pulse_value_config(uint32_t timer_periph, uint16_t channel, uint32_t pulse) +{ + switch(channel){ + /* configure TIMER_CH_0 */ + case TIMER_CH_0: + TIMER_CH0CV(timer_periph) = (uint32_t)pulse; + break; + /* configure TIMER_CH_1 */ + case TIMER_CH_1: + TIMER_CH1CV(timer_periph) = (uint32_t)pulse; + break; + /* configure TIMER_CH_2 */ + case TIMER_CH_2: + TIMER_CH2CV(timer_periph) = (uint32_t)pulse; + break; + /* configure TIMER_CH_3 */ + case TIMER_CH_3: + TIMER_CH3CV(timer_periph) = (uint32_t)pulse; + break; + default: + break; + } +} + +/*! + \brief configure TIMER channel output shadow function + \param[in] timer_periph: please refer to the following parameters + \param[in] channel: + only one parameter can be selected which is shown as below: + \arg TIMER_CH_0: TIMER channel0(TIMERx(x=0..4,7..13)) + \arg TIMER_CH_1: TIMER channel1(TIMERx(x=0..4,7,8,11)) + \arg TIMER_CH_2: TIMER channel2(TIMERx(x=0..4,7)) + \arg TIMER_CH_3: TIMER channel3(TIMERx(x=0..4,7)) + \param[in] ocshadow: channel output shadow state + only one parameter can be selected which is shown as below: + \arg TIMER_OC_SHADOW_ENABLE: channel output shadow state enable + \arg TIMER_OC_SHADOW_DISABLE: channel output shadow state disable + \param[out] none + \retval none +*/ +void timer_channel_output_shadow_config(uint32_t timer_periph, uint16_t channel, uint16_t ocshadow) +{ + switch(channel){ + /* configure TIMER_CH_0 */ + case TIMER_CH_0: + TIMER_CHCTL0(timer_periph) &= (~(uint32_t)TIMER_CHCTL0_CH0COMSEN); + TIMER_CHCTL0(timer_periph) |= (uint32_t)ocshadow; + break; + /* configure TIMER_CH_1 */ + case TIMER_CH_1: + TIMER_CHCTL0(timer_periph) &= (~(uint32_t)TIMER_CHCTL0_CH1COMSEN); + TIMER_CHCTL0(timer_periph) |= (uint32_t)((uint32_t)(ocshadow) << 8U); + break; + /* configure TIMER_CH_2 */ + case TIMER_CH_2: + TIMER_CHCTL1(timer_periph) &= (~(uint32_t)TIMER_CHCTL1_CH2COMSEN); + TIMER_CHCTL1(timer_periph) |= (uint32_t)ocshadow; + break; + /* configure TIMER_CH_3 */ + case TIMER_CH_3: + TIMER_CHCTL1(timer_periph) &= (~(uint32_t)TIMER_CHCTL1_CH3COMSEN); + TIMER_CHCTL1(timer_periph) |= (uint32_t)((uint32_t)(ocshadow) << 8U); + break; + default: + break; + } +} + +/*! + \brief configure TIMER channel output fast function + \param[in] timer_periph: please refer to the following parameters + \param[in] channel: + only one parameter can be selected which is shown as below: + \arg TIMER_CH_0: TIMER channel0(TIMERx(x=0..4,7..13)) + \arg TIMER_CH_1: TIMER channel1(TIMERx(x=0..4,7,8,11)) + \arg TIMER_CH_2: TIMER channel2(TIMERx(x=0..4,7)) + \arg TIMER_CH_3: TIMER channel3(TIMERx(x=0..4,7)) + \param[in] ocfast: channel output fast function + only one parameter can be selected which is shown as below: + \arg TIMER_OC_FAST_ENABLE: channel output fast function enable + \arg TIMER_OC_FAST_DISABLE: channel output fast function disable + \param[out] none + \retval none +*/ +void timer_channel_output_fast_config(uint32_t timer_periph, uint16_t channel, uint16_t ocfast) +{ + switch(channel){ + /* configure TIMER_CH_0 */ + case TIMER_CH_0: + TIMER_CHCTL0(timer_periph) &= (~(uint32_t)TIMER_CHCTL0_CH0COMFEN); + TIMER_CHCTL0(timer_periph) |= (uint32_t)ocfast; + break; + /* configure TIMER_CH_1 */ + case TIMER_CH_1: + TIMER_CHCTL0(timer_periph) &= (~(uint32_t)TIMER_CHCTL0_CH1COMFEN); + TIMER_CHCTL0(timer_periph) |= (uint32_t)((uint32_t)ocfast << 8U); + break; + /* configure TIMER_CH_2 */ + case TIMER_CH_2: + TIMER_CHCTL1(timer_periph) &= (~(uint32_t)TIMER_CHCTL1_CH2COMFEN); + TIMER_CHCTL1(timer_periph) |= (uint32_t)ocfast; + break; + /* configure TIMER_CH_3 */ + case TIMER_CH_3: + TIMER_CHCTL1(timer_periph) &= (~(uint32_t)TIMER_CHCTL1_CH3COMFEN); + TIMER_CHCTL1(timer_periph) |= (uint32_t)((uint32_t)ocfast << 8U); + break; + default: + break; + } +} + +/*! + \brief configure TIMER channel output clear function + \param[in] timer_periph: TIMERx(x=0..4,7) + \param[in] channel: + only one parameter can be selected which is shown as below: + \arg TIMER_CH_0: TIMER channel0 + \arg TIMER_CH_1: TIMER channel1 + \arg TIMER_CH_2: TIMER channel2 + \arg TIMER_CH_3: TIMER channel3 + \param[in] occlear: channel output clear function + only one parameter can be selected which is shown as below: + \arg TIMER_OC_CLEAR_ENABLE: channel output clear function enable + \arg TIMER_OC_CLEAR_DISABLE: channel output clear function disable + \param[out] none + \retval none +*/ +void timer_channel_output_clear_config(uint32_t timer_periph, uint16_t channel, uint16_t occlear) +{ + switch(channel){ + /* configure TIMER_CH_0 */ + case TIMER_CH_0: + TIMER_CHCTL0(timer_periph) &= (~(uint32_t)TIMER_CHCTL0_CH0COMCEN); + TIMER_CHCTL0(timer_periph) |= (uint32_t)occlear; + break; + /* configure TIMER_CH_1 */ + case TIMER_CH_1: + TIMER_CHCTL0(timer_periph) &= (~(uint32_t)TIMER_CHCTL0_CH1COMCEN); + TIMER_CHCTL0(timer_periph) |= (uint32_t)((uint32_t)occlear << 8U); + break; + /* configure TIMER_CH_2 */ + case TIMER_CH_2: + TIMER_CHCTL1(timer_periph) &= (~(uint32_t)TIMER_CHCTL1_CH2COMCEN); + TIMER_CHCTL1(timer_periph) |= (uint32_t)occlear; + break; + /* configure TIMER_CH_3 */ + case TIMER_CH_3: + TIMER_CHCTL1(timer_periph) &= (~(uint32_t)TIMER_CHCTL1_CH3COMCEN); + TIMER_CHCTL1(timer_periph) |= (uint32_t)((uint32_t)occlear << 8U); + break; + default: + break; + } +} + +/*! + \brief configure TIMER channel output polarity + \param[in] timer_periph: please refer to the following parameters + \param[in] channel: + only one parameter can be selected which is shown as below: + \arg TIMER_CH_0: TIMER channel0(TIMERx(x=0..4,7..13)) + \arg TIMER_CH_1: TIMER channel1(TIMERx(x=0..4,7,8,11)) + \arg TIMER_CH_2: TIMER channel2(TIMERx(x=0..4,7)) + \arg TIMER_CH_3: TIMER channel3(TIMERx(x=0..4,7)) + \param[in] ocpolarity: channel output polarity + only one parameter can be selected which is shown as below: + \arg TIMER_OC_POLARITY_HIGH: channel output polarity is high + \arg TIMER_OC_POLARITY_LOW: channel output polarity is low + \param[out] none + \retval none +*/ +void timer_channel_output_polarity_config(uint32_t timer_periph, uint16_t channel, uint16_t ocpolarity) +{ + switch(channel){ + /* configure TIMER_CH_0 */ + case TIMER_CH_0: + TIMER_CHCTL2(timer_periph) &= (~(uint32_t)TIMER_CHCTL2_CH0P); + TIMER_CHCTL2(timer_periph) |= (uint32_t)ocpolarity; + break; + /* configure TIMER_CH_1 */ + case TIMER_CH_1: + TIMER_CHCTL2(timer_periph) &= (~(uint32_t)TIMER_CHCTL2_CH1P); + TIMER_CHCTL2(timer_periph) |= (uint32_t)((uint32_t)ocpolarity << 4U); + break; + /* configure TIMER_CH_2 */ + case TIMER_CH_2: + TIMER_CHCTL2(timer_periph) &= (~(uint32_t)TIMER_CHCTL2_CH2P); + TIMER_CHCTL2(timer_periph) |= (uint32_t)((uint32_t)ocpolarity << 8U); + break; + /* configure TIMER_CH_3 */ + case TIMER_CH_3: + TIMER_CHCTL2(timer_periph) &= (~(uint32_t)TIMER_CHCTL2_CH3P); + TIMER_CHCTL2(timer_periph) |= (uint32_t)((uint32_t)ocpolarity << 12U); + break; + default: + break; + } +} + +/*! + \brief configure TIMER channel complementary output polarity + \param[in] timer_periph: please refer to the following parameters + \param[in] channel: + only one parameter can be selected which is shown as below: + \arg TIMER_CH_0: TIMER channel0(TIMERx(x=0,7..13)) + \arg TIMER_CH_1: TIMER channel1(TIMERx(x=0,7,8,11)) + \arg TIMER_CH_2: TIMER channel2(TIMERx(x=0,7)) + \param[in] ocnpolarity: channel complementary output polarity + only one parameter can be selected which is shown as below: + \arg TIMER_OCN_POLARITY_HIGH: channel complementary output polarity is high + \arg TIMER_OCN_POLARITY_LOW: channel complementary output polarity is low + \param[out] none + \retval none +*/ +void timer_channel_complementary_output_polarity_config(uint32_t timer_periph, uint16_t channel, uint16_t ocnpolarity) +{ + switch(channel){ + /* configure TIMER_CH_0 */ + case TIMER_CH_0: + TIMER_CHCTL2(timer_periph) &= (~(uint32_t)TIMER_CHCTL2_CH0NP); + TIMER_CHCTL2(timer_periph) |= (uint32_t)ocnpolarity; + break; + /* configure TIMER_CH_1 */ + case TIMER_CH_1: + TIMER_CHCTL2(timer_periph) &= (~(uint32_t)TIMER_CHCTL2_CH1NP); + TIMER_CHCTL2(timer_periph) |= (uint32_t)((uint32_t)ocnpolarity << 4U); + break; + /* configure TIMER_CH_2 */ + case TIMER_CH_2: + TIMER_CHCTL2(timer_periph) &= (~(uint32_t)TIMER_CHCTL2_CH2NP); + TIMER_CHCTL2(timer_periph) |= (uint32_t)((uint32_t)ocnpolarity << 8U); + break; + default: + break; + } +} + +/*! + \brief configure TIMER channel enable state + \param[in] timer_periph: please refer to the following parameters + \param[in] channel: + only one parameter can be selected which is shown as below: + \arg TIMER_CH_0: TIMER channel0(TIMERx(x=0..4,7..13)) + \arg TIMER_CH_1: TIMER channel1(TIMERx(x=0..4,7,8,11)) + \arg TIMER_CH_2: TIMER channel2(TIMERx(x=0..4,7)) + \arg TIMER_CH_3: TIMER channel3(TIMERx(x=0..4,7)) + \param[in] state: TIMER channel enable state + only one parameter can be selected which is shown as below: + \arg TIMER_CCX_ENABLE: channel enable + \arg TIMER_CCX_DISABLE: channel disable + \param[out] none + \retval none +*/ +void timer_channel_output_state_config(uint32_t timer_periph, uint16_t channel, uint32_t state) +{ + switch(channel){ + /* configure TIMER_CH_0 */ + case TIMER_CH_0: + TIMER_CHCTL2(timer_periph) &= (~(uint32_t)TIMER_CHCTL2_CH0EN); + TIMER_CHCTL2(timer_periph) |= (uint32_t)state; + break; + /* configure TIMER_CH_1 */ + case TIMER_CH_1: + TIMER_CHCTL2(timer_periph) &= (~(uint32_t)TIMER_CHCTL2_CH1EN); + TIMER_CHCTL2(timer_periph) |= (uint32_t)((uint32_t)state << 4U); + break; + /* configure TIMER_CH_2 */ + case TIMER_CH_2: + TIMER_CHCTL2(timer_periph) &= (~(uint32_t)TIMER_CHCTL2_CH2EN); + TIMER_CHCTL2(timer_periph) |= (uint32_t)((uint32_t)state << 8U); + break; + /* configure TIMER_CH_3 */ + case TIMER_CH_3: + TIMER_CHCTL2(timer_periph) &= (~(uint32_t)TIMER_CHCTL2_CH3EN); + TIMER_CHCTL2(timer_periph) |= (uint32_t)((uint32_t)state << 12U); + break; + default: + break; + } +} + +/*! + \brief configure TIMER channel complementary output enable state + \param[in] timer_periph: please refer to the following parameters + \param[in] channel: + only one parameter can be selected which is shown as below: + \arg TIMER_CH_0: TIMER channel0(TIMERx(x=0,7)) + \arg TIMER_CH_1: TIMER channel1(TIMERx(x=0,7)) + \arg TIMER_CH_2: TIMER channel2(TIMERx(x=0,7)) + \param[in] ocnstate: TIMER channel complementary output enable state + only one parameter can be selected which is shown as below: + \arg TIMER_CCXN_ENABLE: channel complementary enable + \arg TIMER_CCXN_DISABLE: channel complementary disable + \param[out] none + \retval none +*/ +void timer_channel_complementary_output_state_config(uint32_t timer_periph, uint16_t channel, uint16_t ocnstate) +{ + switch(channel){ + /* configure TIMER_CH_0 */ + case TIMER_CH_0: + TIMER_CHCTL2(timer_periph) &= (~(uint32_t)TIMER_CHCTL2_CH0NEN); + TIMER_CHCTL2(timer_periph) |= (uint32_t)ocnstate; + break; + /* configure TIMER_CH_1 */ + case TIMER_CH_1: + TIMER_CHCTL2(timer_periph) &= (~(uint32_t)TIMER_CHCTL2_CH1NEN); + TIMER_CHCTL2(timer_periph) |= (uint32_t)((uint32_t)ocnstate << 4U); + break; + /* configure TIMER_CH_2 */ + case TIMER_CH_2: + TIMER_CHCTL2(timer_periph) &= (~(uint32_t)TIMER_CHCTL2_CH2NEN); + TIMER_CHCTL2(timer_periph) |= (uint32_t)((uint32_t)ocnstate << 8U); + break; + default: + break; + } +} + +/*! + \brief initialize TIMER channel input parameter struct with a default value + \param[in] icpara: TIMER channel intput parameter struct + \param[out] none + \retval none +*/ +void timer_channel_input_struct_para_init(timer_ic_parameter_struct* icpara) +{ + /* initialize the channel input parameter struct member with the default value */ + icpara->icpolarity = TIMER_IC_POLARITY_RISING; + icpara->icselection = TIMER_IC_SELECTION_DIRECTTI; + icpara->icprescaler = TIMER_IC_PSC_DIV1; + icpara->icfilter = 0U; +} + +/*! + \brief configure TIMER input capture parameter + \param[in] timer_periph: please refer to the following parameters + \param[in] channel: + only one parameter can be selected which is shown as below: + \arg TIMER_CH_0: TIMER channel0(TIMERx(x=0..4,7..13)) + \arg TIMER_CH_1: TIMER channel1(TIMERx(x=0..4,7,8,11)) + \arg TIMER_CH_2: TIMER channel2(TIMERx(x=0..4,7)) + \arg TIMER_CH_3: TIMER channel3(TIMERx(x=0..4,7)) + \param[in] icpara: TIMER channel intput parameter struct + icpolarity: TIMER_IC_POLARITY_RISING,TIMER_IC_POLARITY_FALLING + icselection: TIMER_IC_SELECTION_DIRECTTI,TIMER_IC_SELECTION_INDIRECTTI,TIMER_IC_SELECTION_ITS + icprescaler: TIMER_IC_PSC_DIV1,TIMER_IC_PSC_DIV2,TIMER_IC_PSC_DIV4,TIMER_IC_PSC_DIV8 + icfilter: 0~15 + \param[out] none + \retval none +*/ +void timer_input_capture_config(uint32_t timer_periph,uint16_t channel, timer_ic_parameter_struct* icpara) +{ + switch(channel){ + /* configure TIMER_CH_0 */ + case TIMER_CH_0: + /* reset the CH0EN bit */ + TIMER_CHCTL2(timer_periph) &= (~(uint32_t)TIMER_CHCTL2_CH0EN); + + /* reset the CH0P and CH0NP bits */ + TIMER_CHCTL2(timer_periph) &= (~(uint32_t)(TIMER_CHCTL2_CH0P | TIMER_CHCTL2_CH0NP)); + TIMER_CHCTL2(timer_periph) |= (uint32_t)(icpara->icpolarity); + /* reset the CH0MS bit */ + TIMER_CHCTL0(timer_periph) &= (~(uint32_t)TIMER_CHCTL0_CH0MS); + TIMER_CHCTL0(timer_periph) |= (uint32_t)(icpara->icselection); + /* reset the CH0CAPFLT bit */ + TIMER_CHCTL0(timer_periph) &= (~(uint32_t)TIMER_CHCTL0_CH0CAPFLT); + TIMER_CHCTL0(timer_periph) |= (uint32_t)((uint32_t)(icpara->icfilter) << 4U); + + /* set the CH0EN bit */ + TIMER_CHCTL2(timer_periph) |= (uint32_t)TIMER_CHCTL2_CH0EN; + break; + + /* configure TIMER_CH_1 */ + case TIMER_CH_1: + /* reset the CH1EN bit */ + TIMER_CHCTL2(timer_periph) &= (~(uint32_t)TIMER_CHCTL2_CH1EN); + + /* reset the CH1P and CH1NP bits */ + TIMER_CHCTL2(timer_periph) &= (~(uint32_t)(TIMER_CHCTL2_CH1P | TIMER_CHCTL2_CH1NP)); + TIMER_CHCTL2(timer_periph) |= (uint32_t)((uint32_t)(icpara->icpolarity) << 4U); + /* reset the CH1MS bit */ + TIMER_CHCTL0(timer_periph) &= (~(uint32_t)TIMER_CHCTL0_CH1MS); + TIMER_CHCTL0(timer_periph) |= (uint32_t)((uint32_t)(icpara->icselection) << 8U); + /* reset the CH1CAPFLT bit */ + TIMER_CHCTL0(timer_periph) &= (~(uint32_t)TIMER_CHCTL0_CH1CAPFLT); + TIMER_CHCTL0(timer_periph) |= (uint32_t)((uint32_t)(icpara->icfilter) << 12U); + + /* set the CH1EN bit */ + TIMER_CHCTL2(timer_periph) |= (uint32_t)TIMER_CHCTL2_CH1EN; + break; + /* configure TIMER_CH_2 */ + case TIMER_CH_2: + /* reset the CH2EN bit */ + TIMER_CHCTL2(timer_periph) &= (~(uint32_t)TIMER_CHCTL2_CH2EN); + + /* reset the CH2P and CH2NP bits */ + TIMER_CHCTL2(timer_periph) &= (~(uint32_t)(TIMER_CHCTL2_CH2P|TIMER_CHCTL2_CH2NP)); + TIMER_CHCTL2(timer_periph) |= (uint32_t)((uint32_t)(icpara->icpolarity) << 8U); + + /* reset the CH2MS bit */ + TIMER_CHCTL1(timer_periph) &= (~(uint32_t)TIMER_CHCTL1_CH2MS); + TIMER_CHCTL1(timer_periph) |= (uint32_t)((uint32_t)(icpara->icselection)); + + /* reset the CH2CAPFLT bit */ + TIMER_CHCTL1(timer_periph) &= (~(uint32_t)TIMER_CHCTL1_CH2CAPFLT); + TIMER_CHCTL1(timer_periph) |= (uint32_t)((uint32_t)(icpara->icfilter) << 4U); + + /* set the CH2EN bit */ + TIMER_CHCTL2(timer_periph) |= (uint32_t)TIMER_CHCTL2_CH2EN; + break; + /* configure TIMER_CH_3 */ + case TIMER_CH_3: + /* reset the CH3EN bit */ + TIMER_CHCTL2(timer_periph) &= (~(uint32_t)TIMER_CHCTL2_CH3EN); + + /* reset the CH3P bits */ + TIMER_CHCTL2(timer_periph) &= (~(uint32_t)(TIMER_CHCTL2_CH3P)); + TIMER_CHCTL2(timer_periph) |= (uint32_t)((uint32_t)(icpara->icpolarity) << 12U); + + /* reset the CH3MS bit */ + TIMER_CHCTL1(timer_periph) &= (~(uint32_t)TIMER_CHCTL1_CH3MS); + TIMER_CHCTL1(timer_periph) |= (uint32_t)((uint32_t)(icpara->icselection) << 8U); + + /* reset the CH3CAPFLT bit */ + TIMER_CHCTL1(timer_periph) &= (~(uint32_t)TIMER_CHCTL1_CH3CAPFLT); + TIMER_CHCTL1(timer_periph) |= (uint32_t)((uint32_t)(icpara->icfilter) << 12U); + + /* set the CH3EN bit */ + TIMER_CHCTL2(timer_periph) |= (uint32_t)TIMER_CHCTL2_CH3EN; + break; + default: + break; + } + /* configure TIMER channel input capture prescaler value */ + timer_channel_input_capture_prescaler_config(timer_periph, channel, (uint16_t)(icpara->icprescaler)); +} + +/*! + \brief configure TIMER channel input capture prescaler value + \param[in] timer_periph: please refer to the following parameters + \param[in] channel: + only one parameter can be selected which is shown as below: + \arg TIMER_CH_0: TIMER channel0(TIMERx(x=0..4,7..13)) + \arg TIMER_CH_1: TIMER channel1(TIMERx(x=0..4,7,8,11)) + \arg TIMER_CH_2: TIMER channel2(TIMERx(x=0..4,7)) + \arg TIMER_CH_3: TIMER channel3(TIMERx(x=0..4,7)) + \param[in] prescaler: channel input capture prescaler value + only one parameter can be selected which is shown as below: + \arg TIMER_IC_PSC_DIV1: no prescaler + \arg TIMER_IC_PSC_DIV2: divided by 2 + \arg TIMER_IC_PSC_DIV4: divided by 4 + \arg TIMER_IC_PSC_DIV8: divided by 8 + \param[out] none + \retval none +*/ +void timer_channel_input_capture_prescaler_config(uint32_t timer_periph, uint16_t channel, uint16_t prescaler) +{ + switch(channel){ + /* configure TIMER_CH_0 */ + case TIMER_CH_0: + TIMER_CHCTL0(timer_periph) &= (~(uint32_t)TIMER_CHCTL0_CH0CAPPSC); + TIMER_CHCTL0(timer_periph) |= (uint32_t)prescaler; + break; + /* configure TIMER_CH_1 */ + case TIMER_CH_1: + TIMER_CHCTL0(timer_periph) &= (~(uint32_t)TIMER_CHCTL0_CH1CAPPSC); + TIMER_CHCTL0(timer_periph) |= ((uint32_t)prescaler << 8U); + break; + /* configure TIMER_CH_2 */ + case TIMER_CH_2: + TIMER_CHCTL1(timer_periph) &= (~(uint32_t)TIMER_CHCTL1_CH2CAPPSC); + TIMER_CHCTL1(timer_periph) |= (uint32_t)prescaler; + break; + /* configure TIMER_CH_3 */ + case TIMER_CH_3: + TIMER_CHCTL1(timer_periph) &= (~(uint32_t)TIMER_CHCTL1_CH3CAPPSC); + TIMER_CHCTL1(timer_periph) |= ((uint32_t)prescaler << 8U); + break; + default: + break; + } +} + +/*! + \brief read TIMER channel capture compare register value + \param[in] timer_periph: please refer to the following parameters + \param[in] channel: + only one parameter can be selected which is shown as below: + \arg TIMER_CH_0: TIMER channel0(TIMERx(x=0..4,7..13)) + \arg TIMER_CH_1: TIMER channel1(TIMERx(x=0..4,7,8,11)) + \arg TIMER_CH_2: TIMER channel2(TIMERx(x=0..4,7)) + \arg TIMER_CH_3: TIMER channel3(TIMERx(x=0..4,7)) + \param[out] none + \retval channel capture compare register value +*/ +uint32_t timer_channel_capture_value_register_read(uint32_t timer_periph, uint16_t channel) +{ + uint32_t count_value = 0U; + + switch(channel){ + /* read TIMER channel 0 capture compare register value */ + case TIMER_CH_0: + count_value = TIMER_CH0CV(timer_periph); + break; + /* read TIMER channel 1 capture compare register value */ + case TIMER_CH_1: + count_value = TIMER_CH1CV(timer_periph); + break; + /* read TIMER channel 2 capture compare register value */ + case TIMER_CH_2: + count_value = TIMER_CH2CV(timer_periph); + break; + /* read TIMER channel 3 capture compare register value */ + case TIMER_CH_3: + count_value = TIMER_CH3CV(timer_periph); + break; + default: + break; + } + return (count_value); +} + +/*! + \brief configure TIMER input pwm capture function + \param[in] timer_periph: TIMERx(x=0..4,7,8,11) + \param[in] channel: + only one parameter can be selected which is shown as below: + \arg TIMER_CH_0: TIMER channel0 + \arg TIMER_CH_1: TIMER channel1 + \param[in] icpwm:TIMER channel intput pwm parameter struct + icpolarity: TIMER_IC_POLARITY_RISING,TIMER_IC_POLARITY_FALLING + icselection: TIMER_IC_SELECTION_DIRECTTI,TIMER_IC_SELECTION_INDIRECTTI + icprescaler: TIMER_IC_PSC_DIV1,TIMER_IC_PSC_DIV2,TIMER_IC_PSC_DIV4,TIMER_IC_PSC_DIV8 + icfilter: 0~15 + \param[out] none + \retval none +*/ +void timer_input_pwm_capture_config(uint32_t timer_periph, uint16_t channel, timer_ic_parameter_struct* icpwm) +{ + uint16_t icpolarity = 0x0U; + uint16_t icselection = 0x0U; + + /* Set channel input polarity */ + if(TIMER_IC_POLARITY_RISING == icpwm->icpolarity){ + icpolarity = TIMER_IC_POLARITY_FALLING; + }else{ + icpolarity = TIMER_IC_POLARITY_RISING; + } + + /* Set channel input mode selection */ + if(TIMER_IC_SELECTION_DIRECTTI == icpwm->icselection){ + icselection = TIMER_IC_SELECTION_INDIRECTTI; + }else{ + icselection = TIMER_IC_SELECTION_DIRECTTI; + } + + if(TIMER_CH_0 == channel){ + /* reset the CH0EN bit */ + TIMER_CHCTL2(timer_periph) &= (~(uint32_t)TIMER_CHCTL2_CH0EN); + /* reset the CH0P and CH0NP bits */ + TIMER_CHCTL2(timer_periph) &= (~(uint32_t)(TIMER_CHCTL2_CH0P|TIMER_CHCTL2_CH0NP)); + /* set the CH0P and CH0NP bits */ + TIMER_CHCTL2(timer_periph) |= (uint32_t)(icpwm->icpolarity); + /* reset the CH0MS bit */ + TIMER_CHCTL0(timer_periph) &= (~(uint32_t)TIMER_CHCTL0_CH0MS); + /* set the CH0MS bit */ + TIMER_CHCTL0(timer_periph) |= (uint32_t)(icpwm->icselection); + /* reset the CH0CAPFLT bit */ + TIMER_CHCTL0(timer_periph) &= (~(uint32_t)TIMER_CHCTL0_CH0CAPFLT); + /* set the CH0CAPFLT bit */ + TIMER_CHCTL0(timer_periph) |= ((uint32_t)(icpwm->icfilter) << 4U); + /* set the CH0EN bit */ + TIMER_CHCTL2(timer_periph) |= (uint32_t)TIMER_CHCTL2_CH0EN; + /* configure TIMER channel input capture prescaler value */ + timer_channel_input_capture_prescaler_config(timer_periph,TIMER_CH_0,(uint16_t)(icpwm->icprescaler)); + + /* reset the CH1EN bit */ + TIMER_CHCTL2(timer_periph) &= (~(uint32_t)TIMER_CHCTL2_CH1EN); + /* reset the CH1P and CH1NP bits */ + TIMER_CHCTL2(timer_periph) &= (~(uint32_t)(TIMER_CHCTL2_CH1P|TIMER_CHCTL2_CH1NP)); + /* set the CH1P and CH1NP bits */ + TIMER_CHCTL2(timer_periph) |= (uint32_t)((uint32_t)icpolarity << 4U); + /* reset the CH1MS bit */ + TIMER_CHCTL0(timer_periph) &= (~(uint32_t)TIMER_CHCTL0_CH1MS); + /* set the CH1MS bit */ + TIMER_CHCTL0(timer_periph) |= (uint32_t)((uint32_t)icselection << 8U); + /* reset the CH1CAPFLT bit */ + TIMER_CHCTL0(timer_periph) &= (~(uint32_t)TIMER_CHCTL0_CH1CAPFLT); + /* set the CH1CAPFLT bit */ + TIMER_CHCTL0(timer_periph) |= (uint32_t)((uint32_t)(icpwm->icfilter) << 12U); + /* set the CH1EN bit */ + TIMER_CHCTL2(timer_periph) |= (uint32_t)TIMER_CHCTL2_CH1EN; + /* configure TIMER channel input capture prescaler value */ + timer_channel_input_capture_prescaler_config(timer_periph,TIMER_CH_1,(uint16_t)(icpwm->icprescaler)); + }else{ + /* reset the CH1EN bit */ + TIMER_CHCTL2(timer_periph) &= (~(uint32_t)TIMER_CHCTL2_CH1EN); + /* reset the CH1P and CH1NP bits */ + TIMER_CHCTL2(timer_periph) &= (~(uint32_t)(TIMER_CHCTL2_CH1P|TIMER_CHCTL2_CH1NP)); + /* set the CH1P and CH1NP bits */ + TIMER_CHCTL2(timer_periph) |= (uint32_t)((uint32_t)(icpwm->icpolarity) << 4U); + /* reset the CH1MS bit */ + TIMER_CHCTL0(timer_periph) &= (~(uint32_t)TIMER_CHCTL0_CH1MS); + /* set the CH1MS bit */ + TIMER_CHCTL0(timer_periph) |= (uint32_t)((uint32_t)(icpwm->icselection) << 8U); + /* reset the CH1CAPFLT bit */ + TIMER_CHCTL0(timer_periph) &= (~(uint32_t)TIMER_CHCTL0_CH1CAPFLT); + /* set the CH1CAPFLT bit */ + TIMER_CHCTL0(timer_periph) |= (uint32_t)((uint32_t)(icpwm->icfilter) << 12U); + /* set the CH1EN bit */ + TIMER_CHCTL2(timer_periph) |= (uint32_t)TIMER_CHCTL2_CH1EN; + /* configure TIMER channel input capture prescaler value */ + timer_channel_input_capture_prescaler_config(timer_periph, TIMER_CH_1, (uint16_t)(icpwm->icprescaler)); + + /* reset the CH0EN bit */ + TIMER_CHCTL2(timer_periph) &= (~(uint32_t)TIMER_CHCTL2_CH0EN); + /* reset the CH0P and CH0NP bits */ + TIMER_CHCTL2(timer_periph) &= (~(uint32_t)(TIMER_CHCTL2_CH0P|TIMER_CHCTL2_CH0NP)); + /* set the CH0P and CH0NP bits */ + TIMER_CHCTL2(timer_periph) |= (uint32_t)icpolarity; + /* reset the CH0MS bit */ + TIMER_CHCTL0(timer_periph) &= (~(uint32_t)TIMER_CHCTL0_CH0MS); + /* set the CH0MS bit */ + TIMER_CHCTL0(timer_periph) |= (uint32_t)icselection; + /* reset the CH0CAPFLT bit */ + TIMER_CHCTL0(timer_periph) &= (~(uint32_t)TIMER_CHCTL0_CH0CAPFLT); + /* set the CH0CAPFLT bit */ + TIMER_CHCTL0(timer_periph) |= ((uint32_t)(icpwm->icfilter) << 4U); + /* set the CH0EN bit */ + TIMER_CHCTL2(timer_periph) |= (uint32_t)TIMER_CHCTL2_CH0EN; + /* configure TIMER channel input capture prescaler value */ + timer_channel_input_capture_prescaler_config(timer_periph, TIMER_CH_0, (uint16_t)(icpwm->icprescaler)); + } +} + +/*! + \brief configure TIMER hall sensor mode + \param[in] timer_periph: TIMERx(x=0..4,7) + \param[in] hallmode: + only one parameter can be selected which is shown as below: + \arg TIMER_HALLINTERFACE_ENABLE: TIMER hall sensor mode enable + \arg TIMER_HALLINTERFACE_DISABLE: TIMER hall sensor mode disable + \param[out] none + \retval none +*/ +void timer_hall_mode_config(uint32_t timer_periph, uint32_t hallmode) +{ + if(TIMER_HALLINTERFACE_ENABLE == hallmode){ + TIMER_CTL1(timer_periph) |= (uint32_t)TIMER_CTL1_TI0S; + }else if(TIMER_HALLINTERFACE_DISABLE == hallmode){ + TIMER_CTL1(timer_periph) &= ~(uint32_t)TIMER_CTL1_TI0S; + }else{ + /* illegal parameters */ + } +} + +/*! + \brief select TIMER input trigger source + \param[in] timer_periph: TIMERx(x=0..4,7,8,11) + \param[in] intrigger: + only one parameter can be selected which is shown as below: + \arg TIMER_SMCFG_TRGSEL_ITI0: internal trigger 0 + \arg TIMER_SMCFG_TRGSEL_ITI1: internal trigger 1 + \arg TIMER_SMCFG_TRGSEL_ITI2: internal trigger 2 + \arg TIMER_SMCFG_TRGSEL_ITI3: internal trigger 3 + \arg TIMER_SMCFG_TRGSEL_CI0F_ED: TI0 edge detector + \arg TIMER_SMCFG_TRGSEL_CI0FE0: filtered TIMER input 0 + \arg TIMER_SMCFG_TRGSEL_CI1FE1: filtered TIMER input 1 + \arg TIMER_SMCFG_TRGSEL_ETIFP: external trigger(x=0..4,7) + \param[out] none + \retval none +*/ +void timer_input_trigger_source_select(uint32_t timer_periph, uint32_t intrigger) +{ + TIMER_SMCFG(timer_periph) &= (~(uint32_t)TIMER_SMCFG_TRGS); + TIMER_SMCFG(timer_periph) |= (uint32_t)intrigger; +} + +/*! + \brief select TIMER master mode output trigger source + \param[in] timer_periph: TIMERx(x=0..7) + \param[in] outrigger: + only one parameter can be selected which is shown as below: + \arg TIMER_TRI_OUT_SRC_RESET: the UPG bit as trigger output + \arg TIMER_TRI_OUT_SRC_ENABLE: the counter enable signal TIMER_CTL0_CEN as trigger output + \arg TIMER_TRI_OUT_SRC_UPDATE: update event as trigger output + \arg TIMER_TRI_OUT_SRC_CH0: a capture or a compare match occurred in channal0 as trigger output TRGO + \arg TIMER_TRI_OUT_SRC_O0CPRE: O0CPRE as trigger output + \arg TIMER_TRI_OUT_SRC_O1CPRE: O1CPRE as trigger output + \arg TIMER_TRI_OUT_SRC_O2CPRE: O2CPRE as trigger output + \arg TIMER_TRI_OUT_SRC_O3CPRE: O3CPRE as trigger output + \param[out] none + \retval none +*/ +void timer_master_output_trigger_source_select(uint32_t timer_periph, uint32_t outrigger) +{ + TIMER_CTL1(timer_periph) &= (~(uint32_t)TIMER_CTL1_MMC); + TIMER_CTL1(timer_periph) |= (uint32_t)outrigger; +} + +/*! + \brief select TIMER slave mode + \param[in] timer_periph: TIMERx(x=0..4,7,8,11) + \param[in] slavemode: + only one parameter can be selected which is shown as below: + \arg TIMER_SLAVE_MODE_DISABLE: slave mode disable + \arg TIMER_ENCODER_MODE0: encoder mode 0 + \arg TIMER_ENCODER_MODE1: encoder mode 1 + \arg TIMER_ENCODER_MODE2: encoder mode 2 + \arg TIMER_SLAVE_MODE_RESTART: restart mode + \arg TIMER_SLAVE_MODE_PAUSE: pause mode + \arg TIMER_SLAVE_MODE_EVENT: event mode + \arg TIMER_SLAVE_MODE_EXTERNAL0: external clock mode 0. + \param[out] none + \retval none +*/ + +void timer_slave_mode_select(uint32_t timer_periph, uint32_t slavemode) +{ + TIMER_SMCFG(timer_periph) &= (~(uint32_t)TIMER_SMCFG_SMC); + + TIMER_SMCFG(timer_periph) |= (uint32_t)slavemode; +} + +/*! + \brief configure TIMER master slave mode + \param[in] timer_periph: TIMERx(x=0..4,7,8,11) + \param[in] masterslave: + only one parameter can be selected which is shown as below: + \arg TIMER_MASTER_SLAVE_MODE_ENABLE: master slave mode enable + \arg TIMER_MASTER_SLAVE_MODE_DISABLE: master slave mode disable + \param[out] none + \retval none +*/ +void timer_master_slave_mode_config(uint32_t timer_periph, uint32_t masterslave) +{ + if(TIMER_MASTER_SLAVE_MODE_ENABLE == masterslave){ + TIMER_SMCFG(timer_periph) |= (uint32_t)TIMER_SMCFG_MSM; + }else if(TIMER_MASTER_SLAVE_MODE_DISABLE == masterslave){ + TIMER_SMCFG(timer_periph) &= ~(uint32_t)TIMER_SMCFG_MSM; + }else{ + /* illegal parameters */ + } +} + +/*! + \brief configure TIMER external trigger input + \param[in] timer_periph: TIMERx(x=0..4,7) + \param[in] extprescaler: + only one parameter can be selected which is shown as below: + \arg TIMER_EXT_TRI_PSC_OFF: no divided + \arg TIMER_EXT_TRI_PSC_DIV2: divided by 2 + \arg TIMER_EXT_TRI_PSC_DIV4: divided by 4 + \arg TIMER_EXT_TRI_PSC_DIV8: divided by 8 + \param[in] extpolarity: + only one parameter can be selected which is shown as below: + \arg TIMER_ETP_FALLING: active low or falling edge active + \arg TIMER_ETP_RISING: active high or rising edge active + \param[in] extfilter: a value between 0 and 15 + \param[out] none + \retval none +*/ +void timer_external_trigger_config(uint32_t timer_periph, uint32_t extprescaler, + uint32_t extpolarity, uint32_t extfilter) +{ + TIMER_SMCFG(timer_periph) &= (~(uint32_t)(TIMER_SMCFG_ETP | TIMER_SMCFG_ETPSC | TIMER_SMCFG_ETFC)); + TIMER_SMCFG(timer_periph) |= (uint32_t)(extprescaler | extpolarity); + TIMER_SMCFG(timer_periph) |= (uint32_t)(extfilter << 8U); +} + +/*! + \brief configure TIMER quadrature decoder mode + \param[in] timer_periph: TIMERx(x=0..4,7) + \param[in] decomode: + only one parameter can be selected which is shown as below: + \arg TIMER_ENCODER_MODE0: counter counts on CI0FE0 edge depending on CI1FE1 level + \arg TIMER_ENCODER_MODE1: counter counts on CI1FE1 edge depending on CI0FE0 level + \arg TIMER_ENCODER_MODE2: counter counts on both CI0FE0 and CI1FE1 edges depending on the level of the other input + \param[in] ic0polarity: + only one parameter can be selected which is shown as below: + \arg TIMER_IC_POLARITY_RISING: capture rising edge + \arg TIMER_IC_POLARITY_FALLING: capture falling edge + \param[in] ic1polarity: + only one parameter can be selected which is shown as below: + \arg TIMER_IC_POLARITY_RISING: capture rising edge + \arg TIMER_IC_POLARITY_FALLING: capture falling edge + \param[out] none + \retval none +*/ +void timer_quadrature_decoder_mode_config(uint32_t timer_periph, uint32_t decomode, + uint16_t ic0polarity, uint16_t ic1polarity) +{ + TIMER_SMCFG(timer_periph) &= (~(uint32_t)TIMER_SMCFG_SMC); + TIMER_SMCFG(timer_periph) |= (uint32_t)decomode; + + TIMER_CHCTL0(timer_periph) &= (uint32_t)(((~(uint32_t)TIMER_CHCTL0_CH0MS))&((~(uint32_t)TIMER_CHCTL0_CH1MS))); + TIMER_CHCTL0(timer_periph) |= (uint32_t)(TIMER_IC_SELECTION_DIRECTTI|((uint32_t)TIMER_IC_SELECTION_DIRECTTI << 8U)); + + TIMER_CHCTL2(timer_periph) &= (~(uint32_t)(TIMER_CHCTL2_CH0P|TIMER_CHCTL2_CH0NP)); + TIMER_CHCTL2(timer_periph) &= (~(uint32_t)(TIMER_CHCTL2_CH1P|TIMER_CHCTL2_CH1NP)); + TIMER_CHCTL2(timer_periph) |= ((uint32_t)ic0polarity|((uint32_t)ic1polarity << 4U)); +} + +/*! + \brief configure TIMER internal clock mode + \param[in] timer_periph: TIMERx(x=0..4,7,8,11) + \param[out] none + \retval none +*/ +void timer_internal_clock_config(uint32_t timer_periph) +{ + TIMER_SMCFG(timer_periph) &= ~(uint32_t)TIMER_SMCFG_SMC; +} + +/*! + \brief configure TIMER the internal trigger as external clock input + \param[in] timer_periph: TIMERx(x=0..4,7,8,11) + \param[in] intrigger: + only one parameter can be selected which is shown as below: + \arg TIMER_SMCFG_TRGSEL_ITI0: internal trigger 0 + \arg TIMER_SMCFG_TRGSEL_ITI1: internal trigger 1 + \arg TIMER_SMCFG_TRGSEL_ITI2: internal trigger 2 + \arg TIMER_SMCFG_TRGSEL_ITI3: internal trigger 3 + \param[out] none + \retval none +*/ +void timer_internal_trigger_as_external_clock_config(uint32_t timer_periph, uint32_t intrigger) +{ + timer_input_trigger_source_select(timer_periph, intrigger); + TIMER_SMCFG(timer_periph) &= ~(uint32_t)TIMER_SMCFG_SMC; + TIMER_SMCFG(timer_periph) |= (uint32_t)TIMER_SLAVE_MODE_EXTERNAL0; +} + +/*! + \brief configure TIMER the external trigger as external clock input + \param[in] timer_periph: TIMERx(x=0..4,7,8,11) + \param[in] extrigger: + only one parameter can be selected which is shown as below: + \arg TIMER_SMCFG_TRGSEL_CI0F_ED: TI0 edge detector + \arg TIMER_SMCFG_TRGSEL_CI0FE0: filtered TIMER input 0 + \arg TIMER_SMCFG_TRGSEL_CI1FE1: filtered TIMER input 1 + \param[in] extpolarity: + only one parameter can be selected which is shown as below: + \arg TIMER_IC_POLARITY_RISING: active high or rising edge active + \arg TIMER_IC_POLARITY_FALLING: active low or falling edge active + \param[in] extfilter: a value between 0 and 15 + \param[out] none + \retval none +*/ +void timer_external_trigger_as_external_clock_config(uint32_t timer_periph, uint32_t extrigger, + uint16_t extpolarity, uint32_t extfilter) +{ + if(TIMER_SMCFG_TRGSEL_CI1FE1 == extrigger){ + /* reset the CH1EN bit */ + TIMER_CHCTL2(timer_periph) &= (~(uint32_t)TIMER_CHCTL2_CH1EN); + /* reset the CH1NP bit */ + TIMER_CHCTL2(timer_periph) &= (~(uint32_t)(TIMER_CHCTL2_CH1P|TIMER_CHCTL2_CH1NP)); + /* set the CH1NP bit */ + TIMER_CHCTL2(timer_periph) |= (uint32_t)((uint32_t)extpolarity << 4U); + /* reset the CH1MS bit */ + TIMER_CHCTL0(timer_periph) &= (~(uint32_t)TIMER_CHCTL0_CH1MS); + /* set the CH1MS bit */ + TIMER_CHCTL0(timer_periph) |= (uint32_t)((uint32_t)TIMER_IC_SELECTION_DIRECTTI << 8U); + /* reset the CH1CAPFLT bit */ + TIMER_CHCTL0(timer_periph) &= (~(uint32_t)TIMER_CHCTL0_CH1CAPFLT); + /* set the CH1CAPFLT bit */ + TIMER_CHCTL0(timer_periph) |= (uint32_t)(extfilter << 12U); + /* set the CH1EN bit */ + TIMER_CHCTL2(timer_periph) |= (uint32_t)TIMER_CHCTL2_CH1EN; + }else{ + /* reset the CH0EN bit */ + TIMER_CHCTL2(timer_periph) &= (~(uint32_t)TIMER_CHCTL2_CH0EN); + /* reset the CH0P and CH0NP bits */ + TIMER_CHCTL2(timer_periph) &= (~(uint32_t)(TIMER_CHCTL2_CH0P|TIMER_CHCTL2_CH0NP)); + /* set the CH0P and CH0NP bits */ + TIMER_CHCTL2(timer_periph) |= (uint32_t)extpolarity; + /* reset the CH0MS bit */ + TIMER_CHCTL0(timer_periph) &= (~(uint32_t)TIMER_CHCTL0_CH0MS); + /* set the CH0MS bit */ + TIMER_CHCTL0(timer_periph) |= (uint32_t)TIMER_IC_SELECTION_DIRECTTI; + /* reset the CH0CAPFLT bit */ + TIMER_CHCTL0(timer_periph) &= (~(uint32_t)TIMER_CHCTL0_CH0CAPFLT); + /* reset the CH0CAPFLT bit */ + TIMER_CHCTL0(timer_periph) |= (uint32_t)(extfilter << 4U); + /* set the CH0EN bit */ + TIMER_CHCTL2(timer_periph) |= (uint32_t)TIMER_CHCTL2_CH0EN; + } + /* select TIMER input trigger source */ + timer_input_trigger_source_select(timer_periph,extrigger); + /* reset the SMC bit */ + TIMER_SMCFG(timer_periph) &= (~(uint32_t)TIMER_SMCFG_SMC); + /* set the SMC bit */ + TIMER_SMCFG(timer_periph) |= (uint32_t)TIMER_SLAVE_MODE_EXTERNAL0; +} + +/*! + \brief configure TIMER the external clock mode0 + \param[in] timer_periph: TIMERx(x=0..4,7,8,11) + \param[in] extprescaler: + only one parameter can be selected which is shown as below: + \arg TIMER_EXT_TRI_PSC_OFF: no divided + \arg TIMER_EXT_TRI_PSC_DIV2: divided by 2 + \arg TIMER_EXT_TRI_PSC_DIV4: divided by 4 + \arg TIMER_EXT_TRI_PSC_DIV8: divided by 8 + \param[in] extpolarity: + only one parameter can be selected which is shown as below: + \arg TIMER_ETP_FALLING: active low or falling edge active + \arg TIMER_ETP_RISING: active high or rising edge active + \param[in] extfilter: a value between 0 and 15 + \param[out] none + \retval none +*/ +void timer_external_clock_mode0_config(uint32_t timer_periph, uint32_t extprescaler, + uint32_t extpolarity, uint32_t extfilter) +{ + /* configure TIMER external trigger input */ + timer_external_trigger_config(timer_periph, extprescaler, extpolarity, extfilter); + + /* reset the SMC bit,TRGS bit */ + TIMER_SMCFG(timer_periph) &= (~(uint32_t)(TIMER_SMCFG_SMC | TIMER_SMCFG_TRGS)); + /* set the SMC bit,TRGS bit */ + TIMER_SMCFG(timer_periph) |= (uint32_t)(TIMER_SLAVE_MODE_EXTERNAL0 | TIMER_SMCFG_TRGSEL_ETIFP); +} + +/*! + \brief configure TIMER the external clock mode1 + \param[in] timer_periph: TIMERx(x=0..4,7) + \param[in] extprescaler: + only one parameter can be selected which is shown as below: + \arg TIMER_EXT_TRI_PSC_OFF: no divided + \arg TIMER_EXT_TRI_PSC_DIV2: divided by 2 + \arg TIMER_EXT_TRI_PSC_DIV4: divided by 4 + \arg TIMER_EXT_TRI_PSC_DIV8: divided by 8 + \param[in] extpolarity: + only one parameter can be selected which is shown as below: + \arg TIMER_ETP_FALLING: active low or falling edge active + \arg TIMER_ETP_RISING: active high or rising edge active + \param[in] extfilter: a value between 0 and 15 + \param[out] none + \retval none +*/ +void timer_external_clock_mode1_config(uint32_t timer_periph, uint32_t extprescaler, + uint32_t extpolarity, uint32_t extfilter) +{ + /* configure TIMER external trigger input */ + timer_external_trigger_config(timer_periph, extprescaler, extpolarity, extfilter); + + TIMER_SMCFG(timer_periph) |= (uint32_t)TIMER_SMCFG_SMC1; +} + +/*! + \brief disable TIMER the external clock mode1 + \param[in] timer_periph: TIMERx(x=0..4,7) + \param[out] none + \retval none +*/ +void timer_external_clock_mode1_disable(uint32_t timer_periph) +{ + TIMER_SMCFG(timer_periph) &= ~(uint32_t)TIMER_SMCFG_SMC1; +} + +/*! + \brief configure TIMER write CHxVAL register selection + \param[in] timer_periph: TIMERx(x=0..4,7..13) + \param[in] ccsel: + only one parameter can be selected which is shown as below: + \arg TIMER_CHVSEL_DISABLE: no effect + \arg TIMER_CHVSEL_ENABLE: when write the CHxVAL register, if the write value is same as the CHxVAL value, the write access is ignored + \param[out] none + \retval none +*/ +void timer_write_chxval_register_config(uint32_t timer_periph, uint16_t ccsel) +{ + if(TIMER_CHVSEL_ENABLE == ccsel){ + TIMER_CFG(timer_periph) |= (uint32_t)TIMER_CFG_CHVSEL; + }else if(TIMER_CHVSEL_DISABLE == ccsel){ + TIMER_CFG(timer_periph) &= ~(uint32_t)TIMER_CFG_CHVSEL; + }else{ + /* illegal parameters */ + } +} + +/*! + \brief configure TIMER output value selection + \param[in] timer_periph: TIMERx(x=0,7) + \param[in] outsel: + only one parameter can be selected which is shown as below: + \arg TIMER_OUTSEL_DISABLE: no effect + \arg TIMER_OUTSEL_ENABLE: if POEN and IOS is 0, the output disabled + \param[out] none + \retval none +*/ +void timer_output_value_selection_config(uint32_t timer_periph, uint16_t outsel) +{ + if(TIMER_OUTSEL_ENABLE == outsel){ + TIMER_CFG(timer_periph) |= (uint32_t)TIMER_CFG_OUTSEL; + }else if(TIMER_OUTSEL_DISABLE == outsel){ + TIMER_CFG(timer_periph) &= ~(uint32_t)TIMER_CFG_OUTSEL; + }else{ + /* illegal parameters */ + } +} diff --git a/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_standard_peripheral/Source/gd32f30x_usart.c b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_standard_peripheral/Source/gd32f30x_usart.c new file mode 100644 index 0000000000..42f6fe7990 --- /dev/null +++ b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_standard_peripheral/Source/gd32f30x_usart.c @@ -0,0 +1,909 @@ +/*! + \file gd32f30x_usart.c + \brief USART driver + + \version 2017-02-10, V1.0.0, firmware for GD32F30x + \version 2018-10-10, V1.1.0, firmware for GD32F30x + \version 2018-12-25, V2.0.0, firmware for GD32F30x + \version 2020-09-30, V2.1.0, firmware for GD32F30x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "gd32f30x_usart.h" + +/* USART register bit offset */ +#define GP_GUAT_OFFSET ((uint32_t)8U) /* bit offset of GUAT in USART_GP */ +#define CTL3_SCRTNUM_OFFSET ((uint32_t)1U) /* bit offset of SCRTNUM in USART_CTL3 */ +#define RT_BL_OFFSET ((uint32_t)24U) /* bit offset of BL in USART_RT */ + +/*! + \brief reset USART/UART + \param[in] usart_periph: USARTx(x=0,1,2)/UARTx(x=3,4) + \param[out] none + \retval none +*/ +void usart_deinit(uint32_t usart_periph) +{ + switch(usart_periph){ + case USART0: + /* reset USART0 */ + rcu_periph_reset_enable(RCU_USART0RST); + rcu_periph_reset_disable(RCU_USART0RST); + break; + case USART1: + /* reset USART1 */ + rcu_periph_reset_enable(RCU_USART1RST); + rcu_periph_reset_disable(RCU_USART1RST); + break; + case USART2: + /* reset USART2 */ + rcu_periph_reset_enable(RCU_USART2RST); + rcu_periph_reset_disable(RCU_USART2RST); + break; + case UART3: + /* reset UART3 */ + rcu_periph_reset_enable(RCU_UART3RST); + rcu_periph_reset_disable(RCU_UART3RST); + break; + case UART4: + /* reset UART4 */ + rcu_periph_reset_enable(RCU_UART4RST); + rcu_periph_reset_disable(RCU_UART4RST); + break; + default: + break; + } +} + +/*! + \brief configure USART baud rate value + \param[in] usart_periph: USARTx(x=0,1,2)/UARTx(x=3,4) + \param[in] baudval: baud rate value + \param[out] none + \retval none +*/ +void usart_baudrate_set(uint32_t usart_periph, uint32_t baudval) +{ + uint32_t uclk=0U, intdiv=0U, fradiv=0U, udiv=0U; + switch(usart_periph){ + /* get clock frequency */ + case USART0: + /* get USART0 clock */ + uclk = rcu_clock_freq_get(CK_APB2); + break; + case USART1: + /* get USART1 clock */ + uclk = rcu_clock_freq_get(CK_APB1); + break; + case USART2: + /* get USART2 clock */ + uclk = rcu_clock_freq_get(CK_APB1); + break; + case UART3: + /* get UART3 clock */ + uclk = rcu_clock_freq_get(CK_APB1); + break; + case UART4: + /* get UART4 clock */ + uclk = rcu_clock_freq_get(CK_APB1); + break; + default: + break; + } + /* oversampling by 16, configure the value of USART_BAUD */ + udiv = (uclk+baudval/2U)/baudval; + intdiv = udiv & 0xfff0U; + fradiv = udiv & 0xfU; + USART_BAUD(usart_periph) = ((USART_BAUD_FRADIV | USART_BAUD_INTDIV) & (intdiv | fradiv)); +} + +/*! + \brief configure USART parity + \param[in] usart_periph: USARTx(x=0,1,2)/UARTx(x=3,4) + \param[in] paritycfg: configure USART parity + only one parameter can be selected which is shown as below: + \arg USART_PM_NONE: no parity + \arg USART_PM_ODD: odd parity + \arg USART_PM_EVEN: even parity + \param[out] none + \retval none +*/ +void usart_parity_config(uint32_t usart_periph, uint32_t paritycfg) +{ + /* clear USART_CTL0 PM,PCEN bits */ + USART_CTL0(usart_periph) &= ~(USART_CTL0_PM | USART_CTL0_PCEN); + /* configure USART parity mode */ + USART_CTL0(usart_periph) |= paritycfg ; +} + +/*! + \brief configure USART word length + \param[in] usart_periph: USARTx(x=0,1,2)/UARTx(x=3,4) + \param[in] wlen: USART word length configure + only one parameter can be selected which is shown as below: + \arg USART_WL_8BIT: 8 bits + \arg USART_WL_9BIT: 9 bits + \param[out] none + \retval none +*/ +void usart_word_length_set(uint32_t usart_periph, uint32_t wlen) +{ + /* clear USART_CTL0 WL bit */ + USART_CTL0(usart_periph) &= ~USART_CTL0_WL; + /* configure USART word length */ + USART_CTL0(usart_periph) |= wlen; +} + +/*! + \brief configure USART stop bit length + \param[in] usart_periph: USARTx(x=0,1,2)/UARTx(x=3,4) + \param[in] stblen: USART stop bit configure + only one parameter can be selected which is shown as below: + \arg USART_STB_1BIT: 1 bit + \arg USART_STB_0_5BIT: 0.5 bit, not available for UARTx(x=3,4) + \arg USART_STB_2BIT: 2 bits + \arg USART_STB_1_5BIT: 1.5 bits, not available for UARTx(x=3,4) + \param[out] none + \retval none +*/ +void usart_stop_bit_set(uint32_t usart_periph, uint32_t stblen) +{ + /* clear USART_CTL1 STB bits */ + USART_CTL1(usart_periph) &= ~USART_CTL1_STB; + /* configure USART stop bits */ + USART_CTL1(usart_periph) |= stblen; +} + +/*! + \brief enable USART + \param[in] usart_periph: USARTx(x=0,1,2)/UARTx(x=3,4) + \param[out] none + \retval none +*/ +void usart_enable(uint32_t usart_periph) +{ + USART_CTL0(usart_periph) |= USART_CTL0_UEN; +} + +/*! + \brief disable USART + \param[in] usart_periph: USARTx(x=0,1,2)/UARTx(x=3,4) + \param[out] none + \retval none +*/ +void usart_disable(uint32_t usart_periph) +{ + USART_CTL0(usart_periph) &= ~(USART_CTL0_UEN); +} + +/*! + \brief configure USART transmitter + \param[in] usart_periph: USARTx(x=0,1,2)/UARTx(x=3,4) + \param[in] txconfig: enable or disable USART transmitter + only one parameter can be selected which is shown as below: + \arg USART_TRANSMIT_ENABLE: enable USART transmission + \arg USART_TRANSMIT_DISABLE: enable USART transmission + \param[out] none + \retval none +*/ +void usart_transmit_config(uint32_t usart_periph, uint32_t txconfig) +{ + uint32_t ctl = 0U; + + ctl = USART_CTL0(usart_periph); + ctl &= ~USART_CTL0_TEN; + ctl |= txconfig; + /* configure transfer mode */ + USART_CTL0(usart_periph) = ctl; +} + +/*! + \brief configure USART receiver + \param[in] usart_periph: USARTx(x=0,1,2)/UARTx(x=3,4) + \param[in] rxconfig: enable or disable USART receiver + only one parameter can be selected which is shown as below: + \arg USART_RECEIVE_ENABLE: enable USART reception + \arg USART_RECEIVE_DISABLE: disable USART reception + \param[out] none + \retval none +*/ +void usart_receive_config(uint32_t usart_periph, uint32_t rxconfig) +{ + uint32_t ctl = 0U; + + ctl = USART_CTL0(usart_periph); + ctl &= ~USART_CTL0_REN; + ctl |= rxconfig; + /* configure transfer mode */ + USART_CTL0(usart_periph) = ctl; +} + +/*! + \brief data is transmitted/received with the LSB/MSB first + \param[in] usart_periph: USARTx(x=0,1,2) + \param[in] msbf: LSB/MSB + only one parameter can be selected which is shown as below: + \arg USART_MSBF_LSB: LSB first + \arg USART_MSBF_MSB: MSB first + \param[out] none + \retval none +*/ +void usart_data_first_config(uint32_t usart_periph, uint32_t msbf) +{ + USART_CTL3(usart_periph) &= ~(USART_CTL3_MSBF); + USART_CTL3(usart_periph) |= msbf; +} + +/*! + \brief configure USART inversion + \param[in] usart_periph: USARTx(x=0,1,2) + \param[in] invertpara: refer to enum usart_invert_enum + only one parameter can be selected which is shown as below: + \arg USART_DINV_ENABLE: data bit level inversion + \arg USART_DINV_DISABLE: data bit level not inversion + \arg USART_TXPIN_ENABLE: TX pin level inversion + \arg USART_TXPIN_DISABLE: TX pin level not inversion + \arg USART_RXPIN_ENABLE: RX pin level inversion + \arg USART_RXPIN_DISABLE: RX pin level not inversion + \param[out] none + \retval none +*/ +void usart_invert_config(uint32_t usart_periph, usart_invert_enum invertpara) +{ + /* inverted or not the specified siginal */ + switch(invertpara){ + case USART_DINV_ENABLE: + /* data bit level inversion */ + USART_CTL3(usart_periph) |= USART_CTL3_DINV; + break; + case USART_TXPIN_ENABLE: + /* TX pin level inversion */ + USART_CTL3(usart_periph) |= USART_CTL3_TINV; + break; + case USART_RXPIN_ENABLE: + /* RX pin level inversion */ + USART_CTL3(usart_periph) |= USART_CTL3_RINV; + break; + case USART_DINV_DISABLE: + /* data bit level not inversion */ + USART_CTL3(usart_periph) &= ~(USART_CTL3_DINV); + break; + case USART_TXPIN_DISABLE: + /* TX pin level not inversion */ + USART_CTL3(usart_periph) &= ~(USART_CTL3_TINV); + break; + case USART_RXPIN_DISABLE: + /* RX pin level not inversion */ + USART_CTL3(usart_periph) &= ~(USART_CTL3_RINV); + break; + default: + break; + } +} + +/*! + \brief enable receiver timeout of USART + \param[in] usart_periph: USARTx(x=0,1,2) + \param[out] none + \retval none +*/ +void usart_receiver_timeout_enable(uint32_t usart_periph) +{ + USART_CTL3(usart_periph) |= USART_CTL3_RTEN; +} + +/*! + \brief disable receiver timeout of USART + \param[in] usart_periph: USARTx(x=0,1,2) + \param[out] none + \retval none +*/ +void usart_receiver_timeout_disable(uint32_t usart_periph) +{ + USART_CTL3(usart_periph) &= ~(USART_CTL3_RTEN); +} + +/*! + \brief set the receiver timeout threshold of USART + \param[in] usart_periph: USARTx(x=0,1,2) + \param[in] rtimeout: 0-0xFFFFFF + \param[out] none + \retval none +*/ +void usart_receiver_timeout_threshold_config(uint32_t usart_periph, uint32_t rtimeout) +{ + USART_RT(usart_periph) &= ~(USART_RT_RT); + USART_RT(usart_periph) |= rtimeout; +} + +/*! + \brief USART transmit data function + \param[in] usart_periph: USARTx(x=0,1,2)/UARTx(x=3,4) + \param[in] data: data of transmission + \param[out] none + \retval none +*/ +void usart_data_transmit(uint32_t usart_periph, uint32_t data) +{ + USART_DATA(usart_periph) = ((uint16_t)USART_DATA_DATA & data); +} + +/*! + \brief USART receive data function + \param[in] usart_periph: USARTx(x=0,1,2)/UARTx(x=3,4) + \param[out] none + \retval data of received +*/ +uint16_t usart_data_receive(uint32_t usart_periph) +{ + return (uint16_t)(GET_BITS(USART_DATA(usart_periph), 0U, 8U)); +} + +/*! + \brief configure the address of the USART in wake up by address match mode + \param[in] usart_periph: USARTx(x=0,1,2)/UARTx(x=3,4) + \param[in] addr: address of USART/UART + \param[out] none + \retval none +*/ +void usart_address_config(uint32_t usart_periph, uint8_t addr) +{ + USART_CTL1(usart_periph) &= ~(USART_CTL1_ADDR); + USART_CTL1(usart_periph) |= (USART_CTL1_ADDR & addr); +} + +/*! + \brief receiver in mute mode + \param[in] usart_periph: USARTx(x=0,1,2)/UARTx(x=3,4) + \param[out] none + \retval none +*/ +void usart_mute_mode_enable(uint32_t usart_periph) +{ + USART_CTL0(usart_periph) |= USART_CTL0_RWU; +} + +/*! + \brief receiver in active mode + \param[in] usart_periph: USARTx(x=0,1,2)/UARTx(x=3,4) + \param[out] none + \retval none +*/ +void usart_mute_mode_disable(uint32_t usart_periph) +{ + USART_CTL0(usart_periph) &= ~(USART_CTL0_RWU); +} + +/*! + \brief configure wakeup method in mute mode + \param[in] usart_periph: USARTx(x=0,1,2)/UARTx(x=3,4) + \param[in] wmethod: two methods be used to enter or exit the mute mode + only one parameter can be selected which is shown as below: + \arg USART_WM_IDLE: idle line + \arg USART_WM_ADDR: address mask + \param[out] none + \retval none +*/ +void usart_mute_mode_wakeup_config(uint32_t usart_periph, uint32_t wmethod) +{ + USART_CTL0(usart_periph) &= ~(USART_CTL0_WM); + USART_CTL0(usart_periph) |= wmethod; +} + +/*! + \brief enable LIN mode + \param[in] usart_periph: USARTx(x=0,1,2)/UARTx(x=3,4) + \param[out] none + \retval none +*/ +void usart_lin_mode_enable(uint32_t usart_periph) +{ + USART_CTL1(usart_periph) |= USART_CTL1_LMEN; +} + +/*! + \brief disable LIN mode + \param[in] usart_periph: USARTx(x=0,1,2)/UARTx(x=3,4) + \param[out] none + \retval none +*/ +void usart_lin_mode_disable(uint32_t usart_periph) +{ + USART_CTL1(usart_periph) &= ~(USART_CTL1_LMEN); +} + +/*! + \brief configure lin break frame length + \param[in] usart_periph: USARTx(x=0,1,2)/UARTx(x=3,4) + \param[in] lblen: lin break frame length + only one parameter can be selected which is shown as below: + \arg USART_LBLEN_10B: 10 bits + \arg USART_LBLEN_11B: 11 bits + \param[out] none + \retval none +*/ +void usart_lin_break_detection_length_config(uint32_t usart_periph, uint32_t lblen) +{ + USART_CTL1(usart_periph) &= ~(USART_CTL1_LBLEN); + USART_CTL1(usart_periph) |= (USART_CTL1_LBLEN & lblen); +} + +/*! + \brief send break frame + \param[in] usart_periph: USARTx(x=0,1,2)/UARTx(x=3,4) + \param[out] none + \retval none +*/ +void usart_send_break(uint32_t usart_periph) +{ + USART_CTL0(usart_periph) |= USART_CTL0_SBKCMD; +} + +/*! + \brief enable half duplex mode + \param[in] usart_periph: USARTx(x=0,1,2)/UARTx(x=3,4) + \param[out] none + \retval none +*/ +void usart_halfduplex_enable(uint32_t usart_periph) +{ + USART_CTL2(usart_periph) |= USART_CTL2_HDEN; +} + +/*! + \brief disable half duplex mode + \param[in] usart_periph: USARTx(x=0,1,2)/UARTx(x=3,4) + \param[out] none + \retval none +*/ +void usart_halfduplex_disable(uint32_t usart_periph) +{ + USART_CTL2(usart_periph) &= ~(USART_CTL2_HDEN); +} + +/*! + \brief enable CK pin in synchronous mode + \param[in] usart_periph: USARTx(x=0,1,2) + \param[out] none + \retval none +*/ +void usart_synchronous_clock_enable(uint32_t usart_periph) +{ + USART_CTL1(usart_periph) |= USART_CTL1_CKEN; +} + +/*! + \brief disable CK pin in synchronous mode + \param[in] usart_periph: USARTx(x=0,1,2) + \param[out] none + \retval none +*/ +void usart_synchronous_clock_disable(uint32_t usart_periph) +{ + USART_CTL1(usart_periph) &= ~(USART_CTL1_CKEN); +} + +/*! + \brief configure USART synchronous mode parameters + \param[in] usart_periph: USARTx(x=0,1,2) + \param[in] clen: CK length + only one parameter can be selected which is shown as below: + \arg USART_CLEN_NONE: there are 7 CK pulses for an 8 bit frame and 8 CK pulses for a 9 bit frame + \arg USART_CLEN_EN: there are 8 CK pulses for an 8 bit frame and 9 CK pulses for a 9 bit frame + \param[in] cph: clock phase + only one parameter can be selected which is shown as below: + \arg USART_CPH_1CK: first clock transition is the first data capture edge + \arg USART_CPH_2CK: second clock transition is the first data capture edge + \param[in] cpl: clock polarity + only one parameter can be selected which is shown as below: + \arg USART_CPL_LOW: steady low value on CK pin + \arg USART_CPL_HIGH: steady high value on CK pin + \param[out] none + \retval none +*/ +void usart_synchronous_clock_config(uint32_t usart_periph, uint32_t clen, uint32_t cph, uint32_t cpl) +{ + uint32_t ctl = 0U; + + /* read USART_CTL1 register */ + ctl = USART_CTL1(usart_periph); + ctl &= ~(USART_CTL1_CLEN | USART_CTL1_CPH | USART_CTL1_CPL); + /* set CK length, CK phase, CK polarity */ + ctl |= (USART_CTL1_CLEN & clen) | (USART_CTL1_CPH & cph) | (USART_CTL1_CPL & cpl); + + USART_CTL1(usart_periph) = ctl; +} + +/*! + \brief configure guard time value in smartcard mode + \param[in] usart_periph: USARTx(x=0,1,2) + \param[in] guat: guard time value, 0-0xFF + \param[out] none + \retval none +*/ +void usart_guard_time_config(uint32_t usart_periph,uint32_t guat) +{ + USART_GP(usart_periph) &= ~(USART_GP_GUAT); + USART_GP(usart_periph) |= (USART_GP_GUAT & ((guat)<> 8);(uint8_t)((x) >> 16) + +/* audio_freq * data_size (2 bytes) * num_channels (stereo: 2) */ +#define DEFAULT_OUT_BIT_RESOLUTION 16U +#define DEFAULT_OUT_CHANNEL_NBR 2U /* mono = 1, stereo = 2 */ +#define AUDIO_OUT_PACKET (uint32_t)(((USBD_AUDIO_FREQ_16K * \ + (DEFAULT_OUT_BIT_RESOLUTION / 8U) *\ + DEFAULT_OUT_CHANNEL_NBR) / 1000U)) + +/* number of sub-packets in the audio transfer buffer. you can modify this value but always make sure + that it is an even number and higher than 3 */ +#define OUT_PACKET_NUM 4U + +/* total size of the audio transfer buffer */ +#define OUT_BUF_MARGIN 4U +#define TOTAL_OUT_BUF_SIZE ((uint32_t)((AUDIO_OUT_PACKET + OUT_BUF_MARGIN) * OUT_PACKET_NUM)) + +#define AUDIO_CONFIG_DESC_SET_LEN 109U +#define AUDIO_INTERFACE_DESC_SIZE 9U + +#define USB_AUDIO_DESC_SIZ 0x09U +#define AUDIO_STANDARD_EP_DESC_SIZE 0x09U +#define AUDIO_STREAMING_EP_DESC_SIZE 0x07U + +/* audio interface class code */ +#define USB_CLASS_AUDIO 0x01U + +/* audio interface subclass codes */ +#define AUDIO_SUBCLASS_CONTROL 0x01U +#define AUDIO_SUBCLASS_AUDIOSTREAMING 0x02U +#define AUDIO_SUBCLASS_MIDISTREAMING 0x03U + +/* audio interface protocol codes */ +#define AUDIO_PROTOCOL_UNDEFINED 0x00U +#define AUDIO_STREAMING_GENERAL 0x01U +#define AUDIO_STREAMING_FORMAT_TYPE 0x02U + +/* audio class-specific descriptor types */ +#define AUDIO_DESCTYPE_UNDEFINED 0x20U +#define AUDIO_DESCTYPE_DEVICE 0x21U +#define AUDIO_DESCTYPE_CONFIGURATION 0x22U +#define AUDIO_DESCTYPE_STRING 0x23U +#define AUDIO_DESCTYPE_INTERFACE 0x24U +#define AUDIO_DESCTYPE_ENDPOINT 0x25U + +/* audio control interface descriptor subtypes */ +#define AUDIO_CONTROL_HEADER 0x01U +#define AUDIO_CONTROL_INPUT_TERMINAL 0x02U +#define AUDIO_CONTROL_OUTPUT_TERMINAL 0x03U +#define AUDIO_CONTROL_MIXER_UNIT 0x04U +#define AUDIO_CONTROL_SELECTOR_UNIT 0x05U +#define AUDIO_CONTROL_FEATURE_UNIT 0x06U +#define AUDIO_CONTROL_PROCESSING_UNIT 0x07U +#define AUDIO_CONTROL_EXTENSION_UNIT 0x08U + +#define AUDIO_INPUT_TERMINAL_DESC_SIZE 0x0CU +#define AUDIO_OUTPUT_TERMINAL_DESC_SIZE 0x09U +#define AUDIO_STREAMING_INTERFACE_DESC_SIZE 0x07U + +#define AUDIO_CONTROL_MUTE 0x0001U + +#define AUDIO_FORMAT_TYPE_I 0x01U +#define AUDIO_FORMAT_TYPE_III 0x03U + +#define USB_ENDPOINT_TYPE_ISOCHRONOUS 0x01U +#define AUDIO_ENDPOINT_GENERAL 0x01U + +#define AUDIO_REQ_GET_CUR 0x81U +#define AUDIO_REQ_SET_CUR 0x01U + +#define AUDIO_OUT_STREAMING_CTRL 0x02U + +#define PACKET_SIZE(freq) (((freq) * 2U) * 2U / 1000U) + +#define AUDIO_PACKET_SIZE(frq) (uint8_t)(PACKET_SIZE(frq) & 0xFFU), \ + (uint8_t)((PACKET_SIZE(frq) >> 8U) & 0xFFU) + +#define SAMPLE_FREQ(frq) (uint8_t)(frq), (uint8_t)((frq) >> 8U), \ + (uint8_t)((frq) >> 16U) + + +#pragma pack(1) + +typedef struct +{ + usb_desc_header header; /*!< descriptor header, including type and size */ + uint8_t bDescriptorSubtype; /*!< header descriptor subtype */ + uint16_t bcdADC; /*!< audio device class specification release number in binary-coded decimal */ + uint16_t wTotalLength; /*!< total number of bytes */ + uint8_t bInCollection; /*!< the number of the streaming interfaces */ + uint8_t baInterfaceNr; /*!< interface number of the streaming interfaces */ +} usb_desc_AC_itf; + +typedef struct +{ + usb_desc_header header; /*!< descriptor header, including type and size */ + uint8_t bDescriptorSubtype; /*!< AS_GENERAL descriptor subtype */ + uint8_t bTerminalLink; /*!< the terminal ID */ + uint8_t bDelay; /*!< delay introduced by the data path */ + uint16_t wFormatTag; /*!< the audio data format */ +} usb_desc_AS_itf; + +typedef struct +{ + usb_desc_header header; /*!< descriptor header, including type and size */ + uint8_t bDescriptorSubtype; /*!< INPUT_TERMINAL descriptor subtype. */ + uint8_t bTerminalID; /*!< constant uniquely identifying the terminal within the audio function */ + uint16_t wTerminalType; /*!< constant characterizing the type of terminal */ + uint8_t bAssocTerminal; /*!< ID of the output terminal */ + uint8_t bNrChannels; /*!< number of logical output channels */ + uint16_t wChannelConfig; /*!< describes the spatial location of the logical channels */ + uint8_t iChannelNames; /*!< index of a string descriptor */ + uint8_t iTerminal; /*!< index of a string descriptor */ +} usb_desc_input_terminal; + +typedef struct +{ + usb_desc_header header; /*!< descriptor header, including type and size */ + uint8_t bDescriptorSubtype; /*!< OUTPUT_TERMINAL descriptor subtype */ + uint8_t bTerminalID; /*!< constant uniquely identifying the terminal within the audio function */ + uint16_t wTerminalType; /*!< constant characterizing the type of terminal */ + uint8_t bAssocTerminal; /*!< constant, identifying the input terminal to which this output terminal is associated */ + uint8_t bSourceID; /*!< ID of the unit or terminal */ + uint8_t iTerminal; /*!< index of a string descriptor */ +} usb_desc_output_terminal; + +typedef struct +{ + usb_desc_header header; /*!< descriptor header, including type and size */ + uint8_t bDescriptorSubtype; /*!< FEATURE_UNIT descriptor subtype */ + uint8_t bUnitID; /*!< constant uniquely identifying the unit within the audio function */ + uint8_t bSourceID; /*!< ID of the unit or terminal */ + uint8_t bControlSize; /*!< size in bytes of an element of the bmaControls() array */ + uint8_t bmaControls0; /*!< a bit set to 1 indicates that the mentioned control is supported for master channel 0 */ + uint8_t bmaControls1; /*!< a bit set to 1 indicates that the mentioned control is supported for logical channel 1 */ + uint8_t iFeature; /*!< index of a string descriptor */ +} usb_desc_mono_feature_unit; + +typedef struct +{ + usb_desc_header header; /*!< descriptor header, including type and size */ + uint8_t bDescriptorSubtype; /*!< FEATURE_UNIT descriptor subtype */ + uint8_t bUnitID; /*!< constant uniquely identifying the unit within the audio function */ + uint8_t bSourceID; /*!< ID of the unit or terminal */ + uint8_t bControlSize; /*!< size in bytes of an element of the bmaControls() array */ + uint16_t bmaControls0; /*!< a bit set to 1 indicates that the mentioned control is supported for master channel 0 */ + uint16_t bmaControls1; /*!< a bit set to 1 indicates that the mentioned control is supported for logical channel 1 */ + uint16_t bmaControls2; /*!< a bit set to 1 indicates that the mentioned control is supported for logical channel 2 */ + uint8_t iFeature; /*!< index of a string descriptor */ +} usb_desc_stereo_feature_unit; + +typedef struct +{ + usb_desc_header header; /*!< descriptor header, including type and size */ + uint8_t bDescriptorSubtype; /*!< FORMAT_TYPE descriptor subtype */ + uint8_t bFormatType; /*!< constant identifying the format type */ + uint8_t bNrChannels; /*!< indicates the number of physical channels in the audio data stream */ + uint8_t bSubFrameSize; /*!< the number of bytes occupied by one audio sub-frame */ + uint8_t bBitResolution; /*!< the number of effectively used bits from the available bits in an audio sub-frame */ + uint8_t bSamFreqType; /*!< indicates how the sampling frequency can be programmed */ + uint8_t bSamFreq[3]; /*!< sampling frequency ns in Hz for this isochronous data endpoint */ +} usb_desc_format_type; + +typedef struct +{ + usb_desc_header header; /*!< descriptor header, including type and size */ + uint8_t bEndpointAddress; /*!< the address of the endpoint */ + uint8_t bmAttributes; /*!< transfer type and synchronization type */ + uint16_t wMaxPacketSize; /*!< maximum packet size this endpoint is capable of sending or receiving */ + uint8_t bInterval; /*!< left to the designer's discretion */ + uint8_t bRefresh; /*!< reset to 0 */ + uint8_t bSynchAddress; /*!< reset to 0 */ +} usb_desc_std_ep; + +typedef struct +{ + usb_desc_header header; /*!< descriptor header, including type and size */ + uint8_t bDescriptorSubtype; /*!< EP_GENERAL descriptor subtype */ + uint8_t bmAttributes; /*!< transfer type and synchronization type */ + uint8_t bLockDelayUnits; /*!< indicates the units used for the wLockDelay field */ + uint16_t wLockDelay; /*!< indicates the time it takes this endpoint to reliably lock its internal clock recovery circuitry */ +} usb_desc_AS_ep; + +#pragma pack() + +/* USB configuration descriptor structure */ +typedef struct +{ + usb_desc_config config; + usb_desc_itf std_itf; + usb_desc_AC_itf ac_itf; + usb_desc_input_terminal in_terminal; + usb_desc_mono_feature_unit feature_unit; + usb_desc_output_terminal out_terminal; + usb_desc_itf std_as_itf_zeroband; + usb_desc_itf std_as_itf_opera; + usb_desc_AS_itf as_itf; + usb_desc_format_type format_typeI; + usb_desc_std_ep std_endpoint; + usb_desc_AS_ep as_endpoint; +} usb_desc_config_set; + +typedef struct +{ + /* main buffer for audio data out transfers and its relative pointers */ + uint8_t isoc_out_buff[TOTAL_OUT_BUF_SIZE * 2U]; + uint8_t* isoc_out_wrptr; + uint8_t* isoc_out_rdptr; + + /* main buffer for audio control requests transfers and its relative variables */ + uint8_t audioctl[64]; + uint8_t audioctl_unit; + uint32_t audioctl_len; + + uint32_t play_flag; +} usbd_audio_handler; + +extern usb_desc audio_desc; +extern usb_class audio_class; + +#endif /* __AUDIO_CORE_H */ diff --git a/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbd_library/class/device/audio/Include/audio_out_itf.h b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbd_library/class/device/audio/Include/audio_out_itf.h new file mode 100644 index 0000000000..0ef370cfc3 --- /dev/null +++ b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbd_library/class/device/audio/Include/audio_out_itf.h @@ -0,0 +1,76 @@ +/*! + \file audio_out_itf.h + \brief audio OUT (playback) interface header file + + \version 2020-08-01, V3.0.0, firmware for GD32F30x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef __AUDIO_OUT_ITF_H +#define __AUDIO_OUT_ITF_H + +#include "usbd_conf.h" + +/* audio commands enumeration */ +typedef enum +{ + AUDIO_CMD_PLAY = 1U, + AUDIO_CMD_PAUSE, + AUDIO_CMD_STOP, +}audio_cmd_enum; + +/* mute commands */ +#define AUDIO_MUTE 0x01U +#define AUDIO_UNMUTE 0x00U + +/* functions return value */ +#define AUDIO_OK 0x00U +#define AUDIO_FAIL 0xFFU + +/* audio machine states */ +#define AUDIO_STATE_INACTIVE 0x00U +#define AUDIO_STATE_ACTIVE 0x01U +#define AUDIO_STATE_PLAYING 0x02U +#define AUDIO_STATE_PAUSED 0x03U +#define AUDIO_STATE_STOPPED 0x04U +#define AUDIO_STATE_ERROR 0x05U + +typedef struct { + uint8_t (*audio_init) (uint32_t audio_freq, uint32_t volume, uint32_t options); + uint8_t (*audio_deinit) (uint32_t options); + uint8_t (*audio_cmd) (uint8_t* pbuf, uint32_t size, uint8_t cmd); + uint8_t (*audio_volume_ctl) (uint8_t vol); + uint8_t (*audio_mute_ctl) (uint8_t cmd); + uint8_t (*audio_periodic_tc) (uint8_t cmd); + uint8_t (*audio_state_get) (void); +} audio_fops_struct; + +extern audio_fops_struct audio_out_fops; + +#endif /* __AUDIO_OUT_ITF_H */ diff --git a/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbd_library/class/device/audio/Source/audio_core.c b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbd_library/class/device/audio/Source/audio_core.c new file mode 100644 index 0000000000..c15eeca223 --- /dev/null +++ b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbd_library/class/device/audio/Source/audio_core.c @@ -0,0 +1,549 @@ +/*! + \file audio_core.c + \brief USB audio device class core functions + + \version 2020-08-01, V3.0.0, firmware for GD32F30x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "usbd_transc.h" +#include "audio_out_itf.h" +#include "audio_core.h" +#include + +#define USBD_VID 0x28E9U +#define USBD_PID 0x9574U + +/* local function prototypes ('static') */ +static uint8_t usbd_audio_sof (usb_dev *udev); +static uint8_t audio_init (usb_dev *udev, uint8_t config_index); +static uint8_t audio_deinit (usb_dev *udev, uint8_t config_index); +static uint8_t audio_req_handler (usb_dev *udev, usb_req *req); +static uint8_t audio_ctlx_out (usb_dev *udev); +static void audio_data_out (usb_dev *udev, uint8_t ep_num); + +usb_class audio_class = { + .init = audio_init, + .deinit = audio_deinit, + .req_process = audio_req_handler, + .ctlx_out = audio_ctlx_out, + .data_out = audio_data_out +}; + +usbd_int_cb_struct usb_inthandler = +{ + usbd_audio_sof, +}; + +/* note:it should use the c99 standard when compiling the below codes */ +/* USB standard device descriptor */ +usb_desc_dev audio_dev_desc = +{ + .header = + { + .bLength = USB_DEV_DESC_LEN, + .bDescriptorType = USB_DESCTYPE_DEV + }, + .bcdUSB = 0x0200U, + .bDeviceClass = 0x00U, + .bDeviceSubClass = 0x00U, + .bDeviceProtocol = 0x00U, + .bMaxPacketSize0 = USBD_EP0_MAX_SIZE, + .idVendor = USBD_VID, + .idProduct = USBD_PID, + .bcdDevice = 0x0100U, + .iManufacturer = STR_IDX_MFC, + .iProduct = STR_IDX_PRODUCT, + .iSerialNumber = STR_IDX_SERIAL, + .bNumberConfigurations = USBD_CFG_MAX_NUM +}; + +/* USB device configuration descriptor */ +usb_desc_config_set audio_config_set = +{ + .config = + { + .header = + { + .bLength = sizeof(usb_desc_config), + .bDescriptorType = USB_DESCTYPE_CONFIG + }, + .wTotalLength = AUDIO_CONFIG_DESC_SET_LEN, + .bNumInterfaces = 0x02U, + .bConfigurationValue = 0x01U, + .iConfiguration = 0x00U, + .bmAttributes = 0xC0U, + .bMaxPower = 0x32U + }, + + .std_itf = + { + .header = + { + .bLength = sizeof(usb_desc_itf), + .bDescriptorType = USB_DESCTYPE_ITF + }, + .bInterfaceNumber = 0x00U, + .bAlternateSetting = 0x00U, + .bNumEndpoints = 0x00U, + .bInterfaceClass = USB_CLASS_AUDIO, + .bInterfaceSubClass = AUDIO_SUBCLASS_CONTROL, + .bInterfaceProtocol = AUDIO_PROTOCOL_UNDEFINED, + .iInterface = 0x00U + }, + + .ac_itf = + { + .header = + { + .bLength = sizeof(usb_desc_AC_itf), + .bDescriptorType = AUDIO_DESCTYPE_INTERFACE + }, + .bDescriptorSubtype = 0x01U, + .bcdADC = 0x0100U, + .wTotalLength = 0x0027U, + .bInCollection = 0x01U, + .baInterfaceNr = 0x01U + }, + + .in_terminal = + { + .header = + { + .bLength = sizeof(usb_desc_input_terminal), + .bDescriptorType = AUDIO_DESCTYPE_INTERFACE + }, + .bDescriptorSubtype = 0x02U, + .bTerminalID = 0x01U, + .wTerminalType = 0x0101U, + .bAssocTerminal = 0x00U, + .bNrChannels = 0x01U, + .wChannelConfig = 0x0000U, + .iChannelNames = 0x00U, + .iTerminal = 0x00U + }, + + .feature_unit = + { + .header = + { + .bLength = sizeof(usb_desc_mono_feature_unit), + .bDescriptorType = AUDIO_DESCTYPE_INTERFACE + }, + .bDescriptorSubtype = AUDIO_CONTROL_FEATURE_UNIT, + .bUnitID = AUDIO_OUT_STREAMING_CTRL, + .bSourceID = 0x01U, + .bControlSize = 0x01U, + .bmaControls0 = AUDIO_CONTROL_MUTE, + .bmaControls1 = 0x00U, + .iFeature = 0x00U + }, + + .out_terminal = + { + .header = + { + .bLength = sizeof(usb_desc_output_terminal), + .bDescriptorType = AUDIO_DESCTYPE_INTERFACE + }, + .bDescriptorSubtype = AUDIO_CONTROL_OUTPUT_TERMINAL, + .bTerminalID = 0x03U, + .wTerminalType = 0x0301U, + .bAssocTerminal = 0x00U, + .bSourceID = 0x02U, + .iTerminal = 0x00U + }, + + .std_as_itf_zeroband = + { + .header = + { + .bLength = sizeof(usb_desc_itf), + .bDescriptorType = USB_DESCTYPE_ITF + }, + .bInterfaceNumber = 0x01U, + .bAlternateSetting = 0x00U, + .bNumEndpoints = 0x00U, + .bInterfaceClass = USB_CLASS_AUDIO, + .bInterfaceSubClass = AUDIO_SUBCLASS_AUDIOSTREAMING, + .bInterfaceProtocol = AUDIO_PROTOCOL_UNDEFINED, + .iInterface = 0x00U + }, + + .std_as_itf_opera = + { + .header = + { + .bLength = sizeof(usb_desc_itf), + .bDescriptorType = USB_DESCTYPE_ITF + }, + .bInterfaceNumber = 0x01U, + .bAlternateSetting = 0x01U, + .bNumEndpoints = 0x01U, + .bInterfaceClass = USB_CLASS_AUDIO, + .bInterfaceSubClass = AUDIO_SUBCLASS_AUDIOSTREAMING, + .bInterfaceProtocol = AUDIO_PROTOCOL_UNDEFINED, + .iInterface = 0x00U + }, + + .as_itf = + { + .header = + { + .bLength = sizeof(usb_desc_AS_itf), + .bDescriptorType = AUDIO_DESCTYPE_INTERFACE + }, + .bDescriptorSubtype = AUDIO_STREAMING_GENERAL, + .bTerminalLink = 0x01U, + .bDelay = 0x01U, + .wFormatTag = 0x0001U, + }, + + .format_typeI = + { + .header = + { + .bLength = sizeof(usb_desc_format_type), + .bDescriptorType = AUDIO_DESCTYPE_INTERFACE + }, + .bDescriptorSubtype = AUDIO_STREAMING_FORMAT_TYPE, + .bFormatType = AUDIO_FORMAT_TYPE_III, + .bNrChannels = 0x02U, + .bSubFrameSize = 0x02U, + .bBitResolution = 0x10U, + .bSamFreqType = 0x01U, + .bSamFreq[0] = (uint8_t)USBD_AUDIO_FREQ_16K, + .bSamFreq[1] = USBD_AUDIO_FREQ_16K >> 8, + .bSamFreq[2] = USBD_AUDIO_FREQ_16K >> 16 + }, + + .std_endpoint = + { + .header = + { + .bLength = sizeof(usb_desc_std_ep), + .bDescriptorType = USB_DESCTYPE_EP + }, + .bEndpointAddress = AUDIO_OUT_EP, + .bmAttributes = USB_ENDPOINT_TYPE_ISOCHRONOUS, + .wMaxPacketSize = PACKET_SIZE(USBD_AUDIO_FREQ_16K), + .bInterval = 0x01U, + .bRefresh = 0x00U, + .bSynchAddress = 0x00U + }, + + .as_endpoint = + { + .header = + { + .bLength = sizeof(usb_desc_AS_ep), + .bDescriptorType = AUDIO_DESCTYPE_ENDPOINT + }, + .bDescriptorSubtype = AUDIO_ENDPOINT_GENERAL, + .bmAttributes = 0x00U, + .bLockDelayUnits = 0x00U, + .wLockDelay = 0x0000U, + } +}; + +/* USB language ID descriptor */ +static usb_desc_LANGID usbd_language_id_desc = +{ + .header = + { + .bLength = sizeof(usb_desc_LANGID), + .bDescriptorType = USB_DESCTYPE_STR + }, + + .wLANGID = ENG_LANGID +}; + +/* USB manufacture string */ +static usb_desc_str manufacturer_string = +{ + .header = + { + .bLength = USB_STRING_LEN(10U), + .bDescriptorType = USB_DESCTYPE_STR, + }, + .unicode_string = {'G', 'i', 'g', 'a', 'D', 'e', 'v', 'i', 'c', 'e'} +}; + +/* USB product string */ +static usb_desc_str product_string = +{ + .header = + { + .bLength = USB_STRING_LEN(14U), + .bDescriptorType = USB_DESCTYPE_STR, + }, + .unicode_string = {'G', 'D', '3', '2', '-', 'U', 'S', 'B', '_', 'A', 'u', 'd', 'i', 'o'} +}; + +/* USBD serial string */ +static usb_desc_str serial_string = +{ + .header = + { + .bLength = USB_STRING_LEN(12U), + .bDescriptorType = USB_DESCTYPE_STR, + } +}; + +/* USB string descriptor */ +static uint8_t* usbd_audio_strings[] = +{ + [STR_IDX_LANGID] = (uint8_t *)&usbd_language_id_desc, + [STR_IDX_MFC] = (uint8_t *)&manufacturer_string, + [STR_IDX_PRODUCT] = (uint8_t *)&product_string, + [STR_IDX_SERIAL] = (uint8_t *)&serial_string +}; + +usb_desc audio_desc = { + .dev_desc = (uint8_t *)&audio_dev_desc, + .config_desc = (uint8_t *)&audio_config_set, + .strings = usbd_audio_strings +}; + + +/*! + \brief initialize the audio device + \param[in] udev: pointer to USB device instance + \param[in] config_index: configuration index + \param[out] none + \retval USB device operation status +*/ +static uint8_t audio_init (usb_dev *udev, uint8_t config_index) +{ + usb_desc_std_ep std_ep = audio_config_set.std_endpoint; + + static usbd_audio_handler audio_handler; + + memset((void *)&audio_handler, 0, sizeof(usbd_audio_handler)); + + usb_desc_ep ep = { + .header = std_ep.header, + .bEndpointAddress = std_ep.bEndpointAddress, + .bmAttributes = std_ep.bmAttributes, + .wMaxPacketSize = std_ep.wMaxPacketSize, + .bInterval = std_ep.bInterval + }; + + /* initialize RX endpoint */ + usbd_ep_init(udev, EP_BUF_DBL, AUDIO_BUF_ADDR, &ep); + + usbd_int_fops = &usb_inthandler; + + audio_handler.isoc_out_rdptr = audio_handler.isoc_out_buff; + audio_handler.isoc_out_wrptr = audio_handler.isoc_out_buff; + + /* initialize the audio output hardware layer */ + if (USBD_OK != audio_out_fops.audio_init(USBD_AUDIO_FREQ_16K, DEFAULT_VOLUME, 0U)) { + return USBD_FAIL; + } + + udev->ep_transc[AUDIO_OUT_EP][TRANSC_OUT] = audio_class.data_out; + + /* prepare out endpoint to receive audio data */ + usbd_ep_recev (udev, AUDIO_OUT_EP, (uint8_t*)audio_handler.isoc_out_buff, (uint16_t)AUDIO_OUT_PACKET); + + udev->class_data[USBD_AUDIO_INTERFACE] = (void *)&audio_handler; + + return USBD_OK; +} + +/*! + \brief de-initialize the audio device + \param[in] udev: pointer to USB device instance + \param[in] config_index: configuration index + \param[out] none + \retval USB device operation status +*/ +static uint8_t audio_deinit (usb_dev *udev, uint8_t config_index) +{ + /* deinitialize audio endpoints */ + usbd_ep_deinit(udev, AUDIO_OUT_EP); + + /* deinitialize the audio output hardware layer */ + if (USBD_OK != audio_out_fops.audio_deinit(0U)) { + return USBD_FAIL; + } + + return USBD_OK; +} + +/*! + \brief handle the audio class-specific requests + \param[in] udev: pointer to USB device instance + \param[in] req: device class-specific request + \param[out] none + \retval USB device operation status +*/ +static uint8_t audio_req_handler (usb_dev *udev, usb_req *req) +{ + uint8_t status = REQ_NOTSUPP; + + usbd_audio_handler *audio = (usbd_audio_handler *)udev->class_data[USBD_AUDIO_INTERFACE]; + + switch (req->bRequest) { + case AUDIO_REQ_GET_CUR: + usb_transc_config(&udev->transc_in[0], audio->audioctl, req->wLength, 0U); + + status = REQ_SUPP; + break; + + case AUDIO_REQ_SET_CUR: + if (req->wLength) { + usb_transc_config(&udev->transc_out[0], audio->audioctl, req->wLength, 0U); + + udev->class_core->req_cmd = AUDIO_REQ_SET_CUR; + + audio->audioctl_len = req->wLength; + audio->audioctl_unit = BYTE_HIGH(req->wIndex); + + status = REQ_SUPP; + } + break; + + default: + break; + } + + return status; +} + +/*! + \brief handles the audio out data stage + \param[in] udev: pointer to USB device instance + \param[in] ep_num: endpoint number + \param[out] none + \retval USB device operation status +*/ +static void audio_data_out (usb_dev *udev, uint8_t ep_num) +{ + usbd_audio_handler *audio = (usbd_audio_handler *)udev->class_data[USBD_AUDIO_INTERFACE]; + + if (AUDIO_OUT_EP == ep_num) { + /* increment the Buffer pointer or roll it back when all buffers are full */ + if (audio->isoc_out_wrptr >= (audio->isoc_out_buff + (AUDIO_OUT_PACKET * OUT_PACKET_NUM))) { + /* all buffers are full: roll back */ + audio->isoc_out_wrptr = audio->isoc_out_buff; + } else { + /* increment the buffer pointer */ + audio->isoc_out_wrptr += AUDIO_OUT_PACKET; + } + + /* prepare out endpoint to receive next audio packet */ + usbd_ep_recev (udev, AUDIO_OUT_EP, (uint8_t*)(audio->isoc_out_wrptr), (uint16_t)AUDIO_OUT_PACKET); + + /* trigger the start of streaming only when half buffer is full */ + if ((0U == audio->play_flag) && (audio->isoc_out_wrptr >= (audio->isoc_out_buff + ((AUDIO_OUT_PACKET * OUT_PACKET_NUM) / 2U)))) { + /* enable start of streaming */ + audio->play_flag = 1U; + } + } +} + +/*! + \brief handles audio control request data + \param[in] udev: pointer to USB device instance + \param[out] none + \retval USB device operation status +*/ +static uint8_t audio_ctlx_out (usb_dev *udev) +{ + usbd_audio_handler *audio = (usbd_audio_handler *)udev->class_data[USBD_AUDIO_INTERFACE]; + + /* check if an audio_control request has been issued */ + if (AUDIO_REQ_SET_CUR == udev->class_core->req_cmd) { + /* in this driver, to simplify code, only SET_CUR request is managed */ + + /* check for which addressed unit the audio_control request has been issued */ + if (AUDIO_OUT_STREAMING_CTRL == audio->audioctl_unit) { + /* in this driver, to simplify code, only one unit is manage */ + + /* call the audio interface mute function */ + audio_out_fops.audio_mute_ctl(audio->audioctl[0]); + + /* reset the audioctl_cmd variable to prevent re-entering this function */ + udev->class_core->req_cmd = 0U; + + audio->audioctl_len = 0U; + } + } + + return USBD_OK; +} + +/*! + \brief handles the SOF event (data buffer update and synchronization) + \param[in] udev: pointer to USB device instance + \param[out] none + \retval USB device operation status +*/ +static uint8_t usbd_audio_sof (usb_dev *udev) +{ + usbd_audio_handler *audio = (usbd_audio_handler *)udev->class_data[USBD_AUDIO_INTERFACE]; + + /* check if there are available data in stream buffer. + in this function, a single variable (play_flag) is used to avoid software delays. + the play operation must be executed as soon as possible after the SOF detection. */ + if (audio->play_flag) { + /* start playing received packet */ + audio_out_fops.audio_cmd((uint8_t*)(audio->isoc_out_rdptr), /* samples buffer pointer */ + AUDIO_OUT_PACKET, /* number of samples in Bytes */ + AUDIO_CMD_PLAY); /* command to be processed */ + + /* increment the Buffer pointer or roll it back when all buffers all full */ + if (audio->isoc_out_rdptr >= (audio->isoc_out_buff + (AUDIO_OUT_PACKET * OUT_PACKET_NUM))) { + /* roll back to the start of buffer */ + audio->isoc_out_rdptr = audio->isoc_out_buff; + } else { + /* increment to the next sub-buffer */ + audio->isoc_out_rdptr += AUDIO_OUT_PACKET; + } + + /* if all available buffers have been consumed, stop playing */ + if (audio->isoc_out_rdptr == audio->isoc_out_wrptr) { + /* pause the audio stream */ + audio_out_fops.audio_cmd((uint8_t*)(audio->isoc_out_buff), /* samples buffer pointer */ + AUDIO_OUT_PACKET, /* number of samples in Bytes */ + AUDIO_CMD_PAUSE); /* command to be processed */ + + /* stop entering play loop */ + audio->play_flag = 0U; + + /* reset buffer pointers */ + audio->isoc_out_rdptr = audio->isoc_out_buff; + audio->isoc_out_wrptr = audio->isoc_out_buff; + } + } + + return USBD_OK; +} diff --git a/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbd_library/class/device/audio/Source/audio_out_itf.c b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbd_library/class/device/audio/Source/audio_out_itf.c new file mode 100644 index 0000000000..7e55fdcf7a --- /dev/null +++ b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbd_library/class/device/audio/Source/audio_out_itf.c @@ -0,0 +1,242 @@ +/*! + \file audio_out_itf.c + \brief audio OUT (playback) interface functions + + \version 2020-08-01, V3.0.0, firmware for GD32F30x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "audio_core.h" +#include "audio_out_itf.h" + +/* local function prototypes ('static') */ +static uint8_t init (uint32_t audio_freq, uint32_t volume, uint32_t options); +static uint8_t deinit (uint32_t options); +static uint8_t audio_cmd (uint8_t* pbuf, uint32_t size, uint8_t cmd); +static uint8_t volume_ctl (uint8_t vol); +static uint8_t mute_ctl (uint8_t cmd); +static uint8_t periodic_tc (uint8_t cmd); +static uint8_t get_state (void); + +audio_fops_struct audio_out_fops = +{ + init, + deinit, + audio_cmd, + volume_ctl, + mute_ctl, + periodic_tc, + get_state +}; + +static uint8_t audio_state = AUDIO_STATE_INACTIVE; + +/*! + \brief initialize and configures all required resources for audio play function + \param[in] audio_freq: statrt_up audio frequency + \param[in] volume: start_up volume to be set + \param[in] options: specific options passed to low layer function + \param[out] none + \retval AUDIO_OK if all operations succeed, otherwise, AUDIO_FAIL. +*/ +static uint8_t init (uint32_t audio_freq, uint32_t volume, uint32_t options) +{ + static uint32_t initialized = 0U; + + /* check if the low layer has already been initialized */ + if (0U == initialized) { + /* call low layer function */ + if (0U != eval_audio_init(OUTPUT_DEVICE_AUTO, volume, audio_freq)) { + audio_state = AUDIO_STATE_ERROR; + + return AUDIO_FAIL; + } + + /* set the initialization flag to prevent reinitializing the interface again */ + initialized = 1U; + } + + /* update the audio state machine */ + audio_state = AUDIO_STATE_ACTIVE; + + return AUDIO_OK; +} + +/*! + \brief free all resources used by low layer and stops audio-play function + \param[in] options: specific options passed to low layer function + \param[out] none + \retval AUDIO_OK if all operations succeed, otherwise, AUDIO_FAIL. +*/ +static uint8_t deinit (uint32_t options) +{ + /* update the audio state machine */ + audio_state = AUDIO_STATE_INACTIVE; + + return AUDIO_OK; +} + +/*! + \brief play, stop, pause or resume current file + \param[in] pbuf: address from which file should be played + \param[in] size: size of the current buffer/file + \param[in] cmd: command to be executed, can be: + \arg AUDIO_CMD_PLAY + \arg AUDIO_CMD_PAUSE + \arg AUDIO_CMD_RESUME + \arg AUDIO_CMD_STOP + \param[out] none + \retval AUDIO_OK if all operations succeed, otherwise, AUDIO_FAIL. +*/ +static uint8_t audio_cmd (uint8_t* pbuf, uint32_t size, uint8_t cmd) +{ + uint8_t status = AUDIO_OK; + + /* check the current state */ + if ((AUDIO_STATE_INACTIVE == audio_state) || (AUDIO_STATE_ERROR == audio_state)) { + audio_state = AUDIO_STATE_ERROR; + + return AUDIO_FAIL; + } + + switch (cmd) { + /* process the play command */ + case AUDIO_CMD_PLAY: + /* if current state is active or stopped */ + if ((AUDIO_STATE_ACTIVE == audio_state) || \ + (AUDIO_STATE_STOPPED == audio_state) || \ + (AUDIO_STATE_PLAYING == audio_state)) { + audio_mal_play((uint32_t)pbuf, (size / 2U)); + audio_state = AUDIO_STATE_PLAYING; + } else if (AUDIO_STATE_PAUSED == audio_state) { + if (eval_audio_pause_resume(AUDIO_RESUME, (uint32_t)pbuf, (size / 2U))) { + audio_state = AUDIO_STATE_ERROR; + + status = AUDIO_FAIL; + } else { + audio_state = AUDIO_STATE_PLAYING; + } + } else { + status = AUDIO_FAIL; + } + break; + + /* process the stop command */ + case AUDIO_CMD_STOP: + if (AUDIO_STATE_PLAYING != audio_state) { + /* unsupported command */ + status = AUDIO_FAIL; + } else if (eval_audio_stop(CODEC_PDWN_SW)) { + audio_state = AUDIO_STATE_ERROR; + + status = AUDIO_FAIL; + } else { + audio_state = AUDIO_STATE_STOPPED; + } + break; + + /* process the pause command */ + case AUDIO_CMD_PAUSE: + if (AUDIO_STATE_PLAYING != audio_state) { + /* unsupported command */ + status = AUDIO_FAIL; + } else if (eval_audio_pause_resume(AUDIO_PAUSE, (uint32_t)pbuf, (size / 2U))) { + audio_state = AUDIO_STATE_ERROR; + + status = AUDIO_FAIL; + } else { + audio_state = AUDIO_STATE_PAUSED; + } + break; + + /* unsupported command */ + default: + break; + } + + return status; +} + +/*! + \brief set the volume level + \param[in] vol: volume level to be set in % (from 0% to 100%) + \param[out] none + \retval AUDIO_OK if all operations succeed, otherwise, AUDIO_FAIL. +*/ +static uint8_t volume_ctl (uint8_t vol) +{ + /* call low layer volume setting function */ + if (eval_audio_volume_ctl(vol)) { + audio_state = AUDIO_STATE_ERROR; + + return AUDIO_FAIL; + } + + return AUDIO_OK; +} + +/*! + \brief mute or unmute the audio current output + \param[in] cmd: can be 0 to unmute, or 1 to mute + \param[out] none + \retval AUDIO_OK if all operations succeed, otherwise, AUDIO_FAIL. +*/ +static uint8_t mute_ctl (uint8_t cmd) +{ + /* call low layer mute setting function */ + if (eval_audio_mute((uint32_t)cmd)) { + audio_state = AUDIO_STATE_ERROR; + + return AUDIO_FAIL; + } + + return AUDIO_OK; +} + +/*! + \brief periodic transfer control + \param[in] cmd: command + \param[out] none + \retval AUDIO_OK if all operations succeed, otherwise, AUDIO_FAIL. +*/ +static uint8_t periodic_tc (uint8_t cmd) +{ + return AUDIO_OK; +} + +/*! + \brief return the current state of the audio machine + \param[in] none + \param[out] none + \retval AUDIO_OK if all operations succeed, otherwise, AUDIO_FAIL. +*/ +static uint8_t get_state (void) +{ + return audio_state; +} diff --git a/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbd_library/class/device/cdc/Include/cdc_acm_core.h b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbd_library/class/device/cdc/Include/cdc_acm_core.h new file mode 100644 index 0000000000..930e93dc80 --- /dev/null +++ b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbd_library/class/device/cdc/Include/cdc_acm_core.h @@ -0,0 +1,163 @@ +/*! + \file cdc_acm_core.h + \brief the header file of cdc acm driver + + \version 2020-08-01, V3.0.0, firmware for GD32F30x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef __CDC_ACM_CORE_H +#define __CDC_ACM_CORE_H + +#include "usbd_enum.h" + +/* communications device class code */ +#define USB_CLASS_CDC 0x02U + +/* CDC subclass code */ +#define USB_CDC_SUBCLASS_DLCM 0x01U +#define USB_CDC_SUBCLASS_ACM 0x02U + +/* communications interface class control protocol codes */ +#define USB_CDC_PROTOCOL_NONE 0x00U +#define USB_CDC_PROTOCOL_AT 0x01U + +/* data interface class code */ +#define USB_CLASS_DATA 0x0AU + +#define USB_DESCTYPE_CDC_ACM 0x21U +#define USB_DESCTYPE_CS_INTERFACE 0x24U + +#define USB_CDC_ACM_CONFIG_DESC_SIZE 0x43U + +/* class-specific notification codes for PSTN subclasses */ +#define USB_CDC_NOTIFY_SERIAL_STATE 0x20U + +/* class-specific request codes */ +#define SEND_ENCAPSULATED_COMMAND 0x00U +#define GET_ENCAPSULATED_RESPONSE 0x01U +#define SET_COMM_FEATURE 0x02U +#define GET_COMM_FEATURE 0x03U +#define CLEAR_COMM_FEATURE 0x04U +#define SET_LINE_CODING 0x20U +#define GET_LINE_CODING 0x21U +#define SET_CONTROL_LINE_STATE 0x22U +#define SEND_BREAK 0x23U +#define NO_CMD 0xFFU + +#pragma pack(1) + +/* CDC ACM line coding struct */ +typedef struct { + uint32_t dwDTERate; /*!< data terminal rate */ + uint8_t bCharFormat; /*!< stop bits */ + uint8_t bParityType; /*!< parity */ + uint8_t bDataBits; /*!< data bits */ +} acm_line; + +/* notification structure */ +typedef struct { + uint8_t bmRequestType; /*!< type of request */ + uint8_t bNotification; /*!< communication interface class notifications */ + uint16_t wValue; /*!< value of notification */ + uint16_t wIndex; /*!< index of interface */ + uint16_t wLength; /*!< length of notification data */ +} acm_notification; + +/* header function struct */ +typedef struct { + usb_desc_header header; /*!< descriptor header, including type and size. */ + uint8_t bDescriptorSubtype; /*!< bDescriptorSubtype: header function descriptor */ + uint16_t bcdCDC; /*!< bcdCDC: low byte of spec release number (CDC1.10) */ +} usb_desc_header_func; + +/* call managment function struct */ +typedef struct { + usb_desc_header header; /*!< descriptor header, including type and size. */ + uint8_t bDescriptorSubtype; /*!< bDescriptorSubtype: call management function descriptor */ + uint8_t bmCapabilities; /*!< bmCapabilities: D0 is reset, D1 is ignored */ + uint8_t bDataInterface; /*!< bDataInterface: 1 interface used for call management */ +} usb_desc_call_managment_func; + +/* acm function struct */ +typedef struct { + usb_desc_header header; /*!< descriptor header, including type and size. */ + uint8_t bDescriptorSubtype; /*!< bDescriptorSubtype: abstract control management descriptor */ + uint8_t bmCapabilities; /*!< bmCapabilities: D1 */ +} usb_desc_acm_func; + +/* union function struct */ +typedef struct { + usb_desc_header header; /*!< descriptor header, including type and size. */ + uint8_t bDescriptorSubtype; /*!< bDescriptorSubtype: union function descriptor */ + uint8_t bMasterInterface; /*!< bMasterInterface: communication class interface */ + uint8_t bSlaveInterface0; /*!< bSlaveInterface0: data class interface */ +} usb_desc_union_func; + +#pragma pack() +/* configuration descriptor struct */ +typedef struct { + usb_desc_config config; + usb_desc_itf cmd_itf; + usb_desc_header_func cdc_header; + usb_desc_call_managment_func cdc_call_managment; + usb_desc_acm_func cdc_acm; + usb_desc_union_func cdc_union; + usb_desc_ep cdc_cmd_endpoint; + usb_desc_itf cdc_data_interface; + usb_desc_ep cdc_out_endpoint; + usb_desc_ep cdc_in_endpoint; +} usb_cdc_desc_config_set; + +#define USB_CDC_RX_LEN 64U + +typedef struct { + uint8_t pre_packet_send; + uint8_t packet_sent; + uint8_t packet_receive; + + uint8_t data[USB_CDC_RX_LEN]; + + uint32_t receive_length; + + acm_line line_coding; +} usb_cdc_handler; + +extern usb_desc cdc_desc; +extern usb_class cdc_class; + +/* function declarations */ +/* receive CDC ACM data */ +void cdc_acm_data_receive(usb_dev *udev); +/* send CDC ACM data */ +void cdc_acm_data_send(usb_dev *udev); +/* check cdc acm is ready for data transfer */ +uint8_t cdc_acm_check_ready(usb_dev *udev); + +#endif /* __CDC_ACM_CORE_H */ diff --git a/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbd_library/class/device/cdc/Source/cdc_acm_core.c b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbd_library/class/device/cdc/Source/cdc_acm_core.c new file mode 100644 index 0000000000..3f8d8409b5 --- /dev/null +++ b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbd_library/class/device/cdc/Source/cdc_acm_core.c @@ -0,0 +1,510 @@ +/*! + \file cdc_acm_core.c + \brief CDC ACM driver + + \version 2020-08-01, V3.0.0, firmware for GD32F30x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "usbd_transc.h" +#include "cdc_acm_core.h" + +#define USBD_VID 0x28E9U +#define USBD_PID 0x018AU + +/* note:it should use the C99 standard when compiling the below codes */ +/* USB standard device descriptor */ +usb_desc_dev cdc_dev_desc = +{ + .header = + { + .bLength = USB_DEV_DESC_LEN, + .bDescriptorType = USB_DESCTYPE_DEV, + }, + .bcdUSB = 0x0200U, + .bDeviceClass = USB_CLASS_CDC, + .bDeviceSubClass = 0x00U, + .bDeviceProtocol = 0x00U, + .bMaxPacketSize0 = USBD_EP0_MAX_SIZE, + .idVendor = USBD_VID, + .idProduct = USBD_PID, + .bcdDevice = 0x0100U, + .iManufacturer = STR_IDX_MFC, + .iProduct = STR_IDX_PRODUCT, + .iSerialNumber = STR_IDX_SERIAL, + .bNumberConfigurations = USBD_CFG_MAX_NUM, +}; + +/* USB device configuration descriptor */ +usb_cdc_desc_config_set cdc_config_desc = +{ + .config = + { + .header = + { + .bLength = sizeof(usb_desc_config), + .bDescriptorType = USB_DESCTYPE_CONFIG, + }, + .wTotalLength = USB_CDC_ACM_CONFIG_DESC_SIZE, + .bNumInterfaces = 0x02U, + .bConfigurationValue = 0x01U, + .iConfiguration = 0x00U, + .bmAttributes = 0x80U, + .bMaxPower = 0x32U + }, + + .cmd_itf = + { + .header = + { + .bLength = sizeof(usb_desc_itf), + .bDescriptorType = USB_DESCTYPE_ITF + }, + .bInterfaceNumber = 0x00U, + .bAlternateSetting = 0x00U, + .bNumEndpoints = 0x01U, + .bInterfaceClass = USB_CLASS_CDC, + .bInterfaceSubClass = USB_CDC_SUBCLASS_ACM, + .bInterfaceProtocol = USB_CDC_PROTOCOL_AT, + .iInterface = 0x00U + }, + + .cdc_header = + { + .header = + { + .bLength = sizeof(usb_desc_header_func), + .bDescriptorType = USB_DESCTYPE_CS_INTERFACE + }, + .bDescriptorSubtype = 0x00U, + .bcdCDC = 0x0110U + }, + + .cdc_call_managment = + { + .header = + { + .bLength = sizeof(usb_desc_call_managment_func), + .bDescriptorType = USB_DESCTYPE_CS_INTERFACE + }, + .bDescriptorSubtype = 0x01U, + .bmCapabilities = 0x00U, + .bDataInterface = 0x01U + }, + + .cdc_acm = + { + .header = + { + .bLength = sizeof(usb_desc_acm_func), + .bDescriptorType = USB_DESCTYPE_CS_INTERFACE + }, + .bDescriptorSubtype = 0x02U, + .bmCapabilities = 0x02U, + }, + + .cdc_union = + { + .header = + { + .bLength = sizeof(usb_desc_union_func), + .bDescriptorType = USB_DESCTYPE_CS_INTERFACE + }, + .bDescriptorSubtype = 0x06U, + .bMasterInterface = 0x00U, + .bSlaveInterface0 = 0x01U, + }, + + .cdc_cmd_endpoint = + { + .header = + { + .bLength = sizeof(usb_desc_ep), + .bDescriptorType = USB_DESCTYPE_EP, + }, + .bEndpointAddress = CDC_CMD_EP, + .bmAttributes = USB_EP_ATTR_INT, + .wMaxPacketSize = CDC_ACM_CMD_PACKET_SIZE, + .bInterval = 0x0AU + }, + + .cdc_data_interface = + { + .header = + { + .bLength = sizeof(usb_desc_itf), + .bDescriptorType = USB_DESCTYPE_ITF, + }, + .bInterfaceNumber = 0x01U, + .bAlternateSetting = 0x00U, + .bNumEndpoints = 0x02U, + .bInterfaceClass = USB_CLASS_DATA, + .bInterfaceSubClass = 0x00U, + .bInterfaceProtocol = USB_CDC_PROTOCOL_NONE, + .iInterface = 0x00U + }, + + .cdc_out_endpoint = + { + .header = + { + .bLength = sizeof(usb_desc_ep), + .bDescriptorType = USB_DESCTYPE_EP, + }, + .bEndpointAddress = CDC_OUT_EP, + .bmAttributes = USB_EP_ATTR_BULK, + .wMaxPacketSize = CDC_ACM_DATA_PACKET_SIZE, + .bInterval = 0x00U + }, + + .cdc_in_endpoint = + { + .header = + { + .bLength = sizeof(usb_desc_ep), + .bDescriptorType = USB_DESCTYPE_EP + }, + .bEndpointAddress = CDC_IN_EP, + .bmAttributes = USB_EP_ATTR_BULK, + .wMaxPacketSize = CDC_ACM_DATA_PACKET_SIZE, + .bInterval = 0x00U + } +}; + +/* USB language ID descriptor */ +static usb_desc_LANGID usbd_language_id_desc = +{ + .header = + { + .bLength = sizeof(usb_desc_LANGID), + .bDescriptorType = USB_DESCTYPE_STR, + }, + .wLANGID = ENG_LANGID +}; + +/* USB manufacture string */ +static usb_desc_str manufacturer_string = +{ + .header = + { + .bLength = USB_STRING_LEN(10U), + .bDescriptorType = USB_DESCTYPE_STR, + }, + .unicode_string = {'G', 'i', 'g', 'a', 'D', 'e', 'v', 'i', 'c', 'e'} +}; + +/* USB product string */ +static usb_desc_str product_string = +{ + .header = + { + .bLength = USB_STRING_LEN(12U), + .bDescriptorType = USB_DESCTYPE_STR, + }, + .unicode_string = {'G', 'D', '3', '2', '-', 'C', 'D', 'C', '_', 'A', 'C', 'M'} +}; + +/* USBD serial string */ +static usb_desc_str serial_string = +{ + .header = + { + .bLength = USB_STRING_LEN(12U), + .bDescriptorType = USB_DESCTYPE_STR, + } +}; + +/* USB string descriptor set */ +uint8_t* usbd_cdc_strings[] = +{ + [STR_IDX_LANGID] = (uint8_t *)&usbd_language_id_desc, + [STR_IDX_MFC] = (uint8_t *)&manufacturer_string, + [STR_IDX_PRODUCT] = (uint8_t *)&product_string, + [STR_IDX_SERIAL] = (uint8_t *)&serial_string +}; + +usb_desc cdc_desc = { + .dev_desc = (uint8_t *)&cdc_dev_desc, + .config_desc = (uint8_t *)&cdc_config_desc, + .strings = usbd_cdc_strings +}; + +/* local function prototypes ('static') */ +static uint8_t cdc_acm_init (usb_dev *udev, uint8_t config_index); +static uint8_t cdc_acm_deinit (usb_dev *udev, uint8_t config_index); +static uint8_t cdc_acm_req_handler (usb_dev *udev, usb_req *req); +static uint8_t cdc_acm_ctlx_out (usb_dev *udev); +static void cdc_acm_data_in (usb_dev *udev, uint8_t ep_num); +static void cdc_acm_data_out (usb_dev *udev, uint8_t ep_num); + +usb_class cdc_class = { + .req_cmd = NO_CMD, + + .init = cdc_acm_init, + .deinit = cdc_acm_deinit, + .req_process = cdc_acm_req_handler, + .ctlx_out = cdc_acm_ctlx_out, + .data_in = cdc_acm_data_in, + .data_out = cdc_acm_data_out +}; + +/*! + \brief receive CDC ACM data + \param[in] udev: pointer to USB device instance + \param[out] none + \retval USB device operation status +*/ +void cdc_acm_data_receive(usb_dev *udev) +{ + usb_cdc_handler *cdc = (usb_cdc_handler *)udev->class_data[CDC_COM_INTERFACE]; + + cdc->packet_receive = 0U; + cdc->pre_packet_send = 0U; + + usbd_ep_recev(udev, CDC_OUT_EP, (uint8_t*)(cdc->data), USB_CDC_RX_LEN); +} + +/*! + \brief send CDC ACM data + \param[in] udev: pointer to USB device instance + \param[out] none + \retval USB device operation status +*/ +void cdc_acm_data_send (usb_dev *udev) +{ + usb_cdc_handler *cdc = (usb_cdc_handler *)udev->class_data[CDC_COM_INTERFACE]; + uint32_t data_len = cdc->receive_length; + + if ((0U != data_len) && (1U == cdc->packet_sent)) { + cdc->packet_sent = 0U; + usbd_ep_send(udev, CDC_IN_EP, (uint8_t*)(cdc->data), (uint16_t)data_len); + cdc->receive_length = 0U; + } +} + +/*! + \brief check cdc acm is ready for data transfer + \param[in] udev: pointer to USB device instance + \param[out] none + \retval 0 if CDC is ready, 5 otherwise +*/ +uint8_t cdc_acm_check_ready(usb_dev *udev) +{ + if (udev->class_data[CDC_COM_INTERFACE] != NULL) { + usb_cdc_handler *cdc = (usb_cdc_handler *)udev->class_data[CDC_COM_INTERFACE]; + + if ((1U == cdc->packet_receive) && (1U == cdc->pre_packet_send)) { + return 0U; + } + } + + return 5U; +} + +/*! + \brief initialize the CDC ACM device + \param[in] udev: pointer to USB device instance + \param[in] config_index: configuration index + \param[out] none + \retval USB device operation status +*/ +static uint8_t cdc_acm_init (usb_dev *udev, uint8_t config_index) +{ + static usb_cdc_handler cdc_handler; + + /* initialize the data endpoints */ + usbd_ep_init(udev, EP_BUF_SNG, BULK_TX_ADDR, &(cdc_config_desc.cdc_in_endpoint)); + usbd_ep_init(udev, EP_BUF_SNG, BULK_RX_ADDR, &(cdc_config_desc.cdc_out_endpoint)); + + /* initialize the command endpoint */ + usbd_ep_init(udev, EP_BUF_SNG, INT_TX_ADDR, &(cdc_config_desc.cdc_cmd_endpoint)); + + udev->ep_transc[EP_ID(CDC_IN_EP)][TRANSC_IN] = cdc_class.data_in; + udev->ep_transc[CDC_OUT_EP][TRANSC_OUT] = cdc_class.data_out; + + /* initialize cdc handler structure */ + cdc_handler.packet_receive = 0U; + cdc_handler.packet_sent = 1U; + cdc_handler.pre_packet_send = 1U; + cdc_handler.receive_length = 0U; + + cdc_handler.line_coding = (acm_line){ + .dwDTERate = 115200U, + .bCharFormat = 0U, + .bParityType = 0U, + .bDataBits = 0x08U + }; + + udev->class_data[CDC_COM_INTERFACE] = (void *)&cdc_handler; + + return USBD_OK; +} + +/*! + \brief de-initialize the CDC ACM device + \param[in] udev: pointer to USB device instance + \param[in] config_index: configuration index + \param[out] none + \retval USB device operation status +*/ +static uint8_t cdc_acm_deinit (usb_dev *udev, uint8_t config_index) +{ + /* deinitialize the data endpoints */ + usbd_ep_deinit(udev, CDC_IN_EP); + usbd_ep_deinit(udev, CDC_OUT_EP); + + /* deinitialize the command endpoint */ + usbd_ep_deinit(udev, CDC_CMD_EP); + + return USBD_OK; +} + +/*! + \brief command data received on control endpoint + \param[in] udev: pointer to USB device instance + \param[out] none + \retval USB device operation status +*/ +static uint8_t cdc_acm_ctlx_out (usb_dev *udev) +{ + usb_cdc_handler *cdc = (usb_cdc_handler *)udev->class_data[CDC_COM_INTERFACE]; + + if (NO_CMD != udev->class_core->req_cmd) { + cdc->packet_receive = 1U; + cdc->pre_packet_send = 1U; + + udev->class_core->req_cmd = NO_CMD; + } + + return USBD_OK; +} + + +/*! + \brief handle CDC ACM data in transaction + \param[in] udev: pointer to USB device instance + \param[in] ep_num: endpoint number + \param[out] none + \retval USB device operation status +*/ +static void cdc_acm_data_in (usb_dev *udev, uint8_t ep_num) +{ + usb_transc *transc = &udev->transc_in[ep_num]; + usb_cdc_handler *cdc = (usb_cdc_handler *)udev->class_data[CDC_COM_INTERFACE]; + + if (transc->xfer_count == transc->max_len) { + usbd_ep_send(udev, EP_ID(ep_num), NULL, 0U); + } else { + cdc->packet_sent = 1U; + cdc->pre_packet_send = 1U; + } +} + +/*! + \brief handle CDC ACM data out transaction + \param[in] udev: pointer to USB device instance + \param[in] ep_num: endpoint number + \param[out] none + \retval USB device operation status +*/ +static void cdc_acm_data_out (usb_dev *udev, uint8_t ep_num) +{ + usb_cdc_handler *cdc = (usb_cdc_handler *)udev->class_data[CDC_COM_INTERFACE]; + + cdc->packet_receive = 1U; + + cdc->receive_length = udev->transc_out[ep_num].xfer_count; +} + +/*! + \brief handle the CDC ACM class-specific requests + \param[in] udev: pointer to USB device instance + \param[in] req: device class-specific request + \param[out] none + \retval USB device operation status +*/ +static uint8_t cdc_acm_req_handler (usb_dev *udev, usb_req *req) +{ + uint8_t status = REQ_NOTSUPP, noti_buf[10] = {0U}; + usb_cdc_handler *cdc = (usb_cdc_handler *)udev->class_data[CDC_COM_INTERFACE]; + + acm_notification *notif = (void *)noti_buf; + + switch (req->bRequest) { + case SEND_ENCAPSULATED_COMMAND: + break; + + case GET_ENCAPSULATED_RESPONSE: + break; + + case SET_COMM_FEATURE: + break; + + case GET_COMM_FEATURE: + break; + + case CLEAR_COMM_FEATURE: + break; + + case SET_LINE_CODING: + /* set the value of the current command to be processed */ + udev->class_core->req_cmd = req->bRequest; + + usb_transc_config(&udev->transc_out[0U], (uint8_t *)&cdc->line_coding, req->wLength, 0U); + + status = REQ_SUPP; + break; + + case GET_LINE_CODING: + usb_transc_config(&udev->transc_in[0U], (uint8_t *)&cdc->line_coding, 7U, 0U); + + status = REQ_SUPP; + break; + + case SET_CONTROL_LINE_STATE: + notif->bmRequestType = 0xA1U; + notif->bNotification = USB_CDC_NOTIFY_SERIAL_STATE; + notif->wIndex = 0U; + notif->wValue = 0U; + notif->wLength = 2U; + noti_buf[8] = (uint8_t)req->wValue & 3U; + noti_buf[9] = 0U; + + status = REQ_SUPP; + break; + + case SEND_BREAK: + break; + + default: + break; + } + + return status; +} diff --git a/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbd_library/class/device/dfu/Include/dfu_core.h b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbd_library/class/device/dfu/Include/dfu_core.h new file mode 100644 index 0000000000..933fb3bf64 --- /dev/null +++ b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbd_library/class/device/dfu/Include/dfu_core.h @@ -0,0 +1,179 @@ +/*! + \file dfu_core.h + \brief the header file of USB DFU device class core functions + + \version 2020-08-01, V3.0.0, firmware for GD32F30x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef __DFU_CORE_H +#define __DFU_CORE_H + +#include "usbd_enum.h" + +/* DFU class code */ +#define USB_DFU_CLASS 0xFEU + +/* DFU subclass code */ +#define USB_DFU_SUBCLASS_UPGRADE 0x01U + +/* DFU protocol code */ +#define USB_DFU_PROTOCL_RUNTIME 0x01U +#define USB_DFU_PROTOCL_DFU 0x02U + +/* manifestation state */ +#define MANIFEST_COMPLETE 0x00U +#define MANIFEST_IN_PROGRESS 0x01U + +/* DFU attributes code */ +#define USB_DFU_CAN_DOWNLOAD 0x01U +#define USB_DFU_CAN_UPLOAD 0x02U +#define USB_DFU_MANIFEST_TOLERANT 0x04U +#define USB_DFU_WILL_DETACH 0x08U + +/* special commands with download request */ +#define GET_COMMANDS 0x00U +#define SET_ADDRESS_POINTER 0x21U +#define ERASE 0x41U + +/* memory operation command */ +#define CMD_ERASE 0U +#define CMD_WRITE 1U + +#define _BYTE1(x) (uint8_t)((x) & 0xFFU) /*!< addressing cycle 1st byte */ +#define _BYTE2(x) (uint8_t)(((x) & 0xFF00U) >> 8U) /*!< addressing cycle 2nd byte */ +#define _BYTE3(x) (uint8_t)(((x) & 0xFF0000U) >> 16U) /*!< addressing cycle 3rd byte */ + +#define SET_POLLING_TIMEOUT(x) do { \ + dfu->bwPollTimeout0 = _BYTE1(x);\ + dfu->bwPollTimeout1 = _BYTE2(x);\ + dfu->bwPollTimeout2 = _BYTE3(x);\ + } while(0) + +#define FLASH_ERASE_TIMEOUT 60U +#define FLASH_WRITE_TIMEOUT 80U + +/* bit detach capable = bit 3 in bmAttributes field */ +#define DFU_DETACH_MASK (uint8_t)(0x10U) +#define USB_DFU_CONFIG_DESC_SIZE (18U + (9U * USBD_ITF_MAX_NUM)) +#define DFU_DESC_TYPE 0x21U + +/* DFU device state enumeration */ +typedef enum { + STATE_APP_IDLE = 0x00U, + 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 +} dfu_state; + +/* DFU device status enumeration */ +typedef enum { + STATUS_OK = 0x00U, + STATUS_ERR_TARGET, + STATUS_ERR_FILE, + STATUS_ERR_WRITE, + STATUS_ERR_ERASE, + STATUS_ERR_CHECK_ERASED, + STATUS_ERR_PROG, + STATUS_ERR_VERIFY, + STATUS_ERR_ADDRESS, + STATUS_ERR_NOTDONE, + STATUS_ERR_FIRMWARE, + STATUS_ERR_VENDOR, + STATUS_ERR_USBR, + STATUS_ERR_POR, + STATUS_ERR_UNKNOWN, + STATUS_ERR_STALLEDPKT +} dfu_status; + +/* DFU class-specific requests enumeration */ +typedef enum { + DFU_DETACH = 0U, + DFU_DNLOAD, + DFU_UPLOAD, + DFU_GETSTATUS, + DFU_CLRSTATUS, + DFU_GETSTATE, + DFU_ABORT, + DFU_REQ_MAX +} dfu_requests; + +#pragma pack(1) + +/* USB DFU function descriptor struct */ +typedef struct +{ + usb_desc_header header; /*!< descriptor header, including type and size */ + uint8_t bmAttributes; /*!< DFU attributes */ + uint16_t wDetachTimeOut; /*!< time, in milliseconds, that the device will wait after receipt of the DFU_DETACH request. If */ + uint16_t wTransferSize; /*!< maximum number of bytes that the device can accept per control-write transaction */ + uint16_t bcdDFUVersion; /*!< numeric expression identifying the version of the DFU specification release. */ +} usb_desc_dfu_func; + +#pragma pack() + +/* USB configuration descriptor struct */ +typedef struct +{ + usb_desc_config config; + usb_desc_itf dfu_itf; + usb_desc_dfu_func dfu_func; +} usb_dfu_desc_config_set; + +/* USB DFU handler struct */ +typedef struct +{ + uint8_t bStatus; + uint8_t bwPollTimeout0; + uint8_t bwPollTimeout1; + uint8_t bwPollTimeout2; + uint8_t bState; + uint8_t iString; + + uint8_t manifest_state; + uint16_t data_len; + uint16_t block_num; + uint32_t base_addr; + + uint8_t buf[TRANSFER_SIZE]; +} usbd_dfu_handler; + +typedef void (*app_func) (void); + +extern usb_desc dfu_desc; +extern usb_class dfu_class; + +#endif /* __DFU_CORE_H */ diff --git a/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbd_library/class/device/dfu/Source/dfu_core.c b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbd_library/class/device/dfu/Source/dfu_core.c new file mode 100644 index 0000000000..c1e42597b4 --- /dev/null +++ b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbd_library/class/device/dfu/Source/dfu_core.c @@ -0,0 +1,674 @@ +/*! + \file dfu_core.c + \brief USB DFU device class core functions + + \version 2020-08-01, V3.0.0, firmware for GD32F30x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "dfu_core.h" +#include "systick.h" + +#include + +#define USBD_VID 0x28E9U +#define USBD_PID 0x0189U + +/* local function prototypes ('static') */ +static uint8_t dfu_init (usb_dev *udev, uint8_t config_index); +static uint8_t dfu_deinit (usb_dev *udev, uint8_t config_index); +static uint8_t dfu_req_handler (usb_dev *udev, usb_req *req); +static uint8_t dfu_ctlx_in (usb_dev *udev); + +/* DFU requests management functions */ +static void dfu_detach (usb_dev *udev, usb_req *req); +static void dfu_dnload (usb_dev *udev, usb_req *req); +static void dfu_upload (usb_dev *udev, usb_req *req); +static void dfu_getstatus (usb_dev *udev, usb_req *req); +static void dfu_clrstatus (usb_dev *udev, usb_req *req); +static void dfu_getstate (usb_dev *udev, usb_req *req); +static void dfu_abort (usb_dev *udev, usb_req *req); +static void dfu_mode_leave (usb_dev *udev); +static uint8_t dfu_getstatus_complete (usb_dev *udev); + +static void (*dfu_request_process[])(usb_dev *udev, usb_req *req) = +{ + [DFU_DETACH] = dfu_detach, + [DFU_DNLOAD] = dfu_dnload, + [DFU_UPLOAD] = dfu_upload, + [DFU_GETSTATUS] = dfu_getstatus, + [DFU_CLRSTATUS] = dfu_clrstatus, + [DFU_GETSTATE] = dfu_getstate, + [DFU_ABORT] = dfu_abort +}; + +/* note:it should use the c99 standard when compiling the below codes */ +/* USB standard device descriptor */ +usb_desc_dev dfu_dev_desc = +{ + .header = + { + .bLength = USB_DEV_DESC_LEN, + .bDescriptorType = USB_DESCTYPE_DEV + }, + .bcdUSB = 0x0200U, + .bDeviceClass = 0x00U, + .bDeviceSubClass = 0x00U, + .bDeviceProtocol = 0x00U, + .bMaxPacketSize0 = USBD_EP0_MAX_SIZE, + .idVendor = USBD_VID, + .idProduct = USBD_PID, + .bcdDevice = 0x0100U, + .iManufacturer = STR_IDX_MFC, + .iProduct = STR_IDX_PRODUCT, + .iSerialNumber = STR_IDX_SERIAL, + .bNumberConfigurations = USBD_CFG_MAX_NUM +}; + +/* USB device configuration descriptor */ +usb_dfu_desc_config_set dfu_config_desc = +{ + .config = + { + .header = + { + .bLength = sizeof(usb_desc_config), + .bDescriptorType = USB_DESCTYPE_CONFIG + }, + .wTotalLength = USB_DFU_CONFIG_DESC_SIZE, + .bNumInterfaces = 0x01U, + .bConfigurationValue = 0x01U, + .iConfiguration = 0x00U, + .bmAttributes = 0x80U, + .bMaxPower = 0x32U + }, + + .dfu_itf = + { + .header = + { + .bLength = sizeof(usb_desc_itf), + .bDescriptorType = USB_DESCTYPE_ITF + }, + .bInterfaceNumber = 0x00U, + .bAlternateSetting = 0x00U, + .bNumEndpoints = 0x00U, + .bInterfaceClass = USB_DFU_CLASS, + .bInterfaceSubClass = USB_DFU_SUBCLASS_UPGRADE, + .bInterfaceProtocol = USB_DFU_PROTOCL_DFU, + .iInterface = 0x00U + }, + + .dfu_func = + { + .header = + { + .bLength = sizeof(usb_desc_dfu_func), + .bDescriptorType = DFU_DESC_TYPE + }, + .bmAttributes = USB_DFU_CAN_DOWNLOAD | USB_DFU_CAN_UPLOAD | USB_DFU_WILL_DETACH, + .wDetachTimeOut = 0x00FFU, + .wTransferSize = TRANSFER_SIZE, + .bcdDFUVersion = 0x011AU, + }, +}; + +/* USB language ID descriptor */ +static usb_desc_LANGID usbd_language_id_desc = +{ + .header = { + .bLength = sizeof(usb_desc_LANGID), + .bDescriptorType = USB_DESCTYPE_STR + }, + .wLANGID = ENG_LANGID +}; + +/* USB manufacture string */ +static usb_desc_str manufacturer_string = +{ + .header = + { + .bLength = USB_STRING_LEN(10U), + .bDescriptorType = USB_DESCTYPE_STR, + }, + .unicode_string = {'G', 'i', 'g', 'a', 'D', 'e', 'v', 'i', 'c', 'e'} +}; + +/* USB product string */ +static usb_desc_str product_string = +{ + .header = + { + .bLength = USB_STRING_LEN(12U), + .bDescriptorType = USB_DESCTYPE_STR, + }, + .unicode_string = {'G', 'D', '3', '2', '-', 'U', 'S', 'B', '_', 'D', 'F', 'U'} +}; + +/* USBD serial string */ +static usb_desc_str serial_string = +{ + .header = + { + .bLength = USB_STRING_LEN(2U), + .bDescriptorType = USB_DESCTYPE_STR, + } +}; + +/* USB config string */ +static usb_desc_str config_string = +{ + .header = + { + .bLength = USB_STRING_LEN(15U), + .bDescriptorType = USB_DESCTYPE_STR, + }, + .unicode_string = {'G', 'D', '3', '2', ' ', 'U', 'S', 'B', ' ', 'C', 'O', 'N', 'F', 'I', 'G'} +}; + +static usb_desc_str interface_string = +{ + .header = + { + .bLength = USB_STRING_LEN(15U), + .bDescriptorType = USB_DESCTYPE_STR, + }, + .unicode_string = {'@', 'I', 'n', 't', 'e', 'r', 'n', 'a', 'l', 'F', 'l', 'a', 's', 'h', ' ', '/', '0', 'x', '0', '8', '0', '0', + '0', '0', '0', '0', '/', '1', '6', '*', '0', '0', '1', 'K', 'a', ',', '4', '8', '*', '0', '0', '1', 'K', 'g'} +}; + +uint8_t* usbd_dfu_strings[] = +{ + [STR_IDX_LANGID] = (uint8_t *)&usbd_language_id_desc, + [STR_IDX_MFC] = (uint8_t *)&manufacturer_string, + [STR_IDX_PRODUCT] = (uint8_t *)&product_string, + [STR_IDX_SERIAL] = (uint8_t *)&serial_string, + [STR_IDX_CONFIG] = (uint8_t *)&config_string, + [STR_IDX_ITF] = (uint8_t *)&interface_string +}; + +usb_desc dfu_desc = { + .dev_desc = (uint8_t *)&dfu_dev_desc, + .config_desc = (uint8_t *)&dfu_config_desc, + .strings = usbd_dfu_strings +}; + +usb_class dfu_class = { + .init = dfu_init, + .deinit = dfu_deinit, + .req_process = dfu_req_handler, + .ctlx_in = dfu_ctlx_in +}; + +/*! + \brief initialize the USB DFU device + \param[in] udev: pointer to USB device instance + \param[in] config_index: configuration index + \param[out] none + \retval USB device operation status +*/ +static uint8_t dfu_init (usb_dev *udev, uint8_t config_index) +{ + static usbd_dfu_handler dfu_handler; + + /* unlock the internal flash */ + fmc_unlock(); + + systick_config(); + + memset((void *)&dfu_handler, 0, sizeof(usbd_dfu_handler)); + + dfu_handler.base_addr = APP_LOADED_ADDR; + dfu_handler.manifest_state = MANIFEST_COMPLETE; + dfu_handler.bState = STATE_DFU_IDLE; + dfu_handler.bStatus = STATUS_OK; + + udev->class_data[USBD_DFU_INTERFACE] = (void *)&dfu_handler; + + return USBD_OK; +} + +/*! + \brief de-initialize the USB DFU device + \param[in] udev: pointer to USB device instance + \param[in] config_index: configuration index + \param[out] none + \retval USB device operation status +*/ +static uint8_t dfu_deinit (usb_dev *udev, uint8_t config_index) +{ + usbd_dfu_handler *dfu = (usbd_dfu_handler *)udev->class_data[USBD_DFU_INTERFACE]; + + /* restore device default state */ + memset(udev->class_data[USBD_DFU_INTERFACE], 0, sizeof(usbd_dfu_handler)); + + dfu->bState = STATE_DFU_IDLE; + dfu->bStatus = STATUS_OK; + + /* lock the internal flash */ + fmc_lock(); + + return USBD_OK; +} + +/*! + \brief handle the USB DFU class-specific requests + \param[in] udev: pointer to USB device instance + \param[in] req: device class-specific request + \param[out] none + \retval USB device operation status +*/ +static uint8_t dfu_req_handler (usb_dev *udev, usb_req *req) +{ + if (req->bRequest < DFU_REQ_MAX) { + dfu_request_process[req->bRequest](udev, req); + } else { + return USBD_FAIL; + } + + return USBD_OK; +} + +/*! + \brief handle data stage + \param[in] udev: pointer to USB device instance + \param[out] none + \retval USB device operation status +*/ +static uint8_t dfu_ctlx_in (usb_dev *udev) +{ + dfu_getstatus_complete(udev); + + return USBD_OK; +} + +/*! + \brief handle data in stage in control endpoint 0 + \param[in] udev: pointer to USB device instance + \param[out] none + \retval USB device operation status + */ +static uint8_t dfu_getstatus_complete (usb_dev *udev) +{ + uint32_t addr; + + usbd_dfu_handler *dfu = (usbd_dfu_handler *)udev->class_data[USBD_DFU_INTERFACE]; + + if (STATE_DFU_DNBUSY == dfu->bState) { + /* decode the special command */ + if (0U == dfu->block_num) { + if (1U == dfu->data_len){ + if (GET_COMMANDS == dfu->buf[0]) { + /* no operation */ + } + } else if (5U == dfu->data_len) { + if (SET_ADDRESS_POINTER == dfu->buf[0]) { + /* set flash operation address */ + dfu->base_addr = *(uint32_t *)(dfu->buf + 1U); + } else if (ERASE == dfu->buf[0]) { + dfu->base_addr = *(uint32_t *)(dfu->buf + 1U); + + fmc_page_erase(dfu->base_addr); + } else { + /* no operation */ + } + } else { + /* no operation */ + } + } else if (dfu->block_num > 1U) { /* regular download command */ + /* preform the write operation */ + uint32_t idx = 0U; + + /* decode the required address */ + addr = (dfu->block_num - 2U) * TRANSFER_SIZE + dfu->base_addr; + + if (dfu->data_len & 0x03U) { /* not an aligned data */ + for (idx = dfu->data_len; idx < ((dfu->data_len & 0xFFFCU) + 4U); idx++) { + dfu->buf[idx] = 0xFFU; + } + } + + /* data received are word multiple */ + for (idx = 0U; idx < dfu->data_len; idx += 4U) { + fmc_word_program(addr, *(uint32_t *)(dfu->buf + idx)); + + addr += 4U; + } + + dfu->block_num = 0U; + } else { + /* no operation */ + } + + dfu->data_len = 0U; + + /* update the device state and poll timeout */ + dfu->bState = STATE_DFU_DNLOAD_SYNC; + + return USBD_OK; + } else if (STATE_DFU_MANIFEST == dfu->bState) { /* manifestation in progress */ + /* start leaving DFU mode */ + dfu_mode_leave(udev); + } else { + /* no operation */ + } + + return USBD_OK; +} + +/*! + \brief handle the DFU_DETACH request + \param[in] udev: pointer to USB device instance + \param[in] req: DFU class request + \param[out] none + \retval none. +*/ +static void dfu_detach(usb_dev *udev, usb_req *req) +{ + usbd_dfu_handler *dfu = (usbd_dfu_handler *)udev->class_data[USBD_DFU_INTERFACE]; + + switch (dfu->bState) { + case STATE_DFU_IDLE: + case STATE_DFU_DNLOAD_SYNC: + case STATE_DFU_DNLOAD_IDLE: + case STATE_DFU_MANIFEST_SYNC: + case STATE_DFU_UPLOAD_IDLE: + dfu->bStatus = STATUS_OK; + dfu->bState = STATE_DFU_IDLE; + dfu->iString = 0U; /* iString */ + + dfu->block_num = 0U; + dfu->data_len = 0U; + break; + + default: + break; + } + + /* check the detach capability in the DFU functional descriptor */ + if (dfu_config_desc.dfu_func.wDetachTimeOut & DFU_DETACH_MASK) { + usbd_disconnect(udev); + + usbd_connect(udev); + } else { + /* wait for the period of time specified in detach request */ + delay_1ms(4U); + } +} + +/*! + \brief handle the DFU_DNLOAD request + \param[in] udev: pointer to USB device instance + \param[in] req: DFU class request + \param[out] none + \retval none +*/ +static void dfu_dnload(usb_dev *udev, usb_req *req) +{ + usb_transc *transc = &udev->transc_out[0]; + + usbd_dfu_handler *dfu = (usbd_dfu_handler *)udev->class_data[USBD_DFU_INTERFACE]; + + switch (dfu->bState) { + case STATE_DFU_IDLE: + case STATE_DFU_DNLOAD_IDLE: + if (req->wLength > 0U) { + /* update the global length and block number */ + dfu->block_num = req->wValue; + dfu->data_len = req->wLength; + + dfu->bState = STATE_DFU_DNLOAD_SYNC; + + transc->xfer_len = dfu->data_len; + transc->xfer_buf = dfu->buf; + transc->xfer_count = 0U; + } else { + dfu->manifest_state = MANIFEST_IN_PROGRESS; + dfu->bState = STATE_DFU_MANIFEST_SYNC; + } + break; + + default: + break; + } +} + +/*! + \brief handles the DFU UPLOAD request. + \param[in] udev: pointer to USB device instance + \param[in] req: DFU class request + \param[out] none + \retval none +*/ +static void dfu_upload (usb_dev *udev, usb_req *req) +{ + uint8_t *phy_addr = NULL; + uint32_t addr = 0U; + + usbd_dfu_handler *dfu = (usbd_dfu_handler *)udev->class_data[USBD_DFU_INTERFACE]; + + if(req->wLength <= 0U) { + dfu->bState = STATE_DFU_IDLE; + + return; + } + + usb_transc *transc = &udev->transc_in[0]; + + switch (dfu->bState) { + case STATE_DFU_IDLE: + case STATE_DFU_UPLOAD_IDLE: + /* update the global length and block number */ + dfu->block_num = req->wValue; + dfu->data_len = req->wLength; + + /* DFU get command */ + if (0U == dfu->block_num) { + /* update the state machine */ + dfu->bState = (dfu->data_len > 3U) ? STATE_DFU_IDLE : STATE_DFU_UPLOAD_IDLE; + + /* store the values of all supported commands */ + dfu->buf[0] = GET_COMMANDS; + dfu->buf[1] = SET_ADDRESS_POINTER; + dfu->buf[2] = ERASE; + + /* send the status data over EP0 */ + transc->xfer_buf = &(dfu->buf[0]); + transc->xfer_len = 3U; + } else if (dfu->block_num > 1U) { + dfu->bState = STATE_DFU_UPLOAD_IDLE; + + /* change is accelerated */ + addr = (dfu->block_num - 2U) * TRANSFER_SIZE + dfu->base_addr; + + /* return the physical address where data are stored */ + phy_addr = (uint8_t *)(addr); + + /* send the status data over EP0 */ + transc->xfer_buf = phy_addr; + transc->xfer_len = dfu->data_len; + } else { + dfu->bState = STATUS_ERR_STALLEDPKT; + } + break; + + default: + dfu->data_len = 0U; + dfu->block_num = 0U; + break; + } +} + +/*! + \brief handle the DFU_GETSTATUS request + \param[in] udev: pointer to USB device instance + \param[in] req: DFU class request + \param[out] none + \retval none +*/ +static void dfu_getstatus (usb_dev *udev, usb_req *req) +{ + usb_transc *transc = &udev->transc_in[0]; + + usbd_dfu_handler *dfu = (usbd_dfu_handler *)udev->class_data[USBD_DFU_INTERFACE]; + + switch (dfu->bState) { + case STATE_DFU_DNLOAD_SYNC: + if (0U != dfu->data_len) { + dfu->bState = STATE_DFU_DNBUSY; + + if (0U == dfu->block_num) { + if (ERASE == dfu->buf[0]) { + SET_POLLING_TIMEOUT(FLASH_ERASE_TIMEOUT); + } else { + SET_POLLING_TIMEOUT(FLASH_WRITE_TIMEOUT); + } + } + } else { + dfu->bState = STATE_DFU_DNLOAD_IDLE; + } + break; + + case STATE_DFU_MANIFEST_SYNC: + if (MANIFEST_IN_PROGRESS == dfu->manifest_state) { + dfu->bState = STATE_DFU_MANIFEST; + dfu->bwPollTimeout0 = 1U; + } else if ((MANIFEST_COMPLETE == dfu->manifest_state) && \ + (dfu_config_desc.dfu_func.bmAttributes & 0x04U)){ + dfu->bState = STATE_DFU_IDLE; + dfu->bwPollTimeout0 = 0U; + } else { + /* no operation */ + } + break; + + default: + break; + } + + /* send the status data of DFU interface to host over EP0 */ + transc->xfer_buf = (uint8_t *)&(dfu->bStatus); + transc->xfer_len = 6U; +} + +/*! + \brief handle the DFU_CLRSTATUS request + \param[in] udev: pointer to USB device instance + \param[in] req: DFU class request + \param[out] none + \retval none +*/ +static void dfu_clrstatus (usb_dev *udev, usb_req *req) +{ + usbd_dfu_handler *dfu = (usbd_dfu_handler *)udev->class_data[USBD_DFU_INTERFACE]; + + if (STATE_DFU_ERROR == dfu->bState) { + dfu->bStatus = STATUS_OK; + dfu->bState = STATE_DFU_IDLE; + } else { + /* state error */ + dfu->bStatus = STATUS_ERR_UNKNOWN; + dfu->bState = STATE_DFU_ERROR; + } + + dfu->iString = 0U; /* iString: index = 0 */ +} + +/*! + \brief handle the DFU_GETSTATE request + \param[in] udev: pointer to USB device instance + \param[in] req: DFU class request + \param[out] none + \retval none +*/ +static void dfu_getstate (usb_dev *udev, usb_req *req) +{ + usb_transc *transc = &udev->transc_in[0]; + + usbd_dfu_handler *dfu = (usbd_dfu_handler *)udev->class_data[USBD_DFU_INTERFACE]; + + /* send the current state of the DFU interface to host */ + transc->xfer_buf = &(dfu->bState); + transc->xfer_len = 1U; +} + +/*! + \brief handle the DFU_ABORT request + \param[in] udev: pointer to USB device instance + \param[in] req: DFU class request + \param[out] none + \retval none +*/ +static void dfu_abort (usb_dev *udev, usb_req *req) +{ + usbd_dfu_handler *dfu = (usbd_dfu_handler *)udev->class_data[USBD_DFU_INTERFACE]; + + switch (dfu->bState){ + case STATE_DFU_IDLE: + case STATE_DFU_DNLOAD_SYNC: + case STATE_DFU_DNLOAD_IDLE: + case STATE_DFU_MANIFEST_SYNC: + case STATE_DFU_UPLOAD_IDLE: + dfu->bStatus = STATUS_OK; + dfu->bState = STATE_DFU_IDLE; + dfu->iString = 0U; /* iString: index = 0 */ + + dfu->block_num = 0U; + dfu->data_len = 0U; + break; + + default: + break; + } +} + +/*! + \brief leave DFU mode and reset device to jump to user loaded code + \param[in] udev: pointer to USB device instance + \param[out] none + \retval none +*/ +static void dfu_mode_leave (usb_dev *udev) +{ + usbd_dfu_handler *dfu = (usbd_dfu_handler *)udev->class_data[USBD_DFU_INTERFACE]; + + dfu->manifest_state = MANIFEST_COMPLETE; + + if (dfu_config_desc.dfu_func.bmAttributes & 0x04U) { + dfu->bState = STATE_DFU_MANIFEST_SYNC; + } else { + dfu->bState = STATE_DFU_MANIFEST_WAIT_RESET; + + /* lock the internal flash */ + fmc_lock(); + + /* generate system reset to allow jumping to the user code */ + NVIC_SystemReset(); + } +} diff --git a/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbd_library/class/device/hid/Include/custom_hid_core.h b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbd_library/class/device/hid/Include/custom_hid_core.h new file mode 100644 index 0000000000..b650f0738c --- /dev/null +++ b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbd_library/class/device/hid/Include/custom_hid_core.h @@ -0,0 +1,67 @@ +/*! + \file custom_hid_core.h + \brief definitions for HID core + + \version 2020-08-01, V3.0.0, firmware for GD32F30x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef __CUSTOM_HID_CORE_H +#define __CUSTOM_HID_CORE_H + +#include "usbd_enum.h" +#include "usb_hid.h" + +#define DESC_LEN_REPORT 96U +#define DESC_LEN_CONFIG 41U + +#define MAX_PERIPH_NUM 4U + +typedef struct { + uint8_t data[2]; + + uint8_t reportID; + uint8_t idlestate; + uint8_t protocol; +} custom_hid_handler; + +typedef struct { + void (*periph_config[MAX_PERIPH_NUM])(void); +} hid_fop_handler; + +extern usb_desc custom_hid_desc; +extern usb_class custom_hid_class; + +/* function declarations */ +/* register HID interface operation functions */ +uint8_t custom_hid_itfop_register (usb_dev *udev, hid_fop_handler *hid_fop); +/* send custom HID report */ +uint8_t custom_hid_report_send (usb_dev *udev, uint8_t *report, uint16_t len); + +#endif /* __CUSTOM_HID_CORE_H */ diff --git a/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbd_library/class/device/hid/Include/standard_hid_core.h b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbd_library/class/device/hid/Include/standard_hid_core.h new file mode 100644 index 0000000000..1b00045a61 --- /dev/null +++ b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbd_library/class/device/hid/Include/standard_hid_core.h @@ -0,0 +1,66 @@ +/*! + \file standard_hid_core.h + \brief definitions for HID core + + \version 2020-08-01, V3.0.0, firmware for GD32F30x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef __STANDARD_HID_CORE_H +#define __STANDARD_HID_CORE_H + +#include "usbd_enum.h" +#include "usb_hid.h" + +#define USB_HID_CONFIG_DESC_LEN 0x22U +#define USB_HID_REPORT_DESC_LEN 0x2EU + +typedef struct { + uint32_t protocol; + uint32_t idle_state; + + uint8_t data[HID_IN_PACKET]; + __IO uint8_t prev_transfer_complete; +} standard_hid_handler; + +typedef struct { + void (*hid_itf_config) (void); + void (*hid_itf_data_process) (usb_dev *udev); +} hid_fop_handler; + +extern usb_desc hid_desc; +extern usb_class hid_class; + +/* function declarations */ +/* register HID interface operation functions */ +uint8_t hid_itfop_register (usb_dev *udev, hid_fop_handler *hid_fop); +/* send HID report */ +uint8_t hid_report_send (usb_dev *udev, uint8_t *report, uint16_t len); + +#endif /* __STANDARD_HID_CORE_H */ diff --git a/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbd_library/class/device/hid/Include/std_hid_mouse_core.h b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbd_library/class/device/hid/Include/std_hid_mouse_core.h new file mode 100644 index 0000000000..91a5f5f20d --- /dev/null +++ b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbd_library/class/device/hid/Include/std_hid_mouse_core.h @@ -0,0 +1,69 @@ +/*! + \file std_hid_mouse_core.h + \brief definitions for HID mouse core + + \version 2020-08-01, V3.0.0, firmware for GD32F30x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef __STD_HID_MOUSE_CORE_H +#define __STD_HID_MOUSE_CORE_H + +#include "usbd_enum.h" +#include "usb_hid.h" + +#define USB_HID_CONFIG_DESC_LEN 0x22U +#define USB_HID_REPORT_DESC_LEN 0x34U + +#define MOUSE_LEFT_BUTTON 0x01U +#define MOUSE_RIGHT_BUTTON 0x02U + +typedef struct { + uint32_t protocol; + uint32_t idle_state; + + uint8_t data[HID_IN_PACKET]; + __IO uint8_t prev_transfer_complete; +} standard_mice_handler; + +typedef struct { + void (*mice_itf_config) (void); + void (*mice_itf_data_process) (usb_dev *udev); +} mice_fop_handler; + +extern usb_desc hid_mouse_desc; +extern usb_class hid_class; + +/* function declarations */ +/* register HID interface operation functions */ +uint8_t hid_itfop_register (usb_dev *udev, mice_fop_handler *hid_fop); +/* send mouse report */ +uint8_t hid_report_send (usb_dev *udev, uint8_t *report, uint16_t len); + +#endif /* __STD_HID_MOUSE_CORE_H */ diff --git a/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbd_library/class/device/hid/Include/usb_hid.h b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbd_library/class/device/hid/Include/usb_hid.h new file mode 100644 index 0000000000..0492ceec80 --- /dev/null +++ b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbd_library/class/device/hid/Include/usb_hid.h @@ -0,0 +1,83 @@ +/*! + \file usb_hid.h + \brief definitions for the USB HID class + + \version 2020-08-01, V3.0.0, firmware for GD32F30x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef __USB_HID_H +#define __USB_HID_H + +#include "usb_ch9_std.h" + +#define USB_HID_CLASS 0x03U + +#define USB_DESCTYPE_HID 0x21U +#define USB_DESCTYPE_REPORT 0x22U + +/* HID subclass code */ +#define USB_HID_SUBCLASS_BOOT_ITF 0x01U + +/* HID protocol codes */ +#define USB_HID_PROTOCOL_KEYBOARD 0x01U +#define USB_HID_PROTOCOL_MOUSE 0x02U + +#define GET_REPORT 0x01U +#define GET_IDLE 0x02U +#define GET_PROTOCOL 0x03U +#define SET_REPORT 0x09U +#define SET_IDLE 0x0AU +#define SET_PROTOCOL 0x0BU + +#pragma pack(1) + +typedef struct +{ + usb_desc_header header; /*!< regular descriptor header containing the descriptor's type and length */ + + uint16_t bcdHID; /*!< BCD encoded version that the HID descriptor and device complies to */ + uint8_t bCountryCode; /*!< country code of the localized device, or zero if universal */ + uint8_t bNumDescriptors; /*!< total number of HID report descriptors for the interface */ + uint8_t bDescriptorType; /*!< type of HID report */ + uint16_t wDescriptorLength; /*!< length of the associated HID report descriptor, in bytes */ +} usb_desc_hid; + +#pragma pack() + +typedef struct +{ + usb_desc_config config; + usb_desc_itf hid_itf; + usb_desc_hid hid_vendor; + usb_desc_ep hid_epin; + usb_desc_ep hid_epout; +} usb_hid_desc_config_set; + +#endif /* __USB_HID_H */ diff --git a/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbd_library/class/device/hid/Source/custom_hid_core.c b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbd_library/class/device/hid/Source/custom_hid_core.c new file mode 100644 index 0000000000..a85e6af72d --- /dev/null +++ b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbd_library/class/device/hid/Source/custom_hid_core.c @@ -0,0 +1,503 @@ +/*! + \file custom_hid_core.c + \brief custom HID class driver + + \version 2020-08-01, V3.0.0, firmware for GD32F30x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "usbd_transc.h" +#include "custom_hid_core.h" +#include + +#define USBD_VID 0x28E9U +#define USBD_PID 0x128AU + +/* Note:it should use the C99 standard when compiling the below codes */ +/* USB standard device descriptor */ +usb_desc_dev custom_hid_dev_desc = +{ + .header = + { + .bLength = USB_DEV_DESC_LEN, + .bDescriptorType = USB_DESCTYPE_DEV, + }, + .bcdUSB = 0x0200U, + .bDeviceClass = 0x00U, + .bDeviceSubClass = 0x00U, + .bDeviceProtocol = 0x00U, + .bMaxPacketSize0 = USBD_EP0_MAX_SIZE, + .idVendor = USBD_VID, + .idProduct = USBD_PID, + .bcdDevice = 0x0100U, + .iManufacturer = STR_IDX_MFC, + .iProduct = STR_IDX_PRODUCT, + .iSerialNumber = STR_IDX_SERIAL, + .bNumberConfigurations = USBD_CFG_MAX_NUM, +}; + +usb_hid_desc_config_set custom_hid_config_desc = +{ + .config = + { + .header = + { + .bLength = sizeof(usb_desc_config), + .bDescriptorType = USB_DESCTYPE_CONFIG + }, + .wTotalLength = DESC_LEN_CONFIG, + .bNumInterfaces = 0x01U, + .bConfigurationValue = 0x01U, + .iConfiguration = 0x00U, + .bmAttributes = 0x80U, + .bMaxPower = 0x32U + }, + + .hid_itf = + { + .header = + { + .bLength = sizeof(usb_desc_itf), + .bDescriptorType = USB_DESCTYPE_ITF + }, + .bInterfaceNumber = 0x00U, + .bAlternateSetting = 0x00U, + .bNumEndpoints = 0x02U, + .bInterfaceClass = USB_HID_CLASS, + .bInterfaceSubClass = 0x00U, + .bInterfaceProtocol = 0x00U, + .iInterface = 0x00U + }, + + .hid_vendor = + { + .header = + { + .bLength = sizeof(usb_desc_hid), + .bDescriptorType = USB_DESCTYPE_HID + }, + .bcdHID = 0x0111U, + .bCountryCode = 0x00U, + .bNumDescriptors = 0x01U, + .bDescriptorType = USB_DESCTYPE_REPORT, + .wDescriptorLength = DESC_LEN_REPORT, + }, + + .hid_epin = + { + .header = + { + .bLength = sizeof(usb_desc_ep), + .bDescriptorType = USB_DESCTYPE_EP + }, + .bEndpointAddress = CUSTOMHID_IN_EP, + .bmAttributes = USB_EP_ATTR_INT, + .wMaxPacketSize = CUSTOMHID_IN_PACKET, + .bInterval = 0x20U + }, + + .hid_epout = + { + .header = + { + .bLength = sizeof(usb_desc_ep), + .bDescriptorType = USB_DESCTYPE_EP + }, + .bEndpointAddress = CUSTOMHID_OUT_EP, + .bmAttributes = USB_EP_ATTR_INT, + .wMaxPacketSize = CUSTOMHID_OUT_PACKET, + .bInterval = 0x20U + } +}; + +/* USB language ID descriptor */ +static usb_desc_LANGID usbd_language_id_desc = +{ + .header = + { + .bLength = sizeof(usb_desc_LANGID), + .bDescriptorType = USB_DESCTYPE_STR + }, + .wLANGID = ENG_LANGID +}; + +/* USB manufacture string */ +static usb_desc_str manufacturer_string = +{ + .header = + { + .bLength = USB_STRING_LEN(10U), + .bDescriptorType = USB_DESCTYPE_STR, + }, + .unicode_string = {'G', 'i', 'g', 'a', 'D', 'e', 'v', 'i', 'c', 'e'} +}; + +/* USB product string */ +static usb_desc_str product_string = +{ + .header = + { + .bLength = USB_STRING_LEN(14U), + .bDescriptorType = USB_DESCTYPE_STR, + }, + .unicode_string = {'G', 'D', '3', '2', '-', 'C', 'u', 's', 't', 'o', 'm', 'H', 'I', 'D'} +}; + +/* USBD serial string */ +static usb_desc_str serial_string = +{ + .header = + { + .bLength = USB_STRING_LEN(12U), + .bDescriptorType = USB_DESCTYPE_STR, + } +}; + +/* USB string descriptor set */ +uint8_t* usbd_hid_strings[] = +{ + [STR_IDX_LANGID] = (uint8_t *)&usbd_language_id_desc, + [STR_IDX_MFC] = (uint8_t *)&manufacturer_string, + [STR_IDX_PRODUCT] = (uint8_t *)&product_string, + [STR_IDX_SERIAL] = (uint8_t *)&serial_string +}; + +usb_desc custom_hid_desc = { + .dev_desc = (uint8_t *)&custom_hid_dev_desc, + .config_desc = (uint8_t *)&custom_hid_config_desc, + .strings = usbd_hid_strings +}; + +/* local function prototypes ('static') */ +static uint8_t custom_hid_init (usb_dev *udev, uint8_t config_index); +static uint8_t custom_hid_deinit (usb_dev *udev, uint8_t config_index); +static uint8_t custom_hid_req_handler (usb_dev *udev, usb_req *req); +static void custom_hid_data_in (usb_dev *udev, uint8_t ep_num); +static void custom_hid_data_out (usb_dev *udev, uint8_t ep_num); + +usb_class custom_hid_class = { + .req_cmd = 0xFFU, + + .init = custom_hid_init, + .deinit = custom_hid_deinit, + .req_process = custom_hid_req_handler, + .data_in = custom_hid_data_in, + .data_out = custom_hid_data_out +}; + +const uint8_t customhid_report_descriptor[DESC_LEN_REPORT] = +{ + 0x06, 0x00, 0xFF, /* USAGE_PAGE (Vendor Defined: 0xFF00) */ + 0x09, 0x00, /* USAGE (Custom Device) */ + 0xa1, 0x01, /* COLLECTION (Application) */ + + /* led 1 */ + 0x85, 0x11, /* REPORT_ID (0x11) */ + 0x09, 0x01, /* USAGE (LED 1) */ + 0x15, 0x00, /* LOGICAL_MINIMUM (0) */ + 0x25, 0x01, /* LOGICAL_MAXIMUM (1) */ + 0x75, 0x08, /* REPORT_SIZE (8) */ + 0x95, 0x01, /* REPORT_COUNT (1) */ + 0x91, 0x82, /* OUTPUT (Data,Var,Abs,Vol) */ + + /* led 2 */ + 0x85, 0x12, /* REPORT_ID (0x12) */ + 0x09, 0x02, /* USAGE (LED 2) */ + 0x15, 0x00, /* LOGICAL_MINIMUM (0) */ + 0x25, 0x01, /* LOGICAL_MAXIMUM (1) */ + 0x75, 0x08, /* REPORT_SIZE (8) */ + 0x95, 0x01, /* REPORT_COUNT (1) */ + 0x91, 0x82, /* OUTPUT (Data,Var,Abs,Vol) */ + + /* led 3 */ + 0x85, 0x13, /* REPORT_ID (0x13) */ + 0x09, 0x03, /* USAGE (LED 3) */ + 0x15, 0x00, /* LOGICAL_MINIMUM (0) */ + 0x25, 0x01, /* LOGICAL_MAXIMUM (1) */ + 0x75, 0x08, /* REPORT_SIZE (8) */ + 0x95, 0x01, /* REPORT_COUNT (1) */ + 0x91, 0x82, /* OUTPUT (Data,Var,Abs,Vol) */ + + /* led 4 */ + 0x85, 0x14, /* REPORT_ID (0x14) */ + 0x09, 0x04, /* USAGE (LED 4) */ + 0x15, 0x00, /* LOGICAL_MINIMUM (0) */ + 0x25, 0x01, /* LOGICAL_MAXIMUM (1) */ + 0x75, 0x08, /* REPORT_SIZE (8) */ + 0x95, 0x01, /* REPORT_COUNT (1) */ + 0x91, 0x82, /* OUTPUT (Data,Var,Abs,Vol) */ + + /* wakeup key */ + 0x85, 0x15, /* REPORT_ID (0x15) */ + 0x09, 0x05, /* USAGE (Push Button) */ + 0x15, 0x00, /* LOGICAL_MINIMUM (0) */ + 0x25, 0x01, /* LOGICAL_MAXIMUM (1) */ + 0x75, 0x01, /* REPORT_SIZE (1) */ + 0x81, 0x02, /* INPUT (Data,Var,Abs,Vol) */ + + 0x75, 0x07, /* REPORT_SIZE (7) */ + 0x81, 0x03, /* INPUT (Cnst,Var,Abs,Vol) */ + + /* tamper key */ + 0x85, 0x16, /* REPORT_ID (0x16) */ + 0x09, 0x06, /* USAGE (Push Button) */ + 0x15, 0x00, /* LOGICAL_MINIMUM (0) */ + 0x25, 0x01, /* LOGICAL_MAXIMUM (1) */ + 0x75, 0x01, /* REPORT_SIZE (1) */ + 0x81, 0x02, /* INPUT (Data,Var,Abs,Vol) */ + + 0x75, 0x07, /* REPORT_SIZE (7) */ + 0x81, 0x03, /* INPUT (Cnst,Var,Abs,Vol) */ + + 0xc0 /* END_COLLECTION */ +}; + +/*! + \brief register HID interface operation functions + \param[in] udev: pointer to USB device instance + \param[in] hid_fop: HID operation functions structure + \param[out] none + \retval USB device operation status +*/ +uint8_t custom_hid_itfop_register (usb_dev *udev, hid_fop_handler *hid_fop) +{ + if (NULL != hid_fop) { + udev->user_data = hid_fop; + + return USBD_OK; + } + + return USBD_FAIL; +} + +/*! + \brief send custom HID report + \param[in] udev: pointer to USB device instance + \param[in] report: pointer to HID report + \param[in] len: data length + \param[out] none + \retval USB device operation status +*/ +uint8_t custom_hid_report_send (usb_dev *udev, uint8_t *report, uint16_t len) +{ + usbd_ep_send (udev, CUSTOMHID_IN_EP, report, len); + + return USBD_OK; +} + +/*! + \brief initialize the HID device + \param[in] pudev: pointer to USB device instance + \param[in] config_index: configuration index + \param[out] none + \retval USB device operation status +*/ +static uint8_t custom_hid_init (usb_dev *udev, uint8_t config_index) +{ + static custom_hid_handler hid_handler; + + memset((void *)&hid_handler, 0, sizeof(custom_hid_handler)); + + /* initialize the data endpoints */ + usbd_ep_init(udev, EP_BUF_SNG, HID_TX_ADDR, &(custom_hid_config_desc.hid_epin)); + usbd_ep_init(udev, EP_BUF_SNG, HID_RX_ADDR, &(custom_hid_config_desc.hid_epout)); + + usbd_ep_recev (udev, CUSTOMHID_OUT_EP, hid_handler.data, 2U); + + udev->ep_transc[EP_ID(CUSTOMHID_IN_EP)][TRANSC_IN] = custom_hid_class.data_in; + udev->ep_transc[EP_ID(CUSTOMHID_OUT_EP)][TRANSC_OUT] = custom_hid_class.data_out; + + udev->class_data[CUSTOM_HID_INTERFACE] = (void *)&hid_handler; + + if (udev->user_data != NULL) { + for (uint8_t i = 0U; i < MAX_PERIPH_NUM; i++) { + if (((hid_fop_handler *)udev->user_data)->periph_config[i] != NULL) { + ((hid_fop_handler *)udev->user_data)->periph_config[i](); + } + } + } + + return USBD_OK; +} + +/*! + \brief de-initialize the HID device + \param[in] udev: pointer to USB device instance + \param[in] config_index: configuration index + \param[out] none + \retval USB device operation status +*/ +static uint8_t custom_hid_deinit (usb_dev *udev, uint8_t config_index) +{ + /* deinitialize HID endpoints */ + usbd_ep_deinit(udev, CUSTOMHID_IN_EP); + usbd_ep_deinit(udev, CUSTOMHID_OUT_EP); + + return USBD_OK; +} + +/*! + \brief handle the HID class-specific requests + \param[in] udev: pointer to USB device instance + \param[in] req: device class-specific request + \param[out] none + \retval USB device operation status +*/ +static uint8_t custom_hid_req_handler (usb_dev *udev, usb_req *req) +{ + uint8_t status = REQ_NOTSUPP; + + custom_hid_handler *hid = (custom_hid_handler *)udev->class_data[CUSTOM_HID_INTERFACE]; + + switch (req->bRequest) { + case USB_GET_DESCRIPTOR: + if (USB_DESCTYPE_REPORT == (req->wValue >> 8)) { + usb_transc_config(&udev->transc_in[0], + (uint8_t *)customhid_report_descriptor, + USB_MIN(DESC_LEN_REPORT, req->wLength), + 0U); + + status = REQ_SUPP; + } + break; + + case GET_REPORT: + if (2U == req->wLength) { + usb_transc_config(&udev->transc_in[0], hid->data, 2U, 0U); + + status = REQ_SUPP; + } + break; + + case GET_IDLE: + usb_transc_config(&udev->transc_in[0], (uint8_t *)&hid->idlestate, 1U, 0U); + + status = REQ_SUPP; + break; + + case GET_PROTOCOL: + usb_transc_config(&udev->transc_in[0], (uint8_t *)&hid->protocol, 1U, 0U); + + status = REQ_SUPP; + break; + + case SET_REPORT: + hid->reportID = (uint8_t)(req->wValue); + + usb_transc_config(&udev->transc_out[0], hid->data, req->wLength, 0U); + + status = REQ_SUPP; + break; + + case SET_IDLE: + hid->idlestate = (uint8_t)(req->wValue >> 8); + + status = REQ_SUPP; + break; + + case SET_PROTOCOL: + hid->protocol = (uint8_t)(req->wValue); + + status = REQ_SUPP; + break; + + default: + break; + } + + return status; +} + +/*! + \brief handle custom HID data in transaction + \param[in] udev: pointer to USB device instance + \param[in] ep_num: endpoint number + \param[out] none + \retval none +*/ +static void custom_hid_data_in (usb_dev *udev, uint8_t ep_num) +{ + return; +} + +/*! + \brief handle custom HID data out transaction + \param[in] udev: pointer to USB device instance + \param[in] ep_num: endpoint number + \param[out] none + \retval none +*/ +static void custom_hid_data_out (usb_dev *udev, uint8_t ep_num) +{ + custom_hid_handler *hid = (custom_hid_handler *)udev->class_data[CUSTOM_HID_INTERFACE]; + + if (CUSTOMHID_OUT_EP == ep_num){ + + switch (hid->data[0]){ + case 0x11: + if (RESET != hid->data[1]) { + /* turn on led1 */ + gd_eval_led_on(LED5); + } else { + gd_eval_led_off(LED5); + } + break; + case 0x12: + if (RESET != hid->data[1]) { + gd_eval_led_on(LED2); + } else { + gd_eval_led_off(LED2); + } + break; + case 0x13: + if (RESET != hid->data[1]) { + gd_eval_led_on(LED3); + } else { + gd_eval_led_off(LED3); + } + break; + case 0x14: + if (RESET != hid->data[1]) { + gd_eval_led_on(LED4); + } else { + gd_eval_led_off(LED4); + } + break; + default: + /* turn off all leds */ + gd_eval_led_off(LED5); + gd_eval_led_off(LED2); + gd_eval_led_off(LED3); + gd_eval_led_off(LED4); + break; + } + + usbd_ep_recev(udev, CUSTOMHID_IN_EP, hid->data, 2U); + } +} diff --git a/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbd_library/class/device/hid/Source/standard_hid_core.c b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbd_library/class/device/hid/Source/standard_hid_core.c new file mode 100644 index 0000000000..373810b6b7 --- /dev/null +++ b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbd_library/class/device/hid/Source/standard_hid_core.c @@ -0,0 +1,427 @@ +/*! + \file standard_hid_core.c + \brief HID class driver + + \version 2020-08-01, V3.0.0, firmware for GD32F30x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "usbd_transc.h" +#include "standard_hid_core.h" + +#include + +#define USBD_VID 0x28E9U +#define USBD_PID 0x0380U + +/* Note:it should use the C99 standard when compiling the below codes */ +/* USB standard device descriptor */ +usb_desc_dev hid_dev_desc = +{ + .header = + { + .bLength = USB_DEV_DESC_LEN, + .bDescriptorType = USB_DESCTYPE_DEV + }, +#ifdef LPM_ENABLED + .bcdUSB = 0x0201U, +#else + .bcdUSB = 0x0200U, +#endif /* LPM_ENABLED */ + .bDeviceClass = 0x00U, + .bDeviceSubClass = 0x00U, + .bDeviceProtocol = 0x00U, + .bMaxPacketSize0 = USBD_EP0_MAX_SIZE, + .idVendor = USBD_VID, + .idProduct = USBD_PID, + .bcdDevice = 0x0100U, + .iManufacturer = STR_IDX_MFC, + .iProduct = STR_IDX_PRODUCT, + .iSerialNumber = STR_IDX_SERIAL, + .bNumberConfigurations = USBD_CFG_MAX_NUM +}; + +#ifdef LPM_ENABLED + +/* BOS descriptor */ +uint8_t USBD_BOSDesc[USB_BOS_DESC_LEN] = +{ + 0x05, + USB_DESCTYPE_BOS, + 0x0C, + 0x00, + 0x01, /* 1 device capability descriptor */ + + /* device capability*/ + 0x07, + USB_DEVICE_CAPABITY, + 0x02, + 0x06, /* LPM capability bit set */ + 0x00, + 0x00, + 0x00 +}; + +#endif /* LPM_ENABLED */ + +usb_hid_desc_config_set hid_config_desc = +{ + .config = + { + .header = + { + .bLength = sizeof(usb_desc_config), + .bDescriptorType = USB_DESCTYPE_CONFIG + }, + .wTotalLength = USB_HID_CONFIG_DESC_LEN, + .bNumInterfaces = 0x01U, + .bConfigurationValue = 0x01U, + .iConfiguration = 0x00U, + .bmAttributes = 0xA0U, + .bMaxPower = 0x32U + }, + + .hid_itf = + { + .header = + { + .bLength = sizeof(usb_desc_itf), + .bDescriptorType = USB_DESCTYPE_ITF + }, + .bInterfaceNumber = 0x00U, + .bAlternateSetting = 0x00U, + .bNumEndpoints = 0x01U, + .bInterfaceClass = USB_HID_CLASS, + .bInterfaceSubClass = USB_HID_SUBCLASS_BOOT_ITF, + .bInterfaceProtocol = USB_HID_PROTOCOL_KEYBOARD, + .iInterface = 0x00U + }, + + .hid_vendor = + { + .header = + { + .bLength = sizeof(usb_desc_hid), + .bDescriptorType = USB_DESCTYPE_HID + }, + .bcdHID = 0x0111U, + .bCountryCode = 0x00U, + .bNumDescriptors = 0x01U, + .bDescriptorType = USB_DESCTYPE_REPORT, + .wDescriptorLength = USB_HID_REPORT_DESC_LEN, + }, + + .hid_epin = + { + .header = + { + .bLength = sizeof(usb_desc_ep), + .bDescriptorType = USB_DESCTYPE_EP + }, + .bEndpointAddress = HID_IN_EP, + .bmAttributes = USB_EP_ATTR_INT, + .wMaxPacketSize = HID_IN_PACKET, + .bInterval = 0x40U + } +}; + +/* USB language ID Descriptor */ +static usb_desc_LANGID usbd_language_id_desc = +{ + .header = + { + .bLength = sizeof(usb_desc_LANGID), + .bDescriptorType = USB_DESCTYPE_STR + }, + .wLANGID = ENG_LANGID +}; + +/* USB manufacture string */ +static usb_desc_str manufacturer_string = +{ + .header = + { + .bLength = USB_STRING_LEN(10U), + .bDescriptorType = USB_DESCTYPE_STR, + }, + .unicode_string = {'G', 'i', 'g', 'a', 'D', 'e', 'v', 'i', 'c', 'e'} +}; + +/* USB product string */ +static usb_desc_str product_string = +{ + .header = + { + .bLength = USB_STRING_LEN(17U), + .bDescriptorType = USB_DESCTYPE_STR, + }, + .unicode_string = {'G', 'D', '3', '2', '-', 'U', 'S', 'B', '_', 'K', 'e', 'y', 'b', 'o', 'a', 'r', 'd'} +}; + +/* USBD serial string */ +static usb_desc_str serial_string = +{ + .header = + { + .bLength = USB_STRING_LEN(12U), + .bDescriptorType = USB_DESCTYPE_STR, + } +}; + +uint8_t* usbd_hid_strings[] = +{ + [STR_IDX_LANGID] = (uint8_t *)&usbd_language_id_desc, + [STR_IDX_MFC] = (uint8_t *)&manufacturer_string, + [STR_IDX_PRODUCT] = (uint8_t *)&product_string, + [STR_IDX_SERIAL] = (uint8_t *)&serial_string +}; + +usb_desc hid_desc = { +#ifdef LPM_ENABLED + .bos_desc = (uint8_t *)&USBD_BOSDesc, +#endif /* LPM_ENABLED */ + .dev_desc = (uint8_t *)&hid_dev_desc, + .config_desc = (uint8_t *)&hid_config_desc, + .strings = usbd_hid_strings +}; + +/* local function prototypes ('static') */ +static uint8_t hid_init (usb_dev *udev, uint8_t config_index); +static uint8_t hid_deinit (usb_dev *udev, uint8_t config_index); +static uint8_t hid_req_handler (usb_dev *udev, usb_req *req); +static void hid_data_in_handler (usb_dev *udev, uint8_t ep_num); + +usb_class hid_class = { + .init = hid_init, + .deinit = hid_deinit, + .req_process = hid_req_handler, + .data_in = hid_data_in_handler +}; + +const uint8_t hid_report_desc[USB_HID_REPORT_DESC_LEN] = +{ + 0x05, 0x01, /* USAGE_PAGE (Generic Desktop) */ + 0x09, 0x06, /* USAGE (Keyboard) */ + 0xa1, 0x01, /* COLLECTION (Application) */ + + 0x05, 0x07, /* USAGE_PAGE (Keyboard/Keypad) */ + 0x19, 0xe0, /* USAGE_MINIMUM (Keyboard LeftControl) */ + 0x29, 0xe7, /* USAGE_MAXIMUM (Keyboard Right GUI) */ + 0x15, 0x00, /* LOGICAL_MINIMUM (0) */ + 0x25, 0x01, /* LOGICAL_MAXIMUM (1) */ + 0x95, 0x08, /* REPORT_COUNT (8) */ + 0x75, 0x01, /* REPORT_SIZE (1) */ + 0x81, 0x02, /* INPUT (Data,Var,Abs) */ + + 0x95, 0x01, /* REPORT_COUNT (1) */ + 0x75, 0x08, /* REPORT_SIZE (8) */ + 0x81, 0x03, /* INPUT (Cnst,Var,Abs) */ + + 0x95, 0x06, /* REPORT_COUNT (6) */ + 0x75, 0x08, /* REPORT_SIZE (8) */ + 0x15, 0x00, /* LOGICAL_MINIMUM (0) */ + 0x26, 0xFF, 0x00, /* LOGICAL_MAXIMUM (255) */ + 0x05, 0x07, /* USAGE_PAGE (Keyboard/Keypad) */ + 0x19, 0x00, /* USAGE_MINIMUM (Reserved (no event indicated)) */ + 0x29, 0x65, /* USAGE_MAXIMUM (Keyboard Application) */ + 0x81, 0x00, /* INPUT (Data,Ary,Abs) */ + + 0xc0 /* END_COLLECTION */ +}; + +/*! + \brief register HID interface operation functions + \param[in] udev: pointer to USB device instance + \param[in] hid_fop: HID operation functions structure + \param[out] none + \retval USB device operation status +*/ +uint8_t hid_itfop_register (usb_dev *udev, hid_fop_handler *hid_fop) +{ + if (NULL != hid_fop) { + udev->user_data = (void *)hid_fop; + + return USBD_OK; + } + + return USBD_FAIL; +} + +/*! + \brief send keyboard report + \param[in] udev: pointer to USB device instance + \param[in] report: pointer to HID report + \param[in] len: data length + \param[out] none + \retval USB device operation status +*/ +uint8_t hid_report_send (usb_dev *udev, uint8_t *report, uint16_t len) +{ + standard_hid_handler *hid = (standard_hid_handler *)udev->class_data[USBD_HID_INTERFACE]; + + /* check if USB is configured */ + hid->prev_transfer_complete = 0U; + + usbd_ep_send(udev, HID_IN_EP, report, len); + + return USBD_OK; +} + +/*! + \brief initialize the HID device + \param[in] udev: pointer to USB device instance + \param[in] config_index: configuration index + \param[out] none + \retval USB device operation status +*/ +static uint8_t hid_init (usb_dev *udev, uint8_t config_index) +{ + static standard_hid_handler hid_handler; + + memset((void *)&hid_handler, 0, sizeof(standard_hid_handler)); + + /* initialize Tx endpoint */ + usbd_ep_init(udev, EP_BUF_SNG, INT_TX_ADDR, &(hid_config_desc.hid_epin)); + + udev->ep_transc[EP_ID(HID_IN_EP)][TRANSC_IN] = hid_class.data_in; + + hid_handler.prev_transfer_complete = 1U; + + udev->class_data[USBD_HID_INTERFACE] = (void *)&hid_handler; + + if (NULL != udev->user_data) { + ((hid_fop_handler *)udev->user_data)->hid_itf_config(); + } + + return USBD_OK; +} + +/*! + \brief de-initialize the HID device + \param[in] udev: pointer to USB device instance + \param[in] config_index: configuration index + \param[out] none + \retval USB device operation status +*/ +static uint8_t hid_deinit (usb_dev *udev, uint8_t config_index) +{ + /* deinitialize HID endpoints */ + usbd_ep_deinit (udev, HID_IN_EP); + + return USBD_OK; +} + +/*! + \brief handle the HID class-specific requests + \param[in] udev: pointer to USB device instance + \param[in] req: device class-specific request + \param[out] none + \retval USB device operation status +*/ +static uint8_t hid_req_handler (usb_dev *udev, usb_req *req) +{ + uint8_t status = REQ_NOTSUPP; + + standard_hid_handler *hid = (standard_hid_handler *)udev->class_data[USBD_HID_INTERFACE]; + + switch (req->bRequest) { + case GET_REPORT: + /* no use for this driver */ + break; + + case GET_IDLE: + usb_transc_config(&udev->transc_in[0U], (uint8_t *)&hid->idle_state, 1U, 0U); + + status = REQ_SUPP; + break; + + case GET_PROTOCOL: + usb_transc_config(&udev->transc_in[0U], (uint8_t *)&hid->protocol, 1U, 0U); + + status = REQ_SUPP; + break; + + case SET_REPORT: + /* no use for this driver */ + break; + + case SET_IDLE: + hid->idle_state = (uint8_t)(req->wValue >> 8); + + status = REQ_SUPP; + break; + + case SET_PROTOCOL: + hid->protocol = (uint8_t)(req->wValue); + + status = REQ_SUPP; + break; + + case USB_GET_DESCRIPTOR: + if (USB_DESCTYPE_REPORT == (req->wValue >> 8)) { + usb_transc_config(&udev->transc_in[0U], + (uint8_t *)hid_report_desc, + USB_MIN(USB_HID_REPORT_DESC_LEN, req->wLength), + 0U); + + status = REQ_SUPP; + } else if (USB_DESCTYPE_HID == (req->wValue >> 8U)) { + usb_transc_config(&udev->transc_in[0U], + (uint8_t *)(&(hid_config_desc.hid_vendor)), + USB_MIN(9U, req->wLength), + 0U); + } + break; + + default: + break; + } + + return status; +} + +/*! + \brief handle data stage in DATA IN transaction + \param[in] udev: pointer to USB device instance + \param[in] ep_num: endpoint identifier + \param[out] none + \retval none +*/ +static void hid_data_in_handler (usb_dev *udev, uint8_t ep_num) +{ + standard_hid_handler *hid = (standard_hid_handler *)udev->class_data[USBD_HID_INTERFACE]; + + if (hid->data[2]) { + hid->data[2] = 0x00U; + + usbd_ep_send(udev, HID_IN_EP, hid->data, HID_IN_PACKET); + } else { + hid->prev_transfer_complete = 1U; + } +} diff --git a/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbd_library/class/device/hid/Source/std_hid_mouse_core.c b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbd_library/class/device/hid/Source/std_hid_mouse_core.c new file mode 100644 index 0000000000..6ac896d475 --- /dev/null +++ b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbd_library/class/device/hid/Source/std_hid_mouse_core.c @@ -0,0 +1,425 @@ +/*! + \file std_hid_mouse_core.c + \brief HID class driver + + \version 2020-08-01, V3.0.0, firmware for GD32F30x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "usbd_transc.h" +#include "std_hid_mouse_core.h" + +#include + +#define USBD_VID 0x28E9U +#define USBD_PID 0x0381U + +/* Note:it should use the C99 standard when compiling the below codes */ +/* USB standard device descriptor */ +usb_desc_dev hid_dev_desc = +{ + .header = + { + .bLength = USB_DEV_DESC_LEN, + .bDescriptorType = USB_DESCTYPE_DEV + }, +#ifdef LPM_ENABLED + .bcdUSB = 0x0201U, +#else + .bcdUSB = 0x0200U, +#endif /* LPM_ENABLED */ + .bDeviceClass = 0x00U, + .bDeviceSubClass = 0x00U, + .bDeviceProtocol = 0x00U, + .bMaxPacketSize0 = USBD_EP0_MAX_SIZE, + .idVendor = USBD_VID, + .idProduct = USBD_PID, + .bcdDevice = 0x0100U, + .iManufacturer = STR_IDX_MFC, + .iProduct = STR_IDX_PRODUCT, + .iSerialNumber = STR_IDX_SERIAL, + .bNumberConfigurations = USBD_CFG_MAX_NUM +}; + +#ifdef LPM_ENABLED + +/* BOS descriptor */ +uint8_t USBD_BOSDesc[USB_BOS_DESC_LEN] = +{ + 0x05, + USB_DESCTYPE_BOS, + 0x0C, + 0x00, + 0x01, /* 1 device capability descriptor */ + + /* device capability*/ + 0x07, + USB_DEVICE_CAPABITY, + 0x02, + 0x06, /* LPM capability bit set */ + 0x00, + 0x00, + 0x00 +}; + +#endif /* LPM_ENABLED */ + +usb_hid_desc_config_set hid_config_desc = +{ + .config = + { + .header = + { + .bLength = sizeof(usb_desc_config), + .bDescriptorType = USB_DESCTYPE_CONFIG + }, + .wTotalLength = USB_HID_CONFIG_DESC_LEN, + .bNumInterfaces = 0x01U, + .bConfigurationValue = 0x01U, + .iConfiguration = 0x00U, + .bmAttributes = 0xA0U, + .bMaxPower = 0x32U + }, + + .hid_itf = + { + .header = + { + .bLength = sizeof(usb_desc_itf), + .bDescriptorType = USB_DESCTYPE_ITF + }, + .bInterfaceNumber = 0x00U, + .bAlternateSetting = 0x00U, + .bNumEndpoints = 0x01U, + .bInterfaceClass = USB_HID_CLASS, + .bInterfaceSubClass = USB_HID_SUBCLASS_BOOT_ITF, + .bInterfaceProtocol = USB_HID_PROTOCOL_MOUSE, + .iInterface = 0x00U + }, + + .hid_vendor = + { + .header = + { + .bLength = sizeof(usb_desc_hid), + .bDescriptorType = USB_DESCTYPE_HID + }, + .bcdHID = 0x0111U, + .bCountryCode = 0x00U, + .bNumDescriptors = 0x01U, + .bDescriptorType = USB_DESCTYPE_REPORT, + .wDescriptorLength = USB_HID_REPORT_DESC_LEN, + }, + + .hid_epin = + { + .header = + { + .bLength = sizeof(usb_desc_ep), + .bDescriptorType = USB_DESCTYPE_EP + }, + .bEndpointAddress = HID_IN_EP, + .bmAttributes = USB_EP_ATTR_INT, + .wMaxPacketSize = HID_IN_PACKET, + .bInterval = 0x40U + } +}; + +/* USB language ID Descriptor */ +usb_desc_LANGID usbd_language_id_desc = +{ + .header = + { + .bLength = sizeof(usb_desc_LANGID), + .bDescriptorType = USB_DESCTYPE_STR + }, + .wLANGID = ENG_LANGID +}; + +/* USB manufacture string */ +static usb_desc_str manufacturer_string = +{ + .header = + { + .bLength = USB_STRING_LEN(10U), + .bDescriptorType = USB_DESCTYPE_STR, + }, + .unicode_string = {'G', 'i', 'g', 'a', 'D', 'e', 'v', 'i', 'c', 'e'} +}; + +/* USB product string */ +static usb_desc_str product_string = +{ + .header = + { + .bLength = USB_STRING_LEN(14U), + .bDescriptorType = USB_DESCTYPE_STR, + }, + .unicode_string = {'G', 'D', '3', '2', '-', 'U', 'S', 'B', '_', 'M', 'o', 'u', 's', 'e'} +}; + +/* USBD serial string */ +static usb_desc_str serial_string = +{ + .header = + { + .bLength = USB_STRING_LEN(12U), + .bDescriptorType = USB_DESCTYPE_STR, + } +}; + +static uint8_t* usbd_hid_strings[] = +{ + [STR_IDX_LANGID] = (uint8_t *)&usbd_language_id_desc, + [STR_IDX_MFC] = (uint8_t *)&manufacturer_string, + [STR_IDX_PRODUCT] = (uint8_t *)&product_string, + [STR_IDX_SERIAL] = (uint8_t *)&serial_string +}; + +usb_desc hid_mouse_desc = { + .dev_desc = (uint8_t *)&hid_dev_desc, + .config_desc = (uint8_t *)&hid_config_desc, + .strings = usbd_hid_strings +}; + +static uint8_t hid_init (usb_dev *udev, uint8_t config_index); +static uint8_t hid_deinit (usb_dev *udev, uint8_t config_index); +static uint8_t hid_req_handler (usb_dev *udev, usb_req *req); + +static void hid_data_in_handler (usb_dev *udev, uint8_t ep_num); + +usb_class hid_class = { + .init = hid_init, + .deinit = hid_deinit, + .req_process = hid_req_handler, + .data_in = hid_data_in_handler +}; + +const uint8_t hid_report_desc[USB_HID_REPORT_DESC_LEN] = +{ + 0x05, 0x01, /* USAGE_PAGE (Generic Desktop) */ + 0x09, 0x02, /* USAGE (Mouse) */ + 0xa1, 0x01, /* COLLECTION (Application) */ + 0x09, 0x01, /* USAGE (Pointer) */ + + 0xa1, 0x00, /* COLLECTION (Physical) */ + 0x05, 0x09, /* USAGE_PAGE (Button) */ + 0x19, 0x01, /* USAGE_MINIMUM (1) */ + 0x29, 0x03, /* USAGE_MAXIMUM (3) */ + + 0x15, 0x00, /* LOGICAL_MINIMUM (0) */ + 0x25, 0x01, /* LOGICAL_MAXIMUM (1) */ + 0x95, 0x03, /* REPORT_COUNT (3) */ + 0x75, 0x01, /* REPORT_SIZE (1) */ + 0x81, 0x02, /* INPUT (Data,Var,Abs) */ + + 0x95, 0x01, /* REPORT_COUNT (1) */ + 0x75, 0x05, /* REPORT_SIZE (5) */ + 0x81, 0x01, /* INPUT (Cnst,Var,Abs) */ + + 0x05, 0x01, /* USAGE_PAGE (Generic Desktop) */ + 0x09, 0x30, /* USAGE (X) */ + 0x09, 0x31, /* USAGE (Y) */ + 0x09, 0x38, /* USAGE (Wheel) */ + + 0x15, 0x81, /* LOGICAL_MINIMUM (-127) */ + 0x25, 0x7F, /* LOGICAL_MAXIMUM (127) */ + 0x75, 0x08, /* REPORT_SIZE (8) */ + 0x95, 0x03, /* REPORT_COUNT (3) */ + 0x81, 0x06, /* INPUT (Data,Var,Rel) */ + 0xc0, /* END_COLLECTION */ + 0xc0 /* END_COLLECTION */ +}; + +/*! + \brief register HID interface operation functions + \param[in] udev: pointer to USB device instance + \param[in] hid_fop: HID operation functions structure + \param[out] none + \retval USB device operation status +*/ +uint8_t hid_itfop_register (usb_dev *udev, mice_fop_handler *hid_fop) +{ + if (NULL != hid_fop) { + udev->user_data = (void *)hid_fop; + + return USBD_OK; + } + + return USBD_FAIL; +} + +/*! + \brief send mouse report + \param[in] udev: pointer to USB device instance + \param[in] report: pointer to HID report + \param[in] len: data length + \param[out] none + \retval USB device operation status +*/ +uint8_t hid_report_send (usb_dev *udev, uint8_t *report, uint16_t len) +{ + standard_mice_handler *hid = (standard_mice_handler *)udev->class_data[USBD_HID_INTERFACE]; + + if(udev->cur_status == USBD_CONFIGURED){ + if(1U == hid->prev_transfer_complete){ + hid->prev_transfer_complete = 0U; + usbd_ep_send(udev, HID_IN_EP, report, len); + } + } + + return USBD_OK; +} + +/*! + \brief initialize the HID device + \param[in] udev: pointer to USB device instance + \param[in] config_index: configuration index + \param[out] none + \retval USB device operation status +*/ +static uint8_t hid_init (usb_dev *udev, uint8_t config_index) +{ + static standard_mice_handler mice_handler; + + memset((void *)&mice_handler, 0, sizeof(standard_mice_handler)); + + /* initialize Tx endpoint */ + usbd_ep_init(udev, EP_BUF_SNG, INT_TX_ADDR, &(hid_config_desc.hid_epin)); + + udev->ep_transc[EP_ID(HID_IN_EP)][TRANSC_IN] = hid_class.data_in; + + mice_handler.prev_transfer_complete = 1U; + + udev->class_data[USBD_HID_INTERFACE] = (void *)&mice_handler; + + if (NULL != udev->user_data) { + ((mice_fop_handler *)(udev->user_data))->mice_itf_config(); + } + + return USBD_OK; +} + +/*! + \brief de-initialize the HID device + \param[in] udev: pointer to USB device instance + \param[in] config_index: configuration index + \param[out] none + \retval USB device operation status +*/ +static uint8_t hid_deinit (usb_dev *udev, uint8_t config_index) +{ + /* deinitialize HID endpoints */ + usbd_ep_deinit (udev, HID_IN_EP); + + return USBD_OK; +} + +/*! + \brief handle the HID class-specific requests + \param[in] udev: pointer to USB device instance + \param[in] req: device class-specific request + \param[out] none + \retval USB device operation status +*/ +static uint8_t hid_req_handler (usb_dev *udev, usb_req *req) +{ + uint8_t status = REQ_NOTSUPP; + + standard_mice_handler *hid = (standard_mice_handler *)udev->class_data[USBD_HID_INTERFACE]; + + switch (req->bRequest) { + case GET_REPORT: + /* no use for this driver */ + break; + + case GET_IDLE: + usb_transc_config(&udev->transc_in[0U], (uint8_t *)&hid->idle_state, 1U, 0U); + + status = REQ_SUPP; + break; + + case GET_PROTOCOL: + usb_transc_config(&udev->transc_in[0], (uint8_t *)&hid->protocol, 1U, 0U); + + status = REQ_SUPP; + break; + + case SET_REPORT: + /* no use for this driver */ + break; + + case SET_IDLE: + hid->idle_state = (uint8_t)(req->wValue >> 8); + + status = REQ_SUPP; + break; + + case SET_PROTOCOL: + hid->protocol = (uint8_t)(req->wValue); + + status = REQ_SUPP; + break; + + case USB_GET_DESCRIPTOR: + if (USB_DESCTYPE_REPORT == (req->wValue >> 8)) { + usb_transc_config(&udev->transc_in[0U], + (uint8_t *)hid_report_desc, + USB_MIN(USB_HID_REPORT_DESC_LEN, req->wLength), + 0U); + + status = REQ_SUPP; + } + break; + + default: + break; + } + + return status; +} + +/*! + \brief handle data stage in DATA IN transaction + \param[in] udev: pointer to USB device instance + \param[in] ep_num: endpoint identifier + \param[out] none + \retval none +*/ +static void hid_data_in_handler (usb_dev *udev, uint8_t ep_num) +{ + standard_mice_handler *hid = (standard_mice_handler *)udev->class_data[USBD_HID_INTERFACE]; + + if(hid->data[0] == 0U){ + hid->prev_transfer_complete = 1U; + }else{ + hid->data[0] = 0U; + usbd_ep_send(udev, HID_IN_EP, hid->data, HID_IN_PACKET); + } +} diff --git a/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbd_library/class/device/iap/Include/usb_iap_core.h b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbd_library/class/device/iap/Include/usb_iap_core.h new file mode 100644 index 0000000000..d9f7a8aa7e --- /dev/null +++ b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbd_library/class/device/iap/Include/usb_iap_core.h @@ -0,0 +1,82 @@ +/*! + \file usb_iap_core.h + \brief the header file of IAP driver + + \version 2020-08-01, V3.0.0, firmware for GD32F30x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef __USB_IAP_CORE_H +#define __USB_IAP_CORE_H + +#include "usbd_enum.h" +#include "usb_hid.h" + +#define USB_DESC_LEN_IAP_REPORT 35U +#define USB_DESC_LEN_IAP_CONFIG_SET 41U + +/* special commands with download request */ +#define IAP_OPTION_BYTE 0x01U +#define IAP_ERASE 0x02U +#define IAP_DNLOAD 0x03U +#define IAP_LEAVE 0x04U +#define IAP_GETBIN_ADDRESS 0x05U + +typedef void (*app_func) (void); + +typedef struct +{ + uint8_t report_buf[IAP_OUT_PACKET + 1U]; + uint8_t option_byte[IAP_IN_PACKET]; + + /* state machine variables */ + uint8_t dev_status[IAP_IN_PACKET]; + uint8_t bin_addr[IAP_IN_PACKET]; + + uint8_t reportID; + uint8_t flag; + + uint32_t protocol; + uint32_t idlestate; + + uint16_t transfer_times; + uint16_t page_count; + uint16_t lps; /* last packet size */ + uint32_t file_length; + uint32_t base_address; +} usbd_iap_handler; + +extern usb_desc iap_desc; +extern usb_class iap_class; + +/* function declarations */ +/* send IAP report */ +uint8_t iap_report_send(usb_dev *udev, uint8_t *report, uint16_t len); + +#endif /* __USB_IAP_CORE_H */ diff --git a/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbd_library/class/device/iap/Source/usb_iap_core.c b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbd_library/class/device/iap/Source/usb_iap_core.c new file mode 100644 index 0000000000..093214e9d0 --- /dev/null +++ b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbd_library/class/device/iap/Source/usb_iap_core.c @@ -0,0 +1,594 @@ +/*! + \file usb_iap_core.c + \brief IAP driver + + \version 2020-08-01, V3.0.0, firmware for GD32F30x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "usbd_transc.h" +#include "usb_iap_core.h" +#include + +#define USBD_VID 0x28E9U +#define USBD_PID 0x028BU + +/* Note:it should use the C99 standard when compiling the below codes */ +/* USB standard device descriptor */ +usb_desc_dev iap_dev_desc = +{ + .header = + { + .bLength = USB_DEV_DESC_LEN, + .bDescriptorType = USB_DESCTYPE_DEV + }, + .bcdUSB = 0x0200U, + .bDeviceClass = 0x00U, + .bDeviceSubClass = 0x00U, + .bDeviceProtocol = 0x00U, + .bMaxPacketSize0 = USBD_EP0_MAX_SIZE, + .idVendor = USBD_VID, + .idProduct = USBD_PID, + .bcdDevice = 0x0100U, + .iManufacturer = STR_IDX_MFC, + .iProduct = STR_IDX_PRODUCT, + .iSerialNumber = STR_IDX_SERIAL, + .bNumberConfigurations = USBD_CFG_MAX_NUM +}; + +usb_hid_desc_config_set iap_config_desc = +{ + .config = + { + .header = + { + .bLength = sizeof(usb_desc_config), + .bDescriptorType = USB_DESCTYPE_CONFIG + }, + .wTotalLength = USB_DESC_LEN_IAP_CONFIG_SET, + .bNumInterfaces = 0x01U, + .bConfigurationValue = 0x01U, + .iConfiguration = 0x00U, + .bmAttributes = 0x80U, + .bMaxPower = 0x32U + }, + + .hid_itf = + { + .header = + { + .bLength = sizeof(usb_desc_itf), + .bDescriptorType = USB_DESCTYPE_ITF + }, + .bInterfaceNumber = 0x00U, + .bAlternateSetting = 0x00U, + .bNumEndpoints = 0x02U, + .bInterfaceClass = USB_HID_CLASS, + .bInterfaceSubClass = 0x00U, + .bInterfaceProtocol = 0x01U, + .iInterface = 0x00U + }, + + .hid_vendor = + { + .header = + { + .bLength = sizeof(usb_desc_hid), + .bDescriptorType = USB_DESCTYPE_HID + }, + .bcdHID = 0x0111U, + .bCountryCode = 0x00U, + .bNumDescriptors = 0x01U, + .bDescriptorType = USB_DESCTYPE_REPORT, + .wDescriptorLength = USB_DESC_LEN_IAP_REPORT, + }, + + .hid_epin = + { + .header = + { + .bLength = sizeof(usb_desc_ep), + .bDescriptorType = USB_DESCTYPE_EP + }, + .bEndpointAddress = IAP_IN_EP, + .bmAttributes = USB_EP_ATTR_INT, + .wMaxPacketSize = IAP_IN_PACKET, + .bInterval = 0x01U + }, + + .hid_epout = + { + .header = + { + .bLength = sizeof(usb_desc_ep), + .bDescriptorType = USB_DESCTYPE_EP + }, + .bEndpointAddress = IAP_OUT_EP, + .bmAttributes = USB_EP_ATTR_INT, + .wMaxPacketSize = IAP_OUT_PACKET, + .bInterval = 0x01U + } +}; + +/* USB language ID Descriptor */ +usb_desc_LANGID usbd_language_id_desc = +{ + .header = + { + .bLength = sizeof(usb_desc_LANGID), + .bDescriptorType = USB_DESCTYPE_STR + }, + .wLANGID = ENG_LANGID +}; + +/* USB manufacture string */ +static usb_desc_str manufacturer_string = +{ + .header = + { + .bLength = USB_STRING_LEN(10U), + .bDescriptorType = USB_DESCTYPE_STR, + }, + .unicode_string = {'G', 'i', 'g', 'a', 'D', 'e', 'v', 'i', 'c', 'e'} +}; + +/* USB product string */ +static usb_desc_str product_string = +{ + .header = + { + .bLength = USB_STRING_LEN(12U), + .bDescriptorType = USB_DESCTYPE_STR, + }, + .unicode_string = {'G', 'D', '3', '2', '-', 'U', 'S', 'B', '_', 'I', 'A', 'P'} +}; + +/* USBD serial string */ +static usb_desc_str serial_string = +{ + .header = + { + .bLength = USB_STRING_LEN(2U), + .bDescriptorType = USB_DESCTYPE_STR, + } +}; + +uint8_t* usbd_iap_strings[] = +{ + [STR_IDX_LANGID] = (uint8_t *)&usbd_language_id_desc, + [STR_IDX_MFC] = (uint8_t *)&manufacturer_string, + [STR_IDX_PRODUCT] = (uint8_t *)&product_string, + [STR_IDX_SERIAL] = (uint8_t *)&serial_string +}; + +usb_desc iap_desc = { + .dev_desc = (uint8_t *)&iap_dev_desc, + .config_desc = (uint8_t *)&iap_config_desc, + .strings = usbd_iap_strings +}; + +/* local function prototypes ('static') */ +static uint8_t iap_init (usb_dev *udev, uint8_t config_index); +static uint8_t iap_deinit (usb_dev *udev, uint8_t config_index); +static uint8_t iap_req_handler (usb_dev *udev, usb_req *req); +static void iap_data_out (usb_dev *udev, uint8_t ep_num); + +usb_class iap_class = { + .init = iap_init, + .deinit = iap_deinit, + .req_process = iap_req_handler, + .data_out = iap_data_out +}; + +/* USB custom HID device report descriptor */ +const uint8_t iap_report_desc[USB_DESC_LEN_IAP_REPORT] = +{ + 0x05, 0x01, /* USAGE_PAGE (Generic Desktop) */ + 0x09, 0x00, /* USAGE (Custom Device) */ + 0xa1, 0x01, /* COLLECTION (Application) */ + + /* IAP command and data */ + 0x85, 0x01, /* REPORT_ID (0x01) */ + 0x09, 0x01, /* USAGE (IAP command) */ + 0x15, 0x00, /* LOGICAL_MINIMUM (0) */ + 0x25, 0xff, /* LOGICAL_MAXIMUM (255) */ + 0x75, 0x08, /* REPORT_SIZE (8) */ + 0x95, 0x3f, /* REPORT_COUNT (63) */ + 0x91, 0x82, /* OUTPUT (Data,Var,Abs,Vol) */ + + /* device status and option byte */ + 0x85, 0x02, /* REPORT_ID (0x02) */ + 0x09, 0x02, /* USAGE (Status and option byte) */ + 0x15, 0x00, /* LOGICAL_MINIMUM (0) */ + 0x25, 0xff, /* LOGICAL_MAXIMUM (255) */ + 0x75, 0x08, /* REPORT_SIZE (8) */ + 0x95, 0x10, /* REPORT_COUNT (16) */ + 0x81, 0x82, /* INPUT (Data,Var,Abs,Vol) */ + + 0xc0 /* END_COLLECTION */ +}; + +/* IAP requests management functions */ +static void iap_req_erase (usb_dev *udev); +static void iap_req_dnload (usb_dev *udev); +static void iap_req_optionbyte(usb_dev *udev); +static void iap_req_leave (usb_dev *udev); +static void iap_address_send (usb_dev *udev); +static void iap_data_write (uint8_t *data, uint32_t addr, uint32_t len); + +/*! + \brief initialize the HID device + \param[in] udev: pointer to USB device instance + \param[in] config_index: configuration index + \param[out] none + \retval USB device operation status +*/ +static uint8_t iap_init (usb_dev *udev, uint8_t config_index) +{ + static usbd_iap_handler iap_handler; + + /* initialize Tx endpoint */ + usbd_ep_init(udev, EP_BUF_SNG, INT_TX_ADDR, &(iap_config_desc.hid_epin)); + + /* initialize Rx endpoint */ + usbd_ep_init(udev, EP_BUF_SNG, INT_RX_ADDR, &(iap_config_desc.hid_epout)); + + /* unlock the internal flash */ + fmc_unlock(); + + memset((void *)&iap_handler, 0, sizeof(usbd_iap_handler)); + + /* prepare receive Data */ + usbd_ep_recev(udev, IAP_OUT_EP, iap_handler.report_buf, IAP_OUT_PACKET); + + udev->ep_transc[EP_ID(IAP_OUT_EP)][TRANSC_OUT] = iap_class.data_out; + + iap_handler.base_address = APP_LOADED_ADDR; + + udev->class_data[USBD_IAP_INTERFACE] = (void *)&iap_handler; + + return USBD_OK; +} + +/*! + \brief de-initialize the HID device + \param[in] udev: pointer to USB device instance + \param[in] config_index: configuration index + \param[out] none + \retval USB device operation status +*/ +static uint8_t iap_deinit (usb_dev *udev, uint8_t config_index) +{ + /* deinitialize HID endpoints */ + usbd_ep_deinit (udev, IAP_IN_EP); + usbd_ep_deinit (udev, IAP_OUT_EP); + + /* lock the internal flash */ + fmc_lock(); + + return USBD_OK; +} + +/*! + \brief handle the HID class-specific requests + \param[in] udev: pointer to USB device instance + \param[in] req: device class-specific request + \param[out] none + \retval USB device operation status +*/ +static uint8_t iap_req_handler (usb_dev *udev, usb_req *req) +{ + uint8_t status = REQ_NOTSUPP; + + usbd_iap_handler *iap = (usbd_iap_handler *)udev->class_data[USBD_IAP_INTERFACE]; + + switch (req->bRequest) { + case GET_REPORT: + /* no use for this driver */ + break; + + case GET_IDLE: + usb_transc_config(&udev->transc_in[0], (uint8_t *)&iap->idlestate, 1U, 0U); + + status = REQ_SUPP; + break; + + case GET_PROTOCOL: + usb_transc_config(&udev->transc_in[0], (uint8_t *)&iap->protocol, 1U, 0U); + + status = REQ_SUPP; + break; + + case SET_REPORT: + iap->reportID = (uint8_t)(req->wValue); + + usb_transc_config(&udev->transc_out[0], iap->report_buf, req->wLength, 0U); + + status = REQ_SUPP; + break; + + case SET_IDLE: + iap->idlestate = (uint8_t)(req->wValue >> 8); + + status = REQ_SUPP; + break; + + case SET_PROTOCOL: + iap->protocol = (uint8_t)(req->wValue); + + status = REQ_SUPP; + break; + + case USB_GET_DESCRIPTOR: + if (USB_DESCTYPE_REPORT == (req->wValue >> 8)) { + usb_transc_config(&udev->transc_in[0], + (uint8_t *)iap_report_desc, + USB_MIN(USB_DESC_LEN_IAP_REPORT, req->wLength), + 0U); + + return REQ_SUPP; + } + break; + + default: + break; + } + + return status; +} + +/*! + \brief handle data out stage + \param[in] udev: pointer to USB device instance + \param[in] ep_num: endpoint number + \param[out] none + \retval none +*/ +static void iap_data_out (usb_dev *udev ,uint8_t ep_num) +{ + usbd_iap_handler *iap = (usbd_iap_handler *)udev->class_data[USBD_IAP_INTERFACE]; + + if (0x01U == iap->report_buf[0]) { + switch(iap->report_buf[1]) { + case IAP_DNLOAD: + iap_req_dnload(udev); + break; + + case IAP_ERASE: + iap_req_erase(udev); + break; + + case IAP_OPTION_BYTE: + iap_req_optionbyte(udev); + break; + + case IAP_LEAVE: + iap_req_leave(udev); + break; + + case IAP_GETBIN_ADDRESS: + iap_address_send(udev); + break; + + default: + break; + } + } + + usbd_ep_recev(udev, IAP_OUT_EP, iap->report_buf, IAP_OUT_PACKET); +} + +/*! + \brief send iap report + \param[in] udev: pointer to USB device instance + \param[in] report: pointer to HID report + \param[in] len: data length + \param[out] none + \retval USB device operation status +*/ +uint8_t iap_report_send (usb_dev *udev, uint8_t *report, uint16_t len) +{ + usbd_ep_send (udev, IAP_IN_EP, report, len); + + return USBD_OK; +} + +/*! + \brief handle the IAP_DNLOAD request + \param[in] udev: pointer to USB device instance + \param[out] none + \retval none +*/ +static void iap_req_dnload (usb_dev *udev) +{ + usbd_iap_handler *iap = (usbd_iap_handler *)udev->class_data[USBD_IAP_INTERFACE]; + + if (0U != iap->transfer_times) { + if (1U == iap->transfer_times) { + if (0U == iap->lps) { + iap_data_write(&iap->report_buf[2], iap->base_address, TRANSFER_SIZE); + } else { + iap_data_write(&iap->report_buf[2], iap->base_address, iap->file_length % TRANSFER_SIZE); + iap->lps = 0U; + } + + iap->dev_status[0] = 0x02U; + iap->dev_status[1] = 0x02U; + iap_report_send (udev, iap->dev_status, IAP_IN_PACKET); + } else { + iap_data_write(&iap->report_buf[2], iap->base_address, TRANSFER_SIZE); + + iap->base_address += TRANSFER_SIZE; + } + + iap->transfer_times--; + } +} + +/*! + \brief handle the IAP_ERASE request + \param[in] udev: pointer to USB device instance + \param[out] none + \retval none +*/ +static void iap_req_erase (usb_dev *udev) +{ + uint32_t i, addr = 0U; + + usbd_iap_handler *iap = (usbd_iap_handler *)udev->class_data[USBD_IAP_INTERFACE]; + + /* get base address to erase */ + iap->base_address = iap->report_buf[2]; + iap->base_address |= (uint32_t)iap->report_buf[3] << 8; + iap->base_address |= (uint32_t)iap->report_buf[4] << 16; + iap->base_address |= (uint32_t)iap->report_buf[5] << 24; + + iap->page_count = iap->report_buf[6]; + + /* get file length */ + iap->file_length = iap->report_buf[7]; + iap->file_length |= (uint32_t)iap->report_buf[8] << 8; + iap->file_length |= (uint32_t)iap->report_buf[9] << 16; + iap->file_length |= (uint32_t)iap->report_buf[10] << 24; + + /* compute last packet size and transfer times */ + iap->lps = iap->file_length % TRANSFER_SIZE; + if (0U == iap->lps) { + iap->transfer_times = (uint16_t)iap->file_length / TRANSFER_SIZE; + } else { + iap->transfer_times = (uint16_t)iap->file_length / TRANSFER_SIZE + 1U; + } + + /* check if the address is in protected area */ + if (IS_PROTECTED_AREA(iap->base_address)) { + return; + } + + addr = iap->base_address; + + for (i = 0U; i < iap->page_count; i ++) { + /* call the standard flash erase-page function */ + fmc_page_erase(addr); + + addr += PAGE_SIZE; + } + + iap->dev_status[0] = 0x02U; + iap->dev_status[1] = 0x01U; + + usbd_ep_send(udev, IAP_IN_EP, iap->dev_status, IAP_IN_PACKET); +} + +/*! + \brief handle the IAP_OPTION_BYTE request + \param[in] udev: pointer to USB device instance + \param[out] none + \retval none +*/ +static void iap_req_optionbyte (usb_dev *udev) +{ + uint8_t i = 0U; + uint32_t address = 0x1FFFF800U; + + usbd_iap_handler *iap = (usbd_iap_handler *)udev->class_data[USBD_IAP_INTERFACE]; + + iap->option_byte[0] = 0x02U; + + for (i = 1U; i < 17U; i++) { + iap->option_byte[i] = *(uint8_t *)address; + address++; + } + + iap_report_send(udev, iap->option_byte, IAP_IN_PACKET); +} + +/*! + \brief handle the IAP_LEAVE request + \param[in] udev: pointer to USB device instance + \param[out] none + \retval none +*/ +static void iap_req_leave (usb_dev *udev) +{ + /* lock the internal flash */ + fmc_lock(); + + /* generate system reset to allow jumping to the user code */ + NVIC_SystemReset(); +} + +/*! + \brief handle the IAP_SEND_ADDRESS request + \param[in] udev: pointer to USB device instance + \param[out] none + \retval none +*/ +static void iap_address_send(usb_dev *udev) +{ + usbd_iap_handler *iap = (usbd_iap_handler *)udev->class_data[USBD_IAP_INTERFACE]; + + iap->bin_addr[0] = 0x02U; + + iap->bin_addr[1] = (uint8_t)(APP_LOADED_ADDR); + iap->bin_addr[2] = (uint8_t)(APP_LOADED_ADDR >> 8); + iap->bin_addr[3] = (uint8_t)(APP_LOADED_ADDR >> 16); + iap->bin_addr[4] = (uint8_t)(APP_LOADED_ADDR >> 24); + + iap_report_send (udev, iap->bin_addr, IAP_IN_PACKET); +} + +/*! + \brief write data to sectors of memory + \param[in] data: data to be written + \param[in] addr: sector address/code + \param[in] len: length of data to be written (in bytes) + \param[out] none + \retval MAL_OK if all operations are OK, MAL_FAIL else +*/ +static void iap_data_write (uint8_t *data, uint32_t addr, uint32_t len) +{ + uint32_t index = 0U; + + /* check if the address is in protected area */ + if (IS_PROTECTED_AREA(addr)) { + return; + } + + if (len & 0x03U) {/* not an aligned data */ + for (index = len; index < ((len & 0xFFFCU) + 4U); index++) { + data[index] = 0xFFU; + } + } + + /* data received are word multiple */ + for (index = 0U; index < len; index += 4U) { + fmc_word_program(addr, *(uint32_t *)(data + index)); + addr += 4U; + } +} diff --git a/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbd_library/class/device/msc/Include/usbd_msc_bbb.h b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbd_library/class/device/msc/Include/usbd_msc_bbb.h new file mode 100644 index 0000000000..24518f078a --- /dev/null +++ b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbd_library/class/device/msc/Include/usbd_msc_bbb.h @@ -0,0 +1,130 @@ +/*! + \file usbd_msc_bbb.h + \brief the header file of the usbd_msc_bot.c file + + \version 2020-08-01, V3.0.0, firmware for GD32F30x + \version 2021-02-20, V3.0.1, firmware for GD32F30x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef __USBD_MSC_BBB_H +#define __USBD_MSC_BBB_H + +#include "usbd_core.h" +#include "usbd_msc_mem.h" +#include "usbd_msc_scsi.h" + +#define BBB_CBW_SIGNATURE 0x43425355U +#define BBB_CSW_SIGNATURE 0x53425355U +#define BBB_CBW_LENGTH 31U +#define BBB_CSW_LENGTH 13U + +typedef struct { + uint32_t dCBWSignature; + uint32_t dCBWTag; + uint32_t dCBWDataTransferLength; + uint8_t bmCBWFlags; + uint8_t bCBWLUN; + uint8_t bCBWCBLength; + uint8_t CBWCB[16]; +}msc_bbb_cbw; + +typedef struct { + uint32_t dCSWSignature; + uint32_t dCSWTag; + uint32_t dCSWDataResidue; + uint8_t bCSWStatus; +}msc_bbb_csw; + +/* CSW command status */ +enum msc_csw_status { + CSW_CMD_PASSED = 0, + CSW_CMD_FAILED, + CSW_PHASE_ERROR +}; + +/* MSC BBB state */ +enum msc_bbb_state { + BBB_IDLE = 0U, /*!< idle state */ + BBB_DATA_OUT, /*!< data OUT state */ + BBB_DATA_IN, /*!< data IN state */ + BBB_LAST_DATA_IN, /*!< last data IN state */ + BBB_SEND_DATA /*!< send immediate data state */ +}; + +/* MSC BBB status */ +enum msc_bbb_status { + BBB_STATUS_NORMAL = 0U, /*!< normal status */ + BBB_STATUS_RECOVERY, /*!< recovery status*/ + BBB_STATUS_ERROR /*!< error status */ +}; + +typedef struct +{ + uint8_t bbb_data[MSC_MEDIA_PACKET_SIZE]; + + uint8_t max_lun; + uint8_t bbb_state; + uint8_t bbb_status; + + uint32_t bbb_datalen; + + msc_bbb_cbw bbb_cbw; + msc_bbb_csw bbb_csw; + + uint8_t scsi_sense_head; + uint8_t scsi_sense_tail; + + uint32_t scsi_blk_size[MEM_LUN_NUM]; + uint32_t scsi_blk_nbr[MEM_LUN_NUM]; + + uint32_t scsi_blk_addr; + uint32_t scsi_blk_len; +// uint32_t scsi_disk_pop; + + msc_scsi_sense scsi_sense[SENSE_LIST_DEEPTH]; +} usbd_msc_handler; + +/* function declarations */ +/* initialize the bbb process */ +void msc_bbb_init (usb_dev *udev); +/* reset the BBB machine */ +void msc_bbb_reset (usb_dev *udev); +/* deinitialize the BBB machine */ +void msc_bbb_deinit (usb_dev *udev); +/* handle BBB data IN stage */ +void msc_bbb_data_in (usb_dev *udev, uint8_t ep_num); +/* handle BBB data OUT stage */ +void msc_bbb_data_out (usb_dev *udev, uint8_t ep_num); +/* send the CSW(command status wrapper) */ +void msc_bbb_csw_send (usb_dev *udev, uint8_t csw_status); +/* complete the clear feature request */ +void msc_bbb_clrfeature (usb_dev *udev, uint8_t ep_num); + +#endif /* __USBD_MSC_BBB_H */ diff --git a/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbd_library/class/device/msc/Include/usbd_msc_core.h b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbd_library/class/device/msc/Include/usbd_msc_core.h new file mode 100644 index 0000000000..cd624dbda5 --- /dev/null +++ b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbd_library/class/device/msc/Include/usbd_msc_core.h @@ -0,0 +1,86 @@ +/*! + \file usbd_msc_core.h + \brief the header file of USB MSC device class core functions + + \version 2020-08-01, V3.0.0, firmware for GD32F30x + \version 2021-02-20, V3.0.1, firmware for GD32F30x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef __USBD_MSC_CORE_H +#define __USBD_MSC_CORE_H + +#include "usbd_core.h" + +/* mass storage device class code */ +#define USB_CLASS_MSC 0x08U + +/* mass storage subclass code */ +#define USB_MSC_SUBCLASS_RBC 0x01U +#define USB_MSC_SUBCLASS_ATAPI 0x02U +#define USB_MSC_SUBCLASS_UFI 0x04U +#define USB_MSC_SUBCLASS_SCSI 0x06U +#define USB_MSC_SUBCLASS_LOCKABLE 0x07U +#define USB_MSC_SUBCLASS_IEEE1667 0x08U + +/* mass storage interface class control protocol codes */ +#define USB_MSC_PROTOCOL_CBI 0x00U +#define USB_MSC_PROTOCOL_CBI_ALT 0x01U +#define USB_MSC_PROTOCOL_BBB 0x50U + +/* mass storage request codes */ +#define USB_MSC_REQ_CODES_ADSC 0x00U +#define USB_MSC_REQ_CODES_GET 0xFCU +#define USB_MSC_REQ_CODES_PUT 0xFDU +#define USB_MSC_REQ_CODES_GML 0xFEU +#define USB_MSC_REQ_CODES_BOMSR 0xFFU + +/* mass storage class-specific request codes */ +#define BBB_GET_MAX_LUN 0xFEU +#define BBB_RESET 0xFFU + +#define USB_MSC_CONFIG_DESC_SIZE 32U + +#define MSC_EPIN_SIZE MSC_DATA_PACKET_SIZE +#define MSC_EPOUT_SIZE MSC_DATA_PACKET_SIZE + +/* USB configuration descriptor structure */ +typedef struct +{ + usb_desc_config config; + + usb_desc_itf msc_itf; + usb_desc_ep msc_epin; + usb_desc_ep msc_epout; +} usb_desc_config_set; + +extern usb_desc msc_desc; +extern usb_class msc_class; + +#endif /* __USBD_MSC_CORE_H */ diff --git a/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbd_library/class/device/msc/Include/usbd_msc_data.h b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbd_library/class/device/msc/Include/usbd_msc_data.h new file mode 100644 index 0000000000..db125424b3 --- /dev/null +++ b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbd_library/class/device/msc/Include/usbd_msc_data.h @@ -0,0 +1,50 @@ +/*! + \file usbd_msc_data.h + \brief the header file of the usbd_msc_data.c file + + \version 2020-08-01, V3.0.0, firmware for GD32F30x + \version 2021-02-20, V3.0.1, firmware for GD32F30x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef __USBD_MSC_DATA_H +#define __USBD_MSC_DATA_H + +#include "usbd_conf.h" + +#define MODE_SENSE6_LENGTH 8U +#define MODE_SENSE10_LENGTH 8U +#define INQUIRY_PAGE00_LENGTH 96U +#define FORMAT_CAPACITIES_LENGTH 20U + +extern const uint8_t msc_page00_inquiry_data[]; +extern const uint8_t msc_mode_sense6_data[]; +extern const uint8_t msc_mode_sense10_data[]; + +#endif /* __USBD_MSC_DATA_H */ diff --git a/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbd_library/class/device/msc/Include/usbd_msc_mem.h b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbd_library/class/device/msc/Include/usbd_msc_mem.h new file mode 100644 index 0000000000..91891ec110 --- /dev/null +++ b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbd_library/class/device/msc/Include/usbd_msc_mem.h @@ -0,0 +1,60 @@ +/*! + \file usbd_msc_mem.h + \brief header file for storage memory + + \version 2020-08-01, V3.0.0, firmware for GD32F30x + \version 2021-02-20, V3.0.1, firmware for GD32F30x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef __USBD_MSC_MEM_H +#define __USBD_MSC_MEM_H + +#include "usbd_conf.h" + +#define USBD_STD_INQUIRY_LENGTH 36U + +typedef struct +{ + int8_t (*mem_init) (uint8_t lun); + int8_t (*mem_ready) (uint8_t lun); + int8_t (*mem_protected) (uint8_t lun); + int8_t (*mem_read) (uint8_t lun, uint8_t *buf, uint32_t block_addr, uint16_t block_len); + int8_t (*mem_write) (uint8_t lun, uint8_t *buf, uint32_t block_addr, uint16_t block_len); + int8_t (*mem_maxlun) (void); + + uint8_t *mem_toc_data; + uint8_t *mem_inquiry_data[MEM_LUN_NUM]; + uint32_t mem_block_size[MEM_LUN_NUM]; + uint32_t mem_block_len[MEM_LUN_NUM]; +}usbd_mem_cb; + +extern usbd_mem_cb *usbd_mem_fops; + +#endif /* __USBD_MSC_MEM_H */ diff --git a/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbd_library/class/device/msc/Include/usbd_msc_scsi.h b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbd_library/class/device/msc/Include/usbd_msc_scsi.h new file mode 100644 index 0000000000..308cf2d807 --- /dev/null +++ b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbd_library/class/device/msc/Include/usbd_msc_scsi.h @@ -0,0 +1,127 @@ +/*! + \file usbd_msc_scsi.h + \brief the header file of the usbd_msc_scsi.c file + + \version 2020-08-01, V3.0.0, firmware for GD32F30x + \version 2021-02-20, V3.0.1, firmware for GD32F30x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef __USBD_MSC_SCSI_H +#define __USBD_MSC_SCSI_H + +#include "usbd_msc_data.h" +#include "usbd_msc_bbb.h" + +#define SENSE_LIST_DEEPTH 4U + +/* SCSI commands */ +#define SCSI_FORMAT_UNIT 0x04U +#define SCSI_INQUIRY 0x12U +#define SCSI_MODE_SELECT6 0x15U +#define SCSI_MODE_SELECT10 0x55U +#define SCSI_MODE_SENSE6 0x1AU +#define SCSI_READ_TOC_DATA 0x43U +#define SCSI_MODE_SENSE10 0x5AU +#define SCSI_ALLOW_MEDIUM_REMOVAL 0x1EU +#define SCSI_READ6 0x08U +#define SCSI_READ10 0x28U +#define SCSI_READ12 0xA8U +#define SCSI_READ16 0x88U + +#define SCSI_READ_CAPACITY10 0x25U +#define SCSI_READ_CAPACITY16 0x9EU + +#define SCSI_REQUEST_SENSE 0x03U +#define SCSI_START_STOP_UNIT 0x1BU +#define SCSI_TEST_UNIT_READY 0x00U +#define SCSI_WRITE6 0x0AU +#define SCSI_WRITE10 0x2AU +#define SCSI_WRITE12 0xAAU +#define SCSI_WRITE16 0x8AU + +#define SCSI_VERIFY10 0x2FU +#define SCSI_VERIFY12 0xAFU +#define SCSI_VERIFY16 0x8FU + +#define SCSI_SEND_DIAGNOSTIC 0x1DU +#define SCSI_READ_FORMAT_CAPACITIES 0x23U + +#define INVALID_CDB 0x20U +#define INVALID_FIELED_IN_COMMAND 0x24U +#define PARAMETER_LIST_LENGTH_ERROR 0x1AU +#define INVALID_FIELD_IN_PARAMETER_LIST 0x26U +#define ADDRESS_OUT_OF_RANGE 0x21U +#define MEDIUM_NOT_PRESENT 0x3AU +#define MEDIUM_HAVE_CHANGED 0x28U +#define WRITE_PROTECTED 0x27U +#define UNRECOVERED_READ_ERROR 0x11U +#define WRITE_FAULT 0x03U + +#define READ_FORMAT_CAPACITY_DATA_LEN 0x0CU +#define READ_CAPACITY10_DATA_LEN 0x08U +#define MODE_SENSE10_DATA_LEN 0x08U +#define MODE_SENSE6_DATA_LEN 0x04U +#define READ_TOC_CMD_LEN 0x14U +#define REQUEST_SENSE_DATA_LEN 0x12U +#define STANDARD_INQUIRY_DATA_LEN 0x24U +#define BLKVFY 0x04U + +enum sense_state { + NO_SENSE = 0U, + RECOVERED_ERROR, + NOT_READY, + MEDIUM_ERROR, + HARDWARE_ERROR, + ILLEGAL_REQUEST, + UNIT_ATTENTION, + DATA_PROTECT, + BLANK_CHECK, + VENDOR_SPECIFIC, + COPY_ABORTED, + ABORTED_COMMAND, + RESERVED, + VOLUME_OVERFLOW, + MISCOMPARE +}; + +typedef struct { + uint8_t SenseKey; + uint32_t Information; + uint8_t ASC; + uint8_t ASCQ; +} msc_scsi_sense; + +/* function declarations */ +/* process SCSI commands */ +int8_t scsi_process_cmd (usb_dev *udev, uint8_t lun, uint8_t *cmd); +/* load the last error code in the error list */ +void scsi_sense_code (usb_dev *udev, uint8_t lun, uint8_t skey, uint8_t asc); + +#endif /* __USBD_MSC_SCSI_H */ diff --git a/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbd_library/class/device/msc/Source/usbd_msc_bbb.c b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbd_library/class/device/msc/Source/usbd_msc_bbb.c new file mode 100644 index 0000000000..7246c11071 --- /dev/null +++ b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbd_library/class/device/msc/Source/usbd_msc_bbb.c @@ -0,0 +1,284 @@ +/*! + \file usbd_msc_bbb.c + \brief USB BBB(Bulk/Bulk/Bulk) protocol core functions + \note BBB means Bulk-only transport protocol for USB MSC + + \version 2020-08-01, V3.0.0, firmware for GD32F30x + \version 2021-02-20, V3.0.1, firmware for GD32F30x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "usbd_enum.h" +#include "usbd_msc_bbb.h" + +/* local function prototypes ('static') */ +static void msc_bbb_cbw_decode (usb_dev *udev); +static void msc_bbb_data_send (usb_dev *udev, uint8_t *pbuf, uint32_t Len); +static void msc_bbb_abort (usb_dev *udev); + +/*! + \brief initialize the bbb process + \param[in] udev: pointer to USB device instance + \param[out] none + \retval none +*/ +void msc_bbb_init (usb_dev *udev) +{ + uint8_t lun_num; + + usbd_msc_handler *msc = (usbd_msc_handler *)udev->class_data[USBD_MSC_INTERFACE]; + + msc->bbb_state = BBB_IDLE; + msc->bbb_status = BBB_STATUS_NORMAL; + + /* initializes the storage logic unit */ + for(lun_num = 0U; lun_num < MEM_LUN_NUM; lun_num++) { + usbd_mem_fops->mem_init(lun_num); + } + + /* prepare endpoint to receive the first BBB CBW */ + usbd_ep_recev (udev, MSC_OUT_EP, (uint8_t *)&msc->bbb_cbw, BBB_CBW_LENGTH); +} + +/*! + \brief reset the BBB machine + \param[in] udev: pointer to USB device instance + \param[out] none + \retval none +*/ +void msc_bbb_reset (usb_dev *udev) +{ + usbd_msc_handler *msc = (usbd_msc_handler *)udev->class_data[USBD_MSC_INTERFACE]; + + msc->bbb_state = BBB_IDLE; + msc->bbb_status = BBB_STATUS_RECOVERY; + + /* prepare endpoint to receive the first BBB command */ + usbd_ep_recev (udev, MSC_OUT_EP, (uint8_t *)&msc->bbb_cbw, BBB_CBW_LENGTH); +} + +/*! + \brief deinitialize the BBB machine + \param[in] udev: pointer to USB device instance + \param[out] none + \retval none +*/ +void msc_bbb_deinit (usb_dev *udev) +{ + usbd_msc_handler *msc = (usbd_msc_handler *)udev->class_data[USBD_MSC_INTERFACE]; + + msc->bbb_state = BBB_IDLE; +} + +/*! + \brief handle BBB data IN stage + \param[in] udev: pointer to USB device instance + \param[in] ep_num: endpoint number + \param[out] none + \retval none +*/ +void msc_bbb_data_in (usb_dev *udev, uint8_t ep_num) +{ + usbd_msc_handler *msc = (usbd_msc_handler *)udev->class_data[USBD_MSC_INTERFACE]; + + switch (msc->bbb_state) { + case BBB_DATA_IN: + if (scsi_process_cmd (udev, msc->bbb_cbw.bCBWLUN, &msc->bbb_cbw.CBWCB[0]) < 0) { + msc_bbb_csw_send (udev, CSW_CMD_FAILED); + } + break; + + case BBB_SEND_DATA: + case BBB_LAST_DATA_IN: + msc_bbb_csw_send (udev, CSW_CMD_PASSED); + break; + + default: + break; + } +} + +/*! + \brief handle BBB data OUT stage + \param[in] udev: pointer to USB device instance + \param[in] ep_num: endpoint number + \param[out] none + \retval none +*/ +void msc_bbb_data_out (usb_dev *udev, uint8_t ep_num) +{ + usbd_msc_handler *msc = (usbd_msc_handler *)udev->class_data[USBD_MSC_INTERFACE]; + + switch (msc->bbb_state) { + case BBB_IDLE: + msc_bbb_cbw_decode (udev); + break; + + case BBB_DATA_OUT: + if (scsi_process_cmd (udev, msc->bbb_cbw.bCBWLUN, &msc->bbb_cbw.CBWCB[0]) < 0) { + msc_bbb_csw_send (udev, CSW_CMD_FAILED); + } + break; + + default: + break; + } +} + +/*! + \brief send the CSW(command status wrapper) + \param[in] udev: pointer to USB device instance + \param[in] csw_status: CSW status + \param[out] none + \retval none +*/ +void msc_bbb_csw_send (usb_dev *udev, uint8_t csw_status) +{ + usbd_msc_handler *msc = (usbd_msc_handler *)udev->class_data[USBD_MSC_INTERFACE]; + + msc->bbb_csw.dCSWSignature = BBB_CSW_SIGNATURE; + msc->bbb_csw.bCSWStatus = csw_status; + msc->bbb_state = BBB_IDLE; + + usbd_ep_send (udev, MSC_IN_EP, (uint8_t *)&msc->bbb_csw, BBB_CSW_LENGTH); + + /* prepare endpoint to receive next command */ + usbd_ep_recev (udev, MSC_OUT_EP, (uint8_t *)&msc->bbb_cbw, BBB_CBW_LENGTH); +} + +/*! + \brief complete the clear feature request + \param[in] udev: pointer to USB device instance + \param[in] ep_num: endpoint number + \param[out] none + \retval none +*/ +void msc_bbb_clrfeature (usb_dev *udev, uint8_t ep_num) +{ + usbd_msc_handler *msc = (usbd_msc_handler *)udev->class_data[USBD_MSC_INTERFACE]; + + if (msc->bbb_status == BBB_STATUS_ERROR)/* bad CBW signature */ { + usbd_ep_stall(udev, MSC_IN_EP); + + msc->bbb_status = BBB_STATUS_NORMAL; + } else if(((ep_num & 0x80U) == 0x80U) && (msc->bbb_status != BBB_STATUS_RECOVERY)) { + msc_bbb_csw_send (udev, CSW_CMD_FAILED); + } else { + + } +} + +/*! + \brief decode the CBW command and set the BBB state machine accordingly + \param[in] udev: pointer to USB device instance + \param[out] none + \retval none +*/ +static void msc_bbb_cbw_decode (usb_dev *udev) +{ + usbd_msc_handler *msc = (usbd_msc_handler *)udev->class_data[USBD_MSC_INTERFACE]; + + uint16_t rx_len = udev->transc_out[MSC_OUT_EP].xfer_count; + + msc->bbb_csw.dCSWTag = msc->bbb_cbw.dCBWTag; + msc->bbb_csw.dCSWDataResidue = msc->bbb_cbw.dCBWDataTransferLength; + + if ((BBB_CBW_LENGTH != rx_len) || + (BBB_CBW_SIGNATURE != msc->bbb_cbw.dCBWSignature)|| + (msc->bbb_cbw.bCBWLUN > 1U) || + (msc->bbb_cbw.bCBWCBLength < 1U) || + (msc->bbb_cbw.bCBWCBLength > 16U)) { + /* illegal command handler */ + scsi_sense_code (udev, msc->bbb_cbw.bCBWLUN, ILLEGAL_REQUEST, INVALID_CDB); + + msc->bbb_status = BBB_STATUS_ERROR; + + msc_bbb_abort (udev); + } else { + if (scsi_process_cmd (udev, msc->bbb_cbw.bCBWLUN, &msc->bbb_cbw.CBWCB[0]) < 0) { + msc_bbb_abort (udev); + } else if ((BBB_DATA_IN != msc->bbb_state) && + (BBB_DATA_OUT != msc->bbb_state) && + (BBB_LAST_DATA_IN != msc->bbb_state)) { /* burst xfer handled internally */ + if (msc->bbb_datalen > 0U) { + msc_bbb_data_send (udev, msc->bbb_data, msc->bbb_datalen); + } else if (0U == msc->bbb_datalen) { + msc_bbb_csw_send (udev, CSW_CMD_PASSED); + } else { + + } + } else { + + } + } +} + +/*! + \brief send the requested data + \param[in] udev: pointer to USB device instance + \param[in] buf: pointer to data buffer + \param[in] len: data length + \param[out] none + \retval none +*/ +static void msc_bbb_data_send (usb_dev *udev, uint8_t *buf, uint32_t len) +{ + usbd_msc_handler *msc = (usbd_msc_handler *)udev->class_data[USBD_MSC_INTERFACE]; + + len = USB_MIN (msc->bbb_cbw.dCBWDataTransferLength, len); + + msc->bbb_csw.dCSWDataResidue -= len; + msc->bbb_csw.bCSWStatus = CSW_CMD_PASSED; + msc->bbb_state = BBB_SEND_DATA; + + usbd_ep_send (udev, MSC_IN_EP, buf, len); +} + +/*! + \brief abort the current transfer + \param[in] udev: pointer to USB device instance + \param[out] none + \retval none +*/ +static void msc_bbb_abort (usb_dev *udev) +{ + usbd_msc_handler *msc = (usbd_msc_handler *)udev->class_data[USBD_MSC_INTERFACE]; + + if ((0U == msc->bbb_cbw.bmCBWFlags) && + (0U != msc->bbb_cbw.dCBWDataTransferLength) && + (BBB_STATUS_NORMAL == msc->bbb_status)) { + usbd_ep_stall(udev, MSC_OUT_EP); + } + + usbd_ep_stall(udev, MSC_IN_EP); + + if (msc->bbb_status == BBB_STATUS_ERROR) { + usbd_ep_recev (udev, MSC_OUT_EP, (uint8_t *)&msc->bbb_cbw, BBB_CBW_LENGTH); + } +} diff --git a/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbd_library/class/device/msc/Source/usbd_msc_core.c b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbd_library/class/device/msc/Source/usbd_msc_core.c new file mode 100644 index 0000000000..bd8b26eafa --- /dev/null +++ b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbd_library/class/device/msc/Source/usbd_msc_core.c @@ -0,0 +1,316 @@ +/*! + \file usbd_msc_core.c + \brief USB MSC device class core functions + + \version 2020-08-01, V3.0.0, firmware for GD32F30x + \version 2021-02-20, V3.0.1, firmware for GD32F30x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "usbd_enum.h" +#include "usbd_msc_bbb.h" +#include "usbd_msc_core.h" +#include "usbd_transc.h" +#include + +#define USBD_VID 0x28E9U +#define USBD_PID 0x128FU + +/* local function prototypes ('static') */ +static uint8_t msc_core_init (usb_dev *udev, uint8_t config_index); +static uint8_t msc_core_deinit (usb_dev *udev, uint8_t config_index); +static uint8_t msc_core_req (usb_dev *udev, usb_req *req); +static void msc_core_in (usb_dev *udev, uint8_t ep_num); +static void msc_core_out (usb_dev *udev, uint8_t ep_num); + +usb_class msc_class = +{ + .init = msc_core_init, + .deinit = msc_core_deinit, + + .req_process = msc_core_req, + + .data_in = msc_core_in, + .data_out = msc_core_out +}; + +/* note: it should use the C99 standard when compiling the below codes */ +/* USB standard device descriptor */ +const usb_desc_dev msc_dev_desc = +{ + .header = { + .bLength = USB_DEV_DESC_LEN, + .bDescriptorType = USB_DESCTYPE_DEV + }, + .bcdUSB = 0x0200U, + .bDeviceClass = 0x00U, + .bDeviceSubClass = 0x00U, + .bDeviceProtocol = 0x00U, + .bMaxPacketSize0 = USBD_EP0_MAX_SIZE, + .idVendor = USBD_VID, + .idProduct = USBD_PID, + .bcdDevice = 0x0100U, + .iManufacturer = STR_IDX_MFC, + .iProduct = STR_IDX_PRODUCT, + .iSerialNumber = STR_IDX_SERIAL, + .bNumberConfigurations = USBD_CFG_MAX_NUM +}; + +/* USB device configuration descriptor */ +const usb_desc_config_set msc_config_desc = +{ + .config = + { + .header = { + .bLength = sizeof(usb_desc_config), + .bDescriptorType = USB_DESCTYPE_CONFIG + }, + .wTotalLength = USB_MSC_CONFIG_DESC_SIZE, + .bNumInterfaces = 0x01U, + .bConfigurationValue = 0x01U, + .iConfiguration = 0x00U, + .bmAttributes = 0xC0U, + .bMaxPower = 0x32U + }, + + .msc_itf = + { + .header = { + .bLength = sizeof(usb_desc_itf), + .bDescriptorType = USB_DESCTYPE_ITF + }, + .bInterfaceNumber = 0x00U, + .bAlternateSetting = 0x00U, + .bNumEndpoints = 0x02U, + .bInterfaceClass = USB_CLASS_MSC, + .bInterfaceSubClass = USB_MSC_SUBCLASS_SCSI, + .bInterfaceProtocol = USB_MSC_PROTOCOL_BBB, + .iInterface = 0x00U + }, + + .msc_epin = + { + .header = { + .bLength = sizeof(usb_desc_ep), + .bDescriptorType = USB_DESCTYPE_EP + }, + .bEndpointAddress = MSC_IN_EP, + .bmAttributes = USB_EP_ATTR_BULK, + .wMaxPacketSize = MSC_EPIN_SIZE, + .bInterval = 0x00U + }, + + .msc_epout = + { + .header = { + .bLength = sizeof(usb_desc_ep), + .bDescriptorType = USB_DESCTYPE_EP + }, + .bEndpointAddress = MSC_OUT_EP, + .bmAttributes = USB_EP_ATTR_BULK, + .wMaxPacketSize = MSC_EPOUT_SIZE, + .bInterval = 0x00U + } +}; + +/* USB language ID descriptor */ +const usb_desc_LANGID usbd_language_id_desc = +{ + .header = + { + .bLength = sizeof(usb_desc_LANGID), + .bDescriptorType = USB_DESCTYPE_STR + }, + .wLANGID = ENG_LANGID +}; + +/* USB manufacture string */ +static const usb_desc_str manufacturer_string = +{ + .header = + { + .bLength = USB_STRING_LEN(10U), + .bDescriptorType = USB_DESCTYPE_STR, + }, + .unicode_string = {'G', 'i', 'g', 'a', 'D', 'e', 'v', 'i', 'c', 'e'} +}; + +/* USB product string */ +static const usb_desc_str product_string = +{ + .header = + { + .bLength = USB_STRING_LEN(12U), + .bDescriptorType = USB_DESCTYPE_STR, + }, + .unicode_string = {'G', 'D', '3', '2', '-', 'U', 'S', 'B', '_', 'M', 'S', 'C'} +}; + +/* USBD serial string */ +static usb_desc_str serial_string = +{ + .header = + { + .bLength = USB_STRING_LEN(12U), + .bDescriptorType = USB_DESCTYPE_STR, + } +}; + +/* USB string descriptor */ +uint8_t* usbd_msc_strings[] = +{ + [STR_IDX_LANGID] = (uint8_t *)&usbd_language_id_desc, + [STR_IDX_MFC] = (uint8_t *)&manufacturer_string, + [STR_IDX_PRODUCT] = (uint8_t *)&product_string, + [STR_IDX_SERIAL] = (uint8_t *)&serial_string +}; + +usb_desc msc_desc = { + .dev_desc = (uint8_t *)&msc_dev_desc, + .config_desc = (uint8_t *)&msc_config_desc, + .strings = usbd_msc_strings +}; + +static uint8_t usbd_msc_maxlun = 0U; + +/*! + \brief initialize the MSC device + \param[in] udev: pointer to USB device instance + \param[in] config_index: configuration index + \param[out] none + \retval USB device operation status +*/ +static uint8_t msc_core_init (usb_dev *udev, uint8_t config_index) +{ + static usbd_msc_handler msc_handler; + + memset((void *)&msc_handler, 0U, sizeof(usbd_msc_handler)); + + udev->class_data[USBD_MSC_INTERFACE] = (void *)&msc_handler; + + /* initialize Tx endpoint */ + usbd_ep_init(udev, EP_BUF_SNG, BULK_TX_ADDR, &(msc_config_desc.msc_epin)); + + /* initialize Rx endpoint */ + usbd_ep_init(udev, EP_BUF_SNG, BULK_RX_ADDR, &(msc_config_desc.msc_epout)); + + udev->ep_transc[EP_ID(MSC_IN_EP)][TRANSC_IN] = msc_class.data_in; + udev->ep_transc[MSC_OUT_EP][TRANSC_OUT] = msc_class.data_out; + + /* initialize the BBB layer */ + msc_bbb_init(udev); + + return USBD_OK; +} + +/*! + \brief deinitialize the MSC device + \param[in] udev: pointer to USB device instance + \param[in] config_index: configuration index + \param[out] none + \retval USB device operation status +*/ +static uint8_t msc_core_deinit (usb_dev *udev, uint8_t config_index) +{ + /* clear MSC endpoints */ + usbd_ep_deinit (udev, MSC_IN_EP); + usbd_ep_deinit (udev, MSC_OUT_EP); + + /* deinitialize the BBB layer */ + msc_bbb_deinit(udev); + + return USBD_OK; +} + +/*! + \brief handle the MSC class-specific and standard requests + \param[in] udev: pointer to USB device instance + \param[in] req: device class-specific request + \param[out] none + \retval USB device operation status +*/ +static uint8_t msc_core_req (usb_dev *udev, usb_req *req) +{ + switch (req->bRequest) { + case BBB_GET_MAX_LUN : + if((0U == req->wValue) && + (1U == req->wLength) && + (0x80U == (req->bmRequestType & 0x80U))) { + usbd_msc_maxlun = (uint8_t)usbd_mem_fops->mem_maxlun(); + + usb_transc_config(&udev->transc_in[0], &usbd_msc_maxlun, 1U, 0U); + } else { + return USBD_FAIL; + } + break; + + case BBB_RESET : + if((0U == req->wValue) && + (0U == req->wLength) && + (0x80U != (req->bmRequestType & 0x80U))) { + msc_bbb_reset(udev); + } else { + return USBD_FAIL; + } + break; + + case USB_CLEAR_FEATURE: + msc_bbb_clrfeature (udev, (uint8_t)req->wIndex); + break; + + default: + return USBD_FAIL; + } + + return USBD_OK; +} + +/*! + \brief handle data in stage + \param[in] udev: pointer to USB device instance + \param[in] ep_num: the endpoint number + \param[out] none + \retval none +*/ +static void msc_core_in (usb_dev *udev, uint8_t ep_num) +{ + msc_bbb_data_in(udev, ep_num); +} + +/*! + \brief handle data out stage + \param[in] udev: pointer to USB device instance + \param[in] ep_num: the endpoint number + \param[out] none + \retval none +*/ +static void msc_core_out (usb_dev *udev, uint8_t ep_num) +{ + msc_bbb_data_out (udev, ep_num); +} diff --git a/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbd_library/class/device/msc/Source/usbd_msc_data.c b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbd_library/class/device/msc/Source/usbd_msc_data.c new file mode 100644 index 0000000000..9e81754c1e --- /dev/null +++ b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbd_library/class/device/msc/Source/usbd_msc_data.c @@ -0,0 +1,74 @@ +/*! + \file msc_bbb_scsi.h + \brief the header file of the msc_bbb_scsi.c + + \version 2020-08-01, V3.0.0, firmware for GD32F30x + \version 2021-02-20, V3.0.1, firmware for GD32F30x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "usbd_msc_data.h" + +/* USB mass storage page 0 inquiry data */ +const uint8_t msc_page00_inquiry_data[] = +{ + 0x00U, + 0x00U, + 0x00U, + 0x00U, + (INQUIRY_PAGE00_LENGTH - 4U), + 0x80U, + 0x83U, +}; + +/* USB mass storage sense 6 data */ +const uint8_t msc_mode_sense6_data[] = +{ + 0x00U, + 0x00U, + 0x00U, + 0x00U, + 0x00U, + 0x00U, + 0x00U, + 0x00U +}; + +/* USB mass storage sense 10 data */ +const uint8_t msc_mode_sense10_data[] = +{ + 0x00U, + 0x06U, + 0x00U, + 0x00U, + 0x00U, + 0x00U, + 0x00U, + 0x00U +}; diff --git a/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbd_library/class/device/msc/Source/usbd_msc_scsi.c b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbd_library/class/device/msc/Source/usbd_msc_scsi.c new file mode 100644 index 0000000000..25152de1c7 --- /dev/null +++ b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbd_library/class/device/msc/Source/usbd_msc_scsi.c @@ -0,0 +1,729 @@ +/*! + \file usbd_msc_scsi.c + \brief USB SCSI layer functions + + \version 2020-08-01, V3.0.0, firmware for GD32F30x + \version 2021-02-20, V3.0.1, firmware for GD32F30x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "usbd_enum.h" +#include "usbd_msc_bbb.h" +#include "usbd_msc_scsi.h" +#include "usbd_msc_data.h" + +/* local function prototypes ('static') */ +static int8_t scsi_test_unit_ready (usb_dev *udev, uint8_t lun, uint8_t *params); +static int8_t scsi_mode_select6 (usb_dev *udev, uint8_t lun, uint8_t *params); +static int8_t scsi_mode_select10 (usb_dev *udev, uint8_t lun, uint8_t *params); +static int8_t scsi_inquiry (usb_dev *udev, uint8_t lun, uint8_t *params); +static int8_t scsi_read_format_capacity (usb_dev *udev, uint8_t lun, uint8_t *params); +static int8_t scsi_read_capacity10 (usb_dev *udev, uint8_t lun, uint8_t *params); +static int8_t scsi_request_sense (usb_dev *udev, uint8_t lun, uint8_t *params); +static int8_t scsi_mode_sense6 (usb_dev *udev, uint8_t lun, uint8_t *params); +static int8_t scsi_toc_cmd_read (usb_dev *udev, uint8_t lun, uint8_t *params); +static int8_t scsi_mode_sense10 (usb_dev *udev, uint8_t lun, uint8_t *params); +static int8_t scsi_write10 (usb_dev *udev, uint8_t lun, uint8_t *params); +static int8_t scsi_read10 (usb_dev *udev, uint8_t lun, uint8_t *params); +static int8_t scsi_verify10 (usb_dev *udev, uint8_t lun, uint8_t *params); + +static int8_t scsi_process_read (usb_dev *udev, uint8_t lun); +static int8_t scsi_process_write (usb_dev *udev, uint8_t lun); + +static inline int8_t scsi_check_address_range (usb_dev *udev, uint8_t lun, uint32_t blk_offset, uint16_t blk_nbr); +static inline int8_t scsi_format_cmd (usb_dev *udev, uint8_t lun); +static inline int8_t scsi_start_stop_unit (usb_dev *udev, uint8_t lun, uint8_t *params); +static inline int8_t scsi_allow_medium_removal (usb_dev *udev, uint8_t lun, uint8_t *params); + +/*! + \brief process SCSI commands + \param[in] udev: pointer to USB device instance + \param[in] lun: logical unit number + \param[in] params: command parameters + \param[out] none + \retval status +*/ +int8_t scsi_process_cmd(usb_dev *udev, uint8_t lun, uint8_t *params) +{ + switch (params[0]) { + case SCSI_TEST_UNIT_READY: + return scsi_test_unit_ready (udev, lun, params); + + case SCSI_REQUEST_SENSE: + return scsi_request_sense (udev, lun, params); + + case SCSI_INQUIRY: + return scsi_inquiry (udev, lun, params); + + case SCSI_START_STOP_UNIT: + return scsi_start_stop_unit (udev, lun, params); + + case SCSI_ALLOW_MEDIUM_REMOVAL: + return scsi_allow_medium_removal (udev, lun, params); + + case SCSI_MODE_SENSE6: + return scsi_mode_sense6 (udev, lun, params); + + case SCSI_MODE_SENSE10: + return scsi_mode_sense10 (udev, lun, params); + + case SCSI_READ_FORMAT_CAPACITIES: + return scsi_read_format_capacity (udev, lun, params); + + case SCSI_READ_CAPACITY10: + return scsi_read_capacity10 (udev, lun, params); + + case SCSI_READ10: + return scsi_read10 (udev, lun, params); + + case SCSI_WRITE10: + return scsi_write10 (udev, lun, params); + + case SCSI_VERIFY10: + return scsi_verify10 (udev, lun, params); + + case SCSI_FORMAT_UNIT: + return scsi_format_cmd (udev, lun); + + case SCSI_READ_TOC_DATA: + return scsi_toc_cmd_read (udev, lun, params); + + case SCSI_MODE_SELECT6: + return scsi_mode_select6 (udev, lun, params); + + case SCSI_MODE_SELECT10: + return scsi_mode_select10 (udev, lun, params); + + default: + scsi_sense_code (udev, lun, ILLEGAL_REQUEST, INVALID_CDB); + return -1; + } +} + +/*! + \brief load the last error code in the error list + \param[in] udev: pointer to USB device instance + \param[in] lun: logical unit number + \param[in] skey: sense key + \param[in] asc: additional sense key + \param[out] none + \retval none +*/ +void scsi_sense_code (usb_dev *udev, uint8_t lun, uint8_t skey, uint8_t asc) +{ + usbd_msc_handler *msc = (usbd_msc_handler *)udev->class_data[USBD_MSC_INTERFACE]; + + msc->scsi_sense[msc->scsi_sense_tail].SenseKey = skey; + msc->scsi_sense[msc->scsi_sense_tail].ASC = asc << 8U; + msc->scsi_sense_tail++; + + if (SENSE_LIST_DEEPTH == msc->scsi_sense_tail) { + msc->scsi_sense_tail = 0U; + } +} + +/*! + \brief process SCSI Test Unit Ready command + \param[in] udev: pointer to USB device instance + \param[in] lun: logical unit number + \param[in] params: command parameters + \param[out] none + \retval status +*/ +static int8_t scsi_test_unit_ready (usb_dev *udev, uint8_t lun, uint8_t *params) +{ + usbd_msc_handler *msc = (usbd_msc_handler *)udev->class_data[USBD_MSC_INTERFACE]; + + /* case 9 : Hi > D0 */ + if (0U != msc->bbb_cbw.dCBWDataTransferLength) { + scsi_sense_code (udev, msc->bbb_cbw.bCBWLUN, ILLEGAL_REQUEST, INVALID_CDB); + + return -1; + } + + if (0 != usbd_mem_fops->mem_ready(lun)) { + scsi_sense_code(udev, lun, NOT_READY, MEDIUM_NOT_PRESENT); + + return -1; + } + +// if (1U == msc->scsi_disk_pop) { +// usbd_disconnect (udev); +// } + + msc->bbb_datalen = 0U; + + return 0; +} + +/*! + \brief process Inquiry command + \param[in] udev: pointer to USB device instance + \param[in] lun: logical unit number + \param[in] params: command parameters + \param[out] none + \retval status +*/ +static int8_t scsi_mode_select6 (usb_dev *udev, uint8_t lun, uint8_t *params) +{ + usbd_msc_handler *msc = (usbd_msc_handler *)udev->class_data[USBD_MSC_INTERFACE]; + + msc->bbb_datalen = 0U; + + return 0; +} + +/*! + \brief process Inquiry command + \param[in] udev: pointer to USB device instance + \param[in] lun: logical unit number + \param[in] params: command parameters + \param[out] none + \retval status +*/ +static int8_t scsi_mode_select10 (usb_dev *udev, uint8_t lun, uint8_t *params) +{ + usbd_msc_handler *msc = (usbd_msc_handler *)udev->class_data[USBD_MSC_INTERFACE]; + + msc->bbb_datalen = 0U; + + return 0; +} + +/*! + \brief process Inquiry command + \param[in] udev: pointer to USB device instance + \param[in] lun: logical unit number + \param[in] params: command parameters + \param[out] none + \retval status +*/ +static int8_t scsi_inquiry (usb_dev *udev, uint8_t lun, uint8_t *params) +{ + uint8_t *page = NULL; + uint16_t len = 0U; + + usbd_msc_handler *msc = (usbd_msc_handler *)udev->class_data[USBD_MSC_INTERFACE]; + + if (params[1] & 0x01U) { + page = (uint8_t *)msc_page00_inquiry_data; + + len = INQUIRY_PAGE00_LENGTH; + } else { + page = (uint8_t *)usbd_mem_fops->mem_inquiry_data[lun]; + + len = (uint16_t)(page[4] + 5U); + + if (params[4] <= len) { + len = params[4]; + } + } + + msc->bbb_datalen = len; + + while (len) { + len--; + msc->bbb_data[len] = page[len]; + } + + return 0; +} + +/*! + \brief process Read Capacity 10 command + \param[in] udev: pointer to USB device instance + \param[in] lun: logical unit number + \param[in] params: command parameters + \param[out] none + \retval status +*/ +static int8_t scsi_read_capacity10 (usb_dev *udev, uint8_t lun, uint8_t *params) +{ + uint32_t blk_num = usbd_mem_fops->mem_block_len[lun] - 1U; + usbd_msc_handler *msc = (usbd_msc_handler *)udev->class_data[USBD_MSC_INTERFACE]; + + msc->scsi_blk_nbr[lun] = usbd_mem_fops->mem_block_len[lun]; + msc->scsi_blk_size[lun] = usbd_mem_fops->mem_block_size[lun]; + + msc->bbb_data[0] = (uint8_t)(blk_num >> 24U); + msc->bbb_data[1] = (uint8_t)(blk_num >> 16U); + msc->bbb_data[2] = (uint8_t)(blk_num >> 8U); + msc->bbb_data[3] = (uint8_t)(blk_num); + + msc->bbb_data[4] = (uint8_t)(msc->scsi_blk_size[lun] >> 24U); + msc->bbb_data[5] = (uint8_t)(msc->scsi_blk_size[lun] >> 16U); + msc->bbb_data[6] = (uint8_t)(msc->scsi_blk_size[lun] >> 8U); + msc->bbb_data[7] = (uint8_t)(msc->scsi_blk_size[lun]); + + msc->bbb_datalen = 8U; + + return 0; +} + +/*! + \brief process Read Format Capacity command + \param[in] udev: pointer to USB device instance + \param[in] lun: logical unit number + \param[in] params: command parameters + \param[out] none + \retval status +*/ +static int8_t scsi_read_format_capacity (usb_dev *udev, uint8_t lun, uint8_t *params) +{ + uint16_t i = 0U; + uint32_t blk_size = usbd_mem_fops->mem_block_size[lun]; + uint32_t blk_num = usbd_mem_fops->mem_block_len[lun]; + uint32_t blk_nbr = blk_num - 1U; + + usbd_msc_handler *msc = (usbd_msc_handler *)udev->class_data[USBD_MSC_INTERFACE]; + + for (i = 0U; i < 12U; i++) { + msc->bbb_data[i] = 0U; + } + + msc->bbb_data[3] = 0x08U; + msc->bbb_data[4] = (uint8_t)(blk_nbr >> 24U); + msc->bbb_data[5] = (uint8_t)(blk_nbr >> 16U); + msc->bbb_data[6] = (uint8_t)(blk_nbr >> 8U); + msc->bbb_data[7] = (uint8_t)(blk_nbr); + + msc->bbb_data[8] = 0x02U; + msc->bbb_data[9] = (uint8_t)(blk_size >> 16U); + msc->bbb_data[10] = (uint8_t)(blk_size >> 8U); + msc->bbb_data[11] = (uint8_t)(blk_size); + + msc->bbb_datalen = 12U; + + return 0; +} + +/*! + \brief process Mode Sense6 command + \param[in] udev: pointer to USB device instance + \param[in] lun: logical unit number + \param[in] params: command parameters + \param[out] none + \retval status +*/ +static int8_t scsi_mode_sense6 (usb_dev *udev, uint8_t lun, uint8_t *params) +{ + uint16_t len = 8U; + usbd_msc_handler *msc = (usbd_msc_handler *)udev->class_data[USBD_MSC_INTERFACE]; + + msc->bbb_datalen = len; + + while (len) { + len--; + msc->bbb_data[len] = msc_mode_sense6_data[len]; + } + + return 0; +} + +/*! + \brief process Mode Sense10 command + \param[in] udev: pointer to USB device instance + \param[in] lun: logical unit number + \param[in] params: command parameters + \param[out] none + \retval status +*/ +static int8_t scsi_mode_sense10 (usb_dev *udev, uint8_t lun, uint8_t *params) +{ + uint16_t len = 8U; + usbd_msc_handler *msc = (usbd_msc_handler *)udev->class_data[USBD_MSC_INTERFACE]; + + msc->bbb_datalen = len; + + while (len) { + len--; + msc->bbb_data[len] = msc_mode_sense10_data[len]; + } + + return 0; +} + +/*! + \brief process Request Sense command + \param[in] udev: pointer to USB device instance + \param[in] lun: logical unit number + \param[in] params: command parameters + \param[out] none + \retval status +*/ +static int8_t scsi_request_sense (usb_dev *udev, uint8_t lun, uint8_t *params) +{ + uint8_t i = 0U; + usbd_msc_handler *msc = (usbd_msc_handler *)udev->class_data[USBD_MSC_INTERFACE]; + + for (i = 0U; i < REQUEST_SENSE_DATA_LEN; i++) { + msc->bbb_data[i] = 0U; + } + + msc->bbb_data[0] = 0x70U; + msc->bbb_data[7] = REQUEST_SENSE_DATA_LEN - 6U; + + if ((msc->scsi_sense_head != msc->scsi_sense_tail)) { + msc->bbb_data[2] = msc->scsi_sense[msc->scsi_sense_head].SenseKey; + msc->bbb_data[12] = msc->scsi_sense[msc->scsi_sense_head].ASCQ; + msc->bbb_data[13] = msc->scsi_sense[msc->scsi_sense_head].ASC; + msc->scsi_sense_head++; + + if (msc->scsi_sense_head == SENSE_LIST_DEEPTH) { + msc->scsi_sense_head = 0U; + } + } + + msc->bbb_datalen = USB_MIN(REQUEST_SENSE_DATA_LEN, params[4]); + + return 0; +} + +/*! + \brief process Start Stop Unit command + \param[in] udev: pointer to USB device instance + \param[in] lun: logical unit number + \param[in] params: command parameters + \param[out] none + \retval status +*/ +static inline int8_t scsi_start_stop_unit (usb_dev *udev, uint8_t lun, uint8_t *params) +{ + usbd_msc_handler *msc = (usbd_msc_handler *)udev->class_data[USBD_MSC_INTERFACE]; + + msc->bbb_datalen = 0U; +// msc->scsi_disk_pop = 1U; + + return 0; +} + +/*! + \brief process Allow Medium Removal command + \param[in] udev: pointer to USB device instance + \param[in] lun: logical unit number + \param[in] params: command parameters + \param[out] none + \retval status +*/ +static inline int8_t scsi_allow_medium_removal (usb_dev *udev, uint8_t lun, uint8_t *params) +{ + usbd_msc_handler *msc = (usbd_msc_handler *)udev->class_data[USBD_MSC_INTERFACE]; + + msc->bbb_datalen = 0U; + + return 0; +} + +/*! + \brief process Read10 command + \param[in] udev: pointer to USB device instance + \param[in] lun: logical unit number + \param[in] params: command parameters + \param[out] none + \retval status +*/ +static int8_t scsi_read10 (usb_dev *udev, uint8_t lun, uint8_t *params) +{ + usbd_msc_handler *msc = (usbd_msc_handler *)udev->class_data[USBD_MSC_INTERFACE]; + + if (msc->bbb_state == BBB_IDLE) { + /* direction is from device to host */ + if (0x80U != (msc->bbb_cbw.bmCBWFlags & 0x80U)) { + scsi_sense_code (udev, msc->bbb_cbw.bCBWLUN, ILLEGAL_REQUEST, INVALID_CDB); + + return -1; + } + + if (0 != usbd_mem_fops->mem_ready(lun)) { + scsi_sense_code (udev, lun, NOT_READY, MEDIUM_NOT_PRESENT); + + return -1; + } + + msc->scsi_blk_addr = (params[2] << 24U) | (params[3] << 16U) | \ + (params[4] << 8U) | params[5]; + + msc->scsi_blk_len = (params[7] << 8U) | params[8]; + + if (scsi_check_address_range (udev, lun, msc->scsi_blk_addr, (uint16_t)msc->scsi_blk_len) < 0) { + return -1; /* error */ + } + + msc->bbb_state = BBB_DATA_IN; + + msc->scsi_blk_addr *= msc->scsi_blk_size[lun]; + msc->scsi_blk_len *= msc->scsi_blk_size[lun]; + + /* cases 4,5 : Hi <> Dn */ + if (msc->bbb_cbw.dCBWDataTransferLength != msc->scsi_blk_len) { + scsi_sense_code (udev, msc->bbb_cbw.bCBWLUN, ILLEGAL_REQUEST, INVALID_CDB); + + return -1; + } + } + + msc->bbb_datalen = MSC_MEDIA_PACKET_SIZE; + + return scsi_process_read (udev, lun); +} + +/*! + \brief process Write10 command + \param[in] udev: pointer to USB device instance + \param[in] lun: logical unit number + \param[in] params: command parameters + \param[out] none + \retval status +*/ +static int8_t scsi_write10 (usb_dev *udev, uint8_t lun, uint8_t *params) +{ + usbd_msc_handler *msc = (usbd_msc_handler *)udev->class_data[USBD_MSC_INTERFACE]; + + if (BBB_IDLE == msc->bbb_state) { + /* case 8 : Hi <> Do */ + if (0x80U == (msc->bbb_cbw.bmCBWFlags & 0x80U)) { + scsi_sense_code (udev, msc->bbb_cbw.bCBWLUN, ILLEGAL_REQUEST, INVALID_CDB); + + return -1; + } + + /* check whether media is ready */ + if (0 != usbd_mem_fops->mem_ready(lun)) { + scsi_sense_code (udev, lun, NOT_READY, MEDIUM_NOT_PRESENT); + + return -1; + } + + /* check if media is write-protected */ + if (0 != usbd_mem_fops->mem_protected(lun)) { + scsi_sense_code (udev, lun, NOT_READY, WRITE_PROTECTED); + + return -1; + } + + msc->scsi_blk_addr = (params[2] << 24U) | (params[3] << 16U) | \ + (params[4] << 8U) | params[5]; + + msc->scsi_blk_len = (params[7] << 8U) | params[8]; + + /* check if LBA address is in the right range */ + if (scsi_check_address_range (udev, lun, msc->scsi_blk_addr, (uint16_t)msc->scsi_blk_len) < 0) { + return -1; /* error */ + } + + msc->scsi_blk_addr *= msc->scsi_blk_size[lun]; + msc->scsi_blk_len *= msc->scsi_blk_size[lun]; + + /* cases 3,11,13 : Hn,Ho <> D0 */ + if (msc->bbb_cbw.dCBWDataTransferLength != msc->scsi_blk_len) { + scsi_sense_code (udev, msc->bbb_cbw.bCBWLUN, ILLEGAL_REQUEST, INVALID_CDB); + + return -1; + } + + /* prepare endpoint to receive first data packet */ + msc->bbb_state = BBB_DATA_OUT; + + usbd_ep_recev (udev, + MSC_OUT_EP, + msc->bbb_data, + USB_MIN (msc->scsi_blk_len, MSC_MEDIA_PACKET_SIZE)); + } else { /* write process ongoing */ + return scsi_process_write (udev, lun); + } + + return 0; +} + +/*! + \brief process Verify10 command + \param[in] udev: pointer to USB device instance + \param[in] lun: logical unit number + \param[in] params: command parameters + \param[out] none + \retval status +*/ +static int8_t scsi_verify10 (usb_dev *udev, uint8_t lun, uint8_t *params) +{ + usbd_msc_handler *msc = (usbd_msc_handler *)udev->class_data[USBD_MSC_INTERFACE]; + + if (0x02U == (params[1] & 0x02U)) { + scsi_sense_code (udev, lun, ILLEGAL_REQUEST, INVALID_FIELED_IN_COMMAND); + + return -1; /* error, verify mode not supported*/ + } + + if (scsi_check_address_range (udev, lun, msc->scsi_blk_addr, (uint16_t)msc->scsi_blk_len) < 0) { + return -1; /* error */ + } + + msc->bbb_datalen = 0U; + + return 0; +} + +/*! + \brief check address range + \param[in] udev: pointer to USB device instance + \param[in] lun: logical unit number + \param[in] blk_offset: block offset + \param[in] blk_nbr: number of block to be processed + \param[out] none + \retval status +*/ +static inline int8_t scsi_check_address_range (usb_dev *udev, uint8_t lun, uint32_t blk_offset, uint16_t blk_nbr) +{ + usbd_msc_handler *msc = (usbd_msc_handler *)udev->class_data[USBD_MSC_INTERFACE]; + + if ((blk_offset + blk_nbr) > msc->scsi_blk_nbr[lun]) { + scsi_sense_code (udev, lun, ILLEGAL_REQUEST, ADDRESS_OUT_OF_RANGE); + + return -1; + } + + return 0; +} + +/*! + \brief handle read process + \param[in] udev: pointer to USB device instance + \param[in] lun: logical unit number + \param[out] none + \retval status +*/ +static int8_t scsi_process_read (usb_dev *udev, uint8_t lun) +{ + usbd_msc_handler *msc = (usbd_msc_handler *)udev->class_data[USBD_MSC_INTERFACE]; + + uint32_t len = USB_MIN(msc->scsi_blk_len, MSC_MEDIA_PACKET_SIZE); + + if (usbd_mem_fops->mem_read(lun, + msc->bbb_data, + msc->scsi_blk_addr, + (uint16_t)(len / msc->scsi_blk_size[lun])) < 0) { + scsi_sense_code(udev, lun, HARDWARE_ERROR, UNRECOVERED_READ_ERROR); + + return -1; + } + + usbd_ep_send (udev, MSC_IN_EP, msc->bbb_data, len); + + msc->scsi_blk_addr += len; + msc->scsi_blk_len -= len; + + /* case 6 : Hi = Di */ + msc->bbb_csw.dCSWDataResidue -= len; + + if (0U == msc->scsi_blk_len) { + msc->bbb_state = BBB_LAST_DATA_IN; + } + + return 0; +} + +/*! + \brief handle write process + \param[in] udev: pointer to USB device instance + \param[in] lun: logical unit number + \param[out] none + \retval status +*/ +static int8_t scsi_process_write (usb_dev *udev, uint8_t lun) +{ + usbd_msc_handler *msc = (usbd_msc_handler *)udev->class_data[USBD_MSC_INTERFACE]; + + uint32_t len = USB_MIN(msc->scsi_blk_len, MSC_MEDIA_PACKET_SIZE); + + if (usbd_mem_fops->mem_write (lun, + msc->bbb_data, + msc->scsi_blk_addr, + (uint16_t)(len / msc->scsi_blk_size[lun])) < 0) { + scsi_sense_code(udev, lun, HARDWARE_ERROR, WRITE_FAULT); + + return -1; + } + + msc->scsi_blk_addr += len; + msc->scsi_blk_len -= len; + + /* case 12 : Ho = Do */ + msc->bbb_csw.dCSWDataResidue -= len; + + if (0U == msc->scsi_blk_len) { + msc_bbb_csw_send (udev, CSW_CMD_PASSED); + } else { + /* prepare endpoint to receive next packet */ + usbd_ep_recev (udev, + MSC_OUT_EP, + msc->bbb_data, + USB_MIN (msc->scsi_blk_len, MSC_MEDIA_PACKET_SIZE)); + } + + return 0; +} + +/*! + \brief process Format Unit command + \param[in] udev: pointer to USB device instance + \param[in] lun: logical unit number + \param[out] none + \retval status +*/ +static inline int8_t scsi_format_cmd (usb_dev *udev, uint8_t lun) +{ + return 0; +} + +/*! + \brief process Read_Toc command + \param[in] udev: pointer to USB device instance + \param[in] lun: logical unit number + \param[in] params: command parameters + \param[out] none + \retval status +*/ +static int8_t scsi_toc_cmd_read (usb_dev *udev, uint8_t lun, uint8_t *params) +{ + uint8_t* pPage; + uint16_t len; + + usbd_msc_handler *msc = (usbd_msc_handler *)udev->class_data[USBD_MSC_INTERFACE]; + + pPage = (uint8_t *)&usbd_mem_fops->mem_toc_data[lun * READ_TOC_CMD_LEN]; + len = (uint16_t)pPage[1] + 2U; + + msc->bbb_datalen = len; + + while (len) { + len--; + msc->bbb_data[len] = pPage[len]; + } + + return 0; +} diff --git a/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbd_library/class/device/printer/Include/printer_core.h b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbd_library/class/device/printer/Include/printer_core.h new file mode 100644 index 0000000000..98b2ee4fe0 --- /dev/null +++ b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbd_library/class/device/printer/Include/printer_core.h @@ -0,0 +1,73 @@ +/*! + \file printer_core.h + \brief the header file of USB printer device class core functions + + \version 2020-08-01, V3.0.0, firmware for GD32F30x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef __PRINTER_CORE_H +#define __PRINTER_CORE_H + +#include "usbd_enum.h" + +/* USB printing device class code */ +#define USB_CLASS_PRINTER 0x07U + +/* printing device subclass code */ +#define USB_SUBCLASS_PRINTER 0x01U + +/* printing device protocol code */ +#define PROTOCOL_UNIDIRECTIONAL_ITF 0x01U +#define PROTOCOL_BI_DIRECTIONAL_ITF 0x02U +#define PROTOCOL_1284_4_ITF 0x03U +#define PROTOCOL_VENDOR 0xFFU + +#define DEVICE_ID_LEN 103U + +#define USB_PRINTER_CONFIG_DESC_LEN 32U + +/* printing device specific-class request */ +#define GET_DEVICE_ID 0x00U +#define GET_PORT_STATUS 0x01U +#define SOFT_RESET 0x02U + +/* USB configuration descriptor structure */ +typedef struct +{ + usb_desc_config config; + usb_desc_itf printer_itf; + usb_desc_ep printer_epin; + usb_desc_ep printer_epout; +} usb_printer_desc_config_set; + +extern usb_desc printer_desc; +extern usb_class printer_class; + +#endif /* __PRINTER_CORE_H */ diff --git a/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbd_library/class/device/printer/Source/printer_core.c b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbd_library/class/device/printer/Source/printer_core.c new file mode 100644 index 0000000000..720bda45cf --- /dev/null +++ b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbd_library/class/device/printer/Source/printer_core.c @@ -0,0 +1,310 @@ +/*! + \file printer_core.c + \brief USB printer device class core functions + + \version 2020-08-01, V3.0.0, firmware for GD32F30x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "usbd_transc.h" +#include "printer_core.h" + +#define USBD_VID 0x28E9U +#define USBD_PID 0x028DU + +/* printer port status: paper not empty/selected/no error */ +static uint8_t g_port_status = 0x18U; +uint8_t g_printer_data_buf[PRINTER_OUT_PACKET]; + +uint8_t Printer_DEVICE_ID[DEVICE_ID_LEN] = +{ + 0x00, 0x67, + 'M', 'A', 'N', 'U', 'F', 'A', 'C', 'T', 'U', 'R', 'E', 'R', ':', + 'G', 'I', 'G', 'A', ' ', 'D', 'E', 'V', 'I', 'C', 'E', '-', ';', + 'C', 'O', 'M', 'M', 'A', 'N', 'D', ' ', 'S', 'E', 'T', ':', + 'P', 'C', 'L', ',', 'M', 'P', 'L', ';', + 'M', 'O', 'D', 'E', 'L', ':', + 'L', 'a', 's', 'e', 'r', 'B', 'e', 'a', 'm', '?', ';', + 'C', 'O', 'M', 'M', 'E', 'N', 'T', ':', + 'G', 'o', 'o', 'd', ' ', '!', ';', + 'A', 'C', 'T', 'I', 'V', 'E', ' ', 'C', 'O', 'M', 'M', 'A', 'N', 'D', ' ', 'S', 'E', 'T', ':', + 'P', 'C', 'L', ';' +}; + +/* USB standard device descriptor */ +usb_desc_dev printer_dev_desc = +{ + .header = + { + .bLength = USB_DEV_DESC_LEN, + .bDescriptorType = USB_DESCTYPE_DEV, + }, + .bcdUSB = 0x0200U, + .bDeviceClass = 0x00U, + .bDeviceSubClass = 0x00U, + .bDeviceProtocol = 0x00U, + .bMaxPacketSize0 = USBD_EP0_MAX_SIZE, + .idVendor = USBD_VID, + .idProduct = USBD_PID, + .bcdDevice = 0x0100U, + .iManufacturer = STR_IDX_MFC, + .iProduct = STR_IDX_PRODUCT, + .iSerialNumber = STR_IDX_SERIAL, + .bNumberConfigurations = USBD_CFG_MAX_NUM, +}; + +/* USB device configuration descriptor */ +usb_printer_desc_config_set printer_config_desc = +{ + .config = + { + .header = + { + .bLength = sizeof(usb_desc_config), + .bDescriptorType = USB_DESCTYPE_CONFIG + }, + .wTotalLength = USB_PRINTER_CONFIG_DESC_LEN, + .bNumInterfaces = 0x01U, + .bConfigurationValue = 0x01U, + .iConfiguration = 0x00U, + .bmAttributes = 0xA0U, + .bMaxPower = 0x32U + }, + + .printer_itf = + { + .header = + { + .bLength = sizeof(usb_desc_itf), + .bDescriptorType = USB_DESCTYPE_ITF + }, + .bInterfaceNumber = 0x00U, + .bAlternateSetting = 0x00U, + .bNumEndpoints = 0x02U, + .bInterfaceClass = USB_CLASS_PRINTER, + .bInterfaceSubClass = USB_SUBCLASS_PRINTER, + .bInterfaceProtocol = PROTOCOL_BI_DIRECTIONAL_ITF, + .iInterface = 0x00U + }, + + .printer_epin = + { + .header = + { + .bLength = sizeof(usb_desc_ep), + .bDescriptorType = USB_DESCTYPE_EP + }, + .bEndpointAddress = PRINTER_IN_EP, + .bmAttributes = USB_EP_ATTR_BULK, + .wMaxPacketSize = PRINTER_IN_PACKET, + .bInterval = 0x00U + }, + + .printer_epout = + { + .header = + { + .bLength = sizeof(usb_desc_ep), + .bDescriptorType = USB_DESCTYPE_EP + }, + .bEndpointAddress = PRINTER_OUT_EP, + .bmAttributes = USB_EP_ATTR_BULK, + .wMaxPacketSize = PRINTER_OUT_PACKET, + .bInterval = 0x00U + }, +}; + +/* USB language ID Descriptor */ +static usb_desc_LANGID usbd_language_id_desc = +{ + .header = + { + .bLength = sizeof(usb_desc_LANGID), + .bDescriptorType = USB_DESCTYPE_STR, + }, + .wLANGID = ENG_LANGID +}; + +/* USB manufacture string */ +static usb_desc_str manufacturer_string = +{ + .header = + { + .bLength = USB_STRING_LEN(10U), + .bDescriptorType = USB_DESCTYPE_STR, + }, + .unicode_string = {'G', 'i', 'g', 'a', 'D', 'e', 'v', 'i', 'c', 'e'} +}; + +/* USB product string */ +static usb_desc_str product_string = +{ + .header = + { + .bLength = USB_STRING_LEN(16U), + .bDescriptorType = USB_DESCTYPE_STR, + }, + .unicode_string = {'G', 'D', '3', '2', '-', 'U', 'S', 'B', '_', 'P', 'r', 'i', 'n', 't', 'e', 'r'} +}; + +/* USBD serial string */ +static usb_desc_str serial_string = +{ + .header = + { + .bLength = USB_STRING_LEN(12U), + .bDescriptorType = USB_DESCTYPE_STR, + } +}; + +/* USB string descriptor */ +static uint8_t* usbd_msc_strings[] = +{ + [STR_IDX_LANGID] = (uint8_t *)&usbd_language_id_desc, + [STR_IDX_MFC] = (uint8_t *)&manufacturer_string, + [STR_IDX_PRODUCT] = (uint8_t *)&product_string, + [STR_IDX_SERIAL] = (uint8_t *)&serial_string +}; + +usb_desc printer_desc = { + .dev_desc = (uint8_t *)&printer_dev_desc, + .config_desc = (uint8_t *)&printer_config_desc, + .strings = usbd_msc_strings +}; + +/* local function prototypes ('static') */ +static uint8_t printer_init (usb_dev *udev, uint8_t config_index); +static uint8_t printer_deinit (usb_dev *udev, uint8_t config_index); +static uint8_t printer_req_handler (usb_dev *udev, usb_req *req); +static void printer_data_in (usb_dev *udev, uint8_t ep_num); +static void printer_data_out (usb_dev *udev, uint8_t ep_num); + +usb_class printer_class = { + .init = printer_init, + .deinit = printer_deinit, + .req_process = printer_req_handler, + .data_in = printer_data_in, + .data_out = printer_data_out +}; +/*! + \brief initialize the printer device + \param[in] udev: pointer to USB device instance + \param[in] config_index: configuration index + \param[out] none + \retval USB device operation status +*/ +static uint8_t printer_init (usb_dev *udev, uint8_t config_index) +{ + /* initialize the data Tx/Rx endpoint */ + usbd_ep_init(udev, EP_BUF_SNG, BULK_TX_ADDR, &(printer_config_desc.printer_epin)); + usbd_ep_init(udev, EP_BUF_SNG, BULK_RX_ADDR, &(printer_config_desc.printer_epout)); + + udev->ep_transc[EP_ID(PRINTER_IN_EP)][TRANSC_IN] = printer_class.data_in; + udev->ep_transc[PRINTER_OUT_EP][TRANSC_OUT] = printer_class.data_out; + + /* prepare to receive data */ + usbd_ep_recev(udev, PRINTER_OUT_EP, g_printer_data_buf, PRINTER_OUT_PACKET); + + return USBD_OK; +} + +/*! + \brief de-initialize the printer device + \param[in] udev: pointer to USB device instance + \param[in] config_index: configuration index + \param[out] none + \retval USB device operation status +*/ +static uint8_t printer_deinit (usb_dev *udev, uint8_t config_index) +{ + /* deinitialize the data Tx/Rx endpoint */ + usbd_ep_deinit(udev, PRINTER_IN_EP); + usbd_ep_deinit(udev, PRINTER_OUT_EP); + + return USBD_OK; +} + +/*! + \brief handle the printer class-specific requests + \param[in] udev: pointer to USB device instance + \param[in] req: device class-specific request + \param[out] none + \retval USB device operation status +*/ +static uint8_t printer_req_handler (usb_dev *udev, usb_req *req) +{ + uint8_t status = REQ_NOTSUPP; + + switch (req->bRequest) { + case GET_DEVICE_ID: + usb_transc_config(&udev->transc_in[0], Printer_DEVICE_ID, DEVICE_ID_LEN, 0U); + + status = REQ_SUPP; + break; + + case GET_PORT_STATUS: + usb_transc_config(&udev->transc_in[0], (uint8_t *)&g_port_status, 1U, 0U); + + status = REQ_SUPP; + break; + + case SOFT_RESET: + usbd_ep_recev(udev, PRINTER_OUT_EP, g_printer_data_buf, PRINTER_OUT_PACKET); + + status = REQ_SUPP; + break; + + default: + break; + } + + return status; +} + +/*! + \brief handle printer data + \param[in] udev: pointer to USB device instance + \param[in] ep_num: endpoint number + \param[out] none + \retval none +*/ +static void printer_data_in (usb_dev *udev, uint8_t ep_num) +{ +} + +/*! + \brief handle printer data + \param[in] udev: pointer to USB device instance + \param[in] ep_num: endpoint number + \param[out] none + \retval none +*/ +static void printer_data_out (usb_dev *udev, uint8_t ep_num) +{ +} diff --git a/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbd_library/device/Include/usb_ch9_std.h b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbd_library/device/Include/usb_ch9_std.h new file mode 100644 index 0000000000..7ba1d3d08e --- /dev/null +++ b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbd_library/device/Include/usb_ch9_std.h @@ -0,0 +1,212 @@ +/*! + \file usb_ch9_std.h + \brief USB 2.0 standard defines + + \version 2020-08-01, V3.0.0, firmware for GD32F30x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef __USB_CH9_STD_H +#define __USB_CH9_STD_H + +#include "usbd_conf.h" + +#define USB_DEV_QUALIFIER_DESC_LEN 0x0AU /*!< USB device qualifier descriptor length */ +#define USB_DEV_DESC_LEN 0x12U /*!< USB device descriptor length */ +#define USB_CFG_DESC_LEN 0x09U /*!< USB configuration descriptor length */ +#define USB_ITF_DESC_LEN 0x09U /*!< USB interface descriptor length */ +#define USB_EP_DESC_LEN 0x07U /*!< USB endpoint descriptor length */ +#define USB_BOS_DESC_LEN 0x0CU /*!< USB BOS descriptor length */ +#define USB_OTG_DESC_LEN 0x03U /*!< USB device OTG descriptor length */ +#define USB_SETUP_PACKET_LEN 0x08U /*!< USB SETUP packet length */ +#define USB_DEVICE_CAPABITY 0x10U /*!< USB device capabity */ + + +/* bit 7 of bmRequestType: data phase transfer direction */ +#define USB_TRX_MASK 0x80U /*!< USB transfer direction mask */ +#define USB_TRX_OUT 0x00U /*!< USB transfer OUT direction */ +#define USB_TRX_IN 0x80U /*!< USB transfer IN direction */ + +/* bit 6..5 of bmRequestType: request type */ +#define USB_REQTYPE_STRD 0x00U /*!< USB standard request */ +#define USB_REQTYPE_CLASS 0x20U /*!< USB class request */ +#define USB_REQTYPE_VENDOR 0x40U /*!< USB vendor request */ +#define USB_REQTYPE_MASK 0x60U /*!< USB request mask */ + +#define USBD_BUS_POWERED 0x00U /*!< USB bus power supply */ +#define USBD_SELF_POWERED 0x01U /*!< USB self power supply */ + +#define USB_STATUS_REMOTE_WAKEUP 2U /*!< USB is in remote wakeup status */ +#define USB_STATUS_SELF_POWERED 1U /*!< USB is in self powered status */ + +/* bit 4..0 of bmRequestType: recipient type */ +enum _usb_recp_type { + USB_RECPTYPE_DEV = 0x0U, /*!< USB device request type */ + USB_RECPTYPE_ITF = 0x1U, /*!< USB interface request type */ + USB_RECPTYPE_EP = 0x2U, /*!< USB endpoint request type */ + USB_RECPTYPE_MASK = 0x3U /*!< USB request type mask */ +}; + +/* bRequest value */ +enum _usb_request { + USB_GET_STATUS = 0x0U, /*!< USB get status request */ + USB_CLEAR_FEATURE = 0x1U, /*!< USB clear feature request */ + USB_RESERVED2 = 0x2U, /*!< USB reserved2 */ + USB_SET_FEATURE = 0x3U, /*!< USB set feature request */ + USB_RESERVED4 = 0x4U, /*!< USB reserved4 */ + USB_SET_ADDRESS = 0x5U, /*!< USB set address request */ + USB_GET_DESCRIPTOR = 0x6U, /*!< USB get descriptor request */ + USB_SET_DESCRIPTOR = 0x7U, /*!< USB set descriptor request */ + USB_GET_CONFIGURATION = 0x8U, /*!< USB get configuration request */ + USB_SET_CONFIGURATION = 0x9U, /*!< USB set configuration request */ + USB_GET_INTERFACE = 0xAU, /*!< USB get interface request */ + USB_SET_INTERFACE = 0xBU, /*!< USB set interface request */ + USB_SYNCH_FRAME = 0xCU /*!< USB synchronized frame request */ +}; + +/* descriptor types of USB specifications */ +enum _usb_desctype { + USB_DESCTYPE_DEV = 0x1U, /*!< USB device descriptor type */ + USB_DESCTYPE_CONFIG = 0x2U, /*!< USB configuration descriptor type */ + USB_DESCTYPE_STR = 0x3U, /*!< USB string descriptor type */ + USB_DESCTYPE_ITF = 0x4U, /*!< USB interface descriptor type */ + USB_DESCTYPE_EP = 0x5U, /*!< USB endpoint descriptor type */ + USB_DESCTYPE_DEV_QUALIFIER = 0x6U, /*!< USB device qualifier descriptor type */ + USB_DESCTYPE_OTHER_SPD_CONFIG = 0x7U, /*!< USB other speed configuration descriptor type */ + USB_DESCTYPE_ITF_POWER = 0x8U, /*!< USB interface power descriptor type */ + USB_DESCTYPE_BOS = 0xFU /*!< USB BOS descriptor type */ +}; + +/* USB endpoint descriptor bmAttributes bit definitions */ +/* bits 1..0 : transfer type */ +enum _usbx_type { + USB_EP_ATTR_CTL = 0x0U, /*!< USB endpoint control attributes*/ + USB_EP_ATTR_ISO = 0x1U, /*!< USB endpoint isochronous attributes*/ + USB_EP_ATTR_BULK = 0x2U, /*!< USB endpoint bulk attributes*/ + USB_EP_ATTR_INT = 0x3U /*!< USB endpoint interrupt attributes*/ +}; + +/* bits 3..2 : Sync type (only if ISOCHRONOUS) */ +#define USB_EP_ATTR_NOSYNC 0x00U /*!< USB endpoint no SYNC attributes*/ +#define USB_EP_ATTR_ASYNC 0x04U /*!< USB endpoint ASYNC attributes*/ +#define USB_EP_ATTR_ADAPTIVE 0x08U /*!< USB endpoint adaptive attributes*/ +#define USB_EP_ATTR_SYNC 0x0CU /*!< USB endpoint SYNC attributes*/ +#define USB_EP_ATTR_SYNCTYPE 0x0CU /*!< USB endpoint SYNC type attributes*/ + +/* bits 5..4 : usage type (only if ISOCHRONOUS) */ +#define USB_EP_ATTR_DATA 0x00U /*!< USB endpoint data attributes*/ +#define USB_EP_ATTR_FEEDBACK 0x10U /*!< USB endpoint feedback attributes*/ +#define USB_EP_ATTR_IMPLICIT_FEEDBACK_DATA 0x20U /*!< USB endpoint implicit feedback attributes*/ +#define USB_EP_ATTR_USAGETYPE 0x30U /*!< USB endpoint usage type attributes*/ + +#pragma pack(1) + +/* USB standard device request structure */ +typedef struct _usb_req { + uint8_t bmRequestType; /*!< type of request */ + uint8_t bRequest; /*!< request of setup packet */ + uint16_t wValue; /*!< value of setup packet */ + uint16_t wIndex; /*!< index of setup packet */ + uint16_t wLength; /*!< length of setup packet */ +} usb_req; + +/* USB setup packet definition */ +typedef union _usb_setup { + uint8_t data[8]; /*!< USB setup data */ + + usb_req req; /*!< USB setup request */ +} usb_setup; + +/* USB descriptor definition */ +typedef struct _usb_desc_header { + uint8_t bLength; /*!< size of the descriptor */ + uint8_t bDescriptorType; /*!< type of the descriptor */ +} usb_desc_header; + +typedef struct _usb_desc_dev { + usb_desc_header header; /*!< descriptor header, including type and size */ + uint16_t bcdUSB; /*!< BCD of the supported USB specification */ + uint8_t bDeviceClass; /*!< USB device class */ + uint8_t bDeviceSubClass; /*!< USB device subclass */ + uint8_t bDeviceProtocol; /*!< USB device protocol */ + uint8_t bMaxPacketSize0; /*!< size of the control (address 0) endpoint's bank in bytes */ + uint16_t idVendor; /*!< vendor ID for the USB product */ + uint16_t idProduct; /*!< unique product ID for the USB product */ + uint16_t bcdDevice; /*!< product release (version) number */ + uint8_t iManufacturer; /*!< string index for the manufacturer's name */ + uint8_t iProduct; /*!< string index for the product name/details */ + uint8_t iSerialNumber; /*!< string index for the product's globally unique hexadecimal serial number */ + uint8_t bNumberConfigurations; /*!< total number of configurations supported by the device */ +} usb_desc_dev; + +typedef struct _usb_desc_config { + usb_desc_header header; /*!< descriptor header, including type and size */ + uint16_t wTotalLength; /*!< size of the configuration descriptor header, and all sub descriptors inside the configuration */ + uint8_t bNumInterfaces; /*!< total number of interfaces in the configuration */ + uint8_t bConfigurationValue; /*!< configuration index of the current configuration */ + uint8_t iConfiguration; /*!< index of a string descriptor describing the configuration */ + uint8_t bmAttributes; /*!< configuration attributes */ + uint8_t bMaxPower; /*!< maximum power consumption of the device while in the current configuration */ +} usb_desc_config; + +typedef struct _usb_desc_itf { + usb_desc_header header; /*!< descriptor header, including type and size */ + uint8_t bInterfaceNumber; /*!< index of the interface in the current configuration */ + uint8_t bAlternateSetting; /*!< alternate setting for the interface number */ + uint8_t bNumEndpoints; /*!< total number of endpoints in the interface */ + uint8_t bInterfaceClass; /*!< interface class ID */ + uint8_t bInterfaceSubClass; /*!< interface subclass ID */ + uint8_t bInterfaceProtocol; /*!< interface protocol ID */ + uint8_t iInterface; /*!< index of the string descriptor describing the interface */ +} usb_desc_itf; + +typedef struct _usb_desc_ep { + usb_desc_header header; /*!< descriptor header, including type and size */ + uint8_t bEndpointAddress; /*!< logical address of the endpoint */ + uint8_t bmAttributes; /*!< endpoint attribute */ + uint16_t wMaxPacketSize; /*!< size of the endpoint bank, in bytes */ + uint8_t bInterval; /*!< polling interval in milliseconds for the endpoint if it is an INTERRUPT or ISOCHRONOUS type */ +} usb_desc_ep; + +typedef struct _usb_desc_LANGID { + usb_desc_header header; /*!< descriptor header, including type and size. */ + uint16_t wLANGID; /*!< LANGID code */ +} usb_desc_LANGID; + +typedef struct _usb_desc_str { + usb_desc_header header; /*!< descriptor header, including type and size. */ + uint16_t unicode_string[64]; /*!< unicode string data */ +} usb_desc_str; + +#pragma pack() + +/* compute string descriptor length */ +#define USB_STRING_LEN(unicode_chars) (sizeof(usb_desc_header) + ((unicode_chars) << 1)) + +#endif /* __USB_CH9_STD_H */ diff --git a/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbd_library/device/Include/usbd_core.h b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbd_library/device/Include/usbd_core.h new file mode 100644 index 0000000000..138880172e --- /dev/null +++ b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbd_library/device/Include/usbd_core.h @@ -0,0 +1,332 @@ +/*! + \file usbd_core.h + \brief USB device driver core + + \version 2020-08-01, V3.0.0, firmware for GD32F30x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef __USBD_CORE_H +#define __USBD_CORE_H + +#include "usb_ch9_std.h" + +/* endpoints definitions */ +#define EP_IN(x) ((uint8_t)(0x80U | (x))) +#define EP_OUT(x) ((uint8_t)(x)) + +#define EP_DIR(x) ((uint8_t)((x) >> 7U)) +#define EP_ID(x) ((uint8_t)((x) & 0x7FU)) + +/* USB device endpoint0 max packet size */ +#define USBD_EP0_MAX_SIZE 64U + +#define USBD_TRANSC_COUNT 3U + +/* USB device operation status */ +enum usbd_status { + USBD_UNCONNECTED = 0U, /*!< USB device unconnected status */ + USBD_DEFAULT, /*!< USB device default status */ + USBD_ADDRESSED, /*!< USB device addressed status */ + USBD_CONFIGURED, /*!< USB device configured status */ + USBD_SUSPENDED, /*!< USB device suspended status */ + USBD_CONNECTED /*!< USB device connected status */ +}; + +/* USB device operation state */ +enum usbd_state { + USBD_OK = 0U, /*!< USB device OK state */ + USBD_BUSY, /*!< USB device busy state */ + USBD_FAIL /*!< USB device fail state */ +}; + +/* USB device transaction type */ +enum usbd_transc { + TRANSC_SETUP = 0U, /*!< SETUP transaction */ + TRANSC_OUT, /*!< OUT transaction */ + TRANSC_IN, /*!< IN transaction */ + TRANSC_UNKNOWN /*!< unknown transaction */ +}; + +/* USB device endpoint buffer type */ +enum usbd_ep_kind { + EP_BUF_SNG = 0U, /*!< single buffer endpoint type value */ + EP_BUF_DBL /*!< double buffer endpoint type value */ +}; + +/* USB device transaction struct */ +typedef struct { + uint8_t max_len; /*!< packet max length */ + uint8_t ep_stall; /*!< endpoint STALL */ + + uint8_t *xfer_buf; /*!< transfer buffer */ + uint16_t xfer_len; /*!< transfer length */ + uint16_t xfer_count; /*!< transfer count */ +} usb_transc; + +/* USB device basic struct */ +typedef struct { + uint8_t max_ep_count; /*!< endpoint max count */ + uint8_t twin_buf; /*!< double buffer */ + uint16_t ram_size; /*!< ram size */ +} usb_basic; + +/* USB descriptor */ +typedef struct { + uint8_t *dev_desc; /*!< device descriptor */ + uint8_t *config_desc; /*!< configure descriptor */ + uint8_t *bos_desc; /*!< bos descriptor */ + uint8_t **strings; /*!< strings descriptor */ +} usb_desc; + +/* USB power management */ +typedef struct { + uint8_t power_mode; /*!< power mode */ + uint8_t power_low; /*!< power low */ + uint8_t esof_count; /*!< ESOF count */ + uint8_t suspend_enabled; /*!< suspend enabled flag */ + uint8_t remote_wakeup; /*!< remote wakeup */ + uint8_t remote_wakeup_on; /*!< remote wakeup enable */ + uint8_t lpm_enable; /*!< LPM enable */ +} usb_pm; + +/* USB LPM management */ +typedef struct { + uint32_t besl; /*!< besl */ + uint32_t L1_resume; /*!< L1 resume */ + uint32_t L1_remote_wakeup; /*!< L1 remote wakeup */ +} usb_lpm; + +/* USB control information */ +typedef struct { + usb_req req; /*!< USB request */ + uint8_t ctl_zlp; /*!< control zero length packet */ +} usb_control; + +typedef struct _usb_dev usb_dev; +typedef struct _usb_handler usb_handler; +typedef void (*usb_ep_transc) (usb_dev *usbd_dev, uint8_t ep_num); + +/* USB class struct */ +typedef struct { + uint8_t req_cmd; + uint8_t req_altset; + + uint8_t (*init) (usb_dev *udev, uint8_t config_index); + uint8_t (*deinit) (usb_dev *udev, uint8_t config_index); + + uint8_t (*req_process) (usb_dev *udev, usb_req *req); + + uint8_t (*ctlx_in) (usb_dev *udev); + uint8_t (*ctlx_out) (usb_dev *udev); + + void (*data_in) (usb_dev *udev, uint8_t ep_num); + void (*data_out) (usb_dev *udev, uint8_t ep_num); +} usb_class; + +/* USB core driver struct */ +struct _usb_dev { + /* basic parameters */ + uint8_t config; + uint8_t dev_addr; + + __IO uint8_t cur_status; + __IO uint8_t backup_status; + + usb_pm pm; +#ifdef LPM_ENABLED + usb_lpm lpm; +#endif /* LPM_ENABLED */ + usb_control control; + + usb_transc transc_out[EP_COUNT]; + usb_transc transc_in[EP_COUNT]; + + usb_ep_transc ep_transc[EP_COUNT][USBD_TRANSC_COUNT]; + + /* device class */ + usb_desc *desc; + usb_class *class_core; + usb_handler *drv_handler; + + void *class_data[USBD_ITF_MAX_NUM]; + void *user_data; + void *data; +}; + +typedef struct +{ + uint8_t (*SOF) (usb_dev *udev); /*!< SOF ISR callback */ +} usbd_int_cb_struct; + +/* USB handler struct */ +struct _usb_handler { + void (*init) (void); + void (*deinit) (void); + + void (*dp_pullup) (FlagStatus status); + void (*set_addr) (usb_dev *udev); + void (*suspend) (void); + void (*suspend_leave) (void); + void (*resume) (usb_dev *udev); + + void (*ep_reset) (usb_dev *udev); + void (*ep_setup) (usb_dev *udev, uint8_t buf_kind, uint32_t buf_addr, const usb_desc_ep *ep_desc); + void (*ep_disable) (usb_dev *udev, uint8_t ep_addr); + void (*ep_rx_enable) (usb_dev *udev, uint8_t ep_num); + void (*ep_write) (uint8_t *fifo, uint8_t ep_num, uint16_t bytes); + uint16_t (*ep_read) (uint8_t *fifo, uint8_t ep_num, uint8_t buf_kind); + void (*ep_stall_set) (usb_dev *udev, uint8_t ep_addr); + void (*ep_stall_clear) (usb_dev *udev, uint8_t ep_addr); + uint8_t (*ep_status_get) (usb_dev *udev, uint8_t ep_addr); +}; + +extern usbd_int_cb_struct *usbd_int_fops; + +/* static inline function definitions */ +/*! + \brief device connect + \param[in] udev: pointer to USB core instance + \param[out] none + \retval none +*/ +__STATIC_INLINE void usbd_connect (usb_dev *udev) +{ + udev->drv_handler->dp_pullup(SET); + + udev->cur_status = (uint8_t)USBD_CONNECTED; +} + +/*! + \brief device disconnect + \param[in] udev: pointer to USB core instance + \param[out] none + \retval none +*/ +__STATIC_INLINE void usbd_disconnect (usb_dev *udev) +{ + udev->drv_handler->dp_pullup(RESET); + + udev->cur_status = (uint8_t)USBD_UNCONNECTED; +} + +/*! + \brief device core register configure when stop device + \param[in] udev: pointer to USB core instance + \param[out] none + \retval none +*/ +__STATIC_INLINE void usbd_core_deinit (usb_dev *udev) +{ + udev->drv_handler->deinit(); +} + +/*! + \brief initialize endpoint + \param[in] udev: pointer to USB core instance + \param[in] buf_kind: endpoint buffer kind + \param[in] buf_addr: buffer addresss + \param[in] ep_desc: pointer to endpoint descriptor + \param[out] none + \retval none +*/ +__STATIC_INLINE void usbd_ep_init (usb_dev *udev, uint8_t buf_kind, uint32_t buf_addr, const usb_desc_ep *ep_desc) +{ + udev->drv_handler->ep_setup(udev, buf_kind, buf_addr, ep_desc); +} + +/*! + \brief configure the endpoint when it is disabled + \param[in] udev: pointer to USB core instance + \param[in] ep_addr: endpoint address + in this parameter: + bit0..bit6: endpoint number (0..7) + bit7: endpoint direction which can be IN(1) or OUT(0) + \param[out] none + \retval none +*/ +__STATIC_INLINE void usbd_ep_deinit (usb_dev *udev, uint8_t ep_addr) +{ + udev->drv_handler->ep_disable(udev, ep_addr); +} + +/*! + \brief set an endpoint to STALL status + \param[in] udev: pointer to USB core instance + \param[in] ep_addr: endpoint address + in this parameter: + bit0..bit6: endpoint number (0..7) + bit7: endpoint direction which can be IN(1) or OUT(0) + \param[out] none + \retval none +*/ +__STATIC_INLINE void usbd_ep_stall (usb_dev *udev, uint8_t ep_addr) +{ + udev->drv_handler->ep_stall_set(udev, ep_addr); +} + +/*! + \brief clear endpoint stalled status + \param[in] udev: pointer to USB core instance + \param[in] ep_addr: endpoint address + in this parameter: + bit0..bit6: endpoint number (0..7) + bit7: endpoint direction which can be IN(1) or OUT(0) + \param[out] none + \retval none +*/ +__STATIC_INLINE void usbd_ep_clear_stall (usb_dev *udev, uint8_t ep_addr) +{ + udev->drv_handler->ep_stall_clear(udev, ep_addr); +} + +/*! + \brief get endpoint status + \param[in] udev: pointer to USB core instance + \param[in] ep_addr: endpoint address + in this parameter: + bit0..bit6: endpoint number (0..7) + bit7: endpoint direction which can be IN(1) or OUT(0) + \param[out] none + \retval none +*/ +__STATIC_INLINE uint8_t usbd_ep_status_get (usb_dev *udev, uint8_t ep_addr) +{ + return udev->drv_handler->ep_status_get(udev, ep_addr); +} + +/* function declarations */ +/* initialize USBD */ +void usbd_init(usb_dev *udev, usb_desc *desc, usb_class *usbc); +/* endpoint prepare to transmit data */ +void usbd_ep_send (usb_dev *udev, uint8_t ep_addr, uint8_t *pbuf, uint16_t buf_len); +/* endpoint prepare to receive data */ +void usbd_ep_recev (usb_dev *udev, uint8_t ep_addr, uint8_t *pbuf, uint16_t buf_len); + +#endif /* __USBD_CORE_H */ diff --git a/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbd_library/device/Include/usbd_enum.h b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbd_library/device/Include/usbd_enum.h new file mode 100644 index 0000000000..da6238bb99 --- /dev/null +++ b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbd_library/device/Include/usbd_enum.h @@ -0,0 +1,111 @@ +/*! + \file usbd_enum.h + \brief USB enumeration definitions + + \version 2020-08-01, V3.0.0, firmware for GD32F30x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef __USBD_ENUM_H +#define __USBD_ENUM_H + +#include "usbd_core.h" +#include "usb_ch9_std.h" + +#ifndef NULL + #define NULL 0U +#endif + +/* request state enumeration */ +typedef enum _usb_reqsta +{ + REQ_SUPP = 0x0U, /* supported request */ + REQ_NOTSUPP = 0x1U /* unsupported request */ +} usb_reqsta; + +/* string descriptor index enumeration */ +enum _str_index +{ + STR_IDX_LANGID = 0x0U, /* language ID string index */ + STR_IDX_MFC = 0x1U, /* manufacturer string index */ + STR_IDX_PRODUCT = 0x2U, /* product string index */ + STR_IDX_SERIAL = 0x3U, /* serial string index */ + STR_IDX_CONFIG = 0x4U, /* configuration string index */ + STR_IDX_ITF = 0x5U, /* interface string index */ + STR_IDX_MAX = 0x6U /* string index max value */ +}; + +/* PWR status enumeration */ +typedef enum +{ + USB_PWRSTA_SELF_POWERED = 0x1U, /* USB is in self powered status */ + USB_PWRSTA_REMOTE_WAKEUP = 0x2U, /* USB is in remote wakeup status */ +} usb_pwrsta; + +/* usb endpoint feature enumeration */ +typedef enum +{ + USB_FEATURE_EP_HALT = 0x0U, /* USB has endpoint halt feature */ + USB_FEATURE_REMOTE_WAKEUP = 0x1U, /* USB has endpoint remote wakeup feature */ + USB_FEATURE_TEST_MODE = 0x2U /* USB has endpoint test mode feature */ +} usb_feature; + +#define ENG_LANGID 0x0409U /* english language ID */ +#define CHN_LANGID 0x0804U /* chinese language ID */ + +/* device unique ID */ +#define DEVICE_ID1 (0x1FFFF7E8U) /* device ID1 */ +#define DEVICE_ID2 (0x1FFFF7ECU) /* device ID2 */ +#define DEVICE_ID3 (0x1FFFF7F0U) /* device ID3 */ + +#define DEVICE_ID (0x40022100U) /* device ID information */ + +//#define USB_SERIAL_STRING_SIZE 0x1AU + +/* USB device exported macros */ +#define BYTE_SWAP(addr) (((uint16_t)(*((uint8_t *)(addr)))) + \ + (uint16_t)(((uint16_t)(*(((uint8_t *)(addr)) + 1U))) << 8U)) +#define BYTE_LOW(x) ((uint8_t)((x) & 0x00FFU)) +#define BYTE_HIGH(x) ((uint8_t)(((x) & 0xFF00U) >> 8U)) + +#define USB_MIN(a, b) (((a) < (b)) ? (a) : (b)) + +#define CTL_EP(ep) (((ep) == 0x00U) || ((ep) == 0x80U)) + +/* function declarations */ +/* handle USB standard device request */ +usb_reqsta usbd_standard_request (usb_dev *udev, usb_req *req); +/* handle device class request */ +usb_reqsta usbd_class_request (usb_dev *udev, usb_req *req); +/* handle USB vendor request */ +usb_reqsta usbd_vendor_request (usb_dev *udev, usb_req *req); +/* get serial string */ +void serial_string_get (uint16_t *unicode_str); + +#endif /* __USBD_ENUM_H */ diff --git a/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbd_library/device/Include/usbd_pwr.h b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbd_library/device/Include/usbd_pwr.h new file mode 100644 index 0000000000..84a31fc788 --- /dev/null +++ b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbd_library/device/Include/usbd_pwr.h @@ -0,0 +1,67 @@ +/*! + \file usbd_pwr.h + \brief USB device power management functions prototype + + \version 2020-08-01, V3.0.0, firmware for GD32F30x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef __USBD_PWR_H +#define __USBD_PWR_H + +#include "usbd_core.h" + +/* static inline function definitions */ +/*! + \brief first operation of USB wakeup is to wakeup MCU + \param[in] udev: pointer to USB core instance + \param[out] none + \retval none +*/ +__STATIC_INLINE void resume_mcu (usb_dev *udev) +{ + udev->drv_handler->suspend_leave(); +} + +/*! + \brief set USB device to suspend mode + \param[in] udev: pointer to USB core instance + \param[out] none + \retval none +*/ +__STATIC_INLINE void usbd_to_suspend (usb_dev *udev) +{ + udev->drv_handler->suspend(); +} + +/* function declarations */ +/* start to remote wakeup */ +void usbd_remote_wakeup_active (usb_dev *udev); + +#endif /* __USBD_PWR_H */ diff --git a/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbd_library/device/Include/usbd_transc.h b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbd_library/device/Include/usbd_transc.h new file mode 100644 index 0000000000..e60da374e5 --- /dev/null +++ b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbd_library/device/Include/usbd_transc.h @@ -0,0 +1,63 @@ +/*! + \file usbd_transc.h + \brief USBD transaction + + \version 2020-08-01, V3.0.0, firmware for GD32F30x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef __USB_TRANSC_H +#define __USB_TRANSC_H + +#include "usbd_core.h" + +/*! + \brief USB transaction configure + \param[in] udev: pointer to USB device instance + \param[in] buf: transfer data buffer + \param[in] len: transfer data length + \param[out] none + \retval none +*/ +__STATIC_INLINE void usb_transc_config (usb_transc *transc, uint8_t *buf, uint16_t len, uint16_t count) +{ + transc->xfer_buf = buf; + transc->xfer_len = len; + transc->xfer_count = count; +} + +/* function declarations */ +/* process USB SETUP transaction */ +void _usb_setup_transc (usb_dev *udev, uint8_t ep_num); +/* process USB OUT transaction */ +void _usb_out0_transc (usb_dev *udev, uint8_t ep_num); +/* process USB IN transaction */ +void _usb_in0_transc (usb_dev *udev, uint8_t ep_num); + +#endif /* __USB_TRANSC_H */ diff --git a/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbd_library/device/Source/usbd_core.c b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbd_library/device/Source/usbd_core.c new file mode 100644 index 0000000000..0f76ccb9ab --- /dev/null +++ b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbd_library/device/Source/usbd_core.c @@ -0,0 +1,129 @@ +/*! + \file usbd_core.c + \brief USB device driver + + \version 2020-08-01, V3.0.0, firmware for GD32F30x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "usbd_core.h" +#include "usbd_enum.h" +#include "usbd_transc.h" +#include "usbd_lld_core.h" + +usbd_int_cb_struct *usbd_int_fops = NULL; + +/*! + \brief configure USB device initialization + \param[in] udev: pointer to USB core instance + \param[in] core: endpoint address + \param[in] usbc: USB class + \param[in] usbha: USB handler + \param[out] none + \retval none +*/ +void usbd_init (usb_dev *udev, usb_desc *desc, usb_class *usbc) +{ + /* configure USBD core basic attributes */ + usbd_core.basic.max_ep_count = 8U; + usbd_core.basic.twin_buf = 1U; + usbd_core.basic.ram_size = 512U; + + usbd_core.dev = udev; + + udev->desc = desc; + udev->class_core = usbc; + udev->drv_handler = &usbd_drv_handler; + + udev->ep_transc[0][TRANSC_SETUP] = _usb_setup_transc; + udev->ep_transc[0][TRANSC_OUT] = _usb_out0_transc; + udev->ep_transc[0][TRANSC_IN] = _usb_in0_transc; + + /* configure power management */ + udev->pm.power_mode = (udev->desc->config_desc[7] & 0x40U) >> 5; + + /* enable USB suspend */ + udev->pm.suspend_enabled = 1U; + + /* USB low level initialization */ + udev->drv_handler->init(); + + /* create serial string */ + serial_string_get((uint16_t *)udev->desc->strings[STR_IDX_SERIAL]); +} + +/*! + \brief endpoint prepare to receive data + \param[in] udev: pointer to USB core instance + \param[in] ep_addr: endpoint address + in this parameter: + bit0..bit6: endpoint number (0..7) + bit7: endpoint direction which can be IN(1) or OUT(0) + \param[in] pbuf: user buffer address pointer + \param[in] buf_len: buffer length + \param[out] none + \retval none +*/ +void usbd_ep_recev (usb_dev *udev, uint8_t ep_addr, uint8_t *pbuf, uint16_t buf_len) +{ + /* configure the transaction level parameters */ + usb_transc *transc = &udev->transc_out[EP_ID(ep_addr)]; + + usb_transc_config(transc, pbuf, buf_len, 0U); + + /* enable endpoint to receive */ + udev->drv_handler->ep_rx_enable(udev, ep_addr); +} + +/*! + \brief endpoint prepare to transmit data + \param[in] udev: pointer to USB core instance + \param[in] ep_addr: endpoint address + in this parameter: + bit0..bit6: endpoint number (0..7) + bit7: endpoint direction which can be IN(1) or OUT(0) + \param[in] pbuf: transmit buffer address pointer + \param[in] buf_len: buffer length + \param[out] none + \retval none +*/ +void usbd_ep_send (usb_dev *udev, uint8_t ep_addr, uint8_t *pbuf, uint16_t buf_len) +{ + uint8_t ep_num = EP_ID(ep_addr); + + usb_transc *transc = &udev->transc_in[ep_num]; + + uint16_t len = USB_MIN(buf_len, transc->max_len); + + /* configure the transaction level parameters */ + + udev->drv_handler->ep_write(pbuf, ep_num, len); + + usb_transc_config(transc, pbuf + len, buf_len - len, len); +} diff --git a/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbd_library/device/Source/usbd_enum.c b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbd_library/device/Source/usbd_enum.c new file mode 100644 index 0000000000..75bb3c2886 --- /dev/null +++ b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbd_library/device/Source/usbd_enum.c @@ -0,0 +1,743 @@ +/*! + \file usbd_enum.c + \brief USB enumeration function + + \version 2020-08-01, V3.0.0, firmware for GD32F30x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "usbd_enum.h" +#include "usbd_transc.h" + +/* USB enumeration handle functions */ +static usb_reqsta _usb_std_getstatus (usb_dev *udev, usb_req *req); +static usb_reqsta _usb_std_clearfeature (usb_dev *udev, usb_req *req); +static usb_reqsta _usb_std_setfeature (usb_dev *udev, usb_req *req); +static usb_reqsta _usb_std_setaddress (usb_dev *udev, usb_req *req); +static usb_reqsta _usb_std_getdescriptor (usb_dev *udev, usb_req *req); +static usb_reqsta _usb_std_setdescriptor (usb_dev *udev, usb_req *req); +static usb_reqsta _usb_std_getconfiguration (usb_dev *udev, usb_req *req); +static usb_reqsta _usb_std_setconfiguration (usb_dev *udev, usb_req *req); +static usb_reqsta _usb_std_reserved (usb_dev *udev, usb_req *req); +static usb_reqsta _usb_std_getinterface (usb_dev *udev, usb_req *req); +static usb_reqsta _usb_std_setinterface (usb_dev *udev, usb_req *req); +static usb_reqsta _usb_std_synchframe (usb_dev *udev, usb_req *req); +static uint8_t* _usb_dev_desc_get (usb_dev *udev, uint8_t index, uint16_t *len); +static uint8_t* _usb_config_desc_get (usb_dev *udev, uint8_t index, uint16_t *len); +static uint8_t* _usb_str_desc_get (usb_dev *udev, uint8_t index, uint16_t *len); +static uint8_t* _usb_bos_desc_get (usb_dev *udev, uint8_t index, uint16_t *len); +static void int_to_unicode (uint32_t value, uint8_t *pbuf, uint8_t len); + +/* standard device request handler */ +static usb_reqsta (*_std_dev_req[]) (usb_dev *udev, usb_req *req) = { + [USB_GET_STATUS] = _usb_std_getstatus, + [USB_CLEAR_FEATURE] = _usb_std_clearfeature, + [USB_RESERVED2] = _usb_std_reserved, + [USB_SET_FEATURE] = _usb_std_setfeature, + [USB_RESERVED4] = _usb_std_reserved, + [USB_SET_ADDRESS] = _usb_std_setaddress, + [USB_GET_DESCRIPTOR] = _usb_std_getdescriptor, + [USB_SET_DESCRIPTOR] = _usb_std_setdescriptor, + [USB_GET_CONFIGURATION] = _usb_std_getconfiguration, + [USB_SET_CONFIGURATION] = _usb_std_setconfiguration, + [USB_GET_INTERFACE] = _usb_std_getinterface, + [USB_SET_INTERFACE] = _usb_std_setinterface, + [USB_SYNCH_FRAME] = _usb_std_synchframe, +}; + +/* get standard descriptor handler */ +static uint8_t* (*std_desc_get[])(usb_dev *udev, uint8_t index, uint16_t *len) = { + [USB_DESCTYPE_DEV - 1U] = _usb_dev_desc_get, + [USB_DESCTYPE_CONFIG - 1U] = _usb_config_desc_get, + [USB_DESCTYPE_STR - 1U] = _usb_str_desc_get +}; + +/*! + \brief handle USB standard device request + \param[in] udev: pointer to USB device instance + \param[in] req: pointer to USB device request + \param[out] none + \retval USB device operation cur_status +*/ +usb_reqsta usbd_standard_request (usb_dev *udev, usb_req *req) +{ + /* call device request handle function */ + return (*_std_dev_req[req->bRequest]) (udev, req); +} + +/*! + \brief handle USB device class request + \param[in] udev: pointer to USB device instance + \param[in] req: pointer to USB device class request + \param[out] none + \retval USB device request status +*/ +usb_reqsta usbd_class_request (usb_dev *udev, usb_req *req) +{ + if ((uint8_t)USBD_CONFIGURED == udev->cur_status) { + if (BYTE_LOW(req->wIndex) < USBD_ITF_MAX_NUM) { + /* call device class handle function */ + return (usb_reqsta)udev->class_core->req_process(udev, req); + } + } + + return REQ_NOTSUPP; +} + +/*! + \brief handle USB vendor request + \param[in] udev: pointer to USB device instance + \param[in] req: pointer to USB vendor request + \param[out] none + \retval USB device request status +*/ +usb_reqsta usbd_vendor_request (usb_dev *udev, usb_req *req) +{ + (void)udev; + (void)req; + + /* added by user */ + + return REQ_NOTSUPP; +} + +/*! + \brief no operation, just for reserved + \param[in] udev: pointer to USB device instance + \param[in] req: pointer to USB device request + \param[out] none + \retval USB device request status +*/ +static usb_reqsta _usb_std_reserved (usb_dev *udev, usb_req *req) +{ + (void)udev; + (void)req; + + /* no operation */ + return REQ_NOTSUPP; +} + +/*! + \brief get the device descriptor + \param[in] udev: pointer to USB device instance + \param[in] index: no use + \param[out] len: data length pointer + \retval descriptor buffer pointer +*/ +static uint8_t* _usb_dev_desc_get (usb_dev *udev, uint8_t index, uint16_t *len) +{ + (void)index; + + *len = udev->desc->dev_desc[0]; + + return udev->desc->dev_desc; +} + +/*! + \brief get the configuration descriptor + \brief[in] udev: pointer to USB device instance + \brief[in] index: no use + \param[out] len: data length pointer + \retval descriptor buffer pointer +*/ +static uint8_t* _usb_config_desc_get (usb_dev *udev, uint8_t index, uint16_t *len) +{ + (void)index; + + *len = udev->desc->config_desc[2]; + + return udev->desc->config_desc; +} + +/*! + \brief get the BOS descriptor + \brief[in] udev: pointer to USB device instance + \brief[in] index: no use + \param[out] len: data length pointer + \retval descriptor buffer pointer +*/ +static uint8_t* _usb_bos_desc_get (usb_dev *udev, uint8_t index, uint16_t *len) +{ + if (NULL != udev->desc->bos_desc) { + (void)index; + + *len = (uint16_t)udev->desc->bos_desc[2] | (uint16_t)((uint16_t)udev->desc->bos_desc[3] << 8); + + return udev->desc->bos_desc; + } else { + *len = 0U; + + return NULL; + } +} + +/*! + \brief get string descriptor + \param[in] udev: pointer to USB device instance + \param[in] index: string descriptor index + \param[out] len: pointer to string length + \retval string descriptor +*/ +static uint8_t* _usb_str_desc_get (usb_dev *udev, uint8_t index, uint16_t *len) +{ + uint8_t* desc = udev->desc->strings[index]; + + *len = desc[0]; + + return desc; +} + +/*! + \brief handle Get_Status request + \param[in] udev: pointer to USB device instance + \param[in] req: pointer to USB device request + \param[out] none + \retval USB device request status +*/ +static usb_reqsta _usb_std_getstatus (usb_dev *udev, usb_req *req) +{ + uint8_t recp = BYTE_LOW(req->wIndex); + + usb_reqsta req_status = REQ_NOTSUPP; + + static uint8_t status[2] = {0U}; + + switch(req->bmRequestType & USB_RECPTYPE_MASK) { + /* handle device get status request */ + case USB_RECPTYPE_DEV: + switch (udev->cur_status) { + case USBD_ADDRESSED: + case USBD_CONFIGURED: + if (udev->pm.power_mode) { + status[0] = USB_STATUS_SELF_POWERED; + } else { + status[0] = 0U; + } + + if (udev->pm.remote_wakeup) { + status[0] |= USB_STATUS_REMOTE_WAKEUP; + } else { + status[0] = 0U; + } + + req_status = REQ_SUPP; + break; + + default: + break; + } + break; + /* handle interface get status request */ + case USB_RECPTYPE_ITF: + if (((uint8_t)USBD_CONFIGURED == udev->cur_status) && (recp < USBD_ITF_MAX_NUM)) { + req_status = REQ_SUPP; + } + break; + /* handle endpoint get status request */ + case USB_RECPTYPE_EP: + if ((uint8_t)USBD_CONFIGURED == udev->cur_status) { + if (0x80U == (recp & 0x80U)) { + status[0] = udev->transc_in[EP_ID(recp)].ep_stall; + } else { + status[0] = udev->transc_out[recp].ep_stall; + } + req_status = REQ_SUPP; + } + break; + + default: + break; + } + + if (REQ_SUPP == req_status) { + usb_transc_config(&udev->transc_in[0], status, 2U, 2U); + } + + return req_status; +} + +/*! + \brief handle USB Clear_Feature request + \param[in] udev: pointer to USB device instance + \param[in] req: USB device request + \param[out] none + \retval USB device request status +*/ +static usb_reqsta _usb_std_clearfeature (usb_dev *udev, usb_req *req) +{ + uint8_t ep = 0U; + + switch (req->bmRequestType & (uint8_t)USB_RECPTYPE_MASK) { + case USB_RECPTYPE_DEV: + switch (udev->cur_status) { + case USBD_ADDRESSED: + case USBD_CONFIGURED: + /* clear device remote wakeup feature */ + if ((uint16_t)USB_FEATURE_REMOTE_WAKEUP == req->wValue) { + udev->pm.remote_wakeup = 0U; + + return REQ_SUPP; + } + break; + + default: + break; + } + break; + + case USB_RECPTYPE_EP: + /* get endpoint address */ + ep = BYTE_LOW(req->wIndex); + + if ((uint8_t)USBD_CONFIGURED == udev->cur_status) { + /* clear endpoint halt feature */ + if (((uint16_t)USB_FEATURE_EP_HALT == req->wValue) && (!CTL_EP(ep))) { + usbd_ep_clear_stall(udev, ep); + + udev->class_core->req_process(udev, req); + + return REQ_SUPP; + } + } + break; + + case USB_RECPTYPE_ITF: + break; + + default: + break; + } + + return REQ_NOTSUPP; +} + +/*! + \brief handle USB Set_Feature request + \param[in] udev: pointer to USB device instance + \param[in] req: pointer to USB device request + \param[out] none + \retval USB device request status +*/ +static usb_reqsta _usb_std_setfeature (usb_dev *udev, usb_req *req) +{ + uint8_t ep = 0U; + + switch (req->bmRequestType & (uint8_t)USB_RECPTYPE_MASK) { + case USB_RECPTYPE_DEV: + switch (udev->cur_status) { + case USBD_ADDRESSED: + case USBD_CONFIGURED: + /* set device remote wakeup feature */ + if ((uint16_t)USB_FEATURE_REMOTE_WAKEUP == req->wValue) { + udev->pm.remote_wakeup = 1U; + + return REQ_SUPP; + } + break; + + default: + break; + } + break; + + case USB_RECPTYPE_EP: + /* get endpoint address */ + ep = BYTE_LOW(req->wIndex); + + if ((uint8_t)USBD_CONFIGURED == udev->cur_status) { + /* set endpoint halt feature */ + if (((uint8_t)USB_FEATURE_EP_HALT == req->wValue) && (!CTL_EP(ep))) { + usbd_ep_stall(udev, ep); + + return REQ_SUPP; + } + } + break; + + case USB_RECPTYPE_ITF: + break; + + default: + break; + } + + return REQ_NOTSUPP; +} + +/*! + \brief handle USB Set_Address request + \param[in] udev: pointer to USB device instance + \param[in] req: pointer to USB device request + \param[out] none + \retval USB device request status +*/ +static usb_reqsta _usb_std_setaddress (usb_dev *udev, usb_req *req) +{ + if ((0U == req->wIndex) && (0U == req->wLength)) { + udev->dev_addr = (uint8_t)(req->wValue) & 0x7FU; + + if (udev->cur_status != (uint8_t)USBD_CONFIGURED) { + if (udev->dev_addr) { + udev->cur_status = (uint8_t)USBD_ADDRESSED; + } else { + udev->cur_status = (uint8_t)USBD_DEFAULT; + } + + return REQ_SUPP; + } + } + + return REQ_NOTSUPP; +} + +/*! + \brief handle USB Get_Descriptor request + \param[in] udev: pointer to USB device instance + \param[in] req: pointer to USB device request + \param[out] none + \retval USB device request status +*/ +static usb_reqsta _usb_std_getdescriptor (usb_dev *udev, usb_req *req) +{ + uint8_t desc_type = 0U; + uint8_t desc_index = 0U; + + usb_reqsta status = REQ_NOTSUPP; + + usb_transc *transc = &udev->transc_in[0]; + + switch (req->bmRequestType & USB_RECPTYPE_MASK) { + case USB_RECPTYPE_DEV: + desc_type = BYTE_HIGH(req->wValue); + desc_index = BYTE_LOW(req->wValue); + + switch (desc_type) { + case USB_DESCTYPE_DEV: + transc->xfer_buf = std_desc_get[desc_type - 1U](udev, desc_index, &transc->xfer_len); + if (64U == req->wLength) { + transc->xfer_len = 8U; + } + break; + + case USB_DESCTYPE_CONFIG: + transc->xfer_buf = std_desc_get[desc_type - 1U](udev, desc_index, &transc->xfer_len); + break; + + case USB_DESCTYPE_STR: + if (desc_index < STR_IDX_MAX) { + transc->xfer_buf = std_desc_get[desc_type - 1U](udev, desc_index, &transc->xfer_len); + } + break; + + case USB_DESCTYPE_ITF: + case USB_DESCTYPE_EP: + case USB_DESCTYPE_DEV_QUALIFIER: + case USB_DESCTYPE_OTHER_SPD_CONFIG: + case USB_DESCTYPE_ITF_POWER: + break; + + case USB_DESCTYPE_BOS: + transc->xfer_buf = _usb_bos_desc_get(udev, desc_index, &transc->xfer_len); + break; + + default: + break; + } + break; + + case USB_RECPTYPE_ITF: + /* get device class special descriptor */ + status = (usb_reqsta)(udev->class_core->req_process(udev, req)); + break; + + case USB_RECPTYPE_EP: + break; + + default: + break; + } + + if ((transc->xfer_len) && (req->wLength)) { + transc->xfer_len = USB_MIN(transc->xfer_len, req->wLength); + + if ((transc->xfer_len < udev->control.req.wLength) && + (0U == transc->xfer_len % transc->max_len)) { + udev->control.ctl_zlp = 1U; + } + + status = REQ_SUPP; + } + + return status; +} + +/*! + \brief handle USB Set_Descriptor request + \param[in] udev: pointer to USB device instance + \param[in] req: pointer to USB device request + \param[out] none + \retval USB device request status +*/ +static usb_reqsta _usb_std_setdescriptor (usb_dev *udev, usb_req *req) +{ + (void)udev; + (void)req; + + /* no handle */ + return REQ_SUPP; +} + +/*! + \brief handle USB Get_Configuration request + \param[in] udev: pointer to USB device instance + \param[in] req: pointer to USB device request + \param[out] none + \retval USB device request status +*/ +static usb_reqsta _usb_std_getconfiguration (usb_dev *udev, usb_req *req) +{ + (void)req; + + usb_reqsta req_status = REQ_NOTSUPP; + + switch (udev->cur_status) { + case USBD_ADDRESSED: + if (0U == udev->config) { + req_status = REQ_SUPP; + } + break; + + case USBD_CONFIGURED: + if (udev->config) { + req_status = REQ_SUPP; + } + break; + + default: + break; + } + + if (REQ_SUPP == req_status) { + usb_transc_config(&udev->transc_in[0], &(udev->config), 1U, 1U); + } + + return req_status; +} + +/*! + \brief handle USB Set_Configuration request + \param[in] udev: pointer to USB device instance + \param[in] req: pointer to USB device request + \param[out] none + \retval USB device operation cur_status +*/ +static usb_reqsta _usb_std_setconfiguration (usb_dev *udev, usb_req *req) +{ + static uint8_t config; + usb_reqsta status = REQ_NOTSUPP; + + config = (uint8_t)(req->wValue); + + if (config <= USBD_CFG_MAX_NUM) { + switch (udev->cur_status) { + case USBD_ADDRESSED: + if (config){ + (void)udev->class_core->init(udev, config); + + udev->config = config; + udev->cur_status = (uint8_t)USBD_CONFIGURED; + } + status = REQ_SUPP; + break; + + case USBD_CONFIGURED: + if (0U == config) { + (void)udev->class_core->deinit(udev, config); + + udev->config = config; + udev->cur_status = (uint8_t)USBD_ADDRESSED; + } else if (config != udev->config) { + /* clear old configuration */ + (void)udev->class_core->deinit(udev, udev->config); + + /* set new configuration */ + udev->config = config; + + (void)udev->class_core->init(udev, config); + } else { + /* no operation */ + } + status = REQ_SUPP; + break; + + case USBD_DEFAULT: + break; + + default: + break; + } + } + + return status; +} + +/*! + \brief handle USB Get_Interface request + \param[in] udev: pointer to USB device instance + \param[in] req: pointer to USB device request + \param[out] none + \retval USB device request status +*/ +static usb_reqsta _usb_std_getinterface (usb_dev *udev, usb_req *req) +{ + switch (udev->cur_status) { + case USBD_DEFAULT: + break; + + case USBD_ADDRESSED: + break; + + case USBD_CONFIGURED: + if (BYTE_LOW(req->wIndex) < USBD_ITF_MAX_NUM) { + usb_transc_config(&udev->transc_in[0], &(udev->class_core->req_altset), 1U, 1U); + + return REQ_SUPP; + } + break; + + default: + break; + } + + return REQ_NOTSUPP; +} + +/*! + \brief handle USB Set_Interface request + \param[in] udev: pointer to USB device instance + \param[in] req: pointer to USB device request + \param[out] none + \retval USB device request status +*/ +static usb_reqsta _usb_std_setinterface (usb_dev *udev, usb_req *req) +{ + switch (udev->cur_status) { + case USBD_DEFAULT: + break; + + case USBD_ADDRESSED: + break; + + case USBD_CONFIGURED: + if (BYTE_LOW(req->wIndex) < USBD_ITF_MAX_NUM) { + udev->class_core->req_altset = (uint8_t)req->wValue; + + return REQ_SUPP; + } + break; + + default: + break; + } + + return REQ_NOTSUPP; +} + +/*! + \brief handle USB SynchFrame request + \param[in] udev: pointer to USB device instance + \param[in] req: pointer to USB device request + \param[out] none + \retval USB device request status +*/ +static usb_reqsta _usb_std_synchframe (usb_dev *udev, usb_req *req) +{ + (void)udev; + (void)req; + + /* no handle */ + return REQ_SUPP; +} + +/*! + \brief convert hex 32bits value into unicode char + \param[in] value: Hex 32bits value + \param[in] pbuf: buffer pointer to store unicode char + \param[in] len: value length + \param[out] none + \retval none +*/ +static void int_to_unicode (uint32_t value, uint8_t *pbuf, uint8_t len) +{ + uint8_t index = 0U; + + for (index = 0U; index < len; index++) { + if ((value >> 28U) < 0x0AU) { + pbuf[2U * index] = (uint8_t)((value >> 28) + '0'); + } else { + pbuf[2U * index] = (uint8_t)((value >> 28) + 'A' - 10U); + } + + value = value << 4U; + + pbuf[2U * index + 1U] = 0U; + } +} + +/*! + \brief convert hex 32bits value into unicode char + \param[in] none + \param[out] none + \retval none +*/ +void serial_string_get (uint16_t *unicode_str) +{ + if (6U != (unicode_str[0] & 0x00FFU)) { + uint32_t DeviceSerial0, DeviceSerial1, DeviceSerial2; + + DeviceSerial0 = *(uint32_t*)DEVICE_ID1; + DeviceSerial1 = *(uint32_t*)DEVICE_ID2; + DeviceSerial2 = *(uint32_t*)DEVICE_ID3; + + DeviceSerial0 += DeviceSerial2; + + if (0U != DeviceSerial0) { + int_to_unicode(DeviceSerial0, (uint8_t*)&(unicode_str[1]), 8U); + int_to_unicode(DeviceSerial1, (uint8_t*)&(unicode_str[9]), 4U); + } + } else { + uint32_t device_serial = *(uint32_t*)DEVICE_ID; + + if (0U != device_serial) { + unicode_str[1] = (uint16_t)(device_serial & 0x0000FFFFU); + unicode_str[2] = (uint16_t)((device_serial & 0xFFFF0000U) >> 16U); + + } + } +} diff --git a/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbd_library/device/Source/usbd_pwr.c b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbd_library/device/Source/usbd_pwr.c new file mode 100644 index 0000000000..952a125352 --- /dev/null +++ b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbd_library/device/Source/usbd_pwr.c @@ -0,0 +1,60 @@ +/*! + \file usbd_pwr.c + \brief USB device power management driver + + \version 2020-08-01, V3.0.0, firmware for GD32F30x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "usbd_pwr.h" + +/*! + \brief start to remote wakeup + \param[in] udev: pointer to USB core instance + \param[out] none + \retval none +*/ +void usbd_remote_wakeup_active(usb_dev *udev) +{ + resume_mcu(udev); + +#ifdef LPM_ENABLED + if(1 == udev->lpm.L1_remote_wakeup){ + udev->drv_handler->resume(udev); + + udev->lpm.L1_resume = 1U; + } +#endif /* LPM_ENABLED */ + + if(1U == udev->pm.remote_wakeup){ + udev->pm.remote_wakeup_on = 1U; + udev->pm.esof_count = 15U; + udev->drv_handler->resume(udev); + } +} diff --git a/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbd_library/device/Source/usbd_transc.c b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbd_library/device/Source/usbd_transc.c new file mode 100644 index 0000000000..bbbfe5f5a7 --- /dev/null +++ b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbd_library/device/Source/usbd_transc.c @@ -0,0 +1,207 @@ +/*! + \file usbd_transc.c + \brief USBD transaction function + + \version 2020-08-01, V3.0.0, firmware for GD32F30x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "usbd_enum.h" +#include "usbd_transc.h" + +/* local function prototypes ('static') */ +static inline void usb_stall_transc (usb_dev *udev); +static inline void usb_ctl_status_in (usb_dev *udev); +static inline void usb_ctl_data_in (usb_dev *udev); +static inline void usb_ctl_out (usb_dev *udev); +static inline void usb_0len_packet_send (usb_dev *udev); + +/*! + \brief USB setup stage processing + \param[in] udev: pointer to USB device instance + \param[out] none + \retval none +*/ +void _usb_setup_transc (usb_dev *udev, uint8_t ep_num) +{ + (void)ep_num; + + usb_reqsta reqstat = REQ_NOTSUPP; + + uint16_t count = udev->drv_handler->ep_read((uint8_t *)(&udev->control.req), 0U, (uint8_t)EP_BUF_SNG); + + if (count != USB_SETUP_PACKET_LEN) { + usb_stall_transc(udev); + + return; + } + + switch (udev->control.req.bmRequestType & USB_REQTYPE_MASK) { + /* standard device request */ + case USB_REQTYPE_STRD: + reqstat = usbd_standard_request(udev, &udev->control.req); + break; + + /* device class request */ + case USB_REQTYPE_CLASS: + reqstat = usbd_class_request(udev, &udev->control.req); + break; + + /* vendor defined request */ + case USB_REQTYPE_VENDOR: + reqstat = usbd_vendor_request(udev, &udev->control.req); + break; + + default: + break; + } + + if (REQ_SUPP == reqstat) { + if (0U == udev->control.req.wLength) { + /* USB control transfer status in stage */ + usb_ctl_status_in(udev); + } else { + if (udev->control.req.bmRequestType & 0x80U) { + usb_ctl_data_in(udev); + } else { + /* USB control transfer data out stage */ + usb_ctl_out(udev); + } + } + } else { + usb_stall_transc(udev); + } +} + +/*! + \brief data out stage processing + \param[in] udev: pointer to USB device instance + \param[in] ep_num: endpoint identifier(0..7) + \param[out] none + \retval none +*/ +void _usb_out0_transc (usb_dev *udev, uint8_t ep_num) +{ + if (((uint8_t)USBD_CONFIGURED == udev->cur_status) && (udev->class_core->ctlx_out != NULL)) { + /* device class handle */ + (void)udev->class_core->ctlx_out(udev); + } + + usb_transc_config(&udev->transc_out[ep_num], NULL, 0U, 0U); + + /* enter the control transaction status in stage */ + usb_ctl_status_in(udev); +} + +/*! + \brief data in stage processing + \param[in] udev: pointer to USB device instance + \param[in] ep_num: endpoint identifier(0..7) + \param[out] none + \retval none +*/ +void _usb_in0_transc (usb_dev *udev, uint8_t ep_num) +{ + (void)ep_num; + + if (udev->control.ctl_zlp) { + /* send 0 length packet */ + usb_0len_packet_send(udev); + + udev->control.ctl_zlp = 0U; + } + + if (((uint8_t)USBD_CONFIGURED == udev->cur_status) && (udev->class_core->ctlx_in != NULL)) { + (void)udev->class_core->ctlx_in(udev); + } + + /* USB control transfer status out stage */ + usb_ctl_out(udev); + + if (0U != udev->dev_addr) { + udev->drv_handler->set_addr(udev); + + udev->dev_addr = 0U; + } +} + +/*! + \brief USB stalled transaction + \param[in] udev: pointer to USB device instance + \param[out] none + \retval none +*/ +static inline void usb_stall_transc (usb_dev *udev) +{ + usbd_ep_stall(udev, 0x0U); +} + +/*! + \brief USB control transaction status in stage + \param[in] udev: pointer to USB device instance + \param[out] none + \retval none +*/ +static inline void usb_ctl_status_in (usb_dev *udev) +{ + udev->drv_handler->ep_write(udev->transc_in[0].xfer_buf, 0U, 0U); +} + +/*! + \brief USB control transaction data in stage + \param[in] udev: pointer to USB device instance + \param[out] none + \retval none +*/ +static inline void usb_ctl_data_in (usb_dev *udev) +{ + usbd_ep_send(udev, 0U, udev->transc_in[0].xfer_buf, udev->transc_in[0].xfer_len); +} + +/*! + \brief USB control transaction data out & status out stage + \param[in] udev: pointer to USB device instance + \param[out] none + \retval none +*/ +static inline void usb_ctl_out (usb_dev *udev) +{ + udev->drv_handler->ep_rx_enable(udev, 0U); +} + +/*! + \brief USB send 0 length data packet + \param[in] udev: pointer to USB device instance + \param[out] none + \retval none +*/ +static inline void usb_0len_packet_send (usb_dev *udev) +{ + udev->drv_handler->ep_write(udev->transc_in[0].xfer_buf, 0U, 0U); +} diff --git a/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbd_library/usbd/Include/usbd_lld_core.h b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbd_library/usbd/Include/usbd_lld_core.h new file mode 100644 index 0000000000..77862453db --- /dev/null +++ b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbd_library/usbd/Include/usbd_lld_core.h @@ -0,0 +1,73 @@ +/*! + \file usbd_lld_core.h + \brief USB device low level driver core + + \version 2020-08-01, V3.0.0, firmware for GD32F30x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef __USBD_LLD_CORE_H +#define __USBD_LLD_CORE_H + +#include "usbd_lld_regs.h" +#include "usbd_core.h" + +/* double buffer endpoint direction enumeration */ +enum dbuf_ep_dir +{ + DBUF_EP_IN, /*!< double buffer in direction */ + DBUF_EP_OUT, /*!< double buffer out direction */ + DBUF_EP_ERR, /*!< double buffer error direction */ +}; + +/* USBD endpoint ram struct */ +typedef struct +{ + __IO uint32_t tx_addr; /*!< transmission address */ + __IO uint32_t tx_count; /*!< transmission count */ + __IO uint32_t rx_addr; /*!< reception address */ + __IO uint32_t rx_count; /*!< reception count */ +} usbd_ep_ram; + +extern struct _usb_handler usbd_drv_handler; + +/* USB core driver struct */ +typedef struct +{ + usb_basic basic; + usb_dev *dev; +} usb_core_drv; + +extern usb_core_drv usbd_core; + +/* function declarations */ +/* free buffer used from application by toggling the SW_BUF byte */ +void user_buffer_free (uint8_t ep_num, uint8_t dir); + +#endif /* __USBD_LLD_CORE_H */ diff --git a/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbd_library/usbd/Include/usbd_lld_int.h b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbd_library/usbd/Include/usbd_lld_int.h new file mode 100644 index 0000000000..86ebff830b --- /dev/null +++ b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbd_library/usbd/Include/usbd_lld_int.h @@ -0,0 +1,48 @@ +/*! + \file usbd_lld_int.h + \brief USB device low level interrupt handler + + \version 2020-08-01, V3.0.0, firmware for GD32F30x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef __USBD_LLD_INT_H +#define __USBD_LLD_INT_H + +#include "usbd_core.h" +#include "usbd_enum.h" +#include "usbd_pwr.h" + +/* function declarations */ +/* USB device interrupt service routine */ +void usbd_isr (void); +/* handle USB high priority successful transfer event */ +void usbd_int_hpst (usb_dev *udev); + +#endif /* __USBD_LLD_INT_H */ diff --git a/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbd_library/usbd/Include/usbd_lld_regs.h b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbd_library/usbd/Include/usbd_lld_regs.h new file mode 100644 index 0000000000..52ab730523 --- /dev/null +++ b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbd_library/usbd/Include/usbd_lld_regs.h @@ -0,0 +1,227 @@ +/*! + \file usbd_lld_regs.h + \brief USB device low level registers + + \version 2020-08-01, V3.0.0, firmware for GD32F30x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef __USBD_LLD_REGS_H +#define __USBD_LLD_REGS_H + +#include "usbd_conf.h" + +/* USB device registers base address */ +#define USBD USBD_BASE +#define USBD_RAM USBD_RAM_BASE + +/* registers definitions */ +/* common registers */ +#define USBD_CTL (REG32(USBD + 0x40U)) /*!< control register */ +#define USBD_INTF (REG32(USBD + 0x44U)) /*!< interrupt flag register */ +#define USBD_STAT (REG32(USBD + 0x48U)) /*!< status register */ +#define USBD_DADDR (REG32(USBD + 0x4CU)) /*!< device address register */ +#define USBD_BADDR (REG32(USBD + 0x50U)) /*!< buffer address register */ +#define USBD_LPMCS (REG32(USBD + 0x54U)) /*!< USBD LPM control and status register */ + +/* endpoint control and status register */ +#define USBD_EPxCS(ep_num) (REG32(USBD + (ep_num) * 4U)) /*!< endpoint x control and status register address */ + +/* bits definitions */ +/* USBD_CTL */ +#define CTL_STIE BIT(15) /*!< successful transfer interrupt enable mask */ +#define CTL_PMOUIE BIT(14) /*!< packet memory overrun/underrun interrupt enable mask */ +#define CTL_ERRIE BIT(13) /*!< error interrupt enable mask */ +#define CTL_WKUPIE BIT(12) /*!< wakeup interrupt enable mask */ +#define CTL_SPSIE BIT(11) /*!< suspend state interrupt enable mask */ +#define CTL_RSTIE BIT(10) /*!< reset interrupt enable mask */ +#define CTL_SOFIE BIT(9) /*!< start of frame interrupt enable mask */ +#define CTL_ESOFIE BIT(8) /*!< expected start of frame interrupt enable mask */ +#define CTL_L1REQIE BIT(7) /*!< LPM L1 state request interrupt enable */ +#define CTL_L1RSREQ BIT(5) /*!< LPM L1 resume request */ +#define CTL_RSREQ BIT(4) /*!< resume request */ +#define CTL_SETSPS BIT(3) /*!< set suspend state */ +#define CTL_LOWM BIT(2) /*!< low-power mode at suspend state */ +#define CTL_CLOSE BIT(1) /*!< goes to close state */ +#define CTL_SETRST BIT(0) /*!< set USB reset */ + +#ifdef LPM_ENABLED +#define USBD_INTEN BITS(7, 15) /*!< USBD interrupt enable bits */ +#else +#define USBD_INTEN BITS(8, 15) /*!< USBD interrupt enable bits */ +#endif +/* USBD_INTF */ +#define INTF_STIF BIT(15) /*!< successful transfer interrupt flag (read only bit) */ +#define INTF_PMOUIF BIT(14) /*!< packet memory overrun/underrun interrupt flag (clear-only bit) */ +#define INTF_ERRIF BIT(13) /*!< error interrupt flag (clear-only bit) */ +#define INTF_WKUPIF BIT(12) /*!< wakeup interrupt flag (clear-only bit) */ +#define INTF_SPSIF BIT(11) /*!< suspend state interrupt flag (clear-only bit) */ +#define INTF_RSTIF BIT(10) /*!< reset interrupt flag (clear-only bit) */ +#define INTF_SOFIF BIT(9) /*!< start of frame interrupt flag (clear-only bit) */ +#define INTF_ESOFIF BIT(8) /*!< expected start of frame interrupt flag(clear-only bit) */ +#define INTF_L1REQ BIT(7) /*!< LPM L1 transaction is successfully received and acknowledged */ +#define INTF_DIR BIT(4) /*!< direction of transaction (read-only bit) */ +#define INTF_EPNUM BITS(0, 3) /*!< endpoint number (read-only bit) */ + +/* USBD_STAT */ +#define STAT_RXDP BIT(15) /*!< data plus line status */ +#define STAT_RXDM BIT(14) /*!< data minus line status */ +#define STAT_LOCK BIT(13) /*!< locked the USB */ +#define STAT_SOFLN BITS(11, 12) /*!< SOF lost number */ +#define STAT_FCNT BITS(0, 10) /*!< frame number count */ + +/* USBD_DADDR */ +#define DADDR_USBEN BIT(7) /*!< USB module enable */ +#define DADDR_USBADDR BITS(0, 6) /*!< USB device address */ + +/* USBD_EPxCS */ +#define EPxCS_RX_ST BIT(15) /*!< endpoint reception successful transferred */ +#define EPxCS_RX_DTG BIT(14) /*!< endpoint reception data PID toggle */ +#define EPxCS_RX_STA BITS(12, 13) /*!< endpoint reception status bits */ +#define EPxCS_SETUP BIT(11) /*!< endpoint setup transaction completed */ +#define EPxCS_CTL BITS(9, 10) /*!< endpoint type control */ +#define EPxCS_KCTL BIT(8) /*!< endpoint kind control */ +#define EPxCS_TX_ST BIT(7) /*!< endpoint transmission successful transfer */ +#define EPxCS_TX_DTG BIT(6) /*!< endpoint transmission data toggle */ +#define EPxCS_TX_STA BITS(4, 5) /*!< endpoint transmission transfers status bits */ +#define EPxCS_AR BITS(0, 3) /*!< endpoint address */ + +/* USBD_LPMCS */ +#define LPMCS_BLSTAT BITS(4, 7) /*!< bLinkState value */ +#define LPMCS_REMWK BIT(3) /*!< bRemoteWake value */ +#define LPMCS_LPMACK BIT(1) /*!< LPM token acknowledge enable */ +#define LPMCS_LPMEN BIT(0) /*!< LPM support enable */ + +/* constants definitions */ +/* endpoint control and status register mask (no toggle fields) */ +#define EPCS_MASK (EPxCS_RX_ST | EPxCS_SETUP | \ + EPxCS_CTL | EPxCS_KCTL | EPxCS_TX_ST | EPxCS_AR) + +/* EPxCS_CTL[1:0] endpoint type control */ +#define ENDP_TYPE(regval) (EPxCS_CTL & ((regval) << 9U)) + +#define EP_BULK ENDP_TYPE(0U) /* bulk transfers */ +#define EP_CONTROL ENDP_TYPE(1U) /* control transfers */ +#define EP_ISO ENDP_TYPE(2U) /* isochronous transfers */ +#define EP_INTERRUPT ENDP_TYPE(3U) /* interrupt transfers */ +#define EP_CTL_MASK (~EPxCS_CTL & EPCS_MASK) + +/* endpoint kind control mask */ +#define EPKCTL_MASK (~EPxCS_KCTL & EPCS_MASK) + +/* EPxCS_TX_STA[1:0] status for Tx transfer */ +#define ENDP_TXSTAT(regval) (EPxCS_TX_STA & ((regval) << 4U)) + +#define EPTX_DISABLED ENDP_TXSTAT(0U) /* transmission state is disabled */ +#define EPTX_STALL ENDP_TXSTAT(1U) /* transmission state is STALL */ +#define EPTX_NAK ENDP_TXSTAT(2U) /* transmission state is NAK */ +#define EPTX_VALID ENDP_TXSTAT(3U) /* transmission state is enabled */ +#define EPTX_DTGMASK (EPxCS_TX_STA | EPCS_MASK) + +/* EPxCS_RX_STA[1:0] status for Rx transfer */ +#define ENDP_RXSTAT(regval) (EPxCS_RX_STA & ((regval) << 12U)) + +#define EPRX_DISABLED ENDP_RXSTAT(0U) /* reception state is disabled */ +#define EPRX_STALL ENDP_RXSTAT(1U) /* reception state is STALL */ +#define EPRX_NAK ENDP_RXSTAT(2U) /* reception state is NAK */ +#define EPRX_VALID ENDP_RXSTAT(3U) /* reception state is enabled */ +#define EPRX_DTGMASK (EPxCS_RX_STA | EPCS_MASK) + +/* endpoint receive/transmission counter register bit definitions */ +#define EPRCNT_BLKSIZ BIT(15) /* reception data block size */ +#define EPRCNT_BLKNUM BITS(10, 14) /* reception data block number */ +#define EPRCNT_CNT BITS(0, 9) /* reception data count */ + +#define EPTCNT_CNT BITS(0, 9) /* transmisson data count */ + +/* interrupt flag clear bits */ +#define CLR(x) (USBD_INTF = ~INTF_##x) + +/* endpoint receive/transmission counter register bit offset */ +#define BLKSIZE_OFFSET (0x01U) +#define BLKNUM_OFFSET (0x05U) +#define RXCNT_OFFSET (0x0AU) + +#define TXCNT_OFFSET (0x0AU) + +#define BLKSIZE32_MASK (0x1fU) +#define BLKSIZE2_MASK (0x01U) + +#define BLKSIZE32_OFFSETMASK (0x05U) +#define BLKSIZE2_OFFSETMASK (0x01U) + +/* USBD operation macros */ + +/* Tx or Rx transfer status setting (bits EPTX_STA[1:0]) */ + +#define USBD_EP_TX_STAT_SET(ep, stat) do {\ + USBD_EPxCS(ep) = (USBD_EPxCS(ep) & (uint16_t)EPTX_DTGMASK) ^ (stat); \ +} while(0) + +#define USBD_EP_RX_STAT_SET(ep, stat) do {\ + USBD_EPxCS(ep) = (USBD_EPxCS(ep) & (uint16_t)EPRX_DTGMASK) ^ (stat); \ +} while(0) + +/* clear bit EPxCS_RX_ST/EPxCS_TX_ST in the endpoint control and status register */ + +#define USBD_EP_TX_ST_CLEAR(ep) do {\ + USBD_EPxCS(ep) &= ~EPxCS_TX_ST & (uint16_t)EPCS_MASK; \ +} while(0) + +#define USBD_EP_RX_ST_CLEAR(ep) do {\ + USBD_EPxCS(ep) &= ~EPxCS_RX_ST & (uint16_t)EPCS_MASK; \ +} while(0) + +/* toggle EPxCS_RX_DTG or EPxCS_TX_DTG bit in the endpoint control and status register */ + +#define USBD_TX_DTG_TOGGLE(ep) do {\ + USBD_EPxCS(ep) = EPxCS_TX_DTG | (USBD_EPxCS(ep) & EPCS_MASK); \ +} while(0) + +#define USBD_RX_DTG_TOGGLE(ep) do {\ + USBD_EPxCS(ep) = EPxCS_RX_DTG | (USBD_EPxCS(ep) & EPCS_MASK); \ +} while(0) + +/* clear EPxCS_RX_DTG or EPxCS_TX_DTG bit in the endpoint control and status register */ + +#define USBD_TX_DTG_CLEAR(ep) do {\ + if ((USBD_EPxCS(ep_num) & EPxCS_TX_DTG) != 0U) {\ + USBD_TX_DTG_TOGGLE(ep);\ + } \ +} while(0) + +#define USBD_RX_DTG_CLEAR(ep) do {\ + if ((USBD_EPxCS(ep_num) & EPxCS_RX_DTG) != 0U) {\ + USBD_RX_DTG_TOGGLE(ep);\ + } \ +} while(0) + +#define USBD_EP_DBL_BUF_SET(ep) (USBD_EPxCS(ep) = (USBD_EPxCS(ep) | EPxCS_KCTL) & EPCS_MASK) + +#endif /* __USBD_LLD_REGS_H */ diff --git a/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbd_library/usbd/Source/usbd_lld_core.c b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbd_library/usbd/Source/usbd_lld_core.c new file mode 100644 index 0000000000..28e659c19c --- /dev/null +++ b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbd_library/usbd/Source/usbd_lld_core.c @@ -0,0 +1,641 @@ +/*! + \file usbd_lld_core.c + \brief USB device low level driver core + + \version 2020-08-01, V3.0.0, firmware for GD32F30x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "usbd_lld_core.h" +#include "usbd_enum.h" + +#define USB_EPTYPE_MASK 0x03U + +#if defined (__CC_ARM) /* ARM Compiler */ +static usbd_ep_ram btable_ep[EP_COUNT]__attribute__((at(USBD_RAM + 2 * (BTABLE_OFFSET & 0xFFF8)))); +#elif defined (__ICCARM__) /* IAR Compiler */ + __no_init usbd_ep_ram btable_ep[EP_COUNT] @(USBD_RAM + 2 * (BTABLE_OFFSET & 0xFFF8)); +#elif defined (__GNUC__) /* GNU GCC Compiler */ + usbd_ep_ram *btable_ep = (usbd_ep_ram *)(USBD_RAM + 2 * (BTABLE_OFFSET & 0xFFF8)); +#endif + +usb_core_drv usbd_core; + +static const uint32_t ep_type[] = { + [USB_EP_ATTR_CTL] = EP_CONTROL, + [USB_EP_ATTR_BULK] = EP_BULK, + [USB_EP_ATTR_INT] = EP_INTERRUPT, + [USB_EP_ATTR_ISO] = EP_ISO +}; + +/* local function prototypes ('static') */ +static void usbd_dp_pullup (FlagStatus status); +static void usbd_core_reset (void); +static void usbd_core_stop (void); +static void usbd_address_set (usb_dev *udev); +static void usbd_ep_reset (usb_dev *udev); +static void usbd_ep_setup (usb_dev *udev, uint8_t buf_kind, uint32_t buf_addr, const usb_desc_ep *ep_desc); +static void usbd_ep_rx_enable (usb_dev *udev, uint8_t ep_addr); +static void usbd_ep_disable (usb_dev *udev, uint8_t ep_addr); +static void usbd_ep_stall_set (usb_dev *udev, uint8_t ep_addr); +static void usbd_ep_stall_clear (usb_dev *udev, uint8_t ep_addr); +static void usbd_ep_data_write (uint8_t *user_fifo, uint8_t ep_num, uint16_t bytes); +static uint16_t usbd_ep_data_read (uint8_t *user_fifo, uint8_t ep_num, uint8_t buf_kind); +static void usbd_resume (usb_dev *udev); +static void usbd_suspend (void); +static void usbd_leave_suspend (void); +static uint8_t usbd_ep_status (usb_dev *udev, uint8_t ep_addr); + +struct _usb_handler usbd_drv_handler = { + .dp_pullup = usbd_dp_pullup, + .init = usbd_core_reset, + .deinit = usbd_core_stop, + .suspend = usbd_suspend, + .suspend_leave = usbd_leave_suspend, + .resume = usbd_resume, + .set_addr = usbd_address_set, + .ep_reset = usbd_ep_reset, + .ep_disable = usbd_ep_disable, + .ep_setup = usbd_ep_setup, + .ep_rx_enable = usbd_ep_rx_enable, + .ep_write = usbd_ep_data_write, + .ep_read = usbd_ep_data_read, + .ep_stall_set = usbd_ep_stall_set, + .ep_stall_clear = usbd_ep_stall_clear, + .ep_status_get = usbd_ep_status +}; + +/*! + \brief free buffer used from application by toggling the SW_BUF byte + \param[in] ep_num: endpoint identifier (0..7) + \param[in] dir: endpoint direction which can be OUT(0) or IN(1) + \param[out] none + \retval None +*/ +void user_buffer_free (uint8_t ep_num, uint8_t dir) +{ + if ((uint8_t)DBUF_EP_OUT == dir) { + USBD_TX_DTG_TOGGLE(ep_num); + } else if ((uint8_t)DBUF_EP_IN == dir) { + USBD_RX_DTG_TOGGLE(ep_num); + } else { + /* no operation */ + } +} + +/*! + \brief set the status of pull-up pin + \param[in] status: SET or RESET + \param[out] none + \retval none +*/ +static void usbd_dp_pullup (FlagStatus status) +{ + if (SET == status) { + gpio_bit_set(USB_PULLUP, USB_PULLUP_PIN); + } else { + gpio_bit_reset(USB_PULLUP, USB_PULLUP_PIN); + } +} + +/*! + \brief device core register initialization + \param[in] none + \param[out] none + \retval none +*/ +static void usbd_core_reset (void) +{ + /* reset the CLOSE bit */ + USBD_CTL = CTL_SETRST; + + /* may be need wait some time(tSTARTUP) */ + + /* clear SETRST bit in USBD_CTL register */ + USBD_CTL = 0U; + + /* clear all pending interrupts */ + USBD_INTF = 0U; + + /* set descriptors table offset in USB dedicated SRAM */ + USBD_BADDR = BTABLE_OFFSET & 0xFFF8U; + +#ifdef LPM_ENABLED + /* enable L1REQ interrupt */ + USBD_CTL = CTL_L1REQIE; + + USBD_LPMCS = LPMCS_LPMACK | LPMCS_LPMEN; +#endif /* LPM_ENABLED */ + + /* enable all interrupts mask bits */ + USBD_CTL |= CTL_STIE | CTL_WKUPIE | CTL_SPSIE | CTL_SOFIE | CTL_ESOFIE | CTL_RSTIE; +} + +/*! + \brief device core register configure when stop device + \param[in] none + \param[out] none + \retval none +*/ +static void usbd_core_stop (void) +{ + /* disable all interrupts and set USB reset */ + USBD_CTL = CTL_SETRST; + + /* clear all interrupt flags */ + USBD_INTF = 0U; + + /* close device */ + USBD_CTL = CTL_SETRST | CTL_CLOSE; +} + +/*! + \brief set device address + \param[in] udev: pointer to USB device instance + \param[out] none + \retval none +*/ +static void usbd_address_set (usb_dev *udev) +{ + USBD_DADDR = DADDR_USBEN | udev->dev_addr; +} + +/*! + \brief handle USB reset event + \param[in] udev: pointer to USB device instance + \param[out] none + \retval none +*/ +static void usbd_ep_reset (usb_dev *udev) +{ + uint8_t i = 0U; + + usb_transc *transc = &udev->transc_in[0]; + + btable_ep[0].tx_addr = EP0_TX_ADDR; + btable_ep[0].tx_count = 0U; + + transc->max_len = USBD_EP0_MAX_SIZE; + + transc = &udev->transc_out[0]; + + btable_ep[0].rx_addr = EP0_RX_ADDR; + + transc->max_len = USBD_EP0_MAX_SIZE; + + if (transc->max_len > 62U) { + btable_ep[0].rx_count = ((uint16_t)((uint16_t)transc->max_len << 5) - 1U) | 0x8000U; + } else { + btable_ep[0].rx_count = ((transc->max_len + 1U) & ~1U) << 9U; + } + + /* reset non-control endpoints */ + for (i = 1U; i < EP_COUNT; i++) { + USBD_EPxCS(i) = (USBD_EPxCS(i) & EPCS_MASK) | i; + } + + /* clear endpoint 0 register */ + USBD_EPxCS(0U)= (uint16_t)(USBD_EPxCS(0U)); + + USBD_EPxCS(0U) = EP_CONTROL | EPRX_VALID | EPTX_NAK; + + /* set device address as default address 0 */ + USBD_DADDR = DADDR_USBEN; + + udev->cur_status = (uint8_t)USBD_DEFAULT; +} + +/*! + \brief endpoint initialization + \param[in] udev: pointer to USB core instance + \param[in] buf_kind: endpoint buffer kind + \param[in] buf_addr: endpoint buffer address + \param[in] ep_desc: pointer to endpoint descriptor + \param[out] none + \retval none +*/ +static void usbd_ep_setup (usb_dev *udev, uint8_t buf_kind, uint32_t buf_addr, const usb_desc_ep *ep_desc) +{ + uint8_t ep_addr = ep_desc->bEndpointAddress; + uint8_t ep_num = EP_ID(ep_addr); + uint16_t max_len = ep_desc->wMaxPacketSize; + + usb_transc *transc = NULL; + + /* set the endpoint type */ + USBD_EPxCS(ep_num) = ep_type[ep_desc->bmAttributes & USB_EPTYPE_MASK] | ep_num; + + if (EP_DIR(ep_addr)) { + transc = &udev->transc_in[ep_num]; + + transc->max_len = (uint8_t)max_len; + + if ((uint8_t)EP_BUF_SNG == buf_kind) { + btable_ep[ep_num].tx_addr = buf_addr; + + /* configure the endpoint status as NAK status */ + USBD_EP_TX_STAT_SET(ep_num, EPTX_NAK); + } else if ((uint8_t)EP_BUF_DBL == buf_kind) { + USBD_EP_DBL_BUF_SET(ep_num); + + btable_ep[ep_num].tx_addr = buf_addr & 0xFFFFU; + btable_ep[ep_num].rx_addr = (buf_addr & 0xFFFF0000U) >> 16U; + + USBD_EP_TX_STAT_SET(ep_num, EPTX_VALID); + USBD_EP_RX_STAT_SET(ep_num, EPRX_DISABLED); + } else { + /* error operation */ + } + } else { + transc = &udev->transc_out[ep_num]; + + transc->max_len = (uint8_t)max_len; + + if ((uint8_t)EP_BUF_SNG == buf_kind) { + btable_ep[ep_num].rx_addr = buf_addr; + } else if ((uint8_t)EP_BUF_DBL == buf_kind) { + USBD_EP_DBL_BUF_SET(ep_num); + + USBD_TX_DTG_TOGGLE(ep_num); + + btable_ep[ep_num].tx_addr = buf_addr & 0xFFFFU; + btable_ep[ep_num].rx_addr = (buf_addr & 0xFFFF0000U) >> 16U; + + if (max_len > 62U) { + btable_ep[ep_num].tx_count = (((uint32_t)max_len << 5) - 1U) | 0x8000U; + } else { + btable_ep[ep_num].tx_count = ((max_len + 1U) & ~1U) << 9U; + } + } else { + /* error operation */ + } + + if (max_len > 62U) { + btable_ep[ep_num].rx_count = (((uint32_t)max_len << 5U) - 1U) | 0x8000U; + } else { + btable_ep[ep_num].rx_count = ((max_len + 1U) & ~1U) << 9U; + } + + if ((uint8_t)EP_BUF_SNG == buf_kind) { + /* configure the endpoint status as NAK status */ + USBD_EP_RX_STAT_SET(ep_num, EPRX_NAK); + } else if ((uint8_t)EP_BUF_DBL == buf_kind) { + USBD_EP_RX_STAT_SET(ep_num, EPRX_DISABLED); + USBD_EP_TX_STAT_SET(ep_num, EPTX_NAK); + } else { + /* error operation */ + } + } +} + +/*! + \brief configure the endpoint when it is disabled + \param[in] udev: pointer to USB core instance + \param[in] ep_addr: endpoint address + in this parameter: + bit0..bit6: endpoint number (0..7) + bit7: endpoint direction which can be IN(1) or OUT(0) + \param[out] none + \retval none +*/ +static void usbd_ep_disable (usb_dev *udev, uint8_t ep_addr) +{ + (void)udev; + + uint8_t ep_num = EP_ID(ep_addr); + + if (EP_DIR(ep_addr)) { + USBD_TX_DTG_CLEAR(ep_num); + + /* configure the endpoint status as DISABLED */ + USBD_EP_TX_STAT_SET(ep_num, EPTX_DISABLED); + } else { + USBD_RX_DTG_CLEAR(ep_num); + + /* configure the endpoint status as DISABLED */ + USBD_EP_RX_STAT_SET(ep_num, EPRX_DISABLED); + } +} + +/*! + \brief enable endpoint to receive + \param[in] udev: pointer to USB core instance + \param[in] ep_addr: endpoint address + in this parameter: + bit0..bit6: endpoint number (0..7) + bit7: endpoint direction which can be IN(1) or OUT(0) + \param[out] none + \retval none +*/ +static void usbd_ep_rx_enable (usb_dev *udev, uint8_t ep_addr) +{ + (void)udev; + + /* enable endpoint to receive */ + USBD_EP_RX_STAT_SET(EP_ID(ep_addr), EPRX_VALID); +} + +/*! + \brief set an endpoint to STALL status + \param[in] udev: pointer to USB core instance + \param[in] ep_addr: endpoint address + in this parameter: + bit0..bit6: endpoint number (0..7) + bit7: endpoint direction which can be IN(1) or OUT(0) + \param[out] none + \retval none +*/ +static void usbd_ep_stall_set (usb_dev *udev, uint8_t ep_addr) +{ + uint8_t ep_num = EP_ID(ep_addr); + + if (0U == ep_num) { + USBD_EP_TX_STAT_SET(0U, EPTX_STALL); + USBD_EP_RX_STAT_SET(0U, EPRX_STALL); + } else { + if (EP_DIR(ep_addr)) { + udev->transc_in[ep_num].ep_stall = 1U; + + USBD_EP_TX_STAT_SET(ep_num, EPTX_STALL); + } else { + udev->transc_out[ep_num].ep_stall = 1U; + + USBD_EP_RX_STAT_SET(ep_num, EPRX_STALL); + } + } +} + +/*! + \brief clear endpoint stalled status + \param[in] udev: pointer to USB core instance + \param[in] ep_addr: endpoint address + in this parameter: + bit0..bit6: endpoint number (0..7) + bit7: endpoint direction which can be IN(1) or OUT(0) + \param[out] none + \retval none +*/ +static void usbd_ep_stall_clear (usb_dev *udev, uint8_t ep_addr) +{ + uint8_t ep_num = EP_ID(ep_addr); + + if (EP_DIR(ep_addr)) { + /* clear endpoint data toggle bit */ + USBD_TX_DTG_CLEAR(ep_num); + + udev->transc_in[ep_num].ep_stall = 0U; + + /* clear endpoint stall status */ + USBD_EP_TX_STAT_SET(ep_num, EPTX_VALID); + } else { + /* clear endpoint data toggle bit */ + USBD_RX_DTG_CLEAR(ep_num); + + udev->transc_out[ep_num].ep_stall = 0U; + + /* clear endpoint stall status */ + USBD_EP_RX_STAT_SET(ep_num, EPRX_VALID); + } +} + +/*! + \brief get the endpoint status + \param[in] udev: pointer to USB core instance + \param[in] ep_addr: endpoint address + in this parameter: + bit0..bit6: endpoint number (0..7) + bit7: endpoint direction which can be IN(1) or OUT(0) + \param[out] none + \retval endpoint status +*/ +static uint8_t usbd_ep_status (usb_dev *udev, uint8_t ep_addr) +{ + (void)udev; + + uint32_t epcs = USBD_EPxCS(EP_ID(ep_addr)); + + if (EP_DIR(ep_addr)) { + return (uint8_t)(epcs & EPxCS_TX_STA); + } else { + return (uint8_t)(epcs & EPxCS_RX_STA); + } +} + +/*! + \brief write data from user FIFO to USB RAM + \param[in] user_fifo: pointer to user FIFO + \param[in] ep_num: endpoint number + \param[in] bytes: the bytes count of the write data + \param[out] none + \retval none +*/ +static void usbd_ep_data_write (uint8_t *user_fifo, uint8_t ep_num, uint16_t bytes) +{ + if (0U != bytes) { + uint32_t n; + uint32_t *write_addr = (uint32_t *)(btable_ep[ep_num].tx_addr * 2U + USBD_RAM); + + for (n = 0U; n < (bytes + 1U) / 2U; n++) { + *write_addr++ = *((uint16_t*)user_fifo); + user_fifo += 2U; + } + } + + btable_ep[ep_num].tx_count = bytes; + + USBD_EP_TX_STAT_SET(ep_num, EPTX_VALID); +} + +/*! + \brief read data from USBRAM to user FIFO + \param[in] user_fifo: pointer to user FIFO + \param[in] ep_num: endpoint number + \param[in] buf_kind: endpoint buffer kind + \param[out] none + \retval none +*/ +static uint16_t usbd_ep_data_read (uint8_t *user_fifo, uint8_t ep_num, uint8_t buf_kind) +{ + uint16_t n = 0U, bytes = 0U; + uint32_t *read_addr = NULL; + + if ((uint8_t)EP_BUF_SNG == buf_kind) { + bytes = (uint16_t)(btable_ep[ep_num].rx_count & EPRCNT_CNT); + + read_addr = (uint32_t *)(btable_ep[ep_num].rx_addr * 2U + USBD_RAM); + } else if ((uint8_t)EP_BUF_DBL == buf_kind) { + if (USBD_EPxCS(ep_num) & EPxCS_TX_DTG) { + bytes = (uint16_t)(btable_ep[ep_num].tx_count & EPRCNT_CNT); + + read_addr = (uint32_t *)(btable_ep[ep_num].tx_addr * 2U + USBD_RAM); + } else { + bytes = (uint16_t)(btable_ep[ep_num].rx_count & EPRCNT_CNT); + + read_addr = (uint32_t *)(btable_ep[ep_num].rx_addr * 2U + USBD_RAM); + } + } else { + return 0U; + } + + for (n = 0U; n < (bytes + 1U) / 2U; n++) { + *((uint16_t*)user_fifo) = (uint16_t)*read_addr++; + user_fifo += 2U; + } + + return bytes; +} + +#ifdef USBD_LOWPWR_MODE_ENABLE + +/*! + \brief restore system clocks and power while exiting from suspend mode + \param[in] none + \param[out] none + \retval none +*/ +static void lowpower_mode_exit (void) +{ + /* restore system clock */ + +#ifdef LPM_ENABLED + /* enable IRC8M */ + rcu_osci_on(RCU_IRC8M); + + /* wait till IRC8M is ready */ + while (RESET == rcu_flag_get(RCU_FLAG_IRC8MSTB)) { + } +#else + /* enable HXTAL */ + rcu_osci_on(RCU_HXTAL); + + /* wait till HXTAL is ready */ + while(RESET == rcu_flag_get(RCU_FLAG_HXTALSTB)) { + } +#endif + + /* enable PLL */ + rcu_osci_on(RCU_PLL_CK); + + /* wait till PLL is ready */ + while(RESET == rcu_flag_get(RCU_FLAG_PLLSTB)) { + } + + /* select PLL as system clock source */ + rcu_system_clock_source_config(RCU_CKSYSSRC_PLL); + + /* wait till PLL is used as system clock source */ + while(0x08U != rcu_system_clock_source_get()) { + } + + /* low power sleep on exit disabled */ + system_lowpower_reset(SCB_LPM_DEEPSLEEP); + +#ifdef USE_IRC48M + /* enable IRC48M clock */ + rcu_osci_on(RCU_IRC48M); + + /* wait till IRC48M is ready */ + while (SUCCESS != rcu_osci_stab_wait(RCU_IRC48M)) { + } + + rcu_ck48m_clock_config(RCU_CK48MSRC_IRC48M); +#endif +} + +#endif /* USBD_LOWPWR_MODE_ENABLE */ + +/*! + \brief resume the USB device + \param[in] none + \param[out] none + \retval none +*/ +static void usbd_resume (usb_dev *udev) +{ +#ifdef LPM_ENABLED + if(1 == udev->lpm.L1_remote_wakeup){ + USBD_CTL |= CTL_L1RSREQ; + } +#endif /* LPM_ENABLED */ + + if(1U == usbd_core.dev->pm.remote_wakeup){ + /* make USB resume */ + USBD_CTL |= CTL_RSREQ; + } +} + +/*! + \brief set USB device to leave mode + \param[in] none + \param[out] none + \retval none +*/ +static void usbd_leave_suspend (void) +{ + /* clear low_power mode bit in USBD_CTL */ + USBD_CTL &= ~CTL_LOWM; + +#ifdef USBD_LOWPWR_MODE_ENABLE + + /* restore normal operations */ + lowpower_mode_exit(); + +#endif /* USBD_LOWPWR_MODE_ENABLE */ + + /* clear SETSPS bit */ + USBD_CTL &= ~CTL_SETSPS; +} + +/*! + \brief set USB device to enter suspend mode + \param[in] none + \param[out] none + \retval none +*/ +static void usbd_suspend (void) +{ + /* set USB module to suspend and low-power mode */ + USBD_CTL |= CTL_SETSPS | CTL_LOWM; + +#ifdef USBD_LOWPWR_MODE_ENABLE + + /* check wakeup flag is set */ + if (0U == (USBD_INTF & INTF_WKUPIF)) { + /* enter DEEP_SLEEP mode with LDO in low power mode */ + pmu_to_deepsleepmode(PMU_LDO_LOWPOWER, WFI_CMD); + } else { + /* clear wakeup interrupt flag */ + CLR(WKUPIF); + + /* clear set_suspend flag */ + USBD_CTL &= ~CTL_SETSPS; + } + +#endif /* USBD_LOWPWR_MODE_ENABLE */ +} diff --git a/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbd_library/usbd/Source/usbd_lld_int.c b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbd_library/usbd/Source/usbd_lld_int.c new file mode 100644 index 0000000000..c57b282887 --- /dev/null +++ b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbd_library/usbd/Source/usbd_lld_int.c @@ -0,0 +1,276 @@ + /*! + \file usbd_lld_int.c + \brief USB device low level interrupt routines + + \version 2020-08-01, V3.0.0, firmware for GD32F30x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "usbd_lld_int.h" +#include "usbd_lld_core.h" + +/* local function prototypes ('static') */ +static void usbd_int_suspend (usb_dev *udev); + +/*! + \brief handle USB high priority successful transfer event + \param[in] udev: pointer to USB device instance + \param[out] none + \retval none +*/ +void usbd_int_hpst (usb_dev *udev) +{ + __IO uint16_t int_status = 0U; + + /* wait till interrupts are not pending */ + while ((int_status = (uint16_t)USBD_INTF) & (uint16_t)INTF_STIF) { + /* get endpoint number */ + uint8_t ep_num = (uint8_t)(int_status & INTF_EPNUM); + + uint8_t transc_num = (uint8_t)TRANSC_UNKNOWN; + + if (int_status & INTF_DIR) { + if (USBD_EPxCS(ep_num) & EPxCS_RX_ST) { + uint16_t count = 0U; + + usb_transc *transc = &udev->transc_out[ep_num]; + + /* clear successful receive interrupt flag */ + USBD_EP_RX_ST_CLEAR(ep_num); + + count = udev->drv_handler->ep_read (transc->xfer_buf, ep_num, (uint8_t)EP_BUF_DBL); + + user_buffer_free(ep_num, (uint8_t)DBUF_EP_OUT); + + transc->xfer_buf += count; + transc->xfer_count += count; + transc->xfer_len -= count; + + if ((0U == transc->xfer_len) || (count < transc->max_len)) { + USBD_EP_RX_STAT_SET(ep_num, EPRX_NAK); + + transc_num = (uint8_t)TRANSC_OUT; + } + } + } else { + /* handle the in direction transaction */ + if (USBD_EPxCS(ep_num) & EPxCS_TX_ST) { + /* clear successful transmit interrupt flag */ + USBD_EP_TX_ST_CLEAR(ep_num); + + transc_num = (uint8_t)TRANSC_IN; + } + } + + if ((uint8_t)TRANSC_UNKNOWN != transc_num) { + udev->ep_transc[ep_num][transc_num](udev, ep_num); + } + } +} + +/*! + \brief USB interrupt events service routine + \param[in] none + \param[out] none + \retval none +*/ +void usbd_isr (void) +{ + __IO uint16_t int_status = (uint16_t)USBD_INTF; + __IO uint16_t int_flag = (uint16_t)(USBD_INTF & (USBD_CTL & USBD_INTEN)); + + usb_dev *udev = usbd_core.dev; + + if (INTF_STIF & int_flag) { + /* wait till interrupts are not pending */ + while ((int_status = (uint16_t)USBD_INTF) & (uint16_t)INTF_STIF) { + /* get endpoint number */ + uint8_t ep_num = (uint8_t)(int_status & INTF_EPNUM); + + if (int_status & INTF_DIR) { + /* handle the USB OUT direction transaction */ + if (USBD_EPxCS(ep_num) & EPxCS_RX_ST) { + /* clear successful receive interrupt flag */ + USBD_EP_RX_ST_CLEAR(ep_num); + + if (USBD_EPxCS(ep_num) & EPxCS_SETUP) { + + if (ep_num == 0U) { + udev->ep_transc[ep_num][TRANSC_SETUP](udev, ep_num); + } else { + return; + } + } else { + usb_transc *transc = &udev->transc_out[ep_num]; + + uint16_t count = udev->drv_handler->ep_read (transc->xfer_buf, ep_num, (uint8_t)EP_BUF_SNG); + + transc->xfer_buf += count; + transc->xfer_count += count; + + if ((transc->xfer_count >= transc->xfer_len) || (count < transc->max_len)) { + if (udev->ep_transc[ep_num][TRANSC_OUT]) { + udev->ep_transc[ep_num][TRANSC_OUT](udev, ep_num); + } + } else { + udev->drv_handler->ep_rx_enable(udev, ep_num); + } + } + } + } else { + /* handle the USB IN direction transaction */ + if (USBD_EPxCS(ep_num) & EPxCS_TX_ST) { + /* clear successful transmit interrupt flag */ + USBD_EP_TX_ST_CLEAR(ep_num); + + usb_transc *transc = &udev->transc_in[ep_num]; + + if (transc->xfer_len == 0U) { + if (udev->ep_transc[ep_num][TRANSC_IN]) { + udev->ep_transc[ep_num][TRANSC_IN](udev, ep_num); + } + } else { + usbd_ep_send(udev, ep_num, transc->xfer_buf, transc->xfer_len); + } + } + } + } + } + + if (INTF_WKUPIF & int_flag) { + /* clear wakeup interrupt flag in INTF */ + CLR(WKUPIF); + + /* restore the old cur_status */ + udev->cur_status = udev->backup_status; + +#ifdef LPM_ENABLED + if ((0U == udev->pm.remote_wakeup_on) && (0U == udev->lpm.L1_resume)) { + resume_mcu(udev); + } else if (1U == udev->pm.remote_wakeup_on) { + /* no operation */ + } else { + udev->lpm.L1_resume = 0U; + } + + /* clear L1 remote wakeup flag */ + udev->lpm.L1_remote_wakeup = 0U; +#else + if (0U == udev->pm.remote_wakeup_on) { + resume_mcu(udev); + } +#endif /* LPM_ENABLED */ + } + + if (INTF_SPSIF & int_flag) { + if(!(USBD_CTL & CTL_RSREQ)) { + usbd_int_suspend (udev); + + /* clear of suspend interrupt flag bit must be done after setting of CTLR_SETSPS */ + CLR(SPSIF); + } + } + + if (INTF_SOFIF & int_flag) { + /* clear SOF interrupt flag in INTF */ + CLR(SOFIF); + + /* if necessary, user can add code here */ + if (NULL != usbd_int_fops) { + (void)usbd_int_fops->SOF(udev); + } + } + + if (INTF_ESOFIF & int_flag) { + /* clear ESOF interrupt flag in INTF */ + CLR(ESOFIF); + + /* control resume time by ESOFs */ + if (udev->pm.esof_count > 0U) { + if (0U == --udev->pm.esof_count) { + if (udev->pm.remote_wakeup_on) { + USBD_CTL &= ~CTL_RSREQ; + + udev->pm.remote_wakeup_on = 0U; + } else { + USBD_CTL |= CTL_RSREQ; + + udev->pm.esof_count = 3U; + udev->pm.remote_wakeup_on = 1U; + } + } + } + } + + if (INTF_RSTIF & int_flag) { + /* clear reset interrupt flag in INTF */ + CLR(RSTIF); + + udev->drv_handler->ep_reset(udev); + } + +#ifdef LPM_ENABLED + if (INTF_L1REQ & int_flag) { + /* clear L1 ST bit in LPM INTF */ + USBD_INTF = CLR(L1REQ); + + /* read BESL field from subendpoint0 register which corresponds to HIRD parameter in LPM spec */ + udev->lpm.besl = (USBD_LPMCS & LPMCS_BLSTAT) >> 4; + + /* read BREMOTEWAKE bit from subendpoint0 register which corresponding to bRemoteWake bit in LPM request */ + udev->lpm.L1_remote_wakeup = (USBD_LPMCS & LPMCS_REMWK) >> 3; + + /* process USB device core layer suspend routine */ + usbd_int_suspend(udev); + } +#endif /* LPM_ENABLED */ +} + +/*! + \brief handle USB suspend event + \param[in] udev: pointer to USB device instance + \param[out] none + \retval none +*/ +static void usbd_int_suspend (usb_dev *udev) +{ + /* store the device current status */ + udev->backup_status = udev->cur_status; + + /* set device in suspended state */ + udev->cur_status = (uint8_t)USBD_SUSPENDED; + + /* usb enter in suspend mode and mcu system in low power mode */ + if (udev->pm.suspend_enabled) { + usbd_to_suspend(udev); + } else { + /* if not possible then resume after xx ms */ + udev->pm.esof_count = 3U; + } +} diff --git a/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/device/class/audio/Include/audio_core.h b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/device/class/audio/Include/audio_core.h new file mode 100644 index 0000000000..51d0c0091b --- /dev/null +++ b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/device/class/audio/Include/audio_core.h @@ -0,0 +1,300 @@ +/*! + \file audio_core.h + \brief the header file of USB audio device class core functions + + \version 2020-08-01, V3.0.0, firmware for GD32F30x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef __AUDIO_CORE_H +#define __AUDIO_CORE_H + +#include "usbd_enum.h" + +#define FORMAT_24BIT(x) (uint8_t)(x);(uint8_t)(x >> 8U);(uint8_t)(x >> 16U) + +/* number of sub-packets in the audio transfer buffer. you can modify this value but always make sure + that it is an even number and higher than 3 */ +#define OUT_PACKET_NUM 4U + +/* total size of the audio transfer buffer */ +#define OUT_BUF_MARGIN 4U +#define TOTAL_OUT_BUF_SIZE ((uint32_t)((SPEAKER_OUT_PACKET + OUT_BUF_MARGIN) * OUT_PACKET_NUM)) + +#define AUDIO_CONFIG_DESC_SET_LEN (sizeof(usb_desc_config_set)) +#define AUDIO_INTERFACE_DESC_SIZE 9U + +#define USB_AUDIO_DESC_SIZ 0x09U +#define AUDIO_STANDARD_EP_DESC_SIZE 0x09U +#define AUDIO_STREAMING_EP_DESC_SIZE 0x07U + +/* audio interface class code */ +#define USB_CLASS_AUDIO 0x01U + +/* audio interface subclass codes */ +#define AUDIO_SUBCLASS_CONTROL 0x01U +#define AUDIO_SUBCLASS_AUDIOSTREAMING 0x02U +#define AUDIO_SUBCLASS_MIDISTREAMING 0x03U + +/* audio interface protocol codes */ +#define AUDIO_PROTOCOL_UNDEFINED 0x00U +#define AUDIO_STREAMING_GENERAL 0x01U +#define AUDIO_STREAMING_FORMAT_TYPE 0x02U + +/* audio class-specific descriptor types */ +#define AUDIO_DESCTYPE_UNDEFINED 0x20U +#define AUDIO_DESCTYPE_DEVICE 0x21U +#define AUDIO_DESCTYPE_CONFIGURATION 0x22U +#define AUDIO_DESCTYPE_STRING 0x23U +#define AUDIO_DESCTYPE_INTERFACE 0x24U +#define AUDIO_DESCTYPE_ENDPOINT 0x25U + +/* audio control interface descriptor subtypes */ +#define AUDIO_CONTROL_HEADER 0x01U +#define AUDIO_CONTROL_INPUT_TERMINAL 0x02U +#define AUDIO_CONTROL_OUTPUT_TERMINAL 0x03U +#define AUDIO_CONTROL_MIXER_UNIT 0x04U +#define AUDIO_CONTROL_SELECTOR_UNIT 0x05U +#define AUDIO_CONTROL_FEATURE_UNIT 0x06U +#define AUDIO_CONTROL_PROCESSING_UNIT 0x07U +#define AUDIO_CONTROL_EXTENSION_UNIT 0x08U + +#define AUDIO_INPUT_TERMINAL_DESC_SIZE 0x0CU +#define AUDIO_OUTPUT_TERMINAL_DESC_SIZE 0x09U +#define AUDIO_STREAMING_INTERFACE_DESC_SIZE 0x07U + +#define AUDIO_CONTROL_MUTE 0x01U +#define AUDIO_CONTROL_VOLUME 0x02U + +#define AUDIO_FORMAT_TYPE_I 0x01U +#define AUDIO_FORMAT_TYPE_III 0x03U + +#define USB_ENDPOINT_TYPE_ISOCHRONOUS 0x01U +#define AUDIO_ENDPOINT_GENERAL 0x01U + +#define AUDIO_REQ_UNDEFINED 0x00U +#define AUDIO_REQ_SET_CUR 0x01U +#define AUDIO_REQ_GET_CUR 0x81U +#define AUDIO_REQ_SET_MIN 0x02U +#define AUDIO_REQ_GET_MIN 0x82U +#define AUDIO_REQ_SET_MAX 0x03U +#define AUDIO_REQ_GET_MAX 0x83U +#define AUDIO_REQ_SET_RES 0x04U +#define AUDIO_REQ_GET_RES 0x84U +#define AUDIO_REQ_SET_MEM 0x05U +#define AUDIO_REQ_GET_MEM 0x85U +#define AUDIO_REQ_GET_STAT 0xFFU + +#define AUDIO_OUT_STREAMING_CTRL 0x05U +#define AUDIO_IN_STREAMING_CTRL 0x02U + +/* audio stream interface number */ +enum +{ +#ifdef USE_USB_AUDIO_MICPHONE + MIC_INTERFACE_COUNT, +#endif +#ifdef USE_USB_AUDIO_SPEAKER + SPEAK_INTERFACE_COUNT, +#endif + CONFIG_DESC_AS_ITF_COUNT, +}; + +#define AC_ITF_TOTAL_LEN (sizeof(usb_desc_AC_itf) + CONFIG_DESC_AS_ITF_COUNT*(sizeof(usb_desc_input_terminal) + \ + sizeof(usb_desc_mono_feature_unit) + sizeof(usb_desc_output_terminal))) + +#pragma pack(1) + +typedef struct +{ + usb_desc_header header; /*!< descriptor header, including type and size */ + uint8_t bDescriptorSubtype; /*!< header descriptor subtype */ + uint16_t bcdADC; /*!< audio device class specification release number in binary-coded decimal */ + uint16_t wTotalLength; /*!< total number of bytes */ + uint8_t bInCollection; /*!< the number of the streaming interfaces */ +#ifdef USE_USB_AUDIO_MICPHONE + uint8_t baInterfaceNr0; /*!< interface number of the streaming interfaces */ +#endif + +#ifdef USE_USB_AUDIO_SPEAKER + uint8_t baInterfaceNr1; /*!< interface number of the streaming interfaces */ +#endif +} usb_desc_AC_itf; + +typedef struct +{ + usb_desc_header header; /*!< descriptor header, including type and size */ + uint8_t bDescriptorSubtype; /*!< AS_GENERAL descriptor subtype */ + uint8_t bTerminalLink; /*!< the terminal ID */ + uint8_t bDelay; /*!< delay introduced by the data path */ + uint16_t wFormatTag; /*!< the audio data format */ +} usb_desc_AS_itf; + +typedef struct +{ + usb_desc_header header; /*!< descriptor header, including type and size */ + uint8_t bDescriptorSubtype; /*!< INPUT_TERMINAL descriptor subtype. */ + uint8_t bTerminalID; /*!< constant uniquely identifying the terminal within the audio function */ + uint16_t wTerminalType; /*!< constant characterizing the type of terminal */ + uint8_t bAssocTerminal; /*!< ID of the output terminal */ + uint8_t bNrChannels; /*!< number of logical output channels */ + uint16_t wChannelConfig; /*!< describes the spatial location of the logical channels */ + uint8_t iChannelNames; /*!< index of a string descriptor */ + uint8_t iTerminal; /*!< index of a string descriptor */ +} usb_desc_input_terminal; + +typedef struct +{ + usb_desc_header header; /*!< descriptor header, including type and size */ + uint8_t bDescriptorSubtype; /*!< OUTPUT_TERMINAL descriptor subtype */ + uint8_t bTerminalID; /*!< constant uniquely identifying the terminal within the audio function */ + uint16_t wTerminalType; /*!< constant characterizing the type of terminal */ + uint8_t bAssocTerminal; /*!< constant, identifying the input terminal to which this output terminal is associated */ + uint8_t bSourceID; /*!< ID of the unit or terminal */ + uint8_t iTerminal; /*!< index of a string descriptor */ +} usb_desc_output_terminal; + +typedef struct +{ + usb_desc_header header; /*!< descriptor header, including type and size */ + uint8_t bDescriptorSubtype; /*!< FEATURE_UNIT descriptor subtype */ + uint8_t bUnitID; /*!< constant uniquely identifying the unit within the audio function */ + uint8_t bSourceID; /*!< ID of the unit or terminal */ + uint8_t bControlSize; /*!< size in bytes of an element of the bmaControls() array */ + uint8_t bmaControls0; /*!< a bit set to 1 indicates that the mentioned control is supported for master channel 0 */ + uint8_t bmaControls1; /*!< a bit set to 1 indicates that the mentioned control is supported for logical channel 1 */ + uint8_t iFeature; /*!< index of a string descriptor */ +} usb_desc_mono_feature_unit; + +typedef struct +{ + usb_desc_header header; /*!< descriptor header, including type and size */ + uint8_t bDescriptorSubtype; /*!< FEATURE_UNIT descriptor subtype */ + uint8_t bUnitID; /*!< constant uniquely identifying the unit within the audio function */ + uint8_t bSourceID; /*!< ID of the unit or terminal */ + uint8_t bControlSize; /*!< size in bytes of an element of the bmaControls() array */ + uint16_t bmaControls0; /*!< a bit set to 1 indicates that the mentioned control is supported for master channel 0 */ + uint16_t bmaControls1; /*!< a bit set to 1 indicates that the mentioned control is supported for logical channel 1 */ + uint16_t bmaControls2; /*!< a bit set to 1 indicates that the mentioned control is supported for logical channel 2 */ + uint8_t iFeature; /*!< index of a string descriptor */ +} usb_desc_stereo_feature_unit; + +typedef struct +{ + usb_desc_header header; /*!< descriptor header, including type and size */ + uint8_t bDescriptorSubtype; /*!< FORMAT_TYPE descriptor subtype */ + uint8_t bFormatType; /*!< constant identifying the format type */ + uint8_t bNrChannels; /*!< indicates the number of physical channels in the audio data stream */ + uint8_t bSubFrameSize; /*!< the number of bytes occupied by one audio subframe */ + uint8_t bBitResolution; /*!< the number of effectively used bits from the available bits in an audio subframe */ + uint8_t bSamFreqType; /*!< indicates how the sampling frequency can be programmed */ + uint8_t bSamFreq[3]; /*!< sampling frequency ns in Hz for this isochronous data endpoint */ +} usb_desc_format_type; + +typedef struct +{ + usb_desc_header header; /*!< descriptor header, including type and size */ + uint8_t bEndpointAddress; /*!< the address of the endpoint */ + uint8_t bmAttributes; /*!< transfer type and synchronization type */ + uint16_t wMaxPacketSize; /*!< maximum packet size this endpoint is capable of sending or receiving */ + uint8_t bInterval; /*!< left to the designer's discretion */ + uint8_t bRefresh; /*!< reset to 0 */ + uint8_t bSynchAddress; /*!< reset to 0 */ +} usb_desc_std_ep; + +typedef struct +{ + usb_desc_header header; /*!< descriptor header, including type and size */ + uint8_t bDescriptorSubtype; /*!< EP_GENERAL descriptor subtype */ + uint8_t bmAttributes; /*!< transfer type and synchronization type */ + uint8_t bLockDelayUnits; /*!< indicates the units used for the wLockDelay field */ + uint16_t wLockDelay; /*!< indicates the time it takes this endpoint to reliably lock its internal clock recovery circuitry */ +} usb_desc_AS_ep; + +#pragma pack() + +/* USB configuration descriptor structure */ +typedef struct +{ + usb_desc_config config; + usb_desc_itf std_itf; + usb_desc_AC_itf ac_itf; + +#ifdef USE_USB_AUDIO_MICPHONE + usb_desc_input_terminal mic_in_terminal; + usb_desc_mono_feature_unit mic_feature_unit; + usb_desc_output_terminal mic_out_terminal; +#endif + +#ifdef USE_USB_AUDIO_SPEAKER + usb_desc_input_terminal speak_in_terminal; + usb_desc_mono_feature_unit speak_feature_unit; + usb_desc_output_terminal speak_out_terminal; +#endif + +#ifdef USE_USB_AUDIO_MICPHONE + usb_desc_itf mic_std_as_itf_zeroband; + usb_desc_itf mic_std_as_itf_opera; + usb_desc_AS_itf mic_as_itf; + usb_desc_format_type mic_format_typeI; + usb_desc_std_ep mic_std_endpoint; + usb_desc_AS_ep mic_as_endpoint; +#endif + +#ifdef USE_USB_AUDIO_SPEAKER + usb_desc_itf speak_std_as_itf_zeroband; + usb_desc_itf speak_std_as_itf_opera; + usb_desc_AS_itf speak_as_itf; + usb_desc_format_type speak_format_typeI; + usb_desc_std_ep speak_std_endpoint; + usb_desc_AS_ep speak_as_endpoint; +#endif +} usb_desc_config_set; + +typedef struct +{ + /* main buffer for audio data out transfers and its relative pointers */ + uint8_t isoc_out_buff[TOTAL_OUT_BUF_SIZE * 2U]; + uint8_t* isoc_out_wrptr; + uint8_t* isoc_out_rdptr; + + /* main buffer for audio control requests transfers and its relative variables */ + uint8_t audioctl[64]; + uint8_t audioctl_unit; + uint32_t audioctl_len; + +#ifdef USE_USB_AUDIO_SPEAKER + uint32_t play_flag; +#endif /* USE_USB_AUDIO_SPEAKER */ +} usbd_audio_handler; + +extern usb_desc audio_desc; +extern usb_class_core usbd_audio_cb; + +#endif /* __AUDIO_CORE_H */ diff --git a/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/device/class/audio/Include/audio_out_itf.h b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/device/class/audio/Include/audio_out_itf.h new file mode 100644 index 0000000000..30d5fd6893 --- /dev/null +++ b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/device/class/audio/Include/audio_out_itf.h @@ -0,0 +1,76 @@ +/*! + \file audio_out_itf.h + \brief audio OUT (playback) interface header file + + \version 2020-08-01, V3.0.0, firmware for GD32F30x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef __AUDIO_OUT_ITF_H +#define __AUDIO_OUT_ITF_H + +#include "usbd_conf.h" + +/* audio commands enumeration */ +typedef enum +{ + AUDIO_CMD_PLAY = 1U, + AUDIO_CMD_PAUSE, + AUDIO_CMD_STOP, +}audio_cmd_enum; + +/* mute commands */ +#define AUDIO_MUTE 0x01U +#define AUDIO_UNMUTE 0x00U + +/* functions return value */ +#define AUDIO_OK 0x00U +#define AUDIO_FAIL 0xFFU + +/* audio machine states */ +#define AUDIO_STATE_INACTIVE 0x00U +#define AUDIO_STATE_ACTIVE 0x01U +#define AUDIO_STATE_PLAYING 0x02U +#define AUDIO_STATE_PAUSED 0x03U +#define AUDIO_STATE_STOPPED 0x04U +#define AUDIO_STATE_ERROR 0x05U + +typedef struct { + uint8_t (*audio_init) (uint32_t audio_freq, uint32_t volume, uint32_t options); + uint8_t (*audio_deinit) (uint32_t options); + uint8_t (*audio_cmd) (uint8_t* pbuf, uint32_t size, uint8_t cmd); + uint8_t (*audio_volume_ctl) (uint8_t vol); + uint8_t (*audio_mute_ctl) (uint8_t cmd); + uint8_t (*audio_periodic_tc) (uint8_t cmd); + uint8_t (*audio_state_get) (void); +} audio_fops_struct; + +extern audio_fops_struct audio_out_fops; + +#endif /* __AUDIO_OUT_ITF_H */ diff --git a/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/device/class/audio/Source/audio_core.c b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/device/class/audio/Source/audio_core.c new file mode 100644 index 0000000000..b965c38218 --- /dev/null +++ b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/device/class/audio/Source/audio_core.c @@ -0,0 +1,809 @@ +/*! + \file audio_core.c + \brief USB audio device class core functions + + \version 2020-08-01, V3.0.0, firmware for GD32F30x + \version 2020-12-07, V3.0.1, firmware for GD32F30x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "audio_out_itf.h" +#include "audio_core.h" +#include + +#define USBD_VID 0x28E9U +#define USBD_PID 0x9574U + +#ifdef USE_USB_AUDIO_MICPHONE +extern volatile uint32_t count_data; +extern const char wavetestdata[]; +#define LENGTH_DATA (1747 * 32) +#endif + +/* local function prototypes ('static') */ +static uint8_t audio_init (usb_dev *udev, uint8_t config_index); +static uint8_t audio_deinit (usb_dev *udev, uint8_t config_index); +static uint8_t audio_req_handler (usb_dev *udev, usb_req *req); +static uint8_t audio_set_intf (usb_dev *udev, usb_req *req); +static uint8_t audio_ctlx_out (usb_dev *udev); +static uint8_t audio_data_in (usb_dev *udev, uint8_t ep_num); +static uint8_t audio_data_out (usb_dev *udev, uint8_t ep_num); +static uint8_t usbd_audio_sof (usb_dev *udev); + +usb_class_core usbd_audio_cb = { + .init = audio_init, + .deinit = audio_deinit, + .req_proc = audio_req_handler, + .set_intf = audio_set_intf, + .ctlx_out = audio_ctlx_out, + .data_in = audio_data_in, + .data_out = audio_data_out, + .SOF = usbd_audio_sof +}; + +#define VOL_MIN 0U /* Volume Minimum Value */ +#define VOL_MAX 100U /* Volume Maximum Value */ +#define VOL_RES 1U /* Volume Resolution */ +#define VOL_0dB 70U /* 0dB is in the middle of VOL_MIN and VOL_MAX */ + +/* note:it should use the c99 standard when compiling the below codes */ +/* USB standard device descriptor */ +const usb_desc_dev audio_dev_desc = +{ + .header = + { + .bLength = USB_DEV_DESC_LEN, + .bDescriptorType = USB_DESCTYPE_DEV + }, + .bcdUSB = 0x0200U, + .bDeviceClass = 0x00U, + .bDeviceSubClass = 0x00U, + .bDeviceProtocol = 0x00U, + .bMaxPacketSize0 = USB_FS_EP0_MAX_LEN, + .idVendor = USBD_VID, + .idProduct = USBD_PID, + .bcdDevice = 0x0100U, + .iManufacturer = STR_IDX_MFC, + .iProduct = STR_IDX_PRODUCT, + .iSerialNumber = STR_IDX_SERIAL, + .bNumberConfigurations = USBD_CFG_MAX_NUM +}; + +/* USB device configuration descriptor */ +const usb_desc_config_set audio_config_set = +{ + .config = + { + .header = + { + .bLength = sizeof(usb_desc_config), + .bDescriptorType = USB_DESCTYPE_CONFIG + }, + .wTotalLength = AUDIO_CONFIG_DESC_SET_LEN, + .bNumInterfaces = 0x01U + CONFIG_DESC_AS_ITF_COUNT, + .bConfigurationValue = 0x01U, + .iConfiguration = 0x00U, + .bmAttributes = 0xC0U, + .bMaxPower = 0x32U + }, + + .std_itf = + { + .header = + { + .bLength = sizeof(usb_desc_itf), + .bDescriptorType = USB_DESCTYPE_ITF + }, + .bInterfaceNumber = 0x00U, + .bAlternateSetting = 0x00U, + .bNumEndpoints = 0x00U, + .bInterfaceClass = USB_CLASS_AUDIO, + .bInterfaceSubClass = AUDIO_SUBCLASS_CONTROL, + .bInterfaceProtocol = AUDIO_PROTOCOL_UNDEFINED, + .iInterface = 0x00U + }, + + .ac_itf = + { + .header = + { + .bLength = sizeof(usb_desc_AC_itf), + .bDescriptorType = AUDIO_DESCTYPE_INTERFACE + }, + .bDescriptorSubtype = 0x01U, + .bcdADC = 0x0100U, + .wTotalLength = AC_ITF_TOTAL_LEN, + .bInCollection = CONFIG_DESC_AS_ITF_COUNT, +#ifdef USE_USB_AUDIO_MICPHONE + .baInterfaceNr0 = 0x01U, +#endif +#ifdef USE_USB_AUDIO_SPEAKER + .baInterfaceNr1 = 0x02U +#endif + }, + +#ifdef USE_USB_AUDIO_MICPHONE + .mic_in_terminal = + { + .header = + { + .bLength = sizeof(usb_desc_input_terminal), + .bDescriptorType = AUDIO_DESCTYPE_INTERFACE + }, + .bDescriptorSubtype = 0x02U, + .bTerminalID = 0x01U, + .wTerminalType = 0x0201U, + .bAssocTerminal = 0x00U, + .bNrChannels = 0x02U, + .wChannelConfig = 0x0003U, + .iChannelNames = 0x00U, + .iTerminal = 0x00U + }, + + .mic_feature_unit = + { + .header = + { + .bLength = sizeof(usb_desc_mono_feature_unit), + .bDescriptorType = AUDIO_DESCTYPE_INTERFACE + }, + .bDescriptorSubtype = AUDIO_CONTROL_FEATURE_UNIT, + .bUnitID = AUDIO_IN_STREAMING_CTRL, + .bSourceID = 0x01U, + .bControlSize = 0x01U, + .bmaControls0 = AUDIO_CONTROL_MUTE, + .bmaControls1 = AUDIO_CONTROL_VOLUME, + .iFeature = 0x00U + }, + + .mic_out_terminal = + { + .header = + { + .bLength = sizeof(usb_desc_output_terminal), + .bDescriptorType = AUDIO_DESCTYPE_INTERFACE + }, + .bDescriptorSubtype = AUDIO_CONTROL_OUTPUT_TERMINAL, + .bTerminalID = 0x03U, + .wTerminalType = 0x0101U, + .bAssocTerminal = 0x00U, + .bSourceID = 0x02U, + .iTerminal = 0x00U + }, +#endif + +#ifdef USE_USB_AUDIO_SPEAKER + .speak_in_terminal = + { + .header = + { + .bLength = sizeof(usb_desc_input_terminal), + .bDescriptorType = AUDIO_DESCTYPE_INTERFACE + }, + .bDescriptorSubtype = AUDIO_CONTROL_INPUT_TERMINAL, + .bTerminalID = 0x04U, + .wTerminalType = 0x0101U, + .bAssocTerminal = 0x00U, + .bNrChannels = 0x02U, + .wChannelConfig = 0x0003U, + .iChannelNames = 0x00U, + .iTerminal = 0x00U + }, + + .speak_feature_unit = + { + .header = + { + .bLength = sizeof(usb_desc_mono_feature_unit), + .bDescriptorType = AUDIO_DESCTYPE_INTERFACE + }, + .bDescriptorSubtype = AUDIO_CONTROL_FEATURE_UNIT, + .bUnitID = AUDIO_OUT_STREAMING_CTRL, + .bSourceID = 0x04U, + .bControlSize = 0x01U, + .bmaControls0 = AUDIO_CONTROL_MUTE, + .bmaControls1 = AUDIO_CONTROL_VOLUME, + .iFeature = 0x00U + }, + + .speak_out_terminal = + { + .header = + { + .bLength = sizeof(usb_desc_output_terminal), + .bDescriptorType = AUDIO_DESCTYPE_INTERFACE + }, + .bDescriptorSubtype = AUDIO_CONTROL_OUTPUT_TERMINAL, + .bTerminalID = 0x06U, + .wTerminalType = 0x0301U, + .bAssocTerminal = 0x00U, + .bSourceID = 0x05U, + .iTerminal = 0x00U + }, +#endif + +#ifdef USE_USB_AUDIO_MICPHONE + .mic_std_as_itf_zeroband = + { + .header = + { + .bLength = sizeof(usb_desc_itf), + .bDescriptorType = USB_DESCTYPE_ITF + }, + .bInterfaceNumber = 0x01U, + .bAlternateSetting = 0x00U, + .bNumEndpoints = 0x00U, + .bInterfaceClass = USB_CLASS_AUDIO, + .bInterfaceSubClass = AUDIO_SUBCLASS_AUDIOSTREAMING, + .bInterfaceProtocol = AUDIO_PROTOCOL_UNDEFINED, + .iInterface = 0x00U + }, + + .mic_std_as_itf_opera = + { + .header = + { + .bLength = sizeof(usb_desc_itf), + .bDescriptorType = USB_DESCTYPE_ITF + }, + .bInterfaceNumber = 0x01U, + .bAlternateSetting = 0x01U, + .bNumEndpoints = 0x01U, + .bInterfaceClass = USB_CLASS_AUDIO, + .bInterfaceSubClass = AUDIO_SUBCLASS_AUDIOSTREAMING, + .bInterfaceProtocol = AUDIO_PROTOCOL_UNDEFINED, + .iInterface = 0x00U + }, + + .mic_as_itf = + { + .header = + { + .bLength = sizeof(usb_desc_AS_itf), + .bDescriptorType = AUDIO_DESCTYPE_INTERFACE + }, + .bDescriptorSubtype = AUDIO_STREAMING_GENERAL, + .bTerminalLink = 0x03U, + .bDelay = 0x01U, + .wFormatTag = 0x0001U, + }, + + .mic_format_typeI = + { + .header = + { + .bLength = sizeof(usb_desc_format_type), + .bDescriptorType = AUDIO_DESCTYPE_INTERFACE + }, + .bDescriptorSubtype = AUDIO_STREAMING_FORMAT_TYPE, + .bFormatType = AUDIO_FORMAT_TYPE_I, + .bNrChannels = MIC_IN_CHANNEL_NBR, + .bSubFrameSize = 0x02U, + .bBitResolution = MIC_IN_BIT_RESOLUTION, + .bSamFreqType = 0x01U, + .bSamFreq[0] = (uint8_t)USBD_MIC_FREQ, + .bSamFreq[1] = USBD_MIC_FREQ >> 8U, + .bSamFreq[2] = USBD_MIC_FREQ >> 16U + }, + + .mic_std_endpoint = + { + .header = + { + .bLength = sizeof(usb_desc_std_ep), + .bDescriptorType = USB_DESCTYPE_EP + }, + .bEndpointAddress = AUDIO_IN_EP, + .bmAttributes = USB_ENDPOINT_TYPE_ISOCHRONOUS, + .wMaxPacketSize = MIC_IN_PACKET, + .bInterval = 0x01U, + .bRefresh = 0x00U, + .bSynchAddress = 0x00U + }, + + .mic_as_endpoint = + { + .header = + { + .bLength = sizeof(usb_desc_AS_ep), + .bDescriptorType = AUDIO_DESCTYPE_ENDPOINT + }, + .bDescriptorSubtype = AUDIO_ENDPOINT_GENERAL, + .bmAttributes = 0x00U, + .bLockDelayUnits = 0x00U, + .wLockDelay = 0x0000U, + }, +#endif + +#ifdef USE_USB_AUDIO_SPEAKER + .speak_std_as_itf_zeroband = + { + .header = + { + .bLength = sizeof(usb_desc_itf), + .bDescriptorType = USB_DESCTYPE_ITF + }, + .bInterfaceNumber = 0x02U, + .bAlternateSetting = 0x00U, + .bNumEndpoints = 0x00U, + .bInterfaceClass = USB_CLASS_AUDIO, + .bInterfaceSubClass = AUDIO_SUBCLASS_AUDIOSTREAMING, + .bInterfaceProtocol = AUDIO_PROTOCOL_UNDEFINED, + .iInterface = 0x00U + }, + + .speak_std_as_itf_opera = + { + .header = + { + .bLength = sizeof(usb_desc_itf), + .bDescriptorType = USB_DESCTYPE_ITF + }, + .bInterfaceNumber = 0x02U, + .bAlternateSetting = 0x01U, + .bNumEndpoints = 0x01U, + .bInterfaceClass = USB_CLASS_AUDIO, + .bInterfaceSubClass = AUDIO_SUBCLASS_AUDIOSTREAMING, + .bInterfaceProtocol = AUDIO_PROTOCOL_UNDEFINED, + .iInterface = 0x00U + }, + + .speak_as_itf = + { + .header = + { + .bLength = sizeof(usb_desc_AS_itf), + .bDescriptorType = AUDIO_DESCTYPE_INTERFACE + }, + .bDescriptorSubtype = AUDIO_STREAMING_GENERAL, + .bTerminalLink = 0x04U, + .bDelay = 0x01U, + .wFormatTag = 0x0001U, + }, + + .speak_format_typeI = + { + .header = + { + .bLength = sizeof(usb_desc_format_type), + .bDescriptorType = AUDIO_DESCTYPE_INTERFACE + }, + .bDescriptorSubtype = AUDIO_STREAMING_FORMAT_TYPE, + .bFormatType = AUDIO_FORMAT_TYPE_I, + .bNrChannels = SPEAKER_OUT_CHANNEL_NBR, + .bSubFrameSize = 0x02U, + .bBitResolution = SPEAKER_OUT_BIT_RESOLUTION, + .bSamFreqType = 0x01U, + .bSamFreq[0] = (uint8_t)USBD_SPEAKER_FREQ, + .bSamFreq[1] = USBD_SPEAKER_FREQ >> 8U, + .bSamFreq[2] = USBD_SPEAKER_FREQ >> 16U + }, + + .speak_std_endpoint = + { + .header = + { + .bLength = sizeof(usb_desc_std_ep), + .bDescriptorType = USB_DESCTYPE_EP + }, + .bEndpointAddress = AUDIO_OUT_EP, + .bmAttributes = USB_ENDPOINT_TYPE_ISOCHRONOUS, + .wMaxPacketSize = SPEAKER_OUT_PACKET, + .bInterval = 0x01U, + .bRefresh = 0x00U, + .bSynchAddress = 0x00U + }, + + .speak_as_endpoint = + { + .header = + { + .bLength = sizeof(usb_desc_AS_ep), + .bDescriptorType = AUDIO_DESCTYPE_ENDPOINT + }, + .bDescriptorSubtype = AUDIO_ENDPOINT_GENERAL, + .bmAttributes = 0x00U, + .bLockDelayUnits = 0x00U, + .wLockDelay = 0x0000U, + } +#endif +}; + +/* USB language ID descriptor */ +static const usb_desc_LANGID usbd_language_id_desc = +{ + .header = + { + .bLength = sizeof(usb_desc_LANGID), + .bDescriptorType = USB_DESCTYPE_STR + }, + + .wLANGID = ENG_LANGID +}; + +/* USB manufacture string */ +static const usb_desc_str manufacturer_string = +{ + .header = + { + .bLength = USB_STRING_LEN(10), + .bDescriptorType = USB_DESCTYPE_STR, + }, + .unicode_string = {'G', 'i', 'g', 'a', 'D', 'e', 'v', 'i', 'c', 'e'} +}; + +/* USB product string */ +static const usb_desc_str product_string = +{ + .header = + { + .bLength = USB_STRING_LEN(14), + .bDescriptorType = USB_DESCTYPE_STR, + }, + .unicode_string = {'G', 'D', '3', '2', '-', 'U', 'S', 'B', '_', 'A', 'u', 'd', 'i', 'o'} +}; + +/* USBD serial string */ +static usb_desc_str serial_string = +{ + .header = + { + .bLength = USB_STRING_LEN(12), + .bDescriptorType = USB_DESCTYPE_STR, + } +}; + +/* USB string descriptor */ +void *const usbd_audio_strings[] = +{ + [STR_IDX_LANGID] = (uint8_t *)&usbd_language_id_desc, + [STR_IDX_MFC] = (uint8_t *)&manufacturer_string, + [STR_IDX_PRODUCT] = (uint8_t *)&product_string, + [STR_IDX_SERIAL] = (uint8_t *)&serial_string +}; + +usb_desc audio_desc = { + .dev_desc = (uint8_t *)&audio_dev_desc, + .config_desc = (uint8_t *)&audio_config_set, + .strings = usbd_audio_strings +}; + +/*! + \brief initialize the AUDIO device + \param[in] udev: pointer to USB device instance + \param[in] config_index: configuration index + \param[out] none + \retval USB device operation status +*/ +static uint8_t audio_init (usb_dev *udev, uint8_t config_index) +{ + static usbd_audio_handler audio_handler; + + memset((void *)&audio_handler, 0, sizeof(usbd_audio_handler)); + +#ifdef USE_USB_AUDIO_MICPHONE +{ + usb_desc_std_ep std_ep = audio_config_set.mic_std_endpoint; + + usb_desc_ep ep = { + .header = std_ep.header, + .bEndpointAddress = std_ep.bEndpointAddress, + .bmAttributes = std_ep.bmAttributes, + .wMaxPacketSize = std_ep.wMaxPacketSize, + .bInterval = std_ep.bInterval + }; + + /* initialize Tx endpoint */ + usbd_ep_setup (udev, &ep); +} +#endif + +#ifdef USE_USB_AUDIO_SPEAKER +{ + audio_handler.isoc_out_rdptr = audio_handler.isoc_out_buff; + audio_handler.isoc_out_wrptr = audio_handler.isoc_out_buff; + + usb_desc_std_ep std_ep = audio_config_set.speak_std_endpoint; + + usb_desc_ep ep = { + .header = std_ep.header, + .bEndpointAddress = std_ep.bEndpointAddress, + .bmAttributes = std_ep.bmAttributes, + .wMaxPacketSize = std_ep.wMaxPacketSize, + .bInterval = std_ep.bInterval + }; + + /* initialize Rx endpoint */ + usbd_ep_setup (udev, &ep); + + /* initialize the audio output hardware layer */ + if (USBD_OK != audio_out_fops.audio_init(USBD_AUDIO_FREQ_16K, DEFAULT_VOLUME, 0U)) { + return USBD_FAIL; + } + + /* prepare OUT endpoint to receive audio data */ + usbd_ep_recev (udev, AUDIO_OUT_EP, (uint8_t*)audio_handler.isoc_out_buff, SPEAKER_OUT_PACKET); +} +#endif + + udev->dev.class_data[USBD_AUDIO_INTERFACE] = (void *)&audio_handler; + + return USBD_OK; +} + +/*! + \brief de-initialize the AUDIO device + \param[in] udev: pointer to USB device instance + \param[in] config_index: configuration index + \param[out] none + \retval USB device operation status +*/ +static uint8_t audio_deinit (usb_dev *udev, uint8_t config_index) +{ +#ifdef USE_USB_AUDIO_MICPHONE + /* deinitialize AUDIO endpoints */ + usbd_ep_clear(udev, AUDIO_IN_EP); +#endif + +#ifdef USE_USB_AUDIO_SPEAKER + /* deinitialize AUDIO endpoints */ + usbd_ep_clear(udev, AUDIO_OUT_EP); + + /* deinitialize the audio output hardware layer */ + if (USBD_OK != audio_out_fops.audio_deinit(0U)) { + return USBD_FAIL; + } +#endif + + return USBD_OK; +} + +/*! + \brief handle the AUDIO class-specific requests + \param[in] udev: pointer to USB device instance + \param[in] req: device class-specific request + \param[out] none + \retval USB device operation status +*/ +static uint8_t audio_req_handler (usb_dev *udev, usb_req *req) +{ + uint8_t status = REQ_NOTSUPP; + + usbd_audio_handler *audio = (usbd_audio_handler *)udev->dev.class_data[USBD_AUDIO_INTERFACE]; + + usb_transc *transc_in = &udev->dev.transc_in[0]; + usb_transc *transc_out = &udev->dev.transc_out[0]; + + switch (req->bRequest) { + case AUDIO_REQ_GET_CUR: + transc_in->xfer_buf = audio->audioctl; + transc_in->remain_len = req->wLength; + + status = REQ_SUPP; + break; + + case AUDIO_REQ_SET_CUR: + if (req->wLength) { + transc_out->xfer_buf = audio->audioctl; + transc_out->remain_len = req->wLength; + + udev->dev.class_core->command = AUDIO_REQ_SET_CUR; + + audio->audioctl_len = req->wLength; + audio->audioctl_unit = BYTE_HIGH(req->wIndex); + + status = REQ_SUPP; + } + break; + + case AUDIO_REQ_GET_MIN: + *((uint16_t *)audio->audioctl) = VOL_MIN; + transc_in->xfer_buf = audio->audioctl; + transc_in->remain_len = req->wLength; + status = REQ_SUPP; + break; + + case AUDIO_REQ_GET_MAX: + *((uint16_t *)audio->audioctl) = VOL_MAX; + transc_in->xfer_buf = audio->audioctl; + transc_in->remain_len = req->wLength; + status = REQ_SUPP; + break; + + case AUDIO_REQ_GET_RES: + *((uint16_t *)audio->audioctl) = VOL_RES; + transc_in->xfer_buf = audio->audioctl; + transc_in->remain_len = req->wLength; + status = REQ_SUPP; + break; + + default: + break; + } + + return status; +} + +/*! + \brief handle the AUDIO set interface requests + \param[in] udev: pointer to USB device instance + \param[in] req: device class-specific request + \param[out] none + \retval USB device operation status +*/ +static uint8_t audio_set_intf(usb_dev *udev, usb_req *req) +{ + udev->dev.class_core->alter_set = req->wValue; + + return USBD_OK; +} + +/*! + \brief handles the control transfer OUT callback + \param[in] udev: pointer to USB device instance + \param[out] none + \retval USB device operation status +*/ +static uint8_t audio_ctlx_out (usb_dev *udev) +{ +#ifdef USE_USB_AUDIO_SPEAKER + usbd_audio_handler *audio = (usbd_audio_handler *)udev->dev.class_data[USBD_AUDIO_INTERFACE]; + + /* handles audio control requests data */ + /* check if an audio_control request has been issued */ + if (AUDIO_REQ_SET_CUR == udev->dev.class_core->command) { + /* in this driver, to simplify code, only SET_CUR request is managed */ + + /* check for which addressed unit the audio_control request has been issued */ + if (AUDIO_OUT_STREAMING_CTRL == audio->audioctl_unit) { + /* in this driver, to simplify code, only one unit is manage */ + + /* call the audio interface mute function */ + audio_out_fops.audio_mute_ctl(audio->audioctl[0]); + + /* reset the audioctl_cmd variable to prevent re-entering this function */ + udev->dev.class_core->command = 0U; + + audio->audioctl_len = 0U; + } + } +#endif + + return USBD_OK; +} + +/*! + \brief handles the audio IN data stage + \param[in] udev: pointer to USB device instance + \param[in] ep_num: endpoint number + \param[out] none + \retval USB device operation status +*/ +static uint8_t audio_data_in (usb_dev *udev, uint8_t ep_num) +{ +#ifdef USE_USB_AUDIO_MICPHONE + if(count_data < LENGTH_DATA){ + /* Prepare next buffer to be sent: dummy data */ + usbd_ep_send(udev, AUDIO_IN_EP,(uint8_t*)&wavetestdata[count_data],MIC_IN_PACKET); + count_data += MIC_IN_PACKET; + } else { + usbd_ep_send(udev, AUDIO_IN_EP,(uint8_t*)wavetestdata,MIC_IN_PACKET); + count_data = MIC_IN_PACKET; + } +#endif + + return USBD_OK; +} + +/*! + \brief handles the audio OUT data stage + \param[in] udev: pointer to USB device instance + \param[in] ep_num: endpoint number + \param[out] none + \retval USB device operation status +*/ +static uint8_t audio_data_out (usb_dev *udev, uint8_t ep_num) +{ +#ifdef USE_USB_AUDIO_SPEAKER + usbd_audio_handler *audio = (usbd_audio_handler *)udev->dev.class_data[USBD_AUDIO_INTERFACE]; + + /* increment the Buffer pointer or roll it back when all buffers are full */ + if (audio->isoc_out_wrptr >= (audio->isoc_out_buff + (SPEAKER_OUT_PACKET * OUT_PACKET_NUM))) { + /* all buffers are full: roll back */ + audio->isoc_out_wrptr = audio->isoc_out_buff; + } else { + /* increment the buffer pointer */ + audio->isoc_out_wrptr += SPEAKER_OUT_PACKET; + } + + /* Toggle the frame index */ + udev->dev.transc_out[ep_num].frame_num = + (udev->dev.transc_out[ep_num].frame_num)? 0U:1U; + + /* prepare out endpoint to receive next audio packet */ + usbd_ep_recev (udev, AUDIO_OUT_EP, (uint8_t*)(audio->isoc_out_wrptr), SPEAKER_OUT_PACKET); + + /* trigger the start of streaming only when half buffer is full */ + if ((0U == audio->play_flag) && (audio->isoc_out_wrptr >= (audio->isoc_out_buff + ((SPEAKER_OUT_PACKET * OUT_PACKET_NUM) / 2U)))) { + /* enable start of streaming */ + audio->play_flag = 1U; + } +#endif + + return USBD_OK; +} + +/*! + \brief handles the SOF event (data buffer update and synchronization) + \param[in] udev: pointer to USB device instance + \param[out] none + \retval USB device operation status +*/ +static uint8_t usbd_audio_sof (usb_dev *udev) +{ +#ifdef USE_USB_AUDIO_SPEAKER + usbd_audio_handler *audio = (usbd_audio_handler *)udev->dev.class_data[USBD_AUDIO_INTERFACE]; + + /* check if there are available data in stream buffer. + in this function, a single variable (play_flag) is used to avoid software delays. + the play operation must be executed as soon as possible after the SOF detection. */ + if (audio->play_flag) { + /* start playing received packet */ + audio_out_fops.audio_cmd((uint8_t*)(audio->isoc_out_rdptr), /* samples buffer pointer */ + SPEAKER_OUT_PACKET, /* number of samples in Bytes */ + AUDIO_CMD_PLAY); /* command to be processed */ + + /* increment the Buffer pointer or roll it back when all buffers all full */ + if (audio->isoc_out_rdptr >= (audio->isoc_out_buff + (SPEAKER_OUT_PACKET * OUT_PACKET_NUM))) { + /* roll back to the start of buffer */ + audio->isoc_out_rdptr = audio->isoc_out_buff; + } else { + /* increment to the next sub-buffer */ + audio->isoc_out_rdptr += SPEAKER_OUT_PACKET; + } + + /* if all available buffers have been consumed, stop playing */ + if (audio->isoc_out_rdptr == audio->isoc_out_wrptr) { + /* Pause the audio stream */ + audio_out_fops.audio_cmd((uint8_t*)(audio->isoc_out_buff), /* samples buffer pointer */ + SPEAKER_OUT_PACKET, /* number of samples in Bytes */ + AUDIO_CMD_PAUSE); /* command to be processed */ + + /* stop entering play loop */ + audio->play_flag = 0U; + + /* reset buffer pointers */ + audio->isoc_out_rdptr = audio->isoc_out_buff; + audio->isoc_out_wrptr = audio->isoc_out_buff; + } + } +#endif + + return USBD_OK; +} diff --git a/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/device/class/audio/Source/audio_out_itf.c b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/device/class/audio/Source/audio_out_itf.c new file mode 100644 index 0000000000..3682171868 --- /dev/null +++ b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/device/class/audio/Source/audio_out_itf.c @@ -0,0 +1,229 @@ +/*! + \file audio_out_itf.c + \brief audio OUT (playback) interface functions + + \version 2020-08-01, V3.0.0, firmware for GD32F30x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "audio_core.h" +#include "audio_out_itf.h" + +/* local function prototypes ('static') */ +static uint8_t init (uint32_t audiofreq, uint32_t volume, uint32_t options); +static uint8_t deinit (uint32_t options); +static uint8_t audio_cmd (uint8_t* pbuf, uint32_t size, uint8_t cmd); +static uint8_t volume_ctl (uint8_t vol); +static uint8_t mute_ctl (uint8_t cmd); +static uint8_t periodic_tc (uint8_t cmd); +static uint8_t get_state (void); + +audio_fops_struct audio_out_fops = +{ + init, + deinit, + audio_cmd, + volume_ctl, + mute_ctl, + periodic_tc, + get_state +}; + +static uint8_t audio_state = AUDIO_STATE_INACTIVE; + +/*! + \brief initialize and configures all required resources for audio play function + \param[in] audio_freq: statrt_up audio frequency + \param[in] volume: start_up volume to be set + \param[in] options: specific options passed to low layer function + \param[out] none + \retval AUDIO_OK if all operations succeed, AUDIO_FAIL else +*/ +static uint8_t init (uint32_t audio_freq, uint32_t volume, uint32_t options) +{ + static uint32_t initialized = 0U; + + /* check if the low layer has already been initialized */ + if (0U == initialized) { + /* call low layer function */ + if (0U != eval_audio_init(OUTPUT_DEVICE_AUTO, (uint8_t)volume, audio_freq)) { + audio_state = AUDIO_STATE_ERROR; + + return AUDIO_FAIL; + } + + /* set the initialization flag to prevent reinitializing the interface again */ + initialized = 1U; + } + + /* update the audio state machine */ + audio_state = AUDIO_STATE_ACTIVE; + + return AUDIO_OK; +} + +/*! + \brief free all resources used by low layer and stops audio-play function + \param[in] options: specific options passed to low layer function + \param[out] none + \retval AUDIO_OK if all operations succeed, AUDIO_FAIL else +*/ +static uint8_t deinit (uint32_t options) +{ + /* update the audio state machine */ + audio_state = AUDIO_STATE_INACTIVE; + + return AUDIO_OK; +} + +/*! + \brief play, stop, pause or resume current file + \param[in] pbuf: address from which file should be played + \param[in] size: size of the current buffer/file + \param[in] cmd: command to be executed, can be: + \arg AUDIO_CMD_PLAY + \arg AUDIO_CMD_PAUSE + \arg AUDIO_CMD_RESUME + \arg AUDIO_CMD_STOP + \param[out] none + \retval AUDIO_OK if all operations succeed, AUDIO_FAIL else +*/ +static uint8_t audio_cmd (uint8_t* pbuf, uint32_t size, uint8_t cmd) +{ + /* check the current state */ + if ((AUDIO_STATE_INACTIVE == audio_state) || (AUDIO_STATE_ERROR == audio_state)) { + audio_state = AUDIO_STATE_ERROR; + + return AUDIO_FAIL; + } + + switch (cmd) { + /* process the play command */ + case AUDIO_CMD_PLAY: + /* if current state is active or stopped */ + if ((AUDIO_STATE_ACTIVE == audio_state) || \ + (AUDIO_STATE_STOPPED == audio_state) || \ + (AUDIO_STATE_PLAYING == audio_state)) { + audio_mal_play((uint32_t)pbuf, size); + audio_state = AUDIO_STATE_PLAYING; + + return AUDIO_OK; + } else if (AUDIO_STATE_PAUSED == audio_state) { + if (eval_audio_pause_resume(AUDIO_RESUME, (uint32_t)pbuf, (size / 2U))) { + audio_state = AUDIO_STATE_ERROR; + + return AUDIO_FAIL; + } else { + audio_state = AUDIO_STATE_PLAYING; + + return AUDIO_OK; + } + } else { + return AUDIO_FAIL; + } + + /* process the stop command */ + case AUDIO_CMD_STOP: + if (AUDIO_STATE_PLAYING != audio_state) { + /* unsupported command */ + return AUDIO_FAIL; + } else if (eval_audio_stop(CODEC_PDWN_SW)) { + audio_state = AUDIO_STATE_ERROR; + + return AUDIO_FAIL; + } else { + audio_state = AUDIO_STATE_STOPPED; + + return AUDIO_OK; + } + + /* process the pause command */ + case AUDIO_CMD_PAUSE: + if (AUDIO_STATE_PLAYING != audio_state) { + /* unsupported command */ + return AUDIO_FAIL; + } else if (eval_audio_pause_resume(AUDIO_PAUSE, (uint32_t)pbuf, (size / 2U))) { + audio_state = AUDIO_STATE_ERROR; + + return AUDIO_FAIL; + } else { + audio_state = AUDIO_STATE_PAUSED; + + return AUDIO_OK; + } + + /* unsupported command */ + default: + return AUDIO_FAIL; + } +} + +/*! + \brief set the volume level + \param[in] vol: volume level to be set in % (from 0% to 100%) + \param[out] none + \retval AUDIO_OK if all operations succeed, AUDIO_FAIL else +*/ +static uint8_t volume_ctl (uint8_t vol) +{ + return AUDIO_OK; +} + +/*! + \brief mute or unmute the audio current output + \param[in] cmd: can be 0 to unmute, or 1 to mute + \param[out] none + \retval AUDIO_OK if all operations succeed, AUDIO_FAIL else +*/ +static uint8_t mute_ctl (uint8_t cmd) +{ + return AUDIO_OK; +} + +/*! + \brief periodic transfer control + \param[in] cmd: command + \param[out] none + \retval AUDIO_OK if all operations succeed, AUDIO_FAIL else +*/ +static uint8_t periodic_tc (uint8_t cmd) +{ + return AUDIO_OK; +} + +/*! + \brief return the current state of the audio machine + \param[in] none + \param[out] none + \retval AUDIO_OK if all operations succeed, AUDIO_FAIL else +*/ +static uint8_t get_state (void) +{ + return audio_state; +} diff --git a/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/device/class/cdc/Include/cdc_acm_core.h b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/device/class/cdc/Include/cdc_acm_core.h new file mode 100644 index 0000000000..63e63e82d7 --- /dev/null +++ b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/device/class/cdc/Include/cdc_acm_core.h @@ -0,0 +1,66 @@ +/*! + \file cdc_acm_core.h + \brief the header file of cdc acm driver + + \version 2020-08-01, V3.0.0, firmware for GD32F30x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef __CDC_ACM_CORE_H +#define __CDC_ACM_CORE_H + +#include "usbd_enum.h" +#include "usb_cdc.h" + +#define USB_CDC_RX_LEN 64 + +typedef struct { + uint8_t packet_sent; + uint8_t packet_receive; + + uint8_t data[USB_CDC_RX_LEN]; + uint8_t cmd[USB_CDC_CMD_PACKET_SIZE]; + + uint32_t receive_length; + + acm_line line_coding; +} usb_cdc_handler; + +extern usb_desc cdc_desc; +extern usb_class_core cdc_class; + +/* function declarations */ +/* check cdc acm is ready for data transfer */ +uint8_t cdc_acm_check_ready(usb_dev *udev); +/* send CDC ACM data */ +void cdc_acm_data_send(usb_dev *udev); +/* receive CDC ACM data */ +void cdc_acm_data_receive(usb_dev *udev); + +#endif /* __CDC_ACM_CORE_H */ diff --git a/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/device/class/cdc/Source/cdc_acm_core.c b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/device/class/cdc/Source/cdc_acm_core.c new file mode 100644 index 0000000000..38f47dd4d4 --- /dev/null +++ b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/device/class/cdc/Source/cdc_acm_core.c @@ -0,0 +1,524 @@ +/*! + \file cdc_acm_core.c + \brief CDC ACM driver + + \version 2020-08-01, V3.0.0, firmware for GD32F30x + \version 2020-12-07, V3.0.1, firmware for GD32F30x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "cdc_acm_core.h" + +#define USBD_VID 0x28E9U +#define USBD_PID 0x018AU + +/* note:it should use the C99 standard when compiling the below codes */ +/* USB standard device descriptor */ +const usb_desc_dev cdc_dev_desc = +{ + .header = + { + .bLength = USB_DEV_DESC_LEN, + .bDescriptorType = USB_DESCTYPE_DEV, + }, + .bcdUSB = 0x0200U, + .bDeviceClass = USB_CLASS_CDC, + .bDeviceSubClass = 0x00U, + .bDeviceProtocol = 0x00U, + .bMaxPacketSize0 = USB_FS_EP0_MAX_LEN, + .idVendor = USBD_VID, + .idProduct = USBD_PID, + .bcdDevice = 0x0100U, + .iManufacturer = STR_IDX_MFC, + .iProduct = STR_IDX_PRODUCT, + .iSerialNumber = STR_IDX_SERIAL, + .bNumberConfigurations = USBD_CFG_MAX_NUM, +}; + +/* USB device configuration descriptor */ +const usb_cdc_desc_config_set cdc_config_desc = +{ + .config = + { + .header = + { + .bLength = sizeof(usb_desc_config), + .bDescriptorType = USB_DESCTYPE_CONFIG, + }, + .wTotalLength = USB_CDC_ACM_CONFIG_DESC_SIZE, + .bNumInterfaces = 0x02U, + .bConfigurationValue = 0x01U, + .iConfiguration = 0x00U, + .bmAttributes = 0x80U, + .bMaxPower = 0x32U + }, + + .cmd_itf = + { + .header = + { + .bLength = sizeof(usb_desc_itf), + .bDescriptorType = USB_DESCTYPE_ITF + }, + .bInterfaceNumber = 0x00U, + .bAlternateSetting = 0x00U, + .bNumEndpoints = 0x01U, + .bInterfaceClass = USB_CLASS_CDC, + .bInterfaceSubClass = USB_CDC_SUBCLASS_ACM, + .bInterfaceProtocol = USB_CDC_PROTOCOL_AT, + .iInterface = 0x00U + }, + + .cdc_header = + { + .header = + { + .bLength = sizeof(usb_desc_header_func), + .bDescriptorType = USB_DESCTYPE_CS_INTERFACE + }, + .bDescriptorSubtype = 0x00U, + .bcdCDC = 0x0110U + }, + + .cdc_call_managment = + { + .header = + { + .bLength = sizeof(usb_desc_call_managment_func), + .bDescriptorType = USB_DESCTYPE_CS_INTERFACE + }, + .bDescriptorSubtype = 0x01U, + .bmCapabilities = 0x00U, + .bDataInterface = 0x01U + }, + + .cdc_acm = + { + .header = + { + .bLength = sizeof(usb_desc_acm_func), + .bDescriptorType = USB_DESCTYPE_CS_INTERFACE + }, + .bDescriptorSubtype = 0x02U, + .bmCapabilities = 0x02U, + }, + + .cdc_union = + { + .header = + { + .bLength = sizeof(usb_desc_union_func), + .bDescriptorType = USB_DESCTYPE_CS_INTERFACE + }, + .bDescriptorSubtype = 0x06U, + .bMasterInterface = 0x00U, + .bSlaveInterface0 = 0x01U, + }, + + .cdc_cmd_endpoint = + { + .header = + { + .bLength = sizeof(usb_desc_ep), + .bDescriptorType = USB_DESCTYPE_EP, + }, + .bEndpointAddress = CDC_CMD_EP, + .bmAttributes = USB_EP_ATTR_INT, + .wMaxPacketSize = USB_CDC_CMD_PACKET_SIZE, + .bInterval = 0x0AU + }, + + .cdc_data_interface = + { + .header = + { + .bLength = sizeof(usb_desc_itf), + .bDescriptorType = USB_DESCTYPE_ITF, + }, + .bInterfaceNumber = 0x01U, + .bAlternateSetting = 0x00U, + .bNumEndpoints = 0x02U, + .bInterfaceClass = USB_CLASS_DATA, + .bInterfaceSubClass = 0x00U, + .bInterfaceProtocol = USB_CDC_PROTOCOL_NONE, + .iInterface = 0x00U + }, + + .cdc_out_endpoint = + { + .header = + { + .bLength = sizeof(usb_desc_ep), + .bDescriptorType = USB_DESCTYPE_EP, + }, + .bEndpointAddress = CDC_DATA_OUT_EP, + .bmAttributes = USB_EP_ATTR_BULK, + .wMaxPacketSize = USB_CDC_DATA_PACKET_SIZE, + .bInterval = 0x00U + }, + + .cdc_in_endpoint = + { + .header = + { + .bLength = sizeof(usb_desc_ep), + .bDescriptorType = USB_DESCTYPE_EP + }, + .bEndpointAddress = CDC_DATA_IN_EP, + .bmAttributes = USB_EP_ATTR_BULK, + .wMaxPacketSize = USB_CDC_DATA_PACKET_SIZE, + .bInterval = 0x00U + } +}; + +/* USB language ID Descriptor */ +static const usb_desc_LANGID usbd_language_id_desc = +{ + .header = + { + .bLength = sizeof(usb_desc_LANGID), + .bDescriptorType = USB_DESCTYPE_STR, + }, + .wLANGID = ENG_LANGID +}; + +/* USB manufacture string */ +static const usb_desc_str manufacturer_string = +{ + .header = + { + .bLength = USB_STRING_LEN(10), + .bDescriptorType = USB_DESCTYPE_STR, + }, + .unicode_string = {'G', 'i', 'g', 'a', 'D', 'e', 'v', 'i', 'c', 'e'} +}; + +/* USB product string */ +static const usb_desc_str product_string = +{ + .header = + { + .bLength = USB_STRING_LEN(12), + .bDescriptorType = USB_DESCTYPE_STR, + }, + .unicode_string = {'G', 'D', '3', '2', '-', 'C', 'D', 'C', '_', 'A', 'C', 'M'} +}; + +/* USBD serial string */ +static usb_desc_str serial_string = +{ + .header = + { + .bLength = USB_STRING_LEN(12), + .bDescriptorType = USB_DESCTYPE_STR, + } +}; + +/* USB string descriptor set */ +void *const usbd_cdc_strings[] = +{ + [STR_IDX_LANGID] = (uint8_t *)&usbd_language_id_desc, + [STR_IDX_MFC] = (uint8_t *)&manufacturer_string, + [STR_IDX_PRODUCT] = (uint8_t *)&product_string, + [STR_IDX_SERIAL] = (uint8_t *)&serial_string +}; + +usb_desc cdc_desc = +{ + .dev_desc = (uint8_t *)&cdc_dev_desc, + .config_desc = (uint8_t *)&cdc_config_desc, + .strings = usbd_cdc_strings +}; + +/* local function prototypes ('static') */ +static uint8_t cdc_acm_init (usb_dev *udev, uint8_t config_index); +static uint8_t cdc_acm_deinit (usb_dev *udev, uint8_t config_index); +static uint8_t cdc_acm_req (usb_dev *udev, usb_req *req); +static uint8_t cdc_ctlx_out (usb_dev *udev); +static uint8_t cdc_acm_in (usb_dev *udev, uint8_t ep_num); +static uint8_t cdc_acm_out (usb_dev *udev, uint8_t ep_num); + +/* USB CDC device class callbacks structure */ +usb_class_core cdc_class = +{ + .command = NO_CMD, + .alter_set = 0U, + + .init = cdc_acm_init, + .deinit = cdc_acm_deinit, + .req_proc = cdc_acm_req, + .ctlx_out = cdc_ctlx_out, + + .data_in = cdc_acm_in, + .data_out = cdc_acm_out +}; + +/*! + \brief check cdc acm is ready for data transfer + \param[in] udev: pointer to USB device instance + \param[out] none + \retval 0 if cdc is ready, 5 else +*/ +uint8_t cdc_acm_check_ready(usb_dev *udev) +{ + if (udev->dev.class_data[CDC_COM_INTERFACE] != NULL) { + usb_cdc_handler *cdc = (usb_cdc_handler *)udev->dev.class_data[CDC_COM_INTERFACE]; + + if ((1U == cdc->packet_receive) && (1U == cdc->packet_sent)) { + return 0U; + } + } + + return 1U; +} + +/*! + \brief send CDC ACM data + \param[in] udev: pointer to USB device instance + \param[out] none + \retval USB device operation status +*/ +void cdc_acm_data_send (usb_dev *udev) +{ + usb_cdc_handler *cdc = (usb_cdc_handler *)udev->dev.class_data[CDC_COM_INTERFACE]; + + if (0U != cdc->receive_length) { + cdc->packet_sent = 0U; + + usbd_ep_send (udev, CDC_DATA_IN_EP, (uint8_t*)(cdc->data), cdc->receive_length); + + cdc->receive_length = 0U; + } +} + +/*! + \brief receive CDC ACM data + \param[in] udev: pointer to USB device instance + \param[out] none + \retval USB device operation status +*/ +void cdc_acm_data_receive (usb_dev *udev) +{ + usb_cdc_handler *cdc = (usb_cdc_handler *)udev->dev.class_data[CDC_COM_INTERFACE]; + + cdc->packet_receive = 0U; + cdc->packet_sent = 0U; + + usbd_ep_recev(udev, CDC_DATA_OUT_EP, (uint8_t*)(cdc->data), USB_CDC_DATA_PACKET_SIZE); +} + +/*! + \brief initialize the CDC ACM device + \param[in] udev: pointer to USB device instance + \param[in] config_index: configuration index + \param[out] none + \retval USB device operation status +*/ +static uint8_t cdc_acm_init (usb_dev *udev, uint8_t config_index) +{ + static usb_cdc_handler cdc_handler; + + /* initialize the data Tx endpoint */ + usbd_ep_setup (udev, &(cdc_config_desc.cdc_in_endpoint)); + + /* initialize the data Rx endpoint */ + usbd_ep_setup (udev, &(cdc_config_desc.cdc_out_endpoint)); + + /* initialize the command Tx endpoint */ + usbd_ep_setup (udev, &(cdc_config_desc.cdc_cmd_endpoint)); + + /* initialize cdc handler structure */ + cdc_handler.packet_receive = 1U; + cdc_handler.packet_sent = 1U; + cdc_handler.receive_length = 0U; + + cdc_handler.line_coding = (acm_line){ + .dwDTERate = 115200, + .bCharFormat = 0, + .bParityType = 0, + .bDataBits = 0x08 + }; + + udev->dev.class_data[CDC_COM_INTERFACE] = (void *)&cdc_handler; + + return USBD_OK; +} + +/*! + \brief de-initialize the CDC ACM device + \param[in] udev: pointer to USB device instance + \param[in] config_index: configuration index + \param[out] none + \retval USB device operation status +*/ +static uint8_t cdc_acm_deinit (usb_dev *udev, uint8_t config_index) +{ + /* deinitialize the data Tx/Rx endpoint */ + usbd_ep_clear (udev, CDC_DATA_IN_EP); + usbd_ep_clear (udev, CDC_DATA_OUT_EP); + + /* deinitialize the command Tx endpoint */ + usbd_ep_clear (udev, CDC_CMD_EP); + + return USBD_OK; +} + +/*! + \brief handle the CDC ACM class-specific requests + \param[in] udev: pointer to USB device instance + \param[in] req: device class-specific request + \param[out] none + \retval USB device operation status +*/ +static uint8_t cdc_acm_req (usb_dev *udev, usb_req *req) +{ + usb_cdc_handler *cdc = (usb_cdc_handler *)udev->dev.class_data[CDC_COM_INTERFACE]; + + usb_transc *transc = NULL; + + switch (req->bRequest) { + case SEND_ENCAPSULATED_COMMAND: + /* no operation for this driver */ + break; + + case GET_ENCAPSULATED_RESPONSE: + /* no operation for this driver */ + break; + + case SET_COMM_FEATURE: + /* no operation for this driver */ + break; + + case GET_COMM_FEATURE: + /* no operation for this driver */ + break; + + case CLEAR_COMM_FEATURE: + /* no operation for this driver */ + break; + + case SET_LINE_CODING: + transc = &udev->dev.transc_out[0]; + /* set the value of the current command to be processed */ + udev->dev.class_core->alter_set = req->bRequest; + + /* enable EP0 prepare to receive command data packet */ + transc->remain_len = req->wLength; + transc->xfer_buf = cdc->cmd; + break; + + case GET_LINE_CODING: + transc = &udev->dev.transc_in[0]; + + cdc->cmd[0] = (uint8_t)(cdc->line_coding.dwDTERate); + cdc->cmd[1] = (uint8_t)(cdc->line_coding.dwDTERate >> 8); + cdc->cmd[2] = (uint8_t)(cdc->line_coding.dwDTERate >> 16); + cdc->cmd[3] = (uint8_t)(cdc->line_coding.dwDTERate >> 24); + cdc->cmd[4] = cdc->line_coding.bCharFormat; + cdc->cmd[5] = cdc->line_coding.bParityType; + cdc->cmd[6] = cdc->line_coding.bDataBits; + + transc->xfer_buf = cdc->cmd; + transc->remain_len = 7U; + break; + + case SET_CONTROL_LINE_STATE: + /* no operation for this driver */ + break; + + case SEND_BREAK: + /* no operation for this driver */ + break; + + default: + break; + } + + return USBD_OK; +} + +static uint8_t cdc_ctlx_out (usb_dev *udev) +{ + usb_cdc_handler *cdc = (usb_cdc_handler *)udev->dev.class_data[CDC_COM_INTERFACE]; + + if (udev->dev.class_core->alter_set != NO_CMD) { + /* process the command data */ + cdc->line_coding.dwDTERate = (uint32_t)((uint32_t)cdc->cmd[0] | + ((uint32_t)cdc->cmd[1] << 8U) | + ((uint32_t)cdc->cmd[2] << 16U) | + ((uint32_t)cdc->cmd[3] << 24U)); + + cdc->line_coding.bCharFormat = cdc->cmd[4]; + cdc->line_coding.bParityType = cdc->cmd[5]; + cdc->line_coding.bDataBits = cdc->cmd[6]; + + udev->dev.class_core->alter_set = NO_CMD; + } + + return USBD_OK; +} + +/*! + \brief handle CDC ACM data + \param[in] udev: pointer to USB device instance + \param[in] ep_num: endpoint identifier + \param[out] none + \retval USB device operation status +*/ +static uint8_t cdc_acm_in (usb_dev *udev, uint8_t ep_num) +{ + usb_transc *transc = &udev->dev.transc_in[EP_ID(ep_num)]; + + usb_cdc_handler *cdc = (usb_cdc_handler *)udev->dev.class_data[CDC_COM_INTERFACE]; + + if ((0U == transc->xfer_len % transc->max_len) && (0U != transc->xfer_len)) { + usbd_ep_send (udev, ep_num, NULL, 0U); + } else { + cdc->packet_sent = 1U; + } + + return USBD_OK; +} + +/*! + \brief handle CDC ACM data + \param[in] udev: pointer to USB device instance + \param[in] ep_num: endpoint identifier + \param[out] none + \retval USB device operation status +*/ +static uint8_t cdc_acm_out (usb_dev *udev, uint8_t ep_num) +{ + usb_cdc_handler *cdc = (usb_cdc_handler *)udev->dev.class_data[CDC_COM_INTERFACE]; + + cdc->packet_receive = 1U; + cdc->receive_length = ((usb_core_driver *)udev)->dev.transc_out[ep_num].xfer_count; + + return USBD_OK; +} diff --git a/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/device/class/dfu/Include/dfu_core.h b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/device/class/dfu/Include/dfu_core.h new file mode 100644 index 0000000000..538be38f77 --- /dev/null +++ b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/device/class/dfu/Include/dfu_core.h @@ -0,0 +1,176 @@ +/*! + \file dfu_core.h + \brief the header file of USB DFU device class core functions + + \version 2020-08-01, V3.0.0, firmware for GD32F30x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef __DFU_CORE_H +#define __DFU_CORE_H + +#include "usbd_enum.h" + +/* DFU class code */ +#define USB_DFU_CLASS 0xFEU + +/* DFU subclass code */ +#define USB_DFU_SUBCLASS_UPGRADE 0x01U + +/* DFU protocl code */ +#define USB_DFU_PROTOCL_RUNTIME 0x01U +#define USB_DFU_PROTOCL_DFU 0x02U + +/* manifestation state */ +#define MANIFEST_COMPLETE 0x00U +#define MANIFEST_IN_PROGRESS 0x01U + +/* DFU attributes code */ +#define USB_DFU_CAN_DOWNLOAD 0x01U +#define USB_DFU_CAN_UPLOAD 0x02U +#define USB_DFU_MANIFEST_TOLERANT 0x04U +#define USB_DFU_WILL_DETACH 0x08U + +/* special commands with download request */ +#define GET_COMMANDS 0x00U +#define SET_ADDRESS_POINTER 0x21U +#define ERASE 0x41U + +/* memory operation command */ +#define CMD_ERASE 0U +#define CMD_WRITE 1U + +#define _BYTE1(x) (uint8_t)((x) & 0xFFU) /*!< addressing cycle 1st byte */ +#define _BYTE2(x) (uint8_t)(((x) & 0xFF00U) >> 8U) /*!< addressing cycle 2nd byte */ +#define _BYTE3(x) (uint8_t)(((x) & 0xFF0000U) >> 16U) /*!< addressing cycle 3rd byte */ + +#define FLASH_ERASE_TIMEOUT 60U +#define FLASH_WRITE_TIMEOUT 80U + +/* bit detach capable = bit 3 in bmAttributes field */ +#define DFU_DETACH_MASK (uint8_t)(0x10U) + +#define USB_SERIAL_STR_LEN 0x06U + +#define USB_DFU_CONFIG_DESC_SIZE 27U + +#define DFU_DESC_TYPE 0x21U + +/* DFU device state defines */ +typedef enum { + STATE_APP_IDLE = 0x00U, + 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 +} dfu_state; + +/* DFU device status defines */ +typedef enum { + STATUS_OK = 0x00U, + STATUS_ERR_TARGET, + STATUS_ERR_FILE, + STATUS_ERR_WRITE, + STATUS_ERR_ERASE, + STATUS_ERR_CHECK_ERASED, + STATUS_ERR_PROG, + STATUS_ERR_VERIFY, + STATUS_ERR_ADDRESS, + STATUS_ERR_NOTDONE, + STATUS_ERR_FIRMWARE, + STATUS_ERR_VENDOR, + STATUS_ERR_USBR, + STATUS_ERR_POR, + STATUS_ERR_UNKNOWN, + STATUS_ERR_STALLEDPKT +} dfu_status; + +/* DFU class-specific requests */ +typedef enum { + DFU_DETACH = 0U, + DFU_DNLOAD, + DFU_UPLOAD, + DFU_GETSTATUS, + DFU_CLRSTATUS, + DFU_GETSTATE, + DFU_ABORT, + DFU_REQ_MAX +} dfu_requests; + +#pragma pack(1) + +/* USB dfu function descriptor structure */ +typedef struct +{ + usb_desc_header header; /*!< descriptor header, including type and size */ + uint8_t bmAttributes; /*!< DFU attributes */ + uint16_t wDetachTimeOut; /*!< time, in milliseconds, that the device will wait after receipt of the DFU_DETACH request. If */ + uint16_t wTransferSize; /*!< maximum number of bytes that the device can accept per control-write transaction */ + uint16_t bcdDFUVersion; /*!< numeric expression identifying the version of the DFU Specification release. */ +} usb_desc_dfu_func; + +#pragma pack() + +/* USB configuration descriptor structure */ +typedef struct +{ + usb_desc_config config; + usb_desc_itf dfu_itf; + usb_desc_dfu_func dfu_func; +} usb_dfu_desc_config_set; + +typedef struct +{ + uint8_t bStatus; + uint8_t bwPollTimeout0; + uint8_t bwPollTimeout1; + uint8_t bwPollTimeout2; + uint8_t bState; + uint8_t iString; + + uint8_t manifest_state; + uint32_t data_len; + uint16_t block_num; + uint32_t base_addr; + + uint8_t buf[TRANSFER_SIZE]; +} usbd_dfu_handler; + +typedef void (*app_func) (void); + +extern usb_desc dfu_desc; +extern usb_class_core dfu_class; + +#endif /* DFU_CORE_H */ diff --git a/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/device/class/dfu/Include/dfu_mal.h b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/device/class/dfu/Include/dfu_mal.h new file mode 100644 index 0000000000..e0af991ca4 --- /dev/null +++ b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/device/class/dfu/Include/dfu_mal.h @@ -0,0 +1,84 @@ +/*! + \file dfu_mal.h + \brief USB DFU device media access layer header file + + \version 2020-08-01, V3.0.0, firmware for GD32F30x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef __DFU_MAL_H +#define __DFU_MAL_H + +#include "usbd_conf.h" + +typedef struct _dfu_mal_prop +{ + const uint8_t* pstr_desc; + + uint8_t (*mal_init) (void); + uint8_t (*mal_deinit) (void); + uint8_t (*mal_erase) (uint32_t addr); + uint8_t (*mal_write) (uint8_t *buf, uint32_t addr, uint32_t len); + uint8_t* (*mal_read) (uint8_t *buf, uint32_t addr, uint32_t len); + uint8_t (*mal_checkaddr) (uint32_t addr); + + const uint32_t erase_timeout; + const uint32_t write_timeout; +} dfu_mal_prop; + +typedef enum +{ + MAL_OK = 0, + MAL_FAIL +} MAL_Status; + +#define _1st_BYTE(x) (uint8_t)((x) & 0xFF) /*!< addressing cycle 1st byte */ +#define _2nd_BYTE(x) (uint8_t)(((x) & 0xFF00) >> 8) /*!< addressing cycle 2nd byte */ +#define _3rd_BYTE(x) (uint8_t)(((x) & 0xFF0000) >> 16) /*!< addressing cycle 3rd byte */ + +#define SET_POLLING_TIMEOUT(x) buffer[0] = _1st_BYTE(x);\ + buffer[1] = _2nd_BYTE(x);\ + buffer[2] = _3rd_BYTE(x); + +/* function declarations */ +/* initialize the memory media on the GD32 */ +uint8_t dfu_mal_init(void); +/* deinitialize the memory media on the GD32 */ +uint8_t dfu_mal_deinit(void); +/* erase a memory sector */ +uint8_t dfu_mal_erase(uint32_t addr); +/* write data to sectors of memory */ +uint8_t dfu_mal_write(uint8_t *buf, uint32_t addr, uint32_t len); +/* read data from sectors of memory */ +uint8_t* dfu_mal_read(uint8_t *buf, uint32_t addr, uint32_t len); +/* get the status of a given memory and store in buffer */ +uint8_t dfu_mal_getstatus(uint32_t addr, uint8_t cmd, uint8_t *buffer); + +#endif /* __DFU_MAL_H */ + diff --git a/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/device/class/dfu/Source/dfu_core.c b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/device/class/dfu/Source/dfu_core.c new file mode 100644 index 0000000000..35a895a52c --- /dev/null +++ b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/device/class/dfu/Source/dfu_core.c @@ -0,0 +1,652 @@ +/*! + \file dfu_core.c + \brief USB DFU device class core functions + + \version 2020-08-01, V3.0.0, firmware for GD32F30x + \version 2020-12-07, V3.0.1, firmware for GD32F30x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "dfu_core.h" +#include "drv_usb_hw.h" +#include "dfu_mal.h" +#include "flash_if.h" +#include + +#define USBD_VID 0x28E9U +#define USBD_PID 0x0189U + +/* local function prototypes ('static') */ +static uint8_t dfu_init(usb_dev *udev, uint8_t config_index); +static uint8_t dfu_deinit(usb_dev *udev, uint8_t config_index); +static uint8_t dfu_req_handler(usb_dev *udev, usb_req *req); +static uint8_t dfu_ctlx_in(usb_dev *udev); +static void dfu_detach(usb_dev *udev, usb_req *req); +static void dfu_dnload(usb_dev *udev, usb_req *req); +static void dfu_upload(usb_dev *udev, usb_req *req); +static void dfu_getstatus(usb_dev *udev, usb_req *req); +static void dfu_clrstatus(usb_dev *udev, usb_req *req); +static void dfu_getstate(usb_dev *udev, usb_req *req); +static void dfu_abort(usb_dev *udev, usb_req *req); +static void dfu_mode_leave(usb_dev *udev); +static uint8_t dfu_getstatus_complete (usb_dev *udev); + +static void (*dfu_request_process[])(usb_dev *udev, usb_req *req) = +{ + [DFU_DETACH] = dfu_detach, + [DFU_DNLOAD] = dfu_dnload, + [DFU_UPLOAD] = dfu_upload, + [DFU_GETSTATUS] = dfu_getstatus, + [DFU_CLRSTATUS] = dfu_clrstatus, + [DFU_GETSTATE] = dfu_getstate, + [DFU_ABORT] = dfu_abort +}; + +/* note:it should use the c99 standard when compiling the below codes */ +/* USB standard device descriptor */ +const usb_desc_dev dfu_dev_desc = +{ + .header = + { + .bLength = USB_DEV_DESC_LEN, + .bDescriptorType = USB_DESCTYPE_DEV + }, + .bcdUSB = 0x0200U, + .bDeviceClass = 0x00U, + .bDeviceSubClass = 0x00U, + .bDeviceProtocol = 0x00U, + .bMaxPacketSize0 = USB_FS_EP0_MAX_LEN, + .idVendor = USBD_VID, + .idProduct = USBD_PID, + .bcdDevice = 0x0100U, + .iManufacturer = STR_IDX_MFC, + .iProduct = STR_IDX_PRODUCT, + .iSerialNumber = STR_IDX_SERIAL, + .bNumberConfigurations = USBD_CFG_MAX_NUM +}; + +/* USB device configuration descriptor */ +const usb_dfu_desc_config_set dfu_config_desc = +{ + .config = + { + .header = + { + .bLength = sizeof(usb_desc_config), + .bDescriptorType = USB_DESCTYPE_CONFIG + }, + .wTotalLength = USB_DFU_CONFIG_DESC_SIZE, + .bNumInterfaces = 0x01U, + .bConfigurationValue = 0x01U, + .iConfiguration = 0x00U, + .bmAttributes = 0x80U, + .bMaxPower = 0x32U + }, + + .dfu_itf = + { + .header = + { + .bLength = sizeof(usb_desc_itf), + .bDescriptorType = USB_DESCTYPE_ITF + }, + .bInterfaceNumber = 0x00U, + .bAlternateSetting = 0x00U, + .bNumEndpoints = 0x00U, + .bInterfaceClass = USB_DFU_CLASS, + .bInterfaceSubClass = USB_DFU_SUBCLASS_UPGRADE, + .bInterfaceProtocol = USB_DFU_PROTOCL_DFU, + .iInterface = 0x05U + }, + + .dfu_func = + { + .header = + { + .bLength = sizeof(usb_desc_dfu_func), + .bDescriptorType = DFU_DESC_TYPE + }, + .bmAttributes = USB_DFU_CAN_DOWNLOAD | USB_DFU_CAN_UPLOAD | USB_DFU_WILL_DETACH, + .wDetachTimeOut = 0x00FFU, + .wTransferSize = TRANSFER_SIZE, + .bcdDFUVersion = 0x011AU, + }, +}; + +/* USB language ID Descriptor */ +static const usb_desc_LANGID usbd_language_id_desc = +{ + .header = { + .bLength = sizeof(usb_desc_LANGID), + .bDescriptorType = USB_DESCTYPE_STR + }, + .wLANGID = ENG_LANGID +}; + +/* USB manufacture string */ +static const usb_desc_str manufacturer_string = +{ + .header = + { + .bLength = USB_STRING_LEN(10U), + .bDescriptorType = USB_DESCTYPE_STR, + }, + .unicode_string = {'G', 'i', 'g', 'a', 'D', 'e', 'v', 'i', 'c', 'e'} +}; + +/* USB product string */ +static const usb_desc_str product_string = +{ + .header = + { + .bLength = USB_STRING_LEN(12U), + .bDescriptorType = USB_DESCTYPE_STR, + }, + .unicode_string = {'G', 'D', '3', '2', '-', 'U', 'S', 'B', '_', 'D', 'F', 'U'} +}; + +/* USBD serial string */ +static usb_desc_str serial_string = +{ + .header = + { + .bLength = USB_STRING_LEN(2U), + .bDescriptorType = USB_DESCTYPE_STR, + } +}; + +/* USB configure string */ +static const usb_desc_str config_string = +{ + .header = + { + .bLength = USB_STRING_LEN(15U), + .bDescriptorType = USB_DESCTYPE_STR, + }, + .unicode_string = {'G', 'D', '3', '2', ' ', 'U', 'S', 'B', ' ', 'C', 'O', 'N', 'F', 'I', 'G'} +}; + +static const usb_desc_str interface_string = +{ + .header = + { + .bLength = USB_STRING_LEN(44U), + .bDescriptorType = USB_DESCTYPE_STR, + }, + .unicode_string = {'@', 'I', 'n', 't', 'e', 'r', 'n', 'a', 'l', 'F', 'l', 'a', 's', 'h', ' ', '/', '0', 'x', '0', '8', '0', '0', + '0', '0', '0', '0', '/', '1', '6', '*', '0', '0', '1', 'K', 'a', ',', '4', '8', '*', '0', '0', '1', 'K', 'g'} +}; + +void *const usbd_dfu_strings[] = +{ + [STR_IDX_LANGID] = (uint8_t *)&usbd_language_id_desc, + [STR_IDX_MFC] = (uint8_t *)&manufacturer_string, + [STR_IDX_PRODUCT] = (uint8_t *)&product_string, + [STR_IDX_SERIAL] = (uint8_t *)&serial_string, + [STR_IDX_CONFIG] = (uint8_t *)&config_string, + [STR_IDX_ITF] = (uint8_t *)&interface_string +}; + +usb_desc dfu_desc = { + .dev_desc = (uint8_t *)&dfu_dev_desc, + .config_desc = (uint8_t *)&dfu_config_desc, + .strings = usbd_dfu_strings +}; + +usb_class_core dfu_class = { + .init = dfu_init, + .deinit = dfu_deinit, + .req_proc = dfu_req_handler, + .ctlx_in = dfu_ctlx_in +}; + +/*! + \brief initialize the DFU device + \param[in] udev: pointer to USB device instance + \param[in] config_index: configuration index + \param[out] none + \retval USB device operation status +*/ +static uint8_t dfu_init (usb_dev *udev, uint8_t config_index) +{ + static usbd_dfu_handler dfu_handler; + + /* unlock the internal flash */ + dfu_mal_init(); + + memset((void *)&dfu_handler, 0, sizeof(usbd_dfu_handler)); + + dfu_handler.base_addr = APP_LOADED_ADDR; + dfu_handler.manifest_state = MANIFEST_COMPLETE; + dfu_handler.bState = STATE_DFU_IDLE; + dfu_handler.bStatus = STATUS_OK; + + udev->dev.class_data[USBD_DFU_INTERFACE] = (void *)&dfu_handler; + + return USBD_OK; +} + +/*! + \brief de-initialize the DFU device + \param[in] udev: pointer to USB device instance + \param[in] config_index: configuration index + \param[out] none + \retval USB device operation status +*/ +static uint8_t dfu_deinit (usb_dev *udev, uint8_t config_index) +{ + usbd_dfu_handler *dfu = (usbd_dfu_handler *)udev->dev.class_data[USBD_DFU_INTERFACE]; + + /* restore device default state */ + memset(udev->dev.class_data[USBD_DFU_INTERFACE], 0, sizeof(usbd_dfu_handler)); + + dfu->bState = STATE_DFU_IDLE; + dfu->bStatus = STATUS_OK; + + /* lock the internal flash */ + dfu_mal_deinit(); + + return USBD_OK; +} + +/*! + \brief handle the DFU class-specific requests + \param[in] udev: pointer to USB device instance + \param[in] req: device class-specific request + \param[out] none + \retval USB device operation status +*/ +static uint8_t dfu_req_handler (usb_dev *udev, usb_req *req) +{ + if (req->bRequest < DFU_REQ_MAX) { + dfu_request_process[req->bRequest](udev, req); + } else { + return USBD_FAIL; + } + + return USBD_OK; +} + +/*! + \brief handle data Stage + \param[in] udev: pointer to USB device instance + \param[in] ep_num: the endpoint number + \param[out] none + \retval USB device operation status +*/ +static uint8_t dfu_ctlx_in (usb_dev *udev) +{ + dfu_getstatus_complete(udev); + + return USBD_OK; +} + +/*! + \brief leave DFU mode and reset device to jump to user loaded code + \param[in] udev: pointer to USB device instance + \param[out] none + \retval none +*/ +static void dfu_mode_leave (usb_dev *udev) +{ + usbd_dfu_handler *dfu = (usbd_dfu_handler *)udev->dev.class_data[USBD_DFU_INTERFACE]; + + dfu->manifest_state = MANIFEST_COMPLETE; + + if (dfu_config_desc.dfu_func.bmAttributes & 0x04U) { + dfu->bState = STATE_DFU_MANIFEST_SYNC; + } else { + dfu->bState = STATE_DFU_MANIFEST_WAIT_RESET; + + /* lock the internal flash */ + dfu_mal_deinit(); + + /* generate system reset to allow jumping to the user code */ + NVIC_SystemReset(); + } +} + +/*! + \brief handle data IN stage in control endpoint 0 + \param[in] udev: pointer to usb device instance + \param[out] none + \retval usb device operation status + */ +static uint8_t dfu_getstatus_complete (usb_dev *udev) +{ + uint32_t addr; + + usbd_dfu_handler *dfu = (usbd_dfu_handler *)udev->dev.class_data[USBD_DFU_INTERFACE]; + + if (STATE_DFU_DNBUSY == dfu->bState) { + /* decode the special command */ + if (0U == dfu->block_num) { + if (1U == dfu->data_len){ + if (GET_COMMANDS == dfu->buf[0]) { + /* no operation */ + } + } else if (5U == dfu->data_len) { + if (SET_ADDRESS_POINTER == dfu->buf[0]) { + /* set flash operation address */ + dfu->base_addr = *(uint32_t *)(dfu->buf + 1U); + } else if (ERASE == dfu->buf[0]) { + dfu->base_addr = *(uint32_t *)(dfu->buf + 1U); + + dfu_mal_erase(dfu->base_addr); + } else { + /* no operation */ + } + } else { + /* no operation */ + } + } else if (dfu->block_num > 1U) { /* regular download command */ + /* decode the required address */ + addr = (dfu->block_num - 2U) * TRANSFER_SIZE + dfu->base_addr; + + dfu_mal_write (dfu->buf, addr, dfu->data_len); + + dfu->block_num = 0U; + } else { + /* no operation */ + } + + dfu->data_len = 0U; + + /* update the device state and poll timeout */ + dfu->bState = STATE_DFU_DNLOAD_SYNC; + + return USBD_OK; + } else if (dfu->bState == STATE_DFU_MANIFEST) { /* manifestation in progress */ + /* start leaving DFU mode */ + dfu_mode_leave(udev); + } else { + /* no operation */ + } + + return USBD_OK; +} + +/*! + \brief handle the DFU_DETACH request + \param[in] udev: pointer to usb device instance + \param[in] req: DFU class request + \param[out] none + \retval none. +*/ +static void dfu_detach(usb_dev *udev, usb_req *req) +{ + usbd_dfu_handler *dfu = (usbd_dfu_handler *)udev->dev.class_data[USBD_DFU_INTERFACE]; + + switch (dfu->bState) { + case STATE_DFU_IDLE: + case STATE_DFU_DNLOAD_SYNC: + case STATE_DFU_DNLOAD_IDLE: + case STATE_DFU_MANIFEST_SYNC: + case STATE_DFU_UPLOAD_IDLE: + dfu->bStatus = STATUS_OK; + dfu->bState = STATE_DFU_IDLE; + dfu->iString = 0U; /* iString */ + + dfu->block_num = 0U; + dfu->data_len = 0U; + break; + + default: + break; + } + + /* check the detach capability in the DFU functional descriptor */ + if (dfu_config_desc.dfu_func.wDetachTimeOut & DFU_DETACH_MASK) { + usbd_disconnect (udev); + + usbd_connect (udev); + } else { + /* wait for the period of time specified in detach request */ + usb_mdelay (4U); + } +} + +/*! + \brief handle the DFU_DNLOAD request + \param[in] udev: pointer to usb device instance + \param[in] req: DFU class request + \param[out] none + \retval none +*/ +static void dfu_dnload(usb_dev *udev, usb_req *req) +{ + usb_transc *transc = &udev->dev.transc_out[0]; + usbd_dfu_handler *dfu = (usbd_dfu_handler *)udev->dev.class_data[USBD_DFU_INTERFACE]; + + switch (dfu->bState) { + case STATE_DFU_IDLE: + case STATE_DFU_DNLOAD_IDLE: + if (req->wLength > 0U) { + /* update the global length and block number */ + dfu->block_num = req->wValue; + dfu->data_len = req->wLength; + + dfu->bState = STATE_DFU_DNLOAD_SYNC; + + transc->remain_len = dfu->data_len; + transc->xfer_buf = dfu->buf; + } else { + dfu->manifest_state = MANIFEST_IN_PROGRESS; + dfu->bState = STATE_DFU_MANIFEST_SYNC; + } + break; + + default: + break; + } +} + +/*! + \brief handles the DFU UPLOAD request. + \param[in] udev: pointer to usb device instance + \param[in] req: DFU class request + \param[out] none + \retval none +*/ +static void dfu_upload (usb_dev *udev, usb_req *req) +{ + uint8_t *phy_addr = NULL; + uint32_t addr = 0U; + usbd_dfu_handler *dfu = (usbd_dfu_handler *)udev->dev.class_data[USBD_DFU_INTERFACE]; + + usb_transc *transc = &udev->dev.transc_in[0]; + + if(req->wLength <= 0U) { + dfu->bState = STATE_DFU_IDLE; + return; + } + + switch (dfu->bState) { + case STATE_DFU_IDLE: + case STATE_DFU_UPLOAD_IDLE: + /* update the global length and block number */ + dfu->block_num = req->wValue; + dfu->data_len = req->wLength; + + /* DFU get command */ + if (0U == dfu->block_num) { + /* update the state machine */ + dfu->bState = (dfu->data_len > 3U) ? STATE_DFU_IDLE : STATE_DFU_UPLOAD_IDLE; + + /* store the values of all supported commands */ + dfu->buf[0] = GET_COMMANDS; + dfu->buf[1] = SET_ADDRESS_POINTER; + dfu->buf[2] = ERASE; + + /* send the status data over EP0 */ + transc->xfer_buf = &(dfu->buf[0]); + transc->remain_len = 3U; + } else if (dfu->block_num > 1U) { + dfu->bState = STATE_DFU_UPLOAD_IDLE; + + /* change is accelerated */ + addr = (dfu->block_num - 2U) * TRANSFER_SIZE + dfu->base_addr; + + /* return the physical address where data are stored */ + phy_addr = dfu_mal_read (dfu->buf, addr, dfu->data_len); + + /* send the status data over EP0 */ + transc->xfer_buf = phy_addr; + transc->remain_len = dfu->data_len; + } else { + dfu->bState = STATUS_ERR_STALLEDPKT; + } + break; + + default: + dfu->data_len = 0U; + dfu->block_num = 0U; + break; + } +} + +/*! + \brief handle the DFU_GETSTATUS request + \param[in] udev: pointer to usb device instance + \param[in] req: DFU class request + \param[out] none + \retval none +*/ +static void dfu_getstatus (usb_dev *udev, usb_req *req) +{ + usbd_dfu_handler *dfu = (usbd_dfu_handler *)udev->dev.class_data[USBD_DFU_INTERFACE]; + + usb_transc *transc = &udev->dev.transc_in[0]; + + switch (dfu->bState) { + case STATE_DFU_DNLOAD_SYNC: + if (0U != dfu->data_len) { + dfu->bState = STATE_DFU_DNBUSY; + + if (0U == dfu->block_num) { + if (ERASE == dfu->buf[0]) { + dfu_mal_getstatus (dfu->base_addr, CMD_ERASE, (uint8_t *)&dfu->bwPollTimeout0); + } else { + dfu_mal_getstatus (dfu->base_addr, CMD_WRITE, (uint8_t *)&dfu->bwPollTimeout0); + } + } + } else { + dfu->bState = STATE_DFU_DNLOAD_IDLE; + } + break; + + case STATE_DFU_MANIFEST_SYNC: + if (MANIFEST_IN_PROGRESS == dfu->manifest_state) { + dfu->bState = STATE_DFU_MANIFEST; + dfu->bwPollTimeout0 = 1U; + } else if ((MANIFEST_COMPLETE == dfu->manifest_state) && \ + (dfu_config_desc.dfu_func.bmAttributes & 0x04U)){ + dfu->bState = STATE_DFU_IDLE; + dfu->bwPollTimeout0 = 0U; + } else { + /* no operation */ + } + break; + + default: + break; + } + + /* send the status data of DFU interface to host over EP0 */ + transc->xfer_buf = (uint8_t *)&(dfu->bStatus); + transc->remain_len = 6U; +} + +/*! + \brief handle the DFU_CLRSTATUS request + \param udev: pointer to usb device instance + \param[out] none + \retval none +*/ +static void dfu_clrstatus (usb_dev *udev, usb_req *req) +{ + usbd_dfu_handler *dfu = (usbd_dfu_handler *)udev->dev.class_data[USBD_DFU_INTERFACE]; + + if (STATE_DFU_ERROR == dfu->bState) { + dfu->bStatus = STATUS_OK; + dfu->bState = STATE_DFU_IDLE; + } else { + /* state error */ + dfu->bStatus = STATUS_ERR_UNKNOWN; + dfu->bState = STATE_DFU_ERROR; + } + + dfu->iString = 0U; /* iString: index = 0 */ +} + +/*! + \brief handle the DFU_GETSTATE request + \param[in] udev: pointer to usb device instance + \param[out] none + \retval none +*/ +static void dfu_getstate (usb_dev *udev, usb_req *req) +{ + usbd_dfu_handler *dfu = (usbd_dfu_handler *)udev->dev.class_data[USBD_DFU_INTERFACE]; + + usb_transc *transc = &udev->dev.transc_in[0]; + + /* send the current state of the DFU interface to host */ + transc->xfer_buf = &(dfu->bState); + transc->remain_len = 1U; +} + +/*! + \brief handle the DFU_ABORT request + \param[in] udev: pointer to usb device instance + \param[out] none + \retval none +*/ +static void dfu_abort (usb_dev *udev, usb_req *req) +{ + usbd_dfu_handler *dfu = (usbd_dfu_handler *)udev->dev.class_data[USBD_DFU_INTERFACE]; + + switch (dfu->bState){ + case STATE_DFU_IDLE: + case STATE_DFU_DNLOAD_SYNC: + case STATE_DFU_DNLOAD_IDLE: + case STATE_DFU_MANIFEST_SYNC: + case STATE_DFU_UPLOAD_IDLE: + dfu->bStatus = STATUS_OK; + dfu->bState = STATE_DFU_IDLE; + dfu->iString = 0U; /* iString: index = 0 */ + + dfu->block_num = 0U; + dfu->data_len = 0U; + break; + + default: + break; + } +} diff --git a/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/device/class/dfu/Source/dfu_mal.c b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/device/class/dfu/Source/dfu_mal.c new file mode 100644 index 0000000000..1333ca86b7 --- /dev/null +++ b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/device/class/dfu/Source/dfu_mal.c @@ -0,0 +1,233 @@ +/*! + \file dfu_mal.c + \brief USB DFU device media access layer functions + + \version 2020-08-01, V3.0.0, firmware for GD32F30x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "dfu_mal.h" +#include "flash_if.h" +#include "drv_usb_hw.h" +#include "usbd_transc.h" + +extern usb_core_driver usb_dfu_dev; + +extern struct { + uint8_t buf[TRANSFER_SIZE]; + uint16_t data_len; + uint16_t block_num; + uint32_t base_addr; +} prog; + +dfu_mal_prop* tMALTab[MAX_USED_MEMORY_MEDIA] = { + &DFU_Flash_cb +}; + +/* The list of memory interface string descriptor pointers. This list + can be updated whenever a memory has to be added or removed */ +const uint8_t* USBD_DFU_StringDesc[MAX_USED_MEMORY_MEDIA] = +{ + (const uint8_t *)FLASH_IF_STRING +}; + +static uint8_t dfu_mal_checkaddr (uint32_t addr); + +/*! + \brief initialize the memory media on the GD32 + \param[in] none + \param[out] none + \retval MAL_OK +*/ +uint8_t dfu_mal_init (void) +{ + uint32_t mem_index = 0U; + + /* initialize all supported memory medias */ + for (mem_index = 0U; mem_index < MAX_USED_MEMORY_MEDIA; mem_index++) { + /* check if the memory media exists */ + if (NULL != tMALTab[mem_index]->mal_init) { + tMALTab[mem_index]->mal_init(); + } + } + + return MAL_OK; +} + +/*! + \brief deinitialize the memory media on the GD32 + \param[in] none + \param[out] none + \retval MAL_OK +*/ +uint8_t dfu_mal_deinit (void) +{ + uint32_t mem_index = 0U; + + /* deinitializes all supported memory medias */ + for (mem_index = 0U; mem_index < MAX_USED_MEMORY_MEDIA; mem_index++) { + /* check if the memory media exists */ + if (NULL != tMALTab[mem_index]->mal_deinit) { + tMALTab[mem_index]->mal_deinit(); + } + } + + return MAL_OK; +} + +/*! + \brief erase a memory sector + \param[in] addr: memory sector address/code + \param[out] none + \retval MAL_OK +*/ +uint8_t dfu_mal_erase (uint32_t addr) +{ + uint32_t mem_index = dfu_mal_checkaddr(addr); + + /* check if the address is in protected area */ + if (IS_PROTECTED_AREA(addr)) { + return MAL_FAIL; + } + + if (mem_index < MAX_USED_MEMORY_MEDIA) { + /* check if the operation is supported */ + if (NULL != tMALTab[mem_index]->mal_erase) { + return tMALTab[mem_index]->mal_erase(addr); + } else { + return MAL_FAIL; + } + } else { + return MAL_FAIL; + } +} + +/*! + \brief write data to sectors of memory + \param[in] buf: the data buffer to be write + \param[in] addr: memory sector address/code + \param[in] len: data length + \param[out] none + \retval MAL_OK +*/ +uint8_t dfu_mal_write (uint8_t *buf, uint32_t addr, uint32_t len) +{ + uint32_t mem_index = dfu_mal_checkaddr(addr); + + /* check if the address is in protected area */ + if (IS_PROTECTED_AREA(addr)) { + return MAL_FAIL; + } + + if (mem_index < MAX_USED_MEMORY_MEDIA) { + /* check if the operation is supported */ + if (NULL != tMALTab[mem_index]->mal_write) { + return tMALTab[mem_index]->mal_write(buf, addr, len); + } else { + return MAL_FAIL; + } + } else { + return MAL_FAIL; + } +} + +/*! + \brief read data from sectors of memory + \param[in] buf: the data buffer to be write + \param[in] addr: memory sector address/code + \param[in] len: data length + \param[out] none + \retval pointer to buffer +*/ +uint8_t* dfu_mal_read (uint8_t *buf, uint32_t addr, uint32_t len) +{ + uint32_t mem_index = 0U; + + if (OB_RDPT != addr) { + mem_index = dfu_mal_checkaddr(addr); + } + + if (mem_index < MAX_USED_MEMORY_MEDIA) { + /* check if the operation is supported */ + if (NULL != tMALTab[mem_index]->mal_read) { + return tMALTab[mem_index]->mal_read(buf, addr, len); + } else { + return buf; + } + } else { + return buf; + } +} + +/*! + \brief get the status of a given memory and store in buffer + \param[in] addr: memory sector address/code + \param[in] cmd: 0 for erase and 1 for write + \param[in] buffer: pointer to the buffer where the status data will be stored + \param[out] none + \retval MAL_OK if all operations are OK, MAL_FAIL else +*/ +uint8_t dfu_mal_getstatus (uint32_t addr, uint8_t cmd, uint8_t *buffer) +{ + uint32_t mem_index = dfu_mal_checkaddr(addr); + + if (mem_index < MAX_USED_MEMORY_MEDIA) { + if (cmd & 0x01U) { + SET_POLLING_TIMEOUT(tMALTab[mem_index]->write_timeout); + } else { + SET_POLLING_TIMEOUT(tMALTab[mem_index]->erase_timeout); + } + + return MAL_OK; + } else { + return MAL_FAIL; + } +} + +/*! + \brief check the address is supported + \param[in] addr: memory sector address/code + \param[out] none + \retval index of the addressed memory +*/ +static uint8_t dfu_mal_checkaddr (uint32_t addr) +{ + uint8_t mem_index = 0U; + + /* check with all supported memories */ + for (mem_index = 0U; mem_index < MAX_USED_MEMORY_MEDIA; mem_index++) { + /* if the check address is supported, return the memory index */ + if (MAL_OK == tMALTab[mem_index]->mal_checkaddr(addr)) { + return mem_index; + } + } + + /* if there is no memory found, return MAX_USED_MEMORY_MEDIA */ + return (MAX_USED_MEMORY_MEDIA); +} diff --git a/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/device/class/hid/Include/custom_hid_core.h b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/device/class/hid/Include/custom_hid_core.h new file mode 100644 index 0000000000..b7aa7d98dd --- /dev/null +++ b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/device/class/hid/Include/custom_hid_core.h @@ -0,0 +1,69 @@ +/*! + \file custom_hid_core.h + \brief definitions for HID core + + \version 2020-08-01, V3.0.0, firmware for GD32F30x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef __CUSTOM_HID_CORE_H +#define __CUSTOM_HID_CORE_H + +#include "usbd_enum.h" +#include "usb_hid.h" + +#define DESC_LEN_REPORT 96U +#define DESC_LEN_CONFIG 41U + +#define NO_CMD 0xFFU + +#define MAX_PERIPH_NUM 4U + +typedef struct { + uint8_t data[2]; + + uint8_t reportID; + uint8_t idlestate; + uint8_t protocol; +} custom_hid_handler; + +typedef struct { + void (*periph_config[MAX_PERIPH_NUM])(void); +} hid_fop_handler; + +extern usb_desc custom_hid_desc; +extern usb_class_core usbd_custom_hid_cb; + +/* function declarations */ +/* register HID interface operation functions */ +uint8_t custom_hid_itfop_register (usb_dev *udev, hid_fop_handler *hid_fop); +/* send custom HID report */ +uint8_t custom_hid_report_send (usb_dev *udev, uint8_t *report, uint32_t len); + +#endif /* __CUSTOM_HID_CORE_H */ diff --git a/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/device/class/hid/Include/standard_hid_core.h b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/device/class/hid/Include/standard_hid_core.h new file mode 100644 index 0000000000..cbec412a86 --- /dev/null +++ b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/device/class/hid/Include/standard_hid_core.h @@ -0,0 +1,68 @@ +/*! + \file standard_hid_core.h + \brief definitions for HID core + + \version 2020-08-01, V3.0.0, firmware for GD32F30x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef __STANDARD_HID_CORE_H +#define __STANDARD_HID_CORE_H + +#include "usbd_enum.h" +#include "usb_hid.h" + +#define USB_HID_CONFIG_DESC_LEN 0x22U +#define USB_HID_REPORT_DESC_LEN 0x2EU + +#define NO_CMD 0xFFU + +typedef struct { + uint32_t protocol; + uint32_t idle_state; + + uint8_t data[HID_IN_PACKET]; + __IO uint8_t prev_transfer_complete; +} standard_hid_handler; + +typedef struct { + void (*hid_itf_config) (void); + void (*hid_itf_data_process) (usb_dev *udev); +} hid_fop_handler; + +extern usb_desc hid_desc; +extern usb_class_core usbd_hid_cb; + +/* function declarations */ +/* register HID interface operation functions */ +uint8_t hid_itfop_register (usb_dev *udev, hid_fop_handler *hid_fop); +/* send keyboard report */ +uint8_t hid_report_send (usb_dev *pudev, uint8_t *report, uint32_t len); + +#endif /* __STANDARD_HID_CORE_H */ diff --git a/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/device/class/hid/Source/custom_hid_core.c b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/device/class/hid/Source/custom_hid_core.c new file mode 100644 index 0000000000..bc499cadf2 --- /dev/null +++ b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/device/class/hid/Source/custom_hid_core.c @@ -0,0 +1,488 @@ +/*! + \file custom_hid_core.c + \brief custom HID class driver + + \version 2020-08-01, V3.0.0, firmware for GD32F30x + \version 2020-12-07, V3.0.1, firmware for GD32F30x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "custom_hid_core.h" +#include "usbd_enum.h" +#include + +#define USBD_VID 0x28E9U +#define USBD_PID 0x028AU + +/* Note:it should use the C99 standard when compiling the below codes */ +/* USB standard device descriptor */ +const usb_desc_dev custom_hid_dev_desc = +{ + .header = + { + .bLength = USB_DEV_DESC_LEN, + .bDescriptorType = USB_DESCTYPE_DEV, + }, + .bcdUSB = 0x0200U, + .bDeviceClass = 0x00U, + .bDeviceSubClass = 0x00U, + .bDeviceProtocol = 0x00U, + .bMaxPacketSize0 = USB_FS_EP0_MAX_LEN, + .idVendor = USBD_VID, + .idProduct = USBD_PID, + .bcdDevice = 0x0100U, + .iManufacturer = STR_IDX_MFC, + .iProduct = STR_IDX_PRODUCT, + .iSerialNumber = STR_IDX_SERIAL, + .bNumberConfigurations = USBD_CFG_MAX_NUM, +}; + +/* USB device configuration descriptor */ +const usb_hid_desc_config_set custom_hid_config_desc = +{ + .config = + { + .header = + { + .bLength = sizeof(usb_desc_config), + .bDescriptorType = USB_DESCTYPE_CONFIG + }, + .wTotalLength = DESC_LEN_CONFIG, + .bNumInterfaces = 0x01U, + .bConfigurationValue = 0x01U, + .iConfiguration = 0x00U, + .bmAttributes = 0x80U, + .bMaxPower = 0x32U + }, + + .hid_itf = + { + .header = + { + .bLength = sizeof(usb_desc_itf), + .bDescriptorType = USB_DESCTYPE_ITF + }, + .bInterfaceNumber = 0x00U, + .bAlternateSetting = 0x00U, + .bNumEndpoints = 0x02U, + .bInterfaceClass = USB_HID_CLASS, + .bInterfaceSubClass = 0x00U, + .bInterfaceProtocol = 0x00U, + .iInterface = 0x00U + }, + + .hid_vendor = + { + .header = + { + .bLength = sizeof(usb_desc_hid), + .bDescriptorType = USB_DESCTYPE_HID + }, + .bcdHID = 0x0111U, + .bCountryCode = 0x00U, + .bNumDescriptors = 0x01U, + .bDescriptorType = USB_DESCTYPE_REPORT, + .wDescriptorLength = DESC_LEN_REPORT, + }, + + .hid_epin = + { + .header = + { + .bLength = sizeof(usb_desc_ep), + .bDescriptorType = USB_DESCTYPE_EP + }, + .bEndpointAddress = CUSTOMHID_IN_EP, + .bmAttributes = USB_EP_ATTR_INT, + .wMaxPacketSize = CUSTOMHID_IN_PACKET, + .bInterval = 0x20U + }, + + .hid_epout = + { + .header = + { + .bLength = sizeof(usb_desc_ep), + .bDescriptorType = USB_DESCTYPE_EP + }, + .bEndpointAddress = CUSTOMHID_OUT_EP, + .bmAttributes = USB_EP_ATTR_INT, + .wMaxPacketSize = CUSTOMHID_OUT_PACKET, + .bInterval = 0x20U + } +}; + +/* USB language ID descriptor */ +static const usb_desc_LANGID usbd_language_id_desc = +{ + .header = + { + .bLength = sizeof(usb_desc_LANGID), + .bDescriptorType = USB_DESCTYPE_STR + }, + .wLANGID = ENG_LANGID +}; + +/* USB manufacture string */ +static const usb_desc_str manufacturer_string = +{ + .header = + { + .bLength = USB_STRING_LEN(10U), + .bDescriptorType = USB_DESCTYPE_STR, + }, + .unicode_string = {'G', 'i', 'g', 'a', 'D', 'e', 'v', 'i', 'c', 'e'} +}; + +/* USB product string */ +static const usb_desc_str product_string = +{ + .header = + { + .bLength = USB_STRING_LEN(14U), + .bDescriptorType = USB_DESCTYPE_STR, + }, + .unicode_string = {'G', 'D', '3', '2', '-', 'C', 'u', 's', 't', 'o', 'm', 'H', 'I', 'D'} +}; + +/* USBD serial string */ +static usb_desc_str serial_string = +{ + .header = + { + .bLength = USB_STRING_LEN(12U), + .bDescriptorType = USB_DESCTYPE_STR, + } +}; + +/* USB string descriptor set */ +void *const usbd_hid_strings[] = +{ + [STR_IDX_LANGID] = (uint8_t *)&usbd_language_id_desc, + [STR_IDX_MFC] = (uint8_t *)&manufacturer_string, + [STR_IDX_PRODUCT] = (uint8_t *)&product_string, + [STR_IDX_SERIAL] = (uint8_t *)&serial_string +}; + +usb_desc custom_hid_desc = { + .dev_desc = (uint8_t *)&custom_hid_dev_desc, + .config_desc = (uint8_t *)&custom_hid_config_desc, + .strings = usbd_hid_strings +}; + +const uint8_t customhid_report_descriptor[DESC_LEN_REPORT] = +{ + 0x06, 0x00, 0xFF, /* USAGE_PAGE (Vendor Defined: 0xFF00) */ + 0x09, 0x00, /* USAGE (Custom Device) */ + 0xa1, 0x01, /* COLLECTION (Application) */ + + /* led 1 */ + 0x85, 0x11, /* REPORT_ID (0x11) */ + 0x09, 0x01, /* USAGE (LED 1) */ + 0x15, 0x00, /* LOGICAL_MINIMUM (0) */ + 0x25, 0x01, /* LOGICAL_MAXIMUM (1) */ + 0x75, 0x08, /* REPORT_SIZE (8) */ + 0x95, 0x01, /* REPORT_COUNT (1) */ + 0x91, 0x82, /* OUTPUT (Data,Var,Abs,Vol) */ + + /* led 2 */ + 0x85, 0x12, /* REPORT_ID (0x12) */ + 0x09, 0x02, /* USAGE (LED 2) */ + 0x15, 0x00, /* LOGICAL_MINIMUM (0) */ + 0x25, 0x01, /* LOGICAL_MAXIMUM (1) */ + 0x75, 0x08, /* REPORT_SIZE (8) */ + 0x95, 0x01, /* REPORT_COUNT (1) */ + 0x91, 0x82, /* OUTPUT (Data,Var,Abs,Vol) */ + + /* led 3 */ + 0x85, 0x13, /* REPORT_ID (0x13) */ + 0x09, 0x03, /* USAGE (LED 3) */ + 0x15, 0x00, /* LOGICAL_MINIMUM (0) */ + 0x25, 0x01, /* LOGICAL_MAXIMUM (1) */ + 0x75, 0x08, /* REPORT_SIZE (8) */ + 0x95, 0x01, /* REPORT_COUNT (1) */ + 0x91, 0x82, /* OUTPUT (Data,Var,Abs,Vol) */ + + /* led 4 */ + 0x85, 0x14, /* REPORT_ID (0x14) */ + 0x09, 0x04, /* USAGE (LED 4) */ + 0x15, 0x00, /* LOGICAL_MINIMUM (0) */ + 0x25, 0x01, /* LOGICAL_MAXIMUM (1) */ + 0x75, 0x08, /* REPORT_SIZE (8) */ + 0x95, 0x01, /* REPORT_COUNT (1) */ + 0x91, 0x82, /* OUTPUT (Data,Var,Abs,Vol) */ + + /* wakeup key */ + 0x85, 0x15, /* REPORT_ID (0x15) */ + 0x09, 0x05, /* USAGE (Push Button) */ + 0x15, 0x00, /* LOGICAL_MINIMUM (0) */ + 0x25, 0x01, /* LOGICAL_MAXIMUM (1) */ + 0x75, 0x01, /* REPORT_SIZE (1) */ + 0x81, 0x02, /* INPUT (Data,Var,Abs,Vol) */ + + 0x75, 0x07, /* REPORT_SIZE (7) */ + 0x81, 0x03, /* INPUT (Cnst,Var,Abs,Vol) */ + + /* tamper key */ + 0x85, 0x16, /* REPORT_ID (0x16) */ + 0x09, 0x06, /* USAGE (Push Button) */ + 0x15, 0x00, /* LOGICAL_MINIMUM (0) */ + 0x25, 0x01, /* LOGICAL_MAXIMUM (1) */ + 0x75, 0x01, /* REPORT_SIZE (1) */ + 0x81, 0x02, /* INPUT (Data,Var,Abs,Vol) */ + + 0x75, 0x07, /* REPORT_SIZE (7) */ + 0x81, 0x03, /* INPUT (Cnst,Var,Abs,Vol) */ + + 0xc0 /* END_COLLECTION */ +}; + +/* local function prototypes ('static') */ +static uint8_t custom_hid_init (usb_dev *udev, uint8_t config_index); +static uint8_t custom_hid_deinit (usb_dev *udev, uint8_t config_index); +static uint8_t custom_hid_req_handler (usb_dev *udev, usb_req *req); +static uint8_t custom_hid_data_in (usb_dev *udev, uint8_t ep_num); +static uint8_t custom_hid_data_out (usb_dev *udev, uint8_t ep_num); + +usb_class_core usbd_custom_hid_cb = +{ + .command = NO_CMD, + .alter_set = 0U, + + .init = custom_hid_init, + .deinit = custom_hid_deinit, + + .req_proc = custom_hid_req_handler, + + .data_in = custom_hid_data_in, + .data_out = custom_hid_data_out +}; + +/*! + \brief register HID interface operation functions + \param[in] udev: pointer to USB device instance + \param[in] hid_fop: HID operation functions structure + \param[out] none + \retval USB device operation status +*/ +uint8_t custom_hid_itfop_register (usb_dev *udev, hid_fop_handler *hid_fop) +{ + if (NULL != hid_fop) { + udev->dev.user_data = hid_fop; + + return USBD_OK; + } + + return USBD_FAIL; +} + +/*! + \brief send custom HID report + \param[in] udev: pointer to USB device instance + \param[in] report: pointer to HID report + \param[in] len: data length + \param[out] none + \retval USB device operation status +*/ +uint8_t custom_hid_report_send (usb_dev *udev, uint8_t *report, uint32_t len) +{ + usbd_ep_send (udev, CUSTOMHID_IN_EP, report, len); + + return USBD_OK; +} + +/*! + \brief initialize the HID device + \param[in] udev: pointer to USB device instance + \param[in] config_index: configuration index + \param[out] none + \retval USB device operation status +*/ +static uint8_t custom_hid_init (usb_dev *udev, uint8_t config_index) +{ + static custom_hid_handler hid_handler; + + memset((void *)&hid_handler, 0U, sizeof(custom_hid_handler)); + + /* Initialize the data Tx endpoint */ + usbd_ep_setup (udev, &(custom_hid_config_desc.hid_epin)); + + /* Initialize the data Rx endpoint */ + usbd_ep_setup (udev, &(custom_hid_config_desc.hid_epout)); + + /* prepare receive data */ + usbd_ep_recev (udev, CUSTOMHID_OUT_EP, hid_handler.data, 2U); + + udev->dev.class_data[CUSTOM_HID_INTERFACE] = (void *)&hid_handler; + + if (udev->dev.user_data != NULL) { + for (uint8_t i = 0U; i < MAX_PERIPH_NUM; i++) { + if (((hid_fop_handler *)udev->dev.user_data)->periph_config[i] != NULL) { + ((hid_fop_handler *)udev->dev.user_data)->periph_config[i](); + } + } + } + + return USBD_OK; +} + +/*! + \brief de-initialize the HID device + \param[in] udev: pointer to USB device instance + \param[in] config_index: configuration index + \param[out] none + \retval USB device operation status +*/ +static uint8_t custom_hid_deinit (usb_dev *udev, uint8_t config_index) +{ + /* deinitialize HID endpoints */ + usbd_ep_clear(udev, CUSTOMHID_IN_EP); + usbd_ep_clear(udev, CUSTOMHID_OUT_EP); + + return USBD_OK; +} + +/*! + \brief handle the HID class-specific requests + \param[in] udev: pointer to USB device instance + \param[in] req: device class-specific request + \param[out] none + \retval USB device operation status +*/ +static uint8_t custom_hid_req_handler (usb_dev *udev, usb_req *req) +{ + usb_transc *transc = &udev->dev.transc_in[0]; + + custom_hid_handler *hid = (custom_hid_handler *)udev->dev.class_data[CUSTOM_HID_INTERFACE]; + + switch (req->bRequest) { + case GET_REPORT: + break; + + case GET_IDLE: + transc->xfer_buf = (uint8_t *)&hid->idlestate; + transc->remain_len = 1U; + break; + + case GET_PROTOCOL: + transc->xfer_buf = (uint8_t *)&hid->protocol; + transc->remain_len = 1U; + break; + + case SET_REPORT: + hid->reportID = (uint8_t)(req->wValue); + break; + + case SET_IDLE: + hid->idlestate = (uint8_t)(req->wValue >> 8U); + break; + + case SET_PROTOCOL: + hid->protocol = (uint8_t)(req->wValue); + break; + + case USB_GET_DESCRIPTOR: + if (USB_DESCTYPE_REPORT == (req->wValue >> 8U)) { + transc->remain_len = USB_MIN(DESC_LEN_REPORT, req->wLength); + transc->xfer_buf = (uint8_t *)customhid_report_descriptor; + } + break; + + default: + return USBD_FAIL; + } + + return USBD_OK; +} + +/*! + \brief handle custom HID data + \param[in] udev: pointer to USB device instance + \param[in] ep_num: endpoint identifier + \param[out] none + \retval USB device operation status +*/ +static uint8_t custom_hid_data_in (usb_dev *udev, uint8_t ep_num) +{ + return USBD_OK; +} + +/*! + \brief handle custom HID data + \param[in] udev: pointer to USB device instance + \param[in] ep_num: endpoint identifier + \param[out] none + \retval USB device operation status +*/ +static uint8_t custom_hid_data_out (usb_dev *udev, uint8_t ep_num) +{ + custom_hid_handler *hid = (custom_hid_handler *)udev->dev.class_data[CUSTOM_HID_INTERFACE]; + + switch (hid->data[0]){ + case 0x11U: + if (RESET != hid->data[1]) { + gd_eval_led_on(LED5); + } else { + gd_eval_led_off(LED5); + } + break; + + case 0x12U: + if (RESET != hid->data[1]) { + gd_eval_led_on(LED2); + } else { + gd_eval_led_off(LED2); + } + break; + + case 0x13U: + if (RESET != hid->data[1]) { + gd_eval_led_on(LED3); + } else { + gd_eval_led_off(LED3); + } + break; + + case 0x14U: + if (RESET != hid->data[1]) { + gd_eval_led_on(LED4); + } else { + gd_eval_led_off(LED4); + } + break; + + + default: + break; + } + + usbd_ep_recev (udev, CUSTOMHID_IN_EP, hid->data, 2U); + + return USBD_OK; +} diff --git a/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/device/class/hid/Source/standard_hid_core.c b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/device/class/hid/Source/standard_hid_core.c new file mode 100644 index 0000000000..e78782611f --- /dev/null +++ b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/device/class/hid/Source/standard_hid_core.c @@ -0,0 +1,389 @@ +/*! + \file standard_hid_core.c + \brief HID class driver + + \version 2020-08-01, V3.0.0, firmware for GD32F30x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "standard_hid_core.h" +#include + +#define USBD_VID 0x28e9U +#define USBD_PID 0x0380U + +/* Note:it should use the C99 standard when compiling the below codes */ +/* USB standard device descriptor */ +const usb_desc_dev hid_dev_desc = +{ + .header = + { + .bLength = USB_DEV_DESC_LEN, + .bDescriptorType = USB_DESCTYPE_DEV + }, + .bcdUSB = 0x0200U, + .bDeviceClass = 0x00U, + .bDeviceSubClass = 0x00U, + .bDeviceProtocol = 0x00U, + .bMaxPacketSize0 = USB_FS_EP0_MAX_LEN, + .idVendor = USBD_VID, + .idProduct = USBD_PID, + .bcdDevice = 0x0100U, + .iManufacturer = STR_IDX_MFC, + .iProduct = STR_IDX_PRODUCT, + .iSerialNumber = STR_IDX_SERIAL, + .bNumberConfigurations = USBD_CFG_MAX_NUM +}; + +const usb_hid_desc_config_set hid_config_desc = +{ + .config = + { + .header = + { + .bLength = sizeof(usb_desc_config), + .bDescriptorType = USB_DESCTYPE_CONFIG + }, + .wTotalLength = USB_HID_CONFIG_DESC_LEN, + .bNumInterfaces = 0x01U, + .bConfigurationValue = 0x01U, + .iConfiguration = 0x00U, + .bmAttributes = 0xA0U, + .bMaxPower = 0x32U + }, + + .hid_itf = + { + .header = + { + .bLength = sizeof(usb_desc_itf), + .bDescriptorType = USB_DESCTYPE_ITF + }, + .bInterfaceNumber = 0x00U, + .bAlternateSetting = 0x00U, + .bNumEndpoints = 0x01U, + .bInterfaceClass = USB_HID_CLASS, + .bInterfaceSubClass = USB_HID_SUBCLASS_BOOT_ITF, + .bInterfaceProtocol = USB_HID_PROTOCOL_KEYBOARD, + .iInterface = 0x00U + }, + + .hid_vendor = + { + .header = + { + .bLength = sizeof(usb_desc_hid), + .bDescriptorType = USB_DESCTYPE_HID + }, + .bcdHID = 0x0111U, + .bCountryCode = 0x00U, + .bNumDescriptors = 0x01U, + .bDescriptorType = USB_DESCTYPE_REPORT, + .wDescriptorLength = USB_HID_REPORT_DESC_LEN, + }, + + .hid_epin = + { + .header = + { + .bLength = sizeof(usb_desc_ep), + .bDescriptorType = USB_DESCTYPE_EP + }, + .bEndpointAddress = HID_IN_EP, + .bmAttributes = USB_EP_ATTR_INT, + .wMaxPacketSize = HID_IN_PACKET, + .bInterval = 0x40U + } +}; + +/* USB language ID Descriptor */ +const usb_desc_LANGID usbd_language_id_desc = +{ + .header = + { + .bLength = sizeof(usb_desc_LANGID), + .bDescriptorType = USB_DESCTYPE_STR + }, + .wLANGID = ENG_LANGID +}; + +/* USB manufacture string */ +static const usb_desc_str manufacturer_string = +{ + .header = + { + .bLength = USB_STRING_LEN(10U), + .bDescriptorType = USB_DESCTYPE_STR, + }, + .unicode_string = {'G', 'i', 'g', 'a', 'D', 'e', 'v', 'i', 'c', 'e'} +}; + +/* USB product string */ +static const usb_desc_str product_string = +{ + .header = + { + .bLength = USB_STRING_LEN(17U), + .bDescriptorType = USB_DESCTYPE_STR, + }, + .unicode_string = {'G', 'D', '3', '2', '-','U', 'S', 'B', '_', 'K', 'e', 'y', 'b', 'o', 'a', 'r', 'd'} +}; + +/* USBD serial string */ +static usb_desc_str serial_string = +{ + .header = + { + .bLength = USB_STRING_LEN(12U), + .bDescriptorType = USB_DESCTYPE_STR, + } +}; + +void *const usbd_hid_strings[] = +{ + [STR_IDX_LANGID] = (uint8_t *)&usbd_language_id_desc, + [STR_IDX_MFC] = (uint8_t *)&manufacturer_string, + [STR_IDX_PRODUCT] = (uint8_t *)&product_string, + [STR_IDX_SERIAL] = (uint8_t *)&serial_string +}; + +usb_desc hid_desc = { + .dev_desc = (uint8_t *)&hid_dev_desc, + .config_desc = (uint8_t *)&hid_config_desc, + .strings = usbd_hid_strings +}; + +const uint8_t hid_report_desc[USB_HID_REPORT_DESC_LEN] = +{ + 0x05, 0x01, /* USAGE_PAGE (Generic Desktop) */ + 0x09, 0x06, /* USAGE (Keyboard) */ + 0xa1, 0x01, /* COLLECTION (Application) */ + + 0x05, 0x07, /* USAGE_PAGE (Keyboard/Keypad) */ + 0x19, 0xe0, /* USAGE_MINIMUM (Keyboard LeftControl) */ + 0x29, 0xe7, /* USAGE_MAXIMUM (Keyboard Right GUI) */ + 0x15, 0x00, /* LOGICAL_MINIMUM (0) */ + 0x25, 0x01, /* LOGICAL_MAXIMUM (1) */ + 0x95, 0x08, /* REPORT_COUNT (8) */ + 0x75, 0x01, /* REPORT_SIZE (1) */ + 0x81, 0x02, /* INPUT (Data,Var,Abs) */ + + 0x95, 0x01, /* REPORT_COUNT (1) */ + 0x75, 0x08, /* REPORT_SIZE (8) */ + 0x81, 0x03, /* INPUT (Cnst,Var,Abs) */ + + 0x95, 0x06, /* REPORT_COUNT (6) */ + 0x75, 0x08, /* REPORT_SIZE (8) */ + 0x15, 0x00, /* LOGICAL_MINIMUM (0) */ + 0x26, 0xFF, 0x00, /* LOGICAL_MAXIMUM (255) */ + 0x05, 0x07, /* USAGE_PAGE (Keyboard/Keypad) */ + 0x19, 0x00, /* USAGE_MINIMUM (Reserved (no event indicated)) */ + 0x29, 0x65, /* USAGE_MAXIMUM (Keyboard Application) */ + 0x81, 0x00, /* INPUT (Data,Ary,Abs) */ + + 0xc0 /* END_COLLECTION */ +}; + +/* local function prototypes ('static') */ +static uint8_t hid_init (usb_dev *udev, uint8_t config_index); +static uint8_t hid_deinit (usb_dev *udev, uint8_t config_index); +static uint8_t hid_req (usb_dev *udev, usb_req *req); +static uint8_t hid_data_in (usb_dev *udev, uint8_t ep_num); + +usb_class_core usbd_hid_cb = { + .command = NO_CMD, + .alter_set = 0U, + + .init = hid_init, + .deinit = hid_deinit, + .req_proc = hid_req, + .data_in = hid_data_in +}; + +/*! + \brief register HID interface operation functions + \param[in] udev: pointer to USB device instance + \param[in] hid_fop: HID operation functions structure + \param[out] none + \retval USB device operation status +*/ +uint8_t hid_itfop_register (usb_dev *udev, hid_fop_handler *hid_fop) +{ + if (NULL != hid_fop) { + udev->dev.user_data = (void *)hid_fop; + + return USBD_OK; + } + + return USBD_FAIL; +} + +/*! + \brief send keyboard report + \param[in] udev: pointer to USB device instance + \param[in] report: pointer to HID report + \param[in] len: data length + \param[out] none + \retval USB device operation status +*/ +uint8_t hid_report_send (usb_dev *udev, uint8_t *report, uint32_t len) +{ + standard_hid_handler *hid = (standard_hid_handler *)udev->dev.class_data[USBD_HID_INTERFACE]; + + hid->prev_transfer_complete = 0U; + + usbd_ep_send(udev, HID_IN_EP, report, len); + + return USBD_OK; +} + +/*! + \brief initialize the HID device + \param[in] udev: pointer to USB device instance + \param[in] config_index: configuration index + \param[out] none + \retval USB device operation status +*/ +static uint8_t hid_init (usb_dev *udev, uint8_t config_index) +{ + static standard_hid_handler hid_handler; + + memset((void *)&hid_handler, 0U, sizeof(standard_hid_handler)); + + /* Initialize the data Tx endpoint */ + usbd_ep_setup (udev, &(hid_config_desc.hid_epin)); + + hid_handler.prev_transfer_complete = 1U; + + udev->dev.class_data[USBD_HID_INTERFACE] = (void *)&hid_handler; + + if (NULL != udev->dev.user_data) { + ((hid_fop_handler *)udev->dev.user_data)->hid_itf_config(); + } + + return USBD_OK; +} + +/*! + \brief de-initialize the HID device + \param[in] udev: pointer to USB device instance + \param[in] config_index: configuration index + \param[out] none + \retval USB device operation status +*/ +static uint8_t hid_deinit (usb_dev *udev, uint8_t config_index) +{ + /* deinitialize HID endpoints */ + usbd_ep_clear(udev, HID_IN_EP); + + return USBD_OK; +} + +/*! + \brief handle the HID class-specific requests + \param[in] udev: pointer to USB device instance + \param[in] req: device class-specific request + \param[out] none + \retval USB device operation status +*/ +static uint8_t hid_req (usb_dev *udev, usb_req *req) +{ + usb_transc *transc = &udev->dev.transc_in[0]; + + standard_hid_handler *hid = (standard_hid_handler *)udev->dev.class_data[USBD_HID_INTERFACE]; + + switch (req->bRequest) { + case GET_REPORT: + /* no use for this driver */ + break; + + case GET_IDLE: + transc->xfer_buf = (uint8_t *)&hid->idle_state; + + transc->remain_len = 1U; + break; + + case GET_PROTOCOL: + transc->xfer_buf = (uint8_t *)&hid->protocol; + + transc->remain_len = 1U; + break; + + case SET_REPORT: + /* no use for this driver */ + break; + + case SET_IDLE: + hid->idle_state = (uint8_t)(req->wValue >> 8U); + break; + + case SET_PROTOCOL: + hid->protocol = (uint8_t)(req->wValue); + break; + + case USB_GET_DESCRIPTOR: + if (USB_DESCTYPE_REPORT == (req->wValue >> 8U)) { + transc->remain_len = USB_MIN(USB_HID_REPORT_DESC_LEN, req->wLength); + transc->xfer_buf = (uint8_t *)hid_report_desc; + + return REQ_SUPP; + } else if (USB_DESCTYPE_HID == (req->wValue >> 8U)) { + transc->remain_len = USB_MIN(9U, req->wLength); + transc->xfer_buf = (uint8_t *)(&(hid_config_desc.hid_vendor)); + } + break; + + default: + break; + } + + return USBD_OK; +} + +/*! + \brief handle data stage + \param[in] udev: pointer to USB device instance + \param[in] ep_num: endpoint identifier + \param[out] none + \retval USB device operation status +*/ +static uint8_t hid_data_in (usb_dev *udev, uint8_t ep_num) +{ + standard_hid_handler *hid = (standard_hid_handler *)udev->dev.class_data[USBD_HID_INTERFACE]; + + if (0U != hid->data[2]) { + hid->data[2] = 0x00U; + + usbd_ep_send(udev, HID_IN_EP, hid->data, HID_IN_PACKET); + } else { + hid->prev_transfer_complete = 1U; + } + + return USBD_OK; +} diff --git a/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/device/class/iap/Include/usb_iap_core.h b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/device/class/iap/Include/usb_iap_core.h new file mode 100644 index 0000000000..20d1e82646 --- /dev/null +++ b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/device/class/iap/Include/usb_iap_core.h @@ -0,0 +1,87 @@ +/*! + \file usb_iap_core.h + \brief the header file of IAP driver + + \version 2020-08-01, V3.0.0, firmware for GD32F30x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef __USB_IAP_CORE_H +#define __USB_IAP_CORE_H + +#include "usbd_enum.h" +#include "usb_hid.h" + +#define USB_SERIAL_STRING_SIZE 0x06U + +#ifdef USE_USB_FS + #define USB_DESC_LEN_IAP_REPORT 35U +#endif +#define USB_DESC_LEN_IAP_CONFIG_SET 41U + +/* special commands with download request */ +#define IAP_OPTION_BYTE1 0x01U +#define IAP_ERASE 0x02U +#define IAP_DNLOAD 0x03U +#define IAP_LEAVE 0x04U +#define IAP_GETBIN_ADDRESS 0x05U +#define IAP_OPTION_BYTE2 0x06U + +typedef struct +{ + uint8_t report_buf[IAP_OUT_PACKET + 1U]; + uint8_t option_byte[IAP_IN_PACKET]; + + /* state machine variables */ + uint8_t dev_status[IAP_IN_PACKET]; + uint8_t bin_addr[IAP_IN_PACKET]; + + uint8_t reportID; + uint8_t flag; + + uint32_t protocol; + uint32_t idlestate; + + uint16_t transfer_times; + uint16_t page_count; + uint16_t lps; /* last packet size */ + uint32_t file_length; + uint32_t base_address; +} usbd_iap_handler; + +typedef void (*app_func) (void); + +extern usb_desc iap_desc; +extern usb_class_core iap_class; + +/* function declarations */ +/* send iap report */ +uint8_t iap_report_send (usb_dev *udev, uint8_t *report, uint32_t len); + +#endif /* __USB_IAP_CORE_H */ diff --git a/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/device/class/iap/Source/usb_iap_core.c b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/device/class/iap/Source/usb_iap_core.c new file mode 100644 index 0000000000..330bc0bd40 --- /dev/null +++ b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/device/class/iap/Source/usb_iap_core.c @@ -0,0 +1,562 @@ +/*! + \file usb_iap_core.c + \brief IAP driver + + \version 2020-08-01, V3.0.0, firmware for GD32F30x + \version 2020-12-07, V3.0.1, firmware for GD32F30x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "usb_iap_core.h" +#include "flash_operation.h" +#include + +#define USBD_VID 0x28E9U +#define USBD_PID 0x0228U + +/* Note:it should use the C99 standard when compiling the below codes */ +/* USB standard device descriptor */ +__ALIGN_BEGIN const usb_desc_dev iap_dev_desc __ALIGN_END = +{ + .header = + { + .bLength = USB_DEV_DESC_LEN, + .bDescriptorType = USB_DESCTYPE_DEV + }, + .bcdUSB = 0x0200U, + .bDeviceClass = 0x00U, + .bDeviceSubClass = 0x00U, + .bDeviceProtocol = 0x00U, + .bMaxPacketSize0 = USB_FS_EP0_MAX_LEN, + .idVendor = USBD_VID, + .idProduct = USBD_PID, + .bcdDevice = 0x0100U, + .iManufacturer = STR_IDX_MFC, + .iProduct = STR_IDX_PRODUCT, + .iSerialNumber = STR_IDX_SERIAL, + .bNumberConfigurations = USBD_CFG_MAX_NUM +}; + +__ALIGN_BEGIN const usb_hid_desc_config_set iap_config_desc __ALIGN_END = +{ + .config = + { + .header = + { + .bLength = sizeof(usb_desc_config), + .bDescriptorType = USB_DESCTYPE_CONFIG + }, + .wTotalLength = USB_DESC_LEN_IAP_CONFIG_SET, + .bNumInterfaces = 0x01U, + .bConfigurationValue = 0x01U, + .iConfiguration = 0x00U, + .bmAttributes = 0x80U, + .bMaxPower = 0x32U + }, + + .hid_itf = + { + .header = + { + .bLength = sizeof(usb_desc_itf), + .bDescriptorType = USB_DESCTYPE_ITF + }, + .bInterfaceNumber = 0x00U, + .bAlternateSetting = 0x00U, + .bNumEndpoints = 0x02U, + .bInterfaceClass = USB_HID_CLASS, + .bInterfaceSubClass = 0x00U, + .bInterfaceProtocol = 0x00U, + .iInterface = 0x00U + }, + + .hid_vendor = + { + .header = + { + .bLength = sizeof(usb_desc_hid), + .bDescriptorType = USB_DESCTYPE_HID + }, + .bcdHID = 0x0111U, + .bCountryCode = 0x00U, + .bNumDescriptors = 0x01U, + .bDescriptorType = USB_DESCTYPE_REPORT, + .wDescriptorLength = USB_DESC_LEN_IAP_REPORT, + }, + + .hid_epin = + { + .header = + { + .bLength = sizeof(usb_desc_ep), + .bDescriptorType = USB_DESCTYPE_EP + }, + .bEndpointAddress = IAP_IN_EP, + .bmAttributes = USB_EP_ATTR_INT, + .wMaxPacketSize = IAP_IN_PACKET, + .bInterval = 0x01U + }, + + .hid_epout = + { + .header = + { + .bLength = sizeof(usb_desc_ep), + .bDescriptorType = USB_DESCTYPE_EP + }, + .bEndpointAddress = IAP_OUT_EP, + .bmAttributes = USB_EP_ATTR_INT, + .wMaxPacketSize = IAP_OUT_PACKET, + .bInterval = 0x01U + } +}; + +/* USB language ID Descriptor */ +static __ALIGN_BEGIN const usb_desc_LANGID usbd_language_id_desc __ALIGN_END = +{ + .header = + { + .bLength = sizeof(usb_desc_LANGID), + .bDescriptorType = USB_DESCTYPE_STR + }, + .wLANGID = ENG_LANGID +}; + +/* USB manufacture string */ +static __ALIGN_BEGIN const usb_desc_str manufacturer_string __ALIGN_END = +{ + .header = + { + .bLength = USB_STRING_LEN(10U), + .bDescriptorType = USB_DESCTYPE_STR, + }, + .unicode_string = {'G', 'i', 'g', 'a', 'D', 'e', 'v', 'i', 'c', 'e'} +}; + +/* USB product string */ +static __ALIGN_BEGIN const usb_desc_str product_string __ALIGN_END = +{ + .header = + { + .bLength = USB_STRING_LEN(12U), + .bDescriptorType = USB_DESCTYPE_STR, + }, + .unicode_string = {'G', 'D', '3', '2', '-', 'U', 'S', 'B', '_', 'I', 'A', 'P'} +}; + +/* USBD serial string */ +static __ALIGN_BEGIN usb_desc_str serial_string __ALIGN_END = +{ + .header = + { + .bLength = USB_STRING_LEN(2U), + .bDescriptorType = USB_DESCTYPE_STR, + } +}; + +void *const usbd_iap_strings[] = +{ + [STR_IDX_LANGID] = (uint8_t *)&usbd_language_id_desc, + [STR_IDX_MFC] = (uint8_t *)&manufacturer_string, + [STR_IDX_PRODUCT] = (uint8_t *)&product_string, + [STR_IDX_SERIAL] = (uint8_t *)&serial_string +}; + +usb_desc iap_desc = { + .dev_desc = (uint8_t *)&iap_dev_desc, + .config_desc = (uint8_t *)&iap_config_desc, + .strings = usbd_iap_strings +}; + +/* local function prototypes ('static') */ +static uint8_t iap_init (usb_dev *udev, uint8_t config_index); +static uint8_t iap_deinit (usb_dev *udev, uint8_t config_index); +static uint8_t iap_req_handler (usb_dev *udev, usb_req *req); +static uint8_t iap_data_out (usb_dev *udev, uint8_t ep_num); + +/* IAP requests management functions */ +static void iap_req_erase (usb_dev *udev); +static void iap_req_dnload (usb_dev *udev); +static void iap_req_optionbyte(usb_dev *udev, uint8_t option_num); +static void iap_req_leave (usb_dev *udev); +static void iap_address_send (usb_dev *udev); + +usb_class_core iap_class = { + .init = iap_init, + .deinit = iap_deinit, + .req_proc = iap_req_handler, + .data_out = iap_data_out +}; + +/* USB custom HID device report descriptor */ +__ALIGN_BEGIN const uint8_t iap_report_desc[USB_DESC_LEN_IAP_REPORT] __ALIGN_END = +{ + 0x05, 0x01, /* USAGE_PAGE (Generic Desktop) */ + 0x09, 0x00, /* USAGE (Custom Device) */ + 0xa1, 0x01, /* COLLECTION (Application) */ + + /* IAP command and data */ + 0x85, 0x01, /* REPORT_ID (0x01) */ + 0x09, 0x01, /* USAGE (IAP command) */ + 0x15, 0x00, /* LOGICAL_MINIMUM (0) */ + 0x25, 0xff, /* LOGICAL_MAXIMUM (255) */ + 0x75, 0x08, /* REPORT_SIZE (8) */ + 0x95, REPORT_OUT_COUNT, + 0x91, 0x82, /* OUTPUT (Data,Var,Abs,Vol) */ + + /* device status and option byte */ + 0x85, 0x02, /* REPORT_ID (0x02) */ + 0x09, 0x02, /* USAGE (Status and option byte) */ + 0x15, 0x00, /* LOGICAL_MINIMUM (0) */ + 0x25, 0xff, /* LOGICAL_MAXIMUM (255) */ + 0x75, 0x08, /* REPORT_SIZE (8) */ + 0x95, REPORT_IN_COUNT, /* REPORT_COUNT (23) */ + 0x81, 0x82, /* INPUT (Data,Var,Abs,Vol) */ + + 0xc0 /* END_COLLECTION */ +}; + +/*! + \brief send iap report + \param[in] udev: pointer to USB device instance + \param[in] report: pointer to HID report + \param[in] len: data length + \param[out] none + \retval USB device operation status +*/ +uint8_t iap_report_send (usb_dev *udev, uint8_t *report, uint32_t len) +{ + usbd_ep_send (udev, IAP_IN_EP, report, len); + + return USBD_OK; +} + +/*! + \brief initialize the IAP device + \param[in] udev: pointer to USB device instance + \param[in] config_index: configuration index + \param[out] none + \retval USB device operation status +*/ +static uint8_t iap_init (usb_dev *udev, uint8_t config_index) +{ + static __ALIGN_BEGIN usbd_iap_handler iap_handler __ALIGN_END; + + /* initialize Tx endpoint */ + usbd_ep_setup(udev, &(iap_config_desc.hid_epin)); + + /* initialize Rx endpoint */ + usbd_ep_setup(udev, &(iap_config_desc.hid_epout)); + + /* unlock the internal flash */ + fmc_unlock(); + + memset((void *)&iap_handler, 0U, sizeof(usbd_iap_handler)); + + /* prepare receive data */ + usbd_ep_recev(udev, IAP_OUT_EP, iap_handler.report_buf, IAP_OUT_PACKET); + + iap_handler.base_address = APP_LOADED_ADDR; + + udev->dev.class_data[USBD_IAP_INTERFACE] = (void *)&iap_handler; + + return USBD_OK; +} + +/*! + \brief de-initialize the iap device + \param[in] udev: pointer to USB device instance + \param[in] config_index: configuration index + \param[out] none + \retval USB device operation status +*/ +static uint8_t iap_deinit (usb_dev *udev, uint8_t config_index) +{ + /* deinitialize iap endpoints */ + usbd_ep_clear (udev, IAP_IN_EP); + usbd_ep_clear (udev, IAP_OUT_EP); + + /* lock the internal flash */ + fmc_lock(); + + return USBD_OK; +} + +/*! + \brief handle the iap class-specific requests + \param[in] udev: pointer to USB device instance + \param[in] req: device class-specific request + \param[out] none + \retval USB device operation status +*/ +static uint8_t iap_req_handler (usb_dev *udev, usb_req *req) +{ + usb_transc *transc = &udev->dev.transc_in[0]; + + usbd_iap_handler *iap = (usbd_iap_handler *)udev->dev.class_data[USBD_IAP_INTERFACE]; + + switch (req->bRequest) { + case GET_REPORT: + /* no use for this driver */ + break; + + case GET_IDLE: + transc->xfer_buf = (uint8_t *)&iap->idlestate; + transc->remain_len = 1U; + break; + + case GET_PROTOCOL: + transc->xfer_buf = (uint8_t *)&iap->protocol; + transc->remain_len = 1U; + break; + + case SET_REPORT: + iap->reportID = (uint8_t)(req->wValue); + break; + + case SET_IDLE: + iap->idlestate = (uint8_t)(req->wValue >> 8U); + break; + + case SET_PROTOCOL: + iap->protocol = (uint8_t)(req->wValue); + break; + + case USB_GET_DESCRIPTOR: + if (USB_DESCTYPE_REPORT == (req->wValue >> 8U)) { + transc->remain_len = USB_MIN(USB_DESC_LEN_IAP_REPORT, req->wLength); + transc->xfer_buf = (uint8_t *)iap_report_desc; + } + break; + + default: + return USBD_FAIL; + } + + return USBD_OK; +} + +/*! + \brief handle data out stage + \param[in] udev: pointer to USB device instance + \param[in] ep_num: endpoint identifier + \param[out] none + \retval none +*/ +static uint8_t iap_data_out (usb_dev *udev ,uint8_t ep_num) +{ + usbd_iap_handler *iap = (usbd_iap_handler *)udev->dev.class_data[USBD_IAP_INTERFACE]; + + if (0x01U == iap->report_buf[0]) { + switch (iap->report_buf[1]) { + case IAP_DNLOAD: + iap_req_dnload(udev); + break; + + case IAP_ERASE: + iap_req_erase(udev); + break; + + case IAP_OPTION_BYTE1: + iap_req_optionbyte(udev, 0x01U); + break; + + case IAP_LEAVE: + iap_req_leave(udev); + break; + + case IAP_GETBIN_ADDRESS: + iap_address_send(udev); + break; + + case IAP_OPTION_BYTE2: + iap_req_optionbyte(udev, 0x02U); + break; + + default: + break; + } + } + + usbd_ep_recev(udev, IAP_OUT_EP, iap->report_buf, IAP_OUT_PACKET); + + return USBD_OK; +} + +/*! + \brief handle the IAP_DNLOAD request + \param[in] udev: pointer to usb device instance + \param[out] none + \retval none +*/ +static void iap_req_dnload(usb_dev *udev) +{ + usbd_iap_handler *iap = (usbd_iap_handler *)udev->dev.class_data[USBD_IAP_INTERFACE]; + + if (0U != iap->transfer_times) { + if (1U == iap->transfer_times) { + if (0U == iap->lps) { + iap_data_write(&iap->report_buf[2], iap->base_address, TRANSFER_SIZE); + } else { + iap_data_write(&iap->report_buf[2], iap->base_address, iap->file_length % TRANSFER_SIZE); + iap->lps = 0U; + } + + iap->dev_status[0] = 0x02U; + iap->dev_status[1] = 0x02U; + iap_report_send (udev, iap->dev_status, IAP_IN_PACKET); + } else { + iap_data_write(&iap->report_buf[2], iap->base_address, TRANSFER_SIZE); + + iap->base_address += TRANSFER_SIZE; + } + + iap->transfer_times--; + } +} + +/*! + \brief handle the IAP_ERASE request + \param[in] udev: pointer to usb device instance + \param[out] none + \retval none +*/ +static void iap_req_erase(usb_dev *udev) +{ + uint32_t addr = 0U; + + usbd_iap_handler *iap = (usbd_iap_handler *)udev->dev.class_data[USBD_IAP_INTERFACE]; + + /* get base address to erase */ + iap->base_address = iap->report_buf[2]; + iap->base_address |= iap->report_buf[3] << 8U; + iap->base_address |= iap->report_buf[4] << 16U; + iap->base_address |= iap->report_buf[5] << 24U; + + /* get file length */ + iap->file_length = iap->report_buf[7]; + iap->file_length |= iap->report_buf[8] << 8U; + iap->file_length |= iap->report_buf[9] << 16U; + iap->file_length |= iap->report_buf[10] << 24U; + + iap->lps = iap->file_length % TRANSFER_SIZE; + if (0U == iap->lps) { + iap->transfer_times = iap->file_length / TRANSFER_SIZE; + } else { + iap->transfer_times = iap->file_length / TRANSFER_SIZE + 1U; + } + + /* check if the address is in protected area */ + if (IS_PROTECTED_AREA(iap->base_address)) { + return; + } + + addr = iap->base_address; + + /* unlock the flash program erase controller */ + fmc_unlock(); + + flash_erase(addr, iap->file_length, iap->report_buf); + + fmc_lock(); + + iap->dev_status[0] = 0x02U; + iap->dev_status[1] = 0x01U; + + usbd_ep_send(udev, IAP_IN_EP, iap->dev_status, IAP_IN_PACKET); +} + +/*! + \brief handle the IAP_OPTION_BYTE request + \param[in] udev: pointer to USB device instance + \param[in] option_num: number of option byte + \param[out] none + \retval none +*/ +static void iap_req_optionbyte(usb_dev *udev, uint8_t option_num) +{ + uint8_t i = 0U; + uint32_t address = 0U; + + usbd_iap_handler *iap = (usbd_iap_handler *)udev->dev.class_data[USBD_IAP_INTERFACE]; + + iap->option_byte[0]= 0x02U; + + if (0x01U == option_num) { + address = OPT_BYTE_ADDR1; +#ifdef OPT_BYTE_ADDR2 + } else if (0x02U == option_num) { + address = OPT_BYTE_ADDR2; +#endif + } else { + return; + } + + for (i = 1U; i < 17U; i++) { + iap->option_byte[i] = *(uint8_t *)address; + address++; + } + + iap_report_send (udev, iap->option_byte, IAP_IN_PACKET); +} + +/*! + \brief handle the IAP_LEAVE request + \param[in] udev: pointer to usb device instance + \param[out] none + \retval none +*/ +static void iap_req_leave(usb_dev *udev) +{ + /* lock the internal flash */ + fmc_lock(); + + /* generate system reset to allow jumping to the user code */ + NVIC_SystemReset(); +} + +/*! + \brief handle the IAP_SEND_ADDRESS request + \param[in] udev: pointer to usb device instance + \param[out] none + \retval none +*/ +static void iap_address_send(usb_dev *udev) +{ + usbd_iap_handler *iap = (usbd_iap_handler *)udev->dev.class_data[USBD_IAP_INTERFACE]; + + iap->bin_addr[0] = 0x02U; + + iap->bin_addr[1] = (uint8_t)(APP_LOADED_ADDR); + iap->bin_addr[2] = (uint8_t)(APP_LOADED_ADDR >> 8U); + iap->bin_addr[3] = (uint8_t)(APP_LOADED_ADDR >> 16U); + iap->bin_addr[4] = (uint8_t)(APP_LOADED_ADDR >> 24U); + + iap_report_send (udev, iap->bin_addr, IAP_IN_PACKET); +} diff --git a/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/device/class/msc/Include/usbd_msc_bbb.h b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/device/class/msc/Include/usbd_msc_bbb.h new file mode 100644 index 0000000000..ef3f883780 --- /dev/null +++ b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/device/class/msc/Include/usbd_msc_bbb.h @@ -0,0 +1,101 @@ +/*! + \file usbd_msc_bbb.h + \brief the header file of the usbd_msc_bot.c file + + \version 2020-08-01, V3.0.0, firmware for GD32F30x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef __USBD_MSC_BBB_H +#define __USBD_MSC_BBB_H + +#include "usbd_core.h" +#include "msc_bbb.h" +#include "usbd_msc_mem.h" +#include "usbd_msc_scsi.h" + +/* MSC BBB state */ +enum msc_bbb_state { + BBB_IDLE = 0U, /*!< idle state */ + BBB_DATA_OUT, /*!< data OUT state */ + BBB_DATA_IN, /*!< data IN state */ + BBB_LAST_DATA_IN, /*!< last data IN state */ + BBB_SEND_DATA /*!< send immediate data state */ +}; + +/* MSC BBB status */ +enum msc_bbb_status { + BBB_STATUS_NORMAL = 0U, /*!< normal status */ + BBB_STATUS_RECOVERY, /*!< recovery status*/ + BBB_STATUS_ERROR /*!< error status */ +}; + +typedef struct +{ + uint8_t bbb_data[MSC_MEDIA_PACKET_SIZE]; + + uint8_t max_lun; + uint8_t bbb_state; + uint8_t bbb_status; + + uint32_t bbb_datalen; + + msc_bbb_cbw bbb_cbw; + msc_bbb_csw bbb_csw; + + uint8_t scsi_sense_head; + uint8_t scsi_sense_tail; + + uint32_t scsi_blk_size[MEM_LUN_NUM]; + uint32_t scsi_blk_nbr[MEM_LUN_NUM]; + + uint32_t scsi_blk_addr; + uint32_t scsi_blk_len; + uint32_t scsi_disk_pop; + + msc_scsi_sense scsi_sense[SENSE_LIST_DEEPTH]; +} usbd_msc_handler; + +/* function declarations */ +/* initialize the bbb process */ +void msc_bbb_init (usb_core_driver *pudev); +/* reset the BBB machine */ +void msc_bbb_reset (usb_core_driver *pudev); +/* de-initialize the BBB machine */ +void msc_bbb_deinit (usb_core_driver *pudev); +/* handle BBB data IN stage */ +void msc_bbb_data_in (usb_core_driver *pudev, uint8_t ep_num); +/* handle BBB data OUT stage */ +void msc_bbb_data_out (usb_core_driver *pudev, uint8_t ep_num); +/* send the CSW(command status wrapper) */ +void msc_bbb_csw_send (usb_core_driver *pudev, uint8_t csw_status); +/* complete the clear feature request */ +void msc_bbb_clrfeature (usb_core_driver *pudev, uint8_t ep_num); + +#endif /* __USBD_MSC_BBB_H */ diff --git a/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/device/class/msc/Include/usbd_msc_core.h b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/device/class/msc/Include/usbd_msc_core.h new file mode 100644 index 0000000000..24f24a8ad9 --- /dev/null +++ b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/device/class/msc/Include/usbd_msc_core.h @@ -0,0 +1,59 @@ +/*! + \file usbd_msc_core.h + \brief the header file of USB MSC device class core functions + + \version 2020-08-01, V3.0.0, firmware for GD32F30x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef __USBD_MSC_CORE_H +#define __USBD_MSC_CORE_H + +#include "usbd_core.h" +#include "usb_msc.h" + +#define USB_MSC_CONFIG_DESC_SIZE 32U + +#define MSC_EPIN_SIZE MSC_DATA_PACKET_SIZE +#define MSC_EPOUT_SIZE MSC_DATA_PACKET_SIZE + +/* USB configuration descriptor structure */ +typedef struct +{ + usb_desc_config config; + + usb_desc_itf msc_itf; + usb_desc_ep msc_epin; + usb_desc_ep msc_epout; +} usb_desc_config_set; + +extern usb_desc msc_desc; +extern usb_class_core msc_class; + +#endif /* __USBD_MSC_CORE_H */ diff --git a/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/device/class/msc/Include/usbd_msc_data.h b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/device/class/msc/Include/usbd_msc_data.h new file mode 100644 index 0000000000..cc232adda7 --- /dev/null +++ b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/device/class/msc/Include/usbd_msc_data.h @@ -0,0 +1,49 @@ +/*! + \file usbd_msc_data.h + \brief the header file of the usbd_msc_data.c file + + \version 2020-08-01, V3.0.0, firmware for GD32F30x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef __USBD_MSC_DATA_H +#define __USBD_MSC_DATA_H + +#include "usbd_conf.h" + +#define MODE_SENSE6_LENGTH 8U +#define MODE_SENSE10_LENGTH 8U +#define INQUIRY_PAGE00_LENGTH 96U +#define FORMAT_CAPACITIES_LENGTH 20U + +extern const uint8_t msc_page00_inquiry_data[]; +extern const uint8_t msc_mode_sense6_data[]; +extern const uint8_t msc_mode_sense10_data[]; + +#endif /* __USBD_MSC_DATA_H */ diff --git a/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/device/class/msc/Include/usbd_msc_mem.h b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/device/class/msc/Include/usbd_msc_mem.h new file mode 100644 index 0000000000..e411a162fc --- /dev/null +++ b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/device/class/msc/Include/usbd_msc_mem.h @@ -0,0 +1,59 @@ +/*! + \file usbd_msc_mem.h + \brief header file for storage memory + + \version 2020-08-01, V3.0.0, firmware for GD32F30x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef __USBD_MSC_MEM_H +#define __USBD_MSC_MEM_H + +#include "usbd_conf.h" + +#define USBD_STD_INQUIRY_LENGTH 36U + +typedef struct +{ + int8_t (*mem_init) (uint8_t lun); + int8_t (*mem_ready) (uint8_t lun); + int8_t (*mem_protected) (uint8_t lun); + int8_t (*mem_read) (uint8_t lun, uint8_t *buf, uint32_t block_addr, uint16_t block_len); + int8_t (*mem_write) (uint8_t lun, uint8_t *buf, uint32_t block_addr, uint16_t block_len); + int8_t (*mem_maxlun) (void); + + uint8_t *mem_toc_data; + uint8_t *mem_inquiry_data[MEM_LUN_NUM]; + uint32_t mem_block_size[MEM_LUN_NUM]; + uint32_t mem_block_len[MEM_LUN_NUM]; +}usbd_mem_cb; + +extern usbd_mem_cb *usbd_mem_fops; + +#endif /* __USBD_MSC_MEM_H */ diff --git a/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/device/class/msc/Include/usbd_msc_scsi.h b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/device/class/msc/Include/usbd_msc_scsi.h new file mode 100644 index 0000000000..6143edb00e --- /dev/null +++ b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/device/class/msc/Include/usbd_msc_scsi.h @@ -0,0 +1,50 @@ +/*! + \file usbd_msc_scsi.h + \brief the header file of the usbd_msc_scsi.c file + + \version 2020-08-01, V3.0.0, firmware for GD32F30x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef __USBD_MSC_SCSI_H +#define __USBD_MSC_SCSI_H + +#include "usbd_msc_data.h" +#include "usbd_msc_bbb.h" +#include "msc_scsi.h" + +#define SENSE_LIST_DEEPTH 4U + +/* function declarations */ +/* process SCSI commands */ +int8_t scsi_process_cmd (usb_core_driver *pudev, uint8_t lun, uint8_t *cmd); +/* load the last error code in the error list */ +void scsi_sense_code (usb_core_driver *pudev, uint8_t lun, uint8_t skey, uint8_t asc); + +#endif /* __USBD_MSC_SCSI_H */ diff --git a/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/device/class/msc/Source/usbd_msc_bbb.c b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/device/class/msc/Source/usbd_msc_bbb.c new file mode 100644 index 0000000000..7e5550d7da --- /dev/null +++ b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/device/class/msc/Source/usbd_msc_bbb.c @@ -0,0 +1,287 @@ +/*! + \file usbd_msc_bbb.c + \brief USB BBB(Bulk/Bulk/Bulk) protocol core functions + \note BBB means Bulk-only transport protocol for USB MSC + + \version 2020-08-01, V3.0.0, firmware for GD32F30x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "usbd_enum.h" +#include "usbd_msc_bbb.h" + +/* local function prototypes ('static') */ +static void msc_bbb_cbw_decode (usb_core_driver *pudev); +static void msc_bbb_data_send (usb_core_driver *pudev, uint8_t *pbuf, uint32_t Len); +static void msc_bbb_abort (usb_core_driver *pudev); + +/*! + \brief initialize the bbb process + \param[in] pudev: pointer to USB device instance + \param[out] none + \retval none +*/ +void msc_bbb_init (usb_core_driver *pudev) +{ + uint8_t lun_num; + + usbd_msc_handler *msc = (usbd_msc_handler *)pudev->dev.class_data[USBD_MSC_INTERFACE]; + + msc->bbb_state = BBB_IDLE; + msc->bbb_status = BBB_STATUS_NORMAL; + + /* init the storage logic unit */ + for(lun_num = 0U; lun_num < MEM_LUN_NUM; lun_num++) { + usbd_mem_fops->mem_init(lun_num); + } + + /* flush the Rx FIFO */ + usbd_fifo_flush (pudev, MSC_OUT_EP); + + /* flush the Tx FIFO */ + usbd_fifo_flush (pudev, MSC_IN_EP); + + /* prepare endpoint to receive the first BBB CBW */ + usbd_ep_recev (pudev, MSC_OUT_EP, (uint8_t *)&msc->bbb_cbw, BBB_CBW_LENGTH); +} + +/*! + \brief reset the BBB machine + \param[in] pudev: pointer to USB device instance + \param[out] none + \retval none +*/ +void msc_bbb_reset (usb_core_driver *pudev) +{ + usbd_msc_handler *msc = (usbd_msc_handler *)pudev->dev.class_data[USBD_MSC_INTERFACE]; + + msc->bbb_state = BBB_IDLE; + msc->bbb_status = BBB_STATUS_RECOVERY; + + /* prepare endpoint to receive the first BBB command */ + usbd_ep_recev (pudev, MSC_OUT_EP, (uint8_t *)&msc->bbb_cbw, BBB_CBW_LENGTH); +} + +/*! + \brief de-initialize the BBB machine + \param[in] pudev: pointer to USB device instance + \param[out] none + \retval none +*/ +void msc_bbb_deinit (usb_core_driver *pudev) +{ + usbd_msc_handler *msc = (usbd_msc_handler *)pudev->dev.class_data[USBD_MSC_INTERFACE]; + + msc->bbb_state = BBB_IDLE; +} + +/*! + \brief handle BBB data IN stage + \param[in] pudev: pointer to USB device instance + \param[in] ep_num: endpoint number + \param[out] none + \retval none +*/ +void msc_bbb_data_in (usb_core_driver *pudev, uint8_t ep_num) +{ + usbd_msc_handler *msc = (usbd_msc_handler *)pudev->dev.class_data[USBD_MSC_INTERFACE]; + + switch (msc->bbb_state) { + case BBB_DATA_IN: + if (scsi_process_cmd (pudev, msc->bbb_cbw.bCBWLUN, &msc->bbb_cbw.CBWCB[0]) < 0) { + msc_bbb_csw_send (pudev, CSW_CMD_FAILED); + } + break; + + case BBB_SEND_DATA: + case BBB_LAST_DATA_IN: + msc_bbb_csw_send (pudev, CSW_CMD_PASSED); + break; + + default: + break; + } +} + +/*! + \brief handle BBB data OUT stage + \param[in] pudev: pointer to USB device instance + \param[in] ep_num: endpoint number + \param[out] none + \retval none +*/ +void msc_bbb_data_out (usb_core_driver *pudev, uint8_t ep_num) +{ + usbd_msc_handler *msc = (usbd_msc_handler *)pudev->dev.class_data[USBD_MSC_INTERFACE]; + + switch (msc->bbb_state) { + case BBB_IDLE: + msc_bbb_cbw_decode (pudev); + break; + + case BBB_DATA_OUT: + if (scsi_process_cmd (pudev, msc->bbb_cbw.bCBWLUN, &msc->bbb_cbw.CBWCB[0]) < 0) { + msc_bbb_csw_send (pudev, CSW_CMD_FAILED); + } + break; + + default: + break; + } +} + +/*! + \brief send the CSW(command status wrapper) + \param[in] pudev: pointer to USB device instance + \param[in] csw_status: CSW status + \param[out] none + \retval none +*/ +void msc_bbb_csw_send (usb_core_driver *pudev, uint8_t csw_status) +{ + usbd_msc_handler *msc = (usbd_msc_handler *)pudev->dev.class_data[USBD_MSC_INTERFACE]; + + msc->bbb_csw.dCSWSignature = BBB_CSW_SIGNATURE; + msc->bbb_csw.bCSWStatus = csw_status; + msc->bbb_state = BBB_IDLE; + + usbd_ep_send (pudev, MSC_IN_EP, (uint8_t *)&msc->bbb_csw, BBB_CSW_LENGTH); + + /* prapare endpoint to receive next command */ + usbd_ep_recev (pudev, MSC_OUT_EP, (uint8_t *)&msc->bbb_cbw, BBB_CBW_LENGTH); +} + +/*! + \brief complete the clear feature request + \param[in] pudev: pointer to USB device instance + \param[in] ep_num: endpoint number + \param[out] none + \retval none +*/ +void msc_bbb_clrfeature (usb_core_driver *pudev, uint8_t ep_num) +{ + usbd_msc_handler *msc = (usbd_msc_handler *)pudev->dev.class_data[USBD_MSC_INTERFACE]; + + if (msc->bbb_status == BBB_STATUS_ERROR)/* bad CBW signature */ { + usbd_ep_stall(pudev, MSC_IN_EP); + + msc->bbb_status = BBB_STATUS_NORMAL; + } else if(((ep_num & 0x80U) == 0x80U) && (msc->bbb_status != BBB_STATUS_RECOVERY)) { + msc_bbb_csw_send (pudev, CSW_CMD_FAILED); + } else { + + } +} + +/*! + \brief decode the CBW command and set the BBB state machine accordingly + \param[in] pudev: pointer to USB device instance + \param[out] none + \retval none +*/ +static void msc_bbb_cbw_decode (usb_core_driver *pudev) +{ + usbd_msc_handler *msc = (usbd_msc_handler *)pudev->dev.class_data[USBD_MSC_INTERFACE]; + + msc->bbb_csw.dCSWTag = msc->bbb_cbw.dCBWTag; + msc->bbb_csw.dCSWDataResidue = msc->bbb_cbw.dCBWDataTransferLength; + + if ((BBB_CBW_LENGTH != usbd_rxcount_get (pudev, MSC_OUT_EP)) || + (BBB_CBW_SIGNATURE != msc->bbb_cbw.dCBWSignature)|| + (msc->bbb_cbw.bCBWLUN > 1U) || + (msc->bbb_cbw.bCBWCBLength < 1U) || + (msc->bbb_cbw.bCBWCBLength > 16U)) { + /* illegal command handler */ + scsi_sense_code (pudev, msc->bbb_cbw.bCBWLUN, ILLEGAL_REQUEST, INVALID_CDB); + + msc->bbb_status = BBB_STATUS_ERROR; + + msc_bbb_abort (pudev); + } else { + if (scsi_process_cmd (pudev, msc->bbb_cbw.bCBWLUN, &msc->bbb_cbw.CBWCB[0]) < 0) { + msc_bbb_abort (pudev); + } else if ((BBB_DATA_IN != msc->bbb_state) && + (BBB_DATA_OUT != msc->bbb_state) && + (BBB_LAST_DATA_IN != msc->bbb_state)) { /* burst xfer handled internally */ + if (msc->bbb_datalen > 0U) { + msc_bbb_data_send (pudev, msc->bbb_data, msc->bbb_datalen); + } else if (0U == msc->bbb_datalen) { + msc_bbb_csw_send (pudev, CSW_CMD_PASSED); + } else { + + } + } else { + + } + } +} + +/*! + \brief send the requested data + \param[in] pudev: pointer to USB device instance + \param[in] buf: pointer to data buffer + \param[in] len: data length + \param[out] none + \retval none +*/ +static void msc_bbb_data_send (usb_core_driver *pudev, uint8_t *buf, uint32_t len) +{ + usbd_msc_handler *msc = (usbd_msc_handler *)pudev->dev.class_data[USBD_MSC_INTERFACE]; + + len = USB_MIN (msc->bbb_cbw.dCBWDataTransferLength, len); + + msc->bbb_csw.dCSWDataResidue -= len; + msc->bbb_csw.bCSWStatus = CSW_CMD_PASSED; + msc->bbb_state = BBB_SEND_DATA; + + usbd_ep_send (pudev, MSC_IN_EP, buf, len); +} + +/*! + \brief abort the current transfer + \param[in] pudev: pointer to USB device instance + \param[out] none + \retval none +*/ +static void msc_bbb_abort (usb_core_driver *pudev) +{ + usbd_msc_handler *msc = (usbd_msc_handler *)pudev->dev.class_data[USBD_MSC_INTERFACE]; + + if ((0U == msc->bbb_cbw.bmCBWFlags) && + (0U != msc->bbb_cbw.dCBWDataTransferLength) && + (BBB_STATUS_NORMAL == msc->bbb_status)) { + usbd_ep_stall(pudev, MSC_OUT_EP); + } + + usbd_ep_stall(pudev, MSC_IN_EP); + + if (msc->bbb_status == BBB_STATUS_ERROR) { + usbd_ep_recev (pudev, MSC_OUT_EP, (uint8_t *)&msc->bbb_cbw, BBB_CBW_LENGTH); + } +} diff --git a/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/device/class/msc/Source/usbd_msc_core.c b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/device/class/msc/Source/usbd_msc_core.c new file mode 100644 index 0000000000..1f2e93938e --- /dev/null +++ b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/device/class/msc/Source/usbd_msc_core.c @@ -0,0 +1,319 @@ +/*! + \file usbd_msc_core.c + \brief USB MSC device class core functions + + \version 2020-08-01, V3.0.0, firmware for GD32F30x + \version 2020-12-07, V3.0.1, firmware for GD32F30x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "usbd_enum.h" +#include "usbd_msc_bbb.h" +#include "usbd_msc_core.h" +#include + +#define USBD_VID 0x28E9U +#define USBD_PID 0x028FU + +/* local function prototypes ('static') */ +static uint8_t msc_core_init (usb_dev *pudev, uint8_t config_index); +static uint8_t msc_core_deinit (usb_dev *pudev, uint8_t config_index); +static uint8_t msc_core_req (usb_dev *pudev, usb_req *req); +static uint8_t msc_core_in (usb_dev *pudev, uint8_t ep_num); +static uint8_t msc_core_out (usb_dev *pudev, uint8_t ep_num); + +usb_class_core msc_class = +{ + .init = msc_core_init, + .deinit = msc_core_deinit, + + .req_proc = msc_core_req, + + .data_in = msc_core_in, + .data_out = msc_core_out +}; + +/* note: it should use the C99 standard when compiling the below codes */ +/* USB standard device descriptor */ +__ALIGN_BEGIN const usb_desc_dev msc_dev_desc __ALIGN_END = +{ + .header = { + .bLength = USB_DEV_DESC_LEN, + .bDescriptorType = USB_DESCTYPE_DEV + }, + .bcdUSB = 0x0200U, + .bDeviceClass = 0x00U, + .bDeviceSubClass = 0x00U, + .bDeviceProtocol = 0x00U, + .bMaxPacketSize0 = USB_FS_EP0_MAX_LEN, + .idVendor = USBD_VID, + .idProduct = USBD_PID, + .bcdDevice = 0x0100U, + .iManufacturer = STR_IDX_MFC, + .iProduct = STR_IDX_PRODUCT, + .iSerialNumber = STR_IDX_SERIAL, + .bNumberConfigurations = USBD_CFG_MAX_NUM +}; + +/* USB device configuration descriptor */ +__ALIGN_BEGIN const usb_desc_config_set msc_config_desc __ALIGN_END = +{ + .config = + { + .header = { + .bLength = sizeof(usb_desc_config), + .bDescriptorType = USB_DESCTYPE_CONFIG + }, + .wTotalLength = USB_MSC_CONFIG_DESC_SIZE, + .bNumInterfaces = 0x01U, + .bConfigurationValue = 0x01U, + .iConfiguration = 0x00U, + .bmAttributes = 0xC0U, + .bMaxPower = 0x32U + }, + + .msc_itf = + { + .header = { + .bLength = sizeof(usb_desc_itf), + .bDescriptorType = USB_DESCTYPE_ITF + }, + .bInterfaceNumber = 0x00U, + .bAlternateSetting = 0x00U, + .bNumEndpoints = 0x02U, + .bInterfaceClass = USB_CLASS_MSC, + .bInterfaceSubClass = USB_MSC_SUBCLASS_SCSI, + .bInterfaceProtocol = USB_MSC_PROTOCOL_BBB, + .iInterface = 0x00U + }, + + .msc_epin = + { + .header = { + .bLength = sizeof(usb_desc_ep), + .bDescriptorType = USB_DESCTYPE_EP + }, + .bEndpointAddress = MSC_IN_EP, + .bmAttributes = USB_EP_ATTR_BULK, + .wMaxPacketSize = MSC_EPIN_SIZE, + .bInterval = 0x00U + }, + + .msc_epout = + { + .header = { + .bLength = sizeof(usb_desc_ep), + .bDescriptorType = USB_DESCTYPE_EP + }, + .bEndpointAddress = MSC_OUT_EP, + .bmAttributes = USB_EP_ATTR_BULK, + .wMaxPacketSize = MSC_EPOUT_SIZE, + .bInterval = 0x00U + } +}; + +/* USB language ID descriptor */ +__ALIGN_BEGIN const usb_desc_LANGID usbd_language_id_desc __ALIGN_END = +{ + .header = + { + .bLength = sizeof(usb_desc_LANGID), + .bDescriptorType = USB_DESCTYPE_STR + }, + .wLANGID = ENG_LANGID +}; + +/* USB manufacture string */ +static __ALIGN_BEGIN const usb_desc_str manufacturer_string __ALIGN_END = +{ + .header = + { + .bLength = USB_STRING_LEN(10U), + .bDescriptorType = USB_DESCTYPE_STR, + }, + .unicode_string = {'G', 'i', 'g', 'a', 'D', 'e', 'v', 'i', 'c', 'e'} +}; + +/* USB product string */ +static __ALIGN_BEGIN const usb_desc_str product_string __ALIGN_END = +{ + .header = + { + .bLength = USB_STRING_LEN(12U), + .bDescriptorType = USB_DESCTYPE_STR, + }, + .unicode_string = {'G', 'D', '3', '2', '-', 'U', 'S', 'B', '_', 'M', 'S', 'C'} +}; + +/* USBD serial string */ +static __ALIGN_BEGIN usb_desc_str serial_string __ALIGN_END = +{ + .header = + { + .bLength = USB_STRING_LEN(12U), + .bDescriptorType = USB_DESCTYPE_STR, + } +}; + +/* USB string descriptor */ +void *const usbd_msc_strings[] = +{ + [STR_IDX_LANGID] = (uint8_t *)&usbd_language_id_desc, + [STR_IDX_MFC] = (uint8_t *)&manufacturer_string, + [STR_IDX_PRODUCT] = (uint8_t *)&product_string, + [STR_IDX_SERIAL] = (uint8_t *)&serial_string +}; + +usb_desc msc_desc = { + .dev_desc = (uint8_t *)&msc_dev_desc, + .config_desc = (uint8_t *)&msc_config_desc, + .strings = usbd_msc_strings +}; + +static __ALIGN_BEGIN uint8_t usbd_msc_maxlun = 0U __ALIGN_END; + +/*! + \brief initialize the MSC device + \param[in] pudev: pointer to USB device instance + \param[in] config_index: configuration index + \param[out] none + \retval USB device operation status +*/ +static uint8_t msc_core_init (usb_dev *pudev, uint8_t config_index) +{ + static __ALIGN_BEGIN usbd_msc_handler msc_handler __ALIGN_END; + + memset((void *)&msc_handler, 0U, sizeof(usbd_msc_handler)); + + pudev->dev.class_data[USBD_MSC_INTERFACE] = (void *)&msc_handler; + + /* configure MSC Tx endpoint */ + usbd_ep_setup (pudev, &(msc_config_desc.msc_epin)); + + /* configure MSC Rx endpoint */ + usbd_ep_setup (pudev, &(msc_config_desc.msc_epout)); + + /* init the BBB layer */ + msc_bbb_init(pudev); + + return USBD_OK; +} + +/*! + \brief de-initialize the MSC device + \param[in] pudev: pointer to USB device instance + \param[in] config_index: configuration index + \param[out] none + \retval USB device operation status +*/ +static uint8_t msc_core_deinit (usb_dev *pudev, uint8_t config_index) +{ + /* clear MSC endpoints */ + usbd_ep_clear (pudev, MSC_IN_EP); + usbd_ep_clear (pudev, MSC_OUT_EP); + + /* un-init the BBB layer */ + msc_bbb_deinit(pudev); + + return USBD_OK; +} + +/*! + \brief handle the MSC class-specific and standard requests + \param[in] pudev: pointer to USB device instance + \param[in] req: device class-specific request + \param[out] none + \retval USB device operation status +*/ +static uint8_t msc_core_req (usb_dev *pudev, usb_req *req) +{ + usb_transc *transc = &pudev->dev.transc_in[0]; + + switch (req->bRequest) { + case BBB_GET_MAX_LUN : + if((0U == req->wValue) && + (1U == req->wLength) && + (0x80U == (req->bmRequestType & 0x80U))) { + usbd_msc_maxlun = (uint8_t)usbd_mem_fops->mem_maxlun(); + + transc->xfer_buf = &usbd_msc_maxlun; + transc->remain_len = 1U; + } else { + return USBD_FAIL; + } + break; + + case BBB_RESET : + if((0U == req->wValue) && + (0U == req->wLength) && + (0x80U != (req->bmRequestType & 0x80U))) { + msc_bbb_reset(pudev); + } else { + return USBD_FAIL; + } + break; + + case USB_CLEAR_FEATURE: + msc_bbb_clrfeature (pudev, (uint8_t)req->wIndex); + break; + + default: + return USBD_FAIL; + } + + return USBD_OK; +} + +/*! + \brief handle data in stage + \param[in] pudev: pointer to USB device instance + \param[in] ep_num: the endpoint number + \param[out] none + \retval none +*/ +static uint8_t msc_core_in (usb_dev *pudev, uint8_t ep_num) +{ + msc_bbb_data_in(pudev, ep_num); + + return USBD_OK; +} + +/*! + \brief handle data out stage + \param[in] pudev: pointer to USB device instance + \param[in] ep_num: the endpoint number + \param[out] none + \retval none +*/ +static uint8_t msc_core_out (usb_dev *pudev, uint8_t ep_num) +{ + msc_bbb_data_out (pudev, ep_num); + + return USBD_OK; +} diff --git a/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/device/class/msc/Source/usbd_msc_data.c b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/device/class/msc/Source/usbd_msc_data.c new file mode 100644 index 0000000000..56ce9e3eeb --- /dev/null +++ b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/device/class/msc/Source/usbd_msc_data.c @@ -0,0 +1,73 @@ +/*! + \file usbd_msc_data.c + \brief USB MSC vital inquiry pages and sense data + + \version 2020-08-01, V3.0.0, firmware for GD32F30x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "usbd_msc_data.h" + +/* USB mass storage page 0 inquiry data */ +const uint8_t msc_page00_inquiry_data[] = +{ + 0x00U, + 0x00U, + 0x00U, + 0x00U, + (INQUIRY_PAGE00_LENGTH - 4U), + 0x80U, + 0x83U, +}; + +/* USB mass storage sense 6 data */ +const uint8_t msc_mode_sense6_data[] = +{ + 0x00U, + 0x00U, + 0x00U, + 0x00U, + 0x00U, + 0x00U, + 0x00U, + 0x00U +}; + +/* USB mass storage sense 10 data */ +const uint8_t msc_mode_sense10_data[] = +{ + 0x00U, + 0x06U, + 0x00U, + 0x00U, + 0x00U, + 0x00U, + 0x00U, + 0x00U +}; diff --git a/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/device/class/msc/Source/usbd_msc_scsi.c b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/device/class/msc/Source/usbd_msc_scsi.c new file mode 100644 index 0000000000..5d68b810fd --- /dev/null +++ b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/device/class/msc/Source/usbd_msc_scsi.c @@ -0,0 +1,724 @@ +/*! + \file usbd_msc_scsi.c + \brief USB SCSI layer functions + + \version 2020-08-01, V3.0.0, firmware for GD32F30x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "usbd_enum.h" +#include "usbd_msc_bbb.h" +#include "usbd_msc_scsi.h" +#include "usbd_msc_data.h" + +/* local function prototypes ('static') */ +static int8_t scsi_test_unit_ready (usb_core_driver *pudev, uint8_t lun, uint8_t *params); +static int8_t scsi_mode_select6 (usb_core_driver *pudev, uint8_t lun, uint8_t *params); +static int8_t scsi_mode_select10 (usb_core_driver *pudev, uint8_t lun, uint8_t *params); +static int8_t scsi_inquiry (usb_core_driver *pudev, uint8_t lun, uint8_t *params); +static int8_t scsi_read_format_capacity (usb_core_driver *pudev, uint8_t lun, uint8_t *params); +static int8_t scsi_read_capacity10 (usb_core_driver *pudev, uint8_t lun, uint8_t *params); +static int8_t scsi_request_sense (usb_core_driver *pudev, uint8_t lun, uint8_t *params); +static int8_t scsi_mode_sense6 (usb_core_driver *pudev, uint8_t lun, uint8_t *params); +static int8_t scsi_toc_cmd_read (usb_core_driver *pudev, uint8_t lun, uint8_t *params); +static int8_t scsi_mode_sense10 (usb_core_driver *pudev, uint8_t lun, uint8_t *params); +static int8_t scsi_write10 (usb_core_driver *pudev, uint8_t lun, uint8_t *params); +static int8_t scsi_read10 (usb_core_driver *pudev, uint8_t lun, uint8_t *params); +static int8_t scsi_verify10 (usb_core_driver *pudev, uint8_t lun, uint8_t *params); +static int8_t scsi_process_read (usb_core_driver *pudev, uint8_t lun); +static int8_t scsi_process_write (usb_core_driver *pudev, uint8_t lun); + +static inline int8_t scsi_check_address_range (usb_core_driver *pudev, uint8_t lun, uint32_t blk_offset, uint16_t blk_nbr); +static inline int8_t scsi_format_cmd (usb_core_driver *pudev, uint8_t lun); +static inline int8_t scsi_start_stop_unit (usb_core_driver *pudev, uint8_t lun, uint8_t *params); +static inline int8_t scsi_allow_medium_removal (usb_core_driver *pudev, uint8_t lun, uint8_t *params); + +/*! + \brief process SCSI commands + \param[in] pudev: pointer to USB device instance + \param[in] lun: logical unit number + \param[in] params: command parameters + \param[out] none + \retval status +*/ +int8_t scsi_process_cmd(usb_core_driver *pudev, uint8_t lun, uint8_t *params) +{ + switch (params[0]) { + case SCSI_TEST_UNIT_READY: + return scsi_test_unit_ready (pudev, lun, params); + + case SCSI_REQUEST_SENSE: + return scsi_request_sense (pudev, lun, params); + + case SCSI_INQUIRY: + return scsi_inquiry (pudev, lun, params); + + case SCSI_START_STOP_UNIT: + return scsi_start_stop_unit (pudev, lun, params); + + case SCSI_ALLOW_MEDIUM_REMOVAL: + return scsi_allow_medium_removal (pudev, lun, params); + + case SCSI_MODE_SENSE6: + return scsi_mode_sense6 (pudev, lun, params); + + case SCSI_MODE_SENSE10: + return scsi_mode_sense10 (pudev, lun, params); + + case SCSI_READ_FORMAT_CAPACITIES: + return scsi_read_format_capacity (pudev, lun, params); + + case SCSI_READ_CAPACITY10: + return scsi_read_capacity10 (pudev, lun, params); + + case SCSI_READ10: + return scsi_read10 (pudev, lun, params); + + case SCSI_WRITE10: + return scsi_write10 (pudev, lun, params); + + case SCSI_VERIFY10: + return scsi_verify10 (pudev, lun, params); + + case SCSI_FORMAT_UNIT: + return scsi_format_cmd (pudev, lun); + + case SCSI_READ_TOC_DATA: + return scsi_toc_cmd_read (pudev, lun, params); + + case SCSI_MODE_SELECT6: + return scsi_mode_select6 (pudev, lun, params); + + case SCSI_MODE_SELECT10: + return scsi_mode_select10 (pudev, lun, params); + + default: + scsi_sense_code (pudev, lun, ILLEGAL_REQUEST, INVALID_CDB); + return -1; + } +} + +/*! + \brief load the last error code in the error list + \param[in] pudev: pointer to USB device instance + \param[in] lun: logical unit number + \param[in] skey: sense key + \param[in] asc: additional aense key + \param[out] none + \retval none +*/ +void scsi_sense_code (usb_core_driver *pudev, uint8_t lun, uint8_t skey, uint8_t asc) +{ + usbd_msc_handler *msc = (usbd_msc_handler *)pudev->dev.class_data[USBD_MSC_INTERFACE]; + + msc->scsi_sense[msc->scsi_sense_tail].SenseKey = skey; + msc->scsi_sense[msc->scsi_sense_tail].ASC = asc << 8U; + msc->scsi_sense_tail++; + + if (SENSE_LIST_DEEPTH == msc->scsi_sense_tail) { + msc->scsi_sense_tail = 0U; + } +} + +/*! + \brief process SCSI Test Unit Ready command + \param[in] pudev: pointer to USB device instance + \param[in] lun: logical unit number + \param[in] params: command parameters + \param[out] none + \retval status +*/ +static int8_t scsi_test_unit_ready (usb_core_driver *pudev, uint8_t lun, uint8_t *params) +{ + usbd_msc_handler *msc = (usbd_msc_handler *)pudev->dev.class_data[USBD_MSC_INTERFACE]; + + /* case 9 : Hi > D0 */ + if (0U != msc->bbb_cbw.dCBWDataTransferLength) { + scsi_sense_code (pudev, msc->bbb_cbw.bCBWLUN, ILLEGAL_REQUEST, INVALID_CDB); + + return -1; + } + + if (0 != usbd_mem_fops->mem_ready(lun)) { + scsi_sense_code(pudev, lun, NOT_READY, MEDIUM_NOT_PRESENT); + + return -1; + } + + msc->bbb_datalen = 0U; + + return 0; +} + +/*! + \brief process Inquiry command + \param[in] udev: pointer to USB device instance + \param[in] lun: logical unit number + \param[in] params: command parameters + \param[out] none + \retval status +*/ +static int8_t scsi_mode_select6 (usb_core_driver *pudev, uint8_t lun, uint8_t *params) +{ + usbd_msc_handler *msc = (usbd_msc_handler *)pudev->dev.class_data[USBD_MSC_INTERFACE]; + + msc->bbb_datalen = 0U; + + return 0; +} + +/*! + \brief process Inquiry command + \param[in] udev: pointer to USB device instance + \param[in] lun: logical unit number + \param[in] params: command parameters + \param[out] none + \retval status +*/ +static int8_t scsi_mode_select10 (usb_core_driver *pudev, uint8_t lun, uint8_t *params) +{ + usbd_msc_handler *msc = (usbd_msc_handler *)pudev->dev.class_data[USBD_MSC_INTERFACE]; + + msc->bbb_datalen = 0U; + + return 0; +} + +/*! + \brief process Inquiry command + \param[in] pudev: pointer to USB device instance + \param[in] lun: logical unit number + \param[in] params: command parameters + \param[out] none + \retval status +*/ +static int8_t scsi_inquiry (usb_core_driver *pudev, uint8_t lun, uint8_t *params) +{ + uint8_t *page = NULL; + uint16_t len = 0U; + + usbd_msc_handler *msc = (usbd_msc_handler *)pudev->dev.class_data[USBD_MSC_INTERFACE]; + + if (params[1] & 0x01U) { + /* Evpd is set */ + page = (uint8_t *)msc_page00_inquiry_data; + + len = INQUIRY_PAGE00_LENGTH; + } else { + page = (uint8_t *)usbd_mem_fops->mem_inquiry_data[lun]; + + len = (uint16_t)(page[4] + 5U); + + if (params[4] <= len) { + len = params[4]; + } + } + + msc->bbb_datalen = len; + + while (len) { + len--; + msc->bbb_data[len] = page[len]; + } + + return 0; +} + +/*! + \brief process Read Capacity 10 command + \param[in] pudev: pointer to USB device instance + \param[in] lun: logical unit number + \param[in] params: command parameters + \param[out] none + \retval status +*/ +static int8_t scsi_read_capacity10 (usb_core_driver *pudev, uint8_t lun, uint8_t *params) +{ + uint32_t blk_num = usbd_mem_fops->mem_block_len[lun] - 1U; + usbd_msc_handler *msc = (usbd_msc_handler *)pudev->dev.class_data[USBD_MSC_INTERFACE]; + + msc->scsi_blk_nbr[lun] = usbd_mem_fops->mem_block_len[lun]; + msc->scsi_blk_size[lun] = usbd_mem_fops->mem_block_size[lun]; + + msc->bbb_data[0] = (uint8_t)(blk_num >> 24U); + msc->bbb_data[1] = (uint8_t)(blk_num >> 16U); + msc->bbb_data[2] = (uint8_t)(blk_num >> 8U); + msc->bbb_data[3] = (uint8_t)(blk_num); + + msc->bbb_data[4] = (uint8_t)(msc->scsi_blk_size[lun] >> 24U); + msc->bbb_data[5] = (uint8_t)(msc->scsi_blk_size[lun] >> 16U); + msc->bbb_data[6] = (uint8_t)(msc->scsi_blk_size[lun] >> 8U); + msc->bbb_data[7] = (uint8_t)(msc->scsi_blk_size[lun]); + + msc->bbb_datalen = 8U; + + return 0; +} + +/*! + \brief process Read Format Capacity command + \param[in] pudev: pointer to USB device instance + \param[in] lun: logical unit number + \param[in] params: command parameters + \param[out] none + \retval status +*/ +static int8_t scsi_read_format_capacity (usb_core_driver *pudev, uint8_t lun, uint8_t *params) +{ + uint16_t i = 0U; + uint32_t blk_size = usbd_mem_fops->mem_block_size[lun]; + uint32_t blk_num = usbd_mem_fops->mem_block_len[lun]; + uint32_t blk_nbr = blk_num - 1U; + + usbd_msc_handler *msc = (usbd_msc_handler *)pudev->dev.class_data[USBD_MSC_INTERFACE]; + + for (i = 0U; i < 12U; i++) { + msc->bbb_data[i] = 0U; + } + + msc->bbb_data[3] = 0x08U; + msc->bbb_data[4] = (uint8_t)(blk_nbr >> 24U); + msc->bbb_data[5] = (uint8_t)(blk_nbr >> 16U); + msc->bbb_data[6] = (uint8_t)(blk_nbr >> 8U); + msc->bbb_data[7] = (uint8_t)(blk_nbr); + + msc->bbb_data[8] = 0x02U; + msc->bbb_data[9] = (uint8_t)(blk_size >> 16U); + msc->bbb_data[10] = (uint8_t)(blk_size >> 8U); + msc->bbb_data[11] = (uint8_t)(blk_size); + + msc->bbb_datalen = 12U; + + return 0; +} + +/*! + \brief process Mode Sense6 command + \param[in] pudev: pointer to USB device instance + \param[in] lun: logical unit number + \param[in] params: command parameters + \param[out] none + \retval status +*/ +static int8_t scsi_mode_sense6 (usb_core_driver *pudev, uint8_t lun, uint8_t *params) +{ + uint16_t len = 8U; + usbd_msc_handler *msc = (usbd_msc_handler *)pudev->dev.class_data[USBD_MSC_INTERFACE]; + + msc->bbb_datalen = len; + + while (len) { + len--; + msc->bbb_data[len] = msc_mode_sense6_data[len]; + } + + return 0; +} + +/*! + \brief process Mode Sense10 command + \param[in] pudev: pointer to USB device instance + \param[in] lun: logical unit number + \param[in] params: command parameters + \param[out] none + \retval status +*/ +static int8_t scsi_mode_sense10 (usb_core_driver *pudev, uint8_t lun, uint8_t *params) +{ + uint16_t len = 8U; + usbd_msc_handler *msc = (usbd_msc_handler *)pudev->dev.class_data[USBD_MSC_INTERFACE]; + + msc->bbb_datalen = len; + + while (len) { + len--; + msc->bbb_data[len] = msc_mode_sense10_data[len]; + } + + return 0; +} + +/*! + \brief process Request Sense command + \param[in] pudev: pointer to USB device instance + \param[in] lun: logical unit number + \param[in] params: command parameters + \param[out] none + \retval status +*/ +static int8_t scsi_request_sense (usb_core_driver *pudev, uint8_t lun, uint8_t *params) +{ + uint8_t i = 0U; + usbd_msc_handler *msc = (usbd_msc_handler *)pudev->dev.class_data[USBD_MSC_INTERFACE]; + + for (i = 0U; i < REQUEST_SENSE_DATA_LEN; i++) { + msc->bbb_data[i] = 0U; + } + + msc->bbb_data[0] = 0x70U; + msc->bbb_data[7] = REQUEST_SENSE_DATA_LEN - 6U; + + if ((msc->scsi_sense_head != msc->scsi_sense_tail)) { + msc->bbb_data[2] = msc->scsi_sense[msc->scsi_sense_head].SenseKey; + msc->bbb_data[12] = msc->scsi_sense[msc->scsi_sense_head].ASCQ; + msc->bbb_data[13] = msc->scsi_sense[msc->scsi_sense_head].ASC; + msc->scsi_sense_head++; + + if (msc->scsi_sense_head == SENSE_LIST_DEEPTH) { + msc->scsi_sense_head = 0U; + } + } + + msc->bbb_datalen = USB_MIN(REQUEST_SENSE_DATA_LEN, params[4]); + + return 0; +} + +/*! + \brief process Start Stop Unit command + \param[in] pudev: pointer to USB device instance + \param[in] lun: logical unit number + \param[in] params: command parameters + \param[out] none + \retval status +*/ +static inline int8_t scsi_start_stop_unit (usb_core_driver *pudev, uint8_t lun, uint8_t *params) +{ + usbd_msc_handler *msc = (usbd_msc_handler *)pudev->dev.class_data[USBD_MSC_INTERFACE]; + + msc->bbb_datalen = 0U; + msc->scsi_disk_pop = 1U; + + return 0; +} + +/*! + \brief process Allow Medium Removal command + \param[in] pudev: pointer to USB device instance + \param[in] lun: logical unit number + \param[in] params: command parameters + \param[out] none + \retval status +*/ +static inline int8_t scsi_allow_medium_removal (usb_core_driver *pudev, uint8_t lun, uint8_t *params) +{ + usbd_msc_handler *msc = (usbd_msc_handler *)pudev->dev.class_data[USBD_MSC_INTERFACE]; + + msc->bbb_datalen = 0U; + + return 0; +} + +/*! + \brief process Read10 command + \param[in] pudev: pointer to USB device instance + \param[in] lun: logical unit number + \param[in] params: command parameters + \param[out] none + \retval status +*/ +static int8_t scsi_read10 (usb_core_driver *pudev, uint8_t lun, uint8_t *params) +{ + usbd_msc_handler *msc = (usbd_msc_handler *)pudev->dev.class_data[USBD_MSC_INTERFACE]; + + if (msc->bbb_state == BBB_IDLE) { + /* direction is from device to host */ + if (0x80U != (msc->bbb_cbw.bmCBWFlags & 0x80U)) { + scsi_sense_code (pudev, msc->bbb_cbw.bCBWLUN, ILLEGAL_REQUEST, INVALID_CDB); + + return -1; + } + + if (0 != usbd_mem_fops->mem_ready(lun)) { + scsi_sense_code (pudev, lun, NOT_READY, MEDIUM_NOT_PRESENT); + + return -1; + } + + msc->scsi_blk_addr = (params[2] << 24U) | (params[3] << 16U) | \ + (params[4] << 8U) | params[5]; + + msc->scsi_blk_len = (params[7] << 8U) | params[8]; + + if (scsi_check_address_range (pudev, lun, msc->scsi_blk_addr, (uint16_t)msc->scsi_blk_len) < 0) { + return -1; /* error */ + } + + msc->bbb_state = BBB_DATA_IN; + + msc->scsi_blk_addr *= msc->scsi_blk_size[lun]; + msc->scsi_blk_len *= msc->scsi_blk_size[lun]; + + /* cases 4,5 : Hi <> Dn */ + if (msc->bbb_cbw.dCBWDataTransferLength != msc->scsi_blk_len) { + scsi_sense_code (pudev, msc->bbb_cbw.bCBWLUN, ILLEGAL_REQUEST, INVALID_CDB); + + return -1; + } + } + + msc->bbb_datalen = MSC_MEDIA_PACKET_SIZE; + + return scsi_process_read (pudev, lun); +} + +/*! + \brief process Write10 command + \param[in] pudev: pointer to USB device instance + \param[in] lun: logical unit number + \param[in] params: command parameters + \param[out] none + \retval status +*/ +static int8_t scsi_write10 (usb_core_driver *pudev, uint8_t lun, uint8_t *params) +{ + usbd_msc_handler *msc = (usbd_msc_handler *)pudev->dev.class_data[USBD_MSC_INTERFACE]; + + if (BBB_IDLE == msc->bbb_state) { + /* case 8 : Hi <> Do */ + if (0x80U == (msc->bbb_cbw.bmCBWFlags & 0x80U)) { + scsi_sense_code (pudev, msc->bbb_cbw.bCBWLUN, ILLEGAL_REQUEST, INVALID_CDB); + + return -1; + } + + /* check whether media is ready */ + if (0 != usbd_mem_fops->mem_ready(lun)) { + scsi_sense_code (pudev, lun, NOT_READY, MEDIUM_NOT_PRESENT); + + return -1; + } + + /* check if media is write-protected */ + if (0 != usbd_mem_fops->mem_protected(lun)) { + scsi_sense_code (pudev, lun, NOT_READY, WRITE_PROTECTED); + + return -1; + } + + msc->scsi_blk_addr = (params[2] << 24U) | (params[3] << 16U) | \ + (params[4] << 8U) | params[5]; + + msc->scsi_blk_len = (params[7] << 8U) | params[8]; + + /* check if LBA address is in the right range */ + if (scsi_check_address_range (pudev, lun, msc->scsi_blk_addr, (uint16_t)msc->scsi_blk_len) < 0) { + return -1; /* error */ + } + + msc->scsi_blk_addr *= msc->scsi_blk_size[lun]; + msc->scsi_blk_len *= msc->scsi_blk_size[lun]; + + /* cases 3,11,13 : Hn,Ho <> D0 */ + if (msc->bbb_cbw.dCBWDataTransferLength != msc->scsi_blk_len) { + scsi_sense_code (pudev, msc->bbb_cbw.bCBWLUN, ILLEGAL_REQUEST, INVALID_CDB); + + return -1; + } + + /* prepare endpoint to receive first data packet */ + msc->bbb_state = BBB_DATA_OUT; + + usbd_ep_recev (pudev, + MSC_OUT_EP, + msc->bbb_data, + USB_MIN (msc->scsi_blk_len, MSC_MEDIA_PACKET_SIZE)); + } else { /* write process ongoing */ + return scsi_process_write (pudev, lun); + } + + return 0; +} + +/*! + \brief process Verify10 command + \param[in] pudev: pointer to USB device instance + \param[in] lun: logical unit number + \param[in] params: command parameters + \param[out] none + \retval status +*/ +static int8_t scsi_verify10 (usb_core_driver *pudev, uint8_t lun, uint8_t *params) +{ + usbd_msc_handler *msc = (usbd_msc_handler *)pudev->dev.class_data[USBD_MSC_INTERFACE]; + + if (0x02U == (params[1] & 0x02U)) { + scsi_sense_code (pudev, lun, ILLEGAL_REQUEST, INVALID_FIELED_IN_COMMAND); + + return -1; /* error, verify mode not supported*/ + } + + if (scsi_check_address_range (pudev, lun, msc->scsi_blk_addr, (uint16_t)msc->scsi_blk_len) < 0) { + return -1; /* error */ + } + + msc->bbb_datalen = 0U; + + return 0; +} + +/*! + \brief check address range + \param[in] pudev: pointer to USB device instance + \param[in] lun: logical unit number + \param[in] blk_offset: block offset + \param[in] blk_nbr: number of block to be processed + \param[out] none + \retval status +*/ +static inline int8_t scsi_check_address_range (usb_core_driver *pudev, uint8_t lun, uint32_t blk_offset, uint16_t blk_nbr) +{ + usbd_msc_handler *msc = (usbd_msc_handler *)pudev->dev.class_data[USBD_MSC_INTERFACE]; + + if ((blk_offset + blk_nbr) > msc->scsi_blk_nbr[lun]) { + scsi_sense_code (pudev, lun, ILLEGAL_REQUEST, ADDRESS_OUT_OF_RANGE); + + return -1; + } + + return 0; +} + +/*! + \brief handle read process + \param[in] pudev: pointer to USB device instance + \param[in] lun: logical unit number + \param[out] none + \retval status +*/ +static int8_t scsi_process_read (usb_core_driver *pudev, uint8_t lun) +{ + usbd_msc_handler *msc = (usbd_msc_handler *)pudev->dev.class_data[USBD_MSC_INTERFACE]; + + uint32_t len = USB_MIN(msc->scsi_blk_len, MSC_MEDIA_PACKET_SIZE); + + if (usbd_mem_fops->mem_read(lun, + msc->bbb_data, + msc->scsi_blk_addr, + (uint16_t)(len / msc->scsi_blk_size[lun])) < 0) { + scsi_sense_code(pudev, lun, HARDWARE_ERROR, UNRECOVERED_READ_ERROR); + + return -1; + } + + usbd_ep_send (pudev, MSC_IN_EP, msc->bbb_data, len); + + msc->scsi_blk_addr += len; + msc->scsi_blk_len -= len; + + /* case 6 : Hi = Di */ + msc->bbb_csw.dCSWDataResidue -= len; + + if (0U == msc->scsi_blk_len) { + msc->bbb_state = BBB_LAST_DATA_IN; + } + + return 0; +} + +/*! + \brief handle write process + \param[in] pudev: pointer to USB device instance + \param[in] lun: logical unit number + \param[out] none + \retval status +*/ +static int8_t scsi_process_write (usb_core_driver *pudev, uint8_t lun) +{ + usbd_msc_handler *msc = (usbd_msc_handler *)pudev->dev.class_data[USBD_MSC_INTERFACE]; + + uint32_t len = USB_MIN(msc->scsi_blk_len, MSC_MEDIA_PACKET_SIZE); + + if (usbd_mem_fops->mem_write (lun, + msc->bbb_data, + msc->scsi_blk_addr, + (uint16_t)(len / msc->scsi_blk_size[lun])) < 0) { + scsi_sense_code(pudev, lun, HARDWARE_ERROR, WRITE_FAULT); + + return -1; + } + + msc->scsi_blk_addr += len; + msc->scsi_blk_len -= len; + + /* case 12 : Ho = Do */ + msc->bbb_csw.dCSWDataResidue -= len; + + if (0U == msc->scsi_blk_len) { + msc_bbb_csw_send (pudev, CSW_CMD_PASSED); + } else { + /* prapare endpoint to receive next packet */ + usbd_ep_recev (pudev, + MSC_OUT_EP, + msc->bbb_data, + USB_MIN (msc->scsi_blk_len, MSC_MEDIA_PACKET_SIZE)); + } + + return 0; +} + +/*! + \brief process Format Unit command + \param[in] pudev: pointer to USB device instance + \param[in] lun: logical unit number + \param[out] none + \retval status +*/ +static inline int8_t scsi_format_cmd (usb_core_driver *pudev, uint8_t lun) +{ + return 0; +} + +/*! + \brief process Read_Toc command + \param[in] pudev: pointer to USB device instance + \param[in] lun: logical unit number + \param[in] params: command parameters + \param[out] none + \retval status +*/ +static int8_t scsi_toc_cmd_read (usb_core_driver *pudev, uint8_t lun, uint8_t *params) +{ + uint8_t* pPage; + uint16_t len; + + usbd_msc_handler *msc = (usbd_msc_handler *)pudev->dev.class_data[USBD_MSC_INTERFACE]; + + pPage = (uint8_t *)&usbd_mem_fops->mem_toc_data[lun * READ_TOC_CMD_LEN]; + len = (uint16_t)pPage[1] + 2U; + + msc->bbb_datalen = len; + + while (len) { + len--; + msc->bbb_data[len] = pPage[len]; + } + + return 0; +} diff --git a/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/device/class/printer/Include/printer_core.h b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/device/class/printer/Include/printer_core.h new file mode 100644 index 0000000000..3e32cd603c --- /dev/null +++ b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/device/class/printer/Include/printer_core.h @@ -0,0 +1,78 @@ +/*! + \file printer_core.h + \brief the header file of USB printer device class core functions + + \version 2020-08-01, V3.0.0, firmware for GD32F30x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef __PRINTER_CORE_H +#define __PRINTER_CORE_H + +#include "usbd_enum.h" +#include "usb_ch9_std.h" + +/* USB printing device class code */ +#define USB_CLASS_PRINTER 0x07U + +/* printing device subclass code */ +#define USB_SUBCLASS_PRINTER 0x01U + +/* printing device protocol code */ +#define PROTOCOL_UNIDIRECTIONAL_ITF 0x01U +#define PROTOCOL_BI_DIRECTIONAL_ITF 0x02U +#define PROTOCOL_1284_4_ITF 0x03U +#define PROTOCOL_VENDOR 0xFFU + +#define DEVICE_ID_LEN 103U + +#define USB_PRINTER_CONFIG_DESC_LEN 32U + +/* printing device specific-class request */ +#define GET_DEVICE_ID 0x00U +#define GET_PORT_STATUS 0x01U +#define SOFT_RESET 0x02U + +#pragma pack(1) + +/* USB configuration descriptor struct */ +typedef struct +{ + usb_desc_config config; + usb_desc_itf printer_itf; + usb_desc_ep printer_epin; + usb_desc_ep printer_epout; +} usb_printer_desc_config_set; + +#pragma pack() + +extern usb_desc printer_desc; +extern usb_class_core usbd_printer_cb; + +#endif /* __PRINTER_CORE_H */ diff --git a/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/device/class/printer/Source/printer_core.c b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/device/class/printer/Source/printer_core.c new file mode 100644 index 0000000000..6f7ac0de91 --- /dev/null +++ b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/device/class/printer/Source/printer_core.c @@ -0,0 +1,309 @@ +/*! + \file printer_core.c + \brief USB printer device class core functions + + \version 2020-08-01, V3.0.0, firmware for GD32F30x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "printer_core.h" + +#define USBD_VID 0x28E9U +#define USBD_PID 0x028DU + +/* printer port status: paper not empty/selected/no error */ +static uint8_t g_port_status = 0x18U; + +uint8_t g_printer_data_buf[PRINTER_OUT_PACKET]; + +uint8_t PRINTER_DEVICE_ID[DEVICE_ID_LEN] = +{ + 0x00, 0x67, + 'M', 'A', 'N', 'U', 'F', 'A', 'C', 'T', 'U', 'R', 'E', 'R', ':', + 'G', 'I', 'G', 'A', ' ', 'D', 'E', 'V', 'I', 'C', 'E', '-', ';', + 'C', 'O', 'M', 'M', 'A', 'N', 'D', ' ', 'S', 'E', 'T', ':', + 'P', 'C', 'L', ',', 'M', 'P', 'L', ';', + 'M', 'O', 'D', 'E', 'L', ':', + 'L', 'a', 's', 'e', 'r', 'B', 'e', 'a', 'm', '?', ';', + 'C', 'O', 'M', 'M', 'E', 'N', 'T', ':', + 'G', 'o', 'o', 'd', ' ', '!', ';', + 'A', 'C', 'T', 'I', 'V', 'E', ' ', 'C', 'O', 'M', 'M', 'A', 'N', 'D', ' ', 'S', 'E', 'T', ':', + 'P', 'C', 'L', ';' +}; + +/* USB standard device descriptor */ +const usb_desc_dev printer_dev_desc = +{ + .header = + { + .bLength = USB_DEV_DESC_LEN, + .bDescriptorType = USB_DESCTYPE_DEV, + }, + .bcdUSB = 0x0200U, + .bDeviceClass = 0x00U, + .bDeviceSubClass = 0x00U, + .bDeviceProtocol = 0x00U, + .bMaxPacketSize0 = USB_FS_EP0_MAX_LEN, + .idVendor = USBD_VID, + .idProduct = USBD_PID, + .bcdDevice = 0x0100U, + .iManufacturer = STR_IDX_MFC, + .iProduct = STR_IDX_PRODUCT, + .iSerialNumber = STR_IDX_SERIAL, + .bNumberConfigurations = USBD_CFG_MAX_NUM, +}; +/* USB device configuration descriptor */ +const usb_printer_desc_config_set printer_config_desc = +{ + .config = + { + .header = + { + .bLength = sizeof(usb_desc_config), + .bDescriptorType = USB_DESCTYPE_CONFIG + }, + .wTotalLength = USB_PRINTER_CONFIG_DESC_LEN, + .bNumInterfaces = 0x01U, + .bConfigurationValue = 0x01U, + .iConfiguration = 0x00U, + .bmAttributes = 0xA0U, + .bMaxPower = 0x32U + }, + + .printer_itf = + { + .header = + { + .bLength = sizeof(usb_desc_itf), + .bDescriptorType = USB_DESCTYPE_ITF + }, + .bInterfaceNumber = 0x00U, + .bAlternateSetting = 0x00U, + .bNumEndpoints = 0x02U, + .bInterfaceClass = USB_CLASS_PRINTER, + .bInterfaceSubClass = USB_SUBCLASS_PRINTER, + .bInterfaceProtocol = PROTOCOL_BI_DIRECTIONAL_ITF, + .iInterface = 0x00U + }, + + .printer_epin = + { + .header = + { + .bLength = sizeof(usb_desc_ep), + .bDescriptorType = USB_DESCTYPE_EP + }, + .bEndpointAddress = PRINTER_IN_EP, + .bmAttributes = USB_EP_ATTR_BULK, + .wMaxPacketSize = PRINTER_IN_PACKET, + .bInterval = 0x00U + }, + + .printer_epout = + { + .header = + { + .bLength = sizeof(usb_desc_ep), + .bDescriptorType = USB_DESCTYPE_EP + }, + .bEndpointAddress = PRINTER_OUT_EP, + .bmAttributes = USB_EP_ATTR_BULK, + .wMaxPacketSize = PRINTER_OUT_PACKET, + .bInterval = 0x00U + }, +}; + +/* USB language ID Descriptor */ +static const usb_desc_LANGID usbd_language_id_desc = +{ + .header = + { + .bLength = sizeof(usb_desc_LANGID), + .bDescriptorType = USB_DESCTYPE_STR, + }, + .wLANGID = ENG_LANGID +}; + +/* USB manufacture string */ +static const usb_desc_str manufacturer_string = +{ + .header = + { + .bLength = USB_STRING_LEN(10U), + .bDescriptorType = USB_DESCTYPE_STR, + }, + .unicode_string = {'G', 'i', 'g', 'a', 'D', 'e', 'v', 'i', 'c', 'e'} +}; + +/* USB product string */ +static const usb_desc_str product_string = +{ + .header = + { + .bLength = USB_STRING_LEN(16U), + .bDescriptorType = USB_DESCTYPE_STR, + }, + .unicode_string = {'G', 'D', '3', '2', '-', 'U', 'S', 'B', '_', 'P', 'r', 'i', 'n', 't', 'e', 'r'} +}; + +/* USBD serial string */ +static usb_desc_str serial_string = +{ + .header = + { + .bLength = USB_STRING_LEN(12U), + .bDescriptorType = USB_DESCTYPE_STR, + } +}; + +/* USB string descriptor */ +static void *const usbd_msc_strings[] = +{ + [STR_IDX_LANGID] = (uint8_t *)&usbd_language_id_desc, + [STR_IDX_MFC] = (uint8_t *)&manufacturer_string, + [STR_IDX_PRODUCT] = (uint8_t *)&product_string, + [STR_IDX_SERIAL] = (uint8_t *)&serial_string +}; + +usb_desc printer_desc = { + .dev_desc = (uint8_t *)&printer_dev_desc, + .config_desc = (uint8_t *)&printer_config_desc, + .strings = usbd_msc_strings +}; + +/* local function prototypes ('static') */ +static uint8_t printer_init (usb_dev *udev, uint8_t config_index); +static uint8_t printer_deinit (usb_dev *udev, uint8_t config_index); +static uint8_t printer_req (usb_dev *udev, usb_req *req); +static uint8_t printer_in (usb_dev *udev, uint8_t ep_num); +static uint8_t printer_out (usb_dev *udev, uint8_t ep_num); + +usb_class_core usbd_printer_cb = { + .init = printer_init, + .deinit = printer_deinit, + + .req_proc = printer_req, + + .data_in = printer_in, + .data_out = printer_out +}; + +/*! + \brief initialize the printer device + \param[in] udev: pointer to usb device instance + \param[in] config_index: configuration index + \param[out] none + \retval usb device operation status +*/ +static uint8_t printer_init (usb_dev *udev, uint8_t config_index) +{ + /* initialize the data Tx endpoint */ + usbd_ep_setup (udev, &(printer_config_desc.printer_epin)); + + /* initialize the data Rx endpoint */ + usbd_ep_setup (udev, &(printer_config_desc.printer_epout)); + + /* prepare to receive data */ + usbd_ep_recev(udev, PRINTER_OUT_EP, g_printer_data_buf, PRINTER_OUT_PACKET); + + return USBD_OK; +} + +/*! + \brief de-initialize the printer device + \param[in] udev: pointer to usb device instance + \param[in] config_index: configuration index + \param[out] none + \retval usb device operation status +*/ +static uint8_t printer_deinit (usb_dev *udev, uint8_t config_index) +{ + /* deinitialize the data Tx/Rx endpoint */ + usbd_ep_clear (udev, PRINTER_IN_EP); + usbd_ep_clear (udev, PRINTER_OUT_EP); + + return USBD_OK; +} + +/*! + \brief handle the printer class-specific requests + \param[in] udev: pointer to usb device instance + \param[in] req: device class-specific request + \param[out] none + \retval usb device operation status +*/ +static uint8_t printer_req(usb_dev *udev, usb_req *req) +{ + usb_transc *transc = &udev->dev.transc_in[0]; + + switch (req->bRequest) { + case GET_DEVICE_ID: + transc->xfer_buf = (uint8_t *)PRINTER_DEVICE_ID; + transc->remain_len = DEVICE_ID_LEN; + break; + + case GET_PORT_STATUS: + transc->xfer_buf = (uint8_t *)&g_port_status; + transc->remain_len = 1U; + break; + + case SOFT_RESET: + usbd_ep_recev(udev, PRINTER_OUT_EP, g_printer_data_buf, PRINTER_OUT_PACKET); + break; + + default: + return USBD_FAIL; + } + + return USBD_OK; +} + +/*! + \brief handle printer data + \param[in] udev: pointer to USB device instance + \param[in] ep_num: endpoint number + \param[out] none + \retval USB device operation status +*/ +static uint8_t printer_in (usb_dev *udev, uint8_t ep_num) +{ + return USBD_OK; +} + +/*! + \brief handle printer data + \param[in] udev: pointer to USB device instance + \param[in] ep_num: endpoint number + \param[out] none + \retval USB device operation status +*/ +static uint8_t printer_out (usb_dev *udev, uint8_t ep_num) +{ + return USBD_OK; +} diff --git a/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/device/core/Include/usbd_core.h b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/device/core/Include/usbd_core.h new file mode 100644 index 0000000000..cdfdeac1c7 --- /dev/null +++ b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/device/core/Include/usbd_core.h @@ -0,0 +1,103 @@ +/*! + \file usbd_core.h + \brief USB device mode core functions protype + + \version 2020-08-01, V3.0.0, firmware for GD32F30x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef __USBD_CORE_H +#define __USBD_CORE_H + +#include "drv_usb_core.h" +#include "drv_usb_dev.h" + +typedef enum +{ + USBD_OK = 0U, /*!< status OK */ + USBD_BUSY, /*!< status busy */ + USBD_FAIL, /*!< status fail */ +} usbd_status; + +enum _usbd_status { + USBD_DEFAULT = 1U, /*!< default status */ + USBD_ADDRESSED = 2U, /*!< address send status */ + USBD_CONFIGURED = 3U, /*!< configured status */ + USBD_SUSPENDED = 4U /*!< suspended status */ +}; + +/* static inline function definitions */ + +/*! + \brief set USB device address + \param[in] udev: pointer to USB core instance + \param[in] addr: device address to set + \param[out] none + \retval none +*/ +__STATIC_INLINE void usbd_addr_set (usb_core_driver *udev, uint8_t addr) +{ + usb_devaddr_set(udev, addr); +} + +/*! + \brief get the received data length + \param[in] udev: pointer to USB device instance + \param[in] ep_num: endpoint number + \param[out] none + \retval USB device operation cur_status +*/ +__STATIC_INLINE uint16_t usbd_rxcount_get (usb_core_driver *udev, uint8_t ep_num) +{ + return (uint16_t)udev->dev.transc_out[ep_num].xfer_count; +} + +/* function declarations */ +/* initializes the USB device-mode stack and load the class driver */ +void usbd_init (usb_core_driver *udev, usb_core_enum core, usb_desc *desc, usb_class_core *class_core); +/* endpoint initialization */ +uint32_t usbd_ep_setup (usb_core_driver *udev, const usb_desc_ep *ep_desc); +/* configure the endpoint when it is disabled */ +uint32_t usbd_ep_clear (usb_core_driver *udev, uint8_t ep_addr); +/* endpoint prepare to receive data */ +uint32_t usbd_ep_recev (usb_core_driver *udev, uint8_t ep_addr, uint8_t *pbuf, uint32_t len); +/* endpoint prepare to transmit data */ +uint32_t usbd_ep_send (usb_core_driver *udev, uint8_t ep_addr, uint8_t *pbuf, uint32_t len); +/* set an endpoint to STALL status */ +uint32_t usbd_ep_stall (usb_core_driver *udev, uint8_t ep_addr); +/* clear endpoint STALLed status */ +uint32_t usbd_ep_stall_clear (usb_core_driver *udev, uint8_t ep_addr); +/* flush the endpoint FIFOs */ +uint32_t usbd_fifo_flush (usb_core_driver *udev, uint8_t ep_addr); +/* device connect */ +void usbd_connect (usb_core_driver *udev); +/* device disconnect */ +void usbd_disconnect (usb_core_driver *udev); + +#endif /* __USBD_CORE_H */ diff --git a/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/device/core/Include/usbd_enum.h b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/device/core/Include/usbd_enum.h new file mode 100644 index 0000000000..0a2223bde4 --- /dev/null +++ b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/device/core/Include/usbd_enum.h @@ -0,0 +1,105 @@ +/*! + \file usbd_enum.h + \brief USB enumeration definitions + + \version 2020-08-01, V3.0.0, firmware for GD32F30x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef __USBD_ENUM_H +#define __USBD_ENUM_H + +#include "usbd_core.h" +#include "usbd_conf.h" +#include + +#ifndef NULL + #define NULL 0U +#endif + +typedef enum _usb_reqsta { + REQ_SUPP = 0x0U, /* request support */ + REQ_NOTSUPP = 0x1U, /* request not support */ +} usb_reqsta; + +/* string descriptor index */ +enum _str_index +{ + STR_IDX_LANGID = 0x0U, /* language ID string index */ + STR_IDX_MFC = 0x1U, /* manufacturer string index */ + STR_IDX_PRODUCT = 0x2U, /* product string index */ + STR_IDX_SERIAL = 0x3U, /* serial string index */ + STR_IDX_CONFIG = 0x4U, /* configuration string index */ + STR_IDX_ITF = 0x5U, /* interface string index */ +#ifndef WINUSB_EXEMPT_DRIVER + STR_IDX_MAX = 0x6U, /* string maximum index */ +#else + STR_IDX_MAX = 0xEFU, /* string maximum index */ +#endif /* WINUSB_EXEMPT_DRIVER */ +}; + +typedef enum _usb_pwrsta { + USB_PWRSTA_SELF_POWERED = 0x1U, /* USB is in self powered status */ + USB_PWRSTA_REMOTE_WAKEUP = 0x2U, /* USB is in remote wakeup status */ +} usb_pwrsta; + +typedef enum _usb_feature +{ + USB_FEATURE_EP_HALT = 0x0U, /* USB has endpoint halt feature */ + USB_FEATURE_REMOTE_WAKEUP = 0x1U, /* USB has endpoint remote wakeup feature */ + USB_FEATURE_TEST_MODE = 0x2U, /* USB has endpoint test mode feature */ +} usb_feature; + +#define ENG_LANGID 0x0409U /* english language ID */ +#define CHN_LANGID 0x0804U /* chinese language ID */ + +/* USB device exported macros */ +#define CTL_EP(ep) (((ep) == 0x00U) || ((ep) == 0x80U)) + +#define DEVICE_ID1 (0x1FFFF7E8U) /* device ID1 */ +#define DEVICE_ID2 (0x1FFFF7ECU) /* device ID2 */ +#define DEVICE_ID3 (0x1FFFF7F0U) /* device ID3 */ + +#define DEVICE_ID (0x40022100U) + +/* function declarations */ +/* handle USB standard device request */ +usb_reqsta usbd_standard_request (usb_core_driver *udev, usb_req *req); +/* handle USB device class request */ +usb_reqsta usbd_class_request (usb_core_driver *udev, usb_req *req); +/* handle USB vendor request */ +usb_reqsta usbd_vendor_request (usb_core_driver *udev, usb_req *req); +/* handle USB enumeration error */ +void usbd_enum_error (usb_core_driver *udev, usb_req *req); +/* convert hex 32bits value into unicode char */ +void int_to_unicode (uint32_t value, uint8_t *pbuf, uint8_t len); +/* get serial string */ +void serial_string_get (uint16_t *unicode_str); + +#endif /* __USBD_ENUM_H */ diff --git a/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/device/core/Include/usbd_transc.h b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/device/core/Include/usbd_transc.h new file mode 100644 index 0000000000..7bc1ac131d --- /dev/null +++ b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/device/core/Include/usbd_transc.h @@ -0,0 +1,56 @@ +/*! + \file usbd_transc.h + \brief USB transaction core functions prototype + + \version 2020-08-01, V3.0.0, firmware for GD32F30x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef __USBD_TRANSC_H +#define __USBD_TRANSC_H + +#include "usbd_core.h" + +/* function declarations */ +/* USB send data in the control transaction */ +usbd_status usbd_ctl_send (usb_core_driver *udev); +/* USB receive data in control transaction */ +usbd_status usbd_ctl_recev (usb_core_driver *udev); +/* USB send control transaction status */ +usbd_status usbd_ctl_status_send (usb_core_driver *udev); +/* USB control receive status */ +usbd_status usbd_ctl_status_recev (usb_core_driver *udev); +/* USB setup stage processing */ +uint8_t usbd_setup_transc (usb_core_driver *udev); +/* data out stage processing */ +uint8_t usbd_out_transc (usb_core_driver *udev, uint8_t ep_num); +/* data in stage processing */ +uint8_t usbd_in_transc (usb_core_driver *udev, uint8_t ep_num); + +#endif /* __USBD_TRANSC_H */ diff --git a/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/device/core/Source/usbd_core.c b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/device/core/Source/usbd_core.c new file mode 100644 index 0000000000..5ef0a41aaa --- /dev/null +++ b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/device/core/Source/usbd_core.c @@ -0,0 +1,320 @@ +/*! + \file usbd_core.c + \brief USB device mode core functions + + \version 2020-08-01, V3.0.0, firmware for GD32F30x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "usbd_core.h" +#include "usbd_enum.h" +#include "drv_usb_hw.h" + +/* endpoint type */ +const uint32_t ep_type[] = { + [USB_EP_ATTR_CTL] = (uint32_t)USB_EPTYPE_CTRL, + [USB_EP_ATTR_BULK] = (uint32_t)USB_EPTYPE_BULK, + [USB_EP_ATTR_INT] = (uint32_t)USB_EPTYPE_INTR, + [USB_EP_ATTR_ISO] = (uint32_t)USB_EPTYPE_ISOC +}; + +/*! + \brief initializes the USB device-mode stack and load the class driver + \param[in] udev: pointer to USB core instance + \param[in] core: USB core type + \param[in] desc: pointer to USB descriptor + \param[in] class_core: class driver + \param[out] none + \retval none +*/ +void usbd_init (usb_core_driver *udev, usb_core_enum core, usb_desc *desc, usb_class_core *class_core) +{ + udev->dev.desc = desc; + + /* class callbacks */ + udev->dev.class_core = class_core; + + /* create serial string */ + serial_string_get(udev->dev.desc->strings[STR_IDX_SERIAL]); + + /* configure USB capabilities */ + (void)usb_basic_init (&udev->bp, &udev->regs, core); + + usb_globalint_disable(&udev->regs); + + /* initializes the USB core*/ + (void)usb_core_init (udev->bp, &udev->regs); + + /* set device disconnect */ + usbd_disconnect (udev); + +#ifndef USE_OTG_MODE + usb_curmode_set(&udev->regs, DEVICE_MODE); +#endif + + /* initializes device mode */ + (void)usb_devcore_init (udev); + + usb_globalint_enable(&udev->regs); + + /* set device connect */ + usbd_connect (udev); + + udev->dev.cur_status = (uint8_t)USBD_DEFAULT; +} + +/*! + \brief endpoint initialization + \param[in] udev: pointer to USB core instance + \param[in] ep_desc: pointer to endpoint descriptor + \param[out] none + \retval none +*/ +uint32_t usbd_ep_setup (usb_core_driver *udev, const usb_desc_ep *ep_desc) +{ + usb_transc *transc; + + uint8_t ep_addr = ep_desc->bEndpointAddress; + uint16_t max_len = ep_desc->wMaxPacketSize; + + /* set endpoint direction */ + if (EP_DIR(ep_addr)) { + transc = &udev->dev.transc_in[EP_ID(ep_addr)]; + + transc->ep_addr.dir = 1U; + } else { + transc = &udev->dev.transc_out[ep_addr]; + + transc->ep_addr.dir = 0U; + } + + transc->ep_addr.num = EP_ID(ep_addr); + transc->max_len = max_len; + transc->ep_type = (uint8_t)ep_type[ep_desc->bmAttributes & (uint8_t)USB_EPTYPE_MASK]; + + /* active USB endpoint function */ + (void)usb_transc_active (udev, transc); + + return 0U; +} + +/*! + \brief configure the endpoint when it is disabled + \param[in] udev: pointer to USB core instance + \param[in] ep_addr: endpoint address + in this parameter: + bit0..bit6: endpoint number (0..7) + bit7: endpoint direction which can be IN(1) or OUT(0) + \param[out] none + \retval none +*/ +uint32_t usbd_ep_clear (usb_core_driver *udev, uint8_t ep_addr) +{ + usb_transc *transc; + + if (EP_DIR(ep_addr)) { + transc = &udev->dev.transc_in[EP_ID(ep_addr)]; + } else { + transc = &udev->dev.transc_out[ep_addr]; + } + + /* deactivate USB endpoint function */ + (void)usb_transc_deactivate (udev, transc); + + return 0U; +} + +/*! + \brief endpoint prepare to receive data + \param[in] udev: pointer to USB core instance + \param[in] ep_addr: endpoint address + in this parameter: + bit0..bit6: endpoint number (0..7) + bit7: endpoint direction which can be IN(1) or OUT(0) + \param[in] pbuf: user buffer address pointer + \param[in] len: buffer length + \param[out] none + \retval none +*/ +uint32_t usbd_ep_recev (usb_core_driver *udev, uint8_t ep_addr, uint8_t *pbuf, uint32_t len) +{ + usb_transc *transc = &udev->dev.transc_out[EP_ID(ep_addr)]; + + /* setup the transfer */ + transc->xfer_buf = pbuf; + transc->xfer_len = len; + transc->xfer_count = 0U; + + if ((uint8_t)USB_USE_DMA == udev->bp.transfer_mode) { + transc->dma_addr = (uint32_t)pbuf; + } + + /* start the transfer */ + (void)usb_transc_outxfer (udev, transc); + + return 0U; +} + +/*! + \brief endpoint prepare to transmit data + \param[in] udev: pointer to USB core instance + \param[in] ep_addr: endpoint address + in this parameter: + bit0..bit6: endpoint number (0..7) + bit7: endpoint direction which can be IN(1) or OUT(0) + \param[in] pbuf: transmit buffer address pointer + \param[in] len: buffer length + \param[out] none + \retval none +*/ +uint32_t usbd_ep_send (usb_core_driver *udev, uint8_t ep_addr, uint8_t *pbuf, uint32_t len) +{ + usb_transc *transc = &udev->dev.transc_in[EP_ID(ep_addr)]; + + /* setup the transfer */ + transc->xfer_buf = pbuf; + transc->xfer_len = len; + transc->xfer_count = 0U; + + if ((uint8_t)USB_USE_DMA == udev->bp.transfer_mode) { + transc->dma_addr = (uint32_t)pbuf; + } + + /* start the transfer */ + (void)usb_transc_inxfer (udev, transc); + + return 0U; +} + +/*! + \brief set an endpoint to STALL status + \param[in] udev: pointer to USB core instance + \param[in] ep_addr: endpoint address + in this parameter: + bit0..bit6: endpoint number (0..7) + bit7: endpoint direction which can be IN(1) or OUT(0) + \param[out] none + \retval none +*/ +uint32_t usbd_ep_stall (usb_core_driver *udev, uint8_t ep_addr) +{ + usb_transc *transc = NULL; + + if (EP_DIR(ep_addr)) { + transc = &udev->dev.transc_in[EP_ID(ep_addr)]; + } else { + transc = &udev->dev.transc_out[ep_addr]; + } + + transc->ep_stall = 1U; + + (void)usb_transc_stall (udev, transc); + + return (0U); +} + +/*! + \brief clear endpoint STALLed status + \param[in] udev: pointer to usb core instance + \param[in] ep_addr: endpoint address + in this parameter: + bit0..bit6: endpoint number (0..7) + bit7: endpoint direction which can be IN(1) or OUT(0) + \param[out] none + \retval none +*/ +uint32_t usbd_ep_stall_clear (usb_core_driver *udev, uint8_t ep_addr) +{ + usb_transc *transc = NULL; + + if (EP_DIR(ep_addr)) { + transc = &udev->dev.transc_in[EP_ID(ep_addr)]; + } else { + transc = &udev->dev.transc_out[ep_addr]; + } + + transc->ep_stall = 0U; + + (void)usb_transc_clrstall (udev, transc); + + return (0U); +} + +/*! + \brief flush the endpoint FIFOs + \param[in] udev: pointer to USB core instance + \param[in] ep_addr: endpoint address + in this parameter: + bit0..bit6: endpoint number (0..7) + bit7: endpoint direction which can be IN(1) or OUT(0) + \param[out] none + \retval none +*/ +uint32_t usbd_fifo_flush (usb_core_driver *udev, uint8_t ep_addr) +{ + if (EP_DIR(ep_addr)) { + (void)usb_txfifo_flush (&udev->regs, EP_ID(ep_addr)); + } else { + (void)usb_rxfifo_flush (&udev->regs); + } + + return (0U); +} + +/*! + \brief device connect + \param[in] udev: pointer to USB device instance + \param[out] none + \retval none +*/ +void usbd_connect (usb_core_driver *udev) +{ +#ifndef USE_OTG_MODE + /* connect device */ + usb_dev_connect (udev); + + usb_mdelay(3U); +#endif /* USE_OTG_MODE */ +} + +/*! + \brief device disconnect + \param[in] udev: pointer to USB device instance + \param[out] none + \retval none +*/ +void usbd_disconnect (usb_core_driver *udev) +{ +#ifndef USE_OTG_MODE + /* disconnect device for 3ms */ + usb_dev_disconnect (udev); + + usb_mdelay(3U); +#endif /* USE_OTG_MODE */ +} diff --git a/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/device/core/Source/usbd_enum.c b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/device/core/Source/usbd_enum.c new file mode 100644 index 0000000000..77107d5e7c --- /dev/null +++ b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/device/core/Source/usbd_enum.c @@ -0,0 +1,764 @@ +/*! + \file usbd_enum.c + \brief USB enumeration function + + \version 2020-08-01, V3.0.0, firmware for GD32F30x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "usbd_enum.h" +#include "usb_ch9_std.h" + +#ifdef WINUSB_EXEMPT_DRIVER + +extern usbd_status usbd_OEM_req(usb_dev *udev, usb_req *req); + +#endif /* WINUSB_EXEMPT_DRIVER */ + +/* local function prototypes ('static') */ +static usb_reqsta _usb_std_reserved (usb_core_driver *udev, usb_req *req); +static uint8_t* _usb_dev_desc_get (usb_core_driver *udev, uint8_t index, uint16_t *len); +static uint8_t* _usb_config_desc_get (usb_core_driver *udev, uint8_t index, uint16_t *len); +static uint8_t* _usb_bos_desc_get (usb_core_driver *udev, uint8_t index, uint16_t *len); +static uint8_t* _usb_str_desc_get (usb_core_driver *udev, uint8_t index, uint16_t *len); +static usb_reqsta _usb_std_getstatus (usb_core_driver *udev, usb_req *req); +static usb_reqsta _usb_std_clearfeature (usb_core_driver *udev, usb_req *req); +static usb_reqsta _usb_std_setfeature (usb_core_driver *udev, usb_req *req); +static usb_reqsta _usb_std_setaddress (usb_core_driver *udev, usb_req *req); +static usb_reqsta _usb_std_getdescriptor (usb_core_driver *udev, usb_req *req); +static usb_reqsta _usb_std_setdescriptor (usb_core_driver *udev, usb_req *req); +static usb_reqsta _usb_std_getconfiguration (usb_core_driver *udev, usb_req *req); +static usb_reqsta _usb_std_setconfiguration (usb_core_driver *udev, usb_req *req); +static usb_reqsta _usb_std_getinterface (usb_core_driver *udev, usb_req *req); +static usb_reqsta _usb_std_setinterface (usb_core_driver *udev, usb_req *req); +static usb_reqsta _usb_std_synchframe (usb_core_driver *udev, usb_req *req); + +static usb_reqsta (*_std_dev_req[])(usb_core_driver *udev, usb_req *req) = +{ + [USB_GET_STATUS] = _usb_std_getstatus, + [USB_CLEAR_FEATURE] = _usb_std_clearfeature, + [USB_RESERVED2] = _usb_std_reserved, + [USB_SET_FEATURE] = _usb_std_setfeature, + [USB_RESERVED4] = _usb_std_reserved, + [USB_SET_ADDRESS] = _usb_std_setaddress, + [USB_GET_DESCRIPTOR] = _usb_std_getdescriptor, + [USB_SET_DESCRIPTOR] = _usb_std_setdescriptor, + [USB_GET_CONFIGURATION] = _usb_std_getconfiguration, + [USB_SET_CONFIGURATION] = _usb_std_setconfiguration, + [USB_GET_INTERFACE] = _usb_std_getinterface, + [USB_SET_INTERFACE] = _usb_std_setinterface, + [USB_SYNCH_FRAME] = _usb_std_synchframe, +}; + +/* get standard descriptor handler */ +static uint8_t* (*std_desc_get[])(usb_core_driver *udev, uint8_t index, uint16_t *len) = { + [(uint8_t)USB_DESCTYPE_DEV - 1U] = _usb_dev_desc_get, + [(uint8_t)USB_DESCTYPE_CONFIG - 1U] = _usb_config_desc_get, + [(uint8_t)USB_DESCTYPE_STR - 1U] = _usb_str_desc_get +}; + +/*! + \brief handle USB standard device request + \param[in] udev: pointer to USB device instance + \param[in] req: pointer to USB device request + \param[out] none + \retval USB device request status +*/ +usb_reqsta usbd_standard_request (usb_core_driver *udev, usb_req *req) +{ + return (*_std_dev_req[req->bRequest])(udev, req); +} + +/*! + \brief handle USB device class request + \param[in] udev: pointer to USB device instance + \param[in] req: pointer to USB device class request + \param[out] none + \retval USB device request status +*/ +usb_reqsta usbd_class_request (usb_core_driver *udev, usb_req *req) +{ + if ((uint8_t)USBD_CONFIGURED == udev->dev.cur_status) { + if (BYTE_LOW(req->wIndex) <= USBD_ITF_MAX_NUM) { + /* call device class handle function */ + return (usb_reqsta)udev->dev.class_core->req_proc(udev, req); + } + } + + return REQ_NOTSUPP; +} + +/*! + \brief handle USB vendor request + \param[in] udev: pointer to USB device instance + \param[in] req: pointer to USB vendor request + \param[out] none + \retval USB device request status +*/ +usb_reqsta usbd_vendor_request (usb_core_driver *udev, usb_req *req) +{ + (void)udev; + (void)req; + + /* added by user... */ +#ifdef WINUSB_EXEMPT_DRIVER + usbd_OEM_req(udev, req); +#endif + + return REQ_SUPP; +} + +/*! + \brief handle USB enumeration error + \param[in] udev: pointer to USB device instance + \param[in] req: pointer to USB device request + \param[out] none + \retval none +*/ +void usbd_enum_error (usb_core_driver *udev, usb_req *req) +{ + (void)req; + + (void)usbd_ep_stall (udev, 0x80U); + (void)usbd_ep_stall (udev, 0x00U); + + usb_ctlep_startout(udev); +} + +/*! + \brief convert hex 32bits value into unicode char + \param[in] value: hex 32bits value + \param[in] pbuf: buffer pointer to store unicode char + \param[in] len: value length + \param[out] none + \retval none +*/ +void int_to_unicode (uint32_t value, uint8_t *pbuf, uint8_t len) +{ + uint8_t index; + + for (index = 0U; index < len; index++) { + if ((value >> 28U) < 0x0AU) { + pbuf[2U * index] = (uint8_t)((value >> 28U) + '0'); + } else { + pbuf[2U * index] = (uint8_t)((value >> 28U) + 'A' - 10U); + } + + value = value << 4U; + + pbuf[2U * index + 1U] = 0U; + } +} + +/*! + \brief convert hex 32bits value into unicode char + \param[in] unicode_str: pointer to unicode string + \param[out] none + \retval none +*/ +void serial_string_get (uint16_t *unicode_str) +{ + if ((unicode_str[0] & 0x00FFU) != 6U) { + uint32_t DeviceSerial0, DeviceSerial1, DeviceSerial2; + + DeviceSerial0 = *(uint32_t*)DEVICE_ID1; + DeviceSerial1 = *(uint32_t*)DEVICE_ID2; + DeviceSerial2 = *(uint32_t*)DEVICE_ID3; + + DeviceSerial0 += DeviceSerial2; + + if (0U != DeviceSerial0) { + int_to_unicode(DeviceSerial0, (uint8_t*)&(unicode_str[1]), 8U); + int_to_unicode(DeviceSerial1, (uint8_t*)&(unicode_str[9]), 4U); + } + } else { + uint32_t device_serial = *(uint32_t*)DEVICE_ID; + + if(0U != device_serial) { + unicode_str[1] = (uint16_t)(device_serial & 0x0000FFFFU); + unicode_str[2] = (uint16_t)((device_serial & 0xFFFF0000U) >> 16U); + + } + } +} + +/*! + \brief no operation, just for reserved + \param[in] udev: pointer to USB device instance + \param[in] req: pointer to USB vendor request + \param[out] none + \retval USB device request status +*/ +static usb_reqsta _usb_std_reserved (usb_core_driver *udev, usb_req *req) +{ + (void)udev; + (void)req; + + /* no operation... */ + + return REQ_NOTSUPP; +} + +/*! + \brief get the device descriptor + \param[in] udev: pointer to USB device instance + \param[in] index: no use + \param[out] len: data length pointer + \retval descriptor buffer pointer +*/ +static uint8_t* _usb_dev_desc_get (usb_core_driver *udev, uint8_t index, uint16_t *len) +{ + (void)index; + + *len = udev->dev.desc->dev_desc[0]; + + return udev->dev.desc->dev_desc; +} + +/*! + \brief get the configuration descriptor + \brief[in] udev: pointer to USB device instance + \brief[in] index: no use + \param[out] len: data length pointer + \retval descriptor buffer pointer +*/ +static uint8_t* _usb_config_desc_get (usb_core_driver *udev, uint8_t index, uint16_t *len) +{ + (void)index; + + *len = udev->dev.desc->config_desc[2]; + + return udev->dev.desc->config_desc; +} + +/*! + \brief get the BOS descriptor + \brief[in] udev: pointer to USB device instance + \brief[in] index: no use + \param[out] len: data length pointer + \retval descriptor buffer pointer +*/ +static uint8_t* _usb_bos_desc_get (usb_core_driver *udev, uint8_t index, uint16_t *len) +{ + (void)index; + + *len = udev->dev.desc->bos_desc[2]; + + return udev->dev.desc->bos_desc; +} + +/*! + \brief get string descriptor + \param[in] udev: pointer to USB device instance + \param[in] index: string descriptor index + \param[out] len: pointer to string length + \retval descriptor buffer pointer +*/ +static uint8_t* _usb_str_desc_get (usb_core_driver *udev, uint8_t index, uint16_t *len) +{ + uint8_t *desc = udev->dev.desc->strings[index]; + + *len = desc[0]; + + return desc; +} + +/*! + \brief handle Get_Status request + \param[in] udev: pointer to USB device instance + \param[in] req: pointer to USB device request + \param[out] none + \retval USB device request status +*/ +static usb_reqsta _usb_std_getstatus (usb_core_driver *udev, usb_req *req) +{ + uint8_t recp = BYTE_LOW(req->wIndex); + usb_reqsta req_status = REQ_NOTSUPP; + usb_transc *transc = &udev->dev.transc_in[0]; + + static uint8_t status[2] = {0}; + + switch(req->bmRequestType & (uint8_t)USB_RECPTYPE_MASK) { + case USB_RECPTYPE_DEV: + if (((uint8_t)USBD_ADDRESSED == udev->dev.cur_status) || \ + ((uint8_t)USBD_CONFIGURED == udev->dev.cur_status)) { + + if (udev->dev.pm.power_mode) { + status[0] = USB_STATUS_SELF_POWERED; + } else { + status[0] = 0U; + } + + if (udev->dev.pm.dev_remote_wakeup) { + status[0] |= USB_STATUS_REMOTE_WAKEUP; + } else { + status[0] = 0U; + } + + req_status = REQ_SUPP; + } + break; + + case USB_RECPTYPE_ITF: + if (((uint8_t)USBD_CONFIGURED == udev->dev.cur_status) && (recp <= USBD_ITF_MAX_NUM)) { + req_status = REQ_SUPP; + } + break; + + case USB_RECPTYPE_EP: + if ((uint8_t)USBD_CONFIGURED == udev->dev.cur_status) { + if (0x80U == (recp & 0x80U)) { + status[0] = udev->dev.transc_in[EP_ID(recp)].ep_stall; + } else { + status[0] = udev->dev.transc_out[recp].ep_stall; + } + + req_status = REQ_SUPP; + } + break; + + default: + break; + } + + if (REQ_SUPP == req_status) { + transc->xfer_buf = status; + transc->remain_len = 2U; + } + + return req_status; +} + +/*! + \brief handle USB Clear_Feature request + \param[in] udev: pointer to USB device instance + \param[in] req: USB device request + \param[out] none + \retval USB device request status +*/ +static usb_reqsta _usb_std_clearfeature (usb_core_driver *udev, usb_req *req) +{ + uint8_t ep = 0U; + + switch(req->bmRequestType & (uint8_t)USB_RECPTYPE_MASK) { + case USB_RECPTYPE_DEV: + if (((uint8_t)USBD_ADDRESSED == udev->dev.cur_status) || \ + ((uint8_t)USBD_CONFIGURED == udev->dev.cur_status)) { + + /* clear device remote wakeup feature */ + if ((uint16_t)USB_FEATURE_REMOTE_WAKEUP == req->wValue) { + udev->dev.pm.dev_remote_wakeup = 0U; + + return REQ_SUPP; + } + } + break; + + case USB_RECPTYPE_ITF: + break; + + case USB_RECPTYPE_EP: + /* get endpoint address */ + ep = BYTE_LOW(req->wIndex); + + if ((uint8_t)USBD_CONFIGURED == udev->dev.cur_status) { + /* clear endpoint halt feature */ + if (((uint16_t)USB_FEATURE_EP_HALT == req->wValue) && (!CTL_EP(ep))) { + (void)usbd_ep_stall_clear (udev, ep); + + (void)udev->dev.class_core->req_proc (udev, req); + } + + return REQ_SUPP; + } + break; + + default: + break; + } + + return REQ_NOTSUPP; +} + +/*! + \brief handle USB Set_Feature request + \param[in] udev: pointer to USB device instance + \param[in] req: pointer to USB device request + \param[out] none + \retval USB device request status +*/ +static usb_reqsta _usb_std_setfeature (usb_core_driver *udev, usb_req *req) +{ + uint8_t ep = 0U; + + switch (req->bmRequestType & (uint8_t)USB_RECPTYPE_MASK) { + case USB_RECPTYPE_DEV: + if (((uint8_t)USBD_ADDRESSED == udev->dev.cur_status) || \ + ((uint8_t)USBD_CONFIGURED == udev->dev.cur_status)) { + /* set device remote wakeup feature */ + if ((uint16_t)USB_FEATURE_REMOTE_WAKEUP == req->wValue) { + udev->dev.pm.dev_remote_wakeup = 1U; + } + + return REQ_SUPP; + } + break; + + case USB_RECPTYPE_ITF: + break; + + case USB_RECPTYPE_EP: + /* get endpoint address */ + ep = BYTE_LOW(req->wIndex); + + if ((uint8_t)USBD_CONFIGURED == udev->dev.cur_status) { + /* set endpoint halt feature */ + if (((uint16_t)USB_FEATURE_EP_HALT == req->wValue) && (!CTL_EP(ep))) { + (void)usbd_ep_stall (udev, ep); + } + + return REQ_SUPP; + } + break; + + default: + break; + } + + return REQ_NOTSUPP; +} + +/*! + \brief handle USB Set_Address request + \param[in] udev: pointer to USB device instance + \param[in] req: pointer to USB device request + \param[out] none + \retval USB device request status +*/ +static usb_reqsta _usb_std_setaddress (usb_core_driver *udev, usb_req *req) +{ + if ((0U == req->wIndex) && (0U == req->wLength)) { + udev->dev.dev_addr = (uint8_t)(req->wValue) & 0x7FU; + + if (udev->dev.cur_status != (uint8_t)USBD_CONFIGURED) { + usbd_addr_set (udev, udev->dev.dev_addr); + + if (udev->dev.dev_addr) { + udev->dev.cur_status = (uint8_t)USBD_ADDRESSED; + } else { + udev->dev.cur_status = (uint8_t)USBD_DEFAULT; + } + + return REQ_SUPP; + } + } + + return REQ_NOTSUPP; +} + +/*! + \brief handle USB Get_Descriptor request + \param[in] udev: pointer to USB device instance + \param[in] req: pointer to USB device request + \param[out] none + \retval USB device request status +*/ +static usb_reqsta _usb_std_getdescriptor (usb_core_driver *udev, usb_req *req) +{ + uint8_t desc_type = 0U; + uint8_t desc_index = 0U; + + usb_reqsta status = REQ_NOTSUPP; + + usb_transc *transc = &udev->dev.transc_in[0]; + + /* get device standard descriptor */ + switch (req->bmRequestType & USB_RECPTYPE_MASK) { + case USB_RECPTYPE_DEV: + desc_type = BYTE_HIGH(req->wValue); + desc_index = BYTE_LOW(req->wValue); + + switch (desc_type) { + case USB_DESCTYPE_DEV: + transc->xfer_buf = std_desc_get[desc_type - 1U](udev, desc_index, (uint16_t *)&(transc->remain_len)); + + if (64U == req->wLength) { + transc->remain_len = 8U; + } + break; + + case USB_DESCTYPE_CONFIG: + transc->xfer_buf = std_desc_get[desc_type - 1U](udev, desc_index, (uint16_t *)&(transc->remain_len)); + break; + + case USB_DESCTYPE_STR: + if (desc_index < (uint8_t)STR_IDX_MAX) { + transc->xfer_buf = std_desc_get[desc_type - 1U](udev, desc_index, (uint16_t *)&(transc->remain_len)); + } + break; + + case USB_DESCTYPE_ITF: + case USB_DESCTYPE_EP: + case USB_DESCTYPE_DEV_QUALIFIER: + case USB_DESCTYPE_OTHER_SPD_CONFIG: + case USB_DESCTYPE_ITF_POWER: + break; + + case USB_DESCTYPE_BOS: + transc->xfer_buf = _usb_bos_desc_get(udev, desc_index, (uint16_t *)&(transc->remain_len)); + break; + + default: + break; + } + break; + + case USB_RECPTYPE_ITF: + /* get device class special descriptor */ + status = (usb_reqsta)(udev->dev.class_core->req_proc(udev, req)); + break; + + case USB_RECPTYPE_EP: + break; + + default: + break; + } + + if ((0U != transc->remain_len) && (0U != req->wLength)) { + if (transc->remain_len < req->wLength) { + if ((transc->remain_len >= transc->max_len) && (0U == (transc->remain_len % transc->max_len))) { + udev->dev.control.ctl_zlp = 1U; + } + } else { + transc->remain_len = req->wLength; + } + + status = REQ_SUPP; + } + + return status; +} + +/*! + \brief handle USB Set_Descriptor request + \param[in] udev: pointer to USB device instance + \param[in] req: pointer to USB device request + \param[out] none + \retval USB device request status +*/ +static usb_reqsta _usb_std_setdescriptor (usb_core_driver *udev, usb_req *req) +{ + (void)udev; + (void)req; + + /* no handle... */ + return REQ_SUPP; +} + +/*! + \brief handle USB Get_Configuration request + \param[in] udev: pointer to USB device instance + \param[in] req: pointer to USB device request + \param[out] none + \retval USB device request status +*/ +static usb_reqsta _usb_std_getconfiguration (usb_core_driver *udev, usb_req *req) +{ + (void)req; + + usb_reqsta req_status = REQ_NOTSUPP; + usb_transc *transc = &udev->dev.transc_in[0]; + + switch (udev->dev.cur_status) { + case USBD_ADDRESSED: + if (USB_DEFAULT_CONFIG == udev->dev.config) { + req_status = REQ_SUPP; + } + break; + + case USBD_CONFIGURED: + if (udev->dev.config != USB_DEFAULT_CONFIG) { + req_status = REQ_SUPP; + } + break; + + default: + break; + } + + if (REQ_SUPP == req_status) { + transc->xfer_buf = &(udev->dev.config); + transc->remain_len = 1U; + } + + return req_status; +} + +/*! + \brief handle USB Set_Configuration request + \param[in] udev: pointer to USB device instance + \param[in] req: pointer to USB device request + \param[out] none + \retval USB device request status +*/ +static usb_reqsta _usb_std_setconfiguration (usb_core_driver *udev, usb_req *req) +{ + static uint8_t config; + usb_reqsta status = REQ_NOTSUPP; + + config = (uint8_t)(req->wValue); + + if (config <= USBD_CFG_MAX_NUM) { + switch (udev->dev.cur_status) { + case USBD_ADDRESSED: + if (config){ + (void)udev->dev.class_core->init(udev, config); + + udev->dev.config = config; + udev->dev.cur_status = (uint8_t)USBD_CONFIGURED; + } + + status = REQ_SUPP; + break; + + case USBD_CONFIGURED: + if (USB_DEFAULT_CONFIG == config) { + (void)udev->dev.class_core->deinit(udev, config); + + udev->dev.config = config; + udev->dev.cur_status = (uint8_t)USBD_ADDRESSED; + } else if (config != udev->dev.config) { + /* clear old configuration */ + (void)udev->dev.class_core->deinit(udev, config); + + /* set new configuration */ + udev->dev.config = config; + + (void)udev->dev.class_core->init(udev, config); + } else { + /* no operation */ + } + + status = REQ_SUPP; + break; + + case USBD_DEFAULT: + break; + + default: + break; + } + } + + return status; +} + +/*! + \brief handle USB Get_Interface request + \param[in] udev: pointer to USB device instance + \param[in] req: pointer to USB device request + \param[out] none + \retval USB device request status +*/ +static usb_reqsta _usb_std_getinterface (usb_core_driver *udev, usb_req *req) +{ + switch (udev->dev.cur_status) { + case USBD_DEFAULT: + break; + + case USBD_ADDRESSED: + break; + + case USBD_CONFIGURED: + if (BYTE_LOW(req->wIndex) <= USBD_ITF_MAX_NUM) { + usb_transc *transc = &udev->dev.transc_in[0]; + + transc->xfer_buf = &(udev->dev.class_core->alter_set); + transc->remain_len = 1U; + + return REQ_SUPP; + } + break; + + default: + break; + } + + return REQ_NOTSUPP; +} + +/*! + \brief handle USB Set_Interface request + \param[in] udev: pointer to USB device instance + \param[in] req: pointer to USB device request + \param[out] none + \retval USB device request status +*/ +static usb_reqsta _usb_std_setinterface (usb_core_driver *udev, usb_req *req) +{ + switch (udev->dev.cur_status) { + case USBD_DEFAULT: + break; + + case USBD_ADDRESSED: + break; + + case USBD_CONFIGURED: + if (BYTE_LOW(req->wIndex) <= USBD_ITF_MAX_NUM) { + if (NULL != udev->dev.class_core->set_intf) { + (void)udev->dev.class_core->set_intf (udev, req); + } + + return REQ_SUPP; + } + break; + + default: + break; + } + + return REQ_NOTSUPP; +} + +/*! + \brief handle USB SynchFrame request + \param[in] udev: pointer to USB device instance + \param[in] req: pointer to USB device request + \param[out] none + \retval USB device request status +*/ +static usb_reqsta _usb_std_synchframe (usb_core_driver *udev, usb_req *req) +{ + (void)udev; + (void)req; + + /* no handle */ + return REQ_SUPP; +} diff --git a/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/device/core/Source/usbd_transc.c b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/device/core/Source/usbd_transc.c new file mode 100644 index 0000000000..e299d532d3 --- /dev/null +++ b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/device/core/Source/usbd_transc.c @@ -0,0 +1,264 @@ +/*! + \file usbd_transc.c + \brief USB transaction core functions + + \version 2020-08-01, V3.0.0, firmware for GD32F30x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "usbd_enum.h" +#include "usbd_transc.h" + +/*! + \brief USB send data in the control transaction + \param[in] udev: pointer to USB device instance + \param[out] none + \retval USB device operation cur_status +*/ +usbd_status usbd_ctl_send (usb_core_driver *udev) +{ + usb_transc *transc = &udev->dev.transc_in[0]; + + (void)usbd_ep_send(udev, 0U, transc->xfer_buf, transc->remain_len); + + if (transc->remain_len > transc->max_len) { + udev->dev.control.ctl_state = (uint8_t)USB_CTL_DATA_IN; + } else { + udev->dev.control.ctl_state = (uint8_t)USB_CTL_LAST_DATA_IN; + } + + return USBD_OK; +} + +/*! + \brief USB receive data in control transaction + \param[in] udev: pointer to USB device instance + \param[out] none + \retval USB device operation cur_status +*/ +usbd_status usbd_ctl_recev (usb_core_driver *udev) +{ + usb_transc *transc = &udev->dev.transc_out[0]; + + (void)usbd_ep_recev (udev, 0U, transc->xfer_buf, transc->remain_len); + + if (transc->remain_len > transc->max_len) { + udev->dev.control.ctl_state = (uint8_t)USB_CTL_DATA_OUT; + } else { + udev->dev.control.ctl_state = (uint8_t)USB_CTL_LAST_DATA_OUT; + } + + return USBD_OK; +} + +/*! + \brief USB send control transaction status + \param[in] udev: pointer to USB device instance + \param[out] none + \retval USB device operation cur_status +*/ +usbd_status usbd_ctl_status_send (usb_core_driver *udev) +{ + udev->dev.control.ctl_state = (uint8_t)USB_CTL_STATUS_IN; + + (void)usbd_ep_send (udev, 0U, NULL, 0U); + + usb_ctlep_startout(udev); + + return USBD_OK; +} + +/*! + \brief USB control receive status + \param[in] udev: pointer to USB device instance + \param[out] none + \retval USB device operation cur_status +*/ +usbd_status usbd_ctl_status_recev (usb_core_driver *udev) +{ + udev->dev.control.ctl_state = (uint8_t)USB_CTL_STATUS_OUT; + + (void)usbd_ep_recev (udev, 0U, NULL, 0U); + + usb_ctlep_startout(udev); + + return USBD_OK; +} + +/*! + \brief USB setup stage processing + \param[in] udev: pointer to USB device instance + \param[out] none + \retval USB device operation cur_status +*/ +uint8_t usbd_setup_transc (usb_core_driver *udev) +{ + usb_reqsta reqstat = REQ_NOTSUPP; + + usb_req req = udev->dev.control.req; + + switch (req.bmRequestType & USB_REQTYPE_MASK) { + /* standard device request */ + case USB_REQTYPE_STRD: + reqstat = usbd_standard_request (udev, &req); + break; + + /* device class request */ + case USB_REQTYPE_CLASS: + reqstat = usbd_class_request (udev, &req); + break; + + /* vendor defined request */ + case USB_REQTYPE_VENDOR: + reqstat = usbd_vendor_request (udev, &req); + break; + + default: + break; + } + + if (REQ_SUPP == reqstat) { + if (0U == req.wLength) { + (void)usbd_ctl_status_send (udev); + } else { + if (req.bmRequestType & 0x80U) { + (void)usbd_ctl_send (udev); + } else { + (void)usbd_ctl_recev (udev); + } + } + } else { + usbd_enum_error (udev, &req); + } + + return (uint8_t)USBD_OK; +} + +/*! + \brief data out stage processing + \param[in] udev: pointer to USB device instance + \param[in] ep_num: endpoint identifier(0..7) + \param[out] none + \retval USB device operation cur_status +*/ +uint8_t usbd_out_transc (usb_core_driver *udev, uint8_t ep_num) +{ + if (0U == ep_num) { + usb_transc *transc = &udev->dev.transc_out[0]; + + switch (udev->dev.control.ctl_state) { + case USB_CTL_DATA_OUT: + /* update transfer length */ + transc->remain_len -= transc->max_len; + + if ((uint8_t)USB_USE_DMA == udev->bp.transfer_mode) { + transc->xfer_buf += transc->max_len; + } + + (void)usbd_ctl_recev (udev); + break; + + case USB_CTL_LAST_DATA_OUT: + if (udev->dev.cur_status == (uint8_t)USBD_CONFIGURED) { + if (udev->dev.class_core->ctlx_out != NULL) { + (void)udev->dev.class_core->ctlx_out (udev); + } + } + + transc->remain_len = 0U; + + (void)usbd_ctl_status_send (udev); + break; + + default: + break; + } + } else if ((udev->dev.class_core->data_out != NULL) && (udev->dev.cur_status == (uint8_t)USBD_CONFIGURED)) { + (void)udev->dev.class_core->data_out (udev, ep_num); + } else { + /* no operation */ + } + + return (uint8_t)USBD_OK; +} + +/*! + \brief data in stage processing + \param[in] udev: pointer to USB device instance + \param[in] ep_num: endpoint identifier(0..7) + \param[out] none + \retval USB device operation cur_status +*/ +uint8_t usbd_in_transc (usb_core_driver *udev, uint8_t ep_num) +{ + if (0U == ep_num) { + usb_transc *transc = &udev->dev.transc_in[0]; + + switch (udev->dev.control.ctl_state) { + case USB_CTL_DATA_IN: + /* update transfer length */ + transc->remain_len -= transc->max_len; + + if ((uint8_t)USB_USE_DMA == udev->bp.transfer_mode) { + transc->xfer_buf += transc->max_len; + } + + (void)usbd_ctl_send (udev); + break; + + case USB_CTL_LAST_DATA_IN: + /* last packet is MPS multiple, so send ZLP packet */ + if (udev->dev.control.ctl_zlp) { + (void)usbd_ep_send (udev, 0U, NULL, 0U); + + udev->dev.control.ctl_zlp = 0U; + } else { + if (udev->dev.cur_status == (uint8_t)USBD_CONFIGURED) { + if (udev->dev.class_core->ctlx_in != NULL) { + (void)udev->dev.class_core->ctlx_in (udev); + } + } + + transc->remain_len = 0U; + + (void)usbd_ctl_status_recev (udev); + } + break; + + default: + break; + } + } else { + if ((udev->dev.cur_status == (uint8_t)USBD_CONFIGURED) && (udev->dev.class_core->data_in != NULL)) { + (void)udev->dev.class_core->data_in (udev, ep_num); + } + } + + return (uint8_t)USBD_OK; +} diff --git a/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/driver/Include/drv_usb_core.h b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/driver/Include/drv_usb_core.h new file mode 100644 index 0000000000..b332de8e99 --- /dev/null +++ b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/driver/Include/drv_usb_core.h @@ -0,0 +1,163 @@ +/*! + \file drv_usb_core.h + \brief USB core low level driver header file + + \version 2020-08-01, V3.0.0, firmware for GD32F30x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef __DRV_USB_CORE_H +#define __DRV_USB_CORE_H + +#include "drv_usb_regs.h" +#include "usb_ch9_std.h" + +#define USB_FS_EP0_MAX_LEN 64U /*!< maximum packet size of endpoint 0 */ +#define HC_MAX_PACKET_COUNT 140U /*!< maximum packet count */ + +#define EP_ID(x) ((uint8_t)((x) & 0x7FU)) /*!< endpoint number */ +#define EP_DIR(x) ((uint8_t)((x) >> 7)) /*!< endpoint direction */ + +enum _usb_mode { + DEVICE_MODE = 0U, /*!< device mode */ + HOST_MODE, /*!< host mode */ + OTG_MODE /*!< OTG mode */ +}; + +enum _usb_eptype { + USB_EPTYPE_CTRL = 0U, /*!< control endpoint type */ + USB_EPTYPE_ISOC = 1U, /*!< isochronous endpoint type */ + USB_EPTYPE_BULK = 2U, /*!< bulk endpoint type */ + USB_EPTYPE_INTR = 3U, /*!< interrupt endpoint type */ + USB_EPTYPE_MASK = 3U /*!< endpoint type mask */ +}; + +typedef enum +{ + USB_OTG_OK = 0U, /*!< USB OTG status OK*/ + USB_OTG_FAIL /*!< USB OTG status fail*/ +} usb_otg_status; + +typedef enum +{ + USB_OK = 0U, /*!< USB status OK*/ + USB_FAIL /*!< USB status fail*/ +} usb_status; + +typedef enum +{ + USB_USE_FIFO, /*!< USB use FIFO transfer mode */ + USB_USE_DMA /*!< USB use DMA transfer mode */ +} usb_transfer_mode; + +typedef struct +{ + uint8_t core_enum; /*!< USB core type */ + uint8_t core_speed; /*!< USB core speed */ + uint8_t num_pipe; /*!< USB host channel numbers */ + uint8_t num_ep; /*!< USB device endpoint numbers */ + uint8_t transfer_mode; /*!< USB transfer mode */ + uint8_t phy_itf; /*!< USB core PHY interface */ + uint8_t sof_enable; /*!< USB SOF output */ + uint8_t low_power; /*!< USB low power */ + uint8_t lpm_enable; /*!< USB link power mode(LPM) */ + uint8_t vbus_sensing_enable; /*!< USB VBUS sensing feature */ + uint8_t use_dedicated_ep1; /*!< USB dedicated endpoint1 interrupt */ + uint8_t use_external_vbus; /*!< enable or disable the use of the external VBUS */ + uint32_t base_reg; /*!< base register address */ +} usb_core_basic; + +/* static inline function definitions */ + +/*! + \brief get the global interrupts + \param[in] usb_regs: pointer to USB core registers + \param[out] none + \retval interrupt status +*/ +__STATIC_INLINE uint32_t usb_coreintr_get(usb_core_regs *usb_regs) +{ + return usb_regs->gr->GINTEN & usb_regs->gr->GINTF; +} + +/*! + \brief set USB RX FIFO size + \param[in] usb_regs: pointer to USB core registers + \param[in] size: assigned FIFO size + \param[out] none + \retval none +*/ +__STATIC_INLINE void usb_set_rxfifo(usb_core_regs *usb_regs, uint16_t size) +{ + usb_regs->gr->GRFLEN = size; +} + +/*! + \brief enable the global interrupts + \param[in] usb_regs: pointer to USB core registers + \param[out] none + \retval none +*/ +__STATIC_INLINE void usb_globalint_enable(usb_core_regs *usb_regs) +{ + /* enable USB global interrupt */ + usb_regs->gr->GAHBCS |= GAHBCS_GINTEN; +} + +/*! + \brief disable the global interrupts + \param[in] usb_regs: pointer to USB core registers + \param[out] none + \retval none +*/ +__STATIC_INLINE void usb_globalint_disable(usb_core_regs *usb_regs) +{ + /* disable USB global interrupt */ + usb_regs->gr->GAHBCS &= ~GAHBCS_GINTEN; +} + +/* function declarations */ +/* configure core capabilities */ +usb_status usb_basic_init (usb_core_basic *usb_basic, usb_core_regs *usb_regs, usb_core_enum usb_core); +/* initializes the USB controller registers and prepares the core device mode or host mode operation */ +usb_status usb_core_init (usb_core_basic usb_basic, usb_core_regs *usb_regs); +/* write a packet into the Tx FIFO associated with the endpoint */ +usb_status usb_txfifo_write (usb_core_regs *usb_regs, uint8_t *src_buf, uint8_t fifo_num, uint16_t byte_count); +/* read a packet from the Rx FIFO associated with the endpoint */ +void *usb_rxfifo_read (usb_core_regs *usb_regs, uint8_t *dest_buf, uint16_t byte_count); +/* flush a Tx FIFO or all Tx FIFOs */ +usb_status usb_txfifo_flush (usb_core_regs *usb_regs, uint8_t fifo_num); +/* flush the entire Rx FIFO */ +usb_status usb_rxfifo_flush (usb_core_regs *usb_regs); +/* set endpoint or channel TX FIFO size */ +void usb_set_txfifo(usb_core_regs *usb_regs, uint8_t fifo, uint16_t size); +/* set USB current mode */ +void usb_curmode_set(usb_core_regs *usb_regs, uint8_t mode); + +#endif /* __DRV_USB_CORE_H */ diff --git a/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/driver/Include/drv_usb_dev.h b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/driver/Include/drv_usb_dev.h new file mode 100644 index 0000000000..31cf52d6c9 --- /dev/null +++ b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/driver/Include/drv_usb_dev.h @@ -0,0 +1,300 @@ +/*! + \file drv_usb_dev.h + \brief USB device low level driver header file + + \version 2020-08-01, V3.0.0, firmware for GD32F30x + \version 2020-12-07, V3.0.1, firmware for GD32F30x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef __DRV_USB_DEV_H +#define __DRV_USB_DEV_H + +#include "usbd_conf.h" +#include "drv_usb_core.h" + +enum usb_ctl_status { + USB_CTL_IDLE = 0U, /*!< USB control transfer idle state */ + USB_CTL_DATA_IN, /*!< USB control transfer data in state */ + USB_CTL_LAST_DATA_IN, /*!< USB control transfer last data in state */ + USB_CTL_DATA_OUT, /*!< USB control transfer data out state */ + USB_CTL_LAST_DATA_OUT, /*!< USB control transfer last data out state */ + USB_CTL_STATUS_IN, /*!< USB control transfer status in state*/ + USB_CTL_STATUS_OUT /*!< USB control transfer status out state */ +}; + +#define EP_IN(x) ((uint8_t)(0x80U | (x))) /*!< device IN endpoint */ +#define EP_OUT(x) ((uint8_t)(x)) /*!< device OUT endpoint */ + +/* USB descriptor */ +typedef struct _usb_desc { + uint8_t *dev_desc; /*!< device descriptor */ + uint8_t *config_desc; /*!< configure descriptor */ + uint8_t *bos_desc; /*!< BOS descriptor */ + + void* const *strings; /*!< string descriptor */ +} usb_desc; + +/* USB power management */ +typedef struct _usb_pm { + uint8_t power_mode; /*!< power mode */ + uint8_t power_low; /*!< power low */ + uint8_t dev_remote_wakeup; /*!< remote wakeup */ + uint8_t remote_wakeup_on; /*!< remote wakeup on */ +} usb_pm; + +/* USB control information */ +typedef struct _usb_control { + usb_req req; /*!< USB standard device request */ + + uint8_t ctl_state; /*!< USB control transfer state */ + uint8_t ctl_zlp; /*!< zero length package */ +} usb_control; + +typedef struct +{ + struct { + uint8_t num: 4; /*!< the endpoint number.it can be from 0 to 6 */ + uint8_t pad: 3; /*!< padding between number and direction */ + uint8_t dir: 1; /*!< the endpoint direction */ + } ep_addr; + + uint8_t ep_type; /*!< USB endpoint type */ + uint8_t ep_stall; /*!< USB endpoint stall status */ + + uint8_t frame_num; /*!< number of frame */ + uint16_t max_len; /*!< Maximum packet length */ + + /* transaction level variables */ + uint8_t *xfer_buf; /*!< transmit buffer */ + uint32_t xfer_len; /*!< transmit buffer length */ + uint32_t xfer_count; /*!< transmit buffer count */ + + uint32_t remain_len; /*!< remain packet length */ + + uint32_t dma_addr; /*!< DMA address */ +} usb_transc; + +typedef struct _usb_core_driver usb_dev; + +typedef struct _usb_class_core +{ + uint8_t command; /*!< device class request command */ + uint8_t alter_set; /*!< alternative set */ + + uint8_t (*init) (usb_dev *udev, uint8_t config_index); /*!< initialize handler */ + uint8_t (*deinit) (usb_dev *udev, uint8_t config_index); /*!< de-initialize handler */ + + uint8_t (*req_proc) (usb_dev *udev, usb_req *req); /*!< device request handler */ + + uint8_t (*set_intf) (usb_dev *udev, usb_req *req); /*!< device set interface callback */ + + uint8_t (*ctlx_in) (usb_dev *udev); /*!< device contrl in callback */ + uint8_t (*ctlx_out) (usb_dev *udev); /*!< device contrl out callback */ + + uint8_t (*data_in) (usb_dev *udev, uint8_t ep_num); /*!< device data in handler */ + uint8_t (*data_out) (usb_dev *udev, uint8_t ep_num); /*!< device data out handler */ + + uint8_t (*SOF) (usb_dev *udev); /*!< Start of frame handler */ + + uint8_t (*incomplete_isoc_in) (usb_dev *udev); /*!< Incomplete synchronization IN transfer handler */ + uint8_t (*incomplete_isoc_out) (usb_dev *udev); /*!< Incomplete synchronization OUT transfer handler */ +} usb_class_core; + +typedef struct _usb_perp_dev +{ + uint8_t config; /*!< configuration */ + uint8_t dev_addr; /*!< device address */ + + __IO uint8_t cur_status; /*!< current status */ + __IO uint8_t backup_status; /*!< backup status */ + + usb_transc transc_in[USBFS_MAX_TX_FIFOS]; /*!< endpoint IN transaction */ + usb_transc transc_out[USBFS_MAX_TX_FIFOS]; /*!< endpoint OUT transaction */ + + usb_pm pm; /*!< power management */ + usb_control control; /*!< USB control information */ + usb_desc *desc; /*!< USB descriptors pointer */ + usb_class_core *class_core; /*!< class driver */ + void *class_data[USBD_ITF_MAX_NUM]; /*!< class data pointer */ + void *user_data; /*!< user data pointer */ + void *pdata; /*!< reserved data pointer */ +} usb_perp_dev; + +typedef struct _usb_core_driver +{ + usb_core_basic bp; /*!< USB basic parameters */ + usb_core_regs regs; /*!< USB registers */ + usb_perp_dev dev; /*!< USB peripheral device */ +} usb_core_driver; + +/* static inline function definitions */ + +/*! + \brief configure the USB device to be disconnected + \param[in] udev: pointer to USB device + \param[out] none + \retval operation status +*/ +__STATIC_INLINE void usb_dev_disconnect (usb_core_driver *udev) +{ + udev->regs.dr->DCTL |= DCTL_SD; +} + +/*! + \brief configure the USB device to be connected + \param[in] udev: pointer to USB device + \param[out] none + \retval operation status +*/ +__STATIC_INLINE void usb_dev_connect (usb_core_driver *udev) +{ + udev->regs.dr->DCTL &= ~DCTL_SD; +} + +/*! + \brief set the USB device address + \param[in] udev: pointer to USB device + \param[in] dev_addr: device address for setting + \param[out] none + \retval operation status +*/ +__STATIC_INLINE void usb_devaddr_set (usb_core_driver *udev, uint8_t dev_addr) +{ + udev->regs.dr->DCFG &= ~DCFG_DAR; + udev->regs.dr->DCFG |= (uint32_t)dev_addr << 4U; +} + +/*! + \brief read device all OUT endpoint interrupt register + \param[in] udev: pointer to USB device + \param[out] none + \retval interrupt status +*/ +__STATIC_INLINE uint32_t usb_oepintnum_read (usb_core_driver *udev) +{ + uint32_t value = udev->regs.dr->DAEPINT; + + value &= udev->regs.dr->DAEPINTEN; + + return (value & DAEPINT_OEPITB) >> 16U; +} + +/*! + \brief read device OUT endpoint interrupt flag register + \param[in] udev: pointer to USB device + \param[in] ep_num: endpoint number + \param[out] none + \retval interrupt status +*/ +__STATIC_INLINE uint32_t usb_oepintr_read (usb_core_driver *udev, uint8_t ep_num) +{ + uint32_t value = udev->regs.er_out[ep_num]->DOEPINTF; + + value &= udev->regs.dr->DOEPINTEN; + + return value; +} + +/*! + \brief read device all IN endpoint interrupt register + \param[in] udev: pointer to USB device + \param[out] none + \retval interrupt status +*/ +__STATIC_INLINE uint32_t usb_iepintnum_read (usb_core_driver *udev) +{ + uint32_t value = udev->regs.dr->DAEPINT; + + value &= udev->regs.dr->DAEPINTEN; + + return value & DAEPINT_IEPITB; +} + +/*! + \brief set remote wakeup signaling + \param[in] udev: pointer to USB device + \param[out] none + \retval none +*/ +__STATIC_INLINE void usb_rwkup_set (usb_core_driver *udev) +{ + if (udev->dev.pm.dev_remote_wakeup) { + /* enable remote wakeup signaling */ + udev->regs.dr->DCTL |= DCTL_RWKUP; + } +} + +/*! + \brief reset remote wakeup signaling + \param[in] udev: pointer to USB device + \param[out] none + \retval none +*/ +__STATIC_INLINE void usb_rwkup_reset (usb_core_driver *udev) +{ + if (udev->dev.pm.dev_remote_wakeup) { + /* disable remote wakeup signaling */ + udev->regs.dr->DCTL &= ~DCTL_RWKUP; + } +} + +/* function declarations */ +/* initialize USB core registers for device mode */ +usb_status usb_devcore_init (usb_core_driver *udev); +/* enable the USB device mode interrupts */ +usb_status usb_devint_enable (usb_core_driver *udev); +/* active the USB endpoint 0 transaction */ +usb_status usb_transc0_active (usb_core_driver *udev, usb_transc *transc); +/* active the USB transaction */ +usb_status usb_transc_active (usb_core_driver *udev, usb_transc *transc); +/* deactivate the USB transaction */ +usb_status usb_transc_deactivate (usb_core_driver *udev, usb_transc *transc); +/* configure USB transaction to start IN transfer */ +usb_status usb_transc_inxfer (usb_core_driver *udev, usb_transc *transc); +/* configure USB transaction to start OUT transfer */ +usb_status usb_transc_outxfer (usb_core_driver *udev, usb_transc *transc); +/* set the USB transaction STALL status */ +usb_status usb_transc_stall (usb_core_driver *udev, usb_transc *transc); +/* clear the USB transaction STALL status */ +usb_status usb_transc_clrstall (usb_core_driver *udev, usb_transc *transc); +/* read device IN endpoint interrupt flag register */ +uint32_t usb_iepintr_read (usb_core_driver *udev, uint8_t ep_num); +/* configures OUT endpoint 0 to receive SETUP packets */ +void usb_ctlep_startout (usb_core_driver *udev); +/* active remote wakeup signaling */ +void usb_rwkup_active (usb_core_driver *udev); +/* active USB core clock */ +void usb_clock_active (usb_core_driver *udev); +/* USB device suspend */ +void usb_dev_suspend (usb_core_driver *udev); +/* stop the device and clean up FIFOs */ +void usb_dev_stop (usb_core_driver *udev); + +#endif /* __DRV_USB_DEV_H */ diff --git a/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/driver/Include/drv_usb_host.h b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/driver/Include/drv_usb_host.h new file mode 100644 index 0000000000..0cf18b5bf7 --- /dev/null +++ b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/driver/Include/drv_usb_host.h @@ -0,0 +1,193 @@ +/*! + \file drv_usb_host.h + \brief USB host mode low level driver header file + + \version 2020-08-01, V3.0.0, firmware for GD32F30x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef __DRV_USB_HOST_H +#define __DRV_USB_HOST_H + +#include "drv_usb_regs.h" +#include "usb_ch9_std.h" +#include "drv_usb_core.h" + +typedef enum _usb_pipe_status +{ + PIPE_IDLE = 0U, + PIPE_XF, + PIPE_HALTED, + PIPE_NAK, + PIPE_NYET, + PIPE_STALL, + PIPE_TRACERR, + PIPE_BBERR, + PIPE_REQOVR, + PIPE_DTGERR, +} usb_pipe_staus; + +typedef enum _usb_pipe_mode +{ + PIPE_PERIOD = 0U, + PIPE_NON_PERIOD = 1U +} usb_pipe_mode; + +typedef enum _usb_urb_state +{ + URB_IDLE = 0U, + URB_DONE, + URB_NOTREADY, + URB_ERROR, + URB_STALL, + URB_PING +} usb_urb_state; + +typedef struct _usb_pipe +{ + uint8_t in_used; + uint8_t dev_addr; + uint32_t dev_speed; + + struct { + uint8_t num; + uint8_t dir; + uint8_t type; + uint16_t mps; + } ep; + + uint8_t ping; + uint32_t DPID; + + uint8_t *xfer_buf; + uint32_t xfer_len; + uint32_t xfer_count; + + uint8_t data_toggle_in; + uint8_t data_toggle_out; + + __IO uint32_t err_count; + __IO usb_pipe_staus pp_status; + __IO usb_urb_state urb_state; +} usb_pipe; + + +typedef struct _usb_host_drv +{ + __IO uint32_t connect_status; + __IO uint32_t port_enabled; + __IO uint32_t backup_xfercount[USBFS_MAX_TX_FIFOS]; + + usb_pipe pipe[USBFS_MAX_TX_FIFOS]; + void *data; +} usb_host_drv; + +typedef struct _usb_core_driver +{ + usb_core_basic bp; + usb_core_regs regs; + usb_host_drv host; +} usb_core_driver; + +/*! + \brief get USB even frame + \param[in] pudev: pointer to USB device + \param[out] none + \retval none +*/ +__STATIC_INLINE uint8_t usb_frame_even (usb_core_driver *pudev) +{ + return (uint8_t)!(pudev->regs.hr->HFINFR & 0x01U); +} + +/*! + \brief configure USB clock of PHY + \param[in] pudev: pointer to USB device + \param[in] clock: PHY clock + \param[out] none + \retval none +*/ +__STATIC_INLINE void usb_phyclock_config (usb_core_driver *pudev, uint8_t clock) +{ + pudev->regs.hr->HCTL &= ~HCTL_CLKSEL; + pudev->regs.hr->HCTL |= clock; +} + +/*! + \brief read USB port + \param[in] pudev: pointer to USB device + \param[out] none + \retval port status +*/ +__STATIC_INLINE uint32_t usb_port_read (usb_core_driver *pudev) +{ + return *pudev->regs.HPCS & ~(HPCS_PE | HPCS_PCD | HPCS_PEDC); +} + +/*! + \brief get USB current speed + \param[in] pudev: pointer to USB device + \param[out] none + \retval USB current speed +*/ +__STATIC_INLINE uint32_t usb_curspeed_get (usb_core_driver *pudev) +{ + return *pudev->regs.HPCS & HPCS_PS; +} + +/*! + \brief get USB current frame + \param[in] pudev: pointer to USB device + \param[out] none + \retval USB current frame +*/ +__STATIC_INLINE uint32_t usb_curframe_get (usb_core_driver *pudev) +{ + return (pudev->regs.hr->HFINFR & 0xFFFFU); +} + +/* function declarations */ +/* initializes USB core for host mode */ +usb_status usb_host_init (usb_core_driver *pudev); +/* control the VBUS to power */ +void usb_portvbus_switch (usb_core_driver *pudev, uint8_t state); +/* reset host port */ +uint32_t usb_port_reset (usb_core_driver *pudev); +/* initialize host pipe */ +usb_status usb_pipe_init (usb_core_driver *pudev, uint8_t pipe_num); +/* prepare host pipe for transferring packets */ +usb_status usb_pipe_xfer (usb_core_driver *pudev, uint8_t pipe_num); +/* halt host pipe */ +usb_status usb_pipe_halt (usb_core_driver *pudev, uint8_t pipe_num); +/* configure host pipe to do ping operation */ +usb_status usb_pipe_ping (usb_core_driver *pudev, uint8_t pipe_num); +/* stop the USB host and clean up FIFO */ +void usb_host_stop (usb_core_driver *pudev); + +#endif /* __DRV_USB_HOST_H */ diff --git a/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/driver/Include/drv_usb_hw.h b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/driver/Include/drv_usb_hw.h new file mode 100644 index 0000000000..34a4b6b24c --- /dev/null +++ b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/driver/Include/drv_usb_hw.h @@ -0,0 +1,69 @@ +/*! + \file drv_usb_hw.h + \brief usb hardware configuration header file + + \version 2020-08-01, V3.0.0, firmware for GD32F30x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef __DRV_USB_HW_H +#define __DRV_USB_HW_H + +#include "usb_conf.h" + +/* function declarations */ +/* configure USB clock */ +void usb_rcu_config (void); +/* configure USB interrupt */ +void usb_intr_config (void); +/* initializes delay unit using Timer2 */ +void usb_timer_init (void); +/* delay in micro seconds */ +void usb_udelay (const uint32_t usec); +/* delay in milliseconds */ +void usb_mdelay (const uint32_t msec); +/* configures system clock after wakeup from STOP mode */ +void system_clk_config_stop(void); + +/* configure the CTC peripheral */ +#ifdef USE_IRC48M + void ctc_config(void); +#endif /* USE_IRC48M */ + +#ifdef USE_HOST_MODE + void systick_config(void); + + /* configure USB VBus */ + void usb_vbus_config (void); + + /* drive USB VBus */ + void usb_vbus_drive (uint8_t State); +#endif /* USE_HOST_MODE */ + +#endif /* __DRV_USB_HW_H */ diff --git a/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/driver/Include/drv_usb_regs.h b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/driver/Include/drv_usb_regs.h new file mode 100644 index 0000000000..b07922b2ac --- /dev/null +++ b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/driver/Include/drv_usb_regs.h @@ -0,0 +1,657 @@ +/*! + \file drv_usb_regs.h + \brief USB cell registers definition and handle macros + + \version 2020-08-01, V3.0.0, firmware for GD32F30x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef __DRV_USB_REGS_H +#define __DRV_USB_REGS_H + +#include "usb_conf.h" + +#define USBHS_REG_BASE 0x40040000L /*!< base address of USBHS registers */ +#define USBFS_REG_BASE 0x50000000L /*!< base address of USBFS registers */ + +#define USBFS_MAX_TX_FIFOS 15U /*!< FIFO number */ + +#define USBFS_MAX_PACKET_SIZE 64U /*!< USBFS max packet size */ +#define USBFS_MAX_CHANNEL_COUNT 8U /*!< USBFS host channel count */ +#define USBFS_MAX_EP_COUNT 4U /*!< USBFS device endpoint count */ +#define USBFS_MAX_FIFO_WORDLEN 320U /*!< USBFS max fifo size in words */ + +#define USBHS_MAX_PACKET_SIZE 512U /*!< USBHS max packet size */ +#define USBHS_MAX_CHANNEL_COUNT 12U /*!< USBHS host channel count */ +#define USBHS_MAX_EP_COUNT 6U /*!< USBHS device endpoint count */ +#define USBHS_MAX_FIFO_WORDLEN 1280U /*!< USBHS max fifo size in words */ + +#define USB_DATA_FIFO_OFFSET 0x1000U /*!< USB data fifo offset */ +#define USB_DATA_FIFO_SIZE 0x1000U /*!< USB data fifo size */ + +typedef enum +{ + USB_CORE_ENUM_HS = 0, /*!< USB core type is HS */ + USB_CORE_ENUM_FS = 1 /*!< USB core type is FS */ +} usb_core_enum; + +enum USB_SPEED { + USB_SPEED_UNKNOWN = 0, /*!< USB speed unknown */ + USB_SPEED_LOW, /*!< USB speed low */ + USB_SPEED_FULL, /*!< USB speed full */ + USB_SPEED_HIGH, /*!< USB speed high */ +}; + +enum usb_reg_offset { + USB_REG_OFFSET_CORE = 0x0000U, /*!< global OTG control and status register */ + USB_REG_OFFSET_DEV = 0x0800U, /*!< device mode control and status registers */ + USB_REG_OFFSET_EP = 0x0020U, + USB_REG_OFFSET_EP_IN = 0x0900U, /*!< device IN endpoint 0 control register */ + USB_REG_OFFSET_EP_OUT = 0x0B00U, /*!< device OUT endpoint 0 control register */ + USB_REG_OFFSET_HOST = 0x0400U, /*!< host control register */ + USB_REG_OFFSET_CH = 0x0020U, + USB_REG_OFFSET_PORT = 0x0440U, /*!< host port control and status register */ + USB_REG_OFFSET_CH_INOUT = 0x0500U, /*!< Host channel-x control registers */ + USB_REG_OFFSET_PWRCLKCTL = 0x0E00U, /*!< power and clock register */ +}; + +typedef struct +{ + __IO uint32_t GOTGCS; /*!< USB global OTG control and status register 000h */ + __IO uint32_t GOTGINTF; /*!< USB global OTG interrupt flag register 004h */ + __IO uint32_t GAHBCS; /*!< USB global AHB control and status register 008h */ + __IO uint32_t GUSBCS; /*!< USB global USB control and status register 00Ch */ + __IO uint32_t GRSTCTL; /*!< USB global reset control register 010h */ + __IO uint32_t GINTF; /*!< USB global interrupt flag register 014h */ + __IO uint32_t GINTEN; /*!< USB global interrupt enable register 018h */ + __IO uint32_t GRSTATR; /*!< USB receive status debug read register 01Ch */ + __IO uint32_t GRSTATP; /*!< USB receive status and pop register 020h */ + __IO uint32_t GRFLEN; /*!< USB global receive FIFO length register 024h */ + __IO uint32_t DIEP0TFLEN_HNPTFLEN; /*!< USB device IN endpoint 0/host non-periodic transmit FIFO length register 028h */ + __IO uint32_t HNPTFQSTAT; /*!< USB host non-periodic FIFO/queue status register 02Ch */ + uint32_t Reserved30[2]; /*!< Reserved 030h */ + __IO uint32_t GCCFG; /*!< USB global core configuration register 038h */ + __IO uint32_t CID; /*!< USB core ID register 03Ch */ + uint32_t Reserved40[48]; /*!< Reserved 040h-0FFh */ + __IO uint32_t HPTFLEN; /*!< USB host periodic transmit FIFO length register 100h */ + __IO uint32_t DIEPTFLEN[15]; /*!< USB device IN endpoint transmit FIFO length register 104h */ +} usb_gr; + +typedef struct +{ + __IO uint32_t HCTL; /*!< USB host control register 400h */ + __IO uint32_t HFT; /*!< USB host frame interval register 404h */ + __IO uint32_t HFINFR; /*!< USB host frame information remaining register 408h */ + uint32_t Reserved40C; /*!< Reserved 40Ch */ + __IO uint32_t HPTFQSTAT; /*!< USB host periodic transmit FIFO/queue status register 410h */ + __IO uint32_t HACHINT; /*!< USB host all channels interrupt register 414h */ + __IO uint32_t HACHINTEN; /*!< USB host all channels interrupt enable register 418h */ +} usb_hr; + +typedef struct +{ + __IO uint32_t HCHCTL; /*!< USB host channel control register 500h */ + __IO uint32_t HCHSTCTL; /*!< Reserved 504h */ + __IO uint32_t HCHINTF; /*!< USB host channel interrupt flag register 508h */ + __IO uint32_t HCHINTEN; /*!< USB host channel interrupt enable register 50Ch */ + __IO uint32_t HCHLEN; /*!< USB host channel transfer length register 510h */ + __IO uint32_t HCHDMAADDR; /*!< USB host channel-x DMA address register 514h*/ + uint32_t Reserved[2]; +} usb_pr; + +typedef struct +{ + __IO uint32_t DCFG; /*!< USB device configuration register 800h */ + __IO uint32_t DCTL; /*!< USB device control register 804h */ + __IO uint32_t DSTAT; /*!< USB device status register 808h */ + uint32_t Reserved0C; /*!< Reserved 80Ch */ + __IO uint32_t DIEPINTEN; /*!< USB device IN endpoint common interrupt enable register 810h */ + __IO uint32_t DOEPINTEN; /*!< USB device OUT endpoint common interrupt enable register 814h */ + __IO uint32_t DAEPINT; /*!< USB device all endpoints interrupt register 818h */ + __IO uint32_t DAEPINTEN; /*!< USB device all endpoints interrupt enable register 81Ch */ + uint32_t Reserved20; /*!< Reserved 820h */ + uint32_t Reserved24; /*!< Reserved 824h */ + __IO uint32_t DVBUSDT; /*!< USB device VBUS discharge time register 828h */ + __IO uint32_t DVBUSPT; /*!< USB device VBUS pulsing time register 82Ch */ + __IO uint32_t DTHRCTL; /*!< dev threshold control 830h */ + __IO uint32_t DIEPFEINTEN; /*!< USB Device IN endpoint FIFO empty interrupt enable register 834h */ + __IO uint32_t DEP1INT; /*!< USB device endpoint 1 interrupt register 838h */ + __IO uint32_t DEP1INTEN; /*!< USB device endpoint 1 interrupt enable register 83Ch */ + uint32_t Reserved40; /*!< Reserved 840h */ + __IO uint32_t DIEP1INTEN; /*!< USB device IN endpoint-1 interrupt enable register 844h */ + uint32_t Reserved48[15]; /*!< Reserved 848-880h */ + __IO uint32_t DOEP1INTEN; /*!< USB device OUT endpoint-1 interrupt enable register 884h */ +} usb_dr; + +typedef struct +{ + __IO uint32_t DIEPCTL; /*!< USB device IN endpoint control register 900h + (EpNum * 20h) + 00h */ + uint32_t Reserved04; /*!< Reserved 900h + (EpNum * 20h) + 04h */ + __IO uint32_t DIEPINTF; /*!< USB device IN endpoint interrupt flag register 900h + (EpNum * 20h) + 08h */ + uint32_t Reserved0C; /*!< Reserved 900h + (EpNum * 20h) + 0Ch */ + __IO uint32_t DIEPLEN; /*!< USB device IN endpoint transfer length register 900h + (EpNum * 20h) + 10h */ + __IO uint32_t DIEPDMAADDR; /*!< Device IN endpoint-x DMA address register 900h + (EpNum * 20h) + 14h */ + __IO uint32_t DIEPTFSTAT; /*!< USB device IN endpoint transmit FIFO status register 900h + (EpNum * 20h) + 18h */ +} usb_erin; + +typedef struct +{ + __IO uint32_t DOEPCTL; /*!< USB device IN endpoint control register B00h + (EpNum * 20h) + 00h */ + uint32_t Reserved04; /*!< Reserved B00h + (EpNum * 20h) + 04h */ + __IO uint32_t DOEPINTF; /*!< USB device IN endpoint interrupt flag register B00h + (EpNum * 20h) + 08h */ + uint32_t Reserved0C; /*!< Reserved B00h + (EpNum * 20h) + 0Ch */ + __IO uint32_t DOEPLEN; /*!< USB device IN endpoint transfer length register B00h + (EpNum * 20h) + 10h */ + __IO uint32_t DOEPDMAADDR; /*!< Device OUT endpoint-x DMA address register B00h + (EpNum * 20h) + 0Ch */ +} usb_erout; + +typedef struct _usb_regs +{ + usb_gr *gr; /*!< USBFS global registers */ + usb_dr *dr; /*!< Device control and status registers */ + usb_hr *hr; /*!< Host control and status registers */ + usb_erin *er_in[6]; /*!< USB device IN endpoint register */ + usb_erout *er_out[6]; /*!< USB device OUT endpoint register */ + usb_pr *pr[15]; /*!< USB Host channel-x control register */ + + __IO uint32_t *HPCS; /*!< USB host port control and status register */ + __IO uint32_t *DFIFO[USBFS_MAX_TX_FIFOS]; + __IO uint32_t *PWRCLKCTL; /*!< USB power and clock control register */ +} usb_core_regs; + +/* global OTG control and status register bits definitions */ +#define GOTGCS_BSV BIT(19) /*!< B-Session Valid */ +#define GOTGCS_ASV BIT(18) /*!< A-session valid */ +#define GOTGCS_DI BIT(17) /*!< debounce interval */ +#define GOTGCS_CIDPS BIT(16) /*!< id pin status */ +#define GOTGCS_DHNPEN BIT(11) /*!< device HNP enable */ +#define GOTGCS_HHNPEN BIT(10) /*!< host HNP enable */ +#define GOTGCS_HNPREQ BIT(9) /*!< HNP request */ +#define GOTGCS_HNPS BIT(8) /*!< HNP successes */ +#define GOTGCS_SRPREQ BIT(1) /*!< SRP request */ +#define GOTGCS_SRPS BIT(0) /*!< SRP successes */ + +/* global OTG interrupt flag register bits definitions */ +#define GOTGINTF_DF BIT(19) /*!< debounce finish */ +#define GOTGINTF_ADTO BIT(18) /*!< A-device timeout */ +#define GOTGINTF_HNPDET BIT(17) /*!< host negotiation request detected */ +#define GOTGINTF_HNPEND BIT(9) /*!< HNP end */ +#define GOTGINTF_SRPEND BIT(8) /*!< SRP end */ +#define GOTGINTF_SESEND BIT(2) /*!< session end */ + +/* global AHB control and status register bits definitions */ +#define GAHBCS_PTXFTH BIT(8) /*!< periodic Tx FIFO threshold */ +#define GAHBCS_TXFTH BIT(7) /*!< tx FIFO threshold */ +#define GAHBCS_DMAEN BIT(5) /*!< DMA function Enable */ +#define GAHBCS_BURST BITS(1, 4) /*!< the AHB burst type used by DMA */ +#define GAHBCS_GINTEN BIT(0) /*!< global interrupt enable */ + +/* global USB control and status register bits definitions */ +#define GUSBCS_FDM BIT(30) /*!< force device mode */ +#define GUSBCS_FHM BIT(29) /*!< force host mode */ +#define GUSBCS_ULPIEOI BIT(21) /*!< ULPI external over-current indicator */ +#define GUSBCS_ULPIEVD BIT(20) /*!< ULPI external VBUS driver */ +#define GUSBCS_UTT BITS(10, 13) /*!< USB turnaround time */ +#define GUSBCS_HNPCEN BIT(9) /*!< HNP capability enable */ +#define GUSBCS_SRPCEN BIT(8) /*!< SRP capability enable */ +#define GUSBCS_EMBPHY BIT(6) /*!< embedded PHY selected */ +#define GUSBCS_TOC BITS(0, 2) /*!< timeout calibration */ + +/* global reset control register bits definitions */ +#define GRSTCTL_DMAIDL BIT(31) /*!< DMA idle state */ +#define GRSTCTL_DMABSY BIT(30) /*!< DMA busy */ +#define GRSTCTL_TXFNUM BITS(6, 10) /*!< tx FIFO number */ +#define GRSTCTL_TXFF BIT(5) /*!< tx FIFO flush */ +#define GRSTCTL_RXFF BIT(4) /*!< rx FIFO flush */ +#define GRSTCTL_HFCRST BIT(2) /*!< host frame counter reset */ +#define GRSTCTL_HCSRST BIT(1) /*!< HCLK soft reset */ +#define GRSTCTL_CSRST BIT(0) /*!< core soft reset */ + +/* global interrupt flag register bits definitions */ +#define GINTF_WKUPIF BIT(31) /*!< wakeup interrupt flag */ +#define GINTF_SESIF BIT(30) /*!< session interrupt flag */ +#define GINTF_DISCIF BIT(29) /*!< disconnect interrupt flag */ +#define GINTF_IDPSC BIT(28) /*!< id pin status change */ +#define GINTF_PTXFEIF BIT(26) /*!< periodic tx FIFO empty interrupt flag */ +#define GINTF_HCIF BIT(25) /*!< host channels interrupt flag */ +#define GINTF_HPIF BIT(24) /*!< host port interrupt flag */ +#define GINTF_PXNCIF BIT(21) /*!< periodic transfer not complete interrupt flag */ +#define GINTF_ISOONCIF BIT(21) /*!< isochronous OUT transfer not complete interrupt flag */ +#define GINTF_ISOINCIF BIT(20) /*!< isochronous IN transfer not complete interrupt flag */ +#define GINTF_OEPIF BIT(19) /*!< OUT endpoint interrupt flag */ +#define GINTF_IEPIF BIT(18) /*!< IN endpoint interrupt flag */ +#define GINTF_EOPFIF BIT(15) /*!< end of periodic frame interrupt flag */ +#define GINTF_ISOOPDIF BIT(14) /*!< isochronous OUT packet dropped interrupt flag */ +#define GINTF_ENUMFIF BIT(13) /*!< enumeration finished */ +#define GINTF_RST BIT(12) /*!< USB reset */ +#define GINTF_SP BIT(11) /*!< USB suspend */ +#define GINTF_ESP BIT(10) /*!< early suspend */ +#define GINTF_GONAK BIT(7) /*!< global OUT NAK effective */ +#define GINTF_GNPINAK BIT(6) /*!< global IN non-periodic NAK effective */ +#define GINTF_NPTXFEIF BIT(5) /*!< non-periodic tx FIFO empty interrupt flag */ +#define GINTF_RXFNEIF BIT(4) /*!< rx FIFO non-empty interrupt flag */ +#define GINTF_SOF BIT(3) /*!< start of frame */ +#define GINTF_OTGIF BIT(2) /*!< OTG interrupt flag */ +#define GINTF_MFIF BIT(1) /*!< mode fault interrupt flag */ +#define GINTF_COPM BIT(0) /*!< current operation mode */ + +/* global interrupt enable register bits definitions */ +#define GINTEN_WKUPIE BIT(31) /*!< wakeup interrupt enable */ +#define GINTEN_SESIE BIT(30) /*!< session interrupt enable */ +#define GINTEN_DISCIE BIT(29) /*!< disconnect interrupt enable */ +#define GINTEN_IDPSCIE BIT(28) /*!< id pin status change interrupt enable */ +#define GINTEN_PTXFEIE BIT(26) /*!< periodic tx FIFO empty interrupt enable */ +#define GINTEN_HCIE BIT(25) /*!< host channels interrupt enable */ +#define GINTEN_HPIE BIT(24) /*!< host port interrupt enable */ +#define GINTEN_IPXIE BIT(21) /*!< periodic transfer not complete interrupt enable */ +#define GINTEN_ISOONCIE BIT(21) /*!< isochronous OUT transfer not complete interrupt enable */ +#define GINTEN_ISOINCIE BIT(20) /*!< isochronous IN transfer not complete interrupt enable */ +#define GINTEN_OEPIE BIT(19) /*!< OUT endpoints interrupt enable */ +#define GINTEN_IEPIE BIT(18) /*!< IN endpoints interrupt enable */ +#define GINTEN_EOPFIE BIT(15) /*!< end of periodic frame interrupt enable */ +#define GINTEN_ISOOPDIE BIT(14) /*!< isochronous OUT packet dropped interrupt enable */ +#define GINTEN_ENUMFIE BIT(13) /*!< enumeration finish enable */ +#define GINTEN_RSTIE BIT(12) /*!< USB reset interrupt enable */ +#define GINTEN_SPIE BIT(11) /*!< USB suspend interrupt enable */ +#define GINTEN_ESPIE BIT(10) /*!< early suspend interrupt enable */ +#define GINTEN_GONAKIE BIT(7) /*!< global OUT NAK effective interrupt enable */ +#define GINTEN_GNPINAKIE BIT(6) /*!< global non-periodic IN NAK effective interrupt enable */ +#define GINTEN_NPTXFEIE BIT(5) /*!< non-periodic Tx FIFO empty interrupt enable */ +#define GINTEN_RXFNEIE BIT(4) /*!< receive FIFO non-empty interrupt enable */ +#define GINTEN_SOFIE BIT(3) /*!< start of frame interrupt enable */ +#define GINTEN_OTGIE BIT(2) /*!< OTG interrupt enable */ +#define GINTEN_MFIE BIT(1) /*!< mode fault interrupt enable */ + +/* global receive status read and pop register bits definitions */ +#define GRSTATRP_RPCKST BITS(17, 20) /*!< received packet status */ +#define GRSTATRP_DPID BITS(15, 16) /*!< data PID */ +#define GRSTATRP_BCOUNT BITS(4, 14) /*!< byte count */ +#define GRSTATRP_CNUM BITS(0, 3) /*!< channel number */ +#define GRSTATRP_EPNUM BITS(0, 3) /*!< endpoint number */ + +/* global receive FIFO length register bits definitions */ +#define GRFLEN_RXFD BITS(0, 15) /*!< rx FIFO depth */ + +/* host non-periodic transmit FIFO length register bits definitions */ +#define HNPTFLEN_HNPTXFD BITS(16, 31) /*!< non-periodic Tx FIFO depth */ +#define HNPTFLEN_HNPTXRSAR BITS(0, 15) /*!< non-periodic Tx RAM start address */ + +/* USB IN endpoint 0 transmit FIFO length register bits definitions */ +#define DIEP0TFLEN_IEP0TXFD BITS(16, 31) /*!< IN Endpoint 0 Tx FIFO depth */ +#define DIEP0TFLEN_IEP0TXRSAR BITS(0, 15) /*!< IN Endpoint 0 TX RAM start address */ + +/* host non-periodic transmit FIFO/queue status register bits definitions */ +#define HNPTFQSTAT_NPTXRQTOP BITS(24, 30) /*!< top entry of the non-periodic Tx request queue */ +#define HNPTFQSTAT_NPTXRQS BITS(16, 23) /*!< non-periodic Tx request queue space */ +#define HNPTFQSTAT_NPTXFS BITS(0, 15) /*!< non-periodic Tx FIFO space */ +#define HNPTFQSTAT_CNUM BITS(27, 30) /*!< channel number*/ +#define HNPTFQSTAT_EPNUM BITS(27, 30) /*!< endpoint number */ +#define HNPTFQSTAT_TYPE BITS(25, 26) /*!< token type */ +#define HNPTFQSTAT_TMF BIT(24) /*!< terminate flag */ + +/* global core configuration register bits definitions */ +#define GCCFG_VBUSIG BIT(21) /*!< vbus ignored */ +#define GCCFG_SOFOEN BIT(20) /*!< SOF output enable */ +#define GCCFG_VBUSBCEN BIT(19) /*!< the VBUS B-device comparer enable */ +#define GCCFG_VBUSACEN BIT(18) /*!< the VBUS A-device comparer enable */ +#define GCCFG_PWRON BIT(16) /*!< power on */ + +/* core ID register bits definitions */ +#define CID_CID BITS(0, 31) /*!< core ID */ + +/* host periodic transmit FIFO length register bits definitions */ +#define HPTFLEN_HPTXFD BITS(16, 31) /*!< host periodic Tx FIFO depth */ +#define HPTFLEN_HPTXFSAR BITS(0, 15) /*!< host periodic Tx RAM start address */ + +/* device IN endpoint transmit FIFO length register bits definitions */ +#define DIEPTFLEN_IEPTXFD BITS(16, 31) /*!< IN endpoint Tx FIFO x depth */ +#define DIEPTFLEN_IEPTXRSAR BITS(0, 15) /*!< IN endpoint FIFOx Tx x RAM start address */ + +/* host control register bits definitions */ +#define HCTL_SPDFSLS BIT(2) /*!< speed limited to FS and LS */ +#define HCTL_CLKSEL BITS(0, 1) /*!< clock select for USB clock */ + +/* host frame interval register bits definitions */ +#define HFT_FRI BITS(0, 15) /*!< frame interval */ + +/* host frame information remaining register bits definitions */ +#define HFINFR_FRT BITS(16, 31) /*!< frame remaining time */ +#define HFINFR_FRNUM BITS(0, 15) /*!< frame number */ + +/* host periodic transmit FIFO/queue status register bits definitions */ +#define HPTFQSTAT_PTXREQT BITS(24, 31) /*!< top entry of the periodic Tx request queue */ +#define HPTFQSTAT_PTXREQS BITS(16, 23) /*!< periodic Tx request queue space */ +#define HPTFQSTAT_PTXFS BITS(0, 15) /*!< periodic Tx FIFO space */ +#define HPTFQSTAT_OEFRM BIT(31) /*!< odd/eveb frame */ +#define HPTFQSTAT_CNUM BITS(27, 30) /*!< channel number */ +#define HPTFQSTAT_EPNUM BITS(27, 30) /*!< endpoint number */ +#define HPTFQSTAT_TYPE BITS(25, 26) /*!< token type */ +#define HPTFQSTAT_TMF BIT(24) /*!< terminate flag */ + +#define TFQSTAT_TXFS BITS(0, 15) +#define TFQSTAT_CNUM BITS(27, 30) + +/* host all channels interrupt register bits definitions */ +#define HACHINT_HACHINT BITS(0, 11) /*!< host all channel interrupts */ + +/* host all channels interrupt enable register bits definitions */ +#define HACHINTEN_CINTEN BITS(0, 11) /*!< channel interrupt enable */ + +/* host port control and status register bits definitions */ +#define HPCS_PS BITS(17, 18) /*!< port speed */ +#define HPCS_PP BIT(12) /*!< port power */ +#define HPCS_PLST BITS(10, 11) /*!< port line status */ +#define HPCS_PRST BIT(8) /*!< port reset */ +#define HPCS_PSP BIT(7) /*!< port suspend */ +#define HPCS_PREM BIT(6) /*!< port resume */ +#define HPCS_PEDC BIT(3) /*!< port enable/disable change */ +#define HPCS_PE BIT(2) /*!< port enable */ +#define HPCS_PCD BIT(1) /*!< port connect detected */ +#define HPCS_PCST BIT(0) /*!< port connect status */ + +/* host channel-x control register bits definitions */ +#define HCHCTL_CEN BIT(31) /*!< channel enable */ +#define HCHCTL_CDIS BIT(30) /*!< channel disable */ +#define HCHCTL_ODDFRM BIT(29) /*!< odd frame */ +#define HCHCTL_DAR BITS(22, 28) /*!< device address */ +#define HCHCTL_MPC BITS(20, 21) /*!< multiple packet count */ +#define HCHCTL_EPTYPE BITS(18, 19) /*!< endpoint type */ +#define HCHCTL_LSD BIT(17) /*!< low-speed device */ +#define HCHCTL_EPDIR BIT(15) /*!< endpoint direction */ +#define HCHCTL_EPNUM BITS(11, 14) /*!< endpoint number */ +#define HCHCTL_MPL BITS(0, 10) /*!< maximum packet length */ + +/* host channel-x split transaction register bits definitions */ +#define HCHSTCTL_SPLEN BIT(31) /*!< enable high-speed split transaction */ +#define HCHSTCTL_CSPLT BIT(16) /*!< complete-split enable */ +#define HCHSTCTL_ISOPCE BITS(14, 15) /*!< isochronous OUT payload continuation encoding */ +#define HCHSTCTL_HADDR BITS(7, 13) /*!< HUB address */ +#define HCHSTCTL_PADDR BITS(0, 6) /*!< port address */ + +/* host channel-x interrupt flag register bits definitions */ +#define HCHINTF_DTER BIT(10) /*!< data toggle error */ +#define HCHINTF_REQOVR BIT(9) /*!< request queue overrun */ +#define HCHINTF_BBER BIT(8) /*!< babble error */ +#define HCHINTF_USBER BIT(7) /*!< USB bus Error */ +#define HCHINTF_NYET BIT(6) /*!< NYET */ +#define HCHINTF_ACK BIT(5) /*!< ACK */ +#define HCHINTF_NAK BIT(4) /*!< NAK */ +#define HCHINTF_STALL BIT(3) /*!< STALL */ +#define HCHINTF_DMAER BIT(2) /*!< DMA error */ +#define HCHINTF_CH BIT(1) /*!< channel halted */ +#define HCHINTF_TF BIT(0) /*!< transfer finished */ + +/* host channel-x interrupt enable register bits definitions */ +#define HCHINTEN_DTERIE BIT(10) /*!< data toggle error interrupt enable */ +#define HCHINTEN_REQOVRIE BIT(9) /*!< request queue overrun interrupt enable */ +#define HCHINTEN_BBERIE BIT(8) /*!< babble error interrupt enable */ +#define HCHINTEN_USBERIE BIT(7) /*!< USB bus error interrupt enable */ +#define HCHINTEN_NYETIE BIT(6) /*!< NYET interrupt enable */ +#define HCHINTEN_ACKIE BIT(5) /*!< ACK interrupt enable */ +#define HCHINTEN_NAKIE BIT(4) /*!< NAK interrupt enable */ +#define HCHINTEN_STALLIE BIT(3) /*!< STALL interrupt enable */ +#define HCHINTEN_DMAERIE BIT(2) /*!< DMA error interrupt enable */ +#define HCHINTEN_CHIE BIT(1) /*!< channel halted interrupt enable */ +#define HCHINTEN_TFIE BIT(0) /*!< transfer finished interrupt enable */ + +/* host channel-x transfer length register bits definitions */ +#define HCHLEN_PING BIT(31) /*!< PING token request */ +#define HCHLEN_DPID BITS(29, 30) /*!< data PID */ +#define HCHLEN_PCNT BITS(19, 28) /*!< packet count */ +#define HCHLEN_TLEN BITS(0, 18) /*!< transfer length */ + +/* host channel-x DMA address register bits definitions */ +#define HCHDMAADDR_DMAADDR BITS(0, 31) /*!< DMA address */ + +#define PORT_SPEED(x) (((uint32_t)(x) << 17) & HPCS_PS) /*!< Port speed */ + +#define PORT_SPEED_HIGH PORT_SPEED(0U) /*!< high speed */ +#define PORT_SPEED_FULL PORT_SPEED(1U) /*!< full speed */ +#define PORT_SPEED_LOW PORT_SPEED(2U) /*!< low speed */ + +#define PIPE_CTL_DAR(x) (((uint32_t)(x) << 22) & HCHCTL_DAR) /*!< device address */ +#define PIPE_CTL_EPTYPE(x) (((uint32_t)(x) << 18) & HCHCTL_EPTYPE) /*!< endpoint type */ +#define PIPE_CTL_EPNUM(x) (((uint32_t)(x) << 11) & HCHCTL_EPNUM) /*!< endpoint number */ +#define PIPE_CTL_EPDIR(x) (((uint32_t)(x) << 15) & HCHCTL_EPDIR) /*!< endpoint direction */ +#define PIPE_CTL_EPMPL(x) (((uint32_t)(x) << 0) & HCHCTL_MPL) /*!< maximum packet length */ +#define PIPE_CTL_LSD(x) (((uint32_t)(x) << 17) & HCHCTL_LSD) /*!< low-Speed device */ + +#define PIPE_XFER_PCNT(x) (((uint32_t)(x) << 19) & HCHLEN_PCNT) /*!< packet count */ +#define PIPE_XFER_DPID(x) (((uint32_t)(x) << 29) & HCHLEN_DPID) /*!< data PID */ + +#define PIPE_DPID_DATA0 PIPE_XFER_DPID(0) /*!< DATA0 */ +#define PIPE_DPID_DATA1 PIPE_XFER_DPID(2) /*!< DATA1 */ +#define PIPE_DPID_DATA2 PIPE_XFER_DPID(1) /*!< DATA2 */ +#define PIPE_DPID_SETUP PIPE_XFER_DPID(3) /*!< MDATA (non-control)/SETUP (control) */ + +extern const uint32_t PIPE_DPID[2]; + +/* device configuration registers bits definitions */ +#define DCFG_EOPFT BITS(11, 12) /*!< end of periodic frame time */ +#define DCFG_DAR BITS(4, 10) /*!< device address */ +#define DCFG_NZLSOH BIT(2) /*!< non-zero-length status OUT handshake */ +#define DCFG_DS BITS(0, 1) /*!< device speed */ + +/* device control registers bits definitions */ +#define DCTL_POIF BIT(11) /*!< power-on initialization finished */ +#define DCTL_CGONAK BIT(10) /*!< clear global OUT NAK */ +#define DCTL_SGONAK BIT(9) /*!< set global OUT NAK */ +#define DCTL_CGINAK BIT(8) /*!< clear global IN NAK */ +#define DCTL_SGINAK BIT(7) /*!< set global IN NAK */ +#define DCTL_GONS BIT(3) /*!< global OUT NAK status */ +#define DCTL_GINS BIT(2) /*!< global IN NAK status */ +#define DCTL_SD BIT(1) /*!< soft disconnect */ +#define DCTL_RWKUP BIT(0) /*!< remote wakeup */ + +/* device status registers bits definitions */ +#define DSTAT_FNRSOF BITS(8, 21) /*!< the frame number of the received SOF. */ +#define DSTAT_ES BITS(1, 2) /*!< enumerated speed */ +#define DSTAT_SPST BIT(0) /*!< suspend status */ + +/* device IN endpoint common interrupt enable registers bits definitions */ +#define DIEPINTEN_NAKEN BIT(13) /*!< NAK handshake sent by USBHS interrupt enable bit */ +#define DIEPINTEN_TXFEEN BIT(7) /*!< transmit FIFO empty interrupt enable bit */ +#define DIEPINTEN_IEPNEEN BIT(6) /*!< IN endpoint NAK effective interrupt enable bit */ +#define DIEPINTEN_EPTXFUDEN BIT(4) /*!< endpoint Tx FIFO underrun interrupt enable bit */ +#define DIEPINTEN_CITOEN BIT(3) /*!< control In Timeout interrupt enable bit */ +#define DIEPINTEN_EPDISEN BIT(1) /*!< endpoint disabled interrupt enable bit */ +#define DIEPINTEN_TFEN BIT(0) /*!< transfer finished interrupt enable bit */ + +/* device OUT endpoint common interrupt enable registers bits definitions */ +#define DOEPINTEN_NYETEN BIT(14) /*!< NYET handshake is sent interrupt enable bit */ +#define DOEPINTEN_BTBSTPEN BIT(6) /*!< back-to-back SETUP packets interrupt enable bit */ +#define DOEPINTEN_EPRXFOVREN BIT(4) /*!< endpoint Rx FIFO overrun interrupt enable bit */ +#define DOEPINTEN_STPFEN BIT(3) /*!< SETUP phase finished interrupt enable bit */ +#define DOEPINTEN_EPDISEN BIT(1) /*!< endpoint disabled interrupt enable bit */ +#define DOEPINTEN_TFEN BIT(0) /*!< transfer finished interrupt enable bit */ + +/* device all endpoints interrupt registers bits definitions */ +#define DAEPINT_OEPITB BITS(16, 21) /*!< device all OUT endpoint interrupt bits */ +#define DAEPINT_IEPITB BITS(0, 5) /*!< device all IN endpoint interrupt bits */ + +/* device all endpoints interrupt enable registers bits definitions */ +#define DAEPINTEN_OEPIE BITS(16, 21) /*!< OUT endpoint interrupt enable */ +#define DAEPINTEN_IEPIE BITS(0, 3) /*!< IN endpoint interrupt enable */ + +/* device Vbus discharge time registers bits definitions */ +#define DVBUSDT_DVBUSDT BITS(0, 15) /*!< device VBUS discharge time */ + +/* device Vbus pulsing time registers bits definitions */ +#define DVBUSPT_DVBUSPT BITS(0, 11) /*!< device VBUS pulsing time */ + +/* device IN endpoint FIFO empty interrupt enable register bits definitions */ +#define DIEPFEINTEN_IEPTXFEIE BITS(0, 5) /*!< IN endpoint Tx FIFO empty interrupt enable bits */ + +/* device endpoint 0 control register bits definitions */ +#define DEP0CTL_EPEN BIT(31) /*!< endpoint enable */ +#define DEP0CTL_EPD BIT(30) /*!< endpoint disable */ +#define DEP0CTL_SNAK BIT(27) /*!< set NAK */ +#define DEP0CTL_CNAK BIT(26) /*!< clear NAK */ +#define DIEP0CTL_TXFNUM BITS(22, 25) /*!< tx FIFO number */ +#define DEP0CTL_STALL BIT(21) /*!< STALL handshake */ +#define DOEP0CTL_SNOOP BIT(20) /*!< snoop mode */ +#define DEP0CTL_EPTYPE BITS(18, 19) /*!< endpoint type */ +#define DEP0CTL_NAKS BIT(17) /*!< NAK status */ +#define DEP0CTL_EPACT BIT(15) /*!< endpoint active */ +#define DEP0CTL_MPL BITS(0, 1) /*!< maximum packet length */ + +/* device endpoint x control register bits definitions */ +#define DEPCTL_EPEN BIT(31) /*!< endpoint enable */ +#define DEPCTL_EPD BIT(30) /*!< endpoint disable */ +#define DEPCTL_SODDFRM BIT(29) /*!< set odd frame */ +#define DEPCTL_SD1PID BIT(29) /*!< set DATA1 PID */ +#define DEPCTL_SEVNFRM BIT(28) /*!< set even frame */ +#define DEPCTL_SD0PID BIT(28) /*!< set DATA0 PID */ +#define DEPCTL_SNAK BIT(27) /*!< set NAK */ +#define DEPCTL_CNAK BIT(26) /*!< clear NAK */ +#define DIEPCTL_TXFNUM BITS(22, 25) /*!< tx FIFO number */ +#define DEPCTL_STALL BIT(21) /*!< STALL handshake */ +#define DOEPCTL_SNOOP BIT(20) /*!< snoop mode */ +#define DEPCTL_EPTYPE BITS(18, 19) /*!< endpoint type */ +#define DEPCTL_NAKS BIT(17) /*!< NAK status */ +#define DEPCTL_EOFRM BIT(16) /*!< even/odd frame */ +#define DEPCTL_DPID BIT(16) /*!< endpoint data PID */ +#define DEPCTL_EPACT BIT(15) /*!< endpoint active */ +#define DEPCTL_MPL BITS(0, 10) /*!< maximum packet length */ + +/* device IN endpoint-x interrupt flag register bits definitions */ +#define DIEPINTF_NAK BIT(13) /*!< NAK handshake sent by USBHS */ +#define DIEPINTF_TXFE BIT(7) /*!< transmit FIFO empty */ +#define DIEPINTF_IEPNE BIT(6) /*!< IN endpoint NAK effective */ +#define DIEPINTF_EPTXFUD BIT(4) /*!< endpoint Tx FIFO underrun */ +#define DIEPINTF_CITO BIT(3) /*!< control In Timeout interrupt */ +#define DIEPINTF_EPDIS BIT(1) /*!< endpoint disabled */ +#define DIEPINTF_TF BIT(0) /*!< transfer finished */ + +/* device OUT endpoint-x interrupt flag register bits definitions */ +#define DOEPINTF_NYET BIT(14) /*!< NYET handshake is sent */ +#define DOEPINTF_BTBSTP BIT(6) /*!< back-to-back SETUP packets */ +#define DOEPINTF_EPRXFOVR BIT(4) /*!< endpoint Rx FIFO overrun */ +#define DOEPINTF_STPF BIT(3) /*!< SETUP phase finished */ +#define DOEPINTF_EPDIS BIT(1) /*!< endpoint disabled */ +#define DOEPINTF_TF BIT(0) /*!< transfer finished */ + +/* device IN endpoint 0 transfer length register bits definitions */ +#define DIEP0LEN_PCNT BITS(19, 20) /*!< packet count */ +#define DIEP0LEN_TLEN BITS(0, 6) /*!< transfer length */ + +/* device OUT endpoint 0 transfer length register bits definitions */ +#define DOEP0LEN_STPCNT BITS(29, 30) /*!< SETUP packet count */ +#define DOEP0LEN_PCNT BIT(19) /*!< packet count */ +#define DOEP0LEN_TLEN BITS(0, 6) /*!< transfer length */ + +/* device OUT endpoint-x transfer length register bits definitions */ +#define DOEPLEN_RXDPID BITS(29, 30) /*!< received data PID */ +#define DOEPLEN_STPCNT BITS(29, 30) /*!< SETUP packet count */ +#define DIEPLEN_MCNT BITS(29, 30) /*!< multi count */ +#define DEPLEN_PCNT BITS(19, 28) /*!< packet count */ +#define DEPLEN_TLEN BITS(0, 18) /*!< transfer length */ + +/* device IN endpoint-x DMA address register bits definitions */ +#define DIEPDMAADDR_DMAADDR BITS(0, 31) /*!< DMA address */ + +/* device OUT endpoint-x DMA address register bits definitions */ +#define DOEPDMAADDR_DMAADDR BITS(0, 31) /*!< DMA address */ + +/* device IN endpoint-x transmit FIFO status register bits definitions */ +#define DIEPTFSTAT_IEPTFS BITS(0, 15) /*!< IN endpoint Tx FIFO space remaining */ + +/* USB power and clock registers bits definition */ +#define PWRCLKCTL_SHCLK BIT(1) /*!< stop HCLK */ +#define PWRCLKCTL_SUCLK BIT(0) /*!< stop the USB clock */ + +#define RSTAT_GOUT_NAK 1U /* global OUT NAK (triggers an interrupt) */ +#define RSTAT_DATA_UPDT 2U /* OUT data packet received */ +#define RSTAT_XFER_COMP 3U /* OUT transfer completed (triggers an interrupt) */ +#define RSTAT_SETUP_COMP 4U /* SETUP transaction completed (triggers an interrupt) */ +#define RSTAT_SETUP_UPDT 6U /* SETUP data packet received */ + +#define DSTAT_EM_HS_PHY_30MHZ_60MHZ 0U /* USB enumerate speed use high-speed PHY clock in 30MHz or 60MHz */ +#define DSTAT_EM_FS_PHY_30MHZ_60MHZ 1U /* USB enumerate speed use full-speed PHY clock in 30MHz or 60MHz */ +#define DSTAT_EM_LS_PHY_6MHZ 2U /* USB enumerate speed use low-speed PHY clock in 6MHz */ +#define DSTAT_EM_FS_PHY_48MHZ 3U /* USB enumerate speed use full-speed PHY clock in 48MHz */ + +#define DPID_DATA0 0U /* device endpoint data PID is DATA0 */ +#define DPID_DATA1 2U /* device endpoint data PID is DATA1 */ +#define DPID_DATA2 1U /* device endpoint data PID is DATA2 */ +#define DPID_MDATA 3U /* device endpoint data PID is MDATA */ + +#define GAHBCS_DMAINCR(regval) (GAHBCS_BURST & ((regval) << 1)) /*!< AHB burst type used by DMA*/ + +#define DMA_INCR0 GAHBCS_DMAINCR(0U) /*!< single burst type used by DMA*/ +#define DMA_INCR1 GAHBCS_DMAINCR(1U) /*!< 4-beat incrementing burst type used by DMA*/ +#define DMA_INCR4 GAHBCS_DMAINCR(3U) /*!< 8-beat incrementing burst type used by DMA*/ +#define DMA_INCR8 GAHBCS_DMAINCR(5U) /*!< 16-beat incrementing burst type used by DMA*/ +#define DMA_INCR16 GAHBCS_DMAINCR(7U) /*!< 32-beat incrementing burst type used by DMA*/ + +#define DCFG_PFRI(regval) (DCFG_EOPFT & ((regval) << 11)) /*!< end of periodic frame time configuration */ + +#define FRAME_INTERVAL_80 DCFG_PFRI(0U) /*!< 80% of the frame time */ +#define FRAME_INTERVAL_85 DCFG_PFRI(1U) /*!< 85% of the frame time */ +#define FRAME_INTERVAL_90 DCFG_PFRI(2U) /*!< 90% of the frame time */ +#define FRAME_INTERVAL_95 DCFG_PFRI(3U) /*!< 95% of the frame time */ + +#define DCFG_DEVSPEED(regval) (DCFG_DS & ((regval) << 0)) /*!< device speed configuration */ + +#define USB_SPEED_EXP_HIGH DCFG_DEVSPEED(0U) /*!< device external PHY high speed */ +#define USB_SPEED_EXP_FULL DCFG_DEVSPEED(1U) /*!< device external PHY full speed */ +#define USB_SPEED_INP_FULL DCFG_DEVSPEED(3U) /*!< device internal PHY full speed */ + +#define DEP0_MPL(regval) (DEP0CTL_MPL & ((regval) << 0)) /*!< maximum packet length configuration */ + +#define EP0MPL_64 DEP0_MPL(0U) /*!< maximum packet length 64 bytes */ +#define EP0MPL_32 DEP0_MPL(1U) /*!< maximum packet length 32 bytes */ +#define EP0MPL_16 DEP0_MPL(2U) /*!< maximum packet length 16 bytes */ +#define EP0MPL_8 DEP0_MPL(3U) /*!< maximum packet length 8 bytes */ + +#define DOEP0_TLEN(regval) (DOEP0LEN_TLEN & ((regval) << 0)) /*!< Transfer length */ +#define DOEP0_PCNT(regval) (DOEP0LEN_PCNT & ((regval) << 19)) /*!< Packet count */ +#define DOEP0_STPCNT(regval) (DOEP0LEN_STPCNT & ((regval) << 29)) /*!< SETUP packet count */ + +#define USB_ULPI_PHY 1U /*!< ULPI interface external PHY */ +#define USB_EMBEDDED_PHY 2U /*!< Embedded PHY */ + +#define GRXSTS_PKTSTS_IN 2U +#define GRXSTS_PKTSTS_IN_XFER_COMP 3U +#define GRXSTS_PKTSTS_DATA_TOGGLE_ERR 5U +#define GRXSTS_PKTSTS_CH_HALTED 7U + +#define HCTL_30_60MHZ 0U /*!< USB clock 30-60MHZ */ +#define HCTL_48MHZ 1U /*!< USB clock 48MHZ */ +#define HCTL_6MHZ 2U /*!< USB clock 6MHZ */ + +#define EP0_OUT ((uint8_t)0x00) /*!< endpoint out 0 */ +#define EP0_IN ((uint8_t)0x80) /*!< endpoint in 0 */ +#define EP1_OUT ((uint8_t)0x01) /*!< endpoint out 1 */ +#define EP1_IN ((uint8_t)0x81) /*!< endpoint in 1 */ +#define EP2_OUT ((uint8_t)0x02) /*!< endpoint out 2 */ +#define EP2_IN ((uint8_t)0x82) /*!< endpoint in 2 */ +#define EP3_OUT ((uint8_t)0x03) /*!< endpoint out 3 */ +#define EP3_IN ((uint8_t)0x83) /*!< endpoint in 3 */ + +#endif /* __DRV_USB_REGS_H */ diff --git a/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/driver/Include/drv_usbd_int.h b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/driver/Include/drv_usbd_int.h new file mode 100644 index 0000000000..0e2803a98d --- /dev/null +++ b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/driver/Include/drv_usbd_int.h @@ -0,0 +1,45 @@ +/*! + \file drv_usbd_int.h + \brief USB device mode interrupt header file + + \version 2020-08-01, V3.0.0, firmware for GD32F30x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef __DRV_USBD_INT_H +#define __DRV_USBD_INT_H + +#include "drv_usb_core.h" +#include "drv_usb_dev.h" + +/* function declarations */ +/* USB device-mode interrupts global service routine handler */ +void usbd_isr (usb_core_driver *udev); + +#endif /* __DRV_USBD_INT_H */ diff --git a/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/driver/Include/drv_usbh_int.h b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/driver/Include/drv_usbh_int.h new file mode 100644 index 0000000000..995e32e791 --- /dev/null +++ b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/driver/Include/drv_usbh_int.h @@ -0,0 +1,56 @@ +/*! + \file drv_usbh_int.h.h + \brief USB host mode interrupt management header file + + \version 2020-08-01, V3.0.0, firmware for GD32F30x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef __DRV_USBH_INT_H +#define __DRV_USBH_INT_H + +#include "drv_usb_host.h" +#include "usbh_core.h" + +typedef struct _usbh_int_cb +{ + uint8_t (*connect) (usbh_host *puhost); + uint8_t (*disconnect) (usbh_host *puhost); + uint8_t (*port_enabled) (usbh_host *puhost); + uint8_t (*port_disabled) (usbh_host *puhost); + uint8_t (*SOF) (usbh_host *puhost); +} usbh_int_cb; + +extern usbh_int_cb *usbh_int_fop; + +/* function declarations */ +/* handle global host interrupt */ +uint32_t usbh_isr (usb_core_driver *pudev); + +#endif /* __DRV_USBH_INT_H */ diff --git a/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/driver/Source/drv_usb_core.c b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/driver/Source/drv_usb_core.c new file mode 100644 index 0000000000..7944a8194b --- /dev/null +++ b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/driver/Source/drv_usb_core.c @@ -0,0 +1,343 @@ +/*! + \file drv_usb_core.c + \brief USB core driver which can operate in host and device mode + + \version 2020-08-01, V3.0.0, firmware for GD32F30x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "drv_usb_core.h" +#include "drv_usb_hw.h" + +/* local function prototypes ('static') */ +static void usb_core_reset (usb_core_regs *usb_regs); + +/*! + \brief configure USB core basic + \param[in] usb_basic: pointer to usb capabilities + \param[in] usb_regs: USB core registers + \param[in] usb_core: USB core + \param[out] none + \retval operation status +*/ +usb_status usb_basic_init (usb_core_basic *usb_basic, + usb_core_regs *usb_regs, + usb_core_enum usb_core) +{ + /* configure USB default transfer mode as FIFO mode */ + usb_basic->transfer_mode = (uint8_t)USB_USE_FIFO; + + /* USB default speed is full-speed */ + usb_basic->core_speed = (uint8_t)USB_SPEED_FULL; + + usb_basic->core_enum = (uint8_t)usb_core; + + switch (usb_core) { + case USB_CORE_ENUM_FS: + usb_basic->base_reg = (uint32_t)USBFS_REG_BASE; + + /* set the host channel numbers */ + usb_basic->num_pipe = USBFS_MAX_CHANNEL_COUNT; + + /* set the device endpoint numbers */ + usb_basic->num_ep = USBFS_MAX_EP_COUNT; + + /* USBFS core use embedded physical layer */ + usb_basic->phy_itf = USB_EMBEDDED_PHY; + break; + + default: + return USB_FAIL; + } + + usb_basic->sof_enable = USB_SOF_OUTPUT; + usb_basic->low_power = USB_LOW_POWER; + + /* assign main registers address */ + *usb_regs = (usb_core_regs) { + .gr = (usb_gr*) (usb_basic->base_reg + USB_REG_OFFSET_CORE), + .hr = (usb_hr*) (usb_basic->base_reg + USB_REG_OFFSET_HOST), + .dr = (usb_dr*) (usb_basic->base_reg + USB_REG_OFFSET_DEV), + + .HPCS = (uint32_t*) (usb_basic->base_reg + USB_REG_OFFSET_PORT), + .PWRCLKCTL = (uint32_t*) (usb_basic->base_reg + USB_REG_OFFSET_PWRCLKCTL) + }; + + /* assign device endpoint registers address */ + for (uint8_t i = 0U; i < usb_basic->num_ep; i++) { + usb_regs->er_in[i] = (usb_erin *) \ + (usb_basic->base_reg + USB_REG_OFFSET_EP_IN + (i * USB_REG_OFFSET_EP)); + + usb_regs->er_out[i] = (usb_erout *)\ + (usb_basic->base_reg + USB_REG_OFFSET_EP_OUT + (i * USB_REG_OFFSET_EP)); + } + + /* assign host pipe registers address */ + for (uint8_t i = 0U; i < usb_basic->num_pipe; i++) { + usb_regs->pr[i] = (usb_pr *) \ + (usb_basic->base_reg + USB_REG_OFFSET_CH_INOUT + (i * USB_REG_OFFSET_CH)); + + usb_regs->DFIFO[i] = (uint32_t *) \ + (usb_basic->base_reg + USB_DATA_FIFO_OFFSET + (i * USB_DATA_FIFO_SIZE)); + } + + return USB_OK; +} + +/*! + \brief initializes the USB controller registers and + prepares the core device mode or host mode operation + \param[in] usb_basic: pointer to USB capabilities + \param[in] usb_regs: pointer to USB core registers + \param[out] none + \retval operation status +*/ +usb_status usb_core_init (usb_core_basic usb_basic, usb_core_regs *usb_regs) +{ + if (USB_ULPI_PHY == usb_basic.phy_itf) { + usb_regs->gr->GCCFG &= ~GCCFG_PWRON; + + if (usb_basic.sof_enable) { + usb_regs->gr->GCCFG |= GCCFG_SOFOEN; + } + + /* init the ULPI interface */ + usb_regs->gr->GUSBCS &= ~(GUSBCS_EMBPHY | GUSBCS_ULPIEOI); + +#ifdef USBHS_EXTERNAL_VBUS_ENABLED + /* use external VBUS driver */ + usb_regs->gr->GUSBCS |= GUSBCS_ULPIEVD; +#else + /* use internal VBUS driver */ + usb_regs->gr->GUSBCS &= ~GUSBCS_ULPIEVD; +#endif /* USBHS_EXTERNAL_VBUS_ENABLED */ + + /* soft reset the core */ + usb_core_reset (usb_regs); + } else { + usb_regs->gr->GUSBCS |= GUSBCS_EMBPHY; + + /* soft reset the core */ + usb_core_reset (usb_regs); + + /* active the transceiver and enable VBUS sensing */ + usb_regs->gr->GCCFG |= GCCFG_PWRON | GCCFG_VBUSACEN | GCCFG_VBUSBCEN; + +#ifndef VBUS_SENSING_ENABLED + usb_regs->gr->GCCFG |= GCCFG_VBUSIG; +#endif /* VBUS_SENSING_ENABLED */ + + /* enable SOF output */ + if (usb_basic.sof_enable) { + usb_regs->gr->GCCFG |= GCCFG_SOFOEN; + } + + usb_mdelay(20U); + } + + if ((uint8_t)USB_USE_DMA == usb_basic.transfer_mode) { + usb_regs->gr->GAHBCS &= ~GAHBCS_BURST; + usb_regs->gr->GAHBCS |= DMA_INCR8 | GAHBCS_DMAEN; + } + +#ifdef USE_OTG_MODE + + /* enable USB OTG features */ + usb_regs->gr->GUSBCS |= GUSBCS_HNPCEN | GUSBCS_SRPCEN; + + /* enable the USB wakeup and suspend interrupts */ + usb_regs->gr->GINTF = 0xBFFFFFFFU; + + usb_regs->gr->GINTEN = GINTEN_WKUPIE | GINTEN_SPIE | \ + GINTEN_OTGIE | GINTEN_SESIE | GINTEN_CIDPSCIE; + +#endif /* USE_OTG_MODE */ + + return USB_OK; +} + +/*! + \brief write a packet into the Tx FIFO associated with the endpoint + \param[in] usb_regs: pointer to USB core registers + \param[in] src_buf: pointer to source buffer + \param[in] fifo_num: FIFO number which is in (0..3) + \param[in] byte_count: packet byte count + \param[out] none + \retval operation status +*/ +usb_status usb_txfifo_write (usb_core_regs *usb_regs, + uint8_t *src_buf, + uint8_t fifo_num, + uint16_t byte_count) +{ + uint32_t word_count = (byte_count + 3U) / 4U; + + __IO uint32_t *fifo = usb_regs->DFIFO[fifo_num]; + + while (word_count-- > 0U) { + *fifo = *((__packed uint32_t *)src_buf); + + src_buf += 4U; + } + + return USB_OK; +} + +/*! + \brief read a packet from the Rx FIFO associated with the endpoint + \param[in] usb_regs: pointer to USB core registers + \param[in] dest_buf: pointer to destination buffer + \param[in] byte_count: packet byte count + \param[out] none + \retval void type pointer +*/ +void *usb_rxfifo_read (usb_core_regs *usb_regs, uint8_t *dest_buf, uint16_t byte_count) +{ + uint32_t word_count = (byte_count + 3U) / 4U; + + __IO uint32_t *fifo = usb_regs->DFIFO[0]; + + while (word_count-- > 0U) { + *(__packed uint32_t *)dest_buf = *fifo; + + dest_buf += 4U; + } + + return ((void *)dest_buf); +} + +/*! + \brief flush a Tx FIFO or all Tx FIFOs + \param[in] usb_regs: pointer to USB core registers + \param[in] fifo_num: FIFO number which is in (0..3) + \param[out] none + \retval operation status +*/ +usb_status usb_txfifo_flush (usb_core_regs *usb_regs, uint8_t fifo_num) +{ + usb_regs->gr->GRSTCTL = ((uint32_t)fifo_num << 6U) | GRSTCTL_TXFF; + + /* wait for Tx FIFO flush bit is set */ + while (usb_regs->gr->GRSTCTL & GRSTCTL_TXFF) { + /* no operation */ + } + + /* wait for 3 PHY clocks*/ + usb_udelay(3U); + + return USB_OK; +} + +/*! + \brief flush the entire Rx FIFO + \param[in] usb_regs: pointer to usb core registers + \param[out] none + \retval operation status +*/ +usb_status usb_rxfifo_flush (usb_core_regs *usb_regs) +{ + usb_regs->gr->GRSTCTL = GRSTCTL_RXFF; + + /* wait for Rx FIFO flush bit is set */ + while (usb_regs->gr->GRSTCTL & GRSTCTL_RXFF) { + /* no operation */ + } + + /* wait for 3 PHY clocks */ + usb_udelay(3U); + + return USB_OK; +} + +/*! + \brief set endpoint or channel TX FIFO size + \param[in] usb_regs: pointer to USB core registers + \param[in] fifo: TX FIFO number + \param[in] size: assigned TX FIFO size + \param[out] none + \retval none +*/ +void usb_set_txfifo(usb_core_regs *usb_regs, uint8_t fifo, uint16_t size) +{ + uint32_t tx_offset; + + tx_offset = usb_regs->gr->GRFLEN; + + if (fifo == 0U) { + usb_regs->gr->DIEP0TFLEN_HNPTFLEN = ((uint32_t)size << 16) | tx_offset; + } else { + tx_offset += (usb_regs->gr->DIEP0TFLEN_HNPTFLEN) >> 16; + + for (uint8_t i = 0U; i < (fifo - 1U); i++) { + tx_offset += (usb_regs->gr->DIEPTFLEN[i] >> 16); + } + + /* Multiply Tx_Size by 2 to get higher performance */ + usb_regs->gr->DIEPTFLEN[fifo - 1U] = ((uint32_t)size << 16) | tx_offset; + } +} + +/*! + \brief set USB current mode + \param[in] usb_regs: pointer to USB core registers + \param[out] none + \retval none +*/ +void usb_curmode_set(usb_core_regs *usb_regs, uint8_t mode) +{ + usb_regs->gr->GUSBCS &= ~(GUSBCS_FDM | GUSBCS_FHM); + + if (DEVICE_MODE == mode) { + usb_regs->gr->GUSBCS |= GUSBCS_FDM; + } else if (HOST_MODE == mode) { + usb_regs->gr->GUSBCS |= GUSBCS_FHM; + } else { + /* OTG mode and other mode can not be here! */ + } +} + +/*! + \brief configure USB core to soft reset + \param[in] usb_regs: pointer to USB core registers + \param[out] none + \retval none +*/ +static void usb_core_reset (usb_core_regs *usb_regs) +{ + /* enable core soft reset */ + usb_regs->gr->GRSTCTL |= GRSTCTL_CSRST; + + /* wait for the core to be soft reset */ + while (usb_regs->gr->GRSTCTL & GRSTCTL_CSRST) { + /* no operation */ + } + + /* wait for additional 3 PHY clocks */ + usb_udelay(3U); +} diff --git a/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/driver/Source/drv_usb_dev.c b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/driver/Source/drv_usb_dev.c new file mode 100644 index 0000000000..22be493ad7 --- /dev/null +++ b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/driver/Source/drv_usb_dev.c @@ -0,0 +1,610 @@ +/*! + \file drv_usb_dev.c + \brief USB device mode low level driver + + \version 2020-08-01, V3.0.0, firmware for GD32F30x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "drv_usb_hw.h" +#include "drv_usb_core.h" +#include "drv_usb_dev.h" + +/* endpoint 0 max packet length */ +static const uint8_t EP0_MAXLEN[4] = { + [DSTAT_EM_HS_PHY_30MHZ_60MHZ] = EP0MPL_64, + [DSTAT_EM_FS_PHY_30MHZ_60MHZ] = EP0MPL_64, + [DSTAT_EM_FS_PHY_48MHZ] = EP0MPL_64, + [DSTAT_EM_LS_PHY_6MHZ] = EP0MPL_8 +}; + +#ifdef USB_FS_CORE + +/* USB endpoint Tx FIFO size */ +static uint16_t USBFS_TX_FIFO_SIZE[USBFS_MAX_EP_COUNT] = +{ + (uint16_t)TX0_FIFO_FS_SIZE, + (uint16_t)TX1_FIFO_FS_SIZE, + (uint16_t)TX2_FIFO_FS_SIZE, + (uint16_t)TX3_FIFO_FS_SIZE +}; + +#endif /* USBFS_CORE */ + +/*! + \brief initialize USB core registers for device mode + \param[in] udev: pointer to USB device + \param[out] none + \retval operation status +*/ +usb_status usb_devcore_init (usb_core_driver *udev) +{ + uint8_t i; + + /* restart the PHY clock (maybe don't need to...) */ + *udev->regs.PWRCLKCTL = 0U; + + /* config periodic frame interval to default value */ + udev->regs.dr->DCFG &= ~DCFG_EOPFT; + udev->regs.dr->DCFG |= FRAME_INTERVAL_80; + + udev->regs.dr->DCFG &= ~DCFG_DS; + +#ifdef USB_FS_CORE + if (udev->bp.core_enum == (uint8_t)USB_CORE_ENUM_FS) { + /* set full-speed PHY */ + udev->regs.dr->DCFG |= USB_SPEED_INP_FULL; + + /* set Rx FIFO size */ + usb_set_rxfifo(&udev->regs, RX_FIFO_FS_SIZE); + + /* set endpoint 0 to 3's Tx FIFO length and RAM address */ + for (i = 0U; i < USBFS_MAX_EP_COUNT; i++) { + usb_set_txfifo(&udev->regs, i, USBFS_TX_FIFO_SIZE[i]); + } + } +#endif /* USB_FS_CORE */ + + /* make sure all FIFOs are flushed */ + + /* flush all Tx FIFOs */ + (void)usb_txfifo_flush (&udev->regs, 0x10U); + + /* flush entire Rx FIFO */ + (void)usb_rxfifo_flush (&udev->regs); + + /* clear all pending device interrupts */ + udev->regs.dr->DIEPINTEN = 0U; + udev->regs.dr->DOEPINTEN = 0U; + udev->regs.dr->DAEPINT = 0xFFFFFFFFU; + udev->regs.dr->DAEPINTEN = 0U; + + /* configure all IN/OUT endpoints */ + for (i = 0U; i < udev->bp.num_ep; i++) { + if (udev->regs.er_in[i]->DIEPCTL & DEPCTL_EPEN) { + udev->regs.er_in[i]->DIEPCTL |= DEPCTL_EPD | DEPCTL_SNAK; + } else { + udev->regs.er_in[i]->DIEPCTL = 0U; + } + + /* set IN endpoint transfer length to 0 */ + udev->regs.er_in[i]->DIEPLEN = 0U; + + /* clear all pending IN endpoint interrupts */ + udev->regs.er_in[i]->DIEPINTF = 0xFFU; + + if (udev->regs.er_out[i]->DOEPCTL & DEPCTL_EPEN) { + udev->regs.er_out[i]->DOEPCTL |= DEPCTL_EPD | DEPCTL_SNAK; + } else { + udev->regs.er_out[i]->DOEPCTL = 0U; + } + + /* set OUT endpoint transfer length to 0 */ + udev->regs.er_out[i]->DOEPLEN = 0U; + + /* clear all pending OUT endpoint interrupts */ + udev->regs.er_out[i]->DOEPINTF = 0xFFU; + } + + udev->regs.dr->DIEPINTEN |= DIEPINTEN_EPTXFUDEN; + + (void)usb_devint_enable (udev); + + return USB_OK; +} + +/*! + \brief enable the USB device mode interrupts + \param[in] udev: pointer to USB device + \param[out] none + \retval operation status +*/ +usb_status usb_devint_enable (usb_core_driver *udev) +{ + /* clear any pending USB OTG interrupts */ + udev->regs.gr->GOTGINTF = 0xFFFFFFFFU; + + /* clear any pending interrupts */ + udev->regs.gr->GINTF = 0xBFFFFFFFU; + + /* enable the USB wakeup and suspend interrupts */ + udev->regs.gr->GINTEN = GINTEN_WKUPIE | GINTEN_SPIE; + + /* enable device_mode-related interrupts */ + if ((uint8_t)USB_USE_FIFO == udev->bp.transfer_mode) { + udev->regs.gr->GINTEN |= GINTEN_RXFNEIE; + } + + udev->regs.gr->GINTEN |= GINTEN_RSTIE | GINTEN_ENUMFIE | GINTEN_IEPIE |\ + GINTEN_OEPIE | GINTEN_SOFIE | GINTEN_ISOONCIE | GINTEN_ISOINCIE; + +#ifdef VBUS_SENSING_ENABLED + udev->regs.gr->GINTEN |= GINTEN_SESIE | GINTEN_OTGIE; +#endif /* VBUS_SENSING_ENABLED */ + + return USB_OK; +} + +/*! + \brief active the USB endpoint0 transaction + \param[in] udev: pointer to USB device + \param[in] transc: the USB endpoint0 transaction + \param[out] none + \retval operation status +*/ +usb_status usb_transc0_active (usb_core_driver *udev, usb_transc *transc) +{ + __IO uint32_t *reg_addr = NULL; + + /* get the endpoint number */ + uint8_t ep_num = transc->ep_addr.num; + + if (ep_num) { + /* not endpoint 0 */ + return USB_FAIL; + } + + if (transc->ep_addr.dir) { + reg_addr = &udev->regs.er_in[0]->DIEPCTL; + } else { + reg_addr = &udev->regs.er_out[0]->DOEPCTL; + } + + /* endpoint 0 is activated after USB clock is enabled */ + + *reg_addr &= ~(DEPCTL_MPL | DEPCTL_EPTYPE | DIEPCTL_TXFNUM); + + /* set endpoint 0 maximum packet length */ + *reg_addr |= EP0_MAXLEN[udev->regs.dr->DSTAT & DSTAT_ES]; + + /* activate endpoint */ + *reg_addr |= ((uint32_t)transc->ep_type << 18U) | ((uint32_t)ep_num << 22U) | DEPCTL_SD0PID | DEPCTL_EPACT; + + return USB_OK; +} + +/*! + \brief active the USB transaction + \param[in] udev: pointer to USB device + \param[in] transc: the USB transaction + \param[out] none + \retval status +*/ +usb_status usb_transc_active (usb_core_driver *udev, usb_transc *transc) +{ + __IO uint32_t *reg_addr = NULL; + __IO uint32_t epinten = 0U; + + /* get the endpoint number */ + uint8_t ep_num = transc->ep_addr.num; + + /* enable endpoint interrupt number */ + if (transc->ep_addr.dir) { + reg_addr = &udev->regs.er_in[ep_num]->DIEPCTL; + + epinten = 1U << ep_num; + } else { + reg_addr = &udev->regs.er_out[ep_num]->DOEPCTL; + + epinten = 1U << (16U + ep_num); + } + + /* if the endpoint is not active, need change the endpoint control register */ + if (!(*reg_addr & DEPCTL_EPACT)) { + *reg_addr &= ~(DEPCTL_MPL | DEPCTL_EPTYPE | DIEPCTL_TXFNUM); + + /* set endpoint maximum packet length */ + if (0U == ep_num) { + *reg_addr |= EP0_MAXLEN[udev->regs.dr->DSTAT & DSTAT_ES]; + } else { + *reg_addr |= transc->max_len; + } + + /* activate endpoint */ + *reg_addr |= ((uint32_t)transc->ep_type << 18U) | ((uint32_t)ep_num << 22U) | DEPCTL_SD0PID | DEPCTL_EPACT; + } + + + /* enable the interrupts for this endpoint */ + udev->regs.dr->DAEPINTEN |= epinten; + + return USB_OK; +} + +/*! + \brief deactivate the USB transaction + \param[in] udev: pointer to USB device + \param[in] transc: the USB transaction + \param[out] none + \retval status +*/ +usb_status usb_transc_deactivate(usb_core_driver *udev, usb_transc *transc) +{ + uint32_t epinten = 0U; + + uint8_t ep_num = transc->ep_addr.num; + + /* disable endpoint interrupt number */ + if (transc->ep_addr.dir) { + epinten = 1U << ep_num; + + udev->regs.er_in[ep_num]->DIEPCTL &= ~DEPCTL_EPACT; + } else { + epinten = 1U << (ep_num + 16U); + + udev->regs.er_out[ep_num]->DOEPCTL &= ~DEPCTL_EPACT; + } + + + /* disable the interrupts for this endpoint */ + udev->regs.dr->DAEPINTEN &= ~epinten; + + return USB_OK; +} + +/*! + \brief configure USB transaction to start IN transfer + \param[in] udev: pointer to USB device + \param[in] transc: the USB IN transaction + \param[out] none + \retval operation status +*/ +usb_status usb_transc_inxfer (usb_core_driver *udev, usb_transc *transc) +{ + usb_status status = USB_OK; + + uint8_t ep_num = transc->ep_addr.num; + + __IO uint32_t epctl = udev->regs.er_in[ep_num]->DIEPCTL; + __IO uint32_t eplen = udev->regs.er_in[ep_num]->DIEPLEN; + + eplen &= ~(DEPLEN_TLEN | DEPLEN_PCNT); + + /* zero length packet or endpoint 0 */ + if (0U == transc->xfer_len) { + /* set transfer packet count to 1 */ + eplen |= 1U << 19U; + } else { + /* set transfer packet count */ + if (0U == ep_num) { + transc->xfer_len = USB_MIN(transc->xfer_len, transc->max_len); + + eplen |= 1U << 19U; + } else { + eplen |= (((transc->xfer_len - 1U) + transc->max_len) / transc->max_len) << 19U; + } + + /* set endpoint transfer length */ + eplen |= transc->xfer_len; + + if (transc->ep_type == (uint8_t)USB_EPTYPE_ISOC) { + eplen |= DIEPLEN_MCNT & (1U << 29U); + } + } + + udev->regs.er_in[ep_num]->DIEPLEN = eplen; + + if (transc->ep_type == (uint8_t)USB_EPTYPE_ISOC) { + if (((udev->regs.dr->DSTAT & DSTAT_FNRSOF) >> 8U) & 0x01U) { + epctl |= DEPCTL_SEVNFRM; + } else { + epctl |= DEPCTL_SODDFRM; + } + } + + if ((uint8_t)USB_USE_DMA == udev->bp.transfer_mode) { + udev->regs.er_in[ep_num]->DIEPDMAADDR = transc->dma_addr; + } + + /* enable the endpoint and clear the NAK */ + epctl |= DEPCTL_CNAK | DEPCTL_EPEN; + + udev->regs.er_in[ep_num]->DIEPCTL = epctl; + + if ((uint8_t)USB_USE_FIFO == udev->bp.transfer_mode) { + if (transc->ep_type != (uint8_t)USB_EPTYPE_ISOC) { + /* enable the Tx FIFO empty interrupt for this endpoint */ + if (transc->xfer_len > 0U) { + udev->regs.dr->DIEPFEINTEN |= 1U << ep_num; + } + } else { + (void)usb_txfifo_write (&udev->regs, transc->xfer_buf, ep_num, (uint16_t)transc->xfer_len); + } + } + + return status; +} + +/*! + \brief configure usb transaction to start OUT transfer + \param[in] udev: pointer to usb device + \param[in] transc: the usb OUT transaction + \param[out] none + \retval status +*/ +usb_status usb_transc_outxfer (usb_core_driver *udev, usb_transc *transc) +{ + usb_status status = USB_OK; + + uint8_t ep_num = transc->ep_addr.num; + + uint32_t epctl = udev->regs.er_out[ep_num]->DOEPCTL; + uint32_t eplen = udev->regs.er_out[ep_num]->DOEPLEN; + + eplen &= ~(DEPLEN_TLEN | DEPLEN_PCNT); + + /* zero length packet or endpoint 0 */ + if ((0U == transc->xfer_len) || (0U == ep_num)) { + /* set the transfer length to max packet size */ + eplen |= transc->max_len; + + /* set the transfer packet count to 1 */ + eplen |= 1U << 19U; + } else { + /* configure the transfer size and packet count as follows: + * pktcnt = N + * xfersize = N * maxpacket + */ + uint32_t packet_count = (transc->xfer_len + transc->max_len - 1U) / transc->max_len; + + eplen |= packet_count << 19U; + eplen |= packet_count * transc->max_len; + } + + udev->regs.er_out[ep_num]->DOEPLEN = eplen; + + if ((uint8_t)USB_USE_DMA == udev->bp.transfer_mode) { + udev->regs.er_out[ep_num]->DOEPDMAADDR = transc->dma_addr; + } + + if (transc->ep_type == (uint8_t)USB_EPTYPE_ISOC) { + if (transc->frame_num) { + epctl |= DEPCTL_SD1PID; + } else { + epctl |= DEPCTL_SD0PID; + } + } + + /* enable the endpoint and clear the NAK */ + epctl |= DEPCTL_EPEN | DEPCTL_CNAK; + + udev->regs.er_out[ep_num]->DOEPCTL = epctl; + + return status; +} + +/*! + \brief set the USB transaction STALL status + \param[in] udev: pointer to USB device + \param[in] transc: the USB transaction + \param[out] none + \retval status +*/ +usb_status usb_transc_stall (usb_core_driver *udev, usb_transc *transc) +{ + __IO uint32_t *reg_addr = NULL; + + uint8_t ep_num = transc->ep_addr.num; + + if (transc->ep_addr.dir) { + reg_addr = &(udev->regs.er_in[ep_num]->DIEPCTL); + + /* set the endpoint disable bit */ + if (*reg_addr & DEPCTL_EPEN) { + *reg_addr |= DEPCTL_EPD; + } + } else { + /* set the endpoint stall bit */ + reg_addr = &(udev->regs.er_out[ep_num]->DOEPCTL); + } + + /* set the endpoint stall bit */ + *reg_addr |= DEPCTL_STALL; + + return USB_OK; +} + +/*! + \brief clear the USB transaction STALL status + \param[in] udev: pointer to USB device + \param[in] transc: the USB transaction + \param[out] none + \retval operation status +*/ +usb_status usb_transc_clrstall(usb_core_driver *udev, usb_transc *transc) +{ + __IO uint32_t *reg_addr = NULL; + + uint8_t ep_num = transc->ep_addr.num; + + if (transc->ep_addr.dir) { + reg_addr = &(udev->regs.er_in[ep_num]->DIEPCTL); + } else { + reg_addr = &(udev->regs.er_out[ep_num]->DOEPCTL); + } + + /* clear the endpoint stall bits */ + *reg_addr &= ~DEPCTL_STALL; + + /* reset data PID of the periodic endpoints */ + if ((transc->ep_type == (uint8_t)USB_EPTYPE_INTR) || (transc->ep_type == (uint8_t)USB_EPTYPE_BULK)) { + *reg_addr |= DEPCTL_SD0PID; + } + + return USB_OK; +} + +/*! + \brief read device IN endpoint interrupt flag register + \param[in] udev: pointer to USB device + \param[in] ep_num: endpoint number + \param[out] none + \retval interrupt value +*/ +uint32_t usb_iepintr_read (usb_core_driver *udev, uint8_t ep_num) +{ + uint32_t value = 0U, fifoemptymask, commonintmask; + + commonintmask = udev->regs.dr->DIEPINTEN; + fifoemptymask = udev->regs.dr->DIEPFEINTEN; + + /* check FIFO empty interrupt enable bit */ + commonintmask |= ((fifoemptymask >> ep_num) & 0x1U) << 7; + + value = udev->regs.er_in[ep_num]->DIEPINTF & commonintmask; + + return value; +} + +/*! + \brief configures OUT endpoint 0 to receive SETUP packets + \param[in] udev: pointer to USB device + \param[out] none + \retval none +*/ +void usb_ctlep_startout (usb_core_driver *udev) +{ + /* set OUT endpoint 0 receive length to 24 bytes, 1 packet and 3 setup packets */ + udev->regs.er_out[0]->DOEPLEN = DOEP0_TLEN(8U * 3U) | DOEP0_PCNT(1U) | DOEP0_STPCNT(3U); + + if ((uint8_t)USB_USE_DMA == udev->bp.transfer_mode) { + udev->regs.er_out[0]->DOEPDMAADDR = (uint32_t)&udev->dev.control.req; + + /* endpoint enable */ + udev->regs.er_out[0]->DOEPCTL |= DEPCTL_EPACT | DEPCTL_EPEN; + } +} + +/*! + \brief active remote wakeup signaling + \param[in] udev: pointer to USB device + \param[out] none + \retval none +*/ +void usb_rwkup_active (usb_core_driver *udev) +{ + if (udev->dev.pm.dev_remote_wakeup) { + if (udev->regs.dr->DSTAT & DSTAT_SPST) { + if (udev->bp.low_power) { + /* ungate USB core clock */ + *udev->regs.PWRCLKCTL &= ~(PWRCLKCTL_SHCLK | PWRCLKCTL_SUCLK); + } + + /* active remote wakeup signaling */ + udev->regs.dr->DCTL |= DCTL_RWKUP; + + usb_mdelay(5U); + + udev->regs.dr->DCTL &= ~DCTL_RWKUP; + } + } +} + +/*! + \brief active USB core clock + \param[in] udev: pointer to USB device + \param[out] none + \retval none +*/ +void usb_clock_active (usb_core_driver *udev) +{ + if (udev->bp.low_power) { + if (udev->regs.dr->DSTAT & DSTAT_SPST) { + /* un-gate USB Core clock */ + *udev->regs.PWRCLKCTL &= ~(PWRCLKCTL_SHCLK | PWRCLKCTL_SUCLK); + } + } +} + +/*! + \brief USB device suspend + \param[in] udev: pointer to USB device + \param[out] none + \retval none +*/ +void usb_dev_suspend (usb_core_driver *udev) +{ + __IO uint32_t devstat = udev->regs.dr->DSTAT; + + if ((udev->bp.low_power) && (devstat & DSTAT_SPST)) { + /* switch-off the USB clocks */ + *udev->regs.PWRCLKCTL |= PWRCLKCTL_SHCLK; + + /* enter DEEP_SLEEP mode with LDO in low power mode */ + pmu_to_deepsleepmode(PMU_LDO_LOWPOWER, WFI_CMD); + } +} + +/*! + \brief stop the device and clean up FIFOs + \param[in] udev: pointer to USB device + \param[out] none + \retval none +*/ +void usb_dev_stop (usb_core_driver *udev) +{ + uint32_t i; + + udev->dev.cur_status = 1U; + + /* clear all interrupt flag and enable bits */ + for (i = 0U; i < udev->bp.num_ep; i++) { + udev->regs.er_in[i]->DIEPINTF = 0xFFU; + udev->regs.er_out[i]->DOEPINTF = 0xFFU; + } + + udev->regs.dr->DIEPINTEN = 0U; + udev->regs.dr->DOEPINTEN = 0U; + udev->regs.dr->DAEPINTEN = 0U; + udev->regs.dr->DAEPINT = 0xFFFFFFFFU; + + /* flush the FIFO */ + (void)usb_rxfifo_flush (&udev->regs); + (void)usb_txfifo_flush (&udev->regs, 0x10U); +} diff --git a/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/driver/Source/drv_usb_host.c b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/driver/Source/drv_usb_host.c new file mode 100644 index 0000000000..95eac3758d --- /dev/null +++ b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/driver/Source/drv_usb_host.c @@ -0,0 +1,452 @@ +/*! + \file drv_usb_host.c + \brief USB host mode low level driver + + \version 2020-08-01, V3.0.0, firmware for GD32F30x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "drv_usb_hw.h" +#include "drv_usb_core.h" +#include "drv_usb_host.h" + +const uint32_t PIPE_DPID[2] = { + PIPE_DPID_DATA0, + PIPE_DPID_DATA1 +}; + +/*! + \brief initializes USB core for host mode + \param[in] pudev: pointer to selected usb host + \param[out] none + \retval operation status +*/ +usb_status usb_host_init (usb_core_driver *pudev) +{ + uint32_t i = 0U, inten = 0U; + + uint32_t nptxfifolen = 0U; + uint32_t ptxfifolen = 0U; + + /* restart the PHY Clock */ + *pudev->regs.PWRCLKCTL = 0U; + + /* support FS/LS only */ + pudev->regs.hr->HCTL &= ~HCTL_SPDFSLS; + + /* configure data FIFOs size */ +#ifdef USB_FS_CORE + if (USB_CORE_ENUM_FS == pudev->bp.core_enum) { + /* set Rx FIFO size */ + pudev->regs.gr->GRFLEN = USB_RX_FIFO_FS_SIZE; + + /* set non-periodic Tx FIFO size and address */ + nptxfifolen |= USB_RX_FIFO_FS_SIZE; + nptxfifolen |= USB_HTX_NPFIFO_FS_SIZE << 16U; + pudev->regs.gr->DIEP0TFLEN_HNPTFLEN = nptxfifolen; + + /* set periodic Tx FIFO size and address */ + ptxfifolen |= USB_RX_FIFO_FS_SIZE + USB_HTX_NPFIFO_FS_SIZE; + ptxfifolen |= USB_HTX_PFIFO_FS_SIZE << 16U; + pudev->regs.gr->HPTFLEN = ptxfifolen; + } +#endif /* USB_FS_CORE */ + +#ifdef USE_OTG_MODE + + /* clear host set hnp enable in the usb_otg control register */ + pudev->regs.gr->GOTGCS &= ~GOTGCS_HHNPEN; + +#endif /* USE_OTG_MODE */ + + /* make sure the FIFOs are flushed */ + + /* flush all Tx FIFOs in device or host mode */ + usb_txfifo_flush (&pudev->regs, 0x10U); + + /* flush the entire Rx FIFO */ + usb_rxfifo_flush (&pudev->regs); + + /* disable all interrupts */ + pudev->regs.gr->GINTEN = 0U; + + /* clear any pending USB OTG interrupts */ + pudev->regs.gr->GOTGINTF = 0xFFFFFFFFU; + + /* enable the USB wakeup and suspend interrupts */ + pudev->regs.gr->GINTF = 0xBFFFFFFFU; + + /* clear all pending host channel interrupts */ + for (i = 0U; i < pudev->bp.num_pipe; i++) { + pudev->regs.pr[i]->HCHINTF = 0xFFFFFFFFU; + pudev->regs.pr[i]->HCHINTEN = 0U; + } + +#ifndef USE_OTG_MODE + usb_portvbus_switch (pudev, 1U); +#endif /* USE_OTG_MODE */ + + pudev->regs.gr->GINTEN = GINTEN_WKUPIE | GINTEN_SPIE; + + /* enable host_mode-related interrupts */ + if (USB_USE_FIFO == pudev->bp.transfer_mode) { + inten = GINTEN_RXFNEIE; + } + + inten |= GINTEN_SESIE | GINTEN_HPIE | GINTEN_HCIE | GINTEN_ISOINCIE; + + pudev->regs.gr->GINTEN |= inten; + + inten = GINTEN_DISCIE | GINTEN_SOFIE; + + pudev->regs.gr->GINTEN &= ~inten; + + return USB_OK; +} + +/*! + \brief control the VBUS to power + \param[in] pudev: pointer to selected usb host + \param[in] state: VBUS state + \param[out] none + \retval none +*/ +void usb_portvbus_switch (usb_core_driver *pudev, uint8_t state) +{ + uint32_t port = 0U; + + /* enable or disable the external charge pump */ + usb_vbus_drive (state); + + /* turn on the host port power. */ + port = usb_port_read (pudev); + + if (!(port & HPCS_PP) && (1U == state)) { + port |= HPCS_PP; + } + + if ((port & HPCS_PP) && (0U == state)) { + port &= ~HPCS_PP; + } + + *pudev->regs.HPCS = port; + + usb_mdelay (200U); +} + +/*! + \brief reset host port + \param[in] pudev: pointer to usb device + \param[out] none + \retval operation status +*/ +uint32_t usb_port_reset (usb_core_driver *pudev) +{ + __IO uint32_t port = usb_port_read (pudev); + + *pudev->regs.HPCS = port | HPCS_PRST; + + usb_mdelay(20U); /* see note */ + + *pudev->regs.HPCS = port & ~HPCS_PRST; + + usb_mdelay(20U); + + return 1U; +} + +/*! + \brief initialize host pipe + \param[in] pudev: pointer to usb device + \param[in] pipe_num: host pipe number which is in (0..7) + \param[out] none + \retval operation status +*/ +usb_status usb_pipe_init (usb_core_driver *pudev, uint8_t pipe_num) +{ + usb_status status = USB_OK; + + __IO uint32_t pp_ctl = 0U; + __IO uint32_t pp_inten = HCHINTEN_TFIE; + + usb_pipe *pp = &pudev->host.pipe[pipe_num]; + + /* clear old interrupt conditions for this host channel */ + pudev->regs.pr[pipe_num]->HCHINTF = 0xFFFFFFFFU; + + if (USB_USE_DMA == pudev->bp.transfer_mode) { + pp_inten |= HCHINTEN_DMAERIE; + } + + if (pp->ep.dir) { + pp_inten |= HCHINTEN_BBERIE; + } + + /* enable channel interrupts required for this transfer */ + switch (pp->ep.type) { + case USB_EPTYPE_CTRL: + case USB_EPTYPE_BULK: + pp_inten |= HCHINTEN_STALLIE | HCHINTEN_USBERIE \ + | HCHINTEN_DTERIE | HCHINTEN_NAKIE; + + if (!pp->ep.dir) { + pp_inten |= HCHINTEN_NYETIE; + + if (pp->ping) { + pp_inten |= HCHINTEN_ACKIE; + } + } + break; + + case USB_EPTYPE_INTR: + pp_inten |= HCHINTEN_STALLIE | HCHINTEN_USBERIE | HCHINTEN_DTERIE \ + | HCHINTEN_NAKIE | HCHINTEN_REQOVRIE; + break; + + case USB_EPTYPE_ISOC: + pp_inten |= HCHINTEN_REQOVRIE | HCHINTEN_ACKIE; + + if (pp->ep.dir) { + pp_inten |= HCHINTEN_USBERIE; + } + break; + + default: + break; + } + + pudev->regs.pr[pipe_num]->HCHINTEN = pp_inten; + + /* enable the top level host channel interrupt */ + pudev->regs.hr->HACHINTEN |= 1U << pipe_num; + + /* make sure host channel interrupts are enabled */ + pudev->regs.gr->GINTEN |= GINTEN_HCIE; + + /* program the host channel control register */ + pp_ctl |= PIPE_CTL_DAR(pp->dev_addr); + pp_ctl |= PIPE_CTL_EPNUM(pp->ep.num); + pp_ctl |= PIPE_CTL_EPDIR(pp->ep.dir); + pp_ctl |= PIPE_CTL_EPTYPE(pp->ep.type); + pp_ctl |= PIPE_CTL_LSD(pp->dev_speed == PORT_SPEED_LOW); + + pp_ctl |= pp->ep.mps; + pp_ctl |= ((uint32_t)(pp->ep.type == USB_EPTYPE_INTR) << 29U) & HCHCTL_ODDFRM; + + pudev->regs.pr[pipe_num]->HCHCTL = pp_ctl; + + return status; +} + +/*! + \brief prepare host channel for transferring packets + \param[in] pudev: pointer to usb device + \param[in] pipe_num: host pipe number which is in (0..7) + \param[out] none + \retval operation status +*/ +usb_status usb_pipe_xfer (usb_core_driver *pudev, uint8_t pipe_num) +{ + usb_status status = USB_OK; + + uint16_t dword_len = 0U; + uint16_t packet_count = 0U; + + __IO uint32_t pp_ctl = 0U; + + usb_pipe *pp = &pudev->host.pipe[pipe_num]; + + uint16_t max_packet_len = pp->ep.mps; + + /* compute the expected number of packets associated to the transfer */ + if (pp->xfer_len > 0U) { + packet_count = (uint16_t)((pp->xfer_len + max_packet_len - 1U) / max_packet_len); + + if (packet_count > HC_MAX_PACKET_COUNT) { + packet_count = HC_MAX_PACKET_COUNT; + pp->xfer_len = (uint16_t)(packet_count * max_packet_len); + } + } else { + packet_count = 1U; + } + + if (pp->ep.dir) { + pp->xfer_len = (uint16_t)(packet_count * max_packet_len); + } + + /* initialize the host channel transfer information */ + pudev->regs.pr[pipe_num]->HCHLEN = pp->xfer_len | pp->DPID | PIPE_XFER_PCNT(packet_count); + + if (USB_USE_DMA == pudev->bp.transfer_mode) { + pudev->regs.pr[pipe_num]->HCHDMAADDR = (unsigned int)pp->xfer_buf; + } + + pp_ctl = pudev->regs.pr[pipe_num]->HCHCTL; + + if (usb_frame_even(pudev)) { + pp_ctl |= HCHCTL_ODDFRM; + } else { + pp_ctl &= ~HCHCTL_ODDFRM; + } + + /* set host channel enabled */ + pp_ctl |= HCHCTL_CEN; + pp_ctl &= ~HCHCTL_CDIS; + + pudev->regs.pr[pipe_num]->HCHCTL = pp_ctl; + + if (USB_USE_FIFO == pudev->bp.transfer_mode) { + if ((0U == pp->ep.dir) && (pp->xfer_len > 0U)) { + switch (pp->ep.type) { + /* non-periodic transfer */ + case USB_EPTYPE_CTRL: + case USB_EPTYPE_BULK: + dword_len = (uint16_t)((pp->xfer_len + 3U) / 4U); + + /* check if there is enough space in fifo space */ + if (dword_len > (pudev->regs.gr->HNPTFQSTAT & HNPTFQSTAT_NPTXFS)) { + /* need to process data in nptxfempty interrupt */ + pudev->regs.gr->GINTEN |= GINTEN_NPTXFEIE; + } + break; + + /* periodic transfer */ + case USB_EPTYPE_INTR: + case USB_EPTYPE_ISOC: + dword_len = (uint16_t)((pp->xfer_len + 3U) / 4U); + + /* check if there is enough space in fifo space */ + if (dword_len > (pudev->regs.hr->HPTFQSTAT & HPTFQSTAT_PTXFS)) { + /* need to process data in ptxfempty interrupt */ + pudev->regs.gr->GINTEN |= GINTEN_PTXFEIE; + } + break; + + default: + break; + } + + /* write packet into the tx fifo. */ + usb_txfifo_write (&pudev->regs, pp->xfer_buf, pipe_num, (uint16_t)pp->xfer_len); + } + } + + return status; +} + +/*! + \brief halt pipe + \param[in] pudev: pointer to usb device + \param[in] pipe_num: host pipe number which is in (0..7) + \param[out] none + \retval operation status +*/ +usb_status usb_pipe_halt (usb_core_driver *pudev, uint8_t pipe_num) +{ + __IO uint32_t pp_ctl = pudev->regs.pr[pipe_num]->HCHCTL; + + uint8_t ep_type = (uint8_t)((pp_ctl & HCHCTL_EPTYPE) >> 18U); + + pp_ctl |= HCHCTL_CEN | HCHCTL_CDIS; + + switch (ep_type) { + case USB_EPTYPE_CTRL: + case USB_EPTYPE_BULK: + if (0U == (pudev->regs.gr->HNPTFQSTAT & HNPTFQSTAT_NPTXFS)) { + pp_ctl &= ~HCHCTL_CEN; + } + break; + + case USB_EPTYPE_INTR: + case USB_EPTYPE_ISOC: + if (0U == (pudev->regs.hr->HPTFQSTAT & HPTFQSTAT_PTXFS)) { + pp_ctl &= ~HCHCTL_CEN; + } + break; + + default: + break; + } + + pudev->regs.pr[pipe_num]->HCHCTL = pp_ctl; + + return USB_OK; +} + +/*! + \brief configure host pipe to do ping operation + \param[in] pudev: pointer to usb device + \param[in] pipe_num: host pipe number which is in (0..7) + \param[out] none + \retval operation status +*/ +usb_status usb_pipe_ping (usb_core_driver *pudev, uint8_t pipe_num) +{ + uint32_t pp_ctl = 0U; + + pudev->regs.pr[pipe_num]->HCHLEN = HCHLEN_PING | (HCHLEN_PCNT & (1U << 19U)); + + pp_ctl = pudev->regs.pr[pipe_num]->HCHCTL; + + pp_ctl |= HCHCTL_CEN; + pp_ctl &= ~HCHCTL_CDIS; + + pudev->regs.pr[pipe_num]->HCHCTL = pp_ctl; + + return USB_OK; +} + +/*! + \brief stop the USB host and clean up FIFO + \param[in] pudev: pointer to usb device + \param[out] none + \retval none +*/ +void usb_host_stop (usb_core_driver *pudev) +{ + uint32_t i; + __IO uint32_t pp_ctl = 0U; + + pudev->regs.hr->HACHINTEN = 0x0U; + pudev->regs.hr->HACHINT = 0xFFFFFFFFU; + + /* flush out any leftover queued requests. */ + for (i = 0U; i < pudev->bp.num_pipe; i++) { + pp_ctl = pudev->regs.pr[i]->HCHCTL; + + pp_ctl &= ~(HCHCTL_CEN | HCHCTL_EPDIR); + pp_ctl |= HCHCTL_CDIS; + + pudev->regs.pr[i]->HCHCTL = pp_ctl; + } + + /* flush the FIFO */ + usb_rxfifo_flush (&pudev->regs); + usb_txfifo_flush (&pudev->regs, 0x10U); +} diff --git a/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/driver/Source/drv_usbd_int.c b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/driver/Source/drv_usbd_int.c new file mode 100644 index 0000000000..f378dad4bc --- /dev/null +++ b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/driver/Source/drv_usbd_int.c @@ -0,0 +1,491 @@ +/*! + \file drv_usbd_int.c + \brief USB device mode interrupt routines + + \version 2020-08-01, V3.0.0, firmware for GD32F30x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "usbd_conf.h" +#include "drv_usbd_int.h" +#include "usbd_transc.h" + +/* local function prototypes ('static') */ +static uint32_t usbd_int_epout (usb_core_driver *udev); +static uint32_t usbd_int_epin (usb_core_driver *udev); +static uint32_t usbd_int_rxfifo (usb_core_driver *udev); +static uint32_t usbd_int_reset (usb_core_driver *udev); +static uint32_t usbd_int_enumfinish (usb_core_driver *udev); +static uint32_t usbd_int_suspend (usb_core_driver *udev); +static uint32_t usbd_emptytxfifo_write (usb_core_driver *udev, uint32_t ep_num); + +static const uint8_t USB_SPEED[4] = { + [DSTAT_EM_HS_PHY_30MHZ_60MHZ] = (uint8_t)USB_SPEED_HIGH, + [DSTAT_EM_FS_PHY_30MHZ_60MHZ] = (uint8_t)USB_SPEED_FULL, + [DSTAT_EM_FS_PHY_48MHZ] = (uint8_t)USB_SPEED_FULL, + [DSTAT_EM_LS_PHY_6MHZ] = (uint8_t)USB_SPEED_LOW +}; + +/*! + \brief USB device-mode interrupts global service routine handler + \param[in] udev: pointer to USB device instance + \param[out] none + \retval none +*/ +void usbd_isr (usb_core_driver *udev) +{ + if (HOST_MODE != (udev->regs.gr->GINTF & GINTF_COPM)) { + uint32_t intr = udev->regs.gr->GINTF & udev->regs.gr->GINTEN; + + /* there are no interrupts, avoid spurious interrupt */ + if (!intr) { + return; + } + + /* OUT endpoints interrupts */ + if (intr & GINTF_OEPIF) { + (void)usbd_int_epout (udev); + } + + /* IN endpoints interrupts */ + if (intr & GINTF_IEPIF) { + (void)usbd_int_epin (udev); + } + + /* suspend interrupt */ + if (intr & GINTF_SP) { + (void)usbd_int_suspend (udev); + } + + /* wakeup interrupt */ + if (intr & GINTF_WKUPIF) { + /* inform upper layer by the resume event */ + udev->dev.cur_status = USBD_CONFIGURED; + + /* clear interrupt */ + udev->regs.gr->GINTF = GINTF_WKUPIF; + } + + /* start of frame interrupt */ + if (intr & GINTF_SOF) { + if (udev->dev.class_core->SOF) { + (void)udev->dev.class_core->SOF(udev); + } + + /* clear interrupt */ + udev->regs.gr->GINTF = GINTF_SOF; + } + + /* receive FIFO not empty interrupt */ + if (intr & GINTF_RXFNEIF) { + (void)usbd_int_rxfifo (udev); + } + + /* USB reset interrupt */ + if (intr & GINTF_RST) { + (void)usbd_int_reset (udev); + } + + /* enumeration has been done interrupt */ + if (intr & GINTF_ENUMFIF) { + (void)usbd_int_enumfinish (udev); + } + + /* incomplete synchronization IN transfer interrupt*/ + if (intr & GINTF_ISOINCIF) { + if (NULL != udev->dev.class_core->incomplete_isoc_in) { + (void)udev->dev.class_core->incomplete_isoc_in(udev); + } + + /* Clear interrupt */ + udev->regs.gr->GINTF = GINTF_ISOINCIF; + } + + /* incomplete synchronization OUT transfer interrupt*/ + if (intr & GINTF_ISOONCIF) { + if (NULL != udev->dev.class_core->incomplete_isoc_out) { + (void)udev->dev.class_core->incomplete_isoc_out(udev); + } + + /* clear interrupt */ + udev->regs.gr->GINTF = GINTF_ISOONCIF; + } + +#ifdef VBUS_SENSING_ENABLED + + /* Session request interrupt */ + if (intr & GINTF_SESIF) { + udev->regs.gr->GINTF = GINTF_SESIF; + } + + /* OTG mode interrupt */ + if (intr & GINTF_OTGIF) { + if(udev->regs.gr->GOTGINTF & GOTGINTF_SESEND) { + + } + + /* Clear OTG interrupt */ + udev->regs.gr->GINTF = GINTF_OTGIF; + } +#endif /* VBUS_SENSING_ENABLED */ + } +} + +/*! + \brief indicates that an OUT endpoint has a pending interrupt + \param[in] udev: pointer to USB device instance + \param[out] none + \retval operation status +*/ +static uint32_t usbd_int_epout (usb_core_driver *udev) +{ + uint32_t epintnum = 0U; + uint8_t ep_num = 0U; + + for (epintnum = usb_oepintnum_read (udev); epintnum; epintnum >>= 1, ep_num++) { + if (epintnum & 0x01U) { + __IO uint32_t oepintr = usb_oepintr_read (udev, ep_num); + + /* transfer complete interrupt */ + if (oepintr & DOEPINTF_TF) { + /* clear the bit in DOEPINTF for this interrupt */ + udev->regs.er_out[ep_num]->DOEPINTF = DOEPINTF_TF; + + if ((uint8_t)USB_USE_DMA == udev->bp.transfer_mode) { + __IO uint32_t eplen = udev->regs.er_out[ep_num]->DOEPLEN; + + udev->dev.transc_out[ep_num].xfer_count = udev->dev.transc_out[ep_num].max_len - \ + (eplen & DEPLEN_TLEN); + } + + /* inform upper layer: data ready */ + (void)usbd_out_transc (udev, ep_num); + + if ((uint8_t)USB_USE_DMA == udev->bp.transfer_mode) { + if ((0U == ep_num) && ((uint8_t)USB_CTL_STATUS_OUT == udev->dev.control.ctl_state)) { + usb_ctlep_startout (udev); + } + } + } + + /* setup phase finished interrupt (control endpoints) */ + if (oepintr & DOEPINTF_STPF) { + /* inform the upper layer that a setup packet is available */ + (void)usbd_setup_transc (udev); + + udev->regs.er_out[ep_num]->DOEPINTF = DOEPINTF_STPF; + } + } + } + + return 1U; +} + +/*! + \brief indicates that an IN endpoint has a pending interrupt + \param[in] udev: pointer to USB device instance + \param[out] none + \retval operation status +*/ +static uint32_t usbd_int_epin (usb_core_driver *udev) +{ + uint32_t epintnum = 0U; + uint8_t ep_num = 0U; + + for (epintnum = usb_iepintnum_read (udev); epintnum; epintnum >>= 1, ep_num++) { + if (epintnum & 0x1U) { + __IO uint32_t iepintr = usb_iepintr_read (udev, ep_num); + + if (iepintr & DIEPINTF_TF) { + udev->regs.er_in[ep_num]->DIEPINTF = DIEPINTF_TF; + + /* data transmission is completed */ + (void)usbd_in_transc (udev, ep_num); + + if ((uint8_t)USB_USE_DMA == udev->bp.transfer_mode) { + if ((0U == ep_num) && ((uint8_t)USB_CTL_STATUS_IN == udev->dev.control.ctl_state)) { + usb_ctlep_startout (udev); + } + } + } + + if (iepintr & DIEPINTF_TXFE) { + usbd_emptytxfifo_write (udev, (uint32_t)ep_num); + + udev->regs.er_in[ep_num]->DIEPINTF = DIEPINTF_TXFE; + } + } + } + + return 1U; +} + +/*! + \brief handle the RX status queue level interrupt + \param[in] udev: pointer to USB device instance + \param[out] none + \retval operation status +*/ +static uint32_t usbd_int_rxfifo (usb_core_driver *udev) +{ + usb_transc *transc = NULL; + + uint8_t data_PID = 0U; + uint32_t bcount = 0U; + + __IO uint32_t devrxstat = 0U; + + /* disable the Rx status queue non-empty interrupt */ + udev->regs.gr->GINTEN &= ~GINTEN_RXFNEIE; + + /* get the status from the top of the FIFO */ + devrxstat = udev->regs.gr->GRSTATP; + + uint8_t ep_num = (uint8_t)(devrxstat & GRSTATRP_EPNUM); + + transc = &udev->dev.transc_out[ep_num]; + + bcount = (devrxstat & GRSTATRP_BCOUNT) >> 4U; + data_PID = (uint8_t)((devrxstat & GRSTATRP_DPID) >> 15U); + + switch ((devrxstat & GRSTATRP_RPCKST) >> 17U) { + case RSTAT_GOUT_NAK: + break; + + case RSTAT_DATA_UPDT: + if (bcount > 0U) { + (void)usb_rxfifo_read (&udev->regs, transc->xfer_buf, (uint16_t)bcount); + + transc->xfer_buf += bcount; + transc->xfer_count += bcount; + } + break; + + case RSTAT_XFER_COMP: + /* trigger the OUT endpoint interrupt */ + break; + + case RSTAT_SETUP_COMP: + /* trigger the OUT endpoint interrupt */ + break; + + case RSTAT_SETUP_UPDT: + if ((0U == transc->ep_addr.num) && (8U == bcount) && (DPID_DATA0 == data_PID)) { + /* copy the setup packet received in FIFO into the setup buffer in RAM */ + (void)usb_rxfifo_read (&udev->regs, (uint8_t *)&udev->dev.control.req, (uint16_t)bcount); + + transc->xfer_count += bcount; + } + break; + + default: + break; + } + + /* enable the Rx status queue level interrupt */ + udev->regs.gr->GINTEN |= GINTEN_RXFNEIE; + + return 1U; +} + +/*! + \brief handle USB reset interrupt + \param[in] udev: pointer to USB device instance + \param[out] none + \retval status +*/ +static uint32_t usbd_int_reset (usb_core_driver *udev) +{ + uint32_t i; + + /* clear the remote wakeup signaling */ + udev->regs.dr->DCTL &= ~DCTL_RWKUP; + + /* flush the Tx FIFO */ + (void)usb_txfifo_flush (&udev->regs, 0U); + + for (i = 0U; i < udev->bp.num_ep; i++) { + udev->regs.er_in[i]->DIEPINTF = 0xFFU; + udev->regs.er_out[i]->DOEPINTF = 0xFFU; + } + + /* clear all pending device endpoint interrupts */ + udev->regs.dr->DAEPINT = 0xFFFFFFFFU; + + /* enable endpoint 0 interrupts */ + udev->regs.dr->DAEPINTEN = 1U | (1U << 16U); + + /* enable OUT endpoint interrupts */ + udev->regs.dr->DOEPINTEN = DOEPINTEN_STPFEN | DOEPINTEN_TFEN; + + /* enable IN endpoint interrupts */ + udev->regs.dr->DIEPINTEN = DIEPINTEN_TFEN; + + /* reset device address */ + udev->regs.dr->DCFG &= ~DCFG_DAR; + + /* configure endpoint 0 to receive SETUP packets */ + usb_ctlep_startout (udev); + + /* clear USB reset interrupt */ + udev->regs.gr->GINTF = GINTF_RST; + + udev->dev.transc_out[0] = (usb_transc) { + .ep_type = USB_EPTYPE_CTRL, + .max_len = USB_FS_EP0_MAX_LEN + }; + + (void)usb_transc_active (udev, &udev->dev.transc_out[0]); + + udev->dev.transc_in[0] = (usb_transc) { + .ep_addr = { + .dir = 1U + }, + + .ep_type = USB_EPTYPE_CTRL, + .max_len = USB_FS_EP0_MAX_LEN + }; + + (void)usb_transc_active (udev, &udev->dev.transc_in[0]); + + /* upon reset call user call back */ + udev->dev.cur_status = (uint8_t)USBD_DEFAULT; + + return 1U; +} + +/*! + \brief handle USB speed enumeration finish interrupt + \param[in] udev: pointer to USB device instance + \param[out] none + \retval status +*/ +static uint32_t usbd_int_enumfinish (usb_core_driver *udev) +{ + uint8_t enum_speed = (uint8_t)((udev->regs.dr->DSTAT & DSTAT_ES) >> 1U); + + udev->regs.dr->DCTL &= ~DCTL_CGINAK; + udev->regs.dr->DCTL |= DCTL_CGINAK; + + udev->regs.gr->GUSBCS &= ~GUSBCS_UTT; + + /* set USB turn-around time based on device speed and PHY interface */ + if (USB_SPEED[enum_speed] == (uint8_t)USB_SPEED_HIGH) { + udev->bp.core_speed = (uint8_t)USB_SPEED_HIGH; + + udev->regs.gr->GUSBCS |= 0x09U << 10U; + } else { + udev->bp.core_speed = (uint8_t)USB_SPEED_FULL; + + udev->regs.gr->GUSBCS |= 0x05U << 10U; + } + + /* clear interrupt */ + udev->regs.gr->GINTF = GINTF_ENUMFIF; + + return 1U; +} + +/*! + \brief USB suspend interrupt handler + \param[in] udev: pointer to USB device instance + \param[out] none + \retval operation status +*/ +static uint32_t usbd_int_suspend (usb_core_driver *udev) +{ + __IO uint8_t low_power = udev->bp.low_power; + __IO uint8_t suspend = (uint8_t)(udev->regs.dr->DSTAT & DSTAT_SPST); + __IO uint8_t is_configured = (udev->dev.cur_status == (uint8_t)USBD_CONFIGURED)? 1U : 0U; + + udev->dev.backup_status = udev->dev.cur_status; + udev->dev.cur_status = (uint8_t)USBD_SUSPENDED; + + if (low_power && suspend && is_configured) { + /* switch-off the OTG clocks */ + *udev->regs.PWRCLKCTL |= PWRCLKCTL_SUCLK | PWRCLKCTL_SHCLK; + + /* enter DEEP_SLEEP mode with LDO in low power mode */ + pmu_to_deepsleepmode(PMU_LDO_LOWPOWER, WFI_CMD); + } + + /* clear interrupt */ + udev->regs.gr->GINTF = GINTF_SP; + + return 1U; +} + +/*! + \brief check FIFO for the next packet to be loaded + \param[in] udev: pointer to USB device instance + \param[in] ep_num: endpoint identifier which is in (0..3) + \param[out] none + \retval status +*/ +static uint32_t usbd_emptytxfifo_write (usb_core_driver *udev, uint32_t ep_num) +{ + uint32_t len; + uint32_t word_count; + + usb_transc *transc = &udev->dev.transc_in[ep_num]; + + len = transc->xfer_len - transc->xfer_count; + + /* get the data length to write */ + if (len > transc->max_len) { + len = transc->max_len; + } + + word_count = (len + 3U) / 4U; + + while (((udev->regs.er_in[ep_num]->DIEPTFSTAT & DIEPTFSTAT_IEPTFS) >= word_count) && \ + (transc->xfer_count < transc->xfer_len)) { + len = transc->xfer_len - transc->xfer_count; + + if (len > transc->max_len) { + len = transc->max_len; + } + + /* write FIFO in word(4bytes) */ + word_count = (len + 3U) / 4U; + + /* write the FIFO */ + (void)usb_txfifo_write (&udev->regs, transc->xfer_buf, (uint8_t)ep_num, (uint16_t)len); + + transc->xfer_buf += len; + transc->xfer_count += len; + + if (transc->xfer_count == transc->xfer_len) { + /* disable the device endpoint FIFO empty interrupt */ + udev->regs.dr->DIEPFEINTEN &= ~(0x01U << ep_num); + } + } + + return 1U; +} diff --git a/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/driver/Source/drv_usbh_int.c b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/driver/Source/drv_usbh_int.c new file mode 100644 index 0000000000..3dc8e37c42 --- /dev/null +++ b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/driver/Source/drv_usbh_int.c @@ -0,0 +1,622 @@ +/*! + \file drv_usbh_int.c + \brief USB host mode interrupt handler file + + \version 2020-08-01, V3.0.0, firmware for GD32F30x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "drv_usb_core.h" +#include "drv_usb_host.h" +#include "drv_usbh_int.h" +#include "usbh_core.h" + +#if defined (__CC_ARM) /*!< ARM compiler */ + #pragma O0 +#elif defined (__GNUC__) /*!< GNU compiler */ + #pragma GCC optimize ("O0") +#elif defined (__TASKING__) /*!< TASKING compiler */ + #pragma optimize=0 +#endif /* __CC_ARM */ + +/* local function prototypes ('static') */ +static uint32_t usbh_int_port (usb_core_driver *pudev); +static uint32_t usbh_int_pipe (usb_core_driver *pudev); +static uint32_t usbh_int_pipe_in (usb_core_driver *pudev, uint32_t pp_num); +static uint32_t usbh_int_pipe_out (usb_core_driver *pudev, uint32_t pp_num); +static uint32_t usbh_int_rxfifonoempty (usb_core_driver *pudev); +static uint32_t usbh_int_txfifoempty (usb_core_driver *pudev, usb_pipe_mode pp_mode); + +/*! + \brief handle global host interrupt + \param[in] pudev: pointer to USB core instance + \param[out] none + \retval operation status +*/ +uint32_t usbh_isr (usb_core_driver *pudev) +{ + uint32_t retval = 0U; + + __IO uint32_t intr = 0U; + + /* check if host mode */ + if (HOST_MODE == (pudev->regs.gr->GINTF & GINTF_COPM)) { + intr = usb_coreintr_get(&pudev->regs); + + if (!intr) { + return 0U; + } + + if (intr & GINTF_SOF) { + usbh_int_fop->SOF(pudev->host.data); + + /* clear interrupt */ + pudev->regs.gr->GINTF = GINTF_SOF; + } + + if (intr & GINTF_RXFNEIF) { + retval |= usbh_int_rxfifonoempty (pudev); + } + + if (intr & GINTF_NPTXFEIF) { + retval |= usbh_int_txfifoempty (pudev, PIPE_NON_PERIOD); + } + + if (intr & GINTF_PTXFEIF) { + retval |= usbh_int_txfifoempty (pudev, PIPE_PERIOD); + } + + if (intr & GINTF_HCIF) { + retval |= usbh_int_pipe (pudev); + } + + if (intr & GINTF_HPIF) { + retval |= usbh_int_port (pudev); + } + + if (intr & GINTF_DISCIF) { + usbh_int_fop->disconnect(pudev->host.data); + + /* clear interrupt */ + pudev->regs.gr->GINTF = GINTF_DISCIF; + } + + if (intr & GINTF_ISOONCIF) { + pudev->regs.pr[0]->HCHCTL |= HCHCTL_CEN | HCHCTL_CDIS; + + /* clear interrupt */ + pudev->regs.gr->GINTF = GINTF_ISOONCIF; + } + + if (intr & GINTF_SESIF) { + usb_portvbus_switch (pudev, 1U); + + pudev->regs.gr->GINTF = GINTF_SESIF; + } + + if (intr & GINTF_WKUPIF) { + /* clear interrupt */ + pudev->regs.gr->GINTF = GINTF_WKUPIF; + } + } + + return retval; +} + +/*! + \brief handle USB pipe halt + \param[in] pudev: pointer to USB core instance + \param[in] pp_num: pp_num: host channel number which is in (0..7) + \param[in] pp_int: pipe interrupt + \param[in] pp_status: pipe status + \param[out] none + \retval none +*/ +static inline void usb_pp_halt (usb_core_driver *pudev, + uint8_t pp_num, + uint32_t pp_int, + usb_pipe_staus pp_status) +{ + pudev->regs.pr[pp_num]->HCHINTEN |= HCHINTEN_CHIE; + + usb_pipe_halt(pudev, pp_num); + + pudev->regs.pr[pp_num]->HCHINTF = pp_int; + + pudev->host.pipe[pp_num].pp_status = pp_status; +} + +/*! + \brief handle the host port interrupt + \param[in] pudev: pointer to USB device instance + \param[out] none + \retval operation status +*/ +#if defined (__ICCARM__) /*!< IAR compiler */ + #pragma optimize = none +#endif /* __ICCARM */ +static uint32_t usbh_int_port (usb_core_driver *pudev) +{ + uint32_t retval = 0U; + + /* note: when the USB PHY use USB HS PHY, the flag is needed */ + uint8_t port_reset = 0U; + + __IO uint32_t port_state = *pudev->regs.HPCS; + + /* clear the interrupt bits in GINTSTS */ + port_state &= ~(HPCS_PE | HPCS_PCD | HPCS_PEDC); + + /* port connect detected */ + if (*pudev->regs.HPCS & HPCS_PCD) { + port_state |= HPCS_PCD; + + usbh_int_fop->connect(pudev->host.data); + + retval |= 1U; + } + + /* port enable changed */ + if (*pudev->regs.HPCS & HPCS_PEDC) { + port_state |= HPCS_PEDC; + + if (*pudev->regs.HPCS & HPCS_PE) { + uint32_t port_speed = usb_curspeed_get(pudev); + uint32_t clock_type = pudev->regs.hr->HCTL & HCTL_CLKSEL; + + pudev->host.connect_status = 1U; + + if (PORT_SPEED_LOW == port_speed) { + pudev->regs.hr->HFT = 6000U; + + if (HCTL_6MHZ != clock_type) { + if (USB_EMBEDDED_PHY == pudev->bp.phy_itf) { + usb_phyclock_config (pudev, HCTL_6MHZ); + } + + port_reset = 1U; + } + } else if (PORT_SPEED_FULL == port_speed) { + pudev->regs.hr->HFT = 48000U; + + if (HCTL_48MHZ != clock_type) { + usb_phyclock_config (pudev, HCTL_48MHZ); + } + + port_reset = 1U; + } else { + /* for high speed device and others */ + port_reset = 1U; + } + + usbh_int_fop->port_enabled(pudev->host.data); + + pudev->regs.gr->GINTEN |= GINTEN_DISCIE | GINTEN_SOFIE; + } else { + usbh_int_fop->port_disabled(pudev->host.data); + } + } + + if (port_reset) { + usb_port_reset(pudev); + } + + /* clear port interrupts */ + *pudev->regs.HPCS = port_state; + + return retval; +} + +/*! + \brief handle all host channels interrupt + \param[in] pudev: pointer to USB device instance + \param[out] none + \retval operation status +*/ +static uint32_t usbh_int_pipe (usb_core_driver *pudev) +{ + uint32_t pp_num = 0U; + uint32_t retval = 0U; + + for (pp_num = 0U; pp_num < pudev->bp.num_pipe; pp_num++) { + if ((pudev->regs.hr->HACHINT & HACHINT_HACHINT) & (1UL << pp_num)) { + if (pudev->regs.pr[pp_num]->HCHCTL & HCHCTL_EPDIR) { + retval |= usbh_int_pipe_in (pudev, pp_num); + } else { + retval |= usbh_int_pipe_out (pudev, pp_num); + } + } + } + + return retval; +} + +/*! + \brief handle the IN channel interrupt + \param[in] pudev: pointer to USB device instance + \param[in] pp_num: host channel number which is in (0..7) + \param[out] none + \retval operation status +*/ +#if defined (__ICCARM__) /*!< IAR compiler */ + #pragma optimize = none +#endif /* __ICCARM */ +static uint32_t usbh_int_pipe_in (usb_core_driver *pudev, uint32_t pp_num) +{ + usb_pr *pp_reg = pudev->regs.pr[pp_num]; + + usb_pipe *pp = &pudev->host.pipe[pp_num]; + + __IO uint32_t intr_pp = pp_reg->HCHINTF & pp_reg->HCHINTEN; + + uint8_t ep_type = (uint8_t)((pp_reg->HCHCTL & HCHCTL_EPTYPE) >> 18U); + + if (intr_pp & HCHINTF_ACK) { + pp_reg->HCHINTF = HCHINTF_ACK; + } else if (intr_pp & HCHINTF_STALL) { + usb_pp_halt (pudev, (uint8_t)pp_num, HCHINTF_STALL, PIPE_STALL); + pp_reg->HCHINTF = HCHINTF_NAK; + + /* note: When there is a 'STALL', reset also NAK, + else, the pudev->host.pp_status = HC_STALL + will be overwritten by 'NAK' in code below */ + intr_pp &= ~HCHINTF_NAK; + } else if (intr_pp & HCHINTF_DTER) { + usb_pp_halt (pudev, (uint8_t)pp_num, HCHINTF_DTER, PIPE_DTGERR); + pp_reg->HCHINTF = HCHINTF_NAK; + } else { + /* no operation */ + } + + if (intr_pp & HCHINTF_REQOVR) { + usb_pp_halt (pudev, (uint8_t)pp_num, HCHINTF_REQOVR, PIPE_REQOVR); + } else if (intr_pp & HCHINTF_TF) { + if ((uint8_t)USB_USE_DMA == pudev->bp.transfer_mode) { + pudev->host.backup_xfercount[pp_num] = pp->xfer_len - (pp_reg->HCHLEN & HCHLEN_TLEN); + } + + pp->pp_status = PIPE_XF; + pp->err_count = 0U; + + pp_reg->HCHINTF = HCHINTF_TF; + + switch (ep_type) { + case USB_EPTYPE_CTRL: + case USB_EPTYPE_BULK: + usb_pp_halt (pudev, (uint8_t)pp_num, HCHINTF_NAK, PIPE_XF); + + pp->data_toggle_in ^= 1U; + break; + + case USB_EPTYPE_INTR: + case USB_EPTYPE_ISOC: + pp_reg->HCHCTL |= HCHCTL_ODDFRM; + pp->urb_state = URB_DONE; + break; + + default: + break; + } + } else if (intr_pp & HCHINTF_CH) { + pp_reg->HCHINTEN &= ~HCHINTEN_CHIE; + + switch (pp->pp_status) { + case PIPE_XF: + pp->urb_state = URB_DONE; + break; + + case PIPE_STALL: + pp->urb_state = URB_STALL; + break; + + case PIPE_TRACERR: + case PIPE_DTGERR: + pp->err_count = 0U; + pp->urb_state = URB_ERROR; + + pp->data_toggle_in ^= 1U; + break; + + case PIPE_IDLE: + case PIPE_HALTED: + case PIPE_NAK: + case PIPE_NYET: + case PIPE_BBERR: + case PIPE_REQOVR: + default: + if((uint8_t)USB_EPTYPE_INTR == ep_type) { + pp->data_toggle_in ^= 1U; + } + break; + } + + pp_reg->HCHINTF = HCHINTF_CH; + } else if (intr_pp & HCHINTF_USBER) { + pp->err_count++; + usb_pp_halt (pudev, (uint8_t)pp_num, HCHINTF_USBER, PIPE_TRACERR); + } else if (intr_pp & HCHINTF_NAK) { + switch (ep_type) { + case USB_EPTYPE_CTRL: + case USB_EPTYPE_BULK: + /* re-activate the channel */ + pp_reg->HCHCTL = (pp_reg->HCHCTL | HCHCTL_CEN) & ~HCHCTL_CDIS; + break; + + case USB_EPTYPE_INTR: + pp_reg->HCHINTEN |= HCHINTEN_CHIE; + + (void)usb_pipe_halt(pudev, (uint8_t)pp_num); + break; + + default: + break; + } + + pp->pp_status = PIPE_NAK; + + pp_reg->HCHINTF = HCHINTF_NAK; + } else { + /* no operation */ + } + + return 1U; +} + +/*! + \brief handle the OUT channel interrupt + \param[in] pudev: pointer to USB device instance + \param[in] pp_num: host channel number which is in (0..7) + \param[out] none + \retval operation status +*/ +#if defined (__ICCARM__) /*!< IAR compiler */ + #pragma optimize = none +#endif /* __ICCARM */ +static uint32_t usbh_int_pipe_out (usb_core_driver *pudev, uint32_t pp_num) +{ + usb_pr *pp_reg = pudev->regs.pr[pp_num]; + + usb_pipe *pp = &pudev->host.pipe[pp_num]; + + uint32_t intr_pp = pp_reg->HCHINTF & pp_reg->HCHINTEN; + + if (intr_pp & HCHINTF_ACK) { + if (URB_PING == pp->urb_state) { + pp->err_count = 0U; + usb_pp_halt (pudev, (uint8_t)pp_num, HCHINTF_TF, PIPE_XF); + } + + pp_reg->HCHINTF = HCHINTF_ACK; + } else if (intr_pp & HCHINTF_STALL) { + usb_pp_halt (pudev, (uint8_t)pp_num, HCHINTF_STALL, PIPE_STALL); + } else if (intr_pp & HCHINTF_DTER) { + usb_pp_halt (pudev, (uint8_t)pp_num, HCHINTF_DTER, PIPE_DTGERR); + pp_reg->HCHINTF = HCHINTF_NAK; + } else if (intr_pp & HCHINTF_REQOVR) { + usb_pp_halt (pudev, (uint8_t)pp_num, HCHINTF_REQOVR, PIPE_REQOVR); + } else if (intr_pp & HCHINTF_TF) { + pp->err_count = 0U; + usb_pp_halt (pudev, (uint8_t)pp_num, HCHINTF_TF, PIPE_XF); + } else if (intr_pp & HCHINTF_NAK) { + pp->err_count = 0U; + usb_pp_halt (pudev, (uint8_t)pp_num, HCHINTF_NAK, PIPE_NAK); + } else if (intr_pp & HCHINTF_USBER) { + pp->err_count++; + usb_pp_halt (pudev, (uint8_t)pp_num, HCHINTF_USBER, PIPE_TRACERR); + } else if (intr_pp & HCHINTF_NYET) { + pp->err_count = 0U; + usb_pp_halt (pudev, (uint8_t)pp_num, HCHINTF_NYET, PIPE_NYET); + } else if (intr_pp & HCHINTF_CH) { + pudev->regs.pr[pp_num]->HCHINTEN &= ~HCHINTEN_CHIE; + + switch (pp->pp_status) { + case PIPE_XF: + pp->urb_state = URB_DONE; + + if ((uint8_t)USB_EPTYPE_BULK == ((pp_reg->HCHCTL & HCHCTL_EPTYPE) >> 18U)) { + pp->data_toggle_out ^= 1U; + } + break; + + case PIPE_NAK: + + if (URB_PING == pp->urb_state) { + (void)usb_pipe_ping (pudev, (uint8_t)pp_num); + } else { + pp->urb_state = URB_NOTREADY; + } + break; + + case PIPE_NYET: + if (1U == pudev->host.pipe[pp_num].ping) { + (void)usb_pipe_ping (pudev, (uint8_t)pp_num); + pp->urb_state = URB_PING; + } + else { + pp->urb_state = URB_NOTREADY; + } + break; + + case PIPE_STALL: + pp->urb_state = URB_STALL; + break; + + case PIPE_TRACERR: + if (3U == pp->err_count) { + pp->urb_state = URB_ERROR; + pp->err_count = 0U; + } + break; + + case PIPE_IDLE: + case PIPE_HALTED: + case PIPE_BBERR: + case PIPE_REQOVR: + case PIPE_DTGERR: + default: + break; + } + + pp_reg->HCHINTF = HCHINTF_CH; + } else { + /* no operation */ + } + + return 1U; +} + +/*! + \brief handle the RX FIFO non-empty interrupt + \param[in] pudev: pointer to USB device instance + \param[out] none + \retval operation status +*/ +#if defined (__ICCARM__) /*!< IAR compiler */ + #pragma optimize = none +#endif /* __ICCARM */ +static uint32_t usbh_int_rxfifonoempty (usb_core_driver *pudev) +{ + uint32_t count = 0U; + + __IO uint8_t pp_num = 0U; + __IO uint32_t rx_stat = 0U; + + /* disable the RX status queue level interrupt */ + pudev->regs.gr->GINTEN &= ~GINTEN_RXFNEIE; + + rx_stat = pudev->regs.gr->GRSTATP; + pp_num = (uint8_t)(rx_stat & GRSTATRP_CNUM); + + switch ((rx_stat & GRSTATRP_RPCKST) >> 17U) { + case GRXSTS_PKTSTS_IN: + count = (rx_stat & GRSTATRP_BCOUNT) >> 4U; + + /* read the data into the host buffer. */ + if ((count > 0U) && (NULL != pudev->host.pipe[pp_num].xfer_buf)) { + (void)usb_rxfifo_read (&pudev->regs, pudev->host.pipe[pp_num].xfer_buf, (uint16_t)count); + + /* manage multiple transfer packet */ + pudev->host.pipe[pp_num].xfer_buf += count; + pudev->host.pipe[pp_num].xfer_count += count; + + pudev->host.backup_xfercount[pp_num] = pudev->host.pipe[pp_num].xfer_count; + + if (pudev->regs.pr[pp_num]->HCHLEN & HCHLEN_PCNT) { + /* re-activate the channel when more packets are expected */ + __IO uint32_t pp_ctl = pudev->regs.pr[pp_num]->HCHCTL; + + pp_ctl |= HCHCTL_CEN; + pp_ctl &= ~HCHCTL_CDIS; + + pudev->regs.pr[pp_num]->HCHCTL = pp_ctl; + } + } + break; + + case GRXSTS_PKTSTS_IN_XFER_COMP: + break; + + case GRXSTS_PKTSTS_DATA_TOGGLE_ERR: + count = (rx_stat & GRSTATRP_BCOUNT) >> 4U; + + while (count > 0U) { + rx_stat = pudev->regs.gr->GRSTATP; + count--; + } + break; + + case GRXSTS_PKTSTS_CH_HALTED: + break; + + default: + break; + } + + /* enable the RX status queue level interrupt */ + pudev->regs.gr->GINTEN |= GINTEN_RXFNEIE; + + return 1U; +} + +/*! + \brief handle the TX FIFO empty interrupt + \param[in] pudev: pointer to USB device instance + \param[in] pp_mode: pipe mode + \param[out] none + \retval operation status +*/ +#if defined (__ICCARM__) /*!< IAR compiler */ + #pragma optimize = none +#endif /* __ICCARM */ +static uint32_t usbh_int_txfifoempty (usb_core_driver *pudev, usb_pipe_mode pp_mode) +{ + uint8_t pp_num = 0U; + uint16_t word_count = 0U, len = 0U; + __IO uint32_t *txfiforeg = 0U, txfifostate = 0U; + + if (PIPE_NON_PERIOD == pp_mode) { + txfiforeg = &pudev->regs.gr->HNPTFQSTAT; + } else if (PIPE_PERIOD == pp_mode) { + txfiforeg = &pudev->regs.hr->HPTFQSTAT; + } else { + return 0U; + } + + txfifostate = *txfiforeg; + + pp_num = (uint8_t)((txfifostate & TFQSTAT_CNUM) >> 27U); + + word_count = (uint16_t)(pudev->host.pipe[pp_num].xfer_len + 3U) / 4U; + + while (((txfifostate & TFQSTAT_TXFS) >= word_count) && (0U != pudev->host.pipe[pp_num].xfer_len)) { + len = (uint16_t)(txfifostate & TFQSTAT_TXFS) * 4U; + + if (len > pudev->host.pipe[pp_num].xfer_len) { + /* last packet */ + len = (uint16_t)pudev->host.pipe[pp_num].xfer_len; + + if (PIPE_NON_PERIOD == pp_mode) { + pudev->regs.gr->GINTEN &= ~GINTEN_NPTXFEIE; + } else { + pudev->regs.gr->GINTEN &= ~GINTEN_PTXFEIE; + } + } + + word_count = (uint16_t)((pudev->host.pipe[pp_num].xfer_len + 3U) / 4U); + usb_txfifo_write (&pudev->regs, pudev->host.pipe[pp_num].xfer_buf, pp_num, len); + + pudev->host.pipe[pp_num].xfer_buf += len; + pudev->host.pipe[pp_num].xfer_len -= len; + pudev->host.pipe[pp_num].xfer_count += len; + + txfifostate = *txfiforeg; + } + + return 1U; +} diff --git a/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/host/class/hid/Include/usbh_hid_core.h b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/host/class/hid/Include/usbh_hid_core.h new file mode 100644 index 0000000000..f58463172f --- /dev/null +++ b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/host/class/hid/Include/usbh_hid_core.h @@ -0,0 +1,212 @@ +/*! + \file usbh_hid_core.h + \brief header file for the usbh_hid_core.c + + \version 2020-08-01, V3.0.0, firmware for GD32F30x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef __USBH_HID_CORE_H +#define __USBH_HID_CORE_H + +#include "usb_hid.h" +#include "usbh_enum.h" +#include "usbh_transc.h" + +#define HID_MIN_POLL 10U +#define HID_REPORT_SIZE 16U +#define HID_MAX_USAGE 10U +#define HID_MAX_NBR_REPORT_FMT 10U +#define HID_QUEUE_SIZE 10U + +#define HID_ITEM_LONG 0xFEU + +#define HID_ITEM_TYPE_MAIN 0x00U +#define HID_ITEM_TYPE_GLOBAL 0x01U +#define HID_ITEM_TYPE_LOCAL 0x02U +#define HID_ITEM_TYPE_RESERVED 0x03U + +#define HID_MAIN_ITEM_TAG_INPUT 0x08U +#define HID_MAIN_ITEM_TAG_OUTPUT 0x09U +#define HID_MAIN_ITEM_TAG_COLLECTION 0x0AU +#define HID_MAIN_ITEM_TAG_FEATURE 0x0BU +#define HID_MAIN_ITEM_TAG_ENDCOLLECTION 0x0CU + +#define HID_GLOBAL_ITEM_TAG_USAGE_PAGE 0x00U +#define HID_GLOBAL_ITEM_TAG_LOG_MIN 0x01U +#define HID_GLOBAL_ITEM_TAG_LOG_MAX 0x02U +#define HID_GLOBAL_ITEM_TAG_PHY_MIN 0x03U +#define HID_GLOBAL_ITEM_TAG_PHY_MAX 0x04U +#define HID_GLOBAL_ITEM_TAG_UNIT_EXPONENT 0x05U +#define HID_GLOBAL_ITEM_TAG_UNIT 0x06U +#define HID_GLOBAL_ITEM_TAG_REPORT_SIZE 0x07U +#define HID_GLOBAL_ITEM_TAG_REPORT_ID 0x08U +#define HID_GLOBAL_ITEM_TAG_REPORT_COUNT 0x09U +#define HID_GLOBAL_ITEM_TAG_PUSH 0x0AU +#define HID_GLOBAL_ITEM_TAG_POP 0x0BU + +#define HID_LOCAL_ITEM_TAG_USAGE 0x00U +#define HID_LOCAL_ITEM_TAG_USAGE_MIN 0x01U +#define HID_LOCAL_ITEM_TAG_USAGE_MAX 0x02U +#define HID_LOCAL_ITEM_TAG_DESIGNATOR_INDEX 0x03U +#define HID_LOCAL_ITEM_TAG_DESIGNATOR_MIN 0x04U +#define HID_LOCAL_ITEM_TAG_DESIGNATOR_MAX 0x05U +#define HID_LOCAL_ITEM_TAG_STRING_INDEX 0x07U +#define HID_LOCAL_ITEM_TAG_STRING_MIN 0x08U +#define HID_LOCAL_ITEM_TAG_STRING_MAX 0x09U +#define HID_LOCAL_ITEM_TAG_DELIMITER 0x0AU + +#define USB_HID_DESC_SIZE 9U + +/* states for HID state machine */ +typedef enum { + HID_INIT = 0U, + HID_IDLE, + HID_SEND_DATA, + HID_BUSY, + HID_GET_DATA, + HID_SYNC, + HID_POLL, + HID_ERROR, +} hid_state; + +typedef enum { + HID_REQ_INIT = 0U, + HID_REQ_IDLE, + HID_REQ_GET_REPORT_DESC, + HID_REQ_GET_HID_DESC, + HID_REQ_SET_IDLE, + HID_REQ_SET_PROTOCOL, + HID_REQ_SET_REPORT, +} hid_ctlstate; + +typedef enum +{ + HID_MOUSE = 0x01U, + HID_KEYBOARD = 0x02U, + HID_UNKNOWN = 0xFFU, +} hid_type; + +typedef struct _hid_report_data +{ + uint8_t ReportID; + uint8_t ReportType; + uint16_t UsagePage; + uint32_t Usage[HID_MAX_USAGE]; + uint32_t NbrUsage; + uint32_t UsageMin; + uint32_t UsageMax; + int32_t LogMin; + int32_t LogMax; + int32_t PhyMin; + int32_t PhyMax; + int32_t UnitExp; + uint32_t Unit; + uint32_t ReportSize; + uint32_t ReportCnt; + uint32_t Flag; + uint32_t PhyUsage; + uint32_t AppUsage; + uint32_t LogUsage; +} hid_report_data; + +typedef struct _hid_report_ID +{ + uint8_t size; /*!< report size return by the device ID */ + uint8_t reportID; /*!< report ID */ + uint8_t type; /*!< report type (INPUT/OUTPUT/FEATURE) */ +} hid_report_ID; + +typedef struct _hid_collection +{ + uint32_t usage; + uint8_t type; + struct _hid_collection *next_ptr; +} hid_collection; + +typedef struct _hid_appcollection +{ + uint32_t usage; + uint8_t type; + uint8_t nbr_report_fmt; + hid_report_data report_data[HID_MAX_NBR_REPORT_FMT]; +} hid_appcollection; + +typedef struct +{ + uint8_t *buf; + uint16_t head; + uint16_t tail; + uint16_t size; + uint8_t lock; +} data_fifo; + +/* structure for HID process */ +typedef struct _hid_process +{ + uint8_t pipe_in; + uint8_t pipe_out; + uint8_t ep_addr; + uint8_t ep_in; + uint8_t ep_out; + __IO uint8_t data_ready; + uint8_t *pdata; + uint16_t len; + uint16_t poll; + + __IO uint32_t timer; + + data_fifo fifo; + usb_desc_hid hid_desc; + hid_report_data hid_report; + + hid_state state; + hid_ctlstate ctl_state; + usbh_status (*init)(usb_core_driver *pudev, usbh_host *puhost); + void (*machine)(usb_core_driver *pudev, usbh_host *puhost); +} usbh_hid_handler; + +extern usbh_class usbh_hid; + +/* function declarations */ +/* set HID report */ +usbh_status usbh_set_report (usb_core_driver *pudev, + usbh_host *puhost, + uint8_t report_type, + uint8_t report_ID, + uint8_t report_len, + uint8_t *report_buf); +/* read data from FIFO */ +uint16_t usbh_hid_fifo_read (data_fifo *fifo, void *buf, uint16_t nbytes); +/* write data to FIFO */ +uint16_t usbh_hid_fifo_write (data_fifo *fifo, void *buf, uint16_t nbytes); +/* initialize FIFO */ +void usbh_hid_fifo_init (data_fifo *fifo, uint8_t *buf, uint16_t size); + +#endif /* __USBH_HID_CORE_H */ diff --git a/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/host/class/hid/Include/usbh_hid_keybd.h b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/host/class/hid/Include/usbh_hid_keybd.h new file mode 100644 index 0000000000..0d93792ce4 --- /dev/null +++ b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/host/class/hid/Include/usbh_hid_keybd.h @@ -0,0 +1,303 @@ +/*! + \file usbh_hid_keybd.h + \brief header file for usbh_hid_keybd.c + + \version 2020-08-01, V3.0.0, firmware for GD32F30x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef __USBH_HID_KEYBD_H +#define __USBH_HID_KEYBD_H + +#include "usb_conf.h" +#include "usbh_hid_core.h" + +//#define AZERTY_KEYBOARD +#define QWERTY_KEYBOARD + +#define KBD_LEFT_CTRL 0x01U +#define KBD_LEFT_SHIFT 0x02U +#define KBD_LEFT_ALT 0x04U +#define KBD_LEFT_GUI 0x08U +#define KBD_RIGHT_CTRL 0x10U +#define KBD_RIGHT_SHIFT 0x20U +#define KBD_RIGHT_ALT 0x40U +#define KBD_RIGHT_GUI 0x80U + +#define KEY_NONE 0x00U +#define KEY_ERRORROLLOVER 0x01U +#define KEY_POSTFAIL 0x02U +#define KEY_ERRORUNDEFINED 0x03U +#define KEY_A 0x04U +#define KEY_B 0x05U +#define KEY_C 0x06U +#define KEY_D 0x07U +#define KEY_E 0x08U +#define KEY_F 0x09U +#define KEY_G 0x0AU +#define KEY_H 0x0BU +#define KEY_I 0x0CU +#define KEY_J 0x0DU +#define KEY_K 0x0EU +#define KEY_L 0x0FU +#define KEY_M 0x10U +#define KEY_N 0x11U +#define KEY_O 0x12U +#define KEY_P 0x13U +#define KEY_Q 0x14U +#define KEY_R 0x15U +#define KEY_S 0x16U +#define KEY_T 0x17U +#define KEY_U 0x18U +#define KEY_V 0x19U +#define KEY_W 0x1AU +#define KEY_X 0x1BU +#define KEY_Y 0x1CU +#define KEY_Z 0x1DU +#define KEY_1_EXCLAMATION_MARK 0x1EU +#define KEY_2_AT 0x1FU +#define KEY_3_NUMBER_SIGN 0x20U +#define KEY_4_DOLLAR 0x21U +#define KEY_5_PERCENT 0x22U +#define KEY_6_CARET 0x23U +#define KEY_7_AMPERSAND 0x24U +#define KEY_8_ASTERISK 0x25U +#define KEY_9_OPARENTHESIS 0x26U +#define KEY_0_CPARENTHESIS 0x27U +#define KEY_ENTER 0x28U +#define KEY_ESCAPE 0x29U +#define KEY_BACKSPACE 0x2AU +#define KEY_TAB 0x2BU +#define KEY_SPACEBAR 0x2CU +#define KEY_MINUS_UNDERSCORE 0x2DU +#define KEY_EQUAL_PLUS 0x2EU +#define KEY_OBRACKET_AND_OBRACE 0x2FU +#define KEY_CBRACKET_AND_CBRACE 0x30U +#define KEY_BACKSLASH_VERTICAL_BAR 0x31U +#define KEY_NONUS_NUMBER_SIGN_TILDE 0x32U +#define KEY_SEMICOLON_COLON 0x33U +#define KEY_SINGLE_AND_DOUBLE_QUOTE 0x34U +#define KEY_GRAVE ACCENT AND TILDE 0x35U +#define KEY_COMMA_AND_LESS 0x36U +#define KEY_DOT_GREATER 0x37U +#define KEY_SLASH_QUESTION 0x38U +#define KEY_CAPS LOCK 0x39U +#define KEY_F1 0x3AU +#define KEY_F2 0x3BU +#define KEY_F3 0x3CU +#define KEY_F4 0x3DU +#define KEY_F5 0x3EU +#define KEY_F6 0x3FU +#define KEY_F7 0x40U +#define KEY_F8 0x41U +#define KEY_F9 0x42U +#define KEY_F10 0x43U +#define KEY_F11 0x44U +#define KEY_F12 0x45U +#define KEY_PRINTSCREEN 0x46U +#define KEY_SCROLL LOCK 0x47U +#define KEY_PAUSE 0x48U +#define KEY_INSERT 0x49U +#define KEY_HOME 0x4AU +#define KEY_PAGEUP 0x4BU +#define KEY_DELETE 0x4CU +#define KEY_END1 0x4DU +#define KEY_PAGEDOWN 0x4EU +#define KEY_RIGHTARROW 0x4FU +#define KEY_LEFTARROW 0x50U +#define KEY_DOWNARROW 0x51U +#define KEY_UPARROW 0x52U +#define KEY_KEYPAD_NUM_LOCK_AND_CLEAR 0x53U +#define KEY_KEYPAD_SLASH 0x54U +#define KEY_KEYPAD_ASTERIKS 0x55U +#define KEY_KEYPAD_MINUS 0x56U +#define KEY_KEYPAD_PLUS 0x57U +#define KEY_KEYPAD_ENTER 0x58U +#define KEY_KEYPAD_1_END 0x59U +#define KEY_KEYPAD_2_DOWN_ARROW 0x5AU +#define KEY_KEYPAD_3_PAGEDN 0x5BU +#define KEY_KEYPAD_4_LEFT_ARROW 0x5CU +#define KEY_KEYPAD_5 0x5DU +#define KEY_KEYPAD_6_RIGHT_ARROW 0x5EU +#define KEY_KEYPAD_7_HOME 0x5FU +#define KEY_KEYPAD_8_UP_ARROW 0x60U +#define KEY_KEYPAD_9_PAGEUP 0x61U +#define KEY_KEYPAD_0_INSERT 0x62U +#define KEY_KEYPAD_DECIMAL_SEPARATOR_DELETE 0x63U +#define KEY_NONUS_BACK_SLASH_VERTICAL_BAR 0x64U +#define KEY_APPLICATION 0x65U +#define KEY_POWER 0x66U +#define KEY_KEYPAD_EQUAL 0x67U +#define KEY_F13 0x68U +#define KEY_F14 0x69U +#define KEY_F15 0x6AU +#define KEY_F16 0x6BU +#define KEY_F17 0x6CU +#define KEY_F18 0x6DU +#define KEY_F19 0x6EU +#define KEY_F20 0x6FU +#define KEY_F21 0x70U +#define KEY_F22 0x71U +#define KEY_F23 0x72U +#define KEY_F24 0x73U +#define KEY_EXECUTE 0x74U +#define KEY_HELP 0x75U +#define KEY_MENU 0x76U +#define KEY_SELECT 0x77U +#define KEY_STOP 0x78U +#define KEY_AGAIN 0x79U +#define KEY_UNDO 0x7AU +#define KEY_CUT 0x7BU +#define KEY_COPY 0x7CU +#define KEY_PASTE 0x7DU +#define KEY_FIND 0x7EU +#define KEY_MUTE 0x7FU +#define KEY_VOLUME_UP 0x80U +#define KEY_VOLUME_DOWN 0x81U +#define KEY_LOCKING_CAPS_LOCK 0x82U +#define KEY_LOCKING_NUM_LOCK 0x83U +#define KEY_LOCKING_SCROLL_LOCK 0x84U +#define KEY_KEYPAD_COMMA 0x85U +#define KEY_KEYPAD_EQUAL_SIGN 0x86U +#define KEY_INTERNATIONAL1 0x87U +#define KEY_INTERNATIONAL2 0x88U +#define KEY_INTERNATIONAL3 0x89U +#define KEY_INTERNATIONAL4 0x8AU +#define KEY_INTERNATIONAL5 0x8BU +#define KEY_INTERNATIONAL6 0x8CU +#define KEY_INTERNATIONAL7 0x8DU +#define KEY_INTERNATIONAL8 0x8EU +#define KEY_INTERNATIONAL9 0x8FU +#define KEY_LANG1 0x90U +#define KEY_LANG2 0x91U +#define KEY_LANG3 0x92U +#define KEY_LANG4 0x93U +#define KEY_LANG5 0x94U +#define KEY_LANG6 0x95U +#define KEY_LANG7 0x96U +#define KEY_LANG8 0x97U +#define KEY_LANG9 0x98U +#define KEY_ALTERNATE_ERASE 0x99U +#define KEY_SYSREQ 0x9AU +#define KEY_CANCEL 0x9BU +#define KEY_CLEAR 0x9CU +#define KEY_PRIOR 0x9DU +#define KEY_RETURN 0x9EU +#define KEY_SEPARATOR 0x9FU +#define KEY_OUT 0xA0U +#define KEY_OPER 0xA1U +#define KEY_CLEAR_AGAIN 0xA2U +#define KEY_CRSEL 0xA3U +#define KEY_EXSEL 0xA4U +#define KEY_KEYPAD_00 0xB0U +#define KEY_KEYPAD_000 0xB1U +#define KEY_THOUSANDS_SEPARATOR 0xB2U +#define KEY_DECIMAL_SEPARATOR 0xB3U +#define KEY_CURRENCY_UNIT 0xB4U +#define KEY_CURRENCY_SUB_UNIT 0xB5U +#define KEY_KEYPAD_OPARENTHESIS 0xB6U +#define KEY_KEYPAD_CPARENTHESIS 0xB7U +#define KEY_KEYPAD_OBRACE 0xB8U +#define KEY_KEYPAD_CBRACE 0xB9U +#define KEY_KEYPAD_TAB 0xBAU +#define KEY_KEYPAD_BACKSPACE 0xBBU +#define KEY_KEYPAD_A 0xBCU +#define KEY_KEYPAD_B 0xBDU +#define KEY_KEYPAD_C 0xBEU +#define KEY_KEYPAD_D 0xBFU +#define KEY_KEYPAD_E 0xC0U +#define KEY_KEYPAD_F 0xC1U +#define KEY_KEYPAD_XOR 0xC2U +#define KEY_KEYPAD_CARET 0xC3U +#define KEY_KEYPAD_PERCENT 0xC4U +#define KEY_KEYPAD_LESS 0xC5U +#define KEY_KEYPAD_GREATER 0xC6U +#define KEY_KEYPAD_AMPERSAND 0xC7U +#define KEY_KEYPAD_LOGICAL_AND 0xC8U +#define KEY_KEYPAD_VERTICAL_BAR 0xC9U +#define KEY_KEYPAD_LOGIACL_OR 0xCAU +#define KEY_KEYPAD_COLON 0xCBU +#define KEY_KEYPAD_NUMBER_SIGN 0xCCU +#define KEY_KEYPAD_SPACE 0xCDU +#define KEY_KEYPAD_AT 0xCEU +#define KEY_KEYPAD_EXCLAMATION_MARK 0xCFU +#define KEY_KEYPAD_MEMORY_STORE 0xD0U +#define KEY_KEYPAD_MEMORY_RECALL 0xD1U +#define KEY_KEYPAD_MEMORY_CLEAR 0xD2U +#define KEY_KEYPAD_MEMORY_ADD 0xD3U +#define KEY_KEYPAD_MEMORY_SUBTRACT 0xD4U +#define KEY_KEYPAD_MEMORY_MULTIPLY 0xD5U +#define KEY_KEYPAD_MEMORY_DIVIDE 0xD6U +#define KEY_KEYPAD_PLUSMINUS 0xD7U +#define KEY_KEYPAD_CLEAR 0xD8U +#define KEY_KEYPAD_CLEAR_ENTRY 0xD9U +#define KEY_KEYPAD_BINARY 0xDAU +#define KEY_KEYPAD_OCTAL 0xDBU +#define KEY_KEYPAD_DECIMAL 0xDCU +#define KEY_KEYPAD_HEXADECIMAL 0xDDU +#define KEY_LEFTCONTROL 0xE0U +#define KEY_LEFTSHIFT 0xE1U +#define KEY_LEFTALT 0xE2U +#define KEY_LEFT_GUI 0xE3U +#define KEY_RIGHTCONTROL 0xE4U +#define KEY_RIGHTSHIFT 0xE5U +#define KEY_RIGHTALT 0xE6U +#define KEY_RIGHT_GUI 0xE7U + +#define KBR_MAX_NBR_PRESSED 6U + +typedef struct +{ + uint8_t state; + uint8_t lctrl; + uint8_t lshift; + uint8_t lalt; + uint8_t lgui; + uint8_t rctrl; + uint8_t rshift; + uint8_t ralt; + uint8_t rgui; + uint8_t keys[6]; +} hid_keybd_info; + +/* function declarations */ +/* initialize keyboard */ +void USR_KEYBRD_Init (void); +/* process keyboard data */ +void USR_KEYBRD_ProcessData (uint8_t pbuf); +/* initialize the keyboard function */ +usbh_status usbh_hid_keybd_init (usb_core_driver *pudev, usbh_host *puhost); +/* get keyboard information */ +hid_keybd_info *usbh_hid_keybd_info_get (usb_core_driver *pudev, usbh_host *puhost); +/* get the ascii code of hid */ +uint8_t usbh_hid_ascii_code_get (hid_keybd_info *info); +/* keyboard machine */ +void usbh_hid_keybrd_machine (usb_core_driver *pudev, usbh_host *puhost); + +#endif /* __USBH_HID_KEYBD_H */ diff --git a/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/host/class/hid/Include/usbh_hid_mouse.h b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/host/class/hid/Include/usbh_hid_mouse.h new file mode 100644 index 0000000000..94b51654b5 --- /dev/null +++ b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/host/class/hid/Include/usbh_hid_mouse.h @@ -0,0 +1,59 @@ +/*! + \file usbh_hid_mouse.h + \brief header file for the usbh_hid_mouse.c + + \version 2020-08-01, V3.0.0, firmware for GD32F30x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef __USBH_HID_MOUSE_H +#define __USBH_HID_MOUSE_H + +#include "usbh_hid_core.h" + +typedef struct _hid_mouse_info +{ + uint8_t x; + uint8_t y; + uint8_t buttons[3]; +} hid_mouse_info; + +/* function declarations */ +/* initialize mouse */ +void USR_MOUSE_Init (void); +/* process mouse data */ +void USR_MOUSE_ProcessData (hid_mouse_info *data); +/* initialize mouse function */ +usbh_status usbh_hid_mouse_init (usb_core_driver *pudev, usbh_host *puhost); +/* get mouse information */ +hid_mouse_info *usbh_hid_mouse_info_get (usb_core_driver *pudev, usbh_host *puhost); +/* mouse machine */ +void usbh_hid_mouse_machine (usb_core_driver *pudev, usbh_host *puhost); + +#endif /* __USBH_HID_MOUSE_H */ diff --git a/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/host/class/hid/Include/usbh_hid_parser.h b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/host/class/hid/Include/usbh_hid_parser.h new file mode 100644 index 0000000000..45c68af100 --- /dev/null +++ b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/host/class/hid/Include/usbh_hid_parser.h @@ -0,0 +1,61 @@ +/*! + \file usbh_hid_core.h + \brief header file for the usbh_hid_core.c + + \version 2020-08-01, V3.0.0, firmware for GD32F30x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef __USBH_HID_PARSER_H +#define __USBH_HID_PARSER_H + +#include "usbh_hid_core.h" +#include "usbh_hid_usage.h" + +typedef struct +{ + uint8_t *data; + uint32_t size; + uint8_t shift; + uint8_t count; + uint8_t sign; + uint32_t logical_min; /*min value device can return*/ + uint32_t logical_max; /*max value device can return*/ + uint32_t physical_min; /*min vale read can report*/ + uint32_t physical_max; /*max value read can report*/ + uint32_t resolution; +} hid_report_item; + +/* function declarations */ +/* read a hid report item */ +uint32_t hid_item_read (hid_report_item *ri, uint8_t ndx); +/* write a hid report item */ +uint32_t hid_item_write (hid_report_item *ri, uint32_t value, uint8_t ndx); + +#endif /* __USBH_HID_PARSER_H */ diff --git a/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/host/class/hid/Include/usbh_hid_usage.h b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/host/class/hid/Include/usbh_hid_usage.h new file mode 100644 index 0000000000..be3d9d9132 --- /dev/null +++ b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/host/class/hid/Include/usbh_hid_usage.h @@ -0,0 +1,141 @@ +/*! + \file usbh_hid_core.h + \brief header file for the usbh_hid_core.c + + \version 2020-08-01, V3.0.0, firmware for GD32F30x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef __USDH_HID_USAGE_H +#define __USDH_HID_USAGE_H + +/* HID 1.11 usage pages */ +#define HID_USAGE_PAGE_UNDEFINED uint16_t (0x00) /* Undefined */ + +/* top level pages */ +#define HID_USAGE_PAGE_GEN_DES uint16_t (0x01) /* Generic Desktop Controls*/ +#define HID_USAGE_PAGE_SIM_CTR uint16_t (0x02) /* Simulation Controls */ +#define HID_USAGE_PAGE_VR_CTR uint16_t (0x03) /* VR Controls */ +#define HID_USAGE_PAGE_SPORT_CTR uint16_t (0x04) /* Sport Controls */ +#define HID_USAGE_PAGE_GAME_CTR uint16_t (0x05) /* Game Controls */ +#define HID_USAGE_PAGE_GEN_DEV uint16_t (0x06) /* Generic Device Controls */ +#define HID_USAGE_PAGE_KEYB uint16_t (0x07) /* Keyboard/Keypad */ +#define HID_USAGE_PAGE_LED uint16_t (0x08) /* LEDs */ +#define HID_USAGE_PAGE_BUTTON uint16_t (0x09) /* Button */ +#define HID_USAGE_PAGE_ORDINAL uint16_t (0x0A) /* Ordinal */ +#define HID_USAGE_PAGE_PHONE uint16_t (0x0B) /* Telephony */ +#define HID_USAGE_PAGE_CONSUMER uint16_t (0x0C) /* Consumer */ +#define HID_USAGE_PAGE_DIGITIZER uint16_t (0x0D) /* Digitizer*/ +#define HID_USAGE_PAGE_PID uint16_t (0x0F) /* PID Page (force feedback and related devices) */ +#define HID_USAGE_PAGE_UNICODE uint16_t (0x10) /* Unicode */ +#define HID_USAGE_PAGE_ALNUM_DISP uint16_t (0x14) /* Alphanumeric Display */ +/* end of top level pages */ + +#define HID_USAGE_PAGE_MEDICAL uint16_t (0x40) /* Medical Instruments */ + +/* 80-83 Monitor pages USB Device Class Definition for Monitor Devices */ +/* 84-87 Power pages USB Device Class Definition for Power Devices */ +#define HID_USAGE_PAGE_BARCODE uint16_t (0x8C) /* Bar Code Scanner page */ +#define HID_USAGE_PAGE_SCALE uint16_t (0x8D) /* Scale page */ +#define HID_USAGE_PAGE_MSR uint16_t (0x8E) /* Magnetic Stripe Reading (MSR) Devices */ +#define HID_USAGE_PAGE_POS uint16_t (0x8F) /* Reserved Point of Sale pages */ +#define HID_USAGE_PAGE_CAMERA_CTR uint16_t (0x90) /* Camera Control Page */ +#define HID_USAGE_PAGE_ARCADE uint16_t (0x91) /* Arcade Page */ + +/* usage definitions for the "generic desktop" page */ +#define HID_USAGE_UNDEFINED uint16_t (0x00) /* Undefined */ +#define HID_USAGE_POINTER uint16_t (0x01) /* Pointer (Physical Collection) */ +#define HID_USAGE_MOUSE uint16_t (0x02) /* Mouse (Application Collection) */ +#define HID_USAGE_JOYSTICK uint16_t (0x04) /* Joystick (Application Collection) */ +#define HID_USAGE_GAMEPAD uint16_t (0x05) /* Game Pad (Application Collection) */ +#define HID_USAGE_KBD uint16_t (0x06) /* Keyboard (Application Collection) */ +#define HID_USAGE_KEYPAD uint16_t (0x07) /* Keypad (Application Collection) */ +#define HID_USAGE_MAX_CTR uint16_t (0x08) /* Multi-axis Controller (Application Collection) */ +#define HID_USAGE_X uint16_t (0x30) /* X (Dynamic Value) */ +#define HID_USAGE_Y uint16_t (0x31) /* Y (Dynamic Value) */ +#define HID_USAGE_Z uint16_t (0x32) /* Z (Dynamic Value) */ +#define HID_USAGE_RX uint16_t (0x33) /* Rx (Dynamic Value) */ +#define HID_USAGE_RY uint16_t (0x34) /* Ry (Dynamic Value) */ +#define HID_USAGE_RZ uint16_t (0x35) /* Rz (Dynamic Value) */ +#define HID_USAGE_SLIDER uint16_t (0x36) /* Slider (Dynamic Value) */ +#define HID_USAGE_DIAL uint16_t (0x37) /* Dial (Dynamic Value) */ +#define HID_USAGE_WHEEL uint16_t (0x38) /* Wheel (Dynamic Value) */ +#define HID_USAGE_HATSW uint16_t (0x39) /* Hat switch (Dynamic Value) */ +#define HID_USAGE_COUNTEDBUF uint16_t (0x3A) /* Counted Buffer (Logical Collection) */ +#define HID_USAGE_BYTECOUNT uint16_t (0x3B) /* Byte Count (Dynamic Value) */ +#define HID_USAGE_MOTIONWAKE uint16_t (0x3C) /* Motion Wakeup (One Shot Control) */ +#define HID_USAGE_START uint16_t (0x3D) /* Start (On/Off Control) */ +#define HID_USAGE_SELECT uint16_t (0x3E) /* Select (On/Off Control) */ +#define HID_USAGE_VX uint16_t (0x40) /* Vx (Dynamic Value) */ +#define HID_USAGE_VY uint16_t (0x41) /* Vy (Dynamic Value) */ +#define HID_USAGE_VZ uint16_t (0x42) /* Vz (Dynamic Value) */ +#define HID_USAGE_VBRX uint16_t (0x43) /* Vbrx (Dynamic Value) */ +#define HID_USAGE_VBRY uint16_t (0x44) /* Vbry (Dynamic Value) */ +#define HID_USAGE_VBRZ uint16_t (0x45) /* Vbrz (Dynamic Value) */ +#define HID_USAGE_VNO uint16_t (0x46) /* Vno (Dynamic Value) */ +#define HID_USAGE_FEATNOTIF uint16_t (0x47) /* Feature Notification (Dynamic Value),(Dynamic Flag) */ +#define HID_USAGE_SYSCTL uint16_t (0x80) /* System Control (Application Collection) */ +#define HID_USAGE_PWDOWN uint16_t (0x81) /* System Power Down (One Shot Control) */ +#define HID_USAGE_SLEEP uint16_t (0x82) /* System Sleep (One Shot Control) */ +#define HID_USAGE_WAKEUP uint16_t (0x83) /* System Wake Up (One Shot Control) */ +#define HID_USAGE_CONTEXTM uint16_t (0x84) /* System Context Menu (One Shot Control) */ +#define HID_USAGE_MAINM uint16_t (0x85) /* System Main Menu (One Shot Control) */ +#define HID_USAGE_APPM uint16_t (0x86) /* System App Menu (One Shot Control) */ +#define HID_USAGE_MENUHELP uint16_t (0x87) /* System Menu Help (One Shot Control) */ +#define HID_USAGE_MENUEXIT uint16_t (0x88) /* System Menu Exit (One Shot Control) */ +#define HID_USAGE_MENUSELECT uint16_t (0x89) /* System Menu Select (One Shot Control) */ +#define HID_USAGE_SYSM_RIGHT uint16_t (0x8A) /* System Menu Right (Re-Trigger Control) */ +#define HID_USAGE_SYSM_LEFT uint16_t (0x8B) /* System Menu Left (Re-Trigger Control) */ +#define HID_USAGE_SYSM_UP uint16_t (0x8C) /* System Menu Up (Re-Trigger Control) */ +#define HID_USAGE_SYSM_DOWN uint16_t (0x8D) /* System Menu Down (Re-Trigger Control) */ +#define HID_USAGE_COLDRESET uint16_t (0x8E) /* System Cold Restart (One Shot Control) */ +#define HID_USAGE_WARMRESET uint16_t (0x8F) /* System Warm Restart (One Shot Control) */ +#define HID_USAGE_DUP uint16_t (0x90) /* D-pad Up (On/Off Control) */ +#define HID_USAGE_DDOWN uint16_t (0x91) /* D-pad Down (On/Off Control) */ +#define HID_USAGE_DRIGHT uint16_t (0x92) /* D-pad Right (On/Off Control) */ +#define HID_USAGE_DLEFT uint16_t (0x93) /* D-pad Left (On/Off Control) */ +#define HID_USAGE_SYS_DOCK uint16_t (0xA0) /* System Dock (One Shot Control) */ +#define HID_USAGE_SYS_UNDOCK uint16_t (0xA1) /* System Undock (One Shot Control) */ +#define HID_USAGE_SYS_SETUP uint16_t (0xA2) /* System Setup (One Shot Control) */ +#define HID_USAGE_SYS_BREAK uint16_t (0xA3) /* System Break (One Shot Control) */ +#define HID_USAGE_SYS_DBGBRK uint16_t (0xA4) /* System Debugger Break (One Shot Control) */ +#define HID_USAGE_APP_BRK uint16_t (0xA5) /* Application Break (One Shot Control) */ +#define HID_USAGE_APP_DBGBRK uint16_t (0xA6) /* Application Debugger Break (One Shot Control) */ +#define HID_USAGE_SYS_SPKMUTE uint16_t (0xA7) /* System Speaker Mute (One Shot Control) */ +#define HID_USAGE_SYS_HIBERN uint16_t (0xA8) /* System Hibernate (One Shot Control) */ +#define HID_USAGE_SYS_SIDPINV uint16_t (0xB0) /* System Display Invert (One Shot Control) */ +#define HID_USAGE_SYS_DISPINT uint16_t (0xB1) /* System Display Internal (One Shot Control) */ +#define HID_USAGE_SYS_DISPEXT uint16_t (0xB2) /* System Display External (One Shot Control) */ +#define HID_USAGE_SYS_DISPBOTH uint16_t (0xB3) /* System Display Both (One Shot Control) */ +#define HID_USAGE_SYS_DISPDUAL uint16_t (0xB4) /* System Display Dual (One Shot Control) */ +#define HID_USAGE_SYS_DISPTGLIE uint16_t (0xB5) /* System Display Toggle Int/Ext (One Shot Control) */ +#define HID_USAGE_SYS_DISP_SWAP uint16_t (0xB6) /* System Display Swap Primary/Secondary (One Shot Control) */ +#define HID_USAGE_SYS_DIPS_LCDA uint16_t (0xB7) /* System Display LCD Autoscale (One Shot Control) */ + +#endif /* __USDH_HID_USAGE_H */ diff --git a/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/host/class/hid/Source/usbh_hid_core.c b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/host/class/hid/Source/usbh_hid_core.c new file mode 100644 index 0000000000..978502f9fc --- /dev/null +++ b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/host/class/hid/Source/usbh_hid_core.c @@ -0,0 +1,675 @@ +/*! + \file usbh_hid_core.c + \brief USB host HID class driver + + \version 2020-08-01, V3.0.0, firmware for GD32F30x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "usbh_pipe.h" +#include "usbh_hid_core.h" +#include "usbh_hid_mouse.h" +#include "usbh_hid_keybd.h" +#include +#include + +/* local function prototypes ('static') */ +static void usbh_hiddesc_parse (usb_desc_hid *hid_desc, uint8_t *buf); +static void usbh_hid_itf_deinit (usbh_host *puhost); +static usbh_status usbh_hid_itf_init (usbh_host *puhost); +static usbh_status usbh_hid_class_req (usbh_host *puhost); +static usbh_status usbh_hid_handle (usbh_host *puhost); +static usbh_status usbh_hid_reportdesc_get (usbh_host *puhost, uint16_t len); +static usbh_status usbh_hid_sof(usbh_host *puhost); +static usbh_status usbh_hid_desc_get (usbh_host *puhost, uint16_t len); +static usbh_status usbh_set_idle (usbh_host *puhost, uint8_t duration, uint8_t report_ID); +static usbh_status usbh_set_protocol (usbh_host *puhost, uint8_t protocol); + +usbh_class usbh_hid = +{ + USB_HID_CLASS, + usbh_hid_itf_init, + usbh_hid_itf_deinit, + usbh_hid_class_req, + usbh_hid_handle, + usbh_hid_sof +}; + +/*! + \brief get report + \param[in] puhost: pointer to usb host + \param[in] report_type: duration for HID set idle request + \param[in] report_ID: targeted report ID for HID set idle request + \param[in] report_len: length of data report to be send + \param[in] report_buf: report buffer + \param[out] none + \retval operation status +*/ +usbh_status usbh_get_report (usbh_host *puhost, + uint8_t report_type, + uint8_t report_ID, + uint8_t report_len, + uint8_t *report_buf) +{ + usbh_status status = USBH_BUSY; + + if (CTL_IDLE == puhost->control.ctl_state) { + puhost->control.setup.req = (usb_req) { + .bmRequestType = USB_TRX_IN | USB_RECPTYPE_ITF | USB_REQTYPE_CLASS, + .bRequest = GET_REPORT, + .wValue = (report_type << 8U) | report_ID, + .wIndex = 0U, + .wLength = report_len + }; + + usbh_ctlstate_config (puhost, report_buf, report_len); + } + + status = usbh_ctl_handler (puhost); + + return status; +} + +/*! + \brief set report + \param[in] pudev: pointer to usb core instance + \param[in] puhost: pointer to usb host + \param[in] report_type: duration for HID set idle request + \param[in] report_ID: targeted report ID for HID set idle request + \param[in] report_len: length of data report to be send + \param[in] report_buf: report buffer + \param[out] none + \retval operation status +*/ +usbh_status usbh_set_report (usb_core_driver *pudev, + usbh_host *puhost, + uint8_t report_type, + uint8_t report_ID, + uint8_t report_len, + uint8_t *report_buf) +{ + usbh_status status = USBH_BUSY; + + if (CTL_IDLE == puhost->control.ctl_state) { + puhost->control.setup.req = (usb_req) { + .bmRequestType = USB_TRX_OUT | USB_RECPTYPE_ITF | USB_REQTYPE_CLASS, + .bRequest = SET_REPORT, + .wValue = (report_type << 8U) | report_ID, + .wIndex = 0U, + .wLength = report_len + }; + + usbh_ctlstate_config (puhost, report_buf, report_len); + } + + status = usbh_ctl_handler (puhost); + + return status; +} + +/*! + \brief de-initialize the host pipes used for the HID class + \param[in] puhost: pointer to usb host + \param[out] none + \retval operation status +*/ +void usbh_hid_itf_deinit (usbh_host *puhost) +{ + usbh_hid_handler *hid = (usbh_hid_handler *)puhost->active_class->class_data; + + if (0x00U != hid->pipe_in) { + usb_pipe_halt (puhost->data, hid->pipe_in); + + usbh_pipe_free (puhost->data, hid->pipe_in); + + hid->pipe_in = 0U; /* reset the pipe as free */ + } + + if (0x00U != hid->pipe_out) { + usb_pipe_halt (puhost->data, hid->pipe_out); + + usbh_pipe_free (puhost->data, hid->pipe_out); + + hid->pipe_out = 0U; /* reset the channel as free */ + } +} + +/*! + \brief return device type + \param[in] pudev: pointer to usb core instance + \param[in] puhost: pointer to usb host + \param[out] none + \retval hid_type +*/ +hid_type usbh_hid_device_type_get(usb_core_driver *pudev, usbh_host *puhost) +{ + hid_type type = HID_UNKNOWN; + uint8_t interface_protocol; + + if (HOST_CLASS_HANDLER == puhost->cur_state) { + interface_protocol = puhost->dev_prop.cfg_desc_set.itf_desc_set[puhost->dev_prop.cur_itf][0].itf_desc.bInterfaceProtocol; + + if (USB_HID_PROTOCOL_KEYBOARD == interface_protocol) { + type = HID_KEYBOARD; + } else { + if (USB_HID_PROTOCOL_MOUSE == interface_protocol) { + type = HID_MOUSE; + } + } + } + + return type; +} + +/*! + \brief return HID device poll time + \param[in] pudev: pointer to usb core instance + \param[in] puhost: pointer to usb host + \param[out] none + \retval poll time (ms) +*/ +uint8_t usbh_hid_poll_interval_get (usb_core_driver *pudev, usbh_host *puhost) +{ + usbh_hid_handler *hid = (usbh_hid_handler *)puhost->active_class->class_data; + + if ((HOST_CLASS_ENUM == puhost->cur_state) || + (HOST_USER_INPUT == puhost->cur_state) || + (HOST_CHECK_CLASS == puhost->cur_state) || + (HOST_CLASS_HANDLER == puhost->cur_state)) { + return (uint8_t)(hid->poll); + } else { + return 0U; + } +} + +/*! + \brief read from FIFO + \param[in] fifo: fifo address + \param[in] buf: read buffer + \param[in] nbytes: number of item to read + \param[out] none + \retval number of read items +*/ +uint16_t usbh_hid_fifo_read (data_fifo *fifo, void *buf, uint16_t nbytes) +{ + uint16_t i = 0U; + uint8_t *p = (uint8_t*) buf; + + if (0U == fifo->lock) { + fifo->lock = 1U; + + for (i = 0U; i < nbytes; i++) { + if (fifo->tail != fifo->head) { + *p++ = fifo->buf[fifo->tail]; + fifo->tail++; + + if (fifo->tail == fifo->size) { + fifo->tail = 0U; + } + } else { + fifo->lock = 0U; + + return i; + } + } + } + + fifo->lock = 0U; + + return nbytes; +} + +/*! + \brief write to FIFO + \param[in] fifo: fifo address + \param[in] buf: read buffer + \param[in] nbytes: number of item to read + \param[out] none + \retval number of write items +*/ +uint16_t usbh_hid_fifo_write (data_fifo *fifo, void *buf, uint16_t nbytes) +{ + uint16_t i = 0U; + uint8_t *p = (uint8_t*) buf; + + if (0U == fifo->lock) { + fifo->lock = 1U; + + for (i = 0U; i < nbytes; i++) { + if ((fifo->head + 1U == fifo->tail) || + ((fifo->head + 1U == fifo->size) && (0U == fifo->tail))) { + fifo->lock = 0U; + + return i; + } else { + fifo->buf[fifo->head] = *p++; + fifo->head++; + + if (fifo->head == fifo->size) { + fifo->head = 0U; + } + } + } + } + + fifo->lock = 0U; + + return nbytes; +} + +/*! + \brief initialize FIFO + \param[in] fifo: fifo address + \param[in] buf: read buffer + \param[in] size: size of FIFO + \param[out] none + \retval none +*/ +void usbh_hid_fifo_init (data_fifo *fifo, uint8_t *buf, uint16_t size) +{ + fifo->head = 0U; + fifo->tail = 0U; + fifo->lock = 0U; + fifo->size = size; + fifo->buf = buf; +} + +/*! + \brief initialize the hid class + \param[in] puhost: pointer to usb host + \param[out] none + \retval operation status +*/ +static usbh_status usbh_hid_itf_init (usbh_host *puhost) +{ + uint8_t num = 0U, ep_num = 0U, interface = 0U; + usbh_status status = USBH_BUSY; + + interface = usbh_interface_find(&puhost->dev_prop, USB_HID_CLASS, USB_HID_SUBCLASS_BOOT_ITF, 0xFFU); + + if (0xFFU == interface) { + puhost->usr_cb->dev_not_supported(); + + status = USBH_FAIL; + } else { + usbh_interface_select(&puhost->dev_prop, interface); + + static usbh_hid_handler hid_handler; + + memset((void*)&hid_handler, 0, sizeof(usbh_hid_handler)); + + hid_handler.state = HID_ERROR; + + uint8_t itf_protocol = puhost->dev_prop.cfg_desc_set.itf_desc_set[puhost->dev_prop.cur_itf][0].itf_desc.bInterfaceProtocol; + if (USB_HID_PROTOCOL_KEYBOARD == itf_protocol) { + hid_handler.init = usbh_hid_keybd_init; + hid_handler.machine = usbh_hid_keybrd_machine; + } else if (USB_HID_PROTOCOL_MOUSE == itf_protocol) { + hid_handler.init = usbh_hid_mouse_init; + hid_handler.machine = usbh_hid_mouse_machine; + } else { + status = USBH_FAIL; + } + + hid_handler.state = HID_INIT; + hid_handler.ctl_state = HID_REQ_INIT; + hid_handler.ep_addr = puhost->dev_prop.cfg_desc_set.itf_desc_set[puhost->dev_prop.cur_itf][0].ep_desc[0].bEndpointAddress; + hid_handler.len = puhost->dev_prop.cfg_desc_set.itf_desc_set[puhost->dev_prop.cur_itf][0].ep_desc[0].wMaxPacketSize; + hid_handler.poll = puhost->dev_prop.cfg_desc_set.itf_desc_set[puhost->dev_prop.cur_itf][0].ep_desc[0].bInterval; + + if (hid_handler.poll < HID_MIN_POLL) { + hid_handler.poll = HID_MIN_POLL; + } + + /* check for available number of endpoints */ + /* find the number of endpoints in the interface descriptor */ + /* choose the lower number in order not to overrun the buffer allocated */ + ep_num = USB_MIN(puhost->dev_prop.cfg_desc_set.itf_desc_set[puhost->dev_prop.cur_itf][0].itf_desc.bNumEndpoints, USBH_MAX_EP_NUM); + + /* decode endpoint IN and OUT address from interface descriptor */ + for (num = 0U; num < ep_num; num++) { + usb_desc_ep *ep_desc = &puhost->dev_prop.cfg_desc_set.itf_desc_set[puhost->dev_prop.cur_itf][0].ep_desc[num]; + + uint8_t ep_addr = ep_desc->bEndpointAddress; + + if (ep_addr & 0x80U) { + hid_handler.ep_in = ep_addr; + hid_handler.pipe_in = usbh_pipe_allocate (puhost->data, ep_addr); + + /* open channel for IN endpoint */ + usbh_pipe_create (puhost->data, + &puhost->dev_prop, + hid_handler.pipe_in, + USB_EPTYPE_INTR, + hid_handler.len); + + usbh_pipe_toggle_set(puhost->data, hid_handler.pipe_in, 0U); + } else { + hid_handler.ep_out = ep_addr; + hid_handler.pipe_out = usbh_pipe_allocate (puhost->data, ep_addr); + + /* open channel for OUT endpoint */ + usbh_pipe_create (puhost->data, + &puhost->dev_prop, + hid_handler.pipe_out, + USB_EPTYPE_INTR, + hid_handler.len); + + usbh_pipe_toggle_set(puhost->data, hid_handler.pipe_out, 0U); + } + } + + puhost->active_class->class_data = (void *)&hid_handler; + + status = USBH_OK; + } + + return status; +} + +/*! + \brief handle HID class requests for HID class + \param[in] puhost: pointer to usb host + \param[out] none + \retval operation status +*/ +static usbh_status usbh_hid_class_req (usbh_host *puhost) +{ + usbh_status status = USBH_BUSY; + usbh_status class_req_status = USBH_BUSY; + + usbh_hid_handler *hid = (usbh_hid_handler *)puhost->active_class->class_data; + + /* handle HID control state machine */ + switch (hid->ctl_state) { + case HID_REQ_INIT: + case HID_REQ_GET_HID_DESC: + /* get HID descriptor */ + if (USBH_OK == usbh_hid_desc_get (puhost, USB_HID_DESC_SIZE)) { + usbh_hiddesc_parse(&hid->hid_desc, puhost->dev_prop.data); + + hid->ctl_state = HID_REQ_GET_REPORT_DESC; + } + break; + + case HID_REQ_GET_REPORT_DESC: + /* get report descriptor */ + if (USBH_OK == usbh_hid_reportdesc_get(puhost, hid->hid_desc.wDescriptorLength)) { + hid->ctl_state = HID_REQ_SET_IDLE; + } + break; + + case HID_REQ_SET_IDLE: + class_req_status = usbh_set_idle (puhost, 0U, 0U); + + /* set idle */ + if (USBH_OK == class_req_status) { + hid->ctl_state = HID_REQ_SET_PROTOCOL; + } else { + if(USBH_NOT_SUPPORTED == class_req_status) { + hid->ctl_state = HID_REQ_SET_PROTOCOL; + } + } + break; + + case HID_REQ_SET_PROTOCOL: + /* set protocol */ + if (USBH_OK == usbh_set_protocol (puhost, 0U)) { + hid->ctl_state = HID_REQ_IDLE; + + /* all requests performed */ + status = USBH_OK; + } + break; + + case HID_REQ_IDLE: + default: + break; + } + + return status; +} + +/*! + \brief manage state machine for HID data transfers + \param[in] puhost: pointer to usb host + \param[out] none + \retval operation status +*/ +static usbh_status usbh_hid_handle (usbh_host *puhost) +{ + usbh_status status = USBH_OK; + usbh_hid_handler *hid = (usbh_hid_handler *)puhost->active_class->class_data; + + switch (hid->state) { + case HID_INIT: + hid->init(puhost->data, puhost); + hid->state = HID_IDLE; + break; + + case HID_IDLE: + hid->state = HID_SYNC; + status = USBH_OK; + break; + + case HID_SYNC: + /* sync with start of even frame */ + if (true == usb_frame_even(puhost->data)) { + hid->state = HID_GET_DATA; + } + break; + + case HID_GET_DATA: + usbh_data_recev (puhost->data, hid->pdata, hid->pipe_in, hid->len); + + hid->state = HID_POLL; + hid->timer = usb_curframe_get (puhost->data); + hid->data_ready = 0U; + break; + + case HID_POLL: + if (URB_DONE == usbh_urbstate_get (puhost->data, hid->pipe_in)) { + if (0U == hid->data_ready) { /* handle data once */ + usbh_hid_fifo_write(&hid->fifo, hid->pdata, hid->len); + hid->data_ready = 1U; + + hid->machine(puhost->data, puhost); + } + } else { + if (URB_STALL == usbh_urbstate_get (puhost->data, hid->pipe_in)) { /* IN endpoint stalled */ + /* issue clear feature on interrupt in endpoint */ + if (USBH_OK == (usbh_clrfeature (puhost, hid->ep_addr, hid->pipe_in))) { + /* change state to issue next in token */ + hid->state = HID_GET_DATA; + } + } + } + break; + + default: + break; + } + return status; +} + +/*! + \brief send get report descriptor command to the device + \param[in] puhost: pointer to usb host + \param[in] len: HID report descriptor length + \param[out] none + \retval operation status +*/ +static usbh_status usbh_hid_reportdesc_get (usbh_host *puhost, uint16_t len) +{ + usbh_status status = USBH_BUSY; + + if (CTL_IDLE == puhost->control.ctl_state) { + puhost->control.setup.req = (usb_req) { + .bmRequestType = USB_TRX_IN | USB_RECPTYPE_ITF | USB_REQTYPE_STRD, + .bRequest = USB_GET_DESCRIPTOR, + .wValue = USBH_DESC(USB_DESCTYPE_REPORT), + .wIndex = 0U, + .wLength = len + }; + + usbh_ctlstate_config (puhost, puhost->dev_prop.data, len); + } + + status = usbh_ctl_handler (puhost); + + return status; +} + +/*! + \brief managing the SOF process + \param[in] puhost: pointer to usb host + \param[out] none + \retval operation status +*/ +static usbh_status usbh_hid_sof(usbh_host *puhost) +{ + usbh_hid_handler *hid = (usbh_hid_handler *)puhost->active_class->class_data; + + if (HID_POLL == hid->state) { + uint32_t frame_count = usb_curframe_get (puhost->data); + + if ((frame_count > hid->timer) && ((frame_count - hid->timer) >= hid->poll)) { + hid->state = HID_GET_DATA; + } else if ((frame_count < hid->timer) && ((frame_count + 0x3FFFU - hid->timer) >= hid->poll)) { + hid->state = HID_GET_DATA; + } else { + /* no operation */ + } + } + + return USBH_OK; +} + +/*! + \brief send the command of get HID descriptor to the device + \param[in] puhost: pointer to usb host + \param[in] len: HID descriptor length + \param[out] none + \retval operation status +*/ +static usbh_status usbh_hid_desc_get (usbh_host *puhost, uint16_t len) +{ + usbh_status status = USBH_BUSY; + + if (CTL_IDLE == puhost->control.ctl_state) { + puhost->control.setup.req = (usb_req) { + .bmRequestType = USB_TRX_IN | USB_RECPTYPE_ITF | USB_REQTYPE_STRD, + .bRequest = USB_GET_DESCRIPTOR, + .wValue = USBH_DESC(USB_DESCTYPE_HID), + .wIndex = 0U, + .wLength = len + }; + + usbh_ctlstate_config (puhost, puhost->dev_prop.data, len); + } + + status = usbh_ctl_handler (puhost); + + return status; +} + +/*! + \brief set idle state + \param[in] puhost: pointer to usb host + \param[in] duration: duration for HID set idle request + \param[in] report_ID: targeted report ID for HID set idle request + \param[out] none + \retval operation status +*/ +static usbh_status usbh_set_idle (usbh_host *puhost, uint8_t duration, uint8_t report_ID) +{ + usbh_status status = USBH_BUSY; + + if (CTL_IDLE == puhost->control.ctl_state) { + puhost->control.setup.req = (usb_req) { + .bmRequestType = USB_TRX_OUT | USB_RECPTYPE_ITF | USB_REQTYPE_CLASS, + .bRequest = SET_IDLE, + .wValue = (duration << 8U) | report_ID, + .wIndex = 0U, + .wLength = 0U + }; + + usbh_ctlstate_config (puhost, NULL, 0U); + } + + status = usbh_ctl_handler (puhost); + + return status; +} + +/*! + \brief set protocol state + \param[in] puhost: pointer to usb host + \param[in] protocol: boot/report protocol + \param[out] none + \retval operation status +*/ +static usbh_status usbh_set_protocol (usbh_host *puhost, uint8_t protocol) +{ + usbh_status status = USBH_BUSY; + + if (CTL_IDLE == puhost->control.ctl_state) { + puhost->control.setup.req = (usb_req) { + .bmRequestType = USB_TRX_OUT | USB_RECPTYPE_ITF | USB_REQTYPE_CLASS, + .bRequest = SET_PROTOCOL, + .wValue = !protocol, + .wIndex = 0U, + .wLength = 0U + }; + + usbh_ctlstate_config (puhost, NULL, 0U); + } + + status = usbh_ctl_handler (puhost); + + return status; +} + +/*! + \brief parse the HID descriptor + \param[in] hid_desc: pointer to HID descriptor + \param[in] buf: pointer to buffer where the source descriptor is available + \param[out] none + \retval none +*/ +static void usbh_hiddesc_parse (usb_desc_hid *hid_desc, uint8_t *buf) +{ + hid_desc->header.bLength = *(uint8_t *)(buf + 0U); + hid_desc->header.bDescriptorType = *(uint8_t *)(buf + 1U); + hid_desc->bcdHID = BYTE_SWAP(buf + 2U); + hid_desc->bCountryCode = *(uint8_t *)(buf + 4U); + hid_desc->bNumDescriptors = *(uint8_t *)(buf + 5U); + hid_desc->bDescriptorType = *(uint8_t *)(buf + 6U); + hid_desc->wDescriptorLength = BYTE_SWAP(buf + 7U); +} diff --git a/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/host/class/hid/Source/usbh_hid_keybd.c b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/host/class/hid/Source/usbh_hid_keybd.c new file mode 100644 index 0000000000..b32b8aef7e --- /dev/null +++ b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/host/class/hid/Source/usbh_hid_keybd.c @@ -0,0 +1,399 @@ +/*! + \file usbh_hid_keybd.c + \brief USB host HID keyboard driver + + \version 2020-08-01, V3.0.0, firmware for GD32F30x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "usbh_hid_keybd.h" +#include "usbh_hid_parser.h" +#include + +hid_keybd_info keybd_info; + +uint32_t keybd_report_data[2]; + +static const hid_report_item imp_0_lctrl = +{ + (uint8_t*)(void *)keybd_report_data + 0, /* data */ + 1, /* size */ + 0, /* shift */ + 0, /* count (only for array items) */ + 0, /* signed */ + 0, /* min value read can return */ + 1, /* max value read can return */ + 0, /* min vale device can report */ + 1, /* max value device can report */ + 1 /* resolution */ +}; + +static const hid_report_item imp_0_lshift = +{ + (uint8_t*)(void *)keybd_report_data + 0, /* data */ + 1, /* size */ + 1, /* shift */ + 0, /* count (only for array items) */ + 0, /* signed */ + 0, /* min value read can return */ + 1, /* max value read can return */ + 0, /* min vale device can report */ + 1, /* max value device can report */ + 1 /* resolution */ +}; + +static const hid_report_item imp_0_lalt = +{ + (uint8_t*)(void *)keybd_report_data + 0, /* data */ + 1, /* size */ + 2, /* shift */ + 0, /* count (only for array items) */ + 0, /* signed */ + 0, /* min value read can return */ + 1, /* max value read can return */ + 0, /* min vale device can report */ + 1, /* max value device can report */ + 1 /* resolution */ +}; + +static const hid_report_item imp_0_lgui = +{ + (uint8_t*)(void *)keybd_report_data + 0, /* data */ + 1, /* size */ + 3, /* shift */ + 0, /* count (only for array items) */ + 0, /* signed */ + 0, /* min value read can return */ + 1, /* max value read can return */ + 0, /* min vale device can report */ + 1, /* max value device can report */ + 1 /* resolution */ +}; + +static const hid_report_item imp_0_rctrl = +{ + (uint8_t*)(void *)keybd_report_data + 0, /* data */ + 1, /* size */ + 4, /* shift */ + 0, /* count (only for array items) */ + 0, /* signed */ + 0, /* min value read can return */ + 1, /* max value read can return */ + 0, /* min vale device can report */ + 1, /* max value device can report */ + 1 /* resolution */ +}; + +static const hid_report_item imp_0_rshift = +{ + (uint8_t*)(void *)keybd_report_data + 0, /* data */ + 1, /* size */ + 5, /* shift */ + 0, /* count (only for array items) */ + 0, /* signed */ + 0, /* min value read can return */ + 1, /* max value read can return */ + 0, /* min vale device can report */ + 1, /* max value device can report */ + 1 /* resolution */ +}; + +static const hid_report_item imp_0_ralt = +{ + (uint8_t*)(void *)keybd_report_data + 0, /* data */ + 1, /* size */ + 6, /* shift */ + 0, /* count (only for array items) */ + 0, /* signed */ + 0, /* min value read can return */ + 1, /* max value read can return */ + 0, /* min vale device can report */ + 1, /* max value device can report */ + 1 /* resolution */ +}; + +static const hid_report_item imp_0_rgui = +{ + (uint8_t*)(void *)keybd_report_data + 0, /* data */ + 1, /* size */ + 7, /* shift */ + 0, /* count (only for array items) */ + 0, /* signed */ + 0, /* min value read can return */ + 1, /* max value read can return */ + 0, /* min vale device can report */ + 1, /* max value device can report */ + 1 /* resolution */ +}; + +static const hid_report_item imp_0_key_array = +{ + (uint8_t*)(void *)keybd_report_data + 2, /* data */ + 8, /* size */ + 0, /* shift */ + 6, /* count (only for array items) */ + 0, /* signed */ + 0, /* min value read can return */ + 101, /* max value read can return */ + 0, /* min vale device can report */ + 101, /* max value device can report */ + 1 /* resolution */ +}; + +/* local constants */ +static const uint8_t hid_keybrd_codes[] = +{ + 0, 0, 0, 0, 31, 50, 48, 33, + 19, 34, 35, 36, 24, 37, 38, 39, /* 0x00 - 0x0F */ + 52, 51, 25, 26, 17, 20, 32, 21, + 23, 49, 18, 47, 22, 46, 2, 3, /* 0x10 - 0x1F */ + 4, 5, 6, 7, 8, 9, 10, 11, + 43, 110, 15, 16, 61, 12, 13, 27, /* 0x20 - 0x2F */ + 28, 29, 42, 40, 41, 1, 53, 54, + 55, 30, 112, 113, 114, 115, 116, 117, /* 0x30 - 0x3F */ + 118, 119, 120, 121, 122, 123, 124, 125, + 126, 75, 80, 85, 76, 81, 86, 89, /* 0x40 - 0x4F */ + 79, 84, 83, 90, 95, 100, 105, 106, + 108, 93, 98, 103, 92, 97, 102, 91, /* 0x50 - 0x5F */ + 96, 101, 99, 104, 45, 129, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, /* 0x60 - 0x6F */ + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, /* 0x70 - 0x7F */ + 0, 0, 0, 0, 0, 107, 0, 56, + 0, 0, 0, 0, 0, 0, 0, 0, /* 0x80 - 0x8F */ + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, /* 0x90 - 0x9F */ + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, /* 0xA0 - 0xAF */ + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, /* 0xB0 - 0xBF */ + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, /* 0xC0 - 0xCF */ + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, /* 0xD0 - 0xDF */ + 58, 44, 60, 127, 64, 57, 62, 128 /* 0xE0 - 0xE7 */ +}; + +#ifdef QWERTY_KEYBOARD + +static const int8_t hid_keybrd_key[] = +{ + '\0', '`', '1', '2', '3', '4', '5', '6', + '7', '8', '9', '0', '-', '=', '\0', '\r', + '\t', 'q', 'w', 'e', 'r', 't', 'y', 'u', + 'i', 'o', 'p', '[', ']', '\\', + '\0', 'a', 's', 'd', 'f', 'g', 'h', 'j', + 'k', 'l', ';', '\'', '\0', '\n', + '\0', '\0', 'z', 'x', 'c', 'v', 'b', 'n', + 'm', ',', '.', '/', '\0', '\0', + '\0', '\0', '\0', ' ', '\0', '\0', '\0', '\0', + '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', + '\0', '\0', '\0', '\0', '\0', '\r', '\0', '\0', + '\0', '\0', '\0', '\0', '\0', '\0', + '\0', '\0', '7', '4', '1', + '\0', '/', '8', '5', '2', + '0', '*', '9', '6', '3', + '.', '-', '+', '\0', '\n', '\0', '\0', '\0', '\0', '\0', '\0', + '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', + '\0', '\0', '\0', '\0' +}; + +static const int8_t hid_keybrd_shiftkey[] = { + '\0', '~', '!', '@', '#', '$', '%', '^', '&', '*', '(', ')', + '_', '+', '\0', '\0', '\0', 'Q', 'W', 'E', 'R', 'T', 'Y', 'U', + 'I', 'O', 'P', '{', '}', '|', '\0', 'A', 'S', 'D', 'F', 'G', + 'H', 'J', 'K', 'L', ':', '"', '\0', '\n', '\0', '\0', 'Z', 'X', + 'C', 'V', 'B', 'N', 'M', '<', '>', '?', '\0', '\0', '\0', '\0', + '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', + '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', + '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', + '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', + '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', + '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0' +}; + +#else + +static const int8_t hid_keybrd_key[] = { + '\0', '`', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', + '-', '=', '\0', '\r', '\t', 'a', 'z', 'e', 'r', 't', 'y', 'u', + 'i', 'o', 'p', '[', ']', '\\', '\0', 'q', 's', 'd', 'f', 'g', + 'h', 'j', 'k', 'l', 'm', '\0', '\0', '\n', '\0', '\0', 'w', 'x', + 'c', 'v', 'b', 'n', ',', ';', ':', '!', '\0', '\0', '\0', '\0', + '\0', ' ', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', + '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\r', '\0', '\0', '\0', + '\0', '\0', '\0', '\0', '\0', '\0', '\0', '7', '4', '1', '\0', '/', + '8', '5', '2', '0', '*', '9', '6', '3', '.', '-', '+', '\0', + '\n', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', + '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0' +}; + +static const int8_t hid_keybrd_shiftkey[] = { + '\0', '~', '!', '@', '#', '$', '%', '^', '&', '*', '(', ')', '_', + '+', '\0', '\0', '\0', 'A', 'Z', 'E', 'R', 'T', 'Y', 'U', 'I', 'O', + 'P', '{', '}', '*', '\0', 'Q', 'S', 'D', 'F', 'G', 'H', 'J', 'K', + 'L', 'M', '%', '\0', '\n', '\0', '\0', 'W', 'X', 'C', 'V', 'B', 'N', + '?', '.', '/', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', + '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', + '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', + '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', + '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', + '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0' +}; + +#endif + +/* local function prototypes ('static') */ +static usbh_status usbh_hid_keybrd_decode (usb_core_driver *pudev, usbh_host *puhost); + +/*! + \brief initialize the keyboard function + \param[in] pudev: pointer to usb core instance + \param[in] puhost: pointer to usb host + \param[out] none + \retval operation status +*/ +usbh_status usbh_hid_keybd_init (usb_core_driver *pudev, usbh_host *puhost) +{ + usbh_hid_handler *hid = (usbh_hid_handler *)puhost->active_class->class_data; + + keybd_info.lctrl = keybd_info.lshift = 0U; + keybd_info.lalt = keybd_info.lgui = 0U; + keybd_info.rctrl = keybd_info.rshift = 0U; + keybd_info.ralt = keybd_info.rgui = 0U; + + for (uint32_t x = 0U; x < (sizeof(keybd_report_data) / sizeof(uint32_t)); x++) { + keybd_report_data[x] = 0U; + } + + if (hid->len > (sizeof(keybd_report_data) / sizeof(uint32_t))) { + hid->len = (sizeof(keybd_report_data) / sizeof(uint32_t)); + } + + hid->pdata = (uint8_t*)(void *)keybd_report_data; + + usbh_hid_fifo_init (&hid->fifo, puhost->dev_prop.data, HID_QUEUE_SIZE * sizeof(keybd_report_data)); + + /* call user init*/ + USR_KEYBRD_Init(); + + return USBH_OK; +} + +/*! + \brief get keyboard information + \param[in] pudev: pointer to USB core instance + \param[in] puhost: pointer to USB host handler + \param[out] none + \retval keyboard information +*/ +hid_keybd_info *usbh_hid_keybd_info_get (usb_core_driver *pudev, usbh_host *puhost) +{ + if (USBH_OK == usbh_hid_keybrd_decode(pudev, puhost)) { + return &keybd_info; + } else { + return NULL; + } +} + +/*! + \brief get ascii code + \param[in] info: keyboard information + \param[out] none + \retval output +*/ +uint8_t usbh_hid_ascii_code_get (hid_keybd_info *info) +{ + uint8_t output; + if ((1U == info->lshift) || (info->rshift)) { + output = hid_keybrd_shiftkey[hid_keybrd_codes[info->keys[0]]]; + } else { + output = hid_keybrd_key[hid_keybrd_codes[info->keys[0]]]; + } + + return output; +} + +/*! + \brief decode the pressed keys + \param[in] pudev: pointer to usb core instance + \param[in] puhost: pointer to usb host + \param[out] none + \retval none +*/ +void usbh_hid_keybrd_machine (usb_core_driver *pudev, usbh_host *puhost) +{ + hid_keybd_info *k_pinfo; + + k_pinfo = usbh_hid_keybd_info_get(pudev, puhost); + + if (k_pinfo != NULL) { + char c = usbh_hid_ascii_code_get(k_pinfo); + + if (c != 0U) { + USR_KEYBRD_ProcessData(c); + } + } +} + +/*! + \brief decode keyboard information + \param[in] pudev: pointer to usb core instance + \param[in] puhost: pointer to usb host + \param[out] none + \retval operation status +*/ +static usbh_status usbh_hid_keybrd_decode (usb_core_driver *pudev, usbh_host *puhost) +{ + usbh_hid_handler *hid = (usbh_hid_handler *)puhost->active_class->class_data; + + if (hid->len == 0U) { + return USBH_FAIL; + } + + /* fill report */ + if (usbh_hid_fifo_read (&hid->fifo, &keybd_report_data, hid->len) == hid->len) { + keybd_info.lctrl = (uint8_t)hid_item_read((hid_report_item *)&imp_0_lctrl, 0U); + keybd_info.lshift = (uint8_t)hid_item_read((hid_report_item *)&imp_0_lshift, 0U); + keybd_info.lalt = (uint8_t)hid_item_read((hid_report_item *)&imp_0_lalt, 0U); + keybd_info.lgui = (uint8_t)hid_item_read((hid_report_item *)&imp_0_lgui, 0U); + keybd_info.rctrl = (uint8_t)hid_item_read((hid_report_item *)&imp_0_rctrl, 0U); + keybd_info.rshift = (uint8_t)hid_item_read((hid_report_item *)&imp_0_rshift, 0U); + keybd_info.ralt = (uint8_t)hid_item_read((hid_report_item *)&imp_0_ralt, 0U); + keybd_info.rgui = (uint8_t)hid_item_read((hid_report_item *)&imp_0_rgui, 0U); + + for (uint8_t x = 0U; x < sizeof(keybd_info.keys); x++) { + keybd_info.keys[x] = (uint8_t)hid_item_read((hid_report_item *)&imp_0_key_array, x); + } + + return USBH_OK; + } + + return USBH_FAIL; +} diff --git a/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/host/class/hid/Source/usbh_hid_mouse.c b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/host/class/hid/Source/usbh_hid_mouse.c new file mode 100644 index 0000000000..f684298df9 --- /dev/null +++ b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/host/class/hid/Source/usbh_hid_mouse.c @@ -0,0 +1,216 @@ +/*! + \file usbh_hid_mouse.c + \brief USB host HID mouse driver + + \version 2020-08-01, V3.0.0, firmware for GD32F30x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "usbh_hid_mouse.h" +#include "usbh_hid_parser.h" + +hid_mouse_info mouse_info; +uint32_t mouse_report_data[1]; + +/* structures defining how to access items in a hid mouse report */ +/* access button 1 state. */ +static const hid_report_item prop_b1 = +{ + (uint8_t *)(void *)mouse_report_data + 0, /* data */ + 1, /* size */ + 0, /* shift */ + 0, /* count (only for array items) */ + 0, /* signed? */ + 0, /* min value read can return */ + 1, /* max value read can return */ + 0, /* min value device can report */ + 1, /* max value device can report */ + 1 /* resolution */ +}; + +/* access button 2 state. */ +static const hid_report_item prop_b2 = +{ + (uint8_t *)(void *)mouse_report_data + 0, /* data */ + 1, /* size */ + 1, /* shift */ + 0, /* count (only for array items) */ + 0, /* signed? */ + 0, /* min value read can return */ + 1, /* max value read can return */ + 0, /* min value device can report */ + 1, /* max value device can report */ + 1 /* resolution */ +}; + +/* access button 3 state. */ +static const hid_report_item prop_b3 = +{ + (uint8_t *)(void *)mouse_report_data + 0, /* data */ + 1, /* size */ + 2, /* shift */ + 0, /* count (only for array items) */ + 0, /* signed? */ + 0, /* min value read can return */ + 1, /* max value read can return */ + 0, /* min vale device can report */ + 1, /* max value device can report */ + 1 /* resolution */ +}; + +/* access x coordinate change. */ +static const hid_report_item prop_x = +{ + (uint8_t *)(void *)mouse_report_data + 1, /* data */ + 8, /* size */ + 0, /* shift */ + 0, /* count (only for array items) */ + 1, /* signed? */ + 0, /* min value read can return */ + 0xFFFF,/* max value read can return */ + 0, /* min vale device can report */ + 0xFFFF,/* max value device can report */ + 1 /* resolution */ +}; + +/* access y coordinate change. */ +static const hid_report_item prop_y = +{ + (uint8_t *)(void *)mouse_report_data + 2, /* data */ + 8, /* size */ + 0, /* shift */ + 0, /* count (only for array items) */ + 1, /* signed? */ + 0, /* min value read can return */ + 0xFFFF,/* max value read can return */ + 0, /* min vale device can report */ + 0xFFFF,/* max value device can report */ + 1 /* resolution */ +}; + +/* local function prototypes ('static') */ +static usbh_status usbh_hid_mouse_decode(usb_core_driver *pudev, usbh_host *puhost); + +/*! + \brief initialize the mouse function + \param[in] pudev: pointer to usb core instance + \param[in] puhost: pointer to usb host + \param[out] none + \retval none +*/ +usbh_status usbh_hid_mouse_init (usb_core_driver *pudev, usbh_host *puhost) +{ + usbh_hid_handler *hid = (usbh_hid_handler *)puhost->active_class->class_data; + + mouse_info.x = 0U; + mouse_info.y = 0U; + mouse_info.buttons[0] = 0U; + mouse_info.buttons[1] = 0U; + mouse_info.buttons[2] = 0U; + + mouse_report_data[0] = 0U; + + if(hid->len > sizeof(mouse_report_data)) { + hid->len = sizeof(mouse_report_data); + } + + hid->pdata = (uint8_t *)(void *)mouse_report_data; + + usbh_hid_fifo_init(&hid->fifo, puhost->dev_prop.data, HID_QUEUE_SIZE * sizeof(mouse_report_data)); + + USR_MOUSE_Init(); + + return USBH_OK; +} + +/*! + \brief get mouse information + \param[in] pudev: pointer to usb core instance + \param[in] puhost: pointer to usb host + \param[out] none + \retval mouse information +*/ +hid_mouse_info *usbh_hid_mouse_info_get (usb_core_driver *pudev, usbh_host *puhost) +{ + if(usbh_hid_mouse_decode(pudev, puhost)== USBH_OK) { + return &mouse_info; + } else { + return NULL; + } +} + +/*! + \brief decode mouse data + \param[in] pudev: pointer to usb core instance + \param[in] puhost: pointer to usb host + \param[out] none + \retval none +*/ +void usbh_hid_mouse_machine (usb_core_driver *pudev, usbh_host *puhost) +{ + hid_mouse_info *m_pinfo = NULL; + + m_pinfo = usbh_hid_mouse_info_get(pudev, puhost); + + if (NULL != m_pinfo) { + /* handle mouse data position */ + USR_MOUSE_ProcessData(&mouse_info); + } +} + +/*! + \brief decode mouse information + \param[in] pudev: pointer to usb core instance + \param[in] puhost: pointer to usb host + \param[out] none + \retval operation status +*/ +static usbh_status usbh_hid_mouse_decode(usb_core_driver *pudev, usbh_host *puhost) +{ + usbh_hid_handler *hid = (usbh_hid_handler *)puhost->active_class->class_data; + + if (0U == hid->len) { + return USBH_FAIL; + } + + /* fill report */ + if (usbh_hid_fifo_read(&hid->fifo, &mouse_report_data, hid->len) == hid->len) { + /* decode report */ + mouse_info.x = (uint8_t)hid_item_read((hid_report_item *)&prop_x, 0U); + mouse_info.y = (uint8_t)hid_item_read((hid_report_item *)&prop_y, 0U); + + mouse_info.buttons[0] = (uint8_t)hid_item_read((hid_report_item *)&prop_b1, 0U); + mouse_info.buttons[1] = (uint8_t)hid_item_read((hid_report_item *)&prop_b2, 0U); + mouse_info.buttons[2] = (uint8_t)hid_item_read((hid_report_item *)&prop_b3, 0U); + + return USBH_OK; + } + + return USBH_FAIL; +} diff --git a/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/host/class/hid/Source/usbh_hid_parser.c b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/host/class/hid/Source/usbh_hid_parser.c new file mode 100644 index 0000000000..04d09567ce --- /dev/null +++ b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/host/class/hid/Source/usbh_hid_parser.c @@ -0,0 +1,148 @@ +/*! + \file usbh_hid_parser.c + \brief USB host HID parser driver + + \version 2020-08-01, V3.0.0, firmware for GD32F30x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "usbh_hid_parser.h" + +/*! + \brief read a hid report item + \param[in] ri: pointer to report item + \param[in] ndx: report index + \param[out] none + \retval operation status (0: fail otherwise: item value) +*/ +uint32_t hid_item_read (hid_report_item *ri, uint8_t ndx) +{ + uint32_t val = 0U; + uint32_t bofs = 0U; + uint8_t *data = ri->data; + uint8_t shift = ri->shift; + + /* get the logical value of the item */ + + /* if this is an array, wee may need to offset ri->data.*/ + if (ri->count > 0U) { + /* if app tries to read outside of the array. */ + if (ri->count <= ndx) { + return(0U); + } + + /* calculate bit offset */ + bofs = ndx * ri->size; + bofs += shift; + + /* calculate byte offset + shift pair from bit offset. */ + data += bofs / 8U; + shift = (uint8_t)(bofs % 8U); + } + + /* read data bytes in little endian order */ + for (uint32_t x = 0U; x < ((ri->size & 0x7U) ? (ri->size / 8U) + 1U : (ri->size / 8U)); x++) { + val=(uint32_t)((uint32_t)(*data) << (x * 8U)); + } + + val=(val >> shift) & ((1U << ri->size) - 1U); + + if ((val < ri->logical_min) || (val > ri->logical_max)) { + return(0U); + } + + /* convert logical value to physical value */ + /* see if the number is negative or not. */ + if ((ri->sign) && (val & (1U << (ri->size - 1U)))) { + /* yes, so sign extend value to 32 bits. */ + uint32_t vs = (uint32_t)((0xffffffffU & ~((1U << (ri->size)) - 1U)) | val); + + if (1U == ri->resolution) { + return((uint32_t)vs); + } + return((uint32_t)(vs * ri->resolution)); + } else { + if (1U == ri->resolution) { + return(val); + } + + return (val * ri->resolution); + } +} + +/*! + \brief write a hid report item + \param[in] ri: pointer to report item + \param[in] value: the value to be write + \param[in] ndx: report index + \param[out] none + \retval operation status (1: fail 0: Ok) +*/ +uint32_t hid_item_write(hid_report_item *ri, uint32_t value, uint8_t ndx) +{ + uint32_t mask; + uint32_t bofs; + uint8_t *data = ri->data; + uint8_t shift = ri->shift; + + if ((value < ri->physical_min) || (value > ri->physical_max)) { + return(1U); + } + + /* if this is an array, wee may need to offset ri->data.*/ + if (ri->count > 0U) { + /* if app tries to read outside of the array. */ + if (ri->count >= ndx) { + return(0U); + } + + /* calculate bit offset */ + bofs = ndx * ri->size; + bofs += shift; + + /* calculate byte offset + shift pair from bit offset. */ + data += bofs / 8U; + shift = (uint8_t)(bofs % 8U); + } + + /* convert physical value to logical value. */ + if (1U != ri->resolution) { + value = value / ri->resolution; + } + + /* write logical value to report in little endian order. */ + mask = (1U << ri->size) - 1U; + value = (value & mask) << shift; + + for (uint32_t x = 0U; x < ((ri->size & 0x7U) ? (ri->size / 8U) + 1U : (ri->size / 8U)); x++) { + *(ri->data + x) = (uint8_t)((*(ri->data+x) & ~(mask>>(x* 8U))) | ((value >> (x * 8U)) & (mask >> (x * 8U)))); + } + + return 0U; +} diff --git a/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/host/class/msc/Include/usbh_msc_bbb.h b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/host/class/msc/Include/usbh_msc_bbb.h new file mode 100644 index 0000000000..75eea727b2 --- /dev/null +++ b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/host/class/msc/Include/usbh_msc_bbb.h @@ -0,0 +1,150 @@ +/*! + \file usbh_msc_bbb.h + \brief header file for usbh_msc_bbb.c + + \version 2020-08-01, V3.0.0, firmware for GD32F30x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef __USBH_MSC_BBB_H +#define __USBH_MSC_BBB_H + +#include "usbh_enum.h" +#include "msc_bbb.h" + +typedef union { + msc_bbb_cbw field; + + uint8_t CBWArray[31]; +}usbh_cbw_pkt; + +typedef union { + msc_bbb_csw field; + + uint8_t CSWArray[13]; +}usbh_csw_pkt; + +enum usbh_msc_state { + USBH_MSC_BOT_INIT_STATE = 0U, + USBH_MSC_BOT_RESET, + USBH_MSC_GET_MAX_LUN, + USBH_MSC_TEST_UNIT_READY, + USBH_MSC_READ_CAPACITY10, + USBH_MSC_MODE_SENSE6, + USBH_MSC_REQUEST_SENSE, + USBH_MSC_BOT_USB_TRANSFERS, + USBH_MSC_DEFAULT_APPLI_STATE, + USBH_MSC_CTRL_ERROR_STATE, + USBH_MSC_UNRECOVERED_STATE +}; + +typedef enum +{ + BOT_OK = 0U, + BOT_FAIL, + BOT_PHASE_ERROR, + BOT_BUSY +} bot_status; + +typedef enum +{ + BOT_CMD_IDLE = 0U, + BOT_CMD_SEND, + BOT_CMD_WAIT, +} bot_cmd_state; + +/* csw status definitions */ +typedef enum +{ + BOT_CSW_CMD_PASSED = 0U, + BOT_CSW_CMD_FAILED, + BOT_CSW_PHASE_ERROR, +} bot_csw_status; + +typedef enum +{ + BOT_SEND_CBW = 1U, + BOT_SEND_CBW_WAIT, + BOT_DATA_IN, + BOT_DATA_IN_WAIT, + BOT_DATA_OUT, + BOT_DATA_OUT_WAIT, + BOT_RECEIVE_CSW, + BOT_RECEIVE_CSW_WAIT, + BOT_ERROR_IN, + BOT_ERROR_OUT, + BOT_UNRECOVERED_ERROR +} bot_state; + +typedef struct +{ + uint8_t *pbuf; + uint32_t data[16]; + bot_state state; + bot_state prev_state; + bot_cmd_state cmd_state; + usbh_cbw_pkt cbw; + usbh_csw_pkt csw; +} bot_handle; + +#define USBH_MSC_BOT_CBW_TAG 0x20304050U + +#define USBH_MSC_CSW_MAX_LENGTH 63U + +#define USBH_MSC_SEND_CSW_DISABLE 0U +#define USBH_MSC_SEND_CSW_ENABLE 1U + +#define USBH_MSC_DIR_IN 0U +#define USBH_MSC_DIR_OUT 1U +#define USBH_MSC_BOTH_DIR 2U + +#define USBH_MSC_PAGE_LENGTH 512U + +#define CBW_CB_LENGTH 16U +#define CBW_LENGTH 10U +#define CBW_LENGTH_TEST_UNIT_READY 0U + +#define MAX_BULK_STALL_COUNT_LIMIT 0x04U /*!< If STALL is seen on Bulk + Endpoint continously, this means + that device and Host has phase error + Hence a Reset is needed */ + +/* function declarations */ +/* initialize the mass storage parameters */ +void usbh_msc_bot_init (usbh_host *puhost); +/* manage the different states of BOT transfer and updates the status to upper layer */ +usbh_status usbh_msc_bot_process (usbh_host *puhost, uint8_t lun); +/* manages the different error handling for stall */ +usbh_status usbh_msc_bot_abort (usbh_host *puhost, uint8_t direction); +/* reset msc bot request struct */ +usbh_status usbh_msc_bot_reset (usbh_host *puhost); +/* decode the CSW received by the device and updates the same to upper layer */ +bot_csw_status usbh_msc_csw_decode (usbh_host *puhost); + +#endif /* __USBH_MSC_BBB_H */ diff --git a/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/host/class/msc/Include/usbh_msc_core.h b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/host/class/msc/Include/usbh_msc_core.h new file mode 100644 index 0000000000..914aa44501 --- /dev/null +++ b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/host/class/msc/Include/usbh_msc_core.h @@ -0,0 +1,124 @@ +/*! + \file usbh_core.h + \brief header file for the usbh_core.c + + \version 2020-08-01, V3.0.0, firmware for GD32F30x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef __USBH_MSC_CORE_H +#define __USBH_MSC_CORE_H + +#include "usb_msc.h" +#include "usbh_msc_scsi.h" +#include "usbh_msc_bbb.h" + +#define MSC_MAX_SUPPORTED_LUN 2U + +typedef enum +{ + MSC_INIT = 0U, + MSC_IDLE, + MSC_TEST_UNIT_READY, + MSC_READ_CAPACITY10, + MSC_READ_INQUIRY, + MSC_REQUEST_SENSE, + MSC_READ, + MSC_WRITE, + MSC_UNRECOVERED_ERROR, + MSC_PERIODIC_CHECK, +} msc_state; + +typedef enum +{ + MSC_OK, + MSC_NOT_READY, + MSC_ERROR, +} msc_error; + +typedef enum +{ + MSC_REQ_IDLE = 0U, + MSC_REQ_RESET, + MSC_REQ_GET_MAX_LUN, + MSC_REQ_ERROR, +} msc_req_state; + +/* Structure for LUN */ +typedef struct +{ + msc_state state; + msc_error error; + msc_scsi_sense sense; + scsi_capacity capacity; + scsi_std_inquiry_data inquiry; + usbh_status prev_ready_state; + uint8_t state_changed; +} msc_lun; + +/* structure for msc process */ +typedef struct _msc_process +{ + uint8_t pipe_in; + uint8_t pipe_out; + uint8_t ep_in; + uint8_t ep_out; + uint16_t ep_size_in; + uint16_t ep_size_out; + uint8_t cur_lun; + uint16_t rw_lun; + uint32_t max_lun; + msc_state state; + msc_error error; + msc_req_state req_state; + msc_req_state prev_req_state; + bot_handle bot; + msc_lun unit[MSC_MAX_SUPPORTED_LUN]; + uint32_t timer; +} usbh_msc_handler; + +extern usbh_class usbh_msc; + +/* function declarations */ +/* get msc logic unit information */ +usbh_status usbh_msc_lun_info_get (usbh_host *puhost, uint8_t lun, msc_lun *info); +/* msc read interface */ +usbh_status usbh_msc_read (usbh_host *puhost, + uint8_t lun, + uint32_t address, + uint8_t *pbuf, + uint32_t length); +/* msc write interface */ +usbh_status usbh_msc_write (usbh_host *puhost, + uint8_t lun, + uint32_t address, + uint8_t *pbuf, + uint32_t length); + +#endif /* __USBH_MSC_CORE_H */ diff --git a/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/host/class/msc/Include/usbh_msc_scsi.h b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/host/class/msc/Include/usbh_msc_scsi.h new file mode 100644 index 0000000000..562adb24cb --- /dev/null +++ b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/host/class/msc/Include/usbh_msc_scsi.h @@ -0,0 +1,100 @@ +/*! + \file usbh_msc_scsi.h + \brief header file for usbh_msc_scsi.c + + \version 2020-08-01, V3.0.0, firmware for GD32F30x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef __USBH_MSC_SCSI_H +#define __USBH_MSC_SCSI_H + +#include "msc_scsi.h" +#include "usbh_enum.h" + +/* capacity data */ +typedef struct +{ + uint32_t block_nbr; + uint16_t block_size; +} scsi_capacity; + +/* inquiry data */ +typedef struct +{ + uint8_t peripheral_qualifier; + uint8_t device_type; + uint8_t removable_media; + uint8_t vendor_id[9]; + uint8_t product_id[17]; + uint8_t revision_id[5]; +} scsi_std_inquiry_data; + +typedef struct +{ + uint32_t msc_capacity; + uint32_t msc_sense_key; + uint16_t msc_page_len; + uint8_t msc_write_protect; +}usbh_msc_parameter; + +#define DESC_REQUEST_SENSE 0x00U +#define ALLOCATION_LENGTH_REQUEST_SENSE 63U +#define XFER_LEN_MODE_SENSE6 63U + +#define MASK_MODE_SENSE_WRITE_PROTECT 0x80U +#define MODE_SENSE_PAGE_CONTROL_FIELD 0x00U +#define MODE_SENSE_PAGE_CODE 0x3FU +#define DISK_WRITE_PROTECTED 0x01U + +/* function declarations */ +/* send 'Inquiry' command to the device */ +usbh_status usbh_msc_scsi_inquiry (usbh_host *puhost, uint8_t lun, scsi_std_inquiry_data *inquiry); +/* send 'Test unit ready' command to the device */ +usbh_status usbh_msc_test_unitready (usbh_host *puhost, uint8_t lun); +/* send the read capacity command to the device */ +usbh_status usbh_msc_read_capacity10 (usbh_host *puhost, uint8_t lun, scsi_capacity *capacity); +/* send the mode sense6 command to the device */ +usbh_status usbh_msc_mode_sense6 (usbh_host *puhost, uint8_t lun); +/* send the Request Sense command to the device */ +usbh_status usbh_msc_request_sense (usbh_host *puhost, uint8_t lun, msc_scsi_sense *sense_data); +/* send the write10 command to the device */ +usbh_status usbh_msc_write10 (usbh_host *puhost, + uint8_t lun, + uint8_t *data_buf, + uint32_t addr, + uint32_t byte_num); +/* send the read10 command to the device */ +usbh_status usbh_msc_read10 (usbh_host *puhost, + uint8_t lun, + uint8_t *data_buf, + uint32_t addr, + uint32_t byte_num); + +#endif /* __USBH_MSC_SCSI_H */ diff --git a/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/host/class/msc/Source/usbh_msc_bbb.c b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/host/class/msc/Source/usbh_msc_bbb.c new file mode 100644 index 0000000000..071a94bfc2 --- /dev/null +++ b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/host/class/msc/Source/usbh_msc_bbb.c @@ -0,0 +1,362 @@ +/*! + \file usbh_msc_bbb.c + \brief USB MSC BBB protocol related functions + + \version 2020-08-01, V3.0.0, firmware for GD32F30x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "usbh_pipe.h" +#include "usbh_msc_core.h" +#include "usbh_msc_scsi.h" +#include "usbh_msc_bbb.h" +#include "usbh_transc.h" +#include "drv_usbh_int.h" + +/*! + \brief initialize the mass storage parameters + \param[in] puhost: pointer to usb host handler + \param[out] none + \retval none +*/ +void usbh_msc_bot_init (usbh_host *puhost) +{ + usbh_msc_handler *msc = (usbh_msc_handler *)puhost->active_class->class_data; + + msc->bot.cbw.field.dCBWSignature = BBB_CBW_SIGNATURE; + msc->bot.cbw.field.dCBWTag = USBH_MSC_BOT_CBW_TAG; + msc->bot.state = BOT_SEND_CBW; + msc->bot.cmd_state = BOT_CMD_SEND; +} + +/*! + \brief manage the different states of BOT transfer and updates the status to upper layer + \param[in] puhost: pointer to usb host handler + \param[in] lun: logic unit number + \param[out] none + \retval operation status +*/ +usbh_status usbh_msc_bot_process (usbh_host *puhost, uint8_t lun) +{ + bot_csw_status csw_status = BOT_CSW_CMD_FAILED; + usbh_status status = USBH_BUSY; + usbh_status error = USBH_BUSY; + usb_urb_state urb_status = URB_IDLE; + usbh_msc_handler *msc = (usbh_msc_handler *)puhost->active_class->class_data; + + switch (msc->bot.state) { + case BOT_SEND_CBW: + msc->bot.cbw.field.bCBWLUN = lun; + msc->bot.state = BOT_SEND_CBW_WAIT; + /* send CBW */ + usbh_data_send (puhost->data, + msc->bot.cbw.CBWArray, + msc->pipe_out, + BBB_CBW_LENGTH); + break; + + case BOT_SEND_CBW_WAIT: + urb_status = usbh_urbstate_get(puhost->data, msc->pipe_out); + + if (URB_DONE == urb_status) { + if (0U != msc->bot.cbw.field.dCBWDataTransferLength) { + if (USB_TRX_IN == (msc->bot.cbw.field.bmCBWFlags & USB_TRX_MASK)) { + msc->bot.state = BOT_DATA_IN; + } else { + msc->bot.state = BOT_DATA_OUT; + } + } else { + msc->bot.state = BOT_RECEIVE_CSW; + } + + } else if (URB_NOTREADY == urb_status) { + msc->bot.state = BOT_SEND_CBW; + } else { + if (URB_STALL == urb_status) { + msc->bot.state = BOT_ERROR_OUT; + } + } + break; + + case BOT_DATA_IN: + usbh_data_recev (puhost->data, + msc->bot.pbuf, + msc->pipe_in, + msc->ep_size_in); + + msc->bot.state = BOT_DATA_IN_WAIT; + break; + + case BOT_DATA_IN_WAIT: + urb_status = usbh_urbstate_get(puhost->data, msc->pipe_in); + + /* BOT DATA IN stage */ + if (URB_DONE == urb_status) { + if (msc->bot.cbw.field.dCBWDataTransferLength > msc->ep_size_in) { + msc->bot.pbuf += msc->ep_size_in; + msc->bot.cbw.field.dCBWDataTransferLength -= msc->ep_size_in; + } else { + msc->bot.cbw.field.dCBWDataTransferLength = 0U; + } + + if (msc->bot.cbw.field.dCBWDataTransferLength > 0U) { + usbh_data_recev (puhost->data, + msc->bot.pbuf, + msc->pipe_in, + msc->ep_size_in); + } else { + msc->bot.state = BOT_RECEIVE_CSW; + } + } else if(URB_STALL == urb_status) { + /* this is data stage stall condition */ + msc->bot.state = BOT_ERROR_IN; + } else { + /* no operation */ + } + break; + + case BOT_DATA_OUT: + usbh_data_send (puhost->data, + msc->bot.pbuf, + msc->pipe_out, + msc->ep_size_out); + + msc->bot.state = BOT_DATA_OUT_WAIT; + break; + + case BOT_DATA_OUT_WAIT: + /* BOT DATA OUT stage */ + urb_status = usbh_urbstate_get(puhost->data, msc->pipe_out); + if (URB_DONE == urb_status) { + if (msc->bot.cbw.field.dCBWDataTransferLength > msc->ep_size_out) { + msc->bot.pbuf += msc->ep_size_out; + msc->bot.cbw.field.dCBWDataTransferLength -= msc->ep_size_out; + } else { + msc->bot.cbw.field.dCBWDataTransferLength = 0; /* reset this value and keep in same state */ + } + + if (msc->bot.cbw.field.dCBWDataTransferLength > 0) { + usbh_data_send (puhost->data, + msc->bot.pbuf, + msc->pipe_out, + msc->ep_size_out); + } else { + msc->bot.state = BOT_RECEIVE_CSW; + } + } else if (URB_NOTREADY == urb_status) { + msc->bot.state = BOT_DATA_OUT; + } else if (URB_STALL == urb_status) { + msc->bot.state = BOT_ERROR_OUT; + } else { + /* no operation */ + } + break; + + case BOT_RECEIVE_CSW: + /* BOT CSW stage */ + usbh_data_recev (puhost->data, + msc->bot.csw.CSWArray, + msc->pipe_in, + BBB_CSW_LENGTH); + + msc->bot.state = BOT_RECEIVE_CSW_WAIT; + break; + + case BOT_RECEIVE_CSW_WAIT: + urb_status = usbh_urbstate_get(puhost->data, msc->pipe_in); + + /* decode CSW */ + if (URB_DONE == urb_status) { + msc->bot.state = BOT_SEND_CBW; + msc->bot.cmd_state = BOT_CMD_SEND; + + csw_status = usbh_msc_csw_decode(puhost); + if (BOT_CSW_CMD_PASSED == csw_status) { + status = USBH_OK; + } else { + status = USBH_FAIL; + } + } else if (URB_STALL == urb_status) { + msc->bot.state = BOT_ERROR_IN; + } else { + /* no operation */ + } + break; + + case BOT_ERROR_IN: + error = usbh_msc_bot_abort(puhost, USBH_MSC_DIR_IN); + + if (USBH_OK == error) { + msc->bot.state = BOT_RECEIVE_CSW; + } else if (USBH_UNRECOVERED_ERROR == status) { + /* this means that there is a stall error limit, do reset recovery */ + msc->bot.state = BOT_UNRECOVERED_ERROR; + } else { + /* no operation */ + } + break; + + case BOT_ERROR_OUT: + status = usbh_msc_bot_abort (puhost, USBH_MSC_DIR_OUT); + + if (USBH_OK == status) { + uint8_t toggle = usbh_pipe_toggle_get(puhost->data, msc->pipe_out); + usbh_pipe_toggle_set(puhost->data, msc->pipe_out, 1U - toggle); + usbh_pipe_toggle_set(puhost->data, msc->pipe_in, 0U); + msc->bot.state = BOT_ERROR_IN; + } else { + if (USBH_UNRECOVERED_ERROR == status) { + msc->bot.state = BOT_UNRECOVERED_ERROR; + } + } + break; + + case BOT_UNRECOVERED_ERROR: + status = usbh_msc_bot_reset(puhost); + if (USBH_OK == status) { + msc->bot.state = BOT_SEND_CBW; + } + break; + + default: + break; + } + + return status; +} + +/*! + \brief manages the different error handling for stall + \param[in] puhost: pointer to usb host handler + \param[in] direction: data IN or OUT + \param[out] none + \retval operation status +*/ +usbh_status usbh_msc_bot_abort (usbh_host *puhost, uint8_t direction) +{ + usbh_status status = USBH_BUSY; + usbh_msc_handler *msc = (usbh_msc_handler *)puhost->active_class->class_data; + + switch (direction) { + case USBH_MSC_DIR_IN : + /* send clrfeture command on bulk IN endpoint */ + status = usbh_clrfeature(puhost, + msc->ep_in, + msc->pipe_in); + break; + + case USBH_MSC_DIR_OUT : + /*send clrfeature command on bulk OUT endpoint */ + status = usbh_clrfeature(puhost, + msc->ep_out, + msc->pipe_out); + break; + + default: + break; + } + + return status; +} + +/*! + \brief reset msc bot transfer + \param[in] puhost: pointer to usb host handler + \param[out] none + \retval operation status +*/ +usbh_status usbh_msc_bot_reset (usbh_host *puhost) +{ + usbh_status status = USBH_BUSY; + + if (CTL_IDLE == puhost->control.ctl_state) { + puhost->control.setup.req = (usb_req) { + .bmRequestType = USB_TRX_OUT | USB_REQTYPE_CLASS | USB_RECPTYPE_ITF, + .bRequest = BBB_RESET, + .wValue = 0U, + .wIndex = 0U, + .wLength = 0U + }; + + usbh_ctlstate_config (puhost, NULL, 0U); + } + + status = usbh_ctl_handler (puhost); + + return status; +} + +/*! + \brief decode the CSW received by the device and updates the same to upper layer + \param[in] puhost: pointer to usb host + \param[out] none + \retval on success USBH_MSC_OK, on failure USBH_MSC_FAIL + \notes + Refer to USB Mass-Storage Class: BOT (www.usb.org) + 6.3.1 Valid CSW Conditions : + The host shall consider the CSW valid when: + 1. dCSWSignature is equal to 53425355h + 2. the CSW is 13 (Dh) bytes in length, + 3. dCSWTag matches the dCBWTag from the corresponding CBW. +*/ +bot_csw_status usbh_msc_csw_decode (usbh_host *puhost) +{ + bot_csw_status status = BOT_CSW_CMD_FAILED; + usbh_msc_handler *msc = (usbh_msc_handler *)puhost->active_class->class_data; + + /* checking if the transfer length is different than 13 */ + if (BBB_CSW_LENGTH != usbh_xfercount_get (puhost->data, msc->pipe_in)) { + status = BOT_CSW_PHASE_ERROR; + } else { + /* CSW length is correct */ + + /* check validity of the CSW Signature and CSWStatus */ + if (BBB_CSW_SIGNATURE == msc->bot.csw.field.dCSWSignature) { + /* check condition 1. dCSWSignature is equal to 53425355h */ + if (msc->bot.csw.field.dCSWTag == msc->bot.cbw.field.dCBWTag) { + /* check condition 3. dCSWTag matches the dCBWTag from the corresponding CBW */ + if (0U == msc->bot.csw.field.bCSWStatus) { + status = BOT_CSW_CMD_PASSED; + } else if (1U == msc->bot.csw.field.bCSWStatus) { + status = BOT_CSW_CMD_FAILED; + } else if (2U == msc->bot.csw.field.bCSWStatus) { + status = BOT_CSW_PHASE_ERROR; + } else { + /* no operation */ + } + } + } else { + /* If the CSW signature is not valid, we will return the phase error to + upper layers for reset recovery */ + status = BOT_CSW_PHASE_ERROR; + } + } + + return status; +} diff --git a/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/host/class/msc/Source/usbh_msc_core.c b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/host/class/msc/Source/usbh_msc_core.c new file mode 100644 index 0000000000..53c9c84882 --- /dev/null +++ b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/host/class/msc/Source/usbh_msc_core.c @@ -0,0 +1,561 @@ +/*! + \file usbh_core.c + \brief USB MSC(mass storage device) class driver + + \version 2020-08-01, V3.0.0, firmware for GD32F30x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "usbh_msc_core.h" +#include "usbh_msc_scsi.h" +#include "usbh_msc_bbb.h" +#include "usbh_pipe.h" +#include "usbh_transc.h" +#include +#include + +/* local function prototypes ('static') */ +static void usbh_msc_itf_deinit (usbh_host *puhost); +static usbh_status usbh_msc_itf_init (usbh_host *puhost); +static usbh_status usbh_msc_req (usbh_host *puhost); +static usbh_status usbh_msc_handle (usbh_host *puhost); +static usbh_status usbh_msc_maxlun_get (usbh_host *puhost, uint8_t *maxlun); +static usbh_status usbh_msc_rdwr_process(usbh_host *puhost, uint8_t lun); + +usbh_class usbh_msc = +{ + USB_CLASS_MSC, + usbh_msc_itf_init, + usbh_msc_itf_deinit, + usbh_msc_req, + usbh_msc_handle, +}; + +/*! + \brief interface initialization for MSC class + \param[in] puhost: pointer to usb host + \param[out] none + \retval operation status +*/ +static usbh_status usbh_msc_itf_init (usbh_host *puhost) +{ + usbh_status status = USBH_OK; + + uint8_t interface = usbh_interface_find(&puhost->dev_prop, MSC_CLASS, USB_MSC_SUBCLASS_SCSI, MSC_PROTOCOL); + + if (0xFFU == interface) { + puhost->usr_cb->dev_not_supported(); + + status = USBH_FAIL; + } else { + static usbh_msc_handler msc_handler; + + memset((void*)&msc_handler, 0, sizeof(usbh_msc_handler)); + + puhost->active_class->class_data = (void *)&msc_handler; + + usbh_interface_select(&puhost->dev_prop, interface); + + usb_desc_ep *ep_desc = &puhost->dev_prop.cfg_desc_set.itf_desc_set[interface][0].ep_desc[0]; + + if (ep_desc->bEndpointAddress & 0x80) { + msc_handler.ep_in = ep_desc->bEndpointAddress; + msc_handler.ep_size_in = ep_desc->wMaxPacketSize; + } else { + msc_handler.ep_out = ep_desc->bEndpointAddress; + msc_handler.ep_size_out = ep_desc->wMaxPacketSize; + } + + ep_desc = &puhost->dev_prop.cfg_desc_set.itf_desc_set[interface][0].ep_desc[1]; + + if (ep_desc->bEndpointAddress & 0x80) { + msc_handler.ep_in = ep_desc->bEndpointAddress; + msc_handler.ep_size_in = ep_desc->wMaxPacketSize; + } else { + msc_handler.ep_out = ep_desc->bEndpointAddress; + msc_handler.ep_size_out = ep_desc->wMaxPacketSize; + } + + msc_handler.state = MSC_INIT; + msc_handler.error = MSC_OK; + msc_handler.req_state = MSC_REQ_IDLE; + msc_handler.pipe_out = usbh_pipe_allocate(puhost->data, msc_handler.ep_out); + msc_handler.pipe_in = usbh_pipe_allocate(puhost->data, msc_handler.ep_in); + + usbh_msc_bot_init(puhost); + + /* open the new channels */ + usbh_pipe_create (puhost->data, + &puhost->dev_prop, + msc_handler.pipe_out, + USB_EPTYPE_BULK, + msc_handler.ep_size_out); + + usbh_pipe_create (puhost->data, + &puhost->dev_prop, + msc_handler.pipe_in, + USB_EPTYPE_BULK, + msc_handler.ep_size_in); + + usbh_pipe_toggle_set (puhost->data, msc_handler.pipe_out, 0U); + usbh_pipe_toggle_set (puhost->data, msc_handler.pipe_in, 0U); + } + + return status; +} + +/*! + \brief de-initialize interface by freeing host channels allocated to interface + \param[in] puhost: pointer to usb host + \param[out] none + \retval operation status +*/ +void usbh_msc_itf_deinit (usbh_host *puhost) +{ + usbh_msc_handler *msc = (usbh_msc_handler *)puhost->active_class->class_data; + + if (msc->pipe_out) { + usb_pipe_halt (puhost->data, msc->pipe_out); + usbh_pipe_free (puhost->data, msc->pipe_out); + + msc->pipe_out = 0U; + } + + if (msc->pipe_in) { + usb_pipe_halt (puhost->data, msc->pipe_in); + usbh_pipe_free (puhost->data, msc->pipe_in); + + msc->pipe_in = 0U; + } +} + +/*! + \brief initialize the MSC state machine + \param[in] puhost: pointer to usb host + \param[out] none + \retval operation status +*/ +static usbh_status usbh_msc_req (usbh_host *puhost) +{ + usbh_status status = USBH_BUSY; + usbh_msc_handler *msc = (usbh_msc_handler *)puhost->active_class->class_data; + + switch (msc->req_state) { + case MSC_REQ_IDLE: + case MSC_REQ_GET_MAX_LUN: + /* issue Get_MaxLun request */ + status = usbh_msc_maxlun_get (puhost, (uint8_t *)&msc->max_lun); + + if (USBH_OK == status) { + msc->max_lun = ((uint8_t)msc->max_lun > MSC_MAX_SUPPORTED_LUN) ? MSC_MAX_SUPPORTED_LUN : (uint8_t)msc->max_lun + 1U; + + for (uint8_t i = 0U; i < msc->max_lun; i++) { + msc->unit[i].prev_ready_state = USBH_FAIL; + msc->unit[i].state_changed = 0U; + } + } else { + if (USBH_NOT_SUPPORTED == status) { + msc->max_lun = 0U; + status = USBH_OK; + } + } + break; + + case MSC_REQ_ERROR: + /* issue clear feature request */ + if (USBH_OK == usbh_clrfeature(puhost, 0x00U, puhost->control.pipe_out_num)) { + msc->req_state = msc->prev_req_state; + } + break; + + default: + break; + } + + return status; +} + +/*! + \brief MSC state machine handler + \param[in] puhost: pointer to usb host + \param[out] none + \retval operation status +*/ +static usbh_status usbh_msc_handle (usbh_host *puhost) +{ + usbh_status status = USBH_BUSY; + uint8_t scsi_status = USBH_BUSY; + uint8_t ready_status = USBH_BUSY; + usbh_msc_handler *msc = (usbh_msc_handler *)puhost->active_class->class_data; + + + switch (msc->state) { + case MSC_INIT: + if (msc->cur_lun < msc->max_lun) { + msc->unit[msc->cur_lun].error = MSC_NOT_READY; + + switch (msc->unit[msc->cur_lun].state) { + case MSC_INIT: + msc->unit[msc->cur_lun].state = MSC_READ_INQUIRY; + msc->timer = puhost->control.timer; + break; + + case MSC_READ_INQUIRY: + scsi_status = usbh_msc_scsi_inquiry(puhost, msc->cur_lun, &msc->unit[msc->cur_lun].inquiry); + + if (USBH_OK == scsi_status) { + msc->unit[msc->cur_lun].state = MSC_TEST_UNIT_READY; + } else if (scsi_status == USBH_FAIL) { + msc->unit[msc->cur_lun].state = MSC_REQUEST_SENSE; + } else { + if (scsi_status == USBH_UNRECOVERED_ERROR) { + msc->unit[msc->cur_lun].state = MSC_IDLE; + msc->unit[msc->cur_lun].error = MSC_ERROR; + } + } + break; + + case MSC_TEST_UNIT_READY: + /* issue SCSI command TestUnitReady */ + ready_status = usbh_msc_test_unitready(puhost, msc->cur_lun); + + if (USBH_OK == ready_status) { + if (USBH_OK != msc->unit[msc->cur_lun].prev_ready_state) { + msc->unit[msc->cur_lun].state_changed = 1U; + } else { + msc->unit[msc->cur_lun].state_changed = 0U; + } + + msc->unit[msc->cur_lun].state = MSC_READ_CAPACITY10; + msc->unit[msc->cur_lun].error = MSC_OK; + msc->unit[msc->cur_lun].prev_ready_state = USBH_OK; + } else if (USBH_FAIL == ready_status) { + if (USBH_FAIL != msc->unit[msc->cur_lun].prev_ready_state) { + msc->unit[msc->cur_lun].state_changed = 1U; + } else { + msc->unit[msc->cur_lun].state_changed = 0U; + } + + msc->unit[msc->cur_lun].state = MSC_REQUEST_SENSE; + msc->unit[msc->cur_lun].error = MSC_NOT_READY; + msc->unit[msc->cur_lun].prev_ready_state = USBH_FAIL; + } else { + if (USBH_UNRECOVERED_ERROR == ready_status) { + msc->unit[msc->cur_lun].state = MSC_IDLE; + msc->unit[msc->cur_lun].error = MSC_ERROR; + } + } + break; + + case MSC_READ_CAPACITY10: + /* issue READ_CAPACITY10 SCSI command */ + scsi_status = usbh_msc_read_capacity10(puhost, msc->cur_lun, &msc->unit[msc->cur_lun].capacity); + + if (USBH_OK == scsi_status) { + if (1U == msc->unit[msc->cur_lun].state_changed) { + } + msc->unit[msc->cur_lun].state = MSC_IDLE; + msc->unit[msc->cur_lun].error = MSC_OK; + msc->cur_lun ++; + } else if (USBH_FAIL == scsi_status) { + msc->unit[msc->cur_lun].state = MSC_REQUEST_SENSE; + } else { + if (USBH_UNRECOVERED_ERROR == scsi_status) { + msc->unit[msc->cur_lun].state = MSC_IDLE; + msc->unit[msc->cur_lun].error = MSC_ERROR; + } + } + break; + + case MSC_REQUEST_SENSE: + /* issue RequestSense SCSI command for recovering error code */ + scsi_status = usbh_msc_request_sense (puhost, msc->cur_lun, &msc->unit[msc->cur_lun].sense); + if (USBH_OK == scsi_status) { + if ((msc->unit[msc->cur_lun].sense.SenseKey == UNIT_ATTENTION) || (msc->unit[msc->cur_lun].sense.SenseKey == NOT_READY)) { + if (((puhost->control.timer > msc->timer) && ((puhost->control.timer - msc->timer) < 10000U)) \ + || ((puhost->control.timer < msc->timer) && ((puhost->control.timer + 0x3FFFU - msc->timer) < 10000U))){ + msc->unit[msc->cur_lun].state = MSC_TEST_UNIT_READY; + break; + } + } + + msc->unit[msc->cur_lun].state = MSC_IDLE; + msc->cur_lun++; + } else if (USBH_FAIL == scsi_status) { + msc->unit[msc->cur_lun].state = MSC_UNRECOVERED_ERROR; + } else { + if (MSC_UNRECOVERED_ERROR == scsi_status) { + msc->unit[msc->cur_lun].state = MSC_IDLE; + msc->unit[msc->cur_lun].error = MSC_ERROR; + } + } + break; + + case MSC_UNRECOVERED_ERROR: + msc->cur_lun ++; + break; + + default: + break; + } + } else { + msc->cur_lun = 0U; + msc->state = MSC_IDLE; + } + break; + + case MSC_IDLE: + puhost->usr_cb->dev_user_app(); + status = USBH_OK; + break; + + default: + break; + } + + return status; +} + +/*! + \brief get max lun of the mass storage device + \param[in] puhost: pointer to USB host + \param[in] maxlun: pointer to max lun + \param[out] none + \retval operation status +*/ +static usbh_status usbh_msc_maxlun_get (usbh_host *puhost, uint8_t *maxlun) +{ + usbh_status status = USBH_BUSY; + + if (puhost->control.ctl_state == CTL_IDLE) { + puhost->control.setup.req = (usb_req) { + .bmRequestType = USB_TRX_IN | USB_REQTYPE_CLASS | USB_RECPTYPE_ITF, + .bRequest = BBB_GET_MAX_LUN, + .wValue = 0U, + .wIndex = 0U, + .wLength = 1U + }; + + usbh_ctlstate_config (puhost, maxlun, 1U); + } + + status = usbh_ctl_handler (puhost); + + return status; +} + +/*! + \brief get max lun of the mass storage device + \param[in] puhost: pointer to USB host + \param[in] lun: logic unit number + \param[out] none + \retval operation status +*/ +static usbh_status usbh_msc_rdwr_process(usbh_host *puhost, uint8_t lun) +{ + usbh_status error = USBH_BUSY; + usbh_status scsi_status = USBH_BUSY; + usbh_msc_handler *msc = (usbh_msc_handler *)puhost->active_class->class_data; + + /* switch msc req state machine */ + switch (msc->unit[lun].state) { + case MSC_READ: + scsi_status = usbh_msc_read10(puhost, lun, NULL, 0U, 0U); + + if (USBH_OK == scsi_status) { + msc->unit[lun].state = MSC_IDLE; + error = USBH_OK; + } else if (USBH_FAIL == scsi_status) { + msc->unit[lun].state = MSC_REQUEST_SENSE; + } else { + if (USBH_UNRECOVERED_ERROR == scsi_status) { + msc->unit[lun].state = MSC_UNRECOVERED_ERROR; + error = USBH_FAIL; + } + } + break; + + case MSC_WRITE: + scsi_status = usbh_msc_write10(puhost, lun, NULL, 0U, 0U); + + if (USBH_OK == scsi_status) { + msc->unit[lun].state = MSC_IDLE; + error = USBH_OK; + } else if(USBH_FAIL == scsi_status) { + msc->unit[lun].state = MSC_REQUEST_SENSE; + } else { + if (USBH_UNRECOVERED_ERROR == scsi_status) { + msc->unit[lun].state = MSC_UNRECOVERED_ERROR; + error = USBH_FAIL; + } + } + break; + + case MSC_REQUEST_SENSE: + scsi_status = usbh_msc_request_sense (puhost, lun, &msc->unit[lun].sense); + + if (USBH_OK == scsi_status) { + msc->unit[lun].state = MSC_IDLE; + msc->unit[lun].error = MSC_ERROR; + + error = USBH_FAIL; + } + + if (USBH_FAIL == scsi_status) { + } else { + if (USBH_UNRECOVERED_ERROR == scsi_status) { + msc->unit[lun].state = MSC_UNRECOVERED_ERROR; + error = USBH_FAIL; + } + } + break; + + default: + break; + } + + return error; +} + +/*! + \brief get lun information + \param[in] puhost: pointer to USB host + \param[in] lun: logic unit number + \param[in] info: pointer to lun information + \param[out] none + \retval operation status +*/ +usbh_status usbh_msc_lun_info_get (usbh_host *puhost, uint8_t lun, msc_lun *info) +{ + usbh_msc_handler *msc = (usbh_msc_handler *)puhost->active_class->class_data; + + if (HOST_CLASS_HANDLER == puhost->cur_state) { + memcpy(info, &msc->unit[lun], sizeof(msc_lun)); + + return USBH_OK; + } else { + return USBH_FAIL; + } +} + +/*! + \brief handle msc read operation + \param[in] puhost: pointer to USB host + \param[in] lun: logic unit number + \param[in] address: data address + \param[in] pbuf: pointer to data buffer + \param[in] length: buffer length + \param[out] none + \retval operation status +*/ +usbh_status usbh_msc_read (usbh_host *puhost, + uint8_t lun, + uint32_t address, + uint8_t *pbuf, + uint32_t length) +{ + uint32_t timeout = 0U; + usbh_msc_handler *msc = (usbh_msc_handler *)puhost->active_class->class_data; + usb_core_driver *pudev = (usb_core_driver *)puhost->data; + + if ((0U == pudev->host.connect_status) || + (HOST_CLASS_HANDLER != puhost->cur_state) || + (MSC_IDLE != msc->unit[lun].state)) { + return USBH_FAIL; + } + + msc->state = MSC_READ; + msc->unit[lun].state = MSC_READ; + msc->rw_lun = lun; + + usbh_msc_read10(puhost, lun, pbuf, address, length); + + timeout = puhost->control.timer; + + while (USBH_BUSY == usbh_msc_rdwr_process(puhost, lun)) { + if (((puhost->control.timer > timeout) && ((puhost->control.timer - timeout) > (1000U * length))) \ + || ((puhost->control.timer < timeout) && ((puhost->control.timer + 0x3FFFU - timeout) > (1000U * length))) \ + || (0U == pudev->host.connect_status)){ + msc->state = MSC_IDLE; + return USBH_FAIL; + } + } + + msc->state = MSC_IDLE; + + return USBH_OK; +} + +/*! + \brief handle msc write operation + \param[in] puhost: pointer to USB host + \param[in] lun: logic unit number + \param[in] address: data address + \param[in] pbuf: pointer to data buffer + \param[in] length: buffer length + \param[out] none + \retval operation status +*/ +usbh_status usbh_msc_write (usbh_host *puhost, + uint8_t lun, + uint32_t address, + uint8_t *pbuf, + uint32_t length) +{ + uint32_t timeout = 0U; + usb_core_driver *pudev = (usb_core_driver *)puhost->data; + usbh_msc_handler *msc = (usbh_msc_handler *)puhost->active_class->class_data; + + if ((0U == pudev->host.connect_status) || + (HOST_CLASS_HANDLER != puhost->cur_state) || + (MSC_IDLE != msc->unit[lun].state)) { + return USBH_FAIL; + } + + msc->state = MSC_WRITE; + msc->unit[lun].state = MSC_WRITE; + msc->rw_lun = lun; + + usbh_msc_write10(puhost, lun, pbuf, address, length); + + timeout = puhost->control.timer; + + while (USBH_BUSY == usbh_msc_rdwr_process(puhost, lun)) { + if (((puhost->control.timer > timeout) && ((puhost->control.timer - timeout) > (1000U * length))) \ + || ((puhost->control.timer < timeout) && ((puhost->control.timer + 0x3FFFU - timeout) > (1000U * length))) \ + || (0U == pudev->host.connect_status)){ + msc->state = MSC_IDLE; + return USBH_FAIL; + } + } + + msc->state = MSC_IDLE; + + return USBH_OK; +} diff --git a/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/host/class/msc/Source/usbh_msc_fatfs.c b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/host/class/msc/Source/usbh_msc_fatfs.c new file mode 100644 index 0000000000..4923d3af00 --- /dev/null +++ b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/host/class/msc/Source/usbh_msc_fatfs.c @@ -0,0 +1,233 @@ +/*! + \file usbh_msc_fatfs.c + \brief USB MSC host FATFS related functions + + \version 2020-08-01, V3.0.0, firmware for GD32F30x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "usb_conf.h" +#include "diskio.h" +#include "usbh_msc_core.h" + +static volatile DSTATUS state = STA_NOINIT; /* disk status */ + +extern usbh_host usb_host; + +/*! + \brief initialize the disk drive + \param[in] drv: physical drive number (0) + \param[out] none + \retval operation status +*/ +DSTATUS disk_initialize (BYTE drv) +{ + usb_core_driver *pudev = (usb_core_driver *)usb_host.data; + + if (pudev->host.connect_status) { + state &= ~STA_NOINIT; + } + + return state; +} + +/*! + \brief get disk status + \param[in] drv: physical drive number (0) + \param[out] none + \retval operation status +*/ +DSTATUS disk_status (BYTE drv) +{ + if (drv) { + return STA_NOINIT; /* supports only single drive */ + } + + return state; +} + +/*! + \brief read sectors + \param[in] drv: physical drive number (0) + \param[in] buff: pointer to the data buffer to store read data + \param[in] sector: start sector number (LBA) + \param[in] count: sector count (1..255) + \param[out] none + \retval operation status +*/ +DRESULT disk_read (BYTE drv, BYTE *buff, DWORD sector, UINT count) +{ + BYTE status = USBH_OK; + usb_core_driver *pudev = (usb_core_driver *)usb_host.data; + + if (drv || (!count)) { + return RES_PARERR; + } + + if (state & STA_NOINIT) { + return RES_NOTRDY; + } + + if (pudev->host.connect_status) { + do { + status = usbh_msc_read (&usb_host, drv, sector, buff, count); + + if (!pudev->host.connect_status) { + return RES_ERROR; + } + } while(status == USBH_BUSY); + } + + if (status == USBH_OK) { + return RES_OK; + } + + return RES_ERROR; +} + +#if _READONLY == 0U + +/*! + \brief write sectors + \param[in] drv: physical drive number (0) + \param[in] buff: pointer to the data buffer to store read data + \param[in] sector: start sector number (LBA) + \param[in] count: sector count (1..255) + \param[out] none + \retval operation status +*/ +DRESULT disk_write (BYTE drv, const BYTE *buff, DWORD sector, UINT count) +{ + BYTE status = USBH_OK; + usb_core_driver *pudev = (usb_core_driver *)usb_host.data; + + if ((!count) || drv) { + return RES_PARERR; + } + + if (state & STA_NOINIT) { + return RES_NOTRDY; + } + + if (state & STA_PROTECT) { + return RES_WRPRT; + } + + if (pudev->host.connect_status) { + do { + status = usbh_msc_write (&usb_host, drv, sector, (BYTE*)buff, count); + + if (!pudev->host.connect_status) { + return RES_ERROR; + } + } while(status == USBH_BUSY); + } + + if (status == USBH_OK) { + return RES_OK; + } + + return RES_ERROR; +} + +#endif /* _READONLY == 0 */ + +/*! + \brief I/O control function + \param[in] drv: physical drive number (0) + \param[in] ctrl: control code + \param[in] buff: pointer to the data buffer to store read data + \param[out] none + \retval operation status +*/ +DRESULT disk_ioctl (BYTE drv, BYTE ctrl, void *buff) +{ + DRESULT res = RES_OK; + msc_lun info; + + if (drv) { + return RES_PARERR; + } + + res = RES_ERROR; + + if (state & STA_NOINIT) { + return RES_NOTRDY; + } + + switch (ctrl) { + /* make sure that no pending write process */ + case CTRL_SYNC: + res = RES_OK; + break; + + /* get number of sectors on the disk (dword) */ + case GET_SECTOR_COUNT: + if (USBH_OK == usbh_msc_lun_info_get(&usb_host, drv, &info)) { + *(DWORD*)buff = (DWORD)info.capacity.block_nbr; + res = RES_OK; + } + break; + + /* get r/w sector size (word) */ + case GET_SECTOR_SIZE: + if (USBH_OK == usbh_msc_lun_info_get(&usb_host, drv, &info)) { + *(WORD*)buff = (DWORD)info.capacity.block_size; + res = RES_OK; + } + break; + + /* get erase block size in unit of sector (dword) */ + case GET_BLOCK_SIZE: + *(DWORD*)buff = 512; + break; + + default: + res = RES_PARERR; + break; + } + + return res; +} + +/*! + \brief get fat time + \param[in] none + \param[out] none + \retval time value +*/ +DWORD get_fattime(void) { + + return ((DWORD)(2019U - 1980U) << 25U) /* Year 2019 */ + | ((DWORD)1U << 21U) /* Month 1 */ + | ((DWORD)1U << 16U) /* Mday 1 */ + | ((DWORD)0U << 11U) /* Hour 0 */ + | ((DWORD)0U << 5U) /* Min 0 */ + | ((DWORD)0U >> 1U); /* Sec 0 */ +} diff --git a/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/host/class/msc/Source/usbh_msc_scsi.c b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/host/class/msc/Source/usbh_msc_scsi.c new file mode 100644 index 0000000000..d6f47445d3 --- /dev/null +++ b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/host/class/msc/Source/usbh_msc_scsi.c @@ -0,0 +1,397 @@ +/*! + \file usbh_msc_scsi.c + \brief USB MSC SCSI commands implemention + + \version 2020-08-01, V3.0.0, firmware for GD32F30x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "usbh_msc_core.h" +#include "usbh_msc_scsi.h" +#include "usbh_msc_bbb.h" +#include + +/*! + \brief send 'Inquiry' command to the device + \param[in] puhost: pointer to usb host handler + \param[in] lun: logic unit number + \param[in] inquiry: pointer to the inquiry structure + \param[out] none + \retval operation status +*/ +usbh_status usbh_msc_scsi_inquiry (usbh_host *puhost, uint8_t lun, scsi_std_inquiry_data *inquiry) +{ + usbh_status error = USBH_FAIL; + usbh_msc_handler *msc = (usbh_msc_handler *)puhost->active_class->class_data; + + switch (msc->bot.cmd_state) { + case BOT_CMD_SEND: + /* prepare the cbw and relevant field*/ + msc->bot.cbw.field.dCBWDataTransferLength = STANDARD_INQUIRY_DATA_LEN; + msc->bot.cbw.field.bmCBWFlags = USB_TRX_IN; + msc->bot.cbw.field.bCBWCBLength = CBW_LENGTH; + + memset(msc->bot.cbw.field.CBWCB, 0U, CBW_LENGTH); + + msc->bot.cbw.field.CBWCB[0] = SCSI_INQUIRY; + msc->bot.cbw.field.CBWCB[1] = (lun << 5U); + msc->bot.cbw.field.CBWCB[4] = 0x24U; + + msc->bot.state = BOT_SEND_CBW; + msc->bot.cmd_state = BOT_CMD_WAIT; + msc->bot.pbuf = (uint8_t *)(void *)msc->bot.data; + error = USBH_BUSY; + break; + + case BOT_CMD_WAIT: + error = usbh_msc_bot_process(puhost, lun); + + if (USBH_OK == error) { + memset(inquiry, 0U, sizeof(scsi_std_inquiry_data)); + + /* assign inquiry data */ + inquiry->device_type = msc->bot.pbuf[0] & 0x1FU; + inquiry->peripheral_qualifier = msc->bot.pbuf[0] >> 5U; + + if (0x80U == ((uint32_t)msc->bot.pbuf[1] & 0x80U)) { + inquiry->removable_media = 1U; + } else { + inquiry->removable_media = 0U; + } + + memcpy (inquiry->vendor_id, &msc->bot.pbuf[8], 8U); + memcpy (inquiry->product_id, &msc->bot.pbuf[16], 16U); + memcpy (inquiry->revision_id, &msc->bot.pbuf[32], 4U); + } + break; + + default: + break; + } + + return error; +} + +/*! + \brief send 'Test unit ready' command to the device + \param[in] puhost: pointer to USB host handler + \param[in] lun: logic unit number + \param[out] none + \retval operation status +*/ +usbh_status usbh_msc_test_unitready (usbh_host *puhost, uint8_t lun) +{ + usbh_status status = USBH_FAIL; + usbh_msc_handler *msc = (usbh_msc_handler *)puhost->active_class->class_data; + + + switch (msc->bot.cmd_state) { + case BOT_CMD_SEND: + /* prepare the CBW and relevant field */ + msc->bot.cbw.field.dCBWDataTransferLength = CBW_LENGTH_TEST_UNIT_READY; + msc->bot.cbw.field.bmCBWFlags = USB_TRX_OUT; + msc->bot.cbw.field.bCBWCBLength = CBW_LENGTH; + + memset(msc->bot.cbw.field.CBWCB, 0U, CBW_CB_LENGTH); + + msc->bot.cbw.field.CBWCB[0] = SCSI_TEST_UNIT_READY; + msc->bot.state = BOT_SEND_CBW; + msc->bot.cmd_state = BOT_CMD_WAIT; + + status = USBH_BUSY; + break; + + case BOT_CMD_WAIT: + status = usbh_msc_bot_process(puhost, lun); + break; + + default: + break; + } + + return status; +} + +/*! + \brief send the read capacity command to the device + \param[in] puhost: pointer to usb host handler + \param[in] lun: logic unit number + \param[in] capacity: pointer to scsi capacity + \param[out] none + \retval operation status +*/ +usbh_status usbh_msc_read_capacity10 (usbh_host *puhost, uint8_t lun, scsi_capacity *capacity) +{ + usbh_status status = USBH_FAIL; + usbh_msc_handler *msc = (usbh_msc_handler *)puhost->active_class->class_data; + + switch (msc->bot.cmd_state) { + case BOT_CMD_SEND: + /* prepare the CBW and relevant field */ + msc->bot.cbw.field.dCBWDataTransferLength = READ_CAPACITY10_DATA_LEN; + msc->bot.cbw.field.bmCBWFlags = USB_TRX_IN; + msc->bot.cbw.field.bCBWCBLength = CBW_LENGTH; + + memset(msc->bot.cbw.field.CBWCB, 0U, CBW_CB_LENGTH); + + msc->bot.cbw.field.CBWCB[0] = SCSI_READ_CAPACITY10; + msc->bot.state = BOT_SEND_CBW; + msc->bot.cmd_state = BOT_CMD_WAIT; + msc->bot.pbuf = (uint8_t *)(void *)msc->bot.data; + + status = USBH_BUSY; + break; + + case BOT_CMD_WAIT: + status = usbh_msc_bot_process(puhost, lun); + + if (USBH_OK == status) { + capacity->block_nbr = msc->bot.pbuf[3] | \ + ((uint32_t)msc->bot.pbuf[2] << 8U) | \ + ((uint32_t)msc->bot.pbuf[1] << 16U) | \ + ((uint32_t)msc->bot.pbuf[0] << 24U); + + capacity->block_size = (uint16_t)(msc->bot.pbuf[7] | ((uint32_t)msc->bot.pbuf[6] << 8U)); + } + break; + + default: + break; + } + + return status; +} + +/*! + \brief send the mode sense6 command to the device + \param[in] puhost: pointer to usb host handler + \param[in] lun: logic unit number + \param[out] none + \retval operation status +*/ +usbh_status usbh_msc_mode_sense6 (usbh_host *puhost, uint8_t lun) +{ + usbh_status status = USBH_FAIL; + usbh_msc_handler *msc = (usbh_msc_handler *)puhost->active_class->class_data; + + switch (msc->bot.cmd_state) { + case BOT_CMD_SEND: + /* prepare the CBW and relevant field */ + msc->bot.cbw.field.dCBWDataTransferLength = XFER_LEN_MODE_SENSE6; + msc->bot.cbw.field.bmCBWFlags = USB_TRX_IN; + msc->bot.cbw.field.bCBWCBLength = CBW_LENGTH; + + memset(msc->bot.cbw.field.CBWCB, 0U, CBW_CB_LENGTH); + + msc->bot.cbw.field.CBWCB[0] = SCSI_MODE_SENSE6; + msc->bot.cbw.field.CBWCB[2] = MODE_SENSE_PAGE_CONTROL_FIELD | MODE_SENSE_PAGE_CODE; + msc->bot.cbw.field.CBWCB[4] = XFER_LEN_MODE_SENSE6; + msc->bot.state = BOT_SEND_CBW; + msc->bot.cmd_state = BOT_CMD_WAIT; + msc->bot.pbuf = (uint8_t *)(void *)msc->bot.data; + + status = USBH_BUSY; + break; + + case BOT_CMD_WAIT: + status = usbh_msc_bot_process(puhost, lun); + + if (USBH_OK == status) { + if (msc->bot.data[2] & MASK_MODE_SENSE_WRITE_PROTECT) { + + } else { + + } + } + break; + + default: + break; + } + + return status; +} + +/*! + \brief send the Request Sense command to the device + \param[in] puhost: pointer to usb host handler + \param[in] lun: logic unit number + \param[in] sense_data: pointer to sense data + \param[out] none + \retval operation status +*/ +usbh_status usbh_msc_request_sense (usbh_host *puhost, uint8_t lun, msc_scsi_sense *sense_data) +{ + usbh_status status = USBH_FAIL; + usbh_msc_handler *msc = (usbh_msc_handler *)puhost->active_class->class_data; + + switch (msc->bot.cmd_state) { + case BOT_CMD_SEND: + /* prepare the cbw and relevant field */ + msc->bot.cbw.field.dCBWDataTransferLength = ALLOCATION_LENGTH_REQUEST_SENSE; + msc->bot.cbw.field.bmCBWFlags = USB_TRX_IN; + msc->bot.cbw.field.bCBWCBLength = CBW_LENGTH; + + memset(msc->bot.cbw.field.CBWCB, 0U, CBW_CB_LENGTH); + + msc->bot.cbw.field.CBWCB[0] = SCSI_REQUEST_SENSE; + msc->bot.cbw.field.CBWCB[1] = (lun << 5U); + msc->bot.cbw.field.CBWCB[4] = ALLOCATION_LENGTH_REQUEST_SENSE; + + msc->bot.state = BOT_SEND_CBW; + msc->bot.cmd_state = BOT_CMD_WAIT; + msc->bot.pbuf = (uint8_t *)(void *)msc->bot.data; + + status = USBH_BUSY; + break; + + case BOT_CMD_WAIT: + status = usbh_msc_bot_process(puhost, lun); + + if (status == USBH_OK) { + /* get sense data */ + sense_data->SenseKey = msc->bot.pbuf[2] & 0x0FU; + sense_data->ASC = msc->bot.pbuf[12]; + sense_data->ASCQ = msc->bot.pbuf[13]; + } + break; + + default: + break; + } + + return status; +} + +/*! + \brief send the write10 command to the device + \param[in] puhost: pointer to usb host handler + \param[in] lun: logic unit number + \param[in] data_buf: data buffer contains the data to write + \param[in] addr: address to which the data will be written + \param[in] sector_num: number of sector to be written + \param[out] none + \retval operation status +*/ +usbh_status usbh_msc_write10 (usbh_host *puhost, uint8_t lun, uint8_t *data_buf, uint32_t addr, uint32_t sector_num) +{ + usbh_status status = USBH_FAIL; + usbh_msc_handler *msc = (usbh_msc_handler *)puhost->active_class->class_data; + + switch (msc->bot.cmd_state) { + case BOT_CMD_SEND: + msc->bot.cbw.field.dCBWDataTransferLength = sector_num * msc->unit[lun].capacity.block_size; + msc->bot.cbw.field.bmCBWFlags = USB_TRX_OUT; + msc->bot.cbw.field.bCBWCBLength = CBW_LENGTH; + + memset(msc->bot.cbw.field.CBWCB, 0U, CBW_CB_LENGTH); + + msc->bot.cbw.field.CBWCB[0] = SCSI_WRITE10; + + /* logical block address */ + msc->bot.cbw.field.CBWCB[2] = (((uint8_t*)&addr)[3]); + msc->bot.cbw.field.CBWCB[3] = (((uint8_t*)&addr)[2]); + msc->bot.cbw.field.CBWCB[4] = (((uint8_t*)&addr)[1]); + msc->bot.cbw.field.CBWCB[5] = (((uint8_t*)&addr)[0]); + + /* transfer length */ + msc->bot.cbw.field.CBWCB[7] = (((uint8_t *)§or_num)[1]); + msc->bot.cbw.field.CBWCB[8] = (((uint8_t *)§or_num)[0]); + + msc->bot.state = BOT_SEND_CBW; + msc->bot.cmd_state = BOT_CMD_WAIT; + msc->bot.pbuf = data_buf; + + status = USBH_BUSY; + break; + + case BOT_CMD_WAIT: + status = usbh_msc_bot_process(puhost, lun); + break; + + default: + break; + } + + return status; +} + +/*! + \brief send the read10 command to the device + \param[in] puhost: pointer to usb host handler + \param[in] lun: logic unit number + \param[in] data_buf: data buffer contains the data to write + \param[in] addr: address to which the data will be read + \param[in] sector_num: number of sector to be read + \param[out] none + \retval operation status +*/ +usbh_status usbh_msc_read10 (usbh_host *puhost, uint8_t lun, uint8_t *data_buf, uint32_t addr, uint32_t sector_num) +{ + usbh_status status = USBH_FAIL; + usbh_msc_handler *msc = (usbh_msc_handler *)puhost->active_class->class_data; + + switch (msc->bot.cmd_state) { + case BOT_CMD_SEND: + /* prepare the CBW and relevant field */ + msc->bot.cbw.field.dCBWDataTransferLength = sector_num * msc->unit[lun].capacity.block_size; + msc->bot.cbw.field.bmCBWFlags = USB_TRX_IN; + msc->bot.cbw.field.bCBWCBLength = CBW_LENGTH; + + memset(msc->bot.cbw.field.CBWCB, 0U, CBW_CB_LENGTH); + + msc->bot.cbw.field.CBWCB[0] = SCSI_READ10; + + /* logical block address */ + msc->bot.cbw.field.CBWCB[2] = (((uint8_t*)&addr)[3]); + msc->bot.cbw.field.CBWCB[3] = (((uint8_t*)&addr)[2]); + msc->bot.cbw.field.CBWCB[4] = (((uint8_t*)&addr)[1]); + msc->bot.cbw.field.CBWCB[5] = (((uint8_t*)&addr)[0]); + + /* transfer length */ + msc->bot.cbw.field.CBWCB[7] = (((uint8_t *)§or_num)[1]); + msc->bot.cbw.field.CBWCB[8] = (((uint8_t *)§or_num)[0]); + + msc->bot.state = BOT_SEND_CBW; + msc->bot.cmd_state = BOT_CMD_WAIT; + msc->bot.pbuf = data_buf; + + status = USBH_BUSY; + break; + + case BOT_CMD_WAIT: + status = usbh_msc_bot_process(puhost, lun); + break; + + default: + break; + } + + return status; +} diff --git a/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/host/core/Include/usbh_core.h b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/host/core/Include/usbh_core.h new file mode 100644 index 0000000000..e52da96a1e --- /dev/null +++ b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/host/core/Include/usbh_core.h @@ -0,0 +1,274 @@ +/*! + \file usbh_core.h + \brief USB host core state machine header file + + \version 2020-08-01, V3.0.0, firmware for GD32F30x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef __USBH_CORE_H +#define __USBH_CORE_H + +#include "usbh_conf.h" +#include "drv_usb_host.h" + +#define MSC_CLASS 0x08U +#define HID_CLASS 0x03U +#define MSC_PROTOCOL 0x50U +#define CBI_PROTOCOL 0x01U + +#define USBH_MAX_ERROR_COUNT 3U + +#define USBH_DEV_ADDR_DEFAULT 0U +#define USBH_DEV_ADDR 1U + +typedef enum +{ + USBH_OK = 0U, + USBH_BUSY, + USBH_FAIL, + USBH_NOT_SUPPORTED, + USBH_UNRECOVERED_ERROR, + USBH_SPEED_UNKNOWN_ERROR, + USBH_APPLY_DEINIT +} usbh_status; + +/* USB host global operation state */ +typedef enum +{ + HOST_DEFAULT = 0U, + HOST_DETECT_DEV_SPEED, + HOST_DEV_ATTACHED, + HOST_DEV_DETACHED, + HOST_ENUM, + HOST_SET_WAKEUP_FEATURE, + HOST_CHECK_CLASS, + HOST_CLASS_ENUM, + HOST_CLASS_HANDLER, + HOST_USER_INPUT, + HOST_SUSPENDED, + HOST_WAKEUP, + HOST_ERROR +} usb_host_state; + +/* USB host enumeration state */ +typedef enum +{ + ENUM_DEFAULT = 0U, + ENUM_GET_DEV_DESC, + ENUM_SET_ADDR, + ENUM_GET_CFG_DESC, + ENUM_GET_CFG_DESC_SET, + ENUM_GET_STR_DESC, +#ifdef USB_MTP + ENUM_GET_MTP_STR, +#endif + ENUM_SET_CONFIGURATION, + ENUM_DEV_CONFIGURED +} usbh_enum_state; + +/* USB host control transfer state */ +typedef enum +{ + CTL_IDLE = 0U, + CTL_SETUP, + CTL_SETUP_WAIT, + CTL_DATA_IN, + CTL_DATA_IN_WAIT, + CTL_DATA_OUT, + CTL_DATA_OUT_WAIT, + CTL_STATUS_IN, + CTL_STATUS_IN_WAIT, + CTL_STATUS_OUT, + CTL_STATUS_OUT_WAIT, + CTL_ERROR, + CTL_FINISH +} usbh_ctl_state; + +/* user action state */ +typedef enum +{ + USBH_USER_NO_RESP = 0U, + USBH_USER_RESP_OK = 1U, +} usbh_user_status; + +typedef enum +{ + USBH_PORT_EVENT = 1U, + USBH_URB_EVENT, + USBH_CONTROL_EVENT, + USBH_CLASS_EVENT, + USBH_STATE_CHANGED_EVENT, +}usbh_os_event; + +/* control transfer information */ +typedef struct _usbh_control +{ + uint8_t pipe_in_num; + uint8_t pipe_out_num; + uint8_t max_len; + uint8_t error_count; + + uint8_t *buf; + uint16_t ctl_len; + uint16_t timer; + + usb_setup setup; + usbh_ctl_state ctl_state; +} usbh_control; + +/* USB interface descriptor set */ +typedef struct _usb_desc_itf_set +{ + usb_desc_itf itf_desc; + usb_desc_ep ep_desc[USBH_MAX_EP_NUM]; +} usb_desc_itf_set; + +/* USB configure descriptor set */ +typedef struct _usb_desc_cfg_set +{ + usb_desc_config cfg_desc; + usb_desc_itf_set itf_desc_set[USBH_MAX_INTERFACES_NUM][USBH_MAX_ALT_SETTING]; +} usb_desc_cfg_set; + +/* USB device property */ +typedef struct +{ + uint8_t data[USBH_DATA_BUF_MAX_LEN]; /* if DMA is used, the data array must be located in the first position */ + uint8_t cur_itf; + uint8_t addr; + + uint32_t speed; + + usb_desc_dev dev_desc; + usb_desc_cfg_set cfg_desc_set; + +#if (USBH_KEEP_CFG_DESCRIPTOR == 1U) + uint8_t cfgdesc_rawdata[USBH_CFGSET_MAX_LEN]; +#endif /* (USBH_KEEP_CFG_DESCRIPTOR == 1U) */ +} usb_dev_prop; + +struct _usbh_host; + +/* device class callbacks */ +typedef struct +{ + uint8_t class_code; /*!< USB class type */ + + usbh_status (*class_init) (struct _usbh_host *phost); + void (*class_deinit) (struct _usbh_host *phost); + usbh_status (*class_requests) (struct _usbh_host *phost); + usbh_status (*class_machine) (struct _usbh_host *phost); + usbh_status (*class_sof) (struct _usbh_host *puhost); + + void *class_data; +} usbh_class; + +/* user callbacks */ +typedef struct +{ + void (*dev_init) (void); + void (*dev_deinit) (void); + void (*dev_attach) (void); + void (*dev_reset) (void); + void (*dev_detach) (void); + void (*dev_over_currented) (void); + void (*dev_speed_detected) (uint32_t dev_speed); + void (*dev_devdesc_assigned) (void *dev_desc); + void (*dev_address_set) (void); + + void (*dev_cfgdesc_assigned) (usb_desc_config *cfg_desc, + usb_desc_itf *itf_desc, + usb_desc_ep *ep_desc); + + void (*dev_mfc_str) (void *mfc_str); + void (*dev_prod_str) (void *prod_str); + void (*dev_seral_str) (void *serial_str); + void (*dev_enumerated) (void); + usbh_user_status (*dev_user_input) (void); + int (*dev_user_app) (void); + void (*dev_not_supported) (void); + void (*dev_error) (void); +} usbh_user_cb; + +/* host information */ +typedef struct _usbh_host +{ + usb_host_state cur_state; /*!< host state machine value */ + usb_host_state backup_state; /*!< backup of previous state machine value */ + usbh_enum_state enum_state; /*!< enumeration state machine */ + usbh_control control; /*!< USB host control state machine */ + usb_dev_prop dev_prop; /*!< USB device property */ + + usbh_class *uclass[USBH_MAX_SUPPORTED_CLASS]; /*!< USB host supported class */ + usbh_class *active_class; /*!< USB active class */ + usbh_user_cb *usr_cb; /*!< USB user callback */ + + uint8_t class_num; /*!< USB class number */ + + void *data; /*!< used for... */ +} usbh_host; + +/*! + \brief get USB URB state + \param[in] pudev: pointer to USB core instance + \param[in] pp_num: pipe number + \param[out] none + \retval none +*/ +static inline usb_urb_state usbh_urbstate_get (usb_core_driver *pudev, uint8_t pp_num) +{ + return pudev->host.pipe[pp_num].urb_state; +} + +/*! + \brief get USB transfer data count + \param[in] pudev: pointer to USB core instance + \param[in] pp_num: pipe number + \param[out] none + \retval none +*/ +static inline uint32_t usbh_xfercount_get (usb_core_driver *pudev, uint8_t pp_num) +{ + return pudev->host.backup_xfercount[pp_num]; +} + +/* function declarations */ +/* USB host stack initializations */ +void usbh_init (usbh_host *puhost, usbh_user_cb *user_cb); +/* USB host register device class */ +usbh_status usbh_class_register (usbh_host *puhost, usbh_class *puclass); +/* de-initialize USB host */ +usbh_status usbh_deinit (usbh_host *puhost); +/* USB host core main state machine process */ +void usbh_core_task (usbh_host *puhost); +/* handle the error on USB host side */ +void usbh_error_handler (usbh_host *puhost, usbh_status err_type); + +#endif /* __USBH_CORE_H */ diff --git a/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/host/core/Include/usbh_enum.h b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/host/core/Include/usbh_enum.h new file mode 100644 index 0000000000..2e666fd907 --- /dev/null +++ b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/host/core/Include/usbh_enum.h @@ -0,0 +1,71 @@ +/*! + \file usbh_enum.h + \brief USB host mode USB enumeration header file + + \version 2020-08-01, V3.0.0, firmware for GD32F30x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef __USBH_ENUM_H +#define __USBH_ENUM_H + +#include "usb_conf.h" +#include "usbh_core.h" + +/* function declarations */ +/* configure USB control status parameters */ +void usbh_ctlstate_config (usbh_host *puhost, uint8_t *buf, uint16_t len); +/* get device descriptor from the USB device */ +usbh_status usbh_devdesc_get (usbh_host *puhost, uint8_t len); +/* get configuration descriptor from the USB device */ +usbh_status usbh_cfgdesc_get (usbh_host *puhost, uint16_t len); +/* get string descriptor from the USB device */ +usbh_status usbh_strdesc_get (usbh_host *puhost,uint8_t str_index, uint8_t *buf, uint16_t len); +/* set the address to the connected device */ +usbh_status usbh_setaddress (usbh_host *puhost, uint8_t dev_addr); +/* set the configuration value to the connected device */ +usbh_status usbh_setcfg (usbh_host *puhost, uint16_t config); +/* set the interface value to the connected device */ +usbh_status usbh_setinterface (usbh_host *puhost, uint8_t itf_num, uint8_t alter_setting); +/* set or enable a specific device feature */ +usbh_status usbh_setdevfeature (usbh_host *puhost, uint8_t feature_selector, uint16_t windex); +/* clear or disable a specific device feature */ +usbh_status usbh_clrdevfeature (usbh_host *puhost, uint8_t feature_selector, uint16_t windex); +/* clear or disable a specific feature */ +usbh_status usbh_clrfeature (usbh_host *puhost, uint8_t ep_addr, uint8_t pp_num); +/* get the next descriptor header */ +usb_desc_header *usbh_nextdesc_get (uint8_t *pbuf, uint16_t *ptr); +/* select an interface */ +usbh_status usbh_interface_select (usb_dev_prop *udev, uint8_t interface); +/* find the interface index for a specific class */ +uint8_t usbh_interface_find (usb_dev_prop *udev, uint8_t main_class, uint8_t sub_class, uint8_t protocol); +/* find the interface index for a specific class interface and alternate setting number */ +uint8_t usbh_interfaceindex_find (usb_dev_prop *udev, uint8_t interface_number, uint8_t alt_settings); + +#endif /* __USBH_ENUM_H */ diff --git a/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/host/core/Include/usbh_pipe.h b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/host/core/Include/usbh_pipe.h new file mode 100644 index 0000000000..4d899a683a --- /dev/null +++ b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/host/core/Include/usbh_pipe.h @@ -0,0 +1,100 @@ +/*! + \file usbh_pipe.h + \brief USB host mode pipe header file + + \version 2020-08-01, V3.0.0, firmware for GD32F30x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef __USBH_PIPE_H +#define __USBH_PIPE_H + +#include "usbh_core.h" + +#define HC_MAX 8U + +#define HC_OK 0x0000U +#define HC_USED 0x8000U +#define HC_ERROR 0xFFFFU +#define HC_USED_MASK 0x7FFFU + +/*! + \brief set toggle for a pipe + \param[in] pudev: pointer to USB core instance + \param[in] pp_num: pipe number + \param[in] toggle: toggle (0/1) + \param[out] none + \retval operation status +*/ +__STATIC_INLINE void usbh_pipe_toggle_set (usb_core_driver *pudev, uint8_t pp_num, uint8_t toggle) +{ + if (pudev->host.pipe[pp_num].ep.dir) { + pudev->host.pipe[pp_num].data_toggle_in = toggle; + } else { + pudev->host.pipe[pp_num].data_toggle_out = toggle; + } +} + +/*! + \brief get toggle flag of pipe + \param[in] pudev: pointer to USB core instance + \param[in] pp_num: pipe number + \param[out] none + \retval operation status +*/ +__STATIC_INLINE uint8_t usbh_pipe_toggle_get (usb_core_driver *pudev, uint8_t pp_num) +{ + if (pudev->host.pipe[pp_num].ep.dir) { + return pudev->host.pipe[pp_num].data_toggle_in; + } else { + return pudev->host.pipe[pp_num].data_toggle_out; + } +} + +/* function declarations */ +/* create a pipe */ +uint8_t usbh_pipe_create (usb_core_driver *pudev, + usb_dev_prop *udev, + uint8_t pp_num, + uint8_t ep_type, + uint16_t ep_mpl); +/* modify a pipe */ +uint8_t usbh_pipe_update (usb_core_driver *pudev, + uint8_t pp_num, + uint8_t dev_addr, + uint32_t dev_speed, + uint16_t ep_mpl); +/* allocate a new pipe */ +uint8_t usbh_pipe_allocate (usb_core_driver *pudev, uint8_t ep_addr); +/* free a pipe */ +uint8_t usbh_pipe_free (usb_core_driver *pudev, uint8_t pp_num); +/* delete all USB host pipe */ +uint8_t usbh_pipe_delete (usb_core_driver *pudev); + +#endif /* __USBH_PIPE_H */ diff --git a/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/host/core/Include/usbh_transc.h b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/host/core/Include/usbh_transc.h new file mode 100644 index 0000000000..8d876c8a2d --- /dev/null +++ b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/host/core/Include/usbh_transc.h @@ -0,0 +1,51 @@ +/*! + \file usbh_transc.h + \brief USB host mode transactions header file + + \version 2020-08-01, V3.0.0, firmware for GD32F30x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef __USBH_TRANSC_H +#define __USBH_TRANSC_H + +#include "usb_conf.h" +#include "usbh_core.h" + +/* function declarations */ +/* send the setup packet to the USB device */ +usbh_status usbh_ctlsetup_send (usb_core_driver *pudev, uint8_t *buf, uint8_t pp_num); +/* send a data packet to the USB device */ +usbh_status usbh_data_send (usb_core_driver *pudev, uint8_t *buf, uint8_t pp_num, uint16_t len); +/* receive a data packet from the USB device */ +usbh_status usbh_data_recev (usb_core_driver *pudev, uint8_t *buf, uint8_t pp_num, uint16_t len); +/* USB control transfer handler */ +usbh_status usbh_ctl_handler (usbh_host *puhost); + +#endif /* __USBH_TRANSC_H */ diff --git a/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/host/core/Source/usbh_core.c b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/host/core/Source/usbh_core.c new file mode 100644 index 0000000000..777942e302 --- /dev/null +++ b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/host/core/Source/usbh_core.c @@ -0,0 +1,650 @@ +/*! + \file usbh_core.c + \brief USB host core state machine driver + + \version 2020-08-01, V3.0.0, firmware for GD32F30x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "drv_usb_hw.h" +#include "usbh_pipe.h" +#include "usbh_enum.h" +#include "usbh_core.h" +#include "drv_usbh_int.h" +#include + +usb_core_driver usbh_core; + +/* local function prototypes ('static') */ +static uint8_t usbh_sof (usbh_host *puhost); +static uint8_t usbh_connect (usbh_host *puhost); +static uint8_t usbh_disconnect (usbh_host *puhost); +static uint8_t usbh_port_enabled (usbh_host *puhost); +static uint8_t usbh_port_disabled (usbh_host *puhost); +static usbh_status usbh_enum_task (usbh_host *puhost); + +#ifdef USB_FS_LOW_PWR_ENABLE +static void usb_hwp_suspend(usb_core_driver *pudev); +static void usb_hwp_resume(usb_core_driver *pudev); +#endif + +usbh_int_cb usbh_int_op = +{ + usbh_connect, + usbh_disconnect, + usbh_port_enabled, + usbh_port_disabled, + usbh_sof +}; + +usbh_int_cb *usbh_int_fop = &usbh_int_op; + +/*! + \brief USB host stack initializations + \param[in] puhost: pointer to USB host + \param[in] user_cb: pointer to user callback + \param[out] none + \retval none +*/ +void usbh_init (usbh_host *puhost, usbh_user_cb *user_cb) +{ + /* host de-initializations */ + usbh_deinit(puhost); + + puhost->usr_cb = user_cb; + + usbh_core.host.connect_status = 0U; + + for (uint8_t i = 0U; i < USBFS_MAX_TX_FIFOS; i++) { + usbh_core.host.pipe[i].err_count = 0U; + usbh_core.host.pipe[i].pp_status = PIPE_IDLE; + usbh_core.host.backup_xfercount[i] = 0U; + } + + usbh_core.host.pipe[0].ep.mps = 8U; + +#ifdef USE_USB_FS + usb_basic_init (&usbh_core.bp, &usbh_core.regs, USB_CORE_ENUM_FS); +#endif /* USE_USB_FS */ + +#ifndef DUAL_ROLE_MODE_ENABLED + usb_globalint_disable(&usbh_core.regs); + + usb_core_init (usbh_core.bp, &usbh_core.regs); + +#ifndef USE_OTG_MODE + usb_curmode_set (&usbh_core.regs, HOST_MODE); +#endif /* USE_OTG_MODE */ + + usb_host_init (&usbh_core); + + usb_globalint_enable(&usbh_core.regs); +#endif /* DUAL_ROLE_MODE_ENABLED */ + + /* link driver to the stack */ + usbh_core.host.data = (void *)puhost; + puhost->data = (void *)&usbh_core; + + /* upon init call usr call back */ + puhost->usr_cb->dev_init(); +} + +/*! + \brief USB host register device class + \param[in] puhost: pointer to usb host instance + \param[in] puclass: pointer to USB device class + \param[out] none + \retval operation status +*/ +usbh_status usbh_class_register (usbh_host *puhost, usbh_class *puclass) +{ + usbh_status status = USBH_OK; + + if (NULL != puclass) { + if (puhost->class_num < USBH_MAX_SUPPORTED_CLASS) { + puhost->uclass[puhost->class_num++] = puclass; + } else { + status = USBH_FAIL; + } + } else { + status = USBH_FAIL; + } + + return status; +} + +/*! + \brief de-initialize USB host + \param[in] puhost: pointer to USB host + \param[out] none + \retval operation status +*/ +usbh_status usbh_deinit(usbh_host *puhost) +{ + /* software init */ + puhost->cur_state = HOST_DEFAULT; + puhost->backup_state = HOST_DEFAULT; + puhost->enum_state = ENUM_DEFAULT; + + puhost->control.ctl_state = CTL_IDLE; + puhost->control.max_len = USB_FS_EP0_MAX_LEN; + + puhost->dev_prop.addr = USBH_DEV_ADDR_DEFAULT; + puhost->dev_prop.speed = PORT_SPEED_FULL; + puhost->dev_prop.cur_itf = 0xFFU; + + usbh_pipe_free(&usbh_core, puhost->control.pipe_in_num); + usbh_pipe_free(&usbh_core, puhost->control.pipe_out_num); + + return USBH_OK; +} + +/*! + \brief USB host core main state machine process + \param[in] puhost: pointer to USB host + \param[out] none + \retval none +*/ +void usbh_core_task (usbh_host *puhost) +{ + volatile usbh_status status = USBH_FAIL; + + /* check for host port events */ + if (((0U == usbh_core.host.connect_status) || (0U == usbh_core.host.port_enabled)) && (HOST_DEFAULT != puhost->cur_state)) { + if (puhost->cur_state != HOST_DEV_DETACHED) { + puhost->cur_state = HOST_DEV_DETACHED; + } + } + + switch (puhost->cur_state) { + case HOST_DEFAULT: + if (usbh_core.host.connect_status) { + puhost->cur_state = HOST_DETECT_DEV_SPEED; + + usb_mdelay (100U); + + usb_port_reset (&usbh_core); + + puhost->usr_cb->dev_reset(); + } + break; + + case HOST_DETECT_DEV_SPEED: + if (usbh_core.host.port_enabled) { + puhost->cur_state = HOST_DEV_ATTACHED; + + puhost->dev_prop.speed = usb_curspeed_get (&usbh_core); + + puhost->usr_cb->dev_speed_detected(puhost->dev_prop.speed); + + usb_mdelay (50U); + } + break; + + case HOST_DEV_ATTACHED: + puhost->usr_cb->dev_attach(); + puhost->control.pipe_out_num = usbh_pipe_allocate(&usbh_core, 0x00U); + puhost->control.pipe_in_num = usbh_pipe_allocate(&usbh_core, 0x80U); + + /* open IN control pipe */ + usbh_pipe_create (&usbh_core, + &puhost->dev_prop, + puhost->control.pipe_in_num, + USB_EPTYPE_CTRL, + (uint16_t)puhost->control.max_len); + + /* open OUT control pipe */ + usbh_pipe_create (&usbh_core, + &puhost->dev_prop, + puhost->control.pipe_out_num, + USB_EPTYPE_CTRL, + (uint16_t)puhost->control.max_len); + + puhost->cur_state = HOST_ENUM; + break; + + case HOST_ENUM: + /* check for enumeration status */ + if (USBH_OK == usbh_enum_task (puhost)) { + /* the function shall return USBH_OK when full enumeration is complete */ + + /* user callback for end of device basic enumeration */ + puhost->usr_cb->dev_enumerated(); + +#ifdef USB_FS_LOW_PWR_ENABLE + puhost->cur_state = HOST_SUSPENDED; +#else + puhost->cur_state = HOST_SET_WAKEUP_FEATURE; +#endif + } + break; + + case HOST_SET_WAKEUP_FEATURE: + if ((puhost->dev_prop.cfg_desc_set.cfg_desc.bmAttributes) & (1U << 5)) { + if (usbh_setdevfeature(puhost, FEATURE_SELECTOR_REMOTEWAKEUP, 0U) == USBH_OK) { + puhost->cur_state = HOST_CHECK_CLASS; + } + } else { + puhost->cur_state = HOST_CHECK_CLASS; + } + break; + + case HOST_CHECK_CLASS: + if (puhost->class_num == 0U) { + puhost->cur_state = HOST_ERROR; + } else { + puhost->active_class = NULL; + + uint8_t itf_class = puhost->dev_prop.cfg_desc_set.itf_desc_set[0][0].itf_desc.bInterfaceClass; + + for (uint8_t index = 0U; index < puhost->class_num; index++) { + if ((puhost->uclass[index]->class_code == itf_class) || (0xFFU == itf_class)) { + puhost->active_class = puhost->uclass[index]; + } + } + + if (puhost->active_class != NULL) { + puhost->cur_state = HOST_USER_INPUT; + } else { + puhost->cur_state = HOST_ERROR; + } + } + break; + + case HOST_USER_INPUT: + /* the function should return user response true to move to class state */ + if (USBH_USER_RESP_OK == puhost->usr_cb->dev_user_input()) { + if ((USBH_OK == puhost->active_class->class_init(puhost))) { + puhost->cur_state = HOST_CLASS_ENUM; + } + } + break; + +#ifdef USB_FS_LOW_PWR_ENABLE + case HOST_SUSPENDED: + if (USBH_OK == usbh_setdevfeature(puhost, FEATURE_SELECTOR_DEV, 0U)) { + puhost->suspend_flag = 1; + usb_hwp_suspend(puhost->data); + puhost->usr_cb->dev_user_input(); + pmu_to_deepsleepmode(PMU_LDO_LOWPOWER, WFI_CMD); + puhost->cur_state = HOST_WAKEUP; + } + break; + + case HOST_WAKEUP: + if (USBH_OK == usbh_clrdevfeature(puhost, FEATURE_SELECTOR_DEV, 0U)) { + /* user callback for initalization */ + puhost->usr_cb->dev_init(); + + puhost->cur_state = HOST_CHECK_CLASS; + } + break; +#endif + + case HOST_CLASS_ENUM: + /* process class standard contol requests state machine */ + status = puhost->active_class->class_requests(puhost); + + if (USBH_OK == status) { + puhost->cur_state = HOST_CLASS_HANDLER; + } else { + usbh_error_handler (puhost, status); + } + break; + + case HOST_CLASS_HANDLER: + /* process class state machine */ + status = puhost->active_class->class_machine(puhost); + + usbh_error_handler (puhost, status); + break; + + case HOST_ERROR: + /* re-initilaize host for new enumeration */ + usbh_deinit (puhost); + puhost->usr_cb->dev_deinit(); + puhost->active_class->class_deinit(puhost); + break; + + case HOST_DEV_DETACHED: + /* manage user disconnect operations*/ + puhost->usr_cb->dev_detach(); + + /* re-initilaize host for new enumeration */ + usbh_deinit(puhost); + puhost->usr_cb->dev_deinit(); + puhost->active_class->class_deinit(puhost); + usbh_pipe_delete(&usbh_core); + puhost->cur_state = HOST_DEFAULT; + break; + + default: + break; + } +} + +/*! + \brief handle the error on USB host side + \param[in] puhost: pointer to USB host + \param[in] err_type: type of error or busy/OK state + \param[out] none + \retval none +*/ +void usbh_error_handler (usbh_host *puhost, usbh_status err_type) +{ + /* error unrecovered or not supported device speed */ + if ((USBH_SPEED_UNKNOWN_ERROR == err_type) || (USBH_UNRECOVERED_ERROR == err_type)) { + puhost->usr_cb->dev_error(); + + puhost->cur_state = HOST_ERROR; + } else if (USBH_APPLY_DEINIT == err_type) { + puhost->cur_state = HOST_ERROR; + + /* user callback for initalization */ + puhost->usr_cb->dev_init(); + } else { + /* no operation */ + } +} + +/*! + \brief USB SOF callback function from the interrupt + \param[in] puhost: pointer to usb host + \param[out] none + \retval operation status +*/ +static uint8_t usbh_sof (usbh_host *puhost) +{ + /* this callback could be used to implement a scheduler process */ + puhost->control.timer = (uint16_t)usb_curframe_get(&usbh_core); + + if (puhost->active_class != NULL) { + if (puhost->active_class->class_sof != NULL) { + puhost->active_class->class_sof(puhost); + } + } + + return 0U; +} + +/*! + \brief USB connect callback function from the interrupt + \param[in] puhost: pointer to usb host + \param[out] none + \retval operation status +*/ +static uint8_t usbh_connect (usbh_host *puhost) +{ + usbh_core.host.connect_status = 1U; + + return 0U; +} + +/*! + \brief USB disconnect callback function from the interrupt + \param[in] puhost: pointer to usb host + \param[out] none + \retval operation status +*/ +static uint8_t usbh_disconnect (usbh_host *puhost) +{ + usbh_core.host.connect_status = 0U; + + return 0U; +} + +/*! + \brief USB port enable callback function from the interrupt + \param[in] puhost: pointer to usb host + \param[out] none + \retval operation status +*/ +static uint8_t usbh_port_enabled (usbh_host *puhost) +{ + usbh_core.host.port_enabled = 1U; + + return 0U; +} + +/*! + \brief USB port disabled callback function from the interrupt + \param[in] puhost: pointer to usb host + \param[out] none + \retval operation status +*/ +static uint8_t usbh_port_disabled (usbh_host *puhost) +{ + usbh_core.host.port_enabled = 0U; + + return 0U; +} + +/*! + \brief handle the USB enumeration task + \param[in] puhost: pointer to host + \param[out] none + \retval none +*/ +static usbh_status usbh_enum_task (usbh_host *puhost) +{ + uint8_t str_buf[64]; + + usbh_status status = USBH_BUSY; + + static uint8_t index_mfc_str = 0U, index_prod_str = 0U, index_serial_str = 0U; + + switch (puhost->enum_state) { + case ENUM_DEFAULT: + /* get device descriptor for only 1st 8 bytes : to get ep0 maxpacketsize */ + if (USBH_OK == usbh_devdesc_get (puhost, 8U)) { + puhost->control.max_len = puhost->dev_prop.dev_desc.bMaxPacketSize0; + + /* modify control channels configuration for maximum packet size */ + usbh_pipe_update (&usbh_core, + puhost->control.pipe_out_num, + 0U, 0U, + (uint16_t)puhost->control.max_len); + + usbh_pipe_update (&usbh_core, + puhost->control.pipe_in_num, + 0U, 0U, + (uint16_t)puhost->control.max_len); + + puhost->enum_state = ENUM_GET_DEV_DESC; + } + break; + + case ENUM_GET_DEV_DESC: + /* get full device descriptor */ + if (USBH_OK == usbh_devdesc_get (puhost, USB_DEV_DESC_LEN)) { + puhost->usr_cb->dev_devdesc_assigned(&puhost->dev_prop.dev_desc); + + index_mfc_str = puhost->dev_prop.dev_desc.iManufacturer; + index_prod_str = puhost->dev_prop.dev_desc.iProduct; + index_serial_str = puhost->dev_prop.dev_desc.iSerialNumber; + + puhost->enum_state = ENUM_SET_ADDR; + } + break; + + case ENUM_SET_ADDR: + /* set address */ + if (USBH_OK == usbh_setaddress (puhost, USBH_DEV_ADDR)) { + usb_mdelay (2U); + + puhost->dev_prop.addr = USBH_DEV_ADDR; + + /* user callback for device address assigned */ + puhost->usr_cb->dev_address_set(); + + /* modify control channels to update device address */ + usbh_pipe_update (&usbh_core, + puhost->control.pipe_in_num, + puhost->dev_prop.addr, + 0U, 0U); + + usbh_pipe_update (&usbh_core, + puhost->control.pipe_out_num, + puhost->dev_prop.addr, + 0U, 0U); + + puhost->enum_state = ENUM_GET_CFG_DESC; + } + break; + + case ENUM_GET_CFG_DESC: + /* get standard configuration descriptor */ + if (USBH_OK == usbh_cfgdesc_get (puhost, USB_CFG_DESC_LEN)) { + puhost->enum_state = ENUM_GET_CFG_DESC_SET; + } + break; + + case ENUM_GET_CFG_DESC_SET: + /* get full config descriptor (config, interface, endpoints) */ + if (USBH_OK == usbh_cfgdesc_get (puhost, puhost->dev_prop.cfg_desc_set.cfg_desc.wTotalLength)) { + /* user callback for configuration descriptors available */ + puhost->usr_cb->dev_cfgdesc_assigned (&puhost->dev_prop.cfg_desc_set.cfg_desc, + &puhost->dev_prop.cfg_desc_set.itf_desc_set[0][0].itf_desc, + &puhost->dev_prop.cfg_desc_set.itf_desc_set[0][0].ep_desc[0]); + + puhost->enum_state = ENUM_GET_STR_DESC; + } + break; + + case ENUM_GET_STR_DESC: + if (index_mfc_str) { + if (USBH_OK == usbh_strdesc_get (puhost, + puhost->dev_prop.dev_desc.iManufacturer, + str_buf, + 0xFFU)) { + /* user callback for manufacturing string */ + puhost->usr_cb->dev_mfc_str(str_buf); + + index_mfc_str = 0U; + } + } else { + if (index_prod_str) { + /* check that product string is available */ + if (USBH_OK == usbh_strdesc_get (puhost, + puhost->dev_prop.dev_desc.iProduct, + str_buf, + 0xFFU)) { + puhost->usr_cb->dev_prod_str(str_buf); + + index_prod_str = 0U; + } + } else { + if (index_serial_str) { + if (USBH_OK == usbh_strdesc_get (puhost, + puhost->dev_prop.dev_desc.iSerialNumber, + str_buf, + 0xFFU)) { + puhost->usr_cb->dev_seral_str(str_buf); + puhost->enum_state = ENUM_SET_CONFIGURATION; + index_serial_str = 0U; + } + } else { + puhost->enum_state = ENUM_SET_CONFIGURATION; + } + } + } + break; + + case ENUM_SET_CONFIGURATION: + if (USBH_OK == usbh_setcfg (puhost, (uint16_t)puhost->dev_prop.cfg_desc_set.cfg_desc.bConfigurationValue)) { + puhost->enum_state = ENUM_DEV_CONFIGURED; + } + break; + + case ENUM_DEV_CONFIGURED: + status = USBH_OK; + break; + + default: + break; + } + + return status; +} + + +#ifdef USB_FS_LOW_PWR_ENABLE + +/*! + \brief handles the USB resume from suspend mode + \param[in] pudev: pointer to selected USB device + \param[out] none + \retval none +*/ +static void usb_hwp_resume(usb_core_driver *pudev) +{ + __IO uint32_t hprt = 0U; + + /* switch-on the clocks */ + *pudev->regs.PWRCLKCTL &= ~PWRCLKCTL_SUCLK; + + *pudev->regs.PWRCLKCTL &= ~PWRCLKCTL_SHCLK; + + hprt = usb_port_read(pudev); + + hprt &= ~HPCS_PSP; + hprt |= HPCS_PREM; + + *pudev->regs.HPCS = hprt; + + usb_mdelay (20U); + + hprt &= ~HPCS_PREM; + + *pudev->regs.HPCS = hprt; +} + +/*! + \brief handles the USB enter to suspend mode + \param[in] pudev: pointer to selected USB device + \param[out] none + \retval none +*/ +static void usb_hwp_suspend(usb_core_driver *pudev) +{ + __IO uint32_t hprt = 0U; + + hprt = usb_port_read(pudev); + + hprt |= HPCS_PSP; + + *pudev->regs.HPCS = hprt; + + /* switch-off the clocks */ + *pudev->regs.PWRCLKCTL |= PWRCLKCTL_SUCLK; + + *pudev->regs.PWRCLKCTL |= PWRCLKCTL_SHCLK; +} + +#endif diff --git a/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/host/core/Source/usbh_enum.c b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/host/core/Source/usbh_enum.c new file mode 100644 index 0000000000..19a71167d0 --- /dev/null +++ b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/host/core/Source/usbh_enum.c @@ -0,0 +1,693 @@ +/*! + \file usbh_enum.c + \brief USB host mode enumeration driver + + \version 2020-08-01, V3.0.0, firmware for GD32F30x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "usbh_pipe.h" +#include "usbh_transc.h" +#include "usbh_enum.h" + +/* local function prototypes ('static') */ +static void usbh_devdesc_parse (usb_desc_dev *dev_desc, uint8_t *buf, uint16_t len); +static void usbh_cfgdesc_parse (usb_desc_config *cfg_desc, uint8_t *buf); +static void usbh_cfgset_parse (usb_dev_prop *udev, uint8_t *buf); +static void usbh_itfdesc_parse (usb_desc_itf *itf_desc, uint8_t *buf); +static void usbh_epdesc_parse (usb_desc_ep *ep_desc, uint8_t *buf); +static void usbh_strdesc_parse (uint8_t *psrc, uint8_t *pdest, uint16_t len); + +/*! + \brief configure USB control status parameters + \param[in] puhost: pointer to usb host + \param[in] buf: control transfer data buffer pointer + \param[in] len: length of the data buffer + \param[out] none + \retval none +*/ +void usbh_ctlstate_config (usbh_host *puhost, uint8_t *buf, uint16_t len) +{ + /* prepare the transactions */ + puhost->control.buf = buf; + puhost->control.ctl_len = len; + + puhost->control.ctl_state = CTL_SETUP; +} + +/*! + \brief get device descriptor from the USB device + \param[in] puhost: pointer to usb host + \param[in] len: length of the descriptor + \param[out] none + \retval operation status +*/ +usbh_status usbh_devdesc_get (usbh_host *puhost, uint8_t len) +{ + usbh_status status = USBH_BUSY; + + usbh_control *usb_ctl = &puhost->control; + + if (CTL_IDLE == usb_ctl->ctl_state) { + usb_ctl->setup.req = (usb_req) { + .bmRequestType = USB_TRX_IN | USB_RECPTYPE_DEV | USB_REQTYPE_STRD, + .bRequest = USB_GET_DESCRIPTOR, + .wValue = USBH_DESC(USB_DESCTYPE_DEV), + .wIndex = 0U, + .wLength = len + }; + + usbh_ctlstate_config (puhost, puhost->dev_prop.data, (uint16_t)len); + } + + status = usbh_ctl_handler (puhost); + + if (USBH_OK == status) { + /* commands successfully sent and response received */ + usbh_devdesc_parse (&puhost->dev_prop.dev_desc, puhost->dev_prop.data, (uint16_t)len); + } + + return status; +} + +/*! + \brief get configuration descriptor from the USB device + \param[in] puhost: pointer to usb host + \param[in] len: length of the descriptor + \param[out] none + \retval operation status +*/ +usbh_status usbh_cfgdesc_get (usbh_host *puhost, uint16_t len) +{ + uint8_t *pdata = NULL; + + usbh_status status = USBH_BUSY; + + usbh_control *usb_ctl = &puhost->control; + +#if (USBH_KEEP_CFG_DESCRIPTOR == 1U) + pdata = puhost->dev_prop.cfgdesc_rawdata; +#else + pdata = puhost->dev_prop.data; +#endif + + if (CTL_IDLE == usb_ctl->ctl_state) { + usb_ctl->setup.req = (usb_req) { + .bmRequestType = USB_TRX_IN | USB_RECPTYPE_DEV | USB_REQTYPE_STRD, + .bRequest = USB_GET_DESCRIPTOR, + .wValue = USBH_DESC(USB_DESCTYPE_CONFIG), + .wIndex = 0U, + .wLength = len + }; + + usbh_ctlstate_config (puhost, pdata, len); + } + + status = usbh_ctl_handler (puhost); + + if (USBH_OK == status) { + if (len <= USB_CFG_DESC_LEN) { + usbh_cfgdesc_parse (&puhost->dev_prop.cfg_desc_set.cfg_desc, pdata); + } else { + usbh_cfgset_parse (&puhost->dev_prop, pdata); + } + } + + return status; +} + +/*! + \brief get string descriptor from the USB device + \param[in] puhost: pointer to usb host + \param[in] str_index: index for the string descriptor + \param[in] buf: buffer pointer to the string descriptor + \param[in] len: length of the descriptor + \param[out] none + \retval operation status +*/ +usbh_status usbh_strdesc_get (usbh_host *puhost, + uint8_t str_index, + uint8_t *buf, + uint16_t len) +{ + usbh_status status = USBH_BUSY; + + usbh_control *usb_ctl = &puhost->control; + + if (CTL_IDLE == usb_ctl->ctl_state) { + usb_ctl->setup.req = (usb_req) { + .bmRequestType = USB_TRX_IN | USB_RECPTYPE_DEV | USB_REQTYPE_STRD, + .bRequest = USB_GET_DESCRIPTOR, + .wValue = USBH_DESC(USB_DESCTYPE_STR) | str_index, + .wIndex = 0x0409U, + .wLength = len + }; + + usbh_ctlstate_config (puhost, puhost->dev_prop.data, len); + } + + status = usbh_ctl_handler (puhost); + + if (USBH_OK == status) { + /* commands successfully sent and response received */ + usbh_strdesc_parse (puhost->dev_prop.data, buf, len); + } + + return status; +} + +/*! + \brief set the address to the connected device + \param[in] puhost: pointer to usb host + \param[in] dev_addr: device address to assign + \param[out] none + \retval operation status +*/ +usbh_status usbh_setaddress (usbh_host *puhost, uint8_t dev_addr) +{ + usbh_status status = USBH_BUSY; + + usbh_control *usb_ctl = &puhost->control; + + if (CTL_IDLE == usb_ctl->ctl_state) { + usb_ctl->setup.req = (usb_req) { + .bmRequestType = USB_TRX_OUT | USB_RECPTYPE_DEV | USB_REQTYPE_STRD, + .bRequest = USB_SET_ADDRESS, + .wValue = (uint16_t)dev_addr, + .wIndex = 0U, + .wLength = 0U + }; + + usbh_ctlstate_config (puhost, NULL, 0U); + } + + status = usbh_ctl_handler (puhost); + + return status; +} + +/*! + \brief set the configuration value to the connected device + \param[in] puhost: pointer to usb host + \param[in] config_index: configuration value + \param[out] none + \retval operation status +*/ +usbh_status usbh_setcfg (usbh_host *puhost, uint16_t config_index) +{ + usbh_status status = USBH_BUSY; + + usbh_control *usb_ctl = &puhost->control; + + if (CTL_IDLE == usb_ctl->ctl_state) { + usb_ctl->setup.req = (usb_req) { + .bmRequestType = USB_TRX_OUT | USB_RECPTYPE_DEV | USB_REQTYPE_STRD, + .bRequest = USB_SET_CONFIGURATION, + .wValue = config_index, + .wIndex = 0U, + .wLength = 0U + }; + + usbh_ctlstate_config (puhost, NULL, 0U); + } + + status = usbh_ctl_handler (puhost); + + return status; +} + +/*! + \brief set the interface value to the connected device + \param[in] puhost: pointer to usb host + \param[in] itf_num: interface number + \param[in] set: alternated setting value + \param[out] none + \retval operation status +*/ +usbh_status usbh_setinterface (usbh_host *puhost, uint8_t itf_num, uint8_t set) +{ + usbh_status status = USBH_BUSY; + + usbh_control *usb_ctl = &puhost->control; + + if (CTL_IDLE == usb_ctl->ctl_state) { + usb_ctl->setup.req = (usb_req) { + .bmRequestType = USB_TRX_OUT | USB_RECPTYPE_ITF | USB_REQTYPE_STRD, + .bRequest = USB_SET_INTERFACE, + .wValue = set, + .wIndex = itf_num, + .wLength = 0U + }; + + usbh_ctlstate_config (puhost, NULL, 0U); + } + + status = usbh_ctl_handler (puhost); + + return status; +} + +/*! + \brief set the interface value to the connected device + \param[in] puhost: pointer to usb host + \param[in] feature_selector: feature selector + \param[in] windex: index value + \param[out] none + \retval operation status +*/ +usbh_status usbh_setdevfeature (usbh_host *puhost, uint8_t feature_selector, uint16_t windex) +{ + usbh_status status = USBH_BUSY; + + usbh_control *usb_ctl = &puhost->control; + + if (CTL_IDLE == usb_ctl->ctl_state) { + usb_ctl->setup.req = (usb_req) { + .bmRequestType = USB_TRX_OUT | USB_RECPTYPE_DEV | USB_REQTYPE_STRD, + .bRequest = USB_SET_FEATURE, + .wValue = feature_selector, + .wIndex = windex, + .wLength = 0U + }; + + usbh_ctlstate_config (puhost, NULL, 0U); + } + + status = usbh_ctl_handler (puhost); + + return status; +} + +/*! + \brief clear the interface value to the connected device + \param[in] puhost: pointer to usb host + \param[in] feature_selector: feature selector + \param[in] windex: index value + \param[out] none + \retval operation status +*/ +usbh_status usbh_clrdevfeature (usbh_host *puhost, uint8_t feature_selector, uint16_t windex) +{ + usbh_status status = USBH_BUSY; + + usbh_control *usb_ctl = &puhost->control; + + if (CTL_IDLE == usb_ctl->ctl_state) { + usb_ctl->setup.req = (usb_req) { + .bmRequestType = USB_TRX_OUT | USB_RECPTYPE_DEV | USB_REQTYPE_STRD, + .bRequest = USB_CLEAR_FEATURE, + .wValue = feature_selector, + .wIndex = windex, + .wLength = 0U + }; + + usbh_ctlstate_config (puhost, NULL, 0U); + } + + status = usbh_ctl_handler (puhost); + + return status; +} + +/*! + \brief clear or disable a specific feature + \param[in] puhost: pointer to usb host + \param[in] ep_addr: endpoint address + \param[in] pp_num: pipe number + \param[out] none + \retval operation status +*/ +usbh_status usbh_clrfeature (usbh_host *puhost, uint8_t ep_addr, uint8_t pp_num) +{ + usbh_status status = USBH_BUSY; + usbh_control *usb_ctl = &puhost->control; + usb_core_driver *pudev = (usb_core_driver *)puhost->data; + + if (CTL_IDLE == usb_ctl->ctl_state) { + usb_ctl->setup.req = (usb_req) { + .bmRequestType = USB_TRX_OUT | USB_RECPTYPE_EP | USB_REQTYPE_STRD, + .bRequest = USB_CLEAR_FEATURE, + .wValue = FEATURE_SELECTOR_EP, + .wIndex = ep_addr, + .wLength = 0U + }; + + if (EP_ID(ep_addr) == pudev->host.pipe[pp_num].ep.num) { + usbh_pipe_toggle_set(pudev, pp_num, 0U); + } else { + return USBH_FAIL; + } + + usbh_ctlstate_config (puhost, NULL, 0U); + } + + status = usbh_ctl_handler (puhost); + + return status; +} + +/*! + \brief get the next descriptor header + \param[in] pbuf: pointer to buffer where the configuration descriptor set is available + \param[in] ptr: data pointer inside the configuration descriptor set + \param[out] none + \retval return descriptor header +*/ +usb_desc_header *usbh_nextdesc_get (uint8_t *pbuf, uint16_t *ptr) +{ + usb_desc_header *pnext; + + *ptr += ((usb_desc_header *)pbuf)->bLength; + + pnext = (usb_desc_header *)((uint8_t *)pbuf + ((usb_desc_header *)pbuf)->bLength); + + return (pnext); +} + +/*! + \brief get the next descriptor header + \param[in] udev: pointer to device property + \param[in] interface: interface number + \param[out] none + \retval operation status +*/ +usbh_status usbh_interface_select (usb_dev_prop *udev, uint8_t interface) +{ + usbh_status status = USBH_OK; + + if (interface < udev->cfg_desc_set.cfg_desc.bNumInterfaces) { + udev->cur_itf = interface; + } else { + status = USBH_FAIL; + } + + return status; +} + +/*! + \brief find the interface index for a specific class + \param[in] udev: pointer to device property + \param[in] main_class: class code + \param[in] sub_class: subclass code + \param[in] protocol: Protocol code + \param[out] none + \retval interface index in the configuration structure + \note interface index 0xFF means interface index not found +*/ +uint8_t usbh_interface_find (usb_dev_prop *udev, uint8_t main_class, uint8_t sub_class, uint8_t protocol) +{ + usb_desc_itf *pif; + + uint8_t if_ix = 0U; + + pif = (usb_desc_itf *)0; + + while (if_ix < udev->cfg_desc_set.cfg_desc.bNumInterfaces) { + pif = &udev->cfg_desc_set.itf_desc_set[if_ix][0].itf_desc; + + if (((pif->bInterfaceClass == main_class) || (main_class == 0xFFU))&& + ((pif->bInterfaceSubClass == sub_class) || (sub_class == 0xFFU))&& + ((pif->bInterfaceProtocol == protocol) || (protocol == 0xFFU))) { + return if_ix; + } + + if_ix++; + } + + return 0xFFU; +} + +/*! + \brief find the interface index for a specific class interface and alternate setting number + \param[in] udev: pointer to device property + \param[in] interface_number: interface number + \param[in] alt_settings: alternate setting number + \param[out] none + \retval interface index in the configuration structure + \note interface index 0xFF means interface index not found +*/ +uint8_t usbh_interfaceindex_find (usb_dev_prop *udev, uint8_t interface_number, uint8_t alt_settings) +{ + usb_desc_itf *pif; + + uint8_t if_ix = 0U; + + pif = (usb_desc_itf *)0; + + while (if_ix < USBH_MAX_INTERFACES_NUM) { + pif = &udev->cfg_desc_set.itf_desc_set[if_ix][alt_settings].itf_desc; + + if ((pif->bInterfaceNumber == interface_number) && (pif->bAlternateSetting == alt_settings)) { + return if_ix; + } + + if_ix++; + } + + return 0xFFU; +} + +/*! + \brief parse the device descriptor + \param[in] dev_desc: pointer to usb device descriptor buffer + \param[in] buf: pointer to the source descriptor buffer + \param[in] len: length of the descriptor + \param[out] none + \retval none +*/ +static void usbh_devdesc_parse (usb_desc_dev *dev_desc, uint8_t *buf, uint16_t len) +{ + *dev_desc = (usb_desc_dev) { + .header = { + .bLength = *(uint8_t *)(buf + 0U), + .bDescriptorType = *(uint8_t *)(buf + 1U) + }, + + .bcdUSB = BYTE_SWAP(buf + 2U), + .bDeviceClass = *(uint8_t *)(buf + 4U), + .bDeviceSubClass = *(uint8_t *)(buf + 5U), + .bDeviceProtocol = *(uint8_t *)(buf + 6U), + .bMaxPacketSize0 = *(uint8_t *)(buf + 7U) + }; + + if (len > 8U) { + /* for 1st time after device connection, host may issue only 8 bytes for device descriptor length */ + dev_desc->idVendor = BYTE_SWAP(buf + 8U); + dev_desc->idProduct = BYTE_SWAP(buf + 10U); + dev_desc->bcdDevice = BYTE_SWAP(buf + 12U); + dev_desc->iManufacturer = *(uint8_t *)(buf + 14U); + dev_desc->iProduct = *(uint8_t *)(buf + 15U); + dev_desc->iSerialNumber = *(uint8_t *)(buf + 16U); + dev_desc->bNumberConfigurations = *(uint8_t *)(buf + 17U); + } +} + +/*! + \brief parse the configuration descriptor + \param[in] cfg_desc: pointer to usb configuration descriptor buffer + \param[in] buf: pointer to the source descriptor buffer + \param[out] none + \retval none +*/ +static void usbh_cfgdesc_parse (usb_desc_config *cfg_desc, uint8_t *buf) +{ + /* parse configuration descriptor */ + *cfg_desc = (usb_desc_config) { + .header = { + .bLength = *(uint8_t *)(buf + 0U), + .bDescriptorType = *(uint8_t *)(buf + 1U), + }, + + .wTotalLength = BYTE_SWAP(buf + 2U), + .bNumInterfaces = *(uint8_t *)(buf + 4U), + .bConfigurationValue = *(uint8_t *)(buf + 5U), + .iConfiguration = *(uint8_t *)(buf + 6U), + .bmAttributes = *(uint8_t *)(buf + 7U), + .bMaxPower = *(uint8_t *)(buf + 8U) + }; +} + +/*! + \brief parse the configuration descriptor set + \param[in] udev: pointer to device property + \param[in] buf: pointer to the source descriptor buffer + \param[out] none + \retval none +*/ +static void usbh_cfgset_parse (usb_dev_prop *udev, uint8_t *buf) +{ + usb_desc_ep *ep = NULL; + usb_desc_itf_set *itf = NULL; + usb_desc_itf itf_value; + usb_desc_config *cfg = NULL; + + usb_desc_header *pdesc = (usb_desc_header *)buf; + + uint8_t itf_index = 0U, ep_index = 0U, alt_setting = 0U; + uint8_t pre_itf_index = 0U; + uint16_t ptr; + + /* parse configuration descriptor */ + usbh_cfgdesc_parse (&udev->cfg_desc_set.cfg_desc, buf); + cfg = &udev->cfg_desc_set.cfg_desc; + ptr = USB_CFG_DESC_LEN; + + if (cfg->bNumInterfaces > USBH_MAX_INTERFACES_NUM) { + return; + } + + while (ptr < cfg->wTotalLength) { + pdesc = usbh_nextdesc_get ((uint8_t *)pdesc, &ptr); + + if (pdesc->bDescriptorType == USB_DESCTYPE_ITF) { + itf_index = *(((uint8_t *)pdesc) + 2U); + + if (pre_itf_index != itf_index) { + alt_setting = 0U; + } + + itf = &udev->cfg_desc_set.itf_desc_set[itf_index][alt_setting]; + + alt_setting++; + + if ((*((uint8_t *)pdesc + 3U)) < 3U) { + usbh_itfdesc_parse (&itf_value, (uint8_t *)pdesc); + + /* parse endpoint descriptors relative to the current interface */ + if (itf_value.bNumEndpoints > USBH_MAX_EP_NUM) { + return; + } + + usbh_itfdesc_parse (&itf->itf_desc, (uint8_t *)&itf_value); + + /* store the previous interface index */ + pre_itf_index = itf_index; + + if (0U == itf_value.bNumEndpoints) { + continue; + } + + for (ep_index = 0U; ep_index < itf_value.bNumEndpoints; ) { + pdesc = usbh_nextdesc_get ((void*)pdesc, &ptr); + + if (pdesc->bDescriptorType == USB_DESCTYPE_EP) { + ep = &itf->ep_desc[ep_index]; + + usbh_epdesc_parse (ep, (uint8_t *)pdesc); + + ep_index++; + } + } + } + } + } +} + +/*! + \brief parse the interface descriptor + \param[in] itf_desc: pointer to usb interface descriptor buffer + \param[in] buf: pointer to the source descriptor buffer + \param[out] none + \retval none +*/ +static void usbh_itfdesc_parse (usb_desc_itf *itf_desc, uint8_t *buf) +{ + *itf_desc = (usb_desc_itf) { + .header = { + .bLength = *(uint8_t *)(buf + 0U), + .bDescriptorType = *(uint8_t *)(buf + 1U), + }, + + .bInterfaceNumber = *(uint8_t *)(buf + 2U), + .bAlternateSetting = *(uint8_t *)(buf + 3U), + .bNumEndpoints = *(uint8_t *)(buf + 4U), + .bInterfaceClass = *(uint8_t *)(buf + 5U), + .bInterfaceSubClass = *(uint8_t *)(buf + 6U), + .bInterfaceProtocol = *(uint8_t *)(buf + 7U), + .iInterface = *(uint8_t *)(buf + 8U) + }; +} + +/*! + \brief parse the endpoint descriptor + \param[in] ep_desc: pointer to usb endpoint descriptor buffer + \param[in] buf: pointer to the source descriptor buffer + \param[out] none + \retval none +*/ +static void usbh_epdesc_parse (usb_desc_ep *ep_desc, uint8_t *buf) +{ + *ep_desc = (usb_desc_ep) { + .header = { + .bLength = *(uint8_t *)(buf + 0U), + .bDescriptorType = *(uint8_t *)(buf + 1U) + }, + + .bEndpointAddress = *(uint8_t *)(buf + 2U), + .bmAttributes = *(uint8_t *)(buf + 3U), + .wMaxPacketSize = BYTE_SWAP(buf + 4U), + .bInterval = *(uint8_t *)(buf + 6U) + }; +} + +/*! + \brief parse the string descriptor + \param[in] psrc: source pointer containing the descriptor data + \param[in] pdest: destination address pointer + \param[in] len: length of the descriptor + \param[out] none + \retval none +*/ +static void usbh_strdesc_parse (uint8_t *psrc, uint8_t *pdest, uint16_t len) +{ + uint16_t str_len = 0U, index = 0U; + + /* the unicode string descriptor is not NULL-terminated. The string length is + * computed by substracting two from the value of the first byte of the descriptor. + */ + + /* check which is lower size, the size of string or the length of bytes read from the device */ + if (USB_DESCTYPE_STR == psrc[1]) { + /* make sure the descriptor is string type */ + + /* psrc[0] contains Size of Descriptor, subtract 2 to get the length of string */ + str_len = USB_MIN((uint16_t)psrc[0] - 2U, len); + + psrc += 2U; /* adjust the offset ignoring the string len and descriptor type */ + + for (index = 0U; index < str_len; index += 2U) { + /* copy only the string and ignore the unicode id, hence add the src */ + *pdest = psrc[index]; + + pdest++; + } + + *pdest = 0U; /* mark end of string */ + } +} diff --git a/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/host/core/Source/usbh_pipe.c b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/host/core/Source/usbh_pipe.c new file mode 100644 index 0000000000..ab14434619 --- /dev/null +++ b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/host/core/Source/usbh_pipe.c @@ -0,0 +1,174 @@ +/*! + \file usbh_pipe.c + \brief USB host mode pipe operation driver + + \version 2020-08-01, V3.0.0, firmware for GD32F30x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "usbh_pipe.h" + +/* local function prototypes ('static') */ +static uint16_t usbh_freepipe_get (usb_core_driver *pudev); + +/*! + \brief create a pipe + \param[in] pudev: pointer to usb core instance + \param[in] udev: USB device + \param[in] pp_num: pipe number + \param[in] ep_type: endpoint type + \param[in] ep_mpl: endpoint max packet length + \param[out] none + \retval operation status +*/ +uint8_t usbh_pipe_create (usb_core_driver *pudev, + usb_dev_prop *udev, + uint8_t pp_num, + uint8_t ep_type, + uint16_t ep_mpl) +{ + usb_pipe *pp = &pudev->host.pipe[pp_num]; + + pp->dev_addr = udev->addr; + pp->dev_speed = udev->speed; + pp->ep.type = ep_type; + pp->ep.mps = ep_mpl; + pp->ping = (uint8_t)(udev->speed == PORT_SPEED_HIGH); + + usb_pipe_init (pudev, pp_num); + + return HC_OK; +} + +/*! + \brief modify a pipe + \param[in] pudev: pointer to usb core instance + \param[in] pp_num: pipe number + \param[in] dev_addr: device address + \param[in] dev_speed: device speed + \param[in] ep_mpl: endpoint max packet length + \param[out] none + \retval operation status +*/ +uint8_t usbh_pipe_update (usb_core_driver *pudev, + uint8_t pp_num, + uint8_t dev_addr, + uint32_t dev_speed, + uint16_t ep_mpl) +{ + usb_pipe *pp = &pudev->host.pipe[pp_num]; + + if ((pp->dev_addr != dev_addr) && (dev_addr)) { + pp->dev_addr = dev_addr; + } + + if ((pp->dev_speed != dev_speed) && (dev_speed)) { + pp->dev_speed = dev_speed; + } + + if ((pp->ep.mps != ep_mpl) && (ep_mpl)) { + pp->ep.mps = ep_mpl; + } + + usb_pipe_init (pudev, pp_num); + + return HC_OK; +} + +/*! + \brief allocate a new pipe + \param[in] pudev: pointer to usb core instance + \param[in] ep_addr: endpoint address + \param[out] none + \retval operation status +*/ +uint8_t usbh_pipe_allocate (usb_core_driver *pudev, uint8_t ep_addr) +{ + uint16_t pp_num = usbh_freepipe_get (pudev); + + if (HC_ERROR != pp_num) { + pudev->host.pipe[pp_num].in_used = 1U; + pudev->host.pipe[pp_num].ep.dir = EP_DIR(ep_addr); + pudev->host.pipe[pp_num].ep.num = EP_ID(ep_addr); + } + + return (uint8_t)pp_num; +} + +/*! + \brief free a pipe + \param[in] pudev: pointer to usb core instance + \param[in] pp_num: pipe number + \param[out] none + \retval operation status +*/ +uint8_t usbh_pipe_free (usb_core_driver *pudev, uint8_t pp_num) +{ + if (pp_num < HC_MAX) { + pudev->host.pipe[pp_num].in_used = 0U; + } + + return USBH_OK; +} + +/*! + \brief delete all USB host pipe + \param[in] pudev: pointer to usb core instance + \param[out] none + \retval operation status +*/ +uint8_t usbh_pipe_delete (usb_core_driver *pudev) +{ + uint8_t pp_num = 0U; + + for (pp_num = 2U; pp_num < HC_MAX; pp_num++) { + pudev->host.pipe[pp_num] = (usb_pipe) {0}; + } + + return USBH_OK; +} + +/*! + \brief get a free pipe number for allocation + \param[in] pudev: pointer to usb core instance + \param[out] none + \retval operation status +*/ +static uint16_t usbh_freepipe_get (usb_core_driver *pudev) +{ + uint8_t pp_num = 0U; + + for (pp_num = 0U; pp_num < HC_MAX; pp_num++) { + if (0U == pudev->host.pipe[pp_num].in_used) { + return (uint16_t)pp_num; + } + } + + return HC_ERROR; +} diff --git a/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/host/core/Source/usbh_transc.c b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/host/core/Source/usbh_transc.c new file mode 100644 index 0000000000..64201003a2 --- /dev/null +++ b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/host/core/Source/usbh_transc.c @@ -0,0 +1,370 @@ +/*! + \file usbh_transc.c + \brief USB host mode transactions driver + + \version 2020-08-01, V3.0.0, firmware for GD32F30x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "drv_usb_hw.h" +#include "usbh_pipe.h" +#include "usbh_transc.h" + +/* local function prototypes ('static') */ +static usb_urb_state usbh_urb_wait (usbh_host *puhost, uint8_t pp_num, uint32_t wait_time); +static void usbh_setup_transc (usbh_host *puhost); +static void usbh_data_in_transc (usbh_host *puhost); +static void usbh_data_out_transc (usbh_host *puhost); +static void usbh_status_in_transc (usbh_host *puhost); +static void usbh_status_out_transc (usbh_host *puhost); +static uint32_t usbh_request_submit (usb_core_driver *pudev, uint8_t pp_num); + +/*! + \brief send the setup packet to the USB device + \param[in] pudev: pointer to usb core instance + \param[in] buf: data buffer which will be sent to USB device + \param[in] pp_num: pipe number + \param[out] none + \retval operation status +*/ +usbh_status usbh_ctlsetup_send (usb_core_driver *pudev, uint8_t *buf, uint8_t pp_num) +{ + usb_pipe *pp = &pudev->host.pipe[pp_num]; + + pp->DPID = PIPE_DPID_SETUP; + pp->xfer_buf = buf; + pp->xfer_len = USB_SETUP_PACKET_LEN; + + return (usbh_status)usbh_request_submit (pudev, pp_num); +} + +/*! + \brief send a data packet to the USB device + \param[in] pudev: pointer to usb core instance + \param[in] buf: data buffer which will be sent to USB device + \param[in] pp_num: pipe number + \param[in] len: length of the data to be sent + \param[out] none + \retval operation status +*/ +usbh_status usbh_data_send (usb_core_driver *pudev, uint8_t *buf, uint8_t pp_num, uint16_t len) +{ + usb_pipe *pp = &pudev->host.pipe[pp_num]; + + pp->xfer_buf = buf; + pp->xfer_len = len; + + switch (pp->ep.type) { + case USB_EPTYPE_CTRL: + if (0U == len) { + pp->data_toggle_out = 1U; + } + + pp->DPID = PIPE_DPID[pp->data_toggle_out]; + break; + + case USB_EPTYPE_INTR: + pp->DPID = PIPE_DPID[pp->data_toggle_out]; + + pp->data_toggle_out ^= 1U; + break; + + case USB_EPTYPE_BULK: + pp->DPID = PIPE_DPID[pp->data_toggle_out]; + break; + + case USB_EPTYPE_ISOC: + pp->DPID = PIPE_DPID[0]; + break; + + default: + break; + } + + usbh_request_submit (pudev, pp_num); + + return USBH_OK; +} + +/*! + \brief receive a data packet from the USB device + \param[in] pudev: pointer to usb core instance + \param[in] buf: data buffer which will be received from USB device + \param[in] pp_num: pipe number + \param[in] len: length of the data to be received + \param[out] none + \retval operation status +*/ +usbh_status usbh_data_recev (usb_core_driver *pudev, uint8_t *buf, uint8_t pp_num, uint16_t len) +{ + usb_pipe *pp = &pudev->host.pipe[pp_num]; + + pp->xfer_buf = buf; + pp->xfer_len = len; + + switch (pp->ep.type) { + case USB_EPTYPE_CTRL: + pp->DPID = PIPE_DPID[1]; + break; + + case USB_EPTYPE_INTR: + pp->DPID = PIPE_DPID[pp->data_toggle_in]; + + /* Toggle DATA PID */ + pp->data_toggle_in ^= 1U; + break; + + case USB_EPTYPE_BULK: + pp->DPID = PIPE_DPID[pp->data_toggle_in]; + break; + + case USB_EPTYPE_ISOC: + pp->DPID = PIPE_DPID[0]; + break; + + default: + break; + } + + usbh_request_submit (pudev, pp_num); + + return USBH_OK; +} + +/*! + \brief USB control transfer handler + \param[in] puhost: pointer to USB host + \param[out] none + \retval operation status +*/ +usbh_status usbh_ctl_handler (usbh_host *puhost) +{ + usbh_status status = USBH_BUSY; + + switch (puhost->control.ctl_state) { + case CTL_SETUP: + usbh_setup_transc (puhost); + break; + + case CTL_DATA_IN: + usbh_data_in_transc (puhost); + break; + + case CTL_DATA_OUT: + usbh_data_out_transc (puhost); + break; + + case CTL_STATUS_IN: + usbh_status_in_transc (puhost); + break; + + case CTL_STATUS_OUT: + usbh_status_out_transc (puhost); + break; + + case CTL_FINISH: + puhost->control.ctl_state = CTL_IDLE; + + status = USBH_OK; + break; + + case CTL_ERROR: + if (++puhost->control.error_count <= USBH_MAX_ERROR_COUNT) { + /* do the transmission again, starting from SETUP packet */ + puhost->control.ctl_state = CTL_SETUP; + } else { + status = USBH_FAIL; + } + break; + + default: + break; + } + + return status; +} + +/*! + \brief wait for USB URB(USB request block) state + \param[in] puhost: pointer to USB host + \param[in] pp_num: pipe number + \param[in] wait_time: wait time + \param[out] none + \retval USB URB state +*/ +static usb_urb_state usbh_urb_wait (usbh_host *puhost, uint8_t pp_num, uint32_t wait_time) +{ + usb_urb_state urb_status = URB_IDLE; + + while (URB_DONE != (urb_status = usbh_urbstate_get(puhost->data, pp_num))) { + if (URB_NOTREADY == urb_status) { + break; + } else if (URB_STALL == urb_status) { + puhost->control.ctl_state = CTL_SETUP; + break; + } else if (URB_ERROR == urb_status) { + puhost->control.ctl_state = CTL_ERROR; + break; + } else if ((wait_time > 0U) && ((usb_curframe_get(puhost->data)- puhost->control.timer) > wait_time)) { + /* timeout for in transfer */ + puhost->control.ctl_state = CTL_ERROR; + break; + } else { + /* no operation, just wait */ + } + } + + return urb_status; +} + +/*! + \brief USB setup transaction + \param[in] puhost: pointer to USB host + \param[out] none + \retval none +*/ +static void usbh_setup_transc (usbh_host *puhost) +{ + /* send a SETUP packet */ + usbh_ctlsetup_send (puhost->data, + puhost->control.setup.data, + puhost->control.pipe_out_num); + + if (URB_DONE == usbh_urb_wait (puhost, puhost->control.pipe_out_num, 0U)) { + uint8_t dir = (puhost->control.setup.req.bmRequestType & USB_TRX_MASK); + + if (puhost->control.setup.req.wLength) { + if (USB_TRX_IN == dir) { + puhost->control.ctl_state = CTL_DATA_IN; + } else { + puhost->control.ctl_state = CTL_DATA_OUT; + } + } else { + if (USB_TRX_IN == dir) { + puhost->control.ctl_state = CTL_STATUS_OUT; + } else { + puhost->control.ctl_state = CTL_STATUS_IN; + } + } + + /* set the delay timer to enable timeout for data stage completion */ + puhost->control.timer = (uint16_t)usb_curframe_get(puhost->data); + } +} + +/*! + \brief USB data IN transaction + \param[in] puhost: pointer to USB host + \param[out] none + \retval none +*/ +static void usbh_data_in_transc (usbh_host *puhost) +{ + usbh_data_recev (puhost->data, + puhost->control.buf, + puhost->control.pipe_in_num, + puhost->control.ctl_len); + + if (URB_DONE == usbh_urb_wait (puhost, puhost->control.pipe_in_num, DATA_STAGE_TIMEOUT)) { + puhost->control.ctl_state = CTL_STATUS_OUT; + + puhost->control.timer = (uint16_t)usb_curframe_get(puhost->data); + } +} + +/*! + \brief USB data OUT transaction + \param[in] puhost: pointer to USB host + \param[out] none + \retval none +*/ +static void usbh_data_out_transc (usbh_host *puhost) +{ + usbh_pipe_toggle_set(puhost->data, puhost->control.pipe_out_num, 1U); + + usbh_data_send (puhost->data, + puhost->control.buf, + puhost->control.pipe_out_num, + puhost->control.ctl_len); + + if (URB_DONE == usbh_urb_wait (puhost, puhost->control.pipe_out_num, DATA_STAGE_TIMEOUT)) { + puhost->control.ctl_state = CTL_STATUS_IN; + + puhost->control.timer = (uint16_t)usb_curframe_get(puhost->data); + } +} + +/*! + \brief USB status IN transaction + \param[in] puhost: pointer to USB host + \param[out] none + \retval none +*/ +static void usbh_status_in_transc (usbh_host *puhost) +{ + uint8_t pp_num = puhost->control.pipe_in_num; + + usbh_data_recev (puhost->data, NULL, pp_num, 0U); + + if (URB_DONE == usbh_urb_wait (puhost, pp_num, NODATA_STAGE_TIMEOUT)) { + puhost->control.ctl_state = CTL_FINISH; + } +} + +/*! + \brief USB status OUT transaction + \param[in] puhost: pointer to USB host + \param[out] none + \retval none +*/ +static void usbh_status_out_transc (usbh_host *puhost) +{ + uint8_t pp_num = puhost->control.pipe_out_num; + + usbh_data_send (puhost->data, NULL, pp_num, 0U); + + if (URB_DONE == usbh_urb_wait (puhost, pp_num, NODATA_STAGE_TIMEOUT)) { + puhost->control.ctl_state = CTL_FINISH; + } +} + +/*! + \brief prepare a pipe and start a transfer + \param[in] pudev: pointer to usb core instance + \param[in] pp_num: pipe number + \param[out] none + \retval operation status +*/ +static uint32_t usbh_request_submit (usb_core_driver *pudev, uint8_t pp_num) +{ + pudev->host.pipe[pp_num].urb_state = URB_IDLE; + pudev->host.pipe[pp_num].xfer_count = 0U; + + return (uint32_t)usb_pipe_xfer (pudev, pp_num); +} diff --git a/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/ustd/class/cdc/usb_cdc.h b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/ustd/class/cdc/usb_cdc.h new file mode 100644 index 0000000000..f228286740 --- /dev/null +++ b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/ustd/class/cdc/usb_cdc.h @@ -0,0 +1,180 @@ +/*! + \file usb_cdc.h + \brief the header file of communication device class standard + + \version 2020-08-01, V3.0.0, firmware for GD32F30x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef __USB_CDC_H +#define __USB_CDC_H + +#include "usb_ch9_std.h" + +/* communications device class code */ +#define USB_CLASS_CDC 0x02U + +/* communications interface class control protocol codes */ +#define USB_CDC_PROTOCOL_NONE 0x00U +#define USB_CDC_PROTOCOL_AT 0x01U +#define USB_CDC_PROTOCOL_VENDOR 0xFFU + +/* data interface class code */ +#define USB_CLASS_DATA 0x0AU + +#define USB_DESCTYPE_CDC_ACM 0x21U +#define USB_DESCTYPE_CS_INTERFACE 0x24U + +#define USB_CDC_ACM_CONFIG_DESC_SIZE 0x43U + +/* class-specific notification codes for pstn subclasses */ +#define USB_CDC_NOTIFY_SERIAL_STATE 0x20U + +/* class-specific request codes */ +#define SEND_ENCAPSULATED_COMMAND 0x00U +#define GET_ENCAPSULATED_RESPONSE 0x01U +#define SET_COMM_FEATURE 0x02U +#define GET_COMM_FEATURE 0x03U +#define CLEAR_COMM_FEATURE 0x04U + +#define SET_AUX_LINE_STATE 0x10U +#define SET_HOOK_STATE 0x11U +#define PULSE_SETUP 0x12U +#define SEND_PULSE 0x13U +#define SET_PULSE_TIME 0x14U +#define RING_AUX_JACK 0x15U + +#define SET_LINE_CODING 0x20U +#define GET_LINE_CODING 0x21U +#define SET_CONTROL_LINE_STATE 0x22U +#define SEND_BREAK 0x23U +#define NO_CMD 0xFFU + +#define SET_RINGER_PARMS 0x30U +#define GET_RINGER_PARMS 0x31U +#define SET_OPERATION_PARMS 0x32U +#define GET_OPERATION_PARMS 0x33U +#define SET_LINE_PARMS 0x34U +#define GET_LINE_PARMS 0x35U +#define DIAL_DIGITS 0x36U +#define SET_UNIT_PARAMETER 0x37U +#define GET_UNIT_PARAMETER 0x38U +#define CLEAR_UNIT_PARAMETER 0x39U +#define GET_PROFILE 0x3AU + +#define SET_ETHERNET_MULTICAST_FILTERS 0x40U +#define SET_ETHERNET_POWER_MANAGEMENT_PATTERN FILTER 0x41U +#define GET_ETHERNET_POWER_MANAGEMENT_PATTERN FILTER 0x42U +#define SET_ETHERNET_PACKET_FILTER 0x43U +#define GET_ETHERNET_STATISTIC 0x44U + +#define SET_ATM_DATA_FORMAT 0x50U +#define GET_ATM_DEVICE_STATISTICS 0x51U +#define SET_ATM_DEFAULT_VC 0x52U +#define GET_ATM_VC_STATISTICS 0x53U + +/* wValue for set control line state */ +#define CDC_ACTIVATE_CARRIER_SIGNAL_RTS 0x0002U +#define CDC_DEACTIVATE_CARRIER_SIGNAL_RTS 0x0000U +#define CDC_ACTIVATE_SIGNAL_DTR 0x0001U +#define CDC_DEACTIVATE_SIGNAL_DTR 0x0000U + +/* CDC subclass code */ +enum usb_cdc_subclass { + USB_CDC_SUBCLASS_RESERVED = 0U, /*!< reserved */ + USB_CDC_SUBCLASS_DLCM, /*!< direct line control mode */ + USB_CDC_SUBCLASS_ACM, /*!< abstract control mode */ + USB_CDC_SUBCLASS_TCM, /*!< telephone control mode */ + USB_CDC_SUBCLASS_MCM, /*!< multichannel control model */ + USB_CDC_SUBCLASS_CCM, /*!< CAPI control model */ + USB_CDC_SUBCLASS_ENCM, /*!< ethernet networking control model */ + USB_CDC_SUBCLASS_ANCM /*!< ATM networking control model */ +}; + +#pragma pack(1) + +/* cdc acm line coding structure */ +typedef struct { + uint32_t dwDTERate; /*!< data terminal rate */ + uint8_t bCharFormat; /*!< stop bits */ + uint8_t bParityType; /*!< parity */ + uint8_t bDataBits; /*!< data bits */ +} acm_line; + +/* notification structure */ +typedef struct { + uint8_t bmRequestType; /*!< type of request */ + uint8_t bNotification; /*!< communication interface class notifications */ + uint16_t wValue; /*!< value of notification */ + uint16_t wIndex; /*!< index of interface */ + uint16_t wLength; /*!< length of notification data */ +} acm_notification; + +typedef struct { + usb_desc_header header; /*!< descriptor header, including type and size. */ + uint8_t bDescriptorSubtype; /*!< bDescriptorSubtype: header function descriptor */ + uint16_t bcdCDC; /*!< bcdCDC: low byte of spec release number (CDC1.10) */ +} usb_desc_header_func; + +typedef struct { + usb_desc_header header; /*!< descriptor header, including type and size. */ + uint8_t bDescriptorSubtype; /*!< bDescriptorSubtype: call management function descriptor */ + uint8_t bmCapabilities; /*!< bmCapabilities: D0 is reset, D1 is ignored */ + uint8_t bDataInterface; /*!< bDataInterface: 1 interface used for call management */ +} usb_desc_call_managment_func; + +typedef struct { + usb_desc_header header; /*!< descriptor header, including type and size. */ + uint8_t bDescriptorSubtype; /*!< bDescriptorSubtype: abstract control management descriptor */ + uint8_t bmCapabilities; /*!< bmCapabilities: D1 */ +} usb_desc_acm_func; + +typedef struct { + usb_desc_header header; /*!< descriptor header, including type and size. */ + uint8_t bDescriptorSubtype; /*!< bDescriptorSubtype: union function descriptor */ + uint8_t bMasterInterface; /*!< bMasterInterface: communication class interface */ + uint8_t bSlaveInterface0; /*!< bSlaveInterface0: data class interface */ +} usb_desc_union_func; + +#pragma pack() + +typedef struct { + usb_desc_config config; + usb_desc_itf cmd_itf; + usb_desc_header_func cdc_header; + usb_desc_call_managment_func cdc_call_managment; + usb_desc_acm_func cdc_acm; + usb_desc_union_func cdc_union; + usb_desc_ep cdc_cmd_endpoint; + usb_desc_itf cdc_data_interface; + usb_desc_ep cdc_out_endpoint; + usb_desc_ep cdc_in_endpoint; +} usb_cdc_desc_config_set; + +#endif /* __USB_CDC_H */ diff --git a/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/ustd/class/hid/usb_hid.h b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/ustd/class/hid/usb_hid.h new file mode 100644 index 0000000000..3e70345725 --- /dev/null +++ b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/ustd/class/hid/usb_hid.h @@ -0,0 +1,83 @@ +/*! + \file usb_hid.h + \brief definitions for the USB HID class + + \version 2020-08-01, V3.0.0, firmware for GD32F30x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef __USB_HID_H +#define __USB_HID_H + +#include "usb_ch9_std.h" + +#define USB_HID_CLASS 0x03U + +#define USB_DESCTYPE_HID 0x21U +#define USB_DESCTYPE_REPORT 0x22U + +/* HID subclass code */ +#define USB_HID_SUBCLASS_BOOT_ITF 0x01U + +/* HID protocol codes */ +#define USB_HID_PROTOCOL_KEYBOARD 0x01U +#define USB_HID_PROTOCOL_MOUSE 0x02U + +#define GET_REPORT 0x01U +#define GET_IDLE 0x02U +#define GET_PROTOCOL 0x03U +#define SET_REPORT 0x09U +#define SET_IDLE 0x0AU +#define SET_PROTOCOL 0x0BU + +#pragma pack(1) + +typedef struct +{ + usb_desc_header header; /*!< regular descriptor header containing the descriptor's type and length */ + + uint16_t bcdHID; /*!< BCD encoded version that the HID descriptor and device complies to */ + uint8_t bCountryCode; /*!< country code of the localized device, or zero if universal */ + uint8_t bNumDescriptors; /*!< total number of HID report descriptors for the interface */ + uint8_t bDescriptorType; /*!< type of HID report */ + uint16_t wDescriptorLength; /*!< length of the associated HID report descriptor, in bytes */ +} usb_desc_hid; + +#pragma pack() + +typedef struct +{ + usb_desc_config config; + usb_desc_itf hid_itf; + usb_desc_hid hid_vendor; + usb_desc_ep hid_epin; + usb_desc_ep hid_epout; +}usb_hid_desc_config_set; + +#endif /* __USB_HID_H */ diff --git a/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/ustd/class/msc/msc_bbb.h b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/ustd/class/msc/msc_bbb.h new file mode 100644 index 0000000000..4c5d11781e --- /dev/null +++ b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/ustd/class/msc/msc_bbb.h @@ -0,0 +1,69 @@ +/*! + \file msc_bbb.h + \brief definitions for the USB MSC BBB(bulk/bulk/bulk) protocol + + \version 2020-08-01, V3.0.0, firmware for GD32F30x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef __MSC_BBB_H +#define __MSC_BBB_H + +#include "usb_ch9_std.h" + +#define BBB_CBW_SIGNATURE 0x43425355U +#define BBB_CSW_SIGNATURE 0x53425355U +#define BBB_CBW_LENGTH 31U +#define BBB_CSW_LENGTH 13U + +typedef struct { + uint32_t dCBWSignature; + uint32_t dCBWTag; + uint32_t dCBWDataTransferLength; + uint8_t bmCBWFlags; + uint8_t bCBWLUN; + uint8_t bCBWCBLength; + uint8_t CBWCB[16]; +}msc_bbb_cbw; + +typedef struct { + uint32_t dCSWSignature; + uint32_t dCSWTag; + uint32_t dCSWDataResidue; + uint8_t bCSWStatus; +}msc_bbb_csw; + +/* CSW command status */ +enum msc_csw_status { + CSW_CMD_PASSED = 0, + CSW_CMD_FAILED, + CSW_PHASE_ERROR +}; + +#endif /* __MSC_BBB_H */ diff --git a/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/ustd/class/msc/msc_scsi.h b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/ustd/class/msc/msc_scsi.h new file mode 100644 index 0000000000..ddfbcc8a2d --- /dev/null +++ b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/ustd/class/msc/msc_scsi.h @@ -0,0 +1,117 @@ +/*! + \file msc_scsi.h + \brief definitions for the USB MSC SCSI commands + + \version 2020-08-01, V3.0.0, firmware for GD32F30x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef __MSC_SCSI_H +#define __MSC_SCSI_H + +#include "usb_ch9_std.h" + +/* SCSI commands */ +#define SCSI_FORMAT_UNIT 0x04U +#define SCSI_INQUIRY 0x12U +#define SCSI_MODE_SELECT6 0x15U +#define SCSI_MODE_SELECT10 0x55U +#define SCSI_MODE_SENSE6 0x1AU +#define SCSI_READ_TOC_DATA 0x43U +#define SCSI_MODE_SENSE10 0x5AU +#define SCSI_ALLOW_MEDIUM_REMOVAL 0x1EU +#define SCSI_READ6 0x08U +#define SCSI_READ10 0x28U +#define SCSI_READ12 0xA8U +#define SCSI_READ16 0x88U + +#define SCSI_READ_CAPACITY10 0x25U +#define SCSI_READ_CAPACITY16 0x9EU + +#define SCSI_REQUEST_SENSE 0x03U +#define SCSI_START_STOP_UNIT 0x1BU +#define SCSI_TEST_UNIT_READY 0x00U +#define SCSI_WRITE6 0x0AU +#define SCSI_WRITE10 0x2AU +#define SCSI_WRITE12 0xAAU +#define SCSI_WRITE16 0x8AU + +#define SCSI_VERIFY10 0x2FU +#define SCSI_VERIFY12 0xAFU +#define SCSI_VERIFY16 0x8FU + +#define SCSI_SEND_DIAGNOSTIC 0x1DU +#define SCSI_READ_FORMAT_CAPACITIES 0x23U + +#define INVALID_CDB 0x20U +#define INVALID_FIELED_IN_COMMAND 0x24U +#define PARAMETER_LIST_LENGTH_ERROR 0x1AU +#define INVALID_FIELD_IN_PARAMETER_LIST 0x26U +#define ADDRESS_OUT_OF_RANGE 0x21U +#define MEDIUM_NOT_PRESENT 0x3AU +#define MEDIUM_HAVE_CHANGED 0x28U +#define WRITE_PROTECTED 0x27U +#define UNRECOVERED_READ_ERROR 0x11U +#define WRITE_FAULT 0x03U + +#define READ_FORMAT_CAPACITY_DATA_LEN 0x0CU +#define READ_CAPACITY10_DATA_LEN 0x08U +#define MODE_SENSE10_DATA_LEN 0x08U +#define MODE_SENSE6_DATA_LEN 0x04U +#define READ_TOC_CMD_LEN 0x14U +#define REQUEST_SENSE_DATA_LEN 0x12U +#define STANDARD_INQUIRY_DATA_LEN 0x24U +#define BLKVFY 0x04U + +enum sense_state { + NO_SENSE = 0U, + RECOVERED_ERROR, + NOT_READY, + MEDIUM_ERROR, + HARDWARE_ERROR, + ILLEGAL_REQUEST, + UNIT_ATTENTION, + DATA_PROTECT, + BLANK_CHECK, + VENDOR_SPECIFIC, + COPY_ABORTED, + ABORTED_COMMAND, + RESERVED, + VOLUME_OVERFLOW, + MISCOMPARE +}; + +typedef struct { + uint8_t SenseKey; + uint32_t Information; + uint8_t ASC; + uint8_t ASCQ; +} msc_scsi_sense; + +#endif /* __MSC_SCSI_H */ diff --git a/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/ustd/class/msc/usb_msc.h b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/ustd/class/msc/usb_msc.h new file mode 100644 index 0000000000..21cf610890 --- /dev/null +++ b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/ustd/class/msc/usb_msc.h @@ -0,0 +1,68 @@ +/*! + \file usb_msc.h + \brief definitions for the USB MSC class + + \version 2020-08-01, V3.0.0, firmware for GD32F30x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef __USB_MSC_H +#define __USB_MSC_H + +#include "usb_ch9_std.h" + +/* mass storage device class code */ +#define USB_CLASS_MSC 0x08U + +/* mass storage subclass code */ +#define USB_MSC_SUBCLASS_RBC 0x01U +#define USB_MSC_SUBCLASS_ATAPI 0x02U +#define USB_MSC_SUBCLASS_UFI 0x04U +#define USB_MSC_SUBCLASS_SCSI 0x06U +#define USB_MSC_SUBCLASS_LOCKABLE 0x07U +#define USB_MSC_SUBCLASS_IEEE1667 0x08U + +/* mass storage interface class control protocol codes */ +#define USB_MSC_PROTOCOL_CBI 0x00U +#define USB_MSC_PROTOCOL_CBI_ALT 0x01U +#define USB_MSC_PROTOCOL_BBB 0x50U + +/* mass storage request codes */ +#define USB_MSC_REQ_CODES_ADSC 0x00U +#define USB_MSC_REQ_CODES_GET 0xFCU +#define USB_MSC_REQ_CODES_PUT 0xFDU +#define USB_MSC_REQ_CODES_GML 0xFEU +#define USB_MSC_REQ_CODES_BOMSR 0xFFU + +#define BBB_GET_MAX_LUN 0xFEU +#define BBB_RESET 0xFFU + +#define SCSI_CMD_LENGTH 16U + +#endif /* __USB_MSC_H */ diff --git a/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/ustd/common/usb_ch9_std.h b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/ustd/common/usb_ch9_std.h new file mode 100644 index 0000000000..3dd33165ff --- /dev/null +++ b/bsp/gd32/libraries/GD32F30x_Firmware_Library/GD32F30x_usbfs_library/ustd/common/usb_ch9_std.h @@ -0,0 +1,248 @@ +/*! + \file usb_ch9_std.h + \brief USB 2.0 standard defines + + \version 2020-08-01, V3.0.0, firmware for GD32F30x +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef __USB_CH9_STD_H +#define __USB_CH9_STD_H + +#include "usb_conf.h" + +#define USB_DEV_QUALIFIER_DESC_LEN 0x0AU /*!< USB device qualifier descriptor length */ +#define USB_DEV_DESC_LEN 0x12U /*!< USB device descriptor length */ +#define USB_CFG_DESC_LEN 0x09U /*!< USB configuration descriptor length */ +#define USB_ITF_DESC_LEN 0x09U /*!< USB interface descriptor length */ +#define USB_EP_DESC_LEN 0x07U /*!< USB endpoint descriptor length */ +#define USB_IAD_DESC_LEN 0x08U /*!< USB IAD descriptor length */ +#define USB_OTG_DESC_LEN 0x03U /*!< USB device OTG descriptor length */ + +#define USB_SETUP_PACKET_LEN 0x08U /*!< USB setup packet length */ + +/* bit 7 of bmRequestType: data phase transfer direction */ +#define USB_TRX_MASK 0x80U /*!< USB transfer direction mask */ +#define USB_TRX_OUT 0x00U /*!< USB transfer OUT direction */ +#define USB_TRX_IN 0x80U /*!< USB transfer IN direction */ + +/* bit 6..5 of bmRequestType: request type */ +#define USB_REQTYPE_STRD 0x00U /*!< USB standard request */ +#define USB_REQTYPE_CLASS 0x20U /*!< USB class request */ +#define USB_REQTYPE_VENDOR 0x40U /*!< USB vendor request */ +#define USB_REQTYPE_MASK 0x60U /*!< USB request mask */ + +#define USBD_BUS_POWERED 0x00U /*!< USB bus power supply */ +#define USBD_SELF_POWERED 0x01U /*!< USB self power supply */ + +#define USB_STATUS_REMOTE_WAKEUP 2U /*!< USB is in remote wakeup status */ +#define USB_STATUS_SELF_POWERED 1U /*!< USB is in self powered status */ + +/* bit 4..0 of bmRequestType: recipient type */ +enum _usb_recp_type { + USB_RECPTYPE_DEV = 0x0U, /*!< USB device request type */ + USB_RECPTYPE_ITF = 0x1U, /*!< USB interface request type */ + USB_RECPTYPE_EP = 0x2U, /*!< USB endpoint request type */ + USB_RECPTYPE_MASK = 0x3U /*!< USB request type mask */ +}; + +/* bRequest value */ +enum _usb_request { + USB_GET_STATUS = 0x0U, /*!< USB get status request */ + USB_CLEAR_FEATURE = 0x1U, /*!< USB clear feature request */ + USB_RESERVED2 = 0x2U, + USB_SET_FEATURE = 0x3U, /*!< USB set feature request */ + USB_RESERVED4 = 0x4U, + USB_SET_ADDRESS = 0x5U, /*!< USB set address request */ + USB_GET_DESCRIPTOR = 0x6U, /*!< USB get descriptor request */ + USB_SET_DESCRIPTOR = 0x7U, /*!< USB set descriptor request */ + USB_GET_CONFIGURATION = 0x8U, /*!< USB get configuration request */ + USB_SET_CONFIGURATION = 0x9U, /*!< USB set configuration request */ + USB_GET_INTERFACE = 0xAU, /*!< USB get interface request */ + USB_SET_INTERFACE = 0xBU, /*!< USB set interface request */ + USB_SYNCH_FRAME = 0xCU /*!< USB synchronize frame request */ +}; + +/* descriptor types of USB specifications */ +enum _usb_desctype { + USB_DESCTYPE_DEV = 0x1U, /*!< USB device descriptor type */ + USB_DESCTYPE_CONFIG = 0x2U, /*!< USB configuration descriptor type */ + USB_DESCTYPE_STR = 0x3U, /*!< USB string descriptor type */ + USB_DESCTYPE_ITF = 0x4U, /*!< USB interface descriptor type */ + USB_DESCTYPE_EP = 0x5U, /*!< USB endpoint descriptor type */ + USB_DESCTYPE_DEV_QUALIFIER = 0x6U, /*!< USB device qualifier descriptor type */ + USB_DESCTYPE_OTHER_SPD_CONFIG = 0x7U, /*!< USB other speed configuration descriptor type */ + USB_DESCTYPE_ITF_POWER = 0x8U, /*!< USB interface power descriptor type */ + USB_DESCTYPE_IAD = 0xBU, /*!< USB interface association descriptor type */ + USB_DESCTYPE_BOS = 0xFU /*!< USB BOS descriptor type */ +}; + +/* USB Endpoint Descriptor bmAttributes bit definitions */ +/* bits 1..0 : transfer type */ +enum _usbx_type { + USB_EP_ATTR_CTL = 0x0U, /*!< USB control transfer type */ + USB_EP_ATTR_ISO = 0x1U, /*!< USB Isochronous transfer type */ + USB_EP_ATTR_BULK = 0x2U, /*!< USB Bulk transfer type */ + USB_EP_ATTR_INT = 0x3U /*!< USB Interrupt transfer type */ +}; + +/* bits 3..2 : Sync type (only if ISOCHRONOUS) */ +#define USB_EP_ATTR_NOSYNC 0x00U /*!< No Synchronization */ +#define USB_EP_ATTR_ASYNC 0x04U /*!< Asynchronous */ +#define USB_EP_ATTR_ADAPTIVE 0x08U /*!< Adaptive */ +#define USB_EP_ATTR_SYNC 0x0CU /*!< Synchronous */ +#define USB_EP_ATTR_SYNCTYPE 0x0CU /*!< Synchronous type */ + +/* bits 5..4 : usage type (only if ISOCHRONOUS) */ +#define USB_EP_ATTR_DATA 0x00U /*!< Data endpoint */ +#define USB_EP_ATTR_FEEDBACK 0x10U /*!< Feedback endpoint */ +#define USB_EP_ATTR_IMPLICIT_FEEDBACK_DATA 0x20U /*!< Implicit feedback Data endpoint */ +#define USB_EP_ATTR_USAGETYPE 0x30U /*!< Usage type */ + +/* endpoint max packet size bits12..11 */ +#define USB_EP_MPS_ADD_0 (0x00 << 11) /*!< None(1 transaction per microframe */ +#define USB_EP_MPS_ADD_1 (0x01 << 11) /*!< 1 additional(2 transaction per microframe */ +#define USB_EP_MPS_ADD_2 (0x02 << 11) /*!< 2 additional(3 transaction per microframe */ + +#define FEATURE_SELECTOR_EP 0x00U /*!< USB endpoint feature selector */ +#define FEATURE_SELECTOR_DEV 0x01U /*!< USB device feature selector */ +#define FEATURE_SELECTOR_REMOTEWAKEUP 0x01U /*!< USB feature selector remote wakeup */ + +#define BYTE_SWAP(addr) (((uint16_t)(*((uint8_t *)(addr)))) + \ + (uint16_t)(((uint16_t)(*(((uint8_t *)(addr)) + 1U))) << 8U)) + +#define BYTE_LOW(x) ((uint8_t)((x) & 0x00FFU)) +#define BYTE_HIGH(x) ((uint8_t)(((x) & 0xFF00U) >> 8U)) + +#define USB_MIN(a, b) (((a) < (b)) ? (a) : (b)) + +#define USB_DEFAULT_CONFIG 0U + +/* USB classes */ +#define USB_CLASS_HID 0x03U /*!< USB HID class */ +#define USB_CLASS_MSC 0x08U /*!< USB MSC class */ + +/* use the following values when USB host need to get descriptor */ +#define USBH_DESC(x) (((x)<< 8U) & 0xFF00U) + +/* as per USB specs 9.2.6.4 :standard request with data request timeout: 5sec + standard request with no data stage timeout : 50ms */ +#define DATA_STAGE_TIMEOUT 5000U /*!< USB data stage timeout*/ +#define NODATA_STAGE_TIMEOUT 50U /*!< USB no data stage timeout*/ + +#pragma pack(1) + +/* USB standard device request structure */ +typedef struct _usb_req { + uint8_t bmRequestType; /*!< type of request */ + uint8_t bRequest; /*!< request of setup packet */ + uint16_t wValue; /*!< value of setup packet */ + uint16_t wIndex; /*!< index of setup packet */ + uint16_t wLength; /*!< length of setup packet */ +} usb_req; + +/* USB setup packet define */ +typedef union _usb_setup { + uint8_t data[8]; + + usb_req req; +} usb_setup; + +/* USB descriptor defines */ + +typedef struct _usb_desc_header { + uint8_t bLength; /*!< size of the descriptor */ + uint8_t bDescriptorType; /*!< type of the descriptor */ +} usb_desc_header; + +typedef struct _usb_desc_dev { + usb_desc_header header; /*!< descriptor header, including type and size */ + + uint16_t bcdUSB; /*!< BCD of the supported USB specification */ + uint8_t bDeviceClass; /*!< USB device class */ + uint8_t bDeviceSubClass; /*!< USB device subclass */ + uint8_t bDeviceProtocol; /*!< USB device protocol */ + uint8_t bMaxPacketSize0; /*!< size of the control (address 0) endpoint's bank in bytes */ + uint16_t idVendor; /*!< vendor ID for the USB product */ + uint16_t idProduct; /*!< unique product ID for the USB product */ + uint16_t bcdDevice; /*!< product release (version) number */ + uint8_t iManufacturer; /*!< string index for the manufacturer's name */ + uint8_t iProduct; /*!< string index for the product name/details */ + uint8_t iSerialNumber; /*!< string index for the product's globally unique hexadecimal serial number */ + uint8_t bNumberConfigurations; /*!< total number of configurations supported by the device */ +} usb_desc_dev; + +typedef struct _usb_desc_config { + usb_desc_header header; /*!< descriptor header, including type and size */ + + uint16_t wTotalLength; /*!< size of the configuration descriptor header,and all sub descriptors inside the configuration */ + uint8_t bNumInterfaces; /*!< total number of interfaces in the configuration */ + uint8_t bConfigurationValue; /*!< configuration index of the current configuration */ + uint8_t iConfiguration; /*!< index of a string descriptor describing the configuration */ + uint8_t bmAttributes; /*!< configuration attributes */ + uint8_t bMaxPower; /*!< maximum power consumption of the device while in the current configuration */ +} usb_desc_config; + +typedef struct _usb_desc_itf { + usb_desc_header header; /*!< descriptor header, including type and size */ + + uint8_t bInterfaceNumber; /*!< index of the interface in the current configuration */ + uint8_t bAlternateSetting; /*!< alternate setting for the interface number */ + uint8_t bNumEndpoints; /*!< total number of endpoints in the interface */ + uint8_t bInterfaceClass; /*!< interface class ID */ + uint8_t bInterfaceSubClass; /*!< interface subclass ID */ + uint8_t bInterfaceProtocol; /*!< interface protocol ID */ + uint8_t iInterface; /*!< index of the string descriptor describing the interface */ +} usb_desc_itf; + +typedef struct _usb_desc_ep { + usb_desc_header header; /*!< descriptor header, including type and size. */ + + uint8_t bEndpointAddress; /*!< logical address of the endpoint */ + uint8_t bmAttributes; /*!< endpoint attributes */ + uint16_t wMaxPacketSize; /*!< size of the endpoint bank, in bytes */ + uint8_t bInterval; /*!< polling interval in milliseconds for the endpoint if it is an INTERRUPT or ISOCHRONOUS type */ +} usb_desc_ep; + +typedef struct _usb_desc_LANGID { + usb_desc_header header; /*!< descriptor header, including type and size. */ + uint16_t wLANGID; /*!< LANGID code */ +} usb_desc_LANGID; + +typedef struct _usb_desc_str { + usb_desc_header header; /*!< descriptor header, including type and size. */ + uint16_t unicode_string[64]; /*!< unicode string data */ +} usb_desc_str; + +#pragma pack() + +/* compute string descriptor length */ +#define USB_STRING_LEN(unicode_chars) (sizeof(usb_desc_header) + ((unicode_chars) << 1U)) + +#endif /* __USB_CH9_STD_H */ diff --git a/bsp/gd32/libraries/GD32F30x_Firmware_Library/SConscript b/bsp/gd32/libraries/GD32F30x_Firmware_Library/SConscript new file mode 100644 index 0000000000..09f70ea989 --- /dev/null +++ b/bsp/gd32/libraries/GD32F30x_Firmware_Library/SConscript @@ -0,0 +1,57 @@ +import rtconfig +from building import * + +# get current directory +cwd = GetCurrentDir() + +# The set of source files associated with this SConscript file. + +src = Split(''' +CMSIS/GD/GD32F30x/Source/system_gd32f30x.c +GD32F30x_standard_peripheral/Source/gd32f30x_gpio.c +GD32F30x_standard_peripheral/Source/gd32f30x_rcu.c +GD32F30x_standard_peripheral/Source/gd32f30x_exti.c +GD32F30x_standard_peripheral/Source/gd32f30x_misc.c +''') + +if GetDepend(['RT_USING_SERIAL']): + src += ['GD32F30x_standard_peripheral/Source/gd32f30x_usart.c'] + +if GetDepend(['RT_USING_I2C']): + src += ['GD32F30x_standard_peripheral/Source/gd32f30x_i2c.c'] + +if GetDepend(['RT_USING_SPI']): + src += ['GD32F30x_standard_peripheral/Source/gd32f30x_spi.c'] + +if GetDepend(['RT_USING_CAN']): + src += ['GD32F30x_standard_peripheral/Source/gd32f30x_can.c'] + +if GetDepend(['BSP_USING_ETH']): + src += ['GD32F30x_standard_peripheral/Source/gd32f30x_enet.c'] + +if GetDepend(['RT_USING_ADC']): + src += ['GD32F30x_standard_peripheral/Source/gd32f30x_adc.c'] + +if GetDepend(['RT_USING_DAC']): + src += ['GD32F30x_standard_peripheral/Source/gd32f30x_dac.c'] + +if GetDepend(['RT_USING_RTC']): + src += ['GD32F30x_standard_peripheral/Source/gd32f30x_rtc.c'] + +if GetDepend(['RT_USING_WDT']): + src += ['GD32F30x_standard_peripheral/Source/gd32f30x_wwdgt.c'] + src += ['GD32F30x_standard_peripheral/Source/gd32f30x_fwdgt.c'] + +if GetDepend(['RT_USING_SDIO']): + src += ['GD32F30x_standard_peripheral/Source/gd32f30x_sdio.c'] + +path = [ + cwd + '/CMSIS/GD/GD32F30x/Include', + cwd + '/CMSIS', + cwd + '/GD32F30x_standard_peripheral/Include',] + +CPPDEFINES = ['USE_STDPERIPH_DRIVER'] + +group = DefineGroup('Libraries', src, depend = [''], CPPPATH = path, CPPDEFINES = CPPDEFINES) + +Return('group') diff --git a/bsp/gd32/libraries/GD32F4xx_HAL/CMSIS/GD/GD32F4xx/Include/gd32f4xx.h b/bsp/gd32/libraries/GD32F4xx_Firmware_Library/CMSIS/GD/GD32F4xx/Include/gd32f4xx.h similarity index 100% rename from bsp/gd32/libraries/GD32F4xx_HAL/CMSIS/GD/GD32F4xx/Include/gd32f4xx.h rename to bsp/gd32/libraries/GD32F4xx_Firmware_Library/CMSIS/GD/GD32F4xx/Include/gd32f4xx.h diff --git a/bsp/gd32/libraries/GD32F4xx_HAL/CMSIS/GD/GD32F4xx/Include/system_gd32f4xx.h b/bsp/gd32/libraries/GD32F4xx_Firmware_Library/CMSIS/GD/GD32F4xx/Include/system_gd32f4xx.h similarity index 100% rename from bsp/gd32/libraries/GD32F4xx_HAL/CMSIS/GD/GD32F4xx/Include/system_gd32f4xx.h rename to bsp/gd32/libraries/GD32F4xx_Firmware_Library/CMSIS/GD/GD32F4xx/Include/system_gd32f4xx.h diff --git a/bsp/gd32/libraries/GD32F4xx_HAL/CMSIS/GD/GD32F4xx/Source/ARM/startup_gd32f4xx.s b/bsp/gd32/libraries/GD32F4xx_Firmware_Library/CMSIS/GD/GD32F4xx/Source/ARM/startup_gd32f4xx.s similarity index 100% rename from bsp/gd32/libraries/GD32F4xx_HAL/CMSIS/GD/GD32F4xx/Source/ARM/startup_gd32f4xx.s rename to bsp/gd32/libraries/GD32F4xx_Firmware_Library/CMSIS/GD/GD32F4xx/Source/ARM/startup_gd32f4xx.s diff --git a/bsp/gd32/libraries/GD32F4xx_HAL/CMSIS/GD/GD32F4xx/Source/GCC/startup_gd32f4xx.S b/bsp/gd32/libraries/GD32F4xx_Firmware_Library/CMSIS/GD/GD32F4xx/Source/GCC/startup_gd32f4xx.s similarity index 100% rename from bsp/gd32/libraries/GD32F4xx_HAL/CMSIS/GD/GD32F4xx/Source/GCC/startup_gd32f4xx.S rename to bsp/gd32/libraries/GD32F4xx_Firmware_Library/CMSIS/GD/GD32F4xx/Source/GCC/startup_gd32f4xx.s diff --git a/bsp/gd32/libraries/GD32F4xx_HAL/CMSIS/GD/GD32F4xx/Source/IAR/startup_gd32f4xx.s b/bsp/gd32/libraries/GD32F4xx_Firmware_Library/CMSIS/GD/GD32F4xx/Source/IAR/startup_gd32f4xx.s similarity index 100% rename from bsp/gd32/libraries/GD32F4xx_HAL/CMSIS/GD/GD32F4xx/Source/IAR/startup_gd32f4xx.s rename to bsp/gd32/libraries/GD32F4xx_Firmware_Library/CMSIS/GD/GD32F4xx/Source/IAR/startup_gd32f4xx.s diff --git a/bsp/gd32/libraries/GD32F4xx_HAL/CMSIS/GD/GD32F4xx/Source/system_gd32f4xx.c b/bsp/gd32/libraries/GD32F4xx_Firmware_Library/CMSIS/GD/GD32F4xx/Source/system_gd32f4xx.c similarity index 100% rename from bsp/gd32/libraries/GD32F4xx_HAL/CMSIS/GD/GD32F4xx/Source/system_gd32f4xx.c rename to bsp/gd32/libraries/GD32F4xx_Firmware_Library/CMSIS/GD/GD32F4xx/Source/system_gd32f4xx.c diff --git a/bsp/gd32/libraries/GD32F4xx_Firmware_Library/CMSIS/core_cm4.h b/bsp/gd32/libraries/GD32F4xx_Firmware_Library/CMSIS/core_cm4.h new file mode 100644 index 0000000000..e3cd89f728 --- /dev/null +++ b/bsp/gd32/libraries/GD32F4xx_Firmware_Library/CMSIS/core_cm4.h @@ -0,0 +1,1790 @@ +/**************************************************************************//** + * @file core_cm4.h + * @brief CMSIS Cortex-M4 Core Peripheral Access Layer Header File + * @version V3.30 + * @date 17. February 2014 + * + * @note + * + ******************************************************************************/ +/* Copyright (c) 2009 - 2014 ARM LIMITED + + All rights reserved. + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + - Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + - Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + - Neither the name of ARM nor the names of its contributors may be used + to endorse or promote products derived from this software without + specific prior written permission. + * + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDERS AND CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + ---------------------------------------------------------------------------*/ + + +#if defined ( __ICCARM__ ) + #pragma system_include /* treat file as system include file for MISRA check */ +#endif + +#ifdef __cplusplus + extern "C" { +#endif + +#ifndef __CORE_CM4_H_GENERIC +#define __CORE_CM4_H_GENERIC + +/** \page CMSIS_MISRA_Exceptions MISRA-C:2004 Compliance Exceptions + CMSIS violates the following MISRA-C:2004 rules: + + \li Required Rule 8.5, object/function definition in header file.
+ Function definitions in header files are used to allow 'inlining'. + + \li Required Rule 18.4, declaration of union type or object of union type: '{...}'.
+ Unions are used for effective representation of core registers. + + \li Advisory Rule 19.7, Function-like macro defined.
+ Function-like macros are used to allow more efficient code. + */ + + +/******************************************************************************* + * CMSIS definitions + ******************************************************************************/ +/** \ingroup Cortex_M4 + @{ + */ + +/* CMSIS CM4 definitions */ +#define __CM4_CMSIS_VERSION_MAIN (0x03) /*!< [31:16] CMSIS HAL main version */ +#define __CM4_CMSIS_VERSION_SUB (0x20) /*!< [15:0] CMSIS HAL sub version */ +#define __CM4_CMSIS_VERSION ((__CM4_CMSIS_VERSION_MAIN << 16) | \ + __CM4_CMSIS_VERSION_SUB ) /*!< CMSIS HAL version number */ + +#define __CORTEX_M (0x04) /*!< Cortex-M Core */ + + +#if defined ( __CC_ARM ) + #define __ASM __asm /*!< asm keyword for ARM Compiler */ + #define __INLINE __inline /*!< inline keyword for ARM Compiler */ + #define __STATIC_INLINE static __inline + +#elif defined ( __GNUC__ ) + #define __ASM __asm /*!< asm keyword for GNU Compiler */ + #define __INLINE inline /*!< inline keyword for GNU Compiler */ + #define __STATIC_INLINE static inline + +#elif defined ( __ICCARM__ ) + #define __ASM __asm /*!< asm keyword for IAR Compiler */ + #define __INLINE inline /*!< inline keyword for IAR Compiler. Only available in High optimization mode! */ + #define __STATIC_INLINE static inline + +#elif defined ( __TMS470__ ) + #define __ASM __asm /*!< asm keyword for TI CCS Compiler */ + #define __STATIC_INLINE static inline + +#elif defined ( __TASKING__ ) + #define __ASM __asm /*!< asm keyword for TASKING Compiler */ + #define __INLINE inline /*!< inline keyword for TASKING Compiler */ + #define __STATIC_INLINE static inline + +#elif defined ( __CSMC__ ) /* Cosmic */ + #define __packed + #define __ASM _asm /*!< asm keyword for COSMIC Compiler */ + #define __INLINE inline /*use -pc99 on compile line !< inline keyword for COSMIC Compiler */ + #define __STATIC_INLINE static inline + +#endif + +/** __FPU_USED indicates whether an FPU is used or not. For this, __FPU_PRESENT has to be checked prior to making use of FPU specific registers and functions. +*/ +#if defined ( __CC_ARM ) + #if defined __TARGET_FPU_VFP + #if (__FPU_PRESENT == 1) + #define __FPU_USED 1 + #else + #warning "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" + #define __FPU_USED 0 + #endif + #else + #define __FPU_USED 0 + #endif + +#elif defined ( __GNUC__ ) + #if defined (__VFP_FP__) && !defined(__SOFTFP__) + #if (__FPU_PRESENT == 1) + #define __FPU_USED 1 + #else + #warning "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" + #define __FPU_USED 0 + #endif + #else + #define __FPU_USED 0 + #endif + +#elif defined ( __ICCARM__ ) + #if defined __ARMVFP__ + #if (__FPU_PRESENT == 1) + #define __FPU_USED 1 + #else + #warning "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" + #define __FPU_USED 0 + #endif + #else + #define __FPU_USED 0 + #endif + +#elif defined ( __TMS470__ ) + #if defined __TI_VFP_SUPPORT__ + #if (__FPU_PRESENT == 1) + #define __FPU_USED 1 + #else + #warning "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" + #define __FPU_USED 0 + #endif + #else + #define __FPU_USED 0 + #endif + +#elif defined ( __TASKING__ ) + #if defined __FPU_VFP__ + #if (__FPU_PRESENT == 1) + #define __FPU_USED 1 + #else + #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" + #define __FPU_USED 0 + #endif + #else + #define __FPU_USED 0 + #endif + +#elif defined ( __CSMC__ ) /* Cosmic */ + #if ( __CSMC__ & 0x400) // FPU present for parser + #if (__FPU_PRESENT == 1) + #define __FPU_USED 1 + #else + #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" + #define __FPU_USED 0 + #endif + #else + #define __FPU_USED 0 + #endif +#endif + +#include /* standard types definitions */ +#include /* Core Instruction Access */ +#include /* Core Function Access */ +#include /* Compiler specific SIMD Intrinsics */ + +#endif /* __CORE_CM4_H_GENERIC */ + +#ifndef __CMSIS_GENERIC + +#ifndef __CORE_CM4_H_DEPENDANT +#define __CORE_CM4_H_DEPENDANT + +/* check device defines and use defaults */ +#if defined __CHECK_DEVICE_DEFINES + #ifndef __CM4_REV + #define __CM4_REV 0x0000 + #warning "__CM4_REV not defined in device header file; using default!" + #endif + + #ifndef __FPU_PRESENT + #define __FPU_PRESENT 0 + #warning "__FPU_PRESENT not defined in device header file; using default!" + #endif + + #ifndef __MPU_PRESENT + #define __MPU_PRESENT 0 + #warning "__MPU_PRESENT not defined in device header file; using default!" + #endif + + #ifndef __NVIC_PRIO_BITS + #define __NVIC_PRIO_BITS 4 + #warning "__NVIC_PRIO_BITS not defined in device header file; using default!" + #endif + + #ifndef __Vendor_SysTickConfig + #define __Vendor_SysTickConfig 0 + #warning "__Vendor_SysTickConfig not defined in device header file; using default!" + #endif +#endif + +/* IO definitions (access restrictions to peripheral registers) */ +/** + \defgroup CMSIS_glob_defs CMSIS Global Defines + + IO Type Qualifiers are used + \li to specify the access to peripheral variables. + \li for automatic generation of peripheral register debug information. +*/ +#ifdef __cplusplus + #define __I volatile /*!< Defines 'read only' permissions */ +#else + #define __I volatile const /*!< Defines 'read only' permissions */ +#endif +#define __O volatile /*!< Defines 'write only' permissions */ +#define __IO volatile /*!< Defines 'read / write' permissions */ + +/*@} end of group Cortex_M4 */ + + + +/******************************************************************************* + * Register Abstraction + Core Register contain: + - Core Register + - Core NVIC Register + - Core SCB Register + - Core SysTick Register + - Core Debug Register + - Core MPU Register + - Core FPU Register + ******************************************************************************/ +/** \defgroup CMSIS_core_register Defines and Type Definitions + \brief Type definitions and defines for Cortex-M processor based devices. +*/ + +/** \ingroup CMSIS_core_register + \defgroup CMSIS_CORE Status and Control Registers + \brief Core Register type definitions. + @{ + */ + +/** \brief Union type to access the Application Program Status Register (APSR). + */ +typedef union +{ + struct + { +#if (__CORTEX_M != 0x04) + uint32_t _reserved0:27; /*!< bit: 0..26 Reserved */ +#else + uint32_t _reserved0:16; /*!< bit: 0..15 Reserved */ + uint32_t GE:4; /*!< bit: 16..19 Greater than or Equal flags */ + uint32_t _reserved1:7; /*!< bit: 20..26 Reserved */ +#endif + uint32_t Q:1; /*!< bit: 27 Saturation condition flag */ + uint32_t V:1; /*!< bit: 28 Overflow condition code flag */ + uint32_t C:1; /*!< bit: 29 Carry condition code flag */ + uint32_t Z:1; /*!< bit: 30 Zero condition code flag */ + uint32_t N:1; /*!< bit: 31 Negative condition code flag */ + } b; /*!< Structure used for bit access */ + uint32_t w; /*!< Type used for word access */ +} APSR_Type; + + +/** \brief Union type to access the Interrupt Program Status Register (IPSR). + */ +typedef union +{ + struct + { + uint32_t ISR:9; /*!< bit: 0.. 8 Exception number */ + uint32_t _reserved0:23; /*!< bit: 9..31 Reserved */ + } b; /*!< Structure used for bit access */ + uint32_t w; /*!< Type used for word access */ +} IPSR_Type; + + +/** \brief Union type to access the Special-Purpose Program Status Registers (xPSR). + */ +typedef union +{ + struct + { + uint32_t ISR:9; /*!< bit: 0.. 8 Exception number */ +#if (__CORTEX_M != 0x04) + uint32_t _reserved0:15; /*!< bit: 9..23 Reserved */ +#else + uint32_t _reserved0:7; /*!< bit: 9..15 Reserved */ + uint32_t GE:4; /*!< bit: 16..19 Greater than or Equal flags */ + uint32_t _reserved1:4; /*!< bit: 20..23 Reserved */ +#endif + uint32_t T:1; /*!< bit: 24 Thumb bit (read 0) */ + uint32_t IT:2; /*!< bit: 25..26 saved IT state (read 0) */ + uint32_t Q:1; /*!< bit: 27 Saturation condition flag */ + uint32_t V:1; /*!< bit: 28 Overflow condition code flag */ + uint32_t C:1; /*!< bit: 29 Carry condition code flag */ + uint32_t Z:1; /*!< bit: 30 Zero condition code flag */ + uint32_t N:1; /*!< bit: 31 Negative condition code flag */ + } b; /*!< Structure used for bit access */ + uint32_t w; /*!< Type used for word access */ +} xPSR_Type; + + +/** \brief Union type to access the Control Registers (CONTROL). + */ +typedef union +{ + struct + { + uint32_t nPRIV:1; /*!< bit: 0 Execution privilege in Thread mode */ + uint32_t SPSEL:1; /*!< bit: 1 Stack to be used */ + uint32_t FPCA:1; /*!< bit: 2 FP extension active flag */ + uint32_t _reserved0:29; /*!< bit: 3..31 Reserved */ + } b; /*!< Structure used for bit access */ + uint32_t w; /*!< Type used for word access */ +} CONTROL_Type; + +/*@} end of group CMSIS_CORE */ + + +/** \ingroup CMSIS_core_register + \defgroup CMSIS_NVIC Nested Vectored Interrupt Controller (NVIC) + \brief Type definitions for the NVIC Registers + @{ + */ + +/** \brief Structure type to access the Nested Vectored Interrupt Controller (NVIC). + */ +typedef struct +{ + __IO uint32_t ISER[8]; /*!< Offset: 0x000 (R/W) Interrupt Set Enable Register */ + uint32_t RESERVED0[24]; + __IO uint32_t ICER[8]; /*!< Offset: 0x080 (R/W) Interrupt Clear Enable Register */ + uint32_t RSERVED1[24]; + __IO uint32_t ISPR[8]; /*!< Offset: 0x100 (R/W) Interrupt Set Pending Register */ + uint32_t RESERVED2[24]; + __IO uint32_t ICPR[8]; /*!< Offset: 0x180 (R/W) Interrupt Clear Pending Register */ + uint32_t RESERVED3[24]; + __IO uint32_t IABR[8]; /*!< Offset: 0x200 (R/W) Interrupt Active bit Register */ + uint32_t RESERVED4[56]; + __IO uint8_t IP[240]; /*!< Offset: 0x300 (R/W) Interrupt Priority Register (8Bit wide) */ + uint32_t RESERVED5[644]; + __O uint32_t STIR; /*!< Offset: 0xE00 ( /W) Software Trigger Interrupt Register */ +} NVIC_Type; + +/* Software Triggered Interrupt Register Definitions */ +#define NVIC_STIR_INTID_Pos 0 /*!< STIR: INTLINESNUM Position */ +#define NVIC_STIR_INTID_Msk (0x1FFUL << NVIC_STIR_INTID_Pos) /*!< STIR: INTLINESNUM Mask */ + +/*@} end of group CMSIS_NVIC */ + + +/** \ingroup CMSIS_core_register + \defgroup CMSIS_SCB System Control Block (SCB) + \brief Type definitions for the System Control Block Registers + @{ + */ + +/** \brief Structure type to access the System Control Block (SCB). + */ +typedef struct +{ + __I uint32_t CPUID; /*!< Offset: 0x000 (R/ ) CPUID Base Register */ + __IO uint32_t ICSR; /*!< Offset: 0x004 (R/W) Interrupt Control and State Register */ + __IO uint32_t VTOR; /*!< Offset: 0x008 (R/W) Vector Table Offset Register */ + __IO uint32_t AIRCR; /*!< Offset: 0x00C (R/W) Application Interrupt and Reset Control Register */ + __IO uint32_t SCR; /*!< Offset: 0x010 (R/W) System Control Register */ + __IO uint32_t CCR; /*!< Offset: 0x014 (R/W) Configuration Control Register */ + __IO uint8_t SHP[12]; /*!< Offset: 0x018 (R/W) System Handlers Priority Registers (4-7, 8-11, 12-15) */ + __IO uint32_t SHCSR; /*!< Offset: 0x024 (R/W) System Handler Control and State Register */ + __IO uint32_t CFSR; /*!< Offset: 0x028 (R/W) Configurable Fault Status Register */ + __IO uint32_t HFSR; /*!< Offset: 0x02C (R/W) HardFault Status Register */ + __IO uint32_t DFSR; /*!< Offset: 0x030 (R/W) Debug Fault Status Register */ + __IO uint32_t MMFAR; /*!< Offset: 0x034 (R/W) MemManage Fault Address Register */ + __IO uint32_t BFAR; /*!< Offset: 0x038 (R/W) BusFault Address Register */ + __IO uint32_t AFSR; /*!< Offset: 0x03C (R/W) Auxiliary Fault Status Register */ + __I uint32_t PFR[2]; /*!< Offset: 0x040 (R/ ) Processor Feature Register */ + __I uint32_t DFR; /*!< Offset: 0x048 (R/ ) Debug Feature Register */ + __I uint32_t ADR; /*!< Offset: 0x04C (R/ ) Auxiliary Feature Register */ + __I uint32_t MMFR[4]; /*!< Offset: 0x050 (R/ ) Memory Model Feature Register */ + __I uint32_t ISAR[5]; /*!< Offset: 0x060 (R/ ) Instruction Set Attributes Register */ + uint32_t RESERVED0[5]; + __IO uint32_t CPACR; /*!< Offset: 0x088 (R/W) Coprocessor Access Control Register */ +} SCB_Type; + +/* SCB CPUID Register Definitions */ +#define SCB_CPUID_IMPLEMENTER_Pos 24 /*!< SCB CPUID: IMPLEMENTER Position */ +#define SCB_CPUID_IMPLEMENTER_Msk (0xFFUL << SCB_CPUID_IMPLEMENTER_Pos) /*!< SCB CPUID: IMPLEMENTER Mask */ + +#define SCB_CPUID_VARIANT_Pos 20 /*!< SCB CPUID: VARIANT Position */ +#define SCB_CPUID_VARIANT_Msk (0xFUL << SCB_CPUID_VARIANT_Pos) /*!< SCB CPUID: VARIANT Mask */ + +#define SCB_CPUID_ARCHITECTURE_Pos 16 /*!< SCB CPUID: ARCHITECTURE Position */ +#define SCB_CPUID_ARCHITECTURE_Msk (0xFUL << SCB_CPUID_ARCHITECTURE_Pos) /*!< SCB CPUID: ARCHITECTURE Mask */ + +#define SCB_CPUID_PARTNO_Pos 4 /*!< SCB CPUID: PARTNO Position */ +#define SCB_CPUID_PARTNO_Msk (0xFFFUL << SCB_CPUID_PARTNO_Pos) /*!< SCB CPUID: PARTNO Mask */ + +#define SCB_CPUID_REVISION_Pos 0 /*!< SCB CPUID: REVISION Position */ +#define SCB_CPUID_REVISION_Msk (0xFUL << SCB_CPUID_REVISION_Pos) /*!< SCB CPUID: REVISION Mask */ + +/* SCB Interrupt Control State Register Definitions */ +#define SCB_ICSR_NMIPENDSET_Pos 31 /*!< SCB ICSR: NMIPENDSET Position */ +#define SCB_ICSR_NMIPENDSET_Msk (1UL << SCB_ICSR_NMIPENDSET_Pos) /*!< SCB ICSR: NMIPENDSET Mask */ + +#define SCB_ICSR_PENDSVSET_Pos 28 /*!< SCB ICSR: PENDSVSET Position */ +#define SCB_ICSR_PENDSVSET_Msk (1UL << SCB_ICSR_PENDSVSET_Pos) /*!< SCB ICSR: PENDSVSET Mask */ + +#define SCB_ICSR_PENDSVCLR_Pos 27 /*!< SCB ICSR: PENDSVCLR Position */ +#define SCB_ICSR_PENDSVCLR_Msk (1UL << SCB_ICSR_PENDSVCLR_Pos) /*!< SCB ICSR: PENDSVCLR Mask */ + +#define SCB_ICSR_PENDSTSET_Pos 26 /*!< SCB ICSR: PENDSTSET Position */ +#define SCB_ICSR_PENDSTSET_Msk (1UL << SCB_ICSR_PENDSTSET_Pos) /*!< SCB ICSR: PENDSTSET Mask */ + +#define SCB_ICSR_PENDSTCLR_Pos 25 /*!< SCB ICSR: PENDSTCLR Position */ +#define SCB_ICSR_PENDSTCLR_Msk (1UL << SCB_ICSR_PENDSTCLR_Pos) /*!< SCB ICSR: PENDSTCLR Mask */ + +#define SCB_ICSR_ISRPREEMPT_Pos 23 /*!< SCB ICSR: ISRPREEMPT Position */ +#define SCB_ICSR_ISRPREEMPT_Msk (1UL << SCB_ICSR_ISRPREEMPT_Pos) /*!< SCB ICSR: ISRPREEMPT Mask */ + +#define SCB_ICSR_ISRPENDING_Pos 22 /*!< SCB ICSR: ISRPENDING Position */ +#define SCB_ICSR_ISRPENDING_Msk (1UL << SCB_ICSR_ISRPENDING_Pos) /*!< SCB ICSR: ISRPENDING Mask */ + +#define SCB_ICSR_VECTPENDING_Pos 12 /*!< SCB ICSR: VECTPENDING Position */ +#define SCB_ICSR_VECTPENDING_Msk (0x1FFUL << SCB_ICSR_VECTPENDING_Pos) /*!< SCB ICSR: VECTPENDING Mask */ + +#define SCB_ICSR_RETTOBASE_Pos 11 /*!< SCB ICSR: RETTOBASE Position */ +#define SCB_ICSR_RETTOBASE_Msk (1UL << SCB_ICSR_RETTOBASE_Pos) /*!< SCB ICSR: RETTOBASE Mask */ + +#define SCB_ICSR_VECTACTIVE_Pos 0 /*!< SCB ICSR: VECTACTIVE Position */ +#define SCB_ICSR_VECTACTIVE_Msk (0x1FFUL << SCB_ICSR_VECTACTIVE_Pos) /*!< SCB ICSR: VECTACTIVE Mask */ + +/* SCB Vector Table Offset Register Definitions */ +#define SCB_VTOR_TBLOFF_Pos 7 /*!< SCB VTOR: TBLOFF Position */ +#define SCB_VTOR_TBLOFF_Msk (0x1FFFFFFUL << SCB_VTOR_TBLOFF_Pos) /*!< SCB VTOR: TBLOFF Mask */ + +/* SCB Application Interrupt and Reset Control Register Definitions */ +#define SCB_AIRCR_VECTKEY_Pos 16 /*!< SCB AIRCR: VECTKEY Position */ +#define SCB_AIRCR_VECTKEY_Msk (0xFFFFUL << SCB_AIRCR_VECTKEY_Pos) /*!< SCB AIRCR: VECTKEY Mask */ + +#define SCB_AIRCR_VECTKEYSTAT_Pos 16 /*!< SCB AIRCR: VECTKEYSTAT Position */ +#define SCB_AIRCR_VECTKEYSTAT_Msk (0xFFFFUL << SCB_AIRCR_VECTKEYSTAT_Pos) /*!< SCB AIRCR: VECTKEYSTAT Mask */ + +#define SCB_AIRCR_ENDIANESS_Pos 15 /*!< SCB AIRCR: ENDIANESS Position */ +#define SCB_AIRCR_ENDIANESS_Msk (1UL << SCB_AIRCR_ENDIANESS_Pos) /*!< SCB AIRCR: ENDIANESS Mask */ + +#define SCB_AIRCR_PRIGROUP_Pos 8 /*!< SCB AIRCR: PRIGROUP Position */ +#define SCB_AIRCR_PRIGROUP_Msk (7UL << SCB_AIRCR_PRIGROUP_Pos) /*!< SCB AIRCR: PRIGROUP Mask */ + +#define SCB_AIRCR_SYSRESETREQ_Pos 2 /*!< SCB AIRCR: SYSRESETREQ Position */ +#define SCB_AIRCR_SYSRESETREQ_Msk (1UL << SCB_AIRCR_SYSRESETREQ_Pos) /*!< SCB AIRCR: SYSRESETREQ Mask */ + +#define SCB_AIRCR_VECTCLRACTIVE_Pos 1 /*!< SCB AIRCR: VECTCLRACTIVE Position */ +#define SCB_AIRCR_VECTCLRACTIVE_Msk (1UL << SCB_AIRCR_VECTCLRACTIVE_Pos) /*!< SCB AIRCR: VECTCLRACTIVE Mask */ + +#define SCB_AIRCR_VECTRESET_Pos 0 /*!< SCB AIRCR: VECTRESET Position */ +#define SCB_AIRCR_VECTRESET_Msk (1UL << SCB_AIRCR_VECTRESET_Pos) /*!< SCB AIRCR: VECTRESET Mask */ + +/* SCB System Control Register Definitions */ +#define SCB_SCR_SEVONPEND_Pos 4 /*!< SCB SCR: SEVONPEND Position */ +#define SCB_SCR_SEVONPEND_Msk (1UL << SCB_SCR_SEVONPEND_Pos) /*!< SCB SCR: SEVONPEND Mask */ + +#define SCB_SCR_SLEEPDEEP_Pos 2 /*!< SCB SCR: SLEEPDEEP Position */ +#define SCB_SCR_SLEEPDEEP_Msk (1UL << SCB_SCR_SLEEPDEEP_Pos) /*!< SCB SCR: SLEEPDEEP Mask */ + +#define SCB_SCR_SLEEPONEXIT_Pos 1 /*!< SCB SCR: SLEEPONEXIT Position */ +#define SCB_SCR_SLEEPONEXIT_Msk (1UL << SCB_SCR_SLEEPONEXIT_Pos) /*!< SCB SCR: SLEEPONEXIT Mask */ + +/* SCB Configuration Control Register Definitions */ +#define SCB_CCR_STKALIGN_Pos 9 /*!< SCB CCR: STKALIGN Position */ +#define SCB_CCR_STKALIGN_Msk (1UL << SCB_CCR_STKALIGN_Pos) /*!< SCB CCR: STKALIGN Mask */ + +#define SCB_CCR_BFHFNMIGN_Pos 8 /*!< SCB CCR: BFHFNMIGN Position */ +#define SCB_CCR_BFHFNMIGN_Msk (1UL << SCB_CCR_BFHFNMIGN_Pos) /*!< SCB CCR: BFHFNMIGN Mask */ + +#define SCB_CCR_DIV_0_TRP_Pos 4 /*!< SCB CCR: DIV_0_TRP Position */ +#define SCB_CCR_DIV_0_TRP_Msk (1UL << SCB_CCR_DIV_0_TRP_Pos) /*!< SCB CCR: DIV_0_TRP Mask */ + +#define SCB_CCR_UNALIGN_TRP_Pos 3 /*!< SCB CCR: UNALIGN_TRP Position */ +#define SCB_CCR_UNALIGN_TRP_Msk (1UL << SCB_CCR_UNALIGN_TRP_Pos) /*!< SCB CCR: UNALIGN_TRP Mask */ + +#define SCB_CCR_USERSETMPEND_Pos 1 /*!< SCB CCR: USERSETMPEND Position */ +#define SCB_CCR_USERSETMPEND_Msk (1UL << SCB_CCR_USERSETMPEND_Pos) /*!< SCB CCR: USERSETMPEND Mask */ + +#define SCB_CCR_NONBASETHRDENA_Pos 0 /*!< SCB CCR: NONBASETHRDENA Position */ +#define SCB_CCR_NONBASETHRDENA_Msk (1UL << SCB_CCR_NONBASETHRDENA_Pos) /*!< SCB CCR: NONBASETHRDENA Mask */ + +/* SCB System Handler Control and State Register Definitions */ +#define SCB_SHCSR_USGFAULTENA_Pos 18 /*!< SCB SHCSR: USGFAULTENA Position */ +#define SCB_SHCSR_USGFAULTENA_Msk (1UL << SCB_SHCSR_USGFAULTENA_Pos) /*!< SCB SHCSR: USGFAULTENA Mask */ + +#define SCB_SHCSR_BUSFAULTENA_Pos 17 /*!< SCB SHCSR: BUSFAULTENA Position */ +#define SCB_SHCSR_BUSFAULTENA_Msk (1UL << SCB_SHCSR_BUSFAULTENA_Pos) /*!< SCB SHCSR: BUSFAULTENA Mask */ + +#define SCB_SHCSR_MEMFAULTENA_Pos 16 /*!< SCB SHCSR: MEMFAULTENA Position */ +#define SCB_SHCSR_MEMFAULTENA_Msk (1UL << SCB_SHCSR_MEMFAULTENA_Pos) /*!< SCB SHCSR: MEMFAULTENA Mask */ + +#define SCB_SHCSR_SVCALLPENDED_Pos 15 /*!< SCB SHCSR: SVCALLPENDED Position */ +#define SCB_SHCSR_SVCALLPENDED_Msk (1UL << SCB_SHCSR_SVCALLPENDED_Pos) /*!< SCB SHCSR: SVCALLPENDED Mask */ + +#define SCB_SHCSR_BUSFAULTPENDED_Pos 14 /*!< SCB SHCSR: BUSFAULTPENDED Position */ +#define SCB_SHCSR_BUSFAULTPENDED_Msk (1UL << SCB_SHCSR_BUSFAULTPENDED_Pos) /*!< SCB SHCSR: BUSFAULTPENDED Mask */ + +#define SCB_SHCSR_MEMFAULTPENDED_Pos 13 /*!< SCB SHCSR: MEMFAULTPENDED Position */ +#define SCB_SHCSR_MEMFAULTPENDED_Msk (1UL << SCB_SHCSR_MEMFAULTPENDED_Pos) /*!< SCB SHCSR: MEMFAULTPENDED Mask */ + +#define SCB_SHCSR_USGFAULTPENDED_Pos 12 /*!< SCB SHCSR: USGFAULTPENDED Position */ +#define SCB_SHCSR_USGFAULTPENDED_Msk (1UL << SCB_SHCSR_USGFAULTPENDED_Pos) /*!< SCB SHCSR: USGFAULTPENDED Mask */ + +#define SCB_SHCSR_SYSTICKACT_Pos 11 /*!< SCB SHCSR: SYSTICKACT Position */ +#define SCB_SHCSR_SYSTICKACT_Msk (1UL << SCB_SHCSR_SYSTICKACT_Pos) /*!< SCB SHCSR: SYSTICKACT Mask */ + +#define SCB_SHCSR_PENDSVACT_Pos 10 /*!< SCB SHCSR: PENDSVACT Position */ +#define SCB_SHCSR_PENDSVACT_Msk (1UL << SCB_SHCSR_PENDSVACT_Pos) /*!< SCB SHCSR: PENDSVACT Mask */ + +#define SCB_SHCSR_MONITORACT_Pos 8 /*!< SCB SHCSR: MONITORACT Position */ +#define SCB_SHCSR_MONITORACT_Msk (1UL << SCB_SHCSR_MONITORACT_Pos) /*!< SCB SHCSR: MONITORACT Mask */ + +#define SCB_SHCSR_SVCALLACT_Pos 7 /*!< SCB SHCSR: SVCALLACT Position */ +#define SCB_SHCSR_SVCALLACT_Msk (1UL << SCB_SHCSR_SVCALLACT_Pos) /*!< SCB SHCSR: SVCALLACT Mask */ + +#define SCB_SHCSR_USGFAULTACT_Pos 3 /*!< SCB SHCSR: USGFAULTACT Position */ +#define SCB_SHCSR_USGFAULTACT_Msk (1UL << SCB_SHCSR_USGFAULTACT_Pos) /*!< SCB SHCSR: USGFAULTACT Mask */ + +#define SCB_SHCSR_BUSFAULTACT_Pos 1 /*!< SCB SHCSR: BUSFAULTACT Position */ +#define SCB_SHCSR_BUSFAULTACT_Msk (1UL << SCB_SHCSR_BUSFAULTACT_Pos) /*!< SCB SHCSR: BUSFAULTACT Mask */ + +#define SCB_SHCSR_MEMFAULTACT_Pos 0 /*!< SCB SHCSR: MEMFAULTACT Position */ +#define SCB_SHCSR_MEMFAULTACT_Msk (1UL << SCB_SHCSR_MEMFAULTACT_Pos) /*!< SCB SHCSR: MEMFAULTACT Mask */ + +/* SCB Configurable Fault Status Registers Definitions */ +#define SCB_CFSR_USGFAULTSR_Pos 16 /*!< SCB CFSR: Usage Fault Status Register Position */ +#define SCB_CFSR_USGFAULTSR_Msk (0xFFFFUL << SCB_CFSR_USGFAULTSR_Pos) /*!< SCB CFSR: Usage Fault Status Register Mask */ + +#define SCB_CFSR_BUSFAULTSR_Pos 8 /*!< SCB CFSR: Bus Fault Status Register Position */ +#define SCB_CFSR_BUSFAULTSR_Msk (0xFFUL << SCB_CFSR_BUSFAULTSR_Pos) /*!< SCB CFSR: Bus Fault Status Register Mask */ + +#define SCB_CFSR_MEMFAULTSR_Pos 0 /*!< SCB CFSR: Memory Manage Fault Status Register Position */ +#define SCB_CFSR_MEMFAULTSR_Msk (0xFFUL << SCB_CFSR_MEMFAULTSR_Pos) /*!< SCB CFSR: Memory Manage Fault Status Register Mask */ + +/* SCB Hard Fault Status Registers Definitions */ +#define SCB_HFSR_DEBUGEVT_Pos 31 /*!< SCB HFSR: DEBUGEVT Position */ +#define SCB_HFSR_DEBUGEVT_Msk (1UL << SCB_HFSR_DEBUGEVT_Pos) /*!< SCB HFSR: DEBUGEVT Mask */ + +#define SCB_HFSR_FORCED_Pos 30 /*!< SCB HFSR: FORCED Position */ +#define SCB_HFSR_FORCED_Msk (1UL << SCB_HFSR_FORCED_Pos) /*!< SCB HFSR: FORCED Mask */ + +#define SCB_HFSR_VECTTBL_Pos 1 /*!< SCB HFSR: VECTTBL Position */ +#define SCB_HFSR_VECTTBL_Msk (1UL << SCB_HFSR_VECTTBL_Pos) /*!< SCB HFSR: VECTTBL Mask */ + +/* SCB Debug Fault Status Register Definitions */ +#define SCB_DFSR_EXTERNAL_Pos 4 /*!< SCB DFSR: EXTERNAL Position */ +#define SCB_DFSR_EXTERNAL_Msk (1UL << SCB_DFSR_EXTERNAL_Pos) /*!< SCB DFSR: EXTERNAL Mask */ + +#define SCB_DFSR_VCATCH_Pos 3 /*!< SCB DFSR: VCATCH Position */ +#define SCB_DFSR_VCATCH_Msk (1UL << SCB_DFSR_VCATCH_Pos) /*!< SCB DFSR: VCATCH Mask */ + +#define SCB_DFSR_DWTTRAP_Pos 2 /*!< SCB DFSR: DWTTRAP Position */ +#define SCB_DFSR_DWTTRAP_Msk (1UL << SCB_DFSR_DWTTRAP_Pos) /*!< SCB DFSR: DWTTRAP Mask */ + +#define SCB_DFSR_BKPT_Pos 1 /*!< SCB DFSR: BKPT Position */ +#define SCB_DFSR_BKPT_Msk (1UL << SCB_DFSR_BKPT_Pos) /*!< SCB DFSR: BKPT Mask */ + +#define SCB_DFSR_HALTED_Pos 0 /*!< SCB DFSR: HALTED Position */ +#define SCB_DFSR_HALTED_Msk (1UL << SCB_DFSR_HALTED_Pos) /*!< SCB DFSR: HALTED Mask */ + +/*@} end of group CMSIS_SCB */ + + +/** \ingroup CMSIS_core_register + \defgroup CMSIS_SCnSCB System Controls not in SCB (SCnSCB) + \brief Type definitions for the System Control and ID Register not in the SCB + @{ + */ + +/** \brief Structure type to access the System Control and ID Register not in the SCB. + */ +typedef struct +{ + uint32_t RESERVED0[1]; + __I uint32_t ICTR; /*!< Offset: 0x004 (R/ ) Interrupt Controller Type Register */ + __IO uint32_t ACTLR; /*!< Offset: 0x008 (R/W) Auxiliary Control Register */ +} SCnSCB_Type; + +/* Interrupt Controller Type Register Definitions */ +#define SCnSCB_ICTR_INTLINESNUM_Pos 0 /*!< ICTR: INTLINESNUM Position */ +#define SCnSCB_ICTR_INTLINESNUM_Msk (0xFUL << SCnSCB_ICTR_INTLINESNUM_Pos) /*!< ICTR: INTLINESNUM Mask */ + +/* Auxiliary Control Register Definitions */ +#define SCnSCB_ACTLR_DISOOFP_Pos 9 /*!< ACTLR: DISOOFP Position */ +#define SCnSCB_ACTLR_DISOOFP_Msk (1UL << SCnSCB_ACTLR_DISOOFP_Pos) /*!< ACTLR: DISOOFP Mask */ + +#define SCnSCB_ACTLR_DISFPCA_Pos 8 /*!< ACTLR: DISFPCA Position */ +#define SCnSCB_ACTLR_DISFPCA_Msk (1UL << SCnSCB_ACTLR_DISFPCA_Pos) /*!< ACTLR: DISFPCA Mask */ + +#define SCnSCB_ACTLR_DISFOLD_Pos 2 /*!< ACTLR: DISFOLD Position */ +#define SCnSCB_ACTLR_DISFOLD_Msk (1UL << SCnSCB_ACTLR_DISFOLD_Pos) /*!< ACTLR: DISFOLD Mask */ + +#define SCnSCB_ACTLR_DISDEFWBUF_Pos 1 /*!< ACTLR: DISDEFWBUF Position */ +#define SCnSCB_ACTLR_DISDEFWBUF_Msk (1UL << SCnSCB_ACTLR_DISDEFWBUF_Pos) /*!< ACTLR: DISDEFWBUF Mask */ + +#define SCnSCB_ACTLR_DISMCYCINT_Pos 0 /*!< ACTLR: DISMCYCINT Position */ +#define SCnSCB_ACTLR_DISMCYCINT_Msk (1UL << SCnSCB_ACTLR_DISMCYCINT_Pos) /*!< ACTLR: DISMCYCINT Mask */ + +/*@} end of group CMSIS_SCnotSCB */ + + +/** \ingroup CMSIS_core_register + \defgroup CMSIS_SysTick System Tick Timer (SysTick) + \brief Type definitions for the System Timer Registers. + @{ + */ + +/** \brief Structure type to access the System Timer (SysTick). + */ +typedef struct +{ + __IO uint32_t CTRL; /*!< Offset: 0x000 (R/W) SysTick Control and Status Register */ + __IO uint32_t LOAD; /*!< Offset: 0x004 (R/W) SysTick Reload Value Register */ + __IO uint32_t VAL; /*!< Offset: 0x008 (R/W) SysTick Current Value Register */ + __I uint32_t CALIB; /*!< Offset: 0x00C (R/ ) SysTick Calibration Register */ +} SysTick_Type; + +/* SysTick Control / Status Register Definitions */ +#define SysTick_CTRL_COUNTFLAG_Pos 16 /*!< SysTick CTRL: COUNTFLAG Position */ +#define SysTick_CTRL_COUNTFLAG_Msk (1UL << SysTick_CTRL_COUNTFLAG_Pos) /*!< SysTick CTRL: COUNTFLAG Mask */ + +#define SysTick_CTRL_CLKSOURCE_Pos 2 /*!< SysTick CTRL: CLKSOURCE Position */ +#define SysTick_CTRL_CLKSOURCE_Msk (1UL << SysTick_CTRL_CLKSOURCE_Pos) /*!< SysTick CTRL: CLKSOURCE Mask */ + +#define SysTick_CTRL_TICKINT_Pos 1 /*!< SysTick CTRL: TICKINT Position */ +#define SysTick_CTRL_TICKINT_Msk (1UL << SysTick_CTRL_TICKINT_Pos) /*!< SysTick CTRL: TICKINT Mask */ + +#define SysTick_CTRL_ENABLE_Pos 0 /*!< SysTick CTRL: ENABLE Position */ +#define SysTick_CTRL_ENABLE_Msk (1UL << SysTick_CTRL_ENABLE_Pos) /*!< SysTick CTRL: ENABLE Mask */ + +/* SysTick Reload Register Definitions */ +#define SysTick_LOAD_RELOAD_Pos 0 /*!< SysTick LOAD: RELOAD Position */ +#define SysTick_LOAD_RELOAD_Msk (0xFFFFFFUL << SysTick_LOAD_RELOAD_Pos) /*!< SysTick LOAD: RELOAD Mask */ + +/* SysTick Current Register Definitions */ +#define SysTick_VAL_CURRENT_Pos 0 /*!< SysTick VAL: CURRENT Position */ +#define SysTick_VAL_CURRENT_Msk (0xFFFFFFUL << SysTick_VAL_CURRENT_Pos) /*!< SysTick VAL: CURRENT Mask */ + +/* SysTick Calibration Register Definitions */ +#define SysTick_CALIB_NOREF_Pos 31 /*!< SysTick CALIB: NOREF Position */ +#define SysTick_CALIB_NOREF_Msk (1UL << SysTick_CALIB_NOREF_Pos) /*!< SysTick CALIB: NOREF Mask */ + +#define SysTick_CALIB_SKEW_Pos 30 /*!< SysTick CALIB: SKEW Position */ +#define SysTick_CALIB_SKEW_Msk (1UL << SysTick_CALIB_SKEW_Pos) /*!< SysTick CALIB: SKEW Mask */ + +#define SysTick_CALIB_TENMS_Pos 0 /*!< SysTick CALIB: TENMS Position */ +#define SysTick_CALIB_TENMS_Msk (0xFFFFFFUL << SysTick_VAL_CURRENT_Pos) /*!< SysTick CALIB: TENMS Mask */ + +/*@} end of group CMSIS_SysTick */ + + +/** \ingroup CMSIS_core_register + \defgroup CMSIS_ITM Instrumentation Trace Macrocell (ITM) + \brief Type definitions for the Instrumentation Trace Macrocell (ITM) + @{ + */ + +/** \brief Structure type to access the Instrumentation Trace Macrocell Register (ITM). + */ +typedef struct +{ + __O union + { + __O uint8_t u8; /*!< Offset: 0x000 ( /W) ITM Stimulus Port 8-bit */ + __O uint16_t u16; /*!< Offset: 0x000 ( /W) ITM Stimulus Port 16-bit */ + __O uint32_t u32; /*!< Offset: 0x000 ( /W) ITM Stimulus Port 32-bit */ + } PORT [32]; /*!< Offset: 0x000 ( /W) ITM Stimulus Port Registers */ + uint32_t RESERVED0[864]; + __IO uint32_t TER; /*!< Offset: 0xE00 (R/W) ITM Trace Enable Register */ + uint32_t RESERVED1[15]; + __IO uint32_t TPR; /*!< Offset: 0xE40 (R/W) ITM Trace Privilege Register */ + uint32_t RESERVED2[15]; + __IO uint32_t TCR; /*!< Offset: 0xE80 (R/W) ITM Trace Control Register */ + uint32_t RESERVED3[29]; + __O uint32_t IWR; /*!< Offset: 0xEF8 ( /W) ITM Integration Write Register */ + __I uint32_t IRR; /*!< Offset: 0xEFC (R/ ) ITM Integration Read Register */ + __IO uint32_t IMCR; /*!< Offset: 0xF00 (R/W) ITM Integration Mode Control Register */ + uint32_t RESERVED4[43]; + __O uint32_t LAR; /*!< Offset: 0xFB0 ( /W) ITM Lock Access Register */ + __I uint32_t LSR; /*!< Offset: 0xFB4 (R/ ) ITM Lock Status Register */ + uint32_t RESERVED5[6]; + __I uint32_t PID4; /*!< Offset: 0xFD0 (R/ ) ITM Peripheral Identification Register #4 */ + __I uint32_t PID5; /*!< Offset: 0xFD4 (R/ ) ITM Peripheral Identification Register #5 */ + __I uint32_t PID6; /*!< Offset: 0xFD8 (R/ ) ITM Peripheral Identification Register #6 */ + __I uint32_t PID7; /*!< Offset: 0xFDC (R/ ) ITM Peripheral Identification Register #7 */ + __I uint32_t PID0; /*!< Offset: 0xFE0 (R/ ) ITM Peripheral Identification Register #0 */ + __I uint32_t PID1; /*!< Offset: 0xFE4 (R/ ) ITM Peripheral Identification Register #1 */ + __I uint32_t PID2; /*!< Offset: 0xFE8 (R/ ) ITM Peripheral Identification Register #2 */ + __I uint32_t PID3; /*!< Offset: 0xFEC (R/ ) ITM Peripheral Identification Register #3 */ + __I uint32_t CID0; /*!< Offset: 0xFF0 (R/ ) ITM Component Identification Register #0 */ + __I uint32_t CID1; /*!< Offset: 0xFF4 (R/ ) ITM Component Identification Register #1 */ + __I uint32_t CID2; /*!< Offset: 0xFF8 (R/ ) ITM Component Identification Register #2 */ + __I uint32_t CID3; /*!< Offset: 0xFFC (R/ ) ITM Component Identification Register #3 */ +} ITM_Type; + +/* ITM Trace Privilege Register Definitions */ +#define ITM_TPR_PRIVMASK_Pos 0 /*!< ITM TPR: PRIVMASK Position */ +#define ITM_TPR_PRIVMASK_Msk (0xFUL << ITM_TPR_PRIVMASK_Pos) /*!< ITM TPR: PRIVMASK Mask */ + +/* ITM Trace Control Register Definitions */ +#define ITM_TCR_BUSY_Pos 23 /*!< ITM TCR: BUSY Position */ +#define ITM_TCR_BUSY_Msk (1UL << ITM_TCR_BUSY_Pos) /*!< ITM TCR: BUSY Mask */ + +#define ITM_TCR_TraceBusID_Pos 16 /*!< ITM TCR: ATBID Position */ +#define ITM_TCR_TraceBusID_Msk (0x7FUL << ITM_TCR_TraceBusID_Pos) /*!< ITM TCR: ATBID Mask */ + +#define ITM_TCR_GTSFREQ_Pos 10 /*!< ITM TCR: Global timestamp frequency Position */ +#define ITM_TCR_GTSFREQ_Msk (3UL << ITM_TCR_GTSFREQ_Pos) /*!< ITM TCR: Global timestamp frequency Mask */ + +#define ITM_TCR_TSPrescale_Pos 8 /*!< ITM TCR: TSPrescale Position */ +#define ITM_TCR_TSPrescale_Msk (3UL << ITM_TCR_TSPrescale_Pos) /*!< ITM TCR: TSPrescale Mask */ + +#define ITM_TCR_SWOENA_Pos 4 /*!< ITM TCR: SWOENA Position */ +#define ITM_TCR_SWOENA_Msk (1UL << ITM_TCR_SWOENA_Pos) /*!< ITM TCR: SWOENA Mask */ + +#define ITM_TCR_DWTENA_Pos 3 /*!< ITM TCR: DWTENA Position */ +#define ITM_TCR_DWTENA_Msk (1UL << ITM_TCR_DWTENA_Pos) /*!< ITM TCR: DWTENA Mask */ + +#define ITM_TCR_SYNCENA_Pos 2 /*!< ITM TCR: SYNCENA Position */ +#define ITM_TCR_SYNCENA_Msk (1UL << ITM_TCR_SYNCENA_Pos) /*!< ITM TCR: SYNCENA Mask */ + +#define ITM_TCR_TSENA_Pos 1 /*!< ITM TCR: TSENA Position */ +#define ITM_TCR_TSENA_Msk (1UL << ITM_TCR_TSENA_Pos) /*!< ITM TCR: TSENA Mask */ + +#define ITM_TCR_ITMENA_Pos 0 /*!< ITM TCR: ITM Enable bit Position */ +#define ITM_TCR_ITMENA_Msk (1UL << ITM_TCR_ITMENA_Pos) /*!< ITM TCR: ITM Enable bit Mask */ + +/* ITM Integration Write Register Definitions */ +#define ITM_IWR_ATVALIDM_Pos 0 /*!< ITM IWR: ATVALIDM Position */ +#define ITM_IWR_ATVALIDM_Msk (1UL << ITM_IWR_ATVALIDM_Pos) /*!< ITM IWR: ATVALIDM Mask */ + +/* ITM Integration Read Register Definitions */ +#define ITM_IRR_ATREADYM_Pos 0 /*!< ITM IRR: ATREADYM Position */ +#define ITM_IRR_ATREADYM_Msk (1UL << ITM_IRR_ATREADYM_Pos) /*!< ITM IRR: ATREADYM Mask */ + +/* ITM Integration Mode Control Register Definitions */ +#define ITM_IMCR_INTEGRATION_Pos 0 /*!< ITM IMCR: INTEGRATION Position */ +#define ITM_IMCR_INTEGRATION_Msk (1UL << ITM_IMCR_INTEGRATION_Pos) /*!< ITM IMCR: INTEGRATION Mask */ + +/* ITM Lock Status Register Definitions */ +#define ITM_LSR_ByteAcc_Pos 2 /*!< ITM LSR: ByteAcc Position */ +#define ITM_LSR_ByteAcc_Msk (1UL << ITM_LSR_ByteAcc_Pos) /*!< ITM LSR: ByteAcc Mask */ + +#define ITM_LSR_Access_Pos 1 /*!< ITM LSR: Access Position */ +#define ITM_LSR_Access_Msk (1UL << ITM_LSR_Access_Pos) /*!< ITM LSR: Access Mask */ + +#define ITM_LSR_Present_Pos 0 /*!< ITM LSR: Present Position */ +#define ITM_LSR_Present_Msk (1UL << ITM_LSR_Present_Pos) /*!< ITM LSR: Present Mask */ + +/*@}*/ /* end of group CMSIS_ITM */ + + +/** \ingroup CMSIS_core_register + \defgroup CMSIS_DWT Data Watchpoint and Trace (DWT) + \brief Type definitions for the Data Watchpoint and Trace (DWT) + @{ + */ + +/** \brief Structure type to access the Data Watchpoint and Trace Register (DWT). + */ +typedef struct +{ + __IO uint32_t CTRL; /*!< Offset: 0x000 (R/W) Control Register */ + __IO uint32_t CYCCNT; /*!< Offset: 0x004 (R/W) Cycle Count Register */ + __IO uint32_t CPICNT; /*!< Offset: 0x008 (R/W) CPI Count Register */ + __IO uint32_t EXCCNT; /*!< Offset: 0x00C (R/W) Exception Overhead Count Register */ + __IO uint32_t SLEEPCNT; /*!< Offset: 0x010 (R/W) Sleep Count Register */ + __IO uint32_t LSUCNT; /*!< Offset: 0x014 (R/W) LSU Count Register */ + __IO uint32_t FOLDCNT; /*!< Offset: 0x018 (R/W) Folded-instruction Count Register */ + __I uint32_t PCSR; /*!< Offset: 0x01C (R/ ) Program Counter Sample Register */ + __IO uint32_t COMP0; /*!< Offset: 0x020 (R/W) Comparator Register 0 */ + __IO uint32_t MASK0; /*!< Offset: 0x024 (R/W) Mask Register 0 */ + __IO uint32_t FUNCTION0; /*!< Offset: 0x028 (R/W) Function Register 0 */ + uint32_t RESERVED0[1]; + __IO uint32_t COMP1; /*!< Offset: 0x030 (R/W) Comparator Register 1 */ + __IO uint32_t MASK1; /*!< Offset: 0x034 (R/W) Mask Register 1 */ + __IO uint32_t FUNCTION1; /*!< Offset: 0x038 (R/W) Function Register 1 */ + uint32_t RESERVED1[1]; + __IO uint32_t COMP2; /*!< Offset: 0x040 (R/W) Comparator Register 2 */ + __IO uint32_t MASK2; /*!< Offset: 0x044 (R/W) Mask Register 2 */ + __IO uint32_t FUNCTION2; /*!< Offset: 0x048 (R/W) Function Register 2 */ + uint32_t RESERVED2[1]; + __IO uint32_t COMP3; /*!< Offset: 0x050 (R/W) Comparator Register 3 */ + __IO uint32_t MASK3; /*!< Offset: 0x054 (R/W) Mask Register 3 */ + __IO uint32_t FUNCTION3; /*!< Offset: 0x058 (R/W) Function Register 3 */ +} DWT_Type; + +/* DWT Control Register Definitions */ +#define DWT_CTRL_NUMCOMP_Pos 28 /*!< DWT CTRL: NUMCOMP Position */ +#define DWT_CTRL_NUMCOMP_Msk (0xFUL << DWT_CTRL_NUMCOMP_Pos) /*!< DWT CTRL: NUMCOMP Mask */ + +#define DWT_CTRL_NOTRCPKT_Pos 27 /*!< DWT CTRL: NOTRCPKT Position */ +#define DWT_CTRL_NOTRCPKT_Msk (0x1UL << DWT_CTRL_NOTRCPKT_Pos) /*!< DWT CTRL: NOTRCPKT Mask */ + +#define DWT_CTRL_NOEXTTRIG_Pos 26 /*!< DWT CTRL: NOEXTTRIG Position */ +#define DWT_CTRL_NOEXTTRIG_Msk (0x1UL << DWT_CTRL_NOEXTTRIG_Pos) /*!< DWT CTRL: NOEXTTRIG Mask */ + +#define DWT_CTRL_NOCYCCNT_Pos 25 /*!< DWT CTRL: NOCYCCNT Position */ +#define DWT_CTRL_NOCYCCNT_Msk (0x1UL << DWT_CTRL_NOCYCCNT_Pos) /*!< DWT CTRL: NOCYCCNT Mask */ + +#define DWT_CTRL_NOPRFCNT_Pos 24 /*!< DWT CTRL: NOPRFCNT Position */ +#define DWT_CTRL_NOPRFCNT_Msk (0x1UL << DWT_CTRL_NOPRFCNT_Pos) /*!< DWT CTRL: NOPRFCNT Mask */ + +#define DWT_CTRL_CYCEVTENA_Pos 22 /*!< DWT CTRL: CYCEVTENA Position */ +#define DWT_CTRL_CYCEVTENA_Msk (0x1UL << DWT_CTRL_CYCEVTENA_Pos) /*!< DWT CTRL: CYCEVTENA Mask */ + +#define DWT_CTRL_FOLDEVTENA_Pos 21 /*!< DWT CTRL: FOLDEVTENA Position */ +#define DWT_CTRL_FOLDEVTENA_Msk (0x1UL << DWT_CTRL_FOLDEVTENA_Pos) /*!< DWT CTRL: FOLDEVTENA Mask */ + +#define DWT_CTRL_LSUEVTENA_Pos 20 /*!< DWT CTRL: LSUEVTENA Position */ +#define DWT_CTRL_LSUEVTENA_Msk (0x1UL << DWT_CTRL_LSUEVTENA_Pos) /*!< DWT CTRL: LSUEVTENA Mask */ + +#define DWT_CTRL_SLEEPEVTENA_Pos 19 /*!< DWT CTRL: SLEEPEVTENA Position */ +#define DWT_CTRL_SLEEPEVTENA_Msk (0x1UL << DWT_CTRL_SLEEPEVTENA_Pos) /*!< DWT CTRL: SLEEPEVTENA Mask */ + +#define DWT_CTRL_EXCEVTENA_Pos 18 /*!< DWT CTRL: EXCEVTENA Position */ +#define DWT_CTRL_EXCEVTENA_Msk (0x1UL << DWT_CTRL_EXCEVTENA_Pos) /*!< DWT CTRL: EXCEVTENA Mask */ + +#define DWT_CTRL_CPIEVTENA_Pos 17 /*!< DWT CTRL: CPIEVTENA Position */ +#define DWT_CTRL_CPIEVTENA_Msk (0x1UL << DWT_CTRL_CPIEVTENA_Pos) /*!< DWT CTRL: CPIEVTENA Mask */ + +#define DWT_CTRL_EXCTRCENA_Pos 16 /*!< DWT CTRL: EXCTRCENA Position */ +#define DWT_CTRL_EXCTRCENA_Msk (0x1UL << DWT_CTRL_EXCTRCENA_Pos) /*!< DWT CTRL: EXCTRCENA Mask */ + +#define DWT_CTRL_PCSAMPLENA_Pos 12 /*!< DWT CTRL: PCSAMPLENA Position */ +#define DWT_CTRL_PCSAMPLENA_Msk (0x1UL << DWT_CTRL_PCSAMPLENA_Pos) /*!< DWT CTRL: PCSAMPLENA Mask */ + +#define DWT_CTRL_SYNCTAP_Pos 10 /*!< DWT CTRL: SYNCTAP Position */ +#define DWT_CTRL_SYNCTAP_Msk (0x3UL << DWT_CTRL_SYNCTAP_Pos) /*!< DWT CTRL: SYNCTAP Mask */ + +#define DWT_CTRL_CYCTAP_Pos 9 /*!< DWT CTRL: CYCTAP Position */ +#define DWT_CTRL_CYCTAP_Msk (0x1UL << DWT_CTRL_CYCTAP_Pos) /*!< DWT CTRL: CYCTAP Mask */ + +#define DWT_CTRL_POSTINIT_Pos 5 /*!< DWT CTRL: POSTINIT Position */ +#define DWT_CTRL_POSTINIT_Msk (0xFUL << DWT_CTRL_POSTINIT_Pos) /*!< DWT CTRL: POSTINIT Mask */ + +#define DWT_CTRL_POSTPRESET_Pos 1 /*!< DWT CTRL: POSTPRESET Position */ +#define DWT_CTRL_POSTPRESET_Msk (0xFUL << DWT_CTRL_POSTPRESET_Pos) /*!< DWT CTRL: POSTPRESET Mask */ + +#define DWT_CTRL_CYCCNTENA_Pos 0 /*!< DWT CTRL: CYCCNTENA Position */ +#define DWT_CTRL_CYCCNTENA_Msk (0x1UL << DWT_CTRL_CYCCNTENA_Pos) /*!< DWT CTRL: CYCCNTENA Mask */ + +/* DWT CPI Count Register Definitions */ +#define DWT_CPICNT_CPICNT_Pos 0 /*!< DWT CPICNT: CPICNT Position */ +#define DWT_CPICNT_CPICNT_Msk (0xFFUL << DWT_CPICNT_CPICNT_Pos) /*!< DWT CPICNT: CPICNT Mask */ + +/* DWT Exception Overhead Count Register Definitions */ +#define DWT_EXCCNT_EXCCNT_Pos 0 /*!< DWT EXCCNT: EXCCNT Position */ +#define DWT_EXCCNT_EXCCNT_Msk (0xFFUL << DWT_EXCCNT_EXCCNT_Pos) /*!< DWT EXCCNT: EXCCNT Mask */ + +/* DWT Sleep Count Register Definitions */ +#define DWT_SLEEPCNT_SLEEPCNT_Pos 0 /*!< DWT SLEEPCNT: SLEEPCNT Position */ +#define DWT_SLEEPCNT_SLEEPCNT_Msk (0xFFUL << DWT_SLEEPCNT_SLEEPCNT_Pos) /*!< DWT SLEEPCNT: SLEEPCNT Mask */ + +/* DWT LSU Count Register Definitions */ +#define DWT_LSUCNT_LSUCNT_Pos 0 /*!< DWT LSUCNT: LSUCNT Position */ +#define DWT_LSUCNT_LSUCNT_Msk (0xFFUL << DWT_LSUCNT_LSUCNT_Pos) /*!< DWT LSUCNT: LSUCNT Mask */ + +/* DWT Folded-instruction Count Register Definitions */ +#define DWT_FOLDCNT_FOLDCNT_Pos 0 /*!< DWT FOLDCNT: FOLDCNT Position */ +#define DWT_FOLDCNT_FOLDCNT_Msk (0xFFUL << DWT_FOLDCNT_FOLDCNT_Pos) /*!< DWT FOLDCNT: FOLDCNT Mask */ + +/* DWT Comparator Mask Register Definitions */ +#define DWT_MASK_MASK_Pos 0 /*!< DWT MASK: MASK Position */ +#define DWT_MASK_MASK_Msk (0x1FUL << DWT_MASK_MASK_Pos) /*!< DWT MASK: MASK Mask */ + +/* DWT Comparator Function Register Definitions */ +#define DWT_FUNCTION_MATCHED_Pos 24 /*!< DWT FUNCTION: MATCHED Position */ +#define DWT_FUNCTION_MATCHED_Msk (0x1UL << DWT_FUNCTION_MATCHED_Pos) /*!< DWT FUNCTION: MATCHED Mask */ + +#define DWT_FUNCTION_DATAVADDR1_Pos 16 /*!< DWT FUNCTION: DATAVADDR1 Position */ +#define DWT_FUNCTION_DATAVADDR1_Msk (0xFUL << DWT_FUNCTION_DATAVADDR1_Pos) /*!< DWT FUNCTION: DATAVADDR1 Mask */ + +#define DWT_FUNCTION_DATAVADDR0_Pos 12 /*!< DWT FUNCTION: DATAVADDR0 Position */ +#define DWT_FUNCTION_DATAVADDR0_Msk (0xFUL << DWT_FUNCTION_DATAVADDR0_Pos) /*!< DWT FUNCTION: DATAVADDR0 Mask */ + +#define DWT_FUNCTION_DATAVSIZE_Pos 10 /*!< DWT FUNCTION: DATAVSIZE Position */ +#define DWT_FUNCTION_DATAVSIZE_Msk (0x3UL << DWT_FUNCTION_DATAVSIZE_Pos) /*!< DWT FUNCTION: DATAVSIZE Mask */ + +#define DWT_FUNCTION_LNK1ENA_Pos 9 /*!< DWT FUNCTION: LNK1ENA Position */ +#define DWT_FUNCTION_LNK1ENA_Msk (0x1UL << DWT_FUNCTION_LNK1ENA_Pos) /*!< DWT FUNCTION: LNK1ENA Mask */ + +#define DWT_FUNCTION_DATAVMATCH_Pos 8 /*!< DWT FUNCTION: DATAVMATCH Position */ +#define DWT_FUNCTION_DATAVMATCH_Msk (0x1UL << DWT_FUNCTION_DATAVMATCH_Pos) /*!< DWT FUNCTION: DATAVMATCH Mask */ + +#define DWT_FUNCTION_CYCMATCH_Pos 7 /*!< DWT FUNCTION: CYCMATCH Position */ +#define DWT_FUNCTION_CYCMATCH_Msk (0x1UL << DWT_FUNCTION_CYCMATCH_Pos) /*!< DWT FUNCTION: CYCMATCH Mask */ + +#define DWT_FUNCTION_EMITRANGE_Pos 5 /*!< DWT FUNCTION: EMITRANGE Position */ +#define DWT_FUNCTION_EMITRANGE_Msk (0x1UL << DWT_FUNCTION_EMITRANGE_Pos) /*!< DWT FUNCTION: EMITRANGE Mask */ + +#define DWT_FUNCTION_FUNCTION_Pos 0 /*!< DWT FUNCTION: FUNCTION Position */ +#define DWT_FUNCTION_FUNCTION_Msk (0xFUL << DWT_FUNCTION_FUNCTION_Pos) /*!< DWT FUNCTION: FUNCTION Mask */ + +/*@}*/ /* end of group CMSIS_DWT */ + + +/** \ingroup CMSIS_core_register + \defgroup CMSIS_TPI Trace Port Interface (TPI) + \brief Type definitions for the Trace Port Interface (TPI) + @{ + */ + +/** \brief Structure type to access the Trace Port Interface Register (TPI). + */ +typedef struct +{ + __IO uint32_t SSPSR; /*!< Offset: 0x000 (R/ ) Supported Parallel Port Size Register */ + __IO uint32_t CSPSR; /*!< Offset: 0x004 (R/W) Current Parallel Port Size Register */ + uint32_t RESERVED0[2]; + __IO uint32_t ACPR; /*!< Offset: 0x010 (R/W) Asynchronous Clock Prescaler Register */ + uint32_t RESERVED1[55]; + __IO uint32_t SPPR; /*!< Offset: 0x0F0 (R/W) Selected Pin Protocol Register */ + uint32_t RESERVED2[131]; + __I uint32_t FFSR; /*!< Offset: 0x300 (R/ ) Formatter and Flush Status Register */ + __IO uint32_t FFCR; /*!< Offset: 0x304 (R/W) Formatter and Flush Control Register */ + __I uint32_t FSCR; /*!< Offset: 0x308 (R/ ) Formatter Synchronization Counter Register */ + uint32_t RESERVED3[759]; + __I uint32_t TRIGGER; /*!< Offset: 0xEE8 (R/ ) TRIGGER */ + __I uint32_t FIFO0; /*!< Offset: 0xEEC (R/ ) Integration ETM Data */ + __I uint32_t ITATBCTR2; /*!< Offset: 0xEF0 (R/ ) ITATBCTR2 */ + uint32_t RESERVED4[1]; + __I uint32_t ITATBCTR0; /*!< Offset: 0xEF8 (R/ ) ITATBCTR0 */ + __I uint32_t FIFO1; /*!< Offset: 0xEFC (R/ ) Integration ITM Data */ + __IO uint32_t ITCTRL; /*!< Offset: 0xF00 (R/W) Integration Mode Control */ + uint32_t RESERVED5[39]; + __IO uint32_t CLAIMSET; /*!< Offset: 0xFA0 (R/W) Claim tag set */ + __IO uint32_t CLAIMCLR; /*!< Offset: 0xFA4 (R/W) Claim tag clear */ + uint32_t RESERVED7[8]; + __I uint32_t DEVID; /*!< Offset: 0xFC8 (R/ ) TPIU_DEVID */ + __I uint32_t DEVTYPE; /*!< Offset: 0xFCC (R/ ) TPIU_DEVTYPE */ +} TPI_Type; + +/* TPI Asynchronous Clock Prescaler Register Definitions */ +#define TPI_ACPR_PRESCALER_Pos 0 /*!< TPI ACPR: PRESCALER Position */ +#define TPI_ACPR_PRESCALER_Msk (0x1FFFUL << TPI_ACPR_PRESCALER_Pos) /*!< TPI ACPR: PRESCALER Mask */ + +/* TPI Selected Pin Protocol Register Definitions */ +#define TPI_SPPR_TXMODE_Pos 0 /*!< TPI SPPR: TXMODE Position */ +#define TPI_SPPR_TXMODE_Msk (0x3UL << TPI_SPPR_TXMODE_Pos) /*!< TPI SPPR: TXMODE Mask */ + +/* TPI Formatter and Flush Status Register Definitions */ +#define TPI_FFSR_FtNonStop_Pos 3 /*!< TPI FFSR: FtNonStop Position */ +#define TPI_FFSR_FtNonStop_Msk (0x1UL << TPI_FFSR_FtNonStop_Pos) /*!< TPI FFSR: FtNonStop Mask */ + +#define TPI_FFSR_TCPresent_Pos 2 /*!< TPI FFSR: TCPresent Position */ +#define TPI_FFSR_TCPresent_Msk (0x1UL << TPI_FFSR_TCPresent_Pos) /*!< TPI FFSR: TCPresent Mask */ + +#define TPI_FFSR_FtStopped_Pos 1 /*!< TPI FFSR: FtStopped Position */ +#define TPI_FFSR_FtStopped_Msk (0x1UL << TPI_FFSR_FtStopped_Pos) /*!< TPI FFSR: FtStopped Mask */ + +#define TPI_FFSR_FlInProg_Pos 0 /*!< TPI FFSR: FlInProg Position */ +#define TPI_FFSR_FlInProg_Msk (0x1UL << TPI_FFSR_FlInProg_Pos) /*!< TPI FFSR: FlInProg Mask */ + +/* TPI Formatter and Flush Control Register Definitions */ +#define TPI_FFCR_TrigIn_Pos 8 /*!< TPI FFCR: TrigIn Position */ +#define TPI_FFCR_TrigIn_Msk (0x1UL << TPI_FFCR_TrigIn_Pos) /*!< TPI FFCR: TrigIn Mask */ + +#define TPI_FFCR_EnFCont_Pos 1 /*!< TPI FFCR: EnFCont Position */ +#define TPI_FFCR_EnFCont_Msk (0x1UL << TPI_FFCR_EnFCont_Pos) /*!< TPI FFCR: EnFCont Mask */ + +/* TPI TRIGGER Register Definitions */ +#define TPI_TRIGGER_TRIGGER_Pos 0 /*!< TPI TRIGGER: TRIGGER Position */ +#define TPI_TRIGGER_TRIGGER_Msk (0x1UL << TPI_TRIGGER_TRIGGER_Pos) /*!< TPI TRIGGER: TRIGGER Mask */ + +/* TPI Integration ETM Data Register Definitions (FIFO0) */ +#define TPI_FIFO0_ITM_ATVALID_Pos 29 /*!< TPI FIFO0: ITM_ATVALID Position */ +#define TPI_FIFO0_ITM_ATVALID_Msk (0x3UL << TPI_FIFO0_ITM_ATVALID_Pos) /*!< TPI FIFO0: ITM_ATVALID Mask */ + +#define TPI_FIFO0_ITM_bytecount_Pos 27 /*!< TPI FIFO0: ITM_bytecount Position */ +#define TPI_FIFO0_ITM_bytecount_Msk (0x3UL << TPI_FIFO0_ITM_bytecount_Pos) /*!< TPI FIFO0: ITM_bytecount Mask */ + +#define TPI_FIFO0_ETM_ATVALID_Pos 26 /*!< TPI FIFO0: ETM_ATVALID Position */ +#define TPI_FIFO0_ETM_ATVALID_Msk (0x3UL << TPI_FIFO0_ETM_ATVALID_Pos) /*!< TPI FIFO0: ETM_ATVALID Mask */ + +#define TPI_FIFO0_ETM_bytecount_Pos 24 /*!< TPI FIFO0: ETM_bytecount Position */ +#define TPI_FIFO0_ETM_bytecount_Msk (0x3UL << TPI_FIFO0_ETM_bytecount_Pos) /*!< TPI FIFO0: ETM_bytecount Mask */ + +#define TPI_FIFO0_ETM2_Pos 16 /*!< TPI FIFO0: ETM2 Position */ +#define TPI_FIFO0_ETM2_Msk (0xFFUL << TPI_FIFO0_ETM2_Pos) /*!< TPI FIFO0: ETM2 Mask */ + +#define TPI_FIFO0_ETM1_Pos 8 /*!< TPI FIFO0: ETM1 Position */ +#define TPI_FIFO0_ETM1_Msk (0xFFUL << TPI_FIFO0_ETM1_Pos) /*!< TPI FIFO0: ETM1 Mask */ + +#define TPI_FIFO0_ETM0_Pos 0 /*!< TPI FIFO0: ETM0 Position */ +#define TPI_FIFO0_ETM0_Msk (0xFFUL << TPI_FIFO0_ETM0_Pos) /*!< TPI FIFO0: ETM0 Mask */ + +/* TPI ITATBCTR2 Register Definitions */ +#define TPI_ITATBCTR2_ATREADY_Pos 0 /*!< TPI ITATBCTR2: ATREADY Position */ +#define TPI_ITATBCTR2_ATREADY_Msk (0x1UL << TPI_ITATBCTR2_ATREADY_Pos) /*!< TPI ITATBCTR2: ATREADY Mask */ + +/* TPI Integration ITM Data Register Definitions (FIFO1) */ +#define TPI_FIFO1_ITM_ATVALID_Pos 29 /*!< TPI FIFO1: ITM_ATVALID Position */ +#define TPI_FIFO1_ITM_ATVALID_Msk (0x3UL << TPI_FIFO1_ITM_ATVALID_Pos) /*!< TPI FIFO1: ITM_ATVALID Mask */ + +#define TPI_FIFO1_ITM_bytecount_Pos 27 /*!< TPI FIFO1: ITM_bytecount Position */ +#define TPI_FIFO1_ITM_bytecount_Msk (0x3UL << TPI_FIFO1_ITM_bytecount_Pos) /*!< TPI FIFO1: ITM_bytecount Mask */ + +#define TPI_FIFO1_ETM_ATVALID_Pos 26 /*!< TPI FIFO1: ETM_ATVALID Position */ +#define TPI_FIFO1_ETM_ATVALID_Msk (0x3UL << TPI_FIFO1_ETM_ATVALID_Pos) /*!< TPI FIFO1: ETM_ATVALID Mask */ + +#define TPI_FIFO1_ETM_bytecount_Pos 24 /*!< TPI FIFO1: ETM_bytecount Position */ +#define TPI_FIFO1_ETM_bytecount_Msk (0x3UL << TPI_FIFO1_ETM_bytecount_Pos) /*!< TPI FIFO1: ETM_bytecount Mask */ + +#define TPI_FIFO1_ITM2_Pos 16 /*!< TPI FIFO1: ITM2 Position */ +#define TPI_FIFO1_ITM2_Msk (0xFFUL << TPI_FIFO1_ITM2_Pos) /*!< TPI FIFO1: ITM2 Mask */ + +#define TPI_FIFO1_ITM1_Pos 8 /*!< TPI FIFO1: ITM1 Position */ +#define TPI_FIFO1_ITM1_Msk (0xFFUL << TPI_FIFO1_ITM1_Pos) /*!< TPI FIFO1: ITM1 Mask */ + +#define TPI_FIFO1_ITM0_Pos 0 /*!< TPI FIFO1: ITM0 Position */ +#define TPI_FIFO1_ITM0_Msk (0xFFUL << TPI_FIFO1_ITM0_Pos) /*!< TPI FIFO1: ITM0 Mask */ + +/* TPI ITATBCTR0 Register Definitions */ +#define TPI_ITATBCTR0_ATREADY_Pos 0 /*!< TPI ITATBCTR0: ATREADY Position */ +#define TPI_ITATBCTR0_ATREADY_Msk (0x1UL << TPI_ITATBCTR0_ATREADY_Pos) /*!< TPI ITATBCTR0: ATREADY Mask */ + +/* TPI Integration Mode Control Register Definitions */ +#define TPI_ITCTRL_Mode_Pos 0 /*!< TPI ITCTRL: Mode Position */ +#define TPI_ITCTRL_Mode_Msk (0x1UL << TPI_ITCTRL_Mode_Pos) /*!< TPI ITCTRL: Mode Mask */ + +/* TPI DEVID Register Definitions */ +#define TPI_DEVID_NRZVALID_Pos 11 /*!< TPI DEVID: NRZVALID Position */ +#define TPI_DEVID_NRZVALID_Msk (0x1UL << TPI_DEVID_NRZVALID_Pos) /*!< TPI DEVID: NRZVALID Mask */ + +#define TPI_DEVID_MANCVALID_Pos 10 /*!< TPI DEVID: MANCVALID Position */ +#define TPI_DEVID_MANCVALID_Msk (0x1UL << TPI_DEVID_MANCVALID_Pos) /*!< TPI DEVID: MANCVALID Mask */ + +#define TPI_DEVID_PTINVALID_Pos 9 /*!< TPI DEVID: PTINVALID Position */ +#define TPI_DEVID_PTINVALID_Msk (0x1UL << TPI_DEVID_PTINVALID_Pos) /*!< TPI DEVID: PTINVALID Mask */ + +#define TPI_DEVID_MinBufSz_Pos 6 /*!< TPI DEVID: MinBufSz Position */ +#define TPI_DEVID_MinBufSz_Msk (0x7UL << TPI_DEVID_MinBufSz_Pos) /*!< TPI DEVID: MinBufSz Mask */ + +#define TPI_DEVID_AsynClkIn_Pos 5 /*!< TPI DEVID: AsynClkIn Position */ +#define TPI_DEVID_AsynClkIn_Msk (0x1UL << TPI_DEVID_AsynClkIn_Pos) /*!< TPI DEVID: AsynClkIn Mask */ + +#define TPI_DEVID_NrTraceInput_Pos 0 /*!< TPI DEVID: NrTraceInput Position */ +#define TPI_DEVID_NrTraceInput_Msk (0x1FUL << TPI_DEVID_NrTraceInput_Pos) /*!< TPI DEVID: NrTraceInput Mask */ + +/* TPI DEVTYPE Register Definitions */ +#define TPI_DEVTYPE_SubType_Pos 0 /*!< TPI DEVTYPE: SubType Position */ +#define TPI_DEVTYPE_SubType_Msk (0xFUL << TPI_DEVTYPE_SubType_Pos) /*!< TPI DEVTYPE: SubType Mask */ + +#define TPI_DEVTYPE_MajorType_Pos 4 /*!< TPI DEVTYPE: MajorType Position */ +#define TPI_DEVTYPE_MajorType_Msk (0xFUL << TPI_DEVTYPE_MajorType_Pos) /*!< TPI DEVTYPE: MajorType Mask */ + +/*@}*/ /* end of group CMSIS_TPI */ + + +#if (__MPU_PRESENT == 1) +/** \ingroup CMSIS_core_register + \defgroup CMSIS_MPU Memory Protection Unit (MPU) + \brief Type definitions for the Memory Protection Unit (MPU) + @{ + */ + +/** \brief Structure type to access the Memory Protection Unit (MPU). + */ +typedef struct +{ + __I uint32_t TYPE; /*!< Offset: 0x000 (R/ ) MPU Type Register */ + __IO uint32_t CTRL; /*!< Offset: 0x004 (R/W) MPU Control Register */ + __IO uint32_t RNR; /*!< Offset: 0x008 (R/W) MPU Region RNRber Register */ + __IO uint32_t RBAR; /*!< Offset: 0x00C (R/W) MPU Region Base Address Register */ + __IO uint32_t RASR; /*!< Offset: 0x010 (R/W) MPU Region Attribute and Size Register */ + __IO uint32_t RBAR_A1; /*!< Offset: 0x014 (R/W) MPU Alias 1 Region Base Address Register */ + __IO uint32_t RASR_A1; /*!< Offset: 0x018 (R/W) MPU Alias 1 Region Attribute and Size Register */ + __IO uint32_t RBAR_A2; /*!< Offset: 0x01C (R/W) MPU Alias 2 Region Base Address Register */ + __IO uint32_t RASR_A2; /*!< Offset: 0x020 (R/W) MPU Alias 2 Region Attribute and Size Register */ + __IO uint32_t RBAR_A3; /*!< Offset: 0x024 (R/W) MPU Alias 3 Region Base Address Register */ + __IO uint32_t RASR_A3; /*!< Offset: 0x028 (R/W) MPU Alias 3 Region Attribute and Size Register */ +} MPU_Type; + +/* MPU Type Register */ +#define MPU_TYPE_IREGION_Pos 16 /*!< MPU TYPE: IREGION Position */ +#define MPU_TYPE_IREGION_Msk (0xFFUL << MPU_TYPE_IREGION_Pos) /*!< MPU TYPE: IREGION Mask */ + +#define MPU_TYPE_DREGION_Pos 8 /*!< MPU TYPE: DREGION Position */ +#define MPU_TYPE_DREGION_Msk (0xFFUL << MPU_TYPE_DREGION_Pos) /*!< MPU TYPE: DREGION Mask */ + +#define MPU_TYPE_SEPARATE_Pos 0 /*!< MPU TYPE: SEPARATE Position */ +#define MPU_TYPE_SEPARATE_Msk (1UL << MPU_TYPE_SEPARATE_Pos) /*!< MPU TYPE: SEPARATE Mask */ + +/* MPU Control Register */ +#define MPU_CTRL_PRIVDEFENA_Pos 2 /*!< MPU CTRL: PRIVDEFENA Position */ +#define MPU_CTRL_PRIVDEFENA_Msk (1UL << MPU_CTRL_PRIVDEFENA_Pos) /*!< MPU CTRL: PRIVDEFENA Mask */ + +#define MPU_CTRL_HFNMIENA_Pos 1 /*!< MPU CTRL: HFNMIENA Position */ +#define MPU_CTRL_HFNMIENA_Msk (1UL << MPU_CTRL_HFNMIENA_Pos) /*!< MPU CTRL: HFNMIENA Mask */ + +#define MPU_CTRL_ENABLE_Pos 0 /*!< MPU CTRL: ENABLE Position */ +#define MPU_CTRL_ENABLE_Msk (1UL << MPU_CTRL_ENABLE_Pos) /*!< MPU CTRL: ENABLE Mask */ + +/* MPU Region Number Register */ +#define MPU_RNR_REGION_Pos 0 /*!< MPU RNR: REGION Position */ +#define MPU_RNR_REGION_Msk (0xFFUL << MPU_RNR_REGION_Pos) /*!< MPU RNR: REGION Mask */ + +/* MPU Region Base Address Register */ +#define MPU_RBAR_ADDR_Pos 5 /*!< MPU RBAR: ADDR Position */ +#define MPU_RBAR_ADDR_Msk (0x7FFFFFFUL << MPU_RBAR_ADDR_Pos) /*!< MPU RBAR: ADDR Mask */ + +#define MPU_RBAR_VALID_Pos 4 /*!< MPU RBAR: VALID Position */ +#define MPU_RBAR_VALID_Msk (1UL << MPU_RBAR_VALID_Pos) /*!< MPU RBAR: VALID Mask */ + +#define MPU_RBAR_REGION_Pos 0 /*!< MPU RBAR: REGION Position */ +#define MPU_RBAR_REGION_Msk (0xFUL << MPU_RBAR_REGION_Pos) /*!< MPU RBAR: REGION Mask */ + +/* MPU Region Attribute and Size Register */ +#define MPU_RASR_ATTRS_Pos 16 /*!< MPU RASR: MPU Region Attribute field Position */ +#define MPU_RASR_ATTRS_Msk (0xFFFFUL << MPU_RASR_ATTRS_Pos) /*!< MPU RASR: MPU Region Attribute field Mask */ + +#define MPU_RASR_XN_Pos 28 /*!< MPU RASR: ATTRS.XN Position */ +#define MPU_RASR_XN_Msk (1UL << MPU_RASR_XN_Pos) /*!< MPU RASR: ATTRS.XN Mask */ + +#define MPU_RASR_AP_Pos 24 /*!< MPU RASR: ATTRS.AP Position */ +#define MPU_RASR_AP_Msk (0x7UL << MPU_RASR_AP_Pos) /*!< MPU RASR: ATTRS.AP Mask */ + +#define MPU_RASR_TEX_Pos 19 /*!< MPU RASR: ATTRS.TEX Position */ +#define MPU_RASR_TEX_Msk (0x7UL << MPU_RASR_TEX_Pos) /*!< MPU RASR: ATTRS.TEX Mask */ + +#define MPU_RASR_S_Pos 18 /*!< MPU RASR: ATTRS.S Position */ +#define MPU_RASR_S_Msk (1UL << MPU_RASR_S_Pos) /*!< MPU RASR: ATTRS.S Mask */ + +#define MPU_RASR_C_Pos 17 /*!< MPU RASR: ATTRS.C Position */ +#define MPU_RASR_C_Msk (1UL << MPU_RASR_C_Pos) /*!< MPU RASR: ATTRS.C Mask */ + +#define MPU_RASR_B_Pos 16 /*!< MPU RASR: ATTRS.B Position */ +#define MPU_RASR_B_Msk (1UL << MPU_RASR_B_Pos) /*!< MPU RASR: ATTRS.B Mask */ + +#define MPU_RASR_SRD_Pos 8 /*!< MPU RASR: Sub-Region Disable Position */ +#define MPU_RASR_SRD_Msk (0xFFUL << MPU_RASR_SRD_Pos) /*!< MPU RASR: Sub-Region Disable Mask */ + +#define MPU_RASR_SIZE_Pos 1 /*!< MPU RASR: Region Size Field Position */ +#define MPU_RASR_SIZE_Msk (0x1FUL << MPU_RASR_SIZE_Pos) /*!< MPU RASR: Region Size Field Mask */ + +#define MPU_RASR_ENABLE_Pos 0 /*!< MPU RASR: Region enable bit Position */ +#define MPU_RASR_ENABLE_Msk (1UL << MPU_RASR_ENABLE_Pos) /*!< MPU RASR: Region enable bit Disable Mask */ + +/*@} end of group CMSIS_MPU */ +#endif + + +#if (__FPU_PRESENT == 1) +/** \ingroup CMSIS_core_register + \defgroup CMSIS_FPU Floating Point Unit (FPU) + \brief Type definitions for the Floating Point Unit (FPU) + @{ + */ + +/** \brief Structure type to access the Floating Point Unit (FPU). + */ +typedef struct +{ + uint32_t RESERVED0[1]; + __IO uint32_t FPCCR; /*!< Offset: 0x004 (R/W) Floating-Point Context Control Register */ + __IO uint32_t FPCAR; /*!< Offset: 0x008 (R/W) Floating-Point Context Address Register */ + __IO uint32_t FPDSCR; /*!< Offset: 0x00C (R/W) Floating-Point Default Status Control Register */ + __I uint32_t MVFR0; /*!< Offset: 0x010 (R/ ) Media and FP Feature Register 0 */ + __I uint32_t MVFR1; /*!< Offset: 0x014 (R/ ) Media and FP Feature Register 1 */ +} FPU_Type; + +/* Floating-Point Context Control Register */ +#define FPU_FPCCR_ASPEN_Pos 31 /*!< FPCCR: ASPEN bit Position */ +#define FPU_FPCCR_ASPEN_Msk (1UL << FPU_FPCCR_ASPEN_Pos) /*!< FPCCR: ASPEN bit Mask */ + +#define FPU_FPCCR_LSPEN_Pos 30 /*!< FPCCR: LSPEN Position */ +#define FPU_FPCCR_LSPEN_Msk (1UL << FPU_FPCCR_LSPEN_Pos) /*!< FPCCR: LSPEN bit Mask */ + +#define FPU_FPCCR_MONRDY_Pos 8 /*!< FPCCR: MONRDY Position */ +#define FPU_FPCCR_MONRDY_Msk (1UL << FPU_FPCCR_MONRDY_Pos) /*!< FPCCR: MONRDY bit Mask */ + +#define FPU_FPCCR_BFRDY_Pos 6 /*!< FPCCR: BFRDY Position */ +#define FPU_FPCCR_BFRDY_Msk (1UL << FPU_FPCCR_BFRDY_Pos) /*!< FPCCR: BFRDY bit Mask */ + +#define FPU_FPCCR_MMRDY_Pos 5 /*!< FPCCR: MMRDY Position */ +#define FPU_FPCCR_MMRDY_Msk (1UL << FPU_FPCCR_MMRDY_Pos) /*!< FPCCR: MMRDY bit Mask */ + +#define FPU_FPCCR_HFRDY_Pos 4 /*!< FPCCR: HFRDY Position */ +#define FPU_FPCCR_HFRDY_Msk (1UL << FPU_FPCCR_HFRDY_Pos) /*!< FPCCR: HFRDY bit Mask */ + +#define FPU_FPCCR_THREAD_Pos 3 /*!< FPCCR: processor mode bit Position */ +#define FPU_FPCCR_THREAD_Msk (1UL << FPU_FPCCR_THREAD_Pos) /*!< FPCCR: processor mode active bit Mask */ + +#define FPU_FPCCR_USER_Pos 1 /*!< FPCCR: privilege level bit Position */ +#define FPU_FPCCR_USER_Msk (1UL << FPU_FPCCR_USER_Pos) /*!< FPCCR: privilege level bit Mask */ + +#define FPU_FPCCR_LSPACT_Pos 0 /*!< FPCCR: Lazy state preservation active bit Position */ +#define FPU_FPCCR_LSPACT_Msk (1UL << FPU_FPCCR_LSPACT_Pos) /*!< FPCCR: Lazy state preservation active bit Mask */ + +/* Floating-Point Context Address Register */ +#define FPU_FPCAR_ADDRESS_Pos 3 /*!< FPCAR: ADDRESS bit Position */ +#define FPU_FPCAR_ADDRESS_Msk (0x1FFFFFFFUL << FPU_FPCAR_ADDRESS_Pos) /*!< FPCAR: ADDRESS bit Mask */ + +/* Floating-Point Default Status Control Register */ +#define FPU_FPDSCR_AHP_Pos 26 /*!< FPDSCR: AHP bit Position */ +#define FPU_FPDSCR_AHP_Msk (1UL << FPU_FPDSCR_AHP_Pos) /*!< FPDSCR: AHP bit Mask */ + +#define FPU_FPDSCR_DN_Pos 25 /*!< FPDSCR: DN bit Position */ +#define FPU_FPDSCR_DN_Msk (1UL << FPU_FPDSCR_DN_Pos) /*!< FPDSCR: DN bit Mask */ + +#define FPU_FPDSCR_FZ_Pos 24 /*!< FPDSCR: FZ bit Position */ +#define FPU_FPDSCR_FZ_Msk (1UL << FPU_FPDSCR_FZ_Pos) /*!< FPDSCR: FZ bit Mask */ + +#define FPU_FPDSCR_RMode_Pos 22 /*!< FPDSCR: RMode bit Position */ +#define FPU_FPDSCR_RMode_Msk (3UL << FPU_FPDSCR_RMode_Pos) /*!< FPDSCR: RMode bit Mask */ + +/* Media and FP Feature Register 0 */ +#define FPU_MVFR0_FP_rounding_modes_Pos 28 /*!< MVFR0: FP rounding modes bits Position */ +#define FPU_MVFR0_FP_rounding_modes_Msk (0xFUL << FPU_MVFR0_FP_rounding_modes_Pos) /*!< MVFR0: FP rounding modes bits Mask */ + +#define FPU_MVFR0_Short_vectors_Pos 24 /*!< MVFR0: Short vectors bits Position */ +#define FPU_MVFR0_Short_vectors_Msk (0xFUL << FPU_MVFR0_Short_vectors_Pos) /*!< MVFR0: Short vectors bits Mask */ + +#define FPU_MVFR0_Square_root_Pos 20 /*!< MVFR0: Square root bits Position */ +#define FPU_MVFR0_Square_root_Msk (0xFUL << FPU_MVFR0_Square_root_Pos) /*!< MVFR0: Square root bits Mask */ + +#define FPU_MVFR0_Divide_Pos 16 /*!< MVFR0: Divide bits Position */ +#define FPU_MVFR0_Divide_Msk (0xFUL << FPU_MVFR0_Divide_Pos) /*!< MVFR0: Divide bits Mask */ + +#define FPU_MVFR0_FP_excep_trapping_Pos 12 /*!< MVFR0: FP exception trapping bits Position */ +#define FPU_MVFR0_FP_excep_trapping_Msk (0xFUL << FPU_MVFR0_FP_excep_trapping_Pos) /*!< MVFR0: FP exception trapping bits Mask */ + +#define FPU_MVFR0_Double_precision_Pos 8 /*!< MVFR0: Double-precision bits Position */ +#define FPU_MVFR0_Double_precision_Msk (0xFUL << FPU_MVFR0_Double_precision_Pos) /*!< MVFR0: Double-precision bits Mask */ + +#define FPU_MVFR0_Single_precision_Pos 4 /*!< MVFR0: Single-precision bits Position */ +#define FPU_MVFR0_Single_precision_Msk (0xFUL << FPU_MVFR0_Single_precision_Pos) /*!< MVFR0: Single-precision bits Mask */ + +#define FPU_MVFR0_A_SIMD_registers_Pos 0 /*!< MVFR0: A_SIMD registers bits Position */ +#define FPU_MVFR0_A_SIMD_registers_Msk (0xFUL << FPU_MVFR0_A_SIMD_registers_Pos) /*!< MVFR0: A_SIMD registers bits Mask */ + +/* Media and FP Feature Register 1 */ +#define FPU_MVFR1_FP_fused_MAC_Pos 28 /*!< MVFR1: FP fused MAC bits Position */ +#define FPU_MVFR1_FP_fused_MAC_Msk (0xFUL << FPU_MVFR1_FP_fused_MAC_Pos) /*!< MVFR1: FP fused MAC bits Mask */ + +#define FPU_MVFR1_FP_HPFP_Pos 24 /*!< MVFR1: FP HPFP bits Position */ +#define FPU_MVFR1_FP_HPFP_Msk (0xFUL << FPU_MVFR1_FP_HPFP_Pos) /*!< MVFR1: FP HPFP bits Mask */ + +#define FPU_MVFR1_D_NaN_mode_Pos 4 /*!< MVFR1: D_NaN mode bits Position */ +#define FPU_MVFR1_D_NaN_mode_Msk (0xFUL << FPU_MVFR1_D_NaN_mode_Pos) /*!< MVFR1: D_NaN mode bits Mask */ + +#define FPU_MVFR1_FtZ_mode_Pos 0 /*!< MVFR1: FtZ mode bits Position */ +#define FPU_MVFR1_FtZ_mode_Msk (0xFUL << FPU_MVFR1_FtZ_mode_Pos) /*!< MVFR1: FtZ mode bits Mask */ + +/*@} end of group CMSIS_FPU */ +#endif + + +/** \ingroup CMSIS_core_register + \defgroup CMSIS_CoreDebug Core Debug Registers (CoreDebug) + \brief Type definitions for the Core Debug Registers + @{ + */ + +/** \brief Structure type to access the Core Debug Register (CoreDebug). + */ +typedef struct +{ + __IO uint32_t DHCSR; /*!< Offset: 0x000 (R/W) Debug Halting Control and Status Register */ + __O uint32_t DCRSR; /*!< Offset: 0x004 ( /W) Debug Core Register Selector Register */ + __IO uint32_t DCRDR; /*!< Offset: 0x008 (R/W) Debug Core Register Data Register */ + __IO uint32_t DEMCR; /*!< Offset: 0x00C (R/W) Debug Exception and Monitor Control Register */ +} CoreDebug_Type; + +/* Debug Halting Control and Status Register */ +#define CoreDebug_DHCSR_DBGKEY_Pos 16 /*!< CoreDebug DHCSR: DBGKEY Position */ +#define CoreDebug_DHCSR_DBGKEY_Msk (0xFFFFUL << CoreDebug_DHCSR_DBGKEY_Pos) /*!< CoreDebug DHCSR: DBGKEY Mask */ + +#define CoreDebug_DHCSR_S_RESET_ST_Pos 25 /*!< CoreDebug DHCSR: S_RESET_ST Position */ +#define CoreDebug_DHCSR_S_RESET_ST_Msk (1UL << CoreDebug_DHCSR_S_RESET_ST_Pos) /*!< CoreDebug DHCSR: S_RESET_ST Mask */ + +#define CoreDebug_DHCSR_S_RETIRE_ST_Pos 24 /*!< CoreDebug DHCSR: S_RETIRE_ST Position */ +#define CoreDebug_DHCSR_S_RETIRE_ST_Msk (1UL << CoreDebug_DHCSR_S_RETIRE_ST_Pos) /*!< CoreDebug DHCSR: S_RETIRE_ST Mask */ + +#define CoreDebug_DHCSR_S_LOCKUP_Pos 19 /*!< CoreDebug DHCSR: S_LOCKUP Position */ +#define CoreDebug_DHCSR_S_LOCKUP_Msk (1UL << CoreDebug_DHCSR_S_LOCKUP_Pos) /*!< CoreDebug DHCSR: S_LOCKUP Mask */ + +#define CoreDebug_DHCSR_S_SLEEP_Pos 18 /*!< CoreDebug DHCSR: S_SLEEP Position */ +#define CoreDebug_DHCSR_S_SLEEP_Msk (1UL << CoreDebug_DHCSR_S_SLEEP_Pos) /*!< CoreDebug DHCSR: S_SLEEP Mask */ + +#define CoreDebug_DHCSR_S_HALT_Pos 17 /*!< CoreDebug DHCSR: S_HALT Position */ +#define CoreDebug_DHCSR_S_HALT_Msk (1UL << CoreDebug_DHCSR_S_HALT_Pos) /*!< CoreDebug DHCSR: S_HALT Mask */ + +#define CoreDebug_DHCSR_S_REGRDY_Pos 16 /*!< CoreDebug DHCSR: S_REGRDY Position */ +#define CoreDebug_DHCSR_S_REGRDY_Msk (1UL << CoreDebug_DHCSR_S_REGRDY_Pos) /*!< CoreDebug DHCSR: S_REGRDY Mask */ + +#define CoreDebug_DHCSR_C_SNAPSTALL_Pos 5 /*!< CoreDebug DHCSR: C_SNAPSTALL Position */ +#define CoreDebug_DHCSR_C_SNAPSTALL_Msk (1UL << CoreDebug_DHCSR_C_SNAPSTALL_Pos) /*!< CoreDebug DHCSR: C_SNAPSTALL Mask */ + +#define CoreDebug_DHCSR_C_MASKINTS_Pos 3 /*!< CoreDebug DHCSR: C_MASKINTS Position */ +#define CoreDebug_DHCSR_C_MASKINTS_Msk (1UL << CoreDebug_DHCSR_C_MASKINTS_Pos) /*!< CoreDebug DHCSR: C_MASKINTS Mask */ + +#define CoreDebug_DHCSR_C_STEP_Pos 2 /*!< CoreDebug DHCSR: C_STEP Position */ +#define CoreDebug_DHCSR_C_STEP_Msk (1UL << CoreDebug_DHCSR_C_STEP_Pos) /*!< CoreDebug DHCSR: C_STEP Mask */ + +#define CoreDebug_DHCSR_C_HALT_Pos 1 /*!< CoreDebug DHCSR: C_HALT Position */ +#define CoreDebug_DHCSR_C_HALT_Msk (1UL << CoreDebug_DHCSR_C_HALT_Pos) /*!< CoreDebug DHCSR: C_HALT Mask */ + +#define CoreDebug_DHCSR_C_DEBUGEN_Pos 0 /*!< CoreDebug DHCSR: C_DEBUGEN Position */ +#define CoreDebug_DHCSR_C_DEBUGEN_Msk (1UL << CoreDebug_DHCSR_C_DEBUGEN_Pos) /*!< CoreDebug DHCSR: C_DEBUGEN Mask */ + +/* Debug Core Register Selector Register */ +#define CoreDebug_DCRSR_REGWnR_Pos 16 /*!< CoreDebug DCRSR: REGWnR Position */ +#define CoreDebug_DCRSR_REGWnR_Msk (1UL << CoreDebug_DCRSR_REGWnR_Pos) /*!< CoreDebug DCRSR: REGWnR Mask */ + +#define CoreDebug_DCRSR_REGSEL_Pos 0 /*!< CoreDebug DCRSR: REGSEL Position */ +#define CoreDebug_DCRSR_REGSEL_Msk (0x1FUL << CoreDebug_DCRSR_REGSEL_Pos) /*!< CoreDebug DCRSR: REGSEL Mask */ + +/* Debug Exception and Monitor Control Register */ +#define CoreDebug_DEMCR_TRCENA_Pos 24 /*!< CoreDebug DEMCR: TRCENA Position */ +#define CoreDebug_DEMCR_TRCENA_Msk (1UL << CoreDebug_DEMCR_TRCENA_Pos) /*!< CoreDebug DEMCR: TRCENA Mask */ + +#define CoreDebug_DEMCR_MON_REQ_Pos 19 /*!< CoreDebug DEMCR: MON_REQ Position */ +#define CoreDebug_DEMCR_MON_REQ_Msk (1UL << CoreDebug_DEMCR_MON_REQ_Pos) /*!< CoreDebug DEMCR: MON_REQ Mask */ + +#define CoreDebug_DEMCR_MON_STEP_Pos 18 /*!< CoreDebug DEMCR: MON_STEP Position */ +#define CoreDebug_DEMCR_MON_STEP_Msk (1UL << CoreDebug_DEMCR_MON_STEP_Pos) /*!< CoreDebug DEMCR: MON_STEP Mask */ + +#define CoreDebug_DEMCR_MON_PEND_Pos 17 /*!< CoreDebug DEMCR: MON_PEND Position */ +#define CoreDebug_DEMCR_MON_PEND_Msk (1UL << CoreDebug_DEMCR_MON_PEND_Pos) /*!< CoreDebug DEMCR: MON_PEND Mask */ + +#define CoreDebug_DEMCR_MON_EN_Pos 16 /*!< CoreDebug DEMCR: MON_EN Position */ +#define CoreDebug_DEMCR_MON_EN_Msk (1UL << CoreDebug_DEMCR_MON_EN_Pos) /*!< CoreDebug DEMCR: MON_EN Mask */ + +#define CoreDebug_DEMCR_VC_HARDERR_Pos 10 /*!< CoreDebug DEMCR: VC_HARDERR Position */ +#define CoreDebug_DEMCR_VC_HARDERR_Msk (1UL << CoreDebug_DEMCR_VC_HARDERR_Pos) /*!< CoreDebug DEMCR: VC_HARDERR Mask */ + +#define CoreDebug_DEMCR_VC_INTERR_Pos 9 /*!< CoreDebug DEMCR: VC_INTERR Position */ +#define CoreDebug_DEMCR_VC_INTERR_Msk (1UL << CoreDebug_DEMCR_VC_INTERR_Pos) /*!< CoreDebug DEMCR: VC_INTERR Mask */ + +#define CoreDebug_DEMCR_VC_BUSERR_Pos 8 /*!< CoreDebug DEMCR: VC_BUSERR Position */ +#define CoreDebug_DEMCR_VC_BUSERR_Msk (1UL << CoreDebug_DEMCR_VC_BUSERR_Pos) /*!< CoreDebug DEMCR: VC_BUSERR Mask */ + +#define CoreDebug_DEMCR_VC_STATERR_Pos 7 /*!< CoreDebug DEMCR: VC_STATERR Position */ +#define CoreDebug_DEMCR_VC_STATERR_Msk (1UL << CoreDebug_DEMCR_VC_STATERR_Pos) /*!< CoreDebug DEMCR: VC_STATERR Mask */ + +#define CoreDebug_DEMCR_VC_CHKERR_Pos 6 /*!< CoreDebug DEMCR: VC_CHKERR Position */ +#define CoreDebug_DEMCR_VC_CHKERR_Msk (1UL << CoreDebug_DEMCR_VC_CHKERR_Pos) /*!< CoreDebug DEMCR: VC_CHKERR Mask */ + +#define CoreDebug_DEMCR_VC_NOCPERR_Pos 5 /*!< CoreDebug DEMCR: VC_NOCPERR Position */ +#define CoreDebug_DEMCR_VC_NOCPERR_Msk (1UL << CoreDebug_DEMCR_VC_NOCPERR_Pos) /*!< CoreDebug DEMCR: VC_NOCPERR Mask */ + +#define CoreDebug_DEMCR_VC_MMERR_Pos 4 /*!< CoreDebug DEMCR: VC_MMERR Position */ +#define CoreDebug_DEMCR_VC_MMERR_Msk (1UL << CoreDebug_DEMCR_VC_MMERR_Pos) /*!< CoreDebug DEMCR: VC_MMERR Mask */ + +#define CoreDebug_DEMCR_VC_CORERESET_Pos 0 /*!< CoreDebug DEMCR: VC_CORERESET Position */ +#define CoreDebug_DEMCR_VC_CORERESET_Msk (1UL << CoreDebug_DEMCR_VC_CORERESET_Pos) /*!< CoreDebug DEMCR: VC_CORERESET Mask */ + +/*@} end of group CMSIS_CoreDebug */ + + +/** \ingroup CMSIS_core_register + \defgroup CMSIS_core_base Core Definitions + \brief Definitions for base addresses, unions, and structures. + @{ + */ + +/* Memory mapping of Cortex-M4 Hardware */ +#define SCS_BASE (0xE000E000UL) /*!< System Control Space Base Address */ +#define ITM_BASE (0xE0000000UL) /*!< ITM Base Address */ +#define DWT_BASE (0xE0001000UL) /*!< DWT Base Address */ +#define TPI_BASE (0xE0040000UL) /*!< TPI Base Address */ +#define CoreDebug_BASE (0xE000EDF0UL) /*!< Core Debug Base Address */ +#define SysTick_BASE (SCS_BASE + 0x0010UL) /*!< SysTick Base Address */ +#define NVIC_BASE (SCS_BASE + 0x0100UL) /*!< NVIC Base Address */ +#define SCB_BASE (SCS_BASE + 0x0D00UL) /*!< System Control Block Base Address */ + +#define SCnSCB ((SCnSCB_Type *) SCS_BASE ) /*!< System control Register not in SCB */ +#define SCB ((SCB_Type *) SCB_BASE ) /*!< SCB configuration struct */ +#define SysTick ((SysTick_Type *) SysTick_BASE ) /*!< SysTick configuration struct */ +#define NVIC ((NVIC_Type *) NVIC_BASE ) /*!< NVIC configuration struct */ +#define ITM ((ITM_Type *) ITM_BASE ) /*!< ITM configuration struct */ +#define DWT ((DWT_Type *) DWT_BASE ) /*!< DWT configuration struct */ +#define TPI ((TPI_Type *) TPI_BASE ) /*!< TPI configuration struct */ +#define CoreDebug ((CoreDebug_Type *) CoreDebug_BASE) /*!< Core Debug configuration struct */ + +#if (__MPU_PRESENT == 1) + #define MPU_BASE (SCS_BASE + 0x0D90UL) /*!< Memory Protection Unit */ + #define MPU ((MPU_Type *) MPU_BASE ) /*!< Memory Protection Unit */ +#endif + +#if (__FPU_PRESENT == 1) + #define FPU_BASE (SCS_BASE + 0x0F30UL) /*!< Floating Point Unit */ + #define FPU ((FPU_Type *) FPU_BASE ) /*!< Floating Point Unit */ +#endif + +/*@} */ + + + +/******************************************************************************* + * Hardware Abstraction Layer + Core Function Interface contains: + - Core NVIC Functions + - Core SysTick Functions + - Core Debug Functions + - Core Register Access Functions + ******************************************************************************/ +/** \defgroup CMSIS_Core_FunctionInterface Functions and Instructions Reference +*/ + + + +/* ########################## NVIC functions #################################### */ +/** \ingroup CMSIS_Core_FunctionInterface + \defgroup CMSIS_Core_NVICFunctions NVIC Functions + \brief Functions that manage interrupts and exceptions via the NVIC. + @{ + */ + +/** \brief Set Priority Grouping + + The function sets the priority grouping field using the required unlock sequence. + The parameter PriorityGroup is assigned to the field SCB->AIRCR [10:8] PRIGROUP field. + Only values from 0..7 are used. + In case of a conflict between priority grouping and available + priority bits (__NVIC_PRIO_BITS), the smallest possible priority group is set. + + \param [in] PriorityGroup Priority grouping field. + */ +__STATIC_INLINE void NVIC_SetPriorityGrouping(uint32_t PriorityGroup) +{ + uint32_t reg_value; + uint32_t PriorityGroupTmp = (PriorityGroup & (uint32_t)0x07); /* only values 0..7 are used */ + + reg_value = SCB->AIRCR; /* read old register configuration */ + reg_value &= ~(SCB_AIRCR_VECTKEY_Msk | SCB_AIRCR_PRIGROUP_Msk); /* clear bits to change */ + reg_value = (reg_value | + ((uint32_t)0x5FA << SCB_AIRCR_VECTKEY_Pos) | + (PriorityGroupTmp << 8)); /* Insert write key and priorty group */ + SCB->AIRCR = reg_value; +} + + +/** \brief Get Priority Grouping + + The function reads the priority grouping field from the NVIC Interrupt Controller. + + \return Priority grouping field (SCB->AIRCR [10:8] PRIGROUP field). + */ +__STATIC_INLINE uint32_t NVIC_GetPriorityGrouping(void) +{ + return ((SCB->AIRCR & SCB_AIRCR_PRIGROUP_Msk) >> SCB_AIRCR_PRIGROUP_Pos); /* read priority grouping field */ +} + + +/** \brief Enable External Interrupt + + The function enables a device-specific interrupt in the NVIC interrupt controller. + + \param [in] IRQn External interrupt number. Value cannot be negative. + */ +__STATIC_INLINE void NVIC_EnableIRQ(IRQn_Type IRQn) +{ +/* NVIC->ISER[((uint32_t)(IRQn) >> 5)] = (1 << ((uint32_t)(IRQn) & 0x1F)); enable interrupt */ + NVIC->ISER[(uint32_t)((int32_t)IRQn) >> 5] = (uint32_t)(1 << ((uint32_t)((int32_t)IRQn) & (uint32_t)0x1F)); /* enable interrupt */ +} + + +/** \brief Disable External Interrupt + + The function disables a device-specific interrupt in the NVIC interrupt controller. + + \param [in] IRQn External interrupt number. Value cannot be negative. + */ +__STATIC_INLINE void NVIC_DisableIRQ(IRQn_Type IRQn) +{ + NVIC->ICER[((uint32_t)(IRQn) >> 5)] = (1 << ((uint32_t)(IRQn) & 0x1F)); /* disable interrupt */ +} + + +/** \brief Get Pending Interrupt + + The function reads the pending register in the NVIC and returns the pending bit + for the specified interrupt. + + \param [in] IRQn Interrupt number. + + \return 0 Interrupt status is not pending. + \return 1 Interrupt status is pending. + */ +__STATIC_INLINE uint32_t NVIC_GetPendingIRQ(IRQn_Type IRQn) +{ + return((uint32_t) ((NVIC->ISPR[(uint32_t)(IRQn) >> 5] & (1 << ((uint32_t)(IRQn) & 0x1F)))?1:0)); /* Return 1 if pending else 0 */ +} + + +/** \brief Set Pending Interrupt + + The function sets the pending bit of an external interrupt. + + \param [in] IRQn Interrupt number. Value cannot be negative. + */ +__STATIC_INLINE void NVIC_SetPendingIRQ(IRQn_Type IRQn) +{ + NVIC->ISPR[((uint32_t)(IRQn) >> 5)] = (1 << ((uint32_t)(IRQn) & 0x1F)); /* set interrupt pending */ +} + + +/** \brief Clear Pending Interrupt + + The function clears the pending bit of an external interrupt. + + \param [in] IRQn External interrupt number. Value cannot be negative. + */ +__STATIC_INLINE void NVIC_ClearPendingIRQ(IRQn_Type IRQn) +{ + NVIC->ICPR[((uint32_t)(IRQn) >> 5)] = (1 << ((uint32_t)(IRQn) & 0x1F)); /* Clear pending interrupt */ +} + + +/** \brief Get Active Interrupt + + The function reads the active register in NVIC and returns the active bit. + + \param [in] IRQn Interrupt number. + + \return 0 Interrupt status is not active. + \return 1 Interrupt status is active. + */ +__STATIC_INLINE uint32_t NVIC_GetActive(IRQn_Type IRQn) +{ + return((uint32_t)((NVIC->IABR[(uint32_t)(IRQn) >> 5] & (1 << ((uint32_t)(IRQn) & 0x1F)))?1:0)); /* Return 1 if active else 0 */ +} + + +/** \brief Set Interrupt Priority + + The function sets the priority of an interrupt. + + \note The priority cannot be set for every core interrupt. + + \param [in] IRQn Interrupt number. + \param [in] priority Priority to set. + */ +__STATIC_INLINE void NVIC_SetPriority(IRQn_Type IRQn, uint32_t priority) +{ + if(IRQn < 0) { + SCB->SHP[((uint32_t)(IRQn) & 0xF)-4] = ((priority << (8 - __NVIC_PRIO_BITS)) & 0xff); } /* set Priority for Cortex-M System Interrupts */ + else { + NVIC->IP[(uint32_t)(IRQn)] = ((priority << (8 - __NVIC_PRIO_BITS)) & 0xff); } /* set Priority for device specific Interrupts */ +} + + +/** \brief Get Interrupt Priority + + The function reads the priority of an interrupt. The interrupt + number can be positive to specify an external (device specific) + interrupt, or negative to specify an internal (core) interrupt. + + + \param [in] IRQn Interrupt number. + \return Interrupt Priority. Value is aligned automatically to the implemented + priority bits of the microcontroller. + */ +__STATIC_INLINE uint32_t NVIC_GetPriority(IRQn_Type IRQn) +{ + + if(IRQn < 0) { + return((uint32_t)(SCB->SHP[((uint32_t)(IRQn) & 0xF)-4] >> (8 - __NVIC_PRIO_BITS))); } /* get priority for Cortex-M system interrupts */ + else { + return((uint32_t)(NVIC->IP[(uint32_t)(IRQn)] >> (8 - __NVIC_PRIO_BITS))); } /* get priority for device specific interrupts */ +} + + +/** \brief Encode Priority + + The function encodes the priority for an interrupt with the given priority group, + preemptive priority value, and subpriority value. + In case of a conflict between priority grouping and available + priority bits (__NVIC_PRIO_BITS), the samllest possible priority group is set. + + \param [in] PriorityGroup Used priority group. + \param [in] PreemptPriority Preemptive priority value (starting from 0). + \param [in] SubPriority Subpriority value (starting from 0). + \return Encoded priority. Value can be used in the function \ref NVIC_SetPriority(). + */ +__STATIC_INLINE uint32_t NVIC_EncodePriority (uint32_t PriorityGroup, uint32_t PreemptPriority, uint32_t SubPriority) +{ + uint32_t PriorityGroupTmp = (PriorityGroup & 0x07); /* only values 0..7 are used */ + uint32_t PreemptPriorityBits; + uint32_t SubPriorityBits; + + PreemptPriorityBits = ((7 - PriorityGroupTmp) > __NVIC_PRIO_BITS) ? __NVIC_PRIO_BITS : 7 - PriorityGroupTmp; + SubPriorityBits = ((PriorityGroupTmp + __NVIC_PRIO_BITS) < 7) ? 0 : PriorityGroupTmp - 7 + __NVIC_PRIO_BITS; + + return ( + ((PreemptPriority & ((1 << (PreemptPriorityBits)) - 1)) << SubPriorityBits) | + ((SubPriority & ((1 << (SubPriorityBits )) - 1))) + ); +} + + +/** \brief Decode Priority + + The function decodes an interrupt priority value with a given priority group to + preemptive priority value and subpriority value. + In case of a conflict between priority grouping and available + priority bits (__NVIC_PRIO_BITS) the samllest possible priority group is set. + + \param [in] Priority Priority value, which can be retrieved with the function \ref NVIC_GetPriority(). + \param [in] PriorityGroup Used priority group. + \param [out] pPreemptPriority Preemptive priority value (starting from 0). + \param [out] pSubPriority Subpriority value (starting from 0). + */ +__STATIC_INLINE void NVIC_DecodePriority (uint32_t Priority, uint32_t PriorityGroup, uint32_t* pPreemptPriority, uint32_t* pSubPriority) +{ + uint32_t PriorityGroupTmp = (PriorityGroup & 0x07); /* only values 0..7 are used */ + uint32_t PreemptPriorityBits; + uint32_t SubPriorityBits; + + PreemptPriorityBits = ((7 - PriorityGroupTmp) > __NVIC_PRIO_BITS) ? __NVIC_PRIO_BITS : 7 - PriorityGroupTmp; + SubPriorityBits = ((PriorityGroupTmp + __NVIC_PRIO_BITS) < 7) ? 0 : PriorityGroupTmp - 7 + __NVIC_PRIO_BITS; + + *pPreemptPriority = (Priority >> SubPriorityBits) & ((1 << (PreemptPriorityBits)) - 1); + *pSubPriority = (Priority ) & ((1 << (SubPriorityBits )) - 1); +} + + +/** \brief System Reset + + The function initiates a system reset request to reset the MCU. + */ +__STATIC_INLINE void NVIC_SystemReset(void) +{ + __DSB(); /* Ensure all outstanding memory accesses included + buffered write are completed before reset */ + SCB->AIRCR = ((0x5FA << SCB_AIRCR_VECTKEY_Pos) | + (SCB->AIRCR & SCB_AIRCR_PRIGROUP_Msk) | + SCB_AIRCR_SYSRESETREQ_Msk); /* Keep priority group unchanged */ + __DSB(); /* Ensure completion of memory access */ + while(1); /* wait until reset */ +} + +/*@} end of CMSIS_Core_NVICFunctions */ + + + +/* ################################## SysTick function ############################################ */ +/** \ingroup CMSIS_Core_FunctionInterface + \defgroup CMSIS_Core_SysTickFunctions SysTick Functions + \brief Functions that configure the System. + @{ + */ + +#if (__Vendor_SysTickConfig == 0) + +/** \brief System Tick Configuration + + The function initializes the System Timer and its interrupt, and starts the System Tick Timer. + Counter is in free running mode to generate periodic interrupts. + + \param [in] ticks Number of ticks between two interrupts. + + \return 0 Function succeeded. + \return 1 Function failed. + + \note When the variable __Vendor_SysTickConfig is set to 1, then the + function SysTick_Config is not included. In this case, the file device.h + must contain a vendor-specific implementation of this function. + + */ +__STATIC_INLINE uint32_t SysTick_Config(uint32_t ticks) +{ + if ((ticks - 1) > SysTick_LOAD_RELOAD_Msk) return (1); /* Reload value impossible */ + + SysTick->LOAD = ticks - 1; /* set reload register */ + NVIC_SetPriority (SysTick_IRQn, (1<<__NVIC_PRIO_BITS) - 1); /* set Priority for Systick Interrupt */ + SysTick->VAL = 0; /* Load the SysTick Counter Value */ + SysTick->CTRL = SysTick_CTRL_CLKSOURCE_Msk | + SysTick_CTRL_TICKINT_Msk | + SysTick_CTRL_ENABLE_Msk; /* Enable SysTick IRQ and SysTick Timer */ + return (0); /* Function successful */ +} + +#endif + +/*@} end of CMSIS_Core_SysTickFunctions */ + + + +/* ##################################### Debug In/Output function ########################################### */ +/** \ingroup CMSIS_Core_FunctionInterface + \defgroup CMSIS_core_DebugFunctions ITM Functions + \brief Functions that access the ITM debug interface. + @{ + */ + +extern volatile int32_t ITM_RxBuffer; /*!< External variable to receive characters. */ +#define ITM_RXBUFFER_EMPTY 0x5AA55AA5 /*!< Value identifying \ref ITM_RxBuffer is ready for next character. */ + + +/** \brief ITM Send Character + + The function transmits a character via the ITM channel 0, and + \li Just returns when no debugger is connected that has booked the output. + \li Is blocking when a debugger is connected, but the previous character sent has not been transmitted. + + \param [in] ch Character to transmit. + + \returns Character to transmit. + */ +__STATIC_INLINE uint32_t ITM_SendChar (uint32_t ch) +{ + if ((ITM->TCR & ITM_TCR_ITMENA_Msk) && /* ITM enabled */ + (ITM->TER & (1UL << 0) ) ) /* ITM Port #0 enabled */ + { + while (ITM->PORT[0].u32 == 0); + ITM->PORT[0].u8 = (uint8_t) ch; + } + return (ch); +} + + +/** \brief ITM Receive Character + + The function inputs a character via the external variable \ref ITM_RxBuffer. + + \return Received character. + \return -1 No character pending. + */ +__STATIC_INLINE int32_t ITM_ReceiveChar (void) { + int32_t ch = -1; /* no character available */ + + if (ITM_RxBuffer != ITM_RXBUFFER_EMPTY) { + ch = ITM_RxBuffer; + ITM_RxBuffer = ITM_RXBUFFER_EMPTY; /* ready for next character */ + } + + return (ch); +} + + +/** \brief ITM Check Character + + The function checks whether a character is pending for reading in the variable \ref ITM_RxBuffer. + + \return 0 No character available. + \return 1 Character available. + */ +__STATIC_INLINE int32_t ITM_CheckChar (void) { + + if (ITM_RxBuffer == ITM_RXBUFFER_EMPTY) { + return (0); /* no character available */ + } else { + return (1); /* character available */ + } +} + +/*@} end of CMSIS_core_DebugFunctions */ + +#endif /* __CORE_CM4_H_DEPENDANT */ + +#endif /* __CMSIS_GENERIC */ + +#ifdef __cplusplus +} +#endif diff --git a/bsp/gd32/libraries/GD32F4xx_Firmware_Library/CMSIS/core_cm4_simd.h b/bsp/gd32/libraries/GD32F4xx_Firmware_Library/CMSIS/core_cm4_simd.h new file mode 100644 index 0000000000..f9bceff1e5 --- /dev/null +++ b/bsp/gd32/libraries/GD32F4xx_Firmware_Library/CMSIS/core_cm4_simd.h @@ -0,0 +1,697 @@ +/**************************************************************************//** + * @file core_cm4_simd.h + * @brief CMSIS Cortex-M4 SIMD Header File + * @version V3.30 + * @date 17. February 2014 + * + * @note + * + ******************************************************************************/ +/* Copyright (c) 2009 - 2014 ARM LIMITED + + All rights reserved. + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + - Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + - Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + - Neither the name of ARM nor the names of its contributors may be used + to endorse or promote products derived from this software without + specific prior written permission. + * + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDERS AND CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + ---------------------------------------------------------------------------*/ + + +#if defined ( __ICCARM__ ) + #pragma system_include /* treat file as system include file for MISRA check */ +#endif + +#ifndef __CORE_CM4_SIMD_H +#define __CORE_CM4_SIMD_H + +#ifdef __cplusplus + extern "C" { +#endif + + +/******************************************************************************* + * Hardware Abstraction Layer + ******************************************************************************/ + + +/* ################### Compiler specific Intrinsics ########################### */ +/** \defgroup CMSIS_SIMD_intrinsics CMSIS SIMD Intrinsics + Access to dedicated SIMD instructions + @{ +*/ + +#if defined ( __CC_ARM ) /*------------------RealView Compiler -----------------*/ +/* ARM armcc specific functions */ +#define __SADD8 __sadd8 +#define __QADD8 __qadd8 +#define __SHADD8 __shadd8 +#define __UADD8 __uadd8 +#define __UQADD8 __uqadd8 +#define __UHADD8 __uhadd8 +#define __SSUB8 __ssub8 +#define __QSUB8 __qsub8 +#define __SHSUB8 __shsub8 +#define __USUB8 __usub8 +#define __UQSUB8 __uqsub8 +#define __UHSUB8 __uhsub8 +#define __SADD16 __sadd16 +#define __QADD16 __qadd16 +#define __SHADD16 __shadd16 +#define __UADD16 __uadd16 +#define __UQADD16 __uqadd16 +#define __UHADD16 __uhadd16 +#define __SSUB16 __ssub16 +#define __QSUB16 __qsub16 +#define __SHSUB16 __shsub16 +#define __USUB16 __usub16 +#define __UQSUB16 __uqsub16 +#define __UHSUB16 __uhsub16 +#define __SASX __sasx +#define __QASX __qasx +#define __SHASX __shasx +#define __UASX __uasx +#define __UQASX __uqasx +#define __UHASX __uhasx +#define __SSAX __ssax +#define __QSAX __qsax +#define __SHSAX __shsax +#define __USAX __usax +#define __UQSAX __uqsax +#define __UHSAX __uhsax +#define __USAD8 __usad8 +#define __USADA8 __usada8 +#define __SSAT16 __ssat16 +#define __USAT16 __usat16 +#define __UXTB16 __uxtb16 +#define __UXTAB16 __uxtab16 +#define __SXTB16 __sxtb16 +#define __SXTAB16 __sxtab16 +#define __SMUAD __smuad +#define __SMUADX __smuadx +#define __SMLAD __smlad +#define __SMLADX __smladx +#define __SMLALD __smlald +#define __SMLALDX __smlaldx +#define __SMUSD __smusd +#define __SMUSDX __smusdx +#define __SMLSD __smlsd +#define __SMLSDX __smlsdx +#define __SMLSLD __smlsld +#define __SMLSLDX __smlsldx +#define __SEL __sel +#define __QADD __qadd +#define __QSUB __qsub + +#define __PKHBT(ARG1,ARG2,ARG3) ( ((((uint32_t)(ARG1)) ) & 0x0000FFFFUL) | \ + ((((uint32_t)(ARG2)) << (ARG3)) & 0xFFFF0000UL) ) + +#define __PKHTB(ARG1,ARG2,ARG3) ( ((((uint32_t)(ARG1)) ) & 0xFFFF0000UL) | \ + ((((uint32_t)(ARG2)) >> (ARG3)) & 0x0000FFFFUL) ) + +#define __SMMLA(ARG1,ARG2,ARG3) ( (int32_t)((((int64_t)(ARG1) * (ARG2)) + \ + ((int64_t)(ARG3) << 32) ) >> 32)) + + +#elif defined ( __GNUC__ ) /*------------------ GNU Compiler ---------------------*/ +/* GNU gcc specific functions */ +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SADD8(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("sadd8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __QADD8(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("qadd8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SHADD8(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("shadd8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __UADD8(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("uadd8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __UQADD8(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("uqadd8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __UHADD8(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("uhadd8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SSUB8(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("ssub8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __QSUB8(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("qsub8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SHSUB8(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("shsub8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __USUB8(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("usub8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __UQSUB8(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("uqsub8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __UHSUB8(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("uhsub8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SADD16(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("sadd16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __QADD16(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("qadd16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SHADD16(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("shadd16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __UADD16(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("uadd16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __UQADD16(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("uqadd16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __UHADD16(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("uhadd16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SSUB16(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("ssub16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __QSUB16(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("qsub16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SHSUB16(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("shsub16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __USUB16(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("usub16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __UQSUB16(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("uqsub16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __UHSUB16(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("uhsub16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SASX(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("sasx %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __QASX(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("qasx %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SHASX(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("shasx %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __UASX(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("uasx %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __UQASX(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("uqasx %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __UHASX(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("uhasx %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SSAX(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("ssax %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __QSAX(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("qsax %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SHSAX(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("shsax %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __USAX(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("usax %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __UQSAX(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("uqsax %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __UHSAX(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("uhsax %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __USAD8(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("usad8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __USADA8(uint32_t op1, uint32_t op2, uint32_t op3) +{ + uint32_t result; + + __ASM volatile ("usada8 %0, %1, %2, %3" : "=r" (result) : "r" (op1), "r" (op2), "r" (op3) ); + return(result); +} + +#define __SSAT16(ARG1,ARG2) \ +({ \ + uint32_t __RES, __ARG1 = (ARG1); \ + __ASM ("ssat16 %0, %1, %2" : "=r" (__RES) : "I" (ARG2), "r" (__ARG1) ); \ + __RES; \ + }) + +#define __USAT16(ARG1,ARG2) \ +({ \ + uint32_t __RES, __ARG1 = (ARG1); \ + __ASM ("usat16 %0, %1, %2" : "=r" (__RES) : "I" (ARG2), "r" (__ARG1) ); \ + __RES; \ + }) + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __UXTB16(uint32_t op1) +{ + uint32_t result; + + __ASM volatile ("uxtb16 %0, %1" : "=r" (result) : "r" (op1)); + return(result); +} + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __UXTAB16(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("uxtab16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SXTB16(uint32_t op1) +{ + uint32_t result; + + __ASM volatile ("sxtb16 %0, %1" : "=r" (result) : "r" (op1)); + return(result); +} + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SXTAB16(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("sxtab16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SMUAD (uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("smuad %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SMUADX (uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("smuadx %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SMLAD (uint32_t op1, uint32_t op2, uint32_t op3) +{ + uint32_t result; + + __ASM volatile ("smlad %0, %1, %2, %3" : "=r" (result) : "r" (op1), "r" (op2), "r" (op3) ); + return(result); +} + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SMLADX (uint32_t op1, uint32_t op2, uint32_t op3) +{ + uint32_t result; + + __ASM volatile ("smladx %0, %1, %2, %3" : "=r" (result) : "r" (op1), "r" (op2), "r" (op3) ); + return(result); +} + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint64_t __SMLALD (uint32_t op1, uint32_t op2, uint64_t acc) +{ + union llreg_u{ + uint32_t w32[2]; + uint64_t w64; + } llr; + llr.w64 = acc; + +#ifndef __ARMEB__ // Little endian + __ASM volatile ("smlald %0, %1, %2, %3" : "=r" (llr.w32[0]), "=r" (llr.w32[1]): "r" (op1), "r" (op2) , "0" (llr.w32[0]), "1" (llr.w32[1]) ); +#else // Big endian + __ASM volatile ("smlald %0, %1, %2, %3" : "=r" (llr.w32[1]), "=r" (llr.w32[0]): "r" (op1), "r" (op2) , "0" (llr.w32[1]), "1" (llr.w32[0]) ); +#endif + + return(llr.w64); +} + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint64_t __SMLALDX (uint32_t op1, uint32_t op2, uint64_t acc) +{ + union llreg_u{ + uint32_t w32[2]; + uint64_t w64; + } llr; + llr.w64 = acc; + +#ifndef __ARMEB__ // Little endian + __ASM volatile ("smlaldx %0, %1, %2, %3" : "=r" (llr.w32[0]), "=r" (llr.w32[1]): "r" (op1), "r" (op2) , "0" (llr.w32[0]), "1" (llr.w32[1]) ); +#else // Big endian + __ASM volatile ("smlaldx %0, %1, %2, %3" : "=r" (llr.w32[1]), "=r" (llr.w32[0]): "r" (op1), "r" (op2) , "0" (llr.w32[1]), "1" (llr.w32[0]) ); +#endif + + return(llr.w64); +} + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SMUSD (uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("smusd %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SMUSDX (uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("smusdx %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SMLSD (uint32_t op1, uint32_t op2, uint32_t op3) +{ + uint32_t result; + + __ASM volatile ("smlsd %0, %1, %2, %3" : "=r" (result) : "r" (op1), "r" (op2), "r" (op3) ); + return(result); +} + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SMLSDX (uint32_t op1, uint32_t op2, uint32_t op3) +{ + uint32_t result; + + __ASM volatile ("smlsdx %0, %1, %2, %3" : "=r" (result) : "r" (op1), "r" (op2), "r" (op3) ); + return(result); +} + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint64_t __SMLSLD (uint32_t op1, uint32_t op2, uint64_t acc) +{ + union llreg_u{ + uint32_t w32[2]; + uint64_t w64; + } llr; + llr.w64 = acc; + +#ifndef __ARMEB__ // Little endian + __ASM volatile ("smlsld %0, %1, %2, %3" : "=r" (llr.w32[0]), "=r" (llr.w32[1]): "r" (op1), "r" (op2) , "0" (llr.w32[0]), "1" (llr.w32[1]) ); +#else // Big endian + __ASM volatile ("smlsld %0, %1, %2, %3" : "=r" (llr.w32[1]), "=r" (llr.w32[0]): "r" (op1), "r" (op2) , "0" (llr.w32[1]), "1" (llr.w32[0]) ); +#endif + + return(llr.w64); +} + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint64_t __SMLSLDX (uint32_t op1, uint32_t op2, uint64_t acc) +{ + union llreg_u{ + uint32_t w32[2]; + uint64_t w64; + } llr; + llr.w64 = acc; + +#ifndef __ARMEB__ // Little endian + __ASM volatile ("smlsldx %0, %1, %2, %3" : "=r" (llr.w32[0]), "=r" (llr.w32[1]): "r" (op1), "r" (op2) , "0" (llr.w32[0]), "1" (llr.w32[1]) ); +#else // Big endian + __ASM volatile ("smlsldx %0, %1, %2, %3" : "=r" (llr.w32[1]), "=r" (llr.w32[0]): "r" (op1), "r" (op2) , "0" (llr.w32[1]), "1" (llr.w32[0]) ); +#endif + + return(llr.w64); +} + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SEL (uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("sel %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __QADD(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("qadd %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __QSUB(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("qsub %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +#define __PKHBT(ARG1,ARG2,ARG3) \ +({ \ + uint32_t __RES, __ARG1 = (ARG1), __ARG2 = (ARG2); \ + __ASM ("pkhbt %0, %1, %2, lsl %3" : "=r" (__RES) : "r" (__ARG1), "r" (__ARG2), "I" (ARG3) ); \ + __RES; \ + }) + +#define __PKHTB(ARG1,ARG2,ARG3) \ +({ \ + uint32_t __RES, __ARG1 = (ARG1), __ARG2 = (ARG2); \ + if (ARG3 == 0) \ + __ASM ("pkhtb %0, %1, %2" : "=r" (__RES) : "r" (__ARG1), "r" (__ARG2) ); \ + else \ + __ASM ("pkhtb %0, %1, %2, asr %3" : "=r" (__RES) : "r" (__ARG1), "r" (__ARG2), "I" (ARG3) ); \ + __RES; \ + }) + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SMMLA (int32_t op1, int32_t op2, int32_t op3) +{ + int32_t result; + + __ASM volatile ("smmla %0, %1, %2, %3" : "=r" (result): "r" (op1), "r" (op2), "r" (op3) ); + return(result); +} + + +#elif defined ( __ICCARM__ ) /*------------------ ICC Compiler -------------------*/ +/* IAR iccarm specific functions */ +#include + + +#elif defined ( __TMS470__ ) /*---------------- TI CCS Compiler ------------------*/ +/* TI CCS specific functions */ +#include + + +#elif defined ( __TASKING__ ) /*------------------ TASKING Compiler --------------*/ +/* TASKING carm specific functions */ +/* not yet supported */ + + +#elif defined ( __CSMC__ ) /*------------------ COSMIC Compiler -------------------*/ +/* Cosmic specific functions */ +#include + +#endif + +/*@} end of group CMSIS_SIMD_intrinsics */ + + +#ifdef __cplusplus +} +#endif + +#endif /* __CORE_CM4_SIMD_H */ diff --git a/bsp/gd32/libraries/GD32F4xx_HAL/CMSIS/core_cmFunc.h b/bsp/gd32/libraries/GD32F4xx_Firmware_Library/CMSIS/core_cmFunc.h similarity index 100% rename from bsp/gd32/libraries/GD32F4xx_HAL/CMSIS/core_cmFunc.h rename to bsp/gd32/libraries/GD32F4xx_Firmware_Library/CMSIS/core_cmFunc.h diff --git a/bsp/gd32/libraries/GD32F4xx_HAL/CMSIS/core_cmInstr.h b/bsp/gd32/libraries/GD32F4xx_Firmware_Library/CMSIS/core_cmInstr.h similarity index 100% rename from bsp/gd32/libraries/GD32F4xx_HAL/CMSIS/core_cmInstr.h rename to bsp/gd32/libraries/GD32F4xx_Firmware_Library/CMSIS/core_cmInstr.h diff --git a/bsp/gd32/libraries/GD32F4xx_HAL/GD32F4xx_standard_peripheral/Include/gd32f4xx_adc.h b/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_standard_peripheral/Include/gd32f4xx_adc.h similarity index 100% rename from bsp/gd32/libraries/GD32F4xx_HAL/GD32F4xx_standard_peripheral/Include/gd32f4xx_adc.h rename to bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_standard_peripheral/Include/gd32f4xx_adc.h diff --git a/bsp/gd32/libraries/GD32F4xx_HAL/GD32F4xx_standard_peripheral/Include/gd32f4xx_can.h b/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_standard_peripheral/Include/gd32f4xx_can.h similarity index 100% rename from bsp/gd32/libraries/GD32F4xx_HAL/GD32F4xx_standard_peripheral/Include/gd32f4xx_can.h rename to bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_standard_peripheral/Include/gd32f4xx_can.h diff --git a/bsp/gd32/libraries/GD32F4xx_HAL/GD32F4xx_standard_peripheral/Include/gd32f4xx_crc.h b/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_standard_peripheral/Include/gd32f4xx_crc.h similarity index 100% rename from bsp/gd32/libraries/GD32F4xx_HAL/GD32F4xx_standard_peripheral/Include/gd32f4xx_crc.h rename to bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_standard_peripheral/Include/gd32f4xx_crc.h diff --git a/bsp/gd32/libraries/GD32F4xx_HAL/GD32F4xx_standard_peripheral/Include/gd32f4xx_ctc.h b/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_standard_peripheral/Include/gd32f4xx_ctc.h similarity index 100% rename from bsp/gd32/libraries/GD32F4xx_HAL/GD32F4xx_standard_peripheral/Include/gd32f4xx_ctc.h rename to bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_standard_peripheral/Include/gd32f4xx_ctc.h diff --git a/bsp/gd32/libraries/GD32F4xx_HAL/GD32F4xx_standard_peripheral/Include/gd32f4xx_dac.h b/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_standard_peripheral/Include/gd32f4xx_dac.h similarity index 100% rename from bsp/gd32/libraries/GD32F4xx_HAL/GD32F4xx_standard_peripheral/Include/gd32f4xx_dac.h rename to bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_standard_peripheral/Include/gd32f4xx_dac.h diff --git a/bsp/gd32/libraries/GD32F4xx_HAL/GD32F4xx_standard_peripheral/Include/gd32f4xx_dbg.h b/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_standard_peripheral/Include/gd32f4xx_dbg.h similarity index 100% rename from bsp/gd32/libraries/GD32F4xx_HAL/GD32F4xx_standard_peripheral/Include/gd32f4xx_dbg.h rename to bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_standard_peripheral/Include/gd32f4xx_dbg.h diff --git a/bsp/gd32/libraries/GD32F4xx_HAL/GD32F4xx_standard_peripheral/Include/gd32f4xx_dci.h b/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_standard_peripheral/Include/gd32f4xx_dci.h similarity index 100% rename from bsp/gd32/libraries/GD32F4xx_HAL/GD32F4xx_standard_peripheral/Include/gd32f4xx_dci.h rename to bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_standard_peripheral/Include/gd32f4xx_dci.h diff --git a/bsp/gd32/libraries/GD32F4xx_HAL/GD32F4xx_standard_peripheral/Include/gd32f4xx_dma.h b/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_standard_peripheral/Include/gd32f4xx_dma.h similarity index 100% rename from bsp/gd32/libraries/GD32F4xx_HAL/GD32F4xx_standard_peripheral/Include/gd32f4xx_dma.h rename to bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_standard_peripheral/Include/gd32f4xx_dma.h diff --git a/bsp/gd32/libraries/GD32F4xx_HAL/GD32F4xx_standard_peripheral/Include/gd32f4xx_enet.h b/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_standard_peripheral/Include/gd32f4xx_enet.h similarity index 100% rename from bsp/gd32/libraries/GD32F4xx_HAL/GD32F4xx_standard_peripheral/Include/gd32f4xx_enet.h rename to bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_standard_peripheral/Include/gd32f4xx_enet.h diff --git a/bsp/gd32/libraries/GD32F4xx_HAL/GD32F4xx_standard_peripheral/Include/gd32f4xx_exmc.h b/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_standard_peripheral/Include/gd32f4xx_exmc.h similarity index 100% rename from bsp/gd32/libraries/GD32F4xx_HAL/GD32F4xx_standard_peripheral/Include/gd32f4xx_exmc.h rename to bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_standard_peripheral/Include/gd32f4xx_exmc.h diff --git a/bsp/gd32/libraries/GD32F4xx_HAL/GD32F4xx_standard_peripheral/Include/gd32f4xx_exti.h b/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_standard_peripheral/Include/gd32f4xx_exti.h similarity index 100% rename from bsp/gd32/libraries/GD32F4xx_HAL/GD32F4xx_standard_peripheral/Include/gd32f4xx_exti.h rename to bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_standard_peripheral/Include/gd32f4xx_exti.h diff --git a/bsp/gd32/libraries/GD32F4xx_HAL/GD32F4xx_standard_peripheral/Include/gd32f4xx_fmc.h b/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_standard_peripheral/Include/gd32f4xx_fmc.h similarity index 100% rename from bsp/gd32/libraries/GD32F4xx_HAL/GD32F4xx_standard_peripheral/Include/gd32f4xx_fmc.h rename to bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_standard_peripheral/Include/gd32f4xx_fmc.h diff --git a/bsp/gd32/libraries/GD32F4xx_HAL/GD32F4xx_standard_peripheral/Include/gd32f4xx_fwdgt.h b/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_standard_peripheral/Include/gd32f4xx_fwdgt.h similarity index 100% rename from bsp/gd32/libraries/GD32F4xx_HAL/GD32F4xx_standard_peripheral/Include/gd32f4xx_fwdgt.h rename to bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_standard_peripheral/Include/gd32f4xx_fwdgt.h diff --git a/bsp/gd32/libraries/GD32F4xx_HAL/GD32F4xx_standard_peripheral/Include/gd32f4xx_gpio.h b/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_standard_peripheral/Include/gd32f4xx_gpio.h similarity index 100% rename from bsp/gd32/libraries/GD32F4xx_HAL/GD32F4xx_standard_peripheral/Include/gd32f4xx_gpio.h rename to bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_standard_peripheral/Include/gd32f4xx_gpio.h diff --git a/bsp/gd32/libraries/GD32F4xx_HAL/GD32F4xx_standard_peripheral/Include/gd32f4xx_i2c.h b/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_standard_peripheral/Include/gd32f4xx_i2c.h similarity index 100% rename from bsp/gd32/libraries/GD32F4xx_HAL/GD32F4xx_standard_peripheral/Include/gd32f4xx_i2c.h rename to bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_standard_peripheral/Include/gd32f4xx_i2c.h diff --git a/bsp/gd32/libraries/GD32F4xx_HAL/GD32F4xx_standard_peripheral/Include/gd32f4xx_ipa.h b/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_standard_peripheral/Include/gd32f4xx_ipa.h similarity index 100% rename from bsp/gd32/libraries/GD32F4xx_HAL/GD32F4xx_standard_peripheral/Include/gd32f4xx_ipa.h rename to bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_standard_peripheral/Include/gd32f4xx_ipa.h diff --git a/bsp/gd32/libraries/GD32F4xx_HAL/GD32F4xx_standard_peripheral/Include/gd32f4xx_iref.h b/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_standard_peripheral/Include/gd32f4xx_iref.h similarity index 100% rename from bsp/gd32/libraries/GD32F4xx_HAL/GD32F4xx_standard_peripheral/Include/gd32f4xx_iref.h rename to bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_standard_peripheral/Include/gd32f4xx_iref.h diff --git a/bsp/gd32/libraries/GD32F4xx_HAL/GD32F4xx_standard_peripheral/Include/gd32f4xx_misc.h b/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_standard_peripheral/Include/gd32f4xx_misc.h similarity index 100% rename from bsp/gd32/libraries/GD32F4xx_HAL/GD32F4xx_standard_peripheral/Include/gd32f4xx_misc.h rename to bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_standard_peripheral/Include/gd32f4xx_misc.h diff --git a/bsp/gd32/libraries/GD32F4xx_HAL/GD32F4xx_standard_peripheral/Include/gd32f4xx_pmu.h b/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_standard_peripheral/Include/gd32f4xx_pmu.h similarity index 100% rename from bsp/gd32/libraries/GD32F4xx_HAL/GD32F4xx_standard_peripheral/Include/gd32f4xx_pmu.h rename to bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_standard_peripheral/Include/gd32f4xx_pmu.h diff --git a/bsp/gd32/libraries/GD32F4xx_HAL/GD32F4xx_standard_peripheral/Include/gd32f4xx_rcu.h b/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_standard_peripheral/Include/gd32f4xx_rcu.h similarity index 100% rename from bsp/gd32/libraries/GD32F4xx_HAL/GD32F4xx_standard_peripheral/Include/gd32f4xx_rcu.h rename to bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_standard_peripheral/Include/gd32f4xx_rcu.h diff --git a/bsp/gd32/libraries/GD32F4xx_HAL/GD32F4xx_standard_peripheral/Include/gd32f4xx_rtc.h b/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_standard_peripheral/Include/gd32f4xx_rtc.h similarity index 100% rename from bsp/gd32/libraries/GD32F4xx_HAL/GD32F4xx_standard_peripheral/Include/gd32f4xx_rtc.h rename to bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_standard_peripheral/Include/gd32f4xx_rtc.h diff --git a/bsp/gd32/libraries/GD32F4xx_HAL/GD32F4xx_standard_peripheral/Include/gd32f4xx_sdio.h b/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_standard_peripheral/Include/gd32f4xx_sdio.h similarity index 100% rename from bsp/gd32/libraries/GD32F4xx_HAL/GD32F4xx_standard_peripheral/Include/gd32f4xx_sdio.h rename to bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_standard_peripheral/Include/gd32f4xx_sdio.h diff --git a/bsp/gd32/libraries/GD32F4xx_HAL/GD32F4xx_standard_peripheral/Include/gd32f4xx_spi.h b/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_standard_peripheral/Include/gd32f4xx_spi.h similarity index 100% rename from bsp/gd32/libraries/GD32F4xx_HAL/GD32F4xx_standard_peripheral/Include/gd32f4xx_spi.h rename to bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_standard_peripheral/Include/gd32f4xx_spi.h diff --git a/bsp/gd32/libraries/GD32F4xx_HAL/GD32F4xx_standard_peripheral/Include/gd32f4xx_syscfg.h b/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_standard_peripheral/Include/gd32f4xx_syscfg.h similarity index 100% rename from bsp/gd32/libraries/GD32F4xx_HAL/GD32F4xx_standard_peripheral/Include/gd32f4xx_syscfg.h rename to bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_standard_peripheral/Include/gd32f4xx_syscfg.h diff --git a/bsp/gd32/libraries/GD32F4xx_HAL/GD32F4xx_standard_peripheral/Include/gd32f4xx_timer.h b/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_standard_peripheral/Include/gd32f4xx_timer.h similarity index 100% rename from bsp/gd32/libraries/GD32F4xx_HAL/GD32F4xx_standard_peripheral/Include/gd32f4xx_timer.h rename to bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_standard_peripheral/Include/gd32f4xx_timer.h diff --git a/bsp/gd32/libraries/GD32F4xx_HAL/GD32F4xx_standard_peripheral/Include/gd32f4xx_tli.h b/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_standard_peripheral/Include/gd32f4xx_tli.h similarity index 100% rename from bsp/gd32/libraries/GD32F4xx_HAL/GD32F4xx_standard_peripheral/Include/gd32f4xx_tli.h rename to bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_standard_peripheral/Include/gd32f4xx_tli.h diff --git a/bsp/gd32/libraries/GD32F4xx_HAL/GD32F4xx_standard_peripheral/Include/gd32f4xx_trng.h b/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_standard_peripheral/Include/gd32f4xx_trng.h similarity index 100% rename from bsp/gd32/libraries/GD32F4xx_HAL/GD32F4xx_standard_peripheral/Include/gd32f4xx_trng.h rename to bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_standard_peripheral/Include/gd32f4xx_trng.h diff --git a/bsp/gd32/libraries/GD32F4xx_HAL/GD32F4xx_standard_peripheral/Include/gd32f4xx_usart.h b/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_standard_peripheral/Include/gd32f4xx_usart.h similarity index 100% rename from bsp/gd32/libraries/GD32F4xx_HAL/GD32F4xx_standard_peripheral/Include/gd32f4xx_usart.h rename to bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_standard_peripheral/Include/gd32f4xx_usart.h diff --git a/bsp/gd32/libraries/GD32F4xx_HAL/GD32F4xx_standard_peripheral/Include/gd32f4xx_wwdgt.h b/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_standard_peripheral/Include/gd32f4xx_wwdgt.h similarity index 100% rename from bsp/gd32/libraries/GD32F4xx_HAL/GD32F4xx_standard_peripheral/Include/gd32f4xx_wwdgt.h rename to bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_standard_peripheral/Include/gd32f4xx_wwdgt.h diff --git a/bsp/gd32/libraries/GD32F4xx_HAL/GD32F4xx_standard_peripheral/Source/gd32f4xx_adc.c b/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_standard_peripheral/Source/gd32f4xx_adc.c similarity index 100% rename from bsp/gd32/libraries/GD32F4xx_HAL/GD32F4xx_standard_peripheral/Source/gd32f4xx_adc.c rename to bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_standard_peripheral/Source/gd32f4xx_adc.c diff --git a/bsp/gd32/libraries/GD32F4xx_HAL/GD32F4xx_standard_peripheral/Source/gd32f4xx_can.c b/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_standard_peripheral/Source/gd32f4xx_can.c similarity index 100% rename from bsp/gd32/libraries/GD32F4xx_HAL/GD32F4xx_standard_peripheral/Source/gd32f4xx_can.c rename to bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_standard_peripheral/Source/gd32f4xx_can.c diff --git a/bsp/gd32/libraries/GD32F4xx_HAL/GD32F4xx_standard_peripheral/Source/gd32f4xx_crc.c b/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_standard_peripheral/Source/gd32f4xx_crc.c similarity index 100% rename from bsp/gd32/libraries/GD32F4xx_HAL/GD32F4xx_standard_peripheral/Source/gd32f4xx_crc.c rename to bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_standard_peripheral/Source/gd32f4xx_crc.c diff --git a/bsp/gd32/libraries/GD32F4xx_HAL/GD32F4xx_standard_peripheral/Source/gd32f4xx_ctc.c b/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_standard_peripheral/Source/gd32f4xx_ctc.c similarity index 100% rename from bsp/gd32/libraries/GD32F4xx_HAL/GD32F4xx_standard_peripheral/Source/gd32f4xx_ctc.c rename to bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_standard_peripheral/Source/gd32f4xx_ctc.c diff --git a/bsp/gd32/libraries/GD32F4xx_HAL/GD32F4xx_standard_peripheral/Source/gd32f4xx_dac.c b/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_standard_peripheral/Source/gd32f4xx_dac.c similarity index 100% rename from bsp/gd32/libraries/GD32F4xx_HAL/GD32F4xx_standard_peripheral/Source/gd32f4xx_dac.c rename to bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_standard_peripheral/Source/gd32f4xx_dac.c diff --git a/bsp/gd32/libraries/GD32F4xx_HAL/GD32F4xx_standard_peripheral/Source/gd32f4xx_dbg.c b/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_standard_peripheral/Source/gd32f4xx_dbg.c similarity index 100% rename from bsp/gd32/libraries/GD32F4xx_HAL/GD32F4xx_standard_peripheral/Source/gd32f4xx_dbg.c rename to bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_standard_peripheral/Source/gd32f4xx_dbg.c diff --git a/bsp/gd32/libraries/GD32F4xx_HAL/GD32F4xx_standard_peripheral/Source/gd32f4xx_dci.c b/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_standard_peripheral/Source/gd32f4xx_dci.c similarity index 100% rename from bsp/gd32/libraries/GD32F4xx_HAL/GD32F4xx_standard_peripheral/Source/gd32f4xx_dci.c rename to bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_standard_peripheral/Source/gd32f4xx_dci.c diff --git a/bsp/gd32/libraries/GD32F4xx_HAL/GD32F4xx_standard_peripheral/Source/gd32f4xx_dma.c b/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_standard_peripheral/Source/gd32f4xx_dma.c similarity index 100% rename from bsp/gd32/libraries/GD32F4xx_HAL/GD32F4xx_standard_peripheral/Source/gd32f4xx_dma.c rename to bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_standard_peripheral/Source/gd32f4xx_dma.c diff --git a/bsp/gd32/libraries/GD32F4xx_HAL/GD32F4xx_standard_peripheral/Source/gd32f4xx_enet.c b/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_standard_peripheral/Source/gd32f4xx_enet.c similarity index 100% rename from bsp/gd32/libraries/GD32F4xx_HAL/GD32F4xx_standard_peripheral/Source/gd32f4xx_enet.c rename to bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_standard_peripheral/Source/gd32f4xx_enet.c diff --git a/bsp/gd32/libraries/GD32F4xx_HAL/GD32F4xx_standard_peripheral/Source/gd32f4xx_exmc.c b/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_standard_peripheral/Source/gd32f4xx_exmc.c similarity index 100% rename from bsp/gd32/libraries/GD32F4xx_HAL/GD32F4xx_standard_peripheral/Source/gd32f4xx_exmc.c rename to bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_standard_peripheral/Source/gd32f4xx_exmc.c diff --git a/bsp/gd32/libraries/GD32F4xx_HAL/GD32F4xx_standard_peripheral/Source/gd32f4xx_exti.c b/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_standard_peripheral/Source/gd32f4xx_exti.c similarity index 100% rename from bsp/gd32/libraries/GD32F4xx_HAL/GD32F4xx_standard_peripheral/Source/gd32f4xx_exti.c rename to bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_standard_peripheral/Source/gd32f4xx_exti.c diff --git a/bsp/gd32/libraries/GD32F4xx_HAL/GD32F4xx_standard_peripheral/Source/gd32f4xx_fmc.c b/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_standard_peripheral/Source/gd32f4xx_fmc.c similarity index 100% rename from bsp/gd32/libraries/GD32F4xx_HAL/GD32F4xx_standard_peripheral/Source/gd32f4xx_fmc.c rename to bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_standard_peripheral/Source/gd32f4xx_fmc.c diff --git a/bsp/gd32/libraries/GD32F4xx_HAL/GD32F4xx_standard_peripheral/Source/gd32f4xx_fwdgt.c b/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_standard_peripheral/Source/gd32f4xx_fwdgt.c similarity index 100% rename from bsp/gd32/libraries/GD32F4xx_HAL/GD32F4xx_standard_peripheral/Source/gd32f4xx_fwdgt.c rename to bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_standard_peripheral/Source/gd32f4xx_fwdgt.c diff --git a/bsp/gd32/libraries/GD32F4xx_HAL/GD32F4xx_standard_peripheral/Source/gd32f4xx_gpio.c b/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_standard_peripheral/Source/gd32f4xx_gpio.c similarity index 100% rename from bsp/gd32/libraries/GD32F4xx_HAL/GD32F4xx_standard_peripheral/Source/gd32f4xx_gpio.c rename to bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_standard_peripheral/Source/gd32f4xx_gpio.c diff --git a/bsp/gd32/libraries/GD32F4xx_HAL/GD32F4xx_standard_peripheral/Source/gd32f4xx_i2c.c b/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_standard_peripheral/Source/gd32f4xx_i2c.c similarity index 100% rename from bsp/gd32/libraries/GD32F4xx_HAL/GD32F4xx_standard_peripheral/Source/gd32f4xx_i2c.c rename to bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_standard_peripheral/Source/gd32f4xx_i2c.c diff --git a/bsp/gd32/libraries/GD32F4xx_HAL/GD32F4xx_standard_peripheral/Source/gd32f4xx_ipa.c b/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_standard_peripheral/Source/gd32f4xx_ipa.c similarity index 100% rename from bsp/gd32/libraries/GD32F4xx_HAL/GD32F4xx_standard_peripheral/Source/gd32f4xx_ipa.c rename to bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_standard_peripheral/Source/gd32f4xx_ipa.c diff --git a/bsp/gd32/libraries/GD32F4xx_HAL/GD32F4xx_standard_peripheral/Source/gd32f4xx_iref.c b/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_standard_peripheral/Source/gd32f4xx_iref.c similarity index 100% rename from bsp/gd32/libraries/GD32F4xx_HAL/GD32F4xx_standard_peripheral/Source/gd32f4xx_iref.c rename to bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_standard_peripheral/Source/gd32f4xx_iref.c diff --git a/bsp/gd32/libraries/GD32F4xx_HAL/GD32F4xx_standard_peripheral/Source/gd32f4xx_misc.c b/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_standard_peripheral/Source/gd32f4xx_misc.c similarity index 100% rename from bsp/gd32/libraries/GD32F4xx_HAL/GD32F4xx_standard_peripheral/Source/gd32f4xx_misc.c rename to bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_standard_peripheral/Source/gd32f4xx_misc.c diff --git a/bsp/gd32/libraries/GD32F4xx_HAL/GD32F4xx_standard_peripheral/Source/gd32f4xx_pmu.c b/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_standard_peripheral/Source/gd32f4xx_pmu.c similarity index 100% rename from bsp/gd32/libraries/GD32F4xx_HAL/GD32F4xx_standard_peripheral/Source/gd32f4xx_pmu.c rename to bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_standard_peripheral/Source/gd32f4xx_pmu.c diff --git a/bsp/gd32/libraries/GD32F4xx_HAL/GD32F4xx_standard_peripheral/Source/gd32f4xx_rcu.c b/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_standard_peripheral/Source/gd32f4xx_rcu.c similarity index 100% rename from bsp/gd32/libraries/GD32F4xx_HAL/GD32F4xx_standard_peripheral/Source/gd32f4xx_rcu.c rename to bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_standard_peripheral/Source/gd32f4xx_rcu.c diff --git a/bsp/gd32/libraries/GD32F4xx_HAL/GD32F4xx_standard_peripheral/Source/gd32f4xx_rtc.c b/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_standard_peripheral/Source/gd32f4xx_rtc.c similarity index 100% rename from bsp/gd32/libraries/GD32F4xx_HAL/GD32F4xx_standard_peripheral/Source/gd32f4xx_rtc.c rename to bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_standard_peripheral/Source/gd32f4xx_rtc.c diff --git a/bsp/gd32/libraries/GD32F4xx_HAL/GD32F4xx_standard_peripheral/Source/gd32f4xx_sdio.c b/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_standard_peripheral/Source/gd32f4xx_sdio.c similarity index 100% rename from bsp/gd32/libraries/GD32F4xx_HAL/GD32F4xx_standard_peripheral/Source/gd32f4xx_sdio.c rename to bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_standard_peripheral/Source/gd32f4xx_sdio.c diff --git a/bsp/gd32/libraries/GD32F4xx_HAL/GD32F4xx_standard_peripheral/Source/gd32f4xx_spi.c b/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_standard_peripheral/Source/gd32f4xx_spi.c similarity index 100% rename from bsp/gd32/libraries/GD32F4xx_HAL/GD32F4xx_standard_peripheral/Source/gd32f4xx_spi.c rename to bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_standard_peripheral/Source/gd32f4xx_spi.c diff --git a/bsp/gd32/libraries/GD32F4xx_HAL/GD32F4xx_standard_peripheral/Source/gd32f4xx_syscfg.c b/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_standard_peripheral/Source/gd32f4xx_syscfg.c similarity index 100% rename from bsp/gd32/libraries/GD32F4xx_HAL/GD32F4xx_standard_peripheral/Source/gd32f4xx_syscfg.c rename to bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_standard_peripheral/Source/gd32f4xx_syscfg.c diff --git a/bsp/gd32/libraries/GD32F4xx_HAL/GD32F4xx_standard_peripheral/Source/gd32f4xx_timer.c b/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_standard_peripheral/Source/gd32f4xx_timer.c similarity index 100% rename from bsp/gd32/libraries/GD32F4xx_HAL/GD32F4xx_standard_peripheral/Source/gd32f4xx_timer.c rename to bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_standard_peripheral/Source/gd32f4xx_timer.c diff --git a/bsp/gd32/libraries/GD32F4xx_HAL/GD32F4xx_standard_peripheral/Source/gd32f4xx_tli.c b/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_standard_peripheral/Source/gd32f4xx_tli.c similarity index 100% rename from bsp/gd32/libraries/GD32F4xx_HAL/GD32F4xx_standard_peripheral/Source/gd32f4xx_tli.c rename to bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_standard_peripheral/Source/gd32f4xx_tli.c diff --git a/bsp/gd32/libraries/GD32F4xx_HAL/GD32F4xx_standard_peripheral/Source/gd32f4xx_trng.c b/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_standard_peripheral/Source/gd32f4xx_trng.c similarity index 100% rename from bsp/gd32/libraries/GD32F4xx_HAL/GD32F4xx_standard_peripheral/Source/gd32f4xx_trng.c rename to bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_standard_peripheral/Source/gd32f4xx_trng.c diff --git a/bsp/gd32/libraries/GD32F4xx_HAL/GD32F4xx_standard_peripheral/Source/gd32f4xx_usart.c b/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_standard_peripheral/Source/gd32f4xx_usart.c similarity index 100% rename from bsp/gd32/libraries/GD32F4xx_HAL/GD32F4xx_standard_peripheral/Source/gd32f4xx_usart.c rename to bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_standard_peripheral/Source/gd32f4xx_usart.c diff --git a/bsp/gd32/libraries/GD32F4xx_HAL/GD32F4xx_standard_peripheral/Source/gd32f4xx_wwdgt.c b/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_standard_peripheral/Source/gd32f4xx_wwdgt.c similarity index 100% rename from bsp/gd32/libraries/GD32F4xx_HAL/GD32F4xx_standard_peripheral/Source/gd32f4xx_wwdgt.c rename to bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_standard_peripheral/Source/gd32f4xx_wwdgt.c diff --git a/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/device/class/audio/Include/audio_core.h b/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/device/class/audio/Include/audio_core.h new file mode 100644 index 0000000000..66e224d03a --- /dev/null +++ b/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/device/class/audio/Include/audio_core.h @@ -0,0 +1,300 @@ +/*! + \file audio_core.h + \brief the header file of USB audio device class core functions + + \version 2020-08-01, V3.0.0, firmware for GD32F4xx +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef __AUDIO_CORE_H +#define __AUDIO_CORE_H + +#include "usbd_enum.h" + +#define FORMAT_24BIT(x) (uint8_t)(x);(uint8_t)(x >> 8U);(uint8_t)(x >> 16U) + +/* number of sub-packets in the audio transfer buffer. you can modify this value but always make sure + that it is an even number and higher than 3 */ +#define OUT_PACKET_NUM 4U + +/* total size of the audio transfer buffer */ +#define OUT_BUF_MARGIN 4U +#define TOTAL_OUT_BUF_SIZE ((uint32_t)((SPEAKER_OUT_PACKET + OUT_BUF_MARGIN) * OUT_PACKET_NUM)) + +#define AUDIO_CONFIG_DESC_SET_LEN (sizeof(usb_desc_config_set)) +#define AUDIO_INTERFACE_DESC_SIZE 9U + +#define USB_AUDIO_DESC_SIZ 0x09U +#define AUDIO_STANDARD_EP_DESC_SIZE 0x09U +#define AUDIO_STREAMING_EP_DESC_SIZE 0x07U + +/* audio interface class code */ +#define USB_CLASS_AUDIO 0x01U + +/* audio interface subclass codes */ +#define AUDIO_SUBCLASS_CONTROL 0x01U +#define AUDIO_SUBCLASS_AUDIOSTREAMING 0x02U +#define AUDIO_SUBCLASS_MIDISTREAMING 0x03U + +/* audio interface protocol codes */ +#define AUDIO_PROTOCOL_UNDEFINED 0x00U +#define AUDIO_STREAMING_GENERAL 0x01U +#define AUDIO_STREAMING_FORMAT_TYPE 0x02U + +/* audio class-specific descriptor types */ +#define AUDIO_DESCTYPE_UNDEFINED 0x20U +#define AUDIO_DESCTYPE_DEVICE 0x21U +#define AUDIO_DESCTYPE_CONFIGURATION 0x22U +#define AUDIO_DESCTYPE_STRING 0x23U +#define AUDIO_DESCTYPE_INTERFACE 0x24U +#define AUDIO_DESCTYPE_ENDPOINT 0x25U + +/* audio control interface descriptor subtypes */ +#define AUDIO_CONTROL_HEADER 0x01U +#define AUDIO_CONTROL_INPUT_TERMINAL 0x02U +#define AUDIO_CONTROL_OUTPUT_TERMINAL 0x03U +#define AUDIO_CONTROL_MIXER_UNIT 0x04U +#define AUDIO_CONTROL_SELECTOR_UNIT 0x05U +#define AUDIO_CONTROL_FEATURE_UNIT 0x06U +#define AUDIO_CONTROL_PROCESSING_UNIT 0x07U +#define AUDIO_CONTROL_EXTENSION_UNIT 0x08U + +#define AUDIO_INPUT_TERMINAL_DESC_SIZE 0x0CU +#define AUDIO_OUTPUT_TERMINAL_DESC_SIZE 0x09U +#define AUDIO_STREAMING_INTERFACE_DESC_SIZE 0x07U + +#define AUDIO_CONTROL_MUTE 0x01U +#define AUDIO_CONTROL_VOLUME 0x02U + +#define AUDIO_FORMAT_TYPE_I 0x01U +#define AUDIO_FORMAT_TYPE_III 0x03U + +#define USB_ENDPOINT_TYPE_ISOCHRONOUS 0x01U +#define AUDIO_ENDPOINT_GENERAL 0x01U + +#define AUDIO_REQ_UNDEFINED 0x00U +#define AUDIO_REQ_SET_CUR 0x01U +#define AUDIO_REQ_GET_CUR 0x81U +#define AUDIO_REQ_SET_MIN 0x02U +#define AUDIO_REQ_GET_MIN 0x82U +#define AUDIO_REQ_SET_MAX 0x03U +#define AUDIO_REQ_GET_MAX 0x83U +#define AUDIO_REQ_SET_RES 0x04U +#define AUDIO_REQ_GET_RES 0x84U +#define AUDIO_REQ_SET_MEM 0x05U +#define AUDIO_REQ_GET_MEM 0x85U +#define AUDIO_REQ_GET_STAT 0xFFU + +#define AUDIO_OUT_STREAMING_CTRL 0x05U +#define AUDIO_IN_STREAMING_CTRL 0x02U + +/* audio stream interface number */ +enum +{ +#ifdef USE_USB_AUDIO_MICPHONE + MIC_INTERFACE_COUNT, +#endif +#ifdef USE_USB_AUDIO_SPEAKER + SPEAK_INTERFACE_COUNT, +#endif + CONFIG_DESC_AS_ITF_COUNT, +}; + +#define AC_ITF_TOTAL_LEN (sizeof(usb_desc_AC_itf) + CONFIG_DESC_AS_ITF_COUNT*(sizeof(usb_desc_input_terminal) + \ + sizeof(usb_desc_mono_feature_unit) + sizeof(usb_desc_output_terminal))) + +#pragma pack(1) + +typedef struct +{ + usb_desc_header header; /*!< descriptor header, including type and size */ + uint8_t bDescriptorSubtype; /*!< header descriptor subtype */ + uint16_t bcdADC; /*!< audio device class specification release number in binary-coded decimal */ + uint16_t wTotalLength; /*!< total number of bytes */ + uint8_t bInCollection; /*!< the number of the streaming interfaces */ +#ifdef USE_USB_AUDIO_MICPHONE + uint8_t baInterfaceNr0; /*!< interface number of the streaming interfaces */ +#endif + +#ifdef USE_USB_AUDIO_SPEAKER + uint8_t baInterfaceNr1; /*!< interface number of the streaming interfaces */ +#endif +} usb_desc_AC_itf; + +typedef struct +{ + usb_desc_header header; /*!< descriptor header, including type and size */ + uint8_t bDescriptorSubtype; /*!< AS_GENERAL descriptor subtype */ + uint8_t bTerminalLink; /*!< the terminal ID */ + uint8_t bDelay; /*!< delay introduced by the data path */ + uint16_t wFormatTag; /*!< the audio data format */ +} usb_desc_AS_itf; + +typedef struct +{ + usb_desc_header header; /*!< descriptor header, including type and size */ + uint8_t bDescriptorSubtype; /*!< INPUT_TERMINAL descriptor subtype. */ + uint8_t bTerminalID; /*!< constant uniquely identifying the terminal within the audio function */ + uint16_t wTerminalType; /*!< constant characterizing the type of terminal */ + uint8_t bAssocTerminal; /*!< ID of the output terminal */ + uint8_t bNrChannels; /*!< number of logical output channels */ + uint16_t wChannelConfig; /*!< describes the spatial location of the logical channels */ + uint8_t iChannelNames; /*!< index of a string descriptor */ + uint8_t iTerminal; /*!< index of a string descriptor */ +} usb_desc_input_terminal; + +typedef struct +{ + usb_desc_header header; /*!< descriptor header, including type and size */ + uint8_t bDescriptorSubtype; /*!< OUTPUT_TERMINAL descriptor subtype */ + uint8_t bTerminalID; /*!< constant uniquely identifying the terminal within the audio function */ + uint16_t wTerminalType; /*!< constant characterizing the type of terminal */ + uint8_t bAssocTerminal; /*!< constant, identifying the input terminal to which this output terminal is associated */ + uint8_t bSourceID; /*!< ID of the unit or terminal */ + uint8_t iTerminal; /*!< index of a string descriptor */ +} usb_desc_output_terminal; + +typedef struct +{ + usb_desc_header header; /*!< descriptor header, including type and size */ + uint8_t bDescriptorSubtype; /*!< FEATURE_UNIT descriptor subtype */ + uint8_t bUnitID; /*!< constant uniquely identifying the unit within the audio function */ + uint8_t bSourceID; /*!< ID of the unit or terminal */ + uint8_t bControlSize; /*!< size in bytes of an element of the bmaControls() array */ + uint8_t bmaControls0; /*!< a bit set to 1 indicates that the mentioned control is supported for master channel 0 */ + uint8_t bmaControls1; /*!< a bit set to 1 indicates that the mentioned control is supported for logical channel 1 */ + uint8_t iFeature; /*!< index of a string descriptor */ +} usb_desc_mono_feature_unit; + +typedef struct +{ + usb_desc_header header; /*!< descriptor header, including type and size */ + uint8_t bDescriptorSubtype; /*!< FEATURE_UNIT descriptor subtype */ + uint8_t bUnitID; /*!< constant uniquely identifying the unit within the audio function */ + uint8_t bSourceID; /*!< ID of the unit or terminal */ + uint8_t bControlSize; /*!< size in bytes of an element of the bmaControls() array */ + uint16_t bmaControls0; /*!< a bit set to 1 indicates that the mentioned control is supported for master channel 0 */ + uint16_t bmaControls1; /*!< a bit set to 1 indicates that the mentioned control is supported for logical channel 1 */ + uint16_t bmaControls2; /*!< a bit set to 1 indicates that the mentioned control is supported for logical channel 2 */ + uint8_t iFeature; /*!< index of a string descriptor */ +} usb_desc_stereo_feature_unit; + +typedef struct +{ + usb_desc_header header; /*!< descriptor header, including type and size */ + uint8_t bDescriptorSubtype; /*!< FORMAT_TYPE descriptor subtype */ + uint8_t bFormatType; /*!< constant identifying the format type */ + uint8_t bNrChannels; /*!< indicates the number of physical channels in the audio data stream */ + uint8_t bSubFrameSize; /*!< the number of bytes occupied by one audio subframe */ + uint8_t bBitResolution; /*!< the number of effectively used bits from the available bits in an audio subframe */ + uint8_t bSamFreqType; /*!< indicates how the sampling frequency can be programmed */ + uint8_t bSamFreq[3]; /*!< sampling frequency ns in Hz for this isochronous data endpoint */ +} usb_desc_format_type; + +typedef struct +{ + usb_desc_header header; /*!< descriptor header, including type and size */ + uint8_t bEndpointAddress; /*!< the address of the endpoint */ + uint8_t bmAttributes; /*!< transfer type and synchronization type */ + uint16_t wMaxPacketSize; /*!< maximum packet size this endpoint is capable of sending or receiving */ + uint8_t bInterval; /*!< left to the designer's discretion */ + uint8_t bRefresh; /*!< reset to 0 */ + uint8_t bSynchAddress; /*!< reset to 0 */ +} usb_desc_std_ep; + +typedef struct +{ + usb_desc_header header; /*!< descriptor header, including type and size */ + uint8_t bDescriptorSubtype; /*!< EP_GENERAL descriptor subtype */ + uint8_t bmAttributes; /*!< transfer type and synchronization type */ + uint8_t bLockDelayUnits; /*!< indicates the units used for the wLockDelay field */ + uint16_t wLockDelay; /*!< indicates the time it takes this endpoint to reliably lock its internal clock recovery circuitry */ +} usb_desc_AS_ep; + +#pragma pack() + +/* USB configuration descriptor structure */ +typedef struct +{ + usb_desc_config config; + usb_desc_itf std_itf; + usb_desc_AC_itf ac_itf; + +#ifdef USE_USB_AUDIO_MICPHONE + usb_desc_input_terminal mic_in_terminal; + usb_desc_mono_feature_unit mic_feature_unit; + usb_desc_output_terminal mic_out_terminal; +#endif + +#ifdef USE_USB_AUDIO_SPEAKER + usb_desc_input_terminal speak_in_terminal; + usb_desc_mono_feature_unit speak_feature_unit; + usb_desc_output_terminal speak_out_terminal; +#endif + +#ifdef USE_USB_AUDIO_MICPHONE + usb_desc_itf mic_std_as_itf_zeroband; + usb_desc_itf mic_std_as_itf_opera; + usb_desc_AS_itf mic_as_itf; + usb_desc_format_type mic_format_typeI; + usb_desc_std_ep mic_std_endpoint; + usb_desc_AS_ep mic_as_endpoint; +#endif + +#ifdef USE_USB_AUDIO_SPEAKER + usb_desc_itf speak_std_as_itf_zeroband; + usb_desc_itf speak_std_as_itf_opera; + usb_desc_AS_itf speak_as_itf; + usb_desc_format_type speak_format_typeI; + usb_desc_std_ep speak_std_endpoint; + usb_desc_AS_ep speak_as_endpoint; +#endif +} usb_desc_config_set; + +typedef struct +{ + /* main buffer for audio data out transfers and its relative pointers */ + uint8_t isoc_out_buff[TOTAL_OUT_BUF_SIZE * 2U]; + uint8_t* isoc_out_wrptr; + uint8_t* isoc_out_rdptr; + + /* main buffer for audio control requests transfers and its relative variables */ + uint8_t audioctl[64]; + uint8_t audioctl_unit; + uint32_t audioctl_len; + +#ifdef USE_USB_AUDIO_SPEAKER + uint32_t play_flag; +#endif /* USE_USB_AUDIO_SPEAKER */ +} usbd_audio_handler; + +extern usb_desc audio_desc; +extern usb_class_core usbd_audio_cb; + +#endif /* __AUDIO_CORE_H */ diff --git a/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/device/class/audio/Include/audio_out_itf.h b/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/device/class/audio/Include/audio_out_itf.h new file mode 100644 index 0000000000..b143c5fa44 --- /dev/null +++ b/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/device/class/audio/Include/audio_out_itf.h @@ -0,0 +1,76 @@ +/*! + \file audio_out_itf.h + \brief audio OUT (playback) interface header file + + \version 2020-08-01, V3.0.0, firmware for GD32F4xx +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef __AUDIO_OUT_ITF_H +#define __AUDIO_OUT_ITF_H + +#include "usbd_conf.h" + +/* audio commands enumeration */ +typedef enum +{ + AUDIO_CMD_PLAY = 1U, + AUDIO_CMD_PAUSE, + AUDIO_CMD_STOP, +}audio_cmd_enum; + +/* mute commands */ +#define AUDIO_MUTE 0x01U +#define AUDIO_UNMUTE 0x00U + +/* functions return value */ +#define AUDIO_OK 0x00U +#define AUDIO_FAIL 0xFFU + +/* audio machine states */ +#define AUDIO_STATE_INACTIVE 0x00U +#define AUDIO_STATE_ACTIVE 0x01U +#define AUDIO_STATE_PLAYING 0x02U +#define AUDIO_STATE_PAUSED 0x03U +#define AUDIO_STATE_STOPPED 0x04U +#define AUDIO_STATE_ERROR 0x05U + +typedef struct { + uint8_t (*audio_init) (uint32_t audio_freq, uint32_t volume, uint32_t options); + uint8_t (*audio_deinit) (uint32_t options); + uint8_t (*audio_cmd) (uint8_t* pbuf, uint32_t size, uint8_t cmd); + uint8_t (*audio_volume_ctl) (uint8_t vol); + uint8_t (*audio_mute_ctl) (uint8_t cmd); + uint8_t (*audio_periodic_tc) (uint8_t cmd); + uint8_t (*audio_state_get) (void); +} audio_fops_struct; + +extern audio_fops_struct audio_out_fops; + +#endif /* __AUDIO_OUT_ITF_H */ diff --git a/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/device/class/audio/Source/audio_core.c b/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/device/class/audio/Source/audio_core.c new file mode 100644 index 0000000000..6f686aec70 --- /dev/null +++ b/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/device/class/audio/Source/audio_core.c @@ -0,0 +1,777 @@ +/*! + \file audio_core.c + \brief USB audio device class core functions + + \version 2020-08-01, V3.0.0, firmware for GD32F4xx +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "audio_out_itf.h" +#include "audio_core.h" +#include + +#define USBD_VID 0x28E9U +#define USBD_PID 0x9574U + +#ifdef USE_USB_AUDIO_MICPHONE +extern volatile uint32_t count_data; +extern const char wavetestdata[]; +#define LENGTH_DATA (1747 * 32) +#endif + +/* local function prototypes ('static') */ +static uint8_t audio_init (usb_dev *udev, uint8_t config_index); +static uint8_t audio_deinit (usb_dev *udev, uint8_t config_index); +static uint8_t audio_req_handler (usb_dev *udev, usb_req *req); +static uint8_t audio_data_in (usb_dev *udev, uint8_t ep_num); +static uint8_t audio_data_out (usb_dev *udev, uint8_t ep_num); +static uint8_t usbd_audio_sof (usb_dev *udev); + +usb_class_core usbd_audio_cb = { + .init = audio_init, + .deinit = audio_deinit, + .req_proc = audio_req_handler, + .data_in = audio_data_in, + .data_out = audio_data_out, + .SOF = usbd_audio_sof +}; + +#define VOL_MIN 0U /* volume Minimum Value */ +#define VOL_MAX 100U /* volume Maximum Value */ +#define VOL_RES 1U /* volume Resolution */ +#define VOL_0dB 70U /* 0dB is in the middle of VOL_MIN and VOL_MAX */ + +/* note:it should use the c99 standard when compiling the below codes */ +/* USB standard device descriptor */ +__ALIGN_BEGIN const usb_desc_dev audio_dev_desc __ALIGN_END = +{ + .header = + { + .bLength = USB_DEV_DESC_LEN, + .bDescriptorType = USB_DESCTYPE_DEV + }, + .bcdUSB = 0x0200U, + .bDeviceClass = 0x00U, + .bDeviceSubClass = 0x00U, + .bDeviceProtocol = 0x00U, + .bMaxPacketSize0 = USB_FS_EP0_MAX_LEN, + .idVendor = USBD_VID, + .idProduct = USBD_PID, + .bcdDevice = 0x0100U, + .iManufacturer = STR_IDX_MFC, + .iProduct = STR_IDX_PRODUCT, + .iSerialNumber = STR_IDX_SERIAL, + .bNumberConfigurations = USBD_CFG_MAX_NUM +}; + +/* USB device configuration descriptor */ +__ALIGN_BEGIN const usb_desc_config_set audio_config_set __ALIGN_END = +{ + .config = + { + .header = + { + .bLength = sizeof(usb_desc_config), + .bDescriptorType = USB_DESCTYPE_CONFIG + }, + .wTotalLength = AUDIO_CONFIG_DESC_SET_LEN, + .bNumInterfaces = 0x01U + CONFIG_DESC_AS_ITF_COUNT, + .bConfigurationValue = 0x01U, + .iConfiguration = 0x00U, + .bmAttributes = 0xC0U, + .bMaxPower = 0x32U + }, + + .std_itf = + { + .header = + { + .bLength = sizeof(usb_desc_itf), + .bDescriptorType = USB_DESCTYPE_ITF + }, + .bInterfaceNumber = 0x00U, + .bAlternateSetting = 0x00U, + .bNumEndpoints = 0x00U, + .bInterfaceClass = USB_CLASS_AUDIO, + .bInterfaceSubClass = AUDIO_SUBCLASS_CONTROL, + .bInterfaceProtocol = AUDIO_PROTOCOL_UNDEFINED, + .iInterface = 0x00U + }, + + .ac_itf = + { + .header = + { + .bLength = sizeof(usb_desc_AC_itf), + .bDescriptorType = AUDIO_DESCTYPE_INTERFACE + }, + .bDescriptorSubtype = 0x01U, + .bcdADC = 0x0100U, + .wTotalLength = AC_ITF_TOTAL_LEN, + .bInCollection = CONFIG_DESC_AS_ITF_COUNT, +#ifdef USE_USB_AUDIO_MICPHONE + .baInterfaceNr0 = 0x01U, +#endif +#ifdef USE_USB_AUDIO_SPEAKER + .baInterfaceNr1 = 0x02U +#endif + }, + +#ifdef USE_USB_AUDIO_MICPHONE + .mic_in_terminal = + { + .header = + { + .bLength = sizeof(usb_desc_input_terminal), + .bDescriptorType = AUDIO_DESCTYPE_INTERFACE + }, + .bDescriptorSubtype = 0x02U, + .bTerminalID = 0x01U, + .wTerminalType = 0x0201U, + .bAssocTerminal = 0x00U, + .bNrChannels = 0x02U, + .wChannelConfig = 0x0003U, + .iChannelNames = 0x00U, + .iTerminal = 0x00U + }, + + .mic_feature_unit = + { + .header = + { + .bLength = sizeof(usb_desc_mono_feature_unit), + .bDescriptorType = AUDIO_DESCTYPE_INTERFACE + }, + .bDescriptorSubtype = AUDIO_CONTROL_FEATURE_UNIT, + .bUnitID = AUDIO_IN_STREAMING_CTRL, + .bSourceID = 0x01U, + .bControlSize = 0x01U, + .bmaControls0 = AUDIO_CONTROL_MUTE, + .bmaControls1 = AUDIO_CONTROL_VOLUME, + .iFeature = 0x00U + }, + + .mic_out_terminal = + { + .header = + { + .bLength = sizeof(usb_desc_output_terminal), + .bDescriptorType = AUDIO_DESCTYPE_INTERFACE + }, + .bDescriptorSubtype = AUDIO_CONTROL_OUTPUT_TERMINAL, + .bTerminalID = 0x03U, + .wTerminalType = 0x0101U, + .bAssocTerminal = 0x00U, + .bSourceID = 0x02U, + .iTerminal = 0x00U + }, +#endif + +#ifdef USE_USB_AUDIO_SPEAKER + .speak_in_terminal = + { + .header = + { + .bLength = sizeof(usb_desc_input_terminal), + .bDescriptorType = AUDIO_DESCTYPE_INTERFACE + }, + .bDescriptorSubtype = AUDIO_CONTROL_INPUT_TERMINAL, + .bTerminalID = 0x04U, + .wTerminalType = 0x0101U, + .bAssocTerminal = 0x00U, + .bNrChannels = 0x02U, + .wChannelConfig = 0x0003U, + .iChannelNames = 0x00U, + .iTerminal = 0x00U + }, + + .speak_feature_unit = + { + .header = + { + .bLength = sizeof(usb_desc_mono_feature_unit), + .bDescriptorType = AUDIO_DESCTYPE_INTERFACE + }, + .bDescriptorSubtype = AUDIO_CONTROL_FEATURE_UNIT, + .bUnitID = AUDIO_OUT_STREAMING_CTRL, + .bSourceID = 0x04U, + .bControlSize = 0x01U, + .bmaControls0 = AUDIO_CONTROL_MUTE, + .bmaControls1 = AUDIO_CONTROL_VOLUME, + .iFeature = 0x00U + }, + + .speak_out_terminal = + { + .header = + { + .bLength = sizeof(usb_desc_output_terminal), + .bDescriptorType = AUDIO_DESCTYPE_INTERFACE + }, + .bDescriptorSubtype = AUDIO_CONTROL_OUTPUT_TERMINAL, + .bTerminalID = 0x06U, + .wTerminalType = 0x0301U, + .bAssocTerminal = 0x00U, + .bSourceID = 0x05U, + .iTerminal = 0x00U + }, +#endif + +#ifdef USE_USB_AUDIO_MICPHONE + .mic_std_as_itf_zeroband = + { + .header = + { + .bLength = sizeof(usb_desc_itf), + .bDescriptorType = USB_DESCTYPE_ITF + }, + .bInterfaceNumber = 0x01U, + .bAlternateSetting = 0x00U, + .bNumEndpoints = 0x00U, + .bInterfaceClass = USB_CLASS_AUDIO, + .bInterfaceSubClass = AUDIO_SUBCLASS_AUDIOSTREAMING, + .bInterfaceProtocol = AUDIO_PROTOCOL_UNDEFINED, + .iInterface = 0x00U + }, + + .mic_std_as_itf_opera = + { + .header = + { + .bLength = sizeof(usb_desc_itf), + .bDescriptorType = USB_DESCTYPE_ITF + }, + .bInterfaceNumber = 0x01U, + .bAlternateSetting = 0x01U, + .bNumEndpoints = 0x01U, + .bInterfaceClass = USB_CLASS_AUDIO, + .bInterfaceSubClass = AUDIO_SUBCLASS_AUDIOSTREAMING, + .bInterfaceProtocol = AUDIO_PROTOCOL_UNDEFINED, + .iInterface = 0x00U + }, + + .mic_as_itf = + { + .header = + { + .bLength = sizeof(usb_desc_AS_itf), + .bDescriptorType = AUDIO_DESCTYPE_INTERFACE + }, + .bDescriptorSubtype = AUDIO_STREAMING_GENERAL, + .bTerminalLink = 0x03U, + .bDelay = 0x01U, + .wFormatTag = 0x0001U, + }, + + .mic_format_typeI = + { + .header = + { + .bLength = sizeof(usb_desc_format_type), + .bDescriptorType = AUDIO_DESCTYPE_INTERFACE + }, + .bDescriptorSubtype = AUDIO_STREAMING_FORMAT_TYPE, + .bFormatType = AUDIO_FORMAT_TYPE_I, + .bNrChannels = MIC_IN_CHANNEL_NBR, + .bSubFrameSize = 0x02U, + .bBitResolution = MIC_IN_BIT_RESOLUTION, + .bSamFreqType = 0x01U, + .bSamFreq[0] = (uint8_t)USBD_MIC_FREQ, + .bSamFreq[1] = USBD_MIC_FREQ >> 8U, + .bSamFreq[2] = USBD_MIC_FREQ >> 16U + }, + + .mic_std_endpoint = + { + .header = + { + .bLength = sizeof(usb_desc_std_ep), + .bDescriptorType = USB_DESCTYPE_EP + }, + .bEndpointAddress = AUDIO_IN_EP, + .bmAttributes = USB_ENDPOINT_TYPE_ISOCHRONOUS, + .wMaxPacketSize = MIC_IN_PACKET, + .bInterval = 0x01U, + .bRefresh = 0x00U, + .bSynchAddress = 0x00U + }, + + .mic_as_endpoint = + { + .header = + { + .bLength = sizeof(usb_desc_AS_ep), + .bDescriptorType = AUDIO_DESCTYPE_ENDPOINT + }, + .bDescriptorSubtype = AUDIO_ENDPOINT_GENERAL, + .bmAttributes = 0x00U, + .bLockDelayUnits = 0x00U, + .wLockDelay = 0x0000U, + }, +#endif + +#ifdef USE_USB_AUDIO_SPEAKER + .speak_std_as_itf_zeroband = + { + .header = + { + .bLength = sizeof(usb_desc_itf), + .bDescriptorType = USB_DESCTYPE_ITF + }, + .bInterfaceNumber = 0x02U, + .bAlternateSetting = 0x00U, + .bNumEndpoints = 0x00U, + .bInterfaceClass = USB_CLASS_AUDIO, + .bInterfaceSubClass = AUDIO_SUBCLASS_AUDIOSTREAMING, + .bInterfaceProtocol = AUDIO_PROTOCOL_UNDEFINED, + .iInterface = 0x00U + }, + + .speak_std_as_itf_opera = + { + .header = + { + .bLength = sizeof(usb_desc_itf), + .bDescriptorType = USB_DESCTYPE_ITF + }, + .bInterfaceNumber = 0x02U, + .bAlternateSetting = 0x01U, + .bNumEndpoints = 0x01U, + .bInterfaceClass = USB_CLASS_AUDIO, + .bInterfaceSubClass = AUDIO_SUBCLASS_AUDIOSTREAMING, + .bInterfaceProtocol = AUDIO_PROTOCOL_UNDEFINED, + .iInterface = 0x00U + }, + + .speak_as_itf = + { + .header = + { + .bLength = sizeof(usb_desc_AS_itf), + .bDescriptorType = AUDIO_DESCTYPE_INTERFACE + }, + .bDescriptorSubtype = AUDIO_STREAMING_GENERAL, + .bTerminalLink = 0x04U, + .bDelay = 0x01U, + .wFormatTag = 0x0001U, + }, + + .speak_format_typeI = + { + .header = + { + .bLength = sizeof(usb_desc_format_type), + .bDescriptorType = AUDIO_DESCTYPE_INTERFACE + }, + .bDescriptorSubtype = AUDIO_STREAMING_FORMAT_TYPE, + .bFormatType = AUDIO_FORMAT_TYPE_I, + .bNrChannels = SPEAKER_OUT_CHANNEL_NBR, + .bSubFrameSize = 0x02U, + .bBitResolution = SPEAKER_OUT_BIT_RESOLUTION, + .bSamFreqType = 0x01U, + .bSamFreq[0] = (uint8_t)USBD_SPEAKER_FREQ, + .bSamFreq[1] = USBD_SPEAKER_FREQ >> 8U, + .bSamFreq[2] = USBD_SPEAKER_FREQ >> 16U + }, + + .speak_std_endpoint = + { + .header = + { + .bLength = sizeof(usb_desc_std_ep), + .bDescriptorType = USB_DESCTYPE_EP + }, + .bEndpointAddress = AUDIO_OUT_EP, + .bmAttributes = USB_ENDPOINT_TYPE_ISOCHRONOUS, + .wMaxPacketSize = SPEAKER_OUT_PACKET, + .bInterval = 0x01U, + .bRefresh = 0x00U, + .bSynchAddress = 0x00U + }, + + .speak_as_endpoint = + { + .header = + { + .bLength = sizeof(usb_desc_AS_ep), + .bDescriptorType = AUDIO_DESCTYPE_ENDPOINT + }, + .bDescriptorSubtype = AUDIO_ENDPOINT_GENERAL, + .bmAttributes = 0x00U, + .bLockDelayUnits = 0x00U, + .wLockDelay = 0x0000U, + } +#endif +}; + +/* USB language ID descriptor */ +static __ALIGN_BEGIN const usb_desc_LANGID usbd_language_id_desc __ALIGN_END = +{ + .header = + { + .bLength = sizeof(usb_desc_LANGID), + .bDescriptorType = USB_DESCTYPE_STR + }, + + .wLANGID = ENG_LANGID +}; + +/* USB manufacture string */ +static __ALIGN_BEGIN const usb_desc_str manufacturer_string __ALIGN_END = +{ + .header = + { + .bLength = USB_STRING_LEN(10), + .bDescriptorType = USB_DESCTYPE_STR, + }, + .unicode_string = {'G', 'i', 'g', 'a', 'D', 'e', 'v', 'i', 'c', 'e'} +}; + +/* USB product string */ +static __ALIGN_BEGIN const usb_desc_str product_string __ALIGN_END = +{ + .header = + { + .bLength = USB_STRING_LEN(14), + .bDescriptorType = USB_DESCTYPE_STR, + }, + .unicode_string = {'G', 'D', '3', '2', '-', 'U', 'S', 'B', '_', 'A', 'u', 'd', 'i', 'o'} +}; + +/* USBD serial string */ +static __ALIGN_BEGIN usb_desc_str serial_string __ALIGN_END = +{ + .header = + { + .bLength = USB_STRING_LEN(12), + .bDescriptorType = USB_DESCTYPE_STR, + } +}; + +/* USB string descriptor */ +void *const usbd_audio_strings[] = +{ + [STR_IDX_LANGID] = (uint8_t *)&usbd_language_id_desc, + [STR_IDX_MFC] = (uint8_t *)&manufacturer_string, + [STR_IDX_PRODUCT] = (uint8_t *)&product_string, + [STR_IDX_SERIAL] = (uint8_t *)&serial_string +}; + +usb_desc audio_desc = { + .dev_desc = (uint8_t *)&audio_dev_desc, + .config_desc = (uint8_t *)&audio_config_set, + .strings = usbd_audio_strings +}; + +/*! + \brief initialize the AUDIO device + \param[in] udev: pointer to USB device instance + \param[in] config_index: configuration index + \param[out] none + \retval USB device operation status +*/ +static uint8_t audio_init (usb_dev *udev, uint8_t config_index) +{ + static __ALIGN_BEGIN usbd_audio_handler audio_handler __ALIGN_END; + + memset((void *)&audio_handler, 0, sizeof(usbd_audio_handler)); + +#ifdef USE_USB_AUDIO_MICPHONE +{ + usb_desc_std_ep std_ep = audio_config_set.mic_std_endpoint; + + usb_desc_ep ep = { + .header = std_ep.header, + .bEndpointAddress = std_ep.bEndpointAddress, + .bmAttributes = std_ep.bmAttributes, + .wMaxPacketSize = std_ep.wMaxPacketSize, + .bInterval = std_ep.bInterval + }; + + /* initialize TX endpoint */ + usbd_ep_setup (udev, &ep); +} +#endif + +#ifdef USE_USB_AUDIO_SPEAKER +{ + audio_handler.isoc_out_rdptr = audio_handler.isoc_out_buff; + audio_handler.isoc_out_wrptr = audio_handler.isoc_out_buff; + + usb_desc_std_ep std_ep = audio_config_set.speak_std_endpoint; + + usb_desc_ep ep = { + .header = std_ep.header, + .bEndpointAddress = std_ep.bEndpointAddress, + .bmAttributes = std_ep.bmAttributes, + .wMaxPacketSize = std_ep.wMaxPacketSize, + .bInterval = std_ep.bInterval + }; + + /* initialize RX endpoint */ + usbd_ep_setup (udev, &ep); + + /* initialize the audio output hardware layer */ + if (USBD_OK != audio_out_fops.audio_init(USBD_AUDIO_FREQ_16K, DEFAULT_VOLUME, 0U)) { + return USBD_FAIL; + } + + /* prepare OUT endpoint to receive audio data */ + usbd_ep_recev (udev, AUDIO_OUT_EP, (uint8_t*)audio_handler.isoc_out_buff, SPEAKER_OUT_PACKET); +} +#endif + + udev->dev.class_data[USBD_AUDIO_INTERFACE] = (void *)&audio_handler; + + return USBD_OK; +} + +/*! + \brief de-initialize the AUDIO device + \param[in] udev: pointer to USB device instance + \param[in] config_index: configuration index + \param[out] none + \retval USB device operation status +*/ +static uint8_t audio_deinit (usb_dev *udev, uint8_t config_index) +{ +#ifdef USE_USB_AUDIO_MICPHONE + /* deinitialize AUDIO endpoints */ + usbd_ep_clear(udev, AUDIO_IN_EP); +#endif + +#ifdef USE_USB_AUDIO_SPEAKER + /* deinitialize AUDIO endpoints */ + usbd_ep_clear(udev, AUDIO_OUT_EP); + + /* deinitialize the audio output hardware layer */ + if (USBD_OK != audio_out_fops.audio_deinit(0U)) { + return USBD_FAIL; + } +#endif + + return USBD_OK; +} + +/*! + \brief handle the AUDIO class-specific requests + \param[in] udev: pointer to USB device instance + \param[in] req: device class-specific request + \param[out] none + \retval USB device operation status +*/ +static uint8_t audio_req_handler (usb_dev *udev, usb_req *req) +{ + uint8_t status = REQ_NOTSUPP; + + usbd_audio_handler *audio = (usbd_audio_handler *)udev->dev.class_data[USBD_AUDIO_INTERFACE]; + + usb_transc *transc_in = &udev->dev.transc_in[0]; + usb_transc *transc_out = &udev->dev.transc_out[0]; + + switch (req->bRequest) { + case AUDIO_REQ_GET_CUR: + transc_in->xfer_buf = audio->audioctl; + transc_in->remain_len = req->wLength; + + status = REQ_SUPP; + break; + + case AUDIO_REQ_SET_CUR: + if (req->wLength) { + transc_out->xfer_buf = audio->audioctl; + transc_out->remain_len = req->wLength; + + udev->dev.class_core->command = AUDIO_REQ_SET_CUR; + + audio->audioctl_len = req->wLength; + audio->audioctl_unit = BYTE_HIGH(req->wIndex); + + status = REQ_SUPP; + } + break; + + case AUDIO_REQ_GET_MIN: + *((uint16_t *)audio->audioctl) = VOL_MIN; + transc_in->xfer_buf = audio->audioctl; + transc_in->remain_len = req->wLength; + status = REQ_SUPP; + break; + + case AUDIO_REQ_GET_MAX: + *((uint16_t *)audio->audioctl) = VOL_MAX; + transc_in->xfer_buf = audio->audioctl; + transc_in->remain_len = req->wLength; + status = REQ_SUPP; + break; + + case AUDIO_REQ_GET_RES: + *((uint16_t *)audio->audioctl) = VOL_RES; + transc_in->xfer_buf = audio->audioctl; + transc_in->remain_len = req->wLength; + status = REQ_SUPP; + break; + + default: + break; + } + + return status; +} + +/*! + \brief handles the audio IN data stage + \param[in] udev: pointer to USB device instance + \param[in] ep_num: endpoint number + \param[out] none + \retval USB device operation status +*/ +static uint8_t audio_data_in (usb_dev *udev, uint8_t ep_num) +{ +#ifdef USE_USB_AUDIO_MICPHONE + if(count_data < LENGTH_DATA){ + /* Prepare next buffer to be sent: dummy data */ + usbd_ep_send(udev, AUDIO_IN_EP,(uint8_t*)&wavetestdata[count_data],MIC_IN_PACKET); + count_data += MIC_IN_PACKET; + } else { + usbd_ep_send(udev, AUDIO_IN_EP,(uint8_t*)wavetestdata,MIC_IN_PACKET); + count_data = MIC_IN_PACKET; + } +#endif + + return USBD_OK; +} + +/*! + \brief handles the audio OUT data stage + \param[in] udev: pointer to USB device instance + \param[in] ep_num: endpoint number + \param[out] none + \retval USB device operation status +*/ +static uint8_t audio_data_out (usb_dev *udev, uint8_t ep_num) +{ +#ifdef USE_USB_AUDIO_SPEAKER + usbd_audio_handler *audio = (usbd_audio_handler *)udev->dev.class_data[USBD_AUDIO_INTERFACE]; + + if (AUDIO_OUT_EP == ep_num) { + /* increment the Buffer pointer or roll it back when all buffers are full */ + if (audio->isoc_out_wrptr >= (audio->isoc_out_buff + (SPEAKER_OUT_PACKET * OUT_PACKET_NUM))) { + /* all buffers are full: roll back */ + audio->isoc_out_wrptr = audio->isoc_out_buff; + } else { + /* increment the buffer pointer */ + audio->isoc_out_wrptr += SPEAKER_OUT_PACKET; + } + + /* Toggle the frame index */ + udev->dev.transc_out[ep_num].frame_num = + (udev->dev.transc_out[ep_num].frame_num)? 0U:1U; + + /* prepare out endpoint to receive next audio packet */ + usbd_ep_recev (udev, AUDIO_OUT_EP, (uint8_t*)(audio->isoc_out_wrptr), SPEAKER_OUT_PACKET); + + /* trigger the start of streaming only when half buffer is full */ + if ((0U == audio->play_flag) && (audio->isoc_out_wrptr >= (audio->isoc_out_buff + ((SPEAKER_OUT_PACKET * OUT_PACKET_NUM) / 2U)))) { + /* enable start of streaming */ + audio->play_flag = 1U; + } + } else { + /* handles audio control requests data */ + /* check if an audio_control request has been issued */ + if (AUDIO_REQ_SET_CUR == udev->dev.class_core->command) { + /* in this driver, to simplify code, only SET_CUR request is managed */ + + /* check for which addressed unit the audio_control request has been issued */ + if (AUDIO_OUT_STREAMING_CTRL == audio->audioctl_unit) { + /* in this driver, to simplify code, only one unit is manage */ + + /* call the audio interface mute function */ + audio_out_fops.audio_mute_ctl(audio->audioctl[0]); + + /* reset the audioctl_cmd variable to prevent re-entering this function */ + udev->dev.class_core->command = 0U; + + audio->audioctl_len = 0U; + } + } + } +#endif + + return USBD_OK; +} + +/*! + \brief handles the SOF event (data buffer update and synchronization) + \param[in] udev: pointer to USB device instance + \param[out] none + \retval USB device operation status +*/ +static uint8_t usbd_audio_sof (usb_dev *udev) +{ +#ifdef USE_USB_AUDIO_SPEAKER + usbd_audio_handler *audio = (usbd_audio_handler *)udev->dev.class_data[USBD_AUDIO_INTERFACE]; + + /* check if there are available data in stream buffer. + in this function, a single variable (play_flag) is used to avoid software delays. + the play operation must be executed as soon as possible after the SOF detection. */ + if (audio->play_flag) { + /* start playing received packet */ + audio_out_fops.audio_cmd((uint8_t*)(audio->isoc_out_rdptr), /* samples buffer pointer */ + SPEAKER_OUT_PACKET, /* number of samples in Bytes */ + AUDIO_CMD_PLAY); /* command to be processed */ + + /* increment the Buffer pointer or roll it back when all buffers all full */ + if (audio->isoc_out_rdptr >= (audio->isoc_out_buff + (SPEAKER_OUT_PACKET * OUT_PACKET_NUM))) { + /* roll back to the start of buffer */ + audio->isoc_out_rdptr = audio->isoc_out_buff; + } else { + /* increment to the next sub-buffer */ + audio->isoc_out_rdptr += SPEAKER_OUT_PACKET; + } + + /* if all available buffers have been consumed, stop playing */ + if (audio->isoc_out_rdptr == audio->isoc_out_wrptr) { + /* Pause the audio stream */ + audio_out_fops.audio_cmd((uint8_t*)(audio->isoc_out_buff), /* samples buffer pointer */ + SPEAKER_OUT_PACKET, /* number of samples in Bytes */ + AUDIO_CMD_PAUSE); /* command to be processed */ + + /* stop entering play loop */ + audio->play_flag = 0U; + + /* reset buffer pointers */ + audio->isoc_out_rdptr = audio->isoc_out_buff; + audio->isoc_out_wrptr = audio->isoc_out_buff; + } + } +#endif + + return USBD_OK; +} diff --git a/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/device/class/audio/Source/audio_out_itf.c b/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/device/class/audio/Source/audio_out_itf.c new file mode 100644 index 0000000000..fbe56d907b --- /dev/null +++ b/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/device/class/audio/Source/audio_out_itf.c @@ -0,0 +1,228 @@ +/*! + \file audio_out_itf.c + \brief audio OUT (playback) interface functions + + \version 2020-08-01, V3.0.0, firmware for GD32F4xx +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "audio_core.h" +#include "audio_out_itf.h" + +static uint8_t init (uint32_t audiofreq, uint32_t volume, uint32_t options); +static uint8_t deinit (uint32_t options); +static uint8_t audio_cmd (uint8_t* pbuf, uint32_t size, uint8_t cmd); +static uint8_t volume_ctl (uint8_t vol); +static uint8_t mute_ctl (uint8_t cmd); +static uint8_t periodic_tc (uint8_t cmd); +static uint8_t get_state (void); + +audio_fops_struct audio_out_fops = +{ + init, + deinit, + audio_cmd, + volume_ctl, + mute_ctl, + periodic_tc, + get_state +}; + +static uint8_t audio_state = AUDIO_STATE_INACTIVE; + +/*! + \brief initialize and configures all required resources for audio play function + \param[in] audio_freq: statrt_up audio frequency + \param[in] volume: start_up volume to be set + \param[in] options: specific options passed to low layer function + \param[out] none + \retval AUDIO_OK if all operations succeed, AUDIO_FAIL else +*/ +static uint8_t init (uint32_t audio_freq, uint32_t volume, uint32_t options) +{ + static uint32_t initialized = 0U; + + /* check if the low layer has already been initialized */ + if (0U == initialized) { + /* call low layer function */ + if (0U != eval_audio_init(OUTPUT_DEVICE_AUTO, (uint8_t)volume, audio_freq)) { + audio_state = AUDIO_STATE_ERROR; + + return AUDIO_FAIL; + } + + /* set the initialization flag to prevent reinitializing the interface again */ + initialized = 1U; + } + + /* update the audio state machine */ + audio_state = AUDIO_STATE_ACTIVE; + + return AUDIO_OK; +} + +/*! + \brief free all resources used by low layer and stops audio-play function + \param[in] options: specific options passed to low layer function + \param[out] none + \retval AUDIO_OK if all operations succeed, AUDIO_FAIL else +*/ +static uint8_t deinit (uint32_t options) +{ + /* update the audio state machine */ + audio_state = AUDIO_STATE_INACTIVE; + + return AUDIO_OK; +} + +/*! + \brief play, stop, pause or resume current file + \param[in] pbuf: address from which file should be played + \param[in] size: size of the current buffer/file + \param[in] cmd: command to be executed, can be: + \arg AUDIO_CMD_PLAY + \arg AUDIO_CMD_PAUSE + \arg AUDIO_CMD_RESUME + \arg AUDIO_CMD_STOP + \param[out] none + \retval AUDIO_OK if all operations succeed, AUDIO_FAIL else +*/ +static uint8_t audio_cmd (uint8_t* pbuf, uint32_t size, uint8_t cmd) +{ + /* check the current state */ + if ((AUDIO_STATE_INACTIVE == audio_state) || (AUDIO_STATE_ERROR == audio_state)) { + audio_state = AUDIO_STATE_ERROR; + + return AUDIO_FAIL; + } + + switch (cmd) { + /* process the play command */ + case AUDIO_CMD_PLAY: + /* if current state is active or stopped */ + if ((AUDIO_STATE_ACTIVE == audio_state) || \ + (AUDIO_STATE_STOPPED == audio_state) || \ + (AUDIO_STATE_PLAYING == audio_state)) { + audio_mal_play((uint32_t)pbuf, size); + audio_state = AUDIO_STATE_PLAYING; + + return AUDIO_OK; + } else if (AUDIO_STATE_PAUSED == audio_state) { + if (eval_audio_pause_resume(AUDIO_RESUME, (uint32_t)pbuf, (size / 2U))) { + audio_state = AUDIO_STATE_ERROR; + + return AUDIO_FAIL; + } else { + audio_state = AUDIO_STATE_PLAYING; + + return AUDIO_OK; + } + } else { + return AUDIO_FAIL; + } + + /* process the stop command */ + case AUDIO_CMD_STOP: + if (AUDIO_STATE_PLAYING != audio_state) { + /* unsupported command */ + return AUDIO_FAIL; + } else if (eval_audio_stop(CODEC_PDWN_SW)) { + audio_state = AUDIO_STATE_ERROR; + + return AUDIO_FAIL; + } else { + audio_state = AUDIO_STATE_STOPPED; + + return AUDIO_OK; + } + + /* process the pause command */ + case AUDIO_CMD_PAUSE: + if (AUDIO_STATE_PLAYING != audio_state) { + /* unsupported command */ + return AUDIO_FAIL; + } else if (eval_audio_pause_resume(AUDIO_PAUSE, (uint32_t)pbuf, (size / 2U))) { + audio_state = AUDIO_STATE_ERROR; + + return AUDIO_FAIL; + } else { + audio_state = AUDIO_STATE_PAUSED; + + return AUDIO_OK; + } + + /* unsupported command */ + default: + return AUDIO_FAIL; + } +} + +/*! + \brief set the volume level + \param[in] vol: volume level to be set in % (from 0% to 100%) + \param[out] none + \retval AUDIO_OK if all operations succeed, AUDIO_FAIL else +*/ +static uint8_t volume_ctl (uint8_t vol) +{ + return AUDIO_OK; +} + +/*! + \brief mute or unmute the audio current output + \param[in] cmd: can be 0 to unmute, or 1 to mute + \param[out] none + \retval AUDIO_OK if all operations succeed, AUDIO_FAIL else +*/ +static uint8_t mute_ctl (uint8_t cmd) +{ + return AUDIO_OK; +} + +/*! + \brief periodic transfer control + \param[in] cmd: command + \param[out] none + \retval AUDIO_OK if all operations succeed, AUDIO_FAIL else +*/ +static uint8_t periodic_tc (uint8_t cmd) +{ + return AUDIO_OK; +} + +/*! + \brief return the current state of the audio machine + \param[in] none + \param[out] none + \retval AUDIO_OK if all operations succeed, AUDIO_FAIL else +*/ +static uint8_t get_state (void) +{ + return audio_state; +} diff --git a/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/device/class/cdc/Include/cdc_acm_core.h b/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/device/class/cdc/Include/cdc_acm_core.h new file mode 100644 index 0000000000..c1a2bc8f80 --- /dev/null +++ b/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/device/class/cdc/Include/cdc_acm_core.h @@ -0,0 +1,66 @@ +/*! + \file cdc_acm_core.h + \brief the header file of cdc acm driver + + \version 2020-08-01, V3.0.0, firmware for GD32F4xx +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef __CDC_ACM_CORE_H +#define __CDC_ACM_CORE_H + +#include "usbd_enum.h" +#include "usb_cdc.h" + +#define USB_CDC_RX_LEN 64 + +typedef struct { + uint8_t data[USB_CDC_RX_LEN]; + uint8_t cmd[USB_CDC_CMD_PACKET_SIZE]; + + uint8_t packet_sent; + uint8_t packet_receive; + + uint32_t receive_length; + + acm_line line_coding; +} usb_cdc_handler; + +extern usb_desc cdc_desc; +extern usb_class_core cdc_class; + +/* function declarations */ +/* check CDC ACM is ready for data transfer */ +uint8_t cdc_acm_check_ready(usb_dev *udev); +/* send CDC ACM data */ +void cdc_acm_data_send(usb_dev *udev); +/* receive CDC ACM data */ +void cdc_acm_data_receive(usb_dev *udev); + +#endif /* __CDC_ACM_CORE_H */ diff --git a/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/device/class/cdc/Source/cdc_acm_core.c b/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/device/class/cdc/Source/cdc_acm_core.c new file mode 100644 index 0000000000..a950c091c8 --- /dev/null +++ b/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/device/class/cdc/Source/cdc_acm_core.c @@ -0,0 +1,515 @@ +/*! + \file cdc_acm_core.c + \brief CDC ACM driver + + \version 2020-08-01, V3.0.0, firmware for GD32F4xx +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "cdc_acm_core.h" + +#define USBD_VID 0x28E9U +#define USBD_PID 0x018AU + +/* note:it should use the C99 standard when compiling the below codes */ +/* USB standard device descriptor */ +__ALIGN_BEGIN const usb_desc_dev cdc_dev_desc __ALIGN_END = +{ + .header = + { + .bLength = USB_DEV_DESC_LEN, + .bDescriptorType = USB_DESCTYPE_DEV, + }, + .bcdUSB = 0x0200U, + .bDeviceClass = USB_CLASS_CDC, + .bDeviceSubClass = 0x00U, + .bDeviceProtocol = 0x00U, + .bMaxPacketSize0 = USB_FS_EP0_MAX_LEN, + .idVendor = USBD_VID, + .idProduct = USBD_PID, + .bcdDevice = 0x0100U, + .iManufacturer = STR_IDX_MFC, + .iProduct = STR_IDX_PRODUCT, + .iSerialNumber = STR_IDX_SERIAL, + .bNumberConfigurations = USBD_CFG_MAX_NUM, +}; + +/* USB device configuration descriptor */ +__ALIGN_BEGIN const usb_cdc_desc_config_set cdc_config_desc __ALIGN_END = +{ + .config = + { + .header = + { + .bLength = sizeof(usb_desc_config), + .bDescriptorType = USB_DESCTYPE_CONFIG, + }, + .wTotalLength = USB_CDC_ACM_CONFIG_DESC_SIZE, + .bNumInterfaces = 0x02U, + .bConfigurationValue = 0x01U, + .iConfiguration = 0x00U, + .bmAttributes = 0x80U, + .bMaxPower = 0x32U + }, + + .cmd_itf = + { + .header = + { + .bLength = sizeof(usb_desc_itf), + .bDescriptorType = USB_DESCTYPE_ITF + }, + .bInterfaceNumber = 0x00U, + .bAlternateSetting = 0x00U, + .bNumEndpoints = 0x01U, + .bInterfaceClass = USB_CLASS_CDC, + .bInterfaceSubClass = USB_CDC_SUBCLASS_ACM, + .bInterfaceProtocol = USB_CDC_PROTOCOL_AT, + .iInterface = 0x00U + }, + + .cdc_header = + { + .header = + { + .bLength = sizeof(usb_desc_header_func), + .bDescriptorType = USB_DESCTYPE_CS_INTERFACE + }, + .bDescriptorSubtype = 0x00U, + .bcdCDC = 0x0110U + }, + + .cdc_call_managment = + { + .header = + { + .bLength = sizeof(usb_desc_call_managment_func), + .bDescriptorType = USB_DESCTYPE_CS_INTERFACE + }, + .bDescriptorSubtype = 0x01U, + .bmCapabilities = 0x00U, + .bDataInterface = 0x01U + }, + + .cdc_acm = + { + .header = + { + .bLength = sizeof(usb_desc_acm_func), + .bDescriptorType = USB_DESCTYPE_CS_INTERFACE + }, + .bDescriptorSubtype = 0x02U, + .bmCapabilities = 0x02U, + }, + + .cdc_union = + { + .header = + { + .bLength = sizeof(usb_desc_union_func), + .bDescriptorType = USB_DESCTYPE_CS_INTERFACE + }, + .bDescriptorSubtype = 0x06U, + .bMasterInterface = 0x00U, + .bSlaveInterface0 = 0x01U, + }, + + .cdc_cmd_endpoint = + { + .header = + { + .bLength = sizeof(usb_desc_ep), + .bDescriptorType = USB_DESCTYPE_EP, + }, + .bEndpointAddress = CDC_CMD_EP, + .bmAttributes = USB_EP_ATTR_INT, + .wMaxPacketSize = USB_CDC_CMD_PACKET_SIZE, + .bInterval = 0x0AU + }, + + .cdc_data_interface = + { + .header = + { + .bLength = sizeof(usb_desc_itf), + .bDescriptorType = USB_DESCTYPE_ITF, + }, + .bInterfaceNumber = 0x01U, + .bAlternateSetting = 0x00U, + .bNumEndpoints = 0x02U, + .bInterfaceClass = USB_CLASS_DATA, + .bInterfaceSubClass = 0x00U, + .bInterfaceProtocol = USB_CDC_PROTOCOL_NONE, + .iInterface = 0x00U + }, + + .cdc_out_endpoint = + { + .header = + { + .bLength = sizeof(usb_desc_ep), + .bDescriptorType = USB_DESCTYPE_EP, + }, + .bEndpointAddress = CDC_DATA_OUT_EP, + .bmAttributes = USB_EP_ATTR_BULK, + .wMaxPacketSize = USB_CDC_DATA_PACKET_SIZE, + .bInterval = 0x00U + }, + + .cdc_in_endpoint = + { + .header = + { + .bLength = sizeof(usb_desc_ep), + .bDescriptorType = USB_DESCTYPE_EP + }, + .bEndpointAddress = CDC_DATA_IN_EP, + .bmAttributes = USB_EP_ATTR_BULK, + .wMaxPacketSize = USB_CDC_DATA_PACKET_SIZE, + .bInterval = 0x00U + } +}; + +/* USB language ID Descriptor */ +static __ALIGN_BEGIN const usb_desc_LANGID usbd_language_id_desc __ALIGN_END = +{ + .header = + { + .bLength = sizeof(usb_desc_LANGID), + .bDescriptorType = USB_DESCTYPE_STR, + }, + .wLANGID = ENG_LANGID +}; + +/* USB manufacture string */ +static __ALIGN_BEGIN const usb_desc_str manufacturer_string __ALIGN_END = +{ + .header = + { + .bLength = USB_STRING_LEN(10), + .bDescriptorType = USB_DESCTYPE_STR, + }, + .unicode_string = {'G', 'i', 'g', 'a', 'D', 'e', 'v', 'i', 'c', 'e'} +}; + +/* USB product string */ +static __ALIGN_BEGIN const usb_desc_str product_string __ALIGN_END = +{ + .header = + { + .bLength = USB_STRING_LEN(12), + .bDescriptorType = USB_DESCTYPE_STR, + }, + .unicode_string = {'G', 'D', '3', '2', '-', 'C', 'D', 'C', '_', 'A', 'C', 'M'} +}; + +/* USBD serial string */ +static __ALIGN_BEGIN usb_desc_str serial_string __ALIGN_END = +{ + .header = + { + .bLength = USB_STRING_LEN(12), + .bDescriptorType = USB_DESCTYPE_STR, + } +}; + +/* USB string descriptor set */ +void *const usbd_cdc_strings[] = +{ + [STR_IDX_LANGID] = (uint8_t *)&usbd_language_id_desc, + [STR_IDX_MFC] = (uint8_t *)&manufacturer_string, + [STR_IDX_PRODUCT] = (uint8_t *)&product_string, + [STR_IDX_SERIAL] = (uint8_t *)&serial_string +}; + +usb_desc cdc_desc = +{ + .dev_desc = (uint8_t *)&cdc_dev_desc, + .config_desc = (uint8_t *)&cdc_config_desc, + .strings = usbd_cdc_strings +}; + +/* local function prototypes ('static') */ +static uint8_t cdc_acm_init (usb_dev *udev, uint8_t config_index); +static uint8_t cdc_acm_deinit (usb_dev *udev, uint8_t config_index); +static uint8_t cdc_acm_req (usb_dev *udev, usb_req *req); +static uint8_t cdc_acm_in (usb_dev *udev, uint8_t ep_num); +static uint8_t cdc_acm_out (usb_dev *udev, uint8_t ep_num); + +/* USB CDC device class callbacks structure */ +usb_class_core cdc_class = +{ + .command = NO_CMD, + .alter_set = 0U, + + .init = cdc_acm_init, + .deinit = cdc_acm_deinit, + + .req_proc = cdc_acm_req, + + .data_in = cdc_acm_in, + .data_out = cdc_acm_out +}; + +/*! + \brief check CDC ACM is ready for data transfer + \param[in] udev: pointer to USB device instance + \param[out] none + \retval 0 if CDC is ready, 5 else +*/ +uint8_t cdc_acm_check_ready(usb_dev *udev) +{ + if (udev->dev.class_data[CDC_COM_INTERFACE] != NULL) { + usb_cdc_handler *cdc = (usb_cdc_handler *)udev->dev.class_data[CDC_COM_INTERFACE]; + + if ((1U == cdc->packet_receive) && (1U == cdc->packet_sent)) { + return 0U; + } + } + + return 1U; +} + +/*! + \brief send CDC ACM data + \param[in] udev: pointer to USB device instance + \param[out] none + \retval USB device operation status +*/ +void cdc_acm_data_send (usb_dev *udev) +{ + usb_cdc_handler *cdc = (usb_cdc_handler *)udev->dev.class_data[CDC_COM_INTERFACE]; + + if (0U != cdc->receive_length) { + cdc->packet_sent = 0U; + + usbd_ep_send (udev, CDC_DATA_IN_EP, (uint8_t*)(cdc->data), cdc->receive_length); + + cdc->receive_length = 0U; + } +} + +/*! + \brief receive CDC ACM data + \param[in] udev: pointer to USB device instance + \param[out] none + \retval USB device operation status +*/ +void cdc_acm_data_receive (usb_dev *udev) +{ + usb_cdc_handler *cdc = (usb_cdc_handler *)udev->dev.class_data[CDC_COM_INTERFACE]; + + cdc->packet_receive = 0U; + cdc->packet_sent = 0U; + + usbd_ep_recev(udev, CDC_DATA_OUT_EP, (uint8_t*)(cdc->data), USB_CDC_DATA_PACKET_SIZE); +} + +/*! + \brief initialize the CDC ACM device + \param[in] udev: pointer to USB device instance + \param[in] config_index: configuration index + \param[out] none + \retval USB device operation status +*/ +static uint8_t cdc_acm_init (usb_dev *udev, uint8_t config_index) +{ + static __ALIGN_BEGIN usb_cdc_handler cdc_handler __ALIGN_END; + + /* initialize the data TX endpoint */ + usbd_ep_setup (udev, &(cdc_config_desc.cdc_in_endpoint)); + + /* initialize the data RX endpoint */ + usbd_ep_setup (udev, &(cdc_config_desc.cdc_out_endpoint)); + + /* initialize the command TX endpoint */ + usbd_ep_setup (udev, &(cdc_config_desc.cdc_cmd_endpoint)); + + /* initialize CDC handler structure */ + cdc_handler.packet_receive = 1U; + cdc_handler.packet_sent = 1U; + cdc_handler.receive_length = 0U; + + cdc_handler.line_coding = (acm_line){ + .dwDTERate = 115200, + .bCharFormat = 0, + .bParityType = 0, + .bDataBits = 0x08 + }; + + udev->dev.class_data[CDC_COM_INTERFACE] = (void *)&cdc_handler; + + return USBD_OK; +} + +/*! + \brief de-initialize the CDC ACM device + \param[in] udev: pointer to USB device instance + \param[in] config_index: configuration index + \param[out] none + \retval USB device operation status +*/ +static uint8_t cdc_acm_deinit (usb_dev *udev, uint8_t config_index) +{ + /* deinitialize the data TX/RX endpoint */ + usbd_ep_clear (udev, CDC_DATA_IN_EP); + usbd_ep_clear (udev, CDC_DATA_OUT_EP); + + /* deinitialize the command TX endpoint */ + usbd_ep_clear (udev, CDC_CMD_EP); + + return USBD_OK; +} + +/*! + \brief handle the CDC ACM class-specific requests + \param[in] udev: pointer to USB device instance + \param[in] req: device class-specific request + \param[out] none + \retval USB device operation status +*/ +static uint8_t cdc_acm_req (usb_dev *udev, usb_req *req) +{ + usb_cdc_handler *cdc = (usb_cdc_handler *)udev->dev.class_data[CDC_COM_INTERFACE]; + + usb_transc *transc = &udev->dev.transc_in[0]; + + switch (req->bRequest) { + case SEND_ENCAPSULATED_COMMAND: + /* no operation for this driver */ + break; + + case GET_ENCAPSULATED_RESPONSE: + /* no operation for this driver */ + break; + + case SET_COMM_FEATURE: + /* no operation for this driver */ + break; + + case GET_COMM_FEATURE: + /* no operation for this driver */ + break; + + case CLEAR_COMM_FEATURE: + /* no operation for this driver */ + break; + + case SET_LINE_CODING: + /* set the value of the current command to be processed */ + udev->dev.class_core->alter_set = req->bRequest; + + /* enable EP0 prepare to receive command data packet */ + transc->remain_len = req->wLength; + transc->xfer_buf = cdc->cmd; + break; + + case GET_LINE_CODING: + cdc->cmd[0] = (uint8_t)(cdc->line_coding.dwDTERate); + cdc->cmd[1] = (uint8_t)(cdc->line_coding.dwDTERate >> 8); + cdc->cmd[2] = (uint8_t)(cdc->line_coding.dwDTERate >> 16); + cdc->cmd[3] = (uint8_t)(cdc->line_coding.dwDTERate >> 24); + cdc->cmd[4] = cdc->line_coding.bCharFormat; + cdc->cmd[5] = cdc->line_coding.bParityType; + cdc->cmd[6] = cdc->line_coding.bDataBits; + + transc->xfer_buf = cdc->cmd; + transc->remain_len = 7U; + break; + + case SET_CONTROL_LINE_STATE: + /* no operation for this driver */ + break; + + case SEND_BREAK: + /* no operation for this driver */ + break; + + default: + break; + } + + return USBD_OK; +} + +/*! + \brief handle CDC ACM data + \param[in] udev: pointer to USB device instance + \param[in] ep_num: endpoint identifier + \param[out] none + \retval USB device operation status +*/ +static uint8_t cdc_acm_in (usb_dev *udev, uint8_t ep_num) +{ + usb_transc *transc = &udev->dev.transc_in[EP_ID(ep_num)]; + + usb_cdc_handler *cdc = (usb_cdc_handler *)udev->dev.class_data[CDC_COM_INTERFACE]; + + if ((0U == transc->xfer_len % transc->max_len) && (0U != transc->xfer_len)) { + usbd_ep_send (udev, ep_num, NULL, 0U); + } else { + cdc->packet_sent = 1U; + } + + return USBD_OK; +} + +/*! + \brief handle CDC ACM data + \param[in] udev: pointer to USB device instance + \param[in] ep_num: endpoint identifier + \param[out] none + \retval USB device operation status +*/ +static uint8_t cdc_acm_out (usb_dev *udev, uint8_t ep_num) +{ + usb_cdc_handler *cdc = (usb_cdc_handler *)udev->dev.class_data[CDC_COM_INTERFACE]; + + if (0U == ep_num) { + if (udev->dev.class_core->alter_set != NO_CMD) + { + /* process the command data */ + cdc->line_coding.dwDTERate = (uint32_t)((uint32_t)cdc->cmd[0] | + ((uint32_t)cdc->cmd[1] << 8U) | + ((uint32_t)cdc->cmd[2] << 16U) | + ((uint32_t)cdc->cmd[3] << 24U)); + + cdc->line_coding.bCharFormat = cdc->cmd[4]; + cdc->line_coding.bParityType = cdc->cmd[5]; + cdc->line_coding.bDataBits = cdc->cmd[6]; + + udev->dev.class_core->alter_set = NO_CMD; + } + } else { + cdc->packet_receive = 1U; + cdc->receive_length = ((usb_core_driver *)udev)->dev.transc_out[ep_num].xfer_count; + } + + return USBD_OK; +} diff --git a/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/device/class/dfu/Include/dfu_core.h b/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/device/class/dfu/Include/dfu_core.h new file mode 100644 index 0000000000..e62dd75cf2 --- /dev/null +++ b/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/device/class/dfu/Include/dfu_core.h @@ -0,0 +1,176 @@ +/*! + \file dfu_core.h + \brief the header file of USB DFU device class core functions + + \version 2020-08-01, V3.0.0, firmware for GD32F4xx +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef __DFU_CORE_H +#define __DFU_CORE_H + +#include "usbd_enum.h" + +/* DFU class code */ +#define USB_DFU_CLASS 0xFEU + +/* DFU subclass code */ +#define USB_DFU_SUBCLASS_UPGRADE 0x01U + +/* DFU protocol code */ +#define USB_DFU_PROTOCL_RUNTIME 0x01U +#define USB_DFU_PROTOCL_DFU 0x02U + +/* manifestation state */ +#define MANIFEST_COMPLETE 0x00U +#define MANIFEST_IN_PROGRESS 0x01U + +/* DFU attributes code */ +#define USB_DFU_CAN_DOWNLOAD 0x01U +#define USB_DFU_CAN_UPLOAD 0x02U +#define USB_DFU_MANIFEST_TOLERANT 0x04U +#define USB_DFU_WILL_DETACH 0x08U + +/* special commands with download request */ +#define GET_COMMANDS 0x00U +#define SET_ADDRESS_POINTER 0x21U +#define ERASE 0x41U + +/* memory operation command */ +#define CMD_ERASE 0U +#define CMD_WRITE 1U + +#define _BYTE1(x) (uint8_t)((x) & 0xFFU) /*!< addressing cycle 1st byte */ +#define _BYTE2(x) (uint8_t)(((x) & 0xFF00U) >> 8U) /*!< addressing cycle 2nd byte */ +#define _BYTE3(x) (uint8_t)(((x) & 0xFF0000U) >> 16U) /*!< addressing cycle 3rd byte */ + +#define FLASH_ERASE_TIMEOUT 60U +#define FLASH_WRITE_TIMEOUT 80U + +/* bit detach capable = bit 3 in bmAttributes field */ +#define DFU_DETACH_MASK (uint8_t)(0x10U) + +#define USB_SERIAL_STR_LEN 0x06U + +#define USB_DFU_CONFIG_DESC_SIZE 27U + +#define DFU_DESC_TYPE 0x21U + +/* DFU device state defines */ +typedef enum { + STATE_APP_IDLE = 0x00U, + 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 +} dfu_state; + +/* DFU device status defines */ +typedef enum { + STATUS_OK = 0x00U, + STATUS_ERR_TARGET, + STATUS_ERR_FILE, + STATUS_ERR_WRITE, + STATUS_ERR_ERASE, + STATUS_ERR_CHECK_ERASED, + STATUS_ERR_PROG, + STATUS_ERR_VERIFY, + STATUS_ERR_ADDRESS, + STATUS_ERR_NOTDONE, + STATUS_ERR_FIRMWARE, + STATUS_ERR_VENDOR, + STATUS_ERR_USBR, + STATUS_ERR_POR, + STATUS_ERR_UNKNOWN, + STATUS_ERR_STALLEDPKT +} dfu_status; + +/* DFU class-specific requests */ +typedef enum { + DFU_DETACH = 0U, + DFU_DNLOAD, + DFU_UPLOAD, + DFU_GETSTATUS, + DFU_CLRSTATUS, + DFU_GETSTATE, + DFU_ABORT, + DFU_REQ_MAX +} dfu_requests; + +#pragma pack(1) + +/* USB DFU function descriptor structure */ +typedef struct +{ + usb_desc_header header; /*!< descriptor header, including type and size */ + uint8_t bmAttributes; /*!< DFU attributes */ + uint16_t wDetachTimeOut; /*!< time, in milliseconds, that the device will wait after receipt of the DFU_DETACH request. If */ + uint16_t wTransferSize; /*!< maximum number of bytes that the device can accept per control-write transaction */ + uint16_t bcdDFUVersion; /*!< numeric expression identifying the version of the DFU Specification release. */ +} usb_desc_dfu_func; + +#pragma pack() + +/* USB configuration descriptor structure */ +typedef struct +{ + usb_desc_config config; + usb_desc_itf dfu_itf; + usb_desc_dfu_func dfu_func; +} usb_dfu_desc_config_set; + +typedef struct +{ + uint8_t bStatus; + uint8_t bwPollTimeout0; + uint8_t bwPollTimeout1; + uint8_t bwPollTimeout2; + uint8_t bState; + uint8_t iString; + + uint8_t manifest_state; + uint32_t data_len; + uint16_t block_num; + uint32_t base_addr; + + uint8_t buf[TRANSFER_SIZE]; +} usbd_dfu_handler; + +typedef void (*app_func) (void); + +extern usb_desc dfu_desc; +extern usb_class_core dfu_class; + +#endif /* DFU_CORE_H */ diff --git a/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/device/class/dfu/Include/dfu_mal.h b/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/device/class/dfu/Include/dfu_mal.h new file mode 100644 index 0000000000..2198eb2376 --- /dev/null +++ b/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/device/class/dfu/Include/dfu_mal.h @@ -0,0 +1,84 @@ +/*! + \file dfu_mal.h + \brief USB DFU device media access layer header file + + \version 2020-08-01, V3.0.0, firmware for GD32F4xx +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef __DFU_MAL_H +#define __DFU_MAL_H + +#include "usbd_conf.h" + +typedef struct _dfu_mal_prop +{ + const uint8_t* pstr_desc; + + uint8_t (*mal_init) (void); + uint8_t (*mal_deinit) (void); + uint8_t (*mal_erase) (uint32_t addr); + uint8_t (*mal_write) (uint8_t *buf, uint32_t addr, uint32_t len); + uint8_t* (*mal_read) (uint8_t *buf, uint32_t addr, uint32_t len); + uint8_t (*mal_checkaddr) (uint32_t addr); + + const uint32_t erase_timeout; + const uint32_t write_timeout; +} dfu_mal_prop; + +typedef enum +{ + MAL_OK = 0, + MAL_FAIL +} MAL_Status; + +#define _1st_BYTE(x) (uint8_t)((x) & 0xFF) /*!< addressing cycle 1st byte */ +#define _2nd_BYTE(x) (uint8_t)(((x) & 0xFF00) >> 8) /*!< addressing cycle 2nd byte */ +#define _3rd_BYTE(x) (uint8_t)(((x) & 0xFF0000) >> 16) /*!< addressing cycle 3rd byte */ + +#define SET_POLLING_TIMEOUT(x) buffer[0] = _1st_BYTE(x);\ + buffer[1] = _2nd_BYTE(x);\ + buffer[2] = _3rd_BYTE(x); + +/* function declarations */ +/* initialize the memory media on the GD32 */ +uint8_t dfu_mal_init(void); +/* deinitialize the memory media on the GD32 */ +uint8_t dfu_mal_deinit(void); +/* erase a memory sector */ +uint8_t dfu_mal_erase(uint32_t addr); +/* write data to sectors of memory */ +uint8_t dfu_mal_write(uint8_t *buf, uint32_t addr, uint32_t len); +/* read data from sectors of memory */ +uint8_t* dfu_mal_read(uint8_t *buf, uint32_t addr, uint32_t len); +/* get the status of a given memory and store in buffer */ +uint8_t dfu_mal_getstatus(uint32_t addr, uint8_t cmd, uint8_t *buffer); + +#endif /* __DFU_MAL_H */ + diff --git a/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/device/class/dfu/Source/dfu_core.c b/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/device/class/dfu/Source/dfu_core.c new file mode 100644 index 0000000000..676a8cda78 --- /dev/null +++ b/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/device/class/dfu/Source/dfu_core.c @@ -0,0 +1,653 @@ +/*! + \file dfu_core.c + \brief USB DFU device class core functions + + \version 2020-08-01, V3.0.0, firmware for GD32F4xx +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "dfu_core.h" +#include "drv_usb_hw.h" +#include "dfu_mal.h" +#include "flash_if.h" +#include + +#define USBD_VID 0x28E9U +#define USBD_PID 0x0189U + +/* local function prototypes ('static') */ +static uint8_t dfu_init(usb_dev *udev, uint8_t config_index); +static uint8_t dfu_deinit(usb_dev *udev, uint8_t config_index); +static uint8_t dfu_req_handler(usb_dev *udev, usb_req *req); +static uint8_t dfu_data_in(usb_dev *udev, uint8_t ep_num); +static void dfu_detach(usb_dev *udev, usb_req *req); +static void dfu_dnload(usb_dev *udev, usb_req *req); +static void dfu_upload(usb_dev *udev, usb_req *req); +static void dfu_getstatus(usb_dev *udev, usb_req *req); +static void dfu_clrstatus(usb_dev *udev, usb_req *req); +static void dfu_getstate(usb_dev *udev, usb_req *req); +static void dfu_abort(usb_dev *udev, usb_req *req); +static void dfu_mode_leave(usb_dev *udev); +static uint8_t dfu_getstatus_complete (usb_dev *udev); + +static void (*dfu_request_process[])(usb_dev *udev, usb_req *req) = +{ + [DFU_DETACH] = dfu_detach, + [DFU_DNLOAD] = dfu_dnload, + [DFU_UPLOAD] = dfu_upload, + [DFU_GETSTATUS] = dfu_getstatus, + [DFU_CLRSTATUS] = dfu_clrstatus, + [DFU_GETSTATE] = dfu_getstate, + [DFU_ABORT] = dfu_abort +}; + +/* note:it should use the c99 standard when compiling the below codes */ +/* USB standard device descriptor */ +__ALIGN_BEGIN const usb_desc_dev dfu_dev_desc __ALIGN_END = +{ + .header = + { + .bLength = USB_DEV_DESC_LEN, + .bDescriptorType = USB_DESCTYPE_DEV + }, + .bcdUSB = 0x0200U, + .bDeviceClass = 0x00U, + .bDeviceSubClass = 0x00U, + .bDeviceProtocol = 0x00U, + .bMaxPacketSize0 = USB_FS_EP0_MAX_LEN, + .idVendor = USBD_VID, + .idProduct = USBD_PID, + .bcdDevice = 0x0100U, + .iManufacturer = STR_IDX_MFC, + .iProduct = STR_IDX_PRODUCT, + .iSerialNumber = STR_IDX_SERIAL, + .bNumberConfigurations = USBD_CFG_MAX_NUM +}; + +/* USB device configuration descriptor */ +__ALIGN_BEGIN const usb_dfu_desc_config_set dfu_config_desc __ALIGN_END = +{ + .config = + { + .header = + { + .bLength = sizeof(usb_desc_config), + .bDescriptorType = USB_DESCTYPE_CONFIG + }, + .wTotalLength = USB_DFU_CONFIG_DESC_SIZE, + .bNumInterfaces = 0x01U, + .bConfigurationValue = 0x01U, + .iConfiguration = 0x00U, + .bmAttributes = 0x80U, + .bMaxPower = 0x32U + }, + + .dfu_itf = + { + .header = + { + .bLength = sizeof(usb_desc_itf), + .bDescriptorType = USB_DESCTYPE_ITF + }, + .bInterfaceNumber = 0x00U, + .bAlternateSetting = 0x00U, + .bNumEndpoints = 0x00U, + .bInterfaceClass = USB_DFU_CLASS, + .bInterfaceSubClass = USB_DFU_SUBCLASS_UPGRADE, + .bInterfaceProtocol = USB_DFU_PROTOCL_DFU, + .iInterface = 0x05U + }, + + .dfu_func = + { + .header = + { + .bLength = sizeof(usb_desc_dfu_func), + .bDescriptorType = DFU_DESC_TYPE + }, + .bmAttributes = USB_DFU_CAN_DOWNLOAD | USB_DFU_CAN_UPLOAD | USB_DFU_WILL_DETACH, + .wDetachTimeOut = 0x00FFU, + .wTransferSize = TRANSFER_SIZE, + .bcdDFUVersion = 0x011AU, + }, +}; + +/* USB language ID Descriptor */ +static __ALIGN_BEGIN const usb_desc_LANGID usbd_language_id_desc __ALIGN_END = +{ + .header = { + .bLength = sizeof(usb_desc_LANGID), + .bDescriptorType = USB_DESCTYPE_STR + }, + .wLANGID = ENG_LANGID +}; + +/* USB manufacture string */ +static __ALIGN_BEGIN const usb_desc_str manufacturer_string __ALIGN_END = +{ + .header = + { + .bLength = USB_STRING_LEN(10U), + .bDescriptorType = USB_DESCTYPE_STR, + }, + .unicode_string = {'G', 'i', 'g', 'a', 'D', 'e', 'v', 'i', 'c', 'e'} +}; + +/* USB product string */ +static __ALIGN_BEGIN const usb_desc_str product_string __ALIGN_END = +{ + .header = + { + .bLength = USB_STRING_LEN(12U), + .bDescriptorType = USB_DESCTYPE_STR, + }, + .unicode_string = {'G', 'D', '3', '2', '-', 'U', 'S', 'B', '_', 'D', 'F', 'U'} +}; + +/* USBD serial string */ +static __ALIGN_BEGIN usb_desc_str serial_string __ALIGN_END = +{ + .header = + { + .bLength = USB_STRING_LEN(2U), + .bDescriptorType = USB_DESCTYPE_STR, + } +}; + +/* USB configure string */ +static __ALIGN_BEGIN const usb_desc_str config_string __ALIGN_END = +{ + .header = + { + .bLength = USB_STRING_LEN(15U), + .bDescriptorType = USB_DESCTYPE_STR, + }, + .unicode_string = {'G', 'D', '3', '2', ' ', 'U', 'S', 'B', ' ', 'C', 'O', 'N', 'F', 'I', 'G'} +}; + +static __ALIGN_BEGIN const usb_desc_str interface_string __ALIGN_END = +{ + .header = + { + .bLength = USB_STRING_LEN(44U), + .bDescriptorType = USB_DESCTYPE_STR, + }, + .unicode_string = {'@', 'I', 'n', 't', 'e', 'r', 'n', 'a', 'l', 'F', 'l', 'a', 's', 'h', ' ', '/', '0', 'x', '0', '8', '0', '0', + '0', '0', '0', '0', '/', '1', '6', '*', '0', '0', '1', 'K', 'a', ',', '4', '8', '*', '0', '0', '1', 'K', 'g'} +}; + +void *const usbd_dfu_strings[] = +{ + [STR_IDX_LANGID] = (uint8_t *)&usbd_language_id_desc, + [STR_IDX_MFC] = (uint8_t *)&manufacturer_string, + [STR_IDX_PRODUCT] = (uint8_t *)&product_string, + [STR_IDX_SERIAL] = (uint8_t *)&serial_string, + [STR_IDX_CONFIG] = (uint8_t *)&config_string, + [STR_IDX_ITF] = (uint8_t *)&interface_string +}; + +usb_desc dfu_desc = { + .dev_desc = (uint8_t *)&dfu_dev_desc, + .config_desc = (uint8_t *)&dfu_config_desc, + .strings = usbd_dfu_strings +}; + +usb_class_core dfu_class = { + .init = dfu_init, + .deinit = dfu_deinit, + .req_proc = dfu_req_handler, + .data_in = dfu_data_in +}; + +/*! + \brief initialize the DFU device + \param[in] udev: pointer to USB device instance + \param[in] config_index: configuration index + \param[out] none + \retval USB device operation status +*/ +static uint8_t dfu_init (usb_dev *udev, uint8_t config_index) +{ + static __ALIGN_BEGIN usbd_dfu_handler dfu_handler __ALIGN_END; + + /* unlock the internal flash */ + dfu_mal_init(); + + memset((void *)&dfu_handler, 0, sizeof(usbd_dfu_handler)); + + dfu_handler.base_addr = APP_LOADED_ADDR; + dfu_handler.manifest_state = MANIFEST_COMPLETE; + dfu_handler.bState = STATE_DFU_IDLE; + dfu_handler.bStatus = STATUS_OK; + + udev->dev.class_data[USBD_DFU_INTERFACE] = (void *)&dfu_handler; + + return USBD_OK; +} + +/*! + \brief de-initialize the DFU device + \param[in] udev: pointer to USB device instance + \param[in] config_index: configuration index + \param[out] none + \retval USB device operation status +*/ +static uint8_t dfu_deinit (usb_dev *udev, uint8_t config_index) +{ + usbd_dfu_handler *dfu = (usbd_dfu_handler *)udev->dev.class_data[USBD_DFU_INTERFACE]; + + /* restore device default state */ + memset(udev->dev.class_data[USBD_DFU_INTERFACE], 0, sizeof(usbd_dfu_handler)); + + dfu->bState = STATE_DFU_IDLE; + dfu->bStatus = STATUS_OK; + + /* lock the internal flash */ + dfu_mal_deinit(); + + return USBD_OK; +} + +/*! + \brief handle the DFU class-specific requests + \param[in] udev: pointer to USB device instance + \param[in] req: device class-specific request + \param[out] none + \retval USB device operation status +*/ +static uint8_t dfu_req_handler (usb_dev *udev, usb_req *req) +{ + if (req->bRequest < DFU_REQ_MAX) { + dfu_request_process[req->bRequest](udev, req); + } else { + return USBD_FAIL; + } + + return USBD_OK; +} + +/*! + \brief handle data Stage + \param[in] udev: pointer to USB device instance + \param[in] ep_num: the endpoint number + \param[out] none + \retval USB device operation status +*/ +static uint8_t dfu_data_in (usb_dev *udev, uint8_t ep_num) +{ + if (0U == ep_num) { + dfu_getstatus_complete(udev); + } + + return USBD_OK; +} + +/*! + \brief leave DFU mode and reset device to jump to user loaded code + \param[in] udev: pointer to USB device instance + \param[out] none + \retval none +*/ +static void dfu_mode_leave (usb_dev *udev) +{ + usbd_dfu_handler *dfu = (usbd_dfu_handler *)udev->dev.class_data[USBD_DFU_INTERFACE]; + + dfu->manifest_state = MANIFEST_COMPLETE; + + if (dfu_config_desc.dfu_func.bmAttributes & 0x04U) { + dfu->bState = STATE_DFU_MANIFEST_SYNC; + } else { + dfu->bState = STATE_DFU_MANIFEST_WAIT_RESET; + + /* lock the internal flash */ + dfu_mal_deinit(); + + /* generate system reset to allow jumping to the user code */ + NVIC_SystemReset(); + } +} + +/*! + \brief handle data IN stage in control endpoint 0 + \param[in] udev: pointer to USB device instance + \param[out] none + \retval USB device operation status + */ +static uint8_t dfu_getstatus_complete (usb_dev *udev) +{ + uint32_t addr; + + usbd_dfu_handler *dfu = (usbd_dfu_handler *)udev->dev.class_data[USBD_DFU_INTERFACE]; + + if (STATE_DFU_DNBUSY == dfu->bState) { + /* decode the special command */ + if (0U == dfu->block_num) { + if (1U == dfu->data_len){ + if (GET_COMMANDS == dfu->buf[0]) { + /* no operation */ + } + } else if (5U == dfu->data_len) { + if (SET_ADDRESS_POINTER == dfu->buf[0]) { + /* set flash operation address */ + dfu->base_addr = *(uint32_t *)(dfu->buf + 1U); + } else if (ERASE == dfu->buf[0]) { + dfu->base_addr = *(uint32_t *)(dfu->buf + 1U); + + dfu_mal_erase(dfu->base_addr); + } else { + /* no operation */ + } + } else { + /* no operation */ + } + } else if (dfu->block_num > 1U) { /* regular download command */ + /* decode the required address */ + addr = (dfu->block_num - 2U) * TRANSFER_SIZE + dfu->base_addr; + + dfu_mal_write (dfu->buf, addr, dfu->data_len); + + dfu->block_num = 0U; + } else { + /* no operation */ + } + + dfu->data_len = 0U; + + /* update the device state and poll timeout */ + dfu->bState = STATE_DFU_DNLOAD_SYNC; + + return USBD_OK; + } else if (dfu->bState == STATE_DFU_MANIFEST) { /* manifestation in progress */ + /* start leaving DFU mode */ + dfu_mode_leave(udev); + } else { + /* no operation */ + } + + return USBD_OK; +} + +/*! + \brief handle the DFU_DETACH request + \param[in] udev: pointer to USB device instance + \param[in] req: DFU class request + \param[out] none + \retval none. +*/ +static void dfu_detach(usb_dev *udev, usb_req *req) +{ + usbd_dfu_handler *dfu = (usbd_dfu_handler *)udev->dev.class_data[USBD_DFU_INTERFACE]; + + switch (dfu->bState) { + case STATE_DFU_IDLE: + case STATE_DFU_DNLOAD_SYNC: + case STATE_DFU_DNLOAD_IDLE: + case STATE_DFU_MANIFEST_SYNC: + case STATE_DFU_UPLOAD_IDLE: + dfu->bStatus = STATUS_OK; + dfu->bState = STATE_DFU_IDLE; + dfu->iString = 0U; /* iString */ + + dfu->block_num = 0U; + dfu->data_len = 0U; + break; + + default: + break; + } + + /* check the detach capability in the DFU functional descriptor */ + if (dfu_config_desc.dfu_func.wDetachTimeOut & DFU_DETACH_MASK) { + usbd_disconnect (udev); + + usbd_connect (udev); + } else { + /* wait for the period of time specified in detach request */ + usb_mdelay (4U); + } +} + +/*! + \brief handle the DFU_DNLOAD request + \param[in] udev: pointer to USB device instance + \param[in] req: DFU class request + \param[out] none + \retval none +*/ +static void dfu_dnload(usb_dev *udev, usb_req *req) +{ + usb_transc *transc = &udev->dev.transc_out[0]; + usbd_dfu_handler *dfu = (usbd_dfu_handler *)udev->dev.class_data[USBD_DFU_INTERFACE]; + + switch (dfu->bState) { + case STATE_DFU_IDLE: + case STATE_DFU_DNLOAD_IDLE: + if (req->wLength > 0U) { + /* update the global length and block number */ + dfu->block_num = req->wValue; + dfu->data_len = req->wLength; + + dfu->bState = STATE_DFU_DNLOAD_SYNC; + + transc->remain_len = dfu->data_len; + transc->xfer_buf = dfu->buf; + } else { + dfu->manifest_state = MANIFEST_IN_PROGRESS; + dfu->bState = STATE_DFU_MANIFEST_SYNC; + } + break; + + default: + break; + } +} + +/*! + \brief handles the DFU UPLOAD request. + \param[in] udev: pointer to USB device instance + \param[in] req: DFU class request + \param[out] none + \retval none +*/ +static void dfu_upload (usb_dev *udev, usb_req *req) +{ + uint8_t *phy_addr = NULL; + uint32_t addr = 0U; + usbd_dfu_handler *dfu = (usbd_dfu_handler *)udev->dev.class_data[USBD_DFU_INTERFACE]; + + usb_transc *transc = &udev->dev.transc_in[0]; + + if(req->wLength <= 0U) { + dfu->bState = STATE_DFU_IDLE; + return; + } + + switch (dfu->bState) { + case STATE_DFU_IDLE: + case STATE_DFU_UPLOAD_IDLE: + /* update the global length and block number */ + dfu->block_num = req->wValue; + dfu->data_len = req->wLength; + + /* DFU get command */ + if (0U == dfu->block_num) { + /* update the state machine */ + dfu->bState = (dfu->data_len > 3U) ? STATE_DFU_IDLE : STATE_DFU_UPLOAD_IDLE; + + /* store the values of all supported commands */ + dfu->buf[0] = GET_COMMANDS; + dfu->buf[1] = SET_ADDRESS_POINTER; + dfu->buf[2] = ERASE; + + /* send the status data over EP0 */ + transc->xfer_buf = &(dfu->buf[0]); + transc->remain_len = 3U; + } else if (dfu->block_num > 1U) { + dfu->bState = STATE_DFU_UPLOAD_IDLE; + + /* change is accelerated */ + addr = (dfu->block_num - 2U) * TRANSFER_SIZE + dfu->base_addr; + + /* return the physical address where data are stored */ + phy_addr = dfu_mal_read (dfu->buf, addr, dfu->data_len); + + /* send the status data over EP0 */ + transc->xfer_buf = phy_addr; + transc->remain_len = dfu->data_len; + } else { + dfu->bState = STATUS_ERR_STALLEDPKT; + } + break; + + default: + dfu->data_len = 0U; + dfu->block_num = 0U; + break; + } +} + +/*! + \brief handle the DFU_GETSTATUS request + \param[in] udev: pointer to USB device instance + \param[in] req: DFU class request + \param[out] none + \retval none +*/ +static void dfu_getstatus (usb_dev *udev, usb_req *req) +{ + usbd_dfu_handler *dfu = (usbd_dfu_handler *)udev->dev.class_data[USBD_DFU_INTERFACE]; + + usb_transc *transc = &udev->dev.transc_in[0]; + + switch (dfu->bState) { + case STATE_DFU_DNLOAD_SYNC: + if (0U != dfu->data_len) { + dfu->bState = STATE_DFU_DNBUSY; + + if (0U == dfu->block_num) { + if (ERASE == dfu->buf[0]) { + dfu_mal_getstatus (dfu->base_addr, CMD_ERASE, (uint8_t *)&dfu->bwPollTimeout0); + } else { + dfu_mal_getstatus (dfu->base_addr, CMD_WRITE, (uint8_t *)&dfu->bwPollTimeout0); + } + } + } else { + dfu->bState = STATE_DFU_DNLOAD_IDLE; + } + break; + + case STATE_DFU_MANIFEST_SYNC: + if (MANIFEST_IN_PROGRESS == dfu->manifest_state) { + dfu->bState = STATE_DFU_MANIFEST; + dfu->bwPollTimeout0 = 1U; + } else if ((MANIFEST_COMPLETE == dfu->manifest_state) && \ + (dfu_config_desc.dfu_func.bmAttributes & 0x04U)){ + dfu->bState = STATE_DFU_IDLE; + dfu->bwPollTimeout0 = 0U; + } else { + /* no operation */ + } + break; + + default: + break; + } + + /* send the status data of DFU interface to host over EP0 */ + transc->xfer_buf = (uint8_t *)&(dfu->bStatus); + transc->remain_len = 6U; +} + +/*! + \brief handle the DFU_CLRSTATUS request + \param udev: pointer to USB device instance + \param[out] none + \retval none +*/ +static void dfu_clrstatus (usb_dev *udev, usb_req *req) +{ + usbd_dfu_handler *dfu = (usbd_dfu_handler *)udev->dev.class_data[USBD_DFU_INTERFACE]; + + if (STATE_DFU_ERROR == dfu->bState) { + dfu->bStatus = STATUS_OK; + dfu->bState = STATE_DFU_IDLE; + } else { + /* state error */ + dfu->bStatus = STATUS_ERR_UNKNOWN; + dfu->bState = STATE_DFU_ERROR; + } + + dfu->iString = 0U; /* iString: index = 0 */ +} + +/*! + \brief handle the DFU_GETSTATE request + \param[in] udev: pointer to USB device instance + \param[out] none + \retval none +*/ +static void dfu_getstate (usb_dev *udev, usb_req *req) +{ + usbd_dfu_handler *dfu = (usbd_dfu_handler *)udev->dev.class_data[USBD_DFU_INTERFACE]; + + usb_transc *transc = &udev->dev.transc_in[0]; + + /* send the current state of the DFU interface to host */ + transc->xfer_buf = &(dfu->bState); + transc->remain_len = 1U; +} + +/*! + \brief handle the DFU_ABORT request + \param[in] udev: pointer to USB device instance + \param[out] none + \retval none +*/ +static void dfu_abort (usb_dev *udev, usb_req *req) +{ + usbd_dfu_handler *dfu = (usbd_dfu_handler *)udev->dev.class_data[USBD_DFU_INTERFACE]; + + switch (dfu->bState){ + case STATE_DFU_IDLE: + case STATE_DFU_DNLOAD_SYNC: + case STATE_DFU_DNLOAD_IDLE: + case STATE_DFU_MANIFEST_SYNC: + case STATE_DFU_UPLOAD_IDLE: + dfu->bStatus = STATUS_OK; + dfu->bState = STATE_DFU_IDLE; + dfu->iString = 0U; /* iString: index = 0 */ + + dfu->block_num = 0U; + dfu->data_len = 0U; + break; + + default: + break; + } +} diff --git a/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/device/class/dfu/Source/dfu_mal.c b/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/device/class/dfu/Source/dfu_mal.c new file mode 100644 index 0000000000..11c161c8f1 --- /dev/null +++ b/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/device/class/dfu/Source/dfu_mal.c @@ -0,0 +1,233 @@ +/*! + \file dfu_mal.c + \brief USB DFU device media access layer functions + + \version 2020-08-01, V3.0.0, firmware for GD32F4xx +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "dfu_mal.h" +#include "flash_if.h" +#include "drv_usb_hw.h" +#include "usbd_transc.h" + +extern usb_core_driver usb_dfu_dev; + +extern struct { + uint8_t buf[TRANSFER_SIZE]; + uint16_t data_len; + uint16_t block_num; + uint32_t base_addr; +} prog; + +dfu_mal_prop* tMALTab[MAX_USED_MEMORY_MEDIA] = { + &DFU_Flash_cb +}; + +/* The list of memory interface string descriptor pointers. This list + can be updated whenever a memory has to be added or removed */ +const uint8_t* USBD_DFU_StringDesc[MAX_USED_MEMORY_MEDIA] = +{ + (const uint8_t *)FLASH_IF_STRING +}; + +static uint8_t dfu_mal_checkaddr (uint32_t addr); + +/*! + \brief initialize the memory media on the GD32 + \param[in] none + \param[out] none + \retval MAL_OK +*/ +uint8_t dfu_mal_init (void) +{ + uint32_t mem_index = 0U; + + /* initialize all supported memory medias */ + for (mem_index = 0U; mem_index < MAX_USED_MEMORY_MEDIA; mem_index++) { + /* check if the memory media exists */ + if (NULL != tMALTab[mem_index]->mal_init) { + tMALTab[mem_index]->mal_init(); + } + } + + return MAL_OK; +} + +/*! + \brief deinitialize the memory media on the GD32 + \param[in] none + \param[out] none + \retval MAL_OK +*/ +uint8_t dfu_mal_deinit (void) +{ + uint32_t mem_index = 0U; + + /* deinitialize all supported memory medias */ + for (mem_index = 0U; mem_index < MAX_USED_MEMORY_MEDIA; mem_index++) { + /* check if the memory media exists */ + if (NULL != tMALTab[mem_index]->mal_deinit) { + tMALTab[mem_index]->mal_deinit(); + } + } + + return MAL_OK; +} + +/*! + \brief erase a memory sector + \param[in] addr: memory sector address/code + \param[out] none + \retval MAL_OK +*/ +uint8_t dfu_mal_erase (uint32_t addr) +{ + uint32_t mem_index = dfu_mal_checkaddr(addr); + + /* check if the address is in protected area */ + if (IS_PROTECTED_AREA(addr)) { + return MAL_FAIL; + } + + if (mem_index < MAX_USED_MEMORY_MEDIA) { + /* check if the operation is supported */ + if (NULL != tMALTab[mem_index]->mal_erase) { + return tMALTab[mem_index]->mal_erase(addr); + } else { + return MAL_FAIL; + } + } else { + return MAL_FAIL; + } +} + +/*! + \brief write data to sectors of memory + \param[in] buf: the data buffer to be write + \param[in] addr: memory sector address/code + \param[in] len: data length + \param[out] none + \retval MAL_OK +*/ +uint8_t dfu_mal_write (uint8_t *buf, uint32_t addr, uint32_t len) +{ + uint32_t mem_index = dfu_mal_checkaddr(addr); + + /* check if the address is in protected area */ + if (IS_PROTECTED_AREA(addr)) { + return MAL_FAIL; + } + + if (mem_index < MAX_USED_MEMORY_MEDIA) { + /* check if the operation is supported */ + if (NULL != tMALTab[mem_index]->mal_write) { + return tMALTab[mem_index]->mal_write(buf, addr, len); + } else { + return MAL_FAIL; + } + } else { + return MAL_FAIL; + } +} + +/*! + \brief read data from sectors of memory + \param[in] buf: the data buffer to be write + \param[in] addr: memory sector address/code + \param[in] len: data length + \param[out] none + \retval pointer to buffer +*/ +uint8_t* dfu_mal_read (uint8_t *buf, uint32_t addr, uint32_t len) +{ + uint32_t mem_index = 0U; + + if (OB_RDPT != addr) { + mem_index = dfu_mal_checkaddr(addr); + } + + if (mem_index < MAX_USED_MEMORY_MEDIA) { + /* check if the operation is supported */ + if (NULL != tMALTab[mem_index]->mal_read) { + return tMALTab[mem_index]->mal_read(buf, addr, len); + } else { + return buf; + } + } else { + return buf; + } +} + +/*! + \brief get the status of a given memory and store in buffer + \param[in] addr: memory sector address/code + \param[in] cmd: 0 for erase and 1 for write + \param[in] buffer: pointer to the buffer where the status data will be stored + \param[out] none + \retval MAL_OK if all operations are OK, MAL_FAIL else +*/ +uint8_t dfu_mal_getstatus (uint32_t addr, uint8_t cmd, uint8_t *buffer) +{ + uint32_t mem_index = dfu_mal_checkaddr(addr); + + if (mem_index < MAX_USED_MEMORY_MEDIA) { + if (cmd & 0x01U) { + SET_POLLING_TIMEOUT(tMALTab[mem_index]->write_timeout); + } else { + SET_POLLING_TIMEOUT(tMALTab[mem_index]->erase_timeout); + } + + return MAL_OK; + } else { + return MAL_FAIL; + } +} + +/*! + \brief check the address is supported + \param[in] addr: memory sector address/code + \param[out] none + \retval index of the addressed memory +*/ +static uint8_t dfu_mal_checkaddr (uint32_t addr) +{ + uint8_t mem_index = 0U; + + /* check with all supported memories */ + for (mem_index = 0U; mem_index < MAX_USED_MEMORY_MEDIA; mem_index++) { + /* if the check address is supported, return the memory index */ + if (MAL_OK == tMALTab[mem_index]->mal_checkaddr(addr)) { + return mem_index; + } + } + + /* if there is no memory found, return MAX_USED_MEMORY_MEDIA */ + return (MAX_USED_MEMORY_MEDIA); +} diff --git a/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/device/class/hid/Include/custom_hid_core.h b/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/device/class/hid/Include/custom_hid_core.h new file mode 100644 index 0000000000..f320f77e40 --- /dev/null +++ b/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/device/class/hid/Include/custom_hid_core.h @@ -0,0 +1,69 @@ +/*! + \file custom_hid_core.h + \brief definitions for HID core + + \version 2020-08-01, V3.0.0, firmware for GD32F4xx +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef __CUSTOM_HID_CORE_H +#define __CUSTOM_HID_CORE_H + +#include "usbd_enum.h" +#include "usb_hid.h" + +#define DESC_LEN_REPORT 96U +#define DESC_LEN_CONFIG 41U + +#define NO_CMD 0xFFU + +#define MAX_PERIPH_NUM 4U + +typedef struct { + uint8_t data[2]; + + uint8_t reportID; + uint8_t idlestate; + uint8_t protocol; +} custom_hid_handler; + +typedef struct { + void (*periph_config[MAX_PERIPH_NUM])(void); +} hid_fop_handler; + +extern usb_desc custom_hid_desc; +extern usb_class_core usbd_custom_hid_cb; + +/* function declarations */ +/* register HID interface operation functions */ +uint8_t custom_hid_itfop_register (usb_dev *udev, hid_fop_handler *hid_fop); +/* send custom HID report */ +uint8_t custom_hid_report_send (usb_dev *udev, uint8_t *report, uint32_t len); + +#endif /* __CUSTOM_HID_CORE_H */ diff --git a/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/device/class/hid/Include/standard_hid_core.h b/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/device/class/hid/Include/standard_hid_core.h new file mode 100644 index 0000000000..773470d67f --- /dev/null +++ b/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/device/class/hid/Include/standard_hid_core.h @@ -0,0 +1,68 @@ +/*! + \file standard_hid_core.h + \brief definitions for HID core + + \version 2020-08-01, V3.0.0, firmware for GD32F4xx +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef __STANDARD_HID_CORE_H +#define __STANDARD_HID_CORE_H + +#include "usbd_enum.h" +#include "usb_hid.h" + +#define USB_HID_CONFIG_DESC_LEN 0x22U +#define USB_HID_REPORT_DESC_LEN 0x29U + +#define NO_CMD 0xFFU + +typedef struct { + uint32_t protocol; + uint32_t idle_state; + + uint8_t data[HID_IN_PACKET]; + __IO uint8_t prev_transfer_complete; +} standard_hid_handler; + +typedef struct { + void (*hid_itf_config) (void); + void (*hid_itf_data_process) (usb_dev *udev); +} hid_fop_handler; + +extern usb_desc hid_desc; +extern usb_class_core usbd_hid_cb; + +/* function declarations */ +/* register HID interface operation functions */ +uint8_t hid_itfop_register (usb_dev *udev, hid_fop_handler *hid_fop); +/* send keyboard report */ +uint8_t hid_report_send (usb_dev *udev, uint8_t *report, uint32_t len); + +#endif /* __STANDARD_HID_CORE_H */ diff --git a/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/device/class/hid/Source/custom_hid_core.c b/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/device/class/hid/Source/custom_hid_core.c new file mode 100644 index 0000000000..fd4c9ccca7 --- /dev/null +++ b/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/device/class/hid/Source/custom_hid_core.c @@ -0,0 +1,486 @@ +/*! + \file custom_hid_core.c + \brief custom HID class driver + + \version 2020-08-01, V3.0.0, firmware for GD32F4xx +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "custom_hid_core.h" +#include "usbd_enum.h" +#include + +#define USBD_VID 0x28E9U +#define USBD_PID 0x028AU + +/* Note:it should use the C99 standard when compiling the below codes */ +/* USB standard device descriptor */ +__ALIGN_BEGIN const usb_desc_dev custom_hid_dev_desc __ALIGN_END = +{ + .header = + { + .bLength = USB_DEV_DESC_LEN, + .bDescriptorType = USB_DESCTYPE_DEV, + }, + .bcdUSB = 0x0200U, + .bDeviceClass = 0x00U, + .bDeviceSubClass = 0x00U, + .bDeviceProtocol = 0x00U, + .bMaxPacketSize0 = USB_FS_EP0_MAX_LEN, + .idVendor = USBD_VID, + .idProduct = USBD_PID, + .bcdDevice = 0x0100U, + .iManufacturer = STR_IDX_MFC, + .iProduct = STR_IDX_PRODUCT, + .iSerialNumber = STR_IDX_SERIAL, + .bNumberConfigurations = USBD_CFG_MAX_NUM, +}; + +/* USB device configuration descriptor */ +__ALIGN_BEGIN const usb_hid_desc_config_set custom_hid_config_desc __ALIGN_END = +{ + .config = + { + .header = + { + .bLength = sizeof(usb_desc_config), + .bDescriptorType = USB_DESCTYPE_CONFIG + }, + .wTotalLength = DESC_LEN_CONFIG, + .bNumInterfaces = 0x01U, + .bConfigurationValue = 0x01U, + .iConfiguration = 0x00U, + .bmAttributes = 0x80U, + .bMaxPower = 0x32U + }, + + .hid_itf = + { + .header = + { + .bLength = sizeof(usb_desc_itf), + .bDescriptorType = USB_DESCTYPE_ITF + }, + .bInterfaceNumber = 0x00U, + .bAlternateSetting = 0x00U, + .bNumEndpoints = 0x02U, + .bInterfaceClass = USB_HID_CLASS, + .bInterfaceSubClass = 0x00U, + .bInterfaceProtocol = 0x00U, + .iInterface = 0x00U + }, + + .hid_vendor = + { + .header = + { + .bLength = sizeof(usb_desc_hid), + .bDescriptorType = USB_DESCTYPE_HID + }, + .bcdHID = 0x0111U, + .bCountryCode = 0x00U, + .bNumDescriptors = 0x01U, + .bDescriptorType = USB_DESCTYPE_REPORT, + .wDescriptorLength = DESC_LEN_REPORT, + }, + + .hid_epin = + { + .header = + { + .bLength = sizeof(usb_desc_ep), + .bDescriptorType = USB_DESCTYPE_EP + }, + .bEndpointAddress = CUSTOMHID_IN_EP, + .bmAttributes = USB_EP_ATTR_INT, + .wMaxPacketSize = CUSTOMHID_IN_PACKET, + .bInterval = 0x20U + }, + + .hid_epout = + { + .header = + { + .bLength = sizeof(usb_desc_ep), + .bDescriptorType = USB_DESCTYPE_EP + }, + .bEndpointAddress = CUSTOMHID_OUT_EP, + .bmAttributes = USB_EP_ATTR_INT, + .wMaxPacketSize = CUSTOMHID_OUT_PACKET, + .bInterval = 0x20U + } +}; + +/* USB language ID descriptor */ +static __ALIGN_BEGIN const usb_desc_LANGID usbd_language_id_desc __ALIGN_END = +{ + .header = + { + .bLength = sizeof(usb_desc_LANGID), + .bDescriptorType = USB_DESCTYPE_STR + }, + .wLANGID = ENG_LANGID +}; + +/* USB manufacture string */ +static __ALIGN_BEGIN const usb_desc_str manufacturer_string __ALIGN_END = +{ + .header = + { + .bLength = USB_STRING_LEN(10U), + .bDescriptorType = USB_DESCTYPE_STR, + }, + .unicode_string = {'G', 'i', 'g', 'a', 'D', 'e', 'v', 'i', 'c', 'e'} +}; + +/* USB product string */ +static __ALIGN_BEGIN const usb_desc_str product_string __ALIGN_END = +{ + .header = + { + .bLength = USB_STRING_LEN(14U), + .bDescriptorType = USB_DESCTYPE_STR, + }, + .unicode_string = {'G', 'D', '3', '2', '-', 'C', 'u', 's', 't', 'o', 'm', 'H', 'I', 'D'} +}; + +/* USBD serial string */ +static __ALIGN_BEGIN usb_desc_str serial_string __ALIGN_END = +{ + .header = + { + .bLength = USB_STRING_LEN(12U), + .bDescriptorType = USB_DESCTYPE_STR, + } +}; + +/* USB string descriptor set */ +void *const usbd_hid_strings[] = +{ + [STR_IDX_LANGID] = (uint8_t *)&usbd_language_id_desc, + [STR_IDX_MFC] = (uint8_t *)&manufacturer_string, + [STR_IDX_PRODUCT] = (uint8_t *)&product_string, + [STR_IDX_SERIAL] = (uint8_t *)&serial_string +}; + +usb_desc custom_hid_desc = { + .dev_desc = (uint8_t *)&custom_hid_dev_desc, + .config_desc = (uint8_t *)&custom_hid_config_desc, + .strings = usbd_hid_strings +}; + +__ALIGN_BEGIN const uint8_t customhid_report_descriptor[DESC_LEN_REPORT] __ALIGN_END = +{ + 0x06, 0x00, 0xFF, /* USAGE_PAGE (Vendor Defined: 0xFF00) */ + 0x09, 0x00, /* USAGE (Custom Device) */ + 0xa1, 0x01, /* COLLECTION (Application) */ + + /* led 1 */ + 0x85, 0x11, /* REPORT_ID (0x11) */ + 0x09, 0x01, /* USAGE (LED 1) */ + 0x15, 0x00, /* LOGICAL_MINIMUM (0) */ + 0x25, 0x01, /* LOGICAL_MAXIMUM (1) */ + 0x75, 0x08, /* REPORT_SIZE (8) */ + 0x95, 0x01, /* REPORT_COUNT (1) */ + 0x91, 0x82, /* OUTPUT (Data,Var,Abs,Vol) */ + + /* led 2 */ + 0x85, 0x12, /* REPORT_ID (0x12) */ + 0x09, 0x02, /* USAGE (LED 2) */ + 0x15, 0x00, /* LOGICAL_MINIMUM (0) */ + 0x25, 0x01, /* LOGICAL_MAXIMUM (1) */ + 0x75, 0x08, /* REPORT_SIZE (8) */ + 0x95, 0x01, /* REPORT_COUNT (1) */ + 0x91, 0x82, /* OUTPUT (Data,Var,Abs,Vol) */ + + /* led 3 */ + 0x85, 0x13, /* REPORT_ID (0x13) */ + 0x09, 0x03, /* USAGE (LED 3) */ + 0x15, 0x00, /* LOGICAL_MINIMUM (0) */ + 0x25, 0x01, /* LOGICAL_MAXIMUM (1) */ + 0x75, 0x08, /* REPORT_SIZE (8) */ + 0x95, 0x01, /* REPORT_COUNT (1) */ + 0x91, 0x82, /* OUTPUT (Data,Var,Abs,Vol) */ + + /* led 4 */ + 0x85, 0x14, /* REPORT_ID (0x14) */ + 0x09, 0x04, /* USAGE (LED 4) */ + 0x15, 0x00, /* LOGICAL_MINIMUM (0) */ + 0x25, 0x01, /* LOGICAL_MAXIMUM (1) */ + 0x75, 0x08, /* REPORT_SIZE (8) */ + 0x95, 0x01, /* REPORT_COUNT (1) */ + 0x91, 0x82, /* OUTPUT (Data,Var,Abs,Vol) */ + + /* wakeup key */ + 0x85, 0x15, /* REPORT_ID (0x15) */ + 0x09, 0x05, /* USAGE (Push Button) */ + 0x15, 0x00, /* LOGICAL_MINIMUM (0) */ + 0x25, 0x01, /* LOGICAL_MAXIMUM (1) */ + 0x75, 0x01, /* REPORT_SIZE (1) */ + 0x81, 0x02, /* INPUT (Data,Var,Abs,Vol) */ + + 0x75, 0x07, /* REPORT_SIZE (7) */ + 0x81, 0x03, /* INPUT (Cnst,Var,Abs,Vol) */ + + /* tamper key */ + 0x85, 0x16, /* REPORT_ID (0x16) */ + 0x09, 0x06, /* USAGE (Push Button) */ + 0x15, 0x00, /* LOGICAL_MINIMUM (0) */ + 0x25, 0x01, /* LOGICAL_MAXIMUM (1) */ + 0x75, 0x01, /* REPORT_SIZE (1) */ + 0x81, 0x02, /* INPUT (Data,Var,Abs,Vol) */ + + 0x75, 0x07, /* REPORT_SIZE (7) */ + 0x81, 0x03, /* INPUT (Cnst,Var,Abs,Vol) */ + + 0xc0 /* END_COLLECTION */ +}; + +/* local function prototypes ('static') */ +static uint8_t custom_hid_init (usb_dev *udev, uint8_t config_index); +static uint8_t custom_hid_deinit (usb_dev *udev, uint8_t config_index); +static uint8_t custom_hid_req_handler (usb_dev *udev, usb_req *req); + +static uint8_t custom_hid_data_in (usb_dev *udev, uint8_t ep_num); +static uint8_t custom_hid_data_out (usb_dev *udev, uint8_t ep_num); + +usb_class_core usbd_custom_hid_cb = +{ + .command = NO_CMD, + .alter_set = 0U, + + .init = custom_hid_init, + .deinit = custom_hid_deinit, + + .req_proc = custom_hid_req_handler, + + .data_in = custom_hid_data_in, + .data_out = custom_hid_data_out +}; + +/*! + \brief register HID interface operation functions + \param[in] udev: pointer to USB device instance + \param[in] hid_fop: HID operation functions structure + \param[out] none + \retval USB device operation status +*/ +uint8_t custom_hid_itfop_register (usb_dev *udev, hid_fop_handler *hid_fop) +{ + if (NULL != hid_fop) { + udev->dev.user_data = hid_fop; + + return USBD_OK; + } + + return USBD_FAIL; +} + +/*! + \brief send custom HID report + \param[in] udev: pointer to USB device instance + \param[in] report: pointer to HID report + \param[in] len: data length + \param[out] none + \retval USB device operation status +*/ +uint8_t custom_hid_report_send (usb_dev *udev, uint8_t *report, uint32_t len) +{ + usbd_ep_send (udev, CUSTOMHID_IN_EP, report, len); + + return USBD_OK; +} + +/*! + \brief initialize the HID device + \param[in] udev: pointer to USB device instance + \param[in] config_index: configuration index + \param[out] none + \retval USB device operation status +*/ +static uint8_t custom_hid_init (usb_dev *udev, uint8_t config_index) +{ + static __ALIGN_BEGIN custom_hid_handler hid_handler __ALIGN_END; + + memset((void *)&hid_handler, 0U, sizeof(custom_hid_handler)); + + /* initialize the data TX endpoint */ + usbd_ep_setup (udev, &(custom_hid_config_desc.hid_epin)); + + /* Initialize the data RX endpoint */ + usbd_ep_setup (udev, &(custom_hid_config_desc.hid_epout)); + + /* prepare receive data */ + usbd_ep_recev (udev, CUSTOMHID_OUT_EP, hid_handler.data, 2U); + + udev->dev.class_data[CUSTOM_HID_INTERFACE] = (void *)&hid_handler; + + if (udev->dev.user_data != NULL) { + for (uint8_t i = 0U; i < MAX_PERIPH_NUM; i++) { + if (((hid_fop_handler *)udev->dev.user_data)->periph_config[i] != NULL) { + ((hid_fop_handler *)udev->dev.user_data)->periph_config[i](); + } + } + } + + return USBD_OK; +} + +/*! + \brief de-initialize the HID device + \param[in] udev: pointer to USB device instance + \param[in] config_index: configuration index + \param[out] none + \retval USB device operation status +*/ +static uint8_t custom_hid_deinit (usb_dev *udev, uint8_t config_index) +{ + /* deinitialize HID endpoints */ + usbd_ep_clear(udev, CUSTOMHID_IN_EP); + usbd_ep_clear(udev, CUSTOMHID_OUT_EP); + + return USBD_OK; +} + +/*! + \brief handle the HID class-specific requests + \param[in] udev: pointer to USB device instance + \param[in] req: device class-specific request + \param[out] none + \retval USB device operation status +*/ +static uint8_t custom_hid_req_handler (usb_dev *udev, usb_req *req) +{ + usb_transc *transc = &udev->dev.transc_in[0]; + + custom_hid_handler *hid = (custom_hid_handler *)udev->dev.class_data[CUSTOM_HID_INTERFACE]; + + switch (req->bRequest) { + case GET_REPORT: + break; + + case GET_IDLE: + transc->xfer_buf = (uint8_t *)&hid->idlestate; + transc->remain_len = 1U; + break; + + case GET_PROTOCOL: + transc->xfer_buf = (uint8_t *)&hid->protocol; + transc->remain_len = 1U; + break; + + case SET_REPORT: + hid->reportID = (uint8_t)(req->wValue); + break; + + case SET_IDLE: + hid->idlestate = (uint8_t)(req->wValue >> 8U); + break; + + case SET_PROTOCOL: + hid->protocol = (uint8_t)(req->wValue); + break; + + case USB_GET_DESCRIPTOR: + if (USB_DESCTYPE_REPORT == (req->wValue >> 8U)) { + transc->remain_len = USB_MIN(DESC_LEN_REPORT, req->wLength); + transc->xfer_buf = (uint8_t *)customhid_report_descriptor; + } + break; + + default: + return USBD_FAIL; + } + + return USBD_OK; +} + +/*! + \brief handle custom HID data + \param[in] udev: pointer to USB device instance + \param[in] ep_num: endpoint identifier + \param[out] none + \retval USB device operation status +*/ +static uint8_t custom_hid_data_in (usb_dev *udev, uint8_t ep_num) +{ + return USBD_OK; +} + +/*! + \brief handle custom HID data + \param[in] udev: pointer to USB device instance + \param[in] ep_num: endpoint identifier + \param[out] none + \retval USB device operation status +*/ +static uint8_t custom_hid_data_out (usb_dev *udev, uint8_t ep_num) +{ + custom_hid_handler *hid = (custom_hid_handler *)udev->dev.class_data[CUSTOM_HID_INTERFACE]; + + if ((CUSTOMHID_OUT_EP & 0x7FU) == ep_num) { + switch (hid->data[0]){ + case 0x11U: + if (RESET != hid->data[1]) { + gd_eval_led_on(LED1); + } else { + gd_eval_led_off(LED1); + } + break; + + case 0x12U: + if (RESET != hid->data[1]) { + gd_eval_led_on(LED2); + } else { + gd_eval_led_off(LED2); + } + break; + + case 0x13U: + if (RESET != hid->data[1]) { + gd_eval_led_on(LED3); + } else { + gd_eval_led_off(LED3); + } + break; + + case 0x14U: + break; + + default: + break; + } + + usbd_ep_recev (udev, CUSTOMHID_IN_EP, hid->data, 2U); + + return USBD_OK; + } + + return USBD_FAIL; +} diff --git a/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/device/class/hid/Source/standard_hid_core.c b/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/device/class/hid/Source/standard_hid_core.c new file mode 100644 index 0000000000..8252e33e97 --- /dev/null +++ b/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/device/class/hid/Source/standard_hid_core.c @@ -0,0 +1,384 @@ +/*! + \file standard_hid_core.c + \brief HID class driver + + \version 2020-08-01, V3.0.0, firmware for GD32F4xx +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "standard_hid_core.h" +#include + +#define USBD_VID 0x28e9U +#define USBD_PID 0x0380U + +/* Note:it should use the C99 standard when compiling the below codes */ +/* USB standard device descriptor */ +__ALIGN_BEGIN const usb_desc_dev hid_dev_desc __ALIGN_END = +{ + .header = + { + .bLength = USB_DEV_DESC_LEN, + .bDescriptorType = USB_DESCTYPE_DEV + }, + .bcdUSB = 0x0200U, + .bDeviceClass = 0x00U, + .bDeviceSubClass = 0x00U, + .bDeviceProtocol = 0x00U, + .bMaxPacketSize0 = USB_FS_EP0_MAX_LEN, + .idVendor = USBD_VID, + .idProduct = USBD_PID, + .bcdDevice = 0x0100U, + .iManufacturer = STR_IDX_MFC, + .iProduct = STR_IDX_PRODUCT, + .iSerialNumber = STR_IDX_SERIAL, + .bNumberConfigurations = USBD_CFG_MAX_NUM +}; + +__ALIGN_BEGIN const usb_hid_desc_config_set hid_config_desc __ALIGN_END = +{ + .config = + { + .header = + { + .bLength = sizeof(usb_desc_config), + .bDescriptorType = USB_DESCTYPE_CONFIG + }, + .wTotalLength = USB_HID_CONFIG_DESC_LEN, + .bNumInterfaces = 0x01U, + .bConfigurationValue = 0x01U, + .iConfiguration = 0x00U, + .bmAttributes = 0xA0U, + .bMaxPower = 0x32U + }, + + .hid_itf = + { + .header = + { + .bLength = sizeof(usb_desc_itf), + .bDescriptorType = USB_DESCTYPE_ITF + }, + .bInterfaceNumber = 0x00U, + .bAlternateSetting = 0x00U, + .bNumEndpoints = 0x01U, + .bInterfaceClass = USB_HID_CLASS, + .bInterfaceSubClass = USB_HID_SUBCLASS_BOOT_ITF, + .bInterfaceProtocol = USB_HID_PROTOCOL_KEYBOARD, + .iInterface = 0x00U + }, + + .hid_vendor = + { + .header = + { + .bLength = sizeof(usb_desc_hid), + .bDescriptorType = USB_DESCTYPE_HID + }, + .bcdHID = 0x0111U, + .bCountryCode = 0x00U, + .bNumDescriptors = 0x01U, + .bDescriptorType = USB_DESCTYPE_REPORT, + .wDescriptorLength = USB_HID_REPORT_DESC_LEN, + }, + + .hid_epin = + { + .header = + { + .bLength = sizeof(usb_desc_ep), + .bDescriptorType = USB_DESCTYPE_EP + }, + .bEndpointAddress = HID_IN_EP, + .bmAttributes = USB_EP_ATTR_INT, + .wMaxPacketSize = HID_IN_PACKET, + .bInterval = 0x40U + } +}; + +/* USB language ID Descriptor */ +static __ALIGN_BEGIN const usb_desc_LANGID usbd_language_id_desc __ALIGN_END = +{ + .header = + { + .bLength = sizeof(usb_desc_LANGID), + .bDescriptorType = USB_DESCTYPE_STR + }, + .wLANGID = ENG_LANGID +}; + +/* USB manufacture string */ +static __ALIGN_BEGIN const usb_desc_str manufacturer_string __ALIGN_END = +{ + .header = + { + .bLength = USB_STRING_LEN(10U), + .bDescriptorType = USB_DESCTYPE_STR, + }, + .unicode_string = {'G', 'i', 'g', 'a', 'D', 'e', 'v', 'i', 'c', 'e'} +}; + +/* USB product string */ +static __ALIGN_BEGIN const usb_desc_str product_string __ALIGN_END = +{ + .header = + { + .bLength = USB_STRING_LEN(17U), + .bDescriptorType = USB_DESCTYPE_STR, + }, + .unicode_string = {'G', 'D', '3', '2', '-','U', 'S', 'B', '_', 'K', 'e', 'y', 'b', 'o', 'a', 'r', 'd'} +}; + +/* USBD serial string */ +static __ALIGN_BEGIN usb_desc_str serial_string __ALIGN_END = +{ + .header = + { + .bLength = USB_STRING_LEN(12U), + .bDescriptorType = USB_DESCTYPE_STR, + } +}; + +void *const usbd_hid_strings[] = +{ + [STR_IDX_LANGID] = (uint8_t *)&usbd_language_id_desc, + [STR_IDX_MFC] = (uint8_t *)&manufacturer_string, + [STR_IDX_PRODUCT] = (uint8_t *)&product_string, + [STR_IDX_SERIAL] = (uint8_t *)&serial_string +}; + +usb_desc hid_desc = { + .dev_desc = (uint8_t *)&hid_dev_desc, + .config_desc = (uint8_t *)&hid_config_desc, + .strings = usbd_hid_strings +}; + +__ALIGN_BEGIN const uint8_t hid_report_desc[USB_HID_REPORT_DESC_LEN] __ALIGN_END = +{ + 0x05, 0x01, /* USAGE_PAGE (Generic Desktop) */ + 0x09, 0x06, /* USAGE (Keyboard) */ + 0xa1, 0x01, /* COLLECTION (Application) */ + + 0x05, 0x07, /* USAGE_PAGE (Keyboard/Keypad) */ + 0x19, 0xe0, /* USAGE_MINIMUM (Keyboard LeftControl) */ + 0x29, 0xe7, /* USAGE_MAXIMUM (Keyboard Right GUI) */ + 0x15, 0x00, /* LOGICAL_MINIMUM (0) */ + 0x25, 0x01, /* LOGICAL_MAXIMUM (1) */ + 0x95, 0x08, /* REPORT_COUNT (8) */ + 0x75, 0x01, /* REPORT_SIZE (1) */ + 0x81, 0x02, /* INPUT (Data,Var,Abs) */ + + 0x95, 0x01, /* REPORT_COUNT (1) */ + 0x75, 0x08, /* REPORT_SIZE (8) */ + 0x81, 0x03, /* INPUT (Cnst,Var,Abs) */ + + 0x95, 0x06, /* REPORT_COUNT (6) */ + 0x75, 0x08, /* REPORT_SIZE (8) */ + 0x25, 0xFF, /* LOGICAL_MAXIMUM (255) */ + 0x19, 0x00, /* USAGE_MINIMUM (Reserved (no event indicated)) */ + 0x29, 0x65, /* USAGE_MAXIMUM (Keyboard Application) */ + 0x81, 0x00, /* INPUT (Data,Ary,Abs) */ + + 0xc0 /* END_COLLECTION */ +}; + +/* local function prototypes ('static') */ +static uint8_t hid_init (usb_dev *udev, uint8_t config_index); +static uint8_t hid_deinit (usb_dev *udev, uint8_t config_index); +static uint8_t hid_req (usb_dev *udev, usb_req *req); +static uint8_t hid_data_in (usb_dev *udev, uint8_t ep_num); + +usb_class_core usbd_hid_cb = { + .command = NO_CMD, + .alter_set = 0U, + + .init = hid_init, + .deinit = hid_deinit, + .req_proc = hid_req, + .data_in = hid_data_in +}; + +/*! + \brief register HID interface operation functions + \param[in] udev: pointer to USB device instance + \param[in] hid_fop: HID operation function structure + \param[out] none + \retval USB device operation status +*/ +uint8_t hid_itfop_register (usb_dev *udev, hid_fop_handler *hid_fop) +{ + if (NULL != hid_fop) { + udev->dev.user_data = (void *)hid_fop; + + return USBD_OK; + } + + return USBD_FAIL; +} + +/*! + \brief send keyboard report + \param[in] udev: pointer to USB device instance + \param[in] report: pointer to HID report + \param[in] len: data length + \param[out] none + \retval USB device operation status +*/ +uint8_t hid_report_send (usb_dev *udev, uint8_t *report, uint32_t len) +{ + standard_hid_handler *hid = (standard_hid_handler *)udev->dev.class_data[USBD_HID_INTERFACE]; + + hid->prev_transfer_complete = 0U; + + usbd_ep_send(udev, HID_IN_EP, report, len); + + return USBD_OK; +} + +/*! + \brief initialize the HID device + \param[in] udev: pointer to USB device instance + \param[in] config_index: configuration index + \param[out] none + \retval USB device operation status +*/ +static uint8_t hid_init (usb_dev *udev, uint8_t config_index) +{ + static __ALIGN_BEGIN standard_hid_handler hid_handler __ALIGN_END; + + memset((void *)&hid_handler, 0U, sizeof(standard_hid_handler)); + + /* initialize the data TX endpoint */ + usbd_ep_setup (udev, &(hid_config_desc.hid_epin)); + + hid_handler.prev_transfer_complete = 1U; + + udev->dev.class_data[USBD_HID_INTERFACE] = (void *)&hid_handler; + + if (NULL != udev->dev.user_data) { + ((hid_fop_handler *)udev->dev.user_data)->hid_itf_config(); + } + + return USBD_OK; +} + +/*! + \brief de-initialize the HID device + \param[in] udev: pointer to USB device instance + \param[in] config_index: configuration index + \param[out] none + \retval USB device operation status +*/ +static uint8_t hid_deinit (usb_dev *udev, uint8_t config_index) +{ + /* deinitialize HID endpoints */ + usbd_ep_clear(udev, HID_IN_EP); + + return USBD_OK; +} + +/*! + \brief handle the HID class-specific requests + \param[in] udev: pointer to USB device instance + \param[in] req: device class-specific request + \param[out] none + \retval USB device operation status +*/ +static uint8_t hid_req (usb_dev *udev, usb_req *req) +{ + usb_transc *transc = &udev->dev.transc_in[0]; + + standard_hid_handler *hid = (standard_hid_handler *)udev->dev.class_data[USBD_HID_INTERFACE]; + + switch (req->bRequest) { + case GET_REPORT: + /* no use for this driver */ + break; + + case GET_IDLE: + transc->xfer_buf = (uint8_t *)&hid->idle_state; + + transc->remain_len = 1U; + break; + + case GET_PROTOCOL: + transc->xfer_buf = (uint8_t *)&hid->protocol; + + transc->remain_len = 1U; + break; + + case SET_REPORT: + /* no use for this driver */ + break; + + case SET_IDLE: + hid->idle_state = (uint8_t)(req->wValue >> 8U); + break; + + case SET_PROTOCOL: + hid->protocol = (uint8_t)(req->wValue); + break; + + case USB_GET_DESCRIPTOR: + if (USB_DESCTYPE_REPORT == (req->wValue >> 8U)) { + transc->remain_len = USB_MIN(USB_HID_REPORT_DESC_LEN, req->wLength); + transc->xfer_buf = (uint8_t *)hid_report_desc; + + return REQ_SUPP; + } + break; + + default: + break; + } + + return USBD_OK; +} + +/*! + \brief handle data stage + \param[in] udev: pointer to USB device instance + \param[in] ep_num: endpoint identifier + \param[out] none + \retval USB device operation status +*/ +static uint8_t hid_data_in (usb_dev *udev, uint8_t ep_num) +{ + standard_hid_handler *hid = (standard_hid_handler *)udev->dev.class_data[USBD_HID_INTERFACE]; + + if (0U != hid->data[2]) { + hid->data[2] = 0x00U; + + usbd_ep_send(udev, HID_IN_EP, hid->data, HID_IN_PACKET); + } else { + hid->prev_transfer_complete = 1U; + } + + return USBD_OK; +} diff --git a/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/device/class/iap/Include/usb_iap_core.h b/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/device/class/iap/Include/usb_iap_core.h new file mode 100644 index 0000000000..a84dc4a255 --- /dev/null +++ b/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/device/class/iap/Include/usb_iap_core.h @@ -0,0 +1,93 @@ +/*! + \file usb_iap_core.h + \brief the header file of IAP driver + + \version 2020-08-01, V3.0.0, firmware for GD32F4xx +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef __USB_IAP_CORE_H +#define __USB_IAP_CORE_H + +#include "usbd_enum.h" +#include "usb_hid.h" + +#define USB_SERIAL_STRING_SIZE 0x06U + +#ifdef USE_USB_FS + #define USB_DESC_LEN_IAP_REPORT 35U +#elif defined(USE_USB_HS) + #define USB_DESC_LEN_IAP_REPORT 36U +#else + #error "please select 'USE_USB_FS' or 'USE_USB_HS'" +#endif + +#define USB_DESC_LEN_IAP_CONFIG_SET 41U + +/* special commands with download request */ +#define IAP_OPTION_BYTE1 0x01U +#define IAP_ERASE 0x02U +#define IAP_DNLOAD 0x03U +#define IAP_LEAVE 0x04U +#define IAP_GETBIN_ADDRESS 0x05U +#define IAP_OPTION_BYTE2 0x06U + +typedef struct +{ + uint8_t option_byte[IAP_IN_PACKET]; + + /* state machine variables */ + uint8_t dev_status[IAP_IN_PACKET]; + uint8_t bin_addr[IAP_IN_PACKET]; + + uint8_t report_buf[IAP_OUT_PACKET + 1U]; + + uint8_t reportID; + uint8_t flag; + + uint32_t protocol; + uint32_t idlestate; + + uint16_t transfer_times; + uint16_t page_count; + uint16_t lps; /* last packet size */ + uint32_t file_length; + uint32_t base_address; +} usbd_iap_handler; + +typedef void (*app_func) (void); + +extern usb_desc iap_desc; +extern usb_class_core iap_class; + +/* function declarations */ +/* send IAP report */ +uint8_t iap_report_send (usb_dev *udev, uint8_t *report, uint32_t len); + +#endif /* __USB_IAP_CORE_H */ diff --git a/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/device/class/iap/Source/usb_iap_core.c b/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/device/class/iap/Source/usb_iap_core.c new file mode 100644 index 0000000000..6dced66ab8 --- /dev/null +++ b/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/device/class/iap/Source/usb_iap_core.c @@ -0,0 +1,571 @@ +/*! + \file usb_iap_core.c + \brief IAP driver + + \version 2020-08-01, V3.0.0, firmware for GD32F4xx +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "usb_iap_core.h" +#include "flash_operation.h" +#include + +#define USBD_VID 0x28E9U +#define USBD_PID 0x0228U + +/* Note:it should use the C99 standard when compiling the below codes */ +/* USB standard device descriptor */ +__ALIGN_BEGIN const usb_desc_dev iap_dev_desc __ALIGN_END = +{ + .header = + { + .bLength = USB_DEV_DESC_LEN, + .bDescriptorType = USB_DESCTYPE_DEV + }, + .bcdUSB = 0x0200U, + .bDeviceClass = 0x00U, + .bDeviceSubClass = 0x00U, + .bDeviceProtocol = 0x00U, + .bMaxPacketSize0 = USB_FS_EP0_MAX_LEN, + .idVendor = USBD_VID, + .idProduct = USBD_PID, + .bcdDevice = 0x0100U, + .iManufacturer = STR_IDX_MFC, + .iProduct = STR_IDX_PRODUCT, + .iSerialNumber = STR_IDX_SERIAL, + .bNumberConfigurations = USBD_CFG_MAX_NUM +}; + +__ALIGN_BEGIN const usb_hid_desc_config_set iap_config_desc __ALIGN_END = +{ + .config = + { + .header = + { + .bLength = sizeof(usb_desc_config), + .bDescriptorType = USB_DESCTYPE_CONFIG + }, + .wTotalLength = USB_DESC_LEN_IAP_CONFIG_SET, + .bNumInterfaces = 0x01U, + .bConfigurationValue = 0x01U, + .iConfiguration = 0x00U, + .bmAttributes = 0x80U, + .bMaxPower = 0x32U + }, + + .hid_itf = + { + .header = + { + .bLength = sizeof(usb_desc_itf), + .bDescriptorType = USB_DESCTYPE_ITF + }, + .bInterfaceNumber = 0x00U, + .bAlternateSetting = 0x00U, + .bNumEndpoints = 0x02U, + .bInterfaceClass = USB_HID_CLASS, + .bInterfaceSubClass = 0x00U, + .bInterfaceProtocol = 0x00U, + .iInterface = 0x00U + }, + + .hid_vendor = + { + .header = + { + .bLength = sizeof(usb_desc_hid), + .bDescriptorType = USB_DESCTYPE_HID + }, + .bcdHID = 0x0111U, + .bCountryCode = 0x00U, + .bNumDescriptors = 0x01U, + .bDescriptorType = USB_DESCTYPE_REPORT, + .wDescriptorLength = USB_DESC_LEN_IAP_REPORT, + }, + + .hid_epin = + { + .header = + { + .bLength = sizeof(usb_desc_ep), + .bDescriptorType = USB_DESCTYPE_EP + }, + .bEndpointAddress = IAP_IN_EP, + .bmAttributes = USB_EP_ATTR_INT, + .wMaxPacketSize = IAP_IN_PACKET, + .bInterval = 0x01U + }, + + .hid_epout = + { + .header = + { + .bLength = sizeof(usb_desc_ep), + .bDescriptorType = USB_DESCTYPE_EP + }, + .bEndpointAddress = IAP_OUT_EP, + .bmAttributes = USB_EP_ATTR_INT, + .wMaxPacketSize = IAP_OUT_PACKET, + .bInterval = 0x01U + } +}; + +/* USB language ID Descriptor */ +static __ALIGN_BEGIN const usb_desc_LANGID usbd_language_id_desc __ALIGN_END = +{ + .header = + { + .bLength = sizeof(usb_desc_LANGID), + .bDescriptorType = USB_DESCTYPE_STR + }, + .wLANGID = ENG_LANGID +}; + +/* USB manufacture string */ +static __ALIGN_BEGIN const usb_desc_str manufacturer_string __ALIGN_END = +{ + .header = + { + .bLength = USB_STRING_LEN(10U), + .bDescriptorType = USB_DESCTYPE_STR, + }, + .unicode_string = {'G', 'i', 'g', 'a', 'D', 'e', 'v', 'i', 'c', 'e'} +}; + +/* USB product string */ +static __ALIGN_BEGIN const usb_desc_str product_string __ALIGN_END = +{ + .header = + { + .bLength = USB_STRING_LEN(12U), + .bDescriptorType = USB_DESCTYPE_STR, + }, + .unicode_string = {'G', 'D', '3', '2', '-', 'U', 'S', 'B', '_', 'I', 'A', 'P'} +}; + +/* USBD serial string */ +static __ALIGN_BEGIN usb_desc_str serial_string __ALIGN_END = +{ + .header = + { + .bLength = USB_STRING_LEN(2U), + .bDescriptorType = USB_DESCTYPE_STR, + } +}; + +void *const usbd_iap_strings[] = +{ + [STR_IDX_LANGID] = (uint8_t *)&usbd_language_id_desc, + [STR_IDX_MFC] = (uint8_t *)&manufacturer_string, + [STR_IDX_PRODUCT] = (uint8_t *)&product_string, + [STR_IDX_SERIAL] = (uint8_t *)&serial_string +}; + +usb_desc iap_desc = { + .dev_desc = (uint8_t *)&iap_dev_desc, + .config_desc = (uint8_t *)&iap_config_desc, + .strings = usbd_iap_strings +}; + +/* local function prototypes ('static') */ +static uint8_t iap_init (usb_dev *udev, uint8_t config_index); +static uint8_t iap_deinit (usb_dev *udev, uint8_t config_index); +static uint8_t iap_req_handler (usb_dev *udev, usb_req *req); +static uint8_t iap_data_out (usb_dev *udev, uint8_t ep_num); + +/* IAP requests management functions */ +static void iap_req_erase (usb_dev *udev); +static void iap_req_dnload (usb_dev *udev); +static void iap_req_optionbyte(usb_dev *udev, uint8_t option_num); +static void iap_req_leave (usb_dev *udev); +static void iap_address_send (usb_dev *udev); + +usb_class_core iap_class = { + .init = iap_init, + .deinit = iap_deinit, + .req_proc = iap_req_handler, + .data_out = iap_data_out +}; + +/* USB custom HID device report descriptor */ +__ALIGN_BEGIN const uint8_t iap_report_desc[USB_DESC_LEN_IAP_REPORT] __ALIGN_END = +{ + 0x05, 0x01, /* USAGE_PAGE (Generic Desktop) */ + 0x09, 0x00, /* USAGE (Custom Device) */ + 0xa1, 0x01, /* COLLECTION (Application) */ + + /* IAP command and data */ + 0x85, 0x01, /* REPORT_ID (0x01) */ + 0x09, 0x01, /* USAGE (IAP command) */ + 0x15, 0x00, /* LOGICAL_MINIMUM (0) */ + 0x25, 0xff, /* LOGICAL_MAXIMUM (255) */ + 0x75, 0x08, /* REPORT_SIZE (8) */ +#ifdef USE_USB_FS + 0x95, REPORT_OUT_COUNT, +#else + #ifdef USE_ULPI_PHY + 0x96, BYTE_LOW(REPORT_OUT_COUNT), BYTE_HIGH(REPORT_OUT_COUNT), + #elif defined(USE_EMBEDDED_PHY) + 0x95, REPORT_OUT_COUNT, + #endif +#endif + 0x91, 0x82, /* OUTPUT (Data,Var,Abs,Vol) */ + + /* device status and option byte */ + 0x85, 0x02, /* REPORT_ID (0x02) */ + 0x09, 0x02, /* USAGE (Status and option byte) */ + 0x15, 0x00, /* LOGICAL_MINIMUM (0) */ + 0x25, 0xff, /* LOGICAL_MAXIMUM (255) */ + 0x75, 0x08, /* REPORT_SIZE (8) */ + 0x95, REPORT_IN_COUNT, /* REPORT_COUNT (23) */ + 0x81, 0x82, /* INPUT (Data,Var,Abs,Vol) */ + + 0xc0 /* END_COLLECTION */ +}; + +/*! + \brief send IAP report + \param[in] udev: pointer to USB device instance + \param[in] report: pointer to HID report + \param[in] len: data length + \param[out] none + \retval USB device operation status +*/ +uint8_t iap_report_send (usb_dev *udev, uint8_t *report, uint32_t len) +{ + usbd_ep_send (udev, IAP_IN_EP, report, len); + + return USBD_OK; +} + +/*! + \brief initialize the IAP device + \param[in] udev: pointer to USB device instance + \param[in] config_index: configuration index + \param[out] none + \retval USB device operation status +*/ +static uint8_t iap_init (usb_dev *udev, uint8_t config_index) +{ + static __ALIGN_BEGIN usbd_iap_handler iap_handler __ALIGN_END; + + /* initialize TX endpoint */ + usbd_ep_setup(udev, &(iap_config_desc.hid_epin)); + + /* initialize RX endpoint */ + usbd_ep_setup(udev, &(iap_config_desc.hid_epout)); + + /* unlock the internal flash */ + fmc_unlock(); + + memset((void *)&iap_handler, 0U, sizeof(usbd_iap_handler)); + + /* prepare receive data */ + usbd_ep_recev(udev, IAP_OUT_EP, iap_handler.report_buf, IAP_OUT_PACKET); + + iap_handler.base_address = APP_LOADED_ADDR; + + udev->dev.class_data[USBD_IAP_INTERFACE] = (void *)&iap_handler; + + return USBD_OK; +} + +/*! + \brief deinitialize the IAP device + \param[in] udev: pointer to USB device instance + \param[in] config_index: configuration index + \param[out] none + \retval USB device operation status +*/ +static uint8_t iap_deinit (usb_dev *udev, uint8_t config_index) +{ + /* deinitialize IAP endpoints */ + usbd_ep_clear (udev, IAP_IN_EP); + usbd_ep_clear (udev, IAP_OUT_EP); + + /* lock the internal flash */ + fmc_lock(); + + return USBD_OK; +} + +/*! + \brief handle the IAP class-specific requests + \param[in] udev: pointer to USB device instance + \param[in] req: device class-specific request + \param[out] none + \retval USB device operation status +*/ +static uint8_t iap_req_handler (usb_dev *udev, usb_req *req) +{ + usb_transc *transc = &udev->dev.transc_in[0]; + + usbd_iap_handler *iap = (usbd_iap_handler *)udev->dev.class_data[USBD_IAP_INTERFACE]; + + switch (req->bRequest) { + case GET_REPORT: + /* no use for this driver */ + break; + + case GET_IDLE: + transc->xfer_buf = (uint8_t *)&iap->idlestate; + transc->remain_len = 1U; + break; + + case GET_PROTOCOL: + transc->xfer_buf = (uint8_t *)&iap->protocol; + transc->remain_len = 1U; + break; + + case SET_REPORT: + iap->reportID = (uint8_t)(req->wValue); + break; + + case SET_IDLE: + iap->idlestate = (uint8_t)(req->wValue >> 8U); + break; + + case SET_PROTOCOL: + iap->protocol = (uint8_t)(req->wValue); + break; + + case USB_GET_DESCRIPTOR: + if (USB_DESCTYPE_REPORT == (req->wValue >> 8U)) { + transc->remain_len = USB_MIN(USB_DESC_LEN_IAP_REPORT, req->wLength); + transc->xfer_buf = (uint8_t *)iap_report_desc; + } + break; + + default: + return USBD_FAIL; + } + + return USBD_OK; +} + +/*! + \brief handle data out stage + \param[in] udev: pointer to USB device instance + \param[in] ep_num: endpoint identifier + \param[out] none + \retval none +*/ +static uint8_t iap_data_out (usb_dev *udev ,uint8_t ep_num) +{ + usbd_iap_handler *iap = (usbd_iap_handler *)udev->dev.class_data[USBD_IAP_INTERFACE]; + + if ((IAP_OUT_EP & 0x7FU) == ep_num) { + if (0x01U == iap->report_buf[0]) { + switch (iap->report_buf[1]) { + case IAP_DNLOAD: + iap_req_dnload(udev); + break; + + case IAP_ERASE: + iap_req_erase(udev); + break; + + case IAP_OPTION_BYTE1: + iap_req_optionbyte(udev, 0x01U); + break; + + case IAP_LEAVE: + iap_req_leave(udev); + break; + + case IAP_GETBIN_ADDRESS: + iap_address_send(udev); + break; + + case IAP_OPTION_BYTE2: + iap_req_optionbyte(udev, 0x02U); + break; + + default: + break; + } + } + + usbd_ep_recev(udev, IAP_OUT_EP, iap->report_buf, IAP_OUT_PACKET); + } + + return USBD_OK; +} + +/*! + \brief handle the IAP_DNLOAD request + \param[in] udev: pointer to USB device instance + \param[out] none + \retval none +*/ +static void iap_req_dnload(usb_dev *udev) +{ + usbd_iap_handler *iap = (usbd_iap_handler *)udev->dev.class_data[USBD_IAP_INTERFACE]; + + if (0U != iap->transfer_times) { + if (1U == iap->transfer_times) { + if (0U == iap->lps) { + iap_data_write(&iap->report_buf[2], iap->base_address, TRANSFER_SIZE); + } else { + iap_data_write(&iap->report_buf[2], iap->base_address, iap->file_length % TRANSFER_SIZE); + iap->lps = 0U; + } + + iap->dev_status[0] = 0x02U; + iap->dev_status[1] = 0x02U; + iap_report_send (udev, iap->dev_status, IAP_IN_PACKET); + } else { + iap_data_write(&iap->report_buf[2], iap->base_address, TRANSFER_SIZE); + + iap->base_address += TRANSFER_SIZE; + } + + iap->transfer_times--; + } +} + +/*! + \brief handle the IAP_ERASE request + \param[in] udev: pointer to USB device instance + \param[out] none + \retval none +*/ +static void iap_req_erase(usb_dev *udev) +{ + uint32_t addr = 0U; + + usbd_iap_handler *iap = (usbd_iap_handler *)udev->dev.class_data[USBD_IAP_INTERFACE]; + + /* get base address to erase */ + iap->base_address = iap->report_buf[2]; + iap->base_address |= iap->report_buf[3] << 8U; + iap->base_address |= iap->report_buf[4] << 16U; + iap->base_address |= iap->report_buf[5] << 24U; + + /* get file length */ + iap->file_length = iap->report_buf[7]; + iap->file_length |= iap->report_buf[8] << 8U; + iap->file_length |= iap->report_buf[9] << 16U; + iap->file_length |= iap->report_buf[10] << 24U; + + iap->lps = iap->file_length % TRANSFER_SIZE; + if (0U == iap->lps) { + iap->transfer_times = iap->file_length / TRANSFER_SIZE; + } else { + iap->transfer_times = iap->file_length / TRANSFER_SIZE + 1U; + } + + /* check if the address is in protected area */ + if (IS_PROTECTED_AREA(iap->base_address)) { + return; + } + + addr = iap->base_address; + + /* unlock the flash program erase controller */ + fmc_unlock(); + + flash_erase(addr, iap->file_length, iap->report_buf); + + fmc_lock(); + + iap->dev_status[0] = 0x02U; + iap->dev_status[1] = 0x01U; + + usbd_ep_send(udev, IAP_IN_EP, iap->dev_status, IAP_IN_PACKET); +} + +/*! + \brief handle the IAP_OPTION_BYTE request + \param[in] udev: pointer to USB device instance + \param[in] option_num: number of option byte + \param[out] none + \retval none +*/ +static void iap_req_optionbyte(usb_dev *udev, uint8_t option_num) +{ + uint8_t i = 0U; + uint32_t address = 0U; + + usbd_iap_handler *iap = (usbd_iap_handler *)udev->dev.class_data[USBD_IAP_INTERFACE]; + + iap->option_byte[0]= 0x02U; + + if (0x01U == option_num) { + address = OPT_BYTE_ADDR1; +#ifdef OPT_BYTE_ADDR2 + } else if (0x02U == option_num) { + address = OPT_BYTE_ADDR2; +#endif + } else { + return; + } + + for (i = 1U; i < 17U; i++) { + iap->option_byte[i] = *(uint8_t *)address; + address++; + } + + iap_report_send (udev, iap->option_byte, IAP_IN_PACKET); +} + +/*! + \brief handle the IAP_LEAVE request + \param[in] udev: pointer to USB device instance + \param[out] none + \retval none +*/ +static void iap_req_leave(usb_dev *udev) +{ + /* lock the internal flash */ + fmc_lock(); + + /* generate system reset to allow jumping to the user code */ + NVIC_SystemReset(); +} + +/*! + \brief handle the IAP_SEND_ADDRESS request + \param[in] udev: pointer to USB device instance + \param[out] none + \retval none +*/ +static void iap_address_send(usb_dev *udev) +{ + usbd_iap_handler *iap = (usbd_iap_handler *)udev->dev.class_data[USBD_IAP_INTERFACE]; + + iap->bin_addr[0] = 0x02U; + + iap->bin_addr[1] = (uint8_t)(APP_LOADED_ADDR); + iap->bin_addr[2] = (uint8_t)(APP_LOADED_ADDR >> 8U); + iap->bin_addr[3] = (uint8_t)(APP_LOADED_ADDR >> 16U); + iap->bin_addr[4] = (uint8_t)(APP_LOADED_ADDR >> 24U); + + iap_report_send (udev, iap->bin_addr, IAP_IN_PACKET); +} diff --git a/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/device/class/msc/Include/usbd_msc_bbb.h b/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/device/class/msc/Include/usbd_msc_bbb.h new file mode 100644 index 0000000000..266b932d7a --- /dev/null +++ b/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/device/class/msc/Include/usbd_msc_bbb.h @@ -0,0 +1,101 @@ +/*! + \file usbd_msc_bbb.h + \brief the header file of the usbd_msc_bot.c file + + \version 2020-08-01, V3.0.0, firmware for GD32F4xx +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef __USBD_MSC_BBB_H +#define __USBD_MSC_BBB_H + +#include "usbd_core.h" +#include "msc_bbb.h" +#include "usbd_msc_mem.h" +#include "usbd_msc_scsi.h" + +/* MSC BBB state */ +enum msc_bbb_state { + BBB_IDLE = 0U, /*!< idle state */ + BBB_DATA_OUT, /*!< data OUT state */ + BBB_DATA_IN, /*!< data IN state */ + BBB_LAST_DATA_IN, /*!< last data IN state */ + BBB_SEND_DATA /*!< send immediate data state */ +}; + +/* MSC BBB status */ +enum msc_bbb_status { + BBB_STATUS_NORMAL = 0U, /*!< normal status */ + BBB_STATUS_RECOVERY, /*!< recovery status*/ + BBB_STATUS_ERROR /*!< error status */ +}; + +typedef struct +{ + uint8_t bbb_data[MSC_MEDIA_PACKET_SIZE]; + + uint8_t max_lun; + uint8_t bbb_state; + uint8_t bbb_status; + + uint32_t bbb_datalen; + + msc_bbb_cbw bbb_cbw; + msc_bbb_csw bbb_csw; + + uint8_t scsi_sense_head; + uint8_t scsi_sense_tail; + + uint32_t scsi_blk_size[MEM_LUN_NUM]; + uint32_t scsi_blk_nbr[MEM_LUN_NUM]; + + uint32_t scsi_blk_addr; + uint32_t scsi_blk_len; + uint32_t scsi_disk_pop; + + msc_scsi_sense scsi_sense[SENSE_LIST_DEEPTH]; +} usbd_msc_handler; + +/* function declarations */ +/* initialize the bbb process */ +void msc_bbb_init (usb_core_driver *udev); +/* reset the BBB machine */ +void msc_bbb_reset (usb_core_driver *udev); +/* deinitialize the BBB machine */ +void msc_bbb_deinit (usb_core_driver *udev); +/* handle BBB data IN stage */ +void msc_bbb_data_in (usb_core_driver *udev, uint8_t ep_num); +/* handle BBB data OUT stage */ +void msc_bbb_data_out (usb_core_driver *udev, uint8_t ep_num); +/* send the CSW(command status wrapper) */ +void msc_bbb_csw_send (usb_core_driver *udev, uint8_t csw_status); +/* complete the clear feature request */ +void msc_bbb_clrfeature (usb_core_driver *udev, uint8_t ep_num); + +#endif /* __USBD_MSC_BBB_H */ diff --git a/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/device/class/msc/Include/usbd_msc_core.h b/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/device/class/msc/Include/usbd_msc_core.h new file mode 100644 index 0000000000..a67b539746 --- /dev/null +++ b/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/device/class/msc/Include/usbd_msc_core.h @@ -0,0 +1,59 @@ +/*! + \file usbd_msc_core.h + \brief the header file of USB MSC device class core functions + + \version 2020-08-01, V3.0.0, firmware for GD32F4xx +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef __USBD_MSC_CORE_H +#define __USBD_MSC_CORE_H + +#include "usbd_core.h" +#include "usb_msc.h" + +#define USB_MSC_CONFIG_DESC_SIZE 32U + +#define MSC_EPIN_SIZE MSC_DATA_PACKET_SIZE +#define MSC_EPOUT_SIZE MSC_DATA_PACKET_SIZE + +/* USB configuration descriptor structure */ +typedef struct +{ + usb_desc_config config; + + usb_desc_itf msc_itf; + usb_desc_ep msc_epin; + usb_desc_ep msc_epout; +} usb_desc_config_set; + +extern usb_desc msc_desc; +extern usb_class_core msc_class; + +#endif /* __USBD_MSC_CORE_H */ diff --git a/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/device/class/msc/Include/usbd_msc_data.h b/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/device/class/msc/Include/usbd_msc_data.h new file mode 100644 index 0000000000..f7a180a326 --- /dev/null +++ b/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/device/class/msc/Include/usbd_msc_data.h @@ -0,0 +1,49 @@ +/*! + \file usbd_msc_data.h + \brief the header file of the usbd_msc_data.c file + + \version 2020-08-01, V3.0.0, firmware for GD32F4xx +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef __USBD_MSC_DATA_H +#define __USBD_MSC_DATA_H + +#include "usbd_conf.h" + +#define MODE_SENSE6_LENGTH 8U +#define MODE_SENSE10_LENGTH 8U +#define INQUIRY_PAGE00_LENGTH 96U +#define FORMAT_CAPACITIES_LENGTH 20U + +extern const uint8_t msc_page00_inquiry_data[]; +extern const uint8_t msc_mode_sense6_data[]; +extern const uint8_t msc_mode_sense10_data[]; + +#endif /* __USBD_MSC_DATA_H */ diff --git a/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/device/class/msc/Include/usbd_msc_mem.h b/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/device/class/msc/Include/usbd_msc_mem.h new file mode 100644 index 0000000000..c39778fcf6 --- /dev/null +++ b/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/device/class/msc/Include/usbd_msc_mem.h @@ -0,0 +1,59 @@ +/*! + \file usbd_msc_mem.h + \brief header file for storage memory + + \version 2020-08-01, V3.0.0, firmware for GD32F4xx +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef __USBD_MSC_MEM_H +#define __USBD_MSC_MEM_H + +#include "usbd_conf.h" + +#define USBD_STD_INQUIRY_LENGTH 36U + +typedef struct +{ + int8_t (*mem_init) (uint8_t lun); + int8_t (*mem_ready) (uint8_t lun); + int8_t (*mem_protected) (uint8_t lun); + int8_t (*mem_read) (uint8_t lun, uint8_t *buf, uint32_t block_addr, uint16_t block_len); + int8_t (*mem_write) (uint8_t lun, uint8_t *buf, uint32_t block_addr, uint16_t block_len); + int8_t (*mem_maxlun) (void); + + uint8_t *mem_toc_data; + uint8_t *mem_inquiry_data[MEM_LUN_NUM]; + uint32_t mem_block_size[MEM_LUN_NUM]; + uint32_t mem_block_len[MEM_LUN_NUM]; +}usbd_mem_cb; + +extern usbd_mem_cb *usbd_mem_fops; + +#endif /* __USBD_MSC_MEM_H */ diff --git a/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/device/class/msc/Include/usbd_msc_scsi.h b/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/device/class/msc/Include/usbd_msc_scsi.h new file mode 100644 index 0000000000..188e592ced --- /dev/null +++ b/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/device/class/msc/Include/usbd_msc_scsi.h @@ -0,0 +1,50 @@ +/*! + \file usbd_msc_scsi.h + \brief the header file of the usbd_msc_scsi.c file + + \version 2020-08-01, V3.0.0, firmware for GD32F4xx +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef __USBD_MSC_SCSI_H +#define __USBD_MSC_SCSI_H + +#include "usbd_msc_data.h" +#include "usbd_msc_bbb.h" +#include "msc_scsi.h" + +#define SENSE_LIST_DEEPTH 4U + +/* function declarations */ +/* process SCSI commands */ +int8_t scsi_process_cmd (usb_core_driver *udev, uint8_t lun, uint8_t *cmd); +/* load the last error code in the error list */ +void scsi_sense_code (usb_core_driver *udev, uint8_t lun, uint8_t skey, uint8_t asc); + +#endif /* __USBD_MSC_SCSI_H */ diff --git a/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/device/class/msc/Source/usbd_msc_bbb.c b/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/device/class/msc/Source/usbd_msc_bbb.c new file mode 100644 index 0000000000..d9a74d5d5d --- /dev/null +++ b/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/device/class/msc/Source/usbd_msc_bbb.c @@ -0,0 +1,287 @@ +/*! + \file usbd_msc_bbb.c + \brief USB BBB(Bulk/Bulk/Bulk) protocol core functions + \note BBB means Bulk-only transport protocol for USB MSC + + \version 2020-08-01, V3.0.0, firmware for GD32F4xx +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "usbd_enum.h" +#include "usbd_msc_bbb.h" + +/* local function prototypes ('static') */ +static void msc_bbb_cbw_decode (usb_core_driver *udev); +static void msc_bbb_data_send (usb_core_driver *udev, uint8_t *pbuf, uint32_t Len); +static void msc_bbb_abort (usb_core_driver *udev); + +/*! + \brief initialize the bbb process + \param[in] udev: pointer to USB device instance + \param[out] none + \retval none +*/ +void msc_bbb_init (usb_core_driver *udev) +{ + uint8_t lun_num; + + usbd_msc_handler *msc = (usbd_msc_handler *)udev->dev.class_data[USBD_MSC_INTERFACE]; + + msc->bbb_state = BBB_IDLE; + msc->bbb_status = BBB_STATUS_NORMAL; + + /* initializes the storage logic unit */ + for(lun_num = 0U; lun_num < MEM_LUN_NUM; lun_num++) { + usbd_mem_fops->mem_init(lun_num); + } + + /* flush the RX FIFO */ + usbd_fifo_flush (udev, MSC_OUT_EP); + + /* flush the TX FIFO */ + usbd_fifo_flush (udev, MSC_IN_EP); + + /* prepare endpoint to receive the first BBB CBW */ + usbd_ep_recev (udev, MSC_OUT_EP, (uint8_t *)&msc->bbb_cbw, BBB_CBW_LENGTH); +} + +/*! + \brief reset the BBB machine + \param[in] udev: pointer to USB device instance + \param[out] none + \retval none +*/ +void msc_bbb_reset (usb_core_driver *udev) +{ + usbd_msc_handler *msc = (usbd_msc_handler *)udev->dev.class_data[USBD_MSC_INTERFACE]; + + msc->bbb_state = BBB_IDLE; + msc->bbb_status = BBB_STATUS_RECOVERY; + + /* prepare endpoint to receive the first BBB command */ + usbd_ep_recev (udev, MSC_OUT_EP, (uint8_t *)&msc->bbb_cbw, BBB_CBW_LENGTH); +} + +/*! + \brief de-initialize the BBB machine + \param[in] udev: pointer to USB device instance + \param[out] none + \retval none +*/ +void msc_bbb_deinit (usb_core_driver *udev) +{ + usbd_msc_handler *msc = (usbd_msc_handler *)udev->dev.class_data[USBD_MSC_INTERFACE]; + + msc->bbb_state = BBB_IDLE; +} + +/*! + \brief handle BBB data IN stage + \param[in] udev: pointer to USB device instance + \param[in] ep_num: endpoint number + \param[out] none + \retval none +*/ +void msc_bbb_data_in (usb_core_driver *udev, uint8_t ep_num) +{ + usbd_msc_handler *msc = (usbd_msc_handler *)udev->dev.class_data[USBD_MSC_INTERFACE]; + + switch (msc->bbb_state) { + case BBB_DATA_IN: + if (scsi_process_cmd (udev, msc->bbb_cbw.bCBWLUN, &msc->bbb_cbw.CBWCB[0]) < 0) { + msc_bbb_csw_send (udev, CSW_CMD_FAILED); + } + break; + + case BBB_SEND_DATA: + case BBB_LAST_DATA_IN: + msc_bbb_csw_send (udev, CSW_CMD_PASSED); + break; + + default: + break; + } +} + +/*! + \brief handle BBB data OUT stage + \param[in] udev: pointer to USB device instance + \param[in] ep_num: endpoint number + \param[out] none + \retval none +*/ +void msc_bbb_data_out (usb_core_driver *udev, uint8_t ep_num) +{ + usbd_msc_handler *msc = (usbd_msc_handler *)udev->dev.class_data[USBD_MSC_INTERFACE]; + + switch (msc->bbb_state) { + case BBB_IDLE: + msc_bbb_cbw_decode (udev); + break; + + case BBB_DATA_OUT: + if (scsi_process_cmd (udev, msc->bbb_cbw.bCBWLUN, &msc->bbb_cbw.CBWCB[0]) < 0) { + msc_bbb_csw_send (udev, CSW_CMD_FAILED); + } + break; + + default: + break; + } +} + +/*! + \brief send the CSW(command status wrapper) + \param[in] udev: pointer to USB device instance + \param[in] csw_status: CSW status + \param[out] none + \retval none +*/ +void msc_bbb_csw_send (usb_core_driver *udev, uint8_t csw_status) +{ + usbd_msc_handler *msc = (usbd_msc_handler *)udev->dev.class_data[USBD_MSC_INTERFACE]; + + msc->bbb_csw.dCSWSignature = BBB_CSW_SIGNATURE; + msc->bbb_csw.bCSWStatus = csw_status; + msc->bbb_state = BBB_IDLE; + + usbd_ep_send (udev, MSC_IN_EP, (uint8_t *)&msc->bbb_csw, BBB_CSW_LENGTH); + + /* prepare endpoint to receive next command */ + usbd_ep_recev (udev, MSC_OUT_EP, (uint8_t *)&msc->bbb_cbw, BBB_CBW_LENGTH); +} + +/*! + \brief complete the clear feature request + \param[in] udev: pointer to USB device instance + \param[in] ep_num: endpoint number + \param[out] none + \retval none +*/ +void msc_bbb_clrfeature (usb_core_driver *udev, uint8_t ep_num) +{ + usbd_msc_handler *msc = (usbd_msc_handler *)udev->dev.class_data[USBD_MSC_INTERFACE]; + + if (msc->bbb_status == BBB_STATUS_ERROR)/* bad CBW signature */ { + usbd_ep_stall(udev, MSC_IN_EP); + + msc->bbb_status = BBB_STATUS_NORMAL; + } else if(((ep_num & 0x80U) == 0x80U) && (msc->bbb_status != BBB_STATUS_RECOVERY)) { + msc_bbb_csw_send (udev, CSW_CMD_FAILED); + } else { + + } +} + +/*! + \brief decode the CBW command and set the BBB state machine accordingly + \param[in] udev: pointer to USB device instance + \param[out] none + \retval none +*/ +static void msc_bbb_cbw_decode (usb_core_driver *udev) +{ + usbd_msc_handler *msc = (usbd_msc_handler *)udev->dev.class_data[USBD_MSC_INTERFACE]; + + msc->bbb_csw.dCSWTag = msc->bbb_cbw.dCBWTag; + msc->bbb_csw.dCSWDataResidue = msc->bbb_cbw.dCBWDataTransferLength; + + if ((BBB_CBW_LENGTH != usbd_rxcount_get (udev, MSC_OUT_EP)) || + (BBB_CBW_SIGNATURE != msc->bbb_cbw.dCBWSignature)|| + (msc->bbb_cbw.bCBWLUN > 1U) || + (msc->bbb_cbw.bCBWCBLength < 1U) || + (msc->bbb_cbw.bCBWCBLength > 16U)) { + /* illegal command handler */ + scsi_sense_code (udev, msc->bbb_cbw.bCBWLUN, ILLEGAL_REQUEST, INVALID_CDB); + + msc->bbb_status = BBB_STATUS_ERROR; + + msc_bbb_abort (udev); + } else { + if (scsi_process_cmd (udev, msc->bbb_cbw.bCBWLUN, &msc->bbb_cbw.CBWCB[0]) < 0) { + msc_bbb_abort (udev); + } else if ((BBB_DATA_IN != msc->bbb_state) && + (BBB_DATA_OUT != msc->bbb_state) && + (BBB_LAST_DATA_IN != msc->bbb_state)) { /* burst xfer handled internally */ + if (msc->bbb_datalen > 0U) { + msc_bbb_data_send (udev, msc->bbb_data, msc->bbb_datalen); + } else if (0U == msc->bbb_datalen) { + msc_bbb_csw_send (udev, CSW_CMD_PASSED); + } else { + + } + } else { + + } + } +} + +/*! + \brief send the requested data + \param[in] udev: pointer to USB device instance + \param[in] buf: pointer to data buffer + \param[in] len: data length + \param[out] none + \retval none +*/ +static void msc_bbb_data_send (usb_core_driver *udev, uint8_t *buf, uint32_t len) +{ + usbd_msc_handler *msc = (usbd_msc_handler *)udev->dev.class_data[USBD_MSC_INTERFACE]; + + len = USB_MIN (msc->bbb_cbw.dCBWDataTransferLength, len); + + msc->bbb_csw.dCSWDataResidue -= len; + msc->bbb_csw.bCSWStatus = CSW_CMD_PASSED; + msc->bbb_state = BBB_SEND_DATA; + + usbd_ep_send (udev, MSC_IN_EP, buf, len); +} + +/*! + \brief abort the current transfer + \param[in] udev: pointer to USB device instance + \param[out] none + \retval none +*/ +static void msc_bbb_abort (usb_core_driver *udev) +{ + usbd_msc_handler *msc = (usbd_msc_handler *)udev->dev.class_data[USBD_MSC_INTERFACE]; + + if ((0U == msc->bbb_cbw.bmCBWFlags) && + (0U != msc->bbb_cbw.dCBWDataTransferLength) && + (BBB_STATUS_NORMAL == msc->bbb_status)) { + usbd_ep_stall(udev, MSC_OUT_EP); + } + + usbd_ep_stall(udev, MSC_IN_EP); + + if (msc->bbb_status == BBB_STATUS_ERROR) { + usbd_ep_recev (udev, MSC_OUT_EP, (uint8_t *)&msc->bbb_cbw, BBB_CBW_LENGTH); + } +} diff --git a/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/device/class/msc/Source/usbd_msc_core.c b/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/device/class/msc/Source/usbd_msc_core.c new file mode 100644 index 0000000000..9c6e9f0857 --- /dev/null +++ b/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/device/class/msc/Source/usbd_msc_core.c @@ -0,0 +1,322 @@ +/*! + \file usbd_msc_core.c + \brief USB MSC device class core functions + + \version 2020-08-01, V3.0.0, firmware for GD32F4xx +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "usbd_enum.h" +#include "usbd_msc_bbb.h" +#include "usbd_msc_core.h" +#include + +#define USBD_VID 0x28E9U +#define USBD_PID 0x028FU + +/* local function prototypes ('static') */ +static uint8_t msc_core_init (usb_dev *udev, uint8_t config_index); +static uint8_t msc_core_deinit (usb_dev *udev, uint8_t config_index); +static uint8_t msc_core_req (usb_dev *udev, usb_req *req); +static uint8_t msc_core_in (usb_dev *udev, uint8_t ep_num); +static uint8_t msc_core_out (usb_dev *udev, uint8_t ep_num); + +usb_class_core msc_class = +{ + .init = msc_core_init, + .deinit = msc_core_deinit, + + .req_proc = msc_core_req, + + .data_in = msc_core_in, + .data_out = msc_core_out +}; + +/* note: it should use the C99 standard when compiling the below codes */ +/* USB standard device descriptor */ +__ALIGN_BEGIN const usb_desc_dev msc_dev_desc __ALIGN_END = +{ + .header = { + .bLength = USB_DEV_DESC_LEN, + .bDescriptorType = USB_DESCTYPE_DEV + }, + .bcdUSB = 0x0200U, + .bDeviceClass = 0x00U, + .bDeviceSubClass = 0x00U, + .bDeviceProtocol = 0x00U, + .bMaxPacketSize0 = USB_FS_EP0_MAX_LEN, + .idVendor = USBD_VID, + .idProduct = USBD_PID, + .bcdDevice = 0x0100U, + .iManufacturer = STR_IDX_MFC, + .iProduct = STR_IDX_PRODUCT, + .iSerialNumber = STR_IDX_SERIAL, + .bNumberConfigurations = USBD_CFG_MAX_NUM +}; + +/* USB device configuration descriptor */ +__ALIGN_BEGIN const usb_desc_config_set msc_config_desc __ALIGN_END = +{ + .config = + { + .header = { + .bLength = sizeof(usb_desc_config), + .bDescriptorType = USB_DESCTYPE_CONFIG + }, + .wTotalLength = USB_MSC_CONFIG_DESC_SIZE, + .bNumInterfaces = 0x01U, + .bConfigurationValue = 0x01U, + .iConfiguration = 0x00U, + .bmAttributes = 0xC0U, + .bMaxPower = 0x32U + }, + + .msc_itf = + { + .header = { + .bLength = sizeof(usb_desc_itf), + .bDescriptorType = USB_DESCTYPE_ITF + }, + .bInterfaceNumber = 0x00U, + .bAlternateSetting = 0x00U, + .bNumEndpoints = 0x02U, + .bInterfaceClass = USB_CLASS_MSC, + .bInterfaceSubClass = USB_MSC_SUBCLASS_SCSI, + .bInterfaceProtocol = USB_MSC_PROTOCOL_BBB, + .iInterface = 0x00U + }, + + .msc_epin = + { + .header = { + .bLength = sizeof(usb_desc_ep), + .bDescriptorType = USB_DESCTYPE_EP + }, + .bEndpointAddress = MSC_IN_EP, + .bmAttributes = USB_EP_ATTR_BULK, + .wMaxPacketSize = MSC_EPIN_SIZE, + .bInterval = 0x00U + }, + + .msc_epout = + { + .header = { + .bLength = sizeof(usb_desc_ep), + .bDescriptorType = USB_DESCTYPE_EP + }, + .bEndpointAddress = MSC_OUT_EP, + .bmAttributes = USB_EP_ATTR_BULK, + .wMaxPacketSize = MSC_EPOUT_SIZE, + .bInterval = 0x00U + } +}; + +/* USB language ID descriptor */ +static __ALIGN_BEGIN const usb_desc_LANGID usbd_language_id_desc __ALIGN_END = +{ + .header = + { + .bLength = sizeof(usb_desc_LANGID), + .bDescriptorType = USB_DESCTYPE_STR + }, + .wLANGID = ENG_LANGID +}; + +/* USB manufacture string */ +static __ALIGN_BEGIN const usb_desc_str manufacturer_string __ALIGN_END = +{ + .header = + { + .bLength = USB_STRING_LEN(10U), + .bDescriptorType = USB_DESCTYPE_STR, + }, + .unicode_string = {'G', 'i', 'g', 'a', 'D', 'e', 'v', 'i', 'c', 'e'} +}; + +/* USB product string */ +static __ALIGN_BEGIN const usb_desc_str product_string __ALIGN_END = +{ + .header = + { + .bLength = USB_STRING_LEN(12U), + .bDescriptorType = USB_DESCTYPE_STR, + }, + .unicode_string = {'G', 'D', '3', '2', '-', 'U', 'S', 'B', '_', 'M', 'S', 'C'} +}; + +/* USBD serial string */ +static __ALIGN_BEGIN usb_desc_str serial_string __ALIGN_END = +{ + .header = + { + .bLength = USB_STRING_LEN(12U), + .bDescriptorType = USB_DESCTYPE_STR, + } +}; + +/* USB string descriptor */ +static void *const usbd_msc_strings[] = +{ + [STR_IDX_LANGID] = (uint8_t *)&usbd_language_id_desc, + [STR_IDX_MFC] = (uint8_t *)&manufacturer_string, + [STR_IDX_PRODUCT] = (uint8_t *)&product_string, + [STR_IDX_SERIAL] = (uint8_t *)&serial_string +}; + +usb_desc msc_desc = { + .dev_desc = (uint8_t *)&msc_dev_desc, + .config_desc = (uint8_t *)&msc_config_desc, + .strings = usbd_msc_strings +}; + +static __ALIGN_BEGIN uint8_t usbd_msc_maxlun = 0U __ALIGN_END; + +/*! + \brief initialize the MSC device + \param[in] udev: pointer to USB device instance + \param[in] config_index: configuration index + \param[out] none + \retval USB device operation status +*/ +static uint8_t msc_core_init (usb_dev *udev, uint8_t config_index) +{ + static __ALIGN_BEGIN usbd_msc_handler msc_handler __ALIGN_END; + + memset((void *)&msc_handler, 0U, sizeof(usbd_msc_handler)); + + udev->dev.class_data[USBD_MSC_INTERFACE] = (void *)&msc_handler; + + /* configure MSC TX endpoint */ + usbd_ep_setup (udev, &(msc_config_desc.msc_epin)); + + /* configure MSC RX endpoint */ + usbd_ep_setup (udev, &(msc_config_desc.msc_epout)); + + /* initialize the BBB layer */ + msc_bbb_init(udev); + + return USBD_OK; +} + +/*! + \brief de-initialize the MSC device + \param[in] udev: pointer to USB device instance + \param[in] config_index: configuration index + \param[out] none + \retval USB device operation status +*/ +static uint8_t msc_core_deinit (usb_dev *udev, uint8_t config_index) +{ + /* clear MSC endpoints */ + usbd_ep_clear (udev, MSC_IN_EP); + usbd_ep_clear (udev, MSC_OUT_EP); + + /* deinitialize the BBB layer */ + msc_bbb_deinit(udev); + + return USBD_OK; +} + +/*! + \brief handle the MSC class-specific and standard requests + \param[in] udev: pointer to USB device instance + \param[in] req: device class-specific request + \param[out] none + \retval USB device operation status +*/ +static uint8_t msc_core_req (usb_dev *udev, usb_req *req) +{ + usb_transc *transc = &udev->dev.transc_in[0]; + + switch (req->bRequest) { + case BBB_GET_MAX_LUN : + if((0U == req->wValue) && + (1U == req->wLength) && + (0x80U == (req->bmRequestType & 0x80U))) { + usbd_msc_maxlun = (uint8_t)usbd_mem_fops->mem_maxlun(); + + transc->xfer_buf = &usbd_msc_maxlun; + transc->remain_len = 1U; + } else { + return USBD_FAIL; + } + break; + + case BBB_RESET : + if((0U == req->wValue) && + (0U == req->wLength) && + (0x80U != (req->bmRequestType & 0x80U))) { + msc_bbb_reset(udev); + } else { + return USBD_FAIL; + } + break; + + case USB_CLEAR_FEATURE: + msc_bbb_clrfeature (udev, (uint8_t)req->wIndex); + break; + + default: + return USBD_FAIL; + } + + return USBD_OK; +} + +/*! + \brief handle data in stage + \param[in] udev: pointer to USB device instance + \param[in] ep_num: the endpoint number + \param[out] none + \retval none +*/ +static uint8_t msc_core_in (usb_dev *udev, uint8_t ep_num) +{ + if ((MSC_IN_EP & 0x7FU) == ep_num) { + msc_bbb_data_in(udev, ep_num); + } + + return USBD_OK; +} + +/*! + \brief handle data out stage + \param[in] udev: pointer to USB device instance + \param[in] ep_num: the endpoint number + \param[out] none + \retval none +*/ +static uint8_t msc_core_out (usb_dev *udev, uint8_t ep_num) +{ + if (MSC_OUT_EP == ep_num) { + msc_bbb_data_out (udev, ep_num); + } + + return USBD_OK; +} diff --git a/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/device/class/msc/Source/usbd_msc_data.c b/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/device/class/msc/Source/usbd_msc_data.c new file mode 100644 index 0000000000..53a1afc626 --- /dev/null +++ b/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/device/class/msc/Source/usbd_msc_data.c @@ -0,0 +1,73 @@ +/*! + \file usbd_msc_data.c + \brief USB MSC vital inquiry pages and sense data + + \version 2020-08-01, V3.0.0, firmware for GD32F4xx +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "usbd_msc_data.h" + +/* USB mass storage page 0 inquiry data */ +const uint8_t msc_page00_inquiry_data[] = +{ + 0x00U, + 0x00U, + 0x00U, + 0x00U, + (INQUIRY_PAGE00_LENGTH - 4U), + 0x80U, + 0x83U, +}; + +/* USB mass storage sense 6 data */ +const uint8_t msc_mode_sense6_data[] = +{ + 0x00U, + 0x00U, + 0x00U, + 0x00U, + 0x00U, + 0x00U, + 0x00U, + 0x00U +}; + +/* USB mass storage sense 10 data */ +const uint8_t msc_mode_sense10_data[] = +{ + 0x00U, + 0x06U, + 0x00U, + 0x00U, + 0x00U, + 0x00U, + 0x00U, + 0x00U +}; diff --git a/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/device/class/msc/Source/usbd_msc_scsi.c b/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/device/class/msc/Source/usbd_msc_scsi.c new file mode 100644 index 0000000000..7afae6fa30 --- /dev/null +++ b/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/device/class/msc/Source/usbd_msc_scsi.c @@ -0,0 +1,685 @@ +/*! + \file usbd_msc_scsi.c + \brief USB SCSI layer functions + + \version 2020-08-01, V3.0.0, firmware for GD32F4xx +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ +#include "usbd_enum.h" +#include "usbd_msc_bbb.h" +#include "usbd_msc_scsi.h" +#include "usbd_msc_data.h" + +/* local function prototypes ('static') */ +static int8_t scsi_test_unit_ready (usb_core_driver *udev, uint8_t lun, uint8_t *params); +static int8_t scsi_inquiry (usb_core_driver *udev, uint8_t lun, uint8_t *params); +static int8_t scsi_read_format_capacity (usb_core_driver *udev, uint8_t lun, uint8_t *params); +static int8_t scsi_read_capacity10 (usb_core_driver *udev, uint8_t lun, uint8_t *params); +static int8_t scsi_request_sense (usb_core_driver *udev, uint8_t lun, uint8_t *params); +static int8_t scsi_mode_sense6 (usb_core_driver *udev, uint8_t lun, uint8_t *params); +static int8_t scsi_toc_cmd_read (usb_core_driver *udev, uint8_t lun, uint8_t *params); +static int8_t scsi_mode_sense10 (usb_core_driver *udev, uint8_t lun, uint8_t *params); +static int8_t scsi_write10 (usb_core_driver *udev, uint8_t lun, uint8_t *params); +static int8_t scsi_read10 (usb_core_driver *udev, uint8_t lun, uint8_t *params); +static int8_t scsi_verify10 (usb_core_driver *udev, uint8_t lun, uint8_t *params); + +static int8_t scsi_process_read (usb_core_driver *udev, uint8_t lun); +static int8_t scsi_process_write (usb_core_driver *udev, uint8_t lun); + +static inline int8_t scsi_check_address_range (usb_core_driver *udev, uint8_t lun, uint32_t blk_offset, uint16_t blk_nbr); +static inline int8_t scsi_format_cmd (usb_core_driver *udev, uint8_t lun); +static inline int8_t scsi_start_stop_unit (usb_core_driver *udev, uint8_t lun, uint8_t *params); +static inline int8_t scsi_allow_medium_removal (usb_core_driver *udev, uint8_t lun, uint8_t *params); + +/*! + \brief process SCSI commands + \param[in] udev: pointer to USB device instance + \param[in] lun: logical unit number + \param[in] params: command parameters + \param[out] none + \retval status +*/ +int8_t scsi_process_cmd(usb_core_driver *udev, uint8_t lun, uint8_t *params) +{ + switch (params[0]) { + case SCSI_TEST_UNIT_READY: + return scsi_test_unit_ready (udev, lun, params); + + case SCSI_REQUEST_SENSE: + return scsi_request_sense (udev, lun, params); + + case SCSI_INQUIRY: + return scsi_inquiry (udev, lun, params); + + case SCSI_START_STOP_UNIT: + return scsi_start_stop_unit (udev, lun, params); + + case SCSI_ALLOW_MEDIUM_REMOVAL: + return scsi_allow_medium_removal (udev, lun, params); + + case SCSI_MODE_SENSE6: + return scsi_mode_sense6 (udev, lun, params); + + case SCSI_MODE_SENSE10: + return scsi_mode_sense10 (udev, lun, params); + + case SCSI_READ_FORMAT_CAPACITIES: + return scsi_read_format_capacity (udev, lun, params); + + case SCSI_READ_CAPACITY10: + return scsi_read_capacity10 (udev, lun, params); + + case SCSI_READ10: + return scsi_read10 (udev, lun, params); + + case SCSI_WRITE10: + return scsi_write10 (udev, lun, params); + + case SCSI_VERIFY10: + return scsi_verify10 (udev, lun, params); + + case SCSI_FORMAT_UNIT: + return scsi_format_cmd (udev, lun); + + case SCSI_READ_TOC_DATA: + return scsi_toc_cmd_read (udev, lun, params); + + default: + scsi_sense_code (udev, lun, ILLEGAL_REQUEST, INVALID_CDB); + return -1; + } +} + +/*! + \brief load the last error code in the error list + \param[in] udev: pointer to USB device instance + \param[in] lun: logical unit number + \param[in] skey: sense key + \param[in] asc: additional sense key + \param[out] none + \retval none +*/ +void scsi_sense_code (usb_core_driver *udev, uint8_t lun, uint8_t skey, uint8_t asc) +{ + usbd_msc_handler *msc = (usbd_msc_handler *)udev->dev.class_data[USBD_MSC_INTERFACE]; + + msc->scsi_sense[msc->scsi_sense_tail].SenseKey = skey; + msc->scsi_sense[msc->scsi_sense_tail].ASC = asc << 8U; + msc->scsi_sense_tail++; + + if (SENSE_LIST_DEEPTH == msc->scsi_sense_tail) { + msc->scsi_sense_tail = 0U; + } +} + +/*! + \brief process SCSI Test Unit Ready command + \param[in] udev: pointer to USB device instance + \param[in] lun: logical unit number + \param[in] params: command parameters + \param[out] none + \retval status +*/ +static int8_t scsi_test_unit_ready (usb_core_driver *udev, uint8_t lun, uint8_t *params) +{ + usbd_msc_handler *msc = (usbd_msc_handler *)udev->dev.class_data[USBD_MSC_INTERFACE]; + + /* case 9 : Hi > D0 */ + if (0U != msc->bbb_cbw.dCBWDataTransferLength) { + scsi_sense_code (udev, msc->bbb_cbw.bCBWLUN, ILLEGAL_REQUEST, INVALID_CDB); + + return -1; + } + + if (0 != usbd_mem_fops->mem_ready(lun)) { + scsi_sense_code(udev, lun, NOT_READY, MEDIUM_NOT_PRESENT); + + return -1; + } + + if (1U == msc->scsi_disk_pop) { + usbd_disconnect (udev); + } + + msc->bbb_datalen = 0U; + + return 0; +} + +/*! + \brief process Inquiry command + \param[in] udev: pointer to USB device instance + \param[in] lun: logical unit number + \param[in] params: command parameters + \param[out] none + \retval status +*/ +static int8_t scsi_inquiry (usb_core_driver *udev, uint8_t lun, uint8_t *params) +{ + uint8_t *page = NULL; + uint16_t len = 0U; + + usbd_msc_handler *msc = (usbd_msc_handler *)udev->dev.class_data[USBD_MSC_INTERFACE]; + + if (params[1] & 0x01U) { + page = (uint8_t *)msc_page00_inquiry_data; + + len = INQUIRY_PAGE00_LENGTH; + } else { + page = (uint8_t *)usbd_mem_fops->mem_inquiry_data[lun]; + + len = (uint16_t)(page[4] + 5U); + + if (params[4] <= len) { + len = params[4]; + } + } + + msc->bbb_datalen = len; + + while (len) { + len--; + msc->bbb_data[len] = page[len]; + } + + return 0; +} + +/*! + \brief process Read Capacity 10 command + \param[in] udev: pointer to USB device instance + \param[in] lun: logical unit number + \param[in] params: command parameters + \param[out] none + \retval status +*/ +static int8_t scsi_read_capacity10 (usb_core_driver *udev, uint8_t lun, uint8_t *params) +{ + uint32_t blk_num = usbd_mem_fops->mem_block_len[lun] - 1U; + usbd_msc_handler *msc = (usbd_msc_handler *)udev->dev.class_data[USBD_MSC_INTERFACE]; + + msc->scsi_blk_nbr[lun] = usbd_mem_fops->mem_block_len[lun]; + msc->scsi_blk_size[lun] = usbd_mem_fops->mem_block_size[lun]; + + msc->bbb_data[0] = (uint8_t)(blk_num >> 24U); + msc->bbb_data[1] = (uint8_t)(blk_num >> 16U); + msc->bbb_data[2] = (uint8_t)(blk_num >> 8U); + msc->bbb_data[3] = (uint8_t)(blk_num); + + msc->bbb_data[4] = (uint8_t)(msc->scsi_blk_size[lun] >> 24U); + msc->bbb_data[5] = (uint8_t)(msc->scsi_blk_size[lun] >> 16U); + msc->bbb_data[6] = (uint8_t)(msc->scsi_blk_size[lun] >> 8U); + msc->bbb_data[7] = (uint8_t)(msc->scsi_blk_size[lun]); + + msc->bbb_datalen = 8U; + + return 0; +} + +/*! + \brief process Read Format Capacity command + \param[in] udev: pointer to USB device instance + \param[in] lun: logical unit number + \param[in] params: command parameters + \param[out] none + \retval status +*/ +static int8_t scsi_read_format_capacity (usb_core_driver *udev, uint8_t lun, uint8_t *params) +{ + uint16_t i = 0U; + uint32_t blk_size = usbd_mem_fops->mem_block_size[lun]; + uint32_t blk_num = usbd_mem_fops->mem_block_len[lun]; + uint32_t blk_nbr = blk_num - 1U; + + usbd_msc_handler *msc = (usbd_msc_handler *)udev->dev.class_data[USBD_MSC_INTERFACE]; + + for (i = 0U; i < 12U; i++) { + msc->bbb_data[i] = 0U; + } + + msc->bbb_data[3] = 0x08U; + msc->bbb_data[4] = (uint8_t)(blk_nbr >> 24U); + msc->bbb_data[5] = (uint8_t)(blk_nbr >> 16U); + msc->bbb_data[6] = (uint8_t)(blk_nbr >> 8U); + msc->bbb_data[7] = (uint8_t)(blk_nbr); + + msc->bbb_data[8] = 0x02U; + msc->bbb_data[9] = (uint8_t)(blk_size >> 16U); + msc->bbb_data[10] = (uint8_t)(blk_size >> 8U); + msc->bbb_data[11] = (uint8_t)(blk_size); + + msc->bbb_datalen = 12U; + + return 0; +} + +/*! + \brief process Mode Sense6 command + \param[in] udev: pointer to USB device instance + \param[in] lun: logical unit number + \param[in] params: command parameters + \param[out] none + \retval status +*/ +static int8_t scsi_mode_sense6 (usb_core_driver *udev, uint8_t lun, uint8_t *params) +{ + uint16_t len = 8U; + usbd_msc_handler *msc = (usbd_msc_handler *)udev->dev.class_data[USBD_MSC_INTERFACE]; + + msc->bbb_datalen = len; + + while (len) { + len--; + msc->bbb_data[len] = msc_mode_sense6_data[len]; + } + + return 0; +} + +/*! + \brief process Mode Sense10 command + \param[in] udev: pointer to USB device instance + \param[in] lun: logical unit number + \param[in] params: command parameters + \param[out] none + \retval status +*/ +static int8_t scsi_mode_sense10 (usb_core_driver *udev, uint8_t lun, uint8_t *params) +{ + uint16_t len = 8U; + usbd_msc_handler *msc = (usbd_msc_handler *)udev->dev.class_data[USBD_MSC_INTERFACE]; + + msc->bbb_datalen = len; + + while (len) { + len--; + msc->bbb_data[len] = msc_mode_sense10_data[len]; + } + + return 0; +} + +/*! + \brief process Request Sense command + \param[in] udev: pointer to USB device instance + \param[in] lun: logical unit number + \param[in] params: command parameters + \param[out] none + \retval status +*/ +static int8_t scsi_request_sense (usb_core_driver *udev, uint8_t lun, uint8_t *params) +{ + uint8_t i = 0U; + usbd_msc_handler *msc = (usbd_msc_handler *)udev->dev.class_data[USBD_MSC_INTERFACE]; + + for (i = 0U; i < REQUEST_SENSE_DATA_LEN; i++) { + msc->bbb_data[i] = 0U; + } + + msc->bbb_data[0] = 0x70U; + msc->bbb_data[7] = REQUEST_SENSE_DATA_LEN - 6U; + + if ((msc->scsi_sense_head != msc->scsi_sense_tail)) { + msc->bbb_data[2] = msc->scsi_sense[msc->scsi_sense_head].SenseKey; + msc->bbb_data[12] = msc->scsi_sense[msc->scsi_sense_head].ASCQ; + msc->bbb_data[13] = msc->scsi_sense[msc->scsi_sense_head].ASC; + msc->scsi_sense_head++; + + if (msc->scsi_sense_head == SENSE_LIST_DEEPTH) { + msc->scsi_sense_head = 0U; + } + } + + msc->bbb_datalen = USB_MIN(REQUEST_SENSE_DATA_LEN, params[4]); + + return 0; +} + +/*! + \brief process Start Stop Unit command + \param[in] udev: pointer to USB device instance + \param[in] lun: logical unit number + \param[in] params: command parameters + \param[out] none + \retval status +*/ +static inline int8_t scsi_start_stop_unit (usb_core_driver *udev, uint8_t lun, uint8_t *params) +{ + usbd_msc_handler *msc = (usbd_msc_handler *)udev->dev.class_data[USBD_MSC_INTERFACE]; + + msc->bbb_datalen = 0U; + msc->scsi_disk_pop = 1U; + + return 0; +} + +/*! + \brief process Allow Medium Removal command + \param[in] udev: pointer to USB device instance + \param[in] lun: logical unit number + \param[in] params: command parameters + \param[out] none + \retval status +*/ +static inline int8_t scsi_allow_medium_removal (usb_core_driver *udev, uint8_t lun, uint8_t *params) +{ + usbd_msc_handler *msc = (usbd_msc_handler *)udev->dev.class_data[USBD_MSC_INTERFACE]; + + msc->bbb_datalen = 0U; + + return 0; +} + +/*! + \brief process Read10 command + \param[in] udev: pointer to USB device instance + \param[in] lun: logical unit number + \param[in] params: command parameters + \param[out] none + \retval status +*/ +static int8_t scsi_read10 (usb_core_driver *udev, uint8_t lun, uint8_t *params) +{ + usbd_msc_handler *msc = (usbd_msc_handler *)udev->dev.class_data[USBD_MSC_INTERFACE]; + + if (msc->bbb_state == BBB_IDLE) { + /* direction is from device to host */ + if (0x80U != (msc->bbb_cbw.bmCBWFlags & 0x80U)) { + scsi_sense_code (udev, msc->bbb_cbw.bCBWLUN, ILLEGAL_REQUEST, INVALID_CDB); + + return -1; + } + + if (0 != usbd_mem_fops->mem_ready(lun)) { + scsi_sense_code (udev, lun, NOT_READY, MEDIUM_NOT_PRESENT); + + return -1; + } + + msc->scsi_blk_addr = (params[2] << 24U) | (params[3] << 16U) | \ + (params[4] << 8U) | params[5]; + + msc->scsi_blk_len = (params[7] << 8U) | params[8]; + + if (scsi_check_address_range (udev, lun, msc->scsi_blk_addr, (uint16_t)msc->scsi_blk_len) < 0) { + return -1; /* error */ + } + + msc->bbb_state = BBB_DATA_IN; + + msc->scsi_blk_addr *= msc->scsi_blk_size[lun]; + msc->scsi_blk_len *= msc->scsi_blk_size[lun]; + + /* cases 4,5 : Hi <> Dn */ + if (msc->bbb_cbw.dCBWDataTransferLength != msc->scsi_blk_len) { + scsi_sense_code (udev, msc->bbb_cbw.bCBWLUN, ILLEGAL_REQUEST, INVALID_CDB); + + return -1; + } + } + + msc->bbb_datalen = MSC_MEDIA_PACKET_SIZE; + + return scsi_process_read (udev, lun); +} + +/*! + \brief process Write10 command + \param[in] udev: pointer to USB device instance + \param[in] lun: logical unit number + \param[in] params: command parameters + \param[out] none + \retval status +*/ +static int8_t scsi_write10 (usb_core_driver *udev, uint8_t lun, uint8_t *params) +{ + usbd_msc_handler *msc = (usbd_msc_handler *)udev->dev.class_data[USBD_MSC_INTERFACE]; + + if (BBB_IDLE == msc->bbb_state) { + /* case 8 : Hi <> Do */ + if (0x80U == (msc->bbb_cbw.bmCBWFlags & 0x80U)) { + scsi_sense_code (udev, msc->bbb_cbw.bCBWLUN, ILLEGAL_REQUEST, INVALID_CDB); + + return -1; + } + + /* check whether media is ready */ + if (0 != usbd_mem_fops->mem_ready(lun)) { + scsi_sense_code (udev, lun, NOT_READY, MEDIUM_NOT_PRESENT); + + return -1; + } + + /* check if media is write-protected */ + if (0 != usbd_mem_fops->mem_protected(lun)) { + scsi_sense_code (udev, lun, NOT_READY, WRITE_PROTECTED); + + return -1; + } + + msc->scsi_blk_addr = (params[2] << 24U) | (params[3] << 16U) | \ + (params[4] << 8U) | params[5]; + + msc->scsi_blk_len = (params[7] << 8U) | params[8]; + + /* check if LBA address is in the right range */ + if (scsi_check_address_range (udev, lun, msc->scsi_blk_addr, (uint16_t)msc->scsi_blk_len) < 0) { + return -1; /* error */ + } + + msc->scsi_blk_addr *= msc->scsi_blk_size[lun]; + msc->scsi_blk_len *= msc->scsi_blk_size[lun]; + + /* cases 3,11,13 : Hn,Ho <> D0 */ + if (msc->bbb_cbw.dCBWDataTransferLength != msc->scsi_blk_len) { + scsi_sense_code (udev, msc->bbb_cbw.bCBWLUN, ILLEGAL_REQUEST, INVALID_CDB); + + return -1; + } + + /* prepare endpoint to receive first data packet */ + msc->bbb_state = BBB_DATA_OUT; + + usbd_ep_recev (udev, + MSC_OUT_EP, + msc->bbb_data, + USB_MIN (msc->scsi_blk_len, MSC_MEDIA_PACKET_SIZE)); + } else { /* write process ongoing */ + return scsi_process_write (udev, lun); + } + + return 0; +} + +/*! + \brief process Verify10 command + \param[in] udev: pointer to USB device instance + \param[in] lun: logical unit number + \param[in] params: command parameters + \param[out] none + \retval status +*/ +static int8_t scsi_verify10 (usb_core_driver *udev, uint8_t lun, uint8_t *params) +{ + usbd_msc_handler *msc = (usbd_msc_handler *)udev->dev.class_data[USBD_MSC_INTERFACE]; + + if (0x02U == (params[1] & 0x02U)) { + scsi_sense_code (udev, lun, ILLEGAL_REQUEST, INVALID_FIELED_IN_COMMAND); + + return -1; /* error, verify mode not supported*/ + } + + if (scsi_check_address_range (udev, lun, msc->scsi_blk_addr, (uint16_t)msc->scsi_blk_len) < 0) { + return -1; /* error */ + } + + msc->bbb_datalen = 0U; + + return 0; +} + +/*! + \brief check address range + \param[in] udev: pointer to USB device instance + \param[in] lun: logical unit number + \param[in] blk_offset: block offset + \param[in] blk_nbr: number of block to be processed + \param[out] none + \retval status +*/ +static inline int8_t scsi_check_address_range (usb_core_driver *udev, uint8_t lun, uint32_t blk_offset, uint16_t blk_nbr) +{ + usbd_msc_handler *msc = (usbd_msc_handler *)udev->dev.class_data[USBD_MSC_INTERFACE]; + + if ((blk_offset + blk_nbr) > msc->scsi_blk_nbr[lun]) { + scsi_sense_code (udev, lun, ILLEGAL_REQUEST, ADDRESS_OUT_OF_RANGE); + + return -1; + } + + return 0; +} + +/*! + \brief handle read process + \param[in] udev: pointer to USB device instance + \param[in] lun: logical unit number + \param[out] none + \retval status +*/ +static int8_t scsi_process_read (usb_core_driver *udev, uint8_t lun) +{ + usbd_msc_handler *msc = (usbd_msc_handler *)udev->dev.class_data[USBD_MSC_INTERFACE]; + + uint32_t len = USB_MIN(msc->scsi_blk_len, MSC_MEDIA_PACKET_SIZE); + + if (usbd_mem_fops->mem_read(lun, + msc->bbb_data, + msc->scsi_blk_addr, + (uint16_t)(len / msc->scsi_blk_size[lun])) < 0) { + scsi_sense_code(udev, lun, HARDWARE_ERROR, UNRECOVERED_READ_ERROR); + + return -1; + } + + usbd_ep_send (udev, MSC_IN_EP, msc->bbb_data, len); + + msc->scsi_blk_addr += len; + msc->scsi_blk_len -= len; + + /* case 6 : Hi = Di */ + msc->bbb_csw.dCSWDataResidue -= len; + + if (0U == msc->scsi_blk_len) { + msc->bbb_state = BBB_LAST_DATA_IN; + } + + return 0; +} + +/*! + \brief handle write process + \param[in] udev: pointer to USB device instance + \param[in] lun: logical unit number + \param[out] none + \retval status +*/ +static int8_t scsi_process_write (usb_core_driver *udev, uint8_t lun) +{ + usbd_msc_handler *msc = (usbd_msc_handler *)udev->dev.class_data[USBD_MSC_INTERFACE]; + + uint32_t len = USB_MIN(msc->scsi_blk_len, MSC_MEDIA_PACKET_SIZE); + + if (usbd_mem_fops->mem_write (lun, + msc->bbb_data, + msc->scsi_blk_addr, + (uint16_t)(len / msc->scsi_blk_size[lun])) < 0) { + scsi_sense_code(udev, lun, HARDWARE_ERROR, WRITE_FAULT); + + return -1; + } + + msc->scsi_blk_addr += len; + msc->scsi_blk_len -= len; + + /* case 12 : Ho = Do */ + msc->bbb_csw.dCSWDataResidue -= len; + + if (0U == msc->scsi_blk_len) { + msc_bbb_csw_send (udev, CSW_CMD_PASSED); + } else { + /* prepare endpoint to receive next packet */ + usbd_ep_recev (udev, + MSC_OUT_EP, + msc->bbb_data, + USB_MIN (msc->scsi_blk_len, MSC_MEDIA_PACKET_SIZE)); + } + + return 0; +} + +/*! + \brief process Format Unit command + \param[in] udev: pointer to USB device instance + \param[in] lun: logical unit number + \param[out] none + \retval status +*/ +static inline int8_t scsi_format_cmd (usb_core_driver *udev, uint8_t lun) +{ + return 0; +} + +/*! + \brief process Read_Toc command + \param[in] udev: pointer to USB device instance + \param[in] lun: logical unit number + \param[in] params: command parameters + \param[out] none + \retval status +*/ +static int8_t scsi_toc_cmd_read (usb_core_driver *udev, uint8_t lun, uint8_t *params) +{ + uint8_t* pPage; + uint16_t len; + + usbd_msc_handler *msc = (usbd_msc_handler *)udev->dev.class_data[USBD_MSC_INTERFACE]; + + pPage = (uint8_t *)&usbd_mem_fops->mem_toc_data[lun * READ_TOC_CMD_LEN]; + len = (uint16_t)pPage[1] + 2U; + + msc->bbb_datalen = len; + + while (len) { + len--; + msc->bbb_data[len] = pPage[len]; + } + + return 0; +} diff --git a/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/device/class/printer/Include/printer_core.h b/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/device/class/printer/Include/printer_core.h new file mode 100644 index 0000000000..88c933ac94 --- /dev/null +++ b/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/device/class/printer/Include/printer_core.h @@ -0,0 +1,78 @@ +/*! + \file printer_core.h + \brief the header file of USB printer device class core functions + + \version 2020-08-01, V3.0.0, firmware for GD32F4xx +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef __PRINTER_CORE_H +#define __PRINTER_CORE_H + +#include "usbd_enum.h" +#include "usb_ch9_std.h" + +/* USB printing device class code */ +#define USB_CLASS_PRINTER 0x07U + +/* printing device subclass code */ +#define USB_SUBCLASS_PRINTER 0x01U + +/* printing device protocol code */ +#define PROTOCOL_UNIDIRECTIONAL_ITF 0x01U +#define PROTOCOL_BI_DIRECTIONAL_ITF 0x02U +#define PROTOCOL_1284_4_ITF 0x03U +#define PROTOCOL_VENDOR 0xFFU + +#define DEVICE_ID_LEN 103U + +#define USB_PRINTER_CONFIG_DESC_LEN 32U + +/* printing device specific-class request */ +#define GET_DEVICE_ID 0x00U +#define GET_PORT_STATUS 0x01U +#define SOFT_RESET 0x02U + +#pragma pack(1) + +/* USB configuration descriptor structure */ +typedef struct +{ + usb_desc_config config; + usb_desc_itf printer_itf; + usb_desc_ep printer_epin; + usb_desc_ep printer_epout; +} usb_printer_desc_config_set; + +#pragma pack() + +extern usb_desc printer_desc; +extern usb_class_core usbd_printer_cb; + +#endif /* __PRINTER_CORE_H */ diff --git a/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/device/class/printer/Source/printer_core.c b/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/device/class/printer/Source/printer_core.c new file mode 100644 index 0000000000..71818f03b9 --- /dev/null +++ b/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/device/class/printer/Source/printer_core.c @@ -0,0 +1,310 @@ +/*! + \file printer_core.c + \brief USB printer device class core functions + + \version 2020-08-01, V3.0.0, firmware for GD32F4xx +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "printer_core.h" + +#define USBD_VID 0x28E9U +#define USBD_PID 0x028DU + +/* printer port status: paper not empty/selected/no error */ +static uint8_t g_port_status = 0x18U; + +uint8_t g_printer_data_buf[PRINTER_OUT_PACKET]; + +__ALIGN_BEGIN uint8_t PRINTER_DEVICE_ID[DEVICE_ID_LEN] __ALIGN_END = +{ + 0x00, 0x67, + 'M', 'A', 'N', 'U', 'F', 'A', 'C', 'T', 'U', 'R', 'E', 'R', ':', + 'G', 'I', 'G', 'A', ' ', 'D', 'E', 'V', 'I', 'C', 'E', '-', ';', + 'C', 'O', 'M', 'M', 'A', 'N', 'D', ' ', 'S', 'E', 'T', ':', + 'P', 'C', 'L', ',', 'M', 'P', 'L', ';', + 'M', 'O', 'D', 'E', 'L', ':', + 'L', 'a', 's', 'e', 'r', 'B', 'e', 'a', 'm', '?', ';', + 'C', 'O', 'M', 'M', 'E', 'N', 'T', ':', + 'G', 'o', 'o', 'd', ' ', '!', ';', + 'A', 'C', 'T', 'I', 'V', 'E', ' ', 'C', 'O', 'M', 'M', 'A', 'N', 'D', ' ', 'S', 'E', 'T', ':', + 'P', 'C', 'L', ';' +}; + +/* USB standard device descriptor */ +__ALIGN_BEGIN const usb_desc_dev printer_dev_desc __ALIGN_END = +{ + .header = + { + .bLength = USB_DEV_DESC_LEN, + .bDescriptorType = USB_DESCTYPE_DEV, + }, + .bcdUSB = 0x0200U, + .bDeviceClass = 0x00U, + .bDeviceSubClass = 0x00U, + .bDeviceProtocol = 0x00U, + .bMaxPacketSize0 = USB_FS_EP0_MAX_LEN, + .idVendor = USBD_VID, + .idProduct = USBD_PID, + .bcdDevice = 0x0100U, + .iManufacturer = STR_IDX_MFC, + .iProduct = STR_IDX_PRODUCT, + .iSerialNumber = STR_IDX_SERIAL, + .bNumberConfigurations = USBD_CFG_MAX_NUM, +}; + +/* USB device configuration descriptor */ +__ALIGN_BEGIN const usb_printer_desc_config_set printer_config_desc __ALIGN_END = +{ + .config = + { + .header = + { + .bLength = sizeof(usb_desc_config), + .bDescriptorType = USB_DESCTYPE_CONFIG + }, + .wTotalLength = USB_PRINTER_CONFIG_DESC_LEN, + .bNumInterfaces = 0x01U, + .bConfigurationValue = 0x01U, + .iConfiguration = 0x00U, + .bmAttributes = 0xA0U, + .bMaxPower = 0x32U + }, + + .printer_itf = + { + .header = + { + .bLength = sizeof(usb_desc_itf), + .bDescriptorType = USB_DESCTYPE_ITF + }, + .bInterfaceNumber = 0x00U, + .bAlternateSetting = 0x00U, + .bNumEndpoints = 0x02U, + .bInterfaceClass = USB_CLASS_PRINTER, + .bInterfaceSubClass = USB_SUBCLASS_PRINTER, + .bInterfaceProtocol = PROTOCOL_BI_DIRECTIONAL_ITF, + .iInterface = 0x00U + }, + + .printer_epin = + { + .header = + { + .bLength = sizeof(usb_desc_ep), + .bDescriptorType = USB_DESCTYPE_EP + }, + .bEndpointAddress = PRINTER_IN_EP, + .bmAttributes = USB_EP_ATTR_BULK, + .wMaxPacketSize = PRINTER_IN_PACKET, + .bInterval = 0x00U + }, + + .printer_epout = + { + .header = + { + .bLength = sizeof(usb_desc_ep), + .bDescriptorType = USB_DESCTYPE_EP + }, + .bEndpointAddress = PRINTER_OUT_EP, + .bmAttributes = USB_EP_ATTR_BULK, + .wMaxPacketSize = PRINTER_OUT_PACKET, + .bInterval = 0x00U + }, +}; + +/* USB language ID Descriptor */ +static __ALIGN_BEGIN const usb_desc_LANGID usbd_language_id_desc __ALIGN_END = +{ + .header = + { + .bLength = sizeof(usb_desc_LANGID), + .bDescriptorType = USB_DESCTYPE_STR, + }, + .wLANGID = ENG_LANGID +}; + +/* USB manufacture string */ +static __ALIGN_BEGIN const usb_desc_str manufacturer_string __ALIGN_END = +{ + .header = + { + .bLength = USB_STRING_LEN(10U), + .bDescriptorType = USB_DESCTYPE_STR, + }, + .unicode_string = {'G', 'i', 'g', 'a', 'D', 'e', 'v', 'i', 'c', 'e'} +}; + +/* USB product string */ +static __ALIGN_BEGIN const usb_desc_str product_string __ALIGN_END = +{ + .header = + { + .bLength = USB_STRING_LEN(16U), + .bDescriptorType = USB_DESCTYPE_STR, + }, + .unicode_string = {'G', 'D', '3', '2', '-', 'U', 'S', 'B', '_', 'P', 'r', 'i', 'n', 't', 'e', 'r'} +}; + +/* USBD serial string */ +static __ALIGN_BEGIN usb_desc_str serial_string __ALIGN_END = +{ + .header = + { + .bLength = USB_STRING_LEN(12U), + .bDescriptorType = USB_DESCTYPE_STR, + } +}; + +/* USB string descriptor */ +static void *const usbd_msc_strings[] = +{ + [STR_IDX_LANGID] = (uint8_t *)&usbd_language_id_desc, + [STR_IDX_MFC] = (uint8_t *)&manufacturer_string, + [STR_IDX_PRODUCT] = (uint8_t *)&product_string, + [STR_IDX_SERIAL] = (uint8_t *)&serial_string +}; + +usb_desc printer_desc = { + .dev_desc = (uint8_t *)&printer_dev_desc, + .config_desc = (uint8_t *)&printer_config_desc, + .strings = usbd_msc_strings +}; + +/* local function prototypes ('static') */ +static uint8_t printer_init (usb_dev *udev, uint8_t config_index); +static uint8_t printer_deinit (usb_dev *udev, uint8_t config_index); +static uint8_t printer_req (usb_dev *udev, usb_req *req); +static uint8_t printer_in (usb_dev *udev, uint8_t ep_num); +static uint8_t printer_out (usb_dev *udev, uint8_t ep_num); + +usb_class_core usbd_printer_cb = { + .init = printer_init, + .deinit = printer_deinit, + + .req_proc = printer_req, + + .data_in = printer_in, + .data_out = printer_out +}; + +/*! + \brief initialize the printer device + \param[in] udev: pointer to USB device instance + \param[in] config_index: configuration index + \param[out] none + \retval USB device operation status +*/ +static uint8_t printer_init (usb_dev *udev, uint8_t config_index) +{ + /* initialize the data TX endpoint */ + usbd_ep_setup (udev, &(printer_config_desc.printer_epin)); + + /* initialize the data RX endpoint */ + usbd_ep_setup (udev, &(printer_config_desc.printer_epout)); + + /* prepare to receive data */ + usbd_ep_recev(udev, PRINTER_OUT_EP, g_printer_data_buf, PRINTER_OUT_PACKET); + + return USBD_OK; +} + +/*! + \brief deinitialize the printer device + \param[in] udev: pointer to USB device instance + \param[in] config_index: configuration index + \param[out] none + \retval USB device operation status +*/ +static uint8_t printer_deinit (usb_dev *udev, uint8_t config_index) +{ + /* deinitialize the data TX/RX endpoint */ + usbd_ep_clear (udev, PRINTER_IN_EP); + usbd_ep_clear (udev, PRINTER_OUT_EP); + + return USBD_OK; +} + +/*! + \brief handle the printer class-specific requests + \param[in] udev: pointer to USB device instance + \param[in] req: device class-specific request + \param[out] none + \retval USB device operation status +*/ +static uint8_t printer_req(usb_dev *udev, usb_req *req) +{ + usb_transc *transc = &udev->dev.transc_in[0]; + + switch (req->bRequest) { + case GET_DEVICE_ID: + transc->xfer_buf = (uint8_t *)PRINTER_DEVICE_ID; + transc->remain_len = DEVICE_ID_LEN; + break; + + case GET_PORT_STATUS: + transc->xfer_buf = (uint8_t *)&g_port_status; + transc->remain_len = 1U; + break; + + case SOFT_RESET: + usbd_ep_recev(udev, PRINTER_OUT_EP, g_printer_data_buf, PRINTER_OUT_PACKET); + break; + + default: + return USBD_FAIL; + } + + return USBD_OK; +} + +/*! + \brief handle printer data + \param[in] udev: pointer to USB device instance + \param[in] ep_num: endpoint number + \param[out] none + \retval USB device operation status +*/ +static uint8_t printer_in (usb_dev *udev, uint8_t ep_num) +{ + return USBD_OK; +} + +/*! + \brief handle printer data + \param[in] udev: pointer to USB device instance + \param[in] ep_num: endpoint number + \param[out] none + \retval USB device operation status +*/ +static uint8_t printer_out (usb_dev *udev, uint8_t ep_num) +{ + return USBD_OK; +} diff --git a/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/device/core/Include/usbd_core.h b/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/device/core/Include/usbd_core.h new file mode 100644 index 0000000000..8446487b1d --- /dev/null +++ b/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/device/core/Include/usbd_core.h @@ -0,0 +1,103 @@ +/*! + \file usbd_core.h + \brief USB device mode core functions protype + + \version 2020-08-01, V3.0.0, firmware for GD32F4xx +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef __USBD_CORE_H +#define __USBD_CORE_H + +#include "drv_usb_core.h" +#include "drv_usb_dev.h" + +typedef enum +{ + USBD_OK = 0U, /*!< status OK */ + USBD_BUSY, /*!< status busy */ + USBD_FAIL, /*!< status fail */ +} usbd_status; + +enum _usbd_status { + USBD_DEFAULT = 1U, /*!< default status */ + USBD_ADDRESSED = 2U, /*!< address send status */ + USBD_CONFIGURED = 3U, /*!< configured status */ + USBD_SUSPENDED = 4U /*!< suspended status */ +}; + +/* static inline function definitions */ + +/*! + \brief set USB device address + \param[in] udev: pointer to USB core instance + \param[in] addr: device address to set + \param[out] none + \retval none +*/ +__STATIC_INLINE void usbd_addr_set (usb_core_driver *udev, uint8_t addr) +{ + usb_devaddr_set(udev, addr); +} + +/*! + \brief get the received data length + \param[in] udev: pointer to USB device instance + \param[in] ep_num: endpoint number + \param[out] none + \retval USB device operation cur_status +*/ +__STATIC_INLINE uint16_t usbd_rxcount_get (usb_core_driver *udev, uint8_t ep_num) +{ + return (uint16_t)udev->dev.transc_out[ep_num].xfer_count; +} + +/* function declarations */ +/* initializes the USB device-mode stack and load the class driver */ +void usbd_init (usb_core_driver *udev, usb_core_enum core, usb_desc *desc, usb_class_core *class_core); +/* endpoint initialization */ +uint32_t usbd_ep_setup (usb_core_driver *udev, const usb_desc_ep *ep_desc); +/* configure the endpoint when it is disabled */ +uint32_t usbd_ep_clear (usb_core_driver *udev, uint8_t ep_addr); +/* endpoint prepare to receive data */ +uint32_t usbd_ep_recev (usb_core_driver *udev, uint8_t ep_addr, uint8_t *pbuf, uint32_t len); +/* endpoint prepare to transmit data */ +uint32_t usbd_ep_send (usb_core_driver *udev, uint8_t ep_addr, uint8_t *pbuf, uint32_t len); +/* set an endpoint to STALL status */ +uint32_t usbd_ep_stall (usb_core_driver *udev, uint8_t ep_addr); +/* clear endpoint STALLed status */ +uint32_t usbd_ep_stall_clear (usb_core_driver *udev, uint8_t ep_addr); +/* flush the endpoint FIFOs */ +uint32_t usbd_fifo_flush (usb_core_driver *udev, uint8_t ep_addr); +/* device connect */ +void usbd_connect (usb_core_driver *udev); +/* device disconnect */ +void usbd_disconnect (usb_core_driver *udev); + +#endif /* __USBD_CORE_H */ diff --git a/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/device/core/Include/usbd_enum.h b/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/device/core/Include/usbd_enum.h new file mode 100644 index 0000000000..ffa7f0ca93 --- /dev/null +++ b/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/device/core/Include/usbd_enum.h @@ -0,0 +1,105 @@ +/*! + \file usbd_enum.h + \brief USB enumeration definitions + + \version 2020-08-01, V3.0.0, firmware for GD32F4xx +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef __USBD_ENUM_H +#define __USBD_ENUM_H + +#include "usbd_core.h" +#include "usbd_conf.h" +#include + +#ifndef NULL + #define NULL 0U +#endif + +typedef enum _usb_reqsta { + REQ_SUPP = 0x0U, /* request support */ + REQ_NOTSUPP = 0x1U, /* request not support */ +} usb_reqsta; + +/* string descriptor index */ +enum _str_index +{ + STR_IDX_LANGID = 0x0U, /* language ID string index */ + STR_IDX_MFC = 0x1U, /* manufacturer string index */ + STR_IDX_PRODUCT = 0x2U, /* product string index */ + STR_IDX_SERIAL = 0x3U, /* serial string index */ + STR_IDX_CONFIG = 0x4U, /* configuration string index */ + STR_IDX_ITF = 0x5U, /* interface string index */ +#ifndef WINUSB_EXEMPT_DRIVER + STR_IDX_MAX = 0x6U, /* string maximum index */ +#else + STR_IDX_MAX = 0xEFU, /* string maximum index */ +#endif /* WINUSB_EXEMPT_DRIVER */ +}; + +typedef enum _usb_pwrsta { + USB_PWRSTA_SELF_POWERED = 0x1U, /* USB is in self powered status */ + USB_PWRSTA_REMOTE_WAKEUP = 0x2U, /* USB is in remote wakeup status */ +} usb_pwrsta; + +typedef enum _usb_feature +{ + USB_FEATURE_EP_HALT = 0x0U, /* USB has endpoint halt feature */ + USB_FEATURE_REMOTE_WAKEUP = 0x1U, /* USB has endpoint remote wakeup feature */ + USB_FEATURE_TEST_MODE = 0x2U, /* USB has endpoint test mode feature */ +} usb_feature; + +#define ENG_LANGID 0x0409U /* english language ID */ +#define CHN_LANGID 0x0804U /* chinese language ID */ + +/* USB device exported macros */ +#define CTL_EP(ep) (((ep) == 0x00U) || ((ep) == 0x80U)) + +#define DEVICE_ID1 (0x1FFF7A10U) /* device ID1 */ +#define DEVICE_ID2 (0x1FFF7A14U) /* device ID2 */ +#define DEVICE_ID3 (0x1FFF7A18U) /* device ID3 */ + +#define DEVICE_ID (0x40023D00U) + +/* function declarations */ +/* handle USB standard device request */ +usb_reqsta usbd_standard_request (usb_core_driver *udev, usb_req *req); +/* handle USB device class request */ +usb_reqsta usbd_class_request (usb_core_driver *udev, usb_req *req); +/* handle USB vendor request */ +usb_reqsta usbd_vendor_request (usb_core_driver *udev, usb_req *req); +/* handle USB enumeration error */ +void usbd_enum_error (usb_core_driver *udev, usb_req *req); +/* convert hex 32bits value into unicode char */ +void int_to_unicode (uint32_t value, uint8_t *pbuf, uint8_t len); +/* get serial string */ +void serial_string_get (uint16_t *unicode_str); + +#endif /* __USBD_ENUM_H */ diff --git a/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/device/core/Include/usbd_transc.h b/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/device/core/Include/usbd_transc.h new file mode 100644 index 0000000000..014ea34aee --- /dev/null +++ b/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/device/core/Include/usbd_transc.h @@ -0,0 +1,56 @@ +/*! + \file usbd_transc.h + \brief USB transaction core functions prototype + + \version 2020-08-01, V3.0.0, firmware for GD32F4xx +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef __USBD_TRANSC_H +#define __USBD_TRANSC_H + +#include "usbd_core.h" + +/* function declarations */ +/* USB send data in the control transaction */ +usbd_status usbd_ctl_send (usb_core_driver *udev); +/* USB receive data in control transaction */ +usbd_status usbd_ctl_recev (usb_core_driver *udev); +/* USB send control transaction status */ +usbd_status usbd_ctl_status_send (usb_core_driver *udev); +/* USB control receive status */ +usbd_status usbd_ctl_status_recev (usb_core_driver *udev); +/* USB setup stage processing */ +uint8_t usbd_setup_transc (usb_core_driver *udev); +/* data out stage processing */ +uint8_t usbd_out_transc (usb_core_driver *udev, uint8_t ep_num); +/* data in stage processing */ +uint8_t usbd_in_transc (usb_core_driver *udev, uint8_t ep_num); + +#endif /* __USBD_TRANSC_H */ diff --git a/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/device/core/Source/usbd_core.c b/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/device/core/Source/usbd_core.c new file mode 100644 index 0000000000..065dd3ad15 --- /dev/null +++ b/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/device/core/Source/usbd_core.c @@ -0,0 +1,320 @@ +/*! + \file usbd_core.c + \brief USB device mode core functions + + \version 2020-08-01, V3.0.0, firmware for GD32F4xx +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "usbd_core.h" +#include "usbd_enum.h" +#include "drv_usb_hw.h" + +/* endpoint type */ +const uint32_t ep_type[] = { + [USB_EP_ATTR_CTL] = (uint32_t)USB_EPTYPE_CTRL, + [USB_EP_ATTR_BULK] = (uint32_t)USB_EPTYPE_BULK, + [USB_EP_ATTR_INT] = (uint32_t)USB_EPTYPE_INTR, + [USB_EP_ATTR_ISO] = (uint32_t)USB_EPTYPE_ISOC +}; + +/*! + \brief initializes the USB device-mode stack and load the class driver + \param[in] udev: pointer to USB core instance + \param[in] core: USB core type + \param[in] desc: pointer to USB descriptor + \param[in] class_core: class driver + \param[out] none + \retval none +*/ +void usbd_init (usb_core_driver *udev, usb_core_enum core, usb_desc *desc, usb_class_core *class_core) +{ + udev->dev.desc = desc; + + /* class callbacks */ + udev->dev.class_core = class_core; + + /* create serial string */ + serial_string_get(udev->dev.desc->strings[STR_IDX_SERIAL]); + + /* configure USB capabilities */ + (void)usb_basic_init (&udev->bp, &udev->regs, core); + + usb_globalint_disable(&udev->regs); + + /* initializes the USB core*/ + (void)usb_core_init (udev->bp, &udev->regs); + + /* set device disconnect */ + usbd_disconnect (udev); + +#ifndef USE_OTG_MODE + usb_curmode_set(&udev->regs, DEVICE_MODE); +#endif + + /* initializes device mode */ + (void)usb_devcore_init (udev); + + usb_globalint_enable(&udev->regs); + + /* set device connect */ + usbd_connect (udev); + + udev->dev.cur_status = (uint8_t)USBD_DEFAULT; +} + +/*! + \brief endpoint initialization + \param[in] udev: pointer to USB core instance + \param[in] ep_desc: pointer to endpoint descriptor + \param[out] none + \retval none +*/ +uint32_t usbd_ep_setup (usb_core_driver *udev, const usb_desc_ep *ep_desc) +{ + usb_transc *transc; + + uint8_t ep_addr = ep_desc->bEndpointAddress; + uint16_t max_len = ep_desc->wMaxPacketSize; + + /* set endpoint direction */ + if (EP_DIR(ep_addr)) { + transc = &udev->dev.transc_in[EP_ID(ep_addr)]; + + transc->ep_addr.dir = 1U; + } else { + transc = &udev->dev.transc_out[ep_addr]; + + transc->ep_addr.dir = 0U; + } + + transc->ep_addr.num = EP_ID(ep_addr); + transc->max_len = max_len; + transc->ep_type = (uint8_t)ep_type[ep_desc->bmAttributes & (uint8_t)USB_EPTYPE_MASK]; + + /* active USB endpoint function */ + (void)usb_transc_active (udev, transc); + + return 0U; +} + +/*! + \brief configure the endpoint when it is disabled + \param[in] udev: pointer to USB core instance + \param[in] ep_addr: endpoint address + in this parameter: + bit0..bit6: endpoint number (0..7) + bit7: endpoint direction which can be IN(1) or OUT(0) + \param[out] none + \retval none +*/ +uint32_t usbd_ep_clear (usb_core_driver *udev, uint8_t ep_addr) +{ + usb_transc *transc; + + if (EP_DIR(ep_addr)) { + transc = &udev->dev.transc_in[EP_ID(ep_addr)]; + } else { + transc = &udev->dev.transc_out[ep_addr]; + } + + /* deactivate USB endpoint function */ + (void)usb_transc_deactivate (udev, transc); + + return 0U; +} + +/*! + \brief endpoint prepare to receive data + \param[in] udev: pointer to USB core instance + \param[in] ep_addr: endpoint address + in this parameter: + bit0..bit6: endpoint number (0..7) + bit7: endpoint direction which can be IN(1) or OUT(0) + \param[in] pbuf: user buffer address pointer + \param[in] len: buffer length + \param[out] none + \retval none +*/ +uint32_t usbd_ep_recev (usb_core_driver *udev, uint8_t ep_addr, uint8_t *pbuf, uint32_t len) +{ + usb_transc *transc = &udev->dev.transc_out[EP_ID(ep_addr)]; + + /* setup the transfer */ + transc->xfer_buf = pbuf; + transc->xfer_len = len; + transc->xfer_count = 0U; + + if ((uint8_t)USB_USE_DMA == udev->bp.transfer_mode) { + transc->dma_addr = (uint32_t)pbuf; + } + + /* start the transfer */ + (void)usb_transc_outxfer (udev, transc); + + return 0U; +} + +/*! + \brief endpoint prepare to transmit data + \param[in] udev: pointer to USB core instance + \param[in] ep_addr: endpoint address + in this parameter: + bit0..bit6: endpoint number (0..7) + bit7: endpoint direction which can be IN(1) or OUT(0) + \param[in] pbuf: transmit buffer address pointer + \param[in] len: buffer length + \param[out] none + \retval none +*/ +uint32_t usbd_ep_send (usb_core_driver *udev, uint8_t ep_addr, uint8_t *pbuf, uint32_t len) +{ + usb_transc *transc = &udev->dev.transc_in[EP_ID(ep_addr)]; + + /* setup the transfer */ + transc->xfer_buf = pbuf; + transc->xfer_len = len; + transc->xfer_count = 0U; + + if ((uint8_t)USB_USE_DMA == udev->bp.transfer_mode) { + transc->dma_addr = (uint32_t)pbuf; + } + + /* start the transfer */ + (void)usb_transc_inxfer (udev, transc); + + return 0U; +} + +/*! + \brief set an endpoint to STALL status + \param[in] udev: pointer to USB core instance + \param[in] ep_addr: endpoint address + in this parameter: + bit0..bit6: endpoint number (0..7) + bit7: endpoint direction which can be IN(1) or OUT(0) + \param[out] none + \retval none +*/ +uint32_t usbd_ep_stall (usb_core_driver *udev, uint8_t ep_addr) +{ + usb_transc *transc = NULL; + + if (EP_DIR(ep_addr)) { + transc = &udev->dev.transc_in[EP_ID(ep_addr)]; + } else { + transc = &udev->dev.transc_out[ep_addr]; + } + + transc->ep_stall = 1U; + + (void)usb_transc_stall (udev, transc); + + return (0U); +} + +/*! + \brief clear endpoint STALLed status + \param[in] udev: pointer to USB core instance + \param[in] ep_addr: endpoint address + in this parameter: + bit0..bit6: endpoint number (0..7) + bit7: endpoint direction which can be IN(1) or OUT(0) + \param[out] none + \retval none +*/ +uint32_t usbd_ep_stall_clear (usb_core_driver *udev, uint8_t ep_addr) +{ + usb_transc *transc = NULL; + + if (EP_DIR(ep_addr)) { + transc = &udev->dev.transc_in[EP_ID(ep_addr)]; + } else { + transc = &udev->dev.transc_out[ep_addr]; + } + + transc->ep_stall = 0U; + + (void)usb_transc_clrstall (udev, transc); + + return (0U); +} + +/*! + \brief flush the endpoint FIFOs + \param[in] udev: pointer to USB core instance + \param[in] ep_addr: endpoint address + in this parameter: + bit0..bit6: endpoint number (0..7) + bit7: endpoint direction which can be IN(1) or OUT(0) + \param[out] none + \retval none +*/ +uint32_t usbd_fifo_flush (usb_core_driver *udev, uint8_t ep_addr) +{ + if (EP_DIR(ep_addr)) { + (void)usb_txfifo_flush (&udev->regs, EP_ID(ep_addr)); + } else { + (void)usb_rxfifo_flush (&udev->regs); + } + + return (0U); +} + +/*! + \brief device connect + \param[in] udev: pointer to USB device instance + \param[out] none + \retval none +*/ +void usbd_connect (usb_core_driver *udev) +{ +#ifndef USE_OTG_MODE + /* connect device */ + usb_dev_connect (udev); + + usb_mdelay(3U); +#endif /* USE_OTG_MODE */ +} + +/*! + \brief device disconnect + \param[in] udev: pointer to USB device instance + \param[out] none + \retval none +*/ +void usbd_disconnect (usb_core_driver *udev) +{ +#ifndef USE_OTG_MODE + /* disconnect device for 3ms */ + usb_dev_disconnect (udev); + + usb_mdelay(3U); +#endif /* USE_OTG_MODE */ +} diff --git a/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/device/core/Source/usbd_enum.c b/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/device/core/Source/usbd_enum.c new file mode 100644 index 0000000000..21094d5df4 --- /dev/null +++ b/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/device/core/Source/usbd_enum.c @@ -0,0 +1,764 @@ +/*! + \file usbd_enum.c + \brief USB enumeration function + + \version 2020-08-01, V3.0.0, firmware for GD32F4xx +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "usbd_enum.h" +#include "usb_ch9_std.h" + +#ifdef WINUSB_EXEMPT_DRIVER + +extern usbd_status usbd_OEM_req(usb_dev *udev, usb_req *req); + +#endif /* WINUSB_EXEMPT_DRIVER */ + +/* local function prototypes ('static') */ +static usb_reqsta _usb_std_reserved (usb_core_driver *udev, usb_req *req); +static uint8_t* _usb_dev_desc_get (usb_core_driver *udev, uint8_t index, uint16_t *len); +static uint8_t* _usb_config_desc_get (usb_core_driver *udev, uint8_t index, uint16_t *len); +static uint8_t* _usb_bos_desc_get (usb_core_driver *udev, uint8_t index, uint16_t *len); +static uint8_t* _usb_str_desc_get (usb_core_driver *udev, uint8_t index, uint16_t *len); +static usb_reqsta _usb_std_getstatus (usb_core_driver *udev, usb_req *req); +static usb_reqsta _usb_std_clearfeature (usb_core_driver *udev, usb_req *req); +static usb_reqsta _usb_std_setfeature (usb_core_driver *udev, usb_req *req); +static usb_reqsta _usb_std_setaddress (usb_core_driver *udev, usb_req *req); +static usb_reqsta _usb_std_getdescriptor (usb_core_driver *udev, usb_req *req); +static usb_reqsta _usb_std_setdescriptor (usb_core_driver *udev, usb_req *req); +static usb_reqsta _usb_std_getconfiguration (usb_core_driver *udev, usb_req *req); +static usb_reqsta _usb_std_setconfiguration (usb_core_driver *udev, usb_req *req); +static usb_reqsta _usb_std_getinterface (usb_core_driver *udev, usb_req *req); +static usb_reqsta _usb_std_setinterface (usb_core_driver *udev, usb_req *req); +static usb_reqsta _usb_std_synchframe (usb_core_driver *udev, usb_req *req); + +static usb_reqsta (*_std_dev_req[])(usb_core_driver *udev, usb_req *req) = +{ + [USB_GET_STATUS] = _usb_std_getstatus, + [USB_CLEAR_FEATURE] = _usb_std_clearfeature, + [USB_RESERVED2] = _usb_std_reserved, + [USB_SET_FEATURE] = _usb_std_setfeature, + [USB_RESERVED4] = _usb_std_reserved, + [USB_SET_ADDRESS] = _usb_std_setaddress, + [USB_GET_DESCRIPTOR] = _usb_std_getdescriptor, + [USB_SET_DESCRIPTOR] = _usb_std_setdescriptor, + [USB_GET_CONFIGURATION] = _usb_std_getconfiguration, + [USB_SET_CONFIGURATION] = _usb_std_setconfiguration, + [USB_GET_INTERFACE] = _usb_std_getinterface, + [USB_SET_INTERFACE] = _usb_std_setinterface, + [USB_SYNCH_FRAME] = _usb_std_synchframe, +}; + +/* get standard descriptor handler */ +static uint8_t* (*std_desc_get[])(usb_core_driver *udev, uint8_t index, uint16_t *len) = { + [(uint8_t)USB_DESCTYPE_DEV - 1U] = _usb_dev_desc_get, + [(uint8_t)USB_DESCTYPE_CONFIG - 1U] = _usb_config_desc_get, + [(uint8_t)USB_DESCTYPE_STR - 1U] = _usb_str_desc_get +}; + +/*! + \brief handle USB standard device request + \param[in] udev: pointer to USB device instance + \param[in] req: pointer to USB device request + \param[out] none + \retval USB device request status +*/ +usb_reqsta usbd_standard_request (usb_core_driver *udev, usb_req *req) +{ + return (*_std_dev_req[req->bRequest])(udev, req); +} + +/*! + \brief handle USB device class request + \param[in] udev: pointer to USB device instance + \param[in] req: pointer to USB device class request + \param[out] none + \retval USB device request status +*/ +usb_reqsta usbd_class_request (usb_core_driver *udev, usb_req *req) +{ + if ((uint8_t)USBD_CONFIGURED == udev->dev.cur_status) { + if (BYTE_LOW(req->wIndex) <= USBD_ITF_MAX_NUM) { + /* call device class handle function */ + return (usb_reqsta)udev->dev.class_core->req_proc(udev, req); + } + } + + return REQ_NOTSUPP; +} + +/*! + \brief handle USB vendor request + \param[in] udev: pointer to USB device instance + \param[in] req: pointer to USB vendor request + \param[out] none + \retval USB device request status +*/ +usb_reqsta usbd_vendor_request (usb_core_driver *udev, usb_req *req) +{ + (void)udev; + (void)req; + + /* added by user... */ +#ifdef WINUSB_EXEMPT_DRIVER + usbd_OEM_req(udev, req); +#endif + + return REQ_SUPP; +} + +/*! + \brief handle USB enumeration error + \param[in] udev: pointer to USB device instance + \param[in] req: pointer to USB device request + \param[out] none + \retval none +*/ +void usbd_enum_error (usb_core_driver *udev, usb_req *req) +{ + (void)req; + + (void)usbd_ep_stall (udev, 0x80U); + (void)usbd_ep_stall (udev, 0x00U); + + usb_ctlep_startout(udev); +} + +/*! + \brief convert hex 32bits value into unicode char + \param[in] value: hex 32bits value + \param[in] pbuf: buffer pointer to store unicode char + \param[in] len: value length + \param[out] none + \retval none +*/ +void int_to_unicode (uint32_t value, uint8_t *pbuf, uint8_t len) +{ + uint8_t index; + + for (index = 0U; index < len; index++) { + if ((value >> 28U) < 0x0AU) { + pbuf[2U * index] = (uint8_t)((value >> 28U) + '0'); + } else { + pbuf[2U * index] = (uint8_t)((value >> 28U) + 'A' - 10U); + } + + value = value << 4U; + + pbuf[2U * index + 1U] = 0U; + } +} + +/*! + \brief convert hex 32bits value into unicode char + \param[in] unicode_str: pointer to unicode string + \param[out] none + \retval none +*/ +void serial_string_get (uint16_t *unicode_str) +{ + if ((unicode_str[0] & 0x00FFU) != 6U) { + uint32_t DeviceSerial0, DeviceSerial1, DeviceSerial2; + + DeviceSerial0 = *(uint32_t*)DEVICE_ID1; + DeviceSerial1 = *(uint32_t*)DEVICE_ID2; + DeviceSerial2 = *(uint32_t*)DEVICE_ID3; + + DeviceSerial0 += DeviceSerial2; + + if (0U != DeviceSerial0) { + int_to_unicode(DeviceSerial0, (uint8_t*)&(unicode_str[1]), 8U); + int_to_unicode(DeviceSerial1, (uint8_t*)&(unicode_str[9]), 4U); + } + } else { + uint32_t device_serial = *(uint32_t*)DEVICE_ID; + + if(0U != device_serial) { + unicode_str[1] = (uint16_t)(device_serial & 0x0000FFFFU); + unicode_str[2] = (uint16_t)((device_serial & 0xFFFF0000U) >> 16U); + + } + } +} + +/*! + \brief no operation, just for reserved + \param[in] udev: pointer to USB device instance + \param[in] req: pointer to USB vendor request + \param[out] none + \retval USB device request status +*/ +static usb_reqsta _usb_std_reserved (usb_core_driver *udev, usb_req *req) +{ + (void)udev; + (void)req; + + /* no operation... */ + + return REQ_NOTSUPP; +} + +/*! + \brief get the device descriptor + \param[in] udev: pointer to USB device instance + \param[in] index: no use + \param[out] len: data length pointer + \retval descriptor buffer pointer +*/ +static uint8_t* _usb_dev_desc_get (usb_core_driver *udev, uint8_t index, uint16_t *len) +{ + (void)index; + + *len = udev->dev.desc->dev_desc[0]; + + return udev->dev.desc->dev_desc; +} + +/*! + \brief get the configuration descriptor + \brief[in] udev: pointer to USB device instance + \brief[in] index: no use + \param[out] len: data length pointer + \retval descriptor buffer pointer +*/ +static uint8_t* _usb_config_desc_get (usb_core_driver *udev, uint8_t index, uint16_t *len) +{ + (void)index; + + *len = udev->dev.desc->config_desc[2]; + + return udev->dev.desc->config_desc; +} + +/*! + \brief get the BOS descriptor + \brief[in] udev: pointer to USB device instance + \brief[in] index: no use + \param[out] len: data length pointer + \retval descriptor buffer pointer +*/ +static uint8_t* _usb_bos_desc_get (usb_core_driver *udev, uint8_t index, uint16_t *len) +{ + (void)index; + + *len = udev->dev.desc->bos_desc[2]; + + return udev->dev.desc->bos_desc; +} + +/*! + \brief get string descriptor + \param[in] udev: pointer to USB device instance + \param[in] index: string descriptor index + \param[out] len: pointer to string length + \retval descriptor buffer pointer +*/ +static uint8_t* _usb_str_desc_get (usb_core_driver *udev, uint8_t index, uint16_t *len) +{ + uint8_t *desc = udev->dev.desc->strings[index]; + + *len = desc[0]; + + return desc; +} + +/*! + \brief handle Get_Status request + \param[in] udev: pointer to USB device instance + \param[in] req: pointer to USB device request + \param[out] none + \retval USB device request status +*/ +static usb_reqsta _usb_std_getstatus (usb_core_driver *udev, usb_req *req) +{ + uint8_t recp = BYTE_LOW(req->wIndex); + usb_reqsta req_status = REQ_NOTSUPP; + usb_transc *transc = &udev->dev.transc_in[0]; + + static uint8_t status[2] = {0}; + + switch(req->bmRequestType & (uint8_t)USB_RECPTYPE_MASK) { + case USB_RECPTYPE_DEV: + if (((uint8_t)USBD_ADDRESSED == udev->dev.cur_status) || \ + ((uint8_t)USBD_CONFIGURED == udev->dev.cur_status)) { + + if (udev->dev.pm.power_mode) { + status[0] = USB_STATUS_SELF_POWERED; + } else { + status[0] = 0U; + } + + if (udev->dev.pm.dev_remote_wakeup) { + status[0] |= USB_STATUS_REMOTE_WAKEUP; + } else { + status[0] = 0U; + } + + req_status = REQ_SUPP; + } + break; + + case USB_RECPTYPE_ITF: + if (((uint8_t)USBD_CONFIGURED == udev->dev.cur_status) && (recp <= USBD_ITF_MAX_NUM)) { + req_status = REQ_SUPP; + } + break; + + case USB_RECPTYPE_EP: + if ((uint8_t)USBD_CONFIGURED == udev->dev.cur_status) { + if (0x80U == (recp & 0x80U)) { + status[0] = udev->dev.transc_in[EP_ID(recp)].ep_stall; + } else { + status[0] = udev->dev.transc_out[recp].ep_stall; + } + + req_status = REQ_SUPP; + } + break; + + default: + break; + } + + if (REQ_SUPP == req_status) { + transc->xfer_buf = status; + transc->remain_len = 2U; + } + + return req_status; +} + +/*! + \brief handle USB Clear_Feature request + \param[in] udev: pointer to USB device instance + \param[in] req: USB device request + \param[out] none + \retval USB device request status +*/ +static usb_reqsta _usb_std_clearfeature (usb_core_driver *udev, usb_req *req) +{ + uint8_t ep = 0U; + + switch(req->bmRequestType & (uint8_t)USB_RECPTYPE_MASK) { + case USB_RECPTYPE_DEV: + if (((uint8_t)USBD_ADDRESSED == udev->dev.cur_status) || \ + ((uint8_t)USBD_CONFIGURED == udev->dev.cur_status)) { + + /* clear device remote wakeup feature */ + if ((uint16_t)USB_FEATURE_REMOTE_WAKEUP == req->wValue) { + udev->dev.pm.dev_remote_wakeup = 0U; + + return REQ_SUPP; + } + } + break; + + case USB_RECPTYPE_ITF: + break; + + case USB_RECPTYPE_EP: + /* get endpoint address */ + ep = BYTE_LOW(req->wIndex); + + if ((uint8_t)USBD_CONFIGURED == udev->dev.cur_status) { + /* clear endpoint halt feature */ + if (((uint16_t)USB_FEATURE_EP_HALT == req->wValue) && (!CTL_EP(ep))) { + (void)usbd_ep_stall_clear (udev, ep); + + (void)udev->dev.class_core->req_proc (udev, req); + } + + return REQ_SUPP; + } + break; + + default: + break; + } + + return REQ_NOTSUPP; +} + +/*! + \brief handle USB Set_Feature request + \param[in] udev: pointer to USB device instance + \param[in] req: pointer to USB device request + \param[out] none + \retval USB device request status +*/ +static usb_reqsta _usb_std_setfeature (usb_core_driver *udev, usb_req *req) +{ + uint8_t ep = 0U; + + switch (req->bmRequestType & (uint8_t)USB_RECPTYPE_MASK) { + case USB_RECPTYPE_DEV: + if (((uint8_t)USBD_ADDRESSED == udev->dev.cur_status) || \ + ((uint8_t)USBD_CONFIGURED == udev->dev.cur_status)) { + /* set device remote wakeup feature */ + if ((uint16_t)USB_FEATURE_REMOTE_WAKEUP == req->wValue) { + udev->dev.pm.dev_remote_wakeup = 1U; + } + + return REQ_SUPP; + } + break; + + case USB_RECPTYPE_ITF: + break; + + case USB_RECPTYPE_EP: + /* get endpoint address */ + ep = BYTE_LOW(req->wIndex); + + if ((uint8_t)USBD_CONFIGURED == udev->dev.cur_status) { + /* set endpoint halt feature */ + if (((uint16_t)USB_FEATURE_EP_HALT == req->wValue) && (!CTL_EP(ep))) { + (void)usbd_ep_stall (udev, ep); + } + + return REQ_SUPP; + } + break; + + default: + break; + } + + return REQ_NOTSUPP; +} + +/*! + \brief handle USB Set_Address request + \param[in] udev: pointer to USB device instance + \param[in] req: pointer to USB device request + \param[out] none + \retval USB device request status +*/ +static usb_reqsta _usb_std_setaddress (usb_core_driver *udev, usb_req *req) +{ + if ((0U == req->wIndex) && (0U == req->wLength)) { + udev->dev.dev_addr = (uint8_t)(req->wValue) & 0x7FU; + + if (udev->dev.cur_status != (uint8_t)USBD_CONFIGURED) { + usbd_addr_set (udev, udev->dev.dev_addr); + + if (udev->dev.dev_addr) { + udev->dev.cur_status = (uint8_t)USBD_ADDRESSED; + } else { + udev->dev.cur_status = (uint8_t)USBD_DEFAULT; + } + + return REQ_SUPP; + } + } + + return REQ_NOTSUPP; +} + +/*! + \brief handle USB Get_Descriptor request + \param[in] udev: pointer to USB device instance + \param[in] req: pointer to USB device request + \param[out] none + \retval USB device request status +*/ +static usb_reqsta _usb_std_getdescriptor (usb_core_driver *udev, usb_req *req) +{ + uint8_t desc_type = 0U; + uint8_t desc_index = 0U; + + usb_reqsta status = REQ_NOTSUPP; + + usb_transc *transc = &udev->dev.transc_in[0]; + + /* get device standard descriptor */ + switch (req->bmRequestType & USB_RECPTYPE_MASK) { + case USB_RECPTYPE_DEV: + desc_type = BYTE_HIGH(req->wValue); + desc_index = BYTE_LOW(req->wValue); + + switch (desc_type) { + case USB_DESCTYPE_DEV: + transc->xfer_buf = std_desc_get[desc_type - 1U](udev, desc_index, (uint16_t *)&(transc->remain_len)); + + if (64U == req->wLength) { + transc->remain_len = 8U; + } + break; + + case USB_DESCTYPE_CONFIG: + transc->xfer_buf = std_desc_get[desc_type - 1U](udev, desc_index, (uint16_t *)&(transc->remain_len)); + break; + + case USB_DESCTYPE_STR: + if (desc_index < (uint8_t)STR_IDX_MAX) { + transc->xfer_buf = std_desc_get[desc_type - 1U](udev, desc_index, (uint16_t *)&(transc->remain_len)); + } + break; + + case USB_DESCTYPE_ITF: + case USB_DESCTYPE_EP: + case USB_DESCTYPE_DEV_QUALIFIER: + case USB_DESCTYPE_OTHER_SPD_CONFIG: + case USB_DESCTYPE_ITF_POWER: + break; + + case USB_DESCTYPE_BOS: + transc->xfer_buf = _usb_bos_desc_get(udev, desc_index, (uint16_t *)&(transc->remain_len)); + break; + + default: + break; + } + break; + + case USB_RECPTYPE_ITF: + /* get device class special descriptor */ + status = (usb_reqsta)(udev->dev.class_core->req_proc(udev, req)); + break; + + case USB_RECPTYPE_EP: + break; + + default: + break; + } + + if ((0U != transc->remain_len) && (0U != req->wLength)) { + if (transc->remain_len < req->wLength) { + if ((transc->remain_len >= transc->max_len) && (0U == (transc->remain_len % transc->max_len))) { + udev->dev.control.ctl_zlp = 1U; + } + } else { + transc->remain_len = req->wLength; + } + + status = REQ_SUPP; + } + + return status; +} + +/*! + \brief handle USB Set_Descriptor request + \param[in] udev: pointer to USB device instance + \param[in] req: pointer to USB device request + \param[out] none + \retval USB device request status +*/ +static usb_reqsta _usb_std_setdescriptor (usb_core_driver *udev, usb_req *req) +{ + (void)udev; + (void)req; + + /* no handle... */ + return REQ_SUPP; +} + +/*! + \brief handle USB Get_Configuration request + \param[in] udev: pointer to USB device instance + \param[in] req: pointer to USB device request + \param[out] none + \retval USB device request status +*/ +static usb_reqsta _usb_std_getconfiguration (usb_core_driver *udev, usb_req *req) +{ + (void)req; + + usb_reqsta req_status = REQ_NOTSUPP; + usb_transc *transc = &udev->dev.transc_in[0]; + + switch (udev->dev.cur_status) { + case USBD_ADDRESSED: + if (USB_DEFAULT_CONFIG == udev->dev.config) { + req_status = REQ_SUPP; + } + break; + + case USBD_CONFIGURED: + if (udev->dev.config != USB_DEFAULT_CONFIG) { + req_status = REQ_SUPP; + } + break; + + default: + break; + } + + if (REQ_SUPP == req_status) { + transc->xfer_buf = &(udev->dev.config); + transc->remain_len = 1U; + } + + return req_status; +} + +/*! + \brief handle USB Set_Configuration request + \param[in] udev: pointer to USB device instance + \param[in] req: pointer to USB device request + \param[out] none + \retval USB device request status +*/ +static usb_reqsta _usb_std_setconfiguration (usb_core_driver *udev, usb_req *req) +{ + static uint8_t config; + usb_reqsta status = REQ_NOTSUPP; + + config = (uint8_t)(req->wValue); + + if (config <= USBD_CFG_MAX_NUM) { + switch (udev->dev.cur_status) { + case USBD_ADDRESSED: + if (config){ + (void)udev->dev.class_core->init(udev, config); + + udev->dev.config = config; + udev->dev.cur_status = (uint8_t)USBD_CONFIGURED; + } + + status = REQ_SUPP; + break; + + case USBD_CONFIGURED: + if (USB_DEFAULT_CONFIG == config) { + (void)udev->dev.class_core->deinit(udev, config); + + udev->dev.config = config; + udev->dev.cur_status = (uint8_t)USBD_ADDRESSED; + } else if (config != udev->dev.config) { + /* clear old configuration */ + (void)udev->dev.class_core->deinit(udev, config); + + /* set new configuration */ + udev->dev.config = config; + + (void)udev->dev.class_core->init(udev, config); + } else { + /* no operation */ + } + + status = REQ_SUPP; + break; + + case USBD_DEFAULT: + break; + + default: + break; + } + } + + return status; +} + +/*! + \brief handle USB Get_Interface request + \param[in] udev: pointer to USB device instance + \param[in] req: pointer to USB device request + \param[out] none + \retval USB device request status +*/ +static usb_reqsta _usb_std_getinterface (usb_core_driver *udev, usb_req *req) +{ + switch (udev->dev.cur_status) { + case USBD_DEFAULT: + break; + + case USBD_ADDRESSED: + break; + + case USBD_CONFIGURED: + if (BYTE_LOW(req->wIndex) <= USBD_ITF_MAX_NUM) { + usb_transc *transc = &udev->dev.transc_in[0]; + + transc->xfer_buf = &(udev->dev.class_core->alter_set); + transc->remain_len = 1U; + + return REQ_SUPP; + } + break; + + default: + break; + } + + return REQ_NOTSUPP; +} + +/*! + \brief handle USB Set_Interface request + \param[in] udev: pointer to USB device instance + \param[in] req: pointer to USB device request + \param[out] none + \retval USB device request status +*/ +static usb_reqsta _usb_std_setinterface (usb_core_driver *udev, usb_req *req) +{ + switch (udev->dev.cur_status) { + case USBD_DEFAULT: + break; + + case USBD_ADDRESSED: + break; + + case USBD_CONFIGURED: + if (BYTE_LOW(req->wIndex) <= USBD_ITF_MAX_NUM) { + if (NULL != udev->dev.class_core->set_intf) { + (void)udev->dev.class_core->set_intf (udev, req); + } + + return REQ_SUPP; + } + break; + + default: + break; + } + + return REQ_NOTSUPP; +} + +/*! + \brief handle USB SynchFrame request + \param[in] udev: pointer to USB device instance + \param[in] req: pointer to USB device request + \param[out] none + \retval USB device request status +*/ +static usb_reqsta _usb_std_synchframe (usb_core_driver *udev, usb_req *req) +{ + (void)udev; + (void)req; + + /* no handle */ + return REQ_SUPP; +} diff --git a/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/device/core/Source/usbd_transc.c b/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/device/core/Source/usbd_transc.c new file mode 100644 index 0000000000..a4349ee3a1 --- /dev/null +++ b/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/device/core/Source/usbd_transc.c @@ -0,0 +1,264 @@ +/*! + \file usbd_transc.c + \brief USB transaction core functions + + \version 2020-08-01, V3.0.0, firmware for GD32F4xx +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "usbd_enum.h" +#include "usbd_transc.h" + +/*! + \brief USB send data in the control transaction + \param[in] udev: pointer to USB device instance + \param[out] none + \retval USB device operation cur_status +*/ +usbd_status usbd_ctl_send (usb_core_driver *udev) +{ + usb_transc *transc = &udev->dev.transc_in[0]; + + (void)usbd_ep_send(udev, 0U, transc->xfer_buf, transc->remain_len); + + if (transc->remain_len > transc->max_len) { + udev->dev.control.ctl_state = (uint8_t)USB_CTL_DATA_IN; + } else { + udev->dev.control.ctl_state = (uint8_t)USB_CTL_LAST_DATA_IN; + } + + return USBD_OK; +} + +/*! + \brief USB receive data in control transaction + \param[in] udev: pointer to USB device instance + \param[out] none + \retval USB device operation cur_status +*/ +usbd_status usbd_ctl_recev (usb_core_driver *udev) +{ + usb_transc *transc = &udev->dev.transc_out[0]; + + (void)usbd_ep_recev (udev, 0U, transc->xfer_buf, transc->remain_len); + + if (transc->remain_len > transc->max_len) { + udev->dev.control.ctl_state = (uint8_t)USB_CTL_DATA_OUT; + } else { + udev->dev.control.ctl_state = (uint8_t)USB_CTL_LAST_DATA_OUT; + } + + return USBD_OK; +} + +/*! + \brief USB send control transaction status + \param[in] udev: pointer to USB device instance + \param[out] none + \retval USB device operation cur_status +*/ +usbd_status usbd_ctl_status_send (usb_core_driver *udev) +{ + udev->dev.control.ctl_state = (uint8_t)USB_CTL_STATUS_IN; + + (void)usbd_ep_send (udev, 0U, NULL, 0U); + + usb_ctlep_startout(udev); + + return USBD_OK; +} + +/*! + \brief USB control receive status + \param[in] udev: pointer to USB device instance + \param[out] none + \retval USB device operation cur_status +*/ +usbd_status usbd_ctl_status_recev (usb_core_driver *udev) +{ + udev->dev.control.ctl_state = (uint8_t)USB_CTL_STATUS_OUT; + + (void)usbd_ep_recev (udev, 0U, NULL, 0U); + + usb_ctlep_startout(udev); + + return USBD_OK; +} + +/*! + \brief USB setup stage processing + \param[in] udev: pointer to USB device instance + \param[out] none + \retval USB device operation cur_status +*/ +uint8_t usbd_setup_transc (usb_core_driver *udev) +{ + usb_reqsta reqstat = REQ_NOTSUPP; + + usb_req req = udev->dev.control.req; + + switch (req.bmRequestType & USB_REQTYPE_MASK) { + /* standard device request */ + case USB_REQTYPE_STRD: + reqstat = usbd_standard_request (udev, &req); + break; + + /* device class request */ + case USB_REQTYPE_CLASS: + reqstat = usbd_class_request (udev, &req); + break; + + /* vendor defined request */ + case USB_REQTYPE_VENDOR: + reqstat = usbd_vendor_request (udev, &req); + break; + + default: + break; + } + + if (REQ_SUPP == reqstat) { + if (0U == req.wLength) { + (void)usbd_ctl_status_send (udev); + } else { + if (req.bmRequestType & 0x80U) { + (void)usbd_ctl_send (udev); + } else { + (void)usbd_ctl_recev (udev); + } + } + } else { + usbd_enum_error (udev, &req); + } + + return (uint8_t)USBD_OK; +} + +/*! + \brief data out stage processing + \param[in] udev: pointer to USB device instance + \param[in] ep_num: endpoint identifier(0..7) + \param[out] none + \retval USB device operation cur_status +*/ +uint8_t usbd_out_transc (usb_core_driver *udev, uint8_t ep_num) +{ + if (0U == ep_num) { + usb_transc *transc = &udev->dev.transc_out[0]; + + switch (udev->dev.control.ctl_state) { + case USB_CTL_DATA_OUT: + /* update transfer length */ + transc->remain_len -= transc->max_len; + + if ((uint8_t)USB_USE_DMA == udev->bp.transfer_mode) { + transc->xfer_buf += transc->max_len; + } + + (void)usbd_ctl_recev (udev); + break; + + case USB_CTL_LAST_DATA_OUT: + if (udev->dev.cur_status == (uint8_t)USBD_CONFIGURED) { + if (udev->dev.class_core->data_out != NULL) { + (void)udev->dev.class_core->data_out (udev, 0U); + } + } + + transc->remain_len = 0U; + + (void)usbd_ctl_status_send (udev); + break; + + default: + break; + } + } else if ((udev->dev.class_core->data_out != NULL) && (udev->dev.cur_status == (uint8_t)USBD_CONFIGURED)) { + (void)udev->dev.class_core->data_out (udev, ep_num); + } else { + /* no operation */ + } + + return (uint8_t)USBD_OK; +} + +/*! + \brief data in stage processing + \param[in] udev: pointer to USB device instance + \param[in] ep_num: endpoint identifier(0..7) + \param[out] none + \retval USB device operation cur_status +*/ +uint8_t usbd_in_transc (usb_core_driver *udev, uint8_t ep_num) +{ + if (0U == ep_num) { + usb_transc *transc = &udev->dev.transc_in[0]; + + switch (udev->dev.control.ctl_state) { + case USB_CTL_DATA_IN: + /* update transfer length */ + transc->remain_len -= transc->max_len; + + if ((uint8_t)USB_USE_DMA == udev->bp.transfer_mode) { + transc->xfer_buf += transc->max_len; + } + + (void)usbd_ctl_send (udev); + break; + + case USB_CTL_LAST_DATA_IN: + /* last packet is MPS multiple, so send ZLP packet */ + if (udev->dev.control.ctl_zlp) { + (void)usbd_ep_send (udev, 0U, NULL, 0U); + + udev->dev.control.ctl_zlp = 0U; + } else { + if (udev->dev.cur_status == (uint8_t)USBD_CONFIGURED) { + if (udev->dev.class_core->data_in != NULL) { + (void)udev->dev.class_core->data_in (udev, 0U); + } + } + + transc->remain_len = 0U; + + (void)usbd_ctl_status_recev (udev); + } + break; + + default: + break; + } + } else { + if ((udev->dev.cur_status == (uint8_t)USBD_CONFIGURED) && (udev->dev.class_core->data_in != NULL)) { + (void)udev->dev.class_core->data_in (udev, ep_num); + } + } + + return (uint8_t)USBD_OK; +} diff --git a/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/driver/Include/drv_usb_core.h b/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/driver/Include/drv_usb_core.h new file mode 100644 index 0000000000..daefca3de5 --- /dev/null +++ b/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/driver/Include/drv_usb_core.h @@ -0,0 +1,343 @@ +/*! + \file drv_usb_core.h + \brief USB core low level driver header file + + \version 2020-08-01, V3.0.0, firmware for GD32F4xx +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef __DRV_USB_CORE_H +#define __DRV_USB_CORE_H + +#include "drv_usb_regs.h" +#include "usb_ch9_std.h" + +#ifdef USE_DEVICE_MODE + #include "usbd_conf.h" +#endif /* USE_DEVICE_MODE */ + +#define USB_FS_EP0_MAX_LEN 64U /*!< maximum packet size of endpoint 0 */ +#define HC_MAX_PACKET_COUNT 140U /*!< maximum packet count */ + +#define EP_ID(x) ((uint8_t)((x) & 0x7FU)) /*!< endpoint number */ +#define EP_DIR(x) ((uint8_t)((x) >> 7)) /*!< endpoint direction */ + +enum _usb_mode { + DEVICE_MODE = 0U, /*!< device mode */ + HOST_MODE, /*!< host mode */ + OTG_MODE /*!< OTG mode */ +}; + +enum _usb_eptype { + USB_EPTYPE_CTRL = 0U, /*!< control endpoint type */ + USB_EPTYPE_ISOC = 1U, /*!< isochronous endpoint type */ + USB_EPTYPE_BULK = 2U, /*!< bulk endpoint type */ + USB_EPTYPE_INTR = 3U, /*!< interrupt endpoint type */ + USB_EPTYPE_MASK = 3U /*!< endpoint type mask */ +}; + +typedef enum +{ + USB_OTG_OK = 0U, /*!< USB OTG status OK*/ + USB_OTG_FAIL /*!< USB OTG status fail*/ +} usb_otg_status; + +typedef enum +{ + USB_OK = 0U, /*!< USB status OK*/ + USB_FAIL /*!< USB status fail*/ +} usb_status; + +typedef enum +{ + USB_USE_FIFO, /*!< USB use FIFO transfer mode */ + USB_USE_DMA /*!< USB use DMA transfer mode */ +} usb_transfer_mode; + +typedef struct +{ + uint8_t core_enum; /*!< USB core type */ + uint8_t core_speed; /*!< USB core speed */ + uint8_t num_pipe; /*!< USB host channel numbers */ + uint8_t num_ep; /*!< USB device endpoint numbers */ + uint8_t transfer_mode; /*!< USB transfer mode */ + uint8_t phy_itf; /*!< USB core PHY interface */ + uint8_t sof_enable; /*!< USB SOF output */ + uint8_t low_power; /*!< USB low power */ + uint8_t lpm_enable; /*!< USB link power mode(LPM) */ + uint8_t vbus_sensing_enable; /*!< USB VBUS sensing feature */ + uint8_t use_dedicated_ep1; /*!< USB dedicated endpoint1 interrupt */ + uint8_t use_external_vbus; /*!< enable or disable the use of the external VBUS */ + uint32_t base_reg; /*!< base register address */ +} usb_core_basic; + +#ifdef USE_DEVICE_MODE + +/* USB descriptor */ +typedef struct _usb_desc { + uint8_t *dev_desc; /*!< device descriptor */ + uint8_t *config_desc; /*!< configure descriptor */ + uint8_t *bos_desc; /*!< BOS descriptor */ + + void* const *strings; /*!< string descriptor */ +} usb_desc; + +/* USB power management */ +typedef struct _usb_pm { + uint8_t power_mode; /*!< power mode */ + uint8_t power_low; /*!< power low */ + uint8_t dev_remote_wakeup; /*!< remote wakeup */ + uint8_t remote_wakeup_on; /*!< remote wakeup on */ +} usb_pm; + +/* USB control information */ +typedef struct _usb_control { + usb_req req; /*!< USB standard device request */ + + uint8_t ctl_state; /*!< USB control transfer state */ + uint8_t ctl_zlp; /*!< zero length package */ +} usb_control; + +typedef struct +{ + struct { + uint8_t num: 4; /*!< the endpoint number.it can be from 0 to 6 */ + uint8_t pad: 3; /*!< padding between number and direction */ + uint8_t dir: 1; /*!< the endpoint direction */ + } ep_addr; + + uint8_t ep_type; /*!< USB endpoint type */ + uint8_t ep_stall; /*!< USB endpoint stall status */ + + uint8_t frame_num; /*!< number of frame */ + uint16_t max_len; /*!< Maximum packet length */ + + /* transaction level variables */ + uint8_t *xfer_buf; /*!< transmit buffer */ + uint32_t xfer_len; /*!< transmit buffer length */ + uint32_t xfer_count; /*!< transmit buffer count */ + + uint32_t remain_len; /*!< remain packet length */ + + uint32_t dma_addr; /*!< DMA address */ +} usb_transc; + +typedef struct _usb_core_driver usb_dev; + +typedef struct _usb_class_core +{ + uint8_t command; /*!< device class request command */ + uint8_t alter_set; /*!< alternative set */ + + uint8_t (*init) (usb_dev *udev, uint8_t config_index); /*!< initialize handler */ + uint8_t (*deinit) (usb_dev *udev, uint8_t config_index); /*!< de-initialize handler */ + + uint8_t (*req_proc) (usb_dev *udev, usb_req *req); /*!< device request handler */ + + uint8_t (*set_intf) (usb_dev *udev, usb_req *req); /*!< device set interface callback */ + + uint8_t (*data_in) (usb_dev *udev, uint8_t ep_num); /*!< device data in handler */ + uint8_t (*data_out) (usb_dev *udev, uint8_t ep_num); /*!< device data out handler */ + + uint8_t (*SOF) (usb_dev *udev); /*!< Start of frame handler */ + + uint8_t (*incomplete_isoc_in) (usb_dev *udev); /*!< Incomplete synchronization IN transfer handler */ + uint8_t (*incomplete_isoc_out) (usb_dev *udev); /*!< Incomplete synchronization OUT transfer handler */ +} usb_class_core; + +typedef struct _usb_perp_dev +{ + uint8_t config; /*!< configuration */ + uint8_t dev_addr; /*!< device address */ + + __IO uint8_t cur_status; /*!< current status */ + __IO uint8_t backup_status; /*!< backup status */ + + usb_transc transc_in[USBFS_MAX_TX_FIFOS]; /*!< endpoint IN transaction */ + usb_transc transc_out[USBFS_MAX_TX_FIFOS]; /*!< endpoint OUT transaction */ + + usb_pm pm; /*!< power management */ + usb_control control; /*!< USB control information */ + usb_desc *desc; /*!< USB descriptors pointer */ + usb_class_core *class_core; /*!< class driver */ + void *class_data[USBD_ITF_MAX_NUM]; /*!< class data pointer */ + void *user_data; /*!< user data pointer */ + void *pdata; /*!< reserved data pointer */ +} usb_perp_dev; + +#endif /* USE_DEVICE_MODE */ + +#ifdef USE_HOST_MODE + +typedef enum _usb_pipe_status +{ + PIPE_IDLE = 0U, + PIPE_XF, + PIPE_HALTED, + PIPE_NAK, + PIPE_NYET, + PIPE_STALL, + PIPE_TRACERR, + PIPE_BBERR, + PIPE_REQOVR, + PIPE_DTGERR, +} usb_pipe_staus; + +typedef enum _usb_urb_state +{ + URB_IDLE = 0U, + URB_DONE, + URB_NOTREADY, + URB_ERROR, + URB_STALL, + URB_PING +} usb_urb_state; + +typedef struct _usb_pipe +{ + uint8_t in_used; + uint8_t dev_addr; + uint32_t dev_speed; + + struct { + uint8_t num; + uint8_t dir; + uint8_t type; + uint16_t mps; + } ep; + + uint8_t ping; + uint32_t DPID; + + uint8_t *xfer_buf; + uint32_t xfer_len; + uint32_t xfer_count; + + uint8_t data_toggle_in; + uint8_t data_toggle_out; + + __IO uint32_t err_count; + __IO usb_pipe_staus pp_status; + __IO usb_urb_state urb_state; +} usb_pipe; + +typedef struct _usb_host_drv +{ + __IO uint32_t connect_status; + __IO uint32_t port_enabled; + __IO uint32_t backup_xfercount[USBFS_MAX_TX_FIFOS]; + + usb_pipe pipe[USBFS_MAX_TX_FIFOS]; + void *data; +} usb_host_drv; + +#endif /* USE_HOST_MODE */ + +typedef struct _usb_core_driver +{ + usb_core_basic bp; /*!< USB basic parameters */ + usb_core_regs regs; /*!< USB registers */ + +#ifdef USE_DEVICE_MODE + usb_perp_dev dev; /*!< USB peripheral device */ +#endif /* USE_DEVICE_MODE */ + +#ifdef USE_HOST_MODE + usb_host_drv host; +#endif /* USE_HOST_MODE */ +} usb_core_driver; + +/* static inline function definitions */ + +/*! + \brief get the global interrupts + \param[in] usb_regs: pointer to USB core registers + \param[out] none + \retval interrupt status +*/ +__STATIC_INLINE uint32_t usb_coreintr_get(usb_core_regs *usb_regs) +{ + return usb_regs->gr->GINTEN & usb_regs->gr->GINTF; +} + +/*! + \brief set USB RX FIFO size + \param[in] usb_regs: pointer to USB core registers + \param[in] size: assigned FIFO size + \param[out] none + \retval none +*/ +__STATIC_INLINE void usb_set_rxfifo(usb_core_regs *usb_regs, uint16_t size) +{ + usb_regs->gr->GRFLEN = size; +} + +/*! + \brief enable the global interrupts + \param[in] usb_regs: pointer to USB core registers + \param[out] none + \retval none +*/ +__STATIC_INLINE void usb_globalint_enable(usb_core_regs *usb_regs) +{ + /* enable USB global interrupt */ + usb_regs->gr->GAHBCS |= GAHBCS_GINTEN; +} + +/*! + \brief disable the global interrupts + \param[in] usb_regs: pointer to USB core registers + \param[out] none + \retval none +*/ +__STATIC_INLINE void usb_globalint_disable(usb_core_regs *usb_regs) +{ + /* disable USB global interrupt */ + usb_regs->gr->GAHBCS &= ~GAHBCS_GINTEN; +} + +/* function declarations */ +/* configure core capabilities */ +usb_status usb_basic_init (usb_core_basic *usb_basic, usb_core_regs *usb_regs, usb_core_enum usb_core); +/* initializes the USB controller registers and prepares the core device mode or host mode operation */ +usb_status usb_core_init (usb_core_basic usb_basic, usb_core_regs *usb_regs); +/* write a packet into the TX FIFO associated with the endpoint */ +usb_status usb_txfifo_write (usb_core_regs *usb_regs, uint8_t *src_buf, uint8_t fifo_num, uint16_t byte_count); +/* read a packet from the RX FIFO associated with the endpoint */ +void *usb_rxfifo_read (usb_core_regs *usb_regs, uint8_t *dest_buf, uint16_t byte_count); +/* flush a TX FIFO or all TX FIFOs */ +usb_status usb_txfifo_flush (usb_core_regs *usb_regs, uint8_t fifo_num); +/* flush the entire RX FIFO */ +usb_status usb_rxfifo_flush (usb_core_regs *usb_regs); +/* set endpoint or channel TX FIFO size */ +void usb_set_txfifo(usb_core_regs *usb_regs, uint8_t fifo, uint16_t size); +/* set USB current mode */ +void usb_curmode_set(usb_core_regs *usb_regs, uint8_t mode); + +#endif /* __DRV_USB_CORE_H */ diff --git a/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/driver/Include/drv_usb_dev.h b/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/driver/Include/drv_usb_dev.h new file mode 100644 index 0000000000..8c0431bc1f --- /dev/null +++ b/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/driver/Include/drv_usb_dev.h @@ -0,0 +1,197 @@ +/*! + \file drv_usb_dev.h + \brief USB device low level driver header file + + \version 2020-08-01, V3.0.0, firmware for GD32F4xx +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef __DRV_USB_DEV_H +#define __DRV_USB_DEV_H + +#include "usbd_conf.h" +#include "drv_usb_core.h" + +#define EP_IN(x) ((uint8_t)(0x80U | (x))) /*!< device IN endpoint */ +#define EP_OUT(x) ((uint8_t)(x)) /*!< device OUT endpoint */ + +enum usb_ctl_status { + USB_CTL_IDLE = 0U, /*!< USB control transfer idle state */ + USB_CTL_DATA_IN, /*!< USB control transfer data in state */ + USB_CTL_LAST_DATA_IN, /*!< USB control transfer last data in state */ + USB_CTL_DATA_OUT, /*!< USB control transfer data out state */ + USB_CTL_LAST_DATA_OUT, /*!< USB control transfer last data out state */ + USB_CTL_STATUS_IN, /*!< USB control transfer status in state*/ + USB_CTL_STATUS_OUT /*!< USB control transfer status out state */ +}; + +/* static inline function definitions */ + +/*! + \brief configure the USB device to be disconnected + \param[in] udev: pointer to USB device + \param[out] none + \retval operation status +*/ +__STATIC_INLINE void usb_dev_disconnect (usb_core_driver *udev) +{ + udev->regs.dr->DCTL |= DCTL_SD; +} + +/*! + \brief configure the USB device to be connected + \param[in] udev: pointer to USB device + \param[out] none + \retval operation status +*/ +__STATIC_INLINE void usb_dev_connect (usb_core_driver *udev) +{ + udev->regs.dr->DCTL &= ~DCTL_SD; +} + +/*! + \brief set the USB device address + \param[in] udev: pointer to USB device + \param[in] dev_addr: device address for setting + \param[out] none + \retval operation status +*/ +__STATIC_INLINE void usb_devaddr_set (usb_core_driver *udev, uint8_t dev_addr) +{ + udev->regs.dr->DCFG &= ~DCFG_DAR; + udev->regs.dr->DCFG |= (uint32_t)dev_addr << 4U; +} + +/*! + \brief read device all OUT endpoint interrupt register + \param[in] udev: pointer to USB device + \param[out] none + \retval interrupt status +*/ +__STATIC_INLINE uint32_t usb_oepintnum_read (usb_core_driver *udev) +{ + uint32_t value = udev->regs.dr->DAEPINT; + + value &= udev->regs.dr->DAEPINTEN; + + return (value & DAEPINT_OEPITB) >> 16U; +} + +/*! + \brief read device OUT endpoint interrupt flag register + \param[in] udev: pointer to USB device + \param[in] ep_num: endpoint number + \param[out] none + \retval interrupt status +*/ +__STATIC_INLINE uint32_t usb_oepintr_read (usb_core_driver *udev, uint8_t ep_num) +{ + uint32_t value = udev->regs.er_out[ep_num]->DOEPINTF; + + value &= udev->regs.dr->DOEPINTEN; + + return value; +} + +/*! + \brief read device all IN endpoint interrupt register + \param[in] udev: pointer to USB device + \param[out] none + \retval interrupt status +*/ +__STATIC_INLINE uint32_t usb_iepintnum_read (usb_core_driver *udev) +{ + uint32_t value = udev->regs.dr->DAEPINT; + + value &= udev->regs.dr->DAEPINTEN; + + return value & DAEPINT_IEPITB; +} + +/*! + \brief set remote wakeup signaling + \param[in] udev: pointer to USB device + \param[out] none + \retval none +*/ +__STATIC_INLINE void usb_rwkup_set (usb_core_driver *udev) +{ + if (udev->dev.pm.dev_remote_wakeup) { + /* enable remote wakeup signaling */ + udev->regs.dr->DCTL |= DCTL_RWKUP; + } +} + +/*! + \brief reset remote wakeup signaling + \param[in] udev: pointer to USB device + \param[out] none + \retval none +*/ +__STATIC_INLINE void usb_rwkup_reset (usb_core_driver *udev) +{ + if (udev->dev.pm.dev_remote_wakeup) { + /* disable remote wakeup signaling */ + udev->regs.dr->DCTL &= ~DCTL_RWKUP; + } +} + +/* function declarations */ +/* initialize USB core registers for device mode */ +usb_status usb_devcore_init (usb_core_driver *udev); +/* enable the USB device mode interrupts */ +usb_status usb_devint_enable (usb_core_driver *udev); +/* active the USB endpoint 0 transaction */ +usb_status usb_transc0_active (usb_core_driver *udev, usb_transc *transc); +/* active the USB transaction */ +usb_status usb_transc_active (usb_core_driver *udev, usb_transc *transc); +/* deactivate the USB transaction */ +usb_status usb_transc_deactivate (usb_core_driver *udev, usb_transc *transc); +/* configure USB transaction to start IN transfer */ +usb_status usb_transc_inxfer (usb_core_driver *udev, usb_transc *transc); +/* configure USB transaction to start OUT transfer */ +usb_status usb_transc_outxfer (usb_core_driver *udev, usb_transc *transc); +/* set the USB transaction STALL status */ +usb_status usb_transc_stall (usb_core_driver *udev, usb_transc *transc); +/* clear the USB transaction STALL status */ +usb_status usb_transc_clrstall (usb_core_driver *udev, usb_transc *transc); +/* read device IN endpoint interrupt flag register */ +uint32_t usb_iepintr_read (usb_core_driver *udev, uint8_t ep_num); +/* configures OUT endpoint 0 to receive SETUP packets */ +void usb_ctlep_startout (usb_core_driver *udev); +/* active remote wakeup signaling */ +void usb_rwkup_active (usb_core_driver *udev); +/* active USB core clock */ +void usb_clock_active (usb_core_driver *udev); +/* USB device suspend */ +void usb_dev_suspend (usb_core_driver *udev); +/* stop the device and clean up FIFOs */ +void usb_dev_stop (usb_core_driver *udev); + +#endif /* __DRV_USB_DEV_H */ diff --git a/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/driver/Include/drv_usb_host.h b/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/driver/Include/drv_usb_host.h new file mode 100644 index 0000000000..55ac908d52 --- /dev/null +++ b/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/driver/Include/drv_usb_host.h @@ -0,0 +1,123 @@ +/*! + \file drv_usb_host.h + \brief USB host mode low level driver header file + + \version 2020-08-01, V3.0.0, firmware for GD32F4xx +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef __DRV_USB_HOST_H +#define __DRV_USB_HOST_H + +#include "drv_usb_regs.h" +#include "usb_ch9_std.h" +#include "drv_usb_core.h" + +typedef enum _usb_pipe_mode +{ + PIPE_PERIOD = 0U, + PIPE_NON_PERIOD = 1U +} usb_pipe_mode; + +/*! + \brief get USB even frame + \param[in] udev: pointer to USB device + \param[out] none + \retval none +*/ +__STATIC_INLINE uint8_t usb_frame_even (usb_core_driver *udev) +{ + return (uint8_t)!(udev->regs.hr->HFINFR & 0x01U); +} + +/*! + \brief configure USB clock of PHY + \param[in] udev: pointer to USB device + \param[in] clock: PHY clock + \param[out] none + \retval none +*/ +__STATIC_INLINE void usb_phyclock_config (usb_core_driver *udev, uint8_t clock) +{ + udev->regs.hr->HCTL &= ~HCTL_CLKSEL; + udev->regs.hr->HCTL |= clock; +} + +/*! + \brief read USB port + \param[in] udev: pointer to USB device + \param[out] none + \retval port status +*/ +__STATIC_INLINE uint32_t usb_port_read (usb_core_driver *udev) +{ + return *udev->regs.HPCS & ~(HPCS_PE | HPCS_PCD | HPCS_PEDC); +} + +/*! + \brief get USB current speed + \param[in] udev: pointer to USB device + \param[out] none + \retval USB current speed +*/ +__STATIC_INLINE uint32_t usb_curspeed_get (usb_core_driver *udev) +{ + return *udev->regs.HPCS & HPCS_PS; +} + +/*! + \brief get USB current frame + \param[in] udev: pointer to USB device + \param[out] none + \retval USB current frame +*/ +__STATIC_INLINE uint32_t usb_curframe_get (usb_core_driver *udev) +{ + return (udev->regs.hr->HFINFR & 0xFFFFU); +} + +/* function declarations */ +/* initializes USB core for host mode */ +usb_status usb_host_init (usb_core_driver *udev); +/* control the VBUS to power */ +void usb_portvbus_switch (usb_core_driver *udev, uint8_t state); +/* reset host port */ +uint32_t usb_port_reset (usb_core_driver *udev); +/* initialize host pipe */ +usb_status usb_pipe_init (usb_core_driver *udev, uint8_t pipe_num); +/* prepare host pipe for transferring packets */ +usb_status usb_pipe_xfer (usb_core_driver *udev, uint8_t pipe_num); +/* halt host pipe */ +usb_status usb_pipe_halt (usb_core_driver *udev, uint8_t pipe_num); +/* configure host pipe to do ping operation */ +usb_status usb_pipe_ping (usb_core_driver *udev, uint8_t pipe_num); +/* stop the USB host and clean up FIFO */ +void usb_host_stop (usb_core_driver *udev); + +#endif /* __DRV_USB_HOST_H */ diff --git a/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/driver/Include/drv_usb_hw.h b/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/driver/Include/drv_usb_hw.h new file mode 100644 index 0000000000..725a8d48b0 --- /dev/null +++ b/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/driver/Include/drv_usb_hw.h @@ -0,0 +1,71 @@ +/*! + \file drv_usb_hw.h + \brief usb hardware configuration header file + + \version 2020-08-01, V3.0.0, firmware for GD32F4xx +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef __DRV_USB_HW_H +#define __DRV_USB_HW_H + +#include "usb_conf.h" + +/* function declarations */ +/* configure USB clock */ +void usb_rcu_config (void); +/* configure USB data line gpio */ +void usb_gpio_config (void); +/* configure USB interrupt */ +void usb_intr_config (void); +/* initializes delay unit using Timer2 */ +void usb_timer_init (void); +/* delay in micro seconds */ +void usb_udelay (const uint32_t usec); +/* delay in milliseconds */ +void usb_mdelay (const uint32_t msec); +/* configures system clock after wakeup from STOP mode */ +void system_clk_config_stop(void); + +/* configure the CTC peripheral */ +#ifdef USE_IRC48M + void ctc_config(void); +#endif /* USE_IRC48M */ + +#ifdef USE_HOST_MODE + void systick_config(void); + + /* configure USB VBus */ + void usb_vbus_config (void); + + /* drive USB VBus */ + void usb_vbus_drive (uint8_t State); +#endif /* USE_HOST_MODE */ + +#endif /* __DRV_USB_HW_H */ diff --git a/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/driver/Include/drv_usb_regs.h b/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/driver/Include/drv_usb_regs.h new file mode 100644 index 0000000000..9620357a5a --- /dev/null +++ b/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/driver/Include/drv_usb_regs.h @@ -0,0 +1,662 @@ +/*! + \file drv_usb_regs.h + \brief USB cell registers definition and handle macros + + \version 2020-08-01, V3.0.0, firmware for GD32F4xx +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef __DRV_USB_REGS_H +#define __DRV_USB_REGS_H + +#include "usb_conf.h" + +#define USBHS_REG_BASE 0x40040000L /*!< base address of USBHS registers */ +#define USBFS_REG_BASE 0x50000000L /*!< base address of USBFS registers */ + +#define USBFS_MAX_TX_FIFOS 15U /*!< FIFO number */ + +#define USBFS_MAX_PACKET_SIZE 64U /*!< USBFS max packet size */ +#define USBFS_MAX_CHANNEL_COUNT 8U /*!< USBFS host channel count */ +#define USBFS_MAX_EP_COUNT 4U /*!< USBFS device endpoint count */ +#define USBFS_MAX_FIFO_WORDLEN 320U /*!< USBFS max fifo size in words */ + +#define USBHS_MAX_PACKET_SIZE 512U /*!< USBHS max packet size */ +#define USBHS_MAX_CHANNEL_COUNT 12U /*!< USBHS host channel count */ +#define USBHS_MAX_EP_COUNT 6U /*!< USBHS device endpoint count */ +#define USBHS_MAX_FIFO_WORDLEN 1280U /*!< USBHS max fifo size in words */ + +#define USB_DATA_FIFO_OFFSET 0x1000U /*!< USB data fifo offset */ +#define USB_DATA_FIFO_SIZE 0x1000U /*!< USB data fifo size */ + +typedef enum +{ + USB_CORE_ENUM_HS = 0, /*!< USB core type is HS */ + USB_CORE_ENUM_FS = 1 /*!< USB core type is FS */ +} usb_core_enum; + +enum USB_SPEED { + USB_SPEED_UNKNOWN = 0, /*!< USB speed unknown */ + USB_SPEED_LOW, /*!< USB speed low */ + USB_SPEED_FULL, /*!< USB speed full */ + USB_SPEED_HIGH, /*!< USB speed high */ +}; + +enum usb_reg_offset { + USB_REG_OFFSET_CORE = 0x0000U, /*!< global OTG control and status register */ + USB_REG_OFFSET_DEV = 0x0800U, /*!< device mode control and status registers */ + USB_REG_OFFSET_EP = 0x0020U, + USB_REG_OFFSET_EP_IN = 0x0900U, /*!< device IN endpoint 0 control register */ + USB_REG_OFFSET_EP_OUT = 0x0B00U, /*!< device OUT endpoint 0 control register */ + USB_REG_OFFSET_HOST = 0x0400U, /*!< host control register */ + USB_REG_OFFSET_CH = 0x0020U, + USB_REG_OFFSET_PORT = 0x0440U, /*!< host port control and status register */ + USB_REG_OFFSET_CH_INOUT = 0x0500U, /*!< Host channel-x control registers */ + USB_REG_OFFSET_PWRCLKCTL = 0x0E00U, /*!< power and clock register */ +}; + +typedef struct +{ + __IO uint32_t GOTGCS; /*!< USB global OTG control and status register 000h */ + __IO uint32_t GOTGINTF; /*!< USB global OTG interrupt flag register 004h */ + __IO uint32_t GAHBCS; /*!< USB global AHB control and status register 008h */ + __IO uint32_t GUSBCS; /*!< USB global USB control and status register 00Ch */ + __IO uint32_t GRSTCTL; /*!< USB global reset control register 010h */ + __IO uint32_t GINTF; /*!< USB global interrupt flag register 014h */ + __IO uint32_t GINTEN; /*!< USB global interrupt enable register 018h */ + __IO uint32_t GRSTATR; /*!< USB receive status debug read register 01Ch */ + __IO uint32_t GRSTATP; /*!< USB receive status and pop register 020h */ + __IO uint32_t GRFLEN; /*!< USB global receive FIFO length register 024h */ + __IO uint32_t DIEP0TFLEN_HNPTFLEN; /*!< USB device IN endpoint 0/host non-periodic transmit FIFO length register 028h */ + __IO uint32_t HNPTFQSTAT; /*!< USB host non-periodic FIFO/queue status register 02Ch */ + uint32_t Reserved30[2]; /*!< Reserved 030h */ + __IO uint32_t GCCFG; /*!< USB global core configuration register 038h */ + __IO uint32_t CID; /*!< USB core ID register 03Ch */ + uint32_t Reserved40[48]; /*!< Reserved 040h-0FFh */ + __IO uint32_t HPTFLEN; /*!< USB host periodic transmit FIFO length register 100h */ + __IO uint32_t DIEPTFLEN[15]; /*!< USB device IN endpoint transmit FIFO length register 104h */ +} usb_gr; + + +typedef struct +{ + __IO uint32_t HCTL; /*!< USB host control register 400h */ + __IO uint32_t HFT; /*!< USB host frame interval register 404h */ + __IO uint32_t HFINFR; /*!< USB host frame information remaining register 408h */ + uint32_t Reserved40C; /*!< Reserved 40Ch */ + __IO uint32_t HPTFQSTAT; /*!< USB host periodic transmit FIFO/queue status register 410h */ + __IO uint32_t HACHINT; /*!< USB host all channels interrupt register 414h */ + __IO uint32_t HACHINTEN; /*!< USB host all channels interrupt enable register 418h */ +} usb_hr; + +typedef struct +{ + __IO uint32_t HCHCTL; /*!< USB host channel control register 500h */ + __IO uint32_t HCHSTCTL; /*!< Reserved 504h */ + __IO uint32_t HCHINTF; /*!< USB host channel interrupt flag register 508h */ + __IO uint32_t HCHINTEN; /*!< USB host channel interrupt enable register 50Ch */ + __IO uint32_t HCHLEN; /*!< USB host channel transfer length register 510h */ + __IO uint32_t HCHDMAADDR; /*!< USB host channel-x DMA address register 514h*/ + uint32_t Reserved[2]; +} usb_pr; + +typedef struct +{ + __IO uint32_t DCFG; /*!< USB device configuration register 800h */ + __IO uint32_t DCTL; /*!< USB device control register 804h */ + __IO uint32_t DSTAT; /*!< USB device status register 808h */ + uint32_t Reserved0C; /*!< Reserved 80Ch */ + __IO uint32_t DIEPINTEN; /*!< USB device IN endpoint common interrupt enable register 810h */ + __IO uint32_t DOEPINTEN; /*!< USB device OUT endpoint common interrupt enable register 814h */ + __IO uint32_t DAEPINT; /*!< USB device all endpoints interrupt register 818h */ + __IO uint32_t DAEPINTEN; /*!< USB device all endpoints interrupt enable register 81Ch */ + uint32_t Reserved20; /*!< Reserved 820h */ + uint32_t Reserved24; /*!< Reserved 824h */ + __IO uint32_t DVBUSDT; /*!< USB device VBUS discharge time register 828h */ + __IO uint32_t DVBUSPT; /*!< USB device VBUS pulsing time register 82Ch */ + __IO uint32_t DTHRCTL; /*!< device threshold control 830h */ + __IO uint32_t DIEPFEINTEN; /*!< USB Device IN endpoint FIFO empty interrupt enable register 834h */ + __IO uint32_t DEP1INT; /*!< USB device endpoint 1 interrupt register 838h */ + __IO uint32_t DEP1INTEN; /*!< USB device endpoint 1 interrupt enable register 83Ch */ + uint32_t Reserved40; /*!< Reserved 840h */ + __IO uint32_t DIEP1INTEN; /*!< USB device IN endpoint-1 interrupt enable register 844h */ + uint32_t Reserved48[15]; /*!< Reserved 848-880h */ + __IO uint32_t DOEP1INTEN; /*!< USB device OUT endpoint-1 interrupt enable register 884h */ +} usb_dr; + +typedef struct +{ + __IO uint32_t DIEPCTL; /*!< USB device IN endpoint control register 900h + (EpNum * 20h) + 00h */ + uint32_t Reserved04; /*!< Reserved 900h + (EpNum * 20h) + 04h */ + __IO uint32_t DIEPINTF; /*!< USB device IN endpoint interrupt flag register 900h + (EpNum * 20h) + 08h */ + uint32_t Reserved0C; /*!< Reserved 900h + (EpNum * 20h) + 0Ch */ + __IO uint32_t DIEPLEN; /*!< USB device IN endpoint transfer length register 900h + (EpNum * 20h) + 10h */ + __IO uint32_t DIEPDMAADDR; /*!< Device IN endpoint-x DMA address register 900h + (EpNum * 20h) + 14h */ + __IO uint32_t DIEPTFSTAT; /*!< USB device IN endpoint transmit FIFO status register 900h + (EpNum * 20h) + 18h */ +} usb_erin; + +typedef struct +{ + __IO uint32_t DOEPCTL; /*!< USB device IN endpoint control register B00h + (EpNum * 20h) + 00h */ + uint32_t Reserved04; /*!< Reserved B00h + (EpNum * 20h) + 04h */ + __IO uint32_t DOEPINTF; /*!< USB device IN endpoint interrupt flag register B00h + (EpNum * 20h) + 08h */ + uint32_t Reserved0C; /*!< Reserved B00h + (EpNum * 20h) + 0Ch */ + __IO uint32_t DOEPLEN; /*!< USB device IN endpoint transfer length register B00h + (EpNum * 20h) + 10h */ + __IO uint32_t DOEPDMAADDR; /*!< Device OUT endpoint-x DMA address register B00h + (EpNum * 20h) + 0Ch */ +} usb_erout; + +typedef struct _usb_regs +{ + usb_gr *gr; /*!< USBFS global registers */ + usb_dr *dr; /*!< Device control and status registers */ + usb_hr *hr; /*!< Host control and status registers */ + usb_erin *er_in[6]; /*!< USB device IN endpoint register */ + usb_erout *er_out[6]; /*!< USB device OUT endpoint register */ + usb_pr *pr[15]; /*!< USB Host channel-x control register */ + + __IO uint32_t *HPCS; /*!< USB host port control and status register */ + __IO uint32_t *DFIFO[USBFS_MAX_TX_FIFOS]; + __IO uint32_t *PWRCLKCTL; /*!< USB power and clock control register */ +} usb_core_regs; + +/* global OTG control and status register bits definitions */ +#define GOTGCS_BSV BIT(19) /*!< B-Session Valid */ +#define GOTGCS_ASV BIT(18) /*!< A-session valid */ +#define GOTGCS_DI BIT(17) /*!< debounce interval */ +#define GOTGCS_CIDPS BIT(16) /*!< id pin status */ +#define GOTGCS_DHNPEN BIT(11) /*!< device HNP enable */ +#define GOTGCS_HHNPEN BIT(10) /*!< host HNP enable */ +#define GOTGCS_HNPREQ BIT(9) /*!< HNP request */ +#define GOTGCS_HNPS BIT(8) /*!< HNP successes */ +#define GOTGCS_SRPREQ BIT(1) /*!< SRP request */ +#define GOTGCS_SRPS BIT(0) /*!< SRP successes */ + +/* global OTG interrupt flag register bits definitions */ +#define GOTGINTF_DF BIT(19) /*!< debounce finish */ +#define GOTGINTF_ADTO BIT(18) /*!< A-device timeout */ +#define GOTGINTF_HNPDET BIT(17) /*!< host negotiation request detected */ +#define GOTGINTF_HNPEND BIT(9) /*!< HNP end */ +#define GOTGINTF_SRPEND BIT(8) /*!< SRP end */ +#define GOTGINTF_SESEND BIT(2) /*!< session end */ + +/* global AHB control and status register bits definitions */ +#define GAHBCS_PTXFTH BIT(8) /*!< periodic Tx FIFO threshold */ +#define GAHBCS_TXFTH BIT(7) /*!< tx FIFO threshold */ +#define GAHBCS_DMAEN BIT(5) /*!< DMA function Enable */ +#define GAHBCS_BURST BITS(1, 4) /*!< the AHB burst type used by DMA */ +#define GAHBCS_GINTEN BIT(0) /*!< global interrupt enable */ + +/* global USB control and status register bits definitions */ +#define GUSBCS_FDM BIT(30) /*!< force device mode */ +#define GUSBCS_FHM BIT(29) /*!< force host mode */ +#define GUSBCS_ULPIEOI BIT(21) /*!< ULPI external over-current indicator */ +#define GUSBCS_ULPIEVD BIT(20) /*!< ULPI external VBUS driver */ +#define GUSBCS_UTT BITS(10, 13) /*!< USB turnaround time */ +#define GUSBCS_HNPCEN BIT(9) /*!< HNP capability enable */ +#define GUSBCS_SRPCEN BIT(8) /*!< SRP capability enable */ +#define GUSBCS_EMBPHY BIT(6) /*!< embedded PHY selected */ +#define GUSBCS_TOC BITS(0, 2) /*!< timeout calibration */ + +/* global reset control register bits definitions */ +#define GRSTCTL_DMAIDL BIT(31) /*!< DMA idle state */ +#define GRSTCTL_DMABSY BIT(30) /*!< DMA busy */ +#define GRSTCTL_TXFNUM BITS(6, 10) /*!< tx FIFO number */ +#define GRSTCTL_TXFF BIT(5) /*!< tx FIFO flush */ +#define GRSTCTL_RXFF BIT(4) /*!< rx FIFO flush */ +#define GRSTCTL_HFCRST BIT(2) /*!< host frame counter reset */ +#define GRSTCTL_HCSRST BIT(1) /*!< HCLK soft reset */ +#define GRSTCTL_CSRST BIT(0) /*!< core soft reset */ + +/* global interrupt flag register bits definitions */ +#define GINTF_WKUPIF BIT(31) /*!< wakeup interrupt flag */ +#define GINTF_SESIF BIT(30) /*!< session interrupt flag */ +#define GINTF_DISCIF BIT(29) /*!< disconnect interrupt flag */ +#define GINTF_IDPSC BIT(28) /*!< id pin status change */ +#define GINTF_PTXFEIF BIT(26) /*!< periodic tx FIFO empty interrupt flag */ +#define GINTF_HCIF BIT(25) /*!< host channels interrupt flag */ +#define GINTF_HPIF BIT(24) /*!< host port interrupt flag */ +#define GINTF_PXNCIF BIT(21) /*!< periodic transfer not complete interrupt flag */ +#define GINTF_ISOONCIF BIT(21) /*!< isochronous OUT transfer not complete interrupt flag */ +#define GINTF_ISOINCIF BIT(20) /*!< isochronous IN transfer not complete interrupt flag */ +#define GINTF_OEPIF BIT(19) /*!< OUT endpoint interrupt flag */ +#define GINTF_IEPIF BIT(18) /*!< IN endpoint interrupt flag */ +#define GINTF_EOPFIF BIT(15) /*!< end of periodic frame interrupt flag */ +#define GINTF_ISOOPDIF BIT(14) /*!< isochronous OUT packet dropped interrupt flag */ +#define GINTF_ENUMFIF BIT(13) /*!< enumeration finished */ +#define GINTF_RST BIT(12) /*!< USB reset */ +#define GINTF_SP BIT(11) /*!< USB suspend */ +#define GINTF_ESP BIT(10) /*!< early suspend */ +#define GINTF_GONAK BIT(7) /*!< global OUT NAK effective */ +#define GINTF_GNPINAK BIT(6) /*!< global IN non-periodic NAK effective */ +#define GINTF_NPTXFEIF BIT(5) /*!< non-periodic tx FIFO empty interrupt flag */ +#define GINTF_RXFNEIF BIT(4) /*!< rx FIFO non-empty interrupt flag */ +#define GINTF_SOF BIT(3) /*!< start of frame */ +#define GINTF_OTGIF BIT(2) /*!< OTG interrupt flag */ +#define GINTF_MFIF BIT(1) /*!< mode fault interrupt flag */ +#define GINTF_COPM BIT(0) /*!< current operation mode */ + +/* global interrupt enable register bits definitions */ +#define GINTEN_WKUPIE BIT(31) /*!< wakeup interrupt enable */ +#define GINTEN_SESIE BIT(30) /*!< session interrupt enable */ +#define GINTEN_DISCIE BIT(29) /*!< disconnect interrupt enable */ +#define GINTEN_IDPSCIE BIT(28) /*!< id pin status change interrupt enable */ +#define GINTEN_PTXFEIE BIT(26) /*!< periodic tx FIFO empty interrupt enable */ +#define GINTEN_HCIE BIT(25) /*!< host channels interrupt enable */ +#define GINTEN_HPIE BIT(24) /*!< host port interrupt enable */ +#define GINTEN_IPXIE BIT(21) /*!< periodic transfer not complete interrupt enable */ +#define GINTEN_ISOONCIE BIT(21) /*!< isochronous OUT transfer not complete interrupt enable */ +#define GINTEN_ISOINCIE BIT(20) /*!< isochronous IN transfer not complete interrupt enable */ +#define GINTEN_OEPIE BIT(19) /*!< OUT endpoints interrupt enable */ +#define GINTEN_IEPIE BIT(18) /*!< IN endpoints interrupt enable */ +#define GINTEN_EOPFIE BIT(15) /*!< end of periodic frame interrupt enable */ +#define GINTEN_ISOOPDIE BIT(14) /*!< isochronous OUT packet dropped interrupt enable */ +#define GINTEN_ENUMFIE BIT(13) /*!< enumeration finish enable */ +#define GINTEN_RSTIE BIT(12) /*!< USB reset interrupt enable */ +#define GINTEN_SPIE BIT(11) /*!< USB suspend interrupt enable */ +#define GINTEN_ESPIE BIT(10) /*!< early suspend interrupt enable */ +#define GINTEN_GONAKIE BIT(7) /*!< global OUT NAK effective interrupt enable */ +#define GINTEN_GNPINAKIE BIT(6) /*!< global non-periodic IN NAK effective interrupt enable */ +#define GINTEN_NPTXFEIE BIT(5) /*!< non-periodic Tx FIFO empty interrupt enable */ +#define GINTEN_RXFNEIE BIT(4) /*!< receive FIFO non-empty interrupt enable */ +#define GINTEN_SOFIE BIT(3) /*!< start of frame interrupt enable */ +#define GINTEN_OTGIE BIT(2) /*!< OTG interrupt enable */ +#define GINTEN_MFIE BIT(1) /*!< mode fault interrupt enable */ + +/* global receive status read and pop register bits definitions */ +#define GRSTATRP_RPCKST BITS(17, 20) /*!< received packet status */ +#define GRSTATRP_DPID BITS(15, 16) /*!< data PID */ +#define GRSTATRP_BCOUNT BITS(4, 14) /*!< byte count */ +#define GRSTATRP_CNUM BITS(0, 3) /*!< channel number */ +#define GRSTATRP_EPNUM BITS(0, 3) /*!< endpoint number */ + +/* global receive FIFO length register bits definitions */ +#define GRFLEN_RXFD BITS(0, 15) /*!< rx FIFO depth */ + +/* host non-periodic transmit FIFO length register bits definitions */ +#define HNPTFLEN_HNPTXFD BITS(16, 31) /*!< non-periodic Tx FIFO depth */ +#define HNPTFLEN_HNPTXRSAR BITS(0, 15) /*!< non-periodic Tx RAM start address */ + +/** + * @brief USB IN endpoint 0 transmit FIFO length register bits definitions + */ +#define DIEP0TFLEN_IEP0TXFD BITS(16, 31) /*!< IN Endpoint 0 Tx FIFO depth */ +#define DIEP0TFLEN_IEP0TXRSAR BITS(0, 15) /*!< IN Endpoint 0 TX RAM start address */ + +/* host non-periodic transmit FIFO/queue status register bits definitions */ +#define HNPTFQSTAT_NPTXRQTOP BITS(24, 30) /*!< top entry of the non-periodic Tx request queue */ +#define HNPTFQSTAT_NPTXRQS BITS(16, 23) /*!< non-periodic Tx request queue space */ +#define HNPTFQSTAT_NPTXFS BITS(0, 15) /*!< non-periodic Tx FIFO space */ +#define HNPTFQSTAT_CNUM BITS(27, 30) /*!< channel number*/ +#define HNPTFQSTAT_EPNUM BITS(27, 30) /*!< endpoint number */ +#define HNPTFQSTAT_TYPE BITS(25, 26) /*!< token type */ +#define HNPTFQSTAT_TMF BIT(24) /*!< terminate flag */ + +/* global core configuration register bits definitions */ +#define GCCFG_VBUSIG BIT(21) /*!< vbus ignored */ +#define GCCFG_SOFOEN BIT(20) /*!< SOF output enable */ +#define GCCFG_VBUSBCEN BIT(19) /*!< the VBUS B-device comparer enable */ +#define GCCFG_VBUSACEN BIT(18) /*!< the VBUS A-device comparer enable */ +#define GCCFG_PWRON BIT(16) /*!< power on */ + +/* core ID register bits definitions */ +#define CID_CID BITS(0, 31) /*!< core ID */ + +/* host periodic transmit FIFO length register bits definitions */ +#define HPTFLEN_HPTXFD BITS(16, 31) /*!< host periodic Tx FIFO depth */ +#define HPTFLEN_HPTXFSAR BITS(0, 15) /*!< host periodic Tx RAM start address */ + +/* device IN endpoint transmit FIFO length register bits definitions */ +#define DIEPTFLEN_IEPTXFD BITS(16, 31) /*!< IN endpoint Tx FIFO x depth */ +#define DIEPTFLEN_IEPTXRSAR BITS(0, 15) /*!< IN endpoint FIFOx Tx x RAM start address */ + +/* host control register bits definitions */ +#define HCTL_SPDFSLS BIT(2) /*!< speed limited to FS and LS */ +#define HCTL_CLKSEL BITS(0, 1) /*!< clock select for USB clock */ + +/* host frame interval register bits definitions */ +#define HFT_FRI BITS(0, 15) /*!< frame interval */ + +/* host frame information remaining register bits definitions */ +#define HFINFR_FRT BITS(16, 31) /*!< frame remaining time */ +#define HFINFR_FRNUM BITS(0, 15) /*!< frame number */ + +/* host periodic transmit FIFO/queue status register bits definitions */ +#define HPTFQSTAT_PTXREQT BITS(24, 31) /*!< top entry of the periodic Tx request queue */ +#define HPTFQSTAT_PTXREQS BITS(16, 23) /*!< periodic Tx request queue space */ +#define HPTFQSTAT_PTXFS BITS(0, 15) /*!< periodic Tx FIFO space */ +#define HPTFQSTAT_OEFRM BIT(31) /*!< odd/eveb frame */ +#define HPTFQSTAT_CNUM BITS(27, 30) /*!< channel number */ +#define HPTFQSTAT_EPNUM BITS(27, 30) /*!< endpoint number */ +#define HPTFQSTAT_TYPE BITS(25, 26) /*!< token type */ +#define HPTFQSTAT_TMF BIT(24) /*!< terminate flag */ + + +#define TFQSTAT_TXFS BITS(0, 15) +#define TFQSTAT_CNUM BITS(27, 30) + +/* host all channels interrupt register bits definitions */ +#define HACHINT_HACHINT BITS(0, 11) /*!< host all channel interrupts */ + +/* host all channels interrupt enable register bits definitions */ +#define HACHINTEN_CINTEN BITS(0, 11) /*!< channel interrupt enable */ + +/* host port control and status register bits definitions */ +#define HPCS_PS BITS(17, 18) /*!< port speed */ +#define HPCS_PP BIT(12) /*!< port power */ +#define HPCS_PLST BITS(10, 11) /*!< port line status */ +#define HPCS_PRST BIT(8) /*!< port reset */ +#define HPCS_PSP BIT(7) /*!< port suspend */ +#define HPCS_PREM BIT(6) /*!< port resume */ +#define HPCS_PEDC BIT(3) /*!< port enable/disable change */ +#define HPCS_PE BIT(2) /*!< port enable */ +#define HPCS_PCD BIT(1) /*!< port connect detected */ +#define HPCS_PCST BIT(0) /*!< port connect status */ + +/* host channel-x control register bits definitions */ +#define HCHCTL_CEN BIT(31) /*!< channel enable */ +#define HCHCTL_CDIS BIT(30) /*!< channel disable */ +#define HCHCTL_ODDFRM BIT(29) /*!< odd frame */ +#define HCHCTL_DAR BITS(22, 28) /*!< device address */ +#define HCHCTL_MPC BITS(20, 21) /*!< multiple packet count */ +#define HCHCTL_EPTYPE BITS(18, 19) /*!< endpoint type */ +#define HCHCTL_LSD BIT(17) /*!< low-speed device */ +#define HCHCTL_EPDIR BIT(15) /*!< endpoint direction */ +#define HCHCTL_EPNUM BITS(11, 14) /*!< endpoint number */ +#define HCHCTL_MPL BITS(0, 10) /*!< maximum packet length */ + +/* host channel-x split transaction register bits definitions */ +#define HCHSTCTL_SPLEN BIT(31) /*!< enable high-speed split transaction */ +#define HCHSTCTL_CSPLT BIT(16) /*!< complete-split enable */ +#define HCHSTCTL_ISOPCE BITS(14, 15) /*!< isochronous OUT payload continuation encoding */ +#define HCHSTCTL_HADDR BITS(7, 13) /*!< HUB address */ +#define HCHSTCTL_PADDR BITS(0, 6) /*!< port address */ + +/* host channel-x interrupt flag register bits definitions */ +#define HCHINTF_DTER BIT(10) /*!< data toggle error */ +#define HCHINTF_REQOVR BIT(9) /*!< request queue overrun */ +#define HCHINTF_BBER BIT(8) /*!< babble error */ +#define HCHINTF_USBER BIT(7) /*!< USB bus Error */ +#define HCHINTF_NYET BIT(6) /*!< NYET */ +#define HCHINTF_ACK BIT(5) /*!< ACK */ +#define HCHINTF_NAK BIT(4) /*!< NAK */ +#define HCHINTF_STALL BIT(3) /*!< STALL */ +#define HCHINTF_DMAER BIT(2) /*!< DMA error */ +#define HCHINTF_CH BIT(1) /*!< channel halted */ +#define HCHINTF_TF BIT(0) /*!< transfer finished */ + +/* host channel-x interrupt enable register bits definitions */ +#define HCHINTEN_DTERIE BIT(10) /*!< data toggle error interrupt enable */ +#define HCHINTEN_REQOVRIE BIT(9) /*!< request queue overrun interrupt enable */ +#define HCHINTEN_BBERIE BIT(8) /*!< babble error interrupt enable */ +#define HCHINTEN_USBERIE BIT(7) /*!< USB bus error interrupt enable */ +#define HCHINTEN_NYETIE BIT(6) /*!< NYET interrupt enable */ +#define HCHINTEN_ACKIE BIT(5) /*!< ACK interrupt enable */ +#define HCHINTEN_NAKIE BIT(4) /*!< NAK interrupt enable */ +#define HCHINTEN_STALLIE BIT(3) /*!< STALL interrupt enable */ +#define HCHINTEN_DMAERIE BIT(2) /*!< DMA error interrupt enable */ +#define HCHINTEN_CHIE BIT(1) /*!< channel halted interrupt enable */ +#define HCHINTEN_TFIE BIT(0) /*!< transfer finished interrupt enable */ + +/* host channel-x transfer length register bits definitions */ +#define HCHLEN_PING BIT(31) /*!< PING token request */ +#define HCHLEN_DPID BITS(29, 30) /*!< data PID */ +#define HCHLEN_PCNT BITS(19, 28) /*!< packet count */ +#define HCHLEN_TLEN BITS(0, 18) /*!< transfer length */ + +/* host channel-x DMA address register bits definitions */ +#define HCHDMAADDR_DMAADDR BITS(0, 31) /*!< DMA address */ + + +#define PORT_SPEED(x) (((uint32_t)(x) << 17) & HPCS_PS) /*!< Port speed */ + +#define PORT_SPEED_HIGH PORT_SPEED(0U) /*!< high speed */ +#define PORT_SPEED_FULL PORT_SPEED(1U) /*!< full speed */ +#define PORT_SPEED_LOW PORT_SPEED(2U) /*!< low speed */ + +#define PIPE_CTL_DAR(x) (((uint32_t)(x) << 22) & HCHCTL_DAR) /*!< device address */ +#define PIPE_CTL_EPTYPE(x) (((uint32_t)(x) << 18) & HCHCTL_EPTYPE) /*!< endpoint type */ +#define PIPE_CTL_EPNUM(x) (((uint32_t)(x) << 11) & HCHCTL_EPNUM) /*!< endpoint number */ +#define PIPE_CTL_EPDIR(x) (((uint32_t)(x) << 15) & HCHCTL_EPDIR) /*!< endpoint direction */ +#define PIPE_CTL_EPMPL(x) (((uint32_t)(x) << 0) & HCHCTL_MPL) /*!< maximum packet length */ +#define PIPE_CTL_LSD(x) (((uint32_t)(x) << 17) & HCHCTL_LSD) /*!< low-Speed device */ + +#define PIPE_XFER_PCNT(x) (((uint32_t)(x) << 19) & HCHLEN_PCNT) /*!< packet count */ +#define PIPE_XFER_DPID(x) (((uint32_t)(x) << 29) & HCHLEN_DPID) /*!< data PID */ + +#define PIPE_DPID_DATA0 PIPE_XFER_DPID(0) /*!< DATA0 */ +#define PIPE_DPID_DATA1 PIPE_XFER_DPID(2) /*!< DATA1 */ +#define PIPE_DPID_DATA2 PIPE_XFER_DPID(1) /*!< DATA2 */ +#define PIPE_DPID_SETUP PIPE_XFER_DPID(3) /*!< MDATA (non-control)/SETUP (control) */ + +extern const uint32_t PIPE_DPID[2]; + +/* device configuration registers bits definitions */ +#define DCFG_EOPFT BITS(11, 12) /*!< end of periodic frame time */ +#define DCFG_DAR BITS(4, 10) /*!< device address */ +#define DCFG_NZLSOH BIT(2) /*!< non-zero-length status OUT handshake */ +#define DCFG_DS BITS(0, 1) /*!< device speed */ + +/* device control registers bits definitions */ +#define DCTL_POIF BIT(11) /*!< power-on initialization finished */ +#define DCTL_CGONAK BIT(10) /*!< clear global OUT NAK */ +#define DCTL_SGONAK BIT(9) /*!< set global OUT NAK */ +#define DCTL_CGINAK BIT(8) /*!< clear global IN NAK */ +#define DCTL_SGINAK BIT(7) /*!< set global IN NAK */ +#define DCTL_GONS BIT(3) /*!< global OUT NAK status */ +#define DCTL_GINS BIT(2) /*!< global IN NAK status */ +#define DCTL_SD BIT(1) /*!< soft disconnect */ +#define DCTL_RWKUP BIT(0) /*!< remote wakeup */ + +/* device status registers bits definitions */ +#define DSTAT_FNRSOF BITS(8, 21) /*!< the frame number of the received SOF. */ +#define DSTAT_ES BITS(1, 2) /*!< enumerated speed */ +#define DSTAT_SPST BIT(0) /*!< suspend status */ + +/* device IN endpoint common interrupt enable registers bits definitions */ +#define DIEPINTEN_NAKEN BIT(13) /*!< NAK handshake sent by USBHS interrupt enable bit */ +#define DIEPINTEN_TXFEEN BIT(7) /*!< transmit FIFO empty interrupt enable bit */ +#define DIEPINTEN_IEPNEEN BIT(6) /*!< IN endpoint NAK effective interrupt enable bit */ +#define DIEPINTEN_EPTXFUDEN BIT(4) /*!< endpoint Tx FIFO underrun interrupt enable bit */ +#define DIEPINTEN_CITOEN BIT(3) /*!< control In Timeout interrupt enable bit */ +#define DIEPINTEN_EPDISEN BIT(1) /*!< endpoint disabled interrupt enable bit */ +#define DIEPINTEN_TFEN BIT(0) /*!< transfer finished interrupt enable bit */ + +/* device OUT endpoint common interrupt enable registers bits definitions */ +#define DOEPINTEN_NYETEN BIT(14) /*!< NYET handshake is sent interrupt enable bit */ +#define DOEPINTEN_BTBSTPEN BIT(6) /*!< back-to-back SETUP packets interrupt enable bit */ +#define DOEPINTEN_EPRXFOVREN BIT(4) /*!< endpoint Rx FIFO overrun interrupt enable bit */ +#define DOEPINTEN_STPFEN BIT(3) /*!< SETUP phase finished interrupt enable bit */ +#define DOEPINTEN_EPDISEN BIT(1) /*!< endpoint disabled interrupt enable bit */ +#define DOEPINTEN_TFEN BIT(0) /*!< transfer finished interrupt enable bit */ + +/* device all endpoints interrupt registers bits definitions */ +#define DAEPINT_OEPITB BITS(16, 21) /*!< device all OUT endpoint interrupt bits */ +#define DAEPINT_IEPITB BITS(0, 5) /*!< device all IN endpoint interrupt bits */ + +/* device all endpoints interrupt enable registers bits definitions */ +#define DAEPINTEN_OEPIE BITS(16, 21) /*!< OUT endpoint interrupt enable */ +#define DAEPINTEN_IEPIE BITS(0, 3) /*!< IN endpoint interrupt enable */ + +/* device Vbus discharge time registers bits definitions */ +#define DVBUSDT_DVBUSDT BITS(0, 15) /*!< device VBUS discharge time */ + +/* device Vbus pulsing time registers bits definitions */ +#define DVBUSPT_DVBUSPT BITS(0, 11) /*!< device VBUS pulsing time */ + +/* device IN endpoint FIFO empty interrupt enable register bits definitions */ +#define DIEPFEINTEN_IEPTXFEIE BITS(0, 5) /*!< IN endpoint Tx FIFO empty interrupt enable bits */ + +/* device endpoint 0 control register bits definitions */ +#define DEP0CTL_EPEN BIT(31) /*!< endpoint enable */ +#define DEP0CTL_EPD BIT(30) /*!< endpoint disable */ +#define DEP0CTL_SNAK BIT(27) /*!< set NAK */ +#define DEP0CTL_CNAK BIT(26) /*!< clear NAK */ +#define DIEP0CTL_TXFNUM BITS(22, 25) /*!< tx FIFO number */ +#define DEP0CTL_STALL BIT(21) /*!< STALL handshake */ +#define DOEP0CTL_SNOOP BIT(20) /*!< snoop mode */ +#define DEP0CTL_EPTYPE BITS(18, 19) /*!< endpoint type */ +#define DEP0CTL_NAKS BIT(17) /*!< NAK status */ +#define DEP0CTL_EPACT BIT(15) /*!< endpoint active */ +#define DEP0CTL_MPL BITS(0, 1) /*!< maximum packet length */ + +/* device endpoint x control register bits definitions */ +#define DEPCTL_EPEN BIT(31) /*!< endpoint enable */ +#define DEPCTL_EPD BIT(30) /*!< endpoint disable */ +#define DEPCTL_SODDFRM BIT(29) /*!< set odd frame */ +#define DEPCTL_SD1PID BIT(29) /*!< set DATA1 PID */ +#define DEPCTL_SEVNFRM BIT(28) /*!< set even frame */ +#define DEPCTL_SD0PID BIT(28) /*!< set DATA0 PID */ +#define DEPCTL_SNAK BIT(27) /*!< set NAK */ +#define DEPCTL_CNAK BIT(26) /*!< clear NAK */ +#define DIEPCTL_TXFNUM BITS(22, 25) /*!< tx FIFO number */ +#define DEPCTL_STALL BIT(21) /*!< STALL handshake */ +#define DOEPCTL_SNOOP BIT(20) /*!< snoop mode */ +#define DEPCTL_EPTYPE BITS(18, 19) /*!< endpoint type */ +#define DEPCTL_NAKS BIT(17) /*!< NAK status */ +#define DEPCTL_EOFRM BIT(16) /*!< even/odd frame */ +#define DEPCTL_DPID BIT(16) /*!< endpoint data PID */ +#define DEPCTL_EPACT BIT(15) /*!< endpoint active */ +#define DEPCTL_MPL BITS(0, 10) /*!< maximum packet length */ + +/* device IN endpoint-x interrupt flag register bits definitions */ +#define DIEPINTF_NAK BIT(13) /*!< NAK handshake sent by USBHS */ +#define DIEPINTF_TXFE BIT(7) /*!< transmit FIFO empty */ +#define DIEPINTF_IEPNE BIT(6) /*!< IN endpoint NAK effective */ +#define DIEPINTF_EPTXFUD BIT(4) /*!< endpoint Tx FIFO underrun */ +#define DIEPINTF_CITO BIT(3) /*!< control In Timeout interrupt */ +#define DIEPINTF_EPDIS BIT(1) /*!< endpoint disabled */ +#define DIEPINTF_TF BIT(0) /*!< transfer finished */ + +/* device OUT endpoint-x interrupt flag register bits definitions */ +#define DOEPINTF_NYET BIT(14) /*!< NYET handshake is sent */ +#define DOEPINTF_BTBSTP BIT(6) /*!< back-to-back SETUP packets */ +#define DOEPINTF_EPRXFOVR BIT(4) /*!< endpoint Rx FIFO overrun */ +#define DOEPINTF_STPF BIT(3) /*!< SETUP phase finished */ +#define DOEPINTF_EPDIS BIT(1) /*!< endpoint disabled */ +#define DOEPINTF_TF BIT(0) /*!< transfer finished */ + +/* device IN endpoint 0 transfer length register bits definitions */ +#define DIEP0LEN_PCNT BITS(19, 20) /*!< packet count */ +#define DIEP0LEN_TLEN BITS(0, 6) /*!< transfer length */ + +/* device OUT endpoint 0 transfer length register bits definitions */ +#define DOEP0LEN_STPCNT BITS(29, 30) /*!< SETUP packet count */ +#define DOEP0LEN_PCNT BIT(19) /*!< packet count */ +#define DOEP0LEN_TLEN BITS(0, 6) /*!< transfer length */ + +/* device OUT endpoint-x transfer length register bits definitions */ +#define DOEPLEN_RXDPID BITS(29, 30) /*!< received data PID */ +#define DOEPLEN_STPCNT BITS(29, 30) /*!< SETUP packet count */ +#define DIEPLEN_MCNT BITS(29, 30) /*!< multi count */ +#define DEPLEN_PCNT BITS(19, 28) /*!< packet count */ +#define DEPLEN_TLEN BITS(0, 18) /*!< transfer length */ + +/* device IN endpoint-x DMA address register bits definitions */ +#define DIEPDMAADDR_DMAADDR BITS(0, 31) /*!< DMA address */ + +/* device OUT endpoint-x DMA address register bits definitions */ +#define DOEPDMAADDR_DMAADDR BITS(0, 31) /*!< DMA address */ + +/* device IN endpoint-x transmit FIFO status register bits definitions */ +#define DIEPTFSTAT_IEPTFS BITS(0, 15) /*!< IN endpoint Tx FIFO space remaining */ + +/* USB power and clock registers bits definition */ +#define PWRCLKCTL_SHCLK BIT(1) /*!< stop HCLK */ +#define PWRCLKCTL_SUCLK BIT(0) /*!< stop the USB clock */ + +#define RSTAT_GOUT_NAK 1U /* global OUT NAK (triggers an interrupt) */ +#define RSTAT_DATA_UPDT 2U /* OUT data packet received */ +#define RSTAT_XFER_COMP 3U /* OUT transfer completed (triggers an interrupt) */ +#define RSTAT_SETUP_COMP 4U /* SETUP transaction completed (triggers an interrupt) */ +#define RSTAT_SETUP_UPDT 6U /* SETUP data packet received */ + +#define DSTAT_EM_HS_PHY_30MHZ_60MHZ 0U /* USB enumerate speed use high-speed PHY clock in 30MHz or 60MHz */ +#define DSTAT_EM_FS_PHY_30MHZ_60MHZ 1U /* USB enumerate speed use full-speed PHY clock in 30MHz or 60MHz */ +#define DSTAT_EM_LS_PHY_6MHZ 2U /* USB enumerate speed use low-speed PHY clock in 6MHz */ +#define DSTAT_EM_FS_PHY_48MHZ 3U /* USB enumerate speed use full-speed PHY clock in 48MHz */ + +#define DPID_DATA0 0U /* device endpoint data PID is DATA0 */ +#define DPID_DATA1 2U /* device endpoint data PID is DATA1 */ +#define DPID_DATA2 1U /* device endpoint data PID is DATA2 */ +#define DPID_MDATA 3U /* device endpoint data PID is MDATA */ + +#define GAHBCS_DMAINCR(regval) (GAHBCS_BURST & ((regval) << 1)) /*!< AHB burst type used by DMA*/ + +#define DMA_INCR0 GAHBCS_DMAINCR(0U) /*!< single burst type used by DMA*/ +#define DMA_INCR1 GAHBCS_DMAINCR(1U) /*!< 4-beat incrementing burst type used by DMA*/ +#define DMA_INCR4 GAHBCS_DMAINCR(3U) /*!< 8-beat incrementing burst type used by DMA*/ +#define DMA_INCR8 GAHBCS_DMAINCR(5U) /*!< 16-beat incrementing burst type used by DMA*/ +#define DMA_INCR16 GAHBCS_DMAINCR(7U) /*!< 32-beat incrementing burst type used by DMA*/ + +#define DCFG_PFRI(regval) (DCFG_EOPFT & ((regval) << 11)) /*!< end of periodic frame time configuration */ + +#define FRAME_INTERVAL_80 DCFG_PFRI(0U) /*!< 80% of the frame time */ +#define FRAME_INTERVAL_85 DCFG_PFRI(1U) /*!< 85% of the frame time */ +#define FRAME_INTERVAL_90 DCFG_PFRI(2U) /*!< 90% of the frame time */ +#define FRAME_INTERVAL_95 DCFG_PFRI(3U) /*!< 95% of the frame time */ + +#define DCFG_DEVSPEED(regval) (DCFG_DS & ((regval) << 0)) /*!< device speed configuration */ + +#define USB_SPEED_EXP_HIGH DCFG_DEVSPEED(0U) /*!< device external PHY high speed */ +#define USB_SPEED_EXP_FULL DCFG_DEVSPEED(1U) /*!< device external PHY full speed */ +#define USB_SPEED_INP_FULL DCFG_DEVSPEED(3U) /*!< device internal PHY full speed */ + +#define DEP0_MPL(regval) (DEP0CTL_MPL & ((regval) << 0)) /*!< maximum packet length configuration */ + +#define EP0MPL_64 DEP0_MPL(0U) /*!< maximum packet length 64 bytes */ +#define EP0MPL_32 DEP0_MPL(1U) /*!< maximum packet length 32 bytes */ +#define EP0MPL_16 DEP0_MPL(2U) /*!< maximum packet length 16 bytes */ +#define EP0MPL_8 DEP0_MPL(3U) /*!< maximum packet length 8 bytes */ + +#define DOEP0_TLEN(regval) (DOEP0LEN_TLEN & ((regval) << 0)) /*!< transfer length */ +#define DOEP0_PCNT(regval) (DOEP0LEN_PCNT & ((regval) << 19)) /*!< packet count */ +#define DOEP0_STPCNT(regval) (DOEP0LEN_STPCNT & ((regval) << 29)) /*!< SETUP packet count */ + +#define USB_ULPI_PHY 1U /*!< ULPI interface external PHY */ +#define USB_EMBEDDED_PHY 2U /*!< embedded PHY */ + +#define GRXSTS_PKTSTS_IN 2U +#define GRXSTS_PKTSTS_IN_XFER_COMP 3U +#define GRXSTS_PKTSTS_DATA_TOGGLE_ERR 5U +#define GRXSTS_PKTSTS_CH_HALTED 7U + +#define HCTL_30_60MHZ 0U /*!< USB clock 30-60MHZ */ +#define HCTL_48MHZ 1U /*!< USB clock 48MHZ */ +#define HCTL_6MHZ 2U /*!< USB clock 6MHZ */ + +#define EP0_OUT ((uint8_t)0x00) /*!< endpoint out 0 */ +#define EP0_IN ((uint8_t)0x80) /*!< endpoint in 0 */ +#define EP1_OUT ((uint8_t)0x01) /*!< endpoint out 1 */ +#define EP1_IN ((uint8_t)0x81) /*!< endpoint in 1 */ +#define EP2_OUT ((uint8_t)0x02) /*!< endpoint out 2 */ +#define EP2_IN ((uint8_t)0x82) /*!< endpoint in 2 */ +#define EP3_OUT ((uint8_t)0x03) /*!< endpoint out 3 */ +#define EP3_IN ((uint8_t)0x83) /*!< endpoint in 3 */ + +#endif /* __DRV_USB_REGS_H */ diff --git a/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/driver/Include/drv_usbd_int.h b/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/driver/Include/drv_usbd_int.h new file mode 100644 index 0000000000..dc4a70cc8d --- /dev/null +++ b/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/driver/Include/drv_usbd_int.h @@ -0,0 +1,52 @@ +/*! + \file drv_usbd_int.h + \brief USB device mode interrupt header file + + \version 2020-08-01, V3.0.0, firmware for GD32F4xx +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef __DRV_USBD_INT_H +#define __DRV_USBD_INT_H + +#include "drv_usb_core.h" +#include "drv_usb_dev.h" + +/* function declarations */ +/* USB device-mode interrupts global service routine handler */ +void usbd_isr (usb_core_driver *udev); + +#ifdef USB_HS_DEDICATED_EP1_ENABLED +/* USB dedicated IN endpoint 1 interrupt service routine handler */ +uint32_t usbd_int_dedicated_ep1in (usb_core_driver *udev); +/* USB dedicated OUT endpoint 1 interrupt service routine handler */ +uint32_t usbd_int_dedicated_ep1out (usb_core_driver *udev); +#endif /* USB_HS_DEDICATED_EP1_ENABLED */ + +#endif /* __DRV_USBD_INT_H */ diff --git a/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/driver/Include/drv_usbh_int.h b/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/driver/Include/drv_usbh_int.h new file mode 100644 index 0000000000..d42146e46d --- /dev/null +++ b/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/driver/Include/drv_usbh_int.h @@ -0,0 +1,56 @@ +/*! + \file drv_usbh_int.h.h + \brief USB host mode interrupt management header file + + \version 2020-08-01, V3.0.0, firmware for GD32F4xx +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef __DRV_USBH_INT_H +#define __DRV_USBH_INT_H + +#include "drv_usb_host.h" +#include "usbh_core.h" + +typedef struct _usbh_int_cb +{ + uint8_t (*connect) (usbh_host *uhost); + uint8_t (*disconnect) (usbh_host *uhost); + uint8_t (*port_enabled) (usbh_host *uhost); + uint8_t (*port_disabled) (usbh_host *uhost); + uint8_t (*SOF) (usbh_host *uhost); +} usbh_int_cb; + +extern usbh_int_cb *usbh_int_fop; + +/* function declarations */ +/* handle global host interrupt */ +uint32_t usbh_isr (usb_core_driver *udev); + +#endif /* __DRV_USBH_INT_H */ diff --git a/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/driver/Source/drv_usb_core.c b/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/driver/Source/drv_usb_core.c new file mode 100644 index 0000000000..50c1544214 --- /dev/null +++ b/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/driver/Source/drv_usb_core.c @@ -0,0 +1,363 @@ +/*! + \file drv_usb_core.c + \brief USB core driver which can operate in host and device mode + + \version 2020-08-01, V3.0.0, firmware for GD32F4xx +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "drv_usb_core.h" +#include "drv_usb_hw.h" + +/* local function prototypes ('static') */ +static void usb_core_reset (usb_core_regs *usb_regs); + +/*! + \brief configure USB core basic + \param[in] usb_basic: pointer to USB capabilities + \param[in] usb_regs: USB core registers + \param[in] usb_core: USB core + \param[out] none + \retval operation status +*/ +usb_status usb_basic_init (usb_core_basic *usb_basic, + usb_core_regs *usb_regs, + usb_core_enum usb_core) +{ + /* configure USB default transfer mode as FIFO mode */ + usb_basic->transfer_mode = (uint8_t)USB_USE_FIFO; + + /* USB default speed is full-speed */ + usb_basic->core_speed = (uint8_t)USB_SPEED_FULL; + + usb_basic->core_enum = (uint8_t)usb_core; + + switch (usb_core) { + case USB_CORE_ENUM_HS: + usb_basic->base_reg = (uint32_t)USBHS_REG_BASE; + + /* set the host channel numbers */ + usb_basic->num_pipe = USBHS_MAX_CHANNEL_COUNT; + + /* set the device endpoint numbers */ + usb_basic->num_ep = USBHS_MAX_EP_COUNT; + +#ifdef USB_ULPI_PHY_ENABLED + usb_basic->phy_itf = USB_ULPI_PHY; +#else + usb_basic->phy_itf = USB_EMBEDDED_PHY; +#endif /* USB_ULPI_PHY_ENABLED */ + +#ifdef USB_HS_INTERNAL_DMA_ENABLED + usb_basic->transfer_mode = USB_USE_DMA; +#endif /* USB_HS_INTERNAL_DMA_ENABLED */ + break; + + case USB_CORE_ENUM_FS: + usb_basic->base_reg = (uint32_t)USBFS_REG_BASE; + + /* set the host channel numbers */ + usb_basic->num_pipe = USBFS_MAX_CHANNEL_COUNT; + + /* set the device endpoint numbers */ + usb_basic->num_ep = USBFS_MAX_EP_COUNT; + + /* USBFS core use embedded physical layer */ + usb_basic->phy_itf = USB_EMBEDDED_PHY; + break; + + default: + return USB_FAIL; + } + + usb_basic->sof_enable = USB_SOF_OUTPUT; + usb_basic->low_power = USB_LOW_POWER; + + /* assign main registers address */ + *usb_regs = (usb_core_regs) { + .gr = (usb_gr*) (usb_basic->base_reg + USB_REG_OFFSET_CORE), + .hr = (usb_hr*) (usb_basic->base_reg + USB_REG_OFFSET_HOST), + .dr = (usb_dr*) (usb_basic->base_reg + USB_REG_OFFSET_DEV), + + .HPCS = (uint32_t*) (usb_basic->base_reg + USB_REG_OFFSET_PORT), + .PWRCLKCTL = (uint32_t*) (usb_basic->base_reg + USB_REG_OFFSET_PWRCLKCTL) + }; + + /* assign device endpoint registers address */ + for (uint8_t i = 0U; i < usb_basic->num_ep; i++) { + usb_regs->er_in[i] = (usb_erin *) \ + (usb_basic->base_reg + USB_REG_OFFSET_EP_IN + (i * USB_REG_OFFSET_EP)); + + usb_regs->er_out[i] = (usb_erout *)\ + (usb_basic->base_reg + USB_REG_OFFSET_EP_OUT + (i * USB_REG_OFFSET_EP)); + } + + /* assign host pipe registers address */ + for (uint8_t i = 0U; i < usb_basic->num_pipe; i++) { + usb_regs->pr[i] = (usb_pr *) \ + (usb_basic->base_reg + USB_REG_OFFSET_CH_INOUT + (i * USB_REG_OFFSET_CH)); + + usb_regs->DFIFO[i] = (uint32_t *) \ + (usb_basic->base_reg + USB_DATA_FIFO_OFFSET + (i * USB_DATA_FIFO_SIZE)); + } + + return USB_OK; +} + +/*! + \brief initializes the USB controller registers and + prepares the core device mode or host mode operation + \param[in] usb_basic: pointer to USB capabilities + \param[in] usb_regs: pointer to USB core registers + \param[out] none + \retval operation status +*/ +usb_status usb_core_init (usb_core_basic usb_basic, usb_core_regs *usb_regs) +{ + if (USB_ULPI_PHY == usb_basic.phy_itf) { + usb_regs->gr->GCCFG &= ~GCCFG_PWRON; + + if (usb_basic.sof_enable) { + usb_regs->gr->GCCFG |= GCCFG_SOFOEN; + } + + /* initialize the ULPI interface */ + usb_regs->gr->GUSBCS &= ~(GUSBCS_EMBPHY | GUSBCS_ULPIEOI); + +#ifdef USBHS_EXTERNAL_VBUS_ENABLED + /* use external VBUS driver */ + usb_regs->gr->GUSBCS |= GUSBCS_ULPIEVD; +#else + /* use internal VBUS driver */ + usb_regs->gr->GUSBCS &= ~GUSBCS_ULPIEVD; +#endif /* USBHS_EXTERNAL_VBUS_ENABLED */ + + /* soft reset the core */ + usb_core_reset (usb_regs); + } else { + usb_regs->gr->GUSBCS |= GUSBCS_EMBPHY; + + /* soft reset the core */ + usb_core_reset (usb_regs); + + /* active the transceiver and enable VBUS sensing */ + usb_regs->gr->GCCFG |= GCCFG_PWRON | GCCFG_VBUSACEN | GCCFG_VBUSBCEN; + +#ifndef VBUS_SENSING_ENABLED + usb_regs->gr->GCCFG |= GCCFG_VBUSIG; +#endif /* VBUS_SENSING_ENABLED */ + + /* enable SOF output */ + if (usb_basic.sof_enable) { + usb_regs->gr->GCCFG |= GCCFG_SOFOEN; + } + + usb_mdelay(20U); + } + + if ((uint8_t)USB_USE_DMA == usb_basic.transfer_mode) { + usb_regs->gr->GAHBCS &= ~GAHBCS_BURST; + usb_regs->gr->GAHBCS |= DMA_INCR8 | GAHBCS_DMAEN; + } + +#ifdef USE_OTG_MODE + + /* enable USB OTG features */ + usb_regs->gr->GUSBCS |= GUSBCS_HNPCEN | GUSBCS_SRPCEN; + + /* enable the USB wakeup and suspend interrupts */ + usb_regs->gr->GINTF = 0xBFFFFFFFU; + + usb_regs->gr->GINTEN = GINTEN_WKUPIE | GINTEN_SPIE | \ + GINTEN_OTGIE | GINTEN_SESIE | GINTEN_CIDPSCIE; + +#endif /* USE_OTG_MODE */ + + return USB_OK; +} + +/*! + \brief write a packet into the TX FIFO associated with the endpoint + \param[in] usb_regs: pointer to USB core registers + \param[in] src_buf: pointer to source buffer + \param[in] fifo_num: FIFO number which is in (0..3) + \param[in] byte_count: packet byte count + \param[out] none + \retval operation status +*/ +usb_status usb_txfifo_write (usb_core_regs *usb_regs, + uint8_t *src_buf, + uint8_t fifo_num, + uint16_t byte_count) +{ + uint32_t word_count = (byte_count + 3U) / 4U; + + __IO uint32_t *fifo = usb_regs->DFIFO[fifo_num]; + + while (word_count-- > 0U) { + *fifo = *((__packed uint32_t *)src_buf); + + src_buf += 4U; + } + + return USB_OK; +} + +/*! + \brief read a packet from the Rx FIFO associated with the endpoint + \param[in] usb_regs: pointer to USB core registers + \param[in] dest_buf: pointer to destination buffer + \param[in] byte_count: packet byte count + \param[out] none + \retval void type pointer +*/ +void *usb_rxfifo_read (usb_core_regs *usb_regs, uint8_t *dest_buf, uint16_t byte_count) +{ + uint32_t word_count = (byte_count + 3U) / 4U; + + __IO uint32_t *fifo = usb_regs->DFIFO[0]; + + while (word_count-- > 0U) { + *(__packed uint32_t *)dest_buf = *fifo; + + dest_buf += 4U; + } + + return ((void *)dest_buf); +} + +/*! + \brief flush a TX FIFO or all TX FIFOs + \param[in] usb_regs: pointer to USB core registers + \param[in] fifo_num: FIFO number which is in (0..3) + \param[out] none + \retval operation status +*/ +usb_status usb_txfifo_flush (usb_core_regs *usb_regs, uint8_t fifo_num) +{ + usb_regs->gr->GRSTCTL = ((uint32_t)fifo_num << 6U) | GRSTCTL_TXFF; + + /* wait for TX FIFO flush bit is set */ + while (usb_regs->gr->GRSTCTL & GRSTCTL_TXFF) { + /* no operation */ + } + + /* wait for 3 PHY clocks*/ + usb_udelay(3U); + + return USB_OK; +} + +/*! + \brief flush the entire Rx FIFO + \param[in] usb_regs: pointer to USB core registers + \param[out] none + \retval operation status +*/ +usb_status usb_rxfifo_flush (usb_core_regs *usb_regs) +{ + usb_regs->gr->GRSTCTL = GRSTCTL_RXFF; + + /* wait for RX FIFO flush bit is set */ + while (usb_regs->gr->GRSTCTL & GRSTCTL_RXFF) { + /* no operation */ + } + + /* wait for 3 PHY clocks */ + usb_udelay(3U); + + return USB_OK; +} + +/*! + \brief set endpoint or channel TX FIFO size + \param[in] usb_regs: pointer to USB core registers + \param[in] fifo: TX FIFO number + \param[in] size: assigned TX FIFO size + \param[out] none + \retval none +*/ +void usb_set_txfifo(usb_core_regs *usb_regs, uint8_t fifo, uint16_t size) +{ + uint32_t tx_offset; + + tx_offset = usb_regs->gr->GRFLEN; + + if (fifo == 0U) { + usb_regs->gr->DIEP0TFLEN_HNPTFLEN = ((uint32_t)size << 16) | tx_offset; + } else { + tx_offset += (usb_regs->gr->DIEP0TFLEN_HNPTFLEN) >> 16; + + for (uint8_t i = 0U; i < (fifo - 1U); i++) { + tx_offset += (usb_regs->gr->DIEPTFLEN[i] >> 16); + } + + /* multiply Tx_Size by 2 to get higher performance */ + usb_regs->gr->DIEPTFLEN[fifo - 1U] = ((uint32_t)size << 16) | tx_offset; + } +} + +/*! + \brief set USB current mode + \param[in] usb_regs: pointer to USB core registers + \param[out] none + \retval none +*/ +void usb_curmode_set(usb_core_regs *usb_regs, uint8_t mode) +{ + usb_regs->gr->GUSBCS &= ~(GUSBCS_FDM | GUSBCS_FHM); + + if (DEVICE_MODE == mode) { + usb_regs->gr->GUSBCS |= GUSBCS_FDM; + } else if (HOST_MODE == mode) { + usb_regs->gr->GUSBCS |= GUSBCS_FHM; + } else { + /* OTG mode and other mode can not be here! */ + } +} + +/*! + \brief configure USB core to soft reset + \param[in] usb_regs: pointer to USB core registers + \param[out] none + \retval none +*/ +static void usb_core_reset (usb_core_regs *usb_regs) +{ + /* enable core soft reset */ + usb_regs->gr->GRSTCTL |= GRSTCTL_CSRST; + + /* wait for the core to be soft reset */ + while (usb_regs->gr->GRSTCTL & GRSTCTL_CSRST) { + /* no operation */ + } + + /* wait for additional 3 PHY clocks */ + usb_udelay(3U); +} diff --git a/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/driver/Source/drv_usb_dev.c b/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/driver/Source/drv_usb_dev.c new file mode 100644 index 0000000000..3f6a52a3c4 --- /dev/null +++ b/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/driver/Source/drv_usb_dev.c @@ -0,0 +1,664 @@ +/*! + \file drv_usb_dev.c + \brief USB device mode low level driver + + \version 2020-08-01, V3.0.0, firmware for GD32F4xx +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "drv_usb_hw.h" +#include "drv_usb_core.h" +#include "drv_usb_dev.h" + +/* endpoint 0 max packet length */ +static const uint8_t EP0_MAXLEN[4] = { + [DSTAT_EM_HS_PHY_30MHZ_60MHZ] = EP0MPL_64, + [DSTAT_EM_FS_PHY_30MHZ_60MHZ] = EP0MPL_64, + [DSTAT_EM_FS_PHY_48MHZ] = EP0MPL_64, + [DSTAT_EM_LS_PHY_6MHZ] = EP0MPL_8 +}; + +#ifdef USB_FS_CORE + +/* USB endpoint Tx FIFO size */ +static uint16_t USBFS_TX_FIFO_SIZE[USBFS_MAX_EP_COUNT] = +{ + (uint16_t)TX0_FIFO_FS_SIZE, + (uint16_t)TX1_FIFO_FS_SIZE, + (uint16_t)TX2_FIFO_FS_SIZE, + (uint16_t)TX3_FIFO_FS_SIZE +}; + +#endif /* USBFS_CORE */ + +#ifdef USB_HS_CORE + +uint16_t USBHS_TX_FIFO_SIZE[USBHS_MAX_EP_COUNT] = +{ + (uint16_t)TX0_FIFO_HS_SIZE, + (uint16_t)TX1_FIFO_HS_SIZE, + (uint16_t)TX2_FIFO_HS_SIZE, + (uint16_t)TX3_FIFO_HS_SIZE, + (uint16_t)TX4_FIFO_HS_SIZE, + (uint16_t)TX5_FIFO_HS_SIZE +}; + +#endif /* USBHS_CORE */ + +/*! + \brief initialize USB core registers for device mode + \param[in] udev: pointer to USB device + \param[out] none + \retval operation status +*/ +usb_status usb_devcore_init (usb_core_driver *udev) +{ + uint8_t i; + + /* restart the PHY clock (maybe don't need to...) */ + *udev->regs.PWRCLKCTL = 0U; + + /* configure periodic frame interval to default value */ + udev->regs.dr->DCFG &= ~DCFG_EOPFT; + udev->regs.dr->DCFG |= FRAME_INTERVAL_80; + + udev->regs.dr->DCFG &= ~DCFG_DS; + +#ifdef USB_FS_CORE + if (udev->bp.core_enum == (uint8_t)USB_CORE_ENUM_FS) { + /* set full-speed PHY */ + udev->regs.dr->DCFG |= USB_SPEED_INP_FULL; + + /* set Rx FIFO size */ + usb_set_rxfifo(&udev->regs, RX_FIFO_FS_SIZE); + + /* set endpoint 0 to 3's TX FIFO length and RAM address */ + for (i = 0U; i < USBFS_MAX_EP_COUNT; i++) { + usb_set_txfifo(&udev->regs, i, USBFS_TX_FIFO_SIZE[i]); + } + } +#endif /* USB_FS_CORE */ + +#ifdef USB_HS_CORE + if (udev->bp.core_enum == USB_CORE_ENUM_HS) { + if (udev->bp.phy_itf == USB_ULPI_PHY) { + udev->regs.dr->DCFG |= USB_SPEED_EXP_HIGH; + } else {/* set High speed PHY in Full speed mode */ + udev->regs.dr->DCFG |= USB_SPEED_EXP_FULL; + } + + /* Set Rx FIFO size */ + usb_set_rxfifo(&udev->regs, RX_FIFO_HS_SIZE); + + /* Set endpoint 0 to 6's TX FIFO length and RAM address */ + for (i = 0; i < USBHS_MAX_EP_COUNT; i++) { + usb_set_txfifo(&udev->regs, i, USBHS_TX_FIFO_SIZE[i]); + } + } +#endif /* USB_FS_CORE */ + + /* make sure all FIFOs are flushed */ + + /* flush all TX FIFOs */ + (void)usb_txfifo_flush (&udev->regs, 0x10U); + + /* flush entire RX FIFO */ + (void)usb_rxfifo_flush (&udev->regs); + + /* clear all pending device interrupts */ + udev->regs.dr->DIEPINTEN = 0U; + udev->regs.dr->DOEPINTEN = 0U; + udev->regs.dr->DAEPINT = 0xFFFFFFFFU; + udev->regs.dr->DAEPINTEN = 0U; + + /* configure all IN/OUT endpoints */ + for (i = 0U; i < udev->bp.num_ep; i++) { + if (udev->regs.er_in[i]->DIEPCTL & DEPCTL_EPEN) { + udev->regs.er_in[i]->DIEPCTL |= DEPCTL_EPD | DEPCTL_SNAK; + } else { + udev->regs.er_in[i]->DIEPCTL = 0U; + } + + /* set IN endpoint transfer length to 0 */ + udev->regs.er_in[i]->DIEPLEN = 0U; + + /* clear all pending IN endpoint interrupts */ + udev->regs.er_in[i]->DIEPINTF = 0xFFU; + + if (udev->regs.er_out[i]->DOEPCTL & DEPCTL_EPEN) { + udev->regs.er_out[i]->DOEPCTL |= DEPCTL_EPD | DEPCTL_SNAK; + } else { + udev->regs.er_out[i]->DOEPCTL = 0U; + } + + /* set OUT endpoint transfer length to 0 */ + udev->regs.er_out[i]->DOEPLEN = 0U; + + /* clear all pending OUT endpoint interrupts */ + udev->regs.er_out[i]->DOEPINTF = 0xFFU; + } + + udev->regs.dr->DIEPINTEN |= DIEPINTEN_EPTXFUDEN; + + (void)usb_devint_enable (udev); + + return USB_OK; +} + +/*! + \brief enable the USB device mode interrupts + \param[in] udev: pointer to USB device + \param[out] none + \retval operation status +*/ +usb_status usb_devint_enable (usb_core_driver *udev) +{ + /* clear any pending USB OTG interrupts */ + udev->regs.gr->GOTGINTF = 0xFFFFFFFFU; + + /* clear any pending interrupts */ + udev->regs.gr->GINTF = 0xBFFFFFFFU; + + /* enable the USB wakeup and suspend interrupts */ + udev->regs.gr->GINTEN = GINTEN_WKUPIE | GINTEN_SPIE; + + /* enable device_mode-related interrupts */ + if ((uint8_t)USB_USE_FIFO == udev->bp.transfer_mode) { + udev->regs.gr->GINTEN |= GINTEN_RXFNEIE; + } + + udev->regs.gr->GINTEN |= GINTEN_RSTIE | GINTEN_ENUMFIE | GINTEN_IEPIE |\ + GINTEN_OEPIE | GINTEN_SOFIE | GINTEN_ISOONCIE | GINTEN_ISOINCIE; + +#ifdef VBUS_SENSING_ENABLED + udev->regs.gr->GINTEN |= GINTEN_SESIE | GINTEN_OTGIE; +#endif /* VBUS_SENSING_ENABLED */ + + return USB_OK; +} + +/*! + \brief active the USB endpoint0 transaction + \param[in] udev: pointer to USB device + \param[in] transc: the USB endpoint0 transaction + \param[out] none + \retval operation status +*/ +usb_status usb_transc0_active (usb_core_driver *udev, usb_transc *transc) +{ + __IO uint32_t *reg_addr = NULL; + + /* get the endpoint number */ + uint8_t ep_num = transc->ep_addr.num; + + if (ep_num) { + /* not endpoint 0 */ + return USB_FAIL; + } + + if (transc->ep_addr.dir) { + reg_addr = &udev->regs.er_in[0]->DIEPCTL; + } else { + reg_addr = &udev->regs.er_out[0]->DOEPCTL; + } + + /* endpoint 0 is activated after USB clock is enabled */ + + *reg_addr &= ~(DEPCTL_MPL | DEPCTL_EPTYPE | DIEPCTL_TXFNUM); + + /* set endpoint 0 maximum packet length */ + *reg_addr |= EP0_MAXLEN[udev->regs.dr->DSTAT & DSTAT_ES]; + + /* activate endpoint */ + *reg_addr |= ((uint32_t)transc->ep_type << 18U) | ((uint32_t)ep_num << 22U) | DEPCTL_SD0PID | DEPCTL_EPACT; + + return USB_OK; +} + +/*! + \brief active the USB transaction + \param[in] udev: pointer to USB device + \param[in] transc: the USB transaction + \param[out] none + \retval status +*/ +usb_status usb_transc_active (usb_core_driver *udev, usb_transc *transc) +{ + __IO uint32_t *reg_addr = NULL; + __IO uint32_t epinten = 0U; + + /* get the endpoint number */ + uint8_t ep_num = transc->ep_addr.num; + + /* enable endpoint interrupt number */ + if (transc->ep_addr.dir) { + reg_addr = &udev->regs.er_in[ep_num]->DIEPCTL; + + epinten = 1U << ep_num; + } else { + reg_addr = &udev->regs.er_out[ep_num]->DOEPCTL; + + epinten = 1U << (16U + ep_num); + } + + /* if the endpoint is not active, need change the endpoint control register */ + if (!(*reg_addr & DEPCTL_EPACT)) { + *reg_addr &= ~(DEPCTL_MPL | DEPCTL_EPTYPE | DIEPCTL_TXFNUM); + + /* set endpoint maximum packet length */ + if (0U == ep_num) { + *reg_addr |= EP0_MAXLEN[udev->regs.dr->DSTAT & DSTAT_ES]; + } else { + *reg_addr |= transc->max_len; + } + + /* activate endpoint */ + *reg_addr |= ((uint32_t)transc->ep_type << 18U) | ((uint32_t)ep_num << 22U) | DEPCTL_SD0PID | DEPCTL_EPACT; + } + +#ifdef USB_HS_DEDICATED_EP1_ENABLED + if ((ep_num == 1U) && (udev->bp.core_enum == USB_CORE_ENUM_HS)) { + udev->regs.dr->DEP1INTEN |= epinten; + } + else +#endif /* USB_HS_DEDICATED_EP1_ENABLED */ + { + /* enable the interrupts for this endpoint */ + udev->regs.dr->DAEPINTEN |= epinten; + } + + return USB_OK; +} + +/*! + \brief deactivate the USB transaction + \param[in] udev: pointer to USB device + \param[in] transc: the USB transaction + \param[out] none + \retval status +*/ +usb_status usb_transc_deactivate(usb_core_driver *udev, usb_transc *transc) +{ + uint32_t epinten = 0U; + + uint8_t ep_num = transc->ep_addr.num; + + /* disable endpoint interrupt number */ + if (transc->ep_addr.dir) { + epinten = 1U << ep_num; + + udev->regs.er_in[ep_num]->DIEPCTL &= ~DEPCTL_EPACT; + } else { + epinten = 1U << (ep_num + 16U); + + udev->regs.er_out[ep_num]->DOEPCTL &= ~DEPCTL_EPACT; + } + +#ifdef USB_HS_DEDICATED_EP1_ENABLED + if ((ep_num == 1U) && (udev->bp.core_enum == USB_CORE_ENUM_HS)) { + udev->regs.dr->DEP1INTEN &= ~epinten; + } + else +#endif /* USB_HS_DEDICATED_EP1_ENABLED */ + { + /* disable the interrupts for this endpoint */ + udev->regs.dr->DAEPINTEN &= ~epinten; + } + + return USB_OK; +} + +/*! + \brief configure USB transaction to start IN transfer + \param[in] udev: pointer to USB device + \param[in] transc: the USB IN transaction + \param[out] none + \retval operation status +*/ +usb_status usb_transc_inxfer (usb_core_driver *udev, usb_transc *transc) +{ + usb_status status = USB_OK; + + uint8_t ep_num = transc->ep_addr.num; + + __IO uint32_t epctl = udev->regs.er_in[ep_num]->DIEPCTL; + __IO uint32_t eplen = udev->regs.er_in[ep_num]->DIEPLEN; + + eplen &= ~(DEPLEN_TLEN | DEPLEN_PCNT); + + /* zero length packet or endpoint 0 */ + if (0U == transc->xfer_len) { + /* set transfer packet count to 1 */ + eplen |= 1U << 19U; + } else { + /* set transfer packet count */ + if (0U == ep_num) { + transc->xfer_len = USB_MIN(transc->xfer_len, transc->max_len); + + eplen |= 1U << 19U; + } else { + eplen |= (((transc->xfer_len - 1U) + transc->max_len) / transc->max_len) << 19U; + } + + /* set endpoint transfer length */ + eplen |= transc->xfer_len; + + if (transc->ep_type == (uint8_t)USB_EPTYPE_ISOC) { + eplen |= DIEPLEN_MCNT & (1U << 29U); + } + } + + udev->regs.er_in[ep_num]->DIEPLEN = eplen; + + if (transc->ep_type == (uint8_t)USB_EPTYPE_ISOC) { + if (((udev->regs.dr->DSTAT & DSTAT_FNRSOF) >> 8U) & 0x01U) { + epctl |= DEPCTL_SEVNFRM; + } else { + epctl |= DEPCTL_SODDFRM; + } + } + + if ((uint8_t)USB_USE_DMA == udev->bp.transfer_mode) { + udev->regs.er_in[ep_num]->DIEPDMAADDR = transc->dma_addr; + } + + /* enable the endpoint and clear the NAK */ + epctl |= DEPCTL_CNAK | DEPCTL_EPEN; + + udev->regs.er_in[ep_num]->DIEPCTL = epctl; + + if ((uint8_t)USB_USE_FIFO == udev->bp.transfer_mode) { + udev->regs.er_in[ep_num]->DIEPCTL = epctl; + + if (transc->ep_type != (uint8_t)USB_EPTYPE_ISOC) { + /* enable the TX FIFO empty interrupt for this endpoint */ + if (transc->xfer_len > 0U) { + udev->regs.dr->DIEPFEINTEN |= 1U << ep_num; + } + } else { + (void)usb_txfifo_write (&udev->regs, transc->xfer_buf, ep_num, (uint16_t)transc->xfer_len); + } + } + + return status; +} + +/*! + \brief configure USB transaction to start OUT transfer + \param[in] udev: pointer to USB device + \param[in] transc: the USB OUT transaction + \param[out] none + \retval status +*/ +usb_status usb_transc_outxfer (usb_core_driver *udev, usb_transc *transc) +{ + usb_status status = USB_OK; + + uint8_t ep_num = transc->ep_addr.num; + + uint32_t epctl = udev->regs.er_out[ep_num]->DOEPCTL; + uint32_t eplen = udev->regs.er_out[ep_num]->DOEPLEN; + + eplen &= ~(DEPLEN_TLEN | DEPLEN_PCNT); + + /* zero length packet or endpoint 0 */ + if ((0U == transc->xfer_len) || (0U == ep_num)) { + /* set the transfer length to max packet size */ + eplen |= transc->max_len; + + /* set the transfer packet count to 1 */ + eplen |= 1U << 19U; + } else { + /* configure the transfer size and packet count as follows: + * pktcnt = N + * xfersize = N * maxpacket + */ + uint32_t packet_count = (transc->xfer_len + transc->max_len - 1U) / transc->max_len; + + eplen |= packet_count << 19U; + eplen |= packet_count * transc->max_len; + +#ifdef INT_HIGH_BW + if (transc->ep_type == (uint8_t)USB_EPTYPE_INTR) { + eplen |= DIEPLEN_MCNT & (3U << 29U); + } +#endif /* INT_HIGH_BW */ + } + + udev->regs.er_out[ep_num]->DOEPLEN = eplen; + + if ((uint8_t)USB_USE_DMA == udev->bp.transfer_mode) { + udev->regs.er_out[ep_num]->DOEPDMAADDR = transc->dma_addr; + } + + if (transc->ep_type == (uint8_t)USB_EPTYPE_ISOC) { + if (transc->frame_num) { + epctl |= DEPCTL_SD1PID; + } else { + epctl |= DEPCTL_SD0PID; + } + } + + /* enable the endpoint and clear the NAK */ + epctl |= DEPCTL_EPEN | DEPCTL_CNAK; + + udev->regs.er_out[ep_num]->DOEPCTL = epctl; + + return status; +} + +/*! + \brief set the USB transaction STALL status + \param[in] udev: pointer to USB device + \param[in] transc: the USB transaction + \param[out] none + \retval status +*/ +usb_status usb_transc_stall (usb_core_driver *udev, usb_transc *transc) +{ + __IO uint32_t *reg_addr = NULL; + + uint8_t ep_num = transc->ep_addr.num; + + if (transc->ep_addr.dir) { + reg_addr = &(udev->regs.er_in[ep_num]->DIEPCTL); + + /* set the endpoint disable bit */ + if (*reg_addr & DEPCTL_EPEN) { + *reg_addr |= DEPCTL_EPD; + } + } else { + /* set the endpoint stall bit */ + reg_addr = &(udev->regs.er_out[ep_num]->DOEPCTL); + } + + /* set the endpoint stall bit */ + *reg_addr |= DEPCTL_STALL; + + return USB_OK; +} + +/*! + \brief clear the USB transaction STALL status + \param[in] udev: pointer to USB device + \param[in] transc: the USB transaction + \param[out] none + \retval operation status +*/ +usb_status usb_transc_clrstall(usb_core_driver *udev, usb_transc *transc) +{ + __IO uint32_t *reg_addr = NULL; + + uint8_t ep_num = transc->ep_addr.num; + + if (transc->ep_addr.dir) { + reg_addr = &(udev->regs.er_in[ep_num]->DIEPCTL); + } else { + reg_addr = &(udev->regs.er_out[ep_num]->DOEPCTL); + } + + /* clear the endpoint stall bits */ + *reg_addr &= ~DEPCTL_STALL; + + /* reset data PID of the periodic endpoints */ + if ((transc->ep_type == (uint8_t)USB_EPTYPE_INTR) || (transc->ep_type == (uint8_t)USB_EPTYPE_BULK)) { + *reg_addr |= DEPCTL_SD0PID; + } + + return USB_OK; +} + +/*! + \brief read device IN endpoint interrupt flag register + \param[in] udev: pointer to USB device + \param[in] ep_num: endpoint number + \param[out] none + \retval interrupt value +*/ +uint32_t usb_iepintr_read (usb_core_driver *udev, uint8_t ep_num) +{ + uint32_t value = 0U, fifoemptymask, commonintmask; + + commonintmask = udev->regs.dr->DIEPINTEN; + fifoemptymask = udev->regs.dr->DIEPFEINTEN; + + /* check FIFO empty interrupt enable bit */ + commonintmask |= ((fifoemptymask >> ep_num) & 0x1U) << 7; + + value = udev->regs.er_in[ep_num]->DIEPINTF & commonintmask; + + return value; +} + +/*! + \brief configures OUT endpoint 0 to receive SETUP packets + \param[in] udev: pointer to USB device + \param[out] none + \retval none +*/ +void usb_ctlep_startout (usb_core_driver *udev) +{ + /* set OUT endpoint 0 receive length to 24 bytes, 1 packet and 3 setup packets */ + udev->regs.er_out[0]->DOEPLEN = DOEP0_TLEN(8U * 3U) | DOEP0_PCNT(1U) | DOEP0_STPCNT(3U); + + if ((uint8_t)USB_USE_DMA == udev->bp.transfer_mode) { + udev->regs.er_out[0]->DOEPDMAADDR = (uint32_t)&udev->dev.control.req; + + /* endpoint enable */ + udev->regs.er_out[0]->DOEPCTL |= DEPCTL_EPACT | DEPCTL_EPEN; + } +} + +/*! + \brief active remote wakeup signaling + \param[in] udev: pointer to USB device + \param[out] none + \retval none +*/ +void usb_rwkup_active (usb_core_driver *udev) +{ + if (udev->dev.pm.dev_remote_wakeup) { + if (udev->regs.dr->DSTAT & DSTAT_SPST) { + if (udev->bp.low_power) { + /* ungate USB core clock */ + *udev->regs.PWRCLKCTL &= ~(PWRCLKCTL_SHCLK | PWRCLKCTL_SUCLK); + } + + /* active remote wakeup signaling */ + udev->regs.dr->DCTL |= DCTL_RWKUP; + + usb_mdelay(5U); + + udev->regs.dr->DCTL &= ~DCTL_RWKUP; + } + } +} + +/*! + \brief active USB core clock + \param[in] udev: pointer to USB device + \param[out] none + \retval none +*/ +void usb_clock_active (usb_core_driver *udev) +{ + if (udev->bp.low_power) { + if (udev->regs.dr->DSTAT & DSTAT_SPST) { + /* ungate USB Core clock */ + *udev->regs.PWRCLKCTL &= ~(PWRCLKCTL_SHCLK | PWRCLKCTL_SUCLK); + } + } +} + +/*! + \brief USB device suspend + \param[in] udev: pointer to USB device + \param[out] none + \retval none +*/ +void usb_dev_suspend (usb_core_driver *udev) +{ + __IO uint32_t devstat = udev->regs.dr->DSTAT; + + if ((udev->bp.low_power) && (devstat & DSTAT_SPST)) { + /* switch-off the USB clocks */ + *udev->regs.PWRCLKCTL |= PWRCLKCTL_SHCLK; + + /* enter DEEP_SLEEP mode with LDO in low power mode */ + pmu_to_deepsleepmode(PMU_LDO_LOWPOWER, WFI_CMD); + } +} + +/*! + \brief stop the device and clean up FIFOs + \param[in] udev: pointer to USB device + \param[out] none + \retval none +*/ +void usb_dev_stop (usb_core_driver *udev) +{ + uint32_t i; + + udev->dev.cur_status = 1U; + + /* clear all interrupt flag and enable bits */ + for (i = 0U; i < udev->bp.num_ep; i++) { + udev->regs.er_in[i]->DIEPINTF = 0xFFU; + udev->regs.er_out[i]->DOEPINTF = 0xFFU; + } + + udev->regs.dr->DIEPINTEN = 0U; + udev->regs.dr->DOEPINTEN = 0U; + udev->regs.dr->DAEPINTEN = 0U; + udev->regs.dr->DAEPINT = 0xFFFFFFFFU; + + /* flush the FIFO */ + (void)usb_rxfifo_flush (&udev->regs); + (void)usb_txfifo_flush (&udev->regs, 0x10U); +} diff --git a/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/driver/Source/drv_usb_host.c b/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/driver/Source/drv_usb_host.c new file mode 100644 index 0000000000..c47abac6c7 --- /dev/null +++ b/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/driver/Source/drv_usb_host.c @@ -0,0 +1,476 @@ +/*! + \file drv_usb_host.c + \brief USB host mode low level driver + + \version 2020-08-01, V3.0.0, firmware for GD32F4xx +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "drv_usb_hw.h" +#include "drv_usb_core.h" +#include "drv_usb_host.h" + +const uint32_t PIPE_DPID[2] = { + PIPE_DPID_DATA0, + PIPE_DPID_DATA1 +}; + +/*! + \brief initializes USB core for host mode + \param[in] udev: pointer to selected USB host + \param[out] none + \retval operation status +*/ +usb_status usb_host_init (usb_core_driver *udev) +{ + uint32_t i = 0U, inten = 0U; + + uint32_t nptxfifolen = 0U; + uint32_t ptxfifolen = 0U; + + /* restart the PHY Clock */ + *udev->regs.PWRCLKCTL = 0U; + + /* initialize host configuration register */ + if (USB_ULPI_PHY == udev->bp.phy_itf) { + usb_phyclock_config (udev, HCTL_30_60MHZ); + } else { + usb_phyclock_config (udev, HCTL_48MHZ); + } + + /* support FS/LS only */ + udev->regs.hr->HCTL &= ~HCTL_SPDFSLS; + + /* configure data FIFOs size */ +#ifdef USB_FS_CORE + if (USB_CORE_ENUM_FS == udev->bp.core_enum) { + /* set Rx FIFO size */ + udev->regs.gr->GRFLEN = USB_RX_FIFO_FS_SIZE; + + /* set non-periodic TX FIFO size and address */ + nptxfifolen |= USB_RX_FIFO_FS_SIZE; + nptxfifolen |= USB_HTX_NPFIFO_FS_SIZE << 16U; + udev->regs.gr->DIEP0TFLEN_HNPTFLEN = nptxfifolen; + + /* set periodic TX FIFO size and address */ + ptxfifolen |= USB_RX_FIFO_FS_SIZE + USB_HTX_NPFIFO_FS_SIZE; + ptxfifolen |= USB_HTX_PFIFO_FS_SIZE << 16U; + udev->regs.gr->HPTFLEN = ptxfifolen; + } +#endif /* USB_FS_CORE */ + +#ifdef USB_HS_CORE + if (USB_CORE_ENUM_HS == udev->bp.core_enum) { + /* set Rx FIFO size */ + udev->regs.gr->GRFLEN = USB_RX_FIFO_HS_SIZE; + + /* set non-periodic Tx FIFO size and address */ + nptxfifolen |= USB_RX_FIFO_HS_SIZE; + nptxfifolen |= USB_HTX_NPFIFO_HS_SIZE << 16U; + udev->regs.gr->DIEP0TFLEN_HNPTFLEN = nptxfifolen; + + /* set periodic Tx FIFO size and address */ + ptxfifolen |= USB_RX_FIFO_HS_SIZE + USB_HTX_NPFIFO_HS_SIZE; + ptxfifolen |= USB_HTX_PFIFO_HS_SIZE << 16U; + udev->regs.gr->HPTFLEN = ptxfifolen; + } +#endif /* USB_HS_CORE */ + +#ifdef USE_OTG_MODE + + /* clear host set HNP enable in the usb_otg control register */ + udev->regs.gr->GOTGCS &= ~GOTGCS_HHNPEN; + +#endif /* USE_OTG_MODE */ + + /* make sure the FIFOs are flushed */ + + /* flush all TX FIFOs in device or host mode */ + usb_txfifo_flush (&udev->regs, 0x10U); + + /* flush the entire Rx FIFO */ + usb_rxfifo_flush (&udev->regs); + + /* disable all interrupts */ + udev->regs.gr->GINTEN = 0U; + + /* clear any pending USB OTG interrupts */ + udev->regs.gr->GOTGINTF = 0xFFFFFFFFU; + + /* enable the USB wakeup and suspend interrupts */ + udev->regs.gr->GINTF = 0xBFFFFFFFU; + + /* clear all pending host channel interrupts */ + for (i = 0U; i < udev->bp.num_pipe; i++) { + udev->regs.pr[i]->HCHINTF = 0xFFFFFFFFU; + udev->regs.pr[i]->HCHINTEN = 0U; + } + +#ifndef USE_OTG_MODE + usb_portvbus_switch (udev, 1U); +#endif /* USE_OTG_MODE */ + + udev->regs.gr->GINTEN = GINTEN_WKUPIE | GINTEN_SPIE; + + /* enable host_mode-related interrupts */ + if (USB_USE_FIFO == udev->bp.transfer_mode) { + inten = GINTEN_RXFNEIE; + } + + inten |= GINTEN_SESIE | GINTEN_HPIE | GINTEN_HCIE | GINTEN_ISOINCIE; + + udev->regs.gr->GINTEN |= inten; + + inten = GINTEN_DISCIE | GINTEN_SOFIE; + + udev->regs.gr->GINTEN &= ~inten; + + return USB_OK; +} + +/*! + \brief control the VBUS to power + \param[in] udev: pointer to selected usb host + \param[in] state: VBUS state + \param[out] none + \retval none +*/ +void usb_portvbus_switch (usb_core_driver *udev, uint8_t state) +{ + uint32_t port = 0U; + + /* enable or disable the external charge pump */ + usb_vbus_drive (state); + + /* turn on the host port power. */ + port = usb_port_read (udev); + + if (!(port & HPCS_PP) && (1U == state)) { + port |= HPCS_PP; + } + + if ((port & HPCS_PP) && (0U == state)) { + port &= ~HPCS_PP; + } + + *udev->regs.HPCS = port; + + usb_mdelay (200U); +} + +/*! + \brief reset host port + \param[in] udev: pointer to USB device + \param[out] none + \retval operation status +*/ +uint32_t usb_port_reset (usb_core_driver *udev) +{ + __IO uint32_t port = usb_port_read (udev); + + *udev->regs.HPCS = port | HPCS_PRST; + + usb_mdelay(20U); /* see note */ + + *udev->regs.HPCS = port & ~HPCS_PRST; + + usb_mdelay(20U); + + return 1U; +} + +/*! + \brief initialize host pipe + \param[in] udev: pointer to USB device + \param[in] pipe_num: host pipe number which is in (0..7) + \param[out] none + \retval operation status +*/ +usb_status usb_pipe_init (usb_core_driver *udev, uint8_t pipe_num) +{ + usb_status status = USB_OK; + + __IO uint32_t pp_ctl = 0U; + __IO uint32_t pp_inten = HCHINTEN_TFIE; + + usb_pipe *pp = &udev->host.pipe[pipe_num]; + + /* clear old interrupt conditions for this host channel */ + udev->regs.pr[pipe_num]->HCHINTF = 0xFFFFFFFFU; + + if (USB_USE_DMA == udev->bp.transfer_mode) { + pp_inten |= HCHINTEN_DMAERIE; + } + + if (pp->ep.dir) { + pp_inten |= HCHINTEN_BBERIE; + } + + /* enable channel interrupts required for this transfer */ + switch (pp->ep.type) { + case USB_EPTYPE_CTRL: + case USB_EPTYPE_BULK: + pp_inten |= HCHINTEN_STALLIE | HCHINTEN_USBERIE \ + | HCHINTEN_DTERIE | HCHINTEN_NAKIE; + + if (!pp->ep.dir) { + pp_inten |= HCHINTEN_NYETIE; + + if (pp->ping) { + pp_inten |= HCHINTEN_ACKIE; + } + } + break; + + case USB_EPTYPE_INTR: + pp_inten |= HCHINTEN_STALLIE | HCHINTEN_USBERIE | HCHINTEN_DTERIE \ + | HCHINTEN_NAKIE | HCHINTEN_REQOVRIE; + break; + + case USB_EPTYPE_ISOC: + pp_inten |= HCHINTEN_REQOVRIE | HCHINTEN_ACKIE; + + if (pp->ep.dir) { + pp_inten |= HCHINTEN_USBERIE; + } + break; + + default: + break; + } + + udev->regs.pr[pipe_num]->HCHINTEN = pp_inten; + + /* enable the top level host channel interrupt */ + udev->regs.hr->HACHINTEN |= 1U << pipe_num; + + /* make sure host channel interrupts are enabled */ + udev->regs.gr->GINTEN |= GINTEN_HCIE; + + /* program the host channel control register */ + pp_ctl |= PIPE_CTL_DAR(pp->dev_addr); + pp_ctl |= PIPE_CTL_EPNUM(pp->ep.num); + pp_ctl |= PIPE_CTL_EPDIR(pp->ep.dir); + pp_ctl |= PIPE_CTL_EPTYPE(pp->ep.type); + pp_ctl |= PIPE_CTL_LSD(pp->dev_speed == PORT_SPEED_LOW); + + pp_ctl |= pp->ep.mps; + pp_ctl |= ((uint32_t)(pp->ep.type == USB_EPTYPE_INTR) << 29U) & HCHCTL_ODDFRM; + + udev->regs.pr[pipe_num]->HCHCTL = pp_ctl; + + return status; +} + +/*! + \brief prepare host channel for transferring packets + \param[in] udev: pointer to USB device + \param[in] pipe_num: host pipe number which is in (0..7) + \param[out] none + \retval operation status +*/ +usb_status usb_pipe_xfer (usb_core_driver *udev, uint8_t pipe_num) +{ + usb_status status = USB_OK; + + uint16_t dword_len = 0U; + uint16_t packet_count = 0U; + + __IO uint32_t pp_ctl = 0U; + + usb_pipe *pp = &udev->host.pipe[pipe_num]; + + uint16_t max_packet_len = pp->ep.mps; + + /* compute the expected number of packets associated to the transfer */ + if (pp->xfer_len > 0U) { + packet_count = (uint16_t)((pp->xfer_len + max_packet_len - 1U) / max_packet_len); + + if (packet_count > HC_MAX_PACKET_COUNT) { + packet_count = HC_MAX_PACKET_COUNT; + pp->xfer_len = (uint16_t)(packet_count * max_packet_len); + } + } else { + packet_count = 1U; + } + + if (pp->ep.dir) { + pp->xfer_len = (uint16_t)(packet_count * max_packet_len); + } + + /* initialize the host channel transfer information */ + udev->regs.pr[pipe_num]->HCHLEN = pp->xfer_len | pp->DPID | PIPE_XFER_PCNT(packet_count); + + if (USB_USE_DMA == udev->bp.transfer_mode) { + udev->regs.pr[pipe_num]->HCHDMAADDR = (unsigned int)pp->xfer_buf; + } + + pp_ctl = udev->regs.pr[pipe_num]->HCHCTL; + + if (usb_frame_even(udev)) { + pp_ctl |= HCHCTL_ODDFRM; + } else { + pp_ctl &= ~HCHCTL_ODDFRM; + } + + /* set host channel enabled */ + pp_ctl |= HCHCTL_CEN; + pp_ctl &= ~HCHCTL_CDIS; + + udev->regs.pr[pipe_num]->HCHCTL = pp_ctl; + + if (USB_USE_FIFO == udev->bp.transfer_mode) { + if ((0U == pp->ep.dir) && (pp->xfer_len > 0U)) { + switch (pp->ep.type) { + /* non-periodic transfer */ + case USB_EPTYPE_CTRL: + case USB_EPTYPE_BULK: + dword_len = (uint16_t)((pp->xfer_len + 3U) / 4U); + + /* check if there is enough space in FIFO space */ + if (dword_len > (udev->regs.gr->HNPTFQSTAT & HNPTFQSTAT_NPTXFS)) { + /* need to process data in nptxfempty interrupt */ + udev->regs.gr->GINTEN |= GINTEN_NPTXFEIE; + } + break; + + /* periodic transfer */ + case USB_EPTYPE_INTR: + case USB_EPTYPE_ISOC: + dword_len = (uint16_t)((pp->xfer_len + 3U) / 4U); + + /* check if there is enough space in fifo space */ + if (dword_len > (udev->regs.hr->HPTFQSTAT & HPTFQSTAT_PTXFS)) { + /* need to process data in ptxfempty interrupt */ + udev->regs.gr->GINTEN |= GINTEN_PTXFEIE; + } + break; + + default: + break; + } + + /* write packet into the TX fifo. */ + usb_txfifo_write (&udev->regs, pp->xfer_buf, pipe_num, (uint16_t)pp->xfer_len); + } + } + + return status; +} + +/*! + \brief halt pipe + \param[in] udev: pointer to USB device + \param[in] pipe_num: host pipe number which is in (0..7) + \param[out] none + \retval operation status +*/ +usb_status usb_pipe_halt (usb_core_driver *udev, uint8_t pipe_num) +{ + __IO uint32_t pp_ctl = udev->regs.pr[pipe_num]->HCHCTL; + + uint8_t ep_type = (uint8_t)((pp_ctl & HCHCTL_EPTYPE) >> 18U); + + pp_ctl |= HCHCTL_CEN | HCHCTL_CDIS; + + switch (ep_type) { + case USB_EPTYPE_CTRL: + case USB_EPTYPE_BULK: + if (0U == (udev->regs.gr->HNPTFQSTAT & HNPTFQSTAT_NPTXFS)) { + pp_ctl &= ~HCHCTL_CEN; + } + break; + + case USB_EPTYPE_INTR: + case USB_EPTYPE_ISOC: + if (0U == (udev->regs.hr->HPTFQSTAT & HPTFQSTAT_PTXFS)) { + pp_ctl &= ~HCHCTL_CEN; + } + break; + + default: + break; + } + + udev->regs.pr[pipe_num]->HCHCTL = pp_ctl; + + return USB_OK; +} + +/*! + \brief configure host pipe to do ping operation + \param[in] udev: pointer to USB device + \param[in] pipe_num: host pipe number which is in (0..7) + \param[out] none + \retval operation status +*/ +usb_status usb_pipe_ping (usb_core_driver *udev, uint8_t pipe_num) +{ + uint32_t pp_ctl = 0U; + + udev->regs.pr[pipe_num]->HCHLEN = HCHLEN_PING | (HCHLEN_PCNT & (1U << 19U)); + + pp_ctl = udev->regs.pr[pipe_num]->HCHCTL; + + pp_ctl |= HCHCTL_CEN; + pp_ctl &= ~HCHCTL_CDIS; + + udev->regs.pr[pipe_num]->HCHCTL = pp_ctl; + + return USB_OK; +} + +/*! + \brief stop the USB host and clean up FIFO + \param[in] udev: pointer to USB device + \param[out] none + \retval none +*/ +void usb_host_stop (usb_core_driver *udev) +{ + uint32_t i; + __IO uint32_t pp_ctl = 0U; + + udev->regs.hr->HACHINTEN = 0x0U; + udev->regs.hr->HACHINT = 0xFFFFFFFFU; + + /* flush out any leftover queued requests. */ + for (i = 0U; i < udev->bp.num_pipe; i++) { + pp_ctl = udev->regs.pr[i]->HCHCTL; + + pp_ctl &= ~(HCHCTL_CEN | HCHCTL_EPDIR); + pp_ctl |= HCHCTL_CDIS; + + udev->regs.pr[i]->HCHCTL = pp_ctl; + } + + /* flush the FIFO */ + usb_rxfifo_flush (&udev->regs); + usb_txfifo_flush (&udev->regs, 0x10U); +} diff --git a/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/driver/Source/drv_usbd_int.c b/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/driver/Source/drv_usbd_int.c new file mode 100644 index 0000000000..04844af1aa --- /dev/null +++ b/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/driver/Source/drv_usbd_int.c @@ -0,0 +1,587 @@ +/*! + \file drv_usbd_int.c + \brief USB device mode interrupt routines + + \version 2020-08-01, V3.0.0, firmware for GD32F4xx +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "usbd_conf.h" +#include "drv_usbd_int.h" +#include "usbd_transc.h" + +static uint32_t usbd_int_epout (usb_core_driver *udev); +static uint32_t usbd_int_epin (usb_core_driver *udev); +static uint32_t usbd_int_rxfifo (usb_core_driver *udev); +static uint32_t usbd_int_reset (usb_core_driver *udev); +static uint32_t usbd_int_enumfinish (usb_core_driver *udev); +static uint32_t usbd_int_suspend (usb_core_driver *udev); + +static uint32_t usbd_emptytxfifo_write (usb_core_driver *udev, uint32_t ep_num); + +static const uint8_t USB_SPEED[4] = { + [DSTAT_EM_HS_PHY_30MHZ_60MHZ] = (uint8_t)USB_SPEED_HIGH, + [DSTAT_EM_FS_PHY_30MHZ_60MHZ] = (uint8_t)USB_SPEED_FULL, + [DSTAT_EM_FS_PHY_48MHZ] = (uint8_t)USB_SPEED_FULL, + [DSTAT_EM_LS_PHY_6MHZ] = (uint8_t)USB_SPEED_LOW +}; + +/*! + \brief USB device-mode interrupts global service routine handler + \param[in] udev: pointer to USB device instance + \param[out] none + \retval none +*/ +void usbd_isr (usb_core_driver *udev) +{ + if (HOST_MODE != (udev->regs.gr->GINTF & GINTF_COPM)) { + uint32_t intr = udev->regs.gr->GINTF & udev->regs.gr->GINTEN; + + /* there are no interrupts, avoid spurious interrupt */ + if (!intr) { + return; + } + + /* OUT endpoints interrupts */ + if (intr & GINTF_OEPIF) { + (void)usbd_int_epout (udev); + } + + /* IN endpoints interrupts */ + if (intr & GINTF_IEPIF) { + (void)usbd_int_epin (udev); + } + + /* suspend interrupt */ + if (intr & GINTF_SP) { + (void)usbd_int_suspend (udev); + } + + /* wakeup interrupt */ + if (intr & GINTF_WKUPIF) { + /* inform upper layer by the resume event */ + udev->dev.cur_status = USBD_CONFIGURED; + + /* clear interrupt */ + udev->regs.gr->GINTF = GINTF_WKUPIF; + } + + /* start of frame interrupt */ + if (intr & GINTF_SOF) { + if (udev->dev.class_core->SOF) { + (void)udev->dev.class_core->SOF(udev); + } + + /* clear interrupt */ + udev->regs.gr->GINTF = GINTF_SOF; + } + + /* receive FIFO not empty interrupt */ + if (intr & GINTF_RXFNEIF) { + (void)usbd_int_rxfifo (udev); + } + + /* USB reset interrupt */ + if (intr & GINTF_RST) { + (void)usbd_int_reset (udev); + } + + /* enumeration has been done interrupt */ + if (intr & GINTF_ENUMFIF) { + (void)usbd_int_enumfinish (udev); + } + + /* incomplete synchronization IN transfer interrupt*/ + if (intr & GINTF_ISOINCIF) { + if (NULL != udev->dev.class_core->incomplete_isoc_in) { + (void)udev->dev.class_core->incomplete_isoc_in(udev); + } + + /* Clear interrupt */ + udev->regs.gr->GINTF = GINTF_ISOINCIF; + } + + /* incomplete synchronization OUT transfer interrupt*/ + if (intr & GINTF_ISOONCIF) { + if (NULL != udev->dev.class_core->incomplete_isoc_out) { + (void)udev->dev.class_core->incomplete_isoc_out(udev); + } + + /* clear interrupt */ + udev->regs.gr->GINTF = GINTF_ISOONCIF; + } + +#ifdef VBUS_SENSING_ENABLED + + /* session request interrupt */ + if (intr & GINTF_SESIF) { + udev->regs.gr->GINTF = GINTF_SESIF; + } + + /* OTG mode interrupt */ + if (intr & GINTF_OTGIF) { + if(udev->regs.gr->GOTGINTF & GOTGINTF_SESEND) { + + } + + /* clear OTG interrupt */ + udev->regs.gr->GINTF = GINTF_OTGIF; + } +#endif /* VBUS_SENSING_ENABLED */ + } +} + +#ifdef USB_HS_DEDICATED_EP1_ENABLED + +/*! + \brief USB dedicated OUT endpoint 1 interrupt service routine handler + \param[in] udev: pointer to USB device instance + \param[out] none + \retval operation status +*/ +uint32_t usbd_int_dedicated_ep1out (usb_core_driver *udev) +{ + uint32_t oepintr = 0U; + uint32_t oeplen = 0U; + + oepintr = udev->regs.er_out[1]->DOEPINTF; + oepintr &= udev->regs.dr->DOEP1INTEN; + + /* transfer complete */ + if(oepintr & DOEPINTF_TF){ + /* clear the bit in DOEPINTn for this interrupt */ + udev->regs.er_out[1]->DOEPINTF = DOEPINTF_TF; + + if(USB_USE_DMA == udev->bp.transfer_mode){ + oeplen = udev->regs.er_out[1]->DOEPLEN; + + /* to do : handle more than one single max packet size packet */ + udev->dev.transc_out[1].xfer_count = udev->dev.transc_out[1].max_len - \ + (oeplen & DEPLEN_TLEN); + } + + /* rx complete */ + usbd_out_transc (udev, 1U); + } + + return 1U; +} + +/*! + \brief USB dedicated IN endpoint 1 interrupt service routine handler + \param[in] udev: pointer to USB device instance + \param[out] none + \retval operation status +*/ +uint32_t usbd_int_dedicated_ep1in (usb_core_driver *udev) +{ + uint32_t inten, intr, emptyen; + + inten = udev->regs.dr->DIEP1INTEN; + emptyen = udev->regs.dr->DIEPFEINTEN; + + inten |= ((emptyen >> 1 ) & 0x1) << 7; + + intr = udev->regs.er_in[1]->DIEPINTF & inten; + + if(intr & DIEPINTF_TF){ + udev->regs.dr->DIEPFEINTEN &= ~(0x1 << 1); + + udev->regs.er_in[1]->DIEPINTF = DIEPINTF_TF; + + /* TX complete */ + usbd_in_transc (udev, 1); + } + + if(intr & DIEPINTF_TXFE){ + usbd_emptytxfifo_write(udev, 1); + + udev->regs.er_in[1]->DIEPINTF = DIEPINTF_TXFE; + } + + return 1; +} + +#endif + +/*! + \brief indicates that an OUT endpoint has a pending interrupt + \param[in] udev: pointer to USB device instance + \param[out] none + \retval operation status +*/ +static uint32_t usbd_int_epout (usb_core_driver *udev) +{ + uint32_t epintnum = 0U; + uint8_t ep_num = 0U; + + for (epintnum = usb_oepintnum_read (udev); epintnum; epintnum >>= 1, ep_num++) { + if (epintnum & 0x01U) { + __IO uint32_t oepintr = usb_oepintr_read (udev, ep_num); + + /* transfer complete interrupt */ + if (oepintr & DOEPINTF_TF) { + /* clear the bit in DOEPINTF for this interrupt */ + udev->regs.er_out[ep_num]->DOEPINTF = DOEPINTF_TF; + + if ((uint8_t)USB_USE_DMA == udev->bp.transfer_mode) { + __IO uint32_t eplen = udev->regs.er_out[ep_num]->DOEPLEN; + + udev->dev.transc_out[ep_num].xfer_count = udev->dev.transc_out[ep_num].max_len - \ + (eplen & DEPLEN_TLEN); + } + + /* inform upper layer: data ready */ + (void)usbd_out_transc (udev, ep_num); + + if ((uint8_t)USB_USE_DMA == udev->bp.transfer_mode) { + if ((0U == ep_num) && ((uint8_t)USB_CTL_STATUS_OUT == udev->dev.control.ctl_state)) { + usb_ctlep_startout (udev); + } + } + } + + /* setup phase finished interrupt (control endpoints) */ + if (oepintr & DOEPINTF_STPF) { + /* inform the upper layer that a setup packet is available */ + (void)usbd_setup_transc (udev); + + udev->regs.er_out[ep_num]->DOEPINTF = DOEPINTF_STPF; + } + } + } + + return 1U; +} + +/*! + \brief indicates that an IN endpoint has a pending interrupt + \param[in] udev: pointer to USB device instance + \param[out] none + \retval operation status +*/ +static uint32_t usbd_int_epin (usb_core_driver *udev) +{ + uint32_t epintnum = 0U; + uint8_t ep_num = 0U; + + for (epintnum = usb_iepintnum_read (udev); epintnum; epintnum >>= 1, ep_num++) { + if (epintnum & 0x1U) { + __IO uint32_t iepintr = usb_iepintr_read (udev, ep_num); + + if (iepintr & DIEPINTF_TF) { + udev->regs.er_in[ep_num]->DIEPINTF = DIEPINTF_TF; + + /* data transmission is completed */ + (void)usbd_in_transc (udev, ep_num); + + if ((uint8_t)USB_USE_DMA == udev->bp.transfer_mode) { + if ((0U == ep_num) && ((uint8_t)USB_CTL_STATUS_IN == udev->dev.control.ctl_state)) { + usb_ctlep_startout (udev); + } + } + } + + if (iepintr & DIEPINTF_TXFE) { + usbd_emptytxfifo_write (udev, (uint32_t)ep_num); + + udev->regs.er_in[ep_num]->DIEPINTF = DIEPINTF_TXFE; + } + } + } + + return 1U; +} + +/*! + \brief handle the RX status queue level interrupt + \param[in] udev: pointer to USB device instance + \param[out] none + \retval operation status +*/ +static uint32_t usbd_int_rxfifo (usb_core_driver *udev) +{ + usb_transc *transc = NULL; + + uint8_t data_PID = 0U; + uint32_t bcount = 0U; + + __IO uint32_t devrxstat = 0U; + + /* disable the Rx status queue non-empty interrupt */ + udev->regs.gr->GINTEN &= ~GINTEN_RXFNEIE; + + /* get the status from the top of the FIFO */ + devrxstat = udev->regs.gr->GRSTATP; + + uint8_t ep_num = (uint8_t)(devrxstat & GRSTATRP_EPNUM); + + transc = &udev->dev.transc_out[ep_num]; + + bcount = (devrxstat & GRSTATRP_BCOUNT) >> 4U; + data_PID = (uint8_t)((devrxstat & GRSTATRP_DPID) >> 15U); + +#ifdef USE_USB_HS + #ifndef USE_450Z_EVAL + /* ensure no-DMA mode can work */ + if ((1U == ep_num) && (0U == (udev->regs.er_out[ep_num]->DOEPLEN & DEPLEN_PCNT))) { + uint32_t devepctl = udev->regs.er_out[ep_num]->DOEPCTL; + + devepctl |= DEPCTL_SNAK; + devepctl &= ~DEPCTL_EPEN; + devepctl &= ~DEPCTL_EPD; + + udev->regs.er_out[ep_num]->DOEPCTL = devepctl; + } + #endif /* USE_450Z_EVAL */ +#endif /* USE_USB_HS */ + + switch ((devrxstat & GRSTATRP_RPCKST) >> 17U) { + case RSTAT_GOUT_NAK: + break; + + case RSTAT_DATA_UPDT: + if (bcount > 0U) { + (void)usb_rxfifo_read (&udev->regs, transc->xfer_buf, (uint16_t)bcount); + + transc->xfer_buf += bcount; + transc->xfer_count += bcount; + } + break; + + case RSTAT_XFER_COMP: + /* trigger the OUT endpoint interrupt */ + break; + + case RSTAT_SETUP_COMP: + /* trigger the OUT endpoint interrupt */ + break; + + case RSTAT_SETUP_UPDT: + if ((0U == transc->ep_addr.num) && (8U == bcount) && (DPID_DATA0 == data_PID)) { + /* copy the setup packet received in FIFO into the setup buffer in RAM */ + (void)usb_rxfifo_read (&udev->regs, (uint8_t *)&udev->dev.control.req, (uint16_t)bcount); + + transc->xfer_count += bcount; + } + break; + + default: + break; + } + + /* enable the Rx status queue level interrupt */ + udev->regs.gr->GINTEN |= GINTEN_RXFNEIE; + + return 1U; +} + +/*! + \brief handle USB reset interrupt + \param[in] udev: pointer to USB device instance + \param[out] none + \retval status +*/ +static uint32_t usbd_int_reset (usb_core_driver *udev) +{ + uint32_t i; + + /* clear the remote wakeup signaling */ + udev->regs.dr->DCTL &= ~DCTL_RWKUP; + + /* flush the TX FIFO */ + (void)usb_txfifo_flush (&udev->regs, 0U); + + for (i = 0U; i < udev->bp.num_ep; i++) { + udev->regs.er_in[i]->DIEPINTF = 0xFFU; + udev->regs.er_out[i]->DOEPINTF = 0xFFU; + } + + /* clear all pending device endpoint interrupts */ + udev->regs.dr->DAEPINT = 0xFFFFFFFFU; + + /* enable endpoint 0 interrupts */ + udev->regs.dr->DAEPINTEN = 1U | (1U << 16U); + + /* enable OUT endpoint interrupts */ + udev->regs.dr->DOEPINTEN = DOEPINTEN_STPFEN | DOEPINTEN_TFEN; + +#ifdef USB_HS_DEDICATED_EP1_ENABLED + udev->regs.dr->DOEP1INTEN = DOEPINTEN_STPFEN | DOEPINTEN_TFEN; +#endif + + /* enable IN endpoint interrupts */ + udev->regs.dr->DIEPINTEN = DIEPINTEN_TFEN; + +#ifdef USB_HS_DEDICATED_EP1_ENABLED + udev->regs.dr->DIEP1INTEN = DIEPINTEN_TFEN; +#endif + + /* reset device address */ + udev->regs.dr->DCFG &= ~DCFG_DAR; + + /* configure endpoint 0 to receive SETUP packets */ + usb_ctlep_startout (udev); + + /* clear USB reset interrupt */ + udev->regs.gr->GINTF = GINTF_RST; + + udev->dev.transc_out[0] = (usb_transc) { + .ep_type = USB_EPTYPE_CTRL, + .max_len = USB_FS_EP0_MAX_LEN + }; + + (void)usb_transc_active (udev, &udev->dev.transc_out[0]); + + udev->dev.transc_in[0] = (usb_transc) { + .ep_addr = { + .dir = 1U + }, + + .ep_type = USB_EPTYPE_CTRL, + .max_len = USB_FS_EP0_MAX_LEN + }; + + (void)usb_transc_active (udev, &udev->dev.transc_in[0]); + + /* upon reset call user call back */ + udev->dev.cur_status = (uint8_t)USBD_DEFAULT; + + return 1U; +} + +/*! + \brief handle USB speed enumeration finish interrupt + \param[in] udev: pointer to USB device instance + \param[out] none + \retval status +*/ +static uint32_t usbd_int_enumfinish (usb_core_driver *udev) +{ + uint8_t enum_speed = (uint8_t)((udev->regs.dr->DSTAT & DSTAT_ES) >> 1U); + + udev->regs.dr->DCTL &= ~DCTL_CGINAK; + udev->regs.dr->DCTL |= DCTL_CGINAK; + + udev->regs.gr->GUSBCS &= ~GUSBCS_UTT; + + /* set USB turn-around time based on device speed and PHY interface */ + if (USB_SPEED[enum_speed] == (uint8_t)USB_SPEED_HIGH) { + udev->bp.core_speed = (uint8_t)USB_SPEED_HIGH; + + udev->regs.gr->GUSBCS |= 0x09U << 10U; + } else { + udev->bp.core_speed = (uint8_t)USB_SPEED_FULL; + + udev->regs.gr->GUSBCS |= 0x05U << 10U; + } + + /* clear interrupt */ + udev->regs.gr->GINTF = GINTF_ENUMFIF; + + return 1U; +} + +/*! + \brief USB suspend interrupt handler + \param[in] udev: pointer to USB device instance + \param[out] none + \retval operation status +*/ +static uint32_t usbd_int_suspend (usb_core_driver *udev) +{ + __IO uint8_t low_power = udev->bp.low_power; + __IO uint8_t suspend = (uint8_t)(udev->regs.dr->DSTAT & DSTAT_SPST); + __IO uint8_t is_configured = (udev->dev.cur_status == (uint8_t)USBD_CONFIGURED)? 1U : 0U; + + udev->dev.backup_status = udev->dev.cur_status; + udev->dev.cur_status = (uint8_t)USBD_SUSPENDED; + + if (low_power && suspend && is_configured) { + /* switch-off the OTG clocks */ + *udev->regs.PWRCLKCTL |= PWRCLKCTL_SUCLK | PWRCLKCTL_SHCLK; + + /* enter DEEP_SLEEP mode with LDO in low power mode */ + pmu_to_deepsleepmode(PMU_LDO_LOWPOWER, WFI_CMD); + } + + /* clear interrupt */ + udev->regs.gr->GINTF = GINTF_SP; + + return 1U; +} + +/*! + \brief check FIFO for the next packet to be loaded + \param[in] udev: pointer to USB device instance + \param[in] ep_num: endpoint identifier which is in (0..3) + \param[out] none + \retval status +*/ +static uint32_t usbd_emptytxfifo_write (usb_core_driver *udev, uint32_t ep_num) +{ + uint32_t len; + uint32_t word_count; + + usb_transc *transc = &udev->dev.transc_in[ep_num]; + + len = transc->xfer_len - transc->xfer_count; + + /* get the data length to write */ + if (len > transc->max_len) { + len = transc->max_len; + } + + word_count = (len + 3U) / 4U; + + while (((udev->regs.er_in[ep_num]->DIEPTFSTAT & DIEPTFSTAT_IEPTFS) >= word_count) && \ + (transc->xfer_count < transc->xfer_len)) { + len = transc->xfer_len - transc->xfer_count; + + if (len > transc->max_len) { + len = transc->max_len; + } + + /* write FIFO in word(4bytes) */ + word_count = (len + 3U) / 4U; + + /* write the FIFO */ + (void)usb_txfifo_write (&udev->regs, transc->xfer_buf, (uint8_t)ep_num, (uint16_t)len); + + transc->xfer_buf += len; + transc->xfer_count += len; + + if (transc->xfer_count == transc->xfer_len) { + /* disable the device endpoint FIFO empty interrupt */ + udev->regs.dr->DIEPFEINTEN &= ~(0x01U << ep_num); + } + } + + return 1U; +} diff --git a/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/driver/Source/drv_usbh_int.c b/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/driver/Source/drv_usbh_int.c new file mode 100644 index 0000000000..2bde1469a0 --- /dev/null +++ b/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/driver/Source/drv_usbh_int.c @@ -0,0 +1,622 @@ +/*! + \file drv_usbh_int.c + \brief USB host mode interrupt handler file + + \version 2020-08-01, V3.0.0, firmware for GD32F4xx +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "drv_usb_core.h" +#include "drv_usb_host.h" +#include "drv_usbh_int.h" +#include "usbh_core.h" + +#if defined (__CC_ARM) /*!< ARM compiler */ + #pragma O0 +#elif defined (__GNUC__) /*!< GNU compiler */ + #pragma GCC optimize ("O0") +#elif defined (__TASKING__) /*!< TASKING compiler */ + #pragma optimize=0 +#endif /* __CC_ARM */ + +/* local function prototypes ('static') */ +static uint32_t usbh_int_port (usb_core_driver *udev); +static uint32_t usbh_int_pipe (usb_core_driver *udev); +static uint32_t usbh_int_pipe_in (usb_core_driver *udev, uint32_t pp_num); +static uint32_t usbh_int_pipe_out (usb_core_driver *udev, uint32_t pp_num); +static uint32_t usbh_int_rxfifonoempty (usb_core_driver *udev); +static uint32_t usbh_int_txfifoempty (usb_core_driver *udev, usb_pipe_mode pp_mode); + +/*! + \brief handle global host interrupt + \param[in] udev: pointer to USB core instance + \param[out] none + \retval operation status +*/ +uint32_t usbh_isr (usb_core_driver *udev) +{ + uint32_t retval = 0U; + + __IO uint32_t intr = 0U; + + /* check if host mode */ + if (HOST_MODE == (udev->regs.gr->GINTF & GINTF_COPM)) { + intr = usb_coreintr_get(&udev->regs); + + if (!intr) { + return 0U; + } + + if (intr & GINTF_SOF) { + usbh_int_fop->SOF(udev->host.data); + + /* clear interrupt */ + udev->regs.gr->GINTF = GINTF_SOF; + } + + if (intr & GINTF_RXFNEIF) { + retval |= usbh_int_rxfifonoempty (udev); + } + + if (intr & GINTF_NPTXFEIF) { + retval |= usbh_int_txfifoempty (udev, PIPE_NON_PERIOD); + } + + if (intr & GINTF_PTXFEIF) { + retval |= usbh_int_txfifoempty (udev, PIPE_PERIOD); + } + + if (intr & GINTF_HCIF) { + retval |= usbh_int_pipe (udev); + } + + if (intr & GINTF_HPIF) { + retval |= usbh_int_port (udev); + } + + if (intr & GINTF_DISCIF) { + usbh_int_fop->disconnect(udev->host.data); + + /* clear interrupt */ + udev->regs.gr->GINTF = GINTF_DISCIF; + } + + if (intr & GINTF_ISOONCIF) { + udev->regs.pr[0]->HCHCTL |= HCHCTL_CEN | HCHCTL_CDIS; + + /* clear interrupt */ + udev->regs.gr->GINTF = GINTF_ISOONCIF; + } + + if (intr & GINTF_SESIF) { + usb_portvbus_switch (udev, 1U); + + udev->regs.gr->GINTF = GINTF_SESIF; + } + + if (intr & GINTF_WKUPIF) { + /* clear interrupt */ + udev->regs.gr->GINTF = GINTF_WKUPIF; + } + } + + return retval; +} + +/*! + \brief handle USB pipe halt + \param[in] udev: pointer to USB core instance + \param[in] pp_num: pp_num: host channel number which is in (0..7) + \param[in] pp_int: pipe interrupt + \param[in] pp_status: pipe status + \param[out] none + \retval none +*/ +static inline void usb_pp_halt (usb_core_driver *udev, + uint8_t pp_num, + uint32_t pp_int, + usb_pipe_staus pp_status) +{ + udev->regs.pr[pp_num]->HCHINTEN |= HCHINTEN_CHIE; + + usb_pipe_halt(udev, pp_num); + + udev->regs.pr[pp_num]->HCHINTF = pp_int; + + udev->host.pipe[pp_num].pp_status = pp_status; +} + +/*! + \brief handle the host port interrupt + \param[in] udev: pointer to USB device instance + \param[out] none + \retval operation status +*/ +#if defined (__ICCARM__) /*!< IAR compiler */ + #pragma optimize = none +#endif /* __ICCARM */ +static uint32_t usbh_int_port (usb_core_driver *udev) +{ + uint32_t retval = 0U; + + /* note: when the USB PHY use USB HS PHY, the flag is needed */ + uint8_t port_reset = 0U; + + __IO uint32_t port_state = *udev->regs.HPCS; + + /* clear the interrupt bits in GINTSTS */ + port_state &= ~(HPCS_PE | HPCS_PCD | HPCS_PEDC); + + /* port connect detected */ + if (*udev->regs.HPCS & HPCS_PCD) { + port_state |= HPCS_PCD; + + usbh_int_fop->connect(udev->host.data); + + retval |= 1U; + } + + /* port enable changed */ + if (*udev->regs.HPCS & HPCS_PEDC) { + port_state |= HPCS_PEDC; + + if (*udev->regs.HPCS & HPCS_PE) { + uint32_t port_speed = usb_curspeed_get(udev); + uint32_t clock_type = udev->regs.hr->HCTL & HCTL_CLKSEL; + + udev->host.connect_status = 1U; + + if (PORT_SPEED_LOW == port_speed) { + udev->regs.hr->HFT = 6000U; + + if (HCTL_6MHZ != clock_type) { + if (USB_EMBEDDED_PHY == udev->bp.phy_itf) { + usb_phyclock_config (udev, HCTL_6MHZ); + } + + port_reset = 1U; + } + } else if (PORT_SPEED_FULL == port_speed) { + udev->regs.hr->HFT = 48000U; + + if (HCTL_48MHZ != clock_type) { + usb_phyclock_config (udev, HCTL_48MHZ); + } + + port_reset = 1U; + } else { + /* for high speed device and others */ + port_reset = 1U; + } + + usbh_int_fop->port_enabled(udev->host.data); + + udev->regs.gr->GINTEN |= GINTEN_DISCIE | GINTEN_SOFIE; + } else { + usbh_int_fop->port_disabled(udev->host.data); + } + } + + if (port_reset) { + usb_port_reset(udev); + } + + /* clear port interrupts */ + *udev->regs.HPCS = port_state; + + return retval; +} + +/*! + \brief handle all host channels interrupt + \param[in] udev: pointer to USB device instance + \param[out] none + \retval operation status +*/ +static uint32_t usbh_int_pipe (usb_core_driver *udev) +{ + uint32_t pp_num = 0U; + uint32_t retval = 0U; + + for (pp_num = 0U; pp_num < udev->bp.num_pipe; pp_num++) { + if ((udev->regs.hr->HACHINT & HACHINT_HACHINT) & (1UL << pp_num)) { + if (udev->regs.pr[pp_num]->HCHCTL & HCHCTL_EPDIR) { + retval |= usbh_int_pipe_in (udev, pp_num); + } else { + retval |= usbh_int_pipe_out (udev, pp_num); + } + } + } + + return retval; +} + +/*! + \brief handle the IN channel interrupt + \param[in] udev: pointer to USB device instance + \param[in] pp_num: host channel number which is in (0..7) + \param[out] none + \retval operation status +*/ +#if defined (__ICCARM__) /*!< IAR compiler */ + #pragma optimize = none +#endif /* __ICCARM */ +static uint32_t usbh_int_pipe_in (usb_core_driver *udev, uint32_t pp_num) +{ + usb_pr *pp_reg = udev->regs.pr[pp_num]; + + usb_pipe *pp = &udev->host.pipe[pp_num]; + + __IO uint32_t intr_pp = pp_reg->HCHINTF & pp_reg->HCHINTEN; + + uint8_t ep_type = (uint8_t)((pp_reg->HCHCTL & HCHCTL_EPTYPE) >> 18U); + + if (intr_pp & HCHINTF_ACK) { + pp_reg->HCHINTF = HCHINTF_ACK; + } else if (intr_pp & HCHINTF_STALL) { + usb_pp_halt (udev, (uint8_t)pp_num, HCHINTF_STALL, PIPE_STALL); + pp_reg->HCHINTF = HCHINTF_NAK; + + /* note: When there is a 'STALL', reset also NAK, + else, the udev->host.pp_status = HC_STALL + will be overwritten by 'NAK' in code below */ + intr_pp &= ~HCHINTF_NAK; + } else if (intr_pp & HCHINTF_DTER) { + usb_pp_halt (udev, (uint8_t)pp_num, HCHINTF_DTER, PIPE_DTGERR); + pp_reg->HCHINTF = HCHINTF_NAK; + } else { + /* no operation */ + } + + if (intr_pp & HCHINTF_REQOVR) { + usb_pp_halt (udev, (uint8_t)pp_num, HCHINTF_REQOVR, PIPE_REQOVR); + } else if (intr_pp & HCHINTF_TF) { + if ((uint8_t)USB_USE_DMA == udev->bp.transfer_mode) { + udev->host.backup_xfercount[pp_num] = pp->xfer_len - (pp_reg->HCHLEN & HCHLEN_TLEN); + } + + pp->pp_status = PIPE_XF; + pp->err_count = 0U; + + pp_reg->HCHINTF = HCHINTF_TF; + + switch (ep_type) { + case USB_EPTYPE_CTRL: + case USB_EPTYPE_BULK: + usb_pp_halt (udev, (uint8_t)pp_num, HCHINTF_NAK, PIPE_XF); + + pp->data_toggle_in ^= 1U; + break; + + case USB_EPTYPE_INTR: + case USB_EPTYPE_ISOC: + pp_reg->HCHCTL |= HCHCTL_ODDFRM; + pp->urb_state = URB_DONE; + break; + + default: + break; + } + } else if (intr_pp & HCHINTF_CH) { + pp_reg->HCHINTEN &= ~HCHINTEN_CHIE; + + switch (pp->pp_status) { + case PIPE_XF: + pp->urb_state = URB_DONE; + break; + + case PIPE_STALL: + pp->urb_state = URB_STALL; + break; + + case PIPE_TRACERR: + case PIPE_DTGERR: + pp->err_count = 0U; + pp->urb_state = URB_ERROR; + + pp->data_toggle_in ^= 1U; + break; + + case PIPE_IDLE: + case PIPE_HALTED: + case PIPE_NAK: + case PIPE_NYET: + case PIPE_BBERR: + case PIPE_REQOVR: + default: + if((uint8_t)USB_EPTYPE_INTR == ep_type) { + pp->data_toggle_in ^= 1U; + } + break; + } + + pp_reg->HCHINTF = HCHINTF_CH; + } else if (intr_pp & HCHINTF_USBER) { + pp->err_count++; + usb_pp_halt (udev, (uint8_t)pp_num, HCHINTF_USBER, PIPE_TRACERR); + } else if (intr_pp & HCHINTF_NAK) { + switch (ep_type) { + case USB_EPTYPE_CTRL: + case USB_EPTYPE_BULK: + /* re-activate the channel */ + pp_reg->HCHCTL = (pp_reg->HCHCTL | HCHCTL_CEN) & ~HCHCTL_CDIS; + break; + + case USB_EPTYPE_INTR: + pp_reg->HCHINTEN |= HCHINTEN_CHIE; + + (void)usb_pipe_halt(udev, (uint8_t)pp_num); + break; + + default: + break; + } + + pp->pp_status = PIPE_NAK; + + pp_reg->HCHINTF = HCHINTF_NAK; + } else { + /* no operation */ + } + + return 1U; +} + +/*! + \brief handle the OUT channel interrupt + \param[in] udev: pointer to USB device instance + \param[in] pp_num: host channel number which is in (0..7) + \param[out] none + \retval operation status +*/ +#if defined (__ICCARM__) /*!< IAR compiler */ + #pragma optimize = none +#endif /* __ICCARM */ +static uint32_t usbh_int_pipe_out (usb_core_driver *udev, uint32_t pp_num) +{ + usb_pr *pp_reg = udev->regs.pr[pp_num]; + + usb_pipe *pp = &udev->host.pipe[pp_num]; + + uint32_t intr_pp = pp_reg->HCHINTF & pp_reg->HCHINTEN; + + if (intr_pp & HCHINTF_ACK) { + if (URB_PING == pp->urb_state) { + pp->err_count = 0U; + usb_pp_halt (udev, (uint8_t)pp_num, HCHINTF_TF, PIPE_XF); + } + + pp_reg->HCHINTF = HCHINTF_ACK; + } else if (intr_pp & HCHINTF_STALL) { + usb_pp_halt (udev, (uint8_t)pp_num, HCHINTF_STALL, PIPE_STALL); + } else if (intr_pp & HCHINTF_DTER) { + usb_pp_halt (udev, (uint8_t)pp_num, HCHINTF_DTER, PIPE_DTGERR); + pp_reg->HCHINTF = HCHINTF_NAK; + } else if (intr_pp & HCHINTF_REQOVR) { + usb_pp_halt (udev, (uint8_t)pp_num, HCHINTF_REQOVR, PIPE_REQOVR); + } else if (intr_pp & HCHINTF_TF) { + pp->err_count = 0U; + usb_pp_halt (udev, (uint8_t)pp_num, HCHINTF_TF, PIPE_XF); + } else if (intr_pp & HCHINTF_NAK) { + pp->err_count = 0U; + usb_pp_halt (udev, (uint8_t)pp_num, HCHINTF_NAK, PIPE_NAK); + } else if (intr_pp & HCHINTF_USBER) { + pp->err_count++; + usb_pp_halt (udev, (uint8_t)pp_num, HCHINTF_USBER, PIPE_TRACERR); + } else if (intr_pp & HCHINTF_NYET) { + pp->err_count = 0U; + usb_pp_halt (udev, (uint8_t)pp_num, HCHINTF_NYET, PIPE_NYET); + } else if (intr_pp & HCHINTF_CH) { + udev->regs.pr[pp_num]->HCHINTEN &= ~HCHINTEN_CHIE; + + switch (pp->pp_status) { + case PIPE_XF: + pp->urb_state = URB_DONE; + + if ((uint8_t)USB_EPTYPE_BULK == ((pp_reg->HCHCTL & HCHCTL_EPTYPE) >> 18U)) { + pp->data_toggle_out ^= 1U; + } + break; + + case PIPE_NAK: + + if (URB_PING == pp->urb_state) { + (void)usb_pipe_ping (udev, (uint8_t)pp_num); + } else { + pp->urb_state = URB_NOTREADY; + } + break; + + case PIPE_NYET: + if (1U == udev->host.pipe[pp_num].ping) { + (void)usb_pipe_ping (udev, (uint8_t)pp_num); + pp->urb_state = URB_PING; + } + else { + pp->urb_state = URB_NOTREADY; + } + break; + + case PIPE_STALL: + pp->urb_state = URB_STALL; + break; + + case PIPE_TRACERR: + if (3U == pp->err_count) { + pp->urb_state = URB_ERROR; + pp->err_count = 0U; + } + break; + + case PIPE_IDLE: + case PIPE_HALTED: + case PIPE_BBERR: + case PIPE_REQOVR: + case PIPE_DTGERR: + default: + break; + } + + pp_reg->HCHINTF = HCHINTF_CH; + } else { + /* no operation */ + } + + return 1U; +} + +/*! + \brief handle the RX FIFO non-empty interrupt + \param[in] udev: pointer to USB device instance + \param[out] none + \retval operation status +*/ +#if defined (__ICCARM__) /*!< IAR compiler */ + #pragma optimize = none +#endif /* __ICCARM */ +static uint32_t usbh_int_rxfifonoempty (usb_core_driver *udev) +{ + uint32_t count = 0U; + + __IO uint8_t pp_num = 0U; + __IO uint32_t rx_stat = 0U; + + /* disable the RX status queue level interrupt */ + udev->regs.gr->GINTEN &= ~GINTEN_RXFNEIE; + + rx_stat = udev->regs.gr->GRSTATP; + pp_num = (uint8_t)(rx_stat & GRSTATRP_CNUM); + + switch ((rx_stat & GRSTATRP_RPCKST) >> 17U) { + case GRXSTS_PKTSTS_IN: + count = (rx_stat & GRSTATRP_BCOUNT) >> 4U; + + /* read the data into the host buffer. */ + if ((count > 0U) && (NULL != udev->host.pipe[pp_num].xfer_buf)) { + (void)usb_rxfifo_read (&udev->regs, udev->host.pipe[pp_num].xfer_buf, (uint16_t)count); + + /* manage multiple transfer packet */ + udev->host.pipe[pp_num].xfer_buf += count; + udev->host.pipe[pp_num].xfer_count += count; + + udev->host.backup_xfercount[pp_num] = udev->host.pipe[pp_num].xfer_count; + + if (udev->regs.pr[pp_num]->HCHLEN & HCHLEN_PCNT) { + /* re-activate the channel when more packets are expected */ + __IO uint32_t pp_ctl = udev->regs.pr[pp_num]->HCHCTL; + + pp_ctl |= HCHCTL_CEN; + pp_ctl &= ~HCHCTL_CDIS; + + udev->regs.pr[pp_num]->HCHCTL = pp_ctl; + } + } + break; + + case GRXSTS_PKTSTS_IN_XFER_COMP: + break; + + case GRXSTS_PKTSTS_DATA_TOGGLE_ERR: + count = (rx_stat & GRSTATRP_BCOUNT) >> 4U; + + while (count > 0U) { + rx_stat = udev->regs.gr->GRSTATP; + count--; + } + break; + + case GRXSTS_PKTSTS_CH_HALTED: + break; + + default: + break; + } + + /* enable the RX status queue level interrupt */ + udev->regs.gr->GINTEN |= GINTEN_RXFNEIE; + + return 1U; +} + +/*! + \brief handle the TX FIFO empty interrupt + \param[in] udev: pointer to USB device instance + \param[in] pp_mode: pipe mode + \param[out] none + \retval operation status +*/ +#if defined (__ICCARM__) /*!< IAR compiler */ + #pragma optimize = none +#endif /* __ICCARM */ +static uint32_t usbh_int_txfifoempty (usb_core_driver *udev, usb_pipe_mode pp_mode) +{ + uint8_t pp_num = 0U; + uint16_t word_count = 0U, len = 0U; + __IO uint32_t *txfiforeg = 0U, txfifostate = 0U; + + if (PIPE_NON_PERIOD == pp_mode) { + txfiforeg = &udev->regs.gr->HNPTFQSTAT; + } else if (PIPE_PERIOD == pp_mode) { + txfiforeg = &udev->regs.hr->HPTFQSTAT; + } else { + return 0U; + } + + txfifostate = *txfiforeg; + + pp_num = (uint8_t)((txfifostate & TFQSTAT_CNUM) >> 27U); + + word_count = (uint16_t)(udev->host.pipe[pp_num].xfer_len + 3U) / 4U; + + while (((txfifostate & TFQSTAT_TXFS) >= word_count) && (0U != udev->host.pipe[pp_num].xfer_len)) { + len = (uint16_t)(txfifostate & TFQSTAT_TXFS) * 4U; + + if (len > udev->host.pipe[pp_num].xfer_len) { + /* last packet */ + len = (uint16_t)udev->host.pipe[pp_num].xfer_len; + + if (PIPE_NON_PERIOD == pp_mode) { + udev->regs.gr->GINTEN &= ~GINTEN_NPTXFEIE; + } else { + udev->regs.gr->GINTEN &= ~GINTEN_PTXFEIE; + } + } + + word_count = (uint16_t)((udev->host.pipe[pp_num].xfer_len + 3U) / 4U); + usb_txfifo_write (&udev->regs, udev->host.pipe[pp_num].xfer_buf, pp_num, len); + + udev->host.pipe[pp_num].xfer_buf += len; + udev->host.pipe[pp_num].xfer_len -= len; + udev->host.pipe[pp_num].xfer_count += len; + + txfifostate = *txfiforeg; + } + + return 1U; +} diff --git a/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/host/class/hid/Include/usbh_hid_core.h b/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/host/class/hid/Include/usbh_hid_core.h new file mode 100644 index 0000000000..610af2e0c5 --- /dev/null +++ b/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/host/class/hid/Include/usbh_hid_core.h @@ -0,0 +1,212 @@ +/*! + \file usbh_hid_core.h + \brief header file for the usbh_hid_core.c + + \version 2020-08-01, V3.0.0, firmware for GD32F4xx +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef __USBH_HID_CORE_H +#define __USBH_HID_CORE_H + +#include "usb_hid.h" +#include "usbh_enum.h" +#include "usbh_transc.h" + +#define HID_MIN_POLL 10U +#define HID_REPORT_SIZE 16U +#define HID_MAX_USAGE 10U +#define HID_MAX_NBR_REPORT_FMT 10U +#define HID_QUEUE_SIZE 10U + +#define HID_ITEM_LONG 0xFEU + +#define HID_ITEM_TYPE_MAIN 0x00U +#define HID_ITEM_TYPE_GLOBAL 0x01U +#define HID_ITEM_TYPE_LOCAL 0x02U +#define HID_ITEM_TYPE_RESERVED 0x03U + +#define HID_MAIN_ITEM_TAG_INPUT 0x08U +#define HID_MAIN_ITEM_TAG_OUTPUT 0x09U +#define HID_MAIN_ITEM_TAG_COLLECTION 0x0AU +#define HID_MAIN_ITEM_TAG_FEATURE 0x0BU +#define HID_MAIN_ITEM_TAG_ENDCOLLECTION 0x0CU + +#define HID_GLOBAL_ITEM_TAG_USAGE_PAGE 0x00U +#define HID_GLOBAL_ITEM_TAG_LOG_MIN 0x01U +#define HID_GLOBAL_ITEM_TAG_LOG_MAX 0x02U +#define HID_GLOBAL_ITEM_TAG_PHY_MIN 0x03U +#define HID_GLOBAL_ITEM_TAG_PHY_MAX 0x04U +#define HID_GLOBAL_ITEM_TAG_UNIT_EXPONENT 0x05U +#define HID_GLOBAL_ITEM_TAG_UNIT 0x06U +#define HID_GLOBAL_ITEM_TAG_REPORT_SIZE 0x07U +#define HID_GLOBAL_ITEM_TAG_REPORT_ID 0x08U +#define HID_GLOBAL_ITEM_TAG_REPORT_COUNT 0x09U +#define HID_GLOBAL_ITEM_TAG_PUSH 0x0AU +#define HID_GLOBAL_ITEM_TAG_POP 0x0BU + +#define HID_LOCAL_ITEM_TAG_USAGE 0x00U +#define HID_LOCAL_ITEM_TAG_USAGE_MIN 0x01U +#define HID_LOCAL_ITEM_TAG_USAGE_MAX 0x02U +#define HID_LOCAL_ITEM_TAG_DESIGNATOR_INDEX 0x03U +#define HID_LOCAL_ITEM_TAG_DESIGNATOR_MIN 0x04U +#define HID_LOCAL_ITEM_TAG_DESIGNATOR_MAX 0x05U +#define HID_LOCAL_ITEM_TAG_STRING_INDEX 0x07U +#define HID_LOCAL_ITEM_TAG_STRING_MIN 0x08U +#define HID_LOCAL_ITEM_TAG_STRING_MAX 0x09U +#define HID_LOCAL_ITEM_TAG_DELIMITER 0x0AU + +#define USB_HID_DESC_SIZE 9U + +/* states for HID state machine */ +typedef enum { + HID_INIT = 0U, + HID_IDLE, + HID_SEND_DATA, + HID_BUSY, + HID_GET_DATA, + HID_SYNC, + HID_POLL, + HID_ERROR, +} hid_state; + +typedef enum { + HID_REQ_INIT = 0U, + HID_REQ_IDLE, + HID_REQ_GET_REPORT_DESC, + HID_REQ_GET_HID_DESC, + HID_REQ_SET_IDLE, + HID_REQ_SET_PROTOCOL, + HID_REQ_SET_REPORT, +} hid_ctlstate; + +typedef enum +{ + HID_MOUSE = 0x01U, + HID_KEYBOARD = 0x02U, + HID_UNKNOWN = 0xFFU, +} hid_type; + +typedef struct _hid_report_data +{ + uint8_t ReportID; + uint8_t ReportType; + uint16_t UsagePage; + uint32_t Usage[HID_MAX_USAGE]; + uint32_t NbrUsage; + uint32_t UsageMin; + uint32_t UsageMax; + int32_t LogMin; + int32_t LogMax; + int32_t PhyMin; + int32_t PhyMax; + int32_t UnitExp; + uint32_t Unit; + uint32_t ReportSize; + uint32_t ReportCnt; + uint32_t Flag; + uint32_t PhyUsage; + uint32_t AppUsage; + uint32_t LogUsage; +} hid_report_data; + +typedef struct _hid_report_ID +{ + uint8_t size; /*!< report size return by the device ID */ + uint8_t reportID; /*!< report ID */ + uint8_t type; /*!< report type (INPUT/OUTPUT/FEATURE) */ +} hid_report_ID; + +typedef struct _hid_collection +{ + uint32_t usage; + uint8_t type; + struct _hid_collection *next_ptr; +} hid_collection; + +typedef struct _hid_appcollection +{ + uint32_t usage; + uint8_t type; + uint8_t nbr_report_fmt; + hid_report_data report_data[HID_MAX_NBR_REPORT_FMT]; +} hid_appcollection; + +typedef struct +{ + uint8_t *buf; + uint16_t head; + uint16_t tail; + uint16_t size; + uint8_t lock; +} data_fifo; + +/* structure for HID process */ +typedef struct _hid_process +{ + uint8_t pipe_in; + uint8_t pipe_out; + uint8_t ep_addr; + uint8_t ep_in; + uint8_t ep_out; + __IO uint8_t data_ready; + uint8_t *pdata; + uint16_t len; + uint16_t poll; + + __IO uint32_t timer; + + data_fifo fifo; + usb_desc_hid hid_desc; + hid_report_data hid_report; + + hid_state state; + hid_ctlstate ctl_state; + usbh_status (*init)(usb_core_driver *udev, usbh_host *uhost); + void (*machine)(usb_core_driver *udev, usbh_host *uhost); +} usbh_hid_handler; + +extern usbh_class usbh_hid; + +/* function declarations */ +/* set HID report */ +usbh_status usbh_set_report (usb_core_driver *udev, + usbh_host *uhost, + uint8_t report_type, + uint8_t report_ID, + uint8_t report_len, + uint8_t *report_buf); +/* read data from FIFO */ +uint16_t usbh_hid_fifo_read (data_fifo *fifo, void *buf, uint16_t nbytes); +/* write data to FIFO */ +uint16_t usbh_hid_fifo_write (data_fifo *fifo, void *buf, uint16_t nbytes); +/* initialize FIFO */ +void usbh_hid_fifo_init (data_fifo *fifo, uint8_t *buf, uint16_t size); + +#endif /* __USBH_HID_CORE_H */ diff --git a/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/host/class/hid/Include/usbh_hid_keybd.h b/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/host/class/hid/Include/usbh_hid_keybd.h new file mode 100644 index 0000000000..22cf270ac2 --- /dev/null +++ b/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/host/class/hid/Include/usbh_hid_keybd.h @@ -0,0 +1,303 @@ +/*! + \file usbh_hid_keybd.h + \brief header file for usbh_hid_keybd.c + + \version 2020-08-01, V3.0.0, firmware for GD32F4xx +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef __USBH_HID_KEYBD_H +#define __USBH_HID_KEYBD_H + +#include "usb_conf.h" +#include "usbh_hid_core.h" + +//#define AZERTY_KEYBOARD +#define QWERTY_KEYBOARD + +#define KBD_LEFT_CTRL 0x01U +#define KBD_LEFT_SHIFT 0x02U +#define KBD_LEFT_ALT 0x04U +#define KBD_LEFT_GUI 0x08U +#define KBD_RIGHT_CTRL 0x10U +#define KBD_RIGHT_SHIFT 0x20U +#define KBD_RIGHT_ALT 0x40U +#define KBD_RIGHT_GUI 0x80U + +#define KEY_NONE 0x00U +#define KEY_ERRORROLLOVER 0x01U +#define KEY_POSTFAIL 0x02U +#define KEY_ERRORUNDEFINED 0x03U +#define KEY_A 0x04U +#define KEY_B 0x05U +#define KEY_C 0x06U +#define KEY_D 0x07U +#define KEY_E 0x08U +#define KEY_F 0x09U +#define KEY_G 0x0AU +#define KEY_H 0x0BU +#define KEY_I 0x0CU +#define KEY_J 0x0DU +#define KEY_K 0x0EU +#define KEY_L 0x0FU +#define KEY_M 0x10U +#define KEY_N 0x11U +#define KEY_O 0x12U +#define KEY_P 0x13U +#define KEY_Q 0x14U +#define KEY_R 0x15U +#define KEY_S 0x16U +#define KEY_T 0x17U +#define KEY_U 0x18U +#define KEY_V 0x19U +#define KEY_W 0x1AU +#define KEY_X 0x1BU +#define KEY_Y 0x1CU +#define KEY_Z 0x1DU +#define KEY_1_EXCLAMATION_MARK 0x1EU +#define KEY_2_AT 0x1FU +#define KEY_3_NUMBER_SIGN 0x20U +#define KEY_4_DOLLAR 0x21U +#define KEY_5_PERCENT 0x22U +#define KEY_6_CARET 0x23U +#define KEY_7_AMPERSAND 0x24U +#define KEY_8_ASTERISK 0x25U +#define KEY_9_OPARENTHESIS 0x26U +#define KEY_0_CPARENTHESIS 0x27U +#define KEY_ENTER 0x28U +#define KEY_ESCAPE 0x29U +#define KEY_BACKSPACE 0x2AU +#define KEY_TAB 0x2BU +#define KEY_SPACEBAR 0x2CU +#define KEY_MINUS_UNDERSCORE 0x2DU +#define KEY_EQUAL_PLUS 0x2EU +#define KEY_OBRACKET_AND_OBRACE 0x2FU +#define KEY_CBRACKET_AND_CBRACE 0x30U +#define KEY_BACKSLASH_VERTICAL_BAR 0x31U +#define KEY_NONUS_NUMBER_SIGN_TILDE 0x32U +#define KEY_SEMICOLON_COLON 0x33U +#define KEY_SINGLE_AND_DOUBLE_QUOTE 0x34U +#define KEY_GRAVE ACCENT AND TILDE 0x35U +#define KEY_COMMA_AND_LESS 0x36U +#define KEY_DOT_GREATER 0x37U +#define KEY_SLASH_QUESTION 0x38U +#define KEY_CAPS LOCK 0x39U +#define KEY_F1 0x3AU +#define KEY_F2 0x3BU +#define KEY_F3 0x3CU +#define KEY_F4 0x3DU +#define KEY_F5 0x3EU +#define KEY_F6 0x3FU +#define KEY_F7 0x40U +#define KEY_F8 0x41U +#define KEY_F9 0x42U +#define KEY_F10 0x43U +#define KEY_F11 0x44U +#define KEY_F12 0x45U +#define KEY_PRINTSCREEN 0x46U +#define KEY_SCROLL LOCK 0x47U +#define KEY_PAUSE 0x48U +#define KEY_INSERT 0x49U +#define KEY_HOME 0x4AU +#define KEY_PAGEUP 0x4BU +#define KEY_DELETE 0x4CU +#define KEY_END1 0x4DU +#define KEY_PAGEDOWN 0x4EU +#define KEY_RIGHTARROW 0x4FU +#define KEY_LEFTARROW 0x50U +#define KEY_DOWNARROW 0x51U +#define KEY_UPARROW 0x52U +#define KEY_KEYPAD_NUM_LOCK_AND_CLEAR 0x53U +#define KEY_KEYPAD_SLASH 0x54U +#define KEY_KEYPAD_ASTERIKS 0x55U +#define KEY_KEYPAD_MINUS 0x56U +#define KEY_KEYPAD_PLUS 0x57U +#define KEY_KEYPAD_ENTER 0x58U +#define KEY_KEYPAD_1_END 0x59U +#define KEY_KEYPAD_2_DOWN_ARROW 0x5AU +#define KEY_KEYPAD_3_PAGEDN 0x5BU +#define KEY_KEYPAD_4_LEFT_ARROW 0x5CU +#define KEY_KEYPAD_5 0x5DU +#define KEY_KEYPAD_6_RIGHT_ARROW 0x5EU +#define KEY_KEYPAD_7_HOME 0x5FU +#define KEY_KEYPAD_8_UP_ARROW 0x60U +#define KEY_KEYPAD_9_PAGEUP 0x61U +#define KEY_KEYPAD_0_INSERT 0x62U +#define KEY_KEYPAD_DECIMAL_SEPARATOR_DELETE 0x63U +#define KEY_NONUS_BACK_SLASH_VERTICAL_BAR 0x64U +#define KEY_APPLICATION 0x65U +#define KEY_POWER 0x66U +#define KEY_KEYPAD_EQUAL 0x67U +#define KEY_F13 0x68U +#define KEY_F14 0x69U +#define KEY_F15 0x6AU +#define KEY_F16 0x6BU +#define KEY_F17 0x6CU +#define KEY_F18 0x6DU +#define KEY_F19 0x6EU +#define KEY_F20 0x6FU +#define KEY_F21 0x70U +#define KEY_F22 0x71U +#define KEY_F23 0x72U +#define KEY_F24 0x73U +#define KEY_EXECUTE 0x74U +#define KEY_HELP 0x75U +#define KEY_MENU 0x76U +#define KEY_SELECT 0x77U +#define KEY_STOP 0x78U +#define KEY_AGAIN 0x79U +#define KEY_UNDO 0x7AU +#define KEY_CUT 0x7BU +#define KEY_COPY 0x7CU +#define KEY_PASTE 0x7DU +#define KEY_FIND 0x7EU +#define KEY_MUTE 0x7FU +#define KEY_VOLUME_UP 0x80U +#define KEY_VOLUME_DOWN 0x81U +#define KEY_LOCKING_CAPS_LOCK 0x82U +#define KEY_LOCKING_NUM_LOCK 0x83U +#define KEY_LOCKING_SCROLL_LOCK 0x84U +#define KEY_KEYPAD_COMMA 0x85U +#define KEY_KEYPAD_EQUAL_SIGN 0x86U +#define KEY_INTERNATIONAL1 0x87U +#define KEY_INTERNATIONAL2 0x88U +#define KEY_INTERNATIONAL3 0x89U +#define KEY_INTERNATIONAL4 0x8AU +#define KEY_INTERNATIONAL5 0x8BU +#define KEY_INTERNATIONAL6 0x8CU +#define KEY_INTERNATIONAL7 0x8DU +#define KEY_INTERNATIONAL8 0x8EU +#define KEY_INTERNATIONAL9 0x8FU +#define KEY_LANG1 0x90U +#define KEY_LANG2 0x91U +#define KEY_LANG3 0x92U +#define KEY_LANG4 0x93U +#define KEY_LANG5 0x94U +#define KEY_LANG6 0x95U +#define KEY_LANG7 0x96U +#define KEY_LANG8 0x97U +#define KEY_LANG9 0x98U +#define KEY_ALTERNATE_ERASE 0x99U +#define KEY_SYSREQ 0x9AU +#define KEY_CANCEL 0x9BU +#define KEY_CLEAR 0x9CU +#define KEY_PRIOR 0x9DU +#define KEY_RETURN 0x9EU +#define KEY_SEPARATOR 0x9FU +#define KEY_OUT 0xA0U +#define KEY_OPER 0xA1U +#define KEY_CLEAR_AGAIN 0xA2U +#define KEY_CRSEL 0xA3U +#define KEY_EXSEL 0xA4U +#define KEY_KEYPAD_00 0xB0U +#define KEY_KEYPAD_000 0xB1U +#define KEY_THOUSANDS_SEPARATOR 0xB2U +#define KEY_DECIMAL_SEPARATOR 0xB3U +#define KEY_CURRENCY_UNIT 0xB4U +#define KEY_CURRENCY_SUB_UNIT 0xB5U +#define KEY_KEYPAD_OPARENTHESIS 0xB6U +#define KEY_KEYPAD_CPARENTHESIS 0xB7U +#define KEY_KEYPAD_OBRACE 0xB8U +#define KEY_KEYPAD_CBRACE 0xB9U +#define KEY_KEYPAD_TAB 0xBAU +#define KEY_KEYPAD_BACKSPACE 0xBBU +#define KEY_KEYPAD_A 0xBCU +#define KEY_KEYPAD_B 0xBDU +#define KEY_KEYPAD_C 0xBEU +#define KEY_KEYPAD_D 0xBFU +#define KEY_KEYPAD_E 0xC0U +#define KEY_KEYPAD_F 0xC1U +#define KEY_KEYPAD_XOR 0xC2U +#define KEY_KEYPAD_CARET 0xC3U +#define KEY_KEYPAD_PERCENT 0xC4U +#define KEY_KEYPAD_LESS 0xC5U +#define KEY_KEYPAD_GREATER 0xC6U +#define KEY_KEYPAD_AMPERSAND 0xC7U +#define KEY_KEYPAD_LOGICAL_AND 0xC8U +#define KEY_KEYPAD_VERTICAL_BAR 0xC9U +#define KEY_KEYPAD_LOGIACL_OR 0xCAU +#define KEY_KEYPAD_COLON 0xCBU +#define KEY_KEYPAD_NUMBER_SIGN 0xCCU +#define KEY_KEYPAD_SPACE 0xCDU +#define KEY_KEYPAD_AT 0xCEU +#define KEY_KEYPAD_EXCLAMATION_MARK 0xCFU +#define KEY_KEYPAD_MEMORY_STORE 0xD0U +#define KEY_KEYPAD_MEMORY_RECALL 0xD1U +#define KEY_KEYPAD_MEMORY_CLEAR 0xD2U +#define KEY_KEYPAD_MEMORY_ADD 0xD3U +#define KEY_KEYPAD_MEMORY_SUBTRACT 0xD4U +#define KEY_KEYPAD_MEMORY_MULTIPLY 0xD5U +#define KEY_KEYPAD_MEMORY_DIVIDE 0xD6U +#define KEY_KEYPAD_PLUSMINUS 0xD7U +#define KEY_KEYPAD_CLEAR 0xD8U +#define KEY_KEYPAD_CLEAR_ENTRY 0xD9U +#define KEY_KEYPAD_BINARY 0xDAU +#define KEY_KEYPAD_OCTAL 0xDBU +#define KEY_KEYPAD_DECIMAL 0xDCU +#define KEY_KEYPAD_HEXADECIMAL 0xDDU +#define KEY_LEFTCONTROL 0xE0U +#define KEY_LEFTSHIFT 0xE1U +#define KEY_LEFTALT 0xE2U +#define KEY_LEFT_GUI 0xE3U +#define KEY_RIGHTCONTROL 0xE4U +#define KEY_RIGHTSHIFT 0xE5U +#define KEY_RIGHTALT 0xE6U +#define KEY_RIGHT_GUI 0xE7U + +#define KBR_MAX_NBR_PRESSED 6U + +typedef struct +{ + uint8_t state; + uint8_t lctrl; + uint8_t lshift; + uint8_t lalt; + uint8_t lgui; + uint8_t rctrl; + uint8_t rshift; + uint8_t ralt; + uint8_t rgui; + uint8_t keys[6]; +} hid_keybd_info; + +/* function declarations */ +/* initialize keyboard */ +void usr_keybrd_init (void); +/* process keyboard data */ +void usr_keybrd_process_data (uint8_t pbuf); +/* initialize the keyboard function */ +usbh_status usbh_hid_keybd_init (usb_core_driver *udev, usbh_host *uhost); +/* get keyboard information */ +hid_keybd_info *usbh_hid_keybd_info_get (usb_core_driver *udev, usbh_host *uhost); +/* get the ascii code of hid */ +uint8_t usbh_hid_ascii_code_get (hid_keybd_info *info); +/* keyboard machine */ +void usbh_hid_keybrd_machine (usb_core_driver *udev, usbh_host *uhost); + +#endif /* __USBH_HID_KEYBD_H */ diff --git a/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/host/class/hid/Include/usbh_hid_mouse.h b/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/host/class/hid/Include/usbh_hid_mouse.h new file mode 100644 index 0000000000..bf4cd44573 --- /dev/null +++ b/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/host/class/hid/Include/usbh_hid_mouse.h @@ -0,0 +1,59 @@ +/*! + \file usbh_hid_mouse.h + \brief header file for the usbh_hid_mouse.c + + \version 2020-08-01, V3.0.0, firmware for GD32F4xx +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef __USBH_HID_MOUSE_H +#define __USBH_HID_MOUSE_H + +#include "usbh_hid_core.h" + +typedef struct _hid_mouse_info +{ + uint8_t x; + uint8_t y; + uint8_t buttons[3]; +} hid_mouse_info; + +/* function declarations */ +/* initialize mouse */ +void usr_mouse_init (void); +/* process mouse data */ +void usr_mouse_process_data (hid_mouse_info *data); +/* initialize mouse function */ +usbh_status usbh_hid_mouse_init (usb_core_driver *udev, usbh_host *uhost); +/* get mouse information */ +hid_mouse_info *usbh_hid_mouse_info_get (usb_core_driver *udev, usbh_host *uhost); +/* mouse machine */ +void usbh_hid_mouse_machine (usb_core_driver *udev, usbh_host *uhost); + +#endif /* __USBH_HID_MOUSE_H */ diff --git a/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/host/class/hid/Include/usbh_hid_parser.h b/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/host/class/hid/Include/usbh_hid_parser.h new file mode 100644 index 0000000000..d950b03315 --- /dev/null +++ b/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/host/class/hid/Include/usbh_hid_parser.h @@ -0,0 +1,61 @@ +/*! + \file usbh_hid_core.h + \brief header file for the usbh_hid_core.c + + \version 2020-08-01, V3.0.0, firmware for GD32F4xx +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef __USBH_HID_PARSER_H +#define __USBH_HID_PARSER_H + +#include "usbh_hid_core.h" +#include "usbh_hid_usage.h" + +typedef struct +{ + uint8_t *data; + uint32_t size; + uint8_t shift; + uint8_t count; + uint8_t sign; + uint32_t logical_min; /*min value device can return*/ + uint32_t logical_max; /*max value device can return*/ + uint32_t physical_min; /*min vale read can report*/ + uint32_t physical_max; /*max value read can report*/ + uint32_t resolution; +} hid_report_item; + +/* function declarations */ +/* read a hid report item */ +uint32_t hid_item_read (hid_report_item *ri, uint8_t ndx); +/* write a hid report item */ +uint32_t hid_item_write (hid_report_item *ri, uint32_t value, uint8_t ndx); + +#endif /* __USBH_HID_PARSER_H */ diff --git a/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/host/class/hid/Include/usbh_hid_usage.h b/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/host/class/hid/Include/usbh_hid_usage.h new file mode 100644 index 0000000000..8718435c63 --- /dev/null +++ b/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/host/class/hid/Include/usbh_hid_usage.h @@ -0,0 +1,141 @@ +/*! + \file usbh_hid_core.h + \brief header file for the usbh_hid_core.c + + \version 2020-08-01, V3.0.0, firmware for GD32F4xx +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef __USDH_HID_USAGE_H +#define __USDH_HID_USAGE_H + +/* HID 1.11 usage pages */ +#define HID_USAGE_PAGE_UNDEFINED uint16_t (0x00) /* Undefined */ + +/* top level pages */ +#define HID_USAGE_PAGE_GEN_DES uint16_t (0x01) /* Generic Desktop Controls*/ +#define HID_USAGE_PAGE_SIM_CTR uint16_t (0x02) /* Simulation Controls */ +#define HID_USAGE_PAGE_VR_CTR uint16_t (0x03) /* VR Controls */ +#define HID_USAGE_PAGE_SPORT_CTR uint16_t (0x04) /* Sport Controls */ +#define HID_USAGE_PAGE_GAME_CTR uint16_t (0x05) /* Game Controls */ +#define HID_USAGE_PAGE_GEN_DEV uint16_t (0x06) /* Generic Device Controls */ +#define HID_USAGE_PAGE_KEYB uint16_t (0x07) /* Keyboard/Keypad */ +#define HID_USAGE_PAGE_LED uint16_t (0x08) /* LEDs */ +#define HID_USAGE_PAGE_BUTTON uint16_t (0x09) /* Button */ +#define HID_USAGE_PAGE_ORDINAL uint16_t (0x0A) /* Ordinal */ +#define HID_USAGE_PAGE_PHONE uint16_t (0x0B) /* Telephony */ +#define HID_USAGE_PAGE_CONSUMER uint16_t (0x0C) /* Consumer */ +#define HID_USAGE_PAGE_DIGITIZER uint16_t (0x0D) /* Digitizer*/ +#define HID_USAGE_PAGE_PID uint16_t (0x0F) /* PID Page (force feedback and related devices) */ +#define HID_USAGE_PAGE_UNICODE uint16_t (0x10) /* Unicode */ +#define HID_USAGE_PAGE_ALNUM_DISP uint16_t (0x14) /* Alphanumeric Display */ +/* end of top level pages */ + +#define HID_USAGE_PAGE_MEDICAL uint16_t (0x40) /* Medical Instruments */ + +/* 80-83 Monitor pages USB Device Class Definition for Monitor Devices */ +/* 84-87 Power pages USB Device Class Definition for Power Devices */ +#define HID_USAGE_PAGE_BARCODE uint16_t (0x8C) /* Bar Code Scanner page */ +#define HID_USAGE_PAGE_SCALE uint16_t (0x8D) /* Scale page */ +#define HID_USAGE_PAGE_MSR uint16_t (0x8E) /* Magnetic Stripe Reading (MSR) Devices */ +#define HID_USAGE_PAGE_POS uint16_t (0x8F) /* Reserved Point of Sale pages */ +#define HID_USAGE_PAGE_CAMERA_CTR uint16_t (0x90) /* Camera Control Page */ +#define HID_USAGE_PAGE_ARCADE uint16_t (0x91) /* Arcade Page */ + +/* usage definitions for the "generic desktop" page */ +#define HID_USAGE_UNDEFINED uint16_t (0x00) /* Undefined */ +#define HID_USAGE_POINTER uint16_t (0x01) /* Pointer (Physical Collection) */ +#define HID_USAGE_MOUSE uint16_t (0x02) /* Mouse (Application Collection) */ +#define HID_USAGE_JOYSTICK uint16_t (0x04) /* Joystick (Application Collection) */ +#define HID_USAGE_GAMEPAD uint16_t (0x05) /* Game Pad (Application Collection) */ +#define HID_USAGE_KBD uint16_t (0x06) /* Keyboard (Application Collection) */ +#define HID_USAGE_KEYPAD uint16_t (0x07) /* Keypad (Application Collection) */ +#define HID_USAGE_MAX_CTR uint16_t (0x08) /* Multi-axis Controller (Application Collection) */ +#define HID_USAGE_X uint16_t (0x30) /* X (Dynamic Value) */ +#define HID_USAGE_Y uint16_t (0x31) /* Y (Dynamic Value) */ +#define HID_USAGE_Z uint16_t (0x32) /* Z (Dynamic Value) */ +#define HID_USAGE_RX uint16_t (0x33) /* Rx (Dynamic Value) */ +#define HID_USAGE_RY uint16_t (0x34) /* Ry (Dynamic Value) */ +#define HID_USAGE_RZ uint16_t (0x35) /* Rz (Dynamic Value) */ +#define HID_USAGE_SLIDER uint16_t (0x36) /* Slider (Dynamic Value) */ +#define HID_USAGE_DIAL uint16_t (0x37) /* Dial (Dynamic Value) */ +#define HID_USAGE_WHEEL uint16_t (0x38) /* Wheel (Dynamic Value) */ +#define HID_USAGE_HATSW uint16_t (0x39) /* Hat switch (Dynamic Value) */ +#define HID_USAGE_COUNTEDBUF uint16_t (0x3A) /* Counted Buffer (Logical Collection) */ +#define HID_USAGE_BYTECOUNT uint16_t (0x3B) /* Byte Count (Dynamic Value) */ +#define HID_USAGE_MOTIONWAKE uint16_t (0x3C) /* Motion Wakeup (One Shot Control) */ +#define HID_USAGE_START uint16_t (0x3D) /* Start (On/Off Control) */ +#define HID_USAGE_SELECT uint16_t (0x3E) /* Select (On/Off Control) */ +#define HID_USAGE_VX uint16_t (0x40) /* Vx (Dynamic Value) */ +#define HID_USAGE_VY uint16_t (0x41) /* Vy (Dynamic Value) */ +#define HID_USAGE_VZ uint16_t (0x42) /* Vz (Dynamic Value) */ +#define HID_USAGE_VBRX uint16_t (0x43) /* Vbrx (Dynamic Value) */ +#define HID_USAGE_VBRY uint16_t (0x44) /* Vbry (Dynamic Value) */ +#define HID_USAGE_VBRZ uint16_t (0x45) /* Vbrz (Dynamic Value) */ +#define HID_USAGE_VNO uint16_t (0x46) /* Vno (Dynamic Value) */ +#define HID_USAGE_FEATNOTIF uint16_t (0x47) /* Feature Notification (Dynamic Value),(Dynamic Flag) */ +#define HID_USAGE_SYSCTL uint16_t (0x80) /* System Control (Application Collection) */ +#define HID_USAGE_PWDOWN uint16_t (0x81) /* System Power Down (One Shot Control) */ +#define HID_USAGE_SLEEP uint16_t (0x82) /* System Sleep (One Shot Control) */ +#define HID_USAGE_WAKEUP uint16_t (0x83) /* System Wake Up (One Shot Control) */ +#define HID_USAGE_CONTEXTM uint16_t (0x84) /* System Context Menu (One Shot Control) */ +#define HID_USAGE_MAINM uint16_t (0x85) /* System Main Menu (One Shot Control) */ +#define HID_USAGE_APPM uint16_t (0x86) /* System App Menu (One Shot Control) */ +#define HID_USAGE_MENUHELP uint16_t (0x87) /* System Menu Help (One Shot Control) */ +#define HID_USAGE_MENUEXIT uint16_t (0x88) /* System Menu Exit (One Shot Control) */ +#define HID_USAGE_MENUSELECT uint16_t (0x89) /* System Menu Select (One Shot Control) */ +#define HID_USAGE_SYSM_RIGHT uint16_t (0x8A) /* System Menu Right (Re-Trigger Control) */ +#define HID_USAGE_SYSM_LEFT uint16_t (0x8B) /* System Menu Left (Re-Trigger Control) */ +#define HID_USAGE_SYSM_UP uint16_t (0x8C) /* System Menu Up (Re-Trigger Control) */ +#define HID_USAGE_SYSM_DOWN uint16_t (0x8D) /* System Menu Down (Re-Trigger Control) */ +#define HID_USAGE_COLDRESET uint16_t (0x8E) /* System Cold Restart (One Shot Control) */ +#define HID_USAGE_WARMRESET uint16_t (0x8F) /* System Warm Restart (One Shot Control) */ +#define HID_USAGE_DUP uint16_t (0x90) /* D-pad Up (On/Off Control) */ +#define HID_USAGE_DDOWN uint16_t (0x91) /* D-pad Down (On/Off Control) */ +#define HID_USAGE_DRIGHT uint16_t (0x92) /* D-pad Right (On/Off Control) */ +#define HID_USAGE_DLEFT uint16_t (0x93) /* D-pad Left (On/Off Control) */ +#define HID_USAGE_SYS_DOCK uint16_t (0xA0) /* System Dock (One Shot Control) */ +#define HID_USAGE_SYS_UNDOCK uint16_t (0xA1) /* System Undock (One Shot Control) */ +#define HID_USAGE_SYS_SETUP uint16_t (0xA2) /* System Setup (One Shot Control) */ +#define HID_USAGE_SYS_BREAK uint16_t (0xA3) /* System Break (One Shot Control) */ +#define HID_USAGE_SYS_DBGBRK uint16_t (0xA4) /* System Debugger Break (One Shot Control) */ +#define HID_USAGE_APP_BRK uint16_t (0xA5) /* Application Break (One Shot Control) */ +#define HID_USAGE_APP_DBGBRK uint16_t (0xA6) /* Application Debugger Break (One Shot Control) */ +#define HID_USAGE_SYS_SPKMUTE uint16_t (0xA7) /* System Speaker Mute (One Shot Control) */ +#define HID_USAGE_SYS_HIBERN uint16_t (0xA8) /* System Hibernate (One Shot Control) */ +#define HID_USAGE_SYS_SIDPINV uint16_t (0xB0) /* System Display Invert (One Shot Control) */ +#define HID_USAGE_SYS_DISPINT uint16_t (0xB1) /* System Display Internal (One Shot Control) */ +#define HID_USAGE_SYS_DISPEXT uint16_t (0xB2) /* System Display External (One Shot Control) */ +#define HID_USAGE_SYS_DISPBOTH uint16_t (0xB3) /* System Display Both (One Shot Control) */ +#define HID_USAGE_SYS_DISPDUAL uint16_t (0xB4) /* System Display Dual (One Shot Control) */ +#define HID_USAGE_SYS_DISPTGLIE uint16_t (0xB5) /* System Display Toggle Int/Ext (One Shot Control) */ +#define HID_USAGE_SYS_DISP_SWAP uint16_t (0xB6) /* System Display Swap Primary/Secondary (One Shot Control) */ +#define HID_USAGE_SYS_DIPS_LCDA uint16_t (0xB7) /* System Display LCD Autoscale (One Shot Control) */ + +#endif /* __USDH_HID_USAGE_H */ diff --git a/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/host/class/hid/Source/usbh_hid_core.c b/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/host/class/hid/Source/usbh_hid_core.c new file mode 100644 index 0000000000..75e89959fe --- /dev/null +++ b/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/host/class/hid/Source/usbh_hid_core.c @@ -0,0 +1,675 @@ +/*! + \file usbh_hid_core.c + \brief USB host HID class driver + + \version 2020-08-01, V3.0.0, firmware for GD32F4xx +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "usbh_pipe.h" +#include "usbh_hid_core.h" +#include "usbh_hid_mouse.h" +#include "usbh_hid_keybd.h" + +#include +#include + +static void usbh_hiddesc_parse (usb_desc_hid *hid_desc, uint8_t *buf); +static void usbh_hid_itf_deinit (usbh_host *uhost); +static usbh_status usbh_hid_itf_init (usbh_host *uhost); +static usbh_status usbh_hid_class_req (usbh_host *uhost); +static usbh_status usbh_hid_handle (usbh_host *uhost); +static usbh_status usbh_hid_reportdesc_get (usbh_host *uhost, uint16_t len); +static usbh_status usbh_hid_sof(usbh_host *uhost); +static usbh_status usbh_hid_desc_get (usbh_host *uhost, uint16_t len); +static usbh_status usbh_set_idle (usbh_host *uhost, uint8_t duration, uint8_t report_ID); +static usbh_status usbh_set_protocol (usbh_host *uhost, uint8_t protocol); + +usbh_class usbh_hid = +{ + USB_HID_CLASS, + usbh_hid_itf_init, + usbh_hid_itf_deinit, + usbh_hid_class_req, + usbh_hid_handle, + usbh_hid_sof +}; + +/*! + \brief get report + \param[in] uhost: pointer to USB host + \param[in] report_type: duration for HID set idle request + \param[in] report_ID: targeted report ID for HID set idle request + \param[in] report_len: length of data report to be send + \param[in] report_buf: report buffer + \param[out] none + \retval operation status +*/ +usbh_status usbh_get_report (usbh_host *uhost, + uint8_t report_type, + uint8_t report_ID, + uint8_t report_len, + uint8_t *report_buf) +{ + usbh_status status = USBH_BUSY; + + if (CTL_IDLE == uhost->control.ctl_state) { + uhost->control.setup.req = (usb_req) { + .bmRequestType = USB_TRX_IN | USB_RECPTYPE_ITF | USB_REQTYPE_CLASS, + .bRequest = GET_REPORT, + .wValue = (report_type << 8U) | report_ID, + .wIndex = 0U, + .wLength = report_len + }; + + usbh_ctlstate_config (uhost, report_buf, report_len); + } + + status = usbh_ctl_handler (uhost); + + return status; +} + +/*! + \brief set report + \param[in] udev: pointer to USB core instance + \param[in] uhost: pointer to USB host + \param[in] report_type: duration for HID set idle request + \param[in] report_ID: targeted report ID for HID set idle request + \param[in] report_len: length of data report to be send + \param[in] report_buf: report buffer + \param[out] none + \retval operation status +*/ +usbh_status usbh_set_report (usb_core_driver *udev, + usbh_host *uhost, + uint8_t report_type, + uint8_t report_ID, + uint8_t report_len, + uint8_t *report_buf) +{ + usbh_status status = USBH_BUSY; + + if (CTL_IDLE == uhost->control.ctl_state) { + uhost->control.setup.req = (usb_req) { + .bmRequestType = USB_TRX_OUT | USB_RECPTYPE_ITF | USB_REQTYPE_CLASS, + .bRequest = SET_REPORT, + .wValue = (report_type << 8U) | report_ID, + .wIndex = 0U, + .wLength = report_len + }; + + usbh_ctlstate_config (uhost, report_buf, report_len); + } + + status = usbh_ctl_handler (uhost); + + return status; +} + +/*! + \brief deinitialize the host pipes used for the HID class + \param[in] uhost: pointer to USB host + \param[out] none + \retval operation status +*/ +void usbh_hid_itf_deinit (usbh_host *uhost) +{ + usbh_hid_handler *hid = (usbh_hid_handler *)uhost->active_class->class_data; + + if (0x00U != hid->pipe_in) { + usb_pipe_halt (uhost->data, hid->pipe_in); + + usbh_pipe_free (uhost->data, hid->pipe_in); + + hid->pipe_in = 0U; /* reset the pipe as free */ + } + + if (0x00U != hid->pipe_out) { + usb_pipe_halt (uhost->data, hid->pipe_out); + + usbh_pipe_free (uhost->data, hid->pipe_out); + + hid->pipe_out = 0U; /* reset the channel as free */ + } +} + +/*! + \brief return device type + \param[in] udev: pointer to USB core instance + \param[in] uhost: pointer to USB host + \param[out] none + \retval hid_type +*/ +hid_type usbh_hid_device_type_get(usb_core_driver *udev, usbh_host *uhost) +{ + hid_type type = HID_UNKNOWN; + uint8_t interface_protocol; + + if (HOST_CLASS_HANDLER == uhost->cur_state) { + interface_protocol = uhost->dev_prop.cfg_desc_set.itf_desc_set[uhost->dev_prop.cur_itf][0].itf_desc.bInterfaceProtocol; + + if (USB_HID_PROTOCOL_KEYBOARD == interface_protocol) { + type = HID_KEYBOARD; + } else { + if (USB_HID_PROTOCOL_MOUSE == interface_protocol) { + type = HID_MOUSE; + } + } + } + + return type; +} + +/*! + \brief return HID device poll time + \param[in] udev: pointer to USB core instance + \param[in] uhost: pointer to USB host + \param[out] none + \retval poll time (ms) +*/ +uint8_t usbh_hid_poll_interval_get (usb_core_driver *udev, usbh_host *uhost) +{ + usbh_hid_handler *hid = (usbh_hid_handler *)uhost->active_class->class_data; + + if ((HOST_CLASS_ENUM == uhost->cur_state) || + (HOST_USER_INPUT == uhost->cur_state) || + (HOST_CHECK_CLASS == uhost->cur_state) || + (HOST_CLASS_HANDLER == uhost->cur_state)) { + return (uint8_t)(hid->poll); + } else { + return 0U; + } +} + +/*! + \brief read from FIFO + \param[in] fifo: fifo address + \param[in] buf: read buffer + \param[in] nbytes: number of item to read + \param[out] none + \retval number of read items +*/ +uint16_t usbh_hid_fifo_read (data_fifo *fifo, void *buf, uint16_t nbytes) +{ + uint16_t i = 0U; + uint8_t *p = (uint8_t*) buf; + + if (0U == fifo->lock) { + fifo->lock = 1U; + + for (i = 0U; i < nbytes; i++) { + if (fifo->tail != fifo->head) { + *p++ = fifo->buf[fifo->tail]; + fifo->tail++; + + if (fifo->tail == fifo->size) { + fifo->tail = 0U; + } + } else { + fifo->lock = 0U; + + return i; + } + } + } + + fifo->lock = 0U; + + return nbytes; +} + +/*! + \brief write to FIFO + \param[in] fifo: fifo address + \param[in] buf: read buffer + \param[in] nbytes: number of item to read + \param[out] none + \retval number of write items +*/ +uint16_t usbh_hid_fifo_write (data_fifo *fifo, void *buf, uint16_t nbytes) +{ + uint16_t i = 0U; + uint8_t *p = (uint8_t*) buf; + + if (0U == fifo->lock) { + fifo->lock = 1U; + + for (i = 0U; i < nbytes; i++) { + if ((fifo->head + 1U == fifo->tail) || + ((fifo->head + 1U == fifo->size) && (0U == fifo->tail))) { + fifo->lock = 0U; + + return i; + } else { + fifo->buf[fifo->head] = *p++; + fifo->head++; + + if (fifo->head == fifo->size) { + fifo->head = 0U; + } + } + } + } + + fifo->lock = 0U; + + return nbytes; +} + +/*! + \brief initialize FIFO + \param[in] fifo: fifo address + \param[in] buf: read buffer + \param[in] size: size of FIFO + \param[out] none + \retval none +*/ +void usbh_hid_fifo_init (data_fifo *fifo, uint8_t *buf, uint16_t size) +{ + fifo->head = 0U; + fifo->tail = 0U; + fifo->lock = 0U; + fifo->size = size; + fifo->buf = buf; +} + +/*! + \brief initialize the hid class + \param[in] uhost: pointer to USB host + \param[out] none + \retval operation status +*/ +static usbh_status usbh_hid_itf_init (usbh_host *uhost) +{ + uint8_t num = 0U, ep_num = 0U, interface = 0U; + usbh_status status = USBH_BUSY; + + interface = usbh_interface_find(&uhost->dev_prop, USB_HID_CLASS, USB_HID_SUBCLASS_BOOT_ITF, 0xFFU); + + if (0xFFU == interface) { + uhost->usr_cb->dev_not_supported(); + + status = USBH_FAIL; + } else { + usbh_interface_select(&uhost->dev_prop, interface); + + static usbh_hid_handler hid_handler; + + memset((void*)&hid_handler, 0, sizeof(usbh_hid_handler)); + + hid_handler.state = HID_ERROR; + + uint8_t itf_protocol = uhost->dev_prop.cfg_desc_set.itf_desc_set[uhost->dev_prop.cur_itf][0].itf_desc.bInterfaceProtocol; + if (USB_HID_PROTOCOL_KEYBOARD == itf_protocol) { + hid_handler.init = usbh_hid_keybd_init; + hid_handler.machine = usbh_hid_keybrd_machine; + } else if (USB_HID_PROTOCOL_MOUSE == itf_protocol) { + hid_handler.init = usbh_hid_mouse_init; + hid_handler.machine = usbh_hid_mouse_machine; + } else { + status = USBH_FAIL; + } + + hid_handler.state = HID_INIT; + hid_handler.ctl_state = HID_REQ_INIT; + hid_handler.ep_addr = uhost->dev_prop.cfg_desc_set.itf_desc_set[uhost->dev_prop.cur_itf][0].ep_desc[0].bEndpointAddress; + hid_handler.len = uhost->dev_prop.cfg_desc_set.itf_desc_set[uhost->dev_prop.cur_itf][0].ep_desc[0].wMaxPacketSize; + hid_handler.poll = uhost->dev_prop.cfg_desc_set.itf_desc_set[uhost->dev_prop.cur_itf][0].ep_desc[0].bInterval; + + if (hid_handler.poll < HID_MIN_POLL) { + hid_handler.poll = HID_MIN_POLL; + } + + /* check fifo available number of endpoints */ + /* find the number of endpoints in the interface descriptor */ + /* choose the lower number in order not to overrun the buffer allocated */ + ep_num = USB_MIN(uhost->dev_prop.cfg_desc_set.itf_desc_set[uhost->dev_prop.cur_itf][0].itf_desc.bNumEndpoints, USBH_MAX_EP_NUM); + + /* decode endpoint IN and OUT address from interface descriptor */ + for (num = 0U; num < ep_num; num++) { + usb_desc_ep *ep_desc = &uhost->dev_prop.cfg_desc_set.itf_desc_set[uhost->dev_prop.cur_itf][0].ep_desc[num]; + + uint8_t ep_addr = ep_desc->bEndpointAddress; + + if (ep_addr & 0x80U) { + hid_handler.ep_in = ep_addr; + hid_handler.pipe_in = usbh_pipe_allocate (uhost->data, ep_addr); + + /* open channel for IN endpoint */ + usbh_pipe_create (uhost->data, + &uhost->dev_prop, + hid_handler.pipe_in, + USB_EPTYPE_INTR, + hid_handler.len); + + usbh_pipe_toggle_set(uhost->data, hid_handler.pipe_in, 0U); + } else { + hid_handler.ep_out = ep_addr; + hid_handler.pipe_out = usbh_pipe_allocate (uhost->data, ep_addr); + + /* open channel for OUT endpoint */ + usbh_pipe_create (uhost->data, + &uhost->dev_prop, + hid_handler.pipe_out, + USB_EPTYPE_INTR, + hid_handler.len); + + usbh_pipe_toggle_set(uhost->data, hid_handler.pipe_out, 0U); + } + } + + uhost->active_class->class_data = (void *)&hid_handler; + + status = USBH_OK; + } + + return status; +} + +/*! + \brief handle HID class requests for HID class + \param[in] uhost: pointer to USB host + \param[out] none + \retval operation status +*/ +static usbh_status usbh_hid_class_req (usbh_host *uhost) +{ + usbh_status status = USBH_BUSY; + usbh_status class_req_status = USBH_BUSY; + + usbh_hid_handler *hid = (usbh_hid_handler *)uhost->active_class->class_data; + + /* handle HID control state machine */ + switch (hid->ctl_state) { + case HID_REQ_INIT: + case HID_REQ_GET_HID_DESC: + /* get HID descriptor */ + if (USBH_OK == usbh_hid_desc_get (uhost, USB_HID_DESC_SIZE)) { + usbh_hiddesc_parse(&hid->hid_desc, uhost->dev_prop.data); + + hid->ctl_state = HID_REQ_GET_REPORT_DESC; + } + break; + + case HID_REQ_GET_REPORT_DESC: + /* get report descriptor */ + if (USBH_OK == usbh_hid_reportdesc_get(uhost, hid->hid_desc.wDescriptorLength)) { + hid->ctl_state = HID_REQ_SET_IDLE; + } + break; + + case HID_REQ_SET_IDLE: + class_req_status = usbh_set_idle (uhost, 0U, 0U); + + /* set idle */ + if (USBH_OK == class_req_status) { + hid->ctl_state = HID_REQ_SET_PROTOCOL; + } else { + if(USBH_NOT_SUPPORTED == class_req_status) { + hid->ctl_state = HID_REQ_SET_PROTOCOL; + } + } + break; + + case HID_REQ_SET_PROTOCOL: + /* set protocol */ + if (USBH_OK == usbh_set_protocol (uhost, 0U)) { + hid->ctl_state = HID_REQ_IDLE; + + /* all requests performed */ + status = USBH_OK; + } + break; + + case HID_REQ_IDLE: + default: + break; + } + + return status; +} + +/*! + \brief manage state machine for HID data transfers + \param[in] uhost: pointer to USB host + \param[out] none + \retval operation status +*/ +static usbh_status usbh_hid_handle (usbh_host *uhost) +{ + usbh_status status = USBH_OK; + usbh_hid_handler *hid = (usbh_hid_handler *)uhost->active_class->class_data; + + switch (hid->state) { + case HID_INIT: + hid->init(uhost->data, uhost); + hid->state = HID_IDLE; + break; + + case HID_IDLE: + hid->state = HID_SYNC; + status = USBH_OK; + break; + + case HID_SYNC: + /* sync with start of even frame */ + if (true == usb_frame_even(uhost->data)) { + hid->state = HID_GET_DATA; + } + break; + + case HID_GET_DATA: + usbh_data_recev (uhost->data, hid->pdata, hid->pipe_in, hid->len); + + hid->state = HID_POLL; + hid->timer = usb_curframe_get (uhost->data); + hid->data_ready = 0U; + break; + + case HID_POLL: + if (URB_DONE == usbh_urbstate_get (uhost->data, hid->pipe_in)) { + if (0U == hid->data_ready) { /* handle data once */ + usbh_hid_fifo_write(&hid->fifo, hid->pdata, hid->len); + hid->data_ready = 1U; + + hid->machine(uhost->data, uhost); + } + } else { + if (URB_STALL == usbh_urbstate_get (uhost->data, hid->pipe_in)) { /* IN endpoint stalled */ + /* issue clear feature on interrupt in endpoint */ + if (USBH_OK == (usbh_clrfeature (uhost, hid->ep_addr, hid->pipe_in))) { + /* change state to issue next in token */ + hid->state = HID_GET_DATA; + } + } + } + break; + + default: + break; + } + return status; +} + +/*! + \brief send get report descriptor command to the device + \param[in] uhost: pointer to USB host + \param[in] len: HID report descriptor length + \param[out] none + \retval operation status +*/ +static usbh_status usbh_hid_reportdesc_get (usbh_host *uhost, uint16_t len) +{ + usbh_status status = USBH_BUSY; + + if (CTL_IDLE == uhost->control.ctl_state) { + uhost->control.setup.req = (usb_req) { + .bmRequestType = USB_TRX_IN | USB_RECPTYPE_ITF | USB_REQTYPE_STRD, + .bRequest = USB_GET_DESCRIPTOR, + .wValue = USBH_DESC(USB_DESCTYPE_REPORT), + .wIndex = 0U, + .wLength = len + }; + + usbh_ctlstate_config (uhost, uhost->dev_prop.data, len); + } + + status = usbh_ctl_handler (uhost); + + return status; +} + +/*! + \brief managing the SOF process + \param[in] uhost: pointer to USB host + \param[out] none + \retval operation status +*/ +static usbh_status usbh_hid_sof(usbh_host *uhost) +{ + usbh_hid_handler *hid = (usbh_hid_handler *)uhost->active_class->class_data; + + if (HID_POLL == hid->state) { + uint32_t frame_count = usb_curframe_get (uhost->data); + + if ((frame_count > hid->timer) && ((frame_count - hid->timer) >= hid->poll)) { + hid->state = HID_GET_DATA; + } else if ((frame_count < hid->timer) && ((frame_count + 0x3FFFU - hid->timer) >= hid->poll)) { + hid->state = HID_GET_DATA; + } else { + /* no operation */ + } + } + + return USBH_OK; +} + +/*! + \brief send the command of get HID descriptor to the device + \param[in] uhost: pointer to USB host + \param[in] len: HID descriptor length + \param[out] none + \retval operation status +*/ +static usbh_status usbh_hid_desc_get (usbh_host *uhost, uint16_t len) +{ + usbh_status status = USBH_BUSY; + + if (CTL_IDLE == uhost->control.ctl_state) { + uhost->control.setup.req = (usb_req) { + .bmRequestType = USB_TRX_IN | USB_RECPTYPE_ITF | USB_REQTYPE_STRD, + .bRequest = USB_GET_DESCRIPTOR, + .wValue = USBH_DESC(USB_DESCTYPE_HID), + .wIndex = 0U, + .wLength = len + }; + + usbh_ctlstate_config (uhost, uhost->dev_prop.data, len); + } + + status = usbh_ctl_handler (uhost); + + return status; +} + +/*! + \brief set idle state + \param[in] uhost: pointer to USB host + \param[in] duration: duration for HID set idle request + \param[in] report_ID: targeted report ID for HID set idle request + \param[out] none + \retval operation status +*/ +static usbh_status usbh_set_idle (usbh_host *uhost, uint8_t duration, uint8_t report_ID) +{ + usbh_status status = USBH_BUSY; + + if (CTL_IDLE == uhost->control.ctl_state) { + uhost->control.setup.req = (usb_req) { + .bmRequestType = USB_TRX_OUT | USB_RECPTYPE_ITF | USB_REQTYPE_CLASS, + .bRequest = SET_IDLE, + .wValue = (duration << 8U) | report_ID, + .wIndex = 0U, + .wLength = 0U + }; + + usbh_ctlstate_config (uhost, NULL, 0U); + } + + status = usbh_ctl_handler (uhost); + + return status; +} + +/*! + \brief set protocol state + \param[in] uhost: pointer to USB host + \param[in] protocol: boot/report protocol + \param[out] none + \retval operation status +*/ +static usbh_status usbh_set_protocol (usbh_host *uhost, uint8_t protocol) +{ + usbh_status status = USBH_BUSY; + + if (CTL_IDLE == uhost->control.ctl_state) { + uhost->control.setup.req = (usb_req) { + .bmRequestType = USB_TRX_OUT | USB_RECPTYPE_ITF | USB_REQTYPE_CLASS, + .bRequest = SET_PROTOCOL, + .wValue = !protocol, + .wIndex = 0U, + .wLength = 0U + }; + + usbh_ctlstate_config (uhost, NULL, 0U); + } + + status = usbh_ctl_handler (uhost); + + return status; +} + +/*! + \brief parse the HID descriptor + \param[in] hid_desc: pointer to HID descriptor + \param[in] buf: pointer to buffer where the source descriptor is available + \param[out] none + \retval none +*/ +static void usbh_hiddesc_parse (usb_desc_hid *hid_desc, uint8_t *buf) +{ + hid_desc->header.bLength = *(uint8_t *)(buf + 0U); + hid_desc->header.bDescriptorType = *(uint8_t *)(buf + 1U); + hid_desc->bcdHID = BYTE_SWAP(buf + 2U); + hid_desc->bCountryCode = *(uint8_t *)(buf + 4U); + hid_desc->bNumDescriptors = *(uint8_t *)(buf + 5U); + hid_desc->bDescriptorType = *(uint8_t *)(buf + 6U); + hid_desc->wDescriptorLength = BYTE_SWAP(buf + 7U); +} diff --git a/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/host/class/hid/Source/usbh_hid_keybd.c b/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/host/class/hid/Source/usbh_hid_keybd.c new file mode 100644 index 0000000000..aede5b8cca --- /dev/null +++ b/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/host/class/hid/Source/usbh_hid_keybd.c @@ -0,0 +1,399 @@ +/*! + \file usbh_hid_keybd.c + \brief USB host HID keyboard driver + + \version 2020-08-01, V3.0.0, firmware for GD32F4xx +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "usbh_hid_keybd.h" +#include "usbh_hid_parser.h" +#include + +hid_keybd_info keybd_info; + +uint32_t keybd_report_data[2]; + +static const hid_report_item imp_0_lctrl = +{ + (uint8_t*)(void *)keybd_report_data + 0, /* data */ + 1, /* size */ + 0, /* shift */ + 0, /* count (only for array items) */ + 0, /* signed */ + 0, /* min value read can return */ + 1, /* max value read can return */ + 0, /* min vale device can report */ + 1, /* max value device can report */ + 1 /* resolution */ +}; + +static const hid_report_item imp_0_lshift = +{ + (uint8_t*)(void *)keybd_report_data + 0, /* data */ + 1, /* size */ + 1, /* shift */ + 0, /* count (only for array items) */ + 0, /* signed */ + 0, /* min value read can return */ + 1, /* max value read can return */ + 0, /* min vale device can report */ + 1, /* max value device can report */ + 1 /* resolution */ +}; + +static const hid_report_item imp_0_lalt = +{ + (uint8_t*)(void *)keybd_report_data + 0, /* data */ + 1, /* size */ + 2, /* shift */ + 0, /* count (only for array items) */ + 0, /* signed */ + 0, /* min value read can return */ + 1, /* max value read can return */ + 0, /* min vale device can report */ + 1, /* max value device can report */ + 1 /* resolution */ +}; + +static const hid_report_item imp_0_lgui = +{ + (uint8_t*)(void *)keybd_report_data + 0, /* data */ + 1, /* size */ + 3, /* shift */ + 0, /* count (only for array items) */ + 0, /* signed */ + 0, /* min value read can return */ + 1, /* max value read can return */ + 0, /* min vale device can report */ + 1, /* max value device can report */ + 1 /* resolution */ +}; + +static const hid_report_item imp_0_rctrl = +{ + (uint8_t*)(void *)keybd_report_data + 0, /* data */ + 1, /* size */ + 4, /* shift */ + 0, /* count (only for array items) */ + 0, /* signed */ + 0, /* min value read can return */ + 1, /* max value read can return */ + 0, /* min vale device can report */ + 1, /* max value device can report */ + 1 /* resolution */ +}; + +static const hid_report_item imp_0_rshift = +{ + (uint8_t*)(void *)keybd_report_data + 0, /* data */ + 1, /* size */ + 5, /* shift */ + 0, /* count (only for array items) */ + 0, /* signed */ + 0, /* min value read can return */ + 1, /* max value read can return */ + 0, /* min vale device can report */ + 1, /* max value device can report */ + 1 /* resolution */ +}; + +static const hid_report_item imp_0_ralt = +{ + (uint8_t*)(void *)keybd_report_data + 0, /* data */ + 1, /* size */ + 6, /* shift */ + 0, /* count (only for array items) */ + 0, /* signed */ + 0, /* min value read can return */ + 1, /* max value read can return */ + 0, /* min vale device can report */ + 1, /* max value device can report */ + 1 /* resolution */ +}; + +static const hid_report_item imp_0_rgui = +{ + (uint8_t*)(void *)keybd_report_data + 0, /* data */ + 1, /* size */ + 7, /* shift */ + 0, /* count (only for array items) */ + 0, /* signed */ + 0, /* min value read can return */ + 1, /* max value read can return */ + 0, /* min vale device can report */ + 1, /* max value device can report */ + 1 /* resolution */ +}; + +static const hid_report_item imp_0_key_array = +{ + (uint8_t*)(void *)keybd_report_data + 2, /* data */ + 8, /* size */ + 0, /* shift */ + 6, /* count (only for array items) */ + 0, /* signed */ + 0, /* min value read can return */ + 101, /* max value read can return */ + 0, /* min vale device can report */ + 101, /* max value device can report */ + 1 /* resolution */ +}; + +/* local constants */ +static const uint8_t hid_keybrd_codes[] = +{ + 0, 0, 0, 0, 31, 50, 48, 33, + 19, 34, 35, 36, 24, 37, 38, 39, /* 0x00 - 0x0F */ + 52, 51, 25, 26, 17, 20, 32, 21, + 23, 49, 18, 47, 22, 46, 2, 3, /* 0x10 - 0x1F */ + 4, 5, 6, 7, 8, 9, 10, 11, + 43, 110, 15, 16, 61, 12, 13, 27, /* 0x20 - 0x2F */ + 28, 29, 42, 40, 41, 1, 53, 54, + 55, 30, 112, 113, 114, 115, 116, 117, /* 0x30 - 0x3F */ + 118, 119, 120, 121, 122, 123, 124, 125, + 126, 75, 80, 85, 76, 81, 86, 89, /* 0x40 - 0x4F */ + 79, 84, 83, 90, 95, 100, 105, 106, + 108, 93, 98, 103, 92, 97, 102, 91, /* 0x50 - 0x5F */ + 96, 101, 99, 104, 45, 129, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, /* 0x60 - 0x6F */ + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, /* 0x70 - 0x7F */ + 0, 0, 0, 0, 0, 107, 0, 56, + 0, 0, 0, 0, 0, 0, 0, 0, /* 0x80 - 0x8F */ + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, /* 0x90 - 0x9F */ + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, /* 0xA0 - 0xAF */ + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, /* 0xB0 - 0xBF */ + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, /* 0xC0 - 0xCF */ + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, /* 0xD0 - 0xDF */ + 58, 44, 60, 127, 64, 57, 62, 128 /* 0xE0 - 0xE7 */ +}; + +#ifdef QWERTY_KEYBOARD + +static const int8_t hid_keybrd_key[] = +{ + '\0', '`', '1', '2', '3', '4', '5', '6', + '7', '8', '9', '0', '-', '=', '\0', '\r', + '\t', 'q', 'w', 'e', 'r', 't', 'y', 'u', + 'i', 'o', 'p', '[', ']', '\\', + '\0', 'a', 's', 'd', 'f', 'g', 'h', 'j', + 'k', 'l', ';', '\'', '\0', '\n', + '\0', '\0', 'z', 'x', 'c', 'v', 'b', 'n', + 'm', ',', '.', '/', '\0', '\0', + '\0', '\0', '\0', ' ', '\0', '\0', '\0', '\0', + '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', + '\0', '\0', '\0', '\0', '\0', '\r', '\0', '\0', + '\0', '\0', '\0', '\0', '\0', '\0', + '\0', '\0', '7', '4', '1', + '\0', '/', '8', '5', '2', + '0', '*', '9', '6', '3', + '.', '-', '+', '\0', '\n', '\0', '\0', '\0', '\0', '\0', '\0', + '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', + '\0', '\0', '\0', '\0' +}; + +static const int8_t hid_keybrd_shiftkey[] = { + '\0', '~', '!', '@', '#', '$', '%', '^', '&', '*', '(', ')', + '_', '+', '\0', '\0', '\0', 'Q', 'W', 'E', 'R', 'T', 'Y', 'U', + 'I', 'O', 'P', '{', '}', '|', '\0', 'A', 'S', 'D', 'F', 'G', + 'H', 'J', 'K', 'L', ':', '"', '\0', '\n', '\0', '\0', 'Z', 'X', + 'C', 'V', 'B', 'N', 'M', '<', '>', '?', '\0', '\0', '\0', '\0', + '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', + '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', + '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', + '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', + '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', + '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0' +}; + +#else + +static const int8_t hid_keybrd_key[] = { + '\0', '`', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', + '-', '=', '\0', '\r', '\t', 'a', 'z', 'e', 'r', 't', 'y', 'u', + 'i', 'o', 'p', '[', ']', '\\', '\0', 'q', 's', 'd', 'f', 'g', + 'h', 'j', 'k', 'l', 'm', '\0', '\0', '\n', '\0', '\0', 'w', 'x', + 'c', 'v', 'b', 'n', ',', ';', ':', '!', '\0', '\0', '\0', '\0', + '\0', ' ', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', + '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\r', '\0', '\0', '\0', + '\0', '\0', '\0', '\0', '\0', '\0', '\0', '7', '4', '1', '\0', '/', + '8', '5', '2', '0', '*', '9', '6', '3', '.', '-', '+', '\0', + '\n', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', + '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0' +}; + +static const int8_t hid_keybrd_shiftkey[] = { + '\0', '~', '!', '@', '#', '$', '%', '^', '&', '*', '(', ')', '_', + '+', '\0', '\0', '\0', 'A', 'Z', 'E', 'R', 'T', 'Y', 'U', 'I', 'O', + 'P', '{', '}', '*', '\0', 'Q', 'S', 'D', 'F', 'G', 'H', 'J', 'K', + 'L', 'M', '%', '\0', '\n', '\0', '\0', 'W', 'X', 'C', 'V', 'B', 'N', + '?', '.', '/', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', + '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', + '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', + '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', + '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', + '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0' +}; + +#endif + +/* local function prototypes ('static') */ +static usbh_status usbh_hid_keybrd_decode (usb_core_driver *udev, usbh_host *uhost); + +/*! + \brief initialize the keyboard function + \param[in] udev: pointer to USB core instance + \param[in] uhost: pointer to USB host + \param[out] none + \retval operation status +*/ +usbh_status usbh_hid_keybd_init (usb_core_driver *udev, usbh_host *uhost) +{ + usbh_hid_handler *hid = (usbh_hid_handler *)uhost->active_class->class_data; + + keybd_info.lctrl = keybd_info.lshift = 0U; + keybd_info.lalt = keybd_info.lgui = 0U; + keybd_info.rctrl = keybd_info.rshift = 0U; + keybd_info.ralt = keybd_info.rgui = 0U; + + for (uint32_t x = 0U; x < (sizeof(keybd_report_data) / sizeof(uint32_t)); x++) { + keybd_report_data[x] = 0U; + } + + if (hid->len > (sizeof(keybd_report_data) / sizeof(uint32_t))) { + hid->len = (sizeof(keybd_report_data) / sizeof(uint32_t)); + } + + hid->pdata = (uint8_t*)(void *)keybd_report_data; + + usbh_hid_fifo_init (&hid->fifo, uhost->dev_prop.data, HID_QUEUE_SIZE * sizeof(keybd_report_data)); + + /* call user initialization*/ + usr_keybrd_init(); + + return USBH_OK; +} + +/*! + \brief get keyboard information + \param[in] udev: pointer to USB core instance + \param[in] uhost: pointer to USB host handler + \param[out] none + \retval keyboard information +*/ +hid_keybd_info *usbh_hid_keybd_info_get (usb_core_driver *udev, usbh_host *uhost) +{ + if (USBH_OK == usbh_hid_keybrd_decode(udev, uhost)) { + return &keybd_info; + } else { + return NULL; + } +} + +/*! + \brief get ascii code + \param[in] info: keyboard information + \param[out] none + \retval output +*/ +uint8_t usbh_hid_ascii_code_get (hid_keybd_info *info) +{ + uint8_t output; + if ((1U == info->lshift) || (info->rshift)) { + output = hid_keybrd_shiftkey[hid_keybrd_codes[info->keys[0]]]; + } else { + output = hid_keybrd_key[hid_keybrd_codes[info->keys[0]]]; + } + + return output; +} + +/*! + \brief decode the pressed keys + \param[in] udev: pointer to USB core instance + \param[in] uhost: pointer to USB host + \param[out] none + \retval none +*/ +void usbh_hid_keybrd_machine (usb_core_driver *udev, usbh_host *uhost) +{ + hid_keybd_info *k_pinfo; + + k_pinfo = usbh_hid_keybd_info_get(udev, uhost); + + if (k_pinfo != NULL) { + char c = usbh_hid_ascii_code_get(k_pinfo); + + if (c != 0U) { + usr_keybrd_process_data(c); + } + } +} + +/*! + \brief decode keyboard information + \param[in] udev: pointer to USB core instance + \param[in] uhost: pointer to USB host + \param[out] none + \retval operation status +*/ +static usbh_status usbh_hid_keybrd_decode (usb_core_driver *udev, usbh_host *uhost) +{ + usbh_hid_handler *hid = (usbh_hid_handler *)uhost->active_class->class_data; + + if (hid->len == 0U) { + return USBH_FAIL; + } + + /* fill report */ + if (usbh_hid_fifo_read (&hid->fifo, &keybd_report_data, hid->len) == hid->len) { + keybd_info.lctrl = (uint8_t)hid_item_read((hid_report_item *)&imp_0_lctrl, 0U); + keybd_info.lshift = (uint8_t)hid_item_read((hid_report_item *)&imp_0_lshift, 0U); + keybd_info.lalt = (uint8_t)hid_item_read((hid_report_item *)&imp_0_lalt, 0U); + keybd_info.lgui = (uint8_t)hid_item_read((hid_report_item *)&imp_0_lgui, 0U); + keybd_info.rctrl = (uint8_t)hid_item_read((hid_report_item *)&imp_0_rctrl, 0U); + keybd_info.rshift = (uint8_t)hid_item_read((hid_report_item *)&imp_0_rshift, 0U); + keybd_info.ralt = (uint8_t)hid_item_read((hid_report_item *)&imp_0_ralt, 0U); + keybd_info.rgui = (uint8_t)hid_item_read((hid_report_item *)&imp_0_rgui, 0U); + + for (uint8_t x = 0U; x < sizeof(keybd_info.keys); x++) { + keybd_info.keys[x] = (uint8_t)hid_item_read((hid_report_item *)&imp_0_key_array, x); + } + + return USBH_OK; + } + + return USBH_FAIL; +} diff --git a/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/host/class/hid/Source/usbh_hid_mouse.c b/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/host/class/hid/Source/usbh_hid_mouse.c new file mode 100644 index 0000000000..e92f0ae972 --- /dev/null +++ b/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/host/class/hid/Source/usbh_hid_mouse.c @@ -0,0 +1,216 @@ +/*! + \file usbh_hid_mouse.c + \brief USB host HID mouse driver + + \version 2020-08-01, V3.0.0, firmware for GD32F4xx +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "usbh_hid_mouse.h" +#include "usbh_hid_parser.h" + +hid_mouse_info mouse_info; +uint32_t mouse_report_data[1]; + +/* structures defining how to access items in a hid mouse report */ +/* access button 1 state. */ +static const hid_report_item prop_b1 = +{ + (uint8_t *)(void *)mouse_report_data + 0, /* data */ + 1, /* size */ + 0, /* shift */ + 0, /* count (only for array items) */ + 0, /* signed? */ + 0, /* min value read can return */ + 1, /* max value read can return */ + 0, /* min value device can report */ + 1, /* max value device can report */ + 1 /* resolution */ +}; + +/* access button 2 state. */ +static const hid_report_item prop_b2 = +{ + (uint8_t *)(void *)mouse_report_data + 0, /* data */ + 1, /* size */ + 1, /* shift */ + 0, /* count (only for array items) */ + 0, /* signed? */ + 0, /* min value read can return */ + 1, /* max value read can return */ + 0, /* min value device can report */ + 1, /* max value device can report */ + 1 /* resolution */ +}; + +/* access button 3 state. */ +static const hid_report_item prop_b3 = +{ + (uint8_t *)(void *)mouse_report_data + 0, /* data */ + 1, /* size */ + 2, /* shift */ + 0, /* count (only for array items) */ + 0, /* signed? */ + 0, /* min value read can return */ + 1, /* max value read can return */ + 0, /* min vale device can report */ + 1, /* max value device can report */ + 1 /* resolution */ +}; + +/* access x coordinate change. */ +static const hid_report_item prop_x = +{ + (uint8_t *)(void *)mouse_report_data + 1, /* data */ + 8, /* size */ + 0, /* shift */ + 0, /* count (only for array items) */ + 1, /* signed? */ + 0, /* min value read can return */ + 0xFFFF,/* max value read can return */ + 0, /* min vale device can report */ + 0xFFFF,/* max value device can report */ + 1 /* resolution */ +}; + +/* access y coordinate change. */ +static const hid_report_item prop_y = +{ + (uint8_t *)(void *)mouse_report_data + 2, /* data */ + 8, /* size */ + 0, /* shift */ + 0, /* count (only for array items) */ + 1, /* signed? */ + 0, /* min value read can return */ + 0xFFFF,/* max value read can return */ + 0, /* min vale device can report */ + 0xFFFF,/* max value device can report */ + 1 /* resolution */ +}; + +/* local function prototypes ('static') */ +static usbh_status usbh_hid_mouse_decode(usb_core_driver *udev, usbh_host *uhost); + +/*! + \brief initialize the mouse function + \param[in] udev: pointer to USB core instance + \param[in] uhost: pointer to USB host + \param[out] none + \retval none +*/ +usbh_status usbh_hid_mouse_init (usb_core_driver *udev, usbh_host *uhost) +{ + usbh_hid_handler *hid = (usbh_hid_handler *)uhost->active_class->class_data; + + mouse_info.x = 0U; + mouse_info.y = 0U; + mouse_info.buttons[0] = 0U; + mouse_info.buttons[1] = 0U; + mouse_info.buttons[2] = 0U; + + mouse_report_data[0] = 0U; + + if(hid->len > sizeof(mouse_report_data)) { + hid->len = sizeof(mouse_report_data); + } + + hid->pdata = (uint8_t *)(void *)mouse_report_data; + + usbh_hid_fifo_init(&hid->fifo, uhost->dev_prop.data, HID_QUEUE_SIZE * sizeof(mouse_report_data)); + + usr_mouse_init(); + + return USBH_OK; +} + +/*! + \brief get mouse information + \param[in] udev: pointer to USB core instance + \param[in] uhost: pointer to USB host + \param[out] none + \retval mouse information +*/ +hid_mouse_info *usbh_hid_mouse_info_get (usb_core_driver *udev, usbh_host *uhost) +{ + if(usbh_hid_mouse_decode(udev, uhost)== USBH_OK) { + return &mouse_info; + } else { + return NULL; + } +} + +/*! + \brief decode mouse data + \param[in] udev: pointer to USB core instance + \param[in] uhost: pointer to USB host + \param[out] none + \retval none +*/ +void usbh_hid_mouse_machine (usb_core_driver *udev, usbh_host *uhost) +{ + hid_mouse_info *m_pinfo = NULL; + + m_pinfo = usbh_hid_mouse_info_get(udev, uhost); + + if (NULL != m_pinfo) { + /* handle mouse data position */ + usr_mouse_process_data(&mouse_info); + } +} + +/*! + \brief decode mouse information + \param[in] udev: pointer to USB core instance + \param[in] uhost: pointer to USB host + \param[out] none + \retval operation status +*/ +static usbh_status usbh_hid_mouse_decode(usb_core_driver *udev, usbh_host *uhost) +{ + usbh_hid_handler *hid = (usbh_hid_handler *)uhost->active_class->class_data; + + if (0U == hid->len) { + return USBH_FAIL; + } + + /* fill report */ + if (usbh_hid_fifo_read(&hid->fifo, &mouse_report_data, hid->len) == hid->len) { + /* decode report */ + mouse_info.x = (uint8_t)hid_item_read((hid_report_item *)&prop_x, 0U); + mouse_info.y = (uint8_t)hid_item_read((hid_report_item *)&prop_y, 0U); + + mouse_info.buttons[0] = (uint8_t)hid_item_read((hid_report_item *)&prop_b1, 0U); + mouse_info.buttons[1] = (uint8_t)hid_item_read((hid_report_item *)&prop_b2, 0U); + mouse_info.buttons[2] = (uint8_t)hid_item_read((hid_report_item *)&prop_b3, 0U); + + return USBH_OK; + } + + return USBH_FAIL; +} diff --git a/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/host/class/hid/Source/usbh_hid_parser.c b/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/host/class/hid/Source/usbh_hid_parser.c new file mode 100644 index 0000000000..96218c6cca --- /dev/null +++ b/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/host/class/hid/Source/usbh_hid_parser.c @@ -0,0 +1,148 @@ +/*! + \file usbh_hid_parser.c + \brief USB host HID parser driver + + \version 2020-08-01, V3.0.0, firmware for GD32F4xx +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "usbh_hid_parser.h" + +/*! + \brief read a hid report item + \param[in] ri: pointer to report item + \param[in] ndx: report index + \param[out] none + \retval operation status (0: fail otherwise: item value) +*/ +uint32_t hid_item_read (hid_report_item *ri, uint8_t ndx) +{ + uint32_t val = 0U; + uint32_t bofs = 0U; + uint8_t *data = ri->data; + uint8_t shift = ri->shift; + + /* get the logical value of the item */ + + /* if this is an array, wee may need to offset ri->data.*/ + if (ri->count > 0U) { + /* if app tries to read outside of the array. */ + if (ri->count <= ndx) { + return(0U); + } + + /* calculate bit offset */ + bofs = ndx * ri->size; + bofs += shift; + + /* calculate byte offset + shift pair from bit offset. */ + data += bofs / 8U; + shift = (uint8_t)(bofs % 8U); + } + + /* read data bytes in little endian order */ + for (uint32_t x = 0U; x < ((ri->size & 0x7U) ? (ri->size / 8U) + 1U : (ri->size / 8U)); x++) { + val=(uint32_t)((uint32_t)(*data) << (x * 8U)); + } + + val=(val >> shift) & ((1U << ri->size) - 1U); + + if ((val < ri->logical_min) || (val > ri->logical_max)) { + return(0U); + } + + /* convert logical value to physical value */ + /* see if the number is negative or not. */ + if ((ri->sign) && (val & (1U << (ri->size - 1U)))) { + /* yes, so sign extend value to 32 bits. */ + uint32_t vs = (uint32_t)((0xffffffffU & ~((1U << (ri->size)) - 1U)) | val); + + if (1U == ri->resolution) { + return((uint32_t)vs); + } + return((uint32_t)(vs * ri->resolution)); + } else { + if (1U == ri->resolution) { + return(val); + } + + return (val * ri->resolution); + } +} + +/*! + \brief write a hid report item + \param[in] ri: pointer to report item + \param[in] value: the value to be write + \param[in] ndx: report index + \param[out] none + \retval operation status (1: fail 0: OK) +*/ +uint32_t hid_item_write(hid_report_item *ri, uint32_t value, uint8_t ndx) +{ + uint32_t mask; + uint32_t bofs; + uint8_t *data = ri->data; + uint8_t shift = ri->shift; + + if ((value < ri->physical_min) || (value > ri->physical_max)) { + return(1U); + } + + /* if this is an array, wee may need to offset ri->data.*/ + if (ri->count > 0U) { + /* if app tries to read outside of the array. */ + if (ri->count >= ndx) { + return(0U); + } + + /* calculate bit offset */ + bofs = ndx * ri->size; + bofs += shift; + + /* calculate byte offset + shift pair from bit offset. */ + data += bofs / 8U; + shift = (uint8_t)(bofs % 8U); + } + + /* convert physical value to logical value. */ + if (1U != ri->resolution) { + value = value / ri->resolution; + } + + /* write logical value to report in little endian order. */ + mask = (1U << ri->size) - 1U; + value = (value & mask) << shift; + + for (uint32_t x = 0U; x < ((ri->size & 0x7U) ? (ri->size / 8U) + 1U : (ri->size / 8U)); x++) { + *(ri->data + x) = (uint8_t)((*(ri->data+x) & ~(mask>>(x* 8U))) | ((value >> (x * 8U)) & (mask >> (x * 8U)))); + } + + return 0U; +} diff --git a/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/host/class/msc/Include/usbh_msc_bbb.h b/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/host/class/msc/Include/usbh_msc_bbb.h new file mode 100644 index 0000000000..da71b743ae --- /dev/null +++ b/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/host/class/msc/Include/usbh_msc_bbb.h @@ -0,0 +1,150 @@ +/*! + \file usbh_msc_bbb.h + \brief header file for usbh_msc_bbb.c + + \version 2020-08-01, V3.0.0, firmware for GD32F4xx +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef __USBH_MSC_BBB_H +#define __USBH_MSC_BBB_H + +#include "usbh_enum.h" +#include "msc_bbb.h" + +typedef union { + msc_bbb_cbw field; + + uint8_t CBWArray[31]; +}usbh_cbw_pkt; + +typedef union { + msc_bbb_csw field; + + uint8_t CSWArray[13]; +}usbh_csw_pkt; + +enum usbh_msc_state { + USBH_MSC_BOT_INIT_STATE = 0U, + USBH_MSC_BOT_RESET, + USBH_MSC_GET_MAX_LUN, + USBH_MSC_TEST_UNIT_READY, + USBH_MSC_READ_CAPACITY10, + USBH_MSC_MODE_SENSE6, + USBH_MSC_REQUEST_SENSE, + USBH_MSC_BOT_USB_TRANSFERS, + USBH_MSC_DEFAULT_APPLI_STATE, + USBH_MSC_CTRL_ERROR_STATE, + USBH_MSC_UNRECOVERED_STATE +}; + +typedef enum +{ + BOT_OK = 0U, + BOT_FAIL, + BOT_PHASE_ERROR, + BOT_BUSY +} bot_status; + +typedef enum +{ + BOT_CMD_IDLE = 0U, + BOT_CMD_SEND, + BOT_CMD_WAIT, +} bot_cmd_state; + +/* csw status definitions */ +typedef enum +{ + BOT_CSW_CMD_PASSED = 0U, + BOT_CSW_CMD_FAILED, + BOT_CSW_PHASE_ERROR, +} bot_csw_status; + +typedef enum +{ + BOT_SEND_CBW = 1U, + BOT_SEND_CBW_WAIT, + BOT_DATA_IN, + BOT_DATA_IN_WAIT, + BOT_DATA_OUT, + BOT_DATA_OUT_WAIT, + BOT_RECEIVE_CSW, + BOT_RECEIVE_CSW_WAIT, + BOT_ERROR_IN, + BOT_ERROR_OUT, + BOT_UNRECOVERED_ERROR +} bot_state; + +typedef struct +{ + uint8_t *pbuf; + uint32_t data[16]; + bot_state state; + bot_state prev_state; + bot_cmd_state cmd_state; + usbh_cbw_pkt cbw; + usbh_csw_pkt csw; +} bot_handle; + +#define USBH_MSC_BOT_CBW_TAG 0x20304050U + +#define USBH_MSC_CSW_MAX_LENGTH 63U + +#define USBH_MSC_SEND_CSW_DISABLE 0U +#define USBH_MSC_SEND_CSW_ENABLE 1U + +#define USBH_MSC_DIR_IN 0U +#define USBH_MSC_DIR_OUT 1U +#define USBH_MSC_BOTH_DIR 2U + +#define USBH_MSC_PAGE_LENGTH 512U + +#define CBW_CB_LENGTH 16U +#define CBW_LENGTH 10U +#define CBW_LENGTH_TEST_UNIT_READY 0U + +#define MAX_BULK_STALL_COUNT_LIMIT 0x04U /*!< If STALL is seen on Bulk + Endpoint continously, this means + that device and Host has phase error + Hence a Reset is needed */ + +/* function declarations */ +/* initialize the mass storage parameters */ +void usbh_msc_bot_init (usbh_host *uhost); +/* manage the different states of BOT transfer and updates the status to upper layer */ +usbh_status usbh_msc_bot_process (usbh_host *uhost, uint8_t lun); +/* manages the different error handling for stall */ +usbh_status usbh_msc_bot_abort (usbh_host *uhost, uint8_t direction); +/* reset MSC bot request structure */ +usbh_status usbh_msc_bot_reset (usbh_host *uhost); +/* decode the CSW received by the device and updates the same to upper layer */ +bot_csw_status usbh_msc_csw_decode (usbh_host *uhost); + +#endif /* __USBH_MSC_BBB_H */ diff --git a/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/host/class/msc/Include/usbh_msc_core.h b/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/host/class/msc/Include/usbh_msc_core.h new file mode 100644 index 0000000000..6f32ddcf86 --- /dev/null +++ b/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/host/class/msc/Include/usbh_msc_core.h @@ -0,0 +1,124 @@ +/*! + \file usbh_core.h + \brief header file for the usbh_core.c + + \version 2020-08-01, V3.0.0, firmware for GD32F4xx +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef __USBH_MSC_CORE_H +#define __USBH_MSC_CORE_H + +#include "usb_msc.h" +#include "usbh_msc_scsi.h" +#include "usbh_msc_bbb.h" + +#define MSC_MAX_SUPPORTED_LUN 2U + +typedef enum +{ + MSC_INIT = 0U, + MSC_IDLE, + MSC_TEST_UNIT_READY, + MSC_READ_CAPACITY10, + MSC_READ_INQUIRY, + MSC_REQUEST_SENSE, + MSC_READ, + MSC_WRITE, + MSC_UNRECOVERED_ERROR, + MSC_PERIODIC_CHECK, +} msc_state; + +typedef enum +{ + MSC_OK, + MSC_NOT_READY, + MSC_ERROR, +} msc_error; + +typedef enum +{ + MSC_REQ_IDLE = 0U, + MSC_REQ_RESET, + MSC_REQ_GET_MAX_LUN, + MSC_REQ_ERROR, +} msc_req_state; + +/* Structure for LUN */ +typedef struct +{ + msc_state state; + msc_error error; + msc_scsi_sense sense; + scsi_capacity capacity; + scsi_std_inquiry_data inquiry; + usbh_status prev_ready_state; + uint8_t state_changed; +} msc_lun; + +/* structure for MSC process */ +typedef struct _msc_process +{ + uint8_t pipe_in; + uint8_t pipe_out; + uint8_t ep_in; + uint8_t ep_out; + uint16_t ep_size_in; + uint16_t ep_size_out; + uint8_t cur_lun; + uint16_t rw_lun; + uint32_t max_lun; + msc_state state; + msc_error error; + msc_req_state req_state; + msc_req_state prev_req_state; + bot_handle bot; + msc_lun unit[MSC_MAX_SUPPORTED_LUN]; + uint32_t timer; +} usbh_msc_handler; + +extern usbh_class usbh_msc; + +/* function declarations */ +/* get msc logic unit information */ +usbh_status usbh_msc_lun_info_get (usbh_host *uhost, uint8_t lun, msc_lun *info); +/* msc read interface */ +usbh_status usbh_msc_read (usbh_host *uhost, + uint8_t lun, + uint32_t address, + uint8_t *pbuf, + uint32_t length); +/* msc write interface */ +usbh_status usbh_msc_write (usbh_host *uhost, + uint8_t lun, + uint32_t address, + uint8_t *pbuf, + uint32_t length); + +#endif /* __USBH_MSC_CORE_H */ diff --git a/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/host/class/msc/Include/usbh_msc_scsi.h b/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/host/class/msc/Include/usbh_msc_scsi.h new file mode 100644 index 0000000000..85cd3c65a1 --- /dev/null +++ b/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/host/class/msc/Include/usbh_msc_scsi.h @@ -0,0 +1,100 @@ +/*! + \file usbh_msc_scsi.h + \brief header file for usbh_msc_scsi.c + + \version 2020-08-01, V3.0.0, firmware for GD32F4xx +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef __USBH_MSC_SCSI_H +#define __USBH_MSC_SCSI_H + +#include "msc_scsi.h" +#include "usbh_enum.h" + +/* capacity data */ +typedef struct +{ + uint32_t block_nbr; + uint16_t block_size; +} scsi_capacity; + +/* inquiry data */ +typedef struct +{ + uint8_t peripheral_qualifier; + uint8_t device_type; + uint8_t removable_media; + uint8_t vendor_id[9]; + uint8_t product_id[17]; + uint8_t revision_id[5]; +} scsi_std_inquiry_data; + +typedef struct +{ + uint32_t msc_capacity; + uint32_t msc_sense_key; + uint16_t msc_page_len; + uint8_t msc_write_protect; +}usbh_msc_parameter; + +#define DESC_REQUEST_SENSE 0x00U +#define ALLOCATION_LENGTH_REQUEST_SENSE 63U +#define XFER_LEN_MODE_SENSE6 63U + +#define MASK_MODE_SENSE_WRITE_PROTECT 0x80U +#define MODE_SENSE_PAGE_CONTROL_FIELD 0x00U +#define MODE_SENSE_PAGE_CODE 0x3FU +#define DISK_WRITE_PROTECTED 0x01U + +/* function declarations */ +/* send 'Inquiry' command to the device */ +usbh_status usbh_msc_scsi_inquiry (usbh_host *uhost, uint8_t lun, scsi_std_inquiry_data *inquiry); +/* send 'Test unit ready' command to the device */ +usbh_status usbh_msc_test_unitready (usbh_host *uhost, uint8_t lun); +/* send the read capacity command to the device */ +usbh_status usbh_msc_read_capacity10 (usbh_host *uhost, uint8_t lun, scsi_capacity *capacity); +/* send the mode sense6 command to the device */ +usbh_status usbh_msc_mode_sense6 (usbh_host *uhost, uint8_t lun); +/* send the Request Sense command to the device */ +usbh_status usbh_msc_request_sense (usbh_host *uhost, uint8_t lun, msc_scsi_sense *sense_data); +/* send the write10 command to the device */ +usbh_status usbh_msc_write10 (usbh_host *uhost, + uint8_t lun, + uint8_t *data_buf, + uint32_t addr, + uint32_t byte_num); +/* send the read10 command to the device */ +usbh_status usbh_msc_read10 (usbh_host *uhost, + uint8_t lun, + uint8_t *data_buf, + uint32_t addr, + uint32_t byte_num); + +#endif /* __USBH_MSC_SCSI_H */ diff --git a/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/host/class/msc/Source/usbh_msc_bbb.c b/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/host/class/msc/Source/usbh_msc_bbb.c new file mode 100644 index 0000000000..b5129d8e74 --- /dev/null +++ b/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/host/class/msc/Source/usbh_msc_bbb.c @@ -0,0 +1,362 @@ +/*! + \file usbh_msc_bbb.c + \brief USB MSC BBB protocol related functions + + \version 2020-08-01, V3.0.0, firmware for GD32F4xx +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "usbh_pipe.h" +#include "usbh_msc_core.h" +#include "usbh_msc_scsi.h" +#include "usbh_msc_bbb.h" +#include "usbh_transc.h" +#include "drv_usbh_int.h" + +/*! + \brief initialize the mass storage parameters + \param[in] uhost: pointer to USB host handler + \param[out] none + \retval none +*/ +void usbh_msc_bot_init (usbh_host *uhost) +{ + usbh_msc_handler *msc = (usbh_msc_handler *)uhost->active_class->class_data; + + msc->bot.cbw.field.dCBWSignature = BBB_CBW_SIGNATURE; + msc->bot.cbw.field.dCBWTag = USBH_MSC_BOT_CBW_TAG; + msc->bot.state = BOT_SEND_CBW; + msc->bot.cmd_state = BOT_CMD_SEND; +} + +/*! + \brief manage the different states of BOT transfer and updates the status to upper layer + \param[in] uhost: pointer to usb host handler + \param[in] lun: logic unit number + \param[out] none + \retval operation status +*/ +usbh_status usbh_msc_bot_process (usbh_host *uhost, uint8_t lun) +{ + bot_csw_status csw_status = BOT_CSW_CMD_FAILED; + usbh_status status = USBH_BUSY; + usbh_status error = USBH_BUSY; + usb_urb_state urb_status = URB_IDLE; + usbh_msc_handler *msc = (usbh_msc_handler *)uhost->active_class->class_data; + + switch (msc->bot.state) { + case BOT_SEND_CBW: + msc->bot.cbw.field.bCBWLUN = lun; + msc->bot.state = BOT_SEND_CBW_WAIT; + /* send CBW */ + usbh_data_send (uhost->data, + msc->bot.cbw.CBWArray, + msc->pipe_out, + BBB_CBW_LENGTH); + break; + + case BOT_SEND_CBW_WAIT: + urb_status = usbh_urbstate_get(uhost->data, msc->pipe_out); + + if (URB_DONE == urb_status) { + if (0U != msc->bot.cbw.field.dCBWDataTransferLength) { + if (USB_TRX_IN == (msc->bot.cbw.field.bmCBWFlags & USB_TRX_MASK)) { + msc->bot.state = BOT_DATA_IN; + } else { + msc->bot.state = BOT_DATA_OUT; + } + } else { + msc->bot.state = BOT_RECEIVE_CSW; + } + + } else if (URB_NOTREADY == urb_status) { + msc->bot.state = BOT_SEND_CBW; + } else { + if (URB_STALL == urb_status) { + msc->bot.state = BOT_ERROR_OUT; + } + } + break; + + case BOT_DATA_IN: + usbh_data_recev (uhost->data, + msc->bot.pbuf, + msc->pipe_in, + msc->ep_size_in); + + msc->bot.state = BOT_DATA_IN_WAIT; + break; + + case BOT_DATA_IN_WAIT: + urb_status = usbh_urbstate_get(uhost->data, msc->pipe_in); + + /* BOT DATA IN stage */ + if (URB_DONE == urb_status) { + if (msc->bot.cbw.field.dCBWDataTransferLength > msc->ep_size_in) { + msc->bot.pbuf += msc->ep_size_in; + msc->bot.cbw.field.dCBWDataTransferLength -= msc->ep_size_in; + } else { + msc->bot.cbw.field.dCBWDataTransferLength = 0U; + } + + if (msc->bot.cbw.field.dCBWDataTransferLength > 0U) { + usbh_data_recev (uhost->data, + msc->bot.pbuf, + msc->pipe_in, + msc->ep_size_in); + } else { + msc->bot.state = BOT_RECEIVE_CSW; + } + } else if(URB_STALL == urb_status) { + /* this is data stage stall condition */ + msc->bot.state = BOT_ERROR_IN; + } else { + /* no operation */ + } + break; + + case BOT_DATA_OUT: + usbh_data_send (uhost->data, + msc->bot.pbuf, + msc->pipe_out, + msc->ep_size_out); + + msc->bot.state = BOT_DATA_OUT_WAIT; + break; + + case BOT_DATA_OUT_WAIT: + /* BOT DATA OUT stage */ + urb_status = usbh_urbstate_get(uhost->data, msc->pipe_out); + if (URB_DONE == urb_status) { + if (msc->bot.cbw.field.dCBWDataTransferLength > msc->ep_size_out) { + msc->bot.pbuf += msc->ep_size_out; + msc->bot.cbw.field.dCBWDataTransferLength -= msc->ep_size_out; + } else { + msc->bot.cbw.field.dCBWDataTransferLength = 0; /* reset this value and keep in same state */ + } + + if (msc->bot.cbw.field.dCBWDataTransferLength > 0) { + usbh_data_send (uhost->data, + msc->bot.pbuf, + msc->pipe_out, + msc->ep_size_out); + } else { + msc->bot.state = BOT_RECEIVE_CSW; + } + } else if (URB_NOTREADY == urb_status) { + msc->bot.state = BOT_DATA_OUT; + } else if (URB_STALL == urb_status) { + msc->bot.state = BOT_ERROR_OUT; + } else { + /* no operation */ + } + break; + + case BOT_RECEIVE_CSW: + /* BOT CSW stage */ + usbh_data_recev (uhost->data, + msc->bot.csw.CSWArray, + msc->pipe_in, + BBB_CSW_LENGTH); + + msc->bot.state = BOT_RECEIVE_CSW_WAIT; + break; + + case BOT_RECEIVE_CSW_WAIT: + urb_status = usbh_urbstate_get(uhost->data, msc->pipe_in); + + /* decode CSW */ + if (URB_DONE == urb_status) { + msc->bot.state = BOT_SEND_CBW; + msc->bot.cmd_state = BOT_CMD_SEND; + + csw_status = usbh_msc_csw_decode(uhost); + if (BOT_CSW_CMD_PASSED == csw_status) { + status = USBH_OK; + } else { + status = USBH_FAIL; + } + } else if (URB_STALL == urb_status) { + msc->bot.state = BOT_ERROR_IN; + } else { + /* no operation */ + } + break; + + case BOT_ERROR_IN: + error = usbh_msc_bot_abort(uhost, USBH_MSC_DIR_IN); + + if (USBH_OK == error) { + msc->bot.state = BOT_RECEIVE_CSW; + } else if (USBH_UNRECOVERED_ERROR == status) { + /* this means that there is a stall error limit, do reset recovery */ + msc->bot.state = BOT_UNRECOVERED_ERROR; + } else { + /* no operation */ + } + break; + + case BOT_ERROR_OUT: + status = usbh_msc_bot_abort (uhost, USBH_MSC_DIR_OUT); + + if (USBH_OK == status) { + uint8_t toggle = usbh_pipe_toggle_get(uhost->data, msc->pipe_out); + usbh_pipe_toggle_set(uhost->data, msc->pipe_out, 1U - toggle); + usbh_pipe_toggle_set(uhost->data, msc->pipe_in, 0U); + msc->bot.state = BOT_ERROR_IN; + } else { + if (USBH_UNRECOVERED_ERROR == status) { + msc->bot.state = BOT_UNRECOVERED_ERROR; + } + } + break; + + case BOT_UNRECOVERED_ERROR: + status = usbh_msc_bot_reset(uhost); + if (USBH_OK == status) { + msc->bot.state = BOT_SEND_CBW; + } + break; + + default: + break; + } + + return status; +} + +/*! + \brief manages the different error handling for stall + \param[in] uhost: pointer to USB host handler + \param[in] direction: data IN or OUT + \param[out] none + \retval operation status +*/ +usbh_status usbh_msc_bot_abort (usbh_host *uhost, uint8_t direction) +{ + usbh_status status = USBH_BUSY; + usbh_msc_handler *msc = (usbh_msc_handler *)uhost->active_class->class_data; + + switch (direction) { + case USBH_MSC_DIR_IN : + /* send clear feature command on bulk IN endpoint */ + status = usbh_clrfeature(uhost, + msc->ep_in, + msc->pipe_in); + break; + + case USBH_MSC_DIR_OUT : + /*send clear feature command on bulk OUT endpoint */ + status = usbh_clrfeature(uhost, + msc->ep_out, + msc->pipe_out); + break; + + default: + break; + } + + return status; +} + +/*! + \brief reset MSC bot transfer + \param[in] uhost: pointer to USB host handler + \param[out] none + \retval operation status +*/ +usbh_status usbh_msc_bot_reset (usbh_host *uhost) +{ + usbh_status status = USBH_BUSY; + + if (CTL_IDLE == uhost->control.ctl_state) { + uhost->control.setup.req = (usb_req) { + .bmRequestType = USB_TRX_OUT | USB_REQTYPE_CLASS | USB_RECPTYPE_ITF, + .bRequest = BBB_RESET, + .wValue = 0U, + .wIndex = 0U, + .wLength = 0U + }; + + usbh_ctlstate_config (uhost, NULL, 0U); + } + + status = usbh_ctl_handler (uhost); + + return status; +} + +/*! + \brief decode the CSW received by the device and updates the same to upper layer + \param[in] uhost: pointer to USB host + \param[out] none + \retval on success USBH_MSC_OK, on failure USBH_MSC_FAIL + \notes + Refer to USB Mass-Storage Class: BOT (www.usb.org) + 6.3.1 Valid CSW Conditions : + The host shall consider the CSW valid when: + 1. dCSWSignature is equal to 53425355h + 2. the CSW is 13 (Dh) bytes in length, + 3. dCSWTag matches the dCBWTag from the corresponding CBW. +*/ +bot_csw_status usbh_msc_csw_decode (usbh_host *uhost) +{ + bot_csw_status status = BOT_CSW_CMD_FAILED; + usbh_msc_handler *msc = (usbh_msc_handler *)uhost->active_class->class_data; + + /* checking if the transfer length is different than 13 */ + if (BBB_CSW_LENGTH != usbh_xfercount_get (uhost->data, msc->pipe_in)) { + status = BOT_CSW_PHASE_ERROR; + } else { + /* CSW length is correct */ + + /* check validity of the CSW Signature and CSWStatus */ + if (BBB_CSW_SIGNATURE == msc->bot.csw.field.dCSWSignature) { + /* check condition 1. dCSWSignature is equal to 53425355h */ + if (msc->bot.csw.field.dCSWTag == msc->bot.cbw.field.dCBWTag) { + /* check condition 3. dCSWTag matches the dCBWTag from the corresponding CBW */ + if (0U == msc->bot.csw.field.bCSWStatus) { + status = BOT_CSW_CMD_PASSED; + } else if (1U == msc->bot.csw.field.bCSWStatus) { + status = BOT_CSW_CMD_FAILED; + } else if (2U == msc->bot.csw.field.bCSWStatus) { + status = BOT_CSW_PHASE_ERROR; + } else { + /* no operation */ + } + } + } else { + /* If the CSW signature is not valid, we shall return the phase error to + upper layers for reset recovery */ + status = BOT_CSW_PHASE_ERROR; + } + } + + return status; +} diff --git a/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/host/class/msc/Source/usbh_msc_core.c b/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/host/class/msc/Source/usbh_msc_core.c new file mode 100644 index 0000000000..afb992b017 --- /dev/null +++ b/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/host/class/msc/Source/usbh_msc_core.c @@ -0,0 +1,556 @@ +/*! + \file usbh_core.c + \brief USB MSC(mass storage device) class driver + + \version 2020-08-01, V3.0.0, firmware for GD32F4xx +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "usbh_msc_core.h" +#include "usbh_msc_scsi.h" +#include "usbh_msc_bbb.h" +#include "usbh_pipe.h" +#include "usbh_transc.h" +#include +#include + +/* local function prototypes ('static') */ +static void usbh_msc_itf_deinit (usbh_host *uhost); +static usbh_status usbh_msc_itf_init (usbh_host *uhost); +static usbh_status usbh_msc_req (usbh_host *uhost); +static usbh_status usbh_msc_handle (usbh_host *uhost); +static usbh_status usbh_msc_maxlun_get (usbh_host *uhost, uint8_t *maxlun); +static usbh_status usbh_msc_rdwr_process(usbh_host *uhost, uint8_t lun); + +usbh_class usbh_msc = +{ + USB_CLASS_MSC, + usbh_msc_itf_init, + usbh_msc_itf_deinit, + usbh_msc_req, + usbh_msc_handle, +}; + +/*! + \brief interface initialization for MSC class + \param[in] uhost: pointer to usb host + \param[out] none + \retval operation status +*/ +static usbh_status usbh_msc_itf_init (usbh_host *uhost) +{ + usbh_status status = USBH_OK; + + uint8_t interface = usbh_interface_find(&uhost->dev_prop, MSC_CLASS, USB_MSC_SUBCLASS_SCSI, MSC_PROTOCOL); + + if (0xFFU == interface) { + uhost->usr_cb->dev_not_supported(); + + status = USBH_FAIL; + } else { + uhost->active_class->class_data = (usbh_msc_handler *)malloc(sizeof(usbh_msc_handler)); + + usbh_msc_handler *msc = (usbh_msc_handler *)uhost->active_class->class_data; + + memset(msc, 0U, sizeof(usbh_msc_handler)); + + usbh_interface_select(&uhost->dev_prop, interface); + + usb_desc_ep *ep_desc = &uhost->dev_prop.cfg_desc_set.itf_desc_set[interface][0].ep_desc[0]; + + if (ep_desc->bEndpointAddress & 0x80) { + msc->ep_in = ep_desc->bEndpointAddress; + msc->ep_size_in = ep_desc->wMaxPacketSize; + } else { + msc->ep_out = ep_desc->bEndpointAddress; + msc->ep_size_out = ep_desc->wMaxPacketSize; + } + + ep_desc = &uhost->dev_prop.cfg_desc_set.itf_desc_set[interface][0].ep_desc[1]; + + if (ep_desc->bEndpointAddress & 0x80) { + msc->ep_in = ep_desc->bEndpointAddress; + msc->ep_size_in = ep_desc->wMaxPacketSize; + } else { + msc->ep_out = ep_desc->bEndpointAddress; + msc->ep_size_out = ep_desc->wMaxPacketSize; + } + + msc->state = MSC_INIT; + msc->error = MSC_OK; + msc->req_state = MSC_REQ_IDLE; + msc->pipe_out = usbh_pipe_allocate(uhost->data, msc->ep_out); + msc->pipe_in = usbh_pipe_allocate(uhost->data, msc->ep_in); + + usbh_msc_bot_init(uhost); + + /* open the new channels */ + usbh_pipe_create (uhost->data, + &uhost->dev_prop, + msc->pipe_out, + USB_EPTYPE_BULK, + msc->ep_size_out); + + usbh_pipe_create (uhost->data, + &uhost->dev_prop, + msc->pipe_in, + USB_EPTYPE_BULK, + msc->ep_size_in); + + usbh_pipe_toggle_set (uhost->data, msc->pipe_out, 0U); + usbh_pipe_toggle_set (uhost->data, msc->pipe_in, 0U); + } + + return status; +} + +/*! + \brief de-initialize interface by freeing host channels allocated to interface + \param[in] uhost: pointer to usb host + \param[out] none + \retval operation status +*/ +void usbh_msc_itf_deinit (usbh_host *uhost) +{ + usbh_msc_handler *msc = (usbh_msc_handler *)uhost->active_class->class_data; + + if (msc->pipe_out) { + usb_pipe_halt (uhost->data, msc->pipe_out); + usbh_pipe_free (uhost->data, msc->pipe_out); + + msc->pipe_out = 0U; + } + + if (msc->pipe_in) { + usb_pipe_halt (uhost->data, msc->pipe_in); + usbh_pipe_free (uhost->data, msc->pipe_in); + + msc->pipe_in = 0U; + } +} + +/*! + \brief initialize the MSC state machine + \param[in] uhost: pointer to usb host + \param[out] none + \retval operation status +*/ +static usbh_status usbh_msc_req (usbh_host *uhost) +{ + usbh_status status = USBH_BUSY; + usbh_msc_handler *msc = (usbh_msc_handler *)uhost->active_class->class_data; + + switch (msc->req_state) { + case MSC_REQ_IDLE: + case MSC_REQ_GET_MAX_LUN: + /* issue Get_MaxLun request */ + status = usbh_msc_maxlun_get (uhost, (uint8_t *)&msc->max_lun); + + if (USBH_OK == status) { + msc->max_lun = ((uint8_t)msc->max_lun > MSC_MAX_SUPPORTED_LUN) ? MSC_MAX_SUPPORTED_LUN : (uint8_t)msc->max_lun + 1U; + + for (uint8_t i = 0U; i < msc->max_lun; i++) { + msc->unit[i].prev_ready_state = USBH_FAIL; + msc->unit[i].state_changed = 0U; + } + } else { + if (USBH_NOT_SUPPORTED == status) { + msc->max_lun = 0U; + status = USBH_OK; + } + } + break; + + case MSC_REQ_ERROR: + /* issue clear feature request */ + if (USBH_OK == usbh_clrfeature(uhost, 0x00U, uhost->control.pipe_out_num)) { + msc->req_state = msc->prev_req_state; + } + break; + + default: + break; + } + + return status; +} + +/*! + \brief MSC state machine handler + \param[in] uhost: pointer to usb host + \param[out] none + \retval operation status +*/ +static usbh_status usbh_msc_handle (usbh_host *uhost) +{ + usbh_status status = USBH_BUSY; + uint8_t scsi_status = USBH_BUSY; + uint8_t ready_status = USBH_BUSY; + usbh_msc_handler *msc = (usbh_msc_handler *)uhost->active_class->class_data; + + + switch (msc->state) { + case MSC_INIT: + if (msc->cur_lun < msc->max_lun) { + msc->unit[msc->cur_lun].error = MSC_NOT_READY; + + switch (msc->unit[msc->cur_lun].state) { + case MSC_INIT: + msc->unit[msc->cur_lun].state = MSC_READ_INQUIRY; + msc->timer = uhost->control.timer; + break; + + case MSC_READ_INQUIRY: + scsi_status = usbh_msc_scsi_inquiry(uhost, msc->cur_lun, &msc->unit[msc->cur_lun].inquiry); + + if (USBH_OK == scsi_status) { + msc->unit[msc->cur_lun].state = MSC_TEST_UNIT_READY; + } else if (scsi_status == USBH_FAIL) { + msc->unit[msc->cur_lun].state = MSC_REQUEST_SENSE; + } else { + if (scsi_status == USBH_UNRECOVERED_ERROR) { + msc->unit[msc->cur_lun].state = MSC_IDLE; + msc->unit[msc->cur_lun].error = MSC_ERROR; + } + } + break; + + case MSC_TEST_UNIT_READY: + /* issue SCSI command TestUnitReady */ + ready_status = usbh_msc_test_unitready(uhost, msc->cur_lun); + + if (USBH_OK == ready_status) { + if (USBH_OK != msc->unit[msc->cur_lun].prev_ready_state) { + msc->unit[msc->cur_lun].state_changed = 1U; + } else { + msc->unit[msc->cur_lun].state_changed = 0U; + } + + msc->unit[msc->cur_lun].state = MSC_READ_CAPACITY10; + msc->unit[msc->cur_lun].error = MSC_OK; + msc->unit[msc->cur_lun].prev_ready_state = USBH_OK; + } else if (USBH_FAIL == ready_status) { + if (USBH_FAIL != msc->unit[msc->cur_lun].prev_ready_state) { + msc->unit[msc->cur_lun].state_changed = 1U; + } else { + msc->unit[msc->cur_lun].state_changed = 0U; + } + + msc->unit[msc->cur_lun].state = MSC_REQUEST_SENSE; + msc->unit[msc->cur_lun].error = MSC_NOT_READY; + msc->unit[msc->cur_lun].prev_ready_state = USBH_FAIL; + } else { + if (USBH_UNRECOVERED_ERROR == ready_status) { + msc->unit[msc->cur_lun].state = MSC_IDLE; + msc->unit[msc->cur_lun].error = MSC_ERROR; + } + } + break; + + case MSC_READ_CAPACITY10: + /* issue READ_CAPACITY10 SCSI command */ + scsi_status = usbh_msc_read_capacity10(uhost, msc->cur_lun, &msc->unit[msc->cur_lun].capacity); + + if (USBH_OK == scsi_status) { + if (1U == msc->unit[msc->cur_lun].state_changed) { + } + msc->unit[msc->cur_lun].state = MSC_IDLE; + msc->unit[msc->cur_lun].error = MSC_OK; + msc->cur_lun ++; + } else if (USBH_FAIL == scsi_status) { + msc->unit[msc->cur_lun].state = MSC_REQUEST_SENSE; + } else { + if (USBH_UNRECOVERED_ERROR == scsi_status) { + msc->unit[msc->cur_lun].state = MSC_IDLE; + msc->unit[msc->cur_lun].error = MSC_ERROR; + } + } + break; + + case MSC_REQUEST_SENSE: + /* issue RequestSense SCSI command for receiving error code */ + scsi_status = usbh_msc_request_sense (uhost, msc->cur_lun, &msc->unit[msc->cur_lun].sense); + if (USBH_OK == scsi_status) { + if ((msc->unit[msc->cur_lun].sense.SenseKey == UNIT_ATTENTION) || (msc->unit[msc->cur_lun].sense.SenseKey == NOT_READY)) { + if ((uhost->control.timer - msc->timer) < 10000U) { + msc->unit[msc->cur_lun].state = MSC_TEST_UNIT_READY; + break; + } + } + + msc->unit[msc->cur_lun].state = MSC_IDLE; + msc->cur_lun++; + } else if (USBH_FAIL == scsi_status) { + msc->unit[msc->cur_lun].state = MSC_UNRECOVERED_ERROR; + } else { + if (MSC_UNRECOVERED_ERROR == scsi_status) { + msc->unit[msc->cur_lun].state = MSC_IDLE; + msc->unit[msc->cur_lun].error = MSC_ERROR; + } + } + break; + + case MSC_UNRECOVERED_ERROR: + msc->cur_lun ++; + break; + + default: + break; + } + } else { + msc->cur_lun = 0U; + msc->state = MSC_IDLE; + } + break; + + case MSC_IDLE: + uhost->usr_cb->dev_user_app(); + status = USBH_OK; + break; + + default: + break; + } + + return status; +} + +/*! + \brief get max lun of the mass storage device + \param[in] uhost: pointer to USB host + \param[in] maxlun: pointer to max lun + \param[out] none + \retval operation status +*/ +static usbh_status usbh_msc_maxlun_get (usbh_host *uhost, uint8_t *maxlun) +{ + usbh_status status = USBH_BUSY; + + if (uhost->control.ctl_state == CTL_IDLE) { + uhost->control.setup.req = (usb_req) { + .bmRequestType = USB_TRX_IN | USB_REQTYPE_CLASS | USB_RECPTYPE_ITF, + .bRequest = BBB_GET_MAX_LUN, + .wValue = 0U, + .wIndex = 0U, + .wLength = 1U + }; + + usbh_ctlstate_config (uhost, maxlun, 1U); + } + + status = usbh_ctl_handler (uhost); + + return status; +} + +/*! + \brief get max lun of the mass storage device + \param[in] uhost: pointer to USB host + \param[in] lun: logic unit number + \param[out] none + \retval operation status +*/ +static usbh_status usbh_msc_rdwr_process(usbh_host *uhost, uint8_t lun) +{ + usbh_status error = USBH_BUSY; + usbh_status scsi_status = USBH_BUSY; + usbh_msc_handler *msc = (usbh_msc_handler *)uhost->active_class->class_data; + + /* switch msc req state machine */ + switch (msc->unit[lun].state) { + case MSC_READ: + scsi_status = usbh_msc_read10(uhost, lun, NULL, 0U, 0U); + + if (USBH_OK == scsi_status) { + msc->unit[lun].state = MSC_IDLE; + error = USBH_OK; + } else if (USBH_FAIL == scsi_status) { + msc->unit[lun].state = MSC_REQUEST_SENSE; + } else { + if (USBH_UNRECOVERED_ERROR == scsi_status) { + msc->unit[lun].state = MSC_UNRECOVERED_ERROR; + error = USBH_FAIL; + } + } + break; + + case MSC_WRITE: + scsi_status = usbh_msc_write10(uhost, lun, NULL, 0U, 0U); + + if (USBH_OK == scsi_status) { + msc->unit[lun].state = MSC_IDLE; + error = USBH_OK; + } else if(USBH_FAIL == scsi_status) { + msc->unit[lun].state = MSC_REQUEST_SENSE; + } else { + if (USBH_UNRECOVERED_ERROR == scsi_status) { + msc->unit[lun].state = MSC_UNRECOVERED_ERROR; + error = USBH_FAIL; + } + } + break; + + case MSC_REQUEST_SENSE: + scsi_status = usbh_msc_request_sense (uhost, lun, &msc->unit[lun].sense); + + if (USBH_OK == scsi_status) { + msc->unit[lun].state = MSC_IDLE; + msc->unit[lun].error = MSC_ERROR; + + error = USBH_FAIL; + } + + if (USBH_FAIL == scsi_status) { + } else { + if (USBH_UNRECOVERED_ERROR == scsi_status) { + msc->unit[lun].state = MSC_UNRECOVERED_ERROR; + error = USBH_FAIL; + } + } + break; + + default: + break; + } + + return error; +} + +/*! + \brief get lun information + \param[in] uhost: pointer to USB host + \param[in] lun: logic unit number + \param[in] info: pointer to lun information + \param[out] none + \retval operation status +*/ +usbh_status usbh_msc_lun_info_get (usbh_host *uhost, uint8_t lun, msc_lun *info) +{ + usbh_msc_handler *msc = (usbh_msc_handler *)uhost->active_class->class_data; + + if (HOST_CLASS_HANDLER == uhost->cur_state) { + memcpy(info, &msc->unit[lun], sizeof(msc_lun)); + + return USBH_OK; + } else { + return USBH_FAIL; + } +} + +/*! + \brief handle msc read operation + \param[in] uhost: pointer to USB host + \param[in] lun: logic unit number + \param[in] address: data address + \param[in] pbuf: pointer to data buffer + \param[in] length: buffer length + \param[out] none + \retval operation status +*/ +usbh_status usbh_msc_read (usbh_host *uhost, + uint8_t lun, + uint32_t address, + uint8_t *pbuf, + uint32_t length) +{ + uint32_t timeout = 0U; + usbh_msc_handler *msc = (usbh_msc_handler *)uhost->active_class->class_data; + usb_core_driver *udev = (usb_core_driver *)uhost->data; + + if ((0U == udev->host.connect_status) || + (HOST_CLASS_HANDLER != uhost->cur_state) || + (MSC_IDLE != msc->unit[lun].state)) { + return USBH_FAIL; + } + + msc->state = MSC_READ; + msc->unit[lun].state = MSC_READ; + msc->rw_lun = lun; + + usbh_msc_read10(uhost, lun, pbuf, address, length); + + timeout = uhost->control.timer; + + while (USBH_BUSY == usbh_msc_rdwr_process(uhost, lun)) { + if (((uhost->control.timer - timeout) > (1000U * length)) || (0U == udev->host.connect_status)) { + msc->state = MSC_IDLE; + return USBH_FAIL; + } + } + + msc->state = MSC_IDLE; + + return USBH_OK; +} + +/*! + \brief handle msc write operation + \param[in] uhost: pointer to USB host + \param[in] lun: logic unit number + \param[in] address: data address + \param[in] pbuf: pointer to data buffer + \param[in] length: buffer length + \param[out] none + \retval operation status +*/ +usbh_status usbh_msc_write (usbh_host *uhost, + uint8_t lun, + uint32_t address, + uint8_t *pbuf, + uint32_t length) +{ + uint32_t timeout = 0U; + usb_core_driver *udev = (usb_core_driver *)uhost->data; + usbh_msc_handler *msc = (usbh_msc_handler *)uhost->active_class->class_data; + + if ((0U == udev->host.connect_status) || + (HOST_CLASS_HANDLER != uhost->cur_state) || + (MSC_IDLE != msc->unit[lun].state)) { + return USBH_FAIL; + } + + msc->state = MSC_WRITE; + msc->unit[lun].state = MSC_WRITE; + msc->rw_lun = lun; + + usbh_msc_write10(uhost, lun, pbuf, address, length); + + timeout = uhost->control.timer; + + while (USBH_BUSY == usbh_msc_rdwr_process(uhost, lun)) { + if (((uhost->control.timer - timeout) > (1000U * length)) || (0U == udev->host.connect_status)) { + msc->state = MSC_IDLE; + return USBH_FAIL; + } + } + + msc->state = MSC_IDLE; + + return USBH_OK; +} diff --git a/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/host/class/msc/Source/usbh_msc_fatfs.c b/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/host/class/msc/Source/usbh_msc_fatfs.c new file mode 100644 index 0000000000..f89d7d740a --- /dev/null +++ b/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/host/class/msc/Source/usbh_msc_fatfs.c @@ -0,0 +1,233 @@ +/*! + \file usbh_msc_fatfs.c + \brief USB MSC host FATFS related functions + + \version 2020-08-01, V3.0.0, firmware for GD32F4xx +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "usb_conf.h" +#include "diskio.h" +#include "usbh_msc_core.h" + +static volatile DSTATUS state = STA_NOINIT; /* disk status */ + +extern usbh_host usb_host_msc; + +/*! + \brief initialize the disk drive + \param[in] drv: physical drive number (0) + \param[out] none + \retval operation status +*/ +DSTATUS disk_initialize (BYTE drv) +{ + usb_core_driver *udev = (usb_core_driver *)usb_host_msc.data; + + if (udev->host.connect_status) { + state &= ~STA_NOINIT; + } + + return state; +} + +/*! + \brief get disk status + \param[in] drv: physical drive number (0) + \param[out] none + \retval operation status +*/ +DSTATUS disk_status (BYTE drv) +{ + if (drv) { + return STA_NOINIT; /* supports only single drive */ + } + + return state; +} + +/*! + \brief read sectors + \param[in] drv: physical drive number (0) + \param[in] buff: pointer to the data buffer to store read data + \param[in] sector: start sector number (LBA) + \param[in] count: sector count (1..255) + \param[out] none + \retval operation status +*/ +DRESULT disk_read (BYTE drv, BYTE *buff, DWORD sector, UINT count) +{ + BYTE status = USBH_OK; + usb_core_driver *udev = (usb_core_driver *)usb_host_msc.data; + + if (drv || (!count)) { + return RES_PARERR; + } + + if (state & STA_NOINIT) { + return RES_NOTRDY; + } + + if (udev->host.connect_status) { + do { + status = usbh_msc_read (&usb_host_msc, drv, sector, buff, count); + + if (!udev->host.connect_status) { + return RES_ERROR; + } + } while(status == USBH_BUSY); + } + + if (status == USBH_OK) { + return RES_OK; + } + + return RES_ERROR; +} + +#if _READONLY == 0U + +/*! + \brief write sectors + \param[in] drv: physical drive number (0) + \param[in] buff: pointer to the data buffer to store read data + \param[in] sector: start sector number (LBA) + \param[in] count: sector count (1..255) + \param[out] none + \retval operation status +*/ +DRESULT disk_write (BYTE drv, const BYTE *buff, DWORD sector, UINT count) +{ + BYTE status = USBH_OK; + usb_core_driver *udev = (usb_core_driver *)usb_host_msc.data; + + if ((!count) || drv) { + return RES_PARERR; + } + + if (state & STA_NOINIT) { + return RES_NOTRDY; + } + + if (state & STA_PROTECT) { + return RES_WRPRT; + } + + if (udev->host.connect_status) { + do { + status = usbh_msc_write (&usb_host_msc, drv, sector, (BYTE*)buff, count); + + if (!udev->host.connect_status) { + return RES_ERROR; + } + } while(status == USBH_BUSY); + } + + if (status == USBH_OK) { + return RES_OK; + } + + return RES_ERROR; +} + +#endif /* _READONLY == 0 */ + +/*! + \brief I/O control function + \param[in] drv: physical drive number (0) + \param[in] ctrl: control code + \param[in] buff: pointer to the data buffer to store read data + \param[out] none + \retval operation status +*/ +DRESULT disk_ioctl (BYTE drv, BYTE ctrl, void *buff) +{ + DRESULT res = RES_OK; + msc_lun info; + + if (drv) { + return RES_PARERR; + } + + res = RES_ERROR; + + if (state & STA_NOINIT) { + return RES_NOTRDY; + } + + switch (ctrl) { + /* make sure that no pending write process */ + case CTRL_SYNC: + res = RES_OK; + break; + + /* get number of sectors on the disk (dword) */ + case GET_SECTOR_COUNT: + if (USBH_OK == usbh_msc_lun_info_get(&usb_host_msc, drv, &info)) { + *(DWORD*)buff = (DWORD)info.capacity.block_nbr; + res = RES_OK; + } + break; + + /* get r/w sector size (word) */ + case GET_SECTOR_SIZE: + if (USBH_OK == usbh_msc_lun_info_get(&usb_host_msc, drv, &info)) { + *(WORD*)buff = (DWORD)info.capacity.block_size; + res = RES_OK; + } + break; + + /* get erase block size in unit of sector (dword) */ + case GET_BLOCK_SIZE: + *(DWORD*)buff = 512; + break; + + default: + res = RES_PARERR; + break; + } + + return res; +} + +/*! + \brief get fat time + \param[in] none + \param[out] none + \retval time value +*/ +DWORD get_fattime(void) { + + return ((DWORD)(2019U - 1980U) << 25U) /* year 2019 */ + | ((DWORD)1U << 21U) /* month 1 */ + | ((DWORD)1U << 16U) /* day 1 */ + | ((DWORD)0U << 11U) /* hour 0 */ + | ((DWORD)0U << 5U) /* min 0 */ + | ((DWORD)0U >> 1U); /* sec 0 */ +} diff --git a/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/host/class/msc/Source/usbh_msc_scsi.c b/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/host/class/msc/Source/usbh_msc_scsi.c new file mode 100644 index 0000000000..e9566af405 --- /dev/null +++ b/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/host/class/msc/Source/usbh_msc_scsi.c @@ -0,0 +1,400 @@ +/*! + \file usbh_msc_scsi.c + \brief USB MSC SCSI commands implementing + + \version 2020-08-01, V3.0.0, firmware for GD32F4xx +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "usbh_msc_core.h" +#include "usbh_msc_scsi.h" +#include "usbh_msc_bbb.h" + +#include + +/*! + \brief send 'Inquiry' command to the device + \param[in] uhost: pointer to USB host handler + \param[in] lun: logic unit number + \param[in] inquiry: pointer to the inquiry structure + \param[out] none + \retval operation status +*/ +usbh_status usbh_msc_scsi_inquiry (usbh_host *uhost, uint8_t lun, scsi_std_inquiry_data *inquiry) +{ + usbh_status error = USBH_FAIL; + usbh_msc_handler *msc = (usbh_msc_handler *)uhost->active_class->class_data; + + switch (msc->bot.cmd_state) { + case BOT_CMD_SEND: + /* prepare the CBW and relevant field*/ + msc->bot.cbw.field.dCBWDataTransferLength = STANDARD_INQUIRY_DATA_LEN; + msc->bot.cbw.field.bmCBWFlags = USB_TRX_IN; + msc->bot.cbw.field.bCBWCBLength = CBW_LENGTH; + + memset(msc->bot.cbw.field.CBWCB, 0U, CBW_LENGTH); + + msc->bot.cbw.field.CBWCB[0] = SCSI_INQUIRY; + msc->bot.cbw.field.CBWCB[1] = (lun << 5U); + msc->bot.cbw.field.CBWCB[4] = 0x24U; + + msc->bot.state = BOT_SEND_CBW; + msc->bot.cmd_state = BOT_CMD_WAIT; + msc->bot.pbuf = (uint8_t *)(void *)msc->bot.data; + error = USBH_BUSY; + break; + + case BOT_CMD_WAIT: + error = usbh_msc_bot_process(uhost, lun); + + if (USBH_OK == error) { + memset(inquiry, 0U, sizeof(scsi_std_inquiry_data)); + + /* assign inquiry data */ + inquiry->device_type = msc->bot.pbuf[0] & 0x1FU; + inquiry->peripheral_qualifier = msc->bot.pbuf[0] >> 5U; + + if (0x80U == ((uint32_t)msc->bot.pbuf[1] & 0x80U)) { + inquiry->removable_media = 1U; + } else { + inquiry->removable_media = 0U; + } + + memcpy (inquiry->vendor_id, &msc->bot.pbuf[8], 8U); + memcpy (inquiry->product_id, &msc->bot.pbuf[16], 16U); + memcpy (inquiry->revision_id, &msc->bot.pbuf[32], 4U); + } + break; + + default: + break; + } + + return error; +} + +/*! + \brief send 'Test unit ready' command to the device + \param[in] uhost: pointer to USB host handler + \param[in] lun: logic unit number + \param[out] none + \retval operation status +*/ +usbh_status usbh_msc_test_unitready (usbh_host *uhost, uint8_t lun) +{ + usbh_status status = USBH_FAIL; + usbh_msc_handler *msc = (usbh_msc_handler *)uhost->active_class->class_data; + + + switch (msc->bot.cmd_state) { + case BOT_CMD_SEND: + /* prepare the CBW and relevant field */ + msc->bot.cbw.field.dCBWDataTransferLength = CBW_LENGTH_TEST_UNIT_READY; + msc->bot.cbw.field.bmCBWFlags = USB_TRX_OUT; + msc->bot.cbw.field.bCBWCBLength = CBW_LENGTH; + + memset(msc->bot.cbw.field.CBWCB, 0U, CBW_CB_LENGTH); + + msc->bot.cbw.field.CBWCB[0] = SCSI_TEST_UNIT_READY; + msc->bot.state = BOT_SEND_CBW; + msc->bot.cmd_state = BOT_CMD_WAIT; + + status = USBH_BUSY; + break; + + case BOT_CMD_WAIT: + status = usbh_msc_bot_process(uhost, lun); + break; + + default: + break; + } + + return status; +} + +/*! + \brief send the read capacity command to the device + \param[in] uhost: pointer to USB host handler + \param[in] lun: logic unit number + \param[in] capacity: pointer to SCSI capacity + \param[out] none + \retval operation status +*/ +usbh_status usbh_msc_read_capacity10 (usbh_host *uhost, uint8_t lun, scsi_capacity *capacity) +{ + usbh_status status = USBH_FAIL; + usbh_msc_handler *msc = (usbh_msc_handler *)uhost->active_class->class_data; + + switch (msc->bot.cmd_state) { + case BOT_CMD_SEND: + /* prepare the CBW and relevant field */ + msc->bot.cbw.field.dCBWDataTransferLength = READ_CAPACITY10_DATA_LEN; + msc->bot.cbw.field.bmCBWFlags = USB_TRX_IN; + msc->bot.cbw.field.bCBWCBLength = CBW_LENGTH; + + memset(msc->bot.cbw.field.CBWCB, 0U, CBW_CB_LENGTH); + + msc->bot.cbw.field.CBWCB[0] = SCSI_READ_CAPACITY10; + msc->bot.state = BOT_SEND_CBW; + msc->bot.cmd_state = BOT_CMD_WAIT; + msc->bot.pbuf = (uint8_t *)(void *)msc->bot.data; + + status = USBH_BUSY; + break; + + case BOT_CMD_WAIT: + status = usbh_msc_bot_process(uhost, lun); + + if (USBH_OK == status) { + capacity->block_nbr = msc->bot.pbuf[3] | \ + ((uint32_t)msc->bot.pbuf[2] << 8U) | \ + ((uint32_t)msc->bot.pbuf[1] << 16U) | \ + ((uint32_t)msc->bot.pbuf[0] << 24U); + + capacity->block_size = (uint16_t)(msc->bot.pbuf[7] | ((uint32_t)msc->bot.pbuf[6] << 8U)); + } + break; + + default: + break; + } + + return status; +} + +/*! + \brief send the mode sense6 command to the device + \param[in] uhost: pointer to USB host handler + \param[in] lun: logic unit number + \param[out] none + \retval operation status +*/ +usbh_status usbh_msc_mode_sense6 (usbh_host *uhost, uint8_t lun) +{ + usbh_status status = USBH_FAIL; + usbh_msc_handler *msc = (usbh_msc_handler *)uhost->active_class->class_data; + + + switch (msc->bot.cmd_state) { + case BOT_CMD_SEND: + /* prepare the CBW and relevant field */ + msc->bot.cbw.field.dCBWDataTransferLength = XFER_LEN_MODE_SENSE6; + msc->bot.cbw.field.bmCBWFlags = USB_TRX_IN; + msc->bot.cbw.field.bCBWCBLength = CBW_LENGTH; + + memset(msc->bot.cbw.field.CBWCB, 0U, CBW_CB_LENGTH); + + msc->bot.cbw.field.CBWCB[0] = SCSI_MODE_SENSE6; + msc->bot.cbw.field.CBWCB[2] = MODE_SENSE_PAGE_CONTROL_FIELD | MODE_SENSE_PAGE_CODE; + msc->bot.cbw.field.CBWCB[4] = XFER_LEN_MODE_SENSE6; + msc->bot.state = BOT_SEND_CBW; + msc->bot.cmd_state = BOT_CMD_WAIT; + msc->bot.pbuf = (uint8_t *)(void *)msc->bot.data; + + status = USBH_BUSY; + break; + + case BOT_CMD_WAIT: + status = usbh_msc_bot_process(uhost, lun); + + if (USBH_OK == status) { + if (msc->bot.data[2] & MASK_MODE_SENSE_WRITE_PROTECT) { + + } else { + + } + } + break; + + default: + break; + } + + + return status; +} + +/*! + \brief send the Request Sense command to the device + \param[in] uhost: pointer to USB host handler + \param[in] lun: logic unit number + \param[in] sense_data: pointer to sense data + \param[out] none + \retval operation status +*/ +usbh_status usbh_msc_request_sense (usbh_host *uhost, uint8_t lun, msc_scsi_sense *sense_data) +{ + usbh_status status = USBH_FAIL; + usbh_msc_handler *msc = (usbh_msc_handler *)uhost->active_class->class_data; + + switch (msc->bot.cmd_state) { + case BOT_CMD_SEND: + /* prepare the CBW and relevant field */ + msc->bot.cbw.field.dCBWDataTransferLength = ALLOCATION_LENGTH_REQUEST_SENSE; + msc->bot.cbw.field.bmCBWFlags = USB_TRX_IN; + msc->bot.cbw.field.bCBWCBLength = CBW_LENGTH; + + memset(msc->bot.cbw.field.CBWCB, 0U, CBW_CB_LENGTH); + + msc->bot.cbw.field.CBWCB[0] = SCSI_REQUEST_SENSE; + msc->bot.cbw.field.CBWCB[1] = (lun << 5U); + msc->bot.cbw.field.CBWCB[4] = ALLOCATION_LENGTH_REQUEST_SENSE; + + msc->bot.state = BOT_SEND_CBW; + msc->bot.cmd_state = BOT_CMD_WAIT; + msc->bot.pbuf = (uint8_t *)(void *)msc->bot.data; + + status = USBH_BUSY; + break; + + case BOT_CMD_WAIT: + status = usbh_msc_bot_process(uhost, lun); + + if (status == USBH_OK) { + /* get sense data */ + sense_data->SenseKey = msc->bot.pbuf[2] & 0x0FU; + sense_data->ASC = msc->bot.pbuf[12]; + sense_data->ASCQ = msc->bot.pbuf[13]; + } + break; + + default: + break; + } + + return status; +} + +/*! + \brief send the write10 command to the device + \param[in] uhost: pointer to USB host handler + \param[in] lun: logic unit number + \param[in] data_buf: data buffer contains the data to write + \param[in] addr: address to which the data will be written + \param[in] sector_num: number of sector to be written + \param[out] none + \retval operation status +*/ +usbh_status usbh_msc_write10 (usbh_host *uhost, uint8_t lun, uint8_t *data_buf, uint32_t addr, uint32_t sector_num) +{ + usbh_status status = USBH_FAIL; + usbh_msc_handler *msc = (usbh_msc_handler *)uhost->active_class->class_data; + + switch (msc->bot.cmd_state) { + case BOT_CMD_SEND: + msc->bot.cbw.field.dCBWDataTransferLength = sector_num * msc->unit[lun].capacity.block_size; + msc->bot.cbw.field.bmCBWFlags = USB_TRX_OUT; + msc->bot.cbw.field.bCBWCBLength = CBW_LENGTH; + + memset(msc->bot.cbw.field.CBWCB, 0U, CBW_CB_LENGTH); + + msc->bot.cbw.field.CBWCB[0] = SCSI_WRITE10; + + /* logical block address */ + msc->bot.cbw.field.CBWCB[2] = (((uint8_t*)&addr)[3]); + msc->bot.cbw.field.CBWCB[3] = (((uint8_t*)&addr)[2]); + msc->bot.cbw.field.CBWCB[4] = (((uint8_t*)&addr)[1]); + msc->bot.cbw.field.CBWCB[5] = (((uint8_t*)&addr)[0]); + + /* transfer length */ + msc->bot.cbw.field.CBWCB[7] = (((uint8_t *)§or_num)[1]); + msc->bot.cbw.field.CBWCB[8] = (((uint8_t *)§or_num)[0]); + + msc->bot.state = BOT_SEND_CBW; + msc->bot.cmd_state = BOT_CMD_WAIT; + msc->bot.pbuf = data_buf; + + status = USBH_BUSY; + break; + + case BOT_CMD_WAIT: + status = usbh_msc_bot_process(uhost, lun); + break; + + default: + break; + } + + return status; +} + +/*! + \brief send the read10 command to the device + \param[in] uhost: pointer to USB host handler + \param[in] lun: logic unit number + \param[in] data_buf: data buffer contains the data to write + \param[in] addr: address to which the data will be read + \param[in] sector_num: number of sector to be read + \param[out] none + \retval operation status +*/ +usbh_status usbh_msc_read10 (usbh_host *uhost, uint8_t lun, uint8_t *data_buf, uint32_t addr, uint32_t sector_num) +{ + usbh_status status = USBH_FAIL; + usbh_msc_handler *msc = (usbh_msc_handler *)uhost->active_class->class_data; + + switch (msc->bot.cmd_state) { + case BOT_CMD_SEND: + /* prepare the CBW and relevant field */ + msc->bot.cbw.field.dCBWDataTransferLength = sector_num * msc->unit[lun].capacity.block_size; + msc->bot.cbw.field.bmCBWFlags = USB_TRX_IN; + msc->bot.cbw.field.bCBWCBLength = CBW_LENGTH; + + memset(msc->bot.cbw.field.CBWCB, 0U, CBW_CB_LENGTH); + + msc->bot.cbw.field.CBWCB[0] = SCSI_READ10; + + /* logical block address */ + msc->bot.cbw.field.CBWCB[2] = (((uint8_t*)&addr)[3]); + msc->bot.cbw.field.CBWCB[3] = (((uint8_t*)&addr)[2]); + msc->bot.cbw.field.CBWCB[4] = (((uint8_t*)&addr)[1]); + msc->bot.cbw.field.CBWCB[5] = (((uint8_t*)&addr)[0]); + + /* transfer length */ + msc->bot.cbw.field.CBWCB[7] = (((uint8_t *)§or_num)[1]); + msc->bot.cbw.field.CBWCB[8] = (((uint8_t *)§or_num)[0]); + + msc->bot.state = BOT_SEND_CBW; + msc->bot.cmd_state = BOT_CMD_WAIT; + msc->bot.pbuf = data_buf; + + status = USBH_BUSY; + break; + + case BOT_CMD_WAIT: + status = usbh_msc_bot_process(uhost, lun); + break; + + default: + break; + } + + return status; +} diff --git a/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/host/core/Include/usbh_core.h b/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/host/core/Include/usbh_core.h new file mode 100644 index 0000000000..c8e7ca1e7c --- /dev/null +++ b/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/host/core/Include/usbh_core.h @@ -0,0 +1,282 @@ +/*! + \file usbh_core.h + \brief USB host core state machine header file + + \version 2020-08-01, V3.0.0, firmware for GD32F4xx +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef __USBH_CORE_H +#define __USBH_CORE_H + +#include "usbh_conf.h" +#include "drv_usb_host.h" + +#define MSC_CLASS 0x08U +#define HID_CLASS 0x03U +#define MSC_PROTOCOL 0x50U +#define CBI_PROTOCOL 0x01U + +#define USBH_MAX_ERROR_COUNT 3U + +#define USBH_DEV_ADDR_DEFAULT 0U +#define USBH_DEV_ADDR 1U + +typedef enum +{ + USBH_OK = 0U, + USBH_BUSY, + USBH_FAIL, + USBH_NOT_SUPPORTED, + USBH_UNRECOVERED_ERROR, + USBH_SPEED_UNKNOWN_ERROR, + USBH_APPLY_DEINIT +} usbh_status; + +/* USB host global operation state */ +typedef enum +{ + HOST_DEFAULT = 0U, + HOST_DETECT_DEV_SPEED, + HOST_DEV_ATTACHED, + HOST_DEV_DETACHED, + HOST_ENUM, + HOST_SET_WAKEUP_FEATURE, + HOST_CHECK_CLASS, + HOST_CLASS_ENUM, + HOST_CLASS_HANDLER, + HOST_USER_INPUT, + HOST_SUSPENDED, + HOST_WAKEUP, + HOST_ERROR +} usb_host_state; + +/* USB host enumeration state */ +typedef enum +{ + ENUM_DEFAULT = 0U, + ENUM_GET_DEV_DESC, + ENUM_SET_ADDR, + ENUM_GET_CFG_DESC, + ENUM_GET_CFG_DESC_SET, + ENUM_GET_STR_DESC, +#ifdef USB_MTP + ENUM_GET_MTP_STR, +#endif + ENUM_SET_CONFIGURATION, + ENUM_DEV_CONFIGURED +} usbh_enum_state; + +/* USB host control transfer state */ +typedef enum +{ + CTL_IDLE = 0U, + CTL_SETUP, + CTL_SETUP_WAIT, + CTL_DATA_IN, + CTL_DATA_IN_WAIT, + CTL_DATA_OUT, + CTL_DATA_OUT_WAIT, + CTL_STATUS_IN, + CTL_STATUS_IN_WAIT, + CTL_STATUS_OUT, + CTL_STATUS_OUT_WAIT, + CTL_ERROR, + CTL_FINISH +} usbh_ctl_state; + +/* user action state */ +typedef enum +{ + USBH_USER_NO_RESP = 0U, + USBH_USER_RESP_OK = 1U, +} usbh_user_status; + +typedef enum +{ + USBH_PORT_EVENT = 1U, + USBH_URB_EVENT, + USBH_CONTROL_EVENT, + USBH_CLASS_EVENT, + USBH_STATE_CHANGED_EVENT, +}usbh_os_event; + +/* control transfer information */ +typedef struct _usbh_control +{ + uint8_t pipe_in_num; + uint8_t pipe_out_num; + uint8_t max_len; + uint8_t error_count; + + uint8_t *buf; + uint16_t ctl_len; + uint16_t timer; + + usb_setup setup; + usbh_ctl_state ctl_state; +} usbh_control; + +/* USB interface descriptor set */ +typedef struct _usb_desc_itf_set +{ + usb_desc_itf itf_desc; + usb_desc_ep ep_desc[USBH_MAX_EP_NUM]; +} usb_desc_itf_set; + +/* USB configure descriptor set */ +typedef struct _usb_desc_cfg_set +{ + usb_desc_config cfg_desc; + usb_desc_itf_set itf_desc_set[USBH_MAX_INTERFACES_NUM][USBH_MAX_ALT_SETTING]; +} usb_desc_cfg_set; + +/* USB device property */ +typedef struct +{ + uint8_t data[USBH_DATA_BUF_MAX_LEN]; /* if DMA is used, the data array must be located in the first position */ + uint8_t cur_itf; + uint8_t addr; + + uint32_t speed; + + usb_desc_dev dev_desc; + usb_desc_cfg_set cfg_desc_set; + +#if (USBH_KEEP_CFG_DESCRIPTOR == 1U) + uint8_t cfgdesc_rawdata[USBH_CFGSET_MAX_LEN]; +#endif /* (USBH_KEEP_CFG_DESCRIPTOR == 1U) */ +} usb_dev_prop; + +struct _usbh_host; + +/* device class callbacks */ +typedef struct +{ + uint8_t class_code; /*!< USB class type */ + + usbh_status (*class_init) (struct _usbh_host *phost); + void (*class_deinit) (struct _usbh_host *phost); + usbh_status (*class_requests) (struct _usbh_host *phost); + usbh_status (*class_machine) (struct _usbh_host *phost); + usbh_status (*class_sof) (struct _usbh_host *uhost); + + void *class_data; +} usbh_class; + +/* user callbacks */ +typedef struct +{ + void (*dev_init) (void); + void (*dev_deinit) (void); + void (*dev_attach) (void); + void (*dev_reset) (void); + void (*dev_detach) (void); + void (*dev_over_currented) (void); + void (*dev_speed_detected) (uint32_t dev_speed); + void (*dev_devdesc_assigned) (void *dev_desc); + void (*dev_address_set) (void); + + void (*dev_cfgdesc_assigned) (usb_desc_config *cfg_desc, + usb_desc_itf *itf_desc, + usb_desc_ep *ep_desc); + + void (*dev_mfc_str) (void *mfc_str); + void (*dev_prod_str) (void *prod_str); + void (*dev_seral_str) (void *serial_str); + void (*dev_enumerated) (void); + usbh_user_status (*dev_user_input) (void); + int (*dev_user_app) (void); + void (*dev_not_supported) (void); + void (*dev_error) (void); +} usbh_user_cb; + +/* host information */ +typedef struct _usbh_host +{ + usb_host_state cur_state; /*!< host state machine value */ + usb_host_state backup_state; /*!< backup of previous state machine value */ + usbh_enum_state enum_state; /*!< enumeration state machine */ + usbh_control control; /*!< USB host control state machine */ + usb_dev_prop dev_prop; /*!< USB device property */ + + usbh_class *uclass[USBH_MAX_SUPPORTED_CLASS]; /*!< USB host supported class */ + usbh_class *active_class; /*!< USB active class */ + usbh_user_cb *usr_cb; /*!< USB user callback */ + + uint8_t class_num; /*!< USB class number */ + + void *data; /*!< used for... */ + +#ifdef USB_LOW_PWR_ENABLE + uint8_t suspend_flag; +#endif /* USB_LOW_PWR_ENABLE*/ +} usbh_host; + +/*! + \brief get USB URB state + \param[in] udev: pointer to USB core instance + \param[in] pp_num: pipe number + \param[out] none + \retval none +*/ +static inline usb_urb_state usbh_urbstate_get (usb_core_driver *udev, uint8_t pp_num) +{ + return udev->host.pipe[pp_num].urb_state; +} + +/*! + \brief get USB transfer data count + \param[in] udev: pointer to USB core instance + \param[in] pp_num: pipe number + \param[out] none + \retval none +*/ +static inline uint32_t usbh_xfercount_get (usb_core_driver *udev, uint8_t pp_num) +{ + return udev->host.backup_xfercount[pp_num]; +} + +/* function declarations */ +/* USB host stack initializations */ +void usbh_init (usbh_host *uhost, usb_core_driver *udev, usb_core_enum usb_core, usbh_user_cb *user_cb); +/* USB host register device class */ +usbh_status usbh_class_register (usbh_host *uhost, usbh_class *puclass); +/* de-initialize USB host */ +usbh_status usbh_deinit (usbh_host *uhost); +/* USB host core main state machine process */ +void usbh_core_task (usbh_host *uhost); +/* handle the error on USB host side */ +void usbh_error_handler (usbh_host *uhost, usbh_status err_type); +#ifdef USB_LOW_PWR_ENABLE +/* handles the USB resume from suspend mode */ +void usb_hwp_resume(usb_core_driver *udev); +#endif /* USB_LOW_PWR_ENABLE */ + +#endif /* __USBH_CORE_H */ diff --git a/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/host/core/Include/usbh_enum.h b/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/host/core/Include/usbh_enum.h new file mode 100644 index 0000000000..3112d1a998 --- /dev/null +++ b/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/host/core/Include/usbh_enum.h @@ -0,0 +1,71 @@ +/*! + \file usbh_enum.h + \brief USB host mode USB enumeration header file + + \version 2020-08-01, V3.0.0, firmware for GD32F4xx +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef __USBH_ENUM_H +#define __USBH_ENUM_H + +#include "usb_conf.h" +#include "usbh_core.h" + +/* function declarations */ +/* configure USB control status parameters */ +void usbh_ctlstate_config (usbh_host *uhost, uint8_t *buf, uint16_t len); +/* get device descriptor from the USB device */ +usbh_status usbh_devdesc_get (usbh_host *uhost, uint8_t len); +/* get configuration descriptor from the USB device */ +usbh_status usbh_cfgdesc_get (usbh_host *uhost, uint16_t len); +/* get string descriptor from the USB device */ +usbh_status usbh_strdesc_get (usbh_host *uhost,uint8_t str_index, uint8_t *buf, uint16_t len); +/* set the address to the connected device */ +usbh_status usbh_setaddress (usbh_host *uhost, uint8_t dev_addr); +/* set the configuration value to the connected device */ +usbh_status usbh_setcfg (usbh_host *uhost, uint16_t config); +/* set the interface value to the connected device */ +usbh_status usbh_setinterface (usbh_host *uhost, uint8_t itf_num, uint8_t alter_setting); +/* set or enable a specific device feature */ +usbh_status usbh_setdevfeature (usbh_host *uhost, uint8_t feature_selector, uint16_t windex); +/* clear or disable a specific device feature */ +usbh_status usbh_clrdevfeature (usbh_host *uhost, uint8_t feature_selector, uint16_t windex); +/* clear or disable a specific feature */ +usbh_status usbh_clrfeature (usbh_host *uhost, uint8_t ep_addr, uint8_t pp_num); +/* get the next descriptor header */ +usb_desc_header *usbh_nextdesc_get (uint8_t *pbuf, uint16_t *ptr); +/* select an interface */ +usbh_status usbh_interface_select (usb_dev_prop *udev, uint8_t interface); +/* find the interface index for a specific class */ +uint8_t usbh_interface_find (usb_dev_prop *udev, uint8_t main_class, uint8_t sub_class, uint8_t protocol); +/* find the interface index for a specific class interface and alternate setting number */ +uint8_t usbh_interfaceindex_find (usb_dev_prop *udev, uint8_t interface_number, uint8_t alt_settings); + +#endif /* __USBH_ENUM_H */ diff --git a/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/host/core/Include/usbh_pipe.h b/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/host/core/Include/usbh_pipe.h new file mode 100644 index 0000000000..e89c5fe22f --- /dev/null +++ b/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/host/core/Include/usbh_pipe.h @@ -0,0 +1,100 @@ +/*! + \file usbh_pipe.h + \brief USB host mode pipe header file + + \version 2020-08-01, V3.0.0, firmware for GD32F4xx +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef __USBH_PIPE_H +#define __USBH_PIPE_H + +#include "usbh_core.h" + +#define HC_MAX 8U + +#define HC_OK 0x0000U +#define HC_USED 0x8000U +#define HC_ERROR 0xFFFFU +#define HC_USED_MASK 0x7FFFU + +/*! + \brief set toggle for a pipe + \param[in] udev: pointer to USB core instance + \param[in] pp_num: pipe number + \param[in] toggle: toggle (0/1) + \param[out] none + \retval operation status +*/ +__STATIC_INLINE void usbh_pipe_toggle_set (usb_core_driver *udev, uint8_t pp_num, uint8_t toggle) +{ + if (udev->host.pipe[pp_num].ep.dir) { + udev->host.pipe[pp_num].data_toggle_in = toggle; + } else { + udev->host.pipe[pp_num].data_toggle_out = toggle; + } +} + +/*! + \brief get toggle flag of pipe + \param[in] udev: pointer to USB core instance + \param[in] pp_num: pipe number + \param[out] none + \retval operation status +*/ +__STATIC_INLINE uint8_t usbh_pipe_toggle_get (usb_core_driver *udev, uint8_t pp_num) +{ + if (udev->host.pipe[pp_num].ep.dir) { + return udev->host.pipe[pp_num].data_toggle_in; + } else { + return udev->host.pipe[pp_num].data_toggle_out; + } +} + +/* function declarations */ +/* create a pipe */ +uint8_t usbh_pipe_create (usb_core_driver *udev, + usb_dev_prop *dev, + uint8_t pp_num, + uint8_t ep_type, + uint16_t ep_mpl); +/* modify a pipe */ +uint8_t usbh_pipe_update (usb_core_driver *udev, + uint8_t pp_num, + uint8_t dev_addr, + uint32_t dev_speed, + uint16_t ep_mpl); +/* allocate a new pipe */ +uint8_t usbh_pipe_allocate (usb_core_driver *udev, uint8_t ep_addr); +/* free a pipe */ +uint8_t usbh_pipe_free (usb_core_driver *udev, uint8_t pp_num); +/* delete all USB host pipe */ +uint8_t usbh_pipe_delete (usb_core_driver *udev); + +#endif /* __USBH_PIPE_H */ diff --git a/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/host/core/Include/usbh_transc.h b/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/host/core/Include/usbh_transc.h new file mode 100644 index 0000000000..65f4328c55 --- /dev/null +++ b/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/host/core/Include/usbh_transc.h @@ -0,0 +1,51 @@ +/*! + \file usbh_transc.h + \brief USB host mode transactions header file + + \version 2020-08-01, V3.0.0, firmware for GD32F4xx +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef __USBH_TRANSC_H +#define __USBH_TRANSC_H + +#include "usb_conf.h" +#include "usbh_core.h" + +/* function declarations */ +/* send the setup packet to the USB device */ +usbh_status usbh_ctlsetup_send (usb_core_driver *udev, uint8_t *buf, uint8_t pp_num); +/* send a data packet to the USB device */ +usbh_status usbh_data_send (usb_core_driver *udev, uint8_t *buf, uint8_t pp_num, uint16_t len); +/* receive a data packet from the USB device */ +usbh_status usbh_data_recev (usb_core_driver *udev, uint8_t *buf, uint8_t pp_num, uint16_t len); +/* USB control transfer handler */ +usbh_status usbh_ctl_handler (usbh_host *uhost); + +#endif /* __USBH_TRANSC_H */ diff --git a/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/host/core/Source/usbh_core.c b/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/host/core/Source/usbh_core.c new file mode 100644 index 0000000000..8cb32af254 --- /dev/null +++ b/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/host/core/Source/usbh_core.c @@ -0,0 +1,653 @@ +/*! + \file usbh_core.c + \brief USB host core state machine driver + + \version 2020-08-01, V3.0.0, firmware for GD32F4xx +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "drv_usb_hw.h" +#include "usbh_pipe.h" +#include "usbh_enum.h" +#include "usbh_core.h" +#include "drv_usbh_int.h" +#include + +/* local function prototypes ('static') */ +static uint8_t usbh_sof (usbh_host *uhost); +static uint8_t usbh_connect (usbh_host *uhost); +static uint8_t usbh_disconnect (usbh_host *uhost); +static uint8_t usbh_port_enabled (usbh_host *uhost); +static uint8_t usbh_port_disabled (usbh_host *uhost); +static usbh_status usbh_enum_task (usbh_host *uhost); + +#ifdef USB_LOW_PWR_ENABLE +static void usb_hwp_suspend(usb_core_driver *udev); +#endif + +usbh_int_cb usbh_int_op = +{ + usbh_connect, + usbh_disconnect, + usbh_port_enabled, + usbh_port_disabled, + usbh_sof +}; + +usbh_int_cb *usbh_int_fop = &usbh_int_op; + +/*! + \brief USB host stack initializations + \param[in] uhost: pointer to USB host + \param[in] user_cb: pointer to user callback + \param[out] none + \retval none +*/ +void usbh_init (usbh_host *uhost, usb_core_driver *udev, usb_core_enum usb_core, usbh_user_cb *user_cb) +{ + /* host deinitialization */ + usbh_deinit(uhost); + + uhost->usr_cb = user_cb; + + udev->host.connect_status = 0U; + + for (uint8_t i = 0U; i < USBFS_MAX_TX_FIFOS; i++) { + udev->host.pipe[i].err_count = 0U; + udev->host.pipe[i].pp_status = PIPE_IDLE; + udev->host.backup_xfercount[i] = 0U; + } + + udev->host.pipe[0].ep.mps = 8U; + + usb_basic_init (&udev->bp, &udev->regs, usb_core); + +#ifndef DUAL_ROLE_MODE_ENABLED + usb_globalint_disable(&udev->regs); + + usb_core_init (udev->bp, &udev->regs); + +#ifndef USE_OTG_MODE + usb_curmode_set (&udev->regs, HOST_MODE); +#endif /* USE_OTG_MODE */ + + usb_host_init (udev); + + usb_globalint_enable(&udev->regs); +#endif /* DUAL_ROLE_MODE_ENABLED */ + + /* link driver to the stack */ + udev->host.data = (void *)uhost; + uhost->data = (void *)udev; + + /* upon initialize call usr call back */ + uhost->usr_cb->dev_init(); +} + +/*! + \brief USB host register device class + \param[in] uhost: pointer to USB host instance + \param[in] puclass: pointer to USB device class + \param[out] none + \retval operation status +*/ +usbh_status usbh_class_register (usbh_host *uhost, usbh_class *puclass) +{ + usbh_status status = USBH_OK; + + if (NULL != puclass) { + if (uhost->class_num < USBH_MAX_SUPPORTED_CLASS) { + uhost->uclass[uhost->class_num++] = puclass; + } else { + status = USBH_FAIL; + } + } else { + status = USBH_FAIL; + } + + return status; +} + +/*! + \brief de-initialize USB host + \param[in] uhost: pointer to USB host + \param[out] none + \retval operation status +*/ +usbh_status usbh_deinit(usbh_host *uhost) +{ + usb_core_driver *udev = (usb_core_driver *)uhost->data; + + /* software initialize */ + uhost->cur_state = HOST_DEFAULT; + uhost->backup_state = HOST_DEFAULT; + uhost->enum_state = ENUM_DEFAULT; + + uhost->control.ctl_state = CTL_IDLE; + uhost->control.max_len = USB_FS_EP0_MAX_LEN; + + uhost->dev_prop.addr = USBH_DEV_ADDR_DEFAULT; + uhost->dev_prop.speed = PORT_SPEED_FULL; + uhost->dev_prop.cur_itf = 0xFFU; + + usbh_pipe_free(udev, uhost->control.pipe_in_num); + usbh_pipe_free(udev, uhost->control.pipe_out_num); + + return USBH_OK; +} + +/*! + \brief USB host core main state machine process + \param[in] uhost: pointer to USB host + \param[out] none + \retval none +*/ +void usbh_core_task (usbh_host *uhost) +{ + volatile usbh_status status = USBH_FAIL; + usb_core_driver *udev = (usb_core_driver *)uhost->data; + + /* check for host port events */ + if (((0U == udev->host.connect_status) || (0U == udev->host.port_enabled)) && (HOST_DEFAULT != uhost->cur_state)) { + if (uhost->cur_state != HOST_DEV_DETACHED) { + uhost->cur_state = HOST_DEV_DETACHED; + } + } + + switch (uhost->cur_state) { + case HOST_DEFAULT: + if (udev->host.connect_status) { + uhost->cur_state = HOST_DETECT_DEV_SPEED; + + usb_mdelay (100U); + + usb_port_reset (udev); + + uhost->usr_cb->dev_reset(); + } + break; + + case HOST_DETECT_DEV_SPEED: + if (udev->host.port_enabled) { + uhost->cur_state = HOST_DEV_ATTACHED; + + uhost->dev_prop.speed = usb_curspeed_get (udev); + + uhost->usr_cb->dev_speed_detected(uhost->dev_prop.speed); + + usb_mdelay (50U); + } + break; + + case HOST_DEV_ATTACHED: + uhost->usr_cb->dev_attach(); + uhost->control.pipe_out_num = usbh_pipe_allocate(udev, 0x00U); + uhost->control.pipe_in_num = usbh_pipe_allocate(udev, 0x80U); + + /* open IN control pipe */ + usbh_pipe_create (udev, + &uhost->dev_prop, + uhost->control.pipe_in_num, + USB_EPTYPE_CTRL, + (uint16_t)uhost->control.max_len); + + /* open OUT control pipe */ + usbh_pipe_create (udev, + &uhost->dev_prop, + uhost->control.pipe_out_num, + USB_EPTYPE_CTRL, + (uint16_t)uhost->control.max_len); + + uhost->cur_state = HOST_ENUM; + break; + + case HOST_ENUM: + /* check for enumeration status */ + if (USBH_OK == usbh_enum_task (uhost)) { + /* the function shall return USBH_OK when full enumeration is complete */ + + /* user callback for end of device basic enumeration */ + uhost->usr_cb->dev_enumerated(); + +#ifdef USB_LOW_PWR_ENABLE + uhost->cur_state = HOST_SUSPENDED; +#else + uhost->cur_state = HOST_SET_WAKEUP_FEATURE; +#endif + } + break; + + case HOST_SET_WAKEUP_FEATURE: + if ((uhost->dev_prop.cfg_desc_set.cfg_desc.bmAttributes) & (1U << 5)) { + if (usbh_setdevfeature(uhost, FEATURE_SELECTOR_REMOTEWAKEUP, 0U) == USBH_OK) { + uhost->cur_state = HOST_CHECK_CLASS; + } + } else { + uhost->cur_state = HOST_CHECK_CLASS; + } + break; + + case HOST_CHECK_CLASS: + if (0U == uhost->class_num) { + uhost->cur_state = HOST_ERROR; + } else { + uhost->active_class = NULL; + + uint8_t itf_class = uhost->dev_prop.cfg_desc_set.itf_desc_set[0][0].itf_desc.bInterfaceClass; + + for (uint8_t index = 0U; index < uhost->class_num; index++) { + if ((uhost->uclass[index]->class_code == itf_class) || (0xFFU == itf_class)) { + uhost->active_class = uhost->uclass[index]; + } + } + + if (uhost->active_class != NULL) { + uhost->cur_state = HOST_USER_INPUT; + } else { + uhost->cur_state = HOST_ERROR; + } + } + break; + + case HOST_USER_INPUT: + /* the function should return user response true to move to class state */ + if (USBH_USER_RESP_OK == uhost->usr_cb->dev_user_input()) { + if ((USBH_OK == uhost->active_class->class_init(uhost))) { + uhost->cur_state = HOST_CLASS_ENUM; + } + } + break; + +#ifdef USB_LOW_PWR_ENABLE + case HOST_SUSPENDED: + if (USBH_OK == usbh_setdevfeature(uhost, FEATURE_SELECTOR_DEV, 0U)) { + uhost->suspend_flag = 1; + usb_hwp_suspend(uhost->data); + uhost->usr_cb->dev_user_input(); + pmu_to_deepsleepmode(PMU_LDO_LOWPOWER, WFI_CMD); + uhost->cur_state = HOST_WAKEUP; + } + break; + + case HOST_WAKEUP: + if (USBH_OK == usbh_clrdevfeature(uhost, FEATURE_SELECTOR_DEV, 0U)) { + /* user callback for initialization */ + uhost->usr_cb->dev_init(); + + uhost->cur_state = HOST_CHECK_CLASS; + } + break; +#endif + + case HOST_CLASS_ENUM: + /* process class standard control requests state machine */ + status = uhost->active_class->class_requests(uhost); + + if (USBH_OK == status) { + uhost->cur_state = HOST_CLASS_HANDLER; + } else { + usbh_error_handler (uhost, status); + } + break; + + case HOST_CLASS_HANDLER: + /* process class state machine */ + status = uhost->active_class->class_machine(uhost); + + usbh_error_handler (uhost, status); + break; + + case HOST_ERROR: + /* initialize host for new enumeration */ + usbh_deinit (uhost); + uhost->usr_cb->dev_deinit(); + uhost->active_class->class_deinit(uhost); + break; + + case HOST_DEV_DETACHED: + /* manage user disconnect operations*/ + uhost->usr_cb->dev_detach(); + + /* re-initialize host for new enumeration */ + usbh_deinit(uhost); + uhost->usr_cb->dev_deinit(); + uhost->active_class->class_deinit(uhost); + usbh_pipe_delete(udev); + uhost->cur_state = HOST_DEFAULT; + break; + + default: + break; + } +} + +/*! + \brief handle the error on USB host side + \param[in] uhost: pointer to USB host + \param[in] err_type: type of error or busy/OK state + \param[out] none + \retval none +*/ +void usbh_error_handler (usbh_host *uhost, usbh_status err_type) +{ + /* error unrecovered or not supported device speed */ + if ((USBH_SPEED_UNKNOWN_ERROR == err_type) || (USBH_UNRECOVERED_ERROR == err_type)) { + uhost->usr_cb->dev_error(); + + uhost->cur_state = HOST_ERROR; + } else if (USBH_APPLY_DEINIT == err_type) { + uhost->cur_state = HOST_ERROR; + + /* user callback for initialization */ + uhost->usr_cb->dev_init(); + } else { + /* no operation */ + } +} + +/*! + \brief USB SOF callback function from the interrupt + \param[in] uhost: pointer to USB host + \param[out] none + \retval operation status +*/ +static uint8_t usbh_sof (usbh_host *uhost) +{ + usb_core_driver *udev = (usb_core_driver *)uhost->data; + + /* this callback could be used to implement a scheduler process */ + uhost->control.timer = (uint16_t)usb_curframe_get(udev); + + if (uhost->active_class != NULL) { + if (uhost->active_class->class_sof != NULL) { + uhost->active_class->class_sof(uhost); + } + } + + return 0U; +} + +/*! + \brief USB connect callback function from the interrupt + \param[in] uhost: pointer to USB host + \param[out] none + \retval operation status +*/ +static uint8_t usbh_connect (usbh_host *uhost) +{ + usb_core_driver *udev = (usb_core_driver *)uhost->data; + udev->host.connect_status = 1U; + + return 0U; +} + +/*! + \brief USB disconnect callback function from the interrupt + \param[in] uhost: pointer to USB host + \param[out] none + \retval operation status +*/ +static uint8_t usbh_disconnect (usbh_host *uhost) +{ + usb_core_driver *udev = (usb_core_driver *)uhost->data; + udev->host.connect_status = 0U; + + return 0U; +} + +/*! + \brief USB port enable callback function from the interrupt + \param[in] uhost: pointer to USB host + \param[out] none + \retval operation status +*/ +static uint8_t usbh_port_enabled (usbh_host *uhost) +{ + usb_core_driver *udev = (usb_core_driver *)uhost->data; + udev->host.port_enabled = 1U; + + return 0U; +} + +/*! + \brief USB port disabled callback function from the interrupt + \param[in] uhost: pointer to USB host + \param[out] none + \retval operation status +*/ +static uint8_t usbh_port_disabled (usbh_host *uhost) +{ + usb_core_driver *udev = (usb_core_driver *)uhost->data; + udev->host.port_enabled = 0U; + + return 0U; +} + +/*! + \brief handle the USB enumeration task + \param[in] uhost: pointer to host + \param[out] none + \retval none +*/ +static usbh_status usbh_enum_task (usbh_host *uhost) +{ + uint8_t str_buf[64]; + usbh_status status = USBH_BUSY; + usb_core_driver *udev = (usb_core_driver *)uhost->data; + + static uint8_t index_mfc_str = 0U, index_prod_str = 0U, index_serial_str = 0U; + + switch (uhost->enum_state) { + case ENUM_DEFAULT: + /* get device descriptor for only 1st 8 bytes : to get ep0 max packet size */ + if (USBH_OK == usbh_devdesc_get (uhost, 8U)) { + uhost->control.max_len = uhost->dev_prop.dev_desc.bMaxPacketSize0; + + /* modify control channels configuration for maximum packet size */ + usbh_pipe_update (udev, + uhost->control.pipe_out_num, + 0U, 0U, + (uint16_t)uhost->control.max_len); + + usbh_pipe_update (udev, + uhost->control.pipe_in_num, + 0U, 0U, + (uint16_t)uhost->control.max_len); + + uhost->enum_state = ENUM_GET_DEV_DESC; + } + break; + + case ENUM_GET_DEV_DESC: + /* get full device descriptor */ + if (USBH_OK == usbh_devdesc_get (uhost, USB_DEV_DESC_LEN)) { + uhost->usr_cb->dev_devdesc_assigned(&uhost->dev_prop.dev_desc); + + index_mfc_str = uhost->dev_prop.dev_desc.iManufacturer; + index_prod_str = uhost->dev_prop.dev_desc.iProduct; + index_serial_str = uhost->dev_prop.dev_desc.iSerialNumber; + + uhost->enum_state = ENUM_SET_ADDR; + } + break; + + case ENUM_SET_ADDR: + /* set address */ + if (USBH_OK == usbh_setaddress (uhost, USBH_DEV_ADDR)) { + usb_mdelay (2U); + + uhost->dev_prop.addr = USBH_DEV_ADDR; + + /* user callback for device address assigned */ + uhost->usr_cb->dev_address_set(); + + /* modify control channels to update device address */ + usbh_pipe_update (udev, + uhost->control.pipe_in_num, + uhost->dev_prop.addr, + 0U, 0U); + + usbh_pipe_update (udev, + uhost->control.pipe_out_num, + uhost->dev_prop.addr, + 0U, 0U); + + uhost->enum_state = ENUM_GET_CFG_DESC; + } + break; + + case ENUM_GET_CFG_DESC: + /* get standard configuration descriptor */ + if (USBH_OK == usbh_cfgdesc_get (uhost, USB_CFG_DESC_LEN)) { + uhost->enum_state = ENUM_GET_CFG_DESC_SET; + } + break; + + case ENUM_GET_CFG_DESC_SET: + /* get full configure descriptor (config, interface, endpoints) */ + if (USBH_OK == usbh_cfgdesc_get (uhost, uhost->dev_prop.cfg_desc_set.cfg_desc.wTotalLength)) { + /* user callback for configuration descriptors available */ + uhost->usr_cb->dev_cfgdesc_assigned (&uhost->dev_prop.cfg_desc_set.cfg_desc, + &uhost->dev_prop.cfg_desc_set.itf_desc_set[0][0].itf_desc, + &uhost->dev_prop.cfg_desc_set.itf_desc_set[0][0].ep_desc[0]); + + uhost->enum_state = ENUM_GET_STR_DESC; + } + break; + + case ENUM_GET_STR_DESC: + if (index_mfc_str) { + if (USBH_OK == usbh_strdesc_get (uhost, + uhost->dev_prop.dev_desc.iManufacturer, + str_buf, + 0xFFU)) { + /* user callback for manufacturing string */ + uhost->usr_cb->dev_mfc_str(str_buf); + + index_mfc_str = 0U; + } + } else { + if (index_prod_str) { + /* check that product string is available */ + if (USBH_OK == usbh_strdesc_get (uhost, + uhost->dev_prop.dev_desc.iProduct, + str_buf, + 0xFFU)) { + uhost->usr_cb->dev_prod_str(str_buf); + + index_prod_str = 0U; + } + } else { + if (index_serial_str) { + if (USBH_OK == usbh_strdesc_get (uhost, + uhost->dev_prop.dev_desc.iSerialNumber, + str_buf, + 0xFFU)) { + uhost->usr_cb->dev_seral_str(str_buf); + uhost->enum_state = ENUM_SET_CONFIGURATION; + index_serial_str = 0U; + } + } else { + uhost->enum_state = ENUM_SET_CONFIGURATION; + } + } + } + break; + + case ENUM_SET_CONFIGURATION: + if (USBH_OK == usbh_setcfg (uhost, (uint16_t)uhost->dev_prop.cfg_desc_set.cfg_desc.bConfigurationValue)) { + uhost->enum_state = ENUM_DEV_CONFIGURED; + } + break; + + case ENUM_DEV_CONFIGURED: + status = USBH_OK; + break; + + default: + break; + } + + return status; +} + +#ifdef USB_LOW_PWR_ENABLE + +/*! + \brief handles the USB resume from suspend mode + \param[in] udev: pointer to selected USB device + \param[out] none + \retval none +*/ +void usb_hwp_resume(usb_core_driver *udev) +{ + __IO uint32_t hprt = 0U; + + /* switch-on the clocks */ + *udev->regs.PWRCLKCTL &= ~PWRCLKCTL_SUCLK; + + *udev->regs.PWRCLKCTL &= ~PWRCLKCTL_SHCLK; + + hprt = usb_port_read(udev); + + hprt &= ~HPCS_PSP; + hprt |= HPCS_PREM; + + *udev->regs.HPCS = hprt; + + usb_mdelay (20U); + + hprt &= ~HPCS_PREM; + + *udev->regs.HPCS = hprt; +} + +/*! + \brief handles the USB enter to suspend mode + \param[in] udev: pointer to selected USB device + \param[out] none + \retval none +*/ +static void usb_hwp_suspend(usb_core_driver *udev) +{ + __IO uint32_t hprt = 0U; + + hprt = usb_port_read(udev); + + hprt |= HPCS_PSP; + + *udev->regs.HPCS = hprt; + + /* switch-off the clocks */ + *udev->regs.PWRCLKCTL |= PWRCLKCTL_SUCLK; + + *udev->regs.PWRCLKCTL |= PWRCLKCTL_SHCLK; +} + +#endif /* USB_LOW_PWR_ENABLE */ diff --git a/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/host/core/Source/usbh_enum.c b/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/host/core/Source/usbh_enum.c new file mode 100644 index 0000000000..7966d8a9ac --- /dev/null +++ b/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/host/core/Source/usbh_enum.c @@ -0,0 +1,693 @@ +/*! + \file usbh_enum.c + \brief USB host mode enumeration driver + + \version 2020-08-01, V3.0.0, firmware for GD32F4xx +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "usbh_pipe.h" +#include "usbh_transc.h" +#include "usbh_enum.h" + +/* local function prototypes ('static') */ +static void usbh_devdesc_parse (usb_desc_dev *dev_desc, uint8_t *buf, uint16_t len); +static void usbh_cfgdesc_parse (usb_desc_config *cfg_desc, uint8_t *buf); +static void usbh_cfgset_parse (usb_dev_prop *udev, uint8_t *buf); +static void usbh_itfdesc_parse (usb_desc_itf *itf_desc, uint8_t *buf); +static void usbh_epdesc_parse (usb_desc_ep *ep_desc, uint8_t *buf); +static void usbh_strdesc_parse (uint8_t *psrc, uint8_t *pdest, uint16_t len); + +/*! + \brief configure USB control status parameters + \param[in] uhost: pointer to USB host + \param[in] buf: control transfer data buffer pointer + \param[in] len: length of the data buffer + \param[out] none + \retval none +*/ +void usbh_ctlstate_config (usbh_host *uhost, uint8_t *buf, uint16_t len) +{ + /* prepare the transactions */ + uhost->control.buf = buf; + uhost->control.ctl_len = len; + + uhost->control.ctl_state = CTL_SETUP; +} + +/*! + \brief get device descriptor from the USB device + \param[in] uhost: pointer to USB host + \param[in] len: length of the descriptor + \param[out] none + \retval operation status +*/ +usbh_status usbh_devdesc_get (usbh_host *uhost, uint8_t len) +{ + usbh_status status = USBH_BUSY; + + usbh_control *usb_ctl = &uhost->control; + + if (CTL_IDLE == usb_ctl->ctl_state) { + usb_ctl->setup.req = (usb_req) { + .bmRequestType = USB_TRX_IN | USB_RECPTYPE_DEV | USB_REQTYPE_STRD, + .bRequest = USB_GET_DESCRIPTOR, + .wValue = USBH_DESC(USB_DESCTYPE_DEV), + .wIndex = 0U, + .wLength = len + }; + + usbh_ctlstate_config (uhost, uhost->dev_prop.data, (uint16_t)len); + } + + status = usbh_ctl_handler (uhost); + + if (USBH_OK == status) { + /* commands successfully sent and response received */ + usbh_devdesc_parse (&uhost->dev_prop.dev_desc, uhost->dev_prop.data, (uint16_t)len); + } + + return status; +} + +/*! + \brief get configuration descriptor from the USB device + \param[in] uhost: pointer to USB host + \param[in] len: length of the descriptor + \param[out] none + \retval operation status +*/ +usbh_status usbh_cfgdesc_get (usbh_host *uhost, uint16_t len) +{ + uint8_t *pdata = NULL; + + usbh_status status = USBH_BUSY; + + usbh_control *usb_ctl = &uhost->control; + +#if (USBH_KEEP_CFG_DESCRIPTOR == 1U) + pdata = uhost->dev_prop.cfgdesc_rawdata; +#else + pdata = uhost->dev_prop.data; +#endif + + if (CTL_IDLE == usb_ctl->ctl_state) { + usb_ctl->setup.req = (usb_req) { + .bmRequestType = USB_TRX_IN | USB_RECPTYPE_DEV | USB_REQTYPE_STRD, + .bRequest = USB_GET_DESCRIPTOR, + .wValue = USBH_DESC(USB_DESCTYPE_CONFIG), + .wIndex = 0U, + .wLength = len + }; + + usbh_ctlstate_config (uhost, pdata, len); + } + + status = usbh_ctl_handler (uhost); + + if (USBH_OK == status) { + if (len <= USB_CFG_DESC_LEN) { + usbh_cfgdesc_parse (&uhost->dev_prop.cfg_desc_set.cfg_desc, pdata); + } else { + usbh_cfgset_parse (&uhost->dev_prop, pdata); + } + } + + return status; +} + +/*! + \brief get string descriptor from the USB device + \param[in] uhost: pointer to USB host + \param[in] str_index: index for the string descriptor + \param[in] buf: buffer pointer to the string descriptor + \param[in] len: length of the descriptor + \param[out] none + \retval operation status +*/ +usbh_status usbh_strdesc_get (usbh_host *uhost, + uint8_t str_index, + uint8_t *buf, + uint16_t len) +{ + usbh_status status = USBH_BUSY; + + usbh_control *usb_ctl = &uhost->control; + + if (CTL_IDLE == usb_ctl->ctl_state) { + usb_ctl->setup.req = (usb_req) { + .bmRequestType = USB_TRX_IN | USB_RECPTYPE_DEV | USB_REQTYPE_STRD, + .bRequest = USB_GET_DESCRIPTOR, + .wValue = USBH_DESC(USB_DESCTYPE_STR) | str_index, + .wIndex = 0x0409U, + .wLength = len + }; + + usbh_ctlstate_config (uhost, uhost->dev_prop.data, len); + } + + status = usbh_ctl_handler (uhost); + + if (USBH_OK == status) { + /* commands successfully sent and response received */ + usbh_strdesc_parse (uhost->dev_prop.data, buf, len); + } + + return status; +} + +/*! + \brief set the address to the connected device + \param[in] uhost: pointer to USB host + \param[in] dev_addr: device address to assign + \param[out] none + \retval operation status +*/ +usbh_status usbh_setaddress (usbh_host *uhost, uint8_t dev_addr) +{ + usbh_status status = USBH_BUSY; + + usbh_control *usb_ctl = &uhost->control; + + if (CTL_IDLE == usb_ctl->ctl_state) { + usb_ctl->setup.req = (usb_req) { + .bmRequestType = USB_TRX_OUT | USB_RECPTYPE_DEV | USB_REQTYPE_STRD, + .bRequest = USB_SET_ADDRESS, + .wValue = (uint16_t)dev_addr, + .wIndex = 0U, + .wLength = 0U + }; + + usbh_ctlstate_config (uhost, NULL, 0U); + } + + status = usbh_ctl_handler (uhost); + + return status; +} + +/*! + \brief set the configuration value to the connected device + \param[in] uhost: pointer to USB host + \param[in] config_index: configuration value + \param[out] none + \retval operation status +*/ +usbh_status usbh_setcfg (usbh_host *uhost, uint16_t config_index) +{ + usbh_status status = USBH_BUSY; + + usbh_control *usb_ctl = &uhost->control; + + if (CTL_IDLE == usb_ctl->ctl_state) { + usb_ctl->setup.req = (usb_req) { + .bmRequestType = USB_TRX_OUT | USB_RECPTYPE_DEV | USB_REQTYPE_STRD, + .bRequest = USB_SET_CONFIGURATION, + .wValue = config_index, + .wIndex = 0U, + .wLength = 0U + }; + + usbh_ctlstate_config (uhost, NULL, 0U); + } + + status = usbh_ctl_handler (uhost); + + return status; +} + +/*! + \brief set the interface value to the connected device + \param[in] uhost: pointer to USB host + \param[in] itf_num: interface number + \param[in] set: alternated setting value + \param[out] none + \retval operation status +*/ +usbh_status usbh_setinterface (usbh_host *uhost, uint8_t itf_num, uint8_t set) +{ + usbh_status status = USBH_BUSY; + + usbh_control *usb_ctl = &uhost->control; + + if (CTL_IDLE == usb_ctl->ctl_state) { + usb_ctl->setup.req = (usb_req) { + .bmRequestType = USB_TRX_OUT | USB_RECPTYPE_ITF | USB_REQTYPE_STRD, + .bRequest = USB_SET_INTERFACE, + .wValue = set, + .wIndex = itf_num, + .wLength = 0U + }; + + usbh_ctlstate_config (uhost, NULL, 0U); + } + + status = usbh_ctl_handler (uhost); + + return status; +} + +/*! + \brief set the interface value to the connected device + \param[in] uhost: pointer to USB host + \param[in] feature_selector: feature selector + \param[in] windex: index value + \param[out] none + \retval operation status +*/ +usbh_status usbh_setdevfeature (usbh_host *uhost, uint8_t feature_selector, uint16_t windex) +{ + usbh_status status = USBH_BUSY; + + usbh_control *usb_ctl = &uhost->control; + + if (CTL_IDLE == usb_ctl->ctl_state) { + usb_ctl->setup.req = (usb_req) { + .bmRequestType = USB_TRX_OUT | USB_RECPTYPE_DEV | USB_REQTYPE_STRD, + .bRequest = USB_SET_FEATURE, + .wValue = feature_selector, + .wIndex = windex, + .wLength = 0U + }; + + usbh_ctlstate_config (uhost, NULL, 0U); + } + + status = usbh_ctl_handler (uhost); + + return status; +} + +/*! + \brief clear the interface value to the connected device + \param[in] uhost: pointer to USB host + \param[in] feature_selector: feature selector + \param[in] windex: index value + \param[out] none + \retval operation status +*/ +usbh_status usbh_clrdevfeature (usbh_host *uhost, uint8_t feature_selector, uint16_t windex) +{ + usbh_status status = USBH_BUSY; + + usbh_control *usb_ctl = &uhost->control; + + if (CTL_IDLE == usb_ctl->ctl_state) { + usb_ctl->setup.req = (usb_req) { + .bmRequestType = USB_TRX_OUT | USB_RECPTYPE_DEV | USB_REQTYPE_STRD, + .bRequest = USB_CLEAR_FEATURE, + .wValue = feature_selector, + .wIndex = windex, + .wLength = 0U + }; + + usbh_ctlstate_config (uhost, NULL, 0U); + } + + status = usbh_ctl_handler (uhost); + + return status; +} + +/*! + \brief clear or disable a specific feature + \param[in] uhost: pointer to USB host + \param[in] ep_addr: endpoint address + \param[in] pp_num: pipe number + \param[out] none + \retval operation status +*/ +usbh_status usbh_clrfeature (usbh_host *uhost, uint8_t ep_addr, uint8_t pp_num) +{ + usbh_status status = USBH_BUSY; + usbh_control *usb_ctl = &uhost->control; + usb_core_driver *udev = (usb_core_driver *)uhost->data; + + if (CTL_IDLE == usb_ctl->ctl_state) { + usb_ctl->setup.req = (usb_req) { + .bmRequestType = USB_TRX_OUT | USB_RECPTYPE_EP | USB_REQTYPE_STRD, + .bRequest = USB_CLEAR_FEATURE, + .wValue = FEATURE_SELECTOR_EP, + .wIndex = ep_addr, + .wLength = 0U + }; + + if (EP_ID(ep_addr) == udev->host.pipe[pp_num].ep.num) { + usbh_pipe_toggle_set(udev, pp_num, 0U); + } else { + return USBH_FAIL; + } + + usbh_ctlstate_config (uhost, NULL, 0U); + } + + status = usbh_ctl_handler (uhost); + + return status; +} + +/*! + \brief get the next descriptor header + \param[in] pbuf: pointer to buffer where the configuration descriptor set is available + \param[in] ptr: data pointer inside the configuration descriptor set + \param[out] none + \retval return descriptor header +*/ +usb_desc_header *usbh_nextdesc_get (uint8_t *pbuf, uint16_t *ptr) +{ + usb_desc_header *pnext; + + *ptr += ((usb_desc_header *)pbuf)->bLength; + + pnext = (usb_desc_header *)((uint8_t *)pbuf + ((usb_desc_header *)pbuf)->bLength); + + return (pnext); +} + +/*! + \brief get the next descriptor header + \param[in] udev: pointer to device property + \param[in] interface: interface number + \param[out] none + \retval operation status +*/ +usbh_status usbh_interface_select (usb_dev_prop *udev, uint8_t interface) +{ + usbh_status status = USBH_OK; + + if (interface < udev->cfg_desc_set.cfg_desc.bNumInterfaces) { + udev->cur_itf = interface; + } else { + status = USBH_FAIL; + } + + return status; +} + +/*! + \brief find the interface index for a specific class + \param[in] udev: pointer to device property + \param[in] main_class: class code + \param[in] sub_class: subclass code + \param[in] protocol: Protocol code + \param[out] none + \retval interface index in the configuration structure + \note interface index 0xFF means interface index not found +*/ +uint8_t usbh_interface_find (usb_dev_prop *udev, uint8_t main_class, uint8_t sub_class, uint8_t protocol) +{ + usb_desc_itf *pif; + + uint8_t if_ix = 0U; + + pif = (usb_desc_itf *)0; + + while (if_ix < udev->cfg_desc_set.cfg_desc.bNumInterfaces) { + pif = &udev->cfg_desc_set.itf_desc_set[if_ix][0].itf_desc; + + if (((pif->bInterfaceClass == main_class) || (main_class == 0xFFU))&& + ((pif->bInterfaceSubClass == sub_class) || (sub_class == 0xFFU))&& + ((pif->bInterfaceProtocol == protocol) || (protocol == 0xFFU))) { + return if_ix; + } + + if_ix++; + } + + return 0xFFU; +} + +/*! + \brief find the interface index for a specific class interface and alternate setting number + \param[in] udev: pointer to device property + \param[in] interface_number: interface number + \param[in] alt_settings: alternate setting number + \param[out] none + \retval interface index in the configuration structure + \note interface index 0xFF means interface index not found +*/ +uint8_t usbh_interfaceindex_find (usb_dev_prop *udev, uint8_t interface_number, uint8_t alt_settings) +{ + usb_desc_itf *pif; + + uint8_t if_ix = 0U; + + pif = (usb_desc_itf *)0; + + while (if_ix < USBH_MAX_INTERFACES_NUM) { + pif = &udev->cfg_desc_set.itf_desc_set[if_ix][alt_settings].itf_desc; + + if ((pif->bInterfaceNumber == interface_number) && (pif->bAlternateSetting == alt_settings)) { + return if_ix; + } + + if_ix++; + } + + return 0xFFU; +} + +/*! + \brief parse the device descriptor + \param[in] dev_desc: pointer to USB device descriptor buffer + \param[in] buf: pointer to the source descriptor buffer + \param[in] len: length of the descriptor + \param[out] none + \retval none +*/ +static void usbh_devdesc_parse (usb_desc_dev *dev_desc, uint8_t *buf, uint16_t len) +{ + *dev_desc = (usb_desc_dev) { + .header = { + .bLength = *(uint8_t *)(buf + 0U), + .bDescriptorType = *(uint8_t *)(buf + 1U) + }, + + .bcdUSB = BYTE_SWAP(buf + 2U), + .bDeviceClass = *(uint8_t *)(buf + 4U), + .bDeviceSubClass = *(uint8_t *)(buf + 5U), + .bDeviceProtocol = *(uint8_t *)(buf + 6U), + .bMaxPacketSize0 = *(uint8_t *)(buf + 7U) + }; + + if (len > 8U) { + /* for 1st time after device connection, host may issue only 8 bytes for device descriptor length */ + dev_desc->idVendor = BYTE_SWAP(buf + 8U); + dev_desc->idProduct = BYTE_SWAP(buf + 10U); + dev_desc->bcdDevice = BYTE_SWAP(buf + 12U); + dev_desc->iManufacturer = *(uint8_t *)(buf + 14U); + dev_desc->iProduct = *(uint8_t *)(buf + 15U); + dev_desc->iSerialNumber = *(uint8_t *)(buf + 16U); + dev_desc->bNumberConfigurations = *(uint8_t *)(buf + 17U); + } +} + +/*! + \brief parse the configuration descriptor + \param[in] cfg_desc: pointer to USB configuration descriptor buffer + \param[in] buf: pointer to the source descriptor buffer + \param[out] none + \retval none +*/ +static void usbh_cfgdesc_parse (usb_desc_config *cfg_desc, uint8_t *buf) +{ + /* parse configuration descriptor */ + *cfg_desc = (usb_desc_config) { + .header = { + .bLength = *(uint8_t *)(buf + 0U), + .bDescriptorType = *(uint8_t *)(buf + 1U), + }, + + .wTotalLength = BYTE_SWAP(buf + 2U), + .bNumInterfaces = *(uint8_t *)(buf + 4U), + .bConfigurationValue = *(uint8_t *)(buf + 5U), + .iConfiguration = *(uint8_t *)(buf + 6U), + .bmAttributes = *(uint8_t *)(buf + 7U), + .bMaxPower = *(uint8_t *)(buf + 8U) + }; +} + +/*! + \brief parse the configuration descriptor set + \param[in] udev: pointer to device property + \param[in] buf: pointer to the source descriptor buffer + \param[out] none + \retval none +*/ +static void usbh_cfgset_parse (usb_dev_prop *udev, uint8_t *buf) +{ + usb_desc_ep *ep = NULL; + usb_desc_itf_set *itf = NULL; + usb_desc_itf itf_value; + usb_desc_config *cfg = NULL; + + usb_desc_header *pdesc = (usb_desc_header *)buf; + + uint8_t itf_index = 0U, ep_index = 0U, alt_setting = 0U; + uint8_t pre_itf_index = 0U; + uint16_t ptr; + + /* parse configuration descriptor */ + usbh_cfgdesc_parse (&udev->cfg_desc_set.cfg_desc, buf); + cfg = &udev->cfg_desc_set.cfg_desc; + ptr = USB_CFG_DESC_LEN; + + if (cfg->bNumInterfaces > USBH_MAX_INTERFACES_NUM) { + return; + } + + while (ptr < cfg->wTotalLength) { + pdesc = usbh_nextdesc_get ((uint8_t *)pdesc, &ptr); + + if (pdesc->bDescriptorType == USB_DESCTYPE_ITF) { + itf_index = *(((uint8_t *)pdesc) + 2U); + + if (pre_itf_index != itf_index) { + alt_setting = 0U; + } + + itf = &udev->cfg_desc_set.itf_desc_set[itf_index][alt_setting]; + + alt_setting++; + + if ((*((uint8_t *)pdesc + 3U)) < 3U) { + usbh_itfdesc_parse (&itf_value, (uint8_t *)pdesc); + + /* parse endpoint descriptors relative to the current interface */ + if (itf_value.bNumEndpoints > USBH_MAX_EP_NUM) { + return; + } + + usbh_itfdesc_parse (&itf->itf_desc, (uint8_t *)&itf_value); + + /* store the previous interface index */ + pre_itf_index = itf_index; + + if (0U == itf_value.bNumEndpoints) { + continue; + } + + for (ep_index = 0U; ep_index < itf_value.bNumEndpoints; ) { + pdesc = usbh_nextdesc_get ((void*)pdesc, &ptr); + + if (pdesc->bDescriptorType == USB_DESCTYPE_EP) { + ep = &itf->ep_desc[ep_index]; + + usbh_epdesc_parse (ep, (uint8_t *)pdesc); + + ep_index++; + } + } + } + } + } +} + +/*! + \brief parse the interface descriptor + \param[in] itf_desc: pointer to USB interface descriptor buffer + \param[in] buf: pointer to the source descriptor buffer + \param[out] none + \retval none +*/ +static void usbh_itfdesc_parse (usb_desc_itf *itf_desc, uint8_t *buf) +{ + *itf_desc = (usb_desc_itf) { + .header = { + .bLength = *(uint8_t *)(buf + 0U), + .bDescriptorType = *(uint8_t *)(buf + 1U), + }, + + .bInterfaceNumber = *(uint8_t *)(buf + 2U), + .bAlternateSetting = *(uint8_t *)(buf + 3U), + .bNumEndpoints = *(uint8_t *)(buf + 4U), + .bInterfaceClass = *(uint8_t *)(buf + 5U), + .bInterfaceSubClass = *(uint8_t *)(buf + 6U), + .bInterfaceProtocol = *(uint8_t *)(buf + 7U), + .iInterface = *(uint8_t *)(buf + 8U) + }; +} + +/*! + \brief parse the endpoint descriptor + \param[in] ep_desc: pointer to USB endpoint descriptor buffer + \param[in] buf: pointer to the source descriptor buffer + \param[out] none + \retval none +*/ +static void usbh_epdesc_parse (usb_desc_ep *ep_desc, uint8_t *buf) +{ + *ep_desc = (usb_desc_ep) { + .header = { + .bLength = *(uint8_t *)(buf + 0U), + .bDescriptorType = *(uint8_t *)(buf + 1U) + }, + + .bEndpointAddress = *(uint8_t *)(buf + 2U), + .bmAttributes = *(uint8_t *)(buf + 3U), + .wMaxPacketSize = BYTE_SWAP(buf + 4U), + .bInterval = *(uint8_t *)(buf + 6U) + }; +} + +/*! + \brief parse the string descriptor + \param[in] psrc: source pointer containing the descriptor data + \param[in] pdest: destination address pointer + \param[in] len: length of the descriptor + \param[out] none + \retval none +*/ +static void usbh_strdesc_parse (uint8_t *psrc, uint8_t *pdest, uint16_t len) +{ + uint16_t str_len = 0U, index = 0U; + + /* the unicode string descriptor is not NULL-terminated. The string length is + * computed by substracting two from the value of the first byte of the descriptor. + */ + + /* check which is lower size, the size of string or the length of bytes read from the device */ + if (USB_DESCTYPE_STR == psrc[1]) { + /* make sure the descriptor is string type */ + + /* psrc[0] contains Size of Descriptor, subtract 2 to get the length of string */ + str_len = USB_MIN((uint16_t)psrc[0] - 2U, len); + + psrc += 2U; /* adjust the offset ignoring the string len and descriptor type */ + + for (index = 0U; index < str_len; index += 2U) { + /* copy only the string and ignore the unicode id, hence add the src */ + *pdest = psrc[index]; + + pdest++; + } + + *pdest = 0U; /* mark end of string */ + } +} diff --git a/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/host/core/Source/usbh_pipe.c b/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/host/core/Source/usbh_pipe.c new file mode 100644 index 0000000000..7d00be8d2a --- /dev/null +++ b/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/host/core/Source/usbh_pipe.c @@ -0,0 +1,174 @@ +/*! + \file usbh_pipe.c + \brief USB host mode pipe operation driver + + \version 2020-08-01, V3.0.0, firmware for GD32F4xx +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "usbh_pipe.h" + +/* local function prototypes ('static') */ +static uint16_t usbh_freepipe_get (usb_core_driver *udev); + +/*! + \brief create a pipe + \param[in] udev: pointer to USB core instance + \param[in] dev: USB device + \param[in] pp_num: pipe number + \param[in] ep_type: endpoint type + \param[in] ep_mpl: endpoint max packet length + \param[out] none + \retval operation status +*/ +uint8_t usbh_pipe_create (usb_core_driver *udev, + usb_dev_prop *dev, + uint8_t pp_num, + uint8_t ep_type, + uint16_t ep_mpl) +{ + usb_pipe *pp = &udev->host.pipe[pp_num]; + + pp->dev_addr = dev->addr; + pp->dev_speed = dev->speed; + pp->ep.type = ep_type; + pp->ep.mps = ep_mpl; + pp->ping = (uint8_t)(dev->speed == PORT_SPEED_HIGH); + + usb_pipe_init (udev, pp_num); + + return HC_OK; +} + +/*! + \brief modify a pipe + \param[in] udev: pointer to USB core instance + \param[in] pp_num: pipe number + \param[in] dev_addr: device address + \param[in] dev_speed: device speed + \param[in] ep_mpl: endpoint max packet length + \param[out] none + \retval operation status +*/ +uint8_t usbh_pipe_update (usb_core_driver *udev, + uint8_t pp_num, + uint8_t dev_addr, + uint32_t dev_speed, + uint16_t ep_mpl) +{ + usb_pipe *pp = &udev->host.pipe[pp_num]; + + if ((pp->dev_addr != dev_addr) && (dev_addr)) { + pp->dev_addr = dev_addr; + } + + if ((pp->dev_speed != dev_speed) && (dev_speed)) { + pp->dev_speed = dev_speed; + } + + if ((pp->ep.mps != ep_mpl) && (ep_mpl)) { + pp->ep.mps = ep_mpl; + } + + usb_pipe_init (udev, pp_num); + + return HC_OK; +} + +/*! + \brief allocate a new pipe + \param[in] udev: pointer to USB core instance + \param[in] ep_addr: endpoint address + \param[out] none + \retval operation status +*/ +uint8_t usbh_pipe_allocate (usb_core_driver *udev, uint8_t ep_addr) +{ + uint16_t pp_num = usbh_freepipe_get (udev); + + if (HC_ERROR != pp_num) { + udev->host.pipe[pp_num].in_used = 1U; + udev->host.pipe[pp_num].ep.dir = EP_DIR(ep_addr); + udev->host.pipe[pp_num].ep.num = EP_ID(ep_addr); + } + + return (uint8_t)pp_num; +} + +/*! + \brief free a pipe + \param[in] udev: pointer to USB core instance + \param[in] pp_num: pipe number + \param[out] none + \retval operation status +*/ +uint8_t usbh_pipe_free (usb_core_driver *udev, uint8_t pp_num) +{ + if (pp_num < HC_MAX) { + udev->host.pipe[pp_num].in_used = 0U; + } + + return USBH_OK; +} + +/*! + \brief delete all USB host pipe + \param[in] udev: pointer to USB core instance + \param[out] none + \retval operation status +*/ +uint8_t usbh_pipe_delete (usb_core_driver *udev) +{ + uint8_t pp_num = 0U; + + for (pp_num = 2U; pp_num < HC_MAX; pp_num++) { + udev->host.pipe[pp_num] = (usb_pipe) {0}; + } + + return USBH_OK; +} + +/*! + \brief get a free pipe number for allocation + \param[in] udev: pointer to USB core instance + \param[out] none + \retval operation status +*/ +static uint16_t usbh_freepipe_get (usb_core_driver *udev) +{ + uint8_t pp_num = 0U; + + for (pp_num = 0U; pp_num < HC_MAX; pp_num++) { + if (0U == udev->host.pipe[pp_num].in_used) { + return (uint16_t)pp_num; + } + } + + return HC_ERROR; +} diff --git a/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/host/core/Source/usbh_transc.c b/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/host/core/Source/usbh_transc.c new file mode 100644 index 0000000000..63d6121350 --- /dev/null +++ b/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/host/core/Source/usbh_transc.c @@ -0,0 +1,370 @@ +/*! + \file usbh_transc.c + \brief USB host mode transactions driver + + \version 2020-08-01, V3.0.0, firmware for GD32F4xx +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "drv_usb_hw.h" +#include "usbh_pipe.h" +#include "usbh_transc.h" + +/* local function prototypes ('static') */ +static usb_urb_state usbh_urb_wait (usbh_host *uhost, uint8_t pp_num, uint32_t wait_time); +static void usbh_setup_transc (usbh_host *uhost); +static void usbh_data_in_transc (usbh_host *uhost); +static void usbh_data_out_transc (usbh_host *uhost); +static void usbh_status_in_transc (usbh_host *uhost); +static void usbh_status_out_transc (usbh_host *uhost); +static uint32_t usbh_request_submit (usb_core_driver *udev, uint8_t pp_num); + +/*! + \brief send the setup packet to the USB device + \param[in] udev: pointer to USB core instance + \param[in] buf: data buffer which will be sent to USB device + \param[in] pp_num: pipe number + \param[out] none + \retval operation status +*/ +usbh_status usbh_ctlsetup_send (usb_core_driver *udev, uint8_t *buf, uint8_t pp_num) +{ + usb_pipe *pp = &udev->host.pipe[pp_num]; + + pp->DPID = PIPE_DPID_SETUP; + pp->xfer_buf = buf; + pp->xfer_len = USB_SETUP_PACKET_LEN; + + return (usbh_status)usbh_request_submit (udev, pp_num); +} + +/*! + \brief send a data packet to the USB device + \param[in] udev: pointer to USB core instance + \param[in] buf: data buffer which will be sent to USB device + \param[in] pp_num: pipe number + \param[in] len: length of the data to be sent + \param[out] none + \retval operation status +*/ +usbh_status usbh_data_send (usb_core_driver *udev, uint8_t *buf, uint8_t pp_num, uint16_t len) +{ + usb_pipe *pp = &udev->host.pipe[pp_num]; + + pp->xfer_buf = buf; + pp->xfer_len = len; + + switch (pp->ep.type) { + case USB_EPTYPE_CTRL: + if (0U == len) { + pp->data_toggle_out = 1U; + } + + pp->DPID = PIPE_DPID[pp->data_toggle_out]; + break; + + case USB_EPTYPE_INTR: + pp->DPID = PIPE_DPID[pp->data_toggle_out]; + + pp->data_toggle_out ^= 1U; + break; + + case USB_EPTYPE_BULK: + pp->DPID = PIPE_DPID[pp->data_toggle_out]; + break; + + case USB_EPTYPE_ISOC: + pp->DPID = PIPE_DPID[0]; + break; + + default: + break; + } + + usbh_request_submit (udev, pp_num); + + return USBH_OK; +} + +/*! + \brief receive a data packet from the USB device + \param[in] udev: pointer to USB core instance + \param[in] buf: data buffer which will be received from USB device + \param[in] pp_num: pipe number + \param[in] len: length of the data to be received + \param[out] none + \retval operation status +*/ +usbh_status usbh_data_recev (usb_core_driver *udev, uint8_t *buf, uint8_t pp_num, uint16_t len) +{ + usb_pipe *pp = &udev->host.pipe[pp_num]; + + pp->xfer_buf = buf; + pp->xfer_len = len; + + switch (pp->ep.type) { + case USB_EPTYPE_CTRL: + pp->DPID = PIPE_DPID[1]; + break; + + case USB_EPTYPE_INTR: + pp->DPID = PIPE_DPID[pp->data_toggle_in]; + + /* Toggle DATA PID */ + pp->data_toggle_in ^= 1U; + break; + + case USB_EPTYPE_BULK: + pp->DPID = PIPE_DPID[pp->data_toggle_in]; + break; + + case USB_EPTYPE_ISOC: + pp->DPID = PIPE_DPID[0]; + break; + + default: + break; + } + + usbh_request_submit (udev, pp_num); + + return USBH_OK; +} + +/*! + \brief USB control transfer handler + \param[in] uhost: pointer to USB host + \param[out] none + \retval operation status +*/ +usbh_status usbh_ctl_handler (usbh_host *uhost) +{ + usbh_status status = USBH_BUSY; + + switch (uhost->control.ctl_state) { + case CTL_SETUP: + usbh_setup_transc (uhost); + break; + + case CTL_DATA_IN: + usbh_data_in_transc (uhost); + break; + + case CTL_DATA_OUT: + usbh_data_out_transc (uhost); + break; + + case CTL_STATUS_IN: + usbh_status_in_transc (uhost); + break; + + case CTL_STATUS_OUT: + usbh_status_out_transc (uhost); + break; + + case CTL_FINISH: + uhost->control.ctl_state = CTL_IDLE; + + status = USBH_OK; + break; + + case CTL_ERROR: + if (++uhost->control.error_count <= USBH_MAX_ERROR_COUNT) { + /* do the transmission again, starting from SETUP packet */ + uhost->control.ctl_state = CTL_SETUP; + } else { + status = USBH_FAIL; + } + break; + + default: + break; + } + + return status; +} + +/*! + \brief wait for USB URB(USB request block) state + \param[in] uhost: pointer to USB host + \param[in] pp_num: pipe number + \param[in] wait_time: wait time + \param[out] none + \retval USB URB state +*/ +static usb_urb_state usbh_urb_wait (usbh_host *uhost, uint8_t pp_num, uint32_t wait_time) +{ + usb_urb_state urb_status = URB_IDLE; + + while (URB_DONE != (urb_status = usbh_urbstate_get(uhost->data, pp_num))) { + if (URB_NOTREADY == urb_status) { + break; + } else if (URB_STALL == urb_status) { + uhost->control.ctl_state = CTL_SETUP; + break; + } else if (URB_ERROR == urb_status) { + uhost->control.ctl_state = CTL_ERROR; + break; + } else if ((wait_time > 0U) && ((usb_curframe_get(uhost->data)- uhost->control.timer) > wait_time)) { + /* timeout for in transfer */ + uhost->control.ctl_state = CTL_ERROR; + break; + } else { + /* no operation, just wait */ + } + } + + return urb_status; +} + +/*! + \brief USB setup transaction + \param[in] uhost: pointer to USB host + \param[out] none + \retval none +*/ +static void usbh_setup_transc (usbh_host *uhost) +{ + /* send a SETUP packet */ + usbh_ctlsetup_send (uhost->data, + uhost->control.setup.data, + uhost->control.pipe_out_num); + + if (URB_DONE == usbh_urb_wait (uhost, uhost->control.pipe_out_num, 0U)) { + uint8_t dir = (uhost->control.setup.req.bmRequestType & USB_TRX_MASK); + + if (uhost->control.setup.req.wLength) { + if (USB_TRX_IN == dir) { + uhost->control.ctl_state = CTL_DATA_IN; + } else { + uhost->control.ctl_state = CTL_DATA_OUT; + } + } else { + if (USB_TRX_IN == dir) { + uhost->control.ctl_state = CTL_STATUS_OUT; + } else { + uhost->control.ctl_state = CTL_STATUS_IN; + } + } + + /* set the delay timer to enable timeout for data stage completion */ + uhost->control.timer = (uint16_t)usb_curframe_get(uhost->data); + } +} + +/*! + \brief USB data IN transaction + \param[in] uhost: pointer to USB host + \param[out] none + \retval none +*/ +static void usbh_data_in_transc (usbh_host *uhost) +{ + usbh_data_recev (uhost->data, + uhost->control.buf, + uhost->control.pipe_in_num, + uhost->control.ctl_len); + + if (URB_DONE == usbh_urb_wait (uhost, uhost->control.pipe_in_num, DATA_STAGE_TIMEOUT)) { + uhost->control.ctl_state = CTL_STATUS_OUT; + + uhost->control.timer = (uint16_t)usb_curframe_get(uhost->data); + } +} + +/*! + \brief USB data OUT transaction + \param[in] uhost: pointer to USB host + \param[out] none + \retval none +*/ +static void usbh_data_out_transc (usbh_host *uhost) +{ + usbh_pipe_toggle_set(uhost->data, uhost->control.pipe_out_num, 1U); + + usbh_data_send (uhost->data, + uhost->control.buf, + uhost->control.pipe_out_num, + uhost->control.ctl_len); + + if (URB_DONE == usbh_urb_wait (uhost, uhost->control.pipe_out_num, DATA_STAGE_TIMEOUT)) { + uhost->control.ctl_state = CTL_STATUS_IN; + + uhost->control.timer = (uint16_t)usb_curframe_get(uhost->data); + } +} + +/*! + \brief USB status IN transaction + \param[in] uhost: pointer to USB host + \param[out] none + \retval none +*/ +static void usbh_status_in_transc (usbh_host *uhost) +{ + uint8_t pp_num = uhost->control.pipe_in_num; + + usbh_data_recev (uhost->data, NULL, pp_num, 0U); + + if (URB_DONE == usbh_urb_wait (uhost, pp_num, NODATA_STAGE_TIMEOUT)) { + uhost->control.ctl_state = CTL_FINISH; + } +} + +/*! + \brief USB status OUT transaction + \param[in] uhost: pointer to USB host + \param[out] none + \retval none +*/ +static void usbh_status_out_transc (usbh_host *uhost) +{ + uint8_t pp_num = uhost->control.pipe_out_num; + + usbh_data_send (uhost->data, NULL, pp_num, 0U); + + if (URB_DONE == usbh_urb_wait (uhost, pp_num, NODATA_STAGE_TIMEOUT)) { + uhost->control.ctl_state = CTL_FINISH; + } +} + +/*! + \brief prepare a pipe and start a transfer + \param[in] udev: pointer to USB core instance + \param[in] pp_num: pipe number + \param[out] none + \retval operation status +*/ +static uint32_t usbh_request_submit (usb_core_driver *udev, uint8_t pp_num) +{ + udev->host.pipe[pp_num].urb_state = URB_IDLE; + udev->host.pipe[pp_num].xfer_count = 0U; + + return (uint32_t)usb_pipe_xfer (udev, pp_num); +} diff --git a/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/ustd/class/cdc/usb_cdc.h b/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/ustd/class/cdc/usb_cdc.h new file mode 100644 index 0000000000..df3e56538d --- /dev/null +++ b/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/ustd/class/cdc/usb_cdc.h @@ -0,0 +1,180 @@ +/*! + \file usb_cdc.h + \brief the header file of communication device class standard + + \version 2020-08-01, V3.0.0, firmware for GD32F4xx +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef __USB_CDC_H +#define __USB_CDC_H + +#include "usb_ch9_std.h" + +/* communications device class code */ +#define USB_CLASS_CDC 0x02U + +/* communications interface class control protocol codes */ +#define USB_CDC_PROTOCOL_NONE 0x00U +#define USB_CDC_PROTOCOL_AT 0x01U +#define USB_CDC_PROTOCOL_VENDOR 0xFFU + +/* data interface class code */ +#define USB_CLASS_DATA 0x0AU + +#define USB_DESCTYPE_CDC_ACM 0x21U +#define USB_DESCTYPE_CS_INTERFACE 0x24U + +#define USB_CDC_ACM_CONFIG_DESC_SIZE 0x43U + +/* class-specific notification codes for pstn subclasses */ +#define USB_CDC_NOTIFY_SERIAL_STATE 0x20U + +/* class-specific request codes */ +#define SEND_ENCAPSULATED_COMMAND 0x00U +#define GET_ENCAPSULATED_RESPONSE 0x01U +#define SET_COMM_FEATURE 0x02U +#define GET_COMM_FEATURE 0x03U +#define CLEAR_COMM_FEATURE 0x04U + +#define SET_AUX_LINE_STATE 0x10U +#define SET_HOOK_STATE 0x11U +#define PULSE_SETUP 0x12U +#define SEND_PULSE 0x13U +#define SET_PULSE_TIME 0x14U +#define RING_AUX_JACK 0x15U + +#define SET_LINE_CODING 0x20U +#define GET_LINE_CODING 0x21U +#define SET_CONTROL_LINE_STATE 0x22U +#define SEND_BREAK 0x23U +#define NO_CMD 0xFFU + +#define SET_RINGER_PARMS 0x30U +#define GET_RINGER_PARMS 0x31U +#define SET_OPERATION_PARMS 0x32U +#define GET_OPERATION_PARMS 0x33U +#define SET_LINE_PARMS 0x34U +#define GET_LINE_PARMS 0x35U +#define DIAL_DIGITS 0x36U +#define SET_UNIT_PARAMETER 0x37U +#define GET_UNIT_PARAMETER 0x38U +#define CLEAR_UNIT_PARAMETER 0x39U +#define GET_PROFILE 0x3AU + +#define SET_ETHERNET_MULTICAST_FILTERS 0x40U +#define SET_ETHERNET_POWER_MANAGEMENT_PATTERN FILTER 0x41U +#define GET_ETHERNET_POWER_MANAGEMENT_PATTERN FILTER 0x42U +#define SET_ETHERNET_PACKET_FILTER 0x43U +#define GET_ETHERNET_STATISTIC 0x44U + +#define SET_ATM_DATA_FORMAT 0x50U +#define GET_ATM_DEVICE_STATISTICS 0x51U +#define SET_ATM_DEFAULT_VC 0x52U +#define GET_ATM_VC_STATISTICS 0x53U + +/* wValue for set control line state */ +#define CDC_ACTIVATE_CARRIER_SIGNAL_RTS 0x0002U +#define CDC_DEACTIVATE_CARRIER_SIGNAL_RTS 0x0000U +#define CDC_ACTIVATE_SIGNAL_DTR 0x0001U +#define CDC_DEACTIVATE_SIGNAL_DTR 0x0000U + +/* CDC subclass code */ +enum usb_cdc_subclass { + USB_CDC_SUBCLASS_RESERVED = 0U, /*!< reserved */ + USB_CDC_SUBCLASS_DLCM, /*!< direct line control mode */ + USB_CDC_SUBCLASS_ACM, /*!< abstract control mode */ + USB_CDC_SUBCLASS_TCM, /*!< telephone control mode */ + USB_CDC_SUBCLASS_MCM, /*!< multichannel control model */ + USB_CDC_SUBCLASS_CCM, /*!< CAPI control model */ + USB_CDC_SUBCLASS_ENCM, /*!< ethernet networking control model */ + USB_CDC_SUBCLASS_ANCM /*!< ATM networking control model */ +}; + +#pragma pack(1) + +/* cdc acm line coding structure */ +typedef struct { + uint32_t dwDTERate; /*!< data terminal rate */ + uint8_t bCharFormat; /*!< stop bits */ + uint8_t bParityType; /*!< parity */ + uint8_t bDataBits; /*!< data bits */ +} acm_line; + +/* notification structure */ +typedef struct { + uint8_t bmRequestType; /*!< type of request */ + uint8_t bNotification; /*!< communication interface class notifications */ + uint16_t wValue; /*!< value of notification */ + uint16_t wIndex; /*!< index of interface */ + uint16_t wLength; /*!< length of notification data */ +} acm_notification; + +typedef struct { + usb_desc_header header; /*!< descriptor header, including type and size. */ + uint8_t bDescriptorSubtype; /*!< bDescriptorSubtype: header function descriptor */ + uint16_t bcdCDC; /*!< bcdCDC: low byte of spec release number (CDC1.10) */ +} usb_desc_header_func; + +typedef struct { + usb_desc_header header; /*!< descriptor header, including type and size. */ + uint8_t bDescriptorSubtype; /*!< bDescriptorSubtype: call management function descriptor */ + uint8_t bmCapabilities; /*!< bmCapabilities: D0 is reset, D1 is ignored */ + uint8_t bDataInterface; /*!< bDataInterface: 1 interface used for call management */ +} usb_desc_call_managment_func; + +typedef struct { + usb_desc_header header; /*!< descriptor header, including type and size. */ + uint8_t bDescriptorSubtype; /*!< bDescriptorSubtype: abstract control management descriptor */ + uint8_t bmCapabilities; /*!< bmCapabilities: D1 */ +} usb_desc_acm_func; + +typedef struct { + usb_desc_header header; /*!< descriptor header, including type and size. */ + uint8_t bDescriptorSubtype; /*!< bDescriptorSubtype: union function descriptor */ + uint8_t bMasterInterface; /*!< bMasterInterface: communication class interface */ + uint8_t bSlaveInterface0; /*!< bSlaveInterface0: data class interface */ +} usb_desc_union_func; + +#pragma pack() + +typedef struct { + usb_desc_config config; + usb_desc_itf cmd_itf; + usb_desc_header_func cdc_header; + usb_desc_call_managment_func cdc_call_managment; + usb_desc_acm_func cdc_acm; + usb_desc_union_func cdc_union; + usb_desc_ep cdc_cmd_endpoint; + usb_desc_itf cdc_data_interface; + usb_desc_ep cdc_out_endpoint; + usb_desc_ep cdc_in_endpoint; +} usb_cdc_desc_config_set; + +#endif /* __USB_CDC_H */ diff --git a/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/ustd/class/hid/usb_hid.h b/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/ustd/class/hid/usb_hid.h new file mode 100644 index 0000000000..220468f42b --- /dev/null +++ b/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/ustd/class/hid/usb_hid.h @@ -0,0 +1,83 @@ +/*! + \file usb_hid.h + \brief definitions for the USB HID class + + \version 2020-08-01, V3.0.0, firmware for GD32F4xx +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef __USB_HID_H +#define __USB_HID_H + +#include "usb_ch9_std.h" + +#define USB_HID_CLASS 0x03U + +#define USB_DESCTYPE_HID 0x21U +#define USB_DESCTYPE_REPORT 0x22U + +/* HID subclass code */ +#define USB_HID_SUBCLASS_BOOT_ITF 0x01U + +/* HID protocol codes */ +#define USB_HID_PROTOCOL_KEYBOARD 0x01U +#define USB_HID_PROTOCOL_MOUSE 0x02U + +#define GET_REPORT 0x01U +#define GET_IDLE 0x02U +#define GET_PROTOCOL 0x03U +#define SET_REPORT 0x09U +#define SET_IDLE 0x0AU +#define SET_PROTOCOL 0x0BU + +#pragma pack(1) + +typedef struct +{ + usb_desc_header header; /*!< regular descriptor header containing the descriptor's type and length */ + + uint16_t bcdHID; /*!< BCD encoded version that the HID descriptor and device complies to */ + uint8_t bCountryCode; /*!< country code of the localized device, or zero if universal */ + uint8_t bNumDescriptors; /*!< total number of HID report descriptors for the interface */ + uint8_t bDescriptorType; /*!< type of HID report */ + uint16_t wDescriptorLength; /*!< length of the associated HID report descriptor, in bytes */ +} usb_desc_hid; + +#pragma pack() + +typedef struct +{ + usb_desc_config config; + usb_desc_itf hid_itf; + usb_desc_hid hid_vendor; + usb_desc_ep hid_epin; + usb_desc_ep hid_epout; +}usb_hid_desc_config_set; + +#endif /* __USB_HID_H */ diff --git a/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/ustd/class/msc/msc_bbb.h b/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/ustd/class/msc/msc_bbb.h new file mode 100644 index 0000000000..dddab34227 --- /dev/null +++ b/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/ustd/class/msc/msc_bbb.h @@ -0,0 +1,69 @@ +/*! + \file msc_bbb.h + \brief definitions for the USB MSC BBB(bulk/bulk/bulk) protocol + + \version 2020-08-01, V3.0.0, firmware for GD32F4xx +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef __MSC_BBB_H +#define __MSC_BBB_H + +#include "usb_ch9_std.h" + +#define BBB_CBW_SIGNATURE 0x43425355U +#define BBB_CSW_SIGNATURE 0x53425355U +#define BBB_CBW_LENGTH 31U +#define BBB_CSW_LENGTH 13U + +typedef struct { + uint32_t dCBWSignature; + uint32_t dCBWTag; + uint32_t dCBWDataTransferLength; + uint8_t bmCBWFlags; + uint8_t bCBWLUN; + uint8_t bCBWCBLength; + uint8_t CBWCB[16]; +}msc_bbb_cbw; + +typedef struct { + uint32_t dCSWSignature; + uint32_t dCSWTag; + uint32_t dCSWDataResidue; + uint8_t bCSWStatus; +}msc_bbb_csw; + +/* CSW command status */ +enum msc_csw_status { + CSW_CMD_PASSED = 0, + CSW_CMD_FAILED, + CSW_PHASE_ERROR +}; + +#endif /* __MSC_BBB_H */ diff --git a/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/ustd/class/msc/msc_scsi.h b/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/ustd/class/msc/msc_scsi.h new file mode 100644 index 0000000000..5e836d36da --- /dev/null +++ b/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/ustd/class/msc/msc_scsi.h @@ -0,0 +1,117 @@ +/*! + \file msc_scsi.h + \brief definitions for the USB MSC SCSI commands + + \version 2020-08-01, V3.0.0, firmware for GD32F4xx +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef __MSC_SCSI_H +#define __MSC_SCSI_H + +#include "usb_ch9_std.h" + +/* SCSI commands */ +#define SCSI_FORMAT_UNIT 0x04U +#define SCSI_INQUIRY 0x12U +#define SCSI_MODE_SELECT6 0x15U +#define SCSI_MODE_SELECT10 0x55U +#define SCSI_MODE_SENSE6 0x1AU +#define SCSI_READ_TOC_DATA 0x43U +#define SCSI_MODE_SENSE10 0x5AU +#define SCSI_ALLOW_MEDIUM_REMOVAL 0x1EU +#define SCSI_READ6 0x08U +#define SCSI_READ10 0x28U +#define SCSI_READ12 0xA8U +#define SCSI_READ16 0x88U + +#define SCSI_READ_CAPACITY10 0x25U +#define SCSI_READ_CAPACITY16 0x9EU + +#define SCSI_REQUEST_SENSE 0x03U +#define SCSI_START_STOP_UNIT 0x1BU +#define SCSI_TEST_UNIT_READY 0x00U +#define SCSI_WRITE6 0x0AU +#define SCSI_WRITE10 0x2AU +#define SCSI_WRITE12 0xAAU +#define SCSI_WRITE16 0x8AU + +#define SCSI_VERIFY10 0x2FU +#define SCSI_VERIFY12 0xAFU +#define SCSI_VERIFY16 0x8FU + +#define SCSI_SEND_DIAGNOSTIC 0x1DU +#define SCSI_READ_FORMAT_CAPACITIES 0x23U + +#define INVALID_CDB 0x20U +#define INVALID_FIELED_IN_COMMAND 0x24U +#define PARAMETER_LIST_LENGTH_ERROR 0x1AU +#define INVALID_FIELD_IN_PARAMETER_LIST 0x26U +#define ADDRESS_OUT_OF_RANGE 0x21U +#define MEDIUM_NOT_PRESENT 0x3AU +#define MEDIUM_HAVE_CHANGED 0x28U +#define WRITE_PROTECTED 0x27U +#define UNRECOVERED_READ_ERROR 0x11U +#define WRITE_FAULT 0x03U + +#define READ_FORMAT_CAPACITY_DATA_LEN 0x0CU +#define READ_CAPACITY10_DATA_LEN 0x08U +#define MODE_SENSE10_DATA_LEN 0x08U +#define MODE_SENSE6_DATA_LEN 0x04U +#define READ_TOC_CMD_LEN 0x14U +#define REQUEST_SENSE_DATA_LEN 0x12U +#define STANDARD_INQUIRY_DATA_LEN 0x24U +#define BLKVFY 0x04U + +enum sense_state { + NO_SENSE = 0U, + RECOVERED_ERROR, + NOT_READY, + MEDIUM_ERROR, + HARDWARE_ERROR, + ILLEGAL_REQUEST, + UNIT_ATTENTION, + DATA_PROTECT, + BLANK_CHECK, + VENDOR_SPECIFIC, + COPY_ABORTED, + ABORTED_COMMAND, + RESERVED, + VOLUME_OVERFLOW, + MISCOMPARE +}; + +typedef struct { + uint8_t SenseKey; + uint32_t Information; + uint8_t ASC; + uint8_t ASCQ; +} msc_scsi_sense; + +#endif /* __MSC_SCSI_H */ diff --git a/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/ustd/class/msc/usb_msc.h b/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/ustd/class/msc/usb_msc.h new file mode 100644 index 0000000000..541bfb037b --- /dev/null +++ b/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/ustd/class/msc/usb_msc.h @@ -0,0 +1,68 @@ +/*! + \file usb_msc.h + \brief definitions for the USB MSC class + + \version 2020-08-01, V3.0.0, firmware for GD32F4xx +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef __USB_MSC_H +#define __USB_MSC_H + +#include "usb_ch9_std.h" + +/* mass storage device class code */ +#define USB_CLASS_MSC 0x08U + +/* mass storage subclass code */ +#define USB_MSC_SUBCLASS_RBC 0x01U +#define USB_MSC_SUBCLASS_ATAPI 0x02U +#define USB_MSC_SUBCLASS_UFI 0x04U +#define USB_MSC_SUBCLASS_SCSI 0x06U +#define USB_MSC_SUBCLASS_LOCKABLE 0x07U +#define USB_MSC_SUBCLASS_IEEE1667 0x08U + +/* mass storage interface class control protocol codes */ +#define USB_MSC_PROTOCOL_CBI 0x00U +#define USB_MSC_PROTOCOL_CBI_ALT 0x01U +#define USB_MSC_PROTOCOL_BBB 0x50U + +/* mass storage request codes */ +#define USB_MSC_REQ_CODES_ADSC 0x00U +#define USB_MSC_REQ_CODES_GET 0xFCU +#define USB_MSC_REQ_CODES_PUT 0xFDU +#define USB_MSC_REQ_CODES_GML 0xFEU +#define USB_MSC_REQ_CODES_BOMSR 0xFFU + +#define BBB_GET_MAX_LUN 0xFEU +#define BBB_RESET 0xFFU + +#define SCSI_CMD_LENGTH 16U + +#endif /* __USB_MSC_H */ diff --git a/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/ustd/common/usb_ch9_std.h b/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/ustd/common/usb_ch9_std.h new file mode 100644 index 0000000000..c52931c91e --- /dev/null +++ b/bsp/gd32/libraries/GD32F4xx_Firmware_Library/GD32F4xx_usb_library/ustd/common/usb_ch9_std.h @@ -0,0 +1,248 @@ +/*! + \file usb_ch9_std.h + \brief USB 2.0 standard defines + + \version 2020-08-01, V3.0.0, firmware for GD32F4xx +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef __USB_CH9_STD_H +#define __USB_CH9_STD_H + +#include "usb_conf.h" + +#define USB_DEV_QUALIFIER_DESC_LEN 0x0AU /*!< USB device qualifier descriptor length */ +#define USB_DEV_DESC_LEN 0x12U /*!< USB device descriptor length */ +#define USB_CFG_DESC_LEN 0x09U /*!< USB configuration descriptor length */ +#define USB_ITF_DESC_LEN 0x09U /*!< USB interface descriptor length */ +#define USB_EP_DESC_LEN 0x07U /*!< USB endpoint descriptor length */ +#define USB_IAD_DESC_LEN 0x08U /*!< USB IAD descriptor length */ +#define USB_OTG_DESC_LEN 0x03U /*!< USB device OTG descriptor length */ + +#define USB_SETUP_PACKET_LEN 0x08U /*!< USB setup packet length */ + +/* bit 7 of bmRequestType: data phase transfer direction */ +#define USB_TRX_MASK 0x80U /*!< USB transfer direction mask */ +#define USB_TRX_OUT 0x00U /*!< USB transfer OUT direction */ +#define USB_TRX_IN 0x80U /*!< USB transfer IN direction */ + +/* bit 6..5 of bmRequestType: request type */ +#define USB_REQTYPE_STRD 0x00U /*!< USB standard request */ +#define USB_REQTYPE_CLASS 0x20U /*!< USB class request */ +#define USB_REQTYPE_VENDOR 0x40U /*!< USB vendor request */ +#define USB_REQTYPE_MASK 0x60U /*!< USB request mask */ + +#define USBD_BUS_POWERED 0x00U /*!< USB bus power supply */ +#define USBD_SELF_POWERED 0x01U /*!< USB self power supply */ + +#define USB_STATUS_REMOTE_WAKEUP 2U /*!< USB is in remote wakeup status */ +#define USB_STATUS_SELF_POWERED 1U /*!< USB is in self powered status */ + +/* bit 4..0 of bmRequestType: recipient type */ +enum _usb_recp_type { + USB_RECPTYPE_DEV = 0x0U, /*!< USB device request type */ + USB_RECPTYPE_ITF = 0x1U, /*!< USB interface request type */ + USB_RECPTYPE_EP = 0x2U, /*!< USB endpoint request type */ + USB_RECPTYPE_MASK = 0x3U /*!< USB request type mask */ +}; + +/* bRequest value */ +enum _usb_request { + USB_GET_STATUS = 0x0U, /*!< USB get status request */ + USB_CLEAR_FEATURE = 0x1U, /*!< USB clear feature request */ + USB_RESERVED2 = 0x2U, + USB_SET_FEATURE = 0x3U, /*!< USB set feature request */ + USB_RESERVED4 = 0x4U, + USB_SET_ADDRESS = 0x5U, /*!< USB set address request */ + USB_GET_DESCRIPTOR = 0x6U, /*!< USB get descriptor request */ + USB_SET_DESCRIPTOR = 0x7U, /*!< USB set descriptor request */ + USB_GET_CONFIGURATION = 0x8U, /*!< USB get configuration request */ + USB_SET_CONFIGURATION = 0x9U, /*!< USB set configuration request */ + USB_GET_INTERFACE = 0xAU, /*!< USB get interface request */ + USB_SET_INTERFACE = 0xBU, /*!< USB set interface request */ + USB_SYNCH_FRAME = 0xCU /*!< USB synchronize frame request */ +}; + +/* descriptor types of USB specifications */ +enum _usb_desctype { + USB_DESCTYPE_DEV = 0x1U, /*!< USB device descriptor type */ + USB_DESCTYPE_CONFIG = 0x2U, /*!< USB configuration descriptor type */ + USB_DESCTYPE_STR = 0x3U, /*!< USB string descriptor type */ + USB_DESCTYPE_ITF = 0x4U, /*!< USB interface descriptor type */ + USB_DESCTYPE_EP = 0x5U, /*!< USB endpoint descriptor type */ + USB_DESCTYPE_DEV_QUALIFIER = 0x6U, /*!< USB device qualifier descriptor type */ + USB_DESCTYPE_OTHER_SPD_CONFIG = 0x7U, /*!< USB other speed configuration descriptor type */ + USB_DESCTYPE_ITF_POWER = 0x8U, /*!< USB interface power descriptor type */ + USB_DESCTYPE_IAD = 0xBU, /*!< USB interface association descriptor type */ + USB_DESCTYPE_BOS = 0xFU /*!< USB BOS descriptor type */ +}; + +/* USB Endpoint Descriptor bmAttributes bit definitions */ +/* bits 1..0 : transfer type */ +enum _usbx_type { + USB_EP_ATTR_CTL = 0x0U, /*!< USB control transfer type */ + USB_EP_ATTR_ISO = 0x1U, /*!< USB Isochronous transfer type */ + USB_EP_ATTR_BULK = 0x2U, /*!< USB Bulk transfer type */ + USB_EP_ATTR_INT = 0x3U /*!< USB Interrupt transfer type */ +}; + +/* bits 3..2 : Sync type (only if ISOCHRONOUS) */ +#define USB_EP_ATTR_NOSYNC 0x00U /*!< No Synchronization */ +#define USB_EP_ATTR_ASYNC 0x04U /*!< Asynchronous */ +#define USB_EP_ATTR_ADAPTIVE 0x08U /*!< Adaptive */ +#define USB_EP_ATTR_SYNC 0x0CU /*!< Synchronous */ +#define USB_EP_ATTR_SYNCTYPE 0x0CU /*!< Synchronous type */ + +/* bits 5..4 : usage type (only if ISOCHRONOUS) */ +#define USB_EP_ATTR_DATA 0x00U /*!< Data endpoint */ +#define USB_EP_ATTR_FEEDBACK 0x10U /*!< Feedback endpoint */ +#define USB_EP_ATTR_IMPLICIT_FEEDBACK_DATA 0x20U /*!< Implicit feedback Data endpoint */ +#define USB_EP_ATTR_USAGETYPE 0x30U /*!< Usage type */ + +/* endpoint max packet size bits12..11 */ +#define USB_EP_MPS_ADD_0 (0x00 << 11) /*!< None(1 transaction per microframe */ +#define USB_EP_MPS_ADD_1 (0x01 << 11) /*!< 1 additional(2 transaction per microframe */ +#define USB_EP_MPS_ADD_2 (0x02 << 11) /*!< 2 additional(3 transaction per microframe */ + +#define FEATURE_SELECTOR_EP 0x00U /*!< USB endpoint feature selector */ +#define FEATURE_SELECTOR_DEV 0x01U /*!< USB device feature selector */ +#define FEATURE_SELECTOR_REMOTEWAKEUP 0x01U /*!< USB feature selector remote wakeup */ + +#define BYTE_SWAP(addr) (((uint16_t)(*((uint8_t *)(addr)))) + \ + (uint16_t)(((uint16_t)(*(((uint8_t *)(addr)) + 1U))) << 8U)) + +#define BYTE_LOW(x) ((uint8_t)((x) & 0x00FFU)) +#define BYTE_HIGH(x) ((uint8_t)(((x) & 0xFF00U) >> 8U)) + +#define USB_MIN(a, b) (((a) < (b)) ? (a) : (b)) + +#define USB_DEFAULT_CONFIG 0U + +/* USB classes */ +#define USB_CLASS_HID 0x03U /*!< USB HID class */ +#define USB_CLASS_MSC 0x08U /*!< USB MSC class */ + +/* use the following values when USB host need to get descriptor */ +#define USBH_DESC(x) (((x)<< 8U) & 0xFF00U) + +/* as per USB specs 9.2.6.4 :standard request with data request timeout: 5sec + standard request with no data stage timeout : 50ms */ +#define DATA_STAGE_TIMEOUT 5000U /*!< USB data stage timeout*/ +#define NODATA_STAGE_TIMEOUT 50U /*!< USB no data stage timeout*/ + +#pragma pack(1) + +/* USB standard device request structure */ +typedef struct _usb_req { + uint8_t bmRequestType; /*!< type of request */ + uint8_t bRequest; /*!< request of setup packet */ + uint16_t wValue; /*!< value of setup packet */ + uint16_t wIndex; /*!< index of setup packet */ + uint16_t wLength; /*!< length of setup packet */ +} usb_req; + +/* USB setup packet define */ +typedef union _usb_setup { + uint8_t data[8]; + + usb_req req; +} usb_setup; + +/* USB descriptor defines */ + +typedef struct _usb_desc_header { + uint8_t bLength; /*!< size of the descriptor */ + uint8_t bDescriptorType; /*!< type of the descriptor */ +} usb_desc_header; + +typedef struct _usb_desc_dev { + usb_desc_header header; /*!< descriptor header, including type and size */ + + uint16_t bcdUSB; /*!< BCD of the supported USB specification */ + uint8_t bDeviceClass; /*!< USB device class */ + uint8_t bDeviceSubClass; /*!< USB device subclass */ + uint8_t bDeviceProtocol; /*!< USB device protocol */ + uint8_t bMaxPacketSize0; /*!< size of the control (address 0) endpoint's bank in bytes */ + uint16_t idVendor; /*!< vendor ID for the USB product */ + uint16_t idProduct; /*!< unique product ID for the USB product */ + uint16_t bcdDevice; /*!< product release (version) number */ + uint8_t iManufacturer; /*!< string index for the manufacturer's name */ + uint8_t iProduct; /*!< string index for the product name/details */ + uint8_t iSerialNumber; /*!< string index for the product's globally unique hexadecimal serial number */ + uint8_t bNumberConfigurations; /*!< total number of configurations supported by the device */ +} usb_desc_dev; + +typedef struct _usb_desc_config { + usb_desc_header header; /*!< descriptor header, including type and size */ + + uint16_t wTotalLength; /*!< size of the configuration descriptor header,and all sub descriptors inside the configuration */ + uint8_t bNumInterfaces; /*!< total number of interfaces in the configuration */ + uint8_t bConfigurationValue; /*!< configuration index of the current configuration */ + uint8_t iConfiguration; /*!< index of a string descriptor describing the configuration */ + uint8_t bmAttributes; /*!< configuration attributes */ + uint8_t bMaxPower; /*!< maximum power consumption of the device while in the current configuration */ +} usb_desc_config; + +typedef struct _usb_desc_itf { + usb_desc_header header; /*!< descriptor header, including type and size */ + + uint8_t bInterfaceNumber; /*!< index of the interface in the current configuration */ + uint8_t bAlternateSetting; /*!< alternate setting for the interface number */ + uint8_t bNumEndpoints; /*!< total number of endpoints in the interface */ + uint8_t bInterfaceClass; /*!< interface class ID */ + uint8_t bInterfaceSubClass; /*!< interface subclass ID */ + uint8_t bInterfaceProtocol; /*!< interface protocol ID */ + uint8_t iInterface; /*!< index of the string descriptor describing the interface */ +} usb_desc_itf; + +typedef struct _usb_desc_ep { + usb_desc_header header; /*!< descriptor header, including type and size. */ + + uint8_t bEndpointAddress; /*!< logical address of the endpoint */ + uint8_t bmAttributes; /*!< endpoint attributes */ + uint16_t wMaxPacketSize; /*!< size of the endpoint bank, in bytes */ + uint8_t bInterval; /*!< polling interval in milliseconds for the endpoint if it is an INTERRUPT or ISOCHRONOUS type */ +} usb_desc_ep; + +typedef struct _usb_desc_LANGID { + usb_desc_header header; /*!< descriptor header, including type and size. */ + uint16_t wLANGID; /*!< LANGID code */ +} usb_desc_LANGID; + +typedef struct _usb_desc_str { + usb_desc_header header; /*!< descriptor header, including type and size. */ + uint16_t unicode_string[64]; /*!< unicode string data */ +} usb_desc_str; + +#pragma pack() + +/* compute string descriptor length */ +#define USB_STRING_LEN(unicode_chars) (sizeof(usb_desc_header) + ((unicode_chars) << 1U)) + +#endif /* __USB_CH9_STD_H */ diff --git a/bsp/gd32/libraries/GD32F4xx_HAL/SConscript b/bsp/gd32/libraries/GD32F4xx_Firmware_Library/SConscript similarity index 100% rename from bsp/gd32/libraries/GD32F4xx_HAL/SConscript rename to bsp/gd32/libraries/GD32F4xx_Firmware_Library/SConscript diff --git a/bsp/gd32/libraries/HAL_Drivers/SConscript b/bsp/gd32/libraries/HAL_Drivers/SConscript deleted file mode 100644 index 1b47236afa..0000000000 --- a/bsp/gd32/libraries/HAL_Drivers/SConscript +++ /dev/null @@ -1,22 +0,0 @@ -Import('RTT_ROOT') -Import('rtconfig') -from building import * - -cwd = GetCurrentDir() - -# add the general drivers. -src = Split(""" -""") - -# add pin drivers. -if GetDepend('RT_USING_PIN'): - src += ['drv_gpio.c'] - -if GetDepend(['RT_USING_SERIAL']): - src += ['drv_usart.c'] - -path = [cwd] - -group = DefineGroup('Drivers', src, depend = [''], CPPPATH = path) - -Return('group') diff --git a/bsp/gd32/libraries/HAL_Drivers/drv_usart.h b/bsp/gd32/libraries/HAL_Drivers/drv_usart.h deleted file mode 100644 index a07b0bafce..0000000000 --- a/bsp/gd32/libraries/HAL_Drivers/drv_usart.h +++ /dev/null @@ -1,22 +0,0 @@ -/* - * Copyright (c) 2006-2021, RT-Thread Development Team - * - * SPDX-License-Identifier: Apache-2.0 - * - * Change Logs: - * Date Author Notes - * 2021-08-20 BruceOu first implementation - */ - -#ifndef __USART_H__ -#define __USART_H__ - -#include -#include - -#define UART_ENABLE_IRQ(n) NVIC_EnableIRQ((n)) -#define UART_DISABLE_IRQ(n) NVIC_DisableIRQ((n)) - -int gd32_hw_usart_init(void); - -#endif diff --git a/bsp/gd32/libraries/HAL_Drivers/Kconfig b/bsp/gd32/libraries/gd32_drivers/Kconfig similarity index 100% rename from bsp/gd32/libraries/HAL_Drivers/Kconfig rename to bsp/gd32/libraries/gd32_drivers/Kconfig diff --git a/bsp/gd32/libraries/gd32_drivers/SConscript b/bsp/gd32/libraries/gd32_drivers/SConscript new file mode 100644 index 0000000000..b33b2c5768 --- /dev/null +++ b/bsp/gd32/libraries/gd32_drivers/SConscript @@ -0,0 +1,36 @@ +Import('RTT_ROOT') +Import('rtconfig') +from building import * + +cwd = GetCurrentDir() + +# add the general drivers. +src = Split(""" +""") + +# add pin drivers. +if GetDepend('RT_USING_PIN'): + src += ['drv_gpio.c'] + +# add usart drivers. +if GetDepend(['RT_USING_SERIAL']): + src += ['drv_usart.c'] + +# add i2c drivers. +if GetDepend(['RT_USING_I2C', 'RT_USING_I2C_BITOPS']): + if GetDepend('BSP_USING_I2C0') or GetDepend('BSP_USING_I2C1') or GetDepend('BSP_USING_I2C2') or GetDepend('BSP_USING_I2C3'): + src += ['drv_soft_i2c.c'] + +# add spi drivers. +if GetDepend('RT_USING_SPI'): + src += ['drv_spi.c'] + +# add spi flash drivers. +if GetDepend('RT_USING_SFUD'): + src += ['drv_spi_flash.c', 'drv_spi.c'] + +path = [cwd] + +group = DefineGroup('Drivers', src, depend = [''], CPPPATH = path) + +Return('group') diff --git a/bsp/gd32/libraries/HAL_Drivers/drv_gpio.c b/bsp/gd32/libraries/gd32_drivers/drv_gpio.c similarity index 81% rename from bsp/gd32/libraries/HAL_Drivers/drv_gpio.c rename to bsp/gd32/libraries/gd32_drivers/drv_gpio.c index 3ff4282c82..6eaa7d9f8c 100644 --- a/bsp/gd32/libraries/HAL_Drivers/drv_gpio.c +++ b/bsp/gd32/libraries/gd32_drivers/drv_gpio.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006-2021, RT-Thread Development Team + * Copyright (c) 2006-2022, RT-Thread Development Team * * SPDX-License-Identifier: Apache-2.0 * @@ -10,6 +10,7 @@ #include #include +#include #ifdef RT_USING_PIN @@ -26,7 +27,7 @@ static const struct pin_index pins[] = GD32_PIN(6, A, 6), GD32_PIN(7, A, 7), GD32_PIN(8, A, 8), - GD32_PIN(9, A, 9), + GD32_PIN(9, A, 9), GD32_PIN(10, A, 10), GD32_PIN(11, A, 11), GD32_PIN(12, A, 12), @@ -138,6 +139,12 @@ struct rt_pin_irq_hdr pin_irq_hdr_tab[] = }; #define ITEM_NUM(items) sizeof(items) / sizeof(items[0]) + +/** + * @brief get pin + * @param pin + * @retval None + */ const struct pin_index *get_pin(rt_uint8_t pin) { const struct pin_index *index; @@ -154,12 +161,21 @@ const struct pin_index *get_pin(rt_uint8_t pin) } return index; -}; +} -static void _pin_mode(rt_device_t dev, rt_base_t pin, rt_base_t mode) +/** + * @brief set pin mode + * @param dev, pin, mode + * @retval None + */ +static void gd32_pin_mode(rt_device_t dev, rt_base_t pin, rt_base_t mode) { const struct pin_index *index = RT_NULL; - rt_uint32_t pin_mode = 0, pin_pupd = 0, pin_odpp = 0; + rt_uint32_t pin_mode = 0; + +#if defined SOC_SERIES_GD32F4xx + rt_uint32_t pin_pupd = 0, pin_odpp = 0; +#endif index = get_pin(pin); if (index == RT_NULL) @@ -169,49 +185,82 @@ static void _pin_mode(rt_device_t dev, rt_base_t pin, rt_base_t mode) /* GPIO Periph clock enable */ rcu_periph_clock_enable(index->clk); - pin_mode = GPIO_MODE_OUTPUT; +#if defined SOC_SERIES_GD32F4xx + pin_mode = GPIO_MODE_OUTPUT; +#else + pin_mode = GPIO_MODE_OUT_PP; +#endif switch(mode) { case PIN_MODE_OUTPUT: /* output setting */ +#if defined SOC_SERIES_GD32F4xx pin_mode = GPIO_MODE_OUTPUT; pin_pupd = GPIO_PUPD_NONE; pin_odpp = GPIO_OTYPE_PP; +#else + pin_mode = GPIO_MODE_OUT_PP; +#endif break; case PIN_MODE_OUTPUT_OD: /* output setting: od. */ +#if defined SOC_SERIES_GD32F4xx pin_mode = GPIO_MODE_OUTPUT; pin_pupd = GPIO_PUPD_NONE; pin_odpp = GPIO_OTYPE_OD; +#else + pin_mode = GPIO_MODE_OUT_OD; +#endif break; case PIN_MODE_INPUT: /* input setting: not pull. */ +#if defined SOC_SERIES_GD32F4xx pin_mode = GPIO_MODE_INPUT; pin_pupd = GPIO_PUPD_PULLUP | GPIO_PUPD_PULLDOWN; +#else + pin_mode = GPIO_MODE_IN_FLOATING; +#endif break; case PIN_MODE_INPUT_PULLUP: /* input setting: pull up. */ +#if defined SOC_SERIES_GD32F4xx pin_mode = GPIO_MODE_INPUT; pin_pupd = GPIO_PUPD_PULLUP; +#else + pin_mode = GPIO_MODE_IPU; +#endif break; case PIN_MODE_INPUT_PULLDOWN: /* input setting: pull down. */ +#if defined SOC_SERIES_GD32F4xx pin_mode = GPIO_MODE_INPUT; pin_pupd = GPIO_PUPD_PULLDOWN; +#else + pin_mode = GPIO_MODE_IPD; +#endif break; default: break; } +#if defined SOC_SERIES_GD32F4xx gpio_mode_set(index->gpio_periph, pin_mode, pin_pupd, index->pin); if(pin_mode == GPIO_MODE_OUTPUT) { gpio_output_options_set(index->gpio_periph, pin_odpp, GPIO_OSPEED_50MHZ, index->pin); } +#else + gpio_init(index->gpio_periph, pin_mode, GPIO_OSPEED_50MHZ, index->pin); +#endif } -static void _pin_write(rt_device_t dev, rt_base_t pin, rt_base_t value) +/** + * @brief pin write + * @param dev, pin, valuie + * @retval None + */ +static void gd32_pin_write(rt_device_t dev, rt_base_t pin, rt_base_t value) { const struct pin_index *index = RT_NULL; @@ -224,7 +273,12 @@ static void _pin_write(rt_device_t dev, rt_base_t pin, rt_base_t value) gpio_bit_write(index->gpio_periph, index->pin, (bit_status)value); } -static int _pin_read(rt_device_t dev, rt_base_t pin) +/** + * @brief pin read + * @param dev, pin + * @retval None + */ +static int gd32_pin_read(rt_device_t dev, rt_base_t pin) { int value = PIN_LOW; const struct pin_index *index = RT_NULL; @@ -239,6 +293,11 @@ static int _pin_read(rt_device_t dev, rt_base_t pin) return value; } +/** + * @brief bit2bitno + * @param bit + * @retval None + */ rt_inline rt_int32_t bit2bitno(rt_uint32_t bit) { rt_uint8_t i; @@ -252,6 +311,11 @@ rt_inline rt_int32_t bit2bitno(rt_uint32_t bit) return -1; } +/** + * @brief pin write + * @param pinbit + * @retval None + */ rt_inline const struct pin_irq_map *get_pin_irq_map(rt_uint32_t pinbit) { rt_int32_t map_index = bit2bitno(pinbit); @@ -260,9 +324,14 @@ rt_inline const struct pin_irq_map *get_pin_irq_map(rt_uint32_t pinbit) return RT_NULL; } return &pin_irq_map[map_index]; -}; +} -static rt_err_t _pin_attach_irq(struct rt_device *device, rt_int32_t pin, +/** + * @brief pin irq attach + * @param device, pin, mode + * @retval None + */ +static rt_err_t gd32_pin_attach_irq(struct rt_device *device, rt_int32_t pin, rt_uint32_t mode, void (*hdr)(void *args), void *args) { const struct pin_index *index = RT_NULL; @@ -304,7 +373,12 @@ static rt_err_t _pin_attach_irq(struct rt_device *device, rt_int32_t pin, return RT_EOK; } -static rt_err_t _pin_detach_irq(struct rt_device *device, rt_int32_t pin) +/** + * @brief pin irq detach + * @param device, pin + * @retval None + */ +static rt_err_t gd32_pin_detach_irq(struct rt_device *device, rt_int32_t pin) { const struct pin_index *index = RT_NULL; rt_base_t level; @@ -337,7 +411,12 @@ static rt_err_t _pin_detach_irq(struct rt_device *device, rt_int32_t pin) return RT_EOK; } -static rt_err_t _pin_irq_enable(struct rt_device *device, rt_base_t pin, rt_uint32_t enabled) +/** + * @brief pin irq enable + * @param device, pin, enabled + * @retval None + */ +static rt_err_t gd32_pin_irq_enable(struct rt_device *device, rt_base_t pin, rt_uint32_t enabled) { const struct pin_index *index; const struct pin_irq_map *irqmap; @@ -384,13 +463,21 @@ static rt_err_t _pin_irq_enable(struct rt_device *device, rt_base_t pin, rt_uint return -RT_EINVAL; } +#if defined SOC_SERIES_GD32F4xx rcu_periph_clock_enable(RCU_SYSCFG); +#else + rcu_periph_clock_enable(RCU_AF); +#endif /* enable and set interrupt priority */ nvic_irq_enable(irqmap->irqno, 5U, 0U); /* connect EXTI line to GPIO pin */ +#if defined SOC_SERIES_GD32F4xx syscfg_exti_line_config(index->port_src, index->pin_src); +#else + gpio_exti_source_select(index->port_src, index->pin_src); +#endif /* configure EXTI line */ exti_init((exti_line_enum)(index->pin), EXTI_INTERRUPT, trigger_mode); @@ -417,15 +504,20 @@ static rt_err_t _pin_irq_enable(struct rt_device *device, rt_base_t pin, rt_uint const static struct rt_pin_ops gd32_pin_ops = { - _pin_mode, - _pin_write, - _pin_read, - _pin_attach_irq, - _pin_detach_irq, - _pin_irq_enable, + .pin_mode = gd32_pin_mode, + .pin_write = gd32_pin_write, + .pin_read = gd32_pin_read, + .pin_attach_irq = gd32_pin_attach_irq, + .pin_detach_irq= gd32_pin_detach_irq, + .pin_irq_enable = gd32_pin_irq_enable, RT_NULL, }; +/** + * @brief pin write + * @param irqno + * @retval None + */ rt_inline void pin_irq_hdr(int irqno) { if (pin_irq_hdr_tab[irqno].hdr) @@ -434,6 +526,11 @@ rt_inline void pin_irq_hdr(int irqno) } } +/** + * @brief gd32 exit interrupt + * @param exti_line + * @retval None + */ void GD32_GPIO_EXTI_IRQHandler(rt_int8_t exti_line) { if(RESET != exti_interrupt_flag_get((exti_line_enum)(1 << exti_line))) @@ -509,6 +606,7 @@ int rt_hw_pin_init(void) return result; } + INIT_BOARD_EXPORT(rt_hw_pin_init); #endif diff --git a/bsp/gd32/libraries/HAL_Drivers/drv_gpio.h b/bsp/gd32/libraries/gd32_drivers/drv_gpio.h similarity index 54% rename from bsp/gd32/libraries/HAL_Drivers/drv_gpio.h rename to bsp/gd32/libraries/gd32_drivers/drv_gpio.h index 5b6e32d69b..9300191198 100644 --- a/bsp/gd32/libraries/HAL_Drivers/drv_gpio.h +++ b/bsp/gd32/libraries/gd32_drivers/drv_gpio.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006-2021, RT-Thread Development Team + * Copyright (c) 2006-2022, RT-Thread Development Team * * SPDX-License-Identifier: Apache-2.0 * @@ -19,23 +19,34 @@ extern "C" { #endif -#define GPIOA_BASE (GPIO_BASE + 0x00000800UL) -#define GPIOB_BASE (GPIO_BASE + 0x00000C00UL) -#define GPIOC_BASE (GPIO_BASE + 0x00001000UL) -#define GPIOD_BASE (GPIO_BASE + 0x00001400UL) -#define GPIOE_BASE (GPIO_BASE + 0x00001800UL) -#define GPIOF_BASE (GPIO_BASE + 0x00001C00UL) -#define GPIOG_BASE (GPIO_BASE + 0x00002000UL) +#if defined SOC_SERIES_GD32F10x +#include "gd32f10x_gpio.h" +#elif defined SOC_SERIES_GD32F20x +#include "gd32f20x_gpio.h" +#elif defined SOC_SERIES_GD32F30x +#include "gd32f30x_gpio.h" +#elif defined SOC_SERIES_GD32F4xx +#include "gd32f4xx_gpio.h" +#endif -#define __GD32_PORT(port) GPIO##port##_BASE +#define __GD32_PORT(port) GPIO##port +#if defined SOC_SERIES_GD32F4xx #define GD32_PIN(index, port, pin) {index, RCU_GPIO##port, \ GPIO##port, GPIO_PIN_##pin, \ EXTI_SOURCE_GPIO##port, \ EXTI_SOURCE_PIN##pin} +#else +#define GD32_PIN(index, port, pin) {index, RCU_GPIO##port, \ + GPIO##port, GPIO_PIN_##pin, \ + GPIO_PORT_SOURCE_GPIO##port, \ + GPIO_PIN_SOURCE_##pin} + +#endif + #define GD32_PIN_DEFAULT {-1, (rcu_periph_enum)0, 0, 0, 0, 0} -#define GET_PIN(PORTx, PIN) (rt_base_t)((16 * ( ((rt_base_t)__GD32_PORT(PORTx) - (rt_base_t)GPIOA_BASE)/(0x0400UL) )) + PIN) +#define GET_PIN(PORTx,PIN) (rt_base_t)((16 * ( ((rt_base_t)__GD32_PORT(PORTx) - (rt_base_t)GPIO_BASE)/(0x0400UL) )) + PIN) struct pin_index { diff --git a/bsp/gd32/libraries/gd32_drivers/drv_soft_i2c.c b/bsp/gd32/libraries/gd32_drivers/drv_soft_i2c.c new file mode 100644 index 0000000000..3979d7a36c --- /dev/null +++ b/bsp/gd32/libraries/gd32_drivers/drv_soft_i2c.c @@ -0,0 +1,201 @@ +/* + * Copyright (c) 2006-2022, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2021-12-20 BruceOu the first version + */ +#include "drv_soft_i2c.h" + +#ifdef RT_USING_I2C + +#define LOG_TAG "drv.i2c" +#include + +#if !defined(BSP_USING_I2C0) && !defined(BSP_USING_I2C1) && !defined(BSP_USING_I2C2) && !defined(BSP_USING_I2C3) +#error "Please define at least one BSP_USING_I2Cx" +/* this driver can be disabled at menuconfig → RT-Thread Components → Device Drivers */ +#endif + +static const struct gd32_soft_i2c_config soft_i2c_config[] = +{ +#ifdef BSP_USING_I2C0 + I2C0_BUS_CONFIG, +#endif +#ifdef BSP_USING_I2C1 + I2C1_BUS_CONFIG, +#endif +#ifdef BSP_USING_I2C2 + I2C2_BUS_CONFIG, +#endif +#ifdef BSP_USING_I2C3 + I2C3_BUS_CONFIG, +#endif +}; + +static struct gd32_i2c i2c_obj[sizeof(soft_i2c_config) / sizeof(soft_i2c_config[0])]; + +/** + * @brief This function initializes the i2c pin. + * @param i2c + * @retval None + */ +static void gd32_i2c_gpio_init(struct gd32_i2c *i2c) +{ + struct gd32_soft_i2c_config* cfg = (struct gd32_soft_i2c_config*)i2c->ops.data; + + rt_pin_mode(cfg->scl, PIN_MODE_OUTPUT_OD); + rt_pin_mode(cfg->sda, PIN_MODE_OUTPUT_OD); + + rt_pin_write(cfg->scl, PIN_HIGH); + rt_pin_write(cfg->sda, PIN_HIGH); +} + +/** + * @brief This function sets the sda pin. + * @param data, state + * @retval None + */ +static void gd32_set_sda(void *data, rt_int32_t state) +{ + struct gd32_soft_i2c_config* cfg = (struct gd32_soft_i2c_config*)data; + if (state) + { + rt_pin_write(cfg->sda, PIN_HIGH); + } + else + { + rt_pin_write(cfg->sda, PIN_LOW); + } +} + +/** + * @brief This function sets the scl pin. + * @param data, state + * @retval None + */ +static void gd32_set_scl(void *data, rt_int32_t state) +{ + struct gd32_soft_i2c_config* cfg = (struct gd32_soft_i2c_config*)data; + if (state) + { + rt_pin_write(cfg->scl, PIN_HIGH); + } + else + { + rt_pin_write(cfg->scl, PIN_LOW); + } +} + +/** + * @brief This function gets the sda pin state. + * @param data + * @retval None + */ +static rt_int32_t gd32_get_sda(void *data) +{ + struct gd32_soft_i2c_config* cfg = (struct gd32_soft_i2c_config*)data; + return rt_pin_read(cfg->sda); +} + + +/** + * @brief This function gets the scl pin state. + * @param data + * @retval None + */ +static rt_int32_t gd32_get_scl(void *data) +{ + struct gd32_soft_i2c_config* cfg = (struct gd32_soft_i2c_config*)data; + return rt_pin_read(cfg->scl); +} + +/** + * @brief The time delay function. + * @param us + * @retval None + */ +static void gd32_udelay(rt_uint32_t us) +{ + int i = ( rcu_clock_freq_get(CK_SYS) / 4000000 * us); + while(i) + { + i--; + } +} + +static const struct rt_i2c_bit_ops gd32_bit_ops_default = +{ + .data = RT_NULL, + .set_sda = gd32_set_sda, + .set_scl = gd32_set_scl, + .get_sda = gd32_get_sda, + .get_scl = gd32_get_scl, + .udelay = gd32_udelay, + .delay_us = 1, + .timeout = 100 +}; + +/** + * @brief if i2c is locked, this function will unlock it + * @param cfg + * @retval RT_EOK indicates successful unlock. + */ +static rt_err_t gd32_i2c_bus_unlock(const struct gd32_soft_i2c_config *cfg) +{ + rt_int32_t i = 0; + + if (PIN_LOW == rt_pin_read(cfg->sda)) + { + while (i++ < 9) + { + rt_pin_write(cfg->scl, PIN_HIGH); + gd32_udelay(100); + rt_pin_write(cfg->scl, PIN_LOW); + gd32_udelay(100); + } + } + if (PIN_LOW == rt_pin_read(cfg->sda)) + { + return -RT_ERROR; + } + + return RT_EOK; +} + +/** + * @brief I2C initialization function + * @param None + * @retval RT_EOK indicates successful initialization. + */ +int rt_hw_i2c_init(void) +{ + rt_size_t obj_num = sizeof(i2c_obj) / sizeof(struct gd32_i2c); + rt_err_t result; + + for (int i = 0; i < obj_num; i++) + { + i2c_obj[i].ops = gd32_bit_ops_default; + i2c_obj[i].ops.data = (void*)&soft_i2c_config[i]; + i2c_obj[i].i2c2_bus.priv = &i2c_obj[i].ops; + gd32_i2c_gpio_init(&i2c_obj[i]); + + result = rt_i2c_bit_add_bus(&i2c_obj[i].i2c2_bus, soft_i2c_config[i].bus_name); + + RT_ASSERT(result == RT_EOK); + + gd32_i2c_bus_unlock(&soft_i2c_config[i]); + + LOG_D("software simulation %s init done, pin scl: %d, pin sda %d", + soft_i2c_config[i].bus_name, + soft_i2c_config[i].scl, + soft_i2c_config[i].sda); + } + + return RT_EOK; +} +INIT_BOARD_EXPORT(rt_hw_i2c_init); + +#endif /* RT_USING_I2C */ diff --git a/bsp/gd32/libraries/gd32_drivers/drv_soft_i2c.h b/bsp/gd32/libraries/gd32_drivers/drv_soft_i2c.h new file mode 100644 index 0000000000..f7e8b32abf --- /dev/null +++ b/bsp/gd32/libraries/gd32_drivers/drv_soft_i2c.h @@ -0,0 +1,78 @@ +/* + * Copyright (c) 2006-2022, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2021-12-20 BruceOu the first version + */ + +#ifndef __DRV_I2C__ +#define __DRV_I2C__ + +#include +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* gd32 config class */ +struct gd32_soft_i2c_config +{ + rt_uint8_t scl; + rt_uint8_t sda; + const char *bus_name; +}; + +/* gd32 i2c dirver class */ +struct gd32_i2c +{ + struct rt_i2c_bit_ops ops; + struct rt_i2c_bus_device i2c2_bus; +}; + +#ifdef BSP_USING_I2C0 +#define I2C4_BUS_CONFIG \ + { \ + .scl = BSP_I2C0_SCL_PIN, \ + .sda = BSP_I2C0_SDA_PIN, \ + .bus_name = "i2c0", \ + } +#endif + +#ifdef BSP_USING_I2C1 +#define I2C1_BUS_CONFIG \ + { \ + .scl = BSP_I2C1_SCL_PIN, \ + .sda = BSP_I2C1_SDA_PIN, \ + .bus_name = "i2c1", \ + } +#endif + +#ifdef BSP_USING_I2C2 +#define I2C2_BUS_CONFIG \ + { \ + .scl = BSP_I2C2_SCL_PIN, \ + .sda = BSP_I2C2_SDA_PIN, \ + .bus_name = "i2c2", \ + } +#endif + +#ifdef BSP_USING_I2C3 +#define I2C3_BUS_CONFIG \ + { \ + .scl = BSP_I2C3_SCL_PIN, \ + .sda = BSP_I2C3_SDA_PIN, \ + .bus_name = "i2c3", \ + } +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* __DRV_I2C__ */ diff --git a/bsp/gd32/libraries/gd32_drivers/drv_spi.c b/bsp/gd32/libraries/gd32_drivers/drv_spi.c new file mode 100644 index 0000000000..023ae2c928 --- /dev/null +++ b/bsp/gd32/libraries/gd32_drivers/drv_spi.c @@ -0,0 +1,356 @@ +/* + * Copyright (c) 2006-2022, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2021-12-20 BruceOu first implementation + */ +#include "drv_spi.h" + +#ifdef RT_USING_SPI + +#if defined(BSP_USING_SPI0) || defined(BSP_USING_SPI1) || defined(BSP_USING_SPI2) +#define LOG_TAG "drv.spi" + +#include + +#ifdef BSP_USING_SPI0 +static struct rt_spi_bus spi_bus0; +#endif +#ifdef BSP_USING_SPI1 +static struct rt_spi_bus spi_bus1; +#endif +#ifdef BSP_USING_SPI2 +static struct rt_spi_bus spi_bus2; +#endif + +static const struct gd32_spi spi_bus_obj[] = { + +#ifdef BSP_USING_SPI0 + { + SPI0, + "spi0", + RCU_SPI0, + RCU_GPIOA, + &spi_bus0, + GPIOA, + GPIO_PIN_5, + GPIO_PIN_6, + GPIO_PIN_7, + } +#endif /* BSP_USING_SPI0 */ + +#ifdef BSP_USING_SPI1 + { + SPI1, + "spi1", + RCU_SPI1, + RCU_GPIOB, + &spi_bus1, + GPIOB, + GPIO_PIN_12, + GPIO_PIN_14, + GPIO_PIN_15, + } +#endif /* BSP_USING_SPI1 */ + +#ifdef BSP_USING_SPI2 + { + SPI2, + "spi2", + RCU_SPI2, + RCU_GPIOB, + &spi_bus2, + GPIOB, + GPIO_PIN_3, + GPIO_PIN_4, + GPIO_PIN_5, + } +#endif /* BSP_USING_SPI2 */ +}; + +/* private rt-thread spi ops function */ +static rt_err_t spi_configure(struct rt_spi_device* device, struct rt_spi_configuration* configuration); +static rt_uint32_t spixfer(struct rt_spi_device* device, struct rt_spi_message* message); + +static struct rt_spi_ops gd32_spi_ops = +{ + .configure = spi_configure, + .xfer = spixfer, +}; + +/** +* @brief SPI Initialization +* @param gd32_spi: SPI BUS +* @retval None +*/ +static void gd32_spi_init(struct gd32_spi *gd32_spi) +{ + /* enable SPI clock */ + rcu_periph_clock_enable(gd32_spi->spi_clk); + rcu_periph_clock_enable(gd32_spi->gpio_clk); + +#if defined SOC_SERIES_GD32F4xx + /*GPIO pin configuration*/ + gpio_af_set(gd32_spi->spi_port, GPIO_AF_5, gd32_spi->sck_pin | gd32_spi->mosi_pin | gd32_spi->miso_pin); + + gpio_mode_set(gd32_spi->spi_port, GPIO_MODE_AF, GPIO_PUPD_NONE, gd32_spi->miso_pin| gd32_spi->miso_pin); + gpio_output_options_set(gd32_spi->spi_port, GPIO_OTYPE_PP, GPIO_OSPEED_200MHZ,gd32_spi->miso_pin| gd32_spi->miso_pin); + +#else + /* Init SPI SCK MOSI */ + gpio_init(gd32_spi->spi_port, GPIO_MODE_AF_PP, GPIO_OSPEED_50MHZ, gd32_spi->sck_pin | gd32_spi->mosi_pin); + + /* Init SPI MISO */ + gpio_init(gd32_spi->spi_port, GPIO_MODE_IN_FLOATING, GPIO_OSPEED_50MHZ, gd32_spi->miso_pin); +#endif + +} + +static rt_err_t spi_configure(struct rt_spi_device* device, + struct rt_spi_configuration* configuration) +{ + struct rt_spi_bus * spi_bus = (struct rt_spi_bus *)device->bus; + struct gd32_spi *spi_device = (struct gd32_spi *)spi_bus->parent.user_data; + spi_parameter_struct spi_init_struct; + uint32_t spi_periph = spi_device->spi_periph; + + RT_ASSERT(device != RT_NULL); + RT_ASSERT(configuration != RT_NULL); + + //Init SPI + gd32_spi_init(spi_device); + + /* data_width */ + if(configuration->data_width <= 8) + { + spi_init_struct.frame_size = SPI_FRAMESIZE_8BIT; + } + else if(configuration->data_width <= 16) + { + spi_init_struct.frame_size = SPI_FRAMESIZE_16BIT; + } + else + { + return RT_EIO; + } + + /* baudrate */ + { + rcu_clock_freq_enum spi_src; + uint32_t spi_apb_clock; + uint32_t max_hz; + + max_hz = configuration->max_hz; + + LOG_D("sys freq: %d\n", rcu_clock_freq_get(CK_SYS)); + LOG_D("CK_APB2 freq: %d\n", rcu_clock_freq_get(CK_APB2)); + LOG_D("max freq: %d\n", max_hz); + + if (spi_periph == SPI1 || spi_periph == SPI2) + { + spi_src = CK_APB1; + } + else + { + spi_src = CK_APB2; + } + spi_apb_clock = rcu_clock_freq_get(spi_src); + + if(max_hz >= spi_apb_clock/2) + { + spi_init_struct.prescale = SPI_PSC_2; + } + else if (max_hz >= spi_apb_clock/4) + { + spi_init_struct.prescale = SPI_PSC_4; + } + else if (max_hz >= spi_apb_clock/8) + { + spi_init_struct.prescale = SPI_PSC_8; + } + else if (max_hz >= spi_apb_clock/16) + { + spi_init_struct.prescale = SPI_PSC_16; + } + else if (max_hz >= spi_apb_clock/32) + { + spi_init_struct.prescale = SPI_PSC_32; + } + else if (max_hz >= spi_apb_clock/64) + { + spi_init_struct.prescale = SPI_PSC_64; + } + else if (max_hz >= spi_apb_clock/128) + { + spi_init_struct.prescale = SPI_PSC_128; + } + else + { + /* min prescaler 256 */ + spi_init_struct.prescale = SPI_PSC_256; + } + } /* baudrate */ + + switch(configuration->mode & RT_SPI_MODE_3) + { + case RT_SPI_MODE_0: + spi_init_struct.clock_polarity_phase = SPI_CK_PL_LOW_PH_1EDGE; + break; + case RT_SPI_MODE_1: + spi_init_struct.clock_polarity_phase = SPI_CK_PL_LOW_PH_2EDGE; + break; + case RT_SPI_MODE_2: + spi_init_struct.clock_polarity_phase = SPI_CK_PL_HIGH_PH_1EDGE; + break; + case RT_SPI_MODE_3: + spi_init_struct.clock_polarity_phase = SPI_CK_PL_HIGH_PH_2EDGE; + break; + } + + /* MSB or LSB */ + if(configuration->mode & RT_SPI_MSB) + { + spi_init_struct.endian = SPI_ENDIAN_MSB; + } + else + { + spi_init_struct.endian = SPI_ENDIAN_LSB; + } + + spi_init_struct.trans_mode = SPI_TRANSMODE_FULLDUPLEX; + spi_init_struct.device_mode = SPI_MASTER; + spi_init_struct.nss = SPI_NSS_SOFT; + + spi_crc_off(spi_periph); + + /* init SPI */ + spi_init(spi_periph, &spi_init_struct); + /* Enable SPI_MASTER */ + spi_enable(spi_periph); + + return RT_EOK; +}; + +static rt_uint32_t spixfer(struct rt_spi_device* device, struct rt_spi_message* message) +{ + struct rt_spi_bus * gd32_spi_bus = (struct rt_spi_bus *)device->bus; + struct gd32_spi *spi_device = (struct gd32_spi *)gd32_spi_bus->parent.user_data; + struct rt_spi_configuration * config = &device->config; + struct gd32_spi_cs * gd32_spi_cs = device->parent.user_data; + uint32_t spi_periph = spi_device->spi_periph; + + RT_ASSERT(device != NULL); + RT_ASSERT(message != NULL); + + /* take CS */ + if(message->cs_take) + { + gpio_bit_reset(gd32_spi_cs->GPIOx, gd32_spi_cs->GPIO_Pin); + LOG_D("spi take cs\n"); + } + + { + if(config->data_width <= 8) + { + const rt_uint8_t * send_ptr = message->send_buf; + rt_uint8_t * recv_ptr = message->recv_buf; + rt_uint32_t size = message->length; + + LOG_D("spi poll transfer start: %d\n", size); + + while(size--) + { + rt_uint8_t data = 0xFF; + + if(send_ptr != RT_NULL) + { + data = *send_ptr++; + } + + // Todo: replace register read/write by gd32f4 lib + //Wait until the transmit buffer is empty + while(RESET == spi_i2s_flag_get(spi_periph, SPI_FLAG_TBE)); + // Send the byte + spi_i2s_data_transmit(spi_periph, data); + + //Wait until a data is received + while(RESET == spi_i2s_flag_get(spi_periph, SPI_FLAG_RBNE)); + // Get the received data + data = spi_i2s_data_receive(spi_periph); + + if(recv_ptr != RT_NULL) + { + *recv_ptr++ = data; + } + } + LOG_D("spi poll transfer finsh\n"); + } + else if(config->data_width <= 16) + { + const rt_uint16_t * send_ptr = message->send_buf; + rt_uint16_t * recv_ptr = message->recv_buf; + rt_uint32_t size = message->length; + + while(size--) + { + rt_uint16_t data = 0xFF; + + if(send_ptr != RT_NULL) + { + data = *send_ptr++; + } + + //Wait until the transmit buffer is empty + while(RESET == spi_i2s_flag_get(spi_periph, SPI_FLAG_TBE)); + // Send the byte + spi_i2s_data_transmit(spi_periph, data); + + //Wait until a data is received + while(RESET == spi_i2s_flag_get(spi_periph, SPI_FLAG_RBNE)); + // Get the received data + data = spi_i2s_data_receive(spi_periph); + + if(recv_ptr != RT_NULL) + { + *recv_ptr++ = data; + } + } + } + } + + /* release CS */ + if(message->cs_release) + { + gpio_bit_set(gd32_spi_cs->GPIOx, gd32_spi_cs->GPIO_Pin); + LOG_D("spi release cs\n"); + } + + return message->length; +}; + +int rt_hw_spi_init(void) +{ + int result = 0; + int i; + + for (i = 0; i < sizeof(spi_bus_obj) / sizeof(spi_bus_obj[0]); i++) + { + spi_bus_obj[i].spi_bus->parent.user_data = (void *)&spi_bus_obj[i]; + + result = rt_spi_bus_register(spi_bus_obj[i].spi_bus, spi_bus_obj[i].bus_name, &gd32_spi_ops); + + RT_ASSERT(result == RT_EOK); + + LOG_D("%s bus init done", spi_bus_obj[i].bus_name); + } + + return result; +} + +INIT_BOARD_EXPORT(rt_hw_spi_init); + +#endif /* BSP_USING_SPI0 || BSP_USING_SPI1 || BSP_USING_SPI2 */ +#endif /* RT_USING_SPI */ diff --git a/bsp/gd32/libraries/gd32_drivers/drv_spi.h b/bsp/gd32/libraries/gd32_drivers/drv_spi.h new file mode 100644 index 0000000000..6359d75bd1 --- /dev/null +++ b/bsp/gd32/libraries/gd32_drivers/drv_spi.h @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2006-2022, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2021-12-20 BruceOu first implementation + */ + +#ifndef __DRV_SPI_H__ +#define __DRV_SPI_H__ + +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +struct gd32_spi_cs +{ + uint32_t GPIOx; + uint32_t GPIO_Pin; +}; + +/* gd32 spi dirver class */ +struct gd32_spi +{ + uint32_t spi_periph; + char *bus_name; + rcu_periph_enum spi_clk; + rcu_periph_enum gpio_clk; + struct rt_spi_bus *spi_bus; + uint32_t spi_port; + uint16_t sck_pin; + uint16_t miso_pin; + uint16_t mosi_pin; +}; + +#ifdef __cplusplus +} +#endif + +#endif /* __DRV_SPI_H__ */ diff --git a/bsp/gd32/libraries/gd32_drivers/drv_spi_flash.c b/bsp/gd32/libraries/gd32_drivers/drv_spi_flash.c new file mode 100644 index 0000000000..ea2750d7cd --- /dev/null +++ b/bsp/gd32/libraries/gd32_drivers/drv_spi_flash.c @@ -0,0 +1,87 @@ +/* + * Copyright (c) 2006-2022, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2021-12-31 BruceOu first implementation + */ +#include +#include "drv_spi.h" +#include "spi_flash.h" + +#ifdef RT_USING_SFUD +#include "spi_flash_sfud.h" +#endif + +#include +#include + +#define SPI_BUS_NAME "spi0" +#define SPI_DEVICE_NAME "spi01" +#define SPI_FLASH_DEVICE_NAME "gd25q" + +#define GD25Q_SPI_CS_GPIOX GPIOE +#define GD25Q_SPI_CS_GPIOX_PIN_X GPIO_PIN_3 + +static int rt_hw_spi_flash_init(void) +{ + rt_err_t res; + static struct rt_spi_device spi_dev_gd25q; /* SPI device */ + static struct gd32_spi_cs spi_cs; + spi_cs.GPIOx = GD25Q_SPI_CS_GPIOX; + spi_cs.GPIO_Pin = GD25Q_SPI_CS_GPIOX_PIN_X; + +#if defined SOC_SERIES_GD32F4xx + gpio_mode_set(spi_cs.GPIOx, GPIO_MODE_OUTPUT, GPIO_PUPD_NONE, spi_cs.GPIO_Pin); + gpio_output_options_set(spi_cs.GPIOx, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, spi_cs.GPIO_Pin); + + gpio_bit_set(spi_cs.GPIOx, spi_cs.GPIO_Pin); +#else + gpio_init(spi_cs.GPIOx, GPIO_MODE_AF_PP, GPIO_OSPEED_50MHZ, spi_cs.GPIO_Pin); + +#endif + res = rt_spi_bus_attach_device(&spi_dev_gd25q, SPI_FLASH_DEVICE_NAME, SPI_BUS_NAME, (void*)&spi_cs); + + if (res != RT_EOK) + { + rt_kprintf("rt_spi_bus_attach_device() run failed!\n"); + return res; + } + + return RT_EOK; +} +INIT_DEVICE_EXPORT(rt_hw_spi_flash_init); + +#ifdef RT_USING_SFUD +static int rt_hw_spi_flash_with_sfud_init(void) +{ + if (RT_NULL == rt_sfud_flash_probe(SPI_FLASH_CHIP, SPI_FLASH_DEVICE_NAME)) + { + return RT_ERROR; + }; + + return RT_EOK; +} +INIT_COMPONENT_EXPORT(rt_hw_spi_flash_with_sfud_init) +#endif + +#ifdef RT_USING_DFS +#include + +int mnt_init(void) +{ + if (dfs_mount(SPI_FLASH_DEVICE_NAME, "/", "elm", 0, 0) == 0) + { + rt_kprintf("spi flash mount success !\n"); + } + else + { + rt_kprintf("spi flash mount failed!\n"); + } + + return 0; +} +MSH_CMD_EXPORT(mnt_init, mount spi flash to file system); +#endif diff --git a/bsp/gd32/libraries/HAL_Drivers/drv_usart.c b/bsp/gd32/libraries/gd32_drivers/drv_usart.c similarity index 77% rename from bsp/gd32/libraries/HAL_Drivers/drv_usart.c rename to bsp/gd32/libraries/gd32_drivers/drv_usart.c index 54a36d6f73..7671b6da4f 100644 --- a/bsp/gd32/libraries/HAL_Drivers/drv_usart.c +++ b/bsp/gd32/libraries/gd32_drivers/drv_usart.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006-2021, RT-Thread Development Team + * Copyright (c) 2006-2022, RT-Thread Development Team * * SPDX-License-Identifier: Apache-2.0 * @@ -7,8 +7,8 @@ * Date Author Notes * 2021-08-20 BruceOu first implementation */ + #include "drv_usart.h" -#include #ifdef RT_USING_SERIAL @@ -22,27 +22,7 @@ #include -/* GD32 uart driver */ -// Todo: compress uart info -struct gd32_uart -{ - uint32_t uart_periph; //Todo: 3bits - IRQn_Type irqn; //Todo: 7bits - rcu_periph_enum per_clk; //Todo: 5bits - rcu_periph_enum tx_gpio_clk; //Todo: 5bits - rcu_periph_enum rx_gpio_clk; //Todo: 5bits - uint32_t tx_port; //Todo: 4bits - uint16_t tx_af; //Todo: 4bits - uint16_t tx_pin; //Todo: 4bits - uint32_t rx_port; //Todo: 4bits - uint16_t rx_af; //Todo: 4bits - uint16_t rx_pin; //Todo: 4bits - - struct rt_serial_device * serial; - char *device_name; -}; - -static void uart_isr(struct rt_serial_device *serial); +static void GD32_UART_IRQHandler(struct rt_serial_device *serial); #if defined(BSP_USING_UART0) struct rt_serial_device serial0; @@ -52,7 +32,7 @@ void USART0_IRQHandler(void) /* enter interrupt */ rt_interrupt_enter(); - uart_isr(&serial0); + GD32_UART_IRQHandler(&serial0); /* leave interrupt */ rt_interrupt_leave(); @@ -68,7 +48,7 @@ void USART1_IRQHandler(void) /* enter interrupt */ rt_interrupt_enter(); - uart_isr(&serial1); + GD32_UART_IRQHandler(&serial1); /* leave interrupt */ rt_interrupt_leave(); @@ -84,7 +64,7 @@ void USART2_IRQHandler(void) /* enter interrupt */ rt_interrupt_enter(); - uart_isr(&serial2); + GD32_UART_IRQHandler(&serial2); /* leave interrupt */ rt_interrupt_leave(); @@ -100,7 +80,7 @@ void UART3_IRQHandler(void) /* enter interrupt */ rt_interrupt_enter(); - uart_isr(&serial3); + GD32_UART_IRQHandler(&serial3); /* leave interrupt */ rt_interrupt_leave(); @@ -116,7 +96,7 @@ void UART4_IRQHandler(void) /* enter interrupt */ rt_interrupt_enter(); - uart_isr(&serial4); + GD32_UART_IRQHandler(&serial4); /* leave interrupt */ rt_interrupt_leave(); @@ -131,7 +111,7 @@ void USART5_IRQHandler(void) /* enter interrupt */ rt_interrupt_enter(); - uart_isr(&serial5); + GD32_UART_IRQHandler(&serial5); /* leave interrupt */ rt_interrupt_leave(); @@ -147,7 +127,7 @@ void UART6_IRQHandler(void) /* enter interrupt */ rt_interrupt_enter(); - uart_isr(&serial6); + GD32_UART_IRQHandler(&serial6); /* leave interrupt */ rt_interrupt_leave(); @@ -163,7 +143,7 @@ void UART7_IRQHandler(void) /* enter interrupt */ rt_interrupt_enter(); - uart_isr(&serial7); + GD32_UART_IRQHandler(&serial7); /* leave interrupt */ rt_interrupt_leave(); @@ -171,14 +151,19 @@ void UART7_IRQHandler(void) #endif /* BSP_USING_UART7 */ -static const struct gd32_uart uarts[] = { +static const struct gd32_uart uart_obj[] = { #ifdef BSP_USING_UART0 { USART0, // uart peripheral index USART0_IRQn, // uart iqrn RCU_USART0, RCU_GPIOA, RCU_GPIOA, // periph clock, tx gpio clock, rt gpio clock +#if defined SOC_SERIES_GD32F4xx GPIOA, GPIO_AF_7, GPIO_PIN_9, // tx port, tx alternate, tx pin GPIOA, GPIO_AF_7, GPIO_PIN_10, // rx port, rx alternate, rx pin +#else + GPIOA, GPIO_PIN_9, // tx port, tx pin + GPIOA, GPIO_PIN_10, // rx port, rx pin +#endif &serial0, "uart0", }, @@ -189,8 +174,13 @@ static const struct gd32_uart uarts[] = { USART1, // uart peripheral index USART1_IRQn, // uart iqrn RCU_USART1, RCU_GPIOA, RCU_GPIOA, // periph clock, tx gpio clock, rt gpio clock +#if defined SOC_SERIES_GD32F4xx GPIOA, GPIO_AF_7, GPIO_PIN_2, // tx port, tx alternate, tx pin GPIOA, GPIO_AF_7, GPIO_PIN_3, // rx port, rx alternate, rx pin +#else + GPIOA, GPIO_PIN_2, // tx port, tx pin + GPIOA, GPIO_PIN_3, // rx port, rx pin +#endif &serial1, "uart1", }, @@ -201,8 +191,13 @@ static const struct gd32_uart uarts[] = { USART2, // uart peripheral index USART2_IRQn, // uart iqrn RCU_USART2, RCU_GPIOB, RCU_GPIOB, // periph clock, tx gpio clock, rt gpio clock +#if defined SOC_SERIES_GD32F4xx GPIOB, GPIO_AF_7, GPIO_PIN_10, // tx port, tx alternate, tx pin GPIOB, GPIO_AF_7, GPIO_PIN_11, // rx port, rx alternate, rx pin +#else + GPIOB, GPIO_PIN_10, // tx port, tx pin + GPIOB, GPIO_PIN_11, // rx port, rx pin +#endif &serial2, "uart2", }, @@ -213,8 +208,13 @@ static const struct gd32_uart uarts[] = { UART3, // uart peripheral index UART3_IRQn, // uart iqrn RCU_UART3, RCU_GPIOC, RCU_GPIOC, // periph clock, tx gpio clock, rt gpio clock +#if defined SOC_SERIES_GD32F4xx GPIOC, GPIO_AF_8, GPIO_PIN_10, // tx port, tx alternate, tx pin GPIOC, GPIO_AF_8, GPIO_PIN_11, // rx port, rx alternate, rx pin +#else + GPIOC, GPIO_PIN_10, // tx port, tx pin + GPIOC, GPIO_PIN_11, // rx port, rx pin +#endif &serial3, "uart3", }, @@ -225,8 +225,13 @@ static const struct gd32_uart uarts[] = { UART4, // uart peripheral index UART4_IRQn, // uart iqrn RCU_UART4, RCU_GPIOC, RCU_GPIOD, // periph clock, tx gpio clock, rt gpio clock +#if defined SOC_SERIES_GD32F4xx GPIOC, GPIO_AF_8, GPIO_PIN_12, // tx port, tx alternate, tx pin GPIOD, GPIO_AF_8, GPIO_PIN_2, // rx port, rx alternate, rx pin +#else + GPIOC, GPIO_PIN_12, // tx port, tx pin + GPIOD, GPIO_PIN_2, // rx port, rx pin +#endif &serial4, "uart4", }, @@ -237,8 +242,13 @@ static const struct gd32_uart uarts[] = { USART5, // uart peripheral index USART5_IRQn, // uart iqrn RCU_USART5, RCU_GPIOC, RCU_GPIOC, // periph clock, tx gpio clock, rt gpio clock +#if defined SOC_SERIES_GD32F4xx GPIOC, GPIO_AF_8, GPIO_PIN_6, // tx port, tx alternate, tx pin GPIOC, GPIO_AF_8, GPIO_PIN_7, // rx port, rx alternate, rx pin +#else + GPIOC, GPIO_PIN_6, // tx port, tx pin + GPIOC, GPIO_PIN_7, // rx port, rx pin +#endif &serial5, "uart5", }, @@ -249,8 +259,13 @@ static const struct gd32_uart uarts[] = { UART6, // uart peripheral index UART6_IRQn, // uart iqrn RCU_UART6, RCU_GPIOE, RCU_GPIOE, // periph clock, tx gpio clock, rt gpio clock +#if defined SOC_SERIES_GD32F4xx GPIOE, GPIO_AF_8, GPIO_PIN_7, // tx port, tx alternate, tx pin GPIOE, GPIO_AF_8, GPIO_PIN_8, // rx port, rx alternate, rx pin +#else + GPIOE, GPIO_PIN_7, // tx port, tx pin + GPIOE, GPIO_PIN_8, // rx port, rx pin +#endif &serial6, "uart6", }, @@ -261,8 +276,13 @@ static const struct gd32_uart uarts[] = { UART7, // uart peripheral index UART7_IRQn, // uart iqrn RCU_UART7, RCU_GPIOE, RCU_GPIOE, // periph clock, tx gpio clock, rt gpio clock +#if defined SOC_SERIES_GD32F4xx GPIOE, GPIO_AF_8, GPIO_PIN_0, // tx port, tx alternate, tx pin GPIOE, GPIO_AF_8, GPIO_PIN_1, // rx port, rx alternate, rx pin +#else + GPIOE, GPIO_PIN_0, // tx port, tx pin + GPIOE, GPIO_PIN_1, // rx port, rx pin +#endif &serial7, "uart7", }, @@ -286,6 +306,7 @@ void gd32_uart_gpio_init(struct gd32_uart *uart) rcu_periph_clock_enable(uart->rx_gpio_clk); rcu_periph_clock_enable(uart->per_clk); +#if defined SOC_SERIES_GD32F4xx /* connect port to USARTx_Tx */ gpio_af_set(uart->tx_port, uart->tx_af, uart->tx_pin); @@ -300,11 +321,24 @@ void gd32_uart_gpio_init(struct gd32_uart *uart) gpio_mode_set(uart->rx_port, GPIO_MODE_AF, GPIO_PUPD_PULLUP, uart->rx_pin); gpio_output_options_set(uart->rx_port, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, uart->rx_pin); +#else + /* connect port to USARTx_Tx */ + gpio_init(uart->tx_port, GPIO_MODE_AF_PP, GPIO_OSPEED_50MHZ, uart->tx_pin); + + /* connect port to USARTx_Rx */ + gpio_init(uart->rx_port, GPIO_MODE_IN_FLOATING, GPIO_OSPEED_50MHZ, uart->rx_pin); +#endif + NVIC_SetPriority(uart->irqn, 0); NVIC_EnableIRQ(uart->irqn); } -static rt_err_t _uart_configure(struct rt_serial_device *serial, struct serial_configure *cfg) +/** + * @brief uart configure + * @param serial, cfg + * @retval None + */ +static rt_err_t gd32_uart_configure(struct rt_serial_device *serial, struct serial_configure *cfg) { struct gd32_uart *uart; @@ -358,7 +392,12 @@ static rt_err_t _uart_configure(struct rt_serial_device *serial, struct serial_c return RT_EOK; } -static rt_err_t _uart_control(struct rt_serial_device *serial, int cmd, void *arg) +/** + * @brief uart control + * @param serial, arg + * @retval None + */ +static rt_err_t gd32_uart_control(struct rt_serial_device *serial, int cmd, void *arg) { struct gd32_uart *uart; @@ -385,7 +424,12 @@ static rt_err_t _uart_control(struct rt_serial_device *serial, int cmd, void *ar return RT_EOK; } -static int _uart_putc(struct rt_serial_device *serial, char ch) +/** + * @brief uart put char + * @param serial, ch + * @retval None + */ +static int gd32_uart_putc(struct rt_serial_device *serial, char ch) { struct gd32_uart *uart; @@ -398,7 +442,12 @@ static int _uart_putc(struct rt_serial_device *serial, char ch) return RT_EOK; } -static int _uart_getc(struct rt_serial_device *serial) +/** + * @brief uart get char + * @param serial + * @retval None + */ +static int gd32_uart_getc(struct rt_serial_device *serial) { int ch; struct gd32_uart *uart; @@ -417,7 +466,7 @@ static int _uart_getc(struct rt_serial_device *serial) * * @param serial serial device */ -static void uart_isr(struct rt_serial_device *serial) +static void GD32_UART_IRQHandler(struct rt_serial_device *serial) { struct gd32_uart *uart = (struct gd32_uart *) serial->parent.user_data; @@ -435,12 +484,18 @@ static void uart_isr(struct rt_serial_device *serial) static const struct rt_uart_ops gd32_uart_ops = { - _uart_configure, - _uart_control, - _uart_putc, - _uart_getc, + .configure = gd32_uart_configure, + .control = gd32_uart_control, + .putc = gd32_uart_putc, + .getc = gd32_uart_getc, + RT_NULL, }; +/** + * @brief uart init + * @param None + * @retval None + */ int gd32_hw_usart_init(void) { struct serial_configure config = RT_SERIAL_CONFIG_DEFAULT; @@ -448,20 +503,22 @@ int gd32_hw_usart_init(void) int result; - for (i = 0; i < sizeof(uarts) / sizeof(uarts[0]); i++) + for (i = 0; i < sizeof(uart_obj) / sizeof(uart_obj[0]); i++) { - uarts[i].serial->ops = &gd32_uart_ops; - uarts[i].serial->config = config; + uart_obj[i].serial->ops = &gd32_uart_ops; + uart_obj[i].serial->config = config; /* register UART1 device */ - result = rt_hw_serial_register(uarts[i].serial, - uarts[i].device_name, + result = rt_hw_serial_register(uart_obj[i].serial, + uart_obj[i].device_name, RT_DEVICE_FLAG_RDWR | RT_DEVICE_FLAG_INT_RX, - (void *)&uarts[i]); + (void *)&uart_obj[i]); RT_ASSERT(result == RT_EOK); } return result; } + INIT_BOARD_EXPORT(gd32_hw_usart_init); + #endif diff --git a/bsp/gd32/libraries/gd32_drivers/drv_usart.h b/bsp/gd32/libraries/gd32_drivers/drv_usart.h new file mode 100644 index 0000000000..824cc9c812 --- /dev/null +++ b/bsp/gd32/libraries/gd32_drivers/drv_usart.h @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2006-2022, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2021-08-20 BruceOu first implementation + */ + +#ifndef __DRV_USART_H__ +#define __DRV_USART_H__ + +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +#define UART_ENABLE_IRQ(n) NVIC_EnableIRQ((n)) +#define UART_DISABLE_IRQ(n) NVIC_DisableIRQ((n)) + + +/* GD32 uart driver */ +// Todo: compress uart info +struct gd32_uart +{ + uint32_t uart_periph; //Todo: 3bits + IRQn_Type irqn; //Todo: 7bits + rcu_periph_enum per_clk; //Todo: 5bits + rcu_periph_enum tx_gpio_clk; //Todo: 5bits + rcu_periph_enum rx_gpio_clk; //Todo: 5bits + uint32_t tx_port; //Todo: 4bits +#if defined SOC_SERIES_GD32F4xx + uint16_t tx_af; //Todo: 4bits +#endif + uint16_t tx_pin; //Todo: 4bits + uint32_t rx_port; //Todo: 4bits +#if defined SOC_SERIES_GD32F4xx + uint16_t rx_af; //Todo: 4bits +#endif + uint16_t rx_pin; //Todo: 4bits + + struct rt_serial_device * serial; + char *device_name; +}; + +#ifdef __cplusplus +} +#endif + +#endif /* __DRV_USART_H__ */ diff --git a/bsp/gd32/tools/sdk_dist.py b/bsp/gd32/tools/sdk_dist.py index cc5ccce7c6..d6f97a3835 100644 --- a/bsp/gd32/tools/sdk_dist.py +++ b/bsp/gd32/tools/sdk_dist.py @@ -5,7 +5,20 @@ import shutil cwd_path = os.getcwd() sys.path.append(os.path.join(os.path.dirname(cwd_path), 'rt-thread', 'tools')) +def bsp_update_board_kconfig(dist_dir): + # change board/kconfig path + if not os.path.isfile(os.path.join(dist_dir, 'board/Kconfig')): + return + with open(os.path.join(dist_dir, 'board/Kconfig'), 'r') as f: + data = f.readlines() + with open(os.path.join(dist_dir, 'board/Kconfig'), 'w') as f: + for line in data: + if line.find('../libraries/gd32_drivers/Kconfig') != -1: + position = line.find('../libraries/gd32_drivers/Kconfig') + line = line[0:position] + 'libraries/gd32_drivers/Kconfig"\n' + f.write(line) + # BSP dist function def dist_do_building(BSP_ROOT, dist_dir): from mkdist import bsp_copy_files @@ -18,5 +31,7 @@ def dist_do_building(BSP_ROOT, dist_dir): os.path.join(library_dir, rtconfig.BSP_LIBRARY_TYPE)) print("=> copy bsp drivers") - bsp_copy_files(os.path.join(library_path, 'HAL_Drivers'), os.path.join(library_dir, 'HAL_Drivers')) + bsp_copy_files(os.path.join(library_path, 'gd32_drivers'), os.path.join(library_dir, 'gd32_drivers')) shutil.copyfile(os.path.join(library_path, 'Kconfig'), os.path.join(library_dir, 'Kconfig')) + + bsp_update_board_kconfig(dist_dir)