From 360095ecb149cdca6eec2c9e92e978bca6462ab8 Mon Sep 17 00:00:00 2001 From: "zchongnari@gmail.com" Date: Sat, 26 Jun 2010 03:47:03 +0000 Subject: add sep4020 porting git-svn-id: https://rt-thread.googlecode.com/svn/trunk@776 bbd45198-f89e-11dd-88c7-29a3b14d5316 --- libcpu/arm/sep4020/clk.c | 112 ++++++++++++ libcpu/arm/sep4020/context_rvds.S | 107 +++++++++++ libcpu/arm/sep4020/cpu.c | 42 +++++ libcpu/arm/sep4020/interrupt.c | 107 +++++++++++ libcpu/arm/sep4020/serial.c | 281 ++++++++++++++++++++++++++++ libcpu/arm/sep4020/serial.h | 56 ++++++ libcpu/arm/sep4020/stack.c | 61 +++++++ libcpu/arm/sep4020/start_rvds.S | 374 ++++++++++++++++++++++++++++++++++++++ libcpu/arm/sep4020/trap.c | 66 +++++++ 9 files changed, 1206 insertions(+) create mode 100644 libcpu/arm/sep4020/clk.c create mode 100644 libcpu/arm/sep4020/context_rvds.S create mode 100644 libcpu/arm/sep4020/cpu.c create mode 100644 libcpu/arm/sep4020/interrupt.c create mode 100644 libcpu/arm/sep4020/serial.c create mode 100644 libcpu/arm/sep4020/serial.h create mode 100644 libcpu/arm/sep4020/stack.c create mode 100644 libcpu/arm/sep4020/start_rvds.S create mode 100644 libcpu/arm/sep4020/trap.c (limited to 'libcpu') diff --git a/libcpu/arm/sep4020/clk.c b/libcpu/arm/sep4020/clk.c new file mode 100644 index 0000000000..7b298ea825 --- /dev/null +++ b/libcpu/arm/sep4020/clk.c @@ -0,0 +1,112 @@ +/* + * File : clock.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 + * 2010-03-20 zchong first version + */ + +#include +#include "sep4020.h" + +#define CLK_IN 4000000 /* Fin = 4.00MHz */ +#define SYSCLK 72000000 /* system clock we want */ + +#define CLK_ESRAM 0 +#define CLK_LCDC 1 +#define CLK_PWM 2 +#define CLK_DMAC 3 +#define CLK_EMI 4 +#define CLK_MMCSD 5 +#define CLK_SSI 7 +#define CLK_UART0 8 +#define CLK_UART1 9 +#define CLK_UART2 10 +#define CLK_UART3 11 +#define CLK_USB 12 +#define CLK_MAC 13 +#define CLK_SMC 14 +#define CLK_I2C 15 +#define CLK_GPT 16 + +static void rt_hw_set_system_clock(void) +{ + rt_uint8_t pv; + + /* pv value*/ + pv = SYSCLK/2/CLK_IN; + /* go to normal mode*/ + PMC_PMDR = 0x01; + /* set the clock */ + PMC_PMCR = 0x4000 | pv; + /* trige configurate*/ + PMC_PMCR = 0xc000 | pv; +} + +static void rt_hw_set_usb_clock(void) +{ + /* set the clock */ + PMC_PUCR = 0x000c; + /* trige configurate*/ + PMC_PMCR = 0x800c; + +} + +/** + * @brief System Clock Configuration + */ +void rt_hw_clock_init(void) +{ + /* set system clock */ + rt_hw_set_system_clock(); + /* set usb clock */ + rt_hw_set_usb_clock(); +} + +/** + * @brief Get system clock + */ +rt_uint32_t rt_hw_get_clock(void) +{ + rt_uint32_t val; + rt_uint8_t pv, pd, npd; + + /* get PMCR value */ + val = PMC_PMCR; + /* get NPD */ + npd = (val >> 14) & 0x01; + /* get PD */ + pd = (val >> 10) & 0x0f; + /* get PV */ + pv = val & 0x7f; + /* caculate the system clock */ + if(npd) + val = 2 * CLK_IN * pv; + else + val = CLK_IN * pv / (pd + 1); + + return(val); +} + +/** + * @brief Enable module clock + */ + void rt_hw_enable_module_clock(rt_uint8_t module) + { + + } + +/** + * @brief Disable module clock + */ + void rt_hw_disable_module_clock(rt_uint8_t module) + { + + } + diff --git a/libcpu/arm/sep4020/context_rvds.S b/libcpu/arm/sep4020/context_rvds.S new file mode 100644 index 0000000000..82c5adc574 --- /dev/null +++ b/libcpu/arm/sep4020/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 +; * 2009-01-20 Bernard first version +; */ + +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 cpsr_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_interrput_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_interrput_flag + LDR r3, [r2] + CMP r3, #1 + BEQ _reswitch + MOV r3, #1 ; set rt_thread_switch_interrput_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 \ No newline at end of file diff --git a/libcpu/arm/sep4020/cpu.c b/libcpu/arm/sep4020/cpu.c new file mode 100644 index 0000000000..1905da812e --- /dev/null +++ b/libcpu/arm/sep4020/cpu.c @@ -0,0 +1,42 @@ +/* + * 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://www.rt-thread.org/license/LICENSE + * + * Change Logs: + * Date Author Notes + * 2006-08-23 Bernard first version + */ + +#include + + +/** + * @addtogroup AT91SAM7X + */ +/*@{*/ + +/** + * this function will reset CPU + * + */ +void rt_hw_cpu_reset() +{ +} + +/** + * this function will shutdown CPU + * + */ +void rt_hw_cpu_shutdown() +{ + rt_kprintf("shutdown...\n"); + + while (1); +} + +/*@}*/ diff --git a/libcpu/arm/sep4020/interrupt.c b/libcpu/arm/sep4020/interrupt.c new file mode 100644 index 0000000000..810e0185b7 --- /dev/null +++ b/libcpu/arm/sep4020/interrupt.c @@ -0,0 +1,107 @@ +/* + * File : trap.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 + * 2006-08-23 Bernard first version + * 2010-03-17 zchong SEP4020 + */ + +#include +#include "sep4020.h" + +#define MAX_HANDLERS 32 + +extern rt_uint32_t rt_interrupt_nest; + +/* exception and interrupt handler table */ +rt_isr_handler_t isr_table[MAX_HANDLERS]; +rt_uint32_t rt_interrupt_from_thread, rt_interrupt_to_thread; +rt_uint32_t rt_thread_switch_interrput_flag; + +/** + * @addtogroup SEP4020 + */ +/*@{*/ + +void rt_hw_interrupt_handler(int vector) +{ + rt_kprintf("Unhandled interrupt %d occured!!!\n", vector); +} + +/** + * This function will initialize hardware interrupt + */ +void rt_hw_interrupt_init() +{ + register rt_uint32_t idx; + + /* disable all interrupts */ + INTC_IER = 0x0; + + /* mask all interrupts */ + INTC_IMR = 0xFFFFFFFF; + + /* init exceptions table */ + for(idx=0; idx < MAX_HANDLERS; idx++) + { + isr_table[idx] = (rt_isr_handler_t)rt_hw_interrupt_handler; + } + + /* init interrupt nest, and context in thread sp */ + rt_interrupt_nest = 0; + rt_interrupt_from_thread = 0; + rt_interrupt_to_thread = 0; + rt_thread_switch_interrput_flag = 0; +} + +/** + * This function will mask a interrupt. + * @param vector the interrupt number + */ +void rt_hw_interrupt_mask(int vector) +{ + INTC_IMR |= 1 << vector; +} + +/** + * This function will un-mask a interrupt. + * @param vector the interrupt number + */ +void rt_hw_interrupt_umask(int vector) +{ + /* un-mask interrupt */ + if ((vector == INT_NOTUSED0) || (vector == INT_NOTUSED16)) + { + rt_kprintf("Interrupt vec %d is not used!\n", vector); + // while(1); + } + else if (vector == INTGLOBAL) + INTC_IMR = 0x0; + else + INTC_IMR &= ~(1 << vector); + +} + +/** + * This function will install a interrupt service routine to a interrupt. + * @param vector the interrupt number + * @param new_handler the interrupt service routine to be installed + * @param old_handler the old interrupt service routine + */ +void rt_hw_interrupt_install(int vector, rt_isr_handler_t new_handler, rt_isr_handler_t *old_handler) +{ + if(vector >= 0 && vector < MAX_HANDLERS) + { + if (*old_handler != RT_NULL) *old_handler = isr_table[vector]; + if (new_handler != RT_NULL) isr_table[vector] = new_handler; + } +} + +/*@}*/ diff --git a/libcpu/arm/sep4020/serial.c b/libcpu/arm/sep4020/serial.c new file mode 100644 index 0000000000..7f50348335 --- /dev/null +++ b/libcpu/arm/sep4020/serial.c @@ -0,0 +1,281 @@ +/* + * File : serial.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-02-05 Bernard first version + * 2009-10-25 Bernard fix rt_serial_read bug when there is no data + * in the buffer. + * 2010-03-29 Bernard cleanup code. + * 2010-06-14 zchong for sep4020 + */ + +#include "serial.h" + +/** + * @addtogroup SEP4020 + */ +/*@{*/ + +/* RT-Thread Device Interface */ +static rt_err_t rt_serial_init (rt_device_t dev) +{ + struct serial_device* uart = (struct serial_device*) dev->private; + + if (!(dev->flag & RT_DEVICE_FLAG_ACTIVATED)) + { + + if (dev->flag & RT_DEVICE_FLAG_INT_RX) + { + rt_memset(uart->int_rx->rx_buffer, 0, + sizeof(uart->int_rx->rx_buffer)); + uart->int_rx->read_index = uart->int_rx->save_index = 0; + } + + if (dev->flag & RT_DEVICE_FLAG_INT_TX) + { + rt_memset(uart->int_tx->tx_buffer, 0, + sizeof(uart->int_tx->tx_buffer)); + uart->int_tx->write_index = uart->int_tx->save_index = 0; + } + + dev->flag |= RT_DEVICE_FLAG_ACTIVATED; + } + + return RT_EOK; +} + +static rt_err_t rt_serial_open(rt_device_t dev, rt_uint16_t oflag) +{ + return RT_EOK; +} + +static rt_err_t rt_serial_close(rt_device_t dev) +{ + return RT_EOK; +} + +static rt_size_t rt_serial_read (rt_device_t dev, rt_off_t pos, void* buffer, rt_size_t size) +{ + rt_uint8_t* ptr; + rt_err_t err_code; + struct serial_device* uart; + + ptr = buffer; + err_code = RT_EOK; + uart = (struct serial_device*)dev->private; + + if (dev->flag & RT_DEVICE_FLAG_INT_RX) + { + /* interrupt mode Rx */ + while (size) + { + rt_base_t level; + + /* disable interrupt */ + level = rt_hw_interrupt_disable(); + + if (uart->int_rx->read_index != uart->int_rx->save_index) + { + /* read a character */ + *ptr++ = uart->int_rx->rx_buffer[uart->int_rx->read_index]; + size--; + + /* move to next position */ + uart->int_rx->read_index ++; + if (uart->int_rx->read_index >= UART_RX_BUFFER_SIZE) + uart->int_rx->read_index = 0; + } + else + { + /* set error code */ + err_code = -RT_EEMPTY; + + /* enable interrupt */ + rt_hw_interrupt_enable(level); + break; + } + + /* enable interrupt */ + rt_hw_interrupt_enable(level); + } + } + else + { + /* polling mode */ + while ((rt_uint32_t)ptr - (rt_uint32_t)buffer < size) + { + while (uart->uart_device->lsr & USTAT_RCV_READY) + { + *ptr = uart->uart_device->dlbl_rxfifo_txfifo & 0xff; + ptr ++; + } + } + } + + /* set error code */ + rt_set_errno(err_code); + return (rt_uint32_t)ptr - (rt_uint32_t)buffer; +} + + +static rt_size_t rt_serial_write (rt_device_t dev, rt_off_t pos, const void* buffer, rt_size_t size) +{ + rt_uint8_t* ptr; + rt_err_t err_code; + struct serial_device* uart; + + err_code = RT_EOK; + ptr = (rt_uint8_t*)buffer; + uart = (struct serial_device*)dev->private; + + if (dev->flag & RT_DEVICE_FLAG_INT_TX) + { + /* interrupt mode Tx */ + while (uart->int_tx->save_index != uart->int_tx->write_index) + { + /* save on tx buffer */ + uart->int_tx->tx_buffer[uart->int_tx->save_index] = *ptr++; + + -- size; + + /* move to next position */ + uart->int_tx->save_index ++; + + /* wrap save index */ + if (uart->int_tx->save_index >= UART_TX_BUFFER_SIZE) + uart->int_tx->save_index = 0; + } + + /* set error code */ + if (size > 0) + err_code = -RT_EFULL; + } + else + { + /* polling mode */ + while (size) + { + /* + * to be polite with serial console add a line feed + * to the carriage return character + */ + if (*ptr == '\n' && (dev->flag & RT_DEVICE_FLAG_STREAM)) + { + while (!(uart->uart_device->lsr & USTAT_TXB_EMPTY)); + uart->uart_device->dlbl_rxfifo_txfifo = '\r'; + } + + while (!(uart->uart_device->lsr & USTAT_TXB_EMPTY)); + uart->uart_device->dlbl_rxfifo_txfifo = (*ptr & 0x1FF); + + ++ptr; --size; + } + } + + /* set error code */ + rt_set_errno(err_code); + + return (rt_uint32_t)ptr - (rt_uint32_t)buffer; +} + +static rt_err_t rt_serial_control (rt_device_t dev, rt_uint8_t cmd, void *args) +{ +// struct serial_device* uart; + + RT_ASSERT(dev != RT_NULL); + +// uart = (struct serial_device*)dev->private; + switch (cmd) + { + case RT_DEVICE_CTRL_SUSPEND: + /* suspend device */ + dev->flag |= RT_DEVICE_FLAG_SUSPENDED; + break; + + case RT_DEVICE_CTRL_RESUME: + /* resume device */ + dev->flag &= ~RT_DEVICE_FLAG_SUSPENDED; + break; + } + + return RT_EOK; +} + +/* + * serial register for SEP4020 + */ +rt_err_t rt_hw_serial_register(rt_device_t device, const char* name, rt_uint32_t flag, struct serial_device *serial) +{ + RT_ASSERT(device != RT_NULL); + + + device->type = RT_Device_Class_Char; + device->rx_indicate = RT_NULL; + device->tx_complete = RT_NULL; + device->init = rt_serial_init; + device->open = rt_serial_open; + device->close = rt_serial_close; + device->read = rt_serial_read; + device->write = rt_serial_write; + device->control = rt_serial_control; + device->private = serial; + + /* register a character device */ + return rt_device_register(device, name, RT_DEVICE_FLAG_RDWR | flag); +} + +/* ISR for serial interrupt */ +void rt_hw_serial_isr(rt_device_t device) +{ + rt_base_t level; + struct serial_device* uart = (struct serial_device*) device->private; + + /* interrupt mode receive */ + RT_ASSERT(device->flag & RT_DEVICE_FLAG_INT_RX); + + /* save on rx buffer */ + while (uart->uart_device->lsr & USTAT_RCV_READY) + { + /* disable interrupt */ + level = rt_hw_interrupt_disable(); + + uart->int_rx->rx_buffer[uart->int_rx->save_index] = uart->uart_device->dlbl_rxfifo_txfifo & 0xff; + uart->int_rx->save_index ++; + if (uart->int_rx->save_index >= UART_RX_BUFFER_SIZE) + uart->int_rx->save_index = 0; + + /* if the next position is read index, discard this 'read char' */ + if (uart->int_rx->save_index == uart->int_rx->read_index) + { + uart->int_rx->read_index ++; + if (uart->int_rx->read_index >= UART_RX_BUFFER_SIZE) + uart->int_rx->read_index = 0; + } + + /* enable interrupt */ + rt_hw_interrupt_enable(level); + } + + /* invoke callback */ + if (device->rx_indicate != RT_NULL) + { + rt_size_t rx_length; + + /* get rx length */ + rx_length = uart->int_rx->read_index > uart->int_rx->save_index ? + UART_RX_BUFFER_SIZE - uart->int_rx->read_index + uart->int_rx->save_index : + uart->int_rx->save_index - uart->int_rx->read_index; + + device->rx_indicate(device, rx_length); + } +} + + +/*@}*/ diff --git a/libcpu/arm/sep4020/serial.h b/libcpu/arm/sep4020/serial.h new file mode 100644 index 0000000000..391cbe16e9 --- /dev/null +++ b/libcpu/arm/sep4020/serial.h @@ -0,0 +1,56 @@ +#ifndef __RT_SERIAL_H__ +#define __RT_SERIAL_H__ + +#include +#include + + +#define USTAT_RCV_READY 0x01 /* receive data ready */ +#define USTAT_TXB_EMPTY 0x20 /* tx buffer empty */ +#define BPS 115200 /* serial baudrate */ + +#define UART_RX_BUFFER_SIZE 64 +#define UART_TX_BUFFER_SIZE 64 + +struct serial_int_rx +{ + rt_uint8_t rx_buffer[UART_RX_BUFFER_SIZE]; + rt_uint32_t read_index, save_index; +}; + +struct serial_int_tx +{ + rt_uint8_t tx_buffer[UART_TX_BUFFER_SIZE]; + rt_uint32_t write_index, save_index; +}; + +/* serial port registers */ +typedef struct uartport +{ + rt_uint32_t dlbl_rxfifo_txfifo; + rt_uint32_t dlbh_ier; + rt_uint32_t iir_fcr; + rt_uint32_t lcr; + rt_uint32_t mcr; + rt_uint32_t lsr; + rt_uint32_t msr; +}uartport; + +struct serial_device +{ + /* uart hardware registers */ + uartport* uart_device; + + /* rx structure */ + struct serial_int_rx* int_rx; + + /* tx structure */ + struct serial_int_tx* int_tx; +}; + +rt_err_t rt_hw_serial_register(rt_device_t device, const char* name, rt_uint32_t flag, struct serial_device *serial); + +void rt_hw_serial_isr(rt_device_t device); + +#endif + diff --git a/libcpu/arm/sep4020/stack.c b/libcpu/arm/sep4020/stack.c new file mode 100644 index 0000000000..6060b63722 --- /dev/null +++ b/libcpu/arm/sep4020/stack.c @@ -0,0 +1,61 @@ +/* + * 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 + * 2006-08-23 Bernard the first version + */ +#include + +#define SVCMODE 0x13 + +/** + * @addtogroup AT91SAM7 + */ +/*@{*/ + +/** + * 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) = (unsigned long)tentry; /* entry point */ + *(--stk) = (unsigned long)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) = (unsigned long)parameter; /* r0 : argument */ + *(--stk) = SVCMODE; /* cpsr */ + *(--stk) = SVCMODE; /* spsr */ + + /* return task's current stack address */ + return (rt_uint8_t *)stk; +} + +/*@}*/ diff --git a/libcpu/arm/sep4020/start_rvds.S b/libcpu/arm/sep4020/start_rvds.S new file mode 100644 index 0000000000..6de4ee54a8 --- /dev/null +++ b/libcpu/arm/sep4020/start_rvds.S @@ -0,0 +1,374 @@ +;============================================================================================== +; star_rvds.s for Keil MDK 4.10 +; +; SEP4020 start up code +; +; Change Logs: +; Date Author Notes +; 2010-03-17 zchong +;============================================================================================= + +; + +PMU_PLTR EQU 0x10001000 ; PLL的稳定过渡时间 +PMU_PMCR EQU 0x10001004 ; 系统主时钟PLL的控制寄存器 +PMU_PUCR EQU 0x10001008 ; USB时钟PLL的控制寄存器 +PMU_PCSR EQU 0x1000100C ; 内部模块时钟源供给的控制寄存器 +PMU_PDSLOW EQU 0x10001010 ; SLOW状态下时钟的分频因子 +PMU_PMDR EQU 0x10001014 ; 芯片工作模式寄存器 +PMU_RCTR EQU 0x10001018 ; Reset控制寄存器 +PMU_CLRWAKUP EQU 0x1000101C ; WakeUp清除寄存器 + +RTC_CTR EQU 0x1000200C ; RTC控制寄存器 + +INTC_IER EQU 0x10000000 ; IRQ中断允许寄存器 +INTC_IMR EQU 0x10000008 ; IRQ中断屏蔽寄存器 +INTC_IFSR EQU 0x10000030 ; IRQ中断最终状态寄存器 +INTC_FIER EQU 0x100000C0 ; FIQ中断允许寄存器 +INTC_FIMR EQU 0x100000C4 ; FIQ中断屏蔽寄存器 + +EMI_CSACONF EQU 0x11000000 ; CSA参数配置寄存器 +EMI_CSECONF EQU 0x11000010 ; CSE参数配置寄存器 +EMI_CSFCONF EQU 0x11000014 ; CSF参数配置寄存器 +EMI_SDCONF1 EQU 0x11000018 ; SDRAM时序配置寄存器1 +EMI_SDCONF2 EQU 0x1100001C ; SDRAM时序配置寄存器2, SDRAM初始化用到的配置信息 +EMI_REMAPCONF EQU 0x11000020 ; 片选空间及地址映射REMAP配置寄存器 + +Mode_USR EQU 0x10 +Mode_FIQ EQU 0x11 +Mode_IRQ EQU 0x12 +Mode_SVC EQU 0x13 +Mode_ABT EQU 0x17 +Mode_UND EQU 0x1B +Mode_SYS EQU 0x1F + +I_Bit EQU 0x80 ; when I bit is set, IRQ is disabled +F_Bit EQU 0x40 ; when F bit is set, FIQ is disabled +NOINT EQU 0xc0 +MASK_MODE EQU 0x0000003F +MODE_SVC32 EQU 0x00000013 + +; Internal Memory Base Addresses +FLASH_BASE EQU 0x20000000 +RAM_BASE EQU 0x04000000 + +; Stack +UND_Stack_Size EQU 0x00000000 +SVC_Stack_Size EQU 0x00000400 +ABT_Stack_Size EQU 0x00000000 +FIQ_Stack_Size EQU 0x00000000 +IRQ_Stack_Size EQU 0x00000100 +USR_Stack_Size EQU 0x00000000 + +ISR_Stack_Size EQU (UND_Stack_Size + SVC_Stack_Size + ABT_Stack_Size + \ + FIQ_Stack_Size + IRQ_Stack_Size) + + AREA STACK, NOINIT, READWRITE, ALIGN=3 + +Stack_Mem SPACE USR_Stack_Size +__initial_sp SPACE ISR_Stack_Size +Stack_Top + +; Heap +Heap_Size EQU 0x00000000 + + AREA HEAP, NOINIT, READWRITE, ALIGN=3 +__heap_base +Heap_Mem SPACE Heap_Size +__heap_limit + + + PRESERVE8 + +; Area Definition and Entry Point +; Startup Code must be linked first at Address at which it expects to run. + + AREA RESET, CODE, READONLY + ARM + +; Exception Vectors +; Mapped to Address 0. +; Absolute addressing mode must be used. +; Dummy Handlers are implemented as infinite loops which can be modified. + +Vectors LDR PC,Reset_Addr + LDR PC,Undef_Addr + LDR PC,SWI_Addr + LDR PC,PAbt_Addr + LDR PC,DAbt_Addr + NOP ; Reserved Vector + LDR PC,IRQ_Addr + LDR PC,FIQ_Addr + +Reset_Addr DCD Reset_Handler +Undef_Addr DCD Undef_Handler +SWI_Addr DCD SWI_Handler +PAbt_Addr DCD PAbt_Handler +DAbt_Addr DCD DAbt_Handler + DCD 0 ; Reserved Address +IRQ_Addr DCD IRQ_Handler +FIQ_Addr DCD FIQ_Handler + +Undef_Handler B Undef_Handler +SWI_Handler B SWI_Handler +PAbt_Handler B PAbt_Handler +DAbt_Handler B DAbt_Handler +FIQ_Handler B FIQ_Handler + + +; Reset Handler + + EXPORT Reset_Handler +Reset_Handler + +;**************************************************************** +;* 关闭看门狗 +;**************************************************************** + LDR R0,=RTC_CTR + LDR R1,=0x0 + STR R1,[R0] + +;**************************************************************** +;* 关中断 +;**************************************************************** + MRS R0, CPSR + BIC R0, R0, #MASK_MODE + ORR R0, R0, #MODE_SVC32 + ORR R0, R0, #I_Bit + ORR R0, R0, #F_Bit + MSR CPSR_c, r0 + + LDR R0,=INTC_IER + LDR R1,=0x0 + STR R1,[R0] + LDR R0,=INTC_IMR + LDR R1,=0xFFFFFFFF + STR R1,[R0] + + LDR R0,=INTC_FIER + LDR R1,=0x0 + STR R1,[R0] + LDR R0,=INTC_FIMR + LDR R1,=0x0F + STR R1,[R0] + +;**************************************************************** +;* 初始化PMU模块, 配置系统时钟 +;**************************************************************** + LDR R4, =PMU_PCSR ; 打开所有模块时钟 + LDR R5, =0x0001ffff + STR R5, [ R4 ] + + LDR R4, =PMU_PLTR ; 配置PLL稳定过度时间为保守值50us*100M. + LDR R5, =0x00fa00fa + STR R5, [ R4 ] + + LDR R4, =PMU_PMDR ; 由SLOW模式进入NORMAL模式 + LDR R5, =0x00000001 + STR R5, [ R4 ] + + LDR R4, =PMU_PMCR ; 配置系统时钟为72MHz 2*Fin*9=2*4*9=72MHz + LDR R5, =0x00004009 ; MFCN 0->1 trigger PLL to reconfigure event when mode isn''t SLOW + STR R5, [ R4 ] + LDR R4, =PMU_PMCR ; + LDR R5, =0x0000c009 + STR R5, [ R4 ] + +;**************************************************************** +;* 初始化EMI +;**************************************************************** +; LDR R4, =EMI_CSACONF ; CSA片选时序参数配置 +; LDR R5, =0x08a6a6a1 +; STR R5, [ R4 ] + +; LDR R4, =EMI_CSECONF ; CSE片选时序参数配置,最保守配置 +; LDR R5, =0x8cfffff1 +; STR R5, [ R4 ] + +; LDR R4, =EMI_SDCONF1 ; SDRAM参数配置1 +; LDR R5, =0x1E104177 +; STR R5, [ R4 ] + +; LDR R4, =EMI_SDCONF2 ; SDRAM参数配置2 +; LDR R5, =0x80001860 +; STR R5, [ R4 ] + + +; Copy Exception Vectors to Internal RAM + + IF :DEF:RAM_INTVEC + ADR R8, Vectors ; Source + LDR R9, =RAM_BASE ; Destination + LDMIA R8!, {R0-R7} ; Load Vectors + STMIA R9!, {R0-R7} ; Store Vectors + LDMIA R8!, {R0-R7} ; Load Handler Addresses + STMIA R9!, {R0-R7} ; Store Handler Addresses + ENDIF + + +; Remap on-chip RAM to address 0 + + IF :DEF:REMAP + LDR R0, =EMI_REMAPCONF + MOV R1, #0x80000000 + STR R1, [R0, #0] ; Remap + ENDIF + + +; Setup Stack for each mode + + LDR R0, =Stack_Top + +; Enter Undefined Instruction Mode and set its Stack Pointer + MSR CPSR_c, #Mode_UND:OR:I_Bit:OR:F_Bit + MOV SP, R0 + SUB R0, R0, #UND_Stack_Size + +; Enter Abort Mode and set its Stack Pointer + MSR CPSR_c, #Mode_ABT:OR:I_Bit:OR:F_Bit + MOV SP, R0 + SUB R0, R0, #ABT_Stack_Size + +; Enter FIQ Mode and set its Stack Pointer + MSR CPSR_c, #Mode_FIQ:OR:I_Bit:OR:F_Bit + MOV SP, R0 + SUB R0, R0, #FIQ_Stack_Size + +; Enter IRQ Mode and set its Stack Pointer + MSR CPSR_c, #Mode_IRQ:OR:I_Bit:OR:F_Bit + MOV SP, R0 + SUB R0, R0, #IRQ_Stack_Size + +; Enter Supervisor Mode and set its Stack Pointer + MSR CPSR_c, #Mode_SVC:OR:I_Bit:OR:F_Bit + MOV SP, R0 + SUB R0, R0, #SVC_Stack_Size + +; Enter User Mode and set its Stack Pointer + ; MSR CPSR_c, #Mode_USR + IF :DEF:__MICROLIB + + EXPORT __initial_sp + + ELSE + + ; No usr mode stack here. + ;MOV SP, R0 + ;SUB SL, SP, #USR_Stack_Size + + ENDIF + + +; Enter the C code + + IMPORT __main + LDR R0, =__main + BX R0 + + IMPORT rt_interrupt_enter + IMPORT rt_interrupt_leave + IMPORT rt_thread_switch_interrput_flag + IMPORT rt_interrupt_from_thread + IMPORT rt_interrupt_to_thread + IMPORT rt_hw_trap_irq + IMPORT rt_hw_trap_abort + IMPORT rt_interrupt_nest + +Abort_Handler PROC + EXPORT Abort_Handler + STMFD SP!, {R0-R12,LR} + LDR R0, =rt_interrupt_nest + LDR R1, [R0] + CMP R1, #0 +DeadLoop BHI DeadLoop ; Abort happened in irq mode, halt system. + BL rt_interrupt_enter + BL rt_hw_trap_abort + BL rt_interrupt_leave + B SWITCH + ENDP + +IRQ_Handler PROC + EXPORT IRQ_Handler + STMFD SP!, {R0-R12,LR} + BL rt_interrupt_enter + BL rt_hw_trap_irq + BL rt_interrupt_leave + + ; if rt_thread_switch_interrput_flag set, jump to + ; rt_hw_context_switch_interrupt_do and don't return +SWITCH + LDR R0, =rt_thread_switch_interrput_flag + LDR R1, [R0] + CMP R1, #1 + BEQ rt_hw_context_switch_interrupt_do + + LDMFD SP!, {R0-R12,LR} + SUBS PC, LR, #4 + ENDP + +; /* +; * void rt_hw_context_switch_interrupt_do(rt_base_t flag) +; */ +rt_hw_context_switch_interrupt_do PROC + EXPORT rt_hw_context_switch_interrupt_do + MOV r1, #0 ; clear flag + STR r1, [r0] + + LDMFD sp!, {r0-r12,lr}; reload saved registers + STMFD sp!, {r0-r3} ; save r0-r3 + MOV r1, sp + ADD sp, sp, #16 ; restore sp + SUB r2, lr, #4 ; save old task's pc to r2 + + MRS r3, spsr ; get cpsr of interrupt thread + + ; switch to SVC mode and no interrupt + MSR cpsr_c, #I_Bit:OR:F_Bit:OR:Mode_SVC + + STMFD sp!, {r2} ; push old task's pc + STMFD sp!, {r4-r12,lr}; push old task's lr,r12-r4 + MOV r4, r1 ; Special optimised code below + MOV r5, r3 + LDMFD r4!, {r0-r3} + STMFD sp!, {r0-r3} ; push old task's r3-r0 + STMFD sp!, {r5} ; push old task's cpsr + MRS r4, spsr + STMFD sp!, {r4} ; push old task's spsr + + LDR r4, =rt_interrupt_from_thread + LDR r5, [r4] + STR sp, [r5] ; store sp in preempted tasks's TCB + + LDR r6, =rt_interrupt_to_thread + LDR r6, [r6] + LDR sp, [r6] ; get new task's stack pointer + + LDMFD sp!, {r4} ; pop new task's spsr + MSR spsr_cxsf, r4 + LDMFD sp!, {r4} ; pop new task's psr + MSR cpsr_cxsf, r4 + + LDMFD sp!, {r0-r12,lr,pc} ; pop new task's r0-r12,lr & pc + ENDP + + IF :DEF:__MICROLIB + + EXPORT __heap_base + EXPORT __heap_limit + + ELSE +; User Initial Stack & Heap + AREA |.text|, CODE, READONLY + + IMPORT __use_two_region_memory + EXPORT __user_initial_stackheap +__user_initial_stackheap + + LDR R0, = Heap_Mem + LDR R1, = (Stack_Mem + IRQ_Stack_Size) + LDR R2, = (Heap_Mem + Heap_Size) + LDR R3, = Stack_Mem + BX LR + ENDIF + + END diff --git a/libcpu/arm/sep4020/trap.c b/libcpu/arm/sep4020/trap.c new file mode 100644 index 0000000000..cad14e88fc --- /dev/null +++ b/libcpu/arm/sep4020/trap.c @@ -0,0 +1,66 @@ +/* + * File : trap.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 + * 2006-08-25 Bernard first version + * 2010-03-18 zchong for sep4020 + */ + +#include +#include + +#include "sep4020.h" + +/** + * @addtogroup SEP4020 + */ +/*@{*/ + +extern rt_isr_handler_t isr_table[]; + +void rt_hw_trap_irq() +{ + rt_uint32_t intstat,intnum; + rt_uint8_t i = 0; + rt_isr_handler_t isr_func; + + /* get interrupt source */ + intstat = INTC_IFSR; + + intnum = intstat; + if (intstat == INTGLOBAL) return; + + while(intnum != 0x00000001) + { + intnum = intnum>>1; + i++; + } + /* get interrupt service routine */ + isr_func = isr_table[i]; + + /* turn to interrupt service routine */ + isr_func(intstat); + +} + +void rt_hw_trap_fiq() +{ + rt_kprintf("fast interrupt request\n"); +} + +extern struct rt_thread* rt_current_thread; +void rt_hw_trap_abort() +{ + rt_kprintf("Abort occured!!! Thread [%s] suspended.\n",rt_current_thread->name); + rt_thread_suspend(rt_current_thread); + rt_schedule(); + +} +/*@}*/ -- cgit v1.3.1