Ver código fonte

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>
dannyray019 1 mês atrás
pai
commit
c209173061

+ 106 - 3
bsp/k230/.config

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

+ 16 - 0
bsp/k230/board/Kconfig

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

+ 11 - 0
bsp/k230/drivers/interdrv/pwm/SConscript

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

+ 243 - 0
bsp/k230/drivers/interdrv/pwm/drv_pwm.c

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

+ 88 - 0
bsp/k230/drivers/interdrv/pwm/drv_pwm.h

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

+ 4 - 1
bsp/k230/drivers/utest/SConscript

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

+ 120 - 0
bsp/k230/drivers/utest/test_pwm.c

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

+ 20 - 1
bsp/k230/rtconfig.h

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