From c2507af6bc0162bae42b65e6f40a8163c656d4d4 Mon Sep 17 00:00:00 2001 From: "bernard.xiong@gmail.com" Date: Sun, 22 Aug 2010 23:22:01 +0000 Subject: add Nuvoton Cortex-M0 porting. git-svn-id: https://rt-thread.googlecode.com/svn/trunk@877 bbd45198-f89e-11dd-88c7-29a3b14d5316 --- libcpu/arm/nuc1xx/context_rvds.S | 175 ++++++++++++++++++++ libcpu/arm/nuc1xx/fault.c | 47 ++++++ libcpu/arm/nuc1xx/fault_rvds.S | 32 ++++ libcpu/arm/nuc1xx/interrupt.c | 21 +++ libcpu/arm/nuc1xx/stack.c | 54 ++++++ libcpu/arm/nuc1xx/start_rvds.S | 349 +++++++++++++++++++++++++++++++++++++++ 6 files changed, 678 insertions(+) create mode 100644 libcpu/arm/nuc1xx/context_rvds.S create mode 100644 libcpu/arm/nuc1xx/fault.c create mode 100644 libcpu/arm/nuc1xx/fault_rvds.S create mode 100644 libcpu/arm/nuc1xx/interrupt.c create mode 100644 libcpu/arm/nuc1xx/stack.c create mode 100644 libcpu/arm/nuc1xx/start_rvds.S (limited to 'libcpu') diff --git a/libcpu/arm/nuc1xx/context_rvds.S b/libcpu/arm/nuc1xx/context_rvds.S new file mode 100644 index 0000000000..a2771d0945 --- /dev/null +++ b/libcpu/arm/nuc1xx/context_rvds.S @@ -0,0 +1,175 @@ +;/* +; * 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 +; */ + +;/** +; * @addtogroup NUC100 +; */ +;/*@{*/ + +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_interrput_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_interrput_flag to 1 + LDR r2, =rt_thread_switch_interrput_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 +rt_hw_pend_sv PROC + EXPORT rt_hw_pend_sv + + ; disable interrupt to protect context switch + MRS r2, PRIMASK + CPSID I + + ; get rt_thread_switch_interrupt_flag + LDR r0, =rt_thread_switch_interrput_flag + LDR r1, [r0] + CMP r1, #0x00 + BEQ pendsv_exit ; pendsv already handled + + ; clear rt_thread_switch_interrput_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_interrput_flag + MOVS r0, #1 + STR r0, [r1] + + ; set the PendSV exception priority + ; LDR r0, =NVIC_SYSPRI2 + ; LDR r1, =NVIC_PENDSV_PRI + ; STR r1, [r0] + + ; 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 + ENDP + + END diff --git a/libcpu/arm/nuc1xx/fault.c b/libcpu/arm/nuc1xx/fault.c new file mode 100644 index 0000000000..5b8dc6b62f --- /dev/null +++ b/libcpu/arm/nuc1xx/fault.c @@ -0,0 +1,47 @@ +/* + * File : fault.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 + */ +#include + +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; +}; + +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); +} diff --git a/libcpu/arm/nuc1xx/fault_rvds.S b/libcpu/arm/nuc1xx/fault_rvds.S new file mode 100644 index 0000000000..4029306400 --- /dev/null +++ b/libcpu/arm/nuc1xx/fault_rvds.S @@ -0,0 +1,32 @@ +;/* +; * File : fault_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 +; * 2010-01-25 Bernard first version +; */ + + AREA |.text|, CODE, READONLY, ALIGN=2 + THUMB + REQUIRE8 + PRESERVE8 + + IMPORT rt_hw_hard_fault_exception + +rt_hw_hard_fault PROC + EXPORT rt_hw_hard_fault + + ; get current context + MRS r0, psp ; get fault thread stack pointer + PUSH {lr} + BL rt_hw_hard_fault_exception + POP {pc} + ENDP + + END diff --git a/libcpu/arm/nuc1xx/interrupt.c b/libcpu/arm/nuc1xx/interrupt.c new file mode 100644 index 0000000000..a1a3eb2441 --- /dev/null +++ b/libcpu/arm/nuc1xx/interrupt.c @@ -0,0 +1,21 @@ +/* + * 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 + * 2010-01-25 Bernard first version + */ + +#include + +/* exception and interrupt handler table */ +rt_uint32_t rt_interrupt_from_thread, rt_interrupt_to_thread; +rt_uint8_t rt_thread_switch_interrput_flag; + +/*@}*/ diff --git a/libcpu/arm/nuc1xx/stack.c b/libcpu/arm/nuc1xx/stack.c new file mode 100644 index 0000000000..5329244c67 --- /dev/null +++ b/libcpu/arm/nuc1xx/stack.c @@ -0,0 +1,54 @@ +/* + * File : stack.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 + */ +#include + +/** + * @addtogroup NUC100 + */ +/*@{*/ + +/** + * 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; +} + +/*@}*/ diff --git a/libcpu/arm/nuc1xx/start_rvds.S b/libcpu/arm/nuc1xx/start_rvds.S new file mode 100644 index 0000000000..c0058b6e8a --- /dev/null +++ b/libcpu/arm/nuc1xx/start_rvds.S @@ -0,0 +1,349 @@ +;/*---------------------------------------------------------------------------------------------------------*/ +;/* */ +;/* Copyright(c) 2009 Nuvoton Technology Corp. All rights reserved. */ +;/* */ +;/*---------------------------------------------------------------------------------------------------------*/ + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +CLK_BA_base EQU 0x50000200 +PWRCON EQU 0x00 +AHBCLK EQU 0x04 +APBCLK EQU 0x08 +CLKSEL0 EQU 0x10 +CLKSEL1 EQU 0x14 +CLKDIV EQU 0x18 +PLLCON EQU 0x20 +TEST_S EQU 0x30 + +CLK_BA_APBCLK EQU 0x50000208 + +;// Define clock enable registers + +ADC_COMP_CLK EQU 0x50000208 +ADC_enable EQU 0x10000000 +COMP_enable EQU 0x40000000 + +PDMA_CLK EQU 0x50000204 +PDMA_enable EQU 0x00000003 + +;; bit 0 CPU_EN +;; bit 1 PDMA_EN + +;// Define COMP registers base +COMP_base EQU 0x400D0000 +CMP1CR EQU 0x00 +CMP2CR EQU 0x04 +CMPSR EQU 0x08 + +;// Define ADC registers base +ADC_base EQU 0x400E0000 +ADDR0 EQU 0x00 +ADDR1 EQU 0x04 +ADDR2 EQU 0x08 +ADDR3 EQU 0x0c +ADDR4 EQU 0x10 +ADDR5 EQU 0x14 +ADDR6 EQU 0x18 +ADDR7 EQU 0x1c +ADCR EQU 0x20 +ADCHER EQU 0x24 +ADCMPR0 EQU 0x28 +ADCMPR1 EQU 0x2c +ADSR EQU 0x30 +ADCALR EQU 0x34 +ADCFCR EQU 0x38 +ADCALD EQU 0x3c + +;// Pattern Table +pattern_55555555 EQU 0x55555555 +pattern_aaaaaaaa EQU 0xaaaaaaaa +pattern_00005555 EQU 0x00005555 +pattern_0000aaaa EQU 0x0000aaaa +pattern_05550515 EQU 0x05550515 +pattern_0aaa0a2a EQU 0x0aaa0a2a + +;// Define PDMA regsiter base +PDMA_BA_ch0_base EQU 0x50008000 +PDMA_BA_ch1_base EQU 0x50008100 +PDMA_BA_ch2_base EQU 0x50008200 +PDMA_BA_ch3_base EQU 0x50008300 +PDMA_BA_ch4_base EQU 0x50008400 +PDMA_BA_ch5_base EQU 0x50008500 +PDMA_BA_ch6_base EQU 0x50008600 +PDMA_BA_ch7_base EQU 0x50008700 + +PDMA_BA_GCR EQU 0x50008F00 +PDMA_BA_GCR_base EQU 0x50008F00 + +PDMA_GCRCSR EQU 0X00 +PDMA_PDSSR2 EQU 0X04 +PDMA_PDSSR1 EQU 0X08 ;; PDMA channel select 0x77000000 +PDMA_GCRISR EQU 0X0C + +PDMA_GLOBAL_enable EQU 0x0000FF00 + +PDMA_CSR EQU 0X00 +PDMA_SAR EQU 0X04 +PDMA_DAR EQU 0X08 +PDMA_BCR EQU 0X0C +PDMA_CSAR EQU 0X14 +PDMA_CDAR EQU 0X18 +PDMA_CBSR EQU 0X1C +PDMA_IER EQU 0X20 +PDMA_ISR EQU 0X24 +PDMA_CTCSR EQU 0X28 +PDMA_SASOCR EQU 0X2C +PDMA_DASOCR EQU 0X30 +PDMA_SBUF0 EQU 0X80 +PDMA_SBUF1 EQU 0X84 +PDMA_SBUF2 EQU 0X88 +PDMA_SBUF3 EQU 0X8C + +;// Define VIC control register +VIC_base EQU 0xFFFF0000 +VIC_SCR15 EQU 0x003c +VIC_SVR15 EQU 0x00bc +VIC_SCR16 EQU 0x0040 +VIC_SVR16 EQU 0x00c0 +VIC_SCR30 EQU 0x0078 +VIC_SVR30 EQU 0x00f8 +VIC_MECR EQU 0x0318 +VIC_MDCR EQU 0x031c +VIC_EOSCR EQU 0x0130 + +;//================================== +INT_BA_base EQU 0x50000300 + +;// Parameter table +ADC_PDMA_CFG EQU 0x00002980 +ADC_PDMA_DST EQU 0xC0000000 +ADC_PDMA_SRC EQU 0xE0024200 +ADC_PDMA_TCBL EQU 0x00030008 + +;//================================== + +GPIO_base EQU 0x50004000 +GPIOB_PMD EQU 0x0040 +GPIOB_OFFD EQU 0x0044 +GPIOB_DOUT EQU 0x0048 +GPIOB_DMASK EQU 0x004C +GPIOB_PIN EQU 0x0050 +GPIOB_DBEN EQU 0x0054 +GPIOB_IMD EQU 0x0058 +GPIOB_IEN EQU 0x005C +GPIOB_ISRC EQU 0x0060 + +;//================================== + + +GCR_base EQU 0x50000000 +GPB_MFP EQU 0x0034 + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +Stack_Size EQU 0x00000200 + + AREA STACK, NOINIT, READWRITE, ALIGN=3 +Stack_Mem SPACE Stack_Size +__initial_sp + +Heap_Size EQU 0x00000000 + + AREA HEAP, NOINIT, READWRITE, ALIGN=3 +__heap_base +Heap_Mem SPACE Heap_Size +__heap_limit + + + PRESERVE8 + THUMB + + IMPORT rt_hw_hard_fault + IMPORT rt_hw_pend_sv + IMPORT rt_hw_timer_handler + +; Vector Table Mapped to Address 0 at Reset + AREA RESET, DATA, READONLY + EXPORT __Vectors + +__Vectors DCD __initial_sp ; Top of Stack + DCD Reset_Handler ; Reset Handler + DCD NMI_Handler ; NMI Handler + DCD rt_hw_hard_fault ; Hard Fault Handler + DCD 0 ; Reserved + DCD 0 ; Reserved + DCD 0 ; Reserved + DCD 0 ; Reserved + DCD 0 ; Reserved + DCD 0 ; Reserved + DCD 0 ; Reserved + DCD SVC_Handler ; SVCall Handler + DCD 0 ; Reserved + DCD 0 ; Reserved + DCD rt_hw_pend_sv ; PendSV Handler + DCD rt_hw_timer_handler ; SysTick Handler + + ; External Interrupts + ; maximum of 32 External Interrupts are possible + DCD BOD_IRQHandler + DCD WDT_IRQHandler + DCD EINT0_IRQHandler + DCD EINT1_IRQHandler + DCD GPAB_IRQHandler + DCD GPCDE_IRQHandler + DCD PWMA_IRQHandler + DCD PWMB_IRQHandler + DCD TMR0_IRQHandler + DCD TMR1_IRQHandler + DCD TMR2_IRQHandler + DCD TMR3_IRQHandler + DCD UART0_IRQHandler + DCD UART1_IRQHandler + DCD SPI0_IRQHandler + DCD SPI1_IRQHandler + DCD SPI2_IRQHandler + DCD SPI3_IRQHandler + DCD I2C0_IRQHandler + DCD I2C1_IRQHandler + DCD CAN0_IRQHandler + DCD CAN1_IRQHandler + DCD Default_Handler + DCD USBD_IRQHandler + DCD PS2_IRQHandler + DCD ACMP_IRQHandler + DCD PDMA_IRQHandler + DCD Default_Handler + DCD PWRWU_IRQHandler + DCD ADC_IRQHandler + DCD Default_Handler + DCD RTC_IRQHandler + + + + + + + + AREA |.text|, CODE, READONLY + + + +; Reset Handler + + ENTRY + +Reset_Handler PROC + EXPORT Reset_Handler [WEAK] + IMPORT __main + + LDR R0, =__main + BX R0 + ENDP + + +; Dummy Exception Handlers (infinite loops which can be modified) + +NMI_Handler PROC + EXPORT NMI_Handler [WEAK] + B . + ENDP +SVC_Handler PROC + EXPORT SVC_Handler [WEAK] + B . + ENDP + +Default_Handler PROC + + EXPORT BOD_IRQHandler [WEAK] + EXPORT WDT_IRQHandler [WEAK] + EXPORT EINT0_IRQHandler [WEAK] + EXPORT EINT1_IRQHandler [WEAK] + EXPORT GPAB_IRQHandler [WEAK] + EXPORT GPCDE_IRQHandler [WEAK] + EXPORT PWMA_IRQHandler [WEAK] + EXPORT PWMB_IRQHandler [WEAK] + EXPORT TMR0_IRQHandler [WEAK] + EXPORT TMR1_IRQHandler [WEAK] + EXPORT TMR2_IRQHandler [WEAK] + EXPORT TMR3_IRQHandler [WEAK] + EXPORT UART0_IRQHandler [WEAK] + EXPORT UART1_IRQHandler [WEAK] + EXPORT SPI0_IRQHandler [WEAK] + EXPORT SPI1_IRQHandler [WEAK] + EXPORT SPI2_IRQHandler [WEAK] + EXPORT SPI3_IRQHandler [WEAK] + EXPORT I2C0_IRQHandler [WEAK] + EXPORT I2C1_IRQHandler [WEAK] + EXPORT CAN0_IRQHandler [WEAK] + EXPORT CAN1_IRQHandler [WEAK] + EXPORT USBD_IRQHandler [WEAK] + EXPORT PS2_IRQHandler [WEAK] + EXPORT ACMP_IRQHandler [WEAK] + EXPORT PDMA_IRQHandler [WEAK] + EXPORT PWRWU_IRQHandler [WEAK] + EXPORT ADC_IRQHandler [WEAK] + EXPORT RTC_IRQHandler [WEAK] + +BOD_IRQHandler +WDT_IRQHandler +EINT0_IRQHandler +EINT1_IRQHandler +GPAB_IRQHandler +GPCDE_IRQHandler +PWMA_IRQHandler +PWMB_IRQHandler +TMR0_IRQHandler +TMR1_IRQHandler +TMR2_IRQHandler +TMR3_IRQHandler +UART0_IRQHandler +UART1_IRQHandler +SPI0_IRQHandler +SPI1_IRQHandler +SPI2_IRQHandler +SPI3_IRQHandler +I2C0_IRQHandler +I2C1_IRQHandler +CAN0_IRQHandler +CAN1_IRQHandler +USBD_IRQHandler +PS2_IRQHandler +ACMP_IRQHandler +PDMA_IRQHandler +PWRWU_IRQHandler +ADC_IRQHandler +RTC_IRQHandler + B . + ENDP + + + ALIGN + + +; User Initial Stack & Heap + + IF :DEF:__MICROLIB + + EXPORT __initial_sp + EXPORT __heap_base + EXPORT __heap_limit + + ELSE + + IMPORT __use_two_region_memory + EXPORT __user_initial_stackheap +__user_initial_stackheap + + LDR R0, = Heap_Mem + LDR R1, = (Stack_Mem + Stack_Size) + LDR R2, = (Heap_Mem + Heap_Size) + LDR R3, = Stack_Mem + BX LR + + ALIGN + + ENDIF + + + END -- cgit v1.3.1