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