1 / 31

RT_FIFO, Device driver

RT_FIFO, Device driver. Outline. Introduction of RT_FIFOs Device driver RT_FIFO Example. 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.

Download Presentation

RT_FIFO, Device driver

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  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__ -odst 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 *, unsignedint, 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; } } write_unlock(&chrdevs_lock); return -EBUSY; } if (major >= MAX_CHRDEV) return -EINVAL; ………………………………………………… return0; }

  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; } return0; } 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){ #ifdef CONFIG_RTL_POSIX_IO rtl_unregister_chrdev(RTF_MAJOR, "rtf"); #endif rtf_uninit(); } 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 -EIO; } return0; }

  13. RT_FIFO • Install RT_FIFO module • FIFO structure & file_ops • Real-time part • Non-real-time part

  14. Struct rt_fifo_struct 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 *, unsignedint, 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 staticint 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; } return0; } 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); } return0; }

  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; } 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 - (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) { return -EINVAL; } } else { return -EINVAL; } return0; }

  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); } return0; } 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); } return0; }

  26. rtf_read 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 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(), 10000000); while (1){ sprintf(buf, “[%d]\n“),; status = rtf_put(0, buf, 1024); pthread_wait_np(); } return0; } 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@rtlinux root]# lsmod Module Size Used by Tainted: P fifo 2148 1 rtl_sched 30368 0 [fifo] rtl_fifo 10784 0 [fifo] rtl_posixio 8052 0 [rtl_fifo] rtl_time 7084 0 [fifo rtl_sched rtl_posixio] rtl 21200 0 [rtl_sched rtl_fifo rtl_posixio rtl_time] mbuff 8684 0 (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(), 10000000); while (1){ sprintf(buf, "[%d] fd = %d\n“, i++, fd); status = write(fd, buf, 1024); pthread_wait_np(); } return0; } 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 [root@rtlinux include]# lsmod Module Size Used by Tainted: P fifo_test 2564 0 (unused) fifo 2148 0 (unused) rtl_sched 30368 0 [fifo_test fifo] rtl_fifo 10784 2 [fifo] rtl_posixio 8052 0 [fifo_test rtl_fifo] rtl_time 7084 0 [fifo_test fifo rtl_sched rtl_posixio] rtl 21200 0 [rtl_sched rtl_fifo rtl_posixio rtl_time] mbuff 8684 0 (unused)

More Related