From d128ba91691534b3e64b6736d4dfbfbe81244055 Mon Sep 17 00:00:00 2001 From: wuyangyong Date: Wed, 16 Feb 2011 15:49:53 +0000 Subject: [PATCH] add nios git-svn-id: https://rt-thread.googlecode.com/svn/trunk@1273 bbd45198-f89e-11dd-88c7-29a3b14d5316 --- libcpu/nios/nios_ii/context_gcc.S | 252 ++++++++++++++++++++++++++++++ libcpu/nios/nios_ii/interrupt.c | 22 +++ libcpu/nios/nios_ii/stack.c | 72 +++++++++ libcpu/nios/nios_ii/vector.S | 46 ++++++ 4 files changed, 392 insertions(+) create mode 100644 libcpu/nios/nios_ii/context_gcc.S create mode 100644 libcpu/nios/nios_ii/interrupt.c create mode 100644 libcpu/nios/nios_ii/stack.c create mode 100644 libcpu/nios/nios_ii/vector.S diff --git a/libcpu/nios/nios_ii/context_gcc.S b/libcpu/nios/nios_ii/context_gcc.S new file mode 100644 index 0000000000..9c17d1afe7 --- /dev/null +++ b/libcpu/nios/nios_ii/context_gcc.S @@ -0,0 +1,252 @@ +/* + * File : context_gcc.S + * This file is part of RT-Thread RTOS + * COPYRIGHT (C) 2006-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 + * 2011-02-14 aozima first implementation for Nios II. + */ + +/** + * @addtogroup NIOS_II + */ +/*@{*/ + +.text + +.set noat + +/* + * rt_base_t rt_hw_interrupt_disable(); + */ +.global rt_hw_interrupt_disable +.type rt_hw_interrupt_disable, %function +rt_hw_interrupt_disable: + rdctl r2, status /* return status */ + wrctl status, zero /* disable interrupt */ + ret + +/* + * void rt_hw_interrupt_enable(rt_base_t level); + */ +.global rt_hw_interrupt_enable +.type rt_hw_interrupt_enable, %function +rt_hw_interrupt_enable: + wrctl status, r4 /* enable interrupt by argument */ + ret + +/* void rt_hw_context_switch_interrupt_do(void) */ +.global rt_hw_context_switch_interrupt_do +.type rt_hw_context_switch_interrupt_do, %function +rt_hw_context_switch_interrupt_do: + /* save from thread */ + addi sp,sp,-72 + + rdctl r2, status + stw r2, 68(sp) /* status */ + + stw r2, 4(sp) + stw r3, 8(sp) + stw r4, 12(sp) + + /* get & save from thread pc */ + ldw r4,%gprel(rt_current_thread_entry)(gp) + stw r4, 0(sp) /* thread back */ + + stw r5, 16(sp) + stw r6, 20(sp) + stw r7, 24(sp) + + stw r16, 28(sp) + stw r17, 32(sp) + stw r18, 36(sp) + stw r19, 40(sp) + stw r20, 44(sp) + stw r21, 48(sp) + stw r22, 52(sp) + stw r23, 56(sp) + + stw fp, 60(sp) + stw ra, 64(sp) + + /* save from thread sp */ + ldw r4, %gprel(rt_interrupt_from_thread)(gp) + stw sp, (r4) + + /* clear rt_thread_switch_interrput_flag */ + stw zero,%gprel(rt_thread_switch_interrput_flag)(gp) + + /* load to thread sp */ + ldw r4, %gprel(rt_interrupt_to_thread)(gp) + ldw sp, (r4) + + ldw r2, 68(sp) /* status */ + wrctl status, r2 + + ldw at, 0(sp) /* thread pc */ + ldw r2, 4(sp) + ldw r3, 8(sp) + ldw r4, 12(sp) + ldw r5, 16(sp) + ldw r6, 20(sp) + ldw r7, 24(sp) + + ldw r16, 28(sp) + ldw r17, 32(sp) + ldw r18, 36(sp) + ldw r19, 40(sp) + ldw r20, 44(sp) + ldw r21, 48(sp) + ldw r22, 52(sp) + ldw r23, 56(sp) + + ldw fp, 60(sp) + ldw ra, 64(sp) + + addi sp, sp, 72 + + jmp at + +/* + * void rt_hw_context_switch(rt_uint32 from, rt_uint32 to); + * r4: from + * r5: to + */ +.global rt_hw_context_switch +.type rt_hw_context_switch, %function +rt_hw_context_switch: + /* save from thread */ + addi sp,sp,-72 + + rdctl r2, status + stw r2, 68(sp) /* status */ + + stw ra, 0(sp) /* thread back */ + stw r2, 4(sp) + stw r3, 8(sp) + stw r4, 12(sp) + stw r5, 16(sp) + stw r6, 20(sp) + stw r7, 24(sp) + + stw r16, 28(sp) + stw r17, 32(sp) + stw r18, 36(sp) + stw r19, 40(sp) + stw r20, 44(sp) + stw r21, 48(sp) + stw r22, 52(sp) + stw r23, 56(sp) + + stw fp, 60(sp) + stw ra, 64(sp) + + /* save form thread sp */ + stw sp, (r4) + + /* update rt_interrupt_from_thread */ + stw r4,%gprel(rt_interrupt_from_thread)(gp) + + /* update rt_interrupt_to_thread */ + stw r5,%gprel(rt_interrupt_to_thread)(gp) + + /* get to thread sp */ + ldw sp, (r5) + + ldw r2, 68(sp) /* status */ + wrctl status, r2 + + ldw at, 0(sp) /* thread pc */ + ldw r2, 4(sp) + ldw r3, 8(sp) + ldw r4, 12(sp) + ldw r5, 16(sp) + ldw r6, 20(sp) + ldw r7, 24(sp) + + ldw r16, 28(sp) + ldw r17, 32(sp) + ldw r18, 36(sp) + ldw r19, 40(sp) + ldw r20, 44(sp) + ldw r21, 48(sp) + ldw r22, 52(sp) + ldw r23, 56(sp) + + ldw fp, 60(sp) + ldw ra, 64(sp) + + addi sp, sp, 72 + + jmp at + +/* + * void rt_hw_context_switch_interrupt(rt_uint32 from, rt_uint32 to); + * r4: from + * r5: to + */ +.global rt_hw_context_switch_interrupt +.type rt_hw_context_switch_interrupt, %function +rt_hw_context_switch_interrupt: + /* save ea -> rt_current_thread_entry */ + addi ea,ea,-4 + stw ea,%gprel(rt_current_thread_entry)(gp) + + /* set rt_thread_switch_interrput_flag to 1 */ + movi r2, 1 + stw r2,%gprel(rt_thread_switch_interrput_flag)(gp) + + /* update rt_interrupt_from_thread */ + stw r4,%gprel(rt_interrupt_from_thread)(gp) + + /* update rt_interrupt_to_thread */ + stw r5,%gprel(rt_interrupt_to_thread)(gp) + + ret + +/* + * void rt_hw_context_switch_to(rt_uint32 to); + * r4: to + */ +.global rt_hw_context_switch_to +.type rt_hw_context_switch_to, %function +rt_hw_context_switch_to: + /* save to thread */ + stw r4,%gprel(rt_interrupt_to_thread)(gp) + + /* get sp */ + ldw sp, (r4) // sp = *r4 + + ldw r2, 68(sp) /* status */ + wrctl status, r2 + + ldw at, 0(sp) /* thread entry */ + ldw r2, 4(sp) + ldw r3, 8(sp) + ldw r4, 12(sp) + ldw r5, 16(sp) + ldw r6, 20(sp) + ldw r7, 24(sp) + + ldw r16, 28(sp) + ldw r17, 32(sp) + ldw r18, 36(sp) + ldw r19, 40(sp) + ldw r20, 44(sp) + ldw r21, 48(sp) + ldw r22, 52(sp) + ldw r23, 56(sp) + + ldw fp, 60(sp) + ldw ra, 64(sp) + + addi sp, sp, 72 + + jmp at + +/*@}*/ diff --git a/libcpu/nios/nios_ii/interrupt.c b/libcpu/nios/nios_ii/interrupt.c new file mode 100644 index 0000000000..18c4abd6d8 --- /dev/null +++ b/libcpu/nios/nios_ii/interrupt.c @@ -0,0 +1,22 @@ +/* + * File : interrupt.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 + * 2009-01-05 Bernard first version + */ + +#include + +/* exception and interrupt handler table */ +rt_uint32_t rt_interrupt_from_thread, rt_interrupt_to_thread; +rt_uint32_t rt_thread_switch_interrput_flag; +rt_uint32_t rt_current_thread_entry; + +/*@}*/ diff --git a/libcpu/nios/nios_ii/stack.c b/libcpu/nios/nios_ii/stack.c new file mode 100644 index 0000000000..01fbb2c468 --- /dev/null +++ b/libcpu/nios/nios_ii/stack.c @@ -0,0 +1,72 @@ +/* + * File : stack.c + * This file is part of RT-Thread RTOS + * COPYRIGHT (C) 2006-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 + * 2011-02-14 aozima first implementation for Nios II. + */ + +#include + +/** + * @addtogroup NIOS_II + */ +/*@{*/ + +/** + * 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) = 0x01; /* status */ + *(--stk) = (unsigned long)texit; /* ra */ + *(--stk) = 0xdeadbeef; /* fp */ + *(--stk) = 0xdeadbeef; /* r23 */ + *(--stk) = 0xdeadbeef; /* r22 */ + *(--stk) = 0xdeadbeef; /* r21 */ + *(--stk) = 0xdeadbeef; /* r20 */ + *(--stk) = 0xdeadbeef; /* r19 */ + *(--stk) = 0xdeadbeef; /* r18 */ + *(--stk) = 0xdeadbeef; /* r17 */ + *(--stk) = 0xdeadbeef; /* r16 */ +// *(--stk) = 0xdeadbeef; /* r15 */ +// *(--stk) = 0xdeadbeef; /* r14 */ +// *(--stk) = 0xdeadbeef; /* r13 */ +// *(--stk) = 0xdeadbeef; /* r12 */ +// *(--stk) = 0xdeadbeef; /* r11 */ +// *(--stk) = 0xdeadbeef; /* r10 */ +// *(--stk) = 0xdeadbeef; /* r9 */ +// *(--stk) = 0xdeadbeef; /* r8 */ + *(--stk) = 0xdeadbeef; /* r7 */ + *(--stk) = 0xdeadbeef; /* r6 */ + *(--stk) = 0xdeadbeef; /* r5 */ + *(--stk) = (unsigned long)parameter; /* r4 argument */ + *(--stk) = 0xdeadbeef; /* r3 */ + *(--stk) = 0xdeadbeef; /* r2 */ + *(--stk) = (unsigned long)tentry; /* pc */ + +// *(stk) = (unsigned long)tentry; /* thread entry (ra) */ +// *(--stk) = (unsigned long)parameter; /* thread argument, r4 */ + + /* return task's current stack address */ + return (rt_uint8_t *)stk; +} + +/*@}*/ diff --git a/libcpu/nios/nios_ii/vector.S b/libcpu/nios/nios_ii/vector.S new file mode 100644 index 0000000000..b23a2b8379 --- /dev/null +++ b/libcpu/nios/nios_ii/vector.S @@ -0,0 +1,46 @@ +.set noat + +.globl .Lexception_exit + +.section .exceptions.exit.label +.Lexception_exit: +.section .exceptions.exit, "xa" + ldw r5, 68(sp) + + /* get exception back */ + ldw ea, 72(sp) + ldw r4,%gprel(rt_thread_switch_interrput_flag)(gp) + beq r4,zero,no_need_context +need_context: + movia ea, rt_hw_context_switch_interrupt_do + +no_need_context: + ldw ra, 0(sp) + + wrctl estatus, r5 + + /* + * Leave a gap in the stack frame at 4(sp) for the muldiv handler to + * store zero into. + */ + + ldw r1, 8(sp) + ldw r2, 12(sp) + ldw r3, 16(sp) + ldw r4, 20(sp) + ldw r5, 24(sp) + ldw r6, 28(sp) + ldw r7, 32(sp) + ldw r8, 36(sp) + ldw r9, 40(sp) + ldw r10, 44(sp) + ldw r11, 48(sp) + ldw r12, 52(sp) + ldw r13, 56(sp) + ldw r14, 60(sp) + ldw r15, 64(sp) + + addi sp, sp, 76 + + eret +