[bsp][bouffalo] add pwm & rtc & wdt devices (#7122)

This commit is contained in:
WCX 2023-03-31 08:01:28 +08:00 committed by GitHub
parent 0cdf72f753
commit fb09316cb5
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
12 changed files with 595 additions and 14 deletions

25
bsp/bouffalo_lab/bl808/m0/.config Executable file → Normal file
View File

@ -84,7 +84,9 @@ CONFIG_RT_USING_CONSOLE=y
CONFIG_RT_CONSOLEBUF_SIZE=128
CONFIG_RT_CONSOLE_DEVICE_NAME="uart0"
CONFIG_RT_VER_NUM=0x50000
# CONFIG_RT_USING_STDC_ATOMIC is not set
# CONFIG_RT_USING_CACHE is not set
# CONFIG_RT_USING_HW_ATOMIC is not set
# CONFIG_ARCH_ARM_BOOTWITH_FLUSH_CACHE is not set
# CONFIG_ARCH_CPU_STACK_GROWS_UPWARD is not set
# CONFIG_RT_USING_CPU_FFS is not set
@ -141,15 +143,17 @@ CONFIG_RT_USING_PIN=y
# CONFIG_RT_USING_NULL is not set
# CONFIG_RT_USING_ZERO is not set
# CONFIG_RT_USING_RANDOM is not set
# CONFIG_RT_USING_PWM is not set
CONFIG_RT_USING_PWM=y
# CONFIG_RT_USING_MTD_NOR is not set
# CONFIG_RT_USING_MTD_NAND is not set
# CONFIG_RT_USING_PM is not set
# CONFIG_RT_USING_FDT is not set
# CONFIG_RT_USING_RTC is not set
CONFIG_RT_USING_RTC=y
# CONFIG_RT_USING_ALARM is not set
# CONFIG_RT_USING_SOFT_RTC is not set
# CONFIG_RT_USING_SDIO is not set
# CONFIG_RT_USING_SPI is not set
# CONFIG_RT_USING_WDT is not set
CONFIG_RT_USING_WDT=y
# CONFIG_RT_USING_AUDIO is not set
# CONFIG_RT_USING_SENSOR is not set
# CONFIG_RT_USING_TOUCH is not set
@ -912,7 +916,6 @@ CONFIG_RT_LIBC_DEFAULT_TIMEZONE=8
# Display
#
# CONFIG_PKG_USING_ARDUINO_U8G2 is not set
# CONFIG_PKG_USING_ARDUINO_U8GLIB_ARDUINO is not set
# CONFIG_PKG_USING_SEEED_TM1637 is not set
#
@ -942,17 +945,10 @@ CONFIG_RT_LIBC_DEFAULT_TIMEZONE=8
# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_PCF8574 is not set
# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_PCA9685 is not set
# CONFIG_PKG_USING_ARDUINO_SEEED_PCF85063TP is not set
# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_TPA2016 is not set
# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_DRV2605 is not set
# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_DS1841 is not set
# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_DS3502 is not set
#
# Other
#
# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_MFRC630 is not set
# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_SI5351 is not set
# CONFIG_PKG_USING_ARDUINO_RTCLIB is not set
#
# Signal IO
@ -976,7 +972,7 @@ CONFIG_BL808_CORE_M0=y
#
# General Drivers Configuration
#
# CONFIG_BSP_USING_GPIO is not set
CONFIG_BSP_USING_GPIO=y
#
# General Purpose UARTs
@ -989,3 +985,8 @@ CONFIG_UART0_TX_USING_GPIO14=y
CONFIG_UART0_RX_USING_GPIO15=y
# CONFIG_UART0_RX_USING_GPIO22 is not set
# CONFIG_UART0_RX_USING_GPIO23 is not set
# CONFIG_BSP_USING_UART1 is not set
# CONFIG_BSP_USING_UART2 is not set
# CONFIG_BSP_USING_RTC is not set
# CONFIG_BSP_USING_WDT is not set
# CONFIG_BSP_USING_PWM is not set

View File

@ -0,0 +1,70 @@
/*
* Copyright (c) 2006-2023, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2023-3-27 wcx1024979076 first version.
*/
/*
* PWM 使
* pwm_led_sample
* pwm_led_sample
* PWM LED LED不停的由暗变到亮
*/
#include <rtthread.h>
#include <rtdevice.h>
#ifdef RT_USING_PWM
#define LED_PIN_NUM 8 /* LED PIN脚编号查看驱动文件drv_gpio.c确定 */
#define PWM_DEV_NAME "pwm" /* PWM设备名称 */
#define PWM_DEV_CHANNEL 0 /* PWM通道 */
struct rt_device_pwm *pwm_dev; /* PWM设备句柄 */
static int pwm_led_sample(int argc, char *argv[])
{
rt_uint32_t period, pulse, dir;
period = 500000; /* 周期为0.5ms单位为纳秒ns */
dir = 1; /* PWM脉冲宽度值的增减方向 */
pulse = 0; /* PWM脉冲宽度值单位为纳秒ns */
/* 查找设备 */
pwm_dev = (struct rt_device_pwm *)rt_device_find(PWM_DEV_NAME);
if (pwm_dev == RT_NULL)
{
rt_kprintf("pwm sample run failed! can't find %s device!\n", PWM_DEV_NAME);
return -RT_ERROR;
}
/* 设置PWM周期和脉冲宽度默认值 */
rt_pwm_set(pwm_dev, PWM_DEV_CHANNEL, period, pulse);
/* 使能设备 */
rt_pwm_enable(pwm_dev, PWM_DEV_CHANNEL);
while (1)
{
rt_thread_mdelay(50);
if (dir)
{
pulse += 400000; /* 从0值开始每次增加5000ns */
}
else
{
pulse -= 400000; /* 从最大值开始每次减少5000ns */
}
if (pulse >= period)
{
dir = 0;
}
if (0 == pulse)
{
dir = 1;
}
/* 设置PWM周期和脉冲宽度 */
rt_pwm_set(pwm_dev, PWM_DEV_CHANNEL, period, pulse);
}
}
/* 导出到 msh 命令列表中 */
MSH_CMD_EXPORT(pwm_led_sample, pwm sample);
#endif /* RT_USING_PWM */

View File

@ -0,0 +1,82 @@
/*
* Copyright (c) 2006-2023, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2023-3-27 wcx1024979076 first version.
*/
/*
* 使
* wdt_sample
* wdt_sample wdt
* 使使
*
* 线
*/
#include <rtthread.h>
#include <rtdevice.h>
#ifdef RT_USING_WDT
#define WDT_DEVICE_NAME "wdt" /* 看门狗设备名称 */
static rt_device_t wdg_dev; /* 看门狗设备句柄 */
static void idle_hook(void)
{
/* 在空闲线程的回调函数里喂狗 */
rt_device_control(wdg_dev, RT_DEVICE_CTRL_WDT_KEEPALIVE, NULL);
rt_kprintf("feed the dog!\n ");
}
static int wdt_sample(int argc, char *argv[])
{
rt_err_t ret = RT_EOK;
rt_uint32_t timeout = 1; /* 溢出时间,单位:秒 */
char device_name[RT_NAME_MAX];
/* 判断命令行参数是否给定了设备名称 */
if (argc == 2)
{
rt_strncpy(device_name, argv[1], RT_NAME_MAX);
}
else
{
rt_strncpy(device_name, WDT_DEVICE_NAME, RT_NAME_MAX);
}
/* 根据设备名称查找看门狗设备,获取设备句柄 */
wdg_dev = rt_device_find(device_name);
if (!wdg_dev)
{
rt_kprintf("find %s failed!\n", device_name);
return -RT_ERROR;
}
/* 初始化设备 */
rt_device_init(wdg_dev);
/* 设置看门狗溢出时间 */
ret = rt_device_control(wdg_dev, RT_DEVICE_CTRL_WDT_SET_TIMEOUT, &timeout);
if (ret != RT_EOK)
{
rt_kprintf("set %s timeout failed!\n", device_name);
return -RT_ERROR;
}
/* 启动看门狗 */
ret = rt_device_control(wdg_dev, RT_DEVICE_CTRL_WDT_START, RT_NULL);
if (ret != RT_EOK)
{
rt_kprintf("start %s failed!\n", device_name);
return -RT_ERROR;
}
/* 设置空闲线程回调函数 */
rt_thread_idle_sethook(idle_hook);
return ret;
}
/* 导出到 msh 命令列表中 */
MSH_CMD_EXPORT(wdt_sample, wdt sample);
#endif /* RT_USING_WDT */

View File

@ -83,7 +83,6 @@
#define RT_SERIAL_USING_DMA
#define RT_SERIAL_RB_BUFSZ 64
#define RT_USING_PIN
/* Using USB */
@ -219,7 +218,6 @@
/* Other */
/* Signal IO */
@ -230,6 +228,7 @@
/* General Drivers Configuration */
#define BSP_USING_GPIO
/* General Purpose UARTs */

View File

@ -121,5 +121,37 @@ menu "General Drivers Configuration"
endmenu
menuconfig BSP_USING_RTC
bool "Enable RTC"
select RT_USING_RTC
default n
config BSP_USING_WDT
bool "Enable Watchdog Timer"
select RT_USING_WDT
default n
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
endif
endmenu

View File

@ -12,6 +12,15 @@ if GetDepend('BSP_USING_GPIO'):
if GetDepend('BSP_USING_I2C'):
src += ['drv_i2c.c']
if GetDepend('BSP_USING_RTC'):
src += ['drv_rtc.c']
if GetDepend('RT_USING_PWM'):
src += ['drv_pwm.c']
if GetDepend('RT_USING_WDT'):
src += ['drv_wdt.c']
group = DefineGroup('rt_drivers', src, depend = [''], CPPPATH = CPPPATH)
objs = [group]

View File

@ -0,0 +1,140 @@
/*
* Copyright (c) 2006-2023, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2023-03-12 wcx1024979076 first version
*/
#include <rtthread.h>
#include <rtdevice.h>
#include "drv_pwm.h"
#define DBG_LEVEL DBG_LOG
#include <rtdbg.h>
#define LOG_TAG "DRV.PWM"
#ifdef BSP_USING_PWM
static rt_err_t _pwm_set(rt_uint8_t channel, struct rt_pwm_configuration *configuration)
{
struct bflb_device_s* pwm = bflb_device_get_by_name("pwm_v2_0");
uint32_t period_hz = 1000000000 / configuration->period;
struct bflb_pwm_v2_config_s pwm_config;
pwm_config.clk_source = BFLB_SYSTEM_XCLK;
pwm_config.clk_div = 40;
pwm_config.period = 1000000 / period_hz;
bflb_pwm_v2_init(pwm, &pwm_config);
struct bflb_pwm_v2_channel_config_s pwm_ch_config = {
.positive_polarity = PWM_POLARITY_ACTIVE_HIGH,
.negative_polarity = PWM_POLARITY_ACTIVE_HIGH,
.positive_stop_state = PWM_STATE_INACTIVE,
.negative_stop_state = PWM_STATE_ACTIVE,
.positive_brake_state = PWM_STATE_INACTIVE,
.negative_brake_state = PWM_STATE_INACTIVE,
.dead_time = 0,
};
bflb_pwm_v2_channel_init(pwm, channel, &pwm_ch_config);
bflb_pwm_v2_channel_set_threshold(pwm, channel, 0, configuration->pulse);
bflb_pwm_v2_channel_positive_stop(pwm, channel);
bflb_pwm_v2_channel_negative_stop(pwm, channel);
bflb_pwm_v2_stop(pwm);
bflb_pwm_v2_channel_positive_start(pwm, channel);
bflb_pwm_v2_channel_negative_start(pwm, channel);
bflb_pwm_v2_start(pwm);
return RT_EOK;
}
static rt_err_t _pwm_get(rt_uint8_t channel, struct rt_pwm_configuration *configuration)
{
uint32_t reg_base, regval, tmp;
float period;
reg_base = bflb_device_get_by_name("pwm_v2_0")->reg_base;
regval = getreg32(reg_base + PWM_MC0_PERIOD_OFFSET);
tmp = (regval & PWM_PERIOD_MASK) >> PWM_PERIOD_SHIFT;
period = (float)tmp;
uint32_t period_hz = 1000000 / period;
regval = getreg32(reg_base + PWM_MC0_CH0_THRE_OFFSET + channel * 4);
uint16_t high_threhold = regval >> 16;
uint16_t low_threhold = regval;
configuration->period = 1000000000 / period_hz;
configuration->pulse = high_threhold;
return RT_EOK;
}
static rt_err_t _pwm_control(struct rt_device_pwm *device, int cmd, void *arg)
{
struct rt_pwm_configuration *configuration = (struct rt_pwm_configuration *)arg;
rt_uint32_t channel = 0;
channel = configuration->channel;
if (channel >= 4)
return -RT_EINVAL;
struct bflb_device_s* pwm = bflb_device_get_by_name("pwm_v2_0");
switch (cmd)
{
case PWM_CMD_ENABLE:
bflb_pwm_v2_channel_positive_start(pwm, channel);
bflb_pwm_v2_channel_negative_start(pwm, channel);
return RT_EOK;
case PWM_CMD_DISABLE:
bflb_pwm_v2_channel_positive_stop(pwm, channel);
bflb_pwm_v2_channel_negative_stop(pwm, channel);
return RT_EOK;
case PWM_CMD_SET:
return _pwm_set(channel, configuration);
case PWM_CMD_GET:
return _pwm_get(channel, configuration);
default:
return -RT_EINVAL;
}
}
static struct rt_pwm_ops _pwm_ops =
{
_pwm_control
};
static struct rt_device_pwm pwm_device;
int rt_hw_pwm_init(void)
{
int result = RT_EOK;
struct bflb_device_s* gpio = bflb_device_get_by_name("gpio");
bflb_gpio_init(gpio, GPIO_PIN_8, GPIO_FUNC_PWM0 | GPIO_ALTERNATE | GPIO_PULLDOWN | GPIO_SMT_EN | GPIO_DRV_1);
struct bflb_device_s* pwm = bflb_device_get_by_name("pwm_v2_0");
bflb_pwm_v2_start(pwm);
result = rt_device_pwm_register(&pwm_device, "pwm", &_pwm_ops, 0);
if(result != RT_EOK)
{
LOG_E("pwm device register fail.");
}
return result;
}
INIT_DEVICE_EXPORT(rt_hw_pwm_init);
#endif /* BSP_USING_PWM */

View File

@ -0,0 +1,19 @@
/*
* Copyright (c) 2006-2023, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2023-03-12 wcx1024979076 first version
*/
#ifndef __DRV_PWM_H__
#define __DRV_PWM_H__
#include "bflb_pwm_v2.h"
#include "bflb_clock.h"
#include "board.h"
#include "hardware/pwm_v2_reg.h"
int rt_hw_pwm_init(void);
#endif /* __DRV_PWM_H__ */

View File

@ -0,0 +1,90 @@
/*
* Copyright (c) 2006-2023, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2023-03-13 wcx1024979076 the first version
*/
#include <rtdevice.h>
#include "board.h"
#include "drv_rtc.h"
#define DBG_TAG "DRV.RTC"
#define DBG_LVL DBG_WARNING
#include <rtdbg.h>
#ifdef RT_USING_RTC
static struct rt_device rtc;
static rt_uint32_t rtc_time;
static rt_err_t _rtc_open(rt_device_t dev, rt_uint16_t oflag)
{
if (dev->rx_indicate != RT_NULL)
{
/* Open Interrupt */
}
return RT_EOK;
}
static rt_ssize_t _rtc_read(
rt_device_t dev,
rt_off_t pos,
void* buffer,
rt_size_t size)
{
return 0;
}
static rt_err_t _rtc_control(rt_device_t dev, int cmd, void *args)
{
RT_ASSERT(dev != RT_NULL);
struct bflb_device_s* bflb_rtc = bflb_device_get_by_name("rtc");
switch (cmd)
{
case RT_DEVICE_CTRL_RTC_GET_TIME:
*(rt_uint32_t *)args = rtc_time + BFLB_RTC_TIME2SEC(bflb_rtc_get_time(bflb_rtc));
break;
case RT_DEVICE_CTRL_RTC_SET_TIME:
rtc_time = *(rt_uint32_t *)args;
bflb_rtc_set_time(bflb_rtc, 0);
break;
}
return RT_EOK;
}
int rt_hw_rtc_init(void)
{
int result = RT_EOK;
struct bflb_device_s* bflb_rtc = bflb_device_get_by_name("rtc");
bflb_rtc_set_time(bflb_rtc, 0);
/* register rtc device */
rtc.type = RT_Device_Class_RTC;
rtc.rx_indicate = RT_NULL;
rtc.tx_complete = RT_NULL;
rtc.init = RT_NULL;
rtc.open = _rtc_open;
rtc.close = RT_NULL;
rtc.read = _rtc_read;
rtc.write = RT_NULL;
rtc.control = _rtc_control;
rtc.user_data = RT_NULL; /* no private */
result = rt_device_register(&rtc, "rtc", RT_DEVICE_FLAG_RDWR);
if(result != RT_EOK)
{
LOG_E("rtc device register fail.");
}
return result;
}
INIT_DEVICE_EXPORT(rt_hw_rtc_init);
#endif /* RT_USING_RTC */

View File

@ -0,0 +1,19 @@
/*
* Copyright (c) 2006-2023, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2023-03-13 wcx1024979076 the first version
*/
#ifndef __DRV_RTC_H__
#define __DRV_RTC_H__
#include "bflb_rtc.h"
#include <rtdevice.h>
#include <rthw.h>
int rt_hw_rtc_init(void);
#endif /* __DRV_RTC_H__ */

View File

@ -0,0 +1,97 @@
/*
* Copyright (c) 2006-2022, Synwit Technology Co.,Ltd.
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2023-03-14 wcx1024979076 first version
*/
#include "drv_wdt.h"
#ifdef RT_USING_WDT
#ifdef BSP_USING_WDT
#define DBG_LEVEL DBG_LOG
#include <rtdbg.h>
#define LOG_TAG "DRV.WDT"
struct rt_watchdog_device wdt_device;
static rt_err_t _wdt_configure(rt_watchdog_t *wdt_device)
{
struct bflb_device_s* wdt = bflb_device_get_by_name("watchdog");
struct bflb_wdg_config_s wdg_cfg;
wdg_cfg.clock_source = BFLB_SYSTEM_XCLK;
wdg_cfg.clock_div = 40;
wdg_cfg.comp_val = 10000000;
wdg_cfg.mode = WDG_MODE_RESET;
bflb_wdg_init(wdt, &wdg_cfg);
return RT_EOK;
}
static rt_err_t _wdt_control(rt_watchdog_t *wdt_device, int cmd, void *arg)
{
RT_ASSERT(wdt_device != RT_NULL);
struct bflb_device_s* wdt = bflb_device_get_by_name("watchdog");
struct bflb_wdg_config_s wdg_cfg;
switch (cmd)
{
case RT_DEVICE_CTRL_WDT_KEEPALIVE:
bflb_wdg_reset_countervalue(wdt);
break;
case RT_DEVICE_CTRL_WDT_SET_TIMEOUT:
wdg_cfg.clock_source = BFLB_SYSTEM_XCLK;
wdg_cfg.clock_div = 40;
wdg_cfg.comp_val = 10000000 * (*(rt_uint32_t *)arg);
wdg_cfg.mode = WDG_MODE_RESET;
bflb_wdg_init(wdt, &wdg_cfg);
bflb_wdg_start(wdt);
wdt_device->parent.user_data = (rt_uint32_t)(*(rt_uint32_t *)arg);
break;
case RT_DEVICE_CTRL_WDT_GET_TIMEOUT:
*(rt_uint32_t *)arg = (rt_uint32_t)wdt_device->parent.user_data;
break;
case RT_DEVICE_CTRL_WDT_GET_TIMELEFT:
*(rt_uint32_t *)arg = bflb_wdg_get_countervalue(wdt) / 10000000;
break;
case RT_DEVICE_CTRL_WDT_START:
bflb_wdg_start(wdt);
break;
case RT_DEVICE_CTRL_WDT_STOP:
bflb_wdg_stop(wdt);
break;
default:
LOG_W("This command is not supported.");
return -RT_EINVAL;
}
return RT_EOK;
}
static const struct rt_watchdog_ops _wdt_ops =
{
.init = _wdt_configure,
.control = _wdt_control
};
int rt_hw_wdt_init(void)
{
int result = RT_EOK;
wdt_device.ops = &_wdt_ops;
result = rt_hw_watchdog_register(&wdt_device, "wdt", RT_DEVICE_FLAG_RDWR, RT_NULL);
if(result != RT_EOK)
{
LOG_E("wdt device register fail.");
}
return result;
}
INIT_BOARD_EXPORT(rt_hw_wdt_init);
#endif /* BSP_USING_WDT */
#endif /* RT_USING_WDT */

View File

@ -0,0 +1,23 @@
/*
* Copyright (c) 2006-2022, Synwit Technology Co.,Ltd.
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2023-03-14 wcx1024979076 first version
*/
#ifndef __DRV_WDT_H__
#define __DRV_WDT_H__
#include "board.h"
#include "bflb_wdg.h"
#include "bflb_clock.h"
#include <rtthread.h>
#include "rtdevice.h"
#include <rthw.h>
int rt_hw_wdt_init(void);
#endif /* __DRV_WDT_H__ */