bsp: k230: add support for PWM driver#10536
bsp: k230: add support for PWM driver#10536DannyRay019 wants to merge 1 commit intoRT-Thread:masterfrom
Conversation
📌 Code Review Assignment🏷️ Tag: bsp_k230Reviewers: unicornx Changed Files (Click to expand)
📊 Current Review Status (Last Updated: 2025-07-27 01:32 CST)
📝 Review Instructions
|
There was a problem hiding this comment.
你这里 .config 的变化有点多啊。我基于 d23006e, 应该也是你提的 pr 所基于的 master 吧,执行一下命令:
cd bsp/k230
scons -c
scons --menuconfig # 什么也不做,只是保存后退出得到的 .config 和原先的 .config 的 diff 见附件:
diff_config.txt
你是不是把你本地的一些配置修改全部提交上来了?请清理一下。原则上应该只有我这里看到的这些 diff(这主要是 master 升级后其它 kconfig 修改导致的 default 值的变化)加上你这次 pwm 相关的配置变化才对。
bsp/k230/board/Kconfig
Outdated
| select RT_USING_ADC | ||
| default n | ||
|
|
||
| config BSP_USING_PWM |
|
|
||
| static struct rt_pwm_ops drv_ops = | ||
| { | ||
| .control=kd_pwm_control |
There was a problem hiding this comment.
等号两边加空格隔开。原则是 c 编码时关键字要用空格凸显出来。
| #include "drv_pwm.h" | ||
| #include <sys/ioctl.h> | ||
| static struct rt_device_pwm kd_pwm; | ||
| kd_pwm_t *reg_pwm; |
| #include "sysctl_clk.h" | ||
| #include "drv_pwm.h" | ||
| #include <sys/ioctl.h> | ||
| static struct rt_device_pwm kd_pwm; |
There was a problem hiding this comment.
k230 有两个 pwm,但这里为什么只实现了一个?
可以参考 bsp/cvitek/drivers/drv_pwm.c 的实现做。
|
|
||
| static int check_channel(int channel) | ||
| { | ||
| if (channel < 0 || channel > 5) |
There was a problem hiding this comment.
6 个通道的概念都是错误的,canaan 原来的代码做出来的效果是一个 PWM 上带 6 个 channel。但是我们要做的效果是 两个 PWM,每个 3 个通道。
canaan 的说法也说明了这个问题。
他们也说了他们linux 的驱动也是按照两个 PWM 设备写的:

TRM 上也有相关描述,现在来看 TRM 上的描述只是针对一个 PWM 设备。

所以我觉得可以这么做:
我们严格按照 TRM 上的做,两个 PWM,每个 4 个通道。

寄存器上体现的也是有 4 个,但是我理解是说 0 号 channel 没有用。可用的是 1/2/3,按照 canaan 的说法:

第一个 PWM0 的基地址是 0x9140_A000, 第二个 PWM1 的基地址是 0x9140_A000 + 0x40
每个 PWM 都对应一组寄存器组:

对于第一个通道我们做成 unavailable,如果api 传入 channelno为 0 就返回错误。
你需要签一下 CLA |
bsp/k230/.config
Outdated
| # CONFIG_RT_USING_PHY is not set | ||
| # CONFIG_RT_USING_PHY_V2 is not set | ||
| # CONFIG_RT_USING_ADC is not set | ||
| CONFIG_RT_USING_ADC=y |
bsp/k230/.config
Outdated
| CONFIG_RT_USING_ZERO=y | ||
| CONFIG_RT_USING_RANDOM=y | ||
| # CONFIG_RT_USING_PWM is not set | ||
| CONFIG_RT_USING_PWM=y |
There was a problem hiding this comment.
我感觉你这次提交上来的 .config 文件好像还是多了很多。
附件是我 checkout 到 master 后运行 scons --menuconfig,不做修改直接保存退出后的 .config 和 rtconfig.h, 你对比一下。你那边做出来的应该只会比附件多一些 bsp 的 pwm 的东西,而且 CONFIG_RT_USING_PWM 默认也是 disable 的。
config.txt
rtconfig.h.txt
文件名稍微改了一下,因为 github 贴附件对文件名有限制。
| bool "Enable PWM" | ||
| select RT_USING_PWM | ||
| default n | ||
|
|
There was a problem hiding this comment.
你好像没有理解我说的配置里面做两个 PWM 的意思,摘录 bsp/k230/board/Kconfig 里 watchdog 的写法你再参考一下,参考改成 PWM 的样子。因为我们有两个 PWM 设备,允许用户通过配置开一个或者关一个。默认可以都关掉。做的好一点可以根据我们支持的 01studio 的板子的支持情况,譬如板子有默认开哪个就开哪个。这个目前我们做得比较粗糙后面可以改进。但至少要支持多个 PWM 的可配置。
menuconfig BSP_USING_WDT
bool "Enable Watchdog Timer"
select RT_USING_WDT
default n
if BSP_USING_WDT
config BSP_USING_WDT0
bool "Enable WDT0"
default n
config BSP_USING_WDT1
bool "Enable WDT1"
default n
endif
| } pwm_param_t; | ||
|
|
||
| #endif | ||
|
|
| int rt_hw_pwm_init(void) | ||
| { | ||
| kd_pwm_t *reg_pwm0,*reg_pwm1; | ||
| static struct rt_device_pwm kd_pwm0; |
There was a problem hiding this comment.
建议将 pwm 设备封装一下,参考 bsp/k230/drivers/interdrv/wdt/drv_wdt.c 中的 struct k230_wdt_dev 的写法.
另外如果 Kcofnig 支持了配置,原则上初始化时也应该通过配置的宏来决定我们到底要注册几个设备。配置没有 enable 的设备不注册的。这个我看了一下 watchdog 的驱动做的不好,以后是一个改进点。
比较好的参考可以看 bsp/k230/drivers/interdrv/sdio/drv_sdhci.c 的 kd_sdhci_init
| #define PWM_SCALE_MAX_BITS 15 | ||
|
|
||
| #define PWM0_BASE_ADDR 0x9140A000 | ||
| #define PWM1_BASE_ADDR 0x9140A040 |
There was a problem hiding this comment.
用 bsp/k230/board/board.h 里定义的 PWM_BASE_ADDR 来定义你的宏,不要重复写立即数。
|
|
||
| pwmscale = reg->pwmcfg & 0xf; | ||
| pwm_pclock >>= pwmscale; | ||
| period = reg->pwmcmp0; |
There was a problem hiding this comment.
这里使用 pwmcmp0 是什么意思?第 0 号 channel 不是我们不用的么,是 canaan 说的作为基准的意思?
There was a problem hiding this comment.
cannan那边说的是有0,1,2,3,四个通道,但是第0个通道用不了,只能用1,2,3通道。但是第1,2,3通道在驱动里面的的channel值分别是0,1,2。不知道那个禁用的第0个通道在驱动中代表的数值是几,这个我再向cannan问清楚吧
| #define PWM_DEV_NAME "pwm1" /* PWM设备名称 */ | ||
| #define PWM_DEV_CHANNEL 1 /* PWM通道 */ | ||
| #define TEST_GPIO_LED 52 | ||
|
|
bsp/k230/drivers/utest/test_pwm.c
Outdated
| */ | ||
|
|
||
| #define PWM_DEV_NAME "pwm1" /* PWM设备名称 */ | ||
| #define PWM_DEV_CHANNEL 1 /* PWM通道 */ |
bsp/k230/drivers/utest/test_pwm.c
Outdated
| } | ||
|
|
||
| UTEST_TC_EXPORT(pwm_testcase, "pwm", utest_tc_init, utest_tc_cleanup, 10); | ||
|
|
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>
|
关于.config和rtconfig.h文件多余的部分,我看了一下,都是些被注释了的选项,本身也没有选这些配置,我就手动删掉了大部分,关掉了utest,pwm等一些配置,不知道现在是否符合要求了。其他的都按照您的建议来修改了。 |
unicornx
left a comment
There was a problem hiding this comment.
第三次 review 后的评审意见如下。
此外,我建议你每次正式提交 PR 前用 format 工具规整以下你代码(这个要求以前提过)。因为我发现你的代码中存在很多格式问题,包括行尾空格。你用 git show 在命令行下应该会看到行尾多余空格的红色提醒。
另外你的 commit 的 title 的格式也有问题,你用 git log --oneline 会看到你的 title 比其他正常的缩进了一些。可能和你编辑 commit 的文本时的误操作有关。请改正。
| #define KD_PWM_CMD_ENABLE _IOW('P', 0, int) | ||
| #define KD_PWM_CMD_DISABLE _IOW('P', 1, int) | ||
| #define KD_PWM_CMD_SET _IOW('P', 2, int) | ||
| #define KD_PWM_CMD_GET _IOW('P', 3, int) |
| * - channel 0(pwmcmp0)用于设置周期,不对应输出; | ||
| * - channel 1~3(pwmcmp1~3)用于控制占空比,是实际的输出通道。 | ||
| * 因此,驱动中将这三个通道映射为 channel 0~2。 | ||
| */ |
There was a problem hiding this comment.
- 这两段注释请合并为一段
- 第二段注释前面的 * 没有对齐
- 第二段注释请用英文。原则上代码的注释都是英文。唯一的例外是 k230 的 utest case 中的注释没有用英文,这个先暂时保留,以后再考虑统一改掉。
| #define PWM_MAX_CHANNELS 3 | ||
|
|
||
| #define PWM0_BASE_ADDR PWM_BASE_ADDR | ||
| #define PWM1_BASE_ADDR PWM_BASE_ADDR+PWM_REG_OFFSET |
There was a problem hiding this comment.
“+” 作为关键字两边用空格隔开,不要挤在一起看不清。
| { | ||
| .name = "pwm0", | ||
| .base = PWM0_BASE_ADDR, | ||
| .size = PWM_IO_SIZE, |
There was a problem hiding this comment.
这是 size 设置有问题。PWM_IO_SIZE (0x1000)是整个 PWM 地址空间的范围,但注意这个范围中包含了两个 PWM 设备。如果全部按照这个范围去映射,则对 pmw0 的映射覆盖了 pwm1 的范围,而对 pwm1 的映射则超出了 PWM 地址空间的下边界。
正确做法是根据每个 PWM 设备实际的寄存器范围进行映射。即 sizeof(kd_pwm_t)。而且这对于 PWM0 和 PWM1 来说是一个不变的常量,不需要作为配置体现,在 init 时 ioremap 时直接赋值即可。
|
|
||
| struct k230_pwm_dev | ||
| { | ||
| struct rt_device_pwm* device; |
There was a problem hiding this comment.
没必要定义成指针,你参考 struct k230_wdt_dev 的定义。这样也就不要额外再定义 kd_pwm0/kd_pwm1 这些东西了。
| rt_uint32_t channel = 0; | ||
| int ret; | ||
|
|
||
| kd_pwm_t *reg = (kd_pwm_t *)(device->parent.user_data); |
There was a problem hiding this comment.
不需要这么获取 kd_pwm_t, 具体参考 bsp/k230/drivers/interdrv/wdt/drv_wdt.c 中的写法。
我整体看了一下,我理解你的做法也可以,但不是最好的做法,因为本质上我们不推荐直接访问 rt_device_pwm 的内部成员,即 device->parent.user_data 这种,其实如果只是需要获取寄存器地址的话,更好的写法你再读一下 bsp/k230/drivers/interdrv/wdt/drv_wdt.c 中的写法,具体思路是:
- 定义
rt_watchdog_device的子类k230_wdt_dev(rt_watchdog_device定义为第一个成员,表示基类),定义成员 base,以及其他属性不表 - 定义全局变量
wdt_devices,将 base 成员赋值为物理地址,其他属性赋值不表 rt_hw_wdt_init中将 base 重新映射为虚拟地址(映射虚拟地址是 RT-Smart 的需求, k230 目前只考虑支持 smart)。rt_hw_watchdog_register注册,data 部分如果没有特殊用途,可以直接 NULL- 内核回调函数里,譬如
k230_wdt_init,通过rt_container_of方式从rt_watchdog_device得到k230_wdt_dev,在我们的驱动中只需看到k230_wdt_dev已经足够。
| .base = PWM1_BASE_ADDR, | ||
| .size = PWM_IO_SIZE, | ||
| } | ||
| #endif |
There was a problem hiding this comment.
如果用户选择使能 PWM 但没有 enable 任何一个 PWM 设备,我们应该报错,可以在编译阶段就报错,具体做法参考 bsp/k230/drivers/interdrv/wdt/drv_wdt.c 中定义 wdt_devices 的做法。
There was a problem hiding this comment.
好的,我参考一下,这个是一个bug
| dev0->regs = (kd_pwm_t *)rt_ioremap((void *)(dev0->base), dev0->size); | ||
| dev0->device = &kd_pwm0; | ||
| dev0->device->ops = &drv_ops; | ||
| rt_device_pwm_register(dev0->device, dev0->name, &drv_ops, (void*)dev0->regs); |
| * | ||
| */ | ||
|
|
||
| #define PWM_DEV_NAME "pwm1" /* PWM设备名称 */ |
There was a problem hiding this comment.
pwm0 还有机会测试一下?不用写在测试用例里,只是内部测试一下即可。
| 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 |
There was a problem hiding this comment.
你说的 ”我就手动删掉了大部分“ 这种做法不是合法的做法。我建议你参考以下操作步骤:
- 假设你的开发分支(pr 的分支)是基于 master 的 commit 为 A 拉出来做的。
- checkout 到 master 的 A,将目前主线上的
bsp/k230/.config文件先备份出来 - checkout 到你提交 pr 的分支,假设 commit 对应的是 B,将上一步备份的
.config文件复制过来替换你的修改 - 重新
scons --menuconfig,会生成一份新的.config和rtconfig.h。将这个修改 add/commit, 假设生成的 commit 是 C - 将 B 和 C 压缩成一个 D,比较 A 和 D 就是你实际应该提交的针对
.config和rtconfig.h的修改。
|
新开 #10556 继续这个工作。 |


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