This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

hrtimer generating slow clock speed

Hi I have problem that using hrtimer only getting 21Hz of interrupts. Did I configure it wrongly?

I am looking something that goes for MHz range(says 10-20MHz), anyway for me to that?

I am using omap powered "devkit8000".

#include <linux/device.h>  
#include <linux/interrupt.h>
#include <linux/kthread.h>
#include <linux/irq.h>
#include <linux/gpio.h>
#include <linux/platform_device.h>
#include <linux/slab.h>
#include <linux/time.h> 
#include <linux/delay.h>
#include <plat/mux.h>

#include <linux/string.h>
#include <linux/spi/spi.h>
#include <linux/version.h>
#include <linux/vmalloc.h>	// for vmalloc
#include <linux/kernel.h>
#include <linux/device.h>
#include <linux/module.h>
#include <linux/mutex.h>
#include <linux/init.h>
#include <linux/cdev.h>		// for char device
#include <linux/slab.h>
#include <linux/fs.h>		// for file operation
#include <linux/mm.h>
#include<linux/fcntl.h>
#include <asm/uaccess.h>	// for copy_from and copy_to user
#include <asm/io.h>
#include <linux/ioctl.h>

#include <linux/timer.h>


#define DEBUG_KERNEL	1
#define SPI_BUFF_SIZE	16
#define USER_BUFF_SIZE	128
#define SUCCESS		0
#define ERROR		-1
#define SPI_BUS		1
#define SPI_BUS_CS1	1
#define SPI_BUS_SPEED	1000000

#define PRODUCT_ID_ADDR	0x00
#define PRODUCT_ID	0x33

#define MS_TO_NS(x)	(x * 1E6L)
#define	GPIO_130	130
#define	HIGH		1
#define	LOW		0
#define USER_TIMER	10

const char this_driver_name[] = "testgpio";

struct testgpio_dev {
	struct semaphore spi_sem;
	struct semaphore fop_sem;
	struct mutex mutex;
	dev_t devt;
	struct cdev cdev;
	struct class *class;
	char *user_buff;
	u8 test_data;
        struct mutex lock;
	char loopcounter;
};
static struct testgpio_dev testgpio_dev;
static unsigned long delay_in_ms;
static struct hrtimer hr_timer;
static int my_tasklet_data;
void inittimer(unsigned long data );
void setting_timer(unsigned long data, ktime_t *t);
DECLARE_TASKLET( tasklet_inittimer, inittimer, (unsigned long) &my_tasklet_data );

enum hrtimer_restart my_hrtimer_callback( struct hrtimer *timer )
{
	// ktime	: interval
	// currtime	: current time
	ktime_t currtime, ktime;
	unsigned long missed;

	currtime = ktime_get();
	setting_timer(delay_in_ms, &ktime);
	//hrtimer_start( &hr_timer, ktime, HRTIMER_MODE_REL );

	missed = hrtimer_forward(&hr_timer, currtime, ktime);
	if (missed > 1)
		printk("Missed ticks %ld\n", missed - 1);

	gpio_set_value( GPIO_130, (!gpio_get_value(GPIO_130)) );// tonggle IO

	printk( "my_hrtimer_callback CurrTime: %llu ns\n", (unsigned long long)(ktime_to_ns(currtime)>>10) );

	return HRTIMER_RESTART;
}

void setting_timer(unsigned long data, ktime_t *t)
{
	switch(data)
	{
		case 1:
			*t = ktime_set( 0, 1 );
		break;

		case 10:
			*t = ktime_set( 0, 10L );
		break;

		case 100:
			*t = ktime_set( 0, 100L );
		break;

		case 1000:
			*t = ktime_set( 0, 1000L );
		break;

		case 10000:
			*t = ktime_set( 0, 10000L);
		break;
		default:
		break;
	}
}

void inittimer(	unsigned long data )
{
	ktime_t ktime,currtime;

	printk("HR Timer module installing\n");

	setting_timer(delay_in_ms, &ktime);

	hrtimer_init( &hr_timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL );
	hr_timer.function = &my_hrtimer_callback;

	currtime = ktime_get();

	printk( "Starting timer to fire in %ldms (%ld)\n", delay_in_ms, jiffies );
	printk( "inittimer CurrTime: (%llu)ns.\n", (unsigned long long)(ktime_to_ns(currtime)>>10) );

	hrtimer_start( &hr_timer, ktime, HRTIMER_MODE_REL );
}

static ssize_t testgpio_read(struct file *filp, char __user *buff, size_t count,
			loff_t *offp)
{
	size_t len;
	ssize_t status = 0;

	printk(KERN_ALERT "@testgpio_read\n");

	return status;	
}

static ssize_t testgpio_write(struct file *file, const char __user * buffer, size_t length, loff_t * offset)
{
	int status = 0;
	char cmdtype[10];
	char wrmode[10];
	u8 addval = 0;
	u8 dataval = 0;
	unsigned int timerval = 0;

	mutex_lock(&testgpio_dev.mutex);

	if (!buffer) 
		return -EFAULT;

	if (*offset > 0) 
		return 0;

	printk(KERN_ALERT "@testgpio_write\n");
	printk(KERN_ALERT "@testgpio_write length: %d",length);

	sscanf(buffer,"%s %s  %hhx %hhx %d"
			,cmdtype, wrmode, &addval, &dataval, &timerval);
	printk(KERN_ALERT "@testgpio_write buffer content: %s %s 0x%x 0x%x %d"
			,cmdtype, wrmode, addval, dataval, timerval);
	
	if(strcmp(cmdtype,"timer") == 0)
	{
		if(strcmp(wrmode,"w") == 0)
		{
			//delay_in_ms = (unsigned long)timerval;
			//printk(KERN_ALERT"@testgpio_write user_timer: %lu'\n",user_timer);
		}
		else if(strcmp(wrmode,"i") == 0)
		{
			//delay_in_ms = (signed int)timerval;
			tasklet_schedule( &tasklet_inittimer );
		}
		else if(strcmp(wrmode,"k") == 0)
		{
			hrtimer_try_to_cancel(&hr_timer);	// cancel the timer without waiting
			tasklet_kill(&tasklet_inittimer);
			gpio_set_value(GPIO_130, LOW);		//
		}
		else if(strcmp(wrmode,"k") == 0)
		{
			hrtimer_try_to_cancel(&hr_timer);	// cancel the timer without waiting
		}
		delay_in_ms = timerval;
	}
	
	printk(KERN_ALERT "@testgpio_write counter %d\n",testgpio_dev.loopcounter++);

	status = length; // notes: somehow this need to be length else there will be looping
	mutex_unlock(&testgpio_dev.mutex);

	return status;
}

static int testgpio_open(struct inode *inode, struct file *filp)
{	
	int status = 0;
	testgpio_dev.loopcounter =0;

	printk(KERN_ALERT "@testgpio_open\n");
	if (down_interruptible(&testgpio_dev.fop_sem)) 
		return -ERESTARTSYS;

	if (!testgpio_dev.user_buff) {
		testgpio_dev.user_buff = kmalloc(USER_BUFF_SIZE, GFP_KERNEL);
		if (!testgpio_dev.user_buff) 
			status = -ENOMEM;
	}	
	up(&testgpio_dev.fop_sem);

	return status;
}



static const struct file_operations testgpio_fops = {
	.owner =	THIS_MODULE,
	.read = 	testgpio_read,
	.open =		testgpio_open,
	.write =	testgpio_write,
};

static int __init testgpio_init_GPIO(void)
{
	int status;
	
	printk(KERN_INFO "@testgpio_init_GPIO\n");

	status = omap_cfg_reg(AE2_34XX_GPIO130_OUT);
	printk(KERN_INFO "@testgpio_init_GPIO omap_cfg_reg's status %d, %d\n",
						status,AE2_34XX_GPIO130_OUT  );

	if((gpio_request(GPIO_130, "AE2_34XX_GPIO130_OUT") == 0) &&
		(gpio_direction_output(GPIO_130, HIGH)==0) )
	{
		gpio_set_value(GPIO_130, LOW); // Preset to LOW
		printk(KERN_INFO "@testgpio_init_GPIO AE2_34XX_GPIO130_OUT is good!\n");
		return SUCCESS;
	}
	else
		return ERROR;

	return status;
}

static int __init testgpio_init_cdev(void)
{
	int error;

	printk(KERN_ALERT "@testgpio_init_cdev\n");

	testgpio_dev.devt = MKDEV(0, 0);

	error = alloc_chrdev_region(&testgpio_dev.devt, 0, 1, this_driver_name);
	if (error < 0) {
		printk(KERN_ALERT "alloc_chrdev_region() failed: %d \n", 
			error);
		return -1;
	}

	cdev_init(&testgpio_dev.cdev, &testgpio_fops);
	testgpio_dev.cdev.owner = THIS_MODULE;
	
	error = cdev_add(&testgpio_dev.cdev, testgpio_dev.devt, 1);
	if (error) {
		printk(KERN_ALERT "cdev_add() failed: %d\n", error);
		unregister_chrdev_region(testgpio_dev.devt, 1);
		return -1;
	}
	return 0;
}

static int __init testgpio_init_class(void)
{
	printk(KERN_ALERT "@testgpio_init_class\n");

	testgpio_dev.class = class_create(THIS_MODULE, this_driver_name);

	if (!testgpio_dev.class) {
		printk(KERN_ALERT "class_create() failed\n");
		return -1;
	}

	if (!device_create(testgpio_dev.class, NULL, testgpio_dev.devt, NULL, 	
			this_driver_name)) {
		printk(KERN_ALERT "device_create(..., %s) failed\n",
			this_driver_name);
		class_destroy(testgpio_dev.class);
		return -1;
	}

	return 0;
}

static int __init testgpio_init(void)
{
	memset(&testgpio_dev, 0, sizeof(testgpio_dev));
	memset(&testgpio_ctl, 0, sizeof(testgpio_ctl));

	sema_init(&testgpio_dev.spi_sem, 1);
	sema_init(&testgpio_dev.fop_sem, 1);
	
	if (testgpio_init_cdev() < 0) 
		goto fail_1;
	
	if (testgpio_init_class() < 0)  
		goto fail_2;

	if(testgpio_init_GPIO() < 0)
		goto fail_4;

	return SUCCESS;


fail_3:
	device_destroy(testgpio_dev.class, testgpio_dev.devt);
	class_destroy(testgpio_dev.class);
fail_2:
	cdev_del(&testgpio_dev.cdev);
	unregister_chrdev_region(testgpio_dev.devt, 1);
fail_1:
	return ERROR;
}
module_init(testgpio_init);

static void __exit testgpio_exit(void)
{

	device_destroy(testgpio_dev.class, testgpio_dev.devt);
	class_destroy(testgpio_dev.class);

	cdev_del(&testgpio_dev.cdev);
	unregister_chrdev_region(testgpio_dev.devt, 1);

	gpio_free(GPIO_130);

	if (testgpio_dev.user_buff)
		kfree(testgpio_dev.user_buff);
}
module_exit(testgpio_exit);


MODULE_AUTHOR("Den");
MODULE_DESCRIPTION("testgpio module - an video SPI driver");
MODULE_LICENSE("GPL");
MODULE_VERSION("0.1");