Capture使用参考
REVISION HISTORY¶
Revision No. | Description |
Date |
---|---|---|
1.0 | 04/09/2025 |
1. 概述¶
1.1. Capture¶
Capture可以捕获PWM波形信息,包括周期、占空比及脉冲个数,Capture原理是通过捕获PWM波形的上升沿和下降沿及其时间间隔,从而得到PWM波形的信息,需要注意的是,捕获的波形占空比范围应该在0% < duty < 100%,因为占空比为0%或者100%的时候,不存在上升沿和下降沿,无法捕捉到跳变来获取输入的PWM波形信息。
Capture的时钟频率为24Mhz,不支持切换。
1.2. channel¶
capture共有8组,其中前4组每组有2个channel支持捕获,后四组每组有1个channel支持捕获,总计12个channel支持捕获
Capture最高支持12个channel同时捕获PWM周期及占空比,但每组仅有1个channel捕获脉冲数量,因此最高支持8个channel同时捕获脉冲数量
2. 关键字¶
dts/dtsi:
Linux设备树文件,通常用于描述CPU所支持的外设,外设节点中包含的属性值可用于外设的配置。
padmux:
引脚复用,用于将模块功能引脚连接到具体的外部引脚上面,打通信号连接。
deglitch:
滤波,长度小于deglitch值的波形会被忽略(单位ns),deglitch的设定会影响捕获的PWM频率上限
3. 功能描述¶
capture 支持三种模式的脉冲数量捕获:normal mode、direction mode、quad mode,捕获的频率范围为1Hz~6MHz
3.1. 脉冲计数模式--normal mode¶
8组Capture都支持normal mode,每捕获到两个上升沿后计数加1,最大值为0xFFFF,溢出清0
3.2. 脉冲计数模式--direction mode¶
仅前4组Capture0-Capture3支持direction mode,每组的两个channel,一个作为脉冲计数,另一个作为方向判断,
当作为方向的channel捕获到高电平时,脉冲计数开始递增,最大值为0xFFFF,溢出清0,
当作为方向的channel捕获到低电平时,脉冲计数开始递减,最大值为0xFFFF,逐渐减小至0后再跳变为0xFFFF,循环往复
3.3. 脉冲计数模式--quad mode¶
quad mode也称为正交编码计数模式,仅前4组Capture0-Capture3支持,每组的两个channel,
通过捕获信号完全一样,相位差90度的PWM信号(即正交信号),以此计算出脉冲数量及方向,
如图所示,quad mode就是4倍计数的意思,满足图中4个时刻的计数才会让脉冲数量加1,因此拥有更高的计数精度
如图所示,脉冲在TI1和TI2边沿都计数,其中
1 时刻:TI2为低电平,TI1上升沿跳变,计数器向上计数
2 时刻:TI1为高电平,TI2上升沿跳变,计数器仍然向上计数
3 时刻:TI2为高电平,TI1下降沿跳变,计数器仍然向上计数
4 时刻:TI1为低电平,TI2下降沿跳变,计数器仍然向上计数
4. Kernel用法介绍¶
驱动路径:kernel/drivers/sstar/capture
4.1. Kernel Config配置¶
在编译kernel时需要选择的配置如下:
Device Drivers--> [*] SStar SoC platform drivers--> [*] Sigmastar Capture driver
4.2. 配置DTS¶
Capture的DTS配置只需要在对应的chipname.dtsi中配置如下信息:
capture0: capture@1f2ce000 { compatible = "sstar,capture"; reg = <0x0 0x1F2CE000 0x0 0x80>; interrupts=<GIC_SPI INT_IRQ_CAPTURE IRQ_TYPE_LEVEL_HIGH>; group = <0>; channel = <0 1>; //0: normal mode, 1: quad mode, 2: dir mode pulse-cal-mode = <0>; pulse-cal-chan = <0>; deglitch = <0>; clocks = <&CLK_pwm_capture>; status = "ok"; }; ....... capture4: capture@1f2cf800 { compatible = "sstar,capture"; reg = <0x0 0x1F2CF800 0x0 0x80>; interrupts=<GIC_SPI INT_IRQ_CAPTURE IRQ_TYPE_LEVEL_HIGH>; group = <4>; channel = <8>; //only support 0: normal mode pulse-cal-mode = <0>; pulse-cal-chan = <8>; deglitch = <0>; clocks = <&CLK_pwm_capture>; status = "ok"; };
Capture DTS配置说明:
属性 | 描述 | 设定值 | 备注 |
---|---|---|---|
compatible | 匹配驱动进行注册,需与代码中一致 | "sstar,capture" | 禁止修改 |
reg | 设定寄存器bank的地址 | / | 禁止修改 |
interrupts | 指定使用的硬件中断号及属性 | INT_IRQ_CAPTURE | 禁止修改 |
group | 每个channel所属的group id | / | 禁止修改 |
channel | 每个group下拥有的channel id | / | 禁止修改 |
pulse-cal-mode | 选择不同的脉冲计数模式,可参考脉冲计数模式说明 | Capture03支持02,Capture4~7仅支持0 | 可根据需要修改 |
pulse-cal-chan | 选择捕获脉冲数量的channel | Capture03支持二选1,Capture47仅支持1个channel | 可根据需要修改 |
deglitch | 设定滤除的脉冲 | 以ns为单位,比如设定值为7,那么高电平时长低于24M * 7 = 291.67ns以下的脉冲无法被捕获 | 可根据需要修改 |
clocks | 指定使用的时钟源 | CLK_pwm_capture | 禁止修改 |
status | 选择是否使能Capture驱动 | "ok" or "disable" | 可根据需要修改 |
4.3. PADMUX配置¶
Capture的padmux配置需要根据选择的引脚在对应的arch/arm64/boot/dts/sstar/chipname-xxx-padmux.dtsi
中加入如下所示的代码:
<PAD_OUTP_CH0 PINMUX_FOR_PWMIN0_MODE_1 MDRV_PUSE_PWMIN0>, <PAD_OUTN_CH0 PINMUX_FOR_PWMIN1_MODE_1 MDRV_PUSE_PWMIN1>, <PAD_OUTP_CH1 PINMUX_FOR_PWMIN2_MODE_1 MDRV_PUSE_PWMIN2>, <PAD_OUTN_CH1 PINMUX_FOR_PWMIN3_MODE_1 MDRV_PUSE_PWMIN3>, <PAD_OUTP_CH2 PINMUX_FOR_PWMIN4_MODE_1 MDRV_PUSE_PWMIN4>, <PAD_OUTN_CH2 PINMUX_FOR_PWMIN5_MODE_1 MDRV_PUSE_PWMIN5>, <PAD_OUTP_CH3 PINMUX_FOR_PWMIN6_MODE_1 MDRV_PUSE_PWMIN6>, <PAD_OUTN_CH3 PINMUX_FOR_PWMIN7_MODE_1 MDRV_PUSE_PWMIN7>, <PAD_GPIOE_10 PINMUX_FOR_PWMIN8_MODE_3 MDRV_PUSE_PWMIN8>, <PAD_GPIOD_00 PINMUX_FOR_PWMIN9_MODE_2 MDRV_PUSE_PWMIN9>, <PAD_GPIOE_14 PINMUX_FOR_PWMIN10_MODE_3 MDRV_PUSE_PWMIN10>, <PAD_GPIOE_16 PINMUX_FOR_PWMIN11_MODE_3 MDRV_PUSE_PWMIN11>,
第一列为引脚索引号,可以在/drivers/sstar/inlcude/{chipname}/gpio.h中查到;
第二列为模式定义,在/drivers/sstar/gpio/{chipname}/hal_pinmux.c中hal_gpio_st_padmux_info数组里罗列了所有引脚的复用关系,可用于查询该引脚支持哪些复用功能;
第三列为引脚及搭配模式的索引名称,可在/drivers/sstar/include/drv_puse.h里查询。
4.4. 模块使用介绍¶
4.4.1. sys/class/sstar/capture¶
sys/class/sstar/capture目录结构如下:
-
一级目录
根据DTS Capture status的状态创建不同的group
-
二级目录
每组Capture的各项属性设定
各文件接口的使用介绍:
名称 | 描述 | 参数 | 备注 |
---|---|---|---|
capture | 获取捕获到的频率和占空比 | echo [channel id] > capture;cat capture | |
cap_edge | 设定捕获周期和占空比时的边沿采样模式 | echo [channel id] [edge mode] > cap_edge | edge mode:0->上升沿 1->下降沿 2->双边沿 |
cap_enable | 捕获使能 | echo [enable] > cap_enable | 0->disable 1->enable |
pulse | 获取捕获到的脉冲数量 | cat pulse | 捕获的channel由DTS决定 |
pulse_edge | 设定捕获脉冲数量时的边沿采样模式 | echo [edge mode] > pulse_edge | edge mode:0->上升沿 1->下降沿 2->双边沿,注意单边沿捕获的脉冲数量是双边沿的倍数关系 |
pulse_enable | 捕获使能 | echo [enable] > pulse_enable | 0->disable 1->enable |
pulse_bound | quad mode下捕获的上下限设定 | echo [max] [min]> pulse_bound | 仅支持quad mode使用,当方向为正时,达到max会触发中断并将捕获的pulse数值清0,当方向为负时,达到min会触发中断并将捕获的pulse数值清0 |
direction | 获取捕获脉冲时的方向 | cat direction | 0->负向 1->正向 |
timeout | 设定捕获的超时时间 | echo [channel id] [time ns] > time_out | 在规定时间内捕获的结果不变,软件判定为输入源已断开,捕获失败,可用于较小频率的捕获 |
举例:使用Capture0的channel0捕获频率、占空比和脉冲数量
1. #跳转到Capture0路径 2. cd sys/class/sstar/capture0/ 3. 4. #设置Capture相关属性 5. echo 0 2 > cap_edge 6. echo 1 > cap_enable 7. echo 1 > pulse_edge 8. echo 1 > pulse_enable 9. 10. #获取捕获结果 11. echo 0 > capture; 12. cat capture; 13. cat pulse; 14. cat direction;
4.5 Demo code¶
除sysfs外,capture还提供了ioctl的用户层接口, 用法如下
#include <stdio.h> #include <errno.h> #include <fcntl.h> #include <stdlib.h> #include <unistd.h> #include <signal.h> #include <string.h> #include <sys/stat.h> #include <sys/types.h> #include <sys/ioctl.h> #include <drv_capture.h> void capture_warn(int num) { printf("capture pulse exceeding the threshold\n"); } int main(int argc, char **argv) { u8 id; char cmd; int flags; int fd = -1; char path_name[24]; struct capture_info info; struct capture_config cap_cfg; if (argc != 5) { printf("format: ut_capture [channel] [cap_edge] [pul_edge] [enable]\n"); return -1; } info.channel = atoi(argv[1]); cap_cfg.channel = atoi(argv[1]); cap_cfg.cap_edge = atoi(argv[2]); cap_cfg.pul_edge = atoi(argv[3]); cap_cfg.cap_enable = atoi(argv[4]); cap_cfg.pul_enable = atoi(argv[4]); cap_cfg.quad_pul_up = 20000; cap_cfg.quad_pul_dn = 20000; cap_cfg.timeout = 10000000000; if (cap_cfg.channel >= 0 && cap_cfg.channel <= 1) { id = 0; } else if (cap_cfg.channel >= 2 && cap_cfg.channel <= 3) { id = 1; } else if (cap_cfg.channel >= 4 && cap_cfg.channel <= 5) { id = 2; } else if (cap_cfg.channel >= 6 && cap_cfg.channel <= 7) { id = 3; } else if (cap_cfg.channel == 8) { id = 4; } else if (cap_cfg.channel == 9) { id = 5; } else if (cap_cfg.channel == 10) { id = 6; } else if (cap_cfg.channel == 11) { id = 7; } else { printf("unsupport channel\n"); return -1; } snprintf(path_name, sizeof(path_name), "/dev/capture%hhu", id); fd = open((const char *)(char *)path_name, O_RDWR); if (fd < 0) { printf("open /dev/capture%hhu fail errno:[%d]\n", id, fd); return -1; } if (ioctl(fd, IOCTL_CAPTURE_SET_CONFIG, &cap_cfg)) { printf("capture[%hhu] config fail\n", cap_cfg.channel); close(fd); return -1; } signal(SIGIO, capture_warn); //quad mode达到上下限时触发 fcntl(fd, F_SETOWN, getpid()); flags = fcntl(fd, F_GETFL); fcntl(fd, F_SETFL, flags | FASYNC); while (1) { cmd = getchar(); if (cmd == 'q' || cmd == 'Q') { break; } if (ioctl(fd, IOCTL_CAPTURE_RD_PERIOD, &info)) { printf("capture[%hhu] read period fail\n", info.channel); close(fd); return -1; } printf("capture period [%llu]ns , duty [%llu.%02llu]%% \n", info.period, info.duty_i, info.duty_d); if (ioctl(fd, IOCTL_CAPTURE_RD_PULSE, &info)) { printf("capture[%hhu] read pulse fail\n", info.channel); } else { printf("capture pulse [%u] dir[%hhu]\n", info.pulse, info.dir); } } close(fd); return 0; }
5. API 参考¶
capture的ioctl方法提供以下魔数接口:
Cmd | 功能 |
---|---|
IOCTL_CAPTURE_SET_CONFIG | 设定指定channel的捕获属性 |
IOCTL_CAPTURE_GET_CONFIG | 获取当前channel的捕获属性 |
IOCTL_CAPTURE_RD_PERIOD | 获取当前周期 |
IOCTL_CAPTURE_RD_PULSE | 获取当前脉冲计数 |
使用前需包含头文件/driver/sstar/capture/drv_capture.h,其中定义的数据结构如下:
struct capture_config { u8 channel; //指定捕获channel u64 timeout; //设定超时时间,以ns为单位 u8 cap_edge; //设定捕获周期和占空比时的边沿模式 u8 pul_edge; //设定捕获脉冲数量时的边沿模式 u8 cap_enable; u8 pul_enable; u16 quad_pul_up; //设定quad mode下的脉冲捕获上限 u16 quad_pul_dn; //设定quad mode下的脉冲捕获下限 }; struct capture_info { u8 dir; //捕获脉冲时的方向 u32 pulse; //捕获的脉冲数量 u64 period; //捕获的周期 u64 duty_i; //捕获占空比的整数数值 u64 duty_d; //捕获占空比的小数数值 u8 channel; };
5.1. IOCTL_CAPTURE_SET_CONFIG¶
-
功能
从 cfg 设定file 对应设备的捕获属性。
-
声明
ioctl(struct file *file, IOCTL_CAPTURE_SET_CONFIG,struct capture_config *cfg);
-
形参
参数名称 描述 file 设备节点 IOCTL_CAPTURE_SET_CONFIG 命令 cfg 存储配置的结构体 -
返回值
返回值 描述 0 成功 other 失败
5.2. IOCTL_CAPTURE_GET_CONFIG¶
-
功能
获取 file 对应设备的捕获属性,并返回到 cfg。
-
声明
ioctl(struct file *file, IOCTL_CAPTURE_GET_CONFIG,struct capture_config *cfg);
-
形参
参数名称 描述 file 设备节点 IOCTL_CAPTURE_GET_CONFIG 命令 cfg 存储配置的结构体 -
返回值
返回值 描述 0 成功 other 失败
5.3. IOCTL_CAPTURE_RD_PERIOD¶
-
功能
获取 file 对应设备的当前周期并返回到 info 。
-
声明
ioctl(struct file *file, IOCTL_CAPTURE_RD_PERIOD,struct capture_info *info);
-
形参
参数名称 描述 file 设备节点 IOCTL_CAPTURE_RD_PERIOD 命令 info 存储捕获信息的结构体 -
返回值
返回值 描述 0 成功 other 失败
5.4. IOCTL_CAPTURE_RD_PULSE¶
-
功能
获取 file 对应设备的当前脉冲计数并返回到 info 。
-
声明
ioctl(struct file *file, IOCTL_CAPTURE_RD_PULSE, struct capture_info *info);
-
形参
参数名称 描述 file 设备节点 IOCTL_CAPTURE_RD_PULSE 命令 info 存储捕获信息的结构体 -
返回值
返回值 描述 0 成功 other 失败
6. FAQ¶
6.1. Capture各接口不存在¶
-
检查DTS Capture节点的
status
是否为ok
-
检查kernel config是否配置,详见Kernel Config配置
6.2. 配置后Cature捕获结果异常或超时¶
Step1: 首先确认测量的引脚是否正确:打开对应的原理图确认即可,如果没有错误的话,则进行下一步。
Step2: 确认对应的Capture pad mode是否生效,引脚复用失败主要有两个原因:
原因一:该引脚没有设置为Capture mode,设置方法详见PADMUX配置
原因二:有优先级比Capture mode更高级别的padmux mode被开启,可以在编译的时候打开padmux回读机制的CONFIG:CONFIG_MSYS_PADMUX,它的功能是用于确认使用到的padmux是否有被成功设定,开启后在在user space输入如下命令查看:
echo [pad index] [pinmux index] > /sys/class/sstar/msys/mux_verify cat /sys/class/sstar/msys/mux_verify
Step3:检查相关参数是否设置成功
请参考sysfs接口使用说明规范使用