⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 rtai.c

📁 rtai-3.1-test3的源代码(Real-Time Application Interface )
💻 C
📖 第 1 页 / 共 2 页
字号:
/*Copyright (C) 2002,2003 Axis Communications ABAuthors: Martin P Andersson (martin.andersson@linux.nu)         Jens-Henrik Lindskov (mumrick@linux.nu)This program is free software; you can redistribute it and/or modifyit under the terms of version 2 of the GNU General Public License aspublished by the Free Software Foundation.This program is distributed in the hope that it will be useful,but WITHOUT ANY WARRANTY; without even the implied warranty ofMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See theGNU General Public License for more details.You should have received a copy of the GNU General Public Licensealong with this program; if not, write to the Free SoftwareFoundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA--------------------------------------------------------------------------Acknowledgements- Paolo Mantegazza	(mantegazza@aero.polimi.it)	creator of RTAI --------------------------------------------------------------------------*/#include <linux/config.h>#include <linux/module.h>#include <linux/sched.h>#include <linux/interrupt.h>#include <linux/init.h>#include <linux/slab.h>#include <asm/system.h>#include <rtai_version.h>#ifdef CONFIG_PROC_FS#include <linux/stat.h>#include <linux/proc_fs.h>#include <rtai_proc_fs.h>#endif#define NR_SYSRQS 32#define TIMER_IRQ 2   /* Prescaler=4 gives 6.25 MHz. This means a value of 62500 needs   to be loaded in the cascaded counter to give an interrupt every   10 ms. 62500dec=F424hex. F4hex=244dec, 24hex=36dec. */#define RTAI_CASCADED_TIMER0_DIV 36#define RTAI_CASCADED_TIMER1_DIV 244#define RTAI_CASCADED_TIMER_PRESCALE 4#include <asm/rtai.h>/* --------------------------------------------------------------------------*/static struct global_rt_status {	int pending_irqs;	int pending_srqs; 	unsigned int used_by_linux;} volatile global;static struct cpu_own_status {	unsigned long intr_flag;	unsigned long linux_intr_flag;} volatile cpu;static void* global_irq_handlers[NR_IRQS];static struct sysrq_t {	unsigned int label;	void (*rtai_handler)(void);	long long (*user_handler)(unsigned long whatever);} sysrq[NR_SYSRQS];static unsigned long irq_action_flags[NR_IRQS];static int chained_to_linux[NR_IRQS];static int rtai_mounted = 0;/* The datastructures saved when taking control from Linux */static struct rt_hal linux_rthal;               /* The original rthal-struct.*/#ifdef CONFIG_ETRAX_DISABLE_CASCADED_TIMERS_IN_RTAIstatic unsigned long saved_r_timer_ctrl_shadow; /* Saved timer shadow.*/#endifstatic void *saved_timer_action_handler;        /* Saved timer-action handler*//* --------------------------------------------------------------------------*//* Scheduler related data */unsigned int rtai_delay;     /* Current timer divide factor on timer0 */unsigned long long rtai_tsc; /* timer0 ticks since we started counting */unsigned int rtai_lastcount; /* Last read value on *R_TIMER0_DATA */struct calibration_data tuned = {CPU_FREQ, FREQ_APIC, 0, 0, 0, {0}};struct rt_times rt_times;/* --------------------------------------------------------------------------*//* Some prototypes */long long dispatch_srq(int srq, unsigned long whatever);#ifdef CONFIG_PROC_FSstatic int rtai_proc_register(void);static void rtai_proc_unregister(void);#endif/* Just some dummies to get rid of compiler warnings */static long long do_nothing(int what, unsigned long ever) { return 0;}static void do_nothing_uint(unsigned int whatever) { }#ifdef CONFIG_ETRAX_WATCHDOGextern void reset_watchdog(void);#endif/* --------------------------------------------------------------------------*/static inline void mask_irq(unsigned int irq_nr){	*R_VECT_MASK_CLR = 1 << irq_nr;}static inline void unmask_irq(unsigned int irq_nr){	*R_VECT_MASK_SET = 1 << irq_nr;}/* --------------------------------------------------------------------------*/unsigned int rt_startup_irq(unsigned int irq){       	startup_irq(irq);	return 0;}void rt_shutdown_irq(unsigned int irq){	shutdown_irq(irq);}void rt_enable_irq(unsigned int irq){	unmask_irq(irq);}void rt_disable_irq(unsigned int irq){	mask_irq(irq);}/* * The ACK is not implemented on cris because no generic way to * do this exists. It is up to the RT-handler to ACK properly. */void rt_mask_and_ack_irq(unsigned int irq){	mask_irq(irq);}void rt_mask_irq(unsigned int irq){	mask_irq(irq);}void rt_unmask_irq(unsigned int irq){	unmask_irq(irq);}/* * The ACK is not implemented on cris because no generic way to * do this exists. It is up to the RT-handler to ACK properly. */void rt_ack_irq(unsigned int irq){}/* --------------------------------------------------------------------------*//* Only makes sense on smp */#define send_ipi_shorthand(shorthand, irq)#define send_ipi_logical(dest, irq)/* --------------------------------------------------------------------------*//* * Installs a RT-handler on the requested irq. */int rt_request_global_irq(unsigned int irq, void (*handler)(void)){	unsigned long flags;	if (irq >= NR_IRQS || !handler) {		return -EINVAL;	}	flags = hard_lock_all();	if (global_irq_handlers[irq]) {		hard_unlock_all(flags);		return -EBUSY;	}	global_irq_handlers[irq] = handler;		hard_unlock_all(flags);	return 0;}/* * Uninstalls the previously installed RT-handler on the requested irq. */int rt_free_global_irq(unsigned int irq){	unsigned long flags = hard_lock_all();	if (irq >= NR_IRQS || !global_irq_handlers[irq]) {		hard_unlock_all(flags);		return -EINVAL;	}	global_irq_handlers[irq] = 0;	hard_unlock_all(flags);	return 0;}/* * Installs a new linux interrupt handler. Forces linux to share the * interrupt if necessary. */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 >= NR_IRQS || !linux_handler) {		return -EINVAL;	}	flags = hard_lock_all();	/* Force linux to share the irq */	/* Save the flags to restore them in rt_free_linux_irq */	if (!chained_to_linux[irq]++) {		if (irq_action[irq]) {			irq_action_flags[irq] = irq_action[irq]->flags;			irq_action[irq]->flags |= SA_SHIRQ;		}	}	hard_unlock_all(flags);	/* Call the standard linux function in irq.c */	request_irq(irq, linux_handler, SA_SHIRQ, linux_handler_id, dev_id);	return 0;}/* * Copied from irq.c with some small changes. Called from rt_free_linux_irq  * instead of free_irq in irq.c when there is a RT-handler installed on the  * same interrupt. Does not set the interrupt to the badhandler. */static void linux_free_irq(unsigned int irq, void *dev_id){	struct irqaction *action, **p;	unsigned long flags;	for (p = irq_action + irq; (action = *p) != NULL; p = &action->next) {		if (action->dev_id != dev_id)			continue;		/* Found it - now free it */		save_flags(flags);		cli();		*p = action->next;		restore_flags(flags);		kfree(action);		return;	}}/* * Uninstalls the previously installed linux handler on irq. */int rt_free_linux_irq(unsigned int irq, void *dev_id){	unsigned long flags;	flags = hard_lock_all();	if (irq >= NR_IRQS || !chained_to_linux[irq]) {		hard_unlock_all(flags);		return -EINVAL;	}		if (global_irq_handlers[irq]){		hard_unlock_all(flags);		/* Call our special function above. */		linux_free_irq(irq, dev_id);	}	else{		hard_unlock_all(flags);		/* Call the standard linux function in irq.c */		free_irq(irq, dev_id);	}	flags = hard_lock_all();	if (!(--chained_to_linux[irq]) && irq_action[irq]) {		irq_action[irq]->flags = irq_action_flags[irq];	}	hard_unlock_all(flags);	return 0;}/* * Pend an interrupt to linux. * Called by a RT-handler if it wants to share the interrupt with linux. */void rt_pend_linux_irq(unsigned int irq){	set_bit_non_atomic(irq, (int*) &global.pending_irqs);}/* * The call mechanism for the user_handler is not yet implemented. */int rt_request_srq(unsigned int label, void (*rtai_handler)(void), 		   long long (*user_handler)(unsigned long whatever)){	unsigned long flags;	int srq;     		if (!rtai_handler) {		return -EINVAL;	}		flags = hard_lock_all();	/* srq 0 and 1 are reserved */	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;				rthal.do_SRQ = dispatch_srq;			}			hard_unlock_all(flags);			return srq;		}	}	hard_unlock_all(flags);	return -EBUSY;}int rt_free_srq(unsigned int srq){	unsigned long flags;	flags = hard_lock_all();		if (srq < 2 || srq >= NR_SYSRQS || !sysrq[srq].rtai_handler) {		hard_unlock_all(flags);		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) {			hard_unlock_all(flags);			return 0;		}	}	rthal.do_SRQ = do_nothing;			hard_unlock_all(flags);	return 0;}void rt_pend_linux_srq(unsigned int srq){	set_bit_non_atomic(srq, (int*) &global.pending_srqs);}/* --------------------------------------------------------------------------*/static void linux_cli(void){	/* Soft-disable interrupts */	cpu.intr_flag = 0;}static void linux_sti(void){	static volatile int sti_lock = 0;	static struct pt_regs dummy_regs;	int irq;	int irq_mask;	/* Hard-disable interrupts */	hard_cli(); 		/* When one process is in sti, dispatching irqs, */	/* another one should not be able to enter. */	if (sti_lock) {		cpu.intr_flag = 1;		/* Need to enable interrupts since they were		   enabled before calling this function. */		hard_sti();		return;	}	/* Lock */	sti_lock = 1;	/* Soft-disable interrupts */	cpu.intr_flag = 0; 				irq = 0;	irq_mask = 1;			/* Process all pending IRQs and SRQs */	while (global.pending_irqs || global.pending_srqs) {		/* "irq" active? */		if (irq_mask & global.pending_irqs) {			/* Clear the irq */			clear_bit_non_atomic(irq, (int*) &global.pending_irqs);			/* Hard-enable interrupts (during handler) */			hard_sti();								/* Call standard Linux do_IRQ(). */			linux_rthal.do_IRQ(irq, &dummy_regs); 			/* Hard-disable interrupts */			hard_cli();						/* The interrupt had to remain masked until now			 * because there is no generic ACK on cris.			 * Interrupts with RT-handlers are unmasked			 * immediately in dispatch_irq. */			unmask_irq(irq); 		}		/* If a SRQ has been pended and there is a SRQ-handler */		if ((irq_mask & global.pending_srqs) &&		    sysrq[irq].rtai_handler) {			/* Clear the srq */			clear_bit_non_atomic(irq, (int*) &global.pending_srqs);       			/* Hard-enable interrupts (during handler) */			hard_sti();			/* Call installed SRQ-handler */			sysrq[irq].rtai_handler();			/* Hard-disable interrupts */			hard_cli();		}		/* The interrupts should be enabled here to reduce latency */		hard_sti();		irq_mask = irq_mask << 1;		++irq;		if (irq >= NR_IRQS) {			irq = 0;			irq_mask = 1;		}		hard_cli();	}	/* We are through, so release the lock */	sti_lock = 0;					/* Soft-enable interrupts */	cpu.intr_flag = 1;	/* Hard-enable interrupts */	hard_sti();}static unsigned long linux_save_flags(void){		return cpu.intr_flag;}static void linux_restore_flags(unsigned long flags){	/* check if interrupts were enabled when flag was saved */	if (flags) {		linux_sti();	} else {		cpu.intr_flag = 0;	}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -