bsp: k230: add support for PWM driver

Added a PWM driver and a test file test_pwm.c.
The test uses PWM to control the LED brightness,
to check if the driver works correctly.

Signed-off-by: XU HU <1337858472@qq.com>
This commit is contained in:
dannyray019 2025-07-29 13:26:42 +08:00 committed by Rbb666
parent 95bd6854db
commit c209173061
8 changed files with 608 additions and 5 deletions

View File

@ -204,6 +204,9 @@ CONFIG_ARCH_MM_MMU=y
CONFIG_KERNEL_VADDR_START=0xffffffc000000000
CONFIG_ARCH_RISCV=y
CONFIG_ARCH_RISCV_FPU=y
CONFIG_ARCH_RISCV_VECTOR=y
CONFIG_ARCH_VECTOR_VLEN_128=y
# CONFIG_ARCH_VECTOR_VLEN_256 is not set
CONFIG_ARCH_RISCV_FPU_D=y
CONFIG_ARCH_RISCV64=y
CONFIG_ARCH_USING_NEW_CTX_SWITCH=y
@ -706,6 +709,7 @@ CONFIG_RT_USING_VDSO=y
# CONFIG_PKG_USING_LHC_MODBUS is not set
# CONFIG_PKG_USING_QMODBUS is not set
# CONFIG_PKG_USING_PNET is not set
# CONFIG_PKG_USING_OPENER is not set
# end of IoT - internet of things
#
@ -839,6 +843,7 @@ CONFIG_RT_USING_VDSO=y
# CONFIG_PKG_USING_VOFA_PLUS is not set
# CONFIG_PKG_USING_ZDEBUG is not set
# CONFIG_PKG_USING_RVBACKTRACE is not set
# CONFIG_PKG_USING_HPATCHLITE is not set
# end of tools packages
#
@ -867,7 +872,6 @@ CONFIG_RT_USING_VDSO=y
#
# CONFIG_PKG_USING_CMSIS_5 is not set
# CONFIG_PKG_USING_CMSIS_CORE is not set
# CONFIG_PKG_USING_CMSIS_DSP is not set
# CONFIG_PKG_USING_CMSIS_NN is not set
# CONFIG_PKG_USING_CMSIS_RTOS1 is not set
# CONFIG_PKG_USING_CMSIS_RTOS2 is not set
@ -919,7 +923,6 @@ CONFIG_RT_USING_VDSO=y
# CONFIG_PKG_USING_ARM_2D is not set
# CONFIG_PKG_USING_MCUBOOT is not set
# CONFIG_PKG_USING_TINYUSB is not set
# CONFIG_PKG_USING_CHERRYUSB is not set
# CONFIG_PKG_USING_KMULTI_RTIMER is not set
# CONFIG_PKG_USING_TFDB is not set
# CONFIG_PKG_USING_QPC is not set
@ -931,6 +934,7 @@ CONFIG_RT_USING_VDSO=y
# CONFIG_PKG_USING_SFDB is not set
# CONFIG_PKG_USING_RTP is not set
# CONFIG_PKG_USING_REB is not set
# CONFIG_PKG_USING_RMP is not set
# CONFIG_PKG_USING_R_RHEALSTONE is not set
# CONFIG_PKG_USING_HEARTBEAT is not set
# end of system packages
@ -946,12 +950,44 @@ CONFIG_RT_USING_VDSO=y
#
# STM32 HAL & SDK Drivers
#
# CONFIG_PKG_USING_STM32F0_HAL_DRIVER is not set
# CONFIG_PKG_USING_STM32F0_CMSIS_DRIVER is not set
# CONFIG_PKG_USING_STM32F1_HAL_DRIVER is not set
# CONFIG_PKG_USING_STM32F1_CMSIS_DRIVER is not set
# CONFIG_PKG_USING_STM32F2_HAL_DRIVER is not set
# CONFIG_PKG_USING_STM32F2_CMSIS_DRIVER is not set
# CONFIG_PKG_USING_STM32F3_HAL_DRIVER is not set
# CONFIG_PKG_USING_STM32F3_CMSIS_DRIVER is not set
# CONFIG_PKG_USING_STM32F4_HAL_DRIVER is not set
# CONFIG_PKG_USING_STM32F4_CMSIS_DRIVER is not set
# CONFIG_PKG_USING_STM32F7_HAL_DRIVER is not set
# CONFIG_PKG_USING_STM32F7_CMSIS_DRIVER is not set
# CONFIG_PKG_USING_STM32G0_HAL_DRIVER is not set
# CONFIG_PKG_USING_STM32G0_CMSIS_DRIVER is not set
# CONFIG_PKG_USING_STM32G4_HAL_DRIVER is not set
# CONFIG_PKG_USING_STM32G4_CMSIS_DRIVER is not set
# CONFIG_PKG_USING_STM32H5_HAL_DRIVER is not set
# CONFIG_PKG_USING_STM32H5_CMSIS_DRIVER is not set
# CONFIG_PKG_USING_STM32H7_HAL_DRIVER is not set
# CONFIG_PKG_USING_STM32H7_CMSIS_DRIVER is not set
# CONFIG_PKG_USING_STM32H7RS_HAL_DRIVER is not set
# CONFIG_PKG_USING_STM32H7RS_CMSIS_DRIVER is not set
# CONFIG_PKG_USING_STM32L0_HAL_DRIVER is not set
# CONFIG_PKG_USING_STM32L0_CMSIS_DRIVER is not set
# CONFIG_PKG_USING_STM32L4_HAL_DRIVER is not set
# CONFIG_PKG_USING_STM32L4_CMSIS_DRIVER is not set
# CONFIG_PKG_USING_STM32L5_HAL_DRIVER is not set
# CONFIG_PKG_USING_STM32L5_CMSIS_DRIVER is not set
# CONFIG_PKG_USING_STM32U5_HAL_DRIVER is not set
# CONFIG_PKG_USING_STM32U5_CMSIS_DRIVER is not set
# CONFIG_PKG_USING_STM32WB55_SDK is not set
# CONFIG_PKG_USING_STM32_SDIO is not set
# CONFIG_PKG_USING_STM32WL_HAL_DRIVER is not set
# CONFIG_PKG_USING_STM32WL_CMSIS_DRIVER is not set
# CONFIG_PKG_USING_STM32WB_HAL_DRIVER is not set
# CONFIG_PKG_USING_STM32WB_CMSIS_DRIVER is not set
# CONFIG_PKG_USING_STM32MP1_M4_HAL_DRIVER is not set
# CONFIG_PKG_USING_STM32MP1_M4_CMSIS_DRIVER is not set
# end of STM32 HAL & SDK Drivers
#
@ -984,6 +1020,60 @@ CONFIG_RT_USING_VDSO=y
# CONFIG_PKG_USING_NRFX is not set
# CONFIG_PKG_USING_NUCLEI_SDK is not set
# CONFIG_PKG_USING_RASPBERRYPI_PICO_SDK is not set
# CONFIG_PKG_USING_MM32 is not set
#
# WCH HAL & SDK Drivers
#
# CONFIG_PKG_USING_CH32V20x_SDK is not set
# CONFIG_PKG_USING_CH32V307_SDK is not set
# end of WCH HAL & SDK Drivers
#
# AT32 HAL & SDK Drivers
#
# CONFIG_PKG_USING_AT32A403A_HAL_DRIVER is not set
# CONFIG_PKG_USING_AT32A403A_CMSIS_DRIVER is not set
# CONFIG_PKG_USING_AT32A423_HAL_DRIVER is not set
# CONFIG_PKG_USING_AT32A423_CMSIS_DRIVER is not set
# CONFIG_PKG_USING_AT32F45x_HAL_DRIVER is not set
# CONFIG_PKG_USING_AT32F45x_CMSIS_DRIVER is not set
# CONFIG_PKG_USING_AT32F402_405_HAL_DRIVER is not set
# CONFIG_PKG_USING_AT32F402_405_CMSIS_DRIVER is not set
# CONFIG_PKG_USING_AT32F403A_407_HAL_DRIVER is not set
# CONFIG_PKG_USING_AT32F403A_407_CMSIS_DRIVER is not set
# CONFIG_PKG_USING_AT32F413_HAL_DRIVER is not set
# CONFIG_PKG_USING_AT32F413_CMSIS_DRIVER is not set
# CONFIG_PKG_USING_AT32F415_HAL_DRIVER is not set
# CONFIG_PKG_USING_AT32F415_CMSIS_DRIVER is not set
# CONFIG_PKG_USING_AT32F421_HAL_DRIVER is not set
# CONFIG_PKG_USING_AT32F421_CMSIS_DRIVER is not set
# CONFIG_PKG_USING_AT32F423_HAL_DRIVER is not set
# CONFIG_PKG_USING_AT32F423_CMSIS_DRIVER is not set
# CONFIG_PKG_USING_AT32F425_HAL_DRIVER is not set
# CONFIG_PKG_USING_AT32F425_CMSIS_DRIVER is not set
# CONFIG_PKG_USING_AT32F435_437_HAL_DRIVER is not set
# CONFIG_PKG_USING_AT32F435_437_CMSIS_DRIVER is not set
# CONFIG_PKG_USING_AT32M412_416_HAL_DRIVER is not set
# CONFIG_PKG_USING_AT32M412_416_CMSIS_DRIVER is not set
# end of AT32 HAL & SDK Drivers
#
# HC32 DDL Drivers
#
# end of HC32 DDL Drivers
#
# NXP HAL & SDK Drivers
#
# CONFIG_PKG_USING_NXP_MCX_CMSIS_DRIVER is not set
# CONFIG_PKG_USING_NXP_MCX_SERIES_DRIVER is not set
# CONFIG_PKG_USING_NXP_LPC_DRIVER is not set
# CONFIG_PKG_USING_NXP_LPC55S_DRIVER is not set
# CONFIG_PKG_USING_NXP_IMX6SX_DRIVER is not set
# CONFIG_PKG_USING_NXP_IMX6UL_DRIVER is not set
# CONFIG_PKG_USING_NXP_IMXRT_DRIVER is not set
# end of NXP HAL & SDK Drivers
# end of HAL & SDK Drivers
#
@ -1021,12 +1111,14 @@ CONFIG_RT_USING_VDSO=y
# CONFIG_PKG_USING_BMI088 is not set
# CONFIG_PKG_USING_HMC5883 is not set
# CONFIG_PKG_USING_MAX6675 is not set
# CONFIG_PKG_USING_MAX31855 is not set
# CONFIG_PKG_USING_TMP1075 is not set
# CONFIG_PKG_USING_SR04 is not set
# CONFIG_PKG_USING_CCS811 is not set
# CONFIG_PKG_USING_PMSXX is not set
# CONFIG_PKG_USING_RT3020 is not set
# CONFIG_PKG_USING_MLX90632 is not set
# CONFIG_PKG_USING_MLX90382 is not set
# CONFIG_PKG_USING_MLX90393 is not set
# CONFIG_PKG_USING_MLX90392 is not set
# CONFIG_PKG_USING_MLX90394 is not set
@ -1055,6 +1147,8 @@ CONFIG_RT_USING_VDSO=y
# CONFIG_PKG_USING_ICM20608 is not set
# CONFIG_PKG_USING_PAJ7620 is not set
# CONFIG_PKG_USING_STHS34PF80 is not set
# CONFIG_PKG_USING_P3T1755 is not set
# CONFIG_PKG_USING_QMI8658 is not set
# end of sensors drivers
#
@ -1146,6 +1240,9 @@ CONFIG_RT_USING_VDSO=y
# CONFIG_PKG_USING_BT_MX02 is not set
# CONFIG_PKG_USING_GC9A01 is not set
# CONFIG_PKG_USING_IK485 is not set
# CONFIG_PKG_USING_SERVO is not set
# CONFIG_PKG_USING_SEAN_WS2812B is not set
# CONFIG_PKG_USING_IC74HC165 is not set
# CONFIG_PKG_USING_SPI_TOOLS is not set
# end of peripheral libraries and drivers
@ -1162,6 +1259,7 @@ CONFIG_RT_USING_VDSO=y
# CONFIG_PKG_USING_QUEST is not set
# CONFIG_PKG_USING_NAXOS is not set
# CONFIG_PKG_USING_R_TINYMAIX is not set
# CONFIG_PKG_USING_LLMCHAT is not set
# end of AI packages
#
@ -1238,6 +1336,7 @@ CONFIG_PKG_ZLIB_VER="latest"
# CONFIG_PKG_USING_KI is not set
# CONFIG_PKG_USING_ARMv7M_DWT is not set
# CONFIG_PKG_USING_CRCLIB is not set
# CONFIG_PKG_USING_LIBCRC is not set
# CONFIG_PKG_USING_LWGPS is not set
# CONFIG_PKG_USING_STATE_MACHINE is not set
# CONFIG_PKG_USING_DESIGN_PATTERN is not set
@ -1248,6 +1347,7 @@ CONFIG_PKG_ZLIB_VER="latest"
# CONFIG_PKG_USING_SOEM is not set
# CONFIG_PKG_USING_QPARAM is not set
# CONFIG_PKG_USING_CorevMCU_CLI is not set
# CONFIG_PKG_USING_DRMP is not set
# end of miscellaneous packages
#
@ -1491,6 +1591,7 @@ CONFIG_PKG_ZLIB_VER="latest"
# Drivers Configuration
#
# CONFIG_BSP_USING_ADC is not set
# CONFIG_BSP_USING_PWM is not set
CONFIG_BSP_USING_HARDLOCK=y
CONFIG_BSP_USING_SDIO=y
CONFIG_BSP_USING_SDIO0=y
@ -1503,7 +1604,9 @@ CONFIG_BSP_SD_MNT_DEVNAME="sd0p1"
# CONFIG_BSP_UTEST_DRIVERS is not set
# end of Drivers Configuration
CONFIG_BOARD_fpgac908=y
CONFIG_BOARD_C908=y
CONFIG___STACKSIZE__=65536
CONFIG_BSP_ROOTFS_TYPE_ELMFAT=y
# CONFIG_BSP_ROOTFS_TYPE_CROMFS is not set
# CONFIG_BSP_RISCV_FPU_SOFT is not set
CONFIG_BSP_RISCV_FPU_D=y

View File

@ -5,6 +5,22 @@ menu "Drivers Configuration"
select RT_USING_ADC
default n
menuconfig BSP_USING_PWM
bool "Enable PWM"
select RT_USING_PWM
default n
if BSP_USING_PWM
config BSP_USING_PWM0
bool "Enable PWM0"
default n
config BSP_USING_PWM1
bool "Enable PWM1"
default n
endif
config BSP_USING_HARDLOCK
bool "Enable Hard-Lock"
default y

View File

@ -0,0 +1,11 @@
# RT-Thread building script for component
from building import *
cwd = GetCurrentDir()
src = Glob('*.c')
CPPPATH = [cwd]
group = DefineGroup('PWM', src, depend = ['BSP_USING_PWM'], CPPPATH = CPPPATH)
Return('group')

View File

@ -0,0 +1,243 @@
/* Copyright (c) 2023, Canaan Bright Sight Co., Ltd
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
* CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/*
* Copyright (c) 2006-2025 RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <rtthread.h>
#include <rtdevice.h>
#include "riscv_io.h"
#include "board.h"
#include "ioremap.h"
#include <rtdbg.h>
#include <stdbool.h>
#include "sysctl_clk.h"
#include "drv_pwm.h"
#include <sys/ioctl.h>
/**
*
* pwm0
* channel 0
* channel 1
* channel 2
* pwm1
* channel 0
* channel 1
* channel 2
*
* Note:
* The K230 PWM controller has 4 hardware channels:
* - Channel 0 (pwmcmp0) is used to set the period and does not generate output.
* - Channels 1 to 3 (pwmcmp1~3) are used to control the duty cycle and produce output signals.
* Therefore, the driver maps these output channels (1~3) as logical channels 0~2.
*/
#define PWM_REG_OFFSET 0x40
#define PWM_CFG_BIT_INVERT (1 << 12)
#define PWM_CFG_DEGLITCH (1 << 9)
#define PWM_MAX_SCALE 0xF
#define PWM_CMP_WIDTH 16
#define PWM_PERIOD_BITS 16
#define PWM_SCALE_MAX_BITS 15
#define PWM_DEV_NUM 2
#define PWM_MAX_CHANNELS 3
#define PWM0_BASE_ADDR PWM_BASE_ADDR
#define PWM1_BASE_ADDR PWM_BASE_ADDR + PWM_REG_OFFSET
struct k230_pwm_dev
{
struct rt_device_pwm device;
const char *name;
rt_ubase_t base;
};
static struct k230_pwm_dev pwm_devs[] = {
#ifdef BSP_USING_PWM0
{
.name = "pwm0",
.base = PWM0_BASE_ADDR,
},
#endif
#ifdef BSP_USING_PWM1
{
.name = "pwm1",
.base = PWM1_BASE_ADDR,
},
#endif
#if !defined(BSP_USING_PWM0) && !defined(BSP_USING_PWM1)
#error "No pwm device defined!"
#endif
};
static int check_channel(int channel)
{
if (channel < 0 || channel >= PWM_MAX_CHANNELS)
{
LOG_E("channel %d is not valid\n", channel);
return -RT_ERROR;
}
return channel;
}
static rt_err_t pwm_start(kd_pwm_t *reg, int channel)
{
rt_err_t ret;
ret = (rt_err_t)check_channel(channel);
if (ret < 0)
return ret;
reg->pwmcfg |= PWM_CFG_BIT_INVERT; /* default always mode */
return RT_EOK;
}
static rt_err_t pwm_stop(kd_pwm_t *reg, int channel)
{
rt_err_t ret;
ret = (rt_err_t)check_channel(channel);
if (ret < 0)
return ret;
reg->pwmcfg &= ~PWM_CFG_BIT_INVERT;
return RT_EOK;
}
static rt_err_t kd_pwm_get(kd_pwm_t *reg, int channel, struct rt_pwm_configuration *configuration)
{
int ret;
uint64_t pulse, period;
uint32_t pwm_pclock, pwmscale;
ret = check_channel(channel);
if (ret < 0)
return ret;
pwm_pclock = sysctl_clk_get_leaf_freq(SYSCTL_CLK_PWM_APB_GATE);
pwmscale = reg->pwmcfg & 0xf;
pwm_pclock >>= pwmscale;
period = reg->pwmcmp0;
period = period * NSEC_PER_SEC / pwm_pclock;
pulse = *((&reg->pwmcmp1) + channel);
pulse = pulse * NSEC_PER_SEC / pwm_pclock;
configuration->period = period;
configuration->pulse = pulse;
return RT_EOK;
}
static rt_err_t kd_pwm_set(kd_pwm_t *reg, int channel, struct rt_pwm_configuration *configuration)
{
int ret;
uint64_t pulse, period, pwmcmpx_max;
uint32_t pwm_pclock, pwmscale = 0;
ret = check_channel(channel);
if (ret < 0)
return ret;
pwm_pclock = sysctl_clk_get_leaf_freq(SYSCTL_CLK_PWM_APB_GATE);
pulse = (uint64_t)configuration->pulse * pwm_pclock / NSEC_PER_SEC;
period = (uint64_t)configuration->period * pwm_pclock / NSEC_PER_SEC;
if (pulse > period)
return -RT_EINVAL;
/* Calculate duty cycle */
pwmcmpx_max = (1 << PWM_CMP_WIDTH) - 1;
if (period > ((1 << (PWM_SCALE_MAX_BITS + PWM_PERIOD_BITS)) - 1LL))
return -RT_EINVAL;
while ((period >> pwmscale) > pwmcmpx_max)
pwmscale++;
if (pwmscale > PWM_MAX_SCALE)
return -RT_EINVAL;
reg->pwmcfg |= PWM_CFG_DEGLITCH; /* default always mode */
reg->pwmcfg &= (~PWM_MAX_SCALE);
reg->pwmcfg |= pwmscale; /* scale */
reg->pwmcmp0 = (period >> pwmscale);
*((&reg->pwmcmp1) + channel) = reg->pwmcmp0 - (pulse >> pwmscale);
return RT_EOK;
}
static rt_err_t kd_pwm_control(struct rt_device_pwm *device, int cmd, void *arg)
{
struct rt_pwm_configuration *configuration = (struct rt_pwm_configuration *)arg;
int channel = 0;
int ret;
struct k230_pwm_dev *pwm_dev = rt_container_of(device, struct k230_pwm_dev, device);
kd_pwm_t *reg = (kd_pwm_t *)pwm_dev->base;
channel = configuration->channel;
switch (cmd)
{
case PWM_CMD_ENABLE:
ret = pwm_start(reg, channel);
break;
case PWM_CMD_DISABLE:
ret = pwm_stop(reg, channel);
break;
case PWM_CMD_SET:
ret = kd_pwm_set(reg, channel, configuration);
break;
case PWM_CMD_GET:
ret = kd_pwm_get(reg, channel, configuration);
break;
default:
ret = -RT_EINVAL;
}
return ret;
}
static struct rt_pwm_ops drv_ops =
{
.control = kd_pwm_control
};
int rt_hw_pwm_init(void)
{
rt_err_t ret;
for (int i = 0; i < sizeof(pwm_devs)/sizeof(struct k230_pwm_dev); i++)
{
struct k230_pwm_dev *dev = &pwm_devs[i];
dev->base = (rt_ubase_t)rt_ioremap((void *)(dev->base), sizeof(kd_pwm_t));
ret = rt_device_pwm_register(&dev->device, dev->name, &drv_ops, RT_NULL);
if (ret != RT_EOK)
{
LOG_E("Failed to register PWM device %s, error code: %d\n", dev->name, ret);
return ret;
}
}
return RT_EOK;
}
INIT_DEVICE_EXPORT(rt_hw_pwm_init);

View File

@ -0,0 +1,88 @@
/* Copyright (c) 2023, Canaan Bright Sight Co., Ltd
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
* CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/*
* Copyright (c) 2006-2025 RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*/
#ifndef DRV_PWM_H__
#define DRV_PWM_H__
#include <stdint.h>
#define NSEC_PER_SEC 1000000000L
typedef struct
{
volatile uint32_t pwmcfg; /* 0x00 */
volatile uint32_t reserved0;
volatile uint32_t pwmcount; /* 0x08 */
volatile uint32_t reserved1;
volatile uint32_t pwms; /* 0x10 */
volatile uint32_t reserved2;
volatile uint32_t reserved3;
volatile uint32_t reserved4;
volatile uint32_t pwmcmp0; /* 0x20 */
volatile uint32_t pwmcmp1; /* 0x24 */
volatile uint32_t pwmcmp2; /* 0x28 */
volatile uint32_t pwmcmp3; /* 0x2c */
} kd_pwm_t;
typedef struct
{
uint32_t scale : 4;
uint32_t reserve: 4;
uint32_t sticky : 1;
uint32_t zerocmp : 1;
uint32_t deglitch : 1;
uint32_t reserve1 : 1;
uint32_t enalways : 1;
uint32_t enoneshot : 1;
uint32_t reserve2 : 2;
uint32_t cmp0center : 1;
uint32_t cmp1center : 1;
uint32_t cmp2center : 1;
uint32_t cmp3center : 1;
uint32_t reserve3 : 4;
uint32_t cmp0gang : 1;
uint32_t cmp1gang : 1;
uint32_t cmp2gang : 1;
uint32_t cmp3gang : 1;
uint32_t cmp0ip : 1;
uint32_t cmp1ip : 1;
uint32_t cmp2ip : 1;
uint32_t cmp3ip : 1;
} pwm_cfg_t;
typedef struct
{
pwm_cfg_t cfg;
uint32_t freq;
uint32_t cmp0_val;
double cmp1_duty;
double cmp2_duty;
double cmp3_duty;
} pwm_param_t;
#endif

View File

@ -15,6 +15,9 @@ if GetDepend('RT_UTEST_USING_ALL_CASES') or GetDepend('BSP_UTEST_DRIVERS'):
if GetDepend('BSP_USING_WDT'):
src += ['test_wdt.c']
if GetDepend('BSP_USING_PWM'):
src += ['test_pwm.c']
group = DefineGroup('utestcases', src, depend = [''])
Return('group')
Return('group')

View File

@ -0,0 +1,120 @@
/* Copyright (c) 2023, Canaan Bright Sight Co., Ltd
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
* CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/*
* Copyright (c) 2006-2025 RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <unistd.h>
#include <stdio.h>
#include <drivers/dev_pwm.h>
#include "drv_pwm.h"
#include "drv_pinctrl.h"
#include <rtdbg.h>
#include "utest.h"
/*
* PWM LED
*
* 1. "pwm" PWM
* 2. 使 pinctrl GPIO52 PWM4
* - 使OE
* - IE
* - PU/PD
* - 4
* 3. PWM 100000ns 10kHz
* 4. PWM pulse LED
* - 10% 10000ns
* - 10% 100%
* - 2 便 LED
* 5. PWM LED
*
*
* - K230-01studio
* - GPIO52 LED
* - PWM4 LED
* - LED
*
*/
#define PWM_DEV_NAME "pwm1" /* PWM设备名称 */
#define PWM_DEV_CHANNEL 1 /* PWM通道 */
#define TEST_GPIO_LED 52
void pwm_demo(void)
{
LOG_I("set gpio52 in PWM1 start.\n");
k230_pinctrl_set_function(TEST_GPIO_LED, IOMUX_FUNC3);
/* 使能输出 */
k230_pinctrl_set_oe(TEST_GPIO_LED, 1);
/* 禁止输入 */
k230_pinctrl_set_ie(TEST_GPIO_LED, 0);
/* 禁止上拉 */
k230_pinctrl_set_pu(TEST_GPIO_LED, 0);
/* 禁止下拉 */
k230_pinctrl_set_pd(TEST_GPIO_LED, 0);
/* 设置驱动能力为4中等强度 */
k230_pinctrl_set_drv(TEST_GPIO_LED, 4);
LOG_I("pwm test start.\n");
struct rt_device_pwm *pwm_dev; /* PWM设备句柄 */
rt_uint32_t period; /* 周期, 单位为纳秒ns */
rt_uint32_t pulse; /* PWM脉冲宽度值, 单位为纳秒ns */
rt_err_t ret;
/* 查找设备 */
pwm_dev = (struct rt_device_pwm *)rt_device_find(PWM_DEV_NAME);
uassert_not_null(pwm_dev);
/* 设置PWM周期和脉冲宽度 */
period = 100000; /* PWM 周期100000ns = 100us即 10kHz */
/* 逐步循环提高PWM脉冲宽度 */
for(pulse = 10000; pulse <= 100000; pulse+=10000)
{
ret = rt_pwm_set(pwm_dev, PWM_DEV_CHANNEL, period, pulse);
uassert_int_equal(ret, RT_EOK);
ret = rt_pwm_enable(pwm_dev, PWM_DEV_CHANNEL);
uassert_int_equal(ret, RT_EOK);
sleep(2);
}
ret = rt_pwm_disable(pwm_dev, PWM_DEV_CHANNEL);
uassert_int_equal(ret, RT_EOK);
}
static void pwm_testcase(void)
{
UTEST_UNIT_RUN(pwm_demo);
}
static rt_err_t utest_tc_init(void)
{
return RT_EOK;
}
static rt_err_t utest_tc_cleanup(void)
{
return RT_EOK;
}
UTEST_TC_EXPORT(pwm_testcase, "pwm", utest_tc_init, utest_tc_cleanup, 10);

View File

@ -130,6 +130,8 @@
#define KERNEL_VADDR_START 0xffffffc000000000
#define ARCH_RISCV
#define ARCH_RISCV_FPU
#define ARCH_RISCV_VECTOR
#define ARCH_VECTOR_VLEN_128
#define ARCH_RISCV_FPU_D
#define ARCH_RISCV64
#define ARCH_USING_NEW_CTX_SWITCH
@ -476,6 +478,22 @@
/* Kendryte SDK */
/* end of Kendryte SDK */
/* WCH HAL & SDK Drivers */
/* end of WCH HAL & SDK Drivers */
/* AT32 HAL & SDK Drivers */
/* end of AT32 HAL & SDK Drivers */
/* HC32 DDL Drivers */
/* end of HC32 DDL Drivers */
/* NXP HAL & SDK Drivers */
/* end of NXP HAL & SDK Drivers */
/* end of HAL & SDK Drivers */
/* sensors drivers */
@ -565,8 +583,9 @@
#define BSP_USING_SDIO0
#define BSP_SD_MNT_DEVNAME "sd0p1"
/* end of Drivers Configuration */
#define BOARD_fpgac908
#define BOARD_C908
#define __STACKSIZE__ 65536
#define BSP_ROOTFS_TYPE_ELMFAT
#define BSP_RISCV_FPU_D
#endif