Presentation is loading. Please wait.

Presentation is loading. Please wait.

RT_FIFO, Device driver. Outline Introduction of RT_FIFOs Device driver RT_FIFO Example.

Similar presentations


Presentation on theme: "RT_FIFO, Device driver. Outline Introduction of RT_FIFOs Device driver RT_FIFO Example."— 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. 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; } write_unlock(&chrdevs_lock); 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 Irq > 0 unregister_chrdev get_soft_irq yes no yes rtl_register_chrdev == 0 yes no return 0

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; } 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 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; } 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; } 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 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(), ); 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) 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) 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)


Download ppt "RT_FIFO, Device driver. Outline Introduction of RT_FIFOs Device driver RT_FIFO Example."

Similar presentations


Ads by Google