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.
