summaryrefslogblamecommitdiffstats
path: root/cpukit/score/cpu/arm/rtems/score/cpu.h
blob: d7eca1527c1830f325ce2e4523bed894d67c857e (plain) (tree)
1
2
3
4
5
6
7
8
9
10



                          
  
       
  
                                                                

              

                                                 

                                      
                                            

                                                   




                                                           
                                         


   

                          
 
                            
 
           
                                

      



                             
 



                              
 


                                                        
     

                      
      
 





                                                                 
 








                                 
 
                                        


                                              
                                             
 
                                          
 

                                      
                        
                              
     
                               

      
                             
 
                                  
 
                                 
 
                                        
 
                                           
 
                                
 

                                                              

  
                                                            
  









                                                                               
   
                                     


                                                        

                                             
                                         
 
                                                                                 


                                             
                                         
 
                       
 
                                        
 
                                             
 
                             

  
                           
  


                                                                 
  

                                                                 

   
                                          
 
                                          
 
                                                     
 
           
 


                  
 










                               
 













                         
 








                             
 
                                                
 


                     
 
                                                     
 















                                                    
 



















                                                         
 













                                                        
 



                                                    
 
                                  
 







                            
 

             
 





















                                                     
 



                                            
 

                                         
 

                                       
 


                                          
 
                             





                               
  
 

                                         



                                                   


                                                           
                                                    


                                                
 
                                             
                                             

                                             




                                             

                                             
 
                             
 
                                 

                             


                       

  

                                          
                                                                        
 

                                                         
 
                                                                 
 
                                                                    
 
                                                     
 

                                               
 


                               

                        


                                                                 





                                                            


                                          

 
                                                     
 

                                                                      
 
         
 










                                    




                  


                               
/**
 * @file rtems/score/cpu.h
 */

/*
 * $Id$
 *
 *  This include file contains information pertaining to the ARM
 *  processor.
 *
 *  Copyright (c) 2007 Ray Xu <Rayx.cn@gmail.com>
 *
 *  Copyright (c) 2006 OAR Corporation
 *
 *  Copyright (c) 2002 Advent Networks, Inc.
 *        Jay Monkman <jmonkman@adventnetworks.com>
 *
 *  COPYRIGHT (c) 2000 Canon Research Centre France SA.
 *  Emmanuel Raguet, mailto:raguet@crf.canon.fr
 *
 *  The license and distribution terms for this file may be
 *  found in the file LICENSE in this distribution or at
 *  http://www.rtems.com/license/LICENSE.
 *
 */

#ifndef _RTEMS_SCORE_CPU_H
#define _RTEMS_SCORE_CPU_H

#include <rtems/score/arm.h>

#ifndef ASM
  #include <rtems/score/types.h>
#endif

#ifndef TRUE
  #warning "TRUE not defined"
  #define TRUE 1
#endif

#ifndef FALSE
  #warning "FALSE not defined"
  #define FALSE 0
#endif

#ifdef __thumb__
  #define ARM_TO_THUMB "add %0, pc, #1\nbx %0\n.thumb\n"
  #define THUMB_TO_ARM ".align 2\nbx pc\n.arm\n"
#else
  #define ARM_TO_THUMB
  #define THUMB_TO_ARM
#endif

/* If someone uses THUMB we assume she wants minimal code size */
#ifdef __thumb__
  #define CPU_INLINE_ENABLE_DISPATCH FALSE
#else
  #define CPU_INLINE_ENABLE_DISPATCH TRUE
#endif

#if defined(__ARMEL__)
  #define CPU_BIG_ENDIAN FALSE
  #define CPU_LITTLE_ENDIAN TRUE
#elif defined(__ARMEB__)
  #define CPU_BIG_ENDIAN TRUE
  #define CPU_LITTLE_ENDIAN FALSE
#else
  #error "unknown endianness"
#endif

#define CPU_UNROLL_ENQUEUE_PRIORITY TRUE

#define CPU_HAS_SOFTWARE_INTERRUPT_STACK FALSE

#define CPU_HAS_HARDWARE_INTERRUPT_STACK TRUE

#define CPU_ALLOCATE_INTERRUPT_STACK FALSE

#define CPU_ISR_PASSES_FRAME_POINTER 0

#if ( ARM_HAS_FPU == 1 )
  #define CPU_HARDWARE_FP TRUE
#else
  #define CPU_HARDWARE_FP FALSE
#endif

#define CPU_SOFTWARE_FP FALSE

#define CPU_ALL_TASKS_ARE_FP FALSE

#define CPU_IDLE_TASK_IS_FP FALSE

#define CPU_USE_DEFERRED_FP_SWITCH FALSE

#define CPU_PROVIDES_IDLE_THREAD_BODY FALSE

#define CPU_STACK_GROWS_UP FALSE

/* XXX Why 32? */
#define CPU_STRUCTURE_ALIGNMENT __attribute__ ((aligned (32)))

/*
 * The interrupt mask disables only normal interrupts (IRQ).
 *
 * In order to support fast interrupts (FIQ) such that they can do something
 * useful, we have to disable the operating system support for FIQs.  Having
 * operating system support for them would require that FIQs are disabled
 * during critical sections of the operating system and application.  At this
 * level IRQs and FIQs would be equal.  It is true that FIQs could interrupt
 * the non critical sections of IRQs, so here they would have a small
 * advantage.  Without operating system support, the FIQs can execute at any
 * time (of course not during the service of another FIQ). If someone needs
 * operating system support for a FIQ, she can trigger a software interrupt and
 * service the request in a two-step process.
 */
#define CPU_MODES_INTERRUPT_MASK 0x80

#define CPU_CONTEXT_FP_SIZE sizeof( Context_Control_fp )

#define CPU_MPCI_RECEIVE_SERVER_EXTRA_STACK 0

#define CPU_INTERRUPT_NUMBER_OF_VECTORS 8

#define CPU_INTERRUPT_MAXIMUM_VECTOR_NUMBER (CPU_INTERRUPT_NUMBER_OF_VECTORS - 1)

#define CPU_PROVIDES_ISR_IS_IN_PROGRESS FALSE

#define CPU_STACK_MINIMUM_SIZE (1024 * 4)

#define CPU_ALIGNMENT 4

#define CPU_HEAP_ALIGNMENT CPU_ALIGNMENT

#define CPU_PARTITION_ALIGNMENT CPU_ALIGNMENT

#define CPU_STACK_ALIGNMENT 4

/*
 * Bitfield handler macros.
 *
 * If we had a particularly fast function for finding the first
 * bit set in a word, it would go here. Since we don't (*), we'll
 * just use the universal macros.
 *
 * (*) On ARM V5 and later, there's a CLZ function which could be
 *     used to implement much quicker than the default macro.
 */

#define CPU_USE_GENERIC_BITFIELD_CODE TRUE

#define CPU_USE_GENERIC_BITFIELD_DATA TRUE

#define CPU_ENABLE_C_ISR_DISPATCH_IMPLEMENTATION TRUE

#ifndef ASM

#ifdef __cplusplus
extern "C" {
#endif

typedef enum {
  ARM_EXCEPTION_RESET = 0,
  ARM_EXCEPTION_UNDEF = 1,
  ARM_EXCEPTION_SWI = 2,
  ARM_EXCEPTION_PREF_ABORT = 3,
  ARM_EXCEPTION_DATA_ABORT = 4,
  ARM_EXCEPTION_RESERVED = 5,
  ARM_EXCEPTION_IRQ = 6,
  ARM_EXCEPTION_FIQ = 7,
  MAX_EXCEPTIONS = 8
} Arm_symbolic_exception_name;

typedef struct {
  uint32_t register_cpsr;
  uint32_t register_r4;
  uint32_t register_r5;
  uint32_t register_r6;
  uint32_t register_r7;
  uint32_t register_r8;
  uint32_t register_r9;
  uint32_t register_r10;
  uint32_t register_fp;
  uint32_t register_sp;
  uint32_t register_lr;
  uint32_t register_pc;
} Context_Control;

/* XXX This is out of date */
typedef struct {
  uint32_t register_r0;
  uint32_t register_r1;
  uint32_t register_r2;
  uint32_t register_r3;
  uint32_t register_ip;
  uint32_t register_lr;
} CPU_Exception_frame;

typedef CPU_Exception_frame CPU_Interrupt_frame;

typedef struct {
  /* Not supported */
} Context_Control_fp;

SCORE_EXTERN Context_Control_fp _CPU_Null_fp_context;

static inline uint32_t arm_interrupt_disable( void )
{
  uint32_t reg;
  uint32_t level;

  asm volatile (
    THUMB_TO_ARM
    "mrs %1, cpsr\n"
    "orr %0, %1, #0x80\n"
    "msr cpsr, %0\n"
    ARM_TO_THUMB
    : "=r" (reg), "=r" (level)
  );

  return level;
}

static inline void arm_interrupt_enable( uint32_t level )
{
  #ifdef __thumb__
    uint32_t reg;

    asm volatile (
      THUMB_TO_ARM
      "msr cpsr, %1\n"
      ARM_TO_THUMB
      : "=r" (reg)
      : "r" (level)
    );
  #else
    asm volatile (
      "msr cpsr, %0"
      :
      : "r" (level)
    );
  #endif
}

static inline void arm_interrupt_flash( uint32_t level )
{
  uint32_t reg;

  asm volatile (
    THUMB_TO_ARM
    "mrs %0, cpsr\n"
    "msr cpsr, %1\n"
    "msr cpsr, %0\n"
    ARM_TO_THUMB
    : "=r" (reg)
    : "r" (level)
  );
}

static inline uint32_t arm_status_irq_enable( void )
{
  uint32_t reg;
  uint32_t psr;

  RTEMS_COMPILER_MEMORY_BARRIER();

  asm volatile (
    THUMB_TO_ARM
    "mrs %1, cpsr\n"
    "bic %0, %1, #0x80\n"
    "msr cpsr, %0\n"
    ARM_TO_THUMB
    : "=r" (reg), "=r" (psr)
  );

  return psr;
}

static inline void arm_status_restore( uint32_t psr )
{
  #ifdef __thumb__
    uint32_t reg;

    asm volatile (
      THUMB_TO_ARM
      "msr cpsr, %1\n"
      ARM_TO_THUMB
      : "=r" (reg)
      : "r" (psr)
    );
  #else
    asm volatile (
      "msr cpsr, %0"
      :
      : "r" (psr)
    );
  #endif

  RTEMS_COMPILER_MEMORY_BARRIER();
}

#define _CPU_ISR_Disable( _isr_cookie ) \
  do { \
    _isr_cookie = arm_interrupt_disable(); \
  } while (0)

#define _CPU_ISR_Enable( _isr_cookie )  \
  arm_interrupt_enable( _isr_cookie )

#define _CPU_ISR_Flash( _isr_cookie ) \
  arm_interrupt_flash( _isr_cookie )

void _CPU_ISR_Set_level( uint32_t level );

uint32_t _CPU_ISR_Get_level( void );

void _CPU_Context_Initialize(
  Context_Control *the_context,
  uint32_t *stack_base,
  uint32_t size,
  uint32_t new_level,
  void *entry_point,
  bool is_fp
);

#define _CPU_Context_Get_SP( _context ) \
  (_context)->register_sp

#define _CPU_Context_Restart_self( _the_context ) \
   _CPU_Context_restore( (_the_context) );

#define _CPU_Context_Fp_start( _base, _offset ) \
   ( (void *) _Addresses_Add_offset( (_base), (_offset) ) )

#define _CPU_Context_Initialize_fp( _destination ) \
  do { \
    *(*(_destination)) = _CPU_Null_fp_context; \
  } while (0)

#define _CPU_Fatal_halt( _err )             \
   do {                                     \
     uint32_t _level;                       \
     uint32_t _error = _err;                \
     _CPU_ISR_Disable( _level );            \
     asm volatile ("mov r0, %0\n"           \
                   : "=r" (_error)          \
                   : "0" (_error)           \
                   : "r0" );                \
     while (1);                             \
   } while (0);

void _CPU_Initialize( void );

#define _CPU_Initialize_vectors()

void _CPU_ISR_install_vector(
  uint32_t vector,
  proc_ptr new_handler,
  proc_ptr *old_handler
);

void _CPU_Install_interrupt_stack( void );

void _CPU_Context_switch( Context_Control *run, Context_Control *heir );

void _CPU_Context_restore( Context_Control *new_context )
       RTEMS_COMPILER_NO_RETURN_ATTRIBUTE;

void _CPU_Context_save_fp( Context_Control_fp **fp_context_ptr );

void _CPU_Context_restore_fp( Context_Control_fp **fp_context_ptr );

static inline uint32_t CPU_swap_u32( uint32_t value )
{
#if defined(__thumb__)
  uint32_t byte1, byte2, byte3, byte4, swapped;

  byte4 = (value >> 24) & 0xff;
  byte3 = (value >> 16) & 0xff;
  byte2 = (value >> 8)  & 0xff;
  byte1 =  value & 0xff;

  swapped = (byte1 << 24) | (byte2 << 16) | (byte3 << 8) | byte4;
  return swapped;
#else
  uint32_t tmp = value; /* make compiler warnings go away */
  asm volatile ("EOR %1, %0, %0, ROR #16\n"
                "BIC %1, %1, #0xff0000\n"
                "MOV %0, %0, ROR #8\n"
                "EOR %0, %0, %1, LSR #8\n"
                : "=r" (value), "=r" (tmp)
                : "0" (value), "1" (tmp));
  return value;
#endif
}

static inline uint16_t CPU_swap_u16( uint16_t value )
{
  return (uint16_t) (((value & 0xffU) << 8) | ((value >> 8) & 0xffU));
}

/* XXX */

extern uint32_t arm_cpu_mode;

void arm_exc_abort_data( void );

void arm_exc_abort_prefetch( void );

void arm_exc_interrupt( void );

void arm_exc_undefined( void );

void bsp_interrupt_dispatch( void );

#ifdef __cplusplus
}
#endif

#endif /* ASM */

#endif /* _RTEMS_SCORE_CPU_H */