forked from Imagelibrary/rtems
2002-07-30 Jay Monkman <jtm@smoothsmoothie.com>
* cpu.c, cpu_asm.S, rtems/score/arm.h, rtems/score/cpu.h, rtems/score/cpu_asm.h, rtems/score/types.h: ARM port works well enough to run all sptests, tmtests, and ttcp. In addition to general cleanup, there has been considerable optimization to interrupt disable/enable, endian swapping, and context switching.
This commit is contained in:
@@ -1,3 +1,12 @@
|
|||||||
|
2002-07-30 Jay Monkman <jtm@smoothsmoothie.com>
|
||||||
|
|
||||||
|
* cpu.c, cpu_asm.S, rtems/score/arm.h, rtems/score/cpu.h,
|
||||||
|
rtems/score/cpu_asm.h, rtems/score/types.h: ARM port works
|
||||||
|
well enough to run all sptests, tmtests, and ttcp.
|
||||||
|
In addition to general cleanup, there has been considerable
|
||||||
|
optimization to interrupt disable/enable, endian swapping,
|
||||||
|
and context switching.
|
||||||
|
|
||||||
2002-07-26 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
|
2002-07-26 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
|
||||||
|
|
||||||
* Makefile.am: Build libscorecpu.a instead of rtems-cpu.rel.
|
* Makefile.am: Build libscorecpu.a instead of rtems-cpu.rel.
|
||||||
|
|||||||
@@ -32,6 +32,9 @@
|
|||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
unsigned32 g_data_abort_cnt = 0;
|
||||||
|
unsigned32 g_data_abort_insn_list[1024];
|
||||||
|
|
||||||
void _CPU_Initialize(
|
void _CPU_Initialize(
|
||||||
rtems_cpu_table *cpu_table,
|
rtems_cpu_table *cpu_table,
|
||||||
void (*thread_dispatch) /* ignored on this CPU */
|
void (*thread_dispatch) /* ignored on this CPU */
|
||||||
@@ -51,7 +54,8 @@ unsigned32 _CPU_ISR_Get_level( void )
|
|||||||
|
|
||||||
asm volatile ("mrs %0, cpsr \n" \
|
asm volatile ("mrs %0, cpsr \n" \
|
||||||
"and %0, %0, #0xc0 \n" \
|
"and %0, %0, #0xc0 \n" \
|
||||||
: "=r" (reg));
|
: "=r" (reg) \
|
||||||
|
: "0" (reg) );
|
||||||
|
|
||||||
return reg;
|
return reg;
|
||||||
}
|
}
|
||||||
@@ -101,80 +105,34 @@ void _CPU_Context_Initialize(
|
|||||||
boolean is_fp
|
boolean is_fp
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
the_context->register_sp = ((unsigned32)(stack_base)) + (size) ;
|
the_context->register_sp = (unsigned32)stack_base + size ;
|
||||||
the_context->register_pc = (entry_point);
|
the_context->register_lr = (unsigned32)entry_point;
|
||||||
the_context->register_cpsr = (new_level | 0x13);
|
the_context->register_cpsr = new_level | 0x13;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*PAGE
|
|
||||||
*
|
/*
|
||||||
* _CPU_Install_interrupt_stack
|
* _CPU_Install_interrupt_stack - this function is empty since the
|
||||||
|
* BSP must set up the interrupt stacks.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
void _CPU_Install_interrupt_stack( void )
|
void _CPU_Install_interrupt_stack( void )
|
||||||
{
|
{
|
||||||
/* FIXME: do something here */
|
|
||||||
#if 0
|
|
||||||
extern unsigned long _fiq_stack;
|
|
||||||
extern unsigned long _fiq_stack_size;
|
|
||||||
extern unsigned long _irq_stack;
|
|
||||||
extern unsigned long _irq_stack_size;
|
|
||||||
extern unsigned long _abt_stack;
|
|
||||||
extern unsigned long _abt_stack_size;
|
|
||||||
unsigned long *ptr;
|
|
||||||
int i;
|
|
||||||
|
|
||||||
ptr = &_fiq_stack;
|
|
||||||
for (i = 0; i < ((int)&_fiq_stack_size/4); i++) {
|
|
||||||
ptr[i] = 0x13131313;
|
|
||||||
}
|
|
||||||
|
|
||||||
ptr = &_irq_stack;
|
|
||||||
for (i = 0; i < ((int)&_irq_stack_size/4); i++) {
|
|
||||||
ptr[i] = 0xf0f0f0f0;
|
|
||||||
}
|
|
||||||
|
|
||||||
ptr = &_abt_stack;
|
|
||||||
for (i = 0; i < ((int)&_abt_stack_size/4); i++) {
|
|
||||||
ptr[i] = 0x55555555;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
/*PAGE
|
|
||||||
*
|
|
||||||
* _CPU_Thread_Idle_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.
|
|
||||||
*/
|
|
||||||
|
|
||||||
void _CPU_Thread_Idle_body( void )
|
|
||||||
{
|
|
||||||
|
|
||||||
while(1); /* FIXME: finish this */
|
|
||||||
/* insert your "halt" instruction here */ ;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void _defaultExcHandler (CPU_Exception_frame *ctx)
|
void _defaultExcHandler (CPU_Exception_frame *ctx)
|
||||||
{
|
{
|
||||||
printk("\n\r");
|
printk("\n\r");
|
||||||
printk("----------------------------------------------------------\n\r");
|
printk("----------------------------------------------------------\n\r");
|
||||||
|
#if 0
|
||||||
printk("Exception 0x%x caught at PC 0x%x by thread %d\n",
|
printk("Exception 0x%x caught at PC 0x%x by thread %d\n",
|
||||||
ctx->register_pc, ctx->register_lr - 4,
|
ctx->register_pc, ctx->register_lr - 4,
|
||||||
_Thread_Executing->Object.id);
|
_Thread_Executing->Object.id);
|
||||||
|
#endif
|
||||||
printk("----------------------------------------------------------\n\r");
|
printk("----------------------------------------------------------\n\r");
|
||||||
printk("Processor execution context at time of the fault was :\n\r");
|
printk("Processor execution context at time of the fault was :\n\r");
|
||||||
printk("----------------------------------------------------------\n\r");
|
printk("----------------------------------------------------------\n\r");
|
||||||
|
#if 0
|
||||||
printk(" r0 = %8x r1 = %8x r2 = %8x r3 = %8x\n\r",
|
printk(" r0 = %8x r1 = %8x r2 = %8x r3 = %8x\n\r",
|
||||||
ctx->register_r0, ctx->register_r1,
|
ctx->register_r0, ctx->register_r1,
|
||||||
ctx->register_r2, ctx->register_r3);
|
ctx->register_r2, ctx->register_r3);
|
||||||
@@ -187,7 +145,7 @@ void _defaultExcHandler (CPU_Exception_frame *ctx)
|
|||||||
ctx->register_fp, ctx->register_ip,
|
ctx->register_fp, ctx->register_ip,
|
||||||
ctx->register_sp, ctx->register_lr - 4);
|
ctx->register_sp, ctx->register_lr - 4);
|
||||||
printk("----------------------------------------------------------\n\r");
|
printk("----------------------------------------------------------\n\r");
|
||||||
|
#endif
|
||||||
if (_ISR_Nest_level > 0) {
|
if (_ISR_Nest_level > 0) {
|
||||||
/*
|
/*
|
||||||
* In this case we shall not delete the task interrupted as
|
* In this case we shall not delete the task interrupted as
|
||||||
@@ -207,6 +165,7 @@ cpuExcHandlerType _currentExcHandler = _defaultExcHandler;
|
|||||||
|
|
||||||
extern void _Exception_Handler_Undef_Swi();
|
extern void _Exception_Handler_Undef_Swi();
|
||||||
extern void _Exception_Handler_Abort();
|
extern void _Exception_Handler_Abort();
|
||||||
|
extern void _exc_data_abort();
|
||||||
/* FIXME: put comments here */
|
/* FIXME: put comments here */
|
||||||
void rtems_exception_init_mngt()
|
void rtems_exception_init_mngt()
|
||||||
{
|
{
|
||||||
@@ -226,7 +185,7 @@ void rtems_exception_init_mngt()
|
|||||||
NULL);
|
NULL);
|
||||||
|
|
||||||
_CPU_ISR_install_vector(ARM_EXCEPTION_DATA_ABORT,
|
_CPU_ISR_install_vector(ARM_EXCEPTION_DATA_ABORT,
|
||||||
_Exception_Handler_Abort,
|
_exc_data_abort,
|
||||||
NULL);
|
NULL);
|
||||||
|
|
||||||
_CPU_ISR_install_vector(ARM_EXCEPTION_FIQ,
|
_CPU_ISR_install_vector(ARM_EXCEPTION_FIQ,
|
||||||
@@ -240,4 +199,126 @@ void rtems_exception_init_mngt()
|
|||||||
_CPU_ISR_Enable(level);
|
_CPU_ISR_Enable(level);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#define INSN_MASK 0xc5
|
||||||
|
|
||||||
|
#define INSN_STM1 0x80
|
||||||
|
#define INSN_STM2 0x84
|
||||||
|
#define INSN_STR 0x40
|
||||||
|
#define INSN_STRB 0x44
|
||||||
|
|
||||||
|
#define INSN_LDM1 0x81
|
||||||
|
#define INSN_LDM23 0x85
|
||||||
|
#define INSN_LDR 0x41
|
||||||
|
#define INSN_LDRB 0x45
|
||||||
|
|
||||||
|
#define GET_RD(x) ((x & 0x0000f000) >> 12)
|
||||||
|
#define GET_RN(x) ((x & 0x000f0000) >> 16)
|
||||||
|
|
||||||
|
#define GET_U(x) ((x & 0x00800000) >> 23)
|
||||||
|
#define GET_I(x) ((x & 0x02000000) >> 25)
|
||||||
|
|
||||||
|
#define GET_REG(r, ctx) (((unsigned32 *)ctx)[r])
|
||||||
|
#define SET_REG(r, ctx, v) (((unsigned32 *)ctx)[r] = v)
|
||||||
|
#define GET_OFFSET(insn) (insn & 0xfff)
|
||||||
|
|
||||||
|
|
||||||
|
/* This function is supposed to figure out what caused the
|
||||||
|
* data abort, do that, then return.
|
||||||
|
*
|
||||||
|
* All unhandled instructions cause the system to hang.
|
||||||
|
*/
|
||||||
|
|
||||||
|
void do_data_abort(unsigned32 insn, unsigned32 spsr,
|
||||||
|
CPU_Exception_frame *ctx)
|
||||||
|
{
|
||||||
|
unsigned8 decode;
|
||||||
|
unsigned8 insn_type;
|
||||||
|
|
||||||
|
unsigned32 rn;
|
||||||
|
unsigned32 rd;
|
||||||
|
|
||||||
|
unsigned8 *src_addr;
|
||||||
|
unsigned8 *dest_addr;
|
||||||
|
unsigned32 tmp;
|
||||||
|
|
||||||
|
g_data_abort_insn_list[g_data_abort_cnt & 0x3ff] = ctx->register_lr - 8;
|
||||||
|
g_data_abort_cnt++;
|
||||||
|
|
||||||
|
decode = ((insn >> 20) & 0xff);
|
||||||
|
|
||||||
|
insn_type = decode & INSN_MASK;
|
||||||
|
switch(insn_type) {
|
||||||
|
case INSN_STM1:
|
||||||
|
printk("\n\nINSN_STM1\n");
|
||||||
|
break;
|
||||||
|
case INSN_STM2:
|
||||||
|
printk("\n\nINSN_STM2\n");
|
||||||
|
break;
|
||||||
|
case INSN_STR:
|
||||||
|
printk("\n\nINSN_STR\n");
|
||||||
|
break;
|
||||||
|
case INSN_STRB:
|
||||||
|
printk("\n\nINSN_STRB\n");
|
||||||
|
break;
|
||||||
|
case INSN_LDM1:
|
||||||
|
printk("\n\nINSN_LDM1\n");
|
||||||
|
break;
|
||||||
|
case INSN_LDM23:
|
||||||
|
printk("\n\nINSN_LDM23\n");
|
||||||
|
break;
|
||||||
|
case INSN_LDR:
|
||||||
|
printk("\n\nINSN_LDR\n");
|
||||||
|
|
||||||
|
rn = GET_RN(insn);
|
||||||
|
rd = GET_RD(insn);
|
||||||
|
|
||||||
|
/* immediate offset/index */
|
||||||
|
if (GET_I(insn) == 0) {
|
||||||
|
switch(decode & 0x12) { /* P and W bits */
|
||||||
|
case 0x00: /* P=0, W=0 -> base is updated, post-indexed */
|
||||||
|
printk("\tPost-indexed\n");
|
||||||
|
break;
|
||||||
|
case 0x02: /* P=0, W=1 -> user mode access */
|
||||||
|
printk("\tUser mode\n");
|
||||||
|
break;
|
||||||
|
case 0x10: /* P=1, W=0 -> base not updated */
|
||||||
|
src_addr = GET_REG(rn, ctx);
|
||||||
|
if (GET_U(insn) == 0) {
|
||||||
|
src_addr -= GET_OFFSET(insn);
|
||||||
|
} else {
|
||||||
|
src_addr += GET_OFFSET(insn);
|
||||||
|
}
|
||||||
|
tmp = (src_addr[0] |
|
||||||
|
(src_addr[1] << 8) |
|
||||||
|
(src_addr[2] << 16) |
|
||||||
|
(src_addr[3] << 24));
|
||||||
|
SET_REG(rd, ctx, tmp);
|
||||||
|
return;
|
||||||
|
break;
|
||||||
|
case 0x12: /* P=1, W=1 -> base is updated, pre-indexed */
|
||||||
|
printk("\tPre-indexed\n");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case INSN_LDRB:
|
||||||
|
printk("\n\nINSN_LDRB\n");
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
printk("\n\nUnrecognized instruction\n");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
printk("data_abort at address 0x%x, instruction: 0x%x, spsr = 0x%x\n",
|
||||||
|
ctx->register_lr - 8, insn, spsr);
|
||||||
|
|
||||||
|
/* disable interrupts, wait forever */
|
||||||
|
_CPU_ISR_Disable(tmp);
|
||||||
|
while(1) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -31,57 +31,21 @@
|
|||||||
* This function copies the current registers to where r0 points, then
|
* This function copies the current registers to where r0 points, then
|
||||||
* restores the ones from where r1 points.
|
* restores the ones from where r1 points.
|
||||||
*
|
*
|
||||||
*
|
* Using the ldm/stm opcodes save 2-3 us on 100 MHz ARM9TDMI with
|
||||||
* NOTE: The function should be able to only save/restore the registers
|
* a 16 bit data bus.
|
||||||
* that would be saved by a C function since the others have already
|
|
||||||
* been saved.
|
|
||||||
*
|
|
||||||
* It should also be able to use the stm/ldm instructions.
|
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
.globl _CPU_Context_switch
|
.globl _CPU_Context_switch
|
||||||
_CPU_Context_switch:
|
_CPU_Context_switch:
|
||||||
/* FIXME: This should use load and store multiple instructions */
|
|
||||||
/* Start saving context */
|
/* Start saving context */
|
||||||
str r2, [r0, #REG_R2]
|
|
||||||
str r3, [r0, #REG_R3]
|
|
||||||
str r4, [r0, #REG_R4]
|
|
||||||
str r5, [r0, #REG_R5]
|
|
||||||
str r6, [r0, #REG_R6]
|
|
||||||
str r7, [r0, #REG_R7]
|
|
||||||
str r8, [r0, #REG_R8]
|
|
||||||
str r9, [r0, #REG_R9]
|
|
||||||
str r10, [r0, #REG_R10]
|
|
||||||
|
|
||||||
str r11, [r0, #REG_R11]
|
|
||||||
str r12, [r0, #REG_R12]
|
|
||||||
|
|
||||||
str sp, [r0, #REG_SP]
|
|
||||||
str lr, [r0, #REG_PC] /* save LR at PC's location */
|
|
||||||
|
|
||||||
mrs r2, cpsr
|
mrs r2, cpsr
|
||||||
str r2, [r0, #REG_CPSR]
|
stmia r0, {r2, r4, r5, r6, r7, r8, r9, r10, r11, r13, r14}
|
||||||
|
|
||||||
|
|
||||||
/* Start restoring context */
|
/* Start restoring context */
|
||||||
|
_restore:
|
||||||
ldr r2, [r1, #REG_CPSR]
|
ldmia r1, {r2, r4, r5, r6, r7, r8, r9, r10, r11, r13, r14}
|
||||||
msr cpsr, r2
|
msr cpsr, r2
|
||||||
|
|
||||||
ldr r2, [r1, #REG_R2]
|
|
||||||
ldr r3, [r1, #REG_R3]
|
|
||||||
ldr r4, [r1, #REG_R4]
|
|
||||||
ldr r5, [r1, #REG_R5]
|
|
||||||
ldr r6, [r1, #REG_R6]
|
|
||||||
ldr r7, [r1, #REG_R7]
|
|
||||||
ldr r8, [r1, #REG_R8]
|
|
||||||
ldr r9, [r1, #REG_R9]
|
|
||||||
ldr r10, [r1, #REG_R10]
|
|
||||||
ldr r11, [r1, #REG_R11]
|
|
||||||
ldr r12, [r1, #REG_R12]
|
|
||||||
|
|
||||||
ldr sp, [r1, #REG_SP]
|
|
||||||
ldr lr, [r1, #REG_PC]
|
|
||||||
mov pc, lr
|
mov pc, lr
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -90,34 +54,12 @@ _CPU_Context_switch:
|
|||||||
* This function copies the restores the registers from where r0 points.
|
* This function copies the restores the registers from where r0 points.
|
||||||
* It must match _CPU_Context_switch()
|
* It must match _CPU_Context_switch()
|
||||||
*
|
*
|
||||||
* NOTE: The function should be able to only save/restore the registers
|
|
||||||
* that would be saved by a C function since the others have already
|
|
||||||
* been saved.
|
|
||||||
*
|
|
||||||
* It should also be able to use the stm/ldm instructions.
|
|
||||||
*
|
|
||||||
*/
|
*/
|
||||||
.globl _CPU_Context_restore
|
.globl _CPU_Context_restore
|
||||||
_CPU_Context_restore:
|
_CPU_Context_restore:
|
||||||
/* FIXME: This should use load and store multiple instructions */
|
mov r1, r0
|
||||||
ldr r2, [r0, #REG_CPSR]
|
b _restore
|
||||||
msr cpsr, r2
|
|
||||||
|
|
||||||
ldr r2, [r0, #REG_R2]
|
|
||||||
ldr r3, [r0, #REG_R3]
|
|
||||||
ldr r4, [r0, #REG_R4]
|
|
||||||
ldr r5, [r0, #REG_R5]
|
|
||||||
ldr r6, [r0, #REG_R6]
|
|
||||||
ldr r7, [r0, #REG_R7]
|
|
||||||
ldr r8, [r0, #REG_R8]
|
|
||||||
ldr r9, [r0, #REG_R9]
|
|
||||||
ldr r10, [r0, #REG_R10]
|
|
||||||
ldr r11, [r1, #REG_R11]
|
|
||||||
ldr r12, [r1, #REG_R12]
|
|
||||||
|
|
||||||
ldr sp, [r0, #REG_SP]
|
|
||||||
ldr lr, [r0, #REG_PC]
|
|
||||||
mov pc, lr
|
|
||||||
|
|
||||||
|
|
||||||
/* FIXME: _Exception_Handler_Undef_Swi is untested */
|
/* FIXME: _Exception_Handler_Undef_Swi is untested */
|
||||||
@@ -125,10 +67,6 @@ _CPU_Context_restore:
|
|||||||
_Exception_Handler_Undef_Swi:
|
_Exception_Handler_Undef_Swi:
|
||||||
/* FIXME: This should use load and store multiple instructions */
|
/* FIXME: This should use load and store multiple instructions */
|
||||||
sub r13,r13,#SIZE_REGS
|
sub r13,r13,#SIZE_REGS
|
||||||
str r0, [r13, #REG_R0]
|
|
||||||
str r1, [r13, #REG_R1]
|
|
||||||
str r2, [r13, #REG_R2]
|
|
||||||
str r3, [r13, #REG_R3]
|
|
||||||
str r4, [r13, #REG_R4]
|
str r4, [r13, #REG_R4]
|
||||||
str r5, [r13, #REG_R5]
|
str r5, [r13, #REG_R5]
|
||||||
str r6, [r13, #REG_R6]
|
str r6, [r13, #REG_R6]
|
||||||
@@ -137,7 +75,6 @@ _Exception_Handler_Undef_Swi:
|
|||||||
str r9, [r13, #REG_R9]
|
str r9, [r13, #REG_R9]
|
||||||
str r10, [r13, #REG_R10]
|
str r10, [r13, #REG_R10]
|
||||||
str r11, [r13, #REG_R11]
|
str r11, [r13, #REG_R11]
|
||||||
str r12, [r13, #REG_R12]
|
|
||||||
str sp, [r13, #REG_SP]
|
str sp, [r13, #REG_SP]
|
||||||
str lr, [r13, #REG_LR]
|
str lr, [r13, #REG_LR]
|
||||||
mrs r0, cpsr /* read the status */
|
mrs r0, cpsr /* read the status */
|
||||||
@@ -149,10 +86,6 @@ _Exception_Handler_Undef_Swi:
|
|||||||
ldr lr, =_go_back_1
|
ldr lr, =_go_back_1
|
||||||
ldr pc,[r1] /* call handler */
|
ldr pc,[r1] /* call handler */
|
||||||
_go_back_1:
|
_go_back_1:
|
||||||
ldr r0, [r13, #REG_R0]
|
|
||||||
ldr r1, [r13, #REG_R1]
|
|
||||||
ldr r2, [r13, #REG_R2]
|
|
||||||
ldr r3, [r13, #REG_R3]
|
|
||||||
ldr r4, [r13, #REG_R4]
|
ldr r4, [r13, #REG_R4]
|
||||||
ldr r5, [r13, #REG_R5]
|
ldr r5, [r13, #REG_R5]
|
||||||
ldr r6, [r13, #REG_R6]
|
ldr r6, [r13, #REG_R6]
|
||||||
@@ -161,7 +94,6 @@ _go_back_1:
|
|||||||
ldr r9, [r13, #REG_R9]
|
ldr r9, [r13, #REG_R9]
|
||||||
ldr r10, [r13, #REG_R10]
|
ldr r10, [r13, #REG_R10]
|
||||||
ldr r11, [r13, #REG_R11]
|
ldr r11, [r13, #REG_R11]
|
||||||
ldr r12, [r13, #REG_R12]
|
|
||||||
ldr sp, [r13, #REG_SP]
|
ldr sp, [r13, #REG_SP]
|
||||||
ldr lr, [r13, #REG_LR]
|
ldr lr, [r13, #REG_LR]
|
||||||
add r13,r13,#SIZE_REGS
|
add r13,r13,#SIZE_REGS
|
||||||
@@ -172,19 +104,13 @@ _go_back_1:
|
|||||||
_Exception_Handler_Abort:
|
_Exception_Handler_Abort:
|
||||||
/* FIXME: This should use load and store multiple instructions */
|
/* FIXME: This should use load and store multiple instructions */
|
||||||
sub r13,r13,#SIZE_REGS
|
sub r13,r13,#SIZE_REGS
|
||||||
str r0, [r13, #REG_R0]
|
|
||||||
str r1, [r13, #REG_R1]
|
|
||||||
str r2, [r13, #REG_R2]
|
|
||||||
str r3, [r13, #REG_R3]
|
|
||||||
str r4, [r13, #REG_R4]
|
str r4, [r13, #REG_R4]
|
||||||
str r5, [r13, #REG_R5]
|
str r5, [r13, #REG_R5]
|
||||||
str r6, [r13, #REG_R6]
|
str r6, [r13, #REG_R6]
|
||||||
str r7, [r13, #REG_R7]
|
str r7, [r13, #REG_R7]
|
||||||
str r8, [r13, #REG_R8]
|
str r8, [r13, #REG_R8]
|
||||||
str r9, [r13, #REG_R9]
|
str r9, [r13, #REG_R9]
|
||||||
str r10, [r13, #REG_R10]
|
|
||||||
str sp, [r13, #REG_R11]
|
str sp, [r13, #REG_R11]
|
||||||
str lr, [r13, #REG_R12]
|
|
||||||
str lr, [r13, #REG_SP]
|
str lr, [r13, #REG_SP]
|
||||||
str lr, [r13, #REG_LR]
|
str lr, [r13, #REG_LR]
|
||||||
mrs r0, cpsr /* read the status */
|
mrs r0, cpsr /* read the status */
|
||||||
@@ -196,10 +122,6 @@ _Exception_Handler_Abort:
|
|||||||
ldr lr, =_go_back_2
|
ldr lr, =_go_back_2
|
||||||
ldr pc,[r1] /* call handler */
|
ldr pc,[r1] /* call handler */
|
||||||
_go_back_2:
|
_go_back_2:
|
||||||
ldr r0, [r13, #REG_R0]
|
|
||||||
ldr r1, [r13, #REG_R1]
|
|
||||||
ldr r2, [r13, #REG_R2]
|
|
||||||
ldr r3, [r13, #REG_R3]
|
|
||||||
ldr r4, [r13, #REG_R4]
|
ldr r4, [r13, #REG_R4]
|
||||||
ldr r5, [r13, #REG_R5]
|
ldr r5, [r13, #REG_R5]
|
||||||
ldr r6, [r13, #REG_R6]
|
ldr r6, [r13, #REG_R6]
|
||||||
@@ -208,9 +130,25 @@ _go_back_2:
|
|||||||
ldr r9, [r13, #REG_R9]
|
ldr r9, [r13, #REG_R9]
|
||||||
ldr r10, [r13, #REG_R10]
|
ldr r10, [r13, #REG_R10]
|
||||||
ldr sp, [r13, #REG_R11]
|
ldr sp, [r13, #REG_R11]
|
||||||
ldr lr, [r13, #REG_R12]
|
|
||||||
ldr lr, [r13, #REG_SP]
|
ldr lr, [r13, #REG_SP]
|
||||||
ldr lr, [r13, #REG_LR]
|
ldr lr, [r13, #REG_LR]
|
||||||
add r13,r13,#SIZE_REGS
|
add r13,r13,#SIZE_REGS
|
||||||
subs pc,r14,#4 /* return */
|
subs pc,r14,#4 /* return */
|
||||||
|
|
||||||
|
.globl _exc_data_abort
|
||||||
|
_exc_data_abort:
|
||||||
|
sub sp, sp, #SIZE_REGS /* reserve register frame */
|
||||||
|
stmia sp, {r0-r12}
|
||||||
|
str lr, [sp, #REG_LR]
|
||||||
|
mov r1, lr
|
||||||
|
ldr r0, [r1, #-8] /* r0 = bad instruction */
|
||||||
|
mrs r1, spsr /* r1 = spsr */
|
||||||
|
mov r2, r13 /* r2 = exception frame */
|
||||||
|
bl do_data_abort
|
||||||
|
|
||||||
|
ldr lr, [sp, #REG_LR]
|
||||||
|
ldmia sp, {r0-r12}
|
||||||
|
add sp, sp, #SIZE_REGS
|
||||||
|
|
||||||
|
subs pc, r14, #4 /* return to the instruction */
|
||||||
|
/* _AFTER_ the aborted one */
|
||||||
|
|||||||
@@ -29,25 +29,44 @@ extern "C" {
|
|||||||
* dependent features are present in a particular member
|
* dependent features are present in a particular member
|
||||||
* of the family.
|
* of the family.
|
||||||
*/
|
*/
|
||||||
#if defined(__arm9__)
|
#if defined(__ARM_ARCH_4__)
|
||||||
# define CPU_MODEL_NAME "arm9"
|
# define CPU_MODEL_NAME "ARMv4"
|
||||||
# define ARM_HAS_FPU 0
|
# define ARM_HAS_CLZ 0
|
||||||
#elif defined(__arm9tdmi__)
|
# define ARM_HAS_THUMB 0
|
||||||
# define CPU_MODEL_NAME "arm9tdmi"
|
|
||||||
# define ARM_HAS_FPU 0
|
#elif defined(__ARM_ARCH_4T__)
|
||||||
#elif defined(__arm7__)
|
# define CPU_MODEL_NAME "ARMv4T"
|
||||||
# define CPU_MODEL_NAME "arm7"
|
# define ARM_HAS_CLZ 0
|
||||||
# define ARM_HAS_FPU 0
|
# define ARM_HAS_THUMB 1
|
||||||
#elif defined(__arm7tdmi__)
|
|
||||||
# define CPU_MODEL_NAME "arm7tdmi"
|
#elif defined(__ARM_ARCH_5__)
|
||||||
# define ARM_HAS_FPU 0
|
# define CPU_MODEL_NAME "ARMv5"
|
||||||
#elif defined(__arm__)
|
# define ARM_HAS_CLZ 1
|
||||||
# define CPU_MODEL_NAME "unknown ARM"
|
# define ARM_HAS_THUMB 0
|
||||||
# define ARM_HAS_FPU 0
|
|
||||||
|
#elif defined(__ARM_ARCH_5T__)
|
||||||
|
# define CPU_MODEL_NAME "ARMv5T"
|
||||||
|
# define ARM_HAS_CLZ 1
|
||||||
|
# define ARM_HAS_THUMB 1
|
||||||
|
|
||||||
|
#elif defined(__ARM_ARCH_5E__)
|
||||||
|
# define CPU_MODEL_NAME "ARMv5E"
|
||||||
|
# define ARM_HAS_CLZ 1
|
||||||
|
# define ARM_HAS_THUMB 0
|
||||||
|
|
||||||
|
#elif defined(__ARM_ARCH_5TE__)
|
||||||
|
# define CPU_MODEL_NAME "ARMv5TE"
|
||||||
|
# define ARM_HAS_CLZ 1
|
||||||
|
# define ARM_HAS_THUMB 1
|
||||||
|
|
||||||
#else
|
#else
|
||||||
# error "Unsupported CPU Model"
|
# error "Unsupported CPU Model"
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/* All ARM CPUs are assumed to not have floating point units */
|
||||||
|
#define ARM_HAS_FPU 0
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Define the name of the CPU family.
|
* Define the name of the CPU family.
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -1,8 +1,10 @@
|
|||||||
/*
|
/*
|
||||||
|
* $RCSfile$
|
||||||
|
*
|
||||||
* This include file contains information pertaining to the ARM
|
* This include file contains information pertaining to the ARM
|
||||||
* processor.
|
* processor.
|
||||||
*
|
*
|
||||||
* COPYRIGHT (c) 2002 Advent Networks, Inc.
|
* Copyright (c) 2002 Advent Networks, Inc.
|
||||||
* Jay Monkman <jmonkman@adventnetworks.com>
|
* Jay Monkman <jmonkman@adventnetworks.com>
|
||||||
*
|
*
|
||||||
* COPYRIGHT (c) 2000 Canon Research Centre France SA.
|
* COPYRIGHT (c) 2000 Canon Research Centre France SA.
|
||||||
@@ -12,7 +14,6 @@
|
|||||||
* found in the file LICENSE in this distribution or at
|
* found in the file LICENSE in this distribution or at
|
||||||
* http://www.OARcorp.com/rtems/license.html.
|
* http://www.OARcorp.com/rtems/license.html.
|
||||||
*
|
*
|
||||||
* $Id$
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* FIXME: finish commenting/cleaning up this file */
|
/* FIXME: finish commenting/cleaning up this file */
|
||||||
@@ -25,7 +26,7 @@ extern "C" {
|
|||||||
|
|
||||||
#include <rtems/score/arm.h> /* pick up machine definitions */
|
#include <rtems/score/arm.h> /* pick up machine definitions */
|
||||||
#ifndef ASM
|
#ifndef ASM
|
||||||
#include <rtems/score/types.h>
|
#include <rtems/score/armtypes.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* conditional compilation parameters */
|
/* conditional compilation parameters */
|
||||||
@@ -103,7 +104,7 @@ extern "C" {
|
|||||||
*
|
*
|
||||||
* If this is TRUE, CPU_ALLOCATE_INTERRUPT_STACK should also be TRUE.
|
* If this is TRUE, CPU_ALLOCATE_INTERRUPT_STACK should also be TRUE.
|
||||||
*
|
*
|
||||||
* Only one of CPU_HAS_SOFTWARE_INTERRU
|
* Only one of CPU_HAS_SOFTWARE_INTERRUPT_STACK and
|
||||||
* CPU_HAS_HARDWARE_INTERRUPT_STACK should be set to TRUE. It is
|
* CPU_HAS_HARDWARE_INTERRUPT_STACK should be set to TRUE. It is
|
||||||
* possible that both are FALSE for a particular CPU. Although it
|
* possible that both are FALSE for a particular CPU. Although it
|
||||||
* is unclear what that would imply about the interrupt processing
|
* is unclear what that would imply about the interrupt processing
|
||||||
@@ -122,7 +123,7 @@ extern "C" {
|
|||||||
* or CPU_INSTALL_HARDWARE_INTERRUPT_STACK is TRUE.
|
* or CPU_INSTALL_HARDWARE_INTERRUPT_STACK is TRUE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#define CPU_ALLOCATE_INTERRUPT_STACK TRUE
|
#define CPU_ALLOCATE_INTERRUPT_STACK FALSE
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Does the RTEMS invoke the user's ISR with the vector number and
|
* Does the RTEMS invoke the user's ISR with the vector number and
|
||||||
@@ -141,7 +142,7 @@ extern "C" {
|
|||||||
* If there is a FP coprocessor such as the i387 or mc68881, then
|
* If there is a FP coprocessor such as the i387 or mc68881, then
|
||||||
* the answer is TRUE.
|
* the answer is TRUE.
|
||||||
*
|
*
|
||||||
* The macro name "NO_CPU_HAS_FPU" should be made CPU specific.
|
* The macro name "ARM_HAS_FPU" should be made CPU specific.
|
||||||
* It indicates whether or not this CPU model has FP support. For
|
* It indicates whether or not this CPU model has FP support. For
|
||||||
* example, it would be possible to have an i386_nofp CPU model
|
* 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
|
* which set this to false to indicate that you have an i386 without
|
||||||
@@ -331,12 +332,8 @@ extern "C" {
|
|||||||
* this is enough information for RTEMS, it is probably not enough for
|
* this is enough information for RTEMS, it is probably not enough for
|
||||||
* a debugger such as gdb. But that is another problem.
|
* a debugger such as gdb. But that is another problem.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
unsigned32 register_r0;
|
unsigned32 register_cpsr;
|
||||||
unsigned32 register_r1;
|
|
||||||
unsigned32 register_r2;
|
|
||||||
unsigned32 register_r3;
|
|
||||||
unsigned32 register_r4;
|
unsigned32 register_r4;
|
||||||
unsigned32 register_r5;
|
unsigned32 register_r5;
|
||||||
unsigned32 register_r6;
|
unsigned32 register_r6;
|
||||||
@@ -345,18 +342,23 @@ typedef struct {
|
|||||||
unsigned32 register_r9;
|
unsigned32 register_r9;
|
||||||
unsigned32 register_r10;
|
unsigned32 register_r10;
|
||||||
unsigned32 register_fp;
|
unsigned32 register_fp;
|
||||||
unsigned32 register_ip;
|
|
||||||
unsigned32 register_sp;
|
unsigned32 register_sp;
|
||||||
unsigned32 register_lr;
|
unsigned32 register_lr;
|
||||||
unsigned32 register_pc;
|
unsigned32 register_pc;
|
||||||
unsigned32 register_cpsr;
|
|
||||||
} Context_Control;
|
} Context_Control;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
double some_float_register;
|
double some_float_register;
|
||||||
} Context_Control_fp;
|
} Context_Control_fp;
|
||||||
|
|
||||||
typedef Context_Control CPU_Exception_frame;
|
typedef struct {
|
||||||
|
unsigned32 register_r0;
|
||||||
|
unsigned32 register_r1;
|
||||||
|
unsigned32 register_r2;
|
||||||
|
unsigned32 register_r3;
|
||||||
|
unsigned32 register_ip;
|
||||||
|
unsigned32 register_lr;
|
||||||
|
} CPU_Exception_frame;
|
||||||
|
|
||||||
typedef void (*cpuExcHandlerType) (CPU_Exception_frame*);
|
typedef void (*cpuExcHandlerType) (CPU_Exception_frame*);
|
||||||
extern cpuExcHandlerType _currentExcHandler;
|
extern cpuExcHandlerType _currentExcHandler;
|
||||||
@@ -372,7 +374,7 @@ typedef CPU_Exception_frame CPU_Interrupt_frame;
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
* The following table contains the information required to configure
|
* The following table contains the information required to configure
|
||||||
* the ARM processor specific parameters.
|
* the XXX processor specific parameters.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
@@ -396,7 +398,9 @@ typedef struct {
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Macros to access NO_CPU specific additions to the CPU Table
|
* Macros to access ARM specific additions to the CPU Table
|
||||||
|
*
|
||||||
|
* none required
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* There are no CPU specific additions to the CPU Table for this port. */
|
/* There are no CPU specific additions to the CPU Table for this port. */
|
||||||
@@ -410,40 +414,6 @@ typedef struct {
|
|||||||
|
|
||||||
SCORE_EXTERN Context_Control_fp _CPU_Null_fp_context;
|
SCORE_EXTERN Context_Control_fp _CPU_Null_fp_context;
|
||||||
|
|
||||||
/*
|
|
||||||
* On some CPUs, RTEMS supports a software managed interrupt stack.
|
|
||||||
* 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.
|
|
||||||
*
|
|
||||||
* NOTE: These two variables are required if the macro
|
|
||||||
* CPU_HAS_SOFTWARE_INTERRUPT_STACK is defined as TRUE.
|
|
||||||
*/
|
|
||||||
|
|
||||||
SCORE_EXTERN void *_CPU_Interrupt_stack_low;
|
|
||||||
SCORE_EXTERN void *_CPU_Interrupt_stack_high;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* 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).
|
|
||||||
*/
|
|
||||||
|
|
||||||
SCORE_EXTERN void (*_CPU_Thread_dispatch_pointer)();
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Nothing prevents the porter from declaring more CPU specific variables.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/* XXX: if needed, put more variables here */
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* The size of the floating point context area. On some CPUs this
|
* The size of the floating point context area. On some CPUs this
|
||||||
* will not be a "sizeof" because the format of the floating point
|
* will not be a "sizeof" because the format of the floating point
|
||||||
@@ -481,7 +451,7 @@ SCORE_EXTERN void (*_CPU_Thread_dispatch_pointer)();
|
|||||||
* that a "reasonable" small application should not have any problems.
|
* that a "reasonable" small application should not have any problems.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#define CPU_STACK_MINIMUM_SIZE (1024*16)
|
#define CPU_STACK_MINIMUM_SIZE (1024*4)
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* CPU's worst alignment requirement for data types on a byte boundary. This
|
* CPU's worst alignment requirement for data types on a byte boundary. This
|
||||||
@@ -535,7 +505,7 @@ SCORE_EXTERN void (*_CPU_Thread_dispatch_pointer)();
|
|||||||
* Support routine to initialize the RTEMS vector table after it is allocated.
|
* Support routine to initialize the RTEMS vector table after it is allocated.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#define _CPU_Initialize_vectors()
|
#define _CPU_Initialize_vectors()
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Disable all interrupts for an RTEMS critical section. The previous
|
* Disable all interrupts for an RTEMS critical section. The previous
|
||||||
@@ -543,15 +513,13 @@ SCORE_EXTERN void (*_CPU_Thread_dispatch_pointer)();
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#define _CPU_ISR_Disable( _level ) \
|
#define _CPU_ISR_Disable( _level ) \
|
||||||
do { \
|
{ \
|
||||||
int reg; \
|
int reg; \
|
||||||
asm volatile ("MRS %0, cpsr \n" \
|
asm volatile ("MRS %0, cpsr \n" \
|
||||||
"ORR %1, %0, #0xc0 \n" \
|
"ORR %1, %0, #0xc0 \n" \
|
||||||
"MSR cpsr, %1 \n" \
|
"MSR cpsr, %1 \n" \
|
||||||
"AND %0, %0, #0xc0 \n" \
|
: "=&r" (_level), "=&r" (reg)); \
|
||||||
: "=r" (_level), "=r" (reg) \
|
}
|
||||||
: "0" (_level), "1" (reg)); \
|
|
||||||
} while (0)
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Enable interrupts to the previous level (returned by _CPU_ISR_Disable).
|
* Enable interrupts to the previous level (returned by _CPU_ISR_Disable).
|
||||||
@@ -560,15 +528,10 @@ SCORE_EXTERN void (*_CPU_Thread_dispatch_pointer)();
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#define _CPU_ISR_Enable( _level ) \
|
#define _CPU_ISR_Enable( _level ) \
|
||||||
do { \
|
{ \
|
||||||
int reg; \
|
asm volatile ("MSR cpsr, %0 \n" \
|
||||||
asm volatile ("MRS %0, cpsr \n" \
|
: : "r" (_level)); \
|
||||||
"BIC %0, %0, #0xc0 \n" \
|
}
|
||||||
"ORR %0, %0, %2 \n" \
|
|
||||||
"MSR cpsr, %0 \n" \
|
|
||||||
: "=r" (reg) \
|
|
||||||
: "0" (reg), "r" (_level)); \
|
|
||||||
} while (0)
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* This temporarily restores the interrupt to _level before immediately
|
* This temporarily restores the interrupt to _level before immediately
|
||||||
@@ -579,15 +542,12 @@ SCORE_EXTERN void (*_CPU_Thread_dispatch_pointer)();
|
|||||||
|
|
||||||
#define _CPU_ISR_Flash( _level ) \
|
#define _CPU_ISR_Flash( _level ) \
|
||||||
{ \
|
{ \
|
||||||
int reg1; \
|
int reg; \
|
||||||
int reg2; \
|
|
||||||
asm volatile ("MRS %0, cpsr \n" \
|
asm volatile ("MRS %0, cpsr \n" \
|
||||||
"BIC %1, %0, #0xc0 \n" \
|
|
||||||
"ORR %1, %1, %4 \n" \
|
|
||||||
"MSR cpsr, %1 \n" \
|
"MSR cpsr, %1 \n" \
|
||||||
"MSR cpsr, %0 \n" \
|
"MSR cpsr, %0 \n" \
|
||||||
: "=r" (reg1), "=r" (reg2) \
|
: "=&r" (reg) \
|
||||||
: "0" (reg1), "1" (reg2), "r" (_level)); \
|
: "r" (_level)); \
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -603,15 +563,15 @@ SCORE_EXTERN void (*_CPU_Thread_dispatch_pointer)();
|
|||||||
* The get routine usually must be implemented as a subroutine.
|
* The get routine usually must be implemented as a subroutine.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#define _CPU_ISR_Set_level( new_level ) \
|
#define _CPU_ISR_Set_level( new_level ) \
|
||||||
{ \
|
{ \
|
||||||
int reg; \
|
int reg; \
|
||||||
asm volatile ("MRS %0, cpsr \n" \
|
asm volatile ("MRS %0, cpsr \n" \
|
||||||
"BIC %0, %0, #0xc0 \n" \
|
"BIC %0, %0, #0xc0 \n" \
|
||||||
"ORR %0, %0, %2 \n" \
|
"ORR %0, %0, %2 \n" \
|
||||||
"MSR cpsr_c, %0 \n" \
|
"MSR cpsr_c, %0 \n" \
|
||||||
: "=r" (reg) \
|
: "=r" (reg) \
|
||||||
: "0" (reg), "r" (new_level)); \
|
: "r" (reg), "0" (reg)); \
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -708,9 +668,17 @@ void _CPU_Context_Initialize(
|
|||||||
* halts/stops the CPU.
|
* halts/stops the CPU.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#define _CPU_Fatal_halt( _error ) \
|
#define _CPU_Fatal_halt( _error ) \
|
||||||
{ \
|
do { \
|
||||||
}
|
int _level; \
|
||||||
|
_CPU_ISR_Disable( _level ); \
|
||||||
|
asm volatile ("mov r0, %0\n" \
|
||||||
|
: "=r" (_error) \
|
||||||
|
: "0" (_error) \
|
||||||
|
: "r0" ); \
|
||||||
|
while(1) ; \
|
||||||
|
} while(0);
|
||||||
|
|
||||||
|
|
||||||
/* end of Fatal Error manager macros */
|
/* end of Fatal Error manager macros */
|
||||||
|
|
||||||
@@ -770,18 +738,17 @@ void _CPU_Context_Initialize(
|
|||||||
* where bit_set_table[ 16 ] has values which indicate the first
|
* where bit_set_table[ 16 ] has values which indicate the first
|
||||||
* bit set
|
* bit set
|
||||||
*/
|
*/
|
||||||
|
#if (ARM_HAS_CLZ == 0)
|
||||||
|
# define CPU_USE_GENERIC_BITFIELD_CODE TRUE
|
||||||
|
# define CPU_USE_GENERIC_BITFIELD_DATA TRUE
|
||||||
|
#else
|
||||||
|
# define CPU_USE_GENERIC_BITFIELD_CODE FALSE
|
||||||
|
# define CPU_USE_GENERIC_BITFIELD_DATA FALSE
|
||||||
|
|
||||||
#define CPU_USE_GENERIC_BITFIELD_CODE TRUE
|
# define _CPU_Bitfield_Find_first_bit( _value, _output ) \
|
||||||
#define CPU_USE_GENERIC_BITFIELD_DATA TRUE
|
{ \
|
||||||
|
(_output) = 0; /* do something to prevent warnings */ \
|
||||||
#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 */
|
/* end of Bitfield handler macros */
|
||||||
|
|
||||||
@@ -791,12 +758,10 @@ void _CPU_Context_Initialize(
|
|||||||
* for that routine.
|
* for that routine.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#if (CPU_USE_GENERIC_BITFIELD_CODE == FALSE)
|
|
||||||
|
|
||||||
#define _CPU_Priority_Mask( _bit_number ) \
|
# define _CPU_Priority_Mask( _bit_number ) \
|
||||||
( 1 << (_bit_number) )
|
( 1 << (_bit_number) )
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* This routine translates the bit numbers returned by
|
* This routine translates the bit numbers returned by
|
||||||
@@ -805,11 +770,11 @@ void _CPU_Context_Initialize(
|
|||||||
* for that routine.
|
* for that routine.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#if (CPU_USE_GENERIC_BITFIELD_CODE == FALSE)
|
|
||||||
|
|
||||||
#define _CPU_Priority_bits_index( _priority ) \
|
# define _CPU_Priority_bits_index( _priority ) \
|
||||||
(_priority)
|
(_priority)
|
||||||
|
|
||||||
|
# error "Implement CLZ verson of priority bit functions for ARMv5"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* end of Priority handler macros */
|
/* end of Priority handler macros */
|
||||||
@@ -862,17 +827,6 @@ void _CPU_ISR_install_vector(
|
|||||||
|
|
||||||
void _CPU_Install_interrupt_stack( void );
|
void _CPU_Install_interrupt_stack( void );
|
||||||
|
|
||||||
/*
|
|
||||||
* _CPU_Thread_Idle_body
|
|
||||||
*
|
|
||||||
* This routine is the CPU dependent IDLE thread body.
|
|
||||||
*
|
|
||||||
* NOTE: It need only be provided if CPU_PROVIDES_IDLE_THREAD_BODY
|
|
||||||
* is TRUE.
|
|
||||||
*/
|
|
||||||
|
|
||||||
void _CPU_Thread_Idle_body( void );
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* _CPU_Context_switch
|
* _CPU_Context_switch
|
||||||
*
|
*
|
||||||
@@ -897,6 +851,7 @@ void _CPU_Context_restore(
|
|||||||
Context_Control *new_context
|
Context_Control *new_context
|
||||||
);
|
);
|
||||||
|
|
||||||
|
#if (ARM_HAS_FPU == 1)
|
||||||
/*
|
/*
|
||||||
* _CPU_Context_save_fp
|
* _CPU_Context_save_fp
|
||||||
*
|
*
|
||||||
@@ -916,6 +871,7 @@ void _CPU_Context_save_fp(
|
|||||||
void _CPU_Context_restore_fp(
|
void _CPU_Context_restore_fp(
|
||||||
void **fp_context_ptr
|
void **fp_context_ptr
|
||||||
);
|
);
|
||||||
|
#endif /* (ARM_HAS_FPU == 1) */
|
||||||
|
|
||||||
/* The following routine swaps the endian format of an unsigned int.
|
/* The following routine swaps the endian format of an unsigned int.
|
||||||
* It must be static because it is referenced indirectly.
|
* It must be static because it is referenced indirectly.
|
||||||
@@ -941,19 +897,28 @@ static inline unsigned int CPU_swap_u32(
|
|||||||
unsigned int value
|
unsigned int value
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
unsigned32 byte1, byte2, byte3, byte4, swapped;
|
unsigned32 tmp;
|
||||||
|
asm volatile ("EOR %1, %0, %0, ROR #16\n" \
|
||||||
byte4 = (value >> 24) & 0xff;
|
"BIC %1, %1, #0xff0000\n" \
|
||||||
byte3 = (value >> 16) & 0xff;
|
"MOV %0, %0, ROR #8\n" \
|
||||||
byte2 = (value >> 8) & 0xff;
|
"EOR %0, %0, %1, LSR #8\n" \
|
||||||
byte1 = value & 0xff;
|
: "=&r" (value), "=&r" (tmp) \
|
||||||
|
: "0" (value));
|
||||||
swapped = (byte1 << 24) | (byte2 << 16) | (byte3 << 8) | byte4;
|
|
||||||
return( swapped );
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
#define CPU_swap_u16( value ) \
|
static inline unsigned16 CPU_swap_u16(unsigned16 value)
|
||||||
(((value&0xff) << 8) | ((value >> 8)&0xff))
|
{
|
||||||
|
unsigned32 tmp = value; /* make compiler warnings go away */
|
||||||
|
asm volatile ("MOV %1, %0, LSR #8\n" \
|
||||||
|
"BIC %0, %0, #0xff00\n" \
|
||||||
|
"MOV %0, %0, LSL #8\n" \
|
||||||
|
"ORR %0, %0, %1\n" \
|
||||||
|
: "=&r" (value), "=&r" (tmp) \
|
||||||
|
: "0" (value));
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,24 +18,18 @@
|
|||||||
|
|
||||||
|
|
||||||
/* Registers saved in context switch: */
|
/* Registers saved in context switch: */
|
||||||
.set REG_R0, 0
|
.set REG_CPSR, 0
|
||||||
.set REG_R1, 4
|
.set REG_R4, 4
|
||||||
.set REG_R2, 8
|
.set REG_R5, 8
|
||||||
.set REG_R3, 12
|
.set REG_R6, 12
|
||||||
.set REG_R4, 16
|
.set REG_R7, 16
|
||||||
.set REG_R5, 20
|
.set REG_R8, 20
|
||||||
.set REG_R6, 24
|
.set REG_R9, 24
|
||||||
.set REG_R7, 28
|
.set REG_R10, 28
|
||||||
.set REG_R8, 32
|
.set REG_R11, 32
|
||||||
.set REG_R9, 36
|
.set REG_SP, 36
|
||||||
.set REG_R10, 40
|
.set REG_LR, 40
|
||||||
.set REG_R11, 44
|
.set REG_PC, 44
|
||||||
.set REG_R12, 48
|
.set SIZE_REGS, REG_PC + 4
|
||||||
.set REG_SP, 52
|
|
||||||
.set REG_LR, 56
|
|
||||||
.set REG_PC, 60
|
|
||||||
.set REG_CPSR, 64
|
|
||||||
.set SIZE_REGS, REG_CPSR + 4
|
|
||||||
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -25,25 +25,24 @@ extern "C" {
|
|||||||
* This section defines the basic types for this processor.
|
* This section defines the basic types for this processor.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
typedef unsigned char unsigned8; /* unsigned 8-bit integer */
|
typedef unsigned char unsigned8; /* unsigned 8-bit integer */
|
||||||
typedef unsigned short unsigned16; /* unsigned 16-bit integer */
|
typedef unsigned short unsigned16; /* unsigned 16-bit integer */
|
||||||
typedef unsigned int unsigned32; /* unsigned 32-bit integer */
|
typedef unsigned int unsigned32; /* unsigned 32-bit integer */
|
||||||
typedef unsigned long long unsigned64; /* unsigned 64-bit integer */
|
typedef unsigned long long unsigned64; /* unsigned 64-bit integer */
|
||||||
|
|
||||||
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 unsigned32 boolean; /* Boolean value */
|
||||||
typedef signed short signed16; /* 16-bit signed integer */
|
typedef unsigned16 Priority_Bit_map_control;
|
||||||
typedef signed int signed32; /* 32-bit signed integer */
|
|
||||||
typedef signed long long signed64; /* 64 bit signed integer */
|
|
||||||
|
|
||||||
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 void arm_cpu_isr;
|
||||||
typedef double double_precision; /* double precision float */
|
typedef void ( *arm_cpu_isr_entry )( void );
|
||||||
|
|
||||||
typedef void no_cpu_isr;
|
|
||||||
typedef void ( *no_cpu_isr_entry )( void );
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user