📄 rtai.c
字号:
rtai_trap_handler[trap] = handler; } return old_handler;}void rt_free_rtai_trap_handler(int trap){ rtai_trap_handler[trap] = NULL;}/* Here are the trapped pic functions for Linux interrupt handlers. */static void shared_unmask_irq(unsigned int irq){ unsigned long flags; flags = rt_spin_lock_irqsave(&global.ic_lock); if (linux_irqs[irq].pend_count && (processor[hard_cpu_id()].intr_flag & I_BIT)) { rt_spin_unlock_irqrestore(flags, &global.ic_lock); linux_sti(); } else rt_spin_unlock_irqrestore(flags, &global.ic_lock);}/* Request and free interrupts, system requests and interprocessors messages *//* Request for regular Linux irqs also included. They are nicely chained to *//* Linux, forcing sharing with any already installed handler, so that we can *//* have an echo from Linux for global handlers. We found that usefull during *//* debug, but can be nice for a lot of other things, e.g. see the jiffies *//* recovery in rtai_sched.c, and the global broadcast to local apic timers. */static unsigned long irq_action_flags[NR_IRQS];static int chained_to_linux[NR_IRQS];int rt_request_global_irq_ext(unsigned int irq, void (*handler)(int, void *, struct pt_regs *), void *dev_id){ unsigned long flags; if (irq >= NR_IRQS || !handler) { return -EINVAL; } if (global_irq[irq].handler != NULL) { return -EBUSY; } flags = hard_lock_all(); irq_desc[irq].mask_ack = do_nothing_picfun; irq_desc[irq].mask = do_nothing_picfun; irq_desc[irq].unmask = shared_unmask_irq; shadow_irq_desc[irq].disable_depth = 1; global_irq[irq].handler = handler; global_irq[irq].dev_id = dev_id; hard_unlock_all(flags); return 0;}/* We don't share IRQ's under RT, so, don't need the dev-pointer. */int rt_free_global_irq(unsigned int irq){ unsigned long flags; if (irq >= NR_IRQS || !global_irq[irq].handler) { return -EINVAL; } flags = hard_lock_all(); irq_desc[irq].mask_ack = linux_mask_ack; irq_desc[irq].mask = ic_mask_irq[irq]; irq_desc[irq].unmask = ic_unmask_irq[irq]; global_irq[irq].handler = NULL; hard_unlock_all(flags); return 0;}int rt_request_linux_irq(unsigned int irq, void (*linux_handler)(int irq, void *dev_id, struct pt_regs *regs), char *linux_handler_id, void *dev_id){ unsigned long flags;//## // if (irq == TIMER_8254_IRQ) {// processor[0].trailing_irq_handler = linux_handler;// return 0;// } if (irq >= NR_IRQS || !linux_handler) { return -EINVAL; } save_flags_cli(flags); if (!chained_to_linux[irq]++) { if (irq_desc[irq].action) { irq_action_flags[irq] = irq_desc[irq].action->flags; irq_desc[irq].action->flags |= SA_SHIRQ; } } restore_flags(flags); request_irq(irq, linux_handler, SA_SHIRQ, linux_handler_id, dev_id); return 0;}int rt_free_linux_irq(unsigned int irq, void *dev_id){ unsigned long flags;//##// if (irq == TIMER_8254_IRQ) {// processor[0].trailing_irq_handler = 0;// return 0;// } if (irq >= NR_IRQS || !chained_to_linux[irq]) { return -EINVAL; } free_irq(irq, dev_id); save_flags_cli(flags); if (!(--chained_to_linux[irq]) && irq_desc[irq].action) { irq_desc[irq].action->flags = irq_action_flags[irq]; } restore_flags(flags); return 0;}int rt_request_srq(unsigned int label, void (*rtai_handler)(void), long long (*user_handler)(unsigned int whatever)){ unsigned long flags; unsigned int srq; if (!rtai_handler) { return -EINVAL; } flags = rt_spin_lock_irqsave(&global.data_lock); for (srq = 2; srq < NR_SYSRQS; srq++) { if (!(sysrq[srq].rtai_handler)) { sysrq[srq].rtai_handler = rtai_handler; sysrq[srq].label = label; if (user_handler) { sysrq[srq].user_handler = user_handler; if (!rthal.do_SRQ) { rthal.do_SRQ = dispatch_srq; } } rt_spin_unlock_irqrestore(flags, &global.data_lock); return srq; } } rt_spin_unlock_irqrestore(flags, &global.data_lock); return -EBUSY;}int rt_free_srq(unsigned int srq){ unsigned long flags; flags = rt_spin_lock_irqsave(&global.data_lock); if (srq < 2 || srq >= NR_SYSRQS || !sysrq[srq].rtai_handler) { rt_spin_unlock_irqrestore(flags, &global.data_lock); return -EINVAL; } sysrq[srq].rtai_handler = 0; sysrq[srq].user_handler = 0; sysrq[srq].label = 0; for (srq = 2; srq < NR_SYSRQS; srq++) { if (sysrq[srq].user_handler) { rt_spin_unlock_irqrestore(flags, &global.data_lock); return 0; } } if (rthal.do_SRQ) { rthal.do_SRQ = 0; } rt_spin_unlock_irqrestore(flags, &global.data_lock); return 0;}int rt_is_linux(void){ return test_bit(hard_cpu_id(), (void *)&global.used_by_linux);}void rt_switch_to_linux(int cpuid){ TRACE_RTAI_SWITCHTO_LINUX(cpuid); set_bit(cpuid, &global.used_by_linux); processor[cpuid].intr_flag = processor[cpuid].linux_intr_flag;}void rt_switch_to_real_time(int cpuid){ TRACE_RTAI_SWITCHTO_RT(cpuid); if ( global.used_by_linux & (1<<cpuid) ) processor[cpuid].linux_intr_flag = processor[cpuid].intr_flag; processor[cpuid].intr_flag = 0; clear_bit(cpuid, &global.used_by_linux);}/* RTAI mount-unmount functions to be called from the application to *//* initialise the real time application interface, i.e. this module, only *//* when it is required; so that it can stay asleep when it is not needed */#ifdef CONFIG_RTAI_MOUNT_ON_LOAD#define rtai_mounted 1#elsestatic int rtai_mounted;#endif// Trivial, but we do things carefully, the blocking part is relatively short,// should cause no troubles in the transition phase.// All the zeroings are strictly not required as mostly related to static data.// Done esplicitly for emphasis. Simple, just lock and grab everything from// Linux.void __rt_mount_rtai(void){ unsigned long flags, i; flags = hard_lock_all(); rthal.do_IRQ = dispatch_irq; rthal.do_SRQ = dispatch_srq; rthal.do_TRAP = dispatch_trap; rthal.disint = linux_cli; rthal.enint = linux_sti; rthal.getflags = linux_save_flags; rthal.setflags = linux_restore_flags; rthal.getflags_and_cli = linux_save_flags_and_cli; rthal.fdisint = linux_cli; rthal.fenint = linux_sti; rthal.copy_back = rtai_just_copy_back;#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,21) rthal.getflags_and_sti = linux_save_flags_sti;#endif for (i = 0; i < NR_IRQS; i++) { irq_desc[i].mask_ack = linux_mask_ack; irq_desc[i].mask = ic_mask_irq[i]; irq_desc[i].unmask = ic_unmask_irq[i]; linux_irqs[i].pend_count = 0; }#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,19) rthal.c_do_IRQ = dispatch_irq;#endif INIT_LIST_HEAD(&global.pending_linux_irq); arch_mount_rtai(); saved_timer_action_handler = irq_desc[TIMER_8254_IRQ].action->handler; irq_desc[TIMER_8254_IRQ].action->handler = linux_timer_interrupt; hard_unlock_all(flags); printk("\n***** RTAI NEWLY MOUNTED (MOUNT COUNT %d) ******\n\n", rtai_mounted);}// Simple, now we can simply block other processors and copy original data back// to Linux.void __rt_umount_rtai(void){ int i; unsigned long flags; flags = hard_lock_all(); arch_umount_rtai(); rthal = linux_rthal; for (i = 0; i < NR_IRQS; i++) { irq_desc[i].mask_ack = ic_mask_ack_irq[i]; irq_desc[i].mask = ic_mask_irq[i]; irq_desc[i].unmask = ic_unmask_irq[i]; } irq_desc[TIMER_8254_IRQ].action->handler = saved_timer_action_handler; hard_unlock_all(flags); printk("\n***** RTAI UNMOUNTED (MOUNT COUNT %d) ******\n\n", rtai_mounted);}#ifdef CONFIG_RTAI_MOUNT_ON_LOADvoid rt_mount_rtai(void) { }void rt_umount_rtai(void) { }#elsevoid rt_mount_rtai(void){ rt_spin_lock(&rtai_mount_lock); MOD_INC_USE_COUNT; TRACE_RTAI_MOUNT(); if(++rtai_mounted==1) __rt_mount_rtai(); rt_spin_unlock(&rtai_mount_lock);}void rt_umount_rtai(void){ rt_spin_lock(&rtai_mount_lock); MOD_DEC_USE_COUNT; TRACE_RTAI_UMOUNT(); if(!--rtai_mounted) __rt_umount_rtai(); rt_spin_unlock(&rtai_mount_lock);}#endif/* module init-cleanup */extern void rt_printk_sysreq_handler(void);// Let's prepare our side without any problem, so that there remain just a few// things to be done when mounting RTAI. All the zeroings are strictly not// required as mostly related to static data. Done explicitly for emphasis.static __init int init_rtai(void){ unsigned int i; tuned.cpu_freq = FREQ_SYS_CLK; linux_rthal = rthal; init_pending_srqs(); global.active_srqs = 0; global.used_by_linux = ~(0xFFFFFFFF << smp_num_cpus); global.locked_cpus = 0; spin_lock_init(&(global.data_lock)); spin_lock_init(&(global.ic_lock)); for (i = 0; i < NR_RT_CPUS; i++) { processor[i].intr_flag = I_BIT | (1 << i); processor[i].linux_intr_flag = I_BIT | (1 << i); processor[i].pending_irqs = 0; processor[i].active_irqs = 0; } for (i = 0; i < NR_SYSRQS; i++) { sysrq[i].rtai_handler = 0; sysrq[i].user_handler = 0; sysrq[i].label = 0; } for (i = 0; i < NR_IRQS; i++) { global_irq[i].handler = 0; shadow_irq_desc[i] = irq_desc[i]; ic_mask_ack_irq[i] = irq_desc[i].mask_ack; ic_mask_irq[i] = irq_desc[i].mask; ic_unmask_irq[i] = irq_desc[i].unmask; } sysrq[rt_printk_srq].rtai_handler = rt_printk_sysreq_handler; sysrq[rt_printk_srq].label = 0x1F0000F1;#ifdef CONFIG_RTAI_MOUNT_ON_LOAD __rt_mount_rtai();#endif#ifdef CONFIG_PROC_FS rtai_proc_register();#endif return 0;}static __exit void cleanup_rtai(void){#ifdef CONFIG_RTAI_MOUNT_ON_LOAD __rt_umount_rtai();#endif#ifdef CONFIG_PROC_FS rtai_proc_unregister();#endif return;}module_init(init_rtai);module_exit(cleanup_rtai);MODULE_LICENSE("GPL");/* ----------------------< proc filesystem section >----------------------*/#ifdef CONFIG_PROC_FSstruct proc_dir_entry *rtai_proc_root = NULL;static int rtai_read_rtai(char *page, char **start, off_t off, int count, int *eof, void *data){ PROC_PRINT_VARS; int i; PROC_PRINT("\nRTAI Real Time Kernel, Version: %s\n\n", RTAI_RELEASE); PROC_PRINT(" RTAI mount count: %d\n", rtai_mounted); PROC_PRINT(" Clock frequency: %d Hz\n", FREQ_SYS_CLK); PROC_PRINT(" Timer latency: %d ns\n", LATENCY_MATCH_REG); PROC_PRINT(" Timer setup: %d ns\n", SETUP_TIME_MATCH_REG); PROC_PRINT("\nGlobal irqs used by RTAI: \n"); for (i = 0; i < NR_IRQS; i++) { if (global_irq[i].handler) { PROC_PRINT("%d\t%lu\n", i, global_irq[i].count); } } PROC_PRINT("\nRTAI sysreqs in use: \n"); for (i = 0; i < NR_SYSRQS; i++) { if (sysrq[i].rtai_handler || sysrq[i].user_handler) { PROC_PRINT("%d ", i); } } if ( global.lost_irqs ) PROC_PRINT( "### Lost IRQs: %d ###\n", global.lost_irqs ); PROC_PRINT("\n\n"); PROC_PRINT_DONE;} /* End function - rtai_read_rtai */static int rtai_proc_register(void){ struct proc_dir_entry *ent; rtai_proc_root = create_proc_entry("rtai", S_IFDIR, 0); if (!rtai_proc_root) { printk("Unable to initialize /proc/rtai\n"); return(-1); } rtai_proc_root->owner = THIS_MODULE; ent = create_proc_entry("rtai", S_IFREG|S_IRUGO|S_IWUSR, rtai_proc_root); if (!ent) { printk("Unable to initialize /proc/rtai/rtai\n"); return(-1); } ent->read_proc = rtai_read_rtai; return(0);} /* End function - rtai_proc_register */static void rtai_proc_unregister(void){ remove_proc_entry("rtai", rtai_proc_root); remove_proc_entry("rtai", 0);} /* End function - rtai_proc_unregister */#endif /* CONFIG_PROC_FS *//* ------------------< end of proc filesystem section >------------------*//********** SOME TIMER FUNCTIONS TO BE LIKELY NEVER PUT ELSWHERE *************//* Real time timers. No oneshot, and related timer programming, calibration. *//* Use the utility module. It is also to be decided if this stuff has to *//* stay here. */struct calibration_data tuned;struct rt_times rt_times;struct rt_times rt_smp_times[NR_RT_CPUS];/******** END OF SOME TIMER FUNCTIONS TO BE LIKELY NEVER PUT ELSWHERE *********/// Our printk function, its use should be safe everywhere.#include <linux/console.h>int rtai_print_to_screen(const char *format, ...){ static spinlock_t display_lock = SPIN_LOCK_UNLOCKED; static char display[25*80]; unsigned long flags; struct console *c; va_list args; int len; flags = rt_spin_lock_irqsave(&display_lock); va_start(args, format); len = vsprintf(display, format, args); va_end(args); c = console_drivers; while(c) { if ((c->flags & CON_ENABLED) && c->write) c->write(c, display, len); c = c->next; } rt_spin_unlock_irqrestore(flags, &display_lock); return len;}EXPORT_SYMBOL(rt_mask_ack_irq);EXPORT_SYMBOL(rt_mask_irq);EXPORT_SYMBOL(rt_disable_irq);EXPORT_SYMBOL(rt_enable_irq);EXPORT_SYMBOL(rt_free_global_irq);EXPORT_SYMBOL(rt_free_linux_irq);EXPORT_SYMBOL(rt_free_srq);EXPORT_SYMBOL(rt_free_timer);EXPORT_SYMBOL(rt_mount_rtai);EXPORT_SYMBOL(rt_pend_linux_irq);EXPORT_SYMBOL(rt_pend_linux_srq);EXPORT_SYMBOL(rt_printk);EXPORT_SYMBOL(rt_request_global_irq_ext);EXPORT_SYMBOL(rt_request_linux_irq);EXPORT_SYMBOL(rt_request_srq);EXPORT_SYMBOL(rt_request_timer);EXPORT_SYMBOL(rt_reset_full_intr_vect);EXPORT_SYMBOL(rt_set_full_intr_vect);EXPORT_SYMBOL(rt_shutdown_irq);EXPORT_SYMBOL(rt_startup_irq);EXPORT_SYMBOL(rt_switch_to_linux);EXPORT_SYMBOL(rt_switch_to_real_time);EXPORT_SYMBOL(rt_umount_rtai);EXPORT_SYMBOL(rt_unmask_irq);EXPORT_SYMBOL(rtai_proc_root);EXPORT_SYMBOL(rt_smp_times);EXPORT_SYMBOL(rt_times);EXPORT_SYMBOL(tuned);EXPORT_SYMBOL(locked_cpus);EXPORT_SYMBOL(linux_save_flags_and_cli);EXPORT_SYMBOL(linux_save_flags_and_cli_cpuid);EXPORT_SYMBOL(rtai_just_copy_back);EXPORT_SYMBOL(global);EXPORT_SYMBOL(rtai_print_to_screen);EXPORT_SYMBOL(rtai_tsc);EXPORT_SYMBOL(rt_set_rtai_trap_handler);EXPORT_SYMBOL(rt_free_rtai_trap_handler);EXPORT_SYMBOL(rt_is_linux);EXPORT_SYMBOL(up_task_sw);#include <asm-arm/arch/rtai_exports.h>
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -