diff --git a/bsp/ls1bdev/SConscript b/bsp/ls1bdev/SConscript new file mode 100644 index 0000000000..a0c60722c0 --- /dev/null +++ b/bsp/ls1bdev/SConscript @@ -0,0 +1,12 @@ +Import('RTT_ROOT') +from building import * + +src_bsp = ['application.c', 'startup.c', 'board.c'] + +src_drv = ['uart.c'] + +src = File(src_bsp + src_drv) +CPPPATH = [GetCurrentDir()] +group = DefineGroup('Startup', src, depend = [''], CPPPATH = CPPPATH) + +Return('group') diff --git a/bsp/ls1bdev/SConstruct b/bsp/ls1bdev/SConstruct new file mode 100644 index 0000000000..0980f7a2ab --- /dev/null +++ b/bsp/ls1bdev/SConstruct @@ -0,0 +1,28 @@ +import os +import sys +import rtconfig + +RTT_ROOT = os.path.normpath(os.getcwd() + '/../..') +sys.path = sys.path + [os.path.join(RTT_ROOT, 'tools')] +from building import * + +TARGET = 'rtthread.' + rtconfig.TARGET_EXT + +env = Environment(tools = ['mingw'], + AS = rtconfig.AS, ASFLAGS = rtconfig.AFLAGS, + CC = rtconfig.CC, CCFLAGS = rtconfig.CFLAGS, + AR = rtconfig.AR, ARFLAGS = '-rc', + LINK = rtconfig.LINK, LINKFLAGS = rtconfig.LFLAGS) +env.PrependENVPath('PATH', rtconfig.EXEC_PATH) + +Export('RTT_ROOT') +Export('rtconfig') + +# prepare building environment +objs = PrepareBuilding(env, RTT_ROOT) + +# build program +env.Program(TARGET, objs) + +# end building +EndBuilding(TARGET) diff --git a/bsp/ls1bdev/application.c b/bsp/ls1bdev/application.c new file mode 100644 index 0000000000..0a810452b5 --- /dev/null +++ b/bsp/ls1bdev/application.c @@ -0,0 +1,35 @@ +/* + * File : application.c + * This file is part of RT-Thread RTOS + * COPYRIGHT (C) 2006-2011, 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 + * 2010-06-25 Bernard first version + * 2011-08-08 lgnq modified for Loongson LS1B + */ + +#include +#include + +void rt_init_thread_entry(void* parameter) +{ +} + +int rt_application_init() +{ + rt_thread_t tid; + + /* create initialization thread */ + tid = rt_thread_create("init", + rt_init_thread_entry, RT_NULL, + 4096, 8, 20); + if (tid != RT_NULL) + rt_thread_startup(tid); + + return 0; +} diff --git a/bsp/ls1bdev/board.c b/bsp/ls1bdev/board.c new file mode 100644 index 0000000000..dbfe6038e0 --- /dev/null +++ b/bsp/ls1bdev/board.c @@ -0,0 +1,104 @@ +/* + * File : board.c + * This file is part of RT-Thread RTOS + * COPYRIGHT (C) 2006-2011, 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 + * 2010-06-25 Bernard first version + * 2011-08-08 lgnq modified for Loongson LS1B + */ + +#include +#include + +#include "board.h" +#include "uart.h" +#include "ls1b.h" + +/** + * @addtogroup Loongson LS1B + */ +/*@{*/ + +/** + * This is the timer interrupt service routine. + */ +void rt_hw_timer_handler() +{ + unsigned int count; + + count = read_c0_compare(); + write_c0_compare(count); + write_c0_count(0); + + /* increase a OS tick */ + rt_tick_increase(); +} + +/** + * This function will initial OS timer + */ +void rt_hw_timer_init() +{ + write_c0_compare(CPU_HZ/2/RT_TICK_PER_SECOND); + write_c0_count(0); +} + +/** + * This function will initial sam7s64 board. + */ +void rt_hw_board_init() +{ +#ifdef RT_USING_UART + /* init hardware UART device */ + rt_hw_uart_init(); +#endif + +#ifdef RT_USING_CONSOLE + /* set console device */ + rt_console_set_device("uart0"); +#endif + + /* init operating system timer */ + rt_hw_timer_init(); + + rt_kprintf("current sr: 0x%08x\n", read_c0_status()); +} + +/* UART line status register value */ +#define UARTLSR_ERROR (1 << 7) +#define UARTLSR_TE (1 << 6) +#define UARTLSR_TFE (1 << 5) +#define UARTLSR_BI (1 << 4) +#define UARTLSR_FE (1 << 3) +#define UARTLSR_PE (1 << 2) +#define UARTLSR_OE (1 << 1) +#define UARTLSR_DR (1 << 0) +void rt_hw_console_output(const char* ptr) +{ + /* stream mode */ + while (*ptr) + { + if (*ptr == '\n') + { + /* FIFO status, contain valid data */ + while (!(UART_LSR(UART0_BASE) & (UARTLSR_TE | UARTLSR_TFE))); + /* write data */ + UART_DAT(UART0_BASE) = '\r'; + } + + /* FIFO status, contain valid data */ + while (!(UART_LSR(UART0_BASE) & (UARTLSR_TE | UARTLSR_TFE))); + /* write data */ + UART_DAT(UART0_BASE) = *ptr; + + ptr ++; + } +} + +/*@}*/ diff --git a/bsp/ls1bdev/board.h b/bsp/ls1bdev/board.h new file mode 100644 index 0000000000..62481a2a45 --- /dev/null +++ b/bsp/ls1bdev/board.h @@ -0,0 +1,25 @@ +/* + * File : board.h + * This file is part of RT-Thread RTOS + * COPYRIGHT (C) 2006-2011, 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 + * 2010-06-25 Bernard first version + * 2011-08-08 lgnq modified for Loongson LS1B + */ + +#ifndef __BOARD_H__ +#define __BOARD_H__ + +void rt_hw_board_init(void); + +/* 64M SDRAM */ +#define RT_HW_HEAP_END (0x80000000 + 64 * 1024 * 1024) +#define CPU_HZ (125 * 1000000) + +#endif diff --git a/bsp/ls1bdev/ls1b_ram.lds b/bsp/ls1bdev/ls1b_ram.lds new file mode 100644 index 0000000000..e55c645865 --- /dev/null +++ b/bsp/ls1bdev/ls1b_ram.lds @@ -0,0 +1,119 @@ +/* + * File : ls1b_ram.lds + * This file is part of RT-Thread RTOS + * COPYRIGHT (C) 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 + * 2010-05-17 swkyer first version + * 2010-09-04 bernard move the beginning entry to 0x80200000 + */ + +OUTPUT_ARCH(mips) +GROUP(-lgcc -lc) + +ENTRY(_start) +SECTIONS +{ + . = 0x80200000 ; + + .start : + { + *(.start); + } + + . = ALIGN(4); + .text : + { + *(.text) + *(.text.*) + *(.rodata) + *(.rodata.*) + *(.rodata1) + *(.rodata1.*) + + /* section information for finsh shell */ + . = ALIGN(4); + __fsymtab_start = .; + KEEP(*(FSymTab)) + __fsymtab_end = .; + . = ALIGN(4); + __vsymtab_start = .; + KEEP(*(VSymTab)) + __vsymtab_end = .; + . = ALIGN(4); + } + + . = ALIGN(4); + .data : + { + *(.data) + *(.data.*) + + *(.data1) + *(.data1.*) + + . = ALIGN(8); + _gp = ABSOLUTE(.); /* Base of small data */ + + *(.sdata) + *(.sdata.*) + } + + .sbss : + { + __bss_start = .; + *(.sbss) + *(.sbss.*) + *(.dynsbss) + *(.scommon) + } + + .bss : + { + *(.bss) + *(.bss.*) + *(.dynbss) + *(COMMON) + __bss_end = .; + } + _end = .; + + /* Stabs debugging sections. */ + .stab 0 : { *(.stab) } + .stabstr 0 : { *(.stabstr) } + .stab.excl 0 : { *(.stab.excl) } + .stab.exclstr 0 : { *(.stab.exclstr) } + .stab.index 0 : { *(.stab.index) } + .stab.indexstr 0 : { *(.stab.indexstr) } + .comment 0 : { *(.comment) } + /* DWARF debug sections. + * Symbols in the DWARF debugging sections are relative to the beginning + * of the section so we begin them at 0. */ + /* DWARF 1 */ + .debug 0 : { *(.debug) } + .line 0 : { *(.line) } + /* GNU DWARF 1 extensions */ + .debug_srcinfo 0 : { *(.debug_srcinfo) } + .debug_sfnames 0 : { *(.debug_sfnames) } + /* DWARF 1.1 and DWARF 2 */ + .debug_aranges 0 : { *(.debug_aranges) } + .debug_pubnames 0 : { *(.debug_pubnames) } + /* DWARF 2 */ + .debug_info 0 : { *(.debug_info .gnu.linkonce.wi.*) } + .debug_abbrev 0 : { *(.debug_abbrev) } + .debug_line 0 : { *(.debug_line) } + .debug_frame 0 : { *(.debug_frame) } + .debug_str 0 : { *(.debug_str) } + .debug_loc 0 : { *(.debug_loc) } + .debug_macinfo 0 : { *(.debug_macinfo) } + /* SGI/MIPS DWARF 2 extensions */ + .debug_weaknames 0 : { *(.debug_weaknames) } + .debug_funcnames 0 : { *(.debug_funcnames) } + .debug_typenames 0 : { *(.debug_typenames) } + .debug_varnames 0 : { *(.debug_varnames) } +} diff --git a/bsp/ls1bdev/readme.txt b/bsp/ls1bdev/readme.txt new file mode 100644 index 0000000000..7081f59415 --- /dev/null +++ b/bsp/ls1bdev/readme.txt @@ -0,0 +1,4 @@ +this bsp is based on LS1G DEMO BOARD V1.1 + +# download script for RT-Thread +ifaddr syn0 192.168.1.100;load tftp://192.168.1.5/rtthread.elf;g \ No newline at end of file diff --git a/bsp/ls1bdev/rtconfig.h b/bsp/ls1bdev/rtconfig.h new file mode 100644 index 0000000000..2e454662c2 --- /dev/null +++ b/bsp/ls1bdev/rtconfig.h @@ -0,0 +1,164 @@ +/* RT-Thread config file */ +#ifndef __RTTHREAD_CFG_H__ +#define __RTTHREAD_CFG_H__ + +/* RT_NAME_MAX*/ +#define RT_NAME_MAX 10 + +/* RT_ALIGN_SIZE*/ +#define RT_ALIGN_SIZE 4 + +/* PRIORITY_MAX */ +#define RT_THREAD_PRIORITY_MAX 256 + +/* Tick per Second */ +#define RT_TICK_PER_SECOND 100 + +/* SECTION: RT_DEBUG */ +/* Thread Debug */ +#define RT_DEBUG +#define RT_USING_OVERFLOW_CHECK + +/* Using Hook */ +#define RT_USING_HOOK + +/* Using Software Timer */ +/* #define RT_USING_TIMER_SOFT */ +#define RT_TIMER_THREAD_PRIO 4 +#define RT_TIMER_THREAD_STACK_SIZE 512 +#define RT_TIMER_TICK_PER_SECOND 10 + +/* SECTION: IPC */ +/* Using Semaphore */ +#define RT_USING_SEMAPHORE + +/* Using Mutex */ +#define RT_USING_MUTEX + +/* Using Event */ +#define RT_USING_EVENT + +/* Using MailBox */ +#define RT_USING_MAILBOX + +/* Using Message Queue */ +#define RT_USING_MESSAGEQUEUE + +/* SECTION: Memory Management */ +/* Using Memory Pool Management*/ +#define RT_USING_MEMPOOL + +/* Using Dynamic Heap Management */ +#define RT_USING_HEAP + +/* Using SLAB MM */ +#define RT_USING_SLAB +/* #define RT_USING_SMALL_MEM */ + +/* SECTION: Device System */ +/* Using Device System */ +#define RT_USING_DEVICE +#define RT_USING_UART +#define RT_USING_UART0 +#define RT_UART_RX_BUFFER_SIZE 64 + +/* SECTION: Console options */ +/* the buffer size of console */ +#define RT_USING_CONSOLE +#define RT_CONSOLEBUF_SIZE 128 + +/* SECTION: the runtime libc library */ +/* the runtime libc library */ +/* #define RT_USING_NEWLIB */ +/* #define RT_USING_PTHREADS */ + +/* SECTION: finsh, a C-Express shell */ +/* Using FinSH as Shell*/ +#define RT_USING_FINSH +/* Using symbol table */ +#define FINSH_USING_SYMTAB +#define FINSH_USING_DESCRIPTION +#define FINSH_DEVICE_NAME "uart0" + +/* SECTION: device filesystem support */ +/* #define RT_USING_DFS */ +/* #define RT_USING_DFS_ELMFAT */ +#define RT_USING_DFS_ROMFS +/* #define RT_USING_DFS_DEVFS */ + +/* the max number of mounted filesystem */ +#define DFS_FILESYSTEMS_MAX 2 +/* the max number of opened files */ +#define DFS_FD_MAX 4 +/* the max number of cached sector */ +#define DFS_CACHE_MAX_NUM 4 +/* Using working directory */ +#define DFS_USING_WORKDIR + +/* SECTION: lwip, a lighwight TCP/IP protocol stack */ +/* #define RT_USING_LWIP */ +#define RT_LWIP_USING_RT_MEM + +/* Enable ICMP protocol*/ +#define RT_LWIP_ICMP +/* Enable UDP protocol*/ +#define RT_LWIP_UDP +/* Enable TCP protocol*/ +#define RT_LWIP_TCP +/* Enable DNS */ +#define RT_LWIP_DNS + +/* the number of simulatenously active TCP connections*/ +#define RT_LWIP_TCP_PCB_NUM 5 + +/* ip address of target*/ +#define RT_LWIP_IPADDR0 192 +#define RT_LWIP_IPADDR1 168 +#define RT_LWIP_IPADDR2 1 +#define RT_LWIP_IPADDR3 30 + +/* gateway address of target*/ +#define RT_LWIP_GWADDR0 192 +#define RT_LWIP_GWADDR1 168 +#define RT_LWIP_GWADDR2 1 +#define RT_LWIP_GWADDR3 1 + +/* mask address of target*/ +#define RT_LWIP_MSKADDR0 255 +#define RT_LWIP_MSKADDR1 255 +#define RT_LWIP_MSKADDR2 255 +#define RT_LWIP_MSKADDR3 0 + +/* tcp thread options */ +#define RT_LWIP_TCPTHREAD_PRIORITY 12 +#define RT_LWIP_TCPTHREAD_MBOX_SIZE 4 +#define RT_LWIP_TCPTHREAD_STACKSIZE 1024 + +/* ethernet if thread options */ +#define RT_LWIP_ETHTHREAD_PRIORITY 15 +#define RT_LWIP_ETHTHREAD_MBOX_SIZE 4 +#define RT_LWIP_ETHTHREAD_STACKSIZE 512 + +/* SECTION: RT-Thread/GUI */ +/* #define RT_USING_RTGUI */ + +/* name length of RTGUI object */ +#define RTGUI_NAME_MAX 12 +/* support 16 weight font */ +#define RTGUI_USING_FONT16 +/* support 12 weight font */ +#define RTGUI_USING_FONT12 +/* support Chinese font */ +#define RTGUI_USING_FONTHZ +/* use DFS as file interface */ +#define RTGUI_USING_DFS_FILERW +/* use bmp font as Chinese font */ +#define RTGUI_USING_HZ_BMP +/* use small size in RTGUI */ +#define RTGUI_USING_SMALL_SIZE +/* use mouse cursor */ +/* #define RTGUI_USING_MOUSE_CURSOR */ +/* default font size in RTGUI */ +#define RTGUI_DEFAULT_FONT_SIZE 16 + +#endif diff --git a/bsp/ls1bdev/rtconfig.py b/bsp/ls1bdev/rtconfig.py new file mode 100644 index 0000000000..336c94df3b --- /dev/null +++ b/bsp/ls1bdev/rtconfig.py @@ -0,0 +1,38 @@ +# CPU options +ARCH='mips' +CPU ='loongson_1b' + +# toolchains options +CROSS_TOOL = 'gcc' +PLATFORM = 'gcc' +EXEC_PATH = 'E:/Program Files/CodeSourcery/Sourcery G++ Lite/bin' +BUILD = 'debug' + +PREFIX = 'mips-sde-elf-' +CC = PREFIX + 'gcc' +AS = PREFIX + 'gcc' +AR = PREFIX + 'ar' +LINK = PREFIX + 'gcc' +TARGET_EXT = 'elf' +SIZE = PREFIX + 'size' +OBJDUMP = PREFIX + 'objdump' +OBJCPY = PREFIX + 'objcopy' +READELF = PREFIX + 'readelf' + +DEVICE = ' -mips32' +CFLAGS = DEVICE + ' -EL -G0 -mno-abicalls -fno-pic -fno-builtin -fno-exceptions -ffunction-sections -fomit-frame-pointer' +AFLAGS = ' -c' + DEVICE + ' -EL -fno-pic -fno-builtin -mno-abicalls -x assembler-with-cpp -DSYSTEM_STACK=0x80003fe8' +LFLAGS = DEVICE + ' -EL -Wl,--gc-sections,-Map=rtthread.map,-cref,-u,Reset_Handler -T ls1b_ram.lds' + +CPATH = '' +LPATH = '' + +if BUILD == 'debug': + CFLAGS += ' -O0 -gdwarf-2' + AFLAGS += ' -gdwarf-2' +else: + CFLAGS += ' -O2' + +DUMP_ACTION = OBJDUMP + ' -D -S $TARGET > rtt.asm\n' +READELF_ACTION = READELF + ' -a $TARGET > rtt.map\n' +POST_ACTION = OBJCPY + ' -O binary $TARGET rtthread.bin\n' + SIZE + ' $TARGET \n' diff --git a/bsp/ls1bdev/startup.c b/bsp/ls1bdev/startup.c new file mode 100644 index 0000000000..79cce38978 --- /dev/null +++ b/bsp/ls1bdev/startup.c @@ -0,0 +1,94 @@ +/* + * File : startup.c + * This file is part of RT-Thread RTOS + * COPYRIGHT (C) 2006-2011, 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 + * 2010-06-25 Bernard first version + * 2011-08-08 lgnq modified for Loongson LS1B + */ + +#include +#include + +#include "board.h" +#define A_K0BASE 0x80000000 + +/** + * @addtogroup Loongson LS1B + */ + +/*@{*/ +extern unsigned char __bss_end; + +extern int rt_application_init(void); + +extern void tlb_refill_exception(void); +extern void general_exception(void); +extern void irq_exception(void); + +/** + * This function will startup RT-Thread RTOS. + */ +void rtthread_startup(void) +{ + /* disable interrupt first */ + rt_hw_interrupt_disable(); + + /* init cache */ + rt_hw_cache_init(); + /* init hardware interrupt */ + rt_hw_interrupt_init(); + + /* copy vector */ + memcpy((void *)A_K0BASE, tlb_refill_exception, 0x20); + memcpy((void *)(A_K0BASE + 0x180), general_exception, 0x20); + memcpy((void *)(A_K0BASE + 0x200), irq_exception, 0x20); + + /* init board */ + rt_hw_board_init(); + rt_show_version(); + + /* init tick */ + rt_system_tick_init(); + + /* init timer system */ + rt_system_timer_init(); + +#ifdef RT_USING_HEAP + rt_system_heap_init((void*)&__bss_end, (void*)RT_HW_HEAP_END); +#endif + + /* init scheduler system */ + rt_system_scheduler_init(); + +#ifdef RT_USING_DEVICE + /* init all device */ + rt_device_init_all(); +#endif + + /* init application */ + rt_application_init(); + +#ifdef RT_USING_FINSH + /* init finsh */ + finsh_system_init(); + finsh_set_device(FINSH_DEVICE_NAME); +#endif + + /* init idle thread */ + rt_thread_idle_init(); + + /* start scheduler */ + rt_system_scheduler_start(); + + /* never reach here */ + return ; +} + +/*@}*/ diff --git a/bsp/ls1bdev/uart.c b/bsp/ls1bdev/uart.c new file mode 100644 index 0000000000..fa33194bb8 --- /dev/null +++ b/bsp/ls1bdev/uart.c @@ -0,0 +1,299 @@ +/* + * File : board.c + * This file is part of RT-Thread RTOS + * COPYRIGHT (C) 2006-2011, 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 + * 2011-08-08 lgnq first version + */ + +#include +#include + +#include "ls1b.h" + +/** + * @addtogroup Loongson LS1B + */ + +/*@{*/ +#if defined(RT_USING_UART) && defined(RT_USING_DEVICE) + +/* UART interrupt enable register value */ +#define UARTIER_IME (1 << 3) +#define UARTIER_ILE (1 << 2) +#define UARTIER_ITXE (1 << 1) +#define UARTIER_IRXE (1 << 0) + +/* UART line control register value */ +#define UARTLCR_DLAB (1 << 7) +#define UARTLCR_BCB (1 << 6) +#define UARTLCR_SPB (1 << 5) +#define UARTLCR_EPS (1 << 4) +#define UARTLCR_PE (1 << 3) +#define UARTLCR_SB (1 << 2) + +/* UART line status register value */ +#define UARTLSR_ERROR (1 << 7) +#define UARTLSR_TE (1 << 6) +#define UARTLSR_TFE (1 << 5) +#define UARTLSR_BI (1 << 4) +#define UARTLSR_FE (1 << 3) +#define UARTLSR_PE (1 << 2) +#define UARTLSR_OE (1 << 1) +#define UARTLSR_DR (1 << 0) + +struct rt_uart_ls1b +{ + struct rt_device parent; + + rt_uint32_t hw_base; + rt_uint32_t irq; + + /* buffer for reception */ + rt_uint8_t read_index, save_index; + rt_uint8_t rx_buffer[RT_UART_RX_BUFFER_SIZE]; +}uart_device; + +static void rt_uart_irqhandler(int irqno) +{ + rt_ubase_t level; + rt_uint8_t isr; + struct rt_uart_ls1b* uart = &uart_device; + + /* read interrupt status and clear it */ + isr = UART_IIR(uart->hw_base); + isr = (isr >> 1) & 0x3; + + if (isr & 0x02) /* receive data available */ + { + /* Receive Data Available */ + while (UART_LSR(uart->hw_base) & UARTLSR_DR) + { + uart->rx_buffer[uart->save_index] = UART_DAT(uart->hw_base); + + level = rt_hw_interrupt_disable(); + uart->save_index ++; + if (uart->save_index >= RT_UART_RX_BUFFER_SIZE) + uart->save_index = 0; + rt_hw_interrupt_enable(level); + } + + /* invoke callback */ + if(uart->parent.rx_indicate != RT_NULL) + { + rt_size_t length; + if (uart->read_index > uart->save_index) + length = RT_UART_RX_BUFFER_SIZE - uart->read_index + uart->save_index; + else + length = uart->save_index - uart->read_index; + + uart->parent.rx_indicate(&uart->parent, length); + } + } + + return; +} + +static rt_err_t rt_uart_init (rt_device_t dev) +{ + rt_uint32_t baud_div; + struct rt_uart_ls1b *uart = (struct rt_uart_ls1b*)dev; + + RT_ASSERT(uart != RT_NULL); + +#if 0 + /* init UART Hardware */ + UART_IER(uart->hw_base) = 0; /* clear interrupt */ + UART_FCR(uart->hw_base) = 0x60; /* reset UART Rx/Tx */ + + /* enable UART clock */ + /* set databits, stopbits and parity. (8-bit data, 1 stopbit, no parity) */ + UART_LCR(uart->hw_base) = 0x3; + + /* set baudrate */ + baud_div = DEV_CLK / 16 / UART_BAUDRATE; + UART_LCR(uart->hw_base) |= UARTLCR_DLAB; + + UART_MSB(uart->hw_base) = (baud_div >> 8) & 0xff; + UART_LSB(uart->hw_base) = baud_div & 0xff; + + UART_LCR(uart->hw_base) &= ~UARTLCR_DLAB; + + /* Enable UART unit, enable and clear FIFO */ + UART_FCR(uart->hw_base) = UARTFCR_UUE | UARTFCR_FE | UARTFCR_TFLS | UARTFCR_RFLS; +#endif + + return RT_EOK; +} + +static rt_err_t rt_uart_open(rt_device_t dev, rt_uint16_t oflag) +{ + struct rt_uart_ls1b *uart = (struct rt_uart_ls1b*)dev; + + RT_ASSERT(uart != RT_NULL); + if (dev->flag & RT_DEVICE_FLAG_INT_RX) + { + /* Enable the UART Interrupt */ + UART_IER(uart->hw_base) |= UARTIER_IRXE; + + /* install interrupt */ + rt_hw_interrupt_install(uart->irq, rt_uart_irqhandler, RT_NULL); + rt_hw_interrupt_umask(uart->irq); + } + return RT_EOK; +} + +static rt_err_t rt_uart_close(rt_device_t dev) +{ + struct rt_uart_ls1b *uart = (struct rt_uart_ls1b*)dev; + + RT_ASSERT(uart != RT_NULL); + if (dev->flag & RT_DEVICE_FLAG_INT_RX) + { + /* Disable the UART Interrupt */ + UART_IER(uart->hw_base) &= ~(UARTIER_IRXE); + } + + return RT_EOK; +} + +static rt_size_t rt_uart_read(rt_device_t dev, rt_off_t pos, void* buffer, rt_size_t size) +{ + rt_uint8_t* ptr; + struct rt_uart_ls1b *uart = (struct rt_uart_ls1b*)dev; + + RT_ASSERT(uart != RT_NULL); + + /* point to buffer */ + ptr = (rt_uint8_t*) buffer; + if (dev->flag & RT_DEVICE_FLAG_INT_RX) + { + while (size) + { + /* interrupt receive */ + rt_base_t level; + + /* disable interrupt */ + level = rt_hw_interrupt_disable(); + if (uart->read_index != uart->save_index) + { + *ptr = uart->rx_buffer[uart->read_index]; + + uart->read_index ++; + if (uart->read_index >= RT_UART_RX_BUFFER_SIZE) + uart->read_index = 0; + } + else + { + /* no data in rx buffer */ + + /* enable interrupt */ + rt_hw_interrupt_enable(level); + break; + } + + /* enable interrupt */ + rt_hw_interrupt_enable(level); + + ptr ++; + size --; + } + + return (rt_uint32_t)ptr - (rt_uint32_t)buffer; + } + + return 0; +} + +static rt_size_t rt_uart_write(rt_device_t dev, rt_off_t pos, const void* buffer, rt_size_t size) +{ + char *ptr; + struct rt_uart_ls1b *uart = (struct rt_uart_ls1b*)dev; + + RT_ASSERT(uart != RT_NULL); + + ptr = (char*)buffer; + + if (dev->flag & RT_DEVICE_FLAG_STREAM) + { + /* stream mode */ + while (size) + { + if (*ptr == '\n') + { + /* FIFO status, contain valid data */ + while (!(UART_LSR(uart->hw_base) & (UARTLSR_TE | UARTLSR_TFE))); + /* write data */ + UART_DAT(uart->hw_base) = '\r'; + } + + /* FIFO status, contain valid data */ + while (!(UART_LSR(uart->hw_base) & (UARTLSR_TE | UARTLSR_TFE))); + /* write data */ + UART_DAT(uart->hw_base) = *ptr; + + ptr ++; + size --; + } + } + else + { + while ( size != 0 ) + { + /* FIFO status, contain valid data */ + while (!(UART_LSR(uart->hw_base) & (UARTLSR_TE | UARTLSR_TFE))); + + /* write data */ + UART_DAT(uart->hw_base) = *ptr; + + ptr++; + size--; + } + } + + return (rt_size_t) ptr - (rt_size_t) buffer; +} + +void rt_hw_uart_init(void) +{ + struct rt_uart_ls1b* uart; + + /* get uart device */ + uart = &uart_device; + + /* device initialization */ + uart->parent.type = RT_Device_Class_Char; + rt_memset(uart->rx_buffer, 0, sizeof(uart->rx_buffer)); + uart->read_index = uart->save_index = 0; + +#if defined(RT_USING_UART0) + uart->hw_base = UART0_BASE; + uart->irq = LS1B_UART0_IRQ; +#elif defined(RT_USING_UART1) + uart->hw_base = UART1_BASE; + uart->irq = LS1B_UART1_IRQ; +#endif + + /* device interface */ + uart->parent.init = rt_uart_init; + uart->parent.open = rt_uart_open; + uart->parent.close = rt_uart_close; + uart->parent.read = rt_uart_read; + uart->parent.write = rt_uart_write; + uart->parent.control = RT_NULL; + uart->parent.user_data = RT_NULL; + + rt_device_register(&uart->parent, "uart0", + RT_DEVICE_FLAG_RDWR | + RT_DEVICE_FLAG_STREAM | + RT_DEVICE_FLAG_INT_RX); +} +#endif /* end of UART */ + +/*@}*/ diff --git a/bsp/ls1bdev/uart.h b/bsp/ls1bdev/uart.h new file mode 100644 index 0000000000..14844ad835 --- /dev/null +++ b/bsp/ls1bdev/uart.h @@ -0,0 +1,20 @@ +/* + * File : board.c + * This file is part of RT-Thread RTOS + * COPYRIGHT (C) 2006-2011, 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 + * 2011-08-08 lgnq first version + */ + +#ifndef __UART_H__ +#define __UART_H__ + +void rt_hw_uart_init(void); + +#endif diff --git a/libcpu/mips/loongson_1b/cache.c b/libcpu/mips/loongson_1b/cache.c new file mode 100644 index 0000000000..5782156380 --- /dev/null +++ b/libcpu/mips/loongson_1b/cache.c @@ -0,0 +1,229 @@ +/* + * File : cache.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 + * 2010-07-09 Bernard first version + * 2011-08-08 lgnq modified for LS1B + */ +#include "../common/mipsregs.h" + +#define K0BASE 0x80000000 +#define PRID_LS1B 0x4220 + +extern void Clear_TagLo (void); +extern void Invalidate_Icache_Ls1b(unsigned int); +extern void Invalidate_Dcache_ClearTag_Ls1b(unsigned int); +extern void Invalidate_Dcache_Fill_Ls1b(unsigned int); +extern void Writeback_Invalidate_Dcache(unsigned int); + +typedef struct cacheinfo_t +{ + unsigned int icache_size; + unsigned int dcache_size; + unsigned int icacheline_size; + unsigned int dcacheline_size; +} cacheinfo_t ; + +typedef struct cacheop_t +{ + void (*Clear_TagLo) (void); + void (*Invalidate_Icache) (unsigned int); + void (*Invalidate_Dcache_Fill) (unsigned int); + void (*Invalidate_Dcache_ClearTag) (unsigned int); + void (*Init_Cache)(void); +} cacheop_t ; + +static cacheop_t cacheop, *pcacheop; +static cacheinfo_t cacheinfo, *pcacheinfo; + +int identify_cpu (void) +{ + unsigned int cpu_id; + void invalidate_cache (void); + + pcacheop = &cacheop; + pcacheinfo = &cacheinfo; + + rt_kprintf("CPU configure: 0x%08x\n", read_c0_config()); + cpu_id = read_c0_prid(); + switch (cpu_id) + { + case PRID_LS1B: + rt_kprintf("CPU:LS1B\n"); + pcacheop->Clear_TagLo = Clear_TagLo; + pcacheop->Invalidate_Icache = Invalidate_Icache_Ls1b; + pcacheop->Invalidate_Dcache_Fill = Invalidate_Dcache_Fill_Ls1b; + pcacheop->Invalidate_Dcache_ClearTag = Invalidate_Dcache_ClearTag_Ls1b; + break; + default: + rt_kprintf("Unknown CPU type, system halted!\n"); + while (1) + { + ; + } + break; + } + + return 0; +} + +void probe_cache(void) +{ + unsigned int config1 = read_c0_config1(); + unsigned int icache_size, icache_line_size, icache_sets, icache_ways; + unsigned int dcache_size, dcache_line_size, dcache_sets, dcache_ways; + + if ((icache_line_size = ((config1 >> 19) & 7))) + icache_line_size = 2 << icache_line_size; + else + icache_line_size = icache_line_size; + icache_sets = 64 << ((config1 >> 22) & 7); + icache_ways = 1 + ((config1 >> 16) & 7); + icache_size = icache_sets * icache_ways * icache_line_size; + + if ((dcache_line_size = ((config1 >> 10) & 7))) + dcache_line_size = 2 << dcache_line_size; + else + dcache_line_size = dcache_line_size; + dcache_sets = 64 << ((config1 >> 13) & 7); + dcache_ways = 1 + ((config1 >> 7) & 7); + dcache_size = dcache_sets * dcache_ways * dcache_line_size; + + rt_kprintf("DCache %2dkb, linesize %d bytes.\n", dcache_size >> 10, dcache_line_size); + rt_kprintf("ICache %2dkb, linesize %d bytes.\n", icache_size >> 10, icache_line_size); + + pcacheinfo->icache_size = icache_size; + pcacheinfo->dcache_size = dcache_size; + pcacheinfo->icacheline_size = icache_line_size; + pcacheinfo->dcacheline_size = dcache_line_size; + + return ; +} + +void invalidate_writeback_dcache_all(void) +{ + unsigned int start = K0BASE; + unsigned int end = (start + pcacheinfo->dcache_size); + + start = K0BASE; + while(start < end) + { + Writeback_Invalidate_Dcache(start); //hit writeback invalidate + start += pcacheinfo->dcacheline_size; + } +} + +void invalidate_writeback_dcache(unsigned long addr, int size) +{ + unsigned long start, end; + + start = (addr +pcacheinfo->dcacheline_size -1) & (- pcacheinfo->dcacheline_size); + end = (end + size + pcacheinfo->dcacheline_size -1) & ( -pcacheinfo->dcacheline_size); + + while(start dcacheline_size; + } +} + +void invalidate_icache_all(void) +{ + unsigned int start = K0BASE; + unsigned int end = (start + pcacheinfo->icache_size); + + while(start < end) + { + pcacheop->Invalidate_Icache(start); + start += pcacheinfo->icacheline_size; + } +} + +void invalidate_dcache_all() +{ + unsigned int start = K0BASE; + unsigned int end = (start + pcacheinfo->dcache_size); + while(start icacheline_size; + } +} + +//with cache disabled +void init_dcache(void) +{ + unsigned int start = K0BASE; + unsigned int end = (start + pcacheinfo->dcache_size); + + while(start < end) + { + pcacheop->Invalidate_Dcache_ClearTag(start); + start += pcacheinfo->dcacheline_size; + } + +} + +void rt_hw_cache_init(void) +{ + unsigned int start, end; + + /* 1. identify cpu and probe cache */ + identify_cpu(); + probe_cache(); + + start = K0BASE; + end = (start + pcacheinfo->icache_size); + + /* + * 2. clear CP0 taglo/taghi register; + */ + pcacheop->Clear_TagLo(); + + /* + * 3. invalidate instruction cache; + */ + while(start < end) + { + pcacheop->Invalidate_Icache(start); //index invalidate icache + start += pcacheinfo->icacheline_size; + } + + /* + * 4. invalidate data cache; + */ + start = K0BASE; + end = (start + pcacheinfo->dcache_size); + while(start < end) + { + pcacheop->Invalidate_Dcache_ClearTag(start); + start += pcacheinfo->dcacheline_size; + } + + start = K0BASE; + while(start < end) + { + pcacheop->Invalidate_Dcache_Fill(start); //index invalidate dcache + start += pcacheinfo->dcacheline_size; + } + + start = K0BASE; + while(start < end) + { + pcacheop->Invalidate_Dcache_ClearTag(start); + start += pcacheinfo->dcacheline_size; + } + + /* enable cache */ + enable_cpu_cache(); + rt_kprintf("enable cpu cache done\n"); + + return ; +} diff --git a/libcpu/mips/loongson_1b/cache.h b/libcpu/mips/loongson_1b/cache.h new file mode 100644 index 0000000000..b1ce646857 --- /dev/null +++ b/libcpu/mips/loongson_1b/cache.h @@ -0,0 +1,52 @@ +/* + * File : cache.h + * 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 + * 2010-07-09 Bernard first version + * 2011-08-08 lgnq modified for LS1B + */ +#ifndef __CACHE_H__ +#define __CACHE_H__ + +/* + * Cache Operations + */ +#define Index_Invalidate_I 0x00 +#define Index_Writeback_Inv_D 0x01 +#define Index_Invalidate_SI 0x02 +#define Index_Writeback_Inv_SD 0x03 +#define Index_Load_Tag_I 0x04 +#define Index_Load_Tag_D 0x05 +#define Index_Load_Tag_SI 0x06 +#define Index_Load_Tag_SD 0x07 +#define Index_Store_Tag_I 0x08 +#define Index_Store_Tag_D 0x09 +#define Index_Store_Tag_SI 0x0A +#define Index_Store_Tag_SD 0x0B +#define Create_Dirty_Excl_D 0x0d +#define Create_Dirty_Excl_SD 0x0f +#define Hit_Invalidate_I 0x10 +#define Hit_Invalidate_D 0x11 +#define Hit_Invalidate_SI 0x12 +#define Hit_Invalidate_SD 0x13 +#define Fill 0x14 +#define Hit_Writeback_Inv_D 0x15 +/* 0x16 is unused */ +#define Hit_Writeback_Inv_SD 0x17 +#define Hit_Writeback_I 0x18 +#define Hit_Writeback_D 0x19 +/* 0x1a is unused */ +#define Hit_Writeback_SD 0x1b +/* 0x1c is unused */ +/* 0x1e is unused */ +#define Hit_Set_Virtual_SI 0x1e +#define Hit_Set_Virtual_SD 0x1f + +#endif diff --git a/libcpu/mips/loongson_1b/cache_gcc.S b/libcpu/mips/loongson_1b/cache_gcc.S new file mode 100644 index 0000000000..bb6f46de4c --- /dev/null +++ b/libcpu/mips/loongson_1b/cache_gcc.S @@ -0,0 +1,217 @@ +/* + * File : cache_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 + * 2010-05-17 swkyer first version + * 2010-09-11 bernard port to Loongson SoC3210 + * 2011-08-08 lgnq port to Loongson LS1B + */ +#include "../common/mipsregs.h" +#include "../common/mips.inc" +#include "../common/asm.h" +#include "cache.h" + + .ent cache_init + .global cache_init + .set noreorder +cache_init: + move t1,ra +####part 2#### +cache_detect_4way: + mfc0 t4, CP0_CONFIG + andi t5, t4, 0x0e00 + srl t5, t5, 9 #ic + andi t6, t4, 0x01c0 + srl t6, t6, 6 #dc + addiu t8, $0, 1 + addiu t9, $0, 2 + #set dcache way + beq t6, $0, cache_d1way + addiu t7, $0, 1 #1 way + beq t6, t8, cache_d2way + addiu t7, $0, 2 #2 way + beq $0, $0, cache_d4way + addiu t7, $0, 4 #4 way +cache_d1way: + beq $0, $0, 1f + addiu t6, t6, 12 #1 way +cache_d2way: + beq $0, $0, 1f + addiu t6, t6, 11 #2 way +cache_d4way: + addiu t6, t6, 10 #4 way (10), 2 way(11), 1 way(12) +1: #set icache way + beq t5, $0, cache_i1way + addiu t3, $0, 1 #1 way + beq t5, t8, cache_i2way + addiu t3, $0, 2 #2 way + beq $0, $0, cache_i4way + addiu t3, $0, 4 #4 way +cache_i1way: + beq $0, $0, 1f + addiu t5, t5, 12 +cache_i2way: + beq $0, $0, 1f + addiu t5, t5, 11 +cache_i4way: + addiu t5, t5, 10 #4 way (10), 2 way(11), 1 way(12) + +1: addiu t4, $0, 1 + sllv t6, t4, t6 + sllv t5, t4, t5 +#if 0 + la t0, memvar + sw t7, 0x0(t0) #ways + sw t5, 0x4(t0) #icache size + sw t6, 0x8(t0) #dcache size +#endif +####part 3#### + .set mips3 + lui a0, 0x8000 + addu a1, $0, t5 + addu a2, $0, t6 +cache_init_d2way: +#a0=0x80000000, a1=icache_size, a2=dcache_size +#a3, v0 and v1 used as local registers + mtc0 $0, CP0_TAGHI + addu v0, $0, a0 + addu v1, a0, a2 +1: slt a3, v0, v1 + beq a3, $0, 1f + nop + mtc0 $0, CP0_TAGLO + beq t7, 1, 4f + cache Index_Store_Tag_D, 0x0(v0) # 1 way + beq t7, 2 ,4f + cache Index_Store_Tag_D, 0x1(v0) # 2 way + cache Index_Store_Tag_D, 0x2(v0) # 4 way + cache Index_Store_Tag_D, 0x3(v0) +4: beq $0, $0, 1b + addiu v0, v0, 0x20 +1: +cache_flush_i2way: + addu v0, $0, a0 + addu v1, a0, a1 +1: slt a3, v0, v1 + beq a3, $0, 1f + nop + beq t3, 1, 4f + cache Index_Invalidate_I, 0x0(v0) # 1 way + beq t3, 2, 4f + cache Index_Invalidate_I, 0x1(v0) # 2 way + cache Index_Invalidate_I, 0x2(v0) + cache Index_Invalidate_I, 0x3(v0) # 4 way +4: beq $0, $0, 1b + addiu v0, v0, 0x20 +1: +cache_flush_d2way: + addu v0, $0, a0 + addu v1, a0, a2 +1: slt a3, v0, v1 + beq a3, $0, 1f + nop + beq t7, 1, 4f + cache Index_Writeback_Inv_D, 0x0(v0) #1 way + beq t7, 2, 4f + cache Index_Writeback_Inv_D, 0x1(v0) # 2 way + cache Index_Writeback_Inv_D, 0x2(v0) + cache Index_Writeback_Inv_D, 0x3(v0) # 4 way +4: beq $0, $0, 1b + addiu v0, v0, 0x20 +1: +cache_init_finish: + jr t1 + nop + .set reorder + .end cache_init + +########################### +# Enable CPU cache # +########################### + +LEAF(enable_cpu_cache) + .set noreorder + mfc0 t0, CP0_CONFIG + nop + and t0, ~0x03 + or t0, 0x03 + mtc0 t0, CP0_CONFIG + nop + .set reorder + j ra +END (enable_cpu_cache) + +########################### +# disable CPU cache # +########################### + +LEAF(disable_cpu_cache) + .set noreorder + mfc0 t0, CP0_CONFIG + nop + and t0, ~0x03 + or t0, 0x2 + mtc0 t0, CP0_CONFIG + nop + .set reorder + j ra +END (disable_cpu_cache) + +/**********************************/ +/* Invalidate Instruction Cache */ +/**********************************/ +LEAF(Clear_TagLo) + .set noreorder + mtc0 zero, CP0_TAGLO + nop + .set reorder + j ra +END(Clear_TagLo) + + .set mips3 +/**********************************/ +/* Invalidate Instruction Cache */ +/**********************************/ +LEAF(Invalidate_Icache_Ls1b) + .set noreorder + cache Index_Invalidate_I,0(a0) + cache Index_Invalidate_I,1(a0) + cache Index_Invalidate_I,2(a0) + cache Index_Invalidate_I,3(a0) + .set reorder + j ra +END(Invalidate_Icache_Ls1b) + +/**********************************/ +/* Invalidate Data Cache */ +/**********************************/ +LEAF(Invalidate_Dcache_ClearTag_Ls1b) + .set noreorder + cache Index_Store_Tag_D, 0(a0) # BDSLOT: clear tag + cache Index_Store_Tag_D, 1(a0) # BDSLOT: clear tag + .set reorder + j ra +END(Invalidate_Dcache_ClearTag_Ls1b) + +LEAF(Invalidate_Dcache_Fill_Ls1b) + .set noreorder + cache Index_Writeback_Inv_D, 0(a0) # BDSLOT: clear tag + cache Index_Writeback_Inv_D, 1(a0) # BDSLOT: clear tag + .set reorder + j ra +END(Invalidate_Dcache_Fill_Ls1b) + +LEAF(Writeback_Invalidate_Dcache) + .set noreorder + cache Hit_Writeback_Inv_D, (a0) + .set reorder + j ra +END(Writeback_Invalidate_Dcache) + .set mips0 diff --git a/libcpu/mips/loongson_1b/context_gcc.S b/libcpu/mips/loongson_1b/context_gcc.S new file mode 100644 index 0000000000..a3ae34dc46 --- /dev/null +++ b/libcpu/mips/loongson_1b/context_gcc.S @@ -0,0 +1,148 @@ +/* + * 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 + * 2010-05-17 swkyer first version + * 2010-09-11 bernard port to Loongson SoC3210 + * 2011-08-08 lgnq port to Loongson LS1B + */ +#include "../common/mips.inc" +#include "../common/stackframe.h" + + .section ".text", "ax" + .set noreorder + +/* + * rt_base_t rt_hw_interrupt_disable() + */ + .globl rt_hw_interrupt_disable +rt_hw_interrupt_disable: + mfc0 v0, CP0_STATUS + and v1, v0, 0xfffffffe + mtc0 v1, CP0_STATUS + jr ra + nop + +/* + * void rt_hw_interrupt_enable(rt_base_t level) + */ + .globl rt_hw_interrupt_enable +rt_hw_interrupt_enable: + mtc0 a0, CP0_STATUS + jr ra + nop + +/* + * void rt_hw_context_switch(rt_uint32 from, rt_uint32 to) + * a0 --> from + * a1 --> to + */ + .globl rt_hw_context_switch +rt_hw_context_switch: + mtc0 ra, CP0_EPC + SAVE_ALL + + sw sp, 0(a0) /* store sp in preempted tasks TCB */ + lw sp, 0(a1) /* get new task stack pointer */ + + RESTORE_ALL_AND_RET + +/* + * void rt_hw_context_switch_to(rt_uint32 to)/* + * a0 --> to + */ + .globl rt_hw_context_switch_to +rt_hw_context_switch_to: + lw sp, 0(a0) /* get new task stack pointer */ + + RESTORE_ALL_AND_RET + +/* + * void rt_hw_context_switch_interrupt(rt_uint32 from, rt_uint32 to)/* + */ + .globl rt_thread_switch_interrput_flag + .globl rt_interrupt_from_thread + .globl rt_interrupt_to_thread + .globl rt_hw_context_switch_interrupt +rt_hw_context_switch_interrupt: + la t0, rt_thread_switch_interrput_flag + lw t1, 0(t0) + nop + bnez t1, _reswitch + nop + li t1, 0x01 /* set rt_thread_switch_interrput_flag to 1 */ + sw t1, 0(t0) + la t0, rt_interrupt_from_thread /* set rt_interrupt_from_thread */ + sw a0, 0(t0) +_reswitch: + la t0, rt_interrupt_to_thread /* set rt_interrupt_to_thread */ + sw a1, 0(t0) + jr ra + nop + +/* + * void rt_hw_context_switch_interrupt_do(rt_base_t flag) + */ + .globl rt_interrupt_enter + .globl rt_interrupt_leave + .globl mips_irq_handle +mips_irq_handle: + SAVE_ALL + + mfc0 t0, CP0_CAUSE + and t1, t0, 0xff + bnez t1, spurious_interrupt /* check exception */ + nop + + /* let k0 keep the current context sp */ + move k0, sp + /* switch to kernel stack */ + li sp, SYSTEM_STACK + + jal rt_interrupt_enter + nop + jal rt_interrupt_dispatch + nop + jal rt_interrupt_leave + nop + + /* switch sp back to thread's context */ + move sp, k0 + + /* + * if rt_thread_switch_interrput_flag set, jump to + * rt_hw_context_switch_interrupt_do and don't return + */ + la k0, rt_thread_switch_interrput_flag + lw k1, 0(k0) + beqz k1, spurious_interrupt + nop + sw zero, 0(k0) /* clear flag */ + nop + + /* + * switch to the new thread + */ + la k0, rt_interrupt_from_thread + lw k1, 0(k0) + nop + sw sp, 0(k1) /* store sp in preempted tasks's TCB */ + + la k0, rt_interrupt_to_thread + lw k1, 0(k0) + nop + lw sp, 0(k1) /* get new task's stack pointer */ + j spurious_interrupt + nop + +spurious_interrupt: + RESTORE_ALL_AND_RET + + .set reorder diff --git a/libcpu/mips/loongson_1b/cpuport.c b/libcpu/mips/loongson_1b/cpuport.c new file mode 100644 index 0000000000..6182d39901 --- /dev/null +++ b/libcpu/mips/loongson_1b/cpuport.c @@ -0,0 +1,122 @@ +/* + * File : cpuport.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 + * 2010-07-09 Bernard first version + * 2010-09-11 Bernard add CPU reset implementation + */ +#include +#include "ls1b.h" + +/** + * @addtogroup Loogonson LS1B + */ +/*@{*/ + +/** + * this function will reset CPU + * + */ +void rt_hw_cpu_reset() +{ + /* open the watch-dog */ + WDT_EN = 0x01; /* watch dog enable */ + WDT_TIMER = 0x01; /* watch dog will be timeout after 1 tick */ + WDT_SET = 0x01; /* watch dog start */ + + rt_kprintf("reboot system...\n"); + while (1); +} + +/** + * this function will shutdown CPU + * + */ +void rt_hw_cpu_shutdown() +{ + rt_kprintf("shutdown...\n"); + + while (1); +} + +extern rt_uint32_t cp0_get_cause(void); +extern rt_uint32_t cp0_get_status(void); +extern rt_uint32_t cp0_get_hi(void); +extern rt_uint32_t cp0_get_lo(void); + +/** + * 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) +{ + rt_uint32_t *stk; + static rt_uint32_t g_sr = 0; + + if (g_sr == 0) + { + g_sr = cp0_get_status(); + g_sr &= 0xfffffffe; + g_sr |= 0x8401; + } + + /** Start at stack top */ + stk = (rt_uint32_t *)stack_addr; + *(stk) = (rt_uint32_t) tentry; /* pc: Entry Point */ + *(--stk) = (rt_uint32_t) 0xeeee; /* c0_cause */ + *(--stk) = (rt_uint32_t) 0xffff; /* c0_badvaddr */ + *(--stk) = (rt_uint32_t) cp0_get_lo(); /* lo */ + *(--stk) = (rt_uint32_t) cp0_get_hi(); /* hi */ + *(--stk) = (rt_uint32_t) g_sr; /* C0_SR: HW2 = En, IE = En */ + *(--stk) = (rt_uint32_t) texit; /* ra */ + *(--stk) = (rt_uint32_t) 0x0000001e; /* s8 */ + *(--stk) = (rt_uint32_t) stack_addr; /* sp */ + *(--stk) = (rt_uint32_t) 0x0000001c; /* gp */ + *(--stk) = (rt_uint32_t) 0x0000001b; /* k1 */ + *(--stk) = (rt_uint32_t) 0x0000001a; /* k0 */ + *(--stk) = (rt_uint32_t) 0x00000019; /* t9 */ + *(--stk) = (rt_uint32_t) 0x00000018; /* t8 */ + *(--stk) = (rt_uint32_t) 0x00000017; /* s7 */ + *(--stk) = (rt_uint32_t) 0x00000016; /* s6 */ + *(--stk) = (rt_uint32_t) 0x00000015; /* s5 */ + *(--stk) = (rt_uint32_t) 0x00000014; /* s4 */ + *(--stk) = (rt_uint32_t) 0x00000013; /* s3 */ + *(--stk) = (rt_uint32_t) 0x00000012; /* s2 */ + *(--stk) = (rt_uint32_t) 0x00000011; /* s1 */ + *(--stk) = (rt_uint32_t) 0x00000010; /* s0 */ + *(--stk) = (rt_uint32_t) 0x0000000f; /* t7 */ + *(--stk) = (rt_uint32_t) 0x0000000e; /* t6 */ + *(--stk) = (rt_uint32_t) 0x0000000d; /* t5 */ + *(--stk) = (rt_uint32_t) 0x0000000c; /* t4 */ + *(--stk) = (rt_uint32_t) 0x0000000b; /* t3 */ + *(--stk) = (rt_uint32_t) 0x0000000a; /* t2 */ + *(--stk) = (rt_uint32_t) 0x00000009; /* t1 */ + *(--stk) = (rt_uint32_t) 0x00000008; /* t0 */ + *(--stk) = (rt_uint32_t) 0x00000007; /* a3 */ + *(--stk) = (rt_uint32_t) 0x00000006; /* a2 */ + *(--stk) = (rt_uint32_t) 0x00000005; /* a1 */ + *(--stk) = (rt_uint32_t) parameter; /* a0 */ + *(--stk) = (rt_uint32_t) 0x00000003; /* v1 */ + *(--stk) = (rt_uint32_t) 0x00000002; /* v0 */ + *(--stk) = (rt_uint32_t) 0x00000001; /* at */ + *(--stk) = (rt_uint32_t) 0x00000000; /* zero */ + + /* return task's current stack address */ + return (rt_uint8_t *)stk; +} + +/*@}*/ + diff --git a/libcpu/mips/loongson_1b/exception.c b/libcpu/mips/loongson_1b/exception.c new file mode 100644 index 0000000000..fcc768fb85 --- /dev/null +++ b/libcpu/mips/loongson_1b/exception.c @@ -0,0 +1,90 @@ +/* + * File : cpu.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 + * 2010-05-17 swkyer first version + */ +#include +#include +#include "../common/exception.h" +#include "../common/mipsregs.h" + +/** + * @addtogroup Loongson + */ +/*@{*/ + +/** + * exception handle table + */ +#define RT_EXCEPTION_MAX 8 +exception_func_t sys_exception_handlers[RT_EXCEPTION_MAX]; + +/** + * setup the exception handle + */ +exception_func_t rt_set_except_vector(int n, exception_func_t func) +{ + exception_func_t old_handler = sys_exception_handlers[n]; + + if ((n == 0) || (n > RT_EXCEPTION_MAX) || (!func)) + { + return 0; + } + + sys_exception_handlers[n] = func; + + return old_handler; +} + +void tlb_refill_handler(void) +{ + rt_kprintf("tlb-miss happens, epc: 0x%08x\n", read_c0_epc()); + rt_hw_cpu_shutdown(); +} + +void cache_error_handler(void) +{ + rt_kprintf("cache exception happens, epc: 0x%08x\n", read_c0_epc()); + rt_hw_cpu_shutdown(); +} + +static void unhandled_exception_handle(pt_regs_t *regs) +{ + rt_kprintf("exception happens, epc: 0x%08x, cause: 0x%08x\n", regs->cp0_epc, read_c0_cause()); +} + +void install_default_execpt_handle(void) +{ + rt_int32_t i; + + for (i=0; i> 8; + + for (index = RT_EXCEPTION_MAX; index > 0; index --) + { + if (cause & (1 << index)) + { + sys_exception_handlers[index](regs); + cause &= ~(1 << index); + } + } +} + +/*@}*/ diff --git a/libcpu/mips/loongson_1b/interrupt.c b/libcpu/mips/loongson_1b/interrupt.c new file mode 100644 index 0000000000..594eeb33cb --- /dev/null +++ b/libcpu/mips/loongson_1b/interrupt.c @@ -0,0 +1,167 @@ +/* + * File : interrupt.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 + * 2010-10-15 Bernard first version + * 2010-10-15 lgnq modified for LS1B + */ +#include +#include "ls1b.h" + +#define MAX_INTR 32 + +extern rt_uint32_t rt_interrupt_nest; +rt_uint32_t rt_interrupt_from_thread, rt_interrupt_to_thread; +rt_uint32_t rt_thread_switch_interrput_flag; + +static rt_isr_handler_t irq_handle_table[MAX_INTR]; +void rt_interrupt_dispatch(void *ptreg); +void rt_hw_timer_handler(); + +static struct ls1b_intc_regs volatile *ls1b_hw0_icregs + = (struct ls1b_intc_regs volatile *)(LS1B_INTREG_BASE); + +/** + * @addtogroup Loogonson LS1B + */ +/*@{*/ + +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() +{ + rt_int32_t index; + + /* pci active low */ + ls1b_hw0_icregs->int_pol = -1; //must be done here 20110802 lgnq + /* make all interrupts level triggered */ + (ls1b_hw0_icregs+0)->int_edge = 0x0000e000; + /* mask all interrupts */ + (ls1b_hw0_icregs+0)->int_clr = 0xffffffff; + + for (index = 0; index < MAX_INTR; index ++) + { + irq_handle_table[index] = (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) +{ + /* mask interrupt */ + (ls1b_hw0_icregs+(vector>>5))->int_en &= ~(1 << (vector&0x1f)); +} + +/** + * This function will un-mask a interrupt. + * @param vector the interrupt number + */ +void rt_hw_interrupt_umask(int vector) +{ + (ls1b_hw0_icregs+(vector>>5))->int_en |= (1 << (vector&0x1f)); +} + +/** + * 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_INTR) + { + if (old_handler != RT_NULL) + *old_handler = irq_handle_table[vector]; + if (new_handler != RT_NULL) + irq_handle_table[vector] = (rt_isr_handler_t)new_handler; + } +} + +void rt_interrupt_dispatch(void *ptreg) +{ + int i; + rt_isr_handler_t irq_func; + static rt_uint32_t status = 0; + rt_uint32_t c0_status; + rt_uint32_t c0_cause; + volatile rt_uint32_t cause_im; + volatile rt_uint32_t status_im; + rt_uint32_t pending_im; + + /* check os timer */ + c0_status = read_c0_status(); + c0_cause = read_c0_cause(); + + cause_im = c0_cause & ST0_IM; + status_im = c0_status & ST0_IM; + pending_im = cause_im & status_im; + + if (pending_im & CAUSEF_IP7) + { + rt_hw_timer_handler(); + } + + if (pending_im & CAUSEF_IP2) + { + /* the hardware interrupt */ + status = ls1b_hw0_icregs->int_isr; + if (!status) + return; + + for (i = MAX_INTR; i > 0; --i) + { + if ((status & (1<int_clr |= (1 << i); + } + } + } + else if (pending_im & CAUSEF_IP3) + { + rt_kprintf("%s %d\r\n", __FUNCTION__, __LINE__); + } + else if (pending_im & CAUSEF_IP4) + { + rt_kprintf("%s %d\r\n", __FUNCTION__, __LINE__); + } + else if (pending_im & CAUSEF_IP5) + { + rt_kprintf("%s %d\r\n", __FUNCTION__, __LINE__); + } + else if (pending_im & CAUSEF_IP6) + { + rt_kprintf("%s %d\r\n", __FUNCTION__, __LINE__); + } +} + +/*@}*/ diff --git a/libcpu/mips/loongson_1b/ls1b.h b/libcpu/mips/loongson_1b/ls1b.h new file mode 100644 index 0000000000..fcea5a7de0 --- /dev/null +++ b/libcpu/mips/loongson_1b/ls1b.h @@ -0,0 +1,208 @@ +/* + * File : ls1b.h + * This file is part of RT-Thread RTOS + * COPYRIGHT (C) 2006-2011, 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 + * 2011-08-08 lgnq first version + */ +#ifndef __LS1B_H__ +#define __LS1B_H__ + +#include "../common/mipsregs.h" + +#define LS1B_ACPI_IRQ 0 +#define LS1B_HPET_IRQ 1 +#define LS1B_UART0_IRQ 2 +#define LS1B_UART1_IRQ 3 +#define LS1B_UART2_IRQ 4 +#define LS1B_UART3_IRQ 5 +#define LS1B_CAN0_IRQ 6 +#define LS1B_CAN1_IRQ 7 +#define LS1B_SPI0_IRQ 8 +#define LS1B_SPI1_IRQ 9 +#define LS1B_AC97_IRQ 10 +#define LS1B_MS_IRQ 11 +#define LS1B_KB_IRQ 12 +#define LS1B_DMA0_IRQ 13 +#define LS1B_DMA1_IRQ 14 +#define LS1B_NAND_IRQ 15 +#define LS1B_I2C0_IRQ 16 +#define LS1B_I2C1_IRQ 17 +#define LS1B_PWM0_IRQ 18 +#define LS1B_PWM1_IRQ 19 +#define LS1B_PWM2_IRQ 20 +#define LS1B_PWM3_IRQ 21 +#define LS1B_LPC_IRQ 22 +#define LS1B_EHCI_IRQ 32 +#define LS1B_OHCI_IRQ 33 +#define LS1B_GMAC1_IRQ 34 +#define LS1B_GMAC2_IRQ 35 +#define LS1B_SATA_IRQ 36 +#define LS1B_GPU_IRQ 37 +#define LS1B_PCI_INTA_IRQ 38 +#define LS1B_PCI_INTB_IRQ 39 +#define LS1B_PCI_INTC_IRQ 40 +#define LS1B_PCI_INTD_IRQ 41 + +#define LS1B_GPIO_IRQ 64 +#define LS1B_GPIO_FIRST_IRQ 64 +#define LS1B_GPIO_IRQ_COUNT 96 +#define LS1B_GPIO_LAST_IRQ (LS1B_GPIO_FIRST_IRQ + LS1B_GPIO_IRQ_COUNT-1) + +#define INT_PCI_INTA (1<<6) +#define INT_PCI_INTB (1<<7) +#define INT_PCI_INTC (1<<8) +#define INT_PCI_INTD (1<<9) + +#define LS1B_LAST_IRQ 159 +#define MIPS_CPU_TIMER_IRQ 167 +#define LS1B_INTREG_BASE 0xbfd01040 + +#define LS1B_DMA_IRQ_BASE 168 +#define LS1B_DMA_IRQ_COUNT 16 + +struct ls1b_intc_regs +{ + volatile unsigned int int_isr; + volatile unsigned int int_en; + volatile unsigned int int_set; + volatile unsigned int int_clr; /* offset 0x10*/ + volatile unsigned int int_pol; + volatile unsigned int int_edge; /* offset 0 */ +}; + +struct ls1b_cop_global_regs +{ + volatile unsigned int control; + volatile unsigned int rd_inten; + volatile unsigned int wr_inten; + volatile unsigned int rd_intisr; /* offset 0x10*/ + volatile unsigned int wr_intisr; + unsigned int unused[11]; +} ; + +struct ls1b_cop_channel_regs +{ + volatile unsigned int rd_control; + volatile unsigned int rd_src; + volatile unsigned int rd_cnt; + volatile unsigned int rd_status; /* offset 0x10*/ + volatile unsigned int wr_control; + volatile unsigned int wr_src; + volatile unsigned int wr_cnt; + volatile unsigned int wr_status; /* offset 0x10*/ +} ; + +struct ls1b_cop_regs +{ + struct ls1b_cop_global_regs global; + struct ls1b_cop_channel_regs chan[8][2]; +} ; + +#define __REG8(addr) *((volatile unsigned char *)(addr)) +#define __REG16(addr) *((volatile unsigned short *)(addr)) +#define __REG32(addr) *((volatile unsigned int *)(addr)) + +#define GMAC0_BASE 0xBFE10000 +#define GMAC0_DMA_BASE 0xBFE11000 +#define GMAC1_BASE 0xBFE20000 +#define GMAC1_DMA_BASE 0xBFE21000 +#define UART0_BASE 0xBFE40000 +#define UART0_1_BASE 0xBFE41000 +#define UART0_2_BASE 0xBFE42000 +#define UART0_3_BASE 0xBFE43000 +#define UART1_BASE 0xBFE44000 +#define UART1_1_BASE 0xBFE45000 +#define UART1_2_BASE 0xBFE46000 +#define UART1_3_BASE 0xBFE47000 +#define UART2_BASE 0xBFE48000 +#define UART3_BASE 0xBFE4C000 +#define I2C0_BASE 0xBFE58000 +#define PWM0_BASE 0xBFE5C000 +#define PWM1_BASE 0xBFE5C010 +#define PWM2_BASE 0xBFE5C020 +#define PWM3_BASE 0xBFE5C030 +#define WDT_BASE 0xBFE5C060 +#define RTC_BASE 0xBFE64000 +#define I2C1_BASE 0xBFE68000 +#define UART4_BASE 0xBFE6C000 +#define I2C2_BASE 0xBFE70000 +#define AC97_BASE 0xBFE74000 +#define NAND_BASE 0xBFE78000 +#define UART5_BASE 0xBFE7C000 +#define SPI_BASE 0xBFE80000 +#define CAN1_BASE 0xBF004300 +#define CAN0_BASE 0xBF004400 + +#define DC_BASE 0xBC301240 //Display Control + +/* UART registers */ +#define UART_DAT(base) __REG8(base + 0x00) +#define UART_IER(base) __REG8(base + 0x01) +#define UART_IIR(base) __REG8(base + 0x02) +#define UART_FCR(base) __REG8(base + 0x02) +#define UART_LCR(base) __REG8(base + 0x03) +#define UART_MCR(base) __REG8(base + 0x04) +#define UART_LSR(base) __REG8(base + 0x05) +#define UART_MSR(base) __REG8(base + 0x06) + +#define UART_LSB(base) __REG8(base + 0x00) +#define UART_MSB(base) __REG8(base + 0x01) + +/* UART0 registers */ +#define UART0_DAT __REG8(UART0_BASE + 0x00) +#define UART0_IER __REG8(UART0_BASE + 0x01) +#define UART0_IIR __REG8(UART0_BASE + 0x02) +#define UART0_FCR __REG8(UART0_BASE + 0x02) +#define UART0_LCR __REG8(UART0_BASE + 0x03) +#define UART0_MCR __REG8(UART0_BASE + 0x04) +#define UART0_LSR __REG8(UART0_BASE + 0x05) +#define UART0_MSR __REG8(UART0_BASE + 0x06) + +#define UART0_LSB __REG8(UART0_BASE + 0x00) +#define UART0_MSB __REG8(UART0_BASE + 0x01) + +/* UART1 registers */ +#define UART1_DAT __REG8(UART1_BASE + 0x00) +#define UART1_IER __REG8(UART1_BASE + 0x01) +#define UART1_IIR __REG8(UART1_BASE + 0x02) +#define UART1_FCR __REG8(UART1_BASE + 0x02) +#define UART1_LCR __REG8(UART1_BASE + 0x03) +#define UART1_MCR __REG8(UART1_BASE + 0x04) +#define UART1_LSR __REG8(UART1_BASE + 0x05) +#define UART1_MSR __REG8(UART1_BASE + 0x06) + +#define UART1_LSB __REG8(UART1_BASE + 0x00) +#define UART1_MSB __REG8(UART1_BASE + 0x01) + +/* Watch Dog registers */ +#define WDT_EN __REG32(WDT_BASE + 0x00) +#define WDT_SET __REG32(WDT_BASE + 0x04) +#define WDT_TIMER __REG32(WDT_BASE + 0x08) + +/* Frame Buffer registers */ +#define DC_FB_CONFIG __REG32(DC_BASE + 0x000) +#define DC_FB_BUFFER_ADDR0 __REG32(DC_BASE + 0x020) +#define DC_FB_BUFFER_STRIDE __REG32(DC_BASE + 0x040) +#define DC_FB_BUFFER_ORIGIN __REG32(DC_BASE + 0x060) +#define DC_DITHER_CONFIG __REG32(DC_BASE + 0x120) +#define DC_DITHER_TABLE_LOW __REG32(DC_BASE + 0x140) +#define DC_DITHER_TABLE_HIGH __REG32(DC_BASE + 0x160) +#define DC_PANEL_CONFIG __REG32(DC_BASE + 0x180) +#define DC_PANEL_TIMING __REG32(DC_BASE + 0x1A0) +#define DC_HDISPLAY __REG32(DC_BASE + 0x1C0) +#define DC_HSYNC __REG32(DC_BASE + 0x1E0) +#define DC_VDISPLAY __REG32(DC_BASE + 0x240) +#define DC_VSYNC __REG32(DC_BASE + 0x260) +#define DC_FB_BUFFER_ADDR1 __REG32(DC_BASE + 0x340) + +#define PLL_FREQ __REG32(0xbfe78030) +#define PLL_DIV_PARAM __REG32(0xbfe78034) + +#endif diff --git a/libcpu/mips/loongson_1b/mipscfg.c b/libcpu/mips/loongson_1b/mipscfg.c new file mode 100644 index 0000000000..12907f023c --- /dev/null +++ b/libcpu/mips/loongson_1b/mipscfg.c @@ -0,0 +1,82 @@ +/* + * File : mipscfg.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 + * 2010-05-27 swkyer first version + */ +#include +#include "../common/mipsregs.h" +#include "../common/mipscfg.h" + +mips32_core_cfg_t g_mips_core = +{ + 16, /* icache_line_size */ + 256, /* icache_lines_per_way */ + 4, /* icache_ways */ + 16, /* dcache_line_size */ + 256, /* dcache_lines_per_way */ + 4, /* dcache_ways */ + 16, /* max_tlb_entries */ +}; + +static rt_uint16_t m_pow(rt_uint16_t b, rt_uint16_t n) +{ + rt_uint16_t rets = 1; + + while (n--) + rets *= b; + + return rets; +} + +static rt_uint16_t m_log2(rt_uint16_t b) +{ + rt_uint16_t rets = 0; + + while (b != 1) + { + b /= 2; + rets++; + } + + return rets; +} + +/** + * read core attribute + */ +void mips32_cfg_init(void) +{ + rt_uint16_t val; + rt_uint32_t cp0_config1; + + cp0_config1 = read_c0_config(); + if (cp0_config1 & 0x80000000) + { + cp0_config1 = read_c0_config1(); + + val = (cp0_config1 & (7<<22))>>22; + g_mips_core.icache_lines_per_way = 64 * m_pow(2, val); + val = (cp0_config1 & (7<<19))>>19; + g_mips_core.icache_line_size = 2 * m_pow(2, val); + val = (cp0_config1 & (7<<16))>>16; + g_mips_core.icache_ways = val + 1; + + val = (cp0_config1 & (7<<13))>>13; + g_mips_core.dcache_lines_per_way = 64 * m_pow(2, val); + val = (cp0_config1 & (7<<10))>>10; + g_mips_core.dcache_line_size = 2 * m_pow(2, val); + val = (cp0_config1 & (7<<7))>>7; + g_mips_core.dcache_ways = val + 1; + + val = (cp0_config1 & (0x3F<<25))>>25; + g_mips_core.max_tlb_entries = val + 1; + } +} diff --git a/libcpu/mips/loongson_1b/start_gcc.S b/libcpu/mips/loongson_1b/start_gcc.S new file mode 100644 index 0000000000..964e334ead --- /dev/null +++ b/libcpu/mips/loongson_1b/start_gcc.S @@ -0,0 +1,135 @@ +/* + * File : start_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 + * 2010-05-17 swkyer first version + * 2010-09-04 bernard porting to Jz47xx + */ +#include "../common/mips.inc" +#include "../common/stackframe.h" + + .section ".start", "ax" + .set noreorder + + /* the program entry */ + .globl _start +_start: + .set noreorder + la ra, _start + + /* disable interrupt */ + mfc0 t0, CP0_STATUS + and t0, 0xfffffffe # By default it will be disabled. + mtc0 t0, CP0_STATUS # Set CPU to disable interrupt. + nop + + /* disable cache */ + mfc0 t0, CP0_CONFIG + and t0, 0xfffffff8 + or t0, 0x2 # disable,!default value is not it! + mtc0 t0, CP0_CONFIG # Set CPU to disable cache. + nop + + /* setup stack pointer */ + li sp, SYSTEM_STACK + la gp, _gp + + /* clear bss */ + la t0, __bss_start + la t1, __bss_end +_clr_bss_loop: + sw zero, 0(t0) + bne t0, t1, _clr_bss_loop + addiu t0, t0, 4 + + /* jump to RT-Thread RTOS */ + jal rtthread_startup + nop + + /* restart, never die */ + j _start + nop + .set reorder + + .globl cp0_get_cause +cp0_get_cause: + mfc0 v0, CP0_CAUSE + jr ra + nop + + .globl cp0_get_status +cp0_get_status: + mfc0 v0, CP0_STATUS + jr ra + nop + + .globl cp0_get_hi +cp0_get_hi: + mfhi v0 + jr ra + nop + + .globl cp0_get_lo +cp0_get_lo: + mflo v0 + jr ra + nop + + .extern tlb_refill_handler + .extern cache_error_handler + + /* Exception Handler */ + /* 0x0 - TLB refill handler */ + .section .vectors.1, "ax", %progbits + .global tlb_refill_exception + .type tlb_refill_exception,@function +tlb_refill_exception: + j tlb_refill_handler + nop + + /* 0x100 - Cache error handler */ + .section .vectors.2, "ax", %progbits + j cache_error_handler + nop + + /* 0x180 - Exception/Interrupt handler */ + .section .vectors.3, "ax", %progbits + .global general_exception + .type general_exception,@function +general_exception: + j _general_exception_handler + nop + + /* 0x200 - Special Exception Interrupt handler (when IV is set in CP0_CAUSE) */ + .section .vectors.4, "ax", %progbits + .global irq_exception + .type irq_exception,@function +irq_exception: + j _irq_handler + nop + + .section .vectors, "ax", %progbits + .extern mips_irq_handle + + /* general exception handler */ +_general_exception_handler: + .set noreorder + la k0, mips_irq_handle + jr k0 + nop + .set reorder + + /* interrupt handler */ +_irq_handler: + .set noreorder + la k0, mips_irq_handle + jr k0 + nop + .set reorder