Browse Source

bsp/nuclei: Add more drivers support for gd32vf103_rvstar board

Squashed commit of the following:

commit 32dd349ccff85cdcad81021b5185f8f7347786db
Author: Huaqi Fang <578567190@qq.com>
Date:   Thu Jun 11 16:08:08 2020 +0800

    bsp/nuclei: Add more documentation about how to use RT-Thread in RV-STAR

    Signed-off-by: Huaqi Fang <578567190@qq.com>

commit c9474c20a558e9d7934a3d72cc9bb17a98c20871
Author: Huaqi Fang <578567190@qq.com>
Date:   Thu Jun 11 14:06:42 2020 +0800

    bsp/nuclei: remove comments in rt_hw_*_drvinit

    Signed-off-by: Huaqi Fang <578567190@qq.com>

commit 89b5caa2c3e55dc352b13f8e33229f03351b7049
Author: Huaqi Fang <578567190@qq.com>
Date:   Thu Jun 11 13:52:12 2020 +0800

    bsp/nuclei: Add a entry README.md for nuclei bsp

    Signed-off-by: Huaqi Fang <578567190@qq.com>

commit ae50d6e9bdc92ca4767c5ac7d0ded7252314a42e
Author: Huaqi Fang <578567190@qq.com>
Date:   Thu Jun 11 11:52:52 2020 +0800

    bsp/nuclei: update README.md cover more pinmux section

    Signed-off-by: Huaqi Fang <578567190@qq.com>

commit 1a42d85dfe5bc7b009f057784249d54d0c82de0f
Author: Huaqi Fang <578567190@qq.com>
Date:   Thu Jun 11 08:52:06 2020 +0800

    bsp/nuclei: clean up unused code in drv_spi.c

    Signed-off-by: Huaqi Fang <578567190@qq.com>

commit b40edcdf59c96ef261f65a0c023a24ac78cabb39
Author: Huaqi Fang <578567190@qq.com>
Date:   Wed Jun 10 14:09:15 2020 +0800

    bsp/nuclei: Format the code comments for hw pinmux init

    Signed-off-by: Huaqi Fang <578567190@qq.com>

commit c8ae9fdfdb989bbff85d911fee3124abd9d145db
Author: Huaqi Fang <578567190@qq.com>
Date:   Mon Jun 8 17:12:43 2020 +0800

    bsp/nuclei: Add more drivers support for gd32vf103

    * More drivers are supported for rvstar board, see README.md
    * If user want to use these supported drivers, menuconfig is required
    * User also need to setup pinmux for its coresponding driver in
    board/board.c

    Signed-off-by: Huaqi Fang <578567190@qq.com>

Signed-off-by: Huaqi Fang <578567190@qq.com>
Huaqi Fang 5 years ago
parent
commit
7761923ec5
32 changed files with 2287 additions and 87 deletions
  1. 16 0
      bsp/nuclei/README.md
  2. 24 20
      bsp/nuclei/gd32vf103_rvstar/.config
  3. 129 41
      bsp/nuclei/gd32vf103_rvstar/README.md
  4. 7 2
      bsp/nuclei/gd32vf103_rvstar/SConstruct
  5. 102 0
      bsp/nuclei/gd32vf103_rvstar/board/Kconfig
  6. 94 0
      bsp/nuclei/gd32vf103_rvstar/board/board.c
  7. BIN
      bsp/nuclei/gd32vf103_rvstar/doc/images/config_openocd_cfg.png
  8. BIN
      bsp/nuclei/gd32vf103_rvstar/doc/images/create_c_project.png
  9. BIN
      bsp/nuclei/gd32vf103_rvstar/doc/images/create_gdb_cfg.png
  10. BIN
      bsp/nuclei/gd32vf103_rvstar/doc/images/link_rtthread_code.png
  11. BIN
      bsp/nuclei/gd32vf103_rvstar/doc/images/start_debug_in_ide.png
  12. 8 10
      bsp/nuclei/gd32vf103_rvstar/rtconfig.h
  13. 5 5
      bsp/nuclei/gd32vf103_rvstar/rtconfig.py
  14. 22 0
      bsp/nuclei/libraries/gd32vf103/HAL_Drivers/SConscript
  15. 137 0
      bsp/nuclei/libraries/gd32vf103/HAL_Drivers/drv_adc.c
  16. 32 0
      bsp/nuclei/libraries/gd32vf103/HAL_Drivers/drv_adc.h
  17. 12 2
      bsp/nuclei/libraries/gd32vf103/HAL_Drivers/drv_gpio.c
  18. 315 0
      bsp/nuclei/libraries/gd32vf103/HAL_Drivers/drv_hwtimer.c
  19. 33 0
      bsp/nuclei/libraries/gd32vf103/HAL_Drivers/drv_hwtimer.h
  20. 228 0
      bsp/nuclei/libraries/gd32vf103/HAL_Drivers/drv_i2c.c
  21. 33 0
      bsp/nuclei/libraries/gd32vf103/HAL_Drivers/drv_i2c.h
  22. 352 0
      bsp/nuclei/libraries/gd32vf103/HAL_Drivers/drv_pwm.c
  23. 34 0
      bsp/nuclei/libraries/gd32vf103/HAL_Drivers/drv_pwm.h
  24. 160 0
      bsp/nuclei/libraries/gd32vf103/HAL_Drivers/drv_rtc.c
  25. 19 0
      bsp/nuclei/libraries/gd32vf103/HAL_Drivers/drv_rtc.h
  26. 287 0
      bsp/nuclei/libraries/gd32vf103/HAL_Drivers/drv_spi.c
  27. 40 0
      bsp/nuclei/libraries/gd32vf103/HAL_Drivers/drv_spi.h
  28. 20 4
      bsp/nuclei/libraries/gd32vf103/HAL_Drivers/drv_usart.c
  29. 1 1
      bsp/nuclei/libraries/gd32vf103/HAL_Drivers/drv_usart.h
  30. 156 0
      bsp/nuclei/libraries/gd32vf103/HAL_Drivers/drv_wdt.c
  31. 20 0
      bsp/nuclei/libraries/gd32vf103/HAL_Drivers/drv_wdt.h
  32. 1 2
      bsp/nuclei/tools/sdk_dist.py

+ 16 - 0
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)

+ 24 - 20
bsp/nuclei/gd32vf103_rvstar/.config

@@ -78,7 +78,7 @@ CONFIG_ARCH_RISCV32=y
 #
 #
 CONFIG_RT_USING_COMPONENTS_INIT=y
 CONFIG_RT_USING_COMPONENTS_INIT=y
 CONFIG_RT_USING_USER_MAIN=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
 CONFIG_RT_MAIN_THREAD_PRIORITY=10
 
 
 #
 #
@@ -97,7 +97,7 @@ CONFIG_FINSH_USING_SYMTAB=y
 CONFIG_FINSH_USING_DESCRIPTION=y
 CONFIG_FINSH_USING_DESCRIPTION=y
 # CONFIG_FINSH_ECHO_DISABLE_DEFAULT is not set
 # CONFIG_FINSH_ECHO_DISABLE_DEFAULT is not set
 CONFIG_FINSH_THREAD_PRIORITY=20
 CONFIG_FINSH_THREAD_PRIORITY=20
-CONFIG_FINSH_THREAD_STACK_SIZE=4096
+CONFIG_FINSH_THREAD_STACK_SIZE=2048
 CONFIG_FINSH_CMD_SIZE=80
 CONFIG_FINSH_CMD_SIZE=80
 # CONFIG_FINSH_USING_AUTH is not set
 # CONFIG_FINSH_USING_AUTH is not set
 CONFIG_FINSH_USING_MSH=y
 CONFIG_FINSH_USING_MSH=y
@@ -108,27 +108,18 @@ CONFIG_FINSH_ARG_MAX=10
 #
 #
 # Device virtual file system
 # 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
 # Device Drivers
 #
 #
 CONFIG_RT_USING_DEVICE_IPC=y
 CONFIG_RT_USING_DEVICE_IPC=y
 CONFIG_RT_PIPE_BUFSZ=512
 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_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_SERIAL_RB_BUFSZ=64
 # CONFIG_RT_USING_CAN is not set
 # CONFIG_RT_USING_CAN is not set
 # CONFIG_RT_USING_HWTIMER 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_LIBC=y
 # CONFIG_RT_USING_PTHREADS is not set
 # 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
 # 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_MONGOOSE is not set
 # CONFIG_PKG_USING_MYMQTT is not set
 # CONFIG_PKG_USING_MYMQTT is not set
 # CONFIG_PKG_USING_KAWAII_MQTT 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_WEBTERMINAL is not set
 # CONFIG_PKG_USING_CJSON is not set
 # CONFIG_PKG_USING_CJSON is not set
 # CONFIG_PKG_USING_JSMN 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_COAP is not set
 # CONFIG_PKG_USING_NOPOLL is not set
 # CONFIG_PKG_USING_NOPOLL is not set
 # CONFIG_PKG_USING_NETUTILS 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_PPP_DEVICE is not set
 # CONFIG_PKG_USING_AT_DEVICE is not set
 # CONFIG_PKG_USING_AT_DEVICE is not set
 # CONFIG_PKG_USING_ATSRV_SOCKET 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_CHINESE_FONT_LIBRARY is not set
 # CONFIG_PKG_USING_LUNAR_CALENDAR is not set
 # CONFIG_PKG_USING_LUNAR_CALENDAR is not set
 # CONFIG_PKG_USING_BS8116A is not set
 # CONFIG_PKG_USING_BS8116A is not set
+# CONFIG_PKG_USING_URLENCODE is not set
 
 
 #
 #
 # system packages
 # system packages
@@ -330,6 +320,7 @@ CONFIG_RT_USING_POSIX=y
 # CONFIG_PKG_USING_LWEXT4 is not set
 # CONFIG_PKG_USING_LWEXT4 is not set
 # CONFIG_PKG_USING_PARTITION is not set
 # CONFIG_PKG_USING_PARTITION is not set
 # CONFIG_PKG_USING_FAL 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_SQLITE is not set
 # CONFIG_PKG_USING_RTI is not set
 # CONFIG_PKG_USING_RTI is not set
 # CONFIG_PKG_USING_LITTLEVGL2RTT 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_LITTLED is not set
 # CONFIG_PKG_USING_LKDGUI is not set
 # CONFIG_PKG_USING_LKDGUI is not set
 # CONFIG_PKG_USING_NRF5X_SDK 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_WM_LIBRARIES is not set
 # CONFIG_PKG_USING_KENDRYTE_SDK is not set
 # CONFIG_PKG_USING_KENDRYTE_SDK is not set
 # CONFIG_PKG_USING_INFRARED 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_EASYBLINK is not set
 # CONFIG_PKG_USING_PMS_SERIES is not set
 # CONFIG_PKG_USING_PMS_SERIES is not set
 CONFIG_PKG_USING_NUCLEI_SDK=y
 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_NUCLEI_SDK_PATH="/packages/peripherals/nuclei_sdk"
 # CONFIG_PKG_USING_NUCLEI_SDK_V023 is not set
 # CONFIG_PKG_USING_NUCLEI_SDK_V023 is not set
 CONFIG_PKG_USING_NUCLEI_SDK_LATEST_VERSION=y
 CONFIG_PKG_USING_NUCLEI_SDK_LATEST_VERSION=y
 CONFIG_PKG_NUCLEI_SDK_VER="latest"
 CONFIG_PKG_NUCLEI_SDK_VER="latest"
+# CONFIG_PKG_USING_CAN_YMODEM is not set
 
 
 #
 #
 # miscellaneous packages
 # miscellaneous packages
@@ -446,6 +443,13 @@ CONFIG_BSP_USING_UART=y
 # CONFIG_BSP_USING_UART2 is not set
 # CONFIG_BSP_USING_UART2 is not set
 # CONFIG_BSP_USING_UART3 is not set
 # CONFIG_BSP_USING_UART3 is not set
 CONFIG_BSP_USING_UART4=y
 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
 # Board extended module Drivers

+ 129 - 41
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)
 更多关于 **RVSTAR开发板** 开发板的详细资料请参见 [RVSTAR开发板快速入门](https://www.rvmcu.com/quickstart-quickstart-index-u-RV_STAR.html)
 
 
 ### 板载资源
 ### 板载资源
 
 
-| 硬件 | 描述 |
-| ---  | --- |
-| 内核 | Nuclei N205 |
+| 硬件 | 描述            |
+| ---- | --------------- |
+| 内核 | Nuclei N205     |
 | 架构 | 32-bit RV32IMAC |
 | 架构 | 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 ...
 scons: Reading SConscript files ...
 Supported downloaded modes for board gd32vf103v_rvstar are flashxip, chosen downloaded mode is flashxip
 Supported downloaded modes for board gd32vf103v_rvstar are flashxip, chosen downloaded mode is flashxip
 Upload application rtthread.elf using openocd and gdb
 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"
 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.
 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)
 Nuclei OpenOCD, 64-bit Open On-Chip Debugger 0.10.0+dev-00014-g0eae03214 (2019-12-12-07:43)
 Licensed under GNU GPL v2
 Licensed under GNU GPL v2
 For bug reports, read
 For bug reports, read
         http://openocd.org/doc/doxygen/bugs.html
         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
 cleared protection for sectors 0 through 127 on flash bank 0
 
 
 Loading section .init, size 0x264 lma 0x8000000
 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
 shutdown command invoked
 A debugging session is active.
 A debugging session is active.
 
 
@@ -112,38 +113,55 @@ initialize rti_board_start:0 done
 
 
  \ | /
  \ | /
 - RT -     Thread Operating System
 - 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
  2006 - 2020 Copyright by rt-thread team
 do components initialization.
 do components initialization.
 initialize rti_board_end:0 done
 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 libc_system_init:0 done
 initialize finsh_system_init:0 done
 initialize finsh_system_init:0 done
-msh />
+msh >
 ```
 ```
 
 
 在串口终端(我这里使用的是TeraTerm)输入``ps``即可查看当前线程工作情况:
 在串口终端(我这里使用的是TeraTerm)输入``ps``即可查看当前线程工作情况:
 
 
 ~~~
 ~~~
-msh />ps
+msh >ps
 thread   pri  status      sp     stack size max used left tick  error
 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调试。
 在保证程序编译成功后, 在相同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 ...
 scons: Reading SConscript files ...
 Supported downloaded modes for board gd32vf103v_rvstar are flashxip, chosen downloaded mode is flashxip
 Supported downloaded modes for board gd32vf103v_rvstar are flashxip, chosen downloaded mode is flashxip
 Debug application rtthread.elf using openocd and gdb
 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".
 For help, type "help".
 Type "apropos word" to search for commands related to "word"...
 Type "apropos word" to search for commands related to "word"...
 Reading symbols from rtthread.elf...
 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
 Licensed under GNU GPL v2
 For bug reports, read
 For bug reports, read
         http://openocd.org/doc/doxygen/bugs.html
         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
 (gdb) c
 Continuing.
 Continuing.
 Note: automatically using hardware breakpoints for read-only addresses.
 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
 * 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)目录下。
 - 适配RT-Thread的驱动框架的代码在 [../libraries/gd32vf103/HAL_Drivers](../libraries/gd32vf103/HAL_Drivers)目录下。
 - 如果有开发者想适配更多的驱动, 请在对应目录下增加驱动适配支持。
 - 如果有开发者想适配更多的驱动, 请在对应目录下增加驱动适配支持。
+- GD32VF103的驱动适配开关在 `menuconfig -> Hardware Drivers Config -> On-chip Peripheral Drivers` 可以找到。
+- HWTIMER和PWM都是采用的TIMER模块进行功能实现,所以在使用驱动时,请务必注意不要重叠使用相同模块。
 
 
 ## 联系人信息
 ## 联系人信息
 
 

+ 7 - 2
bsp/nuclei/gd32vf103_rvstar/SConstruct

@@ -24,7 +24,8 @@ DefaultEnvironment(tools=[])
 env = Environment(tools = ['mingw'],
 env = Environment(tools = ['mingw'],
     AS = rtconfig.AS, ASFLAGS = rtconfig.AFLAGS,
     AS = rtconfig.AS, ASFLAGS = rtconfig.AFLAGS,
     CC = rtconfig.CC, CCFLAGS = rtconfig.CFLAGS,
     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)
     LINK = rtconfig.LINK, LINKFLAGS = rtconfig.LFLAGS)
 env.PrependENVPath('PATH', rtconfig.EXEC_PATH)
 env.PrependENVPath('PATH', rtconfig.EXEC_PATH)
 env['ASCOM'] = env['ASPPCOM']
 env['ASCOM'] = env['ASPPCOM']
@@ -50,7 +51,11 @@ objs = PrepareBuilding(env, RTT_ROOT)
 bsp_library_type = rtconfig.NUCLEI_SDK_SOC
 bsp_library_type = rtconfig.NUCLEI_SDK_SOC
 rtconfig.BSP_LIBRARY_TYPE = bsp_library_type
 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 <pkgs --update> in command line first!")
+    exit(0)
 
 
 # include hal drivers
 # include hal drivers
 hal_sconscript = os.path.join(libraries_path_prefix, bsp_library_type, 'HAL_Drivers', 'SConscript')
 hal_sconscript = os.path.join(libraries_path_prefix, bsp_library_type, 'HAL_Drivers', 'SConscript')

+ 102 - 0
bsp/nuclei/gd32vf103_rvstar/board/Kconfig

@@ -38,6 +38,108 @@ menu "On-chip Peripheral Drivers"
                 default n
                 default n
         endif
         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
 endmenu
 
 
 menu "Board extended module Drivers"
 menu "Board extended module Drivers"

+ 94 - 0
bsp/nuclei/gd32vf103_rvstar/board/board.c

@@ -32,6 +32,96 @@ extern void *_heap_end;
  */
  */
 extern void _init(void);
 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
  * @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
     _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 */
     /* USART driver initialization is open by default */
 #ifdef RT_USING_SERIAL
 #ifdef RT_USING_SERIAL
     rt_hw_usart_init();
     rt_hw_usart_init();
@@ -61,6 +154,7 @@ void rt_hw_board_init(void)
 #ifdef RT_USING_COMPONENTS_INIT
 #ifdef RT_USING_COMPONENTS_INIT
     rt_components_board_init();
     rt_components_board_init();
 #endif
 #endif
+
 }
 }
 
 
 /******************** end of file *******************/
 /******************** end of file *******************/

BIN
bsp/nuclei/gd32vf103_rvstar/doc/images/config_openocd_cfg.png


BIN
bsp/nuclei/gd32vf103_rvstar/doc/images/create_c_project.png


BIN
bsp/nuclei/gd32vf103_rvstar/doc/images/create_gdb_cfg.png


BIN
bsp/nuclei/gd32vf103_rvstar/doc/images/link_rtthread_code.png


BIN
bsp/nuclei/gd32vf103_rvstar/doc/images/start_debug_in_ide.png


+ 8 - 10
bsp/nuclei/gd32vf103_rvstar/rtconfig.h

@@ -52,7 +52,7 @@
 
 
 #define RT_USING_COMPONENTS_INIT
 #define RT_USING_COMPONENTS_INIT
 #define RT_USING_USER_MAIN
 #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
 #define RT_MAIN_THREAD_PRIORITY 10
 
 
 /* C++ features */
 /* C++ features */
@@ -67,7 +67,7 @@
 #define FINSH_USING_SYMTAB
 #define FINSH_USING_SYMTAB
 #define FINSH_USING_DESCRIPTION
 #define FINSH_USING_DESCRIPTION
 #define FINSH_THREAD_PRIORITY 20
 #define FINSH_THREAD_PRIORITY 20
-#define FINSH_THREAD_STACK_SIZE 4096
+#define FINSH_THREAD_STACK_SIZE 2048
 #define FINSH_CMD_SIZE 80
 #define FINSH_CMD_SIZE 80
 #define FINSH_USING_MSH
 #define FINSH_USING_MSH
 #define FINSH_USING_MSH_DEFAULT
 #define FINSH_USING_MSH_DEFAULT
@@ -75,19 +75,15 @@
 
 
 /* Device virtual file system */
 /* 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 */
 /* Device Drivers */
 
 
 #define RT_USING_DEVICE_IPC
 #define RT_USING_DEVICE_IPC
 #define RT_PIPE_BUFSZ 512
 #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
-#define RT_SERIAL_USING_DMA
 #define RT_SERIAL_RB_BUFSZ 64
 #define RT_SERIAL_RB_BUFSZ 64
 #define RT_USING_PIN
 #define RT_USING_PIN
 
 
@@ -97,7 +93,6 @@
 /* POSIX layer and C standard library */
 /* POSIX layer and C standard library */
 
 
 #define RT_USING_LIBC
 #define RT_USING_LIBC
-#define RT_USING_POSIX
 
 
 /* Network */
 /* Network */
 
 
@@ -153,6 +148,9 @@
 /* peripheral libraries and drivers */
 /* peripheral libraries and drivers */
 
 
 #define PKG_USING_NUCLEI_SDK
 #define PKG_USING_NUCLEI_SDK
+
+/* !!!Nuclei SDK only works with Nuclei RISC-V Processor IP!!! */
+
 #define PKG_USING_NUCLEI_SDK_LATEST_VERSION
 #define PKG_USING_NUCLEI_SDK_LATEST_VERSION
 
 
 /* miscellaneous packages */
 /* miscellaneous packages */

+ 5 - 5
bsp/nuclei/gd32vf103_rvstar/rtconfig.py

@@ -23,7 +23,6 @@ else:
 BUILD = 'debug'
 BUILD = 'debug'
 
 
 # Fixed configurations below
 # Fixed configurations below
-NUCLEI_SDK_OPENOCD_CFG = "type in your config"
 NUCLEI_SDK_SOC = "gd32vf103"
 NUCLEI_SDK_SOC = "gd32vf103"
 NUCLEI_SDK_BOARD = "gd32vf103v_rvstar"
 NUCLEI_SDK_BOARD = "gd32vf103v_rvstar"
 NUCLEI_SDK_DOWNLOAD = "flashxip"
 NUCLEI_SDK_DOWNLOAD = "flashxip"
@@ -46,13 +45,14 @@ if PLATFORM == 'gcc':
     CFLAGS  = ' -ffunction-sections -fdata-sections -fno-common '
     CFLAGS  = ' -ffunction-sections -fdata-sections -fno-common '
     AFLAGS  = CFLAGS
     AFLAGS  = CFLAGS
     LFLAGS  = ' --specs=nano.specs --specs=nosys.specs -nostartfiles -Wl,--gc-sections '
     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 '
     LFLAGS  += ' -u _isatty -u _write -u _sbrk -u _read -u _close -u _fstat -u _lseek '
     CPATH   = ''
     CPATH   = ''
     LPATH   = ''
     LPATH   = ''
+    LIBS = ['stdc++']
 
 
     if BUILD == 'debug':
     if BUILD == 'debug':
-        CFLAGS += ' -O0 -ggdb'
+        CFLAGS += ' -O2 -Os -ggdb'
         AFLAGS += ' -ggdb'
         AFLAGS += ' -ggdb'
     else:
     else:
         CFLAGS += ' -O2 -Os'
         CFLAGS += ' -O2 -Os'
@@ -62,9 +62,9 @@ if PLATFORM == 'gcc':
 DUMP_ACTION = OBJDUMP + ' -D -S $TARGET > rtt.asm\n'
 DUMP_ACTION = OBJDUMP + ' -D -S $TARGET > rtt.asm\n'
 POST_ACTION = OBJCPY + ' -O binary $TARGET rtthread.bin\n' + SIZE + ' $TARGET \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
     import sys
     cwd_path = os.getcwd()
     cwd_path = os.getcwd()
     sys.path.append(os.path.join(os.path.dirname(BSP_ROOT), 'tools'))
     sys.path.append(os.path.join(os.path.dirname(BSP_ROOT), 'tools'))
     from sdk_dist import dist_do_building
     from sdk_dist import dist_do_building
-    dist_do_building(BSP_ROOT)
+    dist_do_building(BSP_ROOT, dist_dir)

+ 22 - 0
bsp/nuclei/libraries/gd32vf103/HAL_Drivers/SConscript

@@ -14,6 +14,28 @@ if GetDepend(['RT_USING_PIN']):
 if GetDepend(['RT_USING_SERIAL']):
 if GetDepend(['RT_USING_SERIAL']):
     src += ['drv_usart.c']
     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]
 path =  [cwd]
 
 
 group = DefineGroup('Drivers', src, depend = [''], CPPPATH = path)
 group = DefineGroup('Drivers', src, depend = [''], CPPPATH = path)

+ 137 - 0
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 */
+

+ 32 - 0
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 <rtthread.h>
+#include <rtdevice.h>
+#include <rthw.h>
+#include <drv_config.h>
+
+/* 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

+ 12 - 2
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;
     const struct pin_irq_map *irqmap;
     rt_base_t level;
     rt_base_t level;
     rt_int32_t irqindex = -1;
     rt_int32_t irqindex = -1;
+    rt_uint8_t portsrc = 0, pinsrc = 0;
     exti_trig_type_enum trigger_mode;
     exti_trig_type_enum trigger_mode;
 
 
+    portsrc = pin >> 4;
+    pinsrc = pin % 16;
     index = get_pin(pin);
     index = get_pin(pin);
     if (index == RT_NULL)
     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);
             rt_hw_interrupt_enable(level);
             return RT_EINVAL;
             return RT_EINVAL;
         }
         }
+
         /* connect EXTI line to  GPIO pin */
         /* connect EXTI line to  GPIO pin */
-        gpio_exti_source_select(index->gpio, index->pin);
+        gpio_exti_source_select(portsrc, pinsrc);
 
 
         /* configure EXTI line */
         /* configure EXTI line */
         exti_init((exti_line_enum)(index->pin), EXTI_INTERRUPT, trigger_mode);
         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);
         ECLIC_EnableIRQ(irqmap->irqno);
         pin_irq_enable_mask |= irqmap->pinbit;
         pin_irq_enable_mask |= irqmap->pinbit;
 
 
+        exti_interrupt_enable((exti_line_enum)(index->pin));
+
         rt_hw_interrupt_enable(level);
         rt_hw_interrupt_enable(level);
     }
     }
     else if (enabled == PIN_IRQ_DISABLE)
     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)))
             if (!(pin_irq_enable_mask & (GPIO_PIN_5 | GPIO_PIN_6 | GPIO_PIN_7 | GPIO_PIN_8 | GPIO_PIN_9)))
             {
             {
                 ECLIC_DisableIRQ(irqmap->irqno);
                 ECLIC_DisableIRQ(irqmap->irqno);
+                exti_interrupt_disable((exti_line_enum)(index->pin));
             }
             }
         }
         }
         else if ((irqmap->pinbit >= GPIO_PIN_10) && (irqmap->pinbit <= GPIO_PIN_15))
         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)))
             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);
                 ECLIC_DisableIRQ(irqmap->irqno);
+                exti_interrupt_disable((exti_line_enum)(index->pin));
             }
             }
         }
         }
         else
         else
         {
         {
             ECLIC_DisableIRQ(irqmap->irqno);
             ECLIC_DisableIRQ(irqmap->irqno);
+            exti_interrupt_disable((exti_line_enum)(index->pin));
         }
         }
     }
     }
     else
     else
@@ -515,6 +524,7 @@ int rt_hw_pin_init(void)
     rcu_periph_clock_enable(RCU_AF);
     rcu_periph_clock_enable(RCU_AF);
     return rt_device_pin_register("pin", &_gd32_pin_ops, RT_NULL);
     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 */
 #endif /* RT_USING_PIN */

+ 315 - 0
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 */

+ 33 - 0
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 <rtthread.h>
+#include <rtdevice.h>
+#include <rthw.h>
+#include <drv_config.h>
+
+/* 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

+ 228 - 0
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 */

+ 33 - 0
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 <rtthread.h>
+#include <rtdevice.h>
+#include <rthw.h>
+#include <drv_config.h>
+
+/* 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

+ 352 - 0
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 <rtdbg.h>
+
+#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 */

+ 34 - 0
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 <rtthread.h>
+#include <rtdevice.h>
+#include <rthw.h>
+#include <drv_config.h>
+
+/* 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

+ 160 - 0
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 */

+ 19 - 0
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 <rtthread.h>
+#include <rtdevice.h>
+#include <rthw.h>
+#include <drv_config.h>
+
+#endif

+ 287 - 0
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 */

+ 40 - 0
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 <rtthread.h>
+#include <rtdevice.h>
+#include <rthw.h>
+#include <drv_config.h>
+
+/* 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

+ 20 - 4
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) \
 #if !defined(BSP_USING_UART0) && !defined(BSP_USING_UART1) && !defined(BSP_USING_UART2) \
     && !defined(BSP_USING_UART3) && !defined(BSP_USING_UART4)
     && !defined(BSP_USING_UART3) && !defined(BSP_USING_UART4)
     #error "Please define at least one BSP_USING_UARTx"
     #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
 #endif
 
 
 enum
 enum
@@ -64,8 +64,8 @@ static struct gd32_uart_config uart_config[] =
 #ifdef BSP_USING_UART3
 #ifdef BSP_USING_UART3
     {
     {
         "uart3",
         "uart3",
-        USART3,
-        USART3_IRQn,
+        UART3,
+        UART3_IRQn,
     },
     },
 #endif
 #endif
 #ifdef BSP_USING_UART4
 #ifdef BSP_USING_UART4
@@ -137,7 +137,7 @@ static rt_err_t gd32_configure(struct rt_serial_device *serial,
         break;
         break;
     }
     }
     usart_hardware_flow_rts_config(usart->uart_base, USART_RTS_DISABLE);
     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_receive_config(usart->uart_base, USART_RECEIVE_ENABLE);
     usart_transmit_config(usart->uart_base, USART_TRANSMIT_ENABLE);
     usart_transmit_config(usart->uart_base, USART_TRANSMIT_ENABLE);
     usart_enable(usart->uart_base);
     usart_enable(usart->uart_base);
@@ -320,6 +320,22 @@ int rt_hw_usart_init(void)
     rt_size_t obj_num;
     rt_size_t obj_num;
     int index;
     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);
     obj_num = sizeof(uart_obj) / sizeof(struct gd32_uart);
     struct serial_configure config = RT_SERIAL_CONFIG_DEFAULT;
     struct serial_configure config = RT_SERIAL_CONFIG_DEFAULT;
     rt_err_t result = 0;
     rt_err_t result = 0;

+ 1 - 1
bsp/nuclei/libraries/gd32vf103/HAL_Drivers/drv_usart.h

@@ -25,8 +25,8 @@ struct gd32_uart_config
 /* gd32 uart dirver class */
 /* gd32 uart dirver class */
 struct gd32_uart
 struct gd32_uart
 {
 {
-    struct gd32_uart_config *config;
     struct rt_serial_device serial;
     struct rt_serial_device serial;
+    struct gd32_uart_config *config;
 };
 };
 
 
 int rt_hw_usart_init(void);
 int rt_hw_usart_init(void);

+ 156 - 0
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 */
+

+ 20 - 0
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 <rtthread.h>
+#include <rtdevice.h>
+#include <rthw.h>
+#include <drv_config.h>
+
+
+#endif

+ 1 - 2
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'))
 sys.path.append(os.path.join(os.path.dirname(cwd_path), 'rt-thread', 'tools'))
 
 
 # BSP dist function
 # BSP dist function
-def dist_do_building(BSP_ROOT):
+def dist_do_building(BSP_ROOT, dist_dir):
     from mkdist import bsp_copy_files
     from mkdist import bsp_copy_files
     import rtconfig
     import rtconfig
 
 
-    dist_dir  = os.path.join(BSP_ROOT, 'dist', os.path.basename(BSP_ROOT))
     library_dir  = os.path.join(dist_dir, 'libraries')
     library_dir  = os.path.join(dist_dir, 'libraries')
 
 
     print("=> copy nuclei bsp library")
     print("=> copy nuclei bsp library")