diff options
| author | ardafu <[email protected]> | 2015-04-14 21:56:34 +0800 |
|---|---|---|
| committer | ardafu <[email protected]> | 2015-04-14 21:56:34 +0800 |
| commit | 39452b67b0351ac7b0b941971c4fe3be8f76d57e (patch) | |
| tree | 8b230748b96fef02d3b215e7a485c1b75c35db96 /libcpu | |
| parent | 2d1edc94a35a70a74144b460fad0aaa6677a2f81 (diff) | |
1. [cpu] split ARM926 cpu code from AT91SAM9260 BSP
Diffstat (limited to 'libcpu')
| -rw-r--r-- | libcpu/arm/arm926/context_gcc.S | 153 | ||||
| -rw-r--r-- | libcpu/arm/arm926/context_iar.S | 103 | ||||
| -rw-r--r-- | libcpu/arm/arm926/context_rvds.S | 155 | ||||
| -rw-r--r-- | libcpu/arm/arm926/cpuport.c | 194 | ||||
| -rw-r--r-- | libcpu/arm/arm926/mmu.c | 432 | ||||
| -rw-r--r-- | libcpu/arm/arm926/mmu.h | 46 | ||||
| -rw-r--r-- | libcpu/arm/arm926/stack.c | 60 | ||||
| -rw-r--r-- | libcpu/arm/arm926/start_gcc.S | 327 | ||||
| -rw-r--r-- | libcpu/arm/arm926/start_iar.S | 296 | ||||
| -rw-r--r-- | libcpu/arm/arm926/start_rvds.S | 338 | ||||
| -rw-r--r-- | libcpu/arm/arm926/trap.c | 209 |
11 files changed, 1897 insertions, 416 deletions
diff --git a/libcpu/arm/arm926/context_gcc.S b/libcpu/arm/arm926/context_gcc.S index a3f07a1860..5357b36d20 100644 --- a/libcpu/arm/arm926/context_gcc.S +++ b/libcpu/arm/arm926/context_gcc.S @@ -1,110 +1,99 @@ -/* - * File : context.S - * This file is part of RT-Thread RTOS - * COPYRIGHT (C) 2006, RT-Thread Development Team - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Change Logs: - * Date Author Notes - * 2011-01-13 weety copy from mini2440 - */ - -/*! - * \addtogroup AT91SAM926X - */ -/*@{*/ - -#define NOINT 0xc0 +;/* +; * File : context_iar.S +; * This file is part of RT-Thread RTOS +; * COPYRIGHT (C) 2006, RT-Thread Development Team +; * +; * This program is free software; you can redistribute it and/or modify +; * it under the terms of the GNU General Public License as published by +; * the Free Software Foundation; either version 2 of the License, or +; * (at your option) any later version. +; * +; * This program is distributed in the hope that it will be useful, +; * but WITHOUT ANY WARRANTY; without even the implied warranty of +; * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +; * GNU General Public License for more details. +; * +; * You should have received a copy of the GNU General Public License along +; * with this program; if not, write to the Free Software Foundation, Inc., +; * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +; * +; * Change Logs: +; * Date Author Notes +; * 2011-08-14 weety copy from mini2440 +; */ +#define NOINT 0xC0 -/* - * rt_base_t rt_hw_interrupt_disable(); - */ -.globl rt_hw_interrupt_disable +;/* +; * rt_base_t rt_hw_interrupt_disable(); +; */ + .globl rt_hw_interrupt_disable rt_hw_interrupt_disable: - mrs r0, cpsr - orr r1, r0, #NOINT - msr cpsr_c, r1 - mov pc, lr + MRS R0, CPSR + ORR R1, R0, #NOINT + MSR CPSR_c, R1 + BX LR /* * void rt_hw_interrupt_enable(rt_base_t level); */ -.globl rt_hw_interrupt_enable + .globl rt_hw_interrupt_enable rt_hw_interrupt_enable: - msr cpsr, r0 - mov pc, lr + MSR CPSR, R0 + BX LR /* * void rt_hw_context_switch(rt_uint32 from, rt_uint32 to); * r0 --> from * r1 --> to */ -.globl rt_hw_context_switch + .globl rt_hw_context_switch rt_hw_context_switch: - stmfd sp!, {lr} @ push pc (lr should be pushed in place of PC) - stmfd sp!, {r0-r12, lr} @ push lr & register file - - mrs r4, cpsr - stmfd sp!, {r4} @ push cpsr - mrs r4, spsr - stmfd sp!, {r4} @ push spsr - - str sp, [r0] @ store sp in preempted tasks TCB - ldr sp, [r1] @ get new task stack pointer - - ldmfd sp!, {r4} @ pop new task spsr - msr spsr_cxsf, r4 - ldmfd sp!, {r4} @ pop new task cpsr - msr spsr_cxsf, r4 - - ldmfd sp!, {r0-r12, lr, pc}^ @ pop new task r0-r12, lr & pc + stmfd sp!, {lr} @; push pc (lr should be pushed in place of pc) + stmfd sp!, {r0-r12, lr} @; push lr & register file + mrs r4, cpsr + stmfd sp!, {r4} @; push cpsr + mrs r4, spsr + stmfd sp!, {r4} @; push spsr + str sp, [r0] @; store sp in preempted tasks tcb + ldr sp, [r1] @; get new task stack pointer + ldmfd sp!, {r4} @; pop new task spsr + msr spsr_cxsf, r4 + ldmfd sp!, {r4} @; pop new task cpsr + msr spsr_cxsf, r4 + ldmfd sp!, {r0-r12, lr, pc}^ @; pop new task r0-r12, lr & pc /* * void rt_hw_context_switch_to(rt_uint32 to); * r0 --> to */ -.globl rt_hw_context_switch_to + .globl rt_hw_context_switch_to rt_hw_context_switch_to: - ldr sp, [r0] @ get new task stack pointer - - ldmfd sp!, {r4} @ pop new task spsr - msr spsr_cxsf, r4 - ldmfd sp!, {r4} @ pop new task cpsr - msr cpsr_cxsf, r4 + ldr sp, [r0] @; get new task stack pointer - ldmfd sp!, {r0-r12, lr, pc} @ pop new task r0-r12, lr & pc + ldmfd sp!, {r4} @; pop new task spsr + msr spsr_cxsf, r4 + ldmfd sp!, {r4} @; pop new task cpsr + msr spsr_cxsf, r4 + ldmfd sp!, {r0-r12, lr, pc}^ @; pop new task r0-r12, lr & pc /* * void rt_hw_context_switch_interrupt(rt_uint32 from, rt_uint32 to); */ -.globl rt_thread_switch_interrupt_flag -.globl rt_interrupt_from_thread -.globl rt_interrupt_to_thread -.globl rt_hw_context_switch_interrupt + .globl rt_thread_switch_interrupt_flag + .globl rt_interrupt_from_thread + .globl rt_interrupt_to_thread + .globl rt_hw_context_switch_interrupt rt_hw_context_switch_interrupt: - ldr r2, =rt_thread_switch_interrupt_flag - ldr r3, [r2] - cmp r3, #1 - beq _reswitch - mov r3, #1 @ set rt_thread_switch_interrupt_flag to 1 - str r3, [r2] - ldr r2, =rt_interrupt_from_thread @ set rt_interrupt_from_thread - str r0, [r2] + LDR R2, =rt_thread_switch_interrupt_flag + LDR R3, [R2] + CMP R3, #1 + BEQ _reswitch + MOV R3, #1 @; set flag to 1 + STR R3, [R2] + LDR R2, =rt_interrupt_from_thread @; set rt_interrupt_from_thread + STR R0, [R2] _reswitch: - ldr r2, =rt_interrupt_to_thread @ set rt_interrupt_to_thread - str r1, [r2] - mov pc, lr + LDR R2, =rt_interrupt_to_thread @; set rt_interrupt_to_thread + STR R1, [R2] + BX LR diff --git a/libcpu/arm/arm926/context_iar.S b/libcpu/arm/arm926/context_iar.S new file mode 100644 index 0000000000..678c7bacff --- /dev/null +++ b/libcpu/arm/arm926/context_iar.S @@ -0,0 +1,103 @@ +;/* +; * File : context_iar.S +; * This file is part of RT-Thread RTOS +; * COPYRIGHT (C) 2006, RT-Thread Development Team +; * +; * This program is free software; you can redistribute it and/or modify +; * it under the terms of the GNU General Public License as published by +; * the Free Software Foundation; either version 2 of the License, or +; * (at your option) any later version. +; * +; * This program is distributed in the hope that it will be useful, +; * but WITHOUT ANY WARRANTY; without even the implied warranty of +; * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +; * GNU General Public License for more details. +; * +; * You should have received a copy of the GNU General Public License along +; * with this program; if not, write to the Free Software Foundation, Inc., +; * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +; * +; * Change Logs: +; * Date Author Notes +; * 2011-08-14 weety copy from mini2440 +; */ + +#define NOINT 0xc0 + + SECTION .text:CODE(6) +/* + * rt_base_t rt_hw_interrupt_disable(); + */ + PUBLIC rt_hw_interrupt_disable +rt_hw_interrupt_disable: + MRS R0, CPSR + ORR R1, R0, #NOINT + MSR CPSR_C, R1 + MOV PC, LR + +/* + * void rt_hw_interrupt_enable(rt_base_t level); + */ + PUBLIC rt_hw_interrupt_enable +rt_hw_interrupt_enable: + MSR CPSR_CXSF, R0 + MOV PC, LR + +/* + * void rt_hw_context_switch(rt_uint32 from, rt_uint32 to); + * r0 --> from + * r1 --> to + */ + PUBLIC rt_hw_context_switch +rt_hw_context_switch: + STMFD SP!, {LR} ; push pc (lr should be pushed in place of PC) + STMFD SP!, {R0-R12, LR} ; push lr & register file + MRS R4, CPSR + STMFD SP!, {R4} ; push cpsr + MRS R4, SPSR + STMFD SP!, {R4} ; push spsr + STR SP, [R0] ; store sp in preempted tasks TCB + LDR SP, [R1] ; get new task stack pointer + LDMFD SP!, {R4} ; pop new task spsr + MSR SPSR_cxsf, R4 + LDMFD SP!, {R4} ; pop new task cpsr + MSR SPSR_cxsf, R4 + LDMFD SP!, {R0-R12, LR, PC}^ ; pop new task r0-r12, lr & pc + +/* + * void rt_hw_context_switch_to(rt_uint32 to); + * r0 --> to + */ + PUBLIC rt_hw_context_switch_to +rt_hw_context_switch_to: + LDR SP, [R0] ; get new task stack pointer + + LDMFD SP!, {R4} ; pop new task spsr + MSR SPSR_cxsf, R4 + LDMFD SP!, {R4} ; pop new task cpsr + MSR SPSR_cxsf, R4 + + LDMFD SP!, {R0-R12, LR, PC}^ ; pop new task r0-r12, lr & pc + +/* + * void rt_hw_context_switch_interrupt(rt_uint32 from, rt_uint32 to); + */ + IMPORT rt_thread_switch_interrupt_flag + IMPORT rt_interrupt_from_thread + IMPORT rt_interrupt_to_thread + PUBLIC rt_hw_context_switch_interrupt +rt_hw_context_switch_interrupt: + LDR R2, =rt_thread_switch_interrupt_flag + LDR R3, [R2] + CMP R3, #1 + BEQ _reswitch + MOV R3, #1 ; set flag to 1 + STR R3, [R2] + LDR R2, =rt_interrupt_from_thread ; set rt_interrupt_from_thread + STR R0, [R2] +_reswitch: + LDR R2, =rt_interrupt_to_thread ; set rt_interrupt_to_thread + STR R1, [R2] + MOV PC, LR + END + diff --git a/libcpu/arm/arm926/context_rvds.S b/libcpu/arm/arm926/context_rvds.S index 631da83372..e5fda293df 100644 --- a/libcpu/arm/arm926/context_rvds.S +++ b/libcpu/arm/arm926/context_rvds.S @@ -1,117 +1,112 @@ ;/* -; * File : context_rvds.S -; * This file is part of RT-Thread RTOS -; * COPYRIGHT (C) 2006, RT-Thread Development Team +; * file : context_rvds.s +; * this file is part of rt-thread rtos +; * copyright (c) 2006, rt-thread development team ; * -; * This program is free software; you can redistribute it and/or modify -; * it under the terms of the GNU General Public License as published by -; * the Free Software Foundation; either version 2 of the License, or +; * this program is free software; you can redistribute it and/or modify +; * it under the terms of the gnu general public license as published by +; * the free software foundation; either version 2 of the license, or ; * (at your option) any later version. ; * -; * This program is distributed in the hope that it will be useful, -; * but WITHOUT ANY WARRANTY; without even the implied warranty of -; * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -; * GNU General Public License for more details. +; * this program is distributed in the hope that it will be useful, +; * but without any warranty; without even the implied warranty of +; * merchantability or fitness for a particular purpose. see the +; * gnu general public license for more details. ; * -; * You should have received a copy of the GNU General Public License along -; * with this program; if not, write to the Free Software Foundation, Inc., -; * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +; * you should have received a copy of the gnu general public license along +; * with this program; if not, write to the free software foundation, inc., +; * 51 franklin street, fifth floor, boston, ma 02110-1301 usa. ; * -; * Change Logs: -; * Date Author Notes +; * change logs: +; * date author notes ; * 2011-08-14 weety copy from mini2440 ; */ -NOINT EQU 0xc0 ; disable interrupt in psr +NOINT EQU 0XC0 ; disable interrupt in psr - AREA |.text|, CODE, READONLY, ALIGN=2 - ARM - REQUIRE8 - PRESERVE8 + AREA |.TEXT|, CODE, READONLY, ALIGN=2 + ARM + REQUIRE8 + PRESERVE8 ;/* ; * rt_base_t rt_hw_interrupt_disable(); ; */ -rt_hw_interrupt_disable PROC - EXPORT rt_hw_interrupt_disable - MRS r0, cpsr - ORR r1, r0, #NOINT - MSR cpsr_c, r1 - BX lr - ENDP +rt_hw_interrupt_disable PROC + EXPORT rt_hw_interrupt_disable + MRS R0, CPSR + ORR R1, R0, #NOINT + MSR CPSR_C, R1 + BX LR + ENDP ;/* ; * void rt_hw_interrupt_enable(rt_base_t level); ; */ -rt_hw_interrupt_enable PROC - EXPORT rt_hw_interrupt_enable - MSR cpsr_c, r0 - BX lr - ENDP +rt_hw_interrupt_enable proc + export rt_hw_interrupt_enable + msr cpsr_c, r0 + bx lr + endp ;/* ; * void rt_hw_context_switch(rt_uint32 from, rt_uint32 to); ; * r0 --> from ; * r1 --> to ; */ -rt_hw_context_switch PROC - EXPORT rt_hw_context_switch - STMFD sp!, {lr} ; push pc (lr should be pushed in place of PC) - STMFD sp!, {r0-r12, lr} ; push lr & register file - - MRS r4, cpsr - STMFD sp!, {r4} ; push cpsr - MRS r4, spsr - STMFD sp!, {r4} ; push spsr - - STR sp, [r0] ; store sp in preempted tasks TCB - LDR sp, [r1] ; get new task stack pointer - - LDMFD sp!, {r4} ; pop new task spsr - MSR spsr_cxsf, r4 - LDMFD sp!, {r4} ; pop new task cpsr - MSR spsr_cxsf, r4 - - LDMFD sp!, {r0-r12, lr, pc}^ ; pop new task r0-r12, lr & pc - ENDP +rt_hw_context_switch proc + export rt_hw_context_switch + stmfd sp!, {lr} ; push pc (lr should be pushed in place of pc) + stmfd sp!, {r0-r12, lr} ; push lr & register file + mrs r4, cpsr + stmfd sp!, {r4} ; push cpsr + mrs r4, spsr + stmfd sp!, {r4} ; push spsr + str sp, [r0] ; store sp in preempted tasks tcb + ldr sp, [r1] ; get new task stack pointer + ldmfd sp!, {r4} ; pop new task spsr + msr spsr_cxsf, r4 + ldmfd sp!, {r4} ; pop new task cpsr + msr spsr_cxsf, r4 + ldmfd sp!, {r0-r12, lr, pc}^ ; pop new task r0-r12, lr & pc + endp ;/* ; * void rt_hw_context_switch_to(rt_uint32 to); ; * r0 --> to ; */ -rt_hw_context_switch_to PROC - EXPORT rt_hw_context_switch_to - LDR sp, [r0] ; get new task stack pointer - - LDMFD sp!, {r4} ; pop new task spsr - MSR spsr_cxsf, r4 - LDMFD sp!, {r4} ; pop new task cpsr - MSR cpsr_cxsf, r4 +rt_hw_context_switch_to proc + export rt_hw_context_switch_to + ldr sp, [r0] ; get new task stack pointer - LDMFD sp!, {r0-r12, lr, pc} ; pop new task r0-r12, lr & pc - ENDP + ldmfd sp!, {r4} ; pop new task spsr + msr spsr_cxsf, r4 + ldmfd sp!, {r4} ; pop new task cpsr + msr spsr_cxsf, r4 + ldmfd sp!, {r0-r12, lr, pc}^ ; pop new task r0-r12, lr & pc + endp ;/* ; * void rt_hw_context_switch_interrupt(rt_uint32 from, rt_uint32 to); ; */ - IMPORT rt_thread_switch_interrupt_flag - IMPORT rt_interrupt_from_thread - IMPORT rt_interrupt_to_thread + import rt_thread_switch_interrupt_flag + import rt_interrupt_from_thread + import rt_interrupt_to_thread -rt_hw_context_switch_interrupt PROC - EXPORT rt_hw_context_switch_interrupt - LDR r2, =rt_thread_switch_interrupt_flag - LDR r3, [r2] - CMP r3, #1 - BEQ _reswitch - MOV r3, #1 ; set rt_thread_switch_interrupt_flag to 1 - STR r3, [r2] - LDR r2, =rt_interrupt_from_thread ; set rt_interrupt_from_thread - STR r0, [r2] +rt_hw_context_switch_interrupt proc + export rt_hw_context_switch_interrupt + ldr r2, =rt_thread_switch_interrupt_flag + ldr r3, [r2] + cmp r3, #1 + beq _reswitch + mov r3, #1 ; set flag to 1 + str r3, [r2] + ldr r2, =rt_interrupt_from_thread ; set rt_interrupt_from_thread + str r0, [r2] _reswitch - LDR r2, =rt_interrupt_to_thread ; set rt_interrupt_to_thread - STR r1, [r2] - BX lr - ENDP + ldr r2, =rt_interrupt_to_thread ; set rt_interrupt_to_thread + str r1, [r2] + bx lr + endp - END + end diff --git a/libcpu/arm/arm926/cpuport.c b/libcpu/arm/arm926/cpuport.c index 9908471a5c..fd707384f6 100644 --- a/libcpu/arm/arm926/cpuport.c +++ b/libcpu/arm/arm926/cpuport.c @@ -25,8 +25,8 @@ #include <rthw.h> #include <rtthread.h> -#define ICACHE_MASK (rt_uint32_t)(1 << 12) -#define DCACHE_MASK (rt_uint32_t)(1 << 2) +#define ICACHE_MASK (rt_uint32_t)(1 << 12) +#define DCACHE_MASK (rt_uint32_t)(1 << 2) extern void machine_reset(void); extern void machine_shutdown(void); @@ -34,70 +34,102 @@ extern void machine_shutdown(void); #ifdef __GNUC__ rt_inline rt_uint32_t cp15_rd(void) { - rt_uint32_t i; + rt_uint32_t i; - asm ("mrc p15, 0, %0, c1, c0, 0":"=r" (i)); - return i; + asm ("mrc p15, 0, %0, c1, c0, 0":"=r" (i)); + return i; } rt_inline void cache_enable(rt_uint32_t bit) { - __asm__ __volatile__( \ - "mrc p15,0,r0,c1,c0,0\n\t" \ - "orr r0,r0,%0\n\t" \ - "mcr p15,0,r0,c1,c0,0" \ - : \ - :"r" (bit) \ - :"memory"); + __asm__ __volatile__( \ + "mrc p15,0,r0,c1,c0,0\n\t" \ + "orr r0,r0,%0\n\t" \ + "mcr p15,0,r0,c1,c0,0" \ + : \ + :"r" (bit) \ + :"memory"); } rt_inline void cache_disable(rt_uint32_t bit) { - __asm__ __volatile__( \ - "mrc p15,0,r0,c1,c0,0\n\t" \ - "bic r0,r0,%0\n\t" \ - "mcr p15,0,r0,c1,c0,0" \ - : \ - :"r" (bit) \ - :"memory"); + __asm__ __volatile__( \ + "mrc p15,0,r0,c1,c0,0\n\t" \ + "bic r0,r0,%0\n\t" \ + "mcr p15,0,r0,c1,c0,0" \ + : \ + :"r" (bit) \ + :"memory"); } #endif #ifdef __CC_ARM rt_inline rt_uint32_t cp15_rd(void) { - rt_uint32_t i; + rt_uint32_t i; - __asm - { - mrc p15, 0, i, c1, c0, 0 - } + __asm + { + mrc p15, 0, i, c1, c0, 0 + } - return i; + return i; } rt_inline void cache_enable(rt_uint32_t bit) { - rt_uint32_t value; + rt_uint32_t value; - __asm - { - mrc p15, 0, value, c1, c0, 0 - orr value, value, bit - mcr p15, 0, value, c1, c0, 0 - } + __asm + { + mrc p15, 0, value, c1, c0, 0 + orr value, value, bit + mcr p15, 0, value, c1, c0, 0 + } } rt_inline void cache_disable(rt_uint32_t bit) { - rt_uint32_t value; + rt_uint32_t value; - __asm - { - mrc p15, 0, value, c1, c0, 0 - bic value, value, bit - mcr p15, 0, value, c1, c0, 0 - } + __asm + { + mrc p15, 0, value, c1, c0, 0 + bic value, value, bit + mcr p15, 0, value, c1, c0, 0 + } +} +#endif + +#ifdef __ICCARM__ +rt_inline rt_uint32_t cp15_rd(void) +{ + rt_uint32_t i; + + asm ("mrc p15, 0, %0, c1, c0, 0":"=r" (i)); + return i; +} + +rt_inline void cache_enable(rt_uint32_t bit) +{ + asm volatile( \ + "mrc p15,0,r0,c1,c0,0\n\t" \ + "orr r0,r0,%0\n\t" \ + "mcr p15,0,r0,c1,c0,0" \ + : \ + :"r" (bit) \ + :"memory"); +} + +rt_inline void cache_disable(rt_uint32_t bit) +{ + asm volatile( \ + "mrc p15,0,r0,c1,c0,0\n\t" \ + "bic r0,r0,%0\n\t" \ + "mcr p15,0,r0,c1,c0,0" \ + : \ + :"r" (bit) \ + :"memory"); } #endif @@ -107,7 +139,7 @@ rt_inline void cache_disable(rt_uint32_t bit) */ void rt_hw_cpu_icache_enable() { - cache_enable(ICACHE_MASK); + cache_enable(ICACHE_MASK); } /** @@ -116,7 +148,7 @@ void rt_hw_cpu_icache_enable() */ void rt_hw_cpu_icache_disable() { - cache_disable(ICACHE_MASK); + cache_disable(ICACHE_MASK); } /** @@ -125,7 +157,7 @@ void rt_hw_cpu_icache_disable() */ rt_base_t rt_hw_cpu_icache_status() { - return (cp15_rd() & ICACHE_MASK); + return (cp15_rd() & ICACHE_MASK); } /** @@ -134,7 +166,7 @@ rt_base_t rt_hw_cpu_icache_status() */ void rt_hw_cpu_dcache_enable() { - cache_enable(DCACHE_MASK); + cache_enable(DCACHE_MASK); } /** @@ -143,7 +175,7 @@ void rt_hw_cpu_dcache_enable() */ void rt_hw_cpu_dcache_disable() { - cache_disable(DCACHE_MASK); + cache_disable(DCACHE_MASK); } /** @@ -152,7 +184,7 @@ void rt_hw_cpu_dcache_disable() */ rt_base_t rt_hw_cpu_dcache_status() { - return (cp15_rd() & DCACHE_MASK); + return (cp15_rd() & DCACHE_MASK); } /** @@ -161,13 +193,13 @@ rt_base_t rt_hw_cpu_dcache_status() */ void rt_hw_cpu_reset() { - - rt_kprintf("Restarting system...\n"); - machine_reset(); + + rt_kprintf("Restarting system...\n"); + machine_reset(); - while(1); /* loop forever and wait for reset to happen */ + while(1); /* loop forever and wait for reset to happen */ - /* NEVER REACHED */ + /* NEVER REACHED */ } /** @@ -176,15 +208,15 @@ void rt_hw_cpu_reset() */ void rt_hw_cpu_shutdown() { - rt_uint32_t level; - rt_kprintf("shutdown...\n"); + rt_uint32_t level; + rt_kprintf("shutdown...\n"); - level = rt_hw_interrupt_disable(); - machine_shutdown(); - while (level) - { - RT_ASSERT(0); - } + level = rt_hw_interrupt_disable(); + machine_shutdown(); + while (level) + { + RT_ASSERT(0); + } } #ifdef RT_USING_CPU_FFS @@ -201,42 +233,42 @@ void rt_hw_cpu_shutdown() #if defined(__CC_ARM) int __rt_ffs(int value) { - register rt_uint32_t x; + register rt_uint32_t x; - if (value == 0) - return value; - - __asm - { - rsb x, value, #0 - and x, x, value - clz x, x - rsb x, x, #32 - } + if (value == 0) + return value; + + __asm + { + rsb x, value, #0 + and x, x, value + clz x, x + rsb x, x, #32 + } - return x; + return x; } #elif defined(__IAR_SYSTEMS_ICC__) int __rt_ffs(int value) { - if (value == 0) - return value; + if (value == 0) + return value; - __ASM("RSB r4, r0, #0"); - __ASM("AND r4, r4, r0"); - __ASM("CLZ r4, r4"); - __ASM("RSB r0, r4, #32"); + __ASM("RSB r4, r0, #0"); + __ASM("AND r4, r4, r0"); + __ASM("CLZ r4, r4"); + __ASM("RSB r0, r4, #32"); } #elif defined(__GNUC__) int __rt_ffs(int value) { - if (value == 0) - return value; + if (value == 0) + return value; - value &= (-value); - asm ("clz %0, %1": "=r"(value) :"r"(value)); + value &= (-value); + asm ("clz %0, %1": "=r"(value) :"r"(value)); - return (32 - value); + return (32 - value); } #endif diff --git a/libcpu/arm/arm926/mmu.c b/libcpu/arm/arm926/mmu.c index debb88f267..fa074e895f 100644 --- a/libcpu/arm/arm926/mmu.c +++ b/libcpu/arm/arm926/mmu.c @@ -26,22 +26,22 @@ #ifdef __CC_ARM void mmu_setttbase(rt_uint32_t i) { - register rt_uint32_t value; + register rt_uint32_t value; /* Invalidates all TLBs.Domain access is selected as * client by configuring domain access register, * in that case access controlled by permission value * set by page table entry */ - value = 0; + value = 0; __asm { mcr p15, 0, value, c8, c7, 0 - } + } - value = 0x55555555; - __asm - { + value = 0x55555555; + __asm + { mcr p15, 0, value, c3, c0, 0 mcr p15, 0, i, c2, c0, 0 } @@ -167,44 +167,44 @@ void mmu_clean_invalidated_dcache(rt_uint32_t buffer, rt_uint32_t size) while(ptr < buffer + size) { - __asm - { - MCR p15, 0, ptr, c7, c14, 1 - } + __asm + { + MCR p15, 0, ptr, c7, c14, 1 + } ptr += CACHE_LINE_SIZE; } } void mmu_clean_dcache(rt_uint32_t buffer, rt_uint32_t size) { - unsigned int ptr; + unsigned int ptr; - ptr = buffer & ~(CACHE_LINE_SIZE - 1); + ptr = buffer & ~(CACHE_LINE_SIZE - 1); - while (ptr < buffer + size) - { - __asm - { - MCR p15, 0, ptr, c7, c10, 1 - } - ptr += CACHE_LINE_SIZE; - } + while (ptr < buffer + size) + { + __asm + { + MCR p15, 0, ptr, c7, c10, 1 + } + ptr += CACHE_LINE_SIZE; + } } void mmu_invalidate_dcache(rt_uint32_t buffer, rt_uint32_t size) { - unsigned int ptr; + unsigned int ptr; - ptr = buffer & ~(CACHE_LINE_SIZE - 1); + ptr = buffer & ~(CACHE_LINE_SIZE - 1); - while (ptr < buffer + size) - { - __asm - { - MCR p15, 0, ptr, c7, c6, 1 - } - ptr += CACHE_LINE_SIZE; - } + while (ptr < buffer + size) + { + __asm + { + MCR p15, 0, ptr, c7, c6, 1 + } + ptr += CACHE_LINE_SIZE; + } } void mmu_invalidate_tlb() @@ -245,133 +245,319 @@ void mmu_invalidate_dcache_all() #elif defined(__GNUC__) void mmu_setttbase(register rt_uint32_t i) { - register rt_uint32_t value; + register rt_uint32_t value; + + /* Invalidates all TLBs.Domain access is selected as + * client by configuring domain access register, + * in that case access controlled by permission value + * set by page table entry + */ + value = 0; + asm ("mcr p15, 0, %0, c8, c7, 0"::"r"(value)); + + value = 0x55555555; + asm ("mcr p15, 0, %0, c3, c0, 0"::"r"(value)); + asm ("mcr p15, 0, %0, c2, c0, 0"::"r"(i)); +} + +void mmu_set_domain(register rt_uint32_t i) +{ + asm ("mcr p15,0, %0, c3, c0, 0": :"r" (i)); +} + +void mmu_enable() +{ + register rt_uint32_t i; + + /* read control register */ + asm ("mrc p15, 0, %0, c1, c0, 0":"=r" (i)); + + i |= 0x1; + + /* write back to control register */ + asm ("mcr p15, 0, %0, c1, c0, 0": :"r" (i)); +} + +void mmu_disable() +{ + register rt_uint32_t i; + + /* read control register */ + asm ("mrc p15, 0, %0, c1, c0, 0":"=r" (i)); + + i &= ~0x1; + + /* write back to control register */ + asm ("mcr p15, 0, %0, c1, c0, 0": :"r" (i)); +} + +void mmu_enable_icache() +{ + register rt_uint32_t i; + + /* read control register */ + asm ("mrc p15, 0, %0, c1, c0, 0":"=r" (i)); + + i |= (1 << 12); + + /* write back to control register */ + asm ("mcr p15, 0, %0, c1, c0, 0": :"r" (i)); +} + +void mmu_enable_dcache() +{ + register rt_uint32_t i; + + /* read control register */ + asm ("mrc p15, 0, %0, c1, c0, 0":"=r" (i)); + + i |= (1 << 2); + + /* write back to control register */ + asm ("mcr p15, 0, %0, c1, c0, 0": :"r" (i)); +} + +void mmu_disable_icache() +{ + register rt_uint32_t i; + + /* read control register */ + asm ("mrc p15, 0, %0, c1, c0, 0":"=r" (i)); + + i &= ~(1 << 12); + + /* write back to control register */ + asm ("mcr p15, 0, %0, c1, c0, 0": :"r" (i)); +} + +void mmu_disable_dcache() +{ + register rt_uint32_t i; + + /* read control register */ + asm ("mrc p15, 0, %0, c1, c0, 0":"=r" (i)); + + i &= ~(1 << 2); + + /* write back to control register */ + asm ("mcr p15, 0, %0, c1, c0, 0": :"r" (i)); +} + +void mmu_enable_alignfault() +{ + register rt_uint32_t i; + + /* read control register */ + asm ("mrc p15, 0, %0, c1, c0, 0":"=r" (i)); + + i |= (1 << 1); + + /* write back to control register */ + asm ("mcr p15, 0, %0, c1, c0, 0": :"r" (i)); +} + +void mmu_disable_alignfault() +{ + register rt_uint32_t i; + + /* read control register */ + asm ("mrc p15, 0, %0, c1, c0, 0":"=r" (i)); + + i &= ~(1 << 1); + + /* write back to control register */ + asm ("mcr p15, 0, %0, c1, c0, 0": :"r" (i)); +} + +void mmu_clean_invalidated_cache_index(int index) +{ + asm ("mcr p15, 0, %0, c7, c14, 2": :"r" (index)); +} + +void mmu_clean_invalidated_dcache(rt_uint32_t buffer, rt_uint32_t size) +{ + unsigned int ptr; + + ptr = buffer & ~(CACHE_LINE_SIZE - 1); + + while(ptr < buffer + size) + { + asm ("mcr p15, 0, %0, c7, c14, 1": :"r" (ptr)); + ptr += CACHE_LINE_SIZE; + } +} + + +void mmu_clean_dcache(rt_uint32_t buffer, rt_uint32_t size) +{ + unsigned int ptr; + + ptr = buffer & ~(CACHE_LINE_SIZE - 1); + + while (ptr < buffer + size) + { + asm ("mcr p15, 0, %0, c7, c10, 1": :"r" (ptr)); + ptr += CACHE_LINE_SIZE; + } +} + +void mmu_invalidate_dcache(rt_uint32_t buffer, rt_uint32_t size) +{ + unsigned int ptr; + + ptr = buffer & ~(CACHE_LINE_SIZE - 1); + + while (ptr < buffer + size) + { + asm ("mcr p15, 0, %0, c7, c6, 1": :"r" (ptr)); + ptr += CACHE_LINE_SIZE; + } +} + +void mmu_invalidate_tlb() +{ + asm ("mcr p15, 0, %0, c8, c7, 0": :"r" (0)); +} + +void mmu_invalidate_icache() +{ + asm ("mcr p15, 0, %0, c7, c5, 0": :"r" (0)); +} + +void mmu_invalidate_dcache_all() +{ + asm ("mcr p15, 0, %0, c7, c6, 0": :"r" (0)); +} +#elif defined(__ICCARM__) +void mmu_setttbase(register rt_uint32_t i) +{ + register rt_uint32_t value; /* Invalidates all TLBs.Domain access is selected as * client by configuring domain access register, * in that case access controlled by permission value * set by page table entry */ - value = 0; - asm ("mcr p15, 0, %0, c8, c7, 0"::"r"(value)); + value = 0; + asm ("mcr p15, 0, %0, c8, c7, 0"::"r"(value)); - value = 0x55555555; - asm ("mcr p15, 0, %0, c3, c0, 0"::"r"(value)); - asm ("mcr p15, 0, %0, c2, c0, 0"::"r"(i)); + value = 0x55555555; + asm ("mcr p15, 0, %0, c3, c0, 0"::"r"(value)); + asm ("mcr p15, 0, %0, c2, c0, 0"::"r"(i)); } void mmu_set_domain(register rt_uint32_t i) { - asm ("mcr p15,0, %0, c3, c0, 0": :"r" (i)); + asm ("mcr p15,0, %0, c3, c0, 0": :"r" (i)); } void mmu_enable() { - register rt_uint32_t i; + register rt_uint32_t i; - /* read control register */ - asm ("mrc p15, 0, %0, c1, c0, 0":"=r" (i)); + /* read control register */ + asm ("mrc p15, 0, %0, c1, c0, 0":"=r" (i)); - i |= 0x1; + i |= 0x1; - /* write back to control register */ - asm ("mcr p15, 0, %0, c1, c0, 0": :"r" (i)); + /* write back to control register */ + asm ("mcr p15, 0, %0, c1, c0, 0": :"r" (i)); } void mmu_disable() { - register rt_uint32_t i; + register rt_uint32_t i; - /* read control register */ - asm ("mrc p15, 0, %0, c1, c0, 0":"=r" (i)); + /* read control register */ + asm ("mrc p15, 0, %0, c1, c0, 0":"=r" (i)); - i &= ~0x1; + i &= ~0x1; - /* write back to control register */ - asm ("mcr p15, 0, %0, c1, c0, 0": :"r" (i)); + /* write back to control register */ + asm ("mcr p15, 0, %0, c1, c0, 0": :"r" (i)); } void mmu_enable_icache() { - register rt_uint32_t i; + register rt_uint32_t i; - /* read control register */ - asm ("mrc p15, 0, %0, c1, c0, 0":"=r" (i)); + /* read control register */ + asm ("mrc p15, 0, %0, c1, c0, 0":"=r" (i)); - i |= (1 << 12); + i |= (1 << 12); - /* write back to control register */ - asm ("mcr p15, 0, %0, c1, c0, 0": :"r" (i)); + /* write back to control register */ + asm ("mcr p15, 0, %0, c1, c0, 0": :"r" (i)); } void mmu_enable_dcache() { - register rt_uint32_t i; + register rt_uint32_t i; - /* read control register */ - asm ("mrc p15, 0, %0, c1, c0, 0":"=r" (i)); + /* read control register */ + asm ("mrc p15, 0, %0, c1, c0, 0":"=r" (i)); - i |= (1 << 2); + i |= (1 << 2); - /* write back to control register */ - asm ("mcr p15, 0, %0, c1, c0, 0": :"r" (i)); + /* write back to control register */ + asm ("mcr p15, 0, %0, c1, c0, 0": :"r" (i)); } void mmu_disable_icache() { - register rt_uint32_t i; + register rt_uint32_t i; - /* read control register */ - asm ("mrc p15, 0, %0, c1, c0, 0":"=r" (i)); + /* read control register */ + asm ("mrc p15, 0, %0, c1, c0, 0":"=r" (i)); - i &= ~(1 << 12); + i &= ~(1 << 12); - /* write back to control register */ - asm ("mcr p15, 0, %0, c1, c0, 0": :"r" (i)); + /* write back to control register */ + asm ("mcr p15, 0, %0, c1, c0, 0": :"r" (i)); } void mmu_disable_dcache() { - register rt_uint32_t i; + register rt_uint32_t i; - /* read control register */ - asm ("mrc p15, 0, %0, c1, c0, 0":"=r" (i)); + /* read control register */ + asm ("mrc p15, 0, %0, c1, c0, 0":"=r" (i)); - i &= ~(1 << 2); + i &= ~(1 << 2); - /* write back to control register */ - asm ("mcr p15, 0, %0, c1, c0, 0": :"r" (i)); + /* write back to control register */ + asm ("mcr p15, 0, %0, c1, c0, 0": :"r" (i)); } void mmu_enable_alignfault() { - register rt_uint32_t i; + register rt_uint32_t i; - /* read control register */ - asm ("mrc p15, 0, %0, c1, c0, 0":"=r" (i)); + /* read control register */ + asm ("mrc p15, 0, %0, c1, c0, 0":"=r" (i)); - i |= (1 << 1); + i |= (1 << 1); - /* write back to control register */ - asm ("mcr p15, 0, %0, c1, c0, 0": :"r" (i)); + /* write back to control register */ + asm ("mcr p15, 0, %0, c1, c0, 0": :"r" (i)); } void mmu_disable_alignfault() { - register rt_uint32_t i; + register rt_uint32_t i; - /* read control register */ - asm ("mrc p15, 0, %0, c1, c0, 0":"=r" (i)); + /* read control register */ + asm ("mrc p15, 0, %0, c1, c0, 0":"=r" (i)); - i &= ~(1 << 1); + i &= ~(1 << 1); - /* write back to control register */ - asm ("mcr p15, 0, %0, c1, c0, 0": :"r" (i)); + /* write back to control register */ + asm ("mcr p15, 0, %0, c1, c0, 0": :"r" (i)); } void mmu_clean_invalidated_cache_index(int index) { - asm ("mcr p15, 0, %0, c7, c14, 2": :"r" (index)); + asm ("mcr p15, 0, %0, c7, c14, 2": :"r" (index)); } void mmu_clean_invalidated_dcache(rt_uint32_t buffer, rt_uint32_t size) @@ -382,7 +568,7 @@ void mmu_clean_invalidated_dcache(rt_uint32_t buffer, rt_uint32_t size) while(ptr < buffer + size) { - asm ("mcr p15, 0, %0, c7, c14, 1": :"r" (ptr)); + asm ("mcr p15, 0, %0, c7, c14, 1": :"r" (ptr)); ptr += CACHE_LINE_SIZE; } } @@ -390,38 +576,38 @@ void mmu_clean_invalidated_dcache(rt_uint32_t buffer, rt_uint32_t size) void mmu_clean_dcache(rt_uint32_t buffer, rt_uint32_t size) { - unsigned int ptr; + unsigned int ptr; - ptr = buffer & ~(CACHE_LINE_SIZE - 1); + ptr = buffer & ~(CACHE_LINE_SIZE - 1); - while (ptr < buffer + size) - { - asm ("mcr p15, 0, %0, c7, c10, 1": :"r" (ptr)); - ptr += CACHE_LINE_SIZE; - } + while (ptr < buffer + size) + { + asm ("mcr p15, 0, %0, c7, c10, 1": :"r" (ptr)); + ptr += CACHE_LINE_SIZE; + } } void mmu_invalidate_dcache(rt_uint32_t buffer, rt_uint32_t size) { - unsigned int ptr; + unsigned int ptr; - ptr = buffer & ~(CACHE_LINE_SIZE - 1); + ptr = buffer & ~(CACHE_LINE_SIZE - 1); - while (ptr < buffer + size) - { - asm ("mcr p15, 0, %0, c7, c6, 1": :"r" (ptr)); - ptr += CACHE_LINE_SIZE; - } + while (ptr < buffer + size) + { + asm ("mcr p15, 0, %0, c7, c6, 1": :"r" (ptr)); + ptr += CACHE_LINE_SIZE; + } } void mmu_invalidate_tlb() { - asm ("mcr p15, 0, %0, c8, c7, 0": :"r" (0)); + asm ("mcr p15, 0, %0, c8, c7, 0": :"r" (0)); } void mmu_invalidate_icache() { - asm ("mcr p15, 0, %0, c7, c5, 0": :"r" (0)); + asm ("mcr p15, 0, %0, c7, c5, 0": :"r" (0)); } void mmu_invalidate_dcache_all() @@ -431,38 +617,44 @@ void mmu_invalidate_dcache_all() #endif /* level1 page table */ +#if defined(__ICCARM__) +#pragma data_alignment=(16*1024) +static volatile unsigned int _page_table[4*1024];; +#else static volatile unsigned int _page_table[4*1024] __attribute__((aligned(16*1024))); +#endif void mmu_setmtt(rt_uint32_t vaddrStart, rt_uint32_t vaddrEnd, rt_uint32_t paddrStart, rt_uint32_t attr) { volatile rt_uint32_t *pTT; - volatile int i,nSec; + volatile int nSec; + int i = 0; pTT=(rt_uint32_t *)_page_table+(vaddrStart>>20); nSec=(vaddrEnd>>20)-(vaddrStart>>20); for(i=0;i<=nSec;i++) { - *pTT = attr |(((paddrStart>>20)+i)<<20); - pTT++; + *pTT = attr |(((paddrStart>>20)+i)<<20); + pTT++; } } void rt_hw_mmu_init(struct mem_desc *mdesc, rt_uint32_t size) { - /* disable I/D cache */ - mmu_disable_dcache(); - mmu_disable_icache(); - mmu_disable(); - mmu_invalidate_tlb(); + /* disable I/D cache */ + mmu_disable_dcache(); + mmu_disable_icache(); + mmu_disable(); + mmu_invalidate_tlb(); - /* set page table */ - for (; size > 0; size--) - { - mmu_setmtt(mdesc->vaddr_start, mdesc->vaddr_end, - mdesc->paddr_start, mdesc->attr); - mdesc++; - } + /* set page table */ + for (; size > 0; size--) + { + mmu_setmtt(mdesc->vaddr_start, mdesc->vaddr_end, + mdesc->paddr_start, mdesc->attr); + mdesc++; + } - /* set MMU table address */ - mmu_setttbase((rt_uint32_t)_page_table); + /* set MMU table address */ + mmu_setttbase((rt_uint32_t)_page_table); /* enables MMU */ mmu_enable(); diff --git a/libcpu/arm/arm926/mmu.h b/libcpu/arm/arm926/mmu.h index d6c497efb9..adbfe95934 100644 --- a/libcpu/arm/arm926/mmu.h +++ b/libcpu/arm/arm926/mmu.h @@ -26,35 +26,35 @@ #include <rtthread.h> -#define CACHE_LINE_SIZE 32 +#define CACHE_LINE_SIZE 32 -#define DESC_SEC (0x2|(1<<4)) -#define CB (3<<2) //cache_on, write_back -#define CNB (2<<2) //cache_on, write_through -#define NCB (1<<2) //cache_off,WR_BUF on -#define NCNB (0<<2) //cache_off,WR_BUF off -#define AP_RW (3<<10) //supervisor=RW, user=RW -#define AP_RO (2<<10) //supervisor=RW, user=RO +#define DESC_SEC (0x2|(1<<4)) +#define CB (3<<2) //cache_on, write_back +#define CNB (2<<2) //cache_on, write_through +#define NCB (1<<2) //cache_off,WR_BUF on +#define NCNB (0<<2) //cache_off,WR_BUF off +#define AP_RW (3<<10) //supervisor=RW, user=RW +#define AP_RO (2<<10) //supervisor=RW, user=RO -#define DOMAIN_FAULT (0x0) -#define DOMAIN_CHK (0x1) -#define DOMAIN_NOTCHK (0x3) -#define DOMAIN0 (0x0<<5) -#define DOMAIN1 (0x1<<5) +#define DOMAIN_FAULT (0x0) +#define DOMAIN_CHK (0x1) +#define DOMAIN_NOTCHK (0x3) +#define DOMAIN0 (0x0<<5) +#define DOMAIN1 (0x1<<5) -#define DOMAIN0_ATTR (DOMAIN_CHK<<0) -#define DOMAIN1_ATTR (DOMAIN_FAULT<<2) +#define DOMAIN0_ATTR (DOMAIN_CHK<<0) +#define DOMAIN1_ATTR (DOMAIN_FAULT<<2) -#define RW_CB (AP_RW|DOMAIN0|CB|DESC_SEC) /* Read/Write, cache, write back */ -#define RW_CNB (AP_RW|DOMAIN0|CNB|DESC_SEC) /* Read/Write, cache, write through */ -#define RW_NCNB (AP_RW|DOMAIN0|NCNB|DESC_SEC) /* Read/Write without cache and write buffer */ -#define RW_FAULT (AP_RW|DOMAIN1|NCNB|DESC_SEC) /* Read/Write without cache and write buffer */ +#define RW_CB (AP_RW|DOMAIN0|CB|DESC_SEC) /* Read/Write, cache, write back */ +#define RW_CNB (AP_RW|DOMAIN0|CNB|DESC_SEC) /* Read/Write, cache, write through */ +#define RW_NCNB (AP_RW|DOMAIN0|NCNB|DESC_SEC) /* Read/Write without cache and write buffer */ +#define RW_FAULT (AP_RW|DOMAIN1|NCNB|DESC_SEC) /* Read/Write without cache and write buffer */ struct mem_desc { - rt_uint32_t vaddr_start; - rt_uint32_t vaddr_end; - rt_uint32_t paddr_start; - rt_uint32_t attr; + rt_uint32_t vaddr_start; + rt_uint32_t vaddr_end; + rt_uint32_t paddr_start; + rt_uint32_t attr; }; void rt_hw_mmu_init(struct mem_desc *mdesc, rt_uint32_t size); diff --git a/libcpu/arm/arm926/stack.c b/libcpu/arm/arm926/stack.c index f58b43cbd4..b9bb3c8508 100644 --- a/libcpu/arm/arm926/stack.c +++ b/libcpu/arm/arm926/stack.c @@ -26,14 +26,14 @@ /*****************************/ /* CPU Mode */ /*****************************/ -#define USERMODE 0x10 -#define FIQMODE 0x11 -#define IRQMODE 0x12 -#define SVCMODE 0x13 -#define ABORTMODE 0x17 -#define UNDEFMODE 0x1b -#define MODEMASK 0x1f -#define NOINT 0xc0 +#define USERMODE 0x10 +#define FIQMODE 0x11 +#define IRQMODE 0x12 +#define SVCMODE 0x13 +#define ABORTMODE 0x17 +#define UNDEFMODE 0x1b +#define MODEMASK 0x1f +#define NOINT 0xc0 /** * This function will initialize thread stack @@ -46,30 +46,30 @@ * @return stack address */ rt_uint8_t *rt_hw_stack_init(void *tentry, void *parameter, - rt_uint8_t *stack_addr, void *texit) + rt_uint8_t *stack_addr, void *texit) { - rt_uint32_t *stk; + rt_uint32_t *stk; - stk = (rt_uint32_t*)stack_addr; - *(stk) = (rt_uint32_t)tentry; /* entry point */ - *(--stk) = (rt_uint32_t)texit; /* lr */ - *(--stk) = 0; /* r12 */ - *(--stk) = 0; /* r11 */ - *(--stk) = 0; /* r10 */ - *(--stk) = 0; /* r9 */ - *(--stk) = 0; /* r8 */ - *(--stk) = 0; /* r7 */ - *(--stk) = 0; /* r6 */ - *(--stk) = 0; /* r5 */ - *(--stk) = 0; /* r4 */ - *(--stk) = 0; /* r3 */ - *(--stk) = 0; /* r2 */ - *(--stk) = 0; /* r1 */ - *(--stk) = (rt_uint32_t)parameter; /* r0 : argument */ - *(--stk) = SVCMODE; /* cpsr */ - *(--stk) = SVCMODE; /* spsr */ + stk = (rt_uint32_t*)stack_addr; + *(stk) = (rt_uint32_t)tentry; /* entry point */ + *(--stk) = (rt_uint32_t)texit; /* lr */ + *(--stk) = 0; /* r12 */ + *(--stk) = 0; /* r11 */ + *(--stk) = 0; /* r10 */ + *(--stk) = 0; /* r9 */ + *(--stk) = 0; /* r8 */ + *(--stk) = 0; /* r7 */ + *(--stk) = 0; /* r6 */ + *(--stk) = 0; /* r5 */ + *(--stk) = 0; /* r4 */ + *(--stk) = 0; /* r3 */ + *(--stk) = 0; /* r2 */ + *(--stk) = 0; /* r1 */ + *(--stk) = (rt_uint32_t)parameter; /* r0 : argument */ + *(--stk) = SVCMODE; /* cpsr */ + *(--stk) = SVCMODE; /* spsr */ - /* return task's current stack address */ - return (rt_uint8_t *)stk; + /* return task's current stack address */ + return (rt_uint8_t *)stk; } diff --git a/libcpu/arm/arm926/start_gcc.S b/libcpu/arm/arm926/start_gcc.S new file mode 100644 index 0000000000..b6377ed676 --- /dev/null +++ b/libcpu/arm/arm926/start_gcc.S @@ -0,0 +1,327 @@ +/* + * File : start.S + * This file is part of RT-Thread RTOS + * COPYRIGHT (C) 2006, RT-Thread Development Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Change Logs: + * Date Author Notes + * 2011-01-13 weety first version + */ +#define CONFIG_STACKSIZE 512 +#define S_FRAME_SIZE (18*4) //72 + +@#define S_SPSR (17*4) //SPSR +@#define S_CPSR (16*4) //CPSR +#define S_PC (15*4) //R15 +@#define S_LR (14*4) //R14 +@#define S_SP (13*4) //R13 + +@#define S_IP (12*4) //R12 +@#define S_FP (11*4) //R11 +@#define S_R10 (10*4) +@#define S_R9 (9*4) +@#define S_R8 (8*4) +@#define S_R7 (7*4) +@#define S_R6 (6*4) +@#define S_R5 (5*4) +@#define S_R4 (4*4) +@#define S_R3 (3*4) +@#define S_R2 (2*4) +@#define S_R1 (1*4) +@#define S_R0 (0*4) + +#define MODE_SYS 0x1F +#define MODE_FIQ 0x11 +#define MODE_IRQ 0x12 +#define MODE_SVC 0x13 +#define MODE_ABT 0x17 +#define MODE_UND 0x1B +#define MODEMASK 0x1F +#define NOINT 0xC0 + +.include "rt_low_level_gcc.inc" + +@; stack table----------------------------------------------------------------- + .section .nobss, "w" + + .space UND_STK_SIZE + .global UND_STACK_START +UND_STACK_START: + + .space SVC_STK_SIZE + .align 2 + .global SVC_STACK_START +SVC_STACK_START: + + .space ABT_STK_SIZE + .align 2 + .global ABT_STACK_START +ABT_STACK_START: + + .space IRQ_STK_SIZE + .align 2 + .global IRQ_STACK_START +IRQ_STACK_START: + + .space FIQ_STK_SIZE + .align 2 + .global FIQ_STACK_START +FIQ_STACK_START: + + .skip SYS_STK_SIZE + .align 2 + .global SYS_STACK_START +SYS_STACK_START: + + +@; Jump vector table----------------------------------------------------------- + + .section .init, "ax" + .arm + + .global entry +entry: + LDR PC, vector_reset + LDR PC, vector_undef + LDR PC, vector_swi + LDR PC, vector_pabt + LDR PC, vector_dabt + LDR PC, vector_resv + LDR PC, vector_irq + LDR PC, vector_fiq + +vector_reset: + .word Reset_Handler +vector_undef: + .word Undef_Handler +vector_swi: + .word SWI_Handler +vector_pabt: + .word PAbt_Handler +vector_dabt: + .word DAbt_Handler +vector_resv: + .word Resv_Handler +vector_irq: + .word IRQ_Handler +vector_fiq: + .word FIQ_Handler + + .balignl 16,0xdeadbeef + +@;----------------- Reset Handler --------------------------------------------- + .global rt_low_level_init + .global main + .global Reset_Handler +Reset_Handler: + @; Set the cpu to SVC32 mode + MRS R0, CPSR + BIC R0, R0, #MODEMASK + ORR R0, R0, #MODE_SVC|NOINT + MSR CPSR, R0 + LDR SP, =SVC_STACK_START + + @; Call low level init function, + @; disable and clear all IRQs and remap internal ram to 0x00000000. + LDR R0, =rt_low_level_init + BLX R0 + + @; Copy Exception Vectors to Internal RAM + LDR R8, =entry @; Source + LDR R9, =0x00000000 @; Destination + CMP R8, R9 + BEQ Setup_Stack + LDMIA R8!, {R0-R7} @; Load Vectors + STMIA R9!, {R0-R7} @; Store Vectors + LDMIA R8!, {R0-R7} @; Load Handler Addresses + STMIA R9!, {R0-R7} @; Store Handler Addresses + +Setup_Stack: + @; Setup Stack for each mode + MRS R0, CPSR + BIC R0, R0, #MODEMASK + + ORR R1, R0, #MODE_UND|NOINT + MSR CPSR_cxsf, R1 @; Undef mode + LDR SP, =UND_STACK_START + + ORR R1, R0, #MODE_ABT|NOINT + MSR CPSR_cxsf, R1 @; Abort mode + LDR SP, =ABT_STACK_START + + ORR R1, R0, #MODE_IRQ|NOINT + MSR CPSR_cxsf, R1 @; IRQ mode + LDR SP, =IRQ_STACK_START + + ORR R1, R0, #MODE_FIQ|NOINT + MSR CPSR_cxsf, R1 @; FIQ mode + LDR SP, =FIQ_STACK_START + + ORR R1, R0, #MODE_SYS|NOINT + MSR CPSR_cxsf,R1 @; SYS/User mode + LDR SP, =SYS_STACK_START + + ORR R1, R0, #MODE_SVC|NOINT + MSR CPSR_cxsf, R1 @; SVC mode + LDR SP, =SVC_STACK_START + + + @; clear .bss + MOV R0, #0 @; get a zero + LDR R1, =__bss_start__ @; bss start + LDR R2, =__bss_end__ @; bss end + +bss_clear_loop: + CMP R1, R2 @; check if data to clear + STRLO R0, [R1], #4 @; clear 4 bytes + BLO bss_clear_loop @; loop until done + + @; call C++ constructors of global objects + LDR R0, =__ctors_start__ + LDR R1, =__ctors_end__ + +ctor_loop: + CMP R0, R1 + BEQ ctor_end + LDR R2, [R0], #4 + STMFD SP!, {R0-R1} + MOV LR, PC + BX R2 + LDMFD SP!, {R0-R1} + B ctor_loop + +ctor_end: + @; Enter the C code + LDR R0, =main + BLX R0 + +@;----------------- Exception Handler ----------------------------------------- + .global rt_hw_trap_udef + .global rt_hw_trap_swi + .global rt_hw_trap_pabt + .global rt_hw_trap_dabt + .global rt_hw_trap_resv + .global rt_hw_trap_irq + .global rt_hw_trap_fiq + + .global rt_interrupt_enter + .global rt_interrupt_leave + .global rt_thread_switch_interrupt_flag + .global rt_interrupt_from_thread + .global rt_interrupt_to_thread + + .align 5 +Undef_Handler: + SUB SP, SP, #S_FRAME_SIZE + STMIA SP, {R0 - R12} @; Calling R0-R12 + ADD R8, SP, #S_PC + STMDB R8, {SP, LR} @; Calling SP, LR + STR LR, [R8, #0] @; Save calling PC + MRS R6, SPSR + STR R6, [R8, #4] @; Save CPSR + STR R0, [R8, #8] @; Save SPSR + MOV R0, SP + BL rt_hw_trap_udef + + .align 5 +SWI_Handler: + BL rt_hw_trap_swi + + .align 5 +PAbt_Handler: + BL rt_hw_trap_pabt + + .align 5 +DAbt_Handler: + SUB SP, SP, #S_FRAME_SIZE + STMIA SP, {R0 - R12} @; Calling R0-R12 + ADD R8, SP, #S_PC + STMDB R8, {SP, LR} @; Calling SP, LR + STR LR, [R8, #0] @; Save calling PC + MRS R6, SPSR + STR R6, [R8, #4] @; Save CPSR + STR R0, [R8, #8] @; Save SPSR + MOV R0, SP + BL rt_hw_trap_dabt + + .align 5 +Resv_Handler: + BL rt_hw_trap_resv + + .align 5 +FIQ_Handler: + STMFD SP!, {R0-R7,LR} + BL rt_hw_trap_fiq + LDMFD SP!, {R0-R7,LR} + SUBS PC, LR, #4 + + .align 5 +IRQ_Handler: + STMFD SP!, {R0-R12,LR} + BL rt_interrupt_enter + BL rt_hw_trap_irq + BL rt_interrupt_leave + + @; If rt_thread_switch_interrupt_flag set, + @; jump to rt_hw_context_switch_interrupt_do and don't return + LDR R0, =rt_thread_switch_interrupt_flag + LDR R1, [R0] + CMP R1, #1 + BEQ rt_hw_context_switch_interrupt_do + + LDMFD SP!, {R0-R12,LR} + SUBS PC, LR, #4 + +@;------ void rt_hw_context_switch_interrupt_do(rt_base_t flag) ----------------- +rt_hw_context_switch_interrupt_do: + MOV R1, #0 @; Clear flag + STR R1, [R0] @; Save to flag variable + + LDMFD SP!, {R0-R12,LR} @; Reload saved registers + STMFD SP!, {R0-R3} @; Save R0-R3 + MOV R1, SP @; Save old task's SP to R1 + ADD SP, SP, #16 @; Restore SP + SUB R2, LR, #4 @; Save old task's PC to R2 + + MRS R3, SPSR @; Get CPSR of interrupt thread + + MSR CPSR_c, #MODE_SVC|NOINT @; Switch to SVC mode and no interrupt + + STMFD SP!, {R2} @; Push old task's PC + STMFD SP!, {R4-R12,LR} @; Push old task's LR,R12-R4 + MOV R4, R1 @; Special optimised code below + MOV R5, R3 + LDMFD R4!, {R0-R3} + STMFD SP!, {R0-R3} @; Push old task's R3-R0 + STMFD SP!, {R5} @; Push old task's CPSR + MRS R4, SPSR + STMFD SP!, {R4} @; Push old task's SPSR + + LDR R4, =rt_interrupt_from_thread + LDR R5, [R4] @; R5 = stack ptr in old tasks's TCB + STR SP, [R5] @; Store SP in preempted tasks's TCB + + LDR R6, =rt_interrupt_to_thread + LDR R6, [R6] @; R6 = stack ptr in new tasks's TCB + LDR SP, [R6] @; Get new task's stack pointer + + LDMFD SP!, {R4} @; Pop new task's SPSR + MSR SPSR_cxsf, R4 + LDMFD SP!, {R4} @; Pop new task's CPSR + MSR SPSR_cxsf, R4 + + LDMFD SP!, {R0-R12,LR,PC}^ @; pop new task's R0-R12,LR & PC diff --git a/libcpu/arm/arm926/start_iar.S b/libcpu/arm/arm926/start_iar.S new file mode 100644 index 0000000000..1f516462b2 --- /dev/null +++ b/libcpu/arm/arm926/start_iar.S @@ -0,0 +1,296 @@ +;/* +; * File : start.S +; * This file is part of RT-Thread RTOS +; * COPYRIGHT (C) 2006, RT-Thread Development Team +; * +; * This program is free software; you can redistribute it and/or modify +; * it under the terms of the GNU General Public License as published by +; * the Free Software Foundation; either version 2 of the License, or +; * (at your option) any later version. +; * +; * This program is distributed in the hope that it will be useful, +; * but WITHOUT ANY WARRANTY; without even the implied warranty of +; * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +; * GNU General Public License for more details. +; * +; * You should have received a copy of the GNU General Public License along +; * with this program; if not, write to the Free Software Foundation, Inc., +; * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +; * +; * Change Logs: +; * Date Author Notes +; * 2011-01-13 weety first version +; */ + +#define S_FRAME_SIZE (18*4) ;72 + +;#define S_SPSR (17*4) ;SPSR +;#define S_CPSR (16*4) ;CPSR +#define S_PC (15*4) ;R15 +;#define S_LR (14*4) ;R14 +;#define S_SP (13*4) ;R13 + +;#define S_IP (12*4) ;R12 +;#define S_FP (11*4) ;R11 +;#define S_R10 (10*4) +;#define S_R9 (9*4) +;#define S_R8 (8*4) +;#define S_R7 (7*4) +;#define S_R6 (6*4) +;#define S_R5 (5*4) +;#define S_R4 (4*4) +;#define S_R3 (3*4) +;#define S_R2 (2*4) +;#define S_R1 (1*4) +;#define S_R0 (0*4) + +#define MODE_SYS 0x1F +#define MODE_FIQ 0x11 +#define MODE_IRQ 0x12 +#define MODE_SVC 0x13 +#define MODE_ABT 0x17 +#define MODE_UND 0x1B +#define MODEMASK 0x1F +#define NOINT 0xC0 + +#include "rt_low_level_iar.inc" + + MODULE ?cstartup + SECTION .noinit:DATA:NOROOT(3) + DATA + + DS8 UND_STK_SIZE + PUBLIC UND_STACK_START +UND_STACK_START: + + ALIGNRAM 2 + DS8 ABT_STK_SIZE + PUBLIC ABT_STACK_START +ABT_STACK_START: + + ALIGNRAM 2 + DS8 FIQ_STK_SIZE + PUBLIC FIQ_STACK_START +FIQ_STACK_START: + + ALIGNRAM 2 + DS8 IRQ_STK_SIZE + PUBLIC IRQ_STACK_START +IRQ_STACK_START: + + ALIGNRAM 2 + DS8 SVC_STK_SIZE + PUBLIC SVC_STACK_START +SVC_STACK_START: + + ALIGNRAM 2 + DS8 SYS_STK_SIZE + PUBLIC SYS_STACK_START +SYS_STACK_START: + +;--------------Jump vector table------------------------------------------------ + SECTION .intvec:CODE:ROOT(2) + ARM + PUBLIC Entry_Point +Entry_Point: +__iar_init$$done: ; The interrupt vector is not needed + ; until after copy initialization is done + LDR PC, vector_reset + LDR PC, vector_undef + LDR PC, vector_swi + LDR PC, vector_pabt + LDR PC, vector_dabt + LDR PC, vector_resv + LDR PC, vector_irq + LDR PC, vector_fiq + +vector_reset: + DC32 Reset_Handler +vector_undef: + DC32 Undef_Handler +vector_swi: + DC32 SWI_Handler +vector_pabt: + DC32 PAbt_Handler +vector_dabt: + DC32 DAbt_Handler +vector_resv: + DC32 Resv_Handler +vector_irq: + DC32 IRQ_Handler +vector_fiq: + DC32 FIQ_Handler + +;----------------- Reset Handler ----------------------------------------------- + EXTERN rt_low_level_init + EXTERN ?main + PUBLIC __iar_program_start +__iar_program_start: +Reset_Handler: + ; Set the cpu to SVC32 mode + MRS R0, CPSR + BIC R0, R0, #MODEMASK + ORR R0, R0, #MODE_SVC|NOINT + MSR CPSR_cxsf, R0 + LDR SP, =SVC_STACK_START + + ; Call low level init function, + ; disable and clear all IRQs and remap internal ram to 0x00000000. + LDR R0, =rt_low_level_init + BLX R0 + + ; Copy Exception Vectors to Internal RAM + LDR R8, =Entry_Point ; Source + LDR R9, =0x00000000 ; Destination + CMP R8, R9 + BEQ Setup_Stack + LDMIA R8!, {R0-R7} ; Load Vectors + STMIA R9!, {R0-R7} ; Store Vectors + LDMIA R8!, {R0-R7} ; Load Handler Addresses + STMIA R9!, {R0-R7} ; Store Handler Addresses + +Setup_Stack: + ; Setup Stack for each mode + MRS R0, CPSR + BIC R0, R0, #MODEMASK + + ORR R1, R0, #MODE_UND|NOINT + MSR CPSR_cxsf, R1 ; Undef mode + LDR SP, =UND_STACK_START + + ORR R1,R0,#MODE_ABT|NOINT + MSR CPSR_cxsf,R1 ; Abort mode + LDR SP, =ABT_STACK_START + + ORR R1,R0,#MODE_IRQ|NOINT + MSR CPSR_cxsf,R1 ; IRQ mode + LDR SP, =IRQ_STACK_START + + ORR R1,R0,#MODE_FIQ|NOINT + MSR CPSR_cxsf,R1 ; FIQ mode + LDR SP, =FIQ_STACK_START + + ORR R1,R0,#MODE_SYS|NOINT + MSR CPSR_cxsf,R1 ; SYS/User mode + LDR SP, =SYS_STACK_START + + ORR R1,R0,#MODE_SVC|NOINT + MSR CPSR_cxsf,R1 ; SVC mode + LDR SP, =SVC_STACK_START + + ; Enter the C code + LDR R0, =?main + BLX R0 + +;----------------- Exception Handler ------------------------------------------- + IMPORT rt_hw_trap_udef + IMPORT rt_hw_trap_swi + IMPORT rt_hw_trap_pabt + IMPORT rt_hw_trap_dabt + IMPORT rt_hw_trap_resv + IMPORT rt_hw_trap_irq + IMPORT rt_hw_trap_fiq + + IMPORT rt_interrupt_enter + IMPORT rt_interrupt_leave + IMPORT rt_thread_switch_interrupt_flag + IMPORT rt_interrupt_from_thread + IMPORT rt_interrupt_to_thread + + SECTION .text:CODE:ROOT(2) + ARM +Undef_Handler: + SUB SP, SP, #S_FRAME_SIZE + STMIA SP, {R0 - R12} ; Calling R0-R12 + ADD R8, SP, #S_PC + STMDB R8, {SP, LR} ; Calling SP, LR + STR LR, [R8, #0] ; Save calling PC + MRS R6, SPSR + STR R6, [R8, #4] ; Save CPSR + STR R0, [R8, #8] ; Save SPSR + MOV R0, SP + BL rt_hw_trap_udef + +SWI_Handler: + BL rt_hw_trap_swi + +PAbt_Handler: + BL rt_hw_trap_pabt + +DAbt_Handler: + SUB SP, SP, #S_FRAME_SIZE + STMIA SP, {R0 - R12} ; Calling R0-R12 + ADD R8, SP, #S_PC + STMDB R8, {SP, LR} ; Calling SP, LR + STR LR, [R8, #0] ; Save calling PC + MRS R6, SPSR + STR R6, [R8, #4] ; Save CPSR + STR R0, [R8, #8] ; Save SPSR + MOV R0, SP + BL rt_hw_trap_dabt + +Resv_Handler: + BL rt_hw_trap_resv + +IRQ_Handler: + STMFD SP!, {R0-R12,LR} + BL rt_interrupt_enter + BL rt_hw_trap_irq + BL rt_interrupt_leave + + ; If rt_thread_switch_interrupt_flag set, + ; jump to rt_hw_context_switch_interrupt_do and don't return + LDR R0, =rt_thread_switch_interrupt_flag + LDR R1, [R0] + CMP R1, #1 + BEQ rt_hw_context_switch_interrupt_do + + LDMFD SP!, {R0-R12,LR} + SUBS PC, LR, #4 + +FIQ_Handler: + STMFD SP!, {R0-R7,LR} + BL rt_hw_trap_fiq + LDMFD SP!, {R0-R7,LR} + SUBS PC, LR, #4 + +;------ void rt_hw_context_switch_interrupt_do(rt_base_t flag) ----------------- +rt_hw_context_switch_interrupt_do: + MOV R1, #0 ; Clear flag + STR R1, [R0] ; Save to flag variable + + LDMFD SP!, {R0-R12,LR} ; Reload saved registers + STMFD SP!, {R0-R3} ; Save R0-R3 + MOV R1, SP ; Save old task's SP to R1 + ADD SP, SP, #16 ; Restore SP + SUB R2, LR, #4 ; Save old task's PC to R2 + + MRS R3, SPSR ; Get CPSR of interrupt thread + + MSR CPSR_c, #MODE_SVC|NOINT ; Switch to SVC mode and no interrupt + + STMFD SP!, {R2} ; Push old task's PC + STMFD SP!, {R4-R12,LR} ; Push old task's LR,R12-R4 + MOV R4, R1 ; Special optimised code below + MOV R5, R3 + LDMFD R4!, {R0-R3} + STMFD SP!, {R0-R3} ; Push old task's R3-R0 + STMFD SP!, {R5} ; Push old task's CPSR + MRS R4, SPSR + STMFD SP!, {R4} ; Push old task's SPSR + + LDR R4, =rt_interrupt_from_thread + LDR R5, [R4] ; R5 = stack ptr in old tasks's TCB + STR SP, [R5] ; Store SP in preempted tasks's TCB + + LDR R6, =rt_interrupt_to_thread + LDR R6, [R6] ; R6 = stack ptr in new tasks's TCB + LDR SP, [R6] ; Get new task's stack pointer + + LDMFD SP!, {R4} ; Pop new task's SPSR + MSR SPSR_cxsf, R4 + LDMFD SP!, {R4} ; Pop new task's CPSR + MSR SPSR_cxsf, R4 + + LDMFD SP!, {R0-R12,LR,PC}^ ; pop new task's R0-R12,LR & PC + END diff --git a/libcpu/arm/arm926/start_rvds.S b/libcpu/arm/arm926/start_rvds.S new file mode 100644 index 0000000000..42144334bd --- /dev/null +++ b/libcpu/arm/arm926/start_rvds.S @@ -0,0 +1,338 @@ +;/* +; * File : start_rvds.S +; * This file is part of RT-Thread RTOS +; * COPYRIGHT (C) 2006, RT-Thread Development Team +; * +; * This program is free software; you can redistribute it and/or modify +; * it under the terms of the GNU General Public License as published by +; * the Free Software Foundation; either version 2 of the License, or +; * (at your option) any later version. +; * +; * This program is distributed in the hope that it will be useful, +; * but WITHOUT ANY WARRANTY; without even the implied warranty of +; * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +; * GNU General Public License for more details. +; * +; * You should have received a copy of the GNU General Public License along +; * with this program; if not, write to the Free Software Foundation, Inc., +; * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +; * +; * Change Logs: +; * Date Author Notes +; * 2011-08-14 weety first version +; */ + + +; Standard definitions of Mode bits and Interrupt (I & F) flags in PSRs + +S_FRAME_SIZE EQU (18*4) ;72 +;S_SPSR EQU (17*4) ;SPSR +;S_CPSR EQU (16*4) ;CPSR +S_PC EQU (15*4) ;R15 +;S_LR EQU (14*4) ;R14 +;S_SP EQU (13*4) ;R13 + +;S_IP EQU (12*4) ;R12 +;S_FP EQU (11*4) ;R11 +;S_R10 EQU (10*4) +;S_R9 EQU (9*4) +;S_R8 EQU (8*4) +;S_R7 EQU (7*4) +;S_R6 EQU (6*4) +;S_R5 EQU (5*4) +;S_R4 EQU (4*4) +;S_R3 EQU (3*4) +;S_R2 EQU (2*4) +;S_R1 EQU (1*4) +;S_R0 EQU (0*4) + + +MODE_USR EQU 0X10 +MODE_FIQ EQU 0X11 +MODE_IRQ EQU 0X12 +MODE_SVC EQU 0X13 +MODE_ABT EQU 0X17 +MODE_UND EQU 0X1B +MODE_SYS EQU 0X1F +MODEMASK EQU 0X1F + +NOINT EQU 0xC0 + +;----------------------- Stack and Heap Definitions ---------------------------- + AREA STACK, NOINIT, READWRITE, ALIGN=3 + GET rt_low_level_keil.inc + +;-------------- stack area ----------------------------------------------------- + AREA STACK, NOINIT, READWRITE, ALIGN=3 +Stack_Mem + + SPACE UND_STK_SIZE + EXPORT UND_STACK_START +UND_STACK_START + + ALIGN 8 + SPACE ABT_STK_SIZE + EXPORT ABT_STACK_START +ABT_STACK_START + + ALIGN 8 + SPACE FIQ_STK_SIZE + EXPORT FIQ_STACK_START +FIQ_STACK_START + + ALIGN 8 + SPACE IRQ_STK_SIZE + EXPORT IRQ_STACK_START +IRQ_STACK_START + + ALIGN 8 + SPACE SVC_STK_SIZE + EXPORT SVC_STACK_START +SVC_STACK_START + + ALIGN 8 + SPACE SYS_STK_SIZE + EXPORT SYS_STACK_START +SYS_STACK_START +Stack_Top + +Heap_Size EQU 0x00000000 + AREA HEAP, NOINIT, READWRITE, ALIGN=3 +__heap_base +Heap_Mem + SPACE Heap_Size +__heap_limit + +;----------------------- CODE -------------------------------------------------- + PRESERVE8 +; Area Definition and Entry Point +; Startup Code must be linked first at Address at which it expects to run. + +;--------------Jump vector table------------------------------------------------ + EXPORT Entry_Point + AREA RESET, CODE, READONLY + ARM +Entry_Point + LDR PC, vector_reset + LDR PC, vector_undef + LDR PC, vector_swi + LDR PC, vector_pabt + LDR PC, vector_dabt + LDR PC, vector_resv + LDR PC, vector_irq + LDR PC, vector_fiq + +vector_reset + DCD Reset_Handler +vector_undef + DCD Undef_Handler +vector_swi + DCD SWI_Handler +vector_pabt + DCD PAbt_Handler +vector_dabt + DCD DAbt_Handler +vector_resv + DCD Resv_Handler +vector_irq + DCD IRQ_Handler +vector_fiq + DCD FIQ_Handler + +;----------------- Reset Handler ----------------------------------------------- + IMPORT rt_low_level_init + IMPORT __main + EXPORT Reset_Handler +Reset_Handler + ; set the cpu to SVC32 mode + MRS R0,CPSR + BIC R0,R0,#MODEMASK + ORR R0,R0,#MODE_SVC + MSR CPSR_CXSF,R0 + LDR SP, =SVC_STACK_START + + ; Call low level init function, + ; disable and clear all IRQs and remap internal ram to 0x00000000. + LDR R0, =rt_low_level_init + BLX R0 + + ; Copy Exception Vectors to Internal RAM + LDR R8, =Entry_Point ; Source + LDR R9, =0x00000000 ; Destination + CMP R8, R9 + BEQ Setup_Stack + LDMIA R8!, {R0-R7} ; Load Vectors + STMIA R9!, {R0-R7} ; Store Vectors + LDMIA R8!, {R0-R7} ; Load Handler Addresses + STMIA R9!, {R0-R7} ; Store Handler Addresses + +Setup_Stack + ; Setup Stack for each mode + MRS R0, CPSR + BIC R0, R0, #MODEMASK + + ORR R1, R0, #MODE_UND:OR:NOINT + MSR CPSR_cxsf, R1 ; Undef mode + LDR SP, =UND_STACK_START + + ORR R1,R0,#MODE_ABT:OR:NOINT + MSR CPSR_cxsf,R1 ; Abort mode + LDR SP, =ABT_STACK_START + + ORR R1,R0,#MODE_IRQ:OR:NOINT + MSR CPSR_cxsf,R1 ; IRQ mode + LDR SP, =IRQ_STACK_START + + ORR R1,R0,#MODE_FIQ:OR:NOINT + MSR CPSR_cxsf,R1 ; FIQ mode + LDR SP, =FIQ_STACK_START + + ORR R1,R0,#MODE_SYS:OR:NOINT + MSR CPSR_cxsf,R1 ; SYS/User mode + LDR SP, =SYS_STACK_START + + ORR R1,R0,#MODE_SVC:OR:NOINT + MSR CPSR_cxsf,R1 ; SVC mode + LDR SP, =SVC_STACK_START + + ; Enter the C code + LDR R0, =__main + BLX R0 + +;----------------- Exception Handler ------------------------------------------- + IMPORT rt_hw_trap_udef + IMPORT rt_hw_trap_swi + IMPORT rt_hw_trap_pabt + IMPORT rt_hw_trap_dabt + IMPORT rt_hw_trap_resv + IMPORT rt_hw_trap_irq + IMPORT rt_hw_trap_fiq + + IMPORT rt_interrupt_enter + IMPORT rt_interrupt_leave + IMPORT rt_thread_switch_interrupt_flag + IMPORT rt_interrupt_from_thread + IMPORT rt_interrupt_to_thread + +Undef_Handler PROC + SUB SP, SP, #S_FRAME_SIZE + STMIA SP, {R0 - R12} ; Calling R0-R12 + ADD R8, SP, #S_PC + STMDB R8, {SP, LR} ; Calling SP, LR + STR LR, [R8, #0] ; Save calling PC + MRS R6, SPSR + STR R6, [R8, #4] ; Save CPSR + STR R0, [R8, #8] ; Save SPSR + MOV R0, SP + BL rt_hw_trap_udef + ENDP + +SWI_Handler PROC + BL rt_hw_trap_swi + ENDP + +PAbt_Handler PROC + BL rt_hw_trap_pabt + ENDP + +DAbt_Handler PROC + SUB SP, SP, #S_FRAME_SIZE + STMIA SP, {R0 - R12} ; Calling R0-R12 + ADD R8, SP, #S_PC + STMDB R8, {SP, LR} ; Calling SP, LR + STR LR, [R8, #0] ; Save calling PC + MRS R6, SPSR + STR R6, [R8, #4] ; Save CPSR + STR R0, [R8, #8] ; Save SPSR + MOV R0, SP + BL rt_hw_trap_dabt + ENDP + +Resv_Handler PROC + BL rt_hw_trap_resv + ENDP + +FIQ_Handler PROC + STMFD SP!, {R0-R7,LR} + BL rt_hw_trap_fiq + LDMFD SP!, {R0-R7,LR} + SUBS PC, LR, #4 + ENDP + +IRQ_Handler PROC + STMFD SP!, {R0-R12,LR} + BL rt_interrupt_enter + BL rt_hw_trap_irq + BL rt_interrupt_leave + + ; If rt_thread_switch_interrupt_flag set, + ; jump to rt_hw_context_switch_interrupt_do and don't return + LDR R0, =rt_thread_switch_interrupt_flag + LDR R1, [R0] + CMP R1, #1 + BEQ rt_hw_context_switch_interrupt_do + + LDMFD SP!, {R0-R12,LR} + SUBS PC, LR, #4 + ENDP + +;------ void rt_hw_context_switch_interrupt_do(rt_base_t flag) ----------------- +rt_hw_context_switch_interrupt_do PROC + MOV R1, #0 ; Clear flag + STR R1, [R0] ; Save to flag variable + + LDMFD SP!, {R0-R12,LR} ; Reload saved registers + STMFD SP!, {R0-R3} ; Save R0-R3 + MOV R1, SP ; Save old task's SP to R1 + ADD SP, SP, #16 ; Restore SP + SUB R2, LR, #4 ; Save old task's PC to R2 + + MRS R3, SPSR ; Get CPSR of interrupt thread + + MSR CPSR_c, #MODE_SVC:OR:NOINT ; Switch to SVC mode and no interrupt + + STMFD SP!, {R2} ; Push old task's PC + STMFD SP!, {R4-R12,LR} ; Push old task's LR,R12-R4 + MOV R4, R1 ; Special optimised code below + MOV R5, R3 + LDMFD R4!, {R0-R3} + STMFD SP!, {R0-R3} ; Push old task's R3-R0 + STMFD SP!, {R5} ; Push old task's CPSR + MRS R4, SPSR + STMFD SP!, {R4} ; Push old task's SPSR + + LDR R4, =rt_interrupt_from_thread + LDR R5, [R4] ; R5 = stack ptr in old tasks's TCB + STR SP, [R5] ; Store SP in preempted tasks's TCB + + LDR R6, =rt_interrupt_to_thread + LDR R6, [R6] ; R6 = stack ptr in new tasks's TCB + LDR SP, [R6] ; Get new task's stack pointer + + LDMFD SP!, {R4} ; Pop new task's SPSR + MSR SPSR_cxsf, R4 + LDMFD SP!, {R4} ; Pop new task's CPSR + MSR SPSR_cxsf, R4 + + LDMFD SP!, {R0-R12,LR,PC}^ ; pop new task's R0-R12,LR & PC + ENDP + + IF :DEF:__MICROLIB + + EXPORT __heap_base + EXPORT __heap_limit + + ELSE + ; User Initial Stack & Heap + AREA |.text|, CODE, READONLY + + IMPORT __use_two_region_memory + EXPORT __user_initial_stackheap +__user_initial_stackheap + LDR R0, = Heap_Mem + LDR R1, = (Stack_Mem + SYS_STK_SIZE) + LDR R2, = (Heap_Mem + Heap_Size) + LDR R3, = Stack_Mem + BX LR + ENDIF + END diff --git a/libcpu/arm/arm926/trap.c b/libcpu/arm/arm926/trap.c new file mode 100644 index 0000000000..f44c76064e --- /dev/null +++ b/libcpu/arm/arm926/trap.c @@ -0,0 +1,209 @@ +/* + * File : trap.c + * This file is part of RT-Thread RTOS + * COPYRIGHT (C) 2006, RT-Thread Development Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Change Logs: + * Date Author Notes + * 2011-01-13 weety modified from mini2440 + */ + +#include <rtthread.h> +#include <rthw.h> + +#include <interrupt.h> + +/** + * @addtogroup AT91SAM926X + */ +/*@{*/ + +extern struct rt_thread *rt_current_thread; +#ifdef RT_USING_FINSH +extern long list_thread(void); +#endif + +struct rt_hw_register +{ + rt_uint32_t r0; + rt_uint32_t r1; + rt_uint32_t r2; + rt_uint32_t r3; + rt_uint32_t r4; + rt_uint32_t r5; + rt_uint32_t r6; + rt_uint32_t r7; + rt_uint32_t r8; + rt_uint32_t r9; + rt_uint32_t r10; + rt_uint32_t fp; + rt_uint32_t ip; + rt_uint32_t sp; + rt_uint32_t lr; + rt_uint32_t pc; + rt_uint32_t cpsr; + rt_uint32_t ORIG_r0; +}; + +/** + * this function will show registers of CPU + * + * @param regs the registers point + */ + +void rt_hw_show_register (struct rt_hw_register *regs) +{ + rt_kprintf("Execption:\n"); + rt_kprintf("r00:0x%08x r01:0x%08x r02:0x%08x r03:0x%08x\n", regs->r0, regs->r1, regs->r2, regs->r3); + rt_kprintf("r04:0x%08x r05:0x%08x r06:0x%08x r07:0x%08x\n", regs->r4, regs->r5, regs->r6, regs->r7); + rt_kprintf("r08:0x%08x r09:0x%08x r10:0x%08x\n", regs->r8, regs->r9, regs->r10); + rt_kprintf("fp :0x%08x ip :0x%08x\n", regs->fp, regs->ip); + rt_kprintf("sp :0x%08x lr :0x%08x pc :0x%08x\n", regs->sp, regs->lr, regs->pc); + rt_kprintf("cpsr:0x%08x\n", regs->cpsr); +} + +/** + * When ARM7TDMI comes across an instruction which it cannot handle, + * it takes the undefined instruction trap. + * + * @param regs system registers + * + * @note never invoke this function in application + */ +void rt_hw_trap_udef(struct rt_hw_register *regs) +{ + rt_hw_show_register(regs); + + rt_kprintf("undefined instruction\n"); + rt_kprintf("thread - %s stack:\n", rt_current_thread->name); + +#ifdef RT_USING_FINSH + list_thread(); +#endif + rt_hw_cpu_shutdown(); +} + +/** + * The software interrupt instruction (SWI) is used for entering + * Supervisor mode, usually to request a particular supervisor + * function. + * + * @param regs system registers + * + * @note never invoke this function in application + */ +void rt_hw_trap_swi(struct rt_hw_register *regs) +{ + rt_hw_show_register(regs); + + rt_kprintf("software interrupt\n"); + rt_hw_cpu_shutdown(); +} + +/** + * An abort indicates that the current memory access cannot be completed, + * which occurs during an instruction prefetch. + * + * @param regs system registers + * + * @note never invoke this function in application + */ +void rt_hw_trap_pabt(struct rt_hw_register *regs) +{ + rt_hw_show_register(regs); + + rt_kprintf("prefetch abort\n"); + rt_kprintf("thread - %s stack:\n", RT_NAME_MAX, rt_current_thread->name); + +#ifdef RT_USING_FINSH + list_thread(); +#endif + rt_hw_cpu_shutdown(); +} + +/** + * An abort indicates that the current memory access cannot be completed, + * which occurs during a data access. + * + * @param regs system registers + * + * @note never invoke this function in application + */ +void rt_hw_trap_dabt(struct rt_hw_register *regs) +{ + rt_hw_show_register(regs); + + rt_kprintf("data abort\n"); + rt_kprintf("thread - %s stack:\n", RT_NAME_MAX, rt_current_thread->name); + +#ifdef RT_USING_FINSH + list_thread(); +#endif + rt_hw_cpu_shutdown(); +} + +/** + * Normally, system will never reach here + * + * @param regs system registers + * + * @note never invoke this function in application + */ +void rt_hw_trap_resv(struct rt_hw_register *regs) +{ + rt_kprintf("not used\n"); + rt_hw_show_register(regs); + rt_hw_cpu_shutdown(); +} + +extern struct rt_irq_desc irq_desc[]; +rt_uint32_t rt_hw_interrupt_get_active(rt_uint32_t fiq_irq, rt_uint32_t* id); +extern void rt_hw_interrupt_ack(rt_uint32_t fiq_irq); + +void rt_hw_trap_irq() +{ + rt_isr_handler_t isr_func; + rt_uint32_t irqstat, irq; + void *param; + //rt_kprintf("irq interrupt request\n"); + /* get irq number */ + irqstat = rt_hw_interrupt_get_active(INT_IRQ, &irq); + if (irqstat == 0) + { + rt_kprintf("No interrupt occur\n"); + rt_hw_interrupt_ack(INT_IRQ); + return; + } + + /* get interrupt service routine */ + isr_func = irq_desc[irq].handler; + param = irq_desc[irq].param; + + /* turn to interrupt service routine */ + isr_func(irq, param); + // EIOCR must be write any value after interrupt, + // or else can't response next interrupt + rt_hw_interrupt_ack(INT_IRQ); + irq_desc[irq].counter ++; +} + +void rt_hw_trap_fiq() +{ + rt_kprintf("fast interrupt request\n"); +} + +/*@}*/ |
