SPARC port passes all tests

This commit is contained in:
Joel Sherrill
1995-10-30 21:54:45 +00:00
parent ea744828ad
commit 97005786d8
112 changed files with 4355 additions and 1359 deletions

View File

@@ -68,7 +68,8 @@ The following persons/organizations have made contributions:
to port RTEMS to the SPARC V7 architecture for use with their ERC32
radiation-hardened CPU. Jiri Gaisler (jgais@wd.estec.esa.nl) deserves
special thanks for championing this port within the ESA was well as
for developing the SPARC Instruction Simulator used to test this port.
for developing and supporting the SPARC Instruction Simulator used to
develop and test this port.
Finally, the RTEMS project would like to thank those who have contributed
to the other free software efforts which RTEMS utilizes. The primary RTEMS

View File

@@ -10,13 +10,13 @@
#define __RINGBUF_H__
#ifndef RINGBUF_QUEUE_LENGTH
#define RINGBUF_QUEUE_LENGTH 200
#define RINGBUF_QUEUE_LENGTH 128
#endif
typedef struct {
char buffer[RINGBUF_QUEUE_LENGTH];
int head;
int tail;
volatile int head;
volatile int tail;
} Ring_buffer_t;
#define Ring_buffer_Initialize( _buffer ) \
@@ -27,16 +27,27 @@ typedef struct {
#define Ring_buffer_Is_empty( _buffer ) \
( (_buffer)->head == (_buffer)->tail )
#define Ring_buffer_Is_full( _buffer ) \
( (_buffer)->head == ((_buffer)->tail + 1) % RINGBUF_QUEUE_LENGTH )
#define Ring_buffer_Add_character( _buffer, _ch ) \
do { \
(_buffer)->buffer[ (_buffer)->tail ] = (_ch); \
(_buffer)->tail = ((_buffer)->tail+1) % RINGBUF_QUEUE_LENGTH; \
rtems_unsigned32 isrlevel; \
\
rtems_interrupt_disable( isrlevel ); \
(_buffer)->tail = ((_buffer)->tail+1) % RINGBUF_QUEUE_LENGTH; \
(_buffer)->buffer[ (_buffer)->tail ] = (_ch); \
rtems_interrupt_enable( isrlevel ); \
} while ( 0 )
#define Ring_buffer_Remove_character( _buffer, _ch ) \
do { \
(_ch) = (_buffer)->buffer[ (_buffer)->head ]; \
(_buffer)->head = ((_buffer)->head+1) % RINGBUF_QUEUE_LENGTH; \
rtems_unsigned32 isrlevel; \
\
rtems_interrupt_disable( isrlevel ); \
(_buffer)->head = ((_buffer)->head+1) % RINGBUF_QUEUE_LENGTH; \
(_ch) = (_buffer)->buffer[ (_buffer)->head ]; \
rtems_interrupt_enable( isrlevel ); \
} while ( 0 )
#endif

View File

@@ -60,8 +60,7 @@ EXTERN Objects_Information _POSIX_Interrupt_Handlers_Information;
* interrupt handlers installed on each vector.
*/
EXTERN POSIX_Interrupt_Control
_POSIX_Interrupt_Information[ ISR_NUMBER_OF_VECTORS ];
EXTERN POSIX_Interrupt_Control _POSIX_Interrupt_Information[ ISR_NUMBER_OF_VECTORS ];
/*
* _POSIX_Interrupt_Manager_initialization

View File

@@ -60,8 +60,7 @@ EXTERN Objects_Information _POSIX_Interrupt_Handlers_Information;
* interrupt handlers installed on each vector.
*/
EXTERN POSIX_Interrupt_Control
_POSIX_Interrupt_Information[ ISR_NUMBER_OF_VECTORS ];
EXTERN POSIX_Interrupt_Control _POSIX_Interrupt_Information[ ISR_NUMBER_OF_VECTORS ];
/*
* _POSIX_Interrupt_Manager_initialization

View File

@@ -108,3 +108,205 @@ rtems_status_code rtems_event_receive(
_Thread_Enable_dispatch();
return( _Thread_Executing->Wait.return_code );
}
/*PAGE
*
* _Event_Seize
*
* This routine attempts to satisfy the requested event condition
* for the running thread.
*
* Input parameters:
* event_in - the event condition to satisfy
* option_set - acquire event options
* ticks - interval to wait
* event_out - pointer to event set output area
*
* Output parameters: NONE
* *event_out - event set output area filled in
*
* INTERRUPT LATENCY:
* available
* wait
* check sync
*/
void _Event_Seize(
rtems_event_set event_in,
rtems_option option_set,
rtems_interval ticks,
rtems_event_set *event_out
)
{
Thread_Control *executing;
rtems_event_set seized_events;
rtems_event_set pending_events;
ISR_Level level;
RTEMS_API_Control *api;
executing = _Thread_Executing;
executing->Wait.return_code = RTEMS_SUCCESSFUL;
api = executing->API_Extensions[ THREAD_API_RTEMS ];
_ISR_Disable( level );
pending_events = api->pending_events;
seized_events = _Event_sets_Get( pending_events, event_in );
if ( !_Event_sets_Is_empty( seized_events ) &&
(seized_events == event_in || _Options_Is_any( option_set )) ) {
api->pending_events =
_Event_sets_Clear( pending_events, seized_events );
_ISR_Enable( level );
*event_out = seized_events;
return;
}
if ( _Options_Is_no_wait( option_set ) ) {
_ISR_Enable( level );
executing->Wait.return_code = RTEMS_UNSATISFIED;
*event_out = seized_events;
return;
}
_Event_Sync = TRUE;
executing->Wait.option = (unsigned32) option_set;
executing->Wait.count = (unsigned32) event_in;
executing->Wait.return_argument = event_out;
_ISR_Enable( level );
_Thread_Set_state( executing, STATES_WAITING_FOR_EVENT );
if ( ticks ) {
_Watchdog_Initialize(
&executing->Timer,
_Event_Timeout,
executing->Object.id,
NULL
);
_Watchdog_Insert_ticks(
&executing->Timer,
ticks,
WATCHDOG_NO_ACTIVATE
);
}
_ISR_Disable( level );
if ( _Event_Sync == TRUE ) {
_Event_Sync = FALSE;
if ( ticks )
_Watchdog_Activate( &executing->Timer );
_ISR_Enable( level );
return;
}
_ISR_Enable( level );
(void) _Watchdog_Remove( &executing->Timer );
_Thread_Unblock( executing );
return;
}
/*PAGE
*
* _Event_Surrender
*
* This routines remove a thread from the specified threadq.
*
* Input parameters:
* the_thread - pointer to thread to be dequeued
*
* Output parameters: NONE
*
* INTERRUPT LATENCY:
* before flash
* after flash
* check sync
*/
void _Event_Surrender(
Thread_Control *the_thread
)
{
ISR_Level level;
rtems_event_set pending_events;
rtems_event_set event_condition;
rtems_event_set seized_events;
rtems_option option_set;
RTEMS_API_Control *api;
api = the_thread->API_Extensions[ THREAD_API_RTEMS ];
option_set = (rtems_option) the_thread->Wait.option;
_ISR_Disable( level );
pending_events = api->pending_events;
event_condition = (rtems_event_set) the_thread->Wait.count;
seized_events = _Event_sets_Get( pending_events, event_condition );
if ( !_Event_sets_Is_empty( seized_events ) ) {
if ( _States_Is_waiting_for_event( the_thread->current_state ) ) {
if ( seized_events == event_condition || _Options_Is_any( option_set ) ) {
api->pending_events =
_Event_sets_Clear( pending_events, seized_events );
*(rtems_event_set *)the_thread->Wait.return_argument = seized_events;
_ISR_Flash( level );
if ( !_Watchdog_Is_active( &the_thread->Timer ) ) {
_ISR_Enable( level );
_Thread_Unblock( the_thread );
}
else {
_Watchdog_Deactivate( &the_thread->Timer );
_ISR_Enable( level );
(void) _Watchdog_Remove( &the_thread->Timer );
_Thread_Unblock( the_thread );
}
return;
}
}
else if ( _Thread_Is_executing( the_thread ) && _Event_Sync == TRUE ) {
if ( seized_events == event_condition || _Options_Is_any( option_set ) ) {
api->pending_events = _Event_sets_Clear( pending_events,seized_events );
*(rtems_event_set *)the_thread->Wait.return_argument = seized_events;
_Event_Sync = FALSE;
}
}
}
_ISR_Enable( level );
}
/*PAGE
*
* _Event_Timeout
*
* This routine processes a thread which timeouts while waiting to
* receive an event_set. It is called by the watchdog handler.
*
* Input parameters:
* id - thread id
*
* Output parameters: NONE
*/
void _Event_Timeout(
Objects_Id id,
void *ignored
)
{
Thread_Control *the_thread;
Objects_Locations location;
the_thread = _Thread_Get( id, &location );
switch ( location ) {
case OBJECTS_ERROR:
case OBJECTS_REMOTE: /* impossible */
break;
case OBJECTS_LOCAL:
the_thread->Wait.return_code = RTEMS_TIMEOUT;
_Thread_Unblock( the_thread );
_Thread_Unnest_dispatch();
break;
}
}

View File

@@ -278,7 +278,8 @@ EXTERN void *_CPU_Interrupt_stack_high;
* interrupts (genie, rhino, etc)
*/
#define CPU_INTERRUPT_NUMBER_OF_VECTORS (HPPA_INTERRUPT_MAX)
#define CPU_INTERRUPT_NUMBER_OF_VECTORS (HPPA_INTERRUPT_MAX)
#define CPU_INTERRUPT_MAXIMUM_VECTOR_NUMBER (CPU_INTERRUPT_NUMBER_OF_VECTORS - 1)
/*
* Don't be chintzy here; we don't want to debug these problems
@@ -387,7 +388,7 @@ unsigned32 _CPU_ISR_Get_level( void );
*/
#define _CPU_Context_Initialize( _the_context, _stack_base, _size, \
_new_level, _entry_point ) \
_new_level, _entry_point, _is_fp ) \
do { \
unsigned32 _stack; \
\
@@ -456,6 +457,9 @@ void hppa_cpu_halt(unsigned32 type_of_halt, unsigned32 the_error);
* is implemented in software.
*/
#define CPU_USE_GENERIC_BITFIELD_CODE FALSE
#define CPU_USE_GENERIC_BITFIELD_DATA FALSE
int hppa_rtems_ffs(unsigned int value);
#define _CPU_Bitfield_Find_first_bit( _value, _output ) \
_output = hppa_rtems_ffs(_value)
@@ -477,7 +481,7 @@ int hppa_rtems_ffs(unsigned int value);
#define _CPU_Priority_Mask( _bit_number ) \
( 1 << (_bit_number) )
#define _CPU_Priority_Bits_index( _priority ) \
#define _CPU_Priority_bits_index( _priority ) \
(_priority)
/* end of Priority handler macros */

View File

@@ -143,7 +143,8 @@ EXTERN void *_CPU_Interrupt_stack_high;
* i386 family supports 256 distinct vectors.
*/
#define CPU_INTERRUPT_NUMBER_OF_VECTORS 256
#define CPU_INTERRUPT_NUMBER_OF_VECTORS 256
#define CPU_INTERRUPT_MAXIMUM_VECTOR_NUMBER (CPU_INTERRUPT_NUMBER_OF_VECTORS - 1)
/*
* Minimum size of a thread's stack.
@@ -208,7 +209,7 @@ unsigned32 _CPU_ISR_Get_level( void );
#define CPU_EFLAGS_INTERRUPTS_OFF 0x00003002
#define _CPU_Context_Initialize( _the_context, _stack_base, _size, \
_isr, _entry_point ) \
_isr, _entry_point, _is_fp ) \
do { \
unsigned32 _stack; \
\
@@ -265,6 +266,9 @@ unsigned32 _CPU_ISR_Get_level( void );
* + scan for the highest numbered (MSB) set in a 16 bit bitfield
*/
#define CPU_USE_GENERIC_BITFIELD_CODE FALSE
#define CPU_USE_GENERIC_BITFIELD_DATA FALSE
#define _CPU_Bitfield_Find_first_bit( _value, _output ) \
{ \
register unsigned16 __value_in_register = (_value); \
@@ -292,7 +296,7 @@ unsigned32 _CPU_ISR_Get_level( void );
#define _CPU_Priority_Mask( _bit_number ) \
( 1 << (_bit_number) )
#define _CPU_Priority_Bits_index( _priority ) \
#define _CPU_Priority_bits_index( _priority ) \
(_priority)
/* functions */

View File

@@ -185,7 +185,8 @@ EXTERN void *_CPU_Interrupt_stack_high;
* i960 family supports 256 distinct vectors.
*/
#define CPU_INTERRUPT_NUMBER_OF_VECTORS 256
#define CPU_INTERRUPT_NUMBER_OF_VECTORS 256
#define CPU_INTERRUPT_MAXIMUM_VECTOR_NUMBER (CPU_INTERRUPT_NUMBER_OF_VECTORS - 1)
/*
* Minimum size of a thread's stack.
@@ -252,7 +253,7 @@ unsigned32 _CPU_ISR_Get_level( void );
*/
#define _CPU_Context_Initialize( _the_context, _stack_base, _size, \
_isr, _entry ) \
_isr, _entry, _is_fp ) \
{ CPU_Call_frame *_texit_frame; \
unsigned32 _mask; \
unsigned32 _base_pc; \
@@ -318,6 +319,9 @@ unsigned32 _CPU_ISR_Get_level( void );
* + scan for the highest numbered (MSB) set in a 16 bit bitfield
*/
#define CPU_USE_GENERIC_BITFIELD_CODE FALSE
#define CPU_USE_GENERIC_BITFIELD_DATA FALSE
#define _CPU_Bitfield_Find_first_bit( _value, _output ) \
{ unsigned32 _search = (_value); \
\
@@ -341,7 +345,7 @@ unsigned32 _CPU_ISR_Get_level( void );
#define _CPU_Priority_Mask( _bit_number ) \
( 0x8000 >> (_bit_number) )
#define _CPU_Priority_Bits_index( _priority ) \
#define _CPU_Priority_bits_index( _priority ) \
( 15 - (_priority) )
/* end of Priority handler macros */

View File

@@ -175,7 +175,8 @@ extern char _VBR[];
* m68k family supports 256 distinct vectors.
*/
#define CPU_INTERRUPT_NUMBER_OF_VECTORS 256
#define CPU_INTERRUPT_NUMBER_OF_VECTORS 256
#define CPU_INTERRUPT_MAXIMUM_VECTOR_NUMBER (CPU_INTERRUPT_NUMBER_OF_VECTORS - 1)
/*
* Minimum size of a thread's stack.
@@ -237,7 +238,7 @@ unsigned32 _CPU_ISR_Get_level( void );
*/
#define _CPU_Context_Initialize( _the_context, _stack_base, _size, \
_isr, _entry_point ) \
_isr, _entry_point, _is_fp ) \
do { \
void *_stack; \
\
@@ -301,6 +302,9 @@ unsigned32 _CPU_ISR_Get_level( void );
* have a real 16 bit wide bitfield which operates "correctly."
*/
#define CPU_USE_GENERIC_BITFIELD_CODE FALSE
#define CPU_USE_GENERIC_BITFIELD_DATA FALSE
#if ( M68K_HAS_BFFFO == 1 )
#ifdef NO_UNINITIALIZED_WARNINGS
@@ -327,7 +331,7 @@ unsigned32 _CPU_ISR_Get_level( void );
#else
/* duplicates BFFFO results for 16 bits (i.e., 15-(_priority) in
_CPU_Priority_Bits_index is not needed), handles the 0 case, and
_CPU_Priority_bits_index is not needed), handles the 0 case, and
does not molest _value -- jsg */
#ifndef m68000
#define _CPU_Bitfield_Find_first_bit( _value, _output ) \
@@ -386,7 +390,7 @@ unsigned32 _CPU_ISR_Get_level( void );
#define _CPU_Priority_Mask( _bit_number ) \
( 0x8000 >> (_bit_number) )
#define _CPU_Priority_Bits_index( _priority ) \
#define _CPU_Priority_bits_index( _priority ) \
(_priority)
/* end of Priority handler macros */

View File

@@ -174,9 +174,6 @@ SYM (_ISR_Handler):
* in place to know what vector we got on a 68000 core.
*/
.global SYM (_ISR_Exit)
SYM (_ISR_Exit):
subql #1,SYM (_ISR_Nest_level) | one less nest level
subql #1,SYM (_Thread_Dispatch_disable_level)
| unnest multitasking

View File

@@ -412,7 +412,8 @@ EXTERN void (*_CPU_Thread_dispatch_pointer)();
* by RTEMS.
*/
#define CPU_INTERRUPT_NUMBER_OF_VECTORS 32
#define CPU_INTERRUPT_NUMBER_OF_VECTORS 32
#define CPU_INTERRUPT_MAXIMUM_VECTOR_NUMBER (CPU_INTERRUPT_NUMBER_OF_VECTORS - 1)
/*
* Should be large enough to run all RTEMS tests. This insures
@@ -536,7 +537,7 @@ EXTERN void (*_CPU_Thread_dispatch_pointer)();
*/
#define _CPU_Context_Initialize( _the_context, _stack_base, _size, \
_isr, _entry_point ) \
_isr, _entry_point, _is_fp ) \
{ \
}
@@ -621,11 +622,11 @@ EXTERN void (*_CPU_Thread_dispatch_pointer)();
*
* RTEMS guarantees that (1) will never happen so it is not a concern.
* (2),(3), (4) are handled by the macros _CPU_Priority_mask() and
* _CPU_Priority_Bits_index(). These three form a set of routines
* _CPU_Priority_bits_index(). These three form a set of routines
* which must logically operate together. Bits in the _value are
* set and cleared based on masks built by _CPU_Priority_mask().
* The basic major and minor values calculated by _Priority_Major()
* and _Priority_Minor() are "massaged" by _CPU_Priority_Bits_index()
* and _Priority_Minor() are "massaged" by _CPU_Priority_bits_index()
* to properly range between the values returned by the "find first bit"
* instruction. This makes it possible for _Priority_Get_highest() to
* calculate the major and directly index into the minor table.
@@ -660,11 +661,18 @@ EXTERN void (*_CPU_Thread_dispatch_pointer)();
* bit set
*/
#define CPU_USE_GENERIC_BITFIELD_CODE TRUE
#define CPU_USE_GENERIC_BITFIELD_DATA TRUE
#if (CPU_USE_GENERIC_BITFIELD_CODE == FALSE)
#define _CPU_Bitfield_Find_first_bit( _value, _output ) \
{ \
(_output) = 0; /* do something to prevent warnings */ \
}
#endif
/* end of Bitfield handler macros */
/*
@@ -673,9 +681,13 @@ EXTERN void (*_CPU_Thread_dispatch_pointer)();
* for that routine.
*/
#if (CPU_USE_GENERIC_BITFIELD_CODE == FALSE)
#define _CPU_Priority_Mask( _bit_number ) \
( 1 << (_bit_number) )
#endif
/*
* This routine translates the bit numbers returned by
* _CPU_Bitfield_Find_first_bit() into something suitable for use as
@@ -683,9 +695,13 @@ EXTERN void (*_CPU_Thread_dispatch_pointer)();
* for that routine.
*/
#define _CPU_Priority_Bits_index( _priority ) \
#if (CPU_USE_GENERIC_BITFIELD_CODE == FALSE)
#define _CPU_Priority_bits_index( _priority ) \
(_priority)
#endif
/* end of Priority handler macros */
/* functions */

View File

@@ -541,7 +541,8 @@ EXTERN struct {
* by RTEMS.
*/
#define CPU_INTERRUPT_NUMBER_OF_VECTORS (PPC_INTERRUPT_MAX)
#define CPU_INTERRUPT_NUMBER_OF_VECTORS (PPC_INTERRUPT_MAX)
#define CPU_INTERRUPT_MAXIMUM_VECTOR_NUMBER (CPU_INTERRUPT_NUMBER_OF_VECTORS - 1)
/*
* Should be large enough to run all RTEMS tests. This insures
@@ -682,7 +683,7 @@ EXTERN struct {
#if PPC_ABI == PPC_ABI_POWEROPEN
#define _CPU_Context_Initialize( _the_context, _stack_base, _size, \
_isr, _entry_point ) \
_isr, _entry_point, _is_fp ) \
{ \
unsigned32 sp, *desc; \
\
@@ -816,11 +817,11 @@ EXTERN struct {
*
* RTEMS guarantees that (1) will never happen so it is not a concern.
* (2),(3), (4) are handled by the macros _CPU_Priority_mask() and
* _CPU_Priority_Bits_index(). These three form a set of routines
* _CPU_Priority_bits_index(). These three form a set of routines
* which must logically operate together. Bits in the _value are
* set and cleared based on masks built by _CPU_Priority_mask().
* The basic major and minor values calculated by _Priority_Major()
* and _Priority_Minor() are "massaged" by _CPU_Priority_Bits_index()
* and _Priority_Minor() are "massaged" by _CPU_Priority_bits_index()
* to properly range between the values returned by the "find first bit"
* instruction. This makes it possible for _Priority_Get_highest() to
* calculate the major and directly index into the minor table.
@@ -855,6 +856,9 @@ EXTERN struct {
* bit set
*/
#define CPU_USE_GENERIC_BITFIELD_CODE FALSE
#define CPU_USE_GENERIC_BITFIELD_DATA FALSE
#define _CPU_Bitfield_Find_first_bit( _value, _output ) \
{ \
asm volatile ("cntlzw %0, %1" : "=r" ((_output)), "=r" ((_value)) : \
@@ -879,7 +883,7 @@ EXTERN struct {
* for that routine.
*/
#define _CPU_Priority_Bits_index( _priority ) \
#define _CPU_Priority_bits_index( _priority ) \
(_priority)
/* end of Priority handler macros */

View File

@@ -0,0 +1,118 @@
#
# $Id$
#
This file discusses SPARC specific issues which are important to
this port. The primary topics in this file are:
+ Global Register Usage
+ Stack Frame
+ EF bit in the PSR
Global Register Usage
=====================
This information on register usage is based heavily on a comment in the
file gcc-2.7.0/config/sparc/sparc.h in the the gcc 2.7.0 source.
+ g0 is hardwired to 0
+ On non-v9 systems:
- g1 is free to use as temporary.
- g2-g4 are reserved for applications. Gcc normally uses them as
temporaries, but this can be disabled via the -mno-app-regs option.
- g5 through g7 are reserved for the operating system.
+ On v9 systems:
- g1 and g5 are free to use as temporaries.
- g2-g4 are reserved for applications (the compiler will not normally use
them, but they can be used as temporaries with -mapp-regs).
- g6-g7 are reserved for the operating system.
NOTE: As of gcc 2.7.0 register g1 was used in the following scenarios:
+ as a temporary by the 64 bit sethi pattern
+ when restoring call-preserved registers in large stack frames
RTEMS places no constraints on the usage of the global registers. Although
gcc assumes that either g5-g7 (non-V9) or g6-g7 (V9) are reserved for the
operating system, RTEMS does not assume any special use for them.
Stack Frame
===========
The stack grows downward (i.e. to lower addresses) on the SPARC architecture.
The following is the organization of the stack frame:
| ............... |
fp | |
+-------------------------------+
| |
| Local registers, temporaries, |
| and saved floats | x bytes
| |
sp + x +-------------------------------+
| |
| outgoing parameters past |
| the sixth one | x bytes
| |
sp + 92 +-------------------------------+ *
| | *
| area for callee to save | *
| register arguments | * 24 bytes
| | *
sp + 68 +-------------------------------+ *
| | *
| structure return pointer | * 4 bytes
| | *
sp + 64 +-------------------------------+ *
| | *
| local register set | * 32 bytes
| | *
sp + 32 +-------------------------------+ *
| | *
| input register set | * 32 bytes
| | *
sp +-------------------------------+ *
* = minimal stack frame
x = optional components
EF bit in the PSR
=================
The EF (enable floating point unit) in the PSR is utilized in this port to
prevent non-floating point tasks from performing floating point
operations. This bit is maintained as part of the integer context.
However, the floating point context is switched BEFORE the integer
context. Thus the EF bit in place at the time of the FP switch may
indicate that FP operations are disabled. This occurs on certain task
switches, when the EF bit will be 0 for the outgoing task and thus a fault
will be generated on the first FP operation of the FP context save.
The remedy for this is to enable FP access as the first step in both the
save and restore of the FP context area. This bit will be subsequently
reloaded by the integer context switch.
Two of the scenarios which demonstrate this problem are outlined below:
1. When the first FP task is switched to. The system tasks are not FP and
thus would be unable to restore the FP context of the incoming task.
2. On a deferred FP context switch. In this case, the system might switch
from FP Task A to non-FP Task B and then to FP Task C. In this scenario,
the floating point state must technically be saved by a non-FP task.

View File

@@ -28,7 +28,9 @@
*/
#define ASM
#include <rtems/score/sparc.h>
#include <rtems/score/cpu.h>
/*
* Recent versions of GNU cpp define variables which indicate the
@@ -37,7 +39,9 @@
* have to define these as appropriate.
*/
/* XXX This does not appear to work on gcc 2.7.0 on the sparc */
/* XXX __USER_LABEL_PREFIX__ and __REGISTER_PREFIX__ do not work on gcc 2.7.0 */
/* XXX The following ifdef magic fixes the problem but results in a warning */
/* XXX when compiling assembly code. */
#undef __USER_LABEL_PREFIX__
#ifndef __USER_LABEL_PREFIX__
#define __USER_LABEL_PREFIX__ _
@@ -91,6 +95,16 @@
#define PUBLIC(sym) .globl SYM (sym)
#define EXTERN(sym) .globl SYM (sym)
/*
* Entry for traps which jump to a programmer-specified trap handler.
*/
#define TRAP(_vector, _handler) \
mov %psr, %l0 ; \
sethi %hi(_handler), %l4 ; \
jmp %l4+%lo(_handler); \
mov _vector, %l3
#endif
/* end of include file */

View File

@@ -7,52 +7,115 @@
#include <rtems/system.h>
#include <rtems/score/isr.h>
/* _CPU_Initialize
#if defined(erc32)
#include <erc32.h>
#endif
/*
* This initializes the set of opcodes placed in each trap
* table entry. The routine which installs a handler is responsible
* for filling in the fields for the _handler address and the _vector
* trap type.
*
* The constants following this structure are masks for the fields which
* must be filled in when the handler is installed.
*/
const CPU_Trap_table_entry _CPU_Trap_slot_template = {
0xa1480000, /* mov %psr, %l0 */
0x29000000, /* sethi %hi(_handler), %l4 */
0x81c52000, /* jmp %l4 + %lo(_handler) */
0xa6102000 /* mov _vector, %l3 */
};
/*PAGE
*
* _CPU_Initialize
*
* This routine performs processor dependent initialization.
*
* INPUT PARAMETERS:
* Input Parameters:
* cpu_table - CPU table to initialize
* thread_dispatch - address of disptaching routine
*
* Output Parameters: NONE
*
* NOTE: There is no need to save the pointer to the thread dispatch routine.
* The SPARC's assembly code can reference it directly with no problems.
*/
void _CPU_Initialize(
rtems_cpu_table *cpu_table,
void (*thread_dispatch) /* ignored on this CPU */
void (*thread_dispatch) /* ignored on this CPU */
)
{
void *pointer;
void *pointer;
unsigned32 trap_table_start;
unsigned32 tbr_value;
CPU_Trap_table_entry *old_tbr;
CPU_Trap_table_entry *trap_table;
/*
* The thread_dispatch argument is the address of the entry point
* for the routine called at the end of an ISR once it has been
* decided a context switch is necessary. On some compilation
* systems it is difficult to call a high-level language routine
* from assembly. This allows us to trick these systems.
*
* If you encounter this problem save the entry point in a CPU
* dependent variable.
* Install the executive's trap table. All entries from the original
* trap table are copied into the executive's trap table. This is essential
* since this preserves critical trap handlers such as the window underflow
* and overflow handlers. It is the responsibility of the BSP to provide
* install these in the initial trap table.
*/
trap_table_start = (unsigned32) &_CPU_Trap_Table_area;
if (trap_table_start & (SPARC_TRAP_TABLE_ALIGNMENT-1))
trap_table_start = (trap_table_start + SPARC_TRAP_TABLE_ALIGNMENT) &
~(SPARC_TRAP_TABLE_ALIGNMENT-1);
_CPU_Thread_dispatch_pointer = thread_dispatch;
trap_table = (CPU_Trap_table_entry *) trap_table_start;
sparc_get_tbr( tbr_value );
old_tbr = (CPU_Trap_table_entry *) (tbr_value & 0xfffff000);
memcpy( trap_table, (void *) old_tbr, 256 * sizeof( CPU_Trap_table_entry ) );
sparc_set_tbr( trap_table_start );
/*
* If there is not an easy way to initialize the FP context
* during Context_Initialize, then it is usually easier to
* save an "uninitialized" FP context here and copy it to
* the task's during Context_Initialize.
* This seems to be the most appropriate way to obtain an initial
* FP context on the SPARC. The NULL fp context is copied it to
* the task's FP context during Context_Initialize.
*/
pointer = &_CPU_Null_fp_context;
_CPU_Context_save_fp( &pointer );
/*
* Grab our own copy of the user's CPU table.
*/
_CPU_Table = *cpu_table;
#if defined(erc32)
/*
* ERC32 specific initialization
*/
_ERC32_MEC_Timer_Control_Mirror = 0;
ERC32_MEC.Timer_Control = 0;
ERC32_MEC.Control |= ERC32_CONFIGURATION_POWER_DOWN_ALLOWED;
#endif
}
/*PAGE
*
* _CPU_ISR_Get_level
*
* Input Parameters: NONE
*
* Output Parameters:
* returns the current interrupt level (PIL field of the PSR)
*/
unsigned32 _CPU_ISR_Get_level( void )
@@ -64,134 +127,263 @@ unsigned32 _CPU_ISR_Get_level( void )
return level;
}
/* _CPU_ISR_install_vector
/*PAGE
*
* _CPU_ISR_install_raw_handler
*
* This routine installs the specified handler as a "raw" non-executive
* supported trap handler (a.k.a. interrupt service routine).
*
* Input Parameters:
* vector - trap table entry number plus synchronous
* vs. asynchronous information
* new_handler - address of the handler to be installed
* old_handler - pointer to an address of the handler previously installed
*
* Output Parameters: NONE
* *new_handler - address of the handler previously installed
*
* NOTE:
*
* On the SPARC, there are really only 256 vectors. However, the executive
* has no easy, fast, reliable way to determine which traps are synchronous
* and which are asynchronous. By default, synchronous traps return to the
* instruction which caused the interrupt. So if you install a software
* trap handler as an executive interrupt handler (which is desirable since
* RTEMS takes care of window and register issues), then the executive needs
* to know that the return address is to the trap rather than the instruction
* following the trap.
*
* So vectors 0 through 255 are treated as regular asynchronous traps which
* provide the "correct" return address. Vectors 256 through 512 are assumed
* by the executive to be synchronous and to require that the return address
* be fudged.
*
* If you use this mechanism to install a trap handler which must reexecute
* the instruction which caused the trap, then it should be installed as
* an asynchronous trap. This will avoid the executive changing the return
* address.
*/
void _CPU_ISR_install_raw_handler(
unsigned32 vector,
proc_ptr new_handler,
proc_ptr *old_handler
)
{
unsigned32 real_vector;
CPU_Trap_table_entry *tbr;
CPU_Trap_table_entry *slot;
unsigned32 u32_tbr;
unsigned32 u32_handler;
/*
* Get the "real" trap number for this vector ignoring the synchronous
* versus asynchronous indicator included with our vector numbers.
*/
real_vector = SPARC_REAL_TRAP_NUMBER( vector );
/*
* Get the current base address of the trap table and calculate a pointer
* to the slot we are interested in.
*/
sparc_get_tbr( u32_tbr );
u32_tbr &= 0xfffff000;
tbr = (CPU_Trap_table_entry *) u32_tbr;
slot = &tbr[ real_vector ];
/*
* Get the address of the old_handler from the trap table.
*
* NOTE: The old_handler returned will be bogus if it does not follow
* the RTEMS model.
*/
#define HIGH_BITS_MASK 0xFFFFFC00
#define HIGH_BITS_SHIFT 10
#define LOW_BITS_MASK 0x000003FF
if ( slot->mov_psr_l0 == _CPU_Trap_slot_template.mov_psr_l0 ) {
u32_handler =
((slot->sethi_of_handler_to_l4 & HIGH_BITS_MASK) << HIGH_BITS_SHIFT) |
(slot->jmp_to_low_of_handler_plus_l4 & LOW_BITS_MASK);
*old_handler = (proc_ptr) u32_handler;
} else
*old_handler = 0;
/*
* Copy the template to the slot and then fix it.
*/
*slot = _CPU_Trap_slot_template;
u32_handler = (unsigned32) new_handler;
slot->mov_vector_l3 |= vector;
slot->sethi_of_handler_to_l4 |=
(u32_handler & HIGH_BITS_MASK) >> HIGH_BITS_SHIFT;
slot->jmp_to_low_of_handler_plus_l4 |= (u32_handler & LOW_BITS_MASK);
}
/*PAGE
*
* _CPU_ISR_install_vector
*
* This kernel routine installs the RTEMS handler for the
* specified vector.
*
* Input parameters:
* vector - interrupt vector number
* old_handler - former ISR for this vector number
* new_handler - replacement ISR for this vector number
* vector - interrupt vector number
* new_handler - replacement ISR for this vector number
* old_handler - pointer to former ISR for this vector number
*
* Output parameters: NONE
* Output parameters:
* *old_handler - former ISR for this vector number
*
*/
void _CPU_ISR_install_vector(
unsigned32 vector,
proc_ptr new_handler,
proc_ptr *old_handler
)
{
*old_handler = _ISR_Vector_table[ vector ];
unsigned32 real_vector;
proc_ptr ignored;
/*
* Get the "real" trap number for this vector ignoring the synchronous
* versus asynchronous indicator included with our vector numbers.
*/
real_vector = SPARC_REAL_TRAP_NUMBER( vector );
/*
* If the interrupt vector table is a table of pointer to isr entry
* points, then we need to install the appropriate RTEMS interrupt
* handler for this vector number.
* Return the previous ISR handler.
*/
*old_handler = _ISR_Vector_table[ real_vector ];
/*
* Install the wrapper so this ISR can be invoked properly.
*/
_CPU_ISR_install_raw_handler( vector, _ISR_Handler, &ignored );
/*
* We put the actual user ISR address in '_ISR_vector_table'. This will
* be used by the _ISR_Handler so the user gets control.
*/
_ISR_Vector_table[ vector ] = new_handler;
}
/*PAGE
*
* _CPU_Install_interrupt_stack
*/
void _CPU_Install_interrupt_stack( void )
{
_ISR_Vector_table[ real_vector ] = new_handler;
}
/*PAGE
*
* _CPU_Context_Initialize
*
* This kernel routine initializes the basic non-FP context area associated
* with each thread.
*
* Input parameters:
* the_context - pointer to the context area
* stack_base - address of memory for the SPARC
* size - size in bytes of the stack area
* new_level - interrupt level for this context area
* entry_point - the starting execution point for this this context
* is_fp - TRUE if this context is associated with an FP thread
*
* Output parameters: NONE
*/
/*
* The following constants assist in building a thread's initial context.
*/
#define CPU_FRAME_SIZE (112) /* based on disassembled test code */
#define ADDR_ADJ_OFFSET -8
void _CPU_Context_Initialize(
Context_Control *_the_context,
unsigned32 *_stack_base,
unsigned32 _size,
unsigned32 _new_level,
void *_entry_point
Context_Control *the_context,
unsigned32 *stack_base,
unsigned32 size,
unsigned32 new_level,
void *entry_point,
boolean is_fp
)
{
unsigned32 jmp_addr;
unsigned32 _stack_high; /* highest "stack aligned" address */
unsigned32 _the_size;
unsigned32 stack_high; /* highest "stack aligned" address */
unsigned32 the_size;
unsigned32 tmp_psr;
jmp_addr = (unsigned32) _entry_point;
/*
* On CPUs with stacks which grow down (i.e. SPARC), we build the stack
* based on the _stack_high address.
* based on the stack_high address.
*/
_stack_high = ((unsigned32)(_stack_base) + _size);
_stack_high &= ~(CPU_STACK_ALIGNMENT - 1);
stack_high = ((unsigned32)(stack_base) + size);
stack_high &= ~(CPU_STACK_ALIGNMENT - 1);
_the_size = _size & ~(CPU_STACK_ALIGNMENT - 1);
the_size = size & ~(CPU_STACK_ALIGNMENT - 1);
/* XXX following code is based on unix port */
/*
* XXX SPARC port needs a diagram like this one...
* See /usr/include/sys/stack.h in Solaris 2.3 for a nice
* diagram of the stack.
* See the README in this directory for a diagram of the stack.
*/
_the_context->o7 = jmp_addr + ADDR_ADJ_OFFSET;
_the_context->o6 = (unsigned32)(_stack_high - CPU_FRAME_SIZE);
_the_context->i6 = (unsigned32)(_stack_high);
#if 0
_the_context->rp = jmp_addr + ADDR_ADJ_OFFSET;
_the_context->sp = (unsigned32)(_stack_high - CPU_FRAME_SIZE);
_the_context->fp = (unsigned32)(_stack_high);
#endif
the_context->o7 = ((unsigned32) entry_point) - 8;
the_context->o6_sp = stack_high - CPU_MINIMUM_STACK_FRAME_SIZE;
the_context->i6_fp = stack_high;
_the_context->wim = 0x01;
/*
* Build the PSR for the task. Most everything can be 0 and the
* CWP is corrected during the context switch.
*
* The EF bit determines if the floating point unit is available.
* The FPU is ONLY enabled if the context is associated with an FP task
* and this SPARC model has an FPU.
*/
sparc_get_psr( tmp_psr );
tmp_psr &= ~SPARC_PIL_MASK;
tmp_psr |= (((_new_level) << 8) & SPARC_PIL_MASK);
tmp_psr = (tmp_psr & ~0x07) | 0x07; /* XXX should use num windows */
_the_context->psr = tmp_psr;
tmp_psr &= ~SPARC_PSR_PIL_MASK;
tmp_psr |= (new_level << 8) & SPARC_PSR_PIL_MASK;
tmp_psr &= ~SPARC_PSR_EF_MASK; /* disabled by default */
#if (SPARC_HAS_FPU == 1)
/*
* If this bit is not set, then a task gets a fault when it accesses
* a floating point register. This is a nice way to detect floating
* point tasks which are not currently declared as such.
*/
if ( is_fp )
tmp_psr |= SPARC_PSR_EF_MASK;
#endif
the_context->psr = tmp_psr;
}
/*PAGE
*
* _CPU_Internal_threads_Idle_thread_body
*
* NOTES:
*
* 1. This is the same as the regular CPU independent algorithm.
*
* 2. If you implement this using a "halt", "idle", or "shutdown"
* instruction, then don't forget to put it in an infinite loop.
*
* 3. Be warned. Some processors with onboard DMA have been known
* to stop the DMA if the CPU were put in IDLE mode. This might
* also be a problem with other on-chip peripherals. So use this
* hook with caution.
* Some SPARC implementations have low power, sleep, or idle modes. This
* tries to take advantage of those models.
*/
#if (CPU_PROVIDES_IDLE_THREAD_BODY == TRUE)
/*
* This is the implementation for the erc32.
*
* NOTE: Low power mode was enabled at initialization time.
*/
#if defined(erc32)
void _CPU_Internal_threads_Idle_thread_body( void )
{
for( ; ; )
/* insert your "halt" instruction here */ ;
while (1) {
ERC32_MEC.Power_Down = 0; /* value is irrelevant */
}
}
#endif
#endif /* CPU_PROVIDES_IDLE_THREAD_BODY */

View File

@@ -1,7 +1,7 @@
/* cpu.h
*
* This include file contains information pertaining to the XXX
* processor.
* This include file contains information pertaining to the port of
* the executive to the SPARC processor.
*
* $Id$
*/
@@ -25,16 +25,6 @@ extern "C" {
*
* If TRUE, then they are inlined.
* If FALSE, then a subroutine call is made.
*
* Basically this is an example of the classic trade-off of size
* versus speed. Inlining the call (TRUE) typically increases the
* size of the executive while speeding up the enabling of dispatching.
* [NOTE: In general, the _Thread_Dispatch_disable_level will
* only be 0 or 1 unless you are in an interrupt handler and that
* interrupt handler invokes the executive.] When not inlined
* something calls _Thread_Enable_dispatch which in turns calls
* _Thread_Dispatch. If the enable dispatch is inlined, then
* one subroutine call is avoided entirely.]
*/
#define CPU_INLINE_ENABLE_DISPATCH TRUE
@@ -48,13 +38,10 @@ extern "C" {
* If TRUE, then the loops are unrolled.
* If FALSE, then the loops are not unrolled.
*
* The primary factor in making this decision is the cost of disabling
* and enabling interrupts (_ISR_Flash) versus the cost of rest of the
* body of the loop. On some CPUs, the flash is more expensive than
* one iteration of the loop body. In this case, it might be desirable
* to unroll the loop. It is important to note that on some CPUs, this
* code is the longest interrupt disable period in the executive. So it is
* necessary to strike a balance when setting this parameter.
* This parameter could go either way on the SPARC. The interrupt flash
* code is relatively lengthy given the requirements for nops following
* writes to the psr. But if the clock speed were high enough, this would
* not represent a great deal of time.
*/
#define CPU_UNROLL_ENQUEUE_PRIORITY TRUE
@@ -65,25 +52,11 @@ extern "C" {
* If TRUE, then a stack is allocated in _Interrupt_Manager_initialization.
* If FALSE, nothing is done.
*
* If the CPU supports a dedicated interrupt stack in hardware,
* then it is generally the responsibility of the BSP to allocate it
* and set it up.
*
* If the CPU does not support a dedicated interrupt stack, then
* the porter has two options: (1) execute interrupts on the stack of
* the interrupted task, and (2) have the executive manage a dedicated
* interrupt stack.
*
* If this is TRUE, CPU_ALLOCATE_INTERRUPT_STACK should also be TRUE.
*
* Only one of CPU_HAS_SOFTWARE_INTERRUPT_STACK and
* CPU_HAS_HARDWARE_INTERRUPT_STACK should be set to TRUE. It is
* possible that both are FALSE for a particular CPU. Although it
* is unclear what that would imply about the interrupt processing
* procedure on that CPU.
* The SPARC does not have a dedicated HW interrupt stack and one has
* been implemented in SW.
*/
#define CPU_HAS_SOFTWARE_INTERRUPT_STACK FALSE /* XXX */
#define CPU_HAS_SOFTWARE_INTERRUPT_STACK TRUE
/*
* Does this CPU have hardware support for a dedicated interrupt stack?
@@ -91,25 +64,16 @@ extern "C" {
* If TRUE, then it must be installed during initialization.
* If FALSE, then no installation is performed.
*
* If this is TRUE, CPU_ALLOCATE_INTERRUPT_STACK should also be TRUE.
*
* Only one of CPU_HAS_SOFTWARE_INTERRUPT_STACK and
* CPU_HAS_HARDWARE_INTERRUPT_STACK should be set to TRUE. It is
* possible that both are FALSE for a particular CPU. Although it
* is unclear what that would imply about the interrupt processing
* procedure on that CPU.
* The SPARC does not have a dedicated HW interrupt stack.
*/
#define CPU_HAS_HARDWARE_INTERRUPT_STACK TRUE /* XXX */
#define CPU_HAS_HARDWARE_INTERRUPT_STACK FALSE
/*
* Do we allocate a dedicated interrupt stack in the Interrupt Manager?
*
* If TRUE, then the memory is allocated during initialization.
* If FALSE, then the memory is allocated during initialization.
*
* This should be TRUE is CPU_HAS_SOFTWARE_INTERRUPT_STACK is TRUE
* or CPU_INSTALL_HARDWARE_INTERRUPT_STACK is TRUE.
*/
#define CPU_ALLOCATE_INTERRUPT_STACK TRUE
@@ -119,15 +83,6 @@ extern "C" {
*
* If TRUE, then the FLOATING_POINT task attribute is supported.
* If FALSE, then the FLOATING_POINT task attribute is ignored.
*
* If there is a FP coprocessor such as the i387 or mc68881, then
* the answer is TRUE.
*
* The macro name "SPARC_HAS_FPU" should be made CPU specific.
* It indicates whether or not this CPU model has FP support. For
* example, it would be possible to have an i386_nofp CPU model
* which set this to false to indicate that you have an i386 without
* an i387 and wish to leave floating point support out.
*/
#if ( SPARC_HAS_FPU == 1 )
@@ -141,15 +96,6 @@ extern "C" {
*
* If TRUE, then the FLOATING_POINT task attribute is assumed.
* If FALSE, then the FLOATING_POINT task attribute is followed.
*
* So far, the only CPU in which this option has been used is the
* HP PA-RISC. The HP C compiler and gcc both implicitly use the
* floating point registers to perform integer multiplies. If
* a function which you would not think utilize the FP unit DOES,
* then one can not easily predict which tasks will use the FP hardware.
* In this case, this option should be TRUE.
*
* If CPU_HARDWARE_FP is FALSE, then this should be FALSE as well.
*/
#define CPU_ALL_TASKS_ARE_FP FALSE
@@ -160,10 +106,6 @@ extern "C" {
* If TRUE, then the IDLE task is created as a FLOATING_POINT task
* and it has a floating point context which is switched in and out.
* If FALSE, then the IDLE task does not have a floating point context.
*
* Setting this to TRUE negatively impacts the time required to preempt
* the IDLE task from an interrupt because the floating point context
* must be saved as part of the preemption.
*/
#define CPU_IDLE_TASK_IS_FP FALSE
@@ -181,17 +123,6 @@ extern "C" {
* point task is switched out and restored when the next floating point
* task is restored. The state of the floating point registers between
* those two operations is not specified.
*
* If the floating point context does NOT have to be saved as part of
* interrupt dispatching, then it should be safe to set this to TRUE.
*
* Setting this flag to TRUE results in using a different algorithm
* for deciding when to save and restore the floating point context.
* The deferred FP switch algorithm minimizes the number of times
* the FP context is saved and restored. The FP context is not saved
* until a context switch is made to another, different FP task.
* Thus in a system with only one FP task, the FP context will never
* be saved or restored.
*/
#define CPU_USE_DEFERRED_FP_SWITCH TRUE
@@ -205,19 +136,13 @@ extern "C" {
*
* If FALSE, then use the generic IDLE thread body if the BSP does
* not provide one.
*
* This is intended to allow for supporting processors which have
* a low power or idle mode. When the IDLE thread is executed, then
* the CPU can be powered down.
*
* The order of precedence for selecting the IDLE thread body is:
*
* 1. BSP provided
* 2. CPU dependent (if provided)
* 3. generic (if no BSP and no CPU dependent)
*/
#if (SPARC_HAS_LOW_POWER_MODE == 1)
#define CPU_PROVIDES_IDLE_THREAD_BODY TRUE
#else
#define CPU_PROVIDES_IDLE_THREAD_BODY FALSE
#endif
/*
* Does the stack grow up (toward higher addresses) or down
@@ -225,6 +150,8 @@ extern "C" {
*
* If TRUE, then the grows upward.
* If FALSE, then the grows toward smaller addresses.
*
* The stack grows to lower addresses on the SPARC.
*/
#define CPU_STACK_GROWS_UP FALSE
@@ -236,17 +163,8 @@ extern "C" {
* the minimum requirements of the compiler in order to have as
* much of the critical data area as possible in a cache line.
*
* The placement of this macro in the declaration of the variables
* is based on the syntactically requirements of the GNU C
* "__attribute__" extension. For example with GNU C, use
* the following to force a structures to a 32 byte boundary.
*
* __attribute__ ((aligned (32)))
*
* NOTE: Currently only the Priority Bit Map table uses this feature.
* To benefit from using this, the data must be heavily
* used so it will stay in the cache and used frequently enough
* in the executive to justify turning this on.
* The SPARC does not appear to have particularly strict alignment
* requirements. This value was chosen to take advantages of caches.
*/
#define CPU_STRUCTURE_ALIGNMENT __attribute__ ((aligned (16)))
@@ -255,18 +173,80 @@ extern "C" {
* The following defines the number of bits actually used in the
* interrupt field of the task mode. How those bits map to the
* CPU interrupt levels is defined by the routine _CPU_ISR_Set_level().
*
* The SPARC has 16 interrupt levels in the PIL field of the PSR.
*/
#define CPU_MODES_INTERRUPT_MASK 0x0000000F
/*
* Processor defined structures
*
* Examples structures include the descriptor tables from the i386
* and the processor control structure on the i960ca.
* This structure represents the organization of the minimum stack frame
* for the SPARC. More framing information is required in certain situaions
* such as when there are a large number of out parameters or when the callee
* must save floating point registers.
*/
/* XXX may need to put some structures here. */
#ifndef ASM
typedef struct {
unsigned32 l0;
unsigned32 l1;
unsigned32 l2;
unsigned32 l3;
unsigned32 l4;
unsigned32 l5;
unsigned32 l6;
unsigned32 l7;
unsigned32 i0;
unsigned32 i1;
unsigned32 i2;
unsigned32 i3;
unsigned32 i4;
unsigned32 i5;
unsigned32 i6_fp;
unsigned32 i7;
void *structure_return_address;
/*
* The following are for the callee to save the register arguments in
* should this be necessary.
*/
unsigned32 saved_arg0;
unsigned32 saved_arg1;
unsigned32 saved_arg2;
unsigned32 saved_arg3;
unsigned32 saved_arg4;
unsigned32 saved_arg5;
unsigned32 pad0;
} CPU_Minimum_stack_frame;
#endif /* ASM */
#define CPU_STACK_FRAME_L0_OFFSET 0x00
#define CPU_STACK_FRAME_L1_OFFSET 0x04
#define CPU_STACK_FRAME_L2_OFFSET 0x08
#define CPU_STACK_FRAME_L3_OFFSET 0x0c
#define CPU_STACK_FRAME_L4_OFFSET 0x10
#define CPU_STACK_FRAME_L5_OFFSET 0x14
#define CPU_STACK_FRAME_L6_OFFSET 0x18
#define CPU_STACK_FRAME_L7_OFFSET 0x1c
#define CPU_STACK_FRAME_I0_OFFSET 0x20
#define CPU_STACK_FRAME_I1_OFFSET 0x24
#define CPU_STACK_FRAME_I2_OFFSET 0x28
#define CPU_STACK_FRAME_I3_OFFSET 0x2c
#define CPU_STACK_FRAME_I4_OFFSET 0x30
#define CPU_STACK_FRAME_I5_OFFSET 0x34
#define CPU_STACK_FRAME_I6_FP_OFFSET 0x38
#define CPU_STACK_FRAME_I7_OFFSET 0x3c
#define CPU_STRUCTURE_RETURN_ADDRESS_OFFSET 0x40
#define CPU_STACK_FRAME_SAVED_ARG0_OFFSET 0x44
#define CPU_STACK_FRAME_SAVED_ARG1_OFFSET 0x48
#define CPU_STACK_FRAME_SAVED_ARG2_OFFSET 0x4c
#define CPU_STACK_FRAME_SAVED_ARG3_OFFSET 0x50
#define CPU_STACK_FRAME_SAVED_ARG4_OFFSET 0x54
#define CPU_STACK_FRAME_SAVED_ARG5_OFFSET 0x58
#define CPU_STACK_FRAME_PAD0_OFFSET 0x5c
#define CPU_MINIMUM_STACK_FRAME_SIZE 0x60
/*
* Contexts
@@ -280,35 +260,21 @@ extern "C" {
* 2. floating point task stuff:: Context_Control_fp
* 3. special interrupt level context :: Context_Control_interrupt
*
* On some processors, it is cost-effective to save only the callee
* preserved registers during a task context switch. This means
* that the ISR code needs to save those registers which do not
* persist across function calls. It is not mandatory to make this
* distinctions between the caller/callee saves registers for the
* purpose of minimizing context saved during task switch and on interrupts.
* If the cost of saving extra registers is minimal, simplicity is the
* choice. Save the same context on interrupt entry as for tasks in
* this case.
*
* Additionally, if gdb is to be made aware of tasks for this CPU, then
* care should be used in designing the context area.
*
* On some CPUs with hardware floating point support, the Context_Control_fp
* structure will not be used or it simply consist of an array of a
* fixed number of bytes. This is done when the floating point context
* is dumped by a "FP save context" type instruction and the format
* is not really defined by the CPU. In this case, there is no need
* to figure out the exact format -- only the size. Of course, although
* this is enough information for context switches, it is probably not
* enough for a debugger such as gdb. But that is another problem.
* On the SPARC, we are relatively conservative in that we save most
* of the CPU state in the context area. The ET (enable trap) bit and
* the CWP (current window pointer) fields of the PSR are considered
* system wide resources and are not maintained on a per-thread basis.
*/
#ifndef ASM
/* XXX */
typedef struct {
unsigned32 g0;
unsigned32 g1;
/*
* Using a double g0_g1 will put everything in this structure on a
* double word boundary which allows us to use double word loads
* and stores safely in the context switch.
*/
double g0_g1;
unsigned32 g2;
unsigned32 g3;
unsigned32 g4;
@@ -331,7 +297,7 @@ typedef struct {
unsigned32 i3;
unsigned32 i4;
unsigned32 i5;
unsigned32 i6;
unsigned32 i6_fp;
unsigned32 i7;
unsigned32 o0;
@@ -340,10 +306,9 @@ typedef struct {
unsigned32 o3;
unsigned32 o4;
unsigned32 o5;
unsigned32 o6;
unsigned32 o6_sp;
unsigned32 o7;
unsigned32 wim;
unsigned32 psr;
} Context_Control;
@@ -377,7 +342,7 @@ typedef struct {
#define I3_OFFSET 0x4C
#define I4_OFFSET 0x50
#define I5_OFFSET 0x54
#define I6_OFFSET 0x58
#define I6_FP_OFFSET 0x58
#define I7_OFFSET 0x5C
#define O0_OFFSET 0x60
@@ -386,15 +351,19 @@ typedef struct {
#define O3_OFFSET 0x6C
#define O4_OFFSET 0x70
#define O5_OFFSET 0x74
#define O6_OFFSET 0x78
#define O6_SP_OFFSET 0x78
#define O7_OFFSET 0x7C
#define WIM_OFFSET 0x80
#define PSR_OFFSET 0x84
#define PSR_OFFSET 0x80
#define CONTEXT_CONTROL_SIZE 0x84
/*
* The floating point context area.
*/
#ifndef ASM
/* XXX */
typedef struct {
double f0_f1;
double f2_f3;
@@ -439,10 +408,39 @@ typedef struct {
#define F3O_F31_OFFSET 0x78
#define FSR_OFFSET 0x80
#define CONTEXT_CONTROL_FP_SIZE 0x84
#ifndef ASM
/*
* Context saved on stack for an interrupt.
*
* NOTE: The PSR, PC, and NPC are only saved in this structure for the
* benefit of the user's handler.
*/
typedef struct {
unsigned32 special_interrupt_register_XXX;
CPU_Minimum_stack_frame Stack_frame;
unsigned32 psr;
unsigned32 pc;
unsigned32 npc;
unsigned32 g1;
unsigned32 g2;
unsigned32 g3;
unsigned32 g4;
unsigned32 g5;
unsigned32 g6;
unsigned32 g7;
unsigned32 i0;
unsigned32 i1;
unsigned32 i2;
unsigned32 i3;
unsigned32 i4;
unsigned32 i5;
unsigned32 i6_fp;
unsigned32 i7;
unsigned32 y;
unsigned32 pad0_offset;
} CPU_Interrupt_frame;
#endif /* ASM */
@@ -451,11 +449,34 @@ typedef struct {
* Offsets of fields with CPU_Interrupt_frame for assembly routines.
*/
#define ISF_STACK_FRAME_OFFSET 0x00
#define ISF_PSR_OFFSET CPU_MINIMUM_STACK_FRAME_SIZE + 0x00
#define ISF_PC_OFFSET CPU_MINIMUM_STACK_FRAME_SIZE + 0x04
#define ISF_NPC_OFFSET CPU_MINIMUM_STACK_FRAME_SIZE + 0x08
#define ISF_G1_OFFSET CPU_MINIMUM_STACK_FRAME_SIZE + 0x0c
#define ISF_G2_OFFSET CPU_MINIMUM_STACK_FRAME_SIZE + 0x10
#define ISF_G3_OFFSET CPU_MINIMUM_STACK_FRAME_SIZE + 0x14
#define ISF_G4_OFFSET CPU_MINIMUM_STACK_FRAME_SIZE + 0x18
#define ISF_G5_OFFSET CPU_MINIMUM_STACK_FRAME_SIZE + 0x1c
#define ISF_G6_OFFSET CPU_MINIMUM_STACK_FRAME_SIZE + 0x20
#define ISF_G7_OFFSET CPU_MINIMUM_STACK_FRAME_SIZE + 0x24
#define ISF_I0_OFFSET CPU_MINIMUM_STACK_FRAME_SIZE + 0x28
#define ISF_I1_OFFSET CPU_MINIMUM_STACK_FRAME_SIZE + 0x2c
#define ISF_I2_OFFSET CPU_MINIMUM_STACK_FRAME_SIZE + 0x30
#define ISF_I3_OFFSET CPU_MINIMUM_STACK_FRAME_SIZE + 0x34
#define ISF_I4_OFFSET CPU_MINIMUM_STACK_FRAME_SIZE + 0x38
#define ISF_I5_OFFSET CPU_MINIMUM_STACK_FRAME_SIZE + 0x3c
#define ISF_I6_FP_OFFSET CPU_MINIMUM_STACK_FRAME_SIZE + 0x40
#define ISF_I7_OFFSET CPU_MINIMUM_STACK_FRAME_SIZE + 0x44
#define ISF_Y_OFFSET CPU_MINIMUM_STACK_FRAME_SIZE + 0x48
#define ISF_PAD0_OFFSET CPU_MINIMUM_STACK_FRAME_SIZE + 0x4c
#define CONTEXT_CONTROL_INTERRUPT_FRAME_SIZE CPU_MINIMUM_STACK_FRAME_SIZE + 0x50
#ifndef ASM
/*
* The following table contains the information required to configure
* the XXX processor specific parameters.
* the processor specific parameters.
*
* NOTE: The interrupt_stack_size field is required if
* CPU_ALLOCATE_INTERRUPT_STACK is defined as TRUE.
@@ -472,61 +493,97 @@ typedef struct {
boolean do_zero_of_workspace;
unsigned32 interrupt_stack_size;
unsigned32 extra_system_initialization_stack;
unsigned32 some_other_cpu_dependent_info_XXX;
} rtems_cpu_table;
/*
* This variable is optional. It is used on CPUs on which it is difficult
* to generate an "uninitialized" FP context. It is filled in by
* _CPU_Initialize and copied into the task's FP context area during
* _CPU_Context_Initialize.
* This variable is contains the initialize context for the FP unit.
* It is filled in by _CPU_Initialize and copied into the task's FP
* context area during _CPU_Context_Initialize.
*/
EXTERN Context_Control_fp _CPU_Null_fp_context CPU_STRUCTURE_ALIGNMENT;
/*
* On some CPUs, software managed interrupt stack is supported.
* This stack is allocated by the Interrupt Manager and the switch
* is performed in _ISR_Handler. These variables contain pointers
* to the lowest and highest addresses in the chunk of memory allocated
* for the interrupt stack. Since it is unknown whether the stack
* grows up or down (in general), this give the CPU dependent
* code the option of picking the version it wants to use.
* code the option of picking the version it wants to use. Thus
* both must be present if either is.
*
* NOTE: These two variables are required if the macro
* CPU_HAS_SOFTWARE_INTERRUPT_STACK is defined as TRUE.
* The SPARC supports a software based interrupt stack and these
* are required.
*/
EXTERN void *_CPU_Interrupt_stack_low;
EXTERN void *_CPU_Interrupt_stack_high;
EXTERN void *_CPU_Interrupt_stack_low;
EXTERN void *_CPU_Interrupt_stack_high;
#if defined(erc32)
/*
* With some compilation systems, it is difficult if not impossible to
* call a high-level language routine from assembly language. This
* is especially true of commercial Ada compilers and name mangling
* C++ ones. This variable can be optionally defined by the CPU porter
* and contains the address of the routine _Thread_Dispatch. This
* can make it easier to invoke that routine at the end of the interrupt
* sequence (if a dispatch is necessary).
* ERC32 Specific Variables
*/
EXTERN void (*_CPU_Thread_dispatch_pointer)();
EXTERN unsigned32 _ERC32_MEC_Timer_Control_Mirror;
#endif
/*
* Nothing prevents the porter from declaring more CPU specific variables.
* The following type defines an entry in the SPARC's trap table.
*
* NOTE: The instructions chosen are RTEMS dependent although one is
* obligated to use two of the four instructions to perform a
* long jump. The other instructions load one register with the
* trap type (a.k.a. vector) and another with the psr.
*/
/* XXX: if needed, put more variables here */
typedef struct {
unsigned32 mov_psr_l0; /* mov %psr, %l0 */
unsigned32 sethi_of_handler_to_l4; /* sethi %hi(_handler), %l4 */
unsigned32 jmp_to_low_of_handler_plus_l4; /* jmp %l4 + %lo(_handler) */
unsigned32 mov_vector_l3; /* mov _vector, %l3 */
} CPU_Trap_table_entry;
/*
* This is the set of opcodes for the instructions loaded into a trap
* table entry. The routine which installs a handler is responsible
* for filling in the fields for the _handler address and the _vector
* trap type.
*
* The constants following this structure are masks for the fields which
* must be filled in when the handler is installed.
*/
extern const CPU_Trap_table_entry _CPU_Trap_slot_template;
/*
* The size of the floating point context area. On some CPUs this
* will not be a "sizeof" because the format of the floating point
* area is not defined -- only the size is. This is usually on
* CPUs with a "floating point save context" instruction.
* This is the executive's trap table which is installed into the TBR
* register.
*
* NOTE: Unfortunately, this must be aligned on a 4096 byte boundary.
* The GNU tools as of binutils 2.5.2 and gcc 2.7.0 would not
* align an entity to anything greater than a 512 byte boundary.
*
* Because of this, we pull a little bit of a trick. We allocate
* enough memory so we can grab an address on a 4096 byte boundary
* from this area.
*/
#define SPARC_TRAP_TABLE_ALIGNMENT 4096
EXTERN unsigned8 _CPU_Trap_Table_area[ 8192 ]
__attribute__ ((aligned (SPARC_TRAP_TABLE_ALIGNMENT)));
/*
* The size of the floating point context area.
*/
#define CPU_CONTEXT_FP_SIZE sizeof( Context_Control_fp )
#endif
/*
* Amount of extra stack (above minimum stack size) required by
* system initialization thread. Remember that in a multiprocessor
@@ -538,23 +595,55 @@ EXTERN void (*_CPU_Thread_dispatch_pointer)();
/*
* This defines the number of entries in the ISR_Vector_table managed
* by the executive.
*
* On the SPARC, there are really only 256 vectors. However, the executive
* has no easy, fast, reliable way to determine which traps are synchronous
* and which are asynchronous. By default, synchronous traps return to the
* instruction which caused the interrupt. So if you install a software
* trap handler as an executive interrupt handler (which is desirable since
* RTEMS takes care of window and register issues), then the executive needs
* to know that the return address is to the trap rather than the instruction
* following the trap.
*
* So vectors 0 through 255 are treated as regular asynchronous traps which
* provide the "correct" return address. Vectors 256 through 512 are assumed
* by the executive to be synchronous and to require that the return address
* be fudged.
*
* If you use this mechanism to install a trap handler which must reexecute
* the instruction which caused the trap, then it should be installed as
* an asynchronous trap. This will avoid the executive changing the return
* address.
*/
#define CPU_INTERRUPT_NUMBER_OF_VECTORS 255
#define CPU_INTERRUPT_NUMBER_OF_VECTORS 256
#define CPU_INTERRUPT_MAXIMUM_VECTOR_NUMBER 511
#define SPARC_SYNCHRONOUS_TRAP_BIT_MASK 0x100
#define SPARC_ASYNCHRONOUS_TRAP( _trap ) (_trap)
#define SPARC_SYNCHRONOUS_TRAP( _trap ) ((_trap) + 256 )
#define SPARC_REAL_TRAP_NUMBER( _trap ) ((_trap) % 256)
/*
* Should be large enough to run all tests. This insures
* that a "reasonable" small application should not have any problems.
*
* This appears to be a fairly generous number for the SPARC since
* represents a call depth of about 20 routines based on the minimum
* stack frame.
*/
#define CPU_STACK_MINIMUM_SIZE (1024*2)
#define CPU_STACK_MINIMUM_SIZE (1024*2)
/*
* CPU's worst alignment requirement for data types on a byte boundary. This
* alignment does not take into account the requirements for the stack.
*
* On the SPARC, this is required for double word loads and stores.
*/
#define CPU_ALIGNMENT 8
#define CPU_ALIGNMENT 8
/*
* This number corresponds to the byte alignment requirement for the
@@ -591,12 +680,15 @@ EXTERN void (*_CPU_Thread_dispatch_pointer)();
* is strict enough for the stack, then this should be set to 0.
*
* NOTE: This must be a power of 2 either 0 or greater than CPU_ALIGNMENT.
*
* The alignment restrictions for the SPARC are not that strict but this
* should unsure that the stack is always sufficiently alignment that the
* window overflow, underflow, and flush routines can use double word loads
* and stores.
*/
#define CPU_STACK_ALIGNMENT 16
#endif /* ASM */
#ifndef ASM
/* ISR handler macros */
@@ -631,12 +723,7 @@ EXTERN void (*_CPU_Thread_dispatch_pointer)();
/*
* 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 generic fashion are undefined. Someday,
* it would be nice if these were "mapped" by the application
* via a callout. For example, m68k has 8 levels 0 - 7, levels
* 8 - 255 would be available for bsp/application specific meaning.
* This could be used to manage a programmable interrupt controller
* via the rtems_task_mode directive.
* map onto the CPU in a straight fashion are undefined.
*/
#define _CPU_ISR_Set_level( _newlevel ) \
@@ -659,46 +746,33 @@ unsigned32 _CPU_ISR_Get_level( void );
* - setting the proper interrupt level in the context
* - initializing the floating point context
*
* This routine generally does not set any unnecessary register
* in the context. The state of the "general data" registers is
* undefined at task start time.
*
* NOTE: Implemented as a subroutine for the SPARC port.
*/
void _CPU_Context_Initialize(
Context_Control *_the_context,
unsigned32 *_stack_base,
unsigned32 _size,
unsigned32 _new_level,
void *_entry_point
Context_Control *the_context,
unsigned32 *stack_base,
unsigned32 size,
unsigned32 new_level,
void *entry_point,
boolean is_fp
);
/*
* This routine is responsible for somehow restarting the currently
* executing task. If you are lucky, then all that is necessary
* is restoring the context. Otherwise, there will need to be
* a special assembly routine which does something special in this
* case. Context_Restore should work most of the time. It will
* not work if restarting self conflicts with the stack frame
* assumptions of restoring a context.
* executing task.
*
* On the SPARC, this is is relatively painless but requires a small
* amount of wrapper code before using the regular restore code in
* of the context switch.
*/
#define _CPU_Context_Restart_self( _the_context ) \
_CPU_Context_restore( (_the_context) );
/*
* The purpose of this macro is to allow the initial pointer into
* a floating point context area (used to save the floating point
* context) to be at an arbitrary place in the floating point
* context area.
*
* This is necessary because some FP units are designed to have
* their context saved as a stack which grows into lower addresses.
* Other FP units can be saved by simply moving registers into offsets
* from the base of the context area. Finally some FP units provide
* a "dump context" instruction which could fill in from high to low
* or low to high based on the whim of the CPU designers.
* The FP context area for the SPARC is a simple structure and nothing
* special is required to find the "starting load point"
*/
#define _CPU_Context_Fp_start( _base, _offset ) \
@@ -706,20 +780,17 @@ void _CPU_Context_Initialize(
/*
* This routine initializes the FP context area passed to it to.
* There are a few standard ways in which to initialize the
* floating point context. The code included for this macro assumes
* that this is a CPU in which a "initial" FP context was saved into
* _CPU_Null_fp_context and it simply copies it to the destination
* context passed to it.
*
* Other models include (1) not doing anything, and (2) putting
* a "null FP status word" in the correct place in the FP context.
* The SPARC allows us to use the simple initialization model
* in which an "initial" FP context was saved into _CPU_Null_fp_context
* at CPU initialization and it is simply copied into the destination
* context.
*/
#define _CPU_Context_Initialize_fp( _destination ) \
{ \
do { \
*((Context_Control_fp *) *((void **) _destination)) = _CPU_Null_fp_context; \
}
} while (0)
/* end of Context handler macros */
@@ -732,122 +803,42 @@ void _CPU_Context_Initialize(
*/
#define _CPU_Fatal_halt( _error ) \
{ \
}
do { \
unsigned32 level; \
\
sparc_disable_interrupts( level ); \
asm volatile ( "mov %0, %%g1 " : "=r" (level) : "0" (level) ); \
while (1); /* loop forever */ \
} while (0)
/* end of Fatal Error manager macros */
/* Bitfield handler macros */
/*
* This routine sets _output to the bit number of the first bit
* set in _value. _value is of CPU dependent type Priority_Bit_map_control.
* This type may be either 16 or 32 bits wide although only the 16
* least significant bits will be used.
*
* There are a number of variables in using a "find first bit" type
* instruction.
*
* (1) What happens when run on a value of zero?
* (2) Bits may be numbered from MSB to LSB or vice-versa.
* (3) The numbering may be zero or one based.
* (4) The "find first bit" instruction may search from MSB or LSB.
*
* The executive guarantees that (1) will never happen so it is not a concern.
* (2),(3), (4) are handled by the macros _CPU_Priority_mask() and
* _CPU_Priority_Bits_index(). These three form a set of routines
* which must logically operate together. Bits in the _value are
* set and cleared based on masks built by _CPU_Priority_mask().
* The basic major and minor values calculated by _Priority_Major()
* and _Priority_Minor() are "massaged" by _CPU_Priority_Bits_index()
* to properly range between the values returned by the "find first bit"
* instruction. This makes it possible for _Priority_Get_highest() to
* calculate the major and directly index into the minor table.
* This mapping is necessary to ensure that 0 (a high priority major/minor)
* is the first bit found.
*
* This entire "find first bit" and mapping process depends heavily
* on the manner in which a priority is broken into a major and minor
* components with the major being the 4 MSB of a priority and minor
* the 4 LSB. Thus (0 << 4) + 0 corresponds to priority 0 -- the highest
* priority. And (15 << 4) + 14 corresponds to priority 254 -- the next
* to the lowest priority.
*
* If your CPU does not have a "find first bit" instruction, then
* there are ways to make do without it. Here are a handful of ways
* to implement this in software:
*
* - a series of 16 bit test instructions
* - a "binary search using if's"
* - _number = 0
* if _value > 0x00ff
* _value >>=8
* _number = 8;
*
* if _value > 0x0000f
* _value >=8
* _number += 4
*
* _number += bit_set_table[ _value ]
*
* where bit_set_table[ 16 ] has values which indicate the first
* bit set
* The SPARC port uses the generic C algorithm for bitfield scan if the
* CPU model does not have a scan instruction.
*/
#ifndef INIT
extern const unsigned char __log2table[256];
#if ( SPARC_HAS_BITSCAN == 0 )
#define CPU_USE_GENERIC_BITFIELD_CODE TRUE
#define CPU_USE_GENERIC_BITFIELD_DATA TRUE
#else
const unsigned char __log2table[256] = {
0, 0, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3,
4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7
};
#error "scan instruction not currently supported by RTEMS!!"
#endif
#define _CPU_Bitfield_Find_first_bit( _value, _output ) \
{ \
register __value = (_value); \
\
if ( !(__value & 0xff00) ) \
(_output) = __log2table[ __value ]; \
else \
(_output) = __log2table[ __value >> 8 ] + 8; \
}
/* end of Bitfield handler macros */
/*
* This routine builds the mask which corresponds to the bit fields
* as searched by _CPU_Bitfield_Find_first_bit(). See the discussion
* for that routine.
*/
#define _CPU_Priority_Mask( _bit_number ) \
( 0x8000 >> (_bit_number) )
/* Priority handler handler macros */
/*
* This routine translates the bit numbers returned by
* _CPU_Bitfield_Find_first_bit() into something suitable for use as
* a major or minor component of a priority. See the discussion
* for that routine.
* The SPARC port uses the generic C algorithm for bitfield scan if the
* CPU model does not have a scan instruction.
*/
#define _CPU_Priority_Bits_index( _priority ) \
(15 - (_priority))
#if ( SPARC_HAS_BITSCAN == 1 )
#error "scan instruction not currently supported by RTEMS!!"
#endif
/* end of Priority handler macros */
@@ -864,6 +855,19 @@ void _CPU_Initialize(
void (*thread_dispatch)
);
/*
* _CPU_ISR_install_raw_handler
*
* This routine installs new_handler to be directly called from the trap
* table.
*/
void _CPU_ISR_install_raw_handler(
unsigned32 vector,
proc_ptr new_handler,
proc_ptr *old_handler
);
/*
* _CPU_ISR_install_vector
*
@@ -876,27 +880,18 @@ void _CPU_ISR_install_vector(
proc_ptr *old_handler
);
/*
* _CPU_Install_interrupt_stack
*
* This routine installs the hardware interrupt stack pointer.
*
* NOTE: It need only be provided if CPU_HAS_HARDWARE_INTERRUPT_STACK
* is TRUE.
*/
void _CPU_Install_interrupt_stack( void );
#if (CPU_PROVIDES_IDLE_THREAD_BODY == TRUE)
/*
* _CPU_Internal_threads_Idle_thread_body
*
* This routine is the CPU dependent IDLE thread body.
*
* NOTE: It need only be provided if CPU_PROVIDES_IDLE_THREAD_BODY
* is TRUE.
* Some SPARC implementations have low power, sleep, or idle modes. This
* tries to take advantage of those models.
*/
void _CPU_Internal_threads_Idle_thread_body( void );
#endif /* CPU_PROVIDES_IDLE_THREAD_BODY */
/*
* _CPU_Context_switch
@@ -913,9 +908,7 @@ void _CPU_Context_switch(
* _CPU_Context_restore
*
* This routine is generallu used only to restart self in an
* efficient manner. It may simply be a label in _CPU_Context_switch.
*
* NOTE: May be unnecessary to reload some registers.
* efficient manner.
*/
void _CPU_Context_restore(
@@ -942,24 +935,23 @@ void _CPU_Context_restore_fp(
void **fp_context_ptr
);
/* The following routine swaps the endian format of an unsigned int.
/*
* CPU_swap_u32
*
* The following routine swaps the endian format of an unsigned int.
* It must be static because it is referenced indirectly.
*
* This version will work on any processor, but if there is a better
* way for your CPU PLEASE use it. The most common way to do this is to:
* This version will work on any processor, but if you come across a better
* way for the SPARC PLEASE use it. The most common way to swap a 32-bit
* entity as shown below is not any more efficient on the SPARC.
*
* swap least significant two bytes with 16-bit rotate
* swap upper and lower 16-bits
* swap most significant two bytes with 16-bit rotate
*
* Some CPUs have special instructions which swap a 32-bit quantity in
* a single instruction (e.g. i486). It is probably best to avoid
* an "endian swapping control bit" in the CPU. One good reason is
* that interrupts would probably have to be disabled to insure that
* an interrupt does not try to access the same "chunk" with the wrong
* endian. Another good reason is that on some CPUs, the endian bit
* endianness for ALL fetches -- both code and data -- so the code
* will be fetched incorrectly.
* It is not obvious how the SPARC can do significantly better than the
* generic code. gcc 2.7.0 only generates about 12 instructions for the
* following code at optimization level four (i.e. -O4).
*/
static inline unsigned int CPU_swap_u32(

View File

@@ -2,7 +2,7 @@
*
* This file contains the basic algorithms for all assembly code used
* in an specific CPU port of RTEMS. These algorithms must be implemented
* in assembly language
* in assembly language.
*
* $Id$
*/
@@ -10,319 +10,680 @@
#include <asm.h>
#include <rtems/score/cpu.h>
#if (SPARC_HAS_FPU == 1)
/*
* _CPU_Context_save_fp
* void _CPU_Context_save_fp(
* void **fp_context_ptr
* )
*
* This routine is responsible for saving the FP context
* at *fp_context_ptr. If the point to load the FP context
* from is changed then the pointer is modified by this routine.
*
* Sometimes a macro implementation of this is in cpu.h which dereferences
* the ** and a similarly named routine in this file is passed something
* like a (Context_Control_fp *). The general rule on making this decision
* is to avoid writing assembly language.
*
* void _CPU_Context_save_fp(
* void **fp_context_ptr
* )
* {
* }
* NOTE: See the README in this directory for information on the
* management of the "EF" bit in the PSR.
*/
.align 4
PUBLIC(_CPU_Context_save_fp)
SYM(_CPU_Context_save_fp):
save %sp,-104,%sp
ld [%i0],%l0
std %f0,[%l0+FO_F1_OFFSET]
std %f2,[%l0+F2_F3_OFFSET]
std %f4,[%l0+F4_F5_OFFSET]
std %f6,[%l0+F6_F7_OFFSET]
std %f8,[%l0+F8_F9_OFFSET]
std %f10,[%l0+F1O_F11_OFFSET]
std %f12,[%l0+F12_F13_OFFSET]
std %f14,[%l0+F14_F15_OFFSET]
std %f16,[%l0+F16_F17_OFFSET]
std %f18,[%l0+F18_F19_OFFSET]
std %f20,[%l0+F2O_F21_OFFSET]
std %f22,[%l0+F22_F23_OFFSET]
std %f24,[%l0+F24_F25_OFFSET]
std %f26,[%l0+F26_F27_OFFSET]
std %f28,[%l0+F28_F29_OFFSET]
std %f30,[%l0+F3O_F31_OFFSET]
st %fsr,[%l0+FSR_OFFSET]
save %sp, -CPU_MINIMUM_STACK_FRAME_SIZE, %sp
/*
* The following enables the floating point unit.
*/
mov %psr, %l0
sethi %hi(SPARC_PSR_EF_MASK), %l1
or %l1, %lo(SPARC_PSR_EF_MASK), %l1
or %l0, %l1, %l0
mov %l0, %psr ! **** ENABLE FLOAT ACCESS ****
ld [%i0], %l0
std %f0, [%l0 + FO_F1_OFFSET]
std %f2, [%l0 + F2_F3_OFFSET]
std %f4, [%l0 + F4_F5_OFFSET]
std %f6, [%l0 + F6_F7_OFFSET]
std %f8, [%l0 + F8_F9_OFFSET]
std %f10, [%l0 + F1O_F11_OFFSET]
std %f12, [%l0 + F12_F13_OFFSET]
std %f14, [%l0 + F14_F15_OFFSET]
std %f16, [%l0 + F16_F17_OFFSET]
std %f18, [%l0 + F18_F19_OFFSET]
std %f20, [%l0 + F2O_F21_OFFSET]
std %f22, [%l0 + F22_F23_OFFSET]
std %f24, [%l0 + F24_F25_OFFSET]
std %f26, [%l0 + F26_F27_OFFSET]
std %f28, [%l0 + F28_F29_OFFSET]
std %f30, [%l0 + F3O_F31_OFFSET]
st %fsr, [%l0 + FSR_OFFSET]
ret
restore
/*
* _CPU_Context_restore_fp
* void _CPU_Context_restore_fp(
* void **fp_context_ptr
* )
*
* This routine is responsible for restoring the FP context
* at *fp_context_ptr. If the point to load the FP context
* from is changed then the pointer is modified by this routine.
*
* Sometimes a macro implementation of this is in cpu.h which dereferences
* the ** and a similarly named routine in this file is passed something
* like a (Context_Control_fp *). The general rule on making this decision
* is to avoid writing assembly language.
*
* void _CPU_Context_restore_fp(
* void **fp_context_ptr
* )
* {
* }
* NOTE: See the README in this directory for information on the
* management of the "EF" bit in the PSR.
*/
.align 4
PUBLIC(_CPU_Context_restore_fp)
SYM(_CPU_Context_restore_fp):
save %sp,-104,%sp
ld [%o0],%l0
ldd [%l0+FO_F1_OFFSET],%f0
ldd [%l0+F2_F3_OFFSET],%f2
ldd [%l0+F4_F5_OFFSET],%f4
ldd [%l0+F6_F7_OFFSET],%f6
ldd [%l0+F8_F9_OFFSET],%f8
ldd [%l0+F1O_F11_OFFSET],%f10
ldd [%l0+F12_F13_OFFSET],%f12
ldd [%l0+F14_F15_OFFSET],%f14
ldd [%l0+F16_F17_OFFSET],%f16
ldd [%l0+F18_F19_OFFSET],%f18
ldd [%l0+F2O_F21_OFFSET],%f20
ldd [%l0+F22_F23_OFFSET],%f22
ldd [%l0+F24_F25_OFFSET],%f24
ldd [%l0+F26_F27_OFFSET],%f26
ldd [%l0+F28_F29_OFFSET],%f28
ldd [%l0+F3O_F31_OFFSET],%f30
ld [%l0+FSR_OFFSET],%fsr
save %sp, -CPU_MINIMUM_STACK_FRAME_SIZE , %sp
/*
* The following enables the floating point unit.
*/
mov %psr, %l0
sethi %hi(SPARC_PSR_EF_MASK), %l1
or %l1, %lo(SPARC_PSR_EF_MASK), %l1
or %l0, %l1, %l0
mov %l0, %psr ! **** ENABLE FLOAT ACCESS ****
ld [%i0], %l0
ldd [%l0 + FO_F1_OFFSET], %f0
ldd [%l0 + F2_F3_OFFSET], %f2
ldd [%l0 + F4_F5_OFFSET], %f4
ldd [%l0 + F6_F7_OFFSET], %f6
ldd [%l0 + F8_F9_OFFSET], %f8
ldd [%l0 + F1O_F11_OFFSET], %f10
ldd [%l0 + F12_F13_OFFSET], %f12
ldd [%l0 + F14_F15_OFFSET], %f14
ldd [%l0 + F16_F17_OFFSET], %f16
ldd [%l0 + F18_F19_OFFSET], %f18
ldd [%l0 + F2O_F21_OFFSET], %f20
ldd [%l0 + F22_F23_OFFSET], %f22
ldd [%l0 + F24_F25_OFFSET], %f24
ldd [%l0 + F26_F27_OFFSET], %f26
ldd [%l0 + F28_F29_OFFSET], %f28
ldd [%l0 + F3O_F31_OFFSET], %f30
ld [%l0 + FSR_OFFSET], %fsr
ret
restore
/* _CPU_Context_switch
*
* This routine performs a normal non-FP context switch.
*
#endif /* SPARC_HAS_FPU */
/*
* void _CPU_Context_switch(
* Context_Control *run,
* Context_Control *heir
* )
* {
* }
*
* This routine performs a normal non-FP context switch.
*/
/* from gcc-2.7.0/config/sparc/sparc.h on register usage */
/* 1 for registers that have pervasive standard uses
and are not available for the register allocator.
g0 is used for the condition code and not to represent %g0, which is
hardwired to 0, so reg 0 is *not* fixed.
On non-v9 systems:
g1 is free to use as temporary.
g2-g4 are reserved for applications. Gcc normally uses them as
temporaries, but this can be disabled via the -mno-app-regs option.
g5 through g7 are reserved for the operating system.
On v9 systems:
g1 and g5 are free to use as temporaries.
g2-g4 are reserved for applications (the compiler will not normally use
them, but they can be used as temporaries with -mapp-regs).
g6-g7 are reserved for the operating system.
??? Register 1 is used as a temporary by the 64 bit sethi pattern, so must
currently be a fixed register until this pattern is rewritten.
Register 1 is also used when restoring call-preserved registers in large
stack frames. */
.align 4
PUBLIC(_CPU_Context_switch)
SYM(_CPU_Context_switch):
ta 0x03 /* flush registers */
! skip g0
st %g1, [%o0 + G1_OFFSET] ! save the global registers
std %g2, [%o0 + G2_OFFSET]
std %g4, [%o0 + G4_OFFSET]
std %g6, [%o0 + G6_OFFSET]
/* skip g0 */
st %g1,[%o0+G1_OFFSET] /* globals */
st %g2,[%o0+G2_OFFSET]
st %g3,[%o0+G3_OFFSET]
st %g4,[%o0+G4_OFFSET]
st %g5,[%o0+G5_OFFSET]
st %g6,[%o0+G6_OFFSET]
st %g7,[%o0+G7_OFFSET]
std %l0, [%o0 + L0_OFFSET] ! save the local registers
std %l2, [%o0 + L2_OFFSET]
std %l4, [%o0 + L4_OFFSET]
std %l6, [%o0 + L6_OFFSET]
st %l0,[%o0+L0_OFFSET]
st %l1,[%o0+L1_OFFSET]
st %l2,[%o0+L2_OFFSET]
st %l3,[%o0+L3_OFFSET]
st %l4,[%o0+L4_OFFSET]
st %l5,[%o0+L5_OFFSET]
st %l6,[%o0+L6_OFFSET]
st %l7,[%o0+L7_OFFSET]
std %i0, [%o0 + I0_OFFSET] ! save the input registers
std %i2, [%o0 + I2_OFFSET]
std %i4, [%o0 + I4_OFFSET]
std %i6, [%o0 + I6_FP_OFFSET]
st %i0,[%o0+I0_OFFSET]
st %i1,[%o0+I1_OFFSET]
st %i2,[%o0+I2_OFFSET]
st %i3,[%o0+I3_OFFSET]
st %i4,[%o0+I4_OFFSET]
st %i5,[%o0+I5_OFFSET]
st %i6,[%o0+I6_OFFSET]
st %i7,[%o0+I7_OFFSET]
std %o0, [%o0 + O0_OFFSET] ! save the output registers
std %o2, [%o0 + O2_OFFSET]
std %o4, [%o0 + O4_OFFSET]
std %o6, [%o0 + O6_SP_OFFSET]
st %o0,[%o0+O0_OFFSET]
st %o1,[%o0+O1_OFFSET]
st %o2,[%o0+O2_OFFSET]
st %o3,[%o0+O3_OFFSET]
st %o4,[%o0+O4_OFFSET]
st %o5,[%o0+O5_OFFSET]
st %o6,[%o0+O6_OFFSET]
st %o7,[%o0+O7_OFFSET]
rd %psr, %o2
st %o2, [%o0 + PSR_OFFSET] ! save status register
rd %psr,%o2
st %o2,[%o0+PSR_OFFSET] /* save status register */
/*
* This is entered from _CPU_Context_restore with:
* o1 = context to restore
* o2 = psr
*/
/* enter here with o1 = context to restore */
/* o2 = psr */
restore:
PUBLIC(_CPU_Context_restore_heir)
SYM(_CPU_Context_restore_heir):
/*
* Flush all windows with valid contents except the current one.
* In examining the set register windows, one may logically divide
* the windows into sets (some of which may be empty) based on their
* current status:
*
* + current (i.e. in use),
* + used (i.e. a restore would not trap)
* + invalid (i.e. 1 in corresponding bit in WIM)
* + unused
*
* Either the used or unused set of windows may be empty.
*
* NOTE: We assume only one bit is set in the WIM at a time.
*
* Given a CWP of 5 and a WIM of 0x1, the registers are divided
* into sets as follows:
*
* + 0 - invalid
* + 1-4 - unused
* + 5 - current
* + 6-7 - used
*
* In this case, we only would save the used windows -- 6 and 7.
*
* Traps are disabled for the same logical period as in a
* flush all windows trap handler.
*
* Register Usage while saving the windows:
* g1 = current PSR
* g2 = current wim
* g3 = CWP
* g4 = wim scratch
* g5 = scratch
*/
ld [%o1+PSR_OFFSET],%o0
and %o2,31,%o2 /* g1 = cwp */
and %o0,-32,%o0 /* o0 = psr w/o cwp */
or %o0,%o2,%o2 /* o2 = new psr */
wr %o2,0,%psr /* restore status register */
ld [%o1 + PSR_OFFSET], %g1 ! g1 = saved psr
/* skip g0 */
ld [%o1+G1_OFFSET],%g1
ld [%o1+G2_OFFSET],%g2
ld [%o1+G3_OFFSET],%g3
ld [%o1+G4_OFFSET],%g4
ld [%o1+G5_OFFSET],%g5
ld [%o1+G6_OFFSET],%g6
ld [%o1+G7_OFFSET],%g7
and %o2, SPARC_PSR_CWP_MASK, %g3 ! g3 = CWP
! g1 = psr w/o cwp
andn %g1, SPARC_PSR_ET_MASK | SPARC_PSR_CWP_MASK, %g1
or %g1, %g3, %g1 ! g1 = heirs psr
mov %g1, %psr ! restore status register and
! **** DISABLE TRAPS ****
mov %wim, %g2 ! g2 = wim
mov 1, %g4
sll %g4, %g3, %g4 ! g4 = WIM mask for CW invalid
ld [%o1+L0_OFFSET],%l0
ld [%o1+L1_OFFSET],%l1
ld [%o1+L2_OFFSET],%l2
ld [%o1+L3_OFFSET],%l3
ld [%o1+L4_OFFSET],%l4
ld [%o1+L5_OFFSET],%l5
ld [%o1+L6_OFFSET],%l6
ld [%o1+L7_OFFSET],%l7
save_frame_loop:
sll %g4, 1, %g5 ! rotate the "wim" left 1
srl %g4, SPARC_NUMBER_OF_REGISTER_WINDOWS - 1, %g4
or %g4, %g5, %g4 ! g4 = wim if we do one restore
ld [%o1+I0_OFFSET],%i0
ld [%o1+I1_OFFSET],%i1
ld [%o1+I2_OFFSET],%i2
ld [%o1+I3_OFFSET],%i3
ld [%o1+I4_OFFSET],%i4
ld [%o1+I5_OFFSET],%i5
ld [%o1+I6_OFFSET],%i6
ld [%o1+I7_OFFSET],%i7
/*
* If a restore would not underflow, then continue.
*/
ld [%o1+O0_OFFSET],%o0
/* do o1 last to avoid destroying heir context pointer */
ld [%o1+O2_OFFSET],%o2
ld [%o1+O3_OFFSET],%o3
ld [%o1+O4_OFFSET],%o4
ld [%o1+O5_OFFSET],%o5
ld [%o1+O6_OFFSET],%o6
ld [%o1+O7_OFFSET],%o7
andcc %g4, %g2, %g0 ! Any windows to flush?
bnz done_flushing ! No, then continue
nop
ld [%o1+O1_OFFSET],%o1 /* overwrite heir pointer */
restore ! back one window
jmp %o7 + 8 /* return */
nop /* delay slot */
/*
* Now save the window just as if we overflowed to it.
*/
std %l0, [%sp + CPU_STACK_FRAME_L0_OFFSET]
std %l2, [%sp + CPU_STACK_FRAME_L2_OFFSET]
std %l4, [%sp + CPU_STACK_FRAME_L4_OFFSET]
std %l6, [%sp + CPU_STACK_FRAME_L6_OFFSET]
std %i0, [%sp + CPU_STACK_FRAME_I0_OFFSET]
std %i2, [%sp + CPU_STACK_FRAME_I2_OFFSET]
std %i4, [%sp + CPU_STACK_FRAME_I4_OFFSET]
std %i6, [%sp + CPU_STACK_FRAME_I6_FP_OFFSET]
ba save_frame_loop
nop
done_flushing:
add %g3, 1, %g3 ! calculate desired WIM
and %g3, SPARC_NUMBER_OF_REGISTER_WINDOWS - 1, %g3
mov 1, %g4
sll %g4, %g3, %g4 ! g4 = new WIM
mov %g4, %wim
or %g1, SPARC_PSR_ET_MASK, %g1
mov %g1, %psr ! **** ENABLE TRAPS ****
! and restore CWP
nop
nop
nop
! skip g0
ld [%o1 + G1_OFFSET], %g1 ! restore the global registers
ldd [%o1 + G2_OFFSET], %g2
ldd [%o1 + G4_OFFSET], %g4
ldd [%o1 + G6_OFFSET], %g6
ldd [%o1 + L0_OFFSET], %l0 ! restore the local registers
ldd [%o1 + L2_OFFSET], %l2
ldd [%o1 + L4_OFFSET], %l4
ldd [%o1 + L6_OFFSET], %l6
ldd [%o1 + I0_OFFSET], %i0 ! restore the output registers
ldd [%o1 + I2_OFFSET], %i2
ldd [%o1 + I4_OFFSET], %i4
ldd [%o1 + I6_FP_OFFSET], %i6
ldd [%o1 + O2_OFFSET], %o2 ! restore the output registers
ldd [%o1 + O4_OFFSET], %o4
ldd [%o1 + O6_SP_OFFSET], %o6
! do o0/o1 last to avoid destroying heir context pointer
ldd [%o1 + O0_OFFSET], %o0 ! overwrite heir pointer
jmp %o7 + 8 ! return
nop ! delay slot
/*
* _CPU_Context_restore
*
* This routine is generallu used only to restart self in an
* efficient manner. It may simply be a label in _CPU_Context_switch.
*
* NOTE: May be unnecessary to reload some registers.
*
* void _CPU_Context_restore(
* Context_Control *new_context
* )
* {
* }
*
* This routine is generally used only to perform restart self.
*
* NOTE: It is unnecessary to reload some registers.
*/
.align 4
PUBLIC(_CPU_Context_restore)
SYM(_CPU_Context_restore):
save %sp, -104, %sp /* save a stack frame */
ta 0x03 /* flush registers */
rd %psr,%o2
ba restore
mov %i0,%o1 /* in the delay slot */
save %sp, -CPU_MINIMUM_STACK_FRAME_SIZE, %sp
rd %psr, %o2
ba SYM(_CPU_Context_restore_heir)
mov %i0, %o1 ! in the delay slot
/* void _ISR_Handler()
/*
* void _ISR_Handler()
*
* This routine provides the RTEMS interrupt management.
*
* void _ISR_Handler()
* {
* }
* We enter this handler from the 4 instructions in the trap table with
* the following registers assumed to be set as shown:
*
* l0 = PSR
* l1 = PC
* l2 = nPC
* l3 = trap type
*
* NOTE: By an executive defined convention, trap type is between 0 and 255 if
* it is an asynchonous trap and 256 and 511 if it is synchronous.
*/
.align 4
PUBLIC(_ISR_Handler)
SYM(_ISR_Handler):
ret
/*
* Fix the return address for synchronous traps.
*/
/*
* This discussion ignores a lot of the ugly details in a real
* implementation such as saving enough registers/state to be
* able to do something real. Keep in mind that the goal is
* to invoke a user's ISR handler which is written in C and
* uses a certain set of registers.
*
* Also note that the exact order is to a large extent flexible.
* Hardware will dictate a sequence for a certain subset of
* _ISR_Handler while requirements for setting
*/
andcc %l3, SPARC_SYNCHRONOUS_TRAP_BIT_MASK, %g0
! Is this a synchronous trap?
be,a win_ovflow ! No, then skip the adjustment
nop ! DELAY
mov %l2, %l1 ! do not return to the instruction
add %l2, 4, %l2 ! indicated
/*
* At entry to "common" _ISR_Handler, the vector number must be
* available. On some CPUs the hardware puts either the vector
* number or the offset into the vector table for this ISR in a
* known place. If the hardware does not give us this information,
* then the assembly portion of RTEMS for this port will contain
* a set of distinct interrupt entry points which somehow place
* the vector number in a known place (which is safe if another
* interrupt nests this one) and branches to _ISR_Handler.
*
* save some or all context on stack
* may need to save some special interrupt information for exit
*
* #if ( CPU_HAS_SOFTWARE_INTERRUPT_STACK == TRUE )
* if ( _ISR_Nest_level == 0 )
* switch to software interrupt stack
* #endif
*
* _ISR_Nest_level++;
*
* _Thread_Dispatch_disable_level++;
*
* (*_ISR_Vector_table[ vector ])( vector );
*
* --_ISR_Nest_level;
*
* if ( _ISR_Nest_level )
* goto the label "exit interrupt (simple case)"
*
* #if ( CPU_HAS_SOFTWARE_INTERRUPT_STACK == TRUE )
* restore stack
* #endif
*
* if ( !_Context_Switch_necessary )
* goto the label "exit interrupt (simple case)"
*
* if ( !_ISR_Signals_to_thread_executing )
* goto the label "exit interrupt (simple case)"
*
* call _Thread_Dispatch() or prepare to return to _ISR_Dispatch
*
* prepare to get out of interrupt
* return from interrupt (maybe to _ISR_Dispatch)
*
* LABEL "exit interrupt (simple case):
* prepare to get out of interrupt
* return from interrupt
*/
win_ovflow:
/*
* Save the globals this block uses.
*
* These registers are not restored from the locals. Their contents
* are saved directly from the locals into the ISF below.
*/
mov %g4, %l4 ! save the globals this block uses
mov %g5, %l5
/*
* When at a "window overflow" trap, (wim == (1 << cwp)).
* If we get here like that, then process a window overflow.
*/
rd %wim, %g4
srl %g4, %l0, %g5 ! g5 = win >> cwp ; shift count and CWP
! are LS 5 bits ; how convenient :)
cmp %g5, 1 ! Is this an invalid window?
bne dont_do_the_window ! No, then skip all this stuff
! we are using the delay slot
/*
* The following is same as a 1 position right rotate of WIM
*/
srl %g4, 1, %g5 ! g5 = WIM >> 1
sll %g4, SPARC_NUMBER_OF_REGISTER_WINDOWS-1 , %g4
! g4 = WIM << (Number Windows - 1)
or %g4, %g5, %g4 ! g4 = (WIM >> 1) |
! (WIM << (Number Windows - 1))
/*
* At this point:
*
* g4 = the new WIM
* g5 is free
*/
/*
* Since we are tinkering with the register windows, we need to
* make sure that all the required information is in global registers.
*/
save ! Save into the window
wr %g4, 0, %wim ! WIM = new WIM
nop ! delay slots
nop
nop
/*
* Now save the window just as if we overflowed to it.
*/
std %l0, [%sp + CPU_STACK_FRAME_L0_OFFSET]
std %l2, [%sp + CPU_STACK_FRAME_L2_OFFSET]
std %l4, [%sp + CPU_STACK_FRAME_L4_OFFSET]
std %l6, [%sp + CPU_STACK_FRAME_L6_OFFSET]
std %i0, [%sp + CPU_STACK_FRAME_I0_OFFSET]
std %i2, [%sp + CPU_STACK_FRAME_I2_OFFSET]
std %i4, [%sp + CPU_STACK_FRAME_I4_OFFSET]
std %i6, [%sp + CPU_STACK_FRAME_I6_FP_OFFSET]
restore
nop
dont_do_the_window:
/*
* Global registers %g4 and %g5 are saved directly from %l4 and
* %l5 directly into the ISF below.
*/
save_isf:
/*
* Save the state of the interrupted task -- especially the global
* registers -- in the Interrupt Stack Frame. Note that the ISF
* includes a regular minimum stack frame which will be used if
* needed by register window overflow and underflow handlers.
*
* REGISTERS SAME AS AT _ISR_Handler
*/
sub %fp, CONTEXT_CONTROL_INTERRUPT_FRAME_SIZE, %sp
! make space for ISF
std %l0, [%sp + ISF_PSR_OFFSET] ! save psr, PC
st %l2, [%sp + ISF_NPC_OFFSET] ! save nPC
st %g1, [%sp + ISF_G1_OFFSET] ! save g1
std %g2, [%sp + ISF_G2_OFFSET] ! save g2, g3
std %l4, [%sp + ISF_G4_OFFSET] ! save g4, g5 -- see above
std %g6, [%sp + ISF_G6_OFFSET] ! save g6, g7
std %i0, [%sp + ISF_I0_OFFSET] ! save i0, i1
std %i2, [%sp + ISF_I2_OFFSET] ! save i2, i3
std %i4, [%sp + ISF_I4_OFFSET] ! save i4, i5
std %i6, [%sp + ISF_I6_FP_OFFSET] ! save i6/fp, i7
rd %y, %g1
st %g1, [%sp + ISF_Y_OFFSET] ! save y
mov %sp, %o1 ! 2nd arg to ISR Handler
/*
* Increment ISR nest level and Thread dispatch disable level.
*
* Register usage for this section:
*
* l4 = _Thread_Dispatch_disable_level pointer
* l5 = _ISR_Nest_level pointer
* l6 = _Thread_Dispatch_disable_level value
* l7 = _ISR_Nest_level value
*
* NOTE: It is assumed that l4 - l7 will be preserved until the ISR
* nest and thread dispatch disable levels are unnested.
*/
sethi %hi(SYM(_Thread_Dispatch_disable_level)), %l4
ld [%l4 + %lo(SYM(_Thread_Dispatch_disable_level))], %l6
sethi %hi(SYM(_ISR_Nest_level)), %l5
ld [%l5 + %lo(SYM(_ISR_Nest_level))], %l7
add %l6, 1, %l6
st %l6, [%l4 + %lo(SYM(_Thread_Dispatch_disable_level))]
add %l7, 1, %l7
st %l7, [%l5 + %lo(SYM(_ISR_Nest_level))]
/*
* If ISR nest level was zero (now 1), then switch stack.
*/
mov %sp, %fp
subcc %l7, 1, %l7 ! outermost interrupt handler?
bnz dont_switch_stacks ! No, then do not switch stacks
sethi %hi(SYM(_CPU_Interrupt_stack_high)), %g4
ld [%g4 + %lo(SYM(_CPU_Interrupt_stack_high))], %sp
dont_switch_stacks:
/*
* Make sure we have a place on the stack for the window overflow
* trap handler to write into. At this point it is safe to
* enable traps again.
*/
sub %sp, CPU_MINIMUM_STACK_FRAME_SIZE, %sp
wr %l0, SPARC_PSR_ET_MASK, %psr ! **** ENABLE TRAPS ****
/*
* Vector to user's handler.
*
* NOTE: TBR may no longer have vector number in it since
* we just enabled traps. It is definitely in l3.
*/
sethi %hi(SYM(_ISR_Vector_table)), %g4
or %g4, %lo(SYM(_ISR_Vector_table)), %g4
and %l3, 0xFF, %g5 ! remove synchronous trap indicator
sll %g5, 2, %g5 ! g5 = offset into table
ld [%g4 + %g5], %g4 ! g4 = _ISR_Vector_table[ vector ]
! o1 = 2nd arg = address of the ISF
! WAS LOADED WHEN ISF WAS SAVED!!!
mov %l3, %o0 ! o0 = 1st arg = vector number
call %g4, 0
nop ! delay slot
/*
* Redisable traps so we can finish up the interrupt processing.
* This is a VERY conservative place to do this.
*
* NOTE: %l0 has the PSR which was in place when we took the trap.
*/
mov %l0, %psr ! **** DISABLE TRAPS ****
/*
* Decrement ISR nest level and Thread dispatch disable level.
*
* Register usage for this section:
*
* l4 = _Thread_Dispatch_disable_level pointer
* l5 = _ISR_Nest_level pointer
* l6 = _Thread_Dispatch_disable_level value
* l7 = _ISR_Nest_level value
*/
sub %l6, 1, %l6
st %l6, [%l4 + %lo(SYM(_Thread_Dispatch_disable_level))]
st %l7, [%l5 + %lo(SYM(_ISR_Nest_level))]
/*
* If dispatching is disabled (includes nested interrupt case),
* then do a "simple" exit.
*/
orcc %l6, %g0, %g0 ! Is dispatching disabled?
bnz simple_return ! Yes, then do a "simple" exit
nop ! delay slot
/*
* If a context switch is necessary, then do fudge stack to
* return to the interrupt dispatcher.
*/
sethi %hi(SYM(_Context_Switch_necessary)), %l4
ld [%l4 + %lo(SYM(_Context_Switch_necessary))], %l5
orcc %l5, %g0, %g0 ! Is thread switch necessary?
bnz SYM(_ISR_Dispatch) ! yes, then invoke the dispatcher
nop ! delay slot
/*
* Finally, check to see if signals were sent to the currently
* executing task. If so, we need to invoke the interrupt dispatcher.
*/
sethi %hi(SYM(_ISR_Signals_to_thread_executing)), %l6
ld [%l6 + %lo(SYM(_ISR_Signals_to_thread_executing))], %l7
orcc %l7, %g0, %g0 ! Were signals sent to the currently
! executing thread?
bz simple_return ! yes, then invoke the dispatcher
nop ! delay slot
/*
* Invoke interrupt dispatcher.
*/
PUBLIC(_ISR_Dispatch)
SYM(_ISR_Dispatch):
/*
* The following subtract should get us back on the interrupted
* tasks stack and add enough room to invoke the dispatcher.
* When we enable traps, we are mostly back in the context
* of the task and subsequent interrupts can operate normally.
*/
sub %fp, CPU_MINIMUM_STACK_FRAME_SIZE, %sp
or %l0, SPARC_PSR_ET_MASK, %l7 ! l7 = PSR with ET=1
mov %l7, %psr ! **** ENABLE TRAPS ****
nop
nop
nop
call SYM(_Thread_Dispatch), 0
nop
/*
* The CWP in place at this point may be different from
* that which was in effect at the beginning of the ISR if we
* have been context switched between the beginning of this invocation
* of _ISR_Handler and this point. Thus the CWP and WIM should
* not be changed back to their values at ISR entry time. Any
* changes to the PSR must preserve the CWP.
*/
simple_return:
ld [%fp + ISF_Y_OFFSET], %l5 ! restore y
wr %l5, 0, %y
ldd [%fp + ISF_PSR_OFFSET], %l0 ! restore psr, PC
ld [%fp + ISF_NPC_OFFSET], %l2 ! restore nPC
rd %psr, %l3
and %l3, SPARC_PSR_CWP_MASK, %l3 ! want "current" CWP
andn %l0, SPARC_PSR_CWP_MASK, %l0 ! want rest from task
or %l3, %l0, %l0 ! install it later...
andn %l0, SPARC_PSR_ET_MASK, %l0
/*
* Restore tasks global and out registers
*/
mov %fp, %g1
! g1 is restored later
ldd [%fp + ISF_G2_OFFSET], %g2 ! restore g2, g3
ldd [%fp + ISF_G4_OFFSET], %g4 ! restore g4, g5
ldd [%fp + ISF_G6_OFFSET], %g6 ! restore g6, g7
ldd [%fp + ISF_I0_OFFSET], %i0 ! restore i0, i1
ldd [%fp + ISF_I2_OFFSET], %i2 ! restore i2, i3
ldd [%fp + ISF_I4_OFFSET], %i4 ! restore i4, i5
ldd [%fp + ISF_I6_FP_OFFSET], %i6 ! restore i6/fp, i7
/*
* Registers:
*
* ALL global registers EXCEPT G1 and the input registers have
* already been restored and thuse off limits.
*
* The following is the contents of the local registers:
*
* l0 = original psr
* l1 = return address (i.e. PC)
* l2 = nPC
* l3 = CWP
*/
/*
* if (CWP + 1) is an invalid window then we need to reload it.
*
* WARNING: Traps should now be disabled
*/
mov %l0, %psr ! **** DISABLE TRAPS ****
nop
nop
nop
rd %wim, %l4
add %l0, 1, %l6 ! l6 = cwp + 1
and %l6, SPARC_PSR_CWP_MASK, %l6 ! do the modulo on it
srl %l4, %l6, %l5 ! l5 = win >> cwp + 1 ; shift count
! and CWP are conveniently LS 5 bits
cmp %l5, 1 ! Is tasks window invalid?
bne good_task_window
/*
* The following code is the same as a 1 position left rotate of WIM.
*/
sll %l4, 1, %l5 ! l5 = WIM << 1
srl %l4, SPARC_NUMBER_OF_REGISTER_WINDOWS-1 , %l4
! l4 = WIM >> (Number Windows - 1)
or %l4, %l5, %l4 ! l4 = (WIM << 1) |
! (WIM >> (Number Windows - 1))
/*
* Now restore the window just as if we underflowed to it.
*/
wr %l4, 0, %wim ! WIM = new WIM
restore ! now into the tasks window
ldd [%g1 + CPU_STACK_FRAME_L0_OFFSET], %l0
ldd [%g1 + CPU_STACK_FRAME_L2_OFFSET], %l2
ldd [%g1 + CPU_STACK_FRAME_L4_OFFSET], %l4
ldd [%g1 + CPU_STACK_FRAME_L6_OFFSET], %l6
ldd [%g1 + CPU_STACK_FRAME_I0_OFFSET], %i0
ldd [%g1 + CPU_STACK_FRAME_I2_OFFSET], %i2
ldd [%g1 + CPU_STACK_FRAME_I4_OFFSET], %i4
ldd [%g1 + CPU_STACK_FRAME_I6_FP_OFFSET], %i6
! reload of sp clobbers ISF
save ! Back to ISR dispatch window
good_task_window:
mov %l0, %psr ! **** DISABLE TRAPS ****
! and restore condition codes.
ld [%g1 + ISF_G1_OFFSET], %g1 ! restore g1
jmp %l1 ! transfer control and
rett %l2 ! go back to tasks window
/* end of file */

View File

@@ -0,0 +1,503 @@
/* erc32.h
*
* This include file contains information pertaining to the ERC32.
* The ERC32 is a custom SPARC V7 implementation based on the Cypress
* 601/602 chipset. This CPU has a number of on-board peripherals and
* was developed by the European Space Agency to target space applications.
*
* NOTE: Other than where absolutely required, this version currently
* supports only the peripherals and bits used by the basic board
* support package. This includes at least significant pieces of
* the following items:
*
* + UART Channels A and B
* + General Purpose Timer
* + Real Time Clock
* + Watchdog Timer (so it can be disabled)
* + Control Register (so powerdown mode can be enabled)
* + Memory Control Register
* + Interrupt Control
*
* $Id$
*/
#ifndef _INCLUDE_ERC32_h
#define _INCLUDE_ERC32_h
#include <rtems/score/sparc.h>
#ifdef __cplusplus
extern "C" {
#endif
/*
* Interrupt Sources
*
* The interrupt source numbers directly map to the trap type and to
* the bits used in the Interrupt Clear, Interrupt Force, Interrupt Mask,
* and the Interrupt Pending Registers.
*/
#define ERC32_INTERRUPT_MASKED_ERRORS 1
#define ERC32_INTERRUPT_EXTERNAL_1 2
#define ERC32_INTERRUPT_EXTERNAL_2 3
#define ERC32_INTERRUPT_UART_A_RX_TX 4
#define ERC32_INTERRUPT_UART_B_RX_TX 5
#define ERC32_INTERRUPT_CORRECTABLE_MEMORY_ERROR 6
#define ERC32_INTERRUPT_UART_ERROR 7
#define ERC32_INTERRUPT_DMA_ACCESS_ERROR 8
#define ERC32_INTERRUPT_DMA_TIMEOUT 9
#define ERC32_INTERRUPT_EXTERNAL_3 10
#define ERC32_INTERRUPT_EXTERNAL_4 11
#define ERC32_INTERRUPT_GENERAL_PURPOSE_TIMER 12
#define ERC32_INTERRUPT_REAL_TIME_CLOCK 13
#define ERC32_INTERRUPT_EXTERNAL_5 14
#define ERC32_INTERRUPT_WATCHDOG_TIMEOUT 15
#ifndef ASM
/*
* Trap Types for on-chip peripherals
*
* Source: Table 8 - Interrupt Trap Type and Default Priority Assignments
*
* NOTE: The priority level for each source corresponds to the least
* significant nibble of the trap type.
*/
#define ERC32_TRAP_TYPE( _source ) SPARC_ASYNCHRONOUS_TRAP((_source) + 0x10)
#define ERC32_TRAP_SOURCE( _trap ) ((_trap) - 0x10)
#define ERC32_Is_MEC_Trap( _trap ) \
( (_trap) >= ERC32_TRAP_TYPE( ERC32_INTERRUPT_MASKED_ERRORS ) && \
(_trap) <= ERC32_TRAP_TYPE( ERC32_INTERRUPT_WATCHDOG_TIMEOUT ) )
/*
* Structure for ERC32 memory mapped registers.
*
* Source: Section 3.25.2 - Register Address Map
*
* NOTE: There is only one of these structures per CPU, its base address
* is 0x01f80000, and the variable MEC is placed there by the
* linkcmds file.
*/
typedef struct {
volatile unsigned32 Control; /* offset 0x00 */
volatile unsigned32 Software_Reset; /* offset 0x04 */
volatile unsigned32 Power_Down; /* offset 0x08 */
volatile unsigned32 Unimplemented_0; /* offset 0x0c */
volatile unsigned32 Memory_Configuration; /* offset 0x10 */
volatile unsigned32 IO_Configuration; /* offset 0x14 */
volatile unsigned32 Wait_State_Configuration; /* offset 0x18 */
volatile unsigned32 Unimplemented_1; /* offset 0x1c */
volatile unsigned32 Memory_Access_0; /* offset 0x20 */
volatile unsigned32 Memory_Access_1; /* offset 0x24 */
volatile unsigned32 Unimplemented_2[ 7 ]; /* offset 0x28 */
volatile unsigned32 Interrupt_Shape; /* offset 0x44 */
volatile unsigned32 Interrupt_Pending; /* offset 0x48 */
volatile unsigned32 Interrupt_Mask; /* offset 0x4c */
volatile unsigned32 Interrupt_Clear; /* offset 0x50 */
volatile unsigned32 Interrupt_Force; /* offset 0x54 */
volatile unsigned32 Unimplemented_3[ 2 ]; /* offset 0x58 */
/* offset 0x60 */
volatile unsigned32 Watchdog_Program_and_Timeout_Acknowledge;
volatile unsigned32 Watchdog_Trap_Door_Set; /* offset 0x64 */
volatile unsigned32 Unimplemented_4[ 6 ]; /* offset 0x68 */
volatile unsigned32 Real_Time_Clock_Counter; /* offset 0x80 */
volatile unsigned32 Real_Time_Clock_Scalar; /* offset 0x84 */
volatile unsigned32 General_Purpose_Timer_Counter; /* offset 0x88 */
volatile unsigned32 General_Purpose_Timer_Scalar; /* offset 0x8c */
volatile unsigned32 Unimplemented_5[ 2 ]; /* offset 0x90 */
volatile unsigned32 Timer_Control; /* offset 0x98 */
volatile unsigned32 Unimplemented_6; /* offset 0x9c */
volatile unsigned32 System_Fault_Status; /* offset 0xa0 */
volatile unsigned32 First_Failing_Address; /* offset 0xa4 */
volatile unsigned32 First_Failing_Data; /* offset 0xa8 */
volatile unsigned32 First_Failing_Syndrome_and_Check_Bits;/* offset 0xac */
volatile unsigned32 Error_and_Reset_Status; /* offset 0xb0 */
volatile unsigned32 Error_Mask; /* offset 0xb4 */
volatile unsigned32 Unimplemented_7[ 2 ]; /* offset 0xb8 */
volatile unsigned32 Debug_Control; /* offset 0xc0 */
volatile unsigned32 Breakpoint; /* offset 0xc4 */
volatile unsigned32 Watchpoint; /* offset 0xc8 */
volatile unsigned32 Unimplemented_8; /* offset 0xcc */
volatile unsigned32 Test_Control; /* offset 0xd0 */
volatile unsigned32 Test_Data; /* offset 0xd4 */
volatile unsigned32 Unimplemented_9[ 2 ]; /* offset 0xd8 */
volatile unsigned32 UART_Channel_A; /* offset 0xe0 */
volatile unsigned32 UART_Channel_B; /* offset 0xe4 */
volatile unsigned32 UART_Status; /* offset 0xe8 */
} ERC32_Register_Map;
#endif
/*
* The following constants are intended to be used ONLY in assembly
* language files.
*
* NOTE: The intended style of usage is to load the address of MEC
* into a register and then use these as displacements from
* that register.
*/
#ifdef ASM
#define ERC32_MEC_CONTROL_OFFSET 0x00
#define ERC32_MEC_SOFTWARE_RESET_OFFSET 0x04
#define ERC32_MEC_POWER_DOWN_OFFSET 0x08
#define ERC32_MEC_UNIMPLEMENTED_0_OFFSET 0x0C
#define ERC32_MEC_MEMORY_CONFIGURATION_OFFSET 0x10
#define ERC32_MEC_IO_CONFIGURATION_OFFSET 0x14
#define ERC32_MEC_WAIT_STATE_CONFIGURATION_OFFSET 0x18
#define ERC32_MEC_UNIMPLEMENTED_1_OFFSET 0x1C
#define ERC32_MEC_MEMORY_ACCESS_0_OFFSET 0x20
#define ERC32_MEC_MEMORY_ACCESS_1_OFFSET 0x24
#define ERC32_MEC_UNIMPLEMENTED_2_OFFSET 0x28
#define ERC32_MEC_INTERRUPT_SHAPE_OFFSET 0x44
#define ERC32_MEC_INTERRUPT_PENDING_OFFSET 0x48
#define ERC32_MEC_INTERRUPT_MASK_OFFSET 0x4C
#define ERC32_MEC_INTERRUPT_CLEAR_OFFSET 0x50
#define ERC32_MEC_INTERRUPT_FORCE_OFFSET 0x54
#define ERC32_MEC_UNIMPLEMENTED_3_OFFSET 0x58
#define ERC32_MEC_WATCHDOG_PROGRAM_AND_TIMEOUT_ACKNOWLEDGE_OFFSET 0x60
#define ERC32_MEC_WATCHDOG_TRAP_DOOR_SET_OFFSET 0x64
#define ERC32_MEC_UNIMPLEMENTED_4_OFFSET 0x6C
#define ERC32_MEC_REAL_TIME_CLOCK_COUNTER_OFFSET 0x80
#define ERC32_MEC_REAL_TIME_CLOCK_SCALAR_OFFSET 0x84
#define ERC32_MEC_GENERAL_PURPOSE_TIMER_COUNTER_OFFSET 0x88
#define ERC32_MEC_GENERAL_PURPOSE_TIMER_SCALAR_OFFSET 0x8C
#define ERC32_MEC_UNIMPLEMENTED_5_OFFSET 0x90
#define ERC32_MEC_TIMER_CONTROL_OFFSET 0x98
#define ERC32_MEC_UNIMPLEMENTED_6_OFFSET 0x9C
#define ERC32_MEC_SYSTEM_FAULT_STATUS_OFFSET 0xA0
#define ERC32_MEC_FIRST_FAILING_ADDRESS_OFFSET 0xA4
#define ERC32_MEC_FIRST_FAILING_DATA_OFFSET 0xA8
#define ERC32_MEC_FIRST_FAILING_SYNDROME_AND_CHECK_BITS_OFFSET 0xAC
#define ERC32_MEC_ERROR_AND_RESET_STATUS_OFFSET 0xB0
#define ERC32_MEC_ERROR_MASK_OFFSET 0xB4
#define ERC32_MEC_UNIMPLEMENTED_7_OFFSET 0xB8
#define ERC32_MEC_DEBUG_CONTROL_OFFSET 0xC0
#define ERC32_MEC_BREAKPOINT_OFFSET 0xC4
#define ERC32_MEC_WATCHPOINT_OFFSET 0xC8
#define ERC32_MEC_UNIMPLEMENTED_8_OFFSET 0xCC
#define ERC32_MEC_TEST_CONTROL_OFFSET 0xD0
#define ERC32_MEC_TEST_DATA_OFFSET 0xD4
#define ERC32_MEC_UNIMPLEMENTED_9_OFFSET 0xD8
#define ERC32_MEC_UART_CHANNEL_A_OFFSET 0xE0
#define ERC32_MEC_UART_CHANNEL_B_OFFSET 0xE4
#define ERC32_MEC_UART_STATUS_OFFSET 0xE8
#endif
/*
* The following defines the bits in the Configuration Register.
*/
#define ERC32_CONFIGURATION_POWER_DOWN_MASK 0x00000001
#define ERC32_CONFIGURATION_POWER_DOWN_ALLOWED 0x00000001
#define ERC32_CONFIGURATION_POWER_DOWN_DISABLED 0x00000000
#define ERC32_CONFIGURATION_SOFTWARE_RESET_MASK 0x00000002
#define ERC32_CONFIGURATION_SOFTWARE_RESET_ALLOWED 0x00000002
#define ERC32_CONFIGURATION_SOFTWARE_RESET_DISABLED 0x00000000
#define ERC32_CONFIGURATION_BUS_TIMEOUT_MASK 0x00000004
#define ERC32_CONFIGURATION_BUS_TIMEOUT_ENABLED 0x00000004
#define ERC32_CONFIGURATION_BUS_TIMEOUT_DISABLED 0x00000000
#define ERC32_CONFIGURATION_ACCESS_PROTECTION_MASK 0x00000008
#define ERC32_CONFIGURATION_ACCESS_PROTECTION_ENABLED 0x00000008
#define ERC32_CONFIGURATION_ACCESS_PROTECTION_DISABLED 0x00000000
/*
* The following defines the bits in the Memory Configuration Register.
*/
#define ERC32_MEMORY_CONFIGURATION_RAM_SIZE_MASK 0x00001C00
#define ERC32_MEMORY_CONFIGURATION_RAM_SIZE_256K ( 0 << 10 )
#define ERC32_MEMORY_CONFIGURATION_RAM_SIZE_512K ( 1 << 10 )
#define ERC32_MEMORY_CONFIGURATION_RAM_SIZE_1MB ( 2 << 10 )
#define ERC32_MEMORY_CONFIGURATION_RAM_SIZE_2MB ( 3 << 10 )
#define ERC32_MEMORY_CONFIGURATION_RAM_SIZE_4MB ( 4 << 10 )
#define ERC32_MEMORY_CONFIGURATION_RAM_SIZE_8MB ( 5 << 10 )
#define ERC32_MEMORY_CONFIGURATION_RAM_SIZE_16MB ( 6 << 10 )
#define ERC32_MEMORY_CONFIGURATION_RAM_SIZE_32MB ( 7 << 10 )
#define ERC32_MEMORY_CONFIGURATION_PROM_SIZE_MASK 0x001C0000
#define ERC32_MEMORY_CONFIGURATION_PROM_SIZE_4K ( 0 << 18 )
#define ERC32_MEMORY_CONFIGURATION_PROM_SIZE_8K ( 1 << 18 )
#define ERC32_MEMORY_CONFIGURATION_PROM_SIZE_16K ( 2 << 18 )
#define ERC32_MEMORY_CONFIGURATION_PROM_SIZE_32K ( 3 << 18 )
#define ERC32_MEMORY_CONFIGURATION_PROM_SIZE_64K ( 4 << 18 )
#define ERC32_MEMORY_CONFIGURATION_PROM_SIZE_128K ( 5 << 18 )
#define ERC32_MEMORY_CONFIGURATION_PROM_SIZE_256K ( 6 << 18 )
#define ERC32_MEMORY_CONFIGURATION_PROM_SIZE_512K ( 7 << 18 )
/*
* The following defines the bits in the Timer Control Register.
*/
#define ERC32_MEC_TIMER_CONTROL_GCR 0x00000001 /* 1 = reload at 0 */
/* 0 = stop at 0 */
#define ERC32_MEC_TIMER_CONTROL_GCL 0x00000002 /* 1 = load and start */
/* 0 = no function */
#define ERC32_MEC_TIMER_CONTROL_GSE 0x00000004 /* 1 = enable counting */
/* 0 = hold scalar and counter */
#define ERC32_MEC_TIMER_CONTROL_GSL 0x00000008 /* 1 = load scalar and start */
/* 0 = no function */
#define ERC32_MEC_TIMER_CONTROL_RTCCR 0x00000100 /* 1 = reload at 0 */
/* 0 = stop at 0 */
#define ERC32_MEC_TIMER_CONTROL_RTCCL 0x00000200 /* 1 = load and start */
/* 0 = no function */
#define ERC32_MEC_TIMER_CONTROL_RTCSE 0x00000400 /* 1 = enable counting */
/* 0 = hold scalar and counter */
#define ERC32_MEC_TIMER_CONTROL_RTCSL 0x00000800 /* 1 = load scalar and start */
/* 0 = no function */
/*
* The following defines the bits in the UART Control Registers.
*
* NOTE: Same bits in UART channels A and B.
*/
#define ERC32_MEC_UART_CONTROL_RTD 0x000000FF /* RX/TX data */
#define ERC32_MEC_UART_CONTROL_DR 0x00000100 /* RX Data Ready */
#define ERC32_MEC_UART_CONTROL_TSE 0x00000200 /* TX Send Empty */
/* (i.e. no data to send) */
#define ERC32_MEC_UART_CONTROL_THE 0x00000400 /* TX Hold Empty */
/* (i.e. ready to load) */
/*
* The following defines the bits in the MEC UART Control Registers.
*/
#define ERC32_MEC_UART_STATUS_DR 0x00000001 /* Data Ready */
#define ERC32_MEC_UART_STATUS_TSE 0x00000002 /* TX Send Register Empty */
#define ERC32_MEC_UART_STATUS_THE 0x00000004 /* TX Hold Register Empty */
#define ERC32_MEC_UART_STATUS_FE 0x00000010 /* RX Framing Error */
#define ERC32_MEC_UART_STATUS_PE 0x00000020 /* RX Parity Error */
#define ERC32_MEC_UART_STATUS_OE 0x00000040 /* RX Overrun Error */
#define ERC32_MEC_UART_STATUS_CU 0x00000080 /* Clear Errors */
#define ERC32_MEC_UART_STATUS_TXE 0x00000006 /* TX Empty */
#define ERC32_MEC_UART_STATUS_DRA (ERC32_MEC_UART_STATUS_DR << 0)
#define ERC32_MEC_UART_STATUS_TSEA (ERC32_MEC_UART_STATUS_TSE << 0)
#define ERC32_MEC_UART_STATUS_THEA (ERC32_MEC_UART_STATUS_THE << 0)
#define ERC32_MEC_UART_STATUS_FEA (ERC32_MEC_UART_STATUS_FE << 0)
#define ERC32_MEC_UART_STATUS_PEA (ERC32_MEC_UART_STATUS_PE << 0)
#define ERC32_MEC_UART_STATUS_OEA (ERC32_MEC_UART_STATUS_OE << 0)
#define ERC32_MEC_UART_STATUS_CUA (ERC32_MEC_UART_STATUS_CU << 0)
#define ERC32_MEC_UART_STATUS_TXEA (ERC32_MEC_UART_STATUS_TXE << 0)
#define ERC32_MEC_UART_STATUS_DRB (ERC32_MEC_UART_STATUS_DR << 16)
#define ERC32_MEC_UART_STATUS_TSEB (ERC32_MEC_UART_STATUS_TSE << 16)
#define ERC32_MEC_UART_STATUS_THEB (ERC32_MEC_UART_STATUS_THE << 16)
#define ERC32_MEC_UART_STATUS_FEB (ERC32_MEC_UART_STATUS_FE << 16)
#define ERC32_MEC_UART_STATUS_PEB (ERC32_MEC_UART_STATUS_PE << 16)
#define ERC32_MEC_UART_STATUS_OEB (ERC32_MEC_UART_STATUS_OE << 16)
#define ERC32_MEC_UART_STATUS_CUB (ERC32_MEC_UART_STATUS_CU << 16)
#define ERC32_MEC_UART_STATUS_TXEB (ERC32_MEC_UART_STATUS_TXE << 16)
#ifndef ASM
/*
* This is used to manipulate the on-chip registers.
*
* The following symbol must be defined in the linkcmds file and point
* to the correct location.
*/
extern ERC32_Register_Map ERC32_MEC;
/*
* Macros to manipulate the Interrupt Clear, Interrupt Force, Interrupt Mask,
* and the Interrupt Pending Registers.
*
* NOTE: For operations which are not atomic, this code disables interrupts
* to guarantee there are no intervening accesses to the same register.
* The operations which read the register, modify the value and then
* store the result back are vulnerable.
*/
#define ERC32_Clear_interrupt( _source ) \
do { \
ERC32_MEC.Interrupt_Clear = (1 << (_source)); \
} while (0)
#define ERC32_Force_interrupt( _source ) \
do { \
ERC32_MEC.Interrupt_Force = (1 << (_source)); \
} while (0)
#define ERC32_Is_interrupt_pending( _source ) \
(ERC32_MEC.Interrupt_Pending & (1 << (_source)))
#define ERC32_Is_interrupt_masked( _source ) \
(ERC32_MEC.Interrupt_Masked & (1 << (_source)))
#define ERC32_Mask_interrupt( _source ) \
do { \
unsigned32 _level; \
\
sparc_disable_interrupts( _level ); \
ERC32_MEC.Interrupt_Mask |= (1 << (_source)); \
sparc_enable_interrupts( _level ); \
} while (0)
#define ERC32_Unmask_interrupt( _source ) \
do { \
unsigned32 _level; \
\
sparc_disable_interrupts( _level ); \
ERC32_MEC.Interrupt_Mask &= ~(1 << (_source)); \
sparc_enable_interrupts( _level ); \
} while (0)
#define ERC32_Disable_interrupt( _source, _previous ) \
do { \
unsigned32 _level; \
unsigned32 _mask = 1 << (_source); \
\
sparc_disable_interrupts( _level ); \
(_previous) = ERC32_MEC.Interrupt_Mask; \
ERC32_MEC.Interrupt_Mask = _previous | _mask; \
sparc_enable_interrupts( _level ); \
(_previous) &= ~_mask; \
} while (0)
#define ERC32_Restore_interrupt( _source, _previous ) \
do { \
unsigned32 _level; \
unsigned32 _mask = 1 << (_source); \
\
sparc_disable_interrupts( _level ); \
ERC32_MEC.Interrupt_Mask = \
(ERC32_MEC.Interrupt_Mask & ~_mask) | (_previous); \
sparc_enable_interrupts( _level ); \
} while (0)
/*
* The following macros attempt to hide the fact that the General Purpose
* Timer and Real Time Clock Timer share the Timer Control Register. Because
* the Timer Control Register is write only, we must mirror it in software
* and insure that writes to one timer do not alter the current settings
* and status of the other timer.
*
* This code promotes the view that the two timers are completely independent.
* By exclusively using the routines below to access the Timer Control
* Register, the application can view the system as having a General Purpose
* Timer Control Register and a Real Time Clock Timer Control Register
* rather than the single shared value.
*
* Each logical timer control register is organized as follows:
*
* D0 - Counter Reload
* 1 = reload counter at zero and restart
* 0 = stop counter at zero
*
* D1 - Counter Load
* 1 = load counter with preset value and restart
* 0 = no function
*
* D2 - Enable
* 1 = enable counting
* 0 = hold scaler and counter
*
* D2 - Scaler Load
* 1 = load scalar with preset value and restart
* 0 = no function
*
* To insure the management of the mirror is atomic, we disable interrupts
* around updates.
*/
#define ERC32_MEC_TIMER_COUNTER_RELOAD_AT_ZERO 0x00000001
#define ERC32_MEC_TIMER_COUNTER_STOP_AT_ZERO 0x00000000
#define ERC32_MEC_TIMER_COUNTER_LOAD_COUNTER 0x00000002
#define ERC32_MEC_TIMER_COUNTER_ENABLE_COUNTING 0x00000004
#define ERC32_MEC_TIMER_COUNTER_DISABLE_COUNTING 0x00000000
#define ERC32_MEC_TIMER_COUNTER_LOAD_SCALER 0x00000008
#define ERC32_MEC_TIMER_COUNTER_RELOAD_MASK 0x00000001
#define ERC32_MEC_TIMER_COUNTER_ENABLE_MASK 0x00000004
#define ERC32_MEC_TIMER_COUNTER_DEFINED_MASK 0x0000000F
#define ERC32_MEC_TIMER_COUNTER_CURRENT_MODE_MASK 0x00000005
extern unsigned32 _ERC32_MEC_Timer_Control_Mirror;
/*
* This macros manipulate the General Purpose Timer portion of the
* Timer Control register and promote the view that there are actually
* two independent Timer Control Registers.
*/
#define ERC32_MEC_Set_General_Purpose_Timer_Control( _value ) \
do { \
unsigned32 _level; \
unsigned32 _control; \
unsigned32 __value; \
\
__value = ((_value) & 0x0f); \
sparc_disable_interrupts( _level ); \
_control = _ERC32_MEC_Timer_Control_Mirror; \
_control &= ERC32_MEC_TIMER_COUNTER_DEFINED_MASK << 8; \
_ERC32_MEC_Timer_Control_Mirror = _control | _value; \
_control &= (ERC32_MEC_TIMER_COUNTER_CURRENT_MODE_MASK << 8); \
_control |= __value; \
/* printf( "GPT 0x%x 0x%x 0x%x\n", _value, __value, _control ); */ \
ERC32_MEC.Timer_Control = _control; \
sparc_enable_interrupts( _level ); \
} while ( 0 )
#define ERC32_MEC_Get_General_Purpose_Timer_Control( _value ) \
do { \
(_value) = _ERC32_MEC_Timer_Control_Mirror & 0xf; \
} while ( 0 )
/*
* This macros manipulate the Real Timer Clock Timer portion of the
* Timer Control register and promote the view that there are actually
* two independent Timer Control Registers.
*/
#define ERC32_MEC_Set_Real_Time_Clock_Timer_Control( _value ) \
do { \
unsigned32 _level; \
unsigned32 _control; \
unsigned32 __value; \
\
__value = ((_value) & 0x0f) << 8; \
sparc_disable_interrupts( _level ); \
_control = _ERC32_MEC_Timer_Control_Mirror; \
_control &= ERC32_MEC_TIMER_COUNTER_DEFINED_MASK; \
_ERC32_MEC_Timer_Control_Mirror = _control | _value; \
_control &= ERC32_MEC_TIMER_COUNTER_CURRENT_MODE_MASK; \
_control |= __value; \
/* printf( "RTC 0x%x 0x%x 0x%x\n", _value, __value, _control ); */ \
ERC32_MEC.Timer_Control = _control; \
sparc_enable_interrupts( _level ); \
} while ( 0 )
#define ERC32_MEC_Get_Real_Time_Clock_Timer_Control( _value ) \
do { \
(_value) = _ERC32_MEC_Timer_Control_Mirror & 0xf; \
} while ( 0 )
#endif /* !ASM */
#ifdef __cplusplus
}
#endif
#endif /* !_INCLUDE_ERC32_h */
/* end of include file */

View File

@@ -22,12 +22,22 @@
* is used to look up the directive.
*
* void RTEMS()
* {
* }
*/
.align 4
PUBLIC(RTEMS)
SYM(RTEMS):
ret
/*
* g2 was chosen because gcc uses it as a scratch register in
* similar code scenarios and the other locals, ins, and outs
* are off limits to this routine unless it does a "save" and
* copies its in registers to the outs which only works up until
* 6 parameters. Best to take the simple approach in this case.
*/
sethi SYM(_Entry_points), %g2
or %g2, %lo(SYM(_Entry_points)), %g2
sll %g1, 2, %g1
add %g1, %g2, %g2
jmp %g2
nop

View File

@@ -1,7 +1,7 @@
/* sparc.h
*
* This include file contains information pertaining to the Motorola
* SPARC processor family.
* This include file contains information pertaining to the SPARC
* processor family.
*
* $Id$
*/
@@ -37,8 +37,7 @@ extern "C" {
/*
* This file contains the information required to build
* RTEMS for a particular member of the "sparc"
* family when executing in protected mode. It does
* RTEMS for a particular member of the "sparc" family. It does
* this by setting variables to indicate which implementation
* dependent features are present in a particular member
* of the family.
@@ -51,15 +50,25 @@ extern "C" {
*
* + SPARC_HAS_BITSCAN
* 0 - does not have scan instructions
* 1 - has scan instruction (no support implemented)
* 1 - has scan instruction (not currently implemented)
*
* + SPARC_NUMBER_OF_REGISTER_WINDOWS
* 8 is the most common number supported by SPARC implementations.
* SPARC_PSR_CWP_MASK is derived from this value.
*
* + SPARC_HAS_LOW_POWER_MODE
* 0 - does not have low power mode support (or not supported)
* 1 - has low power mode and thus a CPU model dependent idle task.
*
*/
#if defined(erc32)
#define CPU_MODEL_NAME "erc32"
#define SPARC_HAS_FPU 1
#define SPARC_HAS_BITSCAN 0
#define CPU_MODEL_NAME "erc32"
#define SPARC_HAS_FPU 1
#define SPARC_HAS_BITSCAN 0
#define SPARC_NUMBER_OF_REGISTER_WINDOWS 8
#define SPARC_HAS_LOW_POWER_MODE 1
#else
@@ -73,6 +82,49 @@ extern "C" {
#define CPU_NAME "SPARC"
/*
* Miscellaneous constants
*/
/*
* PSR masks and starting bit positions
*
* NOTE: Reserved bits are ignored.
*/
#if (SPARC_NUMBER_OF_REGISTER_WINDOWS == 8)
#define SPARC_PSR_CWP_MASK 0x07 /* bits 0 - 4 */
#elif (SPARC_NUMBER_OF_REGISTER_WINDOWS == 16)
#define SPARC_PSR_CWP_MASK 0x0F /* bits 0 - 4 */
#elif (SPARC_NUMBER_OF_REGISTER_WINDOWS == 32)
#define SPARC_PSR_CWP_MASK 0x1F /* bits 0 - 4 */
#else
#error "Unsupported number of register windows for this cpu"
#endif
#define SPARC_PSR_ET_MASK 0x00000020 /* bit 5 */
#define SPARC_PSR_PS_MASK 0x00000040 /* bit 6 */
#define SPARC_PSR_S_MASK 0x00000080 /* bit 7 */
#define SPARC_PSR_PIL_MASK 0x00000F00 /* bits 8 - 11 */
#define SPARC_PSR_EF_MASK 0x00001000 /* bit 12 */
#define SPARC_PSR_EC_MASK 0x00002000 /* bit 13 */
#define SPARC_PSR_ICC_MASK 0x00F00000 /* bits 20 - 23 */
#define SPARC_PSR_VER_MASK 0x0F000000 /* bits 24 - 27 */
#define SPARC_PSR_IMPL_MASK 0xF0000000 /* bits 28 - 31 */
#define SPARC_PSR_CWP_BIT_POSITION 0 /* bits 0 - 4 */
#define SPARC_PSR_ET_BIT_POSITION 5 /* bit 5 */
#define SPARC_PSR_PS_BIT_POSITION 6 /* bit 6 */
#define SPARC_PSR_S_BIT_POSITION 7 /* bit 7 */
#define SPARC_PSR_PIL_BIT_POSITION 8 /* bits 8 - 11 */
#define SPARC_PSR_EF_BIT_POSITION 12 /* bit 12 */
#define SPARC_PSR_EC_BIT_POSITION 13 /* bit 13 */
#define SPARC_PSR_ICC_BIT_POSITION 20 /* bits 20 - 23 */
#define SPARC_PSR_VER_BIT_POSITION 24 /* bits 24 - 27 */
#define SPARC_PSR_IMPL_BIT_POSITION 28 /* bits 28 - 31 */
#ifndef ASM
/*
* Standard nop
*/
@@ -83,7 +135,7 @@ extern "C" {
} while ( 0 )
/*
* Some macros to aid in accessing special registers.
* Get and set the PSR
*/
#define sparc_get_psr( _psr ) \
@@ -94,26 +146,56 @@ extern "C" {
#define sparc_set_psr( _psr ) \
do { \
asm volatile ( "wr %%g0,%0,%%psr " : "=r" ((_psr)) : "0" ((_psr)) ); \
nop(); nop(); nop(); \
asm volatile ( "mov %0, %%psr " : "=r" ((_psr)) : "0" ((_psr)) ); \
nop(); \
nop(); \
nop(); \
} while ( 0 )
/*
* Get and set the TBR
*/
#define sparc_get_tbr( _tbr ) \
do { \
(_tbr) = 0; /* to avoid unitialized warnings */ \
asm volatile( "rd %%tbr, %0" : "=r" (_tbr) : "0" (_tbr) ); \
} while ( 0 )
#define sparc_set_tbr( _tbr ) \
do { \
asm volatile( "wr %0, 0, %%tbr" : "=r" (_tbr) : "0" (_tbr) ); \
} while ( 0 )
/*
* Get and set the WIM
*/
#define sparc_get_wim( _wim ) \
do { \
asm volatile( "rd %%wim, %0" : "=r" (_wim) : "0" (_wim) ); \
asm volatile( "rd %%wim, %0" : "=r" (_wim) : "0" (_wim) ); \
} while ( 0 )
#define sparc_set_wim( _wim ) \
do { \
asm volatile( "wr %0, %%wim" : "=r" (_wim) : "0" (_wim) ); \
nop(); \
nop(); \
nop(); \
} while ( 0 )
/*
* Get and set the Y
*/
#define sparc_get_y( _y ) \
do { \
asm volatile( "rd %%y, %0" : "=r" (_y) : "0" (_y) ); \
} while ( 0 )
#define sparc_set_y( _y ) \
do { \
asm volatile( "wr %0, %%y" : "=r" (_y) : "0" (_y) ); \
} while ( 0 )
/*
@@ -121,42 +203,41 @@ extern "C" {
*
*/
#define SPARC_PIL_MASK 0x00000F00
#define sparc_disable_interrupts( _level ) \
do { register unsigned int _mask = SPARC_PIL_MASK; \
(_level) = 0; \
do { \
register unsigned int _newlevel; \
\
asm volatile ( "rd %%psr,%0 ; \
wr %0,%1,%%psr " \
: "=r" ((_level)), "=r" (_mask) \
: "0" ((_level)), "1" (_mask) \
); \
nop(); nop(); nop(); \
sparc_get_psr( _level ); \
(_newlevel) = (_level) | SPARC_PSR_PIL_MASK; \
sparc_set_psr( _newlevel ); \
} while ( 0 )
#define sparc_enable_interrupts( _level ) \
do { unsigned int _tmp; \
do { \
unsigned int _tmp; \
\
sparc_get_psr( _tmp ); \
_tmp &= ~SPARC_PIL_MASK; \
_tmp |= (_level) & SPARC_PIL_MASK; \
_tmp &= ~SPARC_PSR_PIL_MASK; \
_tmp |= (_level) & SPARC_PSR_PIL_MASK; \
sparc_set_psr( _tmp ); \
} while ( 0 )
#define sparc_flash_interrupts( _level ) \
do { \
register unsigned32 _ignored = 0; \
sparc_enable_interrupts( (_level) ); \
sparc_disable_interrupts( _ignored ); \
register unsigned32 _ignored = 0; \
\
sparc_enable_interrupts( (_level) ); \
sparc_disable_interrupts( _ignored ); \
} while ( 0 )
#define sparc_set_interrupt_level( _new_level ) \
do { register unsigned32 _new_psr_level = 0; \
do { \
register unsigned32 _new_psr_level = 0; \
\
sparc_get_psr( _new_psr_level ); \
_new_psr_level &= ~SPARC_PIL_MASK; \
_new_psr_level |= (((_new_level) << 8) & SPARC_PIL_MASK); \
_new_psr_level &= ~SPARC_PSR_PIL_MASK; \
_new_psr_level |= \
(((_new_level) << SPARC_PSR_PIL_BIT_POSITION) & SPARC_PSR_PIL_MASK); \
sparc_set_psr( _new_psr_level ); \
} while ( 0 )
@@ -165,9 +246,12 @@ extern "C" {
register unsigned32 _psr_level = 0; \
\
sparc_get_psr( _psr_level ); \
(_level) = (_psr_level & SPARC_PIL_MASK) >> 8; \
(_level) = \
(_psr_level & SPARC_PSR_PIL_MASK) >> SPARC_PSR_PIL_BIT_POSITION; \
} while ( 0 )
#endif
#ifdef __cplusplus
}
#endif

View File

@@ -1,6 +1,6 @@
/* sparctypes.h
*
* This include file contains type definitions pertaining to the Intel
* This include file contains type definitions pertaining to the
* SPARC processor family.
*
* $Id$
@@ -19,22 +19,22 @@ extern "C" {
* This section defines the basic types for this processor.
*/
typedef unsigned char unsigned8; /* unsigned 8-bit integer */
typedef unsigned short unsigned16; /* unsigned 16-bit integer */
typedef unsigned int unsigned32; /* unsigned 32-bit integer */
typedef unsigned long long unsigned64; /* unsigned 64-bit integer */
typedef unsigned char unsigned8; /* unsigned 8-bit integer */
typedef unsigned short unsigned16; /* unsigned 16-bit integer */
typedef unsigned int unsigned32; /* unsigned 32-bit integer */
typedef unsigned long long unsigned64; /* unsigned 64-bit integer */
typedef unsigned16 Priority_Bit_map_control;
typedef unsigned16 Priority_Bit_map_control;
typedef signed char signed8; /* 8-bit signed integer */
typedef signed short signed16; /* 16-bit signed integer */
typedef signed int signed32; /* 32-bit signed integer */
typedef signed long long signed64; /* 64 bit signed integer */
typedef signed char signed8; /* 8-bit signed integer */
typedef signed short signed16; /* 16-bit signed integer */
typedef signed int signed32; /* 32-bit signed integer */
typedef signed long long signed64; /* 64 bit signed integer */
typedef unsigned32 boolean; /* Boolean value */
typedef unsigned32 boolean; /* Boolean value */
typedef float single_precision; /* single precision float */
typedef double double_precision; /* double precision float */
typedef float single_precision; /* single precision float */
typedef double double_precision; /* double precision float */
typedef void sparc_isr;
typedef void ( *sparc_isr_entry )( void );

View File

@@ -341,17 +341,10 @@ void _CPU_Install_interrupt_stack( void )
*
* _CPU_Internal_threads_Idle_thread_body
*
* NOTES:
*
* 1. This is the same as the regular CPU independent algorithm.
*
* 2. If you implement this using a "halt", "idle", or "shutdown"
* instruction, then don't forget to put it in an infinite loop.
*
* 3. Be warned. Some processors with onboard DMA have been known
* to stop the DMA if the CPU were put in IDLE mode. This might
* also be a problem with other on-chip peripherals. So use this
* hook with caution.
* Stop until we get a signal which is the logically the same thing
* entering low-power or sleep mode on a real processor and waiting for
* an interrupt. This significantly reduces the consumption of host
* CPU cycles which is again similar to low power mode.
*/
void _CPU_Internal_threads_Idle_thread_body( void )
@@ -370,7 +363,8 @@ void _CPU_Context_Initialize(
unsigned32 *_stack_base,
unsigned32 _size,
unsigned32 _new_level,
void *_entry_point
void *_entry_point,
boolean _is_fp
)
{
void *source;
@@ -697,49 +691,15 @@ void _CPU_Fatal_error(unsigned32 error)
_exit(error);
}
/*PAGE
*
* _CPU_ffs
*/
int _CPU_ffs(unsigned32 value)
{
int output;
extern int ffs( int );
output = ffs(value);
output = output - 1;
return output;
}
/*
* Special Purpose Routines to hide the use of UNIX system calls.
*/
#if 0
/* XXX clock had this set of #define's */
/*
* In order to get the types and prototypes used in this file under
* Solaris 2.3, it is necessary to pull the following magic.
*/
#if defined(solaris)
#warning "Ignore the undefining __STDC__ warning"
#undef __STDC__
#define __STDC__ 0
#undef _POSIX_C_SOURCE
#endif
#endif
int _CPU_Get_clock_vector( void )
{
return SIGALRM;
}
void _CPU_Start_clock(
int microseconds
)

View File

@@ -549,7 +549,8 @@ EXTERN void (*_CPU_Thread_dispatch_pointer)();
* by RTEMS.
*/
#define CPU_INTERRUPT_NUMBER_OF_VECTORS 64
#define CPU_INTERRUPT_NUMBER_OF_VECTORS 64
#define CPU_INTERRUPT_MAXIMUM_VECTOR_NUMBER (CPU_INTERRUPT_NUMBER_OF_VECTORS - 1)
/*
* Should be large enough to run all RTEMS tests. This insures
@@ -721,7 +722,8 @@ extern void _CPU_Context_Initialize(
unsigned32 *_stack_base,
unsigned32 _size,
unsigned32 _new_level,
void *_entry_point
void *_entry_point,
boolean _is_fp
);
/* end of Context handler macros */
@@ -757,11 +759,11 @@ extern void _CPU_Context_Initialize(
*
* RTEMS guarantees that (1) will never happen so it is not a concern.
* (2),(3), (4) are handled by the macros _CPU_Priority_mask() and
* _CPU_Priority_Bits_index(). These three form a set of routines
* _CPU_Priority_bits_index(). These three form a set of routines
* which must logically operate together. Bits in the _value are
* set and cleared based on masks built by _CPU_Priority_mask().
* The basic major and minor values calculated by _Priority_Major()
* and _Priority_Minor() are "massaged" by _CPU_Priority_Bits_index()
* and _Priority_Minor() are "massaged" by _CPU_Priority_bits_index()
* to properly range between the values returned by the "find first bit"
* instruction. This makes it possible for _Priority_Get_highest() to
* calculate the major and directly index into the minor table.
@@ -796,30 +798,25 @@ extern void _CPU_Context_Initialize(
* bit set
*/
#define _CPU_Bitfield_Find_first_bit( _value, _output ) \
_output = _CPU_ffs( _value )
/*
* The UNIX port uses the generic C algorithm for bitfield scan to avoid
* dependencies on either a native bitscan instruction or an ffs() in the
* C library.
*/
#define CPU_USE_GENERIC_BITFIELD_CODE TRUE
#define CPU_USE_GENERIC_BITFIELD_DATA TRUE
/* end of Bitfield handler macros */
/* Priority handler handler macros */
/*
* This routine builds the mask which corresponds to the bit fields
* as searched by _CPU_Bitfield_Find_first_bit(). See the discussion
* for that routine.
* The UNIX port uses the generic C algorithm for bitfield scan to avoid
* dependencies on either a native bitscan instruction or an ffs() in the
* C library.
*/
#define _CPU_Priority_Mask( _bit_number ) \
( 1 << (_bit_number) )
/*
* This routine translates the bit numbers returned by
* _CPU_Bitfield_Find_first_bit() into something suitable for use as
* a major or minor component of a priority. See the discussion
* for that routine.
*/
#define _CPU_Priority_Bits_index( _priority ) \
(_priority)
/* end of Priority handler macros */
/* functions */
@@ -935,10 +932,6 @@ void _CPU_Fatal_error(
unsigned32 _error
);
int _CPU_ffs(
unsigned32 _value
);
/* The following routine swaps the endian format of an unsigned int.
* It must be static because it is referenced indirectly.
*

View File

@@ -38,9 +38,58 @@ extern "C" {
* significant impact on the performance of the executive as a whole.
*/
#if ( CPU_USE_GENERIC_BITFIELD_DATA == TRUE )
#ifndef INIT
extern const unsigned char __log2table[256];
#else
const unsigned char __log2table[256] = {
7, 7, 6, 6, 5, 5, 5, 5, 4, 4, 4, 4, 4, 4, 4, 4,
3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
};
#endif
#endif
#if ( CPU_USE_GENERIC_BITFIELD_CODE == FALSE )
#define _Bitfield_Find_first_bit( _value, _bit_number ) \
_CPU_Bitfield_Find_first_bit( _value, _bit_number )
#else
/*
* The following must be a macro because if a CPU specific version
* is used it will most likely use inline assembly.
*/
#define _Bitfield_Find_first_bit( _value, _bit_number ) \
{ \
register __value = (_value); \
register const unsigned char *__p = __log2table; \
\
if ( __value < 0x100 ) \
(_bit_number) = __p[ __value ] + 8; \
else \
(_bit_number) = __p[ __value >> 8 ]; \
}
#endif
#ifdef __cplusplus
}
#endif

View File

@@ -47,8 +47,9 @@ EXTERN boolean _Context_Switch_necessary;
* thread's initial state.
*/
#define _Context_Initialize( _the_context, _stack, _size, _isr, _entry ) \
_CPU_Context_Initialize( _the_context, _stack, _size, _isr, _entry )
#define \
_Context_Initialize( _the_context, _stack, _size, _isr, _entry, _is_fp ) \
_CPU_Context_Initialize( _the_context, _stack, _size, _isr, _entry, _is_fp )
/*
* _Context_Switch

View File

@@ -50,11 +50,18 @@ typedef ISR_Handler ( *ISR_Handler_entry )(
ISR_Vector_number
);
/*
* This constant promotes out the number of vectors supported by
* the current CPU being used.
* This constant promotes out the number of vectors truly supported by
* the current CPU being used. This is usually the number of distinct vectors
* the cpu can vector.
*/
#define ISR_NUMBER_OF_VECTORS CPU_INTERRUPT_NUMBER_OF_VECTORS
#define ISR_NUMBER_OF_VECTORS CPU_INTERRUPT_NUMBER_OF_VECTORS
/*
* This constant promotes out the highest valid interrupt vector number.
*/
#define ISR_INTERRUPT_MAXIMUM_VECTOR_NUMBER CPU_INTERRUPT_MAXIMUM_VECTOR_NUMBER
/*
* The following is TRUE if signals have been sent to the currently
@@ -75,7 +82,7 @@ EXTERN unsigned32 _ISR_Nest_level;
* interrupt service routines are vectored by the ISR Handler via this table.
*/
EXTERN ISR_Handler_entry _ISR_Vector_table[CPU_INTERRUPT_NUMBER_OF_VECTORS];
EXTERN ISR_Handler_entry _ISR_Vector_table[ ISR_NUMBER_OF_VECTORS ];
/*
* _ISR_Handler_initialization

View File

@@ -113,6 +113,51 @@ STATIC INLINE unsigned32 _Priority_Minor (
Priority_Control the_priority
);
/*
* _Priority_Mask
*
* DESCRIPTION:
*
* This function returns the mask associated with the major or minor
* number passed to it.
*/
#if ( CPU_USE_GENERIC_BITFIELD_CODE == TRUE )
STATIC INLINE unsigned32 _Priority_Mask (
unsigned32 bit_number
);
#else
#define _Priority_Mask( _bit_number ) \
_CPU_Priority_Mask( _bit_number )
#endif
/*
* _Priority_Bits_index
*
* DESCRIPTION:
*
* This function translates the bit numbers returned by the bit scan
* of a priority bit field into something suitable for use as
* a major or minor component of a priority.
*/
#if ( CPU_USE_GENERIC_BITFIELD_CODE == TRUE )
STATIC INLINE unsigned32 _Priority_Bits_index (
unsigned32 bit_number
);
#else
#define _Priority_Bits_index( _priority ) \
_CPU_Priority_bits_index( _priority )
#endif
/*
* _Priority_Add_to_bit_map
*

View File

@@ -38,9 +38,58 @@ extern "C" {
* significant impact on the performance of the executive as a whole.
*/
#if ( CPU_USE_GENERIC_BITFIELD_DATA == TRUE )
#ifndef INIT
extern const unsigned char __log2table[256];
#else
const unsigned char __log2table[256] = {
7, 7, 6, 6, 5, 5, 5, 5, 4, 4, 4, 4, 4, 4, 4, 4,
3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
};
#endif
#endif
#if ( CPU_USE_GENERIC_BITFIELD_CODE == FALSE )
#define _Bitfield_Find_first_bit( _value, _bit_number ) \
_CPU_Bitfield_Find_first_bit( _value, _bit_number )
#else
/*
* The following must be a macro because if a CPU specific version
* is used it will most likely use inline assembly.
*/
#define _Bitfield_Find_first_bit( _value, _bit_number ) \
{ \
register __value = (_value); \
register const unsigned char *__p = __log2table; \
\
if ( __value < 0x100 ) \
(_bit_number) = __p[ __value ] + 8; \
else \
(_bit_number) = __p[ __value >> 8 ]; \
}
#endif
#ifdef __cplusplus
}
#endif

View File

@@ -47,8 +47,9 @@ EXTERN boolean _Context_Switch_necessary;
* thread's initial state.
*/
#define _Context_Initialize( _the_context, _stack, _size, _isr, _entry ) \
_CPU_Context_Initialize( _the_context, _stack, _size, _isr, _entry )
#define \
_Context_Initialize( _the_context, _stack, _size, _isr, _entry, _is_fp ) \
_CPU_Context_Initialize( _the_context, _stack, _size, _isr, _entry, _is_fp )
/*
* _Context_Switch

View File

@@ -50,11 +50,18 @@ typedef ISR_Handler ( *ISR_Handler_entry )(
ISR_Vector_number
);
/*
* This constant promotes out the number of vectors supported by
* the current CPU being used.
* This constant promotes out the number of vectors truly supported by
* the current CPU being used. This is usually the number of distinct vectors
* the cpu can vector.
*/
#define ISR_NUMBER_OF_VECTORS CPU_INTERRUPT_NUMBER_OF_VECTORS
#define ISR_NUMBER_OF_VECTORS CPU_INTERRUPT_NUMBER_OF_VECTORS
/*
* This constant promotes out the highest valid interrupt vector number.
*/
#define ISR_INTERRUPT_MAXIMUM_VECTOR_NUMBER CPU_INTERRUPT_MAXIMUM_VECTOR_NUMBER
/*
* The following is TRUE if signals have been sent to the currently
@@ -75,7 +82,7 @@ EXTERN unsigned32 _ISR_Nest_level;
* interrupt service routines are vectored by the ISR Handler via this table.
*/
EXTERN ISR_Handler_entry _ISR_Vector_table[CPU_INTERRUPT_NUMBER_OF_VECTORS];
EXTERN ISR_Handler_entry _ISR_Vector_table[ ISR_NUMBER_OF_VECTORS ];
/*
* _ISR_Handler_initialization

View File

@@ -113,6 +113,51 @@ STATIC INLINE unsigned32 _Priority_Minor (
Priority_Control the_priority
);
/*
* _Priority_Mask
*
* DESCRIPTION:
*
* This function returns the mask associated with the major or minor
* number passed to it.
*/
#if ( CPU_USE_GENERIC_BITFIELD_CODE == TRUE )
STATIC INLINE unsigned32 _Priority_Mask (
unsigned32 bit_number
);
#else
#define _Priority_Mask( _bit_number ) \
_CPU_Priority_Mask( _bit_number )
#endif
/*
* _Priority_Bits_index
*
* DESCRIPTION:
*
* This function translates the bit numbers returned by the bit scan
* of a priority bit field into something suitable for use as
* a major or minor component of a priority.
*/
#if ( CPU_USE_GENERIC_BITFIELD_CODE == TRUE )
STATIC INLINE unsigned32 _Priority_Bits_index (
unsigned32 bit_number
);
#else
#define _Priority_Bits_index( _priority ) \
_CPU_Priority_bits_index( _priority )
#endif
/*
* _Priority_Add_to_bit_map
*

View File

@@ -38,7 +38,7 @@ STATIC INLINE boolean _ISR_Is_vector_number_valid (
unsigned32 vector
)
{
return ( vector < CPU_INTERRUPT_NUMBER_OF_VECTORS );
return ( vector <= CPU_INTERRUPT_MAXIMUM_VECTOR_NUMBER );
}
/*PAGE

View File

@@ -78,6 +78,37 @@ STATIC INLINE unsigned32 _Priority_Minor (
return ( the_priority % 16 );
}
#if ( CPU_USE_GENERIC_BITFIELD_CODE == TRUE )
/*PAGE
*
* _Priority_Mask
*
*/
STATIC INLINE unsigned32 _Priority_Mask (
unsigned32 bit_number
)
{
return (0x8000 >> bit_number);
}
/*PAGE
*
* _Priority_Bits_index
*
*/
STATIC INLINE unsigned32 _Priority_Bits_index (
unsigned32 bit_number
)
{
return bit_number;
}
#endif
/*PAGE
*
* _Priority_Add_to_bit_map
@@ -121,8 +152,8 @@ STATIC INLINE Priority_Control _Priority_Get_highest( void )
_Bitfield_Find_first_bit( _Priority_Major_bit_map, major );
_Bitfield_Find_first_bit( _Priority_Bit_map[major], minor );
return (_CPU_Priority_Bits_index( major ) << 4) +
_CPU_Priority_Bits_index( minor );
return (_Priority_Bits_index( major ) << 4) +
_Priority_Bits_index( minor );
}
/*PAGE
@@ -144,13 +175,13 @@ STATIC INLINE void _Priority_Initialize_information(
minor = _Priority_Minor( new_priority );
the_priority_map->minor =
&_Priority_Bit_map[ _CPU_Priority_Bits_index(major) ];
&_Priority_Bit_map[ _Priority_Bits_index(major) ];
mask = _CPU_Priority_Mask( major );
mask = _Priority_Mask( major );
the_priority_map->ready_major = mask;
the_priority_map->block_major = ~mask;
mask = _CPU_Priority_Mask( minor );
mask = _Priority_Mask( minor );
the_priority_map->ready_minor = mask;
the_priority_map->block_minor = ~mask;
}

View File

@@ -38,7 +38,7 @@ STATIC INLINE boolean _ISR_Is_vector_number_valid (
unsigned32 vector
)
{
return ( vector < CPU_INTERRUPT_NUMBER_OF_VECTORS );
return ( vector <= CPU_INTERRUPT_MAXIMUM_VECTOR_NUMBER );
}
/*PAGE

View File

@@ -78,6 +78,37 @@ STATIC INLINE unsigned32 _Priority_Minor (
return ( the_priority % 16 );
}
#if ( CPU_USE_GENERIC_BITFIELD_CODE == TRUE )
/*PAGE
*
* _Priority_Mask
*
*/
STATIC INLINE unsigned32 _Priority_Mask (
unsigned32 bit_number
)
{
return (0x8000 >> bit_number);
}
/*PAGE
*
* _Priority_Bits_index
*
*/
STATIC INLINE unsigned32 _Priority_Bits_index (
unsigned32 bit_number
)
{
return bit_number;
}
#endif
/*PAGE
*
* _Priority_Add_to_bit_map
@@ -121,8 +152,8 @@ STATIC INLINE Priority_Control _Priority_Get_highest( void )
_Bitfield_Find_first_bit( _Priority_Major_bit_map, major );
_Bitfield_Find_first_bit( _Priority_Bit_map[major], minor );
return (_CPU_Priority_Bits_index( major ) << 4) +
_CPU_Priority_Bits_index( minor );
return (_Priority_Bits_index( major ) << 4) +
_Priority_Bits_index( minor );
}
/*PAGE
@@ -144,13 +175,13 @@ STATIC INLINE void _Priority_Initialize_information(
minor = _Priority_Minor( new_priority );
the_priority_map->minor =
&_Priority_Bit_map[ _CPU_Priority_Bits_index(major) ];
&_Priority_Bit_map[ _Priority_Bits_index(major) ];
mask = _CPU_Priority_Mask( major );
mask = _Priority_Mask( major );
the_priority_map->ready_major = mask;
the_priority_map->block_major = ~mask;
mask = _CPU_Priority_Mask( minor );
mask = _Priority_Mask( minor );
the_priority_map->ready_minor = mask;
the_priority_map->block_minor = ~mask;
}

View File

@@ -33,7 +33,7 @@
*/
#define _ISR_Is_vector_number_valid( _vector ) \
( (_vector) < CPU_INTERRUPT_NUMBER_OF_VECTORS )
( (_vector) <= CPU_INTERRUPT_MAXIMUM_VECTOR_NUMBER )
/*PAGE
*

View File

@@ -64,6 +64,28 @@
#define _Priority_Minor( _the_priority ) ( (_the_priority) % 16 )
#if ( CPU_USE_GENERIC_BITFIELD_CODE == TRUE )
/*PAGE
*
* _Priority_Mask
*
*/
#define _Priority_Mask( _bit_number ) \
(0x8000 >> _bit_number)
/*PAGE
*
* _Priority_Bits_index
*
*/
#define _Priority_Bits_index( _bit_number ) \
(_bit_number)
#endif
/*PAGE
*
* _Priority_Add_to_bit_map
@@ -103,8 +125,8 @@
_Bitfield_Find_first_bit( _Priority_Major_bit_map, major ); \
_Bitfield_Find_first_bit( _Priority_Bit_map[major], minor ); \
\
(_high_priority) = (_CPU_Priority_Bits_index( major ) * 16) + \
_CPU_Priority_Bits_index( minor ); \
(_high_priority) = (_Priority_Bits_index( major ) * 16) + \
_Priority_Bits_index( minor ); \
}
/*PAGE
@@ -124,13 +146,13 @@
_minor = _Priority_Minor( (_new_priority) ); \
\
(_the_priority_map)->minor = \
&_Priority_Bit_map[ _CPU_Priority_Bits_index(_major) ]; \
&_Priority_Bit_map[ _Priority_Bits_index(_major) ]; \
\
_mask = _CPU_Priority_Mask( _major ); \
_mask = _Priority_Mask( _major ); \
(_the_priority_map)->ready_major = _mask; \
(_the_priority_map)->block_major = ~_mask; \
\
_mask = _CPU_Priority_Mask( _minor ); \
_mask = _Priority_Mask( _minor ); \
(_the_priority_map)->ready_minor = _mask; \
(_the_priority_map)->block_minor = ~_mask; \
}

View File

@@ -33,7 +33,7 @@
*/
#define _ISR_Is_vector_number_valid( _vector ) \
( (_vector) < CPU_INTERRUPT_NUMBER_OF_VECTORS )
( (_vector) <= CPU_INTERRUPT_MAXIMUM_VECTOR_NUMBER )
/*PAGE
*

View File

@@ -64,6 +64,28 @@
#define _Priority_Minor( _the_priority ) ( (_the_priority) % 16 )
#if ( CPU_USE_GENERIC_BITFIELD_CODE == TRUE )
/*PAGE
*
* _Priority_Mask
*
*/
#define _Priority_Mask( _bit_number ) \
(0x8000 >> _bit_number)
/*PAGE
*
* _Priority_Bits_index
*
*/
#define _Priority_Bits_index( _bit_number ) \
(_bit_number)
#endif
/*PAGE
*
* _Priority_Add_to_bit_map
@@ -103,8 +125,8 @@
_Bitfield_Find_first_bit( _Priority_Major_bit_map, major ); \
_Bitfield_Find_first_bit( _Priority_Bit_map[major], minor ); \
\
(_high_priority) = (_CPU_Priority_Bits_index( major ) * 16) + \
_CPU_Priority_Bits_index( minor ); \
(_high_priority) = (_Priority_Bits_index( major ) * 16) + \
_Priority_Bits_index( minor ); \
}
/*PAGE
@@ -124,13 +146,13 @@
_minor = _Priority_Minor( (_new_priority) ); \
\
(_the_priority_map)->minor = \
&_Priority_Bit_map[ _CPU_Priority_Bits_index(_major) ]; \
&_Priority_Bit_map[ _Priority_Bits_index(_major) ]; \
\
_mask = _CPU_Priority_Mask( _major ); \
_mask = _Priority_Mask( _major ); \
(_the_priority_map)->ready_major = _mask; \
(_the_priority_map)->block_major = ~_mask; \
\
_mask = _CPU_Priority_Mask( _minor ); \
_mask = _Priority_Mask( _minor ); \
(_the_priority_map)->ready_minor = _mask; \
(_the_priority_map)->block_minor = ~_mask; \
}

View File

@@ -805,9 +805,12 @@ void _Thread_Load_environment(
Thread_Control *the_thread
)
{
boolean is_fp = FALSE;
if ( the_thread->Start.fp_context ) {
the_thread->fp_context = the_thread->Start.fp_context;
_Context_Initialize_fp( &the_thread->fp_context );
is_fp = TRUE;
}
the_thread->is_preemptible = the_thread->Start.is_preemptible;
@@ -818,7 +821,8 @@ void _Thread_Load_environment(
the_thread->Start.Initial_stack.area,
the_thread->Start.Initial_stack.size,
the_thread->Start.isr_level,
_Thread_Handler
_Thread_Handler,
is_fp
);
}

View File

@@ -10,13 +10,13 @@
#define __RINGBUF_H__
#ifndef RINGBUF_QUEUE_LENGTH
#define RINGBUF_QUEUE_LENGTH 200
#define RINGBUF_QUEUE_LENGTH 128
#endif
typedef struct {
char buffer[RINGBUF_QUEUE_LENGTH];
int head;
int tail;
volatile int head;
volatile int tail;
} Ring_buffer_t;
#define Ring_buffer_Initialize( _buffer ) \
@@ -27,16 +27,27 @@ typedef struct {
#define Ring_buffer_Is_empty( _buffer ) \
( (_buffer)->head == (_buffer)->tail )
#define Ring_buffer_Is_full( _buffer ) \
( (_buffer)->head == ((_buffer)->tail + 1) % RINGBUF_QUEUE_LENGTH )
#define Ring_buffer_Add_character( _buffer, _ch ) \
do { \
(_buffer)->buffer[ (_buffer)->tail ] = (_ch); \
(_buffer)->tail = ((_buffer)->tail+1) % RINGBUF_QUEUE_LENGTH; \
rtems_unsigned32 isrlevel; \
\
rtems_interrupt_disable( isrlevel ); \
(_buffer)->tail = ((_buffer)->tail+1) % RINGBUF_QUEUE_LENGTH; \
(_buffer)->buffer[ (_buffer)->tail ] = (_ch); \
rtems_interrupt_enable( isrlevel ); \
} while ( 0 )
#define Ring_buffer_Remove_character( _buffer, _ch ) \
do { \
(_ch) = (_buffer)->buffer[ (_buffer)->head ]; \
(_buffer)->head = ((_buffer)->head+1) % RINGBUF_QUEUE_LENGTH; \
rtems_unsigned32 isrlevel; \
\
rtems_interrupt_disable( isrlevel ); \
(_buffer)->head = ((_buffer)->head+1) % RINGBUF_QUEUE_LENGTH; \
(_ch) = (_buffer)->buffer[ (_buffer)->head ]; \
rtems_interrupt_enable( isrlevel ); \
} while ( 0 )
#endif

View File

@@ -29,7 +29,7 @@
#include <rtems.h>
#include <bsp.h>
#include <rtems/libio.h>
#include <rtems/score/intthrd.h>
#include <rtems/intthrd.h>
#include <libcsupport.h>
@@ -243,19 +243,22 @@ bsp_pretasking_hook(void)
void
bsp_postdriver_hook(void)
{
int stdin_fd, stdout_fd, stderr_fd;
if ((stdin_fd = __open("/dev/tty00", O_RDONLY, 0)) == -1)
rtems_fatal_error_occurred('STD0');
if ((stdout_fd = __open("/dev/tty00", O_WRONLY, 0)) == -1)
rtems_fatal_error_occurred('STD1');
if ((stderr_fd = __open("/dev/tty00", O_WRONLY, 0)) == -1)
rtems_fatal_error_occurred('STD2');
if ((stdin_fd != 0) || (stdout_fd != 1) || (stderr_fd != 2))
rtems_fatal_error_occurred('STIO');
int stdin_fd, stdout_fd, stderr_fd;
int error_code;
error_code = 'S' << 24 | 'T' << 16;
if ((stdin_fd = __open("/dev/console", O_RDONLY, 0)) == -1)
rtems_fatal_error_occurred( error_code | 'D' << 8 | '0' );
if ((stdout_fd = __open("/dev/console", O_WRONLY, 0)) == -1)
rtems_fatal_error_occurred( error_code | 'D' << 8 | '1' );
if ((stderr_fd = __open("/dev/console", O_WRONLY, 0)) == -1)
rtems_fatal_error_occurred( error_code | 'D' << 8 | '2' );
if ((stdin_fd != 0) || (stdout_fd != 1) || (stderr_fd != 2))
rtems_fatal_error_occurred( error_code | 'I' << 8 | 'O' );
}
/*

View File

@@ -75,17 +75,6 @@ void Install_clock(
atexit( Clock_exit );
}
void ReInstall_clock(
rtems_isr_entry clock_isr
)
{
rtems_unsigned32 isrlevel = 0;
rtems_interrupt_disable( isrlevel );
(void) set_vector( clock_isr, CLOCK_VECTOR, 1 );
rtems_interrupt_enable( isrlevel );
}
void Clock_exit( void )
{
if ( BSP_Configuration.ticks_per_timeslice ) {
@@ -119,6 +108,7 @@ rtems_device_driver Clock_control(
void *pargp
)
{
rtems_unsigned32 isrlevel;
rtems_libio_ioctl_args_t *args = pargp;
if (args == 0)
@@ -135,7 +125,9 @@ rtems_device_driver Clock_control(
}
else if (args->command == rtems_build_name('N', 'E', 'W', ' '))
{
ReInstall_clock(args->buffer);
rtems_interrupt_disable( isrlevel );
(void) set_vector( args->buffer, CLOCK_VECTOR, 1 );
rtems_interrupt_enable( isrlevel );
}
done:

View File

@@ -122,18 +122,21 @@ void
bsp_postdriver_hook(void)
{
int stdin_fd, stdout_fd, stderr_fd;
int error_code;
error_code = 'S' << 24 | 'T' << 16;
if ((stdin_fd = __open("/dev/console", O_RDONLY, 0)) == -1)
rtems_fatal_error_occurred('STD0');
rtems_fatal_error_occurred( error_code | 'D' << 8 | '0' );
if ((stdout_fd = __open("/dev/console", O_WRONLY, 0)) == -1)
rtems_fatal_error_occurred('STD1');
rtems_fatal_error_occurred( error_code | 'D' << 8 | '1' );
if ((stderr_fd = __open("/dev/console", O_WRONLY, 0)) == -1)
rtems_fatal_error_occurred('STD2');
rtems_fatal_error_occurred( error_code | 'D' << 8 | '2' );
if ((stdin_fd != 0) || (stdout_fd != 1) || (stderr_fd != 2))
rtems_fatal_error_occurred('STIO');
rtems_fatal_error_occurred( error_code | 'I' << 8 | 'O' );
}
int main(

View File

@@ -108,17 +108,6 @@ void Install_clock(
atexit( Clock_exit );
}
void ReInstall_clock(
rtems_isr_entry clock_isr
)
{
rtems_unsigned32 isrlevel = 0;
rtems_interrupt_disable( isrlevel );
(void) set_vector( clock_isr, CLOCK_VECTOR, 1 );
rtems_interrupt_enable( isrlevel );
}
void Clock_exit( void )
{
if ( BSP_Configuration.ticks_per_timeslice ) {
@@ -161,6 +150,7 @@ rtems_device_driver Clock_control(
void *pargp
)
{
rtems_unsigned32 isrlevel;
rtems_libio_ioctl_args_t *args = pargp;
if (args == 0)
@@ -177,7 +167,9 @@ rtems_device_driver Clock_control(
}
else if (args->command == rtems_build_name('N', 'E', 'W', ' '))
{
ReInstall_clock(args->buffer);
rtems_interrupt_disable( isrlevel );
(void) set_vector( args->buffer, CLOCK_VECTOR, 1 );
rtems_interrupt_enable( isrlevel );
}
done:

View File

@@ -129,18 +129,21 @@ void
bsp_postdriver_hook(void)
{
int stdin_fd, stdout_fd, stderr_fd;
int error_code;
error_code = 'S' << 24 | 'T' << 16;
if ((stdin_fd = __open("/dev/console", O_RDONLY, 0)) == -1)
rtems_fatal_error_occurred('STD0');
rtems_fatal_error_occurred( error_code | 'D' << 8 | '0' );
if ((stdout_fd = __open("/dev/console", O_WRONLY, 0)) == -1)
rtems_fatal_error_occurred('STD1');
rtems_fatal_error_occurred( error_code | 'D' << 8 | '1' );
if ((stderr_fd = __open("/dev/console", O_WRONLY, 0)) == -1)
rtems_fatal_error_occurred('STD2');
rtems_fatal_error_occurred( error_code | 'D' << 8 | '2' );
if ((stdin_fd != 0) || (stdout_fd != 1) || (stderr_fd != 2))
rtems_fatal_error_occurred('STIO');
rtems_fatal_error_occurred( error_code | 'I' << 8 | 'O' );
}
/* This is the original command line passed from DOS */

View File

@@ -60,13 +60,6 @@ void Install_clock(
}
}
void ReInstall_clock(
rtems_isr_entry clock_isr
)
{
(void) set_vector( clock_isr, CLOCK_VECTOR, 1 );
}
void Clock_exit()
{
unsigned char *victimer;
@@ -105,6 +98,7 @@ rtems_device_driver Clock_control(
void *pargp
)
{
rtems_unsigned32 isrlevel;
rtems_libio_ioctl_args_t *args = pargp;
if (args == 0)
@@ -121,7 +115,9 @@ rtems_device_driver Clock_control(
}
else if (args->command == rtems_build_name('N', 'E', 'W', ' '))
{
ReInstall_clock(args->buffer);
rtems_interrupt_disable( isrlevel );
(void) set_vector( args->buffer, CLOCK_VECTOR, 1 );
rtems_interrupt_enable( isrlevel );
}
done:

View File

@@ -124,18 +124,21 @@ void
bsp_postdriver_hook(void)
{
int stdin_fd, stdout_fd, stderr_fd;
int error_code;
error_code = 'S' << 24 | 'T' << 16;
if ((stdin_fd = __open("/dev/console", O_RDONLY, 0)) == -1)
rtems_fatal_error_occurred('STD0');
rtems_fatal_error_occurred( error_code | 'D' << 8 | '0' );
if ((stdout_fd = __open("/dev/console", O_WRONLY, 0)) == -1)
rtems_fatal_error_occurred('STD1');
rtems_fatal_error_occurred( error_code | 'D' << 8 | '1' );
if ((stderr_fd = __open("/dev/console", O_WRONLY, 0)) == -1)
rtems_fatal_error_occurred('STD2');
rtems_fatal_error_occurred( error_code | 'D' << 8 | '2' );
if ((stdin_fd != 0) || (stdout_fd != 1) || (stderr_fd != 2))
rtems_fatal_error_occurred('STIO');
rtems_fatal_error_occurred( error_code | 'I' << 8 | 'O' );
}
int main(

View File

@@ -97,17 +97,6 @@ void Install_clock(
}
}
void ReInstall_clock(
rtems_isr_entry clock_isr
)
{
rtems_unsigned32 isrlevel = 0 ;
rtems_interrupt_disable( isrlevel );
(void) set_vector( clock_isr, CLOCK_VECTOR, 1 );
rtems_interrupt_enable( isrlevel );
}
void Clock_exit( void )
{
rtems_unsigned8 data;
@@ -145,6 +134,7 @@ rtems_device_driver Clock_control(
void *pargp
)
{
rtems_unsigned32 isrlevel;
rtems_libio_ioctl_args_t *args = pargp;
if (args == 0)
@@ -161,7 +151,9 @@ rtems_device_driver Clock_control(
}
else if (args->command == rtems_build_name('N', 'E', 'W', ' '))
{
ReInstall_clock(args->buffer);
rtems_interrupt_disable( isrlevel );
(void) set_vector( args->buffer, CLOCK_VECTOR, 1 );
rtems_interrupt_enable( isrlevel );
}
done:

View File

@@ -123,18 +123,21 @@ void
bsp_postdriver_hook(void)
{
int stdin_fd, stdout_fd, stderr_fd;
int error_code;
error_code = 'S' << 24 | 'T' << 16;
if ((stdin_fd = __open("/dev/console", O_RDONLY, 0)) == -1)
rtems_fatal_error_occurred('STD0');
rtems_fatal_error_occurred( error_code | 'D' << 8 | '0' );
if ((stdout_fd = __open("/dev/console", O_WRONLY, 0)) == -1)
rtems_fatal_error_occurred('STD1');
rtems_fatal_error_occurred( error_code | 'D' << 8 | '1' );
if ((stderr_fd = __open("/dev/console", O_WRONLY, 0)) == -1)
rtems_fatal_error_occurred('STD2');
rtems_fatal_error_occurred( error_code | 'D' << 8 | '2' );
if ((stdin_fd != 0) || (stdout_fd != 1) || (stderr_fd != 2))
rtems_fatal_error_occurred('STIO');
rtems_fatal_error_occurred( error_code | 'I' << 8 | 'O' );
}
int main(

View File

@@ -70,17 +70,6 @@ void Install_clock(
}
}
void ReInstall_clock(
rtems_isr_entry clock_isr
)
{
rtems_unsigned32 isrlevel = 0 ;
rtems_interrupt_disable( isrlevel );
(void) set_vector( clock_isr, CLOCK_VECTOR, 1 );
rtems_interrupt_enable( isrlevel );
}
void Clock_exit( void )
{
@@ -120,6 +109,7 @@ rtems_device_driver Clock_control(
void *pargp
)
{
rtems_unsigned32 isrlevel;
rtems_libio_ioctl_args_t *args = pargp;
if (args == 0)
@@ -136,7 +126,9 @@ rtems_device_driver Clock_control(
}
else if (args->command == rtems_build_name('N', 'E', 'W', ' '))
{
ReInstall_clock(args->buffer);
rtems_interrupt_disable( isrlevel );
(void) set_vector( args->buffer, CLOCK_VECTOR, 1 );
rtems_interrupt_enable( isrlevel );
}
done:

View File

@@ -123,18 +123,21 @@ void
bsp_postdriver_hook(void)
{
int stdin_fd, stdout_fd, stderr_fd;
int error_code;
error_code = 'S' << 24 | 'T' << 16;
if ((stdin_fd = __open("/dev/console", O_RDONLY, 0)) == -1)
rtems_fatal_error_occurred('STD0');
rtems_fatal_error_occurred( error_code | 'D' << 8 | '0' );
if ((stdout_fd = __open("/dev/console", O_WRONLY, 0)) == -1)
rtems_fatal_error_occurred('STD1');
rtems_fatal_error_occurred( error_code | 'D' << 8 | '1' );
if ((stderr_fd = __open("/dev/console", O_WRONLY, 0)) == -1)
rtems_fatal_error_occurred('STD2');
rtems_fatal_error_occurred( error_code | 'D' << 8 | '2' );
if ((stdin_fd != 0) || (stdout_fd != 1) || (stderr_fd != 2))
rtems_fatal_error_occurred('STIO');
rtems_fatal_error_occurred( error_code | 'I' << 8 | 'O' );
}
int main(

View File

@@ -93,17 +93,6 @@ void Install_clock(
}
}
void ReInstall_clock(
rtems_isr_entry clock_isr
)
{
rtems_unsigned32 isrlevel = 0 ;
rtems_interrupt_disable( isrlevel );
(void) set_vector( clock_isr, CLOCK_VECTOR, 1 );
rtems_interrupt_enable( isrlevel );
}
void Clock_exit( void )
{
@@ -141,6 +130,7 @@ rtems_device_driver Clock_control(
void *pargp
)
{
rtems_unsigned32 isrlevel;
rtems_libio_ioctl_args_t *args = pargp;
if (args == 0)
@@ -157,7 +147,9 @@ rtems_device_driver Clock_control(
}
else if (args->command == rtems_build_name('N', 'E', 'W', ' '))
{
ReInstall_clock(args->buffer);
rtems_interrupt_disable( isrlevel );
(void) set_vector( args->buffer, CLOCK_VECTOR, 1 );
rtems_interrupt_enable( isrlevel );
}
done:

View File

@@ -130,18 +130,21 @@ void
bsp_postdriver_hook(void)
{
int stdin_fd, stdout_fd, stderr_fd;
int error_code;
error_code = 'S' << 24 | 'T' << 16;
if ((stdin_fd = __open("/dev/console", O_RDONLY, 0)) == -1)
rtems_fatal_error_occurred('STD0');
rtems_fatal_error_occurred( error_code | 'D' << 8 | '0' );
if ((stdout_fd = __open("/dev/console", O_WRONLY, 0)) == -1)
rtems_fatal_error_occurred('STD1');
rtems_fatal_error_occurred( error_code | 'D' << 8 | '1' );
if ((stderr_fd = __open("/dev/console", O_WRONLY, 0)) == -1)
rtems_fatal_error_occurred('STD2');
rtems_fatal_error_occurred( error_code | 'D' << 8 | '2' );
if ((stdin_fd != 0) || (stdout_fd != 1) || (stderr_fd != 2))
rtems_fatal_error_occurred('STIO');
rtems_fatal_error_occurred( error_code | 'I' << 8 | 'O' );
}
int main(

View File

@@ -89,7 +89,7 @@ void Install_clock(
Clock_isrs = BSP_Configuration.microseconds_per_tick / 1000;
if ( BSP_Configuration.ticks_per_timeslice ) {
/* set_vector( clock_isr, CLOCK_VECTOR, 1 );*/
set_vector( clock_isr, CLOCK_VECTOR, 1 );
m302.reg.trr1 = TRR1_VAL; /* set timer reference register */
m302.reg.tmr1 = TMR1_VAL; /* set timer mode register & enable */
@@ -102,17 +102,6 @@ void Install_clock(
}
}
void ReInstall_clock(
rtems_isr_entry clock_isr
)
{
rtems_unsigned32 isrlevel;
rtems_interrupt_disable( isrlevel );
/* (void) set_vector( clock_isr, CLOCK_VECTOR, 1 ); */
rtems_interrupt_enable( isrlevel );
}
void Clock_exit( void )
{
if ( BSP_Configuration.ticks_per_timeslice ) {
@@ -145,6 +134,7 @@ rtems_device_driver Clock_control(
void *pargp
)
{
rtems_unsigned32 isrlevel;
rtems_libio_ioctl_args_t *args = pargp;
if (args == 0)
@@ -161,7 +151,9 @@ rtems_device_driver Clock_control(
}
else if (args->command == rtems_build_name('N', 'E', 'W', ' '))
{
ReInstall_clock(args->buffer);
rtems_interrupt_disable( isrlevel );
(void) set_vector( args->buffer, CLOCK_VECTOR, 1 );
rtems_interrupt_enable( isrlevel );
}
done:

View File

@@ -193,7 +193,6 @@ cpy_Bad1: move.l d1,(a0)+
| move.l #_cnsl_isr,vbase+0x028 | SCC2
move.l #timerisr,vbase+0x018 | Timer ISR
move.l #RTC_ISR,vbase+0x024 | Real Time Clock ISR
|
| zero out uninitialized data area
@@ -236,14 +235,6 @@ loop: movel d0,a1@+ | to zero out uninitialized
Bad: bra Bad
nop
RTC_ISR:
movem.l d0-d1/a0-a1,a7@- | save d0-d1,a0-a1
addql #1,_ISR_Nest_level | one nest level deeper
addql #1,_Thread_Dispatch_disable_level
| disable multitasking
jbsr Clock_isr | invoke the user ISR
jmp _ISR_Exit
END_CODE

View File

@@ -193,7 +193,6 @@ cpy_Bad1: move.l d1,(a0)+
| move.l #_cnsl_isr,vbase+0x028 | SCC2
move.l #timerisr,vbase+0x018 | Timer ISR
move.l #RTC_ISR,vbase+0x024 | Real Time Clock ISR
|
| zero out uninitialized data area
@@ -236,14 +235,6 @@ loop: movel d0,a1@+ | to zero out uninitialized
Bad: bra Bad
nop
RTC_ISR:
movem.l d0-d1/a0-a1,a7@- | save d0-d1,a0-a1
addql #1,_ISR_Nest_level | one nest level deeper
addql #1,_Thread_Dispatch_disable_level
| disable multitasking
jbsr Clock_isr | invoke the user ISR
jmp _ISR_Exit
END_CODE

View File

@@ -130,18 +130,21 @@ void
bsp_postdriver_hook(void)
{
int stdin_fd, stdout_fd, stderr_fd;
int error_code;
error_code = 'S' << 24 | 'T' << 16;
if ((stdin_fd = __open("/dev/console", O_RDONLY, 0)) == -1)
rtems_fatal_error_occurred('STD0');
rtems_fatal_error_occurred( error_code | 'D' << 8 | '0' );
if ((stdout_fd = __open("/dev/console", O_WRONLY, 0)) == -1)
rtems_fatal_error_occurred('STD1');
rtems_fatal_error_occurred( error_code | 'D' << 8 | '1' );
if ((stderr_fd = __open("/dev/console", O_WRONLY, 0)) == -1)
rtems_fatal_error_occurred('STD2');
rtems_fatal_error_occurred( error_code | 'D' << 8 | '2' );
if ((stdin_fd != 0) || (stdout_fd != 1) || (stderr_fd != 2))
rtems_fatal_error_occurred('STIO');
rtems_fatal_error_occurred( error_code | 'I' << 8 | 'O' );
}
int main(

View File

@@ -130,16 +130,6 @@ rtems_isr_entry clock_isr;
}
}
void ReInstall_clock( clock_isr )
rtems_isr_entry clock_isr;
{
rtems_unsigned32 isrlevel = 0 ;
rtems_interrupt_disable( isrlevel );
(void) set_vector( clock_isr, CLOCK_VECTOR, 1 );
rtems_interrupt_enable( isrlevel );
}
/* The following was added for debugging purposes */
void Clock_exit( void )
{
@@ -181,6 +171,7 @@ rtems_device_driver Clock_control(
void *pargp
)
{
rtems_unsigned32 isrlevel;
rtems_libio_ioctl_args_t *args = pargp;
if (args == 0)
@@ -197,7 +188,9 @@ rtems_device_driver Clock_control(
}
else if (args->command == rtems_build_name('N', 'E', 'W', ' '))
{
ReInstall_clock(args->buffer);
rtems_interrupt_disable( isrlevel );
(void) set_vector( args->buffer, CLOCK_VECTOR, 1 );
rtems_interrupt_enable( isrlevel );
}
done:

View File

@@ -1,6 +1,6 @@
#
# $Id$
#
/*
* $Id$
*/
/*#########################################################
#

View File

@@ -131,18 +131,21 @@ void
bsp_postdriver_hook(void)
{
int stdin_fd, stdout_fd, stderr_fd;
int error_code;
error_code = 'S' << 24 | 'T' << 16;
if ((stdin_fd = __open("/dev/console", O_RDONLY, 0)) == -1)
rtems_fatal_error_occurred('STD0');
rtems_fatal_error_occurred( error_code | 'D' << 8 | '0' );
if ((stdout_fd = __open("/dev/console", O_WRONLY, 0)) == -1)
rtems_fatal_error_occurred('STD1');
rtems_fatal_error_occurred( error_code | 'D' << 8 | '1' );
if ((stderr_fd = __open("/dev/console", O_WRONLY, 0)) == -1)
rtems_fatal_error_occurred('STD2');
rtems_fatal_error_occurred( error_code | 'D' << 8 | '2' );
if ((stdin_fd != 0) || (stdout_fd != 1) || (stderr_fd != 2))
rtems_fatal_error_occurred('STIO');
rtems_fatal_error_occurred( error_code | 'I' << 8 | 'O' );
}
int main(

View File

@@ -108,17 +108,6 @@ void Install_clock(
}
void ReInstall_clock(
rtems_isr_entry clock_isr
)
{
rtems_unsigned32 isrlevel;
rtems_interrupt_disable( isrlevel );
(void) set_vector( clock_isr, CLOCK_VECTOR, 1 );
rtems_interrupt_enable( isrlevel );
}
void Clock_exit( void )
{
volatile struct z8036_map *timer;
@@ -157,6 +146,7 @@ rtems_device_driver Clock_control(
void *pargp
)
{
rtems_unsigned32 isrlevel;
rtems_libio_ioctl_args_t *args = pargp;
if (args == 0)
@@ -173,7 +163,9 @@ rtems_device_driver Clock_control(
}
else if (args->command == rtems_build_name('N', 'E', 'W', ' '))
{
ReInstall_clock(args->buffer);
rtems_interrupt_disable( isrlevel );
(void) set_vector( args->buffer, CLOCK_VECTOR, 1 );
rtems_interrupt_enable( isrlevel );
}
done:

View File

@@ -124,18 +124,21 @@ void
bsp_postdriver_hook(void)
{
int stdin_fd, stdout_fd, stderr_fd;
int error_code;
error_code = 'S' << 24 | 'T' << 16;
if ((stdin_fd = __open("/dev/console", O_RDONLY, 0)) == -1)
rtems_fatal_error_occurred('STD0');
rtems_fatal_error_occurred( error_code | 'D' << 8 | '0' );
if ((stdout_fd = __open("/dev/console", O_WRONLY, 0)) == -1)
rtems_fatal_error_occurred('STD1');
rtems_fatal_error_occurred( error_code | 'D' << 8 | '1' );
if ((stderr_fd = __open("/dev/console", O_WRONLY, 0)) == -1)
rtems_fatal_error_occurred('STD2');
rtems_fatal_error_occurred( error_code | 'D' << 8 | '2' );
if ((stdin_fd != 0) || (stdout_fd != 1) || (stderr_fd != 2))
rtems_fatal_error_occurred('STIO');
rtems_fatal_error_occurred( error_code | 'I' << 8 | 'O' );
}

View File

@@ -89,15 +89,6 @@ void Install_clock(rtems_isr_entry clock_isr )
}
}
void ReInstall_clock(rtems_isr_entry clock_isr)
{
rtems_unsigned32 isrlevel;
rtems_interrupt_disable( isrlevel );
(void) set_vector( clock_isr, CLOCK_VECTOR, 1 );
rtems_interrupt_enable( isrlevel );
}
void Clock_exit( void )
{
/* Dummy for now. See other m68k BSP's for code examples */
@@ -127,6 +118,7 @@ rtems_device_driver Clock_control(
void *pargp
)
{
rtems_unsigned32 isrlevel;
rtems_libio_ioctl_args_t *args = pargp;
if (args == 0)
@@ -143,7 +135,9 @@ rtems_device_driver Clock_control(
}
else if (args->command == rtems_build_name('N', 'E', 'W', ' '))
{
ReInstall_clock(args->buffer);
rtems_interrupt_disable( isrlevel );
(void) set_vector( args->buffer, CLOCK_VECTOR, 1 );
rtems_interrupt_enable( isrlevel );
}
done:

View File

@@ -130,18 +130,21 @@ void
bsp_postdriver_hook(void)
{
int stdin_fd, stdout_fd, stderr_fd;
int error_code;
error_code = 'S' << 24 | 'T' << 16;
if ((stdin_fd = __open("/dev/console", O_RDONLY, 0)) == -1)
rtems_fatal_error_occurred('STD0');
rtems_fatal_error_occurred( error_code | 'D' << 8 | '0' );
if ((stdout_fd = __open("/dev/console", O_WRONLY, 0)) == -1)
rtems_fatal_error_occurred('STD1');
rtems_fatal_error_occurred( error_code | 'D' << 8 | '1' );
if ((stderr_fd = __open("/dev/console", O_WRONLY, 0)) == -1)
rtems_fatal_error_occurred('STD2');
rtems_fatal_error_occurred( error_code | 'D' << 8 | '2' );
if ((stdin_fd != 0) || (stdout_fd != 1) || (stderr_fd != 2))
rtems_fatal_error_occurred('STIO');
rtems_fatal_error_occurred( error_code | 'I' << 8 | 'O' );
}
int main(

View File

@@ -105,7 +105,7 @@ void Install_clock(
*/
if ( BSP_Configuration.ticks_per_timeslice ) {
Old_ticker = ( rtems_isr_entry ) set_vector( clock_isr, CLOCK_VECTOR, 1 );
Old_ticker = (rtems_isr_entry) set_vector( clock_isr, CLOCK_VECTOR, 1 );
/*
* Hardware specific initialize goes here
*/
@@ -120,30 +120,6 @@ void Install_clock(
atexit( Clock_exit );
}
/*
* Reinstall_clock
*
* Install a clock tick handler without reprogramming the chip. This
* is used by the polling shared memory device driver.
*/
void ReInstall_clock(
rtems_isr_entry clock_isr
)
{
rtems_unsigned32 isrlevel = 0;
/*
* Disable interrupts and install the clock ISR vector using the
* BSP dependent set_vector routine. In the below example, the clock
* ISR is on vector 4 and is an RTEMS interrupt.
*/
rtems_interrupt_disable( isrlevel );
(void) set_vector( clock_isr, CLOCK_VECTOR, 1 );
rtems_interrupt_enable( isrlevel );
}
/*
* Clean up before the application exits
*/
@@ -188,6 +164,7 @@ rtems_device_driver Clock_control(
void *pargp
)
{
rtems_unsigned32 isrlevel;
rtems_libio_ioctl_args_t *args = pargp;
if (args == 0)
@@ -204,7 +181,9 @@ rtems_device_driver Clock_control(
}
else if (args->command == rtems_build_name('N', 'E', 'W', ' '))
{
ReInstall_clock(args->buffer);
rtems_interrupt_disable( isrlevel );
(void) set_vector( args->buffer, CLOCK_VECTOR, 1 );
rtems_interrupt_enable( isrlevel );
}
done:

View File

@@ -131,18 +131,21 @@ void
bsp_postdriver_hook(void)
{
int stdin_fd, stdout_fd, stderr_fd;
int error_code;
error_code = 'S' << 24 | 'T' << 16;
if ((stdin_fd = __open("/dev/console", O_RDONLY, 0)) == -1)
rtems_fatal_error_occurred('STD0');
rtems_fatal_error_occurred( error_code | 'D' << 8 | '0' );
if ((stdout_fd = __open("/dev/console", O_WRONLY, 0)) == -1)
rtems_fatal_error_occurred('STD1');
rtems_fatal_error_occurred( error_code | 'D' << 8 | '1' );
if ((stderr_fd = __open("/dev/console", O_WRONLY, 0)) == -1)
rtems_fatal_error_occurred('STD2');
rtems_fatal_error_occurred( error_code | 'D' << 8 | '2' );
if ((stdin_fd != 0) || (stdout_fd != 1) || (stderr_fd != 2))
rtems_fatal_error_occurred('STIO');
rtems_fatal_error_occurred( error_code | 'I' << 8 | 'O' );
}
int bsp_start(

View File

@@ -149,18 +149,21 @@ void
bsp_postdriver_hook(void)
{
int stdin_fd, stdout_fd, stderr_fd;
int error_code;
error_code = 'S' << 24 | 'T' << 16;
if ((stdin_fd = __open("/dev/console", O_RDONLY, 0)) == -1)
rtems_fatal_error_occurred('STD0');
rtems_fatal_error_occurred( error_code | 'D' << 8 | '0' );
if ((stdout_fd = __open("/dev/console", O_WRONLY, 0)) == -1)
rtems_fatal_error_occurred('STD1');
rtems_fatal_error_occurred( error_code | 'D' << 8 | '1' );
if ((stderr_fd = __open("/dev/console", O_WRONLY, 0)) == -1)
rtems_fatal_error_occurred('STD2');
rtems_fatal_error_occurred( error_code | 'D' << 8 | '2' );
if ((stdin_fd != 0) || (stdout_fd != 1) || (stderr_fd != 2))
rtems_fatal_error_occurred('STIO');
rtems_fatal_error_occurred( error_code | 'I' << 8 | 'O' );
}
int main(

View File

@@ -31,30 +31,18 @@ rtems_unsigned32 Clock_driver_vector;
rtems_device_major_number rtems_clock_major = ~0;
rtems_device_minor_number rtems_clock_minor;
void
Install_clock(rtems_isr_entry clock_isr)
void Install_clock(rtems_isr_entry clock_isr)
{
Clock_driver_ticks = 0;
(void)set_vector(clock_isr, Clock_driver_vector, 1);
(void) set_vector( clock_isr, Clock_driver_vector, 1 );
_CPU_Start_clock( BSP_Configuration.microseconds_per_tick );
atexit(Clock_exit);
}
void
ReInstall_clock(rtems_isr_entry new_clock_isr)
{
rtems_unsigned32 isrlevel = 0;
rtems_interrupt_disable(isrlevel);
(void)set_vector(new_clock_isr, Clock_driver_vector, 1);
rtems_interrupt_enable(isrlevel);
}
void
Clock_isr(int vector)
void Clock_isr(int vector)
{
Clock_driver_ticks++;
rtems_clock_tick();
@@ -65,16 +53,14 @@ Clock_isr(int vector)
* Remove the clock signal
*/
void
Clock_exit(void)
void Clock_exit(void)
{
_CPU_Stop_clock();
(void)set_vector(0, Clock_driver_vector, 1);
(void) set_vector( 0, Clock_driver_vector, 1 );
}
rtems_device_driver
Clock_initialize(
rtems_device_driver Clock_initialize(
rtems_device_major_number major,
rtems_device_minor_number minor,
void *pargp
@@ -99,6 +85,7 @@ rtems_device_driver Clock_control(
void *pargp
)
{
rtems_unsigned32 isrlevel;
rtems_libio_ioctl_args_t *args = pargp;
if (args == 0)
@@ -115,7 +102,9 @@ rtems_device_driver Clock_control(
}
else if (args->command == rtems_build_name('N', 'E', 'W', ' '))
{
ReInstall_clock(args->buffer);
rtems_interrupt_disable( isrlevel );
(void) set_vector( args->buffer, Clock_driver_vector, 1 );
rtems_interrupt_enable( isrlevel );
}
done:

View File

@@ -182,18 +182,21 @@ bsp_postdriver_hook(void)
{
#if 0
int stdin_fd, stdout_fd, stderr_fd;
int error_code;
error_code = 'S' << 24 | 'T' << 16;
if ((stdin_fd = __open("/dev/console", O_RDONLY, 0)) == -1)
rtems_fatal_error_occurred('STD0');
rtems_fatal_error_occurred( error_code | 'D' << 8 | '0' );
if ((stdout_fd = __open("/dev/console", O_WRONLY, 0)) == -1)
rtems_fatal_error_occurred('STD1');
rtems_fatal_error_occurred( error_code | 'D' << 8 | '1' );
if ((stderr_fd = __open("/dev/console", O_WRONLY, 0)) == -1)
rtems_fatal_error_occurred('STD2');
rtems_fatal_error_occurred( error_code | 'D' << 8 | '2' );
if ((stdin_fd != 0) || (stdout_fd != 1) || (stderr_fd != 2))
rtems_fatal_error_occurred('STIO');
rtems_fatal_error_occurred( error_code | 'I' << 8 | 'O' );
#endif
#if defined(MALLOC_STATS)

View File

@@ -0,0 +1,503 @@
/* erc32.h
*
* This include file contains information pertaining to the ERC32.
* The ERC32 is a custom SPARC V7 implementation based on the Cypress
* 601/602 chipset. This CPU has a number of on-board peripherals and
* was developed by the European Space Agency to target space applications.
*
* NOTE: Other than where absolutely required, this version currently
* supports only the peripherals and bits used by the basic board
* support package. This includes at least significant pieces of
* the following items:
*
* + UART Channels A and B
* + General Purpose Timer
* + Real Time Clock
* + Watchdog Timer (so it can be disabled)
* + Control Register (so powerdown mode can be enabled)
* + Memory Control Register
* + Interrupt Control
*
* $Id$
*/
#ifndef _INCLUDE_ERC32_h
#define _INCLUDE_ERC32_h
#include <rtems/score/sparc.h>
#ifdef __cplusplus
extern "C" {
#endif
/*
* Interrupt Sources
*
* The interrupt source numbers directly map to the trap type and to
* the bits used in the Interrupt Clear, Interrupt Force, Interrupt Mask,
* and the Interrupt Pending Registers.
*/
#define ERC32_INTERRUPT_MASKED_ERRORS 1
#define ERC32_INTERRUPT_EXTERNAL_1 2
#define ERC32_INTERRUPT_EXTERNAL_2 3
#define ERC32_INTERRUPT_UART_A_RX_TX 4
#define ERC32_INTERRUPT_UART_B_RX_TX 5
#define ERC32_INTERRUPT_CORRECTABLE_MEMORY_ERROR 6
#define ERC32_INTERRUPT_UART_ERROR 7
#define ERC32_INTERRUPT_DMA_ACCESS_ERROR 8
#define ERC32_INTERRUPT_DMA_TIMEOUT 9
#define ERC32_INTERRUPT_EXTERNAL_3 10
#define ERC32_INTERRUPT_EXTERNAL_4 11
#define ERC32_INTERRUPT_GENERAL_PURPOSE_TIMER 12
#define ERC32_INTERRUPT_REAL_TIME_CLOCK 13
#define ERC32_INTERRUPT_EXTERNAL_5 14
#define ERC32_INTERRUPT_WATCHDOG_TIMEOUT 15
#ifndef ASM
/*
* Trap Types for on-chip peripherals
*
* Source: Table 8 - Interrupt Trap Type and Default Priority Assignments
*
* NOTE: The priority level for each source corresponds to the least
* significant nibble of the trap type.
*/
#define ERC32_TRAP_TYPE( _source ) SPARC_ASYNCHRONOUS_TRAP((_source) + 0x10)
#define ERC32_TRAP_SOURCE( _trap ) ((_trap) - 0x10)
#define ERC32_Is_MEC_Trap( _trap ) \
( (_trap) >= ERC32_TRAP_TYPE( ERC32_INTERRUPT_MASKED_ERRORS ) && \
(_trap) <= ERC32_TRAP_TYPE( ERC32_INTERRUPT_WATCHDOG_TIMEOUT ) )
/*
* Structure for ERC32 memory mapped registers.
*
* Source: Section 3.25.2 - Register Address Map
*
* NOTE: There is only one of these structures per CPU, its base address
* is 0x01f80000, and the variable MEC is placed there by the
* linkcmds file.
*/
typedef struct {
volatile unsigned32 Control; /* offset 0x00 */
volatile unsigned32 Software_Reset; /* offset 0x04 */
volatile unsigned32 Power_Down; /* offset 0x08 */
volatile unsigned32 Unimplemented_0; /* offset 0x0c */
volatile unsigned32 Memory_Configuration; /* offset 0x10 */
volatile unsigned32 IO_Configuration; /* offset 0x14 */
volatile unsigned32 Wait_State_Configuration; /* offset 0x18 */
volatile unsigned32 Unimplemented_1; /* offset 0x1c */
volatile unsigned32 Memory_Access_0; /* offset 0x20 */
volatile unsigned32 Memory_Access_1; /* offset 0x24 */
volatile unsigned32 Unimplemented_2[ 7 ]; /* offset 0x28 */
volatile unsigned32 Interrupt_Shape; /* offset 0x44 */
volatile unsigned32 Interrupt_Pending; /* offset 0x48 */
volatile unsigned32 Interrupt_Mask; /* offset 0x4c */
volatile unsigned32 Interrupt_Clear; /* offset 0x50 */
volatile unsigned32 Interrupt_Force; /* offset 0x54 */
volatile unsigned32 Unimplemented_3[ 2 ]; /* offset 0x58 */
/* offset 0x60 */
volatile unsigned32 Watchdog_Program_and_Timeout_Acknowledge;
volatile unsigned32 Watchdog_Trap_Door_Set; /* offset 0x64 */
volatile unsigned32 Unimplemented_4[ 6 ]; /* offset 0x68 */
volatile unsigned32 Real_Time_Clock_Counter; /* offset 0x80 */
volatile unsigned32 Real_Time_Clock_Scalar; /* offset 0x84 */
volatile unsigned32 General_Purpose_Timer_Counter; /* offset 0x88 */
volatile unsigned32 General_Purpose_Timer_Scalar; /* offset 0x8c */
volatile unsigned32 Unimplemented_5[ 2 ]; /* offset 0x90 */
volatile unsigned32 Timer_Control; /* offset 0x98 */
volatile unsigned32 Unimplemented_6; /* offset 0x9c */
volatile unsigned32 System_Fault_Status; /* offset 0xa0 */
volatile unsigned32 First_Failing_Address; /* offset 0xa4 */
volatile unsigned32 First_Failing_Data; /* offset 0xa8 */
volatile unsigned32 First_Failing_Syndrome_and_Check_Bits;/* offset 0xac */
volatile unsigned32 Error_and_Reset_Status; /* offset 0xb0 */
volatile unsigned32 Error_Mask; /* offset 0xb4 */
volatile unsigned32 Unimplemented_7[ 2 ]; /* offset 0xb8 */
volatile unsigned32 Debug_Control; /* offset 0xc0 */
volatile unsigned32 Breakpoint; /* offset 0xc4 */
volatile unsigned32 Watchpoint; /* offset 0xc8 */
volatile unsigned32 Unimplemented_8; /* offset 0xcc */
volatile unsigned32 Test_Control; /* offset 0xd0 */
volatile unsigned32 Test_Data; /* offset 0xd4 */
volatile unsigned32 Unimplemented_9[ 2 ]; /* offset 0xd8 */
volatile unsigned32 UART_Channel_A; /* offset 0xe0 */
volatile unsigned32 UART_Channel_B; /* offset 0xe4 */
volatile unsigned32 UART_Status; /* offset 0xe8 */
} ERC32_Register_Map;
#endif
/*
* The following constants are intended to be used ONLY in assembly
* language files.
*
* NOTE: The intended style of usage is to load the address of MEC
* into a register and then use these as displacements from
* that register.
*/
#ifdef ASM
#define ERC32_MEC_CONTROL_OFFSET 0x00
#define ERC32_MEC_SOFTWARE_RESET_OFFSET 0x04
#define ERC32_MEC_POWER_DOWN_OFFSET 0x08
#define ERC32_MEC_UNIMPLEMENTED_0_OFFSET 0x0C
#define ERC32_MEC_MEMORY_CONFIGURATION_OFFSET 0x10
#define ERC32_MEC_IO_CONFIGURATION_OFFSET 0x14
#define ERC32_MEC_WAIT_STATE_CONFIGURATION_OFFSET 0x18
#define ERC32_MEC_UNIMPLEMENTED_1_OFFSET 0x1C
#define ERC32_MEC_MEMORY_ACCESS_0_OFFSET 0x20
#define ERC32_MEC_MEMORY_ACCESS_1_OFFSET 0x24
#define ERC32_MEC_UNIMPLEMENTED_2_OFFSET 0x28
#define ERC32_MEC_INTERRUPT_SHAPE_OFFSET 0x44
#define ERC32_MEC_INTERRUPT_PENDING_OFFSET 0x48
#define ERC32_MEC_INTERRUPT_MASK_OFFSET 0x4C
#define ERC32_MEC_INTERRUPT_CLEAR_OFFSET 0x50
#define ERC32_MEC_INTERRUPT_FORCE_OFFSET 0x54
#define ERC32_MEC_UNIMPLEMENTED_3_OFFSET 0x58
#define ERC32_MEC_WATCHDOG_PROGRAM_AND_TIMEOUT_ACKNOWLEDGE_OFFSET 0x60
#define ERC32_MEC_WATCHDOG_TRAP_DOOR_SET_OFFSET 0x64
#define ERC32_MEC_UNIMPLEMENTED_4_OFFSET 0x6C
#define ERC32_MEC_REAL_TIME_CLOCK_COUNTER_OFFSET 0x80
#define ERC32_MEC_REAL_TIME_CLOCK_SCALAR_OFFSET 0x84
#define ERC32_MEC_GENERAL_PURPOSE_TIMER_COUNTER_OFFSET 0x88
#define ERC32_MEC_GENERAL_PURPOSE_TIMER_SCALAR_OFFSET 0x8C
#define ERC32_MEC_UNIMPLEMENTED_5_OFFSET 0x90
#define ERC32_MEC_TIMER_CONTROL_OFFSET 0x98
#define ERC32_MEC_UNIMPLEMENTED_6_OFFSET 0x9C
#define ERC32_MEC_SYSTEM_FAULT_STATUS_OFFSET 0xA0
#define ERC32_MEC_FIRST_FAILING_ADDRESS_OFFSET 0xA4
#define ERC32_MEC_FIRST_FAILING_DATA_OFFSET 0xA8
#define ERC32_MEC_FIRST_FAILING_SYNDROME_AND_CHECK_BITS_OFFSET 0xAC
#define ERC32_MEC_ERROR_AND_RESET_STATUS_OFFSET 0xB0
#define ERC32_MEC_ERROR_MASK_OFFSET 0xB4
#define ERC32_MEC_UNIMPLEMENTED_7_OFFSET 0xB8
#define ERC32_MEC_DEBUG_CONTROL_OFFSET 0xC0
#define ERC32_MEC_BREAKPOINT_OFFSET 0xC4
#define ERC32_MEC_WATCHPOINT_OFFSET 0xC8
#define ERC32_MEC_UNIMPLEMENTED_8_OFFSET 0xCC
#define ERC32_MEC_TEST_CONTROL_OFFSET 0xD0
#define ERC32_MEC_TEST_DATA_OFFSET 0xD4
#define ERC32_MEC_UNIMPLEMENTED_9_OFFSET 0xD8
#define ERC32_MEC_UART_CHANNEL_A_OFFSET 0xE0
#define ERC32_MEC_UART_CHANNEL_B_OFFSET 0xE4
#define ERC32_MEC_UART_STATUS_OFFSET 0xE8
#endif
/*
* The following defines the bits in the Configuration Register.
*/
#define ERC32_CONFIGURATION_POWER_DOWN_MASK 0x00000001
#define ERC32_CONFIGURATION_POWER_DOWN_ALLOWED 0x00000001
#define ERC32_CONFIGURATION_POWER_DOWN_DISABLED 0x00000000
#define ERC32_CONFIGURATION_SOFTWARE_RESET_MASK 0x00000002
#define ERC32_CONFIGURATION_SOFTWARE_RESET_ALLOWED 0x00000002
#define ERC32_CONFIGURATION_SOFTWARE_RESET_DISABLED 0x00000000
#define ERC32_CONFIGURATION_BUS_TIMEOUT_MASK 0x00000004
#define ERC32_CONFIGURATION_BUS_TIMEOUT_ENABLED 0x00000004
#define ERC32_CONFIGURATION_BUS_TIMEOUT_DISABLED 0x00000000
#define ERC32_CONFIGURATION_ACCESS_PROTECTION_MASK 0x00000008
#define ERC32_CONFIGURATION_ACCESS_PROTECTION_ENABLED 0x00000008
#define ERC32_CONFIGURATION_ACCESS_PROTECTION_DISABLED 0x00000000
/*
* The following defines the bits in the Memory Configuration Register.
*/
#define ERC32_MEMORY_CONFIGURATION_RAM_SIZE_MASK 0x00001C00
#define ERC32_MEMORY_CONFIGURATION_RAM_SIZE_256K ( 0 << 10 )
#define ERC32_MEMORY_CONFIGURATION_RAM_SIZE_512K ( 1 << 10 )
#define ERC32_MEMORY_CONFIGURATION_RAM_SIZE_1MB ( 2 << 10 )
#define ERC32_MEMORY_CONFIGURATION_RAM_SIZE_2MB ( 3 << 10 )
#define ERC32_MEMORY_CONFIGURATION_RAM_SIZE_4MB ( 4 << 10 )
#define ERC32_MEMORY_CONFIGURATION_RAM_SIZE_8MB ( 5 << 10 )
#define ERC32_MEMORY_CONFIGURATION_RAM_SIZE_16MB ( 6 << 10 )
#define ERC32_MEMORY_CONFIGURATION_RAM_SIZE_32MB ( 7 << 10 )
#define ERC32_MEMORY_CONFIGURATION_PROM_SIZE_MASK 0x001C0000
#define ERC32_MEMORY_CONFIGURATION_PROM_SIZE_4K ( 0 << 18 )
#define ERC32_MEMORY_CONFIGURATION_PROM_SIZE_8K ( 1 << 18 )
#define ERC32_MEMORY_CONFIGURATION_PROM_SIZE_16K ( 2 << 18 )
#define ERC32_MEMORY_CONFIGURATION_PROM_SIZE_32K ( 3 << 18 )
#define ERC32_MEMORY_CONFIGURATION_PROM_SIZE_64K ( 4 << 18 )
#define ERC32_MEMORY_CONFIGURATION_PROM_SIZE_128K ( 5 << 18 )
#define ERC32_MEMORY_CONFIGURATION_PROM_SIZE_256K ( 6 << 18 )
#define ERC32_MEMORY_CONFIGURATION_PROM_SIZE_512K ( 7 << 18 )
/*
* The following defines the bits in the Timer Control Register.
*/
#define ERC32_MEC_TIMER_CONTROL_GCR 0x00000001 /* 1 = reload at 0 */
/* 0 = stop at 0 */
#define ERC32_MEC_TIMER_CONTROL_GCL 0x00000002 /* 1 = load and start */
/* 0 = no function */
#define ERC32_MEC_TIMER_CONTROL_GSE 0x00000004 /* 1 = enable counting */
/* 0 = hold scalar and counter */
#define ERC32_MEC_TIMER_CONTROL_GSL 0x00000008 /* 1 = load scalar and start */
/* 0 = no function */
#define ERC32_MEC_TIMER_CONTROL_RTCCR 0x00000100 /* 1 = reload at 0 */
/* 0 = stop at 0 */
#define ERC32_MEC_TIMER_CONTROL_RTCCL 0x00000200 /* 1 = load and start */
/* 0 = no function */
#define ERC32_MEC_TIMER_CONTROL_RTCSE 0x00000400 /* 1 = enable counting */
/* 0 = hold scalar and counter */
#define ERC32_MEC_TIMER_CONTROL_RTCSL 0x00000800 /* 1 = load scalar and start */
/* 0 = no function */
/*
* The following defines the bits in the UART Control Registers.
*
* NOTE: Same bits in UART channels A and B.
*/
#define ERC32_MEC_UART_CONTROL_RTD 0x000000FF /* RX/TX data */
#define ERC32_MEC_UART_CONTROL_DR 0x00000100 /* RX Data Ready */
#define ERC32_MEC_UART_CONTROL_TSE 0x00000200 /* TX Send Empty */
/* (i.e. no data to send) */
#define ERC32_MEC_UART_CONTROL_THE 0x00000400 /* TX Hold Empty */
/* (i.e. ready to load) */
/*
* The following defines the bits in the MEC UART Control Registers.
*/
#define ERC32_MEC_UART_STATUS_DR 0x00000001 /* Data Ready */
#define ERC32_MEC_UART_STATUS_TSE 0x00000002 /* TX Send Register Empty */
#define ERC32_MEC_UART_STATUS_THE 0x00000004 /* TX Hold Register Empty */
#define ERC32_MEC_UART_STATUS_FE 0x00000010 /* RX Framing Error */
#define ERC32_MEC_UART_STATUS_PE 0x00000020 /* RX Parity Error */
#define ERC32_MEC_UART_STATUS_OE 0x00000040 /* RX Overrun Error */
#define ERC32_MEC_UART_STATUS_CU 0x00000080 /* Clear Errors */
#define ERC32_MEC_UART_STATUS_TXE 0x00000006 /* TX Empty */
#define ERC32_MEC_UART_STATUS_DRA (ERC32_MEC_UART_STATUS_DR << 0)
#define ERC32_MEC_UART_STATUS_TSEA (ERC32_MEC_UART_STATUS_TSE << 0)
#define ERC32_MEC_UART_STATUS_THEA (ERC32_MEC_UART_STATUS_THE << 0)
#define ERC32_MEC_UART_STATUS_FEA (ERC32_MEC_UART_STATUS_FE << 0)
#define ERC32_MEC_UART_STATUS_PEA (ERC32_MEC_UART_STATUS_PE << 0)
#define ERC32_MEC_UART_STATUS_OEA (ERC32_MEC_UART_STATUS_OE << 0)
#define ERC32_MEC_UART_STATUS_CUA (ERC32_MEC_UART_STATUS_CU << 0)
#define ERC32_MEC_UART_STATUS_TXEA (ERC32_MEC_UART_STATUS_TXE << 0)
#define ERC32_MEC_UART_STATUS_DRB (ERC32_MEC_UART_STATUS_DR << 16)
#define ERC32_MEC_UART_STATUS_TSEB (ERC32_MEC_UART_STATUS_TSE << 16)
#define ERC32_MEC_UART_STATUS_THEB (ERC32_MEC_UART_STATUS_THE << 16)
#define ERC32_MEC_UART_STATUS_FEB (ERC32_MEC_UART_STATUS_FE << 16)
#define ERC32_MEC_UART_STATUS_PEB (ERC32_MEC_UART_STATUS_PE << 16)
#define ERC32_MEC_UART_STATUS_OEB (ERC32_MEC_UART_STATUS_OE << 16)
#define ERC32_MEC_UART_STATUS_CUB (ERC32_MEC_UART_STATUS_CU << 16)
#define ERC32_MEC_UART_STATUS_TXEB (ERC32_MEC_UART_STATUS_TXE << 16)
#ifndef ASM
/*
* This is used to manipulate the on-chip registers.
*
* The following symbol must be defined in the linkcmds file and point
* to the correct location.
*/
extern ERC32_Register_Map ERC32_MEC;
/*
* Macros to manipulate the Interrupt Clear, Interrupt Force, Interrupt Mask,
* and the Interrupt Pending Registers.
*
* NOTE: For operations which are not atomic, this code disables interrupts
* to guarantee there are no intervening accesses to the same register.
* The operations which read the register, modify the value and then
* store the result back are vulnerable.
*/
#define ERC32_Clear_interrupt( _source ) \
do { \
ERC32_MEC.Interrupt_Clear = (1 << (_source)); \
} while (0)
#define ERC32_Force_interrupt( _source ) \
do { \
ERC32_MEC.Interrupt_Force = (1 << (_source)); \
} while (0)
#define ERC32_Is_interrupt_pending( _source ) \
(ERC32_MEC.Interrupt_Pending & (1 << (_source)))
#define ERC32_Is_interrupt_masked( _source ) \
(ERC32_MEC.Interrupt_Masked & (1 << (_source)))
#define ERC32_Mask_interrupt( _source ) \
do { \
unsigned32 _level; \
\
sparc_disable_interrupts( _level ); \
ERC32_MEC.Interrupt_Mask |= (1 << (_source)); \
sparc_enable_interrupts( _level ); \
} while (0)
#define ERC32_Unmask_interrupt( _source ) \
do { \
unsigned32 _level; \
\
sparc_disable_interrupts( _level ); \
ERC32_MEC.Interrupt_Mask &= ~(1 << (_source)); \
sparc_enable_interrupts( _level ); \
} while (0)
#define ERC32_Disable_interrupt( _source, _previous ) \
do { \
unsigned32 _level; \
unsigned32 _mask = 1 << (_source); \
\
sparc_disable_interrupts( _level ); \
(_previous) = ERC32_MEC.Interrupt_Mask; \
ERC32_MEC.Interrupt_Mask = _previous | _mask; \
sparc_enable_interrupts( _level ); \
(_previous) &= ~_mask; \
} while (0)
#define ERC32_Restore_interrupt( _source, _previous ) \
do { \
unsigned32 _level; \
unsigned32 _mask = 1 << (_source); \
\
sparc_disable_interrupts( _level ); \
ERC32_MEC.Interrupt_Mask = \
(ERC32_MEC.Interrupt_Mask & ~_mask) | (_previous); \
sparc_enable_interrupts( _level ); \
} while (0)
/*
* The following macros attempt to hide the fact that the General Purpose
* Timer and Real Time Clock Timer share the Timer Control Register. Because
* the Timer Control Register is write only, we must mirror it in software
* and insure that writes to one timer do not alter the current settings
* and status of the other timer.
*
* This code promotes the view that the two timers are completely independent.
* By exclusively using the routines below to access the Timer Control
* Register, the application can view the system as having a General Purpose
* Timer Control Register and a Real Time Clock Timer Control Register
* rather than the single shared value.
*
* Each logical timer control register is organized as follows:
*
* D0 - Counter Reload
* 1 = reload counter at zero and restart
* 0 = stop counter at zero
*
* D1 - Counter Load
* 1 = load counter with preset value and restart
* 0 = no function
*
* D2 - Enable
* 1 = enable counting
* 0 = hold scaler and counter
*
* D2 - Scaler Load
* 1 = load scalar with preset value and restart
* 0 = no function
*
* To insure the management of the mirror is atomic, we disable interrupts
* around updates.
*/
#define ERC32_MEC_TIMER_COUNTER_RELOAD_AT_ZERO 0x00000001
#define ERC32_MEC_TIMER_COUNTER_STOP_AT_ZERO 0x00000000
#define ERC32_MEC_TIMER_COUNTER_LOAD_COUNTER 0x00000002
#define ERC32_MEC_TIMER_COUNTER_ENABLE_COUNTING 0x00000004
#define ERC32_MEC_TIMER_COUNTER_DISABLE_COUNTING 0x00000000
#define ERC32_MEC_TIMER_COUNTER_LOAD_SCALER 0x00000008
#define ERC32_MEC_TIMER_COUNTER_RELOAD_MASK 0x00000001
#define ERC32_MEC_TIMER_COUNTER_ENABLE_MASK 0x00000004
#define ERC32_MEC_TIMER_COUNTER_DEFINED_MASK 0x0000000F
#define ERC32_MEC_TIMER_COUNTER_CURRENT_MODE_MASK 0x00000005
extern unsigned32 _ERC32_MEC_Timer_Control_Mirror;
/*
* This macros manipulate the General Purpose Timer portion of the
* Timer Control register and promote the view that there are actually
* two independent Timer Control Registers.
*/
#define ERC32_MEC_Set_General_Purpose_Timer_Control( _value ) \
do { \
unsigned32 _level; \
unsigned32 _control; \
unsigned32 __value; \
\
__value = ((_value) & 0x0f); \
sparc_disable_interrupts( _level ); \
_control = _ERC32_MEC_Timer_Control_Mirror; \
_control &= ERC32_MEC_TIMER_COUNTER_DEFINED_MASK << 8; \
_ERC32_MEC_Timer_Control_Mirror = _control | _value; \
_control &= (ERC32_MEC_TIMER_COUNTER_CURRENT_MODE_MASK << 8); \
_control |= __value; \
/* printf( "GPT 0x%x 0x%x 0x%x\n", _value, __value, _control ); */ \
ERC32_MEC.Timer_Control = _control; \
sparc_enable_interrupts( _level ); \
} while ( 0 )
#define ERC32_MEC_Get_General_Purpose_Timer_Control( _value ) \
do { \
(_value) = _ERC32_MEC_Timer_Control_Mirror & 0xf; \
} while ( 0 )
/*
* This macros manipulate the Real Timer Clock Timer portion of the
* Timer Control register and promote the view that there are actually
* two independent Timer Control Registers.
*/
#define ERC32_MEC_Set_Real_Time_Clock_Timer_Control( _value ) \
do { \
unsigned32 _level; \
unsigned32 _control; \
unsigned32 __value; \
\
__value = ((_value) & 0x0f) << 8; \
sparc_disable_interrupts( _level ); \
_control = _ERC32_MEC_Timer_Control_Mirror; \
_control &= ERC32_MEC_TIMER_COUNTER_DEFINED_MASK; \
_ERC32_MEC_Timer_Control_Mirror = _control | _value; \
_control &= ERC32_MEC_TIMER_COUNTER_CURRENT_MODE_MASK; \
_control |= __value; \
/* printf( "RTC 0x%x 0x%x 0x%x\n", _value, __value, _control ); */ \
ERC32_MEC.Timer_Control = _control; \
sparc_enable_interrupts( _level ); \
} while ( 0 )
#define ERC32_MEC_Get_Real_Time_Clock_Timer_Control( _value ) \
do { \
(_value) = _ERC32_MEC_Timer_Control_Mirror & 0xf; \
} while ( 0 )
#endif /* !ASM */
#ifdef __cplusplus
}
#endif
#endif /* !_INCLUDE_ERC32_h */
/* end of include file */

View File

@@ -30,8 +30,8 @@ rtems_task Task_1(
rtems_mode previous_mode;
rtems_time_of_day time;
rtems_status_code status;
rtems_unsigned32 start;
rtems_unsigned32 end;
rtems_unsigned32 start_time;
rtems_unsigned32 end_time;
puts( "TA1 - rtems_task_suspend - on Task 2" );
status = rtems_task_suspend( Task_id[ 2 ] );
@@ -41,16 +41,16 @@ rtems_task Task_1(
status = rtems_task_suspend( Task_id[ 3 ] );
directive_failed( status, "rtems_task_suspend of TA3" );
status = rtems_clock_get( RTEMS_CLOCK_GET_SECONDS_SINCE_EPOCH, &start );
status = rtems_clock_get( RTEMS_CLOCK_GET_SECONDS_SINCE_EPOCH, &start_time );
directive_failed( status, "rtems_clock_get" );
puts( "TA1 - killing time" );
for ( ; ; ) {
status = rtems_clock_get( RTEMS_CLOCK_GET_SECONDS_SINCE_EPOCH, &end );
status = rtems_clock_get( RTEMS_CLOCK_GET_SECONDS_SINCE_EPOCH, &end_time );
directive_failed( status, "rtems_clock_get" );
if ( end > (start + 2) )
if ( end_time > (start_time + 2) )
break;
}

View File

@@ -25,7 +25,11 @@ void Screen9()
rtems_status_code status;
rtems_isr_entry old_service_routine;
status = rtems_interrupt_catch( Service_routine, 500, &old_service_routine );
status = rtems_interrupt_catch(
Service_routine,
ISR_INTERRUPT_MAXIMUM_VECTOR_NUMBER + 10,
&old_service_routine
);
fatal_directive_status(
status,
RTEMS_INVALID_NUMBER,

View File

@@ -11,7 +11,7 @@ TA1 - rtems_event_receive - waiting with 10 second timeout on RTEMS_EVENT_14
TA2 - RTEMS_EVENT_17 or RTEMS_EVENT_18 received - eventout => 00040000
TA2 - rtems_event_send - send RTEMS_EVENT_14 to TA1
TA2 - rtems_clock_set - 08:15:00 02/12/1988
TA2 - rtems_event_send - sending RTEMS_EVENT_10 to self after 5 seconds
TA2 - rtems_event_send - sending RTEMS_EVENT_10 to self after 4 seconds
TA2 - rtems_event_receive - waiting forever on RTEMS_EVENT_10
TA1 - RTEMS_EVENT_14 received - eventout => 00004000
TA1 - rtems_event_send - send RTEMS_EVENT_19 to TA2

View File

@@ -73,9 +73,9 @@ rtems_task Task_2(
status = rtems_clock_set( &time );
directive_failed( status, "TA2 rtems_clock_set" );
time.second += 5;
time.second += 4;
puts(
"TA2 - rtems_event_send - sending RTEMS_EVENT_10 to self after 5 seconds"
"TA2 - rtems_event_send - sending RTEMS_EVENT_10 to self after 4 seconds"
);
status = rtems_timer_fire_when(
Timer_id[ 5 ],
@@ -83,7 +83,7 @@ rtems_task Task_2(
TA2_send_10_to_self,
NULL
);
directive_failed( status, "rtems_timer_fire_when after 5 seconds" );
directive_failed( status, "rtems_timer_fire_when after 4 seconds" );
puts( "TA2 - rtems_event_receive - waiting forever on RTEMS_EVENT_10" );
status = rtems_event_receive(

View File

@@ -57,6 +57,7 @@ rtems_task Task5(
#define CONFIGURE_TEST_NEEDS_CONSOLE_DRIVER
#define CONFIGURE_TEST_NEEDS_CLOCK_DRIVER
#define CONFIGURE_INIT_TASK_STACK_SIZE (RTEMS_MINIMUM_STACK_SIZE * 2)
#define CONFIGURE_MAXIMUM_SEMAPHORES 10
#define CONFIGURE_TICKS_PER_TIMESLICE 100

View File

@@ -38,6 +38,8 @@ rtems_task Task_1(
#define CONFIGURE_SPTEST
#define CONFIGURE_INIT_TASK_ATTRIBUTES RTEMS_FLOATING_POINT
#define CONFIGURE_TEST_NEEDS_CONSOLE_DRIVER
#define CONFIGURE_TEST_NEEDS_CLOCK_DRIVER

View File

@@ -44,7 +44,7 @@ rtems_task Init(
status = rtems_task_create(
Task_name[ index ],
Priorities[ index ],
RTEMS_MINIMUM_STACK_SIZE,
RTEMS_MINIMUM_STACK_SIZE * 4,
RTEMS_DEFAULT_MODES,
RTEMS_DEFAULT_ATTRIBUTES,
&Task_id[ index ]

View File

@@ -52,7 +52,7 @@ rtems_task Init(
status = rtems_task_create(
Task_name[ index ],
1,
RTEMS_MINIMUM_STACK_SIZE,
RTEMS_MINIMUM_STACK_SIZE * 2,
RTEMS_DEFAULT_MODES,
RTEMS_DEFAULT_ATTRIBUTES,
&Task_id[ index ]

View File

@@ -36,8 +36,12 @@ rtems_task Init(
setvbuf(stdout, 0, _IONBF, 0);
puts( "\n*** RTEMS SIZE PROGRAM ***" );
size_rtems( 1 );
puts( "*** END OF RTEMS SIZE PROGRAM ***" );
exit( 0 );
#if 0
do {
puts( "\n*** RTEMS SIZE PROGRAM ***" );
printf( "\n\nPlease select program mode:\n" );
printf( " 1) Print Formulas\n" );
printf( " 2) Determine Workspace Size\n" );
@@ -52,4 +56,5 @@ rtems_task Init(
default: continue;
}
} while ( FOREVER );
#endif
}

View File

@@ -390,6 +390,22 @@ uninitialized += (sizeof _CPU_Interrupt_stack_low) +
#endif
#ifdef sparc
/* cpu.h */
uninitialized += (sizeof _CPU_Interrupt_stack_low) +
(sizeof _CPU_Interrupt_stack_high) +
(sizeof _CPU_Null_fp_context) +
(sizeof _CPU_Trap_Table_area);
#ifdef erc32
uninitialized += (sizeof _ERC32_MEC_Timer_Control_Mirror);
#endif
#endif
#ifdef no_cpu
/* cpu.h */
@@ -421,13 +437,16 @@ initialized +=
(sizeof _TOD_Days_to_date) +
(sizeof _TOD_Days_since_last_leap_year);
#ifdef sparc
initialized += (sizeof _CPU_Trap_slot_template);
#endif
puts( "" );
#ifdef i960CA
print_formula();
#else
if ( mode == 0 ) help_size();
else print_formula();
#endif
printf( "\n" );
printf( "RTEMS uninitialized data consumes %d bytes\n", uninitialized );

View File

@@ -198,7 +198,7 @@ rtems_task test_task(
end_time = Read_timer();
put_time(
"rtems_task_set_note",
"rtems_task_get_note",
end_time,
OPERATION_COUNT,
overhead,

View File

@@ -11,6 +11,12 @@
* $Id$
*/
/*
* WARNING!!!!!!!!!
*
* THIS TEST USES INTERNAL RTEMS VARIABLES!!!
*/
#define TEST_INIT
#include "system.h"
@@ -33,15 +39,6 @@ rtems_isr Isr_handler(
rtems_vector_number vector
);
/*
* INTERNAL RTEMS VARIABLES!!!
*/
extern rtems_unsigned32 _Thread_Dispatch_disable_level;
extern rtems_unsigned32 _Context_Switch_necessary;
extern Chain_Control *_Thread_Ready_chain;
extern rtems_tcb *_Thread_Heir;
rtems_task Init(
rtems_task_argument argument
)
@@ -169,9 +166,23 @@ rtems_task Task_1(
Interrupt_occurred = 0;
Timer_initialize();
Cause_tm27_intr();
/* goes to Isr_handler */
/*
* goes to Isr_handler and then returns
*/
puts( "*** END OF TEST 27 ***" );
exit( 0 );
}
/*
* NOTE: When this task is executing, some of the assumptions made
* regarding the placement of the currently executing task's TCB
* on the ready chains have been violated. At least the assumption
* that this task is at the head of the chain for its priority
* has been violated.
*/
rtems_task Task_2(
rtems_task_argument argument
)
@@ -197,8 +208,20 @@ rtems_task Task_2(
0
);
puts( "*** END OF TEST 27 ***" );
exit( 0 );
fflush( stdout );
/*
* Switch back to the other task to exit the test.
*/
_Thread_Dispatch_disable_level = 0;
_Thread_Heir = (rtems_tcb *) _Thread_Ready_chain[254].first;
_Context_Switch_necessary = 1;
_Thread_Dispatch();
}
/* The Isr_handler() and Isr_handler_inner() routines are structured

View File

@@ -10,13 +10,13 @@
#define __RINGBUF_H__
#ifndef RINGBUF_QUEUE_LENGTH
#define RINGBUF_QUEUE_LENGTH 200
#define RINGBUF_QUEUE_LENGTH 128
#endif
typedef struct {
char buffer[RINGBUF_QUEUE_LENGTH];
int head;
int tail;
volatile int head;
volatile int tail;
} Ring_buffer_t;
#define Ring_buffer_Initialize( _buffer ) \
@@ -27,16 +27,27 @@ typedef struct {
#define Ring_buffer_Is_empty( _buffer ) \
( (_buffer)->head == (_buffer)->tail )
#define Ring_buffer_Is_full( _buffer ) \
( (_buffer)->head == ((_buffer)->tail + 1) % RINGBUF_QUEUE_LENGTH )
#define Ring_buffer_Add_character( _buffer, _ch ) \
do { \
(_buffer)->buffer[ (_buffer)->tail ] = (_ch); \
(_buffer)->tail = ((_buffer)->tail+1) % RINGBUF_QUEUE_LENGTH; \
rtems_unsigned32 isrlevel; \
\
rtems_interrupt_disable( isrlevel ); \
(_buffer)->tail = ((_buffer)->tail+1) % RINGBUF_QUEUE_LENGTH; \
(_buffer)->buffer[ (_buffer)->tail ] = (_ch); \
rtems_interrupt_enable( isrlevel ); \
} while ( 0 )
#define Ring_buffer_Remove_character( _buffer, _ch ) \
do { \
(_ch) = (_buffer)->buffer[ (_buffer)->head ]; \
(_buffer)->head = ((_buffer)->head+1) % RINGBUF_QUEUE_LENGTH; \
rtems_unsigned32 isrlevel; \
\
rtems_interrupt_disable( isrlevel ); \
(_buffer)->head = ((_buffer)->head+1) % RINGBUF_QUEUE_LENGTH; \
(_ch) = (_buffer)->buffer[ (_buffer)->head ]; \
rtems_interrupt_enable( isrlevel ); \
} while ( 0 )
#endif

View File

@@ -60,8 +60,7 @@ EXTERN Objects_Information _POSIX_Interrupt_Handlers_Information;
* interrupt handlers installed on each vector.
*/
EXTERN POSIX_Interrupt_Control
_POSIX_Interrupt_Information[ ISR_NUMBER_OF_VECTORS ];
EXTERN POSIX_Interrupt_Control _POSIX_Interrupt_Information[ ISR_NUMBER_OF_VECTORS ];
/*
* _POSIX_Interrupt_Manager_initialization

View File

@@ -108,3 +108,205 @@ rtems_status_code rtems_event_receive(
_Thread_Enable_dispatch();
return( _Thread_Executing->Wait.return_code );
}
/*PAGE
*
* _Event_Seize
*
* This routine attempts to satisfy the requested event condition
* for the running thread.
*
* Input parameters:
* event_in - the event condition to satisfy
* option_set - acquire event options
* ticks - interval to wait
* event_out - pointer to event set output area
*
* Output parameters: NONE
* *event_out - event set output area filled in
*
* INTERRUPT LATENCY:
* available
* wait
* check sync
*/
void _Event_Seize(
rtems_event_set event_in,
rtems_option option_set,
rtems_interval ticks,
rtems_event_set *event_out
)
{
Thread_Control *executing;
rtems_event_set seized_events;
rtems_event_set pending_events;
ISR_Level level;
RTEMS_API_Control *api;
executing = _Thread_Executing;
executing->Wait.return_code = RTEMS_SUCCESSFUL;
api = executing->API_Extensions[ THREAD_API_RTEMS ];
_ISR_Disable( level );
pending_events = api->pending_events;
seized_events = _Event_sets_Get( pending_events, event_in );
if ( !_Event_sets_Is_empty( seized_events ) &&
(seized_events == event_in || _Options_Is_any( option_set )) ) {
api->pending_events =
_Event_sets_Clear( pending_events, seized_events );
_ISR_Enable( level );
*event_out = seized_events;
return;
}
if ( _Options_Is_no_wait( option_set ) ) {
_ISR_Enable( level );
executing->Wait.return_code = RTEMS_UNSATISFIED;
*event_out = seized_events;
return;
}
_Event_Sync = TRUE;
executing->Wait.option = (unsigned32) option_set;
executing->Wait.count = (unsigned32) event_in;
executing->Wait.return_argument = event_out;
_ISR_Enable( level );
_Thread_Set_state( executing, STATES_WAITING_FOR_EVENT );
if ( ticks ) {
_Watchdog_Initialize(
&executing->Timer,
_Event_Timeout,
executing->Object.id,
NULL
);
_Watchdog_Insert_ticks(
&executing->Timer,
ticks,
WATCHDOG_NO_ACTIVATE
);
}
_ISR_Disable( level );
if ( _Event_Sync == TRUE ) {
_Event_Sync = FALSE;
if ( ticks )
_Watchdog_Activate( &executing->Timer );
_ISR_Enable( level );
return;
}
_ISR_Enable( level );
(void) _Watchdog_Remove( &executing->Timer );
_Thread_Unblock( executing );
return;
}
/*PAGE
*
* _Event_Surrender
*
* This routines remove a thread from the specified threadq.
*
* Input parameters:
* the_thread - pointer to thread to be dequeued
*
* Output parameters: NONE
*
* INTERRUPT LATENCY:
* before flash
* after flash
* check sync
*/
void _Event_Surrender(
Thread_Control *the_thread
)
{
ISR_Level level;
rtems_event_set pending_events;
rtems_event_set event_condition;
rtems_event_set seized_events;
rtems_option option_set;
RTEMS_API_Control *api;
api = the_thread->API_Extensions[ THREAD_API_RTEMS ];
option_set = (rtems_option) the_thread->Wait.option;
_ISR_Disable( level );
pending_events = api->pending_events;
event_condition = (rtems_event_set) the_thread->Wait.count;
seized_events = _Event_sets_Get( pending_events, event_condition );
if ( !_Event_sets_Is_empty( seized_events ) ) {
if ( _States_Is_waiting_for_event( the_thread->current_state ) ) {
if ( seized_events == event_condition || _Options_Is_any( option_set ) ) {
api->pending_events =
_Event_sets_Clear( pending_events, seized_events );
*(rtems_event_set *)the_thread->Wait.return_argument = seized_events;
_ISR_Flash( level );
if ( !_Watchdog_Is_active( &the_thread->Timer ) ) {
_ISR_Enable( level );
_Thread_Unblock( the_thread );
}
else {
_Watchdog_Deactivate( &the_thread->Timer );
_ISR_Enable( level );
(void) _Watchdog_Remove( &the_thread->Timer );
_Thread_Unblock( the_thread );
}
return;
}
}
else if ( _Thread_Is_executing( the_thread ) && _Event_Sync == TRUE ) {
if ( seized_events == event_condition || _Options_Is_any( option_set ) ) {
api->pending_events = _Event_sets_Clear( pending_events,seized_events );
*(rtems_event_set *)the_thread->Wait.return_argument = seized_events;
_Event_Sync = FALSE;
}
}
}
_ISR_Enable( level );
}
/*PAGE
*
* _Event_Timeout
*
* This routine processes a thread which timeouts while waiting to
* receive an event_set. It is called by the watchdog handler.
*
* Input parameters:
* id - thread id
*
* Output parameters: NONE
*/
void _Event_Timeout(
Objects_Id id,
void *ignored
)
{
Thread_Control *the_thread;
Objects_Locations location;
the_thread = _Thread_Get( id, &location );
switch ( location ) {
case OBJECTS_ERROR:
case OBJECTS_REMOTE: /* impossible */
break;
case OBJECTS_LOCAL:
the_thread->Wait.return_code = RTEMS_TIMEOUT;
_Thread_Unblock( the_thread );
_Thread_Unnest_dispatch();
break;
}
}

View File

@@ -0,0 +1,118 @@
#
# $Id$
#
This file discusses SPARC specific issues which are important to
this port. The primary topics in this file are:
+ Global Register Usage
+ Stack Frame
+ EF bit in the PSR
Global Register Usage
=====================
This information on register usage is based heavily on a comment in the
file gcc-2.7.0/config/sparc/sparc.h in the the gcc 2.7.0 source.
+ g0 is hardwired to 0
+ On non-v9 systems:
- g1 is free to use as temporary.
- g2-g4 are reserved for applications. Gcc normally uses them as
temporaries, but this can be disabled via the -mno-app-regs option.
- g5 through g7 are reserved for the operating system.
+ On v9 systems:
- g1 and g5 are free to use as temporaries.
- g2-g4 are reserved for applications (the compiler will not normally use
them, but they can be used as temporaries with -mapp-regs).
- g6-g7 are reserved for the operating system.
NOTE: As of gcc 2.7.0 register g1 was used in the following scenarios:
+ as a temporary by the 64 bit sethi pattern
+ when restoring call-preserved registers in large stack frames
RTEMS places no constraints on the usage of the global registers. Although
gcc assumes that either g5-g7 (non-V9) or g6-g7 (V9) are reserved for the
operating system, RTEMS does not assume any special use for them.
Stack Frame
===========
The stack grows downward (i.e. to lower addresses) on the SPARC architecture.
The following is the organization of the stack frame:
| ............... |
fp | |
+-------------------------------+
| |
| Local registers, temporaries, |
| and saved floats | x bytes
| |
sp + x +-------------------------------+
| |
| outgoing parameters past |
| the sixth one | x bytes
| |
sp + 92 +-------------------------------+ *
| | *
| area for callee to save | *
| register arguments | * 24 bytes
| | *
sp + 68 +-------------------------------+ *
| | *
| structure return pointer | * 4 bytes
| | *
sp + 64 +-------------------------------+ *
| | *
| local register set | * 32 bytes
| | *
sp + 32 +-------------------------------+ *
| | *
| input register set | * 32 bytes
| | *
sp +-------------------------------+ *
* = minimal stack frame
x = optional components
EF bit in the PSR
=================
The EF (enable floating point unit) in the PSR is utilized in this port to
prevent non-floating point tasks from performing floating point
operations. This bit is maintained as part of the integer context.
However, the floating point context is switched BEFORE the integer
context. Thus the EF bit in place at the time of the FP switch may
indicate that FP operations are disabled. This occurs on certain task
switches, when the EF bit will be 0 for the outgoing task and thus a fault
will be generated on the first FP operation of the FP context save.
The remedy for this is to enable FP access as the first step in both the
save and restore of the FP context area. This bit will be subsequently
reloaded by the integer context switch.
Two of the scenarios which demonstrate this problem are outlined below:
1. When the first FP task is switched to. The system tasks are not FP and
thus would be unable to restore the FP context of the incoming task.
2. On a deferred FP context switch. In this case, the system might switch
from FP Task A to non-FP Task B and then to FP Task C. In this scenario,
the floating point state must technically be saved by a non-FP task.

View File

@@ -28,7 +28,9 @@
*/
#define ASM
#include <rtems/score/sparc.h>
#include <rtems/score/cpu.h>
/*
* Recent versions of GNU cpp define variables which indicate the
@@ -37,7 +39,9 @@
* have to define these as appropriate.
*/
/* XXX This does not appear to work on gcc 2.7.0 on the sparc */
/* XXX __USER_LABEL_PREFIX__ and __REGISTER_PREFIX__ do not work on gcc 2.7.0 */
/* XXX The following ifdef magic fixes the problem but results in a warning */
/* XXX when compiling assembly code. */
#undef __USER_LABEL_PREFIX__
#ifndef __USER_LABEL_PREFIX__
#define __USER_LABEL_PREFIX__ _
@@ -91,6 +95,16 @@
#define PUBLIC(sym) .globl SYM (sym)
#define EXTERN(sym) .globl SYM (sym)
/*
* Entry for traps which jump to a programmer-specified trap handler.
*/
#define TRAP(_vector, _handler) \
mov %psr, %l0 ; \
sethi %hi(_handler), %l4 ; \
jmp %l4+%lo(_handler); \
mov _vector, %l3
#endif
/* end of include file */

View File

@@ -7,52 +7,115 @@
#include <rtems/system.h>
#include <rtems/score/isr.h>
/* _CPU_Initialize
#if defined(erc32)
#include <erc32.h>
#endif
/*
* This initializes the set of opcodes placed in each trap
* table entry. The routine which installs a handler is responsible
* for filling in the fields for the _handler address and the _vector
* trap type.
*
* The constants following this structure are masks for the fields which
* must be filled in when the handler is installed.
*/
const CPU_Trap_table_entry _CPU_Trap_slot_template = {
0xa1480000, /* mov %psr, %l0 */
0x29000000, /* sethi %hi(_handler), %l4 */
0x81c52000, /* jmp %l4 + %lo(_handler) */
0xa6102000 /* mov _vector, %l3 */
};
/*PAGE
*
* _CPU_Initialize
*
* This routine performs processor dependent initialization.
*
* INPUT PARAMETERS:
* Input Parameters:
* cpu_table - CPU table to initialize
* thread_dispatch - address of disptaching routine
*
* Output Parameters: NONE
*
* NOTE: There is no need to save the pointer to the thread dispatch routine.
* The SPARC's assembly code can reference it directly with no problems.
*/
void _CPU_Initialize(
rtems_cpu_table *cpu_table,
void (*thread_dispatch) /* ignored on this CPU */
void (*thread_dispatch) /* ignored on this CPU */
)
{
void *pointer;
void *pointer;
unsigned32 trap_table_start;
unsigned32 tbr_value;
CPU_Trap_table_entry *old_tbr;
CPU_Trap_table_entry *trap_table;
/*
* The thread_dispatch argument is the address of the entry point
* for the routine called at the end of an ISR once it has been
* decided a context switch is necessary. On some compilation
* systems it is difficult to call a high-level language routine
* from assembly. This allows us to trick these systems.
*
* If you encounter this problem save the entry point in a CPU
* dependent variable.
* Install the executive's trap table. All entries from the original
* trap table are copied into the executive's trap table. This is essential
* since this preserves critical trap handlers such as the window underflow
* and overflow handlers. It is the responsibility of the BSP to provide
* install these in the initial trap table.
*/
trap_table_start = (unsigned32) &_CPU_Trap_Table_area;
if (trap_table_start & (SPARC_TRAP_TABLE_ALIGNMENT-1))
trap_table_start = (trap_table_start + SPARC_TRAP_TABLE_ALIGNMENT) &
~(SPARC_TRAP_TABLE_ALIGNMENT-1);
_CPU_Thread_dispatch_pointer = thread_dispatch;
trap_table = (CPU_Trap_table_entry *) trap_table_start;
sparc_get_tbr( tbr_value );
old_tbr = (CPU_Trap_table_entry *) (tbr_value & 0xfffff000);
memcpy( trap_table, (void *) old_tbr, 256 * sizeof( CPU_Trap_table_entry ) );
sparc_set_tbr( trap_table_start );
/*
* If there is not an easy way to initialize the FP context
* during Context_Initialize, then it is usually easier to
* save an "uninitialized" FP context here and copy it to
* the task's during Context_Initialize.
* This seems to be the most appropriate way to obtain an initial
* FP context on the SPARC. The NULL fp context is copied it to
* the task's FP context during Context_Initialize.
*/
pointer = &_CPU_Null_fp_context;
_CPU_Context_save_fp( &pointer );
/*
* Grab our own copy of the user's CPU table.
*/
_CPU_Table = *cpu_table;
#if defined(erc32)
/*
* ERC32 specific initialization
*/
_ERC32_MEC_Timer_Control_Mirror = 0;
ERC32_MEC.Timer_Control = 0;
ERC32_MEC.Control |= ERC32_CONFIGURATION_POWER_DOWN_ALLOWED;
#endif
}
/*PAGE
*
* _CPU_ISR_Get_level
*
* Input Parameters: NONE
*
* Output Parameters:
* returns the current interrupt level (PIL field of the PSR)
*/
unsigned32 _CPU_ISR_Get_level( void )
@@ -64,134 +127,263 @@ unsigned32 _CPU_ISR_Get_level( void )
return level;
}
/* _CPU_ISR_install_vector
/*PAGE
*
* _CPU_ISR_install_raw_handler
*
* This routine installs the specified handler as a "raw" non-executive
* supported trap handler (a.k.a. interrupt service routine).
*
* Input Parameters:
* vector - trap table entry number plus synchronous
* vs. asynchronous information
* new_handler - address of the handler to be installed
* old_handler - pointer to an address of the handler previously installed
*
* Output Parameters: NONE
* *new_handler - address of the handler previously installed
*
* NOTE:
*
* On the SPARC, there are really only 256 vectors. However, the executive
* has no easy, fast, reliable way to determine which traps are synchronous
* and which are asynchronous. By default, synchronous traps return to the
* instruction which caused the interrupt. So if you install a software
* trap handler as an executive interrupt handler (which is desirable since
* RTEMS takes care of window and register issues), then the executive needs
* to know that the return address is to the trap rather than the instruction
* following the trap.
*
* So vectors 0 through 255 are treated as regular asynchronous traps which
* provide the "correct" return address. Vectors 256 through 512 are assumed
* by the executive to be synchronous and to require that the return address
* be fudged.
*
* If you use this mechanism to install a trap handler which must reexecute
* the instruction which caused the trap, then it should be installed as
* an asynchronous trap. This will avoid the executive changing the return
* address.
*/
void _CPU_ISR_install_raw_handler(
unsigned32 vector,
proc_ptr new_handler,
proc_ptr *old_handler
)
{
unsigned32 real_vector;
CPU_Trap_table_entry *tbr;
CPU_Trap_table_entry *slot;
unsigned32 u32_tbr;
unsigned32 u32_handler;
/*
* Get the "real" trap number for this vector ignoring the synchronous
* versus asynchronous indicator included with our vector numbers.
*/
real_vector = SPARC_REAL_TRAP_NUMBER( vector );
/*
* Get the current base address of the trap table and calculate a pointer
* to the slot we are interested in.
*/
sparc_get_tbr( u32_tbr );
u32_tbr &= 0xfffff000;
tbr = (CPU_Trap_table_entry *) u32_tbr;
slot = &tbr[ real_vector ];
/*
* Get the address of the old_handler from the trap table.
*
* NOTE: The old_handler returned will be bogus if it does not follow
* the RTEMS model.
*/
#define HIGH_BITS_MASK 0xFFFFFC00
#define HIGH_BITS_SHIFT 10
#define LOW_BITS_MASK 0x000003FF
if ( slot->mov_psr_l0 == _CPU_Trap_slot_template.mov_psr_l0 ) {
u32_handler =
((slot->sethi_of_handler_to_l4 & HIGH_BITS_MASK) << HIGH_BITS_SHIFT) |
(slot->jmp_to_low_of_handler_plus_l4 & LOW_BITS_MASK);
*old_handler = (proc_ptr) u32_handler;
} else
*old_handler = 0;
/*
* Copy the template to the slot and then fix it.
*/
*slot = _CPU_Trap_slot_template;
u32_handler = (unsigned32) new_handler;
slot->mov_vector_l3 |= vector;
slot->sethi_of_handler_to_l4 |=
(u32_handler & HIGH_BITS_MASK) >> HIGH_BITS_SHIFT;
slot->jmp_to_low_of_handler_plus_l4 |= (u32_handler & LOW_BITS_MASK);
}
/*PAGE
*
* _CPU_ISR_install_vector
*
* This kernel routine installs the RTEMS handler for the
* specified vector.
*
* Input parameters:
* vector - interrupt vector number
* old_handler - former ISR for this vector number
* new_handler - replacement ISR for this vector number
* vector - interrupt vector number
* new_handler - replacement ISR for this vector number
* old_handler - pointer to former ISR for this vector number
*
* Output parameters: NONE
* Output parameters:
* *old_handler - former ISR for this vector number
*
*/
void _CPU_ISR_install_vector(
unsigned32 vector,
proc_ptr new_handler,
proc_ptr *old_handler
)
{
*old_handler = _ISR_Vector_table[ vector ];
unsigned32 real_vector;
proc_ptr ignored;
/*
* Get the "real" trap number for this vector ignoring the synchronous
* versus asynchronous indicator included with our vector numbers.
*/
real_vector = SPARC_REAL_TRAP_NUMBER( vector );
/*
* If the interrupt vector table is a table of pointer to isr entry
* points, then we need to install the appropriate RTEMS interrupt
* handler for this vector number.
* Return the previous ISR handler.
*/
*old_handler = _ISR_Vector_table[ real_vector ];
/*
* Install the wrapper so this ISR can be invoked properly.
*/
_CPU_ISR_install_raw_handler( vector, _ISR_Handler, &ignored );
/*
* We put the actual user ISR address in '_ISR_vector_table'. This will
* be used by the _ISR_Handler so the user gets control.
*/
_ISR_Vector_table[ vector ] = new_handler;
}
/*PAGE
*
* _CPU_Install_interrupt_stack
*/
void _CPU_Install_interrupt_stack( void )
{
_ISR_Vector_table[ real_vector ] = new_handler;
}
/*PAGE
*
* _CPU_Context_Initialize
*
* This kernel routine initializes the basic non-FP context area associated
* with each thread.
*
* Input parameters:
* the_context - pointer to the context area
* stack_base - address of memory for the SPARC
* size - size in bytes of the stack area
* new_level - interrupt level for this context area
* entry_point - the starting execution point for this this context
* is_fp - TRUE if this context is associated with an FP thread
*
* Output parameters: NONE
*/
/*
* The following constants assist in building a thread's initial context.
*/
#define CPU_FRAME_SIZE (112) /* based on disassembled test code */
#define ADDR_ADJ_OFFSET -8
void _CPU_Context_Initialize(
Context_Control *_the_context,
unsigned32 *_stack_base,
unsigned32 _size,
unsigned32 _new_level,
void *_entry_point
Context_Control *the_context,
unsigned32 *stack_base,
unsigned32 size,
unsigned32 new_level,
void *entry_point,
boolean is_fp
)
{
unsigned32 jmp_addr;
unsigned32 _stack_high; /* highest "stack aligned" address */
unsigned32 _the_size;
unsigned32 stack_high; /* highest "stack aligned" address */
unsigned32 the_size;
unsigned32 tmp_psr;
jmp_addr = (unsigned32) _entry_point;
/*
* On CPUs with stacks which grow down (i.e. SPARC), we build the stack
* based on the _stack_high address.
* based on the stack_high address.
*/
_stack_high = ((unsigned32)(_stack_base) + _size);
_stack_high &= ~(CPU_STACK_ALIGNMENT - 1);
stack_high = ((unsigned32)(stack_base) + size);
stack_high &= ~(CPU_STACK_ALIGNMENT - 1);
_the_size = _size & ~(CPU_STACK_ALIGNMENT - 1);
the_size = size & ~(CPU_STACK_ALIGNMENT - 1);
/* XXX following code is based on unix port */
/*
* XXX SPARC port needs a diagram like this one...
* See /usr/include/sys/stack.h in Solaris 2.3 for a nice
* diagram of the stack.
* See the README in this directory for a diagram of the stack.
*/
_the_context->o7 = jmp_addr + ADDR_ADJ_OFFSET;
_the_context->o6 = (unsigned32)(_stack_high - CPU_FRAME_SIZE);
_the_context->i6 = (unsigned32)(_stack_high);
#if 0
_the_context->rp = jmp_addr + ADDR_ADJ_OFFSET;
_the_context->sp = (unsigned32)(_stack_high - CPU_FRAME_SIZE);
_the_context->fp = (unsigned32)(_stack_high);
#endif
the_context->o7 = ((unsigned32) entry_point) - 8;
the_context->o6_sp = stack_high - CPU_MINIMUM_STACK_FRAME_SIZE;
the_context->i6_fp = stack_high;
_the_context->wim = 0x01;
/*
* Build the PSR for the task. Most everything can be 0 and the
* CWP is corrected during the context switch.
*
* The EF bit determines if the floating point unit is available.
* The FPU is ONLY enabled if the context is associated with an FP task
* and this SPARC model has an FPU.
*/
sparc_get_psr( tmp_psr );
tmp_psr &= ~SPARC_PIL_MASK;
tmp_psr |= (((_new_level) << 8) & SPARC_PIL_MASK);
tmp_psr = (tmp_psr & ~0x07) | 0x07; /* XXX should use num windows */
_the_context->psr = tmp_psr;
tmp_psr &= ~SPARC_PSR_PIL_MASK;
tmp_psr |= (new_level << 8) & SPARC_PSR_PIL_MASK;
tmp_psr &= ~SPARC_PSR_EF_MASK; /* disabled by default */
#if (SPARC_HAS_FPU == 1)
/*
* If this bit is not set, then a task gets a fault when it accesses
* a floating point register. This is a nice way to detect floating
* point tasks which are not currently declared as such.
*/
if ( is_fp )
tmp_psr |= SPARC_PSR_EF_MASK;
#endif
the_context->psr = tmp_psr;
}
/*PAGE
*
* _CPU_Internal_threads_Idle_thread_body
*
* NOTES:
*
* 1. This is the same as the regular CPU independent algorithm.
*
* 2. If you implement this using a "halt", "idle", or "shutdown"
* instruction, then don't forget to put it in an infinite loop.
*
* 3. Be warned. Some processors with onboard DMA have been known
* to stop the DMA if the CPU were put in IDLE mode. This might
* also be a problem with other on-chip peripherals. So use this
* hook with caution.
* Some SPARC implementations have low power, sleep, or idle modes. This
* tries to take advantage of those models.
*/
#if (CPU_PROVIDES_IDLE_THREAD_BODY == TRUE)
/*
* This is the implementation for the erc32.
*
* NOTE: Low power mode was enabled at initialization time.
*/
#if defined(erc32)
void _CPU_Internal_threads_Idle_thread_body( void )
{
for( ; ; )
/* insert your "halt" instruction here */ ;
while (1) {
ERC32_MEC.Power_Down = 0; /* value is irrelevant */
}
}
#endif
#endif /* CPU_PROVIDES_IDLE_THREAD_BODY */

View File

@@ -28,7 +28,9 @@
*/
#define ASM
#include <rtems/score/sparc.h>
#include <rtems/score/cpu.h>
/*
* Recent versions of GNU cpp define variables which indicate the
@@ -37,7 +39,9 @@
* have to define these as appropriate.
*/
/* XXX This does not appear to work on gcc 2.7.0 on the sparc */
/* XXX __USER_LABEL_PREFIX__ and __REGISTER_PREFIX__ do not work on gcc 2.7.0 */
/* XXX The following ifdef magic fixes the problem but results in a warning */
/* XXX when compiling assembly code. */
#undef __USER_LABEL_PREFIX__
#ifndef __USER_LABEL_PREFIX__
#define __USER_LABEL_PREFIX__ _
@@ -91,6 +95,16 @@
#define PUBLIC(sym) .globl SYM (sym)
#define EXTERN(sym) .globl SYM (sym)
/*
* Entry for traps which jump to a programmer-specified trap handler.
*/
#define TRAP(_vector, _handler) \
mov %psr, %l0 ; \
sethi %hi(_handler), %l4 ; \
jmp %l4+%lo(_handler); \
mov _vector, %l3
#endif
/* end of include file */

View File

@@ -341,17 +341,10 @@ void _CPU_Install_interrupt_stack( void )
*
* _CPU_Internal_threads_Idle_thread_body
*
* NOTES:
*
* 1. This is the same as the regular CPU independent algorithm.
*
* 2. If you implement this using a "halt", "idle", or "shutdown"
* instruction, then don't forget to put it in an infinite loop.
*
* 3. Be warned. Some processors with onboard DMA have been known
* to stop the DMA if the CPU were put in IDLE mode. This might
* also be a problem with other on-chip peripherals. So use this
* hook with caution.
* Stop until we get a signal which is the logically the same thing
* entering low-power or sleep mode on a real processor and waiting for
* an interrupt. This significantly reduces the consumption of host
* CPU cycles which is again similar to low power mode.
*/
void _CPU_Internal_threads_Idle_thread_body( void )
@@ -370,7 +363,8 @@ void _CPU_Context_Initialize(
unsigned32 *_stack_base,
unsigned32 _size,
unsigned32 _new_level,
void *_entry_point
void *_entry_point,
boolean _is_fp
)
{
void *source;
@@ -697,49 +691,15 @@ void _CPU_Fatal_error(unsigned32 error)
_exit(error);
}
/*PAGE
*
* _CPU_ffs
*/
int _CPU_ffs(unsigned32 value)
{
int output;
extern int ffs( int );
output = ffs(value);
output = output - 1;
return output;
}
/*
* Special Purpose Routines to hide the use of UNIX system calls.
*/
#if 0
/* XXX clock had this set of #define's */
/*
* In order to get the types and prototypes used in this file under
* Solaris 2.3, it is necessary to pull the following magic.
*/
#if defined(solaris)
#warning "Ignore the undefining __STDC__ warning"
#undef __STDC__
#define __STDC__ 0
#undef _POSIX_C_SOURCE
#endif
#endif
int _CPU_Get_clock_vector( void )
{
return SIGALRM;
}
void _CPU_Start_clock(
int microseconds
)

View File

@@ -38,9 +38,58 @@ extern "C" {
* significant impact on the performance of the executive as a whole.
*/
#if ( CPU_USE_GENERIC_BITFIELD_DATA == TRUE )
#ifndef INIT
extern const unsigned char __log2table[256];
#else
const unsigned char __log2table[256] = {
7, 7, 6, 6, 5, 5, 5, 5, 4, 4, 4, 4, 4, 4, 4, 4,
3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
};
#endif
#endif
#if ( CPU_USE_GENERIC_BITFIELD_CODE == FALSE )
#define _Bitfield_Find_first_bit( _value, _bit_number ) \
_CPU_Bitfield_Find_first_bit( _value, _bit_number )
#else
/*
* The following must be a macro because if a CPU specific version
* is used it will most likely use inline assembly.
*/
#define _Bitfield_Find_first_bit( _value, _bit_number ) \
{ \
register __value = (_value); \
register const unsigned char *__p = __log2table; \
\
if ( __value < 0x100 ) \
(_bit_number) = __p[ __value ] + 8; \
else \
(_bit_number) = __p[ __value >> 8 ]; \
}
#endif
#ifdef __cplusplus
}
#endif

View File

@@ -47,8 +47,9 @@ EXTERN boolean _Context_Switch_necessary;
* thread's initial state.
*/
#define _Context_Initialize( _the_context, _stack, _size, _isr, _entry ) \
_CPU_Context_Initialize( _the_context, _stack, _size, _isr, _entry )
#define \
_Context_Initialize( _the_context, _stack, _size, _isr, _entry, _is_fp ) \
_CPU_Context_Initialize( _the_context, _stack, _size, _isr, _entry, _is_fp )
/*
* _Context_Switch

View File

@@ -50,11 +50,18 @@ typedef ISR_Handler ( *ISR_Handler_entry )(
ISR_Vector_number
);
/*
* This constant promotes out the number of vectors supported by
* the current CPU being used.
* This constant promotes out the number of vectors truly supported by
* the current CPU being used. This is usually the number of distinct vectors
* the cpu can vector.
*/
#define ISR_NUMBER_OF_VECTORS CPU_INTERRUPT_NUMBER_OF_VECTORS
#define ISR_NUMBER_OF_VECTORS CPU_INTERRUPT_NUMBER_OF_VECTORS
/*
* This constant promotes out the highest valid interrupt vector number.
*/
#define ISR_INTERRUPT_MAXIMUM_VECTOR_NUMBER CPU_INTERRUPT_MAXIMUM_VECTOR_NUMBER
/*
* The following is TRUE if signals have been sent to the currently
@@ -75,7 +82,7 @@ EXTERN unsigned32 _ISR_Nest_level;
* interrupt service routines are vectored by the ISR Handler via this table.
*/
EXTERN ISR_Handler_entry _ISR_Vector_table[CPU_INTERRUPT_NUMBER_OF_VECTORS];
EXTERN ISR_Handler_entry _ISR_Vector_table[ ISR_NUMBER_OF_VECTORS ];
/*
* _ISR_Handler_initialization

View File

@@ -113,6 +113,51 @@ STATIC INLINE unsigned32 _Priority_Minor (
Priority_Control the_priority
);
/*
* _Priority_Mask
*
* DESCRIPTION:
*
* This function returns the mask associated with the major or minor
* number passed to it.
*/
#if ( CPU_USE_GENERIC_BITFIELD_CODE == TRUE )
STATIC INLINE unsigned32 _Priority_Mask (
unsigned32 bit_number
);
#else
#define _Priority_Mask( _bit_number ) \
_CPU_Priority_Mask( _bit_number )
#endif
/*
* _Priority_Bits_index
*
* DESCRIPTION:
*
* This function translates the bit numbers returned by the bit scan
* of a priority bit field into something suitable for use as
* a major or minor component of a priority.
*/
#if ( CPU_USE_GENERIC_BITFIELD_CODE == TRUE )
STATIC INLINE unsigned32 _Priority_Bits_index (
unsigned32 bit_number
);
#else
#define _Priority_Bits_index( _priority ) \
_CPU_Priority_bits_index( _priority )
#endif
/*
* _Priority_Add_to_bit_map
*

View File

@@ -38,7 +38,7 @@ STATIC INLINE boolean _ISR_Is_vector_number_valid (
unsigned32 vector
)
{
return ( vector < CPU_INTERRUPT_NUMBER_OF_VECTORS );
return ( vector <= CPU_INTERRUPT_MAXIMUM_VECTOR_NUMBER );
}
/*PAGE

View File

@@ -78,6 +78,37 @@ STATIC INLINE unsigned32 _Priority_Minor (
return ( the_priority % 16 );
}
#if ( CPU_USE_GENERIC_BITFIELD_CODE == TRUE )
/*PAGE
*
* _Priority_Mask
*
*/
STATIC INLINE unsigned32 _Priority_Mask (
unsigned32 bit_number
)
{
return (0x8000 >> bit_number);
}
/*PAGE
*
* _Priority_Bits_index
*
*/
STATIC INLINE unsigned32 _Priority_Bits_index (
unsigned32 bit_number
)
{
return bit_number;
}
#endif
/*PAGE
*
* _Priority_Add_to_bit_map
@@ -121,8 +152,8 @@ STATIC INLINE Priority_Control _Priority_Get_highest( void )
_Bitfield_Find_first_bit( _Priority_Major_bit_map, major );
_Bitfield_Find_first_bit( _Priority_Bit_map[major], minor );
return (_CPU_Priority_Bits_index( major ) << 4) +
_CPU_Priority_Bits_index( minor );
return (_Priority_Bits_index( major ) << 4) +
_Priority_Bits_index( minor );
}
/*PAGE
@@ -144,13 +175,13 @@ STATIC INLINE void _Priority_Initialize_information(
minor = _Priority_Minor( new_priority );
the_priority_map->minor =
&_Priority_Bit_map[ _CPU_Priority_Bits_index(major) ];
&_Priority_Bit_map[ _Priority_Bits_index(major) ];
mask = _CPU_Priority_Mask( major );
mask = _Priority_Mask( major );
the_priority_map->ready_major = mask;
the_priority_map->block_major = ~mask;
mask = _CPU_Priority_Mask( minor );
mask = _Priority_Mask( minor );
the_priority_map->ready_minor = mask;
the_priority_map->block_minor = ~mask;
}

View File

@@ -33,7 +33,7 @@
*/
#define _ISR_Is_vector_number_valid( _vector ) \
( (_vector) < CPU_INTERRUPT_NUMBER_OF_VECTORS )
( (_vector) <= CPU_INTERRUPT_MAXIMUM_VECTOR_NUMBER )
/*PAGE
*

View File

@@ -64,6 +64,28 @@
#define _Priority_Minor( _the_priority ) ( (_the_priority) % 16 )
#if ( CPU_USE_GENERIC_BITFIELD_CODE == TRUE )
/*PAGE
*
* _Priority_Mask
*
*/
#define _Priority_Mask( _bit_number ) \
(0x8000 >> _bit_number)
/*PAGE
*
* _Priority_Bits_index
*
*/
#define _Priority_Bits_index( _bit_number ) \
(_bit_number)
#endif
/*PAGE
*
* _Priority_Add_to_bit_map
@@ -103,8 +125,8 @@
_Bitfield_Find_first_bit( _Priority_Major_bit_map, major ); \
_Bitfield_Find_first_bit( _Priority_Bit_map[major], minor ); \
\
(_high_priority) = (_CPU_Priority_Bits_index( major ) * 16) + \
_CPU_Priority_Bits_index( minor ); \
(_high_priority) = (_Priority_Bits_index( major ) * 16) + \
_Priority_Bits_index( minor ); \
}
/*PAGE
@@ -124,13 +146,13 @@
_minor = _Priority_Minor( (_new_priority) ); \
\
(_the_priority_map)->minor = \
&_Priority_Bit_map[ _CPU_Priority_Bits_index(_major) ]; \
&_Priority_Bit_map[ _Priority_Bits_index(_major) ]; \
\
_mask = _CPU_Priority_Mask( _major ); \
_mask = _Priority_Mask( _major ); \
(_the_priority_map)->ready_major = _mask; \
(_the_priority_map)->block_major = ~_mask; \
\
_mask = _CPU_Priority_Mask( _minor ); \
_mask = _Priority_Mask( _minor ); \
(_the_priority_map)->ready_minor = _mask; \
(_the_priority_map)->block_minor = ~_mask; \
}

View File

@@ -805,9 +805,12 @@ void _Thread_Load_environment(
Thread_Control *the_thread
)
{
boolean is_fp = FALSE;
if ( the_thread->Start.fp_context ) {
the_thread->fp_context = the_thread->Start.fp_context;
_Context_Initialize_fp( &the_thread->fp_context );
is_fp = TRUE;
}
the_thread->is_preemptible = the_thread->Start.is_preemptible;
@@ -818,7 +821,8 @@ void _Thread_Load_environment(
the_thread->Start.Initial_stack.area,
the_thread->Start.Initial_stack.size,
the_thread->Start.isr_level,
_Thread_Handler
_Thread_Handler,
is_fp
);
}

Some files were not shown because too many files have changed in this diff Show More