diff --git a/bsp/nuclei/README.md b/bsp/nuclei/README.md new file mode 100644 index 0000000000..65e5dc655e --- /dev/null +++ b/bsp/nuclei/README.md @@ -0,0 +1,16 @@ +# Nuclei RISC-V Processor Support Package + +This directory provided support for [Nuclei RISC-V Processor](https://nucleisys.com/) based board, currently +we mainly provided the following support package. + +| **BSP** | **Development Board Name** | +| :----------------------------------- | :-------------------------------------------------------------------------------------------------------------------------- | +| [gd32vf103_rvstar](gd32vf103_rvstar) | [Nuclei RV-STAR Arduino Compatible Development Board](https://www.riscv-mcu.com/quickstart-quickstart-index-u-RV_STAR.html) | + +**If you want to learn more about Nuclei Processors, please click the following links:** + +* [Professional RISC-V IPs](https://nucleisys.com/product.php) +* [Professional Nuclei Processor Development Boards](https://nucleisys.com/developboard.php) +* [Comprehensive Documents and Development Tools](https://nucleisys.com/download.php) +* [Active RISC-V IP and MCU Community](https://www.rvmcu.com/) +* [Professional University Program](https://nucleisys.com/campus.php) \ No newline at end of file diff --git a/bsp/nuclei/gd32vf103_rvstar/.config b/bsp/nuclei/gd32vf103_rvstar/.config index c68135acc4..00a3354fde 100644 --- a/bsp/nuclei/gd32vf103_rvstar/.config +++ b/bsp/nuclei/gd32vf103_rvstar/.config @@ -78,7 +78,7 @@ CONFIG_ARCH_RISCV32=y # CONFIG_RT_USING_COMPONENTS_INIT=y CONFIG_RT_USING_USER_MAIN=y -CONFIG_RT_MAIN_THREAD_STACK_SIZE=2048 +CONFIG_RT_MAIN_THREAD_STACK_SIZE=1024 CONFIG_RT_MAIN_THREAD_PRIORITY=10 # @@ -97,7 +97,7 @@ CONFIG_FINSH_USING_SYMTAB=y CONFIG_FINSH_USING_DESCRIPTION=y # CONFIG_FINSH_ECHO_DISABLE_DEFAULT is not set CONFIG_FINSH_THREAD_PRIORITY=20 -CONFIG_FINSH_THREAD_STACK_SIZE=4096 +CONFIG_FINSH_THREAD_STACK_SIZE=2048 CONFIG_FINSH_CMD_SIZE=80 # CONFIG_FINSH_USING_AUTH is not set CONFIG_FINSH_USING_MSH=y @@ -108,27 +108,18 @@ CONFIG_FINSH_ARG_MAX=10 # # Device virtual file system # -CONFIG_RT_USING_DFS=y -CONFIG_DFS_USING_WORKDIR=y -CONFIG_DFS_FILESYSTEMS_MAX=2 -CONFIG_DFS_FILESYSTEM_TYPES_MAX=2 -CONFIG_DFS_FD_MAX=16 -# CONFIG_RT_USING_DFS_MNTTABLE is not set -# CONFIG_RT_USING_DFS_ELMFAT is not set -CONFIG_RT_USING_DFS_DEVFS=y -# CONFIG_RT_USING_DFS_ROMFS is not set -# CONFIG_RT_USING_DFS_RAMFS is not set -# CONFIG_RT_USING_DFS_UFFS is not set -# CONFIG_RT_USING_DFS_JFFS2 is not set +# 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 is not set +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_SERIAL_USING_DMA=y +# CONFIG_RT_SERIAL_USING_DMA is not set CONFIG_RT_SERIAL_RB_BUFSZ=64 # CONFIG_RT_USING_CAN is not set # CONFIG_RT_USING_HWTIMER is not set @@ -163,10 +154,6 @@ CONFIG_RT_USING_PIN=y # CONFIG_RT_USING_LIBC=y # CONFIG_RT_USING_PTHREADS is not set -CONFIG_RT_USING_POSIX=y -# CONFIG_RT_USING_POSIX_MMAP is not set -# CONFIG_RT_USING_POSIX_TERMIOS is not set -# CONFIG_RT_USING_POSIX_AIO is not set # CONFIG_RT_USING_MODULE is not set # @@ -218,6 +205,7 @@ CONFIG_RT_USING_POSIX=y # 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 @@ -244,6 +232,7 @@ CONFIG_RT_USING_POSIX=y # 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 @@ -320,6 +309,7 @@ CONFIG_RT_USING_POSIX=y # 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_URLENCODE is not set # # system packages @@ -330,6 +320,7 @@ CONFIG_RT_USING_POSIX=y # CONFIG_PKG_USING_LWEXT4 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_LITTLEVGL2RTT is not set @@ -361,6 +352,7 @@ CONFIG_RT_USING_POSIX=y # 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 @@ -386,10 +378,15 @@ CONFIG_RT_USING_POSIX=y # CONFIG_PKG_USING_EASYBLINK is not set # CONFIG_PKG_USING_PMS_SERIES is not set CONFIG_PKG_USING_NUCLEI_SDK=y + +# +# !!!Nuclei SDK only works with Nuclei RISC-V Processor IP!!! +# CONFIG_PKG_NUCLEI_SDK_PATH="/packages/peripherals/nuclei_sdk" # CONFIG_PKG_USING_NUCLEI_SDK_V023 is not set CONFIG_PKG_USING_NUCLEI_SDK_LATEST_VERSION=y CONFIG_PKG_NUCLEI_SDK_VER="latest" +# CONFIG_PKG_USING_CAN_YMODEM is not set # # miscellaneous packages @@ -446,6 +443,13 @@ CONFIG_BSP_USING_UART=y # CONFIG_BSP_USING_UART2 is not set # CONFIG_BSP_USING_UART3 is not set CONFIG_BSP_USING_UART4=y +# CONFIG_BSP_USING_I2C is not set +# CONFIG_BSP_USING_SPI is not set +# CONFIG_BSP_USING_HWTIMER is not set +# CONFIG_BSP_USING_ADC is not set +# CONFIG_BSP_USING_WDT is not set +# CONFIG_BSP_USING_RTC is not set +# CONFIG_BSP_USING_PWM is not set # # Board extended module Drivers diff --git a/bsp/nuclei/gd32vf103_rvstar/README.md b/bsp/nuclei/gd32vf103_rvstar/README.md index f9575aa2ee..5b8c61804a 100644 --- a/bsp/nuclei/gd32vf103_rvstar/README.md +++ b/bsp/nuclei/gd32vf103_rvstar/README.md @@ -2,17 +2,17 @@ ## 简介 -**RVSTAR开发板** 是由芯来科技公司推出的基于采用芯来科技RISC-V架构处理器芯片的GD32VF103的开发板。 +**RVSTAR开发板** 是由[芯来科技Nuclei](https://nucleisys.com/)公司推出的基于采用芯来科技RISC-V架构处理器芯片的GD32VF103的开发板。 更多关于 **RVSTAR开发板** 开发板的详细资料请参见 [RVSTAR开发板快速入门](https://www.rvmcu.com/quickstart-quickstart-index-u-RV_STAR.html) ### 板载资源 -| 硬件 | 描述 | -| --- | --- | -| 内核 | Nuclei N205 | +| 硬件 | 描述 | +| ---- | --------------- | +| 内核 | Nuclei N205 | | 架构 | 32-bit RV32IMAC | -| 主频 | 108 MHz | +| 主频 | 108 MHz | ## 工具安装 @@ -75,27 +75,28 @@ export PATH=~/Software/Nuclei/gcc/bin:~/Software/Nuclei/openocd/bin:$PATH 正常下载的输出如下: -~~~ +~~~bat +57856@DESKTOP-4LATIEU D:\workspace\Sourcecode\rt-thread\bsp\nuclei\gd32vf103_rvstar +> scons --run upload scons: Reading SConscript files ... Supported downloaded modes for board gd32vf103v_rvstar are flashxip, chosen downloaded mode is flashxip Upload application rtthread.elf using openocd and gdb riscv-nuclei-elf-gdb rtthread.elf -ex "set remotetimeout 240" -ex "target remote | openocd --pipe -f D:/workspace/Sourcecode/rt-thread/bsp/nuclei/gd32vf103_rvstar/packages/nuclei_sdk-latest/SoC/gd32vf103/Board/gd32vf103v_rvstar/openocd_gd32vf103.cfg" --batch -ex "monitor halt" -ex "monitor flash protect 0 0 last off" -ex "load" -ex "monitor resume" -ex "monitor shutdown" -ex "quit" D:\Software\Nuclei\gcc\bin\riscv-nuclei-elf-gdb.exe: warning: Couldn't determine a path for the index cache directory. - Nuclei OpenOCD, 64-bit Open On-Chip Debugger 0.10.0+dev-00014-g0eae03214 (2019-12-12-07:43) Licensed under GNU GPL v2 For bug reports, read http://openocd.org/doc/doxygen/bugs.html -rt_thread_idle_entry (parameter=0x0) at D:\workspace\Sourcecode\rt-thread\src\idle.c:251 -251 if (idle_hook_list[i] != RT_NULL) +rt_assert_handler (ex_string=ex_string@entry=0x800ab10 "0", func=func@entry=0x800ac14 <__FUNCTION__.3090> "rt_sem_take", line=line@entry=363) at D:\workspace\Sourcecode\rt-thread\src\kservice.c:1371 +1371 while (dummy == 0); cleared protection for sectors 0 through 127 on flash bank 0 Loading section .init, size 0x264 lma 0x8000000 -Loading section .text, size 0x140de lma 0x8000280 -Loading section .rodata, size 0x37c0 lma 0x8014360 -Loading section .data, size 0x404 lma 0x8017b20 -Start address 0x800015c, load size 98054 -Transfer rate: 8 KB/sec, 10894 bytes/write. +Loading section .text, size 0xa646 lma 0x8000280 +Loading section .rodata, size 0x2a80 lma 0x800a8c8 +Loading section .data, size 0x350 lma 0x800d348 +Start address 0x800015c, load size 54906 +Transfer rate: 6 KB/sec, 9151 bytes/write. shutdown command invoked A debugging session is active. @@ -112,38 +113,55 @@ initialize rti_board_start:0 done \ | / - RT - Thread Operating System - / | \ 4.0.3 build Apr 9 2020 + / | \ 4.0.3 build Jun 9 2020 2006 - 2020 Copyright by rt-thread team do components initialization. initialize rti_board_end:0 done -initialize dfs_init:0 done +initialize rt_work_sys_workqueue_init:0 done +initialize rt_hw_pin_init:0 done initialize libc_system_init:0 done initialize finsh_system_init:0 done -msh /> +msh > ``` 在串口终端(我这里使用的是TeraTerm)输入``ps``即可查看当前线程工作情况: ~~~ -msh />ps +msh >ps thread pri status sp stack size max used left tick error -------- --- ------- ---------- ---------- ------ ---------- --- -thread01 19 suspend 0x00000158 0x0000018c 87% 0x00000005 000 -thread00 19 suspend 0x00000158 0x0000018c 87% 0x00000005 000 -tshell 20 running 0x00000258 0x00001000 18% 0x00000004 000 -tidle0 31 ready 0x000000a8 0x0000018c 59% 0x0000000e 000 -timer 4 suspend 0x000000f8 0x00000200 49% 0x00000009 000 -main 10 suspend 0x00000168 0x00000800 36% 0x00000006 000 -msh /> +tshell 20 running 0x000000f8 0x00000800 21% 0x00000008 000 +sys_work 23 suspend 0x00000098 0x00000800 07% 0x0000000a 000 +tidle0 31 ready 0x000000b8 0x0000018c 46% 0x00000013 000 +timer 4 suspend 0x00000098 0x00000200 29% 0x00000009 000 +msh >list_device +device type ref count +-------- -------------------- ---------- +pin Miscellaneous Device 0 +uart4 Character Device 2 +msh >version + + \ | / +- RT - Thread Operating System + / | \ 4.0.3 build Jun 11 2020 + 2006 - 2020 Copyright by rt-thread team +msh >free +total memory: 14208 +used memory : 5248 +maximum allocated memory: 6424 ~~~ ### 调试程序 +#### 命令行GDB调试 + 在保证程序编译成功后, 在相同ENV终端执行``scons --run debug``进行代码在命令行下进行GDB调试。 正常的调试输出如下: -~~~ +~~~bat +57856@DESKTOP-4LATIEU D:\workspace\Sourcecode\rt-thread\bsp\nuclei\gd32vf103_rvstar +> scons --run debug scons: Reading SConscript files ... Supported downloaded modes for board gd32vf103v_rvstar are flashxip, chosen downloaded mode is flashxip Debug application rtthread.elf using openocd and gdb @@ -165,42 +183,112 @@ Find the GDB manual and other documentation resources online at: For help, type "help". Type "apropos word" to search for commands related to "word"... Reading symbols from rtthread.elf... -Remote debugging using | openocd --pipe -f D:/workspace/Sourcecode/rt-thread/bsp/nuclei/gd32vf103_rvstar/packages/nuclei_sdk-latest/SoC/gd32vf103/Board/gd32vf103v_rvstar/openocd_gd32vf103.cfg Nuclei OpenOCD, 64-bit Open On-Chip Debugger 0.10.0+dev-00014-g0eae03214 (2019-12-12-07:43) +Remote debugging using | openocd --pipe -f D:/workspace/Sourcecode/rt-thread/bsp/nuclei/gd32vf103_rvstar/packages/nuclei_sdk-latest/SoC/gd32vf103/Board/gd32vf103v_rvstar/openocd_gd32vf103.cfg +Nuclei OpenOCD, 64-bit Open On-Chip Debugger 0.10.0+dev-00014-g0eae03214 (2019-12-12-07:43) Licensed under GNU GPL v2 For bug reports, read http://openocd.org/doc/doxygen/bugs.html -rt_thread_idle_entry (parameter=0x0) at D:\workspace\Sourcecode\rt-thread\src\idle.c:249 -249 for (i = 0; i < RT_IDLE_HOOK_LIST_SIZE; i++) -(gdb) -(gdb) b main.c:35 -Breakpoint 1 at 0x8000290: file applications\main.c, line 35. +0x080011ca in rt_thread_idle_excute () at D:\workspace\Sourcecode\rt-thread\src\idle.c:153 +153 while (_has_defunct_thread()) +(gdb) b irq_entry +Breakpoint 1 at 0x8003840: file D:\workspace\Sourcecode\rt-thread\libcpu\risc-v\nuclei\interrupt_gcc.S, line 190. (gdb) c Continuing. Note: automatically using hardware breakpoints for read-only addresses. -Breakpoint 1, thread_entry (parameter=0x0) at applications\main.c:35 -35 rt_thread_mdelay(500); -(gdb) +Breakpoint 1, irq_entry () at D:\workspace\Sourcecode\rt-thread\libcpu\risc-v\nuclei\interrupt_gcc.S:190 +190 SAVE_CONTEXT +(gdb) c ~~~ 调试例子参见如下文档: * https://doc.nucleisys.com/nuclei_sdk/quickstart.html#debug-application -为了更方便的进行调试, 也可以下载**Nuclei Studio**集成开发环境, 创建一个Debug Configuration, 选择编译好的 -ELF文件, 然后配置OPENOCD和GDB即可, OPENOCD配置文件路径为**bsp\nuclei\gd32vf103_rvstar\packages\nuclei_sdk-latest\SoC\gd32vf103\Board\gd32vf103v_rvstar\openocd_gd32vf103.cfg** +#### Nuclei Studio IDE调试 +为了更方便的进行图形化调试, 也可以下载并使用[**Nuclei Studio IDE**](https://nucleisys.com/download.php)集成开发环境. + +1. 打开Nuclei Studio IDE, 创建一个名为**Nuclei_RT-Thread**的**C Project**,Project Type选择**Empty Project**, + Toolchain选择**RISC-V Cross GCC**, 然后点击**Finish**. + + ![Create A RISC-V C Project](doc/images/create_c_project.png) + +2. 选中**rt-thread**的代码目录,然后鼠标左键拖到Nuclei Studio中创建好的**Nuclei_RT-Thread**工程中,选择 + **Link to files and folders**, 点击**OK**, 就将**rt-thread**的代码拖到了工程中并创建软链接,注意这里建立的工程 + 仅用于调试,不可以用于编译,编译请使用上文中提到的`scons`命令。 + + ![Drop and link RT-Thread source code](doc/images/link_rtthread_code.png) + +3. 创建一个OpenOCD Debugging Configuration, 选择编译好的ELF文件, 并选定**Disable auto build**, 如下图所示: + + ![Create OpenOCD Debugging Configuration](doc/images/create_gdb_cfg.png) + +4. 然后打开**Debugger**Tab, 配置好OPENOCD的配置文件路径, 其中OPENOCD配置文件路径为 +*bsp\nuclei\gd32vf103_rvstar\packages\nuclei_sdk-latest\SoC\gd32vf103\Board\gd32vf103v_rvstar\openocd_gd32vf103.cfg*, + 请在配置时使用完整绝对路径,根据自己文件所在目录来提供。配置完毕后,点击 **Debug**,开始下载调试。 + + ![Configure OpenOCD configuration file](doc/images/config_openocd_cfg.png) + +5. 最终调试界面如下所示 + + ![Debug in Nuclei Studio IDE](doc/images/start_debug_in_ide.png) + +6. 上面步骤中的路径请根据自己的环境进行调整,调试时请确保开发板正常连接到电脑,并且调试器驱动安装正确。 ## 驱动支持情况 -| 驱动 | 支持情况 | 备注 | -| ------ | ---- | :------: | -| UART | 支持 | RV-STAR板载串口是UART4 | +| 驱动 | 支持情况 | 备注 | +| ------- | -------- | :------------------------------: | +| UART | 支持 | RV-STAR板载串口是UART4, 默认使能 | +| GPIO | 支持 | 默认使能,支持中断控制 | +| SPI | 支持 | 默认关闭 | +| I2C | 支持 | 默认关闭 | +| HWTIMER | 支持 | 默认关闭 | +| PWM | 支持 | 默认关闭 | +| WDT | 支持 | 默认关闭 | +| RTC | 支持 | 默认关闭 | +| ADC | 支持 | 默认关闭 | -**注:** +### 适配开发板Pinmux + +如果需要使用到其他的外设驱动,则首先需要运行`menuconfig`命令,在 +`Hardware Drivers Config -> On-chip Peripheral Drivers`中使能对应的外设接口, +但是由于针对不同的外设接口GPIO的pinux配置不一样,开发者仍需要根据自己的需求 +在 `board/board.c` 中的 `rt_hw_drivers_init`入口函数中找到需要使用到的子函数, +并在对应的子函数中进行功能适配。 + +**使用举例** + +* I2C外设Pinmux + +如果需要将I2C1的SCL和SDA配置在PB10和PB11,首先需要在menuconfig中将I2C1使能,然后 +更改board.c中`rt_hw_i2c_drvinit`函数,并进行如下设定。 + +~~~c +/* Configure PB10 PB11 (I2C1 SCL SDA) as alternate function */ +gpio_init(GPIOB, GPIO_MODE_AF_OD, GPIO_OSPEED_50MHZ, GPIO_PIN_10 | GPIO_PIN_11); +~~~ + +* SPI外设Pinmux + +如果需要将SPI0的SCK MISO和MOSI配置在PA5, PA6和PA7,首先需要在menuconfig中将SPI0使能, +然后更改board.c中的`rt_hw_spi_drvinit`函数,并进行如下设定。 + +~~~c +/* Configure PA5 PA6 PA7 (SPI0 SCK MISO MOSI) as alternate function */ +gpio_init(GPIOA, GPIO_MODE_AF_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_5 | GPIO_PIN_7); +gpio_init(GPIOA, GPIO_MODE_IN_FLOATING, GPIO_OSPEED_50MHZ, GPIO_PIN_6); +~~~ + +* 其余类似的外设也是如上做适配处理 + +### 注意 - 适配RT-Thread的驱动框架的代码在 [../libraries/gd32vf103/HAL_Drivers](../libraries/gd32vf103/HAL_Drivers)目录下。 - 如果有开发者想适配更多的驱动, 请在对应目录下增加驱动适配支持。 +- GD32VF103的驱动适配开关在 `menuconfig -> Hardware Drivers Config -> On-chip Peripheral Drivers` 可以找到。 +- HWTIMER和PWM都是采用的TIMER模块进行功能实现,所以在使用驱动时,请务必注意不要重叠使用相同模块。 ## 联系人信息 diff --git a/bsp/nuclei/gd32vf103_rvstar/SConstruct b/bsp/nuclei/gd32vf103_rvstar/SConstruct index 7adcd69070..58c5d745d7 100644 --- a/bsp/nuclei/gd32vf103_rvstar/SConstruct +++ b/bsp/nuclei/gd32vf103_rvstar/SConstruct @@ -24,7 +24,8 @@ 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, + AR = rtconfig.AR, ARFLAGS = '-rc', LIBS = rtconfig.LIBS, LINK = rtconfig.LINK, LINKFLAGS = rtconfig.LFLAGS) env.PrependENVPath('PATH', rtconfig.EXEC_PATH) env['ASCOM'] = env['ASPPCOM'] @@ -50,7 +51,11 @@ objs = PrepareBuilding(env, RTT_ROOT) bsp_library_type = rtconfig.NUCLEI_SDK_SOC rtconfig.BSP_LIBRARY_TYPE = bsp_library_type -openocd_cfg = rtconfig.NUCLEI_SDK_OPENOCD_CFG.replace('\\', '/') +if hasattr(rtconfig, 'NUCLEI_SDK_OPENOCD_CFG'): + openocd_cfg = rtconfig.NUCLEI_SDK_OPENOCD_CFG.replace('\\', '/') +else: + print("ERROR: Nuclei SDK package is not yet downloaded, please execute in command line first!") + exit(0) # include hal drivers hal_sconscript = os.path.join(libraries_path_prefix, bsp_library_type, 'HAL_Drivers', 'SConscript') diff --git a/bsp/nuclei/gd32vf103_rvstar/board/Kconfig b/bsp/nuclei/gd32vf103_rvstar/board/Kconfig index 5165ac7629..efb38aeaf7 100644 --- a/bsp/nuclei/gd32vf103_rvstar/board/Kconfig +++ b/bsp/nuclei/gd32vf103_rvstar/board/Kconfig @@ -38,6 +38,108 @@ menu "On-chip Peripheral Drivers" default n endif + menuconfig BSP_USING_I2C + bool "Enable I2C" + default n + select RT_USING_I2C + if BSP_USING_I2C + config BSP_USING_I2C0 + bool "Enable I2C0" + default n + config BSP_USING_I2C1 + bool "Enable I2C1" + default n + endif + + menuconfig BSP_USING_SPI + bool "Enable SPI" + default n + select RT_USING_SPI + if BSP_USING_SPI + config BSP_USING_SPI0 + bool "Enable SPI0" + default n + config BSP_USING_SPI1 + bool "Enable SPI1" + default n + config BSP_USING_SPI2 + bool "Enable SPI2" + default n + endif + + menuconfig BSP_USING_HWTIMER + bool "Enable TIMER" + default n + select RT_USING_HWTIMER + if BSP_USING_HWTIMER + config BSP_USING_HWTIMER0 + bool "Enable TIMER0" + default n + config BSP_USING_HWTIMER1 + bool "Enable TIMER1" + default n + config BSP_USING_HWTIMER2 + bool "Enable TIMER2" + default n + config BSP_USING_HWTIMER3 + bool "Enable TIMER3" + default n + config BSP_USING_HWTIMER4 + bool "Enable TIMER4" + default n + config BSP_USING_HWTIMER5 + bool "Enable TIMER5" + default n + config BSP_USING_HWTIMER6 + bool "Enable TIMER6" + 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 "Enable ADC0" + default n + config BSP_USING_ADC1 + bool "Enable ADC1" + default n + endif + + menuconfig BSP_USING_WDT + bool "Enable WDT" + default n + select RT_USING_WDT + + menuconfig BSP_USING_RTC + bool "Enable RTC" + default n + select RT_USING_RTC + + menuconfig BSP_USING_PWM + bool "Enable PWM" + default n + select RT_USING_PWM + if BSP_USING_PWM + config BSP_USING_PWM0 + bool "Enable PWM0" + default n + config BSP_USING_PWM1 + bool "Enable PWM1" + default n + config BSP_USING_PWM2 + bool "Enable PWM2" + default n + config BSP_USING_PWM3 + bool "Enable PWM3" + default n + config BSP_USING_PWM4 + bool "Enable PWM4" + default n + endif + endmenu menu "Board extended module Drivers" diff --git a/bsp/nuclei/gd32vf103_rvstar/board/board.c b/bsp/nuclei/gd32vf103_rvstar/board/board.c index 7dad875006..1a470f9b1e 100644 --- a/bsp/nuclei/gd32vf103_rvstar/board/board.c +++ b/bsp/nuclei/gd32vf103_rvstar/board/board.c @@ -32,6 +32,96 @@ extern void *_heap_end; */ extern void _init(void); +/* + * - Check MCU pin assignment here https://doc.nucleisys.com/nuclei_board_labs/hw/hw.html + * - If you changed menuconfig to use different peripherals such as SPI, ADC, GPIO, + * HWTIMER, I2C, PWM, UART, WDT, RTC, please add or change related pinmux configuration + * code in functions(rt_hw_*_drvinit) below + */ + +void rt_hw_spi_drvinit(void) +{ + +} + +void rt_hw_adc_drvinit(void) +{ + +} + +void rt_hw_gpio_drvinit(void) +{ + // Clock on all the GPIOs and AF + rcu_periph_clock_enable(RCU_GPIOA); + rcu_periph_clock_enable(RCU_GPIOB); + rcu_periph_clock_enable(RCU_GPIOC); + rcu_periph_clock_enable(RCU_GPIOD); + rcu_periph_clock_enable(RCU_GPIOE); + rcu_periph_clock_enable(RCU_AF); +} + +void rt_hw_hwtimer_drvinit(void) +{ + +} + +void rt_hw_i2c_drvinit(void) +{ + +} + +void rt_hw_pwm_drvinit(void) +{ + +} + +void rt_hw_rtc_drvinit(void) +{ + +} + +void rt_hw_uart_drvinit(void) +{ + /* Notice: Debug UART4 GPIO pins are already initialized in nuclei_sdk */ + +} + +void rt_hw_wdt_drvinit(void) +{ + +} + +void rt_hw_drivers_init(void) +{ +#ifdef RT_USING_PIN + rt_hw_gpio_drvinit(); +#endif +#ifdef BSP_USING_UART + rt_hw_uart_drvinit(); +#endif +#ifdef BSP_USING_SPI + rt_hw_spi_drvinit(); +#endif +#ifdef BSP_USING_I2C + rt_hw_i2c_drvinit(); +#endif +#ifdef BSP_USING_ADC + rt_hw_adc_drvinit(); +#endif +#ifdef BSP_USING_WDT + rt_hw_wdt_drvinit(); +#endif +#ifdef BSP_USING_RTC + rt_hw_rtc_drvinit(); +#endif +#ifdef BSP_USING_HWTIMER + rt_hw_hwtimer_drvinit(); +#endif +#ifdef BSP_USING_PWM + rt_hw_pwm_drvinit(); +#endif +} + /** * @brief Setup hardware board for rt-thread * @@ -47,6 +137,9 @@ void rt_hw_board_init(void) _init(); // __libc_init_array is not used in RT-Thread + /* Board hardware drivers initialization */ + rt_hw_drivers_init(); + /* USART driver initialization is open by default */ #ifdef RT_USING_SERIAL rt_hw_usart_init(); @@ -61,6 +154,7 @@ void rt_hw_board_init(void) #ifdef RT_USING_COMPONENTS_INIT rt_components_board_init(); #endif + } /******************** end of file *******************/ diff --git a/bsp/nuclei/gd32vf103_rvstar/doc/images/config_openocd_cfg.png b/bsp/nuclei/gd32vf103_rvstar/doc/images/config_openocd_cfg.png new file mode 100644 index 0000000000..887c8402e2 Binary files /dev/null and b/bsp/nuclei/gd32vf103_rvstar/doc/images/config_openocd_cfg.png differ diff --git a/bsp/nuclei/gd32vf103_rvstar/doc/images/create_c_project.png b/bsp/nuclei/gd32vf103_rvstar/doc/images/create_c_project.png new file mode 100644 index 0000000000..28537c2630 Binary files /dev/null and b/bsp/nuclei/gd32vf103_rvstar/doc/images/create_c_project.png differ diff --git a/bsp/nuclei/gd32vf103_rvstar/doc/images/create_gdb_cfg.png b/bsp/nuclei/gd32vf103_rvstar/doc/images/create_gdb_cfg.png new file mode 100644 index 0000000000..f6642ef844 Binary files /dev/null and b/bsp/nuclei/gd32vf103_rvstar/doc/images/create_gdb_cfg.png differ diff --git a/bsp/nuclei/gd32vf103_rvstar/doc/images/link_rtthread_code.png b/bsp/nuclei/gd32vf103_rvstar/doc/images/link_rtthread_code.png new file mode 100644 index 0000000000..69b7bd3519 Binary files /dev/null and b/bsp/nuclei/gd32vf103_rvstar/doc/images/link_rtthread_code.png differ diff --git a/bsp/nuclei/gd32vf103_rvstar/doc/images/start_debug_in_ide.png b/bsp/nuclei/gd32vf103_rvstar/doc/images/start_debug_in_ide.png new file mode 100644 index 0000000000..153b135015 Binary files /dev/null and b/bsp/nuclei/gd32vf103_rvstar/doc/images/start_debug_in_ide.png differ diff --git a/bsp/nuclei/gd32vf103_rvstar/rtconfig.h b/bsp/nuclei/gd32vf103_rvstar/rtconfig.h index 2498e39e9d..88c8053005 100644 --- a/bsp/nuclei/gd32vf103_rvstar/rtconfig.h +++ b/bsp/nuclei/gd32vf103_rvstar/rtconfig.h @@ -52,7 +52,7 @@ #define RT_USING_COMPONENTS_INIT #define RT_USING_USER_MAIN -#define RT_MAIN_THREAD_STACK_SIZE 2048 +#define RT_MAIN_THREAD_STACK_SIZE 1024 #define RT_MAIN_THREAD_PRIORITY 10 /* C++ features */ @@ -67,7 +67,7 @@ #define FINSH_USING_SYMTAB #define FINSH_USING_DESCRIPTION #define FINSH_THREAD_PRIORITY 20 -#define FINSH_THREAD_STACK_SIZE 4096 +#define FINSH_THREAD_STACK_SIZE 2048 #define FINSH_CMD_SIZE 80 #define FINSH_USING_MSH #define FINSH_USING_MSH_DEFAULT @@ -75,19 +75,15 @@ /* Device virtual file system */ -#define RT_USING_DFS -#define DFS_USING_WORKDIR -#define DFS_FILESYSTEMS_MAX 2 -#define DFS_FILESYSTEM_TYPES_MAX 2 -#define DFS_FD_MAX 16 -#define RT_USING_DFS_DEVFS /* 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_SERIAL_USING_DMA #define RT_SERIAL_RB_BUFSZ 64 #define RT_USING_PIN @@ -97,7 +93,6 @@ /* POSIX layer and C standard library */ #define RT_USING_LIBC -#define RT_USING_POSIX /* Network */ @@ -153,6 +148,9 @@ /* peripheral libraries and drivers */ #define PKG_USING_NUCLEI_SDK + +/* !!!Nuclei SDK only works with Nuclei RISC-V Processor IP!!! */ + #define PKG_USING_NUCLEI_SDK_LATEST_VERSION /* miscellaneous packages */ diff --git a/bsp/nuclei/gd32vf103_rvstar/rtconfig.py b/bsp/nuclei/gd32vf103_rvstar/rtconfig.py index bf74338e8a..4ea3c42133 100644 --- a/bsp/nuclei/gd32vf103_rvstar/rtconfig.py +++ b/bsp/nuclei/gd32vf103_rvstar/rtconfig.py @@ -23,7 +23,6 @@ else: BUILD = 'debug' # Fixed configurations below -NUCLEI_SDK_OPENOCD_CFG = "type in your config" NUCLEI_SDK_SOC = "gd32vf103" NUCLEI_SDK_BOARD = "gd32vf103v_rvstar" NUCLEI_SDK_DOWNLOAD = "flashxip" @@ -46,13 +45,14 @@ if PLATFORM == 'gcc': CFLAGS = ' -ffunction-sections -fdata-sections -fno-common ' AFLAGS = CFLAGS LFLAGS = ' --specs=nano.specs --specs=nosys.specs -nostartfiles -Wl,--gc-sections ' - LFLAGS += ' -Wl,-cref,-Map=rtthread.map' + LFLAGS += ' -Wl,-cref,-Map=rtthread.map ' LFLAGS += ' -u _isatty -u _write -u _sbrk -u _read -u _close -u _fstat -u _lseek ' CPATH = '' LPATH = '' + LIBS = ['stdc++'] if BUILD == 'debug': - CFLAGS += ' -O0 -ggdb' + CFLAGS += ' -O2 -Os -ggdb' AFLAGS += ' -ggdb' else: CFLAGS += ' -O2 -Os' @@ -62,9 +62,9 @@ if PLATFORM == 'gcc': DUMP_ACTION = OBJDUMP + ' -D -S $TARGET > rtt.asm\n' POST_ACTION = OBJCPY + ' -O binary $TARGET rtthread.bin\n' + SIZE + ' $TARGET \n' -def dist_handle(BSP_ROOT): +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_do_building(BSP_ROOT, dist_dir) diff --git a/bsp/nuclei/libraries/gd32vf103/HAL_Drivers/SConscript b/bsp/nuclei/libraries/gd32vf103/HAL_Drivers/SConscript index 4761127102..b9cdd5b795 100644 --- a/bsp/nuclei/libraries/gd32vf103/HAL_Drivers/SConscript +++ b/bsp/nuclei/libraries/gd32vf103/HAL_Drivers/SConscript @@ -14,6 +14,28 @@ if GetDepend(['RT_USING_PIN']): if GetDepend(['RT_USING_SERIAL']): src += ['drv_usart.c'] +if GetDepend(['RT_USING_I2C']): + src += ['drv_i2c.c'] + +if GetDepend(['RT_USING_SPI']): + src += ['drv_spi.c'] + +if GetDepend(['RT_USING_HWTIMER']): + src += ['drv_hwtimer.c'] + +if GetDepend(['RT_USING_ADC']): + src += ['drv_adc.c'] + +if GetDepend(['RT_USING_WDT']): + src += ['drv_wdt.c'] + +if GetDepend(['RT_USING_RTC']): + src += ['drv_rtc.c'] + +if GetDepend(['RT_USING_PWM']): + src += ['drv_pwm.c'] + + path = [cwd] group = DefineGroup('Drivers', src, depend = [''], CPPPATH = path) diff --git a/bsp/nuclei/libraries/gd32vf103/HAL_Drivers/drv_adc.c b/bsp/nuclei/libraries/gd32vf103/HAL_Drivers/drv_adc.c new file mode 100644 index 0000000000..5e463be51d --- /dev/null +++ b/bsp/nuclei/libraries/gd32vf103/HAL_Drivers/drv_adc.c @@ -0,0 +1,137 @@ +/* + * Copyright (c) 2006-2020, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2020-06-03 hqfang the first version. + * + */ +#include "drv_adc.h" + +#ifdef BSP_USING_ADC + +#if !defined(BSP_USING_ADC0) && !defined(BSP_USING_ADC1) + #error "Please define at least one BSP_USING_ADCx" + /* this driver can be disabled at menuconfig -> Hardware Drivers Config -> On-chip Peripheral Drivers -> Enable ADC */ +#endif + + +static struct gd32_adc_config adc_config[] = +{ +#ifdef BSP_USING_ADC0 + { + "adc0", + ADC0, + }, +#endif +#ifdef BSP_USING_ADC1 + { + "adc1", + ADC1, + }, +#endif +}; + +static struct gd32_adc adc_obj[sizeof(adc_config) / sizeof(adc_config[0])] = {0}; + +static void gd32_adc_init(struct gd32_adc_config *config) +{ + RT_ASSERT(config != RT_NULL); + adc_deinit(config->adc_periph); + + ADC_CTL0(config->adc_periph) &= ~(ADC_CTL0_SYNCM); + ADC_CTL0(config->adc_periph) |= ADC_MODE_FREE; + + ADC_CTL1(config->adc_periph) |= ADC_CTL1_TSVREN; + + adc_resolution_config(config->adc_periph, ADC_RESOLUTION_12B); + /* ADC contineous function enable */ + adc_special_function_config(config->adc_periph, ADC_SCAN_MODE, ENABLE); + /* ADC data alignment config */ + adc_data_alignment_config(config->adc_periph, ADC_DATAALIGN_RIGHT); + /* ADC channel length config */ + adc_channel_length_config(config->adc_periph, ADC_REGULAR_CHANNEL, 1); + adc_external_trigger_source_config(config->adc_periph, ADC_REGULAR_CHANNEL, ADC0_1_EXTTRIG_REGULAR_NONE); + + /* ADC enable */ + adc_external_trigger_config(config->adc_periph, ADC_REGULAR_CHANNEL, ENABLE); + adc_enable(config->adc_periph); + + adc_calibration_enable(config->adc_periph); +} + +static rt_err_t gd32_adc_enabled(struct rt_adc_device *device, rt_uint32_t channel, rt_bool_t enabled) +{ + if (channel > ADC_CHANNEL_17) + { + return RT_EINVAL; + } + return RT_EOK; +} + +static rt_err_t gd32_adc_convert(struct rt_adc_device *device, rt_uint32_t channel, rt_uint32_t *value) +{ + struct gd32_adc_config *config; + RT_ASSERT(device != RT_NULL); + + if (channel > ADC_CHANNEL_17) + { + return RT_EINVAL; + } + config = (struct gd32_adc_config *)(device->parent.user_data); + + if (channel > ADC_CHANNEL_15) + { + adc_regular_channel_config(config->adc_periph, 0, channel, ADC_SAMPLETIME_239POINT5); + } + else + { + adc_regular_channel_config(config->adc_periph, 0, channel, ADC_SAMPLETIME_55POINT5); + } + adc_software_trigger_enable(config->adc_periph, ADC_REGULAR_CHANNEL); + + while (SET != adc_flag_get(config->adc_periph, ADC_FLAG_EOC)); + adc_flag_clear(config->adc_periph, ADC_FLAG_EOC); + + *value = ADC_RDATA(config->adc_periph); + + return RT_EOK; +} + +static struct rt_adc_ops gd32_adc_ops = +{ + .enabled = gd32_adc_enabled, + .convert = gd32_adc_convert, +}; + +int rt_hw_adc_init(void) +{ + int i = 0; + int result = RT_EOK; + +#if defined(BSP_USING_ADC0) + rcu_periph_clock_enable(RCU_ADC0); +#endif +#if defined(BSP_USING_ADC1) + rcu_periph_clock_enable(RCU_ADC1); +#endif + + rcu_adc_clock_config(RCU_CKADC_CKAPB2_DIV8); + + for (i = 0; i < sizeof(adc_obj) / sizeof(adc_obj[0]); i++) + { + adc_obj[i].config = &adc_config[i]; + gd32_adc_init(&adc_config[i]); + rt_hw_adc_register(&adc_obj[i].adc_device, \ + adc_obj[i].config->name, &gd32_adc_ops, adc_obj[i].config); + } + + return result; +} + +INIT_DEVICE_EXPORT(rt_hw_adc_init); + +#endif /* BSP_USING_ADC */ + diff --git a/bsp/nuclei/libraries/gd32vf103/HAL_Drivers/drv_adc.h b/bsp/nuclei/libraries/gd32vf103/HAL_Drivers/drv_adc.h new file mode 100644 index 0000000000..a3c7380bb0 --- /dev/null +++ b/bsp/nuclei/libraries/gd32vf103/HAL_Drivers/drv_adc.h @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2006-2020, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2020-06-03 hqfang first implementation. + */ + +#ifndef __DRV_ADC__ +#define __DRV_ADC__ + +#include +#include +#include +#include + +/* gd32 config class */ +struct gd32_adc_config +{ + const char *name; + rt_uint32_t adc_periph; +}; + +struct gd32_adc +{ + struct rt_adc_device adc_device; + struct gd32_adc_config *config; +}; + +#endif diff --git a/bsp/nuclei/libraries/gd32vf103/HAL_Drivers/drv_gpio.c b/bsp/nuclei/libraries/gd32vf103/HAL_Drivers/drv_gpio.c index 75ab81f18e..f7572a57db 100644 --- a/bsp/nuclei/libraries/gd32vf103/HAL_Drivers/drv_gpio.c +++ b/bsp/nuclei/libraries/gd32vf103/HAL_Drivers/drv_gpio.c @@ -337,8 +337,11 @@ static rt_err_t gd32_pin_irq_enable(struct rt_device *device, rt_base_t pin, const struct pin_irq_map *irqmap; rt_base_t level; rt_int32_t irqindex = -1; + rt_uint8_t portsrc = 0, pinsrc = 0; exti_trig_type_enum trigger_mode; + portsrc = pin >> 4; + pinsrc = pin % 16; index = get_pin(pin); if (index == RT_NULL) { @@ -378,8 +381,9 @@ static rt_err_t gd32_pin_irq_enable(struct rt_device *device, rt_base_t pin, rt_hw_interrupt_enable(level); return RT_EINVAL; } + /* connect EXTI line to GPIO pin */ - gpio_exti_source_select(index->gpio, index->pin); + gpio_exti_source_select(portsrc, pinsrc); /* configure EXTI line */ exti_init((exti_line_enum)(index->pin), EXTI_INTERRUPT, trigger_mode); @@ -391,6 +395,8 @@ static rt_err_t gd32_pin_irq_enable(struct rt_device *device, rt_base_t pin, ECLIC_EnableIRQ(irqmap->irqno); pin_irq_enable_mask |= irqmap->pinbit; + exti_interrupt_enable((exti_line_enum)(index->pin)); + rt_hw_interrupt_enable(level); } else if (enabled == PIN_IRQ_DISABLE) @@ -405,6 +411,7 @@ static rt_err_t gd32_pin_irq_enable(struct rt_device *device, rt_base_t pin, if (!(pin_irq_enable_mask & (GPIO_PIN_5 | GPIO_PIN_6 | GPIO_PIN_7 | GPIO_PIN_8 | GPIO_PIN_9))) { ECLIC_DisableIRQ(irqmap->irqno); + exti_interrupt_disable((exti_line_enum)(index->pin)); } } else if ((irqmap->pinbit >= GPIO_PIN_10) && (irqmap->pinbit <= GPIO_PIN_15)) @@ -412,11 +419,13 @@ static rt_err_t gd32_pin_irq_enable(struct rt_device *device, rt_base_t pin, if (!(pin_irq_enable_mask & (GPIO_PIN_10 | GPIO_PIN_11 | GPIO_PIN_12 | GPIO_PIN_13 | GPIO_PIN_14 | GPIO_PIN_15))) { ECLIC_DisableIRQ(irqmap->irqno); + exti_interrupt_disable((exti_line_enum)(index->pin)); } } else { ECLIC_DisableIRQ(irqmap->irqno); + exti_interrupt_disable((exti_line_enum)(index->pin)); } } else @@ -515,6 +524,7 @@ int rt_hw_pin_init(void) rcu_periph_clock_enable(RCU_AF); return rt_device_pin_register("pin", &_gd32_pin_ops, RT_NULL); } -INIT_BOARD_EXPORT(rt_hw_pin_init); + +INIT_DEVICE_EXPORT(rt_hw_pin_init); #endif /* RT_USING_PIN */ diff --git a/bsp/nuclei/libraries/gd32vf103/HAL_Drivers/drv_hwtimer.c b/bsp/nuclei/libraries/gd32vf103/HAL_Drivers/drv_hwtimer.c new file mode 100644 index 0000000000..dd351ee146 --- /dev/null +++ b/bsp/nuclei/libraries/gd32vf103/HAL_Drivers/drv_hwtimer.c @@ -0,0 +1,315 @@ +/* + * Copyright (c) 2006-2018, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2020-05-12 hqfang first version + */ + +#include "drv_hwtimer.h" + +#ifdef BSP_USING_HWTIMER + +#if !defined(BSP_USING_HWTIMER0) && !defined(BSP_USING_HWTIMER1) && !defined(BSP_USING_HWTIMER2) \ + && !defined(BSP_USING_HWTIMER3) && !defined(BSP_USING_HWTIMER4) + #error "Please define at least one BSP_USING_HWTIMERx" + /* this driver can be disabled at menuconfig -> Hardware Drivers Config -> On-chip Peripheral Drivers -> Enable HWTIMER */ +#endif + +static struct gd32_hwtimer_config hwtimer_config[] = +{ +#ifdef BSP_USING_HWTIMER0 + { + "timer0", + TIMER0, + TIMER0_UP_IRQn, + }, +#endif +#ifdef BSP_USING_HWTIMER1 + { + "timer1", + TIMER1, + TIMER1_IRQn, + }, +#endif +#ifdef BSP_USING_HWTIMER2 + { + "timer2", + TIMER2, + TIMER2_IRQn, + }, +#endif +#ifdef BSP_USING_HWTIMER3 + { + "timer3", + TIMER3, + TIMER3_IRQn, + }, +#endif +#ifdef BSP_USING_HWTIMER4 + { + "timer4", + TIMER4, + TIMER4_IRQn, + }, +#endif +#ifdef BSP_USING_HWTIMER5 + { + "timer5", + TIMER5, + TIMER5_IRQn, + }, +#endif +#ifdef BSP_USING_HWTIMER6 + { + "timer6", + TIMER6, + TIMER6_IRQn, + }, +#endif +}; + +static struct gd32_hwtimer hwtimer_obj[sizeof(hwtimer_config) / sizeof(hwtimer_config[0])] = {0}; + +static rt_err_t gd32_hwtimer_control(rt_hwtimer_t *timer, rt_uint32_t cmd, void *args) +{ + rt_err_t err = RT_EOK; + struct gd32_hwtimer_config *config; + RT_ASSERT(timer != RT_NULL); + + config = (struct gd32_hwtimer_config *)timer->parent.user_data; + + switch (cmd) + { + case HWTIMER_CTRL_FREQ_SET: + { + uint32_t clk; + uint8_t clkpre; + uint32_t pre; + if (config->timer_periph != TIMER0) + { + clk = rcu_clock_freq_get(CK_APB1); + clkpre = GET_BITS(RCU_CFG0, 8, 10); + } + else + { + clk = rcu_clock_freq_get(CK_APB2); + clkpre = GET_BITS(RCU_CFG0, 11, 13); + } + if (clkpre >= 4) + { + clk = clk * 2; + } + pre = (clk / * ((uint32_t *)args)) - 1; + TIMER_PSC(config->timer_periph) = (uint32_t)pre; + } + break; + case HWTIMER_CTRL_STOP: + timer_disable(config->timer_periph); + break; + default: + err = -RT_ENOSYS; + break; + } + return err; +} + +static rt_uint32_t gd32_hwtimer_count_get(rt_hwtimer_t *timer) +{ + rt_uint32_t CurrentTimer_Count; + struct gd32_hwtimer_config *config; + RT_ASSERT(timer != RT_NULL); + + config = (struct gd32_hwtimer_config *)timer->parent.user_data; + + CurrentTimer_Count = timer_counter_read(config->timer_periph); + + return CurrentTimer_Count; +} + +static void gd32_hwtimer_init(rt_hwtimer_t *timer, rt_uint32_t state) +{ + struct gd32_hwtimer_config *config; + timer_parameter_struct initpara; + RT_ASSERT(timer != RT_NULL); + config = (struct gd32_hwtimer_config *)timer->parent.user_data; + + if (state == 1) + { + timer_deinit(config->timer_periph); + timer_struct_para_init(&initpara); + timer_init(config->timer_periph, &initpara); + } + else + { + timer_disable(config->timer_periph); + timer_interrupt_enable(config->timer_periph, TIMER_INT_FLAG_UP); + ECLIC_DisableIRQ(config->irqn); + } +} + +static rt_err_t gd32_hwtimer_start(rt_hwtimer_t *timer, rt_uint32_t cnt, rt_hwtimer_mode_t mode) +{ + struct gd32_hwtimer_config *config; + RT_ASSERT(timer != RT_NULL); + config = (struct gd32_hwtimer_config *)timer->parent.user_data; + + if (mode == HWTIMER_MODE_ONESHOT) + { + timer_single_pulse_mode_config(config->timer_periph, TIMER_SP_MODE_SINGLE); + } + else + { + timer_single_pulse_mode_config(config->timer_periph, TIMER_SP_MODE_REPETITIVE); + } + timer_counter_value_config(config->timer_periph, 0); + timer_autoreload_value_config(config->timer_periph, cnt); + timer_interrupt_enable(config->timer_periph, TIMER_INT_FLAG_UP); + timer_enable(config->timer_periph); + ECLIC_EnableIRQ(config->irqn); + + return RT_EOK; +} + +static void gd32_hwtimer_stop(rt_hwtimer_t *timer) +{ + struct gd32_hwtimer_config *config; + RT_ASSERT(timer != RT_NULL); + config = (struct gd32_hwtimer_config *)timer->parent.user_data; + + timer_disable(config->timer_periph); + + ECLIC_DisableIRQ(config->irqn); +} + +static const struct rt_hwtimer_ops gd32_hwtimer_ops = +{ + .init = gd32_hwtimer_init, + .start = gd32_hwtimer_start, + .stop = gd32_hwtimer_stop, + .count_get = gd32_hwtimer_count_get, + .control = gd32_hwtimer_control, +}; + +static const struct rt_hwtimer_info gd32_hwtimer_info = +{ + 54000000, /* the maximum count frequency can be set */ + 1000, /* the minimum count frequency can be set */ + 0xFFFF, + HWTIMER_CNTMODE_UP, +}; + +#ifdef BSP_USING_HWTIMER0 + +void TIMER0_UP_IRQHandler(void) +{ + timer_interrupt_flag_clear(hwtimer_obj[0].config->timer_periph, TIMER_INT_FLAG_UP); + rt_device_hwtimer_isr(&hwtimer_obj[0].time_device); +} + +#endif + +#ifdef BSP_USING_HWTIMER1 + +void TIMER1_IRQHandler(void) +{ + timer_interrupt_flag_clear(hwtimer_obj[1].config->timer_periph, TIMER_INT_FLAG_UP); + rt_device_hwtimer_isr(&hwtimer_obj[1].time_device); +} + +#endif + +#ifdef BSP_USING_HWTIMER2 + +void TIMER2_IRQHandler(void) +{ + timer_interrupt_flag_clear(hwtimer_obj[2].config->timer_periph, TIMER_INT_FLAG_UP); + rt_device_hwtimer_isr(&hwtimer_obj[2].time_device); +} + +#endif + +#ifdef BSP_USING_HWTIMER3 + +void TIMER3_IRQHandler(void) +{ + timer_interrupt_flag_clear(hwtimer_obj[3].config->timer_periph, TIMER_INT_FLAG_UP); + rt_device_hwtimer_isr(&hwtimer_obj[3].time_device); +} + +#endif + +#ifdef BSP_USING_HWTIMER4 + +void TIMER4_IRQHandler(void) +{ + timer_interrupt_flag_clear(hwtimer_obj[4].config->timer_periph, TIMER_INT_FLAG_UP); + rt_device_hwtimer_isr(&hwtimer_obj[4].time_device); +} + +#endif + +#ifdef BSP_USING_HWTIMER5 + +void TIMER5_IRQHandler(void) +{ + timer_interrupt_flag_clear(hwtimer_obj[5].config->timer_periph, TIMER_INT_FLAG_UP); + rt_device_hwtimer_isr(&hwtimer_obj[5].time_device); +} + +#endif + +#ifdef BSP_USING_HWTIMER6 + +void TIMER6_IRQHandler(void) +{ + timer_interrupt_flag_clear(hwtimer_obj[6].config->timer_periph, TIMER_INT_FLAG_UP); + rt_device_hwtimer_isr(&hwtimer_obj[6].time_device); +} + +#endif + +static int rt_hwtimer_init(void) +{ + int i = 0; + int result = RT_EOK; + +#ifdef BSP_USING_HWTIMER0 + rcu_periph_clock_enable(RCU_TIMER0); +#endif +#ifdef BSP_USING_HWTIMER1 + rcu_periph_clock_enable(RCU_TIMER1); +#endif +#ifdef BSP_USING_HWTIMER2 + rcu_periph_clock_enable(RCU_TIMER2); +#endif +#ifdef BSP_USING_HWTIMER3 + rcu_periph_clock_enable(RCU_TIMER3); +#endif +#ifdef BSP_USING_HWTIMER4 + rcu_periph_clock_enable(RCU_TIMER4); +#endif +#ifdef BSP_USING_HWTIMER5 + rcu_periph_clock_enable(RCU_TIMER5); +#endif +#ifdef BSP_USING_HWTIMER6 + rcu_periph_clock_enable(RCU_TIMER6); +#endif + + for (i = 0; i < sizeof(hwtimer_obj) / sizeof(hwtimer_obj[0]); i++) + { + hwtimer_obj[i].time_device.info = &gd32_hwtimer_info; + hwtimer_obj[i].time_device.ops = &gd32_hwtimer_ops; + hwtimer_obj[i].config = &hwtimer_config[i]; + rt_device_hwtimer_register(&hwtimer_obj[i].time_device, \ + hwtimer_obj[i].config->name, hwtimer_obj[i].config); + } + + return result; +} + +INIT_DEVICE_EXPORT(rt_hwtimer_init); + +#endif /* RT_USING_HWTIMER */ diff --git a/bsp/nuclei/libraries/gd32vf103/HAL_Drivers/drv_hwtimer.h b/bsp/nuclei/libraries/gd32vf103/HAL_Drivers/drv_hwtimer.h new file mode 100644 index 0000000000..f4664c9d38 --- /dev/null +++ b/bsp/nuclei/libraries/gd32vf103/HAL_Drivers/drv_hwtimer.h @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2006-2020, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2029-05-06 hqfang first implementation. + */ + +#ifndef __DRV_HWTIMER__ +#define __DRV_HWTIMER__ + +#include +#include +#include +#include + +/* gd32 config class */ +struct gd32_hwtimer_config +{ + const char *name; + rt_uint32_t timer_periph; + IRQn_Type irqn; +}; + +struct gd32_hwtimer +{ + rt_hwtimer_t time_device; + struct gd32_hwtimer_config *config; +}; + +#endif diff --git a/bsp/nuclei/libraries/gd32vf103/HAL_Drivers/drv_i2c.c b/bsp/nuclei/libraries/gd32vf103/HAL_Drivers/drv_i2c.c new file mode 100644 index 0000000000..94aa0e234c --- /dev/null +++ b/bsp/nuclei/libraries/gd32vf103/HAL_Drivers/drv_i2c.c @@ -0,0 +1,228 @@ +/* + * Copyright (c) 2006-2020, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2020-04-27 hqfang first implementation. + */ + +#include "drv_i2c.h" + +#ifdef RT_USING_I2C + +#if !defined(BSP_USING_I2C0) && !defined(BSP_USING_I2C1) + #error "Please define at least one BSP_USING_I2Cx" + /* this driver can be disabled at menuconfig -> Hardware Drivers Config -> On-chip Peripheral Drivers -> Enable I2C */ +#endif + +static struct gd32_i2c_config i2c_config[] = +{ +#ifdef BSP_USING_I2C0 + { + "i2c0", + I2C0, + 100000, + }, +#endif +#ifdef BSP_USING_I2C1 + { + "i2c1", + I2C1, + 100000, + }, +#endif +}; + +static struct gd32_i2c i2c_obj[sizeof(i2c_config) / sizeof(i2c_config[0])] = {0}; + +#define GD32_I2C_TIMEOUT 10 + +static int gd32_i2c_read(rt_uint32_t i2c_periph, rt_uint16_t slave_address, rt_uint8_t *p_buffer, rt_uint16_t cnt) +{ + /* send slave address to I2C bus */ + i2c_master_addressing(i2c_periph, slave_address << 1, I2C_RECEIVER); + + /* wait until ADDSEND bit is set */ + while (!i2c_flag_get(i2c_periph, I2C_FLAG_ADDSEND)); + + /* clear the ADDSEND bit */ + i2c_flag_clear(i2c_periph, I2C_FLAG_ADDSEND); + + /* while there is data to be read */ + while (cnt) + { + if (cnt == 1) + { + // Send NACK for last 1 byte receive + i2c_ack_config(i2c_periph, I2C_ACK_DISABLE); + } + /* wait until the RBNE bit is set */ + while (i2c_flag_get(i2c_periph, I2C_FLAG_RBNE) == RESET); + + /* read a byte from i2c */ + *p_buffer = i2c_data_receive(i2c_periph); + + /* point to the next location where the byte read will be saved */ + p_buffer++; + + /* decrement the read bytes counter */ + cnt--; + } + + return 0; +} + +static int gd32_i2c_write(rt_uint32_t i2c_periph, uint16_t slave_address, uint8_t *p_buffer, uint16_t cnt) +{ + /* send slave address to I2C bus */ + i2c_master_addressing(i2c_periph, slave_address << 1, I2C_TRANSMITTER); + + /* wait until ADDSEND bit is set */ + while (!i2c_flag_get(i2c_periph, I2C_FLAG_ADDSEND)); + + /* clear the ADDSEND bit */ + i2c_flag_clear(i2c_periph, I2C_FLAG_ADDSEND); + + /* wait until the transmit data buffer is empty */ + while (SET != i2c_flag_get(i2c_periph, I2C_FLAG_TBE)); + + /* while there is data to be read */ + while (cnt) + { + i2c_data_transmit(i2c_periph, *p_buffer); + + /* point to the next byte to be written */ + p_buffer++; + + /* decrement the write bytes counter */ + cnt--; + + /* wait until BTC bit is set */ + while (!i2c_flag_get(i2c_periph, I2C_FLAG_BTC)); + } + + return 0; +} + +static void gd32_i2c_configure(struct gd32_i2c_config *i2c_cfg) +{ + RT_ASSERT(i2c_cfg != RT_NULL); + + /* configure i2c speed to 100Khz */ + i2c_clock_config(i2c_cfg->i2c_periph, i2c_cfg->speed, I2C_DTCY_2); + /* enable I2C */ + i2c_enable(i2c_cfg->i2c_periph); + /* enable acknowledge */ + i2c_ack_config(i2c_cfg->i2c_periph, I2C_ACK_ENABLE); +} + + +static rt_size_t gd32_i2c_xfer(struct rt_i2c_bus_device *device, struct rt_i2c_msg msgs[], rt_uint32_t num) +{ + struct rt_i2c_msg *msg; + rt_uint32_t i; + rt_err_t ret = RT_ERROR; + rt_uint16_t last_flags; + + RT_ASSERT(device != RT_NULL); + + struct gd32_i2c *i2c_obj = (struct gd32_i2c *)(device); + struct gd32_i2c_config *i2c_cfg = (struct gd32_i2c_config *)(i2c_obj->config); + RT_ASSERT(i2c_cfg != RT_NULL); + + /* wait until I2C bus is idle */ + while (i2c_flag_get(i2c_cfg->i2c_periph, I2C_FLAG_I2CBSY)); + + if (num) + { + if (msg[0].flags & RT_I2C_ADDR_10BIT) + { + i2c_mode_addr_config(i2c_cfg->i2c_periph, I2C_I2CMODE_ENABLE, I2C_ADDFORMAT_10BITS, 0x82); + } + else + { + i2c_mode_addr_config(i2c_cfg->i2c_periph, I2C_I2CMODE_ENABLE, I2C_ADDFORMAT_7BITS, 0x82); + } + } + for (i = 0; i < num; i++) + { + msg = &msgs[i]; + + if (!(msg->flags & RT_I2C_NO_START)) + { + /* send a start condition to I2C bus */ + i2c_start_on_bus(i2c_cfg->i2c_periph); + /* wait until SBSEND bit is set */ + while (!i2c_flag_get(i2c_cfg->i2c_periph, I2C_FLAG_SBSEND)); + } + + if (msg->flags & RT_I2C_RD) + { + gd32_i2c_read(i2c_cfg->i2c_periph, msg->addr, msg->buf, msg->len); + } + else + { + gd32_i2c_write(i2c_cfg->i2c_periph, msg->addr, msg->buf, msg->len); + } + } + + if (num) + { + /* send a stop condition to I2C bus */ + i2c_stop_on_bus(i2c_cfg->i2c_periph); + + /* wait until the stop condition is finished */ + while (I2C_CTL0(i2c_cfg->i2c_periph) & I2C_CTL0_STOP); + } + i2c_ack_config(i2c_cfg->i2c_periph, I2C_ACK_ENABLE); + + ret = i; + + return ret; +} + +static const struct rt_i2c_bus_device_ops i2c_ops = +{ + gd32_i2c_xfer, + RT_NULL, + RT_NULL +}; + +int rt_hw_i2c_init(void) +{ + rt_size_t obj_num; + int index; + rt_err_t result = 0; + +#ifdef BSP_USING_I2C0 + rcu_periph_clock_enable(RCU_I2C0); +#endif +#ifdef BSP_USING_I2C1 + rcu_periph_clock_enable(RCU_I2C1); +#endif + + obj_num = sizeof(i2c_obj) / sizeof(struct gd32_i2c); + for (index = 0; index < obj_num; index++) + { + /* init i2c object */ + i2c_obj[index].config = &i2c_config[index]; + i2c_obj[index].bus.ops = &i2c_ops; + + /* init i2c device */ + gd32_i2c_configure(&i2c_config[index]); + + /* register i2c device */ + result = rt_i2c_bus_device_register(&i2c_obj[index].bus, + i2c_obj[index].config->name + ); + RT_ASSERT(result == RT_EOK); + } + + return 0; +} +INIT_DEVICE_EXPORT(rt_hw_i2c_init); + +#endif +/* end of i2c driver */ diff --git a/bsp/nuclei/libraries/gd32vf103/HAL_Drivers/drv_i2c.h b/bsp/nuclei/libraries/gd32vf103/HAL_Drivers/drv_i2c.h new file mode 100644 index 0000000000..a336b5656e --- /dev/null +++ b/bsp/nuclei/libraries/gd32vf103/HAL_Drivers/drv_i2c.h @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2006-2020, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2020-04-27 hqfang first implementation. + */ + +#ifndef __DRV_I2C__ +#define __DRV_I2C__ + +#include +#include +#include +#include + +/* gd32 config class */ +struct gd32_i2c_config +{ + const char *name; + rt_uint32_t i2c_periph; + rt_uint32_t speed; +}; + +struct gd32_i2c +{ + struct rt_i2c_bus_device bus; + struct gd32_i2c_config *config; +}; + +#endif diff --git a/bsp/nuclei/libraries/gd32vf103/HAL_Drivers/drv_pwm.c b/bsp/nuclei/libraries/gd32vf103/HAL_Drivers/drv_pwm.c new file mode 100644 index 0000000000..b7af639c53 --- /dev/null +++ b/bsp/nuclei/libraries/gd32vf103/HAL_Drivers/drv_pwm.c @@ -0,0 +1,352 @@ +/* + * Copyright (c) 2006-2018, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2020-06-02 hqfang first version + */ + +#include "drv_pwm.h" +// #define DBG_LVL DBG_INFO + +#include + +#ifdef BSP_USING_PWM + +#if !defined(BSP_USING_PWM0) && !defined(BSP_USING_PWM1) && !defined(BSP_USING_PWM2) \ + && !defined(BSP_USING_PWM3) && !defined(BSP_USING_PWM4) + #error "Please define at least one BSP_USING_PWMx" + /* this driver can be disabled at menuconfig -> Hardware Drivers Config -> On-chip Peripheral Drivers -> Enable PWM */ +#endif + +static struct gd32_pwm_config pwm_config[] = +{ +#ifdef BSP_USING_PWM0 + { + "pwm0", + TIMER0, + 1000000, + }, +#endif +#ifdef BSP_USING_PWM1 + { + "pwm1", + TIMER1, + 1000000, + }, +#endif +#ifdef BSP_USING_PWM2 + { + "pwm2", + TIMER2, + 1000000, + }, +#endif +#ifdef BSP_USING_PWM3 + { + "pwm3", + TIMER3, + 1000000, + }, +#endif +#ifdef BSP_USING_PWM4 + { + "pwm4", + TIMER4, + 1000000, + }, +#endif +}; + +#define GD32_MAX_PWM_CHANNELS TIMER_CH_3 +static struct gd32_pwm pwm_obj[sizeof(pwm_config) / sizeof(pwm_config[0])] = {0}; + +static rt_err_t gd32_pwm_enable(struct rt_device_pwm *device, struct rt_pwm_configuration *configuration, rt_bool_t enable) +{ + struct gd32_pwm_config *config; + config = (struct gd32_pwm_config *)device->parent.user_data; + RT_ASSERT(config); + + if (configuration->channel > GD32_MAX_PWM_CHANNELS) + { + return RT_EINVAL; + } + if (!enable) + { + timer_channel_output_state_config(config->periph, configuration->channel, TIMER_CCX_DISABLE); + } + else + { + timer_channel_output_state_config(config->periph, configuration->channel, TIMER_CCX_ENABLE); + } + + return RT_EOK; +} + +static uint32_t gd32_get_pwm_clk(rt_uint32_t periph) +{ + uint32_t clk; + uint8_t clkpre; + if (periph != TIMER0) + { + clk = rcu_clock_freq_get(CK_APB1); + clkpre = GET_BITS(RCU_CFG0, 8, 10); + } + else + { + clk = rcu_clock_freq_get(CK_APB2); + clkpre = GET_BITS(RCU_CFG0, 11, 13); + } + if (clkpre >= 4) + { + clk = clk * 2; + } + return clk; +} + +static rt_err_t gd32_pwm_get(struct rt_device_pwm *device, struct rt_pwm_configuration *configuration) +{ + uint32_t pwmclk; + uint16_t prescale, period, clkdiv, pulse; + struct gd32_pwm_config *config; + config = (struct gd32_pwm_config *)device->parent.user_data; + RT_ASSERT(config); + + pwmclk = gd32_get_pwm_clk(config->periph); + prescale = (uint16_t)TIMER_PSC(config->periph) + 1; + clkdiv = ((uint16_t)(TIMER_CTL0(config->periph) & TIMER_CTL0_CKDIV) >> 8); + clkdiv = 1 << clkdiv; + period = (uint16_t)TIMER_CAR(config->periph) + 1; + pulse = (uint16_t)REG32((config->periph) + 0x34U + configuration->channel << 2) + 1; + + pwmclk = pwmclk / prescale / clkdiv; + LOG_I("current pwmclk is %d\n", pwmclk); + + configuration->period = (uint64_t)period * 1000000000 / pwmclk; + configuration->pulse = (uint64_t)pulse * 1000000000 / pwmclk; + return RT_EOK; +} + +static rt_err_t gd32_pwm_set(struct rt_device_pwm *device, struct rt_pwm_configuration *configuration) +{ + timer_oc_parameter_struct timer_ocinitpara; + timer_parameter_struct timer_initpara; + uint32_t pwmclk, pwmclkv2; + uint64_t period_cmp; + uint16_t prescale, period, clkdiv, pulse; + struct gd32_pwm_config *config; + config = (struct gd32_pwm_config *)device->parent.user_data; + RT_ASSERT(config); + + if (configuration->channel > GD32_MAX_PWM_CHANNELS) + { + LOG_I("max channel supported is %d\n", GD32_MAX_PWM_CHANNELS); + return RT_EINVAL; + } + if (configuration->period < configuration->pulse) + { + LOG_I("period should > pulse \n"); + return RT_EINVAL; + } + + pwmclk = gd32_get_pwm_clk(config->periph); + + // min period value >= 100 + period_cmp = (uint64_t)(1000000000 / pwmclk) * 10; + if (configuration->period < period_cmp) + { + return RT_EINVAL; + } + period_cmp = (uint64_t)(1000000000 / (pwmclk / 65536 / 4)) * 65536; + if (configuration->period > period_cmp) + { + return RT_EINVAL; + } + + period_cmp = (uint64_t) pwmclk * configuration->period / 1000000000; + + if (period_cmp < 65536) + { + prescale = 0; + clkdiv = TIMER_CKDIV_DIV1; + period = period_cmp; + } + else if (period_cmp < 4294967296) + { + prescale = period_cmp / 65536; + period = period_cmp / (prescale + 1); + clkdiv = TIMER_CKDIV_DIV1; + } + else if (period_cmp < 8589934592) + { + prescale = period_cmp / 65536; + period = period_cmp / (prescale + 1) / 2; + clkdiv = TIMER_CKDIV_DIV2; + } + else + { + prescale = period_cmp / 65536; + period = period_cmp / (prescale + 1) / 4; + clkdiv = TIMER_CKDIV_DIV4; + } + + pwmclkv2 = pwmclk / (prescale + 1) / (1 << clkdiv); + LOG_I("current pwmclk is %d\n", pwmclkv2); + + LOG_I("Set channel %d, period %dns, pulse %dns\n", configuration->channel, \ + configuration->period, configuration->pulse); + pulse = (uint64_t)period * configuration->pulse / configuration->period; + LOG_I("pwmclk %d, pwmcmp %d, prescale %d, period %d, pulse %d, clkdiv %d\n", \ + pwmclk, (uint32_t)period_cmp, prescale, period, pulse, clkdiv); + + /* initialize TIMER init parameter struct */ + timer_struct_para_init(&timer_initpara); + /* TIMER configuration */ + timer_initpara.prescaler = prescale; + timer_initpara.alignedmode = TIMER_COUNTER_EDGE; + timer_initpara.counterdirection = TIMER_COUNTER_UP; + timer_initpara.period = period; + timer_initpara.clockdivision = clkdiv; + timer_initpara.repetitioncounter = 0; + timer_init(config->periph, &timer_initpara); + + /* initialize TIMER channel output parameter struct */ + timer_channel_output_struct_para_init(&timer_ocinitpara); + /* CH0, CH1 and CH2 configuration in PWM mode */ + timer_ocinitpara.outputstate = TIMER_CCX_DISABLE; + timer_ocinitpara.outputnstate = TIMER_CCXN_DISABLE; + timer_ocinitpara.ocpolarity = TIMER_OC_POLARITY_HIGH; + timer_ocinitpara.ocnpolarity = TIMER_OCN_POLARITY_HIGH; + timer_ocinitpara.ocidlestate = TIMER_OC_IDLE_STATE_LOW; + timer_ocinitpara.ocnidlestate = TIMER_OCN_IDLE_STATE_LOW; + + timer_channel_output_config(config->periph, configuration->channel, &timer_ocinitpara); + + /* Channel configuration in PWM mode */ + timer_channel_output_pulse_value_config(config->periph, configuration->channel, pulse); + timer_channel_output_mode_config(config->periph, configuration->channel, TIMER_OC_MODE_PWM0); + timer_channel_output_shadow_config(config->periph, configuration->channel, TIMER_OC_SHADOW_DISABLE); + + timer_primary_output_config(config->periph, ENABLE); + /* auto-reload preload enable */ + timer_auto_reload_shadow_enable(config->periph); + timer_enable(config->periph); + + return RT_EOK; +} + +static rt_err_t gd32_pwm_control(struct rt_device_pwm *device, int cmd, void *arg) +{ + struct rt_pwm_configuration *configuration = (struct rt_pwm_configuration *)arg; + + switch (cmd) + { + case PWM_CMD_ENABLE: + return gd32_pwm_enable(device, configuration, RT_TRUE); + case PWM_CMD_DISABLE: + return gd32_pwm_enable(device, configuration, RT_FALSE); + case PWM_CMD_SET: + return gd32_pwm_set(device, configuration); + case PWM_CMD_GET: + return gd32_pwm_get(device, configuration); + default: + return RT_EINVAL; + } +} + +static rt_err_t gd32_pwm_init(struct gd32_pwm_config *config) +{ + timer_oc_parameter_struct timer_ocinitpara; + timer_parameter_struct timer_initpara; + uint32_t pwmclk; + uint16_t prescale; + + pwmclk = gd32_get_pwm_clk(config->periph); + + /* period 1ms, duty 50% */ + prescale = pwmclk / 1000 / 1000 - 1; + + config->period = 1000000; + + LOG_I("pwmclk %d, prescale %d, period %d, clkdiv %d\n", pwmclk, prescale, 999, 0); + + /* initialize TIMER init parameter struct */ + timer_struct_para_init(&timer_initpara); + /* TIMER configuration */ + timer_initpara.prescaler = prescale; + timer_initpara.alignedmode = TIMER_COUNTER_EDGE; + timer_initpara.counterdirection = TIMER_COUNTER_UP; + timer_initpara.period = 999; + timer_initpara.clockdivision = TIMER_CKDIV_DIV1; + timer_initpara.repetitioncounter = 0; + timer_init(config->periph, &timer_initpara); + + /* initialize TIMER channel output parameter struct */ + timer_channel_output_struct_para_init(&timer_ocinitpara); + /* CH0, CH1 and CH2 configuration in PWM mode */ + timer_ocinitpara.outputstate = TIMER_CCX_DISABLE; + timer_ocinitpara.outputnstate = TIMER_CCXN_DISABLE; + timer_ocinitpara.ocpolarity = TIMER_OC_POLARITY_HIGH; + timer_ocinitpara.ocnpolarity = TIMER_OCN_POLARITY_HIGH; + timer_ocinitpara.ocidlestate = TIMER_OC_IDLE_STATE_LOW; + timer_ocinitpara.ocnidlestate = TIMER_OCN_IDLE_STATE_LOW; + + /* Channel configuration in PWM mode */ + for (int i = 0; i <= GD32_MAX_PWM_CHANNELS; i ++) + { + timer_channel_output_config(config->periph, i, &timer_ocinitpara); + timer_channel_output_pulse_value_config(config->periph, i, 499); + timer_channel_output_mode_config(config->periph, i, TIMER_OC_MODE_PWM0); + timer_channel_output_shadow_config(config->periph, i, TIMER_OC_SHADOW_DISABLE); + } + + timer_primary_output_config(config->periph, ENABLE); + /* auto-reload preload enable */ + timer_auto_reload_shadow_enable(config->periph); + timer_enable(config->periph); + + return RT_EOK; +} + +static struct rt_pwm_ops gd32_drv_ops = +{ + .control = gd32_pwm_control +}; + +static int rt_pwm_init(void) +{ + int i = 0; + int result = RT_EOK; + +#ifdef BSP_USING_PWM0 + rcu_periph_clock_enable(RCU_TIMER0); +#endif +#ifdef BSP_USING_PWM1 + rcu_periph_clock_enable(RCU_TIMER1); +#endif +#ifdef BSP_USING_PWM2 + rcu_periph_clock_enable(RCU_TIMER2); +#endif +#ifdef BSP_USING_PWM3 + rcu_periph_clock_enable(RCU_TIMER3); +#endif +#ifdef BSP_USING_PWM4 + rcu_periph_clock_enable(RCU_TIMER4); +#endif + rcu_periph_clock_enable(RCU_AF); + + for (i = 0; i < sizeof(pwm_obj) / sizeof(pwm_obj[0]); i++) + { + pwm_obj[i].config = &pwm_config[i]; + rt_device_pwm_register(&pwm_obj[i].pwm_device, pwm_config[i].name, &gd32_drv_ops, pwm_obj[i].config); + gd32_pwm_init(&pwm_config[i]); + } + + return result; +} + +INIT_DEVICE_EXPORT(rt_pwm_init); + +#endif /* RT_USING_PWM */ diff --git a/bsp/nuclei/libraries/gd32vf103/HAL_Drivers/drv_pwm.h b/bsp/nuclei/libraries/gd32vf103/HAL_Drivers/drv_pwm.h new file mode 100644 index 0000000000..c0c6423263 --- /dev/null +++ b/bsp/nuclei/libraries/gd32vf103/HAL_Drivers/drv_pwm.h @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2006-2020, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2029-06-02 hqfang first implementation. + */ + +#ifndef __DRV_PWM__ +#define __DRV_PWM__ + +#include +#include +#include +#include + +/* gd32 config class */ +struct gd32_pwm_config +{ + const char *name; + rt_uint32_t periph; + rt_uint32_t period; + rt_uint32_t pulse; +}; + +struct gd32_pwm +{ + struct rt_device_pwm pwm_device; + struct gd32_pwm_config *config; +}; + +#endif diff --git a/bsp/nuclei/libraries/gd32vf103/HAL_Drivers/drv_rtc.c b/bsp/nuclei/libraries/gd32vf103/HAL_Drivers/drv_rtc.c new file mode 100644 index 0000000000..1d1c5ced78 --- /dev/null +++ b/bsp/nuclei/libraries/gd32vf103/HAL_Drivers/drv_rtc.c @@ -0,0 +1,160 @@ +/* + * Copyright (c) 2006-2020, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2020-06-08 hqfang first implementation. + */ + +#include "drv_rtc.h" + +#ifdef BSP_USING_RTC + +static time_t get_timestamp(void) +{ + return (time_t)rtc_counter_get(); +} + +static int set_timestamp(time_t timestamp) +{ + /* wait until last write operation on RTC registers has finished */ + rtc_lwoff_wait(); + /* change the current time */ + rtc_counter_set((uint32_t)timestamp); + /* wait until last write operation on RTC registers has finished */ + rtc_lwoff_wait(); + return RT_EOK; +} + +static void rtc_configuration(void) +{ + /* enable PMU and BKPI clocks */ + rcu_periph_clock_enable(RCU_BKPI); + rcu_periph_clock_enable(RCU_PMU); + /* allow access to BKP domain */ + pmu_backup_write_enable(); + + /* reset backup domain */ + bkp_deinit(); + + /* enable LXTAL */ + rcu_osci_on(RCU_LXTAL); + /* wait till LXTAL is ready */ + rcu_osci_stab_wait(RCU_LXTAL); + + /* select RCU_LXTAL as RTC clock source */ + rcu_rtc_clock_config(RCU_RTCSRC_LXTAL); + + /* enable RTC Clock */ + rcu_periph_clock_enable(RCU_RTC); + + /* wait for RTC registers synchronization */ + rtc_register_sync_wait(); + + /* wait until last write operation on RTC registers has finished */ + rtc_lwoff_wait(); + + /* wait until last write operation on RTC registers has finished */ + rtc_lwoff_wait(); + + /* set RTC prescaler: set RTC period to 1s */ + rtc_prescaler_set(32767); + + /* wait until last write operation on RTC registers has finished */ + rtc_lwoff_wait(); +} + +static rt_err_t gd32_rtc_init(rt_device_t dev) +{ + if (bkp_data_read(BKP_DATA_0) != 0xA5A5) + { + rtc_configuration(); + bkp_data_write(BKP_DATA_0, 0xA5A5); + } + else + { + /* allow access to BKP domain */ + rcu_periph_clock_enable(RCU_PMU); + pmu_backup_write_enable(); + + /* wait for RTC registers synchronization */ + rtc_register_sync_wait(); + /* wait until last write operation on RTC registers has finished */ + rtc_lwoff_wait(); + } + + return RT_EOK; +} + +static rt_err_t gd32_rtc_open(rt_device_t dev, rt_uint16_t oflag) +{ + return RT_EOK; +} + +static rt_err_t gd32_rtc_close(rt_device_t dev) +{ + return RT_EOK; +} + +static rt_size_t gd32_rtc_read(rt_device_t dev, rt_off_t pos, void *buffer, rt_size_t size) +{ + return RT_EOK; +} + +static rt_size_t gd32_rtc_write(rt_device_t dev, rt_off_t pos, const void *buffer, rt_size_t size) +{ + return RT_EOK; +} + +static rt_err_t gd32_rtc_control(rt_device_t dev, int cmd, void *args) +{ + RT_ASSERT(dev != RT_NULL); + + switch (cmd) + { + case RT_DEVICE_CTRL_RTC_GET_TIME: + { + *(uint32_t *)args = get_timestamp(); + } + break; + + case RT_DEVICE_CTRL_RTC_SET_TIME: + { + set_timestamp(*(time_t *)args); + } + break; + + default: + return RT_EINVAL; + } + + return RT_EOK; +} + +static struct rt_device rtc_device = +{ + .type = RT_Device_Class_RTC, + .init = gd32_rtc_init, + .open = gd32_rtc_open, + .close = gd32_rtc_close, + .read = gd32_rtc_read, + .write = gd32_rtc_write, + .control = gd32_rtc_control, +}; + +int rt_hw_rtc_init(void) +{ + rt_err_t ret = RT_EOK; + + ret = rt_device_register(&rtc_device, "rtc", RT_DEVICE_FLAG_RDWR); + + rt_device_open(&rtc_device, RT_DEVICE_OFLAG_RDWR); + + return RT_EOK; +} + +INIT_DEVICE_EXPORT(rt_hw_rtc_init); + +#endif /* BSP_USING_RTC */ diff --git a/bsp/nuclei/libraries/gd32vf103/HAL_Drivers/drv_rtc.h b/bsp/nuclei/libraries/gd32vf103/HAL_Drivers/drv_rtc.h new file mode 100644 index 0000000000..ae17cde802 --- /dev/null +++ b/bsp/nuclei/libraries/gd32vf103/HAL_Drivers/drv_rtc.h @@ -0,0 +1,19 @@ +/* + * Copyright (c) 2006-2020, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2020-06-08 hqfang first implementation. + */ + +#ifndef DRV_RTC_H__ +#define DRV_RTC_H__ + +#include +#include +#include +#include + +#endif diff --git a/bsp/nuclei/libraries/gd32vf103/HAL_Drivers/drv_spi.c b/bsp/nuclei/libraries/gd32vf103/HAL_Drivers/drv_spi.c new file mode 100644 index 0000000000..bcdaacb47b --- /dev/null +++ b/bsp/nuclei/libraries/gd32vf103/HAL_Drivers/drv_spi.c @@ -0,0 +1,287 @@ +/* + * Copyright (c) 2006-2020, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2020-05-28 hqfang first implementation. + */ + +#include "drv_spi.h" + +#ifdef RT_USING_SPI + +#if !defined(BSP_USING_SPI0) && !defined(BSP_USING_SPI1) && !defined(BSP_USING_SPI2) + #error "Please define at least one BSP_USING_SPIx" + /* this driver can be disabled at menuconfig -> Hardware Drivers Config -> On-chip Peripheral Drivers -> Enable SPI */ +#endif + +static struct gd32_spi_config spi_config[] = +{ +#ifdef BSP_USING_SPI0 + { + "spi0", + SPI0, + }, +#endif +#ifdef BSP_USING_SPI1 + { + "spi1", + SPI1, + }, +#endif +#ifdef BSP_USING_SPI2 + { + "spi2", + SPI2, + }, +#endif +}; + +static struct gd32_spi spi_obj[sizeof(spi_config) / sizeof(spi_config[0])] = {0}; + +static rt_err_t gd32_spi_init(rt_uint32_t spi_periph, struct rt_spi_configuration *cfg) +{ + spi_parameter_struct spicfg; + uint32_t apbfreq; + uint32_t scale; + + RT_ASSERT(cfg != RT_NULL); + + spi_struct_para_init(&spicfg); + + if (cfg->data_width != 8 && cfg->data_width != 16) + { + return (-RT_EINVAL); + } + + switch (spi_periph) + { + case SPI0: + apbfreq = rcu_clock_freq_get(CK_APB2); + break; + default: + apbfreq = rcu_clock_freq_get(CK_APB1); + break; + } + + scale = apbfreq / cfg->max_hz; + if (scale <= 2) + { + spicfg.prescale = SPI_PSC_2; + } + else if (scale <= 4) + { + spicfg.prescale = SPI_PSC_4; + } + else if (scale <= 8) + { + spicfg.prescale = SPI_PSC_8; + } + else if (scale <= 16) + { + spicfg.prescale = SPI_PSC_16; + } + else if (scale <= 32) + { + spicfg.prescale = SPI_PSC_32; + } + else if (scale <= 64) + { + spicfg.prescale = SPI_PSC_64; + } + else if (scale <= 128) + { + spicfg.prescale = SPI_PSC_128; + } + else if (scale <= 256) + { + spicfg.prescale = SPI_PSC_256; + } + else + { + spicfg.prescale = SPI_PSC_256; + } + + if (cfg->data_width == 8) + { + spicfg.frame_size = SPI_FRAMESIZE_8BIT; + } + else + { + spicfg.frame_size = SPI_FRAMESIZE_16BIT; + } + + if (cfg->mode & RT_SPI_MSB) + { + spicfg.endian = SPI_ENDIAN_MSB; + } + else + { + spicfg.endian = SPI_ENDIAN_LSB; + } + + spicfg.clock_polarity_phase = 0; + if (cfg->mode & RT_SPI_CPHA) + { + spicfg.clock_polarity_phase |= SPI_CTL0_CKPH; + } + if (cfg->mode & RT_SPI_CPOL) + { + spicfg.clock_polarity_phase |= SPI_CTL0_CKPL; + } + + if (cfg->mode & RT_SPI_SLAVE) + { + spicfg.device_mode = SPI_SLAVE; + } + else + { + spicfg.device_mode = SPI_MASTER; + } + spicfg.nss = SPI_NSS_SOFT; + spicfg.trans_mode = SPI_TRANSMODE_FULLDUPLEX; + + spi_init(spi_periph, &spicfg); + /* set crc polynomial */ + spi_crc_polynomial_set(spi_periph, 7); + + return RT_EOK; +} + +static rt_err_t gd32_spi_configure(struct rt_spi_device *device, struct rt_spi_configuration *cfg) +{ + rt_err_t ret = RT_EOK; + RT_ASSERT(device != RT_NULL); + + struct gd32_spi *spi_obj = (struct gd32_spi *)(device->bus->parent.user_data); + struct gd32_spi_config *spi_cfg = (struct gd32_spi_config *)(spi_obj->config); + + ret = gd32_spi_init(spi_cfg->spi_periph, cfg); + /* enable SPI */ + spi_enable(spi_cfg->spi_periph); + + return ret; +} + +/** + * Attach the spi device to SPI bus, this function must be used after initialization. + */ +rt_err_t rt_hw_spi_device_attach(const char *bus_name, const char *device_name, rt_uint32_t pin) +{ + rt_err_t ret = RT_EOK; + + struct rt_spi_device *spi_device = (struct rt_spi_device *)rt_malloc(sizeof(struct rt_spi_device)); + RT_ASSERT(spi_device != RT_NULL); + + struct gd32_spi_cs *cs_pin = (struct gd32_spi_cs *)rt_malloc(sizeof(struct gd32_spi_cs)); + RT_ASSERT(cs_pin != RT_NULL); + + cs_pin->pin = pin; + rt_pin_mode(pin, PIN_MODE_OUTPUT); + rt_pin_write(pin, PIN_HIGH); + + ret = rt_spi_bus_attach_device(spi_device, device_name, bus_name, (void *)cs_pin); + + return ret; +} + +rt_size_t gd32_spi_transmit(rt_uint32_t spi_periph, const void *send_buf, void *recv_buf, rt_size_t length) +{ + uint8_t *send_buf_8b = (uint8_t *)send_buf; + uint8_t *recv_buf_8b = (uint8_t *)recv_buf; + uint8_t sndbyte = 0xFF, rcvbyte; + rt_size_t idx = 0; + + while (idx < length) + { + while (RESET == spi_i2s_flag_get(spi_periph, SPI_FLAG_TBE)); + if (send_buf_8b) + { + sndbyte = send_buf_8b[idx]; + } + spi_i2s_data_transmit(spi_periph, sndbyte); + while (RESET == spi_i2s_flag_get(spi_periph, SPI_FLAG_RBNE)); + rcvbyte = spi_i2s_data_receive(spi_periph); + if (recv_buf_8b) + { + recv_buf_8b[idx] = rcvbyte; + } + idx ++; + } + + return length; +} + +static rt_uint32_t gd32_spi_xfer(struct rt_spi_device *device, struct rt_spi_message *message) +{ + rt_uint32_t total_length = 0; + rt_err_t ret = RT_EOK; + + RT_ASSERT(device != RT_NULL); + + struct gd32_spi *spi_obj = (struct gd32_spi *)(device->bus->parent.user_data); + struct gd32_spi_config *spi_cfg = (struct gd32_spi_config *)(spi_obj->config); + RT_ASSERT(spi_cfg != RT_NULL); + struct gd32_spi_cs *cs = (struct gd32_spi_cs *)(device->parent.user_data); + + if (message && message->cs_take) + { + rt_pin_write(cs->pin, PIN_LOW); + } + if (message && message->length) + { + + total_length += gd32_spi_transmit(spi_cfg->spi_periph, message->send_buf, \ + message->recv_buf, message->length); + } + if (message && message->cs_release) + { + rt_pin_write(cs->pin, PIN_HIGH); + } + return total_length; +} + +static const struct rt_spi_ops spi_ops = +{ + gd32_spi_configure, + gd32_spi_xfer +}; + +int rt_hw_spi_init(void) +{ + rt_size_t obj_num; + int index; + rt_err_t result = 0; + +#ifdef BSP_USING_SPI0 + rcu_periph_clock_enable(RCU_SPI0); +#endif +#ifdef BSP_USING_SPI1 + rcu_periph_clock_enable(RCU_SPI1); +#endif +#ifdef BSP_USING_SPI2 + rcu_periph_clock_enable(RCU_SPI2); +#endif + + obj_num = sizeof(spi_obj) / sizeof(struct gd32_spi); + for (index = 0; index < obj_num; index++) + { + /* init spi object */ + spi_obj[index].config = &spi_config[index]; + spi_obj[index].bus.parent.user_data = &spi_obj[index]; + + /* register spi device */ + result = rt_spi_bus_register(&spi_obj[index].bus, + spi_obj[index].config->name, + &spi_ops); + RT_ASSERT(result == RT_EOK); + } + + return 0; +} +INIT_DEVICE_EXPORT(rt_hw_spi_init); + +#endif +/* end of spi driver */ diff --git a/bsp/nuclei/libraries/gd32vf103/HAL_Drivers/drv_spi.h b/bsp/nuclei/libraries/gd32vf103/HAL_Drivers/drv_spi.h new file mode 100644 index 0000000000..a38f5c40c4 --- /dev/null +++ b/bsp/nuclei/libraries/gd32vf103/HAL_Drivers/drv_spi.h @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2006-2020, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2029-04-29 hqfang first implementation. + */ + +#ifndef __DRV_SPI__ +#define __DRV_SPI__ + +#include +#include +#include +#include + +/* gd32 config class */ +struct gd32_spi_config +{ + const char *name; + rt_uint32_t spi_periph; +}; + +struct gd32_spi_cs +{ + rt_uint32_t pin; +}; + +struct gd32_spi +{ + struct rt_spi_bus bus; + struct gd32_spi_config *config; +}; + +int rt_hw_spi_init(void); +rt_err_t rt_hw_spi_device_attach(const char *bus_name, const char *device_name, rt_uint32_t pin); + +#endif diff --git a/bsp/nuclei/libraries/gd32vf103/HAL_Drivers/drv_usart.c b/bsp/nuclei/libraries/gd32vf103/HAL_Drivers/drv_usart.c index 00fac33b3e..8b729abd8f 100644 --- a/bsp/nuclei/libraries/gd32vf103/HAL_Drivers/drv_usart.c +++ b/bsp/nuclei/libraries/gd32vf103/HAL_Drivers/drv_usart.c @@ -16,7 +16,7 @@ #if !defined(BSP_USING_UART0) && !defined(BSP_USING_UART1) && !defined(BSP_USING_UART2) \ && !defined(BSP_USING_UART3) && !defined(BSP_USING_UART4) #error "Please define at least one BSP_USING_UARTx" - /* this driver can be disabled at menuconfig -> RT-Thread Components -> Device Drivers */ + /* this driver can be disabled at menuconfig -> Hardware Drivers Config -> On-chip Peripheral Drivers -> Enable UART */ #endif enum @@ -64,8 +64,8 @@ static struct gd32_uart_config uart_config[] = #ifdef BSP_USING_UART3 { "uart3", - USART3, - USART3_IRQn, + UART3, + UART3_IRQn, }, #endif #ifdef BSP_USING_UART4 @@ -137,7 +137,7 @@ static rt_err_t gd32_configure(struct rt_serial_device *serial, break; } usart_hardware_flow_rts_config(usart->uart_base, USART_RTS_DISABLE); - usart_hardware_flow_cts_config(usart->uart_base, USART_RTS_DISABLE); + usart_hardware_flow_cts_config(usart->uart_base, USART_CTS_DISABLE); usart_receive_config(usart->uart_base, USART_RECEIVE_ENABLE); usart_transmit_config(usart->uart_base, USART_TRANSMIT_ENABLE); usart_enable(usart->uart_base); @@ -320,6 +320,22 @@ int rt_hw_usart_init(void) rt_size_t obj_num; int index; +#ifdef BSP_USING_UART0 + rcu_periph_clock_enable(RCU_USART0); +#endif +#ifdef BSP_USING_UART1 + rcu_periph_clock_enable(RCU_USART1); +#endif +#ifdef BSP_USING_UART2 + rcu_periph_clock_enable(RCU_USART2); +#endif +#ifdef BSP_USING_UART3 + rcu_periph_clock_enable(RCU_UART3); +#endif +#ifdef BSP_USING_UART4 + rcu_periph_clock_enable(RCU_UART4); +#endif + obj_num = sizeof(uart_obj) / sizeof(struct gd32_uart); struct serial_configure config = RT_SERIAL_CONFIG_DEFAULT; rt_err_t result = 0; diff --git a/bsp/nuclei/libraries/gd32vf103/HAL_Drivers/drv_usart.h b/bsp/nuclei/libraries/gd32vf103/HAL_Drivers/drv_usart.h index 176720c4a2..00b285847c 100644 --- a/bsp/nuclei/libraries/gd32vf103/HAL_Drivers/drv_usart.h +++ b/bsp/nuclei/libraries/gd32vf103/HAL_Drivers/drv_usart.h @@ -25,8 +25,8 @@ struct gd32_uart_config /* gd32 uart dirver class */ struct gd32_uart { - struct gd32_uart_config *config; struct rt_serial_device serial; + struct gd32_uart_config *config; }; int rt_hw_usart_init(void); diff --git a/bsp/nuclei/libraries/gd32vf103/HAL_Drivers/drv_wdt.c b/bsp/nuclei/libraries/gd32vf103/HAL_Drivers/drv_wdt.c new file mode 100644 index 0000000000..f0b340edac --- /dev/null +++ b/bsp/nuclei/libraries/gd32vf103/HAL_Drivers/drv_wdt.c @@ -0,0 +1,156 @@ +/* + * Copyright (c) 2006-2020, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2020-06-08 hqfang the first version. + * + */ +#include "drv_wdt.h" + +#ifdef BSP_USING_WDT + + +static rt_err_t gd32_wdog_close(rt_watchdog_t *wdt) +{ + rt_uint32_t level; + + level = rt_hw_interrupt_disable(); + rcu_osci_off(RCU_IRC40K); + rt_hw_interrupt_enable(level); + + return RT_EOK; +} + +static rt_err_t gd32_wdog_open(rt_watchdog_t *wdt, rt_uint16_t oflag) +{ + rt_uint32_t level; + + level = rt_hw_interrupt_disable(); + /* enable IRC40K */ + rcu_osci_on(RCU_IRC40K); + /* wait till IRC40K is ready */ + while (SUCCESS != rcu_osci_stab_wait(RCU_IRC40K)); + fwdgt_counter_reload(); + fwdgt_enable(); + rt_hw_interrupt_enable(level); + + return RT_EOK; +} + +static rt_err_t gd32_wdog_init(rt_watchdog_t *wdt) +{ + /* confiure FWDGT counter clock: 40KHz(IRC40K) / 256 = 0.15625 KHz */ + fwdgt_config(FWDGT_RLD_RLD, FWDGT_PSC_DIV256); + fwdgt_enable(); + return RT_EOK; +} + +static rt_err_t gd32_wdog_refresh(rt_watchdog_t *wdt) +{ + rt_uint32_t level; + + level = rt_hw_interrupt_disable(); + fwdgt_counter_reload(); + rt_hw_interrupt_enable(level); + + return RT_EOK; +} + +/** + * @function control wdog + * + * @param + * wdt whick wdog used + * cmd control wdog options + * args argument of conrtol + * @retval rt_err_t the status of control result + * + * + */ +#define WDT_RELOAD_SECOND ((FWDGT_RLD & FWDGT_RLD_RLD) / 156) +static rt_err_t gd32_wdog_control(rt_watchdog_t *wdt, int cmd, void *args) +{ + RT_ASSERT(wdt != NULL); + + uint16_t reload_value; + static uint16_t wdt_started = 0; + static rt_tick_t last_tick = 0; + + switch (cmd) + { + case RT_DEVICE_CTRL_WDT_GET_TIMEOUT: + { + *(uint16_t *)args = WDT_RELOAD_SECOND; + } + break; + case RT_DEVICE_CTRL_WDT_SET_TIMEOUT: + { + RT_ASSERT(*(uint16_t *)args != 0); + reload_value = *(uint16_t *)args; + // 6.4ms 1 tick, 1s -> 1000 / 6.4 = 625 / 4 ticks + reload_value = ((uint32_t)reload_value * 625) / 4; + fwdgt_write_enable(); + while (FWDGT_STAT & FWDGT_STAT_RUD); + FWDGT_RLD = FWDGT_RLD_RLD & reload_value; + fwdgt_write_disable(); + } + break; + case RT_DEVICE_CTRL_WDT_GET_TIMELEFT: + *(uint16_t *)args = WDT_RELOAD_SECOND - \ + (rt_tick_get() - last_tick) / RT_TICK_PER_SECOND; + + break; + case RT_DEVICE_CTRL_WDT_KEEPALIVE: + { + last_tick = rt_tick_get(); + gd32_wdog_refresh(wdt); + } + break; + case RT_DEVICE_CTRL_WDT_START: + { + gd32_wdog_open(wdt, *(rt_uint32_t *)args); + last_tick = rt_tick_get(); + wdt_started = 1; + while (FWDGT_STAT & FWDGT_STAT_RUD); + } + break; + case RT_DEVICE_CTRL_WDT_STOP: + { + gd32_wdog_close(wdt); + wdt_started = 0; + } + break; + default: + return RT_EINVAL; + } + + return RT_EOK; +} + +static struct rt_watchdog_ops gd32_wdog_ops = +{ + .init = gd32_wdog_init, + .control = gd32_wdog_control, +}; + +static struct rt_watchdog_device gd32_wdt_device; + +int rt_hw_wdt_init(void) +{ + int result = RT_EOK; + + rcu_osci_off(RCU_IRC40K); + gd32_wdt_device.ops = &gd32_wdog_ops; + result = rt_hw_watchdog_register(&gd32_wdt_device, "wdt", \ + RT_DEVICE_FLAG_RDWR, (void *)FWDGT); + + return result; +} + +INIT_DEVICE_EXPORT(rt_hw_wdt_init); + +#endif /* BSP_USING_WDT */ + diff --git a/bsp/nuclei/libraries/gd32vf103/HAL_Drivers/drv_wdt.h b/bsp/nuclei/libraries/gd32vf103/HAL_Drivers/drv_wdt.h new file mode 100644 index 0000000000..9c279dc5d4 --- /dev/null +++ b/bsp/nuclei/libraries/gd32vf103/HAL_Drivers/drv_wdt.h @@ -0,0 +1,20 @@ +/* + * Copyright (c) 2006-2020, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2029-06-08 hqfang first implementation. + */ + +#ifndef __DRV_WDT__ +#define __DRV_WDT__ + +#include +#include +#include +#include + + +#endif diff --git a/bsp/nuclei/tools/sdk_dist.py b/bsp/nuclei/tools/sdk_dist.py index f802e92730..260f0ee1cf 100644 --- a/bsp/nuclei/tools/sdk_dist.py +++ b/bsp/nuclei/tools/sdk_dist.py @@ -5,11 +5,10 @@ cwd_path = os.getcwd() sys.path.append(os.path.join(os.path.dirname(cwd_path), 'rt-thread', 'tools')) # BSP dist function -def dist_do_building(BSP_ROOT): +def dist_do_building(BSP_ROOT, dist_dir): from mkdist import bsp_copy_files import rtconfig - dist_dir = os.path.join(BSP_ROOT, 'dist', os.path.basename(BSP_ROOT)) library_dir = os.path.join(dist_dir, 'libraries') print("=> copy nuclei bsp library")