Merge pull request #3694 from nuclei-community/dev_nuclei_rvstar_pr_new
bsp/nuclei: Add more drivers support for gd32vf103_rvstar board
This commit is contained in:
commit
fa19533a3d
|
@ -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)
|
|
@ -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
|
||||
|
|
|
@ -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模块进行功能实现,所以在使用驱动时,请务必注意不要重叠使用相同模块。
|
||||
|
||||
## 联系人信息
|
||||
|
||||
|
|
|
@ -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')
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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 *******************/
|
||||
|
|
Binary file not shown.
After Width: | Height: | Size: 93 KiB |
Binary file not shown.
After Width: | Height: | Size: 34 KiB |
Binary file not shown.
After Width: | Height: | Size: 72 KiB |
Binary file not shown.
After Width: | Height: | Size: 39 KiB |
Binary file not shown.
After Width: | Height: | Size: 152 KiB |
|
@ -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 */
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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 */
|
||||
|
|
@ -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
|
|
@ -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 */
|
||||
|
|
|
@ -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 */
|
|
@ -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
|
|
@ -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 */
|
|
@ -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
|
|
@ -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 */
|
|
@ -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
|
|
@ -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 */
|
|
@ -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
|
|
@ -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 */
|
|
@ -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
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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 */
|
||||
|
|
@ -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
|
|
@ -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")
|
||||
|
|
Loading…
Reference in New Issue