summaryrefslogtreecommitdiff
path: root/libcpu/arm/arm926
diff options
context:
space:
mode:
authorweety <[email protected]>2013-07-21 17:19:30 +0800
committerweety <[email protected]>2013-07-21 17:19:30 +0800
commit3bdbf640b7bcdc40a2d5171b67e50f92bbd588f6 (patch)
tree104ec0b9cf631b557e9bd09c309669887303c154 /libcpu/arm/arm926
parent885301bb14f34e840beb14ca2ee1b7b28012e294 (diff)
update at91sam9260 project directory structure.
Diffstat (limited to 'libcpu/arm/arm926')
-rw-r--r--libcpu/arm/arm926/context_gcc.S100
-rw-r--r--libcpu/arm/arm926/context_rvds.S107
-rw-r--r--libcpu/arm/arm926/cpuport.c236
-rw-r--r--libcpu/arm/arm926/mmu.c469
-rw-r--r--libcpu/arm/arm926/mmu.h53
-rw-r--r--libcpu/arm/arm926/stack.c60
6 files changed, 1025 insertions, 0 deletions
diff --git a/libcpu/arm/arm926/context_gcc.S b/libcpu/arm/arm926/context_gcc.S
new file mode 100644
index 0000000000..30d8235331
--- /dev/null
+++ b/libcpu/arm/arm926/context_gcc.S
@@ -0,0 +1,100 @@
+/*
+ * File : context.S
+ * This file is part of RT-Thread RTOS
+ * COPYRIGHT (C) 2006, RT-Thread Development Team
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://openlab.rt-thread.com/license/LICENSE
+ *
+ * Change Logs:
+ * Date Author Notes
+ * 2011-01-13 weety copy from mini2440
+ */
+
+/*!
+ * \addtogroup AT91SAM926X
+ */
+/*@{*/
+
+#define NOINT 0xc0
+
+
+/*
+ * 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
+
+/*
+ * void rt_hw_interrupt_enable(rt_base_t level);
+ */
+.globl rt_hw_interrupt_enable
+rt_hw_interrupt_enable:
+ msr cpsr, r0
+ mov pc, lr
+
+/*
+ * void rt_hw_context_switch(rt_uint32 from, rt_uint32 to);
+ * r0 --> from
+ * r1 --> to
+ */
+.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
+
+/*
+ * void rt_hw_context_switch_to(rt_uint32 to);
+ * r0 --> 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
+
+ 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
+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]
+_reswitch:
+ ldr r2, =rt_interrupt_to_thread @ set rt_interrupt_to_thread
+ str r1, [r2]
+ mov pc, lr
diff --git a/libcpu/arm/arm926/context_rvds.S b/libcpu/arm/arm926/context_rvds.S
new file mode 100644
index 0000000000..86f13dd1ba
--- /dev/null
+++ b/libcpu/arm/arm926/context_rvds.S
@@ -0,0 +1,107 @@
+;/*
+; * File : context_rvds.S
+; * This file is part of RT-Thread RTOS
+; * COPYRIGHT (C) 2006, RT-Thread Development Team
+; *
+; * The license and distribution terms for this file may be
+; * found in the file LICENSE in this distribution or at
+; * http://www.rt-thread.org/license/LICENSE
+; *
+; * Change Logs:
+; * Date Author Notes
+; * 2011-08-14 weety copy from mini2440
+; */
+
+NOINT EQU 0xc0 ; disable interrupt in psr
+
+ 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
+
+;/*
+; * 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
+
+;/*
+; * 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
+
+;/*
+; * 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
+
+ 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
+
+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]
+_reswitch
+ LDR r2, =rt_interrupt_to_thread ; set rt_interrupt_to_thread
+ STR r1, [r2]
+ BX lr
+ ENDP
+
+ END
diff --git a/libcpu/arm/arm926/cpuport.c b/libcpu/arm/arm926/cpuport.c
new file mode 100644
index 0000000000..caddf45a96
--- /dev/null
+++ b/libcpu/arm/arm926/cpuport.c
@@ -0,0 +1,236 @@
+/*
+ * File : cpu.c
+ * This file is part of RT-Thread RTOS
+ * COPYRIGHT (C) 2006, RT-Thread Develop Team
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://openlab.rt-thread.com/license/LICENSE
+ *
+ * Change Logs:
+ * Date Author Notes
+ * 2011-01-13 weety modified from mini2440
+ */
+
+#include <rthw.h>
+#include <rtthread.h>
+
+#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);
+
+#ifdef __GNUC__
+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
+
+#ifdef __CC_ARM
+rt_inline rt_uint32_t cp15_rd(void)
+{
+ rt_uint32_t i;
+
+ __asm
+ {
+ mrc p15, 0, i, c1, c0, 0
+ }
+
+ return i;
+}
+
+rt_inline void cache_enable(rt_uint32_t bit)
+{
+ rt_uint32_t value;
+
+ __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;
+
+ __asm
+ {
+ mrc p15, 0, value, c1, c0, 0
+ bic value, value, bit
+ mcr p15, 0, value, c1, c0, 0
+ }
+}
+#endif
+
+/**
+ * enable I-Cache
+ *
+ */
+void rt_hw_cpu_icache_enable()
+{
+ cache_enable(ICACHE_MASK);
+}
+
+/**
+ * disable I-Cache
+ *
+ */
+void rt_hw_cpu_icache_disable()
+{
+ cache_disable(ICACHE_MASK);
+}
+
+/**
+ * return the status of I-Cache
+ *
+ */
+rt_base_t rt_hw_cpu_icache_status()
+{
+ return (cp15_rd() & ICACHE_MASK);
+}
+
+/**
+ * enable D-Cache
+ *
+ */
+void rt_hw_cpu_dcache_enable()
+{
+ cache_enable(DCACHE_MASK);
+}
+
+/**
+ * disable D-Cache
+ *
+ */
+void rt_hw_cpu_dcache_disable()
+{
+ cache_disable(DCACHE_MASK);
+}
+
+/**
+ * return the status of D-Cache
+ *
+ */
+rt_base_t rt_hw_cpu_dcache_status()
+{
+ return (cp15_rd() & DCACHE_MASK);
+}
+
+/**
+ * reset cpu by dog's time-out
+ *
+ */
+void rt_hw_cpu_reset()
+{
+
+ rt_kprintf("Restarting system...\n");
+ machine_reset();
+
+ while(1); /* loop forever and wait for reset to happen */
+
+ /* NEVER REACHED */
+}
+
+/**
+ * shutdown CPU
+ *
+ */
+void rt_hw_cpu_shutdown()
+{
+ rt_uint32_t level;
+ rt_kprintf("shutdown...\n");
+
+ level = rt_hw_interrupt_disable();
+ machine_shutdown();
+ while (level)
+ {
+ RT_ASSERT(0);
+ }
+}
+
+#ifdef RT_USING_CPU_FFS
+/**
+ * This function finds the first bit set (beginning with the least significant bit)
+ * in value and return the index of that bit.
+ *
+ * Bits are numbered starting at 1 (the least significant bit). A return value of
+ * zero from any of these functions means that the argument was zero.
+ *
+ * @return return the index of the first bit set. If value is 0, then this function
+ * shall return 0.
+ */
+#if defined(__CC_ARM)
+int __rt_ffs(int value)
+{
+ 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
+ }
+
+ return x;
+}
+#elif defined(__IAR_SYSTEMS_ICC__)
+int __rt_ffs(int 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");
+}
+#elif defined(__GNUC__)
+int __rt_ffs(int value)
+{
+ if (value == 0)
+ return value;
+
+ value &= (-value);
+ asm ("clz %0, %1": "=r"(value) :"r"(value));
+
+ return (32 - value);
+}
+#endif
+
+#endif
+
+
+/*@}*/
diff --git a/libcpu/arm/arm926/mmu.c b/libcpu/arm/arm926/mmu.c
new file mode 100644
index 0000000000..c14f22bd84
--- /dev/null
+++ b/libcpu/arm/arm926/mmu.c
@@ -0,0 +1,469 @@
+/*
+ * File : mmu.c
+ * This file is part of RT-Thread RTOS
+ * COPYRIGHT (C) 2006, RT-Thread Development Team
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rt-thread.org/license/LICENSE
+ *
+ * Change Logs:
+ * Date Author Notes
+ */
+
+#include "mmu.h"
+
+#ifdef __CC_ARM
+void mmu_setttbase(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, value, c8, c7, 0
+ }
+
+ value = 0x55555555;
+ __asm
+ {
+ mcr p15, 0, value, c3, c0, 0
+ mcr p15, 0, i, c2, c0, 0
+ }
+}
+
+void mmu_set_domain(rt_uint32_t i)
+{
+ __asm
+ {
+ mcr p15,0, i, c3, c0, 0
+ }
+}
+
+void mmu_enable()
+{
+ register rt_uint32_t value;
+
+ __asm
+ {
+ mrc p15, 0, value, c1, c0, 0
+ orr value, value, #0x01
+ mcr p15, 0, value, c1, c0, 0
+ }
+}
+
+void mmu_disable()
+{
+ register rt_uint32_t value;
+
+ __asm
+ {
+ mrc p15, 0, value, c1, c0, 0
+ bic value, value, #0x01
+ mcr p15, 0, value, c1, c0, 0
+ }
+}
+
+void mmu_enable_icache()
+{
+ register rt_uint32_t value;
+
+ __asm
+ {
+ mrc p15, 0, value, c1, c0, 0
+ orr value, value, #0x1000
+ mcr p15, 0, value, c1, c0, 0
+ }
+}
+
+void mmu_enable_dcache()
+{
+ register rt_uint32_t value;
+
+ __asm
+ {
+ mrc p15, 0, value, c1, c0, 0
+ orr value, value, #0x04
+ mcr p15, 0, value, c1, c0, 0
+ }
+}
+
+void mmu_disable_icache()
+{
+ register rt_uint32_t value;
+
+ __asm
+ {
+ mrc p15, 0, value, c1, c0, 0
+ bic value, value, #0x1000
+ mcr p15, 0, value, c1, c0, 0
+ }
+}
+
+void mmu_disable_dcache()
+{
+ register rt_uint32_t value;
+
+ __asm
+ {
+ mrc p15, 0, value, c1, c0, 0
+ bic value, value, #0x04
+ mcr p15, 0, value, c1, c0, 0
+ }
+}
+
+void mmu_enable_alignfault()
+{
+ register rt_uint32_t value;
+
+ __asm
+ {
+ mrc p15, 0, value, c1, c0, 0
+ orr value, value, #0x02
+ mcr p15, 0, value, c1, c0, 0
+ }
+}
+
+void mmu_disable_alignfault()
+{
+ register rt_uint32_t value;
+
+ __asm
+ {
+ mrc p15, 0, value, c1, c0, 0
+ bic value, value, #0x02
+ mcr p15, 0, value, c1, c0, 0
+ }
+}
+
+void mmu_clean_invalidated_cache_index(int index)
+{
+ __asm
+ {
+ mcr p15, 0, index, c7, c14, 2
+ }
+}
+
+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, ptr, c7, c14, 1
+ }
+ 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, ptr, c7, c10, 1
+ }
+ 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, ptr, c7, c6, 1
+ }
+ ptr += CACHE_LINE_SIZE;
+ }
+}
+
+void mmu_invalidate_tlb()
+{
+ register rt_uint32_t value;
+
+ value = 0;
+ __asm
+ {
+ mcr p15, 0, value, c8, c7, 0
+ }
+}
+
+void mmu_invalidate_icache()
+{
+ register rt_uint32_t value;
+
+ value = 0;
+
+ __asm
+ {
+ mcr p15, 0, value, c7, c5, 0
+ }
+}
+
+
+void mmu_invalidate_dcache_all()
+{
+ register rt_uint32_t value;
+
+ value = 0;
+
+ __asm
+ {
+ mcr p15, 0, value, c7, c6, 0
+ }
+}
+#elif defined(__GNUC__)
+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 = 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));
+}
+#endif
+
+/* level1 page table */
+static volatile unsigned int _page_table[4*1024] __attribute__((aligned(16*1024)));
+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;
+ 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++;
+ }
+}
+
+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();
+
+ /* 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);
+
+ /* enables MMU */
+ mmu_enable();
+
+ /* enable Instruction Cache */
+ mmu_enable_icache();
+
+ /* enable Data Cache */
+ mmu_enable_dcache();
+
+ mmu_invalidate_icache();
+ mmu_invalidate_dcache_all();
+}
+
diff --git a/libcpu/arm/arm926/mmu.h b/libcpu/arm/arm926/mmu.h
new file mode 100644
index 0000000000..e45d3b0239
--- /dev/null
+++ b/libcpu/arm/arm926/mmu.h
@@ -0,0 +1,53 @@
+/*
+ * File : mmu.h
+ * This file is part of RT-Thread RTOS
+ * COPYRIGHT (C) 2006, RT-Thread Development Team
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rt-thread.org/license/LICENSE
+ *
+ * Change Logs:
+ * Date Author Notes
+ */
+
+#ifndef __MMU_H__
+#define __MMU_H__
+
+#include <rtthread.h>
+
+#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 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 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;
+};
+
+void rt_hw_mmu_init(struct mem_desc *mdesc, rt_uint32_t size);
+
+#endif
+
diff --git a/libcpu/arm/arm926/stack.c b/libcpu/arm/arm926/stack.c
new file mode 100644
index 0000000000..7075fcff80
--- /dev/null
+++ b/libcpu/arm/arm926/stack.c
@@ -0,0 +1,60 @@
+/*
+ * File : stack.c
+ * This file is part of RT-Thread RTOS
+ * COPYRIGHT (C) 2006, RT-Thread Development Team
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://openlab.rt-thread.com/license/LICENSE
+ *
+ * Change Logs:
+ * Date Author Notes
+ * 2011-01-13 weety copy from mini2440
+ */
+#include <rtthread.h>
+#include "at91sam926x.h"
+
+/**
+ * @addtogroup AT91SAM926X
+ */
+/*@{*/
+
+/**
+ * This function will initialize thread stack
+ *
+ * @param tentry the entry of thread
+ * @param parameter the parameter of entry
+ * @param stack_addr the beginning stack address
+ * @param texit the function will be called when thread exit
+ *
+ * @return stack address
+ */
+rt_uint8_t *rt_hw_stack_init(void *tentry, void *parameter,
+ rt_uint8_t *stack_addr, void *texit)
+{
+ 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 */
+
+ /* return task's current stack address */
+ return (rt_uint8_t *)stk;
+}
+
+/*@}*/