I'm working on a board using an i.MX6 solo running a customized Linux 4.1.43 (retrieved from https://github.com/Freescale/linux-fslc in September). We need to read a PWM that we are feeding to the SD1_DAT0 pin muxed as GPT_CAPTURE1.
I've modified arch/arm/mach-imx/time.c to handle the GPT's IF1 interrupt and have been able to successfully quantify the incoming PWM at low frequencies. I added a platform driver to time.c that made the PWM values available via sysfs entries .
However the system continually deadlocks and increasing the PWM frequency to 10kHz locks the kernel before it even finishes booting. Sometimes it locks immediately after u-boot starts it.
When I unplug the PWM signal before booting, the system runs as expected.
To simplify the problem I went back to the original version of time.c and changed only the following:
1. Enabled the IF1 interrupt in the GPT_IR register
2. Cleared the OF1 and IF1 interrupts in the GPT_SR register when processing an interrupt
3. Only called the kernel's timer event handler when the OF1 flag is set in GPT_SR
4. Set IM1 to trigger off a rising edge in the GPT_CR register
Just enabling the input capture 1 interrupt, ignoring it and resetting it causes the system to lock up.
Is there a way to safely use the GPT_CAPTURE1 input to read a PWM?
I have attached the original time.c, my modified version and a patch file showing the differences.
Some other interesting info:
Once, after the system locked up trying to boot, I left it running and continued investigating. After a while the system continued booting a little more before getting hung up again.
Another time I left it over lunch and came back to this output on the terminal:
INFO: rcu_preempt self-detected stall on CPU
0: (1 ticks this GP) idle=563/1/0 softirq=5274/5274 fqs=1
(t=143119 jiffies g=2565 c=2564 q=14226)
rcu_preempt kthread starved for 143119 jiffies!
Task dump for CPU 0:
swapper/0 R running 0 0 0 0x00000000
[<80015c48>] (unwind_backtrace) from [<80012698>] (show_stack+0x10/0x14)
[<80012698>] (show_stack) from [<80078658>] (rcu_dump_cpu_stacks+0x84/0xc8)
[<80078658>] (rcu_dump_cpu_stacks) from [<8007c5f8>] (rcu_check_callbacks+0x498/0x89c)
[<8007c5f8>] (rcu_check_callbacks) from [<8007eca8>] (update_process_times+0x38/0x64)
[<8007eca8>] (update_process_times) from [<8008ed08>] (tick_sched_timer+0x4c/0x98)
[<8008ed08>] (tick_sched_timer) from [<8007f958>] (__run_hrtimer.constprop.4+0x44/0xd8)
[<8007f958>] (__run_hrtimer.constprop.4) from [<8007fca0>] (hrtimer_interrupt+0xfc/0x2f4)
[<8007fca0>] (hrtimer_interrupt) from [<80021ffc>] (mxc_timer_interrupt+0x2c/0x48)
[<80021ffc>] (mxc_timer_interrupt) from [<800706bc>] (handle_irq_event_percpu+0x78/0x134)
[<800706bc>] (handle_irq_event_percpu) from [<800707b8>] (handle_irq_event+0x40/0x64)
[<800707b8>] (handle_irq_event) from [<800735c0>] (handle_fasteoi_irq+0xdc/0x1ac)
[<800735c0>] (handle_fasteoi_irq) from [<8006fd78>] (generic_handle_irq+0x28/0x3c)
[<8006fd78>] (generic_handle_irq) from [<80070028>] (__handle_domain_irq+0x68/0xe8)
[<80070028>] (__handle_domain_irq) from [<80009470>] (gic_handle_irq+0x2c/0x70)
[<80009470>] (gic_handle_irq) from [<80013180>] (__irq_svc+0x40/0x74)
Exception stack(0x80865f30 to 0x80865f78)
5f20: 80865f78 fffffff7 539c8caa 0000016f
5f40: 539c5748 0000016f 9fb26dd8 00000000 539c8caa 0000016f 8085e300 00000001
5f60: 00000017 80865f78 a6aaaaab 803fdc04 000e0013 ffffffff
[<80013180>] (__irq_svc) from [<803fdc04>] (cpuidle_enter_state+0xcc/0x1f0)
[<803fdc04>] (cpuidle_enter_state) from [<80067b24>] (cpu_startup_entry+0x1c4/0x308)
[<80067b24>] (cpu_startup_entry) from [<80805c04>] (start_kernel+0x338/0x3a4)
Solved! Go to Solution.
Hi James
seems gpt interrupt routine has not sufficient time to read pwm,
leaving no time for linux system timer interrupts working properly.
One can check sect.3.3 Timer attached Linux Manual and try to use
epit for linux timer, leaving gpt for custom purposes.
epit.c\mach-imx\arm\arch - linux-imx - i.MX Linux kernel
Best regards
igor
-----------------------------------------------------------------------------------------------------------------------
Note: If this post answers your question, please click the Correct Answer button. Thank you!
-----------------------------------------------------------------------------------------------------------------------
I was able to get the EPIT driver to work and was then able to use the GPT to read the PWM without issues.
Here's what I changed:
1. In my device tree I removed the "compatible" attribute for the GPT so it wouldn't load its clocksource driver. I also added a "compatible" attribute for the EPIT driver:
/ {
soc {
aips-bus@02000000 { /* AIPS1 */
gpt: gpt@02098000 {
/delete-property/ compatible;
};
epit1: epit@020d0000 { /* EPIT1 */
compatible = "fsl,imx6q-epit";
};
};
};
2. In arch/arm/mach-imx/epit.c, I added device tree initialization functions and macros.
3. In arch/arm/mach-imx/Kconfig I added "select HAVE_EPIT" to the "config SOC_IMX6" section.
4. In arch/arm/mach-imx/clk-imx6q.c, arch/arm/boot/dts/imx6qdl.dtsi and include/dt-bindings/clock/imx6qdl-clock.h I added clock entries for the EPIT.
5. In my kernel build config file I added the line "CONFIG_MXC_USE_EPIT=y".
Hi James
seems gpt interrupt routine has not sufficient time to read pwm,
leaving no time for linux system timer interrupts working properly.
One can check sect.3.3 Timer attached Linux Manual and try to use
epit for linux timer, leaving gpt for custom purposes.
epit.c\mach-imx\arm\arch - linux-imx - i.MX Linux kernel
Best regards
igor
-----------------------------------------------------------------------------------------------------------------------
Note: If this post answers your question, please click the Correct Answer button. Thank you!
-----------------------------------------------------------------------------------------------------------------------
Thanks for the response Igor.
The EPIT driver in the mach-imx directory is only used by the i.MX35.
I compared the i.MX6 EPIT definition in the manual with what's in epit.c and they appear to be compatible.
However the GPT driver is initialized drastically differently using the device tree.
Are there any examples of an EPIT driver that already works with the i.MX6?