瀏覽代碼

add STM32F40x porting (uncompleted)

git-svn-id: https://rt-thread.googlecode.com/svn/trunk@1770 bbd45198-f89e-11dd-88c7-29a3b14d5316
bernard.xiong@gmail.com 13 年之前
父節點
當前提交
3ac0b7b966
共有 4 個文件被更改,包括 629 次插入0 次删除
  1. 178 0
      libcpu/arm/cortex-m4/context_gcc.S
  2. 176 0
      libcpu/arm/cortex-m4/context_iar.S
  3. 188 0
      libcpu/arm/cortex-m4/context_rvds.S
  4. 87 0
      libcpu/arm/cortex-m4/cpuport.c

+ 178 - 0
libcpu/arm/cortex-m4/context_gcc.S

@@ -0,0 +1,178 @@
+/*
+ * File      : context_gcc.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
+ * 2009-10-11     Bernard      first version
+ */
+
+/**
+ * @addtogroup STM32
+ */
+/*@{*/
+
+.cpu cortex-m3
+.fpu softvfp
+.syntax unified
+.thumb
+.text
+
+.equ    NVIC_INT_CTRL,       0xE000ED04               /* interrupt control state register */
+.equ    NVIC_SYSPRI2,        0xE000ED20               /* system priority register (2) */
+.equ    NVIC_PENDSV_PRI,     0x00FF0000               /* PendSV priority value (lowest) */
+.equ    NVIC_PENDSVSET,      0x10000000               /* value to trigger PendSV exception */
+
+/*
+ * rt_base_t rt_hw_interrupt_disable();
+ */
+.global rt_hw_interrupt_disable
+.type rt_hw_interrupt_disable, %function
+rt_hw_interrupt_disable:
+    MRS     r0, PRIMASK
+    CPSID   I
+    BX      LR
+
+/*
+ * void rt_hw_interrupt_enable(rt_base_t level);
+ */
+.global rt_hw_interrupt_enable
+.type rt_hw_interrupt_enable, %function
+rt_hw_interrupt_enable:
+    MSR     PRIMASK, r0
+    BX      LR
+
+/*
+ * void rt_hw_context_switch(rt_uint32 from, rt_uint32 to);
+ * r0 --> from
+ * r1 --> to
+ */
+.global rt_hw_context_switch_interrupt
+.type rt_hw_context_switch_interrupt, %function
+.global rt_hw_context_switch
+.type rt_hw_context_switch, %function
+
+rt_hw_context_switch_interrupt:
+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
+    MOV     r3, #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]
+
+    LDR r0, =NVIC_INT_CTRL              /* trigger the PendSV exception (causes context switch) */
+    LDR r1, =NVIC_PENDSVSET
+    STR r1, [r0]
+    BX  LR
+
+/* r0 --> swith from thread stack
+ * r1 --> swith to thread stack
+ * psr, pc, lr, r12, r3, r2, r1, r0 are pushed into [from] stack
+ */
+.global PendSV_Handler
+.type PendSV_Handler, %function
+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]
+    CBZ r1, pendsv_exit         /* pendsv already handled */
+
+    /* clear rt_thread_switch_interrupt_flag to 0 */
+    MOV r1, #0x00
+    STR r1, [r0]
+
+    LDR r0, =rt_interrupt_from_thread
+    LDR r1, [r0]
+    CBZ r1, swtich_to_thread    /* skip register save at the first time */
+
+    MRS r1, psp                 /* get from thread stack pointer */
+    STMFD   r1!, {r4 - r11}         /* push r4 - r11 register */
+    LDR r0, [r0]
+    STR r1, [r0]                /* update from thread stack pointer */
+
+swtich_to_thread:
+    LDR r1, =rt_interrupt_to_thread
+    LDR r1, [r1]
+    LDR r1, [r1]                /* load thread stack pointer */
+
+    LDMFD   r1!, {r4 - r11}         /* pop r4 - r11 register */
+    MSR psp, r1                 /* update stack pointer */
+
+pendsv_exit:
+    /* restore interrupt */
+    MSR PRIMASK, r2
+
+    ORR lr, lr, #0x04
+    BX  lr
+
+/*
+ * void rt_hw_context_switch_to(rt_uint32 to);
+ * r0 --> to
+ */
+.global rt_hw_context_switch_to
+.type rt_hw_context_switch_to, %function
+rt_hw_context_switch_to:
+    LDR r1, =rt_interrupt_to_thread
+    STR r0, [r1]
+
+    /* set from thread to 0 */
+    LDR r1, =rt_interrupt_from_thread
+    MOV r0, #0x0
+    STR r0, [r1]
+
+    /* set interrupt flag to 1 */
+    LDR     r1, =rt_thread_switch_interrupt_flag
+    MOV     r0, #1
+    STR     r0, [r1]
+
+    /* set the PendSV exception priority */
+    LDR r0, =NVIC_SYSPRI2
+    LDR r1, =NVIC_PENDSV_PRI
+    LDR.W   r2, [r0,#0x00]       /* read       */
+    ORR     r1,r1,r2             /* modify     */
+    STR     r1, [r0]             /* write-back */
+
+    LDR r0, =NVIC_INT_CTRL      /* trigger the PendSV exception (causes context switch) */
+    LDR r1, =NVIC_PENDSVSET
+    STR r1, [r0]
+
+    CPSIE   I                       /* enable interrupts at processor level */
+
+    /* never reach here! */
+
+/* compatible with old version */
+.global rt_hw_interrupt_thread_switch
+.type rt_hw_interrupt_thread_switch, %function
+rt_hw_interrupt_thread_switch:
+    BX  lr
+    NOP
+
+.global HardFault_Handler
+.type HardFault_Handler, %function
+HardFault_Handler:
+    /* get current context */
+    MRS     r0, psp                 /* get fault thread stack pointer */
+    PUSH    {lr}
+    BL      rt_hw_hard_fault_exception
+    POP     {lr}
+
+    ORR     lr, lr, #0x04
+    BX      lr

+ 176 - 0
libcpu/arm/cortex-m4/context_iar.S

@@ -0,0 +1,176 @@
+;/*
+; * File      : context_iar.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
+; * 2009-01-17     Bernard      first version
+; * 2009-09-27     Bernard      add protect when contex switch occurs
+; */
+
+;/**
+; * @addtogroup STM32
+; */
+;/*@{*/
+
+NVIC_INT_CTRL   EQU     0xE000ED04               ; interrupt control state register
+NVIC_SYSPRI2    EQU     0xE000ED20               ; system priority register (2)
+NVIC_PENDSV_PRI EQU     0x00FF0000               ; PendSV priority value (lowest)
+NVIC_PENDSVSET  EQU     0x10000000               ; value to trigger PendSV exception
+
+    SECTION    .text:CODE(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();
+; */
+    EXPORT rt_hw_interrupt_disable
+rt_hw_interrupt_disable:
+    MRS     r0, PRIMASK
+    CPSID   I
+    BX      LR
+
+;/*
+; * void rt_hw_interrupt_enable(rt_base_t level);
+; */
+    EXPORT  rt_hw_interrupt_enable
+rt_hw_interrupt_enable:
+    MSR     PRIMASK, r0
+    BX      LR
+
+;/*
+; * void rt_hw_context_switch(rt_uint32 from, rt_uint32 to);
+; * r0 --> from
+; * r1 --> to
+; */
+    EXPORT rt_hw_context_switch_interrupt
+    EXPORT rt_hw_context_switch
+rt_hw_context_switch_interrupt:
+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
+    MOV     r3, #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]
+
+    LDR     r0, =NVIC_INT_CTRL              ; trigger the PendSV exception (causes context switch)
+    LDR     r1, =NVIC_PENDSVSET
+    STR     r1, [r0]
+    BX      LR
+
+; r0 --> swith from thread stack
+; r1 --> swith to thread stack
+; psr, pc, lr, r12, r3, r2, r1, r0 are pushed into [from] stack
+    EXPORT PendSV_Handler
+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]
+    CBZ     r1, pendsv_exit         ; pendsv already handled
+
+    ; clear rt_thread_switch_interrupt_flag to 0
+    MOV     r1, #0x00
+    STR     r1, [r0]
+
+    LDR     r0, =rt_interrupt_from_thread
+    LDR     r1, [r0]
+    CBZ     r1, swtich_to_thread    ; skip register save at the first time
+
+    MRS     r1, psp                 ; get from thread stack pointer
+    STMFD   r1!, {r4 - r11}         ; push r4 - r11 register
+    LDR     r0, [r0]
+    STR     r1, [r0]                ; update from thread stack pointer
+
+swtich_to_thread
+    LDR     r1, =rt_interrupt_to_thread
+    LDR     r1, [r1]
+    LDR     r1, [r1]                ; load thread stack pointer
+
+    LDMFD   r1!, {r4 - r11}         ; pop r4 - r11 register
+    MSR     psp, r1                 ; update stack pointer
+
+pendsv_exit
+    ; restore interrupt
+    MSR     PRIMASK, r2
+
+    ORR     lr, lr, #0x04
+    BX      lr
+
+;/*
+; * void rt_hw_context_switch_to(rt_uint32 to);
+; * r0 --> to
+; */
+    EXPORT rt_hw_context_switch_to
+rt_hw_context_switch_to:
+    LDR     r1, =rt_interrupt_to_thread
+    STR     r0, [r1]
+
+    ; set from thread to 0
+    LDR     r1, =rt_interrupt_from_thread
+    MOV     r0, #0x0
+    STR     r0, [r1]
+
+    ; set interrupt flag to 1
+    LDR     r1, =rt_thread_switch_interrupt_flag
+    MOV     r0, #1
+    STR     r0, [r1]
+
+    ; set the PendSV exception priority
+    LDR     r0, =NVIC_SYSPRI2
+    LDR     r1, =NVIC_PENDSV_PRI
+    LDR.W   r2, [r0,#0x00]       ; read
+    ORR     r1,r1,r2             ; modify
+    STR     r1, [r0]             ; write-back
+
+    LDR     r0, =NVIC_INT_CTRL      ; trigger the PendSV exception (causes context switch)
+    LDR     r1, =NVIC_PENDSVSET
+    STR     r1, [r0]
+
+    CPSIE   I                       ; enable interrupts at processor level
+
+    ; never reach here!
+
+; compatible with old version
+    EXPORT rt_hw_interrupt_thread_switch
+rt_hw_interrupt_thread_switch:
+    BX      lr
+
+    IMPORT rt_hw_hard_fault_exception
+    EXPORT HardFault_Handler
+HardFault_Handler:
+
+    ; get current context
+    MRS     r0, psp                 ; get fault thread stack pointer
+    PUSH    {lr}
+    BL      rt_hw_hard_fault_exception
+    POP     {lr}
+
+    ORR     lr, lr, #0x04
+    BX      lr
+
+    END

+ 188 - 0
libcpu/arm/cortex-m4/context_rvds.S

@@ -0,0 +1,188 @@
+;/*
+; * 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
+; * 2009-01-17     Bernard      first version
+; */
+
+;/**
+; * @addtogroup STM32
+; */
+;/*@{*/
+
+NVIC_INT_CTRL   EQU     0xE000ED04               ; interrupt control state register
+NVIC_SYSPRI2    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
+    MOV     r3, #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]
+
+    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]
+    CBZ     r1, pendsv_exit         ; pendsv already handled
+
+    ; clear rt_thread_switch_interrupt_flag to 0
+    MOV     r1, #0x00
+    STR     r1, [r0]
+
+    LDR     r0, =rt_interrupt_from_thread
+    LDR     r1, [r0]
+    CBZ     r1, swtich_to_thread    ; skip register save at the first time
+
+    MRS     r1, psp                 ; get from thread stack pointer
+    STMFD   r1!, {r4 - r11}         ; push r4 - r11 register
+    LDR     r0, [r0]
+    STR     r1, [r0]                ; update from thread stack pointer
+
+swtich_to_thread
+    LDR     r1, =rt_interrupt_to_thread
+    LDR     r1, [r1]
+    LDR     r1, [r1]                ; load thread stack pointer
+
+    LDMFD   r1!, {r4 - r11}         ; pop r4 - r11 register
+    MSR     psp, r1                 ; update stack pointer
+
+pendsv_exit
+    ; restore interrupt
+    MSR     PRIMASK, r2
+
+    ORR     lr, lr, #0x04
+    BX      lr
+    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
+    MOV     r0, #0x0
+    STR     r0, [r1]
+
+    ; set interrupt flag to 1
+    LDR     r1, =rt_thread_switch_interrupt_flag
+    MOV     r0, #1
+    STR     r0, [r1]
+
+    ; set the PendSV exception priority
+    LDR     r0, =NVIC_SYSPRI2
+    LDR     r1, =NVIC_PENDSV_PRI
+    LDR.W   r2, [r0,#0x00]       ; read
+    ORR     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]
+
+    ; 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
+    NOP
+    ENDP
+
+    IMPORT rt_hw_hard_fault_exception
+    EXPORT HardFault_Handler
+HardFault_Handler    PROC
+
+    ; get current context
+    MRS     r0, psp                 ; get fault thread stack pointer
+    PUSH    {lr}
+    BL      rt_hw_hard_fault_exception
+    POP     {lr}
+
+    ORR     lr, lr, #0x04
+    BX      lr
+    ENDP
+
+    END

+ 87 - 0
libcpu/arm/cortex-m4/cpuport.c

@@ -0,0 +1,87 @@
+/*
+ * File      : cpuport.c
+ * This file is part of RT-Thread RTOS
+ * COPYRIGHT (C) 2009 - 2011, 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
+ * 2006-08-23     Bernard      the first version
+ * 2011-06-03     Bernard      merge all of C source code into cpuport.c
+ */
+#include <rtthread.h>
+
+/* exception and interrupt handler table */
+rt_uint32_t rt_interrupt_from_thread, rt_interrupt_to_thread;
+rt_uint32_t rt_thread_switch_interrupt_flag;
+
+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;
+};
+
+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;							/* r11 */
+	*(--stk) = 0;							/* r10 */
+	*(--stk) = 0;							/* r9 */
+	*(--stk) = 0;							/* r8 */
+	*(--stk) = 0;							/* r7 */
+	*(--stk) = 0;							/* r6 */
+	*(--stk) = 0;							/* r5 */
+	*(--stk) = 0;							/* r4 */
+
+	/* return task's current stack address */
+	return (rt_uint8_t *)stk;
+}
+
+extern void rt_hw_interrupt_thread_switch(void);
+extern void 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);
+}
+
+void rt_hw_cpu_shutdown()
+{
+	rt_kprintf("shutdown...\n");
+
+	RT_ASSERT(0);
+}