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

📄 fifo_task.c

📁 A tutorial on RT-Linux
💻 C
字号:
/*  fifo_task.c  Shows how to set up a FIFO data queue for sharing data between  real-time tasks and user-level applications. The RT task creates  two FIFOs, one for commands in from the user process and one for  status back to the user process. As declared in common.h, there  are three commands: turn the speaker on, turn it off, and set the  frequency.  The periodic task just toggles the speaker port and increments  a heartbeat. Most of the work is done by a "handler" task that  is called when the command FIFO is written by the user process.  In the handler, we enable/disable the speaker using a shared global  variable, and reset the period of the speaker task if requested.  The handler also echoes the command and the heartbeat back to   the user process via the status FIFO.*/#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"#include "common.h"/*  Some newer versions define RT_SCHED_LOWEST_PRIORITY instead, so we'll  get that if necessary */#if ! defined(RT_LOWEST_PRIORITY)#if defined(RT_SCHED_LOWEST_PRIORITY)#define RT_LOWEST_PRIORITY RT_SCHED_LOWEST_PRIORITY#else#error RT_SCHED_LOWEST_PRIORITY not defined#endif#endif/*  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");#endifstatic RT_TASK rt_task;static RTIME task_period;	/* used initially and reset by FIFO messages */static int heartbeat;static int freq;static unsigned char enable_sound;#define SOUND_PORT 0x61		/* address of speaker */#define SOUND_MASK 0x02		/* bit to set/clear */static void task_code(int arg){  unsigned char sound_byte;  unsigned char toggle = 0;  enable_sound = 1;  heartbeat = 0;  freq = 100;  while (1) {    sound_byte = inb(SOUND_PORT);    if (enable_sound && toggle) {      sound_byte = sound_byte | SOUND_MASK;    } else {      sound_byte = sound_byte & ~SOUND_MASK;    }    outb(sound_byte, SOUND_PORT);    toggle = ! toggle;    heartbeat++;    rt_task_wait_period();  }  return;}static int fifo_handler(unsigned int fifo){  COMMAND_STRUCT command;  STATUS_STRUCT status;  int num;  /*    Read everything out of the fifo into our 'command' structure,    which will hold the last one read. This will clear out all the    commands, in case there are more than one queued.  */  do {    num = rtf_get(RTF_COMMAND_NUM, &command, sizeof(command));  } while (num != 0);  /*    Let's see what we got...   */  if (command.command == SOUND_ON) {    enable_sound = 1;  } else if (command.command == SOUND_OFF) {    enable_sound = 0;  } else if (command.command == SOUND_FREQ) {    /*      Here we change the period of the task by calling the familiar      rt_task_make_periodic(), which we can do on-the-fly. The period      is the inverse of the frequency, times 1e9 to convert to nanoseconds,      so we want to ensure that the frequency is positive.     */    freq = command.freq > 0 ? command.freq : 1;    task_period = 1e9 / freq;    rt_task_make_periodic(&rt_task,			  rt_get_time(),			  nano2count(task_period));  }  /* else unknown command, so ignore it */  /* now echo what we did to the status fifo */  status.command_num_echo = command.command_num;  status.freq = freq;  status.heartbeat = heartbeat;  rtf_put(RTF_STATUS_NUM, &status, sizeof(status));  return 0;}int init_module(void){  int retval;  /*    Create two FIFOs, one for commands from the user  process to our    RT task, and one from us to them. We call    int rtf_create (unsigned int fifo, int size);    rtf_create creates a real-time fifo (RT-FIFO) of initial size    'size' and assigns it the identifier 'fifo'.  'fifo' is an    integer, 0..63, that identifies the fifo on further    operations. 'fifo' may refer an existing RT-FIFO. In this case the    size is adjusted if necessary.    The RT-FIFO is a mechanism, implemented as a character device, to    communicate between real-time tasks and ordinary Linux processes. The    rtf_* functions are used by the real-time tasks; Linux processes use    standard character device access functions such as read, write, and    select.    RT-FIFO numbers 0..63 are associated with character devices    /dev/rft0..ftf63. If you write to RT-FIFO 3, the user process will    read from /dev/rtf3.   */    retval = rtf_create(RTF_COMMAND_NUM, RTF_SIZE);  if (retval) {    printk("could not create RT-FIFO %d\n", RTF_COMMAND_NUM);    return retval;  }  rtf_reset(RTF_COMMAND_NUM);	/* clear it out */  retval = rtf_create(RTF_STATUS_NUM, RTF_SIZE);  if (retval) {    printk("could not create RT-FIFO %d\n", RTF_STATUS_NUM);    return retval;  }  rtf_reset(RTF_STATUS_NUM);  /*    Associate our handler task with the command FIFO. When data is    written to this FIFO by the user process, this handler will be    called.   */  retval = rtf_create_handler(RTF_COMMAND_NUM, fifo_handler);  if (retval) {    printk("could not create RT-FIFO handler\n");    return retval;  }  retval = rt_task_init(&rt_task, task_code, 0, 1024,			RT_LOWEST_PRIORITY, 0, 0);  if (retval) {    printk("could not init task\n");    return retval;  }  /* run our sound task in one-shot mode, nominally at 100 Hz */  rt_set_oneshot_mode();  start_rt_timer(1);  task_period = nano2count(1e7); /* start at 100 Hz */  retval = rt_task_make_periodic(&rt_task,				 rt_get_time() + task_period,				 task_period);  if (retval) {    printk("could not start task\n");    return retval;  }  return 0;}void cleanup_module(void){  rt_task_delete(&rt_task);  /*    Remove our FIFOs   */  rtf_destroy(RTF_STATUS_NUM);  rtf_destroy(RTF_COMMAND_NUM);  stop_rt_timer();  return;}

⌨️ 快捷键说明

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