您好, 我现在用gpio模拟pwm ,这个频率周期最大支持到多少,现在在内核中使用高精度定时器测试,当频率设置为2微秒时,电平失真,并且达不到需要的2微秒
当使用20微秒周期的时候。信号如下图:
hello 550399056,
may I know what’s your approach to simulate PWM?
or… could you please share the code snippets for reference?
34 static enum hrtimer_restart pwm_timer_callback(struct hrtimer *timer) {
35 timer_cnt++;
36 if(timer_cnt == high_cnt){
37 gpio_set_value(ir_pwm.gpioNum, 0);
38 }
39 if(timer_cnt == period_cnt){
40 gpio_set_value(ir_pwm.gpioNum, 1);
41 timer_cnt = 0;
42 }
43 hrtimer_forward(timer, timer->base->get_time(), pwm_period);
44 // state = !state;
45 // gpio_set_value(ir_pwm.gpioNum, state);
46 // hrtimer_forward_now(timer,pwm_period);
47
48 return HRTIMER_RESTART;
49 }
hello 550399056,
please give it a try by using sleep
instead of variable counts to set high/low period.
sleep
能到精准到微妙级吗
there’re msleep
, usleep_range
…etc, please give it a try.
我使用了 usleep_range
,
36 static int thread_func(void *data) {
37
38 int i, count;
39 int step = 2;
40 int period_us = 1000000 / frequency; // 计算周期(微秒)
41 int duty_cycle = 30;
42 int high_time_us = period_us * duty_cycle / 100; // 高电平时间
43 int low_time_us = period_us - high_time_us; // 低电平时间
44
45 while (1){
46 usleep_range(high_time_us,high_time_us+step);
47 gpio_set_value(ir_pwm.gpioNum, 1);
48 usleep_range(low_time_us,low_time_us+step);
49 gpio_set_value(ir_pwm.gpioNum, 0);
50 }
51 return 0;
52 }
偶尔会出现上面周期不同步的情况。
hello 550399056,
since you’re using an application to toggle GPIO state change, is it related to system process scheduling?
please give it a try by using commands to adjust the process priority (i.e. renice
) for specific process,
you may further to assign CPUs individually (i.e. taskset
) for the test application.
for instance,
$ sudo renice -20 -p <pid>
$ taskset -c -p 2,3 <pid>
这是个内核线程,怎么指定优先级呢?
我使用下面方法,效果还是一样:
thread_body = kthread_create(thread_func, NULL, "thread_pwm");
if((thread_body))
{
thread_body->prio = 1;
bind_thread_to_cpu(thread_body,1);
wake_up_process(thread_body);
}
hello 550399056,
may I know the test results by using constant variable, i.e. usleep_range(10, 20);
and… since it’s a range (i.e. 10~20us) for scheduler to pause the code, would you please also check whether high/low is around 10~20us as well?
上面我设置的是:
45 while (1){
46 usleep_range(high_time_us,high_time_us+step);
47 gpio_set_value(ir_pwm.gpioNum, 1);
48 usleep_range(low_time_us,low_time_us+step);
49 gpio_set_value(ir_pwm.gpioNum, 0);
50 }
具体数值如下:
45 while (1){
46 usleep_range(30,32);
47 gpio_set_value(ir_pwm.gpioNum, 1);
48 usleep_range(70,72);
49 gpio_set_value(ir_pwm.gpioNum, 0);
50 }
最终效果如示波器上显示的方波一样。不稳定
hello 550399056,
may I know which L4T release version you’re working with, did you test on Orin Nano developer kit?
我们使用的是orin nx,版本:
JetPack 5.1.4
Linux 35.6.0
Linux Kernel 5.10
Ubuntu 20.04 root file system
hello 550399056,
just curious, why you don’t use PWM directly. i.e. $ ls -la /sys/class/pwm/pwmchip*
here’s an example to enable pwm0
cd /sys/class/pwm/pwmchip3
echo 0 > export
cd pwm0
echo 100000000 > period # i.e. 10Hz
echo 5000 > duty_cycle
echo 1 > enable