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

31
RT_FIFO, RT_FIFO, Device driver Device driver

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

Page 1: RT_FIFO, Device driver. Outline Introduction of RT_FIFOs Device driver RT_FIFO Example.

RT_FIFO, RT_FIFO, Device driverDevice driver

RT_FIFO, RT_FIFO, Device driverDevice driver

Page 2: RT_FIFO, Device driver. Outline Introduction of RT_FIFOs Device driver RT_FIFO Example.

Outline• Introduction of RT_FIFOs• Device driver• RT_FIFO• Example

Page 3: 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, imple

mented as a character device, to communicate between realtime tasks and ordinary Linux processes.

User Process RT Process

RT FIFO

RT FIFO

Page 4: RT_FIFO, Device driver. Outline Introduction of RT_FIFOs Device driver RT_FIFO Example.

Intro. of RT_FIFOs(2)• In the real-time task interface, read/w

rite must be atomic and non-blocking.• In Linux user processes, see RT_FIFOs

as ordinary character devices

Page 5: RT_FIFO, Device driver. Outline Introduction of RT_FIFOs Device driver RT_FIFO Example.

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

Page 6: RT_FIFO, Device driver. Outline Introduction of RT_FIFOs Device driver RT_FIFO Example.

Linux file_ops structurestruct 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);

}

Page 7: RT_FIFO, Device driver. Outline Introduction of RT_FIFOs Device driver RT_FIFO Example.

register_chrdevint 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;}

Page 8: RT_FIFO, Device driver. Outline Introduction of RT_FIFOs Device driver RT_FIFO Example.

Init_moduleint 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");

}

Page 9: RT_FIFO, Device driver. Outline Introduction of RT_FIFOs Device driver RT_FIFO Example.

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

Page 10: RT_FIFO, Device driver. Outline Introduction of RT_FIFOs Device driver RT_FIFO Example.

RT_FIFO init_module Flowregister_chrdev == 0

Irq > 0

unregister_chrdev

get_soft_irq

yes

no

no

yes

rtl_register_chrdev == 0yes

no

return 0

Page 11: RT_FIFO, Device driver. Outline Introduction of RT_FIFOs Device driver RT_FIFO Example.

RT_FIFO init_moduleint 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

Page 12: RT_FIFO, Device driver. Outline Introduction of RT_FIFOs Device driver RT_FIFO Example.

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

Page 13: RT_FIFO, Device driver. Outline Introduction of RT_FIFOs Device driver RT_FIFO Example.

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

Page 14: RT_FIFO, Device driver. Outline Introduction of RT_FIFOs Device driver RT_FIFO Example.

Struct rt_fifo_structstruct 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;};

Page 15: RT_FIFO, Device driver. Outline Introduction of RT_FIFOs Device driver RT_FIFO Example.

rtl_file_ops structurestruct 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 *);};

Page 16: RT_FIFO, Device driver. Outline Introduction of RT_FIFOs Device driver RT_FIFO Example.

Linux file_ops structurestruct 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);

}

Page 17: RT_FIFO, Device driver. Outline Introduction of RT_FIFOs Device driver RT_FIFO Example.

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

Page 18: RT_FIFO, Device driver. Outline Introduction of RT_FIFOs Device driver RT_FIFO Example.

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

Page 19: RT_FIFO, Device driver. Outline Introduction of RT_FIFOs Device driver RT_FIFO Example.

rtl_rtf_open & rtl_rtf_releasestatic 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;}

Page 20: RT_FIFO, Device driver. Outline Introduction of RT_FIFOs Device driver RT_FIFO Example.

rtl_rtf_read rtf_getint 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;}

Page 21: RT_FIFO, Device driver. Outline Introduction of RT_FIFOs Device driver RT_FIFO Example.

rtl_rtf_write rtf_putint 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;}

Page 22: RT_FIFO, Device driver. Outline Introduction of RT_FIFOs Device driver RT_FIFO Example.

rtl_rtf_ioctlstatic 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;}

Page 23: RT_FIFO, Device driver. Outline Introduction of RT_FIFOs Device driver RT_FIFO Example.

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

Page 24: RT_FIFO, Device driver. Outline Introduction of RT_FIFOs Device driver RT_FIFO Example.

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

Page 25: RT_FIFO, Device driver. Outline Introduction of RT_FIFOs Device driver RT_FIFO Example.

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

Page 26: RT_FIFO, Device driver. Outline Introduction of RT_FIFOs Device driver RT_FIFO Example.

rtf_readstatic 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

Page 27: RT_FIFO, Device driver. Outline Introduction of RT_FIFOs Device driver RT_FIFO Example.

rtf_writestatic 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

Page 28: RT_FIFO, Device driver. Outline Introduction of RT_FIFOs Device driver RT_FIFO Example.

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

Page 29: RT_FIFO, Device driver. Outline Introduction of RT_FIFOs Device driver RT_FIFO Example.

Result (rt_np)

[root@rtlinux rtlinux]# insmod fifo.o

Run a user application[root@rtlinux root]# lsmodModule Size Used by Tainted: Pfifo 2148 1rtl_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)

Page 30: RT_FIFO, Device driver. Outline Introduction of RT_FIFOs Device driver RT_FIFO Example.

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

Page 31: RT_FIFO, Device driver. Outline Introduction of RT_FIFOs Device driver RT_FIFO Example.

Result(rt_posixio)

[root@rtlinux rtlinux]# insmod fifo_test.o

Run a user application[root@rtlinux include]# lsmodModule Size Used by Tainted: Pfifo_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)