base/include/asm-arm/rtai_sched.h

Go to the documentation of this file.
00001 /*
00002  * Architecture specific scheduler support.
00003  *
00004  * Original RTAI/x86 layer implementation:
00005  *   Copyright (c) 2000 Paolo Mantegazza (mantegazza@aero.polimi.it)
00006  *   Copyright (c) 2000 Steve Papacharalambous (stevep@zentropix.com)
00007  *   Copyright (c) 2000 Stuart Hughes
00008  *   and others.
00009  *
00010  * RTAI/x86 rewrite over Adeos:
00011  *   Copyright (c) 2002 Philippe Gerum (rpm@xenomai.org)
00012  *
00013  * Original RTAI/ARM RTHAL implementation:
00014  *   Copyright (c) 2000 Pierre Cloutier (pcloutier@poseidoncontrols.com)
00015  *   Copyright (c) 2001 Alex Züpke, SYSGO RTS GmbH (azu@sysgo.de)
00016  *   Copyright (c) 2002 Guennadi Liakhovetski DSA GmbH (gl@dsa-ac.de)
00017  *   Copyright (c) 2002 Steve Papacharalambous (stevep@zentropix.com)
00018  *   Copyright (c) 2002 Wolfgang Müller (wolfgang.mueller@dsa-ac.de)
00019  *   Copyright (c) 2003 Bernard Haible, Marconi Communications
00020  *   Copyright (c) 2003 Thomas Gleixner (tglx@linutronix.de)
00021  *   Copyright (c) 2003 Philippe Gerum (rpm@xenomai.org)
00022  *
00023  * RTAI/ARM over Adeos rewrite:
00024  *   Copyright (c) 2004-2005 Michael Neuhauser, Firmix Software GmbH (mike@firmix.at)
00025  *
00026  * RTAI/ARM over Adeos rewrite for PXA255_2.6.7:
00027  *   Copyright (c) 2005 Stefano Gafforelli (stefano.gafforelli@tiscali.it)
00028  *   Copyright (c) 2005 Luca Pizzi (lucapizzi@hotmail.com)
00029  *
00030  *
00031  * This program is free software; you can redistribute it and/or modify it under
00032  * the terms of the GNU General Public License as published by the Free Software
00033  * Foundation, Inc., 675 Mass Ave, Cambridge MA 02139, USA; either version 2 of
00034  * the License, or (at your option) any later version.
00035  *
00036  * This program is distributed in the hope that it will be useful, but WITHOUT
00037  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
00038  * FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
00039  * details.
00040  *
00041  * You should have received a copy of the GNU General Public License along with
00042  * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
00043  * Place - Suite 330, Boston, MA 02111-1307, USA.
00044  */
00045 #ifndef _RTAI_ASM_ARM_RTAI_SCHED_H
00046 #define _RTAI_ASM_ARM_RTAI_SCHED_H
00047 
00048 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0)
00049 #   include <asm/proc/ptrace.h>
00050 #else /* LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) */
00051 #   include <asm/ptrace.h>
00052 #   define  I_BIT PSR_I_BIT
00053 #endif /* LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0) */
00054 
00055 #include <rtai_schedcore.h>
00056 
00057 /*
00058  * Registers according to the ARM procedure call standard:
00059  *   Reg    Description
00060  *   r0-r3  argument/scratch registers
00061  *   r4-r9  variable register
00062  *   r10=sl stack limit/variable register
00063  *   r11=fp frame pointer/variable register
00064  *   r12=ip intra-procedure-call scratch register
00065  *   r13=sp stack pointer (auto preserved)
00066  *   r14=lr link register
00067  *   r15=pc program counter (auto preserved)
00068  *
00069  * Take special care to restore r0/r1 for startup of new task (->
00070  * init_arch_stack, rt_startup)!
00071  *
00072  * Stack layout:
00073  *
00074  *  Offset  Content
00075  *
00076  *  12  r14=lr (i.e. resume point for task)
00077  *  11  r11=fp
00078  *  10  r10=sl
00079  *   9  r9
00080  *   8  r8
00081  *   7  r7
00082  *   6  r6
00083  *   5  r5
00084  *   4  r4
00085  *   3  cpsr
00086  *   2  domain_access_control
00087  *   1  r1 (startup: data)
00088  *   0  r0 (startup: rt_thread)
00089  */
00090 
00091 #define rt_exchange_tasks(old_task, new_task) \
00092     asm volatile( \
00093     "mrc    p15, 0, r2, c3, c0\n\t"     /* get current domain_access_control */ \
00094     "adr    lr, 1f\n\t"         /* get address of resume point */ \
00095     "mrs    r3, cpsr\n\t"           /* get current cpsr */ \
00096     "ldr    ip, [%[oldp]]\n\t"      /* get pointer to old task */ \
00097     "stmfd  sp!, {r0 - fp, lr}\n\t"     /* push registers on stack */ \
00098     "str    %[new], [%[oldp]]\n\t"      /* *oldp = new */ \
00099     "str    sp, [ip]\n\t"           /* save current stack-pointer to old task */ \
00100     "ldr    sp, [%[new]]\n\t"       /* get stack-pointer of new task */ \
00101     "ldmfd  sp!, {r0-r3}\n\t"       /* pop new tasks' r0, r1, cpsr & d.a.c from stack */ \
00102     "mcr    p15, 0, r2, c3, c0\n\t"     /* restore previous domain_access_control */ \
00103     "msr    cpsr_c, %[psr]\n\t"     /* disable hw-irqs */ \
00104     "msr    spsr, r3\n\t"           /* set spsr to previous cpsr */ \
00105     "ldmfd  sp!, {r4 - fp, pc}^\n\t"    /* pop registers, pc = resume point, cpsr = spsr */ \
00106     "1:"                    /* resume point (except for startup) */ \
00107     : /* output  */ /* none */ \
00108     : /* input   */ [oldp] "r" (&old_task), \
00109             [new]  "r" (new_task), \
00110             [psr]  "i" (SVC_MODE|I_BIT) \
00111     : /* clobber */ "lr", "ip", "r2", "r3", "memory" \
00112     )
00113 
00114 extern inline unsigned long
00115 current_domain_access_control(void)
00116 {
00117     unsigned long domain_access_control;
00118     asm("mrc p15, 0, %0, c3, c0" : "=r" (domain_access_control));
00119     return domain_access_control;
00120 }
00121 
00122 /*
00123  * Set up stack for new proper RTAI task (i.e. kernel task without
00124  * kernel-thread). This is called in rt_task_init_cpuid() where the following
00125  * variables are used (should be arguments to macro!):
00126  *  rt_thread   pointer to tasks function
00127  *  data        integer to pass to rt_thread
00128  *
00129  * The stack needs to be set-up so that a rt_exchange_tasks() on the newly
00130  * created task will call rt_startup(rt_thread = r0, data = r1).
00131  *
00132  * See rt_exchange_tasks() above for the stack layout.
00133  *
00134  */
00135 #define init_arch_stack()                       \
00136     do {                                \
00137     task->stack -= 13; /* make room on stack */         \
00138     task->stack[12] = (int)rt_startup; /* entry point */        \
00139     task->stack[ 3] = SVC_MODE;    /* cpsr */           \
00140     task->stack[ 2] = (int)current_domain_access_control();     \
00141     task->stack[ 1] = (int)data;       /* arg 2 of rt_startup() */  \
00142     task->stack[ 0] = (int)rt_thread;  /* arg 1 "  " */     \
00143     } while (0)
00144 
00145 #define DEFINE_LINUX_CR0
00146 #define DEFINE_LINUX_SMP_CR0
00147 
00148 #ifdef CONFIG_RTAI_FP_SUPPORT
00149 #define init_fp_env() \
00150 do { \
00151       memset(&task->fpu_reg, 0, sizeof(task->fpu_reg)); \
00152 }while(0)
00153 #else
00154 #define init_fp_env() 
00155 #endif
00156 
00157 #define init_task_fpenv(task)  do { init_fpenv((task)->fpu_reg); } while(0)
00158 
00159 extern inline void *
00160 get_stack_pointer(void)
00161 {
00162     void *sp;
00163     asm("mov %0, sp" : "=r" (sp));
00164     return sp;
00165 }
00166 
00167 /* acknowledge timer interrupt in scheduler's timer-handler (using the
00168  * arch-specific rtai_timer_irq_ack()) also allows to bail out of timer irq
00169  * handler (because of spurious interrupt or whatever) */
00170 #ifndef CONFIG_ARCH_AT91
00171 #define DO_TIMER_PROPER_OP()        \
00172 do {                    \
00173     rtai_timer_irq_ack();       \
00174 } while (0)
00175 #else
00176 /* since we are using extern_timer_isr in __ipipe_grab_irq
00177  * we need to update tsc manually in periodic mode*/
00178 #define DO_TIMER_PROPER_OP()        \
00179 do {                    \
00180     if(rt_periodic) {       \
00181         rtai_at91_update_tsc(); \
00182     }               \
00183 } while (0)
00184 #endif
00185 
00186 #endif /* _RTAI_ASM_ARM_RTAI_SCHED_H */

Generated on Tue Feb 2 17:46:04 2010 for RTAI API by  doxygen 1.4.7