Hi all. I am developing an app where I require to toggle I/O pins with 1 ms intervals and 100 us latency. To explain better, consider this algorithm: (1) When a I/O input pin goes high, set an output pin to '1'. (latency 100 us) (2) Wait 1 ms. (3) Set I/O pin low (toggle the output pin) (latency 100 us) From a rough survey, I can think of three solutions: (1) Use nanosleep() : Is it possible to have a 100 us tolerance with nanosleep() and a delay of 1 ms? What is the heartbeat rate/quantum duration for mini2440? (consider it is the only user process running) (2) Use RTLinux : How? Is it as easy as : X-compile and port? (3) Use the ARM9 timer: How to access the processor timer from C? Do I need another driver? So can anyone share a program where they have used delays? Thank you.
High resolution delays/timers
1. delay 1ms shoudn't be a problem but 100us tolerance (need to be checked not sure about that) 3. you can use high resolution timer in kernel and switch pin marek
Hi, thanks for replying. "you can use high resolution timer in kernel and switch pin" Can you explain a little bit more, a psudeo-code, perhaps? Thank you.
start kernel timer for 1ms and in callback function just swap output of PIN. Measure with scope if it fit to you requirements. marek
See the module #include <linux/kernel.h> #include <linux/module.h> #include <linux/slab.h> #include <linux/input.h> #include <linux/init.h> #include <linux/errno.h> #include <linux/serio.h> #include <linux/delay.h> #include <linux/clk.h> #include <linux/wait.h> #include <linux/sched.h> #include <linux/cdev.h> #include <linux/miscdevice.h> #include <asm/io.h> #include <asm/irq.h> #include <asm/uaccess.h> #include <mach/map.h> #include <mach/regs-clock.h> #include <mach/regs-gpio.h> #include <plat/regs-timer.h> #include <plat/regs-adc.h> #define __TIMREG(name) (*(volatile unsigned long *)(BaseAddr + name)) #define TIMCON __TIMREG(S3C2410_TCON) #define DEVICE_NAME "tim" typedef struct { int delay; } TIM_DEV; static TIM_DEV TimDev; int RUNNED = 0; int test; static irqreturn_t TimerINTHandler(int irq,void *TimDev) { unsigned TimerINTControl; TimerINTControl = readl(S3C_TINT_CSTAT); RUNNED ++; TimerINTControl |= S3C_TINT_CSTAT_T2INT; writel(TimerINTControl, S3C_TINT_CSTAT); return IRQ_HANDLED; } static ssize_t TimerRead(struct file *filp, char *buffer, size_t count, loff_t *ppos) { char str[20]; size_t len; len = sprintf(str, "%d\n", RUNNED); copy_to_user(buffer, str, len); if (*ppos == 0) { *ppos+=len; return len; } else { return 0; } } static struct file_operations dev_fops = { owner: THIS_MODULE, read: TimerRead, }; static struct miscdevice misc = { .minor = MISC_DYNAMIC_MINOR, .name = DEVICE_NAME, .fops = &dev_fops, }; static int __init dev_init(void) { int ret; unsigned TimerControl; unsigned TimerINTControl; unsigned TimerCNTB; unsigned TimerCMPB; RUNNED = 0; TimerControl = readl(S3C_TCON); TimerINTControl = readl(S3C_TINT_CSTAT); TimerCNTB = readl(S3C_TCNTB(2)); TimerCMPB = readl(S3C_TCMPB(2)); TimerCNTB = 0x0000100; TimerCMPB = 0x0000100; writel(TimerCNTB, S3C_TCNTB(2)); writel(TimerCMPB, S3C_TCMPB(2)); //TimerControl |= S3C_TCON_T2RELOAD; TimerControl |= S3C_TCON_T2MANUALUPD; TimerControl &= ~S3C_TCON_T2INVERT; //TimerControl |= S3C_TCON_T2START; TimerINTControl |= S3C_TINT_CSTAT_T2INTEN; writel(TimerControl, S3C_TCON); writel(TimerINTControl, S3C_TINT_CSTAT); TimerControl = readl(S3C_TCON); TimerControl |= S3C_TCON_T2RELOAD; TimerControl &= ~S3C_TCON_T2MANUALUPD; TimerControl |= S3C_TCON_T2START; writel(TimerControl, S3C_TCON); ret = request_irq(IRQ_TIMER2, TimerINTHandler, IRQF_SHARED, DEVICE_NAME, &TimDev); if (ret) { return ret; } ret = misc_register(&misc); printk (DEVICE_NAME"\tinitialized\n"); return ret; } static void __exit dev_exit(void) { free_irq(IRQ_TIMER2, &TimDev); misc_deregister(&misc); } module_init(dev_init); module_exit(dev_exit); MODULE_LICENSE("GPL"); MODULE_AUTHOR("Muhammad Usama Masood");