未验证 提交 0b4e2a98 编写于 作者: B Bernard Xiong 提交者: GitHub

Merge pull request #2731 from jesven/a9-fpu

add cortex-a fpu support
...@@ -76,6 +76,18 @@ rt_hw_context_switch: ...@@ -76,6 +76,18 @@ rt_hw_context_switch:
stmfd sp, {r13, r14}^ @ push usr_sp usr_lr stmfd sp, {r13, r14}^ @ push usr_sp usr_lr
sub sp, #8 sub sp, #8
#endif #endif
#ifdef RT_USING_FPU
/* fpu context */
vmrs r6, fpexc
tst r6, #(1<<30)
beq 1f
vstmdb sp!, {d0-d15}
vstmdb sp!, {d16-d31}
vmrs r5, fpscr
stmfd sp!, {r5}
1:
stmfd sp!, {r6}
#endif
str sp, [r0] @ store sp in preempted tasks TCB str sp, [r0] @ store sp in preempted tasks TCB
ldr sp, [r1] @ get new task stack pointer ldr sp, [r1] @ get new task stack pointer
...@@ -147,6 +159,18 @@ rt_hw_context_switch_exit: ...@@ -147,6 +159,18 @@ rt_hw_context_switch_exit:
mov sp, r0 mov sp, r0
#endif #endif
#endif #endif
#ifdef RT_USING_FPU
/* fpu context */
ldmfd sp!, {r6}
vmsr fpexc, r6
tst r6, #(1<<30)
beq 1f
ldmfd sp!, {r5}
vmsr fpscr, r5
vldmia sp!, {d16-d31}
vldmia sp!, {d0-d15}
1:
#endif
#ifdef RT_USING_LWP #ifdef RT_USING_LWP
ldmfd sp, {r13, r14}^ /* usr_sp, usr_lr */ ldmfd sp, {r13, r14}^ /* usr_sp, usr_lr */
......
...@@ -60,6 +60,9 @@ rt_uint8_t *rt_hw_stack_init(void *tentry, void *parameter, ...@@ -60,6 +60,9 @@ rt_uint8_t *rt_hw_stack_init(void *tentry, void *parameter,
*(--stk) = 0; /* user lr */ *(--stk) = 0; /* user lr */
*(--stk) = 0; /* user sp*/ *(--stk) = 0; /* user sp*/
#endif #endif
#ifdef RT_USING_FPU
*(--stk) = 0; /* not use fpu*/
#endif
/* return task's current stack address */ /* return task's current stack address */
return (rt_uint8_t *)stk; return (rt_uint8_t *)stk;
......
...@@ -22,7 +22,11 @@ ...@@ -22,7 +22,11 @@
.equ I_Bit, 0x80 @ when I bit is set, IRQ is disabled .equ I_Bit, 0x80 @ when I bit is set, IRQ is disabled
.equ F_Bit, 0x40 @ when F bit is set, FIQ is disabled .equ F_Bit, 0x40 @ when F bit is set, FIQ is disabled
#ifdef RT_USING_FPU
.equ UND_Stack_Size, 0x00000400
#else
.equ UND_Stack_Size, 0x00000000 .equ UND_Stack_Size, 0x00000000
#endif
.equ SVC_Stack_Size, 0x00000400 .equ SVC_Stack_Size, 0x00000400
.equ ABT_Stack_Size, 0x00000000 .equ ABT_Stack_Size, 0x00000000
.equ RT_FIQ_STACK_PGSZ, 0x00000000 .equ RT_FIQ_STACK_PGSZ, 0x00000000
...@@ -50,6 +54,11 @@ _reset: ...@@ -50,6 +54,11 @@ _reset:
/* set the cpu to SVC32 mode and disable interrupt */ /* set the cpu to SVC32 mode and disable interrupt */
cps #Mode_SVC cps #Mode_SVC
#ifdef RT_USING_FPU
mov r4, #0xfffffff
mcr p15, 0, r4, c1, c0, 2
#endif
/* disable the data alignment check */ /* disable the data alignment check */
mrc p15, 0, r1, c1, c0, 0 mrc p15, 0, r1, c1, c0, 0
bic r1, #(1<<1) bic r1, #(1<<1)
...@@ -176,6 +185,19 @@ vector_irq: ...@@ -176,6 +185,19 @@ vector_irq:
stmfd r0, {r13, r14}^ /* usr_sp, usr_lr */ stmfd r0, {r13, r14}^ /* usr_sp, usr_lr */
sub r0, #8 sub r0, #8
#endif #endif
#ifdef RT_USING_FPU
/* fpu context */
vmrs r6, fpexc
tst r6, #(1<<30)
beq 1f
vstmdb r0!, {d0-d15}
vstmdb r0!, {d16-d31}
vmrs r5, fpscr
stmfd r0!, {r5}
1:
stmfd r0!, {r6}
#endif
/* now irq stack is clean */ /* now irq stack is clean */
/* r0 is task svc_sp */ /* r0 is task svc_sp */
/* backup r0 -> r8 */ /* backup r0 -> r8 */
...@@ -234,6 +256,18 @@ rt_hw_context_switch_interrupt_do: ...@@ -234,6 +256,18 @@ rt_hw_context_switch_interrupt_do:
stmfd sp, {r13, r14}^ @push usr_sp, usr_lr stmfd sp, {r13, r14}^ @push usr_sp, usr_lr
sub sp, #8 sub sp, #8
#endif #endif
#ifdef RT_USING_FPU
/* fpu context */
vmrs r6, fpexc
tst r6, #(1<<30)
beq 1f
vstmdb sp!, {d0-d15}
vstmdb sp!, {d16-d31}
vmrs r5, fpscr
stmfd sp!, {r5}
1:
stmfd sp!, {r6}
#endif
ldr r4, =rt_interrupt_from_thread ldr r4, =rt_interrupt_from_thread
ldr r5, [r4] ldr r5, [r4]
...@@ -243,6 +277,19 @@ rt_hw_context_switch_interrupt_do: ...@@ -243,6 +277,19 @@ rt_hw_context_switch_interrupt_do:
ldr r6, [r6] ldr r6, [r6]
ldr sp, [r6] @ get new task's stack pointer ldr sp, [r6] @ get new task's stack pointer
#ifdef RT_USING_FPU
/* fpu context */
ldmfd sp!, {r6}
vmsr fpexc, r6
tst r6, #(1<<30)
beq 1f
ldmfd sp!, {r5}
vmsr fpscr, r5
vldmia sp!, {d16-d31}
vldmia sp!, {d0-d15}
1:
#endif
#ifdef RT_USING_LWP #ifdef RT_USING_LWP
ldmfd sp, {r13, r14}^ @pop usr_sp, usr_lr ldmfd sp, {r13, r14}^ @pop usr_sp, usr_lr
add sp, #8 add sp, #8
...@@ -278,7 +325,14 @@ vector_swi: ...@@ -278,7 +325,14 @@ vector_swi:
.globl vector_undef .globl vector_undef
vector_undef: vector_undef:
push_svc_reg push_svc_reg
cps #Mode_UND
bl rt_hw_trap_undef bl rt_hw_trap_undef
#ifdef RT_USING_FPU
ldr lr, [sp, #15*4]
ldmia sp, {r0 - r12}
add sp, sp, #17 * 4
movs pc, lr
#endif
b . b .
.align 5 .align 5
...@@ -315,6 +369,12 @@ set_secondary_cpu_boot_address: ...@@ -315,6 +369,12 @@ set_secondary_cpu_boot_address:
.global secondary_cpu_start .global secondary_cpu_start
secondary_cpu_start: secondary_cpu_start:
#ifdef RT_USING_FPU
mov r4, #0xfffffff
mcr p15, 0, r4, c1, c0, 2
#endif
mrc p15, 0, r1, c1, c0, 1 mrc p15, 0, r1, c1, c0, 1
mov r0, #(1<<6) mov r0, #(1<<6)
orr r1, r0 orr r1, r0
...@@ -324,6 +384,11 @@ secondary_cpu_start: ...@@ -324,6 +384,11 @@ secondary_cpu_start:
bic r0, #(1<<13) bic r0, #(1<<13)
mcr p15, 0, r0, c1, c0, 0 mcr p15, 0, r0, c1, c0, 0
#ifdef RT_USING_FPU
cps #Mode_UND
ldr sp, =und_stack_2_limit
#endif
cps #Mode_IRQ cps #Mode_IRQ
ldr sp, =irq_stack_2_limit ldr sp, =irq_stack_2_limit
...@@ -349,3 +414,8 @@ irq_stack_2: ...@@ -349,3 +414,8 @@ irq_stack_2:
.space (1 << 10) .space (1 << 10)
irq_stack_2_limit: irq_stack_2_limit:
#ifdef RT_USING_FPU
und_stack_2:
.space (1 << 10)
und_stack_2_limit:
#endif
...@@ -45,6 +45,39 @@ void rt_hw_show_register(struct rt_hw_exp_stack *regs) ...@@ -45,6 +45,39 @@ void rt_hw_show_register(struct rt_hw_exp_stack *regs)
*/ */
void rt_hw_trap_undef(struct rt_hw_exp_stack *regs) void rt_hw_trap_undef(struct rt_hw_exp_stack *regs)
{ {
#ifdef RT_USING_FPU
{
uint32_t ins;
uint32_t addr;
if (regs->cpsr & (1 << 5))
{
/* thumb mode */
addr = regs->pc - 2;
ins = (uint32_t)*(uint16_t*)addr;
if ((ins & (3 << 11)) != 0)
{
/* 32 bit ins */
ins <<= 16;
ins += *(uint16_t*)(addr + 2);
}
}
else
{
addr = regs->pc - 4;
ins = *(uint32_t*)addr;
}
if ((ins & 0xe00) == 0xa00)
{
/* float ins */
uint32_t val = (1U << 30);
asm volatile ("vmsr fpexc, %0"::"r"(val):"memory");
regs->pc = addr;
return;
}
}
#endif
rt_kprintf("undefined instruction:\n"); rt_kprintf("undefined instruction:\n");
rt_hw_show_register(regs); rt_hw_show_register(regs);
#ifdef RT_USING_FINSH #ifdef RT_USING_FINSH
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册