⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ledclock_task.c

📁 A tutorial on RT-Linux
💻 C
字号:
/*  ledclock_task.c  Adapted from software written by Stuart Hughes, formerly of Lineo, Inc.,  shughes@lineo.com, seh@zee2.com. Released under the Gnu General Public  License. */#include <linux/kernel.h>#include <linux/module.h>#include <linux/version.h>#include <linux/sched.h>#include <asm/io.h>#include "rtai.h"#include "rtai_sched.h"#include "rtai_fifos.h"/*  THIS SOFTWARE WAS PRODUCED BY EMPLOYEES OF THE U.S. GOVERNMENT AS PART  OF THEIR OFFICIAL DUTIES AND IS IN THE PUBLIC DOMAIN.  When linked into the Linux kernel the resulting work is GPL. You  are free to use this work under other licenses if you wish.*/#if LINUX_VERSION_CODE > KERNEL_VERSION(2,4,0)MODULE_LICENSE("GPL");#endif#define PARPORT_BASE_ADDRESS 0x378#define PARPORT_CTRL_ADDRESS (PARPORT_BASE_ADDRESS + 2)#define PARPORT_IRQ 7#define NCHARS		16#define BASE_PER (1e9 / 7000)	/* 142857 */struct data_ {  int irq;  int count;  int lpt_ctrl;  long long t_diff;  long long t_prev;  long long t_short;  long long t_long;  char pattern[1024];} d = {7, 4, 0, 0, 0, 0, 0, {0xff, 0x00, 0xff, 0x00}};RT_TASK master_task;static void master_function(int arg){  int i, j, cnt, os, cyc;  char *ptr;  os = 0;  while (1) {    rt_task_suspend(&master_task);    /*      Set the start time based on which tempo we're on, and use BASE_PER      as the inter-column period.     */    rt_task_make_periodic(&master_task, nano2count(d.t_long + 34000000), nano2count(BASE_PER));    cnt = d.count;    if (cnt > NCHARS * 8) {      cyc = 1;      os++;      if (os > cnt) {	os = 0;      }    } else {      cyc = 0;      os = 0;    }    ptr = &d.pattern[os];    for (i = 0; i < NCHARS; i++) {      for (j = 0; j < 16; j++) {	if (cyc && (ptr > &d.pattern[cnt])) {	  ptr = d.pattern;	}	rt_task_wait_period();	if (j % 2) {	  outb(~*ptr++, PARPORT_BASE_ADDRESS);	} else {	  outb(0xff, PARPORT_BASE_ADDRESS);	}      }    }    outb(0xff, PARPORT_BASE_ADDRESS);  }  return;}int fifo_handler(unsigned int fifo){  memset(d.pattern, 0, sizeof(d.pattern));  d.count = rtf_get(fifo, d.pattern, sizeof(d.pattern));  return 0;}void slave_isr(void){  long long now;  /* you get 2 pulse close together (42.5), the pattern repeats every     80ms, this is used to get the direction of travel */  now = rt_get_time_ns();  d.t_diff = now - d.t_prev;  d.t_prev = now;  if (d.t_diff < 50000000LL) {    d.t_short = now;    return;  }  d.t_long = now;  rt_task_resume(&master_task);}static void disable_parport_int(void){  /* clear bit 4 of the parallel port control register, two bytes up     from the base address */  outb(inb(PARPORT_BASE_ADDRESS+2) & ~0x10, PARPORT_BASE_ADDRESS+2);}static void enable_parport_int(void){  /* set bit 4 of the parallel port control register, two bytes up     from the base address */  outb(inb(PARPORT_BASE_ADDRESS+2) | 0x10, PARPORT_BASE_ADDRESS+2);}int init_module(void){  int retval;  retval = rtf_create(0, 1024);  if (retval) {    printk("can't create fifo\n");    return retval;  }  retval = rtf_create_handler(0, &fifo_handler);  if (retval) {    printk("can't create fifo handler\n");    return retval;  }  /* create irq handler */  rt_free_global_irq(PARPORT_IRQ);  retval = rt_request_global_irq(PARPORT_IRQ, slave_isr);  if (retval) {    printk("can't attach to IRQ\n");    return retval;  }  rt_startup_irq(PARPORT_IRQ);  enable_parport_int();  /* clear the leds */  outb(0xFF, PARPORT_BASE_ADDRESS);  retval = rt_task_init(&master_task, master_function, 0, 			3000, 10, 0, 0);  if (retval) {    printk("can't initialize master task\n");    return retval;  }  rt_set_oneshot_mode();  start_rt_timer(1);  retval = rt_task_make_periodic(&master_task, rt_get_time(), 1);  if (retval) {    printk("can't start master task\n");    return retval;  }  return 0;}void cleanup_module(void){  rt_task_delete(&master_task);  disable_parport_int();  rt_free_global_irq(PARPORT_IRQ);  rtf_destroy(0);  return;}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -