Hello,
I am using AM335xevm with sdk 8.
I am using one of the DM timer to generate signal for a specific time (around 200 microseconds). I am succeeded to generate the signal, however when i use the logical analyzer to verify the signal time, i found that, there is a random delay (about 60 microseconds) occurs.
Please find the attached 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 "../../arch/arm/plat-omap/include/plat/dmtimer.h" #include <linux/gpio.h> #include <linux/cdev.h> // do some kernel module documentation MODULE_DESCRIPTION("External Interrupt Test Module"); MODULE_LICENSE("GPL"); static struct { struct omap_dm_timer *timer_ptr; int freq; unsigned long match; unsigned long timer_rate; int duty_cycle; } SGTDev; static int32_t timer_irq; #define GPIO_TO_PIN(bank, gpio) ((32 * (bank)) + (gpio)) #define IRQ_GPIO_PIN GPIO_TO_PIN(3, 7) #define MOT_STEP_PIN GPIO_TO_PIN(1, 26) //T16 #define TIMER_MAX_VALUE 0xffffffff int irq_counter=0; struct sgt_dev { struct cdev cdev; dev_t devno; struct class *sgt_dev_class; // struct fasync_struct *async_queue; int message_cdev_open; int irq_no; unsigned int triggered_flags; }; struct sgt_dev sgt_dev; int TIMER_SPEED_TABLE[6]={1,4,8,12,16,20}; static irqreturn_t timer_irq_handler(int irq, void *dev_id) { // keep track of how many calls we had int timer_speed; int status = 0; timer_speed=SGTDev.timer_rate; irq_counter ++; /* Read the current Status */ status = omap_dm_timer_read_status(SGTDev.timer_ptr); //printk(KERN_INFO "status %x OMAP_TIMER_INT_MATCH = %x timer_speed = %ld\n",status,OMAP_TIMER_INT_MATCH,timer_speed); /* Clear the timer interrupt */ if (status == OMAP_TIMER_INT_MATCH) { //omap_dm_timer_write_status(SGTDev.timer_ptr, OMAP_TIMER_INT_MATCH); omap_dm_timer_write_status(SGTDev.timer_ptr, OMAP_TIMER_INT_MATCH | OMAP_TIMER_INT_OVERFLOW | OMAP_TIMER_INT_CAPTURE); omap_dm_timer_read_status(SGTDev.timer_ptr); } gpio_set_value(MOT_STEP_PIN,1); udelay(10); gpio_set_value(MOT_STEP_PIN,0); omap_dm_timer_set_match(SGTDev.timer_ptr, 1, timer_speed); // tell the kernel it's handled if(irq_counter>1000) { omap_dm_timer_set_int_disable(SGTDev.timer_ptr, OMAP_TIMER_INT_MATCH); /* stop timer */ printk("________________DM Timer Count %d\n", irq_counter ++); } return IRQ_HANDLED; } // Initialize the kernel module static int __init gptimer_test_init(void) { struct sgt_dev * dev = &sgt_dev; int ret = 0; struct clk *gt_fclk; uint32_t gt_rate ; const char* gpio_lable = "sg_msg_gpio"; dev->triggered_flags = 0; dev->irq_no = 0; printk("gptimer test: starting moudle init\n"); /////////////////////////////////////////////////////////////////////////////////////////////// // Initializing the DM Timer 1 /// /////////////////////////////////////////////////////////////////////////////////////////////// //SGTDev.timer_ptr = omap_dm_timer_request(); SGTDev.timer_ptr = omap_dm_timer_request_by_cap(OMAP_TIMER_HAS_PWM); if(SGTDev.timer_ptr == NULL){ // oops, no timers available printk("gptimer test: No more gp timers available, bailing out\n"); return -1; } omap_dm_timer_set_source(SGTDev.timer_ptr, OMAP_TIMER_SRC_SYS_CLK);/*set the clock source to system clock*/ omap_dm_timer_set_prescaler(SGTDev.timer_ptr, 0); /*set prescalar to 1:1*/ timer_irq = omap_dm_timer_get_irq(SGTDev.timer_ptr); /*figure out what IRQ our timer triggers*/ ret = request_irq(timer_irq, timer_irq_handler, IRQF_DISABLED | IRQF_TIMER , "gptimer test", timer_irq_handler); /*install our IRQ handler for our timer*/ if(ret){ printk("gptimer test: request_irq failed (on irq %d), bailing out\n", timer_irq); return ret; } gt_fclk = omap_dm_timer_get_fclk(SGTDev.timer_ptr); /*get clock rate in Hz*/ gt_rate = clk_get_rate(gt_fclk)/10000; SGTDev.timer_rate = gt_rate ; omap_dm_timer_enable(SGTDev.timer_ptr); omap_dm_timer_write_counter(SGTDev.timer_ptr, 0); omap_dm_timer_set_match(SGTDev.timer_ptr, 1, gt_rate); omap_dm_timer_set_pwm(SGTDev.timer_ptr, 0, 1, OMAP_TIMER_TRIGGER_OVERFLOW_AND_COMPARE); omap_dm_timer_set_int_enable(SGTDev.timer_ptr, OMAP_TIMER_INT_MATCH); printk("gptimer test: GP Timer1 initialized and started (%lu Hz, IRQ %d)\n", (long unsigned)gt_rate, timer_irq); /////////////////////////////////////////////////////////////////////////////////////////////// // Initializing the GPIO /// /////////////////////////////////////////////////////////////////////////////////////////////// printk("SG_MOT_DEV: Initializing the GPIO\n"); /*MOT_STEP_PIN */ ret = gpio_request(MOT_STEP_PIN, gpio_lable); if(ret){ printk(KERN_ERR "SG_MOT_DEV: MOT_STEP_PIN_request() failed !\n"); return ret; } ret = gpio_direction_output(MOT_STEP_PIN,0); if(ret){ printk(KERN_ERR "SG_MOT_DEV: gpio_direction_output() failed !\n"); return ret; } printk("GPIO: Initial Success\n"); /*start the timer!*/ ret = omap_dm_timer_start(SGTDev.timer_ptr); printk(KERN_INFO "Timer Start ret %d\n", ret); return 0; } // Cleanup after ourselfs static void __exit gptimer_test_exit(void) { struct sgt_dev *dev = &sgt_dev; printk("gptimer test: cleanup called\n"); // stop the timer omap_dm_timer_stop(SGTDev.timer_ptr); // release the IRQ handler free_irq(timer_irq, timer_irq_handler); // release the timer omap_dm_timer_free(SGTDev.timer_ptr); // gpio free gpio_free(MOT_STEP_PIN); } // provide the kernel with the entry/exit routines module_init(gptimer_test_init); module_exit(gptimer_test_exit);
Here is my Logical analyzer result,
Please guide me to generate signal with specific time using DM timer without any latency.
Thank you,
With Regards,
Sahaya P