2011-08-18 Chris Johns <chrisj@rtems.org>

* cpu.c: Fix the ISR get level for the IIC. Make
        _CPU_Context_Initialize a function rather than inlined.
        * cpu_asm.S: Do not enable interrupt on return, rather resume the
        state on entry to the ISR.
        * irq.c, nios2/nios2-iic-low-level.S: Change the ISR handler so
        the ipending decoding is in C and within the interrupt
        context. This is usable with the Altera HAL directly.
        * rtems/score/cpu.h: Add ienable and ipending interfaces. Add some
        comments. Remove _CPU_Context_Initialize.
This commit is contained in:
Chris Johns
2011-08-18 09:00:14 +00:00
parent b7ee9ab913
commit a385489281
6 changed files with 119 additions and 52 deletions

View File

@@ -1,3 +1,15 @@
2011-08-18 Chris Johns <chrisj@rtems.org>
* cpu.c: Fix the ISR get level for the IIC. Make
_CPU_Context_Initialize a function rather than inlined.
* cpu_asm.S: Do not enable interrupt on return, rather resume the
state on entry to the ISR.
* irq.c, nios2/nios2-iic-low-level.S: Change the ISR handler so
the ipending decoding is in C and within the interrupt
context. This is usable with the Altera HAL directly.
* rtems/score/cpu.h: Add ienable and ipending interfaces. Add some
comments. Remove _CPU_Context_Initialize.
2011-08-14 Chris Johns <chrisj@rtems.org>
* rtems/score/cpu.h: Clear the vector table for simple vectored

View File

@@ -19,6 +19,8 @@
#include <rtems/score/isr.h>
#include <rtems/score/wkspace.h>
#include <rtems/score/nios2.h>
/* _CPU_Initialize
*
* This routine performs processor dependent initialization.
@@ -44,19 +46,33 @@ void _CPU_Initialize(void)
/*
* _CPU_ISR_Get_level
*
* NO_CPU Specific Information:
*
* XXX document implementation including references if appropriate
*/
uint32_t _CPU_ISR_Get_level( void )
{
/*
* This routine returns the current interrupt level.
*/
/* @todo Add EIC support. */
uint32_t status = __builtin_rdctl(0);
return status & 1 ? 0 : 1;
}
return 0;
/*
* FIXME: Evaluate interrupt level.
*/
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
)
{
uint32_t stack = (uint32_t)stack_base + size - 4;
the_context->fp = stack;
the_context->sp = stack;
the_context->ra = (intptr_t) entry_point;
/* @todo Add EIC support. */
the_context->status = new_level ? 0 : 1;
}
/*

View File

@@ -70,8 +70,6 @@ _CPU_Context_switch_restore:
ldw ea, 40(r5)
ldw at, 44(r5)
/* FIXME: Always have interrupts enabled when we return from Context_switch */
ori at, at, 1
wrctl estatus, at
eret

View File

@@ -34,19 +34,6 @@
register unsigned long *stack_ptr __asm__ ("sp");
RTEMS_INLINE_ROUTINE void
__Dipatch_interrupt_vector(uint32_t vector, proc_ptr pp)
{
if ( _ISR_Vector_table[ vector] )
{
(*_ISR_Vector_table[ vector ])(vector, pp);
};
}
#if (RTEMS_NIOS_USE_ALT_HAL == TRUE)
#include <bsp/alt/nios2.h>
RTEMS_INLINE_ROUTINE void __IIC_Handler(void)
{
uint32_t active;
@@ -56,7 +43,7 @@ RTEMS_INLINE_ROUTINE void __IIC_Handler(void)
/*
* Obtain from the interrupt controller a bit list of pending interrupts,
* and then process the highest priority interrupt. This process loops,
* loading the active interrupt list on each pass until alt_irq_pending()
* loading the active interrupt list on each pass until ipending
* return zero.
*
* The maximum interrupt latency for the highest priority interrupt is
@@ -66,7 +53,7 @@ RTEMS_INLINE_ROUTINE void __IIC_Handler(void)
* this is the case.
*/
NIOS2_READ_IPENDING (active);
_CPU_read_ipending (active);
while (active)
{
@@ -75,34 +62,29 @@ RTEMS_INLINE_ROUTINE void __IIC_Handler(void)
/*
* Test each bit in turn looking for an active interrupt. Once one is
* found, the interrupt handler asigned by a call to alt_irq_register() is
* called to clear the interrupt condition.
* found call it to clear the interrupt condition.
*/
while (active)
{
if (active & mask)
{
__Dipatch_interrupt_vector(vector, NULL);
if ( _ISR_Vector_table[ vector] )
(*_ISR_Vector_table[ vector ])(vector, NULL);
active &= ~mask;
}
mask <<= 1;
++vector;
};
NIOS2_READ_IPENDING (active);
_CPU_read_ipending (active);
}
}
#endif
#if (RTEMS_NIOS_USE_ALT_HAL == TRUE)
void __ISR_Handler(void)
#else
void __ISR_Handler(uint32_t vector, CPU_Interrupt_frame *ifr)
#endif
{
register uint32_t level;
register uint32_t level;
/* Interrupts are disabled upon entry to this Handler */
@@ -118,11 +100,7 @@ void __ISR_Handler(uint32_t vector, CPU_Interrupt_frame *ifr)
_Thread_Dispatch_increment_disable_level();
#if (RTEMS_NIOS_USE_ALT_HAL == TRUE)
__IIC_Handler();
#else
__Dipatch_interrupt_vector(vector, ifr);
#endif
/* Make sure that interrupts are disabled again */
_CPU_ISR_Disable( level );

View File

@@ -231,6 +231,7 @@ _ISR_Handler:
stw et, 68(sp)
stw ea, 72(sp)
#if REMOVED_BY_CCJ
/*
* Obtain a bitlist of the pending interrupts.
*/
@@ -266,7 +267,8 @@ _ISR_Handler:
*/
mov r5, sp
#endif
.extern __ISR_Handler
call __ISR_Handler

View File

@@ -189,40 +189,101 @@ typedef struct {
#define _CPU_Initialize_vectors()
#endif
/**
* @brief Read the ienable register.
*/
#define _CPU_read_ienable( value ) \
do { value = __builtin_rdctl(3); } while (0)
/**
* @brief Write the ienable register.
*/
#define _CPU_write_ienable( value ) \
do { __builtin_wrctl(3, value); } while (0)
/**
* @brief Read the ipending register.
*/
#define _CPU_read_ipending( value ) \
do { value = __builtin_rdctl(4); } while (0)
/**
* Disable all interrupts for a critical section. The previous
* level is returned in _level.
*/
#define _CPU_ISR_Disable( _isr_cookie ) \
do { \
_isr_cookie = __builtin_rdctl( 0 ); \
__builtin_wrctl( 0, 0 ); \
} while ( 0 )
/**
* Enable interrupts to the previous level (returned by _CPU_ISR_Disable).
* This indicates the end of a critical section. The parameter
* _level is not modified.
*/
#define _CPU_ISR_Enable( _isr_cookie ) \
do { \
__builtin_wrctl( 0, (int) _isr_cookie ); \
} while ( 0 )
/**
* This temporarily restores the interrupt to _level before immediately
* disabling them again. This is used to divide long critical
* sections into two or more parts. The parameter _level is not
* modified.
*/
#define _CPU_ISR_Flash( _isr_cookie ) \
do { \
__builtin_wrctl( 0, (int) _isr_cookie ); \
__builtin_wrctl( 0, 0 ); \
} while ( 0 )
#define _CPU_ISR_Set_level( new_level ) \
/**
* Map interrupt level in task mode onto the hardware that the CPU
* actually provides. Currently, interrupt levels which do not
* map onto the CPU in a straight fashion are undefined.
*/
#define _CPU_ISR_Set_level( new_level ) \
_CPU_ISR_Enable( new_level == 0 ? 1 : 0 );
/**
* @brief Obtain the Current Interrupt Disable Level
*
* This method is invoked to return the current interrupt disable level.
*
* @return This method returns the current interrupt disable level.
*/
uint32_t _CPU_ISR_Get_level( void );
/*
* FIXME: Evaluate interrupt level.
/**
* Initialize the context to a state suitable for starting a
* task after a context restore operation. Generally, this
* involves:
*
* - setting a starting address
* - preparing the stack
* - preparing the stack and frame pointers
* - setting the proper interrupt level in the context
* - initializing the floating point context
*
* @param[in] the_context points to the context area
* @param[in] stack_base is the low address of the allocated stack area
* @param[in] size is the size of the stack area in bytes
* @param[in] new_level is the interrupt level for the task
* @param[in] entry_point is the task's entry point
* @param[in] is_fp is set to TRUE if the task is a floating point task
*
* @note Implemented as a subroutine for the NIOS2 port.
*/
#define _CPU_Context_Initialize( _the_context, _stack_base, _size, \
_isr, _entry_point, _is_fp ) \
do { \
uint32_t _stack = (uint32_t)(_stack_base) + (_size) - 4; \
(_the_context)->fp = (void *)_stack; \
(_the_context)->sp = (void *)_stack; \
(_the_context)->ra = (void *)(_entry_point); \
(_the_context)->status = 0x1; /* IRQs enabled */ \
} while ( 0 )
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_Restart_self( _the_context ) \
_CPU_Context_restore( (_the_context) );