Hello,
Greetings,
I tried to use two DMTimer (TIMER 4 and TIMER 7) on my AM335x Evm,
I configured Timer 4 to generate 180 Microseconds PWM and Timer 7 to100 Microseconds.
when I run both timer continuously, its working well, Timer 4 generates 180 Microseconds pulse width and Timer 7 generates 100 Microseconds pulse width.
Please refer the attached Logic Analyzer Pic1.
However, when I try to start the Timer 7 inside Timer 4 ISR Handler, its not working well, the Timer 7 pulse width is changed,
please refer the attached Logic Analyzer Pic2.
My requirement is, to start the Timer 7 Whenever Timer 4 interrupt occurs. DMTimer Start and Stop then start is not working as expected, please guide me to clear this issue.
Here is my sample source code.
#include <linux/module.h> #include <linux/kernel.h> #include <linux/init.h> #include <linux/clk.h> #include <linux/irq.h> #include <linux/interrupt.h> #include <asm/io.h> #include <linux/types.h> #include <linux/platform_device.h> #include <linux/platform_data/dmtimer-omap.h> #include <linux/sched_clock.h> #include </opt/work/trunk/BSP/AM335X/Linux/linux-3.14.26-g2489c02/arch/arm/plat-omap/include/plat/counter-32k.h> #include </opt/work/trunk/BSP/AM335X/Linux/linux-3.14.26-g2489c02/arch/arm/plat-omap/include/plat/dmtimer.h> #include <linux/gpio.h> #define DRIVER_NAME "test_dev" #define TIMER_MAX 0xFFFFFFFF static struct omap_dm_timer *timer_ptr = NULL; static struct omap_dm_timer *timer_ptr1 = NULL; static int32_t timer_irq; static int32_t timer_irq1; static uint32_t timer_rate; u32 irq_count =0; static irqreturn_t timer_irq_handler( int irq, void * dev_id) { unsigned int retval; retval = omap_dm_timer_read_status(timer_ptr); if (!retval) return IRQ_NONE; if (retval & ~OMAP_TIMER_INT_MATCH) printk("Unexpected interrupt source: %x\n", retval); omap_dm_timer_write_status(timer_ptr, OMAP_TIMER_INT_MATCH | OMAP_TIMER_INT_OVERFLOW | OMAP_TIMER_INT_CAPTURE); omap_dm_timer_read_status(timer_ptr); irq_count++; omap_dm_timer_start(timer_ptr1); if(irq_count > 100) { omap_dm_timer_stop(timer_ptr); omap_dm_timer_stop(timer_ptr1); printk("________________DM Timer Count %d\n", irq_count ); irq_count =0; } return IRQ_HANDLED; } static irqreturn_t timer_irq_handler1( int irq, void * dev_id) { unsigned int retval; retval = omap_dm_timer_read_status(timer_ptr1); if (!retval) return IRQ_NONE; if (retval & ~OMAP_TIMER_INT_MATCH) printk("Unexpected interrupt source: %x\n", retval); omap_dm_timer_write_status(timer_ptr1, OMAP_TIMER_INT_MATCH | OMAP_TIMER_INT_OVERFLOW | OMAP_TIMER_INT_CAPTURE); omap_dm_timer_read_status(timer_ptr1); omap_dm_timer_stop(timer_ptr1); return IRQ_HANDLED; } static int init_timing(struct omap_dm_timer *timer,unsigned int on_time,unsigned int off_time) { u32 load, match; load = timer_rate * (on_time + off_time) / 1000; match = timer_rate * on_time / 1000; omap_dm_timer_set_load(timer, 1, -load); omap_dm_timer_set_match(timer, 1, -match); omap_dm_timer_write_counter(timer, - 2); omap_dm_timer_set_pwm(timer, 1, 1, OMAP_TIMER_TRIGGER_OVERFLOW_AND_COMPARE); omap_dm_timer_set_int_enable(timer, OMAP_TIMER_INT_MATCH); return 0; } static int test_module_init(struct platform_device *pdev) { int ret = 1,i; struct clk *timer_clk; struct device_node *timer_device_node; struct device_node *timer_device_node1; printk(KERN_INFO " INIT DM Timer\n"); timer_device_node = of_parse_phandle(pdev->dev.of_node, "DMtimer", 0); timer_ptr = omap_dm_timer_request_by_node(timer_device_node); if(timer_ptr == NULL) { /* no timers available */ printk(KERN_INFO "Can't request specified DM Timer 4\n"); return -1; } timer_device_node1 = of_parse_phandle(pdev->dev.of_node, "DMtimer1", 0); timer_ptr1 = omap_dm_timer_request_by_node(timer_device_node1); if(timer_ptr1 == NULL) { /* no timers available */ printk(KERN_INFO "Can't request specified DM Timer 7\n"); return -1; } /* Set the Clock source to the System Clock */ ret = omap_dm_timer_set_source(timer_ptr, OMAP_TIMER_SRC_SYS_CLK); ret = omap_dm_timer_set_source(timer_ptr1, OMAP_TIMER_SRC_SYS_CLK); // set prescalar to 1:1 //omap_dm_timer_set_prescaler(timer_ptr, 0); omap_dm_timer_enable(timer_ptr); omap_dm_timer_enable(timer_ptr1); /* Determine what IRQ the timer triggers */ timer_irq = omap_dm_timer_get_irq(timer_ptr); timer_irq1 = omap_dm_timer_get_irq(timer_ptr1); /* Setup the IRQ handler */ ret = request_irq(timer_irq, timer_irq_handler, IRQF_TIMER, "DMTimer 4", NULL); /* Setup the IRQ handler */ ret = request_irq(timer_irq1, timer_irq_handler1, IRQF_TIMER, "DMTimer 7", NULL); /* Get the Clock rate in Hz */ timer_clk = omap_dm_timer_get_fclk(timer_ptr); timer_rate = clk_get_rate(timer_clk)/1000; init_timing(timer_ptr,180,5); //180 microsec init_timing(timer_ptr1,100,5); // 100 microsec /* Start the timer */ omap_dm_timer_start(timer_ptr); //omap_dm_timer_start(timer_ptr1); return 0; } static int test_module_exit(struct platform_device *pdev) { int ret = 1; /* stop the timer */ ret = omap_dm_timer_stop(timer_ptr); printk(KERN_INFO "Timer Stop ret = %d\n", ret); ret = omap_dm_timer_stop(timer_ptr1); printk(KERN_INFO "Timer Stop ret = %d\n", ret); /* Release the IRQ handler */ free_irq(timer_irq, NULL); free_irq(timer_irq1, NULL); printk(KERN_INFO "Free IRQ Done\n"); /* Release the timer */ ret = omap_dm_timer_free(timer_ptr); printk(KERN_INFO "Timer Free ret = %d\n", ret); ret = omap_dm_timer_free(timer_ptr1); printk(KERN_INFO "Timer Free ret = %d\n", ret); return 0; } static const struct of_device_id test_module_timer_of_match[] = { { .compatible ="ti,am335x-timer" }, {}, }; static struct platform_driver test_module_timer_driver = { .driver = { .name = DRIVER_NAME, .of_match_table = test_module_timer_of_match, }, .probe = test_module_init, .remove = test_module_exit, }; module_platform_driver(test_module_timer_driver); MODULE_LICENSE("GPL"); MODULE_AUTHOR("Sahaya Darcius"); MODULE_DESCRIPTION("Sample DMTimer Test Driver"); MODULE_VERSION("0.1");
Thank you.