Download presentation
1
RT_FIFO, Device driver
2
Outline Introduction of RT_FIFOs Device driver RT_FIFO Example
3
Intro. of RT_FIFOs(1) The RT_FIFO is a mechanism, implemented as a character device, to communicate between realtime tasks and ordinary Linux processes. RT FIFO User Process RT Process RT FIFO
4
Intro. of RT_FIFOs(2) In the real-time task interface, read/write must be atomic and non-blocking. In Linux user processes, see RT_FIFOs as ordinary character devices
5
Requirements of a device driver
Compile gcc –DMODULE –D__KERNEL__ -o dst src Code Setup file_opreation structure Register_chrdev / register_blkdev / misc_register in init_module
6
Linux file_ops structure
struct file_operations { int (*seek) (struct inode *, struct file *, off_t, int); int (*read) (struct inode *, struct file *, char, int); int (*write) (struct inode *, struct file *, off_t, int); int (*readdir) (struct inode *, struct file *, struct dirent *, int); int (*ioctl) (struct inode *, struct file *, unsigned int, unsigned long); int (*select) (struct inode *, struct file *, int , select_table *); int (*mmap) (struct inode *, struct file *, struct vm_area_struct *); int (*open) (struct inode *, struct file *); int (*release) (struct inode *, struct file *); int (*fsync) (struct inode *, struct file *); int (*fasync) (struct inode *, struct file *, int); int (*check_media_change) (struct inode *, struct file *); int (*revalidate) (dev_t dev); }
7
register_chrdev int register_chrdev(unsigned int major, const char * name, struct file_operations *fops){ if (major == 0) { write_lock(&chrdevs_lock); for (major = MAX_CHRDEV-1; major > 0; major--) { if (chrdevs[major].fops == NULL) { chrdevs[major].name = name; chrdevs[major].fops = fops; write_unlock(&chrdevs_lock); return major; } return -EBUSY; if (major >= MAX_CHRDEV) return -EINVAL; ………………………………………………… return 0;
8
Init_module int init_module(void){
if (register_chrdev (MAJOR, “name”, &fops)){ printk (“%s: unable to get major %d\n", name, MAJOR); return -EIO; } return 0; void cleanup_module(void){ unregister_chrdev(MAJOR, “name");
9
RT_FIFO Install RT_FIFO module FIFO structure & file_ops
Real-time part Non-real-time part
10
RT_FIFO init_module Flow
register_chrdev == 0 yes no get_soft_irq Irq > 0 no yes rtl_register_chrdev == 0 yes no return 0 unregister_chrdev
11
RT_FIFO init_module int init_module(void){ int ret; ret = rtf_init();
if (ret < 0) return ret; #ifdef CONFIG_RTL_POSIX_IO if (rtl_register_chrdev (RTF_MAJOR, "rtf", &rtl_fifo_fops)) { printk ("RT-FIFO: unable to get RTLinux major %d\n", RTF_MAJOR); rtf_uninit(); return -EIO; } #endif return 0; void cleanup_module(void){ rtl_unregister_chrdev(RTF_MAJOR, "rtf"); Install non-real-time device driver Install real-time device driver
12
rtf_init(); int rtf_init (void){ int irq = -1, i;
if (register_chrdev (RTF_MAJOR, "rtf", &rtf_fops)) { printk ("RT-FIFO: unable to get major %d\n", RTF_MAJOR); return -EIO; } irq = rtl_get_soft_irq (fifo_irq_handler, "RTLinux FIFO"); if (irq > 0) { rtl_fifo_irq = irq; } else { unregister_chrdev (RTF_MAJOR, "rtf"); printk ("Can't get an irq for rt fifos"); return 0;
13
RT_FIFO Install RT_FIFO module FIFO structure & file_ops
Real-time part Non-real-time part
14
Struct rt_fifo_struct
int allocated; int bidirectional; int user_open; struct task_struct *opener; char *base; int bufsize; int start; int len; spinlock_t fifo_spinlock; int (*user_handler) (unsigned int fifo); int (*rt_handler) (unsigned int fifo); int (*user_ioctl)(unsigned int fifo, unsigned int cmd, unsigned long arg); struct module *creator; struct wait_queue *wait; };
15
rtl_file_ops structure
struct rtl_file_operations { loff_t (*llseek) (struct rtl_file *, loff_t, int); ssize_t (*read) (struct rtl_file *, char *, size_t, loff_t *); ssize_t (*write) (struct rtl_file *, const char *, size_t, loff_t *); int (*ioctl) (struct rtl_file *, unsigned int, unsigned long); int (*mmap) (struct rtl_file *, void *start, size_t length, int prot , int flags, off_t offset, caddr_t *result); int (*open) (struct rtl_file *); int (*release) (struct rtl_file *); };
16
Linux file_ops structure
struct file_operations { int (*seek) (struct inode *, struct file *, off_t, int); int (*read) (struct inode *, struct file *, char, int); int (*write) (struct inode *, struct file *, off_t, int); int (*readdir) (struct inode *, struct file *, struct dirent *, int); int (*ioctl) (struct inode *, struct file *, unsigned int, unsigned long); int (*select) (struct inode *, struct file *, int , select_table *); int (*mmap) (struct inode *, struct file *, struct vm_area_struct *); int (*open) (struct inode *, struct file *); int (*release) (struct inode *, struct file *); int (*fsync) (struct inode *, struct file *); int (*fasync) (struct inode *, struct file *, int); int (*check_media_change) (struct inode *, struct file *); int (*revalidate) (dev_t dev); }
17
RT_FIFO Install RT_FIFO module FIFO structure & file_ops
Real-time part Non-real-time part
18
rtl_fifo_fops cont. static struct rtl_file_operations rtl_fifo_fops =
{ NULL, // llseek rtl_rtf_read, // read rtl_rtf_write, // write rtl_rtf_ioctl, // ioctl NULL, // mmap rtl_rtf_open, // open rtl_rtf_release // release };
19
rtl_rtf_open & rtl_rtf_release
static int rtl_rtf_open (struct rtl_file *filp){ if (!(filp->f_flags & O_NONBLOCK)) { return -EACCES; } if( (filp->f_flags & O_CREAT) && !RTF_ALLOCATED(filp->f_minor)){ __rtf_create(filp->f_minor, RTF_DEFAULT_SIZE, &__this_module); if(!RTF_ALLOCATED(filp->f_minor)){ return -EUNATCH; return 0; better be calling from Linux and not RT mode unless there are preallocted fifos still static int rtl_rtf_release (struct rtl_file *filp){ int minor = filp->f_minor; char *old = RTF_BASE(minor); if (RTF_ALLOCATED(minor) && old && find_prealloc(old)) { rtf_destroy(minor); } return 0;
20
rtl_rtf_read rtf_get
int rtf_get(unsigned int minor, void *buf, int count){ int chars = 0, size = 0, read = 0; char *pipebuf; rtl_spin_lock_irqsave(&RTF_SPIN(minor), interrupt_state); while (count > 0 && (size = RTF_LEN(minor))) { ………read circular queue…… count -= chars; memcpy(buf, pipebuf, chars); buf += chars; } rtl_spin_unlock_irqrestore(&RTF_SPIN(minor), interrupt_state); if(*RTF_RT_HANDLER(minor)){ (*RTF_RT_HANDLER(minor))(minor); if (RTF_USER_OPEN(minor)) { fifo_wake_sleepers(minor); return read;
21
rtl_rtf_write rtf_put
int rtf_put(unsigned int minor, void *buf, int count){ int chars = 0, free = 0, written = 0; char *pipebuf; rtl_spin_lock_irqsave(&RTF_SPIN(minor), interrupt_state); if (RTF_FREE(minor) < count) { rtl_spin_unlock_irqrestore(&RTF_SPIN(minor), interrupt_state); return -ENOSPC; } while (count > 0 && (free = RTF_FREE(minor))) { ………write circular queue…… memcpy(pipebuf, buf, chars); buf += chars; if((*RTF_RT_HANDLER(minor))) (*RTF_RT_HANDLER(minor))(minor); if (RTF_USER_OPEN(minor)) fifo_wake_sleepers(minor - (RTF_BI(minor) < 0)); return written;
22
rtl_rtf_ioctl static int rtl_rtf_ioctl (struct rtl_file *filp, unsigned int req, unsigned long arg){ int minor = RTL_MINOR_FROM_FILEPTR(filp); if (!RTF_ALLOCATED(minor)) { return -EINVAL; } if (req == RTF_SETSIZE) { if (rtf_resize(minor, arg) < 0) { } else { return 0;
23
RT_FIFO Install RT_FIFO module FIFO structure & file_ops
Real-time part Non-real-time part
24
rtf_fops cont. static struct file_operations rtf_fops = {
llseek: rtf_llseek, read: rtf_read, write: rtf_write, poll: rtf_poll, ioctl: rtf_ioctl, open: rtf_open, release: rtf_release, };
25
rtf_open& rtf_release
static int rtf_open(struct inode *inode, struct file *filp){ unsigned int minor = MINOR(inode->i_rdev); RTF_OPENER(minor) = current; RTF_USER_OPEN(minor)++; if (RTF_ADDR(minor)->creator) { __MOD_INC_USE_COUNT(RTF_ADDR(minor)->creator); } return 0; static int rtf_release(struct inode *inode, struct file *file){ unsigned int minor = MINOR(inode->i_rdev); RTF_USER_OPEN(minor)--; if (RTF_ADDR(minor)->creator) { __MOD_DEC_USE_COUNT(RTF_ADDR(minor)->creator); } return 0;
26
rtf_read Block until data available copy fifo content to user space
static ssize_t rtf_read(struct file *filp, char *buf, size_t count, loff_t* ppos){ ………………………………….. minor = minor + RTF_BI(minor); if…………… while (RTF_EMPTY(minor) ) { if (signal_pending(current)) return -ERESTARTSYS; fifo_setup_sleep(minor); interruptible_sleep_on_timeout(&RTF_WAIT(minor), RTL_FIFO_TIMEOUT); } while (count > 0 && (size = RTF_LEN(minor))) { ……read from queue…… copy_to_user(buf, pipebuf, chars); rtl_spin_lock_irqsave(&RTF_SPIN(minor), interrupt_state); RTF_START(minor) += chars; RTF_START(minor) = RTF_WRAP(minor, RTF_START(minor)); RTF_LEN(minor) -= chars; rtl_spin_unlock_irqrestore(&RTF_SPIN(minor), interrupt_state); if (read) { if((*RTF_HANDLER(minor))){ ………………………… Block until data available copy fifo content to user space
27
rtf_write Block until able to write if……………… copy buffer to fifo
static ssize_t rtf_write(struct file *filp, const char *buf, size_t count, loff_t* ppos) { …………………… while (count > 0) { while (RTF_FREE(minor) < free) { if…………………… fifo_setup_sleep(minor); interruptible_sleep_on_timeout(&RTF_WAIT(minor), RTL_FIFO_TIMEOUT); } while (count > 0 && (free = RTF_FREE(minor))) { ………..write to queue…… rtl_spin_lock_irqsave(&RTF_SPIN(minor), interrupt_state); pipebuf = RTF_BASE(minor) + RTF_END(minor); copy_from_user(pipebuf, buf, chars); RTF_LEN(minor) += chars; rtl_spin_unlock_irqrestore(&RTF_SPIN(minor), interrupt_state); free = 1; if……………… return result; return written; Block until able to write copy buffer to fifo
28
Example(rt_np) pthread_t thread; void * start_routine(void *arg){
struct sched_param p; int status; p . sched_priority = 1; pthread_setschedparam (pthread_self(), SCHED_FIFO, &p); pthread_make_periodic_np (pthread_self(), gethrtime(), ); while (1){ sprintf(buf, “[%d]\n“),; status = rtf_put(0, buf, 1024); pthread_wait_np(); } return 0; int init_module(void) { rtf_create(0, 1024*1024); return pthread_create (&thread, NULL, start_routine, 0); void cleanup_module(void) { rtf_destroy(0); pthread_delete_np (thread);
29
Result (rt_np) [root@rtlinux rtlinux]# insmod fifo.o
Run a user application root]# lsmod Module Size Used by Tainted: P fifo rtl_sched [fifo] rtl_fifo [fifo] rtl_posixio [rtl_fifo] rtl_time [fifo rtl_sched rtl_posixio] rtl [rtl_sched rtl_fifo rtl_posixio rtl_time] mbuff (unused)
30
Example(rt_posixio) int fd; pthread_t thread;
void * start_routine(void *arg){ struct sched_param p; int status, i=0; p.sched_priority = 1; pthread_setschedparam (pthread_self(), SCHED_FIFO, &p); pthread_make_periodic_np (pthread_self(), gethrtime(), ); while (1){ sprintf(buf, "[%d] fd = %d\n“, i++, fd); status = write(fd, buf, 1024); pthread_wait_np(); } return 0; int init_module(void) { fd = open("/dev/rtf10", O_NONBLOCK | O_CREAT ); if(fd) return -1; return pthread_create (&thread, NULL, start_routine, 0); void cleanup_module(void) { close(fd); pthread_delete_np (thread);
31
Result(rt_posixio) [root@rtlinux rtlinux]# insmod fifo_test.o
Run a user application include]# lsmod Module Size Used by Tainted: P fifo_test (unused) fifo (unused) rtl_sched [fifo_test fifo] rtl_fifo [fifo] rtl_posixio [fifo_test rtl_fifo] rtl_time [fifo_test fifo rtl_sched rtl_posixio] rtl [rtl_sched rtl_fifo rtl_posixio rtl_time] mbuff (unused)
Similar presentations
© 2024 SlidePlayer.com. Inc.
All rights reserved.