bsp/nuclei: Add more drivers support for gd32vf103

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

Signed-off-by: Huaqi Fang <578567190@qq.com>
This commit is contained in:
Huaqi Fang 2020-06-08 17:12:43 +08:00
parent ce83371504
commit c8ae9fdfdb
26 changed files with 2196 additions and 47 deletions

View File

@ -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

View File

@ -195,12 +195,34 @@ ELF文件, 然后配置OPENOCD和GDB即可, OPENOCD配置文件路径为**bsp\nu
| 驱动 | 支持情况 | 备注 |
| ------ | ---- | :------: |
| UART | 支持 | RV-STAR板载串口是UART4 |
| UART | 支持 | RV-STAR板载串口是UART4, 默认使能 |
| GPIO | 支持 | 默认使能,支持中断控制 |
| SPI | 支持 | 默认关闭 |
| I2C | 支持 | 默认关闭 |
| HWTIMER | 支持 | 默认关闭 |
| PWM | 支持 | 默认关闭 |
| WDT | 支持 | 默认关闭 |
| RTC | 支持 | 默认关闭 |
| ADC | 支持 | 默认关闭 |
由于针对不同的外设接口GPIO的pinux配置不一样开发者需要根据自己的需求
`board/board.c` 中的 `rt_hw_drivers_init`入口函数中使用到这个子函数
中进行功能适配。
例如需要将I2C1的SCL和SDA配置在PB10和PB11则配置代码在`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);
~~~
**注:**
- 适配RT-Thread的驱动框架的代码在 [../libraries/gd32vf103/HAL_Drivers](../libraries/gd32vf103/HAL_Drivers)目录下。
- 如果有开发者想适配更多的驱动, 请在对应目录下增加驱动适配支持。
- GD32VF103的驱动适配开关在 `menuconfig -> Hardware Drivers Config -> On-chip Peripheral Drivers` 可以找到。
- HWTIMER和PWM都是采用的TIMER模块进行功能实现所以在使用驱动时请务必注意不要重叠使用相同模块。
## 联系人信息

View File

@ -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
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')

View File

@ -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"

View File

@ -32,6 +32,125 @@ extern void *_heap_end;
*/
extern void _init(void);
// Check pin assignment here https://doc.nucleisys.com/nuclei_board_labs/hw/hw.html
void rt_hw_spi_drvinit(void)
{
// rcu_periph_clock_enable(RCU_GPIOA);
// rcu_periph_clock_enable(RCU_GPIOE);
// rcu_periph_clock_enable(RCU_AF);
// /* 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);
// /* Configure PE2 PE3 PE4 (CS OLED_DC OLED_RES ) as output */
// gpio_init(GPIOE, GPIO_MODE_OUT_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_2 | GPIO_PIN_3 | GPIO_PIN_4);
// rcu_periph_clock_enable(RCU_GPIOB);
// /* SPI1_SCK(PB13), SPI1_MISO(PB14) and SPI1_MOSI(PB15) GPIO pin configuration */
// gpio_init(GPIOB, GPIO_MODE_AF_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_13 | GPIO_PIN_15);
// gpio_init(GPIOB, GPIO_MODE_IN_FLOATING, GPIO_OSPEED_50MHZ, GPIO_PIN_14);
// /* SPI1_CS(PB12) GPIO pin configuration */
// gpio_init(GPIOB, GPIO_MODE_OUT_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_12);
}
void rt_hw_adc_drvinit(void)
{
}
void rt_hw_gpio_drvinit(void)
{
}
void rt_hw_hwtimer_drvinit(void)
{
}
void rt_hw_i2c_drvinit(void)
{
// rcu_periph_clock_enable(RCU_GPIOB);
// rcu_periph_clock_enable(RCU_AF);
// /* 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);
// /* Configure PB6 PB7 (I2C0 SCL SDA) as alternate function */
// gpio_init(GPIOB, GPIO_MODE_AF_OD, GPIO_OSPEED_50MHZ, GPIO_PIN_6 | GPIO_PIN_7);
}
void rt_hw_pwm_drvinit(void)
{
// rcu_periph_clock_enable(RCU_GPIOA);
// rcu_periph_clock_enable(RCU_GPIOB);
// rcu_periph_clock_enable(RCU_AF);
/* Configure PA0 PA1 PA2 PA3(TIMER1 CH0 CH1 CH2 CH3) as alternate function */
// gpio_init(GPIOA, GPIO_MODE_AF_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_0);
// gpio_init(GPIOA, GPIO_MODE_AF_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_1);
// gpio_init(GPIOA, GPIO_MODE_AF_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_2);
// gpio_init(GPIOA, GPIO_MODE_AF_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_3);
/* Configure PA6 PA7 PB0 PB1(TIMER2 CH0 CH1 CH2 CH3) as alternate function */
// gpio_init(GPIOA, GPIO_MODE_AF_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_6);
// gpio_init(GPIOA, GPIO_MODE_AF_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_7);
// gpio_init(GPIOB, GPIO_MODE_AF_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_0);
// gpio_init(GPIOB, GPIO_MODE_AF_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_1);
}
void rt_hw_rtc_drvinit(void)
{
}
void rt_hw_uart_drvinit(void)
{
// Debug UART4 GPIO pins are already initialized in nuclei_sdk
// rcu_periph_clock_enable(RCU_GPIOC);
// rcu_periph_clock_enable(RCU_AF);
// /* Configure PC10 PC11(UART3 TX RX) as alternate function */
// gpio_init(GPIOC, GPIO_MODE_AF_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_10);
// gpio_init(GPIOC, GPIO_MODE_IN_FLOATING, GPIO_OSPEED_50MHZ, GPIO_PIN_11);
}
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 +166,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 +183,7 @@ void rt_hw_board_init(void)
#ifdef RT_USING_COMPONENTS_INIT
rt_components_board_init();
#endif
}
/******************** end of file *******************/

View File

@ -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 */

View File

@ -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"
@ -50,9 +49,10 @@ if PLATFORM == 'gcc':
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)

View File

@ -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)

View File

@ -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 */

View File

@ -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

View File

@ -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 */

View File

@ -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 */

View File

@ -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

View File

@ -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 */

View File

@ -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

View File

@ -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 */

View File

@ -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

View File

@ -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 */

View File

@ -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

View File

@ -0,0 +1,289 @@
/*
* 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 ++;
}
// Wait for transmission complete
// while(SET == spi_i2s_flag_get(spi_periph, SPI_FLAG_TRANS));
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 */

View File

@ -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

View File

@ -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;

View File

@ -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);

View File

@ -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 */

View File

@ -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

View File

@ -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")