Jelajahi Sumber

add libcpu/cortex-m0.

git-svn-id: https://rt-thread.googlecode.com/svn/trunk@2142 bbd45198-f89e-11dd-88c7-29a3b14d5316
wuyangyong 13 tahun lalu
induk
melakukan
a9aa8d503e
2 mengubah file dengan 276 tambahan dan 0 penghapusan
  1. 191 0
      libcpu/arm/cortex-m0/context_rvds.S
  2. 85 0
      libcpu/arm/cortex-m0/cpuport.c

+ 191 - 0
libcpu/arm/cortex-m0/context_rvds.S

@@ -0,0 +1,191 @@
+;/*
+; * File      : context_rvds.S
+; * This file is part of RT-Thread RTOS
+; * COPYRIGHT (C) 2009, 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
+; * 2010-01-25     Bernard      first version
+; * 2012-06-01     aozima       set pendsv priority to 0xFF.
+; */
+
+;/**
+; * @addtogroup CORTEX-M0
+; */
+;/*@{*/
+
+NVIC_INT_CTRL   EQU     0xE000ED04               ; interrupt control state register
+NVIC_SHPR3      EQU     0xE000ED20               ; system priority register (2)
+NVIC_PENDSV_PRI EQU     0x00FF0000               ; PendSV priority value (lowest)
+NVIC_PENDSVSET  EQU     0x10000000               ; value to trigger PendSV exception
+
+    AREA |.text|, CODE, READONLY, ALIGN=2
+    THUMB
+    REQUIRE8
+    PRESERVE8
+
+    IMPORT rt_thread_switch_interrupt_flag
+    IMPORT rt_interrupt_from_thread
+    IMPORT rt_interrupt_to_thread
+
+;/*
+; * rt_base_t rt_hw_interrupt_disable();
+; */
+rt_hw_interrupt_disable    PROC
+    EXPORT  rt_hw_interrupt_disable
+    MRS     r0, PRIMASK
+    CPSID   I
+    BX      LR
+    ENDP
+
+;/*
+; * void rt_hw_interrupt_enable(rt_base_t level);
+; */
+rt_hw_interrupt_enable    PROC
+    EXPORT  rt_hw_interrupt_enable
+    MSR		PRIMASK, r0
+    BX		LR
+    ENDP
+
+;/*
+; * void rt_hw_context_switch(rt_uint32 from, rt_uint32 to);
+; * r0 --> from
+; * r1 --> to
+; */
+rt_hw_context_switch_interrupt
+    EXPORT rt_hw_context_switch_interrupt
+rt_hw_context_switch    PROC
+    EXPORT rt_hw_context_switch
+
+    ; set rt_thread_switch_interrupt_flag to 1
+    LDR     r2, =rt_thread_switch_interrupt_flag
+    LDR     r3, [r2]
+    CMP     r3, #1
+    BEQ     _reswitch
+    MOVS    r3, #0x1
+    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]
+
+    LDR     r0, =NVIC_INT_CTRL              ; trigger the PendSV exception (causes context switch)
+    LDR     r1, =NVIC_PENDSVSET
+    STR     r1, [r0]
+    BX      LR
+    ENDP
+
+; r0 --> swith from thread stack
+; r1 --> swith to thread stack
+; psr, pc, lr, r12, r3, r2, r1, r0 are pushed into [from] stack
+PendSV_Handler    PROC
+    EXPORT PendSV_Handler
+
+    ; disable interrupt to protect context switch
+    MRS     r2, PRIMASK
+    CPSID   I
+
+    ; get rt_thread_switch_interrupt_flag
+    LDR     r0, =rt_thread_switch_interrupt_flag
+    LDR     r1, [r0]
+    CMP     r1, #0x00
+    BEQ     pendsv_exit                ; pendsv already handled
+
+    ; clear rt_thread_switch_interrupt_flag to 0
+    MOVS    r1, #0x00
+    STR     r1, [r0]
+
+    LDR     r0, =rt_interrupt_from_thread
+    LDR     r1, [r0]
+    CMP     r1, #0x00
+    BEQ     swtich_to_thread        ; skip register save at the first time
+
+    MRS     r1, psp                 ; get from thread stack pointer
+    SUBS    r1, r1, #0x10
+    LDR     r0, [r0]
+    STR     r1, [r0]                ; update from thread stack pointer
+    STMIA   r1!, {r4 - r7}          ; push r4 - r7 register
+
+swtich_to_thread
+    LDR     r1, =rt_interrupt_to_thread
+    LDR     r1, [r1]
+    LDR     r1, [r1]                ; load thread stack pointer
+
+    LDMIA   r1!, {r4 - r7}          ; pop r4 - r7 register
+    MSR     psp, r1                 ; update stack pointer
+
+pendsv_exit
+    ; restore interrupt
+    MSR     PRIMASK, r2
+
+    MOVS    r0, #0x04
+    RSBS    r0, #0
+    BX      r0
+    ENDP
+
+;/*
+; * void rt_hw_context_switch_to(rt_uint32 to);
+; * r0 --> to
+; * this fucntion is used to perform the first thread switch
+; */
+rt_hw_context_switch_to    PROC
+    EXPORT rt_hw_context_switch_to
+    ; set to thread
+    LDR     r1, =rt_interrupt_to_thread
+    STR     r0, [r1]
+
+    ; set from thread to 0
+    LDR     r1, =rt_interrupt_from_thread
+    MOVS    r0, #0x0
+    STR     r0, [r1]
+
+    ; set interrupt flag to 1
+    LDR     r1, =rt_thread_switch_interrupt_flag
+    MOVS    r0, #1
+    STR     r0, [r1]
+
+    ; set the PendSV exception priority
+    LDR     r0, =NVIC_SHPR3
+    LDR     r1, =NVIC_PENDSV_PRI
+    LDR     r2, [r0,#0x00]       ; read
+    ORRS    r1,r1,r2             ; modify
+    STR     r1, [r0]             ; write-back
+
+    ; trigger the PendSV exception (causes context switch)
+    LDR     r0, =NVIC_INT_CTRL
+    LDR     r1, =NVIC_PENDSVSET
+    STR     r1, [r0]
+    NOP
+
+    ; enable interrupts at processor level
+    CPSIE   I
+
+    ; never reach here!
+    ENDP
+
+; compatible with old version
+rt_hw_interrupt_thread_switch PROC
+    EXPORT rt_hw_interrupt_thread_switch
+    BX      lr
+    ENDP
+
+    IMPORT rt_hw_hard_fault_exception
+
+HardFault_Handler    PROC
+    EXPORT HardFault_Handler
+
+    ; get current context
+    MRS     r0, psp                 ; get fault thread stack pointer
+    PUSH    {lr}
+    BL      rt_hw_hard_fault_exception
+    POP     {pc}
+    ENDP
+
+    END

+ 85 - 0
libcpu/arm/cortex-m0/cpuport.c

@@ -0,0 +1,85 @@
+/*
+ * File      : cpu.c
+ * This file is part of RT-Thread RTOS
+ * COPYRIGHT (C) 2009, 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
+ * 2010-01-25     Bernard      first version
+ * 2012-05-31     aozima       Merge all of the C source code into cpuport.c
+ */
+
+#include <rtthread.h>
+
+struct stack_contex
+{
+    rt_uint32_t r0;
+    rt_uint32_t r1;
+    rt_uint32_t r2;
+    rt_uint32_t r3;
+    rt_uint32_t r12;
+    rt_uint32_t lr;
+    rt_uint32_t pc;
+    rt_uint32_t psr;
+};
+
+/* flag in interrupt handling */
+rt_uint32_t rt_interrupt_from_thread, rt_interrupt_to_thread;
+rt_uint32_t rt_thread_switch_interrupt_flag;
+
+/**
+ * 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)
+{
+    unsigned long *stk;
+
+    stk 	 = (unsigned long *)stack_addr;
+    *(stk)   = 0x01000000L;					/* PSR */
+    *(--stk) = (unsigned long)tentry;		/* entry point, pc */
+    *(--stk) = (unsigned long)texit;		/* lr */
+    *(--stk) = 0;							/* r12 */
+    *(--stk) = 0;							/* r3 */
+    *(--stk) = 0;							/* r2 */
+    *(--stk) = 0;							/* r1 */
+    *(--stk) = (unsigned long)parameter;	/* r0 : argument */
+    *(--stk) = 0;							/* r7 */
+    *(--stk) = 0;							/* r6 */
+    *(--stk) = 0;							/* r5 */
+    *(--stk) = 0;							/* r4 */
+
+    /* return task's current stack address */
+    return (rt_uint8_t *)stk;
+}
+
+extern long list_thread(void);
+extern rt_thread_t rt_current_thread;
+void rt_hw_hard_fault_exception(struct stack_contex* contex)
+{
+    rt_kprintf("psr: 0x%08x\n", contex->psr);
+    rt_kprintf(" pc: 0x%08x\n", contex->pc);
+    rt_kprintf(" lr: 0x%08x\n", contex->lr);
+    rt_kprintf("r12: 0x%08x\n", contex->r12);
+    rt_kprintf("r03: 0x%08x\n", contex->r3);
+    rt_kprintf("r02: 0x%08x\n", contex->r2);
+    rt_kprintf("r01: 0x%08x\n", contex->r1);
+    rt_kprintf("r00: 0x%08x\n", contex->r0);
+
+    rt_kprintf("hard fault on thread: %s\n", rt_current_thread->name);
+#ifdef RT_USING_FINSH
+    list_thread();
+#endif
+    while (1);
+}